about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2021-03-06 16:54:29 +0100
committerptitSeb <sebastien.chev@gmail.com>2021-03-06 16:54:29 +0100
commit1b350d24c30657c8ea8afd4f3aeeda960a0a2357 (patch)
tree2686c17ba1cca91369f05527c1176a07c1ec53db /src
parent4705ecce1a36ffe29ec894d84cba1299501705ae (diff)
downloadbox64-1b350d24c30657c8ea8afd4f3aeeda960a0a2357.tar.gz
box64-1b350d24c30657c8ea8afd4f3aeeda960a0a2357.zip
Fixed mod/rm relative computation when opcode have trailing bytes
Diffstat (limited to 'src')
-rw-r--r--src/emu/modrm.h18
-rwxr-xr-xsrc/emu/x64run.c196
-rw-r--r--src/emu/x64run0f.c22
-rw-r--r--src/emu/x64run66.c8
-rw-r--r--src/emu/x64run660f.c6
-rwxr-xr-xsrc/emu/x64run_private.c20
-rwxr-xr-xsrc/emu/x64run_private.h10
-rw-r--r--src/emu/x64rund9.c12
-rw-r--r--src/emu/x64rundb.c12
-rw-r--r--src/emu/x64runf0.c6
-rw-r--r--src/emu/x64runf20f.c4
-rw-r--r--src/emu/x64runf30f.c12
12 files changed, 188 insertions, 138 deletions
diff --git a/src/emu/modrm.h b/src/emu/modrm.h
index b95273b3..af678823 100644
--- a/src/emu/modrm.h
+++ b/src/emu/modrm.h
@@ -13,14 +13,14 @@
 #define STEP

 #endif

 

-#define GETED oped=GetEd(emu, rex, nextop)

-#define GETGD opgd=GetGd(emu, rex, nextop)

-#define GETEB oped=GetEb(emu, rex, nextop)

-#define GETGB opgd=GetGb(emu, rex, nextop)

-#define GETEW oped=GetEw(emu, rex, nextop)

-#define GETGW opgd=GetGw(emu, rex, nextop)

-#define GETEX opex=GetEx(emu, rex, nextop)

-#define GETGX opgx=GetGx(emu, rex, nextop)

+#define GETED(D)    oped=GetEd(emu, rex, nextop, D)

+#define GETGD       opgd=GetGd(emu, rex, nextop)

+#define GETEB(D)    oped=GetEb(emu, rex, nextop, D)

+#define GETGB       opgd=GetGb(emu, rex, nextop)

+#define GETEW(D)    oped=GetEw(emu, rex, nextop, D)

+#define GETGW       opgd=GetGw(emu, rex, nextop)

+#define GETEX(D)    opex=GetEx(emu, rex, nextop, D)

+#define GETGX       opgx=GetGx(emu, rex, nextop)

 #define ED  oped

 #define GD  opgd

 #define EB  oped

@@ -30,6 +30,8 @@
 #define EX  opex

 #define GX  opgx

 

+#define MODREG  ((nextop&0xC0)==0xC0)

+

 #define GOCOND(BASE, PREFIX, COND, NOTCOND)     \

     case BASE+0x0:                              \

         PREFIX                                  \

diff --git a/src/emu/x64run.c b/src/emu/x64run.c
index 34710a44..ece834c0 100755
--- a/src/emu/x64run.c
+++ b/src/emu/x64run.c
@@ -34,7 +34,7 @@ int Run(x64emu_t *emu, int step)
     uint8_t opcode;
     uint8_t nextop;
     reg64_t *oped, *opgd;
-    uint8_t tmp8u, tmp8u2;
+    uint8_t tmp8u;
     int8_t tmp8s;
     uint32_t tmp32u;
     uint64_t tmp64u;
@@ -80,18 +80,18 @@ x64emurun:
         #define GO(B, OP)                                   \
         case B+0:                                           \
             nextop = F8;                                    \
-            GETEB;                                          \
+            GETEB(0);                                       \
             GETGB;                                          \
             EB->byte[0] = OP##8(emu, EB->byte[0], GB);      \
             break;                                          \
         case B+1:                                           \
             nextop = F8;                                    \
