about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorYang Liu <liuyang22@iscas.ac.cn>2023-03-15 23:11:28 +0800
committerGitHub <noreply@github.com>2023-03-15 16:11:28 +0100
commit9b2b603c8ddb2c4b94cbab8e5f02d11989641f5d (patch)
tree3bd703fed34b5ab6b118e4db6ebff17ffb1baea3 /src
parent6f85a204a9b913047ae322ba8a48dd85a98c9ab8 (diff)
downloadbox64-9b2b603c8ddb2c4b94cbab8e5f02d11989641f5d.tar.gz
box64-9b2b603c8ddb2c4b94cbab8e5f02d11989641f5d.zip
[RV64_DYNAREC] Added 80 /7 CMP opcode (#567)
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/rv64/dynarec_rv64_00.c20
-rw-r--r--src/dynarec/rv64/dynarec_rv64_emit_math.c4
-rw-r--r--src/dynarec/rv64/dynarec_rv64_emit_tests.c65
-rw-r--r--src/dynarec/rv64/dynarec_rv64_helper.h42
4 files changed, 120 insertions, 11 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_00.c b/src/dynarec/rv64/dynarec_rv64_00.c
index c7434831..f72e9f1b 100644
--- a/src/dynarec/rv64/dynarec_rv64_00.c
+++ b/src/dynarec/rv64/dynarec_rv64_00.c
@@ -108,7 +108,25 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                 ADDI(xRSP, xRSP, 8);
             }
             break;
-
+        case 0x80:
+            nextop = F8;
+            switch((nextop>>3)&7) {
+                case 7: // CMP
+                    INST_NAME("CMP Eb, Ib");
+                    SETFLAGS(X_ALL, SF_SET_PENDING);
+                    GETEB(x1, 1);
+                    u8 = F8;
+                    if(u8) {
+                        ADDI(x2, xZR, u8);
+                        emit_cmp8(dyn, ninst, x1, x2, x3, x4, x5, x6);
+                    } else {
+                        emit_cmp8_0(dyn, ninst, x1, x3, x4);
+                    }
+                    break;
+                default:
+                    DEFAULT;
+            }
+            break;
         case 0x81:
         case 0x83:
             nextop = F8;
diff --git a/src/dynarec/rv64/dynarec_rv64_emit_math.c b/src/dynarec/rv64/dynarec_rv64_emit_math.c
index 417d0ccf..51491555 100644
--- a/src/dynarec/rv64/dynarec_rv64_emit_math.c
+++ b/src/dynarec/rv64/dynarec_rv64_emit_math.c
@@ -146,7 +146,7 @@ void emit_sub32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
     if (!rex.w) {
         ZEROUP(s1);
     }
