mirror of
https://github.com/ptitSeb/box64.git
synced 2025-02-17 04:49:17 +00:00
[DYNAREC] Tweaking indirect jumps for CALL/RET to use the return address stack (#1907)
Some checks are pending
Build and Release Box64 / build (ubuntu-latest, ANDROID, Release) (push) Waiting to run
Build and Release Box64 / build (ubuntu-latest, ANDROID, Trace) (push) Waiting to run
Build and Release Box64 / build (ubuntu-latest, ARM64, Box32) (push) Waiting to run
Build and Release Box64 / build (ubuntu-latest, ARM64, Release) (push) Waiting to run
Build and Release Box64 / build (ubuntu-latest, ARM64, StaticBuild) (push) Waiting to run
Build and Release Box64 / build (ubuntu-latest, ARM64, Trace) (push) Waiting to run
Build and Release Box64 / build (ubuntu-latest, LARCH64, Box32) (push) Waiting to run
Build and Release Box64 / build (ubuntu-latest, LARCH64, Release) (push) Waiting to run
Build and Release Box64 / build (ubuntu-latest, LARCH64, StaticBuild) (push) Waiting to run
Build and Release Box64 / build (ubuntu-latest, LARCH64, Trace) (push) Waiting to run
Build and Release Box64 / build (ubuntu-latest, RISCV, Box32) (push) Waiting to run
Build and Release Box64 / build (ubuntu-latest, RISCV, Release) (push) Waiting to run
Build and Release Box64 / build (ubuntu-latest, RISCV, StaticBuild) (push) Waiting to run
Build and Release Box64 / build (ubuntu-latest, RISCV, Trace) (push) Waiting to run
Build and Release Box64 / build (ubuntu-latest, RK3588, Box32) (push) Waiting to run
Build and Release Box64 / build (ubuntu-latest, RK3588, Release) (push) Waiting to run
Build and Release Box64 / build (ubuntu-latest, RK3588, StaticBuild) (push) Waiting to run
Build and Release Box64 / build (ubuntu-latest, RK3588, Trace) (push) Waiting to run
Build and Release Box64 / build (ubuntu-latest, TERMUX, Release) (push) Waiting to run
Build and Release Box64 / build (ubuntu-latest, TERMUX, Trace) (push) Waiting to run
Build and Release Box64 / build (ubuntu-latest, X64, Box32) (push) Waiting to run
Build and Release Box64 / build (ubuntu-latest, X64, Release) (push) Waiting to run
Build and Release Box64 / build (ubuntu-latest, X64, Trace) (push) Waiting to run
Some checks are pending
Build and Release Box64 / build (ubuntu-latest, ANDROID, Release) (push) Waiting to run
Build and Release Box64 / build (ubuntu-latest, ANDROID, Trace) (push) Waiting to run
Build and Release Box64 / build (ubuntu-latest, ARM64, Box32) (push) Waiting to run
Build and Release Box64 / build (ubuntu-latest, ARM64, Release) (push) Waiting to run
Build and Release Box64 / build (ubuntu-latest, ARM64, StaticBuild) (push) Waiting to run
Build and Release Box64 / build (ubuntu-latest, ARM64, Trace) (push) Waiting to run
Build and Release Box64 / build (ubuntu-latest, LARCH64, Box32) (push) Waiting to run
Build and Release Box64 / build (ubuntu-latest, LARCH64, Release) (push) Waiting to run
Build and Release Box64 / build (ubuntu-latest, LARCH64, StaticBuild) (push) Waiting to run
Build and Release Box64 / build (ubuntu-latest, LARCH64, Trace) (push) Waiting to run
Build and Release Box64 / build (ubuntu-latest, RISCV, Box32) (push) Waiting to run
Build and Release Box64 / build (ubuntu-latest, RISCV, Release) (push) Waiting to run
Build and Release Box64 / build (ubuntu-latest, RISCV, StaticBuild) (push) Waiting to run
Build and Release Box64 / build (ubuntu-latest, RISCV, Trace) (push) Waiting to run
Build and Release Box64 / build (ubuntu-latest, RK3588, Box32) (push) Waiting to run
Build and Release Box64 / build (ubuntu-latest, RK3588, Release) (push) Waiting to run
Build and Release Box64 / build (ubuntu-latest, RK3588, StaticBuild) (push) Waiting to run
Build and Release Box64 / build (ubuntu-latest, RK3588, Trace) (push) Waiting to run
Build and Release Box64 / build (ubuntu-latest, TERMUX, Release) (push) Waiting to run
Build and Release Box64 / build (ubuntu-latest, TERMUX, Trace) (push) Waiting to run
Build and Release Box64 / build (ubuntu-latest, X64, Box32) (push) Waiting to run
Build and Release Box64 / build (ubuntu-latest, X64, Release) (push) Waiting to run
Build and Release Box64 / build (ubuntu-latest, X64, Trace) (push) Waiting to run
This commit is contained in:
parent
b395cd7ccc
commit
172df2cd0c
@ -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))
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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))
|
||||
|
Loading…
x
Reference in New Issue
Block a user