PageRenderTime 135ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 2ms

/arch/m68k/ifpsp060/src/fplsp.S

https://bitbucket.org/cresqo/cm7-p500-kernel
Assembly | 10980 lines | 9796 code | 1184 blank | 0 comment | 71 complexity | c8c88f2e1c605f8e83e2ae51cdf83207 MD5 | raw file
Possible License(s): LGPL-2.0, AGPL-1.0, GPL-2.0
  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. #
  26. # lfptop.s:
  27. # This file is appended to the top of the 060ILSP package
  28. # and contains the entry points into the package. The user, in
  29. # effect, branches to one of the branch table entries located here.
  30. #
  31. bra.l _facoss_
  32. short 0x0000
  33. bra.l _facosd_
  34. short 0x0000
  35. bra.l _facosx_
  36. short 0x0000
  37. bra.l _fasins_
  38. short 0x0000
  39. bra.l _fasind_
  40. short 0x0000
  41. bra.l _fasinx_
  42. short 0x0000
  43. bra.l _fatans_
  44. short 0x0000
  45. bra.l _fatand_
  46. short 0x0000
  47. bra.l _fatanx_
  48. short 0x0000
  49. bra.l _fatanhs_
  50. short 0x0000
  51. bra.l _fatanhd_
  52. short 0x0000
  53. bra.l _fatanhx_
  54. short 0x0000
  55. bra.l _fcoss_
  56. short 0x0000
  57. bra.l _fcosd_
  58. short 0x0000
  59. bra.l _fcosx_
  60. short 0x0000
  61. bra.l _fcoshs_
  62. short 0x0000
  63. bra.l _fcoshd_
  64. short 0x0000
  65. bra.l _fcoshx_
  66. short 0x0000
  67. bra.l _fetoxs_
  68. short 0x0000
  69. bra.l _fetoxd_
  70. short 0x0000
  71. bra.l _fetoxx_
  72. short 0x0000
  73. bra.l _fetoxm1s_
  74. short 0x0000
  75. bra.l _fetoxm1d_
  76. short 0x0000
  77. bra.l _fetoxm1x_
  78. short 0x0000
  79. bra.l _fgetexps_
  80. short 0x0000
  81. bra.l _fgetexpd_
  82. short 0x0000
  83. bra.l _fgetexpx_
  84. short 0x0000
  85. bra.l _fgetmans_
  86. short 0x0000
  87. bra.l _fgetmand_
  88. short 0x0000
  89. bra.l _fgetmanx_
  90. short 0x0000
  91. bra.l _flog10s_
  92. short 0x0000
  93. bra.l _flog10d_
  94. short 0x0000
  95. bra.l _flog10x_
  96. short 0x0000
  97. bra.l _flog2s_
  98. short 0x0000
  99. bra.l _flog2d_
  100. short 0x0000
  101. bra.l _flog2x_
  102. short 0x0000
  103. bra.l _flogns_
  104. short 0x0000
  105. bra.l _flognd_
  106. short 0x0000
  107. bra.l _flognx_
  108. short 0x0000
  109. bra.l _flognp1s_
  110. short 0x0000
  111. bra.l _flognp1d_
  112. short 0x0000
  113. bra.l _flognp1x_
  114. short 0x0000
  115. bra.l _fmods_
  116. short 0x0000
  117. bra.l _fmodd_
  118. short 0x0000
  119. bra.l _fmodx_
  120. short 0x0000
  121. bra.l _frems_
  122. short 0x0000
  123. bra.l _fremd_
  124. short 0x0000
  125. bra.l _fremx_
  126. short 0x0000
  127. bra.l _fscales_
  128. short 0x0000
  129. bra.l _fscaled_
  130. short 0x0000
  131. bra.l _fscalex_
  132. short 0x0000
  133. bra.l _fsins_
  134. short 0x0000
  135. bra.l _fsind_
  136. short 0x0000
  137. bra.l _fsinx_
  138. short 0x0000
  139. bra.l _fsincoss_
  140. short 0x0000
  141. bra.l _fsincosd_
  142. short 0x0000
  143. bra.l _fsincosx_
  144. short 0x0000
  145. bra.l _fsinhs_
  146. short 0x0000
  147. bra.l _fsinhd_
  148. short 0x0000
  149. bra.l _fsinhx_
  150. short 0x0000
  151. bra.l _ftans_
  152. short 0x0000
  153. bra.l _ftand_
  154. short 0x0000
  155. bra.l _ftanx_
  156. short 0x0000
  157. bra.l _ftanhs_
  158. short 0x0000
  159. bra.l _ftanhd_
  160. short 0x0000
  161. bra.l _ftanhx_
  162. short 0x0000
  163. bra.l _ftentoxs_
  164. short 0x0000
  165. bra.l _ftentoxd_
  166. short 0x0000
  167. bra.l _ftentoxx_
  168. short 0x0000
  169. bra.l _ftwotoxs_
  170. short 0x0000
  171. bra.l _ftwotoxd_
  172. short 0x0000
  173. bra.l _ftwotoxx_
  174. short 0x0000
  175. bra.l _fabss_
  176. short 0x0000
  177. bra.l _fabsd_
  178. short 0x0000
  179. bra.l _fabsx_
  180. short 0x0000
  181. bra.l _fadds_
  182. short 0x0000
  183. bra.l _faddd_
  184. short 0x0000
  185. bra.l _faddx_
  186. short 0x0000
  187. bra.l _fdivs_
  188. short 0x0000
  189. bra.l _fdivd_
  190. short 0x0000
  191. bra.l _fdivx_
  192. short 0x0000
  193. bra.l _fints_
  194. short 0x0000
  195. bra.l _fintd_
  196. short 0x0000
  197. bra.l _fintx_
  198. short 0x0000
  199. bra.l _fintrzs_
  200. short 0x0000
  201. bra.l _fintrzd_
  202. short 0x0000
  203. bra.l _fintrzx_
  204. short 0x0000
  205. bra.l _fmuls_
  206. short 0x0000
  207. bra.l _fmuld_
  208. short 0x0000
  209. bra.l _fmulx_
  210. short 0x0000
  211. bra.l _fnegs_
  212. short 0x0000
  213. bra.l _fnegd_
  214. short 0x0000
  215. bra.l _fnegx_
  216. short 0x0000
  217. bra.l _fsqrts_
  218. short 0x0000
  219. bra.l _fsqrtd_
  220. short 0x0000
  221. bra.l _fsqrtx_
  222. short 0x0000
  223. bra.l _fsubs_
  224. short 0x0000
  225. bra.l _fsubd_
  226. short 0x0000
  227. bra.l _fsubx_
  228. short 0x0000
  229. # leave room for future possible additions
  230. align 0x400
  231. #
  232. # This file contains a set of define statements for constants
  233. # in order to promote readability within the corecode itself.
  234. #
  235. set LOCAL_SIZE, 192 # stack frame size(bytes)
  236. set LV, -LOCAL_SIZE # stack offset
  237. set EXC_SR, 0x4 # stack status register
  238. set EXC_PC, 0x6 # stack pc
  239. set EXC_VOFF, 0xa # stacked vector offset
  240. set EXC_EA, 0xc # stacked <ea>
  241. set EXC_FP, 0x0 # frame pointer
  242. set EXC_AREGS, -68 # offset of all address regs
  243. set EXC_DREGS, -100 # offset of all data regs
  244. set EXC_FPREGS, -36 # offset of all fp regs
  245. set EXC_A7, EXC_AREGS+(7*4) # offset of saved a7
  246. set OLD_A7, EXC_AREGS+(6*4) # extra copy of saved a7
  247. set EXC_A6, EXC_AREGS+(6*4) # offset of saved a6
  248. set EXC_A5, EXC_AREGS+(5*4)
  249. set EXC_A4, EXC_AREGS+(4*4)
  250. set EXC_A3, EXC_AREGS+(3*4)
  251. set EXC_A2, EXC_AREGS+(2*4)
  252. set EXC_A1, EXC_AREGS+(1*4)
  253. set EXC_A0, EXC_AREGS+(0*4)
  254. set EXC_D7, EXC_DREGS+(7*4)
  255. set EXC_D6, EXC_DREGS+(6*4)
  256. set EXC_D5, EXC_DREGS+(5*4)
  257. set EXC_D4, EXC_DREGS+(4*4)
  258. set EXC_D3, EXC_DREGS+(3*4)
  259. set EXC_D2, EXC_DREGS+(2*4)
  260. set EXC_D1, EXC_DREGS+(1*4)
  261. set EXC_D0, EXC_DREGS+(0*4)
  262. set EXC_FP0, EXC_FPREGS+(0*12) # offset of saved fp0
  263. set EXC_FP1, EXC_FPREGS+(1*12) # offset of saved fp1
  264. set EXC_FP2, EXC_FPREGS+(2*12) # offset of saved fp2 (not used)
  265. set FP_SCR1, LV+80 # fp scratch 1
  266. set FP_SCR1_EX, FP_SCR1+0
  267. set FP_SCR1_SGN, FP_SCR1+2
  268. set FP_SCR1_HI, FP_SCR1+4
  269. set FP_SCR1_LO, FP_SCR1+8
  270. set FP_SCR0, LV+68 # fp scratch 0
  271. set FP_SCR0_EX, FP_SCR0+0
  272. set FP_SCR0_SGN, FP_SCR0+2
  273. set FP_SCR0_HI, FP_SCR0+4
  274. set FP_SCR0_LO, FP_SCR0+8
  275. set FP_DST, LV+56 # fp destination operand
  276. set FP_DST_EX, FP_DST+0
  277. set FP_DST_SGN, FP_DST+2
  278. set FP_DST_HI, FP_DST+4
  279. set FP_DST_LO, FP_DST+8
  280. set FP_SRC, LV+44 # fp source operand
  281. set FP_SRC_EX, FP_SRC+0
  282. set FP_SRC_SGN, FP_SRC+2
  283. set FP_SRC_HI, FP_SRC+4
  284. set FP_SRC_LO, FP_SRC+8
  285. set USER_FPIAR, LV+40 # FP instr address register
  286. set USER_FPSR, LV+36 # FP status register
  287. set FPSR_CC, USER_FPSR+0 # FPSR condition codes
  288. set FPSR_QBYTE, USER_FPSR+1 # FPSR qoutient byte
  289. set FPSR_EXCEPT, USER_FPSR+2 # FPSR exception status byte
  290. set FPSR_AEXCEPT, USER_FPSR+3 # FPSR accrued exception byte
  291. set USER_FPCR, LV+32 # FP control register
  292. set FPCR_ENABLE, USER_FPCR+2 # FPCR exception enable
  293. set FPCR_MODE, USER_FPCR+3 # FPCR rounding mode control
  294. set L_SCR3, LV+28 # integer scratch 3
  295. set L_SCR2, LV+24 # integer scratch 2
  296. set L_SCR1, LV+20 # integer scratch 1
  297. set STORE_FLG, LV+19 # flag: operand store (ie. not fcmp/ftst)
  298. set EXC_TEMP2, LV+24 # temporary space
  299. set EXC_TEMP, LV+16 # temporary space
  300. set DTAG, LV+15 # destination operand type
  301. set STAG, LV+14 # source operand type
  302. set SPCOND_FLG, LV+10 # flag: special case (see below)
  303. set EXC_CC, LV+8 # saved condition codes
  304. set EXC_EXTWPTR, LV+4 # saved current PC (active)
  305. set EXC_EXTWORD, LV+2 # saved extension word
  306. set EXC_CMDREG, LV+2 # saved extension word
  307. set EXC_OPWORD, LV+0 # saved operation word
  308. ################################
  309. # Helpful macros
  310. set FTEMP, 0 # offsets within an
  311. set FTEMP_EX, 0 # extended precision
  312. set FTEMP_SGN, 2 # value saved in memory.
  313. set FTEMP_HI, 4
  314. set FTEMP_LO, 8
  315. set FTEMP_GRS, 12
  316. set LOCAL, 0 # offsets within an
  317. set LOCAL_EX, 0 # extended precision
  318. set LOCAL_SGN, 2 # value saved in memory.
  319. set LOCAL_HI, 4
  320. set LOCAL_LO, 8
  321. set LOCAL_GRS, 12
  322. set DST, 0 # offsets within an
  323. set DST_EX, 0 # extended precision
  324. set DST_HI, 4 # value saved in memory.
  325. set DST_LO, 8
  326. set SRC, 0 # offsets within an
  327. set SRC_EX, 0 # extended precision
  328. set SRC_HI, 4 # value saved in memory.
  329. set SRC_LO, 8
  330. set SGL_LO, 0x3f81 # min sgl prec exponent
  331. set SGL_HI, 0x407e # max sgl prec exponent
  332. set DBL_LO, 0x3c01 # min dbl prec exponent
  333. set DBL_HI, 0x43fe # max dbl prec exponent
  334. set EXT_LO, 0x0 # min ext prec exponent
  335. set EXT_HI, 0x7ffe # max ext prec exponent
  336. set EXT_BIAS, 0x3fff # extended precision bias
  337. set SGL_BIAS, 0x007f # single precision bias
  338. set DBL_BIAS, 0x03ff # double precision bias
  339. set NORM, 0x00 # operand type for STAG/DTAG
  340. set ZERO, 0x01 # operand type for STAG/DTAG
  341. set INF, 0x02 # operand type for STAG/DTAG
  342. set QNAN, 0x03 # operand type for STAG/DTAG
  343. set DENORM, 0x04 # operand type for STAG/DTAG
  344. set SNAN, 0x05 # operand type for STAG/DTAG
  345. set UNNORM, 0x06 # operand type for STAG/DTAG
  346. ##################
  347. # FPSR/FPCR bits #
  348. ##################
  349. set neg_bit, 0x3 # negative result
  350. set z_bit, 0x2 # zero result
  351. set inf_bit, 0x1 # infinite result
  352. set nan_bit, 0x0 # NAN result
  353. set q_sn_bit, 0x7 # sign bit of quotient byte
  354. set bsun_bit, 7 # branch on unordered
  355. set snan_bit, 6 # signalling NAN
  356. set operr_bit, 5 # operand error
  357. set ovfl_bit, 4 # overflow
  358. set unfl_bit, 3 # underflow
  359. set dz_bit, 2 # divide by zero
  360. set inex2_bit, 1 # inexact result 2
  361. set inex1_bit, 0 # inexact result 1
  362. set aiop_bit, 7 # accrued inexact operation bit
  363. set aovfl_bit, 6 # accrued overflow bit
  364. set aunfl_bit, 5 # accrued underflow bit
  365. set adz_bit, 4 # accrued dz bit
  366. set ainex_bit, 3 # accrued inexact bit
  367. #############################
  368. # FPSR individual bit masks #
  369. #############################
  370. set neg_mask, 0x08000000 # negative bit mask (lw)
  371. set inf_mask, 0x02000000 # infinity bit mask (lw)
  372. set z_mask, 0x04000000 # zero bit mask (lw)
  373. set nan_mask, 0x01000000 # nan bit mask (lw)
  374. set neg_bmask, 0x08 # negative bit mask (byte)
  375. set inf_bmask, 0x02 # infinity bit mask (byte)
  376. set z_bmask, 0x04 # zero bit mask (byte)
  377. set nan_bmask, 0x01 # nan bit mask (byte)
  378. set bsun_mask, 0x00008000 # bsun exception mask
  379. set snan_mask, 0x00004000 # snan exception mask
  380. set operr_mask, 0x00002000 # operr exception mask
  381. set ovfl_mask, 0x00001000 # overflow exception mask
  382. set unfl_mask, 0x00000800 # underflow exception mask
  383. set dz_mask, 0x00000400 # dz exception mask
  384. set inex2_mask, 0x00000200 # inex2 exception mask
  385. set inex1_mask, 0x00000100 # inex1 exception mask
  386. set aiop_mask, 0x00000080 # accrued illegal operation
  387. set aovfl_mask, 0x00000040 # accrued overflow
  388. set aunfl_mask, 0x00000020 # accrued underflow
  389. set adz_mask, 0x00000010 # accrued divide by zero
  390. set ainex_mask, 0x00000008 # accrued inexact
  391. ######################################
  392. # FPSR combinations used in the FPSP #
  393. ######################################
  394. set dzinf_mask, inf_mask+dz_mask+adz_mask
  395. set opnan_mask, nan_mask+operr_mask+aiop_mask
  396. set nzi_mask, 0x01ffffff #clears N, Z, and I
  397. set unfinx_mask, unfl_mask+inex2_mask+aunfl_mask+ainex_mask
  398. set unf2inx_mask, unfl_mask+inex2_mask+ainex_mask
  399. set ovfinx_mask, ovfl_mask+inex2_mask+aovfl_mask+ainex_mask
  400. set inx1a_mask, inex1_mask+ainex_mask
  401. set inx2a_mask, inex2_mask+ainex_mask
  402. set snaniop_mask, nan_mask+snan_mask+aiop_mask
  403. set snaniop2_mask, snan_mask+aiop_mask
  404. set naniop_mask, nan_mask+aiop_mask
  405. set neginf_mask, neg_mask+inf_mask
  406. set infaiop_mask, inf_mask+aiop_mask
  407. set negz_mask, neg_mask+z_mask
  408. set opaop_mask, operr_mask+aiop_mask
  409. set unfl_inx_mask, unfl_mask+aunfl_mask+ainex_mask
  410. set ovfl_inx_mask, ovfl_mask+aovfl_mask+ainex_mask
  411. #########
  412. # misc. #
  413. #########
  414. set rnd_stky_bit, 29 # stky bit pos in longword
  415. set sign_bit, 0x7 # sign bit
  416. set signan_bit, 0x6 # signalling nan bit
  417. set sgl_thresh, 0x3f81 # minimum sgl exponent
  418. set dbl_thresh, 0x3c01 # minimum dbl exponent
  419. set x_mode, 0x0 # extended precision
  420. set s_mode, 0x4 # single precision
  421. set d_mode, 0x8 # double precision
  422. set rn_mode, 0x0 # round-to-nearest
  423. set rz_mode, 0x1 # round-to-zero
  424. set rm_mode, 0x2 # round-tp-minus-infinity
  425. set rp_mode, 0x3 # round-to-plus-infinity
  426. set mantissalen, 64 # length of mantissa in bits
  427. set BYTE, 1 # len(byte) == 1 byte
  428. set WORD, 2 # len(word) == 2 bytes
  429. set LONG, 4 # len(longword) == 2 bytes
  430. set BSUN_VEC, 0xc0 # bsun vector offset
  431. set INEX_VEC, 0xc4 # inexact vector offset
  432. set DZ_VEC, 0xc8 # dz vector offset
  433. set UNFL_VEC, 0xcc # unfl vector offset
  434. set OPERR_VEC, 0xd0 # operr vector offset
  435. set OVFL_VEC, 0xd4 # ovfl vector offset
  436. set SNAN_VEC, 0xd8 # snan vector offset
  437. ###########################
  438. # SPecial CONDition FLaGs #
  439. ###########################
  440. set ftrapcc_flg, 0x01 # flag bit: ftrapcc exception
  441. set fbsun_flg, 0x02 # flag bit: bsun exception
  442. set mia7_flg, 0x04 # flag bit: (a7)+ <ea>
  443. set mda7_flg, 0x08 # flag bit: -(a7) <ea>
  444. set fmovm_flg, 0x40 # flag bit: fmovm instruction
  445. set immed_flg, 0x80 # flag bit: &<data> <ea>
  446. set ftrapcc_bit, 0x0
  447. set fbsun_bit, 0x1
  448. set mia7_bit, 0x2
  449. set mda7_bit, 0x3
  450. set immed_bit, 0x7
  451. ##################################
  452. # TRANSCENDENTAL "LAST-OP" FLAGS #
  453. ##################################
  454. set FMUL_OP, 0x0 # fmul instr performed last
  455. set FDIV_OP, 0x1 # fdiv performed last
  456. set FADD_OP, 0x2 # fadd performed last
  457. set FMOV_OP, 0x3 # fmov performed last
  458. #############
  459. # CONSTANTS #
  460. #############
  461. T1: long 0x40C62D38,0xD3D64634 # 16381 LOG2 LEAD
  462. T2: long 0x3D6F90AE,0xB1E75CC7 # 16381 LOG2 TRAIL
  463. PI: long 0x40000000,0xC90FDAA2,0x2168C235,0x00000000
  464. PIBY2: long 0x3FFF0000,0xC90FDAA2,0x2168C235,0x00000000
  465. TWOBYPI:
  466. long 0x3FE45F30,0x6DC9C883
  467. #########################################################################
  468. # MONADIC TEMPLATE #
  469. #########################################################################
  470. global _fsins_
  471. _fsins_:
  472. link %a6,&-LOCAL_SIZE
  473. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  474. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  475. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  476. fmov.l &0x0,%fpcr # zero FPCR
  477. #
  478. # copy, convert, and tag input argument
  479. #
  480. fmov.s 0x8(%a6),%fp0 # load sgl input
  481. fmov.x %fp0,FP_SRC(%a6)
  482. lea FP_SRC(%a6),%a0
  483. bsr.l tag # fetch operand type
  484. mov.b %d0,STAG(%a6)
  485. mov.b %d0,%d1
  486. andi.l &0x00ff00ff,USER_FPSR(%a6)
  487. clr.l %d0
  488. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  489. tst.b %d1
  490. bne.b _L0_2s
  491. bsr.l ssin # operand is a NORM
  492. bra.b _L0_6s
  493. _L0_2s:
  494. cmpi.b %d1,&ZERO # is operand a ZERO?
  495. bne.b _L0_3s # no
  496. bsr.l src_zero # yes
  497. bra.b _L0_6s
  498. _L0_3s:
  499. cmpi.b %d1,&INF # is operand an INF?
  500. bne.b _L0_4s # no
  501. bsr.l t_operr # yes
  502. bra.b _L0_6s
  503. _L0_4s:
  504. cmpi.b %d1,&QNAN # is operand a QNAN?
  505. bne.b _L0_5s # no
  506. bsr.l src_qnan # yes
  507. bra.b _L0_6s
  508. _L0_5s:
  509. bsr.l ssind # operand is a DENORM
  510. _L0_6s:
  511. #
  512. # Result is now in FP0
  513. #
  514. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  515. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  516. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  517. unlk %a6
  518. rts
  519. global _fsind_
  520. _fsind_:
  521. link %a6,&-LOCAL_SIZE
  522. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  523. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  524. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  525. fmov.l &0x0,%fpcr # zero FPCR
  526. #
  527. # copy, convert, and tag input argument
  528. #
  529. fmov.d 0x8(%a6),%fp0 # load dbl input
  530. fmov.x %fp0,FP_SRC(%a6)
  531. lea FP_SRC(%a6),%a0
  532. bsr.l tag # fetch operand type
  533. mov.b %d0,STAG(%a6)
  534. mov.b %d0,%d1
  535. andi.l &0x00ff00ff,USER_FPSR(%a6)
  536. clr.l %d0
  537. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  538. mov.b %d1,STAG(%a6)
  539. tst.b %d1
  540. bne.b _L0_2d
  541. bsr.l ssin # operand is a NORM
  542. bra.b _L0_6d
  543. _L0_2d:
  544. cmpi.b %d1,&ZERO # is operand a ZERO?
  545. bne.b _L0_3d # no
  546. bsr.l src_zero # yes
  547. bra.b _L0_6d
  548. _L0_3d:
  549. cmpi.b %d1,&INF # is operand an INF?
  550. bne.b _L0_4d # no
  551. bsr.l t_operr # yes
  552. bra.b _L0_6d
  553. _L0_4d:
  554. cmpi.b %d1,&QNAN # is operand a QNAN?
  555. bne.b _L0_5d # no
  556. bsr.l src_qnan # yes
  557. bra.b _L0_6d
  558. _L0_5d:
  559. bsr.l ssind # operand is a DENORM
  560. _L0_6d:
  561. #
  562. # Result is now in FP0
  563. #
  564. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  565. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  566. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  567. unlk %a6
  568. rts
  569. global _fsinx_
  570. _fsinx_:
  571. link %a6,&-LOCAL_SIZE
  572. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  573. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  574. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  575. fmov.l &0x0,%fpcr # zero FPCR
  576. #
  577. # copy, convert, and tag input argument
  578. #
  579. lea FP_SRC(%a6),%a0
  580. mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
  581. mov.l 0x8+0x4(%a6),0x4(%a0)
  582. mov.l 0x8+0x8(%a6),0x8(%a0)
  583. bsr.l tag # fetch operand type
  584. mov.b %d0,STAG(%a6)
  585. mov.b %d0,%d1
  586. andi.l &0x00ff00ff,USER_FPSR(%a6)
  587. clr.l %d0
  588. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  589. tst.b %d1
  590. bne.b _L0_2x
  591. bsr.l ssin # operand is a NORM
  592. bra.b _L0_6x
  593. _L0_2x:
  594. cmpi.b %d1,&ZERO # is operand a ZERO?
  595. bne.b _L0_3x # no
  596. bsr.l src_zero # yes
  597. bra.b _L0_6x
  598. _L0_3x:
  599. cmpi.b %d1,&INF # is operand an INF?
  600. bne.b _L0_4x # no
  601. bsr.l t_operr # yes
  602. bra.b _L0_6x
  603. _L0_4x:
  604. cmpi.b %d1,&QNAN # is operand a QNAN?
  605. bne.b _L0_5x # no
  606. bsr.l src_qnan # yes
  607. bra.b _L0_6x
  608. _L0_5x:
  609. bsr.l ssind # operand is a DENORM
  610. _L0_6x:
  611. #
  612. # Result is now in FP0
  613. #
  614. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  615. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  616. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  617. unlk %a6
  618. rts
  619. #########################################################################
  620. # MONADIC TEMPLATE #
  621. #########################################################################
  622. global _fcoss_
  623. _fcoss_:
  624. link %a6,&-LOCAL_SIZE
  625. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  626. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  627. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  628. fmov.l &0x0,%fpcr # zero FPCR
  629. #
  630. # copy, convert, and tag input argument
  631. #
  632. fmov.s 0x8(%a6),%fp0 # load sgl input
  633. fmov.x %fp0,FP_SRC(%a6)
  634. lea FP_SRC(%a6),%a0
  635. bsr.l tag # fetch operand type
  636. mov.b %d0,STAG(%a6)
  637. mov.b %d0,%d1
  638. andi.l &0x00ff00ff,USER_FPSR(%a6)
  639. clr.l %d0
  640. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  641. tst.b %d1
  642. bne.b _L1_2s
  643. bsr.l scos # operand is a NORM
  644. bra.b _L1_6s
  645. _L1_2s:
  646. cmpi.b %d1,&ZERO # is operand a ZERO?
  647. bne.b _L1_3s # no
  648. bsr.l ld_pone # yes
  649. bra.b _L1_6s
  650. _L1_3s:
  651. cmpi.b %d1,&INF # is operand an INF?
  652. bne.b _L1_4s # no
  653. bsr.l t_operr # yes
  654. bra.b _L1_6s
  655. _L1_4s:
  656. cmpi.b %d1,&QNAN # is operand a QNAN?
  657. bne.b _L1_5s # no
  658. bsr.l src_qnan # yes
  659. bra.b _L1_6s
  660. _L1_5s:
  661. bsr.l scosd # operand is a DENORM
  662. _L1_6s:
  663. #
  664. # Result is now in FP0
  665. #
  666. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  667. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  668. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  669. unlk %a6
  670. rts
  671. global _fcosd_
  672. _fcosd_:
  673. link %a6,&-LOCAL_SIZE
  674. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  675. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  676. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  677. fmov.l &0x0,%fpcr # zero FPCR
  678. #
  679. # copy, convert, and tag input argument
  680. #
  681. fmov.d 0x8(%a6),%fp0 # load dbl input
  682. fmov.x %fp0,FP_SRC(%a6)
  683. lea FP_SRC(%a6),%a0
  684. bsr.l tag # fetch operand type
  685. mov.b %d0,STAG(%a6)
  686. mov.b %d0,%d1
  687. andi.l &0x00ff00ff,USER_FPSR(%a6)
  688. clr.l %d0
  689. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  690. mov.b %d1,STAG(%a6)
  691. tst.b %d1
  692. bne.b _L1_2d
  693. bsr.l scos # operand is a NORM
  694. bra.b _L1_6d
  695. _L1_2d:
  696. cmpi.b %d1,&ZERO # is operand a ZERO?
  697. bne.b _L1_3d # no
  698. bsr.l ld_pone # yes
  699. bra.b _L1_6d
  700. _L1_3d:
  701. cmpi.b %d1,&INF # is operand an INF?
  702. bne.b _L1_4d # no
  703. bsr.l t_operr # yes
  704. bra.b _L1_6d
  705. _L1_4d:
  706. cmpi.b %d1,&QNAN # is operand a QNAN?
  707. bne.b _L1_5d # no
  708. bsr.l src_qnan # yes
  709. bra.b _L1_6d
  710. _L1_5d:
  711. bsr.l scosd # operand is a DENORM
  712. _L1_6d:
  713. #
  714. # Result is now in FP0
  715. #
  716. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  717. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  718. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  719. unlk %a6
  720. rts
  721. global _fcosx_
  722. _fcosx_:
  723. link %a6,&-LOCAL_SIZE
  724. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  725. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  726. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  727. fmov.l &0x0,%fpcr # zero FPCR
  728. #
  729. # copy, convert, and tag input argument
  730. #
  731. lea FP_SRC(%a6),%a0
  732. mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
  733. mov.l 0x8+0x4(%a6),0x4(%a0)
  734. mov.l 0x8+0x8(%a6),0x8(%a0)
  735. bsr.l tag # fetch operand type
  736. mov.b %d0,STAG(%a6)
  737. mov.b %d0,%d1
  738. andi.l &0x00ff00ff,USER_FPSR(%a6)
  739. clr.l %d0
  740. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  741. tst.b %d1
  742. bne.b _L1_2x
  743. bsr.l scos # operand is a NORM
  744. bra.b _L1_6x
  745. _L1_2x:
  746. cmpi.b %d1,&ZERO # is operand a ZERO?
  747. bne.b _L1_3x # no
  748. bsr.l ld_pone # yes
  749. bra.b _L1_6x
  750. _L1_3x:
  751. cmpi.b %d1,&INF # is operand an INF?
  752. bne.b _L1_4x # no
  753. bsr.l t_operr # yes
  754. bra.b _L1_6x
  755. _L1_4x:
  756. cmpi.b %d1,&QNAN # is operand a QNAN?
  757. bne.b _L1_5x # no
  758. bsr.l src_qnan # yes
  759. bra.b _L1_6x
  760. _L1_5x:
  761. bsr.l scosd # operand is a DENORM
  762. _L1_6x:
  763. #
  764. # Result is now in FP0
  765. #
  766. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  767. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  768. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  769. unlk %a6
  770. rts
  771. #########################################################################
  772. # MONADIC TEMPLATE #
  773. #########################################################################
  774. global _fsinhs_
  775. _fsinhs_:
  776. link %a6,&-LOCAL_SIZE
  777. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  778. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  779. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  780. fmov.l &0x0,%fpcr # zero FPCR
  781. #
  782. # copy, convert, and tag input argument
  783. #
  784. fmov.s 0x8(%a6),%fp0 # load sgl input
  785. fmov.x %fp0,FP_SRC(%a6)
  786. lea FP_SRC(%a6),%a0
  787. bsr.l tag # fetch operand type
  788. mov.b %d0,STAG(%a6)
  789. mov.b %d0,%d1
  790. andi.l &0x00ff00ff,USER_FPSR(%a6)
  791. clr.l %d0
  792. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  793. tst.b %d1
  794. bne.b _L2_2s
  795. bsr.l ssinh # operand is a NORM
  796. bra.b _L2_6s
  797. _L2_2s:
  798. cmpi.b %d1,&ZERO # is operand a ZERO?
  799. bne.b _L2_3s # no
  800. bsr.l src_zero # yes
  801. bra.b _L2_6s
  802. _L2_3s:
  803. cmpi.b %d1,&INF # is operand an INF?
  804. bne.b _L2_4s # no
  805. bsr.l src_inf # yes
  806. bra.b _L2_6s
  807. _L2_4s:
  808. cmpi.b %d1,&QNAN # is operand a QNAN?
  809. bne.b _L2_5s # no
  810. bsr.l src_qnan # yes
  811. bra.b _L2_6s
  812. _L2_5s:
  813. bsr.l ssinhd # operand is a DENORM
  814. _L2_6s:
  815. #
  816. # Result is now in FP0
  817. #
  818. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  819. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  820. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  821. unlk %a6
  822. rts
  823. global _fsinhd_
  824. _fsinhd_:
  825. link %a6,&-LOCAL_SIZE
  826. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  827. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  828. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  829. fmov.l &0x0,%fpcr # zero FPCR
  830. #
  831. # copy, convert, and tag input argument
  832. #
  833. fmov.d 0x8(%a6),%fp0 # load dbl input
  834. fmov.x %fp0,FP_SRC(%a6)
  835. lea FP_SRC(%a6),%a0
  836. bsr.l tag # fetch operand type
  837. mov.b %d0,STAG(%a6)
  838. mov.b %d0,%d1
  839. andi.l &0x00ff00ff,USER_FPSR(%a6)
  840. clr.l %d0
  841. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  842. mov.b %d1,STAG(%a6)
  843. tst.b %d1
  844. bne.b _L2_2d
  845. bsr.l ssinh # operand is a NORM
  846. bra.b _L2_6d
  847. _L2_2d:
  848. cmpi.b %d1,&ZERO # is operand a ZERO?
  849. bne.b _L2_3d # no
  850. bsr.l src_zero # yes
  851. bra.b _L2_6d
  852. _L2_3d:
  853. cmpi.b %d1,&INF # is operand an INF?
  854. bne.b _L2_4d # no
  855. bsr.l src_inf # yes
  856. bra.b _L2_6d
  857. _L2_4d:
  858. cmpi.b %d1,&QNAN # is operand a QNAN?
  859. bne.b _L2_5d # no
  860. bsr.l src_qnan # yes
  861. bra.b _L2_6d
  862. _L2_5d:
  863. bsr.l ssinhd # operand is a DENORM
  864. _L2_6d:
  865. #
  866. # Result is now in FP0
  867. #
  868. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  869. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  870. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  871. unlk %a6
  872. rts
  873. global _fsinhx_
  874. _fsinhx_:
  875. link %a6,&-LOCAL_SIZE
  876. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  877. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  878. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  879. fmov.l &0x0,%fpcr # zero FPCR
  880. #
  881. # copy, convert, and tag input argument
  882. #
  883. lea FP_SRC(%a6),%a0
  884. mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
  885. mov.l 0x8+0x4(%a6),0x4(%a0)
  886. mov.l 0x8+0x8(%a6),0x8(%a0)
  887. bsr.l tag # fetch operand type
  888. mov.b %d0,STAG(%a6)
  889. mov.b %d0,%d1
  890. andi.l &0x00ff00ff,USER_FPSR(%a6)
  891. clr.l %d0
  892. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  893. tst.b %d1
  894. bne.b _L2_2x
  895. bsr.l ssinh # operand is a NORM
  896. bra.b _L2_6x
  897. _L2_2x:
  898. cmpi.b %d1,&ZERO # is operand a ZERO?
  899. bne.b _L2_3x # no
  900. bsr.l src_zero # yes
  901. bra.b _L2_6x
  902. _L2_3x:
  903. cmpi.b %d1,&INF # is operand an INF?
  904. bne.b _L2_4x # no
  905. bsr.l src_inf # yes
  906. bra.b _L2_6x
  907. _L2_4x:
  908. cmpi.b %d1,&QNAN # is operand a QNAN?
  909. bne.b _L2_5x # no
  910. bsr.l src_qnan # yes
  911. bra.b _L2_6x
  912. _L2_5x:
  913. bsr.l ssinhd # operand is a DENORM
  914. _L2_6x:
  915. #
  916. # Result is now in FP0
  917. #
  918. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  919. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  920. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  921. unlk %a6
  922. rts
  923. #########################################################################
  924. # MONADIC TEMPLATE #
  925. #########################################################################
  926. global _flognp1s_
  927. _flognp1s_:
  928. link %a6,&-LOCAL_SIZE
  929. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  930. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  931. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  932. fmov.l &0x0,%fpcr # zero FPCR
  933. #
  934. # copy, convert, and tag input argument
  935. #
  936. fmov.s 0x8(%a6),%fp0 # load sgl input
  937. fmov.x %fp0,FP_SRC(%a6)
  938. lea FP_SRC(%a6),%a0
  939. bsr.l tag # fetch operand type
  940. mov.b %d0,STAG(%a6)
  941. mov.b %d0,%d1
  942. andi.l &0x00ff00ff,USER_FPSR(%a6)
  943. clr.l %d0
  944. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  945. tst.b %d1
  946. bne.b _L3_2s
  947. bsr.l slognp1 # operand is a NORM
  948. bra.b _L3_6s
  949. _L3_2s:
  950. cmpi.b %d1,&ZERO # is operand a ZERO?
  951. bne.b _L3_3s # no
  952. bsr.l src_zero # yes
  953. bra.b _L3_6s
  954. _L3_3s:
  955. cmpi.b %d1,&INF # is operand an INF?
  956. bne.b _L3_4s # no
  957. bsr.l sopr_inf # yes
  958. bra.b _L3_6s
  959. _L3_4s:
  960. cmpi.b %d1,&QNAN # is operand a QNAN?
  961. bne.b _L3_5s # no
  962. bsr.l src_qnan # yes
  963. bra.b _L3_6s
  964. _L3_5s:
  965. bsr.l slognp1d # operand is a DENORM
  966. _L3_6s:
  967. #
  968. # Result is now in FP0
  969. #
  970. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  971. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  972. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  973. unlk %a6
  974. rts
  975. global _flognp1d_
  976. _flognp1d_:
  977. link %a6,&-LOCAL_SIZE
  978. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  979. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  980. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  981. fmov.l &0x0,%fpcr # zero FPCR
  982. #
  983. # copy, convert, and tag input argument
  984. #
  985. fmov.d 0x8(%a6),%fp0 # load dbl input
  986. fmov.x %fp0,FP_SRC(%a6)
  987. lea FP_SRC(%a6),%a0
  988. bsr.l tag # fetch operand type
  989. mov.b %d0,STAG(%a6)
  990. mov.b %d0,%d1
  991. andi.l &0x00ff00ff,USER_FPSR(%a6)
  992. clr.l %d0
  993. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  994. mov.b %d1,STAG(%a6)
  995. tst.b %d1
  996. bne.b _L3_2d
  997. bsr.l slognp1 # operand is a NORM
  998. bra.b _L3_6d
  999. _L3_2d:
  1000. cmpi.b %d1,&ZERO # is operand a ZERO?
  1001. bne.b _L3_3d # no
  1002. bsr.l src_zero # yes
  1003. bra.b _L3_6d
  1004. _L3_3d:
  1005. cmpi.b %d1,&INF # is operand an INF?
  1006. bne.b _L3_4d # no
  1007. bsr.l sopr_inf # yes
  1008. bra.b _L3_6d
  1009. _L3_4d:
  1010. cmpi.b %d1,&QNAN # is operand a QNAN?
  1011. bne.b _L3_5d # no
  1012. bsr.l src_qnan # yes
  1013. bra.b _L3_6d
  1014. _L3_5d:
  1015. bsr.l slognp1d # operand is a DENORM
  1016. _L3_6d:
  1017. #
  1018. # Result is now in FP0
  1019. #
  1020. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  1021. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  1022. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  1023. unlk %a6
  1024. rts
  1025. global _flognp1x_
  1026. _flognp1x_:
  1027. link %a6,&-LOCAL_SIZE
  1028. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  1029. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  1030. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  1031. fmov.l &0x0,%fpcr # zero FPCR
  1032. #
  1033. # copy, convert, and tag input argument
  1034. #
  1035. lea FP_SRC(%a6),%a0
  1036. mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
  1037. mov.l 0x8+0x4(%a6),0x4(%a0)
  1038. mov.l 0x8+0x8(%a6),0x8(%a0)
  1039. bsr.l tag # fetch operand type
  1040. mov.b %d0,STAG(%a6)
  1041. mov.b %d0,%d1
  1042. andi.l &0x00ff00ff,USER_FPSR(%a6)
  1043. clr.l %d0
  1044. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  1045. tst.b %d1
  1046. bne.b _L3_2x
  1047. bsr.l slognp1 # operand is a NORM
  1048. bra.b _L3_6x
  1049. _L3_2x:
  1050. cmpi.b %d1,&ZERO # is operand a ZERO?
  1051. bne.b _L3_3x # no
  1052. bsr.l src_zero # yes
  1053. bra.b _L3_6x
  1054. _L3_3x:
  1055. cmpi.b %d1,&INF # is operand an INF?
  1056. bne.b _L3_4x # no
  1057. bsr.l sopr_inf # yes
  1058. bra.b _L3_6x
  1059. _L3_4x:
  1060. cmpi.b %d1,&QNAN # is operand a QNAN?
  1061. bne.b _L3_5x # no
  1062. bsr.l src_qnan # yes
  1063. bra.b _L3_6x
  1064. _L3_5x:
  1065. bsr.l slognp1d # operand is a DENORM
  1066. _L3_6x:
  1067. #
  1068. # Result is now in FP0
  1069. #
  1070. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  1071. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  1072. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  1073. unlk %a6
  1074. rts
  1075. #########################################################################
  1076. # MONADIC TEMPLATE #
  1077. #########################################################################
  1078. global _fetoxm1s_
  1079. _fetoxm1s_:
  1080. link %a6,&-LOCAL_SIZE
  1081. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  1082. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  1083. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  1084. fmov.l &0x0,%fpcr # zero FPCR
  1085. #
  1086. # copy, convert, and tag input argument
  1087. #
  1088. fmov.s 0x8(%a6),%fp0 # load sgl input
  1089. fmov.x %fp0,FP_SRC(%a6)
  1090. lea FP_SRC(%a6),%a0
  1091. bsr.l tag # fetch operand type
  1092. mov.b %d0,STAG(%a6)
  1093. mov.b %d0,%d1
  1094. andi.l &0x00ff00ff,USER_FPSR(%a6)
  1095. clr.l %d0
  1096. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  1097. tst.b %d1
  1098. bne.b _L4_2s
  1099. bsr.l setoxm1 # operand is a NORM
  1100. bra.b _L4_6s
  1101. _L4_2s:
  1102. cmpi.b %d1,&ZERO # is operand a ZERO?
  1103. bne.b _L4_3s # no
  1104. bsr.l src_zero # yes
  1105. bra.b _L4_6s
  1106. _L4_3s:
  1107. cmpi.b %d1,&INF # is operand an INF?
  1108. bne.b _L4_4s # no
  1109. bsr.l setoxm1i # yes
  1110. bra.b _L4_6s
  1111. _L4_4s:
  1112. cmpi.b %d1,&QNAN # is operand a QNAN?
  1113. bne.b _L4_5s # no
  1114. bsr.l src_qnan # yes
  1115. bra.b _L4_6s
  1116. _L4_5s:
  1117. bsr.l setoxm1d # operand is a DENORM
  1118. _L4_6s:
  1119. #
  1120. # Result is now in FP0
  1121. #
  1122. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  1123. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  1124. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  1125. unlk %a6
  1126. rts
  1127. global _fetoxm1d_
  1128. _fetoxm1d_:
  1129. link %a6,&-LOCAL_SIZE
  1130. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  1131. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  1132. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  1133. fmov.l &0x0,%fpcr # zero FPCR
  1134. #
  1135. # copy, convert, and tag input argument
  1136. #
  1137. fmov.d 0x8(%a6),%fp0 # load dbl input
  1138. fmov.x %fp0,FP_SRC(%a6)
  1139. lea FP_SRC(%a6),%a0
  1140. bsr.l tag # fetch operand type
  1141. mov.b %d0,STAG(%a6)
  1142. mov.b %d0,%d1
  1143. andi.l &0x00ff00ff,USER_FPSR(%a6)
  1144. clr.l %d0
  1145. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  1146. mov.b %d1,STAG(%a6)
  1147. tst.b %d1
  1148. bne.b _L4_2d
  1149. bsr.l setoxm1 # operand is a NORM
  1150. bra.b _L4_6d
  1151. _L4_2d:
  1152. cmpi.b %d1,&ZERO # is operand a ZERO?
  1153. bne.b _L4_3d # no
  1154. bsr.l src_zero # yes
  1155. bra.b _L4_6d
  1156. _L4_3d:
  1157. cmpi.b %d1,&INF # is operand an INF?
  1158. bne.b _L4_4d # no
  1159. bsr.l setoxm1i # yes
  1160. bra.b _L4_6d
  1161. _L4_4d:
  1162. cmpi.b %d1,&QNAN # is operand a QNAN?
  1163. bne.b _L4_5d # no
  1164. bsr.l src_qnan # yes
  1165. bra.b _L4_6d
  1166. _L4_5d:
  1167. bsr.l setoxm1d # operand is a DENORM
  1168. _L4_6d:
  1169. #
  1170. # Result is now in FP0
  1171. #
  1172. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  1173. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  1174. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  1175. unlk %a6
  1176. rts
  1177. global _fetoxm1x_
  1178. _fetoxm1x_:
  1179. link %a6,&-LOCAL_SIZE
  1180. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  1181. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  1182. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  1183. fmov.l &0x0,%fpcr # zero FPCR
  1184. #
  1185. # copy, convert, and tag input argument
  1186. #
  1187. lea FP_SRC(%a6),%a0
  1188. mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
  1189. mov.l 0x8+0x4(%a6),0x4(%a0)
  1190. mov.l 0x8+0x8(%a6),0x8(%a0)
  1191. bsr.l tag # fetch operand type
  1192. mov.b %d0,STAG(%a6)
  1193. mov.b %d0,%d1
  1194. andi.l &0x00ff00ff,USER_FPSR(%a6)
  1195. clr.l %d0
  1196. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  1197. tst.b %d1
  1198. bne.b _L4_2x
  1199. bsr.l setoxm1 # operand is a NORM
  1200. bra.b _L4_6x
  1201. _L4_2x:
  1202. cmpi.b %d1,&ZERO # is operand a ZERO?
  1203. bne.b _L4_3x # no
  1204. bsr.l src_zero # yes
  1205. bra.b _L4_6x
  1206. _L4_3x:
  1207. cmpi.b %d1,&INF # is operand an INF?
  1208. bne.b _L4_4x # no
  1209. bsr.l setoxm1i # yes
  1210. bra.b _L4_6x
  1211. _L4_4x:
  1212. cmpi.b %d1,&QNAN # is operand a QNAN?
  1213. bne.b _L4_5x # no
  1214. bsr.l src_qnan # yes
  1215. bra.b _L4_6x
  1216. _L4_5x:
  1217. bsr.l setoxm1d # operand is a DENORM
  1218. _L4_6x:
  1219. #
  1220. # Result is now in FP0
  1221. #
  1222. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  1223. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  1224. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  1225. unlk %a6
  1226. rts
  1227. #########################################################################
  1228. # MONADIC TEMPLATE #
  1229. #########################################################################
  1230. global _ftanhs_
  1231. _ftanhs_:
  1232. link %a6,&-LOCAL_SIZE
  1233. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  1234. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  1235. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  1236. fmov.l &0x0,%fpcr # zero FPCR
  1237. #
  1238. # copy, convert, and tag input argument
  1239. #
  1240. fmov.s 0x8(%a6),%fp0 # load sgl input
  1241. fmov.x %fp0,FP_SRC(%a6)
  1242. lea FP_SRC(%a6),%a0
  1243. bsr.l tag # fetch operand type
  1244. mov.b %d0,STAG(%a6)
  1245. mov.b %d0,%d1
  1246. andi.l &0x00ff00ff,USER_FPSR(%a6)
  1247. clr.l %d0
  1248. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  1249. tst.b %d1
  1250. bne.b _L5_2s
  1251. bsr.l stanh # operand is a NORM
  1252. bra.b _L5_6s
  1253. _L5_2s:
  1254. cmpi.b %d1,&ZERO # is operand a ZERO?
  1255. bne.b _L5_3s # no
  1256. bsr.l src_zero # yes
  1257. bra.b _L5_6s
  1258. _L5_3s:
  1259. cmpi.b %d1,&INF # is operand an INF?
  1260. bne.b _L5_4s # no
  1261. bsr.l src_one # yes
  1262. bra.b _L5_6s
  1263. _L5_4s:
  1264. cmpi.b %d1,&QNAN # is operand a QNAN?
  1265. bne.b _L5_5s # no
  1266. bsr.l src_qnan # yes
  1267. bra.b _L5_6s
  1268. _L5_5s:
  1269. bsr.l stanhd # operand is a DENORM
  1270. _L5_6s:
  1271. #
  1272. # Result is now in FP0
  1273. #
  1274. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  1275. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  1276. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  1277. unlk %a6
  1278. rts
  1279. global _ftanhd_
  1280. _ftanhd_:
  1281. link %a6,&-LOCAL_SIZE
  1282. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  1283. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  1284. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  1285. fmov.l &0x0,%fpcr # zero FPCR
  1286. #
  1287. # copy, convert, and tag input argument
  1288. #
  1289. fmov.d 0x8(%a6),%fp0 # load dbl input
  1290. fmov.x %fp0,FP_SRC(%a6)
  1291. lea FP_SRC(%a6),%a0
  1292. bsr.l tag # fetch operand type
  1293. mov.b %d0,STAG(%a6)
  1294. mov.b %d0,%d1
  1295. andi.l &0x00ff00ff,USER_FPSR(%a6)
  1296. clr.l %d0
  1297. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  1298. mov.b %d1,STAG(%a6)
  1299. tst.b %d1
  1300. bne.b _L5_2d
  1301. bsr.l stanh # operand is a NORM
  1302. bra.b _L5_6d
  1303. _L5_2d:
  1304. cmpi.b %d1,&ZERO # is operand a ZERO?
  1305. bne.b _L5_3d # no
  1306. bsr.l src_zero # yes
  1307. bra.b _L5_6d
  1308. _L5_3d:
  1309. cmpi.b %d1,&INF # is operand an INF?
  1310. bne.b _L5_4d # no
  1311. bsr.l src_one # yes
  1312. bra.b _L5_6d
  1313. _L5_4d:
  1314. cmpi.b %d1,&QNAN # is operand a QNAN?
  1315. bne.b _L5_5d # no
  1316. bsr.l src_qnan # yes
  1317. bra.b _L5_6d
  1318. _L5_5d:
  1319. bsr.l stanhd # operand is a DENORM
  1320. _L5_6d:
  1321. #
  1322. # Result is now in FP0
  1323. #
  1324. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  1325. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  1326. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  1327. unlk %a6
  1328. rts
  1329. global _ftanhx_
  1330. _ftanhx_:
  1331. link %a6,&-LOCAL_SIZE
  1332. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  1333. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  1334. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  1335. fmov.l &0x0,%fpcr # zero FPCR
  1336. #
  1337. # copy, convert, and tag input argument
  1338. #
  1339. lea FP_SRC(%a6),%a0
  1340. mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
  1341. mov.l 0x8+0x4(%a6),0x4(%a0)
  1342. mov.l 0x8+0x8(%a6),0x8(%a0)
  1343. bsr.l tag # fetch operand type
  1344. mov.b %d0,STAG(%a6)
  1345. mov.b %d0,%d1
  1346. andi.l &0x00ff00ff,USER_FPSR(%a6)
  1347. clr.l %d0
  1348. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  1349. tst.b %d1
  1350. bne.b _L5_2x
  1351. bsr.l stanh # operand is a NORM
  1352. bra.b _L5_6x
  1353. _L5_2x:
  1354. cmpi.b %d1,&ZERO # is operand a ZERO?
  1355. bne.b _L5_3x # no
  1356. bsr.l src_zero # yes
  1357. bra.b _L5_6x
  1358. _L5_3x:
  1359. cmpi.b %d1,&INF # is operand an INF?
  1360. bne.b _L5_4x # no
  1361. bsr.l src_one # yes
  1362. bra.b _L5_6x
  1363. _L5_4x:
  1364. cmpi.b %d1,&QNAN # is operand a QNAN?
  1365. bne.b _L5_5x # no
  1366. bsr.l src_qnan # yes
  1367. bra.b _L5_6x
  1368. _L5_5x:
  1369. bsr.l stanhd # operand is a DENORM
  1370. _L5_6x:
  1371. #
  1372. # Result is now in FP0
  1373. #
  1374. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  1375. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  1376. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  1377. unlk %a6
  1378. rts
  1379. #########################################################################
  1380. # MONADIC TEMPLATE #
  1381. #########################################################################
  1382. global _fatans_
  1383. _fatans_:
  1384. link %a6,&-LOCAL_SIZE
  1385. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  1386. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  1387. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  1388. fmov.l &0x0,%fpcr # zero FPCR
  1389. #
  1390. # copy, convert, and tag input argument
  1391. #
  1392. fmov.s 0x8(%a6),%fp0 # load sgl input
  1393. fmov.x %fp0,FP_SRC(%a6)
  1394. lea FP_SRC(%a6),%a0
  1395. bsr.l tag # fetch operand type
  1396. mov.b %d0,STAG(%a6)
  1397. mov.b %d0,%d1
  1398. andi.l &0x00ff00ff,USER_FPSR(%a6)
  1399. clr.l %d0
  1400. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  1401. tst.b %d1
  1402. bne.b _L6_2s
  1403. bsr.l satan # operand is a NORM
  1404. bra.b _L6_6s
  1405. _L6_2s:
  1406. cmpi.b %d1,&ZERO # is operand a ZERO?
  1407. bne.b _L6_3s # no
  1408. bsr.l src_zero # yes
  1409. bra.b _L6_6s
  1410. _L6_3s:
  1411. cmpi.b %d1,&INF # is operand an INF?
  1412. bne.b _L6_4s # no
  1413. bsr.l spi_2 # yes
  1414. bra.b _L6_6s
  1415. _L6_4s:
  1416. cmpi.b %d1,&QNAN # is operand a QNAN?
  1417. bne.b _L6_5s # no
  1418. bsr.l src_qnan # yes
  1419. bra.b _L6_6s
  1420. _L6_5s:
  1421. bsr.l satand # operand is a DENORM
  1422. _L6_6s:
  1423. #
  1424. # Result is now in FP0
  1425. #
  1426. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  1427. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  1428. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  1429. unlk %a6
  1430. rts
  1431. global _fatand_
  1432. _fatand_:
  1433. link %a6,&-LOCAL_SIZE
  1434. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  1435. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  1436. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  1437. fmov.l &0x0,%fpcr # zero FPCR
  1438. #
  1439. # copy, convert, and tag input argument
  1440. #
  1441. fmov.d 0x8(%a6),%fp0 # load dbl input
  1442. fmov.x %fp0,FP_SRC(%a6)
  1443. lea FP_SRC(%a6),%a0
  1444. bsr.l tag # fetch operand type
  1445. mov.b %d0,STAG(%a6)
  1446. mov.b %d0,%d1
  1447. andi.l &0x00ff00ff,USER_FPSR(%a6)
  1448. clr.l %d0
  1449. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  1450. mov.b %d1,STAG(%a6)
  1451. tst.b %d1
  1452. bne.b _L6_2d
  1453. bsr.l satan # operand is a NORM
  1454. bra.b _L6_6d
  1455. _L6_2d:
  1456. cmpi.b %d1,&ZERO # is operand a ZERO?
  1457. bne.b _L6_3d # no
  1458. bsr.l src_zero # yes
  1459. bra.b _L6_6d
  1460. _L6_3d:
  1461. cmpi.b %d1,&INF # is operand an INF?
  1462. bne.b _L6_4d # no
  1463. bsr.l spi_2 # yes
  1464. bra.b _L6_6d
  1465. _L6_4d:
  1466. cmpi.b %d1,&QNAN # is operand a QNAN?
  1467. bne.b _L6_5d # no
  1468. bsr.l src_qnan # yes
  1469. bra.b _L6_6d
  1470. _L6_5d:
  1471. bsr.l satand # operand is a DENORM
  1472. _L6_6d:
  1473. #
  1474. # Result is now in FP0
  1475. #
  1476. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  1477. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  1478. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  1479. unlk %a6
  1480. rts
  1481. global _fatanx_
  1482. _fatanx_:
  1483. link %a6,&-LOCAL_SIZE
  1484. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  1485. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  1486. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  1487. fmov.l &0x0,%fpcr # zero FPCR
  1488. #
  1489. # copy, convert, and tag input argument
  1490. #
  1491. lea FP_SRC(%a6),%a0
  1492. mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
  1493. mov.l 0x8+0x4(%a6),0x4(%a0)
  1494. mov.l 0x8+0x8(%a6),0x8(%a0)
  1495. bsr.l tag # fetch operand type
  1496. mov.b %d0,STAG(%a6)
  1497. mov.b %d0,%d1
  1498. andi.l &0x00ff00ff,USER_FPSR(%a6)
  1499. clr.l %d0
  1500. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  1501. tst.b %d1
  1502. bne.b _L6_2x
  1503. bsr.l satan # operand is a NORM
  1504. bra.b _L6_6x
  1505. _L6_2x:
  1506. cmpi.b %d1,&ZERO # is operand a ZERO?
  1507. bne.b _L6_3x # no
  1508. bsr.l src_zero # yes
  1509. bra.b _L6_6x
  1510. _L6_3x:
  1511. cmpi.b %d1,&INF # is operand an INF?
  1512. bne.b _L6_4x # no
  1513. bsr.l spi_2 # yes
  1514. bra.b _L6_6x
  1515. _L6_4x:
  1516. cmpi.b %d1,&QNAN # is operand a QNAN?
  1517. bne.b _L6_5x # no
  1518. bsr.l src_qnan # yes
  1519. bra.b _L6_6x
  1520. _L6_5x:
  1521. bsr.l satand # operand is a DENORM
  1522. _L6_6x:
  1523. #
  1524. # Result is now in FP0
  1525. #
  1526. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  1527. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  1528. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  1529. unlk %a6
  1530. rts
  1531. #########################################################################
  1532. # MONADIC TEMPLATE #
  1533. #########################################################################
  1534. global _fasins_
  1535. _fasins_:
  1536. link %a6,&-LOCAL_SIZE
  1537. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  1538. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  1539. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  1540. fmov.l &0x0,%fpcr # zero FPCR
  1541. #
  1542. # copy, convert, and tag input argument
  1543. #
  1544. fmov.s 0x8(%a6),%fp0 # load sgl input
  1545. fmov.x %fp0,FP_SRC(%a6)
  1546. lea FP_SRC(%a6),%a0
  1547. bsr.l tag # fetch operand type
  1548. mov.b %d0,STAG(%a6)
  1549. mov.b %d0,%d1
  1550. andi.l &0x00ff00ff,USER_FPSR(%a6)
  1551. clr.l %d0
  1552. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  1553. tst.b %d1
  1554. bne.b _L7_2s
  1555. bsr.l sasin # operand is a NORM
  1556. bra.b _L7_6s
  1557. _L7_2s:
  1558. cmpi.b %d1,&ZERO # is operand a ZERO?
  1559. bne.b _L7_3s # no
  1560. bsr.l src_zero # yes
  1561. bra.b _L7_6s
  1562. _L7_3s:
  1563. cmpi.b %d1,&INF # is operand an INF?
  1564. bne.b _L7_4s # no
  1565. bsr.l t_operr # yes
  1566. bra.b _L7_6s
  1567. _L7_4s:
  1568. cmpi.b %d1,&QNAN # is operand a QNAN?
  1569. bne.b _L7_5s # no
  1570. bsr.l src_qnan # yes
  1571. bra.b _L7_6s
  1572. _L7_5s:
  1573. bsr.l sasind # operand is a DENORM
  1574. _L7_6s:
  1575. #
  1576. # Result is now in FP0
  1577. #
  1578. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  1579. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  1580. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  1581. unlk %a6
  1582. rts
  1583. global _fasind_
  1584. _fasind_:
  1585. link %a6,&-LOCAL_SIZE
  1586. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  1587. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  1588. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  1589. fmov.l &0x0,%fpcr # zero FPCR
  1590. #
  1591. # copy, convert, and tag input argument
  1592. #
  1593. fmov.d 0x8(%a6),%fp0 # load dbl input
  1594. fmov.x %fp0,FP_SRC(%a6)
  1595. lea FP_SRC(%a6),%a0
  1596. bsr.l tag # fetch operand type
  1597. mov.b %d0,STAG(%a6)
  1598. mov.b %d0,%d1
  1599. andi.l &0x00ff00ff,USER_FPSR(%a6)
  1600. clr.l %d0
  1601. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  1602. mov.b %d1,STAG(%a6)
  1603. tst.b %d1
  1604. bne.b _L7_2d
  1605. bsr.l sasin # operand is a NORM
  1606. bra.b _L7_6d
  1607. _L7_2d:
  1608. cmpi.b %d1,&ZERO # is operand a ZERO?
  1609. bne.b _L7_3d # no
  1610. bsr.l src_zero # yes
  1611. bra.b _L7_6d
  1612. _L7_3d:
  1613. cmpi.b %d1,&INF # is operand an INF?
  1614. bne.b _L7_4d # no
  1615. bsr.l t_operr # yes
  1616. bra.b _L7_6d
  1617. _L7_4d:
  1618. cmpi.b %d1,&QNAN # is operand a QNAN?
  1619. bne.b _L7_5d # no
  1620. bsr.l src_qnan # yes
  1621. bra.b _L7_6d
  1622. _L7_5d:
  1623. bsr.l sasind # operand is a DENORM
  1624. _L7_6d:
  1625. #
  1626. # Result is now in FP0
  1627. #
  1628. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  1629. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  1630. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  1631. unlk %a6
  1632. rts
  1633. global _fasinx_
  1634. _fasinx_:
  1635. link %a6,&-LOCAL_SIZE
  1636. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  1637. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  1638. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  1639. fmov.l &0x0,%fpcr # zero FPCR
  1640. #
  1641. # copy, convert, and tag input argument
  1642. #
  1643. lea FP_SRC(%a6),%a0
  1644. mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
  1645. mov.l 0x8+0x4(%a6),0x4(%a0)
  1646. mov.l 0x8+0x8(%a6),0x8(%a0)
  1647. bsr.l tag # fetch operand type
  1648. mov.b %d0,STAG(%a6)
  1649. mov.b %d0,%d1
  1650. andi.l &0x00ff00ff,USER_FPSR(%a6)
  1651. clr.l %d0
  1652. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  1653. tst.b %d1
  1654. bne.b _L7_2x
  1655. bsr.l sasin # operand is a NORM
  1656. bra.b _L7_6x
  1657. _L7_2x:
  1658. cmpi.b %d1,&ZERO # is operand a ZERO?
  1659. bne.b _L7_3x # no
  1660. bsr.l src_zero # yes
  1661. bra.b _L7_6x
  1662. _L7_3x:
  1663. cmpi.b %d1,&INF # is operand an INF?
  1664. bne.b _L7_4x # no
  1665. bsr.l t_operr # yes
  1666. bra.b _L7_6x
  1667. _L7_4x:
  1668. cmpi.b %d1,&QNAN # is operand a QNAN?
  1669. bne.b _L7_5x # no
  1670. bsr.l src_qnan # yes
  1671. bra.b _L7_6x
  1672. _L7_5x:
  1673. bsr.l sasind # operand is a DENORM
  1674. _L7_6x:
  1675. #
  1676. # Result is now in FP0
  1677. #
  1678. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  1679. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  1680. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  1681. unlk %a6
  1682. rts
  1683. #########################################################################
  1684. # MONADIC TEMPLATE #
  1685. #########################################################################
  1686. global _fatanhs_
  1687. _fatanhs_:
  1688. link %a6,&-LOCAL_SIZE
  1689. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  1690. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  1691. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  1692. fmov.l &0x0,%fpcr # zero FPCR
  1693. #
  1694. # copy, convert, and tag input argument
  1695. #
  1696. fmov.s 0x8(%a6),%fp0 # load sgl input
  1697. fmov.x %fp0,FP_SRC(%a6)
  1698. lea FP_SRC(%a6),%a0
  1699. bsr.l tag # fetch operand type
  1700. mov.b %d0,STAG(%a6)
  1701. mov.b %d0,%d1
  1702. andi.l &0x00ff00ff,USER_FPSR(%a6)
  1703. clr.l %d0
  1704. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  1705. tst.b %d1
  1706. bne.b _L8_2s
  1707. bsr.l satanh # operand is a NORM
  1708. bra.b _L8_6s
  1709. _L8_2s:
  1710. cmpi.b %d1,&ZERO # is operand a ZERO?
  1711. bne.b _L8_3s # no
  1712. bsr.l src_zero # yes
  1713. bra.b _L8_6s
  1714. _L8_3s:
  1715. cmpi.b %d1,&INF # is operand an INF?
  1716. bne.b _L8_4s # no
  1717. bsr.l t_operr # yes
  1718. bra.b _L8_6s
  1719. _L8_4s:
  1720. cmpi.b %d1,&QNAN # is operand a QNAN?
  1721. bne.b _L8_5s # no
  1722. bsr.l src_qnan # yes
  1723. bra.b _L8_6s
  1724. _L8_5s:
  1725. bsr.l satanhd # operand is a DENORM
  1726. _L8_6s:
  1727. #
  1728. # Result is now in FP0
  1729. #
  1730. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  1731. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  1732. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  1733. unlk %a6
  1734. rts
  1735. global _fatanhd_
  1736. _fatanhd_:
  1737. link %a6,&-LOCAL_SIZE
  1738. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  1739. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  1740. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  1741. fmov.l &0x0,%fpcr # zero FPCR
  1742. #
  1743. # copy, convert, and tag input argument
  1744. #
  1745. fmov.d 0x8(%a6),%fp0 # load dbl input
  1746. fmov.x %fp0,FP_SRC(%a6)
  1747. lea FP_SRC(%a6),%a0
  1748. bsr.l tag # fetch operand type
  1749. mov.b %d0,STAG(%a6)
  1750. mov.b %d0,%d1
  1751. andi.l &0x00ff00ff,USER_FPSR(%a6)
  1752. clr.l %d0
  1753. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  1754. mov.b %d1,STAG(%a6)
  1755. tst.b %d1
  1756. bne.b _L8_2d
  1757. bsr.l satanh # operand is a NORM
  1758. bra.b _L8_6d
  1759. _L8_2d:
  1760. cmpi.b %d1,&ZERO # is operand a ZERO?
  1761. bne.b _L8_3d # no
  1762. bsr.l src_zero # yes
  1763. bra.b _L8_6d
  1764. _L8_3d:
  1765. cmpi.b %d1,&INF # is operand an INF?
  1766. bne.b _L8_4d # no
  1767. bsr.l t_operr # yes
  1768. bra.b _L8_6d
  1769. _L8_4d:
  1770. cmpi.b %d1,&QNAN # is operand a QNAN?
  1771. bne.b _L8_5d # no
  1772. bsr.l src_qnan # yes
  1773. bra.b _L8_6d
  1774. _L8_5d:
  1775. bsr.l satanhd # operand is a DENORM
  1776. _L8_6d:
  1777. #
  1778. # Result is now in FP0
  1779. #
  1780. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  1781. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  1782. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  1783. unlk %a6
  1784. rts
  1785. global _fatanhx_
  1786. _fatanhx_:
  1787. link %a6,&-LOCAL_SIZE
  1788. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  1789. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  1790. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  1791. fmov.l &0x0,%fpcr # zero FPCR
  1792. #
  1793. # copy, convert, and tag input argument
  1794. #
  1795. lea FP_SRC(%a6),%a0
  1796. mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
  1797. mov.l 0x8+0x4(%a6),0x4(%a0)
  1798. mov.l 0x8+0x8(%a6),0x8(%a0)
  1799. bsr.l tag # fetch operand type
  1800. mov.b %d0,STAG(%a6)
  1801. mov.b %d0,%d1
  1802. andi.l &0x00ff00ff,USER_FPSR(%a6)
  1803. clr.l %d0
  1804. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  1805. tst.b %d1
  1806. bne.b _L8_2x
  1807. bsr.l satanh # operand is a NORM
  1808. bra.b _L8_6x
  1809. _L8_2x:
  1810. cmpi.b %d1,&ZERO # is operand a ZERO?
  1811. bne.b _L8_3x # no
  1812. bsr.l src_zero # yes
  1813. bra.b _L8_6x
  1814. _L8_3x:
  1815. cmpi.b %d1,&INF # is operand an INF?
  1816. bne.b _L8_4x # no
  1817. bsr.l t_operr # yes
  1818. bra.b _L8_6x
  1819. _L8_4x:
  1820. cmpi.b %d1,&QNAN # is operand a QNAN?
  1821. bne.b _L8_5x # no
  1822. bsr.l src_qnan # yes
  1823. bra.b _L8_6x
  1824. _L8_5x:
  1825. bsr.l satanhd # operand is a DENORM
  1826. _L8_6x:
  1827. #
  1828. # Result is now in FP0
  1829. #
  1830. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  1831. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  1832. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  1833. unlk %a6
  1834. rts
  1835. #########################################################################
  1836. # MONADIC TEMPLATE #
  1837. #########################################################################
  1838. global _ftans_
  1839. _ftans_:
  1840. link %a6,&-LOCAL_SIZE
  1841. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  1842. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  1843. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  1844. fmov.l &0x0,%fpcr # zero FPCR
  1845. #
  1846. # copy, convert, and tag input argument
  1847. #
  1848. fmov.s 0x8(%a6),%fp0 # load sgl input
  1849. fmov.x %fp0,FP_SRC(%a6)
  1850. lea FP_SRC(%a6),%a0
  1851. bsr.l tag # fetch operand type
  1852. mov.b %d0,STAG(%a6)
  1853. mov.b %d0,%d1
  1854. andi.l &0x00ff00ff,USER_FPSR(%a6)
  1855. clr.l %d0
  1856. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  1857. tst.b %d1
  1858. bne.b _L9_2s
  1859. bsr.l stan # operand is a NORM
  1860. bra.b _L9_6s
  1861. _L9_2s:
  1862. cmpi.b %d1,&ZERO # is operand a ZERO?
  1863. bne.b _L9_3s # no
  1864. bsr.l src_zero # yes
  1865. bra.b _L9_6s
  1866. _L9_3s:
  1867. cmpi.b %d1,&INF # is operand an INF?
  1868. bne.b _L9_4s # no
  1869. bsr.l t_operr # yes
  1870. bra.b _L9_6s
  1871. _L9_4s:
  1872. cmpi.b %d1,&QNAN # is operand a QNAN?
  1873. bne.b _L9_5s # no
  1874. bsr.l src_qnan # yes
  1875. bra.b _L9_6s
  1876. _L9_5s:
  1877. bsr.l stand # operand is a DENORM
  1878. _L9_6s:
  1879. #
  1880. # Result is now in FP0
  1881. #
  1882. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  1883. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  1884. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  1885. unlk %a6
  1886. rts
  1887. global _ftand_
  1888. _ftand_:
  1889. link %a6,&-LOCAL_SIZE
  1890. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  1891. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  1892. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  1893. fmov.l &0x0,%fpcr # zero FPCR
  1894. #
  1895. # copy, convert, and tag input argument
  1896. #
  1897. fmov.d 0x8(%a6),%fp0 # load dbl input
  1898. fmov.x %fp0,FP_SRC(%a6)
  1899. lea FP_SRC(%a6),%a0
  1900. bsr.l tag # fetch operand type
  1901. mov.b %d0,STAG(%a6)
  1902. mov.b %d0,%d1
  1903. andi.l &0x00ff00ff,USER_FPSR(%a6)
  1904. clr.l %d0
  1905. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  1906. mov.b %d1,STAG(%a6)
  1907. tst.b %d1
  1908. bne.b _L9_2d
  1909. bsr.l stan # operand is a NORM
  1910. bra.b _L9_6d
  1911. _L9_2d:
  1912. cmpi.b %d1,&ZERO # is operand a ZERO?
  1913. bne.b _L9_3d # no
  1914. bsr.l src_zero # yes
  1915. bra.b _L9_6d
  1916. _L9_3d:
  1917. cmpi.b %d1,&INF # is operand an INF?
  1918. bne.b _L9_4d # no
  1919. bsr.l t_operr # yes
  1920. bra.b _L9_6d
  1921. _L9_4d:
  1922. cmpi.b %d1,&QNAN # is operand a QNAN?
  1923. bne.b _L9_5d # no
  1924. bsr.l src_qnan # yes
  1925. bra.b _L9_6d
  1926. _L9_5d:
  1927. bsr.l stand # operand is a DENORM
  1928. _L9_6d:
  1929. #
  1930. # Result is now in FP0
  1931. #
  1932. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  1933. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  1934. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  1935. unlk %a6
  1936. rts
  1937. global _ftanx_
  1938. _ftanx_:
  1939. link %a6,&-LOCAL_SIZE
  1940. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  1941. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  1942. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  1943. fmov.l &0x0,%fpcr # zero FPCR
  1944. #
  1945. # copy, convert, and tag input argument
  1946. #
  1947. lea FP_SRC(%a6),%a0
  1948. mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
  1949. mov.l 0x8+0x4(%a6),0x4(%a0)
  1950. mov.l 0x8+0x8(%a6),0x8(%a0)
  1951. bsr.l tag # fetch operand type
  1952. mov.b %d0,STAG(%a6)
  1953. mov.b %d0,%d1
  1954. andi.l &0x00ff00ff,USER_FPSR(%a6)
  1955. clr.l %d0
  1956. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  1957. tst.b %d1
  1958. bne.b _L9_2x
  1959. bsr.l stan # operand is a NORM
  1960. bra.b _L9_6x
  1961. _L9_2x:
  1962. cmpi.b %d1,&ZERO # is operand a ZERO?
  1963. bne.b _L9_3x # no
  1964. bsr.l src_zero # yes
  1965. bra.b _L9_6x
  1966. _L9_3x:
  1967. cmpi.b %d1,&INF # is operand an INF?
  1968. bne.b _L9_4x # no
  1969. bsr.l t_operr # yes
  1970. bra.b _L9_6x
  1971. _L9_4x:
  1972. cmpi.b %d1,&QNAN # is operand a QNAN?
  1973. bne.b _L9_5x # no
  1974. bsr.l src_qnan # yes
  1975. bra.b _L9_6x
  1976. _L9_5x:
  1977. bsr.l stand # operand is a DENORM
  1978. _L9_6x:
  1979. #
  1980. # Result is now in FP0
  1981. #
  1982. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  1983. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  1984. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  1985. unlk %a6
  1986. rts
  1987. #########################################################################
  1988. # MONADIC TEMPLATE #
  1989. #########################################################################
  1990. global _fetoxs_
  1991. _fetoxs_:
  1992. link %a6,&-LOCAL_SIZE
  1993. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  1994. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  1995. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  1996. fmov.l &0x0,%fpcr # zero FPCR
  1997. #
  1998. # copy, convert, and tag input argument
  1999. #
  2000. fmov.s 0x8(%a6),%fp0 # load sgl input
  2001. fmov.x %fp0,FP_SRC(%a6)
  2002. lea FP_SRC(%a6),%a0
  2003. bsr.l tag # fetch operand type
  2004. mov.b %d0,STAG(%a6)
  2005. mov.b %d0,%d1
  2006. andi.l &0x00ff00ff,USER_FPSR(%a6)
  2007. clr.l %d0
  2008. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  2009. tst.b %d1
  2010. bne.b _L10_2s
  2011. bsr.l setox # operand is a NORM
  2012. bra.b _L10_6s
  2013. _L10_2s:
  2014. cmpi.b %d1,&ZERO # is operand a ZERO?
  2015. bne.b _L10_3s # no
  2016. bsr.l ld_pone # yes
  2017. bra.b _L10_6s
  2018. _L10_3s:
  2019. cmpi.b %d1,&INF # is operand an INF?
  2020. bne.b _L10_4s # no
  2021. bsr.l szr_inf # yes
  2022. bra.b _L10_6s
  2023. _L10_4s:
  2024. cmpi.b %d1,&QNAN # is operand a QNAN?
  2025. bne.b _L10_5s # no
  2026. bsr.l src_qnan # yes
  2027. bra.b _L10_6s
  2028. _L10_5s:
  2029. bsr.l setoxd # operand is a DENORM
  2030. _L10_6s:
  2031. #
  2032. # Result is now in FP0
  2033. #
  2034. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  2035. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  2036. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  2037. unlk %a6
  2038. rts
  2039. global _fetoxd_
  2040. _fetoxd_:
  2041. link %a6,&-LOCAL_SIZE
  2042. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  2043. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  2044. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  2045. fmov.l &0x0,%fpcr # zero FPCR
  2046. #
  2047. # copy, convert, and tag input argument
  2048. #
  2049. fmov.d 0x8(%a6),%fp0 # load dbl input
  2050. fmov.x %fp0,FP_SRC(%a6)
  2051. lea FP_SRC(%a6),%a0
  2052. bsr.l tag # fetch operand type
  2053. mov.b %d0,STAG(%a6)
  2054. mov.b %d0,%d1
  2055. andi.l &0x00ff00ff,USER_FPSR(%a6)
  2056. clr.l %d0
  2057. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  2058. mov.b %d1,STAG(%a6)
  2059. tst.b %d1
  2060. bne.b _L10_2d
  2061. bsr.l setox # operand is a NORM
  2062. bra.b _L10_6d
  2063. _L10_2d:
  2064. cmpi.b %d1,&ZERO # is operand a ZERO?
  2065. bne.b _L10_3d # no
  2066. bsr.l ld_pone # yes
  2067. bra.b _L10_6d
  2068. _L10_3d:
  2069. cmpi.b %d1,&INF # is operand an INF?
  2070. bne.b _L10_4d # no
  2071. bsr.l szr_inf # yes
  2072. bra.b _L10_6d
  2073. _L10_4d:
  2074. cmpi.b %d1,&QNAN # is operand a QNAN?
  2075. bne.b _L10_5d # no
  2076. bsr.l src_qnan # yes
  2077. bra.b _L10_6d
  2078. _L10_5d:
  2079. bsr.l setoxd # operand is a DENORM
  2080. _L10_6d:
  2081. #
  2082. # Result is now in FP0
  2083. #
  2084. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  2085. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  2086. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  2087. unlk %a6
  2088. rts
  2089. global _fetoxx_
  2090. _fetoxx_:
  2091. link %a6,&-LOCAL_SIZE
  2092. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  2093. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  2094. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  2095. fmov.l &0x0,%fpcr # zero FPCR
  2096. #
  2097. # copy, convert, and tag input argument
  2098. #
  2099. lea FP_SRC(%a6),%a0
  2100. mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
  2101. mov.l 0x8+0x4(%a6),0x4(%a0)
  2102. mov.l 0x8+0x8(%a6),0x8(%a0)
  2103. bsr.l tag # fetch operand type
  2104. mov.b %d0,STAG(%a6)
  2105. mov.b %d0,%d1
  2106. andi.l &0x00ff00ff,USER_FPSR(%a6)
  2107. clr.l %d0
  2108. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  2109. tst.b %d1
  2110. bne.b _L10_2x
  2111. bsr.l setox # operand is a NORM
  2112. bra.b _L10_6x
  2113. _L10_2x:
  2114. cmpi.b %d1,&ZERO # is operand a ZERO?
  2115. bne.b _L10_3x # no
  2116. bsr.l ld_pone # yes
  2117. bra.b _L10_6x
  2118. _L10_3x:
  2119. cmpi.b %d1,&INF # is operand an INF?
  2120. bne.b _L10_4x # no
  2121. bsr.l szr_inf # yes
  2122. bra.b _L10_6x
  2123. _L10_4x:
  2124. cmpi.b %d1,&QNAN # is operand a QNAN?
  2125. bne.b _L10_5x # no
  2126. bsr.l src_qnan # yes
  2127. bra.b _L10_6x
  2128. _L10_5x:
  2129. bsr.l setoxd # operand is a DENORM
  2130. _L10_6x:
  2131. #
  2132. # Result is now in FP0
  2133. #
  2134. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  2135. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  2136. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  2137. unlk %a6
  2138. rts
  2139. #########################################################################
  2140. # MONADIC TEMPLATE #
  2141. #########################################################################
  2142. global _ftwotoxs_
  2143. _ftwotoxs_:
  2144. link %a6,&-LOCAL_SIZE
  2145. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  2146. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  2147. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  2148. fmov.l &0x0,%fpcr # zero FPCR
  2149. #
  2150. # copy, convert, and tag input argument
  2151. #
  2152. fmov.s 0x8(%a6),%fp0 # load sgl input
  2153. fmov.x %fp0,FP_SRC(%a6)
  2154. lea FP_SRC(%a6),%a0
  2155. bsr.l tag # fetch operand type
  2156. mov.b %d0,STAG(%a6)
  2157. mov.b %d0,%d1
  2158. andi.l &0x00ff00ff,USER_FPSR(%a6)
  2159. clr.l %d0
  2160. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  2161. tst.b %d1
  2162. bne.b _L11_2s
  2163. bsr.l stwotox # operand is a NORM
  2164. bra.b _L11_6s
  2165. _L11_2s:
  2166. cmpi.b %d1,&ZERO # is operand a ZERO?
  2167. bne.b _L11_3s # no
  2168. bsr.l ld_pone # yes
  2169. bra.b _L11_6s
  2170. _L11_3s:
  2171. cmpi.b %d1,&INF # is operand an INF?
  2172. bne.b _L11_4s # no
  2173. bsr.l szr_inf # yes
  2174. bra.b _L11_6s
  2175. _L11_4s:
  2176. cmpi.b %d1,&QNAN # is operand a QNAN?
  2177. bne.b _L11_5s # no
  2178. bsr.l src_qnan # yes
  2179. bra.b _L11_6s
  2180. _L11_5s:
  2181. bsr.l stwotoxd # operand is a DENORM
  2182. _L11_6s:
  2183. #
  2184. # Result is now in FP0
  2185. #
  2186. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  2187. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  2188. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  2189. unlk %a6
  2190. rts
  2191. global _ftwotoxd_
  2192. _ftwotoxd_:
  2193. link %a6,&-LOCAL_SIZE
  2194. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  2195. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  2196. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  2197. fmov.l &0x0,%fpcr # zero FPCR
  2198. #
  2199. # copy, convert, and tag input argument
  2200. #
  2201. fmov.d 0x8(%a6),%fp0 # load dbl input
  2202. fmov.x %fp0,FP_SRC(%a6)
  2203. lea FP_SRC(%a6),%a0
  2204. bsr.l tag # fetch operand type
  2205. mov.b %d0,STAG(%a6)
  2206. mov.b %d0,%d1
  2207. andi.l &0x00ff00ff,USER_FPSR(%a6)
  2208. clr.l %d0
  2209. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  2210. mov.b %d1,STAG(%a6)
  2211. tst.b %d1
  2212. bne.b _L11_2d
  2213. bsr.l stwotox # operand is a NORM
  2214. bra.b _L11_6d
  2215. _L11_2d:
  2216. cmpi.b %d1,&ZERO # is operand a ZERO?
  2217. bne.b _L11_3d # no
  2218. bsr.l ld_pone # yes
  2219. bra.b _L11_6d
  2220. _L11_3d:
  2221. cmpi.b %d1,&INF # is operand an INF?
  2222. bne.b _L11_4d # no
  2223. bsr.l szr_inf # yes
  2224. bra.b _L11_6d
  2225. _L11_4d:
  2226. cmpi.b %d1,&QNAN # is operand a QNAN?
  2227. bne.b _L11_5d # no
  2228. bsr.l src_qnan # yes
  2229. bra.b _L11_6d
  2230. _L11_5d:
  2231. bsr.l stwotoxd # operand is a DENORM
  2232. _L11_6d:
  2233. #
  2234. # Result is now in FP0
  2235. #
  2236. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  2237. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  2238. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  2239. unlk %a6
  2240. rts
  2241. global _ftwotoxx_
  2242. _ftwotoxx_:
  2243. link %a6,&-LOCAL_SIZE
  2244. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  2245. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  2246. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  2247. fmov.l &0x0,%fpcr # zero FPCR
  2248. #
  2249. # copy, convert, and tag input argument
  2250. #
  2251. lea FP_SRC(%a6),%a0
  2252. mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
  2253. mov.l 0x8+0x4(%a6),0x4(%a0)
  2254. mov.l 0x8+0x8(%a6),0x8(%a0)
  2255. bsr.l tag # fetch operand type
  2256. mov.b %d0,STAG(%a6)
  2257. mov.b %d0,%d1
  2258. andi.l &0x00ff00ff,USER_FPSR(%a6)
  2259. clr.l %d0
  2260. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  2261. tst.b %d1
  2262. bne.b _L11_2x
  2263. bsr.l stwotox # operand is a NORM
  2264. bra.b _L11_6x
  2265. _L11_2x:
  2266. cmpi.b %d1,&ZERO # is operand a ZERO?
  2267. bne.b _L11_3x # no
  2268. bsr.l ld_pone # yes
  2269. bra.b _L11_6x
  2270. _L11_3x:
  2271. cmpi.b %d1,&INF # is operand an INF?
  2272. bne.b _L11_4x # no
  2273. bsr.l szr_inf # yes
  2274. bra.b _L11_6x
  2275. _L11_4x:
  2276. cmpi.b %d1,&QNAN # is operand a QNAN?
  2277. bne.b _L11_5x # no
  2278. bsr.l src_qnan # yes
  2279. bra.b _L11_6x
  2280. _L11_5x:
  2281. bsr.l stwotoxd # operand is a DENORM
  2282. _L11_6x:
  2283. #
  2284. # Result is now in FP0
  2285. #
  2286. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  2287. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  2288. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  2289. unlk %a6
  2290. rts
  2291. #########################################################################
  2292. # MONADIC TEMPLATE #
  2293. #########################################################################
  2294. global _ftentoxs_
  2295. _ftentoxs_:
  2296. link %a6,&-LOCAL_SIZE
  2297. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  2298. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  2299. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  2300. fmov.l &0x0,%fpcr # zero FPCR
  2301. #
  2302. # copy, convert, and tag input argument
  2303. #
  2304. fmov.s 0x8(%a6),%fp0 # load sgl input
  2305. fmov.x %fp0,FP_SRC(%a6)
  2306. lea FP_SRC(%a6),%a0
  2307. bsr.l tag # fetch operand type
  2308. mov.b %d0,STAG(%a6)
  2309. mov.b %d0,%d1
  2310. andi.l &0x00ff00ff,USER_FPSR(%a6)
  2311. clr.l %d0
  2312. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  2313. tst.b %d1
  2314. bne.b _L12_2s
  2315. bsr.l stentox # operand is a NORM
  2316. bra.b _L12_6s
  2317. _L12_2s:
  2318. cmpi.b %d1,&ZERO # is operand a ZERO?
  2319. bne.b _L12_3s # no
  2320. bsr.l ld_pone # yes
  2321. bra.b _L12_6s
  2322. _L12_3s:
  2323. cmpi.b %d1,&INF # is operand an INF?
  2324. bne.b _L12_4s # no
  2325. bsr.l szr_inf # yes
  2326. bra.b _L12_6s
  2327. _L12_4s:
  2328. cmpi.b %d1,&QNAN # is operand a QNAN?
  2329. bne.b _L12_5s # no
  2330. bsr.l src_qnan # yes
  2331. bra.b _L12_6s
  2332. _L12_5s:
  2333. bsr.l stentoxd # operand is a DENORM
  2334. _L12_6s:
  2335. #
  2336. # Result is now in FP0
  2337. #
  2338. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  2339. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  2340. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  2341. unlk %a6
  2342. rts
  2343. global _ftentoxd_
  2344. _ftentoxd_:
  2345. link %a6,&-LOCAL_SIZE
  2346. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  2347. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  2348. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  2349. fmov.l &0x0,%fpcr # zero FPCR
  2350. #
  2351. # copy, convert, and tag input argument
  2352. #
  2353. fmov.d 0x8(%a6),%fp0 # load dbl input
  2354. fmov.x %fp0,FP_SRC(%a6)
  2355. lea FP_SRC(%a6),%a0
  2356. bsr.l tag # fetch operand type
  2357. mov.b %d0,STAG(%a6)
  2358. mov.b %d0,%d1
  2359. andi.l &0x00ff00ff,USER_FPSR(%a6)
  2360. clr.l %d0
  2361. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  2362. mov.b %d1,STAG(%a6)
  2363. tst.b %d1
  2364. bne.b _L12_2d
  2365. bsr.l stentox # operand is a NORM
  2366. bra.b _L12_6d
  2367. _L12_2d:
  2368. cmpi.b %d1,&ZERO # is operand a ZERO?
  2369. bne.b _L12_3d # no
  2370. bsr.l ld_pone # yes
  2371. bra.b _L12_6d
  2372. _L12_3d:
  2373. cmpi.b %d1,&INF # is operand an INF?
  2374. bne.b _L12_4d # no
  2375. bsr.l szr_inf # yes
  2376. bra.b _L12_6d
  2377. _L12_4d:
  2378. cmpi.b %d1,&QNAN # is operand a QNAN?
  2379. bne.b _L12_5d # no
  2380. bsr.l src_qnan # yes
  2381. bra.b _L12_6d
  2382. _L12_5d:
  2383. bsr.l stentoxd # operand is a DENORM
  2384. _L12_6d:
  2385. #
  2386. # Result is now in FP0
  2387. #
  2388. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  2389. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  2390. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  2391. unlk %a6
  2392. rts
  2393. global _ftentoxx_
  2394. _ftentoxx_:
  2395. link %a6,&-LOCAL_SIZE
  2396. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  2397. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  2398. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  2399. fmov.l &0x0,%fpcr # zero FPCR
  2400. #
  2401. # copy, convert, and tag input argument
  2402. #
  2403. lea FP_SRC(%a6),%a0
  2404. mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
  2405. mov.l 0x8+0x4(%a6),0x4(%a0)
  2406. mov.l 0x8+0x8(%a6),0x8(%a0)
  2407. bsr.l tag # fetch operand type
  2408. mov.b %d0,STAG(%a6)
  2409. mov.b %d0,%d1
  2410. andi.l &0x00ff00ff,USER_FPSR(%a6)
  2411. clr.l %d0
  2412. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  2413. tst.b %d1
  2414. bne.b _L12_2x
  2415. bsr.l stentox # operand is a NORM
  2416. bra.b _L12_6x
  2417. _L12_2x:
  2418. cmpi.b %d1,&ZERO # is operand a ZERO?
  2419. bne.b _L12_3x # no
  2420. bsr.l ld_pone # yes
  2421. bra.b _L12_6x
  2422. _L12_3x:
  2423. cmpi.b %d1,&INF # is operand an INF?
  2424. bne.b _L12_4x # no
  2425. bsr.l szr_inf # yes
  2426. bra.b _L12_6x
  2427. _L12_4x:
  2428. cmpi.b %d1,&QNAN # is operand a QNAN?
  2429. bne.b _L12_5x # no
  2430. bsr.l src_qnan # yes
  2431. bra.b _L12_6x
  2432. _L12_5x:
  2433. bsr.l stentoxd # operand is a DENORM
  2434. _L12_6x:
  2435. #
  2436. # Result is now in FP0
  2437. #
  2438. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  2439. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  2440. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  2441. unlk %a6
  2442. rts
  2443. #########################################################################
  2444. # MONADIC TEMPLATE #
  2445. #########################################################################
  2446. global _flogns_
  2447. _flogns_:
  2448. link %a6,&-LOCAL_SIZE
  2449. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  2450. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  2451. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  2452. fmov.l &0x0,%fpcr # zero FPCR
  2453. #
  2454. # copy, convert, and tag input argument
  2455. #
  2456. fmov.s 0x8(%a6),%fp0 # load sgl input
  2457. fmov.x %fp0,FP_SRC(%a6)
  2458. lea FP_SRC(%a6),%a0
  2459. bsr.l tag # fetch operand type
  2460. mov.b %d0,STAG(%a6)
  2461. mov.b %d0,%d1
  2462. andi.l &0x00ff00ff,USER_FPSR(%a6)
  2463. clr.l %d0
  2464. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  2465. tst.b %d1
  2466. bne.b _L13_2s
  2467. bsr.l slogn # operand is a NORM
  2468. bra.b _L13_6s
  2469. _L13_2s:
  2470. cmpi.b %d1,&ZERO # is operand a ZERO?
  2471. bne.b _L13_3s # no
  2472. bsr.l t_dz2 # yes
  2473. bra.b _L13_6s
  2474. _L13_3s:
  2475. cmpi.b %d1,&INF # is operand an INF?
  2476. bne.b _L13_4s # no
  2477. bsr.l sopr_inf # yes
  2478. bra.b _L13_6s
  2479. _L13_4s:
  2480. cmpi.b %d1,&QNAN # is operand a QNAN?
  2481. bne.b _L13_5s # no
  2482. bsr.l src_qnan # yes
  2483. bra.b _L13_6s
  2484. _L13_5s:
  2485. bsr.l slognd # operand is a DENORM
  2486. _L13_6s:
  2487. #
  2488. # Result is now in FP0
  2489. #
  2490. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  2491. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  2492. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  2493. unlk %a6
  2494. rts
  2495. global _flognd_
  2496. _flognd_:
  2497. link %a6,&-LOCAL_SIZE
  2498. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  2499. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  2500. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  2501. fmov.l &0x0,%fpcr # zero FPCR
  2502. #
  2503. # copy, convert, and tag input argument
  2504. #
  2505. fmov.d 0x8(%a6),%fp0 # load dbl input
  2506. fmov.x %fp0,FP_SRC(%a6)
  2507. lea FP_SRC(%a6),%a0
  2508. bsr.l tag # fetch operand type
  2509. mov.b %d0,STAG(%a6)
  2510. mov.b %d0,%d1
  2511. andi.l &0x00ff00ff,USER_FPSR(%a6)
  2512. clr.l %d0
  2513. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  2514. mov.b %d1,STAG(%a6)
  2515. tst.b %d1
  2516. bne.b _L13_2d
  2517. bsr.l slogn # operand is a NORM
  2518. bra.b _L13_6d
  2519. _L13_2d:
  2520. cmpi.b %d1,&ZERO # is operand a ZERO?
  2521. bne.b _L13_3d # no
  2522. bsr.l t_dz2 # yes
  2523. bra.b _L13_6d
  2524. _L13_3d:
  2525. cmpi.b %d1,&INF # is operand an INF?
  2526. bne.b _L13_4d # no
  2527. bsr.l sopr_inf # yes
  2528. bra.b _L13_6d
  2529. _L13_4d:
  2530. cmpi.b %d1,&QNAN # is operand a QNAN?
  2531. bne.b _L13_5d # no
  2532. bsr.l src_qnan # yes
  2533. bra.b _L13_6d
  2534. _L13_5d:
  2535. bsr.l slognd # operand is a DENORM
  2536. _L13_6d:
  2537. #
  2538. # Result is now in FP0
  2539. #
  2540. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  2541. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  2542. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  2543. unlk %a6
  2544. rts
  2545. global _flognx_
  2546. _flognx_:
  2547. link %a6,&-LOCAL_SIZE
  2548. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  2549. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  2550. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  2551. fmov.l &0x0,%fpcr # zero FPCR
  2552. #
  2553. # copy, convert, and tag input argument
  2554. #
  2555. lea FP_SRC(%a6),%a0
  2556. mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
  2557. mov.l 0x8+0x4(%a6),0x4(%a0)
  2558. mov.l 0x8+0x8(%a6),0x8(%a0)
  2559. bsr.l tag # fetch operand type
  2560. mov.b %d0,STAG(%a6)
  2561. mov.b %d0,%d1
  2562. andi.l &0x00ff00ff,USER_FPSR(%a6)
  2563. clr.l %d0
  2564. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  2565. tst.b %d1
  2566. bne.b _L13_2x
  2567. bsr.l slogn # operand is a NORM
  2568. bra.b _L13_6x
  2569. _L13_2x:
  2570. cmpi.b %d1,&ZERO # is operand a ZERO?
  2571. bne.b _L13_3x # no
  2572. bsr.l t_dz2 # yes
  2573. bra.b _L13_6x
  2574. _L13_3x:
  2575. cmpi.b %d1,&INF # is operand an INF?
  2576. bne.b _L13_4x # no
  2577. bsr.l sopr_inf # yes
  2578. bra.b _L13_6x
  2579. _L13_4x:
  2580. cmpi.b %d1,&QNAN # is operand a QNAN?
  2581. bne.b _L13_5x # no
  2582. bsr.l src_qnan # yes
  2583. bra.b _L13_6x
  2584. _L13_5x:
  2585. bsr.l slognd # operand is a DENORM
  2586. _L13_6x:
  2587. #
  2588. # Result is now in FP0
  2589. #
  2590. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  2591. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  2592. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  2593. unlk %a6
  2594. rts
  2595. #########################################################################
  2596. # MONADIC TEMPLATE #
  2597. #########################################################################
  2598. global _flog10s_
  2599. _flog10s_:
  2600. link %a6,&-LOCAL_SIZE
  2601. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  2602. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  2603. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  2604. fmov.l &0x0,%fpcr # zero FPCR
  2605. #
  2606. # copy, convert, and tag input argument
  2607. #
  2608. fmov.s 0x8(%a6),%fp0 # load sgl input
  2609. fmov.x %fp0,FP_SRC(%a6)
  2610. lea FP_SRC(%a6),%a0
  2611. bsr.l tag # fetch operand type
  2612. mov.b %d0,STAG(%a6)
  2613. mov.b %d0,%d1
  2614. andi.l &0x00ff00ff,USER_FPSR(%a6)
  2615. clr.l %d0
  2616. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  2617. tst.b %d1
  2618. bne.b _L14_2s
  2619. bsr.l slog10 # operand is a NORM
  2620. bra.b _L14_6s
  2621. _L14_2s:
  2622. cmpi.b %d1,&ZERO # is operand a ZERO?
  2623. bne.b _L14_3s # no
  2624. bsr.l t_dz2 # yes
  2625. bra.b _L14_6s
  2626. _L14_3s:
  2627. cmpi.b %d1,&INF # is operand an INF?
  2628. bne.b _L14_4s # no
  2629. bsr.l sopr_inf # yes
  2630. bra.b _L14_6s
  2631. _L14_4s:
  2632. cmpi.b %d1,&QNAN # is operand a QNAN?
  2633. bne.b _L14_5s # no
  2634. bsr.l src_qnan # yes
  2635. bra.b _L14_6s
  2636. _L14_5s:
  2637. bsr.l slog10d # operand is a DENORM
  2638. _L14_6s:
  2639. #
  2640. # Result is now in FP0
  2641. #
  2642. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  2643. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  2644. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  2645. unlk %a6
  2646. rts
  2647. global _flog10d_
  2648. _flog10d_:
  2649. link %a6,&-LOCAL_SIZE
  2650. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  2651. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  2652. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  2653. fmov.l &0x0,%fpcr # zero FPCR
  2654. #
  2655. # copy, convert, and tag input argument
  2656. #
  2657. fmov.d 0x8(%a6),%fp0 # load dbl input
  2658. fmov.x %fp0,FP_SRC(%a6)
  2659. lea FP_SRC(%a6),%a0
  2660. bsr.l tag # fetch operand type
  2661. mov.b %d0,STAG(%a6)
  2662. mov.b %d0,%d1
  2663. andi.l &0x00ff00ff,USER_FPSR(%a6)
  2664. clr.l %d0
  2665. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  2666. mov.b %d1,STAG(%a6)
  2667. tst.b %d1
  2668. bne.b _L14_2d
  2669. bsr.l slog10 # operand is a NORM
  2670. bra.b _L14_6d
  2671. _L14_2d:
  2672. cmpi.b %d1,&ZERO # is operand a ZERO?
  2673. bne.b _L14_3d # no
  2674. bsr.l t_dz2 # yes
  2675. bra.b _L14_6d
  2676. _L14_3d:
  2677. cmpi.b %d1,&INF # is operand an INF?
  2678. bne.b _L14_4d # no
  2679. bsr.l sopr_inf # yes
  2680. bra.b _L14_6d
  2681. _L14_4d:
  2682. cmpi.b %d1,&QNAN # is operand a QNAN?
  2683. bne.b _L14_5d # no
  2684. bsr.l src_qnan # yes
  2685. bra.b _L14_6d
  2686. _L14_5d:
  2687. bsr.l slog10d # operand is a DENORM
  2688. _L14_6d:
  2689. #
  2690. # Result is now in FP0
  2691. #
  2692. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  2693. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  2694. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  2695. unlk %a6
  2696. rts
  2697. global _flog10x_
  2698. _flog10x_:
  2699. link %a6,&-LOCAL_SIZE
  2700. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  2701. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  2702. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  2703. fmov.l &0x0,%fpcr # zero FPCR
  2704. #
  2705. # copy, convert, and tag input argument
  2706. #
  2707. lea FP_SRC(%a6),%a0
  2708. mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
  2709. mov.l 0x8+0x4(%a6),0x4(%a0)
  2710. mov.l 0x8+0x8(%a6),0x8(%a0)
  2711. bsr.l tag # fetch operand type
  2712. mov.b %d0,STAG(%a6)
  2713. mov.b %d0,%d1
  2714. andi.l &0x00ff00ff,USER_FPSR(%a6)
  2715. clr.l %d0
  2716. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  2717. tst.b %d1
  2718. bne.b _L14_2x
  2719. bsr.l slog10 # operand is a NORM
  2720. bra.b _L14_6x
  2721. _L14_2x:
  2722. cmpi.b %d1,&ZERO # is operand a ZERO?
  2723. bne.b _L14_3x # no
  2724. bsr.l t_dz2 # yes
  2725. bra.b _L14_6x
  2726. _L14_3x:
  2727. cmpi.b %d1,&INF # is operand an INF?
  2728. bne.b _L14_4x # no
  2729. bsr.l sopr_inf # yes
  2730. bra.b _L14_6x
  2731. _L14_4x:
  2732. cmpi.b %d1,&QNAN # is operand a QNAN?
  2733. bne.b _L14_5x # no
  2734. bsr.l src_qnan # yes
  2735. bra.b _L14_6x
  2736. _L14_5x:
  2737. bsr.l slog10d # operand is a DENORM
  2738. _L14_6x:
  2739. #
  2740. # Result is now in FP0
  2741. #
  2742. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  2743. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  2744. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  2745. unlk %a6
  2746. rts
  2747. #########################################################################
  2748. # MONADIC TEMPLATE #
  2749. #########################################################################
  2750. global _flog2s_
  2751. _flog2s_:
  2752. link %a6,&-LOCAL_SIZE
  2753. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  2754. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  2755. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  2756. fmov.l &0x0,%fpcr # zero FPCR
  2757. #
  2758. # copy, convert, and tag input argument
  2759. #
  2760. fmov.s 0x8(%a6),%fp0 # load sgl input
  2761. fmov.x %fp0,FP_SRC(%a6)
  2762. lea FP_SRC(%a6),%a0
  2763. bsr.l tag # fetch operand type
  2764. mov.b %d0,STAG(%a6)
  2765. mov.b %d0,%d1
  2766. andi.l &0x00ff00ff,USER_FPSR(%a6)
  2767. clr.l %d0
  2768. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  2769. tst.b %d1
  2770. bne.b _L15_2s
  2771. bsr.l slog2 # operand is a NORM
  2772. bra.b _L15_6s
  2773. _L15_2s:
  2774. cmpi.b %d1,&ZERO # is operand a ZERO?
  2775. bne.b _L15_3s # no
  2776. bsr.l t_dz2 # yes
  2777. bra.b _L15_6s
  2778. _L15_3s:
  2779. cmpi.b %d1,&INF # is operand an INF?
  2780. bne.b _L15_4s # no
  2781. bsr.l sopr_inf # yes
  2782. bra.b _L15_6s
  2783. _L15_4s:
  2784. cmpi.b %d1,&QNAN # is operand a QNAN?
  2785. bne.b _L15_5s # no
  2786. bsr.l src_qnan # yes
  2787. bra.b _L15_6s
  2788. _L15_5s:
  2789. bsr.l slog2d # operand is a DENORM
  2790. _L15_6s:
  2791. #
  2792. # Result is now in FP0
  2793. #
  2794. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  2795. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  2796. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  2797. unlk %a6
  2798. rts
  2799. global _flog2d_
  2800. _flog2d_:
  2801. link %a6,&-LOCAL_SIZE
  2802. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  2803. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  2804. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  2805. fmov.l &0x0,%fpcr # zero FPCR
  2806. #
  2807. # copy, convert, and tag input argument
  2808. #
  2809. fmov.d 0x8(%a6),%fp0 # load dbl input
  2810. fmov.x %fp0,FP_SRC(%a6)
  2811. lea FP_SRC(%a6),%a0
  2812. bsr.l tag # fetch operand type
  2813. mov.b %d0,STAG(%a6)
  2814. mov.b %d0,%d1
  2815. andi.l &0x00ff00ff,USER_FPSR(%a6)
  2816. clr.l %d0
  2817. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  2818. mov.b %d1,STAG(%a6)
  2819. tst.b %d1
  2820. bne.b _L15_2d
  2821. bsr.l slog2 # operand is a NORM
  2822. bra.b _L15_6d
  2823. _L15_2d:
  2824. cmpi.b %d1,&ZERO # is operand a ZERO?
  2825. bne.b _L15_3d # no
  2826. bsr.l t_dz2 # yes
  2827. bra.b _L15_6d
  2828. _L15_3d:
  2829. cmpi.b %d1,&INF # is operand an INF?
  2830. bne.b _L15_4d # no
  2831. bsr.l sopr_inf # yes
  2832. bra.b _L15_6d
  2833. _L15_4d:
  2834. cmpi.b %d1,&QNAN # is operand a QNAN?
  2835. bne.b _L15_5d # no
  2836. bsr.l src_qnan # yes
  2837. bra.b _L15_6d
  2838. _L15_5d:
  2839. bsr.l slog2d # operand is a DENORM
  2840. _L15_6d:
  2841. #
  2842. # Result is now in FP0
  2843. #
  2844. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  2845. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  2846. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  2847. unlk %a6
  2848. rts
  2849. global _flog2x_
  2850. _flog2x_:
  2851. link %a6,&-LOCAL_SIZE
  2852. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  2853. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  2854. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  2855. fmov.l &0x0,%fpcr # zero FPCR
  2856. #
  2857. # copy, convert, and tag input argument
  2858. #
  2859. lea FP_SRC(%a6),%a0
  2860. mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
  2861. mov.l 0x8+0x4(%a6),0x4(%a0)
  2862. mov.l 0x8+0x8(%a6),0x8(%a0)
  2863. bsr.l tag # fetch operand type
  2864. mov.b %d0,STAG(%a6)
  2865. mov.b %d0,%d1
  2866. andi.l &0x00ff00ff,USER_FPSR(%a6)
  2867. clr.l %d0
  2868. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  2869. tst.b %d1
  2870. bne.b _L15_2x
  2871. bsr.l slog2 # operand is a NORM
  2872. bra.b _L15_6x
  2873. _L15_2x:
  2874. cmpi.b %d1,&ZERO # is operand a ZERO?
  2875. bne.b _L15_3x # no
  2876. bsr.l t_dz2 # yes
  2877. bra.b _L15_6x
  2878. _L15_3x:
  2879. cmpi.b %d1,&INF # is operand an INF?
  2880. bne.b _L15_4x # no
  2881. bsr.l sopr_inf # yes
  2882. bra.b _L15_6x
  2883. _L15_4x:
  2884. cmpi.b %d1,&QNAN # is operand a QNAN?
  2885. bne.b _L15_5x # no
  2886. bsr.l src_qnan # yes
  2887. bra.b _L15_6x
  2888. _L15_5x:
  2889. bsr.l slog2d # operand is a DENORM
  2890. _L15_6x:
  2891. #
  2892. # Result is now in FP0
  2893. #
  2894. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  2895. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  2896. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  2897. unlk %a6
  2898. rts
  2899. #########################################################################
  2900. # MONADIC TEMPLATE #
  2901. #########################################################################
  2902. global _fcoshs_
  2903. _fcoshs_:
  2904. link %a6,&-LOCAL_SIZE
  2905. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  2906. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  2907. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  2908. fmov.l &0x0,%fpcr # zero FPCR
  2909. #
  2910. # copy, convert, and tag input argument
  2911. #
  2912. fmov.s 0x8(%a6),%fp0 # load sgl input
  2913. fmov.x %fp0,FP_SRC(%a6)
  2914. lea FP_SRC(%a6),%a0
  2915. bsr.l tag # fetch operand type
  2916. mov.b %d0,STAG(%a6)
  2917. mov.b %d0,%d1
  2918. andi.l &0x00ff00ff,USER_FPSR(%a6)
  2919. clr.l %d0
  2920. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  2921. tst.b %d1
  2922. bne.b _L16_2s
  2923. bsr.l scosh # operand is a NORM
  2924. bra.b _L16_6s
  2925. _L16_2s:
  2926. cmpi.b %d1,&ZERO # is operand a ZERO?
  2927. bne.b _L16_3s # no
  2928. bsr.l ld_pone # yes
  2929. bra.b _L16_6s
  2930. _L16_3s:
  2931. cmpi.b %d1,&INF # is operand an INF?
  2932. bne.b _L16_4s # no
  2933. bsr.l ld_pinf # yes
  2934. bra.b _L16_6s
  2935. _L16_4s:
  2936. cmpi.b %d1,&QNAN # is operand a QNAN?
  2937. bne.b _L16_5s # no
  2938. bsr.l src_qnan # yes
  2939. bra.b _L16_6s
  2940. _L16_5s:
  2941. bsr.l scoshd # operand is a DENORM
  2942. _L16_6s:
  2943. #
  2944. # Result is now in FP0
  2945. #
  2946. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  2947. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  2948. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  2949. unlk %a6
  2950. rts
  2951. global _fcoshd_
  2952. _fcoshd_:
  2953. link %a6,&-LOCAL_SIZE
  2954. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  2955. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  2956. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  2957. fmov.l &0x0,%fpcr # zero FPCR
  2958. #
  2959. # copy, convert, and tag input argument
  2960. #
  2961. fmov.d 0x8(%a6),%fp0 # load dbl input
  2962. fmov.x %fp0,FP_SRC(%a6)
  2963. lea FP_SRC(%a6),%a0
  2964. bsr.l tag # fetch operand type
  2965. mov.b %d0,STAG(%a6)
  2966. mov.b %d0,%d1
  2967. andi.l &0x00ff00ff,USER_FPSR(%a6)
  2968. clr.l %d0
  2969. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  2970. mov.b %d1,STAG(%a6)
  2971. tst.b %d1
  2972. bne.b _L16_2d
  2973. bsr.l scosh # operand is a NORM
  2974. bra.b _L16_6d
  2975. _L16_2d:
  2976. cmpi.b %d1,&ZERO # is operand a ZERO?
  2977. bne.b _L16_3d # no
  2978. bsr.l ld_pone # yes
  2979. bra.b _L16_6d
  2980. _L16_3d:
  2981. cmpi.b %d1,&INF # is operand an INF?
  2982. bne.b _L16_4d # no
  2983. bsr.l ld_pinf # yes
  2984. bra.b _L16_6d
  2985. _L16_4d:
  2986. cmpi.b %d1,&QNAN # is operand a QNAN?
  2987. bne.b _L16_5d # no
  2988. bsr.l src_qnan # yes
  2989. bra.b _L16_6d
  2990. _L16_5d:
  2991. bsr.l scoshd # operand is a DENORM
  2992. _L16_6d:
  2993. #
  2994. # Result is now in FP0
  2995. #
  2996. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  2997. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  2998. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  2999. unlk %a6
  3000. rts
  3001. global _fcoshx_
  3002. _fcoshx_:
  3003. link %a6,&-LOCAL_SIZE
  3004. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  3005. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  3006. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  3007. fmov.l &0x0,%fpcr # zero FPCR
  3008. #
  3009. # copy, convert, and tag input argument
  3010. #
  3011. lea FP_SRC(%a6),%a0
  3012. mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
  3013. mov.l 0x8+0x4(%a6),0x4(%a0)
  3014. mov.l 0x8+0x8(%a6),0x8(%a0)
  3015. bsr.l tag # fetch operand type
  3016. mov.b %d0,STAG(%a6)
  3017. mov.b %d0,%d1
  3018. andi.l &0x00ff00ff,USER_FPSR(%a6)
  3019. clr.l %d0
  3020. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  3021. tst.b %d1
  3022. bne.b _L16_2x
  3023. bsr.l scosh # operand is a NORM
  3024. bra.b _L16_6x
  3025. _L16_2x:
  3026. cmpi.b %d1,&ZERO # is operand a ZERO?
  3027. bne.b _L16_3x # no
  3028. bsr.l ld_pone # yes
  3029. bra.b _L16_6x
  3030. _L16_3x:
  3031. cmpi.b %d1,&INF # is operand an INF?
  3032. bne.b _L16_4x # no
  3033. bsr.l ld_pinf # yes
  3034. bra.b _L16_6x
  3035. _L16_4x:
  3036. cmpi.b %d1,&QNAN # is operand a QNAN?
  3037. bne.b _L16_5x # no
  3038. bsr.l src_qnan # yes
  3039. bra.b _L16_6x
  3040. _L16_5x:
  3041. bsr.l scoshd # operand is a DENORM
  3042. _L16_6x:
  3043. #
  3044. # Result is now in FP0
  3045. #
  3046. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  3047. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  3048. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  3049. unlk %a6
  3050. rts
  3051. #########################################################################
  3052. # MONADIC TEMPLATE #
  3053. #########################################################################
  3054. global _facoss_
  3055. _facoss_:
  3056. link %a6,&-LOCAL_SIZE
  3057. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  3058. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  3059. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  3060. fmov.l &0x0,%fpcr # zero FPCR
  3061. #
  3062. # copy, convert, and tag input argument
  3063. #
  3064. fmov.s 0x8(%a6),%fp0 # load sgl input
  3065. fmov.x %fp0,FP_SRC(%a6)
  3066. lea FP_SRC(%a6),%a0
  3067. bsr.l tag # fetch operand type
  3068. mov.b %d0,STAG(%a6)
  3069. mov.b %d0,%d1
  3070. andi.l &0x00ff00ff,USER_FPSR(%a6)
  3071. clr.l %d0
  3072. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  3073. tst.b %d1
  3074. bne.b _L17_2s
  3075. bsr.l sacos # operand is a NORM
  3076. bra.b _L17_6s
  3077. _L17_2s:
  3078. cmpi.b %d1,&ZERO # is operand a ZERO?
  3079. bne.b _L17_3s # no
  3080. bsr.l ld_ppi2 # yes
  3081. bra.b _L17_6s
  3082. _L17_3s:
  3083. cmpi.b %d1,&INF # is operand an INF?
  3084. bne.b _L17_4s # no
  3085. bsr.l t_operr # yes
  3086. bra.b _L17_6s
  3087. _L17_4s:
  3088. cmpi.b %d1,&QNAN # is operand a QNAN?
  3089. bne.b _L17_5s # no
  3090. bsr.l src_qnan # yes
  3091. bra.b _L17_6s
  3092. _L17_5s:
  3093. bsr.l sacosd # operand is a DENORM
  3094. _L17_6s:
  3095. #
  3096. # Result is now in FP0
  3097. #
  3098. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  3099. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  3100. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  3101. unlk %a6
  3102. rts
  3103. global _facosd_
  3104. _facosd_:
  3105. link %a6,&-LOCAL_SIZE
  3106. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  3107. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  3108. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  3109. fmov.l &0x0,%fpcr # zero FPCR
  3110. #
  3111. # copy, convert, and tag input argument
  3112. #
  3113. fmov.d 0x8(%a6),%fp0 # load dbl input
  3114. fmov.x %fp0,FP_SRC(%a6)
  3115. lea FP_SRC(%a6),%a0
  3116. bsr.l tag # fetch operand type
  3117. mov.b %d0,STAG(%a6)
  3118. mov.b %d0,%d1
  3119. andi.l &0x00ff00ff,USER_FPSR(%a6)
  3120. clr.l %d0
  3121. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  3122. mov.b %d1,STAG(%a6)
  3123. tst.b %d1
  3124. bne.b _L17_2d
  3125. bsr.l sacos # operand is a NORM
  3126. bra.b _L17_6d
  3127. _L17_2d:
  3128. cmpi.b %d1,&ZERO # is operand a ZERO?
  3129. bne.b _L17_3d # no
  3130. bsr.l ld_ppi2 # yes
  3131. bra.b _L17_6d
  3132. _L17_3d:
  3133. cmpi.b %d1,&INF # is operand an INF?
  3134. bne.b _L17_4d # no
  3135. bsr.l t_operr # yes
  3136. bra.b _L17_6d
  3137. _L17_4d:
  3138. cmpi.b %d1,&QNAN # is operand a QNAN?
  3139. bne.b _L17_5d # no
  3140. bsr.l src_qnan # yes
  3141. bra.b _L17_6d
  3142. _L17_5d:
  3143. bsr.l sacosd # operand is a DENORM
  3144. _L17_6d:
  3145. #
  3146. # Result is now in FP0
  3147. #
  3148. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  3149. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  3150. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  3151. unlk %a6
  3152. rts
  3153. global _facosx_
  3154. _facosx_:
  3155. link %a6,&-LOCAL_SIZE
  3156. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  3157. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  3158. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  3159. fmov.l &0x0,%fpcr # zero FPCR
  3160. #
  3161. # copy, convert, and tag input argument
  3162. #
  3163. lea FP_SRC(%a6),%a0
  3164. mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
  3165. mov.l 0x8+0x4(%a6),0x4(%a0)
  3166. mov.l 0x8+0x8(%a6),0x8(%a0)
  3167. bsr.l tag # fetch operand type
  3168. mov.b %d0,STAG(%a6)
  3169. mov.b %d0,%d1
  3170. andi.l &0x00ff00ff,USER_FPSR(%a6)
  3171. clr.l %d0
  3172. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  3173. tst.b %d1
  3174. bne.b _L17_2x
  3175. bsr.l sacos # operand is a NORM
  3176. bra.b _L17_6x
  3177. _L17_2x:
  3178. cmpi.b %d1,&ZERO # is operand a ZERO?
  3179. bne.b _L17_3x # no
  3180. bsr.l ld_ppi2 # yes
  3181. bra.b _L17_6x
  3182. _L17_3x:
  3183. cmpi.b %d1,&INF # is operand an INF?
  3184. bne.b _L17_4x # no
  3185. bsr.l t_operr # yes
  3186. bra.b _L17_6x
  3187. _L17_4x:
  3188. cmpi.b %d1,&QNAN # is operand a QNAN?
  3189. bne.b _L17_5x # no
  3190. bsr.l src_qnan # yes
  3191. bra.b _L17_6x
  3192. _L17_5x:
  3193. bsr.l sacosd # operand is a DENORM
  3194. _L17_6x:
  3195. #
  3196. # Result is now in FP0
  3197. #
  3198. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  3199. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  3200. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  3201. unlk %a6
  3202. rts
  3203. #########################################################################
  3204. # MONADIC TEMPLATE #
  3205. #########################################################################
  3206. global _fgetexps_
  3207. _fgetexps_:
  3208. link %a6,&-LOCAL_SIZE
  3209. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  3210. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  3211. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  3212. fmov.l &0x0,%fpcr # zero FPCR
  3213. #
  3214. # copy, convert, and tag input argument
  3215. #
  3216. fmov.s 0x8(%a6),%fp0 # load sgl input
  3217. fmov.x %fp0,FP_SRC(%a6)
  3218. lea FP_SRC(%a6),%a0
  3219. bsr.l tag # fetch operand type
  3220. mov.b %d0,STAG(%a6)
  3221. mov.b %d0,%d1
  3222. andi.l &0x00ff00ff,USER_FPSR(%a6)
  3223. clr.l %d0
  3224. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  3225. tst.b %d1
  3226. bne.b _L18_2s
  3227. bsr.l sgetexp # operand is a NORM
  3228. bra.b _L18_6s
  3229. _L18_2s:
  3230. cmpi.b %d1,&ZERO # is operand a ZERO?
  3231. bne.b _L18_3s # no
  3232. bsr.l src_zero # yes
  3233. bra.b _L18_6s
  3234. _L18_3s:
  3235. cmpi.b %d1,&INF # is operand an INF?
  3236. bne.b _L18_4s # no
  3237. bsr.l t_operr # yes
  3238. bra.b _L18_6s
  3239. _L18_4s:
  3240. cmpi.b %d1,&QNAN # is operand a QNAN?
  3241. bne.b _L18_5s # no
  3242. bsr.l src_qnan # yes
  3243. bra.b _L18_6s
  3244. _L18_5s:
  3245. bsr.l sgetexpd # operand is a DENORM
  3246. _L18_6s:
  3247. #
  3248. # Result is now in FP0
  3249. #
  3250. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  3251. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  3252. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  3253. unlk %a6
  3254. rts
  3255. global _fgetexpd_
  3256. _fgetexpd_:
  3257. link %a6,&-LOCAL_SIZE
  3258. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  3259. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  3260. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  3261. fmov.l &0x0,%fpcr # zero FPCR
  3262. #
  3263. # copy, convert, and tag input argument
  3264. #
  3265. fmov.d 0x8(%a6),%fp0 # load dbl input
  3266. fmov.x %fp0,FP_SRC(%a6)
  3267. lea FP_SRC(%a6),%a0
  3268. bsr.l tag # fetch operand type
  3269. mov.b %d0,STAG(%a6)
  3270. mov.b %d0,%d1
  3271. andi.l &0x00ff00ff,USER_FPSR(%a6)
  3272. clr.l %d0
  3273. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  3274. mov.b %d1,STAG(%a6)
  3275. tst.b %d1
  3276. bne.b _L18_2d
  3277. bsr.l sgetexp # operand is a NORM
  3278. bra.b _L18_6d
  3279. _L18_2d:
  3280. cmpi.b %d1,&ZERO # is operand a ZERO?
  3281. bne.b _L18_3d # no
  3282. bsr.l src_zero # yes
  3283. bra.b _L18_6d
  3284. _L18_3d:
  3285. cmpi.b %d1,&INF # is operand an INF?
  3286. bne.b _L18_4d # no
  3287. bsr.l t_operr # yes
  3288. bra.b _L18_6d
  3289. _L18_4d:
  3290. cmpi.b %d1,&QNAN # is operand a QNAN?
  3291. bne.b _L18_5d # no
  3292. bsr.l src_qnan # yes
  3293. bra.b _L18_6d
  3294. _L18_5d:
  3295. bsr.l sgetexpd # operand is a DENORM
  3296. _L18_6d:
  3297. #
  3298. # Result is now in FP0
  3299. #
  3300. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  3301. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  3302. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  3303. unlk %a6
  3304. rts
  3305. global _fgetexpx_
  3306. _fgetexpx_:
  3307. link %a6,&-LOCAL_SIZE
  3308. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  3309. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  3310. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  3311. fmov.l &0x0,%fpcr # zero FPCR
  3312. #
  3313. # copy, convert, and tag input argument
  3314. #
  3315. lea FP_SRC(%a6),%a0
  3316. mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
  3317. mov.l 0x8+0x4(%a6),0x4(%a0)
  3318. mov.l 0x8+0x8(%a6),0x8(%a0)
  3319. bsr.l tag # fetch operand type
  3320. mov.b %d0,STAG(%a6)
  3321. mov.b %d0,%d1
  3322. andi.l &0x00ff00ff,USER_FPSR(%a6)
  3323. clr.l %d0
  3324. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  3325. tst.b %d1
  3326. bne.b _L18_2x
  3327. bsr.l sgetexp # operand is a NORM
  3328. bra.b _L18_6x
  3329. _L18_2x:
  3330. cmpi.b %d1,&ZERO # is operand a ZERO?
  3331. bne.b _L18_3x # no
  3332. bsr.l src_zero # yes
  3333. bra.b _L18_6x
  3334. _L18_3x:
  3335. cmpi.b %d1,&INF # is operand an INF?
  3336. bne.b _L18_4x # no
  3337. bsr.l t_operr # yes
  3338. bra.b _L18_6x
  3339. _L18_4x:
  3340. cmpi.b %d1,&QNAN # is operand a QNAN?
  3341. bne.b _L18_5x # no
  3342. bsr.l src_qnan # yes
  3343. bra.b _L18_6x
  3344. _L18_5x:
  3345. bsr.l sgetexpd # operand is a DENORM
  3346. _L18_6x:
  3347. #
  3348. # Result is now in FP0
  3349. #
  3350. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  3351. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  3352. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  3353. unlk %a6
  3354. rts
  3355. #########################################################################
  3356. # MONADIC TEMPLATE #
  3357. #########################################################################
  3358. global _fgetmans_
  3359. _fgetmans_:
  3360. link %a6,&-LOCAL_SIZE
  3361. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  3362. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  3363. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  3364. fmov.l &0x0,%fpcr # zero FPCR
  3365. #
  3366. # copy, convert, and tag input argument
  3367. #
  3368. fmov.s 0x8(%a6),%fp0 # load sgl input
  3369. fmov.x %fp0,FP_SRC(%a6)
  3370. lea FP_SRC(%a6),%a0
  3371. bsr.l tag # fetch operand type
  3372. mov.b %d0,STAG(%a6)
  3373. mov.b %d0,%d1
  3374. andi.l &0x00ff00ff,USER_FPSR(%a6)
  3375. clr.l %d0
  3376. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  3377. tst.b %d1
  3378. bne.b _L19_2s
  3379. bsr.l sgetman # operand is a NORM
  3380. bra.b _L19_6s
  3381. _L19_2s:
  3382. cmpi.b %d1,&ZERO # is operand a ZERO?
  3383. bne.b _L19_3s # no
  3384. bsr.l src_zero # yes
  3385. bra.b _L19_6s
  3386. _L19_3s:
  3387. cmpi.b %d1,&INF # is operand an INF?
  3388. bne.b _L19_4s # no
  3389. bsr.l t_operr # yes
  3390. bra.b _L19_6s
  3391. _L19_4s:
  3392. cmpi.b %d1,&QNAN # is operand a QNAN?
  3393. bne.b _L19_5s # no
  3394. bsr.l src_qnan # yes
  3395. bra.b _L19_6s
  3396. _L19_5s:
  3397. bsr.l sgetmand # operand is a DENORM
  3398. _L19_6s:
  3399. #
  3400. # Result is now in FP0
  3401. #
  3402. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  3403. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  3404. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  3405. unlk %a6
  3406. rts
  3407. global _fgetmand_
  3408. _fgetmand_:
  3409. link %a6,&-LOCAL_SIZE
  3410. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  3411. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  3412. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  3413. fmov.l &0x0,%fpcr # zero FPCR
  3414. #
  3415. # copy, convert, and tag input argument
  3416. #
  3417. fmov.d 0x8(%a6),%fp0 # load dbl input
  3418. fmov.x %fp0,FP_SRC(%a6)
  3419. lea FP_SRC(%a6),%a0
  3420. bsr.l tag # fetch operand type
  3421. mov.b %d0,STAG(%a6)
  3422. mov.b %d0,%d1
  3423. andi.l &0x00ff00ff,USER_FPSR(%a6)
  3424. clr.l %d0
  3425. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  3426. mov.b %d1,STAG(%a6)
  3427. tst.b %d1
  3428. bne.b _L19_2d
  3429. bsr.l sgetman # operand is a NORM
  3430. bra.b _L19_6d
  3431. _L19_2d:
  3432. cmpi.b %d1,&ZERO # is operand a ZERO?
  3433. bne.b _L19_3d # no
  3434. bsr.l src_zero # yes
  3435. bra.b _L19_6d
  3436. _L19_3d:
  3437. cmpi.b %d1,&INF # is operand an INF?
  3438. bne.b _L19_4d # no
  3439. bsr.l t_operr # yes
  3440. bra.b _L19_6d
  3441. _L19_4d:
  3442. cmpi.b %d1,&QNAN # is operand a QNAN?
  3443. bne.b _L19_5d # no
  3444. bsr.l src_qnan # yes
  3445. bra.b _L19_6d
  3446. _L19_5d:
  3447. bsr.l sgetmand # operand is a DENORM
  3448. _L19_6d:
  3449. #
  3450. # Result is now in FP0
  3451. #
  3452. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  3453. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  3454. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  3455. unlk %a6
  3456. rts
  3457. global _fgetmanx_
  3458. _fgetmanx_:
  3459. link %a6,&-LOCAL_SIZE
  3460. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  3461. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  3462. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  3463. fmov.l &0x0,%fpcr # zero FPCR
  3464. #
  3465. # copy, convert, and tag input argument
  3466. #
  3467. lea FP_SRC(%a6),%a0
  3468. mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
  3469. mov.l 0x8+0x4(%a6),0x4(%a0)
  3470. mov.l 0x8+0x8(%a6),0x8(%a0)
  3471. bsr.l tag # fetch operand type
  3472. mov.b %d0,STAG(%a6)
  3473. mov.b %d0,%d1
  3474. andi.l &0x00ff00ff,USER_FPSR(%a6)
  3475. clr.l %d0
  3476. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  3477. tst.b %d1
  3478. bne.b _L19_2x
  3479. bsr.l sgetman # operand is a NORM
  3480. bra.b _L19_6x
  3481. _L19_2x:
  3482. cmpi.b %d1,&ZERO # is operand a ZERO?
  3483. bne.b _L19_3x # no
  3484. bsr.l src_zero # yes
  3485. bra.b _L19_6x
  3486. _L19_3x:
  3487. cmpi.b %d1,&INF # is operand an INF?
  3488. bne.b _L19_4x # no
  3489. bsr.l t_operr # yes
  3490. bra.b _L19_6x
  3491. _L19_4x:
  3492. cmpi.b %d1,&QNAN # is operand a QNAN?
  3493. bne.b _L19_5x # no
  3494. bsr.l src_qnan # yes
  3495. bra.b _L19_6x
  3496. _L19_5x:
  3497. bsr.l sgetmand # operand is a DENORM
  3498. _L19_6x:
  3499. #
  3500. # Result is now in FP0
  3501. #
  3502. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  3503. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  3504. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  3505. unlk %a6
  3506. rts
  3507. #########################################################################
  3508. # MONADIC TEMPLATE #
  3509. #########################################################################
  3510. global _fsincoss_
  3511. _fsincoss_:
  3512. link %a6,&-LOCAL_SIZE
  3513. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  3514. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  3515. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  3516. fmov.l &0x0,%fpcr # zero FPCR
  3517. #
  3518. # copy, convert, and tag input argument
  3519. #
  3520. fmov.s 0x8(%a6),%fp0 # load sgl input
  3521. fmov.x %fp0,FP_SRC(%a6)
  3522. lea FP_SRC(%a6),%a0
  3523. bsr.l tag # fetch operand type
  3524. mov.b %d0,STAG(%a6)
  3525. mov.b %d0,%d1
  3526. andi.l &0x00ff00ff,USER_FPSR(%a6)
  3527. clr.l %d0
  3528. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  3529. tst.b %d1
  3530. bne.b _L20_2s
  3531. bsr.l ssincos # operand is a NORM
  3532. bra.b _L20_6s
  3533. _L20_2s:
  3534. cmpi.b %d1,&ZERO # is operand a ZERO?
  3535. bne.b _L20_3s # no
  3536. bsr.l ssincosz # yes
  3537. bra.b _L20_6s
  3538. _L20_3s:
  3539. cmpi.b %d1,&INF # is operand an INF?
  3540. bne.b _L20_4s # no
  3541. bsr.l ssincosi # yes
  3542. bra.b _L20_6s
  3543. _L20_4s:
  3544. cmpi.b %d1,&QNAN # is operand a QNAN?
  3545. bne.b _L20_5s # no
  3546. bsr.l ssincosqnan # yes
  3547. bra.b _L20_6s
  3548. _L20_5s:
  3549. bsr.l ssincosd # operand is a DENORM
  3550. _L20_6s:
  3551. #
  3552. # Result is now in FP0
  3553. #
  3554. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  3555. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  3556. fmovm.x &0x03,-(%sp) # store off fp0/fp1
  3557. fmovm.x (%sp)+,&0x40 # fp0 now in fp1
  3558. fmovm.x (%sp)+,&0x80 # fp1 now in fp0
  3559. unlk %a6
  3560. rts
  3561. global _fsincosd_
  3562. _fsincosd_:
  3563. link %a6,&-LOCAL_SIZE
  3564. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  3565. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  3566. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  3567. fmov.l &0x0,%fpcr # zero FPCR
  3568. #
  3569. # copy, convert, and tag input argument
  3570. #
  3571. fmov.d 0x8(%a6),%fp0 # load dbl input
  3572. fmov.x %fp0,FP_SRC(%a6)
  3573. lea FP_SRC(%a6),%a0
  3574. bsr.l tag # fetch operand type
  3575. mov.b %d0,STAG(%a6)
  3576. mov.b %d0,%d1
  3577. andi.l &0x00ff00ff,USER_FPSR(%a6)
  3578. clr.l %d0
  3579. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  3580. mov.b %d1,STAG(%a6)
  3581. tst.b %d1
  3582. bne.b _L20_2d
  3583. bsr.l ssincos # operand is a NORM
  3584. bra.b _L20_6d
  3585. _L20_2d:
  3586. cmpi.b %d1,&ZERO # is operand a ZERO?
  3587. bne.b _L20_3d # no
  3588. bsr.l ssincosz # yes
  3589. bra.b _L20_6d
  3590. _L20_3d:
  3591. cmpi.b %d1,&INF # is operand an INF?
  3592. bne.b _L20_4d # no
  3593. bsr.l ssincosi # yes
  3594. bra.b _L20_6d
  3595. _L20_4d:
  3596. cmpi.b %d1,&QNAN # is operand a QNAN?
  3597. bne.b _L20_5d # no
  3598. bsr.l ssincosqnan # yes
  3599. bra.b _L20_6d
  3600. _L20_5d:
  3601. bsr.l ssincosd # operand is a DENORM
  3602. _L20_6d:
  3603. #
  3604. # Result is now in FP0
  3605. #
  3606. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  3607. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  3608. fmovm.x &0x03,-(%sp) # store off fp0/fp1
  3609. fmovm.x (%sp)+,&0x40 # fp0 now in fp1
  3610. fmovm.x (%sp)+,&0x80 # fp1 now in fp0
  3611. unlk %a6
  3612. rts
  3613. global _fsincosx_
  3614. _fsincosx_:
  3615. link %a6,&-LOCAL_SIZE
  3616. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  3617. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  3618. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  3619. fmov.l &0x0,%fpcr # zero FPCR
  3620. #
  3621. # copy, convert, and tag input argument
  3622. #
  3623. lea FP_SRC(%a6),%a0
  3624. mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
  3625. mov.l 0x8+0x4(%a6),0x4(%a0)
  3626. mov.l 0x8+0x8(%a6),0x8(%a0)
  3627. bsr.l tag # fetch operand type
  3628. mov.b %d0,STAG(%a6)
  3629. mov.b %d0,%d1
  3630. andi.l &0x00ff00ff,USER_FPSR(%a6)
  3631. clr.l %d0
  3632. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  3633. tst.b %d1
  3634. bne.b _L20_2x
  3635. bsr.l ssincos # operand is a NORM
  3636. bra.b _L20_6x
  3637. _L20_2x:
  3638. cmpi.b %d1,&ZERO # is operand a ZERO?
  3639. bne.b _L20_3x # no
  3640. bsr.l ssincosz # yes
  3641. bra.b _L20_6x
  3642. _L20_3x:
  3643. cmpi.b %d1,&INF # is operand an INF?
  3644. bne.b _L20_4x # no
  3645. bsr.l ssincosi # yes
  3646. bra.b _L20_6x
  3647. _L20_4x:
  3648. cmpi.b %d1,&QNAN # is operand a QNAN?
  3649. bne.b _L20_5x # no
  3650. bsr.l ssincosqnan # yes
  3651. bra.b _L20_6x
  3652. _L20_5x:
  3653. bsr.l ssincosd # operand is a DENORM
  3654. _L20_6x:
  3655. #
  3656. # Result is now in FP0
  3657. #
  3658. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  3659. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  3660. fmovm.x &0x03,-(%sp) # store off fp0/fp1
  3661. fmovm.x (%sp)+,&0x40 # fp0 now in fp1
  3662. fmovm.x (%sp)+,&0x80 # fp1 now in fp0
  3663. unlk %a6
  3664. rts
  3665. #########################################################################
  3666. # DYADIC TEMPLATE #
  3667. #########################################################################
  3668. global _frems_
  3669. _frems_:
  3670. link %a6,&-LOCAL_SIZE
  3671. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  3672. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  3673. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  3674. fmov.l &0x0,%fpcr # zero FPCR
  3675. #
  3676. # copy, convert, and tag input argument
  3677. #
  3678. fmov.s 0x8(%a6),%fp0 # load sgl dst
  3679. fmov.x %fp0,FP_DST(%a6)
  3680. lea FP_DST(%a6),%a0
  3681. bsr.l tag # fetch operand type
  3682. mov.b %d0,DTAG(%a6)
  3683. fmov.s 0xc(%a6),%fp0 # load sgl src
  3684. fmov.x %fp0,FP_SRC(%a6)
  3685. lea FP_SRC(%a6),%a0
  3686. bsr.l tag # fetch operand type
  3687. mov.b %d0,STAG(%a6)
  3688. mov.l %d0,%d1
  3689. andi.l &0x00ff00ff,USER_FPSR(%a6)
  3690. clr.l %d0
  3691. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  3692. lea FP_SRC(%a6),%a0 # pass ptr to src
  3693. lea FP_DST(%a6),%a1 # pass ptr to dst
  3694. tst.b %d1
  3695. bne.b _L21_2s
  3696. bsr.l srem_snorm # operand is a NORM
  3697. bra.b _L21_6s
  3698. _L21_2s:
  3699. cmpi.b %d1,&ZERO # is operand a ZERO?
  3700. bne.b _L21_3s # no
  3701. bsr.l srem_szero # yes
  3702. bra.b _L21_6s
  3703. _L21_3s:
  3704. cmpi.b %d1,&INF # is operand an INF?
  3705. bne.b _L21_4s # no
  3706. bsr.l srem_sinf # yes
  3707. bra.b _L21_6s
  3708. _L21_4s:
  3709. cmpi.b %d1,&QNAN # is operand a QNAN?
  3710. bne.b _L21_5s # no
  3711. bsr.l sop_sqnan # yes
  3712. bra.b _L21_6s
  3713. _L21_5s:
  3714. bsr.l srem_sdnrm # operand is a DENORM
  3715. _L21_6s:
  3716. #
  3717. # Result is now in FP0
  3718. #
  3719. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  3720. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  3721. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  3722. unlk %a6
  3723. rts
  3724. global _fremd_
  3725. _fremd_:
  3726. link %a6,&-LOCAL_SIZE
  3727. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  3728. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  3729. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  3730. fmov.l &0x0,%fpcr # zero FPCR
  3731. #
  3732. # copy, convert, and tag input argument
  3733. #
  3734. fmov.d 0x8(%a6),%fp0 # load dbl dst
  3735. fmov.x %fp0,FP_DST(%a6)
  3736. lea FP_DST(%a6),%a0
  3737. bsr.l tag # fetch operand type
  3738. mov.b %d0,DTAG(%a6)
  3739. fmov.d 0x10(%a6),%fp0 # load dbl src
  3740. fmov.x %fp0,FP_SRC(%a6)
  3741. lea FP_SRC(%a6),%a0
  3742. bsr.l tag # fetch operand type
  3743. mov.b %d0,STAG(%a6)
  3744. mov.l %d0,%d1
  3745. andi.l &0x00ff00ff,USER_FPSR(%a6)
  3746. clr.l %d0
  3747. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  3748. lea FP_SRC(%a6),%a0 # pass ptr to src
  3749. lea FP_DST(%a6),%a1 # pass ptr to dst
  3750. tst.b %d1
  3751. bne.b _L21_2d
  3752. bsr.l srem_snorm # operand is a NORM
  3753. bra.b _L21_6d
  3754. _L21_2d:
  3755. cmpi.b %d1,&ZERO # is operand a ZERO?
  3756. bne.b _L21_3d # no
  3757. bsr.l srem_szero # yes
  3758. bra.b _L21_6d
  3759. _L21_3d:
  3760. cmpi.b %d1,&INF # is operand an INF?
  3761. bne.b _L21_4d # no
  3762. bsr.l srem_sinf # yes
  3763. bra.b _L21_6d
  3764. _L21_4d:
  3765. cmpi.b %d1,&QNAN # is operand a QNAN?
  3766. bne.b _L21_5d # no
  3767. bsr.l sop_sqnan # yes
  3768. bra.b _L21_6d
  3769. _L21_5d:
  3770. bsr.l srem_sdnrm # operand is a DENORM
  3771. _L21_6d:
  3772. #
  3773. # Result is now in FP0
  3774. #
  3775. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  3776. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  3777. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  3778. unlk %a6
  3779. rts
  3780. global _fremx_
  3781. _fremx_:
  3782. link %a6,&-LOCAL_SIZE
  3783. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  3784. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  3785. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  3786. fmov.l &0x0,%fpcr # zero FPCR
  3787. #
  3788. # copy, convert, and tag input argument
  3789. #
  3790. lea FP_DST(%a6),%a0
  3791. mov.l 0x8+0x0(%a6),0x0(%a0) # load ext dst
  3792. mov.l 0x8+0x4(%a6),0x4(%a0)
  3793. mov.l 0x8+0x8(%a6),0x8(%a0)
  3794. bsr.l tag # fetch operand type
  3795. mov.b %d0,DTAG(%a6)
  3796. lea FP_SRC(%a6),%a0
  3797. mov.l 0x14+0x0(%a6),0x0(%a0) # load ext src
  3798. mov.l 0x14+0x4(%a6),0x4(%a0)
  3799. mov.l 0x14+0x8(%a6),0x8(%a0)
  3800. bsr.l tag # fetch operand type
  3801. mov.b %d0,STAG(%a6)
  3802. mov.l %d0,%d1
  3803. andi.l &0x00ff00ff,USER_FPSR(%a6)
  3804. clr.l %d0
  3805. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  3806. lea FP_SRC(%a6),%a0 # pass ptr to src
  3807. lea FP_DST(%a6),%a1 # pass ptr to dst
  3808. tst.b %d1
  3809. bne.b _L21_2x
  3810. bsr.l srem_snorm # operand is a NORM
  3811. bra.b _L21_6x
  3812. _L21_2x:
  3813. cmpi.b %d1,&ZERO # is operand a ZERO?
  3814. bne.b _L21_3x # no
  3815. bsr.l srem_szero # yes
  3816. bra.b _L21_6x
  3817. _L21_3x:
  3818. cmpi.b %d1,&INF # is operand an INF?
  3819. bne.b _L21_4x # no
  3820. bsr.l srem_sinf # yes
  3821. bra.b _L21_6x
  3822. _L21_4x:
  3823. cmpi.b %d1,&QNAN # is operand a QNAN?
  3824. bne.b _L21_5x # no
  3825. bsr.l sop_sqnan # yes
  3826. bra.b _L21_6x
  3827. _L21_5x:
  3828. bsr.l srem_sdnrm # operand is a DENORM
  3829. _L21_6x:
  3830. #
  3831. # Result is now in FP0
  3832. #
  3833. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  3834. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  3835. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  3836. unlk %a6
  3837. rts
  3838. #########################################################################
  3839. # DYADIC TEMPLATE #
  3840. #########################################################################
  3841. global _fmods_
  3842. _fmods_:
  3843. link %a6,&-LOCAL_SIZE
  3844. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  3845. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  3846. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  3847. fmov.l &0x0,%fpcr # zero FPCR
  3848. #
  3849. # copy, convert, and tag input argument
  3850. #
  3851. fmov.s 0x8(%a6),%fp0 # load sgl dst
  3852. fmov.x %fp0,FP_DST(%a6)
  3853. lea FP_DST(%a6),%a0
  3854. bsr.l tag # fetch operand type
  3855. mov.b %d0,DTAG(%a6)
  3856. fmov.s 0xc(%a6),%fp0 # load sgl src
  3857. fmov.x %fp0,FP_SRC(%a6)
  3858. lea FP_SRC(%a6),%a0
  3859. bsr.l tag # fetch operand type
  3860. mov.b %d0,STAG(%a6)
  3861. mov.l %d0,%d1
  3862. andi.l &0x00ff00ff,USER_FPSR(%a6)
  3863. clr.l %d0
  3864. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  3865. lea FP_SRC(%a6),%a0 # pass ptr to src
  3866. lea FP_DST(%a6),%a1 # pass ptr to dst
  3867. tst.b %d1
  3868. bne.b _L22_2s
  3869. bsr.l smod_snorm # operand is a NORM
  3870. bra.b _L22_6s
  3871. _L22_2s:
  3872. cmpi.b %d1,&ZERO # is operand a ZERO?
  3873. bne.b _L22_3s # no
  3874. bsr.l smod_szero # yes
  3875. bra.b _L22_6s
  3876. _L22_3s:
  3877. cmpi.b %d1,&INF # is operand an INF?
  3878. bne.b _L22_4s # no
  3879. bsr.l smod_sinf # yes
  3880. bra.b _L22_6s
  3881. _L22_4s:
  3882. cmpi.b %d1,&QNAN # is operand a QNAN?
  3883. bne.b _L22_5s # no
  3884. bsr.l sop_sqnan # yes
  3885. bra.b _L22_6s
  3886. _L22_5s:
  3887. bsr.l smod_sdnrm # operand is a DENORM
  3888. _L22_6s:
  3889. #
  3890. # Result is now in FP0
  3891. #
  3892. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  3893. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  3894. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  3895. unlk %a6
  3896. rts
  3897. global _fmodd_
  3898. _fmodd_:
  3899. link %a6,&-LOCAL_SIZE
  3900. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  3901. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  3902. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  3903. fmov.l &0x0,%fpcr # zero FPCR
  3904. #
  3905. # copy, convert, and tag input argument
  3906. #
  3907. fmov.d 0x8(%a6),%fp0 # load dbl dst
  3908. fmov.x %fp0,FP_DST(%a6)
  3909. lea FP_DST(%a6),%a0
  3910. bsr.l tag # fetch operand type
  3911. mov.b %d0,DTAG(%a6)
  3912. fmov.d 0x10(%a6),%fp0 # load dbl src
  3913. fmov.x %fp0,FP_SRC(%a6)
  3914. lea FP_SRC(%a6),%a0
  3915. bsr.l tag # fetch operand type
  3916. mov.b %d0,STAG(%a6)
  3917. mov.l %d0,%d1
  3918. andi.l &0x00ff00ff,USER_FPSR(%a6)
  3919. clr.l %d0
  3920. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  3921. lea FP_SRC(%a6),%a0 # pass ptr to src
  3922. lea FP_DST(%a6),%a1 # pass ptr to dst
  3923. tst.b %d1
  3924. bne.b _L22_2d
  3925. bsr.l smod_snorm # operand is a NORM
  3926. bra.b _L22_6d
  3927. _L22_2d:
  3928. cmpi.b %d1,&ZERO # is operand a ZERO?
  3929. bne.b _L22_3d # no
  3930. bsr.l smod_szero # yes
  3931. bra.b _L22_6d
  3932. _L22_3d:
  3933. cmpi.b %d1,&INF # is operand an INF?
  3934. bne.b _L22_4d # no
  3935. bsr.l smod_sinf # yes
  3936. bra.b _L22_6d
  3937. _L22_4d:
  3938. cmpi.b %d1,&QNAN # is operand a QNAN?
  3939. bne.b _L22_5d # no
  3940. bsr.l sop_sqnan # yes
  3941. bra.b _L22_6d
  3942. _L22_5d:
  3943. bsr.l smod_sdnrm # operand is a DENORM
  3944. _L22_6d:
  3945. #
  3946. # Result is now in FP0
  3947. #
  3948. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  3949. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  3950. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  3951. unlk %a6
  3952. rts
  3953. global _fmodx_
  3954. _fmodx_:
  3955. link %a6,&-LOCAL_SIZE
  3956. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  3957. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  3958. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  3959. fmov.l &0x0,%fpcr # zero FPCR
  3960. #
  3961. # copy, convert, and tag input argument
  3962. #
  3963. lea FP_DST(%a6),%a0
  3964. mov.l 0x8+0x0(%a6),0x0(%a0) # load ext dst
  3965. mov.l 0x8+0x4(%a6),0x4(%a0)
  3966. mov.l 0x8+0x8(%a6),0x8(%a0)
  3967. bsr.l tag # fetch operand type
  3968. mov.b %d0,DTAG(%a6)
  3969. lea FP_SRC(%a6),%a0
  3970. mov.l 0x14+0x0(%a6),0x0(%a0) # load ext src
  3971. mov.l 0x14+0x4(%a6),0x4(%a0)
  3972. mov.l 0x14+0x8(%a6),0x8(%a0)
  3973. bsr.l tag # fetch operand type
  3974. mov.b %d0,STAG(%a6)
  3975. mov.l %d0,%d1
  3976. andi.l &0x00ff00ff,USER_FPSR(%a6)
  3977. clr.l %d0
  3978. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  3979. lea FP_SRC(%a6),%a0 # pass ptr to src
  3980. lea FP_DST(%a6),%a1 # pass ptr to dst
  3981. tst.b %d1
  3982. bne.b _L22_2x
  3983. bsr.l smod_snorm # operand is a NORM
  3984. bra.b _L22_6x
  3985. _L22_2x:
  3986. cmpi.b %d1,&ZERO # is operand a ZERO?
  3987. bne.b _L22_3x # no
  3988. bsr.l smod_szero # yes
  3989. bra.b _L22_6x
  3990. _L22_3x:
  3991. cmpi.b %d1,&INF # is operand an INF?
  3992. bne.b _L22_4x # no
  3993. bsr.l smod_sinf # yes
  3994. bra.b _L22_6x
  3995. _L22_4x:
  3996. cmpi.b %d1,&QNAN # is operand a QNAN?
  3997. bne.b _L22_5x # no
  3998. bsr.l sop_sqnan # yes
  3999. bra.b _L22_6x
  4000. _L22_5x:
  4001. bsr.l smod_sdnrm # operand is a DENORM
  4002. _L22_6x:
  4003. #
  4004. # Result is now in FP0
  4005. #
  4006. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  4007. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  4008. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  4009. unlk %a6
  4010. rts
  4011. #########################################################################
  4012. # DYADIC TEMPLATE #
  4013. #########################################################################
  4014. global _fscales_
  4015. _fscales_:
  4016. link %a6,&-LOCAL_SIZE
  4017. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  4018. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  4019. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  4020. fmov.l &0x0,%fpcr # zero FPCR
  4021. #
  4022. # copy, convert, and tag input argument
  4023. #
  4024. fmov.s 0x8(%a6),%fp0 # load sgl dst
  4025. fmov.x %fp0,FP_DST(%a6)
  4026. lea FP_DST(%a6),%a0
  4027. bsr.l tag # fetch operand type
  4028. mov.b %d0,DTAG(%a6)
  4029. fmov.s 0xc(%a6),%fp0 # load sgl src
  4030. fmov.x %fp0,FP_SRC(%a6)
  4031. lea FP_SRC(%a6),%a0
  4032. bsr.l tag # fetch operand type
  4033. mov.b %d0,STAG(%a6)
  4034. mov.l %d0,%d1
  4035. andi.l &0x00ff00ff,USER_FPSR(%a6)
  4036. clr.l %d0
  4037. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  4038. lea FP_SRC(%a6),%a0 # pass ptr to src
  4039. lea FP_DST(%a6),%a1 # pass ptr to dst
  4040. tst.b %d1
  4041. bne.b _L23_2s
  4042. bsr.l sscale_snorm # operand is a NORM
  4043. bra.b _L23_6s
  4044. _L23_2s:
  4045. cmpi.b %d1,&ZERO # is operand a ZERO?
  4046. bne.b _L23_3s # no
  4047. bsr.l sscale_szero # yes
  4048. bra.b _L23_6s
  4049. _L23_3s:
  4050. cmpi.b %d1,&INF # is operand an INF?
  4051. bne.b _L23_4s # no
  4052. bsr.l sscale_sinf # yes
  4053. bra.b _L23_6s
  4054. _L23_4s:
  4055. cmpi.b %d1,&QNAN # is operand a QNAN?
  4056. bne.b _L23_5s # no
  4057. bsr.l sop_sqnan # yes
  4058. bra.b _L23_6s
  4059. _L23_5s:
  4060. bsr.l sscale_sdnrm # operand is a DENORM
  4061. _L23_6s:
  4062. #
  4063. # Result is now in FP0
  4064. #
  4065. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  4066. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  4067. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  4068. unlk %a6
  4069. rts
  4070. global _fscaled_
  4071. _fscaled_:
  4072. link %a6,&-LOCAL_SIZE
  4073. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  4074. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  4075. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  4076. fmov.l &0x0,%fpcr # zero FPCR
  4077. #
  4078. # copy, convert, and tag input argument
  4079. #
  4080. fmov.d 0x8(%a6),%fp0 # load dbl dst
  4081. fmov.x %fp0,FP_DST(%a6)
  4082. lea FP_DST(%a6),%a0
  4083. bsr.l tag # fetch operand type
  4084. mov.b %d0,DTAG(%a6)
  4085. fmov.d 0x10(%a6),%fp0 # load dbl src
  4086. fmov.x %fp0,FP_SRC(%a6)
  4087. lea FP_SRC(%a6),%a0
  4088. bsr.l tag # fetch operand type
  4089. mov.b %d0,STAG(%a6)
  4090. mov.l %d0,%d1
  4091. andi.l &0x00ff00ff,USER_FPSR(%a6)
  4092. clr.l %d0
  4093. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  4094. lea FP_SRC(%a6),%a0 # pass ptr to src
  4095. lea FP_DST(%a6),%a1 # pass ptr to dst
  4096. tst.b %d1
  4097. bne.b _L23_2d
  4098. bsr.l sscale_snorm # operand is a NORM
  4099. bra.b _L23_6d
  4100. _L23_2d:
  4101. cmpi.b %d1,&ZERO # is operand a ZERO?
  4102. bne.b _L23_3d # no
  4103. bsr.l sscale_szero # yes
  4104. bra.b _L23_6d
  4105. _L23_3d:
  4106. cmpi.b %d1,&INF # is operand an INF?
  4107. bne.b _L23_4d # no
  4108. bsr.l sscale_sinf # yes
  4109. bra.b _L23_6d
  4110. _L23_4d:
  4111. cmpi.b %d1,&QNAN # is operand a QNAN?
  4112. bne.b _L23_5d # no
  4113. bsr.l sop_sqnan # yes
  4114. bra.b _L23_6d
  4115. _L23_5d:
  4116. bsr.l sscale_sdnrm # operand is a DENORM
  4117. _L23_6d:
  4118. #
  4119. # Result is now in FP0
  4120. #
  4121. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  4122. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  4123. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  4124. unlk %a6
  4125. rts
  4126. global _fscalex_
  4127. _fscalex_:
  4128. link %a6,&-LOCAL_SIZE
  4129. movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
  4130. fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  4131. fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
  4132. fmov.l &0x0,%fpcr # zero FPCR
  4133. #
  4134. # copy, convert, and tag input argument
  4135. #
  4136. lea FP_DST(%a6),%a0
  4137. mov.l 0x8+0x0(%a6),0x0(%a0) # load ext dst
  4138. mov.l 0x8+0x4(%a6),0x4(%a0)
  4139. mov.l 0x8+0x8(%a6),0x8(%a0)
  4140. bsr.l tag # fetch operand type
  4141. mov.b %d0,DTAG(%a6)
  4142. lea FP_SRC(%a6),%a0
  4143. mov.l 0x14+0x0(%a6),0x0(%a0) # load ext src
  4144. mov.l 0x14+0x4(%a6),0x4(%a0)
  4145. mov.l 0x14+0x8(%a6),0x8(%a0)
  4146. bsr.l tag # fetch operand type
  4147. mov.b %d0,STAG(%a6)
  4148. mov.l %d0,%d1
  4149. andi.l &0x00ff00ff,USER_FPSR(%a6)
  4150. clr.l %d0
  4151. mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
  4152. lea FP_SRC(%a6),%a0 # pass ptr to src
  4153. lea FP_DST(%a6),%a1 # pass ptr to dst
  4154. tst.b %d1
  4155. bne.b _L23_2x
  4156. bsr.l sscale_snorm # operand is a NORM
  4157. bra.b _L23_6x
  4158. _L23_2x:
  4159. cmpi.b %d1,&ZERO # is operand a ZERO?
  4160. bne.b _L23_3x # no
  4161. bsr.l sscale_szero # yes
  4162. bra.b _L23_6x
  4163. _L23_3x:
  4164. cmpi.b %d1,&INF # is operand an INF?
  4165. bne.b _L23_4x # no
  4166. bsr.l sscale_sinf # yes
  4167. bra.b _L23_6x
  4168. _L23_4x:
  4169. cmpi.b %d1,&QNAN # is operand a QNAN?
  4170. bne.b _L23_5x # no
  4171. bsr.l sop_sqnan # yes
  4172. bra.b _L23_6x
  4173. _L23_5x:
  4174. bsr.l sscale_sdnrm # operand is a DENORM
  4175. _L23_6x:
  4176. #
  4177. # Result is now in FP0
  4178. #
  4179. movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
  4180. fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  4181. fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
  4182. unlk %a6
  4183. rts
  4184. #########################################################################
  4185. # ssin(): computes the sine of a normalized input #
  4186. # ssind(): computes the sine of a denormalized input #
  4187. # scos(): computes the cosine of a normalized input #
  4188. # scosd(): computes the cosine of a denormalized input #
  4189. # ssincos(): computes the sine and cosine of a normalized input #
  4190. # ssincosd(): computes the sine and cosine of a denormalized input #
  4191. # #
  4192. # INPUT *************************************************************** #
  4193. # a0 = pointer to extended precision input #
  4194. # d0 = round precision,mode #
  4195. # #
  4196. # OUTPUT ************************************************************** #
  4197. # fp0 = sin(X) or cos(X) #
  4198. # #
  4199. # For ssincos(X): #
  4200. # fp0 = sin(X) #
  4201. # fp1 = cos(X) #
  4202. # #
  4203. # ACCURACY and MONOTONICITY ******************************************* #
  4204. # The returned result is within 1 ulp in 64 significant bit, i.e. #
  4205. # within 0.5001 ulp to 53 bits if the result is subsequently #
  4206. # rounded to double precision. The result is provably monotonic #
  4207. # in double precision. #
  4208. # #
  4209. # ALGORITHM *********************************************************** #
  4210. # #
  4211. # SIN and COS: #
  4212. # 1. If SIN is invoked, set AdjN := 0; otherwise, set AdjN := 1. #
  4213. # #
  4214. # 2. If |X| >= 15Pi or |X| < 2**(-40), go to 7. #
  4215. # #
  4216. # 3. Decompose X as X = N(Pi/2) + r where |r| <= Pi/4. Let #
  4217. # k = N mod 4, so in particular, k = 0,1,2,or 3. #
  4218. # Overwrite k by k := k + AdjN. #
  4219. # #
  4220. # 4. If k is even, go to 6. #
  4221. # #
  4222. # 5. (k is odd) Set j := (k-1)/2, sgn := (-1)**j. #
  4223. # Return sgn*cos(r) where cos(r) is approximated by an #
  4224. # even polynomial in r, 1 + r*r*(B1+s*(B2+ ... + s*B8)), #
  4225. # s = r*r. #
  4226. # Exit. #
  4227. # #
  4228. # 6. (k is even) Set j := k/2, sgn := (-1)**j. Return sgn*sin(r) #
  4229. # where sin(r) is approximated by an odd polynomial in r #
  4230. # r + r*s*(A1+s*(A2+ ... + s*A7)), s = r*r. #
  4231. # Exit. #
  4232. # #
  4233. # 7. If |X| > 1, go to 9. #
  4234. # #
  4235. # 8. (|X|<2**(-40)) If SIN is invoked, return X; #
  4236. # otherwise return 1. #
  4237. # #
  4238. # 9. Overwrite X by X := X rem 2Pi. Now that |X| <= Pi, #
  4239. # go back to 3. #
  4240. # #
  4241. # SINCOS: #
  4242. # 1. If |X| >= 15Pi or |X| < 2**(-40), go to 6. #
  4243. # #
  4244. # 2. Decompose X as X = N(Pi/2) + r where |r| <= Pi/4. Let #
  4245. # k = N mod 4, so in particular, k = 0,1,2,or 3. #
  4246. # #
  4247. # 3. If k is even, go to 5. #
  4248. # #
  4249. # 4. (k is odd) Set j1 := (k-1)/2, j2 := j1 (EOR) (k mod 2), ie. #
  4250. # j1 exclusive or with the l.s.b. of k. #
  4251. # sgn1 := (-1)**j1, sgn2 := (-1)**j2. #
  4252. # SIN(X) = sgn1 * cos(r) and COS(X) = sgn2*sin(r) where #
  4253. # sin(r) and cos(r) are computed as odd and even #
  4254. # polynomials in r, respectively. Exit #
  4255. # #
  4256. # 5. (k is even) Set j1 := k/2, sgn1 := (-1)**j1. #
  4257. # SIN(X) = sgn1 * sin(r) and COS(X) = sgn1*cos(r) where #
  4258. # sin(r) and cos(r) are computed as odd and even #
  4259. # polynomials in r, respectively. Exit #
  4260. # #
  4261. # 6. If |X| > 1, go to 8. #
  4262. # #
  4263. # 7. (|X|<2**(-40)) SIN(X) = X and COS(X) = 1. Exit. #
  4264. # #
  4265. # 8. Overwrite X by X := X rem 2Pi. Now that |X| <= Pi, #
  4266. # go back to 2. #
  4267. # #
  4268. #########################################################################
  4269. SINA7: long 0xBD6AAA77,0xCCC994F5
  4270. SINA6: long 0x3DE61209,0x7AAE8DA1
  4271. SINA5: long 0xBE5AE645,0x2A118AE4
  4272. SINA4: long 0x3EC71DE3,0xA5341531
  4273. SINA3: long 0xBF2A01A0,0x1A018B59,0x00000000,0x00000000
  4274. SINA2: long 0x3FF80000,0x88888888,0x888859AF,0x00000000
  4275. SINA1: long 0xBFFC0000,0xAAAAAAAA,0xAAAAAA99,0x00000000
  4276. COSB8: long 0x3D2AC4D0,0xD6011EE3
  4277. COSB7: long 0xBDA9396F,0x9F45AC19
  4278. COSB6: long 0x3E21EED9,0x0612C972
  4279. COSB5: long 0xBE927E4F,0xB79D9FCF
  4280. COSB4: long 0x3EFA01A0,0x1A01D423,0x00000000,0x00000000
  4281. COSB3: long 0xBFF50000,0xB60B60B6,0x0B61D438,0x00000000
  4282. COSB2: long 0x3FFA0000,0xAAAAAAAA,0xAAAAAB5E
  4283. COSB1: long 0xBF000000
  4284. set INARG,FP_SCR0
  4285. set X,FP_SCR0
  4286. # set XDCARE,X+2
  4287. set XFRAC,X+4
  4288. set RPRIME,FP_SCR0
  4289. set SPRIME,FP_SCR1
  4290. set POSNEG1,L_SCR1
  4291. set TWOTO63,L_SCR1
  4292. set ENDFLAG,L_SCR2
  4293. set INT,L_SCR2
  4294. set ADJN,L_SCR3
  4295. ############################################
  4296. global ssin
  4297. ssin:
  4298. mov.l &0,ADJN(%a6) # yes; SET ADJN TO 0
  4299. bra.b SINBGN
  4300. ############################################
  4301. global scos
  4302. scos:
  4303. mov.l &1,ADJN(%a6) # yes; SET ADJN TO 1
  4304. ############################################
  4305. SINBGN:
  4306. #--SAVE FPCR, FP1. CHECK IF |X| IS TOO SMALL OR LARGE
  4307. fmov.x (%a0),%fp0 # LOAD INPUT
  4308. fmov.x %fp0,X(%a6) # save input at X
  4309. # "COMPACTIFY" X
  4310. mov.l (%a0),%d1 # put exp in hi word
  4311. mov.w 4(%a0),%d1 # fetch hi(man)
  4312. and.l &0x7FFFFFFF,%d1 # strip sign
  4313. cmpi.l %d1,&0x3FD78000 # is |X| >= 2**(-40)?
  4314. bge.b SOK1 # no
  4315. bra.w SINSM # yes; input is very small
  4316. SOK1:
  4317. cmp.l %d1,&0x4004BC7E # is |X| < 15 PI?
  4318. blt.b SINMAIN # no
  4319. bra.w SREDUCEX # yes; input is very large
  4320. #--THIS IS THE USUAL CASE, |X| <= 15 PI.
  4321. #--THE ARGUMENT REDUCTION IS DONE BY TABLE LOOK UP.
  4322. SINMAIN:
  4323. fmov.x %fp0,%fp1
  4324. fmul.d TWOBYPI(%pc),%fp1 # X*2/PI
  4325. lea PITBL+0x200(%pc),%a1 # TABLE OF N*PI/2, N = -32,...,32
  4326. fmov.l %fp1,INT(%a6) # CONVERT TO INTEGER
  4327. mov.l INT(%a6),%d1 # make a copy of N
  4328. asl.l &4,%d1 # N *= 16
  4329. add.l %d1,%a1 # tbl_addr = a1 + (N*16)
  4330. # A1 IS THE ADDRESS OF N*PIBY2
  4331. # ...WHICH IS IN TWO PIECES Y1 & Y2
  4332. fsub.x (%a1)+,%fp0 # X-Y1
  4333. fsub.s (%a1),%fp0 # fp0 = R = (X-Y1)-Y2
  4334. SINCONT:
  4335. #--continuation from REDUCEX
  4336. #--GET N+ADJN AND SEE IF SIN(R) OR COS(R) IS NEEDED
  4337. mov.l INT(%a6),%d1
  4338. add.l ADJN(%a6),%d1 # SEE IF D0 IS ODD OR EVEN
  4339. ror.l &1,%d1 # D0 WAS ODD IFF D0 IS NEGATIVE
  4340. cmp.l %d1,&0
  4341. blt.w COSPOLY
  4342. #--LET J BE THE LEAST SIG. BIT OF D0, LET SGN := (-1)**J.
  4343. #--THEN WE RETURN SGN*SIN(R). SGN*SIN(R) IS COMPUTED BY
  4344. #--R' + R'*S*(A1 + S(A2 + S(A3 + S(A4 + ... + SA7)))), WHERE
  4345. #--R' = SGN*R, S=R*R. THIS CAN BE REWRITTEN AS
  4346. #--R' + R'*S*( [A1+T(A3+T(A5+TA7))] + [S(A2+T(A4+TA6))])
  4347. #--WHERE T=S*S.
  4348. #--NOTE THAT A3 THROUGH A7 ARE STORED IN DOUBLE PRECISION
  4349. #--WHILE A1 AND A2 ARE IN DOUBLE-EXTENDED FORMAT.
  4350. SINPOLY:
  4351. fmovm.x &0x0c,-(%sp) # save fp2/fp3
  4352. fmov.x %fp0,X(%a6) # X IS R
  4353. fmul.x %fp0,%fp0 # FP0 IS S
  4354. fmov.d SINA7(%pc),%fp3
  4355. fmov.d SINA6(%pc),%fp2
  4356. fmov.x %fp0,%fp1
  4357. fmul.x %fp1,%fp1 # FP1 IS T
  4358. ror.l &1,%d1
  4359. and.l &0x80000000,%d1
  4360. # ...LEAST SIG. BIT OF D0 IN SIGN POSITION
  4361. eor.l %d1,X(%a6) # X IS NOW R'= SGN*R
  4362. fmul.x %fp1,%fp3 # TA7
  4363. fmul.x %fp1,%fp2 # TA6
  4364. fadd.d SINA5(%pc),%fp3 # A5+TA7
  4365. fadd.d SINA4(%pc),%fp2 # A4+TA6
  4366. fmul.x %fp1,%fp3 # T(A5+TA7)
  4367. fmul.x %fp1,%fp2 # T(A4+TA6)
  4368. fadd.d SINA3(%pc),%fp3 # A3+T(A5+TA7)
  4369. fadd.x SINA2(%pc),%fp2 # A2+T(A4+TA6)
  4370. fmul.x %fp3,%fp1 # T(A3+T(A5+TA7))
  4371. fmul.x %fp0,%fp2 # S(A2+T(A4+TA6))
  4372. fadd.x SINA1(%pc),%fp1 # A1+T(A3+T(A5+TA7))
  4373. fmul.x X(%a6),%fp0 # R'*S
  4374. fadd.x %fp2,%fp1 # [A1+T(A3+T(A5+TA7))]+[S(A2+T(A4+TA6))]
  4375. fmul.x %fp1,%fp0 # SIN(R')-R'
  4376. fmovm.x (%sp)+,&0x30 # restore fp2/fp3
  4377. fmov.l %d0,%fpcr # restore users round mode,prec
  4378. fadd.x X(%a6),%fp0 # last inst - possible exception set
  4379. bra t_inx2
  4380. #--LET J BE THE LEAST SIG. BIT OF D0, LET SGN := (-1)**J.
  4381. #--THEN WE RETURN SGN*COS(R). SGN*COS(R) IS COMPUTED BY
  4382. #--SGN + S'*(B1 + S(B2 + S(B3 + S(B4 + ... + SB8)))), WHERE
  4383. #--S=R*R AND S'=SGN*S. THIS CAN BE REWRITTEN AS
  4384. #--SGN + S'*([B1+T(B3+T(B5+TB7))] + [S(B2+T(B4+T(B6+TB8)))])
  4385. #--WHERE T=S*S.
  4386. #--NOTE THAT B4 THROUGH B8 ARE STORED IN DOUBLE PRECISION
  4387. #--WHILE B2 AND B3 ARE IN DOUBLE-EXTENDED FORMAT, B1 IS -1/2
  4388. #--AND IS THEREFORE STORED AS SINGLE PRECISION.
  4389. COSPOLY:
  4390. fmovm.x &0x0c,-(%sp) # save fp2/fp3
  4391. fmul.x %fp0,%fp0 # FP0 IS S
  4392. fmov.d COSB8(%pc),%fp2
  4393. fmov.d COSB7(%pc),%fp3
  4394. fmov.x %fp0,%fp1
  4395. fmul.x %fp1,%fp1 # FP1 IS T
  4396. fmov.x %fp0,X(%a6) # X IS S
  4397. ror.l &1,%d1
  4398. and.l &0x80000000,%d1
  4399. # ...LEAST SIG. BIT OF D0 IN SIGN POSITION
  4400. fmul.x %fp1,%fp2 # TB8
  4401. eor.l %d1,X(%a6) # X IS NOW S'= SGN*S
  4402. and.l &0x80000000,%d1
  4403. fmul.x %fp1,%fp3 # TB7
  4404. or.l &0x3F800000,%d1 # D0 IS SGN IN SINGLE
  4405. mov.l %d1,POSNEG1(%a6)
  4406. fadd.d COSB6(%pc),%fp2 # B6+TB8
  4407. fadd.d COSB5(%pc),%fp3 # B5+TB7
  4408. fmul.x %fp1,%fp2 # T(B6+TB8)
  4409. fmul.x %fp1,%fp3 # T(B5+TB7)
  4410. fadd.d COSB4(%pc),%fp2 # B4+T(B6+TB8)
  4411. fadd.x COSB3(%pc),%fp3 # B3+T(B5+TB7)
  4412. fmul.x %fp1,%fp2 # T(B4+T(B6+TB8))
  4413. fmul.x %fp3,%fp1 # T(B3+T(B5+TB7))
  4414. fadd.x COSB2(%pc),%fp2 # B2+T(B4+T(B6+TB8))
  4415. fadd.s COSB1(%pc),%fp1 # B1+T(B3+T(B5+TB7))
  4416. fmul.x %fp2,%fp0 # S(B2+T(B4+T(B6+TB8)))
  4417. fadd.x %fp1,%fp0
  4418. fmul.x X(%a6),%fp0
  4419. fmovm.x (%sp)+,&0x30 # restore fp2/fp3
  4420. fmov.l %d0,%fpcr # restore users round mode,prec
  4421. fadd.s POSNEG1(%a6),%fp0 # last inst - possible exception set
  4422. bra t_inx2
  4423. ##############################################
  4424. # SINe: Big OR Small?
  4425. #--IF |X| > 15PI, WE USE THE GENERAL ARGUMENT REDUCTION.
  4426. #--IF |X| < 2**(-40), RETURN X OR 1.
  4427. SINBORS:
  4428. cmp.l %d1,&0x3FFF8000
  4429. bgt.l SREDUCEX
  4430. SINSM:
  4431. mov.l ADJN(%a6),%d1
  4432. cmp.l %d1,&0
  4433. bgt.b COSTINY
  4434. # here, the operation may underflow iff the precision is sgl or dbl.
  4435. # extended denorms are handled through another entry point.
  4436. SINTINY:
  4437. # mov.w &0x0000,XDCARE(%a6) # JUST IN CASE
  4438. fmov.l %d0,%fpcr # restore users round mode,prec
  4439. mov.b &FMOV_OP,%d1 # last inst is MOVE
  4440. fmov.x X(%a6),%fp0 # last inst - possible exception set
  4441. bra t_catch
  4442. COSTINY:
  4443. fmov.s &0x3F800000,%fp0 # fp0 = 1.0
  4444. fmov.l %d0,%fpcr # restore users round mode,prec
  4445. fadd.s &0x80800000,%fp0 # last inst - possible exception set
  4446. bra t_pinx2
  4447. ################################################
  4448. global ssind
  4449. #--SIN(X) = X FOR DENORMALIZED X
  4450. ssind:
  4451. bra t_extdnrm
  4452. ############################################
  4453. global scosd
  4454. #--COS(X) = 1 FOR DENORMALIZED X
  4455. scosd:
  4456. fmov.s &0x3F800000,%fp0 # fp0 = 1.0
  4457. bra t_pinx2
  4458. ##################################################
  4459. global ssincos
  4460. ssincos:
  4461. #--SET ADJN TO 4
  4462. mov.l &4,ADJN(%a6)
  4463. fmov.x (%a0),%fp0 # LOAD INPUT
  4464. fmov.x %fp0,X(%a6)
  4465. mov.l (%a0),%d1
  4466. mov.w 4(%a0),%d1
  4467. and.l &0x7FFFFFFF,%d1 # COMPACTIFY X
  4468. cmp.l %d1,&0x3FD78000 # |X| >= 2**(-40)?
  4469. bge.b SCOK1
  4470. bra.w SCSM
  4471. SCOK1:
  4472. cmp.l %d1,&0x4004BC7E # |X| < 15 PI?
  4473. blt.b SCMAIN
  4474. bra.w SREDUCEX
  4475. #--THIS IS THE USUAL CASE, |X| <= 15 PI.
  4476. #--THE ARGUMENT REDUCTION IS DONE BY TABLE LOOK UP.
  4477. SCMAIN:
  4478. fmov.x %fp0,%fp1
  4479. fmul.d TWOBYPI(%pc),%fp1 # X*2/PI
  4480. lea PITBL+0x200(%pc),%a1 # TABLE OF N*PI/2, N = -32,...,32
  4481. fmov.l %fp1,INT(%a6) # CONVERT TO INTEGER
  4482. mov.l INT(%a6),%d1
  4483. asl.l &4,%d1
  4484. add.l %d1,%a1 # ADDRESS OF N*PIBY2, IN Y1, Y2
  4485. fsub.x (%a1)+,%fp0 # X-Y1
  4486. fsub.s (%a1),%fp0 # FP0 IS R = (X-Y1)-Y2
  4487. SCCONT:
  4488. #--continuation point from REDUCEX
  4489. mov.l INT(%a6),%d1
  4490. ror.l &1,%d1
  4491. cmp.l %d1,&0 # D0 < 0 IFF N IS ODD
  4492. bge.w NEVEN
  4493. SNODD:
  4494. #--REGISTERS SAVED SO FAR: D0, A0, FP2.
  4495. fmovm.x &0x04,-(%sp) # save fp2
  4496. fmov.x %fp0,RPRIME(%a6)
  4497. fmul.x %fp0,%fp0 # FP0 IS S = R*R
  4498. fmov.d SINA7(%pc),%fp1 # A7
  4499. fmov.d COSB8(%pc),%fp2 # B8
  4500. fmul.x %fp0,%fp1 # SA7
  4501. fmul.x %fp0,%fp2 # SB8
  4502. mov.l %d2,-(%sp)
  4503. mov.l %d1,%d2
  4504. ror.l &1,%d2
  4505. and.l &0x80000000,%d2
  4506. eor.l %d1,%d2
  4507. and.l &0x80000000,%d2
  4508. fadd.d SINA6(%pc),%fp1 # A6+SA7
  4509. fadd.d COSB7(%pc),%fp2 # B7+SB8
  4510. fmul.x %fp0,%fp1 # S(A6+SA7)
  4511. eor.l %d2,RPRIME(%a6)
  4512. mov.l (%sp)+,%d2
  4513. fmul.x %fp0,%fp2 # S(B7+SB8)
  4514. ror.l &1,%d1
  4515. and.l &0x80000000,%d1
  4516. mov.l &0x3F800000,POSNEG1(%a6)
  4517. eor.l %d1,POSNEG1(%a6)
  4518. fadd.d SINA5(%pc),%fp1 # A5+S(A6+SA7)
  4519. fadd.d COSB6(%pc),%fp2 # B6+S(B7+SB8)
  4520. fmul.x %fp0,%fp1 # S(A5+S(A6+SA7))
  4521. fmul.x %fp0,%fp2 # S(B6+S(B7+SB8))
  4522. fmov.x %fp0,SPRIME(%a6)
  4523. fadd.d SINA4(%pc),%fp1 # A4+S(A5+S(A6+SA7))
  4524. eor.l %d1,SPRIME(%a6)
  4525. fadd.d COSB5(%pc),%fp2 # B5+S(B6+S(B7+SB8))
  4526. fmul.x %fp0,%fp1 # S(A4+...)
  4527. fmul.x %fp0,%fp2 # S(B5+...)
  4528. fadd.d SINA3(%pc),%fp1 # A3+S(A4+...)
  4529. fadd.d COSB4(%pc),%fp2 # B4+S(B5+...)
  4530. fmul.x %fp0,%fp1 # S(A3+...)
  4531. fmul.x %fp0,%fp2 # S(B4+...)
  4532. fadd.x SINA2(%pc),%fp1 # A2+S(A3+...)
  4533. fadd.x COSB3(%pc),%fp2 # B3+S(B4+...)
  4534. fmul.x %fp0,%fp1 # S(A2+...)
  4535. fmul.x %fp0,%fp2 # S(B3+...)
  4536. fadd.x SINA1(%pc),%fp1 # A1+S(A2+...)
  4537. fadd.x COSB2(%pc),%fp2 # B2+S(B3+...)
  4538. fmul.x %fp0,%fp1 # S(A1+...)
  4539. fmul.x %fp2,%fp0 # S(B2+...)
  4540. fmul.x RPRIME(%a6),%fp1 # R'S(A1+...)
  4541. fadd.s COSB1(%pc),%fp0 # B1+S(B2...)
  4542. fmul.x SPRIME(%a6),%fp0 # S'(B1+S(B2+...))
  4543. fmovm.x (%sp)+,&0x20 # restore fp2
  4544. fmov.l %d0,%fpcr
  4545. fadd.x RPRIME(%a6),%fp1 # COS(X)
  4546. bsr sto_cos # store cosine result
  4547. fadd.s POSNEG1(%a6),%fp0 # SIN(X)
  4548. bra t_inx2
  4549. NEVEN:
  4550. #--REGISTERS SAVED SO FAR: FP2.
  4551. fmovm.x &0x04,-(%sp) # save fp2
  4552. fmov.x %fp0,RPRIME(%a6)
  4553. fmul.x %fp0,%fp0 # FP0 IS S = R*R
  4554. fmov.d COSB8(%pc),%fp1 # B8
  4555. fmov.d SINA7(%pc),%fp2 # A7
  4556. fmul.x %fp0,%fp1 # SB8
  4557. fmov.x %fp0,SPRIME(%a6)
  4558. fmul.x %fp0,%fp2 # SA7
  4559. ror.l &1,%d1
  4560. and.l &0x80000000,%d1
  4561. fadd.d COSB7(%pc),%fp1 # B7+SB8
  4562. fadd.d SINA6(%pc),%fp2 # A6+SA7
  4563. eor.l %d1,RPRIME(%a6)
  4564. eor.l %d1,SPRIME(%a6)
  4565. fmul.x %fp0,%fp1 # S(B7+SB8)
  4566. or.l &0x3F800000,%d1
  4567. mov.l %d1,POSNEG1(%a6)
  4568. fmul.x %fp0,%fp2 # S(A6+SA7)
  4569. fadd.d COSB6(%pc),%fp1 # B6+S(B7+SB8)
  4570. fadd.d SINA5(%pc),%fp2 # A5+S(A6+SA7)
  4571. fmul.x %fp0,%fp1 # S(B6+S(B7+SB8))
  4572. fmul.x %fp0,%fp2 # S(A5+S(A6+SA7))
  4573. fadd.d COSB5(%pc),%fp1 # B5+S(B6+S(B7+SB8))
  4574. fadd.d SINA4(%pc),%fp2 # A4+S(A5+S(A6+SA7))
  4575. fmul.x %fp0,%fp1 # S(B5+...)
  4576. fmul.x %fp0,%fp2 # S(A4+...)
  4577. fadd.d COSB4(%pc),%fp1 # B4+S(B5+...)
  4578. fadd.d SINA3(%pc),%fp2 # A3+S(A4+...)
  4579. fmul.x %fp0,%fp1 # S(B4+...)
  4580. fmul.x %fp0,%fp2 # S(A3+...)
  4581. fadd.x COSB3(%pc),%fp1 # B3+S(B4+...)
  4582. fadd.x SINA2(%pc),%fp2 # A2+S(A3+...)
  4583. fmul.x %fp0,%fp1 # S(B3+...)
  4584. fmul.x %fp0,%fp2 # S(A2+...)
  4585. fadd.x COSB2(%pc),%fp1 # B2+S(B3+...)
  4586. fadd.x SINA1(%pc),%fp2 # A1+S(A2+...)
  4587. fmul.x %fp0,%fp1 # S(B2+...)
  4588. fmul.x %fp2,%fp0 # s(a1+...)
  4589. fadd.s COSB1(%pc),%fp1 # B1+S(B2...)
  4590. fmul.x RPRIME(%a6),%fp0 # R'S(A1+...)
  4591. fmul.x SPRIME(%a6),%fp1 # S'(B1+S(B2+...))
  4592. fmovm.x (%sp)+,&0x20 # restore fp2
  4593. fmov.l %d0,%fpcr
  4594. fadd.s POSNEG1(%a6),%fp1 # COS(X)
  4595. bsr sto_cos # store cosine result
  4596. fadd.x RPRIME(%a6),%fp0 # SIN(X)
  4597. bra t_inx2
  4598. ################################################
  4599. SCBORS:
  4600. cmp.l %d1,&0x3FFF8000
  4601. bgt.w SREDUCEX
  4602. ################################################
  4603. SCSM:
  4604. # mov.w &0x0000,XDCARE(%a6)
  4605. fmov.s &0x3F800000,%fp1
  4606. fmov.l %d0,%fpcr
  4607. fsub.s &0x00800000,%fp1
  4608. bsr sto_cos # store cosine result
  4609. fmov.l %fpcr,%d0 # d0 must have fpcr,too
  4610. mov.b &FMOV_OP,%d1 # last inst is MOVE
  4611. fmov.x X(%a6),%fp0
  4612. bra t_catch
  4613. ##############################################
  4614. global ssincosd
  4615. #--SIN AND COS OF X FOR DENORMALIZED X
  4616. ssincosd:
  4617. mov.l %d0,-(%sp) # save d0
  4618. fmov.s &0x3F800000,%fp1
  4619. bsr sto_cos # store cosine result
  4620. mov.l (%sp)+,%d0 # restore d0
  4621. bra t_extdnrm
  4622. ############################################
  4623. #--WHEN REDUCEX IS USED, THE CODE WILL INEVITABLY BE SLOW.
  4624. #--THIS REDUCTION METHOD, HOWEVER, IS MUCH FASTER THAN USING
  4625. #--THE REMAINDER INSTRUCTION WHICH IS NOW IN SOFTWARE.
  4626. SREDUCEX:
  4627. fmovm.x &0x3c,-(%sp) # save {fp2-fp5}
  4628. mov.l %d2,-(%sp) # save d2
  4629. fmov.s &0x00000000,%fp1 # fp1 = 0
  4630. #--If compact form of abs(arg) in d0=$7ffeffff, argument is so large that
  4631. #--there is a danger of unwanted overflow in first LOOP iteration. In this
  4632. #--case, reduce argument by one remainder step to make subsequent reduction
  4633. #--safe.
  4634. cmp.l %d1,&0x7ffeffff # is arg dangerously large?
  4635. bne.b SLOOP # no
  4636. # yes; create 2**16383*PI/2
  4637. mov.w &0x7ffe,FP_SCR0_EX(%a6)
  4638. mov.l &0xc90fdaa2,FP_SCR0_HI(%a6)
  4639. clr.l FP_SCR0_LO(%a6)
  4640. # create low half of 2**16383*PI/2 at FP_SCR1
  4641. mov.w &0x7fdc,FP_SCR1_EX(%a6)
  4642. mov.l &0x85a308d3,FP_SCR1_HI(%a6)
  4643. clr.l FP_SCR1_LO(%a6)
  4644. ftest.x %fp0 # test sign of argument
  4645. fblt.w sred_neg
  4646. or.b &0x80,FP_SCR0_EX(%a6) # positive arg
  4647. or.b &0x80,FP_SCR1_EX(%a6)
  4648. sred_neg:
  4649. fadd.x FP_SCR0(%a6),%fp0 # high part of reduction is exact
  4650. fmov.x %fp0,%fp1 # save high result in fp1
  4651. fadd.x FP_SCR1(%a6),%fp0 # low part of reduction
  4652. fsub.x %fp0,%fp1 # determine low component of result
  4653. fadd.x FP_SCR1(%a6),%fp1 # fp0/fp1 are reduced argument.
  4654. #--ON ENTRY, FP0 IS X, ON RETURN, FP0 IS X REM PI/2, |X| <= PI/4.
  4655. #--integer quotient will be stored in N
  4656. #--Intermeditate remainder is 66-bit long; (R,r) in (FP0,FP1)
  4657. SLOOP:
  4658. fmov.x %fp0,INARG(%a6) # +-2**K * F, 1 <= F < 2
  4659. mov.w INARG(%a6),%d1
  4660. mov.l %d1,%a1 # save a copy of D0
  4661. and.l &0x00007FFF,%d1
  4662. sub.l &0x00003FFF,%d1 # d0 = K
  4663. cmp.l %d1,&28
  4664. ble.b SLASTLOOP
  4665. SCONTLOOP:
  4666. sub.l &27,%d1 # d0 = L := K-27
  4667. mov.b &0,ENDFLAG(%a6)
  4668. bra.b SWORK
  4669. SLASTLOOP:
  4670. clr.l %d1 # d0 = L := 0
  4671. mov.b &1,ENDFLAG(%a6)
  4672. SWORK:
  4673. #--FIND THE REMAINDER OF (R,r) W.R.T. 2**L * (PI/2). L IS SO CHOSEN
  4674. #--THAT INT( X * (2/PI) / 2**(L) ) < 2**29.
  4675. #--CREATE 2**(-L) * (2/PI), SIGN(INARG)*2**(63),
  4676. #--2**L * (PIby2_1), 2**L * (PIby2_2)
  4677. mov.l &0x00003FFE,%d2 # BIASED EXP OF 2/PI
  4678. sub.l %d1,%d2 # BIASED EXP OF 2**(-L)*(2/PI)
  4679. mov.l &0xA2F9836E,FP_SCR0_HI(%a6)
  4680. mov.l &0x4E44152A,FP_SCR0_LO(%a6)
  4681. mov.w %d2,FP_SCR0_EX(%a6) # FP_SCR0 = 2**(-L)*(2/PI)
  4682. fmov.x %fp0,%fp2
  4683. fmul.x FP_SCR0(%a6),%fp2 # fp2 = X * 2**(-L)*(2/PI)
  4684. #--WE MUST NOW FIND INT(FP2). SINCE WE NEED THIS VALUE IN
  4685. #--FLOATING POINT FORMAT, THE TWO FMOVE'S FMOVE.L FP <--> N
  4686. #--WILL BE TOO INEFFICIENT. THE WAY AROUND IT IS THAT
  4687. #--(SIGN(INARG)*2**63 + FP2) - SIGN(INARG)*2**63 WILL GIVE
  4688. #--US THE DESIRED VALUE IN FLOATING POINT.
  4689. mov.l %a1,%d2
  4690. swap %d2
  4691. and.l &0x80000000,%d2
  4692. or.l &0x5F000000,%d2 # d2 = SIGN(INARG)*2**63 IN SGL
  4693. mov.l %d2,TWOTO63(%a6)
  4694. fadd.s TWOTO63(%a6),%fp2 # THE FRACTIONAL PART OF FP1 IS ROUNDED
  4695. fsub.s TWOTO63(%a6),%fp2 # fp2 = N
  4696. # fint.x %fp2
  4697. #--CREATING 2**(L)*Piby2_1 and 2**(L)*Piby2_2
  4698. mov.l %d1,%d2 # d2 = L
  4699. add.l &0x00003FFF,%d2 # BIASED EXP OF 2**L * (PI/2)
  4700. mov.w %d2,FP_SCR0_EX(%a6)
  4701. mov.l &0xC90FDAA2,FP_SCR0_HI(%a6)
  4702. clr.l FP_SCR0_LO(%a6) # FP_SCR0 = 2**(L) * Piby2_1
  4703. add.l &0x00003FDD,%d1
  4704. mov.w %d1,FP_SCR1_EX(%a6)
  4705. mov.l &0x85A308D3,FP_SCR1_HI(%a6)
  4706. clr.l FP_SCR1_LO(%a6) # FP_SCR1 = 2**(L) * Piby2_2
  4707. mov.b ENDFLAG(%a6),%d1
  4708. #--We are now ready to perform (R+r) - N*P1 - N*P2, P1 = 2**(L) * Piby2_1 and
  4709. #--P2 = 2**(L) * Piby2_2
  4710. fmov.x %fp2,%fp4 # fp4 = N
  4711. fmul.x FP_SCR0(%a6),%fp4 # fp4 = W = N*P1
  4712. fmov.x %fp2,%fp5 # fp5 = N
  4713. fmul.x FP_SCR1(%a6),%fp5 # fp5 = w = N*P2
  4714. fmov.x %fp4,%fp3 # fp3 = W = N*P1
  4715. #--we want P+p = W+w but |p| <= half ulp of P
  4716. #--Then, we need to compute A := R-P and a := r-p
  4717. fadd.x %fp5,%fp3 # fp3 = P
  4718. fsub.x %fp3,%fp4 # fp4 = W-P
  4719. fsub.x %fp3,%fp0 # fp0 = A := R - P
  4720. fadd.x %fp5,%fp4 # fp4 = p = (W-P)+w
  4721. fmov.x %fp0,%fp3 # fp3 = A
  4722. fsub.x %fp4,%fp1 # fp1 = a := r - p
  4723. #--Now we need to normalize (A,a) to "new (R,r)" where R+r = A+a but
  4724. #--|r| <= half ulp of R.
  4725. fadd.x %fp1,%fp0 # fp0 = R := A+a
  4726. #--No need to calculate r if this is the last loop
  4727. cmp.b %d1,&0
  4728. bgt.w SRESTORE
  4729. #--Need to calculate r
  4730. fsub.x %fp0,%fp3 # fp3 = A-R
  4731. fadd.x %fp3,%fp1 # fp1 = r := (A-R)+a
  4732. bra.w SLOOP
  4733. SRESTORE:
  4734. fmov.l %fp2,INT(%a6)
  4735. mov.l (%sp)+,%d2 # restore d2
  4736. fmovm.x (%sp)+,&0x3c # restore {fp2-fp5}
  4737. mov.l ADJN(%a6),%d1
  4738. cmp.l %d1,&4
  4739. blt.w SINCONT
  4740. bra.w SCCONT
  4741. #########################################################################
  4742. # stan(): computes the tangent of a normalized input #
  4743. # stand(): computes the tangent of a denormalized input #
  4744. # #
  4745. # INPUT *************************************************************** #
  4746. # a0 = pointer to extended precision input #
  4747. # d0 = round precision,mode #
  4748. # #
  4749. # OUTPUT ************************************************************** #
  4750. # fp0 = tan(X) #
  4751. # #
  4752. # ACCURACY and MONOTONICITY ******************************************* #
  4753. # The returned result is within 3 ulp in 64 significant bit, i.e. #
  4754. # within 0.5001 ulp to 53 bits if the result is subsequently #
  4755. # rounded to double precision. The result is provably monotonic #
  4756. # in double precision. #
  4757. # #
  4758. # ALGORITHM *********************************************************** #
  4759. # #
  4760. # 1. If |X| >= 15Pi or |X| < 2**(-40), go to 6. #
  4761. # #
  4762. # 2. Decompose X as X = N(Pi/2) + r where |r| <= Pi/4. Let #
  4763. # k = N mod 2, so in particular, k = 0 or 1. #
  4764. # #
  4765. # 3. If k is odd, go to 5. #
  4766. # #
  4767. # 4. (k is even) Tan(X) = tan(r) and tan(r) is approximated by a #
  4768. # rational function U/V where #
  4769. # U = r + r*s*(P1 + s*(P2 + s*P3)), and #
  4770. # V = 1 + s*(Q1 + s*(Q2 + s*(Q3 + s*Q4))), s = r*r. #
  4771. # Exit. #
  4772. # #
  4773. # 4. (k is odd) Tan(X) = -cot(r). Since tan(r) is approximated by #
  4774. # a rational function U/V where #
  4775. # U = r + r*s*(P1 + s*(P2 + s*P3)), and #
  4776. # V = 1 + s*(Q1 + s*(Q2 + s*(Q3 + s*Q4))), s = r*r, #
  4777. # -Cot(r) = -V/U. Exit. #
  4778. # #
  4779. # 6. If |X| > 1, go to 8. #
  4780. # #
  4781. # 7. (|X|<2**(-40)) Tan(X) = X. Exit. #
  4782. # #
  4783. # 8. Overwrite X by X := X rem 2Pi. Now that |X| <= Pi, go back #
  4784. # to 2. #
  4785. # #
  4786. #########################################################################
  4787. TANQ4:
  4788. long 0x3EA0B759,0xF50F8688
  4789. TANP3:
  4790. long 0xBEF2BAA5,0xA8924F04
  4791. TANQ3:
  4792. long 0xBF346F59,0xB39BA65F,0x00000000,0x00000000
  4793. TANP2:
  4794. long 0x3FF60000,0xE073D3FC,0x199C4A00,0x00000000
  4795. TANQ2:
  4796. long 0x3FF90000,0xD23CD684,0x15D95FA1,0x00000000
  4797. TANP1:
  4798. long 0xBFFC0000,0x8895A6C5,0xFB423BCA,0x00000000
  4799. TANQ1:
  4800. long 0xBFFD0000,0xEEF57E0D,0xA84BC8CE,0x00000000
  4801. INVTWOPI:
  4802. long 0x3FFC0000,0xA2F9836E,0x4E44152A,0x00000000
  4803. TWOPI1:
  4804. long 0x40010000,0xC90FDAA2,0x00000000,0x00000000
  4805. TWOPI2:
  4806. long 0x3FDF0000,0x85A308D4,0x00000000,0x00000000
  4807. #--N*PI/2, -32 <= N <= 32, IN A LEADING TERM IN EXT. AND TRAILING
  4808. #--TERM IN SGL. NOTE THAT PI IS 64-BIT LONG, THUS N*PI/2 IS AT
  4809. #--MOST 69 BITS LONG.
  4810. # global PITBL
  4811. PITBL:
  4812. long 0xC0040000,0xC90FDAA2,0x2168C235,0x21800000
  4813. long 0xC0040000,0xC2C75BCD,0x105D7C23,0xA0D00000
  4814. long 0xC0040000,0xBC7EDCF7,0xFF523611,0xA1E80000
  4815. long 0xC0040000,0xB6365E22,0xEE46F000,0x21480000
  4816. long 0xC0040000,0xAFEDDF4D,0xDD3BA9EE,0xA1200000
  4817. long 0xC0040000,0xA9A56078,0xCC3063DD,0x21FC0000
  4818. long 0xC0040000,0xA35CE1A3,0xBB251DCB,0x21100000
  4819. long 0xC0040000,0x9D1462CE,0xAA19D7B9,0xA1580000
  4820. long 0xC0040000,0x96CBE3F9,0x990E91A8,0x21E00000
  4821. long 0xC0040000,0x90836524,0x88034B96,0x20B00000
  4822. long 0xC0040000,0x8A3AE64F,0x76F80584,0xA1880000
  4823. long 0xC0040000,0x83F2677A,0x65ECBF73,0x21C40000
  4824. long 0xC0030000,0xFB53D14A,0xA9C2F2C2,0x20000000
  4825. long 0xC0030000,0xEEC2D3A0,0x87AC669F,0x21380000
  4826. long 0xC0030000,0xE231D5F6,0x6595DA7B,0xA1300000
  4827. long 0xC0030000,0xD5A0D84C,0x437F4E58,0x9FC00000
  4828. long 0xC0030000,0xC90FDAA2,0x2168C235,0x21000000
  4829. long 0xC0030000,0xBC7EDCF7,0xFF523611,0xA1680000
  4830. long 0xC0030000,0xAFEDDF4D,0xDD3BA9EE,0xA0A00000
  4831. long 0xC0030000,0xA35CE1A3,0xBB251DCB,0x20900000
  4832. long 0xC0030000,0x96CBE3F9,0x990E91A8,0x21600000
  4833. long 0xC0030000,0x8A3AE64F,0x76F80584,0xA1080000
  4834. long 0xC0020000,0xFB53D14A,0xA9C2F2C2,0x1F800000
  4835. long 0xC0020000,0xE231D5F6,0x6595DA7B,0xA0B00000
  4836. long 0xC0020000,0xC90FDAA2,0x2168C235,0x20800000
  4837. long 0xC0020000,0xAFEDDF4D,0xDD3BA9EE,0xA0200000
  4838. long 0xC0020000,0x96CBE3F9,0x990E91A8,0x20E00000
  4839. long 0xC0010000,0xFB53D14A,0xA9C2F2C2,0x1F000000
  4840. long 0xC0010000,0xC90FDAA2,0x2168C235,0x20000000
  4841. long 0xC0010000,0x96CBE3F9,0x990E91A8,0x20600000
  4842. long 0xC0000000,0xC90FDAA2,0x2168C235,0x1F800000
  4843. long 0xBFFF0000,0xC90FDAA2,0x2168C235,0x1F000000
  4844. long 0x00000000,0x00000000,0x00000000,0x00000000
  4845. long 0x3FFF0000,0xC90FDAA2,0x2168C235,0x9F000000
  4846. long 0x40000000,0xC90FDAA2,0x2168C235,0x9F800000
  4847. long 0x40010000,0x96CBE3F9,0x990E91A8,0xA0600000
  4848. long 0x40010000,0xC90FDAA2,0x2168C235,0xA0000000
  4849. long 0x40010000,0xFB53D14A,0xA9C2F2C2,0x9F000000
  4850. long 0x40020000,0x96CBE3F9,0x990E91A8,0xA0E00000
  4851. long 0x40020000,0xAFEDDF4D,0xDD3BA9EE,0x20200000
  4852. long 0x40020000,0xC90FDAA2,0x2168C235,0xA0800000
  4853. long 0x40020000,0xE231D5F6,0x6595DA7B,0x20B00000
  4854. long 0x40020000,0xFB53D14A,0xA9C2F2C2,0x9F800000
  4855. long 0x40030000,0x8A3AE64F,0x76F80584,0x21080000
  4856. long 0x40030000,0x96CBE3F9,0x990E91A8,0xA1600000
  4857. long 0x40030000,0xA35CE1A3,0xBB251DCB,0xA0900000
  4858. long 0x40030000,0xAFEDDF4D,0xDD3BA9EE,0x20A00000
  4859. long 0x40030000,0xBC7EDCF7,0xFF523611,0x21680000
  4860. long 0x40030000,0xC90FDAA2,0x2168C235,0xA1000000
  4861. long 0x40030000,0xD5A0D84C,0x437F4E58,0x1FC00000
  4862. long 0x40030000,0xE231D5F6,0x6595DA7B,0x21300000
  4863. long 0x40030000,0xEEC2D3A0,0x87AC669F,0xA1380000
  4864. long 0x40030000,0xFB53D14A,0xA9C2F2C2,0xA0000000
  4865. long 0x40040000,0x83F2677A,0x65ECBF73,0xA1C40000
  4866. long 0x40040000,0x8A3AE64F,0x76F80584,0x21880000
  4867. long 0x40040000,0x90836524,0x88034B96,0xA0B00000
  4868. long 0x40040000,0x96CBE3F9,0x990E91A8,0xA1E00000
  4869. long 0x40040000,0x9D1462CE,0xAA19D7B9,0x21580000
  4870. long 0x40040000,0xA35CE1A3,0xBB251DCB,0xA1100000
  4871. long 0x40040000,0xA9A56078,0xCC3063DD,0xA1FC0000
  4872. long 0x40040000,0xAFEDDF4D,0xDD3BA9EE,0x21200000
  4873. long 0x40040000,0xB6365E22,0xEE46F000,0xA1480000
  4874. long 0x40040000,0xBC7EDCF7,0xFF523611,0x21E80000
  4875. long 0x40040000,0xC2C75BCD,0x105D7C23,0x20D00000
  4876. long 0x40040000,0xC90FDAA2,0x2168C235,0xA1800000
  4877. set INARG,FP_SCR0
  4878. set TWOTO63,L_SCR1
  4879. set INT,L_SCR1
  4880. set ENDFLAG,L_SCR2
  4881. global stan
  4882. stan:
  4883. fmov.x (%a0),%fp0 # LOAD INPUT
  4884. mov.l (%a0),%d1
  4885. mov.w 4(%a0),%d1
  4886. and.l &0x7FFFFFFF,%d1
  4887. cmp.l %d1,&0x3FD78000 # |X| >= 2**(-40)?
  4888. bge.b TANOK1
  4889. bra.w TANSM
  4890. TANOK1:
  4891. cmp.l %d1,&0x4004BC7E # |X| < 15 PI?
  4892. blt.b TANMAIN
  4893. bra.w REDUCEX
  4894. TANMAIN:
  4895. #--THIS IS THE USUAL CASE, |X| <= 15 PI.
  4896. #--THE ARGUMENT REDUCTION IS DONE BY TABLE LOOK UP.
  4897. fmov.x %fp0,%fp1
  4898. fmul.d TWOBYPI(%pc),%fp1 # X*2/PI
  4899. lea.l PITBL+0x200(%pc),%a1 # TABLE OF N*PI/2, N = -32,...,32
  4900. fmov.l %fp1,%d1 # CONVERT TO INTEGER
  4901. asl.l &4,%d1
  4902. add.l %d1,%a1 # ADDRESS N*PIBY2 IN Y1, Y2
  4903. fsub.x (%a1)+,%fp0 # X-Y1
  4904. fsub.s (%a1),%fp0 # FP0 IS R = (X-Y1)-Y2
  4905. ror.l &5,%d1
  4906. and.l &0x80000000,%d1 # D0 WAS ODD IFF D0 < 0
  4907. TANCONT:
  4908. fmovm.x &0x0c,-(%sp) # save fp2,fp3
  4909. cmp.l %d1,&0
  4910. blt.w NODD
  4911. fmov.x %fp0,%fp1
  4912. fmul.x %fp1,%fp1 # S = R*R
  4913. fmov.d TANQ4(%pc),%fp3
  4914. fmov.d TANP3(%pc),%fp2
  4915. fmul.x %fp1,%fp3 # SQ4
  4916. fmul.x %fp1,%fp2 # SP3
  4917. fadd.d TANQ3(%pc),%fp3 # Q3+SQ4
  4918. fadd.x TANP2(%pc),%fp2 # P2+SP3
  4919. fmul.x %fp1,%fp3 # S(Q3+SQ4)
  4920. fmul.x %fp1,%fp2 # S(P2+SP3)
  4921. fadd.x TANQ2(%pc),%fp3 # Q2+S(Q3+SQ4)
  4922. fadd.x TANP1(%pc),%fp2 # P1+S(P2+SP3)
  4923. fmul.x %fp1,%fp3 # S(Q2+S(Q3+SQ4))
  4924. fmul.x %fp1,%fp2 # S(P1+S(P2+SP3))
  4925. fadd.x TANQ1(%pc),%fp3 # Q1+S(Q2+S(Q3+SQ4))
  4926. fmul.x %fp0,%fp2 # RS(P1+S(P2+SP3))
  4927. fmul.x %fp3,%fp1 # S(Q1+S(Q2+S(Q3+SQ4)))
  4928. fadd.x %fp2,%fp0 # R+RS(P1+S(P2+SP3))
  4929. fadd.s &0x3F800000,%fp1 # 1+S(Q1+...)
  4930. fmovm.x (%sp)+,&0x30 # restore fp2,fp3
  4931. fmov.l %d0,%fpcr # restore users round mode,prec
  4932. fdiv.x %fp1,%fp0 # last inst - possible exception set
  4933. bra t_inx2
  4934. NODD:
  4935. fmov.x %fp0,%fp1
  4936. fmul.x %fp0,%fp0 # S = R*R
  4937. fmov.d TANQ4(%pc),%fp3
  4938. fmov.d TANP3(%pc),%fp2
  4939. fmul.x %fp0,%fp3 # SQ4
  4940. fmul.x %fp0,%fp2 # SP3
  4941. fadd.d TANQ3(%pc),%fp3 # Q3+SQ4
  4942. fadd.x TANP2(%pc),%fp2 # P2+SP3
  4943. fmul.x %fp0,%fp3 # S(Q3+SQ4)
  4944. fmul.x %fp0,%fp2 # S(P2+SP3)
  4945. fadd.x TANQ2(%pc),%fp3 # Q2+S(Q3+SQ4)
  4946. fadd.x TANP1(%pc),%fp2 # P1+S(P2+SP3)
  4947. fmul.x %fp0,%fp3 # S(Q2+S(Q3+SQ4))
  4948. fmul.x %fp0,%fp2 # S(P1+S(P2+SP3))
  4949. fadd.x TANQ1(%pc),%fp3 # Q1+S(Q2+S(Q3+SQ4))
  4950. fmul.x %fp1,%fp2 # RS(P1+S(P2+SP3))
  4951. fmul.x %fp3,%fp0 # S(Q1+S(Q2+S(Q3+SQ4)))
  4952. fadd.x %fp2,%fp1 # R+RS(P1+S(P2+SP3))
  4953. fadd.s &0x3F800000,%fp0 # 1+S(Q1+...)
  4954. fmovm.x (%sp)+,&0x30 # restore fp2,fp3
  4955. fmov.x %fp1,-(%sp)
  4956. eor.l &0x80000000,(%sp)
  4957. fmov.l %d0,%fpcr # restore users round mode,prec
  4958. fdiv.x (%sp)+,%fp0 # last inst - possible exception set
  4959. bra t_inx2
  4960. TANBORS:
  4961. #--IF |X| > 15PI, WE USE THE GENERAL ARGUMENT REDUCTION.
  4962. #--IF |X| < 2**(-40), RETURN X OR 1.
  4963. cmp.l %d1,&0x3FFF8000
  4964. bgt.b REDUCEX
  4965. TANSM:
  4966. fmov.x %fp0,-(%sp)
  4967. fmov.l %d0,%fpcr # restore users round mode,prec
  4968. mov.b &FMOV_OP,%d1 # last inst is MOVE
  4969. fmov.x (%sp)+,%fp0 # last inst - posibble exception set
  4970. bra t_catch
  4971. global stand
  4972. #--TAN(X) = X FOR DENORMALIZED X
  4973. stand:
  4974. bra t_extdnrm
  4975. #--WHEN REDUCEX IS USED, THE CODE WILL INEVITABLY BE SLOW.
  4976. #--THIS REDUCTION METHOD, HOWEVER, IS MUCH FASTER THAN USING
  4977. #--THE REMAINDER INSTRUCTION WHICH IS NOW IN SOFTWARE.
  4978. REDUCEX:
  4979. fmovm.x &0x3c,-(%sp) # save {fp2-fp5}
  4980. mov.l %d2,-(%sp) # save d2
  4981. fmov.s &0x00000000,%fp1 # fp1 = 0
  4982. #--If compact form of abs(arg) in d0=$7ffeffff, argument is so large that
  4983. #--there is a danger of unwanted overflow in first LOOP iteration. In this
  4984. #--case, reduce argument by one remainder step to make subsequent reduction
  4985. #--safe.
  4986. cmp.l %d1,&0x7ffeffff # is arg dangerously large?
  4987. bne.b LOOP # no
  4988. # yes; create 2**16383*PI/2
  4989. mov.w &0x7ffe,FP_SCR0_EX(%a6)
  4990. mov.l &0xc90fdaa2,FP_SCR0_HI(%a6)
  4991. clr.l FP_SCR0_LO(%a6)
  4992. # create low half of 2**16383*PI/2 at FP_SCR1
  4993. mov.w &0x7fdc,FP_SCR1_EX(%a6)
  4994. mov.l &0x85a308d3,FP_SCR1_HI(%a6)
  4995. clr.l FP_SCR1_LO(%a6)
  4996. ftest.x %fp0 # test sign of argument
  4997. fblt.w red_neg
  4998. or.b &0x80,FP_SCR0_EX(%a6) # positive arg
  4999. or.b &0x80,FP_SCR1_EX(%a6)
  5000. red_neg:
  5001. fadd.x FP_SCR0(%a6),%fp0 # high part of reduction is exact
  5002. fmov.x %fp0,%fp1 # save high result in fp1
  5003. fadd.x FP_SCR1(%a6),%fp0 # low part of reduction
  5004. fsub.x %fp0,%fp1 # determine low component of result
  5005. fadd.x FP_SCR1(%a6),%fp1 # fp0/fp1 are reduced argument.
  5006. #--ON ENTRY, FP0 IS X, ON RETURN, FP0 IS X REM PI/2, |X| <= PI/4.
  5007. #--integer quotient will be stored in N
  5008. #--Intermeditate remainder is 66-bit long; (R,r) in (FP0,FP1)
  5009. LOOP:
  5010. fmov.x %fp0,INARG(%a6) # +-2**K * F, 1 <= F < 2
  5011. mov.w INARG(%a6),%d1
  5012. mov.l %d1,%a1 # save a copy of D0
  5013. and.l &0x00007FFF,%d1
  5014. sub.l &0x00003FFF,%d1 # d0 = K
  5015. cmp.l %d1,&28
  5016. ble.b LASTLOOP
  5017. CONTLOOP:
  5018. sub.l &27,%d1 # d0 = L := K-27
  5019. mov.b &0,ENDFLAG(%a6)
  5020. bra.b WORK
  5021. LASTLOOP:
  5022. clr.l %d1 # d0 = L := 0
  5023. mov.b &1,ENDFLAG(%a6)
  5024. WORK:
  5025. #--FIND THE REMAINDER OF (R,r) W.R.T. 2**L * (PI/2). L IS SO CHOSEN
  5026. #--THAT INT( X * (2/PI) / 2**(L) ) < 2**29.
  5027. #--CREATE 2**(-L) * (2/PI), SIGN(INARG)*2**(63),
  5028. #--2**L * (PIby2_1), 2**L * (PIby2_2)
  5029. mov.l &0x00003FFE,%d2 # BIASED EXP OF 2/PI
  5030. sub.l %d1,%d2 # BIASED EXP OF 2**(-L)*(2/PI)
  5031. mov.l &0xA2F9836E,FP_SCR0_HI(%a6)
  5032. mov.l &0x4E44152A,FP_SCR0_LO(%a6)
  5033. mov.w %d2,FP_SCR0_EX(%a6) # FP_SCR0 = 2**(-L)*(2/PI)
  5034. fmov.x %fp0,%fp2
  5035. fmul.x FP_SCR0(%a6),%fp2 # fp2 = X * 2**(-L)*(2/PI)
  5036. #--WE MUST NOW FIND INT(FP2). SINCE WE NEED THIS VALUE IN
  5037. #--FLOATING POINT FORMAT, THE TWO FMOVE'S FMOVE.L FP <--> N
  5038. #--WILL BE TOO INEFFICIENT. THE WAY AROUND IT IS THAT
  5039. #--(SIGN(INARG)*2**63 + FP2) - SIGN(INARG)*2**63 WILL GIVE
  5040. #--US THE DESIRED VALUE IN FLOATING POINT.
  5041. mov.l %a1,%d2
  5042. swap %d2
  5043. and.l &0x80000000,%d2
  5044. or.l &0x5F000000,%d2 # d2 = SIGN(INARG)*2**63 IN SGL
  5045. mov.l %d2,TWOTO63(%a6)
  5046. fadd.s TWOTO63(%a6),%fp2 # THE FRACTIONAL PART OF FP1 IS ROUNDED
  5047. fsub.s TWOTO63(%a6),%fp2 # fp2 = N
  5048. # fintrz.x %fp2,%fp2
  5049. #--CREATING 2**(L)*Piby2_1 and 2**(L)*Piby2_2
  5050. mov.l %d1,%d2 # d2 = L
  5051. add.l &0x00003FFF,%d2 # BIASED EXP OF 2**L * (PI/2)
  5052. mov.w %d2,FP_SCR0_EX(%a6)
  5053. mov.l &0xC90FDAA2,FP_SCR0_HI(%a6)
  5054. clr.l FP_SCR0_LO(%a6) # FP_SCR0 = 2**(L) * Piby2_1
  5055. add.l &0x00003FDD,%d1
  5056. mov.w %d1,FP_SCR1_EX(%a6)
  5057. mov.l &0x85A308D3,FP_SCR1_HI(%a6)
  5058. clr.l FP_SCR1_LO(%a6) # FP_SCR1 = 2**(L) * Piby2_2
  5059. mov.b ENDFLAG(%a6),%d1
  5060. #--We are now ready to perform (R+r) - N*P1 - N*P2, P1 = 2**(L) * Piby2_1 and
  5061. #--P2 = 2**(L) * Piby2_2
  5062. fmov.x %fp2,%fp4 # fp4 = N
  5063. fmul.x FP_SCR0(%a6),%fp4 # fp4 = W = N*P1
  5064. fmov.x %fp2,%fp5 # fp5 = N
  5065. fmul.x FP_SCR1(%a6),%fp5 # fp5 = w = N*P2
  5066. fmov.x %fp4,%fp3 # fp3 = W = N*P1
  5067. #--we want P+p = W+w but |p| <= half ulp of P
  5068. #--Then, we need to compute A := R-P and a := r-p
  5069. fadd.x %fp5,%fp3 # fp3 = P
  5070. fsub.x %fp3,%fp4 # fp4 = W-P
  5071. fsub.x %fp3,%fp0 # fp0 = A := R - P
  5072. fadd.x %fp5,%fp4 # fp4 = p = (W-P)+w
  5073. fmov.x %fp0,%fp3 # fp3 = A
  5074. fsub.x %fp4,%fp1 # fp1 = a := r - p
  5075. #--Now we need to normalize (A,a) to "new (R,r)" where R+r = A+a but
  5076. #--|r| <= half ulp of R.
  5077. fadd.x %fp1,%fp0 # fp0 = R := A+a
  5078. #--No need to calculate r if this is the last loop
  5079. cmp.b %d1,&0
  5080. bgt.w RESTORE
  5081. #--Need to calculate r
  5082. fsub.x %fp0,%fp3 # fp3 = A-R
  5083. fadd.x %fp3,%fp1 # fp1 = r := (A-R)+a
  5084. bra.w LOOP
  5085. RESTORE:
  5086. fmov.l %fp2,INT(%a6)
  5087. mov.l (%sp)+,%d2 # restore d2
  5088. fmovm.x (%sp)+,&0x3c # restore {fp2-fp5}
  5089. mov.l INT(%a6),%d1
  5090. ror.l &1,%d1
  5091. bra.w TANCONT
  5092. #########################################################################
  5093. # satan(): computes the arctangent of a normalized number #
  5094. # satand(): computes the arctangent of a denormalized number #
  5095. # #
  5096. # INPUT *************************************************************** #
  5097. # a0 = pointer to extended precision input #
  5098. # d0 = round precision,mode #
  5099. # #
  5100. # OUTPUT ************************************************************** #
  5101. # fp0 = arctan(X) #
  5102. # #
  5103. # ACCURACY and MONOTONICITY ******************************************* #
  5104. # The returned result is within 2 ulps in 64 significant bit, #
  5105. # i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
  5106. # rounded to double precision. The result is provably monotonic #
  5107. # in double precision. #
  5108. # #
  5109. # ALGORITHM *********************************************************** #
  5110. # Step 1. If |X| >= 16 or |X| < 1/16, go to Step 5. #
  5111. # #
  5112. # Step 2. Let X = sgn * 2**k * 1.xxxxxxxx...x. #
  5113. # Note that k = -4, -3,..., or 3. #
  5114. # Define F = sgn * 2**k * 1.xxxx1, i.e. the first 5 #
  5115. # significant bits of X with a bit-1 attached at the 6-th #
  5116. # bit position. Define u to be u = (X-F) / (1 + X*F). #
  5117. # #
  5118. # Step 3. Approximate arctan(u) by a polynomial poly. #
  5119. # #
  5120. # Step 4. Return arctan(F) + poly, arctan(F) is fetched from a #
  5121. # table of values calculated beforehand. Exit. #
  5122. # #
  5123. # Step 5. If |X| >= 16, go to Step 7. #
  5124. # #
  5125. # Step 6. Approximate arctan(X) by an odd polynomial in X. Exit. #
  5126. # #
  5127. # Step 7. Define X' = -1/X. Approximate arctan(X') by an odd #
  5128. # polynomial in X'. #
  5129. # Arctan(X) = sign(X)*Pi/2 + arctan(X'). Exit. #
  5130. # #
  5131. #########################################################################
  5132. ATANA3: long 0xBFF6687E,0x314987D8
  5133. ATANA2: long 0x4002AC69,0x34A26DB3
  5134. ATANA1: long 0xBFC2476F,0x4E1DA28E
  5135. ATANB6: long 0x3FB34444,0x7F876989
  5136. ATANB5: long 0xBFB744EE,0x7FAF45DB
  5137. ATANB4: long 0x3FBC71C6,0x46940220
  5138. ATANB3: long 0xBFC24924,0x921872F9
  5139. ATANB2: long 0x3FC99999,0x99998FA9
  5140. ATANB1: long 0xBFD55555,0x55555555
  5141. ATANC5: long 0xBFB70BF3,0x98539E6A
  5142. ATANC4: long 0x3FBC7187,0x962D1D7D
  5143. ATANC3: long 0xBFC24924,0x827107B8
  5144. ATANC2: long 0x3FC99999,0x9996263E
  5145. ATANC1: long 0xBFD55555,0x55555536
  5146. PPIBY2: long 0x3FFF0000,0xC90FDAA2,0x2168C235,0x00000000
  5147. NPIBY2: long 0xBFFF0000,0xC90FDAA2,0x2168C235,0x00000000
  5148. PTINY: long 0x00010000,0x80000000,0x00000000,0x00000000
  5149. NTINY: long 0x80010000,0x80000000,0x00000000,0x00000000
  5150. ATANTBL:
  5151. long 0x3FFB0000,0x83D152C5,0x060B7A51,0x00000000
  5152. long 0x3FFB0000,0x8BC85445,0x65498B8B,0x00000000
  5153. long 0x3FFB0000,0x93BE4060,0x17626B0D,0x00000000
  5154. long 0x3FFB0000,0x9BB3078D,0x35AEC202,0x00000000
  5155. long 0x3FFB0000,0xA3A69A52,0x5DDCE7DE,0x00000000
  5156. long 0x3FFB0000,0xAB98E943,0x62765619,0x00000000
  5157. long 0x3FFB0000,0xB389E502,0xF9C59862,0x00000000
  5158. long 0x3FFB0000,0xBB797E43,0x6B09E6FB,0x00000000
  5159. long 0x3FFB0000,0xC367A5C7,0x39E5F446,0x00000000
  5160. long 0x3FFB0000,0xCB544C61,0xCFF7D5C6,0x00000000
  5161. long 0x3FFB0000,0xD33F62F8,0x2488533E,0x00000000
  5162. long 0x3FFB0000,0xDB28DA81,0x62404C77,0x00000000
  5163. long 0x3FFB0000,0xE310A407,0x8AD34F18,0x00000000
  5164. long 0x3FFB0000,0xEAF6B0A8,0x188EE1EB,0x00000000
  5165. long 0x3FFB0000,0xF2DAF194,0x9DBE79D5,0x00000000
  5166. long 0x3FFB0000,0xFABD5813,0x61D47E3E,0x00000000
  5167. long 0x3FFC0000,0x8346AC21,0x0959ECC4,0x00000000
  5168. long 0x3FFC0000,0x8B232A08,0x304282D8,0x00000000
  5169. long 0x3FFC0000,0x92FB70B8,0xD29AE2F9,0x00000000
  5170. long 0x3FFC0000,0x9ACF476F,0x5CCD1CB4,0x00000000
  5171. long 0x3FFC0000,0xA29E7630,0x4954F23F,0x00000000
  5172. long 0x3FFC0000,0xAA68C5D0,0x8AB85230,0x00000000
  5173. long 0x3FFC0000,0xB22DFFFD,0x9D539F83,0x00000000
  5174. long 0x3FFC0000,0xB9EDEF45,0x3E900EA5,0x00000000
  5175. long 0x3FFC0000,0xC1A85F1C,0xC75E3EA5,0x00000000
  5176. long 0x3FFC0000,0xC95D1BE8,0x28138DE6,0x00000000
  5177. long 0x3FFC0000,0xD10BF300,0x840D2DE4,0x00000000
  5178. long 0x3FFC0000,0xD8B4B2BA,0x6BC05E7A,0x00000000
  5179. long 0x3FFC0000,0xE0572A6B,0xB42335F6,0x00000000
  5180. long 0x3FFC0000,0xE7F32A70,0xEA9CAA8F,0x00000000
  5181. long 0x3FFC0000,0xEF888432,0x64ECEFAA,0x00000000
  5182. long 0x3FFC0000,0xF7170A28,0xECC06666,0x00000000
  5183. long 0x3FFD0000,0x812FD288,0x332DAD32,0x00000000
  5184. long 0x3FFD0000,0x88A8D1B1,0x218E4D64,0x00000000
  5185. long 0x3FFD0000,0x9012AB3F,0x23E4AEE8,0x00000000
  5186. long 0x3FFD0000,0x976CC3D4,0x11E7F1B9,0x00000000
  5187. long 0x3FFD0000,0x9EB68949,0x3889A227,0x00000000
  5188. long 0x3FFD0000,0xA5EF72C3,0x4487361B,0x00000000
  5189. long 0x3FFD0000,0xAD1700BA,0xF07A7227,0x00000000
  5190. long 0x3FFD0000,0xB42CBCFA,0xFD37EFB7,0x00000000
  5191. long 0x3FFD0000,0xBB303A94,0x0BA80F89,0x00000000
  5192. long 0x3FFD0000,0xC22115C6,0xFCAEBBAF,0x00000000
  5193. long 0x3FFD0000,0xC8FEF3E6,0x86331221,0x00000000
  5194. long 0x3FFD0000,0xCFC98330,0xB4000C70,0x00000000
  5195. long 0x3FFD0000,0xD6807AA1,0x102C5BF9,0x00000000
  5196. long 0x3FFD0000,0xDD2399BC,0x31252AA3,0x00000000
  5197. long 0x3FFD0000,0xE3B2A855,0x6B8FC517,0x00000000
  5198. long 0x3FFD0000,0xEA2D764F,0x64315989,0x00000000
  5199. long 0x3FFD0000,0xF3BF5BF8,0xBAD1A21D,0x00000000
  5200. long 0x3FFE0000,0x801CE39E,0x0D205C9A,0x00000000
  5201. long 0x3FFE0000,0x8630A2DA,0xDA1ED066,0x00000000
  5202. long 0x3FFE0000,0x8C1AD445,0xF3E09B8C,0x00000000
  5203. long 0x3FFE0000,0x91DB8F16,0x64F350E2,0x00000000
  5204. long 0x3FFE0000,0x97731420,0x365E538C,0x00000000
  5205. long 0x3FFE0000,0x9CE1C8E6,0xA0B8CDBA,0x00000000
  5206. long 0x3FFE0000,0xA22832DB,0xCADAAE09,0x00000000
  5207. long 0x3FFE0000,0xA746F2DD,0xB7602294,0x00000000
  5208. long 0x3FFE0000,0xAC3EC0FB,0x997DD6A2,0x00000000
  5209. long 0x3FFE0000,0xB110688A,0xEBDC6F6A,0x00000000
  5210. long 0x3FFE0000,0xB5BCC490,0x59ECC4B0,0x00000000
  5211. long 0x3FFE0000,0xBA44BC7D,0xD470782F,0x00000000
  5212. long 0x3FFE0000,0xBEA94144,0xFD049AAC,0x00000000
  5213. long 0x3FFE0000,0xC2EB4ABB,0x661628B6,0x00000000
  5214. long 0x3FFE0000,0xC70BD54C,0xE602EE14,0x00000000
  5215. long 0x3FFE0000,0xCD000549,0xADEC7159,0x00000000
  5216. long 0x3FFE0000,0xD48457D2,0xD8EA4EA3,0x00000000
  5217. long 0x3FFE0000,0xDB948DA7,0x12DECE3B,0x00000000
  5218. long 0x3FFE0000,0xE23855F9,0x69E8096A,0x00000000
  5219. long 0x3FFE0000,0xE8771129,0xC4353259,0x00000000
  5220. long 0x3FFE0000,0xEE57C16E,0x0D379C0D,0x00000000
  5221. long 0x3FFE0000,0xF3E10211,0xA87C3779,0x00000000
  5222. long 0x3FFE0000,0xF919039D,0x758B8D41,0x00000000
  5223. long 0x3FFE0000,0xFE058B8F,0x64935FB3,0x00000000
  5224. long 0x3FFF0000,0x8155FB49,0x7B685D04,0x00000000
  5225. long 0x3FFF0000,0x83889E35,0x49D108E1,0x00000000
  5226. long 0x3FFF0000,0x859CFA76,0x511D724B,0x00000000
  5227. long 0x3FFF0000,0x87952ECF,0xFF8131E7,0x00000000
  5228. long 0x3FFF0000,0x89732FD1,0x9557641B,0x00000000
  5229. long 0x3FFF0000,0x8B38CAD1,0x01932A35,0x00000000
  5230. long 0x3FFF0000,0x8CE7A8D8,0x301EE6B5,0x00000000
  5231. long 0x3FFF0000,0x8F46A39E,0x2EAE5281,0x00000000
  5232. long 0x3FFF0000,0x922DA7D7,0x91888487,0x00000000
  5233. long 0x3FFF0000,0x94D19FCB,0xDEDF5241,0x00000000
  5234. long 0x3FFF0000,0x973AB944,0x19D2A08B,0x00000000
  5235. long 0x3FFF0000,0x996FF00E,0x08E10B96,0x00000000
  5236. long 0x3FFF0000,0x9B773F95,0x12321DA7,0x00000000
  5237. long 0x3FFF0000,0x9D55CC32,0x0F935624,0x00000000
  5238. long 0x3FFF0000,0x9F100575,0x006CC571,0x00000000
  5239. long 0x3FFF0000,0xA0A9C290,0xD97CC06C,0x00000000
  5240. long 0x3FFF0000,0xA22659EB,0xEBC0630A,0x00000000
  5241. long 0x3FFF0000,0xA388B4AF,0xF6EF0EC9,0x00000000
  5242. long 0x3FFF0000,0xA4D35F10,0x61D292C4,0x00000000
  5243. long 0x3FFF0000,0xA60895DC,0xFBE3187E,0x00000000
  5244. long 0x3FFF0000,0xA72A51DC,0x7367BEAC,0x00000000
  5245. long 0x3FFF0000,0xA83A5153,0x0956168F,0x00000000
  5246. long 0x3FFF0000,0xA93A2007,0x7539546E,0x00000000
  5247. long 0x3FFF0000,0xAA9E7245,0x023B2605,0x00000000
  5248. long 0x3FFF0000,0xAC4C84BA,0x6FE4D58F,0x00000000
  5249. long 0x3FFF0000,0xADCE4A4A,0x606B9712,0x00000000
  5250. long 0x3FFF0000,0xAF2A2DCD,0x8D263C9C,0x00000000
  5251. long 0x3FFF0000,0xB0656F81,0xF22265C7,0x00000000
  5252. long 0x3FFF0000,0xB1846515,0x0F71496A,0x00000000
  5253. long 0x3FFF0000,0xB28AAA15,0x6F9ADA35,0x00000000
  5254. long 0x3FFF0000,0xB37B44FF,0x3766B895,0x00000000
  5255. long 0x3FFF0000,0xB458C3DC,0xE9630433,0x00000000
  5256. long 0x3FFF0000,0xB525529D,0x562246BD,0x00000000
  5257. long 0x3FFF0000,0xB5E2CCA9,0x5F9D88CC,0x00000000
  5258. long 0x3FFF0000,0xB692CADA,0x7ACA1ADA,0x00000000
  5259. long 0x3FFF0000,0xB736AEA7,0xA6925838,0x00000000
  5260. long 0x3FFF0000,0xB7CFAB28,0x7E9F7B36,0x00000000
  5261. long 0x3FFF0000,0xB85ECC66,0xCB219835,0x00000000
  5262. long 0x3FFF0000,0xB8E4FD5A,0x20A593DA,0x00000000
  5263. long 0x3FFF0000,0xB99F41F6,0x4AFF9BB5,0x00000000
  5264. long 0x3FFF0000,0xBA7F1E17,0x842BBE7B,0x00000000
  5265. long 0x3FFF0000,0xBB471285,0x7637E17D,0x00000000
  5266. long 0x3FFF0000,0xBBFABE8A,0x4788DF6F,0x00000000
  5267. long 0x3FFF0000,0xBC9D0FAD,0x2B689D79,0x00000000
  5268. long 0x3FFF0000,0xBD306A39,0x471ECD86,0x00000000
  5269. long 0x3FFF0000,0xBDB6C731,0x856AF18A,0x00000000
  5270. long 0x3FFF0000,0xBE31CAC5,0x02E80D70,0x00000000
  5271. long 0x3FFF0000,0xBEA2D55C,0xE33194E2,0x00000000
  5272. long 0x3FFF0000,0xBF0B10B7,0xC03128F0,0x00000000
  5273. long 0x3FFF0000,0xBF6B7A18,0xDACB778D,0x00000000
  5274. long 0x3FFF0000,0xBFC4EA46,0x63FA18F6,0x00000000
  5275. long 0x3FFF0000,0xC0181BDE,0x8B89A454,0x00000000
  5276. long 0x3FFF0000,0xC065B066,0xCFBF6439,0x00000000
  5277. long 0x3FFF0000,0xC0AE345F,0x56340AE6,0x00000000
  5278. long 0x3FFF0000,0xC0F22291,0x9CB9E6A7,0x00000000
  5279. set X,FP_SCR0
  5280. set XDCARE,X+2
  5281. set XFRAC,X+4
  5282. set XFRACLO,X+8
  5283. set ATANF,FP_SCR1
  5284. set ATANFHI,ATANF+4
  5285. set ATANFLO,ATANF+8
  5286. global satan
  5287. #--ENTRY POINT FOR ATAN(X), HERE X IS FINITE, NON-ZERO, AND NOT NAN'S
  5288. satan:
  5289. fmov.x (%a0),%fp0 # LOAD INPUT
  5290. mov.l (%a0),%d1
  5291. mov.w 4(%a0),%d1
  5292. fmov.x %fp0,X(%a6)
  5293. and.l &0x7FFFFFFF,%d1
  5294. cmp.l %d1,&0x3FFB8000 # |X| >= 1/16?
  5295. bge.b ATANOK1
  5296. bra.w ATANSM
  5297. ATANOK1:
  5298. cmp.l %d1,&0x4002FFFF # |X| < 16 ?
  5299. ble.b ATANMAIN
  5300. bra.w ATANBIG
  5301. #--THE MOST LIKELY CASE, |X| IN [1/16, 16). WE USE TABLE TECHNIQUE
  5302. #--THE IDEA IS ATAN(X) = ATAN(F) + ATAN( [X-F] / [1+XF] ).
  5303. #--SO IF F IS CHOSEN TO BE CLOSE TO X AND ATAN(F) IS STORED IN
  5304. #--A TABLE, ALL WE NEED IS TO APPROXIMATE ATAN(U) WHERE
  5305. #--U = (X-F)/(1+XF) IS SMALL (REMEMBER F IS CLOSE TO X). IT IS
  5306. #--TRUE THAT A DIVIDE IS NOW NEEDED, BUT THE APPROXIMATION FOR
  5307. #--ATAN(U) IS A VERY SHORT POLYNOMIAL AND THE INDEXING TO
  5308. #--FETCH F AND SAVING OF REGISTERS CAN BE ALL HIDED UNDER THE
  5309. #--DIVIDE. IN THE END THIS METHOD IS MUCH FASTER THAN A TRADITIONAL
  5310. #--ONE. NOTE ALSO THAT THE TRADITIONAL SCHEME THAT APPROXIMATE
  5311. #--ATAN(X) DIRECTLY WILL NEED TO USE A RATIONAL APPROXIMATION
  5312. #--(DIVISION NEEDED) ANYWAY BECAUSE A POLYNOMIAL APPROXIMATION
  5313. #--WILL INVOLVE A VERY LONG POLYNOMIAL.
  5314. #--NOW WE SEE X AS +-2^K * 1.BBBBBBB....B <- 1. + 63 BITS
  5315. #--WE CHOSE F TO BE +-2^K * 1.BBBB1
  5316. #--THAT IS IT MATCHES THE EXPONENT AND FIRST 5 BITS OF X, THE
  5317. #--SIXTH BITS IS SET TO BE 1. SINCE K = -4, -3, ..., 3, THERE
  5318. #--ARE ONLY 8 TIMES 16 = 2^7 = 128 |F|'S. SINCE ATAN(-|F|) IS
  5319. #-- -ATAN(|F|), WE NEED TO STORE ONLY ATAN(|F|).
  5320. ATANMAIN:
  5321. and.l &0xF8000000,XFRAC(%a6) # FIRST 5 BITS
  5322. or.l &0x04000000,XFRAC(%a6) # SET 6-TH BIT TO 1
  5323. mov.l &0x00000000,XFRACLO(%a6) # LOCATION OF X IS NOW F
  5324. fmov.x %fp0,%fp1 # FP1 IS X
  5325. fmul.x X(%a6),%fp1 # FP1 IS X*F, NOTE THAT X*F > 0
  5326. fsub.x X(%a6),%fp0 # FP0 IS X-F
  5327. fadd.s &0x3F800000,%fp1 # FP1 IS 1 + X*F
  5328. fdiv.x %fp1,%fp0 # FP0 IS U = (X-F)/(1+X*F)
  5329. #--WHILE THE DIVISION IS TAKING ITS TIME, WE FETCH ATAN(|F|)
  5330. #--CREATE ATAN(F) AND STORE IT IN ATANF, AND
  5331. #--SAVE REGISTERS FP2.
  5332. mov.l %d2,-(%sp) # SAVE d2 TEMPORARILY
  5333. mov.l %d1,%d2 # THE EXP AND 16 BITS OF X
  5334. and.l &0x00007800,%d1 # 4 VARYING BITS OF F'S FRACTION
  5335. and.l &0x7FFF0000,%d2 # EXPONENT OF F
  5336. sub.l &0x3FFB0000,%d2 # K+4
  5337. asr.l &1,%d2
  5338. add.l %d2,%d1 # THE 7 BITS IDENTIFYING F
  5339. asr.l &7,%d1 # INDEX INTO TBL OF ATAN(|F|)
  5340. lea ATANTBL(%pc),%a1
  5341. add.l %d1,%a1 # ADDRESS OF ATAN(|F|)
  5342. mov.l (%a1)+,ATANF(%a6)
  5343. mov.l (%a1)+,ATANFHI(%a6)
  5344. mov.l (%a1)+,ATANFLO(%a6) # ATANF IS NOW ATAN(|F|)
  5345. mov.l X(%a6),%d1 # LOAD SIGN AND EXPO. AGAIN
  5346. and.l &0x80000000,%d1 # SIGN(F)
  5347. or.l %d1,ATANF(%a6) # ATANF IS NOW SIGN(F)*ATAN(|F|)
  5348. mov.l (%sp)+,%d2 # RESTORE d2
  5349. #--THAT'S ALL I HAVE TO DO FOR NOW,
  5350. #--BUT ALAS, THE DIVIDE IS STILL CRANKING!
  5351. #--U IN FP0, WE ARE NOW READY TO COMPUTE ATAN(U) AS
  5352. #--U + A1*U*V*(A2 + V*(A3 + V)), V = U*U
  5353. #--THE POLYNOMIAL MAY LOOK STRANGE, BUT IS NEVERTHELESS CORRECT.
  5354. #--THE NATURAL FORM IS U + U*V*(A1 + V*(A2 + V*A3))
  5355. #--WHAT WE HAVE HERE IS MERELY A1 = A3, A2 = A1/A3, A3 = A2/A3.
  5356. #--THE REASON FOR THIS REARRANGEMENT IS TO MAKE THE INDEPENDENT
  5357. #--PARTS A1*U*V AND (A2 + ... STUFF) MORE LOAD-BALANCED
  5358. fmovm.x &0x04,-(%sp) # save fp2
  5359. fmov.x %fp0,%fp1
  5360. fmul.x %fp1,%fp1
  5361. fmov.d ATANA3(%pc),%fp2
  5362. fadd.x %fp1,%fp2 # A3+V
  5363. fmul.x %fp1,%fp2 # V*(A3+V)
  5364. fmul.x %fp0,%fp1 # U*V
  5365. fadd.d ATANA2(%pc),%fp2 # A2+V*(A3+V)
  5366. fmul.d ATANA1(%pc),%fp1 # A1*U*V
  5367. fmul.x %fp2,%fp1 # A1*U*V*(A2+V*(A3+V))
  5368. fadd.x %fp1,%fp0 # ATAN(U), FP1 RELEASED
  5369. fmovm.x (%sp)+,&0x20 # restore fp2
  5370. fmov.l %d0,%fpcr # restore users rnd mode,prec
  5371. fadd.x ATANF(%a6),%fp0 # ATAN(X)
  5372. bra t_inx2
  5373. ATANBORS:
  5374. #--|X| IS IN d0 IN COMPACT FORM. FP1, d0 SAVED.
  5375. #--FP0 IS X AND |X| <= 1/16 OR |X| >= 16.
  5376. cmp.l %d1,&0x3FFF8000
  5377. bgt.w ATANBIG # I.E. |X| >= 16
  5378. ATANSM:
  5379. #--|X| <= 1/16
  5380. #--IF |X| < 2^(-40), RETURN X AS ANSWER. OTHERWISE, APPROXIMATE
  5381. #--ATAN(X) BY X + X*Y*(B1+Y*(B2+Y*(B3+Y*(B4+Y*(B5+Y*B6)))))
  5382. #--WHICH IS X + X*Y*( [B1+Z*(B3+Z*B5)] + [Y*(B2+Z*(B4+Z*B6)] )
  5383. #--WHERE Y = X*X, AND Z = Y*Y.
  5384. cmp.l %d1,&0x3FD78000
  5385. blt.w ATANTINY
  5386. #--COMPUTE POLYNOMIAL
  5387. fmovm.x &0x0c,-(%sp) # save fp2/fp3
  5388. fmul.x %fp0,%fp0 # FPO IS Y = X*X
  5389. fmov.x %fp0,%fp1
  5390. fmul.x %fp1,%fp1 # FP1 IS Z = Y*Y
  5391. fmov.d ATANB6(%pc),%fp2
  5392. fmov.d ATANB5(%pc),%fp3
  5393. fmul.x %fp1,%fp2 # Z*B6
  5394. fmul.x %fp1,%fp3 # Z*B5
  5395. fadd.d ATANB4(%pc),%fp2 # B4+Z*B6
  5396. fadd.d ATANB3(%pc),%fp3 # B3+Z*B5
  5397. fmul.x %fp1,%fp2 # Z*(B4+Z*B6)
  5398. fmul.x %fp3,%fp1 # Z*(B3+Z*B5)
  5399. fadd.d ATANB2(%pc),%fp2 # B2+Z*(B4+Z*B6)
  5400. fadd.d ATANB1(%pc),%fp1 # B1+Z*(B3+Z*B5)
  5401. fmul.x %fp0,%fp2 # Y*(B2+Z*(B4+Z*B6))
  5402. fmul.x X(%a6),%fp0 # X*Y
  5403. fadd.x %fp2,%fp1 # [B1+Z*(B3+Z*B5)]+[Y*(B2+Z*(B4+Z*B6))]
  5404. fmul.x %fp1,%fp0 # X*Y*([B1+Z*(B3+Z*B5)]+[Y*(B2+Z*(B4+Z*B6))])
  5405. fmovm.x (%sp)+,&0x30 # restore fp2/fp3
  5406. fmov.l %d0,%fpcr # restore users rnd mode,prec
  5407. fadd.x X(%a6),%fp0
  5408. bra t_inx2
  5409. ATANTINY:
  5410. #--|X| < 2^(-40), ATAN(X) = X
  5411. fmov.l %d0,%fpcr # restore users rnd mode,prec
  5412. mov.b &FMOV_OP,%d1 # last inst is MOVE
  5413. fmov.x X(%a6),%fp0 # last inst - possible exception set
  5414. bra t_catch
  5415. ATANBIG:
  5416. #--IF |X| > 2^(100), RETURN SIGN(X)*(PI/2 - TINY). OTHERWISE,
  5417. #--RETURN SIGN(X)*PI/2 + ATAN(-1/X).
  5418. cmp.l %d1,&0x40638000
  5419. bgt.w ATANHUGE
  5420. #--APPROXIMATE ATAN(-1/X) BY
  5421. #--X'+X'*Y*(C1+Y*(C2+Y*(C3+Y*(C4+Y*C5)))), X' = -1/X, Y = X'*X'
  5422. #--THIS CAN BE RE-WRITTEN AS
  5423. #--X'+X'*Y*( [C1+Z*(C3+Z*C5)] + [Y*(C2+Z*C4)] ), Z = Y*Y.
  5424. fmovm.x &0x0c,-(%sp) # save fp2/fp3
  5425. fmov.s &0xBF800000,%fp1 # LOAD -1
  5426. fdiv.x %fp0,%fp1 # FP1 IS -1/X
  5427. #--DIVIDE IS STILL CRANKING
  5428. fmov.x %fp1,%fp0 # FP0 IS X'
  5429. fmul.x %fp0,%fp0 # FP0 IS Y = X'*X'
  5430. fmov.x %fp1,X(%a6) # X IS REALLY X'
  5431. fmov.x %fp0,%fp1
  5432. fmul.x %fp1,%fp1 # FP1 IS Z = Y*Y
  5433. fmov.d ATANC5(%pc),%fp3
  5434. fmov.d ATANC4(%pc),%fp2
  5435. fmul.x %fp1,%fp3 # Z*C5
  5436. fmul.x %fp1,%fp2 # Z*B4
  5437. fadd.d ATANC3(%pc),%fp3 # C3+Z*C5
  5438. fadd.d ATANC2(%pc),%fp2 # C2+Z*C4
  5439. fmul.x %fp3,%fp1 # Z*(C3+Z*C5), FP3 RELEASED
  5440. fmul.x %fp0,%fp2 # Y*(C2+Z*C4)
  5441. fadd.d ATANC1(%pc),%fp1 # C1+Z*(C3+Z*C5)
  5442. fmul.x X(%a6),%fp0 # X'*Y
  5443. fadd.x %fp2,%fp1 # [Y*(C2+Z*C4)]+[C1+Z*(C3+Z*C5)]
  5444. fmul.x %fp1,%fp0 # X'*Y*([B1+Z*(B3+Z*B5)]
  5445. # ... +[Y*(B2+Z*(B4+Z*B6))])
  5446. fadd.x X(%a6),%fp0
  5447. fmovm.x (%sp)+,&0x30 # restore fp2/fp3
  5448. fmov.l %d0,%fpcr # restore users rnd mode,prec
  5449. tst.b (%a0)
  5450. bpl.b pos_big
  5451. neg_big:
  5452. fadd.x NPIBY2(%pc),%fp0
  5453. bra t_minx2
  5454. pos_big:
  5455. fadd.x PPIBY2(%pc),%fp0
  5456. bra t_pinx2
  5457. ATANHUGE:
  5458. #--RETURN SIGN(X)*(PIBY2 - TINY) = SIGN(X)*PIBY2 - SIGN(X)*TINY
  5459. tst.b (%a0)
  5460. bpl.b pos_huge
  5461. neg_huge:
  5462. fmov.x NPIBY2(%pc),%fp0
  5463. fmov.l %d0,%fpcr
  5464. fadd.x PTINY(%pc),%fp0
  5465. bra t_minx2
  5466. pos_huge:
  5467. fmov.x PPIBY2(%pc),%fp0
  5468. fmov.l %d0,%fpcr
  5469. fadd.x NTINY(%pc),%fp0
  5470. bra t_pinx2
  5471. global satand
  5472. #--ENTRY POINT FOR ATAN(X) FOR DENORMALIZED ARGUMENT
  5473. satand:
  5474. bra t_extdnrm
  5475. #########################################################################
  5476. # sasin(): computes the inverse sine of a normalized input #
  5477. # sasind(): computes the inverse sine of a denormalized input #
  5478. # #
  5479. # INPUT *************************************************************** #
  5480. # a0 = pointer to extended precision input #
  5481. # d0 = round precision,mode #
  5482. # #
  5483. # OUTPUT ************************************************************** #
  5484. # fp0 = arcsin(X) #
  5485. # #
  5486. # ACCURACY and MONOTONICITY ******************************************* #
  5487. # The returned result is within 3 ulps in 64 significant bit, #
  5488. # i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
  5489. # rounded to double precision. The result is provably monotonic #
  5490. # in double precision. #
  5491. # #
  5492. # ALGORITHM *********************************************************** #
  5493. # #
  5494. # ASIN #
  5495. # 1. If |X| >= 1, go to 3. #
  5496. # #
  5497. # 2. (|X| < 1) Calculate asin(X) by #
  5498. # z := sqrt( [1-X][1+X] ) #
  5499. # asin(X) = atan( x / z ). #
  5500. # Exit. #
  5501. # #
  5502. # 3. If |X| > 1, go to 5. #
  5503. # #
  5504. # 4. (|X| = 1) sgn := sign(X), return asin(X) := sgn * Pi/2. Exit.#
  5505. # #
  5506. # 5. (|X| > 1) Generate an invalid operation by 0 * infinity. #
  5507. # Exit. #
  5508. # #
  5509. #########################################################################
  5510. global sasin
  5511. sasin:
  5512. fmov.x (%a0),%fp0 # LOAD INPUT
  5513. mov.l (%a0),%d1
  5514. mov.w 4(%a0),%d1
  5515. and.l &0x7FFFFFFF,%d1
  5516. cmp.l %d1,&0x3FFF8000
  5517. bge.b ASINBIG
  5518. # This catch is added here for the '060 QSP. Originally, the call to
  5519. # satan() would handle this case by causing the exception which would
  5520. # not be caught until gen_except(). Now, with the exceptions being
  5521. # detected inside of satan(), the exception would have been handled there
  5522. # instead of inside sasin() as expected.
  5523. cmp.l %d1,&0x3FD78000
  5524. blt.w ASINTINY
  5525. #--THIS IS THE USUAL CASE, |X| < 1
  5526. #--ASIN(X) = ATAN( X / SQRT( (1-X)(1+X) ) )
  5527. ASINMAIN:
  5528. fmov.s &0x3F800000,%fp1
  5529. fsub.x %fp0,%fp1 # 1-X
  5530. fmovm.x &0x4,-(%sp) # {fp2}
  5531. fmov.s &0x3F800000,%fp2
  5532. fadd.x %fp0,%fp2 # 1+X
  5533. fmul.x %fp2,%fp1 # (1+X)(1-X)
  5534. fmovm.x (%sp)+,&0x20 # {fp2}
  5535. fsqrt.x %fp1 # SQRT([1-X][1+X])
  5536. fdiv.x %fp1,%fp0 # X/SQRT([1-X][1+X])
  5537. fmovm.x &0x01,-(%sp) # save X/SQRT(...)
  5538. lea (%sp),%a0 # pass ptr to X/SQRT(...)
  5539. bsr satan
  5540. add.l &0xc,%sp # clear X/SQRT(...) from stack
  5541. bra t_inx2
  5542. ASINBIG:
  5543. fabs.x %fp0 # |X|
  5544. fcmp.s %fp0,&0x3F800000
  5545. fbgt t_operr # cause an operr exception
  5546. #--|X| = 1, ASIN(X) = +- PI/2.
  5547. ASINONE:
  5548. fmov.x PIBY2(%pc),%fp0
  5549. mov.l (%a0),%d1
  5550. and.l &0x80000000,%d1 # SIGN BIT OF X
  5551. or.l &0x3F800000,%d1 # +-1 IN SGL FORMAT
  5552. mov.l %d1,-(%sp) # push SIGN(X) IN SGL-FMT
  5553. fmov.l %d0,%fpcr
  5554. fmul.s (%sp)+,%fp0
  5555. bra t_inx2
  5556. #--|X| < 2^(-40), ATAN(X) = X
  5557. ASINTINY:
  5558. fmov.l %d0,%fpcr # restore users rnd mode,prec
  5559. mov.b &FMOV_OP,%d1 # last inst is MOVE
  5560. fmov.x (%a0),%fp0 # last inst - possible exception
  5561. bra t_catch
  5562. global sasind
  5563. #--ASIN(X) = X FOR DENORMALIZED X
  5564. sasind:
  5565. bra t_extdnrm
  5566. #########################################################################
  5567. # sacos(): computes the inverse cosine of a normalized input #
  5568. # sacosd(): computes the inverse cosine of a denormalized input #
  5569. # #
  5570. # INPUT *************************************************************** #
  5571. # a0 = pointer to extended precision input #
  5572. # d0 = round precision,mode #
  5573. # #
  5574. # OUTPUT ************************************************************** #
  5575. # fp0 = arccos(X) #
  5576. # #
  5577. # ACCURACY and MONOTONICITY ******************************************* #
  5578. # The returned result is within 3 ulps in 64 significant bit, #
  5579. # i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
  5580. # rounded to double precision. The result is provably monotonic #
  5581. # in double precision. #
  5582. # #
  5583. # ALGORITHM *********************************************************** #
  5584. # #
  5585. # ACOS #
  5586. # 1. If |X| >= 1, go to 3. #
  5587. # #
  5588. # 2. (|X| < 1) Calculate acos(X) by #
  5589. # z := (1-X) / (1+X) #
  5590. # acos(X) = 2 * atan( sqrt(z) ). #
  5591. # Exit. #
  5592. # #
  5593. # 3. If |X| > 1, go to 5. #
  5594. # #
  5595. # 4. (|X| = 1) If X > 0, return 0. Otherwise, return Pi. Exit. #
  5596. # #
  5597. # 5. (|X| > 1) Generate an invalid operation by 0 * infinity. #
  5598. # Exit. #
  5599. # #
  5600. #########################################################################
  5601. global sacos
  5602. sacos:
  5603. fmov.x (%a0),%fp0 # LOAD INPUT
  5604. mov.l (%a0),%d1 # pack exp w/ upper 16 fraction
  5605. mov.w 4(%a0),%d1
  5606. and.l &0x7FFFFFFF,%d1
  5607. cmp.l %d1,&0x3FFF8000
  5608. bge.b ACOSBIG
  5609. #--THIS IS THE USUAL CASE, |X| < 1
  5610. #--ACOS(X) = 2 * ATAN( SQRT( (1-X)/(1+X) ) )
  5611. ACOSMAIN:
  5612. fmov.s &0x3F800000,%fp1
  5613. fadd.x %fp0,%fp1 # 1+X
  5614. fneg.x %fp0 # -X
  5615. fadd.s &0x3F800000,%fp0 # 1-X
  5616. fdiv.x %fp1,%fp0 # (1-X)/(1+X)
  5617. fsqrt.x %fp0 # SQRT((1-X)/(1+X))
  5618. mov.l %d0,-(%sp) # save original users fpcr
  5619. clr.l %d0
  5620. fmovm.x &0x01,-(%sp) # save SQRT(...) to stack
  5621. lea (%sp),%a0 # pass ptr to sqrt
  5622. bsr satan # ATAN(SQRT([1-X]/[1+X]))
  5623. add.l &0xc,%sp # clear SQRT(...) from stack
  5624. fmov.l (%sp)+,%fpcr # restore users round prec,mode
  5625. fadd.x %fp0,%fp0 # 2 * ATAN( STUFF )
  5626. bra t_pinx2
  5627. ACOSBIG:
  5628. fabs.x %fp0
  5629. fcmp.s %fp0,&0x3F800000
  5630. fbgt t_operr # cause an operr exception
  5631. #--|X| = 1, ACOS(X) = 0 OR PI
  5632. tst.b (%a0) # is X positive or negative?
  5633. bpl.b ACOSP1
  5634. #--X = -1
  5635. #Returns PI and inexact exception
  5636. ACOSM1:
  5637. fmov.x PI(%pc),%fp0 # load PI
  5638. fmov.l %d0,%fpcr # load round mode,prec
  5639. fadd.s &0x00800000,%fp0 # add a small value
  5640. bra t_pinx2
  5641. ACOSP1:
  5642. bra ld_pzero # answer is positive zero
  5643. global sacosd
  5644. #--ACOS(X) = PI/2 FOR DENORMALIZED X
  5645. sacosd:
  5646. fmov.l %d0,%fpcr # load user's rnd mode/prec
  5647. fmov.x PIBY2(%pc),%fp0
  5648. bra t_pinx2
  5649. #########################################################################
  5650. # setox(): computes the exponential for a normalized input #
  5651. # setoxd(): computes the exponential for a denormalized input #
  5652. # setoxm1(): computes the exponential minus 1 for a normalized input #
  5653. # setoxm1d(): computes the exponential minus 1 for a denormalized input #
  5654. # #
  5655. # INPUT *************************************************************** #
  5656. # a0 = pointer to extended precision input #
  5657. # d0 = round precision,mode #
  5658. # #
  5659. # OUTPUT ************************************************************** #
  5660. # fp0 = exp(X) or exp(X)-1 #
  5661. # #
  5662. # ACCURACY and MONOTONICITY ******************************************* #
  5663. # The returned result is within 0.85 ulps in 64 significant bit, #
  5664. # i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
  5665. # rounded to double precision. The result is provably monotonic #
  5666. # in double precision. #
  5667. # #
  5668. # ALGORITHM and IMPLEMENTATION **************************************** #
  5669. # #
  5670. # setoxd #
  5671. # ------ #
  5672. # Step 1. Set ans := 1.0 #
  5673. # #
  5674. # Step 2. Return ans := ans + sign(X)*2^(-126). Exit. #
  5675. # Notes: This will always generate one exception -- inexact. #
  5676. # #
  5677. # #
  5678. # setox #
  5679. # ----- #
  5680. # #
  5681. # Step 1. Filter out extreme cases of input argument. #
  5682. # 1.1 If |X| >= 2^(-65), go to Step 1.3. #
  5683. # 1.2 Go to Step 7. #
  5684. # 1.3 If |X| < 16380 log(2), go to Step 2. #
  5685. # 1.4 Go to Step 8. #
  5686. # Notes: The usual case should take the branches 1.1 -> 1.3 -> 2.#
  5687. # To avoid the use of floating-point comparisons, a #
  5688. # compact representation of |X| is used. This format is a #
  5689. # 32-bit integer, the upper (more significant) 16 bits #
  5690. # are the sign and biased exponent field of |X|; the #
  5691. # lower 16 bits are the 16 most significant fraction #
  5692. # (including the explicit bit) bits of |X|. Consequently, #
  5693. # the comparisons in Steps 1.1 and 1.3 can be performed #
  5694. # by integer comparison. Note also that the constant #
  5695. # 16380 log(2) used in Step 1.3 is also in the compact #
  5696. # form. Thus taking the branch to Step 2 guarantees #
  5697. # |X| < 16380 log(2). There is no harm to have a small #
  5698. # number of cases where |X| is less than, but close to, #
  5699. # 16380 log(2) and the branch to Step 9 is taken. #
  5700. # #
  5701. # Step 2. Calculate N = round-to-nearest-int( X * 64/log2 ). #
  5702. # 2.1 Set AdjFlag := 0 (indicates the branch 1.3 -> 2 #
  5703. # was taken) #
  5704. # 2.2 N := round-to-nearest-integer( X * 64/log2 ). #
  5705. # 2.3 Calculate J = N mod 64; so J = 0,1,2,..., #
  5706. # or 63. #
  5707. # 2.4 Calculate M = (N - J)/64; so N = 64M + J. #
  5708. # 2.5 Calculate the address of the stored value of #
  5709. # 2^(J/64). #
  5710. # 2.6 Create the value Scale = 2^M. #
  5711. # Notes: The calculation in 2.2 is really performed by #
  5712. # Z := X * constant #
  5713. # N := round-to-nearest-integer(Z) #
  5714. # where #
  5715. # constant := single-precision( 64/log 2 ). #
  5716. # #
  5717. # Using a single-precision constant avoids memory #
  5718. # access. Another effect of using a single-precision #
  5719. # "constant" is that the calculated value Z is #
  5720. # #
  5721. # Z = X*(64/log2)*(1+eps), |eps| <= 2^(-24). #
  5722. # #
  5723. # This error has to be considered later in Steps 3 and 4. #
  5724. # #
  5725. # Step 3. Calculate X - N*log2/64. #
  5726. # 3.1 R := X + N*L1, #
  5727. # where L1 := single-precision(-log2/64). #
  5728. # 3.2 R := R + N*L2, #
  5729. # L2 := extended-precision(-log2/64 - L1).#
  5730. # Notes: a) The way L1 and L2 are chosen ensures L1+L2 #
  5731. # approximate the value -log2/64 to 88 bits of accuracy. #
  5732. # b) N*L1 is exact because N is no longer than 22 bits #
  5733. # and L1 is no longer than 24 bits. #
  5734. # c) The calculation X+N*L1 is also exact due to #
  5735. # cancellation. Thus, R is practically X+N(L1+L2) to full #
  5736. # 64 bits. #
  5737. # d) It is important to estimate how large can |R| be #
  5738. # after Step 3.2. #
  5739. # #
  5740. # N = rnd-to-int( X*64/log2 (1+eps) ), |eps|<=2^(-24) #
  5741. # X*64/log2 (1+eps) = N + f, |f| <= 0.5 #
  5742. # X*64/log2 - N = f - eps*X 64/log2 #
  5743. # X - N*log2/64 = f*log2/64 - eps*X #
  5744. # #
  5745. # #
  5746. # Now |X| <= 16446 log2, thus #
  5747. # #
  5748. # |X - N*log2/64| <= (0.5 + 16446/2^(18))*log2/64 #
  5749. # <= 0.57 log2/64. #
  5750. # This bound will be used in Step 4. #
  5751. # #
  5752. # Step 4. Approximate exp(R)-1 by a polynomial #
  5753. # p = R + R*R*(A1 + R*(A2 + R*(A3 + R*(A4 + R*A5)))) #
  5754. # Notes: a) In order to reduce memory access, the coefficients #
  5755. # are made as "short" as possible: A1 (which is 1/2), A4 #
  5756. # and A5 are single precision; A2 and A3 are double #
  5757. # precision. #
  5758. # b) Even with the restrictions above, #
  5759. # |p - (exp(R)-1)| < 2^(-68.8) for all |R| <= 0.0062. #
  5760. # Note that 0.0062 is slightly bigger than 0.57 log2/64. #
  5761. # c) To fully utilize the pipeline, p is separated into #
  5762. # two independent pieces of roughly equal complexities #
  5763. # p = [ R + R*S*(A2 + S*A4) ] + #
  5764. # [ S*(A1 + S*(A3 + S*A5)) ] #
  5765. # where S = R*R. #
  5766. # #
  5767. # Step 5. Compute 2^(J/64)*exp(R) = 2^(J/64)*(1+p) by #
  5768. # ans := T + ( T*p + t) #
  5769. # where T and t are the stored values for 2^(J/64). #
  5770. # Notes: 2^(J/64) is stored as T and t where T+t approximates #
  5771. # 2^(J/64) to roughly 85 bits; T is in extended precision #
  5772. # and t is in single precision. Note also that T is #
  5773. # rounded to 62 bits so that the last two bits of T are #
  5774. # zero. The reason for such a special form is that T-1, #
  5775. # T-2, and T-8 will all be exact --- a property that will #
  5776. # give much more accurate computation of the function #
  5777. # EXPM1. #
  5778. # #
  5779. # Step 6. Reconstruction of exp(X) #
  5780. # exp(X) = 2^M * 2^(J/64) * exp(R). #
  5781. # 6.1 If AdjFlag = 0, go to 6.3 #
  5782. # 6.2 ans := ans * AdjScale #
  5783. # 6.3 Restore the user FPCR #
  5784. # 6.4 Return ans := ans * Scale. Exit. #
  5785. # Notes: If AdjFlag = 0, we have X = Mlog2 + Jlog2/64 + R, #
  5786. # |M| <= 16380, and Scale = 2^M. Moreover, exp(X) will #
  5787. # neither overflow nor underflow. If AdjFlag = 1, that #
  5788. # means that #
  5789. # X = (M1+M)log2 + Jlog2/64 + R, |M1+M| >= 16380. #
  5790. # Hence, exp(X) may overflow or underflow or neither. #
  5791. # When that is the case, AdjScale = 2^(M1) where M1 is #
  5792. # approximately M. Thus 6.2 will never cause #
  5793. # over/underflow. Possible exception in 6.4 is overflow #
  5794. # or underflow. The inexact exception is not generated in #
  5795. # 6.4. Although one can argue that the inexact flag #
  5796. # should always be raised, to simulate that exception #
  5797. # cost to much than the flag is worth in practical uses. #
  5798. # #
  5799. # Step 7. Return 1 + X. #
  5800. # 7.1 ans := X #
  5801. # 7.2 Restore user FPCR. #
  5802. # 7.3 Return ans := 1 + ans. Exit #
  5803. # Notes: For non-zero X, the inexact exception will always be #
  5804. # raised by 7.3. That is the only exception raised by 7.3.#
  5805. # Note also that we use the FMOVEM instruction to move X #
  5806. # in Step 7.1 to avoid unnecessary trapping. (Although #
  5807. # the FMOVEM may not seem relevant since X is normalized, #
  5808. # the precaution will be useful in the library version of #
  5809. # this code where the separate entry for denormalized #
  5810. # inputs will be done away with.) #
  5811. # #
  5812. # Step 8. Handle exp(X) where |X| >= 16380log2. #
  5813. # 8.1 If |X| > 16480 log2, go to Step 9. #
  5814. # (mimic 2.2 - 2.6) #
  5815. # 8.2 N := round-to-integer( X * 64/log2 ) #
  5816. # 8.3 Calculate J = N mod 64, J = 0,1,...,63 #
  5817. # 8.4 K := (N-J)/64, M1 := truncate(K/2), M = K-M1, #
  5818. # AdjFlag := 1. #
  5819. # 8.5 Calculate the address of the stored value #
  5820. # 2^(J/64). #
  5821. # 8.6 Create the values Scale = 2^M, AdjScale = 2^M1. #
  5822. # 8.7 Go to Step 3. #
  5823. # Notes: Refer to notes for 2.2 - 2.6. #
  5824. # #
  5825. # Step 9. Handle exp(X), |X| > 16480 log2. #
  5826. # 9.1 If X < 0, go to 9.3 #
  5827. # 9.2 ans := Huge, go to 9.4 #
  5828. # 9.3 ans := Tiny. #
  5829. # 9.4 Restore user FPCR. #
  5830. # 9.5 Return ans := ans * ans. Exit. #
  5831. # Notes: Exp(X) will surely overflow or underflow, depending on #
  5832. # X's sign. "Huge" and "Tiny" are respectively large/tiny #
  5833. # extended-precision numbers whose square over/underflow #
  5834. # with an inexact result. Thus, 9.5 always raises the #
  5835. # inexact together with either overflow or underflow. #
  5836. # #
  5837. # setoxm1d #
  5838. # -------- #
  5839. # #
  5840. # Step 1. Set ans := 0 #
  5841. # #
  5842. # Step 2. Return ans := X + ans. Exit. #
  5843. # Notes: This will return X with the appropriate rounding #
  5844. # precision prescribed by the user FPCR. #
  5845. # #
  5846. # setoxm1 #
  5847. # ------- #
  5848. # #
  5849. # Step 1. Check |X| #
  5850. # 1.1 If |X| >= 1/4, go to Step 1.3. #
  5851. # 1.2 Go to Step 7. #
  5852. # 1.3 If |X| < 70 log(2), go to Step 2. #
  5853. # 1.4 Go to Step 10. #
  5854. # Notes: The usual case should take the branches 1.1 -> 1.3 -> 2.#
  5855. # However, it is conceivable |X| can be small very often #
  5856. # because EXPM1 is intended to evaluate exp(X)-1 #
  5857. # accurately when |X| is small. For further details on #
  5858. # the comparisons, see the notes on Step 1 of setox. #
  5859. # #
  5860. # Step 2. Calculate N = round-to-nearest-int( X * 64/log2 ). #
  5861. # 2.1 N := round-to-nearest-integer( X * 64/log2 ). #
  5862. # 2.2 Calculate J = N mod 64; so J = 0,1,2,..., #
  5863. # or 63. #
  5864. # 2.3 Calculate M = (N - J)/64; so N = 64M + J. #
  5865. # 2.4 Calculate the address of the stored value of #
  5866. # 2^(J/64). #
  5867. # 2.5 Create the values Sc = 2^M and #
  5868. # OnebySc := -2^(-M). #
  5869. # Notes: See the notes on Step 2 of setox. #
  5870. # #
  5871. # Step 3. Calculate X - N*log2/64. #
  5872. # 3.1 R := X + N*L1, #
  5873. # where L1 := single-precision(-log2/64). #
  5874. # 3.2 R := R + N*L2, #
  5875. # L2 := extended-precision(-log2/64 - L1).#
  5876. # Notes: Applying the analysis of Step 3 of setox in this case #
  5877. # shows that |R| <= 0.0055 (note that |X| <= 70 log2 in #
  5878. # this case). #
  5879. # #
  5880. # Step 4. Approximate exp(R)-1 by a polynomial #
  5881. # p = R+R*R*(A1+R*(A2+R*(A3+R*(A4+R*(A5+R*A6))))) #
  5882. # Notes: a) In order to reduce memory access, the coefficients #
  5883. # are made as "short" as possible: A1 (which is 1/2), A5 #
  5884. # and A6 are single precision; A2, A3 and A4 are double #
  5885. # precision. #
  5886. # b) Even with the restriction above, #
  5887. # |p - (exp(R)-1)| < |R| * 2^(-72.7) #
  5888. # for all |R| <= 0.0055. #
  5889. # c) To fully utilize the pipeline, p is separated into #
  5890. # two independent pieces of roughly equal complexity #
  5891. # p = [ R*S*(A2 + S*(A4 + S*A6)) ] + #
  5892. # [ R + S*(A1 + S*(A3 + S*A5)) ] #
  5893. # where S = R*R. #
  5894. # #
  5895. # Step 5. Compute 2^(J/64)*p by #
  5896. # p := T*p #
  5897. # where T and t are the stored values for 2^(J/64). #
  5898. # Notes: 2^(J/64) is stored as T and t where T+t approximates #
  5899. # 2^(J/64) to roughly 85 bits; T is in extended precision #
  5900. # and t is in single precision. Note also that T is #
  5901. # rounded to 62 bits so that the last two bits of T are #
  5902. # zero. The reason for such a special form is that T-1, #
  5903. # T-2, and T-8 will all be exact --- a property that will #
  5904. # be exploited in Step 6 below. The total relative error #
  5905. # in p is no bigger than 2^(-67.7) compared to the final #
  5906. # result. #
  5907. # #
  5908. # Step 6. Reconstruction of exp(X)-1 #
  5909. # exp(X)-1 = 2^M * ( 2^(J/64) + p - 2^(-M) ). #
  5910. # 6.1 If M <= 63, go to Step 6.3. #
  5911. # 6.2 ans := T + (p + (t + OnebySc)). Go to 6.6 #
  5912. # 6.3 If M >= -3, go to 6.5. #
  5913. # 6.4 ans := (T + (p + t)) + OnebySc. Go to 6.6 #
  5914. # 6.5 ans := (T + OnebySc) + (p + t). #
  5915. # 6.6 Restore user FPCR. #
  5916. # 6.7 Return ans := Sc * ans. Exit. #
  5917. # Notes: The various arrangements of the expressions give #
  5918. # accurate evaluations. #
  5919. # #
  5920. # Step 7. exp(X)-1 for |X| < 1/4. #
  5921. # 7.1 If |X| >= 2^(-65), go to Step 9. #
  5922. # 7.2 Go to Step 8. #
  5923. # #
  5924. # Step 8. Calculate exp(X)-1, |X| < 2^(-65). #
  5925. # 8.1 If |X| < 2^(-16312), goto 8.3 #
  5926. # 8.2 Restore FPCR; return ans := X - 2^(-16382). #
  5927. # Exit. #
  5928. # 8.3 X := X * 2^(140). #
  5929. # 8.4 Restore FPCR; ans := ans - 2^(-16382). #
  5930. # Return ans := ans*2^(140). Exit #
  5931. # Notes: The idea is to return "X - tiny" under the user #
  5932. # precision and rounding modes. To avoid unnecessary #
  5933. # inefficiency, we stay away from denormalized numbers #
  5934. # the best we can. For |X| >= 2^(-16312), the #
  5935. # straightforward 8.2 generates the inexact exception as #
  5936. # the case warrants. #
  5937. # #
  5938. # Step 9. Calculate exp(X)-1, |X| < 1/4, by a polynomial #
  5939. # p = X + X*X*(B1 + X*(B2 + ... + X*B12)) #
  5940. # Notes: a) In order to reduce memory access, the coefficients #
  5941. # are made as "short" as possible: B1 (which is 1/2), B9 #
  5942. # to B12 are single precision; B3 to B8 are double #
  5943. # precision; and B2 is double extended. #
  5944. # b) Even with the restriction above, #
  5945. # |p - (exp(X)-1)| < |X| 2^(-70.6) #
  5946. # for all |X| <= 0.251. #
  5947. # Note that 0.251 is slightly bigger than 1/4. #
  5948. # c) To fully preserve accuracy, the polynomial is #
  5949. # computed as #
  5950. # X + ( S*B1 + Q ) where S = X*X and #
  5951. # Q = X*S*(B2 + X*(B3 + ... + X*B12)) #
  5952. # d) To fully utilize the pipeline, Q is separated into #
  5953. # two independent pieces of roughly equal complexity #
  5954. # Q = [ X*S*(B2 + S*(B4 + ... + S*B12)) ] + #
  5955. # [ S*S*(B3 + S*(B5 + ... + S*B11)) ] #
  5956. # #
  5957. # Step 10. Calculate exp(X)-1 for |X| >= 70 log 2. #
  5958. # 10.1 If X >= 70log2 , exp(X) - 1 = exp(X) for all #
  5959. # practical purposes. Therefore, go to Step 1 of setox. #
  5960. # 10.2 If X <= -70log2, exp(X) - 1 = -1 for all practical #
  5961. # purposes. #
  5962. # ans := -1 #
  5963. # Restore user FPCR #
  5964. # Return ans := ans + 2^(-126). Exit. #
  5965. # Notes: 10.2 will always create an inexact and return -1 + tiny #
  5966. # in the user rounding precision and mode. #
  5967. # #
  5968. #########################################################################
  5969. L2: long 0x3FDC0000,0x82E30865,0x4361C4C6,0x00000000
  5970. EEXPA3: long 0x3FA55555,0x55554CC1
  5971. EEXPA2: long 0x3FC55555,0x55554A54
  5972. EM1A4: long 0x3F811111,0x11174385
  5973. EM1A3: long 0x3FA55555,0x55554F5A
  5974. EM1A2: long 0x3FC55555,0x55555555,0x00000000,0x00000000
  5975. EM1B8: long 0x3EC71DE3,0xA5774682
  5976. EM1B7: long 0x3EFA01A0,0x19D7CB68
  5977. EM1B6: long 0x3F2A01A0,0x1A019DF3
  5978. EM1B5: long 0x3F56C16C,0x16C170E2
  5979. EM1B4: long 0x3F811111,0x11111111
  5980. EM1B3: long 0x3FA55555,0x55555555
  5981. EM1B2: long 0x3FFC0000,0xAAAAAAAA,0xAAAAAAAB
  5982. long 0x00000000
  5983. TWO140: long 0x48B00000,0x00000000
  5984. TWON140:
  5985. long 0x37300000,0x00000000
  5986. EEXPTBL:
  5987. long 0x3FFF0000,0x80000000,0x00000000,0x00000000
  5988. long 0x3FFF0000,0x8164D1F3,0xBC030774,0x9F841A9B
  5989. long 0x3FFF0000,0x82CD8698,0xAC2BA1D8,0x9FC1D5B9
  5990. long 0x3FFF0000,0x843A28C3,0xACDE4048,0xA0728369
  5991. long 0x3FFF0000,0x85AAC367,0xCC487B14,0x1FC5C95C
  5992. long 0x3FFF0000,0x871F6196,0x9E8D1010,0x1EE85C9F
  5993. long 0x3FFF0000,0x88980E80,0x92DA8528,0x9FA20729
  5994. long 0x3FFF0000,0x8A14D575,0x496EFD9C,0xA07BF9AF
  5995. long 0x3FFF0000,0x8B95C1E3,0xEA8BD6E8,0xA0020DCF
  5996. long 0x3FFF0000,0x8D1ADF5B,0x7E5BA9E4,0x205A63DA
  5997. long 0x3FFF0000,0x8EA4398B,0x45CD53C0,0x1EB70051
  5998. long 0x3FFF0000,0x9031DC43,0x1466B1DC,0x1F6EB029
  5999. long 0x3FFF0000,0x91C3D373,0xAB11C338,0xA0781494
  6000. long 0x3FFF0000,0x935A2B2F,0x13E6E92C,0x9EB319B0
  6001. long 0x3FFF0000,0x94F4EFA8,0xFEF70960,0x2017457D
  6002. long 0x3FFF0000,0x96942D37,0x20185A00,0x1F11D537
  6003. long 0x3FFF0000,0x9837F051,0x8DB8A970,0x9FB952DD
  6004. long 0x3FFF0000,0x99E04593,0x20B7FA64,0x1FE43087
  6005. long 0x3FFF0000,0x9B8D39B9,0xD54E5538,0x1FA2A818
  6006. long 0x3FFF0000,0x9D3ED9A7,0x2CFFB750,0x1FDE494D
  6007. long 0x3FFF0000,0x9EF53260,0x91A111AC,0x20504890
  6008. long 0x3FFF0000,0xA0B0510F,0xB9714FC4,0xA073691C
  6009. long 0x3FFF0000,0xA2704303,0x0C496818,0x1F9B7A05
  6010. long 0x3FFF0000,0xA43515AE,0x09E680A0,0xA0797126
  6011. long 0x3FFF0000,0xA5FED6A9,0xB15138EC,0xA071A140
  6012. long 0x3FFF0000,0xA7CD93B4,0xE9653568,0x204F62DA
  6013. long 0x3FFF0000,0xA9A15AB4,0xEA7C0EF8,0x1F283C4A
  6014. long 0x3FFF0000,0xAB7A39B5,0xA93ED338,0x9F9A7FDC
  6015. long 0x3FFF0000,0xAD583EEA,0x42A14AC8,0xA05B3FAC
  6016. long 0x3FFF0000,0xAF3B78AD,0x690A4374,0x1FDF2610
  6017. long 0x3FFF0000,0xB123F581,0xD2AC2590,0x9F705F90
  6018. long 0x3FFF0000,0xB311C412,0xA9112488,0x201F678A
  6019. long 0x3FFF0000,0xB504F333,0xF9DE6484,0x1F32FB13
  6020. long 0x3FFF0000,0xB6FD91E3,0x28D17790,0x20038B30
  6021. long 0x3FFF0000,0xB8FBAF47,0x62FB9EE8,0x200DC3CC
  6022. long 0x3FFF0000,0xBAFF5AB2,0x133E45FC,0x9F8B2AE6
  6023. long 0x3FFF0000,0xBD08A39F,0x580C36C0,0xA02BBF70
  6024. long 0x3FFF0000,0xBF1799B6,0x7A731084,0xA00BF518
  6025. long 0x3FFF0000,0xC12C4CCA,0x66709458,0xA041DD41
  6026. long 0x3FFF0000,0xC346CCDA,0x24976408,0x9FDF137B
  6027. long 0x3FFF0000,0xC5672A11,0x5506DADC,0x201F1568
  6028. long 0x3FFF0000,0xC78D74C8,0xABB9B15C,0x1FC13A2E
  6029. long 0x3FFF0000,0xC9B9BD86,0x6E2F27A4,0xA03F8F03
  6030. long 0x3FFF0000,0xCBEC14FE,0xF2727C5C,0x1FF4907D
  6031. long 0x3FFF0000,0xCE248C15,0x1F8480E4,0x9E6E53E4
  6032. long 0x3FFF0000,0xD06333DA,0xEF2B2594,0x1FD6D45C
  6033. long 0x3FFF0000,0xD2A81D91,0xF12AE45C,0xA076EDB9
  6034. long 0x3FFF0000,0xD4F35AAB,0xCFEDFA20,0x9FA6DE21
  6035. long 0x3FFF0000,0xD744FCCA,0xD69D6AF4,0x1EE69A2F
  6036. long 0x3FFF0000,0xD99D15C2,0x78AFD7B4,0x207F439F
  6037. long 0x3FFF0000,0xDBFBB797,0xDAF23754,0x201EC207
  6038. long 0x3FFF0000,0xDE60F482,0x5E0E9124,0x9E8BE175
  6039. long 0x3FFF0000,0xE0CCDEEC,0x2A94E110,0x20032C4B
  6040. long 0x3FFF0000,0xE33F8972,0xBE8A5A50,0x2004DFF5
  6041. long 0x3FFF0000,0xE5B906E7,0x7C8348A8,0x1E72F47A
  6042. long 0x3FFF0000,0xE8396A50,0x3C4BDC68,0x1F722F22
  6043. long 0x3FFF0000,0xEAC0C6E7,0xDD243930,0xA017E945
  6044. long 0x3FFF0000,0xED4F301E,0xD9942B84,0x1F401A5B
  6045. long 0x3FFF0000,0xEFE4B99B,0xDCDAF5CC,0x9FB9A9E3
  6046. long 0x3FFF0000,0xF281773C,0x59FFB138,0x20744C05
  6047. long 0x3FFF0000,0xF5257D15,0x2486CC2C,0x1F773A19
  6048. long 0x3FFF0000,0xF7D0DF73,0x0AD13BB8,0x1FFE90D5
  6049. long 0x3FFF0000,0xFA83B2DB,0x722A033C,0xA041ED22
  6050. long 0x3FFF0000,0xFD3E0C0C,0xF486C174,0x1F853F3A
  6051. set ADJFLAG,L_SCR2
  6052. set SCALE,FP_SCR0
  6053. set ADJSCALE,FP_SCR1
  6054. set SC,FP_SCR0
  6055. set ONEBYSC,FP_SCR1
  6056. global setox
  6057. setox:
  6058. #--entry point for EXP(X), here X is finite, non-zero, and not NaN's
  6059. #--Step 1.
  6060. mov.l (%a0),%d1 # load part of input X
  6061. and.l &0x7FFF0000,%d1 # biased expo. of X
  6062. cmp.l %d1,&0x3FBE0000 # 2^(-65)
  6063. bge.b EXPC1 # normal case
  6064. bra EXPSM
  6065. EXPC1:
  6066. #--The case |X| >= 2^(-65)
  6067. mov.w 4(%a0),%d1 # expo. and partial sig. of |X|
  6068. cmp.l %d1,&0x400CB167 # 16380 log2 trunc. 16 bits
  6069. blt.b EXPMAIN # normal case
  6070. bra EEXPBIG
  6071. EXPMAIN:
  6072. #--Step 2.
  6073. #--This is the normal branch: 2^(-65) <= |X| < 16380 log2.
  6074. fmov.x (%a0),%fp0 # load input from (a0)
  6075. fmov.x %fp0,%fp1
  6076. fmul.s &0x42B8AA3B,%fp0 # 64/log2 * X
  6077. fmovm.x &0xc,-(%sp) # save fp2 {%fp2/%fp3}
  6078. mov.l &0,ADJFLAG(%a6)
  6079. fmov.l %fp0,%d1 # N = int( X * 64/log2 )
  6080. lea EEXPTBL(%pc),%a1
  6081. fmov.l %d1,%fp0 # convert to floating-format
  6082. mov.l %d1,L_SCR1(%a6) # save N temporarily
  6083. and.l &0x3F,%d1 # D0 is J = N mod 64
  6084. lsl.l &4,%d1
  6085. add.l %d1,%a1 # address of 2^(J/64)
  6086. mov.l L_SCR1(%a6),%d1
  6087. asr.l &6,%d1 # D0 is M
  6088. add.w &0x3FFF,%d1 # biased expo. of 2^(M)
  6089. mov.w L2(%pc),L_SCR1(%a6) # prefetch L2, no need in CB
  6090. EXPCONT1:
  6091. #--Step 3.
  6092. #--fp1,fp2 saved on the stack. fp0 is N, fp1 is X,
  6093. #--a0 points to 2^(J/64), D0 is biased expo. of 2^(M)
  6094. fmov.x %fp0,%fp2
  6095. fmul.s &0xBC317218,%fp0 # N * L1, L1 = lead(-log2/64)
  6096. fmul.x L2(%pc),%fp2 # N * L2, L1+L2 = -log2/64
  6097. fadd.x %fp1,%fp0 # X + N*L1
  6098. fadd.x %fp2,%fp0 # fp0 is R, reduced arg.
  6099. #--Step 4.
  6100. #--WE NOW COMPUTE EXP(R)-1 BY A POLYNOMIAL
  6101. #-- R + R*R*(A1 + R*(A2 + R*(A3 + R*(A4 + R*A5))))
  6102. #--TO FULLY UTILIZE THE PIPELINE, WE COMPUTE S = R*R
  6103. #--[R+R*S*(A2+S*A4)] + [S*(A1+S*(A3+S*A5))]
  6104. fmov.x %fp0,%fp1
  6105. fmul.x %fp1,%fp1 # fp1 IS S = R*R
  6106. fmov.s &0x3AB60B70,%fp2 # fp2 IS A5
  6107. fmul.x %fp1,%fp2 # fp2 IS S*A5
  6108. fmov.x %fp1,%fp3
  6109. fmul.s &0x3C088895,%fp3 # fp3 IS S*A4
  6110. fadd.d EEXPA3(%pc),%fp2 # fp2 IS A3+S*A5
  6111. fadd.d EEXPA2(%pc),%fp3 # fp3 IS A2+S*A4
  6112. fmul.x %fp1,%fp2 # fp2 IS S*(A3+S*A5)
  6113. mov.w %d1,SCALE(%a6) # SCALE is 2^(M) in extended
  6114. mov.l &0x80000000,SCALE+4(%a6)
  6115. clr.l SCALE+8(%a6)
  6116. fmul.x %fp1,%fp3 # fp3 IS S*(A2+S*A4)
  6117. fadd.s &0x3F000000,%fp2 # fp2 IS A1+S*(A3+S*A5)
  6118. fmul.x %fp0,%fp3 # fp3 IS R*S*(A2+S*A4)
  6119. fmul.x %fp1,%fp2 # fp2 IS S*(A1+S*(A3+S*A5))
  6120. fadd.x %fp3,%fp0 # fp0 IS R+R*S*(A2+S*A4),
  6121. fmov.x (%a1)+,%fp1 # fp1 is lead. pt. of 2^(J/64)
  6122. fadd.x %fp2,%fp0 # fp0 is EXP(R) - 1
  6123. #--Step 5
  6124. #--final reconstruction process
  6125. #--EXP(X) = 2^M * ( 2^(J/64) + 2^(J/64)*(EXP(R)-1) )
  6126. fmul.x %fp1,%fp0 # 2^(J/64)*(Exp(R)-1)
  6127. fmovm.x (%sp)+,&0x30 # fp2 restored {%fp2/%fp3}
  6128. fadd.s (%a1),%fp0 # accurate 2^(J/64)
  6129. fadd.x %fp1,%fp0 # 2^(J/64) + 2^(J/64)*...
  6130. mov.l ADJFLAG(%a6),%d1
  6131. #--Step 6
  6132. tst.l %d1
  6133. beq.b NORMAL
  6134. ADJUST:
  6135. fmul.x ADJSCALE(%a6),%fp0
  6136. NORMAL:
  6137. fmov.l %d0,%fpcr # restore user FPCR
  6138. mov.b &FMUL_OP,%d1 # last inst is MUL
  6139. fmul.x SCALE(%a6),%fp0 # multiply 2^(M)
  6140. bra t_catch
  6141. EXPSM:
  6142. #--Step 7
  6143. fmovm.x (%a0),&0x80 # load X
  6144. fmov.l %d0,%fpcr
  6145. fadd.s &0x3F800000,%fp0 # 1+X in user mode
  6146. bra t_pinx2
  6147. EEXPBIG:
  6148. #--Step 8
  6149. cmp.l %d1,&0x400CB27C # 16480 log2
  6150. bgt.b EXP2BIG
  6151. #--Steps 8.2 -- 8.6
  6152. fmov.x (%a0),%fp0 # load input from (a0)
  6153. fmov.x %fp0,%fp1
  6154. fmul.s &0x42B8AA3B,%fp0 # 64/log2 * X
  6155. fmovm.x &0xc,-(%sp) # save fp2 {%fp2/%fp3}
  6156. mov.l &1,ADJFLAG(%a6)
  6157. fmov.l %fp0,%d1 # N = int( X * 64/log2 )
  6158. lea EEXPTBL(%pc),%a1
  6159. fmov.l %d1,%fp0 # convert to floating-format
  6160. mov.l %d1,L_SCR1(%a6) # save N temporarily
  6161. and.l &0x3F,%d1 # D0 is J = N mod 64
  6162. lsl.l &4,%d1
  6163. add.l %d1,%a1 # address of 2^(J/64)
  6164. mov.l L_SCR1(%a6),%d1
  6165. asr.l &6,%d1 # D0 is K
  6166. mov.l %d1,L_SCR1(%a6) # save K temporarily
  6167. asr.l &1,%d1 # D0 is M1
  6168. sub.l %d1,L_SCR1(%a6) # a1 is M
  6169. add.w &0x3FFF,%d1 # biased expo. of 2^(M1)
  6170. mov.w %d1,ADJSCALE(%a6) # ADJSCALE := 2^(M1)
  6171. mov.l &0x80000000,ADJSCALE+4(%a6)
  6172. clr.l ADJSCALE+8(%a6)
  6173. mov.l L_SCR1(%a6),%d1 # D0 is M
  6174. add.w &0x3FFF,%d1 # biased expo. of 2^(M)
  6175. bra.w EXPCONT1 # go back to Step 3
  6176. EXP2BIG:
  6177. #--Step 9
  6178. tst.b (%a0) # is X positive or negative?
  6179. bmi t_unfl2
  6180. bra t_ovfl2
  6181. global setoxd
  6182. setoxd:
  6183. #--entry point for EXP(X), X is denormalized
  6184. mov.l (%a0),-(%sp)
  6185. andi.l &0x80000000,(%sp)
  6186. ori.l &0x00800000,(%sp) # sign(X)*2^(-126)
  6187. fmov.s &0x3F800000,%fp0
  6188. fmov.l %d0,%fpcr
  6189. fadd.s (%sp)+,%fp0
  6190. bra t_pinx2
  6191. global setoxm1
  6192. setoxm1:
  6193. #--entry point for EXPM1(X), here X is finite, non-zero, non-NaN
  6194. #--Step 1.
  6195. #--Step 1.1
  6196. mov.l (%a0),%d1 # load part of input X
  6197. and.l &0x7FFF0000,%d1 # biased expo. of X
  6198. cmp.l %d1,&0x3FFD0000 # 1/4
  6199. bge.b EM1CON1 # |X| >= 1/4
  6200. bra EM1SM
  6201. EM1CON1:
  6202. #--Step 1.3
  6203. #--The case |X| >= 1/4
  6204. mov.w 4(%a0),%d1 # expo. and partial sig. of |X|
  6205. cmp.l %d1,&0x4004C215 # 70log2 rounded up to 16 bits
  6206. ble.b EM1MAIN # 1/4 <= |X| <= 70log2
  6207. bra EM1BIG
  6208. EM1MAIN:
  6209. #--Step 2.
  6210. #--This is the case: 1/4 <= |X| <= 70 log2.
  6211. fmov.x (%a0),%fp0 # load input from (a0)
  6212. fmov.x %fp0,%fp1
  6213. fmul.s &0x42B8AA3B,%fp0 # 64/log2 * X
  6214. fmovm.x &0xc,-(%sp) # save fp2 {%fp2/%fp3}
  6215. fmov.l %fp0,%d1 # N = int( X * 64/log2 )
  6216. lea EEXPTBL(%pc),%a1
  6217. fmov.l %d1,%fp0 # convert to floating-format
  6218. mov.l %d1,L_SCR1(%a6) # save N temporarily
  6219. and.l &0x3F,%d1 # D0 is J = N mod 64
  6220. lsl.l &4,%d1
  6221. add.l %d1,%a1 # address of 2^(J/64)
  6222. mov.l L_SCR1(%a6),%d1
  6223. asr.l &6,%d1 # D0 is M
  6224. mov.l %d1,L_SCR1(%a6) # save a copy of M
  6225. #--Step 3.
  6226. #--fp1,fp2 saved on the stack. fp0 is N, fp1 is X,
  6227. #--a0 points to 2^(J/64), D0 and a1 both contain M
  6228. fmov.x %fp0,%fp2
  6229. fmul.s &0xBC317218,%fp0 # N * L1, L1 = lead(-log2/64)
  6230. fmul.x L2(%pc),%fp2 # N * L2, L1+L2 = -log2/64
  6231. fadd.x %fp1,%fp0 # X + N*L1
  6232. fadd.x %fp2,%fp0 # fp0 is R, reduced arg.
  6233. add.w &0x3FFF,%d1 # D0 is biased expo. of 2^M
  6234. #--Step 4.
  6235. #--WE NOW COMPUTE EXP(R)-1 BY A POLYNOMIAL
  6236. #-- R + R*R*(A1 + R*(A2 + R*(A3 + R*(A4 + R*(A5 + R*A6)))))
  6237. #--TO FULLY UTILIZE THE PIPELINE, WE COMPUTE S = R*R
  6238. #--[R*S*(A2+S*(A4+S*A6))] + [R+S*(A1+S*(A3+S*A5))]
  6239. fmov.x %fp0,%fp1
  6240. fmul.x %fp1,%fp1 # fp1 IS S = R*R
  6241. fmov.s &0x3950097B,%fp2 # fp2 IS a6
  6242. fmul.x %fp1,%fp2 # fp2 IS S*A6
  6243. fmov.x %fp1,%fp3
  6244. fmul.s &0x3AB60B6A,%fp3 # fp3 IS S*A5
  6245. fadd.d EM1A4(%pc),%fp2 # fp2 IS A4+S*A6
  6246. fadd.d EM1A3(%pc),%fp3 # fp3 IS A3+S*A5
  6247. mov.w %d1,SC(%a6) # SC is 2^(M) in extended
  6248. mov.l &0x80000000,SC+4(%a6)
  6249. clr.l SC+8(%a6)
  6250. fmul.x %fp1,%fp2 # fp2 IS S*(A4+S*A6)
  6251. mov.l L_SCR1(%a6),%d1 # D0 is M
  6252. neg.w %d1 # D0 is -M
  6253. fmul.x %fp1,%fp3 # fp3 IS S*(A3+S*A5)
  6254. add.w &0x3FFF,%d1 # biased expo. of 2^(-M)
  6255. fadd.d EM1A2(%pc),%fp2 # fp2 IS A2+S*(A4+S*A6)
  6256. fadd.s &0x3F000000,%fp3 # fp3 IS A1+S*(A3+S*A5)
  6257. fmul.x %fp1,%fp2 # fp2 IS S*(A2+S*(A4+S*A6))
  6258. or.w &0x8000,%d1 # signed/expo. of -2^(-M)
  6259. mov.w %d1,ONEBYSC(%a6) # OnebySc is -2^(-M)
  6260. mov.l &0x80000000,ONEBYSC+4(%a6)
  6261. clr.l ONEBYSC+8(%a6)
  6262. fmul.x %fp3,%fp1 # fp1 IS S*(A1+S*(A3+S*A5))
  6263. fmul.x %fp0,%fp2 # fp2 IS R*S*(A2+S*(A4+S*A6))
  6264. fadd.x %fp1,%fp0 # fp0 IS R+S*(A1+S*(A3+S*A5))
  6265. fadd.x %fp2,%fp0 # fp0 IS EXP(R)-1
  6266. fmovm.x (%sp)+,&0x30 # fp2 restored {%fp2/%fp3}
  6267. #--Step 5
  6268. #--Compute 2^(J/64)*p
  6269. fmul.x (%a1),%fp0 # 2^(J/64)*(Exp(R)-1)
  6270. #--Step 6
  6271. #--Step 6.1
  6272. mov.l L_SCR1(%a6),%d1 # retrieve M
  6273. cmp.l %d1,&63
  6274. ble.b MLE63
  6275. #--Step 6.2 M >= 64
  6276. fmov.s 12(%a1),%fp1 # fp1 is t
  6277. fadd.x ONEBYSC(%a6),%fp1 # fp1 is t+OnebySc
  6278. fadd.x %fp1,%fp0 # p+(t+OnebySc), fp1 released
  6279. fadd.x (%a1),%fp0 # T+(p+(t+OnebySc))
  6280. bra EM1SCALE
  6281. MLE63:
  6282. #--Step 6.3 M <= 63
  6283. cmp.l %d1,&-3
  6284. bge.b MGEN3
  6285. MLTN3:
  6286. #--Step 6.4 M <= -4
  6287. fadd.s 12(%a1),%fp0 # p+t
  6288. fadd.x (%a1),%fp0 # T+(p+t)
  6289. fadd.x ONEBYSC(%a6),%fp0 # OnebySc + (T+(p+t))
  6290. bra EM1SCALE
  6291. MGEN3:
  6292. #--Step 6.5 -3 <= M <= 63
  6293. fmov.x (%a1)+,%fp1 # fp1 is T
  6294. fadd.s (%a1),%fp0 # fp0 is p+t
  6295. fadd.x ONEBYSC(%a6),%fp1 # fp1 is T+OnebySc
  6296. fadd.x %fp1,%fp0 # (T+OnebySc)+(p+t)
  6297. EM1SCALE:
  6298. #--Step 6.6
  6299. fmov.l %d0,%fpcr
  6300. fmul.x SC(%a6),%fp0
  6301. bra t_inx2
  6302. EM1SM:
  6303. #--Step 7 |X| < 1/4.
  6304. cmp.l %d1,&0x3FBE0000 # 2^(-65)
  6305. bge.b EM1POLY
  6306. EM1TINY:
  6307. #--Step 8 |X| < 2^(-65)
  6308. cmp.l %d1,&0x00330000 # 2^(-16312)
  6309. blt.b EM12TINY
  6310. #--Step 8.2
  6311. mov.l &0x80010000,SC(%a6) # SC is -2^(-16382)
  6312. mov.l &0x80000000,SC+4(%a6)
  6313. clr.l SC+8(%a6)
  6314. fmov.x (%a0),%fp0
  6315. fmov.l %d0,%fpcr
  6316. mov.b &FADD_OP,%d1 # last inst is ADD
  6317. fadd.x SC(%a6),%fp0
  6318. bra t_catch
  6319. EM12TINY:
  6320. #--Step 8.3
  6321. fmov.x (%a0),%fp0
  6322. fmul.d TWO140(%pc),%fp0
  6323. mov.l &0x80010000,SC(%a6)
  6324. mov.l &0x80000000,SC+4(%a6)
  6325. clr.l SC+8(%a6)
  6326. fadd.x SC(%a6),%fp0
  6327. fmov.l %d0,%fpcr
  6328. mov.b &FMUL_OP,%d1 # last inst is MUL
  6329. fmul.d TWON140(%pc),%fp0
  6330. bra t_catch
  6331. EM1POLY:
  6332. #--Step 9 exp(X)-1 by a simple polynomial
  6333. fmov.x (%a0),%fp0 # fp0 is X
  6334. fmul.x %fp0,%fp0 # fp0 is S := X*X
  6335. fmovm.x &0xc,-(%sp) # save fp2 {%fp2/%fp3}
  6336. fmov.s &0x2F30CAA8,%fp1 # fp1 is B12
  6337. fmul.x %fp0,%fp1 # fp1 is S*B12
  6338. fmov.s &0x310F8290,%fp2 # fp2 is B11
  6339. fadd.s &0x32D73220,%fp1 # fp1 is B10+S*B12
  6340. fmul.x %fp0,%fp2 # fp2 is S*B11
  6341. fmul.x %fp0,%fp1 # fp1 is S*(B10 + ...
  6342. fadd.s &0x3493F281,%fp2 # fp2 is B9+S*...
  6343. fadd.d EM1B8(%pc),%fp1 # fp1 is B8+S*...
  6344. fmul.x %fp0,%fp2 # fp2 is S*(B9+...
  6345. fmul.x %fp0,%fp1 # fp1 is S*(B8+...
  6346. fadd.d EM1B7(%pc),%fp2 # fp2 is B7+S*...
  6347. fadd.d EM1B6(%pc),%fp1 # fp1 is B6+S*...
  6348. fmul.x %fp0,%fp2 # fp2 is S*(B7+...
  6349. fmul.x %fp0,%fp1 # fp1 is S*(B6+...
  6350. fadd.d EM1B5(%pc),%fp2 # fp2 is B5+S*...
  6351. fadd.d EM1B4(%pc),%fp1 # fp1 is B4+S*...
  6352. fmul.x %fp0,%fp2 # fp2 is S*(B5+...
  6353. fmul.x %fp0,%fp1 # fp1 is S*(B4+...
  6354. fadd.d EM1B3(%pc),%fp2 # fp2 is B3+S*...
  6355. fadd.x EM1B2(%pc),%fp1 # fp1 is B2+S*...
  6356. fmul.x %fp0,%fp2 # fp2 is S*(B3+...
  6357. fmul.x %fp0,%fp1 # fp1 is S*(B2+...
  6358. fmul.x %fp0,%fp2 # fp2 is S*S*(B3+...)
  6359. fmul.x (%a0),%fp1 # fp1 is X*S*(B2...
  6360. fmul.s &0x3F000000,%fp0 # fp0 is S*B1
  6361. fadd.x %fp2,%fp1 # fp1 is Q
  6362. fmovm.x (%sp)+,&0x30 # fp2 restored {%fp2/%fp3}
  6363. fadd.x %fp1,%fp0 # fp0 is S*B1+Q
  6364. fmov.l %d0,%fpcr
  6365. fadd.x (%a0),%fp0
  6366. bra t_inx2
  6367. EM1BIG:
  6368. #--Step 10 |X| > 70 log2
  6369. mov.l (%a0),%d1
  6370. cmp.l %d1,&0
  6371. bgt.w EXPC1
  6372. #--Step 10.2
  6373. fmov.s &0xBF800000,%fp0 # fp0 is -1
  6374. fmov.l %d0,%fpcr
  6375. fadd.s &0x00800000,%fp0 # -1 + 2^(-126)
  6376. bra t_minx2
  6377. global setoxm1d
  6378. setoxm1d:
  6379. #--entry point for EXPM1(X), here X is denormalized
  6380. #--Step 0.
  6381. bra t_extdnrm
  6382. #########################################################################
  6383. # sgetexp(): returns the exponent portion of the input argument. #
  6384. # The exponent bias is removed and the exponent value is #
  6385. # returned as an extended precision number in fp0. #
  6386. # sgetexpd(): handles denormalized numbers. #
  6387. # #
  6388. # sgetman(): extracts the mantissa of the input argument. The #
  6389. # mantissa is converted to an extended precision number w/ #
  6390. # an exponent of $3fff and is returned in fp0. The range of #
  6391. # the result is [1.0 - 2.0). #
  6392. # sgetmand(): handles denormalized numbers. #
  6393. # #
  6394. # INPUT *************************************************************** #
  6395. # a0 = pointer to extended precision input #
  6396. # #
  6397. # OUTPUT ************************************************************** #
  6398. # fp0 = exponent(X) or mantissa(X) #
  6399. # #
  6400. #########################################################################
  6401. global sgetexp
  6402. sgetexp:
  6403. mov.w SRC_EX(%a0),%d0 # get the exponent
  6404. bclr &0xf,%d0 # clear the sign bit
  6405. subi.w &0x3fff,%d0 # subtract off the bias
  6406. fmov.w %d0,%fp0 # return exp in fp0
  6407. blt.b sgetexpn # it's negative
  6408. rts
  6409. sgetexpn:
  6410. mov.b &neg_bmask,FPSR_CC(%a6) # set 'N' ccode bit
  6411. rts
  6412. global sgetexpd
  6413. sgetexpd:
  6414. bsr.l norm # normalize
  6415. neg.w %d0 # new exp = -(shft amt)
  6416. subi.w &0x3fff,%d0 # subtract off the bias
  6417. fmov.w %d0,%fp0 # return exp in fp0
  6418. mov.b &neg_bmask,FPSR_CC(%a6) # set 'N' ccode bit
  6419. rts
  6420. global sgetman
  6421. sgetman:
  6422. mov.w SRC_EX(%a0),%d0 # get the exp
  6423. ori.w &0x7fff,%d0 # clear old exp
  6424. bclr &0xe,%d0 # make it the new exp +-3fff
  6425. # here, we build the result in a tmp location so as not to disturb the input
  6426. mov.l SRC_HI(%a0),FP_SCR0_HI(%a6) # copy to tmp loc
  6427. mov.l SRC_LO(%a0),FP_SCR0_LO(%a6) # copy to tmp loc
  6428. mov.w %d0,FP_SCR0_EX(%a6) # insert new exponent
  6429. fmov.x FP_SCR0(%a6),%fp0 # put new value back in fp0
  6430. bmi.b sgetmann # it's negative
  6431. rts
  6432. sgetmann:
  6433. mov.b &neg_bmask,FPSR_CC(%a6) # set 'N' ccode bit
  6434. rts
  6435. #
  6436. # For denormalized numbers, shift the mantissa until the j-bit = 1,
  6437. # then load the exponent with +/1 $3fff.
  6438. #
  6439. global sgetmand
  6440. sgetmand:
  6441. bsr.l norm # normalize exponent
  6442. bra.b sgetman
  6443. #########################################################################
  6444. # scosh(): computes the hyperbolic cosine of a normalized input #
  6445. # scoshd(): computes the hyperbolic cosine of a denormalized input #
  6446. # #
  6447. # INPUT *************************************************************** #
  6448. # a0 = pointer to extended precision input #
  6449. # d0 = round precision,mode #
  6450. # #
  6451. # OUTPUT ************************************************************** #
  6452. # fp0 = cosh(X) #
  6453. # #
  6454. # ACCURACY and MONOTONICITY ******************************************* #
  6455. # The returned result is within 3 ulps in 64 significant bit, #
  6456. # i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
  6457. # rounded to double precision. The result is provably monotonic #
  6458. # in double precision. #
  6459. # #
  6460. # ALGORITHM *********************************************************** #
  6461. # #
  6462. # COSH #
  6463. # 1. If |X| > 16380 log2, go to 3. #
  6464. # #
  6465. # 2. (|X| <= 16380 log2) Cosh(X) is obtained by the formulae #
  6466. # y = |X|, z = exp(Y), and #
  6467. # cosh(X) = (1/2)*( z + 1/z ). #
  6468. # Exit. #
  6469. # #
  6470. # 3. (|X| > 16380 log2). If |X| > 16480 log2, go to 5. #
  6471. # #
  6472. # 4. (16380 log2 < |X| <= 16480 log2) #
  6473. # cosh(X) = sign(X) * exp(|X|)/2. #
  6474. # However, invoking exp(|X|) may cause premature #
  6475. # overflow. Thus, we calculate sinh(X) as follows: #
  6476. # Y := |X| #
  6477. # Fact := 2**(16380) #
  6478. # Y' := Y - 16381 log2 #
  6479. # cosh(X) := Fact * exp(Y'). #
  6480. # Exit. #
  6481. # #
  6482. # 5. (|X| > 16480 log2) sinh(X) must overflow. Return #
  6483. # Huge*Huge to generate overflow and an infinity with #
  6484. # the appropriate sign. Huge is the largest finite number #
  6485. # in extended format. Exit. #
  6486. # #
  6487. #########################################################################
  6488. TWO16380:
  6489. long 0x7FFB0000,0x80000000,0x00000000,0x00000000
  6490. global scosh
  6491. scosh:
  6492. fmov.x (%a0),%fp0 # LOAD INPUT
  6493. mov.l (%a0),%d1
  6494. mov.w 4(%a0),%d1
  6495. and.l &0x7FFFFFFF,%d1
  6496. cmp.l %d1,&0x400CB167
  6497. bgt.b COSHBIG
  6498. #--THIS IS THE USUAL CASE, |X| < 16380 LOG2
  6499. #--COSH(X) = (1/2) * ( EXP(X) + 1/EXP(X) )
  6500. fabs.x %fp0 # |X|
  6501. mov.l %d0,-(%sp)
  6502. clr.l %d0
  6503. fmovm.x &0x01,-(%sp) # save |X| to stack
  6504. lea (%sp),%a0 # pass ptr to |X|
  6505. bsr setox # FP0 IS EXP(|X|)
  6506. add.l &0xc,%sp # erase |X| from stack
  6507. fmul.s &0x3F000000,%fp0 # (1/2)EXP(|X|)
  6508. mov.l (%sp)+,%d0
  6509. fmov.s &0x3E800000,%fp1 # (1/4)
  6510. fdiv.x %fp0,%fp1 # 1/(2 EXP(|X|))
  6511. fmov.l %d0,%fpcr
  6512. mov.b &FADD_OP,%d1 # last inst is ADD
  6513. fadd.x %fp1,%fp0
  6514. bra t_catch
  6515. COSHBIG:
  6516. cmp.l %d1,&0x400CB2B3
  6517. bgt.b COSHHUGE
  6518. fabs.x %fp0
  6519. fsub.d T1(%pc),%fp0 # (|X|-16381LOG2_LEAD)
  6520. fsub.d T2(%pc),%fp0 # |X| - 16381 LOG2, ACCURATE
  6521. mov.l %d0,-(%sp)
  6522. clr.l %d0
  6523. fmovm.x &0x01,-(%sp) # save fp0 to stack
  6524. lea (%sp),%a0 # pass ptr to fp0
  6525. bsr setox
  6526. add.l &0xc,%sp # clear fp0 from stack
  6527. mov.l (%sp)+,%d0
  6528. fmov.l %d0,%fpcr
  6529. mov.b &FMUL_OP,%d1 # last inst is MUL
  6530. fmul.x TWO16380(%pc),%fp0
  6531. bra t_catch
  6532. COSHHUGE:
  6533. bra t_ovfl2
  6534. global scoshd
  6535. #--COSH(X) = 1 FOR DENORMALIZED X
  6536. scoshd:
  6537. fmov.s &0x3F800000,%fp0
  6538. fmov.l %d0,%fpcr
  6539. fadd.s &0x00800000,%fp0
  6540. bra t_pinx2
  6541. #########################################################################
  6542. # ssinh(): computes the hyperbolic sine of a normalized input #
  6543. # ssinhd(): computes the hyperbolic sine of a denormalized input #
  6544. # #
  6545. # INPUT *************************************************************** #
  6546. # a0 = pointer to extended precision input #
  6547. # d0 = round precision,mode #
  6548. # #
  6549. # OUTPUT ************************************************************** #
  6550. # fp0 = sinh(X) #
  6551. # #
  6552. # ACCURACY and MONOTONICITY ******************************************* #
  6553. # The returned result is within 3 ulps in 64 significant bit, #
  6554. # i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
  6555. # rounded to double precision. The result is provably monotonic #
  6556. # in double precision. #
  6557. # #
  6558. # ALGORITHM *********************************************************** #
  6559. # #
  6560. # SINH #
  6561. # 1. If |X| > 16380 log2, go to 3. #
  6562. # #
  6563. # 2. (|X| <= 16380 log2) Sinh(X) is obtained by the formula #
  6564. # y = |X|, sgn = sign(X), and z = expm1(Y), #
  6565. # sinh(X) = sgn*(1/2)*( z + z/(1+z) ). #
  6566. # Exit. #
  6567. # #
  6568. # 3. If |X| > 16480 log2, go to 5. #
  6569. # #
  6570. # 4. (16380 log2 < |X| <= 16480 log2) #
  6571. # sinh(X) = sign(X) * exp(|X|)/2. #
  6572. # However, invoking exp(|X|) may cause premature overflow. #
  6573. # Thus, we calculate sinh(X) as follows: #
  6574. # Y := |X| #
  6575. # sgn := sign(X) #
  6576. # sgnFact := sgn * 2**(16380) #
  6577. # Y' := Y - 16381 log2 #
  6578. # sinh(X) := sgnFact * exp(Y'). #
  6579. # Exit. #
  6580. # #
  6581. # 5. (|X| > 16480 log2) sinh(X) must overflow. Return #
  6582. # sign(X)*Huge*Huge to generate overflow and an infinity with #
  6583. # the appropriate sign. Huge is the largest finite number in #
  6584. # extended format. Exit. #
  6585. # #
  6586. #########################################################################
  6587. global ssinh
  6588. ssinh:
  6589. fmov.x (%a0),%fp0 # LOAD INPUT
  6590. mov.l (%a0),%d1
  6591. mov.w 4(%a0),%d1
  6592. mov.l %d1,%a1 # save (compacted) operand
  6593. and.l &0x7FFFFFFF,%d1
  6594. cmp.l %d1,&0x400CB167
  6595. bgt.b SINHBIG
  6596. #--THIS IS THE USUAL CASE, |X| < 16380 LOG2
  6597. #--Y = |X|, Z = EXPM1(Y), SINH(X) = SIGN(X)*(1/2)*( Z + Z/(1+Z) )
  6598. fabs.x %fp0 # Y = |X|
  6599. movm.l &0x8040,-(%sp) # {a1/d0}
  6600. fmovm.x &0x01,-(%sp) # save Y on stack
  6601. lea (%sp),%a0 # pass ptr to Y
  6602. clr.l %d0
  6603. bsr setoxm1 # FP0 IS Z = EXPM1(Y)
  6604. add.l &0xc,%sp # clear Y from stack
  6605. fmov.l &0,%fpcr
  6606. movm.l (%sp)+,&0x0201 # {a1/d0}
  6607. fmov.x %fp0,%fp1
  6608. fadd.s &0x3F800000,%fp1 # 1+Z
  6609. fmov.x %fp0,-(%sp)
  6610. fdiv.x %fp1,%fp0 # Z/(1+Z)
  6611. mov.l %a1,%d1
  6612. and.l &0x80000000,%d1
  6613. or.l &0x3F000000,%d1
  6614. fadd.x (%sp)+,%fp0
  6615. mov.l %d1,-(%sp)
  6616. fmov.l %d0,%fpcr
  6617. mov.b &FMUL_OP,%d1 # last inst is MUL
  6618. fmul.s (%sp)+,%fp0 # last fp inst - possible exceptions set
  6619. bra t_catch
  6620. SINHBIG:
  6621. cmp.l %d1,&0x400CB2B3
  6622. bgt t_ovfl
  6623. fabs.x %fp0
  6624. fsub.d T1(%pc),%fp0 # (|X|-16381LOG2_LEAD)
  6625. mov.l &0,-(%sp)
  6626. mov.l &0x80000000,-(%sp)
  6627. mov.l %a1,%d1
  6628. and.l &0x80000000,%d1
  6629. or.l &0x7FFB0000,%d1
  6630. mov.l %d1,-(%sp) # EXTENDED FMT
  6631. fsub.d T2(%pc),%fp0 # |X| - 16381 LOG2, ACCURATE
  6632. mov.l %d0,-(%sp)
  6633. clr.l %d0
  6634. fmovm.x &0x01,-(%sp) # save fp0 on stack
  6635. lea (%sp),%a0 # pass ptr to fp0
  6636. bsr setox
  6637. add.l &0xc,%sp # clear fp0 from stack
  6638. mov.l (%sp)+,%d0
  6639. fmov.l %d0,%fpcr
  6640. mov.b &FMUL_OP,%d1 # last inst is MUL
  6641. fmul.x (%sp)+,%fp0 # possible exception
  6642. bra t_catch
  6643. global ssinhd
  6644. #--SINH(X) = X FOR DENORMALIZED X
  6645. ssinhd:
  6646. bra t_extdnrm
  6647. #########################################################################
  6648. # stanh(): computes the hyperbolic tangent of a normalized input #
  6649. # stanhd(): computes the hyperbolic tangent of a denormalized input #
  6650. # #
  6651. # INPUT *************************************************************** #
  6652. # a0 = pointer to extended precision input #
  6653. # d0 = round precision,mode #
  6654. # #
  6655. # OUTPUT ************************************************************** #
  6656. # fp0 = tanh(X) #
  6657. # #
  6658. # ACCURACY and MONOTONICITY ******************************************* #
  6659. # The returned result is within 3 ulps in 64 significant bit, #
  6660. # i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
  6661. # rounded to double precision. The result is provably monotonic #
  6662. # in double precision. #
  6663. # #
  6664. # ALGORITHM *********************************************************** #
  6665. # #
  6666. # TANH #
  6667. # 1. If |X| >= (5/2) log2 or |X| <= 2**(-40), go to 3. #
  6668. # #
  6669. # 2. (2**(-40) < |X| < (5/2) log2) Calculate tanh(X) by #
  6670. # sgn := sign(X), y := 2|X|, z := expm1(Y), and #
  6671. # tanh(X) = sgn*( z/(2+z) ). #
  6672. # Exit. #
  6673. # #
  6674. # 3. (|X| <= 2**(-40) or |X| >= (5/2) log2). If |X| < 1, #
  6675. # go to 7. #
  6676. # #
  6677. # 4. (|X| >= (5/2) log2) If |X| >= 50 log2, go to 6. #
  6678. # #
  6679. # 5. ((5/2) log2 <= |X| < 50 log2) Calculate tanh(X) by #
  6680. # sgn := sign(X), y := 2|X|, z := exp(Y), #
  6681. # tanh(X) = sgn - [ sgn*2/(1+z) ]. #
  6682. # Exit. #
  6683. # #
  6684. # 6. (|X| >= 50 log2) Tanh(X) = +-1 (round to nearest). Thus, we #
  6685. # calculate Tanh(X) by #
  6686. # sgn := sign(X), Tiny := 2**(-126), #
  6687. # tanh(X) := sgn - sgn*Tiny. #
  6688. # Exit. #
  6689. # #
  6690. # 7. (|X| < 2**(-40)). Tanh(X) = X. Exit. #
  6691. # #
  6692. #########################################################################
  6693. set X,FP_SCR0
  6694. set XFRAC,X+4
  6695. set SGN,L_SCR3
  6696. set V,FP_SCR0
  6697. global stanh
  6698. stanh:
  6699. fmov.x (%a0),%fp0 # LOAD INPUT
  6700. fmov.x %fp0,X(%a6)
  6701. mov.l (%a0),%d1
  6702. mov.w 4(%a0),%d1
  6703. mov.l %d1,X(%a6)
  6704. and.l &0x7FFFFFFF,%d1
  6705. cmp.l %d1, &0x3fd78000 # is |X| < 2^(-40)?
  6706. blt.w TANHBORS # yes
  6707. cmp.l %d1, &0x3fffddce # is |X| > (5/2)LOG2?
  6708. bgt.w TANHBORS # yes
  6709. #--THIS IS THE USUAL CASE
  6710. #--Y = 2|X|, Z = EXPM1(Y), TANH(X) = SIGN(X) * Z / (Z+2).
  6711. mov.l X(%a6),%d1
  6712. mov.l %d1,SGN(%a6)
  6713. and.l &0x7FFF0000,%d1
  6714. add.l &0x00010000,%d1 # EXPONENT OF 2|X|
  6715. mov.l %d1,X(%a6)
  6716. and.l &0x80000000,SGN(%a6)
  6717. fmov.x X(%a6),%fp0 # FP0 IS Y = 2|X|
  6718. mov.l %d0,-(%sp)
  6719. clr.l %d0
  6720. fmovm.x &0x1,-(%sp) # save Y on stack
  6721. lea (%sp),%a0 # pass ptr to Y
  6722. bsr setoxm1 # FP0 IS Z = EXPM1(Y)
  6723. add.l &0xc,%sp # clear Y from stack
  6724. mov.l (%sp)+,%d0
  6725. fmov.x %fp0,%fp1
  6726. fadd.s &0x40000000,%fp1 # Z+2
  6727. mov.l SGN(%a6),%d1
  6728. fmov.x %fp1,V(%a6)
  6729. eor.l %d1,V(%a6)
  6730. fmov.l %d0,%fpcr # restore users round prec,mode
  6731. fdiv.x V(%a6),%fp0
  6732. bra t_inx2
  6733. TANHBORS:
  6734. cmp.l %d1,&0x3FFF8000
  6735. blt.w TANHSM
  6736. cmp.l %d1,&0x40048AA1
  6737. bgt.w TANHHUGE
  6738. #-- (5/2) LOG2 < |X| < 50 LOG2,
  6739. #--TANH(X) = 1 - (2/[EXP(2X)+1]). LET Y = 2|X|, SGN = SIGN(X),
  6740. #--TANH(X) = SGN - SGN*2/[EXP(Y)+1].
  6741. mov.l X(%a6),%d1
  6742. mov.l %d1,SGN(%a6)
  6743. and.l &0x7FFF0000,%d1
  6744. add.l &0x00010000,%d1 # EXPO OF 2|X|
  6745. mov.l %d1,X(%a6) # Y = 2|X|
  6746. and.l &0x80000000,SGN(%a6)
  6747. mov.l SGN(%a6),%d1
  6748. fmov.x X(%a6),%fp0 # Y = 2|X|
  6749. mov.l %d0,-(%sp)
  6750. clr.l %d0
  6751. fmovm.x &0x01,-(%sp) # save Y on stack
  6752. lea (%sp),%a0 # pass ptr to Y
  6753. bsr setox # FP0 IS EXP(Y)
  6754. add.l &0xc,%sp # clear Y from stack
  6755. mov.l (%sp)+,%d0
  6756. mov.l SGN(%a6),%d1
  6757. fadd.s &0x3F800000,%fp0 # EXP(Y)+1
  6758. eor.l &0xC0000000,%d1 # -SIGN(X)*2
  6759. fmov.s %d1,%fp1 # -SIGN(X)*2 IN SGL FMT
  6760. fdiv.x %fp0,%fp1 # -SIGN(X)2 / [EXP(Y)+1 ]
  6761. mov.l SGN(%a6),%d1
  6762. or.l &0x3F800000,%d1 # SGN
  6763. fmov.s %d1,%fp0 # SGN IN SGL FMT
  6764. fmov.l %d0,%fpcr # restore users round prec,mode
  6765. mov.b &FADD_OP,%d1 # last inst is ADD
  6766. fadd.x %fp1,%fp0
  6767. bra t_inx2
  6768. TANHSM:
  6769. fmov.l %d0,%fpcr # restore users round prec,mode
  6770. mov.b &FMOV_OP,%d1 # last inst is MOVE
  6771. fmov.x X(%a6),%fp0 # last inst - possible exception set
  6772. bra t_catch
  6773. #---RETURN SGN(X) - SGN(X)EPS
  6774. TANHHUGE:
  6775. mov.l X(%a6),%d1
  6776. and.l &0x80000000,%d1
  6777. or.l &0x3F800000,%d1
  6778. fmov.s %d1,%fp0
  6779. and.l &0x80000000,%d1
  6780. eor.l &0x80800000,%d1 # -SIGN(X)*EPS
  6781. fmov.l %d0,%fpcr # restore users round prec,mode
  6782. fadd.s %d1,%fp0
  6783. bra t_inx2
  6784. global stanhd
  6785. #--TANH(X) = X FOR DENORMALIZED X
  6786. stanhd:
  6787. bra t_extdnrm
  6788. #########################################################################
  6789. # slogn(): computes the natural logarithm of a normalized input #
  6790. # slognd(): computes the natural logarithm of a denormalized input #
  6791. # slognp1(): computes the log(1+X) of a normalized input #
  6792. # slognp1d(): computes the log(1+X) of a denormalized input #
  6793. # #
  6794. # INPUT *************************************************************** #
  6795. # a0 = pointer to extended precision input #
  6796. # d0 = round precision,mode #
  6797. # #
  6798. # OUTPUT ************************************************************** #
  6799. # fp0 = log(X) or log(1+X) #
  6800. # #
  6801. # ACCURACY and MONOTONICITY ******************************************* #
  6802. # The returned result is within 2 ulps in 64 significant bit, #
  6803. # i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
  6804. # rounded to double precision. The result is provably monotonic #
  6805. # in double precision. #
  6806. # #
  6807. # ALGORITHM *********************************************************** #
  6808. # LOGN: #
  6809. # Step 1. If |X-1| < 1/16, approximate log(X) by an odd #
  6810. # polynomial in u, where u = 2(X-1)/(X+1). Otherwise, #
  6811. # move on to Step 2. #
  6812. # #
  6813. # Step 2. X = 2**k * Y where 1 <= Y < 2. Define F to be the first #
  6814. # seven significant bits of Y plus 2**(-7), i.e. #
  6815. # F = 1.xxxxxx1 in base 2 where the six "x" match those #
  6816. # of Y. Note that |Y-F| <= 2**(-7). #
  6817. # #
  6818. # Step 3. Define u = (Y-F)/F. Approximate log(1+u) by a #
  6819. # polynomial in u, log(1+u) = poly. #
  6820. # #
  6821. # Step 4. Reconstruct #
  6822. # log(X) = log( 2**k * Y ) = k*log(2) + log(F) + log(1+u) #
  6823. # by k*log(2) + (log(F) + poly). The values of log(F) are #
  6824. # calculated beforehand and stored in the program. #
  6825. # #
  6826. # lognp1: #
  6827. # Step 1: If |X| < 1/16, approximate log(1+X) by an odd #
  6828. # polynomial in u where u = 2X/(2+X). Otherwise, move on #
  6829. # to Step 2. #
  6830. # #
  6831. # Step 2: Let 1+X = 2**k * Y, where 1 <= Y < 2. Define F as done #
  6832. # in Step 2 of the algorithm for LOGN and compute #
  6833. # log(1+X) as k*log(2) + log(F) + poly where poly #
  6834. # approximates log(1+u), u = (Y-F)/F. #
  6835. # #
  6836. # Implementation Notes: #
  6837. # Note 1. There are 64 different possible values for F, thus 64 #
  6838. # log(F)'s need to be tabulated. Moreover, the values of #
  6839. # 1/F are also tabulated so that the division in (Y-F)/F #
  6840. # can be performed by a multiplication. #
  6841. # #
  6842. # Note 2. In Step 2 of lognp1, in order to preserved accuracy, #
  6843. # the value Y-F has to be calculated carefully when #
  6844. # 1/2 <= X < 3/2. #
  6845. # #
  6846. # Note 3. To fully exploit the pipeline, polynomials are usually #
  6847. # separated into two parts evaluated independently before #
  6848. # being added up. #
  6849. # #
  6850. #########################################################################
  6851. LOGOF2:
  6852. long 0x3FFE0000,0xB17217F7,0xD1CF79AC,0x00000000
  6853. one:
  6854. long 0x3F800000
  6855. zero:
  6856. long 0x00000000
  6857. infty:
  6858. long 0x7F800000
  6859. negone:
  6860. long 0xBF800000
  6861. LOGA6:
  6862. long 0x3FC2499A,0xB5E4040B
  6863. LOGA5:
  6864. long 0xBFC555B5,0x848CB7DB
  6865. LOGA4:
  6866. long 0x3FC99999,0x987D8730
  6867. LOGA3:
  6868. long 0xBFCFFFFF,0xFF6F7E97
  6869. LOGA2:
  6870. long 0x3FD55555,0x555555A4
  6871. LOGA1:
  6872. long 0xBFE00000,0x00000008
  6873. LOGB5:
  6874. long 0x3F175496,0xADD7DAD6
  6875. LOGB4:
  6876. long 0x3F3C71C2,0xFE80C7E0
  6877. LOGB3:
  6878. long 0x3F624924,0x928BCCFF
  6879. LOGB2:
  6880. long 0x3F899999,0x999995EC
  6881. LOGB1:
  6882. long 0x3FB55555,0x55555555
  6883. TWO:
  6884. long 0x40000000,0x00000000
  6885. LTHOLD:
  6886. long 0x3f990000,0x80000000,0x00000000,0x00000000
  6887. LOGTBL:
  6888. long 0x3FFE0000,0xFE03F80F,0xE03F80FE,0x00000000
  6889. long 0x3FF70000,0xFF015358,0x833C47E2,0x00000000
  6890. long 0x3FFE0000,0xFA232CF2,0x52138AC0,0x00000000
  6891. long 0x3FF90000,0xBDC8D83E,0xAD88D549,0x00000000
  6892. long 0x3FFE0000,0xF6603D98,0x0F6603DA,0x00000000
  6893. long 0x3FFA0000,0x9CF43DCF,0xF5EAFD48,0x00000000
  6894. long 0x3FFE0000,0xF2B9D648,0x0F2B9D65,0x00000000
  6895. long 0x3FFA0000,0xDA16EB88,0xCB8DF614,0x00000000
  6896. long 0x3FFE0000,0xEF2EB71F,0xC4345238,0x00000000
  6897. long 0x3FFB0000,0x8B29B775,0x1BD70743,0x00000000
  6898. long 0x3FFE0000,0xEBBDB2A5,0xC1619C8C,0x00000000
  6899. long 0x3FFB0000,0xA8D839F8,0x30C1FB49,0x00000000
  6900. long 0x3FFE0000,0xE865AC7B,0x7603A197,0x00000000
  6901. long 0x3FFB0000,0xC61A2EB1,0x8CD907AD,0x00000000
  6902. long 0x3FFE0000,0xE525982A,0xF70C880E,0x00000000
  6903. long 0x3FFB0000,0xE2F2A47A,0xDE3A18AF,0x00000000
  6904. long 0x3FFE0000,0xE1FC780E,0x1FC780E2,0x00000000
  6905. long 0x3FFB0000,0xFF64898E,0xDF55D551,0x00000000
  6906. long 0x3FFE0000,0xDEE95C4C,0xA037BA57,0x00000000
  6907. long 0x3FFC0000,0x8DB956A9,0x7B3D0148,0x00000000
  6908. long 0x3FFE0000,0xDBEB61EE,0xD19C5958,0x00000000
  6909. long 0x3FFC0000,0x9B8FE100,0xF47BA1DE,0x00000000
  6910. long 0x3FFE0000,0xD901B203,0x6406C80E,0x00000000
  6911. long 0x3FFC0000,0xA9372F1D,0x0DA1BD17,0x00000000
  6912. long 0x3FFE0000,0xD62B80D6,0x2B80D62C,0x00000000
  6913. long 0x3FFC0000,0xB6B07F38,0xCE90E46B,0x00000000
  6914. long 0x3FFE0000,0xD3680D36,0x80D3680D,0x00000000
  6915. long 0x3FFC0000,0xC3FD0329,0x06488481,0x00000000
  6916. long 0x3FFE0000,0xD0B69FCB,0xD2580D0B,0x00000000
  6917. long 0x3FFC0000,0xD11DE0FF,0x15AB18CA,0x00000000
  6918. long 0x3FFE0000,0xCE168A77,0x25080CE1,0x00000000
  6919. long 0x3FFC0000,0xDE1433A1,0x6C66B150,0x00000000
  6920. long 0x3FFE0000,0xCB8727C0,0x65C393E0,0x00000000
  6921. long 0x3FFC0000,0xEAE10B5A,0x7DDC8ADD,0x00000000
  6922. long 0x3FFE0000,0xC907DA4E,0x871146AD,0x00000000
  6923. long 0x3FFC0000,0xF7856E5E,0xE2C9B291,0x00000000
  6924. long 0x3FFE0000,0xC6980C69,0x80C6980C,0x00000000
  6925. long 0x3FFD0000,0x82012CA5,0xA68206D7,0x00000000
  6926. long 0x3FFE0000,0xC4372F85,0x5D824CA6,0x00000000
  6927. long 0x3FFD0000,0x882C5FCD,0x7256A8C5,0x00000000
  6928. long 0x3FFE0000,0xC1E4BBD5,0x95F6E947,0x00000000
  6929. long 0x3FFD0000,0x8E44C60B,0x4CCFD7DE,0x00000000
  6930. long 0x3FFE0000,0xBFA02FE8,0x0BFA02FF,0x00000000
  6931. long 0x3FFD0000,0x944AD09E,0xF4351AF6,0x00000000
  6932. long 0x3FFE0000,0xBD691047,0x07661AA3,0x00000000
  6933. long 0x3FFD0000,0x9A3EECD4,0xC3EAA6B2,0x00000000
  6934. long 0x3FFE0000,0xBB3EE721,0xA54D880C,0x00000000
  6935. long 0x3FFD0000,0xA0218434,0x353F1DE8,0x00000000
  6936. long 0x3FFE0000,0xB92143FA,0x36F5E02E,0x00000000
  6937. long 0x3FFD0000,0xA5F2FCAB,0xBBC506DA,0x00000000
  6938. long 0x3FFE0000,0xB70FBB5A,0x19BE3659,0x00000000
  6939. long 0x3FFD0000,0xABB3B8BA,0x2AD362A5,0x00000000
  6940. long 0x3FFE0000,0xB509E68A,0x9B94821F,0x00000000
  6941. long 0x3FFD0000,0xB1641795,0xCE3CA97B,0x00000000
  6942. long 0x3FFE0000,0xB30F6352,0x8917C80B,0x00000000
  6943. long 0x3FFD0000,0xB7047551,0x5D0F1C61,0x00000000
  6944. long 0x3FFE0000,0xB11FD3B8,0x0B11FD3C,0x00000000
  6945. long 0x3FFD0000,0xBC952AFE,0xEA3D13E1,0x00000000
  6946. long 0x3FFE0000,0xAF3ADDC6,0x80AF3ADE,0x00000000
  6947. long 0x3FFD0000,0xC2168ED0,0xF458BA4A,0x00000000
  6948. long 0x3FFE0000,0xAD602B58,0x0AD602B6,0x00000000
  6949. long 0x3FFD0000,0xC788F439,0xB3163BF1,0x00000000
  6950. long 0x3FFE0000,0xAB8F69E2,0x8359CD11,0x00000000
  6951. long 0x3FFD0000,0xCCECAC08,0xBF04565D,0x00000000
  6952. long 0x3FFE0000,0xA9C84A47,0xA07F5638,0x00000000
  6953. long 0x3FFD0000,0xD2420487,0x2DD85160,0x00000000
  6954. long 0x3FFE0000,0xA80A80A8,0x0A80A80B,0x00000000
  6955. long 0x3FFD0000,0xD7894992,0x3BC3588A,0x00000000
  6956. long 0x3FFE0000,0xA655C439,0x2D7B73A8,0x00000000
  6957. long 0x3FFD0000,0xDCC2C4B4,0x9887DACC,0x00000000
  6958. long 0x3FFE0000,0xA4A9CF1D,0x96833751,0x00000000
  6959. long 0x3FFD0000,0xE1EEBD3E,0x6D6A6B9E,0x00000000
  6960. long 0x3FFE0000,0xA3065E3F,0xAE7CD0E0,0x00000000
  6961. long 0x3FFD0000,0xE70D785C,0x2F9F5BDC,0x00000000
  6962. long 0x3FFE0000,0xA16B312E,0xA8FC377D,0x00000000
  6963. long 0x3FFD0000,0xEC1F392C,0x5179F283,0x00000000
  6964. long 0x3FFE0000,0x9FD809FD,0x809FD80A,0x00000000
  6965. long 0x3FFD0000,0xF12440D3,0xE36130E6,0x00000000
  6966. long 0x3FFE0000,0x9E4CAD23,0xDD5F3A20,0x00000000
  6967. long 0x3FFD0000,0xF61CCE92,0x346600BB,0x00000000
  6968. long 0x3FFE0000,0x9CC8E160,0xC3FB19B9,0x00000000
  6969. long 0x3FFD0000,0xFB091FD3,0x8145630A,0x00000000
  6970. long 0x3FFE0000,0x9B4C6F9E,0xF03A3CAA,0x00000000
  6971. long 0x3FFD0000,0xFFE97042,0xBFA4C2AD,0x00000000
  6972. long 0x3FFE0000,0x99D722DA,0xBDE58F06,0x00000000
  6973. long 0x3FFE0000,0x825EFCED,0x49369330,0x00000000
  6974. long 0x3FFE0000,0x9868C809,0x868C8098,0x00000000
  6975. long 0x3FFE0000,0x84C37A7A,0xB9A905C9,0x00000000
  6976. long 0x3FFE0000,0x97012E02,0x5C04B809,0x00000000
  6977. long 0x3FFE0000,0x87224C2E,0x8E645FB7,0x00000000
  6978. long 0x3FFE0000,0x95A02568,0x095A0257,0x00000000
  6979. long 0x3FFE0000,0x897B8CAC,0x9F7DE298,0x00000000
  6980. long 0x3FFE0000,0x94458094,0x45809446,0x00000000
  6981. long 0x3FFE0000,0x8BCF55DE,0xC4CD05FE,0x00000000
  6982. long 0x3FFE0000,0x92F11384,0x0497889C,0x00000000
  6983. long 0x3FFE0000,0x8E1DC0FB,0x89E125E5,0x00000000
  6984. long 0x3FFE0000,0x91A2B3C4,0xD5E6F809,0x00000000
  6985. long 0x3FFE0000,0x9066E68C,0x955B6C9B,0x00000000
  6986. long 0x3FFE0000,0x905A3863,0x3E06C43B,0x00000000
  6987. long 0x3FFE0000,0x92AADE74,0xC7BE59E0,0x00000000
  6988. long 0x3FFE0000,0x8F1779D9,0xFDC3A219,0x00000000
  6989. long 0x3FFE0000,0x94E9BFF6,0x15845643,0x00000000
  6990. long 0x3FFE0000,0x8DDA5202,0x37694809,0x00000000
  6991. long 0x3FFE0000,0x9723A1B7,0x20134203,0x00000000
  6992. long 0x3FFE0000,0x8CA29C04,0x6514E023,0x00000000
  6993. long 0x3FFE0000,0x995899C8,0x90EB8990,0x00000000
  6994. long 0x3FFE0000,0x8B70344A,0x139BC75A,0x00000000
  6995. long 0x3FFE0000,0x9B88BDAA,0x3A3DAE2F,0x00000000
  6996. long 0x3FFE0000,0x8A42F870,0x5669DB46,0x00000000
  6997. long 0x3FFE0000,0x9DB4224F,0xFFE1157C,0x00000000
  6998. long 0x3FFE0000,0x891AC73A,0xE9819B50,0x00000000
  6999. long 0x3FFE0000,0x9FDADC26,0x8B7A12DA,0x00000000
  7000. long 0x3FFE0000,0x87F78087,0xF78087F8,0x00000000
  7001. long 0x3FFE0000,0xA1FCFF17,0xCE733BD4,0x00000000
  7002. long 0x3FFE0000,0x86D90544,0x7A34ACC6,0x00000000
  7003. long 0x3FFE0000,0xA41A9E8F,0x5446FB9F,0x00000000
  7004. long 0x3FFE0000,0x85BF3761,0x2CEE3C9B,0x00000000
  7005. long 0x3FFE0000,0xA633CD7E,0x6771CD8B,0x00000000
  7006. long 0x3FFE0000,0x84A9F9C8,0x084A9F9D,0x00000000
  7007. long 0x3FFE0000,0xA8489E60,0x0B435A5E,0x00000000
  7008. long 0x3FFE0000,0x83993052,0x3FBE3368,0x00000000
  7009. long 0x3FFE0000,0xAA59233C,0xCCA4BD49,0x00000000
  7010. long 0x3FFE0000,0x828CBFBE,0xB9A020A3,0x00000000
  7011. long 0x3FFE0000,0xAC656DAE,0x6BCC4985,0x00000000
  7012. long 0x3FFE0000,0x81848DA8,0xFAF0D277,0x00000000
  7013. long 0x3FFE0000,0xAE6D8EE3,0x60BB2468,0x00000000
  7014. long 0x3FFE0000,0x80808080,0x80808081,0x00000000
  7015. long 0x3FFE0000,0xB07197A2,0x3C46C654,0x00000000
  7016. set ADJK,L_SCR1
  7017. set X,FP_SCR0
  7018. set XDCARE,X+2
  7019. set XFRAC,X+4
  7020. set F,FP_SCR1
  7021. set FFRAC,F+4
  7022. set KLOG2,FP_SCR0
  7023. set SAVEU,FP_SCR0
  7024. global slogn
  7025. #--ENTRY POINT FOR LOG(X) FOR X FINITE, NON-ZERO, NOT NAN'S
  7026. slogn:
  7027. fmov.x (%a0),%fp0 # LOAD INPUT
  7028. mov.l &0x00000000,ADJK(%a6)
  7029. LOGBGN:
  7030. #--FPCR SAVED AND CLEARED, INPUT IS 2^(ADJK)*FP0, FP0 CONTAINS
  7031. #--A FINITE, NON-ZERO, NORMALIZED NUMBER.
  7032. mov.l (%a0),%d1
  7033. mov.w 4(%a0),%d1
  7034. mov.l (%a0),X(%a6)
  7035. mov.l 4(%a0),X+4(%a6)
  7036. mov.l 8(%a0),X+8(%a6)
  7037. cmp.l %d1,&0 # CHECK IF X IS NEGATIVE
  7038. blt.w LOGNEG # LOG OF NEGATIVE ARGUMENT IS INVALID
  7039. # X IS POSITIVE, CHECK IF X IS NEAR 1
  7040. cmp.l %d1,&0x3ffef07d # IS X < 15/16?
  7041. blt.b LOGMAIN # YES
  7042. cmp.l %d1,&0x3fff8841 # IS X > 17/16?
  7043. ble.w LOGNEAR1 # NO
  7044. LOGMAIN:
  7045. #--THIS SHOULD BE THE USUAL CASE, X NOT VERY CLOSE TO 1
  7046. #--X = 2^(K) * Y, 1 <= Y < 2. THUS, Y = 1.XXXXXXXX....XX IN BINARY.
  7047. #--WE DEFINE F = 1.XXXXXX1, I.E. FIRST 7 BITS OF Y AND ATTACH A 1.
  7048. #--THE IDEA IS THAT LOG(X) = K*LOG2 + LOG(Y)
  7049. #-- = K*LOG2 + LOG(F) + LOG(1 + (Y-F)/F).
  7050. #--NOTE THAT U = (Y-F)/F IS VERY SMALL AND THUS APPROXIMATING
  7051. #--LOG(1+U) CAN BE VERY EFFICIENT.
  7052. #--ALSO NOTE THAT THE VALUE 1/F IS STORED IN A TABLE SO THAT NO
  7053. #--DIVISION IS NEEDED TO CALCULATE (Y-F)/F.
  7054. #--GET K, Y, F, AND ADDRESS OF 1/F.
  7055. asr.l &8,%d1
  7056. asr.l &8,%d1 # SHIFTED 16 BITS, BIASED EXPO. OF X
  7057. sub.l &0x3FFF,%d1 # THIS IS K
  7058. add.l ADJK(%a6),%d1 # ADJUST K, ORIGINAL INPUT MAY BE DENORM.
  7059. lea LOGTBL(%pc),%a0 # BASE ADDRESS OF 1/F AND LOG(F)
  7060. fmov.l %d1,%fp1 # CONVERT K TO FLOATING-POINT FORMAT
  7061. #--WHILE THE CONVERSION IS GOING ON, WE GET F AND ADDRESS OF 1/F
  7062. mov.l &0x3FFF0000,X(%a6) # X IS NOW Y, I.E. 2^(-K)*X
  7063. mov.l XFRAC(%a6),FFRAC(%a6)
  7064. and.l &0xFE000000,FFRAC(%a6) # FIRST 7 BITS OF Y
  7065. or.l &0x01000000,FFRAC(%a6) # GET F: ATTACH A 1 AT THE EIGHTH BIT
  7066. mov.l FFRAC(%a6),%d1 # READY TO GET ADDRESS OF 1/F
  7067. and.l &0x7E000000,%d1
  7068. asr.l &8,%d1
  7069. asr.l &8,%d1
  7070. asr.l &4,%d1 # SHIFTED 20, D0 IS THE DISPLACEMENT
  7071. add.l %d1,%a0 # A0 IS THE ADDRESS FOR 1/F
  7072. fmov.x X(%a6),%fp0
  7073. mov.l &0x3fff0000,F(%a6)
  7074. clr.l F+8(%a6)
  7075. fsub.x F(%a6),%fp0 # Y-F
  7076. fmovm.x &0xc,-(%sp) # SAVE FP2-3 WHILE FP0 IS NOT READY
  7077. #--SUMMARY: FP0 IS Y-F, A0 IS ADDRESS OF 1/F, FP1 IS K
  7078. #--REGISTERS SAVED: FPCR, FP1, FP2
  7079. LP1CONT1:
  7080. #--AN RE-ENTRY POINT FOR LOGNP1
  7081. fmul.x (%a0),%fp0 # FP0 IS U = (Y-F)/F
  7082. fmul.x LOGOF2(%pc),%fp1 # GET K*LOG2 WHILE FP0 IS NOT READY
  7083. fmov.x %fp0,%fp2
  7084. fmul.x %fp2,%fp2 # FP2 IS V=U*U
  7085. fmov.x %fp1,KLOG2(%a6) # PUT K*LOG2 IN MEMEORY, FREE FP1
  7086. #--LOG(1+U) IS APPROXIMATED BY
  7087. #--U + V*(A1+U*(A2+U*(A3+U*(A4+U*(A5+U*A6))))) WHICH IS
  7088. #--[U + V*(A1+V*(A3+V*A5))] + [U*V*(A2+V*(A4+V*A6))]
  7089. fmov.x %fp2,%fp3
  7090. fmov.x %fp2,%fp1
  7091. fmul.d LOGA6(%pc),%fp1 # V*A6
  7092. fmul.d LOGA5(%pc),%fp2 # V*A5
  7093. fadd.d LOGA4(%pc),%fp1 # A4+V*A6
  7094. fadd.d LOGA3(%pc),%fp2 # A3+V*A5
  7095. fmul.x %fp3,%fp1 # V*(A4+V*A6)
  7096. fmul.x %fp3,%fp2 # V*(A3+V*A5)
  7097. fadd.d LOGA2(%pc),%fp1 # A2+V*(A4+V*A6)
  7098. fadd.d LOGA1(%pc),%fp2 # A1+V*(A3+V*A5)
  7099. fmul.x %fp3,%fp1 # V*(A2+V*(A4+V*A6))
  7100. add.l &16,%a0 # ADDRESS OF LOG(F)
  7101. fmul.x %fp3,%fp2 # V*(A1+V*(A3+V*A5))
  7102. fmul.x %fp0,%fp1 # U*V*(A2+V*(A4+V*A6))
  7103. fadd.x %fp2,%fp0 # U+V*(A1+V*(A3+V*A5))
  7104. fadd.x (%a0),%fp1 # LOG(F)+U*V*(A2+V*(A4+V*A6))
  7105. fmovm.x (%sp)+,&0x30 # RESTORE FP2-3
  7106. fadd.x %fp1,%fp0 # FP0 IS LOG(F) + LOG(1+U)
  7107. fmov.l %d0,%fpcr
  7108. fadd.x KLOG2(%a6),%fp0 # FINAL ADD
  7109. bra t_inx2
  7110. LOGNEAR1:
  7111. # if the input is exactly equal to one, then exit through ld_pzero.
  7112. # if these 2 lines weren't here, the correct answer would be returned
  7113. # but the INEX2 bit would be set.
  7114. fcmp.b %fp0,&0x1 # is it equal to one?
  7115. fbeq.l ld_pzero # yes
  7116. #--REGISTERS SAVED: FPCR, FP1. FP0 CONTAINS THE INPUT.
  7117. fmov.x %fp0,%fp1
  7118. fsub.s one(%pc),%fp1 # FP1 IS X-1
  7119. fadd.s one(%pc),%fp0 # FP0 IS X+1
  7120. fadd.x %fp1,%fp1 # FP1 IS 2(X-1)
  7121. #--LOG(X) = LOG(1+U/2)-LOG(1-U/2) WHICH IS AN ODD POLYNOMIAL
  7122. #--IN U, U = 2(X-1)/(X+1) = FP1/FP0
  7123. LP1CONT2:
  7124. #--THIS IS AN RE-ENTRY POINT FOR LOGNP1
  7125. fdiv.x %fp0,%fp1 # FP1 IS U
  7126. fmovm.x &0xc,-(%sp) # SAVE FP2-3
  7127. #--REGISTERS SAVED ARE NOW FPCR,FP1,FP2,FP3
  7128. #--LET V=U*U, W=V*V, CALCULATE
  7129. #--U + U*V*(B1 + V*(B2 + V*(B3 + V*(B4 + V*B5)))) BY
  7130. #--U + U*V*( [B1 + W*(B3 + W*B5)] + [V*(B2 + W*B4)] )
  7131. fmov.x %fp1,%fp0
  7132. fmul.x %fp0,%fp0 # FP0 IS V
  7133. fmov.x %fp1,SAVEU(%a6) # STORE U IN MEMORY, FREE FP1
  7134. fmov.x %fp0,%fp1
  7135. fmul.x %fp1,%fp1 # FP1 IS W
  7136. fmov.d LOGB5(%pc),%fp3
  7137. fmov.d LOGB4(%pc),%fp2
  7138. fmul.x %fp1,%fp3 # W*B5
  7139. fmul.x %fp1,%fp2 # W*B4
  7140. fadd.d LOGB3(%pc),%fp3 # B3+W*B5
  7141. fadd.d LOGB2(%pc),%fp2 # B2+W*B4
  7142. fmul.x %fp3,%fp1 # W*(B3+W*B5), FP3 RELEASED
  7143. fmul.x %fp0,%fp2 # V*(B2+W*B4)
  7144. fadd.d LOGB1(%pc),%fp1 # B1+W*(B3+W*B5)
  7145. fmul.x SAVEU(%a6),%fp0 # FP0 IS U*V
  7146. fadd.x %fp2,%fp1 # B1+W*(B3+W*B5) + V*(B2+W*B4), FP2 RELEASED
  7147. fmovm.x (%sp)+,&0x30 # FP2-3 RESTORED
  7148. fmul.x %fp1,%fp0 # U*V*( [B1+W*(B3+W*B5)] + [V*(B2+W*B4)] )
  7149. fmov.l %d0,%fpcr
  7150. fadd.x SAVEU(%a6),%fp0
  7151. bra t_inx2
  7152. #--REGISTERS SAVED FPCR. LOG(-VE) IS INVALID
  7153. LOGNEG:
  7154. bra t_operr
  7155. global slognd
  7156. slognd:
  7157. #--ENTRY POINT FOR LOG(X) FOR DENORMALIZED INPUT
  7158. mov.l &-100,ADJK(%a6) # INPUT = 2^(ADJK) * FP0
  7159. #----normalize the input value by left shifting k bits (k to be determined
  7160. #----below), adjusting exponent and storing -k to ADJK
  7161. #----the value TWOTO100 is no longer needed.
  7162. #----Note that this code assumes the denormalized input is NON-ZERO.
  7163. movm.l &0x3f00,-(%sp) # save some registers {d2-d7}
  7164. mov.l (%a0),%d3 # D3 is exponent of smallest norm. #
  7165. mov.l 4(%a0),%d4
  7166. mov.l 8(%a0),%d5 # (D4,D5) is (Hi_X,Lo_X)
  7167. clr.l %d2 # D2 used for holding K
  7168. tst.l %d4
  7169. bne.b Hi_not0
  7170. Hi_0:
  7171. mov.l %d5,%d4
  7172. clr.l %d5
  7173. mov.l &32,%d2
  7174. clr.l %d6
  7175. bfffo %d4{&0:&32},%d6
  7176. lsl.l %d6,%d4
  7177. add.l %d6,%d2 # (D3,D4,D5) is normalized
  7178. mov.l %d3,X(%a6)
  7179. mov.l %d4,XFRAC(%a6)
  7180. mov.l %d5,XFRAC+4(%a6)
  7181. neg.l %d2
  7182. mov.l %d2,ADJK(%a6)
  7183. fmov.x X(%a6),%fp0
  7184. movm.l (%sp)+,&0xfc # restore registers {d2-d7}
  7185. lea X(%a6),%a0
  7186. bra.w LOGBGN # begin regular log(X)
  7187. Hi_not0:
  7188. clr.l %d6
  7189. bfffo %d4{&0:&32},%d6 # find first 1
  7190. mov.l %d6,%d2 # get k
  7191. lsl.l %d6,%d4
  7192. mov.l %d5,%d7 # a copy of D5
  7193. lsl.l %d6,%d5
  7194. neg.l %d6
  7195. add.l &32,%d6
  7196. lsr.l %d6,%d7
  7197. or.l %d7,%d4 # (D3,D4,D5) normalized
  7198. mov.l %d3,X(%a6)
  7199. mov.l %d4,XFRAC(%a6)
  7200. mov.l %d5,XFRAC+4(%a6)
  7201. neg.l %d2
  7202. mov.l %d2,ADJK(%a6)
  7203. fmov.x X(%a6),%fp0
  7204. movm.l (%sp)+,&0xfc # restore registers {d2-d7}
  7205. lea X(%a6),%a0
  7206. bra.w LOGBGN # begin regular log(X)
  7207. global slognp1
  7208. #--ENTRY POINT FOR LOG(1+X) FOR X FINITE, NON-ZERO, NOT NAN'S
  7209. slognp1:
  7210. fmov.x (%a0),%fp0 # LOAD INPUT
  7211. fabs.x %fp0 # test magnitude
  7212. fcmp.x %fp0,LTHOLD(%pc) # compare with min threshold
  7213. fbgt.w LP1REAL # if greater, continue
  7214. fmov.l %d0,%fpcr
  7215. mov.b &FMOV_OP,%d1 # last inst is MOVE
  7216. fmov.x (%a0),%fp0 # return signed argument
  7217. bra t_catch
  7218. LP1REAL:
  7219. fmov.x (%a0),%fp0 # LOAD INPUT
  7220. mov.l &0x00000000,ADJK(%a6)
  7221. fmov.x %fp0,%fp1 # FP1 IS INPUT Z
  7222. fadd.s one(%pc),%fp0 # X := ROUND(1+Z)
  7223. fmov.x %fp0,X(%a6)
  7224. mov.w XFRAC(%a6),XDCARE(%a6)
  7225. mov.l X(%a6),%d1
  7226. cmp.l %d1,&0
  7227. ble.w LP1NEG0 # LOG OF ZERO OR -VE
  7228. cmp.l %d1,&0x3ffe8000 # IS BOUNDS [1/2,3/2]?
  7229. blt.w LOGMAIN
  7230. cmp.l %d1,&0x3fffc000
  7231. bgt.w LOGMAIN
  7232. #--IF 1+Z > 3/2 OR 1+Z < 1/2, THEN X, WHICH IS ROUNDING 1+Z,
  7233. #--CONTAINS AT LEAST 63 BITS OF INFORMATION OF Z. IN THAT CASE,
  7234. #--SIMPLY INVOKE LOG(X) FOR LOG(1+Z).
  7235. LP1NEAR1:
  7236. #--NEXT SEE IF EXP(-1/16) < X < EXP(1/16)
  7237. cmp.l %d1,&0x3ffef07d
  7238. blt.w LP1CARE
  7239. cmp.l %d1,&0x3fff8841
  7240. bgt.w LP1CARE
  7241. LP1ONE16:
  7242. #--EXP(-1/16) < X < EXP(1/16). LOG(1+Z) = LOG(1+U/2) - LOG(1-U/2)
  7243. #--WHERE U = 2Z/(2+Z) = 2Z/(1+X).
  7244. fadd.x %fp1,%fp1 # FP1 IS 2Z
  7245. fadd.s one(%pc),%fp0 # FP0 IS 1+X
  7246. #--U = FP1/FP0
  7247. bra.w LP1CONT2
  7248. LP1CARE:
  7249. #--HERE WE USE THE USUAL TABLE DRIVEN APPROACH. CARE HAS TO BE
  7250. #--TAKEN BECAUSE 1+Z CAN HAVE 67 BITS OF INFORMATION AND WE MUST
  7251. #--PRESERVE ALL THE INFORMATION. BECAUSE 1+Z IS IN [1/2,3/2],
  7252. #--THERE ARE ONLY TWO CASES.
  7253. #--CASE 1: 1+Z < 1, THEN K = -1 AND Y-F = (2-F) + 2Z
  7254. #--CASE 2: 1+Z > 1, THEN K = 0 AND Y-F = (1-F) + Z
  7255. #--ON RETURNING TO LP1CONT1, WE MUST HAVE K IN FP1, ADDRESS OF
  7256. #--(1/F) IN A0, Y-F IN FP0, AND FP2 SAVED.
  7257. mov.l XFRAC(%a6),FFRAC(%a6)
  7258. and.l &0xFE000000,FFRAC(%a6)
  7259. or.l &0x01000000,FFRAC(%a6) # F OBTAINED
  7260. cmp.l %d1,&0x3FFF8000 # SEE IF 1+Z > 1
  7261. bge.b KISZERO
  7262. KISNEG1:
  7263. fmov.s TWO(%pc),%fp0
  7264. mov.l &0x3fff0000,F(%a6)
  7265. clr.l F+8(%a6)
  7266. fsub.x F(%a6),%fp0 # 2-F
  7267. mov.l FFRAC(%a6),%d1
  7268. and.l &0x7E000000,%d1
  7269. asr.l &8,%d1
  7270. asr.l &8,%d1
  7271. asr.l &4,%d1 # D0 CONTAINS DISPLACEMENT FOR 1/F
  7272. fadd.x %fp1,%fp1 # GET 2Z
  7273. fmovm.x &0xc,-(%sp) # SAVE FP2 {%fp2/%fp3}
  7274. fadd.x %fp1,%fp0 # FP0 IS Y-F = (2-F)+2Z
  7275. lea LOGTBL(%pc),%a0 # A0 IS ADDRESS OF 1/F
  7276. add.l %d1,%a0
  7277. fmov.s negone(%pc),%fp1 # FP1 IS K = -1
  7278. bra.w LP1CONT1
  7279. KISZERO:
  7280. fmov.s one(%pc),%fp0
  7281. mov.l &0x3fff0000,F(%a6)
  7282. clr.l F+8(%a6)
  7283. fsub.x F(%a6),%fp0 # 1-F
  7284. mov.l FFRAC(%a6),%d1
  7285. and.l &0x7E000000,%d1
  7286. asr.l &8,%d1
  7287. asr.l &8,%d1
  7288. asr.l &4,%d1
  7289. fadd.x %fp1,%fp0 # FP0 IS Y-F
  7290. fmovm.x &0xc,-(%sp) # FP2 SAVED {%fp2/%fp3}
  7291. lea LOGTBL(%pc),%a0
  7292. add.l %d1,%a0 # A0 IS ADDRESS OF 1/F
  7293. fmov.s zero(%pc),%fp1 # FP1 IS K = 0
  7294. bra.w LP1CONT1
  7295. LP1NEG0:
  7296. #--FPCR SAVED. D0 IS X IN COMPACT FORM.
  7297. cmp.l %d1,&0
  7298. blt.b LP1NEG
  7299. LP1ZERO:
  7300. fmov.s negone(%pc),%fp0
  7301. fmov.l %d0,%fpcr
  7302. bra t_dz
  7303. LP1NEG:
  7304. fmov.s zero(%pc),%fp0
  7305. fmov.l %d0,%fpcr
  7306. bra t_operr
  7307. global slognp1d
  7308. #--ENTRY POINT FOR LOG(1+Z) FOR DENORMALIZED INPUT
  7309. # Simply return the denorm
  7310. slognp1d:
  7311. bra t_extdnrm
  7312. #########################################################################
  7313. # satanh(): computes the inverse hyperbolic tangent of a norm input #
  7314. # satanhd(): computes the inverse hyperbolic tangent of a denorm input #
  7315. # #
  7316. # INPUT *************************************************************** #
  7317. # a0 = pointer to extended precision input #
  7318. # d0 = round precision,mode #
  7319. # #
  7320. # OUTPUT ************************************************************** #
  7321. # fp0 = arctanh(X) #
  7322. # #
  7323. # ACCURACY and MONOTONICITY ******************************************* #
  7324. # The returned result is within 3 ulps in 64 significant bit, #
  7325. # i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
  7326. # rounded to double precision. The result is provably monotonic #
  7327. # in double precision. #
  7328. # #
  7329. # ALGORITHM *********************************************************** #
  7330. # #
  7331. # ATANH #
  7332. # 1. If |X| >= 1, go to 3. #
  7333. # #
  7334. # 2. (|X| < 1) Calculate atanh(X) by #
  7335. # sgn := sign(X) #
  7336. # y := |X| #
  7337. # z := 2y/(1-y) #
  7338. # atanh(X) := sgn * (1/2) * logp1(z) #
  7339. # Exit. #
  7340. # #
  7341. # 3. If |X| > 1, go to 5. #
  7342. # #
  7343. # 4. (|X| = 1) Generate infinity with an appropriate sign and #
  7344. # divide-by-zero by #
  7345. # sgn := sign(X) #
  7346. # atan(X) := sgn / (+0). #
  7347. # Exit. #
  7348. # #
  7349. # 5. (|X| > 1) Generate an invalid operation by 0 * infinity. #
  7350. # Exit. #
  7351. # #
  7352. #########################################################################
  7353. global satanh
  7354. satanh:
  7355. mov.l (%a0),%d1
  7356. mov.w 4(%a0),%d1
  7357. and.l &0x7FFFFFFF,%d1
  7358. cmp.l %d1,&0x3FFF8000
  7359. bge.b ATANHBIG
  7360. #--THIS IS THE USUAL CASE, |X| < 1
  7361. #--Y = |X|, Z = 2Y/(1-Y), ATANH(X) = SIGN(X) * (1/2) * LOG1P(Z).
  7362. fabs.x (%a0),%fp0 # Y = |X|
  7363. fmov.x %fp0,%fp1
  7364. fneg.x %fp1 # -Y
  7365. fadd.x %fp0,%fp0 # 2Y
  7366. fadd.s &0x3F800000,%fp1 # 1-Y
  7367. fdiv.x %fp1,%fp0 # 2Y/(1-Y)
  7368. mov.l (%a0),%d1
  7369. and.l &0x80000000,%d1
  7370. or.l &0x3F000000,%d1 # SIGN(X)*HALF
  7371. mov.l %d1,-(%sp)
  7372. mov.l %d0,-(%sp) # save rnd prec,mode
  7373. clr.l %d0 # pass ext prec,RN
  7374. fmovm.x &0x01,-(%sp) # save Z on stack
  7375. lea (%sp),%a0 # pass ptr to Z
  7376. bsr slognp1 # LOG1P(Z)
  7377. add.l &0xc,%sp # clear Z from stack
  7378. mov.l (%sp)+,%d0 # fetch old prec,mode
  7379. fmov.l %d0,%fpcr # load it
  7380. mov.b &FMUL_OP,%d1 # last inst is MUL
  7381. fmul.s (%sp)+,%fp0
  7382. bra t_catch
  7383. ATANHBIG:
  7384. fabs.x (%a0),%fp0 # |X|
  7385. fcmp.s %fp0,&0x3F800000
  7386. fbgt t_operr
  7387. bra t_dz
  7388. global satanhd
  7389. #--ATANH(X) = X FOR DENORMALIZED X
  7390. satanhd:
  7391. bra t_extdnrm
  7392. #########################################################################
  7393. # slog10(): computes the base-10 logarithm of a normalized input #
  7394. # slog10d(): computes the base-10 logarithm of a denormalized input #
  7395. # slog2(): computes the base-2 logarithm of a normalized input #
  7396. # slog2d(): computes the base-2 logarithm of a denormalized input #
  7397. # #
  7398. # INPUT *************************************************************** #
  7399. # a0 = pointer to extended precision input #
  7400. # d0 = round precision,mode #
  7401. # #
  7402. # OUTPUT ************************************************************** #
  7403. # fp0 = log_10(X) or log_2(X) #
  7404. # #
  7405. # ACCURACY and MONOTONICITY ******************************************* #
  7406. # The returned result is within 1.7 ulps in 64 significant bit, #
  7407. # i.e. within 0.5003 ulp to 53 bits if the result is subsequently #
  7408. # rounded to double precision. The result is provably monotonic #
  7409. # in double precision. #
  7410. # #
  7411. # ALGORITHM *********************************************************** #
  7412. # #
  7413. # slog10d: #
  7414. # #
  7415. # Step 0. If X < 0, create a NaN and raise the invalid operation #
  7416. # flag. Otherwise, save FPCR in D1; set FpCR to default. #
  7417. # Notes: Default means round-to-nearest mode, no floating-point #
  7418. # traps, and precision control = double extended. #
  7419. # #
  7420. # Step 1. Call slognd to obtain Y = log(X), the natural log of X. #
  7421. # Notes: Even if X is denormalized, log(X) is always normalized. #
  7422. # #
  7423. # Step 2. Compute log_10(X) = log(X) * (1/log(10)). #
  7424. # 2.1 Restore the user FPCR #
  7425. # 2.2 Return ans := Y * INV_L10. #
  7426. # #
  7427. # slog10: #
  7428. # #
  7429. # Step 0. If X < 0, create a NaN and raise the invalid operation #
  7430. # flag. Otherwise, save FPCR in D1; set FpCR to default. #
  7431. # Notes: Default means round-to-nearest mode, no floating-point #
  7432. # traps, and precision control = double extended. #
  7433. # #
  7434. # Step 1. Call sLogN to obtain Y = log(X), the natural log of X. #
  7435. # #
  7436. # Step 2. Compute log_10(X) = log(X) * (1/log(10)). #
  7437. # 2.1 Restore the user FPCR #
  7438. # 2.2 Return ans := Y * INV_L10. #
  7439. # #
  7440. # sLog2d: #
  7441. # #
  7442. # Step 0. If X < 0, create a NaN and raise the invalid operation #
  7443. # flag. Otherwise, save FPCR in D1; set FpCR to default. #
  7444. # Notes: Default means round-to-nearest mode, no floating-point #
  7445. # traps, and precision control = double extended. #
  7446. # #
  7447. # Step 1. Call slognd to obtain Y = log(X), the natural log of X. #
  7448. # Notes: Even if X is denormalized, log(X) is always normalized. #
  7449. # #
  7450. # Step 2. Compute log_10(X) = log(X) * (1/log(2)). #
  7451. # 2.1 Restore the user FPCR #
  7452. # 2.2 Return ans := Y * INV_L2. #
  7453. # #
  7454. # sLog2: #
  7455. # #
  7456. # Step 0. If X < 0, create a NaN and raise the invalid operation #
  7457. # flag. Otherwise, save FPCR in D1; set FpCR to default. #
  7458. # Notes: Default means round-to-nearest mode, no floating-point #
  7459. # traps, and precision control = double extended. #
  7460. # #
  7461. # Step 1. If X is not an integer power of two, i.e., X != 2^k, #
  7462. # go to Step 3. #
  7463. # #
  7464. # Step 2. Return k. #
  7465. # 2.1 Get integer k, X = 2^k. #
  7466. # 2.2 Restore the user FPCR. #
  7467. # 2.3 Return ans := convert-to-double-extended(k). #
  7468. # #
  7469. # Step 3. Call sLogN to obtain Y = log(X), the natural log of X. #
  7470. # #
  7471. # Step 4. Compute log_2(X) = log(X) * (1/log(2)). #
  7472. # 4.1 Restore the user FPCR #
  7473. # 4.2 Return ans := Y * INV_L2. #
  7474. # #
  7475. #########################################################################
  7476. INV_L10:
  7477. long 0x3FFD0000,0xDE5BD8A9,0x37287195,0x00000000
  7478. INV_L2:
  7479. long 0x3FFF0000,0xB8AA3B29,0x5C17F0BC,0x00000000
  7480. global slog10
  7481. #--entry point for Log10(X), X is normalized
  7482. slog10:
  7483. fmov.b &0x1,%fp0
  7484. fcmp.x %fp0,(%a0) # if operand == 1,
  7485. fbeq.l ld_pzero # return an EXACT zero
  7486. mov.l (%a0),%d1
  7487. blt.w invalid
  7488. mov.l %d0,-(%sp)
  7489. clr.l %d0
  7490. bsr slogn # log(X), X normal.
  7491. fmov.l (%sp)+,%fpcr
  7492. fmul.x INV_L10(%pc),%fp0
  7493. bra t_inx2
  7494. global slog10d
  7495. #--entry point for Log10(X), X is denormalized
  7496. slog10d:
  7497. mov.l (%a0),%d1
  7498. blt.w invalid
  7499. mov.l %d0,-(%sp)
  7500. clr.l %d0
  7501. bsr slognd # log(X), X denorm.
  7502. fmov.l (%sp)+,%fpcr
  7503. fmul.x INV_L10(%pc),%fp0
  7504. bra t_minx2
  7505. global slog2
  7506. #--entry point for Log2(X), X is normalized
  7507. slog2:
  7508. mov.l (%a0),%d1
  7509. blt.w invalid
  7510. mov.l 8(%a0),%d1
  7511. bne.b continue # X is not 2^k
  7512. mov.l 4(%a0),%d1
  7513. and.l &0x7FFFFFFF,%d1
  7514. bne.b continue
  7515. #--X = 2^k.
  7516. mov.w (%a0),%d1
  7517. and.l &0x00007FFF,%d1
  7518. sub.l &0x3FFF,%d1
  7519. beq.l ld_pzero
  7520. fmov.l %d0,%fpcr
  7521. fmov.l %d1,%fp0
  7522. bra t_inx2
  7523. continue:
  7524. mov.l %d0,-(%sp)
  7525. clr.l %d0
  7526. bsr slogn # log(X), X normal.
  7527. fmov.l (%sp)+,%fpcr
  7528. fmul.x INV_L2(%pc),%fp0
  7529. bra t_inx2
  7530. invalid:
  7531. bra t_operr
  7532. global slog2d
  7533. #--entry point for Log2(X), X is denormalized
  7534. slog2d:
  7535. mov.l (%a0),%d1
  7536. blt.w invalid
  7537. mov.l %d0,-(%sp)
  7538. clr.l %d0
  7539. bsr slognd # log(X), X denorm.
  7540. fmov.l (%sp)+,%fpcr
  7541. fmul.x INV_L2(%pc),%fp0
  7542. bra t_minx2
  7543. #########################################################################
  7544. # stwotox(): computes 2**X for a normalized input #
  7545. # stwotoxd(): computes 2**X for a denormalized input #
  7546. # stentox(): computes 10**X for a normalized input #
  7547. # stentoxd(): computes 10**X for a denormalized input #
  7548. # #
  7549. # INPUT *************************************************************** #
  7550. # a0 = pointer to extended precision input #
  7551. # d0 = round precision,mode #
  7552. # #
  7553. # OUTPUT ************************************************************** #
  7554. # fp0 = 2**X or 10**X #
  7555. # #
  7556. # ACCURACY and MONOTONICITY ******************************************* #
  7557. # The returned result is within 2 ulps in 64 significant bit, #
  7558. # i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
  7559. # rounded to double precision. The result is provably monotonic #
  7560. # in double precision. #
  7561. # #
  7562. # ALGORITHM *********************************************************** #
  7563. # #
  7564. # twotox #
  7565. # 1. If |X| > 16480, go to ExpBig. #
  7566. # #
  7567. # 2. If |X| < 2**(-70), go to ExpSm. #
  7568. # #
  7569. # 3. Decompose X as X = N/64 + r where |r| <= 1/128. Furthermore #
  7570. # decompose N as #
  7571. # N = 64(M + M') + j, j = 0,1,2,...,63. #
  7572. # #
  7573. # 4. Overwrite r := r * log2. Then #
  7574. # 2**X = 2**(M') * 2**(M) * 2**(j/64) * exp(r). #
  7575. # Go to expr to compute that expression. #
  7576. # #
  7577. # tentox #
  7578. # 1. If |X| > 16480*log_10(2) (base 10 log of 2), go to ExpBig. #
  7579. # #
  7580. # 2. If |X| < 2**(-70), go to ExpSm. #
  7581. # #
  7582. # 3. Set y := X*log_2(10)*64 (base 2 log of 10). Set #
  7583. # N := round-to-int(y). Decompose N as #
  7584. # N = 64(M + M') + j, j = 0,1,2,...,63. #
  7585. # #
  7586. # 4. Define r as #
  7587. # r := ((X - N*L1)-N*L2) * L10 #
  7588. # where L1, L2 are the leading and trailing parts of #
  7589. # log_10(2)/64 and L10 is the natural log of 10. Then #
  7590. # 10**X = 2**(M') * 2**(M) * 2**(j/64) * exp(r). #
  7591. # Go to expr to compute that expression. #
  7592. # #
  7593. # expr #
  7594. # 1. Fetch 2**(j/64) from table as Fact1 and Fact2. #
  7595. # #
  7596. # 2. Overwrite Fact1 and Fact2 by #
  7597. # Fact1 := 2**(M) * Fact1 #
  7598. # Fact2 := 2**(M) * Fact2 #
  7599. # Thus Fact1 + Fact2 = 2**(M) * 2**(j/64). #
  7600. # #
  7601. # 3. Calculate P where 1 + P approximates exp(r): #
  7602. # P = r + r*r*(A1+r*(A2+...+r*A5)). #
  7603. # #
  7604. # 4. Let AdjFact := 2**(M'). Return #
  7605. # AdjFact * ( Fact1 + ((Fact1*P) + Fact2) ). #
  7606. # Exit. #
  7607. # #
  7608. # ExpBig #
  7609. # 1. Generate overflow by Huge * Huge if X > 0; otherwise, #
  7610. # generate underflow by Tiny * Tiny. #
  7611. # #
  7612. # ExpSm #
  7613. # 1. Return 1 + X. #
  7614. # #
  7615. #########################################################################
  7616. L2TEN64:
  7617. long 0x406A934F,0x0979A371 # 64LOG10/LOG2
  7618. L10TWO1:
  7619. long 0x3F734413,0x509F8000 # LOG2/64LOG10
  7620. L10TWO2:
  7621. long 0xBFCD0000,0xC0219DC1,0xDA994FD2,0x00000000
  7622. LOG10: long 0x40000000,0x935D8DDD,0xAAA8AC17,0x00000000
  7623. LOG2: long 0x3FFE0000,0xB17217F7,0xD1CF79AC,0x00000000
  7624. EXPA5: long 0x3F56C16D,0x6F7BD0B2
  7625. EXPA4: long 0x3F811112,0x302C712C
  7626. EXPA3: long 0x3FA55555,0x55554CC1
  7627. EXPA2: long 0x3FC55555,0x55554A54
  7628. EXPA1: long 0x3FE00000,0x00000000,0x00000000,0x00000000
  7629. TEXPTBL:
  7630. long 0x3FFF0000,0x80000000,0x00000000,0x3F738000
  7631. long 0x3FFF0000,0x8164D1F3,0xBC030773,0x3FBEF7CA
  7632. long 0x3FFF0000,0x82CD8698,0xAC2BA1D7,0x3FBDF8A9
  7633. long 0x3FFF0000,0x843A28C3,0xACDE4046,0x3FBCD7C9
  7634. long 0x3FFF0000,0x85AAC367,0xCC487B15,0xBFBDE8DA
  7635. long 0x3FFF0000,0x871F6196,0x9E8D1010,0x3FBDE85C
  7636. long 0x3FFF0000,0x88980E80,0x92DA8527,0x3FBEBBF1
  7637. long 0x3FFF0000,0x8A14D575,0x496EFD9A,0x3FBB80CA
  7638. long 0x3FFF0000,0x8B95C1E3,0xEA8BD6E7,0xBFBA8373
  7639. long 0x3FFF0000,0x8D1ADF5B,0x7E5BA9E6,0xBFBE9670
  7640. long 0x3FFF0000,0x8EA4398B,0x45CD53C0,0x3FBDB700
  7641. long 0x3FFF0000,0x9031DC43,0x1466B1DC,0x3FBEEEB0
  7642. long 0x3FFF0000,0x91C3D373,0xAB11C336,0x3FBBFD6D
  7643. long 0x3FFF0000,0x935A2B2F,0x13E6E92C,0xBFBDB319
  7644. long 0x3FFF0000,0x94F4EFA8,0xFEF70961,0x3FBDBA2B
  7645. long 0x3FFF0000,0x96942D37,0x20185A00,0x3FBE91D5
  7646. long 0x3FFF0000,0x9837F051,0x8DB8A96F,0x3FBE8D5A
  7647. long 0x3FFF0000,0x99E04593,0x20B7FA65,0xBFBCDE7B
  7648. long 0x3FFF0000,0x9B8D39B9,0xD54E5539,0xBFBEBAAF
  7649. long 0x3FFF0000,0x9D3ED9A7,0x2CFFB751,0xBFBD86DA
  7650. long 0x3FFF0000,0x9EF53260,0x91A111AE,0xBFBEBEDD
  7651. long 0x3FFF0000,0xA0B0510F,0xB9714FC2,0x3FBCC96E
  7652. long 0x3FFF0000,0xA2704303,0x0C496819,0xBFBEC90B
  7653. long 0x3FFF0000,0xA43515AE,0x09E6809E,0x3FBBD1DB
  7654. long 0x3FFF0000,0xA5FED6A9,0xB15138EA,0x3FBCE5EB
  7655. long 0x3FFF0000,0xA7CD93B4,0xE965356A,0xBFBEC274
  7656. long 0x3FFF0000,0xA9A15AB4,0xEA7C0EF8,0x3FBEA83C
  7657. long 0x3FFF0000,0xAB7A39B5,0xA93ED337,0x3FBECB00
  7658. long 0x3FFF0000,0xAD583EEA,0x42A14AC6,0x3FBE9301
  7659. long 0x3FFF0000,0xAF3B78AD,0x690A4375,0xBFBD8367
  7660. long 0x3FFF0000,0xB123F581,0xD2AC2590,0xBFBEF05F
  7661. long 0x3FFF0000,0xB311C412,0xA9112489,0x3FBDFB3C
  7662. long 0x3FFF0000,0xB504F333,0xF9DE6484,0x3FBEB2FB
  7663. long 0x3FFF0000,0xB6FD91E3,0x28D17791,0x3FBAE2CB
  7664. long 0x3FFF0000,0xB8FBAF47,0x62FB9EE9,0x3FBCDC3C
  7665. long 0x3FFF0000,0xBAFF5AB2,0x133E45FB,0x3FBEE9AA
  7666. long 0x3FFF0000,0xBD08A39F,0x580C36BF,0xBFBEAEFD
  7667. long 0x3FFF0000,0xBF1799B6,0x7A731083,0xBFBCBF51
  7668. long 0x3FFF0000,0xC12C4CCA,0x66709456,0x3FBEF88A
  7669. long 0x3FFF0000,0xC346CCDA,0x24976407,0x3FBD83B2
  7670. long 0x3FFF0000,0xC5672A11,0x5506DADD,0x3FBDF8AB
  7671. long 0x3FFF0000,0xC78D74C8,0xABB9B15D,0xBFBDFB17
  7672. long 0x3FFF0000,0xC9B9BD86,0x6E2F27A3,0xBFBEFE3C
  7673. long 0x3FFF0000,0xCBEC14FE,0xF2727C5D,0xBFBBB6F8
  7674. long 0x3FFF0000,0xCE248C15,0x1F8480E4,0xBFBCEE53
  7675. long 0x3FFF0000,0xD06333DA,0xEF2B2595,0xBFBDA4AE
  7676. long 0x3FFF0000,0xD2A81D91,0xF12AE45A,0x3FBC9124
  7677. long 0x3FFF0000,0xD4F35AAB,0xCFEDFA1F,0x3FBEB243
  7678. long 0x3FFF0000,0xD744FCCA,0xD69D6AF4,0x3FBDE69A
  7679. long 0x3FFF0000,0xD99D15C2,0x78AFD7B6,0xBFB8BC61
  7680. long 0x3FFF0000,0xDBFBB797,0xDAF23755,0x3FBDF610
  7681. long 0x3FFF0000,0xDE60F482,0x5E0E9124,0xBFBD8BE1
  7682. long 0x3FFF0000,0xE0CCDEEC,0x2A94E111,0x3FBACB12
  7683. long 0x3FFF0000,0xE33F8972,0xBE8A5A51,0x3FBB9BFE
  7684. long 0x3FFF0000,0xE5B906E7,0x7C8348A8,0x3FBCF2F4
  7685. long 0x3FFF0000,0xE8396A50,0x3C4BDC68,0x3FBEF22F
  7686. long 0x3FFF0000,0xEAC0C6E7,0xDD24392F,0xBFBDBF4A
  7687. long 0x3FFF0000,0xED4F301E,0xD9942B84,0x3FBEC01A
  7688. long 0x3FFF0000,0xEFE4B99B,0xDCDAF5CB,0x3FBE8CAC
  7689. long 0x3FFF0000,0xF281773C,0x59FFB13A,0xBFBCBB3F
  7690. long 0x3FFF0000,0xF5257D15,0x2486CC2C,0x3FBEF73A
  7691. long 0x3FFF0000,0xF7D0DF73,0x0AD13BB9,0xBFB8B795
  7692. long 0x3FFF0000,0xFA83B2DB,0x722A033A,0x3FBEF84B
  7693. long 0x3FFF0000,0xFD3E0C0C,0xF486C175,0xBFBEF581
  7694. set INT,L_SCR1
  7695. set X,FP_SCR0
  7696. set XDCARE,X+2
  7697. set XFRAC,X+4
  7698. set ADJFACT,FP_SCR0
  7699. set FACT1,FP_SCR0
  7700. set FACT1HI,FACT1+4
  7701. set FACT1LOW,FACT1+8
  7702. set FACT2,FP_SCR1
  7703. set FACT2HI,FACT2+4
  7704. set FACT2LOW,FACT2+8
  7705. global stwotox
  7706. #--ENTRY POINT FOR 2**(X), HERE X IS FINITE, NON-ZERO, AND NOT NAN'S
  7707. stwotox:
  7708. fmovm.x (%a0),&0x80 # LOAD INPUT
  7709. mov.l (%a0),%d1
  7710. mov.w 4(%a0),%d1
  7711. fmov.x %fp0,X(%a6)
  7712. and.l &0x7FFFFFFF,%d1
  7713. cmp.l %d1,&0x3FB98000 # |X| >= 2**(-70)?
  7714. bge.b TWOOK1
  7715. bra.w EXPBORS
  7716. TWOOK1:
  7717. cmp.l %d1,&0x400D80C0 # |X| > 16480?
  7718. ble.b TWOMAIN
  7719. bra.w EXPBORS
  7720. TWOMAIN:
  7721. #--USUAL CASE, 2^(-70) <= |X| <= 16480
  7722. fmov.x %fp0,%fp1
  7723. fmul.s &0x42800000,%fp1 # 64 * X
  7724. fmov.l %fp1,INT(%a6) # N = ROUND-TO-INT(64 X)
  7725. mov.l %d2,-(%sp)
  7726. lea TEXPTBL(%pc),%a1 # LOAD ADDRESS OF TABLE OF 2^(J/64)
  7727. fmov.l INT(%a6),%fp1 # N --> FLOATING FMT
  7728. mov.l INT(%a6),%d1
  7729. mov.l %d1,%d2
  7730. and.l &0x3F,%d1 # D0 IS J
  7731. asl.l &4,%d1 # DISPLACEMENT FOR 2^(J/64)
  7732. add.l %d1,%a1 # ADDRESS FOR 2^(J/64)
  7733. asr.l &6,%d2 # d2 IS L, N = 64L + J
  7734. mov.l %d2,%d1
  7735. asr.l &1,%d1 # D0 IS M
  7736. sub.l %d1,%d2 # d2 IS M', N = 64(M+M') + J
  7737. add.l &0x3FFF,%d2
  7738. #--SUMMARY: a1 IS ADDRESS FOR THE LEADING PORTION OF 2^(J/64),
  7739. #--D0 IS M WHERE N = 64(M+M') + J. NOTE THAT |M| <= 16140 BY DESIGN.
  7740. #--ADJFACT = 2^(M').
  7741. #--REGISTERS SAVED SO FAR ARE (IN ORDER) FPCR, D0, FP1, a1, AND FP2.
  7742. fmovm.x &0x0c,-(%sp) # save fp2/fp3
  7743. fmul.s &0x3C800000,%fp1 # (1/64)*N
  7744. mov.l (%a1)+,FACT1(%a6)
  7745. mov.l (%a1)+,FACT1HI(%a6)
  7746. mov.l (%a1)+,FACT1LOW(%a6)
  7747. mov.w (%a1)+,FACT2(%a6)
  7748. fsub.x %fp1,%fp0 # X - (1/64)*INT(64 X)
  7749. mov.w (%a1)+,FACT2HI(%a6)
  7750. clr.w FACT2HI+2(%a6)
  7751. clr.l FACT2LOW(%a6)
  7752. add.w %d1,FACT1(%a6)
  7753. fmul.x LOG2(%pc),%fp0 # FP0 IS R
  7754. add.w %d1,FACT2(%a6)
  7755. bra.w expr
  7756. EXPBORS:
  7757. #--FPCR, D0 SAVED
  7758. cmp.l %d1,&0x3FFF8000
  7759. bgt.b TEXPBIG
  7760. #--|X| IS SMALL, RETURN 1 + X
  7761. fmov.l %d0,%fpcr # restore users round prec,mode
  7762. fadd.s &0x3F800000,%fp0 # RETURN 1 + X
  7763. bra t_pinx2
  7764. TEXPBIG:
  7765. #--|X| IS LARGE, GENERATE OVERFLOW IF X > 0; ELSE GENERATE UNDERFLOW
  7766. #--REGISTERS SAVE SO FAR ARE FPCR AND D0
  7767. mov.l X(%a6),%d1
  7768. cmp.l %d1,&0
  7769. blt.b EXPNEG
  7770. bra t_ovfl2 # t_ovfl expects positive value
  7771. EXPNEG:
  7772. bra t_unfl2 # t_unfl expects positive value
  7773. global stwotoxd
  7774. stwotoxd:
  7775. #--ENTRY POINT FOR 2**(X) FOR DENORMALIZED ARGUMENT
  7776. fmov.l %d0,%fpcr # set user's rounding mode/precision
  7777. fmov.s &0x3F800000,%fp0 # RETURN 1 + X
  7778. mov.l (%a0),%d1
  7779. or.l &0x00800001,%d1
  7780. fadd.s %d1,%fp0
  7781. bra t_pinx2
  7782. global stentox
  7783. #--ENTRY POINT FOR 10**(X), HERE X IS FINITE, NON-ZERO, AND NOT NAN'S
  7784. stentox:
  7785. fmovm.x (%a0),&0x80 # LOAD INPUT
  7786. mov.l (%a0),%d1
  7787. mov.w 4(%a0),%d1
  7788. fmov.x %fp0,X(%a6)
  7789. and.l &0x7FFFFFFF,%d1
  7790. cmp.l %d1,&0x3FB98000 # |X| >= 2**(-70)?
  7791. bge.b TENOK1
  7792. bra.w EXPBORS
  7793. TENOK1:
  7794. cmp.l %d1,&0x400B9B07 # |X| <= 16480*log2/log10 ?
  7795. ble.b TENMAIN
  7796. bra.w EXPBORS
  7797. TENMAIN:
  7798. #--USUAL CASE, 2^(-70) <= |X| <= 16480 LOG 2 / LOG 10
  7799. fmov.x %fp0,%fp1
  7800. fmul.d L2TEN64(%pc),%fp1 # X*64*LOG10/LOG2
  7801. fmov.l %fp1,INT(%a6) # N=INT(X*64*LOG10/LOG2)
  7802. mov.l %d2,-(%sp)
  7803. lea TEXPTBL(%pc),%a1 # LOAD ADDRESS OF TABLE OF 2^(J/64)
  7804. fmov.l INT(%a6),%fp1 # N --> FLOATING FMT
  7805. mov.l INT(%a6),%d1
  7806. mov.l %d1,%d2
  7807. and.l &0x3F,%d1 # D0 IS J
  7808. asl.l &4,%d1 # DISPLACEMENT FOR 2^(J/64)
  7809. add.l %d1,%a1 # ADDRESS FOR 2^(J/64)
  7810. asr.l &6,%d2 # d2 IS L, N = 64L + J
  7811. mov.l %d2,%d1
  7812. asr.l &1,%d1 # D0 IS M
  7813. sub.l %d1,%d2 # d2 IS M', N = 64(M+M') + J
  7814. add.l &0x3FFF,%d2
  7815. #--SUMMARY: a1 IS ADDRESS FOR THE LEADING PORTION OF 2^(J/64),
  7816. #--D0 IS M WHERE N = 64(M+M') + J. NOTE THAT |M| <= 16140 BY DESIGN.
  7817. #--ADJFACT = 2^(M').
  7818. #--REGISTERS SAVED SO FAR ARE (IN ORDER) FPCR, D0, FP1, a1, AND FP2.
  7819. fmovm.x &0x0c,-(%sp) # save fp2/fp3
  7820. fmov.x %fp1,%fp2
  7821. fmul.d L10TWO1(%pc),%fp1 # N*(LOG2/64LOG10)_LEAD
  7822. mov.l (%a1)+,FACT1(%a6)
  7823. fmul.x L10TWO2(%pc),%fp2 # N*(LOG2/64LOG10)_TRAIL
  7824. mov.l (%a1)+,FACT1HI(%a6)
  7825. mov.l (%a1)+,FACT1LOW(%a6)
  7826. fsub.x %fp1,%fp0 # X - N L_LEAD
  7827. mov.w (%a1)+,FACT2(%a6)
  7828. fsub.x %fp2,%fp0 # X - N L_TRAIL
  7829. mov.w (%a1)+,FACT2HI(%a6)
  7830. clr.w FACT2HI+2(%a6)
  7831. clr.l FACT2LOW(%a6)
  7832. fmul.x LOG10(%pc),%fp0 # FP0 IS R
  7833. add.w %d1,FACT1(%a6)
  7834. add.w %d1,FACT2(%a6)
  7835. expr:
  7836. #--FPCR, FP2, FP3 ARE SAVED IN ORDER AS SHOWN.
  7837. #--ADJFACT CONTAINS 2**(M'), FACT1 + FACT2 = 2**(M) * 2**(J/64).
  7838. #--FP0 IS R. THE FOLLOWING CODE COMPUTES
  7839. #-- 2**(M'+M) * 2**(J/64) * EXP(R)
  7840. fmov.x %fp0,%fp1
  7841. fmul.x %fp1,%fp1 # FP1 IS S = R*R
  7842. fmov.d EXPA5(%pc),%fp2 # FP2 IS A5
  7843. fmov.d EXPA4(%pc),%fp3 # FP3 IS A4
  7844. fmul.x %fp1,%fp2 # FP2 IS S*A5
  7845. fmul.x %fp1,%fp3 # FP3 IS S*A4
  7846. fadd.d EXPA3(%pc),%fp2 # FP2 IS A3+S*A5
  7847. fadd.d EXPA2(%pc),%fp3 # FP3 IS A2+S*A4
  7848. fmul.x %fp1,%fp2 # FP2 IS S*(A3+S*A5)
  7849. fmul.x %fp1,%fp3 # FP3 IS S*(A2+S*A4)
  7850. fadd.d EXPA1(%pc),%fp2 # FP2 IS A1+S*(A3+S*A5)
  7851. fmul.x %fp0,%fp3 # FP3 IS R*S*(A2+S*A4)
  7852. fmul.x %fp1,%fp2 # FP2 IS S*(A1+S*(A3+S*A5))
  7853. fadd.x %fp3,%fp0 # FP0 IS R+R*S*(A2+S*A4)
  7854. fadd.x %fp2,%fp0 # FP0 IS EXP(R) - 1
  7855. fmovm.x (%sp)+,&0x30 # restore fp2/fp3
  7856. #--FINAL RECONSTRUCTION PROCESS
  7857. #--EXP(X) = 2^M*2^(J/64) + 2^M*2^(J/64)*(EXP(R)-1) - (1 OR 0)
  7858. fmul.x FACT1(%a6),%fp0
  7859. fadd.x FACT2(%a6),%fp0
  7860. fadd.x FACT1(%a6),%fp0
  7861. fmov.l %d0,%fpcr # restore users round prec,mode
  7862. mov.w %d2,ADJFACT(%a6) # INSERT EXPONENT
  7863. mov.l (%sp)+,%d2
  7864. mov.l &0x80000000,ADJFACT+4(%a6)
  7865. clr.l ADJFACT+8(%a6)
  7866. mov.b &FMUL_OP,%d1 # last inst is MUL
  7867. fmul.x ADJFACT(%a6),%fp0 # FINAL ADJUSTMENT
  7868. bra t_catch
  7869. global stentoxd
  7870. stentoxd:
  7871. #--ENTRY POINT FOR 10**(X) FOR DENORMALIZED ARGUMENT
  7872. fmov.l %d0,%fpcr # set user's rounding mode/precision
  7873. fmov.s &0x3F800000,%fp0 # RETURN 1 + X
  7874. mov.l (%a0),%d1
  7875. or.l &0x00800001,%d1
  7876. fadd.s %d1,%fp0
  7877. bra t_pinx2
  7878. #########################################################################
  7879. # sscale(): computes the destination operand scaled by the source #
  7880. # operand. If the absoulute value of the source operand is #
  7881. # >= 2^14, an overflow or underflow is returned. #
  7882. # #
  7883. # INPUT *************************************************************** #
  7884. # a0 = pointer to double-extended source operand X #
  7885. # a1 = pointer to double-extended destination operand Y #
  7886. # #
  7887. # OUTPUT ************************************************************** #
  7888. # fp0 = scale(X,Y) #
  7889. # #
  7890. #########################################################################
  7891. set SIGN, L_SCR1
  7892. global sscale
  7893. sscale:
  7894. mov.l %d0,-(%sp) # store off ctrl bits for now
  7895. mov.w DST_EX(%a1),%d1 # get dst exponent
  7896. smi.b SIGN(%a6) # use SIGN to hold dst sign
  7897. andi.l &0x00007fff,%d1 # strip sign from dst exp
  7898. mov.w SRC_EX(%a0),%d0 # check src bounds
  7899. andi.w &0x7fff,%d0 # clr src sign bit
  7900. cmpi.w %d0,&0x3fff # is src ~ ZERO?
  7901. blt.w src_small # yes
  7902. cmpi.w %d0,&0x400c # no; is src too big?
  7903. bgt.w src_out # yes
  7904. #
  7905. # Source is within 2^14 range.
  7906. #
  7907. src_ok:
  7908. fintrz.x SRC(%a0),%fp0 # calc int of src
  7909. fmov.l %fp0,%d0 # int src to d0
  7910. # don't want any accrued bits from the fintrz showing up later since
  7911. # we may need to read the fpsr for the last fp op in t_catch2().
  7912. fmov.l &0x0,%fpsr
  7913. tst.b DST_HI(%a1) # is dst denormalized?
  7914. bmi.b sok_norm
  7915. # the dst is a DENORM. normalize the DENORM and add the adjustment to
  7916. # the src value. then, jump to the norm part of the routine.
  7917. sok_dnrm:
  7918. mov.l %d0,-(%sp) # save src for now
  7919. mov.w DST_EX(%a1),FP_SCR0_EX(%a6) # make a copy
  7920. mov.l DST_HI(%a1),FP_SCR0_HI(%a6)
  7921. mov.l DST_LO(%a1),FP_SCR0_LO(%a6)
  7922. lea FP_SCR0(%a6),%a0 # pass ptr to DENORM
  7923. bsr.l norm # normalize the DENORM
  7924. neg.l %d0
  7925. add.l (%sp)+,%d0 # add adjustment to src
  7926. fmovm.x FP_SCR0(%a6),&0x80 # load normalized DENORM
  7927. cmpi.w %d0,&-0x3fff # is the shft amt really low?
  7928. bge.b sok_norm2 # thank goodness no
  7929. # the multiply factor that we're trying to create should be a denorm
  7930. # for the multiply to work. therefore, we're going to actually do a
  7931. # multiply with a denorm which will cause an unimplemented data type
  7932. # exception to be put into the machine which will be caught and corrected
  7933. # later. we don't do this with the DENORMs above because this method
  7934. # is slower. but, don't fret, I don't see it being used much either.
  7935. fmov.l (%sp)+,%fpcr # restore user fpcr
  7936. mov.l &0x80000000,%d1 # load normalized mantissa
  7937. subi.l &-0x3fff,%d0 # how many should we shift?
  7938. neg.l %d0 # make it positive
  7939. cmpi.b %d0,&0x20 # is it > 32?
  7940. bge.b sok_dnrm_32 # yes
  7941. lsr.l %d0,%d1 # no; bit stays in upper lw
  7942. clr.l -(%sp) # insert zero low mantissa
  7943. mov.l %d1,-(%sp) # insert new high mantissa
  7944. clr.l -(%sp) # make zero exponent
  7945. bra.b sok_norm_cont
  7946. sok_dnrm_32:
  7947. subi.b &0x20,%d0 # get shift count
  7948. lsr.l %d0,%d1 # make low mantissa longword
  7949. mov.l %d1,-(%sp) # insert new low mantissa
  7950. clr.l -(%sp) # insert zero high mantissa
  7951. clr.l -(%sp) # make zero exponent
  7952. bra.b sok_norm_cont
  7953. # the src will force the dst to a DENORM value or worse. so, let's
  7954. # create an fp multiply that will create the result.
  7955. sok_norm:
  7956. fmovm.x DST(%a1),&0x80 # load fp0 with normalized src
  7957. sok_norm2:
  7958. fmov.l (%sp)+,%fpcr # restore user fpcr
  7959. addi.w &0x3fff,%d0 # turn src amt into exp value
  7960. swap %d0 # put exponent in high word
  7961. clr.l -(%sp) # insert new exponent
  7962. mov.l &0x80000000,-(%sp) # insert new high mantissa
  7963. mov.l %d0,-(%sp) # insert new lo mantissa
  7964. sok_norm_cont:
  7965. fmov.l %fpcr,%d0 # d0 needs fpcr for t_catch2
  7966. mov.b &FMUL_OP,%d1 # last inst is MUL
  7967. fmul.x (%sp)+,%fp0 # do the multiply
  7968. bra t_catch2 # catch any exceptions
  7969. #
  7970. # Source is outside of 2^14 range. Test the sign and branch
  7971. # to the appropriate exception handler.
  7972. #
  7973. src_out:
  7974. mov.l (%sp)+,%d0 # restore ctrl bits
  7975. exg %a0,%a1 # swap src,dst ptrs
  7976. tst.b SRC_EX(%a1) # is src negative?
  7977. bmi t_unfl # yes; underflow
  7978. bra t_ovfl_sc # no; overflow
  7979. #
  7980. # The source input is below 1, so we check for denormalized numbers
  7981. # and set unfl.
  7982. #
  7983. src_small:
  7984. tst.b DST_HI(%a1) # is dst denormalized?
  7985. bpl.b ssmall_done # yes
  7986. mov.l (%sp)+,%d0
  7987. fmov.l %d0,%fpcr # no; load control bits
  7988. mov.b &FMOV_OP,%d1 # last inst is MOVE
  7989. fmov.x DST(%a1),%fp0 # simply return dest
  7990. bra t_catch2
  7991. ssmall_done:
  7992. mov.l (%sp)+,%d0 # load control bits into d1
  7993. mov.l %a1,%a0 # pass ptr to dst
  7994. bra t_resdnrm
  7995. #########################################################################
  7996. # smod(): computes the fp MOD of the input values X,Y. #
  7997. # srem(): computes the fp (IEEE) REM of the input values X,Y. #
  7998. # #
  7999. # INPUT *************************************************************** #
  8000. # a0 = pointer to extended precision input X #
  8001. # a1 = pointer to extended precision input Y #
  8002. # d0 = round precision,mode #
  8003. # #
  8004. # The input operands X and Y can be either normalized or #
  8005. # denormalized. #
  8006. # #
  8007. # OUTPUT ************************************************************** #
  8008. # fp0 = FREM(X,Y) or FMOD(X,Y) #
  8009. # #
  8010. # ALGORITHM *********************************************************** #
  8011. # #
  8012. # Step 1. Save and strip signs of X and Y: signX := sign(X), #
  8013. # signY := sign(Y), X := |X|, Y := |Y|, #
  8014. # signQ := signX EOR signY. Record whether MOD or REM #
  8015. # is requested. #
  8016. # #
  8017. # Step 2. Set L := expo(X)-expo(Y), k := 0, Q := 0. #
  8018. # If (L < 0) then #
  8019. # R := X, go to Step 4. #
  8020. # else #
  8021. # R := 2^(-L)X, j := L. #
  8022. # endif #
  8023. # #
  8024. # Step 3. Perform MOD(X,Y) #
  8025. # 3.1 If R = Y, go to Step 9. #
  8026. # 3.2 If R > Y, then { R := R - Y, Q := Q + 1} #
  8027. # 3.3 If j = 0, go to Step 4. #
  8028. # 3.4 k := k + 1, j := j - 1, Q := 2Q, R := 2R. Go to #
  8029. # Step 3.1. #
  8030. # #
  8031. # Step 4. At this point, R = X - QY = MOD(X,Y). Set #
  8032. # Last_Subtract := false (used in Step 7 below). If #
  8033. # MOD is requested, go to Step 6. #
  8034. # #
  8035. # Step 5. R = MOD(X,Y), but REM(X,Y) is requested. #
  8036. # 5.1 If R < Y/2, then R = MOD(X,Y) = REM(X,Y). Go to #
  8037. # Step 6. #
  8038. # 5.2 If R > Y/2, then { set Last_Subtract := true, #
  8039. # Q := Q + 1, Y := signY*Y }. Go to Step 6. #
  8040. # 5.3 This is the tricky case of R = Y/2. If Q is odd, #
  8041. # then { Q := Q + 1, signX := -signX }. #
  8042. # #
  8043. # Step 6. R := signX*R. #
  8044. # #
  8045. # Step 7. If Last_Subtract = true, R := R - Y. #
  8046. # #
  8047. # Step 8. Return signQ, last 7 bits of Q, and R as required. #
  8048. # #
  8049. # Step 9. At this point, R = 2^(-j)*X - Q Y = Y. Thus, #
  8050. # X = 2^(j)*(Q+1)Y. set Q := 2^(j)*(Q+1), #
  8051. # R := 0. Return signQ, last 7 bits of Q, and R. #
  8052. # #
  8053. #########################################################################
  8054. set Mod_Flag,L_SCR3
  8055. set Sc_Flag,L_SCR3+1
  8056. set SignY,L_SCR2
  8057. set SignX,L_SCR2+2
  8058. set SignQ,L_SCR3+2
  8059. set Y,FP_SCR0
  8060. set Y_Hi,Y+4
  8061. set Y_Lo,Y+8
  8062. set R,FP_SCR1
  8063. set R_Hi,R+4
  8064. set R_Lo,R+8
  8065. Scale:
  8066. long 0x00010000,0x80000000,0x00000000,0x00000000
  8067. global smod
  8068. smod:
  8069. clr.b FPSR_QBYTE(%a6)
  8070. mov.l %d0,-(%sp) # save ctrl bits
  8071. clr.b Mod_Flag(%a6)
  8072. bra.b Mod_Rem
  8073. global srem
  8074. srem:
  8075. clr.b FPSR_QBYTE(%a6)
  8076. mov.l %d0,-(%sp) # save ctrl bits
  8077. mov.b &0x1,Mod_Flag(%a6)
  8078. Mod_Rem:
  8079. #..Save sign of X and Y
  8080. movm.l &0x3f00,-(%sp) # save data registers
  8081. mov.w SRC_EX(%a0),%d3
  8082. mov.w %d3,SignY(%a6)
  8083. and.l &0x00007FFF,%d3 # Y := |Y|
  8084. #
  8085. mov.l SRC_HI(%a0),%d4
  8086. mov.l SRC_LO(%a0),%d5 # (D3,D4,D5) is |Y|
  8087. tst.l %d3
  8088. bne.b Y_Normal
  8089. mov.l &0x00003FFE,%d3 # $3FFD + 1
  8090. tst.l %d4
  8091. bne.b HiY_not0
  8092. HiY_0:
  8093. mov.l %d5,%d4
  8094. clr.l %d5
  8095. sub.l &32,%d3
  8096. clr.l %d6
  8097. bfffo %d4{&0:&32},%d6
  8098. lsl.l %d6,%d4
  8099. sub.l %d6,%d3 # (D3,D4,D5) is normalized
  8100. # ...with bias $7FFD
  8101. bra.b Chk_X
  8102. HiY_not0:
  8103. clr.l %d6
  8104. bfffo %d4{&0:&32},%d6
  8105. sub.l %d6,%d3
  8106. lsl.l %d6,%d4
  8107. mov.l %d5,%d7 # a copy of D5
  8108. lsl.l %d6,%d5
  8109. neg.l %d6
  8110. add.l &32,%d6
  8111. lsr.l %d6,%d7
  8112. or.l %d7,%d4 # (D3,D4,D5) normalized
  8113. # ...with bias $7FFD
  8114. bra.b Chk_X
  8115. Y_Normal:
  8116. add.l &0x00003FFE,%d3 # (D3,D4,D5) normalized
  8117. # ...with bias $7FFD
  8118. Chk_X:
  8119. mov.w DST_EX(%a1),%d0
  8120. mov.w %d0,SignX(%a6)
  8121. mov.w SignY(%a6),%d1
  8122. eor.l %d0,%d1
  8123. and.l &0x00008000,%d1
  8124. mov.w %d1,SignQ(%a6) # sign(Q) obtained
  8125. and.l &0x00007FFF,%d0
  8126. mov.l DST_HI(%a1),%d1
  8127. mov.l DST_LO(%a1),%d2 # (D0,D1,D2) is |X|
  8128. tst.l %d0
  8129. bne.b X_Normal
  8130. mov.l &0x00003FFE,%d0
  8131. tst.l %d1
  8132. bne.b HiX_not0
  8133. HiX_0:
  8134. mov.l %d2,%d1
  8135. clr.l %d2
  8136. sub.l &32,%d0
  8137. clr.l %d6
  8138. bfffo %d1{&0:&32},%d6
  8139. lsl.l %d6,%d1
  8140. sub.l %d6,%d0 # (D0,D1,D2) is normalized
  8141. # ...with bias $7FFD
  8142. bra.b Init
  8143. HiX_not0:
  8144. clr.l %d6
  8145. bfffo %d1{&0:&32},%d6
  8146. sub.l %d6,%d0
  8147. lsl.l %d6,%d1
  8148. mov.l %d2,%d7 # a copy of D2
  8149. lsl.l %d6,%d2
  8150. neg.l %d6
  8151. add.l &32,%d6
  8152. lsr.l %d6,%d7
  8153. or.l %d7,%d1 # (D0,D1,D2) normalized
  8154. # ...with bias $7FFD
  8155. bra.b Init
  8156. X_Normal:
  8157. add.l &0x00003FFE,%d0 # (D0,D1,D2) normalized
  8158. # ...with bias $7FFD
  8159. Init:
  8160. #
  8161. mov.l %d3,L_SCR1(%a6) # save biased exp(Y)
  8162. mov.l %d0,-(%sp) # save biased exp(X)
  8163. sub.l %d3,%d0 # L := expo(X)-expo(Y)
  8164. clr.l %d6 # D6 := carry <- 0
  8165. clr.l %d3 # D3 is Q
  8166. mov.l &0,%a1 # A1 is k; j+k=L, Q=0
  8167. #..(Carry,D1,D2) is R
  8168. tst.l %d0
  8169. bge.b Mod_Loop_pre
  8170. #..expo(X) < expo(Y). Thus X = mod(X,Y)
  8171. #
  8172. mov.l (%sp)+,%d0 # restore d0
  8173. bra.w Get_Mod
  8174. Mod_Loop_pre:
  8175. addq.l &0x4,%sp # erase exp(X)
  8176. #..At this point R = 2^(-L)X; Q = 0; k = 0; and k+j = L
  8177. Mod_Loop:
  8178. tst.l %d6 # test carry bit
  8179. bgt.b R_GT_Y
  8180. #..At this point carry = 0, R = (D1,D2), Y = (D4,D5)
  8181. cmp.l %d1,%d4 # compare hi(R) and hi(Y)
  8182. bne.b R_NE_Y
  8183. cmp.l %d2,%d5 # compare lo(R) and lo(Y)
  8184. bne.b R_NE_Y
  8185. #..At this point, R = Y
  8186. bra.w Rem_is_0
  8187. R_NE_Y:
  8188. #..use the borrow of the previous compare
  8189. bcs.b R_LT_Y # borrow is set iff R < Y
  8190. R_GT_Y:
  8191. #..If Carry is set, then Y < (Carry,D1,D2) < 2Y. Otherwise, Carry = 0
  8192. #..and Y < (D1,D2) < 2Y. Either way, perform R - Y
  8193. sub.l %d5,%d2 # lo(R) - lo(Y)
  8194. subx.l %d4,%d1 # hi(R) - hi(Y)
  8195. clr.l %d6 # clear carry
  8196. addq.l &1,%d3 # Q := Q + 1
  8197. R_LT_Y:
  8198. #..At this point, Carry=0, R < Y. R = 2^(k-L)X - QY; k+j = L; j >= 0.
  8199. tst.l %d0 # see if j = 0.
  8200. beq.b PostLoop
  8201. add.l %d3,%d3 # Q := 2Q
  8202. add.l %d2,%d2 # lo(R) = 2lo(R)
  8203. roxl.l &1,%d1 # hi(R) = 2hi(R) + carry
  8204. scs %d6 # set Carry if 2(R) overflows
  8205. addq.l &1,%a1 # k := k+1
  8206. subq.l &1,%d0 # j := j - 1
  8207. #..At this point, R=(Carry,D1,D2) = 2^(k-L)X - QY, j+k=L, j >= 0, R < 2Y.
  8208. bra.b Mod_Loop
  8209. PostLoop:
  8210. #..k = L, j = 0, Carry = 0, R = (D1,D2) = X - QY, R < Y.
  8211. #..normalize R.
  8212. mov.l L_SCR1(%a6),%d0 # new biased expo of R
  8213. tst.l %d1
  8214. bne.b HiR_not0
  8215. HiR_0:
  8216. mov.l %d2,%d1
  8217. clr.l %d2
  8218. sub.l &32,%d0
  8219. clr.l %d6
  8220. bfffo %d1{&0:&32},%d6
  8221. lsl.l %d6,%d1
  8222. sub.l %d6,%d0 # (D0,D1,D2) is normalized
  8223. # ...with bias $7FFD
  8224. bra.b Get_Mod
  8225. HiR_not0:
  8226. clr.l %d6
  8227. bfffo %d1{&0:&32},%d6
  8228. bmi.b Get_Mod # already normalized
  8229. sub.l %d6,%d0
  8230. lsl.l %d6,%d1
  8231. mov.l %d2,%d7 # a copy of D2
  8232. lsl.l %d6,%d2
  8233. neg.l %d6
  8234. add.l &32,%d6
  8235. lsr.l %d6,%d7
  8236. or.l %d7,%d1 # (D0,D1,D2) normalized
  8237. #
  8238. Get_Mod:
  8239. cmp.l %d0,&0x000041FE
  8240. bge.b No_Scale
  8241. Do_Scale:
  8242. mov.w %d0,R(%a6)
  8243. mov.l %d1,R_Hi(%a6)
  8244. mov.l %d2,R_Lo(%a6)
  8245. mov.l L_SCR1(%a6),%d6
  8246. mov.w %d6,Y(%a6)
  8247. mov.l %d4,Y_Hi(%a6)
  8248. mov.l %d5,Y_Lo(%a6)
  8249. fmov.x R(%a6),%fp0 # no exception
  8250. mov.b &1,Sc_Flag(%a6)
  8251. bra.b ModOrRem
  8252. No_Scale:
  8253. mov.l %d1,R_Hi(%a6)
  8254. mov.l %d2,R_Lo(%a6)
  8255. sub.l &0x3FFE,%d0
  8256. mov.w %d0,R(%a6)
  8257. mov.l L_SCR1(%a6),%d6
  8258. sub.l &0x3FFE,%d6
  8259. mov.l %d6,L_SCR1(%a6)
  8260. fmov.x R(%a6),%fp0
  8261. mov.w %d6,Y(%a6)
  8262. mov.l %d4,Y_Hi(%a6)
  8263. mov.l %d5,Y_Lo(%a6)
  8264. clr.b Sc_Flag(%a6)
  8265. #
  8266. ModOrRem:
  8267. tst.b Mod_Flag(%a6)
  8268. beq.b Fix_Sign
  8269. mov.l L_SCR1(%a6),%d6 # new biased expo(Y)
  8270. subq.l &1,%d6 # biased expo(Y/2)
  8271. cmp.l %d0,%d6
  8272. blt.b Fix_Sign
  8273. bgt.b Last_Sub
  8274. cmp.l %d1,%d4
  8275. bne.b Not_EQ
  8276. cmp.l %d2,%d5
  8277. bne.b Not_EQ
  8278. bra.w Tie_Case
  8279. Not_EQ:
  8280. bcs.b Fix_Sign
  8281. Last_Sub:
  8282. #
  8283. fsub.x Y(%a6),%fp0 # no exceptions
  8284. addq.l &1,%d3 # Q := Q + 1
  8285. #
  8286. Fix_Sign:
  8287. #..Get sign of X
  8288. mov.w SignX(%a6),%d6
  8289. bge.b Get_Q
  8290. fneg.x %fp0
  8291. #..Get Q
  8292. #
  8293. Get_Q:
  8294. clr.l %d6
  8295. mov.w SignQ(%a6),%d6 # D6 is sign(Q)
  8296. mov.l &8,%d7
  8297. lsr.l %d7,%d6
  8298. and.l &0x0000007F,%d3 # 7 bits of Q
  8299. or.l %d6,%d3 # sign and bits of Q
  8300. # swap %d3
  8301. # fmov.l %fpsr,%d6
  8302. # and.l &0xFF00FFFF,%d6
  8303. # or.l %d3,%d6
  8304. # fmov.l %d6,%fpsr # put Q in fpsr
  8305. mov.b %d3,FPSR_QBYTE(%a6) # put Q in fpsr
  8306. #
  8307. Restore:
  8308. movm.l (%sp)+,&0xfc # {%d2-%d7}
  8309. mov.l (%sp)+,%d0
  8310. fmov.l %d0,%fpcr
  8311. tst.b Sc_Flag(%a6)
  8312. beq.b Finish
  8313. mov.b &FMUL_OP,%d1 # last inst is MUL
  8314. fmul.x Scale(%pc),%fp0 # may cause underflow
  8315. bra t_catch2
  8316. # the '040 package did this apparently to see if the dst operand for the
  8317. # preceding fmul was a denorm. but, it better not have been since the
  8318. # algorithm just got done playing with fp0 and expected no exceptions
  8319. # as a result. trust me...
  8320. # bra t_avoid_unsupp # check for denorm as a
  8321. # ;result of the scaling
  8322. Finish:
  8323. mov.b &FMOV_OP,%d1 # last inst is MOVE
  8324. fmov.x %fp0,%fp0 # capture exceptions & round
  8325. bra t_catch2
  8326. Rem_is_0:
  8327. #..R = 2^(-j)X - Q Y = Y, thus R = 0 and quotient = 2^j (Q+1)
  8328. addq.l &1,%d3
  8329. cmp.l %d0,&8 # D0 is j
  8330. bge.b Q_Big
  8331. lsl.l %d0,%d3
  8332. bra.b Set_R_0
  8333. Q_Big:
  8334. clr.l %d3
  8335. Set_R_0:
  8336. fmov.s &0x00000000,%fp0
  8337. clr.b Sc_Flag(%a6)
  8338. bra.w Fix_Sign
  8339. Tie_Case:
  8340. #..Check parity of Q
  8341. mov.l %d3,%d6
  8342. and.l &0x00000001,%d6
  8343. tst.l %d6
  8344. beq.w Fix_Sign # Q is even
  8345. #..Q is odd, Q := Q + 1, signX := -signX
  8346. addq.l &1,%d3
  8347. mov.w SignX(%a6),%d6
  8348. eor.l &0x00008000,%d6
  8349. mov.w %d6,SignX(%a6)
  8350. bra.w Fix_Sign
  8351. #########################################################################
  8352. # XDEF **************************************************************** #
  8353. # tag(): return the optype of the input ext fp number #
  8354. # #
  8355. # This routine is used by the 060FPLSP. #
  8356. # #
  8357. # XREF **************************************************************** #
  8358. # None #
  8359. # #
  8360. # INPUT *************************************************************** #
  8361. # a0 = pointer to extended precision operand #
  8362. # #
  8363. # OUTPUT ************************************************************** #
  8364. # d0 = value of type tag #
  8365. # one of: NORM, INF, QNAN, SNAN, DENORM, ZERO #
  8366. # #
  8367. # ALGORITHM *********************************************************** #
  8368. # Simply test the exponent, j-bit, and mantissa values to #
  8369. # determine the type of operand. #
  8370. # If it's an unnormalized zero, alter the operand and force it #
  8371. # to be a normal zero. #
  8372. # #
  8373. #########################################################################
  8374. global tag
  8375. tag:
  8376. mov.w FTEMP_EX(%a0), %d0 # extract exponent
  8377. andi.w &0x7fff, %d0 # strip off sign
  8378. cmpi.w %d0, &0x7fff # is (EXP == MAX)?
  8379. beq.b inf_or_nan_x
  8380. not_inf_or_nan_x:
  8381. btst &0x7,FTEMP_HI(%a0)
  8382. beq.b not_norm_x
  8383. is_norm_x:
  8384. mov.b &NORM, %d0
  8385. rts
  8386. not_norm_x:
  8387. tst.w %d0 # is exponent = 0?
  8388. bne.b is_unnorm_x
  8389. not_unnorm_x:
  8390. tst.l FTEMP_HI(%a0)
  8391. bne.b is_denorm_x
  8392. tst.l FTEMP_LO(%a0)
  8393. bne.b is_denorm_x
  8394. is_zero_x:
  8395. mov.b &ZERO, %d0
  8396. rts
  8397. is_denorm_x:
  8398. mov.b &DENORM, %d0
  8399. rts
  8400. is_unnorm_x:
  8401. bsr.l unnorm_fix # convert to norm,denorm,or zero
  8402. rts
  8403. is_unnorm_reg_x:
  8404. mov.b &UNNORM, %d0
  8405. rts
  8406. inf_or_nan_x:
  8407. tst.l FTEMP_LO(%a0)
  8408. bne.b is_nan_x
  8409. mov.l FTEMP_HI(%a0), %d0
  8410. and.l &0x7fffffff, %d0 # msb is a don't care!
  8411. bne.b is_nan_x
  8412. is_inf_x:
  8413. mov.b &INF, %d0
  8414. rts
  8415. is_nan_x:
  8416. mov.b &QNAN, %d0
  8417. rts
  8418. #############################################################
  8419. qnan: long 0x7fff0000, 0xffffffff, 0xffffffff
  8420. #########################################################################
  8421. # XDEF **************************************************************** #
  8422. # t_dz(): Handle 060FPLSP dz exception for "flogn" emulation. #
  8423. # t_dz2(): Handle 060FPLSP dz exception for "fatanh" emulation. #
  8424. # #
  8425. # These rouitnes are used by the 060FPLSP package. #
  8426. # #
  8427. # XREF **************************************************************** #
  8428. # None #
  8429. # #
  8430. # INPUT *************************************************************** #
  8431. # a0 = pointer to extended precision source operand. #
  8432. # #
  8433. # OUTPUT ************************************************************** #
  8434. # fp0 = default DZ result. #
  8435. # #
  8436. # ALGORITHM *********************************************************** #
  8437. # Transcendental emulation for the 060FPLSP has detected that #
  8438. # a DZ exception should occur for the instruction. If DZ is disabled, #
  8439. # return the default result. #
  8440. # If DZ is enabled, the dst operand should be returned unscathed #
  8441. # in fp0 while fp1 is used to create a DZ exception so that the #
  8442. # operating system can log that such an event occurred. #
  8443. # #
  8444. #########################################################################
  8445. global t_dz
  8446. t_dz:
  8447. tst.b SRC_EX(%a0) # check sign for neg or pos
  8448. bpl.b dz_pinf # branch if pos sign
  8449. global t_dz2
  8450. t_dz2:
  8451. ori.l &dzinf_mask+neg_mask,USER_FPSR(%a6) # set N/I/DZ/ADZ
  8452. btst &dz_bit,FPCR_ENABLE(%a6)
  8453. bne.b dz_minf_ena
  8454. # dz is disabled. return a -INF.
  8455. fmov.s &0xff800000,%fp0 # return -INF
  8456. rts
  8457. # dz is enabled. create a dz exception so the user can record it
  8458. # but use fp1 instead. return the dst operand unscathed in fp0.
  8459. dz_minf_ena:
  8460. fmovm.x EXC_FP0(%a6),&0x80 # return fp0 unscathed
  8461. fmov.l USER_FPCR(%a6),%fpcr
  8462. fmov.s &0xbf800000,%fp1 # load -1
  8463. fdiv.s &0x00000000,%fp1 # -1 / 0
  8464. rts
  8465. dz_pinf:
  8466. ori.l &dzinf_mask,USER_FPSR(%a6) # set I/DZ/ADZ
  8467. btst &dz_bit,FPCR_ENABLE(%a6)
  8468. bne.b dz_pinf_ena
  8469. # dz is disabled. return a +INF.
  8470. fmov.s &0x7f800000,%fp0 # return +INF
  8471. rts
  8472. # dz is enabled. create a dz exception so the user can record it
  8473. # but use fp1 instead. return the dst operand unscathed in fp0.
  8474. dz_pinf_ena:
  8475. fmovm.x EXC_FP0(%a6),&0x80 # return fp0 unscathed
  8476. fmov.l USER_FPCR(%a6),%fpcr
  8477. fmov.s &0x3f800000,%fp1 # load +1
  8478. fdiv.s &0x00000000,%fp1 # +1 / 0
  8479. rts
  8480. #########################################################################
  8481. # XDEF **************************************************************** #
  8482. # t_operr(): Handle 060FPLSP OPERR exception during emulation. #
  8483. # #
  8484. # This routine is used by the 060FPLSP package. #
  8485. # #
  8486. # XREF **************************************************************** #
  8487. # None. #
  8488. # #
  8489. # INPUT *************************************************************** #
  8490. # fp1 = source operand #
  8491. # #
  8492. # OUTPUT ************************************************************** #
  8493. # fp0 = default result #
  8494. # fp1 = unchanged #
  8495. # #
  8496. # ALGORITHM *********************************************************** #
  8497. # An operand error should occur as the result of transcendental #
  8498. # emulation in the 060FPLSP. If OPERR is disabled, just return a NAN #
  8499. # in fp0. If OPERR is enabled, return the dst operand unscathed in fp0 #
  8500. # and the source operand in fp1. Use fp2 to create an OPERR exception #
  8501. # so that the operating system can log the event. #
  8502. # #
  8503. #########################################################################
  8504. global t_operr
  8505. t_operr:
  8506. ori.l &opnan_mask,USER_FPSR(%a6) # set NAN/OPERR/AIOP
  8507. btst &operr_bit,FPCR_ENABLE(%a6)
  8508. bne.b operr_ena
  8509. # operr is disabled. return a QNAN in fp0
  8510. fmovm.x qnan(%pc),&0x80 # return QNAN
  8511. rts
  8512. # operr is enabled. create an operr exception so the user can record it
  8513. # but use fp2 instead. return the dst operand unscathed in fp0.
  8514. operr_ena:
  8515. fmovm.x EXC_FP0(%a6),&0x80 # return fp0 unscathed
  8516. fmov.l USER_FPCR(%a6),%fpcr
  8517. fmovm.x &0x04,-(%sp) # save fp2
  8518. fmov.s &0x7f800000,%fp2 # load +INF
  8519. fmul.s &0x00000000,%fp2 # +INF x 0
  8520. fmovm.x (%sp)+,&0x20 # restore fp2
  8521. rts
  8522. pls_huge:
  8523. long 0x7ffe0000,0xffffffff,0xffffffff
  8524. mns_huge:
  8525. long 0xfffe0000,0xffffffff,0xffffffff
  8526. pls_tiny:
  8527. long 0x00000000,0x80000000,0x00000000
  8528. mns_tiny:
  8529. long 0x80000000,0x80000000,0x00000000
  8530. #########################################################################
  8531. # XDEF **************************************************************** #
  8532. # t_unfl(): Handle 060FPLSP underflow exception during emulation. #
  8533. # t_unfl2(): Handle 060FPLSP underflow exception during #
  8534. # emulation. result always positive. #
  8535. # #
  8536. # This routine is used by the 060FPLSP package. #
  8537. # #
  8538. # XREF **************************************************************** #
  8539. # None. #
  8540. # #
  8541. # INPUT *************************************************************** #
  8542. # a0 = pointer to extended precision source operand #
  8543. # #
  8544. # OUTPUT ************************************************************** #
  8545. # fp0 = default underflow result #
  8546. # #
  8547. # ALGORITHM *********************************************************** #
  8548. # An underflow should occur as the result of transcendental #
  8549. # emulation in the 060FPLSP. Create an underflow by using "fmul" #
  8550. # and two very small numbers of appropriate sign so the operating #
  8551. # system can log the event. #
  8552. # #
  8553. #########################################################################
  8554. global t_unfl
  8555. t_unfl:
  8556. tst.b SRC_EX(%a0)
  8557. bpl.b unf_pos
  8558. global t_unfl2
  8559. t_unfl2:
  8560. ori.l &unfinx_mask+neg_mask,USER_FPSR(%a6) # set N/UNFL/INEX2/AUNFL/AINEX
  8561. fmov.l USER_FPCR(%a6),%fpcr
  8562. fmovm.x mns_tiny(%pc),&0x80
  8563. fmul.x pls_tiny(%pc),%fp0
  8564. fmov.l %fpsr,%d0
  8565. rol.l &0x8,%d0
  8566. mov.b %d0,FPSR_CC(%a6)
  8567. rts
  8568. unf_pos:
  8569. ori.w &unfinx_mask,FPSR_EXCEPT(%a6) # set UNFL/INEX2/AUNFL/AINEX
  8570. fmov.l USER_FPCR(%a6),%fpcr
  8571. fmovm.x pls_tiny(%pc),&0x80
  8572. fmul.x %fp0,%fp0
  8573. fmov.l %fpsr,%d0
  8574. rol.l &0x8,%d0
  8575. mov.b %d0,FPSR_CC(%a6)
  8576. rts
  8577. #########################################################################
  8578. # XDEF **************************************************************** #
  8579. # t_ovfl(): Handle 060FPLSP overflow exception during emulation. #
  8580. # (monadic) #
  8581. # t_ovfl2(): Handle 060FPLSP overflow exception during #
  8582. # emulation. result always positive. (dyadic) #
  8583. # t_ovfl_sc(): Handle 060FPLSP overflow exception during #
  8584. # emulation for "fscale". #
  8585. # #
  8586. # This routine is used by the 060FPLSP package. #
  8587. # #
  8588. # XREF **************************************************************** #
  8589. # None. #
  8590. # #
  8591. # INPUT *************************************************************** #
  8592. # a0 = pointer to extended precision source operand #
  8593. # #
  8594. # OUTPUT ************************************************************** #
  8595. # fp0 = default underflow result #
  8596. # #
  8597. # ALGORITHM *********************************************************** #
  8598. # An overflow should occur as the result of transcendental #
  8599. # emulation in the 060FPLSP. Create an overflow by using "fmul" #
  8600. # and two very lareg numbers of appropriate sign so the operating #
  8601. # system can log the event. #
  8602. # For t_ovfl_sc() we take special care not to lose the INEX2 bit. #
  8603. # #
  8604. #########################################################################
  8605. global t_ovfl_sc
  8606. t_ovfl_sc:
  8607. ori.l &ovfl_inx_mask,USER_FPSR(%a6) # set OVFL/AOVFL/AINEX
  8608. mov.b %d0,%d1 # fetch rnd prec,mode
  8609. andi.b &0xc0,%d1 # extract prec
  8610. beq.w ovfl_work
  8611. # dst op is a DENORM. we have to normalize the mantissa to see if the
  8612. # result would be inexact for the given precision. make a copy of the
  8613. # dst so we don't screw up the version passed to us.
  8614. mov.w LOCAL_EX(%a0),FP_SCR0_EX(%a6)
  8615. mov.l LOCAL_HI(%a0),FP_SCR0_HI(%a6)
  8616. mov.l LOCAL_LO(%a0),FP_SCR0_LO(%a6)
  8617. lea FP_SCR0(%a6),%a0 # pass ptr to FP_SCR0
  8618. movm.l &0xc080,-(%sp) # save d0-d1/a0
  8619. bsr.l norm # normalize mantissa
  8620. movm.l (%sp)+,&0x0103 # restore d0-d1/a0
  8621. cmpi.b %d1,&0x40 # is precision sgl?
  8622. bne.b ovfl_sc_dbl # no; dbl
  8623. ovfl_sc_sgl:
  8624. tst.l LOCAL_LO(%a0) # is lo lw of sgl set?
  8625. bne.b ovfl_sc_inx # yes
  8626. tst.b 3+LOCAL_HI(%a0) # is lo byte of hi lw set?
  8627. bne.b ovfl_sc_inx # yes
  8628. bra.w ovfl_work # don't set INEX2
  8629. ovfl_sc_dbl:
  8630. mov.l LOCAL_LO(%a0),%d1 # are any of lo 11 bits of
  8631. andi.l &0x7ff,%d1 # dbl mantissa set?
  8632. beq.w ovfl_work # no; don't set INEX2
  8633. ovfl_sc_inx:
  8634. ori.l &inex2_mask,USER_FPSR(%a6) # set INEX2
  8635. bra.b ovfl_work # continue
  8636. global t_ovfl
  8637. t_ovfl:
  8638. ori.w &ovfinx_mask,FPSR_EXCEPT(%a6) # set OVFL/INEX2/AOVFL/AINEX
  8639. ovfl_work:
  8640. tst.b SRC_EX(%a0)
  8641. bpl.b ovfl_p
  8642. ovfl_m:
  8643. fmov.l USER_FPCR(%a6),%fpcr
  8644. fmovm.x mns_huge(%pc),&0x80
  8645. fmul.x pls_huge(%pc),%fp0
  8646. fmov.l %fpsr,%d0
  8647. rol.l &0x8,%d0
  8648. ori.b &neg_mask,%d0
  8649. mov.b %d0,FPSR_CC(%a6)
  8650. rts
  8651. ovfl_p:
  8652. fmov.l USER_FPCR(%a6),%fpcr
  8653. fmovm.x pls_huge(%pc),&0x80
  8654. fmul.x pls_huge(%pc),%fp0
  8655. fmov.l %fpsr,%d0
  8656. rol.l &0x8,%d0
  8657. mov.b %d0,FPSR_CC(%a6)
  8658. rts
  8659. global t_ovfl2
  8660. t_ovfl2:
  8661. ori.w &ovfinx_mask,FPSR_EXCEPT(%a6) # set OVFL/INEX2/AOVFL/AINEX
  8662. fmov.l USER_FPCR(%a6),%fpcr
  8663. fmovm.x pls_huge(%pc),&0x80
  8664. fmul.x pls_huge(%pc),%fp0
  8665. fmov.l %fpsr,%d0
  8666. rol.l &0x8,%d0
  8667. mov.b %d0,FPSR_CC(%a6)
  8668. rts
  8669. #########################################################################
  8670. # XDEF **************************************************************** #
  8671. # t_catch(): Handle 060FPLSP OVFL,UNFL,or INEX2 exception during #
  8672. # emulation. #
  8673. # t_catch2(): Handle 060FPLSP OVFL,UNFL,or INEX2 exception during #
  8674. # emulation. #
  8675. # #
  8676. # These routines are used by the 060FPLSP package. #
  8677. # #
  8678. # XREF **************************************************************** #
  8679. # None. #
  8680. # #
  8681. # INPUT *************************************************************** #
  8682. # fp0 = default underflow or overflow result #
  8683. # #
  8684. # OUTPUT ************************************************************** #
  8685. # fp0 = default result #
  8686. # #
  8687. # ALGORITHM *********************************************************** #
  8688. # If an overflow or underflow occurred during the last #
  8689. # instruction of transcendental 060FPLSP emulation, then it has already #
  8690. # occurred and has been logged. Now we need to see if an inexact #
  8691. # exception should occur. #
  8692. # #
  8693. #########################################################################
  8694. global t_catch2
  8695. t_catch2:
  8696. fmov.l %fpsr,%d0
  8697. or.l %d0,USER_FPSR(%a6)
  8698. bra.b inx2_work
  8699. global t_catch
  8700. t_catch:
  8701. fmov.l %fpsr,%d0
  8702. or.l %d0,USER_FPSR(%a6)
  8703. #########################################################################
  8704. # XDEF **************************************************************** #
  8705. # t_inx2(): Handle inexact 060FPLSP exception during emulation. #
  8706. # t_pinx2(): Handle inexact 060FPLSP exception for "+" results. #
  8707. # t_minx2(): Handle inexact 060FPLSP exception for "-" results. #
  8708. # #
  8709. # XREF **************************************************************** #
  8710. # None. #
  8711. # #
  8712. # INPUT *************************************************************** #
  8713. # fp0 = default result #
  8714. # #
  8715. # OUTPUT ************************************************************** #
  8716. # fp0 = default result #
  8717. # #
  8718. # ALGORITHM *********************************************************** #
  8719. # The last instruction of transcendental emulation for the #
  8720. # 060FPLSP should be inexact. So, if inexact is enabled, then we create #
  8721. # the event here by adding a large and very small number together #
  8722. # so that the operating system can log the event. #
  8723. # Must check, too, if the result was zero, in which case we just #
  8724. # set the FPSR bits and return. #
  8725. # #
  8726. #########################################################################
  8727. global t_inx2
  8728. t_inx2:
  8729. fblt.w t_minx2
  8730. fbeq.w inx2_zero
  8731. global t_pinx2
  8732. t_pinx2:
  8733. ori.w &inx2a_mask,FPSR_EXCEPT(%a6) # set INEX2/AINEX
  8734. bra.b inx2_work
  8735. global t_minx2
  8736. t_minx2:
  8737. ori.l &inx2a_mask+neg_mask,USER_FPSR(%a6)
  8738. inx2_work:
  8739. btst &inex2_bit,FPCR_ENABLE(%a6) # is inexact enabled?
  8740. bne.b inx2_work_ena # yes
  8741. rts
  8742. inx2_work_ena:
  8743. fmov.l USER_FPCR(%a6),%fpcr # insert user's exceptions
  8744. fmov.s &0x3f800000,%fp1 # load +1
  8745. fadd.x pls_tiny(%pc),%fp1 # cause exception
  8746. rts
  8747. inx2_zero:
  8748. mov.b &z_bmask,FPSR_CC(%a6)
  8749. ori.w &inx2a_mask,2+USER_FPSR(%a6) # set INEX/AINEX
  8750. rts
  8751. #########################################################################
  8752. # XDEF **************************************************************** #
  8753. # t_extdnrm(): Handle DENORM inputs in 060FPLSP. #
  8754. # t_resdnrm(): Handle DENORM inputs in 060FPLSP for "fscale". #
  8755. # #
  8756. # This routine is used by the 060FPLSP package. #
  8757. # #
  8758. # XREF **************************************************************** #
  8759. # None. #
  8760. # #
  8761. # INPUT *************************************************************** #
  8762. # a0 = pointer to extended precision input operand #
  8763. # #
  8764. # OUTPUT ************************************************************** #
  8765. # fp0 = default result #
  8766. # #
  8767. # ALGORITHM *********************************************************** #
  8768. # For all functions that have a denormalized input and that #
  8769. # f(x)=x, this is the entry point. #
  8770. # DENORM value is moved using "fmove" which triggers an exception #
  8771. # if enabled so the operating system can log the event. #
  8772. # #
  8773. #########################################################################
  8774. global t_extdnrm
  8775. t_extdnrm:
  8776. fmov.l USER_FPCR(%a6),%fpcr
  8777. fmov.x SRC_EX(%a0),%fp0
  8778. fmov.l %fpsr,%d0
  8779. ori.l &unfinx_mask,%d0
  8780. or.l %d0,USER_FPSR(%a6)
  8781. rts
  8782. global t_resdnrm
  8783. t_resdnrm:
  8784. fmov.l USER_FPCR(%a6),%fpcr
  8785. fmov.x SRC_EX(%a0),%fp0
  8786. fmov.l %fpsr,%d0
  8787. or.l %d0,USER_FPSR(%a6)
  8788. rts
  8789. ##########################################
  8790. #
  8791. # sto_cos:
  8792. # This is used by fsincos library emulation. The correct
  8793. # values are already in fp0 and fp1 so we do nothing here.
  8794. #
  8795. global sto_cos
  8796. sto_cos:
  8797. rts
  8798. ##########################################
  8799. #
  8800. # dst_qnan --- force result when destination is a NaN
  8801. #
  8802. global dst_qnan
  8803. dst_qnan:
  8804. fmov.x DST(%a1),%fp0
  8805. tst.b DST_EX(%a1)
  8806. bmi.b dst_qnan_m
  8807. dst_qnan_p:
  8808. mov.b &nan_bmask,FPSR_CC(%a6)
  8809. rts
  8810. dst_qnan_m:
  8811. mov.b &nan_bmask+neg_bmask,FPSR_CC(%a6)
  8812. rts
  8813. #
  8814. # src_qnan --- force result when source is a NaN
  8815. #
  8816. global src_qnan
  8817. src_qnan:
  8818. fmov.x SRC(%a0),%fp0
  8819. tst.b SRC_EX(%a0)
  8820. bmi.b src_qnan_m
  8821. src_qnan_p:
  8822. mov.b &nan_bmask,FPSR_CC(%a6)
  8823. rts
  8824. src_qnan_m:
  8825. mov.b &nan_bmask+neg_bmask,FPSR_CC(%a6)
  8826. rts
  8827. ##########################################
  8828. #
  8829. # Native instruction support
  8830. #
  8831. # Some systems may need entry points even for 68060 native
  8832. # instructions. These routines are provided for
  8833. # convenience.
  8834. #
  8835. global _fadds_
  8836. _fadds_:
  8837. fmov.l %fpcr,-(%sp) # save fpcr
  8838. fmov.l &0x00000000,%fpcr # clear fpcr for load
  8839. fmov.s 0x8(%sp),%fp0 # load sgl dst
  8840. fmov.l (%sp)+,%fpcr # restore fpcr
  8841. fadd.s 0x8(%sp),%fp0 # fadd w/ sgl src
  8842. rts
  8843. global _faddd_
  8844. _faddd_:
  8845. fmov.l %fpcr,-(%sp) # save fpcr
  8846. fmov.l &0x00000000,%fpcr # clear fpcr for load
  8847. fmov.d 0x8(%sp),%fp0 # load dbl dst
  8848. fmov.l (%sp)+,%fpcr # restore fpcr
  8849. fadd.d 0xc(%sp),%fp0 # fadd w/ dbl src
  8850. rts
  8851. global _faddx_
  8852. _faddx_:
  8853. fmovm.x 0x4(%sp),&0x80 # load ext dst
  8854. fadd.x 0x10(%sp),%fp0 # fadd w/ ext src
  8855. rts
  8856. global _fsubs_
  8857. _fsubs_:
  8858. fmov.l %fpcr,-(%sp) # save fpcr
  8859. fmov.l &0x00000000,%fpcr # clear fpcr for load
  8860. fmov.s 0x8(%sp),%fp0 # load sgl dst
  8861. fmov.l (%sp)+,%fpcr # restore fpcr
  8862. fsub.s 0x8(%sp),%fp0 # fsub w/ sgl src
  8863. rts
  8864. global _fsubd_
  8865. _fsubd_:
  8866. fmov.l %fpcr,-(%sp) # save fpcr
  8867. fmov.l &0x00000000,%fpcr # clear fpcr for load
  8868. fmov.d 0x8(%sp),%fp0 # load dbl dst
  8869. fmov.l (%sp)+,%fpcr # restore fpcr
  8870. fsub.d 0xc(%sp),%fp0 # fsub w/ dbl src
  8871. rts
  8872. global _fsubx_
  8873. _fsubx_:
  8874. fmovm.x 0x4(%sp),&0x80 # load ext dst
  8875. fsub.x 0x10(%sp),%fp0 # fsub w/ ext src
  8876. rts
  8877. global _fmuls_
  8878. _fmuls_:
  8879. fmov.l %fpcr,-(%sp) # save fpcr
  8880. fmov.l &0x00000000,%fpcr # clear fpcr for load
  8881. fmov.s 0x8(%sp),%fp0 # load sgl dst
  8882. fmov.l (%sp)+,%fpcr # restore fpcr
  8883. fmul.s 0x8(%sp),%fp0 # fmul w/ sgl src
  8884. rts
  8885. global _fmuld_
  8886. _fmuld_:
  8887. fmov.l %fpcr,-(%sp) # save fpcr
  8888. fmov.l &0x00000000,%fpcr # clear fpcr for load
  8889. fmov.d 0x8(%sp),%fp0 # load dbl dst
  8890. fmov.l (%sp)+,%fpcr # restore fpcr
  8891. fmul.d 0xc(%sp),%fp0 # fmul w/ dbl src
  8892. rts
  8893. global _fmulx_
  8894. _fmulx_:
  8895. fmovm.x 0x4(%sp),&0x80 # load ext dst
  8896. fmul.x 0x10(%sp),%fp0 # fmul w/ ext src
  8897. rts
  8898. global _fdivs_
  8899. _fdivs_:
  8900. fmov.l %fpcr,-(%sp) # save fpcr
  8901. fmov.l &0x00000000,%fpcr # clear fpcr for load
  8902. fmov.s 0x8(%sp),%fp0 # load sgl dst
  8903. fmov.l (%sp)+,%fpcr # restore fpcr
  8904. fdiv.s 0x8(%sp),%fp0 # fdiv w/ sgl src
  8905. rts
  8906. global _fdivd_
  8907. _fdivd_:
  8908. fmov.l %fpcr,-(%sp) # save fpcr
  8909. fmov.l &0x00000000,%fpcr # clear fpcr for load
  8910. fmov.d 0x8(%sp),%fp0 # load dbl dst
  8911. fmov.l (%sp)+,%fpcr # restore fpcr
  8912. fdiv.d 0xc(%sp),%fp0 # fdiv w/ dbl src
  8913. rts
  8914. global _fdivx_
  8915. _fdivx_:
  8916. fmovm.x 0x4(%sp),&0x80 # load ext dst
  8917. fdiv.x 0x10(%sp),%fp0 # fdiv w/ ext src
  8918. rts
  8919. global _fabss_
  8920. _fabss_:
  8921. fabs.s 0x4(%sp),%fp0 # fabs w/ sgl src
  8922. rts
  8923. global _fabsd_
  8924. _fabsd_:
  8925. fabs.d 0x4(%sp),%fp0 # fabs w/ dbl src
  8926. rts
  8927. global _fabsx_
  8928. _fabsx_:
  8929. fabs.x 0x4(%sp),%fp0 # fabs w/ ext src
  8930. rts
  8931. global _fnegs_
  8932. _fnegs_:
  8933. fneg.s 0x4(%sp),%fp0 # fneg w/ sgl src
  8934. rts
  8935. global _fnegd_
  8936. _fnegd_:
  8937. fneg.d 0x4(%sp),%fp0 # fneg w/ dbl src
  8938. rts
  8939. global _fnegx_
  8940. _fnegx_:
  8941. fneg.x 0x4(%sp),%fp0 # fneg w/ ext src
  8942. rts
  8943. global _fsqrts_
  8944. _fsqrts_:
  8945. fsqrt.s 0x4(%sp),%fp0 # fsqrt w/ sgl src
  8946. rts
  8947. global _fsqrtd_
  8948. _fsqrtd_:
  8949. fsqrt.d 0x4(%sp),%fp0 # fsqrt w/ dbl src
  8950. rts
  8951. global _fsqrtx_
  8952. _fsqrtx_:
  8953. fsqrt.x 0x4(%sp),%fp0 # fsqrt w/ ext src
  8954. rts
  8955. global _fints_
  8956. _fints_:
  8957. fint.s 0x4(%sp),%fp0 # fint w/ sgl src
  8958. rts
  8959. global _fintd_
  8960. _fintd_:
  8961. fint.d 0x4(%sp),%fp0 # fint w/ dbl src
  8962. rts
  8963. global _fintx_
  8964. _fintx_:
  8965. fint.x 0x4(%sp),%fp0 # fint w/ ext src
  8966. rts
  8967. global _fintrzs_
  8968. _fintrzs_:
  8969. fintrz.s 0x4(%sp),%fp0 # fintrz w/ sgl src
  8970. rts
  8971. global _fintrzd_
  8972. _fintrzd_:
  8973. fintrz.d 0x4(%sp),%fp0 # fintrx w/ dbl src
  8974. rts
  8975. global _fintrzx_
  8976. _fintrzx_:
  8977. fintrz.x 0x4(%sp),%fp0 # fintrz w/ ext src
  8978. rts
  8979. ########################################################################
  8980. #########################################################################
  8981. # src_zero(): Return signed zero according to sign of src operand. #
  8982. #########################################################################
  8983. global src_zero
  8984. src_zero:
  8985. tst.b SRC_EX(%a0) # get sign of src operand
  8986. bmi.b ld_mzero # if neg, load neg zero
  8987. #
  8988. # ld_pzero(): return a positive zero.
  8989. #
  8990. global ld_pzero
  8991. ld_pzero:
  8992. fmov.s &0x00000000,%fp0 # load +0
  8993. mov.b &z_bmask,FPSR_CC(%a6) # set 'Z' ccode bit
  8994. rts
  8995. # ld_mzero(): return a negative zero.
  8996. global ld_mzero
  8997. ld_mzero:
  8998. fmov.s &0x80000000,%fp0 # load -0
  8999. mov.b &neg_bmask+z_bmask,FPSR_CC(%a6) # set 'N','Z' ccode bits
  9000. rts
  9001. #########################################################################
  9002. # dst_zero(): Return signed zero according to sign of dst operand. #
  9003. #########################################################################
  9004. global dst_zero
  9005. dst_zero:
  9006. tst.b DST_EX(%a1) # get sign of dst operand
  9007. bmi.b ld_mzero # if neg, load neg zero
  9008. bra.b ld_pzero # load positive zero
  9009. #########################################################################
  9010. # src_inf(): Return signed inf according to sign of src operand. #
  9011. #########################################################################
  9012. global src_inf
  9013. src_inf:
  9014. tst.b SRC_EX(%a0) # get sign of src operand
  9015. bmi.b ld_minf # if negative branch
  9016. #
  9017. # ld_pinf(): return a positive infinity.
  9018. #
  9019. global ld_pinf
  9020. ld_pinf:
  9021. fmov.s &0x7f800000,%fp0 # load +INF
  9022. mov.b &inf_bmask,FPSR_CC(%a6) # set 'INF' ccode bit
  9023. rts
  9024. #
  9025. # ld_minf():return a negative infinity.
  9026. #
  9027. global ld_minf
  9028. ld_minf:
  9029. fmov.s &0xff800000,%fp0 # load -INF
  9030. mov.b &neg_bmask+inf_bmask,FPSR_CC(%a6) # set 'N','I' ccode bits
  9031. rts
  9032. #########################################################################
  9033. # dst_inf(): Return signed inf according to sign of dst operand. #
  9034. #########################################################################
  9035. global dst_inf
  9036. dst_inf:
  9037. tst.b DST_EX(%a1) # get sign of dst operand
  9038. bmi.b ld_minf # if negative branch
  9039. bra.b ld_pinf
  9040. global szr_inf
  9041. #################################################################
  9042. # szr_inf(): Return +ZERO for a negative src operand or #
  9043. # +INF for a positive src operand. #
  9044. # Routine used for fetox, ftwotox, and ftentox. #
  9045. #################################################################
  9046. szr_inf:
  9047. tst.b SRC_EX(%a0) # check sign of source
  9048. bmi.b ld_pzero
  9049. bra.b ld_pinf
  9050. #########################################################################
  9051. # sopr_inf(): Return +INF for a positive src operand or #
  9052. # jump to operand error routine for a negative src operand. #
  9053. # Routine used for flogn, flognp1, flog10, and flog2. #
  9054. #########################################################################
  9055. global sopr_inf
  9056. sopr_inf:
  9057. tst.b SRC_EX(%a0) # check sign of source
  9058. bmi.w t_operr
  9059. bra.b ld_pinf
  9060. #################################################################
  9061. # setoxm1i(): Return minus one for a negative src operand or #
  9062. # positive infinity for a positive src operand. #
  9063. # Routine used for fetoxm1. #
  9064. #################################################################
  9065. global setoxm1i
  9066. setoxm1i:
  9067. tst.b SRC_EX(%a0) # check sign of source
  9068. bmi.b ld_mone
  9069. bra.b ld_pinf
  9070. #########################################################################
  9071. # src_one(): Return signed one according to sign of src operand. #
  9072. #########################################################################
  9073. global src_one
  9074. src_one:
  9075. tst.b SRC_EX(%a0) # check sign of source
  9076. bmi.b ld_mone
  9077. #
  9078. # ld_pone(): return positive one.
  9079. #
  9080. global ld_pone
  9081. ld_pone:
  9082. fmov.s &0x3f800000,%fp0 # load +1
  9083. clr.b FPSR_CC(%a6)
  9084. rts
  9085. #
  9086. # ld_mone(): return negative one.
  9087. #
  9088. global ld_mone
  9089. ld_mone:
  9090. fmov.s &0xbf800000,%fp0 # load -1
  9091. mov.b &neg_bmask,FPSR_CC(%a6) # set 'N' ccode bit
  9092. rts
  9093. ppiby2: long 0x3fff0000, 0xc90fdaa2, 0x2168c235
  9094. mpiby2: long 0xbfff0000, 0xc90fdaa2, 0x2168c235
  9095. #################################################################
  9096. # spi_2(): Return signed PI/2 according to sign of src operand. #
  9097. #################################################################
  9098. global spi_2
  9099. spi_2:
  9100. tst.b SRC_EX(%a0) # check sign of source
  9101. bmi.b ld_mpi2
  9102. #
  9103. # ld_ppi2(): return positive PI/2.
  9104. #
  9105. global ld_ppi2
  9106. ld_ppi2:
  9107. fmov.l %d0,%fpcr
  9108. fmov.x ppiby2(%pc),%fp0 # load +pi/2
  9109. bra.w t_pinx2 # set INEX2
  9110. #
  9111. # ld_mpi2(): return negative PI/2.
  9112. #
  9113. global ld_mpi2
  9114. ld_mpi2:
  9115. fmov.l %d0,%fpcr
  9116. fmov.x mpiby2(%pc),%fp0 # load -pi/2
  9117. bra.w t_minx2 # set INEX2
  9118. ####################################################
  9119. # The following routines give support for fsincos. #
  9120. ####################################################
  9121. #
  9122. # ssincosz(): When the src operand is ZERO, store a one in the
  9123. # cosine register and return a ZERO in fp0 w/ the same sign
  9124. # as the src operand.
  9125. #
  9126. global ssincosz
  9127. ssincosz:
  9128. fmov.s &0x3f800000,%fp1
  9129. tst.b SRC_EX(%a0) # test sign
  9130. bpl.b sincoszp
  9131. fmov.s &0x80000000,%fp0 # return sin result in fp0
  9132. mov.b &z_bmask+neg_bmask,FPSR_CC(%a6)
  9133. rts
  9134. sincoszp:
  9135. fmov.s &0x00000000,%fp0 # return sin result in fp0
  9136. mov.b &z_bmask,FPSR_CC(%a6)
  9137. rts
  9138. #
  9139. # ssincosi(): When the src operand is INF, store a QNAN in the cosine
  9140. # register and jump to the operand error routine for negative
  9141. # src operands.
  9142. #
  9143. global ssincosi
  9144. ssincosi:
  9145. fmov.x qnan(%pc),%fp1 # load NAN
  9146. bra.w t_operr
  9147. #
  9148. # ssincosqnan(): When the src operand is a QNAN, store the QNAN in the cosine
  9149. # register and branch to the src QNAN routine.
  9150. #
  9151. global ssincosqnan
  9152. ssincosqnan:
  9153. fmov.x LOCAL_EX(%a0),%fp1
  9154. bra.w src_qnan
  9155. ########################################################################
  9156. global smod_sdnrm
  9157. global smod_snorm
  9158. smod_sdnrm:
  9159. smod_snorm:
  9160. mov.b DTAG(%a6),%d1
  9161. beq.l smod
  9162. cmpi.b %d1,&ZERO
  9163. beq.w smod_zro
  9164. cmpi.b %d1,&INF
  9165. beq.l t_operr
  9166. cmpi.b %d1,&DENORM
  9167. beq.l smod
  9168. bra.l dst_qnan
  9169. global smod_szero
  9170. smod_szero:
  9171. mov.b DTAG(%a6),%d1
  9172. beq.l t_operr
  9173. cmpi.b %d1,&ZERO
  9174. beq.l t_operr
  9175. cmpi.b %d1,&INF
  9176. beq.l t_operr
  9177. cmpi.b %d1,&DENORM
  9178. beq.l t_operr
  9179. bra.l dst_qnan
  9180. global smod_sinf
  9181. smod_sinf:
  9182. mov.b DTAG(%a6),%d1
  9183. beq.l smod_fpn
  9184. cmpi.b %d1,&ZERO
  9185. beq.l smod_zro
  9186. cmpi.b %d1,&INF
  9187. beq.l t_operr
  9188. cmpi.b %d1,&DENORM
  9189. beq.l smod_fpn
  9190. bra.l dst_qnan
  9191. smod_zro:
  9192. srem_zro:
  9193. mov.b SRC_EX(%a0),%d1 # get src sign
  9194. mov.b DST_EX(%a1),%d0 # get dst sign
  9195. eor.b %d0,%d1 # get qbyte sign
  9196. andi.b &0x80,%d1
  9197. mov.b %d1,FPSR_QBYTE(%a6)
  9198. tst.b %d0
  9199. bpl.w ld_pzero
  9200. bra.w ld_mzero
  9201. smod_fpn:
  9202. srem_fpn:
  9203. clr.b FPSR_QBYTE(%a6)
  9204. mov.l %d0,-(%sp)
  9205. mov.b SRC_EX(%a0),%d1 # get src sign
  9206. mov.b DST_EX(%a1),%d0 # get dst sign
  9207. eor.b %d0,%d1 # get qbyte sign
  9208. andi.b &0x80,%d1
  9209. mov.b %d1,FPSR_QBYTE(%a6)
  9210. cmpi.b DTAG(%a6),&DENORM
  9211. bne.b smod_nrm
  9212. lea DST(%a1),%a0
  9213. mov.l (%sp)+,%d0
  9214. bra t_resdnrm
  9215. smod_nrm:
  9216. fmov.l (%sp)+,%fpcr
  9217. fmov.x DST(%a1),%fp0
  9218. tst.b DST_EX(%a1)
  9219. bmi.b smod_nrm_neg
  9220. rts
  9221. smod_nrm_neg:
  9222. mov.b &neg_bmask,FPSR_CC(%a6) # set 'N' code
  9223. rts
  9224. #########################################################################
  9225. global srem_snorm
  9226. global srem_sdnrm
  9227. srem_sdnrm:
  9228. srem_snorm:
  9229. mov.b DTAG(%a6),%d1
  9230. beq.l srem
  9231. cmpi.b %d1,&ZERO
  9232. beq.w srem_zro
  9233. cmpi.b %d1,&INF
  9234. beq.l t_operr
  9235. cmpi.b %d1,&DENORM
  9236. beq.l srem
  9237. bra.l dst_qnan
  9238. global srem_szero
  9239. srem_szero:
  9240. mov.b DTAG(%a6),%d1
  9241. beq.l t_operr
  9242. cmpi.b %d1,&ZERO
  9243. beq.l t_operr
  9244. cmpi.b %d1,&INF
  9245. beq.l t_operr
  9246. cmpi.b %d1,&DENORM
  9247. beq.l t_operr
  9248. bra.l dst_qnan
  9249. global srem_sinf
  9250. srem_sinf:
  9251. mov.b DTAG(%a6),%d1
  9252. beq.w srem_fpn
  9253. cmpi.b %d1,&ZERO
  9254. beq.w srem_zro
  9255. cmpi.b %d1,&INF
  9256. beq.l t_operr
  9257. cmpi.b %d1,&DENORM
  9258. beq.l srem_fpn
  9259. bra.l dst_qnan
  9260. #########################################################################
  9261. global sscale_snorm
  9262. global sscale_sdnrm
  9263. sscale_snorm:
  9264. sscale_sdnrm:
  9265. mov.b DTAG(%a6),%d1
  9266. beq.l sscale
  9267. cmpi.b %d1,&ZERO
  9268. beq.l dst_zero
  9269. cmpi.b %d1,&INF
  9270. beq.l dst_inf
  9271. cmpi.b %d1,&DENORM
  9272. beq.l sscale
  9273. bra.l dst_qnan
  9274. global sscale_szero
  9275. sscale_szero:
  9276. mov.b DTAG(%a6),%d1
  9277. beq.l sscale
  9278. cmpi.b %d1,&ZERO
  9279. beq.l dst_zero
  9280. cmpi.b %d1,&INF
  9281. beq.l dst_inf
  9282. cmpi.b %d1,&DENORM
  9283. beq.l sscale
  9284. bra.l dst_qnan
  9285. global sscale_sinf
  9286. sscale_sinf:
  9287. mov.b DTAG(%a6),%d1
  9288. beq.l t_operr
  9289. cmpi.b %d1,&QNAN
  9290. beq.l dst_qnan
  9291. bra.l t_operr
  9292. ########################################################################
  9293. global sop_sqnan
  9294. sop_sqnan:
  9295. mov.b DTAG(%a6),%d1
  9296. cmpi.b %d1,&QNAN
  9297. beq.l dst_qnan
  9298. bra.l src_qnan
  9299. #########################################################################
  9300. # norm(): normalize the mantissa of an extended precision input. the #
  9301. # input operand should not be normalized already. #
  9302. # #
  9303. # XDEF **************************************************************** #
  9304. # norm() #
  9305. # #
  9306. # XREF **************************************************************** #
  9307. # none #
  9308. # #
  9309. # INPUT *************************************************************** #
  9310. # a0 = pointer fp extended precision operand to normalize #
  9311. # #
  9312. # OUTPUT ************************************************************** #
  9313. # d0 = number of bit positions the mantissa was shifted #
  9314. # a0 = the input operand's mantissa is normalized; the exponent #
  9315. # is unchanged. #
  9316. # #
  9317. #########################################################################
  9318. global norm
  9319. norm:
  9320. mov.l %d2, -(%sp) # create some temp regs
  9321. mov.l %d3, -(%sp)
  9322. mov.l FTEMP_HI(%a0), %d0 # load hi(mantissa)
  9323. mov.l FTEMP_LO(%a0), %d1 # load lo(mantissa)
  9324. bfffo %d0{&0:&32}, %d2 # how many places to shift?
  9325. beq.b norm_lo # hi(man) is all zeroes!
  9326. norm_hi:
  9327. lsl.l %d2, %d0 # left shift hi(man)
  9328. bfextu %d1{&0:%d2}, %d3 # extract lo bits
  9329. or.l %d3, %d0 # create hi(man)
  9330. lsl.l %d2, %d1 # create lo(man)
  9331. mov.l %d0, FTEMP_HI(%a0) # store new hi(man)
  9332. mov.l %d1, FTEMP_LO(%a0) # store new lo(man)
  9333. mov.l %d2, %d0 # return shift amount
  9334. mov.l (%sp)+, %d3 # restore temp regs
  9335. mov.l (%sp)+, %d2
  9336. rts
  9337. norm_lo:
  9338. bfffo %d1{&0:&32}, %d2 # how many places to shift?
  9339. lsl.l %d2, %d1 # shift lo(man)
  9340. add.l &32, %d2 # add 32 to shft amount
  9341. mov.l %d1, FTEMP_HI(%a0) # store hi(man)
  9342. clr.l FTEMP_LO(%a0) # lo(man) is now zero
  9343. mov.l %d2, %d0 # return shift amount
  9344. mov.l (%sp)+, %d3 # restore temp regs
  9345. mov.l (%sp)+, %d2
  9346. rts
  9347. #########################################################################
  9348. # unnorm_fix(): - changes an UNNORM to one of NORM, DENORM, or ZERO #
  9349. # - returns corresponding optype tag #
  9350. # #
  9351. # XDEF **************************************************************** #
  9352. # unnorm_fix() #
  9353. # #
  9354. # XREF **************************************************************** #
  9355. # norm() - normalize the mantissa #
  9356. # #
  9357. # INPUT *************************************************************** #
  9358. # a0 = pointer to unnormalized extended precision number #
  9359. # #
  9360. # OUTPUT ************************************************************** #
  9361. # d0 = optype tag - is corrected to one of NORM, DENORM, or ZERO #
  9362. # a0 = input operand has been converted to a norm, denorm, or #
  9363. # zero; both the exponent and mantissa are changed. #
  9364. # #
  9365. #########################################################################
  9366. global unnorm_fix
  9367. unnorm_fix:
  9368. bfffo FTEMP_HI(%a0){&0:&32}, %d0 # how many shifts are needed?
  9369. bne.b unnorm_shift # hi(man) is not all zeroes
  9370. #
  9371. # hi(man) is all zeroes so see if any bits in lo(man) are set
  9372. #
  9373. unnorm_chk_lo:
  9374. bfffo FTEMP_LO(%a0){&0:&32}, %d0 # is operand really a zero?
  9375. beq.w unnorm_zero # yes
  9376. add.w &32, %d0 # no; fix shift distance
  9377. #
  9378. # d0 = # shifts needed for complete normalization
  9379. #
  9380. unnorm_shift:
  9381. clr.l %d1 # clear top word
  9382. mov.w FTEMP_EX(%a0), %d1 # extract exponent
  9383. and.w &0x7fff, %d1 # strip off sgn
  9384. cmp.w %d0, %d1 # will denorm push exp < 0?
  9385. bgt.b unnorm_nrm_zero # yes; denorm only until exp = 0
  9386. #
  9387. # exponent would not go < 0. therefore, number stays normalized
  9388. #
  9389. sub.w %d0, %d1 # shift exponent value
  9390. mov.w FTEMP_EX(%a0), %d0 # load old exponent
  9391. and.w &0x8000, %d0 # save old sign
  9392. or.w %d0, %d1 # {sgn,new exp}
  9393. mov.w %d1, FTEMP_EX(%a0) # insert new exponent
  9394. bsr.l norm # normalize UNNORM
  9395. mov.b &NORM, %d0 # return new optype tag
  9396. rts
  9397. #
  9398. # exponent would go < 0, so only denormalize until exp = 0
  9399. #
  9400. unnorm_nrm_zero:
  9401. cmp.b %d1, &32 # is exp <= 32?
  9402. bgt.b unnorm_nrm_zero_lrg # no; go handle large exponent
  9403. bfextu FTEMP_HI(%a0){%d1:&32}, %d0 # extract new hi(man)
  9404. mov.l %d0, FTEMP_HI(%a0) # save new hi(man)
  9405. mov.l FTEMP_LO(%a0), %d0 # fetch old lo(man)
  9406. lsl.l %d1, %d0 # extract new lo(man)
  9407. mov.l %d0, FTEMP_LO(%a0) # save new lo(man)
  9408. and.w &0x8000, FTEMP_EX(%a0) # set exp = 0
  9409. mov.b &DENORM, %d0 # return new optype tag
  9410. rts
  9411. #
  9412. # only mantissa bits set are in lo(man)
  9413. #
  9414. unnorm_nrm_zero_lrg:
  9415. sub.w &32, %d1 # adjust shft amt by 32
  9416. mov.l FTEMP_LO(%a0), %d0 # fetch old lo(man)
  9417. lsl.l %d1, %d0 # left shift lo(man)
  9418. mov.l %d0, FTEMP_HI(%a0) # store new hi(man)
  9419. clr.l FTEMP_LO(%a0) # lo(man) = 0
  9420. and.w &0x8000, FTEMP_EX(%a0) # set exp = 0
  9421. mov.b &DENORM, %d0 # return new optype tag
  9422. rts
  9423. #
  9424. # whole mantissa is zero so this UNNORM is actually a zero
  9425. #
  9426. unnorm_zero:
  9427. and.w &0x8000, FTEMP_EX(%a0) # force exponent to zero
  9428. mov.b &ZERO, %d0 # fix optype tag
  9429. rts