about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2025-03-26 17:41:44 +0100
committerptitSeb <sebastien.chev@gmail.com>2025-03-26 17:41:44 +0100
commitcb5a52bf40d9f730710edba7f38675317fb58b90 (patch)
tree9731998e3d0f1b2a951a2ee94f3889a7705ac503 /src
parenteaa5f8feec4ed2d8f477753b5fc2ff9e50d1003c (diff)
downloadbox64-cb5a52bf40d9f730710edba7f38675317fb58b90.tar.gz
box64-cb5a52bf40d9f730710edba7f38675317fb58b90.zip
[ARM64_DYNAREC] Addedfastnan=0 code to (V)SQRTPS opcodes
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/arm64/dynarec_arm64_0f.c16
-rw-r--r--src/dynarec/arm64/dynarec_arm64_avx_0f.c18
2 files changed, 30 insertions, 4 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_0f.c b/src/dynarec/arm64/dynarec_arm64_0f.c
index 89a9af89..eb712db4 100644
--- a/src/dynarec/arm64/dynarec_arm64_0f.c
+++ b/src/dynarec/arm64/dynarec_arm64_0f.c
@@ -1065,8 +1065,20 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             INST_NAME("SQRTPS Gx, Ex");

             nextop = F8;

             GETEX(q0, 0, 0);

-            GETGX_empty(v0);

-            VFSQRTQS(v0, q0);

+            GETGX_empty(q1);

+            if(!BOX64ENV(dynarec_fastnan)) {

+                v0 = fpu_get_scratch(dyn, ninst);

+                v1 = fpu_get_scratch(dyn, ninst);

+                // check if any input value was NAN

+                VFCMEQQS(v0, q0, q0);    // 0 if NAN, 1 if not NAN

+                VFSQRTQS(q1, q0);

+                VFCMEQQS(v1, q1, q1);    // 0 => out is NAN

+                VBICQ(v1, v0, v1);      // forget it in any input was a NAN already

+                VSHLQ_32(v1, v1, 31);   // only keep the sign bit

+                VORRQ(q1, q1, v1);      // NAN -> -NAN

+            } else {

+                VFSQRTQS(q1, q0);

+            }

             break;

         case 0x52:

             INST_NAME("RSQRTPS Gx, Ex");

diff --git a/src/dynarec/arm64/dynarec_arm64_avx_0f.c b/src/dynarec/arm64/dynarec_arm64_avx_0f.c
index 412def45..b55bfc77 100644
--- a/src/dynarec/arm64/dynarec_arm64_avx_0f.c
+++ b/src/dynarec/arm64/dynarec_arm64_avx_0f.c
@@ -337,9 +337,23 @@ uintptr_t dynarec64_AVX_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int
             INST_NAME("VSQRTPS Gx, Ex");
             nextop = F8;
             SKIPTEST(x1);
+            if(!BOX64ENV(dynarec_fastnan)) {
+                d0 = fpu_get_scratch(dyn, ninst);
+                d1 = fpu_get_scratch(dyn, ninst);
+            }
             for(int l=0; l<1+vex.l; ++l) {
-                if(!l) { GETGX_empty_EX(q0, q1, 0); } else { GETGY_empty_EY(q0, q1); }
-                VFSQRTQS(q0, q1);
+                if(!l) { GETGX_empty_EX(v0, v1, 0); } else { GETGY_empty_EY(v0, v1); }
+                if(!BOX64ENV(dynarec_fastnan)) {
+                    // check if any input value was NAN
+                    VFCMEQQS(d0, v1, v1);    // 0 if NAN, 1 if not NAN
+                    VFSQRTQS(v0, v1);
+                    VFCMEQQS(d1, v0, v0);    // 0 => out is NAN
+                    VBICQ(d1, d0, d1);      // forget it in any input was a NAN already
+                    VSHLQ_32(d1, d1, 31);   // only keep the sign bit
+                    VORRQ(v0, v0, d1);      // NAN -> -NAN
+                } else {
+                    VFSQRTQS(v0, v1);
+                }
             }
             if(!vex.l) YMM0(gd);
             break;