about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2021-03-07 11:44:09 +0100
committerptitSeb <sebastien.chev@gmail.com>2021-03-07 11:44:09 +0100
commit2a514f14c13c93c32b5ba01a5a3cae811e9f3e0e (patch)
treedd0e0f51100d8144fda9bb832bde9e8ff633e108 /src
parent395d9eb6224841edf72d5494bf306cf1ff79915e (diff)
downloadbox64-2a514f14c13c93c32b5ba01a5a3cae811e9f3e0e.tar.gz
box64-2a514f14c13c93c32b5ba01a5a3cae811e9f3e0e.zip
Reworked FPU/MMX regs, added Context and Signal handling (and test13 works)
Diffstat (limited to 'src')
-rwxr-xr-xsrc/box64context.c5
-rwxr-xr-xsrc/emu/x64emu.c7
-rwxr-xr-xsrc/emu/x64emu_private.h16
-rwxr-xr-xsrc/emu/x64run.c13
-rwxr-xr-xsrc/emu/x64run_private.c10
-rwxr-xr-xsrc/emu/x64run_private.h4
-rw-r--r--src/emu/x64rund9.c10
-rw-r--r--src/emu/x64rundb.c12
-rwxr-xr-xsrc/emu/x87emu_private.c149
-rwxr-xr-xsrc/emu/x87emu_private.h16
-rwxr-xr-xsrc/include/regs.h17
-rwxr-xr-xsrc/include/signals.h41
-rwxr-xr-xsrc/libtools/signals.c1156
-rw-r--r--src/wrapped/generated/functions_list.txt2
-rw-r--r--src/wrapped/generated/wrapper.c4
-rw-r--r--src/wrapped/generated/wrapper.h2
-rwxr-xr-xsrc/wrapped/wrappedlibc.c3
-rwxr-xr-xsrc/wrapped/wrappedlibc_private.h12
18 files changed, 1355 insertions, 124 deletions
diff --git a/src/box64context.c b/src/box64context.c
index 75fb5028..3a5e0c25 100755
--- a/src/box64context.c
+++ b/src/box64context.c
@@ -17,6 +17,7 @@
 #include "library.h"
 #include "wrapper.h"
 #include "x64emu.h"
+#include "signals.h"
 
 EXPORTDYN
 void initAllHelpers(box64context_t* context)
@@ -26,7 +27,7 @@ void initAllHelpers(box64context_t* context)
         return;
     my_context = context;
     init_pthread_helper();
-    //init_signal_helper(context);
+    init_signal_helper(context);
     inited = 1;
 }
 
@@ -37,7 +38,7 @@ void finiAllHelpers(box64context_t* context)
     if(finied)
         return;
     fini_pthread_helper(context);
-    //fini_signal_helper();
+    fini_signal_helper();
     cleanAlternate();
     fini_custommem_helper(context);
     finied = 1;
diff --git a/src/emu/x64emu.c b/src/emu/x64emu.c
index 80752a0a..60cceacb 100755
--- a/src/emu/x64emu.c
+++ b/src/emu/x64emu.c
@@ -205,7 +205,7 @@ void CloneEmu(x64emu_t *newemu, const x64emu_t* emu)
     newemu->old_ip = emu->old_ip;
     memcpy(newemu->segs, emu->segs, sizeof(emu->segs));
     memset(newemu->segs_serial, 0, sizeof(newemu->segs_serial));
-	memcpy(newemu->fpu, emu->fpu, sizeof(emu->fpu));
+	memcpy(newemu->mmx87, emu->mmx87, sizeof(emu->mmx87));
     memcpy(newemu->fpu_ld, emu->fpu_ld, sizeof(emu->fpu_ld));
     memcpy(newemu->fpu_ll, emu->fpu_ll, sizeof(emu->fpu_ll));
 	memcpy(newemu->p_regs, emu->p_regs, sizeof(emu->p_regs));
@@ -215,7 +215,6 @@ void CloneEmu(x64emu_t *newemu, const x64emu_t* emu)
 	newemu->top = emu->top;
     newemu->fpu_stack = emu->fpu_stack;
 	memcpy(&newemu->round, &emu->round, sizeof(emu->round));
-    memcpy(newemu->mmx, emu->mmx, sizeof(emu->mmx));
     memcpy(newemu->xmm, emu->xmm, sizeof(emu->xmm));
     newemu->mxcsr = emu->mxcsr;
     newemu->quit = emu->quit;
@@ -336,7 +335,7 @@ const char* DumpCPURegs(x64emu_t* emu, uintptr_t ip)
     if(trace_emm) {
         // do emm reg is needed
         for(int i=0; i<8; ++i) {
-            sprintf(tmp, "mm%d:%016lx", i, emu->mmx[i].q);
+            sprintf(tmp, "mm%d:%016lx", i, emu->mmx87[i].q);
             strcat(buff, tmp);
             if ((i&3)==3) strcat(buff, "\n"); else strcat(buff, " ");
         }
@@ -352,7 +351,7 @@ const char* DumpCPURegs(x64emu_t* emu, uintptr_t ip)
     // start with FPU regs...
     if(emu->fpu_stack) {
         for (int i=0; i<emu->fpu_stack; i++) {
-            sprintf(tmp, "ST%d=%f", i, emu->fpu[(emu->top+i)&7].d);
+            sprintf(tmp, "ST%d=%f", i, emu->mmx87[(emu->top+i)&7].d);
             strcat(buff, tmp);
             int c = 10-strlen(tmp);
             if(c<1) c=1;
diff --git a/src/emu/x64emu_private.h b/src/emu/x64emu_private.h
index 8e804981..113b722d 100755
--- a/src/emu/x64emu_private.h
+++ b/src/emu/x64emu_private.h
@@ -4,7 +4,7 @@
 #include "regs.h"
 
 typedef struct box64context_s box64context_t;
-//typedef struct i386_ucontext_s i386_ucontext_t;
+typedef struct x64_ucontext_s x64_ucontext_t;
 
 #define ERR_UNIMPL  1
 #define ERR_DIVBY0  2
@@ -29,18 +29,16 @@ typedef struct x64emu_s {
 	x86flags_t  eflags;
     reg64_t     ip;
     uintptr_t   old_ip;
-    // fpu
-	fpu_reg_t   fpu[9];
+    // fpu / mmx
+	mmx87_regs_t mmx87[8];
 	uint16_t    cw,cw_mask_all;
 	x87flags_t  sw;
 	uint32_t    top;        // top is part of sw, but it's faster to have it separatly
     int         fpu_stack;
 	fpu_round_t round;
-    fpu_ld_t    fpu_ld[9]; // for long double emulation / 80bits fld fst
-    fpu_ll_t    fpu_ll[9]; // for 64bits fild / fist sequence
-	fpu_p_reg_t p_regs[9];
-    // mmx
-    mmx_regs_t  mmx[8];
+    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];
     // sse
     sse_regs_t  xmm[16];
     uint32_t    mxcsr;
@@ -77,7 +75,7 @@ typedef struct x64emu_s {
     void*       init_stack; // initial stack (owned or not)
     uint32_t    size_stack; // stack size (owned or not)
 
-    //i386_ucontext_t *uc_link; // to handle setcontext
+    x64_ucontext_t *uc_link; // to handle setcontext
 
     int         type;       // EMUTYPE_xxx define
 
diff --git a/src/emu/x64run.c b/src/emu/x64run.c
index 0795cdb9..9c465d54 100755
--- a/src/emu/x64run.c
+++ b/src/emu/x64run.c
@@ -18,9 +18,8 @@
 #include "x64trace.h"
 #include "x87emu_private.h"
 #include "box64context.h"
-//#include "my_cpuid.h"
 #include "bridge.h"
-//#include "signals.h"
+#include "signals.h"
 #ifdef DYNAREC
 #include "../dynarec/arm_lock_helper.h"
 #endif
@@ -844,10 +843,10 @@ fini:
         goto x64emurun;
     }
     // setcontext handling
-//    else if(emu->uc_link) {
-//        emu->quit = 0;
-//        my_setcontext(emu, emu->uc_link);
-//        goto x64emurun;
-//    }
+    else if(emu->uc_link) {
+        emu->quit = 0;
+        my_setcontext(emu, emu->uc_link);
+        goto x64emurun;
+    }
     return 0;
 }
diff --git a/src/emu/x64run_private.c b/src/emu/x64run_private.c
index a6b900fb..737225e3 100755
--- a/src/emu/x64run_private.c
+++ b/src/emu/x64run_private.c
@@ -1147,12 +1147,12 @@ reg64_t* GetEw16off(x64emu_t *emu, rex_t rex, uint8_t v, uintptr_t offset)
     }
 }
 
-mmx_regs_t* GetEm(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta)
+mmx87_regs_t* GetEm(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta)
 {
     uint8_t m = v&0xC7;    // filter Ed
     if(m>=0xC0) {
-         return &emu->mmx[m&0x07];
-    } else return (mmx_regs_t*)GetECommon(emu, rex, m, delta);
+         return &emu->mmx87[m&0x07];
+    } else return (mmx87_regs_t*)GetECommon(emu, rex, m, delta);
 }
 
 sse_regs_t* GetEx(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta)
@@ -1178,10 +1178,10 @@ reg64_t* GetGb(x64emu_t *emu, rex_t rex, uint8_t v)
         return (reg64_t*)&emu->regs[m&3].byte[m>>2];
 }
 
-mmx_regs_t* GetGm(x64emu_t *emu, rex_t rex, uint8_t v)
+mmx87_regs_t* GetGm(x64emu_t *emu, rex_t rex, uint8_t v)
 {
     uint8_t m = (v&0x38)>>3;
-    return &emu->mmx[m&7];
+    return &emu->mmx87[m&7];
 }
 
 sse_regs_t* GetGx(x64emu_t *emu, rex_t rex, uint8_t v)
diff --git a/src/emu/x64run_private.h b/src/emu/x64run_private.h
index e85dcfce..f9d3012e 100755
--- a/src/emu/x64run_private.h
+++ b/src/emu/x64run_private.h
@@ -82,12 +82,12 @@ reg64_t* GetEdO(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta, uintptr_t of
 #define GetEw GetEd
 reg64_t* GetEw16(x64emu_t *emu, rex_t rex, uint8_t v);
 reg64_t* GetEw16off(x64emu_t *emu, rex_t rex, uint8_t v, uintptr_t offset);
-mmx_regs_t* GetEm(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta);
+mmx87_regs_t* GetEm(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta);
 sse_regs_t* GetEx(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta);
 reg64_t* GetGd(x64emu_t *emu, rex_t rex, uint8_t v);
 #define GetGw GetGd
 reg64_t* GetGb(x64emu_t *emu, rex_t rex, uint8_t v);
-mmx_regs_t* GetGm(x64emu_t *emu, rex_t rex, uint8_t v);
+mmx87_regs_t* GetGm(x64emu_t *emu, rex_t rex, uint8_t v);
 sse_regs_t* GetGx(x64emu_t *emu, rex_t rex, uint8_t v);
 
 void UpdateFlags(x64emu_t *emu);
diff --git a/src/emu/x64rund9.c b/src/emu/x64rund9.c
index 00314c97..113e5d42 100644
--- a/src/emu/x64rund9.c
+++ b/src/emu/x64rund9.c
@@ -45,9 +45,9 @@ int RunD9(x64emu_t *emu, rex_t rex)
         case 0xC5:

         case 0xC6:

         case 0xC7:  /* FLD STx */

-            ll = ST(nextop&7).ll;

+            ll = ST(nextop&7).q;

             fpu_do_push(emu);

-            ST0.ll = ll;

+            ST0.q = ll;

             break;

         case 0xC8:

         case 0xC9:

@@ -57,9 +57,9 @@ int RunD9(x64emu_t *emu, rex_t rex)
         case 0xCD:

         case 0xCE:

         case 0xCF:  /* FXCH STx */

-            ll = ST(nextop&7).ll;

-            ST(nextop&7).ll = ST0.ll;

-            ST0.ll = ll;

+            ll = ST(nextop&7).q;

+            ST(nextop&7).q = ST0.q;

+            ST0.q = ll;

             break;

 

         case 0xD0:  /* FNOP */

diff --git a/src/emu/x64rundb.c b/src/emu/x64rundb.c
index ae29f362..772748a6 100644
--- a/src/emu/x64rundb.c
+++ b/src/emu/x64rundb.c
@@ -45,7 +45,7 @@ int RunDB(x64emu_t *emu, rex_t rex)
     case 0xC7:

         CHECK_FLAGS(emu);

         if(!ACCESS_FLAG(F_CF))

-            ST0.ll = ST(nextop&7).ll;

+            ST0.q = ST(nextop&7).q;

         break;

     case 0xC8:      /* FCMOVNE ST(0), ST(i) */

     case 0xC9:

@@ -57,7 +57,7 @@ int RunDB(x64emu_t *emu, rex_t rex)
     case 0xCF:

         CHECK_FLAGS(emu);

         if(!ACCESS_FLAG(F_ZF))

-            ST0.ll = ST(nextop&7).ll;

+            ST0.q = ST(nextop&7).q;

         break;

     case 0xD0:      /* FCMOVNBE ST(0), ST(i) */

     case 0xD1:

@@ -69,7 +69,7 @@ int RunDB(x64emu_t *emu, rex_t rex)
     case 0xD7:

         CHECK_FLAGS(emu);

         if(!(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF)))

