about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2024-06-01 13:33:20 +0200
committerptitSeb <sebastien.chev@gmail.com>2024-06-01 13:33:20 +0200
commit0336f6a9872d5c95959a8566d5e0391890761794 (patch)
treef089a012956eac892c4448a20560f8a5b24b01cf /src
parent6d68975ba51bc2db7cff709c596487527cd115fd (diff)
downloadbox64-0336f6a9872d5c95959a8566d5e0391890761794.tar.gz
box64-0336f6a9872d5c95959a8566d5e0391890761794.zip
[ARM64_DYNAREC] Added a few 67 prefixed opcodes
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/arm64/dynarec_arm64_67.c61
-rw-r--r--src/dynarec/arm64/dynarec_arm64_67_avx.c112
-rw-r--r--src/dynarec/arm64/dynarec_arm64_helper.h2
-rw-r--r--src/emu/x64run67.c6
4 files changed, 181 insertions, 0 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_67.c b/src/dynarec/arm64/dynarec_arm64_67.c
index 6d8c336e..efe989fb 100644
--- a/src/dynarec/arm64/dynarec_arm64_67.c
+++ b/src/dynarec/arm64/dynarec_arm64_67.c
@@ -1093,6 +1093,53 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             }

             break;

 

+        case 0xC4:

+            nextop = F8;

+            if(rex.is32bits && !(MODREG)) {

+                DEFAULT;

+            } else {

+                if(rex.is32bits) {

+                    DEFAULT;

+                    return addr;

+                }

+                vex_t vex = {0};

+                vex.rex = rex;

+                u8 = nextop;

+                vex.m = u8&0b00011111;

+                vex.rex.b = (u8&0b00100000)?0:1;

+                vex.rex.x = (u8&0b01000000)?0:1;

+                vex.rex.r = (u8&0b10000000)?0:1;

+                u8 = F8;

+                vex.p = u8&0b00000011;

+                vex.l = (u8>>2)&1;

+                vex.v = ((~u8)>>3)&0b1111;

+                vex.rex.w = (u8>>7)&1;

+                addr = dynarec64_67_AVX(dyn, addr, ip, ninst, vex, ok, need_epilog);

+            }

+            break;

+        case 0xC5:

+            nextop = F8;

+            if(rex.is32bits && !(MODREG)) {

+                DEFAULT;

+            } else {

+                if(rex.is32bits) {

+                    DEFAULT;

+                    return addr;

+                }

+                vex_t vex = {0};

+                vex.rex = rex;

+                u8 = nextop;

+                vex.p = u8&0b00000011;

+                vex.l = (u8>>2)&1;

+                vex.v = ((~u8)>>3)&0b1111;

+                vex.rex.r = (u8&0b10000000)?0:1;

+                vex.rex.b = 0;

+                vex.rex.x = 0;

+                vex.rex.w = 0;

+                vex.m = VEX_M_0F;

+                addr = dynarec64_67_AVX(dyn, addr, ip, ninst, vex, ok, need_epilog);

+            }

+            break;

         case 0xC6:

             INST_NAME("MOV Eb, Ib");

             nextop=F8;

@@ -1344,6 +1391,20 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
         case 0xFF:

             nextop = F8;

             switch((nextop>>3)&7) {

+                case 0: // INC Ed

+                    INST_NAME("INC Ed");

+                    SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);

+                    GETED32(0);

+                    emit_inc32(dyn, ninst, rex, ed, x3, x4);

+                    WBACK;

+                    break;

+                case 1: //DEC Ed

+                    INST_NAME("DEC Ed");

+                    SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);

+                    GETED32(0);

+                    emit_dec32(dyn, ninst, rex, ed, x3, x4);

+                    WBACK;

