about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorHaichen Wu <www.wxmqq@gmail.com>2024-04-04 19:43:30 +0800
committerGitHub <noreply@github.com>2024-04-04 13:43:30 +0200
commita4142f68ce3a6b5d5034966ff887a00160539917 (patch)
treeb28254a91527bf89656fa000cb646570751de056 /src
parent4a889e39ad9a8b39119e71a8c9640affd3591a34 (diff)
downloadbox64-a4142f68ce3a6b5d5034966ff887a00160539917.tar.gz
box64-a4142f68ce3a6b5d5034966ff887a00160539917.zip
[LA64_DYNAREC] Added more SSE/SSE2 instructions (#1410)
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/la64/dynarec_la64_00.c3
-rw-r--r--src/dynarec/la64/dynarec_la64_f20f.c85
-rw-r--r--src/dynarec/la64/dynarec_la64_f30f.c16
-rw-r--r--src/dynarec/la64/dynarec_la64_helper.h13
-rw-r--r--src/dynarec/la64/la64_printer.c32
5 files changed, 149 insertions, 0 deletions
diff --git a/src/dynarec/la64/dynarec_la64_00.c b/src/dynarec/la64/dynarec_la64_00.c
index e8411efd..fe7b042d 100644
--- a/src/dynarec/la64/dynarec_la64_00.c
+++ b/src/dynarec/la64/dynarec_la64_00.c
@@ -122,6 +122,9 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                 case 0:
                     addr = dynarec64_0F(dyn, addr, ip, ninst, rex, ok, need_epilog);
                     break;
+                case 1:
+                    addr = dynarec64_F20F(dyn, addr, ip, ninst, rex, ok, need_epilog);
+                    break;
                 case 2:
                     addr = dynarec64_F30F(dyn, addr, ip, ninst, rex, ok, need_epilog);
                     break;
diff --git a/src/dynarec/la64/dynarec_la64_f20f.c b/src/dynarec/la64/dynarec_la64_f20f.c
new file mode 100644
index 00000000..54c8c746
--- /dev/null
+++ b/src/dynarec/la64/dynarec_la64_f20f.c
@@ -0,0 +1,85 @@
+#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 "la64_printer.h"
+#include "dynarec_la64_private.h"
+#include "dynarec_la64_functions.h"
+#include "dynarec_la64_helper.h"
+
+uintptr_t dynarec64_F20F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog)
+{
+    (void)ip; (void)need_epilog;
+
+    uint8_t opcode = F8;
+    uint8_t nextop;
+    uint8_t gd, ed;
+    uint8_t wback, wb1, wb2;
+    uint8_t u8;
+    uint64_t u64, j64;
+    int v0, v1;
+    int q0;
+    int d0, d1;
+    int64_t fixedaddress;
+    int unscaled;
+
+    MAYUSE(d0);
+    MAYUSE(d1);
+    MAYUSE(q0);
+    MAYUSE(v0);
+    MAYUSE(v1);
+
+    switch(opcode) {
+        case 0x10:
+            INST_NAME("MOVSD Gx, Ex");
+            nextop = F8;
+            GETG;
+            if(MODREG) {
+                ed = (nextop&7)+ (rex.b<<3);
+                v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
+                d0 = sse_get_reg(dyn, ninst, x1, ed, 0);
+                FMOV_D(v0, d0);
+            } else {
+                SMREAD();
+                v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
+                addr = geted(dyn, addr, ninst, nextop, &ed, x1, x2, &fixedaddress, rex, NULL, 8, 0);
+                FLD_D(v0, ed, fixedaddress);
+                // reset upper part
+                ST_D(xZR, xEmu, offsetof(x64emu_t, xmm[gd])+8);
+            }
+            break;
+        case 0x58:
+            INST_NAME("ADDSD Gx, Ex");
+            nextop = F8;
+            // TODO: fastnan handling
+            GETGX(v0, 1);
+            GETEXSD(v1, 0);
+            FADD_D(v0, v0, v1);
+            break;
+        case 0x5C:
+            INST_NAME("SUBSD Gx, Ex");
+            nextop = F8;
+            //TODO: fastnan handling
+            GETGX(v0, 1);
+            GETEXSD(v1, 0);
+            FSUB_D(v0, v0, v1);
+            break;
+        default:
+            DEFAULT;
+    }
+    return addr;
+}
\ No newline at end of file
diff --git a/src/dynarec/la64/dynarec_la64_f30f.c b/src/dynarec/la64/dynarec_la64_f30f.c
index 107e5f38..d36ea651 100644
--- a/src/dynarec/la64/dynarec_la64_f30f.c
+++ b/src/dynarec/la64/dynarec_la64_f30f.c
@@ -53,6 +53,22 @@ uintptr_t dynarec64_F30F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
             nextop = F8;
             FAKEED;
             break;