-            ST0.ll = ST(nextop&7).ll;

+            ST0.q = ST(nextop&7).q;

         break;

     case 0xD8:      /* FCMOVNU ST(0), ST(i) */

     case 0xD9:

@@ -81,7 +81,7 @@ int RunDB(x64emu_t *emu, rex_t rex)
     case 0xDF:

         CHECK_FLAGS(emu);

         if(!ACCESS_FLAG(F_PF))

-            ST0.ll = ST(nextop&7).ll;

+            ST0.q = ST(nextop&7).q;

         break;

 

     case 0xE1:      /* FDISI8087_NOP */

@@ -168,11 +168,11 @@ int RunDB(x64emu_t *emu, rex_t rex)
                 fpu_do_push(emu);

                 memcpy(&STld(0).ld, ED, 10);

                 LD2D(&STld(0), &ST(0).d);

-                STld(0).ref = ST0.ll;

+                STld(0).ref = ST0.q;

                 break;

             case 7: /* FSTP tbyte */

                 GETED(0);

-                if(ST0.ll!=STld(0).ref)

+                if(ST0.q!=STld(0).ref)

                     D2LD(&ST0.d, ED);

                 else

                     memcpy(ED, &STld(0).ld, 10);

diff --git a/src/emu/x87emu_private.c b/src/emu/x87emu_private.c
index 3e0c0458..5f638bfb 100755
--- a/src/emu/x87emu_private.c
+++ b/src/emu/x87emu_private.c
@@ -11,13 +11,13 @@
 
 void reset_fpu(x64emu_t* emu)
 {
-    memset(emu->fpu, 0, sizeof(emu->fpu));
+    memset(emu->mmx87, 0, sizeof(emu->mmx87));
     memset(emu->fpu_ld, 0, sizeof(emu->fpu_ld));
     emu->cw = 0x37F;
     emu->sw.x16 = 0x0000;
     emu->top = 0;
     emu->fpu_stack = 0;
-    for(int i=0; i<9; ++i)
+    for(int i=0; i<8; ++i)
         emu->p_regs[i].tag = 0b11;  // STx is empty
 }
 
@@ -67,7 +67,7 @@ void fpu_fbld(x64emu_t* emu, uint8_t* s) {
 }
 
 
-#define FPU_t fpu_reg_t
+#define FPU_t mmx87_regs_t
 #define BIAS80 16383
 #define BIAS64 1023
 // long double (80bits) -> double (64bits)
@@ -83,8 +83,8 @@ void LD2D(void* ld, void* d)
     #if 1
     memcpy(&val, ld, 10);
     #else
-	val.f.l.lower = *(uint32_t*)ld;
-    val.f.l.upper = *(uint32_t*)(char*)(ld+4);
+	val.f.ud[0] = *(uint32_t*)ld;
+    val.f.ud[1] = *(uint32_t*)(char*)(ld+4);
 	val.b  = *(int16_t*)((char*)ld+8);
     #endif
 	int32_t exp64 = (((uint32_t)(val.b&0x7fff) - BIAS80) + BIAS64);
@@ -95,31 +95,31 @@ void LD2D(void* ld, void* d)
     if((uint32_t)(val.b&0x7fff)==0x7fff) {
         // infinity and nans
         int t = 0; //nan
-        switch((val.f.l.upper>>30)) {
-            case 0: if((val.f.l.upper&(1<<29))==0) t = 1;
+        switch((val.f.ud[1]>>30)) {
+            case 0: if((val.f.ud[1]&(1<<29))==0) t = 1;
                     break;
-            case 2: if((val.f.l.upper&(1<<29))==0) t = 1;
+            case 2: if((val.f.ud[1]&(1<<29))==0) t = 1;
                     break;
         }
         if(t) {    // infinite
             result.d = HUGE_VAL;
         } else {      // NaN
-            result.l.upper = 0x7ff << 20;
-            result.l.lower = 0;
+            result.ud[1] = 0x7ff << 20;
+            result.ud[0] = 0;
         }
         if(val.b&0x8000)
-            result.l.upper |= 0x80000000;
-        *(uint64_t*)d = result.ll;
+            result.ud[1] |= 0x80000000;
+        *(uint64_t*)d = result.q;
         return;
     }
     if(((uint32_t)(val.b&0x7fff)==0) || (exp64<=0)) {
-        //if(val.f.ll==0)
+        //if(val.f.q==0)
         // zero
-        //if(val.f.ll!=0)
+        //if(val.f.q!=0)
         // denormal, but that's to small value for double 
         uint64_t r = 0;
         if(val.b&0x8000)
-            r |= 0x8000000000000000LL;
+            r |= 0x8000000000000000L;
         *(uint64_t*)d = r;
         return;
     }
@@ -128,17 +128,17 @@ void LD2D(void* ld, void* d)
         // to big value...
         result.d = HUGE_VAL;
         if(val.b&0x8000)
-            result.l.upper |= 0x80000000;
-        *(uint64_t*)d = result.ll;
+            result.ud[1] |= 0x80000000;
+        *(uint64_t*)d = result.q;
         return;
     }
 
-	uint64_t mant64 = (val.f.ll >> 11) & 0xfffffffffffffLL;
+	uint64_t mant64 = (val.f.q >> 11) & 0xfffffffffffffL;
 	uint32_t sign = (val.b&0x8000)?1:0;
-    result.ll = mant64;
-	result.l.upper |= (sign <<31)|((exp64final&0x7ff) << 20);
+    result.q = mant64;
+	result.ud[1] |= (sign <<31)|((exp64final&0x7ff) << 20);
 
-	*(uint64_t*)d = result.ll;
+	*(uint64_t*)d = result.q;
 }
 
 // double (64bits) -> long double (80bits)
@@ -151,12 +151,12 @@ void D2LD(void* d, void* ld)
 	} val;
     #pragma pack(pop)
     FPU_t s;
-    s.ll = *(uint64_t*)d;   // use memcpy to avoid risk of Bus Error?
+    s.q = *(uint64_t*)d;   // use memcpy to avoid risk of Bus Error?
     // do special value first
-    if((s.ll&0x7fffffffffffffffLL)==0) {
+    if((s.q&0x7fffffffffffffffL)==0) {
         // zero...
-        val.f.ll = 0;
-        if(s.l.upper&0x8000)
+        val.f.q = 0;
+        if(s.ud[1]&0x8000)
             val.b = 0x8000;
         else
             val.b = 0;
@@ -164,26 +164,26 @@ void D2LD(void* d, void* ld)
         return;
     }
 
-	int32_t sign80 = (s.l.upper&0x80000000)?1:0;
-	int32_t exp80 =  s.l.upper&0x7ff00000;
+	int32_t sign80 = (s.ud[1]&0x80000000)?1:0;
+	int32_t exp80 =  s.ud[1]&0x7ff00000;
 	int32_t exp80final = (exp80>>20);
-	int64_t mant80 = s.ll&0x000fffffffffffffLL;
+	int64_t mant80 = s.q&0x000fffffffffffffL;
 	int64_t mant80final = (mant80 << 11);
     if(exp80final==0x7ff) {
         // NaN and Infinite
         exp80final = 0x7fff;
         if(mant80==0x0)
-            mant80final = 0x8000000000000000LL; //infinity
+            mant80final = 0x8000000000000000L; //infinity
         else
-            mant80final = 0xc000000000000000LL; //(quiet)NaN
+            mant80final = 0xc000000000000000L; //(quiet)NaN
     } else {
         if(exp80!=0){ 
-            mant80final |= 0x8000000000000000LL;
+            mant80final |= 0x8000000000000000L;
             exp80final += (BIAS80 - BIAS64);
         }
     }
 	val.b = ((int16_t)(sign80)<<15)| (int16_t)(exp80final);
-	val.f.ll = mant80final;
+	val.f.q = mant80final;
     memcpy(ld, &val, 10);
     /*memcpy(ld, &f.ll, 8);
     memcpy((char*)ld + 8, &val.b, 2);*/
@@ -231,7 +231,8 @@ void fpu_savenv(x64emu_t* emu, char* p, int b16)
     // other stuff are not pushed....
 }
 
