about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rwxr-xr-xsrc/dynarec/arm64/dynarec_arm64_00.c21
-rwxr-xr-xsrc/dynarec/arm64/dynarec_arm64_helper.c29
-rwxr-xr-xsrc/emu/x64emu.c14
-rwxr-xr-xsrc/emu/x64run.c242
-rw-r--r--src/emu/x64run64.c85
-rw-r--r--src/emu/x64run66.c14
-rw-r--r--src/emu/x64run67.c5
-rw-r--r--src/emu/x64run670f.c7
-rwxr-xr-xsrc/emu/x64run_private.c35
-rwxr-xr-xsrc/emu/x64run_private.h21
-rwxr-xr-xsrc/emu/x64tls.c82
-rwxr-xr-xsrc/emu/x86syscall.c2
-rwxr-xr-xsrc/include/regs.h2
-rwxr-xr-xsrc/include/x64emu.h2
-rwxr-xr-xsrc/include/x64tls.h3
-rwxr-xr-xsrc/libtools/signals.c8
16 files changed, 382 insertions, 190 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_00.c b/src/dynarec/arm64/dynarec_arm64_00.c
index 2d621ef6..11888786 100755
--- a/src/dynarec/arm64/dynarec_arm64_00.c
+++ b/src/dynarec/arm64/dynarec_arm64_00.c
@@ -1048,12 +1048,13 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
         case 0x8C:
             INST_NAME("MOV Ed, Seg");
             nextop=F8;
+            u8 = (nextop&0x38)>>3;
+            LDRw_U12(x3, xEmu, offsetof(x64emu_t, segs[u8]));
             if((nextop&0xC0)==0xC0) {   // reg <= seg
-                LDRH_U12(xRAX+(nextop&7)+(rex.b<<3), xEmu, offsetof(x64emu_t, segs[(nextop&0x38)>>3]));
+                UXTHw(xRAX+(nextop&7)+(rex.b<<3), x1);
             } else {                    // mem <= seg
-                addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
-                LDRH_U12(x3, xEmu, offsetof(x64emu_t, segs[(nextop&0x38)>>3]));
-                STH(x3, ed, fixedaddress);
+                addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
+                STH(x3, wback, fixedaddress);
                 SMWRITE2();
             }
             break;
@@ -1076,16 +1077,17 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
         case 0x8E:
             INST_NAME("MOV Seg,Ew");
             nextop = F8;
+            u8 = (nextop&0x38)>>3;
             if((nextop&0xC0)==0xC0) {
                 ed = xRAX+(nextop&7)+(rex.b<<3);
             } else {
                 SMREAD();
-                addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 1, rex, NULL, 0, 0);
-                LDH(x1, ed, fixedaddress);
+                addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
+                LDH(x1, wback, fixedaddress);
                 ed = x1;
             }
-            STRw_U12(ed, xEmu, offsetof(x64emu_t, segs[(nextop&0x38)>>3]));
-            STRw_U12(wZR, xEmu, offsetof(x64emu_t, segs_serial[(nextop&0x38)>>3]));
+            STRw_U12(ed, xEmu, offsetof(x64emu_t, segs[u8]));
+            STRw_U12(wZR, xEmu, offsetof(x64emu_t, segs_serial[u8]));
             break;
         case 0x8F:
             INST_NAME("POP Ed");
@@ -1811,9 +1813,9 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             }
             break;
         case 0xCD:
-            INST_NAME("INT n");
             u8 = F8;
             if(box64_wine && u8==0x2D) {
+                INST_NAME("INT 2D");
                 // lets do nothing
                 MESSAGE(LOG_INFO, "INT 2D Windows anti-debug hack\n");
             } else if (u8==0x80) {
@@ -1833,6 +1835,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                 LOAD_XEMU_REM();
                 jump_to_epilog(dyn, 0, xRIP, ninst);
             } else {
+                INST_NAME("INT n");
                 SETFLAGS(X_ALL, SF_SET);    // Hack to set flags in "don't care" state
                 GETIP(ip);
                 STORE_XEMU_CALL(xRIP);
diff --git a/src/dynarec/arm64/dynarec_arm64_helper.c b/src/dynarec/arm64/dynarec_arm64_helper.c
index e141655a..f2dc26d8 100755
--- a/src/dynarec/arm64/dynarec_arm64_helper.c
+++ b/src/dynarec/arm64/dynarec_arm64_helper.c
@@ -541,23 +541,34 @@ void iret_to_epilog(dynarec_arm_t* dyn, int ninst, int is64bits)
     MESSAGE(LOG_DUMP, "IRet to epilog\n");
     // POP IP
     NOTEST(x2);
-    POP1(xRIP);
-    // POP CS
-    POP1(x2);
+    if(is64bits) {
+        POP1(xRIP);
+        POP1(x2);
+        POP1(xFlags);
+    } else {
+        LDRw_S9_postindex(xRIP, xRSP, 4);
+        LDRw_S9_postindex(x2, xRSP, 4);
+        LDRw_S9_postindex(xFlags, xRSP, 4);
+    }
+    // x2 is CS
     STRH_U12(x2, xEmu, offsetof(x64emu_t, segs[_CS]));
-    STRx_U12(xZR, xEmu, offsetof(x64emu_t, segs_serial[_CS]));
-    STRx_U12(xZR, xEmu, offsetof(x64emu_t, segs_serial[_SS]));
-    // POP EFLAGS
-    POP1(xFlags);
+    STRw_U12(xZR, xEmu, offsetof(x64emu_t, segs_serial[_CS]));
+    // clean EFLAGS
     MOV32w(x1, 0x3F7FD7);
     ANDx_REG(xFlags, xFlags, x1);
     ORRx_mask(xFlags, xFlags, 1, 0b111111, 0);
     SET_DFNONE(x1);
     // POP RSP
-    POP1(x3);
+    if(is64bits) {
+        POP1(x3);   //rsp
+        POP1(x2);   //ss
+    } else {
+        LDRw_S9_postindex(x3, xRSP, 4);
+        LDRw_S9_postindex(x2, xRSP, 4);
+    }
     // POP SS
-    POP1(x2);
     STRH_U12(x2, xEmu, offsetof(x64emu_t, segs[_SS]));
+    STRw_U12(xZR, xEmu, offsetof(x64emu_t, segs_serial[_SS]));
     // set new RSP
     MOVx_REG(xRSP, x3);
     // Ret....
diff --git a/src/emu/x64emu.c b/src/emu/x64emu.c
index 3962f5b9..9de4cb18 100755
--- a/src/emu/x64emu.c
+++ b/src/emu/x64emu.c
@@ -401,6 +401,7 @@ const char* DumpCPURegs(x64emu_t* emu, uintptr_t ip, int is32bits)
     static const char* regname[] = {"RAX", "RCX", "RDX", "RBX", "RSP", "RBP", "RSI", "RDI",
                                     " R8", " R9", "R10", "R11", "R12", "R13", "R14", "R15"};
     static const char* regname32[]={"EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI"};
+    static const char* segname[] = {"ES", "CS", "SS", "DS", "FS", "GS"};
     char tmp[160];
     buff[0] = '\0';
 #ifdef HAVE_TRACE
@@ -439,6 +440,13 @@ const char* DumpCPURegs(x64emu_t* emu, uintptr_t ip, int is32bits)
         }
         strcat(buff, "\n");
     }
