diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2023-03-28 13:34:45 +0200 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2023-03-28 13:34:56 +0200 |
| commit | d73ff21b27b7f2fdca3f817fb37faefe388439d8 (patch) | |
| tree | cfe79810c265024864f845bee0d286df03ab7ae0 | |
| parent | 4a90199f63ea2e8ee16d11a20c5b9cc9abd11498 (diff) | |
| download | box64-d73ff21b27b7f2fdca3f817fb37faefe388439d8.tar.gz box64-d73ff21b27b7f2fdca3f817fb37faefe388439d8.zip | |
[DYNAREC] Improved TEST_INTERPRETER with inter-block testing
| -rwxr-xr-x | src/dynarec/arm64/dynarec_arm64_00.c | 12 | ||||
| -rwxr-xr-x | src/dynarec/arm64/dynarec_arm64_0f.c | 3 | ||||
| -rwxr-xr-x | src/dynarec/arm64/dynarec_arm64_helper.h | 11 | ||||
| -rwxr-xr-x | src/dynarec/arm64/dynarec_arm64_private.h | 1 | ||||
| -rw-r--r-- | src/dynarec/dynarec_native_functions.c | 2 | ||||
| -rwxr-xr-x | src/dynarec/dynarec_native_pass.c | 12 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_00.c | 4 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_0f.c | 2 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_helper.h | 11 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_private.h | 1 | ||||
| -rwxr-xr-x | src/emu/x64emu_private.h | 3 | ||||
| -rwxr-xr-x | src/emu/x64run.c | 8 | ||||
| -rw-r--r-- | src/emu/x64test.c | 41 | ||||
| -rwxr-xr-x | src/libtools/signals.c | 9 |
14 files changed, 81 insertions, 39 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_00.c b/src/dynarec/arm64/dynarec_arm64_00.c index 7a91dcf1..2c82d929 100755 --- a/src/dynarec/arm64/dynarec_arm64_00.c +++ b/src/dynarec/arm64/dynarec_arm64_00.c @@ -500,7 +500,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin case 0x57: INST_NAME("PUSH reg"); if(dyn->doublepush) { - dyn->test = 0; + NOTEST(x1); dyn->doublepush = 0; } else { gd = xRAX+(opcode&0x07)+(rex.b<<3); @@ -525,7 +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 + NOTEST(x1); // disable test for this OP } else { PUSH1(gd); } @@ -541,7 +541,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin case 0x5F: INST_NAME("POP reg"); if(dyn->doublepop) { - dyn->test = 0; + NOTEST(x1); dyn->doublepop = 0; } else { gd = xRAX+(opcode&0x07)+(rex.b<<3); @@ -566,7 +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 + NOTEST(x1); // disable test for this OP } else { if(gd == xRSP) { POP1(x1); @@ -1749,7 +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; + NOTEST(x1); if(PK(0)=='S' && PK(1)=='C') { addr+=2; BARRIER(BARRIER_FLOAT); @@ -2216,7 +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 + NOTEST(x1); // 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_0f.c b/src/dynarec/arm64/dynarec_arm64_0f.c index 8b817c9e..d0f055f2 100755 --- a/src/dynarec/arm64/dynarec_arm64_0f.c +++ b/src/dynarec/arm64/dynarec_arm64_0f.c @@ -75,6 +75,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin case 0x05: INST_NAME("SYSCALL"); + NOTEST(x1); SMEND(); GETIP(addr); STORE_XEMU_CALL(xRIP); @@ -329,6 +330,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin case 0x31: INST_NAME("RDTSC"); + NOTEST(x1); MESSAGE(LOG_DUMP, "Need Optimization\n"); CALL(ReadTSC, xRAX); // will return the u64 in xEAX LSRx(xRDX, xRAX, 32); @@ -1069,6 +1071,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin case 0xA2: INST_NAME("CPUID"); + NOTEST(x1); MOVx_REG(x1, xRAX); CALL_(my_cpuid, -1, 0); break; diff --git a/src/dynarec/arm64/dynarec_arm64_helper.h b/src/dynarec/arm64/dynarec_arm64_helper.h index acc9a0c5..64f05583 100755 --- a/src/dynarec/arm64/dynarec_arm64_helper.h +++ b/src/dynarec/arm64/dynarec_arm64_helper.h @@ -1301,4 +1301,15 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n , cNE, cEQ, X_SF|X_OF|X_ZF) \ break +#define NOTEST(s1) \ + if(box64_dynarec_test) { \ + if(offsetof(x64emu_t, test.test)<(1<<12)) { \ + STRw_U12(xZR, xEmu, offsetof(x64emu_t, test.test));\ + } else { \ + MOV32w(s1, offsetof(x64emu_t, test.test)); \ + ADDx_REG(s1, xEmu, s1); \ + STRw_U12(xZR, s1, 0); \ + } \ + } + #endif //__DYNAREC_ARM64_HELPER_H__ diff --git a/src/dynarec/arm64/dynarec_arm64_private.h b/src/dynarec/arm64/dynarec_arm64_private.h index 82747067..15705634 100755 --- a/src/dynarec/arm64/dynarec_arm64_private.h +++ b/src/dynarec/arm64/dynarec_arm64_private.h @@ -106,7 +106,6 @@ 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 diff --git a/src/dynarec/dynarec_native_functions.c b/src/dynarec/dynarec_native_functions.c index 2cf87003..42c7fba8 100644 --- a/src/dynarec/dynarec_native_functions.c +++ b/src/dynarec/dynarec_native_functions.c @@ -153,6 +153,8 @@ void native_fld(x64emu_t* emu, uint8_t* ed) void native_ud(x64emu_t* emu) { + if(box64_dynarec_test) + emu->test.test = 0; emit_signal(emu, SIGILL, (void*)R_RIP, 0); } diff --git a/src/dynarec/dynarec_native_pass.c b/src/dynarec/dynarec_native_pass.c index 80da9436..d81ef6ee 100755 --- a/src/dynarec/dynarec_native_pass.c +++ b/src/dynarec/dynarec_native_pass.c @@ -86,9 +86,8 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr) if(box64_dynarec_test) { MESSAGE(LOG_DUMP, "TEST INIT ----\n"); fpu_reflectcache(dyn, ninst, x1, x2, x3); - GO_TRACE(x64test_init, dyn->test); + GO_TRACE(x64test_init, 1); MESSAGE(LOG_DUMP, "----------\n"); - dyn->test = 1; } #ifdef HAVE_TRACE else if(my_context->dec && box64_dynarec_trace) { @@ -122,13 +121,6 @@ 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; @@ -262,12 +254,14 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr) dyn->insts[ninst].x64.need_after |= X_PEND; #endif ++ninst; + NOTEST(x3); fpu_purgecache(dyn, ninst, 0, x1, x2, x3); jump_to_next(dyn, addr, 0, ninst); ok=0; need_epilog=0; } } if(need_epilog) { + NOTEST(x3); fpu_purgecache(dyn, ninst, 0, x1, x2, x3); jump_to_epilog(dyn, ip, 0, ninst); // no linker here, it's an unknow instruction } diff --git a/src/dynarec/rv64/dynarec_rv64_00.c b/src/dynarec/rv64/dynarec_rv64_00.c index 2b62f097..4dab2b01 100644 --- a/src/dynarec/rv64/dynarec_rv64_00.c +++ b/src/dynarec/rv64/dynarec_rv64_00.c @@ -1270,7 +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; + NOTEST(x1); if(PK(0)=='S' && PK(1)=='C') { addr+=2; BARRIER(BARRIER_FLOAT); @@ -1464,7 +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; + NOTEST(x1); BARRIER(BARRIER_FULL); //BARRIER_NEXT(BARRIER_FULL); if(dyn->last_ip && (addr-dyn->last_ip<0x1000)) { diff --git a/src/dynarec/rv64/dynarec_rv64_0f.c b/src/dynarec/rv64/dynarec_rv64_0f.c index 74f3379a..965f4fea 100644 --- a/src/dynarec/rv64/dynarec_rv64_0f.c +++ b/src/dynarec/rv64/dynarec_rv64_0f.c @@ -73,6 +73,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni case 0x05: INST_NAME("SYSCALL"); + NOTEST(x1); SMEND(); GETIP(addr); STORE_XEMU_CALL(); @@ -314,6 +315,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni case 0xA2: INST_NAME("CPUID"); + NOTEST(x1); MV(A1, xRAX); CALL_(my_cpuid, -1, 0); // BX and DX are not synchronized durring the call, so need to force the update diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h index 3c3d11e5..e8ad11ab 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.h +++ b/src/dynarec/rv64/dynarec_rv64_helper.h @@ -1106,4 +1106,15 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int , NEZ, EQZ, X_SF|X_OF|X_ZF) \ break +#define NOTEST(s1) \ + if(box64_dynarec_test) { \ + if(offsetof(x64emu_t, test.test)<2048) { \ + SW(xZR, xEmu, offsetof(x64emu_t, test.test)); \ + } else { \ + MOV32w(s1, offsetof(x64emu_t, test.test)); \ + ADD(s1, xEmu, s1); \ + SW(xZR, s1, 0); \ + } \ + } + #endif //__DYNAREC_RV64_HELPER_H__ diff --git a/src/dynarec/rv64/dynarec_rv64_private.h b/src/dynarec/rv64/dynarec_rv64_private.h index e6fc7f63..3d6205d9 100644 --- a/src/dynarec/rv64/dynarec_rv64_private.h +++ b/src/dynarec/rv64/dynarec_rv64_private.h @@ -107,7 +107,6 @@ 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 diff --git a/src/emu/x64emu_private.h b/src/emu/x64emu_private.h index 3393986c..3fb43df3 100755 --- a/src/emu/x64emu_private.h +++ b/src/emu/x64emu_private.h @@ -31,6 +31,7 @@ typedef struct x64test_s { x64emu_t* emu; uintptr_t memaddr; int memsize; + int test; uint8_t mem[16]; } x64test_t; @@ -86,6 +87,7 @@ typedef struct x64emu_s { int quitonlongjmp; // quit if longjmp is called int quitonexit; // quit if exit/_exit is called int longjmp; // if quit because of longjmp + x64test_t test; // used for dynarec testing // scratch stack, used for alignement of double and 64bits ints on arm. 200 elements should be enough uint64_t scratch[200]; // local stack, do be deleted when emu is freed @@ -96,7 +98,6 @@ 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 0f982a77..f064dfd1 100755 --- a/src/emu/x64run.c +++ b/src/emu/x64run.c @@ -1581,9 +1581,9 @@ x64emurun: break; case 0xFF: /* GRP 5 Ed */ nextop = F8; - GETED(0); switch((nextop>>3)&7) { case 0: /* INC Ed */ + GETED(0); if(rex.w) ED->q[0] = inc64(emu, ED->q[0]); else { @@ -1594,6 +1594,7 @@ x64emurun: } break; case 1: /* DEC Ed */ + GETED(0); if(rex.w) ED->q[0] = dec64(emu, ED->q[0]); else { @@ -1604,12 +1605,14 @@ x64emurun: } break; case 2: /* CALL NEAR Ed */ + GETE8(0); tmp64u = (uintptr_t)getAlternate((void*)ED->q[0]); Push(emu, addr); addr = tmp64u; STEP2 break; case 3: /* CALL FAR Ed */ + GETET(0); if(MODREG) { printf_log(LOG_NONE, "Illegal Opcode %p: %02X %02X %02X %02X\n", (void*)R_RIP, opcode, nextop, PK(2), PK(3)); emu->quit=1; @@ -1624,10 +1627,12 @@ x64emurun: } break; case 4: /* JMP NEAR Ed */ + GETE8(0); addr = (uintptr_t)getAlternate((void*)ED->q[0]); STEP2 break; case 5: /* JMP FAR Ed */ + GETET(0); if(MODREG) { printf_log(LOG_NONE, "Illegal Opcode %p: 0x%02X 0x%02X %02X %02X\n", (void*)R_RIP, opcode, nextop, PK(2), PK(3)); emu->quit=1; @@ -1640,6 +1645,7 @@ x64emurun: } break; case 6: /* Push Ed */ + GETE8(0); tmp64u = ED->q[0]; // rex.w ignored #ifdef TEST_INTERPRETER R_RSP -=8; diff --git a/src/emu/x64test.c b/src/emu/x64test.c index f58e68c4..ee241597 100644 --- a/src/emu/x64test.c +++ b/src/emu/x64test.c @@ -7,6 +7,7 @@ #include <signal.h> #include <sys/types.h> #include <unistd.h> +#include <stddef.h> #include "debug.h" #include "box64stack.h" @@ -21,23 +22,6 @@ #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]); @@ -134,9 +118,30 @@ void x64test_check(x64emu_t* ref, uintptr_t ip) printf_log(LOG_NONE, " |"); for(int i=0; i<test->memsize; ++i) printf_log(LOG_NONE, " %02x", ((uint8_t*)test->memaddr)[i]); + printf_log(LOG_NONE, "\n"); } } if(banner) // there was an error, re-sync! CopyEmu(emu, ref); } -#undef BANNER \ No newline at end of file +#undef BANNER + +void x64test_init(x64emu_t* ref, uintptr_t ip) +{ + 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); + } else if(test->test) { + x64test_check(ref, ip); + } + // check if IP is same, else, sync + if(ip != test->emu->ip.q[0] || !test->test) { + CopyEmu(test->emu, ref); + } + // Do a Dry single Step + test->memsize = 0; + test->test = 1; + RunTest(test); +} diff --git a/src/libtools/signals.c b/src/libtools/signals.c index 9526f49b..df715a0f 100755 --- a/src/libtools/signals.c +++ b/src/libtools/signals.c @@ -291,6 +291,10 @@ uint64_t RunFunctionHandler(int* exit, x64_ucontext_t* sigcontext, uintptr_t fnc #endif x64emu_t *emu = thread_get_emu(); + #ifdef DYNAREC + if(box64_dynarec_test) + emu->test.test = 0; + #endif printf_log(LOG_DEBUG, "%04d|signal function handler %p called, RSP=%p\n", GetTID(), (void*)fnc, (void*)R_RSP); @@ -326,6 +330,11 @@ uint64_t RunFunctionHandler(int* exit, x64_ucontext_t* sigcontext, uintptr_t fnc emu->quitonlongjmp = oldquitonlongjmp; + #ifdef DYNAREC + if(box64_dynarec_test) + emu->test.test = 0; + #endif + if(emu->longjmp) { // longjmp inside signal handler, lets grab all relevent value and do the actual longjmp in the signal handler emu->longjmp = 0; |