[DYNAREC] More fixes to CALLRET=1

This commit is contained in:
ptitSeb 2024-05-19 23:22:19 +02:00
parent 984da28f40
commit a9c50ef238
5 changed files with 21 additions and 19 deletions

View File

@ -13,7 +13,7 @@ arm_epilog:
// restore stack pointer
ldr sp, [r0, #(8*4+2*4)]
pop {r4, r5}
str r5, [r0, #(8*4+2*4)] // put back old value
str r4, [r0, #(8*4+2*4)] // put back old value
//restore all used register
vpop {d8-d15}
pop {r4-r12, pc}
@ -26,7 +26,7 @@ arm_epilog_fast:
// restore stack pointer
ldr sp, [r0, #(8*4+2*4)]
pop {r4, r5}
str r5, [r0, #(8*4+2*4)] // put back old value
str r4, [r0, #(8*4+2*4)] // put back old value
//restore all used register
vpop {d8-d15}
pop {r4-r12, pc}

View File

@ -12,8 +12,8 @@ arm_prolog:
push {r4-r12, lr}
vpush {d8-d15}
// save Sp and setup stack for optionnal callret
ldr r5, [r0, #(8*4+2*4)] // grab old value of xSPSave
mov r4, #0
ldr r4, [r0, #(8*4+2*4)] // grab old value of xSPSave
mov r5, #0
push {r4-r5}
str sp, [r0, #(8*4+2*4)]
//setup emu -> register

View File

@ -2337,7 +2337,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
// Push actual return address
if(addr < (dyn->start+dyn->isize)) {
// there is a next...
j32 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size)):0;
j32 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size)-8):0;
MESSAGE(LOG_NONE, "\tCALLRET set return to +%di\n", j32>>2);
ADR(c__, x14, j32);
} else {
@ -2346,7 +2346,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MOV32(x14, j32);
LDR_IMM9(x14, x14, 0);
}
STMDB(xSP, (1<<x2)|(1<<x14));
PUSH(xSP, (1<<x2)|(1<<x14));
} else {
*need_epilog = 0;
*ok = 0;
@ -3002,7 +3002,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
// Push actual return address
if(addr < (dyn->start+dyn->isize)) {
// there is a next...
j32 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size)):0;
j32 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size)-8):0;
MESSAGE(LOG_NONE, "\tCALLRET set return to +%di\n", j32>>2);
ADR(c__, x3, j32);
} else {
@ -3011,7 +3011,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MOV32(x3, j32);
LDR_IMM9(x3, x3, 0);
}
STMDB(xSP, (1<<x2)|(1<<x3));
PUSH(xSP, (1<<x2)|(1<<x3));
}
PUSH1(x2);
jump_to_next(dyn, 0, ed, ninst);

View File

@ -365,7 +365,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
{
READFLAGS(X_PEND); // that's suspicious
} else {
SETFLAGS(X_ALL, SF_SET); //Hack to put flag in "don't care" state
SETFLAGS(X_ALL, SF_SET_NODF); //Hack to put flag in "don't care" state
}
if(MODREG) { // reg
MOV_REG(xEIP, xEAX+(nextop&7));
@ -387,7 +387,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
// Push actual return address
if(addr < (dyn->start+dyn->isize)) {
// there is a next...
j32 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size)):0;
j32 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size)-8):0;
MESSAGE(LOG_NONE, "\tCALLRET set return to +%di\n", j32>>2);
ADR(c__, x3, j32);
} else {
@ -396,7 +396,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MOV32(x3, j32);
LDR_IMM9(x3, x3, 0);
}
STMDB(xSP, (1<<x2)|(1<<x3));
PUSH(xSP, (1<<x2)|(1<<x3));
}
PUSH1(x2);
jump_to_next(dyn, 0, xEIP, ninst);

View File

@ -293,12 +293,13 @@ void ret_to_epilog(dynarec_arm_t* dyn, int ninst)
SMEND();
if(box86_dynarec_callret) {
// pop the actual return address for ARM stack
LDM(xSP, (1<<x2)|(1<<x3));
CMPS_REG_LSL_IMM5(x3, xEIP, 0); // is it the right address?
BXcond(cEQ, x2);
POP(xSP, (1<<x2)|(1<<x3));
CMPS_REG_LSL_IMM5(x2, xEIP, 0); // is it the right address?
BXcond(cEQ, x3);
// not the correct return address, regular jump, but purge the stack first, it's unsync now...
CMPS_IMM8(x2, 0); // that was already the top of the stack...
CMPS_IMM8(x3, 0); // that was already the top of the stack...
LDR_IMM9_COND(cNE, xSP, xEmu, offsetof(x86emu_t, xSPSave)); // load pointer only if not already on top
SUB_COND_IMM8(cEQ, xSP, xSP, 8); // unpop
}
MOV32(x2, getJumpTable());
MOV_REG_LSR_IMM5(x3, xEIP, JMPTABL_SHIFT);
@ -325,12 +326,13 @@ void retn_to_epilog(dynarec_arm_t* dyn, int ninst, int n)
SMEND();
if(box86_dynarec_callret) {
// pop the actual return address for ARM stack
LDM(xSP, (1<<x2)|(1<<x3));
CMPS_REG_LSL_IMM5(x3, xEIP, 0); // is it the right address?
BXcond(cEQ, x2);
POP(xSP, (1<<x2)|(1<<x3));
CMPS_REG_LSL_IMM5(x2, xEIP, 0); // is it the right address?
BXcond(cEQ, x3);
// not the correct return address, regular jump, but purge the stack first, it's unsync now...
CMPS_IMM8(x2, 0); // that was already the top of the stack...
CMPS_IMM8(x3, 0); // that was already the top of the stack...
LDR_IMM9_COND(cNE, xSP, xEmu, offsetof(x86emu_t, xSPSave));
SUB_COND_IMM8(cEQ, xSP, xSP, 8); // unpop
}
MOV32(x2, getJumpTable());
MOV_REG_LSR_IMM5(x3, xEIP, JMPTABL_SHIFT);