about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2021-03-03 20:57:16 +0100
committerptitSeb <sebastien.chev@gmail.com>2021-03-03 20:57:16 +0100
commit12c8d4340b89bbe96123d145f0868528de102b7a (patch)
tree654bf700096e9e19b37bc9a895cc8d20fee0a092 /src
parent8ecc312f387818dbc39665e209157ec1b4c23f36 (diff)
downloadbox64-12c8d4340b89bbe96123d145f0868528de102b7a.tar.gz
box64-12c8d4340b89bbe96123d145f0868528de102b7a.zip
Some work on Mod/RM 64bits decoding (with RIP relative addressing)
Diffstat (limited to 'src')
-rwxr-xr-xsrc/emu/x64emu.c3
-rwxr-xr-xsrc/emu/x64emu_private.h4
-rwxr-xr-xsrc/emu/x64run.c60
-rwxr-xr-xsrc/emu/x64run_private.c4
-rwxr-xr-xsrc/emu/x64run_private.h287
5 files changed, 191 insertions, 167 deletions
diff --git a/src/emu/x64emu.c b/src/emu/x64emu.c
index f691d780..20b187b2 100755
--- a/src/emu/x64emu.c
+++ b/src/emu/x64emu.c
@@ -58,9 +58,10 @@ static void internalX64Setup(x64emu_t* emu, box64context_t *context, uintptr_t s
 {
     emu->context = context;
     // setup cpu helpers
-    for (int i=0; i<8; ++i)
+    for (int i=0; i<16; ++i)
         emu->sbiidx[i] = &emu->regs[i];
     emu->sbiidx[4] = &emu->zero;
+    emu->sbiidx[12] = &emu->zero;
     emu->x86emu_parity_tab = x86emu_parity_tab;
     emu->eflags.x32 = 0x202; // default flags?
     // own stack?
diff --git a/src/emu/x64emu_private.h b/src/emu/x64emu_private.h
index 9b007014..ed2413f8 100755
--- a/src/emu/x64emu_private.h
+++ b/src/emu/x64emu_private.h
@@ -42,7 +42,7 @@ typedef struct x64emu_s {
     // mmx
     mmx_regs_t  mmx[8];
     // sse
-    sse_regs_t  xmm[8];
+    sse_regs_t  xmm[16];
     uint32_t    mxcsr;
     // defered flags
     defered_flags_t df;
@@ -69,7 +69,7 @@ typedef struct x64emu_s {
     box64context_t *context;
     // cpu helpers
     reg64_t     zero;
-    reg64_t     *sbiidx[8];
+    reg64_t     *sbiidx[16];
     // scratch stack, used for alignement of double and 64bits ints on arm. 200 elements should be enough
     uint64_t    scratch[200];
     // local stack, do be deleted when emu is freed
diff --git a/src/emu/x64run.c b/src/emu/x64run.c
index 23c3a7b5..eba4c2d1 100755
--- a/src/emu/x64run.c
+++ b/src/emu/x64run.c
@@ -40,25 +40,26 @@ int Run(x64emu_t *emu, int step)
     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;
-    int rexw, rexb, rexr, rexx;
+    rex_t rex;
 
     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)
+#define F8      *(uint8_t*)(R_RIP++)
+#define F8S     *(int8_t*)(R_RIP++)
+#define F16     *(uint16_t*)(R_RIP+=2, R_RIP-2)
+#define F32     *(uint32_t*)(R_RIP+=4, R_RIP-4)
+#define F32S    *(int32_t*)(R_RIP+=4, R_RIP-4)
+#define F64     *(uint64_t*)(R_RIP+=8, R_RIP-8)
+#define F64S    *(int64_t*)(R_RIP+=8, R_RIP-8)
+#define PK(a)   *(uint8_t*)(R_RIP+a)
 #ifdef DYNAREC
 #define STEP if(step) goto stepout;
 #else
@@ -66,45 +67,54 @@ int Run(x64emu_t *emu, int step)
 #endif
 
 x64emurun:
-    ip = R_RIP;
 
 //#include "modrm.h"
     while(1) {
 #ifdef HAVE_TRACE
-        __builtin_prefetch((void*)ip, 0, 0); 
+        __builtin_prefetch((void*)R_RIP, 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);
+            || ((R_RIP >= trace_start) && (R_RIP < trace_end))) )
+                PrintTrace(emu, R_RIP, 0);
 #endif
 
         opcode = F8;
         if(opcode>=0x40 && opcode<=0x4f) {
-            // REX !
-            rexb = (opcode&0x1);
-            rexx = (opcode>>1)&1;
-            rexr = (opcode>>2)&1;
-            rexw = (opcode>>2)&1;
+            rex.rex = opcode;
             opcode = F8;
-        } else {
-            rexx = rexr = rexw = rexb = 0;
-        }
+        } else
+            rex.rex = 0;
+
         switch(opcode) {
 
+        case 0x40:
+        case 0x41:
+        case 0x42:
+        case 0x43:
+        case 0x44:
+        case 0x45:
+        case 0x46:
+        case 0x47:
+        case 0x48:
+        case 0x49:
+        case 0x4A:
+        case 0x4B:
+        case 0x4C:
+        case 0x4D:
+        case 0x4E:
+        case 0x4F:      /* Another REX */
+            --R_RIP;
+            break;
+
         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
 
diff --git a/src/emu/x64run_private.c b/src/emu/x64run_private.c
index 5ceae0a3..ab3938d0 100755
--- a/src/emu/x64run_private.c
+++ b/src/emu/x64run_private.c
@@ -24,8 +24,8 @@
 #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 PARITY32(x)   (((emu->x64emu_parity_tab[(x) / 32] >> ((x) % 32)) & 1) == 0)
+#define PARITY64(x)   (PARITY64((x)>>32)^PARITY64((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))
diff --git a/src/emu/x64run_private.h b/src/emu/x64run_private.h
index 21c7f722..7fb668f7 100755
--- a/src/emu/x64run_private.h
+++ b/src/emu/x64run_private.h
@@ -6,6 +6,17 @@
 #include "x64emu_private.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;
+    };
+} rex_t;
+
 static inline uint8_t Fetch8(x64emu_t *emu) {return *(uint8_t*)(R_RIP++);}
 static inline int8_t Fetch8s(x64emu_t *emu) {return *(int8_t*)(R_RIP++);}
 static inline uint16_t Fetch16(x64emu_t *emu)
