From 7ccd64dadd5c8ab704fc102a1dd9304fefd0784e Mon Sep 17 00:00:00 2001 From: Paulo Matos Date: Thu, 26 Sep 2024 13:17:02 +0200 Subject: [PATCH] Fix FScale'ing zero that should return zero Added tests will fail without the current patch. This will properly check if we return the correct sign of zero. --- FEXCore/Source/Common/SoftFloat.h | 4 + .../Core/Interpreter/Fallbacks/F80Fallbacks.h | 7 +- unittests/ASM/X87/FScale-Zero.asm | 85 +++++++++++++++++++ unittests/ASM/X87_F64/FScale-Zero_F64.asm | 81 ++++++++++++++++++ 4 files changed, 175 insertions(+), 2 deletions(-) create mode 100644 unittests/ASM/X87/FScale-Zero.asm create mode 100644 unittests/ASM/X87_F64/FScale-Zero_F64.asm diff --git a/FEXCore/Source/Common/SoftFloat.h b/FEXCore/Source/Common/SoftFloat.h index 2c0e8a2240..66c8bf3092 100644 --- a/FEXCore/Source/Common/SoftFloat.h +++ b/FEXCore/Source/Common/SoftFloat.h @@ -262,6 +262,10 @@ struct FEX_PACKED X80SoftFloat { return Result; #else + extFloat80_t Zero {0, 0}; + if (extF80_eq(state, lhs, Zero)) { + return lhs; + } X80SoftFloat Int = FRNDINT(state, rhs, softfloat_round_minMag); LIBRARY_PRECISION Src2_d = Int.ToFMax(state); Src2_d = exp2l(Src2_d); diff --git a/FEXCore/Source/Interface/Core/Interpreter/Fallbacks/F80Fallbacks.h b/FEXCore/Source/Interface/Core/Interpreter/Fallbacks/F80Fallbacks.h index d1e21c3d54..37e901176b 100644 --- a/FEXCore/Source/Interface/Core/Interpreter/Fallbacks/F80Fallbacks.h +++ b/FEXCore/Source/Interface/Core/Interpreter/Fallbacks/F80Fallbacks.h @@ -322,8 +322,11 @@ struct OpHandlers { template<> struct OpHandlers { static double handle(uint16_t FCW, double src1, double src2) { - double trunc = (double)(int64_t)(src2); // truncate - return src1 * exp2(trunc); + if (src1 == 0.0) { + return src1; + } + double trun = trunc(src2); + return src1 * exp2(trun); } }; diff --git a/unittests/ASM/X87/FScale-Zero.asm b/unittests/ASM/X87/FScale-Zero.asm new file mode 100644 index 0000000000..57db659f1d --- /dev/null +++ b/unittests/ASM/X87/FScale-Zero.asm @@ -0,0 +1,85 @@ +%ifdef CONFIG +{ + "RegData": { + "R8": "0", + "R9": "0", + "R10": "0", + "R11": "0", + "R12": "0", + "R13": "0x8000000000000000" + } +} +%endif + +section .data + neg_zero dq 0x8000000000000000 ; -0.0 + +section .bss + align 8 + intstor resq 1 + +section .text +global _start + +_start: +; scale by zero (st1 == 0) +mov rax, 0 +mov qword [rel intstor], rax +finit +fild qword [rel intstor] +fldz +fscale +fst qword [rel intstor] +mov r8, [rel intstor] + +; scale by zero (st1 == 1) +mov rax, 1 +mov qword [rel intstor], rax +finit +fild qword [rel intstor] +fldz +fscale +fst qword [rel intstor] +mov r9, [rel intstor] + +; scale by zero (st1 == 100) +mov rax, 100 +mov qword [rel intstor], rax +finit +fild qword [rel intstor] +fldz +fscale +fst qword [rel intstor] +mov r10, [rel intstor] + +; scale by zero (st1 == 1024) +mov rax, 1024 +mov qword [rel intstor], rax +finit +fild qword [rel intstor] +fldz +fscale +fst qword [rel intstor] +mov r11, [rel intstor] + +; scale by zero (st1 == 1048576) +mov rax, 1048576 +mov qword [rel intstor], rax +finit +fild qword [rel intstor] +fldz +fscale +fst qword [rel intstor] +mov r12, [rel intstor] + +; tests scaling negative zero +mov rax, 1048576 +mov qword [rel intstor], rax +finit +fild qword [rel intstor] +fld qword [rel neg_zero] +fscale +fst qword [rel intstor] +mov r13, [rel intstor] + +hlt diff --git a/unittests/ASM/X87_F64/FScale-Zero_F64.asm b/unittests/ASM/X87_F64/FScale-Zero_F64.asm new file mode 100644 index 0000000000..b3c14301db --- /dev/null +++ b/unittests/ASM/X87_F64/FScale-Zero_F64.asm @@ -0,0 +1,81 @@ +%ifdef CONFIG +{ + "RegData": { + "R8": "0", + "R9": "0", + "R10": "0", + "R11": "0", + "R12": "0" + }, + "Env": { "FEX_X87REDUCEDPRECISION" : "1" } +} +%endif + +section .data + neg_zero dq 0x8000000000000000 ; -0.0 + +section .bss + intstor: resq 1 + +section .text +; scale by zero (st1 == 0) +mov rax, 0 +mov qword [rel intstor], rax +finit +fild qword [rel intstor] +fldz +fscale +fst qword [rel intstor] +mov r8, [rel intstor] + +; scale by zero (st1 == 1) +mov rax, 1 +mov qword [rel intstor], rax +finit +fild qword [rel intstor] +fldz +fscale +fst qword [rel intstor] +mov r9, [rel intstor] + +; scale by zero (st1 == 100) +mov rax, 100 +mov qword [rel intstor], rax +finit +fild qword [rel intstor] +fldz +fscale +fst qword [rel intstor] +mov r10, [rel intstor] + +; scale by zero (st1 == 1024) +mov rax, 1024 +mov qword [rel intstor], rax +finit +fild qword [rel intstor] +fldz +fscale +fst qword [rel intstor] +mov r11, [rel intstor] + +; scale by zero (st1 == 1048576) +mov rax, 1048576 +mov qword [rel intstor], rax +finit +fild qword [rel intstor] +fldz +fscale +fst qword [rel intstor] +mov r12, [rel intstor] + +; tests scaling negative zero +mov rax, 1048576 +mov qword [rel intstor], rax +finit +fild qword [rel intstor] +fld qword [rel neg_zero] +fscale +fst qword [rel intstor] +mov r13, [rel intstor] + +hlt