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.

251 lines
5.6 KiB

  1. page ,132
  2. subttl emfadd.asm - Addition and Subtraction
  3. ;***
  4. ;emfadd.asm - Addition and Subtraction
  5. ;
  6. ; Copyright (c) 1986-89, Microsoft Corporation
  7. ;
  8. ;Purpose:
  9. ; Addition and Subtraction
  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. ; Addition and Subtraction ;
  21. ; ;
  22. ;-----------------------------------------;
  23. ProfBegin FADD
  24. RABRQQ: ; Routine Add Both must see if we have two singles.
  25. if fastSP
  26. MOV BX,DX
  27. XOR BX,Single + 256*Single
  28. TEST BX,Single + 256*Single
  29. JNZ RADRQQ
  30. MOV BX,OFFSET TASRQQ
  31. JMP [BX]
  32. endif ;fastSP
  33. pub RADRQQ ; RoutineAddDouble SI & DI point to valid non-0 reals
  34. ; AX CX are the exponents
  35. ; DL DH are the signs
  36. if fastSP
  37. CALL CoerceToDouble ; insure that both args are double
  38. endif ;fastSP
  39. SUB AX,CX ; See which number is larger
  40. JL short DIBIG
  41. XCHG esi,edi ; Swap pointers to operands
  42. XCHG DH,DL ; Swap signs
  43. ADD CX,AX ; CX = larger exponent (Tentative result)
  44. NEG AX
  45. pub DIBIG ; DI = larger, CX = expon, DH = sign
  46. NEG AX
  47. CMP AX,64+3 ; Is smaller argument significant?
  48. JLE short SIGNIF
  49. PUSH ebp ; Not signif so result is at DI except for
  50. PUSH edx ; rounding. ROUND assumes old BP and Sign on
  51. MOV SI,Expon[edi] ; stack. Exponent in SI
  52. MOV BP,1 ; Other argument collapses into a sticky bit
  53. XOR DL,DH ; if signs of operands differ bit is negative
  54. JNS short GetOpMantissa
  55. NEG BP
  56. pub GetOpMantissa
  57. MOV DX,MB0[edi]
  58. MOV CX,MB2[edi]
  59. MOV BX,MB4[edi]
  60. MOV DI,MB6[edi]
  61. OR BP,BP
  62. JS short NegativeStickyBit
  63. JMP ROUND
  64. pub NegativeStickyBit
  65. SUB DX,1 ; Must propagate negative sticky bit
  66. SBB CX,0
  67. SBB BX,0
  68. SBB DI,0
  69. JMP NODRQQ
  70. pub SIGNIF
  71. ; Now things look like this:
  72. ; SI has pointer to smaller operand
  73. ; DI has pointer to larger operand
  74. ; AX has exponent difference ( 0 <= CL <= 53 )
  75. ; CX has exponent
  76. ; DH has sign
  77. PUSH ebp ; Need all the registers
  78. PUSH edx ; Save sign
  79. PUSH ecx ; Save exponent
  80. XOR DL,DH ; Must eventually know whether signs are same
  81. PUSHF
  82. MOV BP,AX ; Need all 8-bit registers now
  83. ; Load smaller operand
  84. LODS word ptr ds:[esi]
  85. MOV DX,AX
  86. LODS word ptr ds:[esi]
  87. MOV CX,AX
  88. LODS word ptr ds:[esi]
  89. MOV BX,AX
  90. LODS word ptr ds:[esi]
  91. XOR si,si ; BP Will be round,guard, & sticky bits (=0)
  92. XCHG bp,si ; Done with Pointer to small. so SI = shift cnt
  93. ; hi lo 0
  94. ; Smaller operand now in AX:BX:CX:DX:BP with implied bit set, SI has shift count
  95. OR si,si
  96. JZ ALIGNED ; Alignment operations necessary?
  97. pub CHKALN
  98. CMP si,14 ; Do shifts of 16 bits by word rotate
  99. JL short BYTSHFT ; If not enough for word, go try byte
  100. OR BP,BP ; See if we're shifting something off the end
  101. JZ short NOSTIK
  102. OR DX,1 ; Ensure sticky bit will be set
  103. pub NOSTIK
  104. MOV BP,DX
  105. MOV DX,CX
  106. MOV CX,BX
  107. MOV BX,AX
  108. XOR AX,AX
  109. SUB si,16 ; Counts for 16 bit shifts
  110. JA short CHKALN ; If not enough, try again
  111. JZ short ALIGNED ; Hit it exactly?
  112. JB short SHFLEF ; Back up if too far
  113. pub BYTSHFT
  114. CMP si,6 ; Can we do a byte shift?
  115. JL short BITSHFT
  116. XCHG BP,AX
  117. OR AL,AL
  118. JZ short NSTIK
  119. OR AH,1
  120. pub NSTIK
  121. MOV AL,AH
  122. MOV AH,DL
  123. XCHG BP,AX
  124. MOV DL,DH
  125. MOV DH,CL
  126. MOV CL,CH
  127. MOV CH,BL
  128. MOV BL,BH
  129. MOV BH,AL
  130. MOV AL,AH
  131. XOR AH,AH
  132. SUB SI,8
  133. JA short BITSHFT
  134. JZ short ALIGNED
  135. ; To get here, we must have used a byte shift when we needed to shift less than
  136. ; 8 bits. Now we must correct by 1 or 2 left shifts.
  137. pub SHFLEF
  138. SHL BP,1
  139. RCL DX,1
  140. RCL CX,1
  141. RCL BX,1
  142. RCL AX,1
  143. INC SI
  144. JNZ SHFLEF ; Until DI is back to zero (from -1 or -2)
  145. JMP SHORT ALIGNED
  146. pub BITSHFT
  147. ifdef i386
  148. and esi,0FFFFh ; clear upper half of esi
  149. endif
  150. XCHG ecx,esi ; Swap count into CX, lo3:lo4 into DI
  151. TEST BP,3FH ; See if we're shifting stuff off the end
  152. JZ short SHFRIG
  153. OR BP,20H ; Set sticky bit if so
  154. pub SHFRIG
  155. SHR AX,1
  156. RCR BX,1
  157. RCR SI,1
  158. RCR DX,1
  159. RCR BP,1
  160. LOOP SHFRIG ; Do 1 to 5 64-bit right shifts
  161. MOV CX,SI ; Get back CX = lo3:lo4
  162. pub ALIGNED
  163. MOV esi,edi ; Address of larger operand
  164. MOV DI,AX ; Now DI = msb:mid
  165. TEST BP,3FFFH ; Collapse LSBs into sticky bit
  166. JZ short GETSIGN
  167. OR BP,1 ; Set sticky bit
  168. pub GETSIGN
  169. POPF ; Recover XOR of signs
  170. ; 80286 errata for POPF shouldn't
  171. ; apply because interrupts should be
  172. ; turned on in this context
  173. POP eax ; Recover Exponent
  174. ; Sign flag is XOR of signs
  175. JS short SUBMAN ; Subtract mantissas if signs are different
  176. ADD DX,[esi]
  177. ADC CX,[esi+2]
  178. ADC BX,[esi+4]
  179. ADC DI,[esi+6]
  180. JNC short JROUND ; Done if no overflow
  181. ; Have a carry, so result must be shifted right and exponent incremented
  182. RCR DI,1
  183. RCR BX,1
  184. RCR CX,1
  185. RCR DX,1
  186. RCR BP,1
  187. JNC short STIKYOK
  188. OR BP,1 ; Shifted out the sticky bit so reset it.
  189. pub STIKYOK
  190. INC AX ; Bump exponent.
  191. ; JMP JROUND ; and go round. (need not normalize)
  192. pub JROUND
  193. MOV SI,AX ; We must have SI equal to exponent
  194. JMP ROUND ; on our way to Round
  195. pub SUBMAN
  196. ; Subtract mantissas since signs are different. We'll be subtracting larger
  197. ; from smaller, so sign will be inverted first after the subtraction.
  198. SUB DX,[esi]
  199. SBB CX,[esi+2]
  200. SBB BX,[esi+4]
  201. SBB DI,[esi+6]
  202. JNC short JNORM ; Won't carry if we mixed up larger and smaller
  203. ; As expected, we got a carry which means we original sign was OK
  204. XOR SI,SI ; We'll need a zero, so let's use SI
  205. NOT DI
  206. NOT BX
  207. NOT CX
  208. NOT DX
  209. NEG BP ; Carry clear if zero
  210. CMC ; Set CY
  211. ADC DX,SI
  212. ADC CX,SI ; Propagate carry
  213. ADC BX,SI
  214. ADC DI,SI
  215. MOV SI,AX ; Get exponent to SI
  216. JMP NODRQQ ; Go normalize
  217. pub JNORM
  218. MOV SI,AX ; Exponent in SI
  219. POP eax
  220. XOR AH,SIGN ; invert sign bit (on top of stack)
  221. PUSH eax
  222. JMP NODRQQ ; and go normalize
  223. ProfEnd FADD