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

嵌入式Linux

开发平台:

Unix_Linux

  1. |
  2. | kernel_ex.sa 3.3 12/19/90 
  3. |
  4. | This file contains routines to force exception status in the 
  5. | fpu for exceptional cases detected or reported within the
  6. | transcendental functions.  Typically, the t_xx routine will
  7. | set the appropriate bits in the USER_FPSR word on the stack.
  8. | The bits are tested in gen_except.sa to determine if an exceptional
  9. | situation needs to be created on return from the FPSP. 
  10. |
  11. | Copyright (C) Motorola, Inc. 1990
  12. | All Rights Reserved
  13. |
  14. | THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA 
  15. | The copyright notice above does not evidence any  
  16. | actual or intended publication of such source code.
  17. KERNEL_EX:    |idnt    2,1 | Motorola 040 Floating Point Software Package
  18. |section    8
  19. .include "fpsp.h"
  20. mns_inf:  .long 0xffff0000,0x00000000,0x00000000
  21. pls_inf:  .long 0x7fff0000,0x00000000,0x00000000
  22. nan:      .long 0x7fff0000,0xffffffff,0xffffffff
  23. huge:     .long 0x7ffe0000,0xffffffff,0xffffffff
  24. |xref   ovf_r_k
  25. |xref   unf_sub
  26. |xref   nrm_set
  27. .global      t_dz
  28. .global      t_dz2
  29. .global      t_operr
  30. .global      t_unfl
  31. .global      t_ovfl
  32. .global      t_ovfl2
  33. .global      t_inx2
  34. .global   t_frcinx
  35. .global   t_extdnrm
  36. .global   t_resdnrm
  37. .global   dst_nan
  38. .global   src_nan
  39. |
  40. | DZ exception
  41. |
  42. |
  43. | if dz trap disabled
  44. | store properly signed inf (use sign of etemp) into fp0
  45. | set FPSR exception status dz bit, condition code 
  46. | inf bit, and accrued dz bit
  47. | return
  48. | frestore the frame into the machine (done by unimp_hd)
  49. |
  50. | else dz trap enabled
  51. | set exception status bit & accrued bits in FPSR
  52. | set flag to disable sto_res from corrupting fp register
  53. | return
  54. | frestore the frame into the machine (done by unimp_hd)
  55. |
  56. | t_dz2 is used by monadic functions such as flogn (from do_func).
  57. | t_dz is used by monadic functions such as satanh (from the 
  58. | transcendental function).
  59. |
  60. t_dz2:
  61. bsetb #neg_bit,FPSR_CC(%a6) |set neg bit in FPSR
  62. fmovel #0,%FPSR |clr status bits (Z set)
  63. btstb #dz_bit,FPCR_ENABLE(%a6) |test FPCR for dz exc enabled
  64. bnes dz_ena_end
  65. bras m_inf |flogx always returns -inf
  66. t_dz:
  67. fmovel #0,%FPSR |clr status bits (Z set)
  68. btstb #dz_bit,FPCR_ENABLE(%a6) |test FPCR for dz exc enabled
  69. bnes dz_ena
  70. |
  71. | dz disabled
  72. |
  73. btstb #sign_bit,ETEMP_EX(%a6) |check sign for neg or pos
  74. beqs p_inf |branch if pos sign
  75. m_inf:
  76. fmovemx mns_inf,%fp0-%fp0 |load -inf
  77. bsetb #neg_bit,FPSR_CC(%a6) |set neg bit in FPSR
  78. bras set_fpsr
  79. p_inf:
  80. fmovemx pls_inf,%fp0-%fp0 |load +inf
  81. set_fpsr:
  82. orl #dzinf_mask,USER_FPSR(%a6) |set I,DZ,ADZ
  83. rts
  84. |
  85. | dz enabled
  86. |
  87. dz_ena:
  88. btstb #sign_bit,ETEMP_EX(%a6) |check sign for neg or pos
  89. beqs dz_ena_end
  90. bsetb #neg_bit,FPSR_CC(%a6) |set neg bit in FPSR
  91. dz_ena_end:
  92. orl #dzinf_mask,USER_FPSR(%a6) |set I,DZ,ADZ
  93. st STORE_FLG(%a6)
  94. rts
  95. |
  96. | OPERR exception
  97. |
  98. | if (operr trap disabled)
  99. | set FPSR exception status operr bit, condition code 
  100. | nan bit; Store default NAN into fp0
  101. | frestore the frame into the machine (done by unimp_hd)
  102. |
  103. | else (operr trap enabled)
  104. | set FPSR exception status operr bit, accrued operr bit
  105. | set flag to disable sto_res from corrupting fp register
  106. | frestore the frame into the machine (done by unimp_hd)
  107. |
  108. t_operr:
  109. orl #opnan_mask,USER_FPSR(%a6) |set NaN, OPERR, AIOP
  110. btstb #operr_bit,FPCR_ENABLE(%a6) |test FPCR for operr enabled
  111. bnes op_ena
  112. fmovemx nan,%fp0-%fp0 |load default nan
  113. rts
  114. op_ena:
  115. st STORE_FLG(%a6) |do not corrupt destination
  116. rts
  117. |
  118. | t_unfl --- UNFL exception
  119. |
  120. | This entry point is used by all routines requiring unfl, inex2,
  121. | aunfl, and ainex to be set on exit.
  122. |
  123. | On entry, a0 points to the exceptional operand.  The final exceptional
  124. | operand is built in FP_SCR1 and only the sign from the original operand
  125. | is used.
  126. |
  127. t_unfl:
  128. clrl FP_SCR1(%a6) |set exceptional operand to zero
  129. clrl FP_SCR1+4(%a6)
  130. clrl FP_SCR1+8(%a6)
  131. tstb (%a0) |extract sign from caller's exop
  132. bpls unfl_signok
  133. bset #sign_bit,FP_SCR1(%a6)
  134. unfl_signok:
  135. leal FP_SCR1(%a6),%a0
  136. orl #unfinx_mask,USER_FPSR(%a6)
  137. | ;set UNFL, INEX2, AUNFL, AINEX
  138. unfl_con:
  139. btstb #unfl_bit,FPCR_ENABLE(%a6)
  140. beqs unfl_dis
  141. unfl_ena:
  142. bfclr STAG(%a6){#5:#3} |clear wbtm66,wbtm1,wbtm0
  143. bsetb #wbtemp15_bit,WB_BYTE(%a6) |set wbtemp15
  144. bsetb #sticky_bit,STICKY(%a6) |set sticky bit
  145. bclrb #E1,E_BYTE(%a6)
  146. unfl_dis:
  147. bfextu FPCR_MODE(%a6){#0:#2},%d0 |get round precision
  148. bclrb #sign_bit,LOCAL_EX(%a0)
  149. sne LOCAL_SGN(%a0) |convert to internal ext format
  150. bsr unf_sub |returns IEEE result at a0
  151. | ;and sets FPSR_CC accordingly
  152. bfclr LOCAL_SGN(%a0){#0:#8} |convert back to IEEE ext format
  153. beqs unfl_fin
  154. bsetb #sign_bit,LOCAL_EX(%a0)
  155. bsetb #sign_bit,FP_SCR1(%a6) |set sign bit of exc operand
  156. unfl_fin:
  157. fmovemx (%a0),%fp0-%fp0 |store result in fp0
  158. rts
  159. |
  160. | t_ovfl2 --- OVFL exception (without inex2 returned)
  161. |
  162. | This entry is used by scale to force catastrophic overflow.  The
  163. | ovfl, aovfl, and ainex bits are set, but not the inex2 bit.
  164. |
  165. t_ovfl2:
  166. orl #ovfl_inx_mask,USER_FPSR(%a6)
  167. movel ETEMP(%a6),FP_SCR1(%a6)
  168. movel ETEMP_HI(%a6),FP_SCR1+4(%a6)
  169. movel ETEMP_LO(%a6),FP_SCR1+8(%a6)
  170. |
  171. | Check for single or double round precision.  If single, check if
  172. | the lower 40 bits of ETEMP are zero; if not, set inex2.  If double,
  173. | check if the lower 21 bits are zero; if not, set inex2.
  174. |
  175. moveb FPCR_MODE(%a6),%d0
  176. andib #0xc0,%d0
  177. beq t_work |if extended, finish ovfl processing
  178. cmpib #0x40,%d0 |test for single
  179. bnes t_dbl
  180. t_sgl:
  181. tstb ETEMP_LO(%a6)
  182. bnes t_setinx2
  183. movel ETEMP_HI(%a6),%d0
  184. andil #0xff,%d0 |look at only lower 8 bits
  185. bnes t_setinx2
  186. bra t_work
  187. t_dbl:
  188. movel ETEMP_LO(%a6),%d0
  189. andil #0x7ff,%d0 |look at only lower 11 bits
  190. beq t_work
  191. t_setinx2:
  192. orl #inex2_mask,USER_FPSR(%a6)
  193. bras t_work
  194. |
  195. | t_ovfl --- OVFL exception
  196. |
  197. |** Note: the exc operand is returned in ETEMP.
  198. |
  199. t_ovfl:
  200. orl #ovfinx_mask,USER_FPSR(%a6)
  201. t_work:
  202. btstb #ovfl_bit,FPCR_ENABLE(%a6) |test FPCR for ovfl enabled
  203. beqs ovf_dis
  204. ovf_ena:
  205. clrl FP_SCR1(%a6) |set exceptional operand
  206. clrl FP_SCR1+4(%a6)
  207. clrl FP_SCR1+8(%a6)
  208. bfclr STAG(%a6){#5:#3} |clear wbtm66,wbtm1,wbtm0
  209. bclrb #wbtemp15_bit,WB_BYTE(%a6) |clear wbtemp15
  210. bsetb #sticky_bit,STICKY(%a6) |set sticky bit
  211. bclrb #E1,E_BYTE(%a6)
  212. | ;fall through to disabled case
  213. | For disabled overflow call 'ovf_r_k'.  This routine loads the
  214. | correct result based on the rounding precision, destination
  215. | format, rounding mode and sign.
  216. |
  217. ovf_dis:
  218. bsr ovf_r_k |returns unsigned ETEMP_EX
  219. | ;and sets FPSR_CC accordingly.
  220. bfclr ETEMP_SGN(%a6){#0:#8} |fix sign
  221. beqs ovf_pos
  222. bsetb #sign_bit,ETEMP_EX(%a6)
  223. bsetb #sign_bit,FP_SCR1(%a6) |set exceptional operand sign
  224. ovf_pos:
  225. fmovemx ETEMP(%a6),%fp0-%fp0 |move the result to fp0
  226. rts
  227. |
  228. | INEX2 exception
  229. |
  230. | The inex2 and ainex bits are set.
  231. |
  232. t_inx2:
  233. orl #inx2a_mask,USER_FPSR(%a6) |set INEX2, AINEX
  234. rts
  235. |
  236. | Force Inex2
  237. |
  238. | This routine is called by the transcendental routines to force
  239. | the inex2 exception bits set in the FPSR.  If the underflow bit
  240. | is set, but the underflow trap was not taken, the aunfl bit in
  241. | the FPSR must be set.
  242. |
  243. t_frcinx:
  244. orl #inx2a_mask,USER_FPSR(%a6) |set INEX2, AINEX
  245. btstb #unfl_bit,FPSR_EXCEPT(%a6) |test for unfl bit set
  246. beqs no_uacc1 |if clear, do not set aunfl
  247. bsetb #aunfl_bit,FPSR_AEXCEPT(%a6)
  248. no_uacc1:
  249. rts
  250. |
  251. | DST_NAN
  252. |
  253. | Determine if the destination nan is signalling or non-signalling,
  254. | and set the FPSR bits accordingly.  See the MC68040 User's Manual 
  255. | section 3.2.2.5 NOT-A-NUMBERS.
  256. |
  257. dst_nan:
  258. btstb #sign_bit,FPTEMP_EX(%a6) |test sign of nan
  259. beqs dst_pos |if clr, it was positive
  260. bsetb #neg_bit,FPSR_CC(%a6) |set N bit
  261. dst_pos:
  262. btstb #signan_bit,FPTEMP_HI(%a6) |check if signalling 
  263. beqs dst_snan |branch if signalling
  264. fmovel %d1,%fpcr |restore user's rmode/prec
  265. fmovex FPTEMP(%a6),%fp0 |return the non-signalling nan
  266. |
  267. | Check the source nan.  If it is signalling, snan will be reported.
  268. |
  269. moveb STAG(%a6),%d0
  270. andib #0xe0,%d0
  271. cmpib #0x60,%d0
  272. bnes no_snan
  273. btstb #signan_bit,ETEMP_HI(%a6) |check if signalling 
  274. bnes no_snan
  275. orl #snaniop_mask,USER_FPSR(%a6) |set NAN, SNAN, AIOP
  276. no_snan:
  277. rts
  278. dst_snan:
  279. btstb #snan_bit,FPCR_ENABLE(%a6) |check if trap enabled 
  280. beqs dst_dis |branch if disabled
  281. orb #nan_tag,DTAG(%a6) |set up dtag for nan
  282. st STORE_FLG(%a6) |do not store a result
  283. orl #snaniop_mask,USER_FPSR(%a6) |set NAN, SNAN, AIOP
  284. rts
  285. dst_dis:
  286. bsetb #signan_bit,FPTEMP_HI(%a6) |set SNAN bit in sop 
  287. fmovel %d1,%fpcr |restore user's rmode/prec
  288. fmovex FPTEMP(%a6),%fp0 |load non-sign. nan 
  289. orl #snaniop_mask,USER_FPSR(%a6) |set NAN, SNAN, AIOP
  290. rts
  291. |
  292. | SRC_NAN
  293. |
  294. | Determine if the source nan is signalling or non-signalling,
  295. | and set the FPSR bits accordingly.  See the MC68040 User's Manual 
  296. | section 3.2.2.5 NOT-A-NUMBERS.
  297. |
  298. src_nan:
  299. btstb #sign_bit,ETEMP_EX(%a6) |test sign of nan
  300. beqs src_pos |if clr, it was positive
  301. bsetb #neg_bit,FPSR_CC(%a6) |set N bit
  302. src_pos:
  303. btstb #signan_bit,ETEMP_HI(%a6) |check if signalling 
  304. beqs src_snan |branch if signalling
  305. fmovel %d1,%fpcr |restore user's rmode/prec
  306. fmovex ETEMP(%a6),%fp0 |return the non-signalling nan
  307. rts
  308. src_snan:
  309. btstb #snan_bit,FPCR_ENABLE(%a6) |check if trap enabled 
  310. beqs src_dis |branch if disabled
  311. bsetb #signan_bit,ETEMP_HI(%a6) |set SNAN bit in sop 
  312. orb #norm_tag,DTAG(%a6) |set up dtag for norm
  313. orb #nan_tag,STAG(%a6) |set up stag for nan
  314. st STORE_FLG(%a6) |do not store a result
  315. orl #snaniop_mask,USER_FPSR(%a6) |set NAN, SNAN, AIOP
  316. rts
  317. src_dis:
  318. bsetb #signan_bit,ETEMP_HI(%a6) |set SNAN bit in sop 
  319. fmovel %d1,%fpcr |restore user's rmode/prec
  320. fmovex ETEMP(%a6),%fp0 |load non-sign. nan 
  321. orl #snaniop_mask,USER_FPSR(%a6) |set NAN, SNAN, AIOP
  322. rts
  323. |
  324. | For all functions that have a denormalized input and that f(x)=x,
  325. | this is the entry point
  326. |
  327. t_extdnrm:
  328. orl #unfinx_mask,USER_FPSR(%a6)
  329. | ;set UNFL, INEX2, AUNFL, AINEX
  330. bras xdnrm_con
  331. |
  332. | Entry point for scale with extended denorm.  The function does
  333. | not set inex2, aunfl, or ainex.  
  334. |
  335. t_resdnrm:
  336. orl #unfl_mask,USER_FPSR(%a6)
  337. xdnrm_con:
  338. btstb #unfl_bit,FPCR_ENABLE(%a6)
  339. beqs xdnrm_dis
  340. |
  341. | If exceptions are enabled, the additional task of setting up WBTEMP
  342. | is needed so that when the underflow exception handler is entered,
  343. | the user perceives no difference between what the 040 provides vs.
  344. | what the FPSP provides.
  345. |
  346. xdnrm_ena:
  347. movel %a0,-(%a7)
  348. movel LOCAL_EX(%a0),FP_SCR1(%a6)
  349. movel LOCAL_HI(%a0),FP_SCR1+4(%a6)
  350. movel LOCAL_LO(%a0),FP_SCR1+8(%a6)
  351. lea FP_SCR1(%a6),%a0
  352. bclrb #sign_bit,LOCAL_EX(%a0)
  353. sne LOCAL_SGN(%a0) |convert to internal ext format
  354. tstw LOCAL_EX(%a0) |check if input is denorm
  355. beqs xdnrm_dn |if so, skip nrm_set
  356. bsr nrm_set |normalize the result (exponent
  357. | ;will be negative
  358. xdnrm_dn:
  359. bclrb #sign_bit,LOCAL_EX(%a0) |take off false sign
  360. bfclr LOCAL_SGN(%a0){#0:#8} |change back to IEEE ext format
  361. beqs xdep
  362. bsetb #sign_bit,LOCAL_EX(%a0)
  363. xdep:
  364. bfclr STAG(%a6){#5:#3} |clear wbtm66,wbtm1,wbtm0
  365. bsetb #wbtemp15_bit,WB_BYTE(%a6) |set wbtemp15
  366. bclrb #sticky_bit,STICKY(%a6) |clear sticky bit
  367. bclrb #E1,E_BYTE(%a6)
  368. movel (%a7)+,%a0
  369. xdnrm_dis:
  370. bfextu FPCR_MODE(%a6){#0:#2},%d0 |get round precision
  371. bnes not_ext |if not round extended, store
  372. | ;IEEE defaults
  373. is_ext:
  374. btstb #sign_bit,LOCAL_EX(%a0)
  375. beqs xdnrm_store
  376. bsetb #neg_bit,FPSR_CC(%a6) |set N bit in FPSR_CC
  377. bras xdnrm_store
  378. not_ext:
  379. bclrb #sign_bit,LOCAL_EX(%a0)
  380. sne LOCAL_SGN(%a0) |convert to internal ext format
  381. bsr unf_sub |returns IEEE result pointed by
  382. | ;a0; sets FPSR_CC accordingly
  383. bfclr LOCAL_SGN(%a0){#0:#8} |convert back to IEEE ext format
  384. beqs xdnrm_store
  385. bsetb #sign_bit,LOCAL_EX(%a0)
  386. xdnrm_store:
  387. fmovemx (%a0),%fp0-%fp0 |store result in fp0
  388. rts
  389. |
  390. | This subroutine is used for dyadic operations that use an extended
  391. | denorm within the kernel. The approach used is to capture the frame,
  392. | fix/restore.
  393. |
  394. .global t_avoid_unsupp
  395. t_avoid_unsupp:
  396. link %a2,#-LOCAL_SIZE |so that a2 fpsp.h negative 
  397. | ;offsets may be used
  398. fsave -(%a7)
  399. tstb 1(%a7) |check if idle, exit if so
  400. beq idle_end
  401. btstb #E1,E_BYTE(%a2) |check for an E1 exception if
  402. | ;enabled, there is an unsupp
  403. beq end_avun |else, exit
  404. btstb #7,DTAG(%a2) |check for denorm destination
  405. beqs src_den |else, must be a source denorm
  406. |
  407. | handle destination denorm
  408. |
  409. lea FPTEMP(%a2),%a0
  410. btstb #sign_bit,LOCAL_EX(%a0)
  411. sne LOCAL_SGN(%a0) |convert to internal ext format
  412. bclrb #7,DTAG(%a2) |set DTAG to norm
  413. bsr nrm_set |normalize result, exponent
  414. | ;will become negative
  415. bclrb #sign_bit,LOCAL_EX(%a0) |get rid of fake sign
  416. bfclr LOCAL_SGN(%a0){#0:#8} |convert back to IEEE ext format
  417. beqs ck_src_den |check if source is also denorm
  418. bsetb #sign_bit,LOCAL_EX(%a0)
  419. ck_src_den:
  420. btstb #7,STAG(%a2)
  421. beqs end_avun
  422. src_den:
  423. lea ETEMP(%a2),%a0
  424. btstb #sign_bit,LOCAL_EX(%a0)
  425. sne LOCAL_SGN(%a0) |convert to internal ext format
  426. bclrb #7,STAG(%a2) |set STAG to norm
  427. bsr nrm_set |normalize result, exponent
  428. | ;will become negative
  429. bclrb #sign_bit,LOCAL_EX(%a0) |get rid of fake sign
  430. bfclr LOCAL_SGN(%a0){#0:#8} |convert back to IEEE ext format
  431. beqs den_com
  432. bsetb #sign_bit,LOCAL_EX(%a0)
  433. den_com:
  434. moveb #0xfe,CU_SAVEPC(%a2) |set continue frame
  435. clrw NMNEXC(%a2) |clear NMNEXC
  436. bclrb #E1,E_BYTE(%a2)
  437. | fmove.l %FPSR,FPSR_SHADOW(%a2)
  438. | bset.b #SFLAG,E_BYTE(%a2)
  439. | bset.b #XFLAG,T_BYTE(%a2)
  440. end_avun:
  441. frestore (%a7)+
  442. unlk %a2
  443. rts
  444. idle_end:
  445. addl #4,%a7
  446. unlk %a2
  447. rts
  448. |end