about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorYang Liu <liuyang22@iscas.ac.cn>2023-03-24 20:12:42 +0800
committerGitHub <noreply@github.com>2023-03-24 13:12:42 +0100
commit45015d6106133b940cbb5f24e08aac4d70bd7de8 (patch)
tree712b816d0bf866fa6ae61db4048c9a30242ec16b /src
parentc3223245e561f1f78c4e2b053c43a14929df615e (diff)
downloadbox64-45015d6106133b940cbb5f24e08aac4d70bd7de8.tar.gz
box64-45015d6106133b940cbb5f24e08aac4d70bd7de8.zip
[RV64_DYNAREC] Added more opcodes & some fixes & some optimizations (#632)
* [RV64_DYNAREC] Added 66 D1,D3 SAR opcode

* [RV64_DYNAREC] Added 66 F7 /7 IDIV opcode

* [RV64_DYNAREC] Fixed 32 XOR opcode

* [RV64_DYNAREC] Some small optims

* [RV64_DYNAREC] Added 66 33 XOR opcode

* [RV64_DYNAREC] Added 66 81,83 /6 XOR opcode

* [RV64_DYNAREC] Added 66 31 XOR opcode

* [RV64_DYNAREC] Fixed a typo in IDIV opcode

* [RV64_DYNAREC] Added A4 REP MOVSB opcode

* [RV64_DYNAREC] Fixed 66 35 XOR opcode

* [RV64_DYNAREC] Added 66 39 CMP opcode

* [RV64_DYNAREC] Added F6 /7 IDIV opcode

* [RV64_DYNAREC] Added 1C SBB opcode

* [RV64_DYNAREC] Added 66 05 ADD opcode
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/rv64/dynarec_rv64_00.c50
-rw-r--r--src/dynarec/rv64/dynarec_rv64_66.c97
-rw-r--r--src/dynarec/rv64/dynarec_rv64_helper.h10
3 files changed, 144 insertions, 13 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_00.c b/src/dynarec/rv64/dynarec_rv64_00.c
index e1455292..fb259259 100644
--- a/src/dynarec/rv64/dynarec_rv64_00.c
+++ b/src/dynarec/rv64/dynarec_rv64_00.c
@@ -153,6 +153,16 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
             emit_sbb32(dyn, ninst, rex, ed, gd, x3, x4, x5);
             WBACK;
             break;
+        case 0x1C:
+            INST_NAME("SBB AL, Ib");
+            READFLAGS(X_CF);
+            SETFLAGS(X_ALL, SF_SET_PENDING);
+            u8 = F8;
+            ANDI(x1, xRAX, 0xff);
+            emit_sbb8c(dyn, ninst, x1, u8, x3, x4, x5, x6);
+            ANDI(xRAX, xRAX, ~0xff);
+            OR(xRAX, xRAX, x1);
+            break;
         case 0x20:
             INST_NAME("AND Eb, Gb");
             SETFLAGS(X_ALL, SF_SET_PENDING);
@@ -244,7 +254,7 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
             nextop = F8;
             GETEB(x1, 0);
             GETGB(x3);
-            emit_xor8(dyn, ninst, x1, x3, x4, x5);
+            emit_xor8(dyn, ninst, x3, x1, x4, x5);
             GBBACK(x5);
             break;
         case 0x33:
@@ -742,6 +752,37 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                 ZEROUP(xRDX);
             }
             break;
+        case 0xA4:
+            if(rep) {
+                INST_NAME("REP MOVSB");
+                CBZ_NEXT(xRCX);
+                ANDI(x1, xFlags, 1<<F_DF);
+                BNEZ_MARK2(x1);
+                MARK;   // Part with DF==0
+                LBU(x1, xRSI, 0);
+                SB(x1, xRDI, 0);
+                ADDI(xRSI, xRSI, 1);
+                ADDI(xRDI, xRDI, 1);
+                SUBI(xRCX, xRCX, 1);
+                BNEZ_MARK(xRCX);
+                B_NEXT_nocond;
+                MARK2;  // Part with DF==1
+                LBU(x1, xRSI, 0);
+                LBU(x1, xRDI, 0);
+                SUBI(xRSI, xRSI, 1);
+                SUBI(xRDI, xRDI, 1);
+                SUBI(xRCX, xRCX, 1);
+                BNEZ_MARK2(xRCX);
+                // done
+            } else {
+                INST_NAME("MOVSB");
+                GETDIR(x3, x1, 1);
+                LBU(x1, xRSI, 0);
+                SB(x1, xRDI, 0);
+                ADD(xRSI, xRSI, x3);
+                ADD(xRDI, xRDI, x3);
+            }
+            break;
         case 0xA5:
             if(rep) {
                 INST_NAME("REP MOVSD");
@@ -1407,6 +1448,13 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                     GETEB(x1, 0);
                     CALL(div8, -1);
                     break;
+                case 7:
+                    INST_NAME("IDIV Eb");
+                    MESSAGE(LOG_DUMP, "Need Optimization\n");
+                    SETFLAGS(X_ALL, SF_SET);
+                    GETEB(x1, 0);
+                    CALL(idiv8, -1);
+                    break;
                 default:
                     DEFAULT;
             }