+    for (int i=0; i<6; ++i) {
+            sprintf(tmp, "%s=0x%04x", segname[i], emu->segs[i]);
+            strcat(buff, tmp);
+            if(i!=_GS)
+                strcat(buff, " ");
+    }
+    strcat(buff, "\n");
     if(is32bits)
         for (int i=_AX; i<=_RDI; ++i) {
 #ifdef HAVE_TRACE
@@ -527,13 +535,13 @@ void StopEmu(x64emu_t* emu, const char* reason, int is32bits)
 #endif
 }
 
-void UnimpOpcode(x64emu_t* emu)
+void UnimpOpcode(x64emu_t* emu, int is32bits)
 {
     R_RIP = emu->old_ip;
 
     int tid = syscall(SYS_gettid);
-    printf_log(LOG_NONE, "%04d|%p: Unimplemented Opcode (%02X %02X %02X %02X) %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", 
-        tid, (void*)emu->old_ip,
+    printf_log(LOG_NONE, "%04d|%p: Unimplemented %sOpcode (%02X %02X %02X %02X) %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", 
+        tid, (void*)emu->old_ip, is32bits?"32bits ":"",
         Peek(emu, -4), Peek(emu, -3), Peek(emu, -2), Peek(emu, -1),
         Peek(emu, 0), Peek(emu, 1), Peek(emu, 2), Peek(emu, 3),
         Peek(emu, 4), Peek(emu, 5), Peek(emu, 6), Peek(emu, 7),
diff --git a/src/emu/x64run.c b/src/emu/x64run.c
index 6d66ad1e..09d28836 100755
--- a/src/emu/x64run.c
+++ b/src/emu/x64run.c
@@ -49,15 +49,10 @@ int Run(x64emu_t *emu, int step)
     int step = 0;
     #endif
     uintptr_t addr = R_RIP;
-    rex_t rex;
+    rex_t rex = {0};
     int rep;    // 0 none, 1=F2 prefix, 2=F3 prefix
     int unimp = 0;
     int is32bits = (emu->segs[_CS]==0x23);
-    if(is32bits) {
-        printf_log(LOG_INFO, "Error, 32bits execution not yet supported\n");
-        emu->quit = 1;
-        return 0;
-    }
 
     if(emu->quit)
         return 0;
@@ -68,7 +63,7 @@ int Run(x64emu_t *emu, int step)
         return 0;
     }
     //ref opcode: http://ref.x64asm.net/geek32.html#xA1
-    printf_log(LOG_DEBUG, "Run X86 (%p), RIP=%p, Stack=%p is32bits=%D\n", emu, (void*)addr, (void*)R_RSP, is32bits);
+    printf_log(LOG_DEBUG, "Run X86 (%p), RIP=%p, Stack=%p is32bits=%d\n", emu, (void*)addr, (void*)R_RSP, is32bits);
 
 x64emurun:
 #ifndef TEST_INTERPRETER
@@ -81,7 +76,7 @@ x64emurun:
         if(my_context->dec && (
             (trace_end == 0) 
             || ((addr >= trace_start) && (addr < trace_end))) )
-                PrintTrace(emu, addr, 0, is32bits);
+                PrintTrace(emu, addr, 0);
 #endif
         emu->old_ip = addr;
 
@@ -95,6 +90,7 @@ x64emurun:
         while((opcode==0x3E) || (opcode==0x26))   //Branch Taken Hint ignored
             opcode = F8;
         rex.rex = 0;
+        rex.is32bits = is32bits;
         if(!is32bits)
             while(opcode>=0x40 && opcode<=0x4f) {
                 rex.rex = opcode;
@@ -244,13 +240,39 @@ x64emurun:
             else
                 cmp32(emu, R_EAX, F32);
             break;
-
+        case 0x40:
+        case 0x41:
+        case 0x42:
+        case 0x43:
+        case 0x44:
+        case 0x45:
+        case 0x46:
+        case 0x47:                      /* INC Reg (32bits only)*/
+            tmp8u = opcode&7;
+            emu->regs[tmp8u].dword[0] = inc32(emu, emu->regs[tmp8u].dword[0]);
+            break;
+        case 0x48:
+        case 0x49:
+        case 0x4A:
+        case 0x4B:
+        case 0x4C:
+        case 0x4D:
+        case 0x4E:
+        case 0x4F:                      /* DEC Reg (32bits only)*/
+            tmp8u = opcode&7;
+            emu->regs[tmp8u].dword[0] = dec32(emu, emu->regs[tmp8u].dword[0]);
+            break;
         case 0x54:                      /* PUSH ESP */
             if(rex.b)
                 Push(emu, R_R12);
             else {
-                tmp64u = R_RSP;
-                Push(emu, tmp64u);
+                if(rex.is32bits) {
+                    tmp32u = R_ESP;
+                    Push32(emu, tmp32u);
+                } else {
+                    tmp64u = R_RSP;
+                    Push(emu, tmp64u);
+                }
             }
             break;
         case 0x50:
@@ -261,7 +283,10 @@ x64emurun:
         case 0x56:
         case 0x57:                      /* PUSH Reg */
             tmp8u = (opcode&7)+(rex.b<<3);
-            Push(emu, emu->regs[tmp8u].q[0]);
+            if(rex.is32bits)
+                Push32(emu, emu->regs[tmp8u].dword[0]);
+            else
+                Push(emu, emu->regs[tmp8u].q[0]);
             break;
         case 0x58:
         case 0x59:
@@ -272,7 +297,7 @@ x64emurun:
         case 0x5E:
         case 0x5F:                      /* POP Reg */
             tmp8u = (opcode&7)+(rex.b<<3);
-            emu->regs[tmp8u].q[0] = Pop(emu);
+            emu->regs[tmp8u].q[0] = is32bits?Pop32(emu):Pop(emu);
             break;
 
         case 0x63:                      /* MOVSXD Gd,Ed */
@@ -300,6 +325,7 @@ x64emurun:
                 R_RIP = addr;
                 goto fini;
             }
+            is32bits = (emu->segs[_CS]==0x23);
             #endif
             break;
         case 0x65:                      /* GS: prefix */
@@ -315,6 +341,7 @@ x64emurun:
                 R_RIP = addr;
                 goto fini;
             }
+            is32bits = (emu->segs[_CS]==0x23);
             #endif
             break;
         case 0x66:                      /* 16bits prefix */
@@ -348,7 +375,10 @@ x64emurun:
             #endif
             break;
         case 0x68:                      /* Push Id */
-            Push(emu, F32S64);
+            if(rex.is32bits)
+                Push32(emu, F32);
+            else
+                Push(emu, F32S64);
             break;
         case 0x69:                      /* IMUL Gd,Ed,Id */
             nextop = F8;
@@ -361,8 +391,13 @@ x64emurun:
                 GD->q[0] = imul32(emu, ED->dword[0], tmp64u);
             break;
         case 0x6A:                      /* Push Ib */
-            tmp64s = F8S;
-            Push(emu, (uint64_t)tmp64s);
+            if(rex.is32bits) {
+                tmp32s = F8S;
+                Push32(emu, (uint32_t)tmp32s);
+            } else {
+                tmp64s = F8S;
+                Push(emu, (uint64_t)tmp64s);
+            }
             break;
         case 0x6B:                      /* IMUL Gd,Ed,Ib */
             nextop = F8;
@@ -589,17 +624,30 @@ x64emurun:
             else
                 GD->q[0] = tmp64u&0xffffffff;
             break;
-
+        case 0x8E:                      /* MOV Seg, Ew */
+            nextop = F8;
+            GETED(0);
+            emu->segs[((nextop&0x38)>>3)] = ED->word[0];
+            emu->segs_serial[((nextop&0x38)>>3)] = 0;
+            break;
         case 0x8F:                      /* POP Ed */
             nextop = F8;
             if(MODREG) {
                 emu->regs[(nextop&7)+(rex.b<<3)].q[0] = Pop(emu);
             } else {
-                tmp64u = Pop(emu);  // this order allows handling POP [ESP] and variant
-                GETED(0);
-                R_ESP -= sizeof(void*); // to prevent issue with SEGFAULT
-                ED->q[0] = tmp64u;
-                R_ESP += sizeof(void*);
+                if(rex.is32bits) {
+                    tmp32u = Pop32(emu);  // this order allows handling POP [ESP] and variant
+                    GETED(0);
+                    R_ESP -= 4; // to prevent issue with SEGFAULT
+                    ED->dword[0] = tmp32u;
+                    R_ESP += 4;
+                } else {
+                    tmp64u = Pop(emu);  // this order allows handling POP [ESP] and variant
+                    GETED(0);
+                    R_RSP -= sizeof(void*); // to prevent issue with SEGFAULT
+                    ED->q[0] = tmp64u;
+                    R_RSP += sizeof(void*);
+                }
             }
             break;
         case 0x90:                      /* NOP or XCHG R8, RAX*/
@@ -643,7 +691,10 @@ x64emurun:
             break;
         case 0x9C:                      /* PUSHF */
             CHECK_FLAGS(emu);
-            Push(emu, emu->eflags.x64);
+            if(rex.is32bits)
+                Push32(emu, emu->eflags.x64);
+            else
+                Push(emu, emu->eflags.x64);
             break;
         case 0x9D:                      /* POPF */
             emu->eflags.x64 = ((Pop(emu) & 0x3F7FD7)/* & (0xffff-40)*/ ) | 0x2; // mask off res2 and res3 and on res1
@@ -673,22 +724,36 @@ x64emurun:
             R_AH = (uint8_t)emu->eflags.x64;
             break;
         case 0xA0:                      /* MOV AL,Ob */
-            R_AL = *(uint8_t*)F64;
+            if(rex.is32bits)
+                R_AL = *(uint8_t*)(uintptr_t)F32;
+            else
+                R_AL = *(uint8_t*)F64;
             break;
         case 0xA1:                      /* MOV EAX,Od */
-            if(rex.w)
-                R_RAX = *(uint64_t*)F64;
-            else
-                R_RAX = *(uint32_t*)F64;
+            if(rex.is32bits)
+                R_EAX = *(int32_t*)(uintptr_t)F32;
+            else {
+                if(rex.w)
+                    R_RAX = *(uint64_t*)F64;
+                else
+                    R_RAX = *(uint32_t*)F64;
+            }
             break;
         case 0xA2:                      /* MOV Ob,AL */
-            *(uint8_t*)F64 = R_AL;
+            if(rex.is32bits)
+                *(uint8_t*)(uintptr_t)F32 = R_AL;
+            else
+                *(uint8_t*)F64 = R_AL;
             break;
         case 0xA3:                      /* MOV Od,EAX */
-            if(rex.w)
-                *(uint64_t*)F64 = R_RAX;
-            else
-                *(uint32_t*)F64 = R_EAX;
+            if(rex.is32bits)
+                *(uint32_t*)(uintptr_t)F32 = R_EAX;
+            else {
+                if(rex.w)
+                    *(uint64_t*)F64 = R_RAX;
+                else
+                    *(uint32_t*)F64 = R_EAX;
+            }
             break;
         case 0xA4:                      /* MOVSB */
             tmp8s = ACCESS_FLAG(F_DF)?-1:+1;
@@ -1107,12 +1172,12 @@ x64emurun:
             break;
         case 0xC2:                      /* RETN Iw */
             tmp16u = F16;
-            addr = Pop(emu);
+            addr = rex.is32bits?Pop32(emu):Pop(emu);
             R_RSP += tmp16u;
             STEP2
             break;
         case 0xC3:                      /* RET */
-            addr = Pop(emu);
+            addr = rex.is32bits?Pop32(emu):Pop(emu);
             STEP2
             break;
 
@@ -1135,21 +1200,34 @@ x64emurun:
         case 0xC8:                      /* ENTER Iw,Ib */
             tmp16u = F16;
             tmp8u = (F8) & 0x1f;
-            tmp64u = R_RBP;
-            Push(emu, R_RBP);
-            R_RBP = R_RSP;
-            if (tmp8u) {
-                for (tmp8u2 = 1; tmp8u2 < tmp8u; tmp8u2++) {
-                    tmp64u -= sizeof(void*);
-                    Push(emu, *((uintptr_t*)tmp64u));
+            if(rex.is32bits) {
+                tmp64u = R_EBP;
+                Push32(emu, R_EBP);
+                R_EBP = R_ESP;
+                if (tmp8u) {
+                    for (tmp8u2 = 1; tmp8u2 < tmp8u; tmp8u2++) {
+                        tmp64u -= 4;
+                        Push32(emu, *((uint32_t*)tmp64u));
+                    }
+                    Push32(emu, R_EBP);
                 }
+            } else {
+                tmp64u = R_RBP;
                 Push(emu, R_RBP);
+                R_RBP = R_RSP;
+                if (tmp8u) {
+                    for (tmp8u2 = 1; tmp8u2 < tmp8u; tmp8u2++) {
+                        tmp64u -= sizeof(void*);
+                        Push(emu, *((uintptr_t*)tmp64u));
+                    }
+                    Push(emu, R_RBP);
+                }
             }
             R_RSP -= tmp16u;
             break;
         case 0xC9:                      /* LEAVE */
             R_RSP = R_RBP;
-            R_RBP = Pop(emu);
+            R_RBP = rex.is32bits?Pop32(emu):Pop(emu);
             break;
 
         case 0xCC:                      /* INT 3 */
@@ -1179,19 +1257,19 @@ x64emurun:
             }
             break;
 
-
         case 0xCF:                      /* IRET */
-            addr = Pop(emu);
-            emu->segs[_CS] = Pop(emu)&0xffff;
+            addr = rex.is32bits?Pop32(emu):Pop(emu);
+            emu->segs[_CS] = (rex.is32bits?Pop32(emu):Pop(emu))&0xffff;
             emu->segs_serial[_CS] = 0;
-            emu->eflags.x64 = ((Pop(emu) & 0x3F7FD7)/* & (0xffff-40)*/ ) | 0x2; // mask off res2 and res3 and on res1
-            tmp64u = Pop(emu);  //RSP
-            emu->segs[_SS] = Pop(emu)&0xffff;
+            emu->eflags.x64 = (((rex.is32bits?Pop32(emu):Pop(emu)) & 0x3F7FD7)/* & (0xffff-40)*/ ) | 0x2; // mask off res2 and res3 and on res1
+            tmp64u = rex.is32bits?Pop32(emu):Pop(emu);  //RSP
+            emu->segs[_SS] = (rex.is32bits?Pop32(emu):Pop(emu))&0xffff;
             emu->segs_serial[_SS] = 0;
-            R_RSP= tmp64u;
+            R_RSP = tmp64u;
             RESET_FLAGS(emu);
             R_RIP = addr;
-            goto fini;      // exit, to recompute CS if needed
+            STEP;
+            is32bits = (emu->segs[_CS]==0x23);
             break;
         case 0xD0:                      /* GRP2 Eb,1 */
         case 0xD2:                      /* GRP2 Eb,CL */
@@ -1415,7 +1493,10 @@ x64emurun:
             break;
         case 0xE8:                      /* CALL Id */
             tmp32s = F32S; // call is relative
-            Push(emu, addr);
+            if(rex.is32bits)
+                Push32(emu, addr);
+            else
+                Push(emu, addr);
             addr += tmp32s;
             STEP2
             break;
@@ -1635,8 +1716,13 @@ x64emurun:
                     break;
                 case 2:                 /* CALL NEAR Ed */
                     GETE8(0);
-                    tmp64u = (uintptr_t)getAlternate((void*)ED->q[0]);
-                    Push(emu, addr);
+                    if(rex.is32bits) {
+                        tmp64u = (uintptr_t)ED->dword[0];
+                        Push32(emu, addr);
+                    } else {
+                        tmp64u = (uintptr_t)getAlternate((void*)ED->q[0]);
+                        Push(emu, addr);
+                    }
                     addr = tmp64u;
                     STEP2
                     break;
@@ -1648,16 +1734,27 @@ x64emurun:
                         emu->error |= ERR_ILLEGAL;
                         goto fini;
                     } else {
-                        Push(emu, R_CS);
-                        Push(emu, addr);
-                        R_RIP = addr = (uintptr_t)getAlternate((void*)ED->q[0]);   // check CS?
-                        R_CS = (ED+1)->word[0];
-                        goto fini;  // exit loop to recompute new CS...
+                        if(rex.is32bits || !rex.w) {
+                            Push32(emu, R_CS);
+                            Push32(emu, addr);
+                            addr = (uintptr_t)getAlternate((void*)(uintptr_t)ED->dword[0]);
+                            R_CS = ED->word[2];
+                        } else {
+                            Push(emu, R_CS);
+                            Push(emu, addr);
+                            addr = (uintptr_t)getAlternate((void*)ED->q[0]);
+                            R_CS = (ED+1)->word[0];
+                        }
+                        STEP2;
+                        is32bits = (emu->segs[_CS]==0x23);
                     }
                     break;
                 case 4:                 /* JMP NEAR Ed */
                     GETE8(0);
-                    addr = (uintptr_t)getAlternate((void*)ED->q[0]);
+                    if(rex.is32bits)
+                        addr = (uintptr_t)ED->dword[0];
+                    else
+                        addr = (uintptr_t)getAlternate((void*)ED->q[0]);
                     STEP2
                     break;
                 case 5:                 /* JMP FAR Ed */
@@ -1668,15 +1765,26 @@ x64emurun:
                         emu->error |= ERR_ILLEGAL;
                         goto fini;
                     } else {
-                        R_RIP = (uintptr_t)getAlternate((void*)ED->q[0]);   //check CS?
-                        R_CS = (ED+1)->word[0];
-                        goto fini;  // exit loop to recompute CS...
+                        if(rex.is32bits || !rex.w) {
+                            addr = (uintptr_t)getAlternate((void*)(uintptr_t)ED->dword[0]);   //check CS?
+                            R_CS = ED->word[2];
+                        } else {
+                            addr = (uintptr_t)getAlternate((void*)ED->q[0]);   //check CS?
+                            R_CS = (ED+1)->word[0];
+                        }
+                        STEP2;
+                        is32bits = (emu->segs[_CS]==0x23);
                     }
                     break;
                 case 6:                 /* Push Ed */
                     _GETED(0);
