diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2021-03-10 20:44:00 +0100 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2021-03-10 20:44:00 +0100 |
| commit | 5a244911cc9e6066962b75fbbf7ba310d79af524 (patch) | |
| tree | 539c5034d28f3e146e11a4b5adc9df2fb7a9ad63 /src | |
| parent | 02161dc4d761cf209095b614534db908a140384a (diff) | |
| download | box64-5a244911cc9e6066962b75fbbf7ba310d79af524.tar.gz box64-5a244911cc9e6066962b75fbbf7ba310d79af524.zip | |
Added and fixed many opcodes
Diffstat (limited to 'src')
| -rwxr-xr-x | src/emu/x64primop.c | 32 | ||||
| -rwxr-xr-x | src/emu/x64primop.h | 2 | ||||
| -rwxr-xr-x | src/emu/x64run.c | 38 | ||||
| -rw-r--r-- | src/emu/x64run0f.c | 187 | ||||
| -rw-r--r-- | src/emu/x64run66.c | 54 | ||||
| -rw-r--r-- | src/emu/x64run660f.c | 167 | ||||
| -rwxr-xr-x | src/emu/x64run_private.c | 54 |
7 files changed, 471 insertions, 63 deletions
diff --git a/src/emu/x64primop.c b/src/emu/x64primop.c index 9b6fffb8..cc9422e7 100755 --- a/src/emu/x64primop.c +++ b/src/emu/x64primop.c @@ -310,7 +310,7 @@ uint64_t adc64(x64emu_t *emu, uint64_t d, uint64_t s) CONDITIONAL_SET_FLAG(hi & 0x100000000L, F_CF); CONDITIONAL_SET_FLAG(!res, F_ZF); - CONDITIONAL_SET_FLAG(res & 0x8000000000000000L, F_SF); + CONDITIONAL_SET_FLAG(res & 0x8000000000000000LL, F_SF); CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); /* calculate the carry chain SEE NOTE AT TOP. */ @@ -393,13 +393,13 @@ uint64_t cmp64(x64emu_t *emu, uint64_t d, uint64_t s) RESET_FLAGS(emu); res = d - s; - CONDITIONAL_SET_FLAG(res & 0x8000000000000000L, F_SF); + CONDITIONAL_SET_FLAG(res & 0x8000000000000000LL, F_SF); CONDITIONAL_SET_FLAG(!res, F_ZF); CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); /* calculate the borrow chain. See note at top */ bc = (res & (~d | s)) | (~d & s); - CONDITIONAL_SET_FLAG(bc & 0x8000000000000000L, F_CF); + CONDITIONAL_SET_FLAG(bc & 0x8000000000000000LL, F_CF); CONDITIONAL_SET_FLAG(XOR2(bc >> 62), F_OF); CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); return d; @@ -573,7 +573,7 @@ uint32_t rcl32(x64emu_t *emu, uint32_t d, uint8_t s) return res; } -uint32_t rcl64(x64emu_t *emu, uint64_t d, uint8_t s) +uint64_t rcl64(x64emu_t *emu, uint64_t d, uint8_t s) { uint64_t res, cnt, mask, cf; CHECK_FLAGS(emu); @@ -583,10 +583,10 @@ uint32_t rcl64(x64emu_t *emu, uint64_t d, uint8_t s) if ((cnt = s % 65) != 0) { cf = (d >> (64 - cnt)) & 0x1; res = (d << cnt); - mask = (1 << (cnt - 1)) - 1; + mask = (1LL << (cnt - 1)) - 1; res |= (d >> (65 - cnt)) & mask; if (ACCESS_FLAG(F_CF)) { /* carry flag is set */ - res |= 1 << (cnt - 1); + res |= 1LL << (cnt - 1); } CONDITIONAL_SET_FLAG(cf, F_CF); CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 62) & 0x2)), @@ -756,12 +756,12 @@ uint64_t rcr64(x64emu_t *emu, uint64_t d, uint8_t s) ocf = ACCESS_FLAG(F_CF) != 0; } else cf = (d >> (cnt - 1)) & 0x1; - mask = (1 << (64 - cnt)) - 1; + mask = (1LL << (64 - cnt)) - 1; res = (d >> cnt) & mask; if (cnt != 1) res |= (d << (65 - cnt)); if (ACCESS_FLAG(F_CF)) { /* carry flag is set */ - res |= 1 << (64 - cnt); + res |= 1LL << (64 - cnt); } CONDITIONAL_SET_FLAG(cf, F_CF); if (cnt == 1) { @@ -1033,17 +1033,17 @@ uint32_t shld32 (x64emu_t *emu, uint32_t d, uint32_t fill, uint8_t s) uint64_t shld64 (x64emu_t *emu, uint64_t d, uint64_t fill, uint8_t s) { - unsigned int cnt, res, cf; + uint64_t cnt, res, cf; RESET_FLAGS(emu); s = s&0x3f; cnt = s % 64; if (cnt > 0) { res = (d << cnt) | (fill >> (64-cnt)); - cf = d & (1 << (64 - cnt)); + cf = d & (1LL << (64 - cnt)); CONDITIONAL_SET_FLAG(cf, F_CF); CONDITIONAL_SET_FLAG(!res, F_ZF); - CONDITIONAL_SET_FLAG(res & 0x8000000000000000L, F_SF); + CONDITIONAL_SET_FLAG(res & 0x8000000000000000LL, F_SF); CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); } else { res = d; @@ -1139,11 +1139,11 @@ uint64_t shrd64 (x64emu_t *emu, uint64_t d, uint64_t fill, uint8_t s) s = s&0x3f; cnt = s % 64; if (cnt > 0) { - cf = d & (1 << (cnt - 1)); + cf = d & (1LL << (cnt - 1)); res = (d >> cnt) | (fill << (64 - cnt)); CONDITIONAL_SET_FLAG(cf, F_CF); CONDITIONAL_SET_FLAG(!res, F_ZF); - CONDITIONAL_SET_FLAG(res & 0x8000000000000000L, F_SF); + CONDITIONAL_SET_FLAG(res & 0x8000000000000000LL, F_SF); CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); } else { res = d; @@ -1235,13 +1235,13 @@ uint64_t sbb64(x64emu_t *emu, uint64_t d, uint64_t s) res = d - s - 1; else res = d - s; - CONDITIONAL_SET_FLAG(res & 0x8000000000000000L, F_SF); + CONDITIONAL_SET_FLAG(res & 0x8000000000000000LL, F_SF); CONDITIONAL_SET_FLAG(!res, F_ZF); CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); /* calculate the borrow chain. See note at top */ bc = (res & (~d | s)) | (~d & s); - CONDITIONAL_SET_FLAG(bc & 0x8000000000000000L, F_CF); + CONDITIONAL_SET_FLAG(bc & 0x8000000000000000LL, F_CF); CONDITIONAL_SET_FLAG(XOR2(bc >> 62), F_OF); CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); return res; @@ -1304,7 +1304,7 @@ void test64(x64emu_t *emu, uint64_t d, uint64_t s) res = d & s; CLEAR_FLAG(F_OF); - CONDITIONAL_SET_FLAG(res & 0x8000000000000000L, F_SF); + CONDITIONAL_SET_FLAG(res & 0x8000000000000000LL, F_SF); CONDITIONAL_SET_FLAG(res == 0, F_ZF); CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); /* AF == dont care */ diff --git a/src/emu/x64primop.h b/src/emu/x64primop.h index df32d2c4..f27c8cc0 100755 --- a/src/emu/x64primop.h +++ b/src/emu/x64primop.h @@ -34,7 +34,7 @@ static inline uint16_t add16(x64emu_t *emu, uint16_t d, uint16_t s) static inline uint32_t add32(x64emu_t *emu, uint32_t d, uint32_t s) { - emu->res = d + s; + emu->res = (uint64_t)d + s; emu->op1 = d; emu->op2 = s; emu->df = d_add32; diff --git a/src/emu/x64run.c b/src/emu/x64run.c index dbf257c6..32778044 100755 --- a/src/emu/x64run.c +++ b/src/emu/x64run.c @@ -466,6 +466,15 @@ x64emurun: R_RDX=(R_EAX & 0x80000000)?0xFFFFFFFFFFFFFFFFL:0x0000000000000000L; break; + case 0x9C: /* PUSHF */ + CHECK_FLAGS(emu); + Push(emu, emu->eflags.x64); + break; + case 0x9D: /* POPF */ + emu->eflags.x64 = ((Pop(emu) & 0x3F7FD7)/* & (0xffff-40)*/ ) | 0x2; // mask off res2 and res3 and on res1 + RESET_FLAGS(emu); + break; + case 0xA5: /* (REP) MOVSD */ tmp8s = ACCESS_FLAG(F_DF)?-1:+1; tmp64u = (rep)?R_RCX:1L; @@ -913,27 +922,48 @@ x64emurun: test32(emu, ED->dword[0], tmp32u); break; case 2: /* NOT Ed */ - ED->dword[0] = not32(emu, ED->dword[0]); + ED->q[0] = not32(emu, ED->dword[0]); break; case 3: /* NEG Ed */ - ED->dword[0] = neg32(emu, ED->dword[0]); + ED->q[0] = neg32(emu, ED->dword[0]); break; case 4: /* MUL EAX,Ed */ mul32_eax(emu, ED->dword[0]); + emu->regs[_AX].dword[1] = 0; break; case 5: /* IMUL EAX,Ed */ imul32_eax(emu, ED->dword[0]); + emu->regs[_AX].dword[1] = 0; break; case 6: /* DIV Ed */ div32(emu, ED->dword[0]); + emu->regs[_AX].dword[1] = 0; + emu->regs[_DX].dword[1] = 0; break; case 7: /* IDIV Ed */ idiv32(emu, ED->dword[0]); + emu->regs[_AX].dword[1] = 0; + emu->regs[_DX].dword[1] = 0; break; } } break; + case 0xFE: /* GRP 5 Eb */ + nextop = F8; + GETEB(0); + switch((nextop>>3)&7) { + case 0: /* INC Eb */ + ED->byte[0] = inc8(emu, ED->byte[0]); + break; + case 1: /* DEC Ed */ + ED->byte[0] = dec8(emu, ED->byte[0]); + break; + default: + unimp = 1; + goto fini; + } + break; case 0xFF: /* GRP 5 Ed */ nextop = F8; GETED(0); @@ -942,13 +972,13 @@ x64emurun: if(rex.w) ED->q[0] = inc64(emu, ED->q[0]); else - ED->dword[0] = inc32(emu, ED->dword[0]); + ED->q[0] = inc32(emu, ED->dword[0]); break; case 1: /* DEC Ed */ if(rex.w) ED->q[0] = dec64(emu, ED->q[0]); else - ED->dword[0] = dec32(emu, ED->dword[0]); + ED->q[0] = dec32(emu, ED->dword[0]); break; case 2: /* CALL NEAR Ed */ tmp64u = (uintptr_t)getAlternate((void*)ED->q[0]); diff --git a/src/emu/x64run0f.c b/src/emu/x64run0f.c index ec055fb2..a58ed582 100644 --- a/src/emu/x64run0f.c +++ b/src/emu/x64run0f.c @@ -143,8 +143,8 @@ int Run0F(x64emu_t *emu, rex_t rex) GETED(0); GETGD; CHECK_FLAGS(emu); - , if(rex.w) {GD->q[0] = ED->q[0]; } else {GD->dword[0] = ED->dword[0];} - , + , if(rex.w) {GD->q[0] = ED->q[0]; } else {GD->q[0] = ED->dword[0];} + , if(!rex.w) GD->dword[1] = 0; ) /* 0x40 -> 0x4F CMOVxx Gd,Ed */ // conditional move, no sign case 0x51: /* SQRTPS Gx, Ex */ @@ -452,7 +452,86 @@ int Run0F(x64emu_t *emu, rex_t rex) tmp32u = R_EAX; my_cpuid(emu, tmp32u); break; + case 0xA3: /* BT Ed,Gd */ + CHECK_FLAGS(emu); + nextop = F8; + GETED(0); + GETGD; + tmp8u = GD->byte[0]; + if(!MODREG) + { + ED=(reg64_t*)(((uint32_t*)(ED))+(tmp8u>>5)); + } + if(rex.w) { + tmp8u&=63; + if(ED->q[0] & (1LL<<tmp8u)) + SET_FLAG(F_CF); + else + CLEAR_FLAG(F_CF); + } else { + tmp8u&=31; + if(ED->dword[0] & (1<<tmp8u)) + SET_FLAG(F_CF); + else + CLEAR_FLAG(F_CF); + } + break; + case 0xA4: /* SHLD Ed,Gd,Ib */ + case 0xA5: /* SHLD Ed,Gd,CL */ + nextop = F8; + GETED((nextop==0xA4)?1:0); + GETGD; + if(opcode==0xA4) + tmp8u = F8; + else + tmp8u = R_CL; + if(rex.w) + ED->q[0] = shld64(emu, ED->q[0], GD->q[0], tmp8u); + else + ED->q[0] = shld32(emu, ED->dword[0], GD->dword[0], tmp8u); + break; + case 0xAB: /* BTS Ed,Gd */ + CHECK_FLAGS(emu); + nextop = F8; + GETED(0); + GETGD; + tmp8u = GD->byte[0]; + if(!MODREG) + { + ED=(reg64_t*)(((uint32_t*)(ED))+(tmp8u>>5)); + } + if(rex.w) { + tmp8u&=63; + if(ED->q[0] & (1LL<<tmp8u)) + SET_FLAG(F_CF); + else { + ED->q[0] |= (1LL<<tmp8u); + CLEAR_FLAG(F_CF); + } + } else { + tmp8u&=31; + if(ED->dword[0] & (1<<tmp8u)) + SET_FLAG(F_CF); + else { + ED->dword[0] |= (1<<tmp8u); + CLEAR_FLAG(F_CF); + } + if(MODREG) + ED->dword[1] = 0; + } + break; + case 0xAC: /* SHRD Ed,Gd,Ib */ + case 0xAD: /* SHRD Ed,Gd,CL */ + nextop = F8; + GETED((nextop==0xAC)?1:0); + GETGD; + tmp8u = (opcode==0xAC)?(F8):R_CL; + if(rex.w) + ED->q[0] = shrd64(emu, ED->q[0], GD->q[0], tmp8u); + else + ED->q[0] = shrd32(emu, ED->dword[0], GD->dword[0], tmp8u); + break; case 0xAE: /* Grp Ed (SSE) */ nextop = F8; if((nextop&0xF8)==0xE8) { @@ -486,6 +565,35 @@ int Run0F(x64emu_t *emu, rex_t rex) GD->dword[0] = imul32(emu, GD->dword[0], ED->dword[0]); break; + case 0xB3: /* BTR Ed,Gd */ + CHECK_FLAGS(emu); + nextop = F8; + GETED(0); + GETGD; + tmp8u = GD->byte[0]; + if(!MODREG) + { + ED=(reg64_t*)(((uint32_t*)(ED))+(tmp8u>>5)); + } + if(rex.w) { + tmp8u&=63; + if(ED->q[0] & (1LL<<tmp8u)) { + SET_FLAG(F_CF); + ED->q[0] ^= (1LL<<tmp8u); + } else + CLEAR_FLAG(F_CF); + } else { + tmp8u&=31; + if(ED->dword[0] & (1<<tmp8u)) { + SET_FLAG(F_CF); + ED->dword[0] ^= (1<<tmp8u); + } else + CLEAR_FLAG(F_CF); + if(MODREG) + ED->dword[1] = 0; + } + break; + case 0xB6: /* MOVZX Gd,Eb */ nextop = F8; GETEB(0); @@ -510,7 +618,7 @@ int Run0F(x64emu_t *emu, rex_t rex) ED=(reg64_t*)(((uintptr_t*)(ED))+(tmp8u>>5)); if(rex.w) { tmp8u&=63; - if(ED->q[0] & (1L<<tmp8u)) + if(ED->q[0] & (1LL<<tmp8u)) SET_FLAG(F_CF); else CLEAR_FLAG(F_CF); @@ -530,10 +638,10 @@ int Run0F(x64emu_t *emu, rex_t rex) ED=(reg64_t*)(((uintptr_t*)(ED))+(tmp8u>>5)); if(rex.w) { tmp8u&=63; - if(ED->q[0] & (1L<<tmp8u)) { + if(ED->q[0] & (1LL<<tmp8u)) { SET_FLAG(F_CF); } else { - ED->q[0] ^= (1L<<tmp8u); + ED->q[0] ^= (1LL<<tmp8u); CLEAR_FLAG(F_CF); } } else { @@ -554,9 +662,9 @@ int Run0F(x64emu_t *emu, rex_t rex) ED=(reg64_t*)(((uintptr_t*)(ED))+(tmp8u>>5)); if(rex.w) { tmp8u&=63; - if(ED->q[0] & (1L<<tmp8u)) { + if(ED->q[0] & (1LL<<tmp8u)) { SET_FLAG(F_CF); - ED->q[0] ^= (1L<<tmp8u); + ED->q[0] ^= (1LL<<tmp8u); } else CLEAR_FLAG(F_CF); } else { @@ -576,11 +684,11 @@ int Run0F(x64emu_t *emu, rex_t rex) ED=(reg64_t*)(((uintptr_t*)(ED))+(tmp8u>>5)); if(rex.w) { tmp8u&=63; - if(ED->q[0] & (1L<<tmp8u)) + if(ED->q[0] & (1LL<<tmp8u)) SET_FLAG(F_CF); else CLEAR_FLAG(F_CF); - ED->q[0] ^= (1L<<tmp8u); + ED->q[0] ^= (1LL<<tmp8u); } else { tmp8u&=31; if(ED->dword[0] & (1<<tmp8u)) @@ -595,7 +703,64 @@ int Run0F(x64emu_t *emu, rex_t rex) return 1; } break; - + case 0xBB: /* BTC Ed,Gd */ + CHECK_FLAGS(emu); + nextop = F8; + GETED(0); + GETGD; + tmp8u = GD->byte[0]; + if(!MODREG) + { + if(rex.w) + ED=(reg64_t*)(((uint64_t*)(ED))+(tmp8u>>6)); + else + ED=(reg64_t*)(((uint32_t*)(ED))+(tmp8u>>5)); + } + if(rex.w) { + tmp8u&=63; + if(ED->q[0] & (1LL<<tmp8u)) + SET_FLAG(F_CF); + else + CLEAR_FLAG(F_CF); + ED->q[0] ^= (1LL<<tmp8u); + } else { + tmp8u&=31; + if(ED->dword[0] & (1<<tmp8u)) + SET_FLAG(F_CF); + else + CLEAR_FLAG(F_CF); + ED->dword[0] ^= (1<<tmp8u); + if(MODREG) + ED->dword[1] = 0; + } + break; + case 0xBC: /* BSF Ed,Gd */ + CHECK_FLAGS(emu); + nextop = F8; + GETED(0); + GETGD; + if(rex.w) { + tmp64u = ED->q[0]; + if(tmp64u) { + CLEAR_FLAG(F_ZF); + tmp8u = 0; + while(!(tmp64u&(1LL<<tmp8u))) ++tmp8u; + GD->q[0] = tmp8u; + } else { + SET_FLAG(F_ZF); + } + } else { + tmp32u = ED->dword[0]; + if(tmp32u) { + CLEAR_FLAG(F_ZF); + tmp8u = 0; + while(!(tmp32u&(1<<tmp8u))) ++tmp8u; + GD->q[0] = tmp8u; + } else { + SET_FLAG(F_ZF); + } + } + break; case 0xBD: /* BSR Ed,Gd */ CHECK_FLAGS(emu); nextop = F8; @@ -606,7 +771,7 @@ int Run0F(x64emu_t *emu, rex_t rex) if(tmp64u) { CLEAR_FLAG(F_ZF); tmp8u = 63; - while(!(tmp64u&(1L<<tmp8u))) --tmp8u; + while(!(tmp64u&(1LL<<tmp8u))) --tmp8u; GD->q[0] = tmp8u; } else { SET_FLAG(F_ZF); diff --git a/src/emu/x64run66.c b/src/emu/x64run66.c index 822d91df..c2e8a5a0 100644 --- a/src/emu/x64run66.c +++ b/src/emu/x64run66.c @@ -33,6 +33,7 @@ int Run66(x64emu_t *emu, rex_t rex) uint8_t tmp8u; int16_t tmp16s; uint16_t tmp16u; + int64_t tmp64s; uint64_t tmp64u; reg64_t *oped, *opgd; @@ -129,6 +130,32 @@ int Run66(x64emu_t *emu, rex_t rex) case 0x64: /* FS: */ return Run6664(emu, rex); + case 0x69: /* IMUL Gw,Ew,Iw */ + nextop = F8; + GETEW(rex.w?4:2); + GETGW; + if(rex.w) { + tmp64u = F32S64; + GW->q[0] = imul64(emu, EW->q[0], tmp64u); + } else { + tmp16u = F16; + GW->word[0] = imul16(emu, EW->word[0], tmp16u); + } + break; + + case 0x6B: /* IMUL Gw,Ew,Ib */ + nextop = F8; + GETEW(1); + GETGW; + if(rex.w) { + tmp64s = F8S; + GW->q[0] = imul64(emu, EW->q[0], (uint64_t)tmp64s); + } else { + tmp16s = F8S; + GW->word[0] = imul16(emu, EW->word[0], (uint16_t)tmp16s); + } + break; + case 0x81: /* GRP3 Ew,Iw */ case 0x83: /* GRP3 Ew,Ib */ nextop = F8; @@ -300,8 +327,31 @@ int Run66(x64emu_t *emu, rex_t rex) } break; - default: - return 1; + case 0xFF: /* GRP 5 Ew */ + nextop = F8; + GETEW(0); + GETGW; + switch((nextop>>3)&7) { + case 0: /* INC Ed */ + EW->word[0] = inc16(emu, EW->word[0]); + break; + case 1: /* DEC Ed */ + EW->word[0] = dec16(emu, EW->word[0]); + break; + /*case 6: + Push16(emu, EW->word[0]); + break;*/ + default: + R_RIP = emu->old_ip; + printf_log(LOG_NONE, "Illegal Opcode %p: 66 %02X %02X %02X %02X %02X %02X\n",(void*)R_RIP, opcode, nextop, PK(2), PK(3), PK(4), PK(5)); + emu->quit=1; + emu->error |= ERR_ILLEGAL; + return 0; + } + break; + + default: + return 1; } return 0; } \ No newline at end of file diff --git a/src/emu/x64run660f.c b/src/emu/x64run660f.c index 660ac028..434fd81e 100644 --- a/src/emu/x64run660f.c +++ b/src/emu/x64run660f.c @@ -30,7 +30,9 @@ int Run660F(x64emu_t *emu, rex_t rex) { uint8_t opcode; uint8_t nextop; - int32_t tmp32s; + uint8_t tmp8u; + uint16_t tmp16u; + uint64_t tmp64u; reg64_t *oped, *opgd; sse_regs_t *opex, *opgx; mmx87_regs_t *opem; @@ -386,6 +388,169 @@ int Run660F(x64emu_t *emu, rex_t rex) EX->q[1] = GX->q[1]; break; + case 0xA3: /* BT Ew,Gw */ + CHECK_FLAGS(emu); + nextop = F8; + GETEW(0); + GETGW; + if(rex.w) { + if(EW->q[0] & (1LL<<(GW->q[0]&63))) + SET_FLAG(F_CF); + else + CLEAR_FLAG(F_CF); + } else { + if(EW->word[0] & (1<<(GW->word[0]&15))) + SET_FLAG(F_CF); + else + CLEAR_FLAG(F_CF); + } + break; + case 0xA4: /* SHLD Ew,Gw,Ib */ + case 0xA5: /* SHLD Ew,Gw,CL */ + nextop = F8; + GETEW((nextop==0xA4)?1:0); + GETGW; + if(opcode==0xA4) + tmp8u = F8; + else + tmp8u = R_CL; + if(rex.w) + EW->q[0] = shld64(emu, EW->q[0], GW->q[0], tmp8u); + else + EW->word[0] = shld16(emu, EW->word[0], GW->word[0], tmp8u); + break; + + case 0xAB: /* BTS Ew,Gw */ + CHECK_FLAGS(emu); + nextop = F8; + GETEW(0); + GETGW; + if(rex.w) { + if(EW->q[0] & (1LL<<(GW->q[0]&63))) + SET_FLAG(F_CF); + else { + EW->q[0] |= (1LL<<(GW->q[0]&63)); + CLEAR_FLAG(F_CF); + } + } else { + if(EW->word[0] & (1<<(GW->word[0]&15))) + SET_FLAG(F_CF); + else { + EW->word[0] |= (1<<(GW->word[0]&15)); + CLEAR_FLAG(F_CF); + } + } + break; + case 0xAC: /* SHRD Ew,Gw,Ib */ + case 0xAD: /* SHRD Ew,Gw,CL */ + nextop = F8; + GETEW((nextop==0xAC)?1:0); + GETGW; + if(opcode==0xAC) + tmp8u = F8; + else + tmp8u = R_CL; + if(rex.w) + EW->q[0] = shrd64(emu, EW->q[0], GW->q[0], tmp8u); + else + EW->word[0] = shrd16(emu, EW->word[0], GW->word[0], tmp8u); + break; + + case 0xAF: /* IMUL Gw,Ew */ + nextop = F8; + GETEW(0); + GETGW; + if(rex.w) + GW->q[0] = imul64(emu, GW->q[0], EW->q[0]); + else + GW->word[0] = imul16(emu, GW->word[0], EW->word[0]); + break; + + case 0xB3: /* BTR Ew,Gw */ + CHECK_FLAGS(emu); + nextop = F8; + GETEW(0); + GETGW; + if(rex.w) { + if(EW->q[0] & (1LL<<(GW->q[0]&63))) { + SET_FLAG(F_CF); + EW->q[0] ^= (1LL<<(GW->q[0]&63)); + } else + CLEAR_FLAG(F_CF); + } else { + if(EW->word[0] & (1<<(GW->word[0]&15))) { + SET_FLAG(F_CF); + EW->word[0] ^= (1<<(GW->word[0]&15)); + } else + CLEAR_FLAG(F_CF); + } + break; + + case 0xBB: /* BTC Ew,Gw */ + CHECK_FLAGS(emu); + nextop = F8; + GETEW(0); + GETGW; + if(EW->word[0] & (1<<(GW->word[0]&15))) + SET_FLAG(F_CF); + else + CLEAR_FLAG(F_CF); + EW->word[0] ^= (1<<(GW->word[0]&15)); + break; + case 0xBC: /* BSF Ew,Gw */ + CHECK_FLAGS(emu); + nextop = F8; + GETEW(0); + GETGW; + if(rex.w) { + tmp64u = EW->q[0]; + if(tmp64u) { + CLEAR_FLAG(F_ZF); + tmp8u = 0; + while(!(tmp64u&(1LL<<tmp8u))) ++tmp8u; + GW->q[0] = tmp8u; + } else { + SET_FLAG(F_ZF); + } + } else { + tmp16u = EW->word[0]; + if(tmp16u) { + CLEAR_FLAG(F_ZF); + tmp8u = 0; + while(!(tmp16u&(1<<tmp8u))) ++tmp8u; + GW->word[0] = tmp8u; + } else { + SET_FLAG(F_ZF); + } + } + break; + case 0xBD: /* BSR Ew,Gw */ + CHECK_FLAGS(emu); + nextop = F8; + GETEW(0); + GETGW; + if(rex.w) { + tmp64u = EW->q[0]; + if(tmp64u) { + CLEAR_FLAG(F_ZF); + tmp8u = 63; + while(!(tmp64u&(1LL<<tmp8u))) --tmp8u; + GW->q[0] = tmp8u; + } else { + SET_FLAG(F_ZF); + } + } else { + tmp16u = EW->word[0]; + if(tmp16u) { + CLEAR_FLAG(F_ZF); + tmp8u = 15; + while(!(tmp16u&(1<<tmp8u))) --tmp8u; + GW->word[0] = tmp8u; + } else { + SET_FLAG(F_ZF); + } + } + break; case 0xBE: /* MOVSX Gw,Eb */ nextop = F8; GETEB(0); diff --git a/src/emu/x64run_private.c b/src/emu/x64run_private.c index 9e012d1f..b3f21421 100755 --- a/src/emu/x64run_private.c +++ b/src/emu/x64run_private.c @@ -115,7 +115,7 @@ void UpdateFlags(x64emu_t *emu) CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); break; case d_add32: - CONDITIONAL_SET_FLAG(emu->res & 0x100000000, F_CF); + CONDITIONAL_SET_FLAG(emu->res & 0x100000000LL, F_CF); CONDITIONAL_SET_FLAG((emu->res & 0xffffffff) == 0, F_ZF); CONDITIONAL_SET_FLAG(emu->res & 0x80000000, F_SF); CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF); @@ -128,7 +128,7 @@ void UpdateFlags(x64emu_t *emu) hi = (lo >> 32) + (emu->op2 >> 32) + (emu->op1 >> 32); CONDITIONAL_SET_FLAG(hi & 0x100000000, F_CF); CONDITIONAL_SET_FLAG(!emu->res, F_ZF); - CONDITIONAL_SET_FLAG(emu->res & 0x8000000000000000L, F_SF); + CONDITIONAL_SET_FLAG(emu->res & 0x8000000000000000LL, 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 >> 62), F_OF); @@ -162,7 +162,7 @@ void UpdateFlags(x64emu_t *emu) CLEAR_FLAG(F_OF); CLEAR_FLAG(F_CF); CLEAR_FLAG(F_AF); - CONDITIONAL_SET_FLAG(emu->res & 0x8000000000000000L, F_SF); + CONDITIONAL_SET_FLAG(emu->res & 0x8000000000000000LL, F_SF); CONDITIONAL_SET_FLAG(emu->res == 0, F_ZF); CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF); break; @@ -191,7 +191,7 @@ void UpdateFlags(x64emu_t *emu) CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); break; case d_dec64: - CONDITIONAL_SET_FLAG(emu->res & 0x8000000000000000L, F_SF); + CONDITIONAL_SET_FLAG(emu->res & 0x8000000000000000LL, 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); @@ -224,7 +224,7 @@ void UpdateFlags(x64emu_t *emu) break; case d_inc64: CONDITIONAL_SET_FLAG(!emu->res, F_ZF); - CONDITIONAL_SET_FLAG(emu->res & 0x8000000000000000L, F_SF); + CONDITIONAL_SET_FLAG(emu->res & 0x8000000000000000LL, 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 >> 62), F_OF); @@ -268,8 +268,8 @@ void UpdateFlags(x64emu_t *emu) CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF); break; case d_imul64: - if (((emu->res & 0x8000000000000000L) == 0 && emu->op1 == 0x00) || - ((emu->res & 0x8000000000000000L) != 0 && emu->op1 == 0xFFFFFFFFFFFFFFFFL)) { + if (((emu->res & 0x8000000000000000LL) == 0 && emu->op1 == 0x00) || + ((emu->res & 0x8000000000000000LL) != 0 && emu->op1 == 0xFFFFFFFFFFFFFFFFLL)) { CLEAR_FLAG(F_CF); CLEAR_FLAG(F_OF); } else { @@ -303,9 +303,7 @@ void UpdateFlags(x64emu_t *emu) CONDITIONAL_SET_FLAG(PARITY(lo & 0xff), F_PF); break; case d_mul32: - lo = (uint32_t)emu->res; - hi = (uint32_t)(emu->res >> 32); - if (hi == 0) { + if (emu->op1 == 0) { CLEAR_FLAG(F_CF); CLEAR_FLAG(F_OF); } else { @@ -352,7 +350,7 @@ void UpdateFlags(x64emu_t *emu) CLEAR_FLAG(F_OF); CLEAR_FLAG(F_CF); CLEAR_FLAG(F_AF); - CONDITIONAL_SET_FLAG(emu->res & 0x8000000000000000L, F_SF); + CONDITIONAL_SET_FLAG(emu->res & 0x8000000000000000LL, F_SF); CONDITIONAL_SET_FLAG(emu->res == 0, F_ZF); CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF); break; @@ -386,7 +384,7 @@ void UpdateFlags(x64emu_t *emu) case d_neg64: CONDITIONAL_SET_FLAG(emu->op1 != 0, F_CF); CONDITIONAL_SET_FLAG(!emu->res, F_ZF); - CONDITIONAL_SET_FLAG(emu->res & 0x8000000000000000L, F_SF); + CONDITIONAL_SET_FLAG(emu->res & 0x8000000000000000LL, F_SF); CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF); bc = emu->res | emu->op1; CONDITIONAL_SET_FLAG(XOR2(bc >> 62), F_OF); @@ -464,14 +462,14 @@ void UpdateFlags(x64emu_t *emu) break; case d_shl64: if (emu->op2 > 0) { - cc = emu->op1 & (1 << (64 - emu->op2)); + cc = emu->op1 & (1LL << (64 - emu->op2)); CONDITIONAL_SET_FLAG(cc, F_CF); CONDITIONAL_SET_FLAG(!emu->res, F_ZF); - CONDITIONAL_SET_FLAG(emu->res & 0x8000000000000000L, F_SF); + CONDITIONAL_SET_FLAG(emu->res & 0x8000000000000000LL, F_SF); CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF); } if (emu->op2 == 1) { - CONDITIONAL_SET_FLAG(((!!(emu->res & 0x8000000000000000L)) ^ + CONDITIONAL_SET_FLAG(((!!(emu->res & 0x8000000000000000LL)) ^ (ACCESS_FLAG(F_CF) != 0)), F_OF); } else { CLEAR_FLAG(F_OF); @@ -548,10 +546,10 @@ void UpdateFlags(x64emu_t *emu) break; case d_sar64: if(emu->op2) { - cc = emu->op1 & (1 << (emu->op2 - 1)); + cc = emu->op1 & (1LL << (emu->op2 - 1)); CONDITIONAL_SET_FLAG(cc, F_CF); CONDITIONAL_SET_FLAG(emu->res == 0, F_ZF); - CONDITIONAL_SET_FLAG(emu->res & 0x8000000000000000L, F_SF); + CONDITIONAL_SET_FLAG(emu->res & 0x8000000000000000LL, F_SF); CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF); } break; @@ -618,10 +616,10 @@ void UpdateFlags(x64emu_t *emu) case d_shr64: cnt = emu->op2; if (cnt > 0) { - cc = emu->op1 & (1 << (cnt - 1)); + cc = emu->op1 & (1LL << (cnt - 1)); CONDITIONAL_SET_FLAG(cc, F_CF); CONDITIONAL_SET_FLAG(!emu->res, F_ZF); - CONDITIONAL_SET_FLAG(emu->res & 0x8000000000000000L, F_SF); + CONDITIONAL_SET_FLAG(emu->res & 0x8000000000000000LL, F_SF); CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF); } if (cnt == 1) { @@ -656,11 +654,11 @@ void UpdateFlags(x64emu_t *emu) CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); break; case d_sub64: - CONDITIONAL_SET_FLAG(emu->res & 0x8000000000000000L, F_SF); + CONDITIONAL_SET_FLAG(emu->res & 0x8000000000000000LL, 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 & 0x8000000000000000L, F_CF); + CONDITIONAL_SET_FLAG(bc & 0x8000000000000000LL, F_CF); CONDITIONAL_SET_FLAG(XOR2(bc >> 62), F_OF); CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); break; @@ -690,7 +688,7 @@ void UpdateFlags(x64emu_t *emu) break; case d_xor64: CLEAR_FLAG(F_OF); - CONDITIONAL_SET_FLAG(emu->res & 0x8000000000000000L, F_SF); + CONDITIONAL_SET_FLAG(emu->res & 0x8000000000000000LL, F_SF); CONDITIONAL_SET_FLAG(emu->res == 0, F_ZF); CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF); CLEAR_FLAG(F_CF); @@ -725,11 +723,11 @@ void UpdateFlags(x64emu_t *emu) CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); break; case d_cmp64: - CONDITIONAL_SET_FLAG(emu->res & 0x8000000000000000L, F_SF); + CONDITIONAL_SET_FLAG(emu->res & 0x8000000000000000LL, 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 & 0x8000000000000000L, F_CF); + CONDITIONAL_SET_FLAG(bc & 0x8000000000000000LL, F_CF); CONDITIONAL_SET_FLAG(XOR2(bc >> 62), F_OF); CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); break; @@ -756,7 +754,7 @@ void UpdateFlags(x64emu_t *emu) break; case d_tst64: CLEAR_FLAG(F_OF); - CONDITIONAL_SET_FLAG(emu->res & 0x8000000000000000L, F_SF); + CONDITIONAL_SET_FLAG(emu->res & 0x8000000000000000LL, F_SF); CONDITIONAL_SET_FLAG(emu->res == 0, F_ZF); CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF); CLEAR_FLAG(F_CF); @@ -797,7 +795,7 @@ void UpdateFlags(x64emu_t *emu) hi = (lo >> 32) + (emu->op1 >> 32) + (emu->op2 >> 32); CONDITIONAL_SET_FLAG(hi & 0x1000000000000L, F_CF); CONDITIONAL_SET_FLAG(!emu->res, F_ZF); - CONDITIONAL_SET_FLAG(emu->res & 0x8000000000000000L, F_SF); + CONDITIONAL_SET_FLAG(emu->res & 0x8000000000000000LL, 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 >> 62), F_OF); @@ -831,11 +829,11 @@ void UpdateFlags(x64emu_t *emu) CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); break; case d_sbb64: - CONDITIONAL_SET_FLAG(emu->res & 0x8000000000000000L, F_SF); + CONDITIONAL_SET_FLAG(emu->res & 0x8000000000000000LL, 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 & 0x8000000000000000L, F_CF); + CONDITIONAL_SET_FLAG(bc & 0x8000000000000000LL, F_CF); CONDITIONAL_SET_FLAG(XOR2(bc >> 62), F_OF); CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); break; |