about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2022-09-29 11:24:42 +0200
committerptitSeb <sebastien.chev@gmail.com>2022-09-29 11:24:42 +0200
commit32c229215aa438bf5a087c2e9a97462fd26208ad (patch)
treea775056684e36404726f7253b860eae0d4600762 /src
parent9c5cc38c9a11c87ae2ef845879cb479f52b9de00 (diff)
downloadbox64-32c229215aa438bf5a087c2e9a97462fd26208ad.tar.gz
box64-32c229215aa438bf5a087c2e9a97462fd26208ad.zip
Improved signal handling and x87 flags (with tests backported from box86)
Diffstat (limited to 'src')
-rw-r--r--src/custommem.c8
-rw-r--r--src/dynarec/arm64/dynarec_arm64_d9.c2
-rwxr-xr-xsrc/dynarec/arm64/dynarec_arm64_helper.c3
-rwxr-xr-xsrc/emu/x64emu.c3
-rwxr-xr-xsrc/emu/x64emu_private.h3
-rw-r--r--src/emu/x64rund9.c5
-rwxr-xr-xsrc/emu/x87emu_private.c14
-rwxr-xr-xsrc/emu/x87emu_private.h2
-rwxr-xr-xsrc/include/regs.h17
-rwxr-xr-xsrc/libtools/signals.c9
10 files changed, 43 insertions, 23 deletions
diff --git a/src/custommem.c b/src/custommem.c
index 0137084e..c3f9e368 100644
--- a/src/custommem.c
+++ b/src/custommem.c
@@ -794,11 +794,12 @@ void protectDB(uintptr_t addr, uintptr_t size)
         }
     for (uintptr_t i=idx; i<=end; ++i) {
         uint32_t prot = memprot[i>>16][i&0xffff];
+        uint32_t dyn = prot&PROT_CUSTOM;
+        prot&=~PROT_CUSTOM;
         if(!prot)
             prot = PROT_READ | PROT_WRITE | PROT_EXEC;      // comes from malloc & co, so should not be able to execute
         if((prot&PROT_WRITE)) {
-            prot&=~(PROT_WRITE | PROT_CUSTOM);
-            mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot);
+            if(!dyn) mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_WRITE);
             memprot[i>>16][i&0xffff] = prot|PROT_DYNAREC;   // need to use atomic exchange?
         } else 
             memprot[i>>16][i&0xffff] = prot|PROT_DYNAREC_R;
@@ -830,7 +831,6 @@ void unprotectDB(uintptr_t addr, size_t size, int mark)
         uint32_t prot = memprot[i>>16][i&0xffff];
         if(prot&PROT_DYNAREC) {
             prot&=~PROT_CUSTOM;
-            prot|=PROT_WRITE;
             if(mark)
                 cleanDBFromAddressRange((i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, 0);
             mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot);
@@ -982,6 +982,8 @@ void updateProtection(uintptr_t addr, size_t size, uint32_t prot)
         if(dyn && (prot&PROT_WRITE)) {   // need to remove the write protection from this block
             dyn = PROT_DYNAREC;
             mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_WRITE);
+        } else if(dyn && !(prot&PROT_WRITE)) {
+            dyn = PROT_DYNAREC_R;
         }
         memprot[i>>16][i&0xffff] = prot|dyn;
     }
diff --git a/src/dynarec/arm64/dynarec_arm64_d9.c b/src/dynarec/arm64/dynarec_arm64_d9.c
index 46ebf60c..63b39b97 100644
--- a/src/dynarec/arm64/dynarec_arm64_d9.c
+++ b/src/dynarec/arm64/dynarec_arm64_d9.c
@@ -373,8 +373,6 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                     INST_NAME("FLDCW Ew");
                     GETEW(x1, 0);
                     STRH_U12(x1, xEmu, offsetof(x64emu_t, cw));    // hopefully cw is not too far for an imm8