-            GETED;                                          \
+            GETED(0);                                       \
             GETGD;                                          \
             if(rex.w)                                       \
                 ED->q[0] = OP##64(emu, ED->q[0], GD->q[0]); \
             else {                                          \
-                if((nextop&0xC0)==0xC0)                     \
+                if(MODREG)                                  \
                     ED->q[0] = OP##32(emu, ED->dword[0], GD->dword[0]);     \
                 else                                                        \
                     ED->dword[0] = OP##32(emu, ED->dword[0], GD->dword[0]); \
@@ -99,13 +99,13 @@ x64emurun:
             break;                                          \
         case B+2:                                           \
             nextop = F8;                                    \
-            GETEB;                                          \
+            GETEB(0);                                       \
             GETGB;                                          \
             GB = OP##8(emu, GB, EB->byte[0]);               \
             break;                                          \
         case B+3:                                           \
             nextop = F8;                                    \
-            GETED;                                          \
+            GETED(0);                                       \
             GETGD;                                          \
             if(rex.w)                                       \
                 GD->q[0] = OP##64(emu, GD->q[0], ED->q[0]); \
@@ -157,13 +157,13 @@ x64emurun:
 
         case 0x38:
             nextop = F8;
-            GETEB;
+            GETEB(0);
             GETGB;
             cmp8(emu, EB->byte[0], GB);
             break;
         case 0x39:
             nextop = F8;
-            GETED;
+            GETED(0);
             GETGD;
             if(rex.w)
                 cmp64(emu, ED->q[0], GD->q[0]);
@@ -172,13 +172,13 @@ x64emurun:
             break;
         case 0x3A:
             nextop = F8;
-            GETEB;
+            GETEB(0);
             GETGB;
             cmp8(emu, GB, EB->byte[0]);
             break;
         case 0x3B:
             nextop = F8;
-            GETED;
+            GETED(0);
             GETGD;
             if(rex.w)
                 cmp64(emu, GD->q[0], ED->q[0]);
@@ -227,12 +227,15 @@ x64emurun:
 
         case 0x63:                      /* MOVSXD Gd,Ed */
             nextop = F8;
-            GETED;
+            GETED(0);
             GETGD;
             if(rex.w)
                 GD->sq[0] = ED->sdword[0];
             else
-                GD->sdword[0] = ED->sdword[0];  // meh?
+                if(MODREG)
+                    GD->q[0] = ED->sdword[0];
+                else
+                    GD->sdword[0] = ED->sdword[0];  // meh?
             break;
 
         case 0x66:                      /* 16bits prefix */
@@ -249,13 +252,16 @@ x64emurun:
             break;
         case 0x69:                      /* IMUL Gd,Ed,Id */
             nextop = F8;
-            GETED;
+            GETED(4);
             GETGD;
             tmp64u = F32S64;
             if(rex.w)
                 GD->q[0] = imul64(emu, ED->q[0], tmp64u);
             else
-                GD->dword[0] = imul32(emu, ED->dword[0], tmp64u);
+                if((nextop&0xC0)==0xC0)
+                    GD->q[0] = imul32(emu, ED->dword[0], tmp64u);
+                else
+                    GD->dword[0] = imul32(emu, ED->dword[0], tmp64u);
             break;
 
         GOCOND(0x70
@@ -266,7 +272,7 @@ x64emurun:
         
         case 0x80:                      /* GRP Eb,Ib */
             nextop = F8;
-            GETEB;
+            GETEB(1);
             tmp8u = F8;
             switch((nextop>>3)&7) {
                 case 0: EB->byte[0] = add8(emu, EB->byte[0], tmp8u); break;
@@ -282,7 +288,7 @@ x64emurun:
         case 0x81:                      /* GRP Ed,Id */
         case 0x83:                      /* GRP Ed,Ib */
             nextop = F8;
-            GETED;
+            GETED((opcode==0x81)?4:1);
             if(opcode==0x81) {
                 tmp32s = F32S;
             } else {
@@ -302,28 +308,40 @@ x64emurun:
                 }
             } else {
                 tmp32u = (uint32_t)tmp32s;
-                switch((nextop>>3)&7) {
-                    case 0: ED->dword[0] = add32(emu, ED->dword[0], tmp32u); break;
-                    case 1: ED->dword[0] =  or32(emu, ED->dword[0], tmp32u); break;
-                    case 2: ED->dword[0] = adc32(emu, ED->dword[0], tmp32u); break;
-                    case 3: ED->dword[0] = sbb32(emu, ED->dword[0], tmp32u); break;
-                    case 4: ED->dword[0] = and32(emu, ED->dword[0], tmp32u); break;
-                    case 5: ED->dword[0] = sub32(emu, ED->dword[0], tmp32u); break;
-                    case 6: ED->dword[0] = xor32(emu, ED->dword[0], tmp32u); break;
-                    case 7:                cmp32(emu, ED->dword[0], tmp32u); break;
-                }
+                if(MODREG)
+                    switch((nextop>>3)&7) {
+                        case 0: ED->q[0] = add32(emu, ED->dword[0], tmp32u); break;
+                        case 1: ED->q[0] =  or32(emu, ED->dword[0], tmp32u); break;
+                        case 2: ED->q[0] = adc32(emu, ED->dword[0], tmp32u); break;
+                        case 3: ED->q[0] = sbb32(emu, ED->dword[0], tmp32u); break;
+                        case 4: ED->q[0] = and32(emu, ED->dword[0], tmp32u); break;
+                        case 5: ED->q[0] = sub32(emu, ED->dword[0], tmp32u); break;
+                        case 6: ED->q[0] = xor32(emu, ED->dword[0], tmp32u); break;
+                        case 7:            cmp32(emu, ED->dword[0], tmp32u); break;
+                    }
+                else
+                    switch((nextop>>3)&7) {
+                        case 0: ED->dword[0] = add32(emu, ED->dword[0], tmp32u); break;
+                        case 1: ED->dword[0] =  or32(emu, ED->dword[0], tmp32u); break;
+                        case 2: ED->dword[0] = adc32(emu, ED->dword[0], tmp32u); break;
+                        case 3: ED->dword[0] = sbb32(emu, ED->dword[0], tmp32u); break;
+                        case 4: ED->dword[0] = and32(emu, ED->dword[0], tmp32u); break;
+                        case 5: ED->dword[0] = sub32(emu, ED->dword[0], tmp32u); break;
+                        case 6: ED->dword[0] = xor32(emu, ED->dword[0], tmp32u); break;
+                        case 7:                cmp32(emu, ED->dword[0], tmp32u); break;
+                    }
             }
             break;
 
         case 0x84:                      /* TEST Eb,Gb */
             nextop = F8;
-            GETEB;
+            GETEB(0);
             GETGB;
             test8(emu, EB->byte[0], GB);
             break;
         case 0x85:                      /* TEST Ed,Gd */
             nextop = F8;
-            GETED;
+            GETED(0);
             GETGD;
             if(rex.w)
                 test64(emu, ED->q[0], GD->q[0]);
@@ -352,7 +370,7 @@ x64emurun:
                 }
             }
 #else
