Fix bugs and have emulator emulate itself

This commit is contained in:
Justine Tunney 2020-08-31 05:17:31 -07:00
parent 5aabacb361
commit bd29223891
111 changed files with 1283 additions and 2073 deletions

View file

@ -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;

View file

@ -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

View file

@ -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))

View file

@ -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_ */

View file

@ -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);
}

View file

@ -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"

View file

@ -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"

View file

@ -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));

View file

@ -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;
}

View file

@ -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

View file

@ -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 {

View file

@ -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.
*/

View file

@ -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_

View file

@ -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);
}

View file

@ -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;

View file

@ -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;

View file

@ -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
View 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
View 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_ */

View file

@ -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) {