scale.S 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  1. |
  2. | scale.sa 3.3 7/30/91
  3. |
  4. | The entry point sSCALE computes the destination operand
  5. | scaled by the source operand. If the absolute value of
  6. | the source operand is (>= 2^14) an overflow or underflow
  7. | is returned.
  8. |
  9. | The entry point sscale is called from do_func to emulate
  10. | the fscale unimplemented instruction.
  11. |
  12. | Input: Double-extended destination operand in FPTEMP,
  13. | double-extended source operand in ETEMP.
  14. |
  15. | Output: The function returns scale(X,Y) to fp0.
  16. |
  17. | Modifies: fp0.
  18. |
  19. | Algorithm:
  20. |
  21. | Copyright (C) Motorola, Inc. 1990
  22. | All Rights Reserved
  23. |
  24. | For details on the license for this file, please see the
  25. | file, README, in this same directory.
  26. |SCALE idnt 2,1 | Motorola 040 Floating Point Software Package
  27. |section 8
  28. #include "fpsp.h"
  29. |xref t_ovfl2
  30. |xref t_unfl
  31. |xref round
  32. |xref t_resdnrm
  33. SRC_BNDS: .short 0x3fff,0x400c
  34. |
  35. | This entry point is used by the unimplemented instruction exception
  36. | handler.
  37. |
  38. |
  39. |
  40. | FSCALE
  41. |
  42. .global sscale
  43. sscale:
  44. fmovel #0,%fpcr |clr user enabled exc
  45. clrl %d1
  46. movew FPTEMP(%a6),%d1 |get dest exponent
  47. smi L_SCR1(%a6) |use L_SCR1 to hold sign
  48. andil #0x7fff,%d1 |strip sign
  49. movew ETEMP(%a6),%d0 |check src bounds
  50. andiw #0x7fff,%d0 |clr sign bit
  51. cmp2w SRC_BNDS,%d0
  52. bccs src_in
  53. cmpiw #0x400c,%d0 |test for too large
  54. bge src_out
  55. |
  56. | The source input is below 1, so we check for denormalized numbers
  57. | and set unfl.
  58. |
  59. src_small:
  60. moveb DTAG(%a6),%d0
  61. andib #0xe0,%d0
  62. tstb %d0
  63. beqs no_denorm
  64. st STORE_FLG(%a6) |dest already contains result
  65. orl #unfl_mask,USER_FPSR(%a6) |set UNFL
  66. den_done:
  67. leal FPTEMP(%a6),%a0
  68. bra t_resdnrm
  69. no_denorm:
  70. fmovel USER_FPCR(%a6),%FPCR
  71. fmovex FPTEMP(%a6),%fp0 |simply return dest
  72. rts
  73. |
  74. | Source is within 2^14 range. To perform the int operation,
  75. | move it to d0.
  76. |
  77. src_in:
  78. fmovex ETEMP(%a6),%fp0 |move in src for int
  79. fmovel #rz_mode,%fpcr |force rz for src conversion
  80. fmovel %fp0,%d0 |int src to d0
  81. fmovel #0,%FPSR |clr status from above
  82. tstw ETEMP(%a6) |check src sign
  83. blt src_neg
  84. |
  85. | Source is positive. Add the src to the dest exponent.
  86. | The result can be denormalized, if src = 0, or overflow,
  87. | if the result of the add sets a bit in the upper word.
  88. |
  89. src_pos:
  90. tstw %d1 |check for denorm
  91. beq dst_dnrm
  92. addl %d0,%d1 |add src to dest exp
  93. beqs denorm |if zero, result is denorm
  94. cmpil #0x7fff,%d1 |test for overflow
  95. bges ovfl
  96. tstb L_SCR1(%a6)
  97. beqs spos_pos
  98. orw #0x8000,%d1
  99. spos_pos:
  100. movew %d1,FPTEMP(%a6) |result in FPTEMP
  101. fmovel USER_FPCR(%a6),%FPCR
  102. fmovex FPTEMP(%a6),%fp0 |write result to fp0
  103. rts
  104. ovfl:
  105. tstb L_SCR1(%a6)
  106. beqs sovl_pos
  107. orw #0x8000,%d1
  108. sovl_pos:
  109. movew FPTEMP(%a6),ETEMP(%a6) |result in ETEMP
  110. movel FPTEMP_HI(%a6),ETEMP_HI(%a6)
  111. movel FPTEMP_LO(%a6),ETEMP_LO(%a6)
  112. bra t_ovfl2
  113. denorm:
  114. tstb L_SCR1(%a6)
  115. beqs den_pos
  116. orw #0x8000,%d1
  117. den_pos:
  118. tstl FPTEMP_HI(%a6) |check j bit
  119. blts nden_exit |if set, not denorm
  120. movew %d1,ETEMP(%a6) |input expected in ETEMP
  121. movel FPTEMP_HI(%a6),ETEMP_HI(%a6)
  122. movel FPTEMP_LO(%a6),ETEMP_LO(%a6)
  123. orl #unfl_bit,USER_FPSR(%a6) |set unfl
  124. leal ETEMP(%a6),%a0
  125. bra t_resdnrm
  126. nden_exit:
  127. movew %d1,FPTEMP(%a6) |result in FPTEMP
  128. fmovel USER_FPCR(%a6),%FPCR
  129. fmovex FPTEMP(%a6),%fp0 |write result to fp0
  130. rts
  131. |
  132. | Source is negative. Add the src to the dest exponent.
  133. | (The result exponent will be reduced). The result can be
  134. | denormalized.
  135. |
  136. src_neg:
  137. addl %d0,%d1 |add src to dest
  138. beqs denorm |if zero, result is denorm
  139. blts fix_dnrm |if negative, result is
  140. | ;needing denormalization
  141. tstb L_SCR1(%a6)
  142. beqs sneg_pos
  143. orw #0x8000,%d1
  144. sneg_pos:
  145. movew %d1,FPTEMP(%a6) |result in FPTEMP
  146. fmovel USER_FPCR(%a6),%FPCR
  147. fmovex FPTEMP(%a6),%fp0 |write result to fp0
  148. rts
  149. |
  150. | The result exponent is below denorm value. Test for catastrophic
  151. | underflow and force zero if true. If not, try to shift the
  152. | mantissa right until a zero exponent exists.
  153. |
  154. fix_dnrm:
  155. cmpiw #0xffc0,%d1 |lower bound for normalization
  156. blt fix_unfl |if lower, catastrophic unfl
  157. movew %d1,%d0 |use d0 for exp
  158. movel %d2,-(%a7) |free d2 for norm
  159. movel FPTEMP_HI(%a6),%d1
  160. movel FPTEMP_LO(%a6),%d2
  161. clrl L_SCR2(%a6)
  162. fix_loop:
  163. addw #1,%d0 |drive d0 to 0
  164. lsrl #1,%d1 |while shifting the
  165. roxrl #1,%d2 |mantissa to the right
  166. bccs no_carry
  167. st L_SCR2(%a6) |use L_SCR2 to capture inex
  168. no_carry:
  169. tstw %d0 |it is finished when
  170. blts fix_loop |d0 is zero or the mantissa
  171. tstb L_SCR2(%a6)
  172. beqs tst_zero
  173. orl #unfl_inx_mask,USER_FPSR(%a6)
  174. | ;set unfl, aunfl, ainex
  175. |
  176. | Test for zero. If zero, simply use fmove to return +/- zero
  177. | to the fpu.
  178. |
  179. tst_zero:
  180. clrw FPTEMP_EX(%a6)
  181. tstb L_SCR1(%a6) |test for sign
  182. beqs tst_con
  183. orw #0x8000,FPTEMP_EX(%a6) |set sign bit
  184. tst_con:
  185. movel %d1,FPTEMP_HI(%a6)
  186. movel %d2,FPTEMP_LO(%a6)
  187. movel (%a7)+,%d2
  188. tstl %d1
  189. bnes not_zero
  190. tstl FPTEMP_LO(%a6)
  191. bnes not_zero
  192. |
  193. | Result is zero. Check for rounding mode to set lsb. If the
  194. | mode is rp, and the zero is positive, return smallest denorm.
  195. | If the mode is rm, and the zero is negative, return smallest
  196. | negative denorm.
  197. |
  198. btstb #5,FPCR_MODE(%a6) |test if rm or rp
  199. beqs no_dir
  200. btstb #4,FPCR_MODE(%a6) |check which one
  201. beqs zer_rm
  202. zer_rp:
  203. tstb L_SCR1(%a6) |check sign
  204. bnes no_dir |if set, neg op, no inc
  205. movel #1,FPTEMP_LO(%a6) |set lsb
  206. bras sm_dnrm
  207. zer_rm:
  208. tstb L_SCR1(%a6) |check sign
  209. beqs no_dir |if clr, neg op, no inc
  210. movel #1,FPTEMP_LO(%a6) |set lsb
  211. orl #neg_mask,USER_FPSR(%a6) |set N
  212. bras sm_dnrm
  213. no_dir:
  214. fmovel USER_FPCR(%a6),%FPCR
  215. fmovex FPTEMP(%a6),%fp0 |use fmove to set cc's
  216. rts
  217. |
  218. | The rounding mode changed the zero to a smallest denorm. Call
  219. | t_resdnrm with exceptional operand in ETEMP.
  220. |
  221. sm_dnrm:
  222. movel FPTEMP_EX(%a6),ETEMP_EX(%a6)
  223. movel FPTEMP_HI(%a6),ETEMP_HI(%a6)
  224. movel FPTEMP_LO(%a6),ETEMP_LO(%a6)
  225. leal ETEMP(%a6),%a0
  226. bra t_resdnrm
  227. |
  228. | Result is still denormalized.
  229. |
  230. not_zero:
  231. orl #unfl_mask,USER_FPSR(%a6) |set unfl
  232. tstb L_SCR1(%a6) |check for sign
  233. beqs fix_exit
  234. orl #neg_mask,USER_FPSR(%a6) |set N
  235. fix_exit:
  236. bras sm_dnrm
  237. |
  238. | The result has underflowed to zero. Return zero and set
  239. | unfl, aunfl, and ainex.
  240. |
  241. fix_unfl:
  242. orl #unfl_inx_mask,USER_FPSR(%a6)
  243. btstb #5,FPCR_MODE(%a6) |test if rm or rp
  244. beqs no_dir2
  245. btstb #4,FPCR_MODE(%a6) |check which one
  246. beqs zer_rm2
  247. zer_rp2:
  248. tstb L_SCR1(%a6) |check sign
  249. bnes no_dir2 |if set, neg op, no inc
  250. clrl FPTEMP_EX(%a6)
  251. clrl FPTEMP_HI(%a6)
  252. movel #1,FPTEMP_LO(%a6) |set lsb
  253. bras sm_dnrm |return smallest denorm
  254. zer_rm2:
  255. tstb L_SCR1(%a6) |check sign
  256. beqs no_dir2 |if clr, neg op, no inc
  257. movew #0x8000,FPTEMP_EX(%a6)
  258. clrl FPTEMP_HI(%a6)
  259. movel #1,FPTEMP_LO(%a6) |set lsb
  260. orl #neg_mask,USER_FPSR(%a6) |set N
  261. bra sm_dnrm |return smallest denorm
  262. no_dir2:
  263. tstb L_SCR1(%a6)
  264. bges pos_zero
  265. neg_zero:
  266. clrl FP_SCR1(%a6) |clear the exceptional operand
  267. clrl FP_SCR1+4(%a6) |for gen_except.
  268. clrl FP_SCR1+8(%a6)
  269. fmoves #0x80000000,%fp0
  270. rts
  271. pos_zero:
  272. clrl FP_SCR1(%a6) |clear the exceptional operand
  273. clrl FP_SCR1+4(%a6) |for gen_except.
  274. clrl FP_SCR1+8(%a6)
  275. fmoves #0x00000000,%fp0
  276. rts
  277. |
  278. | The destination is a denormalized number. It must be handled
  279. | by first shifting the bits in the mantissa until it is normalized,
  280. | then adding the remainder of the source to the exponent.
  281. |
  282. dst_dnrm:
  283. moveml %d2/%d3,-(%a7)
  284. movew FPTEMP_EX(%a6),%d1
  285. movel FPTEMP_HI(%a6),%d2
  286. movel FPTEMP_LO(%a6),%d3
  287. dst_loop:
  288. tstl %d2 |test for normalized result
  289. blts dst_norm |exit loop if so
  290. tstl %d0 |otherwise, test shift count
  291. beqs dst_fin |if zero, shifting is done
  292. subil #1,%d0 |dec src
  293. lsll #1,%d3
  294. roxll #1,%d2
  295. bras dst_loop
  296. |
  297. | Destination became normalized. Simply add the remaining
  298. | portion of the src to the exponent.
  299. |
  300. dst_norm:
  301. addw %d0,%d1 |dst is normalized; add src
  302. tstb L_SCR1(%a6)
  303. beqs dnrm_pos
  304. orl #0x8000,%d1
  305. dnrm_pos:
  306. movemw %d1,FPTEMP_EX(%a6)
  307. moveml %d2,FPTEMP_HI(%a6)
  308. moveml %d3,FPTEMP_LO(%a6)
  309. fmovel USER_FPCR(%a6),%FPCR
  310. fmovex FPTEMP(%a6),%fp0
  311. moveml (%a7)+,%d2/%d3
  312. rts
  313. |
  314. | Destination remained denormalized. Call t_excdnrm with
  315. | exceptional operand in ETEMP.
  316. |
  317. dst_fin:
  318. tstb L_SCR1(%a6) |check for sign
  319. beqs dst_exit
  320. orl #neg_mask,USER_FPSR(%a6) |set N
  321. orl #0x8000,%d1
  322. dst_exit:
  323. movemw %d1,ETEMP_EX(%a6)
  324. moveml %d2,ETEMP_HI(%a6)
  325. moveml %d3,ETEMP_LO(%a6)
  326. orl #unfl_mask,USER_FPSR(%a6) |set unfl
  327. moveml (%a7)+,%d2/%d3
  328. leal ETEMP(%a6),%a0
  329. bra t_resdnrm
  330. |
  331. | Source is outside of 2^14 range. Test the sign and branch
  332. | to the appropriate exception handler.
  333. |
  334. src_out:
  335. tstb L_SCR1(%a6)
  336. beqs scro_pos
  337. orl #0x8000,%d1
  338. scro_pos:
  339. movel FPTEMP_HI(%a6),ETEMP_HI(%a6)
  340. movel FPTEMP_LO(%a6),ETEMP_LO(%a6)
  341. tstw ETEMP(%a6)
  342. blts res_neg
  343. res_pos:
  344. movew %d1,ETEMP(%a6) |result in ETEMP
  345. bra t_ovfl2
  346. res_neg:
  347. movew %d1,ETEMP(%a6) |result in ETEMP
  348. leal ETEMP(%a6),%a0
  349. bra t_unfl
  350. |end