about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/dynarec.c23
-rw-r--r--src/emu/x64run.c2
-rw-r--r--src/libtools/signals.c2
-rw-r--r--src/tools/callback.c16
4 files changed, 40 insertions, 3 deletions
diff --git a/src/dynarec/dynarec.c b/src/dynarec/dynarec.c
index b832b1e5..16c1c464 100644
--- a/src/dynarec/dynarec.c
+++ b/src/dynarec/dynarec.c
@@ -81,6 +81,15 @@ void DynaCall(x64emu_t* emu, uintptr_t addr)
     uint64_t old_rsi = R_RSI;
     uint64_t old_rbp = R_RBP;
     uint64_t old_rip = R_RIP;
+    // save defered flags
+    deferred_flags_t old_df = emu->df;
+    multiuint_t old_op1 = emu->op1;
+    multiuint_t old_op2 = emu->op2;
+    multiuint_t old_res = emu->res;
+    multiuint_t old_op1_sav= emu->op1_sav;
+    multiuint_t old_res_sav= emu->res_sav;
+    deferred_flags_t old_df_sav= emu->df_sav;
+
     PushExit(emu);
     R_RIP = addr;
     emu->df = d_none;
@@ -91,6 +100,15 @@ void DynaCall(x64emu_t* emu, uintptr_t addr)
         if(emu->flags.quitonlongjmp==1)
             emu->flags.longjmp = 0;   // don't change anything because of the longjmp
     } else {
+        // restore defered flags
+        emu->df = old_df;
+        emu->op1 = old_op1;
+        emu->op2 = old_op2;
+        emu->res = old_res;
+        emu->op1_sav = old_op1_sav;
+        emu->res_sav = old_res_sav;
+        emu->df_sav = old_df_sav;
+        // and the old registers
         R_RBX = old_rbx;
         R_RDI = old_rdi;
         R_RSI = old_rsi;
@@ -100,6 +118,7 @@ void DynaCall(x64emu_t* emu, uintptr_t addr)
     }
 }
 
+int my_setcontext(x64emu_t* emu, void* ucp);
 void DynaRun(x64emu_t* emu)
 {
     // prepare setjump for signal handling
@@ -158,6 +177,10 @@ void DynaRun(x64emu_t* emu)
                 emu->fork = 0;
                 emu = x64emu_fork(emu, forktype);
             }
+            if(emu->quit && emu->uc_link) {
+                emu->quit = 0;
+                my_setcontext(emu, emu->uc_link);
+            }
         }
 #endif
         if(emu->flags.need_jmpbuf)
diff --git a/src/emu/x64run.c b/src/emu/x64run.c
index 2296611e..0edfcc08 100644
--- a/src/emu/x64run.c
+++ b/src/emu/x64run.c
@@ -2068,7 +2068,7 @@ if(emu->segs[_CS]!=0x33 && emu->segs[_CS]!=0x23) printf_log(LOG_NONE, "Warning,
         goto x64emurun;
     }
     // setcontext handling
-    else if(emu->uc_link) {
+    else if(emu->quit && emu->uc_link) {
         emu->quit = 0;
         my_setcontext(emu, emu->uc_link);
         addr = R_RIP;
diff --git a/src/libtools/signals.c b/src/libtools/signals.c
index 19c49dab..2145a3e4 100644
--- a/src/libtools/signals.c
+++ b/src/libtools/signals.c
@@ -966,7 +966,7 @@ void my_sigactionhandler_oldcode(int32_t sig, int simple, siginfo_t* info, void
     else if(sig==SIGSEGV) {
         if((uintptr_t)info->si_addr == sigcontext->uc_mcontext.gregs[X64_RIP]) {
             sigcontext->uc_mcontext.gregs[X64_ERR] = (info->si_errno==0x1234)?0:((info->si_errno==0xdead)?(0x2|(info->si_code<<3)):0x0010);    // execution flag issue (probably), unless it's a #GP(0)
-            sigcontext->uc_mcontext.gregs[X64_TRAPNO] = (info->si_code == SEGV_ACCERR || (info->si_errno==0x1234) || (info->si_errno==0xdead) || (uintptr_t)info->si_addr==0)?13:14;
+            sigcontext->uc_mcontext.gregs[X64_TRAPNO] = ((info->si_code==SEGV_ACCERR) || (info->si_errno==0x1234) || (info->si_errno==0xdead) || ((uintptr_t)info->si_addr==0))?13:14;
         } else if(info->si_code==SEGV_ACCERR && !(prot&PROT_WRITE)) {
             sigcontext->uc_mcontext.gregs[X64_ERR] = 0x0002;    // write flag issue
             if(labs((intptr_t)info->si_addr-(intptr_t)sigcontext->uc_mcontext.gregs[X64_RSP])<16)
diff --git a/src/tools/callback.c b/src/tools/callback.c
index 162c801f..341a554d 100644
--- a/src/tools/callback.c
+++ b/src/tools/callback.c
@@ -164,6 +164,13 @@ uint64_t RunSafeFunction(uintptr_t fnc, int nargs, ...)
     Push64(emu, R_R10);
     Push64(emu, R_R11);
     Push64(emu, R_RAX);
+    deferred_flags_t old_df = emu->df;
+    multiuint_t old_op1 = emu->op1;
+    multiuint_t old_op2 = emu->op2;
+    multiuint_t old_res = emu->res;
+    multiuint_t old_op1_sav= emu->op1_sav;
+    multiuint_t old_res_sav= emu->res_sav;
+    deferred_flags_t old_df_sav= emu->df_sav;
 
     R_RSP -= stackn*sizeof(void*);   // need to push in reverse order
 
@@ -200,7 +207,14 @@ uint64_t RunSafeFunction(uintptr_t fnc, int nargs, ...)
 
     R_RSP = old_rbp;          // mov rsp, rbp
     R_RBP = Pop64(emu);     // pop rbp
-    
+
+    emu->df = old_df;
+    emu->op1 = old_op1;
+    emu->op2 = old_op2;
+    emu->res = old_res;
+    emu->op1_sav = old_op1_sav;
+    emu->res_sav = old_res_sav;
+    emu->df_sav = old_df_sav;
 
     return ret;
 }