fadd.asm 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. _fadd:
  2. PUSH BP
  3. MOV BP,SP
  4. MOV EAX,DWORD PTR [BP+4]
  5. MOV EDX,DWORD PTR [BP+8]
  6. MOV EBX,DWORD PTR [BP+12]
  7. MOV ECX,DWORD PTR [BP+16]
  8. CALL faddfxfy
  9. MOV DWORD PTR _facc,EAX
  10. MOV DWORD PTR _facc+4,EDX
  11. POP BP
  12. RET
  13. fsubfxfy:
  14. XOR ECX,#$80000000 ; complement sign bit, fall into add routine
  15. faddfxfy:
  16. PUSH EBP
  17. PUSH EDI
  18. PUSH ESI
  19. MOV EDI,ECX ; free CL for shifts
  20. MOV ESI,EDX ; this mainly for consistent naming
  21. AND ESI,#$7FFFFFFF ; discard sign so comparison is simple
  22. AND EDI,#$7FFFFFFF
  23. CMP ESI,EDI
  24. JA XBIG
  25. JB SWAP
  26. CMP EAX,EBX
  27. JAE XBIG
  28. SWAP:
  29. XCHG EDX,ECX
  30. XCHG ESI,EDI
  31. XCHG EAX,EBX
  32. XBIG:
  33. AND ESI,#$000FFFFF ; discard exponent
  34. AND EDI,#$000FFFFF
  35. OR ESI,#$00100000 ; normalize
  36. OR EDI,#$00100000
  37. SHR ECX,32-(1+11)
  38. SHR EDX,32-(1+11)
  39. MOV EBP,ECX ; prepare to compare signs (want high bits 0)
  40. SUB CX,DX ; get difference of signs in CX
  41. NEG CX ; D holds sign and exponent of both throughout
  42. CMP CX,#(64-11)+2
  43. JAE TO_DONE1 ; x dominates y
  44. XOR BP,DX
  45. AND BP,#$0800 ; see if signs are same
  46. JNZ TO_SUBTRACT ; else roundoff reg EBP is 0
  47. CMP CL,#32
  48. JAE TO_ADD_BIGSHIFT
  49. SHRD EBP,EBX,CL
  50. SHRD EBX,EDI,CL
  51. SHR EDI,CL
  52. ADD EAX,EBX
  53. ADC ESI,EDI
  54. SUB EBX,EBX
  55. ; result DX(1+11):SI:AX:BP:BX but needs normalization
  56. NORMALIZE:
  57. MOV CX,DX
  58. AND CX,#$07FF
  59. TEST ESI,#$00200000
  60. JZ NORMALIZE2
  61. BR LOVERFLOW
  62. TO_DONE1:
  63. JMP DONE1
  64. TO_SUBTRACT:
  65. BR SUBTRACT
  66. TO_ADD_BIGSHIFT:
  67. BR ADD_BIGSHIFT
  68. TO_NORMLITTLE:
  69. BR NORMLITTLE
  70. ; result DX(1):CX(11):SI:AX:BP:BX
  71. NORMALIZE2:
  72. SHRD EDI,ESI,32-11
  73. ; top 11 bits of ESI known 0 and BSR is slooow
  74. BSR EDI,EDI ; index of leading 1 bit in EDI is 11..31 in DI
  75. JZ TO_NORMLITTLE ; ESI is zero (flag wrong in Intel Manual)
  76. SUB DI,#31
  77. NEG DI
  78. PUSH CX ; gr
  79. MOV CX,DI ; rr
  80. SHLD ESI,EAX,CL
  81. SHLD EAX,EBP,CL
  82. SHLD EBP,EBX,CL
  83. SHL EBX,CL
  84. POP CX ; rr
  85. SUB CX,DI
  86. JC UNDERFLOW
  87. ROUND:
  88. CMP EBP,#$80000000 ; test roundoff register
  89. JA ROUNDUP
  90. JB DONE ; no rounding
  91. TEST EBX,EBX
  92. JNZ ROUNDUP
  93. TEST AL,#1 ; ambiguous case, round to even
  94. JZ DONE ; even, no rounding
  95. ROUNDUP:
  96. ADD EAX,#1
  97. ADC ESI,#0
  98. SUB EBP,EBP
  99. SUB EBX,EBX
  100. TEST ESI,#$00200000
  101. JNZ LOVERFLOW ; rounding may cause overflow!
  102. DONE:
  103. AND DX,#$0800 ; extract sign of largest and result
  104. OR DX,CX ; include exponent with sign
  105. DONE1:
  106. SHL EDX,32-(1+11)
  107. AND ESI,#$000FFFFF ; discard normalization bit
  108. OR EDX,ESI
  109. POP ESI
  110. POP EDI
  111. POP EBP
  112. RET
  113. UNDERFLOW: ; should have error message here
  114. ANSWER0:
  115. SUB EDX,EDX
  116. MOV EAX,EDX
  117. POP ESI
  118. POP EDI
  119. POP EBP
  120. RET
  121. LOVERFLOW: ; carry bit must be right-shifted back in
  122. SHR ESI,1
  123. RCR EAX,1
  124. RCR EBP,1
  125. RCR EBX,1
  126. INC CX
  127. CMP CX,#$0800
  128. JNZ ROUND
  129. OVERFLOW: ; should have error message here
  130. MOV EDX,#$FFE00000 ; + infinity
  131. SUB EAX,EAX
  132. POP ESI
  133. POP EDI
  134. POP EBP
  135. RET
  136. ADD_BIGSHIFT:
  137. SUB CL,#32
  138. SHRD EBP,EBX,CL
  139. SHRD EBX,EDI,CL
  140. SHR EDI,CL
  141. ADD EAX,EDI
  142. ADC ESI,#0
  143. XCHG EBP,EBX
  144. BR NORMALIZE
  145. NORMLITTLE:
  146. SHLD ESI,EAX,32-(1+11)
  147. SHLD EAX,EBP,32-(1+11)
  148. SHLD EBP,EBX,32-(1+11)
  149. SHL EBX,20
  150. SUB CL,#32-(1+11)
  151. JC UNDERFLOW
  152. BR NORMALIZE2
  153. SUBTRACT:
  154. SUB EBP,EBP ; set up roundoff register
  155. CMP CL,#32
  156. JAE SUBTRACT_BIGSHIFT
  157. SHRD EBP,EBX,CL
  158. SHRD EBX,EDI,CL
  159. SHR EDI,CL
  160. NEG EBP
  161. SBB EAX,EBX
  162. SBB ESI,EDI
  163. SUB EBX,EBX
  164. MOV CX,DX
  165. AND CX,#$07FF
  166. BR NORMALIZE2
  167. SUBTRACT_BIGSHIFT:
  168. SUB CL,#32
  169. SHRD EBP,EBX,CL
  170. SHRD EBX,EDI,CL
  171. SHR EDI,CL
  172. NEG EBX
  173. NEG EBP
  174. SBB EBX,#0
  175. SBB EAX,EDI
  176. SBB ESI,#0
  177. XCHG EBP,EBX
  178. MOV CX,DX
  179. AND CX,#$07FF
  180. BR NORMALIZE2
  181. TO_ANSWER0:
  182. BR ANSWER0
  183. TO_OVERFLOW:
  184. JMP TO_OVERFLOW
  185. TO_UNDERFLOW:
  186. BR UNDERFLOW
  187. fmulfxfy:
  188. PUSH EBP
  189. PUSH EDI
  190. PUSH ESI
  191. MOV ESI,EDX ; free DX for multiplications
  192. MOV EDI,ECX ; this mainly for consistent naming
  193. SHR EDX,32-(1+11)
  194. SHR ECX,32-(1+11)
  195. MOV BP,DX
  196. XOR BP,CX
  197. AND BP,#$0800 ; extract sign
  198. AND DX,#$07FF ; exp(x)
  199. JZ TO_ANSWER0
  200. AND CX,#$07FF ; exp(y)
  201. JZ TO_ANSWER0
  202. ADD CX,DX
  203. SUB CX,#$0400
  204. JB TO_UNDERFLOW
  205. CMP CX,#$07FF
  206. JA TO_OVERFLOW ; probably not quite right
  207. AND ESI,#$000FFFFF ; discard sign and exponent
  208. AND EDI,#$000FFFFF
  209. OR ESI,#$00100000 ; normalize
  210. OR EDI,#$00100000
  211. ; exponent is in CX, sign in BP, operands in ESI:EAX and EDI:EBX, DX is free
  212. ; product to go in ESI:EAX:EBP:EBX
  213. ; terminology: x * y = (x32:x0) * (y32:y0) = x32y32 + x32y0 + x0y32 +x0y0
  214. PUSH CX
  215. PUSH BP
  216. MOV ECX,EAX
  217. MUL EBX ; x0y0
  218. MOV EBP,EDX ; x0y0.high in EBP
  219. XCHG EBX,EAX ; x0y0.low in EBX (final), y0 in EAX
  220. MUL ESI ; x32y0
  221. PUSH EAX ; x32y0.low on stack
  222. PUSH EDX ; x32y0.high on stack
  223. MOV EAX,ESI
  224. MUL EDI ; x32y32
  225. MOV ESI,EDX ; x32y32.high in ESI (final except carries)
  226. XCHG ECX,EAX ; x32y32.low in ECX, x0 in EAX
  227. MUL EDI ; x0y32
  228. ADD EBP,EAX ; x0y0.high + x0y32.low
  229. POP EAX ; x32y0.high
  230. ADC EAX,EDX ; x32y0.high + x0y32.high
  231. ADC ESI,#0
  232. POP EDX ; x32y0.low
  233. ADD EBP,EDX ; (x0y0.high + x0y32.low) + x32y0.low
  234. ADC EAX,ECX ; (x32y0.high + x0y32.high) + x32y32.low
  235. ADC ESI,#0
  236. POP DX ; sign
  237. POP CX ; exponent
  238. ADD CX,#13 ; temp fixup
  239. BR NORMALIZE2
  240. _facc:
  241. .word 0,0