diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2025-04-30 15:47:48 +0200 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2025-04-30 15:47:48 +0200 |
| commit | 57f07446eab75538f5a100d763ce0f73834c96a0 (patch) | |
| tree | a2f5c78e59195a80fdfa0df01fbc0556628d80cd /src | |
| parent | 7b2e084170559b6df0bc97391b9bddfcd4a9d5d6 (diff) | |
| download | box64-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.c | 2 | ||||
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_avx_f3_0f.c | 14 | ||||
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_f30f.c | 14 |
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: |