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 | |
| parent | d94b47d1b0c76929324dde744f0b8e3ad02ca374 (diff) | |
| download | box64-3faf66a36bd02eea7d1e6e338f8de4151a3593fd.tar.gz box64-3faf66a36bd02eea7d1e6e338f8de4151a3593fd.zip | |
Some more NAN bordercase handling ([DYNAREC] too, but made FASTNAN default)
| -rwxr-xr-x | CMakeLists.txt | 4 | ||||
| -rwxr-xr-x | src/dynarec/arm64/dynarec_arm64_660f.c | 34 | ||||
| -rwxr-xr-x | src/dynarec/arm64/dynarec_arm64_f20f.c | 42 | ||||
| -rw-r--r-- | src/emu/x64run660f.c | 22 | ||||
| -rw-r--r-- | src/emu/x64runf20f.c | 12 | ||||
| -rwxr-xr-x | src/main.c | 6 |
6 files changed, 100 insertions, 20 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index d1b498fe..e402f67a 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -705,11 +705,13 @@ add_test(test16 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64} -D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref16.txt -P ${CMAKE_SOURCE_DIR}/runTest.cmake ) -add_test(test17 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64} +add_test(sse ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64} -D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test17 -D TEST_OUTPUT=tmpfile17.txt -D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref17.txt -P ${CMAKE_SOURCE_DIR}/runTest.cmake ) +set_tests_properties(sse PROPERTIES ENVIRONMENT "BOX64_DYNAREC_FASTNAN=0") + add_test(aes ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64} -D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test18 -D TEST_OUTPUT=tmpfile18.txt -D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref18.txt 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"); diff --git a/src/emu/x64run660f.c b/src/emu/x64run660f.c index 5fe52958..ac255a0f 100644 --- a/src/emu/x64run660f.c +++ b/src/emu/x64run660f.c @@ -847,8 +847,15 @@ int Run660F(x64emu_t *emu, rex_t rex) nextop = F8; GETEX(0); GETGX; - GX->d[0] += EX->d[0]; - GX->d[1] += EX->d[1]; + for(int i=0; i<2; ++i) { + #ifndef NOALIGN + // add generate a -NAN only if doing inf + -inf + if((isinf(GX->d[i]) && isinf(EX->d[i]) && (EX->q[i]&0x8000000000000000LL)!=(GX->q[i]&0x8000000000000000LL))) + GX->d[i] = -NAN; + else + #endif + GX->d[i] += EX->d[i]; + } break; case 0x59: /* MULPD Gx, Ex */ nextop = F8; @@ -907,8 +914,15 @@ int Run660F(x64emu_t *emu, rex_t rex) nextop = F8; GETEX(0); GETGX; - GX->d[0] -= EX->d[0]; - GX->d[1] -= EX->d[1]; + for(int i=0; i<2; ++i) { + #ifndef NOALIGN + // sub generate a -NAN only if doing inf - inf + if((isinf(GX->d[i]) && isinf(EX->d[i]) && (EX->q[i]&0x8000000000000000LL)==(GX->q[i]&0x8000000000000000LL))) + GX->d[i] = -NAN; + else + #endif + GX->d[i] -= EX->d[i]; + } break; case 0x5D: /* MINPD Gx, Ex */ nextop = F8; diff --git a/src/emu/x64runf20f.c b/src/emu/x64runf20f.c index 3ecf43ef..aebf434d 100644 --- a/src/emu/x64runf20f.c +++ b/src/emu/x64runf20f.c @@ -137,6 +137,12 @@ int RunF20F(x64emu_t *emu, rex_t rex) nextop = F8; GETEX(0); GETGX; + #ifndef NOALIGN + // add generate a -NAN only if doing inf + -inf + if((isinf(GX->d[0]) && isinf(EX->d[0]) && (EX->q[0]&0x8000000000000000LL)!=(GX->q[0]&0x8000000000000000LL))) + GX->d[0] = -NAN; + else + #endif GX->d[0] += EX->d[0]; break; case 0x59: /* MULSD Gx, Ex */ @@ -162,6 +168,12 @@ int RunF20F(x64emu_t *emu, rex_t rex) nextop = F8; GETEX(0); GETGX; + #ifndef NOALIGN + // sub generate a -NAN only if doing inf - inf + if((isinf(GX->d[0]) && isinf(EX->d[0]) && (EX->q[0]&0x8000000000000000LL)==(GX->q[0]&0x8000000000000000LL))) + GX->d[0] = -NAN; + else + #endif GX->d[0] -= EX->d[0]; break; case 0x5D: /* MINSD Gx, Ex */ diff --git a/src/main.c b/src/main.c index a58bb5b0..94d6b3d4 100755 --- a/src/main.c +++ b/src/main.c @@ -46,7 +46,7 @@ int box64_dynarec_forced = 0; int box64_dynarec_bigblock = 1; int box64_dynarec_strongmem = 0; int box64_dynarec_x87double = 0; -int box64_dynarec_fastnan = 0; +int box64_dynarec_fastnan = 1; uintptr_t box64_nodynarec_start = 0; uintptr_t box64_nodynarec_end = 0; #ifdef ARM64 @@ -425,8 +425,8 @@ void LoadLogEnv() if(p[0]>='0' && p[0]<='1') box64_dynarec_fastnan = p[0]-'0'; } - if(box64_dynarec_fastnan) - printf_log(LOG_INFO, "Dynarec will not try to normalize generated NAN\n"); + if(!box64_dynarec_fastnan) + printf_log(LOG_INFO, "Dynarec will try to normalize generated NAN\n"); } p = getenv("BOX64_NODYNAREC"); if(p) { |