about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorphorcys <phorcys@126.com>2025-04-18 23:09:34 +0800
committerGitHub <noreply@github.com>2025-04-18 17:09:34 +0200
commit518c860e5d275663785d88a62e8d11d36a0ee584 (patch)
tree596564dbec89929445e78ba6380ecb7049e57319 /src
parent053c389cfba933fe92b65cd6486e993d3fb1ab74 (diff)
downloadbox64-518c860e5d275663785d88a62e8d11d36a0ee584.tar.gz
box64-518c860e5d275663785d88a62e8d11d36a0ee584.zip
[LA64_DYNAREC]Add/opt more SSE/MMX ops (#2543)
* Add SSE2 op MASKMOVDQU.
 * Opt PSADBW.
 * Add SSE3 HSUBPD op.
 * Add mmx PALIGNR op.
 * Fix PSRLDQ.
 * Fix PSRAW Gx,Ex PSRAW Gm,Em.
     mmx/sse get COUNT from Em/Ex as an 64bit unsigned...
     testsuite with shift 0x4,0x4,0x4,0x4, result COUNT as 0x04040404.
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/la64/dynarec_la64_0f.c20
-rw-r--r--src/dynarec/la64/dynarec_la64_660f.c64
2 files changed, 60 insertions, 24 deletions
diff --git a/src/dynarec/la64/dynarec_la64_0f.c b/src/dynarec/la64/dynarec_la64_0f.c
index 0f2290cb..dd6639a2 100644
--- a/src/dynarec/la64/dynarec_la64_0f.c
+++ b/src/dynarec/la64/dynarec_la64_0f.c
@@ -526,6 +526,24 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
         case 0x3A: // more SSE3 opcodes
             opcode = F8;
             switch (opcode) {
+                case 0x0F:
+                    INST_NAME("PALIGNR Gm, Em, Ib");
+                    nextop = F8;
+                    GETGM(q0);
+                    GETEM(q1, 1);
+                    u8 = F8;
+                    if (u8 > 15) {
+                        VXOR_V(q0, q0, q0);
+                    } else if (!u8) {
+                        VEXTRINS_D(q0, q1, VEXTRINS_IMM_4_0(0, 0));
+                    } else {
+                        d0 = fpu_get_scratch(dyn);
+                        VOR_V(d0, q0, q0);
+                        VSHUF4I_D(d0, q1, 0b00010010);
+                        VBSRL_V(d0, d0, u8);
+                        VEXTRINS_D(q0, d0, 0);
+                    }
+                    break;
                 case 0xCC:
                     INST_NAME("SHA1RNDS4 Gx, Ex, Ib");
                     nextop = F8;
@@ -1917,7 +1935,7 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
             GETGM(v0);
             GETEM(v1, 0);
             q0 = fpu_get_scratch(dyn);
-            VMINI_HU(q0, v1, 15);
+            VMINI_DU(q0, v1, 15);
             VREPLVEI_H(q0, q0, 0);
             VSRA_H(v0, v0, q0);
             break;
diff --git a/src/dynarec/la64/dynarec_la64_660f.c b/src/dynarec/la64/dynarec_la64_660f.c
index c0619ff8..c7ae2a56 100644
--- a/src/dynarec/la64/dynarec_la64_660f.c
+++ b/src/dynarec/la64/dynarec_la64_660f.c
@@ -1787,7 +1787,7 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
                     u8 = F8;
                     if (u8) {
                         if (u8 > 15) {
-                            XVOR_V(q0, q0, q0);
+                            VXOR_V(q0, q0, q0);
                         } else {
                             VBSRL_V(q0, q0, u8);
                         }
@@ -1869,6 +1869,30 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
                 VOR_V(q1, v0, v1);
             }
             break;
+        case 0x7D:
+            INST_NAME("HSUBPD Gx, Ex");
+            nextop = F8;
+            GETGX(q1, 1);
+            GETEX(q0, 0, 0);
+            d0 = fpu_get_scratch(dyn);
+            VPICKEV_D(d0, q0, q1);
+            VPICKOD_D(q1, q0, q1);
+            if (!BOX64ENV(dynarec_fastnan)) {
+                v0 = fpu_get_scratch(dyn);
+                v1 = fpu_get_scratch(dyn);
+                VFCMP_D(v0, d0, q1, cUN);
+            }
+            VFSUB_D(q1, d0, q1);
+            if (!BOX64ENV(dynarec_fastnan)) {
+                VFCMP_D(v1, q1, q1, cUN);
+                VANDN_V(v0, v0, v1);
+                VLDI(v1, 0b011111111000); // broadcast 0xFFFFFFFFFFFFFFF8
+                VSLLI_D(v1, v1, 48);
+                VAND_V(v1, v0, v1);
+                VANDN_V(v0, v0, q1);
+                VOR_V(q1, v0, v1);
+            }
+            break;
         case 0x7E:
             INST_NAME("MOVD Ed,Gx");
             nextop = F8;
@@ -2245,7 +2269,7 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
             GETGX(q0, 1);
             GETEX(q1, 0, 0);
             v0 = fpu_get_scratch(dyn);
-            VMINI_HU(v0, q1, 15);
+            VMINI_DU(v0, q1, 15);
             VREPLVEI_H(v0, v0, 0);
             VSRA_H(q0, q0, v0);
             break;
@@ -2446,27 +2470,21 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
             d0 = fpu_get_scratch(dyn);
             d1 = fpu_get_scratch(dyn);
             VABSD_BU(q0, q0, q1);
-
-            // 8bit -> 16bit merge
-            VPICKEV_B(d0, q0, q0);
-            VPICKOD_B(d1, q0, q0);
-            VEXTH_HU_BU(d0, d0);
-            VEXTH_HU_BU(d1, d1);
-            VADD_H(q0, d0, d1);
-
-            // 16bit to 32bit merge
-            VPICKEV_H(d0, q0, q0);
-            VPICKOD_H(d1, q0, q0);
-            VEXTH_WU_HU(d0, d0);
-            VEXTH_WU_HU(d1, d1);
-            VADD_W(q0, d0, d1);
-
-            // 32bit to 64bit merge
-            VPICKEV_W(d0, q0, q0);
-            VPICKOD_W(d1, q0, q0);
-            VEXTH_DU_WU(d0, d0);
-            VEXTH_DU_WU(d1, d1);
-            VADD_D(q0, d0, d1);
+            VHADDW_HU_BU(q0, q0, q0);
+            VHADDW_WU_HU(q0, q0, q0);
+            VHADDW_DU_WU(q0, q0, q0);
+            break;
+        case 0xF7:
+            INST_NAME("MASKMOVDQU Gx, Ex");
+            nextop = F8;
+            GETGX(v0, 1);
+            GETEX(v1, 0, 0);
+            q0 = fpu_get_scratch(dyn);
+            q1 = fpu_get_scratch(dyn);
+            VSLTI_B(q1, v1, 0); // q1 = byte selection mask
+            VLD(q0, xRDI, 0);
+            VBITSEL_V(q0, q0, v0, q1); // sel v0 if mask is 1
+            VST(q0, xRDI, 0);
             break;
         case 0xF8:
             INST_NAME("PSUBB Gx,Ex");