diff options
| author | Yang Liu <liuyang22@iscas.ac.cn> | 2025-06-10 18:18:35 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-06-10 12:18:35 +0200 |
| commit | bfd0e1700b62123a77151a43cb852a8b68b6def7 (patch) | |
| tree | 5ad50dc4bda2b7275104b1a57591466880f2e353 | |
| parent | 0ae608373075a7cf28fd7eac70c557ca8903f516 (diff) | |
| download | box64-bfd0e1700b62123a77151a43cb852a8b68b6def7.tar.gz box64-bfd0e1700b62123a77151a43cb852a8b68b6def7.zip | |
[DYNAREC] Sync indirect lookup handling and some cleanup (#2722)
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_helper.c | 165 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_helper.c | 93 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_helper.c | 221 |
3 files changed, 151 insertions, 328 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_helper.c b/src/dynarec/arm64/dynarec_arm64_helper.c index 088129e7..9a5dab3c 100644 --- a/src/dynarec/arm64/dynarec_arm64_helper.c +++ b/src/dynarec/arm64/dynarec_arm64_helper.c @@ -565,53 +565,61 @@ void jump_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst) BR(x2); } + +static int indirect_lookup(dynarec_arm_t* dyn, int ninst, int is32bits, int s1, int s2) +{ + MAYUSE(dyn); + + if (!is32bits) { + // check higher 48bits + LSRx_IMM(s1, xRIP, 48); + CBNZw(s1, (intptr_t)dyn->jmp_next - (intptr_t)dyn->block); + // load table + uintptr_t tbl = getJumpTable48(); // this is a static value, so will be a low address + MOV64x(s2, tbl); + #ifdef JMPTABL_SHIFT4 + UBFXx(s1, xRIP, JMPTABL_START3, JMPTABL_SHIFT3); + LDRx_REG_LSL3(s2, s2, s1); + #endif + UBFXx(s1, xRIP, JMPTABL_START2, JMPTABL_SHIFT2); + LDRx_REG_LSL3(s2, s2, s1); + } else { + // check higher 32bits disabled + // LSRx_IMM(s1, xRIP, 32); + // CBNZw(s1, (intptr_t)dyn->jmp_next - (intptr_t)dyn->block); + // load table + uintptr_t tbl = getJumpTable32(); // this will not be a low address + TABLE64(s2, tbl); + #ifdef JMPTABL_SHIFT4 + UBFXx(s1, xRIP, JMPTABL_START2, JMPTABL_SHIFT2); + LDRx_REG_LSL3(s2, s2, s1); + #endif + } + UBFXx(s1, xRIP, JMPTABL_START1, JMPTABL_SHIFT1); + LDRx_REG_LSL3(s2, s2, s1); + UBFXx(s1, xRIP, JMPTABL_START0, JMPTABL_SHIFT0); + LDRx_REG_LSL3(s1, s2, s1); + return s1; +} + void jump_to_next(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst, int is32bits) { - MAYUSE(dyn); MAYUSE(ninst); + MAYUSE(dyn); + MAYUSE(ninst); MESSAGE(LOG_DUMP, "Jump to next\n"); - if(is32bits) + if (is32bits) ip &= 0xffffffffLL; SMEND(); - if(reg) { - if(reg!=xRIP) { + + int dest; + if (reg) { + if (reg != xRIP) { MOVx_REG(xRIP, reg); } NOTEST(x2); - if(!is32bits) { - // check higher 48bits - LSRx_IMM(x2, xRIP, 48); - CBNZw(x2, (intptr_t)dyn->jmp_next - (intptr_t)dyn->block); - // load table - uintptr_t tbl = getJumpTable48(); // this is a static value, so will be a low address - MOV64x(x3, tbl); - #ifdef JMPTABL_SHIFT4 - UBFXx(x2, xRIP, JMPTABL_START3, JMPTABL_SHIFT3); - LDRx_REG_LSL3(x3, x3, x2); - #endif - UBFXx(x2, xRIP, JMPTABL_START2, JMPTABL_SHIFT2); - LDRx_REG_LSL3(x3, x3, x2); - UBFXx(x2, xRIP, JMPTABL_START1, JMPTABL_SHIFT1); - LDRx_REG_LSL3(x3, x3, x2); - UBFXx(x2, xRIP, JMPTABL_START0, JMPTABL_SHIFT0); - LDRx_REG_LSL3(x2, x3, x2); - } else { - // check higher 32bits disabled - //LSRx_IMM(x2, xRIP, 32); - //CBNZw(x2, (intptr_t)dyn->jmp_next - (intptr_t)dyn->block); - // load table - uintptr_t tbl = getJumpTable32(); // this will not be a low address - TABLE64(x3, tbl); - #ifdef JMPTABL_SHIFT4 - UBFXx(x2, xRIP, JMPTABL_START2, JMPTABL_SHIFT2); - LDRx_REG_LSL3(x3, x3, x2); - #endif - UBFXx(x2, xRIP, JMPTABL_START1, JMPTABL_SHIFT1); - LDRx_REG_LSL3(x3, x3, x2); - UBFXx(x2, xRIP, JMPTABL_START0, JMPTABL_SHIFT0); - LDRx_REG_LSL3(x2, x3, x2); - } + dest = indirect_lookup(dyn, ninst, is32bits, x2, x3); } else { NOTEST(x2); uintptr_t p = getJumpTableAddress64(ip); @@ -619,6 +627,7 @@ void jump_to_next(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst, int is32 MOV64x(x3, p); GETIP_(ip); LDRx_U12(x2, x3, 0); + dest = x2; } if(reg!=x1) { MOVx_REG(x1, xRIP); @@ -626,12 +635,12 @@ void jump_to_next(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst, int is32 CLEARIP(); #ifdef HAVE_TRACE //MOVx(x3, 15); no access to PC reg - BLR(x2); // save LR... + BLR(dest); // save LR... #else if (dyn->insts[ninst].x64.has_callret) { - BLR(x2); // save LR... + BLR(dest); // save LR... } else { - BR(x2); + BR(dest); } #endif } @@ -653,43 +662,11 @@ void ret_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int ninst, rex_t rex) SUBx_U12(xSP, xSavedSP, 16); } NOTEST(x2); - if(!rex.is32bits) { - // check higher 48bits - LSRx_IMM(x2, xRIP, 48); - CBNZw(x2, (intptr_t)dyn->jmp_next - (intptr_t)dyn->block); - // load table - uintptr_t tbl = getJumpTable48(); - MOV64x(x3, tbl); - #ifdef JMPTABL_SHIFT4 - UBFXx(x2, xRIP, JMPTABL_START3, JMPTABL_SHIFT3); - LDRx_REG_LSL3(x3, x3, x2); - #endif - UBFXx(x2, xRIP, JMPTABL_START2, JMPTABL_SHIFT2); - LDRx_REG_LSL3(x3, x3, x2); - UBFXx(x2, xRIP, JMPTABL_START1, JMPTABL_SHIFT1); - LDRx_REG_LSL3(x3, x3, x2); - UBFXx(x2, xRIP, JMPTABL_START0, JMPTABL_SHIFT0); - LDRx_REG_LSL3(x2, x3, x2); - } else { - // check higher 32bits disabled - //LSRx_IMM(x2, xRIP, 32); - //CBNZw(x2, (intptr_t)dyn->jmp_next - (intptr_t)dyn->block); - // load table - uintptr_t tbl = getJumpTable32(); - TABLE64(x3, tbl); - #ifdef JMPTABL_SHIFT4 - UBFXx(x2, xRIP, JMPTABL_START2, JMPTABL_SHIFT2); - LDRx_REG_LSL3(x3, x3, x2); - #endif - UBFXx(x2, xRIP, JMPTABL_START1, JMPTABL_SHIFT1); - LDRx_REG_LSL3(x3, x3, x2); - UBFXx(x2, xRIP, JMPTABL_START0, JMPTABL_SHIFT0); - LDRx_REG_LSL3(x2, x3, x2); - } + int dest = indirect_lookup(dyn, ninst, rex.is32bits, x2, x3); #ifdef HAVE_TRACE - BLR(x2); + BLR(dest); #else - BR(x2); + BR(dest); #endif CLEARIP(); } @@ -717,43 +694,11 @@ void retn_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int ninst, rex_t rex, int SUBx_U12(xSP, xSavedSP, 16); } NOTEST(x2); - if(!rex.is32bits) { - // check higher 48bits - LSRx_IMM(x2, xRIP, 48); - CBNZw(x2, (intptr_t)dyn->jmp_next - (intptr_t)dyn->block); - // load table - uintptr_t tbl = getJumpTable48(); - MOV64x(x3, tbl); - #ifdef JMPTABL_SHIFT4 - UBFXx(x2, xRIP, JMPTABL_START3, JMPTABL_SHIFT3); - LDRx_REG_LSL3(x3, x3, x2); - #endif - UBFXx(x2, xRIP, JMPTABL_START2, JMPTABL_SHIFT2); - LDRx_REG_LSL3(x3, x3, x2); - UBFXx(x2, xRIP, JMPTABL_START1, JMPTABL_SHIFT1); - LDRx_REG_LSL3(x3, x3, x2); - UBFXx(x2, xRIP, JMPTABL_START0, JMPTABL_SHIFT0); - LDRx_REG_LSL3(x2, x3, x2); - } else { - // check higher 32bits disbaled - //LSRx_IMM(x2, xRIP, 32); - //CBNZw(x2, (intptr_t)dyn->jmp_next - (intptr_t)dyn->block); - // load table - uintptr_t tbl = getJumpTable32(); - TABLE64(x3, tbl); - #ifdef JMPTABL_SHIFT4 - UBFXx(x2, xRIP, JMPTABL_START2, JMPTABL_SHIFT2); - LDRx_REG_LSL3(x3, x3, x2); - #endif - UBFXx(x2, xRIP, JMPTABL_START1, JMPTABL_SHIFT1); - LDRx_REG_LSL3(x3, x3, x2); - UBFXx(x2, xRIP, JMPTABL_START0, JMPTABL_SHIFT0); - LDRx_REG_LSL3(x2, x3, x2); - } + int dest = indirect_lookup(dyn, ninst, rex.is32bits, x2, x3); #ifdef HAVE_TRACE - BLR(x2); + BLR(dest); #else - BR(x2); + BR(dest); #endif CLEARIP(); } diff --git a/src/dynarec/la64/dynarec_la64_helper.c b/src/dynarec/la64/dynarec_la64_helper.c index 97ed2d97..6fa48606 100644 --- a/src/dynarec/la64/dynarec_la64_helper.c +++ b/src/dynarec/la64/dynarec_la64_helper.c @@ -526,6 +526,31 @@ void jump_to_epilog_fast(dynarec_la64_t* dyn, uintptr_t ip, int reg, int ninst) BR(x2); } + +static int indirect_lookup(dynarec_la64_t* dyn, int ninst, int is32bits, int s1, int s2) +{ + MAYUSE(dyn); + if (!is32bits) { + SRLI_D(s1, xRIP, 48); + BNEZ_safe(s1, (intptr_t)dyn->jmp_next - (intptr_t)dyn->block); + uintptr_t tbl = getJumpTable48(); + MOV64x(s2, tbl); + BSTRPICK_D(s1, xRIP, JMPTABL_START2 + JMPTABL_SHIFT2 - 1, JMPTABL_START2); + ALSL_D(s2, s1, s2, 3); + LD_D(s2, s2, 0); + } else { + uintptr_t tbl = getJumpTable32(); + TABLE64(s2, tbl); + } + BSTRPICK_D(s1, xRIP, JMPTABL_START1 + JMPTABL_SHIFT1 - 1, JMPTABL_START1); + ALSL_D(s2, s1, s2, 3); + LD_D(s2, s2, 0); + BSTRPICK_D(s1, xRIP, JMPTABL_START0 + JMPTABL_SHIFT0 - 1, JMPTABL_START0); + ALSL_D(s2, s1, s2, 3); + LD_D(s1, s2, 0); + return s1; +} + void jump_to_next(dynarec_la64_t* dyn, uintptr_t ip, int reg, int ninst, int is32bits) { MAYUSE(dyn); @@ -535,45 +560,28 @@ void jump_to_next(dynarec_la64_t* dyn, uintptr_t ip, int reg, int ninst, int is3 if (is32bits) ip &= 0xffffffffLL; + int dest; if (reg) { if (reg != xRIP) { MV(xRIP, reg); } NOTEST(x2); - uintptr_t tbl = is32bits ? getJumpTable32() : getJumpTable64(); - MAYUSE(tbl); - TABLE64(x3, tbl); - if (!is32bits) { - BSTRPICK_D(x2, xRIP, JMPTABL_START3 + JMPTABL_SHIFT3 - 1, JMPTABL_START3); - ALSL_D(x3, x2, x3, 3); - LD_D(x3, x3, 0); - BSTRPICK_D(x2, xRIP, JMPTABL_START2 + JMPTABL_SHIFT2 - 1, JMPTABL_START2); - ALSL_D(x3, x2, x3, 3); - LD_D(x3, x3, 0); - } - BSTRPICK_D(x2, xRIP, JMPTABL_START1 + JMPTABL_SHIFT1 - 1, JMPTABL_START1); - ALSL_D(x3, x2, x3, 3); - LD_D(x3, x3, 0); - BSTRPICK_D(x2, xRIP, JMPTABL_START0 + JMPTABL_SHIFT0 - 1, JMPTABL_START0); - ALSL_D(x3, x2, x3, 3); - LD_D(x2, x3, 0); + dest = indirect_lookup(dyn, ninst, is32bits, x2, x3); } else { NOTEST(x2); uintptr_t p = getJumpTableAddress64(ip); MAYUSE(p); TABLE64(x3, p); GETIP_(ip); - LD_D(x2, x3, 0); // LR_D(x2, x3, 1, 1); + LD_D(x2, x3, 0); + dest = x2; } if (reg != x1) { MV(x1, xRIP); } CLEARIP(); -#ifdef HAVE_TRACE -// MOVx(x3, 15); no access to PC reg -#endif SMEND(); - JIRL((dyn->insts[ninst].x64.has_callret ? xRA : xZR), x2, 0x0); // save LR... + JIRL((dyn->insts[ninst].x64.has_callret ? xRA : xZR), dest, 0x0); } void ret_to_epilog(dynarec_la64_t* dyn, uintptr_t ip, int ninst, rex_t rex) @@ -594,24 +602,9 @@ void ret_to_epilog(dynarec_la64_t* dyn, uintptr_t ip, int ninst, rex_t rex) // not the correct return address, regular jump, but purge the stack first, it's unsync now... ADDI_D(xSP, xSavedSP, -16); } - - uintptr_t tbl = rex.is32bits ? getJumpTable32() : getJumpTable64(); - MOV64x(x3, tbl); - if (!rex.is32bits) { - BSTRPICK_D(x2, xRIP, JMPTABL_START3 + JMPTABL_SHIFT3 - 1, JMPTABL_START3); - ALSL_D(x3, x2, x3, 3); - LD_D(x3, x3, 0); - BSTRPICK_D(x2, xRIP, JMPTABL_START2 + JMPTABL_SHIFT2 - 1, JMPTABL_START2); - ALSL_D(x3, x2, x3, 3); - LD_D(x3, x3, 0); - } - BSTRPICK_D(x2, xRIP, JMPTABL_START1 + JMPTABL_SHIFT1 - 1, JMPTABL_START1); - ALSL_D(x3, x2, x3, 3); - LD_D(x3, x3, 0); - BSTRPICK_D(x2, xRIP, JMPTABL_START0 + JMPTABL_SHIFT0 - 1, JMPTABL_START0); - ALSL_D(x3, x2, x3, 3); - LD_D(x2, x3, 0); - BR(x2); + NOTEST(x2); + int dest = indirect_lookup(dyn, ninst, rex.is32bits, x2, x3); + BR(dest); CLEARIP(); } @@ -640,23 +633,9 @@ void retn_to_epilog(dynarec_la64_t* dyn, uintptr_t ip, int ninst, rex_t rex, int ADDI_D(xSP, xSavedSP, -16); } - uintptr_t tbl = rex.is32bits ? getJumpTable32() : getJumpTable64(); - MOV64x(x3, tbl); - if (!rex.is32bits) { - BSTRPICK_D(x2, xRIP, JMPTABL_START3 + JMPTABL_SHIFT3 - 1, JMPTABL_START3); - ALSL_D(x3, x2, x3, 3); - LD_D(x3, x3, 0); - BSTRPICK_D(x2, xRIP, JMPTABL_START2 + JMPTABL_SHIFT2 - 1, JMPTABL_START2); - ALSL_D(x3, x2, x3, 3); - LD_D(x3, x3, 0); - } - BSTRPICK_D(x2, xRIP, JMPTABL_START1 + JMPTABL_SHIFT1 - 1, JMPTABL_START1); - ALSL_D(x3, x2, x3, 3); - LD_D(x3, x3, 0); - BSTRPICK_D(x2, xRIP, JMPTABL_START0 + JMPTABL_SHIFT0 - 1, JMPTABL_START0); - ALSL_D(x3, x2, x3, 3); - LD_D(x2, x3, 0); - BR(x2); + NOTEST(x2); + int dest = indirect_lookup(dyn, ninst, rex.is32bits, x2, x3); + BR(dest); CLEARIP(); } diff --git a/src/dynarec/rv64/dynarec_rv64_helper.c b/src/dynarec/rv64/dynarec_rv64_helper.c index 1f4ef25b..79868e55 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.c +++ b/src/dynarec/rv64/dynarec_rv64_helper.c @@ -583,6 +583,56 @@ void jump_to_epilog_fast(dynarec_rv64_t* dyn, uintptr_t ip, int reg, int ninst) #ifdef JMPTABLE_SHIFT4 #error TODO! #endif + +static int indirect_lookup(dynarec_rv64_t* dyn, int ninst, int is32bits, int s1, int s2) +{ + MAYUSE(dyn); + if (rv64_xtheadbb && rv64_xtheadmemidx) { + if (!is32bits) { + SRLI(s1, xRIP, 48); + BNEZ_safe(s1, (intptr_t)dyn->jmp_next - (intptr_t)dyn->block); + uintptr_t tbl = getJumpTable48(); + MOV64x(s2, tbl); + TH_EXTU(s1, xRIP, JMPTABL_START2 + JMPTABL_SHIFT2 - 1, JMPTABL_START2); + TH_LRD(s2, s2, s1, 3); + } else { + uintptr_t tbl = getJumpTable32(); + TABLE64(s2, tbl); + } + TH_EXTU(s1, xRIP, JMPTABL_START1 + JMPTABL_SHIFT1 - 1, JMPTABL_START1); + TH_LRD(s2, s2, s1, 3); + TH_EXTU(s1, xRIP, JMPTABL_START0 + JMPTABL_SHIFT0 - 1, JMPTABL_START0); + TH_LRD(s1, s2, s1, 3); + } else { + if (!is32bits) { + SRLI(s1, xRIP, 48); + BNEZ_safe(s1, (intptr_t)dyn->jmp_next - (intptr_t)dyn->block); + uintptr_t tbl = getJumpTable48(); + MOV64x(s2, tbl); + SRLI(s1, xRIP, JMPTABL_START2); + ADDSL(s2, s2, s1, 3, s1); + LD(s2, s2, 0); + } else { + uintptr_t tbl = getJumpTable32(); + TABLE64(s2, tbl); + } + MOV64x(x4, JMPTABLE_MASK1 << 3); + SRLI(s1, xRIP, JMPTABL_START1 - 3); + AND(s1, s1, x4); + ADD(s2, s2, s1); + LD(s2, s2, 0); + if (JMPTABLE_MASK0 < 2048) { + ANDI(s1, xRIP, JMPTABLE_MASK0); + } else { + MOV64x(x4, JMPTABLE_MASK0); // x4 = mask + AND(s1, xRIP, x4); + } + ADDSL(s2, s2, s1, 3, s1); + LD(s1, s2, 0); + } + return s1; +} + void jump_to_next(dynarec_rv64_t* dyn, uintptr_t ip, int reg, int ninst, int is32bits) { MAYUSE(dyn); @@ -592,81 +642,27 @@ void jump_to_next(dynarec_rv64_t* dyn, uintptr_t ip, int reg, int ninst, int is3 if (is32bits) ip &= 0xffffffffLL; + int dest; if (reg) { if (reg != xRIP) { MV(xRIP, reg); } NOTEST(x2); - uintptr_t tbl = is32bits ? getJumpTable32() : getJumpTable64(); - MAYUSE(tbl); - TABLE64(x3, tbl); - if (rv64_xtheadbb) { - if (!is32bits) { - TH_EXTU(x2, xRIP, JMPTABL_START3 + JMPTABL_SHIFT3 - 1, JMPTABL_START3); - TH_ADDSL(x3, x3, x2, 3); - LD(x3, x3, 0); - TH_EXTU(x2, xRIP, JMPTABL_START2 + JMPTABL_SHIFT2 - 1, JMPTABL_START2); - TH_ADDSL(x3, x3, x2, 3); - LD(x3, x3, 0); - } - TH_EXTU(x2, xRIP, JMPTABL_START1 + JMPTABL_SHIFT1 - 1, JMPTABL_START1); - TH_ADDSL(x3, x3, x2, 3); - LD(x3, x3, 0); - TH_EXTU(x2, xRIP, JMPTABL_START0 + JMPTABL_SHIFT0 - 1, JMPTABL_START0); - TH_ADDSL(x3, x3, x2, 3); - LD(x2, x3, 0); - } else { - if (!is32bits) { - SRLI(x2, xRIP, JMPTABL_START3); - if (rv64_zba) - SH3ADD(x3, x2, x3); - else { - SLLI(x2, x2, 3); - ADD(x3, x3, x2); - } - LD(x3, x3, 0); // could be LR_D(x3, x3, 1, 1); for better safety - MOV64x(x4, JMPTABLE_MASK2 << 3); // x4 = mask - SRLI(x2, xRIP, JMPTABL_START2 - 3); - AND(x2, x2, x4); - ADD(x3, x3, x2); - LD(x3, x3, 0); // LR_D(x3, x3, 1, 1); - if (JMPTABLE_MASK2 != JMPTABLE_MASK1) { - MOV64x(x4, JMPTABLE_MASK1 << 3); // x4 = mask - } - } else { - MOV64x(x4, JMPTABLE_MASK1 << 3); - } - SRLI(x2, xRIP, JMPTABL_START1 - 3); - AND(x2, x2, x4); - ADD(x3, x3, x2); - LD(x3, x3, 0); // LR_D(x3, x3, 1, 1); - if (JMPTABLE_MASK0 < 2048) { - ANDI(x2, xRIP, JMPTABLE_MASK0); - } else { - MOV64x(x4, JMPTABLE_MASK0); // x4 = mask - AND(x2, xRIP, x4); - } - if (rv64_zba) - SH3ADD(x3, x2, x3); - else { - SLLI(x2, x2, 3); - ADD(x3, x3, x2); - } - LD(x2, x3, 0); - } + dest = indirect_lookup(dyn, ninst, is32bits, x2, x3); } else { uintptr_t p = getJumpTableAddress64(ip); MAYUSE(p); GETIP_(ip, x3); TABLE64(x3, p); LD(x2, x3, 0); + dest = x2; } CLEARIP(); SMEND(); #ifdef HAVE_TRACE - JALR(xRA, x2); + JALR(xRA, dest); #else - JALR((dyn->insts[ninst].x64.has_callret ? xRA : xZR), x2); + JALR((dyn->insts[ninst].x64.has_callret ? xRA : xZR), dest); #endif } @@ -689,58 +685,9 @@ void ret_to_epilog(dynarec_rv64_t* dyn, uintptr_t ip, int ninst, rex_t rex) LD(xSP, xEmu, offsetof(x64emu_t, xSPSave)); ADDI(xSP, xSP, -16); } - - uintptr_t tbl = rex.is32bits ? getJumpTable32() : getJumpTable64(); NOTEST(x2); - MOV64x(x3, tbl); - if (rv64_xtheadbb && rv64_xtheadmemidx) { - if (!rex.is32bits) { - TH_EXTU(x2, xRIP, JMPTABL_START3 + JMPTABL_SHIFT3 - 1, JMPTABL_START3); - TH_LRD(x3, x3, x2, 3); - TH_EXTU(x2, xRIP, JMPTABL_START2 + JMPTABL_SHIFT2 - 1, JMPTABL_START2); - TH_LRD(x3, x3, x2, 3); - } - TH_EXTU(x2, xRIP, JMPTABL_START1 + JMPTABL_SHIFT1 - 1, JMPTABL_START1); - TH_LRD(x3, x3, x2, 3); - TH_EXTU(x2, xRIP, JMPTABL_START0 + JMPTABL_SHIFT0 - 1, JMPTABL_START0); - TH_LRD(x2, x3, x2, 3); - } else { - if (!rex.is32bits) { - SRLI(x2, xRIP, JMPTABL_START3); - ADDSL(x3, x3, x2, 3, x2); - LD(x3, x3, 0); - MOV64x(x4, JMPTABLE_MASK2 << 3); // x4 = mask - SRLI(x2, xRIP, JMPTABL_START2 - 3); - AND(x2, x2, x4); - ADD(x3, x3, x2); - LD(x3, x3, 0); - if (JMPTABLE_MASK2 != JMPTABLE_MASK1) { - MOV64x(x4, JMPTABLE_MASK1 << 3); // x4 = mask - } - } else { - MOV64x(x4, JMPTABLE_MASK1 << 3); // x4 = mask - } - SRLI(x2, xRIP, JMPTABL_START1 - 3); - AND(x2, x2, x4); - ADD(x3, x3, x2); - LD(x3, x3, 0); - if (JMPTABLE_MASK0 < 2048) { - ANDI(x2, xRIP, JMPTABLE_MASK0); - } else { - if (JMPTABLE_MASK1 != JMPTABLE_MASK0) { - MOV64x(x4, JMPTABLE_MASK0); // x4 = mask - } - AND(x2, xRIP, x4); - } - if (rv64_zba) - SH3ADD(x3, x2, x3); - else { - SLLI(x2, x2, 3); - ADD(x3, x3, x2); - } - LD(x2, x3, 0); - } - BR(x2); + int dest = indirect_lookup(dyn, ninst, rex.is32bits, x2, x3); + BR(dest); CLEARIP(); } @@ -769,57 +716,9 @@ void retn_to_epilog(dynarec_rv64_t* dyn, uintptr_t ip, int ninst, rex_t rex, int LD(xSP, xEmu, offsetof(x64emu_t, xSPSave)); ADDI(xSP, xSP, -16); } - uintptr_t tbl = rex.is32bits ? getJumpTable32() : getJumpTable64(); NOTEST(x2); - MOV64x(x3, tbl); - if (rv64_xtheadbb && rv64_xtheadmemidx) { - if (!rex.is32bits) { - TH_EXTU(x2, xRIP, JMPTABL_START3 + JMPTABL_SHIFT3 - 1, JMPTABL_START3); - TH_LRD(x3, x3, x2, 3); - TH_EXTU(x2, xRIP, JMPTABL_START2 + JMPTABL_SHIFT2 - 1, JMPTABL_START2); - TH_LRD(x3, x3, x2, 3); - } - TH_EXTU(x2, xRIP, JMPTABL_START1 + JMPTABL_SHIFT2 - 1, JMPTABL_START1); - TH_LRD(x3, x3, x2, 3); - TH_EXTU(x2, xRIP, JMPTABL_START0 + JMPTABL_SHIFT0 - 1, JMPTABL_START0); - TH_LRD(x2, x3, x2, 3); - } else { - if (!rex.is32bits) { - SRLI(x2, xRIP, JMPTABL_START3); - ADDSL(x3, x3, x2, 3, x2); - LD(x3, x3, 0); - MOV64x(x4, JMPTABLE_MASK2 << 3); // x4 = mask - SRLI(x2, xRIP, JMPTABL_START2 - 3); - AND(x2, x2, x4); - ADD(x3, x3, x2); - LD(x3, x3, 0); - if (JMPTABLE_MASK2 != JMPTABLE_MASK1) { - MOV64x(x4, JMPTABLE_MASK1 << 3); // x4 = mask - } - } else { - MOV64x(x4, JMPTABLE_MASK1 << 3); // x4 = mask - } - SRLI(x2, xRIP, JMPTABL_START1 - 3); - AND(x2, x2, x4); - ADD(x3, x3, x2); - LD(x3, x3, 0); - if (JMPTABLE_MASK0 < 2048) { - ANDI(x2, xRIP, JMPTABLE_MASK0); - } else { - if (JMPTABLE_MASK1 != JMPTABLE_MASK0) { - MOV64x(x4, JMPTABLE_MASK0); // x4 = mask - } - AND(x2, xRIP, x4); - } - if (rv64_zba) - SH3ADD(x3, x2, x3); - else { - SLLI(x2, x2, 3); - ADD(x3, x3, x2); - } - LD(x2, x3, 0); - } - BR(x2); + int dest = indirect_lookup(dyn, ninst, rex.is32bits, x2, x3); + BR(dest); CLEARIP(); } @@ -942,7 +841,7 @@ void call_n(dynarec_rv64_t* dyn, int ninst, void* fnc, int w) int sextw_mask = ((w > 0 ? w : -w) >> 4) & 0b111111; for (int i = 0; i < 6; i++) { if (sextw_mask & (1 << i)) { - SEXT_W(A0+i, A0+i); + SEXT_W(A0 + i, A0 + i); } } // native call |