https://git.reactos.org/?p=reactos.git;a=commitdiff;h=f637e6b809adb5e0ae420ef4f80c73b19172a2e7

commit f637e6b809adb5e0ae420ef4f80c73b19172a2e7
Author:     Timo Kreuzer <timo.kreu...@reactos.org>
AuthorDate: Thu Aug 22 17:00:29 2024 +0300
Commit:     Timo Kreuzer <timo.kreu...@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.kreu...@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

Reply via email to