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

  1. ; file: modf_wmt.asm
  2. ; Copyright (C) 1985-2000 Intel Corporation.
  3. ;
  4. ; The information and source code contained herein is the exclusive property
  5. ; of Intel Corporation and may not be disclosed, examined, or reproduced in
  6. ; whole or in part without explicit written authorization from the Company.
  7. ;
  8. ; Implemented in VNIIEF-STL, july 2000
  9. ; double modf (double x, double *iptr)
  10. ; Returns the value of the signed fractional part of argument
  11. ;
  12. ; Willamette specific version (MASM 6.15 required)
  13. ;
  14. ; Description:
  15. ; The modf functions break the argument value into integral and fractional parts,
  16. ; each of which has the same type and sign as the argument. They store the integral
  17. ; part (in floating-point format) in the object pointed to by iptr.
  18. ;
  19. ; Special cases:
  20. ; modf(NaN,iptr) = that NaN and stores that NaN in the *iptr object
  21. ; modf(INF,iptr) = 0 at the sign of x and stores that INF in the *iptr object
  22. ;
  23. ; Accuracy:
  24. ; The result is always exact.
  25. .xlist
  26. include cruntime.inc
  27. .list
  28. _FUNC_ equ <modf>
  29. _FUNC_DEF_ equ <_modf_default>
  30. _FUNC_P4_ equ <_modf_pentium4>
  31. _FUNC_DEF_EXTERN_ equ 1
  32. include disp_pentium4.inc
  33. EXTRN C __libm_error_support : NEAR
  34. .const
  35. ALIGN 16
  36. ;-- 16x-aligned data --------------------------------------------------------
  37. _Mantissa DQ 0000fffffffffffffH,0000fffffffffffffH
  38. _Bns DQ 00000000000000433H,00000000000000433H
  39. _Sign DQ 08000000000000000H,08000000000000000H
  40. _Zero DQ 00000000000000000H,00000000000000000H
  41. codeseg
  42. ALIGN 16
  43. ; double modf (double x, double *iptr);
  44. ; Stack frame locations
  45. modf_x TEXTEQU <esp+4>
  46. modf_iptr TEXTEQU <esp+12>
  47. modf_result TEXTEQU <modf_x>
  48. XMMWORD TEXTEQU <OWORD>
  49. PUBLIC _modf_pentium4
  50. _modf_pentium4 PROC NEAR
  51. movq xmm0, QWORD PTR [modf_x] ; x
  52. movapd xmm2, XMMWORD PTR _Bns ;
  53. movapd xmm3, xmm0 ; x
  54. movapd xmm1, xmm0 ; x
  55. movapd xmm4, xmm0 ; x
  56. movapd xmm6, xmm0
  57. psllq xmm0, 1 ; exp(x) ; remove sign
  58. psrlq xmm0, 53 ; exp(x) ; exp(x)
  59. psrlq xmm3, 52 ; exp(x) ; sign(x) | exp(x)
  60. andpd xmm4, XMMWORD PTR _Sign ; sign(x)
  61. movd eax, xmm0 ; exp(x)
  62. psubd xmm2, xmm0 ;
  63. mov ecx, DWORD PTR [modf_iptr] ; iptr
  64. psrlq xmm1, xmm2 ; truncate
  65. psllq xmm1, xmm2 ; t = trunc(x)
  66. movd edx, xmm3 ; sign(x) | exp(x)
  67. cmp eax, 03ffH ; if abs(x) < 1.0
  68. jl SHORT ret_z ; case A
  69. cmp eax, 0432H ; if abs(x) >=2**53
  70. jg SHORT ret_xm ; case B
  71. movq QWORD PTR [ecx], xmm1 ; *iptr = t
  72. subsd xmm6, xmm1
  73. orpd xmm6, xmm4 ; set sign if frac = 0.0
  74. movq QWORD PTR [modf_result], xmm6
  75. fld QWORD PTR [modf_result] ; return signed result
  76. ret ;
  77. ret_z: ; case A: |x|<1.0
  78. movq QWORD PTR [ecx], xmm4 ; *iptr = properly-signed 0.0
  79. fld QWORD PTR [modf_x] ; return (X)
  80. ret ;
  81. ret_xm: ; case B: exp(x) >= 53
  82. cmp eax, 07ffH ; check Inf (NaN)
  83. movq xmm0, QWORD PTR [modf_x] ; x
  84. je SHORT ret_inf_nan ;
  85. movq QWORD PTR [ecx], xmm0 ;
  86. cmp edx, 800H ;
  87. fldz ; if x is positive, return 0.0
  88. jl SHORT return ;
  89. fchs ; if x is negative, return -0.0
  90. return:
  91. ret ;
  92. ret_inf_nan:
  93. movapd xmm1, xmm0
  94. addsd xmm0, xmm0
  95. movq QWORD PTR [ecx], xmm0 ;
  96. andpd xmm0, XMMWORD PTR _Mantissa ;
  97. cmppd xmm0, XMMWORD PTR _Zero, 4 ; Mask = (x == Inf) ? 0 : 1
  98. pextrw eax, xmm0, 0 ; eax=(x==INF)? 0:1
  99. andpd xmm0, xmm1 ; t = Mask & x
  100. orpd xmm0, xmm4 ; t |= Sign(x)
  101. mov edx, 1007
  102. cmp eax, 0
  103. ; if NaN, call libm_error_support
  104. jnz CALL_LIBM_ERROR
  105. movq QWORD PTR [modf_result], xmm0 ;
  106. fld QWORD PTR [modf_result] ; return (t)
  107. ret ;
  108. CALL_LIBM_ERROR:
  109. ;call libm_error_support(void *arg1,void *arg2,void *retval,error_types input_tag)
  110. sub esp, 28
  111. movlpd QWORD PTR [esp+16], xmm0
  112. mov DWORD PTR [esp+12],edx
  113. mov edx, esp
  114. add edx,16
  115. mov DWORD PTR [esp+8],edx
  116. add edx,16+8
  117. mov DWORD PTR [esp+4],edx
  118. sub edx, 8
  119. mov DWORD PTR [esp],edx
  120. call NEAR PTR __libm_error_support
  121. ; movlpd xmm0, QWORD PTR [esp+16]
  122. ; movlpd QWORD PTR [esp+16], xmm0 ; return result
  123. fld QWORD PTR [esp+16] ;
  124. add esp,28
  125. ret
  126. _modf_pentium4 ENDP
  127. END