diff options
Diffstat (limited to 'src/emu/x64run64.c')
| -rw-r--r-- | src/emu/x64run64.c | 1094 |
1 files changed, 0 insertions, 1094 deletions
diff --git a/src/emu/x64run64.c b/src/emu/x64run64.c deleted file mode 100644 index 40cf5eb9..00000000 --- a/src/emu/x64run64.c +++ /dev/null @@ -1,1094 +0,0 @@ -#define _GNU_SOURCE -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <math.h> -#include <string.h> -#include <signal.h> -#include <sys/types.h> -#include <unistd.h> - -#include "debug.h" -#include "box64stack.h" -#include "box64cpu_util.h" -#include "x64emu.h" -#include "x64emu_private.h" -#include "x64run_private.h" -#include "x64primop.h" -#include "x64trace.h" -#include "x87emu_private.h" -#include "box64context.h" -#include "alternate.h" -#include "emit_signals.h" - -#include "modrm.h" - -#ifdef TEST_INTERPRETER -uintptr_t Test64(x64test_t *test, rex_t rex, int seg, uintptr_t addr) -#else -uintptr_t Run64(x64emu_t *emu, rex_t rex, int seg, uintptr_t addr) -#endif -{ - uint8_t opcode; - uint8_t nextop; - uint8_t tmp8u; (void)tmp8u; - int16_t tmp16s; (void)tmp16s; - uint16_t tmp16u; (void)tmp16u; - int32_t tmp32s; - uint32_t tmp32u; - uint64_t tmp64u; - reg64_t *oped, *opgd; - sse_regs_t *opex, *opgx; - int rep; - #ifdef TEST_INTERPRETER - x64emu_t* emu = test->emu; - #endif - int is_nan; - uintptr_t tlsdata = GetSegmentBaseEmu(emu, seg); - - opcode = F8; - // REX prefix before the F0 are ignored - rex.rex = 0; - if(!rex.is32bits) - while(opcode>=0x40 && opcode<=0x4f) { - rex.rex = opcode; - opcode = F8; - } - rep = 0; - while((opcode==0xF2) || (opcode==0xF3)) { - rep = opcode-0xF1; - opcode = F8; - } - if(!rex.is32bits) - while(opcode>=0x40 && opcode<=0x4f) { - rex.rex = opcode; - opcode = F8; - } - - switch(opcode) { - #define GO(B, OP) \ - case B+0: \ - nextop = F8; \ - GETEB_OFFS(0, tlsdata); \ - GETGB; \ - EB->byte[0] = OP##8(emu, EB->byte[0], GB); \ - break; \ - case B+1: \ - nextop = F8; \ - GETED_OFFS(0, tlsdata); \ - GETGD; \ - if(rex.w) \ - ED->q[0] = OP##64(emu, ED->q[0], GD->q[0]); \ - else { \ - 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]); \ - } \ - break; \ - case B+2: \ - nextop = F8; \ - GETEB_OFFS(0, tlsdata); \ - GETGB; \ - GB = OP##8(emu, GB, EB->byte[0]); \ - break; \ - case B+3: \ - nextop = F8; \ - GETED_OFFS(0, tlsdata); \ - GETGD; \ - if(rex.w) \ - GD->q[0] = OP##64(emu, GD->q[0], ED->q[0]); \ - else \ - GD->q[0] = OP##32(emu, GD->dword[0], ED->dword[0]); \ - break; \ - case B+4: \ - R_AL = OP##8(emu, R_AL, F8); \ - break; \ - case B+5: \ - if(rex.w) \ - R_RAX = OP##64(emu, R_RAX, F32S64); \ - else \ - R_RAX = OP##32(emu, R_EAX, F32); \ - break; - - GO(0x00, add) /* ADD 0x00 -> 0x05 */ - GO(0x08, or) /* OR 0x08 -> 0x0D */ - GO(0x10, adc) /* ADC 0x10 -> 0x15 */ - GO(0x18, sbb) /* SBB 0x18 -> 0x1D */ - GO(0x20, and) /* AND 0x20 -> 0x25 */ - GO(0x28, sub) /* SUB 0x28 -> 0x2D */ - GO(0x30, xor) /* XOR 0x30 -> 0x35 */ - #undef GO - case 0x0F: - opcode = F8; - switch(opcode) { - - case 0x10: - switch(rep) { - case 0: /* MOVUPS Gx, FS:Ex */ - nextop = F8; - GETEX_OFFS(0, tlsdata); - GETGX; - GX->u128 = EX->u128; - break; - case 1: /* MOVSD Gx, FS:Ex */ - nextop = F8; - GETEX_OFFS(0, tlsdata); - GETGX; - GX->q[0] = EX->q[0]; - if(!MODREG) { - // EX is not a register - GX->q[1] = 0; - } - break; - case 2: /* MOVSS Gx, FS:Ex */ - nextop = F8; - GETEX_OFFS(0, tlsdata); - GETGX; - GX->ud[0] = EX->ud[0]; - if(!MODREG) { - // EX is not a register (reg to reg only move 31:0) - GX->ud[1] = GX->ud[2] = GX->ud[3] = 0; - } - break; - default: - return 0; - } - break; - case 0x11: - switch(rep) { - case 0: /* MOVUPS FS:Ex, Gx */ - nextop = F8; - GETEX_OFFS(0, tlsdata); - GETGX; - EX->u128 = GX->u128; - break; - case 1: /* MOVSD Ex, Gx */ - nextop = F8; - GETEX_OFFS(0, tlsdata); - GETGX; - EX->q[0] = GX->q[0]; - break; - case 2: /* MOVSS FS:Ex, Gx */ - nextop = F8; - GETEX_OFFS(0, tlsdata); - GETGX; - EX->ud[0] = GX->ud[0]; - break; - default: - return 0; - } - break; - - case 0x18: - case 0x19: - case 0x1F: /* NOP (multi-byte) */ - nextop = F8; - FAKEED(0); - break; - case 0x28: - switch(rep) { - case 0: /* MOVAPS Gx, FS:Ex */ - nextop = F8; - GETEX_OFFS(0, tlsdata); - GETGX; - GX->u128 = EX->u128; - break; - default: - return 0; - } - break; - case 0x29: /* MOVAPS FS:Ex,Gx */ - switch(rep) { - case 0: - nextop = F8; - GETEX_OFFS(0, tlsdata); - GETGX; - EX->q[0] = GX->q[0]; - EX->q[1] = GX->q[1]; - break; - default: - return 0; - } - break; - - case 0x58: - switch(rep) { - case 2: /* ADDSS Gx, FS:Ex */ - nextop = F8; - GETEX_OFFS(0, tlsdata); - GETGX; - is_nan = isnanf(GX->f[0]) || isnanf(EX->f[0]); - NAN_PROPAGATION(GX->f[0], EX->f[0], break); - GX->f[0] += EX->f[0]; - if(!is_nan && isnanf(GX->f[0])) GX->f[0] = -NAN; - break; - - default: - return 0; - } - break; - case 0x59: - switch(rep) { - case 2: /* MULSS Gx, FS:Ex */ - nextop = F8; - GETEX_OFFS(0, tlsdata); - GETGX; - NAN_PROPAGATION(GX->f[0], EX->f[0], break); - GX->f[0] *= EX->f[0]; - break; - - default: - return 0; - } - break; - case 0x5A: - switch(rep) { - case 2: /* CVTSS2SD Gx, FS:Ex */ - nextop = F8; - GETEX_OFFS(0, tlsdata); - GETGX; - GX->d[0] = EX->f[0]; - break; - - default: - return 0; - } - break; - - case 0x6F: - switch(rep) { - case 2: /* MOVDQU Gx, FS:Ex */ - nextop = F8; - GETEX_OFFS(0, tlsdata); - GETGX; - memcpy(GX, EX, 16); // unaligned... - break; - - default: - return 0; - } - break; - - case 0x7F: - switch(rep) { - case 2: /* MOVDQU FS:Ex, Gx */ - nextop = F8; - GETEX_OFFS(0, tlsdata); - GETGX; - memcpy(EX, GX, 16); // unaligned... - break; - default: - return 0; - } - break; - - case 0xAF: - switch(rep) { - case 0: /* IMUL Gd, FS:Ed */ - nextop = F8; - GETED_OFFS(0, tlsdata); - GETGD; - if(rex.w) - GD->q[0] = imul64(emu, GD->q[0], ED->q[0]); - else - GD->q[0] = imul32(emu, GD->dword[0], ED->dword[0]); - break; - default: - return 0; - } - break; - - case 0xB6: - switch(rep) { - case 0: /* MOVZX Gd, FS:Eb */ - nextop = F8; - GETEB_OFFS(0, tlsdata); - GETGD; - GD->q[0] = EB->byte[0]; - break; - default: - return 0; - } - break; - case 0xB7: - switch(rep) { - case 0: /* MOVZX Gd, FS:Ew */ - nextop = F8; - GETEW_OFFS(0, tlsdata); - GETGD; - GD->q[0] = EW->word[0]; - break; - default: - return 0; - } - break; - - case 0xBA: - nextop = F8; - switch((nextop>>3)&7) { - case 4: /* BT Ed,Ib */ - CHECK_FLAGS(emu); - GETED_OFFS(1, tlsdata); - tmp8u = F8; - 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); - } - if (BOX64ENV(dynarec_test)) { - CLEAR_FLAG(F_OF); - CLEAR_FLAG(F_SF); - CLEAR_FLAG(F_AF); - CLEAR_FLAG(F_PF); - } - break; - case 5: /* BTS Ed, Ib */ - CHECK_FLAGS(emu); - GETED_OFFS(1, tlsdata); - tmp8u = F8; - 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; - } - if (BOX64ENV(dynarec_test)) { - CLEAR_FLAG(F_OF); - CLEAR_FLAG(F_SF); - CLEAR_FLAG(F_AF); - CLEAR_FLAG(F_PF); - } - break; - case 6: /* BTR Ed, Ib */ - CHECK_FLAGS(emu); - GETED_OFFS(1, tlsdata); - tmp8u = F8; - 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; - } - if (BOX64ENV(dynarec_test)) { - CLEAR_FLAG(F_OF); - CLEAR_FLAG(F_SF); - CLEAR_FLAG(F_AF); - CLEAR_FLAG(F_PF); - } - break; - case 7: /* BTC Ed, Ib */ - CHECK_FLAGS(emu); - GETED_OFFS(1, tlsdata); - tmp8u = F8; - 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; - } - if (BOX64ENV(dynarec_test)) { - CLEAR_FLAG(F_OF); - CLEAR_FLAG(F_SF); - CLEAR_FLAG(F_AF); - CLEAR_FLAG(F_PF); - } - break; - - default: - return 0; - } - break; - - case 0xBF: - switch(rep) { - case 0: /* MOVSX Gd,FS:Ew */ - nextop = F8; - GETEW_OFFS(0, tlsdata); - GETGD; - if(rex.w) - GD->sq[0] = EW->sword[0]; - else { - GD->sdword[0] = EW->sword[0]; - GD->dword[1] = 0; - } - break; - default: - return 0; - } - break; - - default: - return 0; - } - break; - - case 0x38: - nextop = F8; - GETEB_OFFS(0, tlsdata); - GETGB; - cmp8(emu, EB->byte[0], GB); - break; - case 0x39: - nextop = F8; - GETED_OFFS(0, tlsdata); - GETGD; - if(rex.w) - cmp64(emu, ED->q[0], GD->q[0]); - else - cmp32(emu, ED->dword[0], GD->dword[0]); - break; - - case 0x3B: - nextop = F8; - GETED_OFFS(0, tlsdata); - GETGD; - if(rex.w) - cmp64(emu, GD->q[0], ED->q[0]); - else - cmp32(emu, GD->dword[0], ED->dword[0]); - break; - - - case 0x63: /* MOVSXD Gd, FS:Ed */ - nextop = F8; - GETED_OFFS(0, tlsdata); - GETGD; - if(rex.is32bits) { - // ARPL here - // faking to always happy... - SET_FLAG(F_ZF); - } else { - if(rex.w) - GD->sq[0] = ED->sdword[0]; - else - if(MODREG) - GD->q[0] = ED->dword[0]; // not really a sign extension - else - GD->sdword[0] = ED->sdword[0]; // meh? - } - break; - case 0x64: /* FS: prefix */ - #ifdef TEST_INTERPRETER - return Test64(test, rex, _FS, addr); - #else - return Run64(emu, rex, _FS, addr); - #endif - break; - case 0x65: /* GS: prefix */ - #ifdef TEST_INTERPRETER - return Test64(test, rex, _GS, addr); - #else - return Run64(emu, rex, _GS, addr); - #endif - break; - case 0x66: - return Run6664(emu, rex, seg, addr); - case 0x67: - if(rex.is32bits) - return Run6764_32(emu, rex, seg, seg, addr); - else - return Run6764(emu, rex, seg, seg, addr); - - case 0x69: /* IMUL Gd,Ed,Id */ - nextop = F8; - GETED_OFFS(4, tlsdata); - GETGD; - tmp64u = F32S64; - if(rex.w) - GD->q[0] = imul64(emu, ED->q[0], tmp64u); - else - GD->q[0] = imul32(emu, ED->dword[0], tmp64u); - break; - - case 0x6C: /* INSB DX */ - case 0x6D: /* INSD DX */ - case 0x6E: /* OUTSB DX */ - case 0x6F: /* OUTSD DX */ - return addr-1; // skip 64/65 prefix and resume normal execution - - case 0x80: /* GRP Eb,Ib */ - nextop = F8; - GETEB_OFFS(1, tlsdata); - tmp8u = F8; - switch((nextop>>3)&7) { - case 0: EB->byte[0] = add8(emu, EB->byte[0], tmp8u); break; - case 1: EB->byte[0] = or8(emu, EB->byte[0], tmp8u); break; - case 2: EB->byte[0] = adc8(emu, EB->byte[0], tmp8u); break; - case 3: EB->byte[0] = sbb8(emu, EB->byte[0], tmp8u); break; - case 4: EB->byte[0] = and8(emu, EB->byte[0], tmp8u); break; - case 5: EB->byte[0] = sub8(emu, EB->byte[0], tmp8u); break; - case 6: EB->byte[0] = xor8(emu, EB->byte[0], tmp8u); break; - case 7: cmp8(emu, EB->byte[0], tmp8u); break; - } - break; - case 0x81: /* GRP Ed,Id */ - case 0x83: /* GRP Ed,Ib */ - nextop = F8; - GETED_OFFS((opcode==0x81)?4:1, tlsdata); - if(opcode==0x81) { - tmp32s = F32S; - } else { - tmp32s = F8S; - } - if(rex.w) { - tmp64u = (uint64_t)(int64_t)tmp32s; - switch((nextop>>3)&7) { - case 0: ED->q[0] = add64(emu, ED->q[0], tmp64u); break; - case 1: ED->q[0] = or64(emu, ED->q[0], tmp64u); break; - case 2: ED->q[0] = adc64(emu, ED->q[0], tmp64u); break; - case 3: ED->q[0] = sbb64(emu, ED->q[0], tmp64u); break; - case 4: ED->q[0] = and64(emu, ED->q[0], tmp64u); break; - case 5: ED->q[0] = sub64(emu, ED->q[0], tmp64u); break; - case 6: ED->q[0] = xor64(emu, ED->q[0], tmp64u); break; - case 7: cmp64(emu, ED->q[0], tmp64u); break; - } - } else { - tmp32u = (uint32_t)tmp32s; - 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 0x85: /* TEST Ed,Gd */ - nextop = F8; - GETED_OFFS(0, tlsdata); - GETGD; - if(rex.w) - test64(emu, ED->q[0], GD->q[0]); - else - test32(emu, ED->dword[0], GD->dword[0]); - break; - case 0x86: /* XCHG Eb,Gb */ - nextop = F8; -#if defined(DYNAREC) && !defined(TEST_INTERPRETER) - GETEB_OFFS(0, tlsdata); - GETGB; - if(MODREG) { // reg / reg: no lock - tmp8u = GB; - GB = EB->byte[0]; - EB->byte[0] = tmp8u; - } else { - GB = native_lock_xchg_b(EB, GB); - } - // dynarec use need it's own mecanism -#else - GETEB_OFFS(0, tlsdata); - GETGB; - if(!MODREG) - pthread_mutex_lock(&my_context->mutex_lock); // XCHG always LOCK (but when accessing memory only) - tmp8u = GB; - GB = EB->byte[0]; - EB->byte[0] = tmp8u; - if(!MODREG) - pthread_mutex_unlock(&my_context->mutex_lock); -#endif - break; - - case 0x88: /* MOV FS:Eb,Gb */ - nextop = F8; - GETEB_OFFS(0, tlsdata); - GETGB; - EB->byte[0] = GB; - break; - case 0x89: /* MOV FS:Ed,Gd */ - nextop = F8; - GETED_OFFS(0, tlsdata); - GETGD; - if(rex.w) { - ED->q[0] = GD->q[0]; - } else { - if(MODREG) - ED->q[0] = GD->dword[0]; - else - ED->dword[0] = GD->dword[0]; - } - break; - case 0x8A: /* MOV Gb, FS:Eb */ - nextop = F8; - GETEB_OFFS(0, tlsdata); - GETGB; - GB = EB->byte[0]; - break; - case 0x8B: /* MOV Gd, FS:Ed */ - nextop = F8; - GETED_OFFS(0, tlsdata); - GETGD; - if(rex.w) - GD->q[0] = ED->q[0]; - else - GD->q[0] = ED->dword[0]; - break; - - case 0x8D: /* LEA Gd,M */ - nextop = F8; - GETGD; - tmp64u = GETEA(0); - if(rex.w) - GD->q[0] = tmp64u; - else - GD->q[0] = tmp64u&0xffffffff; - break; - case 0x8E: /* MOV Seg, Seg:Ew */ - nextop = F8; - GETED_OFFS(0, tlsdata); - emu->segs[((nextop&0x38)>>3)] = ED->word[0]; - emu->segs_serial[((nextop&0x38)>>3)] = 0; - break; - case 0x8F: /* POP FS:Ed */ - nextop = F8; - if(MODREG) { - emu->regs[(nextop&7)+(rex.b<<3)].q[0] = Pop64(emu); - } else { - if(rex.is32bits) { - tmp32u = Pop32(emu); // this order allows handling POP [ESP] and variant - GETED_OFFS(0, tlsdata); - R_ESP -= 4; // to prevent issue with SEGFAULT - ED->dword[0] = tmp32u; - R_ESP += 4; - } else { - tmp64u = Pop64(emu); // this order allows handling POP [ESP] and variant - GETED_OFFS(0, tlsdata); - R_RSP -= sizeof(void*); // to prevent issue with SEGFAULT - ED->q[0] = tmp64u; - R_RSP += sizeof(void*); - } - } - break; - case 0x90: /* NOP */ - break; - - case 0x9D: /* POPF */ - return addr-1; // skip 64/65 prefix and resume normal execution - - case 0xA1: /* MOV EAX,FS:Od */ - if(rex.is32bits) { - tmp32s = F32S; - R_EAX = *(uint32_t*)(tlsdata+tmp32s); - } else { - tmp64u = F64; - if(rex.w) - R_RAX = *(uint64_t*)(tlsdata+tmp64u); - else - R_RAX = *(uint32_t*)(tlsdata+tmp64u); - } - break; - case 0xA2: /* MOV Ob,AL */ - if(rex.is32bits) { - tmp32s = F32S; - *(uint8_t*)(uintptr_t)(tlsdata+tmp32s) = R_AL; - } else { - tmp64u = F64; - *(uint8_t*)(tlsdata+tmp64u) = R_AL; - } - break; - case 0xA3: /* MOV FS:Od,EAX */ - if(rex.is32bits) { - tmp32s = F32S; - *(uint32_t*)(uintptr_t)(tlsdata+tmp32s) = R_EAX; - } else { - tmp64u = F64; - if(rex.w) - *(uint64_t*)(tlsdata+tmp64u) = R_RAX; - else - *(uint32_t*)(tlsdata+tmp64u) = R_EAX; - } - break; - case 0xC4: /* LES Gd,Ed */ - nextop = F8; - if(rex.is32bits && !(MODREG)) { - GETED(0); - GETGD; - emu->segs[_ES] = *(uint16_t*)(((char*)ED) + 4); - emu->segs_serial[_ES] = 0; - GD->dword[0] = *(uint32_t*)ED; - } else { - vex_t vex = {0}; - vex.rex = rex; - tmp8u = nextop; - vex.m = tmp8u&0b00011111; - vex.rex.b = (tmp8u&0b00100000)?0:1; - vex.rex.x = (tmp8u&0b01000000)?0:1; - vex.rex.r = (tmp8u&0b10000000)?0:1; - tmp8u = F8; - vex.p = tmp8u&0b00000011; - vex.l = (tmp8u>>2)&1; - vex.v = ((~tmp8u)>>3)&0b1111; - vex.rex.w = (tmp8u>>7)&1; - #ifdef TEST_INTERPRETER - addr = Test64AVX(test, vex, addr, tlsdata); - #else - addr = Run64AVX(emu, vex, addr, tlsdata); - #endif - } - break; - case 0xC5: /* LDS Gd,Ed */ - nextop = F8; - if(rex.is32bits && !(MODREG)) { - GETED(0); - GETGD; - emu->segs[_DS] = *(uint16_t*)(((char*)ED) + 4); - emu->segs_serial[_DS] = 0; - GD->dword[0] = *(uint32_t*)ED; - } else { - vex_t vex = {0}; - vex.rex = rex; - tmp8u = nextop; - vex.p = tmp8u&0b00000011; - vex.l = (tmp8u>>2)&1; - vex.v = ((~tmp8u)>>3)&0b1111; - vex.rex.r = (tmp8u&0b10000000)?0:1; - vex.rex.b = 0; - vex.rex.x = 0; - vex.rex.w = 0; - vex.m = VEX_M_0F; - #ifdef TEST_INTERPRETER - addr = Test64AVX(test, vex, addr, tlsdata); - #else - addr = Run64AVX(emu, vex, addr, tlsdata); - #endif - } - break; - case 0xC6: /* MOV FS:Eb, Ib */ - nextop = F8; - GETEB_OFFS(1, tlsdata); - EB->byte[0] = F8; - break; - case 0xC7: /* MOV FS:Ed, Id */ - nextop = F8; - GETED_OFFS(4, tlsdata); - if(rex.w) - ED->q[0] = F32S64; - else - if(MODREG) - ED->q[0] = F32; - else - ED->dword[0] = F32; - break; - - case 0xD1: /* GRP2 Ed,1 */ - case 0xD3: /* GRP2 Ed,CL */ - nextop = F8; - GETED_OFFS(0, tlsdata); - tmp8u = (opcode==0xD1)?1:R_CL; - if(rex.w) { - switch((nextop>>3)&7) { - case 0: ED->q[0] = rol64(emu, ED->q[0], tmp8u); break; - case 1: ED->q[0] = ror64(emu, ED->q[0], tmp8u); break; - case 2: ED->q[0] = rcl64(emu, ED->q[0], tmp8u); break; - case 3: ED->q[0] = rcr64(emu, ED->q[0], tmp8u); break; - case 4: - case 6: ED->q[0] = shl64(emu, ED->q[0], tmp8u); break; - case 5: ED->q[0] = shr64(emu, ED->q[0], tmp8u); break; - case 7: ED->q[0] = sar64(emu, ED->q[0], tmp8u); break; - } - } else { - 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; - - case 0xD8: /* x87 opcodes */ - #ifdef TEST_INTERPRETER - return TestD8(test, rex, addr, tlsdata); - #else - return RunD8(emu, rex, addr, tlsdata); - #endif - break; - case 0xD9: /* x87 opcodes */ - #ifdef TEST_INTERPRETER - return TestD9(test, rex, addr, tlsdata); - #else - return RunD9(emu, rex, addr, tlsdata); - #endif - break; - - case 0xEB: /* JMP Ib */ - return addr-1; // skip 64/65 prefix and resume normal execution - - case 0xF6: /* GRP3 Eb(,Ib) */ - nextop = F8; - tmp8u = (nextop>>3)&7; - GETEB_OFFS((tmp8u<2)?1:0, tlsdata); - switch(tmp8u) { - case 0: - case 1: /* TEST Eb,Ib */ - tmp8u = F8; - test8(emu, EB->byte[0], tmp8u); - break; - case 2: /* NOT Eb */ - EB->byte[0] = not8(emu, EB->byte[0]); - break; - case 3: /* NEG Eb */ - EB->byte[0] = neg8(emu, EB->byte[0]); - break; - case 4: /* MUL AL,Eb */ - mul8(emu, EB->byte[0]); - break; - case 5: /* IMUL AL,Eb */ - imul8(emu, EB->byte[0]); - break; - case 6: /* DIV Eb */ - if(!EB->byte[0]) - EmitDiv0(emu, (void*)R_RIP, 1); - div8(emu, EB->byte[0]); - break; - case 7: /* IDIV Eb */ - if(!EB->byte[0]) - EmitDiv0(emu, (void*)R_RIP, 1); - idiv8(emu, EB->byte[0]); - break; - } - break; - case 0xF7: /* GRP3 Ed(,Id) */ - nextop = F8; - tmp8u = (nextop>>3)&7; - GETED_OFFS((tmp8u<2)?4:0, tlsdata); - if(rex.w) { - switch(tmp8u) { - case 0: - case 1: /* TEST Ed,Id */ - tmp64u = F32S64; - test64(emu, ED->q[0], tmp64u); - break; - case 2: /* NOT Ed */ - ED->q[0] = not64(emu, ED->q[0]); - break; - case 3: /* NEG Ed */ - ED->q[0] = neg64(emu, ED->q[0]); - break; - case 4: /* MUL RAX,Ed */ - mul64_rax(emu, ED->q[0]); - break; - case 5: /* IMUL RAX,Ed */ - imul64_rax(emu, ED->q[0]); - break; - case 6: /* DIV Ed */ - div64(emu, ED->q[0]); - break; - case 7: /* IDIV Ed */ - idiv64(emu, ED->q[0]); - break; - } - } else { - switch(tmp8u) { - case 0: - case 1: /* TEST Ed,Id */ - tmp32u = F32; - test32(emu, ED->dword[0], tmp32u); - break; - case 2: /* NOT Ed */ - if(MODREG) - ED->q[0] = not32(emu, ED->dword[0]); - else - ED->dword[0] = not32(emu, ED->dword[0]); - break; - case 3: /* NEG Ed */ - if(MODREG) - ED->q[0] = neg32(emu, ED->dword[0]); - else - ED->dword[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; // already put high regs to 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 0xFF: /* GRP 5 Ed */ - nextop = F8; - GETED_OFFS(0, tlsdata); - switch((nextop>>3)&7) { - case 0: /* INC Ed */ - if(rex.w) - ED->q[0] = inc64(emu, ED->q[0]); - else { - if(MODREG) - ED->q[0] = inc32(emu, ED->dword[0]); - else - ED->dword[0] = inc32(emu, ED->dword[0]); - } - break; - case 1: /* DEC Ed */ - if(rex.w) - ED->q[0] = dec64(emu, ED->q[0]); - else { - if(MODREG) - ED->q[0] = dec32(emu, ED->dword[0]); - else - ED->dword[0] = dec32(emu, ED->dword[0]); - } - break; - case 2: /* CALL NEAR Ed */ - if(rex.is32bits) { - tmp64u = (uintptr_t)getAlternate((void*)(uintptr_t)ED->dword[0]); - Push32(emu, addr); - } else { - tmp64u = (uintptr_t)getAlternate((void*)ED->q[0]); - Push64(emu, addr); - } - addr = tmp64u; - break; - case 3: /* CALL FAR Ed */ - if(MODREG) { - printf_log(LOG_NONE, "Illegal Opcode %p: %02X %02X %02X %02X\n", (void*)R_RIP, opcode, nextop, PK(2), PK(3)); - emu->quit=1; - emu->error |= ERR_ILLEGAL; - return 0; - } else { - if(rex.is32bits || !rex.w) { - Push32(emu, R_CS); - Push32(emu, addr); - R_RIP = addr = ED->dword[0]; - R_CS = ED->word[2]; - } else { - Push64(emu, R_CS); - Push64(emu, addr); - R_RIP = addr = ED->q[0]; - R_CS = (ED+1)->word[0]; - } - return 0; // exit loop to recompute new CS... - } - break; - case 4: /* JMP NEAR Ed */ - if(rex.is32bits) - addr = (uintptr_t)getAlternate((void*)(uintptr_t)ED->dword[0]); - else - addr = (uintptr_t)getAlternate((void*)ED->q[0]); - break; - case 5: /* JMP FAR Ed */ - if(MODREG) { - printf_log(LOG_NONE, "Illegal Opcode %p: 0x%02X 0x%02X %02X %02X\n", (void*)R_RIP, opcode, nextop, PK(2), PK(3)); - emu->quit=1; - emu->error |= ERR_ILLEGAL; - return 0; - } else { - if(rex.is32bits || !rex.w) { - R_RIP = addr = ED->dword[0]; - R_CS = ED->word[2]; - } else { - R_RIP = addr = ED->q[0]; - R_CS = (ED+1)->word[0]; - } - } - break; - case 6: /* Push Ed */ - if(rex.is32bits) { - tmp32u = ED->dword[0]; - Push32(emu, tmp32u); // avoid potential issue with push [esp+...] - } else { - tmp64u = ED->q[0]; // rex.w ignored - Push64(emu, tmp64u); // avoid potential issue with push [esp+...] - } - break; - default: - printf_log(LOG_NONE, "Illegal Opcode %p: %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 0; - } - return addr; -} |