+        case 0x7E:
+            INST_NAME("MOVQ Gx, Ex");
+            nextop = F8;
+            // Will load Gx as SD. Is that a good choice?
+            if (MODREG) {
+                v1 = sse_get_reg(dyn, ninst, x1, (nextop & 7) + (rex.b << 3), 0);
+                GETGX_empty(v0);
+                FMOV_D(v0, v1);
+            } else {
+                GETGX_empty(v0);
+                SMREAD();
+                addr = geted(dyn, addr, ninst, nextop, &ed, x1, x2, &fixedaddress, rex, NULL, 1, 0);
+                FLD_D(v0, ed, fixedaddress);
+            }
+            ST_D(xZR, xEmu, offsetof(x64emu_t, xmm[gd]) + 8);
+            break;
         default:
             DEFAULT;
     }
diff --git a/src/dynarec/la64/dynarec_la64_helper.h b/src/dynarec/la64/dynarec_la64_helper.h
index 4d8a8d8c..3405afcb 100644
--- a/src/dynarec/la64/dynarec_la64_helper.h
+++ b/src/dynarec/la64/dynarec_la64_helper.h
@@ -195,6 +195,17 @@
         VLD(a, ed, fixedaddress);                                                            \
     }
 
+// Get Ex as a double, not a quad (warning, x1 get used, x2 might too)
+#define GETEXSD(a, D)                                                                        \
+    if (MODREG) {                                                                            \
+        a = sse_get_reg(dyn, ninst, x1, (nextop & 7) + (rex.b << 3), 0);                     \
+    } else {                                                                                 \
+        SMREAD();                                                                            \
+        a = fpu_get_scratch(dyn);                                                            \
+        addr = geted(dyn, addr, ninst, nextop, &ed, x1, x2, &fixedaddress, rex, NULL, 1, D); \
+        FLD_D(a, ed, fixedaddress);                                                            \
+    }
+
 // Write gb (gd) back to original register / memory, using s1 as scratch
 #define GBBACK() BSTRINS_D(gb1, gd, gb2 + 7, gb2);
 
@@ -505,6 +516,7 @@ void* la64_next(x64emu_t* emu, uintptr_t addr);
 #define dynarec64_F30F STEPNAME(dynarec64_F30F)
 #define dynarec64_660F STEPNAME(dynarec64_660F)
 #define dynarec64_F0   STEPNAME(dynarec64_F0)
+#define dynarec64_F20F STEPNAME(dynarec64_F20F)
 
 #define geted               STEPNAME(geted)
 #define geted32             STEPNAME(geted32)
@@ -640,6 +652,7 @@ uintptr_t dynarec64_F30F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
 uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
 uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog);
 uintptr_t dynarec64_F0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
+uintptr_t dynarec64_F20F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog);
 
 #if STEP < 3
 #define PASS3(A)