-typedef struct xsave_s {
+// this is the 64bits version (slightly different than the 32bits!)
+typedef struct xsave32_s {
     uint16_t ControlWord;        /* 000 */
     uint16_t StatusWord;         /* 002 */
     uint8_t  TagWord;            /* 004 */
@@ -248,11 +249,25 @@ typedef struct xsave_s {
     sse_regs_t FloatRegisters[8];/* 020 */  // fpu/mmx are store in 128bits here
     sse_regs_t XmmRegisters[16]; /* 0a0 */
     uint8_t  Reserved4[96];      /* 1a0 */
-} xsave_t;
+} xsave32_t;
+typedef struct xsave64_s {
+    uint16_t ControlWord;        /* 000 */
+    uint16_t StatusWord;         /* 002 */
+    uint8_t  TagWord;            /* 004 */
+    uint8_t  Reserved1;          /* 005 */
+    uint16_t ErrorOpcode;        /* 006 */
+    uint64_t ErrorOffset;        /* 008 */
+    uint64_t DataOffset;         /* 010 */
+    uint32_t MxCsr;              /* 018 */
+    uint32_t MxCsr_Mask;         /* 01c */
+    sse_regs_t FloatRegisters[8];/* 020 */  // fpu/mmx are store in 128bits here
+    sse_regs_t XmmRegisters[16]; /* 0a0 */
+    uint8_t  Reserved4[96];      /* 1a0 */
+} xsave64_t;
 
-void fpu_fxsave(x64emu_t* emu, void* ed)
+void fpu_fxsave32(x64emu_t* emu, void* ed)
 {
-    xsave_t *p = (xsave_t*)ed;
+    xsave32_t *p = (xsave32_t*)ed;
     // should save flags & all
     emu->sw.f.F87_TOP = emu->top&7;
     p->ControlWord = emu->cw;
@@ -268,21 +283,55 @@ void fpu_fxsave(x64emu_t* emu, void* ed)
     p->DataSelector = 0;
     p->MxCsr = 0;
     p->MxCsr_Mask = 0;
-    // copy MMX regs...
+    // copy FPU/MMX regs...
+    for(int i=0; i<8; ++i)
+        memcpy(&p->FloatRegisters[i].q[0], &emu->mmx87[0], sizeof(emu->mmx87[0]));
+    // copy SSE regs
+    memcpy(&p->XmmRegisters[0], &emu->xmm[0], sizeof(emu->xmm));
+}
+
+void fpu_fxsave64(x64emu_t* emu, void* ed)
+{
+    xsave64_t *p = (xsave64_t*)ed;
+    // should save flags & all
+    emu->sw.f.F87_TOP = emu->top&7;
+    p->ControlWord = emu->cw;
+    p->StatusWord = emu->sw.x16;
+    uint8_t tags = 0;
+    for (int i=0; i<8; ++i)
+        tags |= ((emu->p_regs[i].tag)<<(i*2)==0b11)?0:1;
+    p->TagWord = tags;
+    p->ErrorOpcode = 0;
+    p->ErrorOffset = 0;
+    p->DataOffset = 0;
+    p->MxCsr = 0;
+    p->MxCsr_Mask = 0;
+    // copy FPU/MMX regs...
     for(int i=0; i<8; ++i)
-        memcpy(&p->FloatRegisters[i].q[0], &emu->mmx[0], sizeof(emu->mmx[0]));
+        memcpy(&p->FloatRegisters[i].q[0], &emu->mmx87[0], sizeof(emu->mmx87[0]));
     // copy SSE regs
     memcpy(&p->XmmRegisters[0], &emu->xmm[0], sizeof(emu->xmm));
-    // put also FPU regs in a reserved area... on XMM 8-15
+}
+
+void fpu_fxrstor32(x64emu_t* emu, void* ed)
+{
+    xsave32_t *p = (xsave32_t*)ed;
+    emu->cw = p->ControlWord;
+    emu->sw.x16 = p->StatusWord;
+    emu->top = emu->sw.f.F87_TOP;
+    uint8_t tags = p->TagWord;
     for(int i=0; i<8; ++i)
-        memcpy(&p->XmmRegisters[8+i].q[0], &emu->fpu[0], sizeof(emu->fpu[0]));
-    // put a magic sign in reserved area, box86 specific
-    ((unsigned int *)p->Reserved4)[11] = 0x50515253;
+        emu->p_regs[i].tag = (tags>>(i*2))?0:0b11;
+    // copy back MMX regs...
+    for(int i=0; i<8; ++i)
+        memcpy(&emu->mmx87[i], &p->FloatRegisters[i].q[0], sizeof(emu->mmx87[0]));
+    // copy SSE regs
+    memcpy(&emu->xmm[0], &p->XmmRegisters[0], sizeof(emu->xmm));
 }
 
-void fpu_fxrstor(x64emu_t* emu, void* ed)
+void fpu_fxrstor64(x64emu_t* emu, void* ed)
 {
-    xsave_t *p = (xsave_t*)ed;
+    xsave64_t *p = (xsave64_t*)ed;
     emu->cw = p->ControlWord;
     emu->sw.x16 = p->StatusWord;
     emu->top = emu->sw.f.F87_TOP;
@@ -291,17 +340,7 @@ void fpu_fxrstor(x64emu_t* emu, void* ed)
         emu->p_regs[i].tag = (tags>>(i*2))?0:0b11;
     // copy back MMX regs...
     for(int i=0; i<8; ++i)
-        memcpy(&emu->mmx[i], &p->FloatRegisters[i].q[0], sizeof(emu->mmx[0]));
+        memcpy(&emu->mmx87[i], &p->FloatRegisters[i].q[0], sizeof(emu->mmx87[0]));
     // copy SSE regs
     memcpy(&emu->xmm[0], &p->XmmRegisters[0], sizeof(emu->xmm));
-    // check the box86 magic sign in reserved area
-    if(((unsigned int *)p->Reserved4)[11] == 0x50515253) {
-        // also FPU regs where a reserved area... on XMM 8-15?
-        for(int i=0; i<8; ++i)
-            memcpy(&emu->fpu[0], &p->XmmRegisters[8+i].q[0], sizeof(emu->fpu[0]));
-    } else {
-        // copy the mmx to fpu...
-        for(int i=0; i<8; ++i)
-            memcpy(&emu->fpu[0], &emu->mmx[i], sizeof(emu->mmx[0]));
-    }
 }
diff --git a/src/emu/x87emu_private.h b/src/emu/x87emu_private.h
index b8fcf9ad..f188187a 100755
--- a/src/emu/x87emu_private.h
+++ b/src/emu/x87emu_private.h
@@ -18,9 +18,9 @@ typedef struct x64emu_s x64emu_t;
 //void Run66DD(x64emu_t *emu);
 //void RunDF(x64emu_t *emu);
 
-#define ST0 emu->fpu[emu->top]
-#define ST1 emu->fpu[(emu->top+1)&7]
-#define ST(a) emu->fpu[(emu->top+(a))&7]
+#define ST0 emu->mmx87[emu->top]
+#define ST1 emu->mmx87[(emu->top+1)&7]
+#define ST(a) emu->mmx87[(emu->top+(a))&7]
 
 #define STld(a)  emu->fpu_ld[(emu->top+(a))&7]
 #define STll(a)  emu->fpu_ll[(emu->top+(a))&7]
@@ -133,7 +133,7 @@ static inline double fpu_round(x64emu_t* emu, double d) {
 }
 
 static inline void fpu_fxam(x64emu_t* emu) {
-    emu->sw.f.F87_C1 = (ST0.l.upper&0x80000000)?1:0;
+    emu->sw.f.F87_C1 = (ST0.ud[1]&0x80000000)?1:0;
     if(!emu->fpu_stack) {
         emu->sw.f.F87_C3 = 1;
         emu->sw.f.F87_C2 = 0;
@@ -187,7 +187,7 @@ static inline void fpu_ftst(x64emu_t* emu) {
     // normal...
     emu->sw.f.F87_C3 = 0;
     emu->sw.f.F87_C2 = 0;
-    emu->sw.f.F87_C0 = (ST0.l.upper&0x80000000)?1:0;
+    emu->sw.f.F87_C0 = (ST0.ud[1]&0x80000000)?1:0;
 }
 
 void fpu_fbst(x64emu_t* emu, uint8_t* d);
@@ -195,7 +195,9 @@ void fpu_fbld(x64emu_t* emu, uint8_t* s);
 
 void fpu_loadenv(x64emu_t* emu, char* p, int b16);
 void fpu_savenv(x64emu_t* emu, char* p, int b16);
-void fpu_fxsave(x64emu_t* emu, void* ed);
-void fpu_fxrstor(x64emu_t* emu, void* ed);
+void fpu_fxsave32(x64emu_t* emu, void* ed);
+void fpu_fxrstor32(x64emu_t* emu, void* ed);
+void fpu_fxsave64(x64emu_t* emu, void* ed);
+void fpu_fxrstor64(x64emu_t* emu, void* ed);
 
 #endif //__X87RUN_PRIVATE_H_
diff --git a/src/include/regs.h b/src/include/regs.h
index 84159d2b..f75624a0 100755
--- a/src/include/regs.h
+++ b/src/include/regs.h
@@ -127,19 +127,6 @@ typedef enum {
 #pragma pack(push, 1)
 
 typedef union {
-    double d;
-    struct {
-        uint32_t lower;
-        uint32_t upper;
-    } l;
-    struct {
-        float lower;
-        float upper;
-    } f;
-    int64_t ll;
-} fpu_reg_t;
-
-typedef union {
 	//long double ld;	// works only if 80bits!
 	struct {
 		uint64_t lower;
@@ -237,13 +224,15 @@ typedef union {
 typedef union {
 	uint64_t	q;
 	int64_t		sq;
+	double		d;
+	float		f[2];
 	uint32_t	ud[2];
 	int32_t 	sd[2];
 	uint16_t 	uw[4];
 	int16_t 	sw[4];
 	uint8_t 	ub[8];
 	int8_t 		sb[8];
-} mmx_regs_t;
+} mmx87_regs_t;
 
 typedef union {
 	uint64_t q[2];
diff --git a/src/include/signals.h b/src/include/signals.h
new file mode 100755
index 00000000..513e5812
--- /dev/null
+++ b/src/include/signals.h
@@ -0,0 +1,41 @@
+#ifndef __SIGNALS_H__
+#define __SIGNALS_H__
+#include <signal.h>
+
+typedef void (*sighandler_t)(int);
+
+typedef struct x64_sigaction_s {
+	union {
+	  __sighandler_t _sa_handler;
+	  void (*_sa_sigaction)(int, siginfo_t *, void *);
+	} _u;
+	sigset_t sa_mask;
+	uint32_t sa_flags;
+	void (*sa_restorer)(void);
+} x64_sigaction_t;
+
+typedef struct x64_sigaction_restorer_s {
+	union {
+	  __sighandler_t _sa_handler;
+	  void (*_sa_sigaction)(int, siginfo_t *, void *);
+	} _u;
+	uint32_t sa_flags;
+	void (*sa_restorer)(void);
+	sigset_t sa_mask;
+} x64_sigaction_restorer_t;
+
+sighandler_t my_signal(x64emu_t* emu, int signum, sighandler_t handler);
+sighandler_t my___sysv_signal(x64emu_t* emu, int signum, sighandler_t handler);
+sighandler_t my_sysv_signal(x64emu_t* emu, int signum, sighandler_t handler);
+
+int my_sigaction(x64emu_t* emu, int signum, const x64_sigaction_t *act, x64_sigaction_t *oldact);
+int my___sigaction(x64emu_t* emu, int signum, const x64_sigaction_t *act, x64_sigaction_t *oldact);
+
+int my_syscall_rt_sigaction(x64emu_t* emu, int signum, const x64_sigaction_restorer_t *act, x64_sigaction_restorer_t *oldact, int sigsetsize);
+
+void init_signal_helper(box64context_t* context);
+void fini_signal_helper();
+
+void emit_signal(x64emu_t* emu, int sig, void* addr, int code);
+
+#endif //__SIGNALS_H__
\ No newline at end of file
diff --git a/src/libtools/signals.c b/src/libtools/signals.c
new file mode 100755
index 00000000..1ff13887
--- /dev/null
+++ b/src/libtools/signals.c
@@ -0,0 +1,1156 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <signal.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <syscall.h>
+#include <stddef.h>
+#include <stdarg.h>
+#include <ucontext.h>
+#include <setjmp.h>
+#include <sys/mman.h>
+
+#include "box64context.h"
+#include "debug.h"
+#include "x64emu.h"
+#include "emu/x64emu_private.h"
+#include "emu/x64run_private.h"
+#include "signals.h"
+#include "box64stack.h"
+#include "dynarec.h"
+#include "callback.h"
+#include "x64run.h"
+#include "elfloader.h"
+#include "threads.h"
+#include "emu/x87emu_private.h"
+#include "custommem.h"
+#ifdef DYNAREC
+#include "dynablock.h"
+#include "../dynarec/dynablock_private.h"
+#endif
+
+
+typedef uint64_t x64_gregset_t[23];
+enum
+{
+  X64_R8 = 0,
+# define X64_R8         X64_R8
+  X64_R9,
+# define X64_R9         X64_R9
+  X64_R10,
+# define X64_R10        X64_R10
+  X64_R11,
+# define X64_R11        X64_R11
+  X64_R12,
+# define X64_R12        X64_R12
+  X64_R13,
+# define X64_R13        X64_R13
+  X64_R14,
+# define X64_R14        X64_R14
+  X64_R15,
+# define X64_R15        X64_R15
+  X64_RDI,
+# define X64_RDI        X64_RDI
+  X64_RSI,
+# define X64_RSI        X64_RSI
+  X64_RBP,
+# define X64_RBP        X64_RBP
+  X64_RBX,
+# define X64_RBX        X64_RBX
+  X64_RDX,
+# define X64_RDX        X64_RDX
+  X64_RAX,
+# define X64_RAX        X64_RAX
+  X64_RCX,
+# define X64_RCX        X64_RCX
+  X64_RSP,
+# define X64_RSP        X64_RSP
+  X64_RIP,
+# define X64_RIP        X64_RIP
+  X64_EFL,
+# define X64_EFL        X64_EFL
+  X64_CSGSFS,           /* Actually short cs, gs, fs, __pad0.  */
+# define X64_CSGSFS     X64_CSGSFS
+  X64_ERR,
+# define X64_ERR        X64_ERR
+  X64_TRAPNO,
+# define X64_TRAPNO     X64_TRAPNO
+  X64_OLDMASK,
+# define X64_OLDMASK    X64_OLDMASK
+  X64_CR2
+# define X64_CR2        X64_CR2
+};
+
+struct x64_fpreg
+{
+  uint64_t value;
+}__attribute__((packed));
+
+struct x64_fpxreg
+{
+  unsigned short significand[4];
+  unsigned short exponent;
+  unsigned short padding[3];
+}__attribute__((packed));
+
+struct x64_xmmreg
+{
+  uint32_t          element[4];
+}__attribute__((packed));
+
+struct x64_fpstate
+{
+  /* Regular FPU environment.  */
+  uint16_t          cw;
+  uint16_t          sw;
+  uint16_t          tw;
+  uint16_t          fop;
+  uint64_t          rip;
+  uint64_t          rdp;
+  uint32_t          mxcsr;
+  uint32_t          mxcsr_mask;
+  struct x64_fpreg  _st[8];
+  struct x64_xmmreg _xmm[16];
+  uint32_t          res[12];
+  uint32_t          res2[12];
+}__attribute__((packed));
+
+typedef struct x64_fpstate *x64_fpregset_t;
+
+typedef struct
+{
+    void *ss_sp;
+    int ss_flags;
+    size_t ss_size;
+} x64_stack_t;
+
+struct sigcontext_x64
+{
+    uint64_t    r8;
+    uint64_t    r9;
+    uint64_t    r10;
+    uint64_t    r11;
+    uint64_t    r12;
+    uint64_t    r13;
+    uint64_t    r14;
+    uint64_t    r15;
+    uint64_t    di;
+    uint64_t    si;
+    uint64_t    bp;
+    uint64_t    bx;
+    uint64_t    dx;
+    uint64_t    ax;
+    uint64_t    cx;
+    uint64_t    sp;
+    uint64_t    ip;
+    uint64_t    flags;
+    uint64_t    cs;
+    uint64_t    gs;
+    uint64_t    fs;
+    uint64_t    ss;
+    uint64_t    err;
+    uint64_t    trapno;
+    uint64_t    oldmask;
+    uint64_t    cr2;
+    uint64_t    fpstate; /* Zero when no FPU/extended context */
+    uint64_t    reserved1[8];
+};
+
+struct x64_sigcontext
+{
+    uint64_t    r8;
+    uint64_t    r9;
+    uint64_t    r10;
+    uint64_t    r11;
+    uint64_t    r12;
+    uint64_t    r13;
+    uint64_t    r14;
+    uint64_t    r15;
+    uint64_t    rdi;
+    uint64_t    rsi;
+    uint64_t    rbp;
+    uint64_t    rbx;
+    uint64_t    rdx;
+    uint64_t    rax;
+    uint64_t    rcx;
+    uint64_t    rsp;
+    uint64_t    rip;
+    uint64_t    eflags;         /* RFLAGS */
+    uint16_t    cs;
+    uint16_t    gs;
+    uint16_t    fs;
+    union {
+        uint16_t    ss;     /* If UC_SIGCONTEXT_SS */
+        uint16_t    __pad0; /* Alias name for old (!UC_SIGCONTEXT_SS) user-space */
+    };
+    uint64_t    err;
+    uint64_t    trapno;
+    uint64_t    oldmask;
+    uint64_t    cr2;
+    struct x64_fpstate  *fpstate;       /* Zero when no FPU context */
+    uint64_t    reserved1[8];
+};
+
+struct x64_libc_fpstate
+{
+  /* 64-bit FXSAVE format.  */
+  uint16_t              cwd;
+  uint16_t              swd;
+  uint16_t              ftw;
+  uint16_t              fop;
+  uint64_t              rip;
+  uint64_t              rdp;
+  uint32_t              mxcsr;
+  uint32_t              mxcr_mask;
+  struct x64_fpxreg     st[8];
+  struct x64_xmmreg     xmm[16];
+  uint32_t              res1[24];
+};
+
+typedef struct x64_mcontext_s
+{
+    x64_gregset_t gregs;
+    struct x64_libc_fpstate *fpregs;
+    uint64_t    res[8];
+} x64_mcontext_t;
+
+// /!\ signal sig_set is different than glibc __sig_set
+#define _NSIG_WORDS (128 / sizeof(unsigned long int))
+
+typedef struct {
+    unsigned long int sig[_NSIG_WORDS];
+} x64_sigset_t;
+
+typedef struct x64_ucontext_s
+{
+    uint64_t                uc_flags;
+    struct x64_ucontext_s*  uc_link;
+    x64_stack_t             uc_stack;
+    x64_mcontext_t          uc_mcontext;
+    x64_sigset_t            uc_sigmask;
+    struct x64_libc_fpstate xstate;
+    uint64_t                ssp[4];
+} x64_ucontext_t;
+
+typedef struct x64_sigframe_s {
+    uintptr_t       pretcode;   // pointer to retcode
+    int             sig;
+    x64_mcontext_t cpustate;
+    struct x64_libc_fpstate xstate;
+    uintptr_t       extramask[64-1];
+    char            retcode[8];
+} x64_sigframe_t;
+
+struct kernel_sigaction {
+        void (*k_sa_handler) (int);
+        unsigned long sa_flags;
+        void (*sa_restorer) (void);
+        unsigned long sa_mask;
+        unsigned long sa_mask2;
+};
+
+static void sigstack_destroy(void* p)
+{
+	x64_stack_t *ss = (x64_stack_t*)p;
+    free(ss);
+}
+
+static void free_signal_emu(void* p)
+{
+    if(p)
+        FreeX64Emu((x64emu_t**)&p);
+}
+
+static pthread_key_t sigstack_key;
+static pthread_once_t sigstack_key_once = PTHREAD_ONCE_INIT;
+
+static void sigstack_key_alloc() {
+	pthread_key_create(&sigstack_key, sigstack_destroy);
+}
+
+static pthread_key_t sigemu_key;
+static pthread_once_t sigemu_key_once = PTHREAD_ONCE_INIT;
+
+static void sigemu_key_alloc() {
+	pthread_key_create(&sigemu_key, free_signal_emu);
+}
+
+static x64emu_t* get_signal_emu()
+{
+    x64emu_t *emu = (x64emu_t*)pthread_getspecific(sigemu_key);
+    if(!emu) {
+        const int stsize = 8*1024;  // small stack for signal handler
+        void* stack = calloc(1, stsize);
+        emu = NewX64Emu(my_context, 0, (uintptr_t)stack, stsize, 1);
+        emu->type = EMUTYPE_SIGNAL;
+        pthread_setspecific(sigemu_key, emu);
+    }
+    return emu;
+}
+
+
+uint64_t RunFunctionHandler(int* exit, uintptr_t fnc, int nargs, ...)
+{
+    if(fnc==0 || fnc==1) {
+        printf_log(LOG_NONE, "BOX86: Warning, calling Signal function handler %s\n", fnc?"SIG_DFL":"SIG_IGN");
+        return 0;
+    }
+    uintptr_t old_start = trace_start, old_end = trace_end;
+//    trace_start = 0; trace_end = 1; // disabling trace, globably for now...
+
+    x64emu_t *emu = get_signal_emu();
+    printf_log(LOG_DEBUG, "%04d|signal function handler %p called, ESP=%p\n", GetTID(), (void*)fnc, (void*)R_RSP);
+    
+    /*SetFS(emu, default_fs);*/
+    for (int i=0; i<6; ++i)
+        emu->segs_serial[i] = 0;
+        
+    if(nargs>6)
+        R_RSP -= (nargs-6)*4;   // need to push in reverse order
+
+    uint64_t *p = (uint64_t*)R_RSP;
+
+    va_list va;
+    va_start (va, nargs);
+    for (int i=0; i<nargs; ++i) {
+        if(i<6) {
+            int nn[] = {_DI, _SI, _DX, _CX, _R8, _R9};
+            emu->regs[nn[i]].q[0] = va_arg(va, uint64_t);
+        } else {
+            *p = va_arg(va, uint64_t);
+            p++;
+        }
+    }
+    va_end (va);
+
+    EmuCall(emu, fnc);  // avoid DynaCall for now
+    if(nargs>6)
+        R_RSP+=((nargs-6)*4);
+
+    if(exit)
+        *exit = emu->exit;
+
+    uint64_t ret = R_RAX;
+
+    trace_start = old_start; trace_end = old_end;
+
+    return ret;
+}
+
+EXPORT int my_sigaltstack(x64emu_t* emu, const x64_stack_t* ss, x64_stack_t* oss)
+{
+    if(!ss && !oss) {   // this is not true, ss can be NULL to retreive oss info only
+        errno = EFAULT;
+        return -1;
+    }
+    x64emu_t *sigemu = get_signal_emu();
+	x64_stack_t *new_ss = (x64_stack_t*)pthread_getspecific(sigstack_key);
+    if(!ss) {
+        if(!new_ss) {
+            oss->ss_flags = SS_DISABLE;
+            oss->ss_sp = sigemu->init_stack;
+            oss->ss_size = sigemu->size_stack;
+        } else {
+            oss->ss_flags = new_ss->ss_flags;
+            oss->ss_sp = new_ss->ss_sp;
+            oss->ss_size = new_ss->ss_size;
+        }
+        return 0;
+    }
+    printf_log(LOG_DEBUG, "%04d|sigaltstack called ss=%p[flags=0x%x, sp=%p, ss=0x%lx], oss=%p\n", GetTID(), ss, ss->ss_flags, ss->ss_sp, ss->ss_size, oss);
+    if(ss->ss_flags && ss->ss_flags!=SS_DISABLE && ss->ss_flags!=SS_ONSTACK) {
+        errno = EINVAL;
+        return -1;
+    }
+
+    if(ss->ss_flags==SS_DISABLE) {
+        if(new_ss)
+            free(new_ss);
+        pthread_setspecific(sigstack_key, NULL);
+
+        sigemu->regs[_SP].dword[0] = ((uintptr_t)sigemu->init_stack + sigemu->size_stack) & ~7;
+        
+        return 0;
+    }
+    if(oss) {
+        if(!new_ss) {
+            oss->ss_flags = SS_DISABLE;
+            oss->ss_sp = sigemu->init_stack;
+            oss->ss_size = sigemu->size_stack;
+        } else {
+            oss->ss_flags = new_ss->ss_flags;
+            oss->ss_sp = new_ss->ss_sp;
+            oss->ss_size = new_ss->ss_size;
+        }
+    }
+    if(!new_ss)
+        new_ss = (x64_stack_t*)calloc(1, sizeof(x64_stack_t));
+    new_ss->ss_sp = ss->ss_sp;
+    new_ss->ss_size = ss->ss_size;
+
+	pthread_setspecific(sigstack_key, new_ss);
+
+    sigemu->regs[_SP].dword[0] = ((uintptr_t)new_ss->ss_sp + new_ss->ss_size - 16) & ~0x0f;
+
+    return 0;
+}
+
+
+void my_sighandler(int32_t sig)
+{
+    pthread_mutex_unlock(&my_context->mutex_trace);   // just in case
+    printf_log(LOG_DEBUG, "Sighanlder for signal #%d called (jump to %p)\n", sig, (void*)my_context->signals[sig]);
+    uintptr_t restorer = my_context->restorer[sig];
+    int exits = 0;
+    int ret = RunFunctionHandler(&exits, my_context->signals[sig], 1, sig);
+    if(exits)
+        exit(ret);
+    if(restorer)
+        RunFunctionHandler(&exits, restorer, 0);
+}
+
+#ifdef DYNAREC
+uintptr_t getX64Address(dynablock_t* db, uintptr_t arm_addr)
+{
+    uintptr_t x64addr = (uintptr_t)db->x64_addr;
+    uintptr_t armaddr = (uintptr_t)db->block;
+    int i = 0;
+    do {
+        int x64sz = 0;
+        int armsz = 0;
+        do {
+            x64sz+=db->instsize[i].x64;
+            armsz+=db->instsize[i].nat*4;
+        }
+        while(!db->instsize[++i].x64);
+        if(arm_addr>=armaddr && arm_addr<(armaddr+armsz))
+            return x64addr;
+        armaddr+=armsz;
+        x64addr+=x64sz;
+        if(arm_addr==armaddr)
+            return x64addr;
+    } while(db->instsize[i].x64 || db->instsize[i].nat);
+    return x64addr;
+}
+#endif
+
+void my_sigactionhandler_oldcode(int32_t sig, siginfo_t* info, void * ucntx, int* old_code, void* cur_db)
+{
+    // need to create some x64_ucontext????
+    pthread_mutex_unlock(&my_context->mutex_trace);   // just in case
+    printf_log(LOG_DEBUG, "Sigactionhanlder for signal #%d called (jump to %p/%s)\n", sig, (void*)my_context->signals[sig], GetNativeName((void*)my_context->signals[sig]));
+
+    uintptr_t restorer = my_context->restorer[sig];
+    // get that actual ESP first!
+    x64emu_t *emu = thread_get_emu();
+    uint64_t *frame = (uint64_t*)R_RSP;
+#if defined(DYNAREC) && defined(__arm__)
+    ucontext_t *p = (ucontext_t *)ucntx;
+    void * pc = (void*)p->uc_mcontext.arm_pc;
+    dynablock_t* db = (dynablock_t*)cur_db;//FindDynablockFromNativeAddress(pc);
+    if(db) {
+        frame = (uint32_t*)p->uc_mcontext.arm_r8;
+    }
+#endif
+    // stack tracking
+    x64emu_t *sigemu = get_signal_emu();
+	x64_stack_t *new_ss = my_context->onstack[sig]?(x64_stack_t*)pthread_getspecific(sigstack_key):NULL;
+    int used_stack = 0;
+    if(new_ss) {
+        if(new_ss->ss_flags == SS_ONSTACK) { // already using it!
+            frame = (uint64_t*)sigemu->regs[_SP].q[0];
+        } else {
+            frame = (uint64_t*)(((uintptr_t)new_ss->ss_sp + new_ss->ss_size - 16) & ~0x0f);
+            used_stack = 1;
+            new_ss->ss_flags = SS_ONSTACK;
+        }
+    }
+
+    // TODO: do I need to really setup 2 stack frame? That doesn't seems right!
+    // setup stack frame
+    // try to fill some sigcontext....
+    frame -= sizeof(x64_ucontext_t);
+    x64_ucontext_t   *sigcontext = (x64_ucontext_t*)frame;
+    // get general register
+    sigcontext->uc_mcontext.gregs[X64_R8] = R_R8;
+    sigcontext->uc_mcontext.gregs[X64_R9] = R_R9;
+    sigcontext->uc_mcontext.gregs[X64_R10] = R_R10;
+    sigcontext->uc_mcontext.gregs[X64_R11] = R_R11;
+    sigcontext->uc_mcontext.gregs[X64_R12] = R_R12;
+    sigcontext->uc_mcontext.gregs[X64_R13] = R_R13;
+    sigcontext->uc_mcontext.gregs[X64_R14] = R_R14;
+    sigcontext->uc_mcontext.gregs[X64_R15] = R_R15;
+    sigcontext->uc_mcontext.gregs[X64_RAX] = R_RAX;
+    sigcontext->uc_mcontext.gregs[X64_RCX] = R_RCX;
+    sigcontext->uc_mcontext.gregs[X64_RDX] = R_RDX;
+    sigcontext->uc_mcontext.gregs[X64_RDI] = R_RDI;
+    sigcontext->uc_mcontext.gregs[X64_RSI] = R_RSI;
+    sigcontext->uc_mcontext.gregs[X64_RBP] = R_RBP;
+    sigcontext->uc_mcontext.gregs[X64_RIP] = R_RIP;
+    sigcontext->uc_mcontext.gregs[X64_RSP] = R_RSP;
+    sigcontext->uc_mcontext.gregs[X64_RBX] = R_RBX;
+    // flags
+    sigcontext->uc_mcontext.gregs[X64_EFL] = emu->eflags.x32;
+    // get segments
+    sigcontext->uc_mcontext.gregs[X64_CSGSFS] = ((uint64_t)(R_CS)) | (((uint64_t)(R_GS))<<16) | (((uint64_t)(R_FS))<<32);
+#if defined(DYNAREC) && defined(__arm__)
+    if(db) {
+        sigcontext->uc_mcontext.gregs[X64_RAX] = p->uc_mcontext.arm_r4;
+        sigcontext->uc_mcontext.gregs[X64_RCX] = p->uc_mcontext.arm_r5;
+        sigcontext->uc_mcontext.gregs[X64_RDX] = p->uc_mcontext.arm_r6;
+        sigcontext->uc_mcontext.gregs[X64_RBX] = p->uc_mcontext.arm_r7;
+        sigcontext->uc_mcontext.gregs[X64_RSP] = p->uc_mcontext.arm_r8;
+        sigcontext->uc_mcontext.gregs[X64_RBP] = p->uc_mcontext.arm_r9;
+        sigcontext->uc_mcontext.gregs[X64_RSI] = p->uc_mcontext.arm_r10;
+        sigcontext->uc_mcontext.gregs[X64_RDI] = p->uc_mcontext.arm_fp;
+        sigcontext->uc_mcontext.gregs[X64_RIP] = getX86Address(db, (uintptr_t)pc);
+    }
+#endif
+    // get FloatPoint status
+    sigcontext->uc_mcontext.fpregs = (struct x64_libc_fpstate*)&sigcontext->xstate;
+    fpu_fxsave64(emu, &sigcontext->xstate);
+    // add custom SIGN in reserved area
+    //((unsigned int *)(&sigcontext.xstate.fpstate.padding))[8*4+12] = 0x46505853;  // not yet, when XSAVE / XRSTR will be ready
+    // get signal mask
+
+    if(!new_ss) {
+        sigcontext->uc_stack.ss_sp = sigemu->init_stack;
+        sigcontext->uc_stack.ss_size = sigemu->size_stack;
+        sigcontext->uc_stack.ss_flags = SS_DISABLE;
+    } else {
+        sigcontext->uc_stack.ss_sp = new_ss->ss_sp;
+        sigcontext->uc_stack.ss_size = new_ss->ss_size;
+        sigcontext->uc_stack.ss_flags = new_ss->ss_flags;
+    }
+    // Try to guess some X64_TRAPNO
+    /*
+    TRAP_x86_DIVIDE     = 0,   // Division by zero exception
+    TRAP_x86_TRCTRAP    = 1,   // Single-step exception
+    TRAP_x86_NMI        = 2,   // NMI interrupt
+    TRAP_x86_BPTFLT     = 3,   // Breakpoint exception
+    TRAP_x86_OFLOW      = 4,   // Overflow exception
+    TRAP_x86_BOUND      = 5,   // Bound range exception
+    TRAP_x86_PRIVINFLT  = 6,   // Invalid opcode exception
+    TRAP_x86_DNA        = 7,   // Device not available exception
+    TRAP_x86_DOUBLEFLT  = 8,   // Double fault exception
+    TRAP_x86_FPOPFLT    = 9,   // Coprocessor segment overrun
+    TRAP_x86_TSSFLT     = 10,  // Invalid TSS exception
+    TRAP_x86_SEGNPFLT   = 11,  // Segment not present exception
+    TRAP_x86_STKFLT     = 12,  // Stack fault
+    TRAP_x86_PROTFLT    = 13,  // General protection fault
+    TRAP_x86_PAGEFLT    = 14,  // Page fault
+    TRAP_x86_ARITHTRAP  = 16,  // Floating point exception
+    TRAP_x86_ALIGNFLT   = 17,  // Alignment check exception
+    TRAP_x86_MCHK       = 18,  // Machine check exception
+    TRAP_x86_CACHEFLT   = 19   // SIMD exception (via SIGFPE) if CPU is SSE capable otherwise Cache flush exception (via SIGSEV)
+    */
+    uint32_t prot = getProtection((uintptr_t)info->si_addr);
+    if(sig==SIGBUS)
+        sigcontext->uc_mcontext.gregs[X64_TRAPNO] = 17;
+    else if(sig==SIGSEGV) {
+        if((uintptr_t)info->si_addr == sigcontext->uc_mcontext.gregs[X64_RIP]) {
+            sigcontext->uc_mcontext.gregs[X64_ERR] = 0x0010;    // execution flag issue (probably)
+            sigcontext->uc_mcontext.gregs[X64_TRAPNO] = (info->si_code == SEGV_ACCERR)?13:14;
+        } else if(info->si_code==SEGV_ACCERR && !(prot&PROT_WRITE)) {
+            sigcontext->uc_mcontext.gregs[X64_ERR] = 0x0002;    // write flag issue
+            if(abs((intptr_t)info->si_addr-(intptr_t)sigcontext->uc_mcontext.gregs[X64_RSP])<16)
+                sigcontext->uc_mcontext.gregs[X64_TRAPNO] = 12; // stack overflow probably
+            else
+                sigcontext->uc_mcontext.gregs[X64_TRAPNO] = 14; // PAGE_FAULT
+        } else {
+            sigcontext->uc_mcontext.gregs[X64_TRAPNO] = (info->si_code == SEGV_ACCERR)?13:14;
+            //X64_ERR seems to be INT:8 CODE:8. So for write access segfault it's 0x0002 For a read it's 0x0004 (and 8 for exec). For an int 2d it could be 0x2D01 for example
+            sigcontext->uc_mcontext.gregs[X64_ERR] = 0x0004;    // read error? there is no execute control in box86 anyway
+        }
+        if(info->si_code == SEGV_ACCERR && old_code)
+            *old_code = -1;
+    } else if(sig==SIGFPE)
+        sigcontext->uc_mcontext.gregs[X64_TRAPNO] = 19;
+    else if(sig==SIGILL)
+        sigcontext->uc_mcontext.gregs[X64_TRAPNO] = 6;
+    // call the signal handler
+    x64_ucontext_t sigcontext_copy = *sigcontext;
+
+    // set stack pointer
+    sigemu->regs[_SP].dword[0] = (uintptr_t)frame;
+
+    // set segments
+    memcpy(sigemu->segs, emu->segs, sizeof(sigemu->segs));
+
+    int exits = 0;
+    int ret = RunFunctionHandler(&exits, my_context->signals[sig], 3, sig, info, sigcontext);
+
+    if(memcmp(sigcontext, &sigcontext_copy, sizeof(x64_ucontext_t))) {
+        emu_jmpbuf_t* ejb = GetJmpBuf();
+        if(ejb->jmpbuf_ok) {
+            #define GO(R)   if(sigcontext->uc_mcontext.gregs[X64_R##R]!=sigcontext_copy.uc_mcontext.gregs[X64_R##R]) ejb->emu->regs[_##R].dword[0]=sigcontext->uc_mcontext.gregs[X64_R##R]
+            GO(AX);
+            GO(CX);
+            GO(DX);
+            GO(DI);
+            GO(SI);
+            GO(BP);
+            GO(SP);
+            GO(BX);
+            #undef GO
+            #define GO(R)   if(sigcontext->uc_mcontext.gregs[X64_##R]!=sigcontext_copy.uc_mcontext.gregs[X64_##R]) ejb->emu->regs[_##R].dword[0]=sigcontext->uc_mcontext.gregs[X64_##R]
+            GO(R8);
+            GO(R9);
+            GO(R10);
+            GO(R11);
+            GO(R12);
+            GO(R13);
+            GO(R14);
+            GO(R15);
+            #undef GO
+            if(sigcontext->uc_mcontext.gregs[X64_RIP]!=sigcontext_copy.uc_mcontext.gregs[X64_RIP]) ejb->emu->ip.dword[0]=sigcontext->uc_mcontext.gregs[X64_RIP];
+            sigcontext->uc_mcontext.gregs[X64_RIP] = R_RIP;
+            // flags
+            if(sigcontext->uc_mcontext.gregs[X64_EFL]!=sigcontext_copy.uc_mcontext.gregs[X64_EFL]) ejb->emu->eflags.x32=sigcontext->uc_mcontext.gregs[X64_EFL];
+            // get segments
+            uint16_t seg;
+            seg = (sigcontext->uc_mcontext.gregs[X64_CSGSFS] >> 0)&0xffff;
+            #define GO(S) if(ejb->emu->segs[_##S]!=seg)  {ejb->emu->segs[_##S]=seg; ejb->emu->segs_serial[_##S] = 0;}
+            GO(CS);
+            seg = (sigcontext->uc_mcontext.gregs[X64_CSGSFS] >> 16)&0xffff;
+            GO(GS);
+            seg = (sigcontext->uc_mcontext.gregs[X64_CSGSFS] >> 32)&0xffff;
+            GO(FS);
+            #undef GO
+            printf_log(LOG_DEBUG, "Context has been changed in Sigactionhanlder, doing longjmp to resume emu\n");
+            if(old_code)
+                *old_code = -1;    // re-init the value to allow another segfault at the same place
+            if(used_stack)  // release stack
+                new_ss->ss_flags = 0;
+            longjmp(ejb->jmpbuf, 1);
+        }
+        printf_log(LOG_INFO, "Warning, context has been changed in Sigactionhanlder%s\n", (sigcontext->uc_mcontext.gregs[X64_RIP]!=sigcontext_copy.uc_mcontext.gregs[X64_RIP])?" (EIP changed)":"");
+    }
+    printf_log(LOG_DEBUG, "Sigactionhanlder main function returned (exit=%d, restorer=%p)\n", exits, (void*)restorer);
+    if(exits)
+        exit(ret);
+    if(restorer)
+        RunFunctionHandler(&exits, restorer, 0);
+    if(used_stack)  // release stack
+        new_ss->ss_flags = 0;
+}
+
+void my_box86signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
+{
+    // sig==SIGSEGV || sig==SIGBUS || sig==SIGILL here!
+    int log_minimum = (my_context->is_sigaction[sig] && sig==SIGSEGV)?LOG_INFO:LOG_NONE;
+    ucontext_t *p = (ucontext_t *)ucntx;
+    void* addr = (void*)info->si_addr;  // address that triggered the issue
+    void* rsp = NULL;
+#ifdef __aarch64__
+    void * pc = (void*)p->uc_mcontext.arm_pc;
+#elif defined __x86_64__
+    void * pc = (void*)p->uc_mcontext.gregs[X64_RIP];
+#elif defined __powerpc64__
+    void * pc = (void*)p->uc_mcontext.uc_regs->gregs[PT_NIP];
+#else
+    void * pc = NULL;    // unknow arch...
+    #warning Unhandled architecture
+#endif
+#ifdef DYNAREC
+    uint32_t prot = getProtection((uintptr_t)addr);
+    dynablock_t* db = NULL;
+    int db_searched = 0;
+    if ((sig==SIGSEGV) && (addr) && (info->si_code == SEGV_ACCERR) && (prot&PROT_DYNAREC)) {
+        if(box86_dynarec_smc) {
+            dynablock_t* db_pc = NULL;
+            db_pc = FindDynablockFromNativeAddress(pc);
+            if(db_pc) {
+                db = FindDynablockFromNativeAddress(addr);
+                db_searched = 1;
+            }
+            if(db_pc && db) {
+                if (db_pc == db) {
+                    dynarec_log(LOG_NONE, "Warning: Access to protected %p from %p, inside same dynablock\n", addr, pc);            
+                }
+            }
+            if(db && db->x86_addr>= addr && (db->x86_addr+db->x86_size)<addr) {
+                dynarec_log(LOG_INFO, "Warning, addr inside current dynablock!\n");
+            }
+        }
+        dynarec_log(LOG_DEBUG, "Access to protected %p from %p, unprotecting memory (prot=%x)\n", addr, pc, prot);
+        // access error, unprotect the block (and mark them dirty)
+        if(prot&PROT_DYNAREC)   // on heavy multi-thread program, the protection can already be gone...
+            unprotectDB((uintptr_t)addr, 1);    // unprotect 1 byte... But then, the whole page will be unprotected
+        // done
+        if(prot&PROT_WRITE) return; // if there is no write permission, don't return and continue to program signal handling
+    } else if ((sig==SIGSEGV) && (addr) && (info->si_code == SEGV_ACCERR) && (prot&(PROT_READ|PROT_WRITE))) {
+        db = FindDynablockFromNativeAddress(pc);
+        db_searched = 1;
+        if(db && db->x86_addr>= addr && (db->x86_addr+db->x86_size)<addr) {
+            dynarec_log(LOG_INFO, "Warning, addr inside current dynablock!\n");
+        }
+        if(addr && pc && db) {
+            // probably a glitch due to intensive multitask...
+            dynarec_log(/*LOG_DEBUG*/LOG_INFO, "SIGSEGV with Access error on %p for %p , db=%p, retrying\n", pc, addr, db);
+            return; // try again
+        }
+    }
+#else
+    void* db = NULL;
+#endif
+    static int old_code = -1;
+    static void* old_pc = 0;
+    static void* old_addr = 0;
+    const char* signame = (sig==SIGSEGV)?"SIGSEGV":((sig==SIGBUS)?"SIGBUS":"SIGILL");
+    if(old_code==info->si_code && old_pc==pc && old_addr==addr) {
+        printf_log(log_minimum, "%04d|Double %s (code=%d, pc=%p, addr=%p)!\n", GetTID(), signame, old_code, old_pc, old_addr);
+exit(-1);
+    } else {
+#ifdef DYNAREC
+        if(!db_searched)
+            db = FindDynablockFromNativeAddress(pc);
+#endif
+        old_code = info->si_code;
+        old_pc = pc;
+        old_addr = addr;
+        const char* name = GetNativeName(pc);
+        uintptr_t x64pc = (uintptr_t)-1;
+        const char* x64name = NULL;
+        const char* elfname = NULL;
+        x64emu_t* emu = thread_get_emu();
+        x64pc = R_RIP;
+        rsp = (void*)R_RSP;
+#if defined(__arm__) && defined(DYNAREC)
+        if(db && p->uc_mcontext.arm_r0>0x10000) {
+            emu = (x64emu_t*)p->uc_mcontext.arm_r0;
+        }
+        if(db) {
+            x64pc = getX64Address(db, (uintptr_t)pc);
+            rsp = (void*)p->uc_mcontext.arm_r8;
+        }
+#endif
+        x64name = getAddrFunctionName(x64pc);
+        elfheader_t* elf = FindElfAddress(my_context, x64pc);
+        if(elf)
+            elfname = ElfName(elf);
+        if(jit_gdb) {
+            pid_t pid = getpid();
+            int v = fork(); // is this ok in a signal handler???
+            if(v) {
+                // parent process, the one that have the segfault
+                volatile int waiting = 1;
+                printf("Waiting for %s (pid %d)...\n", (jit_gdb==2)?"gdbserver":"gdb", pid);
+                while(waiting) {
+                    // using gdb, use "set waiting=0" to stop waiting...
+                    usleep(1000);
+                }
+            } else {
+                char myarg[50] = {0};
+                sprintf(myarg, "%d", pid);
+                if(jit_gdb==2)
+                    execlp("gdbserver", "gdbserver", "127.0.0.1:1234", "--attach", myarg, (char*)NULL);
+                else
+                    execlp("gdb", "gdb", "-pid", myarg, (char*)NULL);
+                exit(-1);
+            }
+        }
+#ifdef DYNAREC
+        uint32_t hash = 0;
+        if(db)
+            hash = X31_hash_code(db->x86_addr, db->x86_size);
+        printf_log(log_minimum, "%04d|%s @%p (%s) (x64pc=%p/%s:\"%s\", rsp=%p), for accessing %p (code=%d/prot=%x), db=%p(%p:%p/%p:%p/%s:%s, hash:%x/%x)", 
+            GetTID(), signame, pc, name, (void*)x64pc, elfname?elfname:"???", x64name?x64name:"???", rsp, addr, info->si_code, 
+            prot, db, db?db->block:0, db?(db->block+db->size):0, 
+            db?db->x86_addr:0, db?(db->x86_addr+db->x86_size):0, 
+            getAddrFunctionName((uintptr_t)(db?db->x86_addr:0)), (db?db->need_test:0)?"need_stest":"clean", db?db->hash:0, hash);
+#else
+        printf_log(log_minimum, "%04d|%s @%p (%s) (x64pc=%p/%s:\"%s\", rsp=%p), for accessing %p (code=%d)", GetTID(), signame, pc, name, (void*)x64pc, elfname?elfname:"???", x64name?x64name:"???", rsp, addr, info->si_code);
+#endif
+        if(sig==SIGILL)
+            printf_log(log_minimum, " opcode=%02X %02X %02X %02X %02X %02X %02X %02X\n", ((uint8_t*)pc)[0], ((uint8_t*)pc)[1], ((uint8_t*)pc)[2], ((uint8_t*)pc)[3], ((uint8_t*)pc)[4], ((uint8_t*)pc)[5], ((uint8_t*)pc)[6], ((uint8_t*)pc)[7]);
+        else if(sig==SIGBUS)
+            printf_log(log_minimum, " x86opcode=%02X %02X %02X %02X %02X %02X %02X %02X\n", ((uint8_t*)x64pc)[0], ((uint8_t*)x64pc)[1], ((uint8_t*)x64pc)[2], ((uint8_t*)x64pc)[3], ((uint8_t*)x64pc)[4], ((uint8_t*)x64pc)[5], ((uint8_t*)x64pc)[6], ((uint8_t*)x64pc)[7]);
+        else
+            printf_log(log_minimum, "\n");
+    }
+    if(my_context->signals[sig] && my_context->signals[sig]!=1) {
+        if(my_context->is_sigaction[sig])
+            my_sigactionhandler_oldcode(sig, info, ucntx, &old_code, db);
+        else
+            my_sighandler(sig);
+        return;
+    }
+    // no handler (or double identical segfault)
+    // set default and that's it, instruction will restart and default segfault handler will be called...
+    if(my_context->signals[sig]!=1)
+        signal(sig, SIG_DFL);
+}
+
+void my_sigactionhandler(int32_t sig, siginfo_t* info, void * ucntx)
+{
+    #ifdef DYNAREC
+    ucontext_t *p = (ucontext_t *)ucntx;
+    void * pc = (void*)p->uc_mcontext.arm_pc;
+    dynablock_t* db = FindDynablockFromNativeAddress(pc);
+    #else
+    void* db = NULL;
+    #endif
+
+    my_sigactionhandler_oldcode(sig, info, ucntx, NULL, db);
+}
+
+void emit_signal(x64emu_t* emu, int sig, void* addr, int code)
+{
+    ucontext_t ctx = {0};
+    void* db = NULL;
+    siginfo_t info = {0};
+    info.si_signo = sig;
+    info.si_errno = 0;
+    info.si_code = code;
+    info.si_addr = addr;
+    printf_log(LOG_INFO, "Emit Signal %d at IP=%p / addr=%p, code=%d\n", sig, (void*)R_RIP, addr, code);
+    my_sigactionhandler_oldcode(sig, &info, &ctx, NULL, db);
+}
+
+EXPORT sighandler_t my_signal(x64emu_t* emu, int signum, sighandler_t handler)
+{
+    if(signum<0 || signum>=MAX_SIGNAL)
+        return SIG_ERR;
+
+    if(signum==SIGSEGV && emu->context->no_sigsegv)
+        return 0;
+
+    // create a new handler
+    my_context->signals[signum] = (uintptr_t)handler;
+    my_context->is_sigaction[signum] = 0;
+    my_context->restorer[signum] = 0;
+    if(handler!=NULL && handler!=(sighandler_t)1) {
+        handler = my_sighandler;
+    }
+
+    if(signum==SIGSEGV || signum==SIGBUS || signum==SIGILL)
+        return 0;
+
+    return signal(signum, handler);
+}
+EXPORT sighandler_t my___sysv_signal(x64emu_t* emu, int signum, sighandler_t handler) __attribute__((alias("my_signal")));
+EXPORT sighandler_t my_sysv_signal(x64emu_t* emu, int signum, sighandler_t handler) __attribute__((alias("my_signal")));    // not completly exact
+
+int EXPORT my_sigaction(x64emu_t* emu, int signum, const x64_sigaction_t *act, x64_sigaction_t *oldact)
+{
+    if(signum<0 || signum>=MAX_SIGNAL)
+        return -1;
+    
+    if(signum==SIGSEGV && emu->context->no_sigsegv)
+        return 0;
+
+    if(signum==SIGILL && emu->context->no_sigill)
+        return 0;
+    struct sigaction newact = {0};
+    struct sigaction old = {0};
+    if(act) {
+        newact.sa_mask = act->sa_mask;
+        newact.sa_flags = act->sa_flags&~0x04000000;  // No sa_restorer...
+        if(act->sa_flags&0x04) {
+            my_context->signals[signum] = (uintptr_t)act->_u._sa_sigaction;
+            my_context->is_sigaction[signum] = 1;
+            if(act->_u._sa_handler!=NULL && act->_u._sa_handler!=(sighandler_t)1) {
+                newact.sa_sigaction = my_sigactionhandler;
+            } else
+                newact.sa_sigaction = act->_u._sa_sigaction;
+        } else {
+            my_context->signals[signum] = (uintptr_t)act->_u._sa_handler;
+            my_context->is_sigaction[signum] = 0;
+            if(act->_u._sa_handler!=NULL && act->_u._sa_handler!=(sighandler_t)1) {
+                newact.sa_handler = my_sighandler;
+            } else
+                newact.sa_handler = act->_u._sa_handler;
+        }
+        my_context->restorer[signum] = (act->sa_flags&0x04000000)?(uintptr_t)act->sa_restorer:0;
+        my_context->onstack[signum] = (act->sa_flags&SA_ONSTACK)?1:0;
+    }
+    int ret = 0;
+    if(signum!=SIGSEGV && signum!=SIGBUS && signum!=SIGILL)
+        sigaction(signum, act?&newact:NULL, oldact?&old:NULL);
+    if(oldact) {
+        oldact->sa_flags = old.sa_flags;
+        oldact->sa_mask = old.sa_mask;
+        if(old.sa_flags & 0x04)
+            oldact->_u._sa_sigaction = old.sa_sigaction; //TODO should wrap...
+        else
+            oldact->_u._sa_handler = old.sa_handler;  //TODO should wrap...
+        oldact->sa_restorer = NULL; // no handling for now...
+    }
+    return ret;
+}
+int EXPORT my___sigaction(x64emu_t* emu, int signum, const x64_sigaction_t *act, x64_sigaction_t *oldact)
+__attribute__((alias("my_sigaction")));
+
+int EXPORT my_syscall_rt_sigaction(x64emu_t* emu, int signum, const x64_sigaction_restorer_t *act, x64_sigaction_restorer_t *oldact, int sigsetsize)
+{
+    printf_log(LOG_DEBUG, "Syscall/Sigaction(signum=%d, act=%p, old=%p, size=%d)\n", signum, act, oldact, sigsetsize);
+    if(signum<0 || signum>=MAX_SIGNAL)
+        return -1;
+    
+    if(signum==SIGSEGV && emu->context->no_sigsegv)
+        return 0;
+    // TODO, how to handle sigsetsize>4?!
+    if(signum==32 || signum==33) {
+        // cannot use libc sigaction, need to use syscall!
+        struct kernel_sigaction newact = {0};
+        struct kernel_sigaction old = {0};
+        if(act) {
+            printf_log(LOG_DEBUG, " New (kernel) action flags=0x%x mask=0x%x\n", act->sa_flags, *(uint32_t*)&act->sa_mask);
+            memcpy(&newact.sa_mask, &act->sa_mask, (sigsetsize>16)?16:sigsetsize);
+            newact.sa_flags = act->sa_flags&~0x04000000;  // No sa_restorer...
+            if(act->sa_flags&0x04) {
+                my_context->signals[signum] = (uintptr_t)act->_u._sa_sigaction;
+                my_context->is_sigaction[signum] = 1;
+                if(act->_u._sa_handler!=NULL && act->_u._sa_handler!=(sighandler_t)1) {
+                    newact.k_sa_handler = (void*)my_sigactionhandler;
+                } else {
+                    newact.k_sa_handler = (void*)act->_u._sa_sigaction;
+                }
+            } else {
+                my_context->signals[signum] = (uintptr_t)act->_u._sa_handler;
+                my_context->is_sigaction[signum] = 0;
+                if(act->_u._sa_handler!=NULL && act->_u._sa_handler!=(sighandler_t)1) {
+                    newact.k_sa_handler = my_sighandler;
+                } else {
+                    newact.k_sa_handler = act->_u._sa_handler;
+                }
+            }
+            my_context->restorer[signum] = (act->sa_flags&0x04000000)?(uintptr_t)act->sa_restorer:0;
+        }
+
+        if(oldact) {
+            old.sa_flags = oldact->sa_flags;
+            memcpy(&old.sa_mask, &oldact->sa_mask, (sigsetsize>16)?16:sigsetsize);
+        }
+
+        int ret = syscall(__NR_rt_sigaction, signum, act?&newact:NULL, oldact?&old:NULL, (sigsetsize>16)?16:sigsetsize);
+        if(oldact && ret==0) {
+            oldact->sa_flags = old.sa_flags;
+            memcpy(&oldact->sa_mask, &old.sa_mask, (sigsetsize>16)?16:sigsetsize);
+            if(old.sa_flags & 0x04)
+                oldact->_u._sa_sigaction = (void*)old.k_sa_handler; //TODO should wrap...
+            else
+                oldact->_u._sa_handler = old.k_sa_handler;  //TODO should wrap...
+        }
+        return ret;
+    } else {
+        // using libc sigaction
+        struct sigaction newact = {0};
+        struct sigaction old = {0};
+        if(act) {
+            printf_log(LOG_DEBUG, " New action flags=0x%x mask=0x%lx\n", act->sa_flags, *(uint64_t*)&act->sa_mask);
+            newact.sa_mask = act->sa_mask;
+            newact.sa_flags = act->sa_flags&~0x04000000;  // No sa_restorer...
+            if(act->sa_flags&0x04) {
+                if(act->_u._sa_handler!=NULL && act->_u._sa_handler!=(sighandler_t)1) {
+                    my_context->signals[signum] = (uintptr_t)act->_u._sa_sigaction;
+                    newact.sa_sigaction = my_sigactionhandler;
+                } else {
+                    newact.sa_sigaction = act->_u._sa_sigaction;
+                }
+            } else {
+                if(act->_u._sa_handler!=NULL && act->_u._sa_handler!=(sighandler_t)1) {
+                    my_context->signals[signum] = (uintptr_t)act->_u._sa_handler;
+                    my_context->is_sigaction[signum] = 0;
+                    newact.sa_handler = my_sighandler;
+                } else {
+                    newact.sa_handler = act->_u._sa_handler;
+                }
+            }
+            my_context->restorer[signum] = (act->sa_flags&0x04000000)?(uintptr_t)act->sa_restorer:0;
+        }
+
+        if(oldact) {
+            old.sa_flags = oldact->sa_flags;
+            old.sa_mask = oldact->sa_mask;
+        }
+        int ret = 0;
+
+        if(signum!=SIGSEGV && signum!=SIGBUS && signum!=SIGILL)
+            ret = sigaction(signum, act?&newact:NULL, oldact?&old:NULL);
+        if(oldact && ret==0) {
+            oldact->sa_flags = old.sa_flags;
+            oldact->sa_mask = old.sa_mask;
+            if(old.sa_flags & 0x04)
+                oldact->_u._sa_sigaction = old.sa_sigaction; //TODO should wrap...
+            else
+                oldact->_u._sa_handler = old.sa_handler;  //TODO should wrap...
+        }
+        return ret;
+    }
+}
+
+EXPORT sighandler_t my_sigset(x64emu_t* emu, int signum, sighandler_t handler)
+{
+    // emulated SIG_HOLD
+    if(handler == (sighandler_t)2) {
+        x64_sigaction_t oact;
+        sigset_t nset;
+        sigset_t oset;
+        if (sigemptyset (&nset) < 0)
+            return (sighandler_t)-1;
+        if (sigaddset (&nset, signum) < 0)
+            return (sighandler_t)-1;
+        if (sigprocmask (SIG_BLOCK, &nset, &oset) < 0)
+            return (sighandler_t)-1;
+        if (sigismember (&oset, signum))
+            return (sighandler_t)2;
+        if (my_sigaction (emu, signum, NULL, &oact) < 0)
+            return (sighandler_t)-1;
+        return oact._u._sa_handler;
+    }
+    return my_signal(emu, signum, handler);
+}
+
+EXPORT int my_getcontext(x64emu_t* emu, void* ucp)
+{
+//    printf_log(LOG_NONE, "Warning: call to partially implemented getcontext\n");
+    x64_ucontext_t *u = (x64_ucontext_t*)ucp;
+    // stack traking
+    u->uc_stack.ss_sp = NULL;
+    u->uc_stack.ss_size = 0;    // this need to filled
+    // get general register
+    u->uc_mcontext.gregs[X64_RAX] = R_RAX;
+    u->uc_mcontext.gregs[X64_RCX] = R_RCX;
+    u->uc_mcontext.gregs[X64_RDX] = R_RDX;
+    u->uc_mcontext.gregs[X64_RDI] = R_RDI;
+    u->uc_mcontext.gregs[X64_RSI] = R_RSI;
+    u->uc_mcontext.gregs[X64_RBP] = R_RBP;
+    u->uc_mcontext.gregs[X64_RIP] = *(uint64_t*)R_RSP;
+    u->uc_mcontext.gregs[X64_RSP] = R_RSP+sizeof(uintptr_t);
+    u->uc_mcontext.gregs[X64_RBX] = R_RBX;
+    u->uc_mcontext.gregs[X64_R8] = R_R8;
+    u->uc_mcontext.gregs[X64_R9] = R_R9;
+    u->uc_mcontext.gregs[X64_R10] = R_R10;
+    u->uc_mcontext.gregs[X64_R11] = R_R11;
+    u->uc_mcontext.gregs[X64_R12] = R_R12;
+    u->uc_mcontext.gregs[X64_R13] = R_R13;
+    u->uc_mcontext.gregs[X64_R14] = R_R14;
+    u->uc_mcontext.gregs[X64_R15] = R_R15;
+    // get segments
+    u->uc_mcontext.gregs[X64_CSGSFS] = ((uint64_t)(R_CS)) | (((uint64_t)(R_GS))<<16) | (((uint64_t)(R_FS))<<32);
+    // get FloatPoint status
+    // get signal mask
+    sigprocmask(SIG_SETMASK, NULL, (sigset_t*)&u->uc_sigmask);
+
+    return 0;
+}
+
+EXPORT int my_setcontext(x64emu_t* emu, void* ucp)
+{
+//    printf_log(LOG_NONE, "Warning: call to partially implemented setcontext\n");
+    x64_ucontext_t *u = (x64_ucontext_t*)ucp;
+    // stack tracking
+    emu->init_stack = u->uc_stack.ss_sp;
+    emu->size_stack = u->uc_stack.ss_size;
+    // set general register
+    R_RAX = u->uc_mcontext.gregs[X64_RAX];
+    R_RCX = u->uc_mcontext.gregs[X64_RCX];
+    R_RDX = u->uc_mcontext.gregs[X64_RDX];
+    R_RDI = u->uc_mcontext.gregs[X64_RDI];
+    R_RSI = u->uc_mcontext.gregs[X64_RSI];
+    R_RBP = u->uc_mcontext.gregs[X64_RBP];
+    R_RIP = u->uc_mcontext.gregs[X64_RIP];
+    R_RSP = u->uc_mcontext.gregs[X64_RSP];
+    R_RBX = u->uc_mcontext.gregs[X64_RBX];
+    R_R8  = u->uc_mcontext.gregs[X64_R8];
+    R_R9  = u->uc_mcontext.gregs[X64_R9];
+    R_R10 = u->uc_mcontext.gregs[X64_R10];
+    R_R11 = u->uc_mcontext.gregs[X64_R11];
+    R_R12 = u->uc_mcontext.gregs[X64_R12];
+    R_R13 = u->uc_mcontext.gregs[X64_R13];
+    R_R14 = u->uc_mcontext.gregs[X64_R14];
+    R_R15 = u->uc_mcontext.gregs[X64_R15];
+    // get segments
+    R_CS = (u->uc_mcontext.gregs[X64_CSGSFS]>> 0)&0xffff;
+    R_GS = (u->uc_mcontext.gregs[X64_CSGSFS]>>16)&0xffff;
+    R_FS = (u->uc_mcontext.gregs[X64_CSGSFS]>>32)&0xffff;
+    // set FloatPoint status
+    // set signal mask
+    //sigprocmask(SIG_SETMASK, NULL, (sigset_t*)&u->uc_sigmask);
+    // set uc_link
+    emu->uc_link = u->uc_link;
+
+    return R_EAX;
+}
+
+EXPORT int my_makecontext(x64emu_t* emu, void* ucp, void* fnc, int32_t argc, int64_t* argv)
+{
+//    printf_log(LOG_NONE, "Warning: call to unimplemented makecontext\n");
+    x64_ucontext_t *u = (x64_ucontext_t*)ucp;
+    // setup stack
+    uintptr_t* rsp = (uintptr_t*)(u->uc_stack.ss_sp + u->uc_stack.ss_size - sizeof(uintptr_t));
+    // setup the function
+    u->uc_mcontext.gregs[X64_RIP] = (intptr_t)fnc;
+    // setup args
+    int n = 3;
+    int j = 0;
+    int regs_abi[] = {_DI, _SI, _DX, _CX, _R8, _R9};
+    for (int i=0; i<argc; ++i) {
+        // get value first
+        uint64_t v;
+        if(n<6)
+            v = emu->regs[regs_abi[n++]].q[0];
+        else
+            v = argv[j++];
+        // push value
+        switch(i) {
+            case 0: u->uc_mcontext.gregs[X64_RDI] = v; break;
+            case 1: u->uc_mcontext.gregs[X64_RSI] = v; break;
+            case 2: u->uc_mcontext.gregs[X64_RDX] = v; break;
+            case 3: u->uc_mcontext.gregs[X64_RCX] = v; break;
+            case 4: u->uc_mcontext.gregs[X64_R8] = v; break;
+            case 5: u->uc_mcontext.gregs[X64_R9] = v; break;
+            default:
+                --rsp;
+                *rsp = argv[(argc-1)-i];
+        }
+    }
+    // push the return value
+    --rsp;
+    *rsp = (uintptr_t)GetExit();
+    u->uc_mcontext.gregs[X64_RSP] = (uintptr_t)rsp;
+    
+    return 0;
+}
+
+EXPORT int my_swapcontext(x64emu_t* emu, void* ucp1, void* ucp2)
+{
+//    printf_log(LOG_NONE, "Warning: call to unimplemented swapcontext\n");
+    // grab current context in ucp1
+    my_getcontext(emu, ucp1);
+    // activate ucp2
+    my_setcontext(emu, ucp2);
+    return 0;
+}
+
+void init_signal_helper(box64context_t* context)
+{
+    // setup signal handling
+    for(int i=0; i<MAX_SIGNAL; ++i) {
+        context->signals[i] = 1;    // SIG_DFL
+    }
+	struct sigaction action;
+	action.sa_flags = SA_SIGINFO | SA_RESTART | SA_NODEFER;
+	action.sa_sigaction = my_box86signalhandler;
+    sigaction(SIGSEGV, &action, NULL);
+	action.sa_flags = SA_SIGINFO | SA_RESTART | SA_NODEFER;
+	action.sa_sigaction = my_box86signalhandler;
+    sigaction(SIGBUS, &action, NULL);
+	action.sa_flags = SA_SIGINFO | SA_RESTART | SA_NODEFER;
+	action.sa_sigaction = my_box86signalhandler;
+    sigaction(SIGILL, &action, NULL);
+
+	pthread_once(&sigstack_key_once, sigstack_key_alloc);
+	pthread_once(&sigemu_key_once, sigemu_key_alloc);
+}
+
+void fini_signal_helper()
+{
+    signal(SIGSEGV, SIG_DFL);
+    signal(SIGBUS, SIG_DFL);
+    signal(SIGILL, SIG_DFL);
+}
diff --git a/src/wrapped/generated/functions_list.txt b/src/wrapped/generated/functions_list.txt
index 6c6f56d3..2a7ddd9e 100644
--- a/src/wrapped/generated/functions_list.txt
+++ b/src/wrapped/generated/functions_list.txt
@@ -1,5 +1,6 @@
 #() vFE
 #() vFv
+#() vFi
 #() vFp
 #() iFE
 #() iFv
@@ -72,6 +73,7 @@
 #() pFEppp
 #() pFppiL
 #() pFppuL
+#() iFEppiV
 #() iFEpppp
 #() iFipppi
 #() iFEpippppp
diff --git a/src/wrapped/generated/wrapper.c b/src/wrapped/generated/wrapper.c
index 370cdac8..872238a6 100644
--- a/src/wrapped/generated/wrapper.c
+++ b/src/wrapped/generated/wrapper.c
@@ -71,6 +71,7 @@ void VulkanTox86(void* src, void* save);
 int of_convert(int);
 typedef void (*vFE_t)(x64emu_t*);
 typedef void (*vFv_t)(void);
+typedef void (*vFi_t)(int32_t);
 typedef void (*vFp_t)(void*);
 typedef int32_t (*iFE_t)(x64emu_t*);
 typedef int32_t (*iFv_t)(void);
@@ -143,6 +144,7 @@ typedef void* (*pFEppi_t)(x64emu_t*, void*, void*, int32_t);
 typedef void* (*pFEppp_t)(x64emu_t*, void*, void*, void*);
 typedef void* (*pFppiL_t)(void*, void*, int32_t, uintptr_t);
 typedef void* (*pFppuL_t)(void*, void*, uint32_t, uintptr_t);
+typedef int32_t (*iFEppiV_t)(x64emu_t*, void*, void*, int32_t, void*);
 typedef int32_t (*iFEpppp_t)(x64emu_t*, void*, void*, void*, void*);
 typedef int32_t (*iFipppi_t)(int32_t, void*, void*, void*, int32_t);
 typedef int32_t (*iFEpippppp_t)(x64emu_t*, void*, int32_t, void*, void*, void*, void*, void*);
@@ -161,6 +163,7 @@ typedef double (*KFKp_t)(double, void*);
 
 void vFE(x64emu_t *emu, uintptr_t fcn) { vFE_t fn = (vFE_t)fcn; fn(emu); }
 void vFv(x64emu_t *emu, uintptr_t fcn) { vFv_t fn = (vFv_t)fcn; fn(); }
+void vFi(x64emu_t *emu, uintptr_t fcn) { vFi_t fn = (vFi_t)fcn; fn((int32_t)R_RDI); }
 void vFp(x64emu_t *emu, uintptr_t fcn) { vFp_t fn = (vFp_t)fcn; fn((void*)R_RDI); }
 void iFE(x64emu_t *emu, uintptr_t fcn) { iFE_t fn = (iFE_t)fcn; R_RAX=fn(emu); }
 void iFv(x64emu_t *emu, uintptr_t fcn) { iFv_t fn = (iFv_t)fcn; R_RAX=fn(); }
@@ -233,6 +236,7 @@ void pFEppi(x64emu_t *emu, uintptr_t fcn) { pFEppi_t fn = (pFEppi_t)fcn; R_RAX=(
 void pFEppp(x64emu_t *emu, uintptr_t fcn) { pFEppp_t fn = (pFEppp_t)fcn; R_RAX=(uintptr_t)fn(emu, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX); }
 void pFppiL(x64emu_t *emu, uintptr_t fcn) { pFppiL_t fn = (pFppiL_t)fcn; R_RAX=(uintptr_t)fn((void*)R_RDI, (void*)R_RSI, (int32_t)R_RDX, (uintptr_t)R_RCX); }
 void pFppuL(x64emu_t *emu, uintptr_t fcn) { pFppuL_t fn = (pFppuL_t)fcn; R_RAX=(uintptr_t)fn((void*)R_RDI, (void*)R_RSI, (uint32_t)R_RDX, (uintptr_t)R_RCX); }
+void iFEppiV(x64emu_t *emu, uintptr_t fcn) { iFEppiV_t fn = (iFEppiV_t)fcn; R_RAX=fn(emu, (void*)R_RDI, (void*)R_RSI, (int32_t)R_RDX, (void*)(R_RSP + 8)); }
 void iFEpppp(x64emu_t *emu, uintptr_t fcn) { iFEpppp_t fn = (iFEpppp_t)fcn; R_RAX=fn(emu, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX); }
 void iFipppi(x64emu_t *emu, uintptr_t fcn) { iFipppi_t fn = (iFipppi_t)fcn; R_RAX=fn((int32_t)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX, (int32_t)R_R8); }
 void iFEpippppp(x64emu_t *emu, uintptr_t fcn) { iFEpippppp_t fn = (iFEpippppp_t)fcn; R_RAX=fn(emu, (void*)R_RDI, (int32_t)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (void*)R_R9, *(void**)(R_RSP + 8)); }
diff --git a/src/wrapped/generated/wrapper.h b/src/wrapped/generated/wrapper.h
index 7c053833..b134b8fb 100644
--- a/src/wrapped/generated/wrapper.h
+++ b/src/wrapped/generated/wrapper.h
@@ -32,6 +32,7 @@ typedef void (*wrapper_t)(x64emu_t* emu, uintptr_t fnc);
 
 void vFE(x64emu_t *emu, uintptr_t fnc);
 void vFv(x64emu_t *emu, uintptr_t fnc);
+void vFi(x64emu_t *emu, uintptr_t fnc);
 void vFp(x64emu_t *emu, uintptr_t fnc);
 void iFE(x64emu_t *emu, uintptr_t fnc);
 void iFv(x64emu_t *emu, uintptr_t fnc);
@@ -104,6 +105,7 @@ void pFEppi(x64emu_t *emu, uintptr_t fnc);
 void pFEppp(x64emu_t *emu, uintptr_t fnc);
 void pFppiL(x64emu_t *emu, uintptr_t fnc);
 void pFppuL(x64emu_t *emu, uintptr_t fnc);
+void iFEppiV(x64emu_t *emu, uintptr_t fnc);
 void iFEpppp(x64emu_t *emu, uintptr_t fnc);
 void iFipppi(x64emu_t *emu, uintptr_t fnc);
 void iFEpippppp(x64emu_t *emu, uintptr_t fnc);
diff --git a/src/wrapped/wrappedlibc.c b/src/wrapped/wrappedlibc.c
index e7ac5156..b86980e7 100755
--- a/src/wrapped/wrappedlibc.c
+++ b/src/wrapped/wrappedlibc.c
@@ -413,7 +413,7 @@ int EXPORT my_atexit(x64emu_t* emu, void *p)
     AddCleanup(emu, p);
     return 0;
 }
-#if 0
+
 int my_getcontext(x64emu_t* emu, void* ucp);
 int my_setcontext(x64emu_t* emu, void* ucp);
 int my_makecontext(x64emu_t* emu, void* ucp, void* fnc, int32_t argc, void* argv);
@@ -429,7 +429,6 @@ int my_swapcontext(x64emu_t* emu, void* ucp1, void* ucp2);
 // this one is defined in elfloader.c
 int my_dl_iterate_phdr(x64emu_t *emu, void* F, void *data);
 
-#endif
 pid_t EXPORT my_fork(x64emu_t* emu)
 {
     // execute atforks prepare functions, in reverse order
diff --git a/src/wrapped/wrappedlibc_private.h b/src/wrapped/wrappedlibc_private.h
index b199f408..1451abbb 100755
--- a/src/wrapped/wrappedlibc_private.h
+++ b/src/wrapped/wrappedlibc_private.h
@@ -283,9 +283,9 @@ GOM(__cxa_finalize, vFEp)
 //GOW(execve, 
 //GO(execvp, 
 //GOW(execvpe, 
-//GO(_exit, 
-//GO(exit, 
-//GOW(_Exit, 
+GO(_exit, vFi)
+GO(exit, vFi)
+GOW(_Exit, vFi)
 //GO(explicit_bzero, 
 //GO(__explicit_bzero_chk, 
 //GO(faccessat, 
@@ -472,7 +472,7 @@ GOW(fwrite, LFpLLp)
 //GOW(getc, 
 //GO(getchar, 
 //GO(getchar_unlocked, 
-//GOW(getcontext, 
+GOM(getcontext, iFEp)   //Weak
 //GOW(getc_unlocked, 
 //GO(get_current_dir_name, 
 //GOW(getcwd, 
@@ -1086,7 +1086,7 @@ GOM(__libc_start_main, iFEpippppp)
 //GO(__lxstat64, 
 //GO(__madvise, 
 //GOW(madvise, 
-//GOW(makecontext, 
+GOM(makecontext, iFEppiV)   //weak
 //GOW(mallinfo, 
 GO(malloc, pFL) // need to wrap to clear allocated memory?
 //GO(malloc_get_state, 
@@ -1869,7 +1869,7 @@ GO(strlen, LFp)
 //GO(svcunixfd_create, 
 //GO(svc_unregister, 
 //GO(swab, 
-//GOW(swapcontext, 
+GOM(swapcontext, iFEpp) //Weak
 //GOW(swapoff, 
 //GOW(swapon, 
 //GO(swprintf,