diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/emu/modrm.h | 2 | ||||
| -rw-r--r-- | src/emu/x64run.c | 12 | ||||
| -rw-r--r-- | src/emu/x64run660f.c | 28 | ||||
| -rw-r--r-- | src/emu/x64run67.c | 71 | ||||
| -rw-r--r-- | src/emu/x64run67660f.c | 14 | ||||
| -rw-r--r-- | src/emu/x64run67avx.c | 106 | ||||
| -rw-r--r-- | src/emu/x64run_private.h | 25 | ||||
| -rw-r--r-- | src/emu/x64runavx.c | 37 | ||||
| -rw-r--r-- | src/emu/x64runavx0f38.c | 205 | ||||
| -rw-r--r-- | src/emu/x64runavx660f38.c | 16 | ||||
| -rw-r--r-- | src/emu/x64runavxf20f38.c | 116 | ||||
| -rw-r--r-- | src/emu/x64runavxf20f3a.c | 82 | ||||
| -rw-r--r-- | src/emu/x64runavxf30f38.c | 102 | ||||
| -rw-r--r-- | src/emu/x64runavxf30f3a.c | 66 | ||||
| -rw-r--r-- | src/emu/x64runf30f.c | 37 | ||||
| -rw-r--r-- | src/librarian/library.c | 2 | ||||
| -rw-r--r-- | src/tools/my_cpuid.c | 5 | ||||
| -rw-r--r-- | src/wrapped/wrappedlibc.c | 2 |
18 files changed, 905 insertions, 23 deletions
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 <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <math.h> +#include <fenv.h> +#include <string.h> +#include <signal.h> +#include <sys/types.h> +#include <unistd.h> + +#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<<vex.l, avx_prefix_string(vex.p), avx_map_string(vex.m), opcode); + + return addr; +} diff --git a/src/emu/x64run_private.h b/src/emu/x64run_private.h index d33d39ae..14350db8 100644 --- a/src/emu/x64run_private.h +++ b/src/emu/x64run_private.h @@ -156,6 +156,7 @@ uintptr_t Run66D9(x64emu_t *emu, rex_t rex, uintptr_t addr); uintptr_t Run66DD(x64emu_t *emu, rex_t rex, uintptr_t addr); uintptr_t Run66F0(x64emu_t *emu, rex_t rex, uintptr_t addr); uintptr_t Run67(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr); +uintptr_t Run67AVX(x64emu_t *emu, vex_t vex, uintptr_t addr); uintptr_t Run67_32(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr); uintptr_t Run6764_32(x64emu_t *emu, rex_t rex, int rep, int seg, uintptr_t addr); uintptr_t Run670F(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr); @@ -174,11 +175,16 @@ uintptr_t RunF20F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step); uintptr_t RunF30F(x64emu_t *emu, rex_t rex, uintptr_t addr); uintptr_t RunAVX(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step); uintptr_t RunAVX_0F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step); +uintptr_t RunAVX_0F38(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step); uintptr_t RunAVX_660F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step); uintptr_t RunAVX_F20F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step); uintptr_t RunAVX_F30F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step); uintptr_t RunAVX_660F38(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step); uintptr_t RunAVX_660F3A(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step); +uintptr_t RunAVX_F20F38(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step); +uintptr_t RunAVX_F20F3A(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step); +uintptr_t RunAVX_F30F38(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step); +uintptr_t RunAVX_F30F3A(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step); uintptr_t Test0F(x64test_t *test, rex_t rex, uintptr_t addr, int *step); uintptr_t Test64(x64test_t *test, rex_t rex, int seg, uintptr_t addr); @@ -191,6 +197,7 @@ uintptr_t Test66D9(x64test_t *test, rex_t rex, uintptr_t addr); uintptr_t Test66DD(x64test_t *test, rex_t rex, uintptr_t addr); uintptr_t Test66F0(x64test_t *test, rex_t rex, uintptr_t addr); uintptr_t Test67(x64test_t *test, rex_t rex, int rep, uintptr_t addr); +uintptr_t Test67AVX(x64test_t *test, vex_t vex, uintptr_t addr); uintptr_t Test67_32(x64test_t *test, rex_t rex, int rep, uintptr_t addr); uintptr_t Test6764_32(x64test_t *test, rex_t rex, int rep, int seg, uintptr_t addr); uintptr_t Test670F(x64test_t *test, rex_t rex, int rep, uintptr_t addr); @@ -208,13 +215,17 @@ uintptr_t TestF0(x64test_t *test, rex_t rex, uintptr_t addr); uintptr_t TestF20F(x64test_t *test, rex_t rex, uintptr_t addr, int *step); uintptr_t TestF30F(x64test_t *test, rex_t rex, uintptr_t addr); uintptr_t TestAVX(x64test_t *test, vex_t vex, uintptr_t addr, int *step); -uintptr_t TestAVX_OF(x64test_t *test, vex_t vex, uintptr_t addr, int *step); -uintptr_t TestAVX_66OF(x64test_t *test, vex_t vex, uintptr_t addr, int *step); -uintptr_t TestAVX_F2OF(x64test_t *test, vex_t vex, uintptr_t addr, int *step); -uintptr_t TestAVX_F3OF(x64test_t *test, vex_t vex, uintptr_t addr, int *step); -uintptr_t TestAVX_F3OF38(x64test_t *test, vex_t vex, uintptr_t addr, int *step); -uintptr_t TestAVX_F3OF3A(x64test_t *test, vex_t vex, uintptr_t addr, int *step); - +uintptr_t TestAVX_0F(x64test_t *test, vex_t vex, uintptr_t addr, int *step); +uintptr_t TestAVX_0F38(x64test_t *test, vex_t vex, uintptr_t addr, int *step); +uintptr_t TestAVX_660F(x64test_t *test, vex_t vex, uintptr_t addr, int *step); +uintptr_t TestAVX_F20F(x64test_t *test, vex_t vex, uintptr_t addr, int *step); +uintptr_t TestAVX_F30F(x64test_t *test, vex_t vex, uintptr_t addr, int *step); +uintptr_t TestAVX_660F38(x64test_t *test, vex_t vex, uintptr_t addr, int *step); +uintptr_t TestAVX_660F3A(x64test_t *test, vex_t vex, uintptr_t addr, int *step); +uintptr_t TestAVX_F20F38(x64test_t *test, vex_t vex, uintptr_t addr, int *step); +uintptr_t TestAVX_F20F3A(x64test_t *test, vex_t vex, uintptr_t addr, int *step); +uintptr_t TestAVX_F30F38(x64test_t *test, vex_t vex, uintptr_t addr, int *step); +uintptr_t TestAVX_F30F3A(x64test_t *test, vex_t vex, uintptr_t addr, int *step); void x64Syscall(x64emu_t *emu); void x64Int3(x64emu_t* emu, uintptr_t* addr); diff --git a/src/emu/x64runavx.c b/src/emu/x64runavx.c index 6f249498..a4e3fc35 100644 --- a/src/emu/x64runavx.c +++ b/src/emu/x64runavx.c @@ -58,11 +58,35 @@ uintptr_t RunAVX(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) #endif { #ifdef TEST_INTERPRETER - x64emu_t *emu = test->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<<vex.l, avx_prefix_string(vex.p), avx_map_string(vex.m), opcode); +#endif return addr; } diff --git a/src/emu/x64runavx0f38.c b/src/emu/x64runavx0f38.c new file mode 100644 index 00000000..995c57f7 --- /dev/null +++ b/src/emu/x64runavx0f38.c @@ -0,0 +1,205 @@ +#define _GNU_SOURCE +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <math.h> +#include <fenv.h> +#include <string.h> +#include <signal.h> +#include <sys/types.h> +#include <unistd.h> + +#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<<tmp32u)); + CONDITIONAL_SET_FLAG((tmp32u>63), F_CF); + } else { + GD->q[0] = ED->dword[0]; + if(tmp32u<32) GD->dword[0] &= ~((-1<<tmp32u)); + CONDITIONAL_SET_FLAG((tmp32u>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<<tmp32u2)-1LL); + else + tmp64u = -1LL; + if(tmp32u<0x40) + GD->q[0] = (ED->q[0]>>tmp32u)&tmp64u; + else + GD->q[0] = 0; + } else { + if(tmp32u2<0x20) + tmp64u = ((1LL<<tmp32u2)-1LL); + else + tmp64u = -1LL; + if(tmp32u<0x20) + GD->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 <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <math.h> +#include <fenv.h> +#include <string.h> +#include <signal.h> +#include <sys/types.h> +#include <unistd.h> + +#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<<i)) + tmp64u |= ((VD->q[0]>>(u8++))&1LL)<<i; + GD->q[0] = tmp64u; + } else { + tmp32u = 0; + u8 = 0; + for(int i=0; i<32; ++i) + if(ED->dword[0]&(1<<i)) + tmp32u |= ((VD->dword[0]>>(u8++))&1)<<i; + GD->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 <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <math.h> +#include <fenv.h> +#include <string.h> +#include <signal.h> +#include <sys/types.h> +#include <unistd.h> + +#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 <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <math.h> +#include <fenv.h> +#include <string.h> +#include <signal.h> +#include <sys/types.h> +#include <unistd.h> + +#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<<i)) + tmp64u |= ((VD->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<<i)) + tmp32u |= ((VD->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 <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <math.h> +#include <fenv.h> +#include <string.h> +#include <signal.h> +#include <sys/types.h> +#include <unistd.h> + +#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<sizeof(essential_libs)/sizeof(essential_libs[0]); ++i) diff --git a/src/tools/my_cpuid.c b/src/tools/my_cpuid.c index 7c54a379..a42915fd 100644 --- a/src/tools/my_cpuid.c +++ b/src/tools/my_cpuid.c @@ -322,10 +322,11 @@ void my_cpuid(x64emu_t* emu, uint32_t tmp32u) if(R_ECX==0) { R_EAX = 0; R_EBX = - //1<<3 | // BMI1 + box64_avx<<3 | // BMI1 box64_avx2<<5 | //AVX2 - //1<<8 | //BMI2 + box64_avx2<<8 | //BMI2 box64_avx2<<9 | //VAES + box64_avx2<<19 | //ADX 1<<29| // SHA extension 0; } else {R_EAX = R_ECX = R_EBX = R_EDX = 0;} diff --git a/src/wrapped/wrappedlibc.c b/src/wrapped/wrappedlibc.c index e547d523..6b5312b3 100644 --- a/src/wrapped/wrappedlibc.c +++ b/src/wrapped/wrappedlibc.c @@ -1639,7 +1639,7 @@ void CreateCPUInfoFile(int fd) P; sprintf(buff, "bogomips\t: %g\n", getBogoMips()); P; - sprintf(buff, "flags\t\t: fpu cx8 sep ht cmov clflush mmx sse sse2 syscall tsc lahf_lm ssse3 ht tm lm fxsr cpuid pclmulqdq cx16 aes movbe pni sse4_1%s%s lzcnt popcnt%s%s\n", box64_sse42?" sse4_2":"", box64_avx?" avx":"", box64_avx2?" avx2":"", box64_avx2?" vaes":""); + sprintf(buff, "flags\t\t: fpu cx8 sep ht cmov clflush mmx sse sse2 syscall tsc lahf_lm ssse3 ht tm lm fxsr cpuid pclmulqdq cx16 aes movbe pni sse4_1%s%s lzcnt popcnt%s%s%s%s\n", box64_sse42?" sse4_2":"", box64_avx?" avx":"", box64_avx?" bmi1":"", box64_avx2?" avx2":"", box64_avx?" bmi2":"", box64_avx2?" vaes":""); P; sprintf(buff, "address sizes\t: 48 bits physical, 48 bits virtual\n"); P; |