kernel_ex.S 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494
  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