-                    tmp64u = ED->q[0];  // rex.w ignored
-                    Push(emu, tmp64u);  // avoid potential issue with push [esp+...]
+                    if(rex.is32bits) {
+                        tmp32u = ED->dword[0];  // rex.w ignored
+                        Push32(emu, tmp32u);  // avoid potential issue with push [esp+...]
+                    } else {
+                        tmp64u = ED->q[0];  // rex.w ignored
+                        Push(emu, tmp64u);  // avoid potential issue with push [esp+...]
+                    }
                     break;
                 default:
                     printf_log(LOG_NONE, "Illegal Opcode %p: %02X %02X %02X %02X %02X %02X\n",(void*)R_RIP, opcode, nextop, PK(2), PK(3), PK(4), PK(5));
@@ -1694,12 +1802,12 @@ x64emurun:
 
 
 fini:
-if(emu->segs[_CS]!=0x33) printf_log(LOG_NONE, "Warning, CS is not default value: 0x%x\n", emu->segs[_CS]);
+if(emu->segs[_CS]!=0x33 && emu->segs[_CS]!=0x23) printf_log(LOG_NONE, "Warning, CS is not default value: 0x%x\n", emu->segs[_CS]);
 #ifndef TEST_INTERPRETER
     printf_log(LOG_DEBUG, "End of X86 run (%p), RIP=%p, Stack=%p, unimp=%d, emu->fork=%d, emu->uc_link=%p, emu->quit=%d\n", emu, (void*)R_RIP, (void*)R_RSP, unimp, emu->fork, emu->uc_link, emu->quit);
     if(unimp) {
         emu->quit = 1;
-        UnimpOpcode(emu);
+        UnimpOpcode(emu, is32bits);
     }
     // fork handling
     if(emu->fork) {
diff --git a/src/emu/x64run64.c b/src/emu/x64run64.c
index a2d5cc74..b1fb52b7 100644
--- a/src/emu/x64run64.c
+++ b/src/emu/x64run64.c
@@ -47,10 +47,11 @@ uintptr_t Run64(x64emu_t *emu, rex_t rex, int seg, uintptr_t addr)
     opcode = F8;

     // REX prefix before the F0 are ignored

     rex.rex = 0;

-    while(opcode>=0x40 && opcode<=0x4f) {

-        rex.rex = opcode;

-        opcode = F8;

-    }

+    if(!rex.is32bits)

+        while(opcode>=0x40 && opcode<=0x4f) {

+            rex.rex = opcode;

+            opcode = F8;

+        }

     rep = 0;

     while((opcode==0xF2) || (opcode==0xF3)) {

         rep = opcode-0xF1;

@@ -412,11 +413,29 @@ uintptr_t Run64(x64emu_t *emu, rex_t rex, int seg, uintptr_t addr)
             break;

 

         case 0xA1:                      /* MOV EAX,FS:Od */

-            tmp64u = F64;

-            if(rex.w)

-                R_RAX = *(uint64_t*)(tlsdata+tmp64u);

-            else

-                R_RAX = *(uint32_t*)(tlsdata+tmp64u);

+            if(rex.is32bits) {

+                tmp64u = F32;

+                R_EAX = *(uint32_t*)(tlsdata+tmp64u);

+            } else {

+                tmp64u = F64;

+                if(rex.w)

+                    R_RAX = *(uint64_t*)(tlsdata+tmp64u);

+                else

+                    R_RAX = *(uint32_t*)(tlsdata+tmp64u);

+            }

+            break;

+

+        case 0xA3:                      /* MOV FS:Od,EAX */

+            if(rex.is32bits) {

+                tmp64u = F32;

+                *(uint32_t*)(uintptr_t)(tlsdata+tmp64u) = R_EAX;

+            } else {

+                tmp64u = F64;

+                if(rex.w)

+                    *(uint64_t*)(tlsdata+tmp64u) = R_RAX;

+                else

+                    *(uint32_t*)(tlsdata+tmp64u) = R_EAX;

+            }

             break;

 

         case 0xC6:                      /* MOV FS:Eb, Ib */

@@ -574,8 +593,13 @@ uintptr_t Run64(x64emu_t *emu, rex_t rex, int seg, uintptr_t addr)
                     }

                     break;

                 case 2:                 /* CALL NEAR Ed */

-                    tmp64u = (uintptr_t)getAlternate((void*)ED->q[0]);

-                    Push(emu, addr);

+                    if(rex.is32bits) {

+                        tmp64u = (uintptr_t)getAlternate((void*)(uintptr_t)ED->dword[0]);

+                        Push32(emu, addr);

+                    } else {

+                        tmp64u = (uintptr_t)getAlternate((void*)ED->q[0]);

+                        Push(emu, addr);

+                    }

                     addr = tmp64u;

                     break;

                 case 3:                 /* CALL FAR Ed */

@@ -585,15 +609,25 @@ uintptr_t Run64(x64emu_t *emu, rex_t rex, int seg, uintptr_t addr)
                         emu->error |= ERR_ILLEGAL;

                         return 0;

                     } else {

-                        Push16(emu, R_CS);

-                        Push(emu, addr);

-                        R_RIP = addr = ED->dword[0];

-                        R_CS = (ED+1)->word[0];

+                        if(rex.is32bits || !rex.w) {

+                            Push32(emu, R_CS);

+                            Push32(emu, addr);

+                            R_RIP = addr = ED->dword[0];

+                            R_CS = ED->word[2];

+                        } else {

+                            Push(emu, R_CS);

+                            Push(emu, addr);

+                            R_RIP = addr = ED->q[0];

+                            R_CS = (ED+1)->word[0];

+                        }

                         return 0;  // exit loop to recompute new CS...

                     }

                     break;

                 case 4:                 /* JMP NEAR Ed */

