about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2024-05-26 12:57:59 +0200
committerptitSeb <sebastien.chev@gmail.com>2024-05-26 12:57:59 +0200
commit95b516127ae4b851aa21647a55aef0cef976a31f (patch)
tree6844beca6ee3d850ec7503a926bc2d0164303b10 /src
parentda7474b1de99c3952f9b1c67275e7a5bf44e7121 (diff)
downloadbox64-95b516127ae4b851aa21647a55aef0cef976a31f.tar.gz
box64-95b516127ae4b851aa21647a55aef0cef976a31f.zip
[INTERPRETER] Added avx (F3 0F) 6F and (66 0F) 70
Diffstat (limited to 'src')
-rw-r--r--src/emu/modrm.h8
-rw-r--r--src/emu/x64emu_private.h2
-rw-r--r--src/emu/x64run_private.c6
-rw-r--r--src/emu/x64run_private.h7
-rw-r--r--src/emu/x64runavx.c24
-rw-r--r--src/emu/x64runavx0f.c72
-rw-r--r--src/emu/x64runavx660f.c83
-rw-r--r--src/emu/x64runavxf30f.c79
8 files changed, 263 insertions, 18 deletions
diff --git a/src/emu/modrm.h b/src/emu/modrm.h
index 3e49b36b..7eb43555 100644
--- a/src/emu/modrm.h
+++ b/src/emu/modrm.h
@@ -1,3 +1,5 @@
+#include <stddef.h>

+

 #define F8      *(uint8_t*)(addr++)

 #define F8S     *(int8_t*)(addr++)

 #define F16     *(uint16_t*)(addr+=2, addr-2)

@@ -41,6 +43,8 @@
 #define GETEX32(D)          opex=TestEx32O(test, &addr, rex, nextop, D, 0)

 #define GETEX_OFFS(D, O)    opex=TestExO(test, &addr, rex, nextop, D, O)

 #define GETGX               opgx=GetGx(test->emu, &addr, rex, nextop)

+#define GETGY               opgy=GetGy(emu, &addr, rex, nextop)

+#define GETEY               opey=(opex>=&emu->xmm[0] && opex<=&emu->xmm[15])?((sse_regs_t*)((uintptr_t)opex+offsetof(x64emu_t, ymm)-offsetof(x64emu_t, xmm))):((sse_regs_t*)((uintptr_t)opex+16))

 #define GETEM(D)            opem=TestEm(test, &addr, rex, nextop, D)

 #define GETEM32(D)          opem=TestEm32O(test, &addr, rex, nextop, D, 0)

 #define GETGM               opgm=GetGm(test->emu, &addr, rex, nextop)

@@ -67,6 +71,8 @@
 #define GETEX32(D)          opex=GetEx32O(emu, &addr, rex, nextop, D, 0)

 #define GETEX_OFFS(D, O)    opex=GetExO(emu, &addr, rex, nextop, D, O)

 #define GETGX               opgx=GetGx(emu, &addr, rex, nextop)

+#define GETGY               opgy=GetGy(emu, &addr, rex, nextop)

+#define GETEY               opey=(opex>=&emu->xmm[0] && opex<=&emu->xmm[15])?((sse_regs_t*)((uintptr_t)opex+offsetof(x64emu_t, ymm)-offsetof(x64emu_t, xmm))):((sse_regs_t*)((uintptr_t)opex+16))

 #define GETEM(D)            opem=GetEm(emu, &addr, rex, nextop, D)

 #define GETEM32(D)          opem=GetEm32O(emu, &addr, rex, nextop, D, 0)

 #define GETGM               opgm=GetGm(emu, &addr, rex, nextop)

@@ -79,6 +85,8 @@
 #define GW  opgd

 #define EX  opex

 #define GX  opgx

+#define EY  opey

+#define GY  opgy

 #define EM  opem

 #define GM  opgm

 #define FAKEED(D)           GetEd(emu, &addr, rex, nextop, D)

diff --git a/src/emu/x64emu_private.h b/src/emu/x64emu_private.h
index b7ce3308..1d8352fd 100644
--- a/src/emu/x64emu_private.h
+++ b/src/emu/x64emu_private.h
@@ -38,7 +38,7 @@ typedef struct x64test_s {
     int         test;
     int         clean;
     int         notest;
-    uint8_t     mem[16];
+    uint8_t     mem[32];
 } x64test_t;
 
 typedef struct emu_flags_s {
diff --git a/src/emu/x64run_private.c b/src/emu/x64run_private.c
index 06f20118..577d4ce5 100644
--- a/src/emu/x64run_private.c
+++ b/src/emu/x64run_private.c
@@ -2002,3 +2002,9 @@ sse_regs_t* GetGx(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v)
     uint8_t m = (v&0x38)>>3;
     return &emu->xmm[(m&7)+(rex.r<<3)];
 }
+
+sse_regs_t* GetGy(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v)
+{
+    uint8_t m = (v&0x38)>>3;
+    return &emu->ymm[(m&7)+(rex.r<<3)];
+}
diff --git a/src/emu/x64run_private.h b/src/emu/x64run_private.h
index 659b76bf..d739506b 100644
--- a/src/emu/x64run_private.h
+++ b/src/emu/x64run_private.h
@@ -138,6 +138,7 @@ mmx87_regs_t* GetGm(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v);
 mmx87_regs_t* GetEm32O(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset);
 mmx87_regs_t* TestEm32O(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset);
 sse_regs_t* GetGx(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v);
+sse_regs_t* GetGy(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v);
 
 void UpdateFlags(x64emu_t *emu);
 
