about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorYang Liu <liuyang22@iscas.ac.cn>2023-03-20 18:48:09 +0800
committerGitHub <noreply@github.com>2023-03-20 11:48:09 +0100
commit8f52a3a3cc6c07f197d32fca2067dd6b827fae27 (patch)
tree61e867558e138f2e97dd2525fec4256f8436c16d /src
parent61a6af1de7ea81b845115d22459247c90366cb05 (diff)
downloadbox64-8f52a3a3cc6c07f197d32fca2067dd6b827fae27.tar.gz
box64-8f52a3a3cc6c07f197d32fca2067dd6b827fae27.zip
[RV64_DYNAREC] Added 66 3D CMP opcode (#598)
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/rv64/dynarec_rv64_66.c13
-rw-r--r--src/dynarec/rv64/dynarec_rv64_emit_tests.c66
-rw-r--r--src/dynarec/rv64/dynarec_rv64_helper.h5
3 files changed, 81 insertions, 3 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_66.c b/src/dynarec/rv64/dynarec_rv64_66.c
index 86446b7a..9aaf4e2f 100644
--- a/src/dynarec/rv64/dynarec_rv64_66.c
+++ b/src/dynarec/rv64/dynarec_rv64_66.c
@@ -66,6 +66,19 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
             addr = dynarec64_660F(dyn, addr, ip, ninst, rex, ok, need_epilog);
             break;
 
+        case 0x3D:
+            INST_NAME("CMP AX, Iw");
+            SETFLAGS(X_ALL, SF_SET_PENDING);
+            i32 = F16;
+            SLLI(x1, xRAX, 48);
+            SRLI(x1, xRAX, 48);
+            if(i32) {
+                MOV32w(x2, i32);
+                emit_cmp16(dyn, ninst, x1, x2, x3, x4, x5, x6);
+            } else {
+                emit_cmp16_0(dyn, ninst, x1, x3, x4);
+            }
+            break;
         case 0x70:
         case 0x71:
         case 0x72:
diff --git a/src/dynarec/rv64/dynarec_rv64_emit_tests.c b/src/dynarec/rv64/dynarec_rv64_emit_tests.c
index 7ce0ae58..9b0bcf09 100644
--- a/src/dynarec/rv64/dynarec_rv64_emit_tests.c
+++ b/src/dynarec/rv64/dynarec_rv64_emit_tests.c
@@ -88,6 +88,72 @@ void emit_cmp8_0(dynarec_rv64_t* dyn, int ninst, int s1, int s3, int s4)
     }
 }
 
+// emit CMP16 instruction, from cmp s1, s2, using s3 and s4 as scratch
+void emit_cmp16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5, int s6)
+{
+    CLEAR_FLAGS();
+    IFX_PENDOR0 {
+        SH(s1, xEmu, offsetof(x64emu_t, op1));
+        SH(s2, xEmu, offsetof(x64emu_t, op2));
+        SET_DF(s4, d_cmp16);
+    } else {
+        SET_DFNONE();
+    }
+
+    IFX(X_AF | X_CF | X_OF) {
+        // for later flag calculation
+        NOT(s5, s1);
+    }
+
+    // It's a cmp, we can't store the result back to s1.
+    SUB(s6, s1, s2);
+    SLLI(s6, s6, 48);
+    SRLI(s6, s6, 48);
+    IFX_PENDOR0 {
+        SH(s6, xEmu, offsetof(x64emu_t, res));
+    }
+    IFX(X_SF) {
+        SRLI(s3, s6, 15);
+        BEQZ(s3, 8);
+        ORI(xFlags, xFlags, 1 << F_SF);
+    }
+    CALC_SUB_FLAGS(s5, s2, s6, s3, s4, 16);
+    IFX(X_ZF) {
+        BNEZ(s6, 8);
+        ORI(xFlags, xFlags, 1 << F_ZF);
+    }
+    IFX(X_PF) {
+        emit_pf(dyn, ninst, s6, s3, s4);
+    }
+}
+
+// emit CMP16 instruction, from cmp s1 , #0, using s3 and s4 as scratch
+void emit_cmp16_0(dynarec_rv64_t* dyn, int ninst, int s1, int s3, int s4)
+{
+    CLEAR_FLAGS();
+    IFX_PENDOR0 {
+        SH(s1, xEmu, offsetof(x64emu_t, op1));
+        SH(xZR, xEmu, offsetof(x64emu_t, op2));
+        SH(s1, xEmu, offsetof(x64emu_t, res));
+        SET_DF(s3, d_cmp16);
+    } else {
+        SET_DFNONE();
+    }
+
+    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 CMP32 instruction, from cmp s1, s2, using s3 and s4 as scratch
 void emit_cmp32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5, int s6)
 {
diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h
index fc526327..a27315b6 100644
--- a/src/dynarec/rv64/dynarec_rv64_helper.h
+++ b/src/dynarec/rv64/dynarec_rv64_helper.h
@@ -337,7 +337,6 @@
                 ANDI(scratch1, scratch2, 0x80);                           \
             } else {                                                      \
                 SRLI(scratch1, scratch2, (width)-1);                      \
-                if ((width) == 16) ANDI(scratch1, scratch1, 1);           \
             }                                                             \
             BEQZ(scratch1, 8);                                            \
             ORI(xFlags, xFlags, 1 << F_CF);                               \
@@ -650,10 +649,10 @@ void call_c(dynarec_rv64_t* dyn, int ninst, void* fnc, int reg, int ret, int sav
 void call_n(dynarec_rv64_t* dyn, int ninst, void* fnc, int w);
 void grab_segdata(dynarec_rv64_t* dyn, uintptr_t addr, int ninst, int reg, int segment);
 void emit_cmp8(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5, int s6);
-//void emit_cmp16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5);
+void emit_cmp16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5, int s6);
 void emit_cmp32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5, int s6);
 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_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);