diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2023-03-27 23:21:36 +0200 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2023-03-27 23:21:36 +0200 |
| commit | 9f75f28e7a464734bab8e719c1a60178280b224d (patch) | |
| tree | 6c7d9c2d1e1c4d307e7acfbcbf92b04c7e83dea1 /src | |
| parent | feb4a394577ea152b60393875860c551a7573adf (diff) | |
| download | box64-9f75f28e7a464734bab8e719c1a60178280b224d.tar.gz box64-9f75f28e7a464734bab8e719c1a60178280b224d.zip | |
[DYNAREC] Added BOX64_DYNAREC_TEST to run interpeter and dynarec at the same time and compare states
Diffstat (limited to 'src')
43 files changed, 1089 insertions, 62 deletions
diff --git a/src/box64context.c b/src/box64context.c index 589493ec..bae00f9c 100755 --- a/src/box64context.c +++ b/src/box64context.c @@ -143,6 +143,7 @@ static void init_mutexes(box64context_t* context) native_lock_store(&context->mutex_thread, 0); native_lock_store(&context->mutex_bridge, 0); native_lock_store(&context->mutex_dyndump, 0); + pthread_mutex_init(&context->mutex_lock, NULL); #endif } @@ -325,7 +326,9 @@ void FreeBox64Context(box64context_t** context) finiAllHelpers(ctx); -#ifndef DYNAREC +#ifdef DYNAREC + pthread_mutex_destroy(&ctx->mutex_lock); +#else pthread_mutex_destroy(&ctx->mutex_trace); pthread_mutex_destroy(&ctx->mutex_lock); pthread_mutex_destroy(&ctx->mutex_tls); diff --git a/src/dynarec/arm64/dynarec_arm64_00.c b/src/dynarec/arm64/dynarec_arm64_00.c index 2118580a..7a91dcf1 100755 --- a/src/dynarec/arm64/dynarec_arm64_00.c +++ b/src/dynarec/arm64/dynarec_arm64_00.c @@ -499,9 +499,10 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin case 0x56: case 0x57: INST_NAME("PUSH reg"); - if(dyn->doublepush) + if(dyn->doublepush) { + dyn->test = 0; dyn->doublepush = 0; - else { + } else { gd = xRAX+(opcode&0x07)+(rex.b<<3); if(gd==xRSP) { MOVx_REG(x1, gd); @@ -524,6 +525,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } PUSH2(gd, u32); dyn->doublepush = 1; + dyn->test = 0; // disable test for this OP } else { PUSH1(gd); } @@ -538,9 +540,10 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin case 0x5E: case 0x5F: INST_NAME("POP reg"); - if(dyn->doublepop) + if(dyn->doublepop) { + dyn->test = 0; dyn->doublepop = 0; - else { + } else { gd = xRAX+(opcode&0x07)+(rex.b<<3); u32 = 0; i32 = 0; @@ -563,6 +566,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } } dyn->doublepop = 1; + dyn->test = 0; // disable test for this OP } else { if(gd == xRSP) { POP1(x1); @@ -1745,6 +1749,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin case 0xCC: SETFLAGS(X_ALL, SF_SET); // Hack, set all flags (to an unknown state...) + dyn->test = 0; if(PK(0)=='S' && PK(1)=='C') { addr+=2; BARRIER(BARRIER_FLOAT); @@ -2211,6 +2216,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } PUSH1(x2); MESSAGE(LOG_DUMP, "Native Call to %s (retn=%d)\n", GetNativeName(GetNativeFnc(dyn->insts[ninst].natcall-1)), dyn->insts[ninst].retn); + dyn->test=0; // disable test as this hack dos 2 instructions for 1 // calling a native function sse_purge07cache(dyn, ninst, x3); if((box64_log<2 && !cycle_log) && dyn->insts[ninst].natcall) diff --git a/src/dynarec/arm64/dynarec_arm64_private.h b/src/dynarec/arm64/dynarec_arm64_private.h index c966f9b3..b9b91483 100755 --- a/src/dynarec/arm64/dynarec_arm64_private.h +++ b/src/dynarec/arm64/dynarec_arm64_private.h @@ -106,6 +106,7 @@ typedef struct dynarec_arm_s { size_t insts_size; // size of the instruction size array (calculated) uint8_t smread; // for strongmem model emulation uint8_t smwrite; // for strongmem model emulation + int8_t test; // test the opcode? uintptr_t forward; // address of the last end of code while testing forward uintptr_t forward_to; // address of the next jump to (to check if everything is ok) int32_t forward_size; // size at the forward point @@ -123,12 +124,12 @@ int Table64(dynarec_arm_t *dyn, uint64_t val); // add a value to etable64 (if n void CreateJmpNext(void* addr, void* next); -#define GO_TRACE() \ - GETIP_(ip); \ +#define GO_TRACE(A, B) \ + GETIP_(addr); \ MOVx_REG(x1, xRIP); \ STORE_XEMU_CALL(xRIP); \ - MOV32w(x2, 1); \ - CALL(PrintTrace, -1); \ + MOV32w(x2, B); \ + CALL(A, -1); \ LOAD_XEMU_CALL(xRIP) #endif //__DYNAREC_ARM_PRIVATE_H_ diff --git a/src/dynarec/dynarec_native_pass.c b/src/dynarec/dynarec_native_pass.c index 4b1c976d..80da9436 100755 --- a/src/dynarec/dynarec_native_pass.c +++ b/src/dynarec/dynarec_native_pass.c @@ -83,13 +83,20 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr) if((dyn->insts[ninst].x64.need_before&~X_PEND) && !dyn->insts[ninst].pred_sz) { READFLAGS(dyn->insts[ninst].x64.need_before&~X_PEND); } + if(box64_dynarec_test) { + MESSAGE(LOG_DUMP, "TEST INIT ----\n"); + fpu_reflectcache(dyn, ninst, x1, x2, x3); + GO_TRACE(x64test_init, dyn->test); + MESSAGE(LOG_DUMP, "----------\n"); + dyn->test = 1; + } #ifdef HAVE_TRACE - if(my_context->dec && box64_dynarec_trace) { + else if(my_context->dec && box64_dynarec_trace) { if((trace_end == 0) || ((ip >= trace_start) && (ip < trace_end))) { MESSAGE(LOG_DUMP, "TRACE ----\n"); fpu_reflectcache(dyn, ninst, x1, x2, x3); - GO_TRACE(); + GO_TRACE(PrintTrace, 1); MESSAGE(LOG_DUMP, "----------\n"); } } @@ -115,6 +122,13 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr) addr = dynarec64_00(dyn, addr, ip, ninst, rex, rep, &ok, &need_epilog); + if(dyn->test) { + MESSAGE(LOG_DUMP, "TEST CHECK ----\n"); + fpu_reflectcache(dyn, ninst, x1, x2, x3); + GO_TRACE(x64test_check, 1); + MESSAGE(LOG_DUMP, "----------\n"); + } + INST_EPILOG; int next = ninst+1; diff --git a/src/dynarec/rv64/dynarec_rv64_00.c b/src/dynarec/rv64/dynarec_rv64_00.c index e6bfe91f..2b62f097 100644 --- a/src/dynarec/rv64/dynarec_rv64_00.c +++ b/src/dynarec/rv64/dynarec_rv64_00.c @@ -1270,6 +1270,7 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni case 0xCC: SETFLAGS(X_ALL, SF_SET); // Hack, set all flags (to an unknown state...) + dyn->test=0; if(PK(0)=='S' && PK(1)=='C') { addr+=2; BARRIER(BARRIER_FLOAT); @@ -1463,6 +1464,7 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni switch(tmp) { case 3: SETFLAGS(X_ALL, SF_SET); // Hack to set flags to "dont'care" state + dyn->test = 0; BARRIER(BARRIER_FULL); //BARRIER_NEXT(BARRIER_FULL); if(dyn->last_ip && (addr-dyn->last_ip<0x1000)) { diff --git a/src/dynarec/rv64/dynarec_rv64_private.h b/src/dynarec/rv64/dynarec_rv64_private.h index bf510c0b..4f9bdd63 100644 --- a/src/dynarec/rv64/dynarec_rv64_private.h +++ b/src/dynarec/rv64/dynarec_rv64_private.h @@ -107,6 +107,7 @@ typedef struct dynarec_rv64_s { size_t insts_size; // size of the instruction size array (calculated) uint8_t smread; // for strongmem model emulation uint8_t smwrite; // for strongmem model emulation + int8_t test; // test the opcode? uintptr_t forward; // address of the last end of code while testing forward uintptr_t forward_to; // address of the next jump to (to check if everything is ok) int32_t forward_size; // size at the forward point @@ -127,12 +128,12 @@ int Table64(dynarec_rv64_t *dyn, uint64_t val); // add a value to etable64 (if void CreateJmpNext(void* addr, void* next); -#define GO_TRACE() \ +#define GO_TRACE(A, B) \ GETIP_(ip); \ MV(A1, xRIP); \ STORE_XEMU_CALL(); \ - MOV64x(A2, 1); \ - CALL(PrintTrace, -1); \ + MOV64x(A2, B); \ + CALL(A, -1); \ LOAD_XEMU_CALL() #endif //__DYNAREC_RV64_PRIVATE_H_ \ No newline at end of file diff --git a/src/emu/modrm.h b/src/emu/modrm.h index c01343b0..e3fc1e98 100644 --- a/src/emu/modrm.h +++ b/src/emu/modrm.h @@ -18,6 +18,27 @@ #define STEP3 #endif +#ifdef TEST_INTERPRETER +#define GETED(D) oped=TestEd(test, &addr, rex, nextop, D) +#define GETED32(D) oped=TestEd32O(test, &addr, rex, nextop, D, 0) +#define GETED_OFFS(D, O) oped=TestEdO(test, &addr, rex, nextop, D, O) +#define GETGD opgd=GetGd(test->emu, &addr, rex, nextop) +#define GETEB(D) oped=TestEb(test, &addr, rex, nextop, D) +#define GETEB32(D) oped=TestEb32O(test, &addr, rex, nextop, D, 0) +#define GETEB_OFFS(D, O) oped=TestEbO(test, &addr, rex, nextop, D, O) +#define GETGB opgd=GetGb(test->emu, &addr, rex, nextop) +#define GETEW(D) oped=TestEw(test, &addr, rex, nextop, D) +#define GETEW32(D) oped=TestEw32O(test, &addr, rex, nextop, D, 0) +#define GETEW_OFFS(D, O) oped=TestEdO(test, &addr, rex, nextop, D, O) +#define GETGW opgd=GetGw(test->emu, &addr, rex, nextop) +#define GETEX(D) opex=TestEx(test, &addr, rex, nextop, D) +#define GETEX32(D) opex=TestEx32O(test, &addr, rex, nextop, D, 0) +#define GETEX_OFFS(D, O) opex=TestExO(test, &addr, rex, nextop, D, O) +#define GETGX opgx=GetGx(test->emu, &addr, rex, nextop) +#define GETEM(D) opem=TestEm(test, &addr, rex, nextop, D) +#define GETEM32(D) opem=TestEm32O(test, &addr, rex, nextop, D, 0) +#define GETGM opgm=GetGm(test->emu, &addr, rex, nextop) +#else #define GETED(D) oped=GetEd(emu, &addr, rex, nextop, D) #define GETED32(D) oped=GetEd32O(emu, &addr, rex, nextop, D, 0) #define GETED_OFFS(D, O) oped=GetEdO(emu, &addr, rex, nextop, D, O) @@ -37,6 +58,7 @@ #define GETEM(D) opem=GetEm(emu, &addr, rex, nextop, D) #define GETEM32(D) opem=GetEm32O(emu, &addr, rex, nextop, D, 0) #define GETGM opgm=GetGm(emu, &addr, rex, nextop) +#endif #define ED oped #define GD opgd #define EB oped @@ -47,6 +69,8 @@ #define GX opgx #define EM opem #define GM opgm +#define FAKEED(D) GetEd(emu, &addr, rex, nextop, D) +#define FAKEED32(D) GetEd32O(emu, &addr, rex, nextop, D, 0) #define MODREG ((nextop&0xC0)==0xC0) diff --git a/src/emu/x64emu.c b/src/emu/x64emu.c index 9a328bb0..eca8ee1d 100755 --- a/src/emu/x64emu.c +++ b/src/emu/x64emu.c @@ -205,6 +205,11 @@ void FreeX64Emu(x64emu_t **emu) return; printf_log(LOG_DEBUG, "%04d|Free a X86_64 Emu (%p)\n", GetTID(), *emu); + if((*emu)->test.emu) { + internalFreeX64((*emu)->test.emu); + box_free((*emu)->test.emu); + (*emu)->test.emu = NULL; + } internalFreeX64(*emu); box_free(*emu); @@ -238,6 +243,13 @@ void CloneEmu(x64emu_t *newemu, const x64emu_t* emu) newemu->top = emu->top; newemu->fpu_stack = emu->fpu_stack; memcpy(newemu->xmm, emu->xmm, sizeof(emu->xmm)); + newemu->df = emu->df; + newemu->df_sav = emu->df_sav; + newemu->op1 = emu->op1; + newemu->op2 = emu->op2; + newemu->res = emu->res; + newemu->op1_sav = emu->op1_sav; + newemu->res_sav = emu->res_sav; newemu->mxcsr = emu->mxcsr; newemu->quit = emu->quit; newemu->error = emu->error; @@ -247,6 +259,37 @@ void CloneEmu(x64emu_t *newemu, const x64emu_t* emu) newemu->regs[_SP].q[0] = emu->regs[_SP].q[0] + (intptr_t)(newst - oldst); } +void CopyEmu(x64emu_t *newemu, const x64emu_t* emu) +{ + memcpy(newemu->regs, emu->regs, sizeof(emu->regs)); + memcpy(&newemu->ip, &emu->ip, sizeof(emu->ip)); + memcpy(&newemu->eflags, &emu->eflags, sizeof(emu->eflags)); + newemu->old_ip = emu->old_ip; + memcpy(newemu->segs, emu->segs, sizeof(emu->segs)); + memcpy(newemu->segs_serial, emu->segs_serial, sizeof(emu->segs_serial)); + memcpy(newemu->segs_offs, emu->segs_offs, sizeof(emu->segs_offs)); + memcpy(newemu->x87, emu->x87, sizeof(emu->x87)); + memcpy(newemu->mmx, emu->mmx, sizeof(emu->mmx)); + memcpy(newemu->xmm, emu->xmm, sizeof(emu->xmm)); + memcpy(newemu->fpu_ld, emu->fpu_ld, sizeof(emu->fpu_ld)); + memcpy(newemu->fpu_ll, emu->fpu_ll, sizeof(emu->fpu_ll)); + memcpy(newemu->p_regs, emu->p_regs, sizeof(emu->p_regs)); + newemu->cw = emu->cw; + newemu->sw = emu->sw; + newemu->top = emu->top; + newemu->fpu_stack = emu->fpu_stack; + newemu->df = emu->df; + newemu->df_sav = emu->df_sav; + newemu->op1 = emu->op1; + newemu->op2 = emu->op2; + newemu->res = emu->res; + newemu->op1_sav = emu->op1_sav; + newemu->res_sav = emu->res_sav; + newemu->mxcsr = emu->mxcsr; + newemu->quit = emu->quit; + newemu->error = emu->error; +} + box64context_t* GetEmuContext(x64emu_t* emu) { return emu->context; @@ -355,8 +398,8 @@ void ResetFlags(x64emu_t *emu) const char* DumpCPURegs(x64emu_t* emu, uintptr_t ip) { static char buff[1000]; - char* regname[] = {"RAX", "RCX", "RDX", "RBX", "RSP", "RBP", "RSI", "RDI", - " R8", " R9", "R10", "R11", "R12", "R13", "R14", "R15"}; + static const char* regname[] = {"RAX", "RCX", "RDX", "RBX", "RSP", "RBP", "RSI", "RDI", + " R8", " R9", "R10", "R11", "R12", "R13", "R14", "R15"}; char tmp[160]; buff[0] = '\0'; #ifdef HAVE_TRACE diff --git a/src/emu/x64emu_private.h b/src/emu/x64emu_private.h index fb86531a..3393986c 100755 --- a/src/emu/x64emu_private.h +++ b/src/emu/x64emu_private.h @@ -25,6 +25,15 @@ typedef union multiuint_s { uint64_t u64; } multiuint_t; +typedef struct x64emu_s x64emu_t; + +typedef struct x64test_s { + x64emu_t* emu; + uintptr_t memaddr; + int memsize; + uint8_t mem[16]; +} x64test_t; + typedef struct x64emu_s { // cpu reg64_t regs[16]; @@ -87,7 +96,7 @@ typedef struct x64emu_s { x64_ucontext_t *uc_link; // to handle setcontext int type; // EMUTYPE_xxx define - + x64test_t test; } x64emu_t; #define EMUTYPE_NONE 0 diff --git a/src/emu/x64run.c b/src/emu/x64run.c index df1d341e..3eeec71f 100755 --- a/src/emu/x64run.c +++ b/src/emu/x64run.c @@ -28,7 +28,11 @@ int my_setcontext(x64emu_t* emu, void* ucp); +#ifdef TEST_INTERPRETER +int RunTest(x64test_t *test) +#else int Run(x64emu_t *emu, int step) +#endif { uint8_t opcode; uint8_t nextop; @@ -40,6 +44,10 @@ int Run(x64emu_t *emu, int step) uint32_t tmp32u, tmp32u2; int64_t tmp64s; uint64_t tmp64u, tmp64u2, tmp64u3; + #ifdef TEST_INTERPRETER + x64emu_t* emu = test->emu; + int step = 0; + #endif uintptr_t addr = R_RIP; rex_t rex; int rep; // 0 none, 1=F2 prefix, 2=F3 prefix @@ -57,9 +65,11 @@ int Run(x64emu_t *emu, int step) printf_log(LOG_DEBUG, "Run X86 (%p), RIP=%p, Stack=%p\n", emu, (void*)addr, (void*)R_RSP); x64emurun: - - while(1) { -#ifdef HAVE_TRACE +#ifndef TEST_INTERPRETER + while(1) +#endif + { +#if defined(HAVE_TRACE) __builtin_prefetch((void*)addr, 0, 0); emu->prev2_ip = emu->old_ip; if(my_context->dec && ( @@ -136,24 +146,39 @@ x64emurun: case 0x0F: /* More instructions */ switch(rep) { case 1: + #ifdef TEST_INTERPRETER + if(!(addr = TestF20F(test, rex, addr, &step))) + unimp = 1; + #else if(!(addr = RunF20F(emu, rex, addr, &step))) { unimp = 1; goto fini; } if(step==2) STEP2; + #endif break; case 2: + #ifdef TEST_INTERPRETER + if(!(addr = TestF30F(test, rex, addr))) + unimp = 1; + #else if(!(addr = RunF30F(emu, rex, addr))) { unimp = 1; goto fini; } + #endif break; default: + #ifdef TEST_INTERPRETER + if(!(addr = Test0F(test, rex, addr, &step))) + unimp = 1; + #else if(!(addr = Run0F(emu, rex, addr, &step))) { unimp = 1; goto fini; } if(step==2) STEP2; + #endif break; } if(emu->quit) { @@ -255,6 +280,10 @@ x64emurun: GD->sdword[0] = ED->sdword[0]; // meh? break; case 0x64: /* FS: prefix */ + #ifdef TEST_INTERPRETER + if(!(addr = Test64(test, rex, _FS, addr))) + unimp = 1; + #else if(!(addr = Run64(emu, rex, _FS, addr))) { unimp = 1; goto fini; @@ -263,8 +292,13 @@ x64emurun: R_RIP = addr; goto fini; } + #endif break; case 0x65: /* GS: prefix */ + #ifdef TEST_INTERPRETER + if(!(addr = Test64(test, rex, _GS, addr))) + unimp = 1; + #else if(!(addr = Run64(emu, rex, _GS, addr))) { unimp = 1; goto fini; @@ -273,8 +307,13 @@ x64emurun: R_RIP = addr; goto fini; } + #endif break; case 0x66: /* 16bits prefix */ + #ifdef TEST_INTERPRETER + if(!(addr = Test66(test, rex, rep, addr))) + unimp = 1; + #else if(!(addr = Run66(emu, rex, rep, addr))) { unimp = 1; goto fini; @@ -283,8 +322,13 @@ x64emurun: R_RIP = addr; goto fini; } + #endif break; case 0x67: /* reduce EASize prefix */ + #ifdef TEST_INTERPRETER + if(!(addr = Test67(test, rex, rep, addr))) + unimp = 1; + #else if(!(addr = Run67(emu, rex, rep, addr))) { unimp = 1; goto fini; @@ -293,6 +337,7 @@ x64emurun: R_RIP = addr; goto fini; } + #endif break; case 0x68: /* Push Id */ Push(emu, F32S64); @@ -326,8 +371,10 @@ x64emurun: case 0x6E: /* OUTSB DX */ case 0x6F: /* OUTSL DX */ // this is a privilege opcode... + #ifndef TEST_INTERPRETOR emit_signal(emu, SIGSEGV, (void*)R_RIP, 0); STEP; + #endif break; GOCOND(0x70 @@ -416,7 +463,7 @@ x64emurun: break; case 0x86: /* XCHG Eb,Gb */ nextop = F8; -#ifdef DYNAREC +#if defined(DYNAREC) && !defined(TEST_INTERPRETER) GETEB(0); GETGB; if(MODREG) { // reg / reg: no lock @@ -441,7 +488,7 @@ x64emurun: break; case 0x87: /* XCHG Ed,Gd */ nextop = F8; -#ifdef DYNAREC +#if defined(DYNAREC) && !defined(TEST_INTERPRETER) GETED(0); GETGD; if(MODREG) { @@ -527,8 +574,12 @@ x64emurun: break; case 0x8D: /* LEA Gd,M */ nextop = F8; - GETED(0); GETGD; + #ifdef TEST_INTERPRETER + oped=GetEd(emu, &addr, rex, nextop, 0); + #else + GETED(0); + #endif if(rex.w) GD->q[0] = (uint64_t)ED; else @@ -630,7 +681,9 @@ x64emurun: tmp8s = ACCESS_FLAG(F_DF)?-1:+1; tmp64u = (rep)?R_RCX:1L; while(tmp64u) { + #ifndef TEST_INTERPRETER *(uint8_t*)R_RDI = *(uint8_t*)R_RSI; + #endif R_RDI += tmp8s; R_RSI += tmp8s; --tmp64u; @@ -645,7 +698,9 @@ x64emurun: tmp8s *= 8; while(tmp64u) { --tmp64u; + #ifndef TEST_INTERPRETER *(uint64_t*)R_RDI = *(uint64_t*)R_RSI; + #endif R_RDI += tmp8s; R_RSI += tmp8s; } @@ -653,7 +708,9 @@ x64emurun: tmp8s *= 4; while(tmp64u) { --tmp64u; + #ifndef TEST_INTERPRETER *(uint32_t*)R_RDI = *(uint32_t*)R_RSI; + #endif R_RDI += tmp8s; R_RSI += tmp8s; } @@ -793,7 +850,9 @@ x64emurun: tmp8s = ACCESS_FLAG(F_DF)?-1:+1; tmp64u = (rep)?R_RCX:1L; while(tmp64u) { + #ifndef TEST_INTERPRETER *(uint8_t*)R_RDI = R_AL; + #endif R_RDI += tmp8s; --tmp64u; } @@ -808,7 +867,9 @@ x64emurun: tmp64u = (rep)?R_RCX:1L; if((rex.w)) while(tmp64u) { + #ifndef TEST_INTERPRETER *(uint64_t*)R_RDI = R_RAX; + #endif R_RDI += tmp8s; --tmp64u; } @@ -1079,14 +1140,18 @@ x64emurun: break; case 0xCC: /* INT 3 */ + #ifndef TEST_INTERPRETER x64Int3(emu, &addr); if(emu->quit) goto fini; // R_RIP is up to date when returning from x64Int3 addr = R_RIP; + #endif break; case 0xCD: /* INT n */ // this is a privilege opcode... + #ifndef TEST_INTERPRETER emit_signal(emu, SIGSEGV, (void*)R_RIP, 0); STEP; + #endif break; @@ -1165,6 +1230,10 @@ x64emurun: R_AL = *(uint8_t*)(R_RBX + R_AL); break; case 0xD8: /* x87 opcodes */ + #ifdef TEST_INTERPRETER + if(!(addr = TestD8(test, rex, addr))) + unimp = 1; + #else if(!(addr = RunD8(emu, rex, addr))) { unimp = 1; goto fini; @@ -1173,8 +1242,13 @@ x64emurun: R_RIP = addr; goto fini; } + #endif break; case 0xD9: /* x87 opcodes */ + #ifdef TEST_INTERPRETER + if(!(addr = TestD9(test, rex, addr))) + unimp = 1; + #else if(!(addr = RunD9(emu, rex, addr))) { unimp = 1; goto fini; @@ -1183,8 +1257,13 @@ x64emurun: R_RIP = addr; goto fini; } + #endif break; case 0xDA: /* x87 opcodes */ + #ifdef TEST_INTERPRETER + if(!(addr = TestDA(test, rex, addr))) + unimp = 1; + #else if(!(addr = RunDA(emu, rex, addr))) { unimp = 1; goto fini; @@ -1193,8 +1272,13 @@ x64emurun: R_RIP = addr; goto fini; } + #endif break; case 0xDB: /* x87 opcodes */ + #ifdef TEST_INTERPRETER + if(!(addr = TestDB(test, rex, addr))) + unimp = 1; + #else if(!(addr = RunDB(emu, rex, addr))) { unimp = 1; goto fini; @@ -1203,8 +1287,13 @@ x64emurun: R_RIP = addr; goto fini; } + #endif break; case 0xDC: /* x87 opcodes */ + #ifdef TEST_INTERPRETER + if(!(addr = TestDC(test, rex, addr))) + unimp = 1; + #else if(!(addr = RunDC(emu, rex, addr))) { unimp = 1; goto fini; @@ -1213,8 +1302,13 @@ x64emurun: R_RIP = addr; goto fini; } + #endif break; case 0xDD: /* x87 opcodes */ + #ifdef TEST_INTERPRETER + if(!(addr = TestDD(test, rex, addr))) + unimp = 1; + #else if(!(addr = RunDD(emu, rex, addr))) { unimp = 1; goto fini; @@ -1223,8 +1317,13 @@ x64emurun: R_RIP = addr; goto fini; } + #endif break; case 0xDE: /* x87 opcodes */ + #ifdef TEST_INTERPRETER + if(!(addr = TestDE(test, rex, addr))) + unimp = 1; + #else if(!(addr = RunDE(emu, rex, addr))) { unimp = 1; goto fini; @@ -1233,8 +1332,13 @@ x64emurun: R_RIP = addr; goto fini; } + #endif break; case 0xDF: /* x87 opcodes */ + #ifdef TEST_INTERPRETER + if(!(addr = TestDF(test, rex, addr))) + unimp = 1; + #else if(!(addr = RunDF(emu, rex, addr))) { unimp = 1; goto fini; @@ -1243,6 +1347,7 @@ x64emurun: R_RIP = addr; goto fini; } + #endif break; case 0xE0: /* LOOPNZ */ CHECK_FLAGS(emu); @@ -1278,8 +1383,10 @@ x64emurun: case 0xE6: /* OUT XX, AL */ case 0xE7: /* OUT XX, EAX */ // this is a privilege opcode... + #ifndef TEST_INTERPRETER emit_signal(emu, SIGSEGV, (void*)R_RIP, 0); STEP; + #endif break; case 0xE8: /* CALL Id */ tmp32s = F32S; // call is relative @@ -1303,10 +1410,16 @@ x64emurun: case 0xEE: /* OUT DX, AL */ case 0xEF: /* OUT DX, EAX */ // this is a privilege opcode... + #ifndef TEST_INTERPRETER emit_signal(emu, SIGSEGV, (void*)R_RIP, 0); STEP; + #endif break; case 0xF0: /* LOCK prefix */ + #ifdef TEST_INTERPRETER + if(!(addr = TestF0(test, rex, addr))) + unimp = 1; + #else if(!(addr = RunF0(emu, rex, addr))) { unimp = 1; goto fini; @@ -1315,12 +1428,15 @@ x64emurun: R_RIP = addr; goto fini; } + #endif break; case 0xF4: /* HLT */ // this is a privilege opcode... + #ifndef TEST_INTERPRETER emit_signal(emu, SIGSEGV, (void*)R_RIP, 0); STEP; + #endif break; case 0xF5: /* CMC */ CHECK_FLAGS(emu); @@ -1529,7 +1645,15 @@ x64emurun: break; case 6: /* Push Ed */ tmp64u = ED->q[0]; // rex.w ignored + #ifdef TEST_INTERPRETER + R_RSP -=8; + if(test->memsize!=8) + *(uint64_t*)test->mem = *(uint64_t*)test->memaddr; + test->memsize = 8; + test->memaddr = R_RSP; + #else Push(emu, tmp64u); // avoid potential issue with push [esp+...] + #endif break; default: printf_log(LOG_NONE, "Illegal Opcode %p: %02X %02X %02X %02X %02X %02X\n",(void*)R_RIP, opcode, nextop, PK(2), PK(3), PK(4), PK(5)); @@ -1547,6 +1671,7 @@ x64emurun: fini: +#ifndef TEST_INTERPRETER printf_log(LOG_DEBUG, "End of X86 run (%p), RIP=%p, Stack=%p, unimp=%d, emu->fork=%d, emu->uc_link=%p, emu->quit=%d\n", emu, (void*)R_RIP, (void*)R_RSP, unimp, emu->fork, emu->uc_link, emu->quit); if(unimp) { emu->quit = 1; @@ -1570,5 +1695,11 @@ fini: addr = R_RIP; goto x64emurun; } +#else + if(unimp) { + printf_log(LOG_INFO, "Warning, inimplemented opcode in Test Interpreter\n"); + } else + addr = R_RIP; +#endif return 0; } diff --git a/src/emu/x64run0f.c b/src/emu/x64run0f.c index 05c9aab6..745f57f4 100644 --- a/src/emu/x64run0f.c +++ b/src/emu/x64run0f.c @@ -28,7 +28,11 @@ #include "modrm.h" +#ifdef TEST_INTERPRETER +uintptr_t Test0F(x64test_t *test, rex_t rex, uintptr_t addr, int *step) +#else uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step) +#endif { uint8_t opcode; uint8_t nextop; @@ -42,27 +46,38 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step) sse_regs_t *opex, *opgx, eax1; mmx87_regs_t *opem, *opgm, eam1; +#ifdef TEST_INTERPRETER + x64emu_t *emu = test->emu; +#endif opcode = F8; switch(opcode) { case 0x05: /* SYSCALL */ + #ifndef TEST_INTERPRETER R_RIP = addr; x64Syscall(emu); + #endif break; case 0x06: /* CLTS */ // this is a privilege opcode... + #ifndef TEST_INTERPRETER emit_signal(emu, SIGSEGV, (void*)R_RIP, 0); + #endif break; case 0x08: /* INVD */ case 0x09: /* WBINVD */ // this is a privilege opcode... + #ifndef TEST_INTERPRETER emit_signal(emu, SIGSEGV, (void*)R_RIP, 0); + #endif break; case 0x0B: /* UD2 */ + #ifndef TEST_INTERPRETER emit_signal(emu, SIGILL, (void*)R_RIP, 0); + #endif break; case 0x0D: @@ -152,14 +167,16 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step) case 0x1F: /* NOP (multi-byte) */ nextop = F8; - GETED(0); + FAKEED(0); break; case 0x20: /* MOV REG, crX */ case 0x21: /* MOV REG, drX */ case 0x22: /* MOV cxR, REG */ case 0x23: /* MOV drX, REG */ // this is a privilege opcode... + #ifndef TEST_INTERPRETER emit_signal(emu, SIGSEGV, (void*)R_RIP, 0); + #endif break; case 0x28: /* MOVAPS Gx,Ex */ @@ -800,7 +817,15 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step) tmp32s >>= (rex.w?6:5); if(!MODREG) { + #ifdef TEST_INTERPRETER + test->memaddr=((test->memaddr)+(tmp32s<<(rex.w?3:2))); + if(rex.w) + *(uint64_t*)test->mem = *(uint64_t*)test->memaddr; + else + *(uint32_t*)test->mem = *(uint32_t*)test->memaddr; + #else ED=(reg64_t*)(((uintptr_t)(ED))+(tmp32s<<(rex.w?3:2))); + #endif } if(rex.w) { if(ED->q[0] & (1LL<<tmp8u)) @@ -843,7 +868,15 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step) tmp64s >>= (rex.w?6:5); if(!MODREG) { - ED=(reg64_t*)(((uintptr_t)(ED))+(tmp64s<<(rex.w?3:2))); + #ifdef TEST_INTERPRETER + test->memaddr=((test->memaddr)+(tmp32s<<(rex.w?3:2))); + if(rex.w) + *(uint64_t*)test->mem = *(uint64_t*)test->memaddr; + else + *(uint32_t*)test->mem = *(uint32_t*)test->memaddr; + #else + ED=(reg64_t*)(((uintptr_t)(ED))+(tmp32s<<(rex.w?3:2))); + #endif } if(rex.w) { if(ED->q[0] & (1LL<<tmp8u)) @@ -892,27 +925,33 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step) GETED(0); switch((nextop>>3)&7) { case 0: /* FXSAVE Ed */ + #ifndef TEST_INTERPRETER if(rex.w) fpu_fxsave64(emu, ED); else fpu_fxsave32(emu, ED); + #endif break; case 1: /* FXRSTOR Ed */ + #ifndef TEST_INTERPRETER if(rex.w) fpu_fxrstor64(emu, ED); else fpu_fxrstor32(emu, ED); + #endif break; case 2: /* LDMXCSR Md */ emu->mxcsr.x32 = ED->dword[0]; + #ifndef TEST_INTERPRETER if(box64_sse_flushto0) applyFlushTo0(emu); + #endif break; case 3: /* STMXCSR Md */ ED->dword[0] = emu->mxcsr.x32; break; case 7: /* CLFLUSH Ed */ - #ifdef DYNAREC + #if defined(DYNAREC) && !defined(TEST_INTERPRETER) if(box64_dynarec) cleanDBFromAddressRange((uintptr_t)ED, 8, 0); #endif @@ -975,7 +1014,15 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step) tmp64s >>= (rex.w?6:5); if(!MODREG) { - ED=(reg64_t*)(((uintptr_t)(ED))+(tmp64s<<(rex.w?3:2))); + #ifdef TEST_INTERPRETER + test->memaddr=((test->memaddr)+(tmp32s<<(rex.w?3:2))); + if(rex.w) + *(uint64_t*)test->mem = *(uint64_t*)test->memaddr; + else + *(uint32_t*)test->mem = *(uint32_t*)test->memaddr; + #else + ED=(reg64_t*)(((uintptr_t)(ED))+(tmp32s<<(rex.w?3:2))); + #endif } if(rex.w) { if(ED->q[0] & (1LL<<tmp8u)) { @@ -1105,7 +1152,15 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step) tmp64s >>= (rex.w?6:5); if(!MODREG) { - ED=(reg64_t*)(((uintptr_t)(ED))+(tmp64s<<(rex.w?3:2))); + #ifdef TEST_INTERPRETER + test->memaddr=((test->memaddr)+(tmp32s<<(rex.w?3:2))); + if(rex.w) + *(uint64_t*)test->mem = *(uint64_t*)test->memaddr; + else + *(uint32_t*)test->mem = *(uint32_t*)test->memaddr; + #else + ED=(reg64_t*)(((uintptr_t)(ED))+(tmp32s<<(rex.w?3:2))); + #endif } if(rex.w) { if(ED->q[0] & (1LL<<tmp8u)) @@ -1289,6 +1344,10 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step) CHECK_FLAGS(emu); nextop = F8; GETED(0); + #ifdef TEST_INTERPRETER + test->memsize = 16; + ((uint64_t*)test->mem)[1] = ((uint64_t*)test->memaddr)[1]; + #endif switch((nextop>>3)&7) { case 1: if(rex.w) { diff --git a/src/emu/x64run64.c b/src/emu/x64run64.c index fa1ea281..a8d100a3 100644 --- a/src/emu/x64run64.c +++ b/src/emu/x64run64.c @@ -22,7 +22,11 @@ #include "modrm.h" +#ifdef TEST_INTERPRETER +uintptr_t Test64(x64test_t *test, rex_t rex, int seg, uintptr_t addr) +#else uintptr_t Run64(x64emu_t *emu, rex_t rex, int seg, uintptr_t addr) +#endif { uint8_t opcode; uint8_t nextop; @@ -35,6 +39,9 @@ uintptr_t Run64(x64emu_t *emu, rex_t rex, int seg, uintptr_t addr) reg64_t *oped, *opgd; sse_regs_t *opex, *opgx; int rep; + #ifdef TEST_INTERPRETER + x64emu_t* emu = test->emu; + #endif uintptr_t tlsdata = GetSegmentBaseEmu(emu, seg); opcode = F8; diff --git a/src/emu/x64run66.c b/src/emu/x64run66.c index f7696ee1..4a73cf60 100644 --- a/src/emu/x64run66.c +++ b/src/emu/x64run66.c @@ -25,7 +25,11 @@ #include "modrm.h" +#ifdef TEST_INTERPRETER +uintptr_t Test66(x64test_t *test, rex_t rex, int rep, uintptr_t addr) +#else uintptr_t Run66(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr) +#endif { uint8_t opcode; uint8_t nextop; @@ -37,6 +41,9 @@ uintptr_t Run66(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr) int64_t tmp64s; uint64_t tmp64u, tmp64u2, tmp64u3; reg64_t *oped, *opgd; + #ifdef TEST_INTERPRETER + x64emu_t* emu = test->emu; + #endif opcode = F8; @@ -105,7 +112,11 @@ uintptr_t Run66(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr) GO(0x30, xor) /* XOR 0x31 ~> 0x35 */ case 0x0F: /* more opcdes */ + #ifdef TEST_INTERPRETER + return Test660F(test, rex, addr); + #else return Run660F(emu, rex, addr); + #endif case 0x39: nextop = F8; @@ -133,9 +144,17 @@ uintptr_t Run66(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr) break; case 0x64: /* FS: */ + #ifdef TEST_INTERPRETER + return Test6664(test, rex, _FS, addr); + #else return Run6664(emu, rex, _FS, addr); + #endif case 0x65: /* GS: */ + #ifdef TEST_INTERPRETER + return Test6664(test, rex, _GS, addr); + #else return Run6664(emu, rex, _GS, addr); + #endif case 0x69: /* IMUL Gw,Ew,Iw */ nextop = F8; @@ -257,8 +276,12 @@ uintptr_t Run66(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr) break; case 0x8D: /* LEA Gw,M */ nextop = F8; - GETED(0); GETGD; + #ifdef TEST_INTERPRETER + oped=GetEd(emu, &addr, rex, nextop, 0); + #else + GETED(0); + #endif if(rex.w) GD->q[0] = (uint64_t)ED; else @@ -427,13 +450,17 @@ uintptr_t Run66(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr) tmp64u = (rep)?R_RCX:1L; if((rex.w)) while(tmp64u) { + #ifndef TEST_INTERPRETER *(uint64_t*)R_RDI = R_RAX; + #endif R_RDI += tmp8s; --tmp64u; } else while(tmp64u) { + #ifndef TEST_INTERPRETER *(uint16_t*)R_RDI = R_AX; + #endif R_RDI += tmp8s; --tmp64u; } @@ -609,10 +636,18 @@ uintptr_t Run66(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr) break; case 0xD9: /* x87 opcdes */ + #ifdef TEST_INTERPRETER + return Test66D9(test, rex, addr); + #else return Run66D9(emu, rex, addr); + #endif case 0xDD: /* x87 opcdes */ + #ifdef TEST_INTERPRETER + return Test66DD(test, rex, addr); + #else return Run66DD(emu, rex, addr); + #endif case 0xE8: /* CALL Id */ tmp32s = F32S; // call is relative @@ -621,7 +656,11 @@ uintptr_t Run66(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr) break; case 0xF0: /* LOCK: */ + #ifdef TEST_INTERPRETER + return Test66F0(test, rex, addr); + #else return Run66F0(emu, rex, addr); + #endif case 0xF7: /* GRP3 Ew(,Iw) */ nextop = F8; diff --git a/src/emu/x64run660f.c b/src/emu/x64run660f.c index 0b868a27..019aaea7 100644 --- a/src/emu/x64run660f.c +++ b/src/emu/x64run660f.c @@ -43,7 +43,11 @@ static uint8_t ff_mult(uint8_t a, uint8_t b) return retval; } +#ifdef TEST_INTERPRETER +uintptr_t Test660F(x64test_t *test, rex_t rex, uintptr_t addr) +#else uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr) +#endif { uint8_t opcode; uint8_t nextop; @@ -106,6 +110,9 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr) 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d, }; + #ifdef TEST_INTERPRETER + x64emu_t* emu = test->emu; + #endif opcode = F8; switch(opcode) { @@ -162,7 +169,7 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr) case 0x1F: /* NOP (multi-byte) */ nextop = F8; - GETED(0); + FAKEED(0); break; case 0x28: /* MOVAPD Gx, Ex */ @@ -1564,7 +1571,15 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr) tmp32s >>= (rex.w?6:4); if(!MODREG) { + #ifdef TEST_INTERPRETER + test->memaddr=((test->memaddr)+(tmp32s<<(rex.w?3:1))); + if(rex.w) + *(uint64_t*)test->mem = *(uint64_t*)test->memaddr; + else + *(uint16_t*)test->mem = *(uint16_t*)test->memaddr; + #else EW=(reg64_t*)(((uintptr_t)(EW))+(tmp32s<<(rex.w?3:1))); + #endif } if(rex.w) { if(EW->q[0] & (1LL<<tmp8u)) { diff --git a/src/emu/x64run6664.c b/src/emu/x64run6664.c index 9753dfce..668507a4 100644 --- a/src/emu/x64run6664.c +++ b/src/emu/x64run6664.c @@ -22,12 +22,19 @@ #include "modrm.h" +#ifdef TEST_INTERPRETER +uintptr_t Test6664(x64test_t *test, rex_t rex, int seg, uintptr_t addr) +#else uintptr_t Run6664(x64emu_t *emu, rex_t rex, int seg, uintptr_t addr) +#endif { uint8_t opcode; uint8_t nextop; reg64_t *oped, *opgd; sse_regs_t *opex, *opgx; + #ifdef TEST_INTERPRETER + x64emu_t* emu = test->emu; + #endif uintptr_t tlsdata = GetSegmentBaseEmu(emu, seg); opcode = F8; diff --git a/src/emu/x64run66d9.c b/src/emu/x64run66d9.c index 198c3a88..84b554df 100644 --- a/src/emu/x64run66d9.c +++ b/src/emu/x64run66d9.c @@ -22,10 +22,17 @@ #include "modrm.h" +#ifdef TEST_INTERPRETER +uintptr_t Test66D9(x64test_t *test, rex_t rex, uintptr_t addr) +#else uintptr_t Run66D9(x64emu_t *emu, rex_t rex, uintptr_t addr) +#endif { uint8_t nextop; reg64_t *oped; + #ifdef TEST_INTERPRETER + x64emu_t* emu = test->emu; + #endif nextop = F8; switch (nextop) { @@ -84,7 +91,9 @@ uintptr_t Run66D9(x64emu_t *emu, rex_t rex, uintptr_t addr) case 6: /* FNSTENV m */ // warning, incomplete GETEW(0); + #ifndef TEST_INTERPRETER fpu_savenv(emu, (char*)ED, 1); + #endif break; default: return 0; diff --git a/src/emu/x64run66dd.c b/src/emu/x64run66dd.c index d0fc703c..e8465dd2 100644 --- a/src/emu/x64run66dd.c +++ b/src/emu/x64run66dd.c @@ -22,10 +22,17 @@ #include "modrm.h" +#ifdef TEST_INTERPRETER +uintptr_t Test66DD(x64test_t *test, rex_t rex, uintptr_t addr) +#else uintptr_t Run66DD(x64emu_t *emu, rex_t rex, uintptr_t addr) +#endif { uint8_t nextop; reg64_t *oped; + #ifdef TEST_INTERPRETER + x64emu_t* emu = test->emu; + #endif nextop = F8; switch (nextop) { @@ -92,6 +99,7 @@ uintptr_t Run66DD(x64emu_t *emu, rex_t rex, uintptr_t addr) case 6: /* FNSAVE m94byte */ GETEW(0); // ENV first... + #ifndef TEST_INTERPRETER fpu_savenv(emu, (char*)ED, 1); // save the STx { @@ -102,6 +110,7 @@ uintptr_t Run66DD(x64emu_t *emu, rex_t rex, uintptr_t addr) p+=10; } } + #endif reset_fpu(emu); break; default: diff --git a/src/emu/x64run66f0.c b/src/emu/x64run66f0.c index 7b76fe32..a880593c 100644 --- a/src/emu/x64run66f0.c +++ b/src/emu/x64run66f0.c @@ -25,7 +25,11 @@ #include "modrm.h" +#ifdef TEST_INTERPRETER +uintptr_t Test66F0(x64test_t *test, rex_t rex, uintptr_t addr) +#else uintptr_t Run66F0(x64emu_t *emu, rex_t rex, uintptr_t addr) +#endif { uint8_t opcode; uint8_t nextop; @@ -37,7 +41,9 @@ uintptr_t Run66F0(x64emu_t *emu, rex_t rex, uintptr_t addr) #ifdef USE_CAS uint64_t tmpcas; #endif - + #ifdef TEST_INTERPRETER + x64emu_t* emu = test->emu; + #endif opcode = F8; // REX prefix before the F0 are ignored rex.rex = 0; @@ -58,7 +64,7 @@ uintptr_t Run66F0(x64emu_t *emu, rex_t rex, uintptr_t addr) nextop = F8; GETEW(0); GETGW; -#ifdef DYNAREC +#if defined(DYNAREC) && !defined(TEST_INTERPRETER) do { tmp16u = native_lock_read_h(EW); cmp16(emu, R_AX, tmp16u); @@ -85,7 +91,7 @@ uintptr_t Run66F0(x64emu_t *emu, rex_t rex, uintptr_t addr) nextop = F8; GETEW(0); GETGW; -#ifdef DYNAREC +#if defined(DYNAREC) && !defined(TEST_INTERPRETER) if(rex.w) { do { tmp64u = native_lock_read_dd(ED); @@ -128,7 +134,7 @@ uintptr_t Run66F0(x64emu_t *emu, rex_t rex, uintptr_t addr) } break; -#ifdef DYNAREC +#if defined(DYNAREC) && !defined(TEST_INTERPRETER) #define GO(B, OP) \ case B+1: \ nextop = F8; \ @@ -209,7 +215,7 @@ uintptr_t Run66F0(x64emu_t *emu, rex_t rex, uintptr_t addr) GETED((opcode==0x83)?1:2); tmp64s = (opcode==0x83)?(F8S):(F16S); tmp64u = (uint64_t)tmp64s; -#ifdef DYNAREC +#if defined(DYNAREC) && !defined(TEST_INTERPRETER) if(MODREG) switch((nextop>>3)&7) { case 0: ED->word[0] = add16(emu, ED->word[0], tmp64u); break; @@ -253,7 +259,7 @@ uintptr_t Run66F0(x64emu_t *emu, rex_t rex, uintptr_t addr) GETED(0); switch((nextop>>3)&7) { case 0: /* INC Ed */ -#ifdef DYNAREC +#if defined(DYNAREC) && !defined(TEST_INTERPRETER) if(rex.w) if(((uintptr_t)ED)&7) { // unaligned @@ -295,7 +301,7 @@ uintptr_t Run66F0(x64emu_t *emu, rex_t rex, uintptr_t addr) #endif break; case 1: /* DEC Ed */ -#ifdef DYNAREC +#if defined(DYNAREC) && !defined(TEST_INTERPRETER) if(rex.w) if(((uintptr_t)ED)&7) { // unaligned diff --git a/src/emu/x64run67.c b/src/emu/x64run67.c index 034fd640..8b058f6b 100644 --- a/src/emu/x64run67.c +++ b/src/emu/x64run67.c @@ -22,7 +22,11 @@ #include "modrm.h" +#ifdef TEST_INTERPRETER +uintptr_t Test67(x64test_t *test, rex_t rex, int rep, uintptr_t addr) +#else uintptr_t Run67(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr) +#endif { uint8_t opcode; uint8_t nextop; @@ -32,7 +36,9 @@ uintptr_t Run67(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr) int32_t tmp32s; uint64_t tmp64u; reg64_t *oped, *opgd; - + #ifdef TEST_INTERPRETER + x64emu_t* emu = test->emu; + #endif opcode = F8; while(opcode==0x67) @@ -146,7 +152,11 @@ uintptr_t Run67(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr) break; case 0x66: + #ifdef TEST_INTERPRETER + return Test6766(test, rex, rep, addr); + #else return Run6766(emu, rex, rep, addr); + #endif case 0x80: /* GRP Eb,Ib */ nextop = F8; diff --git a/src/emu/x64run670f.c b/src/emu/x64run670f.c index d122d0e0..589e5181 100644 --- a/src/emu/x64run670f.c +++ b/src/emu/x64run670f.c @@ -26,7 +26,11 @@ #include "modrm.h" +#ifdef TEST_INTERPRETER +uintptr_t Test670F(x64test_t *test, rex_t rex, int rep, uintptr_t addr) +#else uintptr_t Run670F(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr) +#endif { (void)rep; uint8_t opcode; @@ -40,6 +44,9 @@ uintptr_t Run670F(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr) sse_regs_t *opex, *opgx, eax1; (void)eax1; mmx87_regs_t *opem, *opgm, eam1; (void)opem; (void)opgm; (void)eam1; + #ifdef TEST_INTERPRETER + x64emu_t* emu = test->emu; + #endif opcode = F8; switch(opcode) { @@ -99,8 +106,10 @@ uintptr_t Run670F(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr) switch(rep) { case 0: /* UD1 Ed */ nextop = F8; - GETED32(0); + FAKEED32(0); + #ifndef TEST_INTERPRETER emit_signal(emu, SIGILL, (void*)R_RIP, 0); + #endif break; default: return 0; diff --git a/src/emu/x64run6766.c b/src/emu/x64run6766.c index c12e9032..ad44f8c4 100644 --- a/src/emu/x64run6766.c +++ b/src/emu/x64run6766.c @@ -25,7 +25,11 @@ #include "modrm.h" +#ifdef TEST_INTERPRETER +uintptr_t Test6766(x64test_t *test, rex_t rex, int rep, uintptr_t addr) +#else uintptr_t Run6766(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr) +#endif { // Hmmmm.... (void)rep; @@ -39,7 +43,9 @@ uintptr_t Run6766(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr) int64_t tmp64s; (void)tmp64s; uint64_t tmp64u, tmp64u2, tmp64u3; (void)tmp64u; (void)tmp64u2; (void)tmp64u3; reg64_t *oped, *opgd; (void)oped; (void)opgd; - + #ifdef TEST_INTERPRETER + x64emu_t* emu = test->emu; + #endif opcode = F8; while((opcode==0x2E) || (opcode==0x66)) // ignoring CS: or multiple 0x66 @@ -59,7 +65,11 @@ uintptr_t Run6766(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr) switch(opcode) { case 0x0F: /* more opcodes */ + #ifdef TEST_INTERPRETER + return Test67660F(test, rex, addr); + #else return Run67660F(emu, rex, addr); + #endif default: return 0; diff --git a/src/emu/x64run67660f.c b/src/emu/x64run67660f.c index 75506426..ba031c8a 100644 --- a/src/emu/x64run67660f.c +++ b/src/emu/x64run67660f.c @@ -22,7 +22,11 @@ #include "modrm.h" +#ifdef TEST_INTERPRETER +uintptr_t Test67660F(x64test_t *test, rex_t rex, uintptr_t addr) +#else uintptr_t Run67660F(x64emu_t *emu, rex_t rex, uintptr_t addr) +#endif { uint8_t opcode; uint8_t nextop; @@ -36,7 +40,9 @@ uintptr_t Run67660F(x64emu_t *emu, rex_t rex, uintptr_t addr) uint64_t tmp64u; (void)tmp64u; reg64_t *oped, *opgd; (void)oped; (void)opgd; sse_regs_t *opex, *opgx; - + #ifdef TEST_INTERPRETER + x64emu_t* emu = test->emu; + #endif opcode = F8; switch(opcode) { diff --git a/src/emu/x64run_private.c b/src/emu/x64run_private.c index 082f0aae..3e519cd2 100755 --- a/src/emu/x64run_private.c +++ b/src/emu/x64run_private.c @@ -1225,6 +1225,26 @@ reg64_t* GetEb(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t del } else return GetECommon(emu, addr, rex, m, delta); } +reg64_t* TestEb(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta) +{ + // rex ignored here + uint8_t m = v&0xC7; // filter Eb + if(m>=0xC0) { + if(rex.rex) { + return &test->emu->regs[(m&0x07)+(rex.b<<3)]; + } else { + int lowhigh = (m&4)>>2; + return (reg64_t *)(((char*)(&test->emu->regs[(m&0x03)]))+lowhigh); //? + } + } else { + reg64_t* ret = GetECommon(test->emu, addr, rex, m, delta); + test->memsize = 1; + test->memaddr = (uintptr_t)ret; + test->mem[0] = ret->byte[0]; + return (reg64_t*)test->mem; + } +} + reg64_t* GetEbO(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset) { // rex ignored here @@ -1239,6 +1259,26 @@ reg64_t* GetEbO(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t de } else return GetECommonO(emu, addr, rex, m, delta, offset); } +reg64_t* TestEbO(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset) +{ + // rex ignored here + uint8_t m = v&0xC7; // filter Eb + if(m>=0xC0) { + if(rex.rex) { + return &test->emu->regs[(m&0x07)+(rex.b<<3)]; + } else { + int lowhigh = (m&4)>>2; + return (reg64_t *)(((char*)(&test->emu->regs[(m&0x03)]))+lowhigh); //? + } + } else { + reg64_t* ret = GetECommonO(test->emu, addr, rex, m, delta, offset); + test->memsize = 1; + test->memaddr = (uintptr_t)ret; + test->mem[0] = ret->byte[0]; + return (reg64_t*)test->mem; + } +} + reg64_t* GetEd(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta) { uint8_t m = v&0xC7; // filter Ed @@ -1247,6 +1287,23 @@ reg64_t* GetEd(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t del } else return GetECommon(emu, addr, rex, m, delta); } +reg64_t* TestEd(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta) +{ + uint8_t m = v&0xC7; // filter Ed + if(m>=0xC0) { + return &test->emu->regs[(m&0x07)+(rex.b<<3)]; + } else { + reg64_t* ret = GetECommon(test->emu, addr, rex, m, delta); + test->memsize = 4<<rex.w; + test->memaddr = (uintptr_t)ret; + if(rex.w) + *(uint64_t*)test->mem = ret->q[0]; + else + *(uint32_t*)test->mem = ret->dword[0]; + return (reg64_t*)test->mem; + } +} + reg64_t* GetEdO(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset) { uint8_t m = v&0xC7; // filter Ed @@ -1255,6 +1312,23 @@ reg64_t* GetEdO(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t de } else return GetECommonO(emu, addr, rex, m, delta, offset); } +reg64_t* TestEdO(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset) +{ + uint8_t m = v&0xC7; // filter Ed + if(m>=0xC0) { + return &test->emu->regs[(m&0x07)+(rex.b<<3)]; + } else { + reg64_t* ret = GetECommonO(test->emu, addr, rex, m, delta, offset); + test->memsize = 4<<rex.w; + test->memaddr = (uintptr_t)ret; + if(rex.w) + *(uint64_t*)test->mem = ret->q[0]; + else + *(uint32_t*)test->mem = ret->dword[0]; + return (reg64_t*)test->mem; + } +} + reg64_t* GetEd32O(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset) { uint8_t m = v&0xC7; // filter Ed @@ -1263,6 +1337,23 @@ reg64_t* GetEd32O(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t } else return GetECommon32O(emu, addr, rex, m, delta, offset); } +reg64_t* TestEd32O(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset) +{ + uint8_t m = v&0xC7; // filter Ed + if(m>=0xC0) { + return &test->emu->regs[(m&0x07)+(rex.b<<3)]; + } else { + reg64_t* ret = GetECommon32O(test->emu, addr, rex, m, delta, offset); + test->memsize = 4<<rex.w; + test->memaddr = (uintptr_t)ret; + if(rex.w) + *(uint64_t*)test->mem = ret->q[0]; + else + *(uint32_t*)test->mem = ret->dword[0]; + return (reg64_t*)test->mem; + } +} + reg64_t* GetEb32O(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset) { uint8_t m = v&0xC7; // filter Eb @@ -1276,7 +1367,27 @@ reg64_t* GetEb32O(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t } else return GetECommon32O(emu, addr, rex, m, delta, offset); } +reg64_t* TestEb32O(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset) +{ + uint8_t m = v&0xC7; // filter Eb + if(m>=0xC0) { + if(rex.rex) { + return &test->emu->regs[(m&0x07)+(rex.b<<3)]; + } else { + int lowhigh = (m&4)>>2; + return (reg64_t *)(((char*)(&test->emu->regs[(m&0x03)]))+lowhigh); //? + } + } else { + reg64_t* ret = GetECommon32O(test->emu, addr, rex, m, delta, offset); + test->memsize = 1; + test->memaddr = (uintptr_t)ret; + test->mem[0] = ret->byte[0]; + return (reg64_t*)test->mem; + } +} + #define GetEw GetEd +#define TestEw TestEd reg64_t* GetEw16(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v) { @@ -1307,6 +1418,39 @@ reg64_t* GetEw16(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v) } } +reg64_t* TestEw16(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v) +{ + (void)rex; + x64emu_t* emu = test->emu; + + uint8_t m = v&0xC7; // filter Ed + if(m>=0xC0) { + return &emu->regs[(m&0x07)]; + } else { + uintptr_t base = 0; + switch(m&7) { + case 0: base = R_BX+R_SI; break; + case 1: base = R_BX+R_DI; break; + case 2: base = R_BP+R_SI; break; + case 3: base = R_BP+R_DI; break; + case 4: base = R_SI; break; + case 5: base = R_DI; break; + case 6: base = R_BP; break; + case 7: base = R_BX; break; + } + switch((m>>6)&3) { + case 0: if(m==6) base = F16(addr); break; + case 1: base += F8S(addr); break; + case 2: base += F16S(addr); break; + // case 3 is C0..C7, already dealt with + } + test->memsize = 2; + *(uint16_t*)test->mem = *(uint16_t*)base; + test->memaddr = (uintptr_t)base; + return (reg64_t*)test->mem; + } +} + reg64_t* GetEw16off(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uintptr_t offset) { (void)rex; @@ -1336,6 +1480,39 @@ reg64_t* GetEw16off(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uintpt } } +reg64_t* TestEw16off(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uintptr_t offset) +{ + (void)rex; + x64emu_t* emu = test->emu; + + uint32_t m = v&0xC7; // filter Ed + if(m>=0xC0) { + return &emu->regs[(m&0x07)]; + } else { + uint32_t base = 0; + switch(m&7) { + case 0: base = R_BX+R_SI; break; + case 1: base = R_BX+R_DI; break; + case 2: base = R_BP+R_SI; break; + case 3: base = R_BP+R_DI; break; + case 4: base = R_SI; break; + case 5: base = R_DI; break; + case 6: base = R_BP; break; + case 7: base = R_BX; break; + } + switch((m>>6)&3) { + case 0: if(m==6) base = F16(addr); break; + case 1: base += F8S(addr); break; + case 2: base += F16S(addr); break; + // case 3 is C0..C7, already dealt with + } + test->memsize = 2; + *(uint16_t*)test->mem = *(uint16_t*)(base+offset); + test->memaddr = (uintptr_t)(base+offset); + return (reg64_t*)test->mem; + } +} + mmx87_regs_t* GetEm(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta) { uint8_t m = v&0xC7; // filter Ed @@ -1344,6 +1521,20 @@ mmx87_regs_t* GetEm(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_ } else return (mmx87_regs_t*)GetECommon(emu, addr, rex, m, delta); } +mmx87_regs_t* TestEm(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta) +{ + uint8_t m = v&0xC7; // filter Ed + if(m>=0xC0) { + return &test->emu->mmx[m&0x07]; + } else { + mmx87_regs_t* ret = (mmx87_regs_t*)GetECommon(test->emu, addr, rex, m, delta); + test->memsize = 8; + *(uint64_t*)test->mem = ret->q; + test->memaddr = (uintptr_t)ret; + return (mmx87_regs_t*)test->mem; + } +} + sse_regs_t* GetEx(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta) { uint8_t m = v&0xC7; // filter Ed @@ -1352,6 +1543,22 @@ sse_regs_t* GetEx(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t } else return (sse_regs_t*)GetECommon(emu, addr, rex, m, delta); } +sse_regs_t* TestEx(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta) +{ + uint8_t m = v&0xC7; // filter Ed + if(m>=0xC0) { + test->memsize=0; + return &test->emu->xmm[(m&0x07)+(rex.b<<3)]; + } else { + sse_regs_t* ret = (sse_regs_t*)GetECommon(test->emu, addr, rex, m, delta); + test->memsize = 16; + ((uint64_t*)test->mem)[0] = ret->q[0]; + ((uint64_t*)test->mem)[1] = ret->q[1]; + test->memaddr = (uintptr_t)ret; + return (sse_regs_t*)test->mem; + } +} + sse_regs_t* GetExO(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset) { uint8_t m = v&0xC7; // filter Ed @@ -1360,6 +1567,21 @@ sse_regs_t* GetExO(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t } else return (sse_regs_t*)GetECommonO(emu, addr, rex, m, delta, offset); } +sse_regs_t* TestExO(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset) +{ + uint8_t m = v&0xC7; // filter Ed + if(m>=0xC0) { + return &test->emu->xmm[(m&0x07)+(rex.b<<3)]; + } else { + sse_regs_t* ret = (sse_regs_t*)GetECommonO(test->emu, addr, rex, m, delta, offset); + test->memsize = 16; + ((uint64_t*)test->mem)[0] = ret->q[0]; + ((uint64_t*)test->mem)[1] = ret->q[1]; + test->memaddr = (uintptr_t)ret; + return (sse_regs_t*)test->mem; + } +} + sse_regs_t* GetEx32O(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset) { uint8_t m = v&0xC7; // filter Ed @@ -1368,6 +1590,21 @@ sse_regs_t* GetEx32O(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8 } else return (sse_regs_t*)GetECommon32O(emu, addr, rex, m, delta, offset); } +sse_regs_t* TestEx32O(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset) +{ + uint8_t m = v&0xC7; // filter Ed + if(m>=0xC0) { + return &test->emu->xmm[(m&0x07)+(rex.b<<3)]; + } else { + sse_regs_t* ret = (sse_regs_t*)GetECommon32O(test->emu, addr, rex, m, delta, offset); + test->memsize = 16; + ((uint64_t*)test->mem)[0] = ret->q[0]; + ((uint64_t*)test->mem)[1] = ret->q[1]; + test->memaddr = (uintptr_t)ret; + return (sse_regs_t*)test->mem; + } +} + mmx87_regs_t* GetEm32O(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset) { uint8_t m = v&0xC7; // filter Ed @@ -1376,6 +1613,19 @@ mmx87_regs_t* GetEm32O(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uin } else return (mmx87_regs_t*)GetECommon32O(emu, addr, rex, m, delta, offset); } +mmx87_regs_t* TestEm32O(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset) +{ + uint8_t m = v&0xC7; // filter Ed + if(m>=0xC0) { + return &test->emu->mmx[(m&0x07)]; + } else { + mmx87_regs_t* ret = (mmx87_regs_t*)GetECommon32O(test->emu, addr, rex, m, delta, offset); + test->memsize = 8; + *(uint64_t*)test->mem = ret->q; + test->memaddr = (uintptr_t)ret; + return (mmx87_regs_t*)test->mem; + } +} reg64_t* GetGd(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v) { diff --git a/src/emu/x64run_private.h b/src/emu/x64run_private.h index c4704a77..df0f177c 100755 --- a/src/emu/x64run_private.h +++ b/src/emu/x64run_private.h @@ -26,12 +26,16 @@ static inline uint64_t Pop(x64emu_t *emu) return *st; } +#ifdef TEST_INTERPRETER +#define Push(E, V) do{R_RSP -=8; test->memsize = 8; *(uint64_t*)test->mem = (V); test->memaddr = R_RSP;}while(0) +#define Push16(E, V) do{R_RSP -=2; test->memsize = 2; *(uint16_t*)test->mem = (V); test->memaddr = R_RSP;}while(0) +#else static inline void Push(x64emu_t *emu, uint64_t v) { R_RSP -= 8; *((uint64_t*)R_RSP) = v; } - +#endif // the op code definition can be found here: http://ref.x86asm.net/geek32.html @@ -39,24 +43,39 @@ reg64_t* GetECommon(x64emu_t* emu, uintptr_t* addr, rex_t rex, uint8_t m, uint8_ reg64_t* GetECommonO(x64emu_t* emu, uintptr_t* addr, rex_t rex, uint8_t m, uint8_t delta, uintptr_t offset); reg64_t* GetECommon32O(x64emu_t* emu, uintptr_t* addr, rex_t rex, uint8_t m, uint8_t delta, uintptr_t offset); reg64_t* GetEb(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta); +reg64_t* TestEb(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta); reg64_t* GetEbO(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset); +reg64_t* TestEbO(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset); reg64_t* GetEd(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta); +reg64_t* TestEd(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta); reg64_t* GetEdO(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset); +reg64_t* TestEdO(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset); reg64_t* GetEd32O(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset); +reg64_t* TestEd32O(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset); reg64_t* GetEb32O(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset); +reg64_t* TestEb32O(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset); #define GetEw GetEd +#define TestEw TestEd #define GetEw32O GetEd32O +#define TestEw32O TestEd32O reg64_t* GetEw16(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v); +reg64_t* TestEw16(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v); reg64_t* GetEw16off(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uintptr_t offset); +reg64_t* TestEw16off(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uintptr_t offset); mmx87_regs_t* GetEm(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta); +mmx87_regs_t* TestEm(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta); sse_regs_t* GetEx(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta); +sse_regs_t* TestEx(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta); sse_regs_t* GetExO(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset); +sse_regs_t* TestExO(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset); sse_regs_t* GetEx32O(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset); +sse_regs_t* TestEx32O(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset); reg64_t* GetGd(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v); #define GetGw GetGd reg64_t* GetGb(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v); mmx87_regs_t* GetGm(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v); mmx87_regs_t* GetEm32O(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset); +mmx87_regs_t* TestEm32O(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset); sse_regs_t* GetGx(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v); void UpdateFlags(x64emu_t *emu); @@ -88,6 +107,31 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr); uintptr_t RunF20F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step); uintptr_t RunF30F(x64emu_t *emu, rex_t rex, uintptr_t addr); +uintptr_t Test0F(x64test_t *test, rex_t rex, uintptr_t addr, int *step); +uintptr_t Test64(x64test_t *test, rex_t rex, int seg, uintptr_t addr); +uintptr_t Test66(x64test_t *test, rex_t rex, int rep, uintptr_t addr); +uintptr_t Test660F(x64test_t *test, rex_t rex, uintptr_t addr); +uintptr_t Test6664(x64test_t *test, rex_t rex, int seg, uintptr_t addr); +uintptr_t Test66D9(x64test_t *test, rex_t rex, uintptr_t addr); +uintptr_t Test66DD(x64test_t *test, rex_t rex, uintptr_t addr); +uintptr_t Test66F0(x64test_t *test, rex_t rex, uintptr_t addr); +uintptr_t Test67(x64test_t *test, rex_t rex, int rep, uintptr_t addr); +uintptr_t Test670F(x64test_t *test, rex_t rex, int rep, uintptr_t addr); +uintptr_t Test6766(x64test_t *test, rex_t rex, int rep, uintptr_t addr); +uintptr_t Test67660F(x64test_t *test, rex_t rex, uintptr_t addr); +uintptr_t TestD8(x64test_t *test, rex_t rex, uintptr_t addr); +uintptr_t TestD9(x64test_t *test, rex_t rex, uintptr_t addr); +uintptr_t TestDA(x64test_t *test, rex_t rex, uintptr_t addr); +uintptr_t TestDB(x64test_t *test, rex_t rex, uintptr_t addr); +uintptr_t TestDC(x64test_t *test, rex_t rex, uintptr_t addr); +uintptr_t TestDD(x64test_t *test, rex_t rex, uintptr_t addr); +uintptr_t TestDE(x64test_t *test, rex_t rex, uintptr_t addr); +uintptr_t TestDF(x64test_t *test, rex_t rex, uintptr_t addr); +uintptr_t TestF0(x64test_t *test, rex_t rex, uintptr_t addr); +uintptr_t TestF20F(x64test_t *test, rex_t rex, uintptr_t addr, int *step); +uintptr_t TestF30F(x64test_t *test, rex_t rex, uintptr_t addr); + + void x64Syscall(x64emu_t *emu); void x64Int3(x64emu_t* emu, uintptr_t* addr); x64emu_t* x64emu_fork(x64emu_t* e, int forktype); diff --git a/src/emu/x64rund8.c b/src/emu/x64rund8.c index 1f851bb5..374658b2 100644 --- a/src/emu/x64rund8.c +++ b/src/emu/x64rund8.c @@ -22,11 +22,18 @@ #include "modrm.h" +#ifdef TEST_INTERPRETER +uintptr_t TestD8(x64test_t *test, rex_t rex, uintptr_t addr) +#else uintptr_t RunD8(x64emu_t *emu, rex_t rex, uintptr_t addr) +#endif { uint8_t nextop; float f; reg64_t *oped; + #ifdef TEST_INTERPRETER + x64emu_t*emu = test->emu; + #endif nextop = F8; switch (nextop) { diff --git a/src/emu/x64rund9.c b/src/emu/x64rund9.c index e50f5bf5..6c1ad490 100644 --- a/src/emu/x64rund9.c +++ b/src/emu/x64rund9.c @@ -22,13 +22,20 @@ #include "modrm.h" +#ifdef TEST_INTERPRETER +uintptr_t TestD9(x64test_t *test, rex_t rex, uintptr_t addr) +#else uintptr_t RunD9(x64emu_t *emu, rex_t rex, uintptr_t addr) +#endif { uint8_t nextop; int32_t tmp32s; uint64_t ll; float f; reg64_t *oped; + #ifdef TEST_INTERPRETER + x64emu_t*emu = test->emu; + #endif nextop = F8; switch (nextop) { @@ -228,6 +235,9 @@ uintptr_t RunD9(x64emu_t *emu, rex_t rex, uintptr_t addr) case 0xEF: return 0; default: + #ifdef TEST_INTERPRETER + rex.w = 0; // hack, 32bit access only here + #endif switch((nextop>>3)&7) { case 0: /* FLD ST0, Ed float */ GETED(0); @@ -256,7 +266,9 @@ uintptr_t RunD9(x64emu_t *emu, rex_t rex, uintptr_t addr) case 6: /* FNSTENV m */ // warning, incomplete GETED(0); + #ifndef TEST_INTERPRETER fpu_savenv(emu, (char*)ED, 0); + #endif // intruction pointer: 48bits // data (operand) pointer: 48bits // last opcode: 11bits save: 16bits restaured (1st and 2nd opcode only) diff --git a/src/emu/x64runda.c b/src/emu/x64runda.c index 8a0f793c..a2f07cca 100644 --- a/src/emu/x64runda.c +++ b/src/emu/x64runda.c @@ -22,10 +22,17 @@ #include "modrm.h" +#ifdef TEST_INTERPRETER +uintptr_t TestDA(x64test_t *test, rex_t rex, uintptr_t addr) +#else uintptr_t RunDA(x64emu_t *emu, rex_t rex, uintptr_t addr) +#endif { uint8_t nextop; reg64_t *oped; + #ifdef TEST_INTERPRETER + x64emu_t*emu = test->emu; + #endif nextop = F8; switch (nextop) { @@ -96,6 +103,9 @@ uintptr_t RunDA(x64emu_t *emu, rex_t rex, uintptr_t addr) case 0xFD: return 0; default: + #ifdef TEST_INTERPRETER + rex.w = 0; // hack, 32bit access only here + #endif switch((nextop>>3)&7) { case 0: /* FIADD ST0, Ed int */ GETED(0); diff --git a/src/emu/x64rundb.c b/src/emu/x64rundb.c index 5791b58d..e3c05216 100644 --- a/src/emu/x64rundb.c +++ b/src/emu/x64rundb.c @@ -22,11 +22,18 @@ #include "modrm.h" +#ifdef TEST_INTERPRETER +uintptr_t TestDB(x64test_t *test, rex_t rex, uintptr_t addr) +#else uintptr_t RunDB(x64emu_t *emu, rex_t rex, uintptr_t addr) +#endif { uint8_t nextop; int32_t tmp32s; reg64_t *oped; + #ifdef TEST_INTERPRETER + x64emu_t*emu = test->emu; + #endif nextop = F8; switch(nextop) { @@ -125,6 +132,9 @@ uintptr_t RunDB(x64emu_t *emu, rex_t rex, uintptr_t addr) case 0xE7: return 0; default: + #ifdef TEST_INTERPRETER + rex.w = 0; // hack, 32bit access only here + #endif switch((nextop>>3)&7) { case 0: /* FILD ST0, Ed */ GETED(0); @@ -160,6 +170,10 @@ uintptr_t RunDB(x64emu_t *emu, rex_t rex, uintptr_t addr) break; case 5: /* FLD ST0, Et */ GETED(0); + #ifdef TEST_INTERPRETER + test->memsize = 10; + memcpy(ED, (void*)test->memaddr, 10); + #endif fpu_do_push(emu); memcpy(&STld(0).ld, ED, 10); LD2D(&STld(0), &ST(0).d); @@ -167,6 +181,9 @@ uintptr_t RunDB(x64emu_t *emu, rex_t rex, uintptr_t addr) break; case 7: /* FSTP tbyte */ GETED(0); + #ifdef TEST_INTERPRETER + test->memsize = 10; + #endif if(ST0.q!=STld(0).uref) D2LD(&ST0.d, ED); else diff --git a/src/emu/x64rundc.c b/src/emu/x64rundc.c index dbe4d45f..3b54f94c 100644 --- a/src/emu/x64rundc.c +++ b/src/emu/x64rundc.c @@ -22,10 +22,17 @@ #include "modrm.h" +#ifdef TEST_INTERPRETER +uintptr_t TestDC(x64test_t *test, rex_t rex, uintptr_t addr) +#else uintptr_t RunDC(x64emu_t *emu, rex_t rex, uintptr_t addr) +#endif { uint8_t nextop; reg64_t *oped; + #ifdef TEST_INTERPRETER + x64emu_t*emu = test->emu; + #endif nextop = F8; switch(nextop) { @@ -111,6 +118,9 @@ uintptr_t RunDC(x64emu_t *emu, rex_t rex, uintptr_t addr) ST(nextop&7).d /= ST0.d; break; default: + #ifdef TEST_INTERPRETER + rex.w = 1; // hack, 64bit access only here + #endif GETED(0); switch((nextop>>3)&7) { case 0: /* FADD ST0, double */ diff --git a/src/emu/x64rundd.c b/src/emu/x64rundd.c index abb18f77..651d04c9 100644 --- a/src/emu/x64rundd.c +++ b/src/emu/x64rundd.c @@ -22,10 +22,17 @@ #include "modrm.h" +#ifdef TEST_INTERPRETER +uintptr_t TestDD(x64test_t *test, rex_t rex, uintptr_t addr) +#else uintptr_t RunDD(x64emu_t *emu, rex_t rex, uintptr_t addr) +#endif { uint8_t nextop; reg64_t *oped; + #ifdef TEST_INTERPRETER + x64emu_t*emu = test->emu; + #endif nextop = F8; switch (nextop) { @@ -110,6 +117,9 @@ uintptr_t RunDD(x64emu_t *emu, rex_t rex, uintptr_t addr) return 0; default: + #ifdef TEST_INTERPRETER + rex.w = 1; // hack, mostly 64bit access only here + #endif switch((nextop>>3)&7) { case 0: /* FLD double */ GETED(0); @@ -147,6 +157,7 @@ uintptr_t RunDD(x64emu_t *emu, rex_t rex, uintptr_t addr) GETED(0); // ENV first... // warning, incomplete + #ifndef TEST_INTERPRETER fpu_savenv(emu, (char*)ED, 0); // save the STx { @@ -157,10 +168,14 @@ uintptr_t RunDD(x64emu_t *emu, rex_t rex, uintptr_t addr) p+=10; } } + #endif reset_fpu(emu); break; case 7: /* FNSTSW m2byte */ GETED(0); + #ifdef TEST_INTERPRETER + test->memsize = 2; + #endif emu->sw.f.F87_TOP = emu->top&7; *(uint16_t*)ED = emu->sw.x16; break; diff --git a/src/emu/x64runde.c b/src/emu/x64runde.c index 4911be32..317c0d95 100644 --- a/src/emu/x64runde.c +++ b/src/emu/x64runde.c @@ -22,10 +22,17 @@ #include "modrm.h" +#ifdef TEST_INTERPRETER +uintptr_t TestDE(x64test_t *test, rex_t rex, uintptr_t addr) +#else uintptr_t RunDE(x64emu_t *emu, rex_t rex, uintptr_t addr) +#endif { uint8_t nextop; reg64_t *oped; + #ifdef TEST_INTERPRETER + x64emu_t*emu = test->emu; + #endif nextop = F8; switch(nextop) { @@ -127,6 +134,9 @@ uintptr_t RunDE(x64emu_t *emu, rex_t rex, uintptr_t addr) return 0; default: + #ifdef TEST_INTERPRETER + rex.w = 0; // hack, 32bit access only here + #endif switch((nextop>>3)&7) { case 0: /* FIADD ST0, Ew int */ GETEW(0); diff --git a/src/emu/x64rundf.c b/src/emu/x64rundf.c index 657c1a48..beec70db 100644 --- a/src/emu/x64rundf.c +++ b/src/emu/x64rundf.c @@ -22,12 +22,19 @@ #include "modrm.h" +#ifdef TEST_INTERPRETER +uintptr_t TestDF(x64test_t *test, rex_t rex, uintptr_t addr) +#else uintptr_t RunDF(x64emu_t *emu, rex_t rex, uintptr_t addr) +#endif { uint8_t nextop; int16_t tmp16s; int64_t tmp64s; reg64_t *oped; + #ifdef TEST_INTERPRETER + x64emu_t*emu = test->emu; + #endif nextop = F8; switch(nextop) { @@ -144,10 +151,17 @@ uintptr_t RunDF(x64emu_t *emu, rex_t rex, uintptr_t addr) break; case 4: /* FBLD ST0, tbytes */ GETED(0); + #ifdef TEST_INTERPRETER + test->memsize = 10; + memcpy(ED, (void*)test->memaddr, 10); + #endif fpu_do_push(emu); fpu_fbld(emu, (uint8_t*)ED); break; case 5: /* FILD ST0, Gq */ + #ifdef TEST_INTERPRETER + rex.w = 1; // hack, 64bit access + #endif GETED(0); tmp64s = ED->sq[0]; fpu_do_push(emu); @@ -157,10 +171,16 @@ uintptr_t RunDF(x64emu_t *emu, rex_t rex, uintptr_t addr) break; case 6: /* FBSTP tbytes, ST0 */ GETED(0); + #ifdef TEST_INTERPRETER + test->memsize = 10; + #endif fpu_fbst(emu, (uint8_t*)ED); fpu_do_pop(emu); break; case 7: /* FISTP i64 */ + #ifdef TEST_INTERPRETER + rex.w = 1; // hack, 64bits access + #endif GETED(0); if(STll(0).sref==ST(0).sq) ED->sq[0] = STll(0).sq; diff --git a/src/emu/x64runf0.c b/src/emu/x64runf0.c index 6a9276be..03f5125e 100644 --- a/src/emu/x64runf0.c +++ b/src/emu/x64runf0.c @@ -26,7 +26,11 @@ #include "modrm.h" +#ifdef TEST_INTERPRETER +uintptr_t TestF0(x64test_t *test, rex_t rex, uintptr_t addr) +#else uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr) +#endif { uint8_t opcode; uint8_t nextop; @@ -39,6 +43,9 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr) #ifdef USE_CAS uint64_t tmpcas; #endif + #ifdef TEST_INTERPRETER + x64emu_t*emu = test->emu; + #endif opcode = F8; // REX prefix before the F0 are ignored @@ -49,7 +56,7 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr) } switch(opcode) { -#ifdef DYNAREC +#if defined(DYNAREC) && !defined(TEST_INTERPRETER) #define GO(B, OP) \ case B+0: \ nextop = F8; \ @@ -181,9 +188,17 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr) tmp64s >>= (rex.w?6:5); if(!MODREG) { + #ifdef TEST_INTERPRETER + test->memaddr=((test->memaddr)+(tmp32s<<(rex.w?3:2))); + if(rex.w) + *(uint64_t*)test->mem = *(uint64_t*)test->memaddr; + else + *(uint32_t*)test->mem = *(uint32_t*)test->memaddr; + #else ED=(reg64_t*)(((uintptr_t)(ED))+(tmp64s<<(rex.w?3:2))); + #endif } -#ifdef DYNAREC +#if defined(DYNAREC) && !defined(TEST_INTERPRETER) if(rex.w) { tmp8u&=63; if(MODREG) { @@ -258,7 +273,7 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr) nextop = F8; GETGB; GETEB(0); -#ifdef DYNAREC +#if defined(DYNAREC) && !defined(TEST_INTERPRETER) do { tmp8u = native_lock_read_b(EB); cmp8(emu, R_AL, tmp8u); @@ -284,7 +299,7 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr) nextop = F8; GETED(0); GETGD; -#ifdef DYNAREC +#if defined(DYNAREC) && !defined(TEST_INTERPRETER) if(rex.w) if(((uintptr_t)ED)&7) { do { @@ -360,10 +375,18 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr) tmp64s >>= (rex.w?6:5); if(!MODREG) { + #ifdef TEST_INTERPRETER + test->memaddr=((test->memaddr)+(tmp32s<<(rex.w?3:2))); + if(rex.w) + *(uint64_t*)test->mem = *(uint64_t*)test->memaddr; + else + *(uint32_t*)test->mem = *(uint32_t*)test->memaddr; + #else ED=(reg64_t*)(((uintptr_t)(ED))+(tmp64s<<(rex.w?3:2))); + #endif } tmp8u&=rex.w?63:31; -#ifdef DYNAREC +#if defined(DYNAREC) && !defined(TEST_INTERPRETER) if(rex.w) do { tmp64u = native_lock_read_dd(ED); @@ -437,7 +460,7 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr) CHECK_FLAGS(emu); GETED(1); tmp8u = F8; -#ifdef DYNAREC +#if defined(DYNAREC) && !defined(TEST_INTERPRETER) if(rex.w) { tmp8u&=63; do { @@ -491,7 +514,7 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr) CHECK_FLAGS(emu); GETED(1); tmp8u = F8; -#ifdef DYNAREC +#if defined(DYNAREC) && !defined(TEST_INTERPRETER) if(rex.w) { do { tmp8u&=63; @@ -543,7 +566,7 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr) CHECK_FLAGS(emu); GETED(1); tmp8u = F8; -#ifdef DYNAREC +#if defined(DYNAREC) && !defined(TEST_INTERPRETER) if(rex.w) { tmp8u&=63; do { @@ -597,7 +620,7 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr) nextop = F8; GETEB(0); GETGB; -#ifdef DYNAREC +#if defined(DYNAREC) && !defined(TEST_INTERPRETER) do { tmp8u = native_lock_read_b(EB); tmp8u2 = add8(emu, tmp8u, GB); @@ -615,7 +638,7 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr) nextop = F8; GETED(0); GETGD; -#ifdef DYNAREC +#if defined(DYNAREC) && !defined(TEST_INTERPRETER) if(rex.w) { do { tmp64u = native_lock_read_dd(ED); @@ -665,7 +688,7 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr) case 1: CHECK_FLAGS(emu); GETGD; -#ifdef DYNAREC +#if defined(DYNAREC) && !defined(TEST_INTERPRETER) if(rex.w) do { native_lock_read_dq(&tmp64u, &tmp64u2, ED); @@ -695,6 +718,9 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr) #else pthread_mutex_lock(&emu->context->mutex_lock); if(rex.w) { + #ifdef TEST_INTERPRETER + test->memsize = 16; + #endif tmp64u = ED->q[0]; tmp64u2= ED->q[1]; if(R_RAX == tmp64u && R_RDX == tmp64u2) { @@ -707,6 +733,9 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr) R_RDX = tmp64u2; } } else { + #ifdef TEST_INTERPRETER + test->memsize = 8; + #endif tmp32u = ED->dword[0]; tmp32u2= ED->dword[1]; if(R_EAX == tmp32u && R_EDX == tmp32u2) { @@ -733,13 +762,17 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr) break; case 0x66: + #ifdef TEST_INTERPRETER + return Test66F0(test, rex, addr); + #else return Run66F0(emu, rex, addr); // more opcode F0 66 and 66 F0 is the same + #endif case 0x80: /* GRP Eb,Ib */ nextop = F8; GETEB(1); tmp8u = F8; -#ifdef DYNAREC +#if defined(DYNAREC) && !defined(TEST_INTERPRETER) switch((nextop>>3)&7) { case 0: do { tmp8u2 = native_lock_read_b(EB); tmp8u2 = add8(emu, tmp8u2, tmp8u);} while(native_lock_write_b(EB, tmp8u2)); break; case 1: do { tmp8u2 = native_lock_read_b(EB); tmp8u2 = or8(emu, tmp8u2, tmp8u);} while(native_lock_write_b(EB, tmp8u2)); break; @@ -774,7 +807,7 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr) tmp64u = (uint64_t)tmp64s; } else tmp64u = F32S64; -#ifdef DYNAREC +#if defined(DYNAREC) && !defined(TEST_INTERPRETER) if(rex.w) { switch((nextop>>3)&7) { case 0: do { tmp64u2 = native_lock_read_dd(ED); tmp64u2 = add64(emu, tmp64u2, tmp64u);} while(native_lock_write_dd(ED, tmp64u2)); break; @@ -853,7 +886,7 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr) case 0x86: /* XCHG Eb,Gb */ nextop = F8; -#ifdef DYNAREC +#if defined(DYNAREC) && !defined(TEST_INTERPRETER) GETEB(0); GETGB; if(MODREG) { // reg / reg: no lock @@ -880,7 +913,7 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr) break; case 0x87: /* XCHG Ed,Gd */ nextop = F8; -#ifdef DYNAREC +#if defined(DYNAREC) && !defined(TEST_INTERPRETER) GETED(0); GETGD; if(MODREG) { @@ -926,7 +959,7 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr) GETEB((tmp8u<2)?1:0); switch(tmp8u) { case 2: /* NOT Eb */ -#ifdef DYNAREC +#if defined(DYNAREC) && !defined(TEST_INTERPRETER) do { tmp8u2 = native_lock_read_b(EB); tmp8u2 = not8(emu, tmp8u2); @@ -947,7 +980,7 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr) GETED(0); switch((nextop>>3)&7) { case 0: /* INC Eb */ -#ifdef DYNAREC +#if defined(DYNAREC) && !defined(TEST_INTERPRETER) do { tmp8u = native_lock_read_b(ED); } while(native_lock_write_b(ED, inc8(emu, tmp8u))); @@ -958,7 +991,7 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr) #endif break; case 1: /* DEC Ed */ -#ifdef DYNAREC +#if defined(DYNAREC) && !defined(TEST_INTERPRETER) do { tmp8u = native_lock_read_b(ED); } while(native_lock_write_b(ED, dec8(emu, tmp8u))); @@ -980,7 +1013,7 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr) GETED(0); switch((nextop>>3)&7) { case 0: /* INC Ed */ -#ifdef DYNAREC +#if defined(DYNAREC) && !defined(TEST_INTERPRETER) if(rex.w) if(((uintptr_t)ED)&7) { // unaligned @@ -1026,7 +1059,7 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr) #endif break; case 1: /* DEC Ed */ -#ifdef DYNAREC +#if defined(DYNAREC) && !defined(TEST_INTERPRETER) if(rex.w) if(((uintptr_t)ED)&7) { // unaligned diff --git a/src/emu/x64runf20f.c b/src/emu/x64runf20f.c index a2c0e8e0..d7ce1eee 100644 --- a/src/emu/x64runf20f.c +++ b/src/emu/x64runf20f.c @@ -22,7 +22,11 @@ #include "modrm.h" +#ifdef TEST_INTERPRETER +uintptr_t TestF20F(x64test_t *test, rex_t rex, uintptr_t addr, int *step) +#else uintptr_t RunF20F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step) +#endif { uint8_t opcode; uint8_t nextop; @@ -35,6 +39,9 @@ uintptr_t RunF20F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step) #ifndef NOALIGN int is_nan; #endif + #ifdef TEST_INTERPRETER + x64emu_t*emu = test->emu; + #endif opcode = F8; diff --git a/src/emu/x64runf30f.c b/src/emu/x64runf30f.c index acfd7895..4149c94e 100644 --- a/src/emu/x64runf30f.c +++ b/src/emu/x64runf30f.c @@ -22,7 +22,11 @@ #include "modrm.h" +#ifdef TEST_INTERPRETER +uintptr_t TestF30F(x64test_t *test, rex_t rex, uintptr_t addr) +#else uintptr_t RunF30F(x64emu_t *emu, rex_t rex, uintptr_t addr) +#endif { uint8_t opcode; uint8_t nextop; @@ -33,6 +37,9 @@ uintptr_t RunF30F(x64emu_t *emu, rex_t rex, uintptr_t addr) reg64_t *oped, *opgd; sse_regs_t *opex, *opgx, eax1; mmx87_regs_t *opem; + #ifdef TEST_INTERPRETER + x64emu_t*emu = test->emu; + #endif opcode = F8; diff --git a/src/emu/x64test.c b/src/emu/x64test.c new file mode 100644 index 00000000..f58e68c4 --- /dev/null +++ b/src/emu/x64test.c @@ -0,0 +1,142 @@ +#define _GNU_SOURCE +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <math.h> +#include <string.h> +#include <signal.h> +#include <sys/types.h> +#include <unistd.h> + +#include "debug.h" +#include "box64stack.h" +#include "x64emu.h" +#include "x64run.h" +#include "x64emu_private.h" +#include "x64run_private.h" +#include "x64primop.h" +#include "x64trace.h" +#include "x87emu_private.h" +#include "box64context.h" +#include "bridge.h" +#include "signals.h" + +void x64test_init(x64emu_t* ref, uintptr_t ip, int ok) +{ + x64test_t* test = &ref->test; + // check if test as a valid emu struct + if(!test->emu) { + test->emu = NewX64Emu(my_context, ip, (uintptr_t)ref->init_stack, ref->size_stack, 0); + CopyEmu(test->emu, ref); + } + // check if IP is same, else, sync + if(ip != test->emu->ip.q[0] || !ok) { + CopyEmu(test->emu, ref); + } + // Do a Dry single Step + test->memsize = 0; + RunTest(test); +} + +void print_banner(x64emu_t* ref) +{ + printf_log(LOG_NONE, "Warning, difference between Interpreter and Dynarec in %p\n=======================================\n", (void*)ref->ip.q[0]); + printf_log(LOG_NONE, "DIF: Dynarec | Intepreter\n----------------------\n"); +} +#define BANNER if(!banner) {banner=1; print_banner(ref);} +void x64test_check(x64emu_t* ref, uintptr_t ip) +{ + int banner = 0; + x64test_t* test = &ref->test; + x64emu_t* emu = test->emu; + if(memcmp(ref->regs, emu->regs, sizeof(emu->regs))) { + static const char* regname[] = {"RAX", "RCX", "RDX", "RBX", "RSP", "RBP", "RSI", "RDI", + " R8", " R9", "R10", "R11", "R12", "R13", "R14", "R15"}; + BANNER; + for(int i=0; i<16; ++i) { + if(ref->regs[i].q[0]!=emu->regs[i].q[0]) { + printf_log(LOG_NONE, "%s: %016zx | %016zx\n", regname[i], ref->regs[i].q[0], emu->regs[i].q[0]); + } + } + } + if(ip!=emu->ip.q[0]) { + BANNER; + printf_log(LOG_NONE, "RIP: %016zx | %016zx\n", ip, emu->ip.q[0]); + } + // flags are volatile, so don't test them + //memcpy(&ref->eflags, &emu->eflags, sizeof(emu->eflags)); + if(memcmp(ref->segs, emu->segs, sizeof(emu->segs))) { + static const char* segname[] = {"CS", "DS", "ES", "SS", "FS", "GS"}; + BANNER; + for(int i=0; i<6; ++i) { + if(ref->segs[i]!=emu->segs[i]) { + printf_log(LOG_NONE, "%s: %04x | %04x\n", segname[i], ref->segs[i], emu->segs[i]); + } + } + } + if(ref->top != emu->top) { + BANNER; + printf_log(LOG_NONE, "X87 TOP: %d | %d\n", ref->top, emu->top); + } + if(ref->fpu_stack != emu->fpu_stack) { + BANNER; + printf_log(LOG_NONE, "X87 STACK: %d | %d\n", ref->fpu_stack, emu->fpu_stack); + } + if(ref->fpu_stack && memcmp(ref->x87, emu->x87, sizeof(emu->x87))) { + // need to check each regs, unused one might have different left over value + for(int i=0; i<ref->fpu_stack; ++i) { + if(ref->x87[(ref->top+i)&7].d != emu->x87[(emu->top+i)&7].d) { + BANNER; + printf_log(LOG_NONE, "ST%d: %g | %g\n", i, ref->x87[(ref->top+i)&7].d, emu->x87[(emu->top+i)&7].d); + } + } + } + //memcpy(ref->fpu_ld, emu->fpu_ld, sizeof(emu->fpu_ld)); + //memcpy(ref->fpu_ll, emu->fpu_ll, sizeof(emu->fpu_ll)); + /*if(ref->p_regs != emu->p_regs) { + BANNER; + printf_log(LOG_NONE, "X87 PREG: %x | %x\n", ref->p_regs, emu->p_regs); + }*/ + if(ref->cw.x16 != emu->cw.x16) { + BANNER; + printf_log(LOG_NONE, "X87 CW: %x | %x\n", ref->cw.x16, emu->cw.x16); + } + if(ref->sw.x16 != emu->sw.x16) { + BANNER; + printf_log(LOG_NONE, "X87 SW: %x | %x\n", ref->sw.x16, emu->sw.x16); + } + if(memcmp(ref->mmx, emu->mmx, sizeof(emu->mmx))) { + BANNER; + for(int i=0; i<8; ++i) { + if(ref->mmx[i].q!=emu->mmx[i].q) { + printf_log(LOG_NONE, "EMM[%d]: %016x | %016x\n", i, ref->mmx[i].q, emu->mmx[i].q); + } + } + } + if(ref->mxcsr.x32 != emu->mxcsr.x32) { + BANNER; + printf_log(LOG_NONE, "MXCSR: %x | %x\n", ref->mxcsr.x32, emu->mxcsr.x32); + } + if(memcmp(ref->xmm, emu->xmm, sizeof(emu->xmm))) { + BANNER; + for(int i=0; i<16; ++i) { + if(ref->xmm[i].q[0]!=emu->xmm[i].q[0] || ref->xmm[i].q[1]!=emu->xmm[i].q[1] ) { + printf_log(LOG_NONE, "XMM[%02d]: %016zx-%016zx | %016zx-%016zx\n", i, ref->xmm[i].q[0], ref->xmm[i].q[1], emu->xmm[i].q[0], emu->xmm[i].q[1]); + } + } + } + if(test->memsize) { + if(memcmp(test->mem, (void*)test->memaddr, test->memsize)) { + BANNER; + printf_log(LOG_NONE, "MEM: @%p :", (void*)test->memaddr); + for(int i=0; i<test->memsize; ++i) + printf_log(LOG_NONE, " %02x", test->mem[i]); + printf_log(LOG_NONE, " |"); + for(int i=0; i<test->memsize; ++i) + printf_log(LOG_NONE, " %02x", ((uint8_t*)test->memaddr)[i]); + } + } + if(banner) // there was an error, re-sync! + CopyEmu(emu, ref); +} +#undef BANNER \ No newline at end of file diff --git a/src/include/box64context.h b/src/include/box64context.h index 1920bb8a..62e4bad5 100755 --- a/src/include/box64context.h +++ b/src/include/box64context.h @@ -136,6 +136,7 @@ typedef struct box64context_s { uint32_t mutex_bridge; uintptr_t max_db_size; // the biggest (in x86_64 instructions bytes) built dynablock int trace_dynarec; + pthread_mutex_t mutex_lock; // this is for the Test interpreter #endif library_t *libclib; // shortcut to libc library (if loaded, so probably yes) diff --git a/src/include/debug.h b/src/include/debug.h index e13de642..37146e02 100755 --- a/src/include/debug.h +++ b/src/include/debug.h @@ -26,6 +26,7 @@ extern int box64_dynarec_bleeding_edge; extern int box64_dynarec_hotpage; extern int box64_dynarec_fastpage; extern int box64_dynarec_wait; +extern int box64_dynarec_test; #ifdef ARM64 extern int arm64_asimd; extern int arm64_aes; diff --git a/src/include/dynarec.h b/src/include/dynarec.h index a68c6d6a..c304cf1e 100755 --- a/src/include/dynarec.h +++ b/src/include/dynarec.h @@ -5,4 +5,7 @@ typedef struct x64emu_s x64emu_t; void DynaCall(x64emu_t* emu, uintptr_t addr); // try to use DynaRec... Fallback to EmuCall if no dynarec available +void x64test_init(x64emu_t* ref); +void x64test_check(x64emu_t* ref); + #endif // __DYNAREC_H_ \ No newline at end of file diff --git a/src/include/x64emu.h b/src/include/x64emu.h index e7efbb07..17252b68 100755 --- a/src/include/x64emu.h +++ b/src/include/x64emu.h @@ -10,6 +10,7 @@ void SetupX64Emu(x64emu_t *emu); void FreeX64Emu(x64emu_t **x64emu); void FreeX64EmuFromStack(x64emu_t **emu); void CloneEmu(x64emu_t *newemu, const x64emu_t* emu); +void CopyEmu(x64emu_t *newemu, const x64emu_t* emu); void SetTraceEmu(uintptr_t trace_start, uintptr_t trace_end); box64context_t* GetEmuContext(x64emu_t* emu); diff --git a/src/include/x64run.h b/src/include/x64run.h index 78903bbc..0e156341 100755 --- a/src/include/x64run.h +++ b/src/include/x64run.h @@ -3,7 +3,9 @@ #include <stdint.h> typedef struct x64emu_s x64emu_t; +typedef struct x64test_s x64test_t; int Run(x64emu_t *emu, int step); // 0 if run was successfull, 1 if error in x86 world +int RunTest(x64test_t *test); int DynaRun(x64emu_t *emu); uint32_t LibSyscall(x64emu_t *emu); diff --git a/src/main.c b/src/main.c index 67c004eb..9d4fc873 100755 --- a/src/main.c +++ b/src/main.c @@ -62,6 +62,7 @@ int box64_dynarec_hotpage = 4; int box64_dynarec_fastpage = 0; int box64_dynarec_bleeding_edge = 1; int box64_dynarec_wait = 1; +int box64_dynarec_test = 0; uintptr_t box64_nodynarec_start = 0; uintptr_t box64_nodynarec_end = 0; #ifdef ARM64 @@ -600,6 +601,18 @@ void LoadLogEnv() printf_log(LOG_INFO, "No dynablock creation that start in the range %p - %p\n", (void*)box64_nodynarec_start, (void*)box64_nodynarec_end); } } + p = getenv("BOX64_DYNAREC_TEST"); + if(p) { + if(strlen(p)==1) { + if(p[0]>='0' && p[0]<='1') + box64_dynarec_test = p[0]-'0'; + } + if(box64_dynarec_test) { + box64_dynarec_fastnan = 0; + box64_dynarec_fastround = 0; + printf_log(LOG_INFO, "Dynarec will compare it's execution with the interpreter (super slow, only for testing)\n"); + } + } #endif #ifdef HAVE_TRACE diff --git a/src/tools/rcfile.c b/src/tools/rcfile.c index 884f60eb..4687ec50 100644 --- a/src/tools/rcfile.c +++ b/src/tools/rcfile.c @@ -127,6 +127,7 @@ ENTRYINT(BOX64_DYNAREC_HOTPAGE, box64_dynarec_hotpage, 0, 255, 8) \ ENTRYBOOL(BOX64_DYNAREC_FASTPAGE, box64_dynarec_fastpage) \ ENTRYBOOL(BOX64_DYNAREC_WAIT, box64_dynarec_wait) \ ENTRYSTRING_(BOX64_NODYNAREC, box64_nodynarec) \ +ENTRYBOOL(BOX64_DYNAREC_TEST, box64_dynarec_test) \ #else #define SUPER3() \ @@ -146,6 +147,7 @@ IGNORE(BOX64_DYNAREC_HOTPAGE) \ IGNORE(BOX64_DYNAREC_FASTPAGE) \ IGNORE(BOX64_DYNAREC_WAIT) \ IGNORE(BOX64_NODYNAREC) \ +IGNORE(BOX64_DYNAREC_TEST) \ #endif |