x_unfl.S
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:7k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. |
  2. | x_unfl.sa 3.4 7/1/91
  3. |
  4. | fpsp_unfl --- FPSP handler for underflow exception
  5. |
  6. | Trap disabled results
  7. | For 881/2 compatibility, sw must denormalize the intermediate 
  8. | result, then store the result.  Denormalization is accomplished 
  9. | by taking the intermediate result (which is always normalized) and 
  10. | shifting the mantissa right while incrementing the exponent until 
  11. | it is equal to the denormalized exponent for the destination 
  12. | format.  After denormalization, the result is rounded to the 
  13. | destination format.
  14. |
  15. | Trap enabled results
  16. |  All trap disabled code applies. In addition the exceptional 
  17. | operand needs to made available to the user with a bias of $6000 
  18. | added to the exponent.
  19. |
  20. | Copyright (C) Motorola, Inc. 1990
  21. | All Rights Reserved
  22. |
  23. | THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA 
  24. | The copyright notice above does not evidence any  
  25. | actual or intended publication of such source code.
  26. X_UNFL: |idnt    2,1 | Motorola 040 Floating Point Software Package
  27. |section 8
  28. .include "fpsp.h"
  29. |xref denorm
  30. |xref round
  31. |xref store
  32. |xref g_rndpr
  33. |xref g_opcls
  34. |xref g_dfmtou
  35. |xref real_unfl
  36. |xref real_inex
  37. |xref fpsp_done
  38. |xref b1238_fix
  39. .global fpsp_unfl
  40. fpsp_unfl:
  41. link %a6,#-LOCAL_SIZE
  42. fsave -(%a7)
  43. moveml %d0-%d1/%a0-%a1,USER_DA(%a6)
  44. fmovemx %fp0-%fp3,USER_FP0(%a6)
  45. fmoveml %fpcr/%fpsr/%fpiar,USER_FPCR(%a6)
  46. |
  47. bsrl unf_res |denormalize, round & store interm op
  48. |
  49. | If underflow exceptions are not enabled, check for inexact
  50. | exception
  51. |
  52. btstb #unfl_bit,FPCR_ENABLE(%a6)
  53. beqs ck_inex
  54. btstb #E3,E_BYTE(%a6)
  55. beqs no_e3_1
  56. |
  57. | Clear dirty bit on dest resister in the frame before branching
  58. | to b1238_fix.
  59. |
  60. bfextu CMDREG3B(%a6){#6:#3},%d0 |get dest reg no
  61. bclrb %d0,FPR_DIRTY_BITS(%a6) |clr dest dirty bit
  62. bsrl b1238_fix |test for bug1238 case
  63. movel USER_FPSR(%a6),FPSR_SHADOW(%a6)
  64. orl #sx_mask,E_BYTE(%a6)
  65. no_e3_1:
  66. moveml USER_DA(%a6),%d0-%d1/%a0-%a1
  67. fmovemx USER_FP0(%a6),%fp0-%fp3
  68. fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
  69. frestore (%a7)+
  70. unlk %a6
  71. bral real_unfl
  72. |
  73. | It is possible to have either inex2 or inex1 exceptions with the
  74. | unfl.  If the inex enable bit is set in the FPCR, and either
  75. | inex2 or inex1 occurred, we must clean up and branch to the
  76. | real inex handler.
  77. |
  78. ck_inex:
  79. moveb FPCR_ENABLE(%a6),%d0
  80. andb FPSR_EXCEPT(%a6),%d0
  81. andib #0x3,%d0
  82. beqs unfl_done
  83. |
  84. | Inexact enabled and reported, and we must take an inexact exception
  85. |
  86. take_inex:
  87. btstb #E3,E_BYTE(%a6)
  88. beqs no_e3_2
  89. |
  90. | Clear dirty bit on dest resister in the frame before branching
  91. | to b1238_fix.
  92. |
  93. bfextu CMDREG3B(%a6){#6:#3},%d0 |get dest reg no
  94. bclrb %d0,FPR_DIRTY_BITS(%a6) |clr dest dirty bit
  95. bsrl b1238_fix |test for bug1238 case
  96. movel USER_FPSR(%a6),FPSR_SHADOW(%a6)
  97. orl #sx_mask,E_BYTE(%a6)
  98. no_e3_2:
  99. moveb #INEX_VEC,EXC_VEC+1(%a6)
  100. moveml         USER_DA(%a6),%d0-%d1/%a0-%a1
  101. fmovemx        USER_FP0(%a6),%fp0-%fp3
  102. fmoveml        USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
  103. frestore        (%a7)+
  104. unlk            %a6
  105. bral real_inex
  106. unfl_done:
  107. bclrb #E3,E_BYTE(%a6)
  108. beqs e1_set |if set then branch
  109. |
  110. | Clear dirty bit on dest resister in the frame before branching
  111. | to b1238_fix.
  112. |
  113. bfextu CMDREG3B(%a6){#6:#3},%d0 |get dest reg no
  114. bclrb %d0,FPR_DIRTY_BITS(%a6) |clr dest dirty bit
  115. bsrl b1238_fix |test for bug1238 case
  116. movel USER_FPSR(%a6),FPSR_SHADOW(%a6)
  117. orl #sx_mask,E_BYTE(%a6)
  118. moveml USER_DA(%a6),%d0-%d1/%a0-%a1
  119. fmovemx USER_FP0(%a6),%fp0-%fp3
  120. fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
  121. frestore (%a7)+
  122. unlk %a6
  123. bral fpsp_done
  124. e1_set:
  125. moveml USER_DA(%a6),%d0-%d1/%a0-%a1
  126. fmovemx USER_FP0(%a6),%fp0-%fp3
  127. fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
  128. unlk %a6
  129. bral fpsp_done
  130. |
  131. | unf_res --- underflow result calculation
  132. |
  133. unf_res:
  134. bsrl g_rndpr |returns RND_PREC in d0 0=ext,
  135. | ;1=sgl, 2=dbl
  136. | ;we need the RND_PREC in the
  137. | ;upper word for round
  138. movew #0,-(%a7)
  139. movew %d0,-(%a7) |copy RND_PREC to stack
  140. |
  141. |
  142. | If the exception bit set is E3, the exceptional operand from the
  143. | fpu is in WBTEMP; else it is in FPTEMP.
  144. |
  145. btstb #E3,E_BYTE(%a6)
  146. beqs unf_E1
  147. unf_E3:
  148. lea WBTEMP(%a6),%a0 |a0 now points to operand
  149. |
  150. | Test for fsgldiv and fsglmul.  If the inst was one of these, then
  151. | force the precision to extended for the denorm routine.  Use
  152. | the user's precision for the round routine.
  153. |
  154. movew CMDREG3B(%a6),%d1 |check for fsgldiv or fsglmul
  155. andiw #0x7f,%d1
  156. cmpiw #0x30,%d1 |check for sgldiv
  157. beqs unf_sgl
  158. cmpiw #0x33,%d1 |check for sglmul
  159. bnes unf_cont |if not, use fpcr prec in round
  160. unf_sgl:
  161. clrl %d0
  162. movew #0x1,(%a7) |override g_rndpr precision
  163. | ;force single
  164. bras unf_cont
  165. unf_E1:
  166. lea FPTEMP(%a6),%a0 |a0 now points to operand
  167. unf_cont:
  168. bclrb #sign_bit,LOCAL_EX(%a0) |clear sign bit
  169. sne LOCAL_SGN(%a0) |store sign
  170. bsrl denorm |returns denorm, a0 points to it
  171. |
  172. | WARNING:
  173. | ;d0 has guard,round sticky bit
  174. | ;make sure that it is not corrupted
  175. | ;before it reaches the round subroutine
  176. | ;also ensure that a0 isn't corrupted
  177. |
  178. | Set up d1 for round subroutine d1 contains the PREC/MODE
  179. | information respectively on upper/lower register halves.
  180. |
  181. bfextu FPCR_MODE(%a6){#2:#2},%d1 |get mode from FPCR
  182. | ;mode in lower d1
  183. addl (%a7)+,%d1 |merge PREC/MODE
  184. |
  185. | WARNING: a0 and d0 are assumed to be intact between the denorm and
  186. | round subroutines. All code between these two subroutines
  187. | must not corrupt a0 and d0.
  188. |
  189. |
  190. | Perform Round
  191. | Input: a0 points to input operand
  192. | d0{31:29} has guard, round, sticky
  193. | d1{01:00} has rounding mode
  194. | d1{17:16} has rounding precision
  195. | Output: a0 points to rounded operand
  196. |
  197. bsrl round |returns rounded denorm at (a0)
  198. |
  199. | Differentiate between store to memory vs. store to register
  200. |
  201. unf_store:
  202. bsrl g_opcls |returns opclass in d0{2:0}
  203. cmpib #0x3,%d0
  204. bnes not_opc011
  205. |
  206. | At this point, a store to memory is pending
  207. |
  208. opc011:
  209. bsrl g_dfmtou
  210. tstb %d0
  211. beqs ext_opc011 |If extended, do not subtract
  212. |  ;If destination format is sgl/dbl, 
  213. tstb LOCAL_HI(%a0) |If rounded result is normal,don't
  214. | ;subtract
  215. bmis ext_opc011
  216. subqw #1,LOCAL_EX(%a0) |account for denorm bias vs.
  217. | ;normalized bias
  218. | ;          normalized   denormalized
  219. | ;single       $7f           $7e
  220. | ;double       $3ff          $3fe
  221. |
  222. ext_opc011:
  223. bsrl store |stores to memory
  224. bras unf_done |finish up
  225. |
  226. | At this point, a store to a float register is pending
  227. |
  228. not_opc011:
  229. bsrl store |stores to float register
  230. | ;a0 is not corrupted on a store to a
  231. | ;float register.
  232. |
  233. | Set the condition codes according to result
  234. |
  235. tstl LOCAL_HI(%a0) |check upper mantissa
  236. bnes ck_sgn
  237. tstl LOCAL_LO(%a0) |check lower mantissa
  238. bnes ck_sgn
  239. bsetb #z_bit,FPSR_CC(%a6) |set condition codes if zero
  240. ck_sgn:
  241. btstb  #sign_bit,LOCAL_EX(%a0) |check the sign bit
  242. beqs unf_done
  243. bsetb #neg_bit,FPSR_CC(%a6)
  244. |
  245. | Finish.  
  246. |
  247. unf_done:
  248. btstb #inex2_bit,FPSR_EXCEPT(%a6)
  249. beqs no_aunfl
  250. bsetb #aunfl_bit,FPSR_AEXCEPT(%a6)
  251. no_aunfl:
  252. rts
  253. |end