about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2023-03-15 22:45:09 +0000
committerptitSeb <sebastien.chev@gmail.com>2023-03-15 22:45:09 +0000
commita3ad297f926b0002bcade8f1648b573310119738 (patch)
tree3627f896388dc6231fdd6215fbf287185f6d5065
parent6707640fa383a3fee40db4ed7db539cbe247d968 (diff)
downloadbox64-a3ad297f926b0002bcade8f1648b573310119738.tar.gz
box64-a3ad297f926b0002bcade8f1648b573310119738.zip
[RV64_PRINTER] Added C2/RETN and C3/RET opocde, along with fixes to jmp_to_next
-rw-r--r--src/dynarec/rv64/dynarec_rv64_00.c24
-rw-r--r--src/dynarec/rv64/dynarec_rv64_helper.c138
-rw-r--r--src/dynarec/rv64/dynarec_rv64_helper.h4
3 files changed, 151 insertions, 15 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_00.c b/src/dynarec/rv64/dynarec_rv64_00.c
index 0adae90a..11d37571 100644
--- a/src/dynarec/rv64/dynarec_rv64_00.c
+++ b/src/dynarec/rv64/dynarec_rv64_00.c
@@ -218,6 +218,30 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                     DEFAULT;
             }
             break;
+        case 0xC2:
+            INST_NAME("RETN");
+            //SETFLAGS(X_ALL, SF_SET);    // Hack, set all flags (to an unknown state...)
+            if(box64_dynarec_safeflags) {
+                READFLAGS(X_PEND);  // lets play safe here too
+            }
+            BARRIER(BARRIER_FLOAT);
+            i32 = F16;
+            retn_to_epilog(dyn, ninst, i32);
+            *need_epilog = 0;
+            *ok = 0;
+            break;
+        case 0xC3:
+            INST_NAME("RET");
+            // SETFLAGS(X_ALL, SF_SET);    // Hack, set all flags (to an unknown state...)
+            if(box64_dynarec_safeflags) {
+                READFLAGS(X_PEND);  // so instead, force the defered flags, so it's not too slow, and flags are not lost
+            }
+            BARRIER(BARRIER_FLOAT);
+            ret_to_epilog(dyn, ninst);
+            *need_epilog = 0;
+            *ok = 0;
+            break;
+
         case 0xC6:
             INST_NAME("MOV Eb, Ib");
             nextop=F8;
diff --git a/src/dynarec/rv64/dynarec_rv64_helper.c b/src/dynarec/rv64/dynarec_rv64_helper.c
index 36800a31..204b891d 100644
--- a/src/dynarec/rv64/dynarec_rv64_helper.c
+++ b/src/dynarec/rv64/dynarec_rv64_helper.c
@@ -202,25 +202,31 @@ void jump_to_next(dynarec_rv64_t* dyn, uintptr_t ip, int reg, int ninst)
         TABLE64(x3, tbl);
         SRLI(x2, xRIP, JMPTABL_START3);
         SLLI(x2, x2, 3);
-        LD(x3, x3, x2);
-        LUI(x4, JMPTABLE_MASK2);    // x4 = mask
-        SRLI(x2, xRIP, JMPTABL_START2);
+        ADD(x3, x3, x2);
+        LD(x3, x3, 0);
+        MOV64x(x4, JMPTABLE_MASK2<<3);    // x4 = mask
+        SRLI(x2, xRIP, JMPTABL_START2-3);
         AND(x2, x2, x4);
-        SLLI(x2, x2, 3);
-        LD(x3, x3, x2);
+        ADD(x3, x3, x2);
+        LD(x3, x3, 0);
         if(JMPTABLE_MASK2!=JMPTABLE_MASK1) {
-            LUI(x4, JMPTABLE_MASK1);    // x4 = mask
+            MOV64x(x4, JMPTABLE_MASK1<<3);    // x4 = mask
         }
-        SRLI(x2, xRIP, JMPTABL_START1);
+        SRLI(x2, xRIP, JMPTABL_START1-3);
         AND(x2, x2, x4);
-        SLLI(x2, x2, 3);
-        LD(x3, x3, x2);
-        if(JMPTABLE_MASK1!=JMPTABLE_MASK0) {
-            LUI(x4, JMPTABLE_MASK0);    // x4 = mask
+        ADD(x3, x3, x2);
+        LD(x3, x3, 0);
+        if(JMPTABLE_MASK0<2048) {
+            ANDI(x2, xRIP, JMPTABLE_MASK0);
+        } else {
+            if(JMPTABLE_MASK1!=JMPTABLE_MASK0) {
+                MOV64x(x4, JMPTABLE_MASK0);    // x4 = mask
+            }
+            AND(x2, xRIP, x4);
         }
-        AND(x2, x2, x4);
         SLLI(x2, x2, 3);
-        LD(x2, x3, x2);
+        ADD(x3, x3, x2);
+        LD(x2, x3, 0);
     } else {
         uintptr_t p = getJumpTableAddress64(ip);
         MAYUSE(p);
@@ -239,6 +245,112 @@ void jump_to_next(dynarec_rv64_t* dyn, uintptr_t ip, int reg, int ninst)
     JALR(x2); // save LR...
 }
 
