diff options
Diffstat (limited to 'src/dynarec/dynarec.c')
| -rw-r--r-- | src/dynarec/dynarec.c | 148 |
1 files changed, 59 insertions, 89 deletions
diff --git a/src/dynarec/dynarec.c b/src/dynarec/dynarec.c index f0b0eeb5..ab7a21ae 100644 --- a/src/dynarec/dynarec.c +++ b/src/dynarec/dynarec.c @@ -1,6 +1,5 @@ #include <stdio.h> #include <stdlib.h> -#include <pthread.h> #include <errno.h> #include <setjmp.h> @@ -8,7 +7,6 @@ #include "box64context.h" #include "dynarec.h" #include "emu/x64emu_private.h" -#include "tools/bridge_private.h" #include "x64run.h" #include "x64emu.h" #include "box64stack.h" @@ -31,6 +29,7 @@ uintptr_t getX64Address(dynablock_t* db, uintptr_t arm_addr); void* LinkNext(x64emu_t* emu, uintptr_t addr, void* x2, uintptr_t* x3) { + int is32bits = (R_CS == 0x23); #ifdef HAVE_TRACE if(!addr) { dynablock_t* db = FindDynablockFromNativeAddress(x2-4); @@ -38,29 +37,28 @@ void* LinkNext(x64emu_t* emu, uintptr_t addr, void* x2, uintptr_t* x3) } #endif void * jblock; - dynablock_t* block = DBGetBlock(emu, addr, 1); + dynablock_t* block = NULL; + if(hasAlternate((void*)addr)) { + printf_log(LOG_DEBUG, "Jmp address has alternate: %p", (void*)addr); + if(box64_log<LOG_DEBUG) dynarec_log(LOG_INFO, "Jmp address has alternate: %p", (void*)addr); + uintptr_t old_addr = addr; + addr = (uintptr_t)getAlternate((void*)addr); // set new address + R_RIP = addr; // but also new RIP! + *x3 = addr; // and the RIP in x27 register + printf_log(LOG_DEBUG, " -> %p\n", (void*)addr); + block = DBAlternateBlock(emu, old_addr, addr, is32bits); + } else + block = DBGetBlock(emu, addr, 1, is32bits); if(!block) { - // no block, let link table as is... - if(hasAlternate((void*)addr)) { - printf_log(LOG_DEBUG, "Jmp address has alternate: %p", (void*)addr); - if(box64_log<LOG_DEBUG) dynarec_log(LOG_INFO, "Jmp address has alternate: %p", (void*)addr); - addr = (uintptr_t)getAlternate((void*)addr); // set new address - R_RIP = addr; // but also new RIP! - *x3 = addr; // and the RIP in x27 register - printf_log(LOG_DEBUG, " -> %p\n", (void*)addr); - block = DBGetBlock(emu, addr, 1); - } - if(!block) { - #ifdef HAVE_TRACE - if(LOG_INFO<=box64_dynarec_log) { - dynablock_t* db = FindDynablockFromNativeAddress(x2-4); - elfheader_t* h = FindElfAddress(my_context, (uintptr_t)x2-4); - dynarec_log(LOG_INFO, "Warning, jumping to a no-block address %p from %p (db=%p, x64addr=%p(elf=%s))\n", (void*)addr, x2-4, db, db?(void*)getX64Address(db, (uintptr_t)x2-4):NULL, h?ElfName(h):"(none)"); - } - #endif - //tableupdate(native_epilog, addr, table); - return native_epilog; + #ifdef HAVE_TRACE + if(LOG_INFO<=box64_dynarec_log) { + dynablock_t* db = FindDynablockFromNativeAddress(x2-4); + elfheader_t* h = FindElfAddress(my_context, (uintptr_t)x2-4); + dynarec_log(LOG_INFO, "Warning, jumping to a no-block address %p from %p (db=%p, x64addr=%p(elf=%s))\n", (void*)addr, x2-4, db, db?(void*)getX64Address(db, (uintptr_t)x2-4):NULL, h?ElfName(h):"(none)"); } + #endif + //tableupdate(native_epilog, addr, table); + return native_epilog; } if(!block->done) { // not finished yet... leave linker @@ -83,26 +81,21 @@ void* LinkNext(x64emu_t* emu, uintptr_t addr, void* x2, uintptr_t* x3) void DynaCall(x64emu_t* emu, uintptr_t addr) { // prepare setjump for signal handling - emu_jmpbuf_t *ejb = NULL; - int jmpbuf_reset = 0; - if(emu->type == EMUTYPE_MAIN) { - ejb = GetJmpBuf(); - if(!ejb->jmpbuf_ok) { - ejb->emu = emu; - ejb->jmpbuf_ok = 1; - jmpbuf_reset = 1; - if(sigsetjmp((struct __jmp_buf_tag*)ejb->jmpbuf, 1)) { - printf_log(LOG_DEBUG, "Setjmp DynaCall, fs=0x%x\n", ejb->emu->segs[_FS]); - addr = R_RIP; // not sure if it should still be inside DynaCall! - #ifdef DYNAREC - if(box64_dynarec_test) { - if(emu->test.clean) - x64test_check(emu, R_RIP); - emu->test.clean = 0; - } - #endif - } + struct __jmp_buf_tag jmpbuf[1] = {0}; + int skip = 0; + struct __jmp_buf_tag *old_jmpbuf = emu->jmpbuf; + emu->jmpbuf = jmpbuf; + + if((skip = sigsetjmp(emu->jmpbuf, 1))) { + printf_log(LOG_DEBUG, "Setjmp DynaCall, fs=0x%x\n", emu->segs[_FS]); + addr = R_RIP; // not sure if it should still be inside DynaCall! + #ifdef DYNAREC + if(box64_dynarec_test) { + if(emu->test.clean) + x64test_check(emu, R_RIP); + emu->test.clean = 0; } + #endif } #ifdef DYNAREC if(!box64_dynarec) @@ -120,8 +113,10 @@ void DynaCall(x64emu_t* emu, uintptr_t addr) R_RIP = addr; emu->df = d_none; while(!emu->quit) { - dynablock_t* block = DBGetBlock(emu, R_RIP, 1); + int is32bits = (emu->segs[_CS]==0x23); + dynablock_t* block = (skip)?NULL:DBGetBlock(emu, R_RIP, 1, is32bits); if(!block || !block->block || !block->done) { + skip = 0; // no block, of block doesn't have DynaRec content (yet, temp is not null) // Use interpreter (should use single instruction step...) dynarec_log(LOG_DEBUG, "%04d|Calling Interpreter @%p, emu=%p\n", GetTID(), (void*)R_RIP, emu); @@ -129,7 +124,7 @@ void DynaCall(x64emu_t* emu, uintptr_t addr) emu->test.clean = 0; Run(emu, 1); } else { - dynarec_log(LOG_DEBUG, "%04d|Calling DynaRec Block @%p (%p) of %d x64 instructions emu=%p\n", GetTID(), (void*)R_RIP, block->block, block->isize ,emu); + dynarec_log(LOG_DEBUG, "%04d|Calling DynaRec Block @%p (%p) of %d x64 instructions (hash=0x%x) emu=%p\n", GetTID(), (void*)R_RIP, block->block, block->isize ,block->hash, emu); CHECK_FLAGS(emu); // block is here, let's run it! native_prolog(emu, block->block); @@ -139,16 +134,6 @@ void DynaCall(x64emu_t* emu, uintptr_t addr) emu->quit = 0; emu->fork = 0; emu = x64emu_fork(emu, forktype); - if(emu->type == EMUTYPE_MAIN) { - ejb = GetJmpBuf(); - ejb->emu = emu; - ejb->jmpbuf_ok = 1; - jmpbuf_reset = 1; - if(sigsetjmp((struct __jmp_buf_tag*)ejb->jmpbuf, 1)) { - printf_log(LOG_DEBUG, "Setjmp inner DynaCall, fs=0x%x\n", ejb->emu->segs[_FS]); - addr = R_RIP; - } - } } } emu->quit = 0; // reset Quit flags... @@ -167,36 +152,28 @@ void DynaCall(x64emu_t* emu, uintptr_t addr) } #endif // clear the setjmp - if(ejb && jmpbuf_reset) - ejb->jmpbuf_ok = 0; + emu->jmpbuf = old_jmpbuf; } int DynaRun(x64emu_t* emu) { // prepare setjump for signal handling - emu_jmpbuf_t *ejb = NULL; -#ifdef DYNAREC - int jmpbuf_reset = 1; -#endif - if(emu->type == EMUTYPE_MAIN) { - ejb = GetJmpBuf(); - if(!ejb->jmpbuf_ok) { - ejb->emu = emu; - ejb->jmpbuf_ok = 1; -#ifdef DYNAREC - jmpbuf_reset = 1; -#endif - if(sigsetjmp((struct __jmp_buf_tag*)ejb->jmpbuf, 1)) - printf_log(LOG_DEBUG, "Setjmp DynaRun, fs=0x%x\n", ejb->emu->segs[_FS]); - #ifdef DYNAREC - if(box64_dynarec_test) { - if(emu->test.clean) - x64test_check(emu, R_RIP); - emu->test.clean = 0; - } - #endif + struct __jmp_buf_tag jmpbuf[1] = {0}; + int skip = 0; + struct __jmp_buf_tag *old_jmpbuf = emu->jmpbuf; + emu->jmpbuf = jmpbuf; + + if((skip=sigsetjmp(emu->jmpbuf, 1))) { + printf_log(LOG_DEBUG, "Setjmp DynaRun, fs=0x%x\n", emu->segs[_FS]); + #ifdef DYNAREC + if(box64_dynarec_test) { + if(emu->test.clean) + x64test_check(emu, R_RIP); + emu->test.clean = 0; } + #endif } + #ifdef DYNAREC if(!box64_dynarec) #endif @@ -204,8 +181,10 @@ int DynaRun(x64emu_t* emu) #ifdef DYNAREC else { while(!emu->quit) { - dynablock_t* block = DBGetBlock(emu, R_RIP, 1); + int is32bits = (emu->segs[_CS]==0x23); + dynablock_t* block = (skip)?NULL:DBGetBlock(emu, R_RIP, 1, is32bits); if(!block || !block->block || !block->done) { + skip = 0; // no block, of block doesn't have DynaRec content (yet, temp is not null) // Use interpreter (should use single instruction step...) dynarec_log(LOG_DEBUG, "%04d|Running Interpreter @%p, emu=%p\n", GetTID(), (void*)R_RIP, emu); @@ -213,7 +192,7 @@ int DynaRun(x64emu_t* emu) emu->test.clean = 0; Run(emu, 1); } else { - dynarec_log(LOG_DEBUG, "%04d|Running DynaRec Block @%p (%p) of %d x64 insts emu=%p\n", GetTID(), (void*)R_RIP, block->block, block->isize, emu); + dynarec_log(LOG_DEBUG, "%04d|Running DynaRec Block @%p (%p) of %d x64 insts (hash=0x%x) emu=%p\n", GetTID(), (void*)R_RIP, block->block, block->isize, block->hash, emu); // block is here, let's run it! native_prolog(emu, block->block); } @@ -222,20 +201,11 @@ int DynaRun(x64emu_t* emu) emu->quit = 0; emu->fork = 0; emu = x64emu_fork(emu, forktype); - if(emu->type == EMUTYPE_MAIN) { - ejb = GetJmpBuf(); - ejb->emu = emu; - ejb->jmpbuf_ok = 1; - jmpbuf_reset = 1; - if(sigsetjmp((struct __jmp_buf_tag*)ejb->jmpbuf, 1)) - printf_log(LOG_DEBUG, "Setjmp inner DynaRun, fs=0x%x\n", ejb->emu->segs[_FS]); - } } } } // clear the setjmp - if(ejb && jmpbuf_reset) - ejb->jmpbuf_ok = 0; + emu->jmpbuf = old_jmpbuf; return 0; #endif } |