about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorYang Liu <liuyang22@iscas.ac.cn>2023-03-22 14:47:56 +0800
committerGitHub <noreply@github.com>2023-03-22 07:47:56 +0100
commit3656cd66ea13833e9959598862e7a1e334bea6a0 (patch)
tree48189638842a62b4fc22a36313b0546a88c34540 /src
parentda88b872790f838ad85f979a7153658bf746479a (diff)
downloadbox64-3656cd66ea13833e9959598862e7a1e334bea6a0.tar.gz
box64-3656cd66ea13833e9959598862e7a1e334bea6a0.zip
[RV64_DYNAREC] Added more opcode (#612)
* [RV64_DYNAREC] Added 66 {90:97} NOP opcode

* [RV64_DYNAREC] Added more 16bit opcodes
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/rv64/dynarec_rv64_66.c49
-rw-r--r--src/dynarec/rv64/dynarec_rv64_emit_logic.c29
-rw-r--r--src/dynarec/rv64/dynarec_rv64_emit_tests.c29
-rw-r--r--src/dynarec/rv64/dynarec_rv64_helper.h6
4 files changed, 109 insertions, 4 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_66.c b/src/dynarec/rv64/dynarec_rv64_66.c
index efa69ca8..0cd1f5e8 100644
--- a/src/dynarec/rv64/dynarec_rv64_66.c
+++ b/src/dynarec/rv64/dynarec_rv64_66.c
@@ -65,7 +65,18 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
         case 0x0F:
             addr = dynarec64_660F(dyn, addr, ip, ninst, rex, ok, need_epilog);
             break;
-
+        case 0x25:
+            INST_NAME("AND AX, Iw");
+            SETFLAGS(X_ALL, SF_SET_PENDING);
+            i32 = F16;
+            SLLI(x1, xRAX, 48);
+            SRLI(x1, x1, 48);
+            MOV32w(x2, i32);
+            emit_and16(dyn, ninst, x1, x2, x3, x4);
+            LUI(x3, 0xfff0);
+            AND(xRAX, xRAX, x3);
+            OR(xRAX, xRAX, x1);
+            break;
         case 0x3D:
             INST_NAME("CMP AX, Iw");
             SETFLAGS(X_ALL, SF_SET_PENDING);
@@ -115,6 +126,14 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                     DEFAULT;
             }
             break;
+        case 0x85:
+            INST_NAME("TEST Ew, Gw");
+            SETFLAGS(X_ALL, SF_SET_PENDING);
+            nextop = F8;
+            GETEW(x1, 0);
+            GETGW(x2);
+            emit_test16(dyn, ninst, x1, x2, x3, x4, x5);
+            break;
         case 0x89:
             INST_NAME("MOV Ew, Gw");
             nextop = F8;
@@ -135,6 +154,34 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                 SMWRITELOCK(lock);
             }
             break;
+            case 0x90:
+            case 0x91:
+            case 0x92:
+            case 0x93:
+            case 0x94:
+            case 0x95:
+            case 0x96:
+            case 0x97:
+                gd = xRAX+(opcode&0x07)+(rex.b<<3);
+                if(gd==xRAX) {
+                    INST_NAME("NOP");
+                } else {
+                    INST_NAME("XCHG AX, Reg");
+                    LUI(x4, 0xfff0);
+                    // x2 <- rax
+                    MV(x2, xRAX);
+                    // rax[15:0] <- gd[15:0]
+                    SLLI(x3, gd, 48);
+                    SRLI(x3, x3, 48);
+                    AND(xRAX, xRAX, x4);
+                    OR(xRAX, xRAX, x3);
+                    // gd[15:0] <- x2[15:0]
+                    SLLI(x2, x2, 48);
+                    SRLI(x2, x2, 48);
+                    AND(gd, gd, x4);
+                    OR(gd, gd, x2);
+                }
+            break;
         case 0xC1:
             nextop = F8;
             switch((nextop>>3)&7) {
diff --git a/src/dynarec/rv64/dynarec_rv64_emit_logic.c b/src/dynarec/rv64/dynarec_rv64_emit_logic.c
index 78bdac67..495453e0 100644
--- a/src/dynarec/rv64/dynarec_rv64_emit_logic.c
+++ b/src/dynarec/rv64/dynarec_rv64_emit_logic.c
@@ -229,6 +229,33 @@ void emit_and8c(dynarec_rv64_t* dyn, int ninst, int s1, int32_t c, int s3, int s
     }
 }
 
