about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorYang Liu <liuyang22@iscas.ac.cn>2025-01-23 15:58:30 +0800
committerGitHub <noreply@github.com>2025-01-23 08:58:30 +0100
commit276191cdcfb0338243b4368672c4eb9159b7a692 (patch)
treebbe2d6df5e74726fec952e8a5db651d8f99f8a78 /src
parent8438b6174759b6c21d2239939bba4f1b37c4fcd1 (diff)
downloadbox64-276191cdcfb0338243b4368672c4eb9159b7a692.tar.gz
box64-276191cdcfb0338243b4368672c4eb9159b7a692.zip
[LA64_DYNAREC] Added fastnan handling to more 0F opcodes (fixes CI) (#2285)
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/la64/dynarec_la64_0f.c54
1 files changed, 48 insertions, 6 deletions
diff --git a/src/dynarec/la64/dynarec_la64_0f.c b/src/dynarec/la64/dynarec_la64_0f.c
index 70b20bd7..a899a365 100644
--- a/src/dynarec/la64/dynarec_la64_0f.c
+++ b/src/dynarec/la64/dynarec_la64_0f.c
@@ -563,8 +563,22 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
             INST_NAME("MULPS Gx, Ex");
             nextop = F8;
             GETEX(q0, 0, 0);
-            GETGX(v0, 1);
-            VFMUL_S(v0, v0, q0);
+            GETGX(q1, 1);
+            if (!BOX64ENV(dynarec_fastnan)) {
+                v0 = fpu_get_scratch(dyn);
+                v1 = fpu_get_scratch(dyn);
+                VFCMP_S(v0, q0, q1, cUN);
+            }
+            VFMUL_S(q1, q1, q0);
+            if (!BOX64ENV(dynarec_fastnan)) {
+                VFCMP_S(v1, q1, q1, cUN);
+                VANDN_V(v0, v0, v1);
+                VLDI(v1, 0b011111111100); // broadcast 0xFFFFFFFFFFFFFFFC
+                VSLLI_W(v1, v1, 20);
+                VAND_V(v1, v0, v1);
+                VANDN_V(v0, v0, q1);
+                VOR_V(q1, v0, v1);
+            }
             break;
         case 0x5A:
             INST_NAME("CVTPS2PD Gx, Ex");
@@ -584,8 +598,22 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
             INST_NAME("SUBPS Gx, Ex");
             nextop = F8;
             GETEX(q0, 0, 0);
-            GETGX(v0, 1);
-            VFSUB_S(v0, v0, q0);
+            GETGX(q1, 1);
+            if (!BOX64ENV(dynarec_fastnan)) {
+                v0 = fpu_get_scratch(dyn);
+                v1 = fpu_get_scratch(dyn);
+                VFCMP_S(v0, q0, q1, cUN);
+            }
+            VFSUB_S(q1, q1, q0);
+            if (!BOX64ENV(dynarec_fastnan)) {
+                VFCMP_S(v1, q1, q1, cUN);
+                VANDN_V(v0, v0, v1);
+                VLDI(v1, 0b011111111100); // broadcast 0xFFFFFFFFFFFFFFFC
+                VSLLI_W(v1, v1, 20);
+                VAND_V(v1, v0, v1);
+                VANDN_V(v0, v0, q1);
+                VOR_V(q1, v0, v1);
+            }
             break;
         case 0x5D:
             INST_NAME("MINPS Gx, Ex");
@@ -606,8 +634,22 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
             INST_NAME("DIVPS Gx, Ex");
             nextop = F8;
             GETEX(q0, 0, 0);
-            GETGX(v0, 1);
-            VFDIV_S(v0, v0, q0);
+            GETGX(q1, 1);
+            if (!BOX64ENV(dynarec_fastnan)) {
+                v0 = fpu_get_scratch(dyn);
+                v1 = fpu_get_scratch(dyn);
+                VFCMP_S(v0, q0, q1, cUN);
+            }
+            VFDIV_S(q1, q1, q0);
+            if (!BOX64ENV(dynarec_fastnan)) {
+                VFCMP_S(v1, q1, q1, cUN);
+                VANDN_V(v0, v0, v1);
+                VLDI(v1, 0b011111111100); // broadcast 0xFFFFFFFFFFFFFFFC
+                VSLLI_W(v1, v1, 20);
+                VAND_V(v1, v0, v1);
+                VANDN_V(v0, v0, q1);
+                VOR_V(q1, v0, v1);
+            }
             break;
         case 0x5F:
             INST_NAME("MAXPS Gx, Ex");