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:09:59 +0800
committerGitHub <noreply@github.com>2023-03-20 11:09:59 +0100
commit61a6af1de7ea81b845115d22459247c90366cb05 (patch)
treebfa74b29fedd71c3d8a4c40a869ea38c22f3fa1d /src
parent77f8bea61510eb5e3906042c6567ca6bb192893e (diff)
downloadbox64-61a6af1de7ea81b845115d22459247c90366cb05.tar.gz
box64-61a6af1de7ea81b845115d22459247c90366cb05.zip
[RV64_DYNAREC] Added 80 /3 SBB opcode (#597)
* [RV64_DYNAREC] Simplify SET_DFNONE

* [RV64_DYNARC] Fixed 80 /3 AND opcode

* [RV64_DYNAREC] Added 80 /3 SBB opcode
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/rv64/dynarec_rv64_00.c25
-rw-r--r--src/dynarec/rv64/dynarec_rv64_emit_logic.c16
-rw-r--r--src/dynarec/rv64/dynarec_rv64_emit_math.c59
-rw-r--r--src/dynarec/rv64/dynarec_rv64_emit_shift.c8
-rw-r--r--src/dynarec/rv64/dynarec_rv64_emit_tests.c14
-rw-r--r--src/dynarec/rv64/dynarec_rv64_helper.h8
6 files changed, 94 insertions, 36 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_00.c b/src/dynarec/rv64/dynarec_rv64_00.c
index 4db2ce60..44aaa4bb 100644
--- a/src/dynarec/rv64/dynarec_rv64_00.c
+++ b/src/dynarec/rv64/dynarec_rv64_00.c
@@ -300,13 +300,22 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
         case 0x80:
             nextop = F8;
             switch((nextop>>3)&7) {
+                case 3: // SBB
+                    INST_NAME("SBB Eb, Ib");
+                    READFLAGS(X_CF);
+                    SETFLAGS(X_ALL, SF_SET_PENDING);
+                    GETEB(x1, 1);
+                    u8 = F8;
+                    emit_sbb8c(dyn, ninst, x1, u8, x3, x4, x5, x6);
+                    EBBACK(x3);
+                    break;
                 case 4: // AND
                     INST_NAME("AND Eb, Ib");
                     SETFLAGS(X_ALL, SF_SET_PENDING);
                     GETEB(x1, 1);
                     u8 = F8;
-                    emit_and8c(dyn, ninst, x1, u8, x2, x4);
-                    EBBACK(x2);
+                    emit_and8c(dyn, ninst, x1, u8, x3, x4);
+                    EBBACK(x3);
                     break;
                 case 7: // CMP
                     INST_NAME("CMP Eb, Ib");
@@ -1026,7 +1035,7 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                     INST_NAME("DIV Ed");
                     SETFLAGS(X_ALL, SF_SET);
                     if(!rex.w) {
-                        SET_DFNONE(x2);
+                        SET_DFNONE();
                         GETED(0);
                         SLLI(x3, xRDX, 32);
                         AND(x2, xRAX, xMASK);
@@ -1044,7 +1053,7 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                            && dyn->insts[ninst-1].x64.addr 
                            && *(uint8_t*)(dyn->insts[ninst-1].x64.addr)==0x31 
                            && *(uint8_t*)(dyn->insts[ninst-1].x64.addr+1)==0xD2) {
-                            SET_DFNONE(x2);
+                            SET_DFNONE();
                             GETED(0);
                             DIVU(x2, xRAX, ed);
                             REMU(xRDX, xRAX, ed);
@@ -1059,7 +1068,7 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                             DIVU(x2, xRAX, ed);
                             REMU(xRDX, xRAX, ed);
                             MV(xRAX, x2);
-                            SET_DFNONE(x2);
+                            SET_DFNONE();
                         }
                     }
                     break;
@@ -1067,7 +1076,7 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                     INST_NAME("IDIV Ed");
                     SETFLAGS(X_ALL, SF_SET);
                     if(!rex.w) {
-                        SET_DFNONE(x2)
+                        SET_DFNONE()
                         GETSED(0);
                         SLLI(x3, xRDX, 32);
                         AND(x2, xRAX, xMASK);
@@ -1081,7 +1090,7 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                            &&  dyn->insts[ninst-1].x64.addr 
                            && *(uint8_t*)(dyn->insts[ninst-1].x64.addr)==0x48
                            && *(uint8_t*)(dyn->insts[ninst-1].x64.addr+1)==0x99) {
-                            SET_DFNONE(x2)
+                            SET_DFNONE()
                             GETED(0);
                             DIV(x2, xRAX, ed);
                             REM(xRDX, xRAX, ed);
@@ -1104,7 +1113,7 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                             DIV(x2, xRAX, ed);
                             REM(xRDX, xRAX, ed);
                             MV(xRAX, x2);
-                            SET_DFNONE(x2)
+                            SET_DFNONE()
                         }
                     }
                     break;
