Source code of Windows XP (NT5)
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.

178 lines
5.0 KiB

  1. page ,132
  2. subttl emfsqrt.asm - Square root
  3. ;***
  4. ;emfsqrt.asm - Square root
  5. ;
  6. ; Copyright (c) 1986-89, Microsoft Corporation
  7. ;
  8. ;Purpose:
  9. ; Square root
  10. ;
  11. ; This Module contains Proprietary Information of Microsoft
  12. ; Corporation and should be treated as Confidential.
  13. ;
  14. ;Revision History:
  15. ; See emulator.hst
  16. ;
  17. ;*******************************************************************************
  18. ;-----------------------------------------;
  19. ; ;
  20. ; Square root ;
  21. ; ;
  22. ;-----------------------------------------;
  23. ProfBegin FSQRT
  24. pub eFSQRT
  25. MOV esi,[CURstk]
  26. CALL $FSQRT
  27. RET
  28. ;---------------------------------------------------
  29. ; !
  30. ; 8087 emulator square root !
  31. ; !
  32. ;---------------------------------------------------
  33. ; With 0<=x={TOS=[SI]}<infinity, $FSQRT performs {TOS=[SI]} <--
  34. ; {TOS=[SI]}^.5. All registers except SI are destroyed. Roots
  35. ; of negative numbers, infinities, and NAN's result in errors. The
  36. ; square root of -0 is -0. Algorithm: x is initially adjusted
  37. ; so that the exponent is even (when the exponent is odd the exponent
  38. ; is incremented and the mantissa is shifted right one bit). The
  39. ; exponent is then divided by two and resaved. A single word
  40. ; estimate of y (the root of x) accurate to 5 bits is produced using
  41. ; a wordlength implementation of a linear polynomial approximation
  42. ; of sqrt x. Four Newton-Raphson iterations are then computed as
  43. ; follows:
  44. ;
  45. ; 1) qa*ya+r1a=xa:0h,ya=(ya+qa)/2
  46. ; 2) qa*ya+r1a=xa:xb,ya=(ya+qa)/2
  47. ; 3) qa*ya+r1a=xa:xb,qb*ya+r2a=r1a:xc,ya:yb=(ya:yb+qa:qb)/2
  48. ; *** iteration 4 implemented with standard divide ***
  49. ; 4) qa*ya+r1a=xa:xb,p1a:p1b=qa*yb,
  50. ; if p1a<r1a continue
  51. ; if p1a=r1a
  52. ; if p1b=xc continue else r1a=r1a+ya,qa=qa-1 endif,
  53. ; else r1a=r1a+ya,qa=qa-1,p1a:p1b=p1a:p1b-yb endif,
  54. ; r1a:r1b=r1a:xc-p1a:p1b,
  55. ; qb:ya+r2a=r1a:r1b,p2a:p2b=qb*yb,
  56. ; if p2a<r2a continue
  57. ; if p2a=r2a
  58. ; if p2b=xd continue else r2a=r2a+ya,qb=qb-1 endif,
  59. ; else r2a=r2a+ya,qb=qb-1,p2a:p2b=p2a:p2b-yb endif,
  60. ; r2a:r2b=r2a:xd-p2a:p2b,
  61. ; qc*ya+r3a=r2a:r2b,p3a:p3b=qc*yb,
  62. ; if p3a>=r3a then r3a=r3a+ya,qc=qc-1 endif,
  63. ; r3a=r3a-p3a,qd*ya+r4a=r3a:0h,
  64. ; ya:yb:yc:yd=(ya:yb:0h:0h+qa:qb:qc:qd)/2
  65. pub SQRTSPECIAL
  66. RCR AH,1 ;if NAN
  67. JNC short SETFLAG ; set invalid flag and return
  68. RCL AL,1 ;if -infinity
  69. JC short SQRTERROR ; return real indefinite
  70. MOV AL,[CWcntl] ;get Infinity control
  71. TEST AL,ICaffine ;if affine closure
  72. JNZ short SQRTDONE ; return +infinity
  73. JMP SHORT SQRTERROR ;else return real indefinite
  74. pub NOTPOSVALID
  75. TEST AH,2 ;if special
  76. JNZ SQRTSPECIAL ; process special
  77. RCR AH,1 ;if zero
  78. JC SHORT SQRTDONE ; return argument
  79. ;otherwise -ve, return NAN
  80. pub SQRTERROR
  81. MOV edi,esi
  82. MOV esi,offset IEEEindefinite
  83. CALL csMOVRQQ
  84. MOV esi,edi ;return indefinite
  85. pub SETFLAG
  86. OR [CURerr],Invalid+SquareRootNeg ;Set flag indicating invalid
  87. pub SQRTDONE
  88. RET
  89. pub $FSQRT
  90. MOV AX,[esi+Flag] ;get flags
  91. TEST AX,00380H ;if Sign, Invalid or Zero
  92. JNZ NOTPOSVALID ; perform special processing
  93. PUSH esi ;save ptr to x
  94. MOV edi,offset TEMP1 ;[DI]=y=temp
  95. MOV word ptr [edi+Flag],0 ;clear flags in y
  96. MOV AX,[esi+Expon] ;get exponent of x
  97. DEC AX ;adjust for shift divide by 2
  98. MOV BX,[esi+6]
  99. MOV CX,[esi+4]
  100. MOV DX,[esi+2] ;get first three mantissa words of x
  101. TEST AL,1 ;if exponent is even
  102. JZ short EXPEVEN ; bypass adjust
  103. INC AX ;increment exponent
  104. SHR BX,1
  105. RCR CX,1
  106. RCR DX,1 ;divide mantissa by 2
  107. pub EXPEVEN
  108. SAR AX,1 ;divide exponent by 2
  109. MOV [edi+Expon],AX ;store exponent of y
  110. CMP BX,0FFFEH ;if mantissa < 0.FFFEh
  111. JB short NOTNEARONE1 ; perform main root routine
  112. STC ;otherwise x to become (1+x)/2
  113. JMP SHORT SINGLEDONE ;single precision complete
  114. pub NOTNEARONE1
  115. PUSH edx ;save third mantissa word
  116. MOV AX,0B075H ;AX=.B075h
  117. MUL BX ;DX=.B075h*x
  118. MOV BP,057D8H ;BP=.57D8h
  119. ADD BP,DX ;BP=.B075h*x+.57D8h
  120. JNC short NORMEST ;if y is more than one
  121. MOV BP,0FFFFH ; replace y with .FFFFh
  122. pub NORMEST
  123. MOV DX,BX
  124. XOR AX,AX ;load divide regs with xa:0h
  125. DIV BP ;qa*ya+r1a=xa:0h
  126. ADD BP,AX ;ya=ya+qa
  127. RCR BP,1 ;ya=ya/2
  128. MOV DX,BX
  129. MOV AX,CX ;load divide regs with xa:xb
  130. DIV BP ;qa*ya+r1a=xa:xb
  131. STC ;add one to qa for better rounding
  132. ADC BP,AX ;ya=ya+qa
  133. RCR BP,1 ;ya=ya/2
  134. MOV DX,BX
  135. MOV AX,CX ;load divide regs with xa:xb
  136. DIV BP ;qa*ya+r1a=xa:xb
  137. MOV SI,AX ;save qa
  138. POP eax ;load divide regs with r1a:xc
  139. DIV BP ;qb*ya+r2a=r1a:xc
  140. MOV BX,BP
  141. MOV CX,AX ;move qa:qb
  142. ADD CX,1 ;add one to qa:qb for better rounding
  143. ADC BX,SI ;ya:yb=ya:0h+qa:qb
  144. pub SINGLEDONE
  145. RCR BX,1
  146. RCR CX,1 ;ya:yb=(ya:0h+qa:qb)/2
  147. MOV word ptr [edi+6],BX
  148. MOV word ptr [edi+4],CX
  149. MOV word ptr [edi+2],0
  150. MOV word ptr [edi],0 ;save ya:yb:0h:0h
  151. MOV esi,edi ;[SI]=y
  152. POP edi ;[DI]=x
  153. MOV [RESULT],edi ;result=[DI]
  154. CALL DIDRQQ ;[DI]=x/y
  155. MOV esi,offset TEMP1 ;[SI]=y
  156. CALL ADDRQQ ;[DI]=y+x/y
  157. DEC word ptr [edi+Expon] ;[DI]=(y+x/y)/2=TOS
  158. MOV esi,edi ;[SI]=sqrt(x)
  159. RET
  160. ProfEnd FSQRT