-                    UBFXw(x1, x1, 10, 2);    // extract round
-                    STRw_U12(x1, xEmu, offsetof(x64emu_t, round));
                     break;
                 case 6:
                     INST_NAME("FNSTENV Ed");
diff --git a/src/dynarec/arm64/dynarec_arm64_helper.c b/src/dynarec/arm64/dynarec_arm64_helper.c
index 211ddb34..961b0278 100755
--- a/src/dynarec/arm64/dynarec_arm64_helper.c
+++ b/src/dynarec/arm64/dynarec_arm64_helper.c
@@ -1076,7 +1076,8 @@ int x87_setround(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
 {
     MAYUSE(dyn); MAYUSE(ninst);
     MAYUSE(s1); MAYUSE(s2);
-    LDRw_U12(s1, xEmu, offsetof(x64emu_t, round));
+    LDRw_U12(s1, xEmu, offsetof(x64emu_t, cw));
+    BFXILw(s1, s1, 10, 2);
     UBFXw(s2, s1, 1, 1);        // bit 1 of round in bit 0 (zero extented) of s2
     BFIw(s2, s1, 1, 1);         // bit 0 of round in bit 1 of s2
     MRS_fpcr(s1);               // get fpscr
diff --git a/src/emu/x64emu.c b/src/emu/x64emu.c
index a91fe04b..9e4fc7e0 100755
--- a/src/emu/x64emu.c
+++ b/src/emu/x64emu.c
@@ -224,10 +224,9 @@ void CloneEmu(x64emu_t *newemu, const x64emu_t* emu)
     memcpy(newemu->fpu_ll, emu->fpu_ll, sizeof(emu->fpu_ll));
 	memcpy(newemu->p_regs, emu->p_regs, sizeof(emu->p_regs));
 	newemu->cw = emu->cw;
-	memcpy(&newemu->sw, &emu->sw, sizeof(emu->sw));
+	newemu->sw = emu->sw;
 	newemu->top = emu->top;
     newemu->fpu_stack = emu->fpu_stack;
-	memcpy(&newemu->round, &emu->round, sizeof(emu->round));
     memcpy(newemu->xmm, emu->xmm, sizeof(emu->xmm));
     newemu->mxcsr = emu->mxcsr;
     newemu->quit = emu->quit;
diff --git a/src/emu/x64emu_private.h b/src/emu/x64emu_private.h
index 1ffdd1fa..093706bf 100755
--- a/src/emu/x64emu_private.h
+++ b/src/emu/x64emu_private.h
@@ -35,12 +35,11 @@ typedef struct x64emu_s {
     // fpu / mmx
 	mmx87_regs_t x87[8];
 	mmx87_regs_t mmx[8];
-	uint16_t    cw;
+	x87control_t cw;
 	x87flags_t  sw;
 	uint32_t    top;        // top is part of sw, but it's faster to have it separatly
     int         fpu_stack;
     uint32_t    mxcsr;
-	fpu_round_t round;
     fpu_ld_t    fpu_ld[8]; // for long double emulation / 80bits fld fst
     fpu_ll_t    fpu_ll[8]; // for 64bits fild / fist sequence
 	fpu_p_reg_t p_regs[8];
diff --git a/src/emu/x64rund9.c b/src/emu/x64rund9.c
index 34e29879..301f2852 100644
--- a/src/emu/x64rund9.c
+++ b/src/emu/x64rund9.c
@@ -265,9 +265,8 @@ uintptr_t RunD9(x64emu_t *emu, rex_t rex, uintptr_t addr)
                 break;

             case 5:     /* FLDCW Ew */

                 GETEW(0);

-                emu->cw = EW->word[0];

+                emu->cw.x16 = EW->word[0];

                 // do something with cw?

-                emu->round = (fpu_round_t)((emu->cw >> 10) & 3);

                 break;

             case 6:     /* FNSTENV m */

                 // warning, incomplete

@@ -279,7 +278,7 @@ uintptr_t RunD9(x64emu_t *emu, rex_t rex, uintptr_t addr)
                 break;

             case 7: /* FNSTCW Ew */

                 GETEW(0);

-                EW->word[0] = emu->cw;

+                EW->word[0] = emu->cw.x16;

                 break;

             default:

                 return 0;

diff --git a/src/emu/x87emu_private.c b/src/emu/x87emu_private.c
index f151ee45..846016c8 100755
--- a/src/emu/x87emu_private.c
+++ b/src/emu/x87emu_private.c
@@ -23,7 +23,7 @@ void reset_fpu(x64emu_t* emu)
 {
     memset(emu->x87, 0, sizeof(emu->x87));
     memset(emu->fpu_ld, 0, sizeof(emu->fpu_ld));
-    emu->cw = 0x37F;
+    emu->cw.x16 = 0x37F;
     emu->sw.x16 = 0x0000;
     emu->top = 0;
     emu->fpu_stack = 0;
@@ -223,7 +223,7 @@ long double LD2localLD(void* ld)
 
 void fpu_loadenv(x64emu_t* emu, char* p, int b16)
 {
-    emu->cw = *(uint16_t*)p;
+    emu->cw.x16 = *(uint16_t*)p;
     p+=(b16)?2:4;
     emu->sw.x16 = *(uint16_t*)p;
     emu->top = emu->sw.f.F87_TOP;
@@ -241,7 +241,7 @@ void fpu_loadenv(x64emu_t* emu, char* p, int b16)
 void fpu_savenv(x64emu_t* emu, char* p, int b16)
 {
     emu->sw.f.F87_TOP = emu->top&7;
-    *(uint16_t*)p = emu->cw;
+    *(uint16_t*)p = emu->cw.x16;
     p+=2;
     if(!b16) {*(uint16_t*)p = 0; p+=2;}
     *(uint16_t*)p = emu->sw.x16;
@@ -299,7 +299,7 @@ void fpu_fxsave32(x64emu_t* emu, void* ed)
     if(top==0)  // check if stack is full or empty, based on tag[0]
         stack = (emu->p_regs[0].tag)?8:0;
     emu->sw.f.F87_TOP = top;
-    p->ControlWord = emu->cw;
+    p->ControlWord = emu->cw.x16;
     p->StatusWord = emu->sw.x16;
     uint8_t tags = 0;
     for (int i=0; i<8; ++i)
@@ -328,7 +328,7 @@ void fpu_fxsave64(x64emu_t* emu, void* ed)
     if(top==0)  // check if stack is full or empty, based on tag[0]
         stack = (emu->p_regs[0].tag)?8:0;
     emu->sw.f.F87_TOP = top;
-    p->ControlWord = emu->cw;
+    p->ControlWord = emu->cw.x16;
     p->StatusWord = emu->sw.x16;
     uint8_t tags = 0;
     for (int i=0; i<8; ++i)
@@ -349,7 +349,7 @@ void fpu_fxsave64(x64emu_t* emu, void* ed)
 void fpu_fxrstor32(x64emu_t* emu, void* ed)
 {
     xsave32_t *p = (xsave32_t*)ed;
-    emu->cw = p->ControlWord;
+    emu->cw.x16 = p->ControlWord;
     emu->sw.x16 = p->StatusWord;
     emu->top = emu->sw.f.F87_TOP;
     uint8_t tags = p->TagWord;
@@ -369,7 +369,7 @@ void fpu_fxrstor32(x64emu_t* emu, void* ed)
 void fpu_fxrstor64(x64emu_t* emu, void* ed)
 {
     xsave64_t *p = (xsave64_t*)ed;
-    emu->cw = p->ControlWord;
+    emu->cw.x16 = p->ControlWord;
     emu->sw.x16 = p->StatusWord;
     emu->top = emu->sw.f.F87_TOP;
     uint8_t tags = p->TagWord;
diff --git a/src/emu/x87emu_private.h b/src/emu/x87emu_private.h
index 7d64bf27..a2287059 100755
--- a/src/emu/x87emu_private.h
+++ b/src/emu/x87emu_private.h
@@ -107,7 +107,7 @@ static inline void fpu_fcomi(x64emu_t* emu, double b)
 static inline double fpu_round(x64emu_t* emu, double d) {
     if (!isfinite(d))
         return d;
-    switch(emu->round) {
+    switch(emu->cw.f.C87_RD) {
         case ROUND_Nearest:
             return nearbyint(d);
         case ROUND_Down:
diff --git a/src/include/regs.h b/src/include/regs.h
index d7ae0250..d66e8065 100755
--- a/src/include/regs.h
+++ b/src/include/regs.h
@@ -242,6 +242,23 @@ typedef union {
 } x87flags_t;
 
 typedef union {
+    struct __attribute__ ((__packed__)) {
+        unsigned int C87_IM:1;	// interupt masks
+        unsigned int C87_DM:1;
+        unsigned int C87_ZM:1;
+        unsigned int C87_OM:1;
+        unsigned int C87_UM:1;
+        unsigned int C87_PM:1;
+        unsigned int C87_R1:2;	// reserved
+        unsigned int C87_PC:2;	// precision control (24bits, reserved, 53bits, 64bits)
+        unsigned int C87_RD:2;	// Rounds
+		unsigned int C87_IC:1;
+		unsigned int C87_R2:3;	// reserved
+    } f;
+    uint16_t    x16;
+} x87control_t;
+
+typedef union {
 	uint64_t	q;
 	int64_t		sq;
 	double		d;
diff --git a/src/libtools/signals.c b/src/libtools/signals.c
index 224260b5..68adee35 100755
--- a/src/libtools/signals.c
+++ b/src/libtools/signals.c
@@ -485,10 +485,15 @@ void my_sigactionhandler_oldcode(int32_t sig, int simple, siginfo_t* info, void
             used_stack = 1;
             new_ss->ss_flags = SS_ONSTACK;
         }
+    } else {
+        frame -= 0x200; // redzone
     }
 
     // TODO: do I need to really setup 2 stack frame? That doesn't seems right!
     // setup stack frame
+    frame -= sizeof(siginfo_t)/sizeof(uintptr_t);
+    siginfo_t* info2 = (siginfo_t*)frame;
+    memcpy(info2, info, sizeof(siginfo_t));
     // try to fill some sigcontext....
     frame -= sizeof(x64_ucontext_t);
     x64_ucontext_t   *sigcontext = (x64_ucontext_t*)frame;
@@ -640,7 +645,7 @@ void my_sigactionhandler_oldcode(int32_t sig, int simple, siginfo_t* info, void
     if (simple)
         ret = RunFunctionHandler(&exits, sigcontext, my_context->signals[sig], 1, sig);
     else
-        ret = RunFunctionHandler(&exits, sigcontext, my_context->signals[sig], 3, sig, info, sigcontext);
+        ret = RunFunctionHandler(&exits, sigcontext, my_context->signals[sig], 3, sig, info2, sigcontext);
     // restore old value from emu
     #define GO(A) R_##A = old_##A
     GO(RAX);
@@ -885,7 +890,7 @@ void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
             return;
         }
         pthread_mutex_unlock(&mutex_dynarec_prot);
-    } else if ((sig==SIGSEGV) && (addr) && (info->si_code == SEGV_ACCERR) && (prot&(PROT_READ|PROT_WRITE)==(PROT_READ|PROT_WRITE))) {
+    } else if ((sig==SIGSEGV) && (addr) && (info->si_code == SEGV_ACCERR) && ((prot&(PROT_READ|PROT_WRITE))==(PROT_READ|PROT_WRITE))) {
         pthread_mutex_lock(&mutex_dynarec_prot);
         db = FindDynablockFromNativeAddress(pc);
         db_searched = 1;