diff --git a/src/dynarec/rv64/dynarec_rv64_emit_logic.c b/src/dynarec/rv64/dynarec_rv64_emit_logic.c
index 1baf214c..f1e92b83 100644
--- a/src/dynarec/rv64/dynarec_rv64_emit_logic.c
+++ b/src/dynarec/rv64/dynarec_rv64_emit_logic.c
@@ -30,7 +30,7 @@ void emit_xor32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
     IFX(X_PEND) {
         SET_DF(s4, rex.w?d_xor64:d_xor32);
     } else IFX(X_ALL) {
-        SET_DFNONE(s4);
+        SET_DFNONE();
     }
 
     XOR(s1, s1, s2);
@@ -64,7 +64,7 @@ void emit_xor32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i
     IFX(X_PEND) {
         SET_DF(s4, rex.w?d_xor64:d_xor32);
     } else IFX(X_ALL) {
-        SET_DFNONE(s4);
+        SET_DFNONE();
     }
 
     if(c>=-2048 && c<=2047) {
@@ -102,7 +102,7 @@ void emit_or16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4) {
     IFX(X_PEND) {
         SET_DF(s3, d_or16);
     } else IFX(X_ALL) {
-        SET_DFNONE(s3);
+        SET_DFNONE();
     }
 
     OR(s1, s1, s2);
@@ -134,7 +134,7 @@ void emit_or32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
     IFX(X_PEND) {
         SET_DF(s4, rex.w?d_or64:d_or32);
     } else IFX(X_ALL) {
-        SET_DFNONE(s4);
+        SET_DFNONE();
     }
 
     OR(s1, s1, s2);
@@ -168,7 +168,7 @@ void emit_or32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, in
     IFX(X_PEND) {
         SET_DF(s4, rex.w?d_or64:d_or32);
     } else IFX(X_ALL) {
-        SET_DFNONE(s4);
+        SET_DFNONE();
     }
 
     if(c>=-2048 && c<=2047) {
@@ -207,7 +207,7 @@ void emit_and8c(dynarec_rv64_t* dyn, int ninst, int s1, int32_t c, int s3, int s
     IFX(X_PEND) {
         SET_DF(s3, d_and8);
     } else IFX(X_ALL) {
-        SET_DFNONE(s3);
+        SET_DFNONE();
     }
 
     ANDI(s1, s1, c&0xff);
@@ -236,7 +236,7 @@ void emit_and32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
     IFX(X_PEND) {
         SET_DF(s3, rex.w?d_tst64:d_tst32);
     } else IFX(X_ALL) {
-        SET_DFNONE(s4);
+        SET_DFNONE();
     }
 
     AND(s1, s1, s2); // res = s1 & s2
@@ -266,7 +266,7 @@ void emit_and32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i
     IFX(X_PEND) {
         SET_DF(s3, rex.w?d_tst64:d_tst32);
     } else IFX(X_ALL) {
-        SET_DFNONE(s4);
+        SET_DFNONE();
     }
 
     if(c>=-2048 && c<=2047) {
diff --git a/src/dynarec/rv64/dynarec_rv64_emit_math.c b/src/dynarec/rv64/dynarec_rv64_emit_math.c
index 8b735f32..ed213f55 100644
--- a/src/dynarec/rv64/dynarec_rv64_emit_math.c
+++ b/src/dynarec/rv64/dynarec_rv64_emit_math.c
@@ -32,7 +32,7 @@ void emit_add32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
         SDxw(s2, xEmu, offsetof(x64emu_t, op2));
         SET_DF(s3, rex.w?d_add64:d_add32b);
     } else IFX(X_ALL) {
-        SET_DFNONE(s3);
+        SET_DFNONE();
     }
     IFX(X_CF) {
         if (rex.w) {
@@ -121,7 +121,7 @@ void emit_add32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i
         SDxw(s2, xEmu, offsetof(x64emu_t, op2));
         SET_DF(s3, rex.w?d_add64:d_add32b);
     } else IFX(X_ALL) {
-        SET_DFNONE(s3);
+        SET_DFNONE();
     }
     IFX(X_CF) {
         if (rex.w) {
@@ -202,7 +202,7 @@ void emit_sub32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
         SDxw(s2, xEmu, offsetof(x64emu_t, op2));
         SET_DF(s3, rex.w?d_sub64:d_sub32);
     } else IFX(X_ALL) {
-        SET_DFNONE(s3);
+        SET_DFNONE();
     }
 
     IFX(X_AF | X_CF | X_OF) {
@@ -254,7 +254,7 @@ void emit_sub32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i
         SDxw(s2, xEmu, offsetof(x64emu_t, op2));
         SET_DF(s3, rex.w?d_sub64:d_sub32);
     } else IFX(X_ALL) {
-        SET_DFNONE(s3);
+        SET_DFNONE();
     }
 
     IFX(X_AF | X_CF | X_OF) {
@@ -305,7 +305,7 @@ void emit_inc32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
         SDxw(s1, xEmu, offsetof(x64emu_t, op1));
         SET_DF(s3, rex.w?d_inc64:d_inc32);
     } else IFX(X_ALL) {
-        SET_DFNONE(s3);
+        SET_DFNONE();
     }
     IFX(X_AF | X_OF) {
         ORI(s3, s1, 1);      // s3 = op1 | op2
@@ -350,3 +350,52 @@ void emit_inc32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
         ORI(xFlags, xFlags, 1 << F_ZF);
     }
 }
+
+// emit SBB8 instruction, from s1, s2, store result in s1 using s3, s4 and s5 as scratch
+void emit_sbb8(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5)
+{
+    IFX(X_PEND) {
+        SB(s1, xEmu, offsetof(x64emu_t, op1));
+        SB(s2, xEmu, offsetof(x64emu_t, op2));
+        SET_DF(s3, d_sbb8);
+    } else IFX(X_ALL) {
+        SET_DFNONE();
+    }
+
+    IFX(X_AF | X_CF | X_OF) {
+        // for later flag calculation
+        NOT(s5, s1);
+    }
+
+    SUBW(s1, s1, s2);
+    ANDI(s1, s1, 0xff);
+    ANDI(s3, xFlags, 1 << F_CF);
+    BEQZ(s3, 12);
+    ADDIW(s1, s1, -1);
+    ANDI(s1, s1, 0xff);
+
+    IFX(X_PEND) {
+        SB(s1, xEmu, offsetof(x64emu_t, res));
+    }
+
+    CALC_SUB_FLAGS(s5, s2, s1, s3, s4, 8);
+    IFX(X_SF) {
+        SRLI(s3, s1, 7);
+        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 SBB8 instruction, from s1, constant c, store result in s1 using s3, s4, s5 and s6 as scratch
+void emit_sbb8c(dynarec_rv64_t* dyn, int ninst, int s1, int c, int s3, int s4, int s5, int s6)
+{
+    MOV32w(s6, c&0xff);
+    emit_sbb8(dyn, ninst, s1, s6, s3, s4, s5);
+}
diff --git a/src/dynarec/rv64/dynarec_rv64_emit_shift.c b/src/dynarec/rv64/dynarec_rv64_emit_shift.c
index 015ea2f5..a9e3a2b9 100644
--- a/src/dynarec/rv64/dynarec_rv64_emit_shift.c
+++ b/src/dynarec/rv64/dynarec_rv64_emit_shift.c
@@ -33,7 +33,7 @@ void emit_shl32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
         SDxw(s2, xEmu, offsetof(x64emu_t, op2));
         SET_DF(s4, rex.w?d_shl64:d_shl32);
     } else IFX(X_ALL) {
-        SET_DFNONE(s4);
+        SET_DFNONE();
     }
 
     IFX(X_CF) {
@@ -83,7 +83,7 @@ void emit_shl32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c,
         SDxw(s1, xEmu, offsetof(x64emu_t, op1));
         SET_DF(s4, rex.w?d_shl64:d_shl32);
     } else IFX(X_ALL) {
-        SET_DFNONE(s4);
+        SET_DFNONE();
     }
 
     if(!c) {
@@ -143,7 +143,7 @@ void emit_shr32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c,
         SDxw(s1, xEmu, offsetof(x64emu_t, op1));
         SET_DF(s4, rex.w?d_shr64:d_shr32);
     } else IFX(X_ALL) {
-        SET_DFNONE(s4);
+        SET_DFNONE();
     }
     if(!c) {
         IFX(X_PEND) {
@@ -208,7 +208,7 @@ void emit_sar32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c,
         SDxw(s1, xEmu, offsetof(x64emu_t, op1));
         SET_DF(s4, rex.w?d_sar64:d_sar32);
     } else IFX(X_ALL) {
-        SET_DFNONE(s4);
+        SET_DFNONE();
     }
     if(!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 4aa41f5b..7ce0ae58 100644
--- a/src/dynarec/rv64/dynarec_rv64_emit_tests.c
+++ b/src/dynarec/rv64/dynarec_rv64_emit_tests.c
@@ -32,7 +32,7 @@ void emit_cmp8(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4, i
         SB(s2, xEmu, offsetof(x64emu_t, op2));
         SET_DF(s4, d_cmp8);
     } else {
-        SET_DFNONE(s4);
+        SET_DFNONE();
     }
 
     IFX(X_AF | X_CF | X_OF) {
@@ -71,7 +71,7 @@ void emit_cmp8_0(dynarec_rv64_t* dyn, int ninst, int s1, int s3, int s4)
         SB(s1, xEmu, offsetof(x64emu_t, res));
         SET_DF(s3, d_cmp8);
     } else {
-        SET_DFNONE(s4);
+        SET_DFNONE();
     }
 
     IFX(X_SF) {
@@ -97,7 +97,7 @@ void emit_cmp32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
         SDxw(s2, xEmu, offsetof(x64emu_t, op2));
         SET_DF(s4, rex.w?d_cmp64:d_cmp32);
     } else {
-        SET_DFNONE(s4);
+        SET_DFNONE();
     }
 
     IFX(X_AF | X_CF | X_OF) {
@@ -137,7 +137,7 @@ void emit_cmp32_0(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s3, int
         SD(s1, xEmu, offsetof(x64emu_t, res));
         SET_DF(s4, rex.w?d_cmp64:d_cmp32);
     } else {
-        SET_DFNONE(s4);
+        SET_DFNONE();
     }
     IFX(X_SF) {
         if (rex.w) {
@@ -163,7 +163,7 @@ void emit_test8(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4,
     IFX_PENDOR0 {
         SET_DF(s3, d_tst8);
     } else {
-        SET_DFNONE(s4);
+        SET_DFNONE();
     }
 
     AND(s3, s1, s2); // res = s1 & s2
@@ -192,7 +192,7 @@ void emit_test32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int
     IFX_PENDOR0 {
         SET_DF(s3, rex.w?d_tst64:d_tst32);
     } else {
-        SET_DFNONE(s4);
+        SET_DFNONE();
     }
 
     AND(s3, s1, s2); // res = s1 & s2
@@ -222,7 +222,7 @@ void emit_test32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c,
     IFX_PENDOR0 {
         SET_DF(s3, rex.w?d_tst64:d_tst32);
     } else {
-        SET_DFNONE(s4);
+        SET_DFNONE();
     }
 
     if(c>=-2048 && c<=2047)
diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h
index 9532b9f2..fc526327 100644
--- a/src/dynarec/rv64/dynarec_rv64_helper.h
+++ b/src/dynarec/rv64/dynarec_rv64_helper.h
@@ -310,8 +310,8 @@
     LOAD_REG(R11);          \
 
 
-#define SET_DFNONE(S)    if(!dyn->f.dfnone) {SW(xZR, xEmu, offsetof(x64emu_t, df)); dyn->f.dfnone=1;}
-#define SET_DF(S, N)     if((N)!=d_none) {MOV_U12(S, (N)); SW(S, xEmu, offsetof(x64emu_t, df)); dyn->f.dfnone=0;} else SET_DFNONE(S)
+#define SET_DFNONE()    if(!dyn->f.dfnone) {SW(xZR, xEmu, offsetof(x64emu_t, df)); dyn->f.dfnone=1;}
+#define SET_DF(S, N)     if((N)!=d_none) {MOV_U12(S, (N)); SW(S, xEmu, offsetof(x64emu_t, df)); dyn->f.dfnone=0;} else SET_DFNONE()
 #define SET_NODF()          dyn->f.dfnone = 0
 #define SET_DFOK()          dyn->f.dfnone = 1
 
@@ -703,8 +703,8 @@ void emit_inc32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
 //void emit_adc16c(dynarec_rv64_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
 //void emit_sbb32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4);
 //void emit_sbb32c(dynarec_rv64_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
-//void emit_sbb8(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4);
-//void emit_sbb8c(dynarec_rv64_t* dyn, int ninst, int s1, int32_t c, int s3, int s4, int s5);
+void emit_sbb8(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5);
+void emit_sbb8c(dynarec_rv64_t* dyn, int ninst, int s1, int32_t c, int s3, int s4, int s5, int s6);
 //void emit_sbb16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4);
 //void emit_sbb16c(dynarec_rv64_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
 //void emit_neg32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s3, int s4);