https://git.reactos.org/?p=reactos.git;a=commitdiff;h=f637e6b809adb5e0ae420…
commit f637e6b809adb5e0ae420ef4f80c73b19172a2e7
Author: Timo Kreuzer <timo.kreuzer(a)reactos.org>
AuthorDate: Thu Aug 22 17:00:29 2024 +0300
Commit: Timo Kreuzer <timo.kreuzer(a)reactos.org>
CommitDate: Tue Aug 27 21:34:50 2024 +0300
[CRT] Implement __ftoul2_legacy
This is used by CL v19.41+. It replicates the behavior of the inline assembly code that previous CL versions generated. According to tests it works the same as with previous VS versions.
---
sdk/lib/crt/math/i386/ftol2_asm.s | 66 +++++++++++++++++++++++++++++++++++----
1 file changed, 60 insertions(+), 6 deletions(-)
diff --git a/sdk/lib/crt/math/i386/ftol2_asm.s b/sdk/lib/crt/math/i386/ftol2_asm.s
index 974d6f5a468..a15a7031abc 100644
--- a/sdk/lib/crt/math/i386/ftol2_asm.s
+++ b/sdk/lib/crt/math/i386/ftol2_asm.s
@@ -1,10 +1,8 @@
/*
- * COPYRIGHT: See COPYING in the top level directory
- * PROJECT: ReactOS kernel
- * PURPOSE: Run-Time Library
- * FILE: lib/sdk/crt/math/i386/ftol2_asm.s
- * PROGRAMER:
- *
+ * PROJECT: ReactOS CRT
+ * LICENSE: MIT (https://spdx.org/licenses/MIT)
+ * PURPOSE: Floating point conversion routines
+ * COPYRIGHT: Copyright 2024 Timo Kreuzer <timo.kreuzer(a)reactos.org>
*/
#include <asm.inc>
@@ -12,6 +10,7 @@
EXTERN __ftol:PROC
PUBLIC __ftol2
PUBLIC __ftol2_sse
+PUBLIC __ftoul2_legacy
/* FUNCTIONS ***************************************************************/
.code
@@ -25,4 +24,59 @@ __ftol2:
__ftol2_sse:
jmp __ftol
+__real@43e0000000000000:
+ .quad HEX(43e0000000000000)
+
+__ftoul2_legacy:
+
+ /* Compare the fp number, passed in st(0), against (LLONG_MAX + 1)
+ aka 9223372036854775808.0 (which is 0x43e0000000000000 in double format).
+ If it is smaller, it fits into an __int64, so we can pass it to _ftol2.
+ After this the original fp value has moved to st(1) */
+ fld qword ptr [__real@43e0000000000000]
+ fcom
+
+ /* Put the comparison result bits into ax */
+ fnstsw ax
+
+ /* Here we test the bits for c0 (0x01) and c3 (0x40).
+ We check the parity bit after the test. If it is set,
+ an even number of bits were set.
+ If both are 0, st(1) < st(0), i.e. our value is ok.
+ If both are 1, the value is NaN/Inf and we let _ftol2 handle it. */
+ test ah, HEX(41)
+ jnp __ftoul2_legacy2
+
+ /* Clean up the fp stack and forward to _ftol2 */
+ fstp st(0)
+ jmp __ftol2
+
+__ftoul2_legacy2:
+
+ /* Subtract (LLONG_MAX + 1) from the given fp value and put the result in st(1).
+ st(0) = 9223372036854775808.0
+ st(1) = original fp value - 9223372036854775808.0 */
+ fsub st(1), st(0)
+
+ /* Compare the result to (LLONG_MAX + 1) again and pop the fp stack.
+ Here we check, whether c0 and c3 are both 0, indicating that st(0) > st(1),
+ i.e. fp - (LLONG_MAX + 1) < (LLONG_MAX + 1) */
+ fcomp
+ fnstsw ax
+ test ah, HEX(41)
+ jnz __ftoul2_legacy3
+
+ /* We have established that fp - (LLONG_MAX + 1) fits into an __int64,
+ so pass that to _ftol2 and manually add the difference to the result */
+ call __ftol2
+ add edx, HEX(80000000)
+ ret
+
+__ftoul2_legacy3:
+
+ /* The value is too large, just return the error value */
+ xor eax, eax
+ mov edx, HEX(80000000)
+ ret
+
END