-            GETED;
+            GETED(0);
             GETGD;
             if((nextop&0xC0)!=0xC0)
                 pthread_mutex_lock(&emu->context->mutex_lock); // XCHG always LOCK (but when accessing memory only)
@@ -371,27 +389,28 @@ x64emurun:
             break;
         case 0x88:                      /* MOV Eb,Gb */
             nextop = F8;
-            GETEB;
+            GETEB(0);
             GETGB;
             EB->byte[0] = GB;
             break;
         case 0x89:                    /* MOV Ed,Gd */
             nextop = F8;
-            GETED;
+            GETED(0);
             GETGD;
-            if(rex.w)
+            if(rex.w) {
                 ED->q[0] = GD->q[0];
-            else
+            } else {
                 //if ED is a reg, than the opcode works like movzx
-                if((nextop&0xC0)==0xC0)
+                if(MODREG)
                     ED->q[0] = GD->dword[0];
                 else
                     ED->dword[0] = GD->dword[0];
+            }
             break;
 
         case 0x8B:                      /* MOV Gd,Ed */
             nextop = F8;
-            GETED;
+            GETED(0);
             GETGD;
             if(rex.w)
                 GD->q[0] = ED->q[0];
@@ -401,12 +420,12 @@ x64emurun:
 
         case 0x8D:                      /* LEA Gd,M */
             nextop = F8;
-            GETED;
+            GETED(0);
             GETGD;
             if(rex.w)
                 GD->q[0] = (uint64_t)ED;
             else
-                GD->dword[0] = (uint32_t)(uintptr_t)ED;
+                GD->dword[0] = (uint32_t)(uintptr_t)ED; // RAZ upper part?
             break;
 
         case 0x90:                      /* NOP */
@@ -434,20 +453,20 @@ x64emurun:
 
         case 0xAB:                      /* (REP) STOSD */
             if(rex.w)
-                tmp8s = ACCESS_FLAG(F_DF)?-4:+4;
-            else
                 tmp8s = ACCESS_FLAG(F_DF)?-8:+8;
+            else
+                tmp8s = ACCESS_FLAG(F_DF)?-4:+4;
             tmp64u = (rep)?R_RCX:1L;
             if((rex.w))
                 while(tmp64u) {
-                    *(uint32_t*)R_RDI = R_EAX;
-                    R_EDI += tmp8s;
+                    *(uint64_t*)R_RDI = R_RAX;
+                    R_RDI += tmp8s;
                     --tmp64u;
                 }
             else
                 while(tmp64u) {
-                    *(uint64_t*)R_RDI = R_RAX;
-                    R_EDI += tmp8s;
+                    *(uint32_t*)R_RDI = R_EAX;
+                    R_RDI += tmp8s;
                     --tmp64u;
                 }
             if(rep)
@@ -470,7 +489,7 @@ x64emurun:
 
         case 0xC1:                      /* GRP2 Ed,Ib */
             nextop = F8;
