about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/rv64/dynarec_rv64_0f.c60
-rw-r--r--src/dynarec/rv64/dynarec_rv64_df.c3
-rw-r--r--src/dynarec/rv64/dynarec_rv64_f20f.c37
-rw-r--r--src/dynarec/rv64/dynarec_rv64_helper.c10
-rw-r--r--src/dynarec/rv64/dynarec_rv64_helper.h3
5 files changed, 112 insertions, 1 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_0f.c b/src/dynarec/rv64/dynarec_rv64_0f.c
index b69cd487..22b21694 100644
--- a/src/dynarec/rv64/dynarec_rv64_0f.c
+++ b/src/dynarec/rv64/dynarec_rv64_0f.c
@@ -17,6 +17,7 @@
 #include "dynarec_native.h"
 #include "my_cpuid.h"
 #include "emu/x87emu_private.h"
+#include "emu/x64shaext.h"
 #include "bitutils.h"
 
 #include "rv64_printer.h"
@@ -387,6 +388,65 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
             // SSE3
             nextop = F8;
             switch (nextop) {
+                case 0xC8 ... 0xCD:
+                    u8 = nextop;
+                    switch (u8) {
+                        case 0xC8:
+                            INST_NAME("SHA1NEXTE Gx, Ex");
+                            break;
+                        case 0xC9:
+                            INST_NAME("SHA1MSG1 Gx, Ex");
+                            break;
+                        case 0xCA:
+                            INST_NAME("SHA1MSG2 Gx, Ex");
+                            break;
+                        case 0xCB:
+                            INST_NAME("SHA256RNDS2 Gx, Ex");
+                            break;
+                        case 0xCC:
+                            INST_NAME("SHA256MSG1 Gx, Ex");
+                            break;
+                        case 0xCD:
+                            INST_NAME("SHA256MSG2 Gx, Ex");
+                            break;
+                    }
+                    nextop = F8;
+                    if (MODREG) {
+                        ed = (nextop & 7) + (rex.b << 3);
+                        sse_reflect_reg(dyn, ninst, ed);
+                        ADDI(x2, xEmu, offsetof(x64emu_t, xmm[ed]));
+                    } else {
+                        SMREAD();
+                        addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 0, 0);
+                        if (ed != x2) {
+                            MV(x2, ed);
+                        }
+                    }
+                    GETG;
+                    sse_forget_reg(dyn, ninst, gd);
+                    ADDI(x1, xEmu, offsetof(x64emu_t, xmm[gd]));
+                    sse_reflect_reg(dyn, ninst, 0);
+                    switch (u8) {
+                        case 0xC8:
+                            CALL(sha1nexte, -1);
+                            break;
+                        case 0xC9:
+                            CALL(sha1msg1, -1);
+                            break;
+                        case 0xCA:
+                            CALL(sha1msg2, -1);
+                            break;
+                        case 0xCB:
+                            CALL(sha256rnds2, -1);
+                            break;
+                        case 0xCC:
+                            CALL(sha256msg1, -1);
+                            break;
+                        case 0xCD:
+                            CALL(sha256msg2, -1);
+                            break;
+                    }
+                    break;
                 case 0xF0:
                     INST_NAME("MOVBE Gd, Ed");
                     nextop = F8;