diff --git a/src/dynarec/la64/la64_printer.c b/src/dynarec/la64/la64_printer.c
index 742d730b..02c2db1e 100644
--- a/src/dynarec/la64/la64_printer.c
+++ b/src/dynarec/la64/la64_printer.c
@@ -7,6 +7,18 @@
 #include "debug.h"
 
 static const char* Xt[] = {"xZR", "r1", "r2", "sp", "xEmu", "x1_r5", "x2_r6", "x3_r7", "x4_r8", "x5_r9", "x6_r10", "xMASK_r11", "xRAX_r12", "xRCX_r13", "xRDX_r14", "xRBX_r15", "xRSP_r16", "xRBP_r17", "xRSI_r18", "xRDI_r19", "xRIP_r20", "r21", "r22", "xR8_r23", "xR9_r24", "xR10_r25", "xR11_r26", "xR12_r27", "xR13_r28", "xR14_r29", "xR15_r30", "xFlags_r31"};
+static const char* fpnames[] = {
+    "fa0",  "fa1",  "fa2",  "fa3",  "fa4",  "fa5",  "fa6",  "fa7",
+    "ft0",  "ft1",  "ft2",  "ft3",  "ft4",  "ft5",  "ft6",  "ft7",
+    "ft8",  "ft9",  "ft10", "ft11", "ft12", "ft13", "ft14", "ft15",
+    "fs0",  "fs1",  "fs2",  "fs3",  "fs4",  "fs5",  "fs6",  "fs7",
+};
+static const char* vrpnames[] = {
+    "vra0",  "vra1",  "vra2",  "vra3",  "vra4",  "vra5",  "vra6",  "vra7",
+    "vrt0",  "vrt1",  "vrt2",  "vrt3",  "vrt4",  "vrt5",  "vrt6",  "vrt7",
+    "vrt8",  "vrt9",  "vrt10", "vrt11", "vrt12", "vrt13", "vrt14", "vrt15",
+    "vrs0",  "vrs1",  "vrs2",  "vrs3",  "vrs4",  "vrs5",  "vrs6",  "vrs7",
+};
 
 typedef struct la64_print_s {
     int d, j, k, a;
@@ -450,6 +462,26 @@ const char* la64_print(uint32_t opcode, uintptr_t addr)
         snprintf(buff, sizeof(buff), "%-15s %s, %s, %d", "ST.D", Xt[Rd], Xt[Rj], signExtend(imm, 12));
         return buff;
     }
+    // FLD.D
+    if(isMask(opcode, "0010101110iiiiiiiiiiiijjjjjddddd", &a)) {
+        snprintf(buff, sizeof(buff), "%-15s %s, %s, %d", "FLD.D", fpnames[Rd], Xt[Rj], signExtend(imm, 12));
+        return buff;
+    }
+    // FADD.D
+    if(isMask(opcode, "00000001000000010kkkkkjjjjjddddd", &a)) {
+        snprintf(buff, sizeof(buff), "%-15s %s, %s, %s", "FADD.D", fpnames[Rd], fpnames[Rj], fpnames[Rk]);
+        return buff;
+    }
+    // FSUB.D
+    if(isMask(opcode, "00000001000000110kkkkkjjjjjddddd", &a)) {
+        snprintf(buff, sizeof(buff), "%-15s %s, %s, %s", "FSUB.D", fpnames[Rd], fpnames[Rj], fpnames[Rk]);
+        return buff;
+    }
+    // VLD
+    if(isMask(opcode, "0010110000iiiiiiiiiiiijjjjjddddd", &a)) {
+        snprintf(buff, sizeof(buff), "%-15s %s, %s, %d", "VLD.D", vrpnames[Rd], Xt[Rj], signExtend(imm, 12));
+        return buff;
+    }
     // EXT.W.H
     if(isMask(opcode, "0000000000000000010110jjjjjddddd", &a)) {
         snprintf(buff, sizeof(buff), "%-15s %s, %s", "EXT.W.H", Xt[Rd], Xt[Rj]);