about summary refs log tree commit diff stats
path: root/src/emu
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2021-03-03 16:43:42 +0100
committerptitSeb <sebastien.chev@gmail.com>2021-03-03 16:43:42 +0100
commitf4829a8ce42b1abbcc8621802d6c6fad3a56cd5d (patch)
tree211276c3587721126ded00be46487bf23b605591 /src/emu
parentf73fbd3cee38b4c0086c934d73972375c9c8c7d6 (diff)
downloadbox64-f4829a8ce42b1abbcc8621802d6c6fad3a56cd5d.tar.gz
box64-f4829a8ce42b1abbcc8621802d6c6fad3a56cd5d.zip
More infrastructure added to elf and x64 emu
Diffstat (limited to 'src/emu')
-rwxr-xr-xsrc/emu/x64emu.c72
-rwxr-xr-xsrc/emu/x64run.c118
-rwxr-xr-xsrc/emu/x64run_private.c787
-rwxr-xr-xsrc/emu/x64syscall.c186
-rwxr-xr-xsrc/emu/x64tls.c213
5 files changed, 1340 insertions, 36 deletions
diff --git a/src/emu/x64emu.c b/src/emu/x64emu.c
index 3ce6b63e..ea3cc138 100755
--- a/src/emu/x64emu.c
+++ b/src/emu/x64emu.c
@@ -14,8 +14,8 @@
 #include "box64context.h"
 #include "x64run.h"
 #include "x64run_private.h"
-//#include "callback.h"
-//#include "bridge.h"
+#include "callback.h"
+#include "bridge.h"
 #ifdef DYNAREC
 #include "custommem.h"
 #endif
@@ -43,16 +43,16 @@ uint32_t* GetParityTab()
     return x86emu_parity_tab;
 }
 
-//void PushExit(x64emu_t* emu)
-//{
-//    uintptr_t endMarker = AddCheckBridge(my_context->system, NULL, NULL, 0);
-//    Push(emu, endMarker);
-//}
+void PushExit(x64emu_t* emu)
+{
+    uintptr_t endMarker = AddCheckBridge(my_context->system, NULL, NULL, 0);
+    Push(emu, endMarker);
+}
 
-//void* GetExit()
-//{
-//    return (void*)AddCheckBridge(my_context->system, NULL, NULL, 0);
-//}
+void* GetExit()
+{
+    return (void*)AddCheckBridge(my_context->system, NULL, NULL, 0);
+}
 
 static void internalX64Setup(x64emu_t* emu, box64context_t *context, uintptr_t start, uintptr_t stack, int stacksize, int ownstack)
 {
@@ -403,31 +403,31 @@ void UnimpOpcode(x64emu_t* emu)
     emu->error |= ERR_UNIMPL;
 }
 
