From b85afdfd258cb959893d28ae194db9118d3e6f5c Mon Sep 17 00:00:00 2001 From: Timo Kreuzer Date: Sat, 29 May 2021 19:40:30 +0200 Subject: [PATCH] [CRT] Implement portable + amd64 asm version of fabs/fabsf Note: older versions of ML64 are broken and don't understand the register form of movq. See https://stackoverflow.com/questions/24789339/move-quadword-between-xmm-and-general-purpose-register-in-ml64 --- modules/rostests/apitests/crt/fabs.c | 4 +-- sdk/lib/crt/math/amd64/fabs.S | 45 ++++++++++++++++++------- sdk/lib/crt/math/amd64/fabsf.S | 49 ++++++++++++++++++++++++++++ sdk/lib/crt/math/arm/fabs.s | 24 -------------- sdk/lib/crt/math/fabs.c | 38 +++++++++++++++++++++ sdk/lib/crt/math/fabsf.c | 26 +++++++++++---- sdk/lib/crt/math/math.cmake | 11 ++++--- 7 files changed, 149 insertions(+), 48 deletions(-) create mode 100644 sdk/lib/crt/math/amd64/fabsf.S delete mode 100644 sdk/lib/crt/math/arm/fabs.s create mode 100644 sdk/lib/crt/math/fabs.c diff --git a/modules/rostests/apitests/crt/fabs.c b/modules/rostests/apitests/crt/fabs.c index 88fd9fb8410..eec1f761757 100644 --- a/modules/rostests/apitests/crt/fabs.c +++ b/modules/rostests/apitests/crt/fabs.c @@ -20,7 +20,7 @@ static TESTENTRY_DBL s_fabs_tests[] = { /* Special values */ { 0x7FF0000000000000ull /* INF */, 0x7FF0000000000000ull /* INF */ }, -#ifdef _M_AMD64 +#ifndef _M_IX86 { 0x7FF0000000000001ull /* NAN(SNAN) */, 0x7FF0000000000001ull /* NAN(SNAN) */ }, { 0x7FF7FFFFFFFFFFFFull /* NAN(SNAN) */, 0x7FF7FFFFFFFFFFFFull /* NAN(SNAN) */ }, #else @@ -31,7 +31,7 @@ static TESTENTRY_DBL s_fabs_tests[] = { 0x7FF8000000000001ull /* NAN */, 0x7FF8000000000001ull /* NAN */ }, { 0x7FFFFFFFFFFFFFFFull /* NAN */, 0x7FFFFFFFFFFFFFFFull /* NAN */ }, { 0xFFF0000000000000ull /* -INF */, 0x7FF0000000000000ull /* INF */ }, -#ifdef _M_AMD64 +#ifndef _M_IX86 { 0xFFF0000000000001ull /* -NAN(SNAN) */, 0xFFF0000000000001ull /* NAN(SNAN) */ }, { 0xFFF7FFFFFFFFFFFFull /* -NAN(SNAN) */, 0xFFF7FFFFFFFFFFFFull /* NAN(SNAN) */ }, #else diff --git a/sdk/lib/crt/math/amd64/fabs.S b/sdk/lib/crt/math/amd64/fabs.S index fb6db3b32e3..a35222ab93e 100644 --- a/sdk/lib/crt/math/amd64/fabs.S +++ b/sdk/lib/crt/math/amd64/fabs.S @@ -1,9 +1,8 @@ /* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * PURPOSE: Implementation of fabs - * FILE: lib/sdk/crt/math/amd64/fabs.S - * PROGRAMMER: Timo Kreuzer (timo.kreuzer@reactos.org) + * PROJECT: ReactOS CRT library + * LICENSE: MIT (https://spdx.org/licenses/MIT) + * PURPOSE: x64 asm implementation of fabs + * COPYRIGHT: Copyright 2021 Timo Kreuzer */ /* INCLUDES ******************************************************************/ @@ -14,18 +13,42 @@ .code64 #ifdef _USE_ML -/* fabs is now allowed as label name, so create _fabs instead and alias fabs to it */ +/* fabs is not allowed as label name, so create _fabs instead and alias fabs to it */ +ALIAS = <_fabs> PUBLIC _fabs _fabs: #else PUBLIC fabs fabs: #endif - UNIMPLEMENTED fabs - ret - -#ifdef _USE_ML -ALIAS = <_fabs> + /* Copy parameter into rcx */ +#if !defined(_MSC_VER) || (_MSC_VER >= 1916) + movq rcx, xmm0 +#else + /* Old ML64 version does not understand this form of movq and uses movd instead */ + movd rcx, xmm0 #endif + /* Copy into rax */ + mov rax, rcx + + /* Clear sign bit in rax */ + btr rax, 63 + + /* Check for NAN */ + mov r8, HEX(7FF0000000000000) + cmp rax, r8 + + /* If it is NAN, copy original value back to rax */ + cmova rax, rcx + +#if !defined(_MSC_VER) || (_MSC_VER >= 1916) + movq xmm0, rax +#else + /* Old ML64 version does not understand this form of movq and uses movd instead */ + movd xmm0, rax +#endif + + ret + END diff --git a/sdk/lib/crt/math/amd64/fabsf.S b/sdk/lib/crt/math/amd64/fabsf.S new file mode 100644 index 00000000000..9d4a9af40a0 --- /dev/null +++ b/sdk/lib/crt/math/amd64/fabsf.S @@ -0,0 +1,49 @@ +/* + * PROJECT: ReactOS CRT library + * LICENSE: MIT (https://spdx.org/licenses/MIT) + * PURPOSE: x64 asm implementation of fabsf + * COPYRIGHT: Copyright 2021 Timo Kreuzer + */ + +/* INCLUDES ******************************************************************/ + +#include + +/* CODE **********************************************************************/ +.code64 + +PUBLIC fabsf +fabsf: + /* Copy parameter into rcx */ +#if !defined(_MSC_VER) || (_MSC_VER >= 1916) + movq rcx, xmm0 +#else + /* Old ML64 version does not understand this form of movq and uses movd instead */ + movd rcx, xmm0 +#endif + + /* Copy into eax */ + mov eax, ecx + + /* Clear sign bit in eax */ + btr eax, 31 + + /* Set error bit in rcx */ + bts ecx, 22 + + /* Check for NAN */ + cmp eax, HEX(7F800000) + + /* If eax is NAN, copy error result to rax */ + cmova eax, ecx + +#if !defined(_MSC_VER) || (_MSC_VER >= 1916) + movq xmm0, rax +#else + /* Old ML64 version does not understand this form of movq and uses movd instead */ + movd xmm0, rax +#endif + + ret + +END diff --git a/sdk/lib/crt/math/arm/fabs.s b/sdk/lib/crt/math/arm/fabs.s deleted file mode 100644 index 331c6ec64c0..00000000000 --- a/sdk/lib/crt/math/arm/fabs.s +++ /dev/null @@ -1,24 +0,0 @@ -/* - * COPYRIGHT: BSD - See COPYING.ARM in the top level directory - * PROJECT: ReactOS CRT library - * PURPOSE: Implementation of fabs - * PROGRAMMER: Timo Kreuzer (timo.kreuzer@reactos.org) - */ - -/* INCLUDES ******************************************************************/ - -#include - -/* CODE **********************************************************************/ - - TEXTAREA - - LEAF_ENTRY fabs - - __assertfail - bx lr - - LEAF_END fabs - - END -/* EOF */ diff --git a/sdk/lib/crt/math/fabs.c b/sdk/lib/crt/math/fabs.c new file mode 100644 index 00000000000..771542881c7 --- /dev/null +++ b/sdk/lib/crt/math/fabs.c @@ -0,0 +1,38 @@ +/* + * PROJECT: ReactOS CRT library + * LICENSE: MIT (https://spdx.org/licenses/MIT) + * PURPOSE: Portable implementation of fabs + * COPYRIGHT: Copyright 2021 Timo Kreuzer + */ + +#include + +#ifdef _MSC_VER +#pragma function(fabs) +#endif + +_Check_return_ +double +__cdecl +fabs( + _In_ double x) +{ + /* Load the value as uint64 */ + unsigned long long u64 = *(unsigned long long*)&x; + + /* Clear the sign bit */ + u64 &= ~(1ULL << 63); + + /* Check for NAN */ + if (u64 > 0x7FF0000000000000ull) + { +#ifdef _M_IX86 + /* Set error bit */ + *(unsigned long long*)&x |= 0x0008000000000000ull; +#endif + return x; + } + + /* Convert back to double */ + return *(double*)&u64; +} diff --git a/sdk/lib/crt/math/fabsf.c b/sdk/lib/crt/math/fabsf.c index 611d94e8a20..155c8559708 100644 --- a/sdk/lib/crt/math/fabsf.c +++ b/sdk/lib/crt/math/fabsf.c @@ -1,8 +1,8 @@ /* - * COPYRIGHT: BSD - See COPYING.ARM in the top level directory - * PROJECT: ReactOS CRT library - * PURPOSE: Implementation of fabsf - * PROGRAMMER: Timo Kreuzer + * PROJECT: ReactOS CRT library + * LICENSE: MIT (https://spdx.org/licenses/MIT) + * PURPOSE: Portable implementation of fabsf + * COPYRIGHT: Copyright 2021 Timo Kreuzer */ #include @@ -13,6 +13,20 @@ __cdecl fabsf( _In_ float x) { - return (float)fabs((double)x); -} + /* Load the value as uint */ + unsigned int u32 = *(unsigned int*)&x; + /* Clear the sign bit */ + u32 &= ~(1 << 31); + + /* Check for NAN */ + if (u32 > 0x7F800000) + { + /* Set error bit */ + *(unsigned int*)&x |= 0x00400000; + return x; + } + + /* Convert back to float */ + return *(float*)&u32; +} diff --git a/sdk/lib/crt/math/math.cmake b/sdk/lib/crt/math/math.cmake index fcf9e5eecdf..1f4a4d5da2a 100644 --- a/sdk/lib/crt/math/math.cmake +++ b/sdk/lib/crt/math/math.cmake @@ -8,6 +8,8 @@ list(APPEND LIBCNTPR_MATH_SOURCE if(ARCH STREQUAL "i386") list(APPEND LIBCNTPR_MATH_SOURCE + math/fabs.c + math/fabsf.c math/i386/ci.c math/i386/cicos.c math/i386/cilog.c @@ -31,7 +33,7 @@ if(ARCH STREQUAL "i386") math/i386/aullshr_asm.s math/i386/ceil_asm.s math/i386/cos_asm.s - math/i386/fabs_asm.s + # math/i386/fabs_asm.s # FIXME math/i386/floor_asm.s math/i386/ftol_asm.s math/i386/ftol2_asm.s @@ -60,6 +62,7 @@ elseif(ARCH STREQUAL "amd64") math/amd64/ceil.S math/amd64/exp.S math/amd64/fabs.S + math/amd64/fabsf.S math/amd64/floor.S math/amd64/floorf.S math/amd64/fmod.S @@ -73,6 +76,8 @@ elseif(ARCH STREQUAL "amd64") elseif(ARCH STREQUAL "arm") list(APPEND LIBCNTPR_MATH_SOURCE math/cos.c + math/fabs.c + math/fabsf.c math/floorf.c math/sin.c math/sqrt.c @@ -92,15 +97,11 @@ elseif(ARCH STREQUAL "arm") math/arm/__u64tos.c math/arm/__64tof.h ) - list(APPEND CRT_MATH_SOURCE - math/fabsf.c - ) list(APPEND LIBCNTPR_MATH_ASM_SOURCE math/arm/atan.s math/arm/atan2.s math/arm/ceil.s math/arm/exp.s - math/arm/fabs.s math/arm/fmod.s math/arm/floor.s math/arm/ldexp.s