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.

224 lines
4.7 KiB

  1. page ,132
  2. subttl emfrndi.asm - Round to INT
  3. ;***
  4. ;emfrndi.asm - Round to INT
  5. ;
  6. ; Copyright (c) 1986-89, Microsoft Corporation
  7. ;
  8. ;Purpose:
  9. ; Round to INT
  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. ; Round TOS to Integer ;
  21. ; ;
  22. ;*********************************************************************;
  23. ProfBegin FRNDI
  24. pub eFRNDINT
  25. MOV esi,[CURstk] ; Point to TOS
  26. MOV CX,Expon[esi] ; Get exponent
  27. CMP CX,63 ; See if we have very large integer
  28. JGE short DONERNDINT
  29. if fastSP
  30. MOV BX,MB4[esi] ; Fetch mantissa to DI:BP:BX:DX
  31. MOV DI,MB6[esi]
  32. TEST byte ptr Flag[esi],Single
  33. JZ RNDD
  34. XOR BL,BL
  35. MOV BP,BX
  36. XOR BX,BX
  37. MOV DX,BX
  38. RND:
  39. else
  40. MOV BP,MB4[esi] ; Fetch mantissa to DI:BP:BX:DX
  41. MOV DI,MB6[esi]
  42. MOV DX,MB0[esi]
  43. MOV BX,MB2[esi]
  44. endif
  45. CALL InternalToInteger
  46. XOR AX,AX ; Test for zero
  47. OR AX,DI
  48. OR AX,BP
  49. OR AX,BX
  50. OR AX,DX
  51. JZ short RoundIntToZero
  52. MOV AX,63 ; What expon should be if no shifting
  53. CALL IntegerToInternal
  54. pub DONERNDINT
  55. RET
  56. if fastSP
  57. RNDD:
  58. MOV BP,BX
  59. MOV DX,MB0[esi]
  60. MOV BX,MB2[esi]
  61. JMP RND
  62. endif
  63. pub RoundIntToZero
  64. MOV Expon[esi],IexpMin - IexpBias
  65. MOV MB0[esi],AX
  66. MOV MB2[esi],AX
  67. MOV MB4[esi],AX
  68. MOV MB6[esi],AX
  69. MOV byte ptr Tag[esi],ZROorINF
  70. JMP DONERNDINT
  71. PAGE
  72. pub IntegerToInternal
  73. ; On entry DI:BP:BX:DX is the integer (unsigned i.e. no longer in 2's
  74. ; compliment) DS:SI points to TOS (the ultimate destination).
  75. ; AX contains the Exponent (assuming that the number will require
  76. ; no shifting. the routine will adjust it as it goes along)
  77. ; On exit the mantissa and exponent will be put in TOS.
  78. ; This routine is used to Load int16 and int32 also to round-to-int
  79. XOR ecx,ecx
  80. pub SHIFTLEFT
  81. SHL DX,1 ; Left justify number
  82. RCL BX,1
  83. RCL BP,1
  84. RCL DI,1
  85. JC short DONESHIFT
  86. LOOP SHIFTLEFT ; CX will count number of shifts done
  87. pub DONESHIFT
  88. RCR DI,1 ; We went one too far so reset
  89. RCR BP,1
  90. RCR BX,1
  91. RCR DX,1
  92. ADD AX,CX ; Adjust exponent
  93. MOV Expon[esi],AX ; Store exponent
  94. MOV MB0[esi],DX ; Store mantissa
  95. MOV MB2[esi],BX
  96. MOV MB4[esi],BP
  97. MOV MB6[esi],DI
  98. RET
  99. PAGE
  100. pub InternalToInteger
  101. ; On entry DI:BP:BX:DX is the mantissa, CX is the Exponent, and
  102. ; DS:SI points to TOS where the number came from. On exit
  103. ; DI:BP:BX:DX is an integer (unsigned i.e. needs to be jiggled to
  104. ; 2's compliment based upon the sign in TOS) rounded according to
  105. ; Round control. This routine used to Store int16 and int32 also
  106. ; by round-to-integer
  107. ifdef i386
  108. movsx ecx,cx ; (ecx) = sign-extended cx
  109. endif
  110. XOR AX,AX ; Clear Stickybit (AL) and roundbit (AH)
  111. SUB ecx,63 ; Convert exponent to shift count
  112. NEG ecx ; Shift will be done in 2 parts, 1st to get
  113. DEC ecx ; sticky then 1 more to get round
  114. ifdef i386
  115. JGE short NOTRUNCATE; Shift count Neg means num was large int.
  116. JMP TRUNCATE
  117. NOTRUNCATE:
  118. JE short GETROUND ; Zero shift means no sticky bit, only round
  119. else
  120. JL short TRUNCATE ; Shift count Neg means num was large int.
  121. JE short GETROUND ; Zero shift means no sticky bit, only round
  122. endif
  123. CMP ecx,64 ; If big shift count then number is all sticky
  124. JGE short STICKYNOROUND
  125. cmp ecx,48 ; fast out for 16-bit ints
  126. jle SHIFTRIGHT ; no
  127. or dx,bx
  128. or dx,bp ; dx = low 48 bits
  129. jz nostick48 ; if 0 then no sticky bits
  130. or al,1 ; set sticky bit
  131. nostick48:
  132. mov dx,di ; move upper 16 to lower 16
  133. xor di,di ; zero upper 48 bits
  134. mov bp,di
  135. mov bx,di
  136. sub ecx,48 ; just like looping 48 times
  137. pub SHIFTRIGHT
  138. SHR DI,1 ; Shift into sticky bit (lsb of AL)
  139. RCR BP,1
  140. RCR BX,1
  141. RCR DX,1
  142. JNC short LOOPEND
  143. RCL AL,1
  144. pub LOOPEND
  145. LOOP SHIFTRIGHT
  146. pub GETROUND
  147. SHR DI,1 ; Shift into round
  148. RCR BP,1
  149. RCR BX,1
  150. RCR DX,1
  151. RCL AH,1 ; Shift round into lsb of AH
  152. pub GOTROUNDANDSTICKY
  153. OR AX,AX ; Was number exact?
  154. JZ short TRUNCATE
  155. OR [CURerr],Precision
  156. TEST [CWcntl],RCdown ; True if down or chop
  157. JNZ short INTDNorCHP
  158. TEST [CWcntl],RCup ; True if UP (or CHOP)
  159. JNZ short INTUP
  160. pub INTNEAR
  161. OR AL,DL ; In near mode inc if (sticky or lastbit) and Roundbit
  162. AND AH,AL
  163. SHR AH,1
  164. JNC short TRUNCATE
  165. pub INCREMENT
  166. XOR AX,AX
  167. ADD DX,1
  168. ADC BX,AX
  169. ADC BP,AX
  170. ADC DI,AX
  171. INTCHOP:
  172. pub TRUNCATE
  173. RET
  174. pub STICKYNOROUND
  175. MOV AL,1
  176. XOR AH,AH
  177. XOR DI,DI
  178. MOV BP,DI
  179. MOV BX,DI
  180. MOV DX,DI
  181. JMP GOTROUNDANDSTICKY
  182. pub INTDNorCHP
  183. TEST [CWcntl],RCup ; True if UP or CHOP
  184. JNZ INTCHOP
  185. pub INTDOWN
  186. TEST byte ptr Flag[esi],Sign ; Truncate if round down and +
  187. JNZ INCREMENT
  188. JMP TRUNCATE
  189. pub INTUP
  190. TEST byte ptr Flag[esi],Sign ; Truncate if round up and -
  191. JNZ TRUNCATE
  192. JMP INCREMENT
  193. ProfEnd FRNDI