about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorxctan <xctan@cirno.icu>2023-03-24 15:15:44 +0800
committerGitHub <noreply@github.com>2023-03-24 08:15:44 +0100
commitfdf43e58747f06f69096d4ca40cb633fd0393470 (patch)
tree773fb876f12e09c023d54723e2c6c674ec627d35 /src
parentdcc1a5db5274c2f23a342c5c8d4fe26e51723cb9 (diff)
downloadbox64-fdf43e58747f06f69096d4ca40cb633fd0393470.tar.gz
box64-fdf43e58747f06f69096d4ca40cb633fd0393470.zip
[RV64_DYNAREC] Added more opcodes and optimize printer output (#630)
* [RV64_DYNAREC] Added 08 OR opcode

* [RV64_DYNAREC] Improve printer output readability

* [RV64_DYNAREC] Added 66 0F BE MOVSX opcode

* [RV64_DYNAREC] Added 66 2B SUB opcode

* [RV64_DYNAREC] Optimize printer output for auipc

* [RV64_DYNAREC] Added F6 /6 DIV opcode

* [RV64_DYNAREC] Added 66 35 XOR opcode

* [RV64_DYNAREC] Fixed 66 0F BE MOVSX opcode
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/rv64/dynarec_rv64_00.c16
-rw-r--r--src/dynarec/rv64/dynarec_rv64_66.c23
-rw-r--r--src/dynarec/rv64/dynarec_rv64_660f.c28
-rw-r--r--src/dynarec/rv64/dynarec_rv64_emit_logic.c31
-rw-r--r--src/dynarec/rv64/dynarec_rv64_helper.h2
-rw-r--r--src/dynarec/rv64/rv64_printer.c41
6 files changed, 135 insertions, 6 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_00.c b/src/dynarec/rv64/dynarec_rv64_00.c
index 89b4305c..ff009df7 100644
--- a/src/dynarec/rv64/dynarec_rv64_00.c
+++ b/src/dynarec/rv64/dynarec_rv64_00.c
@@ -79,6 +79,15 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
             emit_add32c(dyn, ninst, rex, xRAX, i64, x3, x4, x5, x6);
             break;
 
+        case 0x08:
+            INST_NAME("OR Eb, Gb");
+            SETFLAGS(X_ALL, SF_SET_PENDING);
+            nextop = F8;
+            GETEB(x1, 0);
+            GETGB(x3);
+            emit_or8(dyn, ninst, x1, x3, x4, x5);
+            EBBACK(x5);
+            break;
         case 0x09:
             INST_NAME("OR Ed, Gd");
             SETFLAGS(X_ALL, SF_SET_PENDING);
@@ -1359,6 +1368,13 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                     SRLI(x1, x1, 48);
                     OR(xRAX, xRAX, x1);
                     break;
+                case 6:
+                    INST_NAME("DIV Eb");
+                    MESSAGE(LOG_DUMP, "Need Optimization\n");
+                    SETFLAGS(X_ALL, SF_SET);
+                    GETEB(x1, 0);
+                    CALL(div8, -1);
+                    break;
                 default:
                     DEFAULT;
             }
diff --git a/src/dynarec/rv64/dynarec_rv64_66.c b/src/dynarec/rv64/dynarec_rv64_66.c
index 2a6f8ad1..13e4a32c 100644
--- a/src/dynarec/rv64/dynarec_rv64_66.c
+++ b/src/dynarec/rv64/dynarec_rv64_66.c
@@ -97,6 +97,15 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
             AND(xRAX, xRAX, x3);
             OR(xRAX, xRAX, x1);
             break;
+        case 0x2B:
+            INST_NAME("SUB Gw, Ew");
+            SETFLAGS(X_ALL, SF_SET_PENDING);
+            nextop = F8;
+            GETGW(x1);
+            GETEW(x2, 0);
+            emit_sub16(dyn, ninst, x1, x2, x3, x4, x5);
+            GWBACK;
+            break;
         case 0x2D:
             INST_NAME("SUB AX, Iw");
             SETFLAGS(X_ALL, SF_SET_PENDING);
@@ -109,6 +118,20 @@ 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 0x35:
+            INST_NAME("XOR AX, Iw");
+            SETFLAGS(X_ALL, SF_SET_PENDING);
+            i32 = F16;
+            SLLI(x1, x1, 48);
+            SRLI(x1, x1, 48);
+            MOV32w(x2, i32);
+            emit_xor16(dyn, ninst, x1, x2, x3, x4, x5);
+            LUI(x5, 0xffff0);
+            AND(xRAX, xRAX, x5);
+            OR(xRAX, xRAX, x1);
+            break;
+
         case 0x3D:
             INST_NAME("CMP AX, Iw");
             SETFLAGS(X_ALL, SF_SET_PENDING);
diff --git a/src/dynarec/rv64/dynarec_rv64_660f.c b/src/dynarec/rv64/dynarec_rv64_660f.c
index 83569f0e..aabaa019 100644
--- a/src/dynarec/rv64/dynarec_rv64_660f.c
+++ b/src/dynarec/rv64/dynarec_rv64_660f.c
@@ -94,6 +94,34 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
             GWBACK;
             break;
 
