about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2024-05-31 15:59:11 +0200
committerptitSeb <sebastien.chev@gmail.com>2024-05-31 15:59:11 +0200
commitdde85b761b43c5fecb89177b09d6e596e6338a0c (patch)
treeb8f43a0fda57ccbbc2589fe42224445b6e6283ab
parent34809e48d81db027b8f91d2167d6ea4db5a88e69 (diff)
downloadbox64-dde85b761b43c5fecb89177b09d6e596e6338a0c.tar.gz
box64-dde85b761b43c5fecb89177b09d6e596e6338a0c.zip
[INTERPRETER] Added BMI1, BMI2 and ADX extensions
-rw-r--r--CMakeLists.txt6
-rw-r--r--src/emu/modrm.h2
-rw-r--r--src/emu/x64run.c12
-rw-r--r--src/emu/x64run660f.c28
-rw-r--r--src/emu/x64run67.c71
-rw-r--r--src/emu/x64run67660f.c14
-rw-r--r--src/emu/x64run67avx.c106
-rw-r--r--src/emu/x64run_private.h25
-rw-r--r--src/emu/x64runavx.c37
-rw-r--r--src/emu/x64runavx0f38.c205
-rw-r--r--src/emu/x64runavx660f38.c16
-rw-r--r--src/emu/x64runavxf20f38.c116
-rw-r--r--src/emu/x64runavxf20f3a.c82
-rw-r--r--src/emu/x64runavxf30f38.c102
-rw-r--r--src/emu/x64runavxf30f3a.c66
-rw-r--r--src/emu/x64runf30f.c37
-rw-r--r--src/librarian/library.c2
-rw-r--r--src/tools/my_cpuid.c5
-rw-r--r--src/wrapped/wrappedlibc.c2
19 files changed, 911 insertions, 23 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f0aa4c21..ed4c60e9 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -379,6 +379,7 @@ set(INTERPRETER
     "${BOX64_ROOT}/src/emu/x64run66dd.c"
     "${BOX64_ROOT}/src/emu/x64run66f0.c"
     "${BOX64_ROOT}/src/emu/x64run67.c"
+    "${BOX64_ROOT}/src/emu/x64run67avx.c"
     "${BOX64_ROOT}/src/emu/x64run67_32.c"
     "${BOX64_ROOT}/src/emu/x64run6764_32.c"
     "${BOX64_ROOT}/src/emu/x64run670f.c"
@@ -397,11 +398,16 @@ set(INTERPRETER
     "${BOX64_ROOT}/src/emu/x64runf30f.c"
     "${BOX64_ROOT}/src/emu/x64runavx.c"
     "${BOX64_ROOT}/src/emu/x64runavx0f.c"
+    "${BOX64_ROOT}/src/emu/x64runavx0f38.c"
     "${BOX64_ROOT}/src/emu/x64runavx660f.c"
     "${BOX64_ROOT}/src/emu/x64runavxf20f.c"
     "${BOX64_ROOT}/src/emu/x64runavxf30f.c"
     "${BOX64_ROOT}/src/emu/x64runavx660f38.c"
     "${BOX64_ROOT}/src/emu/x64runavx660f3a.c"
+    "${BOX64_ROOT}/src/emu/x64runavxf20f38.c"
+    "${BOX64_ROOT}/src/emu/x64runavxf30f38.c"
+    "${BOX64_ROOT}/src/emu/x64runavxf20f3a.c"
+    "${BOX64_ROOT}/src/emu/x64runavxf30f3a.c"
 )
 
 if(STATICBUILD)
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;