about summary refs log tree commit diff stats
path: root/src/dynarec
diff options
context:
space:
mode:
authorYang Liu <numbksco@gmail.com>2024-06-18 16:01:12 +0800
committerGitHub <noreply@github.com>2024-06-18 10:01:12 +0200
commit8dfbe80b41794e77bc082aef70135c75393df567 (patch)
tree7006cddf0b987b2a379762ffe13ec9014aed90b5 /src/dynarec
parent2bcc997e4b2a43a124e03b75f2f65de99f96e982 (diff)
downloadbox64-8dfbe80b41794e77bc082aef70135c75393df567.tar.gz
box64-8dfbe80b41794e77bc082aef70135c75393df567.zip
[LA64_DYNAREC] Added more opcodes (#1597)
Diffstat (limited to 'src/dynarec')
-rw-r--r--src/dynarec/la64/dynarec_la64_0f.c13
-rw-r--r--src/dynarec/la64/dynarec_la64_64.c9
-rw-r--r--src/dynarec/la64/dynarec_la64_66.c23
-rw-r--r--src/dynarec/la64/dynarec_la64_660f.c10
-rw-r--r--src/dynarec/la64/dynarec_la64_6664.c70
-rw-r--r--src/dynarec/la64/dynarec_la64_67.c33
-rw-r--r--src/dynarec/la64/dynarec_la64_f0.c36
-rw-r--r--src/dynarec/la64/dynarec_la64_f20f.c16
-rw-r--r--src/dynarec/la64/dynarec_la64_f30f.c24
-rw-r--r--src/dynarec/la64/dynarec_la64_helper.h2
-rw-r--r--src/dynarec/la64/la64_emitter.h9
11 files changed, 245 insertions, 0 deletions
diff --git a/src/dynarec/la64/dynarec_la64_0f.c b/src/dynarec/la64/dynarec_la64_0f.c
index 8c0e633c..0c40f766 100644
--- a/src/dynarec/la64/dynarec_la64_0f.c
+++ b/src/dynarec/la64/dynarec_la64_0f.c
@@ -708,6 +708,19 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                 }
             else
                 switch ((nextop >> 3) & 7) {
+                    case 0:
+                        INST_NAME("FXSAVE Ed");
+                        MESSAGE(LOG_DUMP, "Need Optimization\n");
+                        SKIPTEST(x1);
+                        fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
+                        if (MODREG) {
+                            DEFAULT;
+                        } else {
+                            addr = geted(dyn, addr, ninst, nextop, &ed, x1, x3, &fixedaddress, rex, NULL, 0, 0);
+                            if (ed != x1) { MV(x1, ed); }
+                            CALL(rex.w ? ((void*)fpu_fxsave64) : ((void*)fpu_fxsave32), -1);
+                        }
+                        break;
                     case 2:
                         INST_NAME("LDMXCSR Md");
                         GETED(0);
diff --git a/src/dynarec/la64/dynarec_la64_64.c b/src/dynarec/la64/dynarec_la64_64.c
index 152db7b3..0e7b96d6 100644
--- a/src/dynarec/la64/dynarec_la64_64.c
+++ b/src/dynarec/la64/dynarec_la64_64.c
@@ -79,6 +79,15 @@ uintptr_t dynarec64_64(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
             GETEDO(x4, 0);
             emit_xor32(dyn, ninst, rex, gd, ed, x3, x4);
             break;
+        case 0x64:
+            addr = dynarec64_64(dyn, addr, ip, ninst, rex, rep, _FS, ok, need_epilog);
+            break;
+        case 0x65:
+            addr = dynarec64_64(dyn, addr, ip, ninst, rex, rep, _GS, ok, need_epilog);
+            break;
+        case 0x66:
+            addr = dynarec64_6664(dyn, addr, ip, ninst, rex, seg, ok, need_epilog);
+            break;
         case 0x81:
         case 0x83:
             nextop = F8;
diff --git a/src/dynarec/la64/dynarec_la64_66.c b/src/dynarec/la64/dynarec_la64_66.c
index 8250d502..5130a3b0 100644
--- a/src/dynarec/la64/dynarec_la64_66.c
+++ b/src/dynarec/la64/dynarec_la64_66.c
@@ -220,6 +220,15 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                 emit_cmp16_0(dyn, ninst, x1, x3, x4);
             }
             break;
+        case 0x64:
+            addr = dynarec64_6664(dyn, addr, ip, ninst, rex, _FS, ok, need_epilog);
+            break;
+        case 0x65:
+            addr = dynarec64_6664(dyn, addr, ip, ninst, rex, _GS, ok, need_epilog);
+            break;
+        case 0x66:
+            addr = dynarec64_66(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
+            break;
         case 0x69:
         case 0x6B:
             if (opcode == 0x69) {
@@ -537,6 +546,20 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                     UFLAG_RES(ed);
                     UFLAG_DF(x3, d_shr16);
                     break;
+                case 7:
+                    INST_NAME("SAR Ew, Ib");
+                    SETFLAGS(X_ALL, SF_PENDING);
+                    UFLAG_IF { MESSAGE(LOG_DUMP, "Need Optimization for flags\n"); }
+                    GETSEW(x1, 1);
+                    u8 = F8;
+                    UFLAG_IF { MOV32w(x2, (u8 & 15)); }
+                    UFLAG_OP12(ed, x2)
+                    SRAI_D(ed, ed, u8 & 15);
+                    if (MODREG) BSTRPICK_D(ed, ed, 15, 0);
+                    EWBACK;
+                    UFLAG_RES(ed);
+                    UFLAG_DF(x3, d_sar16);
+                    break;
                 default:
                     DEFAULT;
             }
diff --git a/src/dynarec/la64/dynarec_la64_660f.c b/src/dynarec/la64/dynarec_la64_660f.c
index 08fbde4e..70e1ae41 100644
--- a/src/dynarec/la64/dynarec_la64_660f.c
+++ b/src/dynarec/la64/dynarec_la64_660f.c
@@ -868,6 +868,16 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
                 SMWRITE2();
             }
             break;
+        case 0xD7:
+            INST_NAME("PMOVMSKB Gd, Ex");
+            nextop = F8;
+            GETEX(q0, 0, 0);
+            GETGD;
+            v0 = fpu_get_scratch(dyn);
+            VMSKLTZ_B(v0, q0);
+            MOVFR2GR_D(x1, v0);
+            BSTRINS_D(gd, x1, 15, 0);
+            break;
         case 0xDB:
             INST_NAME("PAND Gx,Ex");
             nextop = F8;
diff --git a/src/dynarec/la64/dynarec_la64_6664.c b/src/dynarec/la64/dynarec_la64_6664.c
new file mode 100644
index 00000000..01db8021
--- /dev/null
+++ b/src/dynarec/la64/dynarec_la64_6664.c
@@ -0,0 +1,70 @@
+#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 "la64_emitter.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_helper.h"
+#include "dynarec_la64_functions.h"
+
+uintptr_t dynarec64_6664(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int seg, int* ok, int* need_epilog)
+{
+    (void)ip;
+    (void)need_epilog;
+
+    uint8_t opcode = F8;
+    uint8_t nextop;
+    uint8_t gd, ed;
+    int64_t j64;
+    int v0, v1;
+    int64_t fixedaddress;
+    int unscaled;
+    MAYUSE(j64);
+
+    GETREX();
+
+    switch (opcode) {
+        case 0x8B:
+            INST_NAME("MOV Gd, FS:Ed");
+            nextop = F8;
+            GETGD;
+            if (MODREG) { // reg <= reg
+                ed = TO_LA64((nextop & 7) + (rex.b << 3));
+                if (rex.w) {
+                    MV(gd, ed);
+                } else {
+                    if (ed != gd) BSTRINS_D(gd, ed, 15, 0);
+                }
+            } else { // mem <= reg
+                grab_segdata(dyn, addr, ninst, x4, seg);
+                SMREAD();
+                addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0);
+                if (rex.w) {
+                    LDX_D(gd, ed, x4);
+                } else {
+                    LDX_HU(x1, ed, x4);
+                    BSTRINS_D(gd, x1, 15, 0);
+                }
+            }
+            break;
+
+        default:
+            DEFAULT;
+    }
+    return addr;
+}
diff --git a/src/dynarec/la64/dynarec_la64_67.c b/src/dynarec/la64/dynarec_la64_67.c
index 5b81eb9d..242d315e 100644
--- a/src/dynarec/la64/dynarec_la64_67.c
+++ b/src/dynarec/la64/dynarec_la64_67.c
@@ -62,6 +62,39 @@ uintptr_t dynarec64_67(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
     }
 
     switch(opcode) {
+        case 0x88:
+            INST_NAME("MOV Eb, Gb");
+            nextop = F8;
+            gd = ((nextop & 0x38) >> 3) + (rex.r << 3);
+            if (rex.rex) {
+                gb2 = 0;
+                gb1 = TO_LA64(gd);
+            } else {
+                gb2 = ((gd & 4) << 1);
+                gb1 = TO_LA64(gd & 3);
+            }
+            if (gb2) {
+                gd = x4;
+                BSTRPICK_D(gd, gb1, gb2 + 7, gb2);
+            } else {
+                gd = gb1; // no need to extract
+            }
+            if (MODREG) {
+                ed = (nextop & 7) + (rex.b << 3);
+                if (rex.rex) {
+                    eb1 = TO_LA64(ed);
+                    eb2 = 0;
+                } else {
+                    eb1 = TO_LA64(ed & 3); // Ax, Cx, Dx or Bx
+                    eb2 = ((ed & 4) >> 2); // L or H
+                }
+                BSTRINS_D(eb1, gd, eb2 * 8 + 7, eb2 * 8);
+            } else {
+                addr = geted32(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, &lock, 1, 0);
+                ST_B(gb1, ed, fixedaddress);
+                SMWRITELOCK(lock);
+            }
+            break;
         case 0x89:
             INST_NAME("MOV Ed, Gd");
             nextop = F8;
diff --git a/src/dynarec/la64/dynarec_la64_f0.c b/src/dynarec/la64/dynarec_la64_f0.c
index b6183de6..26610d2c 100644
--- a/src/dynarec/la64/dynarec_la64_f0.c
+++ b/src/dynarec/la64/dynarec_la64_f0.c
@@ -337,6 +337,42 @@ uintptr_t dynarec64_F0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                         SMDMB();
                     }
                     break;
+                case 1: // OR
+                    if (opcode == 0x81) {
+                        INST_NAME("LOCK OR Ed, Id");
+                    } else {
+                        INST_NAME("LOCK OR Ed, Ib");
+                    }
+                    SETFLAGS(X_ALL, SF_SET_PENDING);
+                    if (MODREG) {
+                        if (opcode == 0x81)
+                            i64 = F32S;
+                        else
+                            i64 = F8S;
+                        ed = TO_LA64((nextop & 7) + (rex.b << 3));
+                        emit_or32c(dyn, ninst, rex, ed, i64, x3, x4);
+                    } else {
+                        addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, (opcode == 0x81) ? 4 : 1);
+                        if (opcode == 0x81)
+                            i64 = F32S;
+                        else
+                            i64 = F8S;
+                        if (i64 <= -2048 || i64 > 2048)
+                            MOV64xw(x3, i64);
+                        MARKLOCK;
+                        LLxw(x1, wback, 0);
+                        if (i64 >= -2048 && i64 < 2048) {
+                            ORI(x4, x1, i64);
+                        } else {
+                            OR(x4, x1, x3);
+                        }
+                        if (!rex.w) ZEROUP(x4);
+                        SCxw(x4, wback, 0);
+                        BEQZ_MARKLOCK(x4);
+                        IFX (X_ALL | X_PEND)
+                            emit_or32c(dyn, ninst, rex, x1, i64, x3, x4);
+                    }
+                    break;
                 case 5: // SUB
                     if (opcode == 0x81) {
                         INST_NAME("LOCK SUB Ed, Id");
diff --git a/src/dynarec/la64/dynarec_la64_f20f.c b/src/dynarec/la64/dynarec_la64_f20f.c
index 7c14361d..133b8a2b 100644
--- a/src/dynarec/la64/dynarec_la64_f20f.c
+++ b/src/dynarec/la64/dynarec_la64_f20f.c
@@ -154,6 +154,22 @@ uintptr_t dynarec64_F20F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
                 }
             }
             break;