+        case 0xBE:
+            INST_NAME("MOVSX Gw, Eb");
+            nextop = F8;
+            GETGD;
+            if(MODREG) {
+                if(rex.rex) {
+                    ed = xRAX+(nextop&7)+(rex.b<<3);
+                    eb1=ed;
+                    eb2=0;
+                } else {
+                    ed = (nextop&7);
+                    eb1 = xRAX+(ed&3);  // Ax, Cx, Dx or Bx
+                    eb2 = (ed&4)>>2;    // L or H
+                }
+                SLLI(x1, eb1, 56-eb2*8);
+                SRAI(x1, x1, 56);
+            } else {
+                SMREAD();
+                addr = geted(dyn, addr, ninst, nextop, &ed, x2, x4, &fixedaddress, rex, NULL, 0, 0);
+                LB(x1, ed, fixedaddress);
+            }
+            LUI(x5, 0xffff0);
+            AND(gd, gd, x5);
+            NOT(x5, x5);
+            AND(x1, x1, x5);
+            OR(gd, gd, x1);
+            break;
+
         default:
             DEFAULT;
     }
diff --git a/src/dynarec/rv64/dynarec_rv64_emit_logic.c b/src/dynarec/rv64/dynarec_rv64_emit_logic.c
index c3f09ea4..981c5141 100644
--- a/src/dynarec/rv64/dynarec_rv64_emit_logic.c
+++ b/src/dynarec/rv64/dynarec_rv64_emit_logic.c
@@ -96,6 +96,37 @@ void emit_xor32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i
     }
 }
 
+// emit XOR16 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed)
+void emit_xor16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5)
+{
+    CLEAR_FLAGS();
+    IFX(X_PEND) {
+        SET_DF(s4, d_xor16);
+    } else IFX(X_ALL) {
+        SET_DFNONE();
+    }
+
+    XOR(s1, s1, s2);
+
+    IFX(X_PEND) {
+        SH(s1, xEmu, offsetof(x64emu_t, res));
+    }
+    IFX(X_ZF | X_SF) {
+        SLLI(s3, s1, 48);
+        IFX(X_ZF) {
+            BNEZ(s3, 8);
+            ORI(xFlags, xFlags, 1 << F_ZF);
+        }
+        IFX(X_SF) {
+            BGE(s3, xZR, 8);
+            ORI(xFlags, xFlags, 1 << F_SF);
+        }
+    }
+    IFX(X_PF) {
+        emit_pf(dyn, ninst, s1, s3, s4);
+    }
+}
+
 // emit OR16 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed)
 void emit_or16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4) {
     CLEAR_FLAGS();
diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h
index d0f0b41d..23d4078b 100644
--- a/src/dynarec/rv64/dynarec_rv64_helper.h
+++ b/src/dynarec/rv64/dynarec_rv64_helper.h
@@ -792,7 +792,7 @@ void emit_sub16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4,
 //void emit_sub16c(dynarec_rv64_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
 void emit_or16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4);
 //void emit_or16c(dynarec_rv64_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
-//void emit_xor16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4);
+void emit_xor16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5);
 //void emit_xor16c(dynarec_rv64_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
 void emit_and16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4);
 //void emit_and16c(dynarec_rv64_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
diff --git a/src/dynarec/rv64/rv64_printer.c b/src/dynarec/rv64/rv64_printer.c
index 98db51d7..21cc8554 100644
--- a/src/dynarec/rv64/rv64_printer.c
+++ b/src/dynarec/rv64/rv64_printer.c
@@ -408,6 +408,7 @@ static inline insn_t insn_ciwtype_read(uint16_t data)
 #define RN(r) insn.f ? fpnames[insn.r] : gpnames[insn.r]
 
 #define PRINT_none() snprintf(buff, sizeof(buff), "%s", insn.name); return buff
+#define PRINT_rd_rs1() snprintf(buff, sizeof(buff), "%s\t%s, %s", insn.name, RN(rd), RN(rs1)); return buff
 #define PRINT_rd_rs1_rs2() snprintf(buff, sizeof(buff), "%s\t%s, %s, %s", insn.name, RN(rd), RN(rs1), RN(rs2)); return buff
 #define PRINT_rd_rs1_rs2_rs3() snprintf(buff, sizeof(buff), "%s\t%s, %s, %s, %s", insn.name, RN(rd), RN(rs1), RN(rs2), RN(rs3)); return buff
 #define PRINT_rd_rs1_imm() snprintf(buff, sizeof(buff), "%s\t%s, %s, %d", insn.name, RN(rd), RN(rs1), insn.imm); return buff
