Reactos

[CRT] Fix link issues with __ftol2 when compiling for NT6

__ftol2 is exported from msvcrt on NT6+, not from ntdll for some reason. So native apps still need to statically link _ftol2 and _ftoul2_legacy, but apps linking to msvcrt only need to statically link _ftoul2_legacy (via msvcrtex), when on NT6+.

+81 -61
+1
sdk/lib/crt/CMakeLists.txt
··· 49 49 if(MSVC AND ARCH STREQUAL "i386") 50 50 add_asm_files(ftol2_asm 51 51 math/i386/ftol2_asm.s 52 + math/i386/ftoul2_legacy_asm.s 52 53 ) 53 54 add_library(ftol2 ${ftol2_asm}) 54 55 set_target_properties(ftol2 PROPERTIES LINKER_LANGUAGE "C")
+6 -60
sdk/lib/crt/math/i386/ftol2_asm.s
··· 1 1 /* 2 - * PROJECT: ReactOS CRT 3 - * LICENSE: MIT (https://spdx.org/licenses/MIT) 4 - * PURPOSE: Floating point conversion routines 5 - * COPYRIGHT: Copyright 2024 Timo Kreuzer <timo.kreuzer@reactos.org> 2 + * COPYRIGHT: See COPYING in the top level directory 3 + * PROJECT: ReactOS kernel 4 + * PURPOSE: Run-Time Library 5 + * FILE: lib/sdk/crt/math/i386/ftol2_asm.s 6 + * PROGRAMER: 7 + * 6 8 */ 7 9 8 10 #include <asm.inc> ··· 10 12 EXTERN __ftol:PROC 11 13 PUBLIC __ftol2 12 14 PUBLIC __ftol2_sse 13 - PUBLIC __ftoul2_legacy 14 15 15 16 /* FUNCTIONS ***************************************************************/ 16 17 .code ··· 23 24 __ftol2: 24 25 __ftol2_sse: 25 26 jmp __ftol 26 - 27 - __real@43e0000000000000: 28 - .quad HEX(43e0000000000000) 29 - 30 - __ftoul2_legacy: 31 - 32 - /* Compare the fp number, passed in st(0), against (LLONG_MAX + 1) 33 - aka 9223372036854775808.0 (which is 0x43e0000000000000 in double format). 34 - If it is smaller, it fits into an __int64, so we can pass it to _ftol2. 35 - After this the original fp value has moved to st(1) */ 36 - fld qword ptr [__real@43e0000000000000] 37 - fcom 38 - 39 - /* Put the comparison result bits into ax */ 40 - fnstsw ax 41 - 42 - /* Here we test the bits for c0 (0x01) and c3 (0x40). 43 - We check the parity bit after the test. If it is set, 44 - an even number of bits were set. 45 - If both are 0, st(1) < st(0), i.e. our value is ok. 46 - If both are 1, the value is NaN/Inf and we let _ftol2 handle it. */ 47 - test ah, HEX(41) 48 - jnp __ftoul2_legacy2 49 - 50 - /* Clean up the fp stack and forward to _ftol2 */ 51 - fstp st(0) 52 - jmp __ftol2 53 - 54 - __ftoul2_legacy2: 55 - 56 - /* Subtract (LLONG_MAX + 1) from the given fp value and put the result in st(1). 57 - st(0) = 9223372036854775808.0 58 - st(1) = original fp value - 9223372036854775808.0 */ 59 - fsub st(1), st(0) 60 - 61 - /* Compare the result to (LLONG_MAX + 1) again and pop the fp stack. 62 - Here we check, whether c0 and c3 are both 0, indicating that st(0) > st(1), 63 - i.e. fp - (LLONG_MAX + 1) < (LLONG_MAX + 1) */ 64 - fcomp 65 - fnstsw ax 66 - test ah, HEX(41) 67 - jnz __ftoul2_legacy3 68 - 69 - /* We have established that fp - (LLONG_MAX + 1) fits into an __int64, 70 - so pass that to _ftol2 and manually add the difference to the result */ 71 - call __ftol2 72 - add edx, HEX(80000000) 73 - ret 74 - 75 - __ftoul2_legacy3: 76 - 77 - /* The value is too large, just return the error value */ 78 - xor eax, eax 79 - mov edx, HEX(80000000) 80 - ret 81 27 82 28 END
+71
sdk/lib/crt/math/i386/ftoul2_legacy_asm.s
··· 1 + /* 2 + * PROJECT: ReactOS CRT 3 + * LICENSE: MIT (https://spdx.org/licenses/MIT) 4 + * PURPOSE: Floating point conversion routines 5 + * COPYRIGHT: Copyright 2024 Timo Kreuzer <timo.kreuzer@reactos.org> 6 + */ 7 + 8 + #include <asm.inc> 9 + 10 + EXTERN __ftol2:PROC 11 + 12 + /* FUNCTIONS ***************************************************************/ 13 + .code 14 + 15 + __real@43e0000000000000: 16 + .quad HEX(43e0000000000000) 17 + 18 + PUBLIC __ftoul2_legacy 19 + __ftoul2_legacy: 20 + 21 + /* Compare the fp number, passed in st(0), against (LLONG_MAX + 1) 22 + aka 9223372036854775808.0 (which is 0x43e0000000000000 in double format). 23 + If it is smaller, it fits into an __int64, so we can pass it to _ftol2. 24 + After this the original fp value has moved to st(1) */ 25 + fld qword ptr [__real@43e0000000000000] 26 + fcom 27 + 28 + /* Put the comparison result bits into ax */ 29 + fnstsw ax 30 + 31 + /* Here we test the bits for c0 (0x01) and c3 (0x40). 32 + We check the parity bit after the test. If it is set, 33 + an even number of bits were set. 34 + If both are 0, st(1) < st(0), i.e. our value is ok. 35 + If both are 1, the value is NaN/Inf and we let _ftol2 handle it. */ 36 + test ah, HEX(41) 37 + jnp __ftoul2_legacy2 38 + 39 + /* Clean up the fp stack and forward to _ftol2 */ 40 + fstp st(0) 41 + jmp __ftol2 42 + 43 + __ftoul2_legacy2: 44 + 45 + /* Subtract (LLONG_MAX + 1) from the given fp value and put the result in st(1). 46 + st(0) = 9223372036854775808.0 47 + st(1) = original fp value - 9223372036854775808.0 */ 48 + fsub st(1), st(0) 49 + 50 + /* Compare the result to (LLONG_MAX + 1) again and pop the fp stack. 51 + Here we check, whether c0 and c3 are both 0, indicating that st(0) > st(1), 52 + i.e. fp - (LLONG_MAX + 1) < (LLONG_MAX + 1) */ 53 + fcomp 54 + fnstsw ax 55 + test ah, HEX(41) 56 + jnz __ftoul2_legacy3 57 + 58 + /* We have established that fp - (LLONG_MAX + 1) fits into an __int64, 59 + so pass that to _ftol2 and manually add the difference to the result */ 60 + call __ftol2 61 + add edx, HEX(80000000) 62 + ret 63 + 64 + __ftoul2_legacy3: 65 + 66 + /* The value is too large, just return the error value */ 67 + xor eax, eax 68 + mov edx, HEX(80000000) 69 + ret 70 + 71 + END
+1
sdk/lib/crt/math/math.cmake
··· 40 40 math/i386/floor_asm.s 41 41 math/i386/ftol_asm.s 42 42 math/i386/ftol2_asm.s 43 + math/i386/ftoul2_legacy_asm.s 43 44 math/i386/log_asm.s 44 45 math/i386/log10_asm.s 45 46 math/i386/pow_asm.s
+2 -1
sdk/lib/crt/msvcrtex.cmake
··· 47 47 endif() 48 48 if(MSVC AND DLL_EXPORT_VERSION LESS 0x600) 49 49 list(APPEND MSVCRTEX_ASM_SOURCE 50 - except/i386/__CxxFrameHandler3.s) 50 + except/i386/__CxxFrameHandler3.s 51 + math/i386/ftoul2_legacy_asm.s) 51 52 list(APPEND MSVCRTEX_SOURCE 52 53 except/i386/CxxHandleV8Frame.c) 53 54 endif()