-//void EmuCall(x64emu_t* emu, uintptr_t addr)
-//{
-//    uint64_t old_rsp = R_RSP;
-//    uint64_t old_rbx = R_RBX;
-//    uint64_t old_rdi = R_RDI;
-//    uint64_t old_rsi = R_RSI;
-//    uint64_t old_rbp = R_RBP;
-//    uint64_t old_rip = R_RIP;
-//    PushExit(emu);
-//    R_RIP = addr;
-//    emu->df = d_none;
-//    Run(emu, 0);
-//    emu->quit = 0;  // reset Quit flags...
-//    emu->df = d_none;
-//    if(emu->quitonlongjmp && emu->longjmp) {
-//        emu->longjmp = 0;   // don't change anything because of the longjmp
-//    } else {
-//        R_RBX = old_ebx;
-//        R_RDI = old_edi;
-//        R_RSI = old_esi;
-//        R_RBP = old_ebp;
-//        R_RSP = old_esp;
-//        R_RIP = old_eip;  // and set back instruction pointer
-//    }
-//}
+void EmuCall(x64emu_t* emu, uintptr_t addr)
+{
+    uint64_t old_rsp = R_RSP;
+    uint64_t old_rbx = R_RBX;
+    uint64_t old_rdi = R_RDI;
+    uint64_t old_rsi = R_RSI;
+    uint64_t old_rbp = R_RBP;
+    uint64_t old_rip = R_RIP;
+    PushExit(emu);
+    R_RIP = addr;
+    emu->df = d_none;
+    Run(emu, 0);
+    emu->quit = 0;  // reset Quit flags...
+    emu->df = d_none;
+    if(emu->quitonlongjmp && emu->longjmp) {
+        emu->longjmp = 0;   // don't change anything because of the longjmp
+    } else {
+        R_RBX = old_rbx;
+        R_RDI = old_rdi;
+        R_RSI = old_rsi;
+        R_RBP = old_rbp;
+        R_RSP = old_rsp;
+        R_RIP = old_rip;  // and set back instruction pointer
+    }
+}
 
 uint64_t ReadTSC(x64emu_t* emu)
 {
diff --git a/src/emu/x64run.c b/src/emu/x64run.c
new file mode 100755
index 00000000..39533d8b
--- /dev/null
+++ b/src/emu/x64run.c
@@ -0,0 +1,118 @@
+#define _GNU_SOURCE
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "debug.h"
+#include "box64stack.h"
+#include "x64emu.h"
+#include "x64run.h"
+#include "x64emu_private.h"
+#include "x64run_private.h"
+//#include "x64primop.h"
+#include "x64trace.h"
+#include "x87emu_private.h"
+#include "box64context.h"
+//#include "my_cpuid.h"
+#include "bridge.h"
+//#include "signals.h"
+#ifdef DYNAREC
+#include "../dynarec/arm_lock_helper.h"
+#endif
+
+int my_setcontext(x64emu_t* emu, void* ucp);
+
+int Run(x64emu_t *emu, int step)
+{
+    uint8_t opcode;
+    uint8_t nextop;
+    reg64_t *oped;
+    uint8_t tmp8u, tmp8u2;
+    int8_t tmp8s;
+    uint16_t tmp16u, tmp16u2;
+    int16_t tmp16s;
+    uint32_t tmp32u, tmp32u2, tmp32u3;
+    uint64_t tmp64u, tmp64u2, tmp64u3;
+    int32_t tmp32s, tmp32s2;
+    int64_t tmp64s, tmp64s2;
+    uintptr_t ip;
+    double d;
+    float f;
+    int64_t ll;
+    sse_regs_t *opex, eax1;
+    mmx_regs_t *opem, eam1;
+
+    if(emu->quit)
+        return 0;
+
+    //ref opcode: http://ref.x64asm.net/geek32.html#xA1
+    printf_log(LOG_DEBUG, "Run X86 (%p), RIP=%p, Stack=%p\n", emu, (void*)R_RIP, emu->context->stack);
+#define F8      *(uint8_t*)(ip++)
+#define F8S     *(int8_t*)(ip++)
+#define F16     *(uint16_t*)(ip+=2, ip-2)
+#define F32     *(uint32_t*)(ip+=4, ip-4)
+#define F32S    *(int32_t*)(ip+=4, ip-4)
+#define PK(a)   *(uint8_t*)(ip+a)
+#ifdef DYNAREC
+#define STEP if(step) goto stepout;
+#else
+#define STEP
+#endif
+
+x64emurun:
+    ip = R_RIP;
+
+//#include "modrm.h"
+    while(1) {
+#ifdef HAVE_TRACE
+        __builtin_prefetch((void*)ip, 0, 0); 
+        emu->prev2_ip = emu->prev_ip;
+        emu->prev_ip = R_RIP;
+        R_RIP=ip;
+        if(my_context->dec && (
+            (trace_end == 0) 
+            || ((ip >= trace_start) && (ip < trace_end))) )
+                PrintTrace(emu, ip, 0);
+#endif
+
+        opcode = F8;
+        switch(opcode) {
+
+        default:
+            emu->old_ip = R_RIP;
+            R_RIP = ip;
+            UnimpOpcode(emu);
+            goto fini;
+        }
+    }
+#ifdef DYNAREC
+stepout:
+    emu->old_ip = R_RIP;
+    R_RIP = ip;
+    return 0;
+#endif
+
+fini:
+    // fork handling
+//    if(emu->fork) {
+//        if(step)
+//            return 0;
+//        int forktype = emu->fork;
+//        emu->quit = 0;
+//        emu->fork = 0;
+//        emu = x64emu_fork(emu, forktype);
+//        goto x64emurun;
+//    }
+    // setcontext handling
+//    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
new file mode 100755
index 00000000..5ceae0a3
--- /dev/null
+++ b/src/emu/x64run_private.c
@@ -0,0 +1,787 @@
+#define _GNU_SOURCE         /* See feature_test_macros(7) */
+#include <dlfcn.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_TRACE
+#include <unistd.h>
+#include <sys/syscall.h>
+#endif
+
+#include "debug.h"
+#include "box64stack.h"
+#include "x64emu.h"
+#include "x64run.h"
+#include "x64run_private.h"
+#include "x64emu_private.h"
+#include "box64context.h"
+#include "x64run.h"
+#include "librarian.h"
+#include "elfloader.h"
+#ifdef HAVE_TRACE
+#include "x64trace.h"
+#endif
+#include "x64tls.h"
+
+#define PARITY2(x)   (((emu->x64emu_parity_tab[(x) / 32] >> ((x) % 32)) & 1) == 0)
+#define PARITY(x)   (PARITY2((x)>>32)^PARITY2((x)&0xffffffff))
+#define XOR2(x) 	(((x) ^ ((x)>>1)) & 0x1)
+
+int32_t EXPORT my___libc_start_main(x64emu_t* emu, int *(main) (int, char * *, char * *), int argc, char * * ubp_av, void (*init) (void), void (*fini) (void), void (*rtld_fini) (void), void (* stack_end))
+{
+    //TODO: register rtld_fini
+    //TODO: register fini
+    // let's cheat and set all args...
+    Push(emu, (uint64_t)my_context->envv);
+    Push(emu, (uint64_t)my_context->argv);
+    Push(emu, (uint64_t)my_context->argc);
+    if(init) {
+        PushExit(emu);
+        R_RIP=(uint64_t)*init;
+        printf_log(LOG_DEBUG, "Calling init(%p) from __libc_start_main\n", *init);
+        DynaRun(emu);
+        if(emu->error)  // any error, don't bother with more
+            return 0;
+        emu->quit = 0;
+    }
+    printf_log(LOG_DEBUG, "Transfert to main(%d, %p, %p)=>%p from __libc_start_main\n", my_context->argc, my_context->argv, my_context->envv, main);
+    // call main and finish
+    PushExit(emu);
+    R_RIP=(uint64_t)main;
+#ifdef DYNAREC
+    DynaRun(emu);
+#endif
+    return 0;
+}
+
+const char* GetNativeName(void* p)
+{
+    static char buff[500] = {0};
+    Dl_info info;
+    if(dladdr(p, &info)==0) {
+        const char *ret = GetNameOffset(my_context->maplib, p);
+        if(ret)
+            return ret;
+        sprintf(buff, "%s(%p)", "???", p);
+        return buff;
+    } else {
+        if(info.dli_sname) {
+            strcpy(buff, info.dli_sname);
+            if(info.dli_fname) {
+                strcat(buff, " ("); strcat(buff, info.dli_fname); strcat(buff, ")");
+            }
+        } else {
+            sprintf(buff, "%s(%s/%p)", "???", info.dli_fname, p);
+            return buff;
+        }
+    }
+    return buff;
+}
+#if 0
+void UpdateFlags(x64emu_t *emu)
+{
+    uint32_t cc;
+    uint32_t lo, hi;
+    uint32_t bc;
+    uint32_t cnt;
+
+    switch(emu->df) {
+        case d_none:
+            return;
+        case d_add8:
+            CONDITIONAL_SET_FLAG(emu->res & 0x100, F_CF);
+            CONDITIONAL_SET_FLAG((emu->res & 0xff) == 0, F_ZF);
+            CONDITIONAL_SET_FLAG(emu->res & 0x80, F_SF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+
+            cc = (emu->op1 & emu->op2) | ((~emu->res) & (emu->op1 | emu->op2));
+            CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
+            CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
+            break;
+        case d_add16:
+            CONDITIONAL_SET_FLAG(emu->res & 0x10000, F_CF);
+            CONDITIONAL_SET_FLAG((emu->res & 0xffff) == 0, F_ZF);
+            CONDITIONAL_SET_FLAG(emu->res & 0x8000, F_SF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            cc = (emu->op1 & emu->op2) | ((~emu->res) & (emu->op1 | emu->op2));
+            CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
+            CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
+            break;
+        case d_add32:
+            lo = (emu->op2 & 0xFFFF) + (emu->op1 & 0xFFFF);
+            hi = (lo >> 16) + (emu->op2 >> 16) + (emu->op1 >> 16);
+            CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF);
+            CONDITIONAL_SET_FLAG(!emu->res, F_ZF);
+            CONDITIONAL_SET_FLAG(emu->res & 0x80000000, F_SF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            cc = (emu->op1 & emu->op2) | ((~emu->res) & (emu->op1 | emu->op2));
+            CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
+            CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
+            break;
+        case d_and8:
+            CLEAR_FLAG(F_OF);
+            CLEAR_FLAG(F_CF);
+            CLEAR_FLAG(F_AF);
+            CONDITIONAL_SET_FLAG(emu->res & 0x80, F_SF);
+            CONDITIONAL_SET_FLAG(emu->res == 0, F_ZF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            break;
+        case d_and16:
+            CLEAR_FLAG(F_OF);
+            CLEAR_FLAG(F_CF);
+            CLEAR_FLAG(F_AF);
+            CONDITIONAL_SET_FLAG(emu->res & 0x8000, F_SF);
+            CONDITIONAL_SET_FLAG(emu->res == 0, F_ZF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            break;
+        case d_and32:
+            CLEAR_FLAG(F_OF);
+            CLEAR_FLAG(F_CF);
+            CLEAR_FLAG(F_AF);
+            CONDITIONAL_SET_FLAG(emu->res & 0x80000000, F_SF);
+            CONDITIONAL_SET_FLAG(emu->res == 0, F_ZF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            break;
+        case d_dec8:
+            CONDITIONAL_SET_FLAG(emu->res & 0x80, F_SF);
+            CONDITIONAL_SET_FLAG((emu->res & 0xff) == 0, F_ZF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            bc = (emu->res & (~emu->op1 | 1)) | (~emu->op1 & 1);
+            CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
+            CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+            break;
+        case d_dec16:
+            CONDITIONAL_SET_FLAG(emu->res & 0x8000, F_SF);
+            CONDITIONAL_SET_FLAG((emu->res & 0xffff) == 0, F_ZF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            bc = (emu->res & (~emu->op1 | 1)) | (~emu->op1 & 1);
+            CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
+            CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+            break;
+        case d_dec32:
+            CONDITIONAL_SET_FLAG(emu->res & 0x80000000, F_SF);
+            CONDITIONAL_SET_FLAG(!emu->res, F_ZF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            bc = (emu->res & (~emu->op1 | 1)) | (~emu->op1 & 1);
+            CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
+            CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+            break;
+        case d_inc8:
+            CONDITIONAL_SET_FLAG((emu->res & 0xff) == 0, F_ZF);
+            CONDITIONAL_SET_FLAG(emu->res & 0x80, F_SF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            cc = ((1 & emu->op1) | (~emu->res)) & (1 | emu->op1);
+            CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
+            CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
+            break;
+        case d_inc16:
+            CONDITIONAL_SET_FLAG((emu->res & 0xffff) == 0, F_ZF);
+            CONDITIONAL_SET_FLAG(emu->res & 0x8000, F_SF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            cc = (1 & emu->op1) | ((~emu->res) & (1 | emu->op1));
+            CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
+            CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
+            break;
+        case d_inc32:
+            CONDITIONAL_SET_FLAG(!emu->res, F_ZF);
+            CONDITIONAL_SET_FLAG(emu->res & 0x80000000, F_SF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            cc = (1 & emu->op1) | ((~emu->res) & (1 | emu->op1));
+            CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
+            CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
+            break;
+        case d_imul8:
+            lo = emu->res & 0xff;
+            hi = (emu->res>>8)&0xff;
+            if (((lo & 0x80) == 0 && hi == 0x00) ||
+                ((lo & 0x80) != 0 && hi == 0xFF)) {
+                CLEAR_FLAG(F_CF);
+                CLEAR_FLAG(F_OF);
+            } else {
+                SET_FLAG(F_CF);
+                SET_FLAG(F_OF);
+            }
+            CONDITIONAL_SET_FLAG(PARITY(lo & 0xff), F_PF);
+            break;
+        case d_imul16:
+            lo = (uint16_t)emu->res;
+            hi = (uint16_t)(emu->res >> 16);
+            if (((lo & 0x8000) == 0 && hi == 0x00) ||
+                ((lo & 0x8000) != 0 && hi == 0xFFFF)) {
+                CLEAR_FLAG(F_CF);
+                CLEAR_FLAG(F_OF);
+            } else {
+                SET_FLAG(F_CF);
+                SET_FLAG(F_OF);
+            }
+            CONDITIONAL_SET_FLAG(PARITY(lo & 0xff), F_PF);
+            break;
+        case d_imul32:
+            if (((emu->res & 0x80000000) == 0 && emu->op1 == 0x00) ||
+                ((emu->res & 0x80000000) != 0 && emu->op1 == 0xFFFFFFFF)) {
+                CLEAR_FLAG(F_CF);
+                CLEAR_FLAG(F_OF);
+            } else {
+                SET_FLAG(F_CF);
+                SET_FLAG(F_OF);
+            }
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            break;
+        case d_mul8:
+            lo = emu->res & 0xff;
+            hi = (emu->res>>8)&0xff;
+            if (hi == 0) {
+                CLEAR_FLAG(F_CF);
+                CLEAR_FLAG(F_OF);
+            } else {
+                SET_FLAG(F_CF);
+                SET_FLAG(F_OF);
+            }
+            CONDITIONAL_SET_FLAG(PARITY(lo & 0xff), F_PF);
+            break;
+        case d_mul16:
+            lo = (uint16_t)emu->res;
+            hi = (uint16_t)(emu->res >> 16);
+            if (hi == 0) {
+                CLEAR_FLAG(F_CF);
+                CLEAR_FLAG(F_OF);
+            } else {
+                SET_FLAG(F_CF);
+                SET_FLAG(F_OF);
+            }
+            CONDITIONAL_SET_FLAG(PARITY(lo & 0xff), F_PF);
+            break;
+        case d_mul32:
+            if (emu->op1 == 0) {
+                CLEAR_FLAG(F_CF);
+                CLEAR_FLAG(F_OF);
+            } else {
+                SET_FLAG(F_CF);
+                SET_FLAG(F_OF);
+            }
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            break;
+        case d_or8:
+            CLEAR_FLAG(F_OF);
+            CLEAR_FLAG(F_CF);
+            CLEAR_FLAG(F_AF);
+            CONDITIONAL_SET_FLAG(emu->res & 0x80, F_SF);
+            CONDITIONAL_SET_FLAG(emu->res == 0, F_ZF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            break;
+        case d_or16:
+            CLEAR_FLAG(F_OF);
+            CLEAR_FLAG(F_CF);
+            CLEAR_FLAG(F_AF);
+            CONDITIONAL_SET_FLAG(emu->res & 0x8000, F_SF);
+            CONDITIONAL_SET_FLAG(emu->res == 0, F_ZF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            break;
+        case d_or32:
+            CLEAR_FLAG(F_OF);
+            CLEAR_FLAG(F_CF);
+            CLEAR_FLAG(F_AF);
+            CONDITIONAL_SET_FLAG(emu->res & 0x80000000, F_SF);
+            CONDITIONAL_SET_FLAG(emu->res == 0, F_ZF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            break;
+        case d_neg8:
+            CONDITIONAL_SET_FLAG(emu->op1 != 0, F_CF);
+            CONDITIONAL_SET_FLAG((emu->res & 0xff) == 0, F_ZF);
+            CONDITIONAL_SET_FLAG(emu->res & 0x80, F_SF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            bc = emu->res | emu->op1;
+            CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
+            CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+            break;
+        case d_neg16:
+            CONDITIONAL_SET_FLAG(emu->op1 != 0, F_CF);
+            CONDITIONAL_SET_FLAG((emu->res & 0xffff) == 0, F_ZF);
+            CONDITIONAL_SET_FLAG(emu->res & 0x8000, F_SF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            bc = emu->res | emu->op1;
+            CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
+            CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+            break;
+        case d_neg32:
+            CONDITIONAL_SET_FLAG(emu->op1 != 0, F_CF);
+            CONDITIONAL_SET_FLAG(!emu->res, F_ZF);
+            CONDITIONAL_SET_FLAG(emu->res & 0x80000000, F_SF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            bc = emu->res | emu->op1;
+            CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
+            CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+            break;
+        case d_shl8:
+            if (emu->op2 < 8) {
+                cnt = emu->op2 % 8;
+                if (cnt > 0) {
+                    cc = emu->op1 & (1 << (8 - cnt));
+                    CONDITIONAL_SET_FLAG(cc, F_CF);
+                    CONDITIONAL_SET_FLAG((emu->res & 0xff) == 0, F_ZF);
+                    CONDITIONAL_SET_FLAG(emu->res & 0x80, F_SF);
+                    CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+                }
+                if (cnt == 1) {
+                    CONDITIONAL_SET_FLAG((((emu->res & 0x80) == 0x80) ^(ACCESS_FLAG(F_CF) != 0)), F_OF);
+                } else {
+                    CLEAR_FLAG(F_OF);
+                }
+            } else {
+                CONDITIONAL_SET_FLAG((emu->op1 << (emu->op2-1)) & 0x80, F_CF);
+                CLEAR_FLAG(F_OF);
+                CLEAR_FLAG(F_SF);
+                SET_FLAG(F_PF);
+                SET_FLAG(F_ZF);
+            }
+            break;
+        case d_shl16:
+            if (emu->op2 < 16) {
+                cnt = emu->op2 % 16;
+                if (cnt > 0) {
+                    cc = emu->op1 & (1 << (16 - cnt));
+                    CONDITIONAL_SET_FLAG(cc, F_CF);
+                    CONDITIONAL_SET_FLAG((emu->res & 0xffff) == 0, F_ZF);
+                    CONDITIONAL_SET_FLAG(emu->res & 0x8000, F_SF);
+                    CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+                }
+                if (cnt == 1) {
+                    CONDITIONAL_SET_FLAG(((!!(emu->res & 0x8000)) ^(ACCESS_FLAG(F_CF) != 0)), F_OF);
+                } else {
+                    CLEAR_FLAG(F_OF);
+                }
+            } else {
+                CONDITIONAL_SET_FLAG((emu->op1 << (emu->op2-1)) & 0x8000, F_CF);
+                CLEAR_FLAG(F_OF);
+                CLEAR_FLAG(F_SF);
+                SET_FLAG(F_PF);
+                SET_FLAG(F_ZF);
+            }
+            break;
+        case d_shl32:
+            if (emu->op2 > 0) {
+                cc = emu->op1 & (1 << (32 - emu->op2));
+                CONDITIONAL_SET_FLAG(cc, F_CF);
+                CONDITIONAL_SET_FLAG(!emu->res, F_ZF);
+                CONDITIONAL_SET_FLAG(emu->res & 0x80000000, F_SF);
+                CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            }
+            if (emu->op2 == 1) {
+                CONDITIONAL_SET_FLAG(((!!(emu->res & 0x80000000)) ^
+                                        (ACCESS_FLAG(F_CF) != 0)), F_OF);
+            } else {
+                CLEAR_FLAG(F_OF);
+            }
+            break;
+        case d_sar8:
+            if (emu->op2 < 8) {
+                if(emu->op2) {
+                    cc = emu->op1 & (1 << (emu->op2 - 1));
+                    CONDITIONAL_SET_FLAG(cc, F_CF);
+                    CONDITIONAL_SET_FLAG((emu->res & 0xff) == 0, F_ZF);
+                    CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+                    CONDITIONAL_SET_FLAG(emu->res & 0x80, F_SF);
+                }
+            } else {
+                if (emu->op1&0x80) {
+                    SET_FLAG(F_CF);
+                    CLEAR_FLAG(F_ZF);
+                    SET_FLAG(F_SF);
+                    SET_FLAG(F_PF);
+                } else {
+                    CLEAR_FLAG(F_CF);
+                    SET_FLAG(F_ZF);
+                    CLEAR_FLAG(F_SF);
+                    SET_FLAG(F_PF);
+                }
+            }
+            break;
+        case d_sar16:
+            if (emu->op2 < 16) {
+                if(emu->op2) {
+                    cc = emu->op1 & (1 << (emu->op2 - 1));
+                    CONDITIONAL_SET_FLAG(cc, F_CF);
+                    CONDITIONAL_SET_FLAG((emu->res & 0xffff) == 0, F_ZF);
+                    CONDITIONAL_SET_FLAG(emu->res & 0x8000, F_SF);
+                    CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+                }
+            } else {
+                if (emu->op1&0x8000) {
+                    SET_FLAG(F_CF);
+                    CLEAR_FLAG(F_ZF);
+                    SET_FLAG(F_SF);
+                    SET_FLAG(F_PF);
+                } else {
+                    CLEAR_FLAG(F_CF);
+                    SET_FLAG(F_ZF);
+                    CLEAR_FLAG(F_SF);
+                    SET_FLAG(F_PF);
+                }
+            }
+            break;
+        case d_sar32:
+            if(emu->op2) {
+                cc = emu->op1 & (1 << (emu->op2 - 1));
+                CONDITIONAL_SET_FLAG(cc, F_CF);
+                CONDITIONAL_SET_FLAG(emu->res == 0, F_ZF);
+                CONDITIONAL_SET_FLAG(emu->res & 0x80000000, F_SF);
+                CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            }
+            break;
+        case d_shr8:
+            if (emu->op2 < 8) {
+                cnt = emu->op2 % 8;
+                if (cnt > 0) {
+                    cc = emu->op1 & (1 << (cnt - 1));
+                    CONDITIONAL_SET_FLAG(cc, F_CF);
+                    CONDITIONAL_SET_FLAG((emu->res & 0xff) == 0, F_ZF);
+                    CONDITIONAL_SET_FLAG(emu->res & 0x80, F_SF);
+                    CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+                }
+                if (cnt == 1) {
+                    CONDITIONAL_SET_FLAG(XOR2(emu->res >> 6), F_OF);
+                }
+            } else {
+                CONDITIONAL_SET_FLAG((emu->op1 >> (emu->op2-1)) & 0x1, F_CF);
+                CLEAR_FLAG(F_SF);
+                SET_FLAG(F_PF);
+                SET_FLAG(F_ZF);
+            }
+            break;
+        case d_shr16:
+            if (emu->op2 < 16) {
+                cnt = emu->op2 % 16;
+                if (cnt > 0) {
+                    cc = emu->op1 & (1 << (cnt - 1));
+                    CONDITIONAL_SET_FLAG(cc, F_CF);
+                    CONDITIONAL_SET_FLAG((emu->res & 0xffff) == 0, F_ZF);
+                    CONDITIONAL_SET_FLAG(emu->res & 0x8000, F_SF);
+                    CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+                }
+                if (cnt == 1) {
+                    CONDITIONAL_SET_FLAG(XOR2(emu->res >> 14), F_OF);
+                }
+            } else {
+                CLEAR_FLAG(F_CF);
+                SET_FLAG(F_ZF);
+                CLEAR_FLAG(F_SF);
+                SET_FLAG(F_PF);
+            }
+            break;
+        case d_shr32:
+            cnt = emu->op2;
+            if (cnt > 0) {
+                cc = emu->op1 & (1 << (cnt - 1));
+                CONDITIONAL_SET_FLAG(cc, F_CF);
+                CONDITIONAL_SET_FLAG(!emu->res, F_ZF);
+                CONDITIONAL_SET_FLAG(emu->res & 0x80000000, F_SF);
+                CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            }
+            if (cnt == 1) {
+                CONDITIONAL_SET_FLAG(XOR2(emu->res >> 30), F_OF);
+            }
+            break;
+        case d_sub8:
+            CONDITIONAL_SET_FLAG(emu->res & 0x80, F_SF);
+            CONDITIONAL_SET_FLAG((emu->res & 0xff) == 0, F_ZF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            bc = (emu->res & (~emu->op1 | emu->op2)) | (~emu->op1 & emu->op2);
+            CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
+            CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
+            CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+            break;
+        case d_sub16:
+            CONDITIONAL_SET_FLAG(emu->res & 0x8000, F_SF);
+            CONDITIONAL_SET_FLAG((emu->res & 0xffff) == 0, F_ZF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            bc = (emu->res & (~emu->op1 | emu->op2)) | (~emu->op1 & emu->op2);
+            CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
+            CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
+            CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+            break;
+        case d_sub32:
+            CONDITIONAL_SET_FLAG(emu->res & 0x80000000, F_SF);
+            CONDITIONAL_SET_FLAG(!emu->res, F_ZF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            bc = (emu->res & (~emu->op1 | emu->op2)) | (~emu->op1 & emu->op2);
+            CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
+            CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
+            CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+            break;
+        case d_xor8:
+            CLEAR_FLAG(F_OF);
+            CONDITIONAL_SET_FLAG(emu->res & 0x80, F_SF);
+            CONDITIONAL_SET_FLAG(emu->res == 0, F_ZF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            CLEAR_FLAG(F_CF);
+            CLEAR_FLAG(F_AF);
+            break;
+        case d_xor16:
+            CLEAR_FLAG(F_OF);
+            CONDITIONAL_SET_FLAG(emu->res & 0x8000, F_SF);
+            CONDITIONAL_SET_FLAG(emu->res == 0, F_ZF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            CLEAR_FLAG(F_CF);
+            CLEAR_FLAG(F_AF);
+            break;
+        case d_xor32:
+            CLEAR_FLAG(F_OF);
+            CONDITIONAL_SET_FLAG(emu->res & 0x80000000, F_SF);
+            CONDITIONAL_SET_FLAG(emu->res == 0, F_ZF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            CLEAR_FLAG(F_CF);
+            CLEAR_FLAG(F_AF);
+            break;
+        case d_cmp8:
+            CLEAR_FLAG(F_CF);
+            CONDITIONAL_SET_FLAG(emu->res & 0x80, F_SF);
+            CONDITIONAL_SET_FLAG((emu->res & 0xff) == 0, F_ZF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            bc = (emu->res & (~emu->op1 | emu->op2)) | (~emu->op1 & emu->op2);
+            CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
+            CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
+            CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+            break;
+        case d_cmp16:
+            CONDITIONAL_SET_FLAG(emu->res & 0x8000, F_SF);
+            CONDITIONAL_SET_FLAG((emu->res & 0xffff) == 0, F_ZF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            bc = (emu->res & (~emu->op1 | emu->op2)) | (~emu->op1 & emu->op2);
+            CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
+            CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
+            CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+            break;
+        case d_cmp32:
+        	CONDITIONAL_SET_FLAG(emu->res & 0x80000000, F_SF);
+        	CONDITIONAL_SET_FLAG(!emu->res, F_ZF);
+        	CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+        	bc = (emu->res & (~emu->op1 | emu->op2)) | (~emu->op1 & emu->op2);
+        	CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
+        	CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
+        	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+            break;
+        case d_tst8:
+        	CLEAR_FLAG(F_OF);
+        	CONDITIONAL_SET_FLAG(emu->res & 0x80, F_SF);
+        	CONDITIONAL_SET_FLAG(emu->res == 0, F_ZF);
+        	CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+        	CLEAR_FLAG(F_CF);
+            break;
+        case d_tst16:
+            CLEAR_FLAG(F_OF);
+            CONDITIONAL_SET_FLAG(emu->res & 0x8000, F_SF);
+            CONDITIONAL_SET_FLAG(emu->res == 0, F_ZF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            CLEAR_FLAG(F_CF);
+            break;
+        case d_tst32:
+        	CLEAR_FLAG(F_OF);
+        	CONDITIONAL_SET_FLAG(emu->res & 0x80000000, F_SF);
+        	CONDITIONAL_SET_FLAG(emu->res == 0, F_ZF);
+        	CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+        	CLEAR_FLAG(F_CF);
+            break;
+        case d_adc8:
+            CONDITIONAL_SET_FLAG(emu->res & 0x100, F_CF);
+            CONDITIONAL_SET_FLAG((emu->res & 0xff) == 0, F_ZF);
+            CONDITIONAL_SET_FLAG(emu->res & 0x80, F_SF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            cc = (emu->op1 & emu->op2) | ((~emu->res) & (emu->op1 | emu->op2));
+            CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
+            CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
+            break;
+        case d_adc16:
+            CONDITIONAL_SET_FLAG(emu->res & 0x10000, F_CF);
+            CONDITIONAL_SET_FLAG((emu->res & 0xffff) == 0, F_ZF);
+            CONDITIONAL_SET_FLAG(emu->res & 0x8000, F_SF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            cc = (emu->op1 & emu->op2) | ((~emu->res) & (emu->op1 | emu->op2));
+            CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
+            CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
+            break;
+        case d_adc32:
+            if(emu->res == (emu->op1+emu->op2)) {
+                lo = (emu->op1 & 0xFFFF) + (emu->op2 & 0xFFFF);
+            } else {
+                lo = 1 + (emu->op1 & 0xFFFF) + (emu->op2 & 0xFFFF);
+            }
+            hi = (lo >> 16) + (emu->op1 >> 16) + (emu->op2 >> 16);
+            CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF);
+            CONDITIONAL_SET_FLAG(!emu->res, F_ZF);
+            CONDITIONAL_SET_FLAG(emu->res & 0x80000000, F_SF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            cc = (emu->op2 & emu->op1) | ((~emu->res) & (emu->op2 | emu->op1));
+            CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
+            CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
+            break;
+        case d_sbb8:
+            CONDITIONAL_SET_FLAG(emu->res & 0x80, F_SF);
+            CONDITIONAL_SET_FLAG((emu->res & 0xff) == 0, F_ZF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            bc = (emu->res & (~emu->op1 | emu->op2)) | (~emu->op1 & emu->op2);
+            CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
+            CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
+            CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+            break;
+        case d_sbb16:
+            CONDITIONAL_SET_FLAG(emu->res & 0x8000, F_SF);
+            CONDITIONAL_SET_FLAG((emu->res & 0xffff) == 0, F_ZF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            bc = (emu->res & (~emu->op1 | emu->op2)) | (~emu->op1 & emu->op2);
+            CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
+            CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
+            CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+            break;
+        case d_sbb32:
+            CONDITIONAL_SET_FLAG(emu->res & 0x80000000, F_SF);
+            CONDITIONAL_SET_FLAG(!emu->res, F_ZF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            bc = (emu->res & (~emu->op1 | emu->op2)) | (~emu->op1 & emu->op2);
+            CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
+            CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
+            CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+            break;
+        case d_rol8:
+            if(emu->op2 == 1) {
+                CONDITIONAL_SET_FLAG((emu->res + (emu->res >> 7)) & 1, F_OF);
+            }
+        	CONDITIONAL_SET_FLAG(emu->res & 0x1, F_CF);
+            break;
+        case d_rol16:
+            if(emu->op2 == 1) {
+                CONDITIONAL_SET_FLAG((emu->res + (emu->res >> 15)) & 1, F_OF);
+            }
+        	CONDITIONAL_SET_FLAG(emu->res & 0x1, F_CF);
+            break;
+        case d_rol32:
+            if(emu->op2 == 1) {
+                CONDITIONAL_SET_FLAG((emu->res + (emu->res >> 31)) & 1, F_OF);
+            }
+        	CONDITIONAL_SET_FLAG(emu->res & 0x1, F_CF);
+            break;
+        case d_ror8:
+            if(emu->op2 == 1) {
+                CONDITIONAL_SET_FLAG(XOR2(emu->res >> 6), F_OF);
+            }
+            CONDITIONAL_SET_FLAG(emu->res & (1 << 7), F_CF);
+            break;
+        case d_ror16:
+            if(emu->op2 == 1) {
+                CONDITIONAL_SET_FLAG(XOR2(emu->res >> 14), F_OF);
+            }
+            CONDITIONAL_SET_FLAG(emu->res & (1 << 15), F_CF);
+            break;
+        case d_ror32:
+            if(emu->op2 == 1) {
+                CONDITIONAL_SET_FLAG(XOR2(emu->res >> 30), F_OF);
+            }
+            CONDITIONAL_SET_FLAG(emu->res & (1 << 31), F_CF);
+            break;
+
+        case d_unknown:
+            printf_log(LOG_NONE, "Box86: %p trying to evaluate Unknown defered Flags\n", (void*)R_RIP);
+            break;
+    }
+    RESET_FLAGS(emu);
+}
+#endif
+
+uintptr_t GetSegmentBaseEmu(x64emu_t* emu, int seg)
+{
+    if(emu->segs_serial[seg] != emu->context->sel_serial) {
+        emu->segs_offs[seg] = (uintptr_t)GetSegmentBase(emu->segs[seg]);
+        emu->segs_serial[seg] = emu->context->sel_serial;
+    }
+    return emu->segs_offs[seg];
+}
+
+
+const char* getAddrFunctionName(uintptr_t addr)
+{
+    static char ret[1000];
+    uint32_t sz = 0;
+    uintptr_t start = 0;
+    const char* symbname = FindNearestSymbolName(FindElfAddress(my_context, addr), (void*)addr, &start, &sz);
+    if(symbname && addr>=start && (addr<(start+sz) || !sz)) {
+        if(addr==start)
+            sprintf(ret, "%s/%s", ElfName(FindElfAddress(my_context, addr)), symbname);
+        else
+            sprintf(ret, "%s/%s + %ld", ElfName(FindElfAddress(my_context, addr)), symbname, addr - start);
+    } else
+        sprintf(ret, "???");
+    return ret;
+}
+
+void printFunctionAddr(uintptr_t nextaddr, const char* text)
+{
+    uint32_t sz = 0;
+    uintptr_t start = 0;
+    const char* symbname = FindNearestSymbolName(FindElfAddress(my_context, nextaddr), (void*)nextaddr, &start, &sz);
+    if(symbname && nextaddr>=start && (nextaddr<(start+sz) || !sz)) {
+        if(nextaddr==start)
+            printf_log(LOG_NONE, " (%s%s/%s)", text, ElfName(FindElfAddress(my_context, nextaddr)), symbname);
+        else
+            printf_log(LOG_NONE, " (%s%s/%s + %ld)", text, ElfName(FindElfAddress(my_context, nextaddr)), symbname, nextaddr - start);
+    }
+}
+
+#ifdef HAVE_TRACE
+extern uint64_t start_cnt;
+#define PK(a)   (*(uint8_t*)(ip+a))
+#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)
+{
+    if(start_cnt) --start_cnt;
+    if(!start_cnt && my_context->dec && (
+            (trace_end == 0) 
+            || ((ip >= trace_start) && (ip < trace_end))) ) {
+        int tid = syscall(SYS_gettid);
+        pthread_mutex_lock(&my_context->mutex_trace);
+#ifdef DYNAREC
+        if((my_context->trace_tid != tid) || (my_context->trace_dynarec!=dynarec)) {
+            printf_log(LOG_NONE, "Thread %04d| (%s) |\n", tid, dynarec?"dyn":"int");
+            my_context->trace_tid = tid;
+            my_context->trace_dynarec = dynarec;
+        }
+#else
+        if(my_context->trace_tid != tid) {
+            printf_log(LOG_NONE, "Thread %04d|\n", tid);
+            my_context->trace_tid = tid;
+        }
+#endif
+        printf_log(LOG_NONE, "%s", DumpCPURegs(emu, ip));
+        if(PK(0)==0xcc && PK(1)=='S' && PK(2)=='C') {
+            uint64_t a = *(uint64_t*)(ip+3);
+            if(a==0) {
+                printf_log(LOG_NONE, "%p: Exit x86emu\n", (void*)ip);
+            } else {
+                printf_log(LOG_NONE, "%p: Native call to %p => %s\n", (void*)ip, (void*)a, GetNativeName(*(void**)(ip+7)));
+            }
+        } else {
+            printf_log(LOG_NONE, "%s", DecodeX64Trace(my_context->dec, ip));
+            uint8_t peek = PK(0);
+            if(peek==0xC3 || peek==0xC2) {
+                printf_log(LOG_NONE, " => %p", *(void**)(R_RSP));
+                printFunctionAddr(*(uintptr_t*)(R_RSP), "=> ");
+            } else if(peek==0x55) {
+                printf_log(LOG_NONE, " => STACK_TOP: %p", *(void**)(R_RSP));
+                printFunctionAddr(ip, "here: ");
+            } else if(peek==0xE8) { // Call
+                uintptr_t nextaddr = ip + 5 + PK64(1);
+                printFunctionAddr(nextaddr, "=> ");
+            } else if(peek==0xFF) {
+                if(PK(1)==0x25) {
+                    uintptr_t nextaddr = ip + 6 + PK64(2);
+                    printFunctionAddr(nextaddr, "=> ");
+                }
+            }
+            printf_log(LOG_NONE, "\n");
+        }
+        pthread_mutex_unlock(&my_context->mutex_trace);
+    }
+}
+
+#endif
diff --git a/src/emu/x64syscall.c b/src/emu/x64syscall.c
new file mode 100755
index 00000000..5359939c
--- /dev/null
+++ b/src/emu/x64syscall.c
@@ -0,0 +1,186 @@
+#define _GNU_SOURCE         /* See feature_test_macros(7) */
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sys/syscall.h>   /* For SYS_xxx definitions */
+#include <unistd.h>
+#include <time.h>
+#include <sys/mman.h>
+#include <sys/select.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <asm/stat.h>
+#include <errno.h>
+#include <sched.h>
+#include <sys/wait.h>
+#include <sys/utsname.h>
+#include <sys/resource.h>
+#include <poll.h>
+
+#include "debug.h"
+#include "box64stack.h"
+#include "x64emu.h"
+#include "x64run.h"
+#include "x64emu_private.h"
+#include "x64run_private.h"
+//#include "x64primop.h"
+#include "x64trace.h"
+//#include "myalign.h"
+#include "box64context.h"
+//#include "callback.h"
+//#include "signals.h"
+//#include "x64tls.h"
+
+typedef struct x64_sigaction_s x64_sigaction_t;
+
+
+//int32_t my_getrandom(x64emu_t* emu, void* buf, uint32_t buflen, uint32_t flags);
+//int of_convert(int flag);
+//int32_t my_open(x64emu_t* emu, void* pathname, int32_t flags, uint32_t mode);
+
+//int my_sigaction(x64emu_t* emu, int signum, const x86_sigaction_t *act, x86_sigaction_t *oldact);
+//int32_t my_execve(x64emu_t* emu, const char* path, char* const argv[], char* const envp[]);
+//void* my_mmap(x64emu_t* emu, void *addr, unsigned long length, int prot, int flags, int fd, int offset);
+//void* my_mmap64(x64emu_t* emu, void *addr, unsigned long length, int prot, int flags, int fd, int64_t offset);
+//int my_munmap(x64emu_t* emu, void* addr, unsigned long length);
+//int my_mprotect(x64emu_t* emu, void *addr, unsigned long len, int prot);
+
+// cannot include <fcntl.h>, it conflict with some asm includes...
+#ifndef O_NONBLOCK
+#define O_NONBLOCK 04000
+#endif
+#undef fcntl
+int fcntl(int fd, int cmd, ... /* arg */ );
+
+// Syscall table for x86_64 can be found 
+typedef struct scwrap_s {
+    int x64s;
+    int nats;
+    int nbpars;
+} scwrap_t;
+
+scwrap_t syscallwrap[] = {
+    { 0, __NR_read, 3 },  // wrapped so SA_RESTART can be handled by libc
+    { 1, __NR_write, 3 }, // same
+    { 2, __NR_open, 3 },  // flags need transformation
+    { 3, __NR_close, 1 },   // wrapped so SA_RESTART can be handled by libc
+    { 4, __NR_stat, 2 },
+    { 5, __NR_fstat, 2},
+};
+
+struct mmap_arg_struct {
+    unsigned long addr;
+    unsigned long len;
+    unsigned long prot;
+    unsigned long flags;
+    unsigned long fd;
+    unsigned long offset;
+};
+
+//struct x86_pt_regs {
+//	long ebx;
+//	long ecx;
+//	long edx;
+//	long esi;
+//	long edi;
+//	long ebp;
+//	long eax;
+//	int  xds;
+//	int  xes;
+//	int  xfs;
+//	int  xgs;
+//	long orig_eax;
+//	long eip;
+//	int  xcs;
+//	long eflags;
+//	long esp;
+//	int  xss;
+//};
+
+//int clone_fn(void* arg)
+//{
+//    x64emu_t *emu = (x64emu_t*)arg;
+//    R_RAX = 0;
+//    DynaRun(emu);
+//    int ret = R_EAX;
+//    FreeX64Emu(&emu);
+//    return ret;
+//}
+
+void EXPORT x64Syscall(x64emu_t *emu)
+{
+    RESET_FLAGS(emu);
+    uint32_t s = R_EAX;
+    printf_log(LOG_DEBUG, "%p: Calling syscall 0x%02X (%d) %p %p %p %p %p %p", (void*)R_RIP, s, s, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_R10, (void*)R_R8, (void*)R_R9); 
+    // check wrapper first
+    int cnt = sizeof(syscallwrap) / sizeof(scwrap_t);
+    for (int i=0; i<cnt; i++) {
+        if(syscallwrap[i].x64s == s) {
+            int sc = syscallwrap[i].nats;
+            switch(syscallwrap[i].nbpars) {
+                case 0: *(int64_t*)&R_RAX = syscall(sc); break;
+                case 1: *(int64_t*)&R_RAX = syscall(sc, R_RDI); break;
+                case 2: if(s==33) {printf_log(LOG_DUMP, " => sys_access(\"%s\", %ld)\n", (char*)R_RDI, R_RSI);}; *(int64_t*)&R_RAX = syscall(sc, R_RDI, R_RSI); break;
+                case 3: *(int64_t*)&R_RAX = syscall(sc, R_RDI, R_RSI, R_RDX); break;
+                case 4: *(int64_t*)&R_RAX = syscall(sc, R_RDI, R_RSI, R_RDX, R_R10); break;
+                case 5: *(int64_t*)&R_RAX = syscall(sc, R_RDI, R_RSI, R_RDX, R_R10, R_R8); break;
+                case 6: *(int64_t*)&R_RAX = syscall(sc, R_RDI, R_RSI, R_RDX, R_R10, R_R8, R_R9); break;
+                default:
+                   printf_log(LOG_NONE, "ERROR, Unimplemented syscall wrapper (%d, %d)\n", s, syscallwrap[i].nbpars); 
+                   emu->quit = 1;
+                   return;
+            }
+            printf_log(LOG_DEBUG, " => 0x%x\n", R_EAX);
+            return;
+        }
+    }
+    switch (s) {
+        default:
+            printf_log(LOG_INFO, "Error: Unsupported Syscall 0x%02Xh (%d)\n", s, s);
+            emu->quit = 1;
+            emu->error |= ERR_UNIMPL;
+            return;
+    }
+    printf_log(LOG_DEBUG, " => 0x%x\n", R_EAX);
+}
+
+#define stack(n) (R_RSP+8+n)
+#define i32(n)  *(int32_t*)stack(n)
+#define u32(n)  *(uint32_t*)stack(n)
+#define u64(n)  *(uint64_t*)stack(n)
+#define p(n)    *(void**)stack(n)
+
+uint32_t EXPORT my_syscall(x64emu_t *emu)
+{
+    uint32_t s = R_EDI;;
+    printf_log(LOG_DUMP, "%p: Calling libc syscall 0x%02X (%d) %p %p %p %p %p\n", (void*)R_RIP, s, s, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (void*)R_R9); 
+    // check wrapper first
+    int cnt = sizeof(syscallwrap) / sizeof(scwrap_t);
+    for (int i=0; i<cnt; i++) {
+        if(syscallwrap[i].x64s == s) {
+            int sc = syscallwrap[i].nats;
+            switch(syscallwrap[i].nbpars) {
+                case 0: return syscall(sc);
+                case 1: return syscall(sc, R_RSI);
+                case 2: return syscall(sc, R_RSI, R_RDX);
+                case 3: return syscall(sc, R_RSI, R_RDX, R_RCX);
+                case 4: return syscall(sc, R_RSI, R_RDX, R_RCX, R_R8);
+                case 5: return syscall(sc, R_RSI, R_RDX, R_RCX, R_R8, R_R9);
+                case 6: return syscall(sc, R_RSI, R_RDX, R_RCX, R_R8, R_R9, u64(0));
+                default:
+                   printf_log(LOG_NONE, "ERROR, Unimplemented syscall wrapper (%d, %d)\n", s, syscallwrap[i].nbpars); 
+                   emu->quit = 1;
+                   return 0;
+            }
+        }
+    }
+    switch (s) {
+        default:
+            printf_log(LOG_INFO, "Error: Unsupported libc Syscall 0x%02X (%d)\n", s, s);
+            emu->quit = 1;
+            emu->error |= ERR_UNIMPL;
+    }
+    return 0;
+}
diff --git a/src/emu/x64tls.c b/src/emu/x64tls.c
new file mode 100755
index 00000000..b76646b5
--- /dev/null
+++ b/src/emu/x64tls.c
@@ -0,0 +1,213 @@
+// Handling of TLS calls, include x86 specifi set_thread_area
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "debug.h"
+#include "box64context.h"
+#include "x64emu.h"
+#include "x64tls.h"
+#include "elfloader.h"
+
+typedef struct thread_area_s
+{
+             int  entry_number;
+        uintptr_t base_addr;
+    unsigned int  limit;
+    unsigned int  seg_32bit:1;
+    unsigned int  contents:2;
+    unsigned int  read_exec_only:1;
+    unsigned int  limit_in_pages:1;
+    unsigned int  seg_not_present:1;
+    unsigned int  useable:1;
+} thread_area_t;
+
+static pthread_once_t thread_key_once0 = PTHREAD_ONCE_INIT;
+static pthread_once_t thread_key_once1 = PTHREAD_ONCE_INIT;
+static pthread_once_t thread_key_once2 = PTHREAD_ONCE_INIT;
+
+static void thread_key_alloc0() {
+	pthread_key_create(&my_context->segtls[0].key, NULL);
+}
+static void thread_key_alloc1() {
+	pthread_key_create(&my_context->segtls[1].key, NULL);
+}
+static void thread_key_alloc2() {
+	pthread_key_create(&my_context->segtls[2].key, NULL);
+}
+
+uint32_t my_set_thread_area(thread_area_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*)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=0; i<3 && idx==-1; ++i)
+            if(!my_context->segtls[i].present)
+                idx=i;
+        if(idx==-1) {
+            errno = ESRCH;
+            return (uint32_t)-1;
+        }
+        idx+=7;
+        td->entry_number = idx;
+    }
+    if(isempty && (td->entry_number<7 || td->entry_number>7+2)) {
+        errno = EINVAL;
+        return (uint32_t)-1;
+    }
+    if(isempty) {
+        memset(&my_context->segtls[td->entry_number-7], 0, sizeof(base_segment_t));
+        return 0;
+    }
+    if((idx<7 || idx>7+2)) {
+        errno = EINVAL;
+        return (uint32_t)-1;
+    }
+
+    my_context->segtls[idx-7].base = td->base_addr;
+    my_context->segtls[idx-7].limit = td->limit;
+    my_context->segtls[idx-7].present = 1;
+    switch (idx-7) {
+        case 0:	pthread_once(&thread_key_once0, thread_key_alloc0); break;
+        case 1:	pthread_once(&thread_key_once1, thread_key_alloc1); break;
+        case 2:	pthread_once(&thread_key_once2, thread_key_alloc2); break;
+    }
+
+    pthread_setspecific(my_context->segtls[idx-7].key, (void*)my_context->segtls[idx-7].base);
+
+    ResetSegmentsCache(thread_get_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);
+    if(!td) {
+        errno = EFAULT;
+        return (uint32_t)-1;
+    }
+    if(op!=0x11) {
+        errno = ENOSYS;
+        return (uint32_t)-1;
+    }
+    if(!td->seg_32bit) {
+        // not handling 16bits segments for now
+        errno = EINVAL;
+        return (uint32_t)-1;
+    }
+
+    int idx = td->entry_number - 7;
+    if(idx<0 || idx>2) {
+        errno = EINVAL;
+        return (uint32_t)-1;
+    }
+
+    /*
+    my_context->segtls[idx].base = td->base_addr;
+    my_context->segtls[idx].limit = td->limit;
+    pthread_setspecific(my_context->segtls[idx].key, (void*)my_context->segtls[idx].base);
+    */
+    
+    ResetSegmentsCache(thread_get_emu());
+
+    return 0;
+}
+
+#define POS_TLS     0x50
+
+static tlsdatasize_t* setupTLSData(box64context_t* context)
+{
+    // Setup the GS segment:
+    int dtsize = context->elfsize*8;
+    void *ptr = (char*)malloc(context->tlssize+4+POS_TLS+dtsize);
+    memcpy(ptr, context->tlsdata, context->tlssize);
+    tlsdatasize_t *data = (tlsdatasize_t*)calloc(1, sizeof(tlsdatasize_t));
+    data->tlsdata = ptr;
+    data->tlssize = context->tlssize;
+    pthread_setspecific(context->tlskey, data);
+    // copy canary...
+    memset((void*)((uintptr_t)ptr+context->tlssize), 0, POS_TLS+dtsize);            // set to 0 remining bytes
+    memcpy((void*)((uintptr_t)ptr+context->tlssize+0x14), context->canary, 4);      // put canary in place
+    uintptr_t tlsptr = (uintptr_t)ptr+context->tlssize;
+    memcpy((void*)((uintptr_t)ptr+context->tlssize+0x0), &tlsptr, 4);
+    uintptr_t dtp = (uintptr_t)ptr+context->tlssize+POS_TLS;
+    memcpy((void*)(tlsptr+0x4), &dtp, 4);
+    if(dtsize) {
+        for (int i=0; i<context->elfsize; ++i) {
+            // set pointer
+            dtp = (uintptr_t)ptr + (context->tlssize + GetTLSBase(context->elfs[i]));
+            memcpy((void*)((uintptr_t)ptr+context->tlssize+POS_TLS+i*8), &dtp, 4);
+            memcpy((void*)((uintptr_t)ptr+context->tlssize+POS_TLS+i*8+4), &i, 4); // index
+        }
+    }
+    memcpy((void*)((uintptr_t)ptr+context->tlssize+0x10), &context->vsyscall, 4);  // address of vsyscall
+    return data;
+}
+
+void* fillTLSData(box64context_t *context)
+{
+        pthread_mutex_lock(&context->mutex_tls);
+        tlsdatasize_t *data = setupTLSData(context);
+        pthread_mutex_unlock(&context->mutex_tls);
+        return data;
+}
+
+void* resizeTLSData(box64context_t *context, void* oldptr)
+{
+        pthread_mutex_lock(&context->mutex_tls);
+        tlsdatasize_t* oldata = (tlsdatasize_t*)oldptr;
+        tlsdatasize_t *data = setupTLSData(context);
+        // copy the relevent old part, in case something changed
+        memcpy((void*)((uintptr_t)data->tlsdata+(context->tlssize-oldata->tlssize)), oldata->tlsdata, oldata->tlssize);
+        // all done, update new size, free old pointer and exit
+        pthread_mutex_unlock(&context->mutex_tls);
+        free_tlsdatasize(oldptr);
+        return data;
+}
+
+static void* GetSeg33Base()
+{
+    tlsdatasize_t* ptr;
+    if ((ptr = (tlsdatasize_t*)pthread_getspecific(my_context->tlskey)) == NULL) {
+        ptr = (tlsdatasize_t*)fillTLSData(my_context);
+    }
+    if(ptr->tlssize != my_context->tlssize)
+        ptr = (tlsdatasize_t*)resizeTLSData(my_context, ptr);
+    return ptr->tlsdata+ptr->tlssize;
+}
+
+void* GetSegmentBase(uint32_t desc)
+{
+    if(!desc) {
+        printf_log(LOG_NONE, "Warning, accessing segment NULL\n");
+        return NULL;
+    }
+    int base = desc>>3;
+    if(base==0xe || base==0xf)
+        return NULL;    // regular value...
+    if(base==0x6)
+        return GetSeg33Base();
+
+    if(base>6 && base<10 && my_context->segtls[base-7].present) {
+        void* ptr = pthread_getspecific(my_context->segtls[base-7].key);
+        return ptr;
+    }
+
+    printf_log(LOG_NONE, "Warning, accessing segment unknown 0x%x or unset\n", desc);
+    return NULL;
+}