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 16:00:15 +0800
committerGitHub <noreply@github.com>2023-03-31 10:00:15 +0200
commit4c86c8c2647fc9d88e2c7b847d62fb30f765b597 (patch)
tree5a9958495a7617b28d7d72b69cb33ff13333b9a6 /src
parent275550a9c387a69a6d5b2e5824577d3e2e25df57 (diff)
downloadbox64-4c86c8c2647fc9d88e2c7b847d62fb30f765b597.tar.gz
box64-4c86c8c2647fc9d88e2c7b847d62fb30f765b597.zip
[RV64_DYNAREC] Added more opcodes (#655)
* [RV64_DYNAREC] Added 66 0F 28 MOVAPD opcode

* [RV64_DYNAREC] Added 66 0F 2E,2F COMISD opcode

* [RV64_DYNAREC] Added F2 0F C2 CMPSD opcode

* [RV64_DYNAREC] Added 0F AE /3 STMXCSR opcode

* [RV64_DYNAREC] Added 0F AE /2 LDMXCSR opcode
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/rv64/dynarec_rv64_0f.c14
-rw-r--r--src/dynarec/rv64/dynarec_rv64_660f.c42
-rw-r--r--src/dynarec/rv64/dynarec_rv64_f20f.c44
-rw-r--r--src/dynarec/rv64/dynarec_rv64_helper.h9
4 files changed, 109 insertions, 0 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_0f.c b/src/dynarec/rv64/dynarec_rv64_0f.c
index 8198682b..176e37c2 100644
--- a/src/dynarec/rv64/dynarec_rv64_0f.c
+++ b/src/dynarec/rv64/dynarec_rv64_0f.c
@@ -401,6 +401,20 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                 SMDMB();
             } else {
                 switch((nextop>>3)&7) {
+                    case 2:                 
+                        INST_NAME("LDMXCSR Md");
+                        GETED(0);
+                        SW(ed, xEmu, offsetof(x64emu_t, mxcsr));
+                        if(box64_sse_flushto0) {
+                            // TODO: applyFlushTo0 also needs to add RISC-V support.
+                        }
+                        break;
+                    case 3:
+                        INST_NAME("STMXCSR Md");
+                        addr = geted(dyn, addr, ninst, nextop, &wback, x1, x2, &fixedaddress, rex, NULL, 0, 0);
+                        LWU(x4, xEmu, offsetof(x64emu_t, mxcsr));
+                        SW(x4, wback, fixedaddress);
+                        break;
                     case 7:
                         INST_NAME("CLFLUSH Ed");
                         MESSAGE(LOG_DUMP, "Need Optimization?\n");
diff --git a/src/dynarec/rv64/dynarec_rv64_660f.c b/src/dynarec/rv64/dynarec_rv64_660f.c
index bea17833..44da6083 100644
--- a/src/dynarec/rv64/dynarec_rv64_660f.c
+++ b/src/dynarec/rv64/dynarec_rv64_660f.c
@@ -79,6 +79,48 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
 
         GOCOND(0x40, "CMOV", "Gw, Ew");
         #undef GO
+        case 0x28:
+            INST_NAME("MOVAPD Gx,Ex");
+            nextop = F8;
+            GETEX(x1, 0);
+            GETGX(x2);
+            SSE_LOOP_MV_Q(x3);
+            break;
+        case 0x2E:
+            // no special check...
+        case 0x2F:
+            if(opcode==0x2F) {INST_NAME("COMISD Gx, Ex");} else {INST_NAME("UCOMISD Gx, Ex");}
+            SETFLAGS(X_ALL, SF_SET);
+            nextop = F8;
+            GETGXSD(d0);
+            GETEXSD(v0, 0);
+            CLEAR_FLAGS();
+            // if isnan(d0) || isnan(v0)
+            IFX(X_ZF | X_PF | X_CF) {
+                FEQD(x3, d0, d0);
+                FEQD(x2, v0, v0);
+                AND(x2, x2, x3);
+                XORI(x2, x2, 1);
+                BEQ_MARK(x2, xZR);
+                ORI(xFlags, xFlags, (1<<F_ZF) | (1<<F_PF) | (1<<F_CF));
+                B_NEXT_nocond;
+            }
+            MARK;
+            // else if isless(d0, v0)
+            IFX(X_CF) {
+                FLTD(x2, d0, v0);
+                BEQ_MARK2(x2, xZR);
+                ORI(xFlags, xFlags, 1<<F_CF);
+                B_NEXT_nocond;
+            }
+            MARK2;
+            // else if d0 == v0
+            IFX(X_ZF) {
+                FEQD(x2, d0, v0);
+                CBZ_NEXT(x2);
+                ORI(xFlags, xFlags, 1<<F_ZF);
+            }
+            break;
         case 0x6C:
             INST_NAME("PUNPCKLQDQ Gx,Ex");
             nextop = F8;
diff --git a/src/dynarec/rv64/dynarec_rv64_f20f.c b/src/dynarec/rv64/dynarec_rv64_f20f.c
index 4eba1c3b..27e77a87 100644
--- a/src/dynarec/rv64/dynarec_rv64_f20f.c
+++ b/src/dynarec/rv64/dynarec_rv64_f20f.c
@@ -125,7 +125,51 @@ uintptr_t dynarec64_F20F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
             FSUBD(v0, v0, v1);
             break;
 
+        case 0xC2:
+            INST_NAME("CMPSD Gx, Ex, Ib");
+            nextop = F8;
+            GETGXSD(d0);
+            GETEXSD(d1, 1);
+            u8 = F8;
+            if ((u8&7) == 0) {                                      // Equal
+                FEQD(x2, d0, d1);
+            } else if ((u8&7) == 4) {                               // Not Equal or unordered
+                FEQD(x2, d0, d1);
+                XORI(x2, x2, 1);
+            } else {
+                // x2 = !(isnan(d0) || isnan(d1))
+                FEQD(x3, d0, d0);
+                FEQD(x2, d1, d1);
+                AND(x2, x2, x3);
 
+                switch(u8&7) {
+                case 1: BEQ_MARK(x2, xZR); FLTD(x2, d0, d1); break; // Less than
+                case 2: BEQ_MARK(x2, xZR); FLED(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);
+                    FLED(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);
+                    FLTD(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);
+            FMVDX(d0, x2);
+            break;
         default:
             DEFAULT;
     }
diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h
index cd795aa6..f7fb7a35 100644
--- a/src/dynarec/rv64/dynarec_rv64_helper.h
+++ b/src/dynarec/rv64/dynarec_rv64_helper.h
@@ -365,6 +365,15 @@
     SSE_LOOP_Q_ITEM(GX1, EX1, F, 0) \
     SSE_LOOP_Q_ITEM(GX1, EX1, F, 1)
 
+#define SSE_LOOP_MV_Q_ITEM(s, i)      \
+    LD(s, wback, fixedaddress+i*8);   \
+    SD(s, gback, i*8);
+
+// Loop for SSE opcode that moves 64bits value from wback to gback, use s as scratch.
+#define SSE_LOOP_MV_Q(s)     \
+    SSE_LOOP_MV_Q_ITEM(s, 0) \
+    SSE_LOOP_MV_Q_ITEM(s, 1)
+
 // CALL will use x6 for the call address. Return value can be put in ret (unless ret is -1)
 // R0 will not be pushed/popd if ret is -2
 #define CALL(F, ret) call_c(dyn, ninst, F, x6, ret, 1, 0)