@@ -62,144 +73,146 @@ static inline void Push(x64emu_t *emu, uint64_t v)
 
 // the op code definition can be found here: http://ref.x86asm.net/geek32.html
 
-//static inline reg32_t* GetECommon(x64emu_t* emu, uint32_t m)
-//{
-//    if (m<=7) {
-//        if(m==0x4) {
-//            uint8_t sib = Fetch8(emu);
-//            uintptr_t base = ((sib&0x7)==5)?Fetch32(emu):(emu->regs[(sib&0x7)].dword[0]); // base
-//            base += (emu->sbiidx[(sib>>3)&7]->sdword[0] << (sib>>6));
-//            return (reg32_t*)base;
-//        } else if (m==0x5) { //disp32
-//            return (reg32_t*)Fetch32(emu);
-//        }
-//        return (reg32_t*)(emu->regs[m].dword[0]);
-//    } else {
-//        uintptr_t base;
-//        if((m&7)==4) {
-//            uint8_t sib = Fetch8(emu);
-//            base = emu->regs[(sib&0x7)].dword[0]; // base
-//            base += (emu->sbiidx[(sib>>3)&7]->sdword[0] << (sib>>6));
-//        } else {
-//            base = emu->regs[(m&0x7)].dword[0];
-//        }
-//        base+=(m&0x80)?Fetch32s(emu):Fetch8s(emu);
-//        return (reg32_t*)base;
-//    }
-//}
-
-//static inline reg32_t* GetEb(x64emu_t *emu, uint32_t v)
-//{
-//    uint32_t m = v&0xC7;    // filter Eb
-//    if(m>=0xC0) {
-//        int lowhigh = (m&4)>>2;
-//         return (reg32_t *)(((char*)(&emu->regs[(m&0x03)]))+lowhigh);  //?
-//    } else return GetECommon(emu, m);
-//}
-
-//static inline reg32_t* GetEd(x64emu_t *emu, uint32_t v)
-//{
-//    uint32_t m = v&0xC7;    // filter Ed
-//    if(m>=0xC0) {
-//         return &emu->regs[(m&0x07)];
-//    } else return GetECommon(emu, m);
-//}
+static inline reg64_t* GetECommon(x64emu_t* emu, rex_t rex, uint8_t m)
+{
+    if (m<=7) {
+        if(m==0x4) {
+            uint8_t sib = Fetch8(emu);
+            uintptr_t base = ((sib&0x7)==5)?Fetch32(emu):(emu->regs[(sib&0x7)].q[0]+(rex.b<<4)); // base
+            base += (emu->sbiidx[((sib>>3)&7)+(rex.x<<4)]->sq[0] << (sib>>6));
+            return (reg64_t*)base;
+        } else if (m==0x5) { //disp32
+            uintptr_t base = Fetch32(emu);
+            return (reg64_t*)(base+R_RIP);
+        }
+        return (reg64_t*)(emu->regs[m].q[0]+(rex.b<<4));
+    } else {
+        uintptr_t base;
+        if((m&7)==4) {
+            uint8_t sib = Fetch8(emu);
+            base = emu->regs[(sib&0x7)+(rex.b<<4)].q[0]; // base
+            base += (emu->sbiidx[((sib>>3)&7)+(rex.x<<4)]->sq[0] << (sib>>6));
+        } else {
+            base = emu->regs[(m&0x7)+(rex.b<<4)].q[0];
+        }
+        base+=(m&0x80)?Fetch32s(emu):Fetch8s(emu);
+        return (reg64_t*)base;
+    }
+}
+
+static inline reg64_t* GetEb(x64emu_t *emu, rex_t rex, uint8_t v)
+{
+    // rex ignored here
+    uint8_t m = v&0xC7;    // filter Eb
+    if(m>=0xC0) {
+        int lowhigh = (m&4)>>2;
+         return (reg64_t *)(((char*)(&emu->regs[(m&0x03)]))+lowhigh);  //?
+    } else return GetECommon(emu, rex, m);
+}
+
+static inline reg64_t* GetEd(x64emu_t *emu, rex_t rex, uint8_t v)
+{
+    uint8_t m = v&0xC7;    // filter Ed
+    if(m>=0xC0) {
+         return &emu->regs[(m&0x07)+(rex.b<<4)];
+    } else return GetECommon(emu, rex, m);
+}
 
 #define GetEw GetEd
 
