kernel_ex.S 13 KB

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