about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2025-04-30 15:47:48 +0200
committerptitSeb <sebastien.chev@gmail.com>2025-04-30 15:47:48 +0200
commit57f07446eab75538f5a100d763ce0f73834c96a0 (patch)
treea2f5c78e59195a80fdfa0df01fbc0556628d80cd /src
parent7b2e084170559b6df0bc97391b9bddfcd4a9d5d6 (diff)
downloadbox64-57f07446eab75538f5a100d763ce0f73834c96a0.tar.gz
box64-57f07446eab75538f5a100d763ce0f73834c96a0.zip
[ARM64_DYNAREC] Add fastnan=0 handling in (V)SQRTSS opcodes
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/arm64/dynarec_arm64_avx_f2_0f.c2
-rw-r--r--src/dynarec/arm64/dynarec_arm64_avx_f3_0f.c14
-rw-r--r--src/dynarec/arm64/dynarec_arm64_f30f.c14
3 files changed, 27 insertions, 3 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_avx_f2_0f.c b/src/dynarec/arm64/dynarec_arm64_avx_f2_0f.c
index a07dcee8..79a2b651 100644
--- a/src/dynarec/arm64/dynarec_arm64_avx_f2_0f.c
+++ b/src/dynarec/arm64/dynarec_arm64_avx_f2_0f.c
@@ -220,7 +220,7 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
             if(!BOX64ENV(dynarec_fastnan)) {
                 FCMEQD(q1, d1, d1);    // 0 => out is NAN
                 VBIC(q1, q0, q1);      // forget it in any input was a NAN already
-                VSHLQ_64(q1, q1, 63);   // only keep the sign bit
+                SHL_64(q1, q1, 63);   // only keep the sign bit
                 VORR(d1, d1, q1);      // NAN -> -NAN
             }
             if(v0!=v2) {
diff --git a/src/dynarec/arm64/dynarec_arm64_avx_f3_0f.c b/src/dynarec/arm64/dynarec_arm64_avx_f3_0f.c
index b47f4160..12f11648 100644
--- a/src/dynarec/arm64/dynarec_arm64_avx_f3_0f.c
+++ b/src/dynarec/arm64/dynarec_arm64_avx_f3_0f.c
@@ -205,12 +205,24 @@ uintptr_t dynarec64_AVX_F3_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
             break;
 
         case 0x51:
-            INST_NAME("SQRTSS Gx, Ex");
+            INST_NAME("VSQRTSS Gx, Ex");
             nextop = F8;
             GETEXSS(d0, 0, 0);
             GETGX_empty_VX(v0, v2);
             d1 = fpu_get_scratch(dyn, ninst);
+            if(!BOX64ENV(dynarec_fastnan)) {
+                q0 = fpu_get_scratch(dyn, ninst);
+                q1 = fpu_get_scratch(dyn, ninst);
+                // check if any input value was NAN
+                FCMEQS(q0, v1, v1);    // 0 if NAN, 1 if not NAN
+            }
             FSQRTS(d1, d0);
+            if(!BOX64ENV(dynarec_fastnan)) {
+                FCMEQS(q1, d1, d1);    // 0 => out is NAN
+                VBIC(q1, q0, q1);      // forget it in any input was a NAN already
+                VSHL_32(q1, q1, 31);   // only keep the sign bit
+                VORR(d1, d1, q1);      // NAN -> -NAN
+            }
             if(v0!=v2) VMOVQ(v0, v2);
             VMOVeS(v0, 0, d1, 0);
             YMM0(gd);
diff --git a/src/dynarec/arm64/dynarec_arm64_f30f.c b/src/dynarec/arm64/dynarec_arm64_f30f.c
index 558491f8..35cd6d17 100644
--- a/src/dynarec/arm64/dynarec_arm64_f30f.c
+++ b/src/dynarec/arm64/dynarec_arm64_f30f.c
@@ -218,7 +218,19 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
             GETGX(v0, 1);

             d1 = fpu_get_scratch(dyn, ninst);

             GETEXSS(d0, 0, 0);

-            FSQRTS(d1, d0);

+            if(!BOX64ENV(dynarec_fastnan)) {

+                v0 = fpu_get_scratch(dyn, ninst);

+                v1 = fpu_get_scratch(dyn, ninst);

+                // check if any input value was NAN

+                FCMEQS(v0, d0, d0);    // 0 if NAN, 1 if not NAN

+                FSQRTS(d1, d0);

+                FCMEQS(v1, d1, d1);    // 0 => out is NAN

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

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

+                VORR(d1, d1, v1);      // NAN -> -NAN

+            } else {

+                FSQRTS(d1, d0);

+            }

             VMOVeS(v0, 0, d1, 0);

             break;

         case 0x52: