Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

163 lines
5.5 KiB

; file: modf_wmt.asm
; Copyright (C) 1985-2000 Intel Corporation.
;
; The information and source code contained herein is the exclusive property
; of Intel Corporation and may not be disclosed, examined, or reproduced in
; whole or in part without explicit written authorization from the Company.
;
; Implemented in VNIIEF-STL, july 2000
; double modf (double x, double *iptr)
; Returns the value of the signed fractional part of argument
;
; Willamette specific version (MASM 6.15 required)
;
; Description:
; The modf functions break the argument value into integral and fractional parts,
; each of which has the same type and sign as the argument. They store the integral
; part (in floating-point format) in the object pointed to by iptr.
;
; Special cases:
; modf(NaN,iptr) = that NaN and stores that NaN in the *iptr object
; modf(INF,iptr) = 0 at the sign of x and stores that INF in the *iptr object
;
; Accuracy:
; The result is always exact.
.xlist
include cruntime.inc
.list
_FUNC_ equ <modf>
_FUNC_DEF_ equ <_modf_default>
_FUNC_P4_ equ <_modf_pentium4>
_FUNC_DEF_EXTERN_ equ 1
include disp_pentium4.inc
EXTRN C __libm_error_support : NEAR
.const
ALIGN 16
;-- 16x-aligned data --------------------------------------------------------
_Mantissa DQ 0000fffffffffffffH,0000fffffffffffffH
_Bns DQ 00000000000000433H,00000000000000433H
_Sign DQ 08000000000000000H,08000000000000000H
_Zero DQ 00000000000000000H,00000000000000000H
codeseg
ALIGN 16
; double modf (double x, double *iptr);
; Stack frame locations
modf_x TEXTEQU <esp+4>
modf_iptr TEXTEQU <esp+12>
modf_result TEXTEQU <modf_x>
XMMWORD TEXTEQU <OWORD>
PUBLIC _modf_pentium4
_modf_pentium4 PROC NEAR
movq xmm0, QWORD PTR [modf_x] ; x
movapd xmm2, XMMWORD PTR _Bns ;
movapd xmm3, xmm0 ; x
movapd xmm1, xmm0 ; x
movapd xmm4, xmm0 ; x
movapd xmm6, xmm0
psllq xmm0, 1 ; exp(x) ; remove sign
psrlq xmm0, 53 ; exp(x) ; exp(x)
psrlq xmm3, 52 ; exp(x) ; sign(x) | exp(x)
andpd xmm4, XMMWORD PTR _Sign ; sign(x)
movd eax, xmm0 ; exp(x)
psubd xmm2, xmm0 ;
mov ecx, DWORD PTR [modf_iptr] ; iptr
psrlq xmm1, xmm2 ; truncate
psllq xmm1, xmm2 ; t = trunc(x)
movd edx, xmm3 ; sign(x) | exp(x)
cmp eax, 03ffH ; if abs(x) < 1.0
jl SHORT ret_z ; case A
cmp eax, 0432H ; if abs(x) >=2**53
jg SHORT ret_xm ; case B
movq QWORD PTR [ecx], xmm1 ; *iptr = t
subsd xmm6, xmm1
orpd xmm6, xmm4 ; set sign if frac = 0.0
movq QWORD PTR [modf_result], xmm6
fld QWORD PTR [modf_result] ; return signed result
ret ;
ret_z: ; case A: |x|<1.0
movq QWORD PTR [ecx], xmm4 ; *iptr = properly-signed 0.0
fld QWORD PTR [modf_x] ; return (X)
ret ;
ret_xm: ; case B: exp(x) >= 53
cmp eax, 07ffH ; check Inf (NaN)
movq xmm0, QWORD PTR [modf_x] ; x
je SHORT ret_inf_nan ;
movq QWORD PTR [ecx], xmm0 ;
cmp edx, 800H ;
fldz ; if x is positive, return 0.0
jl SHORT return ;
fchs ; if x is negative, return -0.0
return:
ret ;
ret_inf_nan:
movapd xmm1, xmm0
addsd xmm0, xmm0
movq QWORD PTR [ecx], xmm0 ;
andpd xmm0, XMMWORD PTR _Mantissa ;
cmppd xmm0, XMMWORD PTR _Zero, 4 ; Mask = (x == Inf) ? 0 : 1
pextrw eax, xmm0, 0 ; eax=(x==INF)? 0:1
andpd xmm0, xmm1 ; t = Mask & x
orpd xmm0, xmm4 ; t |= Sign(x)
mov edx, 1007
cmp eax, 0
; if NaN, call libm_error_support
jnz CALL_LIBM_ERROR
movq QWORD PTR [modf_result], xmm0 ;
fld QWORD PTR [modf_result] ; return (t)
ret ;
CALL_LIBM_ERROR:
;call libm_error_support(void *arg1,void *arg2,void *retval,error_types input_tag)
sub esp, 28
movlpd QWORD PTR [esp+16], xmm0
mov DWORD PTR [esp+12],edx
mov edx, esp
add edx,16
mov DWORD PTR [esp+8],edx
add edx,16+8
mov DWORD PTR [esp+4],edx
sub edx, 8
mov DWORD PTR [esp],edx
call NEAR PTR __libm_error_support
; movlpd xmm0, QWORD PTR [esp+16]
; movlpd QWORD PTR [esp+16], xmm0 ; return result
fld QWORD PTR [esp+16] ;
add esp,28
ret
_modf_pentium4 ENDP
END