diff --git a/src/dynarec/rv64/dynarec_rv64_66.c b/src/dynarec/rv64/dynarec_rv64_66.c
index e296b662..5989f2bf 100644
--- a/src/dynarec/rv64/dynarec_rv64_66.c
+++ b/src/dynarec/rv64/dynarec_rv64_66.c
@@ -61,6 +61,18 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
         return dynarec64_00(dyn, addr-1, ip, ninst, rex, rep, ok, need_epilog); // addr-1, to "put back" opcode
 
     switch(opcode) {
+        case 0x05:
+            INST_NAME("ADD AX, Iw");
+            SETFLAGS(X_ALL, SF_SET_PENDING);
+            i32 = F16;
+            SLLI(x1 , xRAX, 48);
+            SRLI(x1, x1, 48);
+            MOV32w(x2, i32);
+            emit_add16(dyn, ninst, x1, x2, x3, x4);
+            LUI(x3, 0xffff0);
+            AND(xRAX, xRAX, x3);
+            OR(xRAX, xRAX, x1);
+            break;
         case 0x0B:
             INST_NAME("OR Gw, Ew");
             SETFLAGS(X_ALL, SF_SET_PENDING);
@@ -136,12 +148,29 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
             AND(xRAX, xRAX, x2);
             OR(xRAX, xRAX, x1);
             break;
-
+        case 0x31:
+            INST_NAME("XOR Ew, Gw");
+            SETFLAGS(X_ALL, SF_SET_PENDING);
+            nextop = F8;
+            GETGW(x2);
+            GETEW(x1, 0);
+            emit_xor16(dyn, ninst, x1, x2, x4, x5, x6);
+            EWBACK;
+            break;
+        case 0x33:
+            INST_NAME("XOR Gw, Ew");
+            SETFLAGS(X_ALL, SF_SET_PENDING);
+            nextop = F8;
+            GETGW(x1);
+            GETEW(x2, 0);
+            emit_xor16(dyn, ninst, x1, x2, x4, x5, x6);
+            GWBACK;
+            break;
         case 0x35:
             INST_NAME("XOR AX, Iw");
             SETFLAGS(X_ALL, SF_SET_PENDING);
             i32 = F16;
-            SLLI(x1, x1, 48);
+            SLLI(x1, xRAX, 48);
             SRLI(x1, x1, 48);
             MOV32w(x2, i32);
             emit_xor16(dyn, ninst, x1, x2, x3, x4, x5);
@@ -149,7 +178,14 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
             AND(xRAX, xRAX, x5);
             OR(xRAX, xRAX, x1);
             break;
-
+        case 0x39:
+            INST_NAME("CMP Ew, Gw");
+            SETFLAGS(X_ALL, SF_SET_PENDING);
+            nextop = F8;
+            GETGW(x2);
+            GETEW(x1, 0);
+            emit_cmp16(dyn, ninst, x1, x2, x3, x4, x5, x6);
+            break;
         case 0x3D:
             INST_NAME("CMP AX, Iw");
             SETFLAGS(X_ALL, SF_SET_PENDING);
@@ -222,6 +258,15 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                     emit_sub16(dyn, ninst, x1, x5, x2, x4, x5);
                     EWBACK;
                     break;
+                case 6: // XOR
+                    if(opcode==0x81) {INST_NAME("XOR Ew, Iw");} else {INST_NAME("XOR Ew, Ib");}
+                    SETFLAGS(X_ALL, SF_SET_PENDING);
+                    GETEW(x1, (opcode==0x81)?2:1);
+                    if(opcode==0x81) i16 = F16S; else i16 = F8S;
+                    MOV32w(x5, i16);
+                    emit_xor16(dyn, ninst, x1, x5, x2, x4, x6);
+                    EWBACK;
+                    break;
                 case 7: // CMP
                     if(opcode==0x81) {INST_NAME("CMP Ew, Iw");} else {INST_NAME("CMP Ew, Ib");}
                     SETFLAGS(X_ALL, SF_SET_PENDING);
@@ -421,7 +466,31 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                 SMWRITELOCK(lock);
             }
             break;
-
+        case 0xD1:
+        case 0xD3:
+            nextop = F8;
+            switch((nextop>>3)&7) {
+                case 7:
+                    if(opcode==0xD1) {
+                        INST_NAME("SAR Ew, 1");
+                        MOV32w(x4, 1);
+                    } else {
+                        INST_NAME("SAR Ew, CL");
+                        ANDI(x4, xRCX, 0x1f);
+                    }
+                    UFLAG_IF {MESSAGE(LOG_DUMP, "Need Optimization for flags\n");}
+                    SETFLAGS(X_ALL, SF_PENDING);
+                    GETSEW(x1, 0);
+                    UFLAG_OP12(ed, x4)
+                    SRA(ed, ed, x4);
+                    EWBACK;
+                    UFLAG_RES(ed);
+                    UFLAG_DF(x3, d_sar16);
+                    break;
+                default:
+                    DEFAULT;
+            }
+            break;
         case 0xF7:
             nextop = F8;
             switch((nextop>>3)&7) {
@@ -454,6 +523,26 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                     OR(xRAX, xRAX, x3);
                     OR(xRDX, xRDX, x4);
                     break;
+                case 7:
+                    INST_NAME("IDIV Ew");
+                    SETFLAGS(X_ALL, SF_SET);
+                    GETSEW(x1, 0);
+                    SLLI(x2, xRAX, 48);
+                    SLLI(x3, xRDX, 48);
+                    SRLI(x2, x2, 48);
+                    SRLI(x3, x3, 32);
+                    OR(x2, x2, x3);
+                    DIVW(x3, x2, ed);
+                    REMW(x4, x2, ed);
+                    MOV64x(x5, ~0xffff);
+                    AND(xRAX, xRAX, x5);
+                    AND(xRDX, xRDX, x5);
+                    NOT(x5, x5);
+                    AND(x3, x3, x5);
+                    AND(x4, x4, x5);
+                    OR(xRAX, xRAX, x3);
+                    OR(xRDX, xRDX, x4);
+                    break;
                 default:
                     DEFAULT;
             }
diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h
index bcdbc840..55467e89 100644
--- a/src/dynarec/rv64/dynarec_rv64_helper.h
+++ b/src/dynarec/rv64/dynarec_rv64_helper.h
@@ -181,9 +181,7 @@
                         wb2 = (wback>>2)*8;     \
                         wback = xRAX+(wback&3); \
                     }                           \
-                    MV(i, wback);               \
-                    if (wb2) SRLI(i, i, wb2);   \
-                    ANDI(i, i, 0xff);           \
+                    if (wb2) {MV(i, wback); SRLI(i, i, wb2); ANDI(i, i, 0xff);} else ANDI(i, wback, 0xff);   \
                     wb1 = 0;                    \
                     ed = i;                     \
                 } else {                        \
@@ -226,21 +224,17 @@
                     gb1 = xRAX+(gd&3);                        \
                 }                                             \
                 gd = i;                                       \
-                MV(gd, gb1);                                  \
-                if (gb2) SRLI(gd, gd, gb2*8);                 \
-                ANDI(gd, gd, 0xff);
+                if (gb2) {MV(gd, gb1); SRLI(gd, gd, 8); ANDI(gd, gd, 0xff);} else ANDI(gd, gb1, 0xff);
 
 // Write gb (gd) back to original register / memory, using s1 as scratch
 #define GBBACK(s1) if(gb2) {                            \
                     assert(gb2 == 8);                   \
                     MOV64x(s1, 0xffffffffffff00ffLL);   \
                     AND(gb1, gb1, s1);                  \
-                    ANDI(gd, gd, 0xff);                 \
                     SLLI(s1, gd, 8);                    \
                     OR(gb1, gb1, s1);                   \
                 } else {                                \
                     ANDI(gb1, gb1, ~0xff);              \
-                    ANDI(gd, gd, 0xff);                 \
                     OR(gb1, gb1, gd);                   \
                 }