mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-06-30 16:28:30 +00:00
Add The LISP Challenge
This change introduces a 2.5kb program that's comes pretty close so far to bootstrapping John McCarthy's metacircular evaluator on bare metal.
This commit is contained in:
parent
fd22e55b42
commit
b6793d42d5
34 changed files with 1056 additions and 358 deletions
|
@ -23,6 +23,10 @@
|
|||
#include "tool/build/lib/modrm.h"
|
||||
#include "tool/build/lib/throw.h"
|
||||
|
||||
uint64_t AddressOb(struct Machine *m, uint32_t rde) {
|
||||
return AddSegment(m, rde, m->xedd->op.disp, m->ds);
|
||||
}
|
||||
|
||||
uint8_t *GetSegment(struct Machine *m, uint32_t rde, int s) {
|
||||
switch (s & 7) {
|
||||
case 0:
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
uint64_t AddressOb(struct Machine *, uint32_t);
|
||||
uint64_t AddressDi(struct Machine *, uint32_t);
|
||||
uint64_t AddressSi(struct Machine *, uint32_t);
|
||||
uint64_t DataSegment(struct Machine *, uint32_t, uint64_t);
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#include "tool/build/lib/flags.h"
|
||||
#include "tool/build/lib/throw.h"
|
||||
|
||||
void OpDas(struct Machine *m, uint32_t rde) {
|
||||
relegated void OpDas(struct Machine *m, uint32_t rde) {
|
||||
uint8_t al, af, cf;
|
||||
af = cf = 0;
|
||||
al = m->ax[0];
|
||||
|
@ -39,7 +39,7 @@ void OpDas(struct Machine *m, uint32_t rde) {
|
|||
AluFlags8(m->ax[0], af, &m->flags, 0, cf);
|
||||
}
|
||||
|
||||
void OpAaa(struct Machine *m, uint32_t rde) {
|
||||
relegated void OpAaa(struct Machine *m, uint32_t rde) {
|
||||
uint8_t af, cf;
|
||||
af = cf = 0;
|
||||
if ((m->ax[0] & 0x0f) > 9 || GetFlag(m->flags, FLAGS_AF)) {
|
||||
|
@ -51,7 +51,7 @@ void OpAaa(struct Machine *m, uint32_t rde) {
|
|||
AluFlags8(m->ax[0], af, &m->flags, 0, cf);
|
||||
}
|
||||
|
||||
void OpAas(struct Machine *m, uint32_t rde) {
|
||||
relegated void OpAas(struct Machine *m, uint32_t rde) {
|
||||
uint8_t af, cf;
|
||||
af = cf = 0;
|
||||
if ((m->ax[0] & 0x0f) > 9 || GetFlag(m->flags, FLAGS_AF)) {
|
||||
|
@ -63,7 +63,7 @@ void OpAas(struct Machine *m, uint32_t rde) {
|
|||
AluFlags8(m->ax[0], af, &m->flags, 0, cf);
|
||||
}
|
||||
|
||||
void OpAam(struct Machine *m, uint32_t rde) {
|
||||
relegated void OpAam(struct Machine *m, uint32_t rde) {
|
||||
uint8_t i = m->xedd->op.uimm0;
|
||||
if (!i) ThrowDivideError(m);
|
||||
m->ax[1] = m->ax[0] / i;
|
||||
|
@ -71,7 +71,7 @@ void OpAam(struct Machine *m, uint32_t rde) {
|
|||
AluFlags8(m->ax[0], 0, &m->flags, 0, 0);
|
||||
}
|
||||
|
||||
void OpAad(struct Machine *m, uint32_t rde) {
|
||||
relegated void OpAad(struct Machine *m, uint32_t rde) {
|
||||
uint8_t i = m->xedd->op.uimm0;
|
||||
Write16(m->ax, (m->ax[1] * i + m->ax[0]) & 0xff);
|
||||
AluFlags8(m->ax[0], 0, &m->flags, 0, 0);
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include "tool/build/lib/case.h"
|
||||
#include "tool/build/lib/demangle.h"
|
||||
#include "tool/build/lib/dis.h"
|
||||
#include "tool/build/lib/endian.h"
|
||||
#include "tool/build/lib/high.h"
|
||||
#include "tool/build/lib/memory.h"
|
||||
#include "tool/build/lib/modrm.h"
|
||||
|
@ -173,19 +174,21 @@ long DisFind(struct Dis *d, int64_t addr) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
static long DisOne(struct Dis *d, struct Machine *m, int64_t addr) {
|
||||
static long DisAppendOpLines(struct Dis *d, struct Machine *m, int64_t addr) {
|
||||
void *r;
|
||||
int64_t ip;
|
||||
unsigned k;
|
||||
uint8_t b[15];
|
||||
struct DisOp op;
|
||||
long i, n, symbol;
|
||||
n = 15;
|
||||
if ((symbol = DisFindSym(d, addr)) != -1) {
|
||||
if (d->syms.p[symbol].addr <= addr &&
|
||||
addr < d->syms.p[symbol].addr + d->syms.p[symbol].size) {
|
||||
n = d->syms.p[symbol].size - (addr - d->syms.p[symbol].addr);
|
||||
ip = addr - Read64(m->cs);
|
||||
if ((symbol = DisFindSym(d, ip)) != -1) {
|
||||
if (d->syms.p[symbol].addr <= ip &&
|
||||
ip < d->syms.p[symbol].addr + d->syms.p[symbol].size) {
|
||||
n = d->syms.p[symbol].size - (ip - d->syms.p[symbol].addr);
|
||||
}
|
||||
if (addr == d->syms.p[symbol].addr && d->syms.p[symbol].name) {
|
||||
if (ip == d->syms.p[symbol].addr && d->syms.p[symbol].name) {
|
||||
op.addr = addr;
|
||||
op.size = 0;
|
||||
op.active = true;
|
||||
|
@ -219,18 +222,19 @@ static long DisOne(struct Dis *d, struct Machine *m, int64_t addr) {
|
|||
return n;
|
||||
}
|
||||
|
||||
long Dis(struct Dis *d, struct Machine *m, int64_t addr, int lines) {
|
||||
long Dis(struct Dis *d, struct Machine *m, uint64_t addr, uint64_t ip,
|
||||
int lines) {
|
||||
int64_t i, j, symbol;
|
||||
DisFreeOps(&d->ops);
|
||||
if ((symbol = DisFindSym(d, addr)) != -1 &&
|
||||
(d->syms.p[symbol].addr < addr &&
|
||||
addr < d->syms.p[symbol].addr + d->syms.p[symbol].size)) {
|
||||
for (i = d->syms.p[symbol].addr; i < addr; i += j) {
|
||||
if ((j = DisOne(d, m, i)) == -1) return -1;
|
||||
if ((j = DisAppendOpLines(d, m, i)) == -1) return -1;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < lines; ++i, addr += j) {
|
||||
if ((j = DisOne(d, m, addr)) == -1) return -1;
|
||||
if ((j = DisAppendOpLines(d, m, addr)) == -1) return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -247,6 +251,7 @@ const char *DisGetLine(struct Dis *d, struct Machine *m, size_t i) {
|
|||
d->xedd, AccessRam(m, d->ops.p[i].addr, d->ops.p[i].size, r, b, true),
|
||||
d->ops.p[i].size);
|
||||
d->addr = d->ops.p[i].addr;
|
||||
d->m = m;
|
||||
p = DisLineCode(d, d->buf);
|
||||
CHECK_LT(p - d->buf, sizeof(d->buf));
|
||||
return d->buf;
|
||||
|
|
|
@ -45,11 +45,12 @@ struct Dis {
|
|||
} * p;
|
||||
} edges;
|
||||
struct XedDecodedInst xedd[1];
|
||||
uint64_t addr;
|
||||
struct Machine *m; /* for the segment registers */
|
||||
uint64_t addr; /* current effective address */
|
||||
char buf[512];
|
||||
};
|
||||
|
||||
long Dis(struct Dis *, struct Machine *, int64_t, int);
|
||||
long Dis(struct Dis *, struct Machine *, uint64_t, uint64_t, int);
|
||||
long DisFind(struct Dis *, int64_t);
|
||||
void DisFree(struct Dis *);
|
||||
void DisFreeOp(struct DisOp *);
|
||||
|
|
|
@ -59,6 +59,43 @@ static int64_t RipRelative(struct Dis *d, int64_t i) {
|
|||
return d->addr + d->xedd->length + i;
|
||||
}
|
||||
|
||||
static int64_t ZeroExtend(uint32_t rde, int64_t i) {
|
||||
switch (Mode(rde)) {
|
||||
case XED_MODE_REAL:
|
||||
return i & 0xffff;
|
||||
case XED_MODE_LEGACY:
|
||||
return i & 0xffffffff;
|
||||
default:
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
static int64_t Unrelative(uint32_t rde, int64_t i) {
|
||||
switch (Eamode(rde)) {
|
||||
case XED_MODE_REAL:
|
||||
return i & 0xffff;
|
||||
case XED_MODE_LEGACY:
|
||||
return i & 0xffffffff;
|
||||
default:
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
static int64_t GetSeg(struct Dis *d, uint32_t rde, unsigned char *s) {
|
||||
switch (Sego(rde) ? Sego(rde) : d->xedd->op.hint) {
|
||||
default:
|
||||
return Read64(s);
|
||||
case 1:
|
||||
return Read64(d->m->es);
|
||||
case 2:
|
||||
return Read64(d->m->cs);
|
||||
case 3:
|
||||
return Read64(d->m->ss);
|
||||
case 4:
|
||||
return Read64(d->m->ds);
|
||||
}
|
||||
}
|
||||
|
||||
static const char *GetAddrReg(struct Dis *d, uint32_t rde, uint8_t x,
|
||||
uint8_t r) {
|
||||
return kGreg[Eamode(rde) == XED_MODE_REAL][Eamode(rde) == XED_MODE_LONG]
|
||||
|
@ -106,12 +143,12 @@ static char *DisInt(char *p, int64_t x) {
|
|||
return p;
|
||||
}
|
||||
|
||||
static char *DisSym(struct Dis *d, char *p, int64_t addr) {
|
||||
static char *DisSym(struct Dis *d, char *p, int64_t addr, int64_t ip) {
|
||||
long sym;
|
||||
int64_t addend;
|
||||
const char *name;
|
||||
if ((sym = DisFindSym(d, addr)) != -1 && d->syms.p[sym].name) {
|
||||
addend = addr - d->syms.p[sym].addr;
|
||||
if ((sym = DisFindSym(d, ip)) != -1 && d->syms.p[sym].name) {
|
||||
addend = ip - d->syms.p[sym].addr;
|
||||
name = d->syms.stab + d->syms.p[sym].name;
|
||||
p = Demangle(p, name);
|
||||
if (addend) {
|
||||
|
@ -124,10 +161,11 @@ static char *DisSym(struct Dis *d, char *p, int64_t addr) {
|
|||
}
|
||||
}
|
||||
|
||||
static char *DisSymLiteral(struct Dis *d, char *p, uint64_t x) {
|
||||
static char *DisSymLiteral(struct Dis *d, uint32_t rde, char *p, uint64_t addr,
|
||||
uint64_t ip) {
|
||||
*p++ = '$';
|
||||
p = HighStart(p, g_high.literal);
|
||||
p = DisSym(d, p, x);
|
||||
p = DisSym(d, p, addr, ip);
|
||||
p = HighEnd(p);
|
||||
return p;
|
||||
}
|
||||
|
@ -154,18 +192,30 @@ static char *DisSego(struct Dis *d, uint32_t rde, char *p) {
|
|||
return p;
|
||||
}
|
||||
|
||||
static bool IsRealModrmAbsolute(uint32_t rde) {
|
||||
return Eamode(rde) == XED_MODE_REAL && ModrmRm(rde) == 6 && !ModrmMod(rde);
|
||||
}
|
||||
|
||||
static char *DisM(struct Dis *d, uint32_t rde, char *p) {
|
||||
int64_t disp;
|
||||
const char *base, *index, *scale;
|
||||
p = DisSego(d, rde, p);
|
||||
base = index = scale = NULL;
|
||||
if (ModrmMod(rde) == 0b01 || ModrmMod(rde) == 0b10 || IsRipRelative(rde) ||
|
||||
(Eamode(rde) == XED_MODE_REAL && ModrmRm(rde) == 6 && !ModrmMod(rde)) ||
|
||||
IsRealModrmAbsolute(rde) ||
|
||||
(ModrmMod(rde) == 0b00 && ModrmRm(rde) == 0b100 &&
|
||||
SibBase(d->xedd) == 0b101)) {
|
||||
disp = d->xedd->op.disp;
|
||||
if (IsRipRelative(rde)) disp = RipRelative(d, disp);
|
||||
p = DisSym(d, p, disp);
|
||||
if (IsRipRelative(rde)) {
|
||||
if (Mode(rde) == XED_MODE_LONG) {
|
||||
disp = RipRelative(d, disp);
|
||||
} else {
|
||||
disp = Unrelative(rde, disp);
|
||||
}
|
||||
} else if (IsRealModrmAbsolute(rde)) {
|
||||
disp = Unrelative(rde, disp);
|
||||
}
|
||||
p = DisSym(d, p, disp, disp);
|
||||
}
|
||||
if (Eamode(rde) != XED_MODE_REAL) {
|
||||
if (!SibExists(rde)) {
|
||||
|
@ -355,11 +405,12 @@ static char *DisHd(struct Dis *d, uint32_t rde, char *p) {
|
|||
}
|
||||
|
||||
static char *DisImm(struct Dis *d, uint32_t rde, char *p) {
|
||||
return DisSymLiteral(d, p, d->xedd->op.uimm0);
|
||||
return DisSymLiteral(d, rde, p, d->xedd->op.uimm0,
|
||||
ZeroExtend(rde, d->xedd->op.uimm0));
|
||||
}
|
||||
|
||||
static char *DisRvds(struct Dis *d, uint32_t rde, char *p) {
|
||||
return DisSymLiteral(d, p, d->xedd->op.disp);
|
||||
return DisSymLiteral(d, rde, p, d->xedd->op.disp, d->xedd->op.disp);
|
||||
}
|
||||
|
||||
static char *DisKpvds(struct Dis *d, uint32_t rde, char *p, uint64_t x) {
|
||||
|
@ -400,11 +451,12 @@ static char *DisJb(struct Dis *d, uint32_t rde, char *p) {
|
|||
}
|
||||
|
||||
static char *DisJvds(struct Dis *d, uint32_t rde, char *p) {
|
||||
return DisSym(d, p, RipRelative(d, d->xedd->op.disp));
|
||||
return DisSym(d, p, RipRelative(d, d->xedd->op.disp),
|
||||
RipRelative(d, d->xedd->op.disp) - Read64(d->m->cs));
|
||||
}
|
||||
|
||||
static char *DisAbs(struct Dis *d, uint32_t rde, char *p) {
|
||||
return DisSym(d, p, d->xedd->op.disp);
|
||||
return DisSym(d, p, d->xedd->op.disp, d->xedd->op.disp);
|
||||
}
|
||||
|
||||
static char *DisSw(struct Dis *d, uint32_t rde, char *p) {
|
||||
|
|
|
@ -188,7 +188,7 @@ static void OpSahf(struct Machine *m, uint32_t rde) {
|
|||
}
|
||||
|
||||
static void OpLeaGvqpM(struct Machine *m, uint32_t rde) {
|
||||
WriteRegister(rde, RegRexrReg(m, rde), ComputeAddress(m, rde));
|
||||
WriteRegister(rde, RegRexrReg(m, rde), LoadEffectiveAddress(m, rde).addr);
|
||||
}
|
||||
|
||||
static relegated void OpPushSeg(struct Machine *m, uint32_t rde) {
|
||||
|
@ -216,6 +216,14 @@ static relegated void OpJmpf(struct Machine *m, uint32_t rde) {
|
|||
m->ip = m->xedd->op.disp;
|
||||
}
|
||||
|
||||
static relegated void OpXlatAlBbb(struct Machine *m, uint32_t rde) {
|
||||
uint64_t v;
|
||||
v = MaskAddress(Eamode(rde), Read64(m->bx) + Read8(m->ax));
|
||||
v = DataSegment(m, rde, v);
|
||||
SetReadAddr(m, v, 1);
|
||||
Write8(m->ax, Read8(ResolveAddress(m, v)));
|
||||
}
|
||||
|
||||
static void WriteEaxAx(struct Machine *m, uint32_t rde, uint32_t x) {
|
||||
if (!Osz(rde)) {
|
||||
Write64(m->ax, x);
|
||||
|
@ -264,14 +272,6 @@ static void OpOutDxAx(struct Machine *m, uint32_t rde) {
|
|||
OpOut(m, Read16(m->dx), ReadEaxAx(m, rde));
|
||||
}
|
||||
|
||||
static void OpXlatAlBbb(struct Machine *m, uint32_t rde) {
|
||||
uint64_t v;
|
||||
v = MaskAddress(Eamode(rde), Read64(m->bx) + Read8(m->ax));
|
||||
v = DataSegment(m, rde, v);
|
||||
SetReadAddr(m, v, 1);
|
||||
Write8(m->ax, Read8(ResolveAddress(m, v)));
|
||||
}
|
||||
|
||||
static void AluEb(struct Machine *m, uint32_t rde, aluop_f op) {
|
||||
uint8_t *p;
|
||||
p = GetModrmRegisterBytePointerWrite(m, rde);
|
||||
|
@ -515,13 +515,17 @@ static void OpMovEbIb(struct Machine *m, uint32_t rde) {
|
|||
}
|
||||
|
||||
static void OpMovAlOb(struct Machine *m, uint32_t rde) {
|
||||
SetReadAddr(m, m->xedd->op.disp, 1);
|
||||
Write8(ResolveAddress(m, m->xedd->op.disp), Read8(m->ax));
|
||||
int64_t addr;
|
||||
addr = AddressOb(m, rde);
|
||||
SetWriteAddr(m, addr, 1);
|
||||
Write8(m->ax, Read8(ResolveAddress(m, addr)));
|
||||
}
|
||||
|
||||
static void OpMovObAl(struct Machine *m, uint32_t rde) {
|
||||
SetWriteAddr(m, m->xedd->op.disp, 1);
|
||||
Write8(m->ax, Read8(ResolveAddress(m, m->xedd->op.disp)));
|
||||
int64_t addr;
|
||||
addr = AddressOb(m, rde);
|
||||
SetReadAddr(m, addr, 1);
|
||||
Write8(ResolveAddress(m, addr), Read8(m->ax));
|
||||
}
|
||||
|
||||
static void OpMovRaxOvqp(struct Machine *m, uint32_t rde) {
|
||||
|
@ -1199,35 +1203,6 @@ static void OpJcxz(struct Machine *m, uint32_t rde) {
|
|||
}
|
||||
}
|
||||
|
||||
static void Loop(struct Machine *m, uint32_t rde, bool cond) {
|
||||
uint64_t cx;
|
||||
cx = Read64(m->cx) - 1;
|
||||
if (Eamode(rde) != XED_MODE_REAL) {
|
||||
if (Eamode(rde) == XED_MODE_LEGACY) {
|
||||
cx &= 0xffffffff;
|
||||
}
|
||||
Write64(m->cx, cx);
|
||||
} else {
|
||||
cx &= 0xffff;
|
||||
Write16(m->cx, cx);
|
||||
}
|
||||
if (cx && cond) {
|
||||
OpJmp(m, rde);
|
||||
}
|
||||
}
|
||||
|
||||
static void OpLoope(struct Machine *m, uint32_t rde) {
|
||||
Loop(m, rde, GetFlag(m->flags, FLAGS_ZF));
|
||||
}
|
||||
|
||||
static void OpLoopne(struct Machine *m, uint32_t rde) {
|
||||
Loop(m, rde, !GetFlag(m->flags, FLAGS_ZF));
|
||||
}
|
||||
|
||||
static void OpLoop1(struct Machine *m, uint32_t rde) {
|
||||
Loop(m, rde, true);
|
||||
}
|
||||
|
||||
static void Bitscan(struct Machine *m, uint32_t rde, bitscan_f op) {
|
||||
WriteRegister(
|
||||
rde, RegRexrReg(m, rde),
|
||||
|
@ -1259,6 +1234,35 @@ static void OpNegEb(struct Machine *m, uint32_t rde) {
|
|||
AluEb(m, rde, Neg8);
|
||||
}
|
||||
|
||||
static relegated void Loop(struct Machine *m, uint32_t rde, bool cond) {
|
||||
uint64_t cx;
|
||||
cx = Read64(m->cx) - 1;
|
||||
if (Eamode(rde) != XED_MODE_REAL) {
|
||||
if (Eamode(rde) == XED_MODE_LEGACY) {
|
||||
cx &= 0xffffffff;
|
||||
}
|
||||
Write64(m->cx, cx);
|
||||
} else {
|
||||
cx &= 0xffff;
|
||||
Write16(m->cx, cx);
|
||||
}
|
||||
if (cx && cond) {
|
||||
OpJmp(m, rde);
|
||||
}
|
||||
}
|
||||
|
||||
static relegated void OpLoope(struct Machine *m, uint32_t rde) {
|
||||
Loop(m, rde, GetFlag(m->flags, FLAGS_ZF));
|
||||
}
|
||||
|
||||
static relegated void OpLoopne(struct Machine *m, uint32_t rde) {
|
||||
Loop(m, rde, !GetFlag(m->flags, FLAGS_ZF));
|
||||
}
|
||||
|
||||
static relegated void OpLoop1(struct Machine *m, uint32_t rde) {
|
||||
Loop(m, rde, true);
|
||||
}
|
||||
|
||||
static const nexgen32e_f kOp0f6[] = {
|
||||
OpAlubiTest,
|
||||
OpAlubiTest,
|
||||
|
|
|
@ -26,51 +26,7 @@
|
|||
#include "tool/build/lib/modrm.h"
|
||||
#include "tool/build/lib/throw.h"
|
||||
|
||||
static relegated noinline int64_t ComputeAddressReal(const struct Machine *m,
|
||||
uint32_t rde, uint8_t *s,
|
||||
uint64_t i) {
|
||||
switch (ModrmRm(rde)) {
|
||||
case 0:
|
||||
i += Read16(m->bx);
|
||||
i += Read16(m->si);
|
||||
break;
|
||||
case 1:
|
||||
i += Read16(m->bx);
|
||||
i += Read16(m->di);
|
||||
break;
|
||||
case 2:
|
||||
s = m->ss;
|
||||
i += Read16(m->bp);
|
||||
i += Read16(m->si);
|
||||
break;
|
||||
case 3:
|
||||
s = m->ss;
|
||||
i += Read16(m->bp);
|
||||
i += Read16(m->di);
|
||||
break;
|
||||
case 4:
|
||||
i += Read16(m->si);
|
||||
break;
|
||||
case 5:
|
||||
i += Read16(m->di);
|
||||
break;
|
||||
case 6:
|
||||
if (ModrmMod(rde)) {
|
||||
s = m->ss;
|
||||
i += Read16(m->bp);
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
i += Read16(m->bx);
|
||||
break;
|
||||
default:
|
||||
unreachable;
|
||||
}
|
||||
i &= 0xffff;
|
||||
return AddSegment(m, rde, i, s);
|
||||
}
|
||||
|
||||
int64_t ComputeAddress(const struct Machine *m, uint32_t rde) {
|
||||
struct AddrSeg LoadEffectiveAddress(const struct Machine *m, uint32_t rde) {
|
||||
uint8_t *s = m->ds;
|
||||
uint64_t i = m->xedd->op.disp;
|
||||
DCHECK(!IsModrmRegister(rde));
|
||||
|
@ -100,10 +56,53 @@ int64_t ComputeAddress(const struct Machine *m, uint32_t rde) {
|
|||
if (Eamode(rde) == XED_MODE_LEGACY) {
|
||||
i &= 0xffffffff;
|
||||
}
|
||||
return AddSegment(m, rde, i, s);
|
||||
} else {
|
||||
return ComputeAddressReal(m, rde, s, i);
|
||||
switch (ModrmRm(rde)) {
|
||||
case 0:
|
||||
i += Read16(m->bx);
|
||||
i += Read16(m->si);
|
||||
break;
|
||||
case 1:
|
||||
i += Read16(m->bx);
|
||||
i += Read16(m->di);
|
||||
break;
|
||||
case 2:
|
||||
s = m->ss;
|
||||
i += Read16(m->bp);
|
||||
i += Read16(m->si);
|
||||
break;
|
||||
case 3:
|
||||
s = m->ss;
|
||||
i += Read16(m->bp);
|
||||
i += Read16(m->di);
|
||||
break;
|
||||
case 4:
|
||||
i += Read16(m->si);
|
||||
break;
|
||||
case 5:
|
||||
i += Read16(m->di);
|
||||
break;
|
||||
case 6:
|
||||
if (ModrmMod(rde)) {
|
||||
s = m->ss;
|
||||
i += Read16(m->bp);
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
i += Read16(m->bx);
|
||||
break;
|
||||
default:
|
||||
unreachable;
|
||||
}
|
||||
i &= 0xffff;
|
||||
}
|
||||
return (struct AddrSeg){i, s};
|
||||
}
|
||||
|
||||
int64_t ComputeAddress(const struct Machine *m, uint32_t rde) {
|
||||
struct AddrSeg ea;
|
||||
ea = LoadEffectiveAddress(m, rde);
|
||||
return AddSegment(m, rde, ea.addr, ea.seg);
|
||||
}
|
||||
|
||||
void *ComputeReserveAddressRead(struct Machine *m, uint32_t rde, size_t n) {
|
||||
|
|
|
@ -50,9 +50,15 @@ COSMOPOLITAN_C_START_
|
|||
#define SibIsAbsolute(x, r) (!SibHasBase(x, r) && !SibHasIndex(x))
|
||||
#define IsRipRelative(x) (ModrmRm(x) == 5 && !ModrmMod(x))
|
||||
|
||||
struct AddrSeg {
|
||||
int64_t addr;
|
||||
uint8_t *seg;
|
||||
};
|
||||
|
||||
extern const uint8_t kByteReg[32];
|
||||
|
||||
int64_t ComputeAddress(const struct Machine *, uint32_t) nosideeffect;
|
||||
int64_t ComputeAddress(const struct Machine *, uint32_t);
|
||||
struct AddrSeg LoadEffectiveAddress(const struct Machine *, uint32_t);
|
||||
|
||||
void *ComputeReserveAddressRead(struct Machine *, uint32_t, size_t);
|
||||
void *ComputeReserveAddressRead1(struct Machine *, uint32_t);
|
||||
|
|
|
@ -469,18 +469,21 @@ ssize_t MachinePtyWrite(struct MachinePty *pty, const void *data, size_t n) {
|
|||
} else if (!ThomPikeCont(p[i])) {
|
||||
pty->state = kMachinePtyUtf8;
|
||||
pty->u8 = ThomPikeByte(p[i]);
|
||||
pty->n8 = ThomPikeLen(p[i]) - 1;
|
||||
}
|
||||
break;
|
||||
case kMachinePtyUtf8:
|
||||
if (ThomPikeCont(p[i])) {
|
||||
pty->u8 <<= 6;
|
||||
pty->u8 |= p[i] & 0b00111111;
|
||||
} else {
|
||||
SetMachinePtyCell(pty, pty->u8);
|
||||
pty->state = kMachinePtyAscii;
|
||||
pty->u8 = 0;
|
||||
--i;
|
||||
if (--pty->n8) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
SetMachinePtyCell(pty, pty->u8);
|
||||
pty->state = kMachinePtyAscii;
|
||||
pty->u8 = 0;
|
||||
--i;
|
||||
break;
|
||||
case kMachinePtyEsc:
|
||||
if (p[i] == '[') {
|
||||
|
@ -531,9 +534,6 @@ ssize_t MachinePtyWrite(struct MachinePty *pty, const void *data, size_t n) {
|
|||
abort();
|
||||
}
|
||||
}
|
||||
if (pty->u8) {
|
||||
SetMachinePtyCell(pty, pty->u8);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@ struct MachinePty {
|
|||
uint32_t fg;
|
||||
uint32_t bg;
|
||||
uint32_t u8;
|
||||
uint32_t n8;
|
||||
uint32_t *wcs;
|
||||
uint32_t *fgs;
|
||||
uint32_t *bgs;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue