about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorYang Liu <liuyang22@iscas.ac.cn>2025-02-09 01:01:53 +0800
committerGitHub <noreply@github.com>2025-02-08 18:01:53 +0100
commit3e2c6987106b9cd8775618a0f3a7f31e0936821b (patch)
treee7d933d4dcacb376aa5ef9a4fc0f7d7ce6b52c35 /src
parent58b24c85a2407a6c2ab6dfc2f18555dd929ad7e1 (diff)
downloadbox64-3e2c6987106b9cd8775618a0f3a7f31e0936821b.tar.gz
box64-3e2c6987106b9cd8775618a0f3a7f31e0936821b.zip
[LA64_DYNAREC] Added more opcodes (#2330)
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/la64/dynarec_la64_00.c72
-rw-r--r--src/dynarec/la64/dynarec_la64_66.c16
-rw-r--r--src/dynarec/la64/dynarec_la64_660f.c30
-rw-r--r--src/dynarec/la64/dynarec_la64_emit_shift.c58
-rw-r--r--src/dynarec/la64/dynarec_la64_helper.h2
5 files changed, 178 insertions, 0 deletions
diff --git a/src/dynarec/la64/dynarec_la64_00.c b/src/dynarec/la64/dynarec_la64_00.c
index ba30e983..49e9bece 100644
--- a/src/dynarec/la64/dynarec_la64_00.c
+++ b/src/dynarec/la64/dynarec_la64_00.c
@@ -1927,6 +1927,62 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                 }
             }
             break;
+        case 0xCD:
+            u8 = F8;
+            if (box64_wine && (u8 == 0x2D || u8 == 0x2C || u8 == 0x29)) {
+                INST_NAME("INT 29/2c/2d");
+                // lets do nothing
+                MESSAGE(LOG_INFO, "INT 29/2c/2d Windows interruption\n");
+                GETIP(ip); // priviledged instruction, IP not updated
+                STORE_XEMU_CALL();
+                MOV32w(x1, u8);
+                CALL(native_int, -1);
+                LOAD_XEMU_CALL();
+            } else if (u8 == 0x80) {
+                INST_NAME("32bits SYSCALL");
+                NOTEST(x1);
+                SMEND();
+                GETIP(addr);
+                STORE_XEMU_CALL();
+                CALL_S(x86Syscall, -1);
+                LOAD_XEMU_CALL();
+                TABLE64(x3, addr); // expected return address
+                BNE_MARK(xRIP, x3);
+                LD_W(x1, xEmu, offsetof(x64emu_t, quit));
+                BEQ_NEXT(x1, xZR);
+                MARK;
+                LOAD_XEMU_REM();
+                jump_to_epilog(dyn, 0, xRIP, ninst);
+            } else if (u8 == 0x03) {
+                INST_NAME("INT 3");
+                if (BOX64DRENV(dynarec_safeflags) > 1) {
+                    READFLAGS(X_PEND);
+                } else {
+                    SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); // Hack to set flags in "don't care" state
+                }
+                GETIP(addr);
+                STORE_XEMU_CALL();
+                CALL(native_int3, -1);
+                LOAD_XEMU_CALL();
+                jump_to_epilog(dyn, 0, xRIP, ninst);
+                *need_epilog = 0;
+                *ok = 0;
+            } else {
+                INST_NAME("INT n");
+                if (BOX64DRENV(dynarec_safeflags) > 1) {
+                    READFLAGS(X_PEND);
+                } else {
+                    SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); // Hack to set flags in "don't care" state
+                }
+                GETIP(ip); // priviledged instruction, IP not updated
+                STORE_XEMU_CALL();
+                CALL(native_priv, -1);
+                LOAD_XEMU_CALL();
+                jump_to_epilog(dyn, 0, xRIP, ninst);
+                *need_epilog = 0;
+                *ok = 0;
+            }
+            break;
         case 0xCF:
             INST_NAME("IRET");
             SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); // Not a hack, EFLAGS are restored
