x_unfl.s
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:8k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* x_unfl.s - Motorola 68040 FP underflow exception handler (EXC) */
  2. /* Copyright 1991-1993 Wind River Systems, Inc. */
  3. .data
  4. .globl _copyright_wind_river
  5. .long _copyright_wind_river
  6. /*
  7. modification history
  8. --------------------
  9. 01e,21jul93,kdl  added .text (SPR #2372).
  10. 01d,23aug92,jcf  changed bxxx to jxx.
  11. 01c,26may92,rrr  the tree shuffle
  12. 01b,10jan92,kdl  added modification history; general cleanup.
  13. 01a,15aug91,kdl  original version, from Motorola FPSP v2.0.
  14. */
  15. /*
  16. DESCRIPTION
  17. x_unflsa 3.3 4/26/91
  18. __x_fpsp_unfl --- FPSP handler for underflow exception
  19. Trap disabled results
  20. For 881/2 compatibility, sw must denormalize the intermediate
  21. result, then store the result.  Denormalization is accomplished
  22. by taking the intermediate result (which is always normalized) and
  23. shifting the mantissa right while incrementing the exponent until
  24. it is equal to the denormalized exponent for the destination
  25. format.  After denormalizatoin, the result is rounded to the
  26. destination format.
  27. Trap enabled results
  28. All trap disabled code applies. In addition the exceptional
  29. operand needs to made available to the user with a bias of 0x6000
  30. added to the exponent.
  31. Copyright (C) Motorola, Inc. 1990
  32. All Rights Reserved
  33. THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
  34. The copyright notice above does not evidence any
  35. actual or intended publication of such source code.
  36. X_UNFL idnt    2,1 Motorola 040 Floating Point Software Package
  37. section 8
  38. NOMANUAL
  39. */
  40. #include "fpsp040E.h"
  41. | xref __x_denorm
  42. | xref __x_round
  43. | xref __x_store
  44. | xref __x_g_rndpr
  45. | xref __x_g_opcls
  46. | xref __x_g_dfmtou
  47. | xref __x_real_unfl
  48. | xref __x_real_inex
  49. | xref __x_fpsp_done
  50. | xref __x_b1238_fix
  51. | xref __x_check_force
  52. .text
  53. .globl __x_fpsp_unfl
  54. __x_fpsp_unfl:
  55. link a6,#-LOCAL_SIZE
  56. fsave a7@-
  57. moveml d0-d1/a0-a1,a6@(USER_DA)
  58. fmovemx fp0-fp3,a6@(USER_FP0)
  59. fmoveml fpcr/fpsr/fpi,a6@(USER_FPCR)
  60. | At this point we need to look at the instructions and see if it is one of
  61. | the force-precision ones (fsadd,fdadd,fssub,fdsub,fsmul,fdmul,fsdiv,fddiv,
  62. | fssqrt,fdsqrt,fsmove,fdmove,fsabs,fdabs,fsneg,fdneg).  If it is then
  63. /* | correct the USER_FPCR to the instruction's rounding precision (s or d). */
  64. | Also, we need to check if the instruction is fsgldiv or fsglmul.  If it
  65. | is then the USER_FPCR is set to extended rounding precision.  Otherwise
  66. | leave the USER_FPCR alone.
  67. | bsrl __x_check_force
  68. |
  69. bsrl unf_res | denormalize, round # store interm op
  70. |
  71. | If underflow exceptions are not enabled, check for inexact
  72. | exception
  73. |
  74. btst #__x_unfl_bit,a6@(fpcr_ENABLE)
  75. jeq  ck_inex
  76. btst #E3,a6@(E_BYTE)
  77. jeq  no_e3_1
  78. |
  79. | Clear dirty bit on dest resister in the frame before branching
  80. | to __x_b1238_fix.
  81. |
  82. bfextu a6@(CMDREG3B){#6:#3},d0 | get dest reg no
  83. bclr d0,a6@(FPR_DIRTY_BITS) | clr dest dirty bit
  84. bsrl __x_b1238_fix | test for bug1238 case
  85. movel a6@(USER_FPSR),a6@(FPSR_SHADOW)
  86. orl #sx_mask,a6@(E_BYTE)
  87. no_e3_1:
  88. moveml a6@(USER_DA),d0-d1/a0-a1
  89. fmovemx a6@(USER_FP0),fp0-fp3
  90. fmoveml a6@(USER_FPCR),fpcr/fpsr/fpi
  91. frestore a7@+
  92. unlk a6
  93. jra  __x_real_unfl
  94. |
  95. | It is possible to have either inex2 or inex1 exceptions with the
  96. | unfl.  If the inex enable bit is set in the fpcr, and either
  97. | inex2 or inex1 occured, we must clean up and branch to the
  98. | real inex handler.
  99. |
  100. ck_inex:
  101. moveb a6@(fpcr_ENABLE),d0
  102. andb a6@(FPSR_EXCEPT),d0
  103. andib #0x3,d0
  104. jeq  __x_unfl_done
  105. |
  106. | Inexact enabled and reported, and we must take an inexact exception
  107. |
  108. take_inex:
  109. btst #E3,a6@(E_BYTE)
  110. jeq  no_e3_2
  111. |
  112. | Clear dirty bit on dest resister in the frame before branching
  113. | to __x_b1238_fix.
  114. |
  115. bfextu a6@(CMDREG3B){#6:#3},d0 | get dest reg no
  116. bclr d0,a6@(FPR_DIRTY_BITS) | clr dest dirty bit
  117. bsrl __x_b1238_fix | test for bug1238 case
  118. movel a6@(USER_FPSR),a6@(FPSR_SHADOW)
  119. orl #sx_mask,a6@(E_BYTE)
  120. no_e3_2:
  121. moveb #INEX_VEC,a6@(EXC_VEC+1)
  122. moveml         a6@(USER_DA),d0-d1/a0-a1
  123. fmovemx        a6@(USER_FP0),fp0-fp3
  124. fmoveml        a6@(USER_FPCR),fpcr/fpsr/fpi
  125. frestore        a7@+
  126. unlk            a6
  127. jra  __x_real_inex
  128. __x_unfl_done:
  129. bclr #E3,a6@(E_BYTE)
  130. jeq  e1_set | if set then branch
  131. |
  132. | Clear dirty bit on dest resister in the frame before branching
  133. | to __x_b1238_fix.
  134. |
  135. bfextu a6@(CMDREG3B){#6:#3},d0 | get dest reg no
  136. bclr d0,a6@(FPR_DIRTY_BITS) | clr dest dirty bit
  137. bsrl __x_b1238_fix | test for bug1238 case
  138. movel a6@(USER_FPSR),a6@(FPSR_SHADOW)
  139. orl #sx_mask,a6@(E_BYTE)
  140. moveml a6@(USER_DA),d0-d1/a0-a1
  141. fmovemx a6@(USER_FP0),fp0-fp3
  142. fmoveml a6@(USER_FPCR),fpcr/fpsr/fpi
  143. frestore a7@+
  144. unlk a6
  145. jra  __x_fpsp_done
  146. e1_set:
  147. moveml a6@(USER_DA),d0-d1/a0-a1
  148. fmovemx a6@(USER_FP0),fp0-fp3
  149. fmoveml a6@(USER_FPCR),fpcr/fpsr/fpi
  150. unlk a6
  151. jra  __x_fpsp_done
  152. |
  153. | unf_res --- underflow result calculation
  154. |
  155. unf_res:
  156. bsrl __x_g_rndpr | returns RND_PREC in d0 0=ext,
  157. | | 1=sgl, 2=dbl
  158. | | we need the RND_PREC in the
  159. | | upper word for __x_round
  160. movew #0,a7@-
  161. movew d0,a7@- | copy RND_PREC to stack
  162. |
  163. |
  164. | If the exception bit set is E3, the exceptional operand from the
  165. | fpu is in WBTEMP|  else it is in FPTEMP.
  166. |
  167. btst #E3,a6@(E_BYTE)
  168. jeq  unf_E1
  169. unf_E3:
  170. lea a6@(WBTEMP),a0 | a0 now points to operand
  171. |
  172. | Test for fsgldiv and fsglmul.  If the inst was one of these, then
  173. | force the precision to extended for the __x_denorm routine.  Use
  174. /* | the user's precision for the __x_round routine. */
  175. |
  176. movew a6@(CMDREG3B),d1 | check for fsgldiv or fsglmul
  177. andiw #0x7f,d1
  178. cmpiw #0x30,d1 | check for sgldiv
  179. jeq  unf_sgl
  180. cmpiw #0x33,d1 | check for sglmul
  181. jne  unf_cont | if not, use fpcr prec in __x_round
  182. unf_sgl:
  183. clrl d0
  184. movew #0x1,a7@ | override __x_g_rndpr precision
  185. | | force single
  186. jra  unf_cont
  187. unf_E1:
  188. lea a6@(FPTEMP),a0 | a0 now points to operand
  189. unf_cont:
  190. bclr #sign_bit,a0@(LOCAL_EX) | clear sign bit
  191. sne a0@(LOCAL_SGN) | store sign
  192. bsrl __x_denorm | returns denorm, a0 points to it
  193. |
  194. | WARNING:
  195. | | d0 has guard,round sticky bit
  196. | | make sure that it is not corrupted
  197. | | before it reaches the __x_round subroutine
  198. /* | | also ensure that a0 isn't corrupted */
  199. |
  200. | Set up d1 for __x_round subroutine d1 contains the PREC/MODE
  201. | information respectively on upper/lower register halves.
  202. |
  203. bfextu a6@(fpcr_MODE){#2:#2},d1 | get mode from fpcr
  204. | | mode in lower d1
  205. addl a7@+,d1 | merge PREC/MODE
  206. |
  207. | WARNING: a0 and d0 are assumed to be intact between the __x_denorm and
  208. | __x_round subroutines. All code between these two subroutines
  209. | must not corrupt a0 and d0.
  210. |
  211. |
  212. | Perform Round
  213. | Input: a0 points to input operand
  214. | d0{31:29} has guard, round, sticky
  215. | d1{01:00} has rounding mode
  216. | d1{17:16} has rounding precision
  217. | Output: a0 points to rounded operand
  218. |
  219. bsrl __x_round | returns rounded denorm at a0@
  220. |
  221. | Differentiate between store to memory vs. store to register
  222. |
  223. unf_store:
  224. bsrl __x_g_opcls | returns opclass in d0{2:0}
  225. cmpib #0x3,d0
  226. jne  not_opc011
  227. |
  228. | At this point, a store to memory is pending
  229. |
  230. opc011:
  231. bsrl __x_g_dfmtou
  232. tstb d0
  233. jeq  ext_opc011 | If extended, do not subtract
  234. |  | If destination format is sgl/dbl,
  235. tstb a0@(LOCAL_HI) /* If rounded result is normal,don't */
  236. | |  subtract
  237. jmi  ext_opc011
  238. subqw #1,a0@(LOCAL_EX) | account for denorm bias vs.
  239. | | normalized bias
  240. | |           normalized   denormalized
  241. | | single       0x7f           0x7e
  242. | | double       0x3ff          0x3fe
  243. |
  244. ext_opc011:
  245. bsrl __x_store | stores to memory
  246. jra  unf_done | finish up
  247. |
  248. | At this point, a store to a float register is pending
  249. |
  250. not_opc011:
  251. bsrl __x_store | stores to float register
  252. | | a0 is not corrupted on a store to a
  253. | | float register.
  254. |
  255. | Set the condition codes according to result
  256. |
  257. tstl a0@(LOCAL_HI) | check upper mantissa
  258. jne  ck_sgn
  259. tstl a0@(LOCAL_LO) | check lower mantissa
  260. jne  ck_sgn
  261. bset #z_bit,a6@(FPSR_CC) | set condition codes if zero
  262. ck_sgn:
  263. btst  #sign_bit,a0@(LOCAL_EX) | check the sign bit
  264. jeq  unf_done
  265. bset #neg_bit,a6@(FPSR_CC)
  266. |
  267. | Finish.
  268. |
  269. unf_done:
  270. btst #__x_inex2_bit,a6@(FPSR_EXCEPT)
  271. jeq  no_aunfl
  272. bset #aunfl_bit,a6@(FPSR_AEXCEPT)
  273. no_aunfl:
  274. rts
  275. | end