-//static inline reg32_t* GetEw16(x64emu_t *emu, uint32_t v)
-//{
-//    uint32_t m = v&0xC7;    // filter Ed
-//    if(m>=0xC0) {
-//         return &emu->regs[(m&0x07)];
-//    } else {
-//        uint32_t base = 0;
-//        switch(m&7) {
-//            case 0: base = R_BX+R_SI; break;
-//            case 1: base = R_BX+R_DI; break;
-//            case 2: base = R_BP+R_SI; break;
-//            case 3: base = R_BP+R_DI; break;
-//            case 4: base =      R_SI; break;
-//            case 5: base =      R_DI; break;
-//            case 6: base =      R_BP; break;
-//            case 7: base =      R_BX; break;
-//        }
-//        switch((m>>6)&3) {
-//            case 0: if(m==6) base = Fetch16(emu); break;
-//            case 1: base += Fetch8s(emu); break;
-//            case 2: base += Fetch16s(emu); break;
-//            // case 3 is C0..C7, already dealt with
-//        }
-//        return (reg32_t*)base;
-//    }
-//}
-
-//static inline reg32_t* GetEw16off(x64emu_t *emu, uint32_t v, uintptr_t offset)
-//{
-//    uint32_t m = v&0xC7;    // filter Ed
-//    if(m>=0xC0) {
-//         return &emu->regs[(m&0x07)];
-//    } else {
-//        uint32_t base = 0;
-//        switch(m&7) {
-//            case 0: base = R_BX+R_SI; break;
-//            case 1: base = R_BX+R_DI; break;
-//            case 2: base = R_BP+R_SI; break;
-//            case 3: base = R_BP+R_DI; break;
-//            case 4: base =      R_SI; break;
-//            case 5: base =      R_DI; break;
-//            case 6: base =      R_BP; break;
-//            case 7: base =      R_BX; break;
-//        }
-//        switch((m>>6)&3) {
-//            case 0: if(m==6) base = Fetch16(emu); break;
-//            case 1: base += Fetch8s(emu); break;
-//            case 2: base += Fetch16s(emu); break;
-//            // case 3 is C0..C7, already dealt with
-//        }
-//        return (reg32_t*)(base+offset);
-//    }
-//}
-
-//static inline mmx_regs_t* GetEm(x64emu_t *emu, uint32_t v)
-//{
-//    uint32_t m = v&0xC7;    // filter Ed
-//    if(m>=0xC0) {
-//         return &emu->mmx[m&0x07];
-//    } else return (mmx_regs_t*)GetECommon(emu, m);
-//}
-
-//static inline sse_regs_t* GetEx(x64emu_t *emu, uint32_t v)
-//{
-//    uint32_t m = v&0xC7;    // filter Ed
-//    if(m>=0xC0) {
-//         return &emu->xmm[m&0x07];
-//    } else return (sse_regs_t*)GetECommon(emu, m);
-//}
-
-
-//static inline reg32_t* GetG(x64emu_t *emu, uint32_t v)
-//{
-//    return &emu->regs[((v&0x38)>>3)];
-//}
-
-//static inline reg32_t* GetGb(x64emu_t *emu, uint32_t v)
-//{
-//    uint8_t m = (v&0x38)>>3;
-//    return (reg32_t*)&emu->regs[m&3].byte[m>>2];
-//}
-
-//static inline mmx_regs_t* GetGm(x64emu_t *emu, uint32_t v)
-//{
-//    uint8_t m = (v&0x38)>>3;
-//    return &emu->mmx[m&7];
-//}
-
-//static inline sse_regs_t* GetGx(x64emu_t *emu, uint32_t v)
-//{
-//    uint8_t m = (v&0x38)>>3;
-//    return &emu->xmm[m&7];
-//}
+static inline reg64_t* GetEw16(x64emu_t *emu, rex_t rex, uint8_t v)
+{
+    uint8_t m = v&0xC7;    // filter Ed
+    if(m>=0xC0) {
+         return &emu->regs[(m&0x07)];
+    } else {
+        uintptr_t base = 0;
+        switch(m&7) {
+            case 0: base = R_BX+R_SI; break;
+            case 1: base = R_BX+R_DI; break;
+            case 2: base = R_BP+R_SI; break;
+            case 3: base = R_BP+R_DI; break;
+            case 4: base =      R_SI; break;
+            case 5: base =      R_DI; break;
+            case 6: base =      R_BP; break;
+            case 7: base =      R_BX; break;
+        }
+        switch((m>>6)&3) {
+            case 0: if(m==6) base = Fetch16(emu); break;
+            case 1: base += Fetch8s(emu); break;
+            case 2: base += Fetch16s(emu); break;
+            // case 3 is C0..C7, already dealt with
+        }
+        return (reg64_t*)base;
+    }
+}
+
+static inline reg64_t* GetEw16off(x64emu_t *emu, rex_t rex, uint8_t v, uintptr_t offset)
+{
+    uint32_t m = v&0xC7;    // filter Ed
+    if(m>=0xC0) {
+         return &emu->regs[(m&0x07)];
+    } else {
+        uint32_t base = 0;
+        switch(m&7) {
+            case 0: base = R_BX+R_SI; break;
+            case 1: base = R_BX+R_DI; break;
+            case 2: base = R_BP+R_SI; break;
+            case 3: base = R_BP+R_DI; break;
+            case 4: base =      R_SI; break;
+            case 5: base =      R_DI; break;
+            case 6: base =      R_BP; break;
+            case 7: base =      R_BX; break;
+        }
+        switch((m>>6)&3) {
+            case 0: if(m==6) base = Fetch16(emu); break;
+            case 1: base += Fetch8s(emu); break;
+            case 2: base += Fetch16s(emu); break;
+            // case 3 is C0..C7, already dealt with
+        }
+        return (reg64_t*)(base+offset);
+    }
+}
+
+static inline mmx_regs_t* GetEm(x64emu_t *emu, rex_t rex, uint8_t v)
+{
+    uint8_t m = v&0xC7;    // filter Ed
+    if(m>=0xC0) {
+         return &emu->mmx[m&0x07];
+    } else return (mmx_regs_t*)GetECommon(emu, rex, m);
+}
+
+static inline sse_regs_t* GetEx(x64emu_t *emu, rex_t rex, uint8_t v)
+{
+    uint8_t m = v&0xC7;    // filter Ed
+    if(m>=0xC0) {
+         return &emu->xmm[(m&0x07)+(rex.b<<4)];
+    } else return (sse_regs_t*)GetECommon(emu, rex, m);
+}
+
+
+static inline reg64_t* GetG(x64emu_t *emu, rex_t rex, uint8_t v)
+{
+    return &emu->regs[((v&0x38)>>3)+(rex.r<<4)];
+}
+
+static inline reg64_t* GetGb(x64emu_t *emu, rex_t rex, uint8_t v)
+{
+    uint8_t m = (v&0x38)>>3;
+    return (reg64_t*)&emu->regs[m&3].byte[m>>2];
+}
+
+static inline mmx_regs_t* GetGm(x64emu_t *emu, rex_t rex, uint8_t v)
+{
+    uint8_t m = (v&0x38)>>3;
+    return &emu->mmx[m&7];
+}
+
+static inline sse_regs_t* GetGx(x64emu_t *emu, rex_t rex, uint8_t v)
+{
+    uint8_t m = (v&0x38)>>3;
+    return &emu->xmm[(m&7)+(rex.r<<4)];
+}
 
 //void UpdateFlags(x64emu_t *emu);
 
@@ -217,11 +230,11 @@ static inline void Push(x64emu_t *emu, uint64_t v)
 //void RunLock(x64emu_t *emu);
 //void RunLock66(x64emu_t *emu);
 
-//void x86Syscall(x64emu_t *emu);
+void x86Syscall(x64emu_t *emu);
 //void x86Int3(x64emu_t* emu);
 //x64emu_t* x64emu_fork(x64emu_t* e, int forktype);
 
-//uintptr_t GetSegmentBaseEmu(x64emu_t* emu, int seg);
+uintptr_t GetSegmentBaseEmu(x64emu_t* emu, int seg);
 #define GetGSBaseEmu(emu)    GetSegmentBaseEmu(emu, _GS)
 #define GetFSBaseEmu(emu)    GetSegmentBaseEmu(emu, _FS)
 #define GetESBaseEmu(emu)    GetSegmentBaseEmu(emu, _ES)