-            GETED;
+            GETED(1);
             tmp8u = F8/* & 0x1f*/; // masking done in each functions
             if(rex.w) {
                 switch((nextop>>3)&7) {
@@ -484,16 +503,28 @@ x64emurun:
                     case 7: ED->q[0] = sar64(emu, ED->q[0], tmp8u); break;
                 }
             } else {
-                switch((nextop>>3)&7) {
-                    case 0: ED->dword[0] = rol32(emu, ED->dword[0], tmp8u); break;
-                    case 1: ED->dword[0] = ror32(emu, ED->dword[0], tmp8u); break;
-                    case 2: ED->dword[0] = rcl32(emu, ED->dword[0], tmp8u); break;
-                    case 3: ED->dword[0] = rcr32(emu, ED->dword[0], tmp8u); break;
-                    case 4:
-                    case 6: ED->dword[0] = shl32(emu, ED->dword[0], tmp8u); break;
-                    case 5: ED->dword[0] = shr32(emu, ED->dword[0], tmp8u); break;
-                    case 7: ED->dword[0] = sar32(emu, ED->dword[0], tmp8u); break;
-                }
+                if(MODREG)
+                    switch((nextop>>3)&7) {
+                        case 0: ED->q[0] = rol32(emu, ED->dword[0], tmp8u); break;
+                        case 1: ED->q[0] = ror32(emu, ED->dword[0], tmp8u); break;
+                        case 2: ED->q[0] = rcl32(emu, ED->dword[0], tmp8u); break;
+                        case 3: ED->q[0] = rcr32(emu, ED->dword[0], tmp8u); break;
+                        case 4:
+                        case 6: ED->q[0] = shl32(emu, ED->dword[0], tmp8u); break;
+                        case 5: ED->q[0] = shr32(emu, ED->dword[0], tmp8u); break;
+                        case 7: ED->q[0] = sar32(emu, ED->dword[0], tmp8u); break;
+                    }
+                else
+                    switch((nextop>>3)&7) {
+                        case 0: ED->dword[0] = rol32(emu, ED->dword[0], tmp8u); break;
+                        case 1: ED->dword[0] = ror32(emu, ED->dword[0], tmp8u); break;
+                        case 2: ED->dword[0] = rcl32(emu, ED->dword[0], tmp8u); break;
+                        case 3: ED->dword[0] = rcr32(emu, ED->dword[0], tmp8u); break;
+                        case 4:
+                        case 6: ED->dword[0] = shl32(emu, ED->dword[0], tmp8u); break;
+                        case 5: ED->dword[0] = shr32(emu, ED->dword[0], tmp8u); break;
+                        case 7: ED->dword[0] = sar32(emu, ED->dword[0], tmp8u); break;
+                    }
             }
             break;
 
@@ -504,16 +535,19 @@ x64emurun:
 
         case 0xC6:                      /* MOV Eb,Ib */
             nextop = F8;
-            GETEB;
+            GETEB(1);
             EB->byte[0] = F8;
             break;
         case 0xC7:                      /* MOV Ed,Id */
             nextop = F8;
-            GETED;
+            GETED(4);
             if(rex.w)
                 ED->q[0] = F32S64;
             else
-                ED->dword[0] = F32;
+                if(MODREG)
+                    ED->q[0] = F32;
+                else
+                    ED->dword[0] = F32;
             break;
 
         case 0xC9:                      /* LEAVE */
@@ -529,7 +563,7 @@ x64emurun:
         case 0xD1:                      /* GRP2 Ed,1 */
         case 0xD3:                      /* GRP2 Ed,CL */
             nextop = F8;
-            GETED;
+            GETED(0);
             tmp8u = (opcode==0xD1)?1:R_CL;
             if(rex.w) {
                 switch((nextop>>3)&7) {
@@ -543,16 +577,28 @@ x64emurun:
                     case 7: ED->q[0] = sar64(emu, ED->q[0], tmp8u); break;
                 }
             } else {
-                switch((nextop>>3)&7) {
-                    case 0: ED->dword[0] = rol32(emu, ED->dword[0], tmp8u); break;
-                    case 1: ED->dword[0] = ror32(emu, ED->dword[0], tmp8u); break;
-                    case 2: ED->dword[0] = rcl32(emu, ED->dword[0], tmp8u); break;
-                    case 3: ED->dword[0] = rcr32(emu, ED->dword[0], tmp8u); break;
-                    case 4: 
-                    case 6: ED->dword[0] = shl32(emu, ED->dword[0], tmp8u); break;
-                    case 5: ED->dword[0] = shr32(emu, ED->dword[0], tmp8u); break;
-                    case 7: ED->dword[0] = sar32(emu, ED->dword[0], tmp8u); break;
-                }
+                if(MODREG)
+                    switch((nextop>>3)&7) {
+                        case 0: ED->q[0] = rol32(emu, ED->dword[0], tmp8u); break;
+                        case 1: ED->q[0] = ror32(emu, ED->dword[0], tmp8u); break;
+                        case 2: ED->q[0] = rcl32(emu, ED->dword[0], tmp8u); break;
+                        case 3: ED->q[0] = rcr32(emu, ED->dword[0], tmp8u); break;
+                        case 4: 
+                        case 6: ED->q[0] = shl32(emu, ED->dword[0], tmp8u); break;
+                        case 5: ED->q[0] = shr32(emu, ED->dword[0], tmp8u); break;
+                        case 7: ED->q[0] = sar32(emu, ED->dword[0], tmp8u); break;
+                    }
+                else
+                    switch((nextop>>3)&7) {
+                        case 0: ED->dword[0] = rol32(emu, ED->dword[0], tmp8u); break;
+                        case 1: ED->dword[0] = ror32(emu, ED->dword[0], tmp8u); break;
+                        case 2: ED->dword[0] = rcl32(emu, ED->dword[0], tmp8u); break;
+                        case 3: ED->dword[0] = rcr32(emu, ED->dword[0], tmp8u); break;
+                        case 4: 
+                        case 6: ED->dword[0] = shl32(emu, ED->dword[0], tmp8u); break;
+                        case 5: ED->dword[0] = shr32(emu, ED->dword[0], tmp8u); break;
+                        case 7: ED->dword[0] = sar32(emu, ED->dword[0], tmp8u); break;
+                    }
             }
             break;
 
@@ -603,8 +649,9 @@ x64emurun:
 
         case 0xF6:                      /* GRP3 Eb(,Ib) */
             nextop = F8;
