diff options
Diffstat (limited to 'src/dynarec')
| -rw-r--r-- | src/dynarec/dynarec.c | 13 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_00_3.c | 36 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_helper.c | 39 | ||||
| -rw-r--r-- | src/dynarec/rv64/rv64_epilog.S | 3 | ||||
| -rw-r--r-- | src/dynarec/rv64/rv64_prolog.S | 8 |
5 files changed, 63 insertions, 36 deletions
diff --git a/src/dynarec/dynarec.c b/src/dynarec/dynarec.c index a46997f8..6fef6935 100644 --- a/src/dynarec/dynarec.c +++ b/src/dynarec/dynarec.c @@ -129,16 +129,22 @@ void DynaRun(x64emu_t* emu) JUMPBUFF jmpbuf[1] = {0}; int skip = 0; JUMPBUFF *old_jmpbuf = emu->jmpbuf; + #ifdef RV64 + uintptr_t old_savesp = emu->xSPSave; + #endif emu->flags.jmpbuf_ready = 0; while(!(emu->quit)) { if(!emu->jmpbuf || (emu->flags.need_jmpbuf && emu->jmpbuf!=jmpbuf)) { emu->jmpbuf = jmpbuf; + #ifdef RV64 + emu->old_savedsp = emu->xSPSave; + #endif emu->flags.jmpbuf_ready = 1; #ifdef ANDROID - if((skip=sigsetjmp(*(JUMPBUFF*)emu->jmpbuf, 1))) + if((skip=sigsetjmp(*(JUMPBUFF*)emu->jmpbuf, 1))) #else - if((skip=sigsetjmp(emu->jmpbuf, 1))) + if((skip=sigsetjmp(emu->jmpbuf, 1))) #endif { printf_log(LOG_DEBUG, "Setjmp DynaRun, fs=0x%x\n", emu->segs[_FS]); @@ -192,4 +198,7 @@ void DynaRun(x64emu_t* emu) } // clear the setjmp emu->jmpbuf = old_jmpbuf; + #ifdef RV64 + emu->xSPSave = old_savesp; + #endif } diff --git a/src/dynarec/rv64/dynarec_rv64_00_3.c b/src/dynarec/rv64/dynarec_rv64_00_3.c index 2f55ab16..6d1296bd 100644 --- a/src/dynarec/rv64/dynarec_rv64_00_3.c +++ b/src/dynarec/rv64/dynarec_rv64_00_3.c @@ -880,22 +880,25 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int TABLE64(x2, addr); } PUSH1z(x2); - // TODO: Add support for CALLRET optim - /*if(box64_dynarec_callret) { + if(box64_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); + AUIPC(x4, ((j64 + 0x800) >> 12) & 0xfffff); + ADDI(x4, x4, j64 & 0xfff); + 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); - LDR(x4, x4, 0); + LD(x4, x4, 0); } - PUSH1(x4); - PUSH1(x2); - } else */ //CALLRET optim disable for now. - { + ADDI(xSP, xSP, -16); + SD(x4, xSP, 0); + SD(x2, xSP, 8); + } else { *ok = 0; *need_epilog = 0; } @@ -1249,20 +1252,25 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int *ok = 0; } GETIP_(addr); - // TODO: Add suport for CALLRET optim - /*if(box64_dynarec_callret) { + if(box64_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); + AUIPC(x4, ((j64 + 0x800) >> 12) & 0xfffff); + ADDI(x4, x4, j64 & 0xfff); + 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); + LD(x4, x4, 0); } - STPx_S7_preindex(x4, xRIP, xSP, -16); - }*/ + ADDI(xSP, xSP, -16); + SD(x4, xSP, 0); + SD(xRIP, xSP, 8); + } PUSH1z(xRIP); jump_to_next(dyn, 0, ed, ninst); break; diff --git a/src/dynarec/rv64/dynarec_rv64_helper.c b/src/dynarec/rv64/dynarec_rv64_helper.c index 7ef65dc8..2e887b84 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.c +++ b/src/dynarec/rv64/dynarec_rv64_helper.c @@ -527,16 +527,18 @@ void ret_to_epilog(dynarec_rv64_t* dyn, int ninst, rex_t rex) POP1z(xRIP); MVz(x1, xRIP); SMEND(); - /*if(box64_dynarec_callret) { + if (box64_dynarec_callret) { // pop the actual return address from RV64 stack - LDPx_S7_offset(x2, x6, xSP, 0); - CBZx(x6, 5*4); - ADDx_U12(xSP, xSP, 16); - SUBx_REG(x6, x6, xRIP); // is it the right address? - CBNZx(x6, 2*4); - BLR(x2); - // not the correct return address, regular jump - }*/ + LD(x2, 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); + // 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); + } + uintptr_t tbl = getJumpTable64(); MOV64x(x3, tbl); SRLI(x2, xRIP, JMPTABL_START3); @@ -581,16 +583,17 @@ void retn_to_epilog(dynarec_rv64_t* dyn, int ninst, rex_t rex, int n) } MVz(x1, xRIP); SMEND(); - /*if(box64_dynarec_callret) { + if (box64_dynarec_callret) { // pop the actual return address from RV64 stack - LDPx_S7_offset(x2, x6, xSP, 0); - CBZx(x6, 5*4); - ADDx_U12(xSP, xSP, 16); - SUBx_REG(x6, x6, xRIP); // is it the right address? - CBNZx(x6, 2*4); - BLR(x2); - // not the correct return address, regular jump - }*/ + LD(x2, 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); + // 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); + } uintptr_t tbl = getJumpTable64(); MOV64x(x3, tbl); SRLI(x2, xRIP, JMPTABL_START3); diff --git a/src/dynarec/rv64/rv64_epilog.S b/src/dynarec/rv64/rv64_epilog.S index 17dc117f..820dff02 100644 --- a/src/dynarec/rv64/rv64_epilog.S +++ b/src/dynarec/rv64/rv64_epilog.S @@ -37,6 +37,9 @@ rv64_epilog: sd x7, 136(a0) // put back reg value in emu, including EIP (so x7 must be EIP now) // fallback to epilog_fast now, just restoring saved regs rv64_epilog_fast: + ld sp, 552(a0) // restore saved sp from emu->xSPSave, see rv64_prolog + ld x9, -8(sp) + sd x9, 552(a0) // put back old value ld ra, (sp) // save ra ld x8, 8(sp) // save fp ld x18, (2*8)(sp) diff --git a/src/dynarec/rv64/rv64_prolog.S b/src/dynarec/rv64/rv64_prolog.S index 96a85d3b..9a780bd6 100644 --- a/src/dynarec/rv64/rv64_prolog.S +++ b/src/dynarec/rv64/rv64_prolog.S @@ -6,8 +6,6 @@ .text .align 4 -.extern rv64_next - .global rv64_prolog rv64_prolog: //save all 18 used register @@ -59,6 +57,12 @@ rv64_prolog: srli x5, x8, 11-5 andi x5, x5, 1<<5 or x8, x8, x5 + ld x5, 552(a0) // grab an old value of emu->xSPSave + sd sp, 552(a0) // save current sp to emu->xSPSave + // push sentinel onto the stack + sd x5, -16(sp) + sd zero, -8(sp) + addi sp, sp, -16 // setup xMASK xori x5, x0, -1 srli x5, x5, 32 |