+                    break;

                 case 2: // CALL Ed

                     INST_NAME("CALL Ed");

                     PASS2IF((box64_dynarec_safeflags>1) ||

diff --git a/src/dynarec/arm64/dynarec_arm64_67_avx.c b/src/dynarec/arm64/dynarec_arm64_67_avx.c
new file mode 100644
index 00000000..1e1e5926
--- /dev/null
+++ b/src/dynarec/arm64/dynarec_arm64_67_avx.c
@@ -0,0 +1,112 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <errno.h>
+
+#include "debug.h"
+#include "box64context.h"
+#include "dynarec.h"
+#include "emu/x64emu_private.h"
+#include "emu/x64run_private.h"
+#include "x64run.h"
+#include "x64emu.h"
+#include "box64stack.h"
+#include "callback.h"
+#include "emu/x64run_private.h"
+#include "x64trace.h"
+#include "dynarec_native.h"
+
+#include "arm64_printer.h"
+#include "dynarec_arm64_private.h"
+#include "dynarec_arm64_functions.h"
+#include "dynarec_arm64_helper.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 "??";
+    }
+}
+
+uintptr_t dynarec64_67_AVX(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, vex_t vex, int* ok, int* need_epilog)
+{
+    (void)ip; (void)need_epilog;
+    uint8_t opcode = F8;
+    uint8_t nextop, u8;
+    uint8_t gd, ed, vd;
+    uint8_t wback, wb1, wb2;
+    uint8_t eb1, eb2, gb1, gb2;
+    int32_t i32, i32_;
+    int cacheupd = 0;
+    int v0, v1, v2;
+    int q0, q1, q2;
+    int d0, d1, d2;
+    int s0;
+    uint64_t tmp64u;
+    int64_t j64;
+    int64_t fixedaddress;
+    int unscaled;
+    MAYUSE(wb1);
+    MAYUSE(wb2);
+    MAYUSE(eb1);
+    MAYUSE(eb2);
+    MAYUSE(gb1);
+    MAYUSE(gb2);
+    MAYUSE(q0);
+    MAYUSE(q1);
+    MAYUSE(d0);
+    MAYUSE(d1);
+    MAYUSE(s0);
+    MAYUSE(j64);
+    MAYUSE(cacheupd);
+
+    rex_t rex = vex.rex;
+
+    if( (vex.m==VEX_M_0F38) && (vex.p==VEX_P_F2)) {
+        switch(opcode) {
+
+            case 0xF6:
+                INST_NAME("MULX Gd, Vd, Ed (,RDX)");
+                nextop = F8;
+                GETGD;
+                GETED32(0);
+                GETVD;
+                if(rex.w) {
+                    // 64bits mul
+                    UMULH(x3, xRDX, ed);
+                    MULx(vd, xRDX, ed);
+                    MOVx_REG(gd, x3);
+                } else {
+                    // 32bits mul
+                    UMULL(x3, xRDX, ed);
+                    MOVw_REG(vd, x3);
+                    LSRx(gd, x3, 32);
+                }
+                break;
+
+            default:
+                DEFAULT;
+        }
+        
+    }
+    else {DEFAULT;}
+
+    if((*ok==-1) && (box64_dynarec_log>=LOG_INFO || box64_dynarec_dump || box64_dynarec_missing)) {
+        dynarec_log(LOG_NONE, "Dynarec 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);
+    }
+    return addr;
+}
diff --git a/src/dynarec/arm64/dynarec_arm64_helper.h b/src/dynarec/arm64/dynarec_arm64_helper.h
index ce7136ef..96d0c6c7 100644
--- a/src/dynarec/arm64/dynarec_arm64_helper.h
+++ b/src/dynarec/arm64/dynarec_arm64_helper.h
@@ -1101,6 +1101,7 @@ void* arm64_next(x64emu_t* emu, uintptr_t addr);
 #define dynarec64_66       STEPNAME(dynarec64_66)
 #define dynarec64_67       STEPNAME(dynarec64_67)
 #define dynarec64_67_32    STEPNAME(dynarec64_67_32)
+#define dynarec64_67_AVX   STEPNAME(dynarec64_67_AVX)
 #define dynarec64_6764_32  STEPNAME(dynarec64_6764_32)
 #define dynarec64_D8       STEPNAME(dynarec64_D8)
 #define dynarec64_D9       STEPNAME(dynarec64_D9)
@@ -1527,6 +1528,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
 uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
 uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
 uintptr_t dynarec64_67_32(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
+uintptr_t dynarec64_67_AVX(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, vex_t vex, int* ok, int* need_epilog);
 uintptr_t dynarec64_6764_32(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int seg, int* ok, int* need_epilog);
 uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
 uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
diff --git a/src/emu/x64run67.c b/src/emu/x64run67.c
index c17db227..f808517d 100644
--- a/src/emu/x64run67.c
+++ b/src/emu/x64run67.c
@@ -337,6 +337,9 @@ uintptr_t Run67(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr)
         if(rex.is32bits && !(MODREG)) {

             return 0;

         } else {

+            if(rex.is32bits) {

+                return 0;

+            }

             vex_t vex = {0};

             vex.rex = rex;

             tmp8u = nextop;

@@ -361,6 +364,9 @@ uintptr_t Run67(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr)
         if(rex.is32bits && !(MODREG)) {

             return 0;

         } else {

+            if(rex.is32bits) {

+                return 0;

+            }

             vex_t vex = {0};

             vex.rex = rex;

             tmp8u = nextop;