about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorYang Liu <liuyang22@iscas.ac.cn>2023-03-31 14:16:33 +0800
committerGitHub <noreply@github.com>2023-03-31 08:16:33 +0200
commit275550a9c387a69a6d5b2e5824577d3e2e25df57 (patch)
tree07e5a7e2e6dbece73329a94fbebab63bb89d8177 /src
parent38cf61209e1a5adcb25053b5bac8a3684cc400af (diff)
downloadbox64-275550a9c387a69a6d5b2e5824577d3e2e25df57.tar.gz
box64-275550a9c387a69a6d5b2e5824577d3e2e25df57.zip
[RV64_DYNAREC] Added more SS opcodes (#654)
* [RV64_DYNAREC] Added F3 0F 5E DIVSS opcode

* [RV64_DYNAREC] Small optim for 0F 2E,2F COMISS opcode

* [RV64_DYNAREC] Added F3 0F C2 CMPSS opcode

* [RV64_DYNAREC] Added 9C PUSHF opcode
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/rv64/dynarec_rv64_00.c5
-rw-r--r--src/dynarec/rv64/dynarec_rv64_0f.c18
-rw-r--r--src/dynarec/rv64/dynarec_rv64_f30f.c53
3 files changed, 65 insertions, 11 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_00.c b/src/dynarec/rv64/dynarec_rv64_00.c
index 61327703..4efb0a97 100644
--- a/src/dynarec/rv64/dynarec_rv64_00.c
+++ b/src/dynarec/rv64/dynarec_rv64_00.c
@@ -913,6 +913,11 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                 ZEROUP(xRDX);
             }
             break;
+        case 0x9C:
+            INST_NAME("PUSHF");
+            READFLAGS(X_ALL);
+            PUSH1(xFlags);
+            break;
         case 0xA4:
             if(rep) {
                 INST_NAME("REP MOVSB");
diff --git a/src/dynarec/rv64/dynarec_rv64_0f.c b/src/dynarec/rv64/dynarec_rv64_0f.c
index 84d0b0a6..8198682b 100644
--- a/src/dynarec/rv64/dynarec_rv64_0f.c
+++ b/src/dynarec/rv64/dynarec_rv64_0f.c
@@ -206,13 +206,12 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
             if(opcode==0x2F) {INST_NAME("COMISS Gx, Ex");} else {INST_NAME("UCOMISS Gx, Ex");}
             SETFLAGS(X_ALL, SF_SET);
             nextop = F8;
-            GETGX(x3);
+            GETGXSS(d0);
             GETEXSS(v0, 0);
             CLEAR_FLAGS();
-            // if isnan(gd) || isnan(v0)
+            // if isnan(d0) || isnan(v0)
             IFX(X_ZF | X_PF | X_CF) {
-                FLW(gd, x3, 0);
-                FEQS(x3, gd, gd);
+                FEQS(x3, d0, d0);
                 FEQS(x2, v0, v0);
                 AND(x2, x2, x3);
                 XORI(x2, x2, 1);
@@ -221,21 +220,20 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                 B_NEXT_nocond;
             }
             MARK;
-            // else if isless(gd, v0)
+            // else if isless(d0, v0)
             IFX(X_CF) {
-                FLTS(x2, gd, v0);
+                FLTS(x2, d0, v0);
                 BEQ_MARK2(x2, xZR);
                 ORI(xFlags, xFlags, 1<<F_CF);
                 B_NEXT_nocond;
             }
             MARK2;
-            // else if gd == v0
+            // else if d0 == v0
             IFX(X_ZF) {
-                FEQS(x2, gd, v0);
-                BEQ_MARK3(x2, xZR);
+                FEQS(x2, d0, v0);
+                CBZ_NEXT(x2);
                 ORI(xFlags, xFlags, 1<<F_ZF);
             }
-            MARK3;
             break;
         case 0x31:
             INST_NAME("RDTSC");
diff --git a/src/dynarec/rv64/dynarec_rv64_f30f.c b/src/dynarec/rv64/dynarec_rv64_f30f.c
index 31f19c64..41c3d62d 100644
--- a/src/dynarec/rv64/dynarec_rv64_f30f.c
+++ b/src/dynarec/rv64/dynarec_rv64_f30f.c
@@ -29,7 +29,7 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
     uint8_t opcode = F8;
     uint8_t nextop, u8;
     uint8_t gd, ed;
-    uint8_t wback;
+    uint8_t wback, gback;
     uint64_t u64;
     int v0, v1;
     int q0, q1;
@@ -126,6 +126,13 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
             GETEXSS(d0, 0);
             FSUBS(v0, v0, d0);
             break;
+        case 0x5E:
+            INST_NAME("DIVSS Gx, Ex");
+            nextop = F8;
+            GETGXSS(v0);
+            GETEXSS(d0, 0);
+            FDIVS(v0, v0, d0);
+            break;
         case 0x7E:
             INST_NAME("MOVQ Gx, Ex");
             nextop = F8;
@@ -142,7 +149,51 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
             }
             SD(xZR, xEmu, offsetof(x64emu_t, xmm[gd])+8);
             break;
+        case 0xC2:
+            INST_NAME("CMPSS Gx, Ex, Ib");
+            nextop = F8;
+            GETGXSS(d0);
+            GETEXSS(d1, 1);
+            u8 = F8;
+            if ((u8&7) == 0) {                                      // Equal
+                FEQS(x2, d0, d1);
+            } else if ((u8&7) == 4) {                               // Not Equal or unordered
+                FEQS(x2, d0, d1);
+                XORI(x2, x2, 1);
+            } else {
+                // x2 = !(isnan(d0) || isnan(d1))
+                FEQS(x3, d0, d0);
+                FEQS(x2, d1, d1);
+                AND(x2, x2, x3);
 
+                switch(u8&7) {
+                case 1: BEQ_MARK(x2, xZR); FLTS(x2, d0, d1); break; // Less than
+                case 2: BEQ_MARK(x2, xZR); FLES(x2, d0, d1); break; // Less or equal
+                case 3: XORI(x2, x2, 1); break;                     // NaN
+                case 5: {                                           // Greater or equal or unordered
+                    BEQ_MARK2(x2, xZR);
+                    FLES(x2, d1, d0);
+                    B_MARK_nocond;
+                    break;
+                }
+                case 6: {                                           // Greater or unordered, test inverted, N!=V so unordered or less than (inverted)
+                    BEQ_MARK2(x2, xZR);
+                    FLTS(x2, d1, d0);
+                    B_MARK_nocond;
+                    break;
+                }
+                case 7: break;                                      // Not NaN
+                }
+                
+                MARK2;
+                if ((u8&7) == 5 || (u8&7) == 6) {
+                    MOV32w(x2, 1);
+                }
+                MARK;
+            }
+            NEG(x2, x2);
+            FMVWX(d0, x2);
+            break;
         default:
             DEFAULT;
     }