@@ -172,6 +173,9 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr);
 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_660F(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 Test0F(x64test_t *test, rex_t rex, uintptr_t addr, int *step);
@@ -202,6 +206,9 @@ 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_F3OF(x64test_t *test, vex_t vex, uintptr_t addr, int *step);
 
 
 void x64Syscall(x64emu_t *emu);
diff --git a/src/emu/x64runavx.c b/src/emu/x64runavx.c
index 78515b25..3afd2b66 100644
--- a/src/emu/x64runavx.c
+++ b/src/emu/x64runavx.c
@@ -51,22 +51,12 @@ uintptr_t RunAVX(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
 #ifdef TEST_INTERPRETER
     x64emu_t *emu = test->emu;
 #endif
-    opcode = F8;
+    if( (vex.m==VEX_M_0F) && (vex.p==VEX_P_NONE))
+        return RunAVX_0F(emu, vex, addr, step);
+    if( (vex.m==VEX_M_0F) && (vex.p==VEX_P_66))
+        return RunAVX_660F(emu, vex, addr, step);
+    if( (vex.m==VEX_M_0F) && (vex.p==VEX_P_F3))
+        return RunAVX_F30F(emu, vex, addr, step);
 
-    switch(opcode) {
-
-        case 0x77:
-            if(!vex.l && (vex.m==VEX_M_0F) && (vex.p==VEX_P_NONE)) {
-                if(vex.v!=0) {
-                    emit_signal(emu, SIGILL, (void*)R_RIP, 0);
-                } else {
-                    memset(emu->ymm, 0, sizeof(sse_regs_t)*(vex.rex.is32bits)?16:8);
-                }
-            } else
-                return 0;
-            break;
-        default:
-            return 0;
-    }
-    return addr;
+    return 0;
 }
diff --git a/src/emu/x64runavx0f.c b/src/emu/x64runavx0f.c
new file mode 100644
index 00000000..c2f76348
--- /dev/null
+++ b/src/emu/x64runavx0f.c
@@ -0,0 +1,72 @@
+#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"
+
+#ifdef TEST_INTERPRETER
+uintptr_t TestAVX_0F(x64test_t *test, vex_t vex, uintptr_t addr, int *step)
+#else
+uintptr_t RunAVX_0F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
+#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;
+    sse_regs_t *opex, *opgx, eax1;
+    mmx87_regs_t *opem, *opgm, eam1;
+
+#ifdef TEST_INTERPRETER
+    x64emu_t *emu = test->emu;
+#endif
+    opcode = F8;
+
+    switch(opcode) {
+
+        case 0x77:
+            if(!vex.l) {    // VZEROUPPER
+                if(vex.v!=0) {
+                    emit_signal(emu, SIGILL, (void*)R_RIP, 0);
+                } else {
+                    memset(emu->ymm, 0, sizeof(sse_regs_t)*(vex.rex.is32bits)?16:8);
+                }
+            } else
+                return 0;
+            break;
+        default:
+            return 0;
+    }
+    return addr;
+}
diff --git a/src/emu/x64runavx660f.c b/src/emu/x64runavx660f.c
new file mode 100644
index 00000000..f9f7acf4
--- /dev/null
+++ b/src/emu/x64runavx660f.c
@@ -0,0 +1,83 @@
+#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"
+
+#ifdef TEST_INTERPRETER
+uintptr_t TestAVX_660F(x64test_t *test, vex_t vex, uintptr_t addr, int *step)
+#else
+uintptr_t RunAVX_660F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
+#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;
+    sse_regs_t *opex, *opgx, eax1;
+    sse_regs_t *opey, *opgy, eay1;
+
+
+#ifdef TEST_INTERPRETER
+    x64emu_t *emu = test->emu;
+#endif
+    opcode = F8;
+
+    rex_t rex = vex.rex;
+
+    switch(opcode) {
+
+        case 0x70:  /* PSHUFD Gx,Ex,Ib */
+            nextop = F8;
+            GETEX(1);
+            GETGX;
+            tmp8u = F8;
+            GETGY;
+            if(vex.l) {
+                GETEY;
+                if(EY==GY) {eay1 = *GY; EY = &eay1;}   // copy is needed
+                for (int i=0; i<4; ++i)
+                    GY->ud[4+i] = EY->ud[4+(tmp8u>>(i*2))&3];
+            } else 
+                memset(GY, 0, 16);
+            if(EX==GX) {eax1 = *GX; EX = &eax1;}   // copy is needed
+            for (int i=0; i<4; ++i)
+                GX->ud[i] = EX->ud[(tmp8u>>(i*2))&3];
+            break;
+
+        default:
+            return 0;
+    }
+    return addr;
+}
diff --git a/src/emu/x64runavxf30f.c b/src/emu/x64runavxf30f.c
new file mode 100644
index 00000000..8e3b964d
--- /dev/null
+++ b/src/emu/x64runavxf30f.c
@@ -0,0 +1,79 @@
+#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"
+
+#ifdef TEST_INTERPRETER
+uintptr_t TestAVX_F30F(x64test_t *test, vex_t vex, uintptr_t addr, int *step)
+#else
+uintptr_t RunAVX_F30F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
+#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;
+    sse_regs_t *opex, *opgx, eax1;
+    sse_regs_t *opey, *opgy, eay1;
+
+
+#ifdef TEST_INTERPRETER
+    x64emu_t *emu = test->emu;
+#endif
+    opcode = F8;
+
+    rex_t rex = vex.rex;
+
+    switch(opcode) {
+
+        case 0x6F:  // VMOVDQU
+            nextop = F8;
+            GETEX(0);
+            GETGX;
+            memcpy(GX, EX, 16);    // unaligned...
+            if(vex.l) {
+                GETGY;
+                GETEY;
+                if(MODREG)
+                    memcpy(GY, EY, 16);
+                else
+                    memset(GY, 0, 16);
+            }
+            break;
+        default:
+            return 0;
+    }
+    return addr;
+}