+void ret_to_epilog(dynarec_rv64_t* dyn, int ninst)
+{
+    MAYUSE(dyn); MAYUSE(ninst);
+    MESSAGE(LOG_DUMP, "Ret to epilog\n");
+    POP1(xRIP);
+    MV(x1, xRIP);
+    SMEND();
+    /*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
+    }*/
+    uintptr_t tbl = getJumpTable64();
+    MOV64x(x3, tbl);
+    SRLI(x2, xRIP, JMPTABL_START3);
+    SLLI(x2, x2, 3);
+    ADD(x3, x3, x2);
+    LD(x3, x3, 0);
+    MOV64x(x4, JMPTABLE_MASK2<<3);    // x4 = mask
+    SRLI(x2, xRIP, JMPTABL_START2-3);
+    AND(x2, x2, x4);
+    ADD(x3, x3, x2);
+    LD(x3, x3, 0);
+    if(JMPTABLE_MASK2!=JMPTABLE_MASK1) {
+        MOV64x(x4, JMPTABLE_MASK1<<3);    // x4 = mask
+    }
+    SRLI(x2, xRIP, JMPTABL_START1-3);
+    AND(x2, x2, x4);
+    ADD(x3, x3, x2);
+    LD(x3, x3, 0);
+    if(JMPTABLE_MASK0<2048) {
+        ANDI(x2, xRIP, JMPTABLE_MASK0);
+    } else {
+        if(JMPTABLE_MASK1!=JMPTABLE_MASK0) {
+            MOV64x(x4, JMPTABLE_MASK0);    // x4 = mask
+        }
+        AND(x2, xRIP, x4);
+    }
+    SLLI(x2, x2, 3);
+    ADD(x3, x3, x2);
+    LD(x2, x3, 0);
+    JALR(x2); // save LR
+    CLEARIP();
+}
+
+void retn_to_epilog(dynarec_rv64_t* dyn, int ninst, int n)
+{
+    MAYUSE(dyn); MAYUSE(ninst);
+    MESSAGE(LOG_DUMP, "Retn to epilog\n");
+    POP1(xRIP);
+    if(n>0x7ff) {
+        MOV64x(w1, n);
+        ADD(xRSP, xRSP, x1);
+    } else {
+        ADDI(xRSP, xRSP, n);
+    }
+    MV(x1, xRIP);
+    SMEND();
+    /*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
+    }*/
+    uintptr_t tbl = getJumpTable64();
+    MOV64x(x3, tbl);
+    SRLI(x2, xRIP, JMPTABL_START3);
+    SLLI(x2, x2, 3);
+    ADD(x3, x3, x2);
+    LD(x3, x3, 0);
+    MOV64x(x4, JMPTABLE_MASK2<<3);    // x4 = mask
+    SRLI(x2, xRIP, JMPTABL_START2-3);
+    AND(x2, x2, x4);
+    ADD(x3, x3, x2);
+    LD(x3, x3, 0);
+    if(JMPTABLE_MASK2!=JMPTABLE_MASK1) {
+        MOV64x(x4, JMPTABLE_MASK1<<3);    // x4 = mask
+    }
+    SRLI(x2, xRIP, JMPTABL_START1-3);
+    AND(x2, x2, x4);
+    ADD(x3, x3, x2);
+    LD(x3, x3, 0);
+    if(JMPTABLE_MASK0<2048) {
+        ANDI(x2, xRIP, JMPTABLE_MASK0);
+    } else {
+        if(JMPTABLE_MASK1!=JMPTABLE_MASK0) {
+            MOV64x(x4, JMPTABLE_MASK0);    // x4 = mask
+        }
+        AND(x2, xRIP, x4);
+    }
+    SLLI(x2, x2, 3);
+    ADD(x3, x3, x2);
+    LD(x2, x3, 0);
+    JALR(x2); // save LR
+    CLEARIP();
+}
+
 void call_c(dynarec_rv64_t* dyn, int ninst, void* fnc, int reg, int ret, int saveflags, int savereg)
 {
     MAYUSE(fnc);
diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h
index e08b2e49..0795c626 100644
--- a/src/dynarec/rv64/dynarec_rv64_helper.h
+++ b/src/dynarec/rv64/dynarec_rv64_helper.h
@@ -494,8 +494,8 @@ uintptr_t geted(dynarec_rv64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop,
 // generic x64 helper
 void jump_to_epilog(dynarec_rv64_t* dyn, uintptr_t ip, int reg, int ninst);
 void jump_to_next(dynarec_rv64_t* dyn, uintptr_t ip, int reg, int ninst);
-//void ret_to_epilog(dynarec_rv64_t* dyn, int ninst);
-//void retn_to_epilog(dynarec_rv64_t* dyn, int ninst, int n);
+void ret_to_epilog(dynarec_rv64_t* dyn, int ninst);
+void retn_to_epilog(dynarec_rv64_t* dyn, int ninst, int n);
 //void iret_to_epilog(dynarec_rv64_t* dyn, int ninst, int is64bits);
 void call_c(dynarec_rv64_t* dyn, int ninst, void* fnc, int reg, int ret, int saveflags, int save_reg);
 void call_n(dynarec_rv64_t* dyn, int ninst, void* fnc, int w);