diff --git a/src/dynarec/rv64/dynarec_rv64_df.c b/src/dynarec/rv64/dynarec_rv64_df.c
index 08e603e5..2a2884c5 100644
--- a/src/dynarec/rv64/dynarec_rv64_df.c
+++ b/src/dynarec/rv64/dynarec_rv64_df.c
@@ -41,7 +41,8 @@ uintptr_t dynarec64_DF(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
     switch(nextop) {
         case 0xC0 ... 0xC7:
             INST_NAME("FFREEP STx");
-            DEFAULT;
+            // not handling Tag...
+            X87_POP_OR_FAIL(dyn, ninst, x3);
             break;
 
         case 0xE0:
diff --git a/src/dynarec/rv64/dynarec_rv64_f20f.c b/src/dynarec/rv64/dynarec_rv64_f20f.c
index 62b66544..04f23a70 100644
--- a/src/dynarec/rv64/dynarec_rv64_f20f.c
+++ b/src/dynarec/rv64/dynarec_rv64_f20f.c
@@ -34,6 +34,7 @@ uintptr_t dynarec64_F20F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
     int v0, v1;
     int q0;
     int d0, d1;
+    int s0, s1;
     int64_t fixedaddress, gdoffset;
     int unscaled;
 
@@ -272,6 +273,42 @@ uintptr_t dynarec64_F20F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
                 SD(x3, gback, gdoffset+8);
             }
             break;
+        case 0x7C:
+            INST_NAME("HADDPS Gx, Ex");
+            nextop = F8;
+            GETGX();
+            GETEX(x2, 0);
+            s0 = fpu_get_scratch(dyn);
+            s1 = fpu_get_scratch(dyn);
+            // GX->f[0] += GX->f[1];
+            FLW(s0, gback, gdoffset + 0);
+            FLW(s1, gback, gdoffset + 4);
+            FADDS(s0, s0, s1);
+            FSW(s0, gback, gdoffset + 0);
+            // GX->f[1] = GX->f[2] + GX->f[3];
+            FLW(s0, gback, gdoffset + 8);
+            FLW(s1, gback, gdoffset + 12);
+            FADDS(s0, s0, s1);
+            FSW(s0, gback, gdoffset + 4);
+            if (MODREG && gd == (nextop & 7) + (rex.b << 3)) {
+                // GX->f[2] = GX->f[0];
+                FLW(s1, gback, gdoffset + 0);
+                FSW(s1, gback, gdoffset + 8);
+                // GX->f[3] = GX->f[1];
+                FSW(s0, gback, gdoffset + 12);
+            } else {
+                // GX->f[2] = EX->f[0] + EX->f[1];
+                FLW(s0, wback, fixedaddress + 0);
+                FLW(s1, wback, fixedaddress + 4);
+                FADDS(s0, s0, s1);
+                FSW(s0, gback, gdoffset + 8);
+                // GX->f[3] = EX->f[2] + EX->f[3];
+                FLW(s0, wback, fixedaddress + 8);
+                FLW(s1, wback, fixedaddress + 12);
+                FADDS(s0, s0, s1);
+                FSW(s0, gback, gdoffset + 12);
+            }
+            break;
         case 0xC2:
             INST_NAME("CMPSD Gx, Ex, Ib");
             nextop = F8;
diff --git a/src/dynarec/rv64/dynarec_rv64_helper.c b/src/dynarec/rv64/dynarec_rv64_helper.c
index 19b4c316..7ef65dc8 100644
--- a/src/dynarec/rv64/dynarec_rv64_helper.c
+++ b/src/dynarec/rv64/dynarec_rv64_helper.c
@@ -1555,6 +1555,16 @@ static void sse_reflectcache(dynarec_rv64_t* dyn, int ninst, int s1)
         }
 }
 
+void sse_reflect_reg(dynarec_rv64_t* dyn, int ninst, int a)
+{
+    if (dyn->e.ssecache[a].v == -1)
+        return;
+    if (dyn->e.ssecache[a].single)
+        FSW(dyn->e.ssecache[a].reg, xEmu, offsetof(x64emu_t, xmm[a]));
+    else
+        FSD(dyn->e.ssecache[a].reg, xEmu, offsetof(x64emu_t, xmm[a]));
+}
+
 void fpu_pushcache(dynarec_rv64_t* dyn, int ninst, int s1, int not07)
 {
     // need to save 0..1 && 10..17 (maybe) && 28..31
diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h
index 3fb8e654..8b631a07 100644
--- a/src/dynarec/rv64/dynarec_rv64_helper.h
+++ b/src/dynarec/rv64/dynarec_rv64_helper.h
@@ -1177,6 +1177,7 @@ void* rv64_next(x64emu_t* emu, uintptr_t addr);
 #define sse_get_reg_empty     STEPNAME(sse_get_reg_empty)
 #define sse_forget_reg        STEPNAME(sse_forget_reg)
 #define sse_purge07cache      STEPNAME(sse_purge07cache)
+#define sse_reflect_reg       STEPNAME(sse_reflect_reg)
 
 #define fpu_pushcache       STEPNAME(fpu_pushcache)
 #define fpu_popcache        STEPNAME(fpu_popcache)
@@ -1377,6 +1378,8 @@ int sse_get_reg_empty(dynarec_rv64_t* dyn, int ninst, int s1, int a, int single)
 void sse_forget_reg(dynarec_rv64_t* dyn, int ninst, int a);
 // purge the XMM0..XMM7 cache (before function call)
 void sse_purge07cache(dynarec_rv64_t* dyn, int ninst, int s1);
+// Push current value to the cache
+void sse_reflect_reg(dynarec_rv64_t* dyn, int ninst, int a);
 
 // common coproc helpers
 // reset the cache