diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/dynarec/arm64/arm64_emitter.h | 1 | ||||
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_helper.c | 18 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_helper.c | 14 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_helper.c | 20 | ||||
| -rw-r--r-- | src/dynarec/rv64/rv64_emitter.h | 4 |
5 files changed, 31 insertions, 26 deletions
diff --git a/src/dynarec/arm64/arm64_emitter.h b/src/dynarec/arm64/arm64_emitter.h index bab9222c..4dc681e7 100644 --- a/src/dynarec/arm64/arm64_emitter.h +++ b/src/dynarec/arm64/arm64_emitter.h @@ -505,6 +505,7 @@ int convert_bitmask(uint64_t bitmask); #define BR_gen(Z, op, A, M, Rn, Rm) (0b1101011<<25 | (Z)<<24 | (op)<<21 | 0b11111<<16 | (A)<<11 | (M)<<10 | (Rn)<<5 | (Rm)) #define BR(Rn) EMIT(BR_gen(0, 0b00, 0, 0, Rn, 0)) #define BLR(Rn) EMIT(BR_gen(0, 0b01, 0, 0, Rn, 0)) +#define RET(Rn) EMIT(BR_gen(0, 0b10, 0, 0, Rn, 0)) #define CB_gen(sf, op, imm19, Rt) ((sf)<<31 | 0b011010<<25 | (op)<<24 | (imm19)<<5 | (Rt)) #define CBNZx(Rt, imm19) EMIT(CB_gen(1, 1, ((imm19)>>2)&0x7FFFF, Rt)) diff --git a/src/dynarec/arm64/dynarec_arm64_helper.c b/src/dynarec/arm64/dynarec_arm64_helper.c index 5e2ed69d..f4497b61 100644 --- a/src/dynarec/arm64/dynarec_arm64_helper.c +++ b/src/dynarec/arm64/dynarec_arm64_helper.c @@ -610,7 +610,11 @@ void jump_to_next(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst, int is32 #ifdef HAVE_TRACE //MOVx(x3, 15); no access to PC reg #endif - BLR(x2); // save LR... + if (dyn->insts[ninst].x64.has_callret) { + BLR(x2); // save LR... + } else { + BR(x2); + } } void ret_to_epilog(dynarec_arm_t* dyn, int ninst, rex_t rex) @@ -622,10 +626,10 @@ void ret_to_epilog(dynarec_arm_t* dyn, int ninst, rex_t rex) SMEND(); if(box64_dynarec_callret) { // pop the actual return address for ARM stack - LDPx_S7_postindex(x2, x6, xSP, 16); + LDPx_S7_postindex(xLR, x6, xSP, 16); SUBx_REG(x6, x6, xRIP); // is it the right address? CBNZx(x6, 2*4); - BLR(x2); + RET(xLR); // not the correct return address, regular jump, but purge the stack first, it's unsync now... SUBx_U12(xSP, xSavedSP, 16); } @@ -646,7 +650,7 @@ void ret_to_epilog(dynarec_arm_t* dyn, int ninst, rex_t rex) LDRx_REG_LSL3(x2, x2, x3); UBFXx(x3, xRIP, JMPTABL_START0, JMPTABL_SHIFT0); LDRx_REG_LSL3(x2, x2, x3); - BLR(x2); // save LR + BR(x2); CLEARIP(); } @@ -665,10 +669,10 @@ void retn_to_epilog(dynarec_arm_t* dyn, int ninst, rex_t rex, int n) SMEND(); if(box64_dynarec_callret) { // pop the actual return address for ARM stack - LDPx_S7_postindex(x2, x6, xSP, 16); + LDPx_S7_postindex(xLR, x6, xSP, 16); SUBx_REG(x6, x6, xRIP); // is it the right address? CBNZx(x6, 2*4); - BLR(x2); + RET(xLR); // not the correct return address, regular jump SUBx_U12(xSP, xSavedSP, 16); } @@ -689,7 +693,7 @@ void retn_to_epilog(dynarec_arm_t* dyn, int ninst, rex_t rex, int n) LDRx_REG_LSL3(x2, x2, x3); UBFXx(x3, xRIP, JMPTABL_START0, JMPTABL_SHIFT0); LDRx_REG_LSL3(x2, x2, x3); - BLR(x2); // save LR + BR(x2); CLEARIP(); } diff --git a/src/dynarec/la64/dynarec_la64_helper.c b/src/dynarec/la64/dynarec_la64_helper.c index 1d23f10a..b33445f3 100644 --- a/src/dynarec/la64/dynarec_la64_helper.c +++ b/src/dynarec/la64/dynarec_la64_helper.c @@ -571,7 +571,7 @@ void jump_to_next(dynarec_la64_t* dyn, uintptr_t ip, int reg, int ninst, int is3 // MOVx(x3, 15); no access to PC reg #endif SMEND(); - JIRL(xRA, x2, 0x0); // save LR... + JIRL((dyn->insts[ninst].x64.has_callret ? xRA : xZR), x2, 0x0); // save LR... } void ret_to_epilog(dynarec_la64_t* dyn, int ninst, rex_t rex) @@ -584,11 +584,11 @@ void ret_to_epilog(dynarec_la64_t* dyn, int ninst, rex_t rex) SMEND(); if (box64_dynarec_callret) { // pop the actual return address from RV64 stack - LD_D(x2, xSP, 0); // native addr + LD_D(xRA, xSP, 0); // native addr LD_D(x6, xSP, 8); // x86 addr ADDI_D(xSP, xSP, 16); // pop BNE(x6, xRIP, 2 * 4); // is it the right address? - BR(x2); + BR(xRA); // not the correct return address, regular jump, but purge the stack first, it's unsync now... ADDI_D(xSP, xSavedSP, -16); } @@ -609,7 +609,7 @@ void ret_to_epilog(dynarec_la64_t* dyn, int ninst, rex_t rex) BSTRPICK_D(x2, xRIP, JMPTABL_START0 + JMPTABL_SHIFT0 - 1, JMPTABL_START0); ALSL_D(x3, x2, x3, 3); LD_D(x2, x3, 0); - BR(x2); // save LR + BR(x2); CLEARIP(); } @@ -629,11 +629,11 @@ void retn_to_epilog(dynarec_la64_t* dyn, int ninst, rex_t rex, int n) SMEND(); if (box64_dynarec_callret) { // pop the actual return address from RV64 stack - LD_D(x2, xSP, 0); // native addr + LD_D(xRA, xSP, 0); // native addr LD_D(x6, xSP, 8); // x86 addr ADDI_D(xSP, xSP, 16); // pop BNE(x6, xRIP, 2 * 4); // is it the right address? - BR(x2); + BR(xRA); // not the correct return address, regular jump, but purge the stack first, it's unsync now... ADDI_D(xSP, xSavedSP, -16); } @@ -654,7 +654,7 @@ void retn_to_epilog(dynarec_la64_t* dyn, int ninst, rex_t rex, int n) BSTRPICK_D(x2, xRIP, JMPTABL_START0 + JMPTABL_SHIFT0 - 1, JMPTABL_START0); ALSL_D(x3, x2, x3, 3); LD_D(x2, x3, 0); - BR(x2); // save LR + BR(x2); CLEARIP(); } diff --git a/src/dynarec/rv64/dynarec_rv64_helper.c b/src/dynarec/rv64/dynarec_rv64_helper.c index 408312dd..7c572092 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.c +++ b/src/dynarec/rv64/dynarec_rv64_helper.c @@ -580,7 +580,7 @@ void jump_to_next(dynarec_rv64_t* dyn, uintptr_t ip, int reg, int ninst, int is3 //MOVx(x3, 15); no access to PC reg #endif SMEND(); - JALR(x2); // save LR... + JALR((dyn->insts[ninst].x64.has_callret ? xRA : xZR), x2); } void ret_to_epilog(dynarec_rv64_t* dyn, int ninst, rex_t rex) @@ -592,11 +592,11 @@ void ret_to_epilog(dynarec_rv64_t* dyn, int ninst, rex_t rex) SMEND(); if (box64_dynarec_callret) { // pop the actual return address from RV64 stack - LD(x2, xSP, 0); // native addr + LD(xRA, xSP, 0); // native addr LD(x6, xSP, 8); // x86 addr ADDI(xSP, xSP, 16); // pop BNE(x6, xRIP, 2*4); // is it the right address? - JALR(x2); + BR(xRA); // not the correct return address, regular jump, but purge the stack first, it's unsync now... LD(xSP, xEmu, offsetof(x64emu_t, xSPSave)); ADDI(xSP, xSP, -16); @@ -631,7 +631,7 @@ void ret_to_epilog(dynarec_rv64_t* dyn, int ninst, rex_t rex) } if(rv64_zba) SH3ADD(x3, x2, x3); else {SLLI(x2, x2, 3); ADD(x3, x3, x2);} LD(x2, x3, 0); - JALR(x2); // save LR + BR(x2); CLEARIP(); } @@ -650,11 +650,11 @@ void retn_to_epilog(dynarec_rv64_t* dyn, int ninst, rex_t rex, int n) SMEND(); if (box64_dynarec_callret) { // pop the actual return address from RV64 stack - LD(x2, xSP, 0); // native addr + LD(xRA, xSP, 0); // native addr LD(x6, xSP, 8); // x86 addr ADDI(xSP, xSP, 16); // pop BNE(x6, xRIP, 2*4); // is it the right address? - JALR(x2); + BR(xRA); // not the correct return address, regular jump, but purge the stack first, it's unsync now... LD(xSP, xEmu, offsetof(x64emu_t, xSPSave)); ADDI(xSP, xSP, -16); @@ -688,7 +688,7 @@ void retn_to_epilog(dynarec_rv64_t* dyn, int ninst, rex_t rex, int n) } if(rv64_zba) SH3ADD(x3, x2, x3); else {SLLI(x2, x2, 3); ADD(x3, x3, x2);} LD(x2, x3, 0); - JALR(x2); // save LR + BR(x2); CLEARIP(); } @@ -760,7 +760,7 @@ void call_c(dynarec_rv64_t* dyn, int ninst, void* fnc, int reg, int ret, int sav SD(xRIP, xEmu, offsetof(x64emu_t, ip)); } TABLE64(reg, (uintptr_t)fnc); - JALR(reg); + JALR(xRA, reg); if(ret>=0) { MV(ret, xEmu); } @@ -833,8 +833,8 @@ void call_n(dynarec_rv64_t* dyn, int ninst, void* fnc, int w) MV(A4, xR8); MV(A5, xR9); // native call - TABLE64(16, (uintptr_t)fnc); // using x16 as scratch regs for call address - JALR(16); + TABLE64(xRAX, (uintptr_t)fnc); // using xRAX as scratch regs for call address + JALR(xRA, xRAX); // put return value in x64 regs if(w>0) { MV(xRAX, A0); diff --git a/src/dynarec/rv64/rv64_emitter.h b/src/dynarec/rv64/rv64_emitter.h index 7076a467..342bf818 100644 --- a/src/dynarec/rv64/rv64_emitter.h +++ b/src/dynarec/rv64/rv64_emitter.h @@ -157,9 +157,9 @@ f28–31 ft8–11 FP temporaries Caller // Unconditionnal branch to r+i12, no return address set #define BR_I12(r, imm12) EMIT(JALR_gen(xZR, r, (imm12) & 0b111111111111)) // Unconditionnal branch to r, return address set to xRA -#define JALR(r) EMIT(JALR_gen(xRA, r, 0)) +#define JALR(rd, rs) EMIT(JALR_gen(rd, rs, 0)) // Unconditionnal branch to r+i12, return address set to xRA -#define JALR_I12(r, imm12) EMIT(JALR_gen(xRA, r, (imm12) & 0b111111111111)) +#define JALR_I12(rd, rs, imm12) EMIT(JALR_gen(rd, rs, (imm12) & 0b111111111111)) // rd = rs1 + imm12 #define ADDI(rd, rs1, imm12) EMIT(I_type((imm12) & 0b111111111111, rs1, 0b000, rd, 0b0010011)) |