about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorxctan <xctan@cirno.icu>2023-12-26 11:55:25 +0000
committerGitHub <noreply@github.com>2023-12-26 12:55:25 +0100
commite2abb6b6db3ed75ff60515b26bc1fd166633437d (patch)
treebe45efd393a354f2afd7b5dbdff160b275d46548
parentcb63cdcd421e33449c5edde04a04a3833c950cfe (diff)
downloadbox64-e2abb6b6db3ed75ff60515b26bc1fd166633437d.tar.gz
box64-e2abb6b6db3ed75ff60515b26bc1fd166633437d.zip
[DYNAREC_RV64] Added more opcodes for VMP-protected GI (#1168)
* [DYNAREC_RV64] Added 66 0F B3 BTR opcode

* [DYNAREC_RV64] Added 66 0F BA /7 BTC opcode

* [DYNAREC_RV64] Added 66 {D1,D3} /{2,3} RCL/RCR opcodes

* [DYNAREC_RV64] Added 66 0F BA /{5,6} BTS/BTR opcodes

* [DYNAREC_RV64] Added 0F C1 XADD opcode

* [DYNAREC_RV64] Added 0F C0 XADD opcode

* [DYNAREC_RV64] Added D3 /2 RCL opcode

* [DYNAREC_RV64] Removed redundant declaration of wb2 in 0F

* [DYNAREC_RV64] Enable 66 0F BD BSR again

* [DYNAREC_RV64] Added 66 1D SBB opcode
-rw-r--r--src/dynarec/rv64/dynarec_rv64_00_3.c10
-rw-r--r--src/dynarec/rv64/dynarec_rv64_0f.c26
-rw-r--r--src/dynarec/rv64/dynarec_rv64_66.c40
-rw-r--r--src/dynarec/rv64/dynarec_rv64_660f.c155
4 files changed, 194 insertions, 37 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_00_3.c b/src/dynarec/rv64/dynarec_rv64_00_3.c
index eddb2ead..2f55ab16 100644
--- a/src/dynarec/rv64/dynarec_rv64_00_3.c
+++ b/src/dynarec/rv64/dynarec_rv64_00_3.c
@@ -648,6 +648,16 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
                     WBACK;
                     if(!wback && !rex.w) ZEROUP(ed);
                     break;
+                case 2:
+                    INST_NAME("RCL Ed, CL");
+                    MESSAGE("LOG_DUMP", "Need optimization\n");
+                    READFLAGS(X_CF);
+                    SETFLAGS(X_OF|X_CF, SF_SET);
+                    ANDI(x2, xRCX, rex.w?0x3f:0x1f);
+                    GETEDW(x4, x1, 0);
+                    CALL_(rex.w ? ((void*)rcl64) : ((void*)rcl32), ed, x4);
+                    WBACK;
+                    break;
                 case 3:
                     INST_NAME("RCR Ed, CL");
                     MESSAGE(LOG_DUMP, "Need Optimization\n");
diff --git a/src/dynarec/rv64/dynarec_rv64_0f.c b/src/dynarec/rv64/dynarec_rv64_0f.c
index 86a5a3e7..ec2b7ae9 100644
--- a/src/dynarec/rv64/dynarec_rv64_0f.c
+++ b/src/dynarec/rv64/dynarec_rv64_0f.c
@@ -33,8 +33,9 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
     uint8_t opcode = F8;
     uint8_t nextop, u8;
     uint8_t gd, ed;
-    uint8_t wback, wb2, gback;
+    uint8_t wb1, wback, wb2, gback;
     uint8_t eb1, eb2;
+    uint8_t gb1, gb2;
     int32_t i32, i32_;
     int cacheupd = 0;
     int v0, v1;
@@ -1687,6 +1688,29 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
             if (!rex.w)
                 ZEROUP(gd);
             break;
+        case 0xC0:
+            INST_NAME("XADD Eb, Gb");
+            SETFLAGS(X_ALL, SF_SET_PENDING);
+            nextop = F8;
+            GETEB(x1, 0);
+            GETGB(x2);
+            MV(x9, ed);
+            emit_add8(dyn, ninst, ed, gd, x4, x5);
+            MV(gd, x9);
+            EBBACK(x5, 0);
+            GBBACK(x5);
+            break;
+        case 0xC1:
+            INST_NAME("XADD Ed, Gd");
+            SETFLAGS(X_ALL, SF_SET_PENDING);
+            nextop = F8;
+            GETGD;
+            GETED(0);
+            MV(x9, ed);
+            emit_add32(dyn, ninst, rex, ed, gd, x4, x5, x6);
+            MV(gd, x9);
+            WBACK;
+            break;
         case 0xC2:
             INST_NAME("CMPPS Gx, Ex, Ib");
             nextop = F8;
diff --git a/src/dynarec/rv64/dynarec_rv64_66.c b/src/dynarec/rv64/dynarec_rv64_66.c
index afa34d48..67c046a0 100644
--- a/src/dynarec/rv64/dynarec_rv64_66.c
+++ b/src/dynarec/rv64/dynarec_rv64_66.c
@@ -179,6 +179,18 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
             emit_sbb16(dyn, ninst, x1, x2, x3, x4, x5);
             GWBACK;
             break;
+        case 0x1D:
+            INST_NAME("SBB AX, Iw");
+            READFLAGS(X_CF);
+            SETFLAGS(X_ALL, SF_SET_PENDING);
+            ZEXTH(x1, xRAX);
+            i16 = F16;
+            MOV64xw(x2, i16);
+            emit_sbb16(dyn, ninst, x1, x2, x3, x4, x5);
+            SRLI(xRAX, xRAX, 16);
+            SLLI(xRAX, xRAX, 16);
+            OR(xRAX, xRAX, x1);
+            break;
         case 0x21:
             INST_NAME("AND Ew, Gw");
             SETFLAGS(X_ALL, SF_SET_PENDING);
@@ -990,6 +1002,34 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                     CALL_(ror16, x1, x3);
                     EWBACK;
                     break;
+                case 2:
+                    if(opcode==0xD1) {
+                        INST_NAME("RCL Ew, 1");
+                        MOV32w(x2, 1);
+                    } else {
+                        INST_NAME("RCL Ew, CL");
+                        ANDI(x2, xRCX, 15);
+                    }
+                    MESSAGE("LOG_DUMP", "Need optimization\n");
+                    READFLAGS(X_CF);
+                    SETFLAGS(X_OF|X_CF, SF_SET);
+                    GETEW(x1, 1);
+                    CALL_(rcl16, x1, x3);
+                    EWBACK;
+                case 3:
+                    if(opcode==0xD1) {
+                        INST_NAME("RCR Ew, 1");
+                        MOV32w(x2, 1);
+                    } else {
+                        INST_NAME("RCR Ew, CL");
+                        ANDI(x2, xRCX, 15);
+                    }
+                    MESSAGE("LOG_DUMP", "Need optimization\n");
+                    READFLAGS(X_CF);
+                    SETFLAGS(X_OF|X_CF, SF_SET);
+                    GETEW(x1, 1);
+                    CALL_(rcr16, x1, x3);
+                    EWBACK;
                 case 5:
                     if(opcode==0xD1) {
                         INST_NAME("SHR Ew, 1");
diff --git a/src/dynarec/rv64/dynarec_rv64_660f.c b/src/dynarec/rv64/dynarec_rv64_660f.c
index e13e775d..59b2ad39 100644
--- a/src/dynarec/rv64/dynarec_rv64_660f.c
+++ b/src/dynarec/rv64/dynarec_rv64_660f.c
@@ -2074,6 +2074,23 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
             ZEXTH(x2, x2);
             GWBACK;
             break;
+        case 0xB3:
+            INST_NAME("BTR Ew, Gw");
+            SETFLAGS(X_CF, SF_SUBSET);
+            SET_DFNONE();
+            nextop = F8;
+            GETEW(x1, 0);
+            GETGW(x2);
+            ANDI(gd, gd, 15);
+            BEXT(x4, ed, gd, x3); // F_CF is 1
+            ANDI(xFlags, xFlags, ~1);
+            OR(xFlags, xFlags, x4);
+            ADDI(x4, xZR, 1);
+            SLL(x4, x4, gd);
+            NOT(x4, x4);
+            AND(ed, ed, x4);
+            EWBACK;
+            break;
         case 0xB6:
             INST_NAME("MOVZX Gw, Eb");
             nextop = F8;
@@ -2114,6 +2131,72 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
                     ANDI(xFlags, xFlags, ~1);
                     OR(xFlags, xFlags, x3);
                     break;
+                case 5:
+                    INST_NAME("BTS Ew, Ib");
+                    SETFLAGS(X_CF, SF_SUBSET);
+                    SET_DFNONE();
+                    GETEW(x1, 1);
+                    u8 = F8;
+                    u8 &= (rex.w ? 0x3f : 15);
+                    ORI(xFlags, xFlags, 1 << F_CF);
+                    if (u8 <= 10) {
+                        ANDI(x6, ed, 1 << u8);
+                        BNE_MARK(x6, xZR);
+                        ANDI(xFlags, xFlags, ~(1 << F_CF));
+                        XORI(ed, ed, 1 << u8);
+                    } else {
+                        ORI(x6, xZR, 1);
+                        SLLI(x6, x6, u8);
+                        AND(x4, ed, x6);
+                        BNE_MARK(x4, xZR);
+                        ANDI(xFlags, xFlags, ~(1 << F_CF));
+                        XOR(ed, ed, x6);
+                    }
+                    EWBACK;
+                    MARK;
+                    break;
+                case 6:
+                    INST_NAME("BTR Ed, Ib");
+                    SETFLAGS(X_CF, SF_SUBSET);
+                    SET_DFNONE();
+                    GETEW(x1, 1);
+                    u8 = F8;
+                    u8 &= (rex.w ? 0x3f : 15);
+                    ANDI(xFlags, xFlags, ~(1 << F_CF));
+                    if (u8 <= 10) {
+                        ANDI(x6, ed, 1 << u8);
+                        BEQ_MARK(x6, xZR);
+                        ORI(xFlags, xFlags, 1 << F_CF);
+                        XORI(ed, ed, 1 << u8);
+                    } else {
+                        ORI(x6, xZR, 1);
+                        SLLI(x6, x6, u8);
+                        AND(x6, ed, x6);
+                        BEQ_MARK(x6, xZR);
+                        ORI(xFlags, xFlags, 1 << F_CF);
+                        XOR(ed, ed, x6);
+                    }
+                    EWBACK;
+                    MARK;
+                    break;
+                case 7:
+                    INST_NAME("BTC Ew, Ib");
+                    SETFLAGS(X_CF, SF_SUBSET);
+                    SET_DFNONE();
+                    GETEW(x1, 1);
+                    u8 = F8;
+                    u8 &= rex.w ? 0x3f : 15;
+                    BEXTI(x3, ed, u8); // F_CF is 1
+                    ANDI(xFlags, xFlags, ~1);
+                    OR(xFlags, xFlags, x3);
+                    if (u8 <= 10) {
+                        XORI(ed, ed, (1LL << u8));
+                    } else {
+                        MOV64xw(x3, (1LL << u8));
+                        XOR(ed, ed, x3);
+                    }
+                    EWBACK;
+                    break;
                 default:
                     DEFAULT;
             }
@@ -2174,42 +2257,42 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
             ANDI(xFlags, xFlags, ~(1 << F_ZF));
             GWBACK;
             break;
-        // case 0xBD:
-        //     INST_NAME("BSR Gw, Ew");
-        //     SETFLAGS(X_ZF, SF_SUBSET);
-        //     SET_DFNONE();
-        //     nextop = F8;
-        //     GETEW(x5, 0);
-        //     GETGW(x4);
-        //     BNE_MARK(ed, xZR);
-        //     ORI(xFlags, xFlags, 1 << F_ZF);
-        //     B_NEXT_nocond;
-        //     MARK;
-        //     ANDI(xFlags, xFlags, ~(1 << F_ZF));
-        //     if (rv64_zbb) {
-        //         MOV32w(x1, 31);
-        //         CLZxw(gd, ed);
-        //         SUB(gd, x1, gd);
-        //     } else {
-        //         u8 = gd;
-        //         ADDI(u8, xZR, 0);
-        //         AND(x2, ed, xMASK);
-        //         SRLI(x3, x2, 8);
-        //         BEQZ(x3, 4 + 2 * 4);
-        //         ADDI(u8, u8, 8);
-        //         MV(x2, x3);
-        //         SRLI(x3, x2, 4);
-        //         BEQZ(x3, 4 + 2 * 4);
-        //         ADDI(u8, u8, 4);
-        //         MV(x2, x3);
-        //         ANDI(x2, x2, 0b1111);
-        //         TABLE64(x3, (uintptr_t)&lead0tab);
-        //         ADD(x3, x3, x2);
-        //         LBU(x2, x3, 0);
-        //         ADD(gd, u8, x2);
-        //     }
-        //     GWBACK;
-        //     break;
+        case 0xBD:
+            INST_NAME("BSR Gw, Ew");
+            SETFLAGS(X_ZF, SF_SUBSET);
+            SET_DFNONE();
+            nextop = F8;
+            GETEW(x5, 0);
+            GETGW(x4);
+            BNE_MARK(ed, xZR);
+            ORI(xFlags, xFlags, 1 << F_ZF);
+            B_NEXT_nocond;
+            MARK;
+            ANDI(xFlags, xFlags, ~(1 << F_ZF));
+            if (rv64_zbb) {
+                MOV32w(x1, rex.w ? 63 : 31);
+                CLZxw(gd, ed);
+                SUB(gd, x1, gd);
+            } else {
+                u8 = gd;
+                ADDI(u8, xZR, 0);
+                AND(x2, ed, xMASK);
+                SRLI(x3, x2, 8);
+                BEQZ(x3, 4 + 2 * 4);
+                ADDI(u8, u8, 8);
+                MV(x2, x3);
+                SRLI(x3, x2, 4);
+                BEQZ(x3, 4 + 2 * 4);
+                ADDI(u8, u8, 4);
+                MV(x2, x3);
+                ANDI(x2, x2, 0b1111);
+                TABLE64(x3, (uintptr_t)&lead0tab);
+                ADD(x3, x3, x2);
+                LBU(x2, x3, 0);
+                ADD(gd, u8, x2);
+            }
+            GWBACK;
+            break;
         case 0xBE:
             INST_NAME("MOVSX Gw, Eb");
             nextop = F8;