Add pseudoteletypewriter to emulator

https://justine.storage.googleapis.com/emulator628.mp4
This commit is contained in:
Justine Tunney 2020-08-26 23:08:08 -07:00
parent e86cff8ba0
commit 5aabacb361
94 changed files with 3245 additions and 2179 deletions

View file

@ -12,8 +12,6 @@
#define ALU_CMP 7
#define ALU_TEST 8
#define ALU_FLIP 16
#define ALU_XCHG 64
#define ALU_BYTE 128
#define BSU_ROL 0
#define BSU_ROR 1
@ -27,8 +25,8 @@
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
typedef uint64_t (*aluop1_f)(struct Machine *, uint64_t);
typedef uint64_t (*aluop2_f)(struct Machine *, uint64_t, uint64_t);
typedef uint64_t (*aluop1_f)(struct Machine *, uint32_t, uint64_t);
typedef uint64_t (*aluop2_f)(struct Machine *, uint32_t, uint64_t, uint64_t);
int64_t Alu(int, int, uint64_t, uint64_t, uint32_t *);
int64_t Bsu(int, int, uint64_t, uint64_t, uint32_t *);

View file

@ -22,14 +22,14 @@
#include "tool/build/lib/machine.h"
#include "tool/build/lib/modrm.h"
uint64_t AluBsr(struct Machine *m, uint64_t _, uint64_t x) {
uint64_t AluBsr(struct Machine *m, uint32_t rde, uint64_t _, uint64_t x) {
unsigned i;
if (Rexw(m->xedd)) {
if (Rexw(rde)) {
x &= 0xffffffffffffffff;
m->flags = SetFlag(m->flags, FLAGS_ZF, !x);
if (!x) return 0;
return 63 ^ __builtin_clzll(x);
} else if (!Osz(m->xedd)) {
} else if (!Osz(rde)) {
x &= 0xffffffff;
m->flags = SetFlag(m->flags, FLAGS_ZF, !x);
if (!x) return 0;
@ -43,14 +43,14 @@ uint64_t AluBsr(struct Machine *m, uint64_t _, uint64_t x) {
}
}
uint64_t AluBsf(struct Machine *m, uint64_t _, uint64_t x) {
uint64_t AluBsf(struct Machine *m, uint32_t rde, uint64_t _, uint64_t x) {
unsigned i;
if (Rexw(m->xedd)) {
if (Rexw(rde)) {
x &= 0xffffffffffffffff;
m->flags = SetFlag(m->flags, FLAGS_ZF, !x);
if (!x) return 0;
return __builtin_ctzll(x);
} else if (!Osz(m->xedd)) {
} else if (!Osz(rde)) {
x &= 0xffffffff;
m->flags = SetFlag(m->flags, FLAGS_ZF, !x);
if (!x) return 0;
@ -64,7 +64,7 @@ uint64_t AluBsf(struct Machine *m, uint64_t _, uint64_t x) {
}
}
uint64_t AluPopcnt(struct Machine *m, uint64_t _, uint64_t x) {
uint64_t AluPopcnt(struct Machine *m, uint32_t rde, uint64_t _, uint64_t x) {
m->flags = SetFlag(m->flags, FLAGS_ZF, !x);
m->flags = SetFlag(m->flags, FLAGS_CF, false);
m->flags = SetFlag(m->flags, FLAGS_SF, false);

View file

@ -4,9 +4,9 @@
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
uint64_t AluBsr(struct Machine *, uint64_t, uint64_t);
uint64_t AluBsf(struct Machine *, uint64_t, uint64_t);
uint64_t AluPopcnt(struct Machine *, uint64_t, uint64_t);
uint64_t AluBsr(struct Machine *, uint32_t, uint64_t, uint64_t);
uint64_t AluBsf(struct Machine *, uint32_t, uint64_t, uint64_t);
uint64_t AluPopcnt(struct Machine *, uint32_t, uint64_t, uint64_t);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View file

@ -21,7 +21,13 @@
#include "libc/assert.h"
#include "tool/build/lib/breakpoint.h"
ssize_t AddBreakpoint(struct Breakpoints *bps, struct Breakpoint *b) {
void PopBreakpoint(struct Breakpoints *bps) {
if (bps->i) {
--bps->i;
}
}
ssize_t PushBreakpoint(struct Breakpoints *bps, struct Breakpoint *b) {
int i;
for (i = 0; i < bps->i; ++i) {
if (bps->p[i].disable) {

View file

@ -14,7 +14,8 @@ struct Breakpoints {
};
ssize_t IsAtBreakpoint(struct Breakpoints *, int64_t);
ssize_t AddBreakpoint(struct Breakpoints *, struct Breakpoint *);
ssize_t PushBreakpoint(struct Breakpoints *, struct Breakpoint *);
void PopBreakpoint(struct Breakpoints *);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View file

@ -17,6 +17,7 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "dsp/tty/tty.h"
#include "libc/alg/arraylist2.h"
#include "libc/calls/calls.h"
#include "libc/fmt/fmt.h"
@ -57,12 +58,5 @@ void AppendFmt(struct Buffer *b, const char *fmt, ...) {
* Writes buffer until completion, interrupt, or error occurs.
*/
ssize_t WriteBuffer(struct Buffer *b, int fd) {
size_t i;
ssize_t rc;
for (i = 0; i < b->i; i += rc) {
if ((rc = write(fd, b->p + i, b->i - i)) == -1) {
return -1;
}
}
return i;
return ttywrite(fd, b->p, b->i);
}

View file

@ -25,6 +25,7 @@ TOOL_BUILD_LIB_A_OBJS = \
$(TOOL_BUILD_LIB_A_SRCS_C:%.c=o/$(MODE)/%.o)
TOOL_BUILD_LIB_A_DIRECTDEPS = \
DSP_TTY \
LIBC_ALG \
LIBC_BITS \
LIBC_CONV \

View file

@ -26,287 +26,287 @@
#include "tool/build/lib/modrm.h"
#include "tool/build/lib/throw.h"
static void OpGdqpWssCvttss2si(struct Machine *m) {
static void OpGdqpWssCvttss2si(struct Machine *m, uint32_t rde) {
float f;
int64_t n;
memcpy(&f, GetModrmRegisterXmmPointerRead4(m), 4);
memcpy(&f, GetModrmRegisterXmmPointerRead4(m, rde), 4);
n = f;
if (!Rexw(m->xedd)) n &= 0xffffffff;
Write64(RegRexrReg(m), n);
if (!Rexw(rde)) n &= 0xffffffff;
Write64(RegRexrReg(m, rde), n);
}
static void OpGdqpWsdCvttsd2si(struct Machine *m) {
static void OpGdqpWsdCvttsd2si(struct Machine *m, uint32_t rde) {
double d;
int64_t n;
memcpy(&d, GetModrmRegisterXmmPointerRead8(m), 8);
memcpy(&d, GetModrmRegisterXmmPointerRead8(m, rde), 8);
n = d;
if (!Rexw(m->xedd)) n &= 0xffffffff;
Write64(RegRexrReg(m), n);
if (!Rexw(rde)) n &= 0xffffffff;
Write64(RegRexrReg(m, rde), n);
}
static void OpGdqpWssCvtss2si(struct Machine *m) {
static void OpGdqpWssCvtss2si(struct Machine *m, uint32_t rde) {
float f;
int64_t n;
memcpy(&f, GetModrmRegisterXmmPointerRead4(m), 4);
memcpy(&f, GetModrmRegisterXmmPointerRead4(m, rde), 4);
n = rintf(f);
if (!Rexw(m->xedd)) n &= 0xffffffff;
Write64(RegRexrReg(m), n);
if (!Rexw(rde)) n &= 0xffffffff;
Write64(RegRexrReg(m, rde), n);
}
static void OpGdqpWsdCvtsd2si(struct Machine *m) {
static void OpGdqpWsdCvtsd2si(struct Machine *m, uint32_t rde) {
double d;
int64_t n;
memcpy(&d, GetModrmRegisterXmmPointerRead8(m), 8);
memcpy(&d, GetModrmRegisterXmmPointerRead8(m, rde), 8);
n = nearbyint(d);
if (!Rexw(m->xedd)) n &= 0xffffffff;
Write64(RegRexrReg(m), n);
if (!Rexw(rde)) n &= 0xffffffff;
Write64(RegRexrReg(m, rde), n);
}
static void OpVssEdqpCvtsi2ss(struct Machine *m) {
static void OpVssEdqpCvtsi2ss(struct Machine *m, uint32_t rde) {
float f;
int64_t n;
uint8_t *p;
if (Rexw(m->xedd)) {
n = (int64_t)Read64(GetModrmRegisterWordPointerRead8(m));
if (Rexw(rde)) {
n = (int64_t)Read64(GetModrmRegisterWordPointerRead8(m, rde));
} else {
n = (int32_t)Read32(GetModrmRegisterWordPointerRead4(m));
n = (int32_t)Read32(GetModrmRegisterWordPointerRead4(m, rde));
}
f = n;
memcpy(XmmRexrReg(m), &f, 4);
memcpy(XmmRexrReg(m, rde), &f, 4);
}
static void OpVsdEdqpCvtsi2sd(struct Machine *m) {
static void OpVsdEdqpCvtsi2sd(struct Machine *m, uint32_t rde) {
double d;
int64_t n;
uint8_t *p;
if (Rexw(m->xedd)) {
n = (int64_t)Read64(GetModrmRegisterWordPointerRead8(m));
if (Rexw(rde)) {
n = (int64_t)Read64(GetModrmRegisterWordPointerRead8(m, rde));
} else {
n = (int32_t)Read32(GetModrmRegisterWordPointerRead4(m));
n = (int32_t)Read32(GetModrmRegisterWordPointerRead4(m, rde));
}
d = n;
memcpy(XmmRexrReg(m), &d, 8);
memcpy(XmmRexrReg(m, rde), &d, 8);
}
static void OpVpsQpiCvtpi2ps(struct Machine *m) {
static void OpVpsQpiCvtpi2ps(struct Machine *m, uint32_t rde) {
uint8_t *p;
float f[2];
int32_t i[2];
p = GetModrmRegisterMmPointerRead8(m);
p = GetModrmRegisterMmPointerRead8(m, rde);
i[0] = Read32(p + 0);
i[1] = Read32(p + 4);
f[0] = i[0];
f[1] = i[1];
memcpy(XmmRexrReg(m), f, 8);
memcpy(XmmRexrReg(m, rde), f, 8);
}
static void OpVpdQpiCvtpi2pd(struct Machine *m) {
static void OpVpdQpiCvtpi2pd(struct Machine *m, uint32_t rde) {
uint8_t *p;
double f[2];
int32_t n[2];
p = GetModrmRegisterMmPointerRead8(m);
p = GetModrmRegisterMmPointerRead8(m, rde);
n[0] = Read32(p + 0);
n[1] = Read32(p + 4);
f[0] = n[0];
f[1] = n[1];
memcpy(XmmRexrReg(m), f, 16);
memcpy(XmmRexrReg(m, rde), f, 16);
}
static void OpPpiWpsqCvtps2pi(struct Machine *m) {
static void OpPpiWpsqCvtps2pi(struct Machine *m, uint32_t rde) {
float f[2];
int32_t n[2];
memcpy(f, GetModrmRegisterXmmPointerRead8(m), 8);
memcpy(f, GetModrmRegisterXmmPointerRead8(m, rde), 8);
n[0] = nearbyintf(f[0]);
n[1] = nearbyintf(f[1]);
Write32(MmReg(m) + 0, n[0]);
Write32(MmReg(m) + 4, n[1]);
Write32(MmReg(m, rde) + 0, n[0]);
Write32(MmReg(m, rde) + 4, n[1]);
}
static void OpPpiWpsqCvttps2pi(struct Machine *m) {
static void OpPpiWpsqCvttps2pi(struct Machine *m, uint32_t rde) {
float f[2];
int32_t n[2];
memcpy(&f, GetModrmRegisterXmmPointerRead8(m), 8);
memcpy(&f, GetModrmRegisterXmmPointerRead8(m, rde), 8);
n[0] = f[0];
n[1] = f[1];
Write32(MmReg(m) + 0, n[0]);
Write32(MmReg(m) + 4, n[1]);
Write32(MmReg(m, rde) + 0, n[0]);
Write32(MmReg(m, rde) + 4, n[1]);
}
static void OpPpiWpdCvtpd2pi(struct Machine *m) {
static void OpPpiWpdCvtpd2pi(struct Machine *m, uint32_t rde) {
double d[2];
int32_t n[2];
memcpy(d, GetModrmRegisterXmmPointerRead16(m), 16);
memcpy(d, GetModrmRegisterXmmPointerRead16(m, rde), 16);
n[0] = nearbyint(d[0]);
n[1] = nearbyint(d[1]);
Write32(MmReg(m) + 0, n[0]);
Write32(MmReg(m) + 4, n[1]);
Write32(MmReg(m, rde) + 0, n[0]);
Write32(MmReg(m, rde) + 4, n[1]);
}
static void OpPpiWpdCvttpd2pi(struct Machine *m) {
static void OpPpiWpdCvttpd2pi(struct Machine *m, uint32_t rde) {
double d[2];
int32_t n[2];
memcpy(&d, GetModrmRegisterXmmPointerRead16(m), 16);
memcpy(&d, GetModrmRegisterXmmPointerRead16(m, rde), 16);
n[0] = d[0];
n[1] = d[1];
Write32(MmReg(m) + 0, n[0]);
Write32(MmReg(m) + 4, n[1]);
Write32(MmReg(m, rde) + 0, n[0]);
Write32(MmReg(m, rde) + 4, n[1]);
}
static void OpVpdWpsCvtps2pd(struct Machine *m) {
static void OpVpdWpsCvtps2pd(struct Machine *m, uint32_t rde) {
float f[2];
double d[2];
memcpy(f, GetModrmRegisterXmmPointerRead8(m), 8);
memcpy(f, GetModrmRegisterXmmPointerRead8(m, rde), 8);
d[0] = f[0];
d[1] = f[1];
memcpy(XmmRexrReg(m), d, 16);
memcpy(XmmRexrReg(m, rde), d, 16);
}
static void OpVpsWpdCvtpd2ps(struct Machine *m) {
static void OpVpsWpdCvtpd2ps(struct Machine *m, uint32_t rde) {
float f[2];
double d[2];
memcpy(d, GetModrmRegisterXmmPointerRead16(m), 16);
memcpy(d, GetModrmRegisterXmmPointerRead16(m, rde), 16);
f[0] = d[0];
f[1] = d[1];
memcpy(XmmRexrReg(m), f, 8);
memcpy(XmmRexrReg(m, rde), f, 8);
}
static void OpVssWsdCvtsd2ss(struct Machine *m) {
static void OpVssWsdCvtsd2ss(struct Machine *m, uint32_t rde) {
float f;
double d;
memcpy(&d, GetModrmRegisterXmmPointerRead8(m), 8);
memcpy(&d, GetModrmRegisterXmmPointerRead8(m, rde), 8);
f = d;
memcpy(XmmRexrReg(m), &f, 4);
memcpy(XmmRexrReg(m, rde), &f, 4);
}
static void OpVsdWssCvtss2sd(struct Machine *m) {
static void OpVsdWssCvtss2sd(struct Machine *m, uint32_t rde) {
float f;
double d;
memcpy(&f, GetModrmRegisterXmmPointerRead4(m), 4);
memcpy(&f, GetModrmRegisterXmmPointerRead4(m, rde), 4);
d = f;
memcpy(XmmRexrReg(m), &d, 8);
memcpy(XmmRexrReg(m, rde), &d, 8);
}
static void OpVpsWdqCvtdq2ps(struct Machine *m) {
static void OpVpsWdqCvtdq2ps(struct Machine *m, uint32_t rde) {
unsigned i;
float f[4];
int32_t n[4];
memcpy(n, GetModrmRegisterXmmPointerRead16(m), 16);
memcpy(n, GetModrmRegisterXmmPointerRead16(m, rde), 16);
for (i = 0; i < 4; ++i) f[i] = n[i];
memcpy(XmmRexrReg(m), f, 16);
memcpy(XmmRexrReg(m, rde), f, 16);
}
static void OpVpdWdqCvtdq2pd(struct Machine *m) {
static void OpVpdWdqCvtdq2pd(struct Machine *m, uint32_t rde) {
unsigned i;
double d[2];
int32_t n[2];
memcpy(n, GetModrmRegisterXmmPointerRead8(m), 8);
memcpy(n, GetModrmRegisterXmmPointerRead8(m, rde), 8);
for (i = 0; i < 2; ++i) d[i] = n[i];
memcpy(XmmRexrReg(m), d, 16);
memcpy(XmmRexrReg(m, rde), d, 16);
}
static void OpVdqWpsCvttps2dq(struct Machine *m) {
static void OpVdqWpsCvttps2dq(struct Machine *m, uint32_t rde) {
unsigned i;
float f[4];
int32_t n[4];
memcpy(f, GetModrmRegisterXmmPointerRead16(m), 16);
memcpy(f, GetModrmRegisterXmmPointerRead16(m, rde), 16);
for (i = 0; i < 4; ++i) n[i] = f[i];
memcpy(XmmRexrReg(m), n, 16);
memcpy(XmmRexrReg(m, rde), n, 16);
}
static void OpVdqWpsCvtps2dq(struct Machine *m) {
static void OpVdqWpsCvtps2dq(struct Machine *m, uint32_t rde) {
unsigned i;
float f[4];
int32_t n[4];
memcpy(f, GetModrmRegisterXmmPointerRead16(m), 16);
memcpy(f, GetModrmRegisterXmmPointerRead16(m, rde), 16);
for (i = 0; i < 4; ++i) n[i] = nearbyintf(f[i]);
memcpy(XmmRexrReg(m), n, 16);
memcpy(XmmRexrReg(m, rde), n, 16);
}
static void OpVdqWpdCvttpd2dq(struct Machine *m) {
static void OpVdqWpdCvttpd2dq(struct Machine *m, uint32_t rde) {
unsigned i;
double d[2];
int32_t n[2];
memcpy(d, GetModrmRegisterXmmPointerRead16(m), 16);
memcpy(d, GetModrmRegisterXmmPointerRead16(m, rde), 16);
for (i = 0; i < 2; ++i) n[i] = d[i];
memcpy(XmmRexrReg(m), n, 8);
memcpy(XmmRexrReg(m, rde), n, 8);
}
static void OpVdqWpdCvtpd2dq(struct Machine *m) {
static void OpVdqWpdCvtpd2dq(struct Machine *m, uint32_t rde) {
unsigned i;
double d[2];
int32_t n[2];
memcpy(d, GetModrmRegisterXmmPointerRead16(m), 16);
memcpy(d, GetModrmRegisterXmmPointerRead16(m, rde), 16);
for (i = 0; i < 2; ++i) n[i] = nearbyintf(d[i]);
memcpy(XmmRexrReg(m), n, 8);
memcpy(XmmRexrReg(m, rde), n, 8);
}
void OpCvt(struct Machine *m, unsigned long op) {
switch (op | Rep(m->xedd) | Osz(m->xedd)) {
void OpCvt(struct Machine *m, uint32_t rde, unsigned long op) {
switch (op | Rep(rde) | Osz(rde)) {
case kOpCvt0f2a + 0:
OpVpsQpiCvtpi2ps(m);
OpVpsQpiCvtpi2ps(m, rde);
break;
case kOpCvt0f2a + 1:
OpVpdQpiCvtpi2pd(m);
OpVpdQpiCvtpi2pd(m, rde);
break;
case kOpCvt0f2a + 2:
OpVsdEdqpCvtsi2sd(m);
OpVsdEdqpCvtsi2sd(m, rde);
break;
case kOpCvt0f2a + 3:
OpVssEdqpCvtsi2ss(m);
OpVssEdqpCvtsi2ss(m, rde);
break;
case kOpCvtt0f2c + 0:
OpPpiWpsqCvttps2pi(m);
OpPpiWpsqCvttps2pi(m, rde);
break;
case kOpCvtt0f2c + 1:
OpPpiWpdCvttpd2pi(m);
OpPpiWpdCvttpd2pi(m, rde);
break;
case kOpCvtt0f2c + 2:
OpGdqpWsdCvttsd2si(m);
OpGdqpWsdCvttsd2si(m, rde);
break;
case kOpCvtt0f2c + 3:
OpGdqpWssCvttss2si(m);
OpGdqpWssCvttss2si(m, rde);
break;
case kOpCvt0f2d + 0:
OpPpiWpsqCvtps2pi(m);
OpPpiWpsqCvtps2pi(m, rde);
break;
case kOpCvt0f2d + 1:
OpPpiWpdCvtpd2pi(m);
OpPpiWpdCvtpd2pi(m, rde);
break;
case kOpCvt0f2d + 2:
OpGdqpWsdCvtsd2si(m);
OpGdqpWsdCvtsd2si(m, rde);
break;
case kOpCvt0f2d + 3:
OpGdqpWssCvtss2si(m);
OpGdqpWssCvtss2si(m, rde);
break;
case kOpCvt0f5a + 0:
OpVpdWpsCvtps2pd(m);
OpVpdWpsCvtps2pd(m, rde);
break;
case kOpCvt0f5a + 1:
OpVpsWpdCvtpd2ps(m);
OpVpsWpdCvtpd2ps(m, rde);
break;
case kOpCvt0f5a + 2:
OpVssWsdCvtsd2ss(m);
OpVssWsdCvtsd2ss(m, rde);
break;
case kOpCvt0f5a + 3:
OpVsdWssCvtss2sd(m);
OpVsdWssCvtss2sd(m, rde);
break;
case kOpCvt0f5b + 0:
OpVpsWdqCvtdq2ps(m);
OpVpsWdqCvtdq2ps(m, rde);
break;
case kOpCvt0f5b + 1:
OpVdqWpsCvtps2dq(m);
OpVdqWpsCvtps2dq(m, rde);
break;
case kOpCvt0f5b + 3:
OpVdqWpsCvttps2dq(m);
OpVdqWpsCvttps2dq(m, rde);
break;
case kOpCvt0fE6 + 1:
OpVdqWpdCvtpd2dq(m);
OpVdqWpdCvtpd2dq(m, rde);
break;
case kOpCvt0fE6 + 2:
OpVdqWpdCvttpd2dq(m);
OpVdqWpdCvttpd2dq(m, rde);
break;
case kOpCvt0fE6 + 3:
OpVpdWdqCvtdq2pd(m);
OpVpdWdqCvtdq2pd(m, rde);
break;
default:
OpUd(m);

View file

@ -11,7 +11,7 @@ COSMOPOLITAN_C_START_
#define kOpCvt0f5b 16
#define kOpCvt0fE6 20
void OpCvt(struct Machine *, unsigned long);
void OpCvt(struct Machine *, uint32_t, unsigned long);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View file

@ -33,6 +33,7 @@
#include "third_party/xed/x86.h"
#include "tool/build/lib/case.h"
#include "tool/build/lib/dis.h"
#include "tool/build/lib/memory.h"
#include "tool/build/lib/modrm.h"
#define ADDRLEN 8

View file

@ -61,7 +61,7 @@ static int64_t RipRelative(struct DisBuilder b, int64_t d) {
}
static const char *GetAddrReg(struct DisBuilder b, uint8_t x, uint8_t r) {
return kRegisterName[0][!Asz(b.xedd)][x & 1][r & 7];
return kRegisterName[0][!Asz(b.xedd->op.rde)][x & 1][r & 7];
}
static char *DisRegister(char *p, const char *s) {
@ -87,24 +87,25 @@ static char *DisComment(char *p, const char *s) {
}
static char *DisRegisterByte(struct DisBuilder b, char *p, bool g, int r) {
return DisRegister(p, kRegisterName8[g][Rex(b.xedd)][r]);
return DisRegister(p, kRegisterName8[g][Rex(b.xedd->op.rde)][r]);
}
static char *DisRegisterWord(struct DisBuilder b, char *p, bool g, int r) {
return DisRegister(p, kRegisterName[Osz(b.xedd)][Rexw(b.xedd)][g][r]);
return DisRegister(
p, kRegisterName[Osz(b.xedd->op.rde)][Rexw(b.xedd->op.rde)][g][r]);
}
static char *DisGvqp(struct DisBuilder b, char *p) {
return DisRegisterWord(b, p, Rexr(b.xedd), ModrmReg(b.xedd));
return DisRegisterWord(b, p, Rexr(b.xedd->op.rde), ModrmReg(b.xedd->op.rde));
}
static char *DisGdqp(struct DisBuilder b, char *p) {
return DisRegister(
p, kRegisterName[0][Rexw(b.xedd)][Rexr(b.xedd)][ModrmReg(b.xedd)]);
return DisRegister(p, kRegisterName[0][Rexw(b.xedd->op.rde)][Rexr(
b.xedd->op.rde)][ModrmReg(b.xedd->op.rde)]);
}
static char *DisGb(struct DisBuilder b, char *p) {
return DisRegisterByte(b, p, Rexr(b.xedd), ModrmReg(b.xedd));
return DisRegisterByte(b, p, Rexr(b.xedd->op.rde), ModrmReg(b.xedd->op.rde));
}
static uint8_t DisSeg(struct DisBuilder b) {
@ -154,30 +155,29 @@ static char *DisM(struct DisBuilder b, char *p) {
p = DisRegister(p, seg);
*p++ = ':';
}
if (ModrmMod(b.xedd) == 0b01 || ModrmMod(b.xedd) == 0b10 ||
IsRipRelative(b.xedd) ||
(ModrmMod(b.xedd) == 0b00 && ModrmRm(b.xedd) == 0b100 &&
SibBase(b.xedd) == 0b101)) {
if (ModrmMod(b.xedd->op.rde) == 0b01 || ModrmMod(b.xedd->op.rde) == 0b10 ||
IsRipRelative(b.xedd->op.rde) ||
(ModrmMod(b.xedd->op.rde) == 0b00 && ModrmRm(b.xedd->op.rde) == 0b100 &&
SibBase(b.xedd->op.rde) == 0b101)) {
disp = b.xedd->op.disp;
if (IsRipRelative(b.xedd)) disp = RipRelative(b, disp);
if (IsRipRelative(b.xedd->op.rde)) disp = RipRelative(b, disp);
p = DisSym(b, p, disp);
}
if (!SibExists(b.xedd)) {
if (!SibExists(b.xedd->op.rde)) {
DCHECK(!b.xedd->op.has_sib);
if (IsRipRelative(b.xedd)) {
if (IsRipRelative(b.xedd->op.rde)) {
base = "rip";
} else {
base = GetAddrReg(b, Rexb(b.xedd), ModrmRm(b.xedd));
base = GetAddrReg(b, Rexb(b.xedd->op.rde), ModrmRm(b.xedd->op.rde));
}
} else if (!SibIsAbsolute(b.xedd)) {
DCHECK(b.xedd->op.has_sib);
if (SibHasBase(b.xedd)) {
base = GetAddrReg(b, Rexb(b.xedd), SibBase(b.xedd));
} else if (!SibIsAbsolute(b.xedd->op.rde)) {
if (SibHasBase(b.xedd->op.rde)) {
base = GetAddrReg(b, Rexb(b.xedd->op.rde), SibBase(b.xedd->op.rde));
}
if (SibHasIndex(b.xedd)) {
index = GetAddrReg(b, Rexx(b.xedd), SibIndex(b.xedd));
if (SibHasIndex(b.xedd->op.rde)) {
index = GetAddrReg(b, Rexx(b.xedd->op.rde), SibIndex(b.xedd->op.rde));
} else if (b.xedd->op.scale) {
index = Asz(b.xedd) ? "eiz" : "riz";
index = Asz(b.xedd->op.rde) ? "eiz" : "riz";
}
scale = kScale[b.xedd->op.scale];
}
@ -198,25 +198,25 @@ static char *DisM(struct DisBuilder b, char *p) {
}
static char *DisEb(struct DisBuilder b, char *p) {
if (IsModrmRegister(b.xedd)) {
return DisRegisterByte(b, p, Rexb(b.xedd), ModrmRm(b.xedd));
if (IsModrmRegister(b.xedd->op.rde)) {
return DisRegisterByte(b, p, Rexb(b.xedd->op.rde), ModrmRm(b.xedd->op.rde));
} else {
return DisM(b, p);
}
}
static char *DisEvqp(struct DisBuilder b, char *p) {
if (IsModrmRegister(b.xedd)) {
return DisRegisterWord(b, p, Rexb(b.xedd), ModrmRm(b.xedd));
if (IsModrmRegister(b.xedd->op.rde)) {
return DisRegisterWord(b, p, Rexb(b.xedd->op.rde), ModrmRm(b.xedd->op.rde));
} else {
return DisM(b, p);
}
}
static char *DisEdqp(struct DisBuilder b, char *p) {
if (IsModrmRegister(b.xedd)) {
return DisRegister(
p, kRegisterName[0][Rexw(b.xedd)][Rexb(b.xedd)][ModrmRm(b.xedd)]);
if (IsModrmRegister(b.xedd->op.rde)) {
return DisRegister(p, kRegisterName[0][Rexw(b.xedd->op.rde)][Rexb(
b.xedd->op.rde)][ModrmRm(b.xedd->op.rde)]);
} else {
return DisM(b, p);
}
@ -224,11 +224,11 @@ static char *DisEdqp(struct DisBuilder b, char *p) {
static char *DisEvq(struct DisBuilder b, char *p) {
const char *s;
if (IsModrmRegister(b.xedd)) {
if (Osz(b.xedd)) {
s = kRegisterName[1][0][Rexb(b.xedd)][ModrmRm(b.xedd)];
if (IsModrmRegister(b.xedd->op.rde)) {
if (Osz(b.xedd->op.rde)) {
s = kRegisterName[1][0][Rexb(b.xedd->op.rde)][ModrmRm(b.xedd->op.rde)];
} else {
s = kRegisterName[0][1][Rexb(b.xedd)][ModrmRm(b.xedd)];
s = kRegisterName[0][1][Rexb(b.xedd->op.rde)][ModrmRm(b.xedd->op.rde)];
}
return DisRegister(p, s);
} else {
@ -237,47 +237,53 @@ static char *DisEvq(struct DisBuilder b, char *p) {
}
static char *DisEd(struct DisBuilder b, char *p) {
if (IsModrmRegister(b.xedd)) {
return DisRegister(p, kRegisterName[0][0][Rexb(b.xedd)][ModrmRm(b.xedd)]);
if (IsModrmRegister(b.xedd->op.rde)) {
return DisRegister(
p, kRegisterName[0][0][Rexb(b.xedd->op.rde)][ModrmRm(b.xedd->op.rde)]);
} else {
return DisM(b, p);
}
}
static char *DisEq(struct DisBuilder b, char *p) {
if (IsModrmRegister(b.xedd)) {
return DisRegister(p, kRegisterName[0][1][Rexb(b.xedd)][ModrmRm(b.xedd)]);
if (IsModrmRegister(b.xedd->op.rde)) {
return DisRegister(
p, kRegisterName[0][1][Rexb(b.xedd->op.rde)][ModrmRm(b.xedd->op.rde)]);
} else {
return DisM(b, p);
}
}
static char *DisZvq(struct DisBuilder b, char *p) {
if (Osz(b.xedd)) {
return DisRegister(p, kRegisterName[1][0][Rexb(b.xedd)][ModrmSrm(b.xedd)]);
if (Osz(b.xedd->op.rde)) {
return DisRegister(
p, kRegisterName[1][0][Rexb(b.xedd->op.rde)][ModrmSrm(b.xedd->op.rde)]);
} else {
return DisRegister(p, kRegisterName[0][1][Rexb(b.xedd)][ModrmSrm(b.xedd)]);
return DisRegister(
p, kRegisterName[0][1][Rexb(b.xedd->op.rde)][ModrmSrm(b.xedd->op.rde)]);
}
}
static char *DisZvqp(struct DisBuilder b, char *p) {
return DisRegisterWord(b, p, Rexb(b.xedd), ModrmSrm(b.xedd));
return DisRegisterWord(b, p, Rexb(b.xedd->op.rde), ModrmSrm(b.xedd->op.rde));
}
static char *DisZb(struct DisBuilder b, char *p) {
return DisRegisterByte(b, p, Rexb(b.xedd), ModrmSrm(b.xedd));
return DisRegisterByte(b, p, Rexb(b.xedd->op.rde), ModrmSrm(b.xedd->op.rde));
}
static char *DisEax(struct DisBuilder b, char *p) {
return DisRegister(p, kRegisterName[Osz(b.xedd)][0][0][0]);
return DisRegister(p, kRegisterName[Osz(b.xedd->op.rde)][0][0][0]);
}
static char *DisRax(struct DisBuilder b, char *p) {
return DisRegister(p, kRegisterName[Osz(b.xedd)][Rexw(b.xedd)][0][0]);
return DisRegister(
p, kRegisterName[Osz(b.xedd->op.rde)][Rexw(b.xedd->op.rde)][0][0]);
}
static char *DisRdx(struct DisBuilder b, char *p) {
return DisRegister(p, kRegisterName[Osz(b.xedd)][Rexw(b.xedd)][0][2]);
return DisRegister(
p, kRegisterName[Osz(b.xedd->op.rde)][Rexw(b.xedd->op.rde)][0][2]);
}
static char *DisImm(struct DisBuilder b, char *p) {
@ -309,8 +315,8 @@ static char *DisAbs(struct DisBuilder b, char *p) {
}
static char *DisSw(struct DisBuilder b, char *p) {
if (kSegName[ModrmReg(b.xedd)][0]) {
p = DisRegister(p, kSegName[ModrmReg(b.xedd)]);
if (kSegName[ModrmReg(b.xedd->op.rde)][0]) {
p = DisRegister(p, kSegName[ModrmReg(b.xedd->op.rde)]);
}
*p = '\0';
return p;
@ -318,7 +324,7 @@ static char *DisSw(struct DisBuilder b, char *p) {
static char *DisY(struct DisBuilder b, char *p) {
*p++ = '(';
p = DisRegister(p, Asz(b.xedd) ? "edi" : "rdi");
p = DisRegister(p, Asz(b.xedd->op.rde) ? "edi" : "rdi");
*p++ = ')';
*p = '\0';
return p;
@ -329,7 +335,7 @@ static char *DisX(struct DisBuilder b, char *p) {
p = DisRegister(p, kSegOverride[b.xedd->op.seg_ovd]);
}
*p++ = '(';
p = DisRegister(p, Asz(b.xedd) ? "esi" : "rsi");
p = DisRegister(p, Asz(b.xedd->op.rde) ? "esi" : "rsi");
*p++ = ')';
*p = '\0';
return p;
@ -340,7 +346,7 @@ static char *DisBBb(struct DisBuilder b, char *p) {
p = DisRegister(p, kSegOverride[b.xedd->op.seg_ovd]);
}
*p++ = '(';
p = DisRegister(p, Asz(b.xedd) ? "ebx" : "rbx");
p = DisRegister(p, Asz(b.xedd->op.rde) ? "ebx" : "rbx");
*p++ = ')';
*p = '\0';
return p;
@ -350,33 +356,33 @@ static char *DisXmm(struct DisBuilder b, char *p, const char *s, int reg) {
if (g_dis_high) p = DisHigh(p, g_dis_high->reg);
*p++ = '%';
p = stpcpy(p, s);
p += uint64toarray_radix10(Rexr(b.xedd) << 3 | reg, p);
p += uint64toarray_radix10(Rexr(b.xedd->op.rde) << 3 | reg, p);
if (g_dis_high) p = DisHigh(p, -1);
return p;
}
static char *DisNq(struct DisBuilder b, char *p) {
return DisXmm(b, p, "mm", ModrmRm(b.xedd));
return DisXmm(b, p, "mm", ModrmRm(b.xedd->op.rde));
}
static char *DisUq(struct DisBuilder b, char *p) {
return DisXmm(b, p, "mm", ModrmRm(b.xedd));
return DisXmm(b, p, "mm", ModrmRm(b.xedd->op.rde));
}
static char *DisPq(struct DisBuilder b, char *p) {
return DisXmm(b, p, "mm", ModrmReg(b.xedd));
return DisXmm(b, p, "mm", ModrmReg(b.xedd->op.rde));
}
static char *DisUdq(struct DisBuilder b, char *p) {
return DisXmm(b, p, "xmm", ModrmRm(b.xedd));
return DisXmm(b, p, "xmm", ModrmRm(b.xedd->op.rde));
}
static char *DisVdq(struct DisBuilder b, char *p) {
return DisXmm(b, p, "xmm", ModrmReg(b.xedd));
return DisXmm(b, p, "xmm", ModrmReg(b.xedd->op.rde));
}
static char *DisQq(struct DisBuilder b, char *p) {
if (IsModrmRegister(b.xedd)) {
if (IsModrmRegister(b.xedd->op.rde)) {
return DisNq(b, p);
} else {
return DisM(b, p);
@ -385,9 +391,9 @@ static char *DisQq(struct DisBuilder b, char *p) {
static char *DisEst(struct DisBuilder b, char *p) {
p = DisRegister(p, "st");
if (ModrmRm(b.xedd) != 0) {
if (ModrmRm(b.xedd->op.rde) != 0) {
*p++ = '(';
*p++ = '0' + ModrmRm(b.xedd);
*p++ = '0' + ModrmRm(b.xedd->op.rde);
*p++ = ')';
*p = '\0';
}
@ -395,7 +401,7 @@ static char *DisEst(struct DisBuilder b, char *p) {
}
static char *DisEst1(struct DisBuilder b, char *p) {
if (ModrmRm(b.xedd) != 1) {
if (ModrmRm(b.xedd->op.rde) != 1) {
p = DisEst(b, p);
} else {
*p = '\0';
@ -404,7 +410,7 @@ static char *DisEst1(struct DisBuilder b, char *p) {
}
static char *DisEssr(struct DisBuilder b, char *p) {
if (IsModrmRegister(b.xedd)) {
if (IsModrmRegister(b.xedd->op.rde)) {
return DisEst(b, p);
} else {
return DisM(b, p);
@ -412,7 +418,7 @@ static char *DisEssr(struct DisBuilder b, char *p) {
}
static char *DisWps(struct DisBuilder b, char *p) {
if (IsModrmRegister(b.xedd)) {
if (IsModrmRegister(b.xedd->op.rde)) {
return DisUdq(b, p);
} else {
return DisM(b, p);

View file

@ -20,7 +20,6 @@
#include "libc/log/check.h"
#include "libc/nexgen32e/tinystrcmp.h"
#include "libc/str/str.h"
#include "tool/build/lib/case.h"
#include "tool/build/lib/dis.h"
#include "tool/build/lib/modrm.h"
@ -29,15 +28,26 @@ static const char kAluOp[8][4] = {"add", "or", "adc", "sbb",
static const char kBitOp[8][4] = {"rol", "ror", "rcl", "rcr",
"shl", "shr", "sal", "sar"};
static bool IsProbablyByteOp(struct XedDecodedInst *x) {
return !(x->op.opcode & 1);
}
static int IsRepOpcode(struct DisBuilder b) {
switch (b.xedd->op.opcode & ~1u) {
CASE(0x6C /*INS */, return 1);
CASE(0x6E /*OUTS*/, return 1);
CASE(0xA4 /*MOVS*/, return 1);
CASE(0xAA /*STOS*/, return 1);
CASE(0xAC /*LODS*/, return 1);
CASE(0xA6 /*CMPS*/, return 2);
CASE(0xAE /*SCAS*/, return 2);
case 0x6C: /* INS */
return 1;
case 0x6E: /* OUTS */
return 1;
case 0xA4: /* MOVS */
return 1;
case 0xAA: /* STOS */
return 1;
case 0xAC: /* LODS */
return 1;
case 0xA6: /* CMPS */
return 2;
case 0xAE: /* SCAS */
return 2;
default:
return 0;
}
@ -45,7 +55,7 @@ static int IsRepOpcode(struct DisBuilder b) {
static char *DisRepPrefix(struct DisBuilder b, char *p) {
const char *s;
if (Rep(b.xedd) && b.xedd->op.map == XED_ILD_MAP0) {
if (Rep(b.xedd->op.rde) && b.xedd->op.map == XED_ILD_MAP0) {
switch (IsRepOpcode(b)) {
case 0:
break;
@ -53,7 +63,7 @@ static char *DisRepPrefix(struct DisBuilder b, char *p) {
p = stpcpy(p, "rep ");
break;
case 2:
p = stpcpy(p, Rep(b.xedd) == 2 ? "repnz " : "repz ");
p = stpcpy(p, Rep(b.xedd->op.rde) == 2 ? "repnz " : "repz ");
break;
default:
break;
@ -81,30 +91,30 @@ static char *DisName(struct DisBuilder b, char *bp, const char *name,
if (b.xedd->op.lock) p = stpcpy(p, "lock ");
p = DisRepPrefix(b, p);
if (tinystrcmp(name, "BIT") == 0) {
p = stpcpy(p, kBitOp[ModrmReg(b.xedd)]);
p = stpcpy(p, kBitOp[ModrmReg(b.xedd->op.rde)]);
} else if (tinystrcmp(name, "CALL") == 0) {
p = stpcpy(p, "call");
} else if (tinystrcmp(name, "JMP") == 0) {
p = stpcpy(p, "jmp");
} else if (tinystrcmp(name, "jcxz") == 0) {
p = stpcpy(p, Asz(b.xedd) ? "jecxz" : "jrcxz");
p = stpcpy(p, Asz(b.xedd->op.rde) ? "jecxz" : "jrcxz");
p = DisBranchTaken(b, p);
} else if (tinystrcmp(name, "loop") == 0) {
p = stpcpy(p, Asz(b.xedd) ? "loopl" : "loop");
p = stpcpy(p, Asz(b.xedd->op.rde) ? "loopl" : "loop");
p = DisBranchTaken(b, p);
} else if (tinystrcmp(name, "loope") == 0) {
p = stpcpy(p, Asz(b.xedd) ? "loopel" : "loope");
p = stpcpy(p, Asz(b.xedd->op.rde) ? "loopel" : "loope");
p = DisBranchTaken(b, p);
} else if (tinystrcmp(name, "loopne") == 0) {
p = stpcpy(p, Asz(b.xedd) ? "loopnel" : "loopne");
p = stpcpy(p, Asz(b.xedd->op.rde) ? "loopnel" : "loopne");
p = DisBranchTaken(b, p);
} else if (tinystrcmp(name, "cwtl") == 0) {
if (Osz(b.xedd)) name = "cbtw";
if (Rexw(b.xedd)) name = "cltq";
if (Osz(b.xedd->op.rde)) name = "cbtw";
if (Rexw(b.xedd->op.rde)) name = "cltq";
p = stpcpy(p, name);
} else if (tinystrcmp(name, "cltd") == 0) {
if (Osz(b.xedd)) name = "cwtd";
if (Rexw(b.xedd)) name = "cqto";
if (Osz(b.xedd->op.rde)) name = "cwtd";
if (Rexw(b.xedd->op.rde)) name = "cqto";
p = stpcpy(p, name);
} else {
notbyte = false;
@ -115,7 +125,7 @@ static char *DisName(struct DisBuilder b, char *bp, const char *name,
*p++ = *np;
}
if (tinystrcmp(name, "ALU") == 0) {
p = stpcpy(p, kAluOp[ModrmReg(b.xedd)]);
p = stpcpy(p, kAluOp[ModrmReg(b.xedd->op.rde)]);
} else if (tinystrcmp(np, "WLQ") == 0) {
notbyte = true;
wantsuffix = true;
@ -130,21 +140,21 @@ static char *DisName(struct DisBuilder b, char *bp, const char *name,
notbyte = true;
wantsuffixsd = true;
} else if (tinystrcmp(np, "ABS") == 0) {
if (Rexw(b.xedd)) p = stpcpy(p, "abs");
if (Rexw(b.xedd->op.rde)) p = stpcpy(p, "abs");
} else if (tinystrcmp(np, "BT") == 0) {
p = DisBranchTaken(b, p);
}
if (wantsuffixsd) {
if (Osz(b.xedd)) {
if (Osz(b.xedd->op.rde)) {
*p++ = 'd';
} else {
*p++ = 's';
}
} else if (wantsuffix || (ambiguous && !startswith(name, "f") &&
!startswith(name, "set"))) {
if (Osz(b.xedd)) {
if (Osz(b.xedd->op.rde)) {
*p++ = 'w';
} else if (Rexw(b.xedd)) {
} else if (Rexw(b.xedd->op.rde)) {
*p++ = 'q';
} else if (ambiguous && !notbyte && IsProbablyByteOp(b.xedd)) {
*p++ = 'b';
@ -169,11 +179,12 @@ char *DisInst(struct DisBuilder b, char *p, const char *spec) {
char args[4][64];
char *s, *name, *state;
bool hasarg, hasmodrm, hasregister, hasmemory;
CHECK_EQ(0, (int)b.xedd->op.error);
DCHECK_LT(strlen(spec), 128);
hasarg = false;
hasmodrm = b.xedd->op.has_modrm;
hasmemory = hasmodrm && !IsModrmRegister(b.xedd);
hasregister = hasmodrm && IsModrmRegister(b.xedd);
hasmemory = hasmodrm && !IsModrmRegister(b.xedd->op.rde);
hasregister = hasmodrm && IsModrmRegister(b.xedd->op.rde);
name = strtok_r(strcpy(sbuf, spec), " ", &state);
for (n = 0; (s = strtok_r(NULL, " ", &state)); ++n) {
hasarg = true;

View file

@ -38,18 +38,18 @@ static const char kFpuName[][8][8] = {
char *DisOpFpu0(struct XedDecodedInst *x, int group) {
const char *s;
s = kFpuName[group][ModrmRm(x)];
s = kFpuName[group][ModrmRm(x->op.rde)];
return *s ? s : UNKNOWN;
}
char *DisOpFpu1(struct XedDecodedInst *x, char *p, const char *extra) {
stpcpy(stpcpy(p, kFpuName[0][ModrmReg(x)]), extra);
stpcpy(stpcpy(p, kFpuName[0][ModrmReg(x->op.rde)]), extra);
return p;
}
char *DisOp66(struct XedDecodedInst *x, char *p, const char *s, const char *a,
const char *b) {
stpcpy(stpcpy(p, s), !Osz(x) ? a : b);
stpcpy(stpcpy(p, s), !Osz(x->op.rde) ? a : b);
return p;
}
@ -76,11 +76,11 @@ char *DisOpNqIbUdqIb(struct XedDecodedInst *x, char *p, const char *s) {
char *DisOpVpsWpsVssWssVpdWpdVsdWsd(struct XedDecodedInst *x, char *p,
const char *s) {
char *q = stpcpy(p, s);
if (x->op.ild_f3) {
if (Rep(x->op.rde) == 3) {
stpcpy(q, "ss %Vss Wss");
} else if (x->op.ild_f2) {
} else if (Rep(x->op.rde) == 2) {
stpcpy(q, "sd %Vsd Wsd");
} else if (Osz(x)) {
} else if (Osz(x->op.rde)) {
stpcpy(q, "pd %Vpd Wpd");
} else {
stpcpy(q, "ps %Vps Wps");
@ -265,53 +265,53 @@ const char *DisSpecMap0(struct XedDecodedInst *x, char *p) {
RCASE(0xFC, "cld");
RCASE(0xFD, "std");
case 0x8F:
switch (ModrmReg(x)) {
switch (ModrmReg(x->op.rde)) {
RCASE(0, "popWQ Evq");
default:
break;
}
break;
case 0xD9:
switch (ModrmReg(x)) {
switch (ModrmReg(x->op.rde)) {
RCASE(1, "fxch EST1");
RCASE(3, "fstps Msr %st");
case 0:
if (IsModrmRegister(x)) {
if (IsModrmRegister(x->op.rde)) {
return "fld EST";
} else {
return "flds Msr";
}
break;
case 2:
if (IsModrmRegister(x)) {
if (IsModrmRegister(x->op.rde)) {
return "fnop";
} else {
return "fsts Msr %st";
}
break;
case 4:
if (IsModrmRegister(x)) {
if (IsModrmRegister(x->op.rde)) {
return DisOpFpu0(x, 1);
} else {
return "fldenv Me";
}
break;
case 5:
if (IsModrmRegister(x)) {
if (IsModrmRegister(x->op.rde)) {
return DisOpFpu0(x, 2);
} else {
return "fldcw Mw";
}
break;
case 6:
if (IsModrmRegister(x)) {
if (IsModrmRegister(x->op.rde)) {
return DisOpFpu0(x, 3);
} else {
return "fnstenv M";
}
break;
case 7:
if (IsModrmRegister(x)) {
if (IsModrmRegister(x->op.rde)) {
return DisOpFpu0(x, 4);
} else {
return "fnstcw Mw";
@ -320,58 +320,58 @@ const char *DisSpecMap0(struct XedDecodedInst *x, char *p) {
}
break;
case 0xDA:
switch (ModrmReg(x)) {
switch (ModrmReg(x->op.rde)) {
case 0:
if (!IsModrmRegister(x)) {
if (!IsModrmRegister(x->op.rde)) {
return "fiaddl Mdi";
} else {
return "fcmovb %st EST";
}
break;
case 1:
if (!IsModrmRegister(x)) {
if (!IsModrmRegister(x->op.rde)) {
return "fimull Mdi";
} else {
return "fcmove %st EST";
}
break;
case 2:
if (!IsModrmRegister(x)) {
if (!IsModrmRegister(x->op.rde)) {
return "ficoml Mdi";
} else {
return "fcmovbe %st EST";
}
break;
case 3:
if (!IsModrmRegister(x)) {
if (!IsModrmRegister(x->op.rde)) {
return "ficompl Mdi";
} else {
return "fcmovu %st EST";
}
break;
case 4:
if (!IsModrmRegister(x)) {
if (!IsModrmRegister(x->op.rde)) {
return "fisubl Mdi";
} else {
return "fisubr Mdi";
}
break;
case 5:
if (!IsModrmRegister(x)) {
if (!IsModrmRegister(x->op.rde)) {
return "fisubrl Mdi";
} else {
return "fucompp";
}
break;
case 6:
if (!IsModrmRegister(x)) {
if (!IsModrmRegister(x->op.rde)) {
return "fidivl Mdi";
} else {
return UNKNOWN;
}
break;
case 7:
if (!IsModrmRegister(x)) {
if (!IsModrmRegister(x->op.rde)) {
return "fidivrl Mdi";
} else {
return UNKNOWN;
@ -380,30 +380,30 @@ const char *DisSpecMap0(struct XedDecodedInst *x, char *p) {
}
break;
case 0xDB:
switch (ModrmReg(x)) {
switch (ModrmReg(x->op.rde)) {
case 0:
if (!IsModrmRegister(x)) {
if (!IsModrmRegister(x->op.rde)) {
return "fildl Mdi";
} else {
return "fcmovnb %st EST";
}
break;
case 1:
if (!IsModrmRegister(x)) {
if (!IsModrmRegister(x->op.rde)) {
return "fisttpl Mdi";
} else {
return "fcmovne %st EST";
}
break;
case 2:
if (!IsModrmRegister(x)) {
if (!IsModrmRegister(x->op.rde)) {
return "fistl Mdi";
} else {
return "fcmovnbe %st EST";
}
break;
case 3:
if (!IsModrmRegister(x)) {
if (!IsModrmRegister(x->op.rde)) {
return "fistpl Mdi";
} else {
return "fcmovnu %st EST";
@ -412,21 +412,21 @@ const char *DisSpecMap0(struct XedDecodedInst *x, char *p) {
case 4:
return DisOpFpu0(x, 5);
case 5:
if (!IsModrmRegister(x)) {
if (!IsModrmRegister(x->op.rde)) {
return "fldt Mer";
} else {
return "fucomi %st EST";
}
break;
case 6:
if (IsModrmRegister(x)) {
if (IsModrmRegister(x->op.rde)) {
return "fcomi %st EST";
} else {
return UNKNOWN;
}
break;
case 7:
if (!IsModrmRegister(x)) {
if (!IsModrmRegister(x->op.rde)) {
return "fstpt Mer";
} else {
return UNKNOWN;
@ -435,12 +435,12 @@ const char *DisSpecMap0(struct XedDecodedInst *x, char *p) {
}
break;
case 0xD8:
return DisOpFpu1(x, p, !IsModrmRegister(x) ? "s Msr" : " EST1");
return DisOpFpu1(x, p, !IsModrmRegister(x->op.rde) ? "s Msr" : " EST1");
case 0xDC:
if (!IsModrmRegister(x)) {
if (!IsModrmRegister(x->op.rde)) {
return DisOpFpu1(x, p, "l Mdr");
} else {
switch (ModrmReg(x)) {
switch (ModrmReg(x->op.rde)) {
RCASE(0, "fadd EST %st");
RCASE(1, "fmul EST %st");
RCASE(2, "fcom %st EST");
@ -453,8 +453,8 @@ const char *DisSpecMap0(struct XedDecodedInst *x, char *p) {
}
break;
case 0xDD:
if (!IsModrmRegister(x)) {
switch (ModrmReg(x)) {
if (!IsModrmRegister(x->op.rde)) {
switch (ModrmReg(x->op.rde)) {
RCASE(0, "fldl Mdr");
RCASE(1, "fisttpll Mqi");
RCASE(2, "fstl Mdr");
@ -464,7 +464,7 @@ const char *DisSpecMap0(struct XedDecodedInst *x, char *p) {
RCASE(7, "fnstsw Mst");
}
} else {
switch (ModrmReg(x)) {
switch (ModrmReg(x->op.rde)) {
RCASE(0, "ffree EST");
RCASE(1, "fxch EST");
RCASE(2, "fst EST");
@ -475,8 +475,8 @@ const char *DisSpecMap0(struct XedDecodedInst *x, char *p) {
}
break;
case 0xDE:
if (!IsModrmRegister(x)) {
switch (ModrmReg(x)) {
if (!IsModrmRegister(x->op.rde)) {
switch (ModrmReg(x->op.rde)) {
RCASE(0, "fiadds Mwi");
RCASE(1, "fimuls Mwi");
RCASE(2, "ficoms Mwi");
@ -487,7 +487,7 @@ const char *DisSpecMap0(struct XedDecodedInst *x, char *p) {
RCASE(7, "fidivrs Mwi");
}
} else {
switch (ModrmReg(x)) {
switch (ModrmReg(x->op.rde)) {
RCASE(0, "faddp EST1");
RCASE(1, "fmulp EST1");
RCASE(2, "fcomp EST1");
@ -500,8 +500,8 @@ const char *DisSpecMap0(struct XedDecodedInst *x, char *p) {
}
break;
case 0xDF:
if (!IsModrmRegister(x)) {
switch (ModrmReg(x)) {
if (!IsModrmRegister(x->op.rde)) {
switch (ModrmReg(x->op.rde)) {
RCASE(0, "filds Mwi");
RCASE(1, "fisttps Mwi");
RCASE(2, "fists Mwi");
@ -512,7 +512,7 @@ const char *DisSpecMap0(struct XedDecodedInst *x, char *p) {
RCASE(7, "fistpll Mqi");
}
} else {
switch (ModrmReg(x)) {
switch (ModrmReg(x->op.rde)) {
RCASE(0, "ffreep EST");
RCASE(1, "fxch");
RCASE(2, "fstp EST");
@ -524,7 +524,7 @@ const char *DisSpecMap0(struct XedDecodedInst *x, char *p) {
}
break;
case 0xF6:
switch (ModrmReg(x)) {
switch (ModrmReg(x->op.rde)) {
RCASE(0, "test Eb Ib");
RCASE(1, "test Eb Ib");
RCASE(2, "not Eb");
@ -536,7 +536,7 @@ const char *DisSpecMap0(struct XedDecodedInst *x, char *p) {
}
break;
case 0xF7:
switch (ModrmReg(x)) {
switch (ModrmReg(x->op.rde)) {
RCASE(0, "test Evqp Ivds");
RCASE(1, "test Evqp Ivds");
RCASE(2, "not Evqp");
@ -548,13 +548,13 @@ const char *DisSpecMap0(struct XedDecodedInst *x, char *p) {
}
break;
case 0xFE:
switch (ModrmReg(x)) {
switch (ModrmReg(x->op.rde)) {
RCASE(0, "inc Eb");
RCASE(1, "dec Eb");
}
break;
case 0xFF:
switch (ModrmReg(x)) {
switch (ModrmReg(x->op.rde)) {
RCASE(0, "inc Evqp");
RCASE(1, "dec Evqp");
RCASE(2, "CALL Eq");
@ -580,8 +580,8 @@ const char *DisSpecMap1(struct XedDecodedInst *x, char *p) {
RCASE(0x28, "movapSD %Vps Wps");
RCASE(0x29, "movapSD Wps %Vps");
RCASE(0x2B, "movntpSD Mps %Vps");
RCASE(0x2E, Osz(x) ? "ucomisd %Vsd Wsd" : "ucomiss %Vss Wss");
RCASE(0x2F, Osz(x) ? "comisd %Vsd Wsd" : "comiss %Vss Wss");
RCASE(0x2E, Osz(x->op.rde) ? "ucomisd %Vsd Wsd" : "ucomiss %Vss Wss");
RCASE(0x2F, Osz(x->op.rde) ? "comisd %Vsd Wsd" : "comiss %Vss Wss");
RCASE(0x31, "rdtsc");
RCASE(0x40, "cmovo %Gvqp Evqp");
RCASE(0x41, "cmovno %Gvqp Evqp");
@ -693,7 +693,7 @@ const char *DisSpecMap1(struct XedDecodedInst *x, char *p) {
RCASE(0xD3, DisOpPqQqVdqWdq(x, p, "psrlq"));
RCASE(0xD4, DisOpPqQqVdqWdq(x, p, "paddq"));
RCASE(0xD5, DisOpPqQqVdqWdq(x, p, "pmullw"));
RCASE(0xD7, Osz(x) ? "pmovmskb %Gdqp %Udq" : "pmovmskb %Gdqp %Nq");
RCASE(0xD7, Osz(x->op.rde) ? "pmovmskb %Gdqp %Udq" : "pmovmskb %Gdqp %Nq");
RCASE(0xD8, DisOpPqQqVdqWdq(x, p, "psubusb"));
RCASE(0xD9, DisOpPqQqVdqWdq(x, p, "psubusw"));
RCASE(0xDA, DisOpPqQqVdqWdq(x, p, "pminub"));
@ -708,7 +708,7 @@ const char *DisSpecMap1(struct XedDecodedInst *x, char *p) {
RCASE(0xE3, DisOpPqQqVdqWdq(x, p, "pavgw"));
RCASE(0xE4, DisOpPqQqVdqWdq(x, p, "pmulhuw"));
RCASE(0xE5, DisOpPqQqVdqWdq(x, p, "pmulhw"));
RCASE(0xE7, Osz(x) ? "movntdq Mdq %Vdq" : "movntq Mq %Pq");
RCASE(0xE7, Osz(x->op.rde) ? "movntdq Mdq %Vdq" : "movntq Mq %Pq");
RCASE(0xE8, DisOpPqQqVdqWdq(x, p, "psubsb"));
RCASE(0xE9, DisOpPqQqVdqWdq(x, p, "psubsw"));
RCASE(0xEA, DisOpPqQqVdqWdq(x, p, "pminsw"));
@ -740,7 +740,7 @@ const char *DisSpecMap1(struct XedDecodedInst *x, char *p) {
}
break;
case 0x70:
switch (Rep(x) | Osz(x)) {
switch (Rep(x->op.rde) | Osz(x->op.rde)) {
RCASE(0, "pshufw %Pq Qq Ib");
RCASE(1, "pshufd %Vdq Wdq Ib");
RCASE(2, "pshuflw %Vdq Wdq Ib");
@ -748,21 +748,21 @@ const char *DisSpecMap1(struct XedDecodedInst *x, char *p) {
}
break;
case 0x71:
switch (ModrmReg(x)) {
switch (ModrmReg(x->op.rde)) {
RCASE(2, DisOpNqIbUdqIb(x, p, "psrlw"));
RCASE(4, DisOpNqIbUdqIb(x, p, "psraw"));
RCASE(6, DisOpNqIbUdqIb(x, p, "psllw"));
}
break;
case 0x72:
switch (ModrmReg(x)) {
switch (ModrmReg(x->op.rde)) {
RCASE(2, DisOpNqIbUdqIb(x, p, "psrld"));
RCASE(4, DisOpNqIbUdqIb(x, p, "psrad"));
RCASE(6, DisOpNqIbUdqIb(x, p, "pslld"));
}
break;
case 0x73:
switch (ModrmReg(x)) {
switch (ModrmReg(x->op.rde)) {
RCASE(2, DisOpNqIbUdqIb(x, p, "psrlq"));
RCASE(3, DisOpNqIbUdqIb(x, p, "psrldq"));
RCASE(6, DisOpNqIbUdqIb(x, p, "psllq"));
@ -770,7 +770,7 @@ const char *DisSpecMap1(struct XedDecodedInst *x, char *p) {
}
break;
case 0xAE:
switch (ModrmReg(x)) {
switch (ModrmReg(x->op.rde)) {
RCASE(0, "fxsave Mstx %st %st(1)");
RCASE(1, "fxrstor Mstx %st %st(1)");
RCASE(2, "ldmxcsr Md");
@ -787,7 +787,7 @@ const char *DisSpecMap1(struct XedDecodedInst *x, char *p) {
}
break;
case 0xBA:
switch (ModrmReg(x)) {
switch (ModrmReg(x->op.rde)) {
RCASE(4, "btWLQ Evqp Ib");
RCASE(5, "btsWLQ Evqp Ib");
RCASE(6, "btrWLQ Evqp Ib");
@ -795,36 +795,36 @@ const char *DisSpecMap1(struct XedDecodedInst *x, char *p) {
}
break;
case 0x10:
if (x->op.ild_f3) {
if (Rep(x->op.rde) == 3) {
return "movss %Vss Wss";
} else if (x->op.ild_f2) {
} else if (Rep(x->op.rde) == 2) {
return "movsd %Vsd Wsd";
} else if (Osz(x)) {
} else if (Osz(x->op.rde)) {
return "movupd %Vpd Wpd";
} else {
return "movups %Vps Wps";
}
break;
case 0x11:
if (x->op.ild_f3) {
if (Rep(x->op.rde) == 3) {
return "movss Wss %Vss";
} else if (x->op.ild_f2) {
} else if (Rep(x->op.rde) == 2) {
return "movsd Wsd %Vsd";
} else if (Osz(x)) {
} else if (Osz(x->op.rde)) {
return "movupd Wpd %Vpd";
} else {
return "movups Wps %Vps";
}
break;
case 0xC4:
if (!Osz(x)) {
if (IsModrmRegister(x)) {
if (!Osz(x->op.rde)) {
if (IsModrmRegister(x->op.rde)) {
return "pinsrw %Pq %Rdqp Ib";
} else {
return "pinsrw %Pq Mw Ib";
}
} else {
if (IsModrmRegister(x)) {
if (IsModrmRegister(x->op.rde)) {
return "pinsrw %Vdq %Rdqp Ib";
} else {
return "pinsrw %Vdq Mw Ib";
@ -832,39 +832,39 @@ const char *DisSpecMap1(struct XedDecodedInst *x, char *p) {
}
break;
case 0xC5:
if (!Osz(x)) {
if (!Osz(x->op.rde)) {
return "pextrw %Gdqp %Nq Ib";
} else {
return "pextrw %Gdqp %Udq Ib";
}
break;
case 0xC6:
if (!Osz(x)) {
if (!Osz(x->op.rde)) {
return "shufps %Vps Wps Ib";
} else {
return "shufpd %Vpd Wpd Ib";
}
break;
case 0xC7:
if (Rexw(x)) {
if (Rexw(x->op.rde)) {
return "cmpxchg16b Mdq";
} else {
return "cmpxchg8b Mq";
}
break;
case 0xD6:
if (Osz(x)) {
if (Osz(x->op.rde)) {
return "movq Wq %Vq";
} else if (x->op.ild_f3) {
} else if (Rep(x->op.rde) == 3) {
return "movq2dq %Vdq %Nq";
} else if (x->op.ild_f2) {
} else if (Rep(x->op.rde) == 2) {
return "movq2dq %Pq %Uq";
}
break;
case 0x12:
switch (Rep(x) | Osz(x)) {
switch (Rep(x->op.rde) | Osz(x->op.rde)) {
case 0:
if (IsModrmRegister(x)) {
if (IsModrmRegister(x->op.rde)) {
return "movhlps %Vq %Uq";
} else {
return "movlps %Vq Mq";
@ -881,16 +881,16 @@ const char *DisSpecMap1(struct XedDecodedInst *x, char *p) {
}
break;
case 0x13:
if (Osz(x)) {
if (Osz(x->op.rde)) {
return "movlpd Mq %Vq";
} else {
return "movlps Mq %Vq";
}
break;
case 0x16:
switch (Rep(x) | Osz(x)) {
switch (Rep(x->op.rde) | Osz(x->op.rde)) {
case 0:
if (IsModrmRegister(x)) {
if (IsModrmRegister(x->op.rde)) {
return "movlhps %Vq %Uq";
} else {
return "movhps %Vq Mq";
@ -905,85 +905,85 @@ const char *DisSpecMap1(struct XedDecodedInst *x, char *p) {
}
break;
case 0x17:
if (Osz(x)) {
if (Osz(x->op.rde)) {
return "movhpd Mq %Vq";
} else {
return "movhps Mq %Vq";
}
break;
case 0x2A:
if (x->op.ild_f3) {
if (Rep(x->op.rde) == 3) {
return "cvtsi2ss %Vss Edqp";
} else if (x->op.ild_f2) {
} else if (Rep(x->op.rde) == 2) {
return "cvtsi2sd %Vsd Edqp";
} else if (Osz(x)) {
} else if (Osz(x->op.rde)) {
return "cvtpi2pd %Vpd Qpi";
} else {
return "cvtpi2ps %Vps Qpi";
}
break;
case 0x2C:
if (x->op.ild_f3) {
if (Rep(x->op.rde) == 3) {
return "cvttss2si %Gdqp Wss";
} else if (x->op.ild_f2) {
} else if (Rep(x->op.rde) == 2) {
return "cvttsd2si %Gdqp Wsd";
} else if (Osz(x)) {
} else if (Osz(x->op.rde)) {
return "cvttpd2pi %Ppi Wpd";
} else {
return "cvttps2pi %Ppi Wpsq";
}
break;
case 0x2D:
if (x->op.ild_f3) {
if (Rep(x->op.rde) == 3) {
return "cvtss2si %Gdqp Wss";
} else if (x->op.ild_f2) {
} else if (Rep(x->op.rde) == 2) {
return "cvtsd2si %Gdqp Wsd";
} else if (Osz(x)) {
} else if (Osz(x->op.rde)) {
return "cvtpd2pi %Ppi Wpd";
} else {
return "cvtps2pi %Ppi Wpsq";
}
break;
case 0x5a:
if (x->op.ild_f3) {
if (Rep(x->op.rde) == 3) {
return "cvtss2sd %Vsd Wss";
} else if (x->op.ild_f2) {
} else if (Rep(x->op.rde) == 2) {
return "cvtsd2ss %Vss Wsd";
} else if (Osz(x)) {
} else if (Osz(x->op.rde)) {
return "cvtpd2ps %Vps Wpd";
} else {
return "cvtps2pd %Vpd Wps";
}
break;
case 0x5b:
if (x->op.ild_f3) {
if (Rep(x->op.rde) == 3) {
return "cvttps2dq %Vdq Wps";
} else if (Osz(x)) {
} else if (Osz(x->op.rde)) {
return "cvtps2dq %Vdq Wps";
} else {
return "cvtdq2ps %Vps Wdq";
}
break;
case 0x51:
if (x->op.ild_f3) {
if (Rep(x->op.rde) == 3) {
return "sqrtss %Vss Wss";
} else if (x->op.ild_f2) {
} else if (Rep(x->op.rde) == 2) {
return "sqrtsd %Vsd Wsd";
} else if (Osz(x)) {
} else if (Osz(x->op.rde)) {
return "sqrtpd %Vpd Wpd";
} else {
return "sqrtps %Vps Wps";
}
break;
case 0x6E:
if (Osz(x)) {
if (Rexw(x)) {
if (Osz(x->op.rde)) {
if (Rexw(x->op.rde)) {
return "movq %Vdq Eqp";
} else {
return "movd %Vdq Ed";
}
} else {
if (Rexw(x)) {
if (Rexw(x->op.rde)) {
return "movq %Pq Eqp";
} else {
return "movd %Pq Ed";
@ -991,25 +991,25 @@ const char *DisSpecMap1(struct XedDecodedInst *x, char *p) {
}
break;
case 0x6F:
if (x->op.ild_f3) {
if (Rep(x->op.rde) == 3) {
return "movdqu %Vdq Wdq";
} else if (Osz(x)) {
} else if (Osz(x->op.rde)) {
return "movdqa %Vdq Wdq";
} else {
return "movq %Pq Qq";
}
break;
case 0x7E:
if (x->op.ild_f3) {
if (Rep(x->op.rde) == 3) {
return "movq %Vq Wq";
} else if (Osz(x)) {
if (Rexw(x)) {
} else if (Osz(x->op.rde)) {
if (Rexw(x->op.rde)) {
return "movq Eqp %Vdq";
} else {
return "movd Ed %Vdq";
}
} else {
if (Rexw(x)) {
if (Rexw(x->op.rde)) {
return "movq Eqp %Pq";
} else {
return "movd Ed %Pq";
@ -1017,20 +1017,20 @@ const char *DisSpecMap1(struct XedDecodedInst *x, char *p) {
}
break;
case 0x7F:
if (x->op.ild_f3) {
if (Rep(x->op.rde) == 3) {
return "movdqu Wdq %Vdq";
} else if (Osz(x)) {
} else if (Osz(x->op.rde)) {
return "movdqa Wdq %Vdq";
} else {
return "movq Qq %Pq";
}
break;
case 0xE6:
if (x->op.ild_f2) {
if (Rep(x->op.rde) == 2) {
return "cvtpd2dq %Vdq Wpd";
} else if (Osz(x)) {
} else if (Osz(x->op.rde)) {
return "cvttpd2dq %Vdq Wpd";
} else if (x->op.ild_f3) {
} else if (Rep(x->op.rde) == 3) {
return "cvtdq2pd %Vpd Wdq";
}
break;

View file

@ -25,12 +25,12 @@
#include "tool/build/lib/modrm.h"
#include "tool/build/lib/throw.h"
void OpDivAlAhAxEbSigned(struct Machine *m) {
void OpDivAlAhAxEbSigned(struct Machine *m, uint32_t rde) {
int8_t y, rem;
int16_t x, quo;
x = Read16(m->ax);
y = Read8(GetModrmRegisterBytePointerRead(m));
if (!y || (x == INT16_MIN && y < 0)) ThrowDivideError(m);
y = Read8(GetModrmRegisterBytePointerRead(m, rde));
if (!y || (x == INT16_MIN && y == -1)) ThrowDivideError(m);
quo = x / y;
rem = x % y;
if (!(INT8_MIN <= quo && quo <= INT8_MAX)) ThrowDivideError(m);
@ -38,11 +38,11 @@ void OpDivAlAhAxEbSigned(struct Machine *m) {
m->ax[1] = rem & 0xff;
}
void OpDivAlAhAxEbUnsigned(struct Machine *m) {
void OpDivAlAhAxEbUnsigned(struct Machine *m, uint32_t rde) {
uint8_t y, rem;
uint16_t x, quo;
x = Read16(m->ax);
y = Read8(GetModrmRegisterBytePointerRead(m));
y = Read8(GetModrmRegisterBytePointerRead(m, rde));
if (!y) ThrowDivideError(m);
quo = x / y;
rem = x % y;
@ -51,12 +51,13 @@ void OpDivAlAhAxEbUnsigned(struct Machine *m) {
m->ax[1] = rem & 0xff;
}
static void OpDivRdxRaxEvqpSigned64(struct Machine *m, uint8_t *p) {
static void OpDivRdxRaxEvqpSigned64(struct Machine *m, uint32_t rde,
uint8_t *p) {
int64_t y, rem;
int128_t x, quo;
x = (uint128_t)Read64(m->dx) << 64 | Read64(m->ax);
y = Read64(p);
if (!y || (x == INT128_MIN && y < 0)) ThrowDivideError(m);
if (!y || (x == INT128_MIN && y == -1)) ThrowDivideError(m);
quo = x / y;
rem = x % y;
if (!(INT64_MIN <= quo && quo <= INT64_MAX)) ThrowDivideError(m);
@ -64,12 +65,13 @@ static void OpDivRdxRaxEvqpSigned64(struct Machine *m, uint8_t *p) {
Write64(m->dx, rem);
}
static void OpDivRdxRaxEvqpSigned32(struct Machine *m, uint8_t *p) {
static void OpDivRdxRaxEvqpSigned32(struct Machine *m, uint32_t rde,
uint8_t *p) {
int32_t y, rem;
int64_t x, quo;
x = (uint64_t)Read32(m->dx) << 32 | Read32(m->ax);
y = Read32(p);
if (!y || (x == INT64_MIN && y < 0)) ThrowDivideError(m);
if (!y || (x == INT64_MIN && y == -1)) ThrowDivideError(m);
quo = x / y;
rem = x % y;
if (!(INT32_MIN <= quo && quo <= INT32_MAX)) ThrowDivideError(m);
@ -77,12 +79,13 @@ static void OpDivRdxRaxEvqpSigned32(struct Machine *m, uint8_t *p) {
Write64(m->dx, rem & 0xffffffff);
}
static void OpDivRdxRaxEvqpSigned16(struct Machine *m, uint8_t *p) {
static void OpDivRdxRaxEvqpSigned16(struct Machine *m, uint32_t rde,
uint8_t *p) {
int16_t y, rem;
int32_t x, quo;
x = (uint32_t)Read16(m->dx) << 16 | Read16(m->ax);
y = Read16(p);
if (!y || (x == INT32_MIN && y < 0)) ThrowDivideError(m);
if (!y || (x == INT32_MIN && y == -1)) ThrowDivideError(m);
quo = x / y;
rem = x % y;
if (!(INT16_MIN <= quo && quo <= INT16_MAX)) ThrowDivideError(m);
@ -90,7 +93,8 @@ static void OpDivRdxRaxEvqpSigned16(struct Machine *m, uint8_t *p) {
Write16(m->dx, rem);
}
static void OpDivRdxRaxEvqpUnsigned16(struct Machine *m, uint8_t *p) {
static void OpDivRdxRaxEvqpUnsigned16(struct Machine *m, uint32_t rde,
uint8_t *p) {
uint16_t y, rem;
uint32_t x, quo;
x = (uint32_t)Read16(m->dx) << 16 | Read16(m->ax);
@ -103,7 +107,8 @@ static void OpDivRdxRaxEvqpUnsigned16(struct Machine *m, uint8_t *p) {
Write16(m->dx, rem);
}
static void OpDivRdxRaxEvqpUnsigned32(struct Machine *m, uint8_t *p) {
static void OpDivRdxRaxEvqpUnsigned32(struct Machine *m, uint32_t rde,
uint8_t *p) {
uint32_t y, rem;
uint64_t x, quo;
x = (uint64_t)Read32(m->dx) << 32 | Read32(m->ax);
@ -116,7 +121,8 @@ static void OpDivRdxRaxEvqpUnsigned32(struct Machine *m, uint8_t *p) {
Write64(m->dx, rem & 0xffffffff);
}
static void OpDivRdxRaxEvqpUnsigned64(struct Machine *m, uint8_t *p) {
static void OpDivRdxRaxEvqpUnsigned64(struct Machine *m, uint32_t rde,
uint8_t *p) {
uint64_t y, rem;
uint128_t x, quo;
x = (uint128_t)Read64(m->dx) << 64 | Read64(m->ax);
@ -129,35 +135,35 @@ static void OpDivRdxRaxEvqpUnsigned64(struct Machine *m, uint8_t *p) {
Write64(m->dx, rem);
}
void OpDivRdxRaxEvqpSigned(struct Machine *m) {
void OpDivRdxRaxEvqpSigned(struct Machine *m, uint32_t rde) {
uint8_t *p;
p = GetModrmRegisterWordPointerReadOszRexw(m);
if (Rexw(m->xedd)) {
OpDivRdxRaxEvqpSigned64(m, p);
} else if (!Osz(m->xedd)) {
OpDivRdxRaxEvqpSigned32(m, p);
p = GetModrmRegisterWordPointerReadOszRexw(m, rde);
if (Rexw(rde)) {
OpDivRdxRaxEvqpSigned64(m, rde, p);
} else if (!Osz(rde)) {
OpDivRdxRaxEvqpSigned32(m, rde, p);
} else {
OpDivRdxRaxEvqpSigned16(m, p);
OpDivRdxRaxEvqpSigned16(m, rde, p);
}
}
void OpDivRdxRaxEvqpUnsigned(struct Machine *m) {
void OpDivRdxRaxEvqpUnsigned(struct Machine *m, uint32_t rde) {
uint8_t *p;
p = GetModrmRegisterWordPointerReadOszRexw(m);
if (Rexw(m->xedd)) {
OpDivRdxRaxEvqpUnsigned64(m, p);
} else if (!Osz(m->xedd)) {
OpDivRdxRaxEvqpUnsigned32(m, p);
p = GetModrmRegisterWordPointerReadOszRexw(m, rde);
if (Rexw(rde)) {
OpDivRdxRaxEvqpUnsigned64(m, rde, p);
} else if (!Osz(rde)) {
OpDivRdxRaxEvqpUnsigned32(m, rde, p);
} else {
OpDivRdxRaxEvqpUnsigned16(m, p);
OpDivRdxRaxEvqpUnsigned16(m, rde, p);
}
}
void OpMulAxAlEbSigned(struct Machine *m) {
void OpMulAxAlEbSigned(struct Machine *m, uint32_t rde) {
bool of;
int16_t ax;
uint8_t *p;
p = GetModrmRegisterBytePointerRead(m);
p = GetModrmRegisterBytePointerRead(m, rde);
__builtin_mul_overflow((int8_t)Read8(m->ax), (int8_t)Read8(p), &ax);
of = (int)ax != (int8_t)ax;
m->flags = SetFlag(m->flags, FLAGS_CF, of);
@ -165,11 +171,11 @@ void OpMulAxAlEbSigned(struct Machine *m) {
Write16(m->ax, ax);
}
void OpMulAxAlEbUnsigned(struct Machine *m) {
void OpMulAxAlEbUnsigned(struct Machine *m, uint32_t rde) {
int ax;
bool of;
uint8_t *p;
p = GetModrmRegisterBytePointerRead(m);
p = GetModrmRegisterBytePointerRead(m, rde);
__builtin_mul_overflow(Read8(m->ax), Read8(p), &ax);
of = (uint8_t)ax != ax;
m->flags = SetFlag(m->flags, FLAGS_CF, of);
@ -177,20 +183,20 @@ void OpMulAxAlEbUnsigned(struct Machine *m) {
Write16(m->ax, ax);
}
void OpMulRdxRaxEvqpSigned(struct Machine *m) {
void OpMulRdxRaxEvqpSigned(struct Machine *m, uint32_t rde) {
bool of;
uint8_t *p;
int32_t dxax;
int64_t edxeax;
int128_t rdxrax;
p = GetModrmRegisterWordPointerReadOszRexw(m);
if (Rexw(m->xedd)) {
p = GetModrmRegisterWordPointerReadOszRexw(m, rde);
if (Rexw(rde)) {
__builtin_mul_overflow((int128_t)(int64_t)Read64(m->ax), (int64_t)Read64(p),
&rdxrax);
of = (int128_t)rdxrax != (int64_t)rdxrax;
Write64(m->ax, rdxrax);
Write64(m->dx, rdxrax >> 64);
} else if (!Osz(m->xedd)) {
} else if (!Osz(rde)) {
__builtin_mul_overflow((int64_t)(int32_t)Read32(m->ax), (int32_t)Read32(p),
&edxeax);
of = (int64_t)edxeax != (int32_t)edxeax;
@ -207,19 +213,19 @@ void OpMulRdxRaxEvqpSigned(struct Machine *m) {
m->flags = SetFlag(m->flags, FLAGS_OF, of);
}
void OpMulRdxRaxEvqpUnsigned(struct Machine *m) {
void OpMulRdxRaxEvqpUnsigned(struct Machine *m, uint32_t rde) {
bool of;
uint8_t *p;
uint32_t dxax;
uint64_t edxeax;
uint128_t rdxrax;
p = GetModrmRegisterWordPointerReadOszRexw(m);
if (Rexw(m->xedd)) {
p = GetModrmRegisterWordPointerReadOszRexw(m, rde);
if (Rexw(rde)) {
__builtin_mul_overflow((uint128_t)Read64(m->ax), Read64(p), &rdxrax);
of = (uint64_t)rdxrax != rdxrax;
Write64(m->ax, rdxrax);
Write64(m->dx, rdxrax >> 64);
} else if (!Osz(m->xedd)) {
} else if (!Osz(rde)) {
__builtin_mul_overflow((uint64_t)Read32(m->ax), Read32(p), &edxeax);
of = (uint32_t)edxeax != edxeax;
Write64(m->ax, edxeax);
@ -235,37 +241,38 @@ void OpMulRdxRaxEvqpUnsigned(struct Machine *m) {
m->flags = SetFlag(m->flags, FLAGS_OF, of);
}
static void AluImul(struct Machine *m, uint8_t *a, uint8_t *b) {
static void AluImul(struct Machine *m, uint32_t rde, uint8_t *a, uint8_t *b) {
unsigned of;
if (Rexw(m->xedd)) {
if (Rexw(rde)) {
int64_t x, y, z;
x = Read64(a);
y = Read64(b);
of = __builtin_mul_overflow(x, y, &z);
Write64(RegRexrReg(m), z);
} else if (!Osz(m->xedd)) {
Write64(RegRexrReg(m, rde), z);
} else if (!Osz(rde)) {
int32_t x, y, z;
x = Read32(a);
y = Read32(b);
of = __builtin_mul_overflow(x, y, &z);
Write64(RegRexrReg(m), z & 0xffffffff);
Write64(RegRexrReg(m, rde), z & 0xffffffff);
} else {
int16_t x, y, z;
x = Read16(a);
y = Read16(b);
of = __builtin_mul_overflow(x, y, &z);
Write16(RegRexrReg(m), z);
Write16(RegRexrReg(m, rde), z);
}
m->flags = SetFlag(m->flags, FLAGS_CF, of);
m->flags = SetFlag(m->flags, FLAGS_OF, of);
}
void OpImulGvqpEvqp(struct Machine *m) {
AluImul(m, RegRexrReg(m), GetModrmRegisterWordPointerReadOszRexw(m));
void OpImulGvqpEvqp(struct Machine *m, uint32_t rde) {
AluImul(m, rde, RegRexrReg(m, rde),
GetModrmRegisterWordPointerReadOszRexw(m, rde));
}
void OpImulGvqpEvqpImm(struct Machine *m) {
void OpImulGvqpEvqpImm(struct Machine *m, uint32_t rde) {
uint8_t b[8];
Write64(b, m->xedd->op.uimm0);
AluImul(m, GetModrmRegisterWordPointerReadOszRexw(m), b);
AluImul(m, rde, GetModrmRegisterWordPointerReadOszRexw(m, rde), b);
}

View file

@ -4,16 +4,16 @@
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
void OpDivAlAhAxEbSigned(struct Machine *);
void OpDivAlAhAxEbUnsigned(struct Machine *);
void OpDivRdxRaxEvqpSigned(struct Machine *);
void OpDivRdxRaxEvqpUnsigned(struct Machine *);
void OpImulGvqpEvqp(struct Machine *);
void OpImulGvqpEvqpImm(struct Machine *);
void OpMulAxAlEbSigned(struct Machine *);
void OpMulAxAlEbUnsigned(struct Machine *);
void OpMulRdxRaxEvqpSigned(struct Machine *);
void OpMulRdxRaxEvqpUnsigned(struct Machine *);
void OpDivAlAhAxEbSigned(struct Machine *, uint32_t);
void OpDivAlAhAxEbUnsigned(struct Machine *, uint32_t);
void OpDivRdxRaxEvqpSigned(struct Machine *, uint32_t);
void OpDivRdxRaxEvqpUnsigned(struct Machine *, uint32_t);
void OpImulGvqpEvqp(struct Machine *, uint32_t);
void OpImulGvqpEvqpImm(struct Machine *, uint32_t);
void OpMulAxAlEbSigned(struct Machine *, uint32_t);
void OpMulAxAlEbUnsigned(struct Machine *, uint32_t);
void OpMulRdxRaxEvqpSigned(struct Machine *, uint32_t);
void OpMulRdxRaxEvqpUnsigned(struct Machine *, uint32_t);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

55
tool/build/lib/fds.c Normal file
View file

@ -0,0 +1,55 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/log/check.h"
#include "libc/mem/mem.h"
#include "libc/x/x.h"
#include "tool/build/lib/fds.h"
int MachineFdAdd(struct MachineFds *mf) {
int fd;
struct MachineFdClosed *closed;
if ((closed = mf->closed)) {
DCHECK_LT(closed->fd, mf->i);
fd = closed->fd;
mf->closed = closed->next;
free(closed);
} else {
DCHECK_LE(mf->i, mf->n);
if (mf->i == mf->n) {
if (!grow(&mf->p, &mf->n, sizeof(struct MachineFd), 0)) {
return -1;
}
}
fd = mf->i++;
}
return fd;
}
void MachineFdRemove(struct MachineFds *mf, int fd) {
struct MachineFdClosed *closed;
DCHECK_GE(fd, 0);
DCHECK_LT(fd, mf->i);
mf->p[fd].cb = NULL;
if ((closed = malloc(sizeof(struct MachineFdClosed)))) {
closed->fd = fd;
closed->next = mf->closed;
mf->closed = closed;
}
}

27
tool/build/lib/fds.h Normal file
View file

@ -0,0 +1,27 @@
#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_FDS_H_
#define COSMOPOLITAN_TOOL_BUILD_LIB_FDS_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
struct MachineFds {
size_t i, n;
struct MachineFd {
int fd;
struct MachineFdCb {
int (*close)(int);
ssize_t (*read)(int, void *, size_t);
ssize_t (*write)(int, const void *, size_t);
} * cb;
} * p;
struct MachineFdClosed {
unsigned fd;
struct MachineFdClosed *next;
} * closed;
};
int MachineFdAdd(struct MachineFds *);
void MachineFdRemove(struct MachineFds *, int);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_FDS_H_ */

View file

@ -50,26 +50,6 @@ static long double OnFpuStackUnderflow(struct Machine *m) {
return -NAN;
}
void FpuPush(struct Machine *m, long double x) {
if (FpuGetTag(m, -1) != kFpuTagEmpty) OnFpuStackOverflow(m);
m->fpu.sp -= 1;
*FpuSt(m, 0) = x;
FpuSetTag(m, 0, kFpuTagValid);
}
long double FpuPop(struct Machine *m) {
long double x;
if (FpuGetTag(m, 0) != kFpuTagEmpty) {
x = *FpuSt(m, 0);
FpuSetTag(m, 0, kFpuTagEmpty);
/* *FpuSt(m, 0) = -NAN; */
} else {
x = OnFpuStackUnderflow(m);
}
m->fpu.sp += 1;
return x;
}
static long double St(struct Machine *m, int i) {
if (FpuGetTag(m, i) == kFpuTagEmpty) OnFpuStackUnderflow(m);
return *FpuSt(m, i);
@ -84,7 +64,7 @@ static long double St1(struct Machine *m) {
}
static long double StRm(struct Machine *m) {
return St(m, ModrmRm(m->xedd));
return St(m, ModrmRm(m->xedd->op.rde));
}
static void FpuClearRoundup(struct Machine *m) {
@ -100,7 +80,7 @@ static void FpuSetSt0(struct Machine *m, long double x) {
}
static void FpuSetStRm(struct Machine *m, long double x) {
*FpuSt(m, ModrmRm(m->xedd)) = x;
*FpuSt(m, ModrmRm(m->xedd->op.rde)) = x;
}
static void FpuSetStPop(struct Machine *m, int i, long double x) {
@ -109,7 +89,7 @@ static void FpuSetStPop(struct Machine *m, int i, long double x) {
}
static void FpuSetStRmPop(struct Machine *m, long double x) {
FpuSetStPop(m, ModrmRm(m->xedd), x);
FpuSetStPop(m, ModrmRm(m->xedd->op.rde), x);
}
static int16_t GetMemoryShort(struct Machine *m) {
@ -414,11 +394,11 @@ static void OpFmulEstSt(struct Machine *m) {
}
static void OpFsubEstSt(struct Machine *m) {
FpuSetStRm(m, StRm(m) - St0(m));
FpuSetStRm(m, St0(m) - StRm(m));
}
static void OpFsubrEstSt(struct Machine *m) {
FpuSetStRm(m, St0(m) - StRm(m));
FpuSetStRm(m, StRm(m) - St0(m));
}
static void OpFdivEstSt(struct Machine *m) {
@ -666,8 +646,7 @@ static void OpFstp(struct Machine *m) {
}
static void OpFxch(struct Machine *m) {
long double t;
t = StRm(m);
long double t = StRm(m);
FpuSetStRm(m, St0(m));
FpuSetSt0(m, t);
}
@ -686,7 +665,7 @@ static void OpFldl(struct Machine *m) {
static void OpFldConstant(struct Machine *m) {
long double x;
switch (ModrmRm(m->xedd)) {
switch (ModrmRm(m->xedd->op.rde)) {
case 0:
x = fld1();
break;
@ -769,7 +748,7 @@ static void OpFistps(struct Machine *m) {
FpuPop(m);
}
void OpFcomi(struct Machine *m) {
static void OpFcomi(struct Machine *m) {
long double x, y;
x = St0(m);
y = StRm(m);
@ -808,7 +787,7 @@ static void OpFucomip(struct Machine *m) {
}
static void OpFfree(struct Machine *m) {
FpuSetTag(m, ModrmRm(m->xedd), kFpuTagEmpty);
FpuSetTag(m, ModrmRm(m->xedd->op.rde), kFpuTagEmpty);
}
static void OpFfreep(struct Machine *m) {
@ -890,6 +869,10 @@ static void OpFnclex(struct Machine *m) {
m->fpu.bf = false;
}
static void OpFnop(struct Machine *m) {
/* do nothing */
}
void OpFinit(struct Machine *m) {
m->fpu.cw = X87_NORMAL;
m->fpu.sw = 0;
@ -905,18 +888,59 @@ void OpFwait(struct Machine *m) {
}
}
static void OpFnop(struct Machine *m) {
/* do nothing */
long double *FpuSt(struct Machine *m, unsigned i) {
i += m->fpu.sp;
i &= 0b111;
return m->fpu.st + i;
}
int FpuGetTag(struct Machine *m, unsigned i) {
unsigned t;
t = m->fpu.tw;
i += m->fpu.sp;
i &= 0b111;
i *= 2;
t &= 0b11 << i;
t >>= i;
return t;
}
void FpuSetTag(struct Machine *m, unsigned i, unsigned t) {
i += m->fpu.sp;
t &= 0b11;
i &= 0b111;
i *= 2;
m->fpu.tw &= ~(0b11 << i);
m->fpu.tw |= t << i;
}
void FpuPush(struct Machine *m, long double x) {
if (FpuGetTag(m, -1) != kFpuTagEmpty) OnFpuStackOverflow(m);
m->fpu.sp -= 1;
*FpuSt(m, 0) = x;
FpuSetTag(m, 0, kFpuTagValid);
}
long double FpuPop(struct Machine *m) {
long double x;
if (FpuGetTag(m, 0) != kFpuTagEmpty) {
x = *FpuSt(m, 0);
FpuSetTag(m, 0, kFpuTagEmpty);
} else {
x = OnFpuStackUnderflow(m);
}
m->fpu.sp += 1;
return x;
}
void OpFpu(struct Machine *m) {
unsigned op;
bool ismemory;
op = m->xedd->op.opcode & 0b111;
ismemory = ModrmMod(m->xedd) != 0b11;
ismemory = ModrmMod(m->xedd->op.rde) != 0b11;
m->fpu.ip = m->ip - m->xedd->length;
m->fpu.op = op << 8 | m->xedd->op.modrm;
m->fpu.dp = ismemory ? ComputeAddress(m) : 0;
m->fpu.dp = ismemory ? ComputeAddress(m, m->xedd->op.rde) : 0;
switch (DISP(op, ismemory, m->xedd->op.reg)) {
CASE(DISP(0xD8, FPUREG, 0), OpFaddStEst(m));
CASE(DISP(0xD8, FPUREG, 1), OpFmulStEst(m));
@ -1029,7 +1053,7 @@ void OpFpu(struct Machine *m) {
CASE(DISP(0xDf, MEMORY, 5), OpFildll(m));
CASE(DISP(0xDf, MEMORY, 7), OpFistpll(m));
case DISP(0xD9, FPUREG, 4):
switch (ModrmRm(m->xedd)) {
switch (ModrmRm(m->xedd->op.rde)) {
CASE(0, OpFchs(m));
CASE(1, OpFabs(m));
CASE(4, OpFtst(m));
@ -1039,7 +1063,7 @@ void OpFpu(struct Machine *m) {
}
break;
case DISP(0xD9, FPUREG, 6):
switch (ModrmRm(m->xedd)) {
switch (ModrmRm(m->xedd->op.rde)) {
CASE(0, OpF2xm1(m));
CASE(1, OpFyl2x(m));
CASE(2, OpFptan(m));
@ -1053,7 +1077,7 @@ void OpFpu(struct Machine *m) {
}
break;
case DISP(0xD9, FPUREG, 7):
switch (ModrmRm(m->xedd)) {
switch (ModrmRm(m->xedd->op.rde)) {
CASE(0, OpFprem(m));
CASE(1, OpFyl2xp1(m));
CASE(2, OpFsqrt(m));
@ -1067,7 +1091,7 @@ void OpFpu(struct Machine *m) {
}
break;
case DISP(0xDb, FPUREG, 4):
switch (ModrmRm(m->xedd)) {
switch (ModrmRm(m->xedd->op.rde)) {
CASE(2, OpFnclex(m));
CASE(3, OpFinit(m));
default:

View file

@ -15,32 +15,9 @@ void OpFinit(struct Machine *);
void OpFwait(struct Machine *);
void FpuPush(struct Machine *, long double);
long double FpuPop(struct Machine *);
forceinline long double *FpuSt(struct Machine *m, unsigned i) {
i += m->fpu.sp;
i &= 0b111;
return m->fpu.st + i;
}
forceinline int FpuGetTag(struct Machine *m, unsigned i) {
unsigned t;
t = m->fpu.tw;
i += m->fpu.sp;
i &= 0b111;
i *= 2;
t &= 0b11 << i;
t >>= i;
return t;
}
forceinline void FpuSetTag(struct Machine *m, unsigned i, unsigned t) {
i += m->fpu.sp;
t &= 0b11;
i &= 0b111;
i *= 2;
m->fpu.tw &= ~(0b11 << i);
m->fpu.tw |= t << i;
}
long double *FpuSt(struct Machine *, unsigned);
int FpuGetTag(struct Machine *, unsigned);
void FpuSetTag(struct Machine *, unsigned, unsigned);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View file

@ -17,13 +17,34 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/stdio/stdio.h"
#include "libc/sysv/consts/fileno.h"
#include "tool/build/lib/ioports.h"
static int OpE9Read(struct Machine *m) {
int fd;
uint8_t b;
fd = STDIN_FILENO;
if (fd >= m->fds.i) return -1;
if (!m->fds.p[fd].cb) return -1;
if (m->fds.p[fd].cb->read(m->fds.p[fd].fd, &b, 1) == 1) {
return b;
} else {
return -1;
}
}
static void OpE9Write(struct Machine *m, uint8_t b) {
int fd;
fd = STDOUT_FILENO;
if (fd >= m->fds.i) return;
if (!m->fds.p[fd].cb) return;
m->fds.p[fd].cb->write(m->fds.p[fd].fd, &b, 1);
}
uint64_t OpIn(struct Machine *m, uint16_t p) {
switch (p) {
case 0xE9:
return getc(stdin);
return OpE9Read(m);
default:
return -1;
}
@ -32,9 +53,7 @@ uint64_t OpIn(struct Machine *m, uint16_t p) {
void OpOut(struct Machine *m, uint16_t p, uint32_t x) {
switch (p) {
case 0xE9:
do {
putc(x, stdout);
} while (x >> 8);
OpE9Write(m, x);
break;
default:
break;

File diff suppressed because it is too large Load diff

View file

@ -3,6 +3,7 @@
#include "libc/elf/struct/ehdr.h"
#include "libc/runtime/runtime.h"
#include "third_party/xed/x86.h"
#include "tool/build/lib/fds.h"
#include "tool/build/lib/pml4t.h"
#define kXmmIntegral 0
@ -136,6 +137,7 @@ struct Machine {
uint8_t stash[4096];
uint8_t xmmtype[2][8];
struct XedDecodedInst icache[512];
struct MachineFds fds;
};
void ResetCpu(struct Machine *);

View file

@ -26,207 +26,223 @@
/**
* Computes virtual address based on modrm and sib bytes.
*/
int64_t ComputeAddress(const struct Machine *m) {
int64_t ComputeAddress(const struct Machine *m, uint32_t rde) {
uint64_t i;
DCHECK(m->xedd->op.has_modrm);
DCHECK(!IsModrmRegister(m->xedd));
DCHECK(!IsModrmRegister(rde));
i = m->xedd->op.disp;
if (!SibExists(m->xedd)) {
i += IsRipRelative(m->xedd) ? m->ip : Read64(RegRexbRm(m));
if (!SibExists(rde)) {
if (IsRipRelative(rde)) {
i += m->ip;
} else {
i += Read64(RegRexbRm(m, rde));
}
} else {
DCHECK(m->xedd->op.has_sib);
if (SibHasBase(m->xedd)) i += Read64(RegRexbBase(m));
if (SibHasIndex(m->xedd)) i += Read64(RegRexxIndex(m)) << m->xedd->op.scale;
if (SibHasBase(rde)) {
i += Read64(RegRexbBase(m, rde));
}
if (SibHasIndex(rde)) {
i += Read64(RegRexxIndex(m, rde)) << m->xedd->op.scale;
}
}
i += GetSegment(m);
if (Asz(m->xedd)) i &= 0xffffffff;
if (Asz(rde)) i &= 0xffffffff;
return i;
}
void *ComputeReserveAddressRead(struct Machine *m, size_t n) {
void *ComputeReserveAddressRead(struct Machine *m, uint32_t rde, size_t n) {
int64_t v;
v = ComputeAddress(m);
v = ComputeAddress(m, rde);
SetReadAddr(m, v, n);
return ReserveAddress(m, v, n);
}
void *ComputeReserveAddressRead1(struct Machine *m) {
return ComputeReserveAddressRead(m, 1);
void *ComputeReserveAddressRead1(struct Machine *m, uint32_t rde) {
return ComputeReserveAddressRead(m, rde, 1);
}
void *ComputeReserveAddressRead8(struct Machine *m) {
return ComputeReserveAddressRead(m, 8);
void *ComputeReserveAddressRead8(struct Machine *m, uint32_t rde) {
return ComputeReserveAddressRead(m, rde, 8);
}
void *ComputeReserveAddressWrite(struct Machine *m, size_t n) {
void *ComputeReserveAddressWrite(struct Machine *m, uint32_t rde, size_t n) {
int64_t v;
v = ComputeAddress(m);
v = ComputeAddress(m, rde);
SetWriteAddr(m, v, n);
return ReserveAddress(m, v, n);
}
void *ComputeReserveAddressWrite1(struct Machine *m) {
return ComputeReserveAddressWrite(m, 1);
void *ComputeReserveAddressWrite1(struct Machine *m, uint32_t rde) {
return ComputeReserveAddressWrite(m, rde, 1);
}
void *ComputeReserveAddressWrite4(struct Machine *m) {
return ComputeReserveAddressWrite(m, 4);
void *ComputeReserveAddressWrite4(struct Machine *m, uint32_t rde) {
return ComputeReserveAddressWrite(m, rde, 4);
}
void *ComputeReserveAddressWrite8(struct Machine *m) {
return ComputeReserveAddressWrite(m, 8);
void *ComputeReserveAddressWrite8(struct Machine *m, uint32_t rde) {
return ComputeReserveAddressWrite(m, rde, 8);
}
uint8_t *GetModrmRegisterMmPointerRead(struct Machine *m, size_t n) {
if (IsModrmRegister(m->xedd)) {
return MmRm(m);
uint8_t *GetModrmRegisterMmPointerRead(struct Machine *m, uint32_t rde,
size_t n) {
if (IsModrmRegister(rde)) {
return MmRm(m, rde);
} else {
return ComputeReserveAddressRead(m, n);
return ComputeReserveAddressRead(m, rde, n);
}
}
uint8_t *GetModrmRegisterMmPointerRead8(struct Machine *m) {
return GetModrmRegisterMmPointerRead(m, 8);
uint8_t *GetModrmRegisterMmPointerRead8(struct Machine *m, uint32_t rde) {
return GetModrmRegisterMmPointerRead(m, rde, 8);
}
uint8_t *GetModrmRegisterMmPointerWrite(struct Machine *m, size_t n) {
if (IsModrmRegister(m->xedd)) {
return MmRm(m);
uint8_t *GetModrmRegisterMmPointerWrite(struct Machine *m, uint32_t rde,
size_t n) {
if (IsModrmRegister(rde)) {
return MmRm(m, rde);
} else {
return ComputeReserveAddressWrite(m, n);
return ComputeReserveAddressWrite(m, rde, n);
}
}
uint8_t *GetModrmRegisterMmPointerWrite8(struct Machine *m) {
return GetModrmRegisterMmPointerWrite(m, 8);
uint8_t *GetModrmRegisterMmPointerWrite8(struct Machine *m, uint32_t rde) {
return GetModrmRegisterMmPointerWrite(m, rde, 8);
}
uint8_t *GetModrmRegisterBytePointerRead(struct Machine *m) {
uint8_t *GetModrmRegisterBytePointerRead(struct Machine *m, uint32_t rde) {
int64_t v;
if (IsModrmRegister(m->xedd)) {
return ByteRexbRm(m);
if (IsModrmRegister(rde)) {
return ByteRexbRm(m, rde);
} else {
return ComputeReserveAddressRead1(m);
return ComputeReserveAddressRead1(m, rde);
}
}
uint8_t *GetModrmRegisterBytePointerWrite(struct Machine *m) {
uint8_t *GetModrmRegisterBytePointerWrite(struct Machine *m, uint32_t rde) {
int64_t v;
if (IsModrmRegister(m->xedd)) {
return ByteRexbRm(m);
if (IsModrmRegister(rde)) {
return ByteRexbRm(m, rde);
} else {
return ComputeReserveAddressWrite1(m);
return ComputeReserveAddressWrite1(m, rde);
}
}
uint8_t *GetModrmRegisterWordPointerRead(struct Machine *m, size_t n) {
if (IsModrmRegister(m->xedd)) {
return RegRexbRm(m);
uint8_t *GetModrmRegisterWordPointerRead(struct Machine *m, uint32_t rde,
size_t n) {
if (IsModrmRegister(rde)) {
return RegRexbRm(m, rde);
} else {
return ComputeReserveAddressRead(m, n);
return ComputeReserveAddressRead(m, rde, n);
}
}
uint8_t *GetModrmRegisterWordPointerRead2(struct Machine *m) {
return GetModrmRegisterWordPointerRead(m, 2);
uint8_t *GetModrmRegisterWordPointerRead2(struct Machine *m, uint32_t rde) {
return GetModrmRegisterWordPointerRead(m, rde, 2);
}
uint8_t *GetModrmRegisterWordPointerRead4(struct Machine *m) {
return GetModrmRegisterWordPointerRead(m, 4);
uint8_t *GetModrmRegisterWordPointerRead4(struct Machine *m, uint32_t rde) {
return GetModrmRegisterWordPointerRead(m, rde, 4);
}
uint8_t *GetModrmRegisterWordPointerRead8(struct Machine *m) {
return GetModrmRegisterWordPointerRead(m, 8);
uint8_t *GetModrmRegisterWordPointerRead8(struct Machine *m, uint32_t rde) {
return GetModrmRegisterWordPointerRead(m, rde, 8);
}
uint8_t *GetModrmRegisterWordPointerReadOsz(struct Machine *m) {
if (!Osz(m->xedd)) {
return GetModrmRegisterWordPointerRead8(m);
uint8_t *GetModrmRegisterWordPointerReadOsz(struct Machine *m, uint32_t rde) {
if (!Osz(rde)) {
return GetModrmRegisterWordPointerRead8(m, rde);
} else {
return GetModrmRegisterWordPointerRead2(m);
return GetModrmRegisterWordPointerRead2(m, rde);
}
}
uint8_t *GetModrmRegisterWordPointerReadOszRexw(struct Machine *m) {
if (Rexw(m->xedd)) {
return GetModrmRegisterWordPointerRead8(m);
} else if (!Osz(m->xedd)) {
return GetModrmRegisterWordPointerRead4(m);
uint8_t *GetModrmRegisterWordPointerReadOszRexw(struct Machine *m,
uint32_t rde) {
if (Rexw(rde)) {
return GetModrmRegisterWordPointerRead8(m, rde);
} else if (!Osz(rde)) {
return GetModrmRegisterWordPointerRead4(m, rde);
} else {
return GetModrmRegisterWordPointerRead2(m);
return GetModrmRegisterWordPointerRead2(m, rde);
}
}
uint8_t *GetModrmRegisterWordPointerWrite(struct Machine *m, size_t n) {
if (IsModrmRegister(m->xedd)) {
return RegRexbRm(m);
uint8_t *GetModrmRegisterWordPointerWrite(struct Machine *m, uint32_t rde,
size_t n) {
if (IsModrmRegister(rde)) {
return RegRexbRm(m, rde);
} else {
return ComputeReserveAddressWrite(m, n);
return ComputeReserveAddressWrite(m, rde, n);
}
}
uint8_t *GetModrmRegisterWordPointerWrite4(struct Machine *m) {
return GetModrmRegisterWordPointerWrite(m, 4);
uint8_t *GetModrmRegisterWordPointerWrite4(struct Machine *m, uint32_t rde) {
return GetModrmRegisterWordPointerWrite(m, rde, 4);
}
uint8_t *GetModrmRegisterWordPointerWrite8(struct Machine *m) {
return GetModrmRegisterWordPointerWrite(m, 8);
uint8_t *GetModrmRegisterWordPointerWrite8(struct Machine *m, uint32_t rde) {
return GetModrmRegisterWordPointerWrite(m, rde, 8);
}
uint8_t *GetModrmRegisterWordPointerWriteOszRexw(struct Machine *m) {
if (Rexw(m->xedd)) {
return GetModrmRegisterWordPointerWrite(m, 8);
} else if (!Osz(m->xedd)) {
return GetModrmRegisterWordPointerWrite(m, 4);
uint8_t *GetModrmRegisterWordPointerWriteOszRexw(struct Machine *m,
uint32_t rde) {
if (Rexw(rde)) {
return GetModrmRegisterWordPointerWrite(m, rde, 8);
} else if (!Osz(rde)) {
return GetModrmRegisterWordPointerWrite(m, rde, 4);
} else {
return GetModrmRegisterWordPointerWrite(m, 2);
return GetModrmRegisterWordPointerWrite(m, rde, 2);
}
}
uint8_t *GetModrmRegisterWordPointerWriteOsz(struct Machine *m) {
if (!Osz(m->xedd)) {
return GetModrmRegisterWordPointerWrite(m, 8);
uint8_t *GetModrmRegisterWordPointerWriteOsz(struct Machine *m, uint32_t rde) {
if (!Osz(rde)) {
return GetModrmRegisterWordPointerWrite(m, rde, 8);
} else {
return GetModrmRegisterWordPointerWrite(m, 2);
return GetModrmRegisterWordPointerWrite(m, rde, 2);
}
}
uint8_t *GetModrmRegisterXmmPointerRead(struct Machine *m, size_t n) {
if (IsModrmRegister(m->xedd)) {
return XmmRexbRm(m);
uint8_t *GetModrmRegisterXmmPointerRead(struct Machine *m, uint32_t rde,
size_t n) {
if (IsModrmRegister(rde)) {
return XmmRexbRm(m, rde);
} else {
return ComputeReserveAddressRead(m, n);
return ComputeReserveAddressRead(m, rde, n);
}
}
uint8_t *GetModrmRegisterXmmPointerRead4(struct Machine *m) {
return GetModrmRegisterXmmPointerRead(m, 4);
uint8_t *GetModrmRegisterXmmPointerRead4(struct Machine *m, uint32_t rde) {
return GetModrmRegisterXmmPointerRead(m, rde, 4);
}
uint8_t *GetModrmRegisterXmmPointerRead8(struct Machine *m) {
return GetModrmRegisterXmmPointerRead(m, 8);
uint8_t *GetModrmRegisterXmmPointerRead8(struct Machine *m, uint32_t rde) {
return GetModrmRegisterXmmPointerRead(m, rde, 8);
}
uint8_t *GetModrmRegisterXmmPointerRead16(struct Machine *m) {
return GetModrmRegisterXmmPointerRead(m, 16);
uint8_t *GetModrmRegisterXmmPointerRead16(struct Machine *m, uint32_t rde) {
return GetModrmRegisterXmmPointerRead(m, rde, 16);
}
uint8_t *GetModrmRegisterXmmPointerWrite(struct Machine *m, size_t n) {
if (IsModrmRegister(m->xedd)) {
return XmmRexbRm(m);
uint8_t *GetModrmRegisterXmmPointerWrite(struct Machine *m, uint32_t rde,
size_t n) {
if (IsModrmRegister(rde)) {
return XmmRexbRm(m, rde);
} else {
return ComputeReserveAddressWrite(m, n);
return ComputeReserveAddressWrite(m, rde, n);
}
}
uint8_t *GetModrmRegisterXmmPointerWrite4(struct Machine *m) {
return GetModrmRegisterXmmPointerWrite(m, 4);
uint8_t *GetModrmRegisterXmmPointerWrite4(struct Machine *m, uint32_t rde) {
return GetModrmRegisterXmmPointerWrite(m, rde, 4);
}
uint8_t *GetModrmRegisterXmmPointerWrite8(struct Machine *m) {
return GetModrmRegisterXmmPointerWrite(m, 8);
uint8_t *GetModrmRegisterXmmPointerWrite8(struct Machine *m, uint32_t rde) {
return GetModrmRegisterXmmPointerWrite(m, rde, 8);
}
uint8_t *GetModrmRegisterXmmPointerWrite16(struct Machine *m) {
return GetModrmRegisterXmmPointerWrite(m, 16);
uint8_t *GetModrmRegisterXmmPointerWrite16(struct Machine *m, uint32_t rde) {
return GetModrmRegisterXmmPointerWrite(m, rde, 16);
}

View file

@ -2,80 +2,80 @@
#define COSMOPOLITAN_TOOL_BUILD_LIB_MODRM_H_
#include "tool/build/lib/abp.h"
#include "tool/build/lib/machine.h"
#include "tool/build/lib/memory.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
#define IsModrmRegister(x) (ModrmMod(x) == 3)
#define IsProbablyByteOp(x) !((x)->op.opcode & 1)
#define SibExists(x) (ModrmRm(x) == 4)
#define SibHasIndex(x) (SibIndex(x) != 4 || Rexx(x))
#define SibHasBase(x) (SibBase(x) != 5 || ModrmMod(x))
#define SibIsAbsolute(x) (!SibHasBase(x) && !SibHasIndex(x))
#define IsRipRelative(x) (ModrmRm(x) == 5 && !ModrmMod(x))
#define SibBase(x) (((x)->op.rde & 000007000000) >> 18)
#define SibIndex(x) (((x)->op.rde & 000700000000) >> 24)
#define ModrmRm(x) (((x)->op.rde & 000000000700) >> 6)
#define ModrmReg(x) (((x)->op.rde & 000000000007) >> 0)
#define ModrmSrm(x) (((x)->op.rde & 000000070000) >> 12)
#define ModrmMod(x) (((x)->op.rde & 000060000000) >> 22)
#define RegLog2(x) (((x)->op.rde & 006000000000) >> 28)
#define Rexx(x) (((x)->op.rde & 001000000000) >> 27)
#define Asz(x) (((x)->op.rde & 000000400000) >> 17)
#define Rexw(x) (((x)->op.rde & 000000004000) >> 11)
#define Rexr(x) (((x)->op.rde & 000000000010) >> 3)
#define Rexb(x) (((x)->op.rde & 000010000000) >> 21)
#define Rex(x) (((x)->op.rde & 000000000020) >> 4)
#define Osz(x) (((x)->op.rde & 000000000040) >> 5)
#define Rep(x) (((x)->op.rde & 030000000000) >> 30)
#define ByteRexrReg(m) m->beg[(m->xedd->op.rde & 00000000037) >> 0]
#define ByteRexbRm(m) m->beg[(m->xedd->op.rde & 00000003700) >> 6]
#define ByteRexbSrm(m) m->beg[(m->xedd->op.rde & 00000370000) >> 12]
#define RegRexrReg(m) Abp8(m->reg[(m->xedd->op.rde & 00000000017) >> 0])
#define RegRexbRm(m) Abp8(m->reg[(m->xedd->op.rde & 00000001700) >> 6])
#define RegRexbSrm(m) Abp8(m->reg[(m->xedd->op.rde & 00000170000) >> 12])
#define RegRexbBase(m) Abp8(m->reg[(m->xedd->op.rde & 00017000000) >> 18])
#define RegRexxIndex(m) Abp8(m->reg[(m->xedd->op.rde & 01700000000) >> 24])
#define XmmRexrReg(m) Abp16(m->veg[(m->xedd->op.rde & 00000000017) >> 0])
#define XmmRexbRm(m) Abp16(m->veg[(m->xedd->op.rde & 00000001700) >> 6])
#define MmReg(m) Abp16(m->veg[(m->xedd->op.rde & 00000000007) >> 0])
#define MmRm(m) Abp16(m->veg[(m->xedd->op.rde & 00000000700) >> 6])
#define SibBase(x) ((x & 000007000000) >> 022)
#define SibIndex(x) ((x & 000700000000) >> 030)
#define ModrmRm(x) ((x & 000000000700) >> 006)
#define ModrmReg(x) ((x & 000000000007) >> 000)
#define ModrmSrm(x) ((x & 000000070000) >> 014)
#define ModrmMod(x) ((x & 000060000000) >> 026)
#define RegLog2(x) ((x & 006000000000) >> 034)
#define Rexx(x) ((x & 001000000000) >> 033)
#define Asz(x) ((x & 000000400000) >> 021)
#define Rexw(x) ((x & 000000004000) >> 013)
#define Rexr(x) ((x & 000000000010) >> 003)
#define Rexb(x) ((x & 000010000000) >> 025)
#define Rex(x) ((x & 000000000020) >> 004)
#define Osz(x) ((x & 000000000040) >> 005)
#define Rep(x) ((x & 030000000000) >> 036)
int64_t ComputeAddress(const struct Machine *) nosideeffect;
#define IsModrmRegister(x) (ModrmMod(x) == 3)
#define SibExists(x) (ModrmRm(x) == 4)
#define SibHasIndex(x) (SibIndex(x) != 4 || Rexx(x))
#define SibHasBase(x) (SibBase(x) != 5 || ModrmMod(x))
#define SibIsAbsolute(x) (!SibHasBase(x) && !SibHasIndex(x))
#define IsRipRelative(x) (ModrmRm(x) == 5 && !ModrmMod(x))
void *ComputeReserveAddressRead(struct Machine *, size_t);
void *ComputeReserveAddressRead1(struct Machine *);
void *ComputeReserveAddressRead8(struct Machine *);
void *ComputeReserveAddressWrite(struct Machine *, size_t);
void *ComputeReserveAddressWrite1(struct Machine *);
void *ComputeReserveAddressWrite4(struct Machine *);
void *ComputeReserveAddressWrite8(struct Machine *);
#define ByteRexrReg(m, x) m->beg[(x & 00000000037) >> 0]
#define ByteRexbRm(m, x) m->beg[(x & 00000003700) >> 6]
#define ByteRexbSrm(m, x) m->beg[(x & 00000370000) >> 12]
#define RegRexbSrm(m, x) Abp8(m->reg[(x & 00000170000) >> 12])
#define RegRexrReg(m, x) Abp8(m->reg[(x & 00000000017) >> 0])
#define RegRexbRm(m, x) Abp8(m->reg[(x & 00000001700) >> 6])
#define RegRexbBase(m, x) Abp8(m->reg[(x & 00017000000) >> 18])
#define RegRexxIndex(m, x) Abp8(m->reg[(x & 01700000000) >> 24])
#define XmmRexrReg(m, x) Abp16(m->veg[(x & 00000000017) >> 0])
#define XmmRexbRm(m, x) Abp16(m->veg[(x & 00000001700) >> 6])
#define MmReg(m, x) Abp16(m->veg[(x & 00000000007) >> 0])
#define MmRm(m, x) Abp16(m->veg[(x & 00000000700) >> 6])
uint8_t *GetModrmRegisterBytePointerRead(struct Machine *);
uint8_t *GetModrmRegisterBytePointerWrite(struct Machine *);
uint8_t *GetModrmRegisterMmPointerRead(struct Machine *, size_t);
uint8_t *GetModrmRegisterMmPointerRead8(struct Machine *);
uint8_t *GetModrmRegisterMmPointerWrite(struct Machine *, size_t);
uint8_t *GetModrmRegisterMmPointerWrite8(struct Machine *);
uint8_t *GetModrmRegisterWordPointerRead(struct Machine *, size_t);
uint8_t *GetModrmRegisterWordPointerRead2(struct Machine *);
uint8_t *GetModrmRegisterWordPointerRead4(struct Machine *);
uint8_t *GetModrmRegisterWordPointerRead8(struct Machine *);
uint8_t *GetModrmRegisterWordPointerReadOsz(struct Machine *);
uint8_t *GetModrmRegisterWordPointerReadOszRexw(struct Machine *);
uint8_t *GetModrmRegisterWordPointerWrite(struct Machine *, size_t);
uint8_t *GetModrmRegisterWordPointerWrite4(struct Machine *);
uint8_t *GetModrmRegisterWordPointerWrite8(struct Machine *);
uint8_t *GetModrmRegisterWordPointerWriteOsz(struct Machine *);
uint8_t *GetModrmRegisterWordPointerWriteOszRexw(struct Machine *);
uint8_t *GetModrmRegisterXmmPointerRead(struct Machine *, size_t);
uint8_t *GetModrmRegisterXmmPointerRead16(struct Machine *);
uint8_t *GetModrmRegisterXmmPointerRead4(struct Machine *);
uint8_t *GetModrmRegisterXmmPointerRead8(struct Machine *);
uint8_t *GetModrmRegisterXmmPointerWrite(struct Machine *, size_t);
uint8_t *GetModrmRegisterXmmPointerWrite16(struct Machine *);
uint8_t *GetModrmRegisterXmmPointerWrite4(struct Machine *);
uint8_t *GetModrmRegisterXmmPointerWrite8(struct Machine *);
int64_t ComputeAddress(const struct Machine *, uint32_t) nosideeffect;
void *ComputeReserveAddressRead(struct Machine *, uint32_t, size_t);
void *ComputeReserveAddressRead1(struct Machine *, uint32_t);
void *ComputeReserveAddressRead8(struct Machine *, uint32_t);
void *ComputeReserveAddressWrite(struct Machine *, uint32_t, size_t);
void *ComputeReserveAddressWrite1(struct Machine *, uint32_t);
void *ComputeReserveAddressWrite4(struct Machine *, uint32_t);
void *ComputeReserveAddressWrite8(struct Machine *, uint32_t);
uint8_t *GetModrmRegisterBytePointerRead(struct Machine *, uint32_t);
uint8_t *GetModrmRegisterBytePointerWrite(struct Machine *, uint32_t);
uint8_t *GetModrmRegisterMmPointerRead(struct Machine *, uint32_t, size_t);
uint8_t *GetModrmRegisterMmPointerRead8(struct Machine *, uint32_t);
uint8_t *GetModrmRegisterMmPointerWrite(struct Machine *, uint32_t, size_t);
uint8_t *GetModrmRegisterMmPointerWrite8(struct Machine *, uint32_t);
uint8_t *GetModrmRegisterWordPointerRead(struct Machine *, uint32_t, size_t);
uint8_t *GetModrmRegisterWordPointerRead2(struct Machine *, uint32_t);
uint8_t *GetModrmRegisterWordPointerRead4(struct Machine *, uint32_t);
uint8_t *GetModrmRegisterWordPointerRead8(struct Machine *, uint32_t);
uint8_t *GetModrmRegisterWordPointerReadOsz(struct Machine *, uint32_t);
uint8_t *GetModrmRegisterWordPointerReadOszRexw(struct Machine *, uint32_t);
uint8_t *GetModrmRegisterWordPointerWrite(struct Machine *, uint32_t, size_t);
uint8_t *GetModrmRegisterWordPointerWrite4(struct Machine *, uint32_t);
uint8_t *GetModrmRegisterWordPointerWrite8(struct Machine *, uint32_t);
uint8_t *GetModrmRegisterWordPointerWriteOsz(struct Machine *, uint32_t);
uint8_t *GetModrmRegisterWordPointerWriteOszRexw(struct Machine *, uint32_t);
uint8_t *GetModrmRegisterXmmPointerRead(struct Machine *, uint32_t, size_t);
uint8_t *GetModrmRegisterXmmPointerRead16(struct Machine *, uint32_t);
uint8_t *GetModrmRegisterXmmPointerRead4(struct Machine *, uint32_t);
uint8_t *GetModrmRegisterXmmPointerRead8(struct Machine *, uint32_t);
uint8_t *GetModrmRegisterXmmPointerWrite(struct Machine *, uint32_t, size_t);
uint8_t *GetModrmRegisterXmmPointerWrite16(struct Machine *, uint32_t);
uint8_t *GetModrmRegisterXmmPointerWrite4(struct Machine *, uint32_t);
uint8_t *GetModrmRegisterXmmPointerWrite8(struct Machine *, uint32_t);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

512
tool/build/lib/pty.c Normal file
View file

@ -0,0 +1,512 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/bits/bits.h"
#include "libc/bits/safemacros.h"
#include "libc/conv/conv.h"
#include "libc/log/check.h"
#include "libc/macros.h"
#include "libc/mem/mem.h"
#include "libc/nexgen32e/bsr.h"
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
#include "libc/str/thompike.h"
#include "libc/unicode/unicode.h"
#include "libc/x/x.h"
#include "tool/build/lib/pty.h"
struct MachinePty *MachinePtyNew(unsigned yn, unsigned xn) {
struct MachinePty *pty;
DCHECK_GT(yn, 0);
DCHECK_GT(xn, 0);
pty = xcalloc(1, sizeof(struct MachinePty));
pty->yn = yn;
pty->xn = xn;
pty->wcs = xcalloc(yn * xn, sizeof(pty->wcs[0]));
pty->fgs = xcalloc(yn * xn, sizeof(pty->fgs[0]));
pty->bgs = xcalloc(yn * xn, sizeof(pty->bgs[0]));
pty->prs = xcalloc(yn * xn, sizeof(pty->prs[0]));
return pty;
}
void MachinePtyFree(struct MachinePty *pty) {
if (pty) {
free(pty->wcs);
free(pty->fgs);
free(pty->bgs);
free(pty->prs);
free(pty);
}
}
static void MachinePtyScrollPlane(struct MachinePty *pty, uint32_t *p) {
memcpy(p, p + pty->xn, sizeof(p[0]) * pty->xn * (pty->yn - 1));
memset(p + pty->xn * (pty->yn - 1), 0, sizeof(p[0]) * pty->xn);
}
static void MachinePtyScroll(struct MachinePty *pty) {
MachinePtyScrollPlane(pty, pty->wcs);
MachinePtyScrollPlane(pty, pty->fgs);
MachinePtyScrollPlane(pty, pty->bgs);
MachinePtyScrollPlane(pty, pty->prs);
}
static void MachinePtyNewline(struct MachinePty *pty) {
pty->x = 0;
if (++pty->y == pty->yn) {
--pty->y;
MachinePtyScroll(pty);
}
}
static void SetMachinePtyCell(struct MachinePty *pty, wint_t wc) {
uint32_t w, i;
if ((w = MAX(0, wcwidth(wc))) > 0) {
i = pty->y * pty->xn + pty->x;
pty->wcs[i] = wc;
pty->fgs[i] = pty->fg;
pty->bgs[i] = pty->bg;
pty->prs[i] = pty->pr;
if ((pty->x += w) >= pty->xn) {
pty->x = 0;
MachinePtyNewline(pty);
}
}
}
static void MachinePtyTab(struct MachinePty *pty) {
unsigned x, x2;
x2 = pty->x + ROUNDUP(pty->x + 1, 8);
if (x2 >= pty->xn) x2 = pty->xn - 1;
for (x = pty->x; x < x2; ++x) {
pty->wcs[pty->y * pty->xn + x] = 0;
}
pty->x = x2;
}
static void MachinePtyCursorSet(struct MachinePty *pty, int y, int x) {
pty->y = MAX(0, MIN(pty->yn - 1, y));
pty->x = MAX(0, MIN(pty->xn - 1, x));
}
static void MachinePtyCursorMove(struct MachinePty *pty, int dy, int dx) {
int n;
if (pty->esc.i > 1) {
n = atoi(pty->esc.s);
dy *= n;
dx *= n;
}
MachinePtyCursorSet(pty, pty->y + dy, pty->x + dx);
}
static void MachinePtyCursorPosition(struct MachinePty *pty) {
int row, col;
row = MAX(1, atoi(pty->esc.s));
col = MAX(1, atoi((char *)firstnonnull(strchr(pty->esc.s, ';'), "x") + 1));
MachinePtyCursorSet(pty, row - 1, col - 1);
}
static void MachinePtyEraseRange(struct MachinePty *pty, size_t i, size_t j) {
size_t n;
n = (j - i) * sizeof(uint32_t);
memset(pty->wcs + i, 0, n);
memset(pty->fgs + i, 0, n);
memset(pty->bgs + i, 0, n);
memset(pty->prs + i, 0, n);
}
static void MachinePtyEraseDisplay(struct MachinePty *pty) {
switch (atoi(pty->esc.s)) {
case 3:
case 2:
pty->y = 0;
pty->x = 0;
case 0:
MachinePtyEraseRange(pty, pty->y * pty->xn + pty->x, pty->yn * pty->xn);
break;
case 1:
MachinePtyEraseRange(pty, 0, pty->y * pty->xn + pty->x);
break;
default:
break;
}
}
static void MachinePtyEraseLine(struct MachinePty *pty) {
switch (atoi(pty->esc.s)) {
case 0:
MachinePtyEraseRange(pty, pty->y * pty->xn + pty->x,
pty->y * pty->xn + pty->xn);
break;
case 1:
MachinePtyEraseRange(pty, pty->y * pty->xn + pty->xn,
pty->y * pty->xn + pty->x);
break;
case 2:
MachinePtyEraseRange(pty, pty->y * pty->xn, pty->y * pty->xn + pty->xn);
break;
default:
break;
}
}
static void MachinePtySelectGraphicsRendition(struct MachinePty *pty) {
char *p, c;
unsigned x;
uint8_t code[4];
enum {
kSgr,
kSgrFg = 010,
kSgrFgTrue = 012,
kSgrFgXterm = 015,
kSgrBg = 020,
kSgrBgTrue = 022,
kSgrBgXterm = 025,
} t;
x = 0;
t = kSgr;
p = pty->esc.s;
memset(code, 0, sizeof(code));
for (;;) {
c = *p++;
switch (c) {
case '\0':
return;
case '0' ... '9':
x *= 10;
x += c - '0';
break;
case ';':
case 'm':
code[code[3]] = x;
x = 0;
switch (t) {
case kSgr:
switch (code[0]) {
case 0:
pty->fg = 0;
pty->bg = 0;
pty->pr = 0;
break;
case 1:
pty->pr |= kMachinePtyBold;
break;
case 21:
pty->pr &= ~kMachinePtyBold;
break;
case 2:
pty->pr |= kMachinePtyFaint;
break;
case 22:
pty->pr &= ~kMachinePtyFaint;
break;
case 7:
pty->pr |= kMachinePtyFlip;
break;
case 27:
pty->pr &= ~kMachinePtyFlip;
break;
case 90 ... 97:
code[0] -= 90 - 30;
code[0] += 8;
case 30 ... 37:
pty->fg = code[0] - 30;
pty->pr |= kMachinePtyFg;
pty->pr &= ~kMachinePtyTrue;
break;
case 38:
t = kSgrFg;
break;
case 39:
pty->pr &= kMachinePtyFg;
break;
case 100 ... 107:
code[0] -= 100 - 40;
code[0] += 8;
case 40 ... 47:
pty->bg = code[0] - 40;
pty->pr |= kMachinePtyBg;
pty->pr &= ~kMachinePtyTrue;
break;
case 48:
t = kSgrBg;
break;
case 49:
pty->pr &= kMachinePtyBg;
break;
default:
break;
}
break;
case kSgrFg:
case kSgrBg:
switch (code[0]) {
case 2:
case 5:
t += code[0];
break;
default:
t = kSgr;
break;
}
break;
case kSgrFgTrue:
if (++code[3] == 3) {
code[3] = 0;
t = kSgr;
pty->fg = READ32LE(code);
pty->pr |= kMachinePtyFg;
pty->pr |= kMachinePtyTrue;
}
break;
case kSgrBgTrue:
if (++code[3] == 3) {
code[3] = 0;
t = kSgr;
pty->bg = READ32LE(code);
pty->pr |= kMachinePtyBg;
pty->pr |= kMachinePtyTrue;
}
break;
case kSgrFgXterm:
t = kSgr;
pty->fg = code[0];
pty->pr |= kMachinePtyFg;
pty->pr &= ~kMachinePtyTrue;
break;
case kSgrBgXterm:
t = kSgr;
pty->bg = code[0];
pty->pr |= kMachinePtyBg;
pty->pr &= ~kMachinePtyTrue;
break;
default:
abort();
}
break;
default:
break;
}
}
}
static void MachinePtyHideCursor(struct MachinePty *pty) {
pty->conf |= kMachinePtyNocursor;
}
static void MachinePtyShowCursor(struct MachinePty *pty) {
pty->conf &= ~kMachinePtyNocursor;
}
static void MachinePtyCsi(struct MachinePty *pty) {
switch (pty->esc.s[pty->esc.i - 1]) {
case 'A':
MachinePtyCursorMove(pty, -1, +0);
break;
case 'B':
MachinePtyCursorMove(pty, +1, +0);
break;
case 'C':
MachinePtyCursorMove(pty, +0, +1);
break;
case 'D':
MachinePtyCursorMove(pty, +0, -1);
break;
case 'f':
case 'H':
MachinePtyCursorPosition(pty);
break;
case 'J':
MachinePtyEraseDisplay(pty);
break;
case 'K':
MachinePtyEraseLine(pty);
break;
case 'm':
MachinePtySelectGraphicsRendition(pty);
break;
case 'l':
if (strcmp(pty->esc.s, "?25l") == 0) {
MachinePtyHideCursor(pty);
}
break;
case 'h':
if (strcmp(pty->esc.s, "?25h") == 0) {
MachinePtyShowCursor(pty);
}
break;
default:
break;
}
}
static void MachinePtyEsc(struct MachinePty *pty) {
}
static void MachinePtyEscAppend(struct MachinePty *pty, char c) {
pty->esc.i = MIN(pty->esc.i + 1, ARRAYLEN(pty->esc.s) - 1);
pty->esc.s[pty->esc.i - 1] = c;
pty->esc.s[pty->esc.i - 0] = '\0';
}
ssize_t MachinePtyWrite(struct MachinePty *pty, const void *data, size_t n) {
int i;
const uint8_t *p;
for (p = data, i = 0; i < n; ++i) {
switch (pty->state) {
case kMachinePtyAscii:
if (p[i] < 0b10000000) {
switch (p[i]) {
case '\e':
pty->state = kMachinePtyEsc;
pty->esc.i = 0;
break;
case '\t':
MachinePtyTab(pty);
break;
case '\r':
pty->x = 0;
break;
case '\n':
MachinePtyNewline(pty);
break;
default:
SetMachinePtyCell(pty, p[i]);
break;
}
} else if (!ThomPikeCont(p[i])) {
pty->state = kMachinePtyUtf8;
pty->u8 = ThomPikeByte(p[i]);
}
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;
}
break;
case kMachinePtyEsc:
if (p[i] == '[') {
pty->state = kMachinePtyCsi;
} else if (0x30 <= p[i] && p[i] <= 0x7e) {
MachinePtyEscAppend(pty, p[i]);
MachinePtyEsc(pty);
pty->state = kMachinePtyAscii;
} else if (0x20 <= p[i] && p[i] <= 0x2f) {
MachinePtyEscAppend(pty, p[i]);
} else {
pty->state = kMachinePtyAscii;
}
break;
case kMachinePtyCsi:
MachinePtyEscAppend(pty, p[i]);
switch (p[i]) {
case ':':
case ';':
case '<':
case '=':
case '>':
case '?':
case '0' ... '9':
break;
case '`':
case '~':
case '^':
case '@':
case '[':
case ']':
case '{':
case '}':
case '_':
case '|':
case '\\':
case 'A' ... 'Z':
case 'a' ... 'z':
MachinePtyCsi(pty);
pty->state = kMachinePtyAscii;
break;
default:
pty->state = kMachinePtyAscii;
continue;
}
break;
default:
abort();
}
}
if (pty->u8) {
SetMachinePtyCell(pty, pty->u8);
}
return n;
}
void MachinePtyAppendLine(struct MachinePty *pty, struct Buffer *buf,
unsigned y) {
uint32_t x, i, fg, bg, pr, wc, w;
CHECK_LT(y, pty->yn);
for (fg = bg = pr = x = 0; x < pty->xn; x += w) {
i = y * pty->xn + x;
wc = pty->wcs[i];
w = MAX(0, wcwidth(wc));
if (w) {
if (pty->prs[i] != pr || pty->fgs[i] != fg || pty->bgs[i] != bg) {
fg = pty->fgs[i];
bg = pty->bgs[i];
pr = pty->prs[i];
AppendStr(buf, "\e[0");
if (pr & kMachinePtyBold) AppendStr(buf, ";1");
if (pr & kMachinePtyFaint) AppendStr(buf, ";2");
if (pr & kMachinePtyFlip) AppendStr(buf, ";7");
if (pr & kMachinePtyFg) {
if (pr & kMachinePtyTrue) {
AppendFmt(buf, ";38;2;%d;%d;%d", (fg & 0x0000ff) >> 000,
(fg & 0x00ff00) >> 010, (fg & 0xff0000) >> 020);
} else {
AppendFmt(buf, ";38;5;%d", fg);
}
}
if (pr & kMachinePtyBg) {
if (pr & kMachinePtyTrue) {
AppendFmt(buf, ";48;2;%d;%d;%d", (bg & 0x0000ff) >> 000,
(bg & 0x00ff00) >> 010, (bg & 0xff0000) >> 020);
} else {
AppendFmt(buf, ";48;5;%d", bg);
}
}
AppendStr(buf, "m");
}
AppendWide(buf, wc);
} else {
w = 1;
if (y == pty->y && x == pty->x) {
if (!(pty->conf & kMachinePtyNocursor)) {
AppendStr(buf, "\e[5m▂\e[25m");
}
} else {
AppendChar(buf, ' ');
}
}
}
AppendStr(buf, "\e[0m");
}

50
tool/build/lib/pty.h Normal file
View file

@ -0,0 +1,50 @@
#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_PTY_H_
#define COSMOPOLITAN_TOOL_BUILD_LIB_PTY_H_
#include "tool/build/lib/buffer.h"
#define kMachinePtyFg 0x01
#define kMachinePtyBg 0x02
#define kMachinePtyTrue 0x04
#define kMachinePtyBold 0x08
#define kMachinePtyFaint 0x10
#define kMachinePtyFlip 0x20
#define kMachinePtyNocursor 0x01
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
struct MachinePty {
uint32_t yn;
uint32_t xn;
uint32_t y;
uint32_t x;
uint32_t pr;
uint32_t fg;
uint32_t bg;
uint32_t u8;
uint32_t *wcs;
uint32_t *fgs;
uint32_t *bgs;
uint32_t *prs;
uint32_t conf;
enum MachinePtyState {
kMachinePtyAscii,
kMachinePtyUtf8,
kMachinePtyEsc,
kMachinePtyCsi,
} state;
struct MachinePtyEsc {
unsigned i;
char s[64];
} esc;
};
struct MachinePty *MachinePtyNew(unsigned, unsigned) nodiscard;
void MachinePtyFree(struct MachinePty *);
ssize_t MachinePtyWrite(struct MachinePty *, const void *, size_t);
void MachinePtyAppendLine(struct MachinePty *, struct Buffer *, unsigned);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_PTY_H_ */

View file

@ -17,8 +17,10 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/calls.h"
#include "libc/macros.h"
#include "libc/math.h"
#include "libc/mem/mem.h"
#include "libc/str/str.h"
#include "tool/build/lib/flags.h"
#include "tool/build/lib/machine.h"
@ -61,8 +63,25 @@ static void ResetSse(struct Machine *m) {
memset(m->xmmtype, 0, sizeof(m->xmmtype));
}
static void ResetTlb(struct Machine *m) {
m->tlbindex = 0;
memset(m->tlb, 0, sizeof(m->tlb));
}
static void ResetMem(struct Machine *m) {
FreePml4t(m->cr3, -0x800000000000, 0x800000000000, free, munmap);
}
void ResetCpu(struct Machine *m) {
InitMachine(m);
m->codevirt = 0;
m->codereal = NULL;
m->faultaddr = 0;
m->stashsize = 0;
m->stashaddr = 0;
m->writeaddr = 0;
m->readaddr = 0;
m->writesize = 0;
m->readsize = 0;
m->flags = SetFlag(m->flags, FLAGS_DF, false);
m->flags = SetFlag(m->flags, FLAGS_CF, false);
m->flags = SetFlag(m->flags, FLAGS_ZF, false);
@ -73,6 +92,9 @@ void ResetCpu(struct Machine *m) {
m->flags = SetFlag(m->flags, FLAGS_IOPL, 3);
memset(m->reg, 0, sizeof(m->reg));
memset(m->bofram, 0, sizeof(m->bofram));
memset(&m->freelist, 0, sizeof(m->freelist));
ResetTlb(m);
ResetSse(m);
ResetFpu(m);
ResetMem(m);
}

View file

@ -114,19 +114,19 @@ union MachineVector {
uint64_t u64[2];
};
void OpSse(struct Machine *m, enum OpSseKernel kernel) {
void OpSse(struct Machine *m, uint32_t rde, enum OpSseKernel kernel) {
int i;
uint8_t *p;
union MachineVector x, y, t;
p = GetModrmRegisterXmmPointerRead16(m);
if (Osz(m->xedd)) {
p = GetModrmRegisterXmmPointerRead16(m, rde);
if (Osz(rde)) {
memcpy(&y, p, 16);
} else {
memset(&t, 0, 16);
memcpy(&t, p, 8);
memcpy(&y, &t, 16);
}
memcpy(&x, XmmRexrReg(m), 16);
memcpy(&x, XmmRexrReg(m, rde), 16);
switch (kernel) {
CASE(kOpSsePsubb, psubb(x.i8, x.i8, y.i8));
CASE(kOpSsePaddb, paddb(x.i8, x.i8, y.i8));
@ -204,18 +204,18 @@ void OpSse(struct Machine *m, enum OpSseKernel kernel) {
default:
unreachable;
}
if (Osz(m->xedd)) {
memcpy(XmmRexrReg(m), &x, 16);
if (Osz(rde)) {
memcpy(XmmRexrReg(m, rde), &x, 16);
} else {
memcpy(XmmRexrReg(m), &x, 8);
memcpy(XmmRexrReg(m, rde), &x, 8);
}
}
void OpSseUdqIb(struct Machine *m, enum OpSseUdqIbKernel kernel) {
void OpSseUdqIb(struct Machine *m, uint32_t rde, enum OpSseUdqIbKernel kernel) {
uint8_t i;
union MachineVector x;
i = m->xedd->op.uimm0;
memcpy(&x, XmmRexbRm(m), 16);
memcpy(&x, XmmRexbRm(m, rde), 16);
switch (kernel) {
CASE(kOpSseUdqIbPsrlw, (psrlw)(x.u16, x.u16, i));
CASE(kOpSseUdqIbPsraw, (psraw)(x.i16, x.i16, i));
@ -230,26 +230,26 @@ void OpSseUdqIb(struct Machine *m, enum OpSseUdqIbKernel kernel) {
default:
unreachable;
}
if (Osz(m->xedd)) {
memcpy(XmmRexbRm(m), &x, 16);
if (Osz(rde)) {
memcpy(XmmRexbRm(m, rde), &x, 16);
} else {
memcpy(XmmRexbRm(m), &x, 8);
memcpy(XmmRexbRm(m, rde), &x, 8);
}
}
static void OpSsePalignrMmx(struct Machine *m) {
static void OpSsePalignrMmx(struct Machine *m, uint32_t rde) {
char t[24];
memcpy(t, GetModrmRegisterXmmPointerRead8(m), 8);
memcpy(t + 8, XmmRexrReg(m), 8);
memcpy(t, GetModrmRegisterXmmPointerRead8(m, rde), 8);
memcpy(t + 8, XmmRexrReg(m, rde), 8);
memset(t + 16, 0, 8);
memcpy(XmmRexrReg(m), t + MIN(m->xedd->op.uimm0, 16), 8);
memcpy(XmmRexrReg(m, rde), t + MIN(m->xedd->op.uimm0, 16), 8);
}
void OpSsePalignr(struct Machine *m) {
if (Osz(m->xedd)) {
palignr(XmmRexrReg(m), XmmRexrReg(m), GetModrmRegisterXmmPointerRead8(m),
m->xedd->op.uimm0);
void OpSsePalignr(struct Machine *m, uint32_t rde) {
if (Osz(rde)) {
palignr(XmmRexrReg(m, rde), XmmRexrReg(m, rde),
GetModrmRegisterXmmPointerRead8(m, rde), m->xedd->op.uimm0);
} else {
OpSsePalignrMmx(m);
OpSsePalignrMmx(m, rde);
}
}

View file

@ -93,9 +93,9 @@ enum OpSseUdqIbKernel {
kOpSseUdqIbPslldq,
};
void OpSse(struct Machine *, enum OpSseKernel);
void OpSseUdqIb(struct Machine *, enum OpSseUdqIbKernel);
void OpSsePalignr(struct Machine *);
void OpSse(struct Machine *, uint32_t, enum OpSseKernel);
void OpSseUdqIb(struct Machine *, uint32_t, enum OpSseUdqIbKernel);
void OpSsePalignr(struct Machine *, uint32_t);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View file

@ -76,12 +76,12 @@ void OpCallJvds(struct Machine *m) {
OpCall(m, m->ip + m->xedd->op.disp);
}
void OpCallEq(struct Machine *m) {
void OpCallEq(struct Machine *m, uint32_t rde) {
void *p[2];
uint8_t b[8];
OpCall(m, Read64(IsModrmRegister(m->xedd)
? RegRexbRm(m)
: AccessRam(m, ComputeAddress(m), 8, p, b, true)));
OpCall(m, Read64(IsModrmRegister(rde)
? RegRexbRm(m, rde)
: AccessRam(m, ComputeAddress(m, rde), 8, p, b, true)));
}
void OpLeave(struct Machine *m) {
@ -93,10 +93,20 @@ void OpRet(struct Machine *m, uint16_t n) {
m->ip = Pop64(m, n);
}
void PushOsz(struct Machine *m, uint64_t x) {
if (!Osz(m->xedd)) {
void PushOsz(struct Machine *m, uint32_t rde, uint64_t x) {
if (!Osz(rde)) {
Push64(m, x);
} else {
Push16(m, x);
}
}
void OpBofram(struct Machine *m) {
if (m->xedd->op.disp) {
m->bofram[0] = m->ip;
m->bofram[1] = m->ip + (m->xedd->op.disp & 0xff);
} else {
m->bofram[0] = 0;
m->bofram[1] = 0;
}
}

View file

@ -11,8 +11,9 @@ uint16_t Pop16(struct Machine *, uint16_t);
void OpCallJvds(struct Machine *);
void OpRet(struct Machine *, uint16_t);
void OpLeave(struct Machine *);
void PushOsz(struct Machine *, uint64_t);
void OpCallEq(struct Machine *);
void PushOsz(struct Machine *, uint32_t, uint64_t);
void OpCallEq(struct Machine *, uint32_t);
void OpBofram(struct Machine *);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View file

@ -65,7 +65,7 @@ static void WriteInt(uint8_t p[8], uint64_t x, unsigned long w) {
}
}
void OpString(struct Machine *m, int op) {
void OpString(struct Machine *m, uint32_t rde, int op) {
void *p[2];
bool compare;
int64_t sgn, v;
@ -73,12 +73,12 @@ void OpString(struct Machine *m, int op) {
unsigned n, lg2;
uint64_t asz, seg;
sgn = GetFlag(m->flags, FLAGS_DF) ? -1 : 1;
asz = Asz(m->xedd) ? 0xffffffff : 0xffffffffffffffff;
asz = Asz(rde) ? 0xffffffff : 0xffffffffffffffff;
seg = GetSegment(m);
lg2 = RegLog2(m->xedd);
lg2 = RegLog2(rde);
n = 1 << lg2;
for (;;) {
if (Rep(m->xedd) && !Read64(m->cx)) break;
if (Rep(rde) && !Read64(m->cx)) break;
v = 0;
*p = NULL;
compare = false;
@ -125,16 +125,16 @@ void OpString(struct Machine *m, int op) {
abort();
}
EndStore(m, v, n, p, s[0]);
if (!Rep(m->xedd)) break;
if (!Rep(rde)) break;
Write64(m->cx, Read64(m->cx) - 1);
if (compare) {
if (Rep(m->xedd) == 2 && GetFlag(m->flags, FLAGS_ZF)) break;
if (Rep(m->xedd) == 3 && !GetFlag(m->flags, FLAGS_ZF)) break;
if (Rep(rde) == 2 && GetFlag(m->flags, FLAGS_ZF)) break;
if (Rep(rde) == 3 && !GetFlag(m->flags, FLAGS_ZF)) break;
}
}
}
void OpRepMovsbEnhanced(struct Machine *m) {
void OpRepMovsbEnhanced(struct Machine *m, uint32_t rde) {
bool failed;
uint8_t *direal, *sireal;
unsigned diremain, siremain, i, n;
@ -143,7 +143,7 @@ void OpRepMovsbEnhanced(struct Machine *m) {
failed = false;
failaddr = 0;
seg = GetSegment(m);
asz = Asz(m->xedd) ? 0xffffffff : 0xffffffffffffffff;
asz = Asz(rde) ? 0xffffffff : 0xffffffffffffffff;
divirtual = Read64(m->di) & asz;
sivirtual = Read64(m->si) & asz;
SetWriteAddr(m, (seg + divirtual) & asz, cx);
@ -177,7 +177,7 @@ void OpRepMovsbEnhanced(struct Machine *m) {
if (failed) ThrowSegmentationFault(m, failaddr);
}
void OpRepStosbEnhanced(struct Machine *m) {
void OpRepStosbEnhanced(struct Machine *m, uint32_t rde) {
bool failed;
uint8_t *direal, al;
unsigned diremain, i, n;
@ -187,7 +187,7 @@ void OpRepStosbEnhanced(struct Machine *m) {
failed = false;
al = Read8(m->ax);
seg = GetSegment(m);
asz = Asz(m->xedd) ? 0xffffffff : 0xffffffffffffffff;
asz = Asz(rde) ? 0xffffffff : 0xffffffffffffffff;
divirtual = Read64(m->di) & asz;
SetWriteAddr(m, (seg + divirtual) & asz, cx);
do {
@ -210,18 +210,18 @@ void OpRepStosbEnhanced(struct Machine *m) {
if (failed) ThrowSegmentationFault(m, failaddr);
}
void OpMovsb(struct Machine *m) {
if (Rep(m->xedd) && !GetFlag(m->flags, FLAGS_DF)) {
OpRepMovsbEnhanced(m);
void OpMovsb(struct Machine *m, uint32_t rde) {
if (Rep(rde) && !GetFlag(m->flags, FLAGS_DF)) {
OpRepMovsbEnhanced(m, rde);
} else {
OpString(m, STRING_MOVS);
OpString(m, rde, STRING_MOVS);
}
}
void OpStosb(struct Machine *m) {
if (Rep(m->xedd) && !GetFlag(m->flags, FLAGS_DF)) {
OpRepStosbEnhanced(m);
void OpStosb(struct Machine *m, uint32_t rde) {
if (Rep(rde) && !GetFlag(m->flags, FLAGS_DF)) {
OpRepStosbEnhanced(m, rde);
} else {
OpString(m, STRING_STOS);
OpString(m, rde, STRING_STOS);
}
}

View file

@ -13,9 +13,9 @@
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
void OpString(struct Machine *, int);
void OpMovsb(struct Machine *);
void OpStosb(struct Machine *);
void OpString(struct Machine *, uint32_t, int);
void OpMovsb(struct Machine *, uint32_t);
void OpStosb(struct Machine *, uint32_t);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View file

@ -46,6 +46,7 @@
#include "libc/sysv/errfuns.h"
#include "libc/time/struct/timezone.h"
#include "libc/time/time.h"
#include "libc/x/x.h"
#include "tool/build/lib/case.h"
#include "tool/build/lib/endian.h"
#include "tool/build/lib/machine.h"
@ -65,6 +66,12 @@
#define P(x) ((x) ? PNN(x) : 0)
#define ASSIGN(D, S) memcpy(&D, &S, MIN(sizeof(S), sizeof(D)))
static const struct MachineFdCb kMachineFdCbHost = {
.close = close,
.read = read,
.write = write,
};
static int XlatSignal(int sig) {
switch (sig) {
XLAT(1, SIGHUP);
@ -188,9 +195,15 @@ static int XlatTcp(int x) {
}
}
static int XlatAfd(int x) {
if (x == AT_FDCWD_LINUX) x = AT_FDCWD;
return x;
static int XlatFd(struct Machine *m, int fd) {
if (!(0 <= fd && fd < m->fds.i)) return ebadf();
if (!m->fds.p[fd].cb) return ebadf();
return m->fds.p[fd].fd;
}
static int XlatAfd(struct Machine *m, int fd) {
if (fd == AT_FDCWD_LINUX) return AT_FDCWD;
return XlatFd(m, fd);
}
static int XlatAtf(int x) {
@ -264,6 +277,7 @@ static int64_t OpMmap(struct Machine *m, int64_t virt, size_t size, int prot,
int flags, int fd, int64_t off) {
void *real;
flags = XlatMapFlags(flags);
if (fd != -1 && (fd = XlatFd(m, fd)) == -1) return -1;
real = mmap(NULL, size, prot, flags & ~MAP_FIXED, fd, off);
if (real == MAP_FAILED) return -1;
if (!(flags & MAP_FIXED)) {
@ -297,19 +311,70 @@ static void *GetDirectBuf(struct Machine *m, int64_t addr, size_t *size) {
return page;
}
static int OpClose(struct Machine *m, int fd) {
int rc;
struct FdClosed *closed;
if (!(0 <= fd && fd < m->fds.i)) return ebadf();
if (!m->fds.p[fd].cb) return ebadf();
rc = m->fds.p[fd].cb->close(m->fds.p[fd].fd);
MachineFdRemove(&m->fds, fd);
return rc;
}
static int OpOpenat(struct Machine *m, int dirfd, int64_t path, int flags,
int mode) {
int fd, i;
flags = XlatOpenFlags(flags);
if ((dirfd = XlatAfd(m, dirfd)) == -1) return -1;
if ((i = MachineFdAdd(&m->fds)) == -1) return -1;
if ((fd = openat(dirfd, LoadStr(m, path), flags, mode)) != -1) {
m->fds.p[i].cb = &kMachineFdCbHost;
m->fds.p[i].fd = fd;
fd = i;
} else {
MachineFdRemove(&m->fds, i);
}
return fd;
}
static int OpPipe(struct Machine *m, int64_t pipefds_addr) {
void *p[2];
uint8_t b[8];
int rc, i, j, *pipefds;
if ((i = MachineFdAdd(&m->fds)) == -1) return -1;
if ((j = MachineFdAdd(&m->fds)) == -1) return -1;
if ((rc = pipe((pipefds = BeginStoreNp(m, pipefds_addr, 8, p, b)))) != -1) {
EndStoreNp(m, pipefds_addr, 8, p, b);
m->fds.p[i].cb = &kMachineFdCbHost;
m->fds.p[i].fd = pipefds[0];
m->fds.p[j].cb = &kMachineFdCbHost;
m->fds.p[j].fd = pipefds[1];
} else {
MachineFdRemove(&m->fds, i);
MachineFdRemove(&m->fds, j);
}
return rc;
}
static ssize_t OpRead(struct Machine *m, int fd, int64_t addr, size_t size) {
void *data;
ssize_t rc;
if (!(0 <= fd && fd < m->fds.i) || !m->fds.p[fd].cb) return ebadf();
if ((data = GetDirectBuf(m, addr, &size)) == MAP_FAILED) return efault();
if ((rc = read(fd, data, size)) != -1) SetWriteAddr(m, addr, rc);
if ((rc = m->fds.p[fd].cb->read(m->fds.p[fd].fd, data, size)) != -1) {
SetWriteAddr(m, addr, rc);
}
return rc;
}
static ssize_t OpWrite(struct Machine *m, int fd, int64_t addr, size_t size) {
void *data;
ssize_t rc;
if (!(0 <= fd && fd < m->fds.i) || !m->fds.p[fd].cb) return ebadf();
if ((data = GetDirectBuf(m, addr, &size)) == MAP_FAILED) return efault();
if ((rc = write(fd, data, size)) != -1) SetReadAddr(m, addr, size);
if ((rc = m->fds.p[fd].cb->write(m->fds.p[fd].fd, data, size)) != -1) {
SetReadAddr(m, addr, size);
}
return rc;
}
@ -317,6 +382,7 @@ static ssize_t OpPread(struct Machine *m, int fd, int64_t addr, size_t size,
int64_t offset) {
void *data;
ssize_t rc;
if ((fd = XlatFd(m, fd)) == -1) return -1;
if ((data = GetDirectBuf(m, addr, &size)) == MAP_FAILED) return efault();
if ((rc = pread(fd, data, size, offset)) != -1) SetWriteAddr(m, addr, rc);
return rc;
@ -326,20 +392,31 @@ static ssize_t OpPwrite(struct Machine *m, int fd, int64_t addr, size_t size,
int64_t offset) {
void *data;
ssize_t rc;
if ((fd = XlatFd(m, fd)) == -1) return -1;
if ((data = GetDirectBuf(m, addr, &size)) == MAP_FAILED) return efault();
if ((rc = pwrite(fd, data, size, offset)) != -1) SetReadAddr(m, addr, size);
return rc;
}
static int OpFaccessat(struct Machine *m, int dirfd, int64_t path, int mode,
int flags) {
flags = XlatAtf(flags);
mode = XlatAccess(mode);
if ((dirfd = XlatAfd(m, dirfd)) == -1) return -1;
return faccessat(dirfd, LoadStr(m, path), mode, flags);
}
static int OpFstatat(struct Machine *m, int dirfd, int64_t path, int64_t st,
int flags) {
int rc;
void *stp[2];
uint8_t *stbuf;
flags = XlatAtf(flags);
if ((dirfd = XlatAfd(m, dirfd)) == -1) return -1;
if (!(stbuf = malloc(sizeof(struct stat)))) return enomem();
if ((rc = fstatat(XlatAfd(dirfd), LoadStr(m, path),
BeginStoreNp(m, st, sizeof(stbuf), stp, stbuf),
XlatAtf(flags))) != -1) {
if ((rc = fstatat(dirfd, LoadStr(m, path),
BeginStoreNp(m, st, sizeof(stbuf), stp, stbuf), flags)) !=
-1) {
EndStoreNp(m, st, sizeof(stbuf), stp, stbuf);
}
free(stbuf);
@ -350,6 +427,7 @@ static int OpFstat(struct Machine *m, int fd, int64_t st) {
int rc;
void *stp[2];
uint8_t *stbuf;
if ((fd = XlatFd(m, fd)) == -1) return -1;
if (!(stbuf = malloc(sizeof(struct stat)))) return enomem();
if ((rc = fstat(fd, BeginStoreNp(m, st, sizeof(stbuf), stp, stbuf))) != -1) {
EndStoreNp(m, st, sizeof(stbuf), stp, stbuf);
@ -358,17 +436,6 @@ static int OpFstat(struct Machine *m, int fd, int64_t st) {
return rc;
}
static int OpOpenat(struct Machine *m, int dirfd, int64_t path, int flags,
int mode) {
return openat(XlatAfd(dirfd), LoadStr(m, path), XlatOpenFlags(flags), mode);
}
static int OpFaccessat(struct Machine *m, int dirfd, int64_t path, int mode,
int flags) {
return faccessat(XlatAfd(dirfd), LoadStr(m, path), XlatAccess(mode),
XlatAtf(flags));
}
static int OpChdir(struct Machine *m, int64_t path) {
return chdir(LoadStr(m, path));
}
@ -449,16 +516,6 @@ static int OpSigaction(struct Machine *m, int sig, int64_t act, int64_t old) {
return rc;
}
static int OpPipe(struct Machine *m, int64_t pipefds_addr) {
int rc;
void *p[2];
uint8_t b[8];
if ((rc = pipe(BeginStoreNp(m, pipefds_addr, 8, p, b))) != -1) {
EndStoreNp(m, pipefds_addr, 8, p, b);
}
return rc;
}
static int OpNanosleep(struct Machine *m, int64_t req, int64_t rem) {
int rc;
void *p[2];
@ -536,7 +593,7 @@ void OpSyscall(struct Machine *m) {
SYSCALL(0x000, OpRead(m, di, si, dx));
SYSCALL(0x001, OpWrite(m, di, si, dx));
SYSCALL(0x002, DoOpen(m, di, si, dx));
SYSCALL(0x003, close(di));
SYSCALL(0x003, OpClose(m, di));
SYSCALL(0x004, DoStat(m, di, si));
SYSCALL(0x005, OpFstat(m, di, si));
SYSCALL(0x006, DoLstat(m, di, si));
@ -624,16 +681,16 @@ void OpSyscall(struct Machine *m) {
SYSCALL(0x0DD, fadvise(di, si, dx, r0));
SYSCALL(0x0E4, OpClockGettime(m, di, si));
SYSCALL(0x101, OpOpenat(m, di, si, dx, r0));
SYSCALL(0x102, mkdirat(XlatAfd(di), P(si), dx));
SYSCALL(0x104, fchownat(XlatAfd(di), P(si), dx, r0, XlatAtf(r8)));
SYSCALL(0x105, futimesat(XlatAfd(di), P(si), P(dx)));
SYSCALL(0x102, mkdirat(XlatAfd(m, di), P(si), dx));
SYSCALL(0x104, fchownat(XlatAfd(m, di), P(si), dx, r0, XlatAtf(r8)));
SYSCALL(0x105, futimesat(XlatAfd(m, di), P(si), P(dx)));
SYSCALL(0x106, OpFstatat(m, di, si, dx, r0));
SYSCALL(0x107, unlinkat(XlatAfd(di), P(si), XlatAtf(dx)));
SYSCALL(0x108, renameat(XlatAfd(di), P(si), XlatAfd(dx), P(r0)));
SYSCALL(0x107, unlinkat(XlatAfd(m, di), P(si), XlatAtf(dx)));
SYSCALL(0x108, renameat(XlatAfd(m, di), P(si), XlatAfd(m, dx), P(r0)));
SYSCALL(0x10D, OpFaccessat(m, di, si, dx, r0));
SYSCALL(0x113, splice(di, P(si), dx, P(r0), r8, XlatAtf(r9)));
SYSCALL(0x115, sync_file_range(di, si, dx, XlatAtf(r0)));
SYSCALL(0x118, utimensat(XlatAfd(di), P(si), P(dx), XlatAtf(r0)));
SYSCALL(0x118, utimensat(XlatAfd(m, di), P(si), P(dx), XlatAtf(r0)));
SYSCALL(0x177, vmsplice(di, P(si), dx, r0));
CASE(0xE7, HaltMachine(m, di | 0x100));
default:

View file

@ -4,8 +4,6 @@
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
enum MachineStatus;
void OpSyscall(struct Machine *);
COSMOPOLITAN_C_END_

40
tool/build/lib/time.c Normal file
View file

@ -0,0 +1,40 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/nexgen32e/rdtsc.h"
#include "libc/sysv/consts/clock.h"
#include "libc/time/time.h"
#include "tool/build/lib/endian.h"
#include "tool/build/lib/time.h"
/**
* I am the timelorde.
*/
void OpRdtsc(struct Machine *m) {
uint64_t c;
#ifdef __x86_64__
c = rdtsc();
#else
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
c = ts.tv_sec * 1000000000 + ts.tv_nsec;
#endif
Write64(m->ax, (c >> 000) & 0xffffffff);
Write64(m->dx, (c >> 040) & 0xffffffff);
}

11
tool/build/lib/time.h Normal file
View file

@ -0,0 +1,11 @@
#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_TIME_H_
#define COSMOPOLITAN_TOOL_BUILD_LIB_TIME_H_
#include "tool/build/lib/machine.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
void OpRdtsc(struct Machine *);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_TIME_H_ */