diff options
Diffstat (limited to 'src')
23 files changed, 291 insertions, 34 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_00.c b/src/dynarec/arm64/dynarec_arm64_00.c index 2947ee42..75d963af 100644 --- a/src/dynarec/arm64/dynarec_arm64_00.c +++ b/src/dynarec/arm64/dynarec_arm64_00.c @@ -2626,7 +2626,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin INST_NAME("INT 3"); if(!BOX64ENV(ignoreint3)) { // check if TRAP signal is handled - TABLE64(x1, (uintptr_t)my_context); + TABLE64C(x1, const_context); MOV32w(x2, offsetof(box64context_t, signals[SIGTRAP])); LDRx_REG(x3, x1, x2); //LDRx_U12(x3, x1, offsetof(box64context_t, signals[SIGTRAP])); @@ -4129,7 +4129,8 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin // jumps out of current dynablock... MARK; j64 = getJumpTableAddress64(addr); - TABLE64(x4, j64); + if(dyn->need_reloc) AddRelocTable64RetEndBlock(dyn, ninst, addr, STEP); + TABLE64_(x4, j64); LDRx_U12(x4, x4, 0); BR(x4); } @@ -4148,24 +4149,6 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin LDH(x3, wback, rex.w?8:4); LDH(x4, xEmu, offsetof(x64emu_t, segs[_CS])); GETIP_(addr); - /* - if(BOX64DRENV(dynarec_callret)) { - SET_HASCALLRET(); - // Push actual return address - if(addr < (dyn->start+dyn->isize)) { - // there is a next... - j64 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->native_size)):0; - ADR_S20(x4, j64); - MESSAGE(LOG_NONE, "\tCALLRET set return to +%di\n", j64>>2); - } else { - MESSAGE(LOG_NONE, "\tCALLRET set return to Jmptable(%p)\n", (void*)addr); - j64 = getJumpTableAddress64(addr); - TABLE64(x4, j64); - LDRx_U12(x4, x4, 0); - } - STPx_S7_preindex(x4, xRIP, xSP, -16); - } - */ // not doing callret because call far will exit the dynablock anyway, to be sure to recompute CS segment PUSH1z(x4); PUSH1z(xRIP); diff --git a/src/dynarec/arm64/dynarec_arm64_64.c b/src/dynarec/arm64/dynarec_arm64_64.c index 73f0ee9a..de10a343 100644 --- a/src/dynarec/arm64/dynarec_arm64_64.c +++ b/src/dynarec/arm64/dynarec_arm64_64.c @@ -1647,6 +1647,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin // jumps out of current dynablock... MARK; j64 = getJumpTableAddress64(addr); + if(dyn->need_reloc) AddRelocTable64RetEndBlock(dyn, ninst, addr, STEP); TABLE64(x4, j64); LDRx_U12(x4, x4, 0); BR(x4); diff --git a/src/dynarec/arm64/dynarec_arm64_660f.c b/src/dynarec/arm64/dynarec_arm64_660f.c index d1581b5d..3acd6dfe 100644 --- a/src/dynarec/arm64/dynarec_arm64_660f.c +++ b/src/dynarec/arm64/dynarec_arm64_660f.c @@ -3038,7 +3038,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n q1 = fpu_get_scratch(dyn, ninst); GETEX(q0, 0, 0); GETGD; - TABLE64(x2, 0x0706050403020100LL); + TABLE64_(x2, 0x0706050403020100LL); VDUPQD(v0, x2); VSHRQ_8(q1, q0, 7); USHLQ_8(q1, q1, v0); // shift diff --git a/src/dynarec/arm64/dynarec_arm64_67.c b/src/dynarec/arm64/dynarec_arm64_67.c index b32433ad..f44cb687 100644 --- a/src/dynarec/arm64/dynarec_arm64_67.c +++ b/src/dynarec/arm64/dynarec_arm64_67.c @@ -1748,6 +1748,7 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin // jumps out of current dynablock... MARK; j64 = getJumpTableAddress64(addr); + if(dyn->need_reloc) AddRelocTable64RetEndBlock(dyn, ninst, addr, STEP); TABLE64(x4, j64); LDRx_U12(x4, x4, 0); BR(x4); diff --git a/src/dynarec/arm64/dynarec_arm64_avx_66_0f.c b/src/dynarec/arm64/dynarec_arm64_avx_66_0f.c index b5e1d362..54b9cecc 100644 --- a/src/dynarec/arm64/dynarec_arm64_avx_66_0f.c +++ b/src/dynarec/arm64/dynarec_arm64_avx_66_0f.c @@ -1459,7 +1459,7 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, q1 = fpu_get_scratch(dyn, ninst); GETEX_Y(q0, 0, 0); GETGD; - TABLE64(x2, 0x0706050403020100LL); + TABLE64_(x2, 0x0706050403020100LL); VDUPQD(v0, x2); VSHRQ_8(q1, q0, 7); USHLQ_8(q1, q1, v0); // shift diff --git a/src/dynarec/arm64/dynarec_arm64_avx_66_0f38.c b/src/dynarec/arm64/dynarec_arm64_avx_66_0f38.c index e65864bf..d83ac74c 100644 --- a/src/dynarec/arm64/dynarec_arm64_avx_66_0f38.c +++ b/src/dynarec/arm64/dynarec_arm64_avx_66_0f38.c @@ -1756,7 +1756,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip INST_NAME("VFMSUBADD231PS/D Gx, Vx, Ex"); nextop = F8; q0 = fpu_get_scratch(dyn, ninst); - TABLE64(x2, rex.w?const_2d_1_m1:const_4f_1_m1_1_m1); + TABLE64C(x2, rex.w?const_2d_1_m1:const_4f_1_m1_1_m1); VLDR128_U12(q0, x2, 0); for(int l=0; l<1+vex.l; ++l) { if(!l) { GETGX_VXEX(v0, v2, v1, 0); if(v0==v2 || v0==v1) q1 = fpu_get_scratch(dyn, ninst); } else { GETGY_VYEY(v0, v2, v1); } diff --git a/src/dynarec/arm64/dynarec_arm64_consts.c b/src/dynarec/arm64/dynarec_arm64_consts.c index f412099f..ce59c954 100644 --- a/src/dynarec/arm64/dynarec_arm64_consts.c +++ b/src/dynarec/arm64/dynarec_arm64_consts.c @@ -126,6 +126,7 @@ uintptr_t getConst(arm64_consts_t which) case const_jmptbl32: return getJumpTable32(); case const_jmptbl48: return getJumpTable48(); case const_jmptbl64: return getJumpTable64(); + case const_context: return (uintptr_t)my_context; case const_8b_m7_m6_m5_m4_m3_m2_m1_0: return (uintptr_t)&mask_shift8; case const_8b_7_6_5_4_3_2_1_0: return (uintptr_t)&mask_string8; case const_8b_15_14_13_12_11_10_9_8: return (uintptr_t)&mask_string16; diff --git a/src/dynarec/arm64/dynarec_arm64_consts.h b/src/dynarec/arm64/dynarec_arm64_consts.h index 2c14640b..71e2bdce 100644 --- a/src/dynarec/arm64/dynarec_arm64_consts.h +++ b/src/dynarec/arm64/dynarec_arm64_consts.h @@ -88,6 +88,7 @@ typedef enum arm64_consts_s { const_jmptbl32, const_jmptbl48, const_jmptbl64, + const_context, const_8b_m7_m6_m5_m4_m3_m2_m1_0, const_8b_7_6_5_4_3_2_1_0, const_8b_15_14_13_12_11_10_9_8, diff --git a/src/dynarec/arm64/dynarec_arm64_helper.c b/src/dynarec/arm64/dynarec_arm64_helper.c index 656ee7ad..d4817803 100644 --- a/src/dynarec/arm64/dynarec_arm64_helper.c +++ b/src/dynarec/arm64/dynarec_arm64_helper.c @@ -622,7 +622,8 @@ void jump_to_next(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst, int is32 NOTEST(x2); uintptr_t p = getJumpTableAddress64(ip); MAYUSE(p); - TABLE64(x3, p); + if(dyn->need_reloc) AddRelocTable64JmpTbl(dyn, ninst, ip, STEP); + TABLE64_(x3, p); GETIP_(ip); LDRx_U12(x2, x3, 0); dest = x2; diff --git a/src/dynarec/arm64/dynarec_arm64_helper.h b/src/dynarec/arm64/dynarec_arm64_helper.h index 50c1279a..8806777c 100644 --- a/src/dynarec/arm64/dynarec_arm64_helper.h +++ b/src/dynarec/arm64/dynarec_arm64_helper.h @@ -1208,6 +1208,9 @@ #ifndef TABLE64 #define TABLE64(A, V) #endif +#ifndef TABLE64_ +#define TABLE64_(A, V) +#endif #ifndef FTABLE64 #define FTABLE64(A, V) #endif @@ -1235,14 +1238,22 @@ } \ } else { \ dyn->last_ip = (A); \ - MOV64x(xRIP, dyn->last_ip); \ + if(dyn->need_reloc) { \ + TABLE64(xRIP, dyn->last_ip); \ + } else { \ + MOV64x(xRIP, dyn->last_ip); \ + } \ } #define GETIP_(A) \ if(dyn->last_ip && ((A)-dyn->last_ip)<0x1000) { \ uint64_t _delta_ip = (A)-dyn->last_ip; \ if(_delta_ip) {ADDx_U12(xRIP, xRIP, _delta_ip);}\ } else { \ - MOV64x(xRIP, (A)); \ + if(dyn->need_reloc) { \ + TABLE64(xRIP, (A)); \ + } else { \ + MOV64x(xRIP, (A)); \ + } \ } #endif #define CLEARIP() dyn->last_ip=0 diff --git a/src/dynarec/arm64/dynarec_arm64_pass2.h b/src/dynarec/arm64/dynarec_arm64_pass2.h index 02f596a9..6bedf76a 100644 --- a/src/dynarec/arm64/dynarec_arm64_pass2.h +++ b/src/dynarec/arm64/dynarec_arm64_pass2.h @@ -15,8 +15,19 @@ } #define INST_EPILOG dyn->insts[ninst].epilog = dyn->native_size; #define INST_NAME(name) -#define TABLE64(A, V) {Table64(dyn, (V), 2); EMIT(0);} -#define TABLE64C(A, V) {Table64(dyn, getConst(V), 2); EMIT(0);} +#define TABLE64(A, V) { \ + if(dyn->need_reloc && !isTable64(dyn, (V))) \ + AddRelocTable64Addr(dyn, ninst, (V), 2); \ + Table64(dyn, (V), 2); EMIT(0); \ + } +#define TABLE64_(A, V) { \ + Table64(dyn, (V), 2); EMIT(0); \ + } +#define TABLE64C(A, V) { \ + if(dyn->need_reloc && !isTable64(dyn, getConst(V))) \ + AddRelocTable64Const(dyn, ninst, (V), 2); \ + Table64(dyn, getConst(V), 2); EMIT(0); \ + } #define FTABLE64(A, V) {mmx87_regs_t v = {.d = V}; Table64(dyn, v.q, 2); EMIT(0);} #define CALLRET_RET() do {dyn->callrets[dyn->callret_size].type = 0; dyn->callrets[dyn->callret_size++].offs = dyn->native_size; EMIT(ARCH_NOP); } while(0) #define CALLRET_LOOP() do {dyn->callrets[dyn->callret_size].type = 1; dyn->callrets[dyn->callret_size++].offs = dyn->native_size; EMIT(ARCH_NOP); } while(0) \ No newline at end of file diff --git a/src/dynarec/arm64/dynarec_arm64_pass3.h b/src/dynarec/arm64/dynarec_arm64_pass3.h index 73f0babf..5930c410 100644 --- a/src/dynarec/arm64/dynarec_arm64_pass3.h +++ b/src/dynarec/arm64/dynarec_arm64_pass3.h @@ -24,8 +24,22 @@ } #define INST_EPILOG #define INST_NAME(name) inst_name_pass3(dyn, ninst, name, rex) -#define TABLE64(A, V) {int val64offset = Table64(dyn, (V), 3); MESSAGE(LOG_DUMP, " Table64: 0x%lx\n", (V)); LDRx_literal(A, val64offset);} -#define TABLE64C(A, V) {int val64offset = Table64(dyn, getConst(V), 3); MESSAGE(LOG_DUMP, " Table64: 0x%lx\n", (V)); LDRx_literal(A, val64offset);} +#define TABLE64(A, V) { \ + if(dyn->need_reloc && !isTable64(dyn, (V))) \ + AddRelocTable64Addr(dyn, ninst, (V), 3); \ + int val64offset = Table64(dyn, (V), 3); \ + MESSAGE(LOG_DUMP, " Table64: 0x%lx\n", (V)); LDRx_literal(A, val64offset); \ + } +#define TABLE64_(A, V) { \ + int val64offset = Table64(dyn, (V), 3); \ + MESSAGE(LOG_DUMP, " Table64: 0x%lx\n", (V)); LDRx_literal(A, val64offset); \ + } +#define TABLE64C(A, V) { \ + if(dyn->need_reloc && !isTable64(dyn, getConst(V))) \ + AddRelocTable64Const(dyn, ninst, (V), 3); \ + int val64offset = Table64(dyn, getConst(V), 3); \ + MESSAGE(LOG_DUMP, " Table64: 0x%lx\n", (V)); LDRx_literal(A, val64offset); \ + } #define FTABLE64(A, V) {mmx87_regs_t v = {.d = V}; int val64offset = Table64(dyn, v.q, 3); MESSAGE(LOG_DUMP, " FTable64: %g\n", v.d); VLDR64_literal(A, val64offset);} #define CALLRET_RET() do {dyn->callrets[dyn->callret_size].type = 0; dyn->callrets[dyn->callret_size++].offs = dyn->native_size; EMIT(ARCH_NOP); } while(0) #define CALLRET_LOOP() do {dyn->callrets[dyn->callret_size].type = 1; dyn->callrets[dyn->callret_size++].offs = dyn->native_size; EMIT(ARCH_NOP); } while(0) diff --git a/src/dynarec/arm64/dynarec_arm64_private.h b/src/dynarec/arm64/dynarec_arm64_private.h index ca249949..b3eeed49 100644 --- a/src/dynarec/arm64/dynarec_arm64_private.h +++ b/src/dynarec/arm64/dynarec_arm64_private.h @@ -180,6 +180,9 @@ typedef struct dynarec_arm_s { void* gdbjit_block; uint32_t need_x87check; // needs x87 precision control check if non-null, or 0 if not uint32_t need_dump; // need to dump the block + int need_reloc; // does the dynablock need relocations + int reloc_size; + uint32_t* relocs; } dynarec_arm_t; void add_next(dynarec_arm_t *dyn, uintptr_t addr); @@ -190,6 +193,7 @@ int get_first_jump_addr(dynarec_arm_t *dyn, uintptr_t next); int is_nops(dynarec_arm_t *dyn, uintptr_t addr, int n); int is_instructions(dynarec_arm_t *dyn, uintptr_t addr, int n); +int isTable64(dynarec_arm_t *dyn, uint64_t val); // return 1 if val already in Table64 int Table64(dynarec_arm_t *dyn, uint64_t val, int pass); // add a value to table64 (if needed) and gives back the imm19 to use in LDR_literal void CreateJmpNext(void* addr, void* next); diff --git a/src/dynarec/dynablock_private.h b/src/dynarec/dynablock_private.h index 8220be0c..f78d457c 100644 --- a/src/dynarec/dynablock_private.h +++ b/src/dynarec/dynablock_private.h @@ -31,6 +31,7 @@ typedef struct dynablock_s { void* arch; // arch dependant per inst info (can be NULL) callret_t* callrets; // array of callret return, with NOP / UDF depending if the block is clean or dirty void* jmpnext; // a branch jmpnext code when block is marked + void* relocs; // relocations, when block is loaded #ifdef GDBJIT void* gdbjit_block; #endif diff --git a/src/dynarec/dynacache_reloc.c b/src/dynarec/dynacache_reloc.c new file mode 100644 index 00000000..7692e007 --- /dev/null +++ b/src/dynarec/dynacache_reloc.c @@ -0,0 +1,162 @@ +#include <stdint.h> +#include <string.h> + +#include "os.h" +#include "dynarec_private.h" +#include "emu/x64run_private.h" +#include "dynarec_arch.h" +#include "custommem.h" +#include "debug.h" + +#define RELOC_TBL64C 1 +#define RELOC_TBL64ADDR 2 +#define RELOC_TBL64RETENDBL 3 +#define RELOC_CANCELBLOCK 4 +#define RELOC_TBL64TBLJMPH 5 +#define RELOC_TBL64TBLJMPL 5 + +typedef union reloc_s { + uint8_t type; + struct { + uint8_t type; + uint8_t C; + uint16_t idx; + } table64c; + struct { + uint8_t type; + uint8_t nothing; + uint16_t idx; + } table64addr; + struct { + uint8_t type; + uint8_t delta; + uint16_t idx; + } table64retendbl; + struct { + uint8_t type; + uint8_t deltah; + uint16_t idx; + } table64jmptblh; + struct { + uint32_t type:8; + uint32_t deltal:24; + } table64jmptbll; + uint32_t x; +} reloc_t; + +void AddRelocTable64Const(dynarec_native_t* dyn, int ninst, native_consts_t C, int pass) +{ + if(!dyn->need_reloc) + return; + if(pass<3) { + dyn->reloc_size++; + return; + } + // generating the reloc + reloc_t reloc = {0}; + reloc.table64c.type = RELOC_TBL64C; + reloc.table64c.C = C; + reloc.table64c.idx = dyn->table64size; + dyn->relocs[dyn->reloc_size++] = reloc.x; +} + +void AddRelocTable64RetEndBlock(dynarec_native_t* dyn, int ninst, uintptr_t addr, int pass) +{ + if(!dyn->need_reloc) + return; + if(isTable64(dyn, getJumpTableAddress64(addr))) + return; // no need, already handled + // TODO: check iif addr is in current map + if(pass<3) { + dyn->reloc_size++; + return; + } + reloc_t reloc = {0}; + intptr_t delta = addr-(dyn->start + dyn->isize); + if(delta>255 || delta<0) { + dynarec_log(LOG_INFO, "Warning Relocation Ret End Block not possible: delta=%lld, aborting block\n", delta); + dyn->abort = 1; + } + reloc.table64retendbl.type = RELOC_TBL64RETENDBL; + reloc.table64retendbl.delta = delta; + reloc.table64retendbl.idx = dyn->table64size; + dyn->relocs[dyn->reloc_size++] = reloc.x; +} + +void AddRelocCancelBlock(dynarec_native_t* dyn, int ninst, int pass) +{ + if(!dyn->need_reloc) + return; + if(pass<3) { + dyn->reloc_size++; + return; + } + reloc_t reloc = {0}; + reloc.type = RELOC_CANCELBLOCK; + dyn->relocs[dyn->reloc_size++] = reloc.x; +} + +void AddRelocTable64Addr(dynarec_native_t* dyn, int ninst, uintptr_t addr, int pass) +{ + if(!dyn->need_reloc) + return; + if(isTable64(dyn, addr)) + return; // no need, already handled + // check if addr is in the same mmap area + // else, use a cancel block instead + uintptr_t start; + int ok = 1; + if(!IsAddrFileMapped(dyn->start, NULL, &start)) + ok = 0; + else { + uintptr_t end = start + SizeFileMapped(dyn->start); + if(addr<start || addr>=end) + ok = 0; + if(ok && ((addr-start)>=0x100000000LL)) + ok = 0; + } + if(!ok) return AddRelocCancelBlock(dyn, ninst, pass); + if(pass<3) { + dyn->reloc_size+=2; + return; + } + reloc_t reloc = {0}; + reloc.type = RELOC_TBL64ADDR; + reloc.table64addr.idx = dyn->table64size; +} + + +void AddRelocTable64JmpTbl(dynarec_native_t* dyn, int ninst, uintptr_t addr, int pass) +{ + if(!dyn->need_reloc) + return; + if(isTable64(dyn, getJumpTableAddress64(addr))) + return; // no need, already handled + // check if addr is in the same mmap area + // else, use a cancel block instead + uintptr_t start; + int ok = 1; + if(!IsAddrFileMapped(dyn->start, NULL, &start)) + ok = 0; + else { + uintptr_t end = start + SizeFileMapped(dyn->start); + if(addr<start || addr>=end) + ok = 0; + if(ok && ((addr-start)>=0x100000000LL)) + ok = 0; + } + if(!ok) return AddRelocCancelBlock(dyn, ninst, pass); + if(pass<3) { + dyn->reloc_size+=2; + return; + } + uintptr_t delta = addr - start; + reloc_t reloc = {0}; + reloc.type = RELOC_TBL64TBLJMPH; + reloc.table64jmptblh.idx = dyn->table64size; + reloc.table64jmptblh.deltah = delta>>24; + dyn->relocs[dyn->reloc_size++] = reloc.x; + reloc.type = RELOC_TBL64TBLJMPL; + reloc.table64jmptbll.deltal = delta&0xffffff; + dyn->relocs[dyn->reloc_size++] = reloc.x; +} \ No newline at end of file diff --git a/src/dynarec/dynacache_reloc.h b/src/dynarec/dynacache_reloc.h new file mode 100644 index 00000000..fed00562 --- /dev/null +++ b/src/dynarec/dynacache_reloc.h @@ -0,0 +1,20 @@ +#ifndef __DYNACACHE_RELOC_H__ +#define __DYNACACHE_RELOC_H__ + +#ifdef ARM64 +#include "dynarec/arm64/dynarec_arm64_consts.h" +#define native_consts_t arm64_consts_t +#else +typedef enum native_consts_s { + const_none, + const_last +} native_consts_t; +#endif + +void AddRelocTable64Const(dynarec_native_t* dyn, int ninst, native_consts_t C, int pass); +void AddRelocTable64Addr(dynarec_native_t* dyn, int ninst, uintptr_t addr, int pass); +void AddRelocTable64RetEndBlock(dynarec_native_t* dyn, int ninst, uintptr_t addr, int pass); +void AddRelocTable64JmpTbl(dynarec_native_t* dyn, int ninst, uintptr_t addr, int pass); +void AddRelocCancelBlock(dynarec_native_t* dyn, int ninst, int pass); + +#endif \ No newline at end of file diff --git a/src/dynarec/dynarec_arch.h b/src/dynarec/dynarec_arch.h index 74d8a6f1..5424c447 100644 --- a/src/dynarec/dynarec_arch.h +++ b/src/dynarec/dynarec_arch.h @@ -103,4 +103,6 @@ extern uint32_t arm64_crc(void* p, uint32_t len); #error Unsupported platform #endif +#include "dynacache_reloc.h" + #endif //__DYNAREC_ARCH__H_ diff --git a/src/dynarec/dynarec_native.c b/src/dynarec/dynarec_native.c index 65868435..6d777805 100644 --- a/src/dynarec/dynarec_native.c +++ b/src/dynarec/dynarec_native.c @@ -293,6 +293,15 @@ void addInst(instsize_t* insts, size_t* size, int x64_size, int native_size) } } +int isTable64(dynarec_native_t *dyn, uint64_t val) +{ + // find the value if already present + int idx = -1; + for(int i=0; i<dyn->table64size && (idx==-1); ++i) + if(dyn->table64[i] == val) + idx = i; + return (idx!=-1); +} // add a value to table64 (if needed) and gives back the imm19 to use in LDR_literal int Table64(dynarec_native_t *dyn, uint64_t val, int pass) { @@ -636,6 +645,7 @@ dynablock_t* FillBlock64(uintptr_t addr, int alternate, int is32bits, int inst_m helper.end = addr + SizeFileMapped(addr); if(helper.end == helper.start) // that means there is no mmap with a file associated to the memory helper.end = (uintptr_t)~0LL; + helper.need_reloc = IsAddrNeedReloc(addr); // pass 0, addresses, x64 jump addresses, overall size of the block uintptr_t end = native_pass0(&helper, addr, alternate, is32bits, inst_max); if(helper.abort) { @@ -771,6 +781,7 @@ dynablock_t* FillBlock64(uintptr_t addr, int alternate, int is32bits, int inst_m helper.next_sz = helper.next_cap = 0; helper.next = NULL; helper.table64size = 0; + helper.reloc_size = 0; // pass 1, float optimizations, first pass for flags native_pass1(&helper, addr, alternate, is32bits, inst_max); if(helper.abort) { @@ -784,6 +795,7 @@ dynablock_t* FillBlock64(uintptr_t addr, int alternate, int is32bits, int inst_m } POSTUPDATE_SPECIFICS(&helper); helper.table64size = 0; + helper.reloc_size = 0; // pass 2, instruction size helper.callrets = static_callrets; native_pass2(&helper, addr, alternate, is32bits, inst_max); @@ -812,9 +824,10 @@ dynablock_t* FillBlock64(uintptr_t addr, int alternate, int is32bits, int inst_m insts_rsize = (insts_rsize+7)&~7; // round the size... size_t arch_size = ARCH_SIZE(&helper); size_t callret_size = helper.callret_size*sizeof(callret_t); + size_t reloc_size = helper.reloc_size*sizeof(uint32_t); // ok, now allocate mapped memory, with executable flag on - size_t sz = sizeof(void*) + native_size + helper.table64size*sizeof(uint64_t) + 4*sizeof(void*) + insts_rsize + arch_size + callret_size + sizeof(dynablock_t); - // dynablock_t* block (arm insts) table64 jmpnext code instsize arch callrets dynablock + size_t sz = sizeof(void*) + native_size + helper.table64size*sizeof(uint64_t) + 4*sizeof(void*) + insts_rsize + arch_size + callret_size + sizeof(dynablock_t) + reloc_size; + // dynablock_t* block (arm insts) table64 jmpnext code instsize arch callrets dynablock relocs void* actual_p = (void*)AllocDynarecMap(addr, sz); void* p = (void*)(((uintptr_t)actual_p) + sizeof(void*)); void* tablestart = p + native_size; @@ -830,10 +843,13 @@ dynablock_t* FillBlock64(uintptr_t addr, int alternate, int is32bits, int inst_m helper.block = p; dynablock_t* block = (dynablock_t*)(callrets+callret_size); memset(block, 0, sizeof(dynablock_t)); + void* relocs = helper.need_reloc?(block+1):NULL; // fill the block block->x64_addr = (void*)addr; block->isize = 0; block->actual_block = actual_p; + helper.relocs = relocs; + block->relocs = relocs; helper.native_start = (uintptr_t)p; helper.tablestart = (uintptr_t)tablestart; helper.jmp_next = (uintptr_t)next+sizeof(void*); @@ -861,6 +877,7 @@ dynablock_t* FillBlock64(uintptr_t addr, int alternate, int is32bits, int inst_m helper.native_size = 0; helper.table64size = 0; // reset table64 (but not the cap) helper.insts_size = 0; // reset + helper.reloc_size = 0; native_pass3(&helper, addr, alternate, is32bits, inst_max); if(helper.abort) { if(dyn->need_dump || BOX64ENV(dynarec_log))dynarec_log(LOG_NONE, "Abort dynablock on pass3\n"); diff --git a/src/dynarec/la64/dynarec_la64_private.h b/src/dynarec/la64/dynarec_la64_private.h index a6250d09..0275218b 100644 --- a/src/dynarec/la64/dynarec_la64_private.h +++ b/src/dynarec/la64/dynarec_la64_private.h @@ -152,6 +152,9 @@ typedef struct dynarec_la64_s { void* gdbjit_block; uint32_t need_x87check; // x87 low precision check uint32_t need_dump; // need to dump the block + int need_reloc; // does the dynablock need relocations + int reloc_size; + uint32_t* relocs; } dynarec_la64_t; void add_next(dynarec_la64_t *dyn, uintptr_t addr); @@ -162,6 +165,7 @@ int get_first_jump_addr(dynarec_la64_t *dyn, uintptr_t next); int is_nops(dynarec_la64_t *dyn, uintptr_t addr, int n); int is_instructions(dynarec_la64_t *dyn, uintptr_t addr, int n); +int isTable64(dynarec_la64_t *dyn, uint64_t val); // return 1 if val already in Table64 int Table64(dynarec_la64_t *dyn, uint64_t val, int pass); // add a value to table64 (if needed) and gives back the imm19 to use in LDR_literal void CreateJmpNext(void* addr, void* next); diff --git a/src/dynarec/rv64/dynarec_rv64_private.h b/src/dynarec/rv64/dynarec_rv64_private.h index f8006a6a..534227b4 100644 --- a/src/dynarec/rv64/dynarec_rv64_private.h +++ b/src/dynarec/rv64/dynarec_rv64_private.h @@ -195,6 +195,9 @@ typedef struct dynarec_rv64_s { void* gdbjit_block; uint32_t need_x87check; // x87 low precision check uint32_t need_dump; // need to dump the block + int need_reloc; // does the dynablock need relocations + int reloc_size; + uint32_t* relocs; } dynarec_rv64_t; // v0 is hardware wired to vector mask register, which should be always reserved @@ -211,6 +214,7 @@ int get_first_jump_addr(dynarec_rv64_t *dyn, uintptr_t next); int is_nops(dynarec_rv64_t *dyn, uintptr_t addr, int n); int is_instructions(dynarec_rv64_t *dyn, uintptr_t addr, int n); +int isTable64(dynarec_rv64_t *dyn, uint64_t val); // return 1 if val already in Table64 int Table64(dynarec_rv64_t *dyn, uint64_t val, int pass); // add a value to table64 (if needed) and gives back the imm19 to use in LDR_literal void CreateJmpNext(void* addr, void* next); diff --git a/src/include/env.h b/src/include/env.h index 75eb0982..1c640091 100644 --- a/src/include/env.h +++ b/src/include/env.h @@ -125,7 +125,8 @@ extern char* ftrace_name; BOOLEAN(BOX64_X11GLX, x11glx, 1, 0) \ BOOLEAN(BOX64_X11SYNC, x11sync, 0, 0) \ BOOLEAN(BOX64_X11THREADS, x11threads, 0, 0) \ - BOOLEAN(BOX64_X87_NO80BITS, x87_no80bits, 0, 1) + BOOLEAN(BOX64_X87_NO80BITS, x87_no80bits, 0, 1) \ + BOOLEAN(BOX64_DYNACACHE, dynacache, 0, 0) \ #ifdef ARM64 #define ENVSUPER2() \ @@ -207,5 +208,6 @@ box64env_t* GetCurEnvByAddr(uintptr_t addr); int IsAddrFileMapped(uintptr_t addr, const char** filename, uintptr_t* start); size_t SizeFileMapped(uintptr_t addr); mmaplist_t* GetMmaplistByAddr(uintptr_t addr); +int IsAddrNeedReloc(uintptr_t addr); #endif // __ENV_H diff --git a/src/tools/env.c b/src/tools/env.c index cd4adb70..b279a988 100644 --- a/src/tools/env.c +++ b/src/tools/env.c @@ -807,3 +807,21 @@ size_t SizeFileMapped(uintptr_t addr) } return 0; } + +int IsAddrNeedReloc(uintptr_t addr) +{ + box64env_t* env = GetCurEnvByAddr(addr); + if(env->nodynarec) + return 0; + if(!env->dynacache) + return 0; + if(env->nodynarec_end && addr>=env->nodynarec_start && addr<env->nodynarec_end) + return 0; + #ifdef HAVE_TRACE + if(env->dynarec_test_end && addr>=env->dynarec_test_start && addr<env->dynarec_test_end) + return 0; + if(env->dynarec_trace && trace_end && addr>=trace_start && addr<trace_end) + return 0; + #endif + return 1; +} \ No newline at end of file diff --git a/src/wrapped/generated/functions_list.txt b/src/wrapped/generated/functions_list.txt index 82b573e2..bf306cfa 100644 --- a/src/wrapped/generated/functions_list.txt +++ b/src/wrapped/generated/functions_list.txt @@ -3506,7 +3506,6 @@ #() iFEpuvvppp -> iFEpuppp wrappedalure: wrappedalut: -wrappedandroidshmem: wrappedanl: wrappedatk: - vFp: |