diff options
Diffstat (limited to 'src/dynarec/dynacache_reloc.c')
| -rw-r--r-- | src/dynarec/dynacache_reloc.c | 84 |
1 files changed, 82 insertions, 2 deletions
diff --git a/src/dynarec/dynacache_reloc.c b/src/dynarec/dynacache_reloc.c index 7692e007..b145629e 100644 --- a/src/dynarec/dynacache_reloc.c +++ b/src/dynarec/dynacache_reloc.c @@ -4,6 +4,7 @@ #include "os.h" #include "dynarec_private.h" #include "emu/x64run_private.h" +#include "dynablock_private.h" #include "dynarec_arch.h" #include "custommem.h" #include "debug.h" @@ -13,7 +14,7 @@ #define RELOC_TBL64RETENDBL 3 #define RELOC_CANCELBLOCK 4 #define RELOC_TBL64TBLJMPH 5 -#define RELOC_TBL64TBLJMPL 5 +#define RELOC_TBL64TBLJMPL 6 typedef union reloc_s { uint8_t type; @@ -48,6 +49,8 @@ void AddRelocTable64Const(dynarec_native_t* dyn, int ninst, native_consts_t C, i { if(!dyn->need_reloc) return; + if(isTable64(dyn, getConst(C))) + return; if(pass<3) { dyn->reloc_size++; return; @@ -117,12 +120,13 @@ void AddRelocTable64Addr(dynarec_native_t* dyn, int ninst, uintptr_t addr, int p } if(!ok) return AddRelocCancelBlock(dyn, ninst, pass); if(pass<3) { - dyn->reloc_size+=2; + dyn->reloc_size++; return; } reloc_t reloc = {0}; reloc.type = RELOC_TBL64ADDR; reloc.table64addr.idx = dyn->table64size; + dyn->relocs[dyn->reloc_size++] = reloc.x; } @@ -159,4 +163,80 @@ void AddRelocTable64JmpTbl(dynarec_native_t* dyn, int ninst, uintptr_t addr, int reloc.type = RELOC_TBL64TBLJMPL; reloc.table64jmptbll.deltal = delta&0xffffff; dyn->relocs[dyn->reloc_size++] = reloc.x; +} + +int ApplyRelocs(dynablock_t* block, intptr_t delta_block, intptr_t delta_map, uintptr_t mapping_start) +{ + if(!block || !block->relocs || !block->relocsize) + return 0; + size_t reloc_size = block->relocsize / sizeof(uint32_t); + reloc_t *relocs = block->relocs; + uint64_t *table64 = block->table64; + int idx; + + int i = 0; + uintptr_t addr; + dynarec_log(LOG_DEBUG, "Will apply %zd reloc to dynablock starting at %p - %p\n", reloc_size, block->x64_addr, block->x64_addr + block->x64_size); + while(i<reloc_size) { + idx = -1; + switch(relocs[i].type) { + case RELOC_TBL64C: + idx = relocs[i].table64c.idx; + table64[idx] = getConst(relocs[i].table64c.C); + dynarec_log(LOG_DEBUG, "\tApply Relocs[%d]: TABLE64[%d]=Const:%d\n", i, idx, relocs[i].table64c.C); + break; + case RELOC_TBL64ADDR: + idx = relocs[i].table64addr.idx; + table64[idx] += delta_map; + dynarec_log(LOG_DEBUG, "\tApply Relocs[%d]: TABLE64[%d]=Addr in Map, delta=%zd\n", i, idx, delta_map); + break; + case RELOC_TBL64RETENDBL: + idx = relocs[i].table64retendbl.idx; + addr = (uintptr_t)block->x64_addr + block->x64_size + relocs[i].table64retendbl.delta; + table64[idx] = getJumpTableAddress64(addr); + dynarec_log(LOG_DEBUG, "\tApply Relocs[%d]: TABLE64[%d]=JmpTable64(%p)\n", i, idx, (void*)addr); + break; + case RELOC_CANCELBLOCK: + dynarec_log(LOG_DEBUG, "\tApply Relocs[%d]: Cancel Block\n", i); + block->dirty = 1; + block->hash = 0; + return 0; + case RELOC_TBL64TBLJMPH: + if(relocs[i+1].type!=RELOC_TBL64TBLJMPL) + return -2; // bad sequence + idx = relocs[i].table64jmptblh.idx; + addr = relocs[i].table64jmptblh.deltah; + addr = mapping_start + relocs[i+1].table64jmptbll.deltal + (addr<<24); + table64[idx] = getJumpTableAddress64(addr); + dynarec_log(LOG_DEBUG, "\tApply Relocs[%d,%d]: TABLE64[%d]=JmpTable64(%p)=%p\n", i, i+1, idx, (void*)addr, getJumpTableAddress64(addr)); + break; + case RELOC_TBL64TBLJMPL: + break; + default: + dynarec_log(LOG_DEBUG, "\tUnknown Relocs[%d]: %d\n", i, relocs[i].type); + return -1; + } + if(idx!=-1) { + if(idx>=block->table64size) { + dynarec_log(LOG_NONE, "Warning: Reloc Table64 idx out of range (%d vs %d)\n", idx, block->table64size); + } + } + ++i; + } + return 0; +} + +int RelocsHaveCancel(dynablock_t* block) +{ + if(!block->relocs || !block->relocsize) + return 0; + size_t reloc_size = block->relocsize/sizeof(uint32_t); + for(size_t i=0; i<reloc_size; ++i) + if(((reloc_t*)block->relocs)[i].type == RELOC_CANCELBLOCK) + return 1; + return 0; +} + +uintptr_t RelocGetNext() { + return getConst(const_native_next); } \ No newline at end of file |