/kern_oII/arch/m68k/ifpsp060/src/pfpsp.S

http://omnia2droid.googlecode.com/ · Assembly · 14745 lines · 13546 code · 1193 blank · 6 comment · 323 complexity · e3acf523978f068fa9c0039c051d6211 MD5 · raw file

Large files are truncated click here to view the full file

  1. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2. MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
  3. M68000 Hi-Performance Microprocessor Division
  4. M68060 Software Package
  5. Production Release P1.00 -- October 10, 1994
  6. M68060 Software Package Copyright Š 1993, 1994 Motorola Inc. All rights reserved.
  7. THE SOFTWARE is provided on an "AS IS" basis and without warranty.
  8. To the maximum extent permitted by applicable law,
  9. MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
  10. INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
  11. and any warranty against infringement with regard to the SOFTWARE
  12. (INCLUDING ANY MODIFIED VERSIONS THEREOF) and any accompanying written materials.
  13. To the maximum extent permitted by applicable law,
  14. IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
  15. (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS,
  16. BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS)
  17. ARISING OF THE USE OR INABILITY TO USE THE SOFTWARE.
  18. Motorola assumes no responsibility for the maintenance and support of the SOFTWARE.
  19. You are hereby granted a copyright license to use, modify, and distribute the SOFTWARE
  20. so long as this entire notice is retained without alteration in any modified and/or
  21. redistributed versions, and that such modified versions are clearly identified as such.
  22. No licenses are granted by implication, estoppel or otherwise under any patents
  23. or trademarks of Motorola, Inc.
  24. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  25. # freal.s:
  26. # This file is appended to the top of the 060FPSP package
  27. # and contains the entry points into the package. The user, in
  28. # effect, branches to one of the branch table entries located
  29. # after _060FPSP_TABLE.
  30. # Also, subroutine stubs exist in this file (_fpsp_done for
  31. # example) that are referenced by the FPSP package itself in order
  32. # to call a given routine. The stub routine actually performs the
  33. # callout. The FPSP code does a "bsr" to the stub routine. This
  34. # extra layer of hierarchy adds a slight performance penalty but
  35. # it makes the FPSP code easier to read and more mainatinable.
  36. #
  37. set _off_bsun, 0x00
  38. set _off_snan, 0x04
  39. set _off_operr, 0x08
  40. set _off_ovfl, 0x0c
  41. set _off_unfl, 0x10
  42. set _off_dz, 0x14
  43. set _off_inex, 0x18
  44. set _off_fline, 0x1c
  45. set _off_fpu_dis, 0x20
  46. set _off_trap, 0x24
  47. set _off_trace, 0x28
  48. set _off_access, 0x2c
  49. set _off_done, 0x30
  50. set _off_imr, 0x40
  51. set _off_dmr, 0x44
  52. set _off_dmw, 0x48
  53. set _off_irw, 0x4c
  54. set _off_irl, 0x50
  55. set _off_drb, 0x54
  56. set _off_drw, 0x58
  57. set _off_drl, 0x5c
  58. set _off_dwb, 0x60
  59. set _off_dww, 0x64
  60. set _off_dwl, 0x68
  61. _060FPSP_TABLE:
  62. ###############################################################
  63. # Here's the table of ENTRY POINTS for those linking the package.
  64. bra.l _fpsp_snan
  65. short 0x0000
  66. bra.l _fpsp_operr
  67. short 0x0000
  68. bra.l _fpsp_ovfl
  69. short 0x0000
  70. bra.l _fpsp_unfl
  71. short 0x0000
  72. bra.l _fpsp_dz
  73. short 0x0000
  74. bra.l _fpsp_inex
  75. short 0x0000
  76. bra.l _fpsp_fline
  77. short 0x0000
  78. bra.l _fpsp_unsupp
  79. short 0x0000
  80. bra.l _fpsp_effadd
  81. short 0x0000
  82. space 56
  83. ###############################################################
  84. global _fpsp_done
  85. _fpsp_done:
  86. mov.l %d0,-(%sp)
  87. mov.l (_060FPSP_TABLE-0x80+_off_done,%pc),%d0
  88. pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
  89. mov.l 0x4(%sp),%d0
  90. rtd &0x4
  91. global _real_ovfl
  92. _real_ovfl:
  93. mov.l %d0,-(%sp)
  94. mov.l (_060FPSP_TABLE-0x80+_off_ovfl,%pc),%d0
  95. pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
  96. mov.l 0x4(%sp),%d0
  97. rtd &0x4
  98. global _real_unfl
  99. _real_unfl:
  100. mov.l %d0,-(%sp)
  101. mov.l (_060FPSP_TABLE-0x80+_off_unfl,%pc),%d0
  102. pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
  103. mov.l 0x4(%sp),%d0
  104. rtd &0x4
  105. global _real_inex
  106. _real_inex:
  107. mov.l %d0,-(%sp)
  108. mov.l (_060FPSP_TABLE-0x80+_off_inex,%pc),%d0
  109. pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
  110. mov.l 0x4(%sp),%d0
  111. rtd &0x4
  112. global _real_bsun
  113. _real_bsun:
  114. mov.l %d0,-(%sp)
  115. mov.l (_060FPSP_TABLE-0x80+_off_bsun,%pc),%d0
  116. pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
  117. mov.l 0x4(%sp),%d0
  118. rtd &0x4
  119. global _real_operr
  120. _real_operr:
  121. mov.l %d0,-(%sp)
  122. mov.l (_060FPSP_TABLE-0x80+_off_operr,%pc),%d0
  123. pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
  124. mov.l 0x4(%sp),%d0
  125. rtd &0x4
  126. global _real_snan
  127. _real_snan:
  128. mov.l %d0,-(%sp)
  129. mov.l (_060FPSP_TABLE-0x80+_off_snan,%pc),%d0
  130. pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
  131. mov.l 0x4(%sp),%d0
  132. rtd &0x4
  133. global _real_dz
  134. _real_dz:
  135. mov.l %d0,-(%sp)
  136. mov.l (_060FPSP_TABLE-0x80+_off_dz,%pc),%d0
  137. pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
  138. mov.l 0x4(%sp),%d0
  139. rtd &0x4
  140. global _real_fline
  141. _real_fline:
  142. mov.l %d0,-(%sp)
  143. mov.l (_060FPSP_TABLE-0x80+_off_fline,%pc),%d0
  144. pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
  145. mov.l 0x4(%sp),%d0
  146. rtd &0x4
  147. global _real_fpu_disabled
  148. _real_fpu_disabled:
  149. mov.l %d0,-(%sp)
  150. mov.l (_060FPSP_TABLE-0x80+_off_fpu_dis,%pc),%d0
  151. pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
  152. mov.l 0x4(%sp),%d0
  153. rtd &0x4
  154. global _real_trap
  155. _real_trap:
  156. mov.l %d0,-(%sp)
  157. mov.l (_060FPSP_TABLE-0x80+_off_trap,%pc),%d0
  158. pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
  159. mov.l 0x4(%sp),%d0
  160. rtd &0x4
  161. global _real_trace
  162. _real_trace:
  163. mov.l %d0,-(%sp)
  164. mov.l (_060FPSP_TABLE-0x80+_off_trace,%pc),%d0
  165. pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
  166. mov.l 0x4(%sp),%d0
  167. rtd &0x4
  168. global _real_access
  169. _real_access:
  170. mov.l %d0,-(%sp)
  171. mov.l (_060FPSP_TABLE-0x80+_off_access,%pc),%d0
  172. pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
  173. mov.l 0x4(%sp),%d0
  174. rtd &0x4
  175. #######################################
  176. global _imem_read
  177. _imem_read:
  178. mov.l %d0,-(%sp)
  179. mov.l (_060FPSP_TABLE-0x80+_off_imr,%pc),%d0
  180. pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
  181. mov.l 0x4(%sp),%d0
  182. rtd &0x4
  183. global _dmem_read
  184. _dmem_read:
  185. mov.l %d0,-(%sp)
  186. mov.l (_060FPSP_TABLE-0x80+_off_dmr,%pc),%d0
  187. pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
  188. mov.l 0x4(%sp),%d0
  189. rtd &0x4
  190. global _dmem_write
  191. _dmem_write:
  192. mov.l %d0,-(%sp)
  193. mov.l (_060FPSP_TABLE-0x80+_off_dmw,%pc),%d0
  194. pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
  195. mov.l 0x4(%sp),%d0
  196. rtd &0x4
  197. global _imem_read_word
  198. _imem_read_word:
  199. mov.l %d0,-(%sp)
  200. mov.l (_060FPSP_TABLE-0x80+_off_irw,%pc),%d0
  201. pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
  202. mov.l 0x4(%sp),%d0
  203. rtd &0x4
  204. global _imem_read_long
  205. _imem_read_long:
  206. mov.l %d0,-(%sp)
  207. mov.l (_060FPSP_TABLE-0x80+_off_irl,%pc),%d0
  208. pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
  209. mov.l 0x4(%sp),%d0
  210. rtd &0x4
  211. global _dmem_read_byte
  212. _dmem_read_byte:
  213. mov.l %d0,-(%sp)
  214. mov.l (_060FPSP_TABLE-0x80+_off_drb,%pc),%d0
  215. pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
  216. mov.l 0x4(%sp),%d0
  217. rtd &0x4
  218. global _dmem_read_word
  219. _dmem_read_word:
  220. mov.l %d0,-(%sp)
  221. mov.l (_060FPSP_TABLE-0x80+_off_drw,%pc),%d0
  222. pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
  223. mov.l 0x4(%sp),%d0
  224. rtd &0x4
  225. global _dmem_read_long
  226. _dmem_read_long:
  227. mov.l %d0,-(%sp)
  228. mov.l (_060FPSP_TABLE-0x80+_off_drl,%pc),%d0
  229. pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
  230. mov.l 0x4(%sp),%d0
  231. rtd &0x4
  232. global _dmem_write_byte
  233. _dmem_write_byte:
  234. mov.l %d0,-(%sp)
  235. mov.l (_060FPSP_TABLE-0x80+_off_dwb,%pc),%d0
  236. pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
  237. mov.l 0x4(%sp),%d0
  238. rtd &0x4
  239. global _dmem_write_word
  240. _dmem_write_word:
  241. mov.l %d0,-(%sp)
  242. mov.l (_060FPSP_TABLE-0x80+_off_dww,%pc),%d0
  243. pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
  244. mov.l 0x4(%sp),%d0
  245. rtd &0x4
  246. global _dmem_write_long
  247. _dmem_write_long:
  248. mov.l %d0,-(%sp)
  249. mov.l (_060FPSP_TABLE-0x80+_off_dwl,%pc),%d0
  250. pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
  251. mov.l 0x4(%sp),%d0
  252. rtd &0x4
  253. #
  254. # This file contains a set of define statements for constants
  255. # in order to promote readability within the corecode itself.
  256. #
  257. set LOCAL_SIZE, 192 # stack frame size(bytes)
  258. set LV, -LOCAL_SIZE # stack offset
  259. set EXC_SR, 0x4 # stack status register
  260. set EXC_PC, 0x6 # stack pc
  261. set EXC_VOFF, 0xa # stacked vector offset
  262. set EXC_EA, 0xc # stacked <ea>
  263. set EXC_FP, 0x0 # frame pointer
  264. set EXC_AREGS, -68 # offset of all address regs
  265. set EXC_DREGS, -100 # offset of all data regs
  266. set EXC_FPREGS, -36 # offset of all fp regs
  267. set EXC_A7, EXC_AREGS+(7*4) # offset of saved a7
  268. set OLD_A7, EXC_AREGS+(6*4) # extra copy of saved a7
  269. set EXC_A6, EXC_AREGS+(6*4) # offset of saved a6
  270. set EXC_A5, EXC_AREGS+(5*4)
  271. set EXC_A4, EXC_AREGS+(4*4)
  272. set EXC_A3, EXC_AREGS+(3*4)
  273. set EXC_A2, EXC_AREGS+(2*4)
  274. set EXC_A1, EXC_AREGS+(1*4)
  275. set EXC_A0, EXC_AREGS+(0*4)
  276. set EXC_D7, EXC_DREGS+(7*4)
  277. set EXC_D6, EXC_DREGS+(6*4)
  278. set EXC_D5, EXC_DREGS+(5*4)
  279. set EXC_D4, EXC_DREGS+(4*4)
  280. set EXC_D3, EXC_DREGS+(3*4)
  281. set EXC_D2, EXC_DREGS+(2*4)
  282. set EXC_D1, EXC_DREGS+(1*4)
  283. set EXC_D0, EXC_DREGS+(0*4)
  284. set EXC_FP0, EXC_FPREGS+(0*12) # offset of saved fp0
  285. set EXC_FP1, EXC_FPREGS+(1*12) # offset of saved fp1
  286. set EXC_FP2, EXC_FPREGS+(2*12) # offset of saved fp2 (not used)
  287. set FP_SCR1, LV+80 # fp scratch 1
  288. set FP_SCR1_EX, FP_SCR1+0
  289. set FP_SCR1_SGN, FP_SCR1+2
  290. set FP_SCR1_HI, FP_SCR1+4
  291. set FP_SCR1_LO, FP_SCR1+8
  292. set FP_SCR0, LV+68 # fp scratch 0
  293. set FP_SCR0_EX, FP_SCR0+0
  294. set FP_SCR0_SGN, FP_SCR0+2
  295. set FP_SCR0_HI, FP_SCR0+4
  296. set FP_SCR0_LO, FP_SCR0+8
  297. set FP_DST, LV+56 # fp destination operand
  298. set FP_DST_EX, FP_DST+0
  299. set FP_DST_SGN, FP_DST+2
  300. set FP_DST_HI, FP_DST+4
  301. set FP_DST_LO, FP_DST+8
  302. set FP_SRC, LV+44 # fp source operand
  303. set FP_SRC_EX, FP_SRC+0
  304. set FP_SRC_SGN, FP_SRC+2
  305. set FP_SRC_HI, FP_SRC+4
  306. set FP_SRC_LO, FP_SRC+8
  307. set USER_FPIAR, LV+40 # FP instr address register
  308. set USER_FPSR, LV+36 # FP status register
  309. set FPSR_CC, USER_FPSR+0 # FPSR condition codes
  310. set FPSR_QBYTE, USER_FPSR+1 # FPSR qoutient byte
  311. set FPSR_EXCEPT, USER_FPSR+2 # FPSR exception status byte
  312. set FPSR_AEXCEPT, USER_FPSR+3 # FPSR accrued exception byte
  313. set USER_FPCR, LV+32 # FP control register
  314. set FPCR_ENABLE, USER_FPCR+2 # FPCR exception enable
  315. set FPCR_MODE, USER_FPCR+3 # FPCR rounding mode control
  316. set L_SCR3, LV+28 # integer scratch 3
  317. set L_SCR2, LV+24 # integer scratch 2
  318. set L_SCR1, LV+20 # integer scratch 1
  319. set STORE_FLG, LV+19 # flag: operand store (ie. not fcmp/ftst)
  320. set EXC_TEMP2, LV+24 # temporary space
  321. set EXC_TEMP, LV+16 # temporary space
  322. set DTAG, LV+15 # destination operand type
  323. set STAG, LV+14 # source operand type
  324. set SPCOND_FLG, LV+10 # flag: special case (see below)
  325. set EXC_CC, LV+8 # saved condition codes
  326. set EXC_EXTWPTR, LV+4 # saved current PC (active)
  327. set EXC_EXTWORD, LV+2 # saved extension word
  328. set EXC_CMDREG, LV+2 # saved extension word
  329. set EXC_OPWORD, LV+0 # saved operation word
  330. ################################
  331. # Helpful macros
  332. set FTEMP, 0 # offsets within an
  333. set FTEMP_EX, 0 # extended precision
  334. set FTEMP_SGN, 2 # value saved in memory.
  335. set FTEMP_HI, 4
  336. set FTEMP_LO, 8
  337. set FTEMP_GRS, 12
  338. set LOCAL, 0 # offsets within an
  339. set LOCAL_EX, 0 # extended precision
  340. set LOCAL_SGN, 2 # value saved in memory.
  341. set LOCAL_HI, 4
  342. set LOCAL_LO, 8
  343. set LOCAL_GRS, 12
  344. set DST, 0 # offsets within an
  345. set DST_EX, 0 # extended precision
  346. set DST_HI, 4 # value saved in memory.
  347. set DST_LO, 8
  348. set SRC, 0 # offsets within an
  349. set SRC_EX, 0 # extended precision
  350. set SRC_HI, 4 # value saved in memory.
  351. set SRC_LO, 8
  352. set SGL_LO, 0x3f81 # min sgl prec exponent
  353. set SGL_HI, 0x407e # max sgl prec exponent
  354. set DBL_LO, 0x3c01 # min dbl prec exponent
  355. set DBL_HI, 0x43fe # max dbl prec exponent
  356. set EXT_LO, 0x0 # min ext prec exponent
  357. set EXT_HI, 0x7ffe # max ext prec exponent
  358. set EXT_BIAS, 0x3fff # extended precision bias
  359. set SGL_BIAS, 0x007f # single precision bias
  360. set DBL_BIAS, 0x03ff # double precision bias
  361. set NORM, 0x00 # operand type for STAG/DTAG
  362. set ZERO, 0x01 # operand type for STAG/DTAG
  363. set INF, 0x02 # operand type for STAG/DTAG
  364. set QNAN, 0x03 # operand type for STAG/DTAG
  365. set DENORM, 0x04 # operand type for STAG/DTAG
  366. set SNAN, 0x05 # operand type for STAG/DTAG
  367. set UNNORM, 0x06 # operand type for STAG/DTAG
  368. ##################
  369. # FPSR/FPCR bits #
  370. ##################
  371. set neg_bit, 0x3 # negative result
  372. set z_bit, 0x2 # zero result
  373. set inf_bit, 0x1 # infinite result
  374. set nan_bit, 0x0 # NAN result
  375. set q_sn_bit, 0x7 # sign bit of quotient byte
  376. set bsun_bit, 7 # branch on unordered
  377. set snan_bit, 6 # signalling NAN
  378. set operr_bit, 5 # operand error
  379. set ovfl_bit, 4 # overflow
  380. set unfl_bit, 3 # underflow
  381. set dz_bit, 2 # divide by zero
  382. set inex2_bit, 1 # inexact result 2
  383. set inex1_bit, 0 # inexact result 1
  384. set aiop_bit, 7 # accrued inexact operation bit
  385. set aovfl_bit, 6 # accrued overflow bit
  386. set aunfl_bit, 5 # accrued underflow bit
  387. set adz_bit, 4 # accrued dz bit
  388. set ainex_bit, 3 # accrued inexact bit
  389. #############################
  390. # FPSR individual bit masks #
  391. #############################
  392. set neg_mask, 0x08000000 # negative bit mask (lw)
  393. set inf_mask, 0x02000000 # infinity bit mask (lw)
  394. set z_mask, 0x04000000 # zero bit mask (lw)
  395. set nan_mask, 0x01000000 # nan bit mask (lw)
  396. set neg_bmask, 0x08 # negative bit mask (byte)
  397. set inf_bmask, 0x02 # infinity bit mask (byte)
  398. set z_bmask, 0x04 # zero bit mask (byte)
  399. set nan_bmask, 0x01 # nan bit mask (byte)
  400. set bsun_mask, 0x00008000 # bsun exception mask
  401. set snan_mask, 0x00004000 # snan exception mask
  402. set operr_mask, 0x00002000 # operr exception mask
  403. set ovfl_mask, 0x00001000 # overflow exception mask
  404. set unfl_mask, 0x00000800 # underflow exception mask
  405. set dz_mask, 0x00000400 # dz exception mask
  406. set inex2_mask, 0x00000200 # inex2 exception mask
  407. set inex1_mask, 0x00000100 # inex1 exception mask
  408. set aiop_mask, 0x00000080 # accrued illegal operation
  409. set aovfl_mask, 0x00000040 # accrued overflow
  410. set aunfl_mask, 0x00000020 # accrued underflow
  411. set adz_mask, 0x00000010 # accrued divide by zero
  412. set ainex_mask, 0x00000008 # accrued inexact
  413. ######################################
  414. # FPSR combinations used in the FPSP #
  415. ######################################
  416. set dzinf_mask, inf_mask+dz_mask+adz_mask
  417. set opnan_mask, nan_mask+operr_mask+aiop_mask
  418. set nzi_mask, 0x01ffffff #clears N, Z, and I
  419. set unfinx_mask, unfl_mask+inex2_mask+aunfl_mask+ainex_mask
  420. set unf2inx_mask, unfl_mask+inex2_mask+ainex_mask
  421. set ovfinx_mask, ovfl_mask+inex2_mask+aovfl_mask+ainex_mask
  422. set inx1a_mask, inex1_mask+ainex_mask
  423. set inx2a_mask, inex2_mask+ainex_mask
  424. set snaniop_mask, nan_mask+snan_mask+aiop_mask
  425. set snaniop2_mask, snan_mask+aiop_mask
  426. set naniop_mask, nan_mask+aiop_mask
  427. set neginf_mask, neg_mask+inf_mask
  428. set infaiop_mask, inf_mask+aiop_mask
  429. set negz_mask, neg_mask+z_mask
  430. set opaop_mask, operr_mask+aiop_mask
  431. set unfl_inx_mask, unfl_mask+aunfl_mask+ainex_mask
  432. set ovfl_inx_mask, ovfl_mask+aovfl_mask+ainex_mask
  433. #########
  434. # misc. #
  435. #########
  436. set rnd_stky_bit, 29 # stky bit pos in longword
  437. set sign_bit, 0x7 # sign bit
  438. set signan_bit, 0x6 # signalling nan bit
  439. set sgl_thresh, 0x3f81 # minimum sgl exponent
  440. set dbl_thresh, 0x3c01 # minimum dbl exponent
  441. set x_mode, 0x0 # extended precision
  442. set s_mode, 0x4 # single precision
  443. set d_mode, 0x8 # double precision
  444. set rn_mode, 0x0 # round-to-nearest
  445. set rz_mode, 0x1 # round-to-zero
  446. set rm_mode, 0x2 # round-tp-minus-infinity
  447. set rp_mode, 0x3 # round-to-plus-infinity
  448. set mantissalen, 64 # length of mantissa in bits
  449. set BYTE, 1 # len(byte) == 1 byte
  450. set WORD, 2 # len(word) == 2 bytes
  451. set LONG, 4 # len(longword) == 2 bytes
  452. set BSUN_VEC, 0xc0 # bsun vector offset
  453. set INEX_VEC, 0xc4 # inexact vector offset
  454. set DZ_VEC, 0xc8 # dz vector offset
  455. set UNFL_VEC, 0xcc # unfl vector offset
  456. set OPERR_VEC, 0xd0 # operr vector offset
  457. set OVFL_VEC, 0xd4 # ovfl vector offset
  458. set SNAN_VEC, 0xd8 # snan vector offset
  459. ###########################
  460. # SPecial CONDition FLaGs #
  461. ###########################
  462. set ftrapcc_flg, 0x01 # flag bit: ftrapcc exception
  463. set fbsun_flg, 0x02 # flag bit: bsun exception
  464. set mia7_flg, 0x04 # flag bit: (a7)+ <ea>
  465. set mda7_flg, 0x08 # flag bit: -(a7) <ea>
  466. set fmovm_flg, 0x40 # flag bit: fmovm instruction
  467. set immed_flg, 0x80 # flag bit: &<data> <ea>
  468. set ftrapcc_bit, 0x0
  469. set fbsun_bit, 0x1
  470. set mia7_bit, 0x2
  471. set mda7_bit, 0x3
  472. set immed_bit, 0x7
  473. ##################################
  474. # TRANSCENDENTAL "LAST-OP" FLAGS #
  475. ##################################
  476. set FMUL_OP, 0x0 # fmul instr performed last
  477. set FDIV_OP, 0x1 # fdiv performed last
  478. set FADD_OP, 0x2 # fadd performed last
  479. set FMOV_OP, 0x3 # fmov performed last
  480. #############
  481. # CONSTANTS #
  482. #############
  483. T1: long 0x40C62D38,0xD3D64634 # 16381 LOG2 LEAD
  484. T2: long 0x3D6F90AE,0xB1E75CC7 # 16381 LOG2 TRAIL
  485. PI: long 0x40000000,0xC90FDAA2,0x2168C235,0x00000000
  486. PIBY2: long 0x3FFF0000,0xC90FDAA2,0x2168C235,0x00000000
  487. TWOBYPI:
  488. long 0x3FE45F30,0x6DC9C883
  489. #########################################################################
  490. # XDEF **************************************************************** #
  491. # _fpsp_ovfl(): 060FPSP entry point for FP Overflow exception. #
  492. # #
  493. # This handler should be the first code executed upon taking the #
  494. # FP Overflow exception in an operating system. #
  495. # #
  496. # XREF **************************************************************** #
  497. # _imem_read_long() - read instruction longword #
  498. # fix_skewed_ops() - adjust src operand in fsave frame #
  499. # set_tag_x() - determine optype of src/dst operands #
  500. # store_fpreg() - store opclass 0 or 2 result to FP regfile #
  501. # unnorm_fix() - change UNNORM operands to NORM or ZERO #
  502. # load_fpn2() - load dst operand from FP regfile #
  503. # fout() - emulate an opclass 3 instruction #
  504. # tbl_unsupp - add of table of emulation routines for opclass 0,2 #
  505. # _fpsp_done() - "callout" for 060FPSP exit (all work done!) #
  506. # _real_ovfl() - "callout" for Overflow exception enabled code #
  507. # _real_inex() - "callout" for Inexact exception enabled code #
  508. # _real_trace() - "callout" for Trace exception code #
  509. # #
  510. # INPUT *************************************************************** #
  511. # - The system stack contains the FP Ovfl exception stack frame #
  512. # - The fsave frame contains the source operand #
  513. # #
  514. # OUTPUT ************************************************************** #
  515. # Overflow Exception enabled: #
  516. # - The system stack is unchanged #
  517. # - The fsave frame contains the adjusted src op for opclass 0,2 #
  518. # Overflow Exception disabled: #
  519. # - The system stack is unchanged #
  520. # - The "exception present" flag in the fsave frame is cleared #
  521. # #
  522. # ALGORITHM *********************************************************** #
  523. # On the 060, if an FP overflow is present as the result of any #
  524. # instruction, the 060 will take an overflow exception whether the #
  525. # exception is enabled or disabled in the FPCR. For the disabled case, #
  526. # This handler emulates the instruction to determine what the correct #
  527. # default result should be for the operation. This default result is #
  528. # then stored in either the FP regfile, data regfile, or memory. #
  529. # Finally, the handler exits through the "callout" _fpsp_done() #
  530. # denoting that no exceptional conditions exist within the machine. #
  531. # If the exception is enabled, then this handler must create the #
  532. # exceptional operand and plave it in the fsave state frame, and store #
  533. # the default result (only if the instruction is opclass 3). For #
  534. # exceptions enabled, this handler must exit through the "callout" #
  535. # _real_ovfl() so that the operating system enabled overflow handler #
  536. # can handle this case. #
  537. # Two other conditions exist. First, if overflow was disabled #
  538. # but the inexact exception was enabled, this handler must exit #
  539. # through the "callout" _real_inex() regardless of whether the result #
  540. # was inexact. #
  541. # Also, in the case of an opclass three instruction where #
  542. # overflow was disabled and the trace exception was enabled, this #
  543. # handler must exit through the "callout" _real_trace(). #
  544. # #
  545. #########################################################################
  546. global _fpsp_ovfl
  547. _fpsp_ovfl:
  548. #$# sub.l &24,%sp # make room for src/dst
  549. link.w %a6,&-LOCAL_SIZE # init stack frame
  550. fsave FP_SRC(%a6) # grab the "busy" frame
  551. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  552. fmovm.l %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
  553. fmovm.x &0xc0,EXC_FPREGS(%a6) # save fp0-fp1 on stack
  554. # the FPIAR holds the "current PC" of the faulting instruction
  555. mov.l USER_FPIAR(%a6),EXC_EXTWPTR(%a6)
  556. mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
  557. addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
  558. bsr.l _imem_read_long # fetch the instruction words
  559. mov.l %d0,EXC_OPWORD(%a6)
  560. ##############################################################################
  561. btst &0x5,EXC_CMDREG(%a6) # is instr an fmove out?
  562. bne.w fovfl_out
  563. lea FP_SRC(%a6),%a0 # pass: ptr to src op
  564. bsr.l fix_skewed_ops # fix src op
  565. # since, I believe, only NORMs and DENORMs can come through here,
  566. # maybe we can avoid the subroutine call.
  567. lea FP_SRC(%a6),%a0 # pass: ptr to src op
  568. bsr.l set_tag_x # tag the operand type
  569. mov.b %d0,STAG(%a6) # maybe NORM,DENORM
  570. # bit five of the fp extension word separates the monadic and dyadic operations
  571. # that can pass through fpsp_ovfl(). remember that fcmp, ftst, and fsincos
  572. # will never take this exception.
  573. btst &0x5,1+EXC_CMDREG(%a6) # is operation monadic or dyadic?
  574. beq.b fovfl_extract # monadic
  575. bfextu EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg
  576. bsr.l load_fpn2 # load dst into FP_DST
  577. lea FP_DST(%a6),%a0 # pass: ptr to dst op
  578. bsr.l set_tag_x # tag the operand type
  579. cmpi.b %d0,&UNNORM # is operand an UNNORM?
  580. bne.b fovfl_op2_done # no
  581. bsr.l unnorm_fix # yes; convert to NORM,DENORM,or ZERO
  582. fovfl_op2_done:
  583. mov.b %d0,DTAG(%a6) # save dst optype tag
  584. fovfl_extract:
  585. #$# mov.l FP_SRC_EX(%a6),TRAP_SRCOP_EX(%a6)
  586. #$# mov.l FP_SRC_HI(%a6),TRAP_SRCOP_HI(%a6)
  587. #$# mov.l FP_SRC_LO(%a6),TRAP_SRCOP_LO(%a6)
  588. #$# mov.l FP_DST_EX(%a6),TRAP_DSTOP_EX(%a6)
  589. #$# mov.l FP_DST_HI(%a6),TRAP_DSTOP_HI(%a6)
  590. #$# mov.l FP_DST_LO(%a6),TRAP_DSTOP_LO(%a6)
  591. clr.l %d0
  592. mov.b FPCR_MODE(%a6),%d0 # pass rnd prec/mode
  593. mov.b 1+EXC_CMDREG(%a6),%d1
  594. andi.w &0x007f,%d1 # extract extension
  595. andi.l &0x00ff01ff,USER_FPSR(%a6) # zero all but accured field
  596. fmov.l &0x0,%fpcr # zero current control regs
  597. fmov.l &0x0,%fpsr
  598. lea FP_SRC(%a6),%a0
  599. lea FP_DST(%a6),%a1
  600. # maybe we can make these entry points ONLY the OVFL entry points of each routine.
  601. mov.l (tbl_unsupp.l,%pc,%d1.w*4),%d1 # fetch routine addr
  602. jsr (tbl_unsupp.l,%pc,%d1.l*1)
  603. # the operation has been emulated. the result is in fp0.
  604. # the EXOP, if an exception occurred, is in fp1.
  605. # we must save the default result regardless of whether
  606. # traps are enabled or disabled.
  607. bfextu EXC_CMDREG(%a6){&6:&3},%d0
  608. bsr.l store_fpreg
  609. # the exceptional possibilities we have left ourselves with are ONLY overflow
  610. # and inexact. and, the inexact is such that overflow occurred and was disabled
  611. # but inexact was enabled.
  612. btst &ovfl_bit,FPCR_ENABLE(%a6)
  613. bne.b fovfl_ovfl_on
  614. btst &inex2_bit,FPCR_ENABLE(%a6)
  615. bne.b fovfl_inex_on
  616. fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
  617. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
  618. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  619. unlk %a6
  620. #$# add.l &24,%sp
  621. bra.l _fpsp_done
  622. # overflow is enabled AND overflow, of course, occurred. so, we have the EXOP
  623. # in fp1. now, simply jump to _real_ovfl()!
  624. fovfl_ovfl_on:
  625. fmovm.x &0x40,FP_SRC(%a6) # save EXOP (fp1) to stack
  626. mov.w &0xe005,2+FP_SRC(%a6) # save exc status
  627. fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
  628. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
  629. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  630. frestore FP_SRC(%a6) # do this after fmovm,other f<op>s!
  631. unlk %a6
  632. bra.l _real_ovfl
  633. # overflow occurred but is disabled. meanwhile, inexact is enabled. therefore,
  634. # we must jump to real_inex().
  635. fovfl_inex_on:
  636. fmovm.x &0x40,FP_SRC(%a6) # save EXOP (fp1) to stack
  637. mov.b &0xc4,1+EXC_VOFF(%a6) # vector offset = 0xc4
  638. mov.w &0xe001,2+FP_SRC(%a6) # save exc status
  639. fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
  640. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
  641. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  642. frestore FP_SRC(%a6) # do this after fmovm,other f<op>s!
  643. unlk %a6
  644. bra.l _real_inex
  645. ########################################################################
  646. fovfl_out:
  647. #$# mov.l FP_SRC_EX(%a6),TRAP_SRCOP_EX(%a6)
  648. #$# mov.l FP_SRC_HI(%a6),TRAP_SRCOP_HI(%a6)
  649. #$# mov.l FP_SRC_LO(%a6),TRAP_SRCOP_LO(%a6)
  650. # the src operand is definitely a NORM(!), so tag it as such
  651. mov.b &NORM,STAG(%a6) # set src optype tag
  652. clr.l %d0
  653. mov.b FPCR_MODE(%a6),%d0 # pass rnd prec/mode
  654. and.l &0xffff00ff,USER_FPSR(%a6) # zero all but accured field
  655. fmov.l &0x0,%fpcr # zero current control regs
  656. fmov.l &0x0,%fpsr
  657. lea FP_SRC(%a6),%a0 # pass ptr to src operand
  658. bsr.l fout
  659. btst &ovfl_bit,FPCR_ENABLE(%a6)
  660. bne.w fovfl_ovfl_on
  661. btst &inex2_bit,FPCR_ENABLE(%a6)
  662. bne.w fovfl_inex_on
  663. fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
  664. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
  665. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  666. unlk %a6
  667. #$# add.l &24,%sp
  668. btst &0x7,(%sp) # is trace on?
  669. beq.l _fpsp_done # no
  670. fmov.l %fpiar,0x8(%sp) # "Current PC" is in FPIAR
  671. mov.w &0x2024,0x6(%sp) # stk fmt = 0x2; voff = 0x024
  672. bra.l _real_trace
  673. #########################################################################
  674. # XDEF **************************************************************** #
  675. # _fpsp_unfl(): 060FPSP entry point for FP Underflow exception. #
  676. # #
  677. # This handler should be the first code executed upon taking the #
  678. # FP Underflow exception in an operating system. #
  679. # #
  680. # XREF **************************************************************** #
  681. # _imem_read_long() - read instruction longword #
  682. # fix_skewed_ops() - adjust src operand in fsave frame #
  683. # set_tag_x() - determine optype of src/dst operands #
  684. # store_fpreg() - store opclass 0 or 2 result to FP regfile #
  685. # unnorm_fix() - change UNNORM operands to NORM or ZERO #
  686. # load_fpn2() - load dst operand from FP regfile #
  687. # fout() - emulate an opclass 3 instruction #
  688. # tbl_unsupp - add of table of emulation routines for opclass 0,2 #
  689. # _fpsp_done() - "callout" for 060FPSP exit (all work done!) #
  690. # _real_ovfl() - "callout" for Overflow exception enabled code #
  691. # _real_inex() - "callout" for Inexact exception enabled code #
  692. # _real_trace() - "callout" for Trace exception code #
  693. # #
  694. # INPUT *************************************************************** #
  695. # - The system stack contains the FP Unfl exception stack frame #
  696. # - The fsave frame contains the source operand #
  697. # #
  698. # OUTPUT ************************************************************** #
  699. # Underflow Exception enabled: #
  700. # - The system stack is unchanged #
  701. # - The fsave frame contains the adjusted src op for opclass 0,2 #
  702. # Underflow Exception disabled: #
  703. # - The system stack is unchanged #
  704. # - The "exception present" flag in the fsave frame is cleared #
  705. # #
  706. # ALGORITHM *********************************************************** #
  707. # On the 060, if an FP underflow is present as the result of any #
  708. # instruction, the 060 will take an underflow exception whether the #
  709. # exception is enabled or disabled in the FPCR. For the disabled case, #
  710. # This handler emulates the instruction to determine what the correct #
  711. # default result should be for the operation. This default result is #
  712. # then stored in either the FP regfile, data regfile, or memory. #
  713. # Finally, the handler exits through the "callout" _fpsp_done() #
  714. # denoting that no exceptional conditions exist within the machine. #
  715. # If the exception is enabled, then this handler must create the #
  716. # exceptional operand and plave it in the fsave state frame, and store #
  717. # the default result (only if the instruction is opclass 3). For #
  718. # exceptions enabled, this handler must exit through the "callout" #
  719. # _real_unfl() so that the operating system enabled overflow handler #
  720. # can handle this case. #
  721. # Two other conditions exist. First, if underflow was disabled #
  722. # but the inexact exception was enabled and the result was inexact, #
  723. # this handler must exit through the "callout" _real_inex(). #
  724. # was inexact. #
  725. # Also, in the case of an opclass three instruction where #
  726. # underflow was disabled and the trace exception was enabled, this #
  727. # handler must exit through the "callout" _real_trace(). #
  728. # #
  729. #########################################################################
  730. global _fpsp_unfl
  731. _fpsp_unfl:
  732. #$# sub.l &24,%sp # make room for src/dst
  733. link.w %a6,&-LOCAL_SIZE # init stack frame
  734. fsave FP_SRC(%a6) # grab the "busy" frame
  735. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  736. fmovm.l %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
  737. fmovm.x &0xc0,EXC_FPREGS(%a6) # save fp0-fp1 on stack
  738. # the FPIAR holds the "current PC" of the faulting instruction
  739. mov.l USER_FPIAR(%a6),EXC_EXTWPTR(%a6)
  740. mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
  741. addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
  742. bsr.l _imem_read_long # fetch the instruction words
  743. mov.l %d0,EXC_OPWORD(%a6)
  744. ##############################################################################
  745. btst &0x5,EXC_CMDREG(%a6) # is instr an fmove out?
  746. bne.w funfl_out
  747. lea FP_SRC(%a6),%a0 # pass: ptr to src op
  748. bsr.l fix_skewed_ops # fix src op
  749. lea FP_SRC(%a6),%a0 # pass: ptr to src op
  750. bsr.l set_tag_x # tag the operand type
  751. mov.b %d0,STAG(%a6) # maybe NORM,DENORM
  752. # bit five of the fp ext word separates the monadic and dyadic operations
  753. # that can pass through fpsp_unfl(). remember that fcmp, and ftst
  754. # will never take this exception.
  755. btst &0x5,1+EXC_CMDREG(%a6) # is op monadic or dyadic?
  756. beq.b funfl_extract # monadic
  757. # now, what's left that's not dyadic is fsincos. we can distinguish it
  758. # from all dyadics by the '0110xxx pattern
  759. btst &0x4,1+EXC_CMDREG(%a6) # is op an fsincos?
  760. bne.b funfl_extract # yes
  761. bfextu EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg
  762. bsr.l load_fpn2 # load dst into FP_DST
  763. lea FP_DST(%a6),%a0 # pass: ptr to dst op
  764. bsr.l set_tag_x # tag the operand type
  765. cmpi.b %d0,&UNNORM # is operand an UNNORM?
  766. bne.b funfl_op2_done # no
  767. bsr.l unnorm_fix # yes; convert to NORM,DENORM,or ZERO
  768. funfl_op2_done:
  769. mov.b %d0,DTAG(%a6) # save dst optype tag
  770. funfl_extract:
  771. #$# mov.l FP_SRC_EX(%a6),TRAP_SRCOP_EX(%a6)
  772. #$# mov.l FP_SRC_HI(%a6),TRAP_SRCOP_HI(%a6)
  773. #$# mov.l FP_SRC_LO(%a6),TRAP_SRCOP_LO(%a6)
  774. #$# mov.l FP_DST_EX(%a6),TRAP_DSTOP_EX(%a6)
  775. #$# mov.l FP_DST_HI(%a6),TRAP_DSTOP_HI(%a6)
  776. #$# mov.l FP_DST_LO(%a6),TRAP_DSTOP_LO(%a6)
  777. clr.l %d0
  778. mov.b FPCR_MODE(%a6),%d0 # pass rnd prec/mode
  779. mov.b 1+EXC_CMDREG(%a6),%d1
  780. andi.w &0x007f,%d1 # extract extension
  781. andi.l &0x00ff01ff,USER_FPSR(%a6)
  782. fmov.l &0x0,%fpcr # zero current control regs
  783. fmov.l &0x0,%fpsr
  784. lea FP_SRC(%a6),%a0
  785. lea FP_DST(%a6),%a1
  786. # maybe we can make these entry points ONLY the OVFL entry points of each routine.
  787. mov.l (tbl_unsupp.l,%pc,%d1.w*4),%d1 # fetch routine addr
  788. jsr (tbl_unsupp.l,%pc,%d1.l*1)
  789. bfextu EXC_CMDREG(%a6){&6:&3},%d0
  790. bsr.l store_fpreg
  791. # The `060 FPU multiplier hardware is such that if the result of a
  792. # multiply operation is the smallest possible normalized number
  793. # (0x00000000_80000000_00000000), then the machine will take an
  794. # underflow exception. Since this is incorrect, we need to check
  795. # if our emulation, after re-doing the operation, decided that
  796. # no underflow was called for. We do these checks only in
  797. # funfl_{unfl,inex}_on() because w/ both exceptions disabled, this
  798. # special case will simply exit gracefully with the correct result.
  799. # the exceptional possibilities we have left ourselves with are ONLY overflow
  800. # and inexact. and, the inexact is such that overflow occurred and was disabled
  801. # but inexact was enabled.
  802. btst &unfl_bit,FPCR_ENABLE(%a6)
  803. bne.b funfl_unfl_on
  804. funfl_chkinex:
  805. btst &inex2_bit,FPCR_ENABLE(%a6)
  806. bne.b funfl_inex_on
  807. funfl_exit:
  808. fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
  809. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
  810. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  811. unlk %a6
  812. #$# add.l &24,%sp
  813. bra.l _fpsp_done
  814. # overflow is enabled AND overflow, of course, occurred. so, we have the EXOP
  815. # in fp1 (don't forget to save fp0). what to do now?
  816. # well, we simply have to get to go to _real_unfl()!
  817. funfl_unfl_on:
  818. # The `060 FPU multiplier hardware is such that if the result of a
  819. # multiply operation is the smallest possible normalized number
  820. # (0x00000000_80000000_00000000), then the machine will take an
  821. # underflow exception. Since this is incorrect, we check here to see
  822. # if our emulation, after re-doing the operation, decided that
  823. # no underflow was called for.
  824. btst &unfl_bit,FPSR_EXCEPT(%a6)
  825. beq.w funfl_chkinex
  826. funfl_unfl_on2:
  827. fmovm.x &0x40,FP_SRC(%a6) # save EXOP (fp1) to stack
  828. mov.w &0xe003,2+FP_SRC(%a6) # save exc status
  829. fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
  830. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
  831. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  832. frestore FP_SRC(%a6) # do this after fmovm,other f<op>s!
  833. unlk %a6
  834. bra.l _real_unfl
  835. # undeflow occurred but is disabled. meanwhile, inexact is enabled. therefore,
  836. # we must jump to real_inex().
  837. funfl_inex_on:
  838. # The `060 FPU multiplier hardware is such that if the result of a
  839. # multiply operation is the smallest possible normalized number
  840. # (0x00000000_80000000_00000000), then the machine will take an
  841. # underflow exception.
  842. # But, whether bogus or not, if inexact is enabled AND it occurred,
  843. # then we have to branch to real_inex.
  844. btst &inex2_bit,FPSR_EXCEPT(%a6)
  845. beq.w funfl_exit
  846. funfl_inex_on2:
  847. fmovm.x &0x40,FP_SRC(%a6) # save EXOP to stack
  848. mov.b &0xc4,1+EXC_VOFF(%a6) # vector offset = 0xc4
  849. mov.w &0xe001,2+FP_SRC(%a6) # save exc status
  850. fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
  851. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
  852. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  853. frestore FP_SRC(%a6) # do this after fmovm,other f<op>s!
  854. unlk %a6
  855. bra.l _real_inex
  856. #######################################################################
  857. funfl_out:
  858. #$# mov.l FP_SRC_EX(%a6),TRAP_SRCOP_EX(%a6)
  859. #$# mov.l FP_SRC_HI(%a6),TRAP_SRCOP_HI(%a6)
  860. #$# mov.l FP_SRC_LO(%a6),TRAP_SRCOP_LO(%a6)
  861. # the src operand is definitely a NORM(!), so tag it as such
  862. mov.b &NORM,STAG(%a6) # set src optype tag
  863. clr.l %d0
  864. mov.b FPCR_MODE(%a6),%d0 # pass rnd prec/mode
  865. and.l &0xffff00ff,USER_FPSR(%a6) # zero all but accured field
  866. fmov.l &0x0,%fpcr # zero current control regs
  867. fmov.l &0x0,%fpsr
  868. lea FP_SRC(%a6),%a0 # pass ptr to src operand
  869. bsr.l fout
  870. btst &unfl_bit,FPCR_ENABLE(%a6)
  871. bne.w funfl_unfl_on2
  872. btst &inex2_bit,FPCR_ENABLE(%a6)
  873. bne.w funfl_inex_on2
  874. fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
  875. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
  876. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  877. unlk %a6
  878. #$# add.l &24,%sp
  879. btst &0x7,(%sp) # is trace on?
  880. beq.l _fpsp_done # no
  881. fmov.l %fpiar,0x8(%sp) # "Current PC" is in FPIAR
  882. mov.w &0x2024,0x6(%sp) # stk fmt = 0x2; voff = 0x024
  883. bra.l _real_trace
  884. #########################################################################
  885. # XDEF **************************************************************** #
  886. # _fpsp_unsupp(): 060FPSP entry point for FP "Unimplemented #
  887. # Data Type" exception. #
  888. # #
  889. # This handler should be the first code executed upon taking the #
  890. # FP Unimplemented Data Type exception in an operating system. #
  891. # #
  892. # XREF **************************************************************** #
  893. # _imem_read_{word,long}() - read instruction word/longword #
  894. # fix_skewed_ops() - adjust src operand in fsave frame #
  895. # set_tag_x() - determine optype of src/dst operands #
  896. # store_fpreg() - store opclass 0 or 2 result to FP regfile #
  897. # unnorm_fix() - change UNNORM operands to NORM or ZERO #
  898. # load_fpn2() - load dst operand from FP regfile #
  899. # load_fpn1() - load src operand from FP regfile #
  900. # fout() - emulate an opclass 3 instruction #
  901. # tbl_unsupp - add of table of emulation routines for opclass 0,2 #
  902. # _real_inex() - "callout" to operating system inexact handler #
  903. # _fpsp_done() - "callout" for exit; work all done #
  904. # _real_trace() - "callout" for Trace enabled exception #
  905. # funimp_skew() - adjust fsave src ops to "incorrect" value #
  906. # _real_snan() - "callout" for SNAN exception #
  907. # _real_operr() - "callout" for OPERR exception #
  908. # _real_ovfl() - "callout" for OVFL exception #
  909. # _real_unfl() - "callout" for UNFL exception #
  910. # get_packed() - fetch packed operand from memory #
  911. # #
  912. # INPUT *************************************************************** #
  913. # - The system stack contains the "Unimp Data Type" stk frame #
  914. # - The fsave frame contains the ssrc op (for UNNORM/DENORM) #
  915. # #
  916. # OUTPUT ************************************************************** #
  917. # If Inexact exception (opclass 3): #
  918. # - The system stack is changed to an Inexact exception stk frame #
  919. # If SNAN exception (opclass 3): #
  920. # - The system stack is changed to an SNAN exception stk frame #
  921. # If OPERR exception (opclass 3): #
  922. # - The system stack is changed to an OPERR exception stk frame #
  923. # If OVFL exception (opclass 3): #
  924. # - The system stack is changed to an OVFL exception stk frame #
  925. # If UNFL exception (opclass 3): #
  926. # - The system stack is changed to an UNFL exception stack frame #
  927. # If Trace exception enabled: #
  928. # - The system stack is changed to a Trace exception stack frame #
  929. # Else: (normal case) #
  930. # - Correct result has been stored as appropriate #
  931. # #
  932. # ALGORITHM *********************************************************** #
  933. # Two main instruction types can enter here: (1) DENORM or UNNORM #
  934. # unimplemented data types. These can be either opclass 0,2 or 3 #
  935. # instructions, and (2) PACKED unimplemented data format instructions #
  936. # also of opclasses 0,2, or 3. #
  937. # For UNNORM/DENORM opclass 0 and 2, the handler fetches the src #
  938. # operand from the fsave state frame and the dst operand (if dyadic) #
  939. # from the FP register file. The instruction is then emulated by #
  940. # choosing an emulation routine from a table of routines indexed by #
  941. # instruction type. Once the instruction has been emulated and result #
  942. # saved, then we check to see if any enabled exceptions resulted from #
  943. # instruction emulation. If none, then we exit through the "callout" #
  944. # _fpsp_done(). If there is an enabled FP exception, then we insert #
  945. # this exception into the FPU in the fsave state frame and then exit #
  946. # through _fpsp_done(). #
  947. # PACKED opclass 0 and 2 is similar in how the instruction is #
  948. # emulated and exceptions handled. The differences occur in how the #
  949. # handler loads the packed op (by calling get_packed() routine) and #
  950. # by the fact that a Trace exception could be pending for PACKED ops. #
  951. # If a Trace exception is pending, then the current exception stack #
  952. # frame is changed to a Trace exception stack frame and an exit is #
  953. # made through _real_trace(). #
  954. # For UNNORM/DENORM opclass 3, the actual move out to memory is #
  955. # performed by calling the routine fout(). If no exception should occur #
  956. # as the result of emulation, then an exit either occurs through #
  957. # _fpsp_done() or through _real_trace() if a Trace exception is pending #
  958. # (a Trace stack frame must be created here, too). If an FP exception #
  959. # should occur, then we must create an exception stack frame of that #
  960. # type and jump to either _real_snan(), _real_operr(), _real_inex(), #
  961. # _real_unfl(), or _real_ovfl() as appropriate. PACKED opclass 3 #
  962. # emulation is performed in a similar manner. #
  963. # #
  964. #########################################################################
  965. #
  966. # (1) DENORM and UNNORM (unimplemented) data types:
  967. #
  968. # post-instruction
  969. # *****************
  970. # * EA *
  971. # pre-instruction * *
  972. # ***************** *****************
  973. # * 0x0 * 0x0dc * * 0x3 * 0x0dc *
  974. # ***************** *****************
  975. # * Next * * Next *
  976. # * PC * * PC *
  977. # ***************** *****************
  978. # * SR * * SR *
  979. # ***************** *****************
  980. #
  981. # (2) PACKED format (unsupported) opclasses two and three:
  982. # *****************
  983. # * EA *
  984. # * *
  985. # *****************
  986. # * 0x2 * 0x0dc *
  987. # *****************
  988. # * Next *
  989. # * PC *
  990. # *****************
  991. # * SR *
  992. # *****************
  993. #
  994. global _fpsp_unsupp
  995. _fpsp_unsupp:
  996. link.w %a6,&-LOCAL_SIZE # init stack frame
  997. fsave FP_SRC(%a6) # save fp state
  998. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  999. fmovm.l %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
  1000. fmovm.x &0xc0,EXC_FPREGS(%a6) # save fp0-fp1 on stack
  1001. btst &0x5,EXC_SR(%a6) # user or supervisor mode?
  1002. bne.b fu_s
  1003. fu_u:
  1004. mov.l %usp,%a0 # fetch user stack pointer
  1005. mov.l %a0,EXC_A7(%a6) # save on stack
  1006. bra.b fu_cont
  1007. # if the exception is an opclass zero or two unimplemented data type
  1008. # exception, then the a7' calculated here is wrong since it doesn't
  1009. # stack an ea. however, we don't need an a7' for this case anyways.
  1010. fu_s:
  1011. lea 0x4+EXC_EA(%a6),%a0 # load old a7'
  1012. mov.l %a0,EXC_A7(%a6) # save on stack
  1013. fu_cont:
  1014. # the FPIAR holds the "current PC" of the faulting instruction
  1015. # the FPIAR should be set correctly for ALL exceptions passing through
  1016. # this point.
  1017. mov.l USER_FPIAR(%a6),EXC_EXTWPTR(%a6)
  1018. mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
  1019. addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
  1020. bsr.l _imem_read_long # fetch the instruction words
  1021. mov.l %d0,EXC_OPWORD(%a6) # store OPWORD and EXTWORD
  1022. ############################
  1023. clr.b SPCOND_FLG(%a6) # clear special condition flag
  1024. # Separate opclass three (fpn-to-mem) ops since they have a different
  1025. # stack frame and protocol.
  1026. btst &0x5,EXC_CMDREG(%a6) # is it an fmove out?
  1027. bne.w fu_out # yes
  1028. # Separate packed opclass two instructions.
  1029. bfextu EXC_CMDREG(%a6){&0:&6},%d0
  1030. cmpi.b %d0,&0x13
  1031. beq.w fu_in_pack
  1032. # I'm not sure at this point what FPSR bits are valid for this instruction.
  1033. # so, since the emulation routines re-create them anyways, zero exception field
  1034. andi.l &0x00ff00ff,USER_FPSR(%a6) # zero exception field
  1035. fmov.l &0x0,%fpcr # zero current control regs
  1036. fmov.l &0x0,%fpsr
  1037. # Opclass two w/ memory-to-fpn operation will have an incorrect extended
  1038. # precision format if the src format was single or double and the
  1039. # source data type was an INF, NAN, DENORM, or UNNORM
  1040. lea FP_SRC(%a6),%a0 # pass ptr to input
  1041. bsr.l fix_skewed_ops
  1042. # we don't know whether the src operand or the dst operand (or both) is the
  1043. # UNNORM or DENORM. call the function that tags the operand type. if the
  1044. # input is an UNNORM, then convert it to a NORM, DENORM, or ZERO.
  1045. lea FP_SRC(%a6),%a0 # pass: ptr to src op
  1046. bsr.l set_tag_x # tag the operand type
  1047. cmpi.b %d0,&UNNORM # is operand an UNNORM?
  1048. bne.b fu_op2 # no
  1049. bsr.l unnorm_fix # yes; convert to NORM,DENORM,or ZERO
  1050. fu_op2:
  1051. mov.b %d0,STAG(%a6) # save src optype tag
  1052. bfextu EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg
  1053. # bit five of the fp extension word separates the monadic and dyadic operations
  1054. # at this point
  1055. btst &0x5,1+EXC_CMDREG(%a6) # is operation monadic or dyadic?
  1056. beq.b fu_extract # monadic
  1057. cmpi.b 1+EXC_CMDREG(%a6),&0x3a # is operation an ftst?
  1058. beq.b fu_extract # yes, so it's monadic, too
  1059. bsr.l load_fpn2 # load dst into FP_DST
  1060. lea FP_DST(%a6),%a0 # pass: ptr to dst op
  1061. bsr.l set_tag_x # tag the operand type
  1062. cmpi.b %d0,&UNNORM # is operand an UNNORM?
  1063. bne.b fu_op2_done # no
  1064. bsr.l unnorm_fix # yes; convert to NORM,DENORM,or ZERO
  1065. fu_op2_done:
  1066. mov.b %d0,DTAG(%a6) # save dst optype tag
  1067. fu_extract:
  1068. clr.l %d0
  1069. mov.b FPCR_MODE(%a6),%d0 # fetch rnd mode/prec
  1070. bfextu 1+EXC_CMDREG(%a6){&1:&7},%d1 # extract extension
  1071. lea FP_SRC(%a6),%a0
  1072. lea FP_DST(%a6),%a1
  1073. mov.l (tbl_unsupp.l,%pc,%d1.l*4),%d1 # fetch routine addr
  1074. jsr (tbl_unsupp.l,%pc,%d1.l*1)
  1075. #
  1076. # Exceptions in order of precedence:
  1077. # BSUN : none
  1078. # SNAN : all dyadic ops
  1079. # OPERR : fsqrt(-NORM)
  1080. # OVFL : all except ftst,fcmp
  1081. # UNFL : all except ftst,fcmp
  1082. # DZ : fdiv
  1083. # INEX2 : all except ftst,fcmp
  1084. # INEX1 : none (packed doesn't go through here)
  1085. #
  1086. # we determine the highest priority exception(if any) set by the
  1087. # emulation routine that has also been enabled by the user.
  1088. mov.b FPCR_ENABLE(%a6),%d0 # fetch exceptions set
  1089. bne.b fu_in_ena # some are enabled
  1090. fu_in_cont:
  1091. # fcmp and ftst do not store any result.
  1092. mov.b 1+EXC_CMDREG(%a6),%d0 # fetch extension
  1093. andi.b &0x38,%d0 # extract bits 3-5
  1094. cmpi.b %d0,&0x38 # is instr fcmp or ftst?
  1095. beq.b fu_in_exit # yes
  1096. bfextu EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg
  1097. bsr.l store_fpreg # store the result
  1098. fu_in_exit:
  1099. fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
  1100. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
  1101. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  1102. unlk %a6
  1103. bra.l _fpsp_done
  1104. fu_in_ena:
  1105. and.b FPSR_EXCEPT(%a6),%d0 # keep only ones enabled
  1106. bfffo %d0{&24:&8},%d0 # find highest priority exception
  1107. bne.b fu_in_exc # there is at least one set
  1108. #
  1109. # No exceptions occurred that were also enabled. Now:
  1110. #
  1111. # if (OVFL && ovfl_disabled && inexact_enabled) {
  1112. # branch to _real_inex() (even if the result was exact!);
  1113. # } else {
  1114. # save the result in the proper fp reg (unless the op is fcmp or ftst);
  1115. # return;
  1116. # }
  1117. #
  1118. btst &ovfl_bit,FPSR_EXCEPT(%a6) # was overflow set?
  1119. beq.b fu_in_cont # no
  1120. fu_in_ovflchk:
  1121. btst &inex2_bit,FPCR_ENABLE(%a6) # was inexact enabled?
  1122. beq.b fu_in_cont # no
  1123. bra.w fu_in_exc_ovfl # go insert overflow frame
  1124. #
  1125. # An exception occurred and that exception was enabled:
  1126. #
  1127. # shift enabled exception field into lo byte of d0;
  1128. # if (((INEX2 || INEX1) && inex_enabled && OVFL && ovfl_disabled) ||
  1129. # ((INEX2 || INEX1) && inex_enabled && UNFL && unfl_disabled)) {
  1130. # /*
  1131. # * this is the case where we must call _real_inex() now or else
  1132. # * there will be no other way to pass it the exceptional operand
  1133. # */
  1134. # call _real_inex();
  1135. # } else {
  1136. # restore exc state (SNAN||OPERR||OVFL||UNFL||DZ||INEX) into the FPU;
  1137. # }
  1138. #
  1139. fu_in_exc:
  1140. subi.l &24,%d0 # fix offset to be 0-8
  1141. cmpi.b %d0,&0x6 # is exception INEX? (6)
  1142. bne.b fu_in_exc_exit # no
  1143. # the enabled exception was inexact
  1144. btst &unfl_bit,FPSR_EXCEPT(%a6) # did disabled underflow occur?
  1145. bne.w fu_in_exc_unfl # yes
  1146. btst &ovfl_bit,FPSR_EXCEPT(%a6) # did disabled overflow occur?
  1147. bne.w fu_in_exc_ovfl # yes
  1148. # here, we insert the correct fsave status value into the fsave frame for the
  1149. # corresponding exception. the operand in the fsave frame should be the original
  1150. # src operand.
  1151. fu_in_exc_exit:
  1152. mov.l %d0,-(%sp) # save d0
  1153. bsr.l funimp_skew # skew sgl or dbl inputs
  1154. mov.l (%sp)+,%d0 # restore d0
  1155. mov.w (tbl_except.b,%pc,%d0.w*2),2+FP_SRC(%a6) # create exc status
  1156. fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
  1157. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
  1158. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  1159. frestore FP_SRC(%a6) # restore src op
  1160. unlk %a6
  1161. bra.l _fpsp_done
  1162. tbl_except:
  1163. short 0xe000,0xe006,0xe004,0xe005
  1164. short 0xe003,0xe002,0xe001,0xe001
  1165. fu_in_exc_unfl:
  1166. mov.w &0x4,%d0
  1167. bra.b fu_in_exc_exit
  1168. fu_in_exc_ovfl:
  1169. mov.w &0x03,%d0
  1170. bra.b fu_in_exc_exit
  1171. # If the input operand to this operation was opclass two and a single
  1172. # or double precision denorm, inf, or nan, the operand needs to be
  1173. # "corrected" in order to have the proper equivalent extended precision
  1174. # number.
  1175. global fix_skewed_ops
  1176. fix_skewed_ops:
  1177. bfextu EXC_CMDREG(%a6){&0:&6},%d0 # extract opclass,src fmt
  1178. cmpi.b %d0,&0x11 # is class = 2 & fmt = sgl?
  1179. beq.b fso_sgl # yes
  1180. cmpi.b %d0,&0x15 # is class = 2 & fmt = dbl?
  1181. beq.b fso_dbl # yes
  1182. rts # no
  1183. fso_sgl:
  1184. mov.w LOCAL_EX(%a0),%d0 # fetch src exponent
  1185. andi.w &0x7fff,%d0 # strip sign
  1186. cmpi.w %d0,&0x3f80 # is |exp| == $3f80?
  1187. beq.b fso_sgl_dnrm_zero # yes
  1188. cmpi.w %d0,&0x407f # no; is |exp| == $407f?
  1189. beq.b fso_infnan # yes
  1190. rts # no
  1191. fso_sgl_dnrm_zero:
  1192. andi.l &0x7fffffff,LOCAL_HI(%a0) # clear j-bit
  1193. beq.b fso_zero # it's a skewed zero
  1194. fso_sgl_dnrm:
  1195. # here, we count on norm not to alter a0...
  1196. bsr.l norm # normalize mantissa
  1197. neg.w %d0 # -shft amt
  1198. addi.w &0x3f81,%d0 # adjust new exponent
  1199. andi.w &0x8000,LOCAL_EX(%a0) # clear old exponent
  1200. or.w %d0,LOCAL_EX(%a0) # insert new exponent
  1201. rts
  1202. fso_zero:
  1203. andi.w &0x8000,LOCAL_EX(%a0) # clear bogus exponent
  1204. rts
  1205. fso_infnan:
  1206. andi.b &0x7f,LOCAL_HI(%a0) # clear j-bit
  1207. ori.w &0x7fff,LOCAL_EX(%a0) # make exponent = $7fff
  1208. rts
  1209. fso_dbl:
  1210. mov.w LOCAL_EX(%a0),%d0 # fetch src exponent
  1211. andi.w &0x7fff,%d0 # strip sign
  1212. cmpi.w %d0,&0x3c00 # is |exp| == $3c00?
  1213. beq.b fso_dbl_dnrm_zero # yes
  1214. cmpi.w %d0,&0x43ff # no; is |exp| == $43ff?
  1215. beq.b fso_infnan # yes
  1216. rts # no
  1217. fso_dbl_dnrm_zero:
  1218. andi.l &0x7fffffff,LOCAL_HI(%a0) # clear j-bit
  1219. bne.b fso_dbl_dnrm # it's a skewed denorm
  1220. tst.l LOCAL_LO(%a0) # is it a zero?
  1221. beq.b fso_zero # yes
  1222. fso_dbl_dnrm:
  1223. # here, we count on norm not to alter a0...
  1224. bsr.l norm # normalize mantissa
  1225. neg.w %d0 # -shft amt
  1226. addi.w &0x3c01,%d0 # adjust new exponent
  1227. andi.w &0x8000,LOCAL_EX(%a0) # clear old exponent
  1228. or.w %d0,LOCAL_EX(%a0) # insert new exponent
  1229. rts
  1230. #################################################################
  1231. # fmove out took an unimplemented data type exception.
  1232. # the src operand is in FP_SRC. Call _fout() to write out the result and
  1233. # to determine which exceptions, if any, to take.
  1234. fu_out:
  1235. # Separate packed move outs from the UNNORM and DENORM move outs.
  1236. bfextu EXC_CMDREG(%a6){&3:&3},%d0
  1237. cmpi.b %d0,&0x3
  1238. beq.w fu_out_pack
  1239. cmpi.b %d0,&0x7
  1240. beq.w fu_out_pack
  1241. # I'm not s…