about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorYang Liu <liuyang22@iscas.ac.cn>2023-04-23 23:31:06 +0800
committerGitHub <noreply@github.com>2023-04-23 17:31:06 +0200
commit29e7497adcf4d7c53d6138e92c2e8d9a18a56c08 (patch)
treea4f256d0ae61df53610d24e7b29d5dd508ccb3c6 /src
parent8ecf28de9bc3d562396b5f81c931e2671319a9e4 (diff)
downloadbox64-29e7497adcf4d7c53d6138e92c2e8d9a18a56c08.tar.gz
box64-29e7497adcf4d7c53d6138e92c2e8d9a18a56c08.zip
[RV64_DYNAREC] Added more opcodes (#733)
* Added 66 1B SBB opcode

* Added 66 0F E4 PMULHUW opcode

* Added 66 0F E8 PSUBSB opcode

* Added 1A SBB opcode

* Added F2 0F E6 CVTPD2DQ opcode

* Added 66 F7 /2 NOT opcode

* Small optimization
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/rv64/dynarec_rv64_00_0.c10
-rw-r--r--src/dynarec/rv64/dynarec_rv64_66.c16
-rw-r--r--src/dynarec/rv64/dynarec_rv64_660f.c37
-rw-r--r--src/dynarec/rv64/dynarec_rv64_emit_math.c44
-rw-r--r--src/dynarec/rv64/dynarec_rv64_f20f.c19
-rw-r--r--src/dynarec/rv64/dynarec_rv64_helper.h2
6 files changed, 126 insertions, 2 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_00_0.c b/src/dynarec/rv64/dynarec_rv64_00_0.c
index 6cf6a342..0320107d 100644
--- a/src/dynarec/rv64/dynarec_rv64_00_0.c
+++ b/src/dynarec/rv64/dynarec_rv64_00_0.c
@@ -202,6 +202,16 @@ uintptr_t dynarec64_00_0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
             emit_sbb32(dyn, ninst, rex, ed, gd, x3, x4, x5);
             WBACK;
             break;
+        case 0x1A:
+            INST_NAME("SBB Gb, Eb");
+            READFLAGS(X_CF);
+            SETFLAGS(X_ALL, SF_SET_PENDING);
+            nextop = F8;
+            GETEB(x2, 0);
+            GETGB(x1);
+            emit_sbb8(dyn, ninst, x1, x2, x3, x4, x5);
+            GBBACK(x5);
+            break;
         case 0x1B:
             INST_NAME("SBB Gd, Ed");
             READFLAGS(X_CF);
diff --git a/src/dynarec/rv64/dynarec_rv64_66.c b/src/dynarec/rv64/dynarec_rv64_66.c
index 320f58a0..acafe265 100644
--- a/src/dynarec/rv64/dynarec_rv64_66.c
+++ b/src/dynarec/rv64/dynarec_rv64_66.c
@@ -124,6 +124,16 @@ 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 0x1B:
+            INST_NAME("SBB Gw, Ew");
+            READFLAGS(X_CF);
+            SETFLAGS(X_ALL, SF_SET_PENDING);
+            nextop = F8;
+            GETGW(x1);
+            GETEW(x2, 0);
+            emit_sbb16(dyn, ninst, x1, x2, x3, x4, x5);
+            GWBACK;
+            break;
         case 0x21:
             INST_NAME("AND Ew, Gw");
             SETFLAGS(X_ALL, SF_SET_PENDING);
@@ -708,6 +718,12 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                     MOV32w(x2, u16);
                     emit_test16(dyn, ninst, x1, x2, x3, x4, x5);
                     break;
+                case 2:
+                    INST_NAME("NOT Ew");
+                    GETEW(x1, 0);
+                    NOT(ed, ed); // No flags affected
+                    EWBACK;
+                    break;
                 case 3:
                     INST_NAME("NEG Ew");
                     SETFLAGS(X_ALL, SF_SET_PENDING);
diff --git a/src/dynarec/rv64/dynarec_rv64_660f.c b/src/dynarec/rv64/dynarec_rv64_660f.c
index 91283c6f..b71af6d0 100644
--- a/src/dynarec/rv64/dynarec_rv64_660f.c
+++ b/src/dynarec/rv64/dynarec_rv64_660f.c
@@ -1216,6 +1216,43 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
             GETEX(x2, 0);
             SSE_LOOP_Q(x3, x4, NOT(x3, x3); AND(x3, x3, x4));
             break;
+        case 0xE4:
+            INST_NAME("PMULHUW Gx,Ex");
+            nextop = F8;
+            GETGX(x1);
+            GETEX(x2, 0);
+            for(int i=0; i<8; ++i) {
+                LHU(x3, gback, 2*i);
+                LHU(x4, wback, fixedaddress+2*i);
+                MULW(x3, x3, x4);
+                SRLIW(x3, x3, 16);
+                SH(x3, gback, 2*i);
+            }
+            break;
+        case 0xE8:
+            INST_NAME("PSUBSB Gx,Ex");
+            nextop = F8;
+            GETGX(x1);
+            GETEX(x2, 0);
+            for(int i=0; i<16; ++i) {
+                // tmp16s = (int16_t)GX->sb[i] - EX->sb[i];
+                // GX->sb[i] = (tmp16s<-128)?-128:((tmp16s>127)?127:tmp16s);
+                LB(x3, gback, i);
+                LB(x4, wback, fixedaddress+i);
+                SUBW(x3, x3, x4);
+                SLLIW(x3, x3, 16);
+                SRAIW(x3, x3, 16);
+                ADDI(x4, xZR, 0x7f);
+                BLT(x3, x4, 12);     // tmp16s>127?
+                SB(x4, gback, i);
+                J(24);               // continue
+                ADDI(x4, xZR, 0xf80);
+                BLT(x4, x3, 12);     // tmp16s<-128?
+                SB(x4, gback, i);
+                J(8);                // continue
+                SB(x3, gback, i);
+            }
+            break;
         case 0xEB:
             INST_NAME("POR Gx,Ex");
             nextop = F8;
diff --git a/src/dynarec/rv64/dynarec_rv64_emit_math.c b/src/dynarec/rv64/dynarec_rv64_emit_math.c
index 90031672..d468e972 100644
--- a/src/dynarec/rv64/dynarec_rv64_emit_math.c
+++ b/src/dynarec/rv64/dynarec_rv64_emit_math.c
@@ -880,7 +880,49 @@ void emit_sbb8c(dynarec_rv64_t* dyn, int ninst, int s1, int c, int s3, int s4, i
     emit_sbb8(dyn, ninst, s1, s6, s3, s4, s5);
 }
 
-// emit SBB32 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
+// emit SBB16 instruction, from s1, s2, store result in s1 using s3, s4 and s5 as scratch
+void emit_sbb16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5)
+{
+    IFX(X_PEND) {
+        SH(s1, xEmu, offsetof(x64emu_t, op1));
+        SH(s2, xEmu, offsetof(x64emu_t, op2));
+        SET_DF(s3, d_sbb16);
+    } 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(s3, xFlags, 1 << F_CF);
+    SUBW(s1, s1, s3);
+
+    IFX(X_SF) {
+        BGE(s1, xZR, 8);
+        ORI(xFlags, xFlags, 1 << F_SF);
+    }
+
+    SLLI(s1, s1, 48);
+    SRLI(s1, s1, 48);
+
+    IFX(X_PEND) {
+        SH(s1, xEmu, offsetof(x64emu_t, res));
+    }
+
+    CALC_SUB_FLAGS(s5, s2, s1, s3, s4, 16);
+    IFX(X_ZF) {
+        BNEZ(s1, 8);
+        ORI(xFlags, xFlags, 1 << F_ZF);
+    }
+    IFX(X_PF) {
+        emit_pf(dyn, ninst, s1, s3, s4);
+    }
+}
+
+// emit SBB32 instruction, from s1, s2, store result in s1 using s3, s4 and s5 as scratch
 void emit_sbb32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5)
 {
     IFX(X_PEND) {
diff --git a/src/dynarec/rv64/dynarec_rv64_f20f.c b/src/dynarec/rv64/dynarec_rv64_f20f.c
index 13e89083..95f526f0 100644
--- a/src/dynarec/rv64/dynarec_rv64_f20f.c
+++ b/src/dynarec/rv64/dynarec_rv64_f20f.c
@@ -344,6 +344,25 @@ uintptr_t dynarec64_F20F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
             NEG(x2, x2);
             FMVDX(d0, x2);
             break;
+        case 0xE6:
+            INST_NAME("CVTPD2DQ Gx, Ex");
+            nextop = F8;
+            GETGX(x1);
+            GETEX(x2, 0);
+            d0 = fpu_get_scratch(dyn);
+            u8 = sse_setround(dyn, ninst, x6, x4);
+            for (int i=0; i<2 ; ++i) {
+                FLD(d0, wback, fixedaddress+8*i);
+                FCVTLD(x3, d0, RD_DYN);
+                SEXT_W(x5, x3);
+                SUB(x5, x5, x3);
+                BEQZ(x5, 8);
+                LUI(x3, 0x80000); // INT32_MIN
+                SW(x3, gback, 4*i);
+            }
+            x87_restoreround(dyn, ninst, u8);
+            SD(xZR, gback, 8);
+            break;
         default:
             DEFAULT;
     }
diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h
index b3675745..7fb1cdc9 100644
--- a/src/dynarec/rv64/dynarec_rv64_helper.h
+++ b/src/dynarec/rv64/dynarec_rv64_helper.h
@@ -960,7 +960,7 @@ void emit_sbb32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
 //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, 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_sbb16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5);
 //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 s2, int s3);
 void emit_neg16(dynarec_rv64_t* dyn, int ninst, int s1, int s3, int s4);