about summary refs log tree commit diff stats
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
parent9c5cc38c9a11c87ae2ef845879cb479f52b9de00 (diff)
downloadbox64-32c229215aa438bf5a087c2e9a97462fd26208ad.tar.gz
box64-32c229215aa438bf5a087c2e9a97462fd26208ad.zip
Improved signal handling and x87 flags (with tests backported from box86)
-rwxr-xr-xCMakeLists.txt10
-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
-rw-r--r--tests/ref21.txt2
-rw-r--r--tests/ref22.txt222
-rwxr-xr-xtests/test21bin0 -> 19088 bytes
-rw-r--r--tests/test21.c30
-rwxr-xr-xtests/test22bin0 -> 21568 bytes
-rw-r--r--tests/test22.c146
17 files changed, 453 insertions, 23 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b3c4783f..781943b6 100755
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -772,6 +772,16 @@ add_test(irelative_reloc ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${
     -D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref20.txt
     -P ${CMAKE_SOURCE_DIR}/runTest.cmake )
 
+    add_test(longjumpInSignals ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
+    -D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test21 -D TEST_OUTPUT=tmpfile21.txt
+    -D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref21.txt
+    -P ${CMAKE_SOURCE_DIR}/runTest.cmake )
+
+    add_test(x87 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
+    -D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test22 -D TEST_OUTPUT=tmpfile22.txt
+    -D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref22.txt
+    -P ${CMAKE_SOURCE_DIR}/runTest.cmake )
+
     file(GLOB extension_tests "${CMAKE_SOURCE_DIR}/tests/extensions/*.c")
 foreach(file ${extension_tests})
     get_filename_component(testname "${file}" NAME_WE)
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;
diff --git a/tests/ref21.txt b/tests/ref21.txt
new file mode 100644
index 00000000..38e983ce
--- /dev/null
+++ b/tests/ref21.txt
@@ -0,0 +1,2 @@
+sig = 11
+got bad_ptr
diff --git a/tests/ref22.txt b/tests/ref22.txt
new file mode 100644
index 00000000..0b90c207
--- /dev/null
+++ b/tests/ref22.txt
@@ -0,0 +1,222 @@
+FUCOMI 0x0 0x4082c00000000000 --C
+FUCOMPP 0x0 0x4082c00000000000 --C
+FRNDINT 0x0 => 0x0
+FRNDINT 0x4082c00000000000 => 0x4082c00000000000
+FISTP 0x0 => word: 0
+FISTP 0x4082c00000000000 => word: 258
+FISTP 0x0 => long: 0
+FISTP 0x4082c00000000000 => long: 258
+FISTP 0x0 => quad: 0
+FISTP 0x4082c00000000000 => quad: 258
+FUCOMI 0x4082c00000000000 0x0 ---
+FUCOMPP 0x4082c00000000000 0x0 ---
+FRNDINT 0x4082c00000000000 => 0x4082c00000000000
+FRNDINT 0x0 => 0x0
+FISTP 0x4082c00000000000 => word: 258
+FISTP 0x0 => word: 0
+FISTP 0x4082c00000000000 => long: 258
+FISTP 0x0 => long: 0
+FISTP 0x4082c00000000000 => quad: 258
+FISTP 0x0 => quad: 0
+FUCOMI 0x8000000000000000 0x4082c00000000000 --C
+FUCOMPP 0x8000000000000000 0x4082c00000000000 --C
+FRNDINT 0x8000000000000000 => 0x8000000000000000
+FRNDINT 0x4082c00000000000 => 0x4082c00000000000
+FISTP 0x8000000000000000 => word: 0
+FISTP 0x4082c00000000000 => word: 258
+FISTP 0x8000000000000000 => long: 0
+FISTP 0x4082c00000000000 => long: 258
+FISTP 0x8000000000000000 => quad: 0
+FISTP 0x4082c00000000000 => quad: 258
+FUCOMI 0x4082c00000000000 0x8000000000000000 ---
+FUCOMPP 0x4082c00000000000 0x8000000000000000 ---
+FRNDINT 0x4082c00000000000 => 0x4082c00000000000
+FRNDINT 0x8000000000000000 => 0x8000000000000000
+FISTP 0x4082c00000000000 => word: 258
+FISTP 0x8000000000000000 => word: 0
+FISTP 0x4082c00000000000 => long: 258
+FISTP 0x8000000000000000 => long: 0
+FISTP 0x4082c00000000000 => quad: 258
+FISTP 0x8000000000000000 => quad: 0
+FUCOMI 0x8000000000000000 0x0 Z--
+FUCOMPP 0x8000000000000000 0x0 Z--
+FRNDINT 0x8000000000000000 => 0x8000000000000000
+FRNDINT 0x0 => 0x0
+FISTP 0x8000000000000000 => word: 0
+FISTP 0x0 => word: 0
+FISTP 0x8000000000000000 => long: 0
+FISTP 0x0 => long: 0
+FISTP 0x8000000000000000 => quad: 0
+FISTP 0x0 => quad: 0
+FUCOMI 0x0 0x8000000000000000 Z--
+FUCOMPP 0x0 0x8000000000000000 Z--
+FRNDINT 0x0 => 0x0
+FRNDINT 0x8000000000000000 => 0x8000000000000000
+FISTP 0x0 => word: 0
+FISTP 0x8000000000000000 => word: 0
+FISTP 0x0 => long: 0
+FISTP 0x8000000000000000 => long: 0
+FISTP 0x0 => quad: 0
+FISTP 0x8000000000000000 => quad: 0
+FUCOMI 0x8000000000000000 0x3ff0000000000000 --C
+FUCOMPP 0x8000000000000000 0x3ff0000000000000 --C
+FRNDINT 0x8000000000000000 => 0x8000000000000000
+FRNDINT 0x3ff0000000000000 => 0x3ff0000000000000
+FISTP 0x8000000000000000 => word: 0
+FISTP 0x3ff0000000000000 => word: 1
+FISTP 0x8000000000000000 => long: 0
+FISTP 0x3ff0000000000000 => long: 1
+FISTP 0x8000000000000000 => quad: 0
+FISTP 0x3ff0000000000000 => quad: 1
+FUCOMI 0x3ff0000000000000 0x8000000000000000 ---
+FUCOMPP 0x3ff0000000000000 0x8000000000000000 ---
+FRNDINT 0x3ff0000000000000 => 0x3ff0000000000000
+FRNDINT 0x8000000000000000 => 0x8000000000000000
+FISTP 0x3ff0000000000000 => word: 1
+FISTP 0x8000000000000000 => word: 0
+FISTP 0x3ff0000000000000 => long: 1
+FISTP 0x8000000000000000 => long: 0
+FISTP 0x3ff0000000000000 => quad: 1
+FISTP 0x8000000000000000 => quad: 0
+FUCOMI 0x3ff0000000000000 0x3fe89d9000000000 ---
+FUCOMPP 0x3ff0000000000000 0x3fe89d9000000000 ---
+FRNDINT 0x3ff0000000000000 => 0x3ff0000000000000
+FRNDINT 0x3fe89d9000000000 => 0x0
+FISTP 0x3ff0000000000000 => word: 1
+FISTP 0x3fe89d9000000000 => word: 0
+FISTP 0x3ff0000000000000 => long: 1
+FISTP 0x3fe89d9000000000 => long: 0
+FISTP 0x3ff0000000000000 => quad: 1
+FISTP 0x3fe89d9000000000 => quad: 0
+FUCOMI 0x3fe89d9000000000 0x3ff0000000000000 --C
+FUCOMPP 0x3fe89d9000000000 0x3ff0000000000000 --C
+FRNDINT 0x3fe89d9000000000 => 0x0
+FRNDINT 0x3ff0000000000000 => 0x3ff0000000000000
+FISTP 0x3fe89d9000000000 => word: 0
+FISTP 0x3ff0000000000000 => word: 1
+FISTP 0x3fe89d9000000000 => long: 0
+FISTP 0x3ff0000000000000 => long: 1
+FISTP 0x3fe89d9000000000 => quad: 0
+FISTP 0x3ff0000000000000 => quad: 1
+FUCOMI 0x3ff0000000000000 0x7ff0000000000000 --C
+FUCOMPP 0x3ff0000000000000 0x7ff0000000000000 --C
+FRNDINT 0x3ff0000000000000 => 0x3ff0000000000000
+FRNDINT 0x7ff0000000000000 => 0x7ff0000000000000
+FISTP 0x3ff0000000000000 => word: 1
+FISTP 0x7ff0000000000000 => word: 8000
+FISTP 0x3ff0000000000000 => long: 1
+FISTP 0x7ff0000000000000 => long: 80000000
+FISTP 0x3ff0000000000000 => quad: 1
+FISTP 0x7ff0000000000000 => quad: 8000000000000000
+FUCOMI 0x7ff0000000000000 0x3ff0000000000000 ---
+FUCOMPP 0x7ff0000000000000 0x3ff0000000000000 ---
+FRNDINT 0x7ff0000000000000 => 0x7ff0000000000000
+FRNDINT 0x3ff0000000000000 => 0x3ff0000000000000
+FISTP 0x7ff0000000000000 => word: 8000
+FISTP 0x3ff0000000000000 => word: 1
+FISTP 0x7ff0000000000000 => long: 80000000
+FISTP 0x3ff0000000000000 => long: 1
+FISTP 0x7ff0000000000000 => quad: 8000000000000000
+FISTP 0x3ff0000000000000 => quad: 1
+FUCOMI 0xfff0000000000000 0x7ff0000000000000 --C
+FUCOMPP 0xfff0000000000000 0x7ff0000000000000 --C
+FRNDINT 0xfff0000000000000 => 0xfff0000000000000
+FRNDINT 0x7ff0000000000000 => 0x7ff0000000000000
+FISTP 0xfff0000000000000 => word: 8000
+FISTP 0x7ff0000000000000 => word: 8000
+FISTP 0xfff0000000000000 => long: 80000000
+FISTP 0x7ff0000000000000 => long: 80000000
+FISTP 0xfff0000000000000 => quad: 8000000000000000
+FISTP 0x7ff0000000000000 => quad: 8000000000000000
+FUCOMI 0x7ff0000000000000 0xfff0000000000000 ---
+FUCOMPP 0x7ff0000000000000 0xfff0000000000000 ---
+FRNDINT 0x7ff0000000000000 => 0x7ff0000000000000
+FRNDINT 0xfff0000000000000 => 0xfff0000000000000
+FISTP 0x7ff0000000000000 => word: 8000
+FISTP 0xfff0000000000000 => word: 8000
+FISTP 0x7ff0000000000000 => long: 80000000
+FISTP 0xfff0000000000000 => long: 80000000
+FISTP 0x7ff0000000000000 => quad: 8000000000000000
+FISTP 0xfff0000000000000 => quad: 8000000000000000
+FUCOMI 0x3ff0002ca0000000 0xaeff000025000000 ---
+FUCOMPP 0x3ff0002ca0000000 0xaeff000025000000 ---
+FRNDINT 0x3ff0002ca0000000 => 0x3ff0000000000000
+FRNDINT 0xaeff000025000000 => 0x8000000000000000
+FISTP 0x3ff0002ca0000000 => word: 1
+FISTP 0xaeff000025000000 => word: 0
+FISTP 0x3ff0002ca0000000 => long: 1
+FISTP 0xaeff000025000000 => long: 0
+FISTP 0x3ff0002ca0000000 => quad: 1
+FISTP 0xaeff000025000000 => quad: 0
+FUCOMI 0xaeff000025000000 0x3ff0002ca0000000 --C
+FUCOMPP 0xaeff000025000000 0x3ff0002ca0000000 --C
+FRNDINT 0xaeff000025000000 => 0x8000000000000000
+FRNDINT 0x3ff0002ca0000000 => 0x3ff0000000000000
+FISTP 0xaeff000025000000 => word: 0
+FISTP 0x3ff0002ca0000000 => word: 1
+FISTP 0xaeff000025000000 => long: 0
+FISTP 0x3ff0002ca0000000 => long: 1
+FISTP 0xaeff000025000000 => quad: 0
+FISTP 0x3ff0002ca0000000 => quad: 1
+FUCOMI 0x3ff0000050000000 0xc082c00000000000 ---
+FUCOMPP 0x3ff0000050000000 0xc082c00000000000 ---
+FRNDINT 0x3ff0000050000000 => 0x3ff0000000000000
+FRNDINT 0xc082c00000000000 => 0xc082c00000000000
+FISTP 0x3ff0000050000000 => word: 1
+FISTP 0xc082c00000000000 => word: fda8
+FISTP 0x3ff0000050000000 => long: 1
+FISTP 0xc082c00000000000 => long: fffffda8
+FISTP 0x3ff0000050000000 => quad: 1
+FISTP 0xc082c00000000000 => quad: fffffffffffffda8
+FUCOMI 0xc082c00000000000 0x3ff0000050000000 --C
+FUCOMPP 0xc082c00000000000 0x3ff0000050000000 --C
+FRNDINT 0xc082c00000000000 => 0xc082c00000000000
+FRNDINT 0x3ff0000050000000 => 0x3ff0000000000000
+FISTP 0xc082c00000000000 => word: fda8
+FISTP 0x3ff0000050000000 => word: 1
+FISTP 0xc082c00000000000 => long: fffffda8
+FISTP 0x3ff0000050000000 => long: 1
+FISTP 0xc082c00000000000 => quad: fffffffffffffda8
+FISTP 0x3ff0000050000000 => quad: 1
+FUCOMI 0x0 0x7ff8000000000001 ZPC
+FUCOMPP 0x0 0x7ff8000000000001 ZPC
+FRNDINT 0x0 => 0x0
+FRNDINT 0x7ff8000000000001 => 0x7ff8000000000001
+FISTP 0x0 => word: 0
+FISTP 0x7ff8000000000001 => word: 8000
+FISTP 0x0 => long: 0
+FISTP 0x7ff8000000000001 => long: 80000000
+FISTP 0x0 => quad: 0
+FISTP 0x7ff8000000000001 => quad: 8000000000000000
+FUCOMI 0x7ff8000000000001 0x0 ZPC
+FUCOMPP 0x7ff8000000000001 0x0 ZPC
+FRNDINT 0x7ff8000000000001 => 0x7ff8000000000001
+FRNDINT 0x0 => 0x0
+FISTP 0x7ff8000000000001 => word: 8000
+FISTP 0x0 => word: 0
+FISTP 0x7ff8000000000001 => long: 80000000
+FISTP 0x0 => long: 0
+FISTP 0x7ff8000000000001 => quad: 8000000000000000
+FISTP 0x0 => quad: 0
+FUCOMI 0x7ff8000000000001 0x7ff8000000000001 ZPC
+FUCOMPP 0x7ff8000000000001 0x7ff8000000000001 ZPC
+FRNDINT 0x7ff8000000000001 => 0x7ff8000000000001
+FRNDINT 0x7ff8000000000001 => 0x7ff8000000000001
+FISTP 0x7ff8000000000001 => word: 8000
+FISTP 0x7ff8000000000001 => word: 8000
+FISTP 0x7ff8000000000001 => long: 80000000
+FISTP 0x7ff8000000000001 => long: 80000000
+FISTP 0x7ff8000000000001 => quad: 8000000000000000
+FISTP 0x7ff8000000000001 => quad: 8000000000000000
+FUCOMI 0x7ff8000000000001 0x7ff8000000000001 ZPC
+FUCOMPP 0x7ff8000000000001 0x7ff8000000000001 ZPC
+FRNDINT 0x7ff8000000000001 => 0x7ff8000000000001
+FRNDINT 0x7ff8000000000001 => 0x7ff8000000000001
+FISTP 0x7ff8000000000001 => word: 8000
+FISTP 0x7ff8000000000001 => word: 8000
+FISTP 0x7ff8000000000001 => long: 80000000
+FISTP 0x7ff8000000000001 => long: 80000000
+FISTP 0x7ff8000000000001 => quad: 8000000000000000
+FISTP 0x7ff8000000000001 => quad: 8000000000000000
+
+Done
diff --git a/tests/test21 b/tests/test21
new file mode 100755
index 00000000..71760a7d
--- /dev/null
+++ b/tests/test21
Binary files differdiff --git a/tests/test21.c b/tests/test21.c
new file mode 100644
index 00000000..803f0142
--- /dev/null
+++ b/tests/test21.c
@@ -0,0 +1,30 @@
+#include <signal.h>
+#include <setjmp.h>
+#include <stdio.h>
+
+static jmp_buf context_buf;
+
+static void segv_handler(int sig)
+{
+	printf("sig = %d\n", sig);
+	longjmp(context_buf, 1);
+}
+
+void test()
+{
+	if(!setjmp(context_buf)) {
+		int *bad_ptr = (int*)0xffffffffdeadbeef;
+		printf("*bad_ptr = %d\n", *bad_ptr);
+	} else {
+		printf("got bad_ptr\n");
+	}
+}
+
+int main()
+{
+	if(signal(SIGSEGV, segv_handler) == SIG_ERR)
+		printf("Err = %m\n");
+	//printf("handler = %p\n", segv_handler);
+	test();
+	return 0;
+}
diff --git a/tests/test22 b/tests/test22
new file mode 100755
index 00000000..4e84cb56
--- /dev/null
+++ b/tests/test22
Binary files differdiff --git a/tests/test22.c b/tests/test22.c
new file mode 100644
index 00000000..68bd41c6
--- /dev/null
+++ b/tests/test22.c
@@ -0,0 +1,146 @@
+#include <string.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <math.h>
+
+#if defined(__x86_64__)
+uint64_t _fucomip_(double a, double b)
+{
+    uint32_t ret;
+    asm volatile (
+    "fldl %2\n"
+    "fldl %1\n"
+    "fucomip %%st(1)\n"
+    "fstp %%st(0)\n"
+    "pushf\n"
+    "pop %%rax\n"
+    :"=a" (ret):"m"(a), "m"(b):"cc");
+    return ret;
+}
+uint64_t _fucompp_(double a, double b)
+{
+    uint32_t ret;
+    asm volatile (
+    "fldl %2\n"
+    "fldl %1\n"
+    "fucompp\n"
+    "fstsw %%ax\n"
+    :"=a" (ret):"m"(a), "m"(b):"cc");
+    return ret;
+}
+uint64_t _fistpw_(double a)
+{
+    uint16_t ret;
+    uint16_t t1, t2;
+    asm volatile (
+    "fldl %1\n"
+    "fstcw %2\n"
+    "mov %2, %%ax\n"
+    "mov $0x0c, %%ah\n"
+    "mov %%ax, %3\n"
+    "fldcw %3\n"
+    "fistp %0\n"
+    "fldcw %2\n"
+    :"=m" (ret):"m"(a), "m"(t1), "m"(t2):"cc");
+    return ret;
+}
+uint64_t _fistpl_(double a)
+{
+    uint32_t ret;
+    uint16_t t1, t2;
+    asm volatile (
+    "fldl %1\n"
+    "fstcw %2\n"
+    "mov %2, %%ax\n"
+    "mov $0x0c, %%ah\n"
+    "mov %%ax, %3\n"
+    "fldcw %3\n"
+    "fistpl %0\n"
+    "fldcw %2\n"
+    :"=m" (ret):"m"(a), "m"(t1), "m"(t2):"cc");
+    return ret;
+}
+uint64_t _fistpq_(double a)
+{
+    uint64_t ret;
+    uint16_t t1, t2;
+    asm volatile (
+    "fldl %1\n"
+    "fstcw %2\n"
+    "mov %2, %%ax\n"
+    "mov $0x0c, %%ah\n"
+    "mov %%ax, %3\n"
+    "fldcw %3\n"
+    "fistpq %0\n"
+    "fldcw %2\n"
+    :"=m" (ret):"m"(a), "m"(t1), "m"(t2):"cc");
+    return ret;
+}
+uint64_t _frndint_(double a)
+{
+    uint64_t ret;
+    uint16_t t1, t2;
+    asm volatile (
+    "fldl %1\n"
+    "fstcw %2\n"
+    "mov %2, %%ax\n"
+    "mov $0x0c, %%ah\n"
+    "mov %%ax, %3\n"
+    "fldcw %3\n"
+    "frndint\n"
+    "fstpl %0\n"
+    "fldcw %2\n"
+    :"=m" (ret):"m"(a), "m"(t1), "m"(t2):"cc");
+    return ret;
+}
+#endif
+
+int main(int argc, const char** argv)
+{
+ double a, b;
+ char pf, cf, zf;
+ char pa, ca, za;
+ uint64_t flags;
+ uint64_t tests[][2] = {
+  {0x0, 0x4082c00000000000LL},
+  {0x8000000000000000LL, 0x4082c00000000000LL},
+  {0x8000000000000000LL, 0x0},
+  {0x8000000000000000LL, 0x3ff0000000000000LL},
+  {0x3ff0000000000000LL, 0x3fe89d9000000000LL},
+  {0x3ff0000000000000LL, 0x7ff0000000000000LL},
+  {0xfff0000000000000LL, 0x7ff0000000000000LL},
+  {0x3ff0002ca0000000LL, 0xaeff000025000000LL},
+  {0x3ff0000050000000LL, 0xc082c00000000000LL},
+  {0x0, 0x7ff8000000000001LL},
+  {0x7ff8000000000001LL, 0x7ff8000000000001LL},
+ };
+ int n = sizeof(tests)/sizeof(tests[0]); 
+ for(int i=0; i<n; ++i)
+  for(int j=0; j<2; ++j) {
+   *(uint64_t*)&a = tests[i][0+j];
+   *(uint64_t*)&b = tests[i][1-j];
+   printf("FUCOMI 0x%llx 0x%llx ", *(uint64_t*)&a, *(uint64_t*)&b);
+   flags = _fucomip_(a, b);
+   ca = (flags>>0)&1?'C':'-';
+   za = (flags>>(0+6))&1?'Z':'-';
+   pa = (flags>>(0+2))&1?'P':'-';
+   printf("%c%c%c\n", za, pa, ca);
+   printf("FUCOMPP 0x%llx 0x%llx ", *(uint64_t*)&a, *(uint64_t*)&b);
+   flags = _fucompp_(a, b);
+   ca = (flags>>8)&1?'C':'-';
+   za = (flags>>(8+6))&1?'Z':'-';
+   pa = (flags>>(8+2))&1?'P':'-';
+   printf("%c%c%c\n", za, pa, ca);
+   printf("FRNDINT 0x%llx => 0x%llx\n", *(uint64_t*)&a, _frndint_(a));
+   printf("FRNDINT 0x%llx => 0x%llx\n", *(uint64_t*)&b, _frndint_(b));
+   printf("FISTP 0x%llx => word: %x\n", *(uint64_t*)&a, _fistpw_(a));
+   printf("FISTP 0x%llx => word: %x\n", *(uint64_t*)&b, _fistpw_(b));
+   printf("FISTP 0x%llx => long: %x\n", *(uint64_t*)&a, _fistpl_(a));
+   printf("FISTP 0x%llx => long: %x\n", *(uint64_t*)&b, _fistpl_(b));
+   printf("FISTP 0x%llx => quad: %llx\n", *(uint64_t*)&a, _fistpq_(a));
+   printf("FISTP 0x%llx => quad: %llx\n", *(uint64_t*)&b, _fistpq_(b));
+ }
+ printf("\nDone\n");
+}