-            GETEB;
-            switch((nextop>>3)&7) {
+            tmp8u = (nextop>>3)&7;
+            GETEB((tmp8u<2)?1:0);
+            switch(tmp8u) {
                 case 0: 
                 case 1:                 /* TEST Eb,Ib */
                     tmp8u = F8;
@@ -632,9 +679,10 @@ x64emurun:
             break;
         case 0xF7:                      /* GRP3 Ed(,Id) */
             nextop = F8;
-            GETED;
+            tmp8u = (nextop>>3)&7;
+            GETED((tmp8u<2)?4:0);
             if(rex.w) {
-                switch((nextop>>3)&7) {
+                switch(tmp8u) {
                     case 0: 
                     case 1:                 /* TEST Ed,Id */
                         tmp64u = F32S64;
@@ -660,7 +708,7 @@ x64emurun:
                         break;
                 }
             } else {
-                switch((nextop>>3)&7) {
+                switch(tmp8u) {
                     case 0: 
                     case 1:                 /* TEST Ed,Id */
                         tmp32u = F32;
@@ -690,7 +738,7 @@ x64emurun:
 
         case 0xFF:                      /* GRP 5 Ed */
             nextop = F8;
-            GETED;
+            GETED(0);
             switch((nextop>>3)&7) {
                 case 0:                 /* INC Ed */
                     if(rex.w)
diff --git a/src/emu/x64run0f.c b/src/emu/x64run0f.c
index fc71e941..2d62fc37 100644
--- a/src/emu/x64run0f.c
+++ b/src/emu/x64run0f.c
@@ -46,19 +46,19 @@ int Run0F(x64emu_t *emu, rex_t rex)
 

         case 0x11:                      /* MOVUPS Ex,Gx */

             nextop = F8;

-            GETEX;

+            GETEX(0);

             GETGX;

             memcpy(EX, GX, 16); // unaligned, so carreful

             break;

 

         case 0x1F:                      /* NOP (multi-byte) */

             nextop = F8;

-            GETED;

+            GETED(0);

             break;

 

         case 0x29:                      /* MOVAPS Ex,Gx */

             nextop = F8;

-            GETEX;

+            GETEX(0);

             GETGX;

             EX->q[0] = GX->q[0];

             EX->q[1] = GX->q[1];

@@ -67,7 +67,7 @@ int Run0F(x64emu_t *emu, rex_t rex)
 

         GOCOND(0x40

             , nextop = F8;

-            GETED;

+            GETED(0);

             GETGD;

             CHECK_FLAGS(emu);

             , if(rex.w) {GD->q[0] = ED->q[0]; } else {GD->dword[0] = ED->dword[0];}

@@ -81,7 +81,7 @@ int Run0F(x64emu_t *emu, rex_t rex)
         )                               /* 0x80 -> 0x8F Jxx */

         GOCOND(0x90

             , nextop = F8; CHECK_FLAGS(emu);

-            GETEB;

+            GETEB(0);

             , EB->byte[0]=1;

             , EB->byte[0]=0;

         )                               /* 0x90 -> 0x9F SETxx Eb */

@@ -102,7 +102,7 @@ int Run0F(x64emu_t *emu, rex_t rex)
             if((nextop&0xF8)==0xF8) {

                 return 0;                   /* SFENCE */

             }

-            GETED;

+            GETED(0);

             switch((nextop>>3)&7) {

                 default:

                     return 1;

@@ -110,7 +110,7 @@ int Run0F(x64emu_t *emu, rex_t rex)
             break;

         case 0xAF:                      /* IMUL Gd,Ed */

             nextop = F8;

-            GETED;

+            GETED(0);

             GETGD;

             if(rex.w)

                 GD->q[0] = imul64(emu, GD->q[0], ED->q[0]);

@@ -120,20 +120,20 @@ int Run0F(x64emu_t *emu, rex_t rex)
 

         case 0xB6:                      /* MOVZX Gd,Eb */

             nextop = F8;

-            GETEB;

+            GETEB(0);

             GETGD;

             GD->q[0] = EB->byte[0];

             break;

         case 0xB7:                      /* MOVZX Gd,Ew */

             nextop = F8;

-            GETEW;

+            GETEW(0);

             GETGD;

             GD->q[0] = EW->word[0];

             break;

 

         case 0xBE:                      /* MOVSX Gd,Eb */

             nextop = F8;

-            GETEB;

+            GETEB(0);

             GETGD;

             if(rex.w)

                 GD->sq[0] = EB->sbyte[0];

@@ -144,7 +144,7 @@ int Run0F(x64emu_t *emu, rex_t rex)
             break;

         case 0xBF:                      /* MOVSX Gd,Ew */

             nextop = F8;

-            GETEW;

+            GETEW(0);

             GETGD;

             if(rex.w)

                 GD->sq[0] = EW->sword[0];

diff --git a/src/emu/x64run66.c b/src/emu/x64run66.c
index 77dd7b06..9f70aee6 100644
--- a/src/emu/x64run66.c
+++ b/src/emu/x64run66.c
@@ -51,7 +51,7 @@ int Run66(x64emu_t *emu, rex_t rex)
     case 0x81:                              /* GRP3 Ew,Iw */

     case 0x83:                              /* GRP3 Ew,Ib */

         nextop = F8;

-        GETEW;

+        GETEW((opcode==0x81)?2:1);

         GETGW;

         if(opcode==0x81) 

             tmp16u = F16;

@@ -73,7 +73,7 @@ int Run66(x64emu_t *emu, rex_t rex)
 

     case 0x89:                              /* MOV Ew,Gw */

         nextop = F8;

-        GETEW;

+        GETEW(0);

         GETGW;

         EW->word[0] = GW->word[0];

         break;

@@ -83,7 +83,7 @@ int Run66(x64emu_t *emu, rex_t rex)
 

     case 0xC1:                              /* GRP2 Ew,Ib */

         nextop = F8;

-        GETEW;

+        GETEW(1);

         tmp8u = F8 /*& 0x1f*/;

         switch((nextop>>3)&7) {

             case 0: EW->word[0] = rol16(emu, EW->word[0], tmp8u); break;

@@ -99,7 +99,7 @@ int Run66(x64emu_t *emu, rex_t rex)
 

     case 0xC7:                              /* MOV Ew,Iw */

         nextop = F8;

-        GETEW;

+        GETEW(2);

         EW->word[0] = F16;

         break;

 

diff --git a/src/emu/x64run660f.c b/src/emu/x64run660f.c
index 53942521..862fcdd9 100644
--- a/src/emu/x64run660f.c
+++ b/src/emu/x64run660f.c
@@ -40,12 +40,12 @@ int Run660F(x64emu_t *emu, rex_t rex)
 

     case 0x1F:                      /* NOP (multi-byte) */

         nextop = F8;

-        GETED;

+        GETED(0);

         break;

 

     case 0x6F:                      /* MOVDQA Gx,Ex */

         nextop = F8;

-        GETEX;

+        GETEX(0);

         GETGX;

         GX->q[0] = EX->q[0];

         GX->q[1] = EX->q[1];

@@ -53,7 +53,7 @@ int Run660F(x64emu_t *emu, rex_t rex)
 

     case 0xEF:                      /* PXOR Gx,Ex */

         nextop = F8;

-        GETEX;

+        GETEX(0);

         GETGX;

         GX->q[0] ^= EX->q[0];

         GX->q[1] ^= EX->q[1];

diff --git a/src/emu/x64run_private.c b/src/emu/x64run_private.c
index 34fed61f..928d531f 100755
--- a/src/emu/x64run_private.c
+++ b/src/emu/x64run_private.c
@@ -994,7 +994,7 @@ void PrintTrace(x64emu_t* emu, uintptr_t ip, int dynarec)
 
 #endif
 
-reg64_t* GetECommon(x64emu_t* emu, rex_t rex, uint8_t m)
+reg64_t* GetECommon(x64emu_t* emu, rex_t rex, uint8_t m, uint8_t delta)
 {
     if (m<=7) {
         if(m==0x4) {
@@ -1004,7 +1004,7 @@ reg64_t* GetECommon(x64emu_t* emu, rex_t rex, uint8_t m)
             return (reg64_t*)base;
         } else if (m==0x5) { //disp32
             int32_t base = Fetch32s(emu);
-            return (reg64_t*)(base+R_RIP);
+            return (reg64_t*)(base+R_RIP+delta);
         }
         return (reg64_t*)(emu->regs[m+(rex.b<<3)].q[0]);
     } else {
@@ -1021,7 +1021,7 @@ reg64_t* GetECommon(x64emu_t* emu, rex_t rex, uint8_t m)
     }
 }
 
-reg64_t* GetEb(x64emu_t *emu, rex_t rex, uint8_t v)
+reg64_t* GetEb(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta)
 {
     // rex ignored here
     uint8_t m = v&0xC7;    // filter Eb
@@ -1032,15 +1032,15 @@ reg64_t* GetEb(x64emu_t *emu, rex_t rex, uint8_t v)
             int lowhigh = (m&4)>>2;
             return (reg64_t *)(((char*)(&emu->regs[(m&0x03)]))+lowhigh);  //?
         }
-    } else return GetECommon(emu, rex, m);
+    } else return GetECommon(emu, rex, m, delta);
 }
 
-reg64_t* GetEd(x64emu_t *emu, rex_t rex, uint8_t v)
+reg64_t* GetEd(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta)
 {
     uint8_t m = v&0xC7;    // filter Ed
     if(m>=0xC0) {
          return &emu->regs[(m&0x07)+(rex.b<<3)];
-    } else return GetECommon(emu, rex, m);
+    } else return GetECommon(emu, rex, m, delta);
 }
 
 #define GetEw GetEd
@@ -1099,20 +1099,20 @@ reg64_t* GetEw16off(x64emu_t *emu, rex_t rex, uint8_t v, uintptr_t offset)
     }
 }
 
-mmx_regs_t* GetEm(x64emu_t *emu, rex_t rex, uint8_t v)
+mmx_regs_t* GetEm(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta)
 {
     uint8_t m = v&0xC7;    // filter Ed
     if(m>=0xC0) {
          return &emu->mmx[m&0x07];
-    } else return (mmx_regs_t*)GetECommon(emu, rex, m);
+    } else return (mmx_regs_t*)GetECommon(emu, rex, m, delta);
 }
 
-sse_regs_t* GetEx(x64emu_t *emu, rex_t rex, uint8_t v)
+sse_regs_t* GetEx(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta)
 {
     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);
+    } else return (sse_regs_t*)GetECommon(emu, rex, m, delta);
 }
 
 