+void emit_and16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4) {
+    CLEAR_FLAGS();
+    IFX(X_PEND) {
+        SET_DF(s3, d_tst16);
+    } else IFX(X_ALL) {
+        SET_DFNONE();
+    }
+
+    AND(s1, s1, s2); // res = s1 & s2
+
+    IFX(X_PEND) {
+        SH(s1, xEmu, offsetof(x64emu_t, res));
+    }
+    IFX(X_SF) {
+        SRLI(s3, s1, 15);
+        BEQZ(s3, 8);
+        ORI(xFlags, xFlags, 1 << F_SF);
+    }
+    IFX(X_ZF) {
+        BNEZ(s1, 8);
+        ORI(xFlags, xFlags, 1 << F_ZF);
+    }
+    IFX(X_PF) {
+        emit_pf(dyn, ninst, s1, s3, s4);
+    }
+}
+
 // emit AND32 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
 void emit_and32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4)
 {
@@ -321,4 +348,4 @@ void emit_or8(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4)
     IFX(X_PF) {
         emit_pf(dyn, ninst, s1, s3, s4);
     }
-}
\ No newline at end of file
+}
diff --git a/src/dynarec/rv64/dynarec_rv64_emit_tests.c b/src/dynarec/rv64/dynarec_rv64_emit_tests.c
index 9b0bcf09..0abb5be2 100644
--- a/src/dynarec/rv64/dynarec_rv64_emit_tests.c
+++ b/src/dynarec/rv64/dynarec_rv64_emit_tests.c
@@ -251,6 +251,35 @@ void emit_test8(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4,
     }
 }
 
+// emit TEST16 instruction, from test s1, s2, using s3, s4 and s5 as scratch
+void emit_test16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5)
+{
+    CLEAR_FLAGS();
+    IFX_PENDOR0 {
+        SET_DF(s3, d_tst16);
+    } else {
+        SET_DFNONE();
+    }
+
+    AND(s3, s1, s2); // res = s1 & s2
+
+    IFX_PENDOR0 {
+        SH(s3, xEmu, offsetof(x64emu_t, res));
+    }
+    IFX(X_SF) {
+        SRLI(s4, s3, 15);
+        BEQZ(s4, 8);
+        ORI(xFlags, xFlags, 1 << F_SF);
+    }
+    IFX(X_ZF) {
+        BNEZ(s3, 8);
+        ORI(xFlags, xFlags, 1 << F_ZF);
+    }
+    IFX(X_PF) {
+        emit_pf(dyn, ninst, s3, s4, s5);
+    }
+}
+
 // emit TEST32 instruction, from test s1, s2, using s3 and s4 as scratch
 void emit_test32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5)
 {
diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h
index fd369085..0ab1a76d 100644
--- a/src/dynarec/rv64/dynarec_rv64_helper.h
+++ b/src/dynarec/rv64/dynarec_rv64_helper.h
@@ -109,6 +109,8 @@
                     LDxw(hint, wback, fixedaddress);    \
                     ed = hint;                          \
                 }
+// GETGW extract x64 register in gd, that is i
+#define GETGW(i) gd = xRAX+((nextop&0x38)>>3)+(rex.r<<3); SLLI(i, gd, 48); SRLI(i, i, 48); gd = i;
 //GETEWW will use i for ed, and can use w for wback.
 #define GETEWW(w, i, D) if(MODREG) {        \
                     wback = xRAX+(nextop&7)+(rex.b<<3);\
@@ -717,7 +719,7 @@ void emit_cmp8_0(dynarec_rv64_t* dyn, int ninst, int s1, int s3, int s4);
 void emit_cmp16_0(dynarec_rv64_t* dyn, int ninst, int s1, int s3, int s4);
 void emit_cmp32_0(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s3, int s4);
 void emit_test8(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5);
-//void emit_test16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5);
+void emit_test16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5);
 void emit_test32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5);
 void emit_test32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4, int s5);
 void emit_add32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5);
@@ -748,7 +750,7 @@ 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_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_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);
 void emit_inc32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5);
 //void emit_inc16(dynarec_rv64_t* dyn, int ninst, int s1, int s3, int s4);