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

VxWorks

开发平台:

C/C++

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