+        case 0x51:
+            INST_NAME("SQRTSD Gx, Ex");
+            nextop = F8;
+            GETGX_empty(v0);
+            d1 = fpu_get_scratch(dyn);
+            GETEXSD(d0, 0, 0);
+            FSQRT_D(d1, d0);
+            if (!box64_dynarec_fastnan) {
+                v1 = fpu_get_scratch(dyn);
+                MOVGR2FR_D(v1, xZR);
+                FCMP_D(fcc0, d0, v1, cLT);
+                BCEQZ(fcc0, 4 + 4);
+                FNEG_D(d1, d1);
+            }
+            VEXTRINS_D(v0, d1, 0);
+            break;
         case 0x58:
             INST_NAME("ADDSD Gx, Ex");
             nextop = F8;
diff --git a/src/dynarec/la64/dynarec_la64_f30f.c b/src/dynarec/la64/dynarec_la64_f30f.c
index 1d147a0a..196e386f 100644
--- a/src/dynarec/la64/dynarec_la64_f30f.c
+++ b/src/dynarec/la64/dynarec_la64_f30f.c
@@ -284,6 +284,30 @@ uintptr_t dynarec64_F30F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
                 SMWRITE2();
             }
             break;
+        case 0xBC:
+            INST_NAME("TZCNT Gd, Ed");
+            SETFLAGS(X_ZF, SF_SUBSET);
+            SET_DFNONE();
+            nextop = F8;
+            GETED(0);
+            GETGD;
+            if (!rex.w && MODREG) {
+                AND(x4, ed, xMASK);
+                ed = x4;
+            }
+            RESTORE_EFLAGS(x1);
+            ANDI(xFlags, xFlags, ~((1 << F_ZF) | (1 << F_CF)));
+            BNE_MARK(ed, xZR);
+            ORI(xFlags, xFlags, 1 << F_CF);
+            MOV32w(gd, rex.w ? 64 : 32);
+            SPILL_EFLAGS();
+            B_NEXT_nocond;
+            MARK;
+            CTZxw(gd, ed);
+            BNE(gd, xZR, 4 + 4);
+            ORI(xFlags, xFlags, 1 << F_ZF);
+            SPILL_EFLAGS();
+            break;
         case 0xC2:
             INST_NAME("CMPSS Gx, Ex, Ib");
             nextop = F8;