diff --git a/src/emu/x64run_private.h b/src/emu/x64run_private.h
index e52e0c62..c2161b3f 100755
--- a/src/emu/x64run_private.h
+++ b/src/emu/x64run_private.h
@@ -73,14 +73,14 @@ static inline void Push(x64emu_t *emu, uint64_t v)
 
 // the op code definition can be found here: http://ref.x86asm.net/geek32.html
 
-reg64_t* GetECommon(x64emu_t* emu, rex_t rex, uint8_t m);
-reg64_t* GetEb(x64emu_t *emu, rex_t rex, uint8_t v);
-reg64_t* GetEd(x64emu_t *emu, rex_t rex, uint8_t v);
+reg64_t* GetECommon(x64emu_t* emu, rex_t rex, uint8_t m, uint8_t delta);
+reg64_t* GetEb(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta);
+reg64_t* GetEd(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta);
 #define GetEw GetEd
 reg64_t* GetEw16(x64emu_t *emu, rex_t rex, uint8_t v);
 reg64_t* GetEw16off(x64emu_t *emu, rex_t rex, uint8_t v, uintptr_t offset);
-mmx_regs_t* GetEm(x64emu_t *emu, rex_t rex, uint8_t v);
-sse_regs_t* GetEx(x64emu_t *emu, rex_t rex, uint8_t v);
+mmx_regs_t* GetEm(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta);
+sse_regs_t* GetEx(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta);
 reg64_t* GetGd(x64emu_t *emu, rex_t rex, uint8_t v);
 #define GetGw GetGd
 reg64_t* GetGb(x64emu_t *emu, rex_t rex, uint8_t v);
