diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2021-03-05 14:38:55 +0100 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2021-03-05 14:38:55 +0100 |
| commit | cafbaa1e239994ee0ef694e2650cb224ce15a7a9 (patch) | |
| tree | 01a2cb599d4f54d6b5107cf3f7bf6f920c03003f /src | |
| parent | b13273be0536d5ecf5b70f9935208540e82f1d05 (diff) | |
| download | box64-cafbaa1e239994ee0ef694e2650cb224ce15a7a9.tar.gz box64-cafbaa1e239994ee0ef694e2650cb224ce15a7a9.zip | |
Added REX F7 opcodes
Diffstat (limited to 'src')
| -rwxr-xr-x | src/emu/x64primop.c | 56 | ||||
| -rwxr-xr-x | src/emu/x64primop.h | 12 | ||||
| -rwxr-xr-x | src/emu/x64run.c | 58 |
3 files changed, 123 insertions, 3 deletions
diff --git a/src/emu/x64primop.c b/src/emu/x64primop.c index 0c040f1d..9b6fffb8 100755 --- a/src/emu/x64primop.c +++ b/src/emu/x64primop.c @@ -1371,10 +1371,10 @@ void idiv32(x64emu_t *emu, uint32_t s) INTR_RAISE_DIV0(emu); return; } - lldiv_t p = lldiv(dvd, (int32_t)s); + ldiv_t p = ldiv(dvd, (int32_t)s); quot = p.quot; mod = p.rem; - if (llabs(quot) > 0x7fffffff) { + if (labs(quot) > 0x7fffffff) { INTR_RAISE_DIV0(emu); return; } @@ -1388,6 +1388,32 @@ void idiv32(x64emu_t *emu, uint32_t s) R_EDX = (uint32_t)mod; } +void idiv64(x64emu_t *emu, uint64_t s) +{ + __int128 dvd, quot, mod; + RESET_FLAGS(emu); + + dvd = (((__int128)R_RDX) << 64) | R_RAX; + if (s == 0) { + INTR_RAISE_DIV0(emu); + return; + } + quot = dvd/(int64_t)s; + mod = dvd%(int64_t)s; + if (llabs(quot) > 0x7fffffffffffffffL) { + INTR_RAISE_DIV0(emu); + return; + } + CLEAR_FLAG(F_CF); + CLEAR_FLAG(F_AF); + CLEAR_FLAG(F_SF); + SET_FLAG(F_ZF); + CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF); + + R_RAX = (uint64_t)quot; + R_RDX = (uint64_t)mod; +} + /**************************************************************************** REMARKS: Implements the DIV instruction and side effects. @@ -1462,3 +1488,29 @@ void div32(x64emu_t *emu, uint32_t s) R_EAX = (uint32_t)div; R_EDX = (uint32_t)mod; } + +void div64(x64emu_t *emu, uint64_t s) +{ + __int128 dvd, div, mod; + RESET_FLAGS(emu); + + dvd = (((__int128)R_RDX) << 64) | R_RAX; + if (s == 0) { + INTR_RAISE_DIV0(emu); + return; + } + div = dvd / (unsigned __int128)s; + mod = dvd % (unsigned __int128)s; + if (div > 0xffffffffffffffffL) { + INTR_RAISE_DIV0(emu); + return; + } + CLEAR_FLAG(F_CF); + CLEAR_FLAG(F_AF); + CLEAR_FLAG(F_SF); + SET_FLAG(F_ZF); + CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF); + + R_RAX = (uint64_t)div; + R_RDX = (uint64_t)mod; +} diff --git a/src/emu/x64primop.h b/src/emu/x64primop.h index 2b018548..df32d2c4 100755 --- a/src/emu/x64primop.h +++ b/src/emu/x64primop.h @@ -559,7 +559,7 @@ static inline uint64_t imul64(x64emu_t *emu, uint64_t op1, uint64_t op2) return emu->res; } -static inline void imul64_eax(x64emu_t *emu, uint64_t s) +static inline void imul64_rax(x64emu_t *emu, uint64_t s) { emu->df = d_imul64; imul64_direct(&R_RAX,&R_RDX,R_RAX,s); @@ -589,11 +589,21 @@ static inline void mul32_eax(x64emu_t *emu, uint32_t s) emu->op1 = R_EDX = (uint32_t)(res >> 32); } +static inline void mul64_rax(x64emu_t *emu, uint64_t s) +{ + emu->df = d_mul64; + __int128 res = (__int128)R_RAX * s; + emu->res = R_RAX = (uint64_t)res; + emu->op1 = R_RDX = (uint64_t)(res >> 64); +} + void idiv8 (x64emu_t *emu, uint8_t s); void idiv16 (x64emu_t *emu, uint16_t s); void idiv32 (x64emu_t *emu, uint32_t s); +void idiv64 (x64emu_t *emu, uint64_t s); void div8 (x64emu_t *emu, uint8_t s); void div16 (x64emu_t *emu, uint16_t s); void div32 (x64emu_t *emu, uint32_t s); +void div64 (x64emu_t *emu, uint64_t s); #endif //__X64PRIMOP_H_ diff --git a/src/emu/x64run.c b/src/emu/x64run.c index 2a6c3585..4f3b9986 100755 --- a/src/emu/x64run.c +++ b/src/emu/x64run.c @@ -473,6 +473,64 @@ x64emurun: STEP break; + case 0xF7: /* GRP3 Ed(,Id) */ + nextop = F8; + GETED; + if(rex.w) { + switch((nextop>>3)&7) { + 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((nextop>>3)&7) { + case 0: + case 1: /* TEST Ed,Id */ + tmp32u = F32; + test32(emu, ED->dword[0], tmp32u); + break; + case 2: /* NOT Ed */ + ED->dword[0] = not32(emu, ED->dword[0]); + break; + case 3: /* NEG Ed */ + ED->dword[0] = neg32(emu, ED->dword[0]); + break; + case 4: /* MUL EAX,Ed */ + mul32_eax(emu, ED->dword[0]); + break; + case 5: /* IMUL EAX,Ed */ + imul32_eax(emu, ED->dword[0]); + break; + case 6: /* DIV Ed */ + div32(emu, ED->dword[0]); + break; + case 7: /* IDIV Ed */ + idiv32(emu, ED->dword[0]); + break; + } + } + break; + case 0xFF: /* GRP 5 Ed */ nextop = F8; GETED; |