mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-28 13:30:29 +00:00
Add pseudoteletypewriter to emulator
https://justine.storage.googleapis.com/emulator628.mp4
This commit is contained in:
parent
e86cff8ba0
commit
5aabacb361
94 changed files with 3245 additions and 2179 deletions
|
@ -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 *);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) */
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
55
tool/build/lib/fds.c
Normal 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
27
tool/build/lib/fds.h
Normal 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_ */
|
|
@ -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:
|
||||
|
|
|
@ -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) */
|
||||
|
|
|
@ -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
|
@ -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 *);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
512
tool/build/lib/pty.c
Normal 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
50
tool/build/lib/pty.h
Normal 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_ */
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) */
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
40
tool/build/lib/time.c
Normal 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
11
tool/build/lib/time.h
Normal 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_ */
|
Loading…
Add table
Add a link
Reference in a new issue