mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-08 04:08:32 +00:00
Fix bugs and have emulator emulate itself
This commit is contained in:
parent
5aabacb361
commit
bd29223891
111 changed files with 1283 additions and 2073 deletions
|
@ -17,7 +17,7 @@ M(1, i, "!", LogicalNot, !x, "logical not")
|
|||
M(2, i, "||", LogicalOr, x || y, "logical or")
|
||||
M(2, i, "&&", LogicalAnd, x &&y, "logical and")
|
||||
|
||||
M(2, g, "=", Equal1, x == y && fpclassify(x) == fpclassify(y), "equal to")
|
||||
M(2, g, "=", Equal1, x == y, "equal to")
|
||||
M(2, g, "!=", Notequal, x != y, "not equal to")
|
||||
M(2, g, "<", LessThan, x < y, "less than")
|
||||
M(2, g, ">", GreaterThan, x > y, "greater than")
|
||||
|
|
|
@ -28,7 +28,7 @@ static void Print(uint8_t c) {
|
|||
int main(int argc, char *argv[]) {
|
||||
int i;
|
||||
#ifdef DISINGENUOUS
|
||||
for (i = 0; i < 1400 * 1000 * 1000 / 3; ++i) asm("nop");
|
||||
for (i = 0; i < 100 * 1000 * 1000 / 3; ++i) asm("nop");
|
||||
#else
|
||||
size_t size;
|
||||
struct MetalSha256Ctx ctx;
|
||||
|
|
|
@ -9,4 +9,4 @@ TOOL_BUILD_EMUCRT = \
|
|||
|
||||
.PHONY: o/$(MODE)/tool/build/emucrt
|
||||
o/$(MODE)/tool/build/emucrt: \
|
||||
o/$(MODE)/tool/build/emucrt/emucrt.o
|
||||
$(TOOL_BUILD_EMUCRT)
|
||||
|
|
|
@ -105,17 +105,15 @@ ARGUMENTS\n\
|
|||
\n\
|
||||
PERFORMANCE\n\
|
||||
\n\
|
||||
1500 MIPS w/ NOP loop\n\
|
||||
1000 MIPS w/ NOP loop\n\
|
||||
Over 9000 MIPS w/ SIMD & Algorithms\n\
|
||||
\n\
|
||||
PROTIP\n\
|
||||
\n\
|
||||
Fix SSH keyboard latency for debugger TUI in CONTINUE mode:\n\
|
||||
\n\
|
||||
sudo sh -c 'echo -n 8192 >/proc/sys/net/core/rmem_default'\n\
|
||||
sudo sh -c 'echo -n 8192 >/proc/sys/net/core/wmem_default'\n\
|
||||
\n\
|
||||
COMPLETENESS\n\
|
||||
\n\
|
||||
Long user mode is supported in addition to SSE3 and SSSE3.\n\
|
||||
Integer ops are implemented rigorously with lots of tests.\n\
|
||||
Floating point instructions are yolo, and tunable more so.\n\
|
||||
Loading, virtual memory management, and syscall need work.\n\
|
||||
\n"
|
||||
|
||||
#define DUMPWIDTH 64
|
||||
|
@ -274,7 +272,6 @@ static uint8_t CycleSseWidth(uint8_t w) {
|
|||
}
|
||||
|
||||
static void OnBusted(void) {
|
||||
LOGF("OnBusted");
|
||||
CHECK(onbusted);
|
||||
longjmp(onbusted, 1);
|
||||
}
|
||||
|
@ -621,15 +618,10 @@ static void DrawTerminal(struct Panel *p) {
|
|||
}
|
||||
}
|
||||
|
||||
static void DrawFlag(struct Panel *p, long i, char *name, bool value,
|
||||
bool previous) {
|
||||
AppendPanel(p, i, " ");
|
||||
if (value) {
|
||||
AppendPanel(p, i, name);
|
||||
} else {
|
||||
AppendPanel(p, i, " ");
|
||||
}
|
||||
AppendPanel(p, i, " ");
|
||||
static void DrawFlag(struct Panel *p, long i, char name, bool value) {
|
||||
char str[] = " ";
|
||||
if (value) str[1] = name;
|
||||
AppendPanel(p, i, str);
|
||||
}
|
||||
|
||||
static void DrawRegister(struct Panel *p, long i, long r) {
|
||||
|
@ -649,13 +641,12 @@ static void DrawRegister(struct Panel *p, long i, long r) {
|
|||
|
||||
static void DrawSt(struct Panel *p, long i, long r) {
|
||||
char buf[32];
|
||||
long double value;
|
||||
bool isempty, changed;
|
||||
long double value, previous;
|
||||
isempty = FpuGetTag(m, r) == kFpuTagEmpty;
|
||||
if (isempty) AppendPanel(p, i, "\e[2m");
|
||||
value = *FpuSt(&m[0], r);
|
||||
previous = *FpuSt(&m[1], r);
|
||||
changed = value != previous;
|
||||
value = m[0].fpu.st[(r + m[0].fpu.sp) & 0b111];
|
||||
changed = value != m[1].fpu.st[(r + m[0].fpu.sp) & 0b111];
|
||||
if (!isempty && changed) AppendPanel(p, i, "\e[7m");
|
||||
snprintf(buf, sizeof(buf), "ST%d ", r);
|
||||
AppendPanel(p, i, buf);
|
||||
|
@ -689,20 +680,27 @@ static void DrawCpu(struct Panel *p) {
|
|||
DrawRegister(p, 7, 11), DrawRegister(p, 7, 15), DrawSt(p, 7, 7);
|
||||
snprintf(buf, sizeof(buf), "RIP 0x%016x FLG", m[0].ip);
|
||||
AppendPanel(p, 8, buf);
|
||||
DrawFlag(p, 8, "C", GetFlag(m[0].flags, FLAGS_CF),
|
||||
GetFlag(m[1].flags, FLAGS_CF));
|
||||
DrawFlag(p, 8, "Z", GetFlag(m[0].flags, FLAGS_ZF),
|
||||
GetFlag(m[1].flags, FLAGS_ZF));
|
||||
DrawFlag(p, 8, "S", GetFlag(m[0].flags, FLAGS_SF),
|
||||
GetFlag(m[1].flags, FLAGS_SF));
|
||||
DrawFlag(p, 8, "O", GetFlag(m[0].flags, FLAGS_OF),
|
||||
GetFlag(m[1].flags, FLAGS_OF));
|
||||
DrawFlag(p, 8, "P", GetFlag(m[0].flags, FLAGS_PF),
|
||||
GetFlag(m[1].flags, FLAGS_PF));
|
||||
DrawFlag(p, 8, "I", GetFlag(m[0].flags, FLAGS_IF),
|
||||
GetFlag(m[1].flags, FLAGS_IF));
|
||||
DrawFlag(p, 8, "D", GetFlag(m[0].flags, FLAGS_DF),
|
||||
GetFlag(m[1].flags, FLAGS_DF));
|
||||
DrawFlag(p, 8, 'C', GetFlag(m[0].flags, FLAGS_CF));
|
||||
DrawFlag(p, 8, 'P', GetFlag(m[0].flags, FLAGS_PF));
|
||||
DrawFlag(p, 8, 'A', GetFlag(m[0].flags, FLAGS_AF));
|
||||
DrawFlag(p, 8, 'Z', GetFlag(m[0].flags, FLAGS_ZF));
|
||||
DrawFlag(p, 8, 'S', GetFlag(m[0].flags, FLAGS_SF));
|
||||
DrawFlag(p, 8, 'I', GetFlag(m[0].flags, FLAGS_IF));
|
||||
DrawFlag(p, 8, 'D', GetFlag(m[0].flags, FLAGS_DF));
|
||||
DrawFlag(p, 8, 'O', GetFlag(m[0].flags, FLAGS_OF));
|
||||
AppendPanel(p, 8, " ");
|
||||
if (m->fpu.ie) AppendPanel(p, 8, " IE");
|
||||
if (m->fpu.de) AppendPanel(p, 8, " DE");
|
||||
if (m->fpu.ze) AppendPanel(p, 8, " ZE");
|
||||
if (m->fpu.oe) AppendPanel(p, 8, " OE");
|
||||
if (m->fpu.ue) AppendPanel(p, 8, " UE");
|
||||
if (m->fpu.pe) AppendPanel(p, 8, " PE");
|
||||
if (m->fpu.sf) AppendPanel(p, 8, " SF");
|
||||
if (m->fpu.es) AppendPanel(p, 8, " ES");
|
||||
if (m->fpu.c0) AppendPanel(p, 8, " C0");
|
||||
if (m->fpu.c1) AppendPanel(p, 8, " C1");
|
||||
if (m->fpu.c2) AppendPanel(p, 8, " C2");
|
||||
if (m->fpu.bf) AppendPanel(p, 8, " BF");
|
||||
}
|
||||
|
||||
static void DrawXmm(struct Panel *p, long i, long r) {
|
||||
|
|
|
@ -25,8 +25,8 @@
|
|||
* NexGen32e Arithmetic Unit.
|
||||
*/
|
||||
int64_t Alu(int w, int h, uint64_t x, uint64_t y, uint32_t *flags) {
|
||||
bool zf, sf, c, o, cf;
|
||||
uint64_t t, z, s, m, k;
|
||||
bool cf, of, zf, sf, af, carry;
|
||||
assert(w < 4);
|
||||
k = 8;
|
||||
k <<= w;
|
||||
|
@ -35,9 +35,10 @@ int64_t Alu(int w, int h, uint64_t x, uint64_t y, uint32_t *flags) {
|
|||
m = s;
|
||||
m |= s - 1;
|
||||
t = x;
|
||||
c = 0;
|
||||
o = 0;
|
||||
cf = GetFlag(*flags, FLAGS_CF);
|
||||
cf = 0;
|
||||
of = 0;
|
||||
af = 0;
|
||||
carry = GetFlag(*flags, FLAGS_CF);
|
||||
switch (h & 7) {
|
||||
case ALU_OR:
|
||||
z = x | y;
|
||||
|
@ -50,22 +51,26 @@ int64_t Alu(int w, int h, uint64_t x, uint64_t y, uint32_t *flags) {
|
|||
break;
|
||||
case ALU_CMP:
|
||||
h |= 8;
|
||||
cf = 0;
|
||||
carry = 0;
|
||||
case ALU_SBB:
|
||||
t = (x & m) - cf;
|
||||
c = (x & m) < (t & m);
|
||||
t = (x & m) - carry;
|
||||
cf = (x & m) < (t & m);
|
||||
af = (x & 15) < (t & 15);
|
||||
case ALU_SUB:
|
||||
z = (t & m) - (y & m);
|
||||
c |= (t & m) < (z & m);
|
||||
o = !!((z ^ x) & (x ^ y) & s);
|
||||
cf |= (t & m) < (z & m);
|
||||
af |= (t & 15) < (z & 15);
|
||||
of = !!((z ^ x) & (x ^ y) & s);
|
||||
break;
|
||||
case ALU_ADC:
|
||||
t = (x & m) + cf;
|
||||
c = (t & m) < (x & m);
|
||||
t = (x & m) + carry;
|
||||
cf = (t & m) < (x & m);
|
||||
af = (t & 15) < (x & 15);
|
||||
case ALU_ADD:
|
||||
z = (t & m) + (y & m);
|
||||
c |= (z & m) < (y & m);
|
||||
o = !!((z ^ x) & (z ^ y) & s);
|
||||
cf |= (z & m) < (y & m);
|
||||
af |= (z & 15) < (y & 15);
|
||||
of = !!((z ^ x) & (z ^ y) & s);
|
||||
break;
|
||||
default:
|
||||
unreachable;
|
||||
|
@ -73,8 +78,10 @@ int64_t Alu(int w, int h, uint64_t x, uint64_t y, uint32_t *flags) {
|
|||
z &= m;
|
||||
zf = !z;
|
||||
sf = !!(z & s);
|
||||
*flags &= ~(1 << FLAGS_CF | 1 << FLAGS_ZF | 1 << FLAGS_SF | 1 << FLAGS_OF);
|
||||
*flags |= c << FLAGS_CF | zf << FLAGS_ZF | sf << FLAGS_SF | o << FLAGS_OF;
|
||||
*flags = (*flags & ~(1 << FLAGS_CF | 1 << FLAGS_ZF | 1 << FLAGS_SF |
|
||||
1 << FLAGS_OF | 1 << FLAGS_AF)) |
|
||||
cf << FLAGS_CF | zf << FLAGS_ZF | sf << FLAGS_SF | of << FLAGS_OF |
|
||||
af << FLAGS_AF;
|
||||
*flags = SetLazyParityByte(*flags, x);
|
||||
if (h & ALU_TEST) z = x;
|
||||
return z;
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
#define ALU_XOR 6
|
||||
#define ALU_CMP 7
|
||||
#define ALU_TEST 8
|
||||
#define ALU_FLIP 16
|
||||
|
||||
#define BSU_ROL 0
|
||||
#define BSU_ROR 1
|
||||
|
|
|
@ -63,6 +63,8 @@ $(TOOL_BUILD_LIB_A).pkg: \
|
|||
$(TOOL_BUILD_LIB_A_OBJS) \
|
||||
$(foreach x,$(TOOL_BUILD_LIB_A_DIRECTDEPS),$($(x)_A).pkg)
|
||||
|
||||
o/$(MODE)/tool/build/lib/fpu.o: OVERRIDE_CFLAGS += -ffast-math
|
||||
|
||||
TOOL_BUILD_LIB_LIBS = $(foreach x,$(TOOL_BUILD_LIB_ARTIFACTS),$($(x)))
|
||||
TOOL_BUILD_LIB_SRCS = $(foreach x,$(TOOL_BUILD_LIB_ARTIFACTS),$($(x)_SRCS))
|
||||
TOOL_BUILD_LIB_HDRS = $(foreach x,$(TOOL_BUILD_LIB_ARTIFACTS),$($(x)_HDRS))
|
||||
|
|
|
@ -7,5 +7,10 @@
|
|||
CODE; \
|
||||
break
|
||||
|
||||
#define CASR(OP, CODE) \
|
||||
case OP: \
|
||||
CODE; \
|
||||
return
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_CASE_H_ */
|
||||
|
|
|
@ -26,6 +26,21 @@
|
|||
#include "tool/build/lib/modrm.h"
|
||||
#include "tool/build/lib/throw.h"
|
||||
|
||||
static double SseRoundDouble(struct Machine *m, double x) {
|
||||
switch (m->sse.rc) {
|
||||
case 0:
|
||||
return nearbyint(x);
|
||||
case 1:
|
||||
return floor(x);
|
||||
case 2:
|
||||
return ceil(x);
|
||||
case 3:
|
||||
return trunc(x);
|
||||
default:
|
||||
unreachable;
|
||||
}
|
||||
}
|
||||
|
||||
static void OpGdqpWssCvttss2si(struct Machine *m, uint32_t rde) {
|
||||
float f;
|
||||
int64_t n;
|
||||
|
@ -57,7 +72,7 @@ static void OpGdqpWsdCvtsd2si(struct Machine *m, uint32_t rde) {
|
|||
double d;
|
||||
int64_t n;
|
||||
memcpy(&d, GetModrmRegisterXmmPointerRead8(m, rde), 8);
|
||||
n = nearbyint(d);
|
||||
n = SseRoundDouble(m, d);
|
||||
if (!Rexw(rde)) n &= 0xffffffff;
|
||||
Write64(RegRexrReg(m, rde), n);
|
||||
}
|
||||
|
@ -113,11 +128,26 @@ static void OpVpdQpiCvtpi2pd(struct Machine *m, uint32_t rde) {
|
|||
}
|
||||
|
||||
static void OpPpiWpsqCvtps2pi(struct Machine *m, uint32_t rde) {
|
||||
unsigned i;
|
||||
float f[2];
|
||||
int32_t n[2];
|
||||
memcpy(f, GetModrmRegisterXmmPointerRead8(m, rde), 8);
|
||||
n[0] = nearbyintf(f[0]);
|
||||
n[1] = nearbyintf(f[1]);
|
||||
switch (m->sse.rc) {
|
||||
case 0:
|
||||
for (i = 0; i < 2; ++i) n[i] = nearbyintf(f[i]);
|
||||
break;
|
||||
case 1:
|
||||
for (i = 0; i < 2; ++i) n[i] = floorf(f[i]);
|
||||
break;
|
||||
case 2:
|
||||
for (i = 0; i < 2; ++i) n[i] = ceilf(f[i]);
|
||||
break;
|
||||
case 3:
|
||||
for (i = 0; i < 2; ++i) n[i] = truncf(f[i]);
|
||||
break;
|
||||
default:
|
||||
unreachable;
|
||||
}
|
||||
Write32(MmReg(m, rde) + 0, n[0]);
|
||||
Write32(MmReg(m, rde) + 4, n[1]);
|
||||
}
|
||||
|
@ -133,11 +163,11 @@ static void OpPpiWpsqCvttps2pi(struct Machine *m, uint32_t rde) {
|
|||
}
|
||||
|
||||
static void OpPpiWpdCvtpd2pi(struct Machine *m, uint32_t rde) {
|
||||
unsigned i;
|
||||
double d[2];
|
||||
int32_t n[2];
|
||||
memcpy(d, GetModrmRegisterXmmPointerRead16(m, rde), 16);
|
||||
n[0] = nearbyint(d[0]);
|
||||
n[1] = nearbyint(d[1]);
|
||||
for (i = 0; i < 2; ++i) n[i] = SseRoundDouble(m, d[i]);
|
||||
Write32(MmReg(m, rde) + 0, n[0]);
|
||||
Write32(MmReg(m, rde) + 4, n[1]);
|
||||
}
|
||||
|
@ -218,7 +248,22 @@ static void OpVdqWpsCvtps2dq(struct Machine *m, uint32_t rde) {
|
|||
float f[4];
|
||||
int32_t n[4];
|
||||
memcpy(f, GetModrmRegisterXmmPointerRead16(m, rde), 16);
|
||||
for (i = 0; i < 4; ++i) n[i] = nearbyintf(f[i]);
|
||||
switch (m->sse.rc) {
|
||||
case 0:
|
||||
for (i = 0; i < 4; ++i) n[i] = nearbyintf(f[i]);
|
||||
break;
|
||||
case 1:
|
||||
for (i = 0; i < 4; ++i) n[i] = floorf(f[i]);
|
||||
break;
|
||||
case 2:
|
||||
for (i = 0; i < 4; ++i) n[i] = ceilf(f[i]);
|
||||
break;
|
||||
case 3:
|
||||
for (i = 0; i < 4; ++i) n[i] = truncf(f[i]);
|
||||
break;
|
||||
default:
|
||||
unreachable;
|
||||
}
|
||||
memcpy(XmmRexrReg(m, rde), n, 16);
|
||||
}
|
||||
|
||||
|
@ -236,7 +281,7 @@ static void OpVdqWpdCvtpd2dq(struct Machine *m, uint32_t rde) {
|
|||
double d[2];
|
||||
int32_t n[2];
|
||||
memcpy(d, GetModrmRegisterXmmPointerRead16(m, rde), 16);
|
||||
for (i = 0; i < 2; ++i) n[i] = nearbyintf(d[i]);
|
||||
for (i = 0; i < 2; ++i) n[i] = SseRoundDouble(m, d[i]);
|
||||
memcpy(XmmRexrReg(m, rde), n, 8);
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "libc/conv/itoa.h"
|
||||
#include "libc/fmt/bing.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/macros.h"
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/conv/itoa.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/log/check.h"
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "tool/build/lib/memory.h"
|
||||
#include "tool/build/lib/modrm.h"
|
||||
#include "tool/build/lib/throw.h"
|
||||
#include "tool/build/lib/word.h"
|
||||
#include "tool/build/lib/x87.h"
|
||||
|
||||
#define FPUREG 0
|
||||
|
@ -92,90 +93,142 @@ static void FpuSetStRmPop(struct Machine *m, long double x) {
|
|||
FpuSetStPop(m, ModrmRm(m->xedd->op.rde), x);
|
||||
}
|
||||
|
||||
static int16_t GetMemoryShort(struct Machine *m) {
|
||||
static int16_t FpuGetMemoryShort(struct Machine *m) {
|
||||
uint8_t b[2];
|
||||
return Read16(Load(m, m->fpu.dp, 2, b));
|
||||
}
|
||||
|
||||
static int32_t GetMemoryInt(struct Machine *m) {
|
||||
static int32_t FpuGetMemoryInt(struct Machine *m) {
|
||||
uint8_t b[4];
|
||||
return Read32(Load(m, m->fpu.dp, 4, b));
|
||||
}
|
||||
|
||||
static int64_t GetMemoryLong(struct Machine *m) {
|
||||
static int64_t FpuGetMemoryLong(struct Machine *m) {
|
||||
uint8_t b[8];
|
||||
return Read64(Load(m, m->fpu.dp, 8, b));
|
||||
}
|
||||
|
||||
static float GetMemoryFloat(struct Machine *m) {
|
||||
static float FpuGetMemoryFloat(struct Machine *m) {
|
||||
float f;
|
||||
uint8_t b[4];
|
||||
memcpy(&f, Load(m, m->fpu.dp, 4, b), 4);
|
||||
return f;
|
||||
}
|
||||
|
||||
static double GetMemoryDouble(struct Machine *m) {
|
||||
static double FpuGetMemoryDouble(struct Machine *m) {
|
||||
double f;
|
||||
uint8_t b[8];
|
||||
memcpy(&f, Load(m, m->fpu.dp, 8, b), 8);
|
||||
return f;
|
||||
}
|
||||
|
||||
static long double GetMemoryLongDouble(struct Machine *m) {
|
||||
static long double FpuGetMemoryLongDouble(struct Machine *m) {
|
||||
long double f;
|
||||
uint8_t b[10];
|
||||
memcpy(&f, Load(m, m->fpu.dp, 10, b), 10);
|
||||
return f;
|
||||
}
|
||||
|
||||
static void SetMemoryShort(struct Machine *m, int16_t i) {
|
||||
void *p[2];
|
||||
uint8_t b[2];
|
||||
Write16(BeginStore(m, m->fpu.dp, 2, p, b), i);
|
||||
EndStore(m, m->fpu.dp, 2, p, b);
|
||||
static void FpuSetMemoryShort(struct Machine *m, int16_t i) {
|
||||
SetMemoryShort(m, m->fpu.dp, i);
|
||||
}
|
||||
|
||||
static void SetMemoryInt(struct Machine *m, int32_t i) {
|
||||
void *p[2];
|
||||
uint8_t b[4];
|
||||
Write32(BeginStore(m, m->fpu.dp, 4, p, b), i);
|
||||
EndStore(m, m->fpu.dp, 4, p, b);
|
||||
static void FpuSetMemoryInt(struct Machine *m, int32_t i) {
|
||||
SetMemoryInt(m, m->fpu.dp, i);
|
||||
}
|
||||
|
||||
static void SetMemoryLong(struct Machine *m, int64_t i) {
|
||||
void *p[2];
|
||||
uint8_t b[8];
|
||||
Write64(BeginStore(m, m->fpu.dp, 8, p, b), i);
|
||||
EndStore(m, m->fpu.dp, 8, p, b);
|
||||
static void FpuSetMemoryLong(struct Machine *m, int64_t i) {
|
||||
SetMemoryLong(m, m->fpu.dp, i);
|
||||
}
|
||||
|
||||
static void SetMemoryFloat(struct Machine *m, float f) {
|
||||
void *p[2];
|
||||
uint8_t b[4];
|
||||
memcpy(BeginStore(m, m->fpu.dp, 4, p, b), &f, 4);
|
||||
EndStore(m, m->fpu.dp, 4, p, b);
|
||||
static void FpuSetMemoryFloat(struct Machine *m, float f) {
|
||||
SetMemoryFloat(m, m->fpu.dp, f);
|
||||
}
|
||||
|
||||
static void SetMemoryDouble(struct Machine *m, double f) {
|
||||
void *p[2];
|
||||
uint8_t b[8];
|
||||
memcpy(BeginStore(m, m->fpu.dp, 8, p, b), &f, 8);
|
||||
EndStore(m, m->fpu.dp, 8, p, b);
|
||||
static void FpuSetMemoryDouble(struct Machine *m, double f) {
|
||||
SetMemoryDouble(m, m->fpu.dp, f);
|
||||
}
|
||||
|
||||
static void SetMemoryLdbl(struct Machine *m, long double f) {
|
||||
void *p[2];
|
||||
uint8_t b[10];
|
||||
memcpy(BeginStore(m, m->fpu.dp, 10, p, b), &f, 10);
|
||||
EndStore(m, m->fpu.dp, 10, p, b);
|
||||
static void FpuSetMemoryLdbl(struct Machine *m, long double f) {
|
||||
SetMemoryLdbl(m, m->fpu.dp, f);
|
||||
}
|
||||
|
||||
static long double FpuDivide(struct Machine *m, long double x, long double y) {
|
||||
if (y) {
|
||||
return x / y;
|
||||
static long double FpuAdd(struct Machine *m, long double x, long double y) {
|
||||
if (!isunordered(x, y)) {
|
||||
switch (isinf(y) << 1 | isinf(x)) {
|
||||
case 0b00:
|
||||
return x + y;
|
||||
case 0b01:
|
||||
return x;
|
||||
case 0b10:
|
||||
return y;
|
||||
case 0b11:
|
||||
if (signbit(x) == signbit(y)) {
|
||||
return x;
|
||||
} else {
|
||||
m->fpu.ie = true;
|
||||
return copysign(NAN, x);
|
||||
}
|
||||
default:
|
||||
unreachable;
|
||||
}
|
||||
} else {
|
||||
m->fpu.ze = true;
|
||||
return signbit(x) ? -INFINITY : INFINITY;
|
||||
return NAN;
|
||||
}
|
||||
}
|
||||
|
||||
static long double FpuSub(struct Machine *m, long double x, long double y) {
|
||||
if (!isunordered(x, y)) {
|
||||
switch (isinf(y) << 1 | isinf(x)) {
|
||||
case 0b00:
|
||||
return x - y;
|
||||
case 0b01:
|
||||
return -x;
|
||||
case 0b10:
|
||||
return y;
|
||||
case 0b11:
|
||||
if (signbit(x) == signbit(y)) {
|
||||
m->fpu.ie = true;
|
||||
return copysign(NAN, x);
|
||||
} else {
|
||||
return y;
|
||||
}
|
||||
default:
|
||||
unreachable;
|
||||
}
|
||||
} else {
|
||||
return NAN;
|
||||
}
|
||||
}
|
||||
|
||||
static long double FpuMul(struct Machine *m, long double x, long double y) {
|
||||
if (!isunordered(x, y)) {
|
||||
if (!((isinf(x) && !y) || (isinf(y) && !x))) {
|
||||
return x * y;
|
||||
} else {
|
||||
m->fpu.ie = true;
|
||||
return -NAN;
|
||||
}
|
||||
} else {
|
||||
return NAN;
|
||||
}
|
||||
}
|
||||
|
||||
static long double FpuDiv(struct Machine *m, long double x, long double y) {
|
||||
if (!isunordered(x, y)) {
|
||||
if (x || y) {
|
||||
if (y) {
|
||||
return x / y;
|
||||
} else {
|
||||
m->fpu.ze = true;
|
||||
return copysign(INFINITY, x);
|
||||
}
|
||||
} else {
|
||||
m->fpu.ie = true;
|
||||
return copysign(NAN, x);
|
||||
}
|
||||
} else {
|
||||
return NAN;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -198,7 +251,7 @@ static void FpuCompare(struct Machine *m, long double y) {
|
|||
long double x;
|
||||
x = St0(m);
|
||||
m->fpu.c1 = false;
|
||||
if (!isnan(x) && !isnan(y)) {
|
||||
if (!isunordered(x, y)) {
|
||||
m->fpu.c0 = x < y;
|
||||
m->fpu.c2 = false;
|
||||
m->fpu.c3 = x == y;
|
||||
|
@ -210,7 +263,7 @@ static void FpuCompare(struct Machine *m, long double y) {
|
|||
}
|
||||
}
|
||||
|
||||
static void OpFxam(struct Machine *m) {
|
||||
void OpFxam(struct Machine *m) {
|
||||
long double x;
|
||||
x = *FpuSt(m, 0);
|
||||
m->fpu.c1 = !!signbit(x);
|
||||
|
@ -362,59 +415,59 @@ static void OpFcomp(struct Machine *m) {
|
|||
}
|
||||
|
||||
static void OpFaddStEst(struct Machine *m) {
|
||||
FpuSetSt0(m, St0(m) + StRm(m));
|
||||
FpuSetSt0(m, FpuAdd(m, St0(m), StRm(m)));
|
||||
}
|
||||
|
||||
static void OpFmulStEst(struct Machine *m) {
|
||||
FpuSetSt0(m, St0(m) * StRm(m));
|
||||
FpuSetSt0(m, FpuMul(m, St0(m), StRm(m)));
|
||||
}
|
||||
|
||||
static void OpFsubStEst(struct Machine *m) {
|
||||
FpuSetSt0(m, St0(m) - StRm(m));
|
||||
FpuSetSt0(m, FpuSub(m, St0(m), StRm(m)));
|
||||
}
|
||||
|
||||
static void OpFsubrStEst(struct Machine *m) {
|
||||
FpuSetSt0(m, StRm(m) - St0(m));
|
||||
FpuSetSt0(m, FpuSub(m, StRm(m), St0(m)));
|
||||
}
|
||||
|
||||
static void OpFdivStEst(struct Machine *m) {
|
||||
FpuSetSt0(m, FpuDivide(m, St0(m), StRm(m)));
|
||||
FpuSetSt0(m, FpuDiv(m, St0(m), StRm(m)));
|
||||
}
|
||||
|
||||
static void OpFdivrStEst(struct Machine *m) {
|
||||
FpuSetSt0(m, FpuDivide(m, StRm(m), St0(m)));
|
||||
FpuSetSt0(m, FpuDiv(m, StRm(m), St0(m)));
|
||||
}
|
||||
|
||||
static void OpFaddEstSt(struct Machine *m) {
|
||||
FpuSetStRm(m, StRm(m) + St0(m));
|
||||
FpuSetStRm(m, FpuAdd(m, StRm(m), St0(m)));
|
||||
}
|
||||
|
||||
static void OpFmulEstSt(struct Machine *m) {
|
||||
FpuSetStRm(m, StRm(m) * St0(m));
|
||||
FpuSetStRm(m, FpuMul(m, StRm(m), St0(m)));
|
||||
}
|
||||
|
||||
static void OpFsubEstSt(struct Machine *m) {
|
||||
FpuSetStRm(m, St0(m) - StRm(m));
|
||||
FpuSetStRm(m, FpuSub(m, St0(m), StRm(m)));
|
||||
}
|
||||
|
||||
static void OpFsubrEstSt(struct Machine *m) {
|
||||
FpuSetStRm(m, StRm(m) - St0(m));
|
||||
FpuSetStRm(m, FpuSub(m, StRm(m), St0(m)));
|
||||
}
|
||||
|
||||
static void OpFdivEstSt(struct Machine *m) {
|
||||
FpuSetStRm(m, FpuDivide(m, StRm(m), St0(m)));
|
||||
FpuSetStRm(m, FpuDiv(m, StRm(m), St0(m)));
|
||||
}
|
||||
|
||||
static void OpFdivrEstSt(struct Machine *m) {
|
||||
FpuSetStRm(m, FpuDivide(m, St0(m), StRm(m)));
|
||||
FpuSetStRm(m, FpuDiv(m, St0(m), StRm(m)));
|
||||
}
|
||||
|
||||
static void OpFaddp(struct Machine *m) {
|
||||
FpuSetStRmPop(m, St0(m) + StRm(m));
|
||||
FpuSetStRmPop(m, FpuAdd(m, St0(m), StRm(m)));
|
||||
}
|
||||
|
||||
static void OpFmulp(struct Machine *m) {
|
||||
FpuSetStRmPop(m, St0(m) * StRm(m));
|
||||
FpuSetStRmPop(m, FpuMul(m, St0(m), StRm(m)));
|
||||
}
|
||||
|
||||
static void OpFcompp(struct Machine *m) {
|
||||
|
@ -423,31 +476,31 @@ static void OpFcompp(struct Machine *m) {
|
|||
}
|
||||
|
||||
static void OpFsubp(struct Machine *m) {
|
||||
FpuSetStRmPop(m, St0(m) - StRm(m));
|
||||
FpuSetStRmPop(m, FpuSub(m, St0(m), StRm(m)));
|
||||
}
|
||||
|
||||
static void OpFsubrp(struct Machine *m) {
|
||||
FpuSetStPop(m, 1, StRm(m) - St0(m));
|
||||
FpuSetStPop(m, 1, FpuSub(m, StRm(m), St0(m)));
|
||||
}
|
||||
|
||||
static void OpFdivp(struct Machine *m) {
|
||||
FpuSetStRmPop(m, FpuDivide(m, St0(m), StRm(m)));
|
||||
FpuSetStRmPop(m, FpuDiv(m, St0(m), StRm(m)));
|
||||
}
|
||||
|
||||
static void OpFdivrp(struct Machine *m) {
|
||||
FpuSetStRmPop(m, FpuDivide(m, StRm(m), St0(m)));
|
||||
FpuSetStRmPop(m, FpuDiv(m, StRm(m), St0(m)));
|
||||
}
|
||||
|
||||
static void OpFadds(struct Machine *m) {
|
||||
FpuSetSt0(m, St0(m) + GetMemoryFloat(m));
|
||||
FpuSetSt0(m, FpuAdd(m, St0(m), FpuGetMemoryFloat(m)));
|
||||
}
|
||||
|
||||
static void OpFmuls(struct Machine *m) {
|
||||
FpuSetSt0(m, St0(m) * GetMemoryFloat(m));
|
||||
FpuSetSt0(m, FpuMul(m, St0(m), FpuGetMemoryFloat(m)));
|
||||
}
|
||||
|
||||
static void OpFcoms(struct Machine *m) {
|
||||
FpuCompare(m, GetMemoryFloat(m));
|
||||
FpuCompare(m, FpuGetMemoryFloat(m));
|
||||
}
|
||||
|
||||
static void OpFcomps(struct Machine *m) {
|
||||
|
@ -456,64 +509,64 @@ static void OpFcomps(struct Machine *m) {
|
|||
}
|
||||
|
||||
static void OpFsubs(struct Machine *m) {
|
||||
FpuSetSt0(m, St0(m) - GetMemoryFloat(m));
|
||||
FpuSetSt0(m, FpuSub(m, St0(m), FpuGetMemoryFloat(m)));
|
||||
}
|
||||
|
||||
static void OpFsubrs(struct Machine *m) {
|
||||
FpuSetSt0(m, GetMemoryFloat(m) - St0(m));
|
||||
FpuSetSt0(m, FpuSub(m, FpuGetMemoryFloat(m), St0(m)));
|
||||
}
|
||||
|
||||
static void OpFdivs(struct Machine *m) {
|
||||
FpuSetSt0(m, FpuDivide(m, St0(m), GetMemoryFloat(m)));
|
||||
FpuSetSt0(m, FpuDiv(m, St0(m), FpuGetMemoryFloat(m)));
|
||||
}
|
||||
|
||||
static void OpFdivrs(struct Machine *m) {
|
||||
FpuSetSt0(m, FpuDivide(m, GetMemoryFloat(m), St0(m)));
|
||||
FpuSetSt0(m, FpuDiv(m, FpuGetMemoryFloat(m), St0(m)));
|
||||
}
|
||||
|
||||
static void OpFaddl(struct Machine *m) {
|
||||
FpuSetSt0(m, St0(m) + GetMemoryDouble(m));
|
||||
FpuSetSt0(m, FpuAdd(m, St0(m), FpuGetMemoryDouble(m)));
|
||||
}
|
||||
|
||||
static void OpFmull(struct Machine *m) {
|
||||
FpuSetSt0(m, St0(m) * GetMemoryDouble(m));
|
||||
FpuSetSt0(m, FpuMul(m, St0(m), FpuGetMemoryDouble(m)));
|
||||
}
|
||||
|
||||
static void OpFcoml(struct Machine *m) {
|
||||
FpuCompare(m, GetMemoryDouble(m));
|
||||
FpuCompare(m, FpuGetMemoryDouble(m));
|
||||
}
|
||||
|
||||
static void OpFcompl(struct Machine *m) {
|
||||
FpuCompare(m, GetMemoryDouble(m));
|
||||
FpuCompare(m, FpuGetMemoryDouble(m));
|
||||
FpuPop(m);
|
||||
}
|
||||
|
||||
static void OpFsubl(struct Machine *m) {
|
||||
FpuSetSt0(m, St0(m) - GetMemoryDouble(m));
|
||||
FpuSetSt0(m, FpuSub(m, St0(m), FpuGetMemoryDouble(m)));
|
||||
}
|
||||
|
||||
static void OpFsubrl(struct Machine *m) {
|
||||
FpuSetSt0(m, GetMemoryDouble(m) - St0(m));
|
||||
FpuSetSt0(m, FpuSub(m, FpuGetMemoryDouble(m), St0(m)));
|
||||
}
|
||||
|
||||
static void OpFdivl(struct Machine *m) {
|
||||
FpuSetSt0(m, FpuDivide(m, St0(m), GetMemoryDouble(m)));
|
||||
FpuSetSt0(m, FpuDiv(m, St0(m), FpuGetMemoryDouble(m)));
|
||||
}
|
||||
|
||||
static void OpFdivrl(struct Machine *m) {
|
||||
FpuSetSt0(m, FpuDivide(m, GetMemoryDouble(m), St0(m)));
|
||||
FpuSetSt0(m, FpuDiv(m, FpuGetMemoryDouble(m), St0(m)));
|
||||
}
|
||||
|
||||
static void OpFiaddl(struct Machine *m) {
|
||||
FpuSetSt0(m, St0(m) + GetMemoryInt(m));
|
||||
FpuSetSt0(m, FpuAdd(m, St0(m), FpuGetMemoryInt(m)));
|
||||
}
|
||||
|
||||
static void OpFimull(struct Machine *m) {
|
||||
FpuSetSt0(m, St0(m) * GetMemoryInt(m));
|
||||
FpuSetSt0(m, FpuMul(m, St0(m), FpuGetMemoryInt(m)));
|
||||
}
|
||||
|
||||
static void OpFicoml(struct Machine *m) {
|
||||
FpuCompare(m, GetMemoryInt(m));
|
||||
FpuCompare(m, FpuGetMemoryInt(m));
|
||||
}
|
||||
|
||||
static void OpFicompl(struct Machine *m) {
|
||||
|
@ -522,31 +575,31 @@ static void OpFicompl(struct Machine *m) {
|
|||
}
|
||||
|
||||
static void OpFisubl(struct Machine *m) {
|
||||
FpuSetSt0(m, St0(m) - GetMemoryInt(m));
|
||||
FpuSetSt0(m, FpuSub(m, St0(m), FpuGetMemoryInt(m)));
|
||||
}
|
||||
|
||||
static void OpFisubrl(struct Machine *m) {
|
||||
FpuSetSt0(m, GetMemoryInt(m) - St0(m));
|
||||
FpuSetSt0(m, FpuSub(m, FpuGetMemoryInt(m), St0(m)));
|
||||
}
|
||||
|
||||
static void OpFidivl(struct Machine *m) {
|
||||
FpuSetSt0(m, FpuDivide(m, St0(m), GetMemoryInt(m)));
|
||||
FpuSetSt0(m, FpuDiv(m, St0(m), FpuGetMemoryInt(m)));
|
||||
}
|
||||
|
||||
static void OpFidivrl(struct Machine *m) {
|
||||
FpuSetSt0(m, FpuDivide(m, GetMemoryInt(m), St0(m)));
|
||||
FpuSetSt0(m, FpuDiv(m, FpuGetMemoryInt(m), St0(m)));
|
||||
}
|
||||
|
||||
static void OpFiadds(struct Machine *m) {
|
||||
FpuSetSt0(m, St0(m) + GetMemoryShort(m));
|
||||
FpuSetSt0(m, FpuAdd(m, St0(m), FpuGetMemoryShort(m)));
|
||||
}
|
||||
|
||||
static void OpFimuls(struct Machine *m) {
|
||||
FpuSetSt0(m, St0(m) * GetMemoryShort(m));
|
||||
FpuSetSt0(m, FpuMul(m, St0(m), FpuGetMemoryShort(m)));
|
||||
}
|
||||
|
||||
static void OpFicoms(struct Machine *m) {
|
||||
FpuCompare(m, GetMemoryShort(m));
|
||||
FpuCompare(m, FpuGetMemoryShort(m));
|
||||
}
|
||||
|
||||
static void OpFicomps(struct Machine *m) {
|
||||
|
@ -555,19 +608,19 @@ static void OpFicomps(struct Machine *m) {
|
|||
}
|
||||
|
||||
static void OpFisubs(struct Machine *m) {
|
||||
FpuSetSt0(m, St0(m) - GetMemoryShort(m));
|
||||
FpuSetSt0(m, FpuSub(m, St0(m), FpuGetMemoryShort(m)));
|
||||
}
|
||||
|
||||
static void OpFisubrs(struct Machine *m) {
|
||||
FpuSetSt0(m, GetMemoryShort(m) - St0(m));
|
||||
FpuSetSt0(m, FpuSub(m, FpuGetMemoryShort(m), St0(m)));
|
||||
}
|
||||
|
||||
static void OpFidivs(struct Machine *m) {
|
||||
FpuSetSt0(m, FpuDivide(m, St0(m), GetMemoryShort(m)));
|
||||
FpuSetSt0(m, FpuDiv(m, St0(m), FpuGetMemoryShort(m)));
|
||||
}
|
||||
|
||||
static void OpFidivrs(struct Machine *m) {
|
||||
FpuSetSt0(m, FpuDivide(m, GetMemoryShort(m), St0(m)));
|
||||
FpuSetSt0(m, FpuDiv(m, FpuGetMemoryShort(m), St0(m)));
|
||||
}
|
||||
|
||||
static void OpFsqrt(struct Machine *m) {
|
||||
|
@ -612,11 +665,11 @@ static void OpFld(struct Machine *m) {
|
|||
}
|
||||
|
||||
static void OpFlds(struct Machine *m) {
|
||||
FpuPush(m, GetMemoryFloat(m));
|
||||
FpuPush(m, FpuGetMemoryFloat(m));
|
||||
}
|
||||
|
||||
static void OpFsts(struct Machine *m) {
|
||||
SetMemoryFloat(m, St0(m));
|
||||
FpuSetMemoryFloat(m, St0(m));
|
||||
}
|
||||
|
||||
static void OpFstps(struct Machine *m) {
|
||||
|
@ -625,11 +678,11 @@ static void OpFstps(struct Machine *m) {
|
|||
}
|
||||
|
||||
static void OpFstpt(struct Machine *m) {
|
||||
SetMemoryLdbl(m, FpuPop(m));
|
||||
FpuSetMemoryLdbl(m, FpuPop(m));
|
||||
}
|
||||
|
||||
static void OpFstl(struct Machine *m) {
|
||||
SetMemoryDouble(m, St0(m));
|
||||
FpuSetMemoryDouble(m, St0(m));
|
||||
}
|
||||
|
||||
static void OpFstpl(struct Machine *m) {
|
||||
|
@ -652,15 +705,15 @@ static void OpFxch(struct Machine *m) {
|
|||
}
|
||||
|
||||
static void OpFldcw(struct Machine *m) {
|
||||
m->fpu.cw = GetMemoryShort(m);
|
||||
m->fpu.cw = FpuGetMemoryShort(m);
|
||||
}
|
||||
|
||||
static void OpFldt(struct Machine *m) {
|
||||
FpuPush(m, GetMemoryLongDouble(m));
|
||||
FpuPush(m, FpuGetMemoryLongDouble(m));
|
||||
}
|
||||
|
||||
static void OpFldl(struct Machine *m) {
|
||||
FpuPush(m, GetMemoryDouble(m));
|
||||
FpuPush(m, FpuGetMemoryDouble(m));
|
||||
}
|
||||
|
||||
static void OpFldConstant(struct Machine *m) {
|
||||
|
@ -694,43 +747,43 @@ static void OpFldConstant(struct Machine *m) {
|
|||
}
|
||||
|
||||
static void OpFstcw(struct Machine *m) {
|
||||
SetMemoryShort(m, m->fpu.cw);
|
||||
FpuSetMemoryShort(m, m->fpu.cw);
|
||||
}
|
||||
|
||||
static void OpFilds(struct Machine *m) {
|
||||
FpuPush(m, GetMemoryShort(m));
|
||||
FpuPush(m, FpuGetMemoryShort(m));
|
||||
}
|
||||
|
||||
static void OpFildl(struct Machine *m) {
|
||||
FpuPush(m, GetMemoryInt(m));
|
||||
FpuPush(m, FpuGetMemoryInt(m));
|
||||
}
|
||||
|
||||
static void OpFildll(struct Machine *m) {
|
||||
FpuPush(m, GetMemoryLong(m));
|
||||
FpuPush(m, FpuGetMemoryLong(m));
|
||||
}
|
||||
|
||||
static void OpFisttpl(struct Machine *m) {
|
||||
SetMemoryInt(m, FpuPop(m));
|
||||
FpuSetMemoryInt(m, FpuPop(m));
|
||||
}
|
||||
|
||||
static void OpFisttpll(struct Machine *m) {
|
||||
SetMemoryLong(m, FpuPop(m));
|
||||
FpuSetMemoryLong(m, FpuPop(m));
|
||||
}
|
||||
|
||||
static void OpFisttps(struct Machine *m) {
|
||||
SetMemoryShort(m, FpuPop(m));
|
||||
FpuSetMemoryShort(m, FpuPop(m));
|
||||
}
|
||||
|
||||
static void OpFists(struct Machine *m) {
|
||||
SetMemoryShort(m, FpuRound(m, St0(m)));
|
||||
FpuSetMemoryShort(m, FpuRound(m, St0(m)));
|
||||
}
|
||||
|
||||
static void OpFistl(struct Machine *m) {
|
||||
SetMemoryInt(m, FpuRound(m, St0(m)));
|
||||
FpuSetMemoryInt(m, FpuRound(m, St0(m)));
|
||||
}
|
||||
|
||||
static void OpFistll(struct Machine *m) {
|
||||
SetMemoryLong(m, FpuRound(m, St0(m)));
|
||||
FpuSetMemoryLong(m, FpuRound(m, St0(m)));
|
||||
}
|
||||
|
||||
static void OpFistpl(struct Machine *m) {
|
||||
|
@ -752,7 +805,7 @@ static void OpFcomi(struct Machine *m) {
|
|||
long double x, y;
|
||||
x = St0(m);
|
||||
y = StRm(m);
|
||||
if (!isnan(x) && !isnan(y)) {
|
||||
if (!isunordered(x, y)) {
|
||||
m->flags = SetFlag(m->flags, FLAGS_ZF, x == y);
|
||||
m->flags = SetFlag(m->flags, FLAGS_CF, x < y);
|
||||
m->flags = SetFlag(m->flags, FLAGS_PF, false);
|
||||
|
@ -796,7 +849,7 @@ static void OpFfreep(struct Machine *m) {
|
|||
}
|
||||
|
||||
static void OpFstswMw(struct Machine *m) {
|
||||
SetMemoryShort(m, m->fpu.sw);
|
||||
FpuSetMemoryShort(m, m->fpu.sw);
|
||||
}
|
||||
|
||||
static void OpFstswAx(struct Machine *m) {
|
||||
|
@ -975,83 +1028,83 @@ void OpFpu(struct Machine *m) {
|
|||
CASE(DISP(0xDA, FPUREG, 2), OpFcmovbe(m));
|
||||
CASE(DISP(0xDA, FPUREG, 3), OpFcmovu(m));
|
||||
CASE(DISP(0xDA, MEMORY, 0), OpFiaddl(m));
|
||||
CASE(DISP(0xDa, MEMORY, 1), OpFimull(m));
|
||||
CASE(DISP(0xDa, MEMORY, 2), OpFicoml(m));
|
||||
CASE(DISP(0xDa, MEMORY, 3), OpFicompl(m));
|
||||
CASE(DISP(0xDa, MEMORY, 4), OpFisubl(m));
|
||||
CASE(DISP(0xDa, MEMORY, 5), OpFisubrl(m));
|
||||
CASE(DISP(0xDa, MEMORY, 6), OpFidivl(m));
|
||||
CASE(DISP(0xDa, MEMORY, 7), OpFidivrl(m));
|
||||
CASE(DISP(0xDb, FPUREG, 0), OpFcmovnb(m));
|
||||
CASE(DISP(0xDb, FPUREG, 1), OpFcmovne(m));
|
||||
CASE(DISP(0xDb, FPUREG, 2), OpFcmovnbe(m));
|
||||
CASE(DISP(0xDb, FPUREG, 3), OpFcmovnu(m));
|
||||
CASE(DISP(0xDb, FPUREG, 5), OpFucomi(m));
|
||||
CASE(DISP(0xDb, FPUREG, 6), OpFcomi(m));
|
||||
CASE(DISP(0xDb, MEMORY, 0), OpFildl(m));
|
||||
CASE(DISP(0xDb, MEMORY, 1), OpFisttpl(m));
|
||||
CASE(DISP(0xDb, MEMORY, 2), OpFistl(m));
|
||||
CASE(DISP(0xDb, MEMORY, 3), OpFistpl(m));
|
||||
CASE(DISP(0xDb, MEMORY, 5), OpFldt(m));
|
||||
CASE(DISP(0xDb, MEMORY, 7), OpFstpt(m));
|
||||
CASE(DISP(0xDc, FPUREG, 0), OpFaddEstSt(m));
|
||||
CASE(DISP(0xDc, FPUREG, 1), OpFmulEstSt(m));
|
||||
CASE(DISP(0xDc, FPUREG, 2), OpFcom(m));
|
||||
CASE(DISP(0xDc, FPUREG, 3), OpFcomp(m));
|
||||
CASE(DISP(0xDc, FPUREG, 4), OpFsubEstSt(m));
|
||||
CASE(DISP(0xDc, FPUREG, 5), OpFsubrEstSt(m));
|
||||
CASE(DISP(0xDc, FPUREG, 6), OpFdivEstSt(m));
|
||||
CASE(DISP(0xDc, FPUREG, 7), OpFdivrEstSt(m));
|
||||
CASE(DISP(0xDc, MEMORY, 0), OpFaddl(m));
|
||||
CASE(DISP(0xDc, MEMORY, 1), OpFmull(m));
|
||||
CASE(DISP(0xDc, MEMORY, 2), OpFcoml(m));
|
||||
CASE(DISP(0xDc, MEMORY, 3), OpFcompl(m));
|
||||
CASE(DISP(0xDc, MEMORY, 4), OpFsubl(m));
|
||||
CASE(DISP(0xDc, MEMORY, 5), OpFsubrl(m));
|
||||
CASE(DISP(0xDc, MEMORY, 6), OpFdivl(m));
|
||||
CASE(DISP(0xDc, MEMORY, 7), OpFdivrl(m));
|
||||
CASE(DISP(0xDd, FPUREG, 0), OpFfree(m));
|
||||
CASE(DISP(0xDd, FPUREG, 1), OpFxch(m));
|
||||
CASE(DISP(0xDd, FPUREG, 2), OpFst(m));
|
||||
CASE(DISP(0xDd, FPUREG, 3), OpFstp(m));
|
||||
CASE(DISP(0xDd, FPUREG, 4), OpFucom(m));
|
||||
CASE(DISP(0xDd, FPUREG, 5), OpFucomp(m));
|
||||
CASE(DISP(0xDd, MEMORY, 0), OpFldl(m));
|
||||
CASE(DISP(0xDd, MEMORY, 1), OpFisttpll(m));
|
||||
CASE(DISP(0xDd, MEMORY, 2), OpFstl(m));
|
||||
CASE(DISP(0xDd, MEMORY, 3), OpFstpl(m));
|
||||
CASE(DISP(0xDd, MEMORY, 4), OpFrstor(m));
|
||||
CASE(DISP(0xDd, MEMORY, 6), OpFsave(m));
|
||||
CASE(DISP(0xDd, MEMORY, 7), OpFstswMw(m));
|
||||
CASE(DISP(0xDe, FPUREG, 0), OpFaddp(m));
|
||||
CASE(DISP(0xDe, FPUREG, 1), OpFmulp(m));
|
||||
CASE(DISP(0xDe, FPUREG, 2), OpFcomp(m));
|
||||
CASE(DISP(0xDe, FPUREG, 3), OpFcompp(m));
|
||||
CASE(DISP(0xDe, FPUREG, 4), OpFsubp(m));
|
||||
CASE(DISP(0xDe, FPUREG, 5), OpFsubrp(m));
|
||||
CASE(DISP(0xDe, FPUREG, 6), OpFdivp(m));
|
||||
CASE(DISP(0xDe, FPUREG, 7), OpFdivrp(m));
|
||||
CASE(DISP(0xDe, MEMORY, 0), OpFiadds(m));
|
||||
CASE(DISP(0xDe, MEMORY, 1), OpFimuls(m));
|
||||
CASE(DISP(0xDe, MEMORY, 2), OpFicoms(m));
|
||||
CASE(DISP(0xDe, MEMORY, 3), OpFicomps(m));
|
||||
CASE(DISP(0xDe, MEMORY, 4), OpFisubs(m));
|
||||
CASE(DISP(0xDe, MEMORY, 5), OpFisubrs(m));
|
||||
CASE(DISP(0xDe, MEMORY, 6), OpFidivs(m));
|
||||
CASE(DISP(0xDe, MEMORY, 7), OpFidivrs(m));
|
||||
CASE(DISP(0xDf, FPUREG, 0), OpFfreep(m));
|
||||
CASE(DISP(0xDf, FPUREG, 1), OpFxch(m));
|
||||
CASE(DISP(0xDf, FPUREG, 2), OpFstp(m));
|
||||
CASE(DISP(0xDf, FPUREG, 3), OpFstp(m));
|
||||
CASE(DISP(0xDf, FPUREG, 4), OpFstswAx(m));
|
||||
CASE(DISP(0xDf, FPUREG, 5), OpFucomip(m));
|
||||
CASE(DISP(0xDf, FPUREG, 6), OpFcomip(m));
|
||||
CASE(DISP(0xDf, MEMORY, 0), OpFilds(m));
|
||||
CASE(DISP(0xDf, MEMORY, 1), OpFisttps(m));
|
||||
CASE(DISP(0xDf, MEMORY, 2), OpFists(m));
|
||||
CASE(DISP(0xDf, MEMORY, 3), OpFistps(m));
|
||||
CASE(DISP(0xDf, MEMORY, 5), OpFildll(m));
|
||||
CASE(DISP(0xDf, MEMORY, 7), OpFistpll(m));
|
||||
CASE(DISP(0xDA, MEMORY, 1), OpFimull(m));
|
||||
CASE(DISP(0xDA, MEMORY, 2), OpFicoml(m));
|
||||
CASE(DISP(0xDA, MEMORY, 3), OpFicompl(m));
|
||||
CASE(DISP(0xDA, MEMORY, 4), OpFisubl(m));
|
||||
CASE(DISP(0xDA, MEMORY, 5), OpFisubrl(m));
|
||||
CASE(DISP(0xDA, MEMORY, 6), OpFidivl(m));
|
||||
CASE(DISP(0xDA, MEMORY, 7), OpFidivrl(m));
|
||||
CASE(DISP(0xDB, FPUREG, 0), OpFcmovnb(m));
|
||||
CASE(DISP(0xDB, FPUREG, 1), OpFcmovne(m));
|
||||
CASE(DISP(0xDB, FPUREG, 2), OpFcmovnbe(m));
|
||||
CASE(DISP(0xDB, FPUREG, 3), OpFcmovnu(m));
|
||||
CASE(DISP(0xDB, FPUREG, 5), OpFucomi(m));
|
||||
CASE(DISP(0xDB, FPUREG, 6), OpFcomi(m));
|
||||
CASE(DISP(0xDB, MEMORY, 0), OpFildl(m));
|
||||
CASE(DISP(0xDB, MEMORY, 1), OpFisttpl(m));
|
||||
CASE(DISP(0xDB, MEMORY, 2), OpFistl(m));
|
||||
CASE(DISP(0xDB, MEMORY, 3), OpFistpl(m));
|
||||
CASE(DISP(0xDB, MEMORY, 5), OpFldt(m));
|
||||
CASE(DISP(0xDB, MEMORY, 7), OpFstpt(m));
|
||||
CASE(DISP(0xDC, FPUREG, 0), OpFaddEstSt(m));
|
||||
CASE(DISP(0xDC, FPUREG, 1), OpFmulEstSt(m));
|
||||
CASE(DISP(0xDC, FPUREG, 2), OpFcom(m));
|
||||
CASE(DISP(0xDC, FPUREG, 3), OpFcomp(m));
|
||||
CASE(DISP(0xDC, FPUREG, 4), OpFsubEstSt(m));
|
||||
CASE(DISP(0xDC, FPUREG, 5), OpFsubrEstSt(m));
|
||||
CASE(DISP(0xDC, FPUREG, 6), OpFdivEstSt(m));
|
||||
CASE(DISP(0xDC, FPUREG, 7), OpFdivrEstSt(m));
|
||||
CASE(DISP(0xDC, MEMORY, 0), OpFaddl(m));
|
||||
CASE(DISP(0xDC, MEMORY, 1), OpFmull(m));
|
||||
CASE(DISP(0xDC, MEMORY, 2), OpFcoml(m));
|
||||
CASE(DISP(0xDC, MEMORY, 3), OpFcompl(m));
|
||||
CASE(DISP(0xDC, MEMORY, 4), OpFsubl(m));
|
||||
CASE(DISP(0xDC, MEMORY, 5), OpFsubrl(m));
|
||||
CASE(DISP(0xDC, MEMORY, 6), OpFdivl(m));
|
||||
CASE(DISP(0xDC, MEMORY, 7), OpFdivrl(m));
|
||||
CASE(DISP(0xDD, FPUREG, 0), OpFfree(m));
|
||||
CASE(DISP(0xDD, FPUREG, 1), OpFxch(m));
|
||||
CASE(DISP(0xDD, FPUREG, 2), OpFst(m));
|
||||
CASE(DISP(0xDD, FPUREG, 3), OpFstp(m));
|
||||
CASE(DISP(0xDD, FPUREG, 4), OpFucom(m));
|
||||
CASE(DISP(0xDD, FPUREG, 5), OpFucomp(m));
|
||||
CASE(DISP(0xDD, MEMORY, 0), OpFldl(m));
|
||||
CASE(DISP(0xDD, MEMORY, 1), OpFisttpll(m));
|
||||
CASE(DISP(0xDD, MEMORY, 2), OpFstl(m));
|
||||
CASE(DISP(0xDD, MEMORY, 3), OpFstpl(m));
|
||||
CASE(DISP(0xDD, MEMORY, 4), OpFrstor(m));
|
||||
CASE(DISP(0xDD, MEMORY, 6), OpFsave(m));
|
||||
CASE(DISP(0xDD, MEMORY, 7), OpFstswMw(m));
|
||||
CASE(DISP(0xDE, FPUREG, 0), OpFaddp(m));
|
||||
CASE(DISP(0xDE, FPUREG, 1), OpFmulp(m));
|
||||
CASE(DISP(0xDE, FPUREG, 2), OpFcomp(m));
|
||||
CASE(DISP(0xDE, FPUREG, 3), OpFcompp(m));
|
||||
CASE(DISP(0xDE, FPUREG, 4), OpFsubp(m));
|
||||
CASE(DISP(0xDE, FPUREG, 5), OpFsubrp(m));
|
||||
CASE(DISP(0xDE, FPUREG, 6), OpFdivp(m));
|
||||
CASE(DISP(0xDE, FPUREG, 7), OpFdivrp(m));
|
||||
CASE(DISP(0xDE, MEMORY, 0), OpFiadds(m));
|
||||
CASE(DISP(0xDE, MEMORY, 1), OpFimuls(m));
|
||||
CASE(DISP(0xDE, MEMORY, 2), OpFicoms(m));
|
||||
CASE(DISP(0xDE, MEMORY, 3), OpFicomps(m));
|
||||
CASE(DISP(0xDE, MEMORY, 4), OpFisubs(m));
|
||||
CASE(DISP(0xDE, MEMORY, 5), OpFisubrs(m));
|
||||
CASE(DISP(0xDE, MEMORY, 6), OpFidivs(m));
|
||||
CASE(DISP(0xDE, MEMORY, 7), OpFidivrs(m));
|
||||
CASE(DISP(0xDF, FPUREG, 0), OpFfreep(m));
|
||||
CASE(DISP(0xDF, FPUREG, 1), OpFxch(m));
|
||||
CASE(DISP(0xDF, FPUREG, 2), OpFstp(m));
|
||||
CASE(DISP(0xDF, FPUREG, 3), OpFstp(m));
|
||||
CASE(DISP(0xDF, FPUREG, 4), OpFstswAx(m));
|
||||
CASE(DISP(0xDF, FPUREG, 5), OpFucomip(m));
|
||||
CASE(DISP(0xDF, FPUREG, 6), OpFcomip(m));
|
||||
CASE(DISP(0xDF, MEMORY, 0), OpFilds(m));
|
||||
CASE(DISP(0xDF, MEMORY, 1), OpFisttps(m));
|
||||
CASE(DISP(0xDF, MEMORY, 2), OpFists(m));
|
||||
CASE(DISP(0xDF, MEMORY, 3), OpFistps(m));
|
||||
CASE(DISP(0xDF, MEMORY, 5), OpFildll(m));
|
||||
CASE(DISP(0xDF, MEMORY, 7), OpFistpll(m));
|
||||
case DISP(0xD9, FPUREG, 4):
|
||||
switch (ModrmRm(m->xedd->op.rde)) {
|
||||
CASE(0, OpFchs(m));
|
||||
|
|
|
@ -26,8 +26,15 @@
|
|||
#include "tool/build/lib/throw.h"
|
||||
|
||||
static bool IsOpcodeEqual(uint8_t *a, uint8_t b[16], size_t size) {
|
||||
if (likely(size)) {
|
||||
return memcmp(a, b, size) == 0;
|
||||
unsigned i;
|
||||
if (size) {
|
||||
i = 0;
|
||||
do {
|
||||
if (a[i] != b[i]) {
|
||||
return false;
|
||||
}
|
||||
} while (++i < size);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -49,8 +49,8 @@ static void LoadElfLoadSegment(struct Machine *m, void *code, size_t codesize,
|
|||
vstart = ROUNDDOWN(phdr->p_vaddr, align);
|
||||
vbss = ROUNDUP(phdr->p_vaddr + phdr->p_filesz, align);
|
||||
vend = ROUNDUP(phdr->p_vaddr + phdr->p_memsz, align);
|
||||
fstart = ROUNDDOWN(felf + phdr->p_offset, align);
|
||||
fend = ROUNDUP(felf + phdr->p_offset + phdr->p_filesz, align);
|
||||
fstart = felf + ROUNDDOWN(phdr->p_offset, align);
|
||||
fend = felf + ROUNDUP(phdr->p_offset + phdr->p_filesz, align);
|
||||
bsssize = vend - vbss;
|
||||
CHECK_GE(vend, vstart);
|
||||
CHECK_GE(fend, fstart);
|
||||
|
@ -112,9 +112,11 @@ static void LoadBin(struct Machine *m, intptr_t base, const char *prog,
|
|||
void LoadProgram(struct Machine *m, const char *prog, char **args, char **vars,
|
||||
struct Elf *elf) {
|
||||
int fd;
|
||||
char *real;
|
||||
ssize_t rc;
|
||||
struct stat st;
|
||||
void *code, *stack;
|
||||
size_t codesize, stacksize;
|
||||
size_t i, codesize, mappedsize, extrasize, stacksize;
|
||||
DCHECK_NOTNULL(prog);
|
||||
elf->prog = prog;
|
||||
if ((fd = open(prog, O_RDONLY)) == -1 ||
|
||||
|
@ -123,16 +125,30 @@ void LoadProgram(struct Machine *m, const char *prog, char **args, char **vars,
|
|||
fputs(": not found\n", stderr);
|
||||
exit(1);
|
||||
}
|
||||
codesize = st.st_size;
|
||||
stacksize = STACKSIZE;
|
||||
codesize = st.st_size;
|
||||
mappedsize = ROUNDDOWN(codesize, FRAMESIZE);
|
||||
extrasize = codesize - mappedsize;
|
||||
CHECK_NE(MAP_FAILED, (stack = mmap(NULL, stacksize, PROT_READ | PROT_WRITE,
|
||||
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0)));
|
||||
CHECK_NE(MAP_FAILED, (code = mmap(NULL, codesize, PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE, fd, 0)));
|
||||
code = real = (char *)0x0000400000000000;
|
||||
if (mappedsize) {
|
||||
CHECK_NE(MAP_FAILED, mmap(real, mappedsize, PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_FIXED, fd, 0));
|
||||
real += mappedsize;
|
||||
}
|
||||
if (extrasize) {
|
||||
CHECK_NE(MAP_FAILED,
|
||||
mmap(real, ROUNDUP(extrasize, FRAMESIZE), PROT_READ | PROT_WRITE,
|
||||
MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0));
|
||||
for (i = 0; i < extrasize; i += (size_t)rc) {
|
||||
CHECK_NE(-1, (rc = pread(fd, real + i, extrasize - i, mappedsize + i)));
|
||||
}
|
||||
}
|
||||
CHECK_NE(-1, close(fd));
|
||||
ResetCpu(m);
|
||||
Write64(m->sp, 0x800000000000);
|
||||
RegisterMemory(m, 0x800000000000 - stacksize, stack, stacksize);
|
||||
Write64(m->sp, 0x0000800000000000);
|
||||
RegisterMemory(m, 0x0000800000000000 - stacksize, stack, stacksize);
|
||||
LoadArgv(m, prog, args, vars);
|
||||
if (memcmp(code, "\177ELF", 4) == 0) {
|
||||
elf->ehdr = code;
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -60,7 +60,7 @@ struct Machine {
|
|||
struct TlbEntry {
|
||||
int64_t v;
|
||||
void *r;
|
||||
} tlb[4];
|
||||
} tlb[16];
|
||||
uint8_t *veg[2 * 8];
|
||||
uint8_t *beg[2 * 2 * 8];
|
||||
struct MachineFpu {
|
||||
|
|
|
@ -52,6 +52,40 @@ static uint64_t *GetPageTable(pml4t_t p, long i, void *NewPhysicalPage(void)) {
|
|||
return res;
|
||||
}
|
||||
|
||||
static void PtFinder(uint64_t *a, uint64_t *b, uint64_t n, pml4t_t pd, int k) {
|
||||
uint64_t e, c;
|
||||
unsigned start;
|
||||
for (start = (*b >> k) & 511; *b - *a < n && ((*b >> k) & 511) >= start;) {
|
||||
e = pd[(*b >> k) & 511];
|
||||
c = ROUNDUP(*b + 1, 1 << k);
|
||||
if (!IsValidPage(e)) {
|
||||
*b = c;
|
||||
} else if (k && *b - *a + (c - *b) > n) {
|
||||
PtFinder(a, b, n, UnmaskPageAddr(e), k - 9);
|
||||
} else {
|
||||
*a = *b = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Locates free memory range.
|
||||
*
|
||||
* @param h specifies signedness and around where to start searching
|
||||
* @return virtual page address with size bytes free, or -1 w/ errno
|
||||
*/
|
||||
int64_t FindPml4t(pml4t_t pml4t, uint64_t h, uint64_t n) {
|
||||
uint64_t a, b;
|
||||
n = ROUNDUP(n, 4096) >> 12;
|
||||
a = b = (h & 0x0000fffffffff000) >> 12;
|
||||
if (!n || n > 0x10000000) return einval();
|
||||
PtFinder(&a, &b, n, pml4t, 9 * 3);
|
||||
if (b > 0x0000001000000000) return eoverflow();
|
||||
if (h < 0x0000800000000000 && b > 0x0000000800000000) return eoverflow();
|
||||
if (b - a < n) return enomem();
|
||||
return a << 12;
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps virtual page region to system memory region.
|
||||
*
|
||||
|
@ -95,70 +129,6 @@ int RegisterPml4t(pml4t_t pml4t, int64_t v, int64_t r, size_t n,
|
|||
return enomem();
|
||||
}
|
||||
|
||||
/**
|
||||
* Locates free memory range.
|
||||
*
|
||||
* @param hint specifies signedness and around where to start searching
|
||||
* @return virtual page address with size bytes free, or -1 w/ errno
|
||||
*/
|
||||
int64_t FindPml4t(pml4t_t pml4t, int64_t hint, uint64_t size,
|
||||
void *NewPhysicalPage(void)) {
|
||||
int64_t res;
|
||||
unsigned short a[4], b[4];
|
||||
uint64_t *pdpt, *pdt, *pd, have;
|
||||
if (!size) return einval();
|
||||
have = 0;
|
||||
size = ROUNDUP(size, 4096) >> 12;
|
||||
b[0] = a[0] = (hint >> 39) & 511;
|
||||
b[1] = a[1] = (hint >> 30) & 511;
|
||||
b[2] = a[2] = (hint >> 21) & 511;
|
||||
a[3] = 0;
|
||||
for (; b[0] < 512; ++b[0]) {
|
||||
if (!(pdpt = GetPageTable(pml4t, b[0], NewPhysicalPage))) return -1;
|
||||
for (; b[1] < 512; ++b[1]) {
|
||||
if (!(pdt = GetPageTable(pdpt, b[1], NewPhysicalPage))) return -1;
|
||||
for (; b[2] < 512; ++b[2]) {
|
||||
if (!IsValidPage(pdt[b[2]])) {
|
||||
if ((have += 512) >= size) {
|
||||
return MakeAddress(a);
|
||||
}
|
||||
} else if (size < 0x200) {
|
||||
pd = UnmaskPageAddr(pdt[b[2]]);
|
||||
for (b[3] = 0; b[3] < 512; ++b[3]) {
|
||||
if (!IsValidPage(pd[b[3]])) {
|
||||
if ((have += 1) >= size) {
|
||||
return MakeAddress(a);
|
||||
}
|
||||
} else {
|
||||
have = 0;
|
||||
a[0] = b[0];
|
||||
a[1] = b[1];
|
||||
a[2] = b[2];
|
||||
a[3] = b[3];
|
||||
if ((a[3] += 1) == 512) {
|
||||
a[3] = 0;
|
||||
if ((a[2] += 1) == 512) {
|
||||
a[2] = 0;
|
||||
if ((a[1] += 1) == 512) {
|
||||
a[1] = 0;
|
||||
a[0] += 1;
|
||||
if (a[0] == 256 || a[0] == 512) {
|
||||
return eoverflow();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
a[2] = 0;
|
||||
}
|
||||
a[1] = 0;
|
||||
}
|
||||
return enomem();
|
||||
}
|
||||
|
||||
/**
|
||||
* Unmaps pages and frees page tables.
|
||||
*/
|
||||
|
|
|
@ -13,7 +13,7 @@ typedef uint64_t pml4t_t[512] aligned(4096);
|
|||
int FreePml4t(pml4t_t, int64_t, uint64_t, void (*)(void *),
|
||||
int (*)(void *, size_t));
|
||||
int RegisterPml4t(pml4t_t, int64_t, int64_t, size_t, void *(*)(void));
|
||||
int64_t FindPml4t(pml4t_t, int64_t, uint64_t, void *(*)(void));
|
||||
int64_t FindPml4t(pml4t_t, uint64_t, uint64_t);
|
||||
char *FormatPml4t(pml4t_t) nodiscard;
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
|
|
|
@ -68,10 +68,6 @@ static void ResetTlb(struct Machine *m) {
|
|||
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) {
|
||||
m->codevirt = 0;
|
||||
m->codereal = NULL;
|
||||
|
@ -96,5 +92,4 @@ void ResetCpu(struct Machine *m) {
|
|||
ResetTlb(m);
|
||||
ResetSse(m);
|
||||
ResetFpu(m);
|
||||
ResetMem(m);
|
||||
}
|
||||
|
|
|
@ -67,16 +67,14 @@ static void WriteInt(uint8_t p[8], uint64_t x, unsigned long w) {
|
|||
|
||||
void OpString(struct Machine *m, uint32_t rde, int op) {
|
||||
void *p[2];
|
||||
unsigned n;
|
||||
uint64_t asz;
|
||||
bool compare;
|
||||
int64_t sgn, v;
|
||||
uint8_t s[3][8];
|
||||
unsigned n, lg2;
|
||||
uint64_t asz, seg;
|
||||
sgn = GetFlag(m->flags, FLAGS_DF) ? -1 : 1;
|
||||
asz = Asz(rde) ? 0xffffffff : 0xffffffffffffffff;
|
||||
seg = GetSegment(m);
|
||||
lg2 = RegLog2(rde);
|
||||
n = 1 << lg2;
|
||||
n = 1 << RegLog2(rde);
|
||||
for (;;) {
|
||||
if (Rep(rde) && !Read64(m->cx)) break;
|
||||
v = 0;
|
||||
|
@ -84,16 +82,18 @@ void OpString(struct Machine *m, uint32_t rde, int op) {
|
|||
compare = false;
|
||||
switch (op) {
|
||||
case STRING_CMPS:
|
||||
Alu(lg2, ALU_SUB,
|
||||
ReadInt(Load(m, (Read64(m->si) + seg) & asz, n, s[2]), lg2),
|
||||
ReadInt(Load(m, Read64(m->di) & asz, n, s[1]), lg2), &m->flags);
|
||||
Alu(RegLog2(rde), ALU_SUB,
|
||||
ReadInt(Load(m, (Read64(m->si) + GetSegment(m)) & asz, n, s[2]),
|
||||
RegLog2(rde)),
|
||||
ReadInt(Load(m, Read64(m->di) & asz, n, s[1]), RegLog2(rde)),
|
||||
&m->flags);
|
||||
Write64(m->di, (Read64(m->di) + sgn * n) & asz);
|
||||
Write64(m->si, (Read64(m->si) + sgn * n) & asz);
|
||||
compare = true;
|
||||
break;
|
||||
case STRING_MOVS:
|
||||
memcpy(BeginStore(m, (v = Read64(m->di) & asz), n, p, s[0]),
|
||||
Load(m, (Read64(m->si) + seg) & asz, n, s[1]), n);
|
||||
Load(m, (Read64(m->si) + GetSegment(m)) & asz, n, s[1]), n);
|
||||
Write64(m->di, (Read64(m->di) + sgn * n) & asz);
|
||||
Write64(m->si, (Read64(m->si) + sgn * n) & asz);
|
||||
break;
|
||||
|
@ -102,23 +102,26 @@ void OpString(struct Machine *m, uint32_t rde, int op) {
|
|||
Write64(m->di, (Read64(m->di) + sgn * n) & asz);
|
||||
break;
|
||||
case STRING_LODS:
|
||||
memcpy(m->ax, Load(m, (Read64(m->si) + seg) & asz, n, s[1]), n);
|
||||
memcpy(m->ax, Load(m, (Read64(m->si) + GetSegment(m)) & asz, n, s[1]),
|
||||
n);
|
||||
Write64(m->si, (Read64(m->si) + sgn * n) & asz);
|
||||
break;
|
||||
case STRING_SCAS:
|
||||
Alu(lg2, ALU_SUB, ReadInt(Load(m, Read64(m->di) & asz, n, s[1]), lg2),
|
||||
ReadInt(m->ax, lg2), &m->flags);
|
||||
Alu(RegLog2(rde), ALU_SUB,
|
||||
ReadInt(Load(m, Read64(m->di) & asz, n, s[1]), RegLog2(rde)),
|
||||
ReadInt(m->ax, RegLog2(rde)), &m->flags);
|
||||
Write64(m->di, (Read64(m->di) + sgn * n) & asz);
|
||||
compare = true;
|
||||
break;
|
||||
case STRING_OUTS:
|
||||
OpOut(m, Read16(m->dx),
|
||||
ReadInt(Load(m, (Read64(m->si) + seg) & asz, n, s[1]), lg2));
|
||||
ReadInt(Load(m, (Read64(m->si) + GetSegment(m)) & asz, n, s[1]),
|
||||
RegLog2(rde)));
|
||||
Write64(m->si, (Read64(m->si) + sgn * n) & asz);
|
||||
break;
|
||||
case STRING_INS:
|
||||
WriteInt(BeginStore(m, (v = Read64(m->di) & asz), n, p, s[0]),
|
||||
OpIn(m, Read16(m->dx)), lg2);
|
||||
OpIn(m, Read16(m->dx)), RegLog2(rde));
|
||||
Write64(m->di, (Read64(m->di) + sgn * n) & asz);
|
||||
break;
|
||||
default:
|
||||
|
@ -138,19 +141,18 @@ void OpRepMovsbEnhanced(struct Machine *m, uint32_t rde) {
|
|||
bool failed;
|
||||
uint8_t *direal, *sireal;
|
||||
unsigned diremain, siremain, i, n;
|
||||
uint64_t divirtual, sivirtual, diactual, siactual, failaddr, seg, asz, cx;
|
||||
uint64_t divirtual, sivirtual, diactual, siactual, failaddr, asz, cx;
|
||||
if (!(cx = Read64(m->cx))) return;
|
||||
failed = false;
|
||||
failaddr = 0;
|
||||
seg = GetSegment(m);
|
||||
asz = Asz(rde) ? 0xffffffff : 0xffffffffffffffff;
|
||||
divirtual = Read64(m->di) & asz;
|
||||
sivirtual = Read64(m->si) & asz;
|
||||
SetWriteAddr(m, (seg + divirtual) & asz, cx);
|
||||
SetReadAddr(m, (seg + sivirtual) & asz, cx);
|
||||
SetWriteAddr(m, (GetSegment(m) + divirtual) & asz, cx);
|
||||
SetReadAddr(m, (GetSegment(m) + sivirtual) & asz, cx);
|
||||
do {
|
||||
diactual = (seg + divirtual) & asz;
|
||||
siactual = (seg + sivirtual) & asz;
|
||||
diactual = (GetSegment(m) + divirtual) & asz;
|
||||
siactual = (GetSegment(m) + sivirtual) & asz;
|
||||
if (!(direal = FindReal(m, diactual))) {
|
||||
failaddr = diactual;
|
||||
failed = true;
|
||||
|
@ -181,17 +183,16 @@ void OpRepStosbEnhanced(struct Machine *m, uint32_t rde) {
|
|||
bool failed;
|
||||
uint8_t *direal, al;
|
||||
unsigned diremain, i, n;
|
||||
uint64_t divirtual, diactual, failaddr, seg, asz, cx;
|
||||
uint64_t divirtual, diactual, failaddr, asz, cx;
|
||||
if (!(cx = Read64(m->cx))) return;
|
||||
failaddr = 0;
|
||||
failed = false;
|
||||
al = Read8(m->ax);
|
||||
seg = GetSegment(m);
|
||||
asz = Asz(rde) ? 0xffffffff : 0xffffffffffffffff;
|
||||
divirtual = Read64(m->di) & asz;
|
||||
SetWriteAddr(m, (seg + divirtual) & asz, cx);
|
||||
SetWriteAddr(m, (GetSegment(m) + divirtual) & asz, cx);
|
||||
do {
|
||||
diactual = (seg + divirtual) & asz;
|
||||
diactual = (GetSegment(m) + divirtual) & asz;
|
||||
if (!(direal = FindReal(m, diactual))) {
|
||||
failaddr = diactual;
|
||||
failed = true;
|
||||
|
|
|
@ -66,7 +66,7 @@
|
|||
#define P(x) ((x) ? PNN(x) : 0)
|
||||
#define ASSIGN(D, S) memcpy(&D, &S, MIN(sizeof(S), sizeof(D)))
|
||||
|
||||
static const struct MachineFdCb kMachineFdCbHost = {
|
||||
const struct MachineFdCb kMachineFdCbHost = {
|
||||
.close = close,
|
||||
.read = read,
|
||||
.write = write,
|
||||
|
@ -282,7 +282,7 @@ static int64_t OpMmap(struct Machine *m, int64_t virt, size_t size, int prot,
|
|||
if (real == MAP_FAILED) return -1;
|
||||
if (!(flags & MAP_FIXED)) {
|
||||
if (0 <= virt && virt < 0x400000) virt = 0x400000;
|
||||
if ((virt = FindPml4t(m->cr3, virt, size, MallocPage)) == -1) return -1;
|
||||
if ((virt = FindPml4t(m->cr3, virt, size)) == -1) return -1;
|
||||
}
|
||||
CHECK_NE(-1, RegisterMemory(m, virt, real, size));
|
||||
return virt;
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_SYSCALL_H_
|
||||
#define COSMOPOLITAN_TOOL_BUILD_LIB_SYSCALL_H_
|
||||
#include "tool/build/lib/fds.h"
|
||||
#include "tool/build/lib/machine.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
extern const struct MachineFdCb kMachineFdCbHost;
|
||||
|
||||
void OpSyscall(struct Machine *);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
|
|
64
tool/build/lib/word.c
Normal file
64
tool/build/lib/word.c
Normal file
|
@ -0,0 +1,64 @@
|
|||
/*-*- 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 "tool/build/lib/endian.h"
|
||||
#include "tool/build/lib/memory.h"
|
||||
#include "tool/build/lib/word.h"
|
||||
|
||||
void SetMemoryShort(struct Machine *m, int64_t v, int16_t i) {
|
||||
void *p[2];
|
||||
uint8_t b[2];
|
||||
Write16(BeginStore(m, v, 2, p, b), i);
|
||||
EndStore(m, v, 2, p, b);
|
||||
}
|
||||
|
||||
void SetMemoryInt(struct Machine *m, int64_t v, int32_t i) {
|
||||
void *p[2];
|
||||
uint8_t b[4];
|
||||
Write32(BeginStore(m, v, 4, p, b), i);
|
||||
EndStore(m, v, 4, p, b);
|
||||
}
|
||||
|
||||
void SetMemoryLong(struct Machine *m, int64_t v, int64_t i) {
|
||||
void *p[2];
|
||||
uint8_t b[8];
|
||||
Write64(BeginStore(m, v, 8, p, b), i);
|
||||
EndStore(m, v, 8, p, b);
|
||||
}
|
||||
|
||||
void SetMemoryFloat(struct Machine *m, int64_t v, float f) {
|
||||
void *p[2];
|
||||
uint8_t b[4];
|
||||
memcpy(BeginStore(m, v, 4, p, b), &f, 4);
|
||||
EndStore(m, v, 4, p, b);
|
||||
}
|
||||
|
||||
void SetMemoryDouble(struct Machine *m, int64_t v, double f) {
|
||||
void *p[2];
|
||||
uint8_t b[8];
|
||||
memcpy(BeginStore(m, v, 8, p, b), &f, 8);
|
||||
EndStore(m, v, 8, p, b);
|
||||
}
|
||||
|
||||
void SetMemoryLdbl(struct Machine *m, int64_t v, long double f) {
|
||||
void *p[2];
|
||||
uint8_t b[10];
|
||||
memcpy(BeginStore(m, v, 10, p, b), &f, 10);
|
||||
EndStore(m, v, 10, p, b);
|
||||
}
|
16
tool/build/lib/word.h
Normal file
16
tool/build/lib/word.h
Normal file
|
@ -0,0 +1,16 @@
|
|||
#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_WORD_H_
|
||||
#define COSMOPOLITAN_TOOL_BUILD_LIB_WORD_H_
|
||||
#include "tool/build/lib/machine.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
void SetMemoryShort(struct Machine *, int64_t, int16_t);
|
||||
void SetMemoryInt(struct Machine *, int64_t, int32_t);
|
||||
void SetMemoryLong(struct Machine *, int64_t, int64_t);
|
||||
void SetMemoryFloat(struct Machine *, int64_t, float);
|
||||
void SetMemoryDouble(struct Machine *, int64_t, double);
|
||||
void SetMemoryLdbl(struct Machine *, int64_t, long double);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_WORD_H_ */
|
|
@ -59,7 +59,7 @@ long double fyl2xp1(long double x, long double y) {
|
|||
}
|
||||
|
||||
long double fscale(long double significand, long double exponent) {
|
||||
return scalbnl(significand, exponent);
|
||||
return scalbl(significand, exponent);
|
||||
}
|
||||
|
||||
long double fprem(long double dividend, long double modulus, uint32_t *sw) {
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/alg/alg.h"
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/hefty/spawn.h"
|
||||
|
@ -273,7 +274,7 @@ int ReadResponse(void) {
|
|||
if (!n) break;
|
||||
do {
|
||||
CHECK_GE(n, 4 + 1);
|
||||
CHECK_EQ(RUNITD_MAGIC, read32be(p));
|
||||
CHECK_EQ(RUNITD_MAGIC, READ32BE(p));
|
||||
p += 4, n -= 4;
|
||||
cmd = *p++, n--;
|
||||
switch (cmd) {
|
||||
|
|
|
@ -20,8 +20,11 @@
|
|||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/sysv/consts/ex.h"
|
||||
#include "libc/sysv/consts/fileno.h"
|
||||
#include "libc/x/x.h"
|
||||
#include "tool/build/lib/loader.h"
|
||||
#include "tool/build/lib/machine.h"
|
||||
#include "tool/build/lib/syscall.h"
|
||||
|
||||
struct Machine m[1];
|
||||
|
||||
|
@ -38,6 +41,15 @@ int main(int argc, char *argv[]) {
|
|||
}
|
||||
InitMachine(m);
|
||||
LoadProgram(m, argv[1], argv + 2, environ, &elf);
|
||||
m->fds.i = 3;
|
||||
m->fds.n = 8;
|
||||
m->fds.p = xcalloc(m->fds.n, sizeof(struct MachineFd));
|
||||
m->fds.p[0].fd = STDIN_FILENO;
|
||||
m->fds.p[0].cb = &kMachineFdCbHost;
|
||||
m->fds.p[1].fd = STDOUT_FILENO;
|
||||
m->fds.p[1].cb = &kMachineFdCbHost;
|
||||
m->fds.p[2].fd = STDERR_FILENO;
|
||||
m->fds.p[2].cb = &kMachineFdCbHost;
|
||||
if (!(rc = setjmp(m->onhalt))) {
|
||||
for (;;) {
|
||||
LoadInstruction(m);
|
||||
|
|
|
@ -149,7 +149,23 @@
|
|||
"__builtin_infl"
|
||||
"__builtin_inffn"
|
||||
"__builtin_inffnx"
|
||||
"__builtin_isnan"
|
||||
"__builtin_signbit"
|
||||
"__builtin_signbitf"
|
||||
"__builtin_signbitl"
|
||||
"__builtin_isfinite"
|
||||
"__builtin_isinf"
|
||||
"__builtin_isinfinite"
|
||||
"__builtin_isnormal"
|
||||
"__builtin_isinf_sign"
|
||||
"__builtin_isgreater"
|
||||
"__builtin_isgreaterequal"
|
||||
"__builtin_isgreater"
|
||||
"__builtin_isgreaterequal"
|
||||
"__builtin_isless"
|
||||
"__builtin_islessequal"
|
||||
"__builtin_islessgreater"
|
||||
"__builtin_isunordered"
|
||||
"__builtin_nan"
|
||||
"__builtin_nand32"
|
||||
"__builtin_nand64"
|
||||
|
|
|
@ -296,6 +296,7 @@
|
|||
"__params_nonnull__"
|
||||
"__weak__"
|
||||
"__vector_size__"
|
||||
"__ms_abi__"
|
||||
"__mode__"))
|
||||
|
||||
(clang
|
||||
|
|
|
@ -105,6 +105,7 @@
|
|||
"PAGESIZE"
|
||||
"FRAMESIZE"
|
||||
"BIGPAGESIZE"
|
||||
"STACKSIZE"
|
||||
"ENV_MAX"
|
||||
"ARG_MAX"
|
||||
"CMD_MAX"
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/conv/conv.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/macros.h"
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
COSMOPOLITAN_C_START_
|
||||
|
||||
typedef void *StringTableFormatter(long yn, long xn, const char *const[yn][xn],
|
||||
int emit(), void *, const char *,
|
||||
int (*)(), void *, const char *,
|
||||
const char *, const char *);
|
||||
|
||||
StringTableFormatter FormatStringTable;
|
||||
|
@ -15,28 +15,27 @@ StringTableFormatter FormatStringTableForAssertion;
|
|||
|
||||
void *FreeStringTableCells(long yn, long xn, char *[yn][xn]);
|
||||
|
||||
void FormatMatrixDouble(long yn, long xn, const double[yn][xn], int emit(),
|
||||
void FormatMatrixDouble(long yn, long xn, const double[yn][xn], int (*)(),
|
||||
void *, StringTableFormatter, const char *,
|
||||
const char *, const char *, double,
|
||||
double rounder(double));
|
||||
void FormatMatrixFloat(long yn, long xn, const float[yn][xn], int emit(),
|
||||
void *, StringTableFormatter, const char *, const char *,
|
||||
const char *, double, double rounder(double));
|
||||
void FormatMatrixByte(long yn, long xn, const unsigned char[yn][xn], int emit(),
|
||||
const char *, const char *, double, double (*)(double));
|
||||
void FormatMatrixFloat(long yn, long xn, const float[yn][xn], int (*)(), void *,
|
||||
StringTableFormatter, const char *, const char *,
|
||||
const char *, double, double (*)(double));
|
||||
void FormatMatrixByte(long yn, long xn, const unsigned char[yn][xn], int (*)(),
|
||||
void *, StringTableFormatter, const char *, const char *,
|
||||
const char *);
|
||||
void FormatMatrixShort(long yn, long xn, const short[yn][xn], int emit(),
|
||||
void *, StringTableFormatter, const char *, const char *,
|
||||
void FormatMatrixShort(long yn, long xn, const short[yn][xn], int (*)(), void *,
|
||||
StringTableFormatter, const char *, const char *,
|
||||
const char *);
|
||||
|
||||
char *StringifyMatrixDouble(long yn, long xn, const double[yn][xn],
|
||||
StringTableFormatter, const char *, const char *,
|
||||
const char *, double,
|
||||
double rounder(double)) mallocesque;
|
||||
double (*)(double)) mallocesque;
|
||||
char *StringifyMatrixFloat(long yn, long xn, const float[yn][xn],
|
||||
StringTableFormatter, const char *, const char *,
|
||||
const char *, double,
|
||||
double rounder(double)) mallocesque;
|
||||
double (*)(double)) mallocesque;
|
||||
char *StringifyMatrixByte(long yn, long xn, const unsigned char[yn][xn],
|
||||
StringTableFormatter, const char *, const char *,
|
||||
const char *) mallocesque;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue