diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2021-03-06 16:54:29 +0100 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2021-03-06 16:54:29 +0100 |
| commit | 1b350d24c30657c8ea8afd4f3aeeda960a0a2357 (patch) | |
| tree | 2686c17ba1cca91369f05527c1176a07c1ec53db /src | |
| parent | 4705ecce1a36ffe29ec894d84cba1299501705ae (diff) | |
| download | box64-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.h | 18 | ||||
| -rwxr-xr-x | src/emu/x64run.c | 196 | ||||
| -rw-r--r-- | src/emu/x64run0f.c | 22 | ||||
| -rw-r--r-- | src/emu/x64run66.c | 8 | ||||
| -rw-r--r-- | src/emu/x64run660f.c | 6 | ||||
| -rwxr-xr-x | src/emu/x64run_private.c | 20 | ||||
| -rwxr-xr-x | src/emu/x64run_private.h | 10 | ||||
| -rw-r--r-- | src/emu/x64rund9.c | 12 | ||||
| -rw-r--r-- | src/emu/x64rundb.c | 12 | ||||
| -rw-r--r-- | src/emu/x64runf0.c | 6 | ||||
| -rw-r--r-- | src/emu/x64runf20f.c | 4 | ||||
| -rw-r--r-- | src/emu/x64runf30f.c | 12 |
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; |