diff --git a/src/dynarec/la64/dynarec_la64_helper.h b/src/dynarec/la64/dynarec_la64_helper.h
index 060917ce..1c921498 100644
--- a/src/dynarec/la64/dynarec_la64_helper.h
+++ b/src/dynarec/la64/dynarec_la64_helper.h
@@ -745,6 +745,7 @@ void* la64_next(x64emu_t* emu, uintptr_t addr);
 #define dynarec64_0F   STEPNAME(dynarec64_0F)
 #define dynarec64_64   STEPNAME(dynarec64_64)
 #define dynarec64_66   STEPNAME(dynarec64_66)
+#define dynarec64_6664 STEPNAME(dynarec64_6664)
 #define dynarec64_67   STEPNAME(dynarec64_67)
 #define dynarec64_F30F STEPNAME(dynarec64_F30F)
 #define dynarec64_660F STEPNAME(dynarec64_660F)
@@ -973,6 +974,7 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
 uintptr_t dynarec64_F30F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog);
 uintptr_t dynarec64_64(dynarec_la64_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_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_6664(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int seg, int* ok, int* need_epilog);
 uintptr_t dynarec64_67(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);
diff --git a/src/dynarec/la64/la64_emitter.h b/src/dynarec/la64/la64_emitter.h
index c912f666..5d872d9c 100644
--- a/src/dynarec/la64/la64_emitter.h
+++ b/src/dynarec/la64/la64_emitter.h
@@ -528,6 +528,15 @@ f24-f31  fs0-fs7   Static registers                Callee
         }                    \
     } while (0)
 
+#define CTZxw(rd, rj)      \
+    do {                   \
+        if (rex.w) {       \
+            CTZ_D(rd, rj); \
+        } else {           \
+            CTZ_W(rd, rj); \
+        }                  \
+    } while (0)
+
 
 // GR[rd] = SignExtend(GR[rj][7:0], GRLEN)
 #define EXT_W_B(rd, rj) EMIT(type_2R(0b0000000000000000010111, rj, rd))