-    CALC_SUB_FLAGS(s5, s2, s1, s3, s4);
+    CALC_SUB_FLAGS(s5, s2, s1, s3, s4, rex.w?64:32);
     IFX(X_ZF) {
         BEQZ(s1, 4);
         ORI(xFlags, xFlags, 1 << F_ZF);
@@ -210,7 +210,7 @@ void emit_sub32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i
     if (!rex.w) {
         ZEROUP(s1);
     }
-    CALC_SUB_FLAGS(s5, s2, s1, s3, s4);
+    CALC_SUB_FLAGS(s5, s2, s1, s3, s4, rex.w?64:32);
     IFX(X_ZF) {
         BEQZ(s1, 4);
         ORI(xFlags, xFlags, 1 << F_ZF);
diff --git a/src/dynarec/rv64/dynarec_rv64_emit_tests.c b/src/dynarec/rv64/dynarec_rv64_emit_tests.c
index f4394800..6218aae6 100644
--- a/src/dynarec/rv64/dynarec_rv64_emit_tests.c
+++ b/src/dynarec/rv64/dynarec_rv64_emit_tests.c
@@ -23,6 +23,69 @@
 #include "dynarec_rv64_functions.h"
 #include "dynarec_rv64_helper.h"
 
+// emit CMP8 instruction, from cmp s1, s2, using s3, s4, s5 and s6 as scratch
+void emit_cmp8(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5, int s6) {
+    CLEAR_FLAGS();
+    IFX_PENDOR0 {
+        SB(s1, xEmu, offsetof(x64emu_t, op1));
+        SB(s2, xEmu, offsetof(x64emu_t, op2));
+        SET_DF(s4, d_cmp8);
+    } else {
+        SET_DFNONE(s4);
+    }
+
+    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);
+    ANDI(s6, s6, 0xff);
+    IFX_PENDOR0 {
+        SB(s6, xEmu, offsetof(x64emu_t, res));
+    }
+    IFX(X_SF) {
+        SRLI(s3, s6, 7);
+        BEQZ(s3, 4);
+        ORI(xFlags, xFlags, 1 << F_SF);
+    }
+    CALC_SUB_FLAGS(s5, s2, s6, s3, s4, 8);
+    IFX(X_ZF) {
+        BEQZ(s6, 4);
+        ORI(xFlags, xFlags, 1 << F_ZF);
+    }
+    IFX(X_PF) {
+        emit_pf(dyn, ninst, s6, s3, s4);
+    }
+}
+
+// emit CMP8 instruction, from cmp s1 , 0, using s3 and s4 as scratch
+void emit_cmp8_0(dynarec_rv64_t* dyn, int ninst, int s1, int s3, int s4) {
+    CLEAR_FLAGS();
+    IFX_PENDOR0 {
+        SB(s1, xEmu, offsetof(x64emu_t, op1));
+        SB(xZR, xEmu, offsetof(x64emu_t, op2));
+        SB(s1, xEmu, offsetof(x64emu_t, res));
+        SET_DF(s3, d_cmp8);
+    } else {
+        SET_DFNONE(s4);
+    }
+
+    IFX(X_SF) {
+        SRLI(s3, s1, 7);
+        BEQZ(s3, 4);
+        ORI(xFlags, xFlags, 1 << F_SF);
+    }
+    IFX(X_ZF) {
+        BEQZ(s1, 4);
+        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)
 {
@@ -52,7 +115,7 @@ void emit_cmp32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
     if (!rex.w) {
         ZEROUP(s1);
     }
-    CALC_SUB_FLAGS(s5, s2, s6, s3, s4);
+    CALC_SUB_FLAGS(s5, s2, s6, s3, s4, rex.w?64:32);
     IFX(X_ZF) {
         BEQZ(s6, 4);
         ORI(xFlags, xFlags, 1 << F_ZF);
diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h
index b3017667..c4bebc19 100644
--- a/src/dynarec/rv64/dynarec_rv64_helper.h
+++ b/src/dynarec/rv64/dynarec_rv64_helper.h
@@ -76,6 +76,29 @@
 // Write back ed in wback (if wback not 0)
 #define WBACK       if(wback) {SDxw(ed, wback, fixedaddress); SMWRITE();}
 
+// GETEB will use i for ed, and can use r3 for wback.
+#define GETEB(i, D) if(MODREG) {                \
+                    if(rex.rex) {               \
+                        wback = xRAX+(nextop&7)+(rex.b<<3);     \
+                        wb2 = 0;                \
+                    } else {                    \
+                        wback = (nextop&7);     \
+                        wb2 = (wback>>2)*8;     \
+                        wback = xRAX+(wback&3); \
+                    }                           \
+                    MV(i, wback);               \
+                    if (wb2) SRLI(i, i, wb2);   \
+                    ANDI(i, i, 0xff);           \
+                    wb1 = 0;                    \
+                    ed = i;                     \
+                } else {                        \
+                    SMREAD();                   \
+                    addr = geted(dyn, addr, ninst, nextop, &wback, x2, x3, &fixedaddress, rex, NULL, 0, D); \
+                    LBU(i, wback, fixedaddress);\
+                    wb1 = 1;                    \
+                    ed = i;                     \
+                }
+
 #define IFX(A)  if((dyn->insts[ninst].x64.gen_flags&(A)))
 #define IFX_PENDOR0  if((dyn->insts[ninst].x64.gen_flags&(X_PEND) || !dyn->insts[ninst].x64.gen_flags))
 #define IFXX(A) if((dyn->insts[ninst].x64.gen_flags==(A)))
@@ -89,7 +112,7 @@
 
 #define CLEAR_FLAGS() IFX(X_ALL) {ANDI(xFlags, xFlags, ~((1UL<<F_AF) | (1UL<<F_CF) | (1UL<<F_OF) | (1UL<<F_ZF) | (1UL<<F_SF) | (1UL<<F_PF)));}
 
-#define CALC_SUB_FLAGS(op1_, op2, res, scratch1, scratch2)                \
+#define CALC_SUB_FLAGS(op1_, op2, res, scratch1, scratch2, width)         \
     IFX(X_AF | X_CF | X_OF) {                                             \
         /* calc borrow chain */                                           \
         /* bc = (res & (~op1 | op2)) | (~op1 & op2) */                    \
@@ -104,14 +127,19 @@
             ORI(xFlags, xFlags, 1 << F_AF);                               \
         }                                                                 \
         IFX(X_CF) {                                                       \
-            /* cf = bc & (rex.w?(1<<63):(1<<31)) */                       \
-            SRLI(scratch1, scratch2, rex.w?63:31);                        \
+            /* cf = bc & (1<<(width-1)) */                                \
+            if (width == 8) {                                             \
+                ANDI(scratch1, scratch2, 0x80);                           \
+            } else {                                                      \
+                SRLI(scratch1, scratch2, width-1);                        \
+                if (width == 16) ANDI(scratch1, scratch1, 1);             \
+            }                                                             \
             BEQZ(scratch1, 4);                                            \
             ORI(xFlags, xFlags, 1 << F_CF);                               \
         }                                                                 \
         IFX(X_OF) {                                                       \
-            /* of = ((bc >> rex.w?62:30) ^ (bc >> rex.w?63:31)) & 0x1; */ \
-            SRLI(scratch1, scratch2, rex.w?62:30);                        \
+            /* of = ((bc >> (width-2)) ^ (bc >> (width-1))) & 0x1; */     \
+            SRLI(scratch1, scratch2, width-2);                            \
             SRLI(scratch2, scratch1, 1);                                  \
             XOR(scratch1, scratch1, scratch2);                            \
             ANDI(scratch1, scratch1, 1);                                  \
@@ -359,10 +387,10 @@ void jump_to_next(dynarec_rv64_t* dyn, uintptr_t ip, int reg, int ninst);
 //void call_c(dynarec_rv64_t* dyn, int ninst, void* fnc, int reg, int ret, int saveflags, int save_reg);
 //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);
+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_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_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);