diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2022-04-16 08:59:28 +0200 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2022-04-16 08:59:28 +0200 |
| commit | 3faf66a36bd02eea7d1e6e338f8de4151a3593fd (patch) | |
| tree | 29ca2dfacbaa7c92781fd00545241d8b1a1bbe4d /src/dynarec | |
| parent | d94b47d1b0c76929324dde744f0b8e3ad02ca374 (diff) | |
| download | box64-3faf66a36bd02eea7d1e6e338f8de4151a3593fd.tar.gz box64-3faf66a36bd02eea7d1e6e338f8de4151a3593fd.zip | |
Some more NAN bordercase handling ([DYNAREC] too, but made FASTNAN default)
Diffstat (limited to 'src/dynarec')
| -rwxr-xr-x | src/dynarec/arm64/dynarec_arm64_660f.c | 34 | ||||
| -rwxr-xr-x | src/dynarec/arm64/dynarec_arm64_f20f.c | 42 |
2 files changed, 64 insertions, 12 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_660f.c b/src/dynarec/arm64/dynarec_arm64_660f.c index ae6b04d0..75d40541 100755 --- a/src/dynarec/arm64/dynarec_arm64_660f.c +++ b/src/dynarec/arm64/dynarec_arm64_660f.c @@ -693,8 +693,21 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n INST_NAME("ADDPD Gx, Ex"); nextop = F8; GETEX(q0, 0, 0); - GETGX(v0, 1); - VFADDQD(v0, v0, q0); + GETGX(q1, 1); + if(!box64_dynarec_fastnan) { + v0 = fpu_get_scratch(dyn); + v1 = fpu_get_scratch(dyn); + // check if any input value was NAN + VFMAXQD(v0, q0, q1); // propagate NAN + VFCMEQQD(v0, v0, v0); // 0 if NAN, 1 if not NAN + } + VFADDQD(q1, q1, q0); + if(!box64_dynarec_fastnan) { + VFCMEQQD(v1, q1, q1); // 0 => out is NAN + VBICQ(v1, v0, v1); // forget it in any input was a NAN already + VSHLQ_64(v1, v1, 63); // only keep the sign bit + VORRQ(q1, q1, v1); // NAN -> -NAN + } break; case 0x59: INST_NAME("MULPD Gx, Ex"); @@ -752,8 +765,21 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n INST_NAME("SUBPD Gx, Ex"); nextop = F8; GETEX(q0, 0, 0); - GETGX(v0, 1); - VFSUBQD(v0, v0, q0); + GETGX(q1, 1); + if(!box64_dynarec_fastnan) { + v0 = fpu_get_scratch(dyn); + v1 = fpu_get_scratch(dyn); + // check if any input value was NAN + VFMAXQD(v0, q0, q1); // propagate NAN + VFCMEQQD(v0, v0, v0); // 0 if NAN, 1 if not NAN + } + VFSUBQD(q1, q1, q0); + if(!box64_dynarec_fastnan) { + VFCMEQQD(v1, q1, q1); // 0 => out is NAN + VBICQ(v1, v0, v1); // forget it in any input was a NAN already + VSHLQ_64(v1, v1, 63); // only keep the sign bit + VORRQ(q1, q1, v1); // NAN -> -NAN + } break; case 0x5D: INST_NAME("MINPD Gx, Ex"); diff --git a/src/dynarec/arm64/dynarec_arm64_f20f.c b/src/dynarec/arm64/dynarec_arm64_f20f.c index f6169f3a..cc9c1c8a 100755 --- a/src/dynarec/arm64/dynarec_arm64_f20f.c +++ b/src/dynarec/arm64/dynarec_arm64_f20f.c @@ -185,11 +185,24 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n case 0x58: INST_NAME("ADDSD Gx, Ex"); nextop = F8; - GETGX(v0, 1); - d1 = fpu_get_scratch(dyn); + GETGX(d1, 1); + v1 = fpu_get_scratch(dyn); GETEX(d0, 0, 0); - FADDD(d1, v0, d0); // the high part of the vector is erased... - VMOVeD(v0, 0, d1, 0); + if(!box64_dynarec_fastnan) { + v0 = fpu_get_scratch(dyn); + q0 = fpu_get_scratch(dyn); + // check if any input value was NAN + FMAXD(v0, d0, d1); // propagate NAN + FCMEQD(v0, v0, v0); // 0 if NAN, 1 if not NAN + } + FADDD(v1, d1, d0); // the high part of the vector is erased... + if(!box64_dynarec_fastnan) { + FCMEQD(q0, v1, v1); // 0 => out is NAN + VBIC(q0, v0, q0); // forget it in any input was a NAN already + SHL_64(q0, q0, 63); // only keep the sign bit + VORR(v1, v1, q0); // NAN -> -NAN + } + VMOVeD(d1, 0, v1, 0); break; case 0x59: INST_NAME("MULSD Gx, Ex"); @@ -226,11 +239,24 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n case 0x5C: INST_NAME("SUBSD Gx, Ex"); nextop = F8; - GETGX(v0, 1); - d1 = fpu_get_scratch(dyn); + GETGX(d1, 1); + v1 = fpu_get_scratch(dyn); GETEX(d0, 0, 0); - FSUBD(d1, v0, d0); - VMOVeD(v0, 0, d1, 0); + if(!box64_dynarec_fastnan) { + v0 = fpu_get_scratch(dyn); + q0 = fpu_get_scratch(dyn); + // check if any input value was NAN + FMAXD(v0, d0, d1); // propagate NAN + FCMEQD(v0, v0, v0); // 0 if NAN, 1 if not NAN + } + FSUBD(v1, d1, d0); + if(!box64_dynarec_fastnan) { + FCMEQD(q0, v1, v1); // 0 => out is NAN + VBIC(q0, v0, q0); // forget it in any input was a NAN already + SHL_64(q0, q0, 63); // only keep the sign bit + VORR(v1, v1, q0); // NAN -> -NAN + } + VMOVeD(d1, 0, v1, 0); break; case 0x5D: INST_NAME("MINSD Gx, Ex"); |