diff --git a/src/emu/x64rund9.c b/src/emu/x64rund9.c
index 52c4c46f..00314c97 100644
--- a/src/emu/x64rund9.c
+++ b/src/emu/x64rund9.c
@@ -228,7 +228,7 @@ int RunD9(x64emu_t *emu, rex_t rex)
         default:

         switch((nextop>>3)&7) {

             case 0:     /* FLD ST0, Ed float */

-                GETED;

+                GETED(0);

                 fpu_do_push(emu);

                 if(!(((uintptr_t)ED)&3))

                     ST0.d = *(float*)ED;

@@ -238,7 +238,7 @@ int RunD9(x64emu_t *emu, rex_t rex)
                 }

                 break;

             case 2:     /* FST Ed, ST0 */

-                GETED;

+                GETED(0);

                 if(!(((uintptr_t)ED)&3))

                     *(float*)ED = ST0.d;

                 else {

@@ -247,7 +247,7 @@ int RunD9(x64emu_t *emu, rex_t rex)
                 }

                 break;

             case 3:     /* FSTP Ed, ST0 */

-                GETED;

+                GETED(0);

                 if(!(((uintptr_t)ED)&3))

                     *(float*)ED = ST0.d;

                 else {

@@ -258,11 +258,11 @@ int RunD9(x64emu_t *emu, rex_t rex)
                 break;

             case 4:     /* FLDENV m */

                 // warning, incomplete

-                GETED;

+                GETED(0);

                 fpu_loadenv(emu, (char*)ED, 0);

                 break;

             case 5:     /* FLDCW Ew */

-                GETEW;

+                GETEW(0);

                 emu->cw = EW->word[0];

                 // do something with cw?

                 emu->round = (fpu_round_t)((emu->cw >> 10) & 3);

@@ -278,7 +278,7 @@ int RunD9(x64emu_t *emu, rex_t rex)
                 break;

             #endif

             case 7: /* FNSTCW Ew */

-                GETEW;

+                GETEW(0);

                 EW->word[0] = emu->cw;

                 break;

             default:

diff --git a/src/emu/x64rundb.c b/src/emu/x64rundb.c
index 30a16d44..ae29f362 100644
--- a/src/emu/x64rundb.c
+++ b/src/emu/x64rundb.c
@@ -132,12 +132,12 @@ int RunDB(x64emu_t *emu, rex_t rex)
     default:

         switch((nextop>>3)&7) {

             case 0: /* FILD ST0, Ed */

-                GETED;

+                GETED(0);

                 fpu_do_push(emu);

                 ST0.d = ED->sdword[0];

                 break;

             case 1: /* FISTTP Ed, ST0 */

-                GETED;

+                GETED(0);

                 tmp32s = ST0.d; // TODO: Handling of FPU Exception

                 if(tmp32s==0x7fffffff && isgreater(ST0.d, (double)(int32_t)0x7fffffff))

                     tmp32s = 0x80000000;

@@ -145,7 +145,7 @@ int RunDB(x64emu_t *emu, rex_t rex)
                 ED->sdword[0] = tmp32s;

                 break;

             case 2: /* FIST Ed, ST0 */

-                GETED;

+                GETED(0);

                 if(isgreater(ST0.d, (double)(int32_t)0x7fffffff) || isless(ST0.d, -(double)(int32_t)0x7fffffff) || !isfinite(ST0.d))

                     ED->sdword[0] = 0x80000000;

                 else {

@@ -154,7 +154,7 @@ int RunDB(x64emu_t *emu, rex_t rex)
                 }

                 break;

             case 3: /* FISTP Ed, ST0 */

-                GETED;

+                GETED(0);

                 if(isgreater(ST0.d, (double)(int32_t)0x7fffffff) || isless(ST0.d, -(double)(int32_t)0x7fffffff) || !isfinite(ST0.d))

                     ED->sdword[0] = 0x80000000;

                 else {

@@ -164,14 +164,14 @@ int RunDB(x64emu_t *emu, rex_t rex)
                 fpu_do_pop(emu);

                 break;

             case 5: /* FLD ST0, Et */

-                GETED;

+                GETED(0);

                 fpu_do_push(emu);

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

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

                 STld(0).ref = ST0.ll;

                 break;

             case 7: /* FSTP tbyte */

-                GETED;

+                GETED(0);

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

                     D2LD(&ST0.d, ED);

                 else

diff --git a/src/emu/x64runf0.c b/src/emu/x64runf0.c
index 9b7cf878..ee75e4f7 100644
--- a/src/emu/x64runf0.c
+++ b/src/emu/x64runf0.c
@@ -52,7 +52,7 @@ int RunF0(x64emu_t *emu, rex_t rex)
 

                 case 0xB1:                      /* CMPXCHG Ed,Gd */

                     nextop = F8;

-                    GETED;

+                    GETED(0);

                     GETGD;

 #ifdef DYNAREC

                     if(((uintptr_t)ED)&3) {

@@ -104,7 +104,7 @@ int RunF0(x64emu_t *emu, rex_t rex)
 

                 case 0xC1:                      /* XADD Gd,Ed */

                     nextop = F8;

-                    GETED;

+                    GETED(0);

                     GETGD;

 #ifdef DYNAREC

                     if(((uintptr_t)ED)&3) {

@@ -147,7 +147,7 @@ int RunF0(x64emu_t *emu, rex_t rex)
         case 0x81:              /* GRP Ed,Id */

         case 0x83:              /* GRP Ed,Ib */

             nextop = F8;

-            GETED;

+            GETED((opcode==0x81)?4:1);

             if(opcode==0x83) {

                 tmp64s = F8S;

                 tmp64u = (uint64_t)tmp64s;

diff --git a/src/emu/x64runf20f.c b/src/emu/x64runf20f.c
index 80728935..3e6b29b3 100644
--- a/src/emu/x64runf20f.c
+++ b/src/emu/x64runf20f.c
@@ -40,7 +40,7 @@ int RunF20F(x64emu_t *emu, rex_t rex)
 

     case 0x10:  /* MOVSD Gx, Ex */

         nextop = F8;

-        GETEX;

+        GETEX(0);

         GETGX;

         GX->q[0] = EX->q[0];

         if((nextop&0xC0)!=0xC0) {

@@ -50,7 +50,7 @@ int RunF20F(x64emu_t *emu, rex_t rex)
         break;

     case 0x11:  /* MOVSD Ex, Gx */

         nextop = F8;

-        GETEX;

+        GETEX(0);

         GETGX;

         EX->q[0] = GX->q[0];

         break;

diff --git a/src/emu/x64runf30f.c b/src/emu/x64runf30f.c
index efbce036..e4a3f643 100644
--- a/src/emu/x64runf30f.c
+++ b/src/emu/x64runf30f.c
@@ -41,7 +41,7 @@ int RunF30F(x64emu_t *emu, rex_t rex)
 

     case 0x10:  /* MOVSS Gx Ex */

         nextop = F8;

-        GETEX;

+        GETEX(0);

         GETGX;

         GX->ud[0] = EX->ud[0];

         if((nextop&0xC0)!=0xC0) {

@@ -51,34 +51,34 @@ int RunF30F(x64emu_t *emu, rex_t rex)
         break;

     case 0x11:  /* MOVSS Ex Gx */

         nextop = F8;

-        GETEX;

+        GETEX(0);

         GETGX;

         EX->ud[0] = GX->ud[0];

         break;

 

     case 0x2A:  /* CVTSI2SS Gx, Ed */

         nextop = F8;

-        GETED;

+        GETED(0);

         GETGX;

         GX->f[0] = ED->sdword[0];

         break;

 

     case 0x59:  /* MULSS Gx, Ex */

         nextop = F8;

-        GETEX;

+        GETEX(0);

         GETGX;

         GX->f[0] *= EX->f[0];

         break;

     case 0x5A:  /* CVTSS2SD Gx, Ex */

         nextop = F8;

-        GETEX;

+        GETEX(0);

         GETGX;

         GX->d[0] = EX->f[0];

         break;

 

     case 0x6F:  /* MOVDQU Gx, Ex */

         nextop = F8;

-        GETEX;

+        GETEX(0);

         GETGX;

         memcpy(GX, EX, 16);    // unaligned...

         break;