about summary refs log tree commit diff stats
path: root/src/dynarec/arm64/dynarec_arm64_helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/dynarec/arm64/dynarec_arm64_helper.c')
-rw-r--r--src/dynarec/arm64/dynarec_arm64_helper.c53
1 files changed, 35 insertions, 18 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_helper.c b/src/dynarec/arm64/dynarec_arm64_helper.c
index a1d9a93b..4e6b4c02 100644
--- a/src/dynarec/arm64/dynarec_arm64_helper.c
+++ b/src/dynarec/arm64/dynarec_arm64_helper.c
@@ -718,42 +718,48 @@ void iret_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int ninst, int is32bits, i
     // POP IP
     NOTEST(x2);
     if(is64bits) {
-        POP1(xRIP);
+        POP1(x1);
         POP1(x2);
-        POP1(xFlags);
+        POP1(x3);
     } else {
-        POP1_32(xRIP);
+        POP1_32(x1);
         POP1_32(x2);
-        POP1_32(xFlags);
+        POP1_32(x3);
     }
-    // x2 is CS
-    STRH_U12(x2, xEmu, offsetof(x64emu_t, segs[_CS]));
-    STRw_U12(xZR, xEmu, offsetof(x64emu_t, segs_serial[_CS]));
+    // check CS is NULL, sgfault if it is
+    CBZw_MARK3(x1);
     // clean EFLAGS
-    MOV32w(x1, 0x3F7FD7);
-    ANDx_REG(xFlags, xFlags, x1);
-    ORRx_mask(xFlags, xFlags, 1, 0b111111, 0); // xFlags | 0b10
+    MOV32w(x4, 0x3F7FD7);
+    ANDx_REG(x3, x3, x4);
+    ORRx_mask(x3, x3, 1, 0b111111, 0); // xFlags | 0b10
     SET_DFNONE();
     if(is32bits) {
-        ANDw_mask(x2, x2, 0, 7);   // mask 0xff
+        ANDw_mask(x4, x2, 0, 7);   // mask 0xff
         // check if return segment is 64bits, then restore rsp too
-        CMPSw_U12(x2, 0x23);
+        CMPSw_U12(x4, 0x23);
         B_MARKSEG(cEQ);
     }
     // POP RSP
     if(is64bits) {
-        POP1(x3);   //rsp
-        POP1(x2);   //ss
+        POP1(x4);   //rsp
+        POP1(x5);   //ss
     } else {
-        POP1_32(x3);   //rsp
-        POP1_32(x2);   //ss
+        POP1_32(x4);   //rsp
+        POP1_32(x5);   //ss
     }
+    // check if SS is NULL
+    CBZw(x5, MARK);
     // POP SS
-    STRH_U12(x2, xEmu, offsetof(x64emu_t, segs[_SS]));
+    STRH_U12(x5, xEmu, offsetof(x64emu_t, segs[_SS]));
     STRw_U12(xZR, xEmu, offsetof(x64emu_t, segs_serial[_SS]));
     // set new RSP
-    MOVx_REG(xRSP, x3);
+    MOVx_REG(xRSP, x4);
     MARKSEG;
+    // x2 is CS, x1 is IP, x3 is eFlags
+    STRH_U12(x2, xEmu, offsetof(x64emu_t, segs[_CS]));
+    STRw_U12(xZR, xEmu, offsetof(x64emu_t, segs_serial[_CS]));
+    MOVx_REG(xRIP, x1);
+    MOVw_REG(xFlags, x3);
     // Ret....
     // epilog on purpose, CS might have changed!
     if(dyn->need_reloc)
@@ -762,6 +768,17 @@ void iret_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int ninst, int is32bits, i
         MOV64x(x2, getConst(const_epilog));
     BR(x2);
     CLEARIP();
+    MARK;
+    if(is64bits)
+        ADDx_U12(xRSP, xRSP, 8*2);
+    else
+        ADDx_U12(xRSP, xRSP, 4*2);
+    MARK3;
+    if(is64bits)
+        ADDx_U12(xRSP, xRSP, 8*3);
+    else
+        ADDx_U12(xRSP, xRSP, 4*3);
+    CALL_S(const_native_priv, -1);
 }
 
 void call_c(dynarec_arm_t* dyn, int ninst, arm64_consts_t fnc, int reg, int ret, int saveflags, int savereg)