-                    addr = (uintptr_t)getAlternate((void*)ED->q[0]);

+                    if(rex.is32bits)

+                        addr = (uintptr_t)getAlternate((void*)(uintptr_t)ED->dword[0]);

+                    else

+                        addr = (uintptr_t)getAlternate((void*)ED->q[0]);

                     break;

                 case 5:                 /* JMP FAR Ed */

                     if(nextop>0xc0) {

@@ -602,14 +636,23 @@ uintptr_t Run64(x64emu_t *emu, rex_t rex, int seg, uintptr_t addr)
                         emu->error |= ERR_ILLEGAL;

                         return 0;

                     } else {

-                        R_RIP = addr = ED->q[0];

-                        R_CS = (ED+1)->word[0];

-                        return 0;  // exit loop to recompute CS...

+                        if(rex.is32bits || !rex.w) {

+                            R_RIP = addr = ED->dword[0];

+                            R_CS = ED->word[2];

+                        } else {

+                            R_RIP = addr = ED->q[0];

+                            R_CS = (ED+1)->word[0];

+                        }

                     }

                     break;

                 case 6:                 /* Push Ed */

-                    tmp64u = ED->q[0];  // rex.w ignored

-                    Push(emu, tmp64u);  // avoid potential issue with push [esp+...]

