about summary refs log tree commit diff stats
path: root/src/dynarec
diff options
context:
space:
mode:
Diffstat (limited to 'src/dynarec')
-rw-r--r--src/dynarec/dynarec.c13
-rw-r--r--src/dynarec/rv64/dynarec_rv64_00_3.c36
-rw-r--r--src/dynarec/rv64/dynarec_rv64_helper.c39
-rw-r--r--src/dynarec/rv64/rv64_epilog.S3
-rw-r--r--src/dynarec/rv64/rv64_prolog.S8
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