about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorYang Liu <liuyang22@iscas.ac.cn>2023-03-16 16:52:30 +0800
committerGitHub <noreply@github.com>2023-03-16 09:52:30 +0100
commit4b6ec02517635f7ff0a074c5b4092b589b9b04bf (patch)
treef1b809a1259fcb0b3439166b6a15f1dfd447c744 /src
parent9ea3b34e7ea60130d5f0dec69241bc60deaf2097 (diff)
downloadbox64-4b6ec02517635f7ff0a074c5b4092b589b9b04bf.tar.gz
box64-4b6ec02517635f7ff0a074c5b4092b589b9b04bf.zip
[RV64_DYNAREC] Added (81/83) /7 CMP opcode (#571)
* [RV64_DYNAREC] Added (81/83) /7 CMP opcode

* [RV64_DYNAREC] Added B[8-F] MOV opcode

* [RV64_DYNAREC] Added another C7 MOV opcode

* [RV64_DYNAREC] Zeroup for MOV32w
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/rv64/dynarec_rv64_00.c56
-rw-r--r--src/dynarec/rv64/dynarec_rv64_emit_math.c14
-rw-r--r--src/dynarec/rv64/dynarec_rv64_emit_tests.c29
-rw-r--r--src/dynarec/rv64/dynarec_rv64_helper.h2
-rw-r--r--src/dynarec/rv64/rv64_emitter.h4
5 files changed, 90 insertions, 15 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_00.c b/src/dynarec/rv64/dynarec_rv64_00.c
index c437299e..6f1b7f7c 100644
--- a/src/dynarec/rv64/dynarec_rv64_00.c
+++ b/src/dynarec/rv64/dynarec_rv64_00.c
@@ -61,7 +61,7 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
             emit_add32(dyn, ninst, rex, ed, gd, x3, x4, x5);
             WBACK;
             break;
-        
+
         case 0x0F:
             switch(rep) {
             case 2:
@@ -150,7 +150,7 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
         case 0x83:
             nextop = F8;
             switch((nextop>>3)&7) {
-                case 0: //ADD
+                case 0: // ADD
                     if(opcode==0x81) {INST_NAME("ADD Ed, Id");} else {INST_NAME("ADD Ed, Ib");}
                     SETFLAGS(X_ALL, SF_SET_PENDING);
                     GETED((opcode==0x81)?4:1);
@@ -166,6 +166,17 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                     emit_sub32c(dyn, ninst, rex, ed, i64, x3, x4, x5, x6);
                     WBACK;
                     break;
+                case 7: // CMP
+                    if(opcode==0x81) {INST_NAME("CMP Ed, Id");} else {INST_NAME("CMP Ed, Ib");}
+                    SETFLAGS(X_ALL, SF_SET_PENDING);
+                    GETED((opcode==0x81)?4:1);
+                    if(opcode==0x81) i64 = F32S; else i64 = F8S;
+                    if(i64) {
+                        MOV64xw(x2, i64);
+                        emit_cmp32(dyn, ninst, rex, ed, x2, x3, x4, x5, x6);
+                    } else
+                        emit_cmp32_0(dyn, ninst, rex, ed, x3, x4);
+                    break;
                 default:
                     DEFAULT;
             }
@@ -222,7 +233,24 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                 }
             }
             break;
-
+        case 0xB8:
+        case 0xB9:
+        case 0xBA:
+        case 0xBB:
+        case 0xBC:
+        case 0xBD:
+        case 0xBE:
+        case 0xBF:
+            INST_NAME("MOV Reg, Id");
+            gd = xRAX+(opcode&7)+(rex.b<<3);
+            if(rex.w) {
+                u64 = F64;
+                MOV64x(gd, u64);
+            } else {
+                u32 = F32;
+                MOV32w(gd, u32);
+            }
+            break;
         case 0xC1:
             nextop = F8;
             switch((nextop>>3)&7) {
@@ -310,7 +338,25 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                 SMWRITELOCK(lock);
             }
             break;
-
+        case 0xC7:
+            INST_NAME("MOV Ed, Id");
+            nextop=F8;
+            if(MODREG) {    // reg <= i32
+                i64 = F32S;
+                ed = xRAX+(nextop&7)+(rex.b<<3);
+                MOV64xw(ed, i64);
+            } else {        // mem <= i32
+                addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, &lock, 0, 4);
+                i64 = F32S;
+                if(i64) {
+                    MOV64xw(x3, i64);
+                    ed = x3;
+                } else
+                    ed = xZR;
+                SDxw(ed, wback, fixedaddress);
+                SMWRITELOCK(lock);
+            }
+            break;
         case 0xCC:
             SETFLAGS(X_ALL, SF_SET);    // Hack, set all flags (to an unknown state...)
             if(PK(0)=='S' && PK(1)=='C') {
@@ -369,7 +415,6 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                 #endif
             }
             break;
-
         case 0xD1:
             nextop = F8;
             switch((nextop>>3)&7) {
@@ -391,7 +436,6 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                     DEFAULT;
             }
             break;
-            
         case 0xE8:
             INST_NAME("CALL Id");
             i32 = F32S;