@@ -1987,6 +2043,22 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                     emit_shr8(dyn, ninst, x1, x2, x5, x4, x6);
                     EBBACK();
                     break;
+                case 7:
+                    if (opcode == 0xD0) {
+                        INST_NAME("SAR Eb, 1");
+                        GETSEB(x1, 0);
+                        MOV32w(x2, 1);
+                    } else {
+                        INST_NAME("SAR Eb, CL");
+                        GETSEB(x1, 0);
+                        ANDI(x2, xRCX, 0x1f);
+                        BEQ_NEXT(x2, xZR);
+                    }
+                    SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); // some flags are left undefined
+                    if (BOX64DRENV(dynarec_safeflags) > 1) MAYSETFLAGS();
+                    emit_sar8(dyn, ninst, x1, x2, x5, x4, x6);
+                    EBBACK();
+                    break;
                 default:
                     DEFAULT;
             }
diff --git a/src/dynarec/la64/dynarec_la64_66.c b/src/dynarec/la64/dynarec_la64_66.c
index bf9cc495..548f01bf 100644
--- a/src/dynarec/la64/dynarec_la64_66.c
+++ b/src/dynarec/la64/dynarec_la64_66.c
@@ -791,6 +791,22 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
         case 0xD3:
             nextop = F8;
             switch ((nextop >> 3) & 7) {
+                case 0:
+                    if (opcode == 0xD1) {
+                        INST_NAME("ROL Ew, 1");
+                        MOV32w(x2, 1);
+                    } else {
+                        INST_NAME("ROL Ew, CL");
+                        ANDI(x2, xRCX, 0x1f);
+                        BEQ_NEXT(x2, xZR);
+                    }
+                    MESSAGE(LOG_DUMP, "Need Optimization\n");
+                    SETFLAGS(X_OF | X_CF, SF_SET_DF, NAT_FLAGS_NOFUSION);
+                    if (BOX64DRENV(dynarec_safeflags) > 1) MAYSETFLAGS();
+                    GETEW(x1, 1);
+                    CALL_(rol16, x1, x3);
+                    EWBACK;
+                    break;
                 case 5:
                     if (opcode == 0xD1) {
                         INST_NAME("SHR Ew, 1");
diff --git a/src/dynarec/la64/dynarec_la64_660f.c b/src/dynarec/la64/dynarec_la64_660f.c
index b5fbce5b..861de379 100644
--- a/src/dynarec/la64/dynarec_la64_660f.c
+++ b/src/dynarec/la64/dynarec_la64_660f.c
@@ -847,6 +847,17 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
             GOCOND(0x40, "CMOV", "Gd, Ed");
         #undef GO
 
+        case 0x50:
+            nextop = F8;
+            INST_NAME("PMOVMSKD Gd, Ex");
+            GETEX(q0, 0, 0);
+            GETGD;
+            VPICKVE2GR_D(x1, q0, 0);
+            VPICKVE2GR_D(gd, q0, 1);
+            SRLI_D(gd, gd, 62);
+            SRLI_D(x1, x1, 63);
+            BSTRINS_D(gd, x1, 0, 0);
+            break;
         case 0x51:
             INST_NAME("SQRTPD Gx, Ex");
             nextop = F8;
@@ -1441,6 +1452,25 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
             gd = TO_NAT(((nextop & 0x38) >> 3) + (rex.r << 3));
             BSTRINS_D(gd, x1, 15, 0); // insert in Gw
             break;
+        case 0xBA:
+            nextop = F8;
+            switch ((nextop >> 3) & 7) {
+                case 4:
+                    INST_NAME("BT Ew, Ib");
+                    SETFLAGS(X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION);
+                    SET_DFNONE();
+                    GETED(1);
+                    u8 = F8;
+                    u8 &= rex.w ? 0x3f : 15;
+                    IFX (X_CF) {
+                        BSTRPICK_D(x3, ed, u8, u8);
+                        BSTRINS_D(xFlags, x3, 0, 0);
+                    }
+                    break;
+                default:
+                    DEFAULT;
+            }
+            break;
         case 0xBE:
             INST_NAME("MOVSX Gw, Eb");
             nextop = F8;
diff --git a/src/dynarec/la64/dynarec_la64_emit_shift.c b/src/dynarec/la64/dynarec_la64_emit_shift.c
index 9c7845dd..0125c1ae 100644
--- a/src/dynarec/la64/dynarec_la64_emit_shift.c
+++ b/src/dynarec/la64/dynarec_la64_emit_shift.c
@@ -461,6 +461,64 @@ void emit_shr8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, i
     }
 }
 