+                    if(rex.is32bits) {

+                        tmp32u = ED->dword[0];  // rex.w ignored

+                        Push32(emu, tmp32u);  // avoid potential issue with push [esp+...]

+                    } else {

+                        tmp64u = ED->q[0];  // rex.w ignored

+                        Push(emu, tmp64u);  // avoid potential issue with push [esp+...]

+                    }

                     break;

                 default:

                     printf_log(LOG_NONE, "Illegal Opcode %p: %02X %02X %02X %02X %02X %02X\n",(void*)R_RIP, opcode, nextop, PK(2), PK(3), PK(4), PK(5));

diff --git a/src/emu/x64run66.c b/src/emu/x64run66.c
index c2d53742..3698911f 100644
--- a/src/emu/x64run66.c
+++ b/src/emu/x64run66.c
@@ -647,7 +647,10 @@ uintptr_t Run66(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr)
 

     case 0xE8:                              /* CALL Id */

         tmp32s = F32S; // call is relative

-        Push(emu, addr);

+        if(rex.is32bits)

+            Push32(emu, addr);

+        else

+            Push(emu, addr);

         addr += tmp32s;

         break;

 

@@ -735,8 +738,13 @@ uintptr_t Run66(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr)
                 EW->word[0] = dec16(emu, EW->word[0]);

                 break;

             case 2:                 /* CALL NEAR Ed */

