about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorYang Liu <liuyang22@iscas.ac.cn>2023-05-04 23:10:02 +0800
committerGitHub <noreply@github.com>2023-05-04 17:10:02 +0200
commitf7326b05333b8b9ec4fa93f05f585505a3a3e63e (patch)
tree176ccf01f9490025215bcb9e10fdd70de0f9bffe
parentdbde650339a74b6dd09a7895679ca5c704b31a76 (diff)
downloadbox64-f7326b05333b8b9ec4fa93f05f585505a3a3e63e.tar.gz
box64-f7326b05333b8b9ec4fa93f05f585505a3a3e63e.zip
[RV64_DYNAREC] Added more opcode for Unciv and some fixes (#759)
* Added F2 AF SCASD opcode

* Added DD FST opcode

* Added DC FCOMP opcode

* Added DD FFREE opcode

* Added 66 0F 3A 21 INSERTPS opcode
-rwxr-xr-xCMakeLists.txt2
-rw-r--r--src/dynarec/rv64/dynarec_rv64_00_2.c42
-rw-r--r--src/dynarec/rv64/dynarec_rv64_00_3.c4
-rw-r--r--src/dynarec/rv64/dynarec_rv64_660f.c18
-rw-r--r--src/dynarec/rv64/dynarec_rv64_d8.c4
-rw-r--r--src/dynarec/rv64/dynarec_rv64_dc.c112
-rw-r--r--src/dynarec/rv64/dynarec_rv64_dd.c11
-rw-r--r--src/dynarec/rv64/dynarec_rv64_helper.h2
8 files changed, 186 insertions, 9 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4b9841e1..b0af3605 100755
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -639,7 +639,7 @@ if(RV64_DYNAREC)
     "${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_d9.c"
     #"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_da.c"
     "${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_db.c"
-    #"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_dc.c"
+    "${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_dc.c"
     "${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_dd.c"
     "${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_de.c"
     "${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_df.c"
diff --git a/src/dynarec/rv64/dynarec_rv64_00_2.c b/src/dynarec/rv64/dynarec_rv64_00_2.c
index 0e9144b7..ec296574 100644
--- a/src/dynarec/rv64/dynarec_rv64_00_2.c
+++ b/src/dynarec/rv64/dynarec_rv64_00_2.c
@@ -690,8 +690,8 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
                 SETFLAGS(X_ALL, SF_SET_PENDING);
                 CBZ_NEXT(xRCX);
                 ANDI(x1, xRAX, 0xff);
-                ANDI(x1, xFlags, 1<<F_DF);
-                BNEZ_MARK2(x1);
+                ANDI(x2, xFlags, 1<<F_DF);
+                BNEZ_MARK2(x2);
                 MARK;   // Part with DF==0
                 LBU(x2, xRDI, 0);
                 ADDI(xRDI, xRDI, 1);
@@ -719,6 +719,44 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
                 break;
             }
             break;
+        case 0xAF:
+            switch (rep) {
+            case 1:
+            case 2:
+                if (rep==1) {INST_NAME("REPNZ SCASD");} else {INST_NAME("REPZ SCASD");}
+                MAYSETFLAGS();
+                SETFLAGS(X_ALL, SF_SET_PENDING);
+                CBZ_NEXT(xRCX);
+                if (rex.w) {MV(x1, xRAX);} else {AND(x1, xRAX, xMASK);}
+                ANDI(x2, xFlags, 1<<F_DF);
+                BNEZ_MARK2(x2);
+                MARK;   // Part with DF==0
+                LDxw(x2, xRDI, 0);
+                ADDI(xRDI, xRDI, rex.w?8:4);
+                SUBI(xRCX, xRCX, 1);
+                if (rep==1) {BEQ_MARK3(x1, x2);} else {BNE_MARK3(x1, x2);}
+                BNE_MARK(xRCX, xZR);
+                B_MARK3_nocond;
+                MARK2;  // Part with DF==1
+                LDxw(x2, xRDI, 0);
+                SUBI(xRDI, xRDI, rex.w?8:4);
+                SUBI(xRCX, xRCX, 1);
+                if (rep==1) {BEQ_MARK3(x1, x2);} else {BNE_MARK3(x1, x2);}
+                BNE_MARK2(xRCX, xZR);
+                MARK3; // end
+                emit_cmp32(dyn, ninst, rex, x1, x2, x3, x4, x5, x6);
+                break;
+            default:
+                INST_NAME("SCASD");
+                SETFLAGS(X_ALL, SF_SET_PENDING);
+                GETDIR(x3, x1, rex.w?8:4);
+                AND(x1, xRAX, xMASK);
+                LDxw(x2, xRDI, 0);
+                ADD(xRDI, xRDI, x3);
+                emit_cmp32(dyn, ninst, rex, x1, x2, x3, x4, x5, x6);
+                break;
+            }
+            break;
         case 0xB0:
         case 0xB1:
         case 0xB2:
diff --git a/src/dynarec/rv64/dynarec_rv64_00_3.c b/src/dynarec/rv64/dynarec_rv64_00_3.c
index 90332b60..4a548677 100644
--- a/src/dynarec/rv64/dynarec_rv64_00_3.c
+++ b/src/dynarec/rv64/dynarec_rv64_00_3.c
@@ -537,7 +537,9 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
         case 0xDB:
             addr = dynarec64_DB(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
             break;
-
+        case 0xDC:
+            addr = dynarec64_DC(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
+            break;
         case 0xDD:
             addr = dynarec64_DD(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
             break;
diff --git a/src/dynarec/rv64/dynarec_rv64_660f.c b/src/dynarec/rv64/dynarec_rv64_660f.c
index 08303f44..742a1209 100644
--- a/src/dynarec/rv64/dynarec_rv64_660f.c
+++ b/src/dynarec/rv64/dynarec_rv64_660f.c
@@ -27,7 +27,7 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
     (void)ip; (void)need_epilog;
 
     uint8_t opcode = F8;
-    uint8_t nextop, u8;
+    uint8_t nextop, u8, s8;
     int32_t i32;
     uint8_t gd, ed;
     uint8_t wback, wb1, wb2, gback;
@@ -466,6 +466,22 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
                     u8 = F8;
                     SB(ed, x3, u8&0xF);
                     break;
+                case 0x21:
+                    INST_NAME("INSERTPS GX, EX, Ib");
+                    nextop = F8;
+                    GETGX(x1);
+                    GETEX(x2, 1);
+                    u8 = F8;
+                    if(MODREG) s8 = (u8>>6)&3; else s8 = 0;
+                    // GX->ud[(tmp8u>>4)&3] = EX->ud[tmp8s];
+                    LWU(x3, wback, fixedaddress+4*s8);
+                    SW(x3, gback, 4*(u8>>4));
+                    for(int i=0; i<4; ++i) {
+                        if(u8&(1<<i))
+                            // GX->ud[i] = 0;
+                            SW(xZR, gback, 4*i);
+                    }
+                    break;
                 case 0x22:
                     INST_NAME("PINSRD Gx, ED, Ib");
                     nextop = F8;
diff --git a/src/dynarec/rv64/dynarec_rv64_d8.c b/src/dynarec/rv64/dynarec_rv64_d8.c
index 3a66bba4..c3c10166 100644
--- a/src/dynarec/rv64/dynarec_rv64_d8.c
+++ b/src/dynarec/rv64/dynarec_rv64_d8.c
@@ -62,7 +62,7 @@ uintptr_t dynarec64_D8(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                 AND(x5, x5, x4);
                 BEQZ(x5, 24); // undefined/NaN
                 FEQS(x5, v1, v2);
-                BNEZ(x5, 24); // equal
+                BNEZ(x5, 28); // equal
                 FLTS(x3, v1, v2); // x3 = (v1<v2)?1:0
                 SLLI(x1, x3, 8);
                 J(20); // end
@@ -79,7 +79,7 @@ uintptr_t dynarec64_D8(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                 AND(x5, x5, x4);
                 BEQZ(x5, 24); // undefined/NaN
                 FEQD(x5, v1, v2);
-                BNEZ(x5, 24); // equal
+                BNEZ(x5, 28); // equal
                 FLTD(x3, v1, v2); // x3 = (v1<v2)?1:0
                 SLLI(x1, x3, 8);
                 J(20); // end
diff --git a/src/dynarec/rv64/dynarec_rv64_dc.c b/src/dynarec/rv64/dynarec_rv64_dc.c
new file mode 100644
index 00000000..4facfe0e
--- /dev/null
+++ b/src/dynarec/rv64/dynarec_rv64_dc.c
@@ -0,0 +1,112 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <pthread.h>
+#include <errno.h>
+
+#include "debug.h"
+#include "box64context.h"
+#include "dynarec.h"
+#include "emu/x64emu_private.h"
+#include "emu/x64run_private.h"
+#include "x64run.h"
+#include "x64emu.h"
+#include "box64stack.h"
+#include "callback.h"
+#include "emu/x64run_private.h"
+#include "x64trace.h"
+#include "emu/x87emu_private.h"
+#include "dynarec_native.h"
+
+#include "rv64_printer.h"
+#include "dynarec_rv64_private.h"
+#include "dynarec_rv64_helper.h"
+#include "dynarec_rv64_functions.h"
+
+
+uintptr_t dynarec64_DC(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
+{
+    (void)ip; (void)rep; (void)need_epilog;
+
+    uint8_t nextop = F8;
+    uint8_t wback;
+    int64_t fixedaddress;
+    int unscaled;
+    int v1, v2;
+
+    MAYUSE(v2);
+    MAYUSE(v1);
+
+    switch(nextop) {
+        case 0xC0 ... 0xC7:
+            INST_NAME("FADD STx, ST0");
+            DEFAULT;
+            break;
+        case 0xC8 ... 0xCF:
+            INST_NAME("FMUL STx, ST0");
+            DEFAULT;
+            break;
+        case 0xD0 ... 0xD7:
+            INST_NAME("FCOM ST0, STx"); //yep
+            DEFAULT;
+            break;
+        case 0xD8 ... 0xDF:
+            INST_NAME("FCOMP ST0, STx");
+            DEFAULT;
+            break;
+        case 0xE0 ... 0xE7:
+            INST_NAME("FSUBR STx, ST0");
+            DEFAULT;
+            break;
+            break;
+        case 0xE8 ... 0xEF:
+            INST_NAME("FSUB STx, ST0");
+            DEFAULT;
+            break;
+        case 0xF0 ... 0xF7:
+            INST_NAME("FDIVR STx, ST0");
+            DEFAULT;
+            break;
+        case 0xF8 ... 0xFF:
+            INST_NAME("FDIV STx, ST0");
+            DEFAULT;
+            break;
+        default:
+            switch((nextop>>3)&7) {
+                case 3:
+                    INST_NAME("FCOMP ST0, double[ED]");
+                    v1 = x87_get_st(dyn, ninst, x1, x2, 0, EXT_CACHE_ST_D);
+                    v2 = fpu_get_scratch(dyn);
+                    addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 1, 0);
+                    FLD(v2, wback, fixedaddress);
+
+                    LHU(x3, xEmu, offsetof(x64emu_t, sw));
+                    MOV32w(x1, 0b1110100011111111); // mask off c0,c1,c2,c3
+                    AND(x3, x3, x1);
+                    FEQD(x5, v1, v1);
+                    FEQD(x4, v2, v2);
+                    AND(x5, x5, x4);
+                    BEQZ(x5, 24); // undefined/NaN
+                    FEQD(x5, v1, v2);
+                    BNEZ(x5, 28); // equal
+                    FLTD(x3, v1, v2); // x3 = (v1<v2)?1:0
+                    SLLI(x1, x3, 8);
+                    J(20); // end
+                    // undefined/NaN
+                    LUI(x1, 1);
+                    ADDI(x1, x1, 0b010100000000);
+                    J(8); // end
+                    // equal
+                    LUI(x1, 1);
+                    // end
+                    OR(x3, x3, x1);
+                    SH(x3, xEmu, offsetof(x64emu_t, sw));
+
+                    x87_do_pop(dyn, ninst, x3);
+                    break;
+                default:
+                    DEFAULT;
+            }
+    }
+    return addr;
+}
diff --git a/src/dynarec/rv64/dynarec_rv64_dd.c b/src/dynarec/rv64/dynarec_rv64_dd.c
index ac5fb980..fa1a6a13 100644
--- a/src/dynarec/rv64/dynarec_rv64_dd.c
+++ b/src/dynarec/rv64/dynarec_rv64_dd.c
@@ -51,7 +51,10 @@ uintptr_t dynarec64_DD(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
         case 0xC6:
         case 0xC7:
             INST_NAME("FFREE STx");
-            DEFAULT;
+            MESSAGE(LOG_DUMP, "Need Optimization\n");
+            x87_purgecache(dyn, ninst, 0, x1, x2, x3);
+            MOV32w(x1, nextop&7);
+            CALL(fpu_do_free, -1);
             break;
         case 0xD0:
         case 0xD1:
@@ -139,6 +142,12 @@ uintptr_t dynarec64_DD(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                     addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 1, 0);
                     FLD(v1, wback, fixedaddress);
                     break;
+                case 2:
+                    INST_NAME("FST double");
+                    v1 = x87_get_st(dyn, ninst, x1, x2, 0, EXT_CACHE_ST_D);
+                    addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 1, 0);
+                    FSD(v1, wback, fixedaddress);
+                    break;
                 case 3:
                     INST_NAME("FSTP double");
                     v1 = x87_get_st(dyn, ninst, x1, x2, 0, EXT_CACHE_ST_D);
diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h
index d8d44460..60d369d2 100644
--- a/src/dynarec/rv64/dynarec_rv64_helper.h
+++ b/src/dynarec/rv64/dynarec_rv64_helper.h
@@ -1131,7 +1131,7 @@ uintptr_t dynarec64_D8(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
 uintptr_t dynarec64_D9(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
 //uintptr_t dynarec64_DA(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
 uintptr_t dynarec64_DB(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
-//uintptr_t dynarec64_DC(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
+uintptr_t dynarec64_DC(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
 uintptr_t dynarec64_DD(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
 uintptr_t dynarec64_DE(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
 uintptr_t dynarec64_DF(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);