+// emit SAR8 instruction, from s1 , shift s2 (!0 and and'd already), store result in s1 using s3, s4 and s5 as scratch
+void emit_sar8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5)
+{
+    int64_t j64;
+
+    if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR);
+
+    IFX (X_PEND) {
+        ST_B(s2, xEmu, offsetof(x64emu_t, op2));
+        ST_B(s1, xEmu, offsetof(x64emu_t, op1));
+        SET_DF(s4, d_sar8);
+    } else IFXORNAT (X_ALL) {
+        SET_DFNONE();
+    }
+
+    if (la64_lbt) {
+        IFX (X_ALL) {
+            X64_SRA_B(s1, s2);
+        }
+        SRA_D(s1, s1, s2);
+        ANDI(s1, s1, 0xff);
+
+        IFX (X_PEND) {
+            ST_B(s1, xEmu, offsetof(x64emu_t, res));
+        }
+        return;
+    }
+
+    CLEAR_FLAGS(s3);
+    IFX (X_CF) {
+        ADDI_D(s3, s2, -1);
+        SRA_D(s3, s1, s3);
+        ANDI(s3, s3, 1); // LSB == F_CF
+        OR(xFlags, xFlags, s3);
+    }
+    // For the SAR instruction, the OF flag is cleared for all 1-bit shifts.
+    // OF nop
+    IFX (X_SF) {
+        // SF is the same as the original operand
+        BGE(s1, xZR, 8);
+        ORI(xFlags, xFlags, 1 << F_SF);
+    }
+
+    SRA_D(s1, s1, s2);
+    ANDI(s1, s1, 0xff);
+
+    IFX (X_PEND) {
+        ST_B(s1, xEmu, offsetof(x64emu_t, res));
+    }
+    IFX (X_ZF) {
+        BNEZ(s1, 8);
+        ORI(xFlags, xFlags, 1 << F_ZF);
+    }
+    IFX (X_PF) {
+        emit_pf(dyn, ninst, s1, s3, s4);
+    }
+}
+
 // emit SHR16 instruction, from s1 , shift s2 (!0 and and'd already), store result in s1 using s3 and s4 as scratch
 void emit_shr16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5)
 {
diff --git a/src/dynarec/la64/dynarec_la64_helper.h b/src/dynarec/la64/dynarec_la64_helper.h
index 4653759d..4bad8557 100644
--- a/src/dynarec/la64/dynarec_la64_helper.h
+++ b/src/dynarec/la64/dynarec_la64_helper.h
@@ -902,6 +902,7 @@ void* la64_next(x64emu_t* emu, uintptr_t addr);
 #define emit_shl32c         STEPNAME(emit_shl32c)
 #define emit_shl8           STEPNAME(emit_shl8)
 #define emit_shr8           STEPNAME(emit_shr8)
+#define emit_sar8           STEPNAME(emit_sar8)
 #define emit_shr16          STEPNAME(emit_shr16)
 #define emit_shr16c         STEPNAME(emit_shr16c)
 #define emit_shr32          STEPNAME(emit_shr32)
@@ -1012,6 +1013,7 @@ void emit_shl32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
 void emit_shl32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4, int s5);
 void emit_shl8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5);
 void emit_shr8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5);
+void emit_sar8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5);
 void emit_shr16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5);
 void emit_shr16c(dynarec_la64_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4, int s5);
 void emit_shr32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4);