-                tmp64u = (uintptr_t)getAlternate((void*)ED->q[0]);

-                Push(emu, addr);

+                if(rex.is32bits) {

+                    tmp64u = (uintptr_t)getAlternate((void*)(uintptr_t)ED->dword[0]);

+                    Push32(emu, addr);

+                } else {

+                    tmp64u = (uintptr_t)getAlternate((void*)ED->q[0]);

+                    Push(emu, addr);

+                }

                 addr = tmp64u;

                 break;

            /*case 6:

diff --git a/src/emu/x64run67.c b/src/emu/x64run67.c
index 63fca1ab..7a03342f 100644
--- a/src/emu/x64run67.c
+++ b/src/emu/x64run67.c
@@ -348,7 +348,10 @@ uintptr_t Run67(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr)
 

     case 0xE8:                      /* CALL Id */

         tmp32s = F32S; // call is relative

-        Push(emu, addr);

+        if(rex.is32bits)

+            Push32(emu, addr);

+        else

+            Push(emu, addr);

         addr += tmp32s;

         break;

 

diff --git a/src/emu/x64run670f.c b/src/emu/x64run670f.c
index 589e5181..4e459e71 100644
--- a/src/emu/x64run670f.c
+++ b/src/emu/x64run670f.c
@@ -116,6 +116,13 @@ uintptr_t Run670F(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr)
             }
             break;
 
+        case 0xB7:                      /* MOVZX Gd,Ew */
+            nextop = F8;
+            GETEW32(0);
+            GETGD;
+            GD->q[0] = EW->word[0];
+            break;
+
     default:
         return 0;
     }
diff --git a/src/emu/x64run_private.c b/src/emu/x64run_private.c
index 57ff7c44..c8aa8794 100755
--- a/src/emu/x64run_private.c
+++ b/src/emu/x64run_private.c
@@ -1030,8 +1030,9 @@ extern uint64_t start_cnt;
 #define PK32(a)   (*(int32_t*)((uint8_t*)(ip+a)))
 #define PK64(a)   (*(int64_t*)((uint8_t*)(ip+a)))
 