diff --git a/src/dynarec/rv64/dynarec_rv64_emit_math.c b/src/dynarec/rv64/dynarec_rv64_emit_math.c
index 307765ac..b2e9be9c 100644
--- a/src/dynarec/rv64/dynarec_rv64_emit_math.c
+++ b/src/dynarec/rv64/dynarec_rv64_emit_math.c
@@ -108,13 +108,13 @@ void emit_add32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i
         if(c >= -2048 && c < 2048) {
             ADDIxw(s1, s1, c);
         } else {
-            MOV64x(s2, c);
+            MOV64xw(s2, c);
             ADDxw(s1, s1, s2);
         }
         return;
     }
     IFX(X_PEND | X_AF | X_CF | X_OF) {
-        MOV64x(s2, c);
+        MOV64xw(s2, c);
     }
     IFX(X_PEND) {
         SDxw(s1, xEmu, offsetof(x64emu_t, op1));
@@ -151,7 +151,7 @@ void emit_add32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i
     if(c >= -2048 && c < 2048) {
         ADDIxw(s1, s1, c);
     } else {
-        IFX(X_PEND | X_AF | X_CF | X_OF) {} else {MOV64x(s2, c);}
+        IFX(X_PEND | X_AF | X_CF | X_OF) {} else {MOV64xw(s2, c);}
         ADDxw(s1, s1, s2);
     }
 
@@ -242,7 +242,7 @@ void emit_sub32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i
         if (c > -2048 && c <= 2048) {
             ADDI(s1, s1, -c);
         } else {
-            MOV64x(s2, c);
+            MOV64xw(s2, c);
             SUBxw(s1, s1, s2);
         }
         return;
@@ -250,7 +250,7 @@ void emit_sub32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i
 
     IFX(X_PEND) {
         SDxw(s1, xEmu, offsetof(x64emu_t, op1));
-        MOV64x(s2, c);
+        MOV64xw(s2, c);
         SDxw(s2, xEmu, offsetof(x64emu_t, op2));
         SET_DF(s3, rex.w?d_sub64:d_sub32);
     } else IFX(X_ALL) {
@@ -265,14 +265,14 @@ void emit_sub32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i
     if (c > -2048 && c <= 2048) {
         ADDIxw(s1, s1, -c);
     } else {
-        IFX(X_PEND) {} else {MOV64x(s2, c);}
+        IFX(X_PEND) {} else {MOV64xw(s2, c);}
         SUBxw(s1, s1, s2);
     }
 
     IFX(X_AF | X_CF | X_OF) {
         IFX(X_PEND) {}
         else if (c > -2048 && c <= 2048) {
-            MOV64x(s2, c);
+            MOV64xw(s2, c);
         }
     }
     IFX(X_PEND) {
diff --git a/src/dynarec/rv64/dynarec_rv64_emit_tests.c b/src/dynarec/rv64/dynarec_rv64_emit_tests.c
index 6218aae6..0b85d831 100644
--- a/src/dynarec/rv64/dynarec_rv64_emit_tests.c
+++ b/src/dynarec/rv64/dynarec_rv64_emit_tests.c
@@ -125,6 +125,35 @@ void emit_cmp32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
     }
 }
 
+// emit CMP32 instruction, from cmp s1, 0, using s3 and s4 as scratch
+void emit_cmp32_0(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s3, int s4)
+{
+    IFX_PENDOR0 {
+        SD(s1, xEmu, offsetof(x64emu_t, op1));
+        SD(xZR, xEmu, offsetof(x64emu_t, op2));
+        SD(s1, xEmu, offsetof(x64emu_t, res));
+        SET_DF(s4, rex.w?d_cmp64:d_cmp32);
+    } else {
+        SET_DFNONE(s4);
+    }
+    IFX(X_SF) {
+        if (rex.w) {
+            BGE(s1, xZR, 4);
+        } else {
+            SRLI(s3, s1, 31);
+            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 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 b9c16ca6..55869194 100644
--- a/src/dynarec/rv64/dynarec_rv64_helper.h
+++ b/src/dynarec/rv64/dynarec_rv64_helper.h
@@ -510,7 +510,7 @@ void emit_cmp8(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4, i
 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_cmp32_0(dynarec_rv64_t* dyn, int ninst, rex_t rex, 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_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/rv64_emitter.h b/src/dynarec/rv64/rv64_emitter.h
index 5359daca..32988c19 100644
--- a/src/dynarec/rv64/rv64_emitter.h
+++ b/src/dynarec/rv64/rv64_emitter.h
@@ -108,8 +108,10 @@ f28–31  ft8–11  FP temporaries                  Caller
 #define SPLIT20(A)  (((A)+0x800)>>12)
 #define SPLIT12(A)  ((A)&0xfff)
 
-// MOVE64x is quite complex, so use a function for this
+// MOV64x/MOV32w is quite complex, so use a function for this
 #define MOV64x(A, B)    rv64_move64(dyn, ninst, A, B)
+#define MOV32w(A, B)    do{ rv64_move32(dyn, ninst, A, B); if(A&0x80000000) ZEROUP(A); }while(0);
+#define MOV64xw(A, B)   if(rex.w) {MOV64x(A, B);} else {MOV32w(A, B);}
 
 // ZERO the upper part
 #define ZEROUP(r)       AND(r, r, xMASK)