From dde85b761b43c5fecb89177b09d6e596e6338a0c Mon Sep 17 00:00:00 2001 From: ptitSeb Date: Fri, 31 May 2024 15:59:11 +0200 Subject: [INTERPRETER] Added BMI1, BMI2 and ADX extensions --- src/emu/modrm.h | 2 + src/emu/x64run.c | 12 +-- src/emu/x64run660f.c | 28 ++++++- src/emu/x64run67.c | 71 +++++++++++++++- src/emu/x64run67660f.c | 14 ++++ src/emu/x64run67avx.c | 106 ++++++++++++++++++++++++ src/emu/x64run_private.h | 25 ++++-- src/emu/x64runavx.c | 37 ++++++++- src/emu/x64runavx0f38.c | 205 ++++++++++++++++++++++++++++++++++++++++++++++ src/emu/x64runavx660f38.c | 16 +++- src/emu/x64runavxf20f38.c | 116 ++++++++++++++++++++++++++ src/emu/x64runavxf20f3a.c | 82 +++++++++++++++++++ src/emu/x64runavxf30f38.c | 102 +++++++++++++++++++++++ src/emu/x64runavxf30f3a.c | 66 +++++++++++++++ src/emu/x64runf30f.c | 37 ++++++++- src/librarian/library.c | 2 +- src/tools/my_cpuid.c | 5 +- src/wrapped/wrappedlibc.c | 2 +- 18 files changed, 905 insertions(+), 23 deletions(-) create mode 100644 src/emu/x64run67avx.c create mode 100644 src/emu/x64runavx0f38.c create mode 100644 src/emu/x64runavxf20f38.c create mode 100644 src/emu/x64runavxf20f3a.c create mode 100644 src/emu/x64runavxf30f38.c create mode 100644 src/emu/x64runavxf30f3a.c (limited to 'src') diff --git a/src/emu/modrm.h b/src/emu/modrm.h index b5d5bcac..8bc3cbd4 100644 --- a/src/emu/modrm.h +++ b/src/emu/modrm.h @@ -79,8 +79,10 @@ #endif #define GETVX opvx=&emu->xmm[vex.v] #define GETVY opvy=&emu->ymm[vex.v] +#define GETVD opvd=&emu->regs[vex.v] #define ED oped #define GD opgd +#define VD opvd #define EB oped #define GB opgd->byte[0] #define EW oped diff --git a/src/emu/x64run.c b/src/emu/x64run.c index 7283a76b..ff08d3fb 100644 --- a/src/emu/x64run.c +++ b/src/emu/x64run.c @@ -1345,8 +1345,8 @@ x64emurun: #endif break; case 0xC4: /* LES Gd,Ed */ - if(rex.is32bits && !(PK(0)&0x80)) { - nextop = F8; + nextop = F8; + if(rex.is32bits && !(MODREG)) { GETED(0); GETGD; emu->segs[_ES] = *(__uint16_t*)(((char*)ED)+4); @@ -1355,7 +1355,7 @@ x64emurun: } else { vex_t vex = {0}; vex.rex = rex; - tmp8u = F8; + tmp8u = nextop; vex.m = tmp8u&0b00011111; vex.rex.b = (tmp8u&0b00100000)?0:1; vex.rex.x = (tmp8u&0b01000000)?0:1; @@ -1380,8 +1380,8 @@ x64emurun: } break; case 0xC5: /* LDS Gd,Ed */ - if(rex.is32bits && !(PK(0)&0x80)) { - nextop = F8; + nextop = F8; + if(rex.is32bits && !(MODREG)) { GETED(0); GETGD; emu->segs[_DS] = *(__uint16_t*)(((char*)ED)+4); @@ -1390,7 +1390,7 @@ x64emurun: } else { vex_t vex = {0}; vex.rex = rex; - tmp8u = F8; + tmp8u = nextop; vex.p = tmp8u&0b00000011; vex.l = (tmp8u>>2)&1; vex.v = ((~tmp8u)>>3)&0b1111; diff --git a/src/emu/x64run660f.c b/src/emu/x64run660f.c index b32b78f9..ba4346ff 100644 --- a/src/emu/x64run660f.c +++ b/src/emu/x64run660f.c @@ -59,7 +59,7 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr) uint16_t tmp16u; int32_t tmp32s; uint32_t tmp32u; - uint64_t tmp64u; + uint64_t tmp64u, tmp64u2; int64_t tmp64s, i64[4]; float tmpf; double tmpd; @@ -811,6 +811,32 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr) GETGD; ED->word[0] = __builtin_bswap16(GD->word[0]); break; + + case 0xF6: /* ADCX Gd, Rd */ + nextop = F8; + GETED(0); + GETGD; + CHECK_FLAGS(emu); + if(rex.w) { + if (ACCESS_FLAG(F_CF)) { + tmp64u = 1 + (GD->q[0] & 0xFFFFFFFF) + (ED->q[0] & 0xFFFFFFFF); + tmp64u2 = 1 + GD->q[0] + ED->q[0]; + } + else { + tmp64u = (GD->q[0] & 0xFFFFFFFF) + (ED->q[0] & 0xFFFFFFFF); + tmp64u2 = GD->q[0] + ED->q[0]; + } + tmp64u = (tmp64u >> 32) + (GD->q[0] >> 32) + (ED->q[0] >> 32); + CONDITIONAL_SET_FLAG(tmp64u & 0x100000000L, F_CF); + GD->q[0] = tmp64u2; + } else { + if (ACCESS_FLAG(F_CF)) + GD->q[0] = 1LL + GD->dword[0] + ED->dword[0]; + else + GD->q[0] = (uint64_t)GD->dword[0] + ED->dword[0]; + CONDITIONAL_SET_FLAG(GD->q[0] & 0x100000000LL, F_CF); + } + break; default: return 0; } diff --git a/src/emu/x64run67.c b/src/emu/x64run67.c index 9cdcba3b..c17db227 100644 --- a/src/emu/x64run67.c +++ b/src/emu/x64run67.c @@ -332,6 +332,53 @@ uintptr_t Run67(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr) } break; + case 0xC4: /* LES Gd,Ed */ + nextop = F8; + if(rex.is32bits && !(MODREG)) { + return 0; + } 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 = Test67AVX(test, vex, addr); + #else + addr = Run67AVX(emu, vex, addr); + #endif + } + break; + case 0xC5: /* LDS Gd,Ed */ + nextop = F8; + if(rex.is32bits && !(MODREG)) { + return 0; + } 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 = Test67AVX(test, vex, addr); + #else + addr = Run67AVX(emu, vex, addr); + #endif + } + break; case 0xC6: /* MOV Eb,Ib */ nextop = F8; GETEB32(1); @@ -460,7 +507,29 @@ uintptr_t Run67(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr) case 0xFF: nextop = F8; switch((nextop>>3)&7) { - case 2: /* CALL NEAR Ed */ + case 0: /* INC Ed */ + GETED32(0); + 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 */ + GETED32(0); + 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 */ GETED32(0); tmp64u = (uintptr_t)getAlternate((void*)ED->q[0]); Push64(emu, addr); diff --git a/src/emu/x64run67660f.c b/src/emu/x64run67660f.c index c74e2644..a58df7c7 100644 --- a/src/emu/x64run67660f.c +++ b/src/emu/x64run67660f.c @@ -63,6 +63,20 @@ uintptr_t Run67660F(x64emu_t *emu, rex_t rex, uintptr_t addr) GX->ud[i] = (GX->ud[i]==EX->ud[i])?0xffffffff:0; break; + case 0x7E: /* MOVD Ed, Gx */ + nextop = F8; + GETED32(0); + GETGX; + if(rex.w) + ED->q[0] = GX->q[0]; + else { + if(MODREG) + ED->q[0] = GX->ud[0]; + else + ED->dword[0] = GX->ud[0]; + } + break; + case 0xD6: /* MOVQ Ex,Gx */ nextop = F8; GETEX32(0); diff --git a/src/emu/x64run67avx.c b/src/emu/x64run67avx.c new file mode 100644 index 00000000..c19a22f7 --- /dev/null +++ b/src/emu/x64run67avx.c @@ -0,0 +1,106 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "debug.h" +#include "box64stack.h" +#include "x64emu.h" +#include "x64run.h" +#include "x64emu_private.h" +#include "x64run_private.h" +#include "x64primop.h" +#include "x64trace.h" +#include "x87emu_private.h" +#include "box64context.h" +#include "my_cpuid.h" +#include "bridge.h" +#include "signals.h" +#include "x64shaext.h" +#ifdef DYNAREC +#include "custommem.h" +#include "../dynarec/native_lock.h" +#endif + +#include "modrm.h" + +static const char* avx_prefix_string(uint16_t p) +{ + switch(p) { + case VEX_P_NONE: return "0"; + case VEX_P_66: return "66"; + case VEX_P_F2: return "F2"; + case VEX_P_F3: return "F3"; + default: return "??"; + } +} +static const char* avx_map_string(uint16_t m) +{ + switch(m) { + case VEX_M_NONE: return "0"; + case VEX_M_0F: return "0F"; + case VEX_M_0F38: return "0F38"; + case VEX_M_0F3A: return "0F3A"; + default: return "??"; + } +} + +#ifdef TEST_INTERPRETER +uintptr_t Test67AVX(x64test_t *test, vex_t vex, uintptr_t addr) +#else +uintptr_t Run67AVX(x64emu_t *emu, vex_t vex, uintptr_t addr) +#endif +{ + uint8_t opcode; + uint8_t nextop; + uint8_t tmp8u; + int8_t tmp8s; + int32_t tmp32s, tmp32s2; + uint32_t tmp32u, tmp32u2; + uint64_t tmp64u, tmp64u2; + int64_t tmp64s; + reg64_t *oped, *opgd, *opvd; + sse_regs_t *opex, *opgx, *opvx, eax1; + sse_regs_t *opey, *opgy, *opvy, eay1; + +#ifdef TEST_INTERPRETER + x64emu_t *emu = test->emu; +#endif + opcode = F8; + + rex_t rex = vex.rex; + + if( (vex.m==VEX_M_0F38) && (vex.p==VEX_P_F2)) + switch(opcode) { + + case 0xF6: /* MULX Gd, Vd, Ed (,RDX) */ + nextop = F8; + GETED32(0); + GETGD; + GETVD; + if(rex.w) { + unsigned __int128 res = (unsigned __int128)R_RDX * ED->q[0]; + VD->q[0] = res&0xFFFFFFFFFFFFFFFFLL; + GD->q[0] = res>>64; + } else { + tmp64u = (uint64_t)R_EDX * ED->dword[0]; + VD->q[0] = tmp64u&0xFFFFFFFF; + GD->q[0] = tmp64u>>32; + } + break; + + default: addr = 0; + } + else addr = 0; + + if(!addr) + printf_log(LOG_INFO, "Unimplemented 67 AVX opcode size %d prefix %s map %s opcode %02X ", 128<emu; -#endif + if( (vex.m==VEX_M_0F) && (vex.p==VEX_P_NONE)) + addr = TestAVX_0F(test, vex, addr, step); + else if( (vex.m==VEX_M_0F38) && (vex.p==VEX_P_NONE)) + addr = TestAVX_0F38(test, vex, addr, step); + else if( (vex.m==VEX_M_0F) && (vex.p==VEX_P_66)) + addr = TestAVX_660F(test, vex, addr, step); + else if( (vex.m==VEX_M_0F) && (vex.p==VEX_P_F2)) + addr = TestAVX_F20F(test, vex, addr, step); + else if( (vex.m==VEX_M_0F) && (vex.p==VEX_P_F3)) + addr = TestAVX_F30F(test, vex, addr, step); + else if( (vex.m==VEX_M_0F38) && (vex.p==VEX_P_66)) + addr = TestAVX_660F38(test, vex, addr, step); + else if( (vex.m==VEX_M_0F3A) && (vex.p==VEX_P_66)) + addr = TestAVX_660F3A(test, vex, addr, step); + else if( (vex.m==VEX_M_0F38) && (vex.p==VEX_P_F2)) + addr = TestAVX_F20F38(test, vex, addr, step); + else if( (vex.m==VEX_M_0F38) && (vex.p==VEX_P_F3)) + addr = TestAVX_F30F38(test, vex, addr, step); + else if( (vex.m==VEX_M_0F3A) && (vex.p==VEX_P_F2)) + addr = TestAVX_F20F3A(test, vex, addr, step); + else if( (vex.m==VEX_M_0F3A) && (vex.p==VEX_P_F3)) + addr = TestAVX_F30F3A(test, vex, addr, step); + else addr = 0; +#else uint8_t opcode = PK(0); if( (vex.m==VEX_M_0F) && (vex.p==VEX_P_NONE)) addr = RunAVX_0F(emu, vex, addr, step); + else if( (vex.m==VEX_M_0F38) && (vex.p==VEX_P_NONE)) + addr = RunAVX_0F38(emu, vex, addr, step); else if( (vex.m==VEX_M_0F) && (vex.p==VEX_P_66)) addr = RunAVX_660F(emu, vex, addr, step); else if( (vex.m==VEX_M_0F) && (vex.p==VEX_P_F2)) @@ -73,10 +97,19 @@ uintptr_t RunAVX(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) addr = RunAVX_660F38(emu, vex, addr, step); else if( (vex.m==VEX_M_0F3A) && (vex.p==VEX_P_66)) addr = RunAVX_660F3A(emu, vex, addr, step); + else if( (vex.m==VEX_M_0F38) && (vex.p==VEX_P_F2)) + addr = RunAVX_F20F38(emu, vex, addr, step); + else if( (vex.m==VEX_M_0F38) && (vex.p==VEX_P_F3)) + addr = RunAVX_F30F38(emu, vex, addr, step); + else if( (vex.m==VEX_M_0F3A) && (vex.p==VEX_P_F2)) + addr = RunAVX_F20F3A(emu, vex, addr, step); + else if( (vex.m==VEX_M_0F3A) && (vex.p==VEX_P_F3)) + addr = RunAVX_F30F3A(emu, vex, addr, step); else addr = 0; if(!addr) printf_log(LOG_INFO, "Unimplemented AVX opcode size %d prefix %s map %s opcode %02X ", 128< +#include +#include +#include +#include +#include +#include +#include +#include + +#include "debug.h" +#include "box64stack.h" +#include "x64emu.h" +#include "x64run.h" +#include "x64emu_private.h" +#include "x64run_private.h" +#include "x64primop.h" +#include "x64trace.h" +#include "x87emu_private.h" +#include "box64context.h" +#include "my_cpuid.h" +#include "bridge.h" +#include "signals.h" +#ifdef DYNAREC +#include "custommem.h" +#include "../dynarec/native_lock.h" +#endif + +#include "modrm.h" + +#ifdef TEST_INTERPRETER +uintptr_t TestAVX_0F38(x64test_t *test, vex_t vex, uintptr_t addr, int *step) +#else +uintptr_t RunAVX_0F38(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) +#endif +{ + uint8_t opcode; + uint8_t nextop; + uint8_t tmp8u, u8; + int8_t tmp8s; + int16_t tmp16s; + uint16_t tmp16u; + int32_t tmp32s, tmp32s2; + uint32_t tmp32u, tmp32u2; + uint64_t tmp64u, tmp64u2; + int64_t tmp64s; + reg64_t *oped, *opgd, *opvd; + sse_regs_t *opex, *opgx, *opvx, eax1, eax2; + sse_regs_t *opey, *opgy, *opvy, eay1, eay2; + + +#ifdef TEST_INTERPRETER + x64emu_t *emu = test->emu; +#endif + opcode = F8; + + rex_t rex = vex.rex; + + switch(opcode) { + + case 0xF2: /* ANDN Gd, Vd, Ed */ + nextop = F8; + if(vex.l) emit_signal(emu, SIGILL, (void*)R_RIP, 0); + GETGD; + GETED(0); + GETVD; + if(rex.w) + GD->q[0] = ED->q[0] & ~VD->q[0]; + else { + if(MODREG) + GD->q[0] = ED->dword[0] & ~VD->dword[0]; + else + GD->dword[0] = ED->dword[0] & ~VD->dword[0]; + } + break; + case 0xF3: + nextop = F8; + switch((nextop>>3)&7) { + case 1: /* BLSR Vd, Ed */ + if(vex.l) emit_signal(emu, SIGILL, (void*)R_RIP, 0); + ResetFlags(emu); + GETVD; + GETED(0); + CONDITIONAL_SET_FLAG(rex.w?(ED->q[0]==0):(ED->dword[0]==0), F_CF); + if(rex.w) + VD->q[0] = ED->q[0] & (ED->q[0]-1LL); + else + VD->dword[0] = ED->dword[0] & (ED->dword[0]-1); + if(MODREG && !rex.w) + VD->dword[1] = 0; + CONDITIONAL_SET_FLAG(rex.w?(VD->q[0]==0):(VD->dword[0]==0), F_ZF); + CONDITIONAL_SET_FLAG(rex.w?(VD->q[0]>>63):(VD->dword[0]>>31), F_SF); + CLEAR_FLAG(F_OF); + CLEAR_FLAG(F_AF); // Undef + CLEAR_FLAG(F_PF); // Undef + break; + case 2: /* BLSMSK Vd, Ed */ + if(vex.l) emit_signal(emu, SIGILL, (void*)R_RIP, 0); + ResetFlags(emu); + GETVD; + GETED(0); + CONDITIONAL_SET_FLAG(rex.w?(ED->q[0]==0):(ED->dword[0]==0), F_CF); + if(rex.w) + VD->q[0] = ED->q[0] ^ (ED->q[0]-1LL); + else + VD->dword[0] = ED->dword[0] ^ (ED->dword[0]-1); + if(MODREG && !rex.w) + VD->dword[1] = 0; + CONDITIONAL_SET_FLAG(rex.w?(VD->q[0]>>63):(VD->dword[0]>>31), F_SF); + CLEAR_FLAG(F_ZF); + CLEAR_FLAG(F_OF); + CLEAR_FLAG(F_AF); // Undef + CLEAR_FLAG(F_PF); // Undef + break; + case 3: /* BLSI Vd, Ed */ + if(vex.l) emit_signal(emu, SIGILL, (void*)R_RIP, 0); + ResetFlags(emu); + GETVD; + GETED(0); + CONDITIONAL_SET_FLAG(rex.w?(ED->q[0]==0):(ED->dword[0]==0), F_CF); + if(rex.w) + VD->sq[0] = ED->sq[0] & (-ED->sq[0]); + else + VD->sdword[0] = ED->sdword[0] & (-ED->sdword[0]); + if(MODREG && !rex.w) + VD->dword[1] = 0; + CONDITIONAL_SET_FLAG(rex.w?(VD->q[0]==0):(VD->dword[0]==0), F_ZF); + CONDITIONAL_SET_FLAG(rex.w?(VD->q[0]>>63):(VD->dword[0]>>31), F_SF); + CLEAR_FLAG(F_OF); + CLEAR_FLAG(F_AF); // Undef + CLEAR_FLAG(F_PF); // Undef + break; + default: + return 0; + } + break; + + case 0xF5: /* BZHI Gd, Ed, Vd */ + nextop = F8; + if(vex.l) emit_signal(emu, SIGILL, (void*)R_RIP, 0); + GETGD; + GETED(0); + GETVD; + tmp32u = VD->byte[0]; // start + if(rex.w) { + GD->q[0] = ED->q[0]; + if(tmp32u<64) GD->q[0] &= ~((-1LL<63), F_CF); + } else { + GD->q[0] = ED->dword[0]; + if(tmp32u<32) GD->dword[0] &= ~((-1<31), F_CF); + } + CONDITIONAL_SET_FLAG(rex.w?(GD->q[0]==0):(GD->dword[0]==0), F_ZF); + CONDITIONAL_SET_FLAG(rex.w?(VD->q[0]>>63):(VD->dword[0]>>31), F_SF); + CLEAR_FLAG(F_OF); + CLEAR_FLAG(F_AF); // Undef + CLEAR_FLAG(F_PF); // Undef + break; + + case 0xF7: /* BEXTR Gd, Ed, Vd */ + nextop = F8; + if(vex.l) emit_signal(emu, SIGILL, (void*)R_RIP, 0); + ResetFlags(emu); + GETGD; + GETED(0); + GETVD; + tmp32u = VD->byte[0]; // start + tmp32u2 = VD->byte[1]; // end + if(rex.w) { + if(tmp32u2<0x40) + tmp64u = ((1LL<q[0] = (ED->q[0]>>tmp32u)&tmp64u; + else + GD->q[0] = 0; + } else { + if(tmp32u2<0x20) + tmp64u = ((1LL<dword[0] = (ED->dword[0]>>tmp32u)&tmp64u; + else + GD->dword[0] = 0; + if(MODREG) + GD->dword[1] = 0; + } + ResetFlags(emu); + CONDITIONAL_SET_FLAG(rex.w?(GD->q[0]==0):(GD->dword[0]==0), F_ZF); + CLEAR_FLAG(F_CF); + CLEAR_FLAG(F_OF); + CLEAR_FLAG(F_AF); // Undef + CLEAR_FLAG(F_SF); // Undef + CLEAR_FLAG(F_PF); // Undef + break; + + default: + return 0; + } + return addr; +} diff --git a/src/emu/x64runavx660f38.c b/src/emu/x64runavx660f38.c index 24acf83c..535371f2 100644 --- a/src/emu/x64runavx660f38.c +++ b/src/emu/x64runavx660f38.c @@ -67,7 +67,7 @@ uintptr_t RunAVX_660F38(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) uint32_t tmp32u, tmp32u2; uint64_t tmp64u, tmp64u2; int64_t tmp64s; - reg64_t *oped, *opgd; + reg64_t *oped, *opgd, *opvd; sse_regs_t *opex, *opgx, *opvx, eax1, eax2; sse_regs_t *opey, *opgy, *opvy, eay1, eay2; // AES opcodes constants @@ -1637,6 +1637,20 @@ uintptr_t RunAVX_660F38(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) GY->u128 = 0; break; + case 0xF7: /* SHLX Gd, Ed, Vd */ + nextop = F8; + GETED(0); + GETGD; + GETVD; + if(rex.w) { + u8 = VD->q[0] & 0x3f; + GD->q[0] = ED->q[0] << u8; + } else { + u8 = VD->dword[0] & 0x1f; + GD->q[0] = ED->dword[0] << u8; + } + break; + default: return 0; } diff --git a/src/emu/x64runavxf20f38.c b/src/emu/x64runavxf20f38.c new file mode 100644 index 00000000..05754092 --- /dev/null +++ b/src/emu/x64runavxf20f38.c @@ -0,0 +1,116 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "debug.h" +#include "box64stack.h" +#include "x64emu.h" +#include "x64run.h" +#include "x64emu_private.h" +#include "x64run_private.h" +#include "x64primop.h" +#include "x64trace.h" +#include "x87emu_private.h" +#include "box64context.h" +#include "my_cpuid.h" +#include "bridge.h" +#include "signals.h" +#ifdef DYNAREC +#include "custommem.h" +#include "../dynarec/native_lock.h" +#endif + +#include "modrm.h" + +#ifdef TEST_INTERPRETER +uintptr_t TestAVX_F20F38(x64test_t *test, vex_t vex, uintptr_t addr, int *step) +#else +uintptr_t RunAVX_F20F38(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) +#endif +{ + uint8_t opcode; + uint8_t nextop; + uint8_t tmp8u, u8; + int8_t tmp8s; + int16_t tmp16s; + uint16_t tmp16u; + int32_t tmp32s, tmp32s2; + uint32_t tmp32u, tmp32u2; + uint64_t tmp64u, tmp64u2; + int64_t tmp64s; + reg64_t *oped, *opgd, *opvd; + sse_regs_t *opex, *opgx, *opvx, eax1, eax2; + sse_regs_t *opey, *opgy, *opvy, eay1, eay2; + + +#ifdef TEST_INTERPRETER + x64emu_t *emu = test->emu; +#endif + opcode = F8; + + rex_t rex = vex.rex; + + switch(opcode) { + + case 0xF5: /* PDEP Gd, Ed, Vd */ + nextop = F8; + GETED(0); + GETGD; + GETVD; + if(rex.w) { + tmp64u = 0; + u8 = 0; + for(int i=0; i<64; ++i) + if(ED->q[0]&(1LL<q[0]>>(u8++))&1LL)<q[0] = tmp64u; + } else { + tmp32u = 0; + u8 = 0; + for(int i=0; i<32; ++i) + if(ED->dword[0]&(1<dword[0]>>(u8++))&1)<q[0] = tmp32u; + } + break; + case 0xF6: /* MULX Gd, Vd, Ed (,RDX) */ + nextop = F8; + GETED(0); + GETGD; + GETVD; + if(rex.w) { + unsigned __int128 res = (unsigned __int128)R_RDX * ED->q[0]; + VD->q[0] = res&0xFFFFFFFFFFFFFFFFLL; + GD->q[0] = res>>64; + } else { + tmp64u = (uint64_t)R_EDX * ED->dword[0]; + VD->q[0] = tmp64u&0xFFFFFFFF; + GD->q[0] = tmp64u>>32; + } + break; + case 0xF7: /* SHRX Gd, Ed, Vd */ + nextop = F8; + GETED(0); + GETGD; + GETVD; + if(rex.w) { + u8 = VD->q[0] & 0x3f; + GD->q[0] = ED->q[0] >> u8; + } else { + u8 = VD->dword[0] & 0x1f; + GD->q[0] = ED->dword[0] >> u8; + } + break; + + default: + return 0; + } + return addr; +} diff --git a/src/emu/x64runavxf20f3a.c b/src/emu/x64runavxf20f3a.c new file mode 100644 index 00000000..dc8142db --- /dev/null +++ b/src/emu/x64runavxf20f3a.c @@ -0,0 +1,82 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "debug.h" +#include "box64stack.h" +#include "x64emu.h" +#include "x64run.h" +#include "x64emu_private.h" +#include "x64run_private.h" +#include "x64primop.h" +#include "x64trace.h" +#include "x87emu_private.h" +#include "box64context.h" +#include "my_cpuid.h" +#include "bridge.h" +#include "signals.h" +#ifdef DYNAREC +#include "custommem.h" +#include "../dynarec/native_lock.h" +#endif + +#include "modrm.h" + +#ifdef TEST_INTERPRETER +uintptr_t TestAVX_F20F3A(x64test_t *test, vex_t vex, uintptr_t addr, int *step) +#else +uintptr_t RunAVX_F20F3A(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) +#endif +{ + uint8_t opcode; + uint8_t nextop; + uint8_t tmp8u, u8; + int8_t tmp8s; + int16_t tmp16s; + uint16_t tmp16u; + int32_t tmp32s, tmp32s2; + uint32_t tmp32u, tmp32u2; + uint64_t tmp64u, tmp64u2; + int64_t tmp64s; + reg64_t *oped, *opgd, *opvd; + sse_regs_t *opex, *opgx, *opvx, eax1, eax2; + sse_regs_t *opey, *opgy, *opvy, eay1, eay2; + + +#ifdef TEST_INTERPRETER + x64emu_t *emu = test->emu; +#endif + opcode = F8; + + rex_t rex = vex.rex; + + switch(opcode) { + + case 0xF0: /* RORX Gd, Ed, Ib */ + nextop = F8; + GETED(1); + GETGD; + u8 = F8; + if(rex.w) { + u8 &= 0x3f; + GD->q[0] = (ED->q[0] << (64 - u8)) + ((ED->q[0] >> (u8)) & ((1L << (64 - u8)) - 1L)); + } else { + u8 &= 0x1f; + ED->dword[0] = (ED->dword[0] << (32 - u8)) + ((ED->dword[0] >> (u8)) & ((1 << (32 - u8)) - 1)); + if(MODREG) + ED->dword[1] = 0; + } + break; + + default: + return 0; + } + return addr; +} diff --git a/src/emu/x64runavxf30f38.c b/src/emu/x64runavxf30f38.c new file mode 100644 index 00000000..62d8513c --- /dev/null +++ b/src/emu/x64runavxf30f38.c @@ -0,0 +1,102 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "debug.h" +#include "box64stack.h" +#include "x64emu.h" +#include "x64run.h" +#include "x64emu_private.h" +#include "x64run_private.h" +#include "x64primop.h" +#include "x64trace.h" +#include "x87emu_private.h" +#include "box64context.h" +#include "my_cpuid.h" +#include "bridge.h" +#include "signals.h" +#ifdef DYNAREC +#include "custommem.h" +#include "../dynarec/native_lock.h" +#endif + +#include "modrm.h" + +#ifdef TEST_INTERPRETER +uintptr_t TestAVX_F30F38(x64test_t *test, vex_t vex, uintptr_t addr, int *step) +#else +uintptr_t RunAVX_F30F38(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) +#endif +{ + uint8_t opcode; + uint8_t nextop; + uint8_t tmp8u, u8; + int8_t tmp8s; + int16_t tmp16s; + uint16_t tmp16u; + int32_t tmp32s, tmp32s2; + uint32_t tmp32u, tmp32u2; + uint64_t tmp64u, tmp64u2; + int64_t tmp64s; + reg64_t *oped, *opgd, *opvd; + sse_regs_t *opex, *opgx, *opvx, eax1, eax2; + sse_regs_t *opey, *opgy, *opvy, eay1, eay2; + + +#ifdef TEST_INTERPRETER + x64emu_t *emu = test->emu; +#endif + opcode = F8; + + rex_t rex = vex.rex; + + switch(opcode) { + + case 0xF5: /* PEXT Gd, Ed, Vd */ + nextop = F8; + GETED(0); + GETGD; + GETVD; + if(rex.w) { + tmp64u = 0; + u8 = 0; + for(int i=0; i<64; ++i) + if(ED->q[0]&(1LL<q[0]>>i)&1LL)<<(u8++); + GD->q[0] = tmp64u; + } else { + tmp32u = 0; + u8 = 0; + for(int i=0; i<32; ++i) + if(ED->dword[0]&(1<dword[0]>>i)&1)<<(u8++); + GD->q[0] = tmp32u; + } + break; + case 0xF7: /* SARX Gd, Ed, Vd */ + nextop = F8; + GETED(0); + GETGD; + GETVD; + if(rex.w) { + u8 = VD->q[0] & 0x3f; + GD->sq[0] = ED->sq[0] >> u8; + } else { + u8 = VD->dword[0] & 0x1f; + GD->sdword[0] = ED->sdword[0] >> u8; + GD->dword[1] = 0; + } + break; + + default: + return 0; + } + return addr; +} diff --git a/src/emu/x64runavxf30f3a.c b/src/emu/x64runavxf30f3a.c new file mode 100644 index 00000000..c5dc9a17 --- /dev/null +++ b/src/emu/x64runavxf30f3a.c @@ -0,0 +1,66 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "debug.h" +#include "box64stack.h" +#include "x64emu.h" +#include "x64run.h" +#include "x64emu_private.h" +#include "x64run_private.h" +#include "x64primop.h" +#include "x64trace.h" +#include "x87emu_private.h" +#include "box64context.h" +#include "my_cpuid.h" +#include "bridge.h" +#include "signals.h" +#ifdef DYNAREC +#include "custommem.h" +#include "../dynarec/native_lock.h" +#endif + +#include "modrm.h" + +#ifdef TEST_INTERPRETER +uintptr_t TestAVX_F30F3A(x64test_t *test, vex_t vex, uintptr_t addr, int *step) +#else +uintptr_t RunAVX_F30F3A(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) +#endif +{ + uint8_t opcode; + uint8_t nextop; + uint8_t tmp8u, u8; + int8_t tmp8s; + int16_t tmp16s; + uint16_t tmp16u; + int32_t tmp32s, tmp32s2; + uint32_t tmp32u, tmp32u2; + uint64_t tmp64u, tmp64u2; + int64_t tmp64s; + reg64_t *oped, *opgd, *opvd; + sse_regs_t *opex, *opgx, *opvx, eax1, eax2; + sse_regs_t *opey, *opgy, *opvy, eay1, eay2; + + +#ifdef TEST_INTERPRETER + x64emu_t *emu = test->emu; +#endif + opcode = F8; + + rex_t rex = vex.rex; + + switch(opcode) { + + default: + return 0; + } + return addr; +} diff --git a/src/emu/x64runf30f.c b/src/emu/x64runf30f.c index 4c79bf8f..1c650469 100644 --- a/src/emu/x64runf30f.c +++ b/src/emu/x64runf30f.c @@ -35,7 +35,7 @@ uintptr_t RunF30F(x64emu_t *emu, rex_t rex, uintptr_t addr) uint8_t tmp8u; uint32_t tmp32u; int64_t tmp64s; - uint64_t tmp64u; + uint64_t tmp64u, tmp64u2; reg64_t *oped, *opgd; sse_regs_t *opex, *opgx, eax1; mmx87_regs_t *opem; @@ -171,6 +171,41 @@ uintptr_t RunF30F(x64emu_t *emu, rex_t rex, uintptr_t addr) GD->dword[1] = 0; } break; + + case 0x38: /* MAP 0F38 */ + opcode = F8; + switch(opcode) { + + case 0xF6: /* ADOX Gd, Rd */ + nextop = F8; + GETED(0); + GETGD; + CHECK_FLAGS(emu); + if(rex.w) { + if (ACCESS_FLAG(F_OF)) { + tmp64u = 1 + (GD->q[0] & 0xFFFFFFFF) + (ED->q[0] & 0xFFFFFFFF); + tmp64u2 = 1 + GD->q[0] + ED->q[0]; + } + else { + tmp64u = (GD->q[0] & 0xFFFFFFFF) + (ED->q[0] & 0xFFFFFFFF); + tmp64u2 = GD->q[0] + ED->q[0]; + } + tmp64u = (tmp64u >> 32) + (GD->q[0] >> 32) + (ED->q[0] >> 32); + CONDITIONAL_SET_FLAG(tmp64u & 0x100000000L, F_OF); + GD->q[0] = tmp64u2; + } else { + if (ACCESS_FLAG(F_OF)) + GD->q[0] = 1LL + GD->dword[0] + ED->dword[0]; + else + GD->q[0] = (uint64_t)GD->dword[0] + ED->dword[0]; + CONDITIONAL_SET_FLAG(GD->q[0] & 0x100000000LL, F_OF); + } + break; + + default: + return 0; + } + break; case 0x51: /* SQRTSS Gx, Ex */ nextop = F8; diff --git a/src/librarian/library.c b/src/librarian/library.c index 14a1334a..a4f31965 100644 --- a/src/librarian/library.c +++ b/src/librarian/library.c @@ -405,7 +405,7 @@ static const char* essential_libs[] = { "libxcb-image.so.0", "libxcb-keysyms.so.1", "libxcb-xtest.so.0", "libxcb-glx.so.0", "libxcb-dri2.so.0", "libxcb-dri3.so.0", "libXtst.so.6", "libXt.so.6", "libXcomposite.so.1", "libXdamage.so.1", "libXmu.so.6", "libxkbcommon.so.0", "libxkbcommon-x11.so.0", "libpulse-simple.so.0", "libpulse.so.0", "libvulkan.so.1", "libvulkan.so", - "ld-linux-x86-64.so.2", "crashhandler.so", "libtcmalloc_minimal.so.0", "libtcmalloc_minimal.so.4" + "ld-linux-x86-64.so.2", "crashhandler.so", "libtcmalloc_minimal.so.0", "libtcmalloc_minimal.so.4", "libanl.so.1" }; static int isEssentialLib(const char* name) { for (unsigned int i=0; i