-void PrintTrace(x64emu_t* emu, uintptr_t ip, int dynarec, int is32bits)
+void PrintTrace(x64emu_t* emu, uintptr_t ip, int dynarec)
 {
+    int is32bits = (emu->segs[_CS]==0x23);
     if(start_cnt) --start_cnt;
     if(!start_cnt && my_context->dec && (
             (trace_end == 0) 
@@ -1136,8 +1137,36 @@ static uint64_t F64(uintptr_t* addr) {
     return ret;
 }
 
+reg64_t* GetECommon_32(x64emu_t* emu, uintptr_t* addr, rex_t rex, uint8_t m, uintptr_t base)
+{
+    if (m<=7) {
+        if(m==0x4) {
+            uint8_t sib = F8(addr);
+            base += ((sib&0x7)==5)?((uint64_t)(int64_t)F32S(addr)):(emu->regs[(sib&0x7)+(rex.b<<3)].dword[0]); // base
+            base += (emu->sbiidx[((sib>>3)&7)+(rex.x<<3)]->sdword[0] << (sib>>6));
+            return (reg64_t*)base;
+        } else if (m==0x5) { //disp32
+            base += F32S(addr);
+            return (reg64_t*)(base);
+        }
+        return (reg64_t*)(uintptr_t)(base + emu->regs[m+(rex.b<<3)].dword[0]);
+    } else {
+        if((m&7)==4) {
+            uint8_t sib = F8(addr);
+            base += emu->regs[(sib&0x7)+(rex.b<<3)].dword[0]; // base
+            base += (emu->sbiidx[((sib>>3)&7)+(rex.x<<3)]->sdword[0] << (sib>>6));
+        } else {
+            base += emu->regs[(m&0x7)+(rex.b<<3)].dword[0];
+        }
+        base+=(m&0x80)?F32S(addr):F8S(addr);
+        return (reg64_t*)base;
+    }
+}
+
 reg64_t* GetECommon(x64emu_t* emu, uintptr_t* addr, rex_t rex, uint8_t m, uint8_t delta)
 {
+    if(rex.is32bits)
+        return GetECommon_32(emu, addr, rex, m, 0);
     if (m<=7) {
         if(m==0x4) {
             uint8_t sib = F8(addr);
@@ -1165,6 +1194,8 @@ reg64_t* GetECommon(x64emu_t* emu, uintptr_t* addr, rex_t rex, uint8_t m, uint8_
 
 reg64_t* GetECommonO(x64emu_t* emu, uintptr_t* addr, rex_t rex, uint8_t m, uint8_t delta, uintptr_t base)
 {
+    if(rex.is32bits)
+        return GetECommon_32(emu, addr, rex, m, base);
     if (m<=7) {
         if(m==0x4) {
             uint8_t sib = F8(addr);
@@ -1191,6 +1222,8 @@ reg64_t* GetECommonO(x64emu_t* emu, uintptr_t* addr, rex_t rex, uint8_t m, uint8
 
 reg64_t* GetECommon32O(x64emu_t* emu, uintptr_t* addr, rex_t rex, uint8_t m, uint8_t delta, uintptr_t base)
 {
+    if(rex.is32bits)
+        printf_log(LOG_INFO, "Warning, calling GetECommon32O with is32bits at %p\n", *addr);
     if (m<=7) {
         if(m==0x4) {
             uint8_t sib = F8(addr);
diff --git a/src/emu/x64run_private.h b/src/emu/x64run_private.h
index accf3a6e..93f6c096 100755
--- a/src/emu/x64run_private.h
+++ b/src/emu/x64run_private.h
@@ -7,15 +7,18 @@
 #include "box64context.h"
 typedef struct x64emu_s x64emu_t;
 
-typedef union rex_s {
-    uint8_t rex;
-    struct {
-        unsigned int b:1;
-        unsigned int x:1;
-        unsigned int r:1;
-        unsigned int w:1;
-        unsigned int s:4;
+typedef struct rex_s {
+    union {
+        uint8_t rex;
+        struct {
+            unsigned int b:1;
+            unsigned int x:1;
+            unsigned int r:1;
+            unsigned int w:1;
+            unsigned int s:4;
+        };
     };
+    int     is32bits;
 } rex_t;
 
 static inline uint8_t Peek(x64emu_t *emu, int offset){return *(uint8_t*)(R_RIP + offset);}
@@ -158,7 +161,7 @@ uintptr_t GetSegmentBaseEmu(x64emu_t* emu, int seg);
 const char* GetNativeName(void* p);
 
 #ifdef HAVE_TRACE
-void PrintTrace(x64emu_t* emu, uintptr_t ip, int dynarec, int is32bits);
+void PrintTrace(x64emu_t* emu, uintptr_t ip, int dynarec);
 #endif
 
 #endif //__X86RUN_PRIVATE_H_
diff --git a/src/emu/x64tls.c b/src/emu/x64tls.c
index af7c4aa0..12a6836d 100755
--- a/src/emu/x64tls.c
+++ b/src/emu/x64tls.c
@@ -15,7 +15,7 @@
 typedef struct thread_area_s
 {
              int  entry_number;
-       uintptr_t  base_addr;
+        uint64_t  base_addr;
     unsigned int  limit;
     unsigned int  seg_32bit:1;
     unsigned int  contents:2;
@@ -23,6 +23,7 @@ typedef struct thread_area_s
     unsigned int  limit_in_pages:1;
     unsigned int  seg_not_present:1;
     unsigned int  useable:1;
+    unsigned int  lm:1;
 } thread_area_t;
 typedef struct thread_area_32_s
 {
@@ -37,64 +38,11 @@ typedef struct thread_area_32_s
     unsigned int  useable:1;
 } thread_area_32_t;
 
-uint32_t my_set_thread_area(thread_area_t* td)
-{
-    printf_log(/*LOG_DEBUG*/LOG_NONE, "set_thread_area(%p[%d/base=%p/limit=%u/32bits:%u/%u/%u...])\n", td, td->entry_number, (void*)td->base_addr, td->limit_in_pages, td->seg_32bit, td->contents, td->read_exec_only);
-
-    int isempty = 0;
-    // first, check if the "user_desc", here td, is "empty"
-    if(td->read_exec_only==1 && td->seg_not_present==1)
-        if( !td->base_addr 
-         && !td->limit
-         && !td->seg_32bit 
-         && !td->contents 
-         && !td->limit_in_pages 
-         && !td->useable)
-            isempty = 1;
-    int idx = td->entry_number;
-    if(idx==-1) {
-        // find a free one
-        for (int i=9; i<15 && idx==-1; ++i)
-            if(!my_context->segtls[i].present)
-                idx=i;
-        if(idx==-1) {
-            errno = ESRCH;
-            return (uint32_t)-1;
-        }
-        td->entry_number = idx;
-    }
-    if(isempty && (td->entry_number<9 || td->entry_number>15)) {
-        errno = EINVAL;
-        return (uint32_t)-1;
-    }
-    if(isempty) {
-        memset(&my_context->segtls[td->entry_number], 0, sizeof(base_segment_t));
-        return 0;
-    }
-    if((idx<9 || idx>15)) {
-        errno = EINVAL;
-        return (uint32_t)-1;
-    }
-
-    my_context->segtls[idx].base = td->base_addr;
-    my_context->segtls[idx].limit = td->limit;
-    my_context->segtls[idx].present = 1;
-    my_context->segtls[idx].is32bits = 0;
-    if(!my_context->segtls[idx].key_init) {
-        pthread_key_create(&my_context->segtls[idx].key, NULL);
-        my_context->segtls[idx].key_init = 1;
-    }
-
-    pthread_setspecific(my_context->segtls[idx].key, (void*)my_context->segtls[idx].base);
-
-    ResetSegmentsCache(thread_get_emu());
-
-    return 0;
-}
+int GetTID();
 
-uint32_t my_set_thread_area_32(thread_area_32_t* td)
+uint32_t my_set_thread_area_32(x64emu_t* emu, thread_area_32_t* td)
 {
-    printf_log(LOG_DEBUG, "set_thread_area(%p[%d/base=%p/limit=%u/32bits:%u/%u/%u...])\n", td, td->entry_number, (void*)(uintptr_t)td->base_addr, td->limit_in_pages, td->seg_32bit, td->contents, td->read_exec_only);
+    printf_log(LOG_DEBUG, "%04d| set_thread_area_32(%p[%d/base=%p/limit=%u/32bits:%u/%u/%u...])\n", GetTID(), td, td->entry_number, (void*)(uintptr_t)td->base_addr, td->limit_in_pages, td->seg_32bit, td->contents, td->read_exec_only);
 
     int isempty = 0;
     // first, check if the "user_desc", here td, is "empty"
@@ -142,14 +90,14 @@ uint32_t my_set_thread_area_32(thread_area_32_t* td)
 
     pthread_setspecific(my_context->segtls[idx].key, (void*)my_context->segtls[idx].base);
 
-    ResetSegmentsCache(thread_get_emu());
+    ResetSegmentsCache(emu);
 
     return 0;
 }
 
 uint32_t my_modify_ldt(x64emu_t* emu, int op, thread_area_t* td, int size)
 {
-    printf_log(/*LOG_DEBUG*/LOG_INFO, "modify_ldt(0x%x, %p[0x%x/base=%p/limit=%u/32bits:%u/%u/%u...], %d)\n", op, td, td->entry_number, (void*)td->base_addr, td->limit_in_pages, td->seg_32bit, td->contents, td->read_exec_only, size);
+    printf_log(LOG_DEBUG, "%04d| modify_ldt(0x%x, %p[0x%x/base=%p/limit=%u/32bits:%u/%u/%u...], %d)\n", GetTID(), op, td, td->entry_number, (void*)td->base_addr, td->limit_in_pages, td->seg_32bit, td->contents, td->read_exec_only, size);
     if(!td) {
         errno = EFAULT;
         return (uint32_t)-1;
@@ -181,7 +129,7 @@ uint32_t my_modify_ldt(x64emu_t* emu, int op, thread_area_t* td, int size)
     return 0;
 }
 
-int GetTID();
+static void* GetSeg43Base();
 int my_arch_prctl(x64emu_t *emu, int code, void* addr)
 {
     printf_log(LOG_DEBUG, "%04d| arch_prctl(0x%x, %p) (RSP=%p, FS=0x%x, GS=0x%x)\n", GetTID(), code, addr,(void*)R_RSP, emu->segs[_FS], emu->segs[_GS]);
@@ -202,7 +150,21 @@ int my_arch_prctl(x64emu_t *emu, int code, void* addr)
         case ARCH_SET_FS:
         case ARCH_SET_GS:
             seg=(code==ARCH_SET_FS)?_FS:_GS;
+            int idx = -1;
+            // search if it's a TLS base
+            // Is this search only occurs when seg==0?
+            for (int i=9; i<15 && idx==-1; ++i)
+                if(my_context->segtls[i].present && my_context->segtls[i].base==(uintptr_t)addr)
+                    idx=i;
+            if(idx==-1 && GetSeg43Base()==addr)
+                idx = 0x43>>3;
+            // found...
+            if(idx!=-1) {
+               printf_log(LOG_DEBUG, "Changing segment selector from 0x%x to 0x%x\n", emu->segs[seg], (idx<<3) +3);
+               emu->segs[seg]=(idx<<3) +3;
+            }
             if(emu->segs[seg]==0) {
+                printf_log(LOG_DEBUG, "Warning, set seg, but it's 0!\n");
                 errno = EINVAL;
                 return -1;
             }
diff --git a/src/emu/x86syscall.c b/src/emu/x86syscall.c
index c1f7bce2..b41b0066 100755
--- a/src/emu/x86syscall.c
+++ b/src/emu/x86syscall.c
@@ -271,7 +271,7 @@ void EXPORT x86Syscall(x64emu_t *emu)
                 R_EAX = (uint32_t)-errno;
             break;*/
         case 243: // set_thread_area
-            R_EAX = my_set_thread_area_32((thread_area_32_t*)(uintptr_t)R_EBX);
+            R_EAX = my_set_thread_area_32(emu, (thread_area_32_t*)(uintptr_t)R_EBX);
             if(R_EAX==0xffffffff && errno>0)
                 R_EAX = (uint32_t)-errno;
             break;
diff --git a/src/include/regs.h b/src/include/regs.h
index 7a4ced73..a80b393e 100755
--- a/src/include/regs.h
+++ b/src/include/regs.h
@@ -17,7 +17,7 @@ enum {
 #define _DI _RDI
 
 enum {
-    _CS, _DS, _SS, _ES, _FS, _GS
+    _ES, _CS, _SS, _DS, _FS, _GS
 };
 
 
diff --git a/src/include/x64emu.h b/src/include/x64emu.h
index dd324add..e9ad201c 100755
--- a/src/include/x64emu.h
+++ b/src/include/x64emu.h
@@ -49,7 +49,7 @@ void AddCleanup(x64emu_t *emu, void *p, void* dso_handle);
 void AddCleanup1Arg(x64emu_t *emu, void *p, void* a, void* dso_handle);
 void CallCleanup(x64emu_t *emu, void* p);
 void CallAllCleanup(x64emu_t *emu);
-void UnimpOpcode(x64emu_t* emu);
+void UnimpOpcode(x64emu_t* emu, int is32bits);
 
 uint64_t ReadTSC(x64emu_t* emu);
 
diff --git a/src/include/x64tls.h b/src/include/x64tls.h
index b99e3bc0..66f0d9eb 100755
--- a/src/include/x64tls.h
+++ b/src/include/x64tls.h
@@ -4,8 +4,7 @@
 typedef struct thread_area_s thread_area_t;
 typedef struct thread_area_32_s thread_area_32_t;
 
-uint32_t my_set_thread_area(thread_area_t* td);
-uint32_t my_set_thread_area_32(thread_area_32_t* td);
+uint32_t my_set_thread_area_32(x64emu_t* emu, thread_area_32_t* td);
 uint32_t my_modify_ldt(x64emu_t* emu, int op, thread_area_t* td, int size);
 
 tlsdatasize_t* getTLSData(box64context_t *context);
diff --git a/src/libtools/signals.c b/src/libtools/signals.c
index 76fd50eb..c38cacbb 100755
--- a/src/libtools/signals.c
+++ b/src/libtools/signals.c
@@ -1242,7 +1242,7 @@ exit(-1);
         }
         if(log_minimum<=box64_log) {
             static const char* reg_name[] = {"RAX", "RCX", "RDX", "RBX", "RSP", "RBP", "RSI", "RDI", " R8", " R9","R10","R11", "R12","R13","R14","R15"};
-            static const char* seg_name[] = {"CS", "DS", "SS", "ES", "GS", "FS"};
+            static const char* seg_name[] = {"ES", "CS", "SS", "DS", "GS", "FS"};
             int shown_regs = 0;
 #ifdef DYNAREC
             uint32_t hash = 0;
@@ -1293,11 +1293,15 @@ exit(-1);
 #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(!shown_regs)
+            if(!shown_regs) {
                 for (int i=0; i<16; ++i) {
                     if(!(i%4)) printf_log(log_minimum, "\n");
                     printf_log(log_minimum, "%s:0x%016llx ", reg_name[i], emu->regs[i].q[0]);
                 }
+                printf_log(log_minimum, "\n");
+                for (int i=0; i<6; ++i)
+                    printf_log(log_minimum, "%s:0x%04x ", seg_name[i], emu->segs[i]);
+            }
             if(sig==SIGILL)
                 printf_log(log_minimum, " opcode=%02X %02X %02X %02X %02X %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], ((uint8_t*)x64pc)[0], ((uint8_t*)x64pc)[1], ((uint8_t*)x64pc)[2], ((uint8_t*)x64pc)[3], ((uint8_t*)x64pc)[4]);
             else if(sig==SIGBUS)