@@ -415,8 +416,11 @@ static inline insn_t insn_ciwtype_read(uint16_t data)
 #define PRINT_rd_imm_rs1() snprintf(buff, sizeof(buff), "%s\t%s, %d(%s)", insn.name, RN(rd), insn.imm, gpnames[insn.rs1]); return buff
 #define PRINT_rs2_imm_rs1() snprintf(buff, sizeof(buff), "%s\t%s, %d(%s)", insn.name, RN(rs2), insn.imm, gpnames[insn.rs1]); return buff
 #define PRINT_rd_imm() snprintf(buff, sizeof(buff), "%s\t%s, %d", insn.name, RN(rd), insn.imm); return buff
+#define PRINT_rd_imm_rel() snprintf(buff, sizeof(buff), "%s\t%s, pc%+d # 0x%llx", insn.name, RN(rd), insn.imm, insn.imm+(uint64_t)addr); return buff
+#define PRINT_imm_rel() snprintf(buff, sizeof(buff), "%s\tpc%+d # 0x%llx", insn.name, insn.imm, insn.imm+(uint64_t)addr); return buff
 #define PRINT_rd_immx() snprintf(buff, sizeof(buff), "%s\t%s, 0x%x", insn.name, RN(rd), insn.imm); return buff
 #define PRINT_rs1_rs2_imm() snprintf(buff, sizeof(buff), "%s\t%s, %s, %d", insn.name, RN(rs1), RN(rs2), insn.imm); return buff
+#define PRINT_rs1_rs2_imm_rel() snprintf(buff, sizeof(buff), "%s\t%s, %s, pc%+d # 0x%llx", insn.name, RN(rs1), RN(rs2), insn.imm, insn.imm+(uint64_t)addr); return buff
 #define PRINT_fd_fs1() snprintf(buff, sizeof(buff), "%s\t%s, %s", insn.name, fpnames[insn.rd], fpnames[insn.rs1]); return buff
 #define PRINT_xd_fs1() snprintf(buff, sizeof(buff), "%s\t%s, %s", insn.name, gpnames[insn.rd], fpnames[insn.rs1]); return buff
 #define PRINT_fd_xs1() snprintf(buff, sizeof(buff), "%s\t%s, %s", insn.name, fpnames[insn.rd], gpnames[insn.rs1]); return buff
@@ -731,12 +735,24 @@ const char* rv64_print(uint32_t data, uintptr_t addr)
         }
         case 0x4: {
             int hex = 0;
+            int mv_alias = 0;
+            int nop_alias = 0;
+            int not_alias = 0;
             uint32_t funct3 = FUNCT3(data);
 
             insn =  insn_itype_read(data);
             switch (funct3) {
             case 0x0: /* ADDI */
                 insn.name = "addi";
+                if (insn.imm == 0) {
+                    if (insn.rd == 0 && insn.rs1 == 0) {
+                        nop_alias = 1;
+                        insn.name = "nop";
+                    } else {
+                        mv_alias = 1;
+                        insn.name = "mv";
+                    }
+                }
                 break;
             case 0x1: {
                 uint32_t imm116 = IMM116(data);
@@ -754,6 +770,10 @@ const char* rv64_print(uint32_t data, uintptr_t addr)
             case 0x4: /* XORI */
                 insn.name = "xori";
                 hex = 1;
+                if (insn.imm == -1) {
+                    not_alias = 1;
+                    insn.name = "not";
+                }
                 break;
             case 0x5: {
                 uint32_t imm116 = IMM116(data);
@@ -775,7 +795,13 @@ const char* rv64_print(uint32_t data, uintptr_t addr)
                 hex = 1;
                 break;
             }
-            if(hex) {
+            if (not_alias) {
+                PRINT_rd_rs1();
+            } else if (nop_alias) {
+                PRINT_none();
+            } else if (mv_alias) {
+                PRINT_rd_rs1();
+            } else if(hex) {
                 PRINT_rd_rs1_immx();
             } else {
                 PRINT_rd_rs1_imm();
@@ -784,7 +810,7 @@ const char* rv64_print(uint32_t data, uintptr_t addr)
         case 0x5: /* AUIPC */
             insn =  insn_utype_read(data);
             insn.name = "auipc";
-            PRINT_rd_imm();
+            PRINT_rd_imm_rel();
         case 0x6: {
             uint32_t funct3 = FUNCT3(data);
             uint32_t funct7 = FUNCT7(data);
@@ -1352,7 +1378,7 @@ const char* rv64_print(uint32_t data, uintptr_t addr)
                 break;
             }
 
-            PRINT_rs1_rs2_imm();
+            PRINT_rs1_rs2_imm_rel();
         }
         case 0x19: /* JALR */
             insn =  insn_itype_read(data);
@@ -1360,8 +1386,13 @@ const char* rv64_print(uint32_t data, uintptr_t addr)
             PRINT_rd_imm_rs1();
         case 0x1b: /* JAL */
             insn =  insn_jtype_read(data);
-            insn.name = "jal";
-            PRINT_rd_imm();
+            if (insn.rd != 0) {
+                insn.name = "jal";
+                PRINT_rd_imm_rel();
+            } else {
+                insn.name = "j";
+                PRINT_imm_rel();
+            }
         case 0x1c: {
             if (data == 0x73) { /* ECALL */
                 insn.name = "ecall";