about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorYang Liu <liuyang22@iscas.ac.cn>2025-10-13 02:29:35 +0800
committerGitHub <noreply@github.com>2025-10-12 20:29:35 +0200
commitf5eff13acc27b11bf9a7078cce6372a051a39689 (patch)
treee6e7ab2a951700ec2443f96da6025a056ba402f0 /src
parent7b66c024f058eddd7055856f1c963d5c84f38cb6 (diff)
downloadbox64-f5eff13acc27b11bf9a7078cce6372a051a39689.tar.gz
box64-f5eff13acc27b11bf9a7078cce6372a051a39689.zip
[RV64_DYNAREC] Fixed some 16bit BT/BTS/BTR/BTC opcodes (#3062)
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/rv64/dynarec_rv64_660f.c182
1 files changed, 135 insertions, 47 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_660f.c b/src/dynarec/rv64/dynarec_rv64_660f.c
index 8d1db074..8a303abf 100644
--- a/src/dynarec/rv64/dynarec_rv64_660f.c
+++ b/src/dynarec/rv64/dynarec_rv64_660f.c
@@ -1170,15 +1170,36 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
             break;
         case 0xA3:
             INST_NAME("BT Ew, Gw");
-            SETFLAGS(X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION);
+            if (!BOX64ENV(dynarec_safeflags)) {
+                SETFLAGS(X_ALL & ~X_ZF, SF_SUBSET, NAT_FLAGS_NOFUSION);
+            } else {
+                SETFLAGS(X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION);
+            }
             SET_DFNONE();
             nextop = F8;
-            GETEW(x1, 0);
-            GETGW(x2);
-            ANDI(gd, gd, 15);
-            BEXT(x4, ed, gd, x6);
-            ANDI(xFlags, xFlags, ~1);
-            OR(xFlags, xFlags, x4);
+            GETGD;
+            if (MODREG) {
+                ed = TO_NAT((nextop & 7) + (rex.b << 3));
+            } else {
+                SMREAD();
+                addr = geted(dyn, addr, ninst, nextop, &wback, x3, x1, &fixedaddress, rex, NULL, 1, 0);
+                SLLI(x1, gd, 48);
+                SRAI(x1, x1, 48 + 4);
+                ADDSL(x3, wback, x1, 1, x1);
+                LH(x1, x3, fixedaddress);
+                ed = x1;
+            }
+            IFX (X_CF) {
+                ANDI(x2, gd, 0xf);
+                if (cpuext.zbs) {
+                    BEXT_(x4, ed, x2);
+                } else {
+                    SRL(x4, ed, x2);
+                    ANDI(x4, x4, 1);
+                }
+                ANDI(xFlags, xFlags, ~1);
+                OR(xFlags, xFlags, x4);
+            }
             break;
         case 0xA4:
             nextop = F8;
@@ -1192,19 +1213,45 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
             break;
         case 0xAB:
             INST_NAME("BTS Ew, Gw");
-            SETFLAGS(X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION);
+            if (!BOX64ENV(dynarec_safeflags)) {
+                SETFLAGS(X_ALL & ~X_ZF, SF_SUBSET, NAT_FLAGS_NOFUSION);
+            } else {
+                SETFLAGS(X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION);
+            }
             SET_DFNONE();
             nextop = F8;
-            GETEW(x1, 0);
-            GETGW(x2);
-            ANDI(gd, gd, 15);
-            BEXT(x4, ed, gd, x6);
-            ANDI(xFlags, xFlags, ~1);
-            OR(xFlags, xFlags, x4);
+            GETGD;
+            if (MODREG) {
+                ed = TO_NAT((nextop & 7) + (rex.b << 3));
+                wback = 0;
+            } else {
+                SMREAD();
+                addr = geted(dyn, addr, ninst, nextop, &wback, x3, x1, &fixedaddress, rex, NULL, 1, 0);
+                SLLI(x1, gd, 48);
+                SRAI(x1, x1, 48 + 4);
+                ADDSL(x3, wback, x1, 1, x1);
+                LH(x1, x3, fixedaddress);
+                ed = x1;
+                wback = x3;
+            }
+            ANDI(x2, gd, 0xf);
+            IFX (X_CF) {
+                if (cpuext.zbs) {
+                    BEXT_(x4, ed, x2);
+                } else {
+                    SRL(x4, ed, x2);
+                    ANDI(x4, x4, 1);
+                }
+                ANDI(xFlags, xFlags, ~1);
+                OR(xFlags, xFlags, x4);
+            }
             ADDI(x4, xZR, 1);
-            SLL(x4, x4, gd);
+            SLL(x4, x4, x2);
             OR(ed, ed, x4);
-            EWBACK;
+            if (wback) {
+                SH(ed, wback, fixedaddress);
+                SMWRITE();
+            }
             break;
         case 0xAC:
             nextop = F8;
@@ -1230,20 +1277,46 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
             break;
         case 0xB3:
             INST_NAME("BTR Ew, Gw");
-            SETFLAGS(X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION);
+            if (!BOX64ENV(dynarec_safeflags)) {
+                SETFLAGS(X_ALL & ~X_ZF, SF_SUBSET, NAT_FLAGS_NOFUSION);
+            } else {
+                SETFLAGS(X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION);
+            }
             SET_DFNONE();
             nextop = F8;
-            GETEW(x1, 0);
-            GETGW(x2);
-            ANDI(gd, gd, 15);
-            BEXT(x4, ed, gd, x5); // F_CF is 1
-            ANDI(xFlags, xFlags, ~1);
-            OR(xFlags, xFlags, x4);
+            GETGD;
+            if (MODREG) {
+                ed = TO_NAT((nextop & 7) + (rex.b << 3));
+                wback = 0;
+            } else {
+                SMREAD();
+                addr = geted(dyn, addr, ninst, nextop, &wback, x3, x1, &fixedaddress, rex, NULL, 1, 0);
+                SLLI(x1, gd, 48);
+                SRAI(x1, x1, 48 + 4);
+                ADDSL(x3, wback, x1, 1, x1);
+                LH(x1, x3, fixedaddress);
+                ed = x1;
+                wback = x3;
+            }
+            ANDI(x2, gd, 0xf);
+            IFX (X_CF) {
+                if (cpuext.zbs) {
+                    BEXT_(x4, ed, x2);
+                } else {
+                    SRL(x4, ed, x2);
+                    ANDI(x4, x4, 1);
+                }
+                ANDI(xFlags, xFlags, ~1);
+                OR(xFlags, xFlags, x4);
+            }
             ADDI(x4, xZR, 1);
-            SLL(x4, x4, gd);
+            SLL(x4, x4, x2);
             NOT(x4, x4);
             AND(ed, ed, x4);
-            EWBACK;
+            if (wback) {
+                SH(ed, wback, fixedaddress);
+                SMWRITE();
+            }
             break;
         case 0xB6:
             INST_NAME("MOVZX Gw, Eb");
@@ -1277,11 +1350,15 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
             switch ((nextop >> 3) & 7) {
                 case 4:
                     INST_NAME("BT Ew, Ib");
-                    SETFLAGS(X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION);
+                    if (!BOX64ENV(dynarec_safeflags)) {
+                        SETFLAGS(X_ALL & ~X_ZF, SF_SUBSET, NAT_FLAGS_NOFUSION);
+                    } else {
+                        SETFLAGS(X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION);
+                    }
                     SET_DFNONE();
                     GETED(1);
                     u8 = F8;
-                    u8 &= rex.w ? 0x3f : 15;
+                    u8 &= (rex.w ? 0x3f : 0x0f);
                     IFX (X_CF) {
                         BEXTI(x3, ed, u8); // F_CF is 1
                         ANDI(xFlags, xFlags, ~1);
@@ -1290,11 +1367,15 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
                     break;
                 case 5:
                     INST_NAME("BTS Ew, Ib");
-                    SETFLAGS(X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION);
+                    if (!BOX64ENV(dynarec_safeflags)) {
+                        SETFLAGS(X_ALL & ~X_ZF, SF_SUBSET, NAT_FLAGS_NOFUSION);
+                    } else {
+                        SETFLAGS(X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION);
+                    }
                     SET_DFNONE();
                     GETEW(x1, 1);
                     u8 = F8;
-                    u8 &= (rex.w ? 0x3f : 15);
+                    u8 &= (rex.w ? 0x3f : 0x0f);
                     IFX (X_CF) ORI(xFlags, xFlags, 1 << F_CF);
                     if (u8 <= 10) {
                         ANDI(x6, ed, 1 << u8);
@@ -1313,12 +1394,16 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
                     MARK;
                     break;
                 case 6:
-                    INST_NAME("BTR Ed, Ib");
-                    SETFLAGS(X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION);
+                    INST_NAME("BTR Ew, Ib");
+                    if (!BOX64ENV(dynarec_safeflags)) {
+                        SETFLAGS(X_ALL & ~X_ZF, SF_SUBSET, NAT_FLAGS_NOFUSION);
+                    } else {
+                        SETFLAGS(X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION);
+                    }
                     SET_DFNONE();
                     GETEW(x1, 1);
                     u8 = F8;
-                    u8 &= (rex.w ? 0x3f : 15);
+                    u8 &= (rex.w ? 0x3f : 0x0f);
                     IFX (X_CF) ANDI(xFlags, xFlags, ~(1 << F_CF));
                     if (u8 <= 10) {
                         ANDI(x6, ed, 1 << u8);
@@ -1338,11 +1423,15 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
                     break;
                 case 7:
                     INST_NAME("BTC Ew, Ib");
-                    SETFLAGS(X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION);
+                    if (!BOX64ENV(dynarec_safeflags)) {
+                        SETFLAGS(X_ALL & ~X_ZF, SF_SUBSET, NAT_FLAGS_NOFUSION);
+                    } else {
+                        SETFLAGS(X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION);
+                    }
                     SET_DFNONE();
                     GETEW(x1, 1);
                     u8 = F8;
-                    u8 &= rex.w ? 0x3f : 15;
+                    u8 &= (rex.w ? 0x3f : 0x0f);
                     IFX (X_CF) {
                         BEXTI(x6, ed, u8); // F_CF is 1
                         ANDI(xFlags, xFlags, ~1);
@@ -1362,7 +1451,11 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
             break;
         case 0xBB:
             INST_NAME("BTC Ew, Gw");
-            SETFLAGS(X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION);
+            if (!BOX64ENV(dynarec_safeflags)) {
+                SETFLAGS(X_ALL & ~X_ZF, SF_SUBSET, NAT_FLAGS_NOFUSION);
+            } else {
+                SETFLAGS(X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION);
+            }
             SET_DFNONE();
             nextop = F8;
             GETGD;
@@ -1372,22 +1465,18 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
             } else {
                 SMREAD();
                 addr = geted(dyn, addr, ninst, nextop, &wback, x3, x1, &fixedaddress, rex, NULL, 1, 0);
-                SRAIxw(x1, gd, 5 + rex.w);
-                ADDSL(x3, wback, x1, 2 + rex.w, x1);
-                LDxw(x1, x3, fixedaddress);
+                SLLI(x1, gd, 48);
+                SRAI(x1, x1, 48 + 4);
+                ADDSL(x3, wback, x1, 1, x1);
+                LH(x1, x3, fixedaddress);
                 ed = x1;
                 wback = x3;
             }
+            ANDI(x2, gd, 0xf);
             IFX (X_CF) {
                 if (cpuext.zbs) {
-                    if (rex.w) {
-                        BEXT_(x4, ed, gd);
-                    } else {
-                        ANDI(x2, gd, 0xf);
-                        BEXT_(x4, ed, x2);
-                    }
+                    BEXT_(x4, ed, x2);
                 } else {
-                    ANDI(x2, gd, rex.w ? 0x3f : 0xf);
                     SRL(x4, ed, x2);
                     ANDI(x4, x4, 1);
                 }
@@ -1395,11 +1484,10 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
                 OR(xFlags, xFlags, x4);
             }
             ADDI(x4, xZR, 1);
-            ANDI(x2, gd, rex.w ? 0x3f : 15);
             SLL(x4, x4, x2);
             XOR(ed, ed, x4);
             if (wback) {
-                SDxw(ed, wback, fixedaddress);
+                SH(ed, wback, fixedaddress);
                 SMWRITE();
             }
             break;