~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~1MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP2M68000 Hi-Performance Microprocessor Division3M68060 Software Package4Production Release P1.00 -- October 10, 199456M68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved.78THE SOFTWARE is provided on an "AS IS" basis and without warranty.9To the maximum extent permitted by applicable law,10MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,11INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE12and any warranty against infringement with regard to the SOFTWARE13(INCLUDING ANY MODIFIED VERSIONS THEREOF) and any accompanying written materials.1415To the maximum extent permitted by applicable law,16IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER17(INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS,18BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS)19ARISING OF THE USE OR INABILITY TO USE THE SOFTWARE.20Motorola assumes no responsibility for the maintenance and support of the SOFTWARE.2122You are hereby granted a copyright license to use, modify, and distribute the SOFTWARE23so long as this entire notice is retained without alteration in any modified and/or24redistributed versions, and that such modified versions are clearly identified as such.25No licenses are granted by implication, estoppel or otherwise under any patents26or trademarks of Motorola, Inc.27~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~28#29# lfptop.s:30# This file is appended to the top of the 060ILSP package31# and contains the entry points into the package. The user, in32# effect, branches to one of the branch table entries located here.33#3435bra.l _facoss_36short 0x000037bra.l _facosd_38short 0x000039bra.l _facosx_40short 0x00004142bra.l _fasins_43short 0x000044bra.l _fasind_45short 0x000046bra.l _fasinx_47short 0x00004849bra.l _fatans_50short 0x000051bra.l _fatand_52short 0x000053bra.l _fatanx_54short 0x00005556bra.l _fatanhs_57short 0x000058bra.l _fatanhd_59short 0x000060bra.l _fatanhx_61short 0x00006263bra.l _fcoss_64short 0x000065bra.l _fcosd_66short 0x000067bra.l _fcosx_68short 0x00006970bra.l _fcoshs_71short 0x000072bra.l _fcoshd_73short 0x000074bra.l _fcoshx_75short 0x00007677bra.l _fetoxs_78short 0x000079bra.l _fetoxd_80short 0x000081bra.l _fetoxx_82short 0x00008384bra.l _fetoxm1s_85short 0x000086bra.l _fetoxm1d_87short 0x000088bra.l _fetoxm1x_89short 0x00009091bra.l _fgetexps_92short 0x000093bra.l _fgetexpd_94short 0x000095bra.l _fgetexpx_96short 0x00009798bra.l _fgetmans_99short 0x0000100bra.l _fgetmand_101short 0x0000102bra.l _fgetmanx_103short 0x0000104105bra.l _flog10s_106short 0x0000107bra.l _flog10d_108short 0x0000109bra.l _flog10x_110short 0x0000111112bra.l _flog2s_113short 0x0000114bra.l _flog2d_115short 0x0000116bra.l _flog2x_117short 0x0000118119bra.l _flogns_120short 0x0000121bra.l _flognd_122short 0x0000123bra.l _flognx_124short 0x0000125126bra.l _flognp1s_127short 0x0000128bra.l _flognp1d_129short 0x0000130bra.l _flognp1x_131short 0x0000132133bra.l _fmods_134short 0x0000135bra.l _fmodd_136short 0x0000137bra.l _fmodx_138short 0x0000139140bra.l _frems_141short 0x0000142bra.l _fremd_143short 0x0000144bra.l _fremx_145short 0x0000146147bra.l _fscales_148short 0x0000149bra.l _fscaled_150short 0x0000151bra.l _fscalex_152short 0x0000153154bra.l _fsins_155short 0x0000156bra.l _fsind_157short 0x0000158bra.l _fsinx_159short 0x0000160161bra.l _fsincoss_162short 0x0000163bra.l _fsincosd_164short 0x0000165bra.l _fsincosx_166short 0x0000167168bra.l _fsinhs_169short 0x0000170bra.l _fsinhd_171short 0x0000172bra.l _fsinhx_173short 0x0000174175bra.l _ftans_176short 0x0000177bra.l _ftand_178short 0x0000179bra.l _ftanx_180short 0x0000181182bra.l _ftanhs_183short 0x0000184bra.l _ftanhd_185short 0x0000186bra.l _ftanhx_187short 0x0000188189bra.l _ftentoxs_190short 0x0000191bra.l _ftentoxd_192short 0x0000193bra.l _ftentoxx_194short 0x0000195196bra.l _ftwotoxs_197short 0x0000198bra.l _ftwotoxd_199short 0x0000200bra.l _ftwotoxx_201short 0x0000202203bra.l _fabss_204short 0x0000205bra.l _fabsd_206short 0x0000207bra.l _fabsx_208short 0x0000209210bra.l _fadds_211short 0x0000212bra.l _faddd_213short 0x0000214bra.l _faddx_215short 0x0000216217bra.l _fdivs_218short 0x0000219bra.l _fdivd_220short 0x0000221bra.l _fdivx_222short 0x0000223224bra.l _fints_225short 0x0000226bra.l _fintd_227short 0x0000228bra.l _fintx_229short 0x0000230231bra.l _fintrzs_232short 0x0000233bra.l _fintrzd_234short 0x0000235bra.l _fintrzx_236short 0x0000237238bra.l _fmuls_239short 0x0000240bra.l _fmuld_241short 0x0000242bra.l _fmulx_243short 0x0000244245bra.l _fnegs_246short 0x0000247bra.l _fnegd_248short 0x0000249bra.l _fnegx_250short 0x0000251252bra.l _fsqrts_253short 0x0000254bra.l _fsqrtd_255short 0x0000256bra.l _fsqrtx_257short 0x0000258259bra.l _fsubs_260short 0x0000261bra.l _fsubd_262short 0x0000263bra.l _fsubx_264short 0x0000265266# leave room for future possible additions267align 0x400268269#270# This file contains a set of define statements for constants271# in order to promote readability within the corecode itself.272#273274set LOCAL_SIZE, 192 # stack frame size(bytes)275set LV, -LOCAL_SIZE # stack offset276277set EXC_SR, 0x4 # stack status register278set EXC_PC, 0x6 # stack pc279set EXC_VOFF, 0xa # stacked vector offset280set EXC_EA, 0xc # stacked <ea>281282set EXC_FP, 0x0 # frame pointer283284set EXC_AREGS, -68 # offset of all address regs285set EXC_DREGS, -100 # offset of all data regs286set EXC_FPREGS, -36 # offset of all fp regs287288set EXC_A7, EXC_AREGS+(7*4) # offset of saved a7289set OLD_A7, EXC_AREGS+(6*4) # extra copy of saved a7290set EXC_A6, EXC_AREGS+(6*4) # offset of saved a6291set EXC_A5, EXC_AREGS+(5*4)292set EXC_A4, EXC_AREGS+(4*4)293set EXC_A3, EXC_AREGS+(3*4)294set EXC_A2, EXC_AREGS+(2*4)295set EXC_A1, EXC_AREGS+(1*4)296set EXC_A0, EXC_AREGS+(0*4)297set EXC_D7, EXC_DREGS+(7*4)298set EXC_D6, EXC_DREGS+(6*4)299set EXC_D5, EXC_DREGS+(5*4)300set EXC_D4, EXC_DREGS+(4*4)301set EXC_D3, EXC_DREGS+(3*4)302set EXC_D2, EXC_DREGS+(2*4)303set EXC_D1, EXC_DREGS+(1*4)304set EXC_D0, EXC_DREGS+(0*4)305306set EXC_FP0, EXC_FPREGS+(0*12) # offset of saved fp0307set EXC_FP1, EXC_FPREGS+(1*12) # offset of saved fp1308set EXC_FP2, EXC_FPREGS+(2*12) # offset of saved fp2 (not used)309310set FP_SCR1, LV+80 # fp scratch 1311set FP_SCR1_EX, FP_SCR1+0312set FP_SCR1_SGN, FP_SCR1+2313set FP_SCR1_HI, FP_SCR1+4314set FP_SCR1_LO, FP_SCR1+8315316set FP_SCR0, LV+68 # fp scratch 0317set FP_SCR0_EX, FP_SCR0+0318set FP_SCR0_SGN, FP_SCR0+2319set FP_SCR0_HI, FP_SCR0+4320set FP_SCR0_LO, FP_SCR0+8321322set FP_DST, LV+56 # fp destination operand323set FP_DST_EX, FP_DST+0324set FP_DST_SGN, FP_DST+2325set FP_DST_HI, FP_DST+4326set FP_DST_LO, FP_DST+8327328set FP_SRC, LV+44 # fp source operand329set FP_SRC_EX, FP_SRC+0330set FP_SRC_SGN, FP_SRC+2331set FP_SRC_HI, FP_SRC+4332set FP_SRC_LO, FP_SRC+8333334set USER_FPIAR, LV+40 # FP instr address register335336set USER_FPSR, LV+36 # FP status register337set FPSR_CC, USER_FPSR+0 # FPSR condition codes338set FPSR_QBYTE, USER_FPSR+1 # FPSR qoutient byte339set FPSR_EXCEPT, USER_FPSR+2 # FPSR exception status byte340set FPSR_AEXCEPT, USER_FPSR+3 # FPSR accrued exception byte341342set USER_FPCR, LV+32 # FP control register343set FPCR_ENABLE, USER_FPCR+2 # FPCR exception enable344set FPCR_MODE, USER_FPCR+3 # FPCR rounding mode control345346set L_SCR3, LV+28 # integer scratch 3347set L_SCR2, LV+24 # integer scratch 2348set L_SCR1, LV+20 # integer scratch 1349350set STORE_FLG, LV+19 # flag: operand store (ie. not fcmp/ftst)351352set EXC_TEMP2, LV+24 # temporary space353set EXC_TEMP, LV+16 # temporary space354355set DTAG, LV+15 # destination operand type356set STAG, LV+14 # source operand type357358set SPCOND_FLG, LV+10 # flag: special case (see below)359360set EXC_CC, LV+8 # saved condition codes361set EXC_EXTWPTR, LV+4 # saved current PC (active)362set EXC_EXTWORD, LV+2 # saved extension word363set EXC_CMDREG, LV+2 # saved extension word364set EXC_OPWORD, LV+0 # saved operation word365366################################367368# Helpful macros369370set FTEMP, 0 # offsets within an371set FTEMP_EX, 0 # extended precision372set FTEMP_SGN, 2 # value saved in memory.373set FTEMP_HI, 4374set FTEMP_LO, 8375set FTEMP_GRS, 12376377set LOCAL, 0 # offsets within an378set LOCAL_EX, 0 # extended precision379set LOCAL_SGN, 2 # value saved in memory.380set LOCAL_HI, 4381set LOCAL_LO, 8382set LOCAL_GRS, 12383384set DST, 0 # offsets within an385set DST_EX, 0 # extended precision386set DST_HI, 4 # value saved in memory.387set DST_LO, 8388389set SRC, 0 # offsets within an390set SRC_EX, 0 # extended precision391set SRC_HI, 4 # value saved in memory.392set SRC_LO, 8393394set SGL_LO, 0x3f81 # min sgl prec exponent395set SGL_HI, 0x407e # max sgl prec exponent396set DBL_LO, 0x3c01 # min dbl prec exponent397set DBL_HI, 0x43fe # max dbl prec exponent398set EXT_LO, 0x0 # min ext prec exponent399set EXT_HI, 0x7ffe # max ext prec exponent400401set EXT_BIAS, 0x3fff # extended precision bias402set SGL_BIAS, 0x007f # single precision bias403set DBL_BIAS, 0x03ff # double precision bias404405set NORM, 0x00 # operand type for STAG/DTAG406set ZERO, 0x01 # operand type for STAG/DTAG407set INF, 0x02 # operand type for STAG/DTAG408set QNAN, 0x03 # operand type for STAG/DTAG409set DENORM, 0x04 # operand type for STAG/DTAG410set SNAN, 0x05 # operand type for STAG/DTAG411set UNNORM, 0x06 # operand type for STAG/DTAG412413##################414# FPSR/FPCR bits #415##################416set neg_bit, 0x3 # negative result417set z_bit, 0x2 # zero result418set inf_bit, 0x1 # infinite result419set nan_bit, 0x0 # NAN result420421set q_sn_bit, 0x7 # sign bit of quotient byte422423set bsun_bit, 7 # branch on unordered424set snan_bit, 6 # signalling NAN425set operr_bit, 5 # operand error426set ovfl_bit, 4 # overflow427set unfl_bit, 3 # underflow428set dz_bit, 2 # divide by zero429set inex2_bit, 1 # inexact result 2430set inex1_bit, 0 # inexact result 1431432set aiop_bit, 7 # accrued inexact operation bit433set aovfl_bit, 6 # accrued overflow bit434set aunfl_bit, 5 # accrued underflow bit435set adz_bit, 4 # accrued dz bit436set ainex_bit, 3 # accrued inexact bit437438#############################439# FPSR individual bit masks #440#############################441set neg_mask, 0x08000000 # negative bit mask (lw)442set inf_mask, 0x02000000 # infinity bit mask (lw)443set z_mask, 0x04000000 # zero bit mask (lw)444set nan_mask, 0x01000000 # nan bit mask (lw)445446set neg_bmask, 0x08 # negative bit mask (byte)447set inf_bmask, 0x02 # infinity bit mask (byte)448set z_bmask, 0x04 # zero bit mask (byte)449set nan_bmask, 0x01 # nan bit mask (byte)450451set bsun_mask, 0x00008000 # bsun exception mask452set snan_mask, 0x00004000 # snan exception mask453set operr_mask, 0x00002000 # operr exception mask454set ovfl_mask, 0x00001000 # overflow exception mask455set unfl_mask, 0x00000800 # underflow exception mask456set dz_mask, 0x00000400 # dz exception mask457set inex2_mask, 0x00000200 # inex2 exception mask458set inex1_mask, 0x00000100 # inex1 exception mask459460set aiop_mask, 0x00000080 # accrued illegal operation461set aovfl_mask, 0x00000040 # accrued overflow462set aunfl_mask, 0x00000020 # accrued underflow463set adz_mask, 0x00000010 # accrued divide by zero464set ainex_mask, 0x00000008 # accrued inexact465466######################################467# FPSR combinations used in the FPSP #468######################################469set dzinf_mask, inf_mask+dz_mask+adz_mask470set opnan_mask, nan_mask+operr_mask+aiop_mask471set nzi_mask, 0x01ffffff #clears N, Z, and I472set unfinx_mask, unfl_mask+inex2_mask+aunfl_mask+ainex_mask473set unf2inx_mask, unfl_mask+inex2_mask+ainex_mask474set ovfinx_mask, ovfl_mask+inex2_mask+aovfl_mask+ainex_mask475set inx1a_mask, inex1_mask+ainex_mask476set inx2a_mask, inex2_mask+ainex_mask477set snaniop_mask, nan_mask+snan_mask+aiop_mask478set snaniop2_mask, snan_mask+aiop_mask479set naniop_mask, nan_mask+aiop_mask480set neginf_mask, neg_mask+inf_mask481set infaiop_mask, inf_mask+aiop_mask482set negz_mask, neg_mask+z_mask483set opaop_mask, operr_mask+aiop_mask484set unfl_inx_mask, unfl_mask+aunfl_mask+ainex_mask485set ovfl_inx_mask, ovfl_mask+aovfl_mask+ainex_mask486487#########488# misc. #489#########490set rnd_stky_bit, 29 # stky bit pos in longword491492set sign_bit, 0x7 # sign bit493set signan_bit, 0x6 # signalling nan bit494495set sgl_thresh, 0x3f81 # minimum sgl exponent496set dbl_thresh, 0x3c01 # minimum dbl exponent497498set x_mode, 0x0 # extended precision499set s_mode, 0x4 # single precision500set d_mode, 0x8 # double precision501502set rn_mode, 0x0 # round-to-nearest503set rz_mode, 0x1 # round-to-zero504set rm_mode, 0x2 # round-tp-minus-infinity505set rp_mode, 0x3 # round-to-plus-infinity506507set mantissalen, 64 # length of mantissa in bits508509set BYTE, 1 # len(byte) == 1 byte510set WORD, 2 # len(word) == 2 bytes511set LONG, 4 # len(longword) == 2 bytes512513set BSUN_VEC, 0xc0 # bsun vector offset514set INEX_VEC, 0xc4 # inexact vector offset515set DZ_VEC, 0xc8 # dz vector offset516set UNFL_VEC, 0xcc # unfl vector offset517set OPERR_VEC, 0xd0 # operr vector offset518set OVFL_VEC, 0xd4 # ovfl vector offset519set SNAN_VEC, 0xd8 # snan vector offset520521###########################522# SPecial CONDition FLaGs #523###########################524set ftrapcc_flg, 0x01 # flag bit: ftrapcc exception525set fbsun_flg, 0x02 # flag bit: bsun exception526set mia7_flg, 0x04 # flag bit: (a7)+ <ea>527set mda7_flg, 0x08 # flag bit: -(a7) <ea>528set fmovm_flg, 0x40 # flag bit: fmovm instruction529set immed_flg, 0x80 # flag bit: &<data> <ea>530531set ftrapcc_bit, 0x0532set fbsun_bit, 0x1533set mia7_bit, 0x2534set mda7_bit, 0x3535set immed_bit, 0x7536537##################################538# TRANSCENDENTAL "LAST-OP" FLAGS #539##################################540set FMUL_OP, 0x0 # fmul instr performed last541set FDIV_OP, 0x1 # fdiv performed last542set FADD_OP, 0x2 # fadd performed last543set FMOV_OP, 0x3 # fmov performed last544545#############546# CONSTANTS #547#############548T1: long 0x40C62D38,0xD3D64634 # 16381 LOG2 LEAD549T2: long 0x3D6F90AE,0xB1E75CC7 # 16381 LOG2 TRAIL550551PI: long 0x40000000,0xC90FDAA2,0x2168C235,0x00000000552PIBY2: long 0x3FFF0000,0xC90FDAA2,0x2168C235,0x00000000553554TWOBYPI:555long 0x3FE45F30,0x6DC9C883556557#########################################################################558# MONADIC TEMPLATE #559#########################################################################560global _fsins_561_fsins_:562link %a6,&-LOCAL_SIZE563564movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1565fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs566fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1567568fmov.l &0x0,%fpcr # zero FPCR569570#571# copy, convert, and tag input argument572#573fmov.s 0x8(%a6),%fp0 # load sgl input574fmov.x %fp0,FP_SRC(%a6)575lea FP_SRC(%a6),%a0576bsr.l tag # fetch operand type577mov.b %d0,STAG(%a6)578mov.b %d0,%d1579580andi.l &0x00ff00ff,USER_FPSR(%a6)581582clr.l %d0583mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec584585tst.b %d1586bne.b _L0_2s587bsr.l ssin # operand is a NORM588bra.b _L0_6s589_L0_2s:590cmpi.b %d1,&ZERO # is operand a ZERO?591bne.b _L0_3s # no592bsr.l src_zero # yes593bra.b _L0_6s594_L0_3s:595cmpi.b %d1,&INF # is operand an INF?596bne.b _L0_4s # no597bsr.l t_operr # yes598bra.b _L0_6s599_L0_4s:600cmpi.b %d1,&QNAN # is operand a QNAN?601bne.b _L0_5s # no602bsr.l src_qnan # yes603bra.b _L0_6s604_L0_5s:605bsr.l ssind # operand is a DENORM606_L0_6s:607608#609# Result is now in FP0610#611movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1612fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs613fmovm.x EXC_FP1(%a6),&0x40 # restore fp1614unlk %a6615rts616617global _fsind_618_fsind_:619link %a6,&-LOCAL_SIZE620621movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1622fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs623fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1624625fmov.l &0x0,%fpcr # zero FPCR626627#628# copy, convert, and tag input argument629#630fmov.d 0x8(%a6),%fp0 # load dbl input631fmov.x %fp0,FP_SRC(%a6)632lea FP_SRC(%a6),%a0633bsr.l tag # fetch operand type634mov.b %d0,STAG(%a6)635mov.b %d0,%d1636637andi.l &0x00ff00ff,USER_FPSR(%a6)638639clr.l %d0640mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec641642mov.b %d1,STAG(%a6)643tst.b %d1644bne.b _L0_2d645bsr.l ssin # operand is a NORM646bra.b _L0_6d647_L0_2d:648cmpi.b %d1,&ZERO # is operand a ZERO?649bne.b _L0_3d # no650bsr.l src_zero # yes651bra.b _L0_6d652_L0_3d:653cmpi.b %d1,&INF # is operand an INF?654bne.b _L0_4d # no655bsr.l t_operr # yes656bra.b _L0_6d657_L0_4d:658cmpi.b %d1,&QNAN # is operand a QNAN?659bne.b _L0_5d # no660bsr.l src_qnan # yes661bra.b _L0_6d662_L0_5d:663bsr.l ssind # operand is a DENORM664_L0_6d:665666#667# Result is now in FP0668#669movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1670fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs671fmovm.x EXC_FP1(%a6),&0x40 # restore fp1672unlk %a6673rts674675global _fsinx_676_fsinx_:677link %a6,&-LOCAL_SIZE678679movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1680fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs681fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1682683fmov.l &0x0,%fpcr # zero FPCR684685#686# copy, convert, and tag input argument687#688lea FP_SRC(%a6),%a0689mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input690mov.l 0x8+0x4(%a6),0x4(%a0)691mov.l 0x8+0x8(%a6),0x8(%a0)692bsr.l tag # fetch operand type693mov.b %d0,STAG(%a6)694mov.b %d0,%d1695696andi.l &0x00ff00ff,USER_FPSR(%a6)697698clr.l %d0699mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec700701tst.b %d1702bne.b _L0_2x703bsr.l ssin # operand is a NORM704bra.b _L0_6x705_L0_2x:706cmpi.b %d1,&ZERO # is operand a ZERO?707bne.b _L0_3x # no708bsr.l src_zero # yes709bra.b _L0_6x710_L0_3x:711cmpi.b %d1,&INF # is operand an INF?712bne.b _L0_4x # no713bsr.l t_operr # yes714bra.b _L0_6x715_L0_4x:716cmpi.b %d1,&QNAN # is operand a QNAN?717bne.b _L0_5x # no718bsr.l src_qnan # yes719bra.b _L0_6x720_L0_5x:721bsr.l ssind # operand is a DENORM722_L0_6x:723724#725# Result is now in FP0726#727movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1728fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs729fmovm.x EXC_FP1(%a6),&0x40 # restore fp1730unlk %a6731rts732733734#########################################################################735# MONADIC TEMPLATE #736#########################################################################737global _fcoss_738_fcoss_:739link %a6,&-LOCAL_SIZE740741movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1742fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs743fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1744745fmov.l &0x0,%fpcr # zero FPCR746747#748# copy, convert, and tag input argument749#750fmov.s 0x8(%a6),%fp0 # load sgl input751fmov.x %fp0,FP_SRC(%a6)752lea FP_SRC(%a6),%a0753bsr.l tag # fetch operand type754mov.b %d0,STAG(%a6)755mov.b %d0,%d1756757andi.l &0x00ff00ff,USER_FPSR(%a6)758759clr.l %d0760mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec761762tst.b %d1763bne.b _L1_2s764bsr.l scos # operand is a NORM765bra.b _L1_6s766_L1_2s:767cmpi.b %d1,&ZERO # is operand a ZERO?768bne.b _L1_3s # no769bsr.l ld_pone # yes770bra.b _L1_6s771_L1_3s:772cmpi.b %d1,&INF # is operand an INF?773bne.b _L1_4s # no774bsr.l t_operr # yes775bra.b _L1_6s776_L1_4s:777cmpi.b %d1,&QNAN # is operand a QNAN?778bne.b _L1_5s # no779bsr.l src_qnan # yes780bra.b _L1_6s781_L1_5s:782bsr.l scosd # operand is a DENORM783_L1_6s:784785#786# Result is now in FP0787#788movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1789fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs790fmovm.x EXC_FP1(%a6),&0x40 # restore fp1791unlk %a6792rts793794global _fcosd_795_fcosd_:796link %a6,&-LOCAL_SIZE797798movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1799fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs800fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1801802fmov.l &0x0,%fpcr # zero FPCR803804#805# copy, convert, and tag input argument806#807fmov.d 0x8(%a6),%fp0 # load dbl input808fmov.x %fp0,FP_SRC(%a6)809lea FP_SRC(%a6),%a0810bsr.l tag # fetch operand type811mov.b %d0,STAG(%a6)812mov.b %d0,%d1813814andi.l &0x00ff00ff,USER_FPSR(%a6)815816clr.l %d0817mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec818819mov.b %d1,STAG(%a6)820tst.b %d1821bne.b _L1_2d822bsr.l scos # operand is a NORM823bra.b _L1_6d824_L1_2d:825cmpi.b %d1,&ZERO # is operand a ZERO?826bne.b _L1_3d # no827bsr.l ld_pone # yes828bra.b _L1_6d829_L1_3d:830cmpi.b %d1,&INF # is operand an INF?831bne.b _L1_4d # no832bsr.l t_operr # yes833bra.b _L1_6d834_L1_4d:835cmpi.b %d1,&QNAN # is operand a QNAN?836bne.b _L1_5d # no837bsr.l src_qnan # yes838bra.b _L1_6d839_L1_5d:840bsr.l scosd # operand is a DENORM841_L1_6d:842843#844# Result is now in FP0845#846movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1847fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs848fmovm.x EXC_FP1(%a6),&0x40 # restore fp1849unlk %a6850rts851852global _fcosx_853_fcosx_:854link %a6,&-LOCAL_SIZE855856movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1857fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs858fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1859860fmov.l &0x0,%fpcr # zero FPCR861862#863# copy, convert, and tag input argument864#865lea FP_SRC(%a6),%a0866mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input867mov.l 0x8+0x4(%a6),0x4(%a0)868mov.l 0x8+0x8(%a6),0x8(%a0)869bsr.l tag # fetch operand type870mov.b %d0,STAG(%a6)871mov.b %d0,%d1872873andi.l &0x00ff00ff,USER_FPSR(%a6)874875clr.l %d0876mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec877878tst.b %d1879bne.b _L1_2x880bsr.l scos # operand is a NORM881bra.b _L1_6x882_L1_2x:883cmpi.b %d1,&ZERO # is operand a ZERO?884bne.b _L1_3x # no885bsr.l ld_pone # yes886bra.b _L1_6x887_L1_3x:888cmpi.b %d1,&INF # is operand an INF?889bne.b _L1_4x # no890bsr.l t_operr # yes891bra.b _L1_6x892_L1_4x:893cmpi.b %d1,&QNAN # is operand a QNAN?894bne.b _L1_5x # no895bsr.l src_qnan # yes896bra.b _L1_6x897_L1_5x:898bsr.l scosd # operand is a DENORM899_L1_6x:900901#902# Result is now in FP0903#904movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1905fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs906fmovm.x EXC_FP1(%a6),&0x40 # restore fp1907unlk %a6908rts909910911#########################################################################912# MONADIC TEMPLATE #913#########################################################################914global _fsinhs_915_fsinhs_:916link %a6,&-LOCAL_SIZE917918movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1919fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs920fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1921922fmov.l &0x0,%fpcr # zero FPCR923924#925# copy, convert, and tag input argument926#927fmov.s 0x8(%a6),%fp0 # load sgl input928fmov.x %fp0,FP_SRC(%a6)929lea FP_SRC(%a6),%a0930bsr.l tag # fetch operand type931mov.b %d0,STAG(%a6)932mov.b %d0,%d1933934andi.l &0x00ff00ff,USER_FPSR(%a6)935936clr.l %d0937mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec938939tst.b %d1940bne.b _L2_2s941bsr.l ssinh # operand is a NORM942bra.b _L2_6s943_L2_2s:944cmpi.b %d1,&ZERO # is operand a ZERO?945bne.b _L2_3s # no946bsr.l src_zero # yes947bra.b _L2_6s948_L2_3s:949cmpi.b %d1,&INF # is operand an INF?950bne.b _L2_4s # no951bsr.l src_inf # yes952bra.b _L2_6s953_L2_4s:954cmpi.b %d1,&QNAN # is operand a QNAN?955bne.b _L2_5s # no956bsr.l src_qnan # yes957bra.b _L2_6s958_L2_5s:959bsr.l ssinhd # operand is a DENORM960_L2_6s:961962#963# Result is now in FP0964#965movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1966fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs967fmovm.x EXC_FP1(%a6),&0x40 # restore fp1968unlk %a6969rts970971global _fsinhd_972_fsinhd_:973link %a6,&-LOCAL_SIZE974975movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1976fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs977fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1978979fmov.l &0x0,%fpcr # zero FPCR980981#982# copy, convert, and tag input argument983#984fmov.d 0x8(%a6),%fp0 # load dbl input985fmov.x %fp0,FP_SRC(%a6)986lea FP_SRC(%a6),%a0987bsr.l tag # fetch operand type988mov.b %d0,STAG(%a6)989mov.b %d0,%d1990991andi.l &0x00ff00ff,USER_FPSR(%a6)992993clr.l %d0994mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec995996mov.b %d1,STAG(%a6)997tst.b %d1998bne.b _L2_2d999bsr.l ssinh # operand is a NORM1000bra.b _L2_6d1001_L2_2d:1002cmpi.b %d1,&ZERO # is operand a ZERO?1003bne.b _L2_3d # no1004bsr.l src_zero # yes1005bra.b _L2_6d1006_L2_3d:1007cmpi.b %d1,&INF # is operand an INF?1008bne.b _L2_4d # no1009bsr.l src_inf # yes1010bra.b _L2_6d1011_L2_4d:1012cmpi.b %d1,&QNAN # is operand a QNAN?1013bne.b _L2_5d # no1014bsr.l src_qnan # yes1015bra.b _L2_6d1016_L2_5d:1017bsr.l ssinhd # operand is a DENORM1018_L2_6d:10191020#1021# Result is now in FP01022#1023movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a11024fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs1025fmovm.x EXC_FP1(%a6),&0x40 # restore fp11026unlk %a61027rts10281029global _fsinhx_1030_fsinhx_:1031link %a6,&-LOCAL_SIZE10321033movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a11034fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs1035fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp110361037fmov.l &0x0,%fpcr # zero FPCR10381039#1040# copy, convert, and tag input argument1041#1042lea FP_SRC(%a6),%a01043mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input1044mov.l 0x8+0x4(%a6),0x4(%a0)1045mov.l 0x8+0x8(%a6),0x8(%a0)1046bsr.l tag # fetch operand type1047mov.b %d0,STAG(%a6)1048mov.b %d0,%d110491050andi.l &0x00ff00ff,USER_FPSR(%a6)10511052clr.l %d01053mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec10541055tst.b %d11056bne.b _L2_2x1057bsr.l ssinh # operand is a NORM1058bra.b _L2_6x1059_L2_2x:1060cmpi.b %d1,&ZERO # is operand a ZERO?1061bne.b _L2_3x # no1062bsr.l src_zero # yes1063bra.b _L2_6x1064_L2_3x:1065cmpi.b %d1,&INF # is operand an INF?1066bne.b _L2_4x # no1067bsr.l src_inf # yes1068bra.b _L2_6x1069_L2_4x:1070cmpi.b %d1,&QNAN # is operand a QNAN?1071bne.b _L2_5x # no1072bsr.l src_qnan # yes1073bra.b _L2_6x1074_L2_5x:1075bsr.l ssinhd # operand is a DENORM1076_L2_6x:10771078#1079# Result is now in FP01080#1081movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a11082fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs1083fmovm.x EXC_FP1(%a6),&0x40 # restore fp11084unlk %a61085rts108610871088#########################################################################1089# MONADIC TEMPLATE #1090#########################################################################1091global _flognp1s_1092_flognp1s_:1093link %a6,&-LOCAL_SIZE10941095movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a11096fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs1097fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp110981099fmov.l &0x0,%fpcr # zero FPCR11001101#1102# copy, convert, and tag input argument1103#1104fmov.s 0x8(%a6),%fp0 # load sgl input1105fmov.x %fp0,FP_SRC(%a6)1106lea FP_SRC(%a6),%a01107bsr.l tag # fetch operand type1108mov.b %d0,STAG(%a6)1109mov.b %d0,%d111101111andi.l &0x00ff00ff,USER_FPSR(%a6)11121113clr.l %d01114mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec11151116tst.b %d11117bne.b _L3_2s1118bsr.l slognp1 # operand is a NORM1119bra.b _L3_6s1120_L3_2s:1121cmpi.b %d1,&ZERO # is operand a ZERO?1122bne.b _L3_3s # no1123bsr.l src_zero # yes1124bra.b _L3_6s1125_L3_3s:1126cmpi.b %d1,&INF # is operand an INF?1127bne.b _L3_4s # no1128bsr.l sopr_inf # yes1129bra.b _L3_6s1130_L3_4s:1131cmpi.b %d1,&QNAN # is operand a QNAN?1132bne.b _L3_5s # no1133bsr.l src_qnan # yes1134bra.b _L3_6s1135_L3_5s:1136bsr.l slognp1d # operand is a DENORM1137_L3_6s:11381139#1140# Result is now in FP01141#1142movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a11143fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs1144fmovm.x EXC_FP1(%a6),&0x40 # restore fp11145unlk %a61146rts11471148global _flognp1d_1149_flognp1d_:1150link %a6,&-LOCAL_SIZE11511152movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a11153fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs1154fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp111551156fmov.l &0x0,%fpcr # zero FPCR11571158#1159# copy, convert, and tag input argument1160#1161fmov.d 0x8(%a6),%fp0 # load dbl input1162fmov.x %fp0,FP_SRC(%a6)1163lea FP_SRC(%a6),%a01164bsr.l tag # fetch operand type1165mov.b %d0,STAG(%a6)1166mov.b %d0,%d111671168andi.l &0x00ff00ff,USER_FPSR(%a6)11691170clr.l %d01171mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec11721173mov.b %d1,STAG(%a6)1174tst.b %d11175bne.b _L3_2d1176bsr.l slognp1 # operand is a NORM1177bra.b _L3_6d1178_L3_2d:1179cmpi.b %d1,&ZERO # is operand a ZERO?1180bne.b _L3_3d # no1181bsr.l src_zero # yes1182bra.b _L3_6d1183_L3_3d:1184cmpi.b %d1,&INF # is operand an INF?1185bne.b _L3_4d # no1186bsr.l sopr_inf # yes1187bra.b _L3_6d1188_L3_4d:1189cmpi.b %d1,&QNAN # is operand a QNAN?1190bne.b _L3_5d # no1191bsr.l src_qnan # yes1192bra.b _L3_6d1193_L3_5d:1194bsr.l slognp1d # operand is a DENORM1195_L3_6d:11961197#1198# Result is now in FP01199#1200movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a11201fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs1202fmovm.x EXC_FP1(%a6),&0x40 # restore fp11203unlk %a61204rts12051206global _flognp1x_1207_flognp1x_:1208link %a6,&-LOCAL_SIZE12091210movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a11211fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs1212fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp112131214fmov.l &0x0,%fpcr # zero FPCR12151216#1217# copy, convert, and tag input argument1218#1219lea FP_SRC(%a6),%a01220mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input1221mov.l 0x8+0x4(%a6),0x4(%a0)1222mov.l 0x8+0x8(%a6),0x8(%a0)1223bsr.l tag # fetch operand type1224mov.b %d0,STAG(%a6)1225mov.b %d0,%d112261227andi.l &0x00ff00ff,USER_FPSR(%a6)12281229clr.l %d01230mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec12311232tst.b %d11233bne.b _L3_2x1234bsr.l slognp1 # operand is a NORM1235bra.b _L3_6x1236_L3_2x:1237cmpi.b %d1,&ZERO # is operand a ZERO?1238bne.b _L3_3x # no1239bsr.l src_zero # yes1240bra.b _L3_6x1241_L3_3x:1242cmpi.b %d1,&INF # is operand an INF?1243bne.b _L3_4x # no1244bsr.l sopr_inf # yes1245bra.b _L3_6x1246_L3_4x:1247cmpi.b %d1,&QNAN # is operand a QNAN?1248bne.b _L3_5x # no1249bsr.l src_qnan # yes1250bra.b _L3_6x1251_L3_5x:1252bsr.l slognp1d # operand is a DENORM1253_L3_6x:12541255#1256# Result is now in FP01257#1258movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a11259fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs1260fmovm.x EXC_FP1(%a6),&0x40 # restore fp11261unlk %a61262rts126312641265#########################################################################1266# MONADIC TEMPLATE #1267#########################################################################1268global _fetoxm1s_1269_fetoxm1s_:1270link %a6,&-LOCAL_SIZE12711272movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a11273fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs1274fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp112751276fmov.l &0x0,%fpcr # zero FPCR12771278#1279# copy, convert, and tag input argument1280#1281fmov.s 0x8(%a6),%fp0 # load sgl input1282fmov.x %fp0,FP_SRC(%a6)1283lea FP_SRC(%a6),%a01284bsr.l tag # fetch operand type1285mov.b %d0,STAG(%a6)1286mov.b %d0,%d112871288andi.l &0x00ff00ff,USER_FPSR(%a6)12891290clr.l %d01291mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec12921293tst.b %d11294bne.b _L4_2s1295bsr.l setoxm1 # operand is a NORM1296bra.b _L4_6s1297_L4_2s:1298cmpi.b %d1,&ZERO # is operand a ZERO?1299bne.b _L4_3s # no1300bsr.l src_zero # yes1301bra.b _L4_6s1302_L4_3s:1303cmpi.b %d1,&INF # is operand an INF?1304bne.b _L4_4s # no1305bsr.l setoxm1i # yes1306bra.b _L4_6s1307_L4_4s:1308cmpi.b %d1,&QNAN # is operand a QNAN?1309bne.b _L4_5s # no1310bsr.l src_qnan # yes1311bra.b _L4_6s1312_L4_5s:1313bsr.l setoxm1d # operand is a DENORM1314_L4_6s:13151316#1317# Result is now in FP01318#1319movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a11320fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs1321fmovm.x EXC_FP1(%a6),&0x40 # restore fp11322unlk %a61323rts13241325global _fetoxm1d_1326_fetoxm1d_:1327link %a6,&-LOCAL_SIZE13281329movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a11330fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs1331fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp113321333fmov.l &0x0,%fpcr # zero FPCR13341335#1336# copy, convert, and tag input argument1337#1338fmov.d 0x8(%a6),%fp0 # load dbl input1339fmov.x %fp0,FP_SRC(%a6)1340lea FP_SRC(%a6),%a01341bsr.l tag # fetch operand type1342mov.b %d0,STAG(%a6)1343mov.b %d0,%d113441345andi.l &0x00ff00ff,USER_FPSR(%a6)13461347clr.l %d01348mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec13491350mov.b %d1,STAG(%a6)1351tst.b %d11352bne.b _L4_2d1353bsr.l setoxm1 # operand is a NORM1354bra.b _L4_6d1355_L4_2d:1356cmpi.b %d1,&ZERO # is operand a ZERO?1357bne.b _L4_3d # no1358bsr.l src_zero # yes1359bra.b _L4_6d1360_L4_3d:1361cmpi.b %d1,&INF # is operand an INF?1362bne.b _L4_4d # no1363bsr.l setoxm1i # yes1364bra.b _L4_6d1365_L4_4d:1366cmpi.b %d1,&QNAN # is operand a QNAN?1367bne.b _L4_5d # no1368bsr.l src_qnan # yes1369bra.b _L4_6d1370_L4_5d:1371bsr.l setoxm1d # operand is a DENORM1372_L4_6d:13731374#1375# Result is now in FP01376#1377movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a11378fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs1379fmovm.x EXC_FP1(%a6),&0x40 # restore fp11380unlk %a61381rts13821383global _fetoxm1x_1384_fetoxm1x_:1385link %a6,&-LOCAL_SIZE13861387movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a11388fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs1389fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp113901391fmov.l &0x0,%fpcr # zero FPCR13921393#1394# copy, convert, and tag input argument1395#1396lea FP_SRC(%a6),%a01397mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input1398mov.l 0x8+0x4(%a6),0x4(%a0)1399mov.l 0x8+0x8(%a6),0x8(%a0)1400bsr.l tag # fetch operand type1401mov.b %d0,STAG(%a6)1402mov.b %d0,%d114031404andi.l &0x00ff00ff,USER_FPSR(%a6)14051406clr.l %d01407mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec14081409tst.b %d11410bne.b _L4_2x1411bsr.l setoxm1 # operand is a NORM1412bra.b _L4_6x1413_L4_2x:1414cmpi.b %d1,&ZERO # is operand a ZERO?1415bne.b _L4_3x # no1416bsr.l src_zero # yes1417bra.b _L4_6x1418_L4_3x:1419cmpi.b %d1,&INF # is operand an INF?1420bne.b _L4_4x # no1421bsr.l setoxm1i # yes1422bra.b _L4_6x1423_L4_4x:1424cmpi.b %d1,&QNAN # is operand a QNAN?1425bne.b _L4_5x # no1426bsr.l src_qnan # yes1427bra.b _L4_6x1428_L4_5x:1429bsr.l setoxm1d # operand is a DENORM1430_L4_6x:14311432#1433# Result is now in FP01434#1435movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a11436fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs1437fmovm.x EXC_FP1(%a6),&0x40 # restore fp11438unlk %a61439rts144014411442#########################################################################1443# MONADIC TEMPLATE #1444#########################################################################1445global _ftanhs_1446_ftanhs_:1447link %a6,&-LOCAL_SIZE14481449movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a11450fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs1451fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp114521453fmov.l &0x0,%fpcr # zero FPCR14541455#1456# copy, convert, and tag input argument1457#1458fmov.s 0x8(%a6),%fp0 # load sgl input1459fmov.x %fp0,FP_SRC(%a6)1460lea FP_SRC(%a6),%a01461bsr.l tag # fetch operand type1462mov.b %d0,STAG(%a6)1463mov.b %d0,%d114641465andi.l &0x00ff00ff,USER_FPSR(%a6)14661467clr.l %d01468mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec14691470tst.b %d11471bne.b _L5_2s1472bsr.l stanh # operand is a NORM1473bra.b _L5_6s1474_L5_2s:1475cmpi.b %d1,&ZERO # is operand a ZERO?1476bne.b _L5_3s # no1477bsr.l src_zero # yes1478bra.b _L5_6s1479_L5_3s:1480cmpi.b %d1,&INF # is operand an INF?1481bne.b _L5_4s # no1482bsr.l src_one # yes1483bra.b _L5_6s1484_L5_4s:1485cmpi.b %d1,&QNAN # is operand a QNAN?1486bne.b _L5_5s # no1487bsr.l src_qnan # yes1488bra.b _L5_6s1489_L5_5s:1490bsr.l stanhd # operand is a DENORM1491_L5_6s:14921493#1494# Result is now in FP01495#1496movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a11497fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs1498fmovm.x EXC_FP1(%a6),&0x40 # restore fp11499unlk %a61500rts15011502global _ftanhd_1503_ftanhd_:1504link %a6,&-LOCAL_SIZE15051506movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a11507fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs1508fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp115091510fmov.l &0x0,%fpcr # zero FPCR15111512#1513# copy, convert, and tag input argument1514#1515fmov.d 0x8(%a6),%fp0 # load dbl input1516fmov.x %fp0,FP_SRC(%a6)1517lea FP_SRC(%a6),%a01518bsr.l tag # fetch operand type1519mov.b %d0,STAG(%a6)1520mov.b %d0,%d115211522andi.l &0x00ff00ff,USER_FPSR(%a6)15231524clr.l %d01525mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec15261527mov.b %d1,STAG(%a6)1528tst.b %d11529bne.b _L5_2d1530bsr.l stanh # operand is a NORM1531bra.b _L5_6d1532_L5_2d:1533cmpi.b %d1,&ZERO # is operand a ZERO?1534bne.b _L5_3d # no1535bsr.l src_zero # yes1536bra.b _L5_6d1537_L5_3d:1538cmpi.b %d1,&INF # is operand an INF?1539bne.b _L5_4d # no1540bsr.l src_one # yes1541bra.b _L5_6d1542_L5_4d:1543cmpi.b %d1,&QNAN # is operand a QNAN?1544bne.b _L5_5d # no1545bsr.l src_qnan # yes1546bra.b _L5_6d1547_L5_5d:1548bsr.l stanhd # operand is a DENORM1549_L5_6d:15501551#1552# Result is now in FP01553#1554movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a11555fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs1556fmovm.x EXC_FP1(%a6),&0x40 # restore fp11557unlk %a61558rts15591560global _ftanhx_1561_ftanhx_:1562link %a6,&-LOCAL_SIZE15631564movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a11565fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs1566fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp115671568fmov.l &0x0,%fpcr # zero FPCR15691570#1571# copy, convert, and tag input argument1572#1573lea FP_SRC(%a6),%a01574mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input1575mov.l 0x8+0x4(%a6),0x4(%a0)1576mov.l 0x8+0x8(%a6),0x8(%a0)1577bsr.l tag # fetch operand type1578mov.b %d0,STAG(%a6)1579mov.b %d0,%d115801581andi.l &0x00ff00ff,USER_FPSR(%a6)15821583clr.l %d01584mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec15851586tst.b %d11587bne.b _L5_2x1588bsr.l stanh # operand is a NORM1589bra.b _L5_6x1590_L5_2x:1591cmpi.b %d1,&ZERO # is operand a ZERO?1592bne.b _L5_3x # no1593bsr.l src_zero # yes1594bra.b _L5_6x1595_L5_3x:1596cmpi.b %d1,&INF # is operand an INF?1597bne.b _L5_4x # no1598bsr.l src_one # yes1599bra.b _L5_6x1600_L5_4x:1601cmpi.b %d1,&QNAN # is operand a QNAN?1602bne.b _L5_5x # no1603bsr.l src_qnan # yes1604bra.b _L5_6x1605_L5_5x:1606bsr.l stanhd # operand is a DENORM1607_L5_6x:16081609#1610# Result is now in FP01611#1612movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a11613fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs1614fmovm.x EXC_FP1(%a6),&0x40 # restore fp11615unlk %a61616rts161716181619#########################################################################1620# MONADIC TEMPLATE #1621#########################################################################1622global _fatans_1623_fatans_:1624link %a6,&-LOCAL_SIZE16251626movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a11627fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs1628fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp116291630fmov.l &0x0,%fpcr # zero FPCR16311632#1633# copy, convert, and tag input argument1634#1635fmov.s 0x8(%a6),%fp0 # load sgl input1636fmov.x %fp0,FP_SRC(%a6)1637lea FP_SRC(%a6),%a01638bsr.l tag # fetch operand type1639mov.b %d0,STAG(%a6)1640mov.b %d0,%d116411642andi.l &0x00ff00ff,USER_FPSR(%a6)16431644clr.l %d01645mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec16461647tst.b %d11648bne.b _L6_2s1649bsr.l satan # operand is a NORM1650bra.b _L6_6s1651_L6_2s:1652cmpi.b %d1,&ZERO # is operand a ZERO?1653bne.b _L6_3s # no1654bsr.l src_zero # yes1655bra.b _L6_6s1656_L6_3s:1657cmpi.b %d1,&INF # is operand an INF?1658bne.b _L6_4s # no1659bsr.l spi_2 # yes1660bra.b _L6_6s1661_L6_4s:1662cmpi.b %d1,&QNAN # is operand a QNAN?1663bne.b _L6_5s # no1664bsr.l src_qnan # yes1665bra.b _L6_6s1666_L6_5s:1667bsr.l satand # operand is a DENORM1668_L6_6s:16691670#1671# Result is now in FP01672#1673movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a11674fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs1675fmovm.x EXC_FP1(%a6),&0x40 # restore fp11676unlk %a61677rts16781679global _fatand_1680_fatand_:1681link %a6,&-LOCAL_SIZE16821683movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a11684fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs1685fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp116861687fmov.l &0x0,%fpcr # zero FPCR16881689#1690# copy, convert, and tag input argument1691#1692fmov.d 0x8(%a6),%fp0 # load dbl input1693fmov.x %fp0,FP_SRC(%a6)1694lea FP_SRC(%a6),%a01695bsr.l tag # fetch operand type1696mov.b %d0,STAG(%a6)1697mov.b %d0,%d116981699andi.l &0x00ff00ff,USER_FPSR(%a6)17001701clr.l %d01702mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec17031704mov.b %d1,STAG(%a6)1705tst.b %d11706bne.b _L6_2d1707bsr.l satan # operand is a NORM1708bra.b _L6_6d1709_L6_2d:1710cmpi.b %d1,&ZERO # is operand a ZERO?1711bne.b _L6_3d # no1712bsr.l src_zero # yes1713bra.b _L6_6d1714_L6_3d:1715cmpi.b %d1,&INF # is operand an INF?1716bne.b _L6_4d # no1717bsr.l spi_2 # yes1718bra.b _L6_6d1719_L6_4d:1720cmpi.b %d1,&QNAN # is operand a QNAN?1721bne.b _L6_5d # no1722bsr.l src_qnan # yes1723bra.b _L6_6d1724_L6_5d:1725bsr.l satand # operand is a DENORM1726_L6_6d:17271728#1729# Result is now in FP01730#1731movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a11732fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs1733fmovm.x EXC_FP1(%a6),&0x40 # restore fp11734unlk %a61735rts17361737global _fatanx_1738_fatanx_:1739link %a6,&-LOCAL_SIZE17401741movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a11742fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs1743fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp117441745fmov.l &0x0,%fpcr # zero FPCR17461747#1748# copy, convert, and tag input argument1749#1750lea FP_SRC(%a6),%a01751mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input1752mov.l 0x8+0x4(%a6),0x4(%a0)1753mov.l 0x8+0x8(%a6),0x8(%a0)1754bsr.l tag # fetch operand type1755mov.b %d0,STAG(%a6)1756mov.b %d0,%d117571758andi.l &0x00ff00ff,USER_FPSR(%a6)17591760clr.l %d01761mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec17621763tst.b %d11764bne.b _L6_2x1765bsr.l satan # operand is a NORM1766bra.b _L6_6x1767_L6_2x:1768cmpi.b %d1,&ZERO # is operand a ZERO?1769bne.b _L6_3x # no1770bsr.l src_zero # yes1771bra.b _L6_6x1772_L6_3x:1773cmpi.b %d1,&INF # is operand an INF?1774bne.b _L6_4x # no1775bsr.l spi_2 # yes1776bra.b _L6_6x1777_L6_4x:1778cmpi.b %d1,&QNAN # is operand a QNAN?1779bne.b _L6_5x # no1780bsr.l src_qnan # yes1781bra.b _L6_6x1782_L6_5x:1783bsr.l satand # operand is a DENORM1784_L6_6x:17851786#1787# Result is now in FP01788#1789movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a11790fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs1791fmovm.x EXC_FP1(%a6),&0x40 # restore fp11792unlk %a61793rts179417951796#########################################################################1797# MONADIC TEMPLATE #1798#########################################################################1799global _fasins_1800_fasins_:1801link %a6,&-LOCAL_SIZE18021803movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a11804fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs1805fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp118061807fmov.l &0x0,%fpcr # zero FPCR18081809#1810# copy, convert, and tag input argument1811#1812fmov.s 0x8(%a6),%fp0 # load sgl input1813fmov.x %fp0,FP_SRC(%a6)1814lea FP_SRC(%a6),%a01815bsr.l tag # fetch operand type1816mov.b %d0,STAG(%a6)1817mov.b %d0,%d118181819andi.l &0x00ff00ff,USER_FPSR(%a6)18201821clr.l %d01822mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec18231824tst.b %d11825bne.b _L7_2s1826bsr.l sasin # operand is a NORM1827bra.b _L7_6s1828_L7_2s:1829cmpi.b %d1,&ZERO # is operand a ZERO?1830bne.b _L7_3s # no1831bsr.l src_zero # yes1832bra.b _L7_6s1833_L7_3s:1834cmpi.b %d1,&INF # is operand an INF?1835bne.b _L7_4s # no1836bsr.l t_operr # yes1837bra.b _L7_6s1838_L7_4s:1839cmpi.b %d1,&QNAN # is operand a QNAN?1840bne.b _L7_5s # no1841bsr.l src_qnan # yes1842bra.b _L7_6s1843_L7_5s:1844bsr.l sasind # operand is a DENORM1845_L7_6s:18461847#1848# Result is now in FP01849#1850movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a11851fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs1852fmovm.x EXC_FP1(%a6),&0x40 # restore fp11853unlk %a61854rts18551856global _fasind_1857_fasind_:1858link %a6,&-LOCAL_SIZE18591860movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a11861fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs1862fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp118631864fmov.l &0x0,%fpcr # zero FPCR18651866#1867# copy, convert, and tag input argument1868#1869fmov.d 0x8(%a6),%fp0 # load dbl input1870fmov.x %fp0,FP_SRC(%a6)1871lea FP_SRC(%a6),%a01872bsr.l tag # fetch operand type1873mov.b %d0,STAG(%a6)1874mov.b %d0,%d118751876andi.l &0x00ff00ff,USER_FPSR(%a6)18771878clr.l %d01879mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec18801881mov.b %d1,STAG(%a6)1882tst.b %d11883bne.b _L7_2d1884bsr.l sasin # operand is a NORM1885bra.b _L7_6d1886_L7_2d:1887cmpi.b %d1,&ZERO # is operand a ZERO?1888bne.b _L7_3d # no1889bsr.l src_zero # yes1890bra.b _L7_6d1891_L7_3d:1892cmpi.b %d1,&INF # is operand an INF?1893bne.b _L7_4d # no1894bsr.l t_operr # yes1895bra.b _L7_6d1896_L7_4d:1897cmpi.b %d1,&QNAN # is operand a QNAN?1898bne.b _L7_5d # no1899bsr.l src_qnan # yes1900bra.b _L7_6d1901_L7_5d:1902bsr.l sasind # operand is a DENORM1903_L7_6d:19041905#1906# Result is now in FP01907#1908movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a11909fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs1910fmovm.x EXC_FP1(%a6),&0x40 # restore fp11911unlk %a61912rts19131914global _fasinx_1915_fasinx_:1916link %a6,&-LOCAL_SIZE19171918movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a11919fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs1920fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp119211922fmov.l &0x0,%fpcr # zero FPCR19231924#1925# copy, convert, and tag input argument1926#1927lea FP_SRC(%a6),%a01928mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input1929mov.l 0x8+0x4(%a6),0x4(%a0)1930mov.l 0x8+0x8(%a6),0x8(%a0)1931bsr.l tag # fetch operand type1932mov.b %d0,STAG(%a6)1933mov.b %d0,%d119341935andi.l &0x00ff00ff,USER_FPSR(%a6)19361937clr.l %d01938mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec19391940tst.b %d11941bne.b _L7_2x1942bsr.l sasin # operand is a NORM1943bra.b _L7_6x1944_L7_2x:1945cmpi.b %d1,&ZERO # is operand a ZERO?1946bne.b _L7_3x # no1947bsr.l src_zero # yes1948bra.b _L7_6x1949_L7_3x:1950cmpi.b %d1,&INF # is operand an INF?1951bne.b _L7_4x # no1952bsr.l t_operr # yes1953bra.b _L7_6x1954_L7_4x:1955cmpi.b %d1,&QNAN # is operand a QNAN?1956bne.b _L7_5x # no1957bsr.l src_qnan # yes1958bra.b _L7_6x1959_L7_5x:1960bsr.l sasind # operand is a DENORM1961_L7_6x:19621963#1964# Result is now in FP01965#1966movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a11967fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs1968fmovm.x EXC_FP1(%a6),&0x40 # restore fp11969unlk %a61970rts197119721973#########################################################################1974# MONADIC TEMPLATE #1975#########################################################################1976global _fatanhs_1977_fatanhs_:1978link %a6,&-LOCAL_SIZE19791980movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a11981fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs1982fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp119831984fmov.l &0x0,%fpcr # zero FPCR19851986#1987# copy, convert, and tag input argument1988#1989fmov.s 0x8(%a6),%fp0 # load sgl input1990fmov.x %fp0,FP_SRC(%a6)1991lea FP_SRC(%a6),%a01992bsr.l tag # fetch operand type1993mov.b %d0,STAG(%a6)1994mov.b %d0,%d119951996andi.l &0x00ff00ff,USER_FPSR(%a6)19971998clr.l %d01999mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec20002001tst.b %d12002bne.b _L8_2s2003bsr.l satanh # operand is a NORM2004bra.b _L8_6s2005_L8_2s:2006cmpi.b %d1,&ZERO # is operand a ZERO?2007bne.b _L8_3s # no2008bsr.l src_zero # yes2009bra.b _L8_6s2010_L8_3s:2011cmpi.b %d1,&INF # is operand an INF?2012bne.b _L8_4s # no2013bsr.l t_operr # yes2014bra.b _L8_6s2015_L8_4s:2016cmpi.b %d1,&QNAN # is operand a QNAN?2017bne.b _L8_5s # no2018bsr.l src_qnan # yes2019bra.b _L8_6s2020_L8_5s:2021bsr.l satanhd # operand is a DENORM2022_L8_6s:20232024#2025# Result is now in FP02026#2027movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a12028fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs2029fmovm.x EXC_FP1(%a6),&0x40 # restore fp12030unlk %a62031rts20322033global _fatanhd_2034_fatanhd_:2035link %a6,&-LOCAL_SIZE20362037movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a12038fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs2039fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp120402041fmov.l &0x0,%fpcr # zero FPCR20422043#2044# copy, convert, and tag input argument2045#2046fmov.d 0x8(%a6),%fp0 # load dbl input2047fmov.x %fp0,FP_SRC(%a6)2048lea FP_SRC(%a6),%a02049bsr.l tag # fetch operand type2050mov.b %d0,STAG(%a6)2051mov.b %d0,%d120522053andi.l &0x00ff00ff,USER_FPSR(%a6)20542055clr.l %d02056mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec20572058mov.b %d1,STAG(%a6)2059tst.b %d12060bne.b _L8_2d2061bsr.l satanh # operand is a NORM2062bra.b _L8_6d2063_L8_2d:2064cmpi.b %d1,&ZERO # is operand a ZERO?2065bne.b _L8_3d # no2066bsr.l src_zero # yes2067bra.b _L8_6d2068_L8_3d:2069cmpi.b %d1,&INF # is operand an INF?2070bne.b _L8_4d # no2071bsr.l t_operr # yes2072bra.b _L8_6d2073_L8_4d:2074cmpi.b %d1,&QNAN # is operand a QNAN?2075bne.b _L8_5d # no2076bsr.l src_qnan # yes2077bra.b _L8_6d2078_L8_5d:2079bsr.l satanhd # operand is a DENORM2080_L8_6d:20812082#2083# Result is now in FP02084#2085movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a12086fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs2087fmovm.x EXC_FP1(%a6),&0x40 # restore fp12088unlk %a62089rts20902091global _fatanhx_2092_fatanhx_:2093link %a6,&-LOCAL_SIZE20942095movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a12096fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs2097fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp120982099fmov.l &0x0,%fpcr # zero FPCR21002101#2102# copy, convert, and tag input argument2103#2104lea FP_SRC(%a6),%a02105mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input2106mov.l 0x8+0x4(%a6),0x4(%a0)2107mov.l 0x8+0x8(%a6),0x8(%a0)2108bsr.l tag # fetch operand type2109mov.b %d0,STAG(%a6)2110mov.b %d0,%d121112112andi.l &0x00ff00ff,USER_FPSR(%a6)21132114clr.l %d02115mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec21162117tst.b %d12118bne.b _L8_2x2119bsr.l satanh # operand is a NORM2120bra.b _L8_6x2121_L8_2x:2122cmpi.b %d1,&ZERO # is operand a ZERO?2123bne.b _L8_3x # no2124bsr.l src_zero # yes2125bra.b _L8_6x2126_L8_3x:2127cmpi.b %d1,&INF # is operand an INF?2128bne.b _L8_4x # no2129bsr.l t_operr # yes2130bra.b _L8_6x2131_L8_4x:2132cmpi.b %d1,&QNAN # is operand a QNAN?2133bne.b _L8_5x # no2134bsr.l src_qnan # yes2135bra.b _L8_6x2136_L8_5x:2137bsr.l satanhd # operand is a DENORM2138_L8_6x:21392140#2141# Result is now in FP02142#2143movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a12144fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs2145fmovm.x EXC_FP1(%a6),&0x40 # restore fp12146unlk %a62147rts214821492150#########################################################################2151# MONADIC TEMPLATE #2152#########################################################################2153global _ftans_2154_ftans_:2155link %a6,&-LOCAL_SIZE21562157movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a12158fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs2159fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp121602161fmov.l &0x0,%fpcr # zero FPCR21622163#2164# copy, convert, and tag input argument2165#2166fmov.s 0x8(%a6),%fp0 # load sgl input2167fmov.x %fp0,FP_SRC(%a6)2168lea FP_SRC(%a6),%a02169bsr.l tag # fetch operand type2170mov.b %d0,STAG(%a6)2171mov.b %d0,%d121722173andi.l &0x00ff00ff,USER_FPSR(%a6)21742175clr.l %d02176mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec21772178tst.b %d12179bne.b _L9_2s2180bsr.l stan # operand is a NORM2181bra.b _L9_6s2182_L9_2s:2183cmpi.b %d1,&ZERO # is operand a ZERO?2184bne.b _L9_3s # no2185bsr.l src_zero # yes2186bra.b _L9_6s2187_L9_3s:2188cmpi.b %d1,&INF # is operand an INF?2189bne.b _L9_4s # no2190bsr.l t_operr # yes2191bra.b _L9_6s2192_L9_4s:2193cmpi.b %d1,&QNAN # is operand a QNAN?2194bne.b _L9_5s # no2195bsr.l src_qnan # yes2196bra.b _L9_6s2197_L9_5s:2198bsr.l stand # operand is a DENORM2199_L9_6s:22002201#2202# Result is now in FP02203#2204movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a12205fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs2206fmovm.x EXC_FP1(%a6),&0x40 # restore fp12207unlk %a62208rts22092210global _ftand_2211_ftand_:2212link %a6,&-LOCAL_SIZE22132214movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a12215fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs2216fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp122172218fmov.l &0x0,%fpcr # zero FPCR22192220#2221# copy, convert, and tag input argument2222#2223fmov.d 0x8(%a6),%fp0 # load dbl input2224fmov.x %fp0,FP_SRC(%a6)2225lea FP_SRC(%a6),%a02226bsr.l tag # fetch operand type2227mov.b %d0,STAG(%a6)2228mov.b %d0,%d122292230andi.l &0x00ff00ff,USER_FPSR(%a6)22312232clr.l %d02233mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec22342235mov.b %d1,STAG(%a6)2236tst.b %d12237bne.b _L9_2d2238bsr.l stan # operand is a NORM2239bra.b _L9_6d2240_L9_2d:2241cmpi.b %d1,&ZERO # is operand a ZERO?2242bne.b _L9_3d # no2243bsr.l src_zero # yes2244bra.b _L9_6d2245_L9_3d:2246cmpi.b %d1,&INF # is operand an INF?2247bne.b _L9_4d # no2248bsr.l t_operr # yes2249bra.b _L9_6d2250_L9_4d:2251cmpi.b %d1,&QNAN # is operand a QNAN?2252bne.b _L9_5d # no2253bsr.l src_qnan # yes2254bra.b _L9_6d2255_L9_5d:2256bsr.l stand # operand is a DENORM2257_L9_6d:22582259#2260# Result is now in FP02261#2262movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a12263fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs2264fmovm.x EXC_FP1(%a6),&0x40 # restore fp12265unlk %a62266rts22672268global _ftanx_2269_ftanx_:2270link %a6,&-LOCAL_SIZE22712272movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a12273fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs2274fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp122752276fmov.l &0x0,%fpcr # zero FPCR22772278#2279# copy, convert, and tag input argument2280#2281lea FP_SRC(%a6),%a02282mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input2283mov.l 0x8+0x4(%a6),0x4(%a0)2284mov.l 0x8+0x8(%a6),0x8(%a0)2285bsr.l tag # fetch operand type2286mov.b %d0,STAG(%a6)2287mov.b %d0,%d122882289andi.l &0x00ff00ff,USER_FPSR(%a6)22902291clr.l %d02292mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec22932294tst.b %d12295bne.b _L9_2x2296bsr.l stan # operand is a NORM2297bra.b _L9_6x2298_L9_2x:2299cmpi.b %d1,&ZERO # is operand a ZERO?2300bne.b _L9_3x # no2301bsr.l src_zero # yes2302bra.b _L9_6x2303_L9_3x:2304cmpi.b %d1,&INF # is operand an INF?2305bne.b _L9_4x # no2306bsr.l t_operr # yes2307bra.b _L9_6x2308_L9_4x:2309cmpi.b %d1,&QNAN # is operand a QNAN?2310bne.b _L9_5x # no2311bsr.l src_qnan # yes2312bra.b _L9_6x2313_L9_5x:2314bsr.l stand # operand is a DENORM2315_L9_6x:23162317#2318# Result is now in FP02319#2320movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a12321fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs2322fmovm.x EXC_FP1(%a6),&0x40 # restore fp12323unlk %a62324rts232523262327#########################################################################2328# MONADIC TEMPLATE #2329#########################################################################2330global _fetoxs_2331_fetoxs_:2332link %a6,&-LOCAL_SIZE23332334movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a12335fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs2336fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp123372338fmov.l &0x0,%fpcr # zero FPCR23392340#2341# copy, convert, and tag input argument2342#2343fmov.s 0x8(%a6),%fp0 # load sgl input2344fmov.x %fp0,FP_SRC(%a6)2345lea FP_SRC(%a6),%a02346bsr.l tag # fetch operand type2347mov.b %d0,STAG(%a6)2348mov.b %d0,%d123492350andi.l &0x00ff00ff,USER_FPSR(%a6)23512352clr.l %d02353mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec23542355tst.b %d12356bne.b _L10_2s2357bsr.l setox # operand is a NORM2358bra.b _L10_6s2359_L10_2s:2360cmpi.b %d1,&ZERO # is operand a ZERO?2361bne.b _L10_3s # no2362bsr.l ld_pone # yes2363bra.b _L10_6s2364_L10_3s:2365cmpi.b %d1,&INF # is operand an INF?2366bne.b _L10_4s # no2367bsr.l szr_inf # yes2368bra.b _L10_6s2369_L10_4s:2370cmpi.b %d1,&QNAN # is operand a QNAN?2371bne.b _L10_5s # no2372bsr.l src_qnan # yes2373bra.b _L10_6s2374_L10_5s:2375bsr.l setoxd # operand is a DENORM2376_L10_6s:23772378#2379# Result is now in FP02380#2381movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a12382fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs2383fmovm.x EXC_FP1(%a6),&0x40 # restore fp12384unlk %a62385rts23862387global _fetoxd_2388_fetoxd_:2389link %a6,&-LOCAL_SIZE23902391movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a12392fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs2393fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp123942395fmov.l &0x0,%fpcr # zero FPCR23962397#2398# copy, convert, and tag input argument2399#2400fmov.d 0x8(%a6),%fp0 # load dbl input2401fmov.x %fp0,FP_SRC(%a6)2402lea FP_SRC(%a6),%a02403bsr.l tag # fetch operand type2404mov.b %d0,STAG(%a6)2405mov.b %d0,%d124062407andi.l &0x00ff00ff,USER_FPSR(%a6)24082409clr.l %d02410mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec24112412mov.b %d1,STAG(%a6)2413tst.b %d12414bne.b _L10_2d2415bsr.l setox # operand is a NORM2416bra.b _L10_6d2417_L10_2d:2418cmpi.b %d1,&ZERO # is operand a ZERO?2419bne.b _L10_3d # no2420bsr.l ld_pone # yes2421bra.b _L10_6d2422_L10_3d:2423cmpi.b %d1,&INF # is operand an INF?2424bne.b _L10_4d # no2425bsr.l szr_inf # yes2426bra.b _L10_6d2427_L10_4d:2428cmpi.b %d1,&QNAN # is operand a QNAN?2429bne.b _L10_5d # no2430bsr.l src_qnan # yes2431bra.b _L10_6d2432_L10_5d:2433bsr.l setoxd # operand is a DENORM2434_L10_6d:24352436#2437# Result is now in FP02438#2439movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a12440fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs2441fmovm.x EXC_FP1(%a6),&0x40 # restore fp12442unlk %a62443rts24442445global _fetoxx_2446_fetoxx_:2447link %a6,&-LOCAL_SIZE24482449movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a12450fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs2451fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp124522453fmov.l &0x0,%fpcr # zero FPCR24542455#2456# copy, convert, and tag input argument2457#2458lea FP_SRC(%a6),%a02459mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input2460mov.l 0x8+0x4(%a6),0x4(%a0)2461mov.l 0x8+0x8(%a6),0x8(%a0)2462bsr.l tag # fetch operand type2463mov.b %d0,STAG(%a6)2464mov.b %d0,%d124652466andi.l &0x00ff00ff,USER_FPSR(%a6)24672468clr.l %d02469mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec24702471tst.b %d12472bne.b _L10_2x2473bsr.l setox # operand is a NORM2474bra.b _L10_6x2475_L10_2x:2476cmpi.b %d1,&ZERO # is operand a ZERO?2477bne.b _L10_3x # no2478bsr.l ld_pone # yes2479bra.b _L10_6x2480_L10_3x:2481cmpi.b %d1,&INF # is operand an INF?2482bne.b _L10_4x # no2483bsr.l szr_inf # yes2484bra.b _L10_6x2485_L10_4x:2486cmpi.b %d1,&QNAN # is operand a QNAN?2487bne.b _L10_5x # no2488bsr.l src_qnan # yes2489bra.b _L10_6x2490_L10_5x:2491bsr.l setoxd # operand is a DENORM2492_L10_6x:24932494#2495# Result is now in FP02496#2497movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a12498fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs2499fmovm.x EXC_FP1(%a6),&0x40 # restore fp12500unlk %a62501rts250225032504#########################################################################2505# MONADIC TEMPLATE #2506#########################################################################2507global _ftwotoxs_2508_ftwotoxs_:2509link %a6,&-LOCAL_SIZE25102511movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a12512fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs2513fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp125142515fmov.l &0x0,%fpcr # zero FPCR25162517#2518# copy, convert, and tag input argument2519#2520fmov.s 0x8(%a6),%fp0 # load sgl input2521fmov.x %fp0,FP_SRC(%a6)2522lea FP_SRC(%a6),%a02523bsr.l tag # fetch operand type2524mov.b %d0,STAG(%a6)2525mov.b %d0,%d125262527andi.l &0x00ff00ff,USER_FPSR(%a6)25282529clr.l %d02530mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec25312532tst.b %d12533bne.b _L11_2s2534bsr.l stwotox # operand is a NORM2535bra.b _L11_6s2536_L11_2s:2537cmpi.b %d1,&ZERO # is operand a ZERO?2538bne.b _L11_3s # no2539bsr.l ld_pone # yes2540bra.b _L11_6s2541_L11_3s:2542cmpi.b %d1,&INF # is operand an INF?2543bne.b _L11_4s # no2544bsr.l szr_inf # yes2545bra.b _L11_6s2546_L11_4s:2547cmpi.b %d1,&QNAN # is operand a QNAN?2548bne.b _L11_5s # no2549bsr.l src_qnan # yes2550bra.b _L11_6s2551_L11_5s:2552bsr.l stwotoxd # operand is a DENORM2553_L11_6s:25542555#2556# Result is now in FP02557#2558movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a12559fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs2560fmovm.x EXC_FP1(%a6),&0x40 # restore fp12561unlk %a62562rts25632564global _ftwotoxd_2565_ftwotoxd_:2566link %a6,&-LOCAL_SIZE25672568movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a12569fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs2570fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp125712572fmov.l &0x0,%fpcr # zero FPCR25732574#2575# copy, convert, and tag input argument2576#2577fmov.d 0x8(%a6),%fp0 # load dbl input2578fmov.x %fp0,FP_SRC(%a6)2579lea FP_SRC(%a6),%a02580bsr.l tag # fetch operand type2581mov.b %d0,STAG(%a6)2582mov.b %d0,%d125832584andi.l &0x00ff00ff,USER_FPSR(%a6)25852586clr.l %d02587mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec25882589mov.b %d1,STAG(%a6)2590tst.b %d12591bne.b _L11_2d2592bsr.l stwotox # operand is a NORM2593bra.b _L11_6d2594_L11_2d:2595cmpi.b %d1,&ZERO # is operand a ZERO?2596bne.b _L11_3d # no2597bsr.l ld_pone # yes2598bra.b _L11_6d2599_L11_3d:2600cmpi.b %d1,&INF # is operand an INF?2601bne.b _L11_4d # no2602bsr.l szr_inf # yes2603bra.b _L11_6d2604_L11_4d:2605cmpi.b %d1,&QNAN # is operand a QNAN?2606bne.b _L11_5d # no2607bsr.l src_qnan # yes2608bra.b _L11_6d2609_L11_5d:2610bsr.l stwotoxd # operand is a DENORM2611_L11_6d:26122613#2614# Result is now in FP02615#2616movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a12617fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs2618fmovm.x EXC_FP1(%a6),&0x40 # restore fp12619unlk %a62620rts26212622global _ftwotoxx_2623_ftwotoxx_:2624link %a6,&-LOCAL_SIZE26252626movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a12627fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs2628fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp126292630fmov.l &0x0,%fpcr # zero FPCR26312632#2633# copy, convert, and tag input argument2634#2635lea FP_SRC(%a6),%a02636mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input2637mov.l 0x8+0x4(%a6),0x4(%a0)2638mov.l 0x8+0x8(%a6),0x8(%a0)2639bsr.l tag # fetch operand type2640mov.b %d0,STAG(%a6)2641mov.b %d0,%d126422643andi.l &0x00ff00ff,USER_FPSR(%a6)26442645clr.l %d02646mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec26472648tst.b %d12649bne.b _L11_2x2650bsr.l stwotox # operand is a NORM2651bra.b _L11_6x2652_L11_2x:2653cmpi.b %d1,&ZERO # is operand a ZERO?2654bne.b _L11_3x # no2655bsr.l ld_pone # yes2656bra.b _L11_6x2657_L11_3x:2658cmpi.b %d1,&INF # is operand an INF?2659bne.b _L11_4x # no2660bsr.l szr_inf # yes2661bra.b _L11_6x2662_L11_4x:2663cmpi.b %d1,&QNAN # is operand a QNAN?2664bne.b _L11_5x # no2665bsr.l src_qnan # yes2666bra.b _L11_6x2667_L11_5x:2668bsr.l stwotoxd # operand is a DENORM2669_L11_6x:26702671#2672# Result is now in FP02673#2674movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a12675fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs2676fmovm.x EXC_FP1(%a6),&0x40 # restore fp12677unlk %a62678rts267926802681#########################################################################2682# MONADIC TEMPLATE #2683#########################################################################2684global _ftentoxs_2685_ftentoxs_:2686link %a6,&-LOCAL_SIZE26872688movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a12689fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs2690fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp126912692fmov.l &0x0,%fpcr # zero FPCR26932694#2695# copy, convert, and tag input argument2696#2697fmov.s 0x8(%a6),%fp0 # load sgl input2698fmov.x %fp0,FP_SRC(%a6)2699lea FP_SRC(%a6),%a02700bsr.l tag # fetch operand type2701mov.b %d0,STAG(%a6)2702mov.b %d0,%d127032704andi.l &0x00ff00ff,USER_FPSR(%a6)27052706clr.l %d02707mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec27082709tst.b %d12710bne.b _L12_2s2711bsr.l stentox # operand is a NORM2712bra.b _L12_6s2713_L12_2s:2714cmpi.b %d1,&ZERO # is operand a ZERO?2715bne.b _L12_3s # no2716bsr.l ld_pone # yes2717bra.b _L12_6s2718_L12_3s:2719cmpi.b %d1,&INF # is operand an INF?2720bne.b _L12_4s # no2721bsr.l szr_inf # yes2722bra.b _L12_6s2723_L12_4s:2724cmpi.b %d1,&QNAN # is operand a QNAN?2725bne.b _L12_5s # no2726bsr.l src_qnan # yes2727bra.b _L12_6s2728_L12_5s:2729bsr.l stentoxd # operand is a DENORM2730_L12_6s:27312732#2733# Result is now in FP02734#2735movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a12736fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs2737fmovm.x EXC_FP1(%a6),&0x40 # restore fp12738unlk %a62739rts27402741global _ftentoxd_2742_ftentoxd_:2743link %a6,&-LOCAL_SIZE27442745movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a12746fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs2747fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp127482749fmov.l &0x0,%fpcr # zero FPCR27502751#2752# copy, convert, and tag input argument2753#2754fmov.d 0x8(%a6),%fp0 # load dbl input2755fmov.x %fp0,FP_SRC(%a6)2756lea FP_SRC(%a6),%a02757bsr.l tag # fetch operand type2758mov.b %d0,STAG(%a6)2759mov.b %d0,%d127602761andi.l &0x00ff00ff,USER_FPSR(%a6)27622763clr.l %d02764mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec27652766mov.b %d1,STAG(%a6)2767tst.b %d12768bne.b _L12_2d2769bsr.l stentox # operand is a NORM2770bra.b _L12_6d2771_L12_2d:2772cmpi.b %d1,&ZERO # is operand a ZERO?2773bne.b _L12_3d # no2774bsr.l ld_pone # yes2775bra.b _L12_6d2776_L12_3d:2777cmpi.b %d1,&INF # is operand an INF?2778bne.b _L12_4d # no2779bsr.l szr_inf # yes2780bra.b _L12_6d2781_L12_4d:2782cmpi.b %d1,&QNAN # is operand a QNAN?2783bne.b _L12_5d # no2784bsr.l src_qnan # yes2785bra.b _L12_6d2786_L12_5d:2787bsr.l stentoxd # operand is a DENORM2788_L12_6d:27892790#2791# Result is now in FP02792#2793movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a12794fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs2795fmovm.x EXC_FP1(%a6),&0x40 # restore fp12796unlk %a62797rts27982799global _ftentoxx_2800_ftentoxx_:2801link %a6,&-LOCAL_SIZE28022803movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a12804fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs2805fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp128062807fmov.l &0x0,%fpcr # zero FPCR28082809#2810# copy, convert, and tag input argument2811#2812lea FP_SRC(%a6),%a02813mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input2814mov.l 0x8+0x4(%a6),0x4(%a0)2815mov.l 0x8+0x8(%a6),0x8(%a0)2816bsr.l tag # fetch operand type2817mov.b %d0,STAG(%a6)2818mov.b %d0,%d128192820andi.l &0x00ff00ff,USER_FPSR(%a6)28212822clr.l %d02823mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec28242825tst.b %d12826bne.b _L12_2x2827bsr.l stentox # operand is a NORM2828bra.b _L12_6x2829_L12_2x:2830cmpi.b %d1,&ZERO # is operand a ZERO?2831bne.b _L12_3x # no2832bsr.l ld_pone # yes2833bra.b _L12_6x2834_L12_3x:2835cmpi.b %d1,&INF # is operand an INF?2836bne.b _L12_4x # no2837bsr.l szr_inf # yes2838bra.b _L12_6x2839_L12_4x:2840cmpi.b %d1,&QNAN # is operand a QNAN?2841bne.b _L12_5x # no2842bsr.l src_qnan # yes2843bra.b _L12_6x2844_L12_5x:2845bsr.l stentoxd # operand is a DENORM2846_L12_6x:28472848#2849# Result is now in FP02850#2851movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a12852fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs2853fmovm.x EXC_FP1(%a6),&0x40 # restore fp12854unlk %a62855rts285628572858#########################################################################2859# MONADIC TEMPLATE #2860#########################################################################2861global _flogns_2862_flogns_:2863link %a6,&-LOCAL_SIZE28642865movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a12866fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs2867fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp128682869fmov.l &0x0,%fpcr # zero FPCR28702871#2872# copy, convert, and tag input argument2873#2874fmov.s 0x8(%a6),%fp0 # load sgl input2875fmov.x %fp0,FP_SRC(%a6)2876lea FP_SRC(%a6),%a02877bsr.l tag # fetch operand type2878mov.b %d0,STAG(%a6)2879mov.b %d0,%d128802881andi.l &0x00ff00ff,USER_FPSR(%a6)28822883clr.l %d02884mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec28852886tst.b %d12887bne.b _L13_2s2888bsr.l slogn # operand is a NORM2889bra.b _L13_6s2890_L13_2s:2891cmpi.b %d1,&ZERO # is operand a ZERO?2892bne.b _L13_3s # no2893bsr.l t_dz2 # yes2894bra.b _L13_6s2895_L13_3s:2896cmpi.b %d1,&INF # is operand an INF?2897bne.b _L13_4s # no2898bsr.l sopr_inf # yes2899bra.b _L13_6s2900_L13_4s:2901cmpi.b %d1,&QNAN # is operand a QNAN?2902bne.b _L13_5s # no2903bsr.l src_qnan # yes2904bra.b _L13_6s2905_L13_5s:2906bsr.l slognd # operand is a DENORM2907_L13_6s:29082909#2910# Result is now in FP02911#2912movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a12913fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs2914fmovm.x EXC_FP1(%a6),&0x40 # restore fp12915unlk %a62916rts29172918global _flognd_2919_flognd_:2920link %a6,&-LOCAL_SIZE29212922movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a12923fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs2924fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp129252926fmov.l &0x0,%fpcr # zero FPCR29272928#2929# copy, convert, and tag input argument2930#2931fmov.d 0x8(%a6),%fp0 # load dbl input2932fmov.x %fp0,FP_SRC(%a6)2933lea FP_SRC(%a6),%a02934bsr.l tag # fetch operand type2935mov.b %d0,STAG(%a6)2936mov.b %d0,%d129372938andi.l &0x00ff00ff,USER_FPSR(%a6)29392940clr.l %d02941mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec29422943mov.b %d1,STAG(%a6)2944tst.b %d12945bne.b _L13_2d2946bsr.l slogn # operand is a NORM2947bra.b _L13_6d2948_L13_2d:2949cmpi.b %d1,&ZERO # is operand a ZERO?2950bne.b _L13_3d # no2951bsr.l t_dz2 # yes2952bra.b _L13_6d2953_L13_3d:2954cmpi.b %d1,&INF # is operand an INF?2955bne.b _L13_4d # no2956bsr.l sopr_inf # yes2957bra.b _L13_6d2958_L13_4d:2959cmpi.b %d1,&QNAN # is operand a QNAN?2960bne.b _L13_5d # no2961bsr.l src_qnan # yes2962bra.b _L13_6d2963_L13_5d:2964bsr.l slognd # operand is a DENORM2965_L13_6d:29662967#2968# Result is now in FP02969#2970movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a12971fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs2972fmovm.x EXC_FP1(%a6),&0x40 # restore fp12973unlk %a62974rts29752976global _flognx_2977_flognx_:2978link %a6,&-LOCAL_SIZE29792980movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a12981fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs2982fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp129832984fmov.l &0x0,%fpcr # zero FPCR29852986#2987# copy, convert, and tag input argument2988#2989lea FP_SRC(%a6),%a02990mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input2991mov.l 0x8+0x4(%a6),0x4(%a0)2992mov.l 0x8+0x8(%a6),0x8(%a0)2993bsr.l tag # fetch operand type2994mov.b %d0,STAG(%a6)2995mov.b %d0,%d129962997andi.l &0x00ff00ff,USER_FPSR(%a6)29982999clr.l %d03000mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec30013002tst.b %d13003bne.b _L13_2x3004bsr.l slogn # operand is a NORM3005bra.b _L13_6x3006_L13_2x:3007cmpi.b %d1,&ZERO # is operand a ZERO?3008bne.b _L13_3x # no3009bsr.l t_dz2 # yes3010bra.b _L13_6x3011_L13_3x:3012cmpi.b %d1,&INF # is operand an INF?3013bne.b _L13_4x # no3014bsr.l sopr_inf # yes3015bra.b _L13_6x3016_L13_4x:3017cmpi.b %d1,&QNAN # is operand a QNAN?3018bne.b _L13_5x # no3019bsr.l src_qnan # yes3020bra.b _L13_6x3021_L13_5x:3022bsr.l slognd # operand is a DENORM3023_L13_6x:30243025#3026# Result is now in FP03027#3028movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a13029fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs3030fmovm.x EXC_FP1(%a6),&0x40 # restore fp13031unlk %a63032rts303330343035#########################################################################3036# MONADIC TEMPLATE #3037#########################################################################3038global _flog10s_3039_flog10s_:3040link %a6,&-LOCAL_SIZE30413042movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a13043fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs3044fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp130453046fmov.l &0x0,%fpcr # zero FPCR30473048#3049# copy, convert, and tag input argument3050#3051fmov.s 0x8(%a6),%fp0 # load sgl input3052fmov.x %fp0,FP_SRC(%a6)3053lea FP_SRC(%a6),%a03054bsr.l tag # fetch operand type3055mov.b %d0,STAG(%a6)3056mov.b %d0,%d130573058andi.l &0x00ff00ff,USER_FPSR(%a6)30593060clr.l %d03061mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec30623063tst.b %d13064bne.b _L14_2s3065bsr.l slog10 # operand is a NORM3066bra.b _L14_6s3067_L14_2s:3068cmpi.b %d1,&ZERO # is operand a ZERO?3069bne.b _L14_3s # no3070bsr.l t_dz2 # yes3071bra.b _L14_6s3072_L14_3s:3073cmpi.b %d1,&INF # is operand an INF?3074bne.b _L14_4s # no3075bsr.l sopr_inf # yes3076bra.b _L14_6s3077_L14_4s:3078cmpi.b %d1,&QNAN # is operand a QNAN?3079bne.b _L14_5s # no3080bsr.l src_qnan # yes3081bra.b _L14_6s3082_L14_5s:3083bsr.l slog10d # operand is a DENORM3084_L14_6s:30853086#3087# Result is now in FP03088#3089movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a13090fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs3091fmovm.x EXC_FP1(%a6),&0x40 # restore fp13092unlk %a63093rts30943095global _flog10d_3096_flog10d_:3097link %a6,&-LOCAL_SIZE30983099movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a13100fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs3101fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp131023103fmov.l &0x0,%fpcr # zero FPCR31043105#3106# copy, convert, and tag input argument3107#3108fmov.d 0x8(%a6),%fp0 # load dbl input3109fmov.x %fp0,FP_SRC(%a6)3110lea FP_SRC(%a6),%a03111bsr.l tag # fetch operand type3112mov.b %d0,STAG(%a6)3113mov.b %d0,%d131143115andi.l &0x00ff00ff,USER_FPSR(%a6)31163117clr.l %d03118mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec31193120mov.b %d1,STAG(%a6)3121tst.b %d13122bne.b _L14_2d3123bsr.l slog10 # operand is a NORM3124bra.b _L14_6d3125_L14_2d:3126cmpi.b %d1,&ZERO # is operand a ZERO?3127bne.b _L14_3d # no3128bsr.l t_dz2 # yes3129bra.b _L14_6d3130_L14_3d:3131cmpi.b %d1,&INF # is operand an INF?3132bne.b _L14_4d # no3133bsr.l sopr_inf # yes3134bra.b _L14_6d3135_L14_4d:3136cmpi.b %d1,&QNAN # is operand a QNAN?3137bne.b _L14_5d # no3138bsr.l src_qnan # yes3139bra.b _L14_6d3140_L14_5d:3141bsr.l slog10d # operand is a DENORM3142_L14_6d:31433144#3145# Result is now in FP03146#3147movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a13148fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs3149fmovm.x EXC_FP1(%a6),&0x40 # restore fp13150unlk %a63151rts31523153global _flog10x_3154_flog10x_:3155link %a6,&-LOCAL_SIZE31563157movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a13158fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs3159fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp131603161fmov.l &0x0,%fpcr # zero FPCR31623163#3164# copy, convert, and tag input argument3165#3166lea FP_SRC(%a6),%a03167mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input3168mov.l 0x8+0x4(%a6),0x4(%a0)3169mov.l 0x8+0x8(%a6),0x8(%a0)3170bsr.l tag # fetch operand type3171mov.b %d0,STAG(%a6)3172mov.b %d0,%d131733174andi.l &0x00ff00ff,USER_FPSR(%a6)31753176clr.l %d03177mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec31783179tst.b %d13180bne.b _L14_2x3181bsr.l slog10 # operand is a NORM3182bra.b _L14_6x3183_L14_2x:3184cmpi.b %d1,&ZERO # is operand a ZERO?3185bne.b _L14_3x # no3186bsr.l t_dz2 # yes3187bra.b _L14_6x3188_L14_3x:3189cmpi.b %d1,&INF # is operand an INF?3190bne.b _L14_4x # no3191bsr.l sopr_inf # yes3192bra.b _L14_6x3193_L14_4x:3194cmpi.b %d1,&QNAN # is operand a QNAN?3195bne.b _L14_5x # no3196bsr.l src_qnan # yes3197bra.b _L14_6x3198_L14_5x:3199bsr.l slog10d # operand is a DENORM3200_L14_6x:32013202#3203# Result is now in FP03204#3205movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a13206fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs3207fmovm.x EXC_FP1(%a6),&0x40 # restore fp13208unlk %a63209rts321032113212#########################################################################3213# MONADIC TEMPLATE #3214#########################################################################3215global _flog2s_3216_flog2s_:3217link %a6,&-LOCAL_SIZE32183219movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a13220fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs3221fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp132223223fmov.l &0x0,%fpcr # zero FPCR32243225#3226# copy, convert, and tag input argument3227#3228fmov.s 0x8(%a6),%fp0 # load sgl input3229fmov.x %fp0,FP_SRC(%a6)3230lea FP_SRC(%a6),%a03231bsr.l tag # fetch operand type3232mov.b %d0,STAG(%a6)3233mov.b %d0,%d132343235andi.l &0x00ff00ff,USER_FPSR(%a6)32363237clr.l %d03238mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec32393240tst.b %d13241bne.b _L15_2s3242bsr.l slog2 # operand is a NORM3243bra.b _L15_6s3244_L15_2s:3245cmpi.b %d1,&ZERO # is operand a ZERO?3246bne.b _L15_3s # no3247bsr.l t_dz2 # yes3248bra.b _L15_6s3249_L15_3s:3250cmpi.b %d1,&INF # is operand an INF?3251bne.b _L15_4s # no3252bsr.l sopr_inf # yes3253bra.b _L15_6s3254_L15_4s:3255cmpi.b %d1,&QNAN # is operand a QNAN?3256bne.b _L15_5s # no3257bsr.l src_qnan # yes3258bra.b _L15_6s3259_L15_5s:3260bsr.l slog2d # operand is a DENORM3261_L15_6s:32623263#3264# Result is now in FP03265#3266movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a13267fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs3268fmovm.x EXC_FP1(%a6),&0x40 # restore fp13269unlk %a63270rts32713272global _flog2d_3273_flog2d_:3274link %a6,&-LOCAL_SIZE32753276movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a13277fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs3278fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp132793280fmov.l &0x0,%fpcr # zero FPCR32813282#3283# copy, convert, and tag input argument3284#3285fmov.d 0x8(%a6),%fp0 # load dbl input3286fmov.x %fp0,FP_SRC(%a6)3287lea FP_SRC(%a6),%a03288bsr.l tag # fetch operand type3289mov.b %d0,STAG(%a6)3290mov.b %d0,%d132913292andi.l &0x00ff00ff,USER_FPSR(%a6)32933294clr.l %d03295mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec32963297mov.b %d1,STAG(%a6)3298tst.b %d13299bne.b _L15_2d3300bsr.l slog2 # operand is a NORM3301bra.b _L15_6d3302_L15_2d:3303cmpi.b %d1,&ZERO # is operand a ZERO?3304bne.b _L15_3d # no3305bsr.l t_dz2 # yes3306bra.b _L15_6d3307_L15_3d:3308cmpi.b %d1,&INF # is operand an INF?3309bne.b _L15_4d # no3310bsr.l sopr_inf # yes3311bra.b _L15_6d3312_L15_4d:3313cmpi.b %d1,&QNAN # is operand a QNAN?3314bne.b _L15_5d # no3315bsr.l src_qnan # yes3316bra.b _L15_6d3317_L15_5d:3318bsr.l slog2d # operand is a DENORM3319_L15_6d:33203321#3322# Result is now in FP03323#3324movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a13325fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs3326fmovm.x EXC_FP1(%a6),&0x40 # restore fp13327unlk %a63328rts33293330global _flog2x_3331_flog2x_:3332link %a6,&-LOCAL_SIZE33333334movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a13335fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs3336fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp133373338fmov.l &0x0,%fpcr # zero FPCR33393340#3341# copy, convert, and tag input argument3342#3343lea FP_SRC(%a6),%a03344mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input3345mov.l 0x8+0x4(%a6),0x4(%a0)3346mov.l 0x8+0x8(%a6),0x8(%a0)3347bsr.l tag # fetch operand type3348mov.b %d0,STAG(%a6)3349mov.b %d0,%d133503351andi.l &0x00ff00ff,USER_FPSR(%a6)33523353clr.l %d03354mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec33553356tst.b %d13357bne.b _L15_2x3358bsr.l slog2 # operand is a NORM3359bra.b _L15_6x3360_L15_2x:3361cmpi.b %d1,&ZERO # is operand a ZERO?3362bne.b _L15_3x # no3363bsr.l t_dz2 # yes3364bra.b _L15_6x3365_L15_3x:3366cmpi.b %d1,&INF # is operand an INF?3367bne.b _L15_4x # no3368bsr.l sopr_inf # yes3369bra.b _L15_6x3370_L15_4x:3371cmpi.b %d1,&QNAN # is operand a QNAN?3372bne.b _L15_5x # no3373bsr.l src_qnan # yes3374bra.b _L15_6x3375_L15_5x:3376bsr.l slog2d # operand is a DENORM3377_L15_6x:33783379#3380# Result is now in FP03381#3382movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a13383fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs3384fmovm.x EXC_FP1(%a6),&0x40 # restore fp13385unlk %a63386rts338733883389#########################################################################3390# MONADIC TEMPLATE #3391#########################################################################3392global _fcoshs_3393_fcoshs_:3394link %a6,&-LOCAL_SIZE33953396movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a13397fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs3398fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp133993400fmov.l &0x0,%fpcr # zero FPCR34013402#3403# copy, convert, and tag input argument3404#3405fmov.s 0x8(%a6),%fp0 # load sgl input3406fmov.x %fp0,FP_SRC(%a6)3407lea FP_SRC(%a6),%a03408bsr.l tag # fetch operand type3409mov.b %d0,STAG(%a6)3410mov.b %d0,%d134113412andi.l &0x00ff00ff,USER_FPSR(%a6)34133414clr.l %d03415mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec34163417tst.b %d13418bne.b _L16_2s3419bsr.l scosh # operand is a NORM3420bra.b _L16_6s3421_L16_2s:3422cmpi.b %d1,&ZERO # is operand a ZERO?3423bne.b _L16_3s # no3424bsr.l ld_pone # yes3425bra.b _L16_6s3426_L16_3s:3427cmpi.b %d1,&INF # is operand an INF?3428bne.b _L16_4s # no3429bsr.l ld_pinf # yes3430bra.b _L16_6s3431_L16_4s:3432cmpi.b %d1,&QNAN # is operand a QNAN?3433bne.b _L16_5s # no3434bsr.l src_qnan # yes3435bra.b _L16_6s3436_L16_5s:3437bsr.l scoshd # operand is a DENORM3438_L16_6s:34393440#3441# Result is now in FP03442#3443movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a13444fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs3445fmovm.x EXC_FP1(%a6),&0x40 # restore fp13446unlk %a63447rts34483449global _fcoshd_3450_fcoshd_:3451link %a6,&-LOCAL_SIZE34523453movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a13454fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs3455fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp134563457fmov.l &0x0,%fpcr # zero FPCR34583459#3460# copy, convert, and tag input argument3461#3462fmov.d 0x8(%a6),%fp0 # load dbl input3463fmov.x %fp0,FP_SRC(%a6)3464lea FP_SRC(%a6),%a03465bsr.l tag # fetch operand type3466mov.b %d0,STAG(%a6)3467mov.b %d0,%d134683469andi.l &0x00ff00ff,USER_FPSR(%a6)34703471clr.l %d03472mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec34733474mov.b %d1,STAG(%a6)3475tst.b %d13476bne.b _L16_2d3477bsr.l scosh # operand is a NORM3478bra.b _L16_6d3479_L16_2d:3480cmpi.b %d1,&ZERO # is operand a ZERO?3481bne.b _L16_3d # no3482bsr.l ld_pone # yes3483bra.b _L16_6d3484_L16_3d:3485cmpi.b %d1,&INF # is operand an INF?3486bne.b _L16_4d # no3487bsr.l ld_pinf # yes3488bra.b _L16_6d3489_L16_4d:3490cmpi.b %d1,&QNAN # is operand a QNAN?3491bne.b _L16_5d # no3492bsr.l src_qnan # yes3493bra.b _L16_6d3494_L16_5d:3495bsr.l scoshd # operand is a DENORM3496_L16_6d:34973498#3499# Result is now in FP03500#3501movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a13502fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs3503fmovm.x EXC_FP1(%a6),&0x40 # restore fp13504unlk %a63505rts35063507global _fcoshx_3508_fcoshx_:3509link %a6,&-LOCAL_SIZE35103511movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a13512fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs3513fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp135143515fmov.l &0x0,%fpcr # zero FPCR35163517#3518# copy, convert, and tag input argument3519#3520lea FP_SRC(%a6),%a03521mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input3522mov.l 0x8+0x4(%a6),0x4(%a0)3523mov.l 0x8+0x8(%a6),0x8(%a0)3524bsr.l tag # fetch operand type3525mov.b %d0,STAG(%a6)3526mov.b %d0,%d135273528andi.l &0x00ff00ff,USER_FPSR(%a6)35293530clr.l %d03531mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec35323533tst.b %d13534bne.b _L16_2x3535bsr.l scosh # operand is a NORM3536bra.b _L16_6x3537_L16_2x:3538cmpi.b %d1,&ZERO # is operand a ZERO?3539bne.b _L16_3x # no3540bsr.l ld_pone # yes3541bra.b _L16_6x3542_L16_3x:3543cmpi.b %d1,&INF # is operand an INF?3544bne.b _L16_4x # no3545bsr.l ld_pinf # yes3546bra.b _L16_6x3547_L16_4x:3548cmpi.b %d1,&QNAN # is operand a QNAN?3549bne.b _L16_5x # no3550bsr.l src_qnan # yes3551bra.b _L16_6x3552_L16_5x:3553bsr.l scoshd # operand is a DENORM3554_L16_6x:35553556#3557# Result is now in FP03558#3559movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a13560fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs3561fmovm.x EXC_FP1(%a6),&0x40 # restore fp13562unlk %a63563rts356435653566#########################################################################3567# MONADIC TEMPLATE #3568#########################################################################3569global _facoss_3570_facoss_:3571link %a6,&-LOCAL_SIZE35723573movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a13574fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs3575fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp135763577fmov.l &0x0,%fpcr # zero FPCR35783579#3580# copy, convert, and tag input argument3581#3582fmov.s 0x8(%a6),%fp0 # load sgl input3583fmov.x %fp0,FP_SRC(%a6)3584lea FP_SRC(%a6),%a03585bsr.l tag # fetch operand type3586mov.b %d0,STAG(%a6)3587mov.b %d0,%d135883589andi.l &0x00ff00ff,USER_FPSR(%a6)35903591clr.l %d03592mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec35933594tst.b %d13595bne.b _L17_2s3596bsr.l sacos # operand is a NORM3597bra.b _L17_6s3598_L17_2s:3599cmpi.b %d1,&ZERO # is operand a ZERO?3600bne.b _L17_3s # no3601bsr.l ld_ppi2 # yes3602bra.b _L17_6s3603_L17_3s:3604cmpi.b %d1,&INF # is operand an INF?3605bne.b _L17_4s # no3606bsr.l t_operr # yes3607bra.b _L17_6s3608_L17_4s:3609cmpi.b %d1,&QNAN # is operand a QNAN?3610bne.b _L17_5s # no3611bsr.l src_qnan # yes3612bra.b _L17_6s3613_L17_5s:3614bsr.l sacosd # operand is a DENORM3615_L17_6s:36163617#3618# Result is now in FP03619#3620movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a13621fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs3622fmovm.x EXC_FP1(%a6),&0x40 # restore fp13623unlk %a63624rts36253626global _facosd_3627_facosd_:3628link %a6,&-LOCAL_SIZE36293630movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a13631fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs3632fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp136333634fmov.l &0x0,%fpcr # zero FPCR36353636#3637# copy, convert, and tag input argument3638#3639fmov.d 0x8(%a6),%fp0 # load dbl input3640fmov.x %fp0,FP_SRC(%a6)3641lea FP_SRC(%a6),%a03642bsr.l tag # fetch operand type3643mov.b %d0,STAG(%a6)3644mov.b %d0,%d136453646andi.l &0x00ff00ff,USER_FPSR(%a6)36473648clr.l %d03649mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec36503651mov.b %d1,STAG(%a6)3652tst.b %d13653bne.b _L17_2d3654bsr.l sacos # operand is a NORM3655bra.b _L17_6d3656_L17_2d:3657cmpi.b %d1,&ZERO # is operand a ZERO?3658bne.b _L17_3d # no3659bsr.l ld_ppi2 # yes3660bra.b _L17_6d3661_L17_3d:3662cmpi.b %d1,&INF # is operand an INF?3663bne.b _L17_4d # no3664bsr.l t_operr # yes3665bra.b _L17_6d3666_L17_4d:3667cmpi.b %d1,&QNAN # is operand a QNAN?3668bne.b _L17_5d # no3669bsr.l src_qnan # yes3670bra.b _L17_6d3671_L17_5d:3672bsr.l sacosd # operand is a DENORM3673_L17_6d:36743675#3676# Result is now in FP03677#3678movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a13679fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs3680fmovm.x EXC_FP1(%a6),&0x40 # restore fp13681unlk %a63682rts36833684global _facosx_3685_facosx_:3686link %a6,&-LOCAL_SIZE36873688movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a13689fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs3690fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp136913692fmov.l &0x0,%fpcr # zero FPCR36933694#3695# copy, convert, and tag input argument3696#3697lea FP_SRC(%a6),%a03698mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input3699mov.l 0x8+0x4(%a6),0x4(%a0)3700mov.l 0x8+0x8(%a6),0x8(%a0)3701bsr.l tag # fetch operand type3702mov.b %d0,STAG(%a6)3703mov.b %d0,%d137043705andi.l &0x00ff00ff,USER_FPSR(%a6)37063707clr.l %d03708mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec37093710tst.b %d13711bne.b _L17_2x3712bsr.l sacos # operand is a NORM3713bra.b _L17_6x3714_L17_2x:3715cmpi.b %d1,&ZERO # is operand a ZERO?3716bne.b _L17_3x # no3717bsr.l ld_ppi2 # yes3718bra.b _L17_6x3719_L17_3x:3720cmpi.b %d1,&INF # is operand an INF?3721bne.b _L17_4x # no3722bsr.l t_operr # yes3723bra.b _L17_6x3724_L17_4x:3725cmpi.b %d1,&QNAN # is operand a QNAN?3726bne.b _L17_5x # no3727bsr.l src_qnan # yes3728bra.b _L17_6x3729_L17_5x:3730bsr.l sacosd # operand is a DENORM3731_L17_6x:37323733#3734# Result is now in FP03735#3736movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a13737fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs3738fmovm.x EXC_FP1(%a6),&0x40 # restore fp13739unlk %a63740rts374137423743#########################################################################3744# MONADIC TEMPLATE #3745#########################################################################3746global _fgetexps_3747_fgetexps_:3748link %a6,&-LOCAL_SIZE37493750movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a13751fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs3752fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp137533754fmov.l &0x0,%fpcr # zero FPCR37553756#3757# copy, convert, and tag input argument3758#3759fmov.s 0x8(%a6),%fp0 # load sgl input3760fmov.x %fp0,FP_SRC(%a6)3761lea FP_SRC(%a6),%a03762bsr.l tag # fetch operand type3763mov.b %d0,STAG(%a6)3764mov.b %d0,%d137653766andi.l &0x00ff00ff,USER_FPSR(%a6)37673768clr.l %d03769mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec37703771tst.b %d13772bne.b _L18_2s3773bsr.l sgetexp # operand is a NORM3774bra.b _L18_6s3775_L18_2s:3776cmpi.b %d1,&ZERO # is operand a ZERO?3777bne.b _L18_3s # no3778bsr.l src_zero # yes3779bra.b _L18_6s3780_L18_3s:3781cmpi.b %d1,&INF # is operand an INF?3782bne.b _L18_4s # no3783bsr.l t_operr # yes3784bra.b _L18_6s3785_L18_4s:3786cmpi.b %d1,&QNAN # is operand a QNAN?3787bne.b _L18_5s # no3788bsr.l src_qnan # yes3789bra.b _L18_6s3790_L18_5s:3791bsr.l sgetexpd # operand is a DENORM3792_L18_6s:37933794#3795# Result is now in FP03796#3797movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a13798fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs3799fmovm.x EXC_FP1(%a6),&0x40 # restore fp13800unlk %a63801rts38023803global _fgetexpd_3804_fgetexpd_:3805link %a6,&-LOCAL_SIZE38063807movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a13808fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs3809fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp138103811fmov.l &0x0,%fpcr # zero FPCR38123813#3814# copy, convert, and tag input argument3815#3816fmov.d 0x8(%a6),%fp0 # load dbl input3817fmov.x %fp0,FP_SRC(%a6)3818lea FP_SRC(%a6),%a03819bsr.l tag # fetch operand type3820mov.b %d0,STAG(%a6)3821mov.b %d0,%d138223823andi.l &0x00ff00ff,USER_FPSR(%a6)38243825clr.l %d03826mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec38273828mov.b %d1,STAG(%a6)3829tst.b %d13830bne.b _L18_2d3831bsr.l sgetexp # operand is a NORM3832bra.b _L18_6d3833_L18_2d:3834cmpi.b %d1,&ZERO # is operand a ZERO?3835bne.b _L18_3d # no3836bsr.l src_zero # yes3837bra.b _L18_6d3838_L18_3d:3839cmpi.b %d1,&INF # is operand an INF?3840bne.b _L18_4d # no3841bsr.l t_operr # yes3842bra.b _L18_6d3843_L18_4d:3844cmpi.b %d1,&QNAN # is operand a QNAN?3845bne.b _L18_5d # no3846bsr.l src_qnan # yes3847bra.b _L18_6d3848_L18_5d:3849bsr.l sgetexpd # operand is a DENORM3850_L18_6d:38513852#3853# Result is now in FP03854#3855movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a13856fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs3857fmovm.x EXC_FP1(%a6),&0x40 # restore fp13858unlk %a63859rts38603861global _fgetexpx_3862_fgetexpx_:3863link %a6,&-LOCAL_SIZE38643865movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a13866fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs3867fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp138683869fmov.l &0x0,%fpcr # zero FPCR38703871#3872# copy, convert, and tag input argument3873#3874lea FP_SRC(%a6),%a03875mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input3876mov.l 0x8+0x4(%a6),0x4(%a0)3877mov.l 0x8+0x8(%a6),0x8(%a0)3878bsr.l tag # fetch operand type3879mov.b %d0,STAG(%a6)3880mov.b %d0,%d138813882andi.l &0x00ff00ff,USER_FPSR(%a6)38833884clr.l %d03885mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec38863887tst.b %d13888bne.b _L18_2x3889bsr.l sgetexp # operand is a NORM3890bra.b _L18_6x3891_L18_2x:3892cmpi.b %d1,&ZERO # is operand a ZERO?3893bne.b _L18_3x # no3894bsr.l src_zero # yes3895bra.b _L18_6x3896_L18_3x:3897cmpi.b %d1,&INF # is operand an INF?3898bne.b _L18_4x # no3899bsr.l t_operr # yes3900bra.b _L18_6x3901_L18_4x:3902cmpi.b %d1,&QNAN # is operand a QNAN?3903bne.b _L18_5x # no3904bsr.l src_qnan # yes3905bra.b _L18_6x3906_L18_5x:3907bsr.l sgetexpd # operand is a DENORM3908_L18_6x:39093910#3911# Result is now in FP03912#3913movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a13914fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs3915fmovm.x EXC_FP1(%a6),&0x40 # restore fp13916unlk %a63917rts391839193920#########################################################################3921# MONADIC TEMPLATE #3922#########################################################################3923global _fgetmans_3924_fgetmans_:3925link %a6,&-LOCAL_SIZE39263927movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a13928fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs3929fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp139303931fmov.l &0x0,%fpcr # zero FPCR39323933#3934# copy, convert, and tag input argument3935#3936fmov.s 0x8(%a6),%fp0 # load sgl input3937fmov.x %fp0,FP_SRC(%a6)3938lea FP_SRC(%a6),%a03939bsr.l tag # fetch operand type3940mov.b %d0,STAG(%a6)3941mov.b %d0,%d139423943andi.l &0x00ff00ff,USER_FPSR(%a6)39443945clr.l %d03946mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec39473948tst.b %d13949bne.b _L19_2s3950bsr.l sgetman # operand is a NORM3951bra.b _L19_6s3952_L19_2s:3953cmpi.b %d1,&ZERO # is operand a ZERO?3954bne.b _L19_3s # no3955bsr.l src_zero # yes3956bra.b _L19_6s3957_L19_3s:3958cmpi.b %d1,&INF # is operand an INF?3959bne.b _L19_4s # no3960bsr.l t_operr # yes3961bra.b _L19_6s3962_L19_4s:3963cmpi.b %d1,&QNAN # is operand a QNAN?3964bne.b _L19_5s # no3965bsr.l src_qnan # yes3966bra.b _L19_6s3967_L19_5s:3968bsr.l sgetmand # operand is a DENORM3969_L19_6s:39703971#3972# Result is now in FP03973#3974movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a13975fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs3976fmovm.x EXC_FP1(%a6),&0x40 # restore fp13977unlk %a63978rts39793980global _fgetmand_3981_fgetmand_:3982link %a6,&-LOCAL_SIZE39833984movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a13985fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs3986fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp139873988fmov.l &0x0,%fpcr # zero FPCR39893990#3991# copy, convert, and tag input argument3992#3993fmov.d 0x8(%a6),%fp0 # load dbl input3994fmov.x %fp0,FP_SRC(%a6)3995lea FP_SRC(%a6),%a03996bsr.l tag # fetch operand type3997mov.b %d0,STAG(%a6)3998mov.b %d0,%d139994000andi.l &0x00ff00ff,USER_FPSR(%a6)40014002clr.l %d04003mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec40044005mov.b %d1,STAG(%a6)4006tst.b %d14007bne.b _L19_2d4008bsr.l sgetman # operand is a NORM4009bra.b _L19_6d4010_L19_2d:4011cmpi.b %d1,&ZERO # is operand a ZERO?4012bne.b _L19_3d # no4013bsr.l src_zero # yes4014bra.b _L19_6d4015_L19_3d:4016cmpi.b %d1,&INF # is operand an INF?4017bne.b _L19_4d # no4018bsr.l t_operr # yes4019bra.b _L19_6d4020_L19_4d:4021cmpi.b %d1,&QNAN # is operand a QNAN?4022bne.b _L19_5d # no4023bsr.l src_qnan # yes4024bra.b _L19_6d4025_L19_5d:4026bsr.l sgetmand # operand is a DENORM4027_L19_6d:40284029#4030# Result is now in FP04031#4032movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a14033fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs4034fmovm.x EXC_FP1(%a6),&0x40 # restore fp14035unlk %a64036rts40374038global _fgetmanx_4039_fgetmanx_:4040link %a6,&-LOCAL_SIZE40414042movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a14043fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs4044fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp140454046fmov.l &0x0,%fpcr # zero FPCR40474048#4049# copy, convert, and tag input argument4050#4051lea FP_SRC(%a6),%a04052mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input4053mov.l 0x8+0x4(%a6),0x4(%a0)4054mov.l 0x8+0x8(%a6),0x8(%a0)4055bsr.l tag # fetch operand type4056mov.b %d0,STAG(%a6)4057mov.b %d0,%d140584059andi.l &0x00ff00ff,USER_FPSR(%a6)40604061clr.l %d04062mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec40634064tst.b %d14065bne.b _L19_2x4066bsr.l sgetman # operand is a NORM4067bra.b _L19_6x4068_L19_2x:4069cmpi.b %d1,&ZERO # is operand a ZERO?4070bne.b _L19_3x # no4071bsr.l src_zero # yes4072bra.b _L19_6x4073_L19_3x:4074cmpi.b %d1,&INF # is operand an INF?4075bne.b _L19_4x # no4076bsr.l t_operr # yes4077bra.b _L19_6x4078_L19_4x:4079cmpi.b %d1,&QNAN # is operand a QNAN?4080bne.b _L19_5x # no4081bsr.l src_qnan # yes4082bra.b _L19_6x4083_L19_5x:4084bsr.l sgetmand # operand is a DENORM4085_L19_6x:40864087#4088# Result is now in FP04089#4090movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a14091fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs4092fmovm.x EXC_FP1(%a6),&0x40 # restore fp14093unlk %a64094rts409540964097#########################################################################4098# MONADIC TEMPLATE #4099#########################################################################4100global _fsincoss_4101_fsincoss_:4102link %a6,&-LOCAL_SIZE41034104movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a14105fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs4106fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp141074108fmov.l &0x0,%fpcr # zero FPCR41094110#4111# copy, convert, and tag input argument4112#4113fmov.s 0x8(%a6),%fp0 # load sgl input4114fmov.x %fp0,FP_SRC(%a6)4115lea FP_SRC(%a6),%a04116bsr.l tag # fetch operand type4117mov.b %d0,STAG(%a6)4118mov.b %d0,%d141194120andi.l &0x00ff00ff,USER_FPSR(%a6)41214122clr.l %d04123mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec41244125tst.b %d14126bne.b _L20_2s4127bsr.l ssincos # operand is a NORM4128bra.b _L20_6s4129_L20_2s:4130cmpi.b %d1,&ZERO # is operand a ZERO?4131bne.b _L20_3s # no4132bsr.l ssincosz # yes4133bra.b _L20_6s4134_L20_3s:4135cmpi.b %d1,&INF # is operand an INF?4136bne.b _L20_4s # no4137bsr.l ssincosi # yes4138bra.b _L20_6s4139_L20_4s:4140cmpi.b %d1,&QNAN # is operand a QNAN?4141bne.b _L20_5s # no4142bsr.l ssincosqnan # yes4143bra.b _L20_6s4144_L20_5s:4145bsr.l ssincosd # operand is a DENORM4146_L20_6s:41474148#4149# Result is now in FP04150#4151movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a14152fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs4153fmovm.x &0x03,-(%sp) # store off fp0/fp14154fmovm.x (%sp)+,&0x40 # fp0 now in fp14155fmovm.x (%sp)+,&0x80 # fp1 now in fp04156unlk %a64157rts41584159global _fsincosd_4160_fsincosd_:4161link %a6,&-LOCAL_SIZE41624163movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a14164fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs4165fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp141664167fmov.l &0x0,%fpcr # zero FPCR41684169#4170# copy, convert, and tag input argument4171#4172fmov.d 0x8(%a6),%fp0 # load dbl input4173fmov.x %fp0,FP_SRC(%a6)4174lea FP_SRC(%a6),%a04175bsr.l tag # fetch operand type4176mov.b %d0,STAG(%a6)4177mov.b %d0,%d141784179andi.l &0x00ff00ff,USER_FPSR(%a6)41804181clr.l %d04182mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec41834184mov.b %d1,STAG(%a6)4185tst.b %d14186bne.b _L20_2d4187bsr.l ssincos # operand is a NORM4188bra.b _L20_6d4189_L20_2d:4190cmpi.b %d1,&ZERO # is operand a ZERO?4191bne.b _L20_3d # no4192bsr.l ssincosz # yes4193bra.b _L20_6d4194_L20_3d:4195cmpi.b %d1,&INF # is operand an INF?4196bne.b _L20_4d # no4197bsr.l ssincosi # yes4198bra.b _L20_6d4199_L20_4d:4200cmpi.b %d1,&QNAN # is operand a QNAN?4201bne.b _L20_5d # no4202bsr.l ssincosqnan # yes4203bra.b _L20_6d4204_L20_5d:4205bsr.l ssincosd # operand is a DENORM4206_L20_6d:42074208#4209# Result is now in FP04210#4211movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a14212fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs4213fmovm.x &0x03,-(%sp) # store off fp0/fp14214fmovm.x (%sp)+,&0x40 # fp0 now in fp14215fmovm.x (%sp)+,&0x80 # fp1 now in fp04216unlk %a64217rts42184219global _fsincosx_4220_fsincosx_:4221link %a6,&-LOCAL_SIZE42224223movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a14224fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs4225fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp142264227fmov.l &0x0,%fpcr # zero FPCR42284229#4230# copy, convert, and tag input argument4231#4232lea FP_SRC(%a6),%a04233mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input4234mov.l 0x8+0x4(%a6),0x4(%a0)4235mov.l 0x8+0x8(%a6),0x8(%a0)4236bsr.l tag # fetch operand type4237mov.b %d0,STAG(%a6)4238mov.b %d0,%d142394240andi.l &0x00ff00ff,USER_FPSR(%a6)42414242clr.l %d04243mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec42444245tst.b %d14246bne.b _L20_2x4247bsr.l ssincos # operand is a NORM4248bra.b _L20_6x4249_L20_2x:4250cmpi.b %d1,&ZERO # is operand a ZERO?4251bne.b _L20_3x # no4252bsr.l ssincosz # yes4253bra.b _L20_6x4254_L20_3x:4255cmpi.b %d1,&INF # is operand an INF?4256bne.b _L20_4x # no4257bsr.l ssincosi # yes4258bra.b _L20_6x4259_L20_4x:4260cmpi.b %d1,&QNAN # is operand a QNAN?4261bne.b _L20_5x # no4262bsr.l ssincosqnan # yes4263bra.b _L20_6x4264_L20_5x:4265bsr.l ssincosd # operand is a DENORM4266_L20_6x:42674268#4269# Result is now in FP04270#4271movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a14272fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs4273fmovm.x &0x03,-(%sp) # store off fp0/fp14274fmovm.x (%sp)+,&0x40 # fp0 now in fp14275fmovm.x (%sp)+,&0x80 # fp1 now in fp04276unlk %a64277rts427842794280#########################################################################4281# DYADIC TEMPLATE #4282#########################################################################4283global _frems_4284_frems_:4285link %a6,&-LOCAL_SIZE42864287movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a14288fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs4289fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp142904291fmov.l &0x0,%fpcr # zero FPCR42924293#4294# copy, convert, and tag input argument4295#4296fmov.s 0x8(%a6),%fp0 # load sgl dst4297fmov.x %fp0,FP_DST(%a6)4298lea FP_DST(%a6),%a04299bsr.l tag # fetch operand type4300mov.b %d0,DTAG(%a6)43014302fmov.s 0xc(%a6),%fp0 # load sgl src4303fmov.x %fp0,FP_SRC(%a6)4304lea FP_SRC(%a6),%a04305bsr.l tag # fetch operand type4306mov.b %d0,STAG(%a6)4307mov.l %d0,%d143084309andi.l &0x00ff00ff,USER_FPSR(%a6)43104311clr.l %d04312mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec43134314lea FP_SRC(%a6),%a0 # pass ptr to src4315lea FP_DST(%a6),%a1 # pass ptr to dst43164317tst.b %d14318bne.b _L21_2s4319bsr.l srem_snorm # operand is a NORM4320bra.b _L21_6s4321_L21_2s:4322cmpi.b %d1,&ZERO # is operand a ZERO?4323bne.b _L21_3s # no4324bsr.l srem_szero # yes4325bra.b _L21_6s4326_L21_3s:4327cmpi.b %d1,&INF # is operand an INF?4328bne.b _L21_4s # no4329bsr.l srem_sinf # yes4330bra.b _L21_6s4331_L21_4s:4332cmpi.b %d1,&QNAN # is operand a QNAN?4333bne.b _L21_5s # no4334bsr.l sop_sqnan # yes4335bra.b _L21_6s4336_L21_5s:4337bsr.l srem_sdnrm # operand is a DENORM4338_L21_6s:43394340#4341# Result is now in FP04342#4343movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a14344fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs4345fmovm.x EXC_FP1(%a6),&0x40 # restore fp14346unlk %a64347rts43484349global _fremd_4350_fremd_:4351link %a6,&-LOCAL_SIZE43524353movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a14354fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs4355fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp143564357fmov.l &0x0,%fpcr # zero FPCR43584359#4360# copy, convert, and tag input argument4361#4362fmov.d 0x8(%a6),%fp0 # load dbl dst4363fmov.x %fp0,FP_DST(%a6)4364lea FP_DST(%a6),%a04365bsr.l tag # fetch operand type4366mov.b %d0,DTAG(%a6)43674368fmov.d 0x10(%a6),%fp0 # load dbl src4369fmov.x %fp0,FP_SRC(%a6)4370lea FP_SRC(%a6),%a04371bsr.l tag # fetch operand type4372mov.b %d0,STAG(%a6)4373mov.l %d0,%d143744375andi.l &0x00ff00ff,USER_FPSR(%a6)43764377clr.l %d04378mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec43794380lea FP_SRC(%a6),%a0 # pass ptr to src4381lea FP_DST(%a6),%a1 # pass ptr to dst43824383tst.b %d14384bne.b _L21_2d4385bsr.l srem_snorm # operand is a NORM4386bra.b _L21_6d4387_L21_2d:4388cmpi.b %d1,&ZERO # is operand a ZERO?4389bne.b _L21_3d # no4390bsr.l srem_szero # yes4391bra.b _L21_6d4392_L21_3d:4393cmpi.b %d1,&INF # is operand an INF?4394bne.b _L21_4d # no4395bsr.l srem_sinf # yes4396bra.b _L21_6d4397_L21_4d:4398cmpi.b %d1,&QNAN # is operand a QNAN?4399bne.b _L21_5d # no4400bsr.l sop_sqnan # yes4401bra.b _L21_6d4402_L21_5d:4403bsr.l srem_sdnrm # operand is a DENORM4404_L21_6d:44054406#4407# Result is now in FP04408#4409movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a14410fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs4411fmovm.x EXC_FP1(%a6),&0x40 # restore fp14412unlk %a64413rts44144415global _fremx_4416_fremx_:4417link %a6,&-LOCAL_SIZE44184419movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a14420fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs4421fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp144224423fmov.l &0x0,%fpcr # zero FPCR44244425#4426# copy, convert, and tag input argument4427#4428lea FP_DST(%a6),%a04429mov.l 0x8+0x0(%a6),0x0(%a0) # load ext dst4430mov.l 0x8+0x4(%a6),0x4(%a0)4431mov.l 0x8+0x8(%a6),0x8(%a0)4432bsr.l tag # fetch operand type4433mov.b %d0,DTAG(%a6)44344435lea FP_SRC(%a6),%a04436mov.l 0x14+0x0(%a6),0x0(%a0) # load ext src4437mov.l 0x14+0x4(%a6),0x4(%a0)4438mov.l 0x14+0x8(%a6),0x8(%a0)4439bsr.l tag # fetch operand type4440mov.b %d0,STAG(%a6)4441mov.l %d0,%d144424443andi.l &0x00ff00ff,USER_FPSR(%a6)44444445clr.l %d04446mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec44474448lea FP_SRC(%a6),%a0 # pass ptr to src4449lea FP_DST(%a6),%a1 # pass ptr to dst44504451tst.b %d14452bne.b _L21_2x4453bsr.l srem_snorm # operand is a NORM4454bra.b _L21_6x4455_L21_2x:4456cmpi.b %d1,&ZERO # is operand a ZERO?4457bne.b _L21_3x # no4458bsr.l srem_szero # yes4459bra.b _L21_6x4460_L21_3x:4461cmpi.b %d1,&INF # is operand an INF?4462bne.b _L21_4x # no4463bsr.l srem_sinf # yes4464bra.b _L21_6x4465_L21_4x:4466cmpi.b %d1,&QNAN # is operand a QNAN?4467bne.b _L21_5x # no4468bsr.l sop_sqnan # yes4469bra.b _L21_6x4470_L21_5x:4471bsr.l srem_sdnrm # operand is a DENORM4472_L21_6x:44734474#4475# Result is now in FP04476#4477movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a14478fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs4479fmovm.x EXC_FP1(%a6),&0x40 # restore fp14480unlk %a64481rts448244834484#########################################################################4485# DYADIC TEMPLATE #4486#########################################################################4487global _fmods_4488_fmods_:4489link %a6,&-LOCAL_SIZE44904491movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a14492fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs4493fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp144944495fmov.l &0x0,%fpcr # zero FPCR44964497#4498# copy, convert, and tag input argument4499#4500fmov.s 0x8(%a6),%fp0 # load sgl dst4501fmov.x %fp0,FP_DST(%a6)4502lea FP_DST(%a6),%a04503bsr.l tag # fetch operand type4504mov.b %d0,DTAG(%a6)45054506fmov.s 0xc(%a6),%fp0 # load sgl src4507fmov.x %fp0,FP_SRC(%a6)4508lea FP_SRC(%a6),%a04509bsr.l tag # fetch operand type4510mov.b %d0,STAG(%a6)4511mov.l %d0,%d145124513andi.l &0x00ff00ff,USER_FPSR(%a6)45144515clr.l %d04516mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec45174518lea FP_SRC(%a6),%a0 # pass ptr to src4519lea FP_DST(%a6),%a1 # pass ptr to dst45204521tst.b %d14522bne.b _L22_2s4523bsr.l smod_snorm # operand is a NORM4524bra.b _L22_6s4525_L22_2s:4526cmpi.b %d1,&ZERO # is operand a ZERO?4527bne.b _L22_3s # no4528bsr.l smod_szero # yes4529bra.b _L22_6s4530_L22_3s:4531cmpi.b %d1,&INF # is operand an INF?4532bne.b _L22_4s # no4533bsr.l smod_sinf # yes4534bra.b _L22_6s4535_L22_4s:4536cmpi.b %d1,&QNAN # is operand a QNAN?4537bne.b _L22_5s # no4538bsr.l sop_sqnan # yes4539bra.b _L22_6s4540_L22_5s:4541bsr.l smod_sdnrm # operand is a DENORM4542_L22_6s:45434544#4545# Result is now in FP04546#4547movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a14548fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs4549fmovm.x EXC_FP1(%a6),&0x40 # restore fp14550unlk %a64551rts45524553global _fmodd_4554_fmodd_:4555link %a6,&-LOCAL_SIZE45564557movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a14558fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs4559fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp145604561fmov.l &0x0,%fpcr # zero FPCR45624563#4564# copy, convert, and tag input argument4565#4566fmov.d 0x8(%a6),%fp0 # load dbl dst4567fmov.x %fp0,FP_DST(%a6)4568lea FP_DST(%a6),%a04569bsr.l tag # fetch operand type4570mov.b %d0,DTAG(%a6)45714572fmov.d 0x10(%a6),%fp0 # load dbl src4573fmov.x %fp0,FP_SRC(%a6)4574lea FP_SRC(%a6),%a04575bsr.l tag # fetch operand type4576mov.b %d0,STAG(%a6)4577mov.l %d0,%d145784579andi.l &0x00ff00ff,USER_FPSR(%a6)45804581clr.l %d04582mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec45834584lea FP_SRC(%a6),%a0 # pass ptr to src4585lea FP_DST(%a6),%a1 # pass ptr to dst45864587tst.b %d14588bne.b _L22_2d4589bsr.l smod_snorm # operand is a NORM4590bra.b _L22_6d4591_L22_2d:4592cmpi.b %d1,&ZERO # is operand a ZERO?4593bne.b _L22_3d # no4594bsr.l smod_szero # yes4595bra.b _L22_6d4596_L22_3d:4597cmpi.b %d1,&INF # is operand an INF?4598bne.b _L22_4d # no4599bsr.l smod_sinf # yes4600bra.b _L22_6d4601_L22_4d:4602cmpi.b %d1,&QNAN # is operand a QNAN?4603bne.b _L22_5d # no4604bsr.l sop_sqnan # yes4605bra.b _L22_6d4606_L22_5d:4607bsr.l smod_sdnrm # operand is a DENORM4608_L22_6d:46094610#4611# Result is now in FP04612#4613movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a14614fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs4615fmovm.x EXC_FP1(%a6),&0x40 # restore fp14616unlk %a64617rts46184619global _fmodx_4620_fmodx_:4621link %a6,&-LOCAL_SIZE46224623movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a14624fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs4625fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp146264627fmov.l &0x0,%fpcr # zero FPCR46284629#4630# copy, convert, and tag input argument4631#4632lea FP_DST(%a6),%a04633mov.l 0x8+0x0(%a6),0x0(%a0) # load ext dst4634mov.l 0x8+0x4(%a6),0x4(%a0)4635mov.l 0x8+0x8(%a6),0x8(%a0)4636bsr.l tag # fetch operand type4637mov.b %d0,DTAG(%a6)46384639lea FP_SRC(%a6),%a04640mov.l 0x14+0x0(%a6),0x0(%a0) # load ext src4641mov.l 0x14+0x4(%a6),0x4(%a0)4642mov.l 0x14+0x8(%a6),0x8(%a0)4643bsr.l tag # fetch operand type4644mov.b %d0,STAG(%a6)4645mov.l %d0,%d146464647andi.l &0x00ff00ff,USER_FPSR(%a6)46484649clr.l %d04650mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec46514652lea FP_SRC(%a6),%a0 # pass ptr to src4653lea FP_DST(%a6),%a1 # pass ptr to dst46544655tst.b %d14656bne.b _L22_2x4657bsr.l smod_snorm # operand is a NORM4658bra.b _L22_6x4659_L22_2x:4660cmpi.b %d1,&ZERO # is operand a ZERO?4661bne.b _L22_3x # no4662bsr.l smod_szero # yes4663bra.b _L22_6x4664_L22_3x:4665cmpi.b %d1,&INF # is operand an INF?4666bne.b _L22_4x # no4667bsr.l smod_sinf # yes4668bra.b _L22_6x4669_L22_4x:4670cmpi.b %d1,&QNAN # is operand a QNAN?4671bne.b _L22_5x # no4672bsr.l sop_sqnan # yes4673bra.b _L22_6x4674_L22_5x:4675bsr.l smod_sdnrm # operand is a DENORM4676_L22_6x:46774678#4679# Result is now in FP04680#4681movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a14682fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs4683fmovm.x EXC_FP1(%a6),&0x40 # restore fp14684unlk %a64685rts468646874688#########################################################################4689# DYADIC TEMPLATE #4690#########################################################################4691global _fscales_4692_fscales_:4693link %a6,&-LOCAL_SIZE46944695movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a14696fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs4697fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp146984699fmov.l &0x0,%fpcr # zero FPCR47004701#4702# copy, convert, and tag input argument4703#4704fmov.s 0x8(%a6),%fp0 # load sgl dst4705fmov.x %fp0,FP_DST(%a6)4706lea FP_DST(%a6),%a04707bsr.l tag # fetch operand type4708mov.b %d0,DTAG(%a6)47094710fmov.s 0xc(%a6),%fp0 # load sgl src4711fmov.x %fp0,FP_SRC(%a6)4712lea FP_SRC(%a6),%a04713bsr.l tag # fetch operand type4714mov.b %d0,STAG(%a6)4715mov.l %d0,%d147164717andi.l &0x00ff00ff,USER_FPSR(%a6)47184719clr.l %d04720mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec47214722lea FP_SRC(%a6),%a0 # pass ptr to src4723lea FP_DST(%a6),%a1 # pass ptr to dst47244725tst.b %d14726bne.b _L23_2s4727bsr.l sscale_snorm # operand is a NORM4728bra.b _L23_6s4729_L23_2s:4730cmpi.b %d1,&ZERO # is operand a ZERO?4731bne.b _L23_3s # no4732bsr.l sscale_szero # yes4733bra.b _L23_6s4734_L23_3s:4735cmpi.b %d1,&INF # is operand an INF?4736bne.b _L23_4s # no4737bsr.l sscale_sinf # yes4738bra.b _L23_6s4739_L23_4s:4740cmpi.b %d1,&QNAN # is operand a QNAN?4741bne.b _L23_5s # no4742bsr.l sop_sqnan # yes4743bra.b _L23_6s4744_L23_5s:4745bsr.l sscale_sdnrm # operand is a DENORM4746_L23_6s:47474748#4749# Result is now in FP04750#4751movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a14752fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs4753fmovm.x EXC_FP1(%a6),&0x40 # restore fp14754unlk %a64755rts47564757global _fscaled_4758_fscaled_:4759link %a6,&-LOCAL_SIZE47604761movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a14762fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs4763fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp147644765fmov.l &0x0,%fpcr # zero FPCR47664767#4768# copy, convert, and tag input argument4769#4770fmov.d 0x8(%a6),%fp0 # load dbl dst4771fmov.x %fp0,FP_DST(%a6)4772lea FP_DST(%a6),%a04773bsr.l tag # fetch operand type4774mov.b %d0,DTAG(%a6)47754776fmov.d 0x10(%a6),%fp0 # load dbl src4777fmov.x %fp0,FP_SRC(%a6)4778lea FP_SRC(%a6),%a04779bsr.l tag # fetch operand type4780mov.b %d0,STAG(%a6)4781mov.l %d0,%d147824783andi.l &0x00ff00ff,USER_FPSR(%a6)47844785clr.l %d04786mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec47874788lea FP_SRC(%a6),%a0 # pass ptr to src4789lea FP_DST(%a6),%a1 # pass ptr to dst47904791tst.b %d14792bne.b _L23_2d4793bsr.l sscale_snorm # operand is a NORM4794bra.b _L23_6d4795_L23_2d:4796cmpi.b %d1,&ZERO # is operand a ZERO?4797bne.b _L23_3d # no4798bsr.l sscale_szero # yes4799bra.b _L23_6d4800_L23_3d:4801cmpi.b %d1,&INF # is operand an INF?4802bne.b _L23_4d # no4803bsr.l sscale_sinf # yes4804bra.b _L23_6d4805_L23_4d:4806cmpi.b %d1,&QNAN # is operand a QNAN?4807bne.b _L23_5d # no4808bsr.l sop_sqnan # yes4809bra.b _L23_6d4810_L23_5d:4811bsr.l sscale_sdnrm # operand is a DENORM4812_L23_6d:48134814#4815# Result is now in FP04816#4817movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a14818fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs4819fmovm.x EXC_FP1(%a6),&0x40 # restore fp14820unlk %a64821rts48224823global _fscalex_4824_fscalex_:4825link %a6,&-LOCAL_SIZE48264827movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a14828fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs4829fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp148304831fmov.l &0x0,%fpcr # zero FPCR48324833#4834# copy, convert, and tag input argument4835#4836lea FP_DST(%a6),%a04837mov.l 0x8+0x0(%a6),0x0(%a0) # load ext dst4838mov.l 0x8+0x4(%a6),0x4(%a0)4839mov.l 0x8+0x8(%a6),0x8(%a0)4840bsr.l tag # fetch operand type4841mov.b %d0,DTAG(%a6)48424843lea FP_SRC(%a6),%a04844mov.l 0x14+0x0(%a6),0x0(%a0) # load ext src4845mov.l 0x14+0x4(%a6),0x4(%a0)4846mov.l 0x14+0x8(%a6),0x8(%a0)4847bsr.l tag # fetch operand type4848mov.b %d0,STAG(%a6)4849mov.l %d0,%d148504851andi.l &0x00ff00ff,USER_FPSR(%a6)48524853clr.l %d04854mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec48554856lea FP_SRC(%a6),%a0 # pass ptr to src4857lea FP_DST(%a6),%a1 # pass ptr to dst48584859tst.b %d14860bne.b _L23_2x4861bsr.l sscale_snorm # operand is a NORM4862bra.b _L23_6x4863_L23_2x:4864cmpi.b %d1,&ZERO # is operand a ZERO?4865bne.b _L23_3x # no4866bsr.l sscale_szero # yes4867bra.b _L23_6x4868_L23_3x:4869cmpi.b %d1,&INF # is operand an INF?4870bne.b _L23_4x # no4871bsr.l sscale_sinf # yes4872bra.b _L23_6x4873_L23_4x:4874cmpi.b %d1,&QNAN # is operand a QNAN?4875bne.b _L23_5x # no4876bsr.l sop_sqnan # yes4877bra.b _L23_6x4878_L23_5x:4879bsr.l sscale_sdnrm # operand is a DENORM4880_L23_6x:48814882#4883# Result is now in FP04884#4885movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a14886fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs4887fmovm.x EXC_FP1(%a6),&0x40 # restore fp14888unlk %a64889rts489048914892#########################################################################4893# ssin(): computes the sine of a normalized input #4894# ssind(): computes the sine of a denormalized input #4895# scos(): computes the cosine of a normalized input #4896# scosd(): computes the cosine of a denormalized input #4897# ssincos(): computes the sine and cosine of a normalized input #4898# ssincosd(): computes the sine and cosine of a denormalized input #4899# #4900# INPUT *************************************************************** #4901# a0 = pointer to extended precision input #4902# d0 = round precision,mode #4903# #4904# OUTPUT ************************************************************** #4905# fp0 = sin(X) or cos(X) #4906# #4907# For ssincos(X): #4908# fp0 = sin(X) #4909# fp1 = cos(X) #4910# #4911# ACCURACY and MONOTONICITY ******************************************* #4912# The returned result is within 1 ulp in 64 significant bit, i.e. #4913# within 0.5001 ulp to 53 bits if the result is subsequently #4914# rounded to double precision. The result is provably monotonic #4915# in double precision. #4916# #4917# ALGORITHM *********************************************************** #4918# #4919# SIN and COS: #4920# 1. If SIN is invoked, set AdjN := 0; otherwise, set AdjN := 1. #4921# #4922# 2. If |X| >= 15Pi or |X| < 2**(-40), go to 7. #4923# #4924# 3. Decompose X as X = N(Pi/2) + r where |r| <= Pi/4. Let #4925# k = N mod 4, so in particular, k = 0,1,2,or 3. #4926# Overwrite k by k := k + AdjN. #4927# #4928# 4. If k is even, go to 6. #4929# #4930# 5. (k is odd) Set j := (k-1)/2, sgn := (-1)**j. #4931# Return sgn*cos(r) where cos(r) is approximated by an #4932# even polynomial in r, 1 + r*r*(B1+s*(B2+ ... + s*B8)), #4933# s = r*r. #4934# Exit. #4935# #4936# 6. (k is even) Set j := k/2, sgn := (-1)**j. Return sgn*sin(r) #4937# where sin(r) is approximated by an odd polynomial in r #4938# r + r*s*(A1+s*(A2+ ... + s*A7)), s = r*r. #4939# Exit. #4940# #4941# 7. If |X| > 1, go to 9. #4942# #4943# 8. (|X|<2**(-40)) If SIN is invoked, return X; #4944# otherwise return 1. #4945# #4946# 9. Overwrite X by X := X rem 2Pi. Now that |X| <= Pi, #4947# go back to 3. #4948# #4949# SINCOS: #4950# 1. If |X| >= 15Pi or |X| < 2**(-40), go to 6. #4951# #4952# 2. Decompose X as X = N(Pi/2) + r where |r| <= Pi/4. Let #4953# k = N mod 4, so in particular, k = 0,1,2,or 3. #4954# #4955# 3. If k is even, go to 5. #4956# #4957# 4. (k is odd) Set j1 := (k-1)/2, j2 := j1 (EOR) (k mod 2), ie. #4958# j1 exclusive or with the l.s.b. of k. #4959# sgn1 := (-1)**j1, sgn2 := (-1)**j2. #4960# SIN(X) = sgn1 * cos(r) and COS(X) = sgn2*sin(r) where #4961# sin(r) and cos(r) are computed as odd and even #4962# polynomials in r, respectively. Exit #4963# #4964# 5. (k is even) Set j1 := k/2, sgn1 := (-1)**j1. #4965# SIN(X) = sgn1 * sin(r) and COS(X) = sgn1*cos(r) where #4966# sin(r) and cos(r) are computed as odd and even #4967# polynomials in r, respectively. Exit #4968# #4969# 6. If |X| > 1, go to 8. #4970# #4971# 7. (|X|<2**(-40)) SIN(X) = X and COS(X) = 1. Exit. #4972# #4973# 8. Overwrite X by X := X rem 2Pi. Now that |X| <= Pi, #4974# go back to 2. #4975# #4976#########################################################################49774978SINA7: long 0xBD6AAA77,0xCCC994F54979SINA6: long 0x3DE61209,0x7AAE8DA14980SINA5: long 0xBE5AE645,0x2A118AE44981SINA4: long 0x3EC71DE3,0xA53415314982SINA3: long 0xBF2A01A0,0x1A018B59,0x00000000,0x000000004983SINA2: long 0x3FF80000,0x88888888,0x888859AF,0x000000004984SINA1: long 0xBFFC0000,0xAAAAAAAA,0xAAAAAA99,0x0000000049854986COSB8: long 0x3D2AC4D0,0xD6011EE34987COSB7: long 0xBDA9396F,0x9F45AC194988COSB6: long 0x3E21EED9,0x0612C9724989COSB5: long 0xBE927E4F,0xB79D9FCF4990COSB4: long 0x3EFA01A0,0x1A01D423,0x00000000,0x000000004991COSB3: long 0xBFF50000,0xB60B60B6,0x0B61D438,0x000000004992COSB2: long 0x3FFA0000,0xAAAAAAAA,0xAAAAAB5E4993COSB1: long 0xBF00000049944995set INARG,FP_SCR049964997set X,FP_SCR04998# set XDCARE,X+24999set XFRAC,X+450005001set RPRIME,FP_SCR05002set SPRIME,FP_SCR150035004set POSNEG1,L_SCR15005set TWOTO63,L_SCR150065007set ENDFLAG,L_SCR25008set INT,L_SCR250095010set ADJN,L_SCR350115012############################################5013global ssin5014ssin:5015mov.l &0,ADJN(%a6) # yes; SET ADJN TO 05016bra.b SINBGN50175018############################################5019global scos5020scos:5021mov.l &1,ADJN(%a6) # yes; SET ADJN TO 150225023############################################5024SINBGN:5025#--SAVE FPCR, FP1. CHECK IF |X| IS TOO SMALL OR LARGE50265027fmov.x (%a0),%fp0 # LOAD INPUT5028fmov.x %fp0,X(%a6) # save input at X50295030# "COMPACTIFY" X5031mov.l (%a0),%d1 # put exp in hi word5032mov.w 4(%a0),%d1 # fetch hi(man)5033and.l &0x7FFFFFFF,%d1 # strip sign50345035cmpi.l %d1,&0x3FD78000 # is |X| >= 2**(-40)?5036bge.b SOK1 # no5037bra.w SINSM # yes; input is very small50385039SOK1:5040cmp.l %d1,&0x4004BC7E # is |X| < 15 PI?5041blt.b SINMAIN # no5042bra.w SREDUCEX # yes; input is very large50435044#--THIS IS THE USUAL CASE, |X| <= 15 PI.5045#--THE ARGUMENT REDUCTION IS DONE BY TABLE LOOK UP.5046SINMAIN:5047fmov.x %fp0,%fp15048fmul.d TWOBYPI(%pc),%fp1 # X*2/PI50495050lea PITBL+0x200(%pc),%a1 # TABLE OF N*PI/2, N = -32,...,3250515052fmov.l %fp1,INT(%a6) # CONVERT TO INTEGER50535054mov.l INT(%a6),%d1 # make a copy of N5055asl.l &4,%d1 # N *= 165056add.l %d1,%a1 # tbl_addr = a1 + (N*16)50575058# A1 IS THE ADDRESS OF N*PIBY25059# ...WHICH IS IN TWO PIECES Y1 & Y25060fsub.x (%a1)+,%fp0 # X-Y15061fsub.s (%a1),%fp0 # fp0 = R = (X-Y1)-Y250625063SINCONT:5064#--continuation from REDUCEX50655066#--GET N+ADJN AND SEE IF SIN(R) OR COS(R) IS NEEDED5067mov.l INT(%a6),%d15068add.l ADJN(%a6),%d1 # SEE IF D0 IS ODD OR EVEN5069ror.l &1,%d1 # D0 WAS ODD IFF D0 IS NEGATIVE5070cmp.l %d1,&05071blt.w COSPOLY50725073#--LET J BE THE LEAST SIG. BIT OF D0, LET SGN := (-1)**J.5074#--THEN WE RETURN SGN*SIN(R). SGN*SIN(R) IS COMPUTED BY5075#--R' + R'*S*(A1 + S(A2 + S(A3 + S(A4 + ... + SA7)))), WHERE5076#--R' = SGN*R, S=R*R. THIS CAN BE REWRITTEN AS5077#--R' + R'*S*( [A1+T(A3+T(A5+TA7))] + [S(A2+T(A4+TA6))])5078#--WHERE T=S*S.5079#--NOTE THAT A3 THROUGH A7 ARE STORED IN DOUBLE PRECISION5080#--WHILE A1 AND A2 ARE IN DOUBLE-EXTENDED FORMAT.5081SINPOLY:5082fmovm.x &0x0c,-(%sp) # save fp2/fp350835084fmov.x %fp0,X(%a6) # X IS R5085fmul.x %fp0,%fp0 # FP0 IS S50865087fmov.d SINA7(%pc),%fp35088fmov.d SINA6(%pc),%fp250895090fmov.x %fp0,%fp15091fmul.x %fp1,%fp1 # FP1 IS T50925093ror.l &1,%d15094and.l &0x80000000,%d15095# ...LEAST SIG. BIT OF D0 IN SIGN POSITION5096eor.l %d1,X(%a6) # X IS NOW R'= SGN*R50975098fmul.x %fp1,%fp3 # TA75099fmul.x %fp1,%fp2 # TA651005101fadd.d SINA5(%pc),%fp3 # A5+TA75102fadd.d SINA4(%pc),%fp2 # A4+TA651035104fmul.x %fp1,%fp3 # T(A5+TA7)5105fmul.x %fp1,%fp2 # T(A4+TA6)51065107fadd.d SINA3(%pc),%fp3 # A3+T(A5+TA7)5108fadd.x SINA2(%pc),%fp2 # A2+T(A4+TA6)51095110fmul.x %fp3,%fp1 # T(A3+T(A5+TA7))51115112fmul.x %fp0,%fp2 # S(A2+T(A4+TA6))5113fadd.x SINA1(%pc),%fp1 # A1+T(A3+T(A5+TA7))5114fmul.x X(%a6),%fp0 # R'*S51155116fadd.x %fp2,%fp1 # [A1+T(A3+T(A5+TA7))]+[S(A2+T(A4+TA6))]51175118fmul.x %fp1,%fp0 # SIN(R')-R'51195120fmovm.x (%sp)+,&0x30 # restore fp2/fp351215122fmov.l %d0,%fpcr # restore users round mode,prec5123fadd.x X(%a6),%fp0 # last inst - possible exception set5124bra t_inx251255126#--LET J BE THE LEAST SIG. BIT OF D0, LET SGN := (-1)**J.5127#--THEN WE RETURN SGN*COS(R). SGN*COS(R) IS COMPUTED BY5128#--SGN + S'*(B1 + S(B2 + S(B3 + S(B4 + ... + SB8)))), WHERE5129#--S=R*R AND S'=SGN*S. THIS CAN BE REWRITTEN AS5130#--SGN + S'*([B1+T(B3+T(B5+TB7))] + [S(B2+T(B4+T(B6+TB8)))])5131#--WHERE T=S*S.5132#--NOTE THAT B4 THROUGH B8 ARE STORED IN DOUBLE PRECISION5133#--WHILE B2 AND B3 ARE IN DOUBLE-EXTENDED FORMAT, B1 IS -1/25134#--AND IS THEREFORE STORED AS SINGLE PRECISION.5135COSPOLY:5136fmovm.x &0x0c,-(%sp) # save fp2/fp351375138fmul.x %fp0,%fp0 # FP0 IS S51395140fmov.d COSB8(%pc),%fp25141fmov.d COSB7(%pc),%fp351425143fmov.x %fp0,%fp15144fmul.x %fp1,%fp1 # FP1 IS T51455146fmov.x %fp0,X(%a6) # X IS S5147ror.l &1,%d15148and.l &0x80000000,%d15149# ...LEAST SIG. BIT OF D0 IN SIGN POSITION51505151fmul.x %fp1,%fp2 # TB851525153eor.l %d1,X(%a6) # X IS NOW S'= SGN*S5154and.l &0x80000000,%d151555156fmul.x %fp1,%fp3 # TB751575158or.l &0x3F800000,%d1 # D0 IS SGN IN SINGLE5159mov.l %d1,POSNEG1(%a6)51605161fadd.d COSB6(%pc),%fp2 # B6+TB85162fadd.d COSB5(%pc),%fp3 # B5+TB751635164fmul.x %fp1,%fp2 # T(B6+TB8)5165fmul.x %fp1,%fp3 # T(B5+TB7)51665167fadd.d COSB4(%pc),%fp2 # B4+T(B6+TB8)5168fadd.x COSB3(%pc),%fp3 # B3+T(B5+TB7)51695170fmul.x %fp1,%fp2 # T(B4+T(B6+TB8))5171fmul.x %fp3,%fp1 # T(B3+T(B5+TB7))51725173fadd.x COSB2(%pc),%fp2 # B2+T(B4+T(B6+TB8))5174fadd.s COSB1(%pc),%fp1 # B1+T(B3+T(B5+TB7))51755176fmul.x %fp2,%fp0 # S(B2+T(B4+T(B6+TB8)))51775178fadd.x %fp1,%fp051795180fmul.x X(%a6),%fp051815182fmovm.x (%sp)+,&0x30 # restore fp2/fp351835184fmov.l %d0,%fpcr # restore users round mode,prec5185fadd.s POSNEG1(%a6),%fp0 # last inst - possible exception set5186bra t_inx251875188##############################################51895190# SINe: Big OR Small?5191#--IF |X| > 15PI, WE USE THE GENERAL ARGUMENT REDUCTION.5192#--IF |X| < 2**(-40), RETURN X OR 1.5193SINBORS:5194cmp.l %d1,&0x3FFF80005195bgt.l SREDUCEX51965197SINSM:5198mov.l ADJN(%a6),%d15199cmp.l %d1,&05200bgt.b COSTINY52015202# here, the operation may underflow iff the precision is sgl or dbl.5203# extended denorms are handled through another entry point.5204SINTINY:5205# mov.w &0x0000,XDCARE(%a6) # JUST IN CASE52065207fmov.l %d0,%fpcr # restore users round mode,prec5208mov.b &FMOV_OP,%d1 # last inst is MOVE5209fmov.x X(%a6),%fp0 # last inst - possible exception set5210bra t_catch52115212COSTINY:5213fmov.s &0x3F800000,%fp0 # fp0 = 1.05214fmov.l %d0,%fpcr # restore users round mode,prec5215fadd.s &0x80800000,%fp0 # last inst - possible exception set5216bra t_pinx252175218################################################5219global ssind5220#--SIN(X) = X FOR DENORMALIZED X5221ssind:5222bra t_extdnrm52235224############################################5225global scosd5226#--COS(X) = 1 FOR DENORMALIZED X5227scosd:5228fmov.s &0x3F800000,%fp0 # fp0 = 1.05229bra t_pinx252305231##################################################52325233global ssincos5234ssincos:5235#--SET ADJN TO 45236mov.l &4,ADJN(%a6)52375238fmov.x (%a0),%fp0 # LOAD INPUT5239fmov.x %fp0,X(%a6)52405241mov.l (%a0),%d15242mov.w 4(%a0),%d15243and.l &0x7FFFFFFF,%d1 # COMPACTIFY X52445245cmp.l %d1,&0x3FD78000 # |X| >= 2**(-40)?5246bge.b SCOK15247bra.w SCSM52485249SCOK1:5250cmp.l %d1,&0x4004BC7E # |X| < 15 PI?5251blt.b SCMAIN5252bra.w SREDUCEX525352545255#--THIS IS THE USUAL CASE, |X| <= 15 PI.5256#--THE ARGUMENT REDUCTION IS DONE BY TABLE LOOK UP.5257SCMAIN:5258fmov.x %fp0,%fp152595260fmul.d TWOBYPI(%pc),%fp1 # X*2/PI52615262lea PITBL+0x200(%pc),%a1 # TABLE OF N*PI/2, N = -32,...,3252635264fmov.l %fp1,INT(%a6) # CONVERT TO INTEGER52655266mov.l INT(%a6),%d15267asl.l &4,%d15268add.l %d1,%a1 # ADDRESS OF N*PIBY2, IN Y1, Y252695270fsub.x (%a1)+,%fp0 # X-Y15271fsub.s (%a1),%fp0 # FP0 IS R = (X-Y1)-Y252725273SCCONT:5274#--continuation point from REDUCEX52755276mov.l INT(%a6),%d15277ror.l &1,%d15278cmp.l %d1,&0 # D0 < 0 IFF N IS ODD5279bge.w NEVEN52805281SNODD:5282#--REGISTERS SAVED SO FAR: D0, A0, FP2.5283fmovm.x &0x04,-(%sp) # save fp252845285fmov.x %fp0,RPRIME(%a6)5286fmul.x %fp0,%fp0 # FP0 IS S = R*R5287fmov.d SINA7(%pc),%fp1 # A75288fmov.d COSB8(%pc),%fp2 # B85289fmul.x %fp0,%fp1 # SA75290fmul.x %fp0,%fp2 # SB852915292mov.l %d2,-(%sp)5293mov.l %d1,%d25294ror.l &1,%d25295and.l &0x80000000,%d25296eor.l %d1,%d25297and.l &0x80000000,%d252985299fadd.d SINA6(%pc),%fp1 # A6+SA75300fadd.d COSB7(%pc),%fp2 # B7+SB853015302fmul.x %fp0,%fp1 # S(A6+SA7)5303eor.l %d2,RPRIME(%a6)5304mov.l (%sp)+,%d25305fmul.x %fp0,%fp2 # S(B7+SB8)5306ror.l &1,%d15307and.l &0x80000000,%d15308mov.l &0x3F800000,POSNEG1(%a6)5309eor.l %d1,POSNEG1(%a6)53105311fadd.d SINA5(%pc),%fp1 # A5+S(A6+SA7)5312fadd.d COSB6(%pc),%fp2 # B6+S(B7+SB8)53135314fmul.x %fp0,%fp1 # S(A5+S(A6+SA7))5315fmul.x %fp0,%fp2 # S(B6+S(B7+SB8))5316fmov.x %fp0,SPRIME(%a6)53175318fadd.d SINA4(%pc),%fp1 # A4+S(A5+S(A6+SA7))5319eor.l %d1,SPRIME(%a6)5320fadd.d COSB5(%pc),%fp2 # B5+S(B6+S(B7+SB8))53215322fmul.x %fp0,%fp1 # S(A4+...)5323fmul.x %fp0,%fp2 # S(B5+...)53245325fadd.d SINA3(%pc),%fp1 # A3+S(A4+...)5326fadd.d COSB4(%pc),%fp2 # B4+S(B5+...)53275328fmul.x %fp0,%fp1 # S(A3+...)5329fmul.x %fp0,%fp2 # S(B4+...)53305331fadd.x SINA2(%pc),%fp1 # A2+S(A3+...)5332fadd.x COSB3(%pc),%fp2 # B3+S(B4+...)53335334fmul.x %fp0,%fp1 # S(A2+...)5335fmul.x %fp0,%fp2 # S(B3+...)53365337fadd.x SINA1(%pc),%fp1 # A1+S(A2+...)5338fadd.x COSB2(%pc),%fp2 # B2+S(B3+...)53395340fmul.x %fp0,%fp1 # S(A1+...)5341fmul.x %fp2,%fp0 # S(B2+...)53425343fmul.x RPRIME(%a6),%fp1 # R'S(A1+...)5344fadd.s COSB1(%pc),%fp0 # B1+S(B2...)5345fmul.x SPRIME(%a6),%fp0 # S'(B1+S(B2+...))53465347fmovm.x (%sp)+,&0x20 # restore fp253485349fmov.l %d0,%fpcr5350fadd.x RPRIME(%a6),%fp1 # COS(X)5351bsr sto_cos # store cosine result5352fadd.s POSNEG1(%a6),%fp0 # SIN(X)5353bra t_inx253545355NEVEN:5356#--REGISTERS SAVED SO FAR: FP2.5357fmovm.x &0x04,-(%sp) # save fp253585359fmov.x %fp0,RPRIME(%a6)5360fmul.x %fp0,%fp0 # FP0 IS S = R*R53615362fmov.d COSB8(%pc),%fp1 # B85363fmov.d SINA7(%pc),%fp2 # A753645365fmul.x %fp0,%fp1 # SB85366fmov.x %fp0,SPRIME(%a6)5367fmul.x %fp0,%fp2 # SA753685369ror.l &1,%d15370and.l &0x80000000,%d153715372fadd.d COSB7(%pc),%fp1 # B7+SB85373fadd.d SINA6(%pc),%fp2 # A6+SA753745375eor.l %d1,RPRIME(%a6)5376eor.l %d1,SPRIME(%a6)53775378fmul.x %fp0,%fp1 # S(B7+SB8)53795380or.l &0x3F800000,%d15381mov.l %d1,POSNEG1(%a6)53825383fmul.x %fp0,%fp2 # S(A6+SA7)53845385fadd.d COSB6(%pc),%fp1 # B6+S(B7+SB8)5386fadd.d SINA5(%pc),%fp2 # A5+S(A6+SA7)53875388fmul.x %fp0,%fp1 # S(B6+S(B7+SB8))5389fmul.x %fp0,%fp2 # S(A5+S(A6+SA7))53905391fadd.d COSB5(%pc),%fp1 # B5+S(B6+S(B7+SB8))5392fadd.d SINA4(%pc),%fp2 # A4+S(A5+S(A6+SA7))53935394fmul.x %fp0,%fp1 # S(B5+...)5395fmul.x %fp0,%fp2 # S(A4+...)53965397fadd.d COSB4(%pc),%fp1 # B4+S(B5+...)5398fadd.d SINA3(%pc),%fp2 # A3+S(A4+...)53995400fmul.x %fp0,%fp1 # S(B4+...)5401fmul.x %fp0,%fp2 # S(A3+...)54025403fadd.x COSB3(%pc),%fp1 # B3+S(B4+...)5404fadd.x SINA2(%pc),%fp2 # A2+S(A3+...)54055406fmul.x %fp0,%fp1 # S(B3+...)5407fmul.x %fp0,%fp2 # S(A2+...)54085409fadd.x COSB2(%pc),%fp1 # B2+S(B3+...)5410fadd.x SINA1(%pc),%fp2 # A1+S(A2+...)54115412fmul.x %fp0,%fp1 # S(B2+...)5413fmul.x %fp2,%fp0 # s(a1+...)541454155416fadd.s COSB1(%pc),%fp1 # B1+S(B2...)5417fmul.x RPRIME(%a6),%fp0 # R'S(A1+...)5418fmul.x SPRIME(%a6),%fp1 # S'(B1+S(B2+...))54195420fmovm.x (%sp)+,&0x20 # restore fp254215422fmov.l %d0,%fpcr5423fadd.s POSNEG1(%a6),%fp1 # COS(X)5424bsr sto_cos # store cosine result5425fadd.x RPRIME(%a6),%fp0 # SIN(X)5426bra t_inx254275428################################################54295430SCBORS:5431cmp.l %d1,&0x3FFF80005432bgt.w SREDUCEX54335434################################################54355436SCSM:5437# mov.w &0x0000,XDCARE(%a6)5438fmov.s &0x3F800000,%fp154395440fmov.l %d0,%fpcr5441fsub.s &0x00800000,%fp15442bsr sto_cos # store cosine result5443fmov.l %fpcr,%d0 # d0 must have fpcr,too5444mov.b &FMOV_OP,%d1 # last inst is MOVE5445fmov.x X(%a6),%fp05446bra t_catch54475448##############################################54495450global ssincosd5451#--SIN AND COS OF X FOR DENORMALIZED X5452ssincosd:5453mov.l %d0,-(%sp) # save d05454fmov.s &0x3F800000,%fp15455bsr sto_cos # store cosine result5456mov.l (%sp)+,%d0 # restore d05457bra t_extdnrm54585459############################################54605461#--WHEN REDUCEX IS USED, THE CODE WILL INEVITABLY BE SLOW.5462#--THIS REDUCTION METHOD, HOWEVER, IS MUCH FASTER THAN USING5463#--THE REMAINDER INSTRUCTION WHICH IS NOW IN SOFTWARE.5464SREDUCEX:5465fmovm.x &0x3c,-(%sp) # save {fp2-fp5}5466mov.l %d2,-(%sp) # save d25467fmov.s &0x00000000,%fp1 # fp1 = 054685469#--If compact form of abs(arg) in d0=$7ffeffff, argument is so large that5470#--there is a danger of unwanted overflow in first LOOP iteration. In this5471#--case, reduce argument by one remainder step to make subsequent reduction5472#--safe.5473cmp.l %d1,&0x7ffeffff # is arg dangerously large?5474bne.b SLOOP # no54755476# yes; create 2**16383*PI/25477mov.w &0x7ffe,FP_SCR0_EX(%a6)5478mov.l &0xc90fdaa2,FP_SCR0_HI(%a6)5479clr.l FP_SCR0_LO(%a6)54805481# create low half of 2**16383*PI/2 at FP_SCR15482mov.w &0x7fdc,FP_SCR1_EX(%a6)5483mov.l &0x85a308d3,FP_SCR1_HI(%a6)5484clr.l FP_SCR1_LO(%a6)54855486ftest.x %fp0 # test sign of argument5487fblt.w sred_neg54885489or.b &0x80,FP_SCR0_EX(%a6) # positive arg5490or.b &0x80,FP_SCR1_EX(%a6)5491sred_neg:5492fadd.x FP_SCR0(%a6),%fp0 # high part of reduction is exact5493fmov.x %fp0,%fp1 # save high result in fp15494fadd.x FP_SCR1(%a6),%fp0 # low part of reduction5495fsub.x %fp0,%fp1 # determine low component of result5496fadd.x FP_SCR1(%a6),%fp1 # fp0/fp1 are reduced argument.54975498#--ON ENTRY, FP0 IS X, ON RETURN, FP0 IS X REM PI/2, |X| <= PI/4.5499#--integer quotient will be stored in N5500#--Intermeditate remainder is 66-bit long; (R,r) in (FP0,FP1)5501SLOOP:5502fmov.x %fp0,INARG(%a6) # +-2**K * F, 1 <= F < 25503mov.w INARG(%a6),%d15504mov.l %d1,%a1 # save a copy of D05505and.l &0x00007FFF,%d15506sub.l &0x00003FFF,%d1 # d0 = K5507cmp.l %d1,&285508ble.b SLASTLOOP5509SCONTLOOP:5510sub.l &27,%d1 # d0 = L := K-275511mov.b &0,ENDFLAG(%a6)5512bra.b SWORK5513SLASTLOOP:5514clr.l %d1 # d0 = L := 05515mov.b &1,ENDFLAG(%a6)55165517SWORK:5518#--FIND THE REMAINDER OF (R,r) W.R.T. 2**L * (PI/2). L IS SO CHOSEN5519#--THAT INT( X * (2/PI) / 2**(L) ) < 2**29.55205521#--CREATE 2**(-L) * (2/PI), SIGN(INARG)*2**(63),5522#--2**L * (PIby2_1), 2**L * (PIby2_2)55235524mov.l &0x00003FFE,%d2 # BIASED EXP OF 2/PI5525sub.l %d1,%d2 # BIASED EXP OF 2**(-L)*(2/PI)55265527mov.l &0xA2F9836E,FP_SCR0_HI(%a6)5528mov.l &0x4E44152A,FP_SCR0_LO(%a6)5529mov.w %d2,FP_SCR0_EX(%a6) # FP_SCR0 = 2**(-L)*(2/PI)55305531fmov.x %fp0,%fp25532fmul.x FP_SCR0(%a6),%fp2 # fp2 = X * 2**(-L)*(2/PI)55335534#--WE MUST NOW FIND INT(FP2). SINCE WE NEED THIS VALUE IN5535#--FLOATING POINT FORMAT, THE TWO FMOVE'S FMOVE.L FP <--> N5536#--WILL BE TOO INEFFICIENT. THE WAY AROUND IT IS THAT5537#--(SIGN(INARG)*2**63 + FP2) - SIGN(INARG)*2**63 WILL GIVE5538#--US THE DESIRED VALUE IN FLOATING POINT.5539mov.l %a1,%d25540swap %d25541and.l &0x80000000,%d25542or.l &0x5F000000,%d2 # d2 = SIGN(INARG)*2**63 IN SGL5543mov.l %d2,TWOTO63(%a6)5544fadd.s TWOTO63(%a6),%fp2 # THE FRACTIONAL PART OF FP1 IS ROUNDED5545fsub.s TWOTO63(%a6),%fp2 # fp2 = N5546# fint.x %fp255475548#--CREATING 2**(L)*Piby2_1 and 2**(L)*Piby2_25549mov.l %d1,%d2 # d2 = L55505551add.l &0x00003FFF,%d2 # BIASED EXP OF 2**L * (PI/2)5552mov.w %d2,FP_SCR0_EX(%a6)5553mov.l &0xC90FDAA2,FP_SCR0_HI(%a6)5554clr.l FP_SCR0_LO(%a6) # FP_SCR0 = 2**(L) * Piby2_155555556add.l &0x00003FDD,%d15557mov.w %d1,FP_SCR1_EX(%a6)5558mov.l &0x85A308D3,FP_SCR1_HI(%a6)5559clr.l FP_SCR1_LO(%a6) # FP_SCR1 = 2**(L) * Piby2_255605561mov.b ENDFLAG(%a6),%d155625563#--We are now ready to perform (R+r) - N*P1 - N*P2, P1 = 2**(L) * Piby2_1 and5564#--P2 = 2**(L) * Piby2_25565fmov.x %fp2,%fp4 # fp4 = N5566fmul.x FP_SCR0(%a6),%fp4 # fp4 = W = N*P15567fmov.x %fp2,%fp5 # fp5 = N5568fmul.x FP_SCR1(%a6),%fp5 # fp5 = w = N*P25569fmov.x %fp4,%fp3 # fp3 = W = N*P155705571#--we want P+p = W+w but |p| <= half ulp of P5572#--Then, we need to compute A := R-P and a := r-p5573fadd.x %fp5,%fp3 # fp3 = P5574fsub.x %fp3,%fp4 # fp4 = W-P55755576fsub.x %fp3,%fp0 # fp0 = A := R - P5577fadd.x %fp5,%fp4 # fp4 = p = (W-P)+w55785579fmov.x %fp0,%fp3 # fp3 = A5580fsub.x %fp4,%fp1 # fp1 = a := r - p55815582#--Now we need to normalize (A,a) to "new (R,r)" where R+r = A+a but5583#--|r| <= half ulp of R.5584fadd.x %fp1,%fp0 # fp0 = R := A+a5585#--No need to calculate r if this is the last loop5586cmp.b %d1,&05587bgt.w SRESTORE55885589#--Need to calculate r5590fsub.x %fp0,%fp3 # fp3 = A-R5591fadd.x %fp3,%fp1 # fp1 = r := (A-R)+a5592bra.w SLOOP55935594SRESTORE:5595fmov.l %fp2,INT(%a6)5596mov.l (%sp)+,%d2 # restore d25597fmovm.x (%sp)+,&0x3c # restore {fp2-fp5}55985599mov.l ADJN(%a6),%d15600cmp.l %d1,&456015602blt.w SINCONT5603bra.w SCCONT56045605#########################################################################5606# stan(): computes the tangent of a normalized input #5607# stand(): computes the tangent of a denormalized input #5608# #5609# INPUT *************************************************************** #5610# a0 = pointer to extended precision input #5611# d0 = round precision,mode #5612# #5613# OUTPUT ************************************************************** #5614# fp0 = tan(X) #5615# #5616# ACCURACY and MONOTONICITY ******************************************* #5617# The returned result is within 3 ulp in 64 significant bit, i.e. #5618# within 0.5001 ulp to 53 bits if the result is subsequently #5619# rounded to double precision. The result is provably monotonic #5620# in double precision. #5621# #5622# ALGORITHM *********************************************************** #5623# #5624# 1. If |X| >= 15Pi or |X| < 2**(-40), go to 6. #5625# #5626# 2. Decompose X as X = N(Pi/2) + r where |r| <= Pi/4. Let #5627# k = N mod 2, so in particular, k = 0 or 1. #5628# #5629# 3. If k is odd, go to 5. #5630# #5631# 4. (k is even) Tan(X) = tan(r) and tan(r) is approximated by a #5632# rational function U/V where #5633# U = r + r*s*(P1 + s*(P2 + s*P3)), and #5634# V = 1 + s*(Q1 + s*(Q2 + s*(Q3 + s*Q4))), s = r*r. #5635# Exit. #5636# #5637# 4. (k is odd) Tan(X) = -cot(r). Since tan(r) is approximated by #5638# a rational function U/V where #5639# U = r + r*s*(P1 + s*(P2 + s*P3)), and #5640# V = 1 + s*(Q1 + s*(Q2 + s*(Q3 + s*Q4))), s = r*r, #5641# -Cot(r) = -V/U. Exit. #5642# #5643# 6. If |X| > 1, go to 8. #5644# #5645# 7. (|X|<2**(-40)) Tan(X) = X. Exit. #5646# #5647# 8. Overwrite X by X := X rem 2Pi. Now that |X| <= Pi, go back #5648# to 2. #5649# #5650#########################################################################56515652TANQ4:5653long 0x3EA0B759,0xF50F86885654TANP3:5655long 0xBEF2BAA5,0xA8924F0456565657TANQ3:5658long 0xBF346F59,0xB39BA65F,0x00000000,0x0000000056595660TANP2:5661long 0x3FF60000,0xE073D3FC,0x199C4A00,0x0000000056625663TANQ2:5664long 0x3FF90000,0xD23CD684,0x15D95FA1,0x0000000056655666TANP1:5667long 0xBFFC0000,0x8895A6C5,0xFB423BCA,0x0000000056685669TANQ1:5670long 0xBFFD0000,0xEEF57E0D,0xA84BC8CE,0x0000000056715672INVTWOPI:5673long 0x3FFC0000,0xA2F9836E,0x4E44152A,0x0000000056745675TWOPI1:5676long 0x40010000,0xC90FDAA2,0x00000000,0x000000005677TWOPI2:5678long 0x3FDF0000,0x85A308D4,0x00000000,0x0000000056795680#--N*PI/2, -32 <= N <= 32, IN A LEADING TERM IN EXT. AND TRAILING5681#--TERM IN SGL. NOTE THAT PI IS 64-BIT LONG, THUS N*PI/2 IS AT5682#--MOST 69 BITS LONG.5683# global PITBL5684PITBL:5685long 0xC0040000,0xC90FDAA2,0x2168C235,0x218000005686long 0xC0040000,0xC2C75BCD,0x105D7C23,0xA0D000005687long 0xC0040000,0xBC7EDCF7,0xFF523611,0xA1E800005688long 0xC0040000,0xB6365E22,0xEE46F000,0x214800005689long 0xC0040000,0xAFEDDF4D,0xDD3BA9EE,0xA12000005690long 0xC0040000,0xA9A56078,0xCC3063DD,0x21FC00005691long 0xC0040000,0xA35CE1A3,0xBB251DCB,0x211000005692long 0xC0040000,0x9D1462CE,0xAA19D7B9,0xA15800005693long 0xC0040000,0x96CBE3F9,0x990E91A8,0x21E000005694long 0xC0040000,0x90836524,0x88034B96,0x20B000005695long 0xC0040000,0x8A3AE64F,0x76F80584,0xA18800005696long 0xC0040000,0x83F2677A,0x65ECBF73,0x21C400005697long 0xC0030000,0xFB53D14A,0xA9C2F2C2,0x200000005698long 0xC0030000,0xEEC2D3A0,0x87AC669F,0x213800005699long 0xC0030000,0xE231D5F6,0x6595DA7B,0xA13000005700long 0xC0030000,0xD5A0D84C,0x437F4E58,0x9FC000005701long 0xC0030000,0xC90FDAA2,0x2168C235,0x210000005702long 0xC0030000,0xBC7EDCF7,0xFF523611,0xA16800005703long 0xC0030000,0xAFEDDF4D,0xDD3BA9EE,0xA0A000005704long 0xC0030000,0xA35CE1A3,0xBB251DCB,0x209000005705long 0xC0030000,0x96CBE3F9,0x990E91A8,0x216000005706long 0xC0030000,0x8A3AE64F,0x76F80584,0xA10800005707long 0xC0020000,0xFB53D14A,0xA9C2F2C2,0x1F8000005708long 0xC0020000,0xE231D5F6,0x6595DA7B,0xA0B000005709long 0xC0020000,0xC90FDAA2,0x2168C235,0x208000005710long 0xC0020000,0xAFEDDF4D,0xDD3BA9EE,0xA02000005711long 0xC0020000,0x96CBE3F9,0x990E91A8,0x20E000005712long 0xC0010000,0xFB53D14A,0xA9C2F2C2,0x1F0000005713long 0xC0010000,0xC90FDAA2,0x2168C235,0x200000005714long 0xC0010000,0x96CBE3F9,0x990E91A8,0x206000005715long 0xC0000000,0xC90FDAA2,0x2168C235,0x1F8000005716long 0xBFFF0000,0xC90FDAA2,0x2168C235,0x1F0000005717long 0x00000000,0x00000000,0x00000000,0x000000005718long 0x3FFF0000,0xC90FDAA2,0x2168C235,0x9F0000005719long 0x40000000,0xC90FDAA2,0x2168C235,0x9F8000005720long 0x40010000,0x96CBE3F9,0x990E91A8,0xA06000005721long 0x40010000,0xC90FDAA2,0x2168C235,0xA00000005722long 0x40010000,0xFB53D14A,0xA9C2F2C2,0x9F0000005723long 0x40020000,0x96CBE3F9,0x990E91A8,0xA0E000005724long 0x40020000,0xAFEDDF4D,0xDD3BA9EE,0x202000005725long 0x40020000,0xC90FDAA2,0x2168C235,0xA08000005726long 0x40020000,0xE231D5F6,0x6595DA7B,0x20B000005727long 0x40020000,0xFB53D14A,0xA9C2F2C2,0x9F8000005728long 0x40030000,0x8A3AE64F,0x76F80584,0x210800005729long 0x40030000,0x96CBE3F9,0x990E91A8,0xA16000005730long 0x40030000,0xA35CE1A3,0xBB251DCB,0xA09000005731long 0x40030000,0xAFEDDF4D,0xDD3BA9EE,0x20A000005732long 0x40030000,0xBC7EDCF7,0xFF523611,0x216800005733long 0x40030000,0xC90FDAA2,0x2168C235,0xA10000005734long 0x40030000,0xD5A0D84C,0x437F4E58,0x1FC000005735long 0x40030000,0xE231D5F6,0x6595DA7B,0x213000005736long 0x40030000,0xEEC2D3A0,0x87AC669F,0xA13800005737long 0x40030000,0xFB53D14A,0xA9C2F2C2,0xA00000005738long 0x40040000,0x83F2677A,0x65ECBF73,0xA1C400005739long 0x40040000,0x8A3AE64F,0x76F80584,0x218800005740long 0x40040000,0x90836524,0x88034B96,0xA0B000005741long 0x40040000,0x96CBE3F9,0x990E91A8,0xA1E000005742long 0x40040000,0x9D1462CE,0xAA19D7B9,0x215800005743long 0x40040000,0xA35CE1A3,0xBB251DCB,0xA11000005744long 0x40040000,0xA9A56078,0xCC3063DD,0xA1FC00005745long 0x40040000,0xAFEDDF4D,0xDD3BA9EE,0x212000005746long 0x40040000,0xB6365E22,0xEE46F000,0xA14800005747long 0x40040000,0xBC7EDCF7,0xFF523611,0x21E800005748long 0x40040000,0xC2C75BCD,0x105D7C23,0x20D000005749long 0x40040000,0xC90FDAA2,0x2168C235,0xA180000057505751set INARG,FP_SCR057525753set TWOTO63,L_SCR15754set INT,L_SCR15755set ENDFLAG,L_SCR257565757global stan5758stan:5759fmov.x (%a0),%fp0 # LOAD INPUT57605761mov.l (%a0),%d15762mov.w 4(%a0),%d15763and.l &0x7FFFFFFF,%d157645765cmp.l %d1,&0x3FD78000 # |X| >= 2**(-40)?5766bge.b TANOK15767bra.w TANSM5768TANOK1:5769cmp.l %d1,&0x4004BC7E # |X| < 15 PI?5770blt.b TANMAIN5771bra.w REDUCEX57725773TANMAIN:5774#--THIS IS THE USUAL CASE, |X| <= 15 PI.5775#--THE ARGUMENT REDUCTION IS DONE BY TABLE LOOK UP.5776fmov.x %fp0,%fp15777fmul.d TWOBYPI(%pc),%fp1 # X*2/PI57785779lea.l PITBL+0x200(%pc),%a1 # TABLE OF N*PI/2, N = -32,...,3257805781fmov.l %fp1,%d1 # CONVERT TO INTEGER57825783asl.l &4,%d15784add.l %d1,%a1 # ADDRESS N*PIBY2 IN Y1, Y257855786fsub.x (%a1)+,%fp0 # X-Y157875788fsub.s (%a1),%fp0 # FP0 IS R = (X-Y1)-Y257895790ror.l &5,%d15791and.l &0x80000000,%d1 # D0 WAS ODD IFF D0 < 057925793TANCONT:5794fmovm.x &0x0c,-(%sp) # save fp2,fp357955796cmp.l %d1,&05797blt.w NODD57985799fmov.x %fp0,%fp15800fmul.x %fp1,%fp1 # S = R*R58015802fmov.d TANQ4(%pc),%fp35803fmov.d TANP3(%pc),%fp258045805fmul.x %fp1,%fp3 # SQ45806fmul.x %fp1,%fp2 # SP358075808fadd.d TANQ3(%pc),%fp3 # Q3+SQ45809fadd.x TANP2(%pc),%fp2 # P2+SP358105811fmul.x %fp1,%fp3 # S(Q3+SQ4)5812fmul.x %fp1,%fp2 # S(P2+SP3)58135814fadd.x TANQ2(%pc),%fp3 # Q2+S(Q3+SQ4)5815fadd.x TANP1(%pc),%fp2 # P1+S(P2+SP3)58165817fmul.x %fp1,%fp3 # S(Q2+S(Q3+SQ4))5818fmul.x %fp1,%fp2 # S(P1+S(P2+SP3))58195820fadd.x TANQ1(%pc),%fp3 # Q1+S(Q2+S(Q3+SQ4))5821fmul.x %fp0,%fp2 # RS(P1+S(P2+SP3))58225823fmul.x %fp3,%fp1 # S(Q1+S(Q2+S(Q3+SQ4)))58245825fadd.x %fp2,%fp0 # R+RS(P1+S(P2+SP3))58265827fadd.s &0x3F800000,%fp1 # 1+S(Q1+...)58285829fmovm.x (%sp)+,&0x30 # restore fp2,fp358305831fmov.l %d0,%fpcr # restore users round mode,prec5832fdiv.x %fp1,%fp0 # last inst - possible exception set5833bra t_inx258345835NODD:5836fmov.x %fp0,%fp15837fmul.x %fp0,%fp0 # S = R*R58385839fmov.d TANQ4(%pc),%fp35840fmov.d TANP3(%pc),%fp258415842fmul.x %fp0,%fp3 # SQ45843fmul.x %fp0,%fp2 # SP358445845fadd.d TANQ3(%pc),%fp3 # Q3+SQ45846fadd.x TANP2(%pc),%fp2 # P2+SP358475848fmul.x %fp0,%fp3 # S(Q3+SQ4)5849fmul.x %fp0,%fp2 # S(P2+SP3)58505851fadd.x TANQ2(%pc),%fp3 # Q2+S(Q3+SQ4)5852fadd.x TANP1(%pc),%fp2 # P1+S(P2+SP3)58535854fmul.x %fp0,%fp3 # S(Q2+S(Q3+SQ4))5855fmul.x %fp0,%fp2 # S(P1+S(P2+SP3))58565857fadd.x TANQ1(%pc),%fp3 # Q1+S(Q2+S(Q3+SQ4))5858fmul.x %fp1,%fp2 # RS(P1+S(P2+SP3))58595860fmul.x %fp3,%fp0 # S(Q1+S(Q2+S(Q3+SQ4)))58615862fadd.x %fp2,%fp1 # R+RS(P1+S(P2+SP3))5863fadd.s &0x3F800000,%fp0 # 1+S(Q1+...)58645865fmovm.x (%sp)+,&0x30 # restore fp2,fp358665867fmov.x %fp1,-(%sp)5868eor.l &0x80000000,(%sp)58695870fmov.l %d0,%fpcr # restore users round mode,prec5871fdiv.x (%sp)+,%fp0 # last inst - possible exception set5872bra t_inx258735874TANBORS:5875#--IF |X| > 15PI, WE USE THE GENERAL ARGUMENT REDUCTION.5876#--IF |X| < 2**(-40), RETURN X OR 1.5877cmp.l %d1,&0x3FFF80005878bgt.b REDUCEX58795880TANSM:5881fmov.x %fp0,-(%sp)5882fmov.l %d0,%fpcr # restore users round mode,prec5883mov.b &FMOV_OP,%d1 # last inst is MOVE5884fmov.x (%sp)+,%fp0 # last inst - posibble exception set5885bra t_catch58865887global stand5888#--TAN(X) = X FOR DENORMALIZED X5889stand:5890bra t_extdnrm58915892#--WHEN REDUCEX IS USED, THE CODE WILL INEVITABLY BE SLOW.5893#--THIS REDUCTION METHOD, HOWEVER, IS MUCH FASTER THAN USING5894#--THE REMAINDER INSTRUCTION WHICH IS NOW IN SOFTWARE.5895REDUCEX:5896fmovm.x &0x3c,-(%sp) # save {fp2-fp5}5897mov.l %d2,-(%sp) # save d25898fmov.s &0x00000000,%fp1 # fp1 = 058995900#--If compact form of abs(arg) in d0=$7ffeffff, argument is so large that5901#--there is a danger of unwanted overflow in first LOOP iteration. In this5902#--case, reduce argument by one remainder step to make subsequent reduction5903#--safe.5904cmp.l %d1,&0x7ffeffff # is arg dangerously large?5905bne.b LOOP # no59065907# yes; create 2**16383*PI/25908mov.w &0x7ffe,FP_SCR0_EX(%a6)5909mov.l &0xc90fdaa2,FP_SCR0_HI(%a6)5910clr.l FP_SCR0_LO(%a6)59115912# create low half of 2**16383*PI/2 at FP_SCR15913mov.w &0x7fdc,FP_SCR1_EX(%a6)5914mov.l &0x85a308d3,FP_SCR1_HI(%a6)5915clr.l FP_SCR1_LO(%a6)59165917ftest.x %fp0 # test sign of argument5918fblt.w red_neg59195920or.b &0x80,FP_SCR0_EX(%a6) # positive arg5921or.b &0x80,FP_SCR1_EX(%a6)5922red_neg:5923fadd.x FP_SCR0(%a6),%fp0 # high part of reduction is exact5924fmov.x %fp0,%fp1 # save high result in fp15925fadd.x FP_SCR1(%a6),%fp0 # low part of reduction5926fsub.x %fp0,%fp1 # determine low component of result5927fadd.x FP_SCR1(%a6),%fp1 # fp0/fp1 are reduced argument.59285929#--ON ENTRY, FP0 IS X, ON RETURN, FP0 IS X REM PI/2, |X| <= PI/4.5930#--integer quotient will be stored in N5931#--Intermeditate remainder is 66-bit long; (R,r) in (FP0,FP1)5932LOOP:5933fmov.x %fp0,INARG(%a6) # +-2**K * F, 1 <= F < 25934mov.w INARG(%a6),%d15935mov.l %d1,%a1 # save a copy of D05936and.l &0x00007FFF,%d15937sub.l &0x00003FFF,%d1 # d0 = K5938cmp.l %d1,&285939ble.b LASTLOOP5940CONTLOOP:5941sub.l &27,%d1 # d0 = L := K-275942mov.b &0,ENDFLAG(%a6)5943bra.b WORK5944LASTLOOP:5945clr.l %d1 # d0 = L := 05946mov.b &1,ENDFLAG(%a6)59475948WORK:5949#--FIND THE REMAINDER OF (R,r) W.R.T. 2**L * (PI/2). L IS SO CHOSEN5950#--THAT INT( X * (2/PI) / 2**(L) ) < 2**29.59515952#--CREATE 2**(-L) * (2/PI), SIGN(INARG)*2**(63),5953#--2**L * (PIby2_1), 2**L * (PIby2_2)59545955mov.l &0x00003FFE,%d2 # BIASED EXP OF 2/PI5956sub.l %d1,%d2 # BIASED EXP OF 2**(-L)*(2/PI)59575958mov.l &0xA2F9836E,FP_SCR0_HI(%a6)5959mov.l &0x4E44152A,FP_SCR0_LO(%a6)5960mov.w %d2,FP_SCR0_EX(%a6) # FP_SCR0 = 2**(-L)*(2/PI)59615962fmov.x %fp0,%fp25963fmul.x FP_SCR0(%a6),%fp2 # fp2 = X * 2**(-L)*(2/PI)59645965#--WE MUST NOW FIND INT(FP2). SINCE WE NEED THIS VALUE IN5966#--FLOATING POINT FORMAT, THE TWO FMOVE'S FMOVE.L FP <--> N5967#--WILL BE TOO INEFFICIENT. THE WAY AROUND IT IS THAT5968#--(SIGN(INARG)*2**63 + FP2) - SIGN(INARG)*2**63 WILL GIVE5969#--US THE DESIRED VALUE IN FLOATING POINT.5970mov.l %a1,%d25971swap %d25972and.l &0x80000000,%d25973or.l &0x5F000000,%d2 # d2 = SIGN(INARG)*2**63 IN SGL5974mov.l %d2,TWOTO63(%a6)5975fadd.s TWOTO63(%a6),%fp2 # THE FRACTIONAL PART OF FP1 IS ROUNDED5976fsub.s TWOTO63(%a6),%fp2 # fp2 = N5977# fintrz.x %fp2,%fp259785979#--CREATING 2**(L)*Piby2_1 and 2**(L)*Piby2_25980mov.l %d1,%d2 # d2 = L59815982add.l &0x00003FFF,%d2 # BIASED EXP OF 2**L * (PI/2)5983mov.w %d2,FP_SCR0_EX(%a6)5984mov.l &0xC90FDAA2,FP_SCR0_HI(%a6)5985clr.l FP_SCR0_LO(%a6) # FP_SCR0 = 2**(L) * Piby2_159865987add.l &0x00003FDD,%d15988mov.w %d1,FP_SCR1_EX(%a6)5989mov.l &0x85A308D3,FP_SCR1_HI(%a6)5990clr.l FP_SCR1_LO(%a6) # FP_SCR1 = 2**(L) * Piby2_259915992mov.b ENDFLAG(%a6),%d159935994#--We are now ready to perform (R+r) - N*P1 - N*P2, P1 = 2**(L) * Piby2_1 and5995#--P2 = 2**(L) * Piby2_25996fmov.x %fp2,%fp4 # fp4 = N5997fmul.x FP_SCR0(%a6),%fp4 # fp4 = W = N*P15998fmov.x %fp2,%fp5 # fp5 = N5999fmul.x FP_SCR1(%a6),%fp5 # fp5 = w = N*P26000fmov.x %fp4,%fp3 # fp3 = W = N*P160016002#--we want P+p = W+w but |p| <= half ulp of P6003#--Then, we need to compute A := R-P and a := r-p6004fadd.x %fp5,%fp3 # fp3 = P6005fsub.x %fp3,%fp4 # fp4 = W-P60066007fsub.x %fp3,%fp0 # fp0 = A := R - P6008fadd.x %fp5,%fp4 # fp4 = p = (W-P)+w60096010fmov.x %fp0,%fp3 # fp3 = A6011fsub.x %fp4,%fp1 # fp1 = a := r - p60126013#--Now we need to normalize (A,a) to "new (R,r)" where R+r = A+a but6014#--|r| <= half ulp of R.6015fadd.x %fp1,%fp0 # fp0 = R := A+a6016#--No need to calculate r if this is the last loop6017cmp.b %d1,&06018bgt.w RESTORE60196020#--Need to calculate r6021fsub.x %fp0,%fp3 # fp3 = A-R6022fadd.x %fp3,%fp1 # fp1 = r := (A-R)+a6023bra.w LOOP60246025RESTORE:6026fmov.l %fp2,INT(%a6)6027mov.l (%sp)+,%d2 # restore d26028fmovm.x (%sp)+,&0x3c # restore {fp2-fp5}60296030mov.l INT(%a6),%d16031ror.l &1,%d160326033bra.w TANCONT60346035#########################################################################6036# satan(): computes the arctangent of a normalized number #6037# satand(): computes the arctangent of a denormalized number #6038# #6039# INPUT *************************************************************** #6040# a0 = pointer to extended precision input #6041# d0 = round precision,mode #6042# #6043# OUTPUT ************************************************************** #6044# fp0 = arctan(X) #6045# #6046# ACCURACY and MONOTONICITY ******************************************* #6047# The returned result is within 2 ulps in 64 significant bit, #6048# i.e. within 0.5001 ulp to 53 bits if the result is subsequently #6049# rounded to double precision. The result is provably monotonic #6050# in double precision. #6051# #6052# ALGORITHM *********************************************************** #6053# Step 1. If |X| >= 16 or |X| < 1/16, go to Step 5. #6054# #6055# Step 2. Let X = sgn * 2**k * 1.xxxxxxxx...x. #6056# Note that k = -4, -3,..., or 3. #6057# Define F = sgn * 2**k * 1.xxxx1, i.e. the first 5 #6058# significant bits of X with a bit-1 attached at the 6-th #6059# bit position. Define u to be u = (X-F) / (1 + X*F). #6060# #6061# Step 3. Approximate arctan(u) by a polynomial poly. #6062# #6063# Step 4. Return arctan(F) + poly, arctan(F) is fetched from a #6064# table of values calculated beforehand. Exit. #6065# #6066# Step 5. If |X| >= 16, go to Step 7. #6067# #6068# Step 6. Approximate arctan(X) by an odd polynomial in X. Exit. #6069# #6070# Step 7. Define X' = -1/X. Approximate arctan(X') by an odd #6071# polynomial in X'. #6072# Arctan(X) = sign(X)*Pi/2 + arctan(X'). Exit. #6073# #6074#########################################################################60756076ATANA3: long 0xBFF6687E,0x314987D86077ATANA2: long 0x4002AC69,0x34A26DB36078ATANA1: long 0xBFC2476F,0x4E1DA28E60796080ATANB6: long 0x3FB34444,0x7F8769896081ATANB5: long 0xBFB744EE,0x7FAF45DB6082ATANB4: long 0x3FBC71C6,0x469402206083ATANB3: long 0xBFC24924,0x921872F96084ATANB2: long 0x3FC99999,0x99998FA96085ATANB1: long 0xBFD55555,0x5555555560866087ATANC5: long 0xBFB70BF3,0x98539E6A6088ATANC4: long 0x3FBC7187,0x962D1D7D6089ATANC3: long 0xBFC24924,0x827107B86090ATANC2: long 0x3FC99999,0x9996263E6091ATANC1: long 0xBFD55555,0x5555553660926093PPIBY2: long 0x3FFF0000,0xC90FDAA2,0x2168C235,0x000000006094NPIBY2: long 0xBFFF0000,0xC90FDAA2,0x2168C235,0x0000000060956096PTINY: long 0x00010000,0x80000000,0x00000000,0x000000006097NTINY: long 0x80010000,0x80000000,0x00000000,0x0000000060986099ATANTBL:6100long 0x3FFB0000,0x83D152C5,0x060B7A51,0x000000006101long 0x3FFB0000,0x8BC85445,0x65498B8B,0x000000006102long 0x3FFB0000,0x93BE4060,0x17626B0D,0x000000006103long 0x3FFB0000,0x9BB3078D,0x35AEC202,0x000000006104long 0x3FFB0000,0xA3A69A52,0x5DDCE7DE,0x000000006105long 0x3FFB0000,0xAB98E943,0x62765619,0x000000006106long 0x3FFB0000,0xB389E502,0xF9C59862,0x000000006107long 0x3FFB0000,0xBB797E43,0x6B09E6FB,0x000000006108long 0x3FFB0000,0xC367A5C7,0x39E5F446,0x000000006109long 0x3FFB0000,0xCB544C61,0xCFF7D5C6,0x000000006110long 0x3FFB0000,0xD33F62F8,0x2488533E,0x000000006111long 0x3FFB0000,0xDB28DA81,0x62404C77,0x000000006112long 0x3FFB0000,0xE310A407,0x8AD34F18,0x000000006113long 0x3FFB0000,0xEAF6B0A8,0x188EE1EB,0x000000006114long 0x3FFB0000,0xF2DAF194,0x9DBE79D5,0x000000006115long 0x3FFB0000,0xFABD5813,0x61D47E3E,0x000000006116long 0x3FFC0000,0x8346AC21,0x0959ECC4,0x000000006117long 0x3FFC0000,0x8B232A08,0x304282D8,0x000000006118long 0x3FFC0000,0x92FB70B8,0xD29AE2F9,0x000000006119long 0x3FFC0000,0x9ACF476F,0x5CCD1CB4,0x000000006120long 0x3FFC0000,0xA29E7630,0x4954F23F,0x000000006121long 0x3FFC0000,0xAA68C5D0,0x8AB85230,0x000000006122long 0x3FFC0000,0xB22DFFFD,0x9D539F83,0x000000006123long 0x3FFC0000,0xB9EDEF45,0x3E900EA5,0x000000006124long 0x3FFC0000,0xC1A85F1C,0xC75E3EA5,0x000000006125long 0x3FFC0000,0xC95D1BE8,0x28138DE6,0x000000006126long 0x3FFC0000,0xD10BF300,0x840D2DE4,0x000000006127long 0x3FFC0000,0xD8B4B2BA,0x6BC05E7A,0x000000006128long 0x3FFC0000,0xE0572A6B,0xB42335F6,0x000000006129long 0x3FFC0000,0xE7F32A70,0xEA9CAA8F,0x000000006130long 0x3FFC0000,0xEF888432,0x64ECEFAA,0x000000006131long 0x3FFC0000,0xF7170A28,0xECC06666,0x000000006132long 0x3FFD0000,0x812FD288,0x332DAD32,0x000000006133long 0x3FFD0000,0x88A8D1B1,0x218E4D64,0x000000006134long 0x3FFD0000,0x9012AB3F,0x23E4AEE8,0x000000006135long 0x3FFD0000,0x976CC3D4,0x11E7F1B9,0x000000006136long 0x3FFD0000,0x9EB68949,0x3889A227,0x000000006137long 0x3FFD0000,0xA5EF72C3,0x4487361B,0x000000006138long 0x3FFD0000,0xAD1700BA,0xF07A7227,0x000000006139long 0x3FFD0000,0xB42CBCFA,0xFD37EFB7,0x000000006140long 0x3FFD0000,0xBB303A94,0x0BA80F89,0x000000006141long 0x3FFD0000,0xC22115C6,0xFCAEBBAF,0x000000006142long 0x3FFD0000,0xC8FEF3E6,0x86331221,0x000000006143long 0x3FFD0000,0xCFC98330,0xB4000C70,0x000000006144long 0x3FFD0000,0xD6807AA1,0x102C5BF9,0x000000006145long 0x3FFD0000,0xDD2399BC,0x31252AA3,0x000000006146long 0x3FFD0000,0xE3B2A855,0x6B8FC517,0x000000006147long 0x3FFD0000,0xEA2D764F,0x64315989,0x000000006148long 0x3FFD0000,0xF3BF5BF8,0xBAD1A21D,0x000000006149long 0x3FFE0000,0x801CE39E,0x0D205C9A,0x000000006150long 0x3FFE0000,0x8630A2DA,0xDA1ED066,0x000000006151long 0x3FFE0000,0x8C1AD445,0xF3E09B8C,0x000000006152long 0x3FFE0000,0x91DB8F16,0x64F350E2,0x000000006153long 0x3FFE0000,0x97731420,0x365E538C,0x000000006154long 0x3FFE0000,0x9CE1C8E6,0xA0B8CDBA,0x000000006155long 0x3FFE0000,0xA22832DB,0xCADAAE09,0x000000006156long 0x3FFE0000,0xA746F2DD,0xB7602294,0x000000006157long 0x3FFE0000,0xAC3EC0FB,0x997DD6A2,0x000000006158long 0x3FFE0000,0xB110688A,0xEBDC6F6A,0x000000006159long 0x3FFE0000,0xB5BCC490,0x59ECC4B0,0x000000006160long 0x3FFE0000,0xBA44BC7D,0xD470782F,0x000000006161long 0x3FFE0000,0xBEA94144,0xFD049AAC,0x000000006162long 0x3FFE0000,0xC2EB4ABB,0x661628B6,0x000000006163long 0x3FFE0000,0xC70BD54C,0xE602EE14,0x000000006164long 0x3FFE0000,0xCD000549,0xADEC7159,0x000000006165long 0x3FFE0000,0xD48457D2,0xD8EA4EA3,0x000000006166long 0x3FFE0000,0xDB948DA7,0x12DECE3B,0x000000006167long 0x3FFE0000,0xE23855F9,0x69E8096A,0x000000006168long 0x3FFE0000,0xE8771129,0xC4353259,0x000000006169long 0x3FFE0000,0xEE57C16E,0x0D379C0D,0x000000006170long 0x3FFE0000,0xF3E10211,0xA87C3779,0x000000006171long 0x3FFE0000,0xF919039D,0x758B8D41,0x000000006172long 0x3FFE0000,0xFE058B8F,0x64935FB3,0x000000006173long 0x3FFF0000,0x8155FB49,0x7B685D04,0x000000006174long 0x3FFF0000,0x83889E35,0x49D108E1,0x000000006175long 0x3FFF0000,0x859CFA76,0x511D724B,0x000000006176long 0x3FFF0000,0x87952ECF,0xFF8131E7,0x000000006177long 0x3FFF0000,0x89732FD1,0x9557641B,0x000000006178long 0x3FFF0000,0x8B38CAD1,0x01932A35,0x000000006179long 0x3FFF0000,0x8CE7A8D8,0x301EE6B5,0x000000006180long 0x3FFF0000,0x8F46A39E,0x2EAE5281,0x000000006181long 0x3FFF0000,0x922DA7D7,0x91888487,0x000000006182long 0x3FFF0000,0x94D19FCB,0xDEDF5241,0x000000006183long 0x3FFF0000,0x973AB944,0x19D2A08B,0x000000006184long 0x3FFF0000,0x996FF00E,0x08E10B96,0x000000006185long 0x3FFF0000,0x9B773F95,0x12321DA7,0x000000006186long 0x3FFF0000,0x9D55CC32,0x0F935624,0x000000006187long 0x3FFF0000,0x9F100575,0x006CC571,0x000000006188long 0x3FFF0000,0xA0A9C290,0xD97CC06C,0x000000006189long 0x3FFF0000,0xA22659EB,0xEBC0630A,0x000000006190long 0x3FFF0000,0xA388B4AF,0xF6EF0EC9,0x000000006191long 0x3FFF0000,0xA4D35F10,0x61D292C4,0x000000006192long 0x3FFF0000,0xA60895DC,0xFBE3187E,0x000000006193long 0x3FFF0000,0xA72A51DC,0x7367BEAC,0x000000006194long 0x3FFF0000,0xA83A5153,0x0956168F,0x000000006195long 0x3FFF0000,0xA93A2007,0x7539546E,0x000000006196long 0x3FFF0000,0xAA9E7245,0x023B2605,0x000000006197long 0x3FFF0000,0xAC4C84BA,0x6FE4D58F,0x000000006198long 0x3FFF0000,0xADCE4A4A,0x606B9712,0x000000006199long 0x3FFF0000,0xAF2A2DCD,0x8D263C9C,0x000000006200long 0x3FFF0000,0xB0656F81,0xF22265C7,0x000000006201long 0x3FFF0000,0xB1846515,0x0F71496A,0x000000006202long 0x3FFF0000,0xB28AAA15,0x6F9ADA35,0x000000006203long 0x3FFF0000,0xB37B44FF,0x3766B895,0x000000006204long 0x3FFF0000,0xB458C3DC,0xE9630433,0x000000006205long 0x3FFF0000,0xB525529D,0x562246BD,0x000000006206long 0x3FFF0000,0xB5E2CCA9,0x5F9D88CC,0x000000006207long 0x3FFF0000,0xB692CADA,0x7ACA1ADA,0x000000006208long 0x3FFF0000,0xB736AEA7,0xA6925838,0x000000006209long 0x3FFF0000,0xB7CFAB28,0x7E9F7B36,0x000000006210long 0x3FFF0000,0xB85ECC66,0xCB219835,0x000000006211long 0x3FFF0000,0xB8E4FD5A,0x20A593DA,0x000000006212long 0x3FFF0000,0xB99F41F6,0x4AFF9BB5,0x000000006213long 0x3FFF0000,0xBA7F1E17,0x842BBE7B,0x000000006214long 0x3FFF0000,0xBB471285,0x7637E17D,0x000000006215long 0x3FFF0000,0xBBFABE8A,0x4788DF6F,0x000000006216long 0x3FFF0000,0xBC9D0FAD,0x2B689D79,0x000000006217long 0x3FFF0000,0xBD306A39,0x471ECD86,0x000000006218long 0x3FFF0000,0xBDB6C731,0x856AF18A,0x000000006219long 0x3FFF0000,0xBE31CAC5,0x02E80D70,0x000000006220long 0x3FFF0000,0xBEA2D55C,0xE33194E2,0x000000006221long 0x3FFF0000,0xBF0B10B7,0xC03128F0,0x000000006222long 0x3FFF0000,0xBF6B7A18,0xDACB778D,0x000000006223long 0x3FFF0000,0xBFC4EA46,0x63FA18F6,0x000000006224long 0x3FFF0000,0xC0181BDE,0x8B89A454,0x000000006225long 0x3FFF0000,0xC065B066,0xCFBF6439,0x000000006226long 0x3FFF0000,0xC0AE345F,0x56340AE6,0x000000006227long 0x3FFF0000,0xC0F22291,0x9CB9E6A7,0x0000000062286229set X,FP_SCR06230set XDCARE,X+26231set XFRAC,X+46232set XFRACLO,X+862336234set ATANF,FP_SCR16235set ATANFHI,ATANF+46236set ATANFLO,ATANF+862376238global satan6239#--ENTRY POINT FOR ATAN(X), HERE X IS FINITE, NON-ZERO, AND NOT NAN'S6240satan:6241fmov.x (%a0),%fp0 # LOAD INPUT62426243mov.l (%a0),%d16244mov.w 4(%a0),%d16245fmov.x %fp0,X(%a6)6246and.l &0x7FFFFFFF,%d162476248cmp.l %d1,&0x3FFB8000 # |X| >= 1/16?6249bge.b ATANOK16250bra.w ATANSM62516252ATANOK1:6253cmp.l %d1,&0x4002FFFF # |X| < 16 ?6254ble.b ATANMAIN6255bra.w ATANBIG62566257#--THE MOST LIKELY CASE, |X| IN [1/16, 16). WE USE TABLE TECHNIQUE6258#--THE IDEA IS ATAN(X) = ATAN(F) + ATAN( [X-F] / [1+XF] ).6259#--SO IF F IS CHOSEN TO BE CLOSE TO X AND ATAN(F) IS STORED IN6260#--A TABLE, ALL WE NEED IS TO APPROXIMATE ATAN(U) WHERE6261#--U = (X-F)/(1+XF) IS SMALL (REMEMBER F IS CLOSE TO X). IT IS6262#--TRUE THAT A DIVIDE IS NOW NEEDED, BUT THE APPROXIMATION FOR6263#--ATAN(U) IS A VERY SHORT POLYNOMIAL AND THE INDEXING TO6264#--FETCH F AND SAVING OF REGISTERS CAN BE ALL HIDED UNDER THE6265#--DIVIDE. IN THE END THIS METHOD IS MUCH FASTER THAN A TRADITIONAL6266#--ONE. NOTE ALSO THAT THE TRADITIONAL SCHEME THAT APPROXIMATE6267#--ATAN(X) DIRECTLY WILL NEED TO USE A RATIONAL APPROXIMATION6268#--(DIVISION NEEDED) ANYWAY BECAUSE A POLYNOMIAL APPROXIMATION6269#--WILL INVOLVE A VERY LONG POLYNOMIAL.62706271#--NOW WE SEE X AS +-2^K * 1.BBBBBBB....B <- 1. + 63 BITS6272#--WE CHOSE F TO BE +-2^K * 1.BBBB16273#--THAT IS IT MATCHES THE EXPONENT AND FIRST 5 BITS OF X, THE6274#--SIXTH BITS IS SET TO BE 1. SINCE K = -4, -3, ..., 3, THERE6275#--ARE ONLY 8 TIMES 16 = 2^7 = 128 |F|'S. SINCE ATAN(-|F|) IS6276#-- -ATAN(|F|), WE NEED TO STORE ONLY ATAN(|F|).62776278ATANMAIN:62796280and.l &0xF8000000,XFRAC(%a6) # FIRST 5 BITS6281or.l &0x04000000,XFRAC(%a6) # SET 6-TH BIT TO 16282mov.l &0x00000000,XFRACLO(%a6) # LOCATION OF X IS NOW F62836284fmov.x %fp0,%fp1 # FP1 IS X6285fmul.x X(%a6),%fp1 # FP1 IS X*F, NOTE THAT X*F > 06286fsub.x X(%a6),%fp0 # FP0 IS X-F6287fadd.s &0x3F800000,%fp1 # FP1 IS 1 + X*F6288fdiv.x %fp1,%fp0 # FP0 IS U = (X-F)/(1+X*F)62896290#--WHILE THE DIVISION IS TAKING ITS TIME, WE FETCH ATAN(|F|)6291#--CREATE ATAN(F) AND STORE IT IN ATANF, AND6292#--SAVE REGISTERS FP2.62936294mov.l %d2,-(%sp) # SAVE d2 TEMPORARILY6295mov.l %d1,%d2 # THE EXP AND 16 BITS OF X6296and.l &0x00007800,%d1 # 4 VARYING BITS OF F'S FRACTION6297and.l &0x7FFF0000,%d2 # EXPONENT OF F6298sub.l &0x3FFB0000,%d2 # K+46299asr.l &1,%d26300add.l %d2,%d1 # THE 7 BITS IDENTIFYING F6301asr.l &7,%d1 # INDEX INTO TBL OF ATAN(|F|)6302lea ATANTBL(%pc),%a16303add.l %d1,%a1 # ADDRESS OF ATAN(|F|)6304mov.l (%a1)+,ATANF(%a6)6305mov.l (%a1)+,ATANFHI(%a6)6306mov.l (%a1)+,ATANFLO(%a6) # ATANF IS NOW ATAN(|F|)6307mov.l X(%a6),%d1 # LOAD SIGN AND EXPO. AGAIN6308and.l &0x80000000,%d1 # SIGN(F)6309or.l %d1,ATANF(%a6) # ATANF IS NOW SIGN(F)*ATAN(|F|)6310mov.l (%sp)+,%d2 # RESTORE d263116312#--THAT'S ALL I HAVE TO DO FOR NOW,6313#--BUT ALAS, THE DIVIDE IS STILL CRANKING!63146315#--U IN FP0, WE ARE NOW READY TO COMPUTE ATAN(U) AS6316#--U + A1*U*V*(A2 + V*(A3 + V)), V = U*U6317#--THE POLYNOMIAL MAY LOOK STRANGE, BUT IS NEVERTHELESS CORRECT.6318#--THE NATURAL FORM IS U + U*V*(A1 + V*(A2 + V*A3))6319#--WHAT WE HAVE HERE IS MERELY A1 = A3, A2 = A1/A3, A3 = A2/A3.6320#--THE REASON FOR THIS REARRANGEMENT IS TO MAKE THE INDEPENDENT6321#--PARTS A1*U*V AND (A2 + ... STUFF) MORE LOAD-BALANCED63226323fmovm.x &0x04,-(%sp) # save fp263246325fmov.x %fp0,%fp16326fmul.x %fp1,%fp16327fmov.d ATANA3(%pc),%fp26328fadd.x %fp1,%fp2 # A3+V6329fmul.x %fp1,%fp2 # V*(A3+V)6330fmul.x %fp0,%fp1 # U*V6331fadd.d ATANA2(%pc),%fp2 # A2+V*(A3+V)6332fmul.d ATANA1(%pc),%fp1 # A1*U*V6333fmul.x %fp2,%fp1 # A1*U*V*(A2+V*(A3+V))6334fadd.x %fp1,%fp0 # ATAN(U), FP1 RELEASED63356336fmovm.x (%sp)+,&0x20 # restore fp263376338fmov.l %d0,%fpcr # restore users rnd mode,prec6339fadd.x ATANF(%a6),%fp0 # ATAN(X)6340bra t_inx263416342ATANBORS:6343#--|X| IS IN d0 IN COMPACT FORM. FP1, d0 SAVED.6344#--FP0 IS X AND |X| <= 1/16 OR |X| >= 16.6345cmp.l %d1,&0x3FFF80006346bgt.w ATANBIG # I.E. |X| >= 1663476348ATANSM:6349#--|X| <= 1/166350#--IF |X| < 2^(-40), RETURN X AS ANSWER. OTHERWISE, APPROXIMATE6351#--ATAN(X) BY X + X*Y*(B1+Y*(B2+Y*(B3+Y*(B4+Y*(B5+Y*B6)))))6352#--WHICH IS X + X*Y*( [B1+Z*(B3+Z*B5)] + [Y*(B2+Z*(B4+Z*B6)] )6353#--WHERE Y = X*X, AND Z = Y*Y.63546355cmp.l %d1,&0x3FD780006356blt.w ATANTINY63576358#--COMPUTE POLYNOMIAL6359fmovm.x &0x0c,-(%sp) # save fp2/fp363606361fmul.x %fp0,%fp0 # FPO IS Y = X*X63626363fmov.x %fp0,%fp16364fmul.x %fp1,%fp1 # FP1 IS Z = Y*Y63656366fmov.d ATANB6(%pc),%fp26367fmov.d ATANB5(%pc),%fp363686369fmul.x %fp1,%fp2 # Z*B66370fmul.x %fp1,%fp3 # Z*B563716372fadd.d ATANB4(%pc),%fp2 # B4+Z*B66373fadd.d ATANB3(%pc),%fp3 # B3+Z*B563746375fmul.x %fp1,%fp2 # Z*(B4+Z*B6)6376fmul.x %fp3,%fp1 # Z*(B3+Z*B5)63776378fadd.d ATANB2(%pc),%fp2 # B2+Z*(B4+Z*B6)6379fadd.d ATANB1(%pc),%fp1 # B1+Z*(B3+Z*B5)63806381fmul.x %fp0,%fp2 # Y*(B2+Z*(B4+Z*B6))6382fmul.x X(%a6),%fp0 # X*Y63836384fadd.x %fp2,%fp1 # [B1+Z*(B3+Z*B5)]+[Y*(B2+Z*(B4+Z*B6))]63856386fmul.x %fp1,%fp0 # X*Y*([B1+Z*(B3+Z*B5)]+[Y*(B2+Z*(B4+Z*B6))])63876388fmovm.x (%sp)+,&0x30 # restore fp2/fp363896390fmov.l %d0,%fpcr # restore users rnd mode,prec6391fadd.x X(%a6),%fp06392bra t_inx263936394ATANTINY:6395#--|X| < 2^(-40), ATAN(X) = X63966397fmov.l %d0,%fpcr # restore users rnd mode,prec6398mov.b &FMOV_OP,%d1 # last inst is MOVE6399fmov.x X(%a6),%fp0 # last inst - possible exception set64006401bra t_catch64026403ATANBIG:6404#--IF |X| > 2^(100), RETURN SIGN(X)*(PI/2 - TINY). OTHERWISE,6405#--RETURN SIGN(X)*PI/2 + ATAN(-1/X).6406cmp.l %d1,&0x406380006407bgt.w ATANHUGE64086409#--APPROXIMATE ATAN(-1/X) BY6410#--X'+X'*Y*(C1+Y*(C2+Y*(C3+Y*(C4+Y*C5)))), X' = -1/X, Y = X'*X'6411#--THIS CAN BE RE-WRITTEN AS6412#--X'+X'*Y*( [C1+Z*(C3+Z*C5)] + [Y*(C2+Z*C4)] ), Z = Y*Y.64136414fmovm.x &0x0c,-(%sp) # save fp2/fp364156416fmov.s &0xBF800000,%fp1 # LOAD -16417fdiv.x %fp0,%fp1 # FP1 IS -1/X64186419#--DIVIDE IS STILL CRANKING64206421fmov.x %fp1,%fp0 # FP0 IS X'6422fmul.x %fp0,%fp0 # FP0 IS Y = X'*X'6423fmov.x %fp1,X(%a6) # X IS REALLY X'64246425fmov.x %fp0,%fp16426fmul.x %fp1,%fp1 # FP1 IS Z = Y*Y64276428fmov.d ATANC5(%pc),%fp36429fmov.d ATANC4(%pc),%fp264306431fmul.x %fp1,%fp3 # Z*C56432fmul.x %fp1,%fp2 # Z*B464336434fadd.d ATANC3(%pc),%fp3 # C3+Z*C56435fadd.d ATANC2(%pc),%fp2 # C2+Z*C464366437fmul.x %fp3,%fp1 # Z*(C3+Z*C5), FP3 RELEASED6438fmul.x %fp0,%fp2 # Y*(C2+Z*C4)64396440fadd.d ATANC1(%pc),%fp1 # C1+Z*(C3+Z*C5)6441fmul.x X(%a6),%fp0 # X'*Y64426443fadd.x %fp2,%fp1 # [Y*(C2+Z*C4)]+[C1+Z*(C3+Z*C5)]64446445fmul.x %fp1,%fp0 # X'*Y*([B1+Z*(B3+Z*B5)]6446# ... +[Y*(B2+Z*(B4+Z*B6))])6447fadd.x X(%a6),%fp064486449fmovm.x (%sp)+,&0x30 # restore fp2/fp364506451fmov.l %d0,%fpcr # restore users rnd mode,prec6452tst.b (%a0)6453bpl.b pos_big64546455neg_big:6456fadd.x NPIBY2(%pc),%fp06457bra t_minx264586459pos_big:6460fadd.x PPIBY2(%pc),%fp06461bra t_pinx264626463ATANHUGE:6464#--RETURN SIGN(X)*(PIBY2 - TINY) = SIGN(X)*PIBY2 - SIGN(X)*TINY6465tst.b (%a0)6466bpl.b pos_huge64676468neg_huge:6469fmov.x NPIBY2(%pc),%fp06470fmov.l %d0,%fpcr6471fadd.x PTINY(%pc),%fp06472bra t_minx264736474pos_huge:6475fmov.x PPIBY2(%pc),%fp06476fmov.l %d0,%fpcr6477fadd.x NTINY(%pc),%fp06478bra t_pinx264796480global satand6481#--ENTRY POINT FOR ATAN(X) FOR DENORMALIZED ARGUMENT6482satand:6483bra t_extdnrm64846485#########################################################################6486# sasin(): computes the inverse sine of a normalized input #6487# sasind(): computes the inverse sine of a denormalized input #6488# #6489# INPUT *************************************************************** #6490# a0 = pointer to extended precision input #6491# d0 = round precision,mode #6492# #6493# OUTPUT ************************************************************** #6494# fp0 = arcsin(X) #6495# #6496# ACCURACY and MONOTONICITY ******************************************* #6497# The returned result is within 3 ulps in 64 significant bit, #6498# i.e. within 0.5001 ulp to 53 bits if the result is subsequently #6499# rounded to double precision. The result is provably monotonic #6500# in double precision. #6501# #6502# ALGORITHM *********************************************************** #6503# #6504# ASIN #6505# 1. If |X| >= 1, go to 3. #6506# #6507# 2. (|X| < 1) Calculate asin(X) by #6508# z := sqrt( [1-X][1+X] ) #6509# asin(X) = atan( x / z ). #6510# Exit. #6511# #6512# 3. If |X| > 1, go to 5. #6513# #6514# 4. (|X| = 1) sgn := sign(X), return asin(X) := sgn * Pi/2. Exit.#6515# #6516# 5. (|X| > 1) Generate an invalid operation by 0 * infinity. #6517# Exit. #6518# #6519#########################################################################65206521global sasin6522sasin:6523fmov.x (%a0),%fp0 # LOAD INPUT65246525mov.l (%a0),%d16526mov.w 4(%a0),%d16527and.l &0x7FFFFFFF,%d16528cmp.l %d1,&0x3FFF80006529bge.b ASINBIG65306531# This catch is added here for the '060 QSP. Originally, the call to6532# satan() would handle this case by causing the exception which would6533# not be caught until gen_except(). Now, with the exceptions being6534# detected inside of satan(), the exception would have been handled there6535# instead of inside sasin() as expected.6536cmp.l %d1,&0x3FD780006537blt.w ASINTINY65386539#--THIS IS THE USUAL CASE, |X| < 16540#--ASIN(X) = ATAN( X / SQRT( (1-X)(1+X) ) )65416542ASINMAIN:6543fmov.s &0x3F800000,%fp16544fsub.x %fp0,%fp1 # 1-X6545fmovm.x &0x4,-(%sp) # {fp2}6546fmov.s &0x3F800000,%fp26547fadd.x %fp0,%fp2 # 1+X6548fmul.x %fp2,%fp1 # (1+X)(1-X)6549fmovm.x (%sp)+,&0x20 # {fp2}6550fsqrt.x %fp1 # SQRT([1-X][1+X])6551fdiv.x %fp1,%fp0 # X/SQRT([1-X][1+X])6552fmovm.x &0x01,-(%sp) # save X/SQRT(...)6553lea (%sp),%a0 # pass ptr to X/SQRT(...)6554bsr satan6555add.l &0xc,%sp # clear X/SQRT(...) from stack6556bra t_inx265576558ASINBIG:6559fabs.x %fp0 # |X|6560fcmp.s %fp0,&0x3F8000006561fbgt t_operr # cause an operr exception65626563#--|X| = 1, ASIN(X) = +- PI/2.6564ASINONE:6565fmov.x PIBY2(%pc),%fp06566mov.l (%a0),%d16567and.l &0x80000000,%d1 # SIGN BIT OF X6568or.l &0x3F800000,%d1 # +-1 IN SGL FORMAT6569mov.l %d1,-(%sp) # push SIGN(X) IN SGL-FMT6570fmov.l %d0,%fpcr6571fmul.s (%sp)+,%fp06572bra t_inx265736574#--|X| < 2^(-40), ATAN(X) = X6575ASINTINY:6576fmov.l %d0,%fpcr # restore users rnd mode,prec6577mov.b &FMOV_OP,%d1 # last inst is MOVE6578fmov.x (%a0),%fp0 # last inst - possible exception6579bra t_catch65806581global sasind6582#--ASIN(X) = X FOR DENORMALIZED X6583sasind:6584bra t_extdnrm65856586#########################################################################6587# sacos(): computes the inverse cosine of a normalized input #6588# sacosd(): computes the inverse cosine of a denormalized input #6589# #6590# INPUT *************************************************************** #6591# a0 = pointer to extended precision input #6592# d0 = round precision,mode #6593# #6594# OUTPUT ************************************************************** #6595# fp0 = arccos(X) #6596# #6597# ACCURACY and MONOTONICITY ******************************************* #6598# The returned result is within 3 ulps in 64 significant bit, #6599# i.e. within 0.5001 ulp to 53 bits if the result is subsequently #6600# rounded to double precision. The result is provably monotonic #6601# in double precision. #6602# #6603# ALGORITHM *********************************************************** #6604# #6605# ACOS #6606# 1. If |X| >= 1, go to 3. #6607# #6608# 2. (|X| < 1) Calculate acos(X) by #6609# z := (1-X) / (1+X) #6610# acos(X) = 2 * atan( sqrt(z) ). #6611# Exit. #6612# #6613# 3. If |X| > 1, go to 5. #6614# #6615# 4. (|X| = 1) If X > 0, return 0. Otherwise, return Pi. Exit. #6616# #6617# 5. (|X| > 1) Generate an invalid operation by 0 * infinity. #6618# Exit. #6619# #6620#########################################################################66216622global sacos6623sacos:6624fmov.x (%a0),%fp0 # LOAD INPUT66256626mov.l (%a0),%d1 # pack exp w/ upper 16 fraction6627mov.w 4(%a0),%d16628and.l &0x7FFFFFFF,%d16629cmp.l %d1,&0x3FFF80006630bge.b ACOSBIG66316632#--THIS IS THE USUAL CASE, |X| < 16633#--ACOS(X) = 2 * ATAN( SQRT( (1-X)/(1+X) ) )66346635ACOSMAIN:6636fmov.s &0x3F800000,%fp16637fadd.x %fp0,%fp1 # 1+X6638fneg.x %fp0 # -X6639fadd.s &0x3F800000,%fp0 # 1-X6640fdiv.x %fp1,%fp0 # (1-X)/(1+X)6641fsqrt.x %fp0 # SQRT((1-X)/(1+X))6642mov.l %d0,-(%sp) # save original users fpcr6643clr.l %d06644fmovm.x &0x01,-(%sp) # save SQRT(...) to stack6645lea (%sp),%a0 # pass ptr to sqrt6646bsr satan # ATAN(SQRT([1-X]/[1+X]))6647add.l &0xc,%sp # clear SQRT(...) from stack66486649fmov.l (%sp)+,%fpcr # restore users round prec,mode6650fadd.x %fp0,%fp0 # 2 * ATAN( STUFF )6651bra t_pinx266526653ACOSBIG:6654fabs.x %fp06655fcmp.s %fp0,&0x3F8000006656fbgt t_operr # cause an operr exception66576658#--|X| = 1, ACOS(X) = 0 OR PI6659tst.b (%a0) # is X positive or negative?6660bpl.b ACOSP166616662#--X = -16663#Returns PI and inexact exception6664ACOSM1:6665fmov.x PI(%pc),%fp0 # load PI6666fmov.l %d0,%fpcr # load round mode,prec6667fadd.s &0x00800000,%fp0 # add a small value6668bra t_pinx266696670ACOSP1:6671bra ld_pzero # answer is positive zero66726673global sacosd6674#--ACOS(X) = PI/2 FOR DENORMALIZED X6675sacosd:6676fmov.l %d0,%fpcr # load user's rnd mode/prec6677fmov.x PIBY2(%pc),%fp06678bra t_pinx266796680#########################################################################6681# setox(): computes the exponential for a normalized input #6682# setoxd(): computes the exponential for a denormalized input #6683# setoxm1(): computes the exponential minus 1 for a normalized input #6684# setoxm1d(): computes the exponential minus 1 for a denormalized input #6685# #6686# INPUT *************************************************************** #6687# a0 = pointer to extended precision input #6688# d0 = round precision,mode #6689# #6690# OUTPUT ************************************************************** #6691# fp0 = exp(X) or exp(X)-1 #6692# #6693# ACCURACY and MONOTONICITY ******************************************* #6694# The returned result is within 0.85 ulps in 64 significant bit, #6695# i.e. within 0.5001 ulp to 53 bits if the result is subsequently #6696# rounded to double precision. The result is provably monotonic #6697# in double precision. #6698# #6699# ALGORITHM and IMPLEMENTATION **************************************** #6700# #6701# setoxd #6702# ------ #6703# Step 1. Set ans := 1.0 #6704# #6705# Step 2. Return ans := ans + sign(X)*2^(-126). Exit. #6706# Notes: This will always generate one exception -- inexact. #6707# #6708# #6709# setox #6710# ----- #6711# #6712# Step 1. Filter out extreme cases of input argument. #6713# 1.1 If |X| >= 2^(-65), go to Step 1.3. #6714# 1.2 Go to Step 7. #6715# 1.3 If |X| < 16380 log(2), go to Step 2. #6716# 1.4 Go to Step 8. #6717# Notes: The usual case should take the branches 1.1 -> 1.3 -> 2.#6718# To avoid the use of floating-point comparisons, a #6719# compact representation of |X| is used. This format is a #6720# 32-bit integer, the upper (more significant) 16 bits #6721# are the sign and biased exponent field of |X|; the #6722# lower 16 bits are the 16 most significant fraction #6723# (including the explicit bit) bits of |X|. Consequently, #6724# the comparisons in Steps 1.1 and 1.3 can be performed #6725# by integer comparison. Note also that the constant #6726# 16380 log(2) used in Step 1.3 is also in the compact #6727# form. Thus taking the branch to Step 2 guarantees #6728# |X| < 16380 log(2). There is no harm to have a small #6729# number of cases where |X| is less than, but close to, #6730# 16380 log(2) and the branch to Step 9 is taken. #6731# #6732# Step 2. Calculate N = round-to-nearest-int( X * 64/log2 ). #6733# 2.1 Set AdjFlag := 0 (indicates the branch 1.3 -> 2 #6734# was taken) #6735# 2.2 N := round-to-nearest-integer( X * 64/log2 ). #6736# 2.3 Calculate J = N mod 64; so J = 0,1,2,..., #6737# or 63. #6738# 2.4 Calculate M = (N - J)/64; so N = 64M + J. #6739# 2.5 Calculate the address of the stored value of #6740# 2^(J/64). #6741# 2.6 Create the value Scale = 2^M. #6742# Notes: The calculation in 2.2 is really performed by #6743# Z := X * constant #6744# N := round-to-nearest-integer(Z) #6745# where #6746# constant := single-precision( 64/log 2 ). #6747# #6748# Using a single-precision constant avoids memory #6749# access. Another effect of using a single-precision #6750# "constant" is that the calculated value Z is #6751# #6752# Z = X*(64/log2)*(1+eps), |eps| <= 2^(-24). #6753# #6754# This error has to be considered later in Steps 3 and 4. #6755# #6756# Step 3. Calculate X - N*log2/64. #6757# 3.1 R := X + N*L1, #6758# where L1 := single-precision(-log2/64). #6759# 3.2 R := R + N*L2, #6760# L2 := extended-precision(-log2/64 - L1).#6761# Notes: a) The way L1 and L2 are chosen ensures L1+L2 #6762# approximate the value -log2/64 to 88 bits of accuracy. #6763# b) N*L1 is exact because N is no longer than 22 bits #6764# and L1 is no longer than 24 bits. #6765# c) The calculation X+N*L1 is also exact due to #6766# cancellation. Thus, R is practically X+N(L1+L2) to full #6767# 64 bits. #6768# d) It is important to estimate how large can |R| be #6769# after Step 3.2. #6770# #6771# N = rnd-to-int( X*64/log2 (1+eps) ), |eps|<=2^(-24) #6772# X*64/log2 (1+eps) = N + f, |f| <= 0.5 #6773# X*64/log2 - N = f - eps*X 64/log2 #6774# X - N*log2/64 = f*log2/64 - eps*X #6775# #6776# #6777# Now |X| <= 16446 log2, thus #6778# #6779# |X - N*log2/64| <= (0.5 + 16446/2^(18))*log2/64 #6780# <= 0.57 log2/64. #6781# This bound will be used in Step 4. #6782# #6783# Step 4. Approximate exp(R)-1 by a polynomial #6784# p = R + R*R*(A1 + R*(A2 + R*(A3 + R*(A4 + R*A5)))) #6785# Notes: a) In order to reduce memory access, the coefficients #6786# are made as "short" as possible: A1 (which is 1/2), A4 #6787# and A5 are single precision; A2 and A3 are double #6788# precision. #6789# b) Even with the restrictions above, #6790# |p - (exp(R)-1)| < 2^(-68.8) for all |R| <= 0.0062. #6791# Note that 0.0062 is slightly bigger than 0.57 log2/64. #6792# c) To fully utilize the pipeline, p is separated into #6793# two independent pieces of roughly equal complexities #6794# p = [ R + R*S*(A2 + S*A4) ] + #6795# [ S*(A1 + S*(A3 + S*A5)) ] #6796# where S = R*R. #6797# #6798# Step 5. Compute 2^(J/64)*exp(R) = 2^(J/64)*(1+p) by #6799# ans := T + ( T*p + t) #6800# where T and t are the stored values for 2^(J/64). #6801# Notes: 2^(J/64) is stored as T and t where T+t approximates #6802# 2^(J/64) to roughly 85 bits; T is in extended precision #6803# and t is in single precision. Note also that T is #6804# rounded to 62 bits so that the last two bits of T are #6805# zero. The reason for such a special form is that T-1, #6806# T-2, and T-8 will all be exact --- a property that will #6807# give much more accurate computation of the function #6808# EXPM1. #6809# #6810# Step 6. Reconstruction of exp(X) #6811# exp(X) = 2^M * 2^(J/64) * exp(R). #6812# 6.1 If AdjFlag = 0, go to 6.3 #6813# 6.2 ans := ans * AdjScale #6814# 6.3 Restore the user FPCR #6815# 6.4 Return ans := ans * Scale. Exit. #6816# Notes: If AdjFlag = 0, we have X = Mlog2 + Jlog2/64 + R, #6817# |M| <= 16380, and Scale = 2^M. Moreover, exp(X) will #6818# neither overflow nor underflow. If AdjFlag = 1, that #6819# means that #6820# X = (M1+M)log2 + Jlog2/64 + R, |M1+M| >= 16380. #6821# Hence, exp(X) may overflow or underflow or neither. #6822# When that is the case, AdjScale = 2^(M1) where M1 is #6823# approximately M. Thus 6.2 will never cause #6824# over/underflow. Possible exception in 6.4 is overflow #6825# or underflow. The inexact exception is not generated in #6826# 6.4. Although one can argue that the inexact flag #6827# should always be raised, to simulate that exception #6828# cost to much than the flag is worth in practical uses. #6829# #6830# Step 7. Return 1 + X. #6831# 7.1 ans := X #6832# 7.2 Restore user FPCR. #6833# 7.3 Return ans := 1 + ans. Exit #6834# Notes: For non-zero X, the inexact exception will always be #6835# raised by 7.3. That is the only exception raised by 7.3.#6836# Note also that we use the FMOVEM instruction to move X #6837# in Step 7.1 to avoid unnecessary trapping. (Although #6838# the FMOVEM may not seem relevant since X is normalized, #6839# the precaution will be useful in the library version of #6840# this code where the separate entry for denormalized #6841# inputs will be done away with.) #6842# #6843# Step 8. Handle exp(X) where |X| >= 16380log2. #6844# 8.1 If |X| > 16480 log2, go to Step 9. #6845# (mimic 2.2 - 2.6) #6846# 8.2 N := round-to-integer( X * 64/log2 ) #6847# 8.3 Calculate J = N mod 64, J = 0,1,...,63 #6848# 8.4 K := (N-J)/64, M1 := truncate(K/2), M = K-M1, #6849# AdjFlag := 1. #6850# 8.5 Calculate the address of the stored value #6851# 2^(J/64). #6852# 8.6 Create the values Scale = 2^M, AdjScale = 2^M1. #6853# 8.7 Go to Step 3. #6854# Notes: Refer to notes for 2.2 - 2.6. #6855# #6856# Step 9. Handle exp(X), |X| > 16480 log2. #6857# 9.1 If X < 0, go to 9.3 #6858# 9.2 ans := Huge, go to 9.4 #6859# 9.3 ans := Tiny. #6860# 9.4 Restore user FPCR. #6861# 9.5 Return ans := ans * ans. Exit. #6862# Notes: Exp(X) will surely overflow or underflow, depending on #6863# X's sign. "Huge" and "Tiny" are respectively large/tiny #6864# extended-precision numbers whose square over/underflow #6865# with an inexact result. Thus, 9.5 always raises the #6866# inexact together with either overflow or underflow. #6867# #6868# setoxm1d #6869# -------- #6870# #6871# Step 1. Set ans := 0 #6872# #6873# Step 2. Return ans := X + ans. Exit. #6874# Notes: This will return X with the appropriate rounding #6875# precision prescribed by the user FPCR. #6876# #6877# setoxm1 #6878# ------- #6879# #6880# Step 1. Check |X| #6881# 1.1 If |X| >= 1/4, go to Step 1.3. #6882# 1.2 Go to Step 7. #6883# 1.3 If |X| < 70 log(2), go to Step 2. #6884# 1.4 Go to Step 10. #6885# Notes: The usual case should take the branches 1.1 -> 1.3 -> 2.#6886# However, it is conceivable |X| can be small very often #6887# because EXPM1 is intended to evaluate exp(X)-1 #6888# accurately when |X| is small. For further details on #6889# the comparisons, see the notes on Step 1 of setox. #6890# #6891# Step 2. Calculate N = round-to-nearest-int( X * 64/log2 ). #6892# 2.1 N := round-to-nearest-integer( X * 64/log2 ). #6893# 2.2 Calculate J = N mod 64; so J = 0,1,2,..., #6894# or 63. #6895# 2.3 Calculate M = (N - J)/64; so N = 64M + J. #6896# 2.4 Calculate the address of the stored value of #6897# 2^(J/64). #6898# 2.5 Create the values Sc = 2^M and #6899# OnebySc := -2^(-M). #6900# Notes: See the notes on Step 2 of setox. #6901# #6902# Step 3. Calculate X - N*log2/64. #6903# 3.1 R := X + N*L1, #6904# where L1 := single-precision(-log2/64). #6905# 3.2 R := R + N*L2, #6906# L2 := extended-precision(-log2/64 - L1).#6907# Notes: Applying the analysis of Step 3 of setox in this case #6908# shows that |R| <= 0.0055 (note that |X| <= 70 log2 in #6909# this case). #6910# #6911# Step 4. Approximate exp(R)-1 by a polynomial #6912# p = R+R*R*(A1+R*(A2+R*(A3+R*(A4+R*(A5+R*A6))))) #6913# Notes: a) In order to reduce memory access, the coefficients #6914# are made as "short" as possible: A1 (which is 1/2), A5 #6915# and A6 are single precision; A2, A3 and A4 are double #6916# precision. #6917# b) Even with the restriction above, #6918# |p - (exp(R)-1)| < |R| * 2^(-72.7) #6919# for all |R| <= 0.0055. #6920# c) To fully utilize the pipeline, p is separated into #6921# two independent pieces of roughly equal complexity #6922# p = [ R*S*(A2 + S*(A4 + S*A6)) ] + #6923# [ R + S*(A1 + S*(A3 + S*A5)) ] #6924# where S = R*R. #6925# #6926# Step 5. Compute 2^(J/64)*p by #6927# p := T*p #6928# where T and t are the stored values for 2^(J/64). #6929# Notes: 2^(J/64) is stored as T and t where T+t approximates #6930# 2^(J/64) to roughly 85 bits; T is in extended precision #6931# and t is in single precision. Note also that T is #6932# rounded to 62 bits so that the last two bits of T are #6933# zero. The reason for such a special form is that T-1, #6934# T-2, and T-8 will all be exact --- a property that will #6935# be exploited in Step 6 below. The total relative error #6936# in p is no bigger than 2^(-67.7) compared to the final #6937# result. #6938# #6939# Step 6. Reconstruction of exp(X)-1 #6940# exp(X)-1 = 2^M * ( 2^(J/64) + p - 2^(-M) ). #6941# 6.1 If M <= 63, go to Step 6.3. #6942# 6.2 ans := T + (p + (t + OnebySc)). Go to 6.6 #6943# 6.3 If M >= -3, go to 6.5. #6944# 6.4 ans := (T + (p + t)) + OnebySc. Go to 6.6 #6945# 6.5 ans := (T + OnebySc) + (p + t). #6946# 6.6 Restore user FPCR. #6947# 6.7 Return ans := Sc * ans. Exit. #6948# Notes: The various arrangements of the expressions give #6949# accurate evaluations. #6950# #6951# Step 7. exp(X)-1 for |X| < 1/4. #6952# 7.1 If |X| >= 2^(-65), go to Step 9. #6953# 7.2 Go to Step 8. #6954# #6955# Step 8. Calculate exp(X)-1, |X| < 2^(-65). #6956# 8.1 If |X| < 2^(-16312), goto 8.3 #6957# 8.2 Restore FPCR; return ans := X - 2^(-16382). #6958# Exit. #6959# 8.3 X := X * 2^(140). #6960# 8.4 Restore FPCR; ans := ans - 2^(-16382). #6961# Return ans := ans*2^(140). Exit #6962# Notes: The idea is to return "X - tiny" under the user #6963# precision and rounding modes. To avoid unnecessary #6964# inefficiency, we stay away from denormalized numbers #6965# the best we can. For |X| >= 2^(-16312), the #6966# straightforward 8.2 generates the inexact exception as #6967# the case warrants. #6968# #6969# Step 9. Calculate exp(X)-1, |X| < 1/4, by a polynomial #6970# p = X + X*X*(B1 + X*(B2 + ... + X*B12)) #6971# Notes: a) In order to reduce memory access, the coefficients #6972# are made as "short" as possible: B1 (which is 1/2), B9 #6973# to B12 are single precision; B3 to B8 are double #6974# precision; and B2 is double extended. #6975# b) Even with the restriction above, #6976# |p - (exp(X)-1)| < |X| 2^(-70.6) #6977# for all |X| <= 0.251. #6978# Note that 0.251 is slightly bigger than 1/4. #6979# c) To fully preserve accuracy, the polynomial is #6980# computed as #6981# X + ( S*B1 + Q ) where S = X*X and #6982# Q = X*S*(B2 + X*(B3 + ... + X*B12)) #6983# d) To fully utilize the pipeline, Q is separated into #6984# two independent pieces of roughly equal complexity #6985# Q = [ X*S*(B2 + S*(B4 + ... + S*B12)) ] + #6986# [ S*S*(B3 + S*(B5 + ... + S*B11)) ] #6987# #6988# Step 10. Calculate exp(X)-1 for |X| >= 70 log 2. #6989# 10.1 If X >= 70log2 , exp(X) - 1 = exp(X) for all #6990# practical purposes. Therefore, go to Step 1 of setox. #6991# 10.2 If X <= -70log2, exp(X) - 1 = -1 for all practical #6992# purposes. #6993# ans := -1 #6994# Restore user FPCR #6995# Return ans := ans + 2^(-126). Exit. #6996# Notes: 10.2 will always create an inexact and return -1 + tiny #6997# in the user rounding precision and mode. #6998# #6999#########################################################################70007001L2: long 0x3FDC0000,0x82E30865,0x4361C4C6,0x0000000070027003EEXPA3: long 0x3FA55555,0x55554CC17004EEXPA2: long 0x3FC55555,0x55554A5470057006EM1A4: long 0x3F811111,0x111743857007EM1A3: long 0x3FA55555,0x55554F5A70087009EM1A2: long 0x3FC55555,0x55555555,0x00000000,0x0000000070107011EM1B8: long 0x3EC71DE3,0xA57746827012EM1B7: long 0x3EFA01A0,0x19D7CB6870137014EM1B6: long 0x3F2A01A0,0x1A019DF37015EM1B5: long 0x3F56C16C,0x16C170E270167017EM1B4: long 0x3F811111,0x111111117018EM1B3: long 0x3FA55555,0x5555555570197020EM1B2: long 0x3FFC0000,0xAAAAAAAA,0xAAAAAAAB7021long 0x0000000070227023TWO140: long 0x48B00000,0x000000007024TWON140:7025long 0x37300000,0x0000000070267027EEXPTBL:7028long 0x3FFF0000,0x80000000,0x00000000,0x000000007029long 0x3FFF0000,0x8164D1F3,0xBC030774,0x9F841A9B7030long 0x3FFF0000,0x82CD8698,0xAC2BA1D8,0x9FC1D5B97031long 0x3FFF0000,0x843A28C3,0xACDE4048,0xA07283697032long 0x3FFF0000,0x85AAC367,0xCC487B14,0x1FC5C95C7033long 0x3FFF0000,0x871F6196,0x9E8D1010,0x1EE85C9F7034long 0x3FFF0000,0x88980E80,0x92DA8528,0x9FA207297035long 0x3FFF0000,0x8A14D575,0x496EFD9C,0xA07BF9AF7036long 0x3FFF0000,0x8B95C1E3,0xEA8BD6E8,0xA0020DCF7037long 0x3FFF0000,0x8D1ADF5B,0x7E5BA9E4,0x205A63DA7038long 0x3FFF0000,0x8EA4398B,0x45CD53C0,0x1EB700517039long 0x3FFF0000,0x9031DC43,0x1466B1DC,0x1F6EB0297040long 0x3FFF0000,0x91C3D373,0xAB11C338,0xA07814947041long 0x3FFF0000,0x935A2B2F,0x13E6E92C,0x9EB319B07042long 0x3FFF0000,0x94F4EFA8,0xFEF70960,0x2017457D7043long 0x3FFF0000,0x96942D37,0x20185A00,0x1F11D5377044long 0x3FFF0000,0x9837F051,0x8DB8A970,0x9FB952DD7045long 0x3FFF0000,0x99E04593,0x20B7FA64,0x1FE430877046long 0x3FFF0000,0x9B8D39B9,0xD54E5538,0x1FA2A8187047long 0x3FFF0000,0x9D3ED9A7,0x2CFFB750,0x1FDE494D7048long 0x3FFF0000,0x9EF53260,0x91A111AC,0x205048907049long 0x3FFF0000,0xA0B0510F,0xB9714FC4,0xA073691C7050long 0x3FFF0000,0xA2704303,0x0C496818,0x1F9B7A057051long 0x3FFF0000,0xA43515AE,0x09E680A0,0xA07971267052long 0x3FFF0000,0xA5FED6A9,0xB15138EC,0xA071A1407053long 0x3FFF0000,0xA7CD93B4,0xE9653568,0x204F62DA7054long 0x3FFF0000,0xA9A15AB4,0xEA7C0EF8,0x1F283C4A7055long 0x3FFF0000,0xAB7A39B5,0xA93ED338,0x9F9A7FDC7056long 0x3FFF0000,0xAD583EEA,0x42A14AC8,0xA05B3FAC7057long 0x3FFF0000,0xAF3B78AD,0x690A4374,0x1FDF26107058long 0x3FFF0000,0xB123F581,0xD2AC2590,0x9F705F907059long 0x3FFF0000,0xB311C412,0xA9112488,0x201F678A7060long 0x3FFF0000,0xB504F333,0xF9DE6484,0x1F32FB137061long 0x3FFF0000,0xB6FD91E3,0x28D17790,0x20038B307062long 0x3FFF0000,0xB8FBAF47,0x62FB9EE8,0x200DC3CC7063long 0x3FFF0000,0xBAFF5AB2,0x133E45FC,0x9F8B2AE67064long 0x3FFF0000,0xBD08A39F,0x580C36C0,0xA02BBF707065long 0x3FFF0000,0xBF1799B6,0x7A731084,0xA00BF5187066long 0x3FFF0000,0xC12C4CCA,0x66709458,0xA041DD417067long 0x3FFF0000,0xC346CCDA,0x24976408,0x9FDF137B7068long 0x3FFF0000,0xC5672A11,0x5506DADC,0x201F15687069long 0x3FFF0000,0xC78D74C8,0xABB9B15C,0x1FC13A2E7070long 0x3FFF0000,0xC9B9BD86,0x6E2F27A4,0xA03F8F037071long 0x3FFF0000,0xCBEC14FE,0xF2727C5C,0x1FF4907D7072long 0x3FFF0000,0xCE248C15,0x1F8480E4,0x9E6E53E47073long 0x3FFF0000,0xD06333DA,0xEF2B2594,0x1FD6D45C7074long 0x3FFF0000,0xD2A81D91,0xF12AE45C,0xA076EDB97075long 0x3FFF0000,0xD4F35AAB,0xCFEDFA20,0x9FA6DE217076long 0x3FFF0000,0xD744FCCA,0xD69D6AF4,0x1EE69A2F7077long 0x3FFF0000,0xD99D15C2,0x78AFD7B4,0x207F439F7078long 0x3FFF0000,0xDBFBB797,0xDAF23754,0x201EC2077079long 0x3FFF0000,0xDE60F482,0x5E0E9124,0x9E8BE1757080long 0x3FFF0000,0xE0CCDEEC,0x2A94E110,0x20032C4B7081long 0x3FFF0000,0xE33F8972,0xBE8A5A50,0x2004DFF57082long 0x3FFF0000,0xE5B906E7,0x7C8348A8,0x1E72F47A7083long 0x3FFF0000,0xE8396A50,0x3C4BDC68,0x1F722F227084long 0x3FFF0000,0xEAC0C6E7,0xDD243930,0xA017E9457085long 0x3FFF0000,0xED4F301E,0xD9942B84,0x1F401A5B7086long 0x3FFF0000,0xEFE4B99B,0xDCDAF5CC,0x9FB9A9E37087long 0x3FFF0000,0xF281773C,0x59FFB138,0x20744C057088long 0x3FFF0000,0xF5257D15,0x2486CC2C,0x1F773A197089long 0x3FFF0000,0xF7D0DF73,0x0AD13BB8,0x1FFE90D57090long 0x3FFF0000,0xFA83B2DB,0x722A033C,0xA041ED227091long 0x3FFF0000,0xFD3E0C0C,0xF486C174,0x1F853F3A70927093set ADJFLAG,L_SCR27094set SCALE,FP_SCR07095set ADJSCALE,FP_SCR17096set SC,FP_SCR07097set ONEBYSC,FP_SCR170987099global setox7100setox:7101#--entry point for EXP(X), here X is finite, non-zero, and not NaN's71027103#--Step 1.7104mov.l (%a0),%d1 # load part of input X7105and.l &0x7FFF0000,%d1 # biased expo. of X7106cmp.l %d1,&0x3FBE0000 # 2^(-65)7107bge.b EXPC1 # normal case7108bra EXPSM71097110EXPC1:7111#--The case |X| >= 2^(-65)7112mov.w 4(%a0),%d1 # expo. and partial sig. of |X|7113cmp.l %d1,&0x400CB167 # 16380 log2 trunc. 16 bits7114blt.b EXPMAIN # normal case7115bra EEXPBIG71167117EXPMAIN:7118#--Step 2.7119#--This is the normal branch: 2^(-65) <= |X| < 16380 log2.7120fmov.x (%a0),%fp0 # load input from (a0)71217122fmov.x %fp0,%fp17123fmul.s &0x42B8AA3B,%fp0 # 64/log2 * X7124fmovm.x &0xc,-(%sp) # save fp2 {%fp2/%fp3}7125mov.l &0,ADJFLAG(%a6)7126fmov.l %fp0,%d1 # N = int( X * 64/log2 )7127lea EEXPTBL(%pc),%a17128fmov.l %d1,%fp0 # convert to floating-format71297130mov.l %d1,L_SCR1(%a6) # save N temporarily7131and.l &0x3F,%d1 # D0 is J = N mod 647132lsl.l &4,%d17133add.l %d1,%a1 # address of 2^(J/64)7134mov.l L_SCR1(%a6),%d17135asr.l &6,%d1 # D0 is M7136add.w &0x3FFF,%d1 # biased expo. of 2^(M)7137mov.w L2(%pc),L_SCR1(%a6) # prefetch L2, no need in CB71387139EXPCONT1:7140#--Step 3.7141#--fp1,fp2 saved on the stack. fp0 is N, fp1 is X,7142#--a0 points to 2^(J/64), D0 is biased expo. of 2^(M)7143fmov.x %fp0,%fp27144fmul.s &0xBC317218,%fp0 # N * L1, L1 = lead(-log2/64)7145fmul.x L2(%pc),%fp2 # N * L2, L1+L2 = -log2/647146fadd.x %fp1,%fp0 # X + N*L17147fadd.x %fp2,%fp0 # fp0 is R, reduced arg.71487149#--Step 4.7150#--WE NOW COMPUTE EXP(R)-1 BY A POLYNOMIAL7151#-- R + R*R*(A1 + R*(A2 + R*(A3 + R*(A4 + R*A5))))7152#--TO FULLY UTILIZE THE PIPELINE, WE COMPUTE S = R*R7153#--[R+R*S*(A2+S*A4)] + [S*(A1+S*(A3+S*A5))]71547155fmov.x %fp0,%fp17156fmul.x %fp1,%fp1 # fp1 IS S = R*R71577158fmov.s &0x3AB60B70,%fp2 # fp2 IS A571597160fmul.x %fp1,%fp2 # fp2 IS S*A57161fmov.x %fp1,%fp37162fmul.s &0x3C088895,%fp3 # fp3 IS S*A471637164fadd.d EEXPA3(%pc),%fp2 # fp2 IS A3+S*A57165fadd.d EEXPA2(%pc),%fp3 # fp3 IS A2+S*A471667167fmul.x %fp1,%fp2 # fp2 IS S*(A3+S*A5)7168mov.w %d1,SCALE(%a6) # SCALE is 2^(M) in extended7169mov.l &0x80000000,SCALE+4(%a6)7170clr.l SCALE+8(%a6)71717172fmul.x %fp1,%fp3 # fp3 IS S*(A2+S*A4)71737174fadd.s &0x3F000000,%fp2 # fp2 IS A1+S*(A3+S*A5)7175fmul.x %fp0,%fp3 # fp3 IS R*S*(A2+S*A4)71767177fmul.x %fp1,%fp2 # fp2 IS S*(A1+S*(A3+S*A5))7178fadd.x %fp3,%fp0 # fp0 IS R+R*S*(A2+S*A4),71797180fmov.x (%a1)+,%fp1 # fp1 is lead. pt. of 2^(J/64)7181fadd.x %fp2,%fp0 # fp0 is EXP(R) - 171827183#--Step 57184#--final reconstruction process7185#--EXP(X) = 2^M * ( 2^(J/64) + 2^(J/64)*(EXP(R)-1) )71867187fmul.x %fp1,%fp0 # 2^(J/64)*(Exp(R)-1)7188fmovm.x (%sp)+,&0x30 # fp2 restored {%fp2/%fp3}7189fadd.s (%a1),%fp0 # accurate 2^(J/64)71907191fadd.x %fp1,%fp0 # 2^(J/64) + 2^(J/64)*...7192mov.l ADJFLAG(%a6),%d171937194#--Step 67195tst.l %d17196beq.b NORMAL7197ADJUST:7198fmul.x ADJSCALE(%a6),%fp07199NORMAL:7200fmov.l %d0,%fpcr # restore user FPCR7201mov.b &FMUL_OP,%d1 # last inst is MUL7202fmul.x SCALE(%a6),%fp0 # multiply 2^(M)7203bra t_catch72047205EXPSM:7206#--Step 77207fmovm.x (%a0),&0x80 # load X7208fmov.l %d0,%fpcr7209fadd.s &0x3F800000,%fp0 # 1+X in user mode7210bra t_pinx272117212EEXPBIG:7213#--Step 87214cmp.l %d1,&0x400CB27C # 16480 log27215bgt.b EXP2BIG7216#--Steps 8.2 -- 8.67217fmov.x (%a0),%fp0 # load input from (a0)72187219fmov.x %fp0,%fp17220fmul.s &0x42B8AA3B,%fp0 # 64/log2 * X7221fmovm.x &0xc,-(%sp) # save fp2 {%fp2/%fp3}7222mov.l &1,ADJFLAG(%a6)7223fmov.l %fp0,%d1 # N = int( X * 64/log2 )7224lea EEXPTBL(%pc),%a17225fmov.l %d1,%fp0 # convert to floating-format7226mov.l %d1,L_SCR1(%a6) # save N temporarily7227and.l &0x3F,%d1 # D0 is J = N mod 647228lsl.l &4,%d17229add.l %d1,%a1 # address of 2^(J/64)7230mov.l L_SCR1(%a6),%d17231asr.l &6,%d1 # D0 is K7232mov.l %d1,L_SCR1(%a6) # save K temporarily7233asr.l &1,%d1 # D0 is M17234sub.l %d1,L_SCR1(%a6) # a1 is M7235add.w &0x3FFF,%d1 # biased expo. of 2^(M1)7236mov.w %d1,ADJSCALE(%a6) # ADJSCALE := 2^(M1)7237mov.l &0x80000000,ADJSCALE+4(%a6)7238clr.l ADJSCALE+8(%a6)7239mov.l L_SCR1(%a6),%d1 # D0 is M7240add.w &0x3FFF,%d1 # biased expo. of 2^(M)7241bra.w EXPCONT1 # go back to Step 372427243EXP2BIG:7244#--Step 97245tst.b (%a0) # is X positive or negative?7246bmi t_unfl27247bra t_ovfl272487249global setoxd7250setoxd:7251#--entry point for EXP(X), X is denormalized7252mov.l (%a0),-(%sp)7253andi.l &0x80000000,(%sp)7254ori.l &0x00800000,(%sp) # sign(X)*2^(-126)72557256fmov.s &0x3F800000,%fp072577258fmov.l %d0,%fpcr7259fadd.s (%sp)+,%fp07260bra t_pinx272617262global setoxm17263setoxm1:7264#--entry point for EXPM1(X), here X is finite, non-zero, non-NaN72657266#--Step 1.7267#--Step 1.17268mov.l (%a0),%d1 # load part of input X7269and.l &0x7FFF0000,%d1 # biased expo. of X7270cmp.l %d1,&0x3FFD0000 # 1/47271bge.b EM1CON1 # |X| >= 1/47272bra EM1SM72737274EM1CON1:7275#--Step 1.37276#--The case |X| >= 1/47277mov.w 4(%a0),%d1 # expo. and partial sig. of |X|7278cmp.l %d1,&0x4004C215 # 70log2 rounded up to 16 bits7279ble.b EM1MAIN # 1/4 <= |X| <= 70log27280bra EM1BIG72817282EM1MAIN:7283#--Step 2.7284#--This is the case: 1/4 <= |X| <= 70 log2.7285fmov.x (%a0),%fp0 # load input from (a0)72867287fmov.x %fp0,%fp17288fmul.s &0x42B8AA3B,%fp0 # 64/log2 * X7289fmovm.x &0xc,-(%sp) # save fp2 {%fp2/%fp3}7290fmov.l %fp0,%d1 # N = int( X * 64/log2 )7291lea EEXPTBL(%pc),%a17292fmov.l %d1,%fp0 # convert to floating-format72937294mov.l %d1,L_SCR1(%a6) # save N temporarily7295and.l &0x3F,%d1 # D0 is J = N mod 647296lsl.l &4,%d17297add.l %d1,%a1 # address of 2^(J/64)7298mov.l L_SCR1(%a6),%d17299asr.l &6,%d1 # D0 is M7300mov.l %d1,L_SCR1(%a6) # save a copy of M73017302#--Step 3.7303#--fp1,fp2 saved on the stack. fp0 is N, fp1 is X,7304#--a0 points to 2^(J/64), D0 and a1 both contain M7305fmov.x %fp0,%fp27306fmul.s &0xBC317218,%fp0 # N * L1, L1 = lead(-log2/64)7307fmul.x L2(%pc),%fp2 # N * L2, L1+L2 = -log2/647308fadd.x %fp1,%fp0 # X + N*L17309fadd.x %fp2,%fp0 # fp0 is R, reduced arg.7310add.w &0x3FFF,%d1 # D0 is biased expo. of 2^M73117312#--Step 4.7313#--WE NOW COMPUTE EXP(R)-1 BY A POLYNOMIAL7314#-- R + R*R*(A1 + R*(A2 + R*(A3 + R*(A4 + R*(A5 + R*A6)))))7315#--TO FULLY UTILIZE THE PIPELINE, WE COMPUTE S = R*R7316#--[R*S*(A2+S*(A4+S*A6))] + [R+S*(A1+S*(A3+S*A5))]73177318fmov.x %fp0,%fp17319fmul.x %fp1,%fp1 # fp1 IS S = R*R73207321fmov.s &0x3950097B,%fp2 # fp2 IS a673227323fmul.x %fp1,%fp2 # fp2 IS S*A67324fmov.x %fp1,%fp37325fmul.s &0x3AB60B6A,%fp3 # fp3 IS S*A573267327fadd.d EM1A4(%pc),%fp2 # fp2 IS A4+S*A67328fadd.d EM1A3(%pc),%fp3 # fp3 IS A3+S*A57329mov.w %d1,SC(%a6) # SC is 2^(M) in extended7330mov.l &0x80000000,SC+4(%a6)7331clr.l SC+8(%a6)73327333fmul.x %fp1,%fp2 # fp2 IS S*(A4+S*A6)7334mov.l L_SCR1(%a6),%d1 # D0 is M7335neg.w %d1 # D0 is -M7336fmul.x %fp1,%fp3 # fp3 IS S*(A3+S*A5)7337add.w &0x3FFF,%d1 # biased expo. of 2^(-M)7338fadd.d EM1A2(%pc),%fp2 # fp2 IS A2+S*(A4+S*A6)7339fadd.s &0x3F000000,%fp3 # fp3 IS A1+S*(A3+S*A5)73407341fmul.x %fp1,%fp2 # fp2 IS S*(A2+S*(A4+S*A6))7342or.w &0x8000,%d1 # signed/expo. of -2^(-M)7343mov.w %d1,ONEBYSC(%a6) # OnebySc is -2^(-M)7344mov.l &0x80000000,ONEBYSC+4(%a6)7345clr.l ONEBYSC+8(%a6)7346fmul.x %fp3,%fp1 # fp1 IS S*(A1+S*(A3+S*A5))73477348fmul.x %fp0,%fp2 # fp2 IS R*S*(A2+S*(A4+S*A6))7349fadd.x %fp1,%fp0 # fp0 IS R+S*(A1+S*(A3+S*A5))73507351fadd.x %fp2,%fp0 # fp0 IS EXP(R)-173527353fmovm.x (%sp)+,&0x30 # fp2 restored {%fp2/%fp3}73547355#--Step 57356#--Compute 2^(J/64)*p73577358fmul.x (%a1),%fp0 # 2^(J/64)*(Exp(R)-1)73597360#--Step 67361#--Step 6.17362mov.l L_SCR1(%a6),%d1 # retrieve M7363cmp.l %d1,&637364ble.b MLE637365#--Step 6.2 M >= 647366fmov.s 12(%a1),%fp1 # fp1 is t7367fadd.x ONEBYSC(%a6),%fp1 # fp1 is t+OnebySc7368fadd.x %fp1,%fp0 # p+(t+OnebySc), fp1 released7369fadd.x (%a1),%fp0 # T+(p+(t+OnebySc))7370bra EM1SCALE7371MLE63:7372#--Step 6.3 M <= 637373cmp.l %d1,&-37374bge.b MGEN37375MLTN3:7376#--Step 6.4 M <= -47377fadd.s 12(%a1),%fp0 # p+t7378fadd.x (%a1),%fp0 # T+(p+t)7379fadd.x ONEBYSC(%a6),%fp0 # OnebySc + (T+(p+t))7380bra EM1SCALE7381MGEN3:7382#--Step 6.5 -3 <= M <= 637383fmov.x (%a1)+,%fp1 # fp1 is T7384fadd.s (%a1),%fp0 # fp0 is p+t7385fadd.x ONEBYSC(%a6),%fp1 # fp1 is T+OnebySc7386fadd.x %fp1,%fp0 # (T+OnebySc)+(p+t)73877388EM1SCALE:7389#--Step 6.67390fmov.l %d0,%fpcr7391fmul.x SC(%a6),%fp07392bra t_inx273937394EM1SM:7395#--Step 7 |X| < 1/4.7396cmp.l %d1,&0x3FBE0000 # 2^(-65)7397bge.b EM1POLY73987399EM1TINY:7400#--Step 8 |X| < 2^(-65)7401cmp.l %d1,&0x00330000 # 2^(-16312)7402blt.b EM12TINY7403#--Step 8.27404mov.l &0x80010000,SC(%a6) # SC is -2^(-16382)7405mov.l &0x80000000,SC+4(%a6)7406clr.l SC+8(%a6)7407fmov.x (%a0),%fp07408fmov.l %d0,%fpcr7409mov.b &FADD_OP,%d1 # last inst is ADD7410fadd.x SC(%a6),%fp07411bra t_catch74127413EM12TINY:7414#--Step 8.37415fmov.x (%a0),%fp07416fmul.d TWO140(%pc),%fp07417mov.l &0x80010000,SC(%a6)7418mov.l &0x80000000,SC+4(%a6)7419clr.l SC+8(%a6)7420fadd.x SC(%a6),%fp07421fmov.l %d0,%fpcr7422mov.b &FMUL_OP,%d1 # last inst is MUL7423fmul.d TWON140(%pc),%fp07424bra t_catch74257426EM1POLY:7427#--Step 9 exp(X)-1 by a simple polynomial7428fmov.x (%a0),%fp0 # fp0 is X7429fmul.x %fp0,%fp0 # fp0 is S := X*X7430fmovm.x &0xc,-(%sp) # save fp2 {%fp2/%fp3}7431fmov.s &0x2F30CAA8,%fp1 # fp1 is B127432fmul.x %fp0,%fp1 # fp1 is S*B127433fmov.s &0x310F8290,%fp2 # fp2 is B117434fadd.s &0x32D73220,%fp1 # fp1 is B10+S*B1274357436fmul.x %fp0,%fp2 # fp2 is S*B117437fmul.x %fp0,%fp1 # fp1 is S*(B10 + ...74387439fadd.s &0x3493F281,%fp2 # fp2 is B9+S*...7440fadd.d EM1B8(%pc),%fp1 # fp1 is B8+S*...74417442fmul.x %fp0,%fp2 # fp2 is S*(B9+...7443fmul.x %fp0,%fp1 # fp1 is S*(B8+...74447445fadd.d EM1B7(%pc),%fp2 # fp2 is B7+S*...7446fadd.d EM1B6(%pc),%fp1 # fp1 is B6+S*...74477448fmul.x %fp0,%fp2 # fp2 is S*(B7+...7449fmul.x %fp0,%fp1 # fp1 is S*(B6+...74507451fadd.d EM1B5(%pc),%fp2 # fp2 is B5+S*...7452fadd.d EM1B4(%pc),%fp1 # fp1 is B4+S*...74537454fmul.x %fp0,%fp2 # fp2 is S*(B5+...7455fmul.x %fp0,%fp1 # fp1 is S*(B4+...74567457fadd.d EM1B3(%pc),%fp2 # fp2 is B3+S*...7458fadd.x EM1B2(%pc),%fp1 # fp1 is B2+S*...74597460fmul.x %fp0,%fp2 # fp2 is S*(B3+...7461fmul.x %fp0,%fp1 # fp1 is S*(B2+...74627463fmul.x %fp0,%fp2 # fp2 is S*S*(B3+...)7464fmul.x (%a0),%fp1 # fp1 is X*S*(B2...74657466fmul.s &0x3F000000,%fp0 # fp0 is S*B17467fadd.x %fp2,%fp1 # fp1 is Q74687469fmovm.x (%sp)+,&0x30 # fp2 restored {%fp2/%fp3}74707471fadd.x %fp1,%fp0 # fp0 is S*B1+Q74727473fmov.l %d0,%fpcr7474fadd.x (%a0),%fp07475bra t_inx274767477EM1BIG:7478#--Step 10 |X| > 70 log27479mov.l (%a0),%d17480cmp.l %d1,&07481bgt.w EXPC17482#--Step 10.27483fmov.s &0xBF800000,%fp0 # fp0 is -17484fmov.l %d0,%fpcr7485fadd.s &0x00800000,%fp0 # -1 + 2^(-126)7486bra t_minx274877488global setoxm1d7489setoxm1d:7490#--entry point for EXPM1(X), here X is denormalized7491#--Step 0.7492bra t_extdnrm74937494#########################################################################7495# sgetexp(): returns the exponent portion of the input argument. #7496# The exponent bias is removed and the exponent value is #7497# returned as an extended precision number in fp0. #7498# sgetexpd(): handles denormalized numbers. #7499# #7500# sgetman(): extracts the mantissa of the input argument. The #7501# mantissa is converted to an extended precision number w/ #7502# an exponent of $3fff and is returned in fp0. The range of #7503# the result is [1.0 - 2.0). #7504# sgetmand(): handles denormalized numbers. #7505# #7506# INPUT *************************************************************** #7507# a0 = pointer to extended precision input #7508# #7509# OUTPUT ************************************************************** #7510# fp0 = exponent(X) or mantissa(X) #7511# #7512#########################################################################75137514global sgetexp7515sgetexp:7516mov.w SRC_EX(%a0),%d0 # get the exponent7517bclr &0xf,%d0 # clear the sign bit7518subi.w &0x3fff,%d0 # subtract off the bias7519fmov.w %d0,%fp0 # return exp in fp07520blt.b sgetexpn # it's negative7521rts75227523sgetexpn:7524mov.b &neg_bmask,FPSR_CC(%a6) # set 'N' ccode bit7525rts75267527global sgetexpd7528sgetexpd:7529bsr.l norm # normalize7530neg.w %d0 # new exp = -(shft amt)7531subi.w &0x3fff,%d0 # subtract off the bias7532fmov.w %d0,%fp0 # return exp in fp07533mov.b &neg_bmask,FPSR_CC(%a6) # set 'N' ccode bit7534rts75357536global sgetman7537sgetman:7538mov.w SRC_EX(%a0),%d0 # get the exp7539ori.w &0x7fff,%d0 # clear old exp7540bclr &0xe,%d0 # make it the new exp +-3fff75417542# here, we build the result in a tmp location so as not to disturb the input7543mov.l SRC_HI(%a0),FP_SCR0_HI(%a6) # copy to tmp loc7544mov.l SRC_LO(%a0),FP_SCR0_LO(%a6) # copy to tmp loc7545mov.w %d0,FP_SCR0_EX(%a6) # insert new exponent7546fmov.x FP_SCR0(%a6),%fp0 # put new value back in fp07547bmi.b sgetmann # it's negative7548rts75497550sgetmann:7551mov.b &neg_bmask,FPSR_CC(%a6) # set 'N' ccode bit7552rts75537554#7555# For denormalized numbers, shift the mantissa until the j-bit = 1,7556# then load the exponent with +/1 $3fff.7557#7558global sgetmand7559sgetmand:7560bsr.l norm # normalize exponent7561bra.b sgetman75627563#########################################################################7564# scosh(): computes the hyperbolic cosine of a normalized input #7565# scoshd(): computes the hyperbolic cosine of a denormalized input #7566# #7567# INPUT *************************************************************** #7568# a0 = pointer to extended precision input #7569# d0 = round precision,mode #7570# #7571# OUTPUT ************************************************************** #7572# fp0 = cosh(X) #7573# #7574# ACCURACY and MONOTONICITY ******************************************* #7575# The returned result is within 3 ulps in 64 significant bit, #7576# i.e. within 0.5001 ulp to 53 bits if the result is subsequently #7577# rounded to double precision. The result is provably monotonic #7578# in double precision. #7579# #7580# ALGORITHM *********************************************************** #7581# #7582# COSH #7583# 1. If |X| > 16380 log2, go to 3. #7584# #7585# 2. (|X| <= 16380 log2) Cosh(X) is obtained by the formulae #7586# y = |X|, z = exp(Y), and #7587# cosh(X) = (1/2)*( z + 1/z ). #7588# Exit. #7589# #7590# 3. (|X| > 16380 log2). If |X| > 16480 log2, go to 5. #7591# #7592# 4. (16380 log2 < |X| <= 16480 log2) #7593# cosh(X) = sign(X) * exp(|X|)/2. #7594# However, invoking exp(|X|) may cause premature #7595# overflow. Thus, we calculate sinh(X) as follows: #7596# Y := |X| #7597# Fact := 2**(16380) #7598# Y' := Y - 16381 log2 #7599# cosh(X) := Fact * exp(Y'). #7600# Exit. #7601# #7602# 5. (|X| > 16480 log2) sinh(X) must overflow. Return #7603# Huge*Huge to generate overflow and an infinity with #7604# the appropriate sign. Huge is the largest finite number #7605# in extended format. Exit. #7606# #7607#########################################################################76087609TWO16380:7610long 0x7FFB0000,0x80000000,0x00000000,0x0000000076117612global scosh7613scosh:7614fmov.x (%a0),%fp0 # LOAD INPUT76157616mov.l (%a0),%d17617mov.w 4(%a0),%d17618and.l &0x7FFFFFFF,%d17619cmp.l %d1,&0x400CB1677620bgt.b COSHBIG76217622#--THIS IS THE USUAL CASE, |X| < 16380 LOG27623#--COSH(X) = (1/2) * ( EXP(X) + 1/EXP(X) )76247625fabs.x %fp0 # |X|76267627mov.l %d0,-(%sp)7628clr.l %d07629fmovm.x &0x01,-(%sp) # save |X| to stack7630lea (%sp),%a0 # pass ptr to |X|7631bsr setox # FP0 IS EXP(|X|)7632add.l &0xc,%sp # erase |X| from stack7633fmul.s &0x3F000000,%fp0 # (1/2)EXP(|X|)7634mov.l (%sp)+,%d076357636fmov.s &0x3E800000,%fp1 # (1/4)7637fdiv.x %fp0,%fp1 # 1/(2 EXP(|X|))76387639fmov.l %d0,%fpcr7640mov.b &FADD_OP,%d1 # last inst is ADD7641fadd.x %fp1,%fp07642bra t_catch76437644COSHBIG:7645cmp.l %d1,&0x400CB2B37646bgt.b COSHHUGE76477648fabs.x %fp07649fsub.d T1(%pc),%fp0 # (|X|-16381LOG2_LEAD)7650fsub.d T2(%pc),%fp0 # |X| - 16381 LOG2, ACCURATE76517652mov.l %d0,-(%sp)7653clr.l %d07654fmovm.x &0x01,-(%sp) # save fp0 to stack7655lea (%sp),%a0 # pass ptr to fp07656bsr setox7657add.l &0xc,%sp # clear fp0 from stack7658mov.l (%sp)+,%d076597660fmov.l %d0,%fpcr7661mov.b &FMUL_OP,%d1 # last inst is MUL7662fmul.x TWO16380(%pc),%fp07663bra t_catch76647665COSHHUGE:7666bra t_ovfl276677668global scoshd7669#--COSH(X) = 1 FOR DENORMALIZED X7670scoshd:7671fmov.s &0x3F800000,%fp076727673fmov.l %d0,%fpcr7674fadd.s &0x00800000,%fp07675bra t_pinx276767677#########################################################################7678# ssinh(): computes the hyperbolic sine of a normalized input #7679# ssinhd(): computes the hyperbolic sine of a denormalized input #7680# #7681# INPUT *************************************************************** #7682# a0 = pointer to extended precision input #7683# d0 = round precision,mode #7684# #7685# OUTPUT ************************************************************** #7686# fp0 = sinh(X) #7687# #7688# ACCURACY and MONOTONICITY ******************************************* #7689# The returned result is within 3 ulps in 64 significant bit, #7690# i.e. within 0.5001 ulp to 53 bits if the result is subsequently #7691# rounded to double precision. The result is provably monotonic #7692# in double precision. #7693# #7694# ALGORITHM *********************************************************** #7695# #7696# SINH #7697# 1. If |X| > 16380 log2, go to 3. #7698# #7699# 2. (|X| <= 16380 log2) Sinh(X) is obtained by the formula #7700# y = |X|, sgn = sign(X), and z = expm1(Y), #7701# sinh(X) = sgn*(1/2)*( z + z/(1+z) ). #7702# Exit. #7703# #7704# 3. If |X| > 16480 log2, go to 5. #7705# #7706# 4. (16380 log2 < |X| <= 16480 log2) #7707# sinh(X) = sign(X) * exp(|X|)/2. #7708# However, invoking exp(|X|) may cause premature overflow. #7709# Thus, we calculate sinh(X) as follows: #7710# Y := |X| #7711# sgn := sign(X) #7712# sgnFact := sgn * 2**(16380) #7713# Y' := Y - 16381 log2 #7714# sinh(X) := sgnFact * exp(Y'). #7715# Exit. #7716# #7717# 5. (|X| > 16480 log2) sinh(X) must overflow. Return #7718# sign(X)*Huge*Huge to generate overflow and an infinity with #7719# the appropriate sign. Huge is the largest finite number in #7720# extended format. Exit. #7721# #7722#########################################################################77237724global ssinh7725ssinh:7726fmov.x (%a0),%fp0 # LOAD INPUT77277728mov.l (%a0),%d17729mov.w 4(%a0),%d17730mov.l %d1,%a1 # save (compacted) operand7731and.l &0x7FFFFFFF,%d17732cmp.l %d1,&0x400CB1677733bgt.b SINHBIG77347735#--THIS IS THE USUAL CASE, |X| < 16380 LOG27736#--Y = |X|, Z = EXPM1(Y), SINH(X) = SIGN(X)*(1/2)*( Z + Z/(1+Z) )77377738fabs.x %fp0 # Y = |X|77397740movm.l &0x8040,-(%sp) # {a1/d0}7741fmovm.x &0x01,-(%sp) # save Y on stack7742lea (%sp),%a0 # pass ptr to Y7743clr.l %d07744bsr setoxm1 # FP0 IS Z = EXPM1(Y)7745add.l &0xc,%sp # clear Y from stack7746fmov.l &0,%fpcr7747movm.l (%sp)+,&0x0201 # {a1/d0}77487749fmov.x %fp0,%fp17750fadd.s &0x3F800000,%fp1 # 1+Z7751fmov.x %fp0,-(%sp)7752fdiv.x %fp1,%fp0 # Z/(1+Z)7753mov.l %a1,%d17754and.l &0x80000000,%d17755or.l &0x3F000000,%d17756fadd.x (%sp)+,%fp07757mov.l %d1,-(%sp)77587759fmov.l %d0,%fpcr7760mov.b &FMUL_OP,%d1 # last inst is MUL7761fmul.s (%sp)+,%fp0 # last fp inst - possible exceptions set7762bra t_catch77637764SINHBIG:7765cmp.l %d1,&0x400CB2B37766bgt t_ovfl7767fabs.x %fp07768fsub.d T1(%pc),%fp0 # (|X|-16381LOG2_LEAD)7769mov.l &0,-(%sp)7770mov.l &0x80000000,-(%sp)7771mov.l %a1,%d17772and.l &0x80000000,%d17773or.l &0x7FFB0000,%d17774mov.l %d1,-(%sp) # EXTENDED FMT7775fsub.d T2(%pc),%fp0 # |X| - 16381 LOG2, ACCURATE77767777mov.l %d0,-(%sp)7778clr.l %d07779fmovm.x &0x01,-(%sp) # save fp0 on stack7780lea (%sp),%a0 # pass ptr to fp07781bsr setox7782add.l &0xc,%sp # clear fp0 from stack77837784mov.l (%sp)+,%d07785fmov.l %d0,%fpcr7786mov.b &FMUL_OP,%d1 # last inst is MUL7787fmul.x (%sp)+,%fp0 # possible exception7788bra t_catch77897790global ssinhd7791#--SINH(X) = X FOR DENORMALIZED X7792ssinhd:7793bra t_extdnrm77947795#########################################################################7796# stanh(): computes the hyperbolic tangent of a normalized input #7797# stanhd(): computes the hyperbolic tangent of a denormalized input #7798# #7799# INPUT *************************************************************** #7800# a0 = pointer to extended precision input #7801# d0 = round precision,mode #7802# #7803# OUTPUT ************************************************************** #7804# fp0 = tanh(X) #7805# #7806# ACCURACY and MONOTONICITY ******************************************* #7807# The returned result is within 3 ulps in 64 significant bit, #7808# i.e. within 0.5001 ulp to 53 bits if the result is subsequently #7809# rounded to double precision. The result is provably monotonic #7810# in double precision. #7811# #7812# ALGORITHM *********************************************************** #7813# #7814# TANH #7815# 1. If |X| >= (5/2) log2 or |X| <= 2**(-40), go to 3. #7816# #7817# 2. (2**(-40) < |X| < (5/2) log2) Calculate tanh(X) by #7818# sgn := sign(X), y := 2|X|, z := expm1(Y), and #7819# tanh(X) = sgn*( z/(2+z) ). #7820# Exit. #7821# #7822# 3. (|X| <= 2**(-40) or |X| >= (5/2) log2). If |X| < 1, #7823# go to 7. #7824# #7825# 4. (|X| >= (5/2) log2) If |X| >= 50 log2, go to 6. #7826# #7827# 5. ((5/2) log2 <= |X| < 50 log2) Calculate tanh(X) by #7828# sgn := sign(X), y := 2|X|, z := exp(Y), #7829# tanh(X) = sgn - [ sgn*2/(1+z) ]. #7830# Exit. #7831# #7832# 6. (|X| >= 50 log2) Tanh(X) = +-1 (round to nearest). Thus, we #7833# calculate Tanh(X) by #7834# sgn := sign(X), Tiny := 2**(-126), #7835# tanh(X) := sgn - sgn*Tiny. #7836# Exit. #7837# #7838# 7. (|X| < 2**(-40)). Tanh(X) = X. Exit. #7839# #7840#########################################################################78417842set X,FP_SCR07843set XFRAC,X+478447845set SGN,L_SCR378467847set V,FP_SCR078487849global stanh7850stanh:7851fmov.x (%a0),%fp0 # LOAD INPUT78527853fmov.x %fp0,X(%a6)7854mov.l (%a0),%d17855mov.w 4(%a0),%d17856mov.l %d1,X(%a6)7857and.l &0x7FFFFFFF,%d17858cmp.l %d1, &0x3fd78000 # is |X| < 2^(-40)?7859blt.w TANHBORS # yes7860cmp.l %d1, &0x3fffddce # is |X| > (5/2)LOG2?7861bgt.w TANHBORS # yes78627863#--THIS IS THE USUAL CASE7864#--Y = 2|X|, Z = EXPM1(Y), TANH(X) = SIGN(X) * Z / (Z+2).78657866mov.l X(%a6),%d17867mov.l %d1,SGN(%a6)7868and.l &0x7FFF0000,%d17869add.l &0x00010000,%d1 # EXPONENT OF 2|X|7870mov.l %d1,X(%a6)7871and.l &0x80000000,SGN(%a6)7872fmov.x X(%a6),%fp0 # FP0 IS Y = 2|X|78737874mov.l %d0,-(%sp)7875clr.l %d07876fmovm.x &0x1,-(%sp) # save Y on stack7877lea (%sp),%a0 # pass ptr to Y7878bsr setoxm1 # FP0 IS Z = EXPM1(Y)7879add.l &0xc,%sp # clear Y from stack7880mov.l (%sp)+,%d078817882fmov.x %fp0,%fp17883fadd.s &0x40000000,%fp1 # Z+27884mov.l SGN(%a6),%d17885fmov.x %fp1,V(%a6)7886eor.l %d1,V(%a6)78877888fmov.l %d0,%fpcr # restore users round prec,mode7889fdiv.x V(%a6),%fp07890bra t_inx278917892TANHBORS:7893cmp.l %d1,&0x3FFF80007894blt.w TANHSM78957896cmp.l %d1,&0x40048AA17897bgt.w TANHHUGE78987899#-- (5/2) LOG2 < |X| < 50 LOG2,7900#--TANH(X) = 1 - (2/[EXP(2X)+1]). LET Y = 2|X|, SGN = SIGN(X),7901#--TANH(X) = SGN - SGN*2/[EXP(Y)+1].79027903mov.l X(%a6),%d17904mov.l %d1,SGN(%a6)7905and.l &0x7FFF0000,%d17906add.l &0x00010000,%d1 # EXPO OF 2|X|7907mov.l %d1,X(%a6) # Y = 2|X|7908and.l &0x80000000,SGN(%a6)7909mov.l SGN(%a6),%d17910fmov.x X(%a6),%fp0 # Y = 2|X|79117912mov.l %d0,-(%sp)7913clr.l %d07914fmovm.x &0x01,-(%sp) # save Y on stack7915lea (%sp),%a0 # pass ptr to Y7916bsr setox # FP0 IS EXP(Y)7917add.l &0xc,%sp # clear Y from stack7918mov.l (%sp)+,%d07919mov.l SGN(%a6),%d17920fadd.s &0x3F800000,%fp0 # EXP(Y)+179217922eor.l &0xC0000000,%d1 # -SIGN(X)*27923fmov.s %d1,%fp1 # -SIGN(X)*2 IN SGL FMT7924fdiv.x %fp0,%fp1 # -SIGN(X)2 / [EXP(Y)+1 ]79257926mov.l SGN(%a6),%d17927or.l &0x3F800000,%d1 # SGN7928fmov.s %d1,%fp0 # SGN IN SGL FMT79297930fmov.l %d0,%fpcr # restore users round prec,mode7931mov.b &FADD_OP,%d1 # last inst is ADD7932fadd.x %fp1,%fp07933bra t_inx279347935TANHSM:7936fmov.l %d0,%fpcr # restore users round prec,mode7937mov.b &FMOV_OP,%d1 # last inst is MOVE7938fmov.x X(%a6),%fp0 # last inst - possible exception set7939bra t_catch79407941#---RETURN SGN(X) - SGN(X)EPS7942TANHHUGE:7943mov.l X(%a6),%d17944and.l &0x80000000,%d17945or.l &0x3F800000,%d17946fmov.s %d1,%fp07947and.l &0x80000000,%d17948eor.l &0x80800000,%d1 # -SIGN(X)*EPS79497950fmov.l %d0,%fpcr # restore users round prec,mode7951fadd.s %d1,%fp07952bra t_inx279537954global stanhd7955#--TANH(X) = X FOR DENORMALIZED X7956stanhd:7957bra t_extdnrm79587959#########################################################################7960# slogn(): computes the natural logarithm of a normalized input #7961# slognd(): computes the natural logarithm of a denormalized input #7962# slognp1(): computes the log(1+X) of a normalized input #7963# slognp1d(): computes the log(1+X) of a denormalized input #7964# #7965# INPUT *************************************************************** #7966# a0 = pointer to extended precision input #7967# d0 = round precision,mode #7968# #7969# OUTPUT ************************************************************** #7970# fp0 = log(X) or log(1+X) #7971# #7972# ACCURACY and MONOTONICITY ******************************************* #7973# The returned result is within 2 ulps in 64 significant bit, #7974# i.e. within 0.5001 ulp to 53 bits if the result is subsequently #7975# rounded to double precision. The result is provably monotonic #7976# in double precision. #7977# #7978# ALGORITHM *********************************************************** #7979# LOGN: #7980# Step 1. If |X-1| < 1/16, approximate log(X) by an odd #7981# polynomial in u, where u = 2(X-1)/(X+1). Otherwise, #7982# move on to Step 2. #7983# #7984# Step 2. X = 2**k * Y where 1 <= Y < 2. Define F to be the first #7985# seven significant bits of Y plus 2**(-7), i.e. #7986# F = 1.xxxxxx1 in base 2 where the six "x" match those #7987# of Y. Note that |Y-F| <= 2**(-7). #7988# #7989# Step 3. Define u = (Y-F)/F. Approximate log(1+u) by a #7990# polynomial in u, log(1+u) = poly. #7991# #7992# Step 4. Reconstruct #7993# log(X) = log( 2**k * Y ) = k*log(2) + log(F) + log(1+u) #7994# by k*log(2) + (log(F) + poly). The values of log(F) are #7995# calculated beforehand and stored in the program. #7996# #7997# lognp1: #7998# Step 1: If |X| < 1/16, approximate log(1+X) by an odd #7999# polynomial in u where u = 2X/(2+X). Otherwise, move on #8000# to Step 2. #8001# #8002# Step 2: Let 1+X = 2**k * Y, where 1 <= Y < 2. Define F as done #8003# in Step 2 of the algorithm for LOGN and compute #8004# log(1+X) as k*log(2) + log(F) + poly where poly #8005# approximates log(1+u), u = (Y-F)/F. #8006# #8007# Implementation Notes: #8008# Note 1. There are 64 different possible values for F, thus 64 #8009# log(F)'s need to be tabulated. Moreover, the values of #8010# 1/F are also tabulated so that the division in (Y-F)/F #8011# can be performed by a multiplication. #8012# #8013# Note 2. In Step 2 of lognp1, in order to preserved accuracy, #8014# the value Y-F has to be calculated carefully when #8015# 1/2 <= X < 3/2. #8016# #8017# Note 3. To fully exploit the pipeline, polynomials are usually #8018# separated into two parts evaluated independently before #8019# being added up. #8020# #8021#########################################################################8022LOGOF2:8023long 0x3FFE0000,0xB17217F7,0xD1CF79AC,0x0000000080248025one:8026long 0x3F8000008027zero:8028long 0x000000008029infty:8030long 0x7F8000008031negone:8032long 0xBF80000080338034LOGA6:8035long 0x3FC2499A,0xB5E4040B8036LOGA5:8037long 0xBFC555B5,0x848CB7DB80388039LOGA4:8040long 0x3FC99999,0x987D87308041LOGA3:8042long 0xBFCFFFFF,0xFF6F7E9780438044LOGA2:8045long 0x3FD55555,0x555555A48046LOGA1:8047long 0xBFE00000,0x0000000880488049LOGB5:8050long 0x3F175496,0xADD7DAD68051LOGB4:8052long 0x3F3C71C2,0xFE80C7E080538054LOGB3:8055long 0x3F624924,0x928BCCFF8056LOGB2:8057long 0x3F899999,0x999995EC80588059LOGB1:8060long 0x3FB55555,0x555555558061TWO:8062long 0x40000000,0x0000000080638064LTHOLD:8065long 0x3f990000,0x80000000,0x00000000,0x0000000080668067LOGTBL:8068long 0x3FFE0000,0xFE03F80F,0xE03F80FE,0x000000008069long 0x3FF70000,0xFF015358,0x833C47E2,0x000000008070long 0x3FFE0000,0xFA232CF2,0x52138AC0,0x000000008071long 0x3FF90000,0xBDC8D83E,0xAD88D549,0x000000008072long 0x3FFE0000,0xF6603D98,0x0F6603DA,0x000000008073long 0x3FFA0000,0x9CF43DCF,0xF5EAFD48,0x000000008074long 0x3FFE0000,0xF2B9D648,0x0F2B9D65,0x000000008075long 0x3FFA0000,0xDA16EB88,0xCB8DF614,0x000000008076long 0x3FFE0000,0xEF2EB71F,0xC4345238,0x000000008077long 0x3FFB0000,0x8B29B775,0x1BD70743,0x000000008078long 0x3FFE0000,0xEBBDB2A5,0xC1619C8C,0x000000008079long 0x3FFB0000,0xA8D839F8,0x30C1FB49,0x000000008080long 0x3FFE0000,0xE865AC7B,0x7603A197,0x000000008081long 0x3FFB0000,0xC61A2EB1,0x8CD907AD,0x000000008082long 0x3FFE0000,0xE525982A,0xF70C880E,0x000000008083long 0x3FFB0000,0xE2F2A47A,0xDE3A18AF,0x000000008084long 0x3FFE0000,0xE1FC780E,0x1FC780E2,0x000000008085long 0x3FFB0000,0xFF64898E,0xDF55D551,0x000000008086long 0x3FFE0000,0xDEE95C4C,0xA037BA57,0x000000008087long 0x3FFC0000,0x8DB956A9,0x7B3D0148,0x000000008088long 0x3FFE0000,0xDBEB61EE,0xD19C5958,0x000000008089long 0x3FFC0000,0x9B8FE100,0xF47BA1DE,0x000000008090long 0x3FFE0000,0xD901B203,0x6406C80E,0x000000008091long 0x3FFC0000,0xA9372F1D,0x0DA1BD17,0x000000008092long 0x3FFE0000,0xD62B80D6,0x2B80D62C,0x000000008093long 0x3FFC0000,0xB6B07F38,0xCE90E46B,0x000000008094long 0x3FFE0000,0xD3680D36,0x80D3680D,0x000000008095long 0x3FFC0000,0xC3FD0329,0x06488481,0x000000008096long 0x3FFE0000,0xD0B69FCB,0xD2580D0B,0x000000008097long 0x3FFC0000,0xD11DE0FF,0x15AB18CA,0x000000008098long 0x3FFE0000,0xCE168A77,0x25080CE1,0x000000008099long 0x3FFC0000,0xDE1433A1,0x6C66B150,0x000000008100long 0x3FFE0000,0xCB8727C0,0x65C393E0,0x000000008101long 0x3FFC0000,0xEAE10B5A,0x7DDC8ADD,0x000000008102long 0x3FFE0000,0xC907DA4E,0x871146AD,0x000000008103long 0x3FFC0000,0xF7856E5E,0xE2C9B291,0x000000008104long 0x3FFE0000,0xC6980C69,0x80C6980C,0x000000008105long 0x3FFD0000,0x82012CA5,0xA68206D7,0x000000008106long 0x3FFE0000,0xC4372F85,0x5D824CA6,0x000000008107long 0x3FFD0000,0x882C5FCD,0x7256A8C5,0x000000008108long 0x3FFE0000,0xC1E4BBD5,0x95F6E947,0x000000008109long 0x3FFD0000,0x8E44C60B,0x4CCFD7DE,0x000000008110long 0x3FFE0000,0xBFA02FE8,0x0BFA02FF,0x000000008111long 0x3FFD0000,0x944AD09E,0xF4351AF6,0x000000008112long 0x3FFE0000,0xBD691047,0x07661AA3,0x000000008113long 0x3FFD0000,0x9A3EECD4,0xC3EAA6B2,0x000000008114long 0x3FFE0000,0xBB3EE721,0xA54D880C,0x000000008115long 0x3FFD0000,0xA0218434,0x353F1DE8,0x000000008116long 0x3FFE0000,0xB92143FA,0x36F5E02E,0x000000008117long 0x3FFD0000,0xA5F2FCAB,0xBBC506DA,0x000000008118long 0x3FFE0000,0xB70FBB5A,0x19BE3659,0x000000008119long 0x3FFD0000,0xABB3B8BA,0x2AD362A5,0x000000008120long 0x3FFE0000,0xB509E68A,0x9B94821F,0x000000008121long 0x3FFD0000,0xB1641795,0xCE3CA97B,0x000000008122long 0x3FFE0000,0xB30F6352,0x8917C80B,0x000000008123long 0x3FFD0000,0xB7047551,0x5D0F1C61,0x000000008124long 0x3FFE0000,0xB11FD3B8,0x0B11FD3C,0x000000008125long 0x3FFD0000,0xBC952AFE,0xEA3D13E1,0x000000008126long 0x3FFE0000,0xAF3ADDC6,0x80AF3ADE,0x000000008127long 0x3FFD0000,0xC2168ED0,0xF458BA4A,0x000000008128long 0x3FFE0000,0xAD602B58,0x0AD602B6,0x000000008129long 0x3FFD0000,0xC788F439,0xB3163BF1,0x000000008130long 0x3FFE0000,0xAB8F69E2,0x8359CD11,0x000000008131long 0x3FFD0000,0xCCECAC08,0xBF04565D,0x000000008132long 0x3FFE0000,0xA9C84A47,0xA07F5638,0x000000008133long 0x3FFD0000,0xD2420487,0x2DD85160,0x000000008134long 0x3FFE0000,0xA80A80A8,0x0A80A80B,0x000000008135long 0x3FFD0000,0xD7894992,0x3BC3588A,0x000000008136long 0x3FFE0000,0xA655C439,0x2D7B73A8,0x000000008137long 0x3FFD0000,0xDCC2C4B4,0x9887DACC,0x000000008138long 0x3FFE0000,0xA4A9CF1D,0x96833751,0x000000008139long 0x3FFD0000,0xE1EEBD3E,0x6D6A6B9E,0x000000008140long 0x3FFE0000,0xA3065E3F,0xAE7CD0E0,0x000000008141long 0x3FFD0000,0xE70D785C,0x2F9F5BDC,0x000000008142long 0x3FFE0000,0xA16B312E,0xA8FC377D,0x000000008143long 0x3FFD0000,0xEC1F392C,0x5179F283,0x000000008144long 0x3FFE0000,0x9FD809FD,0x809FD80A,0x000000008145long 0x3FFD0000,0xF12440D3,0xE36130E6,0x000000008146long 0x3FFE0000,0x9E4CAD23,0xDD5F3A20,0x000000008147long 0x3FFD0000,0xF61CCE92,0x346600BB,0x000000008148long 0x3FFE0000,0x9CC8E160,0xC3FB19B9,0x000000008149long 0x3FFD0000,0xFB091FD3,0x8145630A,0x000000008150long 0x3FFE0000,0x9B4C6F9E,0xF03A3CAA,0x000000008151long 0x3FFD0000,0xFFE97042,0xBFA4C2AD,0x000000008152long 0x3FFE0000,0x99D722DA,0xBDE58F06,0x000000008153long 0x3FFE0000,0x825EFCED,0x49369330,0x000000008154long 0x3FFE0000,0x9868C809,0x868C8098,0x000000008155long 0x3FFE0000,0x84C37A7A,0xB9A905C9,0x000000008156long 0x3FFE0000,0x97012E02,0x5C04B809,0x000000008157long 0x3FFE0000,0x87224C2E,0x8E645FB7,0x000000008158long 0x3FFE0000,0x95A02568,0x095A0257,0x000000008159long 0x3FFE0000,0x897B8CAC,0x9F7DE298,0x000000008160long 0x3FFE0000,0x94458094,0x45809446,0x000000008161long 0x3FFE0000,0x8BCF55DE,0xC4CD05FE,0x000000008162long 0x3FFE0000,0x92F11384,0x0497889C,0x000000008163long 0x3FFE0000,0x8E1DC0FB,0x89E125E5,0x000000008164long 0x3FFE0000,0x91A2B3C4,0xD5E6F809,0x000000008165long 0x3FFE0000,0x9066E68C,0x955B6C9B,0x000000008166long 0x3FFE0000,0x905A3863,0x3E06C43B,0x000000008167long 0x3FFE0000,0x92AADE74,0xC7BE59E0,0x000000008168long 0x3FFE0000,0x8F1779D9,0xFDC3A219,0x000000008169long 0x3FFE0000,0x94E9BFF6,0x15845643,0x000000008170long 0x3FFE0000,0x8DDA5202,0x37694809,0x000000008171long 0x3FFE0000,0x9723A1B7,0x20134203,0x000000008172long 0x3FFE0000,0x8CA29C04,0x6514E023,0x000000008173long 0x3FFE0000,0x995899C8,0x90EB8990,0x000000008174long 0x3FFE0000,0x8B70344A,0x139BC75A,0x000000008175long 0x3FFE0000,0x9B88BDAA,0x3A3DAE2F,0x000000008176long 0x3FFE0000,0x8A42F870,0x5669DB46,0x000000008177long 0x3FFE0000,0x9DB4224F,0xFFE1157C,0x000000008178long 0x3FFE0000,0x891AC73A,0xE9819B50,0x000000008179long 0x3FFE0000,0x9FDADC26,0x8B7A12DA,0x000000008180long 0x3FFE0000,0x87F78087,0xF78087F8,0x000000008181long 0x3FFE0000,0xA1FCFF17,0xCE733BD4,0x000000008182long 0x3FFE0000,0x86D90544,0x7A34ACC6,0x000000008183long 0x3FFE0000,0xA41A9E8F,0x5446FB9F,0x000000008184long 0x3FFE0000,0x85BF3761,0x2CEE3C9B,0x000000008185long 0x3FFE0000,0xA633CD7E,0x6771CD8B,0x000000008186long 0x3FFE0000,0x84A9F9C8,0x084A9F9D,0x000000008187long 0x3FFE0000,0xA8489E60,0x0B435A5E,0x000000008188long 0x3FFE0000,0x83993052,0x3FBE3368,0x000000008189long 0x3FFE0000,0xAA59233C,0xCCA4BD49,0x000000008190long 0x3FFE0000,0x828CBFBE,0xB9A020A3,0x000000008191long 0x3FFE0000,0xAC656DAE,0x6BCC4985,0x000000008192long 0x3FFE0000,0x81848DA8,0xFAF0D277,0x000000008193long 0x3FFE0000,0xAE6D8EE3,0x60BB2468,0x000000008194long 0x3FFE0000,0x80808080,0x80808081,0x000000008195long 0x3FFE0000,0xB07197A2,0x3C46C654,0x0000000081968197set ADJK,L_SCR181988199set X,FP_SCR08200set XDCARE,X+28201set XFRAC,X+482028203set F,FP_SCR18204set FFRAC,F+482058206set KLOG2,FP_SCR082078208set SAVEU,FP_SCR082098210global slogn8211#--ENTRY POINT FOR LOG(X) FOR X FINITE, NON-ZERO, NOT NAN'S8212slogn:8213fmov.x (%a0),%fp0 # LOAD INPUT8214mov.l &0x00000000,ADJK(%a6)82158216LOGBGN:8217#--FPCR SAVED AND CLEARED, INPUT IS 2^(ADJK)*FP0, FP0 CONTAINS8218#--A FINITE, NON-ZERO, NORMALIZED NUMBER.82198220mov.l (%a0),%d18221mov.w 4(%a0),%d182228223mov.l (%a0),X(%a6)8224mov.l 4(%a0),X+4(%a6)8225mov.l 8(%a0),X+8(%a6)82268227cmp.l %d1,&0 # CHECK IF X IS NEGATIVE8228blt.w LOGNEG # LOG OF NEGATIVE ARGUMENT IS INVALID8229# X IS POSITIVE, CHECK IF X IS NEAR 18230cmp.l %d1,&0x3ffef07d # IS X < 15/16?8231blt.b LOGMAIN # YES8232cmp.l %d1,&0x3fff8841 # IS X > 17/16?8233ble.w LOGNEAR1 # NO82348235LOGMAIN:8236#--THIS SHOULD BE THE USUAL CASE, X NOT VERY CLOSE TO 182378238#--X = 2^(K) * Y, 1 <= Y < 2. THUS, Y = 1.XXXXXXXX....XX IN BINARY.8239#--WE DEFINE F = 1.XXXXXX1, I.E. FIRST 7 BITS OF Y AND ATTACH A 1.8240#--THE IDEA IS THAT LOG(X) = K*LOG2 + LOG(Y)8241#-- = K*LOG2 + LOG(F) + LOG(1 + (Y-F)/F).8242#--NOTE THAT U = (Y-F)/F IS VERY SMALL AND THUS APPROXIMATING8243#--LOG(1+U) CAN BE VERY EFFICIENT.8244#--ALSO NOTE THAT THE VALUE 1/F IS STORED IN A TABLE SO THAT NO8245#--DIVISION IS NEEDED TO CALCULATE (Y-F)/F.82468247#--GET K, Y, F, AND ADDRESS OF 1/F.8248asr.l &8,%d18249asr.l &8,%d1 # SHIFTED 16 BITS, BIASED EXPO. OF X8250sub.l &0x3FFF,%d1 # THIS IS K8251add.l ADJK(%a6),%d1 # ADJUST K, ORIGINAL INPUT MAY BE DENORM.8252lea LOGTBL(%pc),%a0 # BASE ADDRESS OF 1/F AND LOG(F)8253fmov.l %d1,%fp1 # CONVERT K TO FLOATING-POINT FORMAT82548255#--WHILE THE CONVERSION IS GOING ON, WE GET F AND ADDRESS OF 1/F8256mov.l &0x3FFF0000,X(%a6) # X IS NOW Y, I.E. 2^(-K)*X8257mov.l XFRAC(%a6),FFRAC(%a6)8258and.l &0xFE000000,FFRAC(%a6) # FIRST 7 BITS OF Y8259or.l &0x01000000,FFRAC(%a6) # GET F: ATTACH A 1 AT THE EIGHTH BIT8260mov.l FFRAC(%a6),%d1 # READY TO GET ADDRESS OF 1/F8261and.l &0x7E000000,%d18262asr.l &8,%d18263asr.l &8,%d18264asr.l &4,%d1 # SHIFTED 20, D0 IS THE DISPLACEMENT8265add.l %d1,%a0 # A0 IS THE ADDRESS FOR 1/F82668267fmov.x X(%a6),%fp08268mov.l &0x3fff0000,F(%a6)8269clr.l F+8(%a6)8270fsub.x F(%a6),%fp0 # Y-F8271fmovm.x &0xc,-(%sp) # SAVE FP2-3 WHILE FP0 IS NOT READY8272#--SUMMARY: FP0 IS Y-F, A0 IS ADDRESS OF 1/F, FP1 IS K8273#--REGISTERS SAVED: FPCR, FP1, FP282748275LP1CONT1:8276#--AN RE-ENTRY POINT FOR LOGNP18277fmul.x (%a0),%fp0 # FP0 IS U = (Y-F)/F8278fmul.x LOGOF2(%pc),%fp1 # GET K*LOG2 WHILE FP0 IS NOT READY8279fmov.x %fp0,%fp28280fmul.x %fp2,%fp2 # FP2 IS V=U*U8281fmov.x %fp1,KLOG2(%a6) # PUT K*LOG2 IN MEMEORY, FREE FP182828283#--LOG(1+U) IS APPROXIMATED BY8284#--U + V*(A1+U*(A2+U*(A3+U*(A4+U*(A5+U*A6))))) WHICH IS8285#--[U + V*(A1+V*(A3+V*A5))] + [U*V*(A2+V*(A4+V*A6))]82868287fmov.x %fp2,%fp38288fmov.x %fp2,%fp182898290fmul.d LOGA6(%pc),%fp1 # V*A68291fmul.d LOGA5(%pc),%fp2 # V*A582928293fadd.d LOGA4(%pc),%fp1 # A4+V*A68294fadd.d LOGA3(%pc),%fp2 # A3+V*A582958296fmul.x %fp3,%fp1 # V*(A4+V*A6)8297fmul.x %fp3,%fp2 # V*(A3+V*A5)82988299fadd.d LOGA2(%pc),%fp1 # A2+V*(A4+V*A6)8300fadd.d LOGA1(%pc),%fp2 # A1+V*(A3+V*A5)83018302fmul.x %fp3,%fp1 # V*(A2+V*(A4+V*A6))8303add.l &16,%a0 # ADDRESS OF LOG(F)8304fmul.x %fp3,%fp2 # V*(A1+V*(A3+V*A5))83058306fmul.x %fp0,%fp1 # U*V*(A2+V*(A4+V*A6))8307fadd.x %fp2,%fp0 # U+V*(A1+V*(A3+V*A5))83088309fadd.x (%a0),%fp1 # LOG(F)+U*V*(A2+V*(A4+V*A6))8310fmovm.x (%sp)+,&0x30 # RESTORE FP2-38311fadd.x %fp1,%fp0 # FP0 IS LOG(F) + LOG(1+U)83128313fmov.l %d0,%fpcr8314fadd.x KLOG2(%a6),%fp0 # FINAL ADD8315bra t_inx2831683178318LOGNEAR1:83198320# if the input is exactly equal to one, then exit through ld_pzero.8321# if these 2 lines weren't here, the correct answer would be returned8322# but the INEX2 bit would be set.8323fcmp.b %fp0,&0x1 # is it equal to one?8324fbeq.l ld_pzero # yes83258326#--REGISTERS SAVED: FPCR, FP1. FP0 CONTAINS THE INPUT.8327fmov.x %fp0,%fp18328fsub.s one(%pc),%fp1 # FP1 IS X-18329fadd.s one(%pc),%fp0 # FP0 IS X+18330fadd.x %fp1,%fp1 # FP1 IS 2(X-1)8331#--LOG(X) = LOG(1+U/2)-LOG(1-U/2) WHICH IS AN ODD POLYNOMIAL8332#--IN U, U = 2(X-1)/(X+1) = FP1/FP083338334LP1CONT2:8335#--THIS IS AN RE-ENTRY POINT FOR LOGNP18336fdiv.x %fp0,%fp1 # FP1 IS U8337fmovm.x &0xc,-(%sp) # SAVE FP2-38338#--REGISTERS SAVED ARE NOW FPCR,FP1,FP2,FP38339#--LET V=U*U, W=V*V, CALCULATE8340#--U + U*V*(B1 + V*(B2 + V*(B3 + V*(B4 + V*B5)))) BY8341#--U + U*V*( [B1 + W*(B3 + W*B5)] + [V*(B2 + W*B4)] )8342fmov.x %fp1,%fp08343fmul.x %fp0,%fp0 # FP0 IS V8344fmov.x %fp1,SAVEU(%a6) # STORE U IN MEMORY, FREE FP18345fmov.x %fp0,%fp18346fmul.x %fp1,%fp1 # FP1 IS W83478348fmov.d LOGB5(%pc),%fp38349fmov.d LOGB4(%pc),%fp283508351fmul.x %fp1,%fp3 # W*B58352fmul.x %fp1,%fp2 # W*B483538354fadd.d LOGB3(%pc),%fp3 # B3+W*B58355fadd.d LOGB2(%pc),%fp2 # B2+W*B483568357fmul.x %fp3,%fp1 # W*(B3+W*B5), FP3 RELEASED83588359fmul.x %fp0,%fp2 # V*(B2+W*B4)83608361fadd.d LOGB1(%pc),%fp1 # B1+W*(B3+W*B5)8362fmul.x SAVEU(%a6),%fp0 # FP0 IS U*V83638364fadd.x %fp2,%fp1 # B1+W*(B3+W*B5) + V*(B2+W*B4), FP2 RELEASED8365fmovm.x (%sp)+,&0x30 # FP2-3 RESTORED83668367fmul.x %fp1,%fp0 # U*V*( [B1+W*(B3+W*B5)] + [V*(B2+W*B4)] )83688369fmov.l %d0,%fpcr8370fadd.x SAVEU(%a6),%fp08371bra t_inx283728373#--REGISTERS SAVED FPCR. LOG(-VE) IS INVALID8374LOGNEG:8375bra t_operr83768377global slognd8378slognd:8379#--ENTRY POINT FOR LOG(X) FOR DENORMALIZED INPUT83808381mov.l &-100,ADJK(%a6) # INPUT = 2^(ADJK) * FP083828383#----normalize the input value by left shifting k bits (k to be determined8384#----below), adjusting exponent and storing -k to ADJK8385#----the value TWOTO100 is no longer needed.8386#----Note that this code assumes the denormalized input is NON-ZERO.83878388movm.l &0x3f00,-(%sp) # save some registers {d2-d7}8389mov.l (%a0),%d3 # D3 is exponent of smallest norm. #8390mov.l 4(%a0),%d48391mov.l 8(%a0),%d5 # (D4,D5) is (Hi_X,Lo_X)8392clr.l %d2 # D2 used for holding K83938394tst.l %d48395bne.b Hi_not083968397Hi_0:8398mov.l %d5,%d48399clr.l %d58400mov.l &32,%d28401clr.l %d68402bfffo %d4{&0:&32},%d68403lsl.l %d6,%d48404add.l %d6,%d2 # (D3,D4,D5) is normalized84058406mov.l %d3,X(%a6)8407mov.l %d4,XFRAC(%a6)8408mov.l %d5,XFRAC+4(%a6)8409neg.l %d28410mov.l %d2,ADJK(%a6)8411fmov.x X(%a6),%fp08412movm.l (%sp)+,&0xfc # restore registers {d2-d7}8413lea X(%a6),%a08414bra.w LOGBGN # begin regular log(X)84158416Hi_not0:8417clr.l %d68418bfffo %d4{&0:&32},%d6 # find first 18419mov.l %d6,%d2 # get k8420lsl.l %d6,%d48421mov.l %d5,%d7 # a copy of D58422lsl.l %d6,%d58423neg.l %d68424add.l &32,%d68425lsr.l %d6,%d78426or.l %d7,%d4 # (D3,D4,D5) normalized84278428mov.l %d3,X(%a6)8429mov.l %d4,XFRAC(%a6)8430mov.l %d5,XFRAC+4(%a6)8431neg.l %d28432mov.l %d2,ADJK(%a6)8433fmov.x X(%a6),%fp08434movm.l (%sp)+,&0xfc # restore registers {d2-d7}8435lea X(%a6),%a08436bra.w LOGBGN # begin regular log(X)84378438global slognp18439#--ENTRY POINT FOR LOG(1+X) FOR X FINITE, NON-ZERO, NOT NAN'S8440slognp1:8441fmov.x (%a0),%fp0 # LOAD INPUT8442fabs.x %fp0 # test magnitude8443fcmp.x %fp0,LTHOLD(%pc) # compare with min threshold8444fbgt.w LP1REAL # if greater, continue8445fmov.l %d0,%fpcr8446mov.b &FMOV_OP,%d1 # last inst is MOVE8447fmov.x (%a0),%fp0 # return signed argument8448bra t_catch84498450LP1REAL:8451fmov.x (%a0),%fp0 # LOAD INPUT8452mov.l &0x00000000,ADJK(%a6)8453fmov.x %fp0,%fp1 # FP1 IS INPUT Z8454fadd.s one(%pc),%fp0 # X := ROUND(1+Z)8455fmov.x %fp0,X(%a6)8456mov.w XFRAC(%a6),XDCARE(%a6)8457mov.l X(%a6),%d18458cmp.l %d1,&08459ble.w LP1NEG0 # LOG OF ZERO OR -VE8460cmp.l %d1,&0x3ffe8000 # IS BOUNDS [1/2,3/2]?8461blt.w LOGMAIN8462cmp.l %d1,&0x3fffc0008463bgt.w LOGMAIN8464#--IF 1+Z > 3/2 OR 1+Z < 1/2, THEN X, WHICH IS ROUNDING 1+Z,8465#--CONTAINS AT LEAST 63 BITS OF INFORMATION OF Z. IN THAT CASE,8466#--SIMPLY INVOKE LOG(X) FOR LOG(1+Z).84678468LP1NEAR1:8469#--NEXT SEE IF EXP(-1/16) < X < EXP(1/16)8470cmp.l %d1,&0x3ffef07d8471blt.w LP1CARE8472cmp.l %d1,&0x3fff88418473bgt.w LP1CARE84748475LP1ONE16:8476#--EXP(-1/16) < X < EXP(1/16). LOG(1+Z) = LOG(1+U/2) - LOG(1-U/2)8477#--WHERE U = 2Z/(2+Z) = 2Z/(1+X).8478fadd.x %fp1,%fp1 # FP1 IS 2Z8479fadd.s one(%pc),%fp0 # FP0 IS 1+X8480#--U = FP1/FP08481bra.w LP1CONT284828483LP1CARE:8484#--HERE WE USE THE USUAL TABLE DRIVEN APPROACH. CARE HAS TO BE8485#--TAKEN BECAUSE 1+Z CAN HAVE 67 BITS OF INFORMATION AND WE MUST8486#--PRESERVE ALL THE INFORMATION. BECAUSE 1+Z IS IN [1/2,3/2],8487#--THERE ARE ONLY TWO CASES.8488#--CASE 1: 1+Z < 1, THEN K = -1 AND Y-F = (2-F) + 2Z8489#--CASE 2: 1+Z > 1, THEN K = 0 AND Y-F = (1-F) + Z8490#--ON RETURNING TO LP1CONT1, WE MUST HAVE K IN FP1, ADDRESS OF8491#--(1/F) IN A0, Y-F IN FP0, AND FP2 SAVED.84928493mov.l XFRAC(%a6),FFRAC(%a6)8494and.l &0xFE000000,FFRAC(%a6)8495or.l &0x01000000,FFRAC(%a6) # F OBTAINED8496cmp.l %d1,&0x3FFF8000 # SEE IF 1+Z > 18497bge.b KISZERO84988499KISNEG1:8500fmov.s TWO(%pc),%fp08501mov.l &0x3fff0000,F(%a6)8502clr.l F+8(%a6)8503fsub.x F(%a6),%fp0 # 2-F8504mov.l FFRAC(%a6),%d18505and.l &0x7E000000,%d18506asr.l &8,%d18507asr.l &8,%d18508asr.l &4,%d1 # D0 CONTAINS DISPLACEMENT FOR 1/F8509fadd.x %fp1,%fp1 # GET 2Z8510fmovm.x &0xc,-(%sp) # SAVE FP2 {%fp2/%fp3}8511fadd.x %fp1,%fp0 # FP0 IS Y-F = (2-F)+2Z8512lea LOGTBL(%pc),%a0 # A0 IS ADDRESS OF 1/F8513add.l %d1,%a08514fmov.s negone(%pc),%fp1 # FP1 IS K = -18515bra.w LP1CONT185168517KISZERO:8518fmov.s one(%pc),%fp08519mov.l &0x3fff0000,F(%a6)8520clr.l F+8(%a6)8521fsub.x F(%a6),%fp0 # 1-F8522mov.l FFRAC(%a6),%d18523and.l &0x7E000000,%d18524asr.l &8,%d18525asr.l &8,%d18526asr.l &4,%d18527fadd.x %fp1,%fp0 # FP0 IS Y-F8528fmovm.x &0xc,-(%sp) # FP2 SAVED {%fp2/%fp3}8529lea LOGTBL(%pc),%a08530add.l %d1,%a0 # A0 IS ADDRESS OF 1/F8531fmov.s zero(%pc),%fp1 # FP1 IS K = 08532bra.w LP1CONT185338534LP1NEG0:8535#--FPCR SAVED. D0 IS X IN COMPACT FORM.8536cmp.l %d1,&08537blt.b LP1NEG8538LP1ZERO:8539fmov.s negone(%pc),%fp085408541fmov.l %d0,%fpcr8542bra t_dz85438544LP1NEG:8545fmov.s zero(%pc),%fp085468547fmov.l %d0,%fpcr8548bra t_operr85498550global slognp1d8551#--ENTRY POINT FOR LOG(1+Z) FOR DENORMALIZED INPUT8552# Simply return the denorm8553slognp1d:8554bra t_extdnrm85558556#########################################################################8557# satanh(): computes the inverse hyperbolic tangent of a norm input #8558# satanhd(): computes the inverse hyperbolic tangent of a denorm input #8559# #8560# INPUT *************************************************************** #8561# a0 = pointer to extended precision input #8562# d0 = round precision,mode #8563# #8564# OUTPUT ************************************************************** #8565# fp0 = arctanh(X) #8566# #8567# ACCURACY and MONOTONICITY ******************************************* #8568# The returned result is within 3 ulps in 64 significant bit, #8569# i.e. within 0.5001 ulp to 53 bits if the result is subsequently #8570# rounded to double precision. The result is provably monotonic #8571# in double precision. #8572# #8573# ALGORITHM *********************************************************** #8574# #8575# ATANH #8576# 1. If |X| >= 1, go to 3. #8577# #8578# 2. (|X| < 1) Calculate atanh(X) by #8579# sgn := sign(X) #8580# y := |X| #8581# z := 2y/(1-y) #8582# atanh(X) := sgn * (1/2) * logp1(z) #8583# Exit. #8584# #8585# 3. If |X| > 1, go to 5. #8586# #8587# 4. (|X| = 1) Generate infinity with an appropriate sign and #8588# divide-by-zero by #8589# sgn := sign(X) #8590# atan(X) := sgn / (+0). #8591# Exit. #8592# #8593# 5. (|X| > 1) Generate an invalid operation by 0 * infinity. #8594# Exit. #8595# #8596#########################################################################85978598global satanh8599satanh:8600mov.l (%a0),%d18601mov.w 4(%a0),%d18602and.l &0x7FFFFFFF,%d18603cmp.l %d1,&0x3FFF80008604bge.b ATANHBIG86058606#--THIS IS THE USUAL CASE, |X| < 18607#--Y = |X|, Z = 2Y/(1-Y), ATANH(X) = SIGN(X) * (1/2) * LOG1P(Z).86088609fabs.x (%a0),%fp0 # Y = |X|8610fmov.x %fp0,%fp18611fneg.x %fp1 # -Y8612fadd.x %fp0,%fp0 # 2Y8613fadd.s &0x3F800000,%fp1 # 1-Y8614fdiv.x %fp1,%fp0 # 2Y/(1-Y)8615mov.l (%a0),%d18616and.l &0x80000000,%d18617or.l &0x3F000000,%d1 # SIGN(X)*HALF8618mov.l %d1,-(%sp)86198620mov.l %d0,-(%sp) # save rnd prec,mode8621clr.l %d0 # pass ext prec,RN8622fmovm.x &0x01,-(%sp) # save Z on stack8623lea (%sp),%a0 # pass ptr to Z8624bsr slognp1 # LOG1P(Z)8625add.l &0xc,%sp # clear Z from stack86268627mov.l (%sp)+,%d0 # fetch old prec,mode8628fmov.l %d0,%fpcr # load it8629mov.b &FMUL_OP,%d1 # last inst is MUL8630fmul.s (%sp)+,%fp08631bra t_catch86328633ATANHBIG:8634fabs.x (%a0),%fp0 # |X|8635fcmp.s %fp0,&0x3F8000008636fbgt t_operr8637bra t_dz86388639global satanhd8640#--ATANH(X) = X FOR DENORMALIZED X8641satanhd:8642bra t_extdnrm86438644#########################################################################8645# slog10(): computes the base-10 logarithm of a normalized input #8646# slog10d(): computes the base-10 logarithm of a denormalized input #8647# slog2(): computes the base-2 logarithm of a normalized input #8648# slog2d(): computes the base-2 logarithm of a denormalized input #8649# #8650# INPUT *************************************************************** #8651# a0 = pointer to extended precision input #8652# d0 = round precision,mode #8653# #8654# OUTPUT ************************************************************** #8655# fp0 = log_10(X) or log_2(X) #8656# #8657# ACCURACY and MONOTONICITY ******************************************* #8658# The returned result is within 1.7 ulps in 64 significant bit, #8659# i.e. within 0.5003 ulp to 53 bits if the result is subsequently #8660# rounded to double precision. The result is provably monotonic #8661# in double precision. #8662# #8663# ALGORITHM *********************************************************** #8664# #8665# slog10d: #8666# #8667# Step 0. If X < 0, create a NaN and raise the invalid operation #8668# flag. Otherwise, save FPCR in D1; set FpCR to default. #8669# Notes: Default means round-to-nearest mode, no floating-point #8670# traps, and precision control = double extended. #8671# #8672# Step 1. Call slognd to obtain Y = log(X), the natural log of X. #8673# Notes: Even if X is denormalized, log(X) is always normalized. #8674# #8675# Step 2. Compute log_10(X) = log(X) * (1/log(10)). #8676# 2.1 Restore the user FPCR #8677# 2.2 Return ans := Y * INV_L10. #8678# #8679# slog10: #8680# #8681# Step 0. If X < 0, create a NaN and raise the invalid operation #8682# flag. Otherwise, save FPCR in D1; set FpCR to default. #8683# Notes: Default means round-to-nearest mode, no floating-point #8684# traps, and precision control = double extended. #8685# #8686# Step 1. Call sLogN to obtain Y = log(X), the natural log of X. #8687# #8688# Step 2. Compute log_10(X) = log(X) * (1/log(10)). #8689# 2.1 Restore the user FPCR #8690# 2.2 Return ans := Y * INV_L10. #8691# #8692# sLog2d: #8693# #8694# Step 0. If X < 0, create a NaN and raise the invalid operation #8695# flag. Otherwise, save FPCR in D1; set FpCR to default. #8696# Notes: Default means round-to-nearest mode, no floating-point #8697# traps, and precision control = double extended. #8698# #8699# Step 1. Call slognd to obtain Y = log(X), the natural log of X. #8700# Notes: Even if X is denormalized, log(X) is always normalized. #8701# #8702# Step 2. Compute log_10(X) = log(X) * (1/log(2)). #8703# 2.1 Restore the user FPCR #8704# 2.2 Return ans := Y * INV_L2. #8705# #8706# sLog2: #8707# #8708# Step 0. If X < 0, create a NaN and raise the invalid operation #8709# flag. Otherwise, save FPCR in D1; set FpCR to default. #8710# Notes: Default means round-to-nearest mode, no floating-point #8711# traps, and precision control = double extended. #8712# #8713# Step 1. If X is not an integer power of two, i.e., X != 2^k, #8714# go to Step 3. #8715# #8716# Step 2. Return k. #8717# 2.1 Get integer k, X = 2^k. #8718# 2.2 Restore the user FPCR. #8719# 2.3 Return ans := convert-to-double-extended(k). #8720# #8721# Step 3. Call sLogN to obtain Y = log(X), the natural log of X. #8722# #8723# Step 4. Compute log_2(X) = log(X) * (1/log(2)). #8724# 4.1 Restore the user FPCR #8725# 4.2 Return ans := Y * INV_L2. #8726# #8727#########################################################################87288729INV_L10:8730long 0x3FFD0000,0xDE5BD8A9,0x37287195,0x0000000087318732INV_L2:8733long 0x3FFF0000,0xB8AA3B29,0x5C17F0BC,0x0000000087348735global slog108736#--entry point for Log10(X), X is normalized8737slog10:8738fmov.b &0x1,%fp08739fcmp.x %fp0,(%a0) # if operand == 1,8740fbeq.l ld_pzero # return an EXACT zero87418742mov.l (%a0),%d18743blt.w invalid8744mov.l %d0,-(%sp)8745clr.l %d08746bsr slogn # log(X), X normal.8747fmov.l (%sp)+,%fpcr8748fmul.x INV_L10(%pc),%fp08749bra t_inx287508751global slog10d8752#--entry point for Log10(X), X is denormalized8753slog10d:8754mov.l (%a0),%d18755blt.w invalid8756mov.l %d0,-(%sp)8757clr.l %d08758bsr slognd # log(X), X denorm.8759fmov.l (%sp)+,%fpcr8760fmul.x INV_L10(%pc),%fp08761bra t_minx287628763global slog28764#--entry point for Log2(X), X is normalized8765slog2:8766mov.l (%a0),%d18767blt.w invalid87688769mov.l 8(%a0),%d18770bne.b continue # X is not 2^k87718772mov.l 4(%a0),%d18773and.l &0x7FFFFFFF,%d18774bne.b continue87758776#--X = 2^k.8777mov.w (%a0),%d18778and.l &0x00007FFF,%d18779sub.l &0x3FFF,%d18780beq.l ld_pzero8781fmov.l %d0,%fpcr8782fmov.l %d1,%fp08783bra t_inx287848785continue:8786mov.l %d0,-(%sp)8787clr.l %d08788bsr slogn # log(X), X normal.8789fmov.l (%sp)+,%fpcr8790fmul.x INV_L2(%pc),%fp08791bra t_inx287928793invalid:8794bra t_operr87958796global slog2d8797#--entry point for Log2(X), X is denormalized8798slog2d:8799mov.l (%a0),%d18800blt.w invalid8801mov.l %d0,-(%sp)8802clr.l %d08803bsr slognd # log(X), X denorm.8804fmov.l (%sp)+,%fpcr8805fmul.x INV_L2(%pc),%fp08806bra t_minx288078808#########################################################################8809# stwotox(): computes 2**X for a normalized input #8810# stwotoxd(): computes 2**X for a denormalized input #8811# stentox(): computes 10**X for a normalized input #8812# stentoxd(): computes 10**X for a denormalized input #8813# #8814# INPUT *************************************************************** #8815# a0 = pointer to extended precision input #8816# d0 = round precision,mode #8817# #8818# OUTPUT ************************************************************** #8819# fp0 = 2**X or 10**X #8820# #8821# ACCURACY and MONOTONICITY ******************************************* #8822# The returned result is within 2 ulps in 64 significant bit, #8823# i.e. within 0.5001 ulp to 53 bits if the result is subsequently #8824# rounded to double precision. The result is provably monotonic #8825# in double precision. #8826# #8827# ALGORITHM *********************************************************** #8828# #8829# twotox #8830# 1. If |X| > 16480, go to ExpBig. #8831# #8832# 2. If |X| < 2**(-70), go to ExpSm. #8833# #8834# 3. Decompose X as X = N/64 + r where |r| <= 1/128. Furthermore #8835# decompose N as #8836# N = 64(M + M') + j, j = 0,1,2,...,63. #8837# #8838# 4. Overwrite r := r * log2. Then #8839# 2**X = 2**(M') * 2**(M) * 2**(j/64) * exp(r). #8840# Go to expr to compute that expression. #8841# #8842# tentox #8843# 1. If |X| > 16480*log_10(2) (base 10 log of 2), go to ExpBig. #8844# #8845# 2. If |X| < 2**(-70), go to ExpSm. #8846# #8847# 3. Set y := X*log_2(10)*64 (base 2 log of 10). Set #8848# N := round-to-int(y). Decompose N as #8849# N = 64(M + M') + j, j = 0,1,2,...,63. #8850# #8851# 4. Define r as #8852# r := ((X - N*L1)-N*L2) * L10 #8853# where L1, L2 are the leading and trailing parts of #8854# log_10(2)/64 and L10 is the natural log of 10. Then #8855# 10**X = 2**(M') * 2**(M) * 2**(j/64) * exp(r). #8856# Go to expr to compute that expression. #8857# #8858# expr #8859# 1. Fetch 2**(j/64) from table as Fact1 and Fact2. #8860# #8861# 2. Overwrite Fact1 and Fact2 by #8862# Fact1 := 2**(M) * Fact1 #8863# Fact2 := 2**(M) * Fact2 #8864# Thus Fact1 + Fact2 = 2**(M) * 2**(j/64). #8865# #8866# 3. Calculate P where 1 + P approximates exp(r): #8867# P = r + r*r*(A1+r*(A2+...+r*A5)). #8868# #8869# 4. Let AdjFact := 2**(M'). Return #8870# AdjFact * ( Fact1 + ((Fact1*P) + Fact2) ). #8871# Exit. #8872# #8873# ExpBig #8874# 1. Generate overflow by Huge * Huge if X > 0; otherwise, #8875# generate underflow by Tiny * Tiny. #8876# #8877# ExpSm #8878# 1. Return 1 + X. #8879# #8880#########################################################################88818882L2TEN64:8883long 0x406A934F,0x0979A371 # 64LOG10/LOG28884L10TWO1:8885long 0x3F734413,0x509F8000 # LOG2/64LOG1088868887L10TWO2:8888long 0xBFCD0000,0xC0219DC1,0xDA994FD2,0x0000000088898890LOG10: long 0x40000000,0x935D8DDD,0xAAA8AC17,0x0000000088918892LOG2: long 0x3FFE0000,0xB17217F7,0xD1CF79AC,0x0000000088938894EXPA5: long 0x3F56C16D,0x6F7BD0B28895EXPA4: long 0x3F811112,0x302C712C8896EXPA3: long 0x3FA55555,0x55554CC18897EXPA2: long 0x3FC55555,0x55554A548898EXPA1: long 0x3FE00000,0x00000000,0x00000000,0x0000000088998900TEXPTBL:8901long 0x3FFF0000,0x80000000,0x00000000,0x3F7380008902long 0x3FFF0000,0x8164D1F3,0xBC030773,0x3FBEF7CA8903long 0x3FFF0000,0x82CD8698,0xAC2BA1D7,0x3FBDF8A98904long 0x3FFF0000,0x843A28C3,0xACDE4046,0x3FBCD7C98905long 0x3FFF0000,0x85AAC367,0xCC487B15,0xBFBDE8DA8906long 0x3FFF0000,0x871F6196,0x9E8D1010,0x3FBDE85C8907long 0x3FFF0000,0x88980E80,0x92DA8527,0x3FBEBBF18908long 0x3FFF0000,0x8A14D575,0x496EFD9A,0x3FBB80CA8909long 0x3FFF0000,0x8B95C1E3,0xEA8BD6E7,0xBFBA83738910long 0x3FFF0000,0x8D1ADF5B,0x7E5BA9E6,0xBFBE96708911long 0x3FFF0000,0x8EA4398B,0x45CD53C0,0x3FBDB7008912long 0x3FFF0000,0x9031DC43,0x1466B1DC,0x3FBEEEB08913long 0x3FFF0000,0x91C3D373,0xAB11C336,0x3FBBFD6D8914long 0x3FFF0000,0x935A2B2F,0x13E6E92C,0xBFBDB3198915long 0x3FFF0000,0x94F4EFA8,0xFEF70961,0x3FBDBA2B8916long 0x3FFF0000,0x96942D37,0x20185A00,0x3FBE91D58917long 0x3FFF0000,0x9837F051,0x8DB8A96F,0x3FBE8D5A8918long 0x3FFF0000,0x99E04593,0x20B7FA65,0xBFBCDE7B8919long 0x3FFF0000,0x9B8D39B9,0xD54E5539,0xBFBEBAAF8920long 0x3FFF0000,0x9D3ED9A7,0x2CFFB751,0xBFBD86DA8921long 0x3FFF0000,0x9EF53260,0x91A111AE,0xBFBEBEDD8922long 0x3FFF0000,0xA0B0510F,0xB9714FC2,0x3FBCC96E8923long 0x3FFF0000,0xA2704303,0x0C496819,0xBFBEC90B8924long 0x3FFF0000,0xA43515AE,0x09E6809E,0x3FBBD1DB8925long 0x3FFF0000,0xA5FED6A9,0xB15138EA,0x3FBCE5EB8926long 0x3FFF0000,0xA7CD93B4,0xE965356A,0xBFBEC2748927long 0x3FFF0000,0xA9A15AB4,0xEA7C0EF8,0x3FBEA83C8928long 0x3FFF0000,0xAB7A39B5,0xA93ED337,0x3FBECB008929long 0x3FFF0000,0xAD583EEA,0x42A14AC6,0x3FBE93018930long 0x3FFF0000,0xAF3B78AD,0x690A4375,0xBFBD83678931long 0x3FFF0000,0xB123F581,0xD2AC2590,0xBFBEF05F8932long 0x3FFF0000,0xB311C412,0xA9112489,0x3FBDFB3C8933long 0x3FFF0000,0xB504F333,0xF9DE6484,0x3FBEB2FB8934long 0x3FFF0000,0xB6FD91E3,0x28D17791,0x3FBAE2CB8935long 0x3FFF0000,0xB8FBAF47,0x62FB9EE9,0x3FBCDC3C8936long 0x3FFF0000,0xBAFF5AB2,0x133E45FB,0x3FBEE9AA8937long 0x3FFF0000,0xBD08A39F,0x580C36BF,0xBFBEAEFD8938long 0x3FFF0000,0xBF1799B6,0x7A731083,0xBFBCBF518939long 0x3FFF0000,0xC12C4CCA,0x66709456,0x3FBEF88A8940long 0x3FFF0000,0xC346CCDA,0x24976407,0x3FBD83B28941long 0x3FFF0000,0xC5672A11,0x5506DADD,0x3FBDF8AB8942long 0x3FFF0000,0xC78D74C8,0xABB9B15D,0xBFBDFB178943long 0x3FFF0000,0xC9B9BD86,0x6E2F27A3,0xBFBEFE3C8944long 0x3FFF0000,0xCBEC14FE,0xF2727C5D,0xBFBBB6F88945long 0x3FFF0000,0xCE248C15,0x1F8480E4,0xBFBCEE538946long 0x3FFF0000,0xD06333DA,0xEF2B2595,0xBFBDA4AE8947long 0x3FFF0000,0xD2A81D91,0xF12AE45A,0x3FBC91248948long 0x3FFF0000,0xD4F35AAB,0xCFEDFA1F,0x3FBEB2438949long 0x3FFF0000,0xD744FCCA,0xD69D6AF4,0x3FBDE69A8950long 0x3FFF0000,0xD99D15C2,0x78AFD7B6,0xBFB8BC618951long 0x3FFF0000,0xDBFBB797,0xDAF23755,0x3FBDF6108952long 0x3FFF0000,0xDE60F482,0x5E0E9124,0xBFBD8BE18953long 0x3FFF0000,0xE0CCDEEC,0x2A94E111,0x3FBACB128954long 0x3FFF0000,0xE33F8972,0xBE8A5A51,0x3FBB9BFE8955long 0x3FFF0000,0xE5B906E7,0x7C8348A8,0x3FBCF2F48956long 0x3FFF0000,0xE8396A50,0x3C4BDC68,0x3FBEF22F8957long 0x3FFF0000,0xEAC0C6E7,0xDD24392F,0xBFBDBF4A8958long 0x3FFF0000,0xED4F301E,0xD9942B84,0x3FBEC01A8959long 0x3FFF0000,0xEFE4B99B,0xDCDAF5CB,0x3FBE8CAC8960long 0x3FFF0000,0xF281773C,0x59FFB13A,0xBFBCBB3F8961long 0x3FFF0000,0xF5257D15,0x2486CC2C,0x3FBEF73A8962long 0x3FFF0000,0xF7D0DF73,0x0AD13BB9,0xBFB8B7958963long 0x3FFF0000,0xFA83B2DB,0x722A033A,0x3FBEF84B8964long 0x3FFF0000,0xFD3E0C0C,0xF486C175,0xBFBEF58189658966set INT,L_SCR189678968set X,FP_SCR08969set XDCARE,X+28970set XFRAC,X+489718972set ADJFACT,FP_SCR089738974set FACT1,FP_SCR08975set FACT1HI,FACT1+48976set FACT1LOW,FACT1+889778978set FACT2,FP_SCR18979set FACT2HI,FACT2+48980set FACT2LOW,FACT2+889818982global stwotox8983#--ENTRY POINT FOR 2**(X), HERE X IS FINITE, NON-ZERO, AND NOT NAN'S8984stwotox:8985fmovm.x (%a0),&0x80 # LOAD INPUT89868987mov.l (%a0),%d18988mov.w 4(%a0),%d18989fmov.x %fp0,X(%a6)8990and.l &0x7FFFFFFF,%d189918992cmp.l %d1,&0x3FB98000 # |X| >= 2**(-70)?8993bge.b TWOOK18994bra.w EXPBORS89958996TWOOK1:8997cmp.l %d1,&0x400D80C0 # |X| > 16480?8998ble.b TWOMAIN8999bra.w EXPBORS90009001TWOMAIN:9002#--USUAL CASE, 2^(-70) <= |X| <= 1648090039004fmov.x %fp0,%fp19005fmul.s &0x42800000,%fp1 # 64 * X9006fmov.l %fp1,INT(%a6) # N = ROUND-TO-INT(64 X)9007mov.l %d2,-(%sp)9008lea TEXPTBL(%pc),%a1 # LOAD ADDRESS OF TABLE OF 2^(J/64)9009fmov.l INT(%a6),%fp1 # N --> FLOATING FMT9010mov.l INT(%a6),%d19011mov.l %d1,%d29012and.l &0x3F,%d1 # D0 IS J9013asl.l &4,%d1 # DISPLACEMENT FOR 2^(J/64)9014add.l %d1,%a1 # ADDRESS FOR 2^(J/64)9015asr.l &6,%d2 # d2 IS L, N = 64L + J9016mov.l %d2,%d19017asr.l &1,%d1 # D0 IS M9018sub.l %d1,%d2 # d2 IS M', N = 64(M+M') + J9019add.l &0x3FFF,%d290209021#--SUMMARY: a1 IS ADDRESS FOR THE LEADING PORTION OF 2^(J/64),9022#--D0 IS M WHERE N = 64(M+M') + J. NOTE THAT |M| <= 16140 BY DESIGN.9023#--ADJFACT = 2^(M').9024#--REGISTERS SAVED SO FAR ARE (IN ORDER) FPCR, D0, FP1, a1, AND FP2.90259026fmovm.x &0x0c,-(%sp) # save fp2/fp390279028fmul.s &0x3C800000,%fp1 # (1/64)*N9029mov.l (%a1)+,FACT1(%a6)9030mov.l (%a1)+,FACT1HI(%a6)9031mov.l (%a1)+,FACT1LOW(%a6)9032mov.w (%a1)+,FACT2(%a6)90339034fsub.x %fp1,%fp0 # X - (1/64)*INT(64 X)90359036mov.w (%a1)+,FACT2HI(%a6)9037clr.w FACT2HI+2(%a6)9038clr.l FACT2LOW(%a6)9039add.w %d1,FACT1(%a6)9040fmul.x LOG2(%pc),%fp0 # FP0 IS R9041add.w %d1,FACT2(%a6)90429043bra.w expr90449045EXPBORS:9046#--FPCR, D0 SAVED9047cmp.l %d1,&0x3FFF80009048bgt.b TEXPBIG90499050#--|X| IS SMALL, RETURN 1 + X90519052fmov.l %d0,%fpcr # restore users round prec,mode9053fadd.s &0x3F800000,%fp0 # RETURN 1 + X9054bra t_pinx290559056TEXPBIG:9057#--|X| IS LARGE, GENERATE OVERFLOW IF X > 0; ELSE GENERATE UNDERFLOW9058#--REGISTERS SAVE SO FAR ARE FPCR AND D09059mov.l X(%a6),%d19060cmp.l %d1,&09061blt.b EXPNEG90629063bra t_ovfl2 # t_ovfl expects positive value90649065EXPNEG:9066bra t_unfl2 # t_unfl expects positive value90679068global stwotoxd9069stwotoxd:9070#--ENTRY POINT FOR 2**(X) FOR DENORMALIZED ARGUMENT90719072fmov.l %d0,%fpcr # set user's rounding mode/precision9073fmov.s &0x3F800000,%fp0 # RETURN 1 + X9074mov.l (%a0),%d19075or.l &0x00800001,%d19076fadd.s %d1,%fp09077bra t_pinx290789079global stentox9080#--ENTRY POINT FOR 10**(X), HERE X IS FINITE, NON-ZERO, AND NOT NAN'S9081stentox:9082fmovm.x (%a0),&0x80 # LOAD INPUT90839084mov.l (%a0),%d19085mov.w 4(%a0),%d19086fmov.x %fp0,X(%a6)9087and.l &0x7FFFFFFF,%d190889089cmp.l %d1,&0x3FB98000 # |X| >= 2**(-70)?9090bge.b TENOK19091bra.w EXPBORS90929093TENOK1:9094cmp.l %d1,&0x400B9B07 # |X| <= 16480*log2/log10 ?9095ble.b TENMAIN9096bra.w EXPBORS90979098TENMAIN:9099#--USUAL CASE, 2^(-70) <= |X| <= 16480 LOG 2 / LOG 1091009101fmov.x %fp0,%fp19102fmul.d L2TEN64(%pc),%fp1 # X*64*LOG10/LOG29103fmov.l %fp1,INT(%a6) # N=INT(X*64*LOG10/LOG2)9104mov.l %d2,-(%sp)9105lea TEXPTBL(%pc),%a1 # LOAD ADDRESS OF TABLE OF 2^(J/64)9106fmov.l INT(%a6),%fp1 # N --> FLOATING FMT9107mov.l INT(%a6),%d19108mov.l %d1,%d29109and.l &0x3F,%d1 # D0 IS J9110asl.l &4,%d1 # DISPLACEMENT FOR 2^(J/64)9111add.l %d1,%a1 # ADDRESS FOR 2^(J/64)9112asr.l &6,%d2 # d2 IS L, N = 64L + J9113mov.l %d2,%d19114asr.l &1,%d1 # D0 IS M9115sub.l %d1,%d2 # d2 IS M', N = 64(M+M') + J9116add.l &0x3FFF,%d291179118#--SUMMARY: a1 IS ADDRESS FOR THE LEADING PORTION OF 2^(J/64),9119#--D0 IS M WHERE N = 64(M+M') + J. NOTE THAT |M| <= 16140 BY DESIGN.9120#--ADJFACT = 2^(M').9121#--REGISTERS SAVED SO FAR ARE (IN ORDER) FPCR, D0, FP1, a1, AND FP2.9122fmovm.x &0x0c,-(%sp) # save fp2/fp391239124fmov.x %fp1,%fp291259126fmul.d L10TWO1(%pc),%fp1 # N*(LOG2/64LOG10)_LEAD9127mov.l (%a1)+,FACT1(%a6)91289129fmul.x L10TWO2(%pc),%fp2 # N*(LOG2/64LOG10)_TRAIL91309131mov.l (%a1)+,FACT1HI(%a6)9132mov.l (%a1)+,FACT1LOW(%a6)9133fsub.x %fp1,%fp0 # X - N L_LEAD9134mov.w (%a1)+,FACT2(%a6)91359136fsub.x %fp2,%fp0 # X - N L_TRAIL91379138mov.w (%a1)+,FACT2HI(%a6)9139clr.w FACT2HI+2(%a6)9140clr.l FACT2LOW(%a6)91419142fmul.x LOG10(%pc),%fp0 # FP0 IS R9143add.w %d1,FACT1(%a6)9144add.w %d1,FACT2(%a6)91459146expr:9147#--FPCR, FP2, FP3 ARE SAVED IN ORDER AS SHOWN.9148#--ADJFACT CONTAINS 2**(M'), FACT1 + FACT2 = 2**(M) * 2**(J/64).9149#--FP0 IS R. THE FOLLOWING CODE COMPUTES9150#-- 2**(M'+M) * 2**(J/64) * EXP(R)91519152fmov.x %fp0,%fp19153fmul.x %fp1,%fp1 # FP1 IS S = R*R91549155fmov.d EXPA5(%pc),%fp2 # FP2 IS A59156fmov.d EXPA4(%pc),%fp3 # FP3 IS A491579158fmul.x %fp1,%fp2 # FP2 IS S*A59159fmul.x %fp1,%fp3 # FP3 IS S*A491609161fadd.d EXPA3(%pc),%fp2 # FP2 IS A3+S*A59162fadd.d EXPA2(%pc),%fp3 # FP3 IS A2+S*A491639164fmul.x %fp1,%fp2 # FP2 IS S*(A3+S*A5)9165fmul.x %fp1,%fp3 # FP3 IS S*(A2+S*A4)91669167fadd.d EXPA1(%pc),%fp2 # FP2 IS A1+S*(A3+S*A5)9168fmul.x %fp0,%fp3 # FP3 IS R*S*(A2+S*A4)91699170fmul.x %fp1,%fp2 # FP2 IS S*(A1+S*(A3+S*A5))9171fadd.x %fp3,%fp0 # FP0 IS R+R*S*(A2+S*A4)9172fadd.x %fp2,%fp0 # FP0 IS EXP(R) - 191739174fmovm.x (%sp)+,&0x30 # restore fp2/fp391759176#--FINAL RECONSTRUCTION PROCESS9177#--EXP(X) = 2^M*2^(J/64) + 2^M*2^(J/64)*(EXP(R)-1) - (1 OR 0)91789179fmul.x FACT1(%a6),%fp09180fadd.x FACT2(%a6),%fp09181fadd.x FACT1(%a6),%fp091829183fmov.l %d0,%fpcr # restore users round prec,mode9184mov.w %d2,ADJFACT(%a6) # INSERT EXPONENT9185mov.l (%sp)+,%d29186mov.l &0x80000000,ADJFACT+4(%a6)9187clr.l ADJFACT+8(%a6)9188mov.b &FMUL_OP,%d1 # last inst is MUL9189fmul.x ADJFACT(%a6),%fp0 # FINAL ADJUSTMENT9190bra t_catch91919192global stentoxd9193stentoxd:9194#--ENTRY POINT FOR 10**(X) FOR DENORMALIZED ARGUMENT91959196fmov.l %d0,%fpcr # set user's rounding mode/precision9197fmov.s &0x3F800000,%fp0 # RETURN 1 + X9198mov.l (%a0),%d19199or.l &0x00800001,%d19200fadd.s %d1,%fp09201bra t_pinx292029203#########################################################################9204# sscale(): computes the destination operand scaled by the source #9205# operand. If the absoulute value of the source operand is #9206# >= 2^14, an overflow or underflow is returned. #9207# #9208# INPUT *************************************************************** #9209# a0 = pointer to double-extended source operand X #9210# a1 = pointer to double-extended destination operand Y #9211# #9212# OUTPUT ************************************************************** #9213# fp0 = scale(X,Y) #9214# #9215#########################################################################92169217set SIGN, L_SCR192189219global sscale9220sscale:9221mov.l %d0,-(%sp) # store off ctrl bits for now92229223mov.w DST_EX(%a1),%d1 # get dst exponent9224smi.b SIGN(%a6) # use SIGN to hold dst sign9225andi.l &0x00007fff,%d1 # strip sign from dst exp92269227mov.w SRC_EX(%a0),%d0 # check src bounds9228andi.w &0x7fff,%d0 # clr src sign bit9229cmpi.w %d0,&0x3fff # is src ~ ZERO?9230blt.w src_small # yes9231cmpi.w %d0,&0x400c # no; is src too big?9232bgt.w src_out # yes92339234#9235# Source is within 2^14 range.9236#9237src_ok:9238fintrz.x SRC(%a0),%fp0 # calc int of src9239fmov.l %fp0,%d0 # int src to d09240# don't want any accrued bits from the fintrz showing up later since9241# we may need to read the fpsr for the last fp op in t_catch2().9242fmov.l &0x0,%fpsr92439244tst.b DST_HI(%a1) # is dst denormalized?9245bmi.b sok_norm92469247# the dst is a DENORM. normalize the DENORM and add the adjustment to9248# the src value. then, jump to the norm part of the routine.9249sok_dnrm:9250mov.l %d0,-(%sp) # save src for now92519252mov.w DST_EX(%a1),FP_SCR0_EX(%a6) # make a copy9253mov.l DST_HI(%a1),FP_SCR0_HI(%a6)9254mov.l DST_LO(%a1),FP_SCR0_LO(%a6)92559256lea FP_SCR0(%a6),%a0 # pass ptr to DENORM9257bsr.l norm # normalize the DENORM9258neg.l %d09259add.l (%sp)+,%d0 # add adjustment to src92609261fmovm.x FP_SCR0(%a6),&0x80 # load normalized DENORM92629263cmpi.w %d0,&-0x3fff # is the shft amt really low?9264bge.b sok_norm2 # thank goodness no92659266# the multiply factor that we're trying to create should be a denorm9267# for the multiply to work. therefore, we're going to actually do a9268# multiply with a denorm which will cause an unimplemented data type9269# exception to be put into the machine which will be caught and corrected9270# later. we don't do this with the DENORMs above because this method9271# is slower. but, don't fret, I don't see it being used much either.9272fmov.l (%sp)+,%fpcr # restore user fpcr9273mov.l &0x80000000,%d1 # load normalized mantissa9274subi.l &-0x3fff,%d0 # how many should we shift?9275neg.l %d0 # make it positive9276cmpi.b %d0,&0x20 # is it > 32?9277bge.b sok_dnrm_32 # yes9278lsr.l %d0,%d1 # no; bit stays in upper lw9279clr.l -(%sp) # insert zero low mantissa9280mov.l %d1,-(%sp) # insert new high mantissa9281clr.l -(%sp) # make zero exponent9282bra.b sok_norm_cont9283sok_dnrm_32:9284subi.b &0x20,%d0 # get shift count9285lsr.l %d0,%d1 # make low mantissa longword9286mov.l %d1,-(%sp) # insert new low mantissa9287clr.l -(%sp) # insert zero high mantissa9288clr.l -(%sp) # make zero exponent9289bra.b sok_norm_cont92909291# the src will force the dst to a DENORM value or worse. so, let's9292# create an fp multiply that will create the result.9293sok_norm:9294fmovm.x DST(%a1),&0x80 # load fp0 with normalized src9295sok_norm2:9296fmov.l (%sp)+,%fpcr # restore user fpcr92979298addi.w &0x3fff,%d0 # turn src amt into exp value9299swap %d0 # put exponent in high word9300clr.l -(%sp) # insert new exponent9301mov.l &0x80000000,-(%sp) # insert new high mantissa9302mov.l %d0,-(%sp) # insert new lo mantissa93039304sok_norm_cont:9305fmov.l %fpcr,%d0 # d0 needs fpcr for t_catch29306mov.b &FMUL_OP,%d1 # last inst is MUL9307fmul.x (%sp)+,%fp0 # do the multiply9308bra t_catch2 # catch any exceptions93099310#9311# Source is outside of 2^14 range. Test the sign and branch9312# to the appropriate exception handler.9313#9314src_out:9315mov.l (%sp)+,%d0 # restore ctrl bits9316exg %a0,%a1 # swap src,dst ptrs9317tst.b SRC_EX(%a1) # is src negative?9318bmi t_unfl # yes; underflow9319bra t_ovfl_sc # no; overflow93209321#9322# The source input is below 1, so we check for denormalized numbers9323# and set unfl.9324#9325src_small:9326tst.b DST_HI(%a1) # is dst denormalized?9327bpl.b ssmall_done # yes93289329mov.l (%sp)+,%d09330fmov.l %d0,%fpcr # no; load control bits9331mov.b &FMOV_OP,%d1 # last inst is MOVE9332fmov.x DST(%a1),%fp0 # simply return dest9333bra t_catch29334ssmall_done:9335mov.l (%sp)+,%d0 # load control bits into d19336mov.l %a1,%a0 # pass ptr to dst9337bra t_resdnrm93389339#########################################################################9340# smod(): computes the fp MOD of the input values X,Y. #9341# srem(): computes the fp (IEEE) REM of the input values X,Y. #9342# #9343# INPUT *************************************************************** #9344# a0 = pointer to extended precision input X #9345# a1 = pointer to extended precision input Y #9346# d0 = round precision,mode #9347# #9348# The input operands X and Y can be either normalized or #9349# denormalized. #9350# #9351# OUTPUT ************************************************************** #9352# fp0 = FREM(X,Y) or FMOD(X,Y) #9353# #9354# ALGORITHM *********************************************************** #9355# #9356# Step 1. Save and strip signs of X and Y: signX := sign(X), #9357# signY := sign(Y), X := |X|, Y := |Y|, #9358# signQ := signX EOR signY. Record whether MOD or REM #9359# is requested. #9360# #9361# Step 2. Set L := expo(X)-expo(Y), k := 0, Q := 0. #9362# If (L < 0) then #9363# R := X, go to Step 4. #9364# else #9365# R := 2^(-L)X, j := L. #9366# endif #9367# #9368# Step 3. Perform MOD(X,Y) #9369# 3.1 If R = Y, go to Step 9. #9370# 3.2 If R > Y, then { R := R - Y, Q := Q + 1} #9371# 3.3 If j = 0, go to Step 4. #9372# 3.4 k := k + 1, j := j - 1, Q := 2Q, R := 2R. Go to #9373# Step 3.1. #9374# #9375# Step 4. At this point, R = X - QY = MOD(X,Y). Set #9376# Last_Subtract := false (used in Step 7 below). If #9377# MOD is requested, go to Step 6. #9378# #9379# Step 5. R = MOD(X,Y), but REM(X,Y) is requested. #9380# 5.1 If R < Y/2, then R = MOD(X,Y) = REM(X,Y). Go to #9381# Step 6. #9382# 5.2 If R > Y/2, then { set Last_Subtract := true, #9383# Q := Q + 1, Y := signY*Y }. Go to Step 6. #9384# 5.3 This is the tricky case of R = Y/2. If Q is odd, #9385# then { Q := Q + 1, signX := -signX }. #9386# #9387# Step 6. R := signX*R. #9388# #9389# Step 7. If Last_Subtract = true, R := R - Y. #9390# #9391# Step 8. Return signQ, last 7 bits of Q, and R as required. #9392# #9393# Step 9. At this point, R = 2^(-j)*X - Q Y = Y. Thus, #9394# X = 2^(j)*(Q+1)Y. set Q := 2^(j)*(Q+1), #9395# R := 0. Return signQ, last 7 bits of Q, and R. #9396# #9397#########################################################################93989399set Mod_Flag,L_SCR39400set Sc_Flag,L_SCR3+194019402set SignY,L_SCR29403set SignX,L_SCR2+29404set SignQ,L_SCR3+294059406set Y,FP_SCR09407set Y_Hi,Y+49408set Y_Lo,Y+894099410set R,FP_SCR19411set R_Hi,R+49412set R_Lo,R+894139414Scale:9415long 0x00010000,0x80000000,0x00000000,0x0000000094169417global smod9418smod:9419clr.b FPSR_QBYTE(%a6)9420mov.l %d0,-(%sp) # save ctrl bits9421clr.b Mod_Flag(%a6)9422bra.b Mod_Rem94239424global srem9425srem:9426clr.b FPSR_QBYTE(%a6)9427mov.l %d0,-(%sp) # save ctrl bits9428mov.b &0x1,Mod_Flag(%a6)94299430Mod_Rem:9431#..Save sign of X and Y9432movm.l &0x3f00,-(%sp) # save data registers9433mov.w SRC_EX(%a0),%d39434mov.w %d3,SignY(%a6)9435and.l &0x00007FFF,%d3 # Y := |Y|94369437#9438mov.l SRC_HI(%a0),%d49439mov.l SRC_LO(%a0),%d5 # (D3,D4,D5) is |Y|94409441tst.l %d39442bne.b Y_Normal94439444mov.l &0x00003FFE,%d3 # $3FFD + 19445tst.l %d49446bne.b HiY_not094479448HiY_0:9449mov.l %d5,%d49450clr.l %d59451sub.l &32,%d39452clr.l %d69453bfffo %d4{&0:&32},%d69454lsl.l %d6,%d49455sub.l %d6,%d3 # (D3,D4,D5) is normalized9456# ...with bias $7FFD9457bra.b Chk_X94589459HiY_not0:9460clr.l %d69461bfffo %d4{&0:&32},%d69462sub.l %d6,%d39463lsl.l %d6,%d49464mov.l %d5,%d7 # a copy of D59465lsl.l %d6,%d59466neg.l %d69467add.l &32,%d69468lsr.l %d6,%d79469or.l %d7,%d4 # (D3,D4,D5) normalized9470# ...with bias $7FFD9471bra.b Chk_X94729473Y_Normal:9474add.l &0x00003FFE,%d3 # (D3,D4,D5) normalized9475# ...with bias $7FFD94769477Chk_X:9478mov.w DST_EX(%a1),%d09479mov.w %d0,SignX(%a6)9480mov.w SignY(%a6),%d19481eor.l %d0,%d19482and.l &0x00008000,%d19483mov.w %d1,SignQ(%a6) # sign(Q) obtained9484and.l &0x00007FFF,%d09485mov.l DST_HI(%a1),%d19486mov.l DST_LO(%a1),%d2 # (D0,D1,D2) is |X|9487tst.l %d09488bne.b X_Normal9489mov.l &0x00003FFE,%d09490tst.l %d19491bne.b HiX_not094929493HiX_0:9494mov.l %d2,%d19495clr.l %d29496sub.l &32,%d09497clr.l %d69498bfffo %d1{&0:&32},%d69499lsl.l %d6,%d19500sub.l %d6,%d0 # (D0,D1,D2) is normalized9501# ...with bias $7FFD9502bra.b Init95039504HiX_not0:9505clr.l %d69506bfffo %d1{&0:&32},%d69507sub.l %d6,%d09508lsl.l %d6,%d19509mov.l %d2,%d7 # a copy of D29510lsl.l %d6,%d29511neg.l %d69512add.l &32,%d69513lsr.l %d6,%d79514or.l %d7,%d1 # (D0,D1,D2) normalized9515# ...with bias $7FFD9516bra.b Init95179518X_Normal:9519add.l &0x00003FFE,%d0 # (D0,D1,D2) normalized9520# ...with bias $7FFD95219522Init:9523#9524mov.l %d3,L_SCR1(%a6) # save biased exp(Y)9525mov.l %d0,-(%sp) # save biased exp(X)9526sub.l %d3,%d0 # L := expo(X)-expo(Y)95279528clr.l %d6 # D6 := carry <- 09529clr.l %d3 # D3 is Q9530mov.l &0,%a1 # A1 is k; j+k=L, Q=095319532#..(Carry,D1,D2) is R9533tst.l %d09534bge.b Mod_Loop_pre95359536#..expo(X) < expo(Y). Thus X = mod(X,Y)9537#9538mov.l (%sp)+,%d0 # restore d09539bra.w Get_Mod95409541Mod_Loop_pre:9542addq.l &0x4,%sp # erase exp(X)9543#..At this point R = 2^(-L)X; Q = 0; k = 0; and k+j = L9544Mod_Loop:9545tst.l %d6 # test carry bit9546bgt.b R_GT_Y95479548#..At this point carry = 0, R = (D1,D2), Y = (D4,D5)9549cmp.l %d1,%d4 # compare hi(R) and hi(Y)9550bne.b R_NE_Y9551cmp.l %d2,%d5 # compare lo(R) and lo(Y)9552bne.b R_NE_Y95539554#..At this point, R = Y9555bra.w Rem_is_095569557R_NE_Y:9558#..use the borrow of the previous compare9559bcs.b R_LT_Y # borrow is set iff R < Y95609561R_GT_Y:9562#..If Carry is set, then Y < (Carry,D1,D2) < 2Y. Otherwise, Carry = 09563#..and Y < (D1,D2) < 2Y. Either way, perform R - Y9564sub.l %d5,%d2 # lo(R) - lo(Y)9565subx.l %d4,%d1 # hi(R) - hi(Y)9566clr.l %d6 # clear carry9567addq.l &1,%d3 # Q := Q + 195689569R_LT_Y:9570#..At this point, Carry=0, R < Y. R = 2^(k-L)X - QY; k+j = L; j >= 0.9571tst.l %d0 # see if j = 0.9572beq.b PostLoop95739574add.l %d3,%d3 # Q := 2Q9575add.l %d2,%d2 # lo(R) = 2lo(R)9576roxl.l &1,%d1 # hi(R) = 2hi(R) + carry9577scs %d6 # set Carry if 2(R) overflows9578addq.l &1,%a1 # k := k+19579subq.l &1,%d0 # j := j - 19580#..At this point, R=(Carry,D1,D2) = 2^(k-L)X - QY, j+k=L, j >= 0, R < 2Y.95819582bra.b Mod_Loop95839584PostLoop:9585#..k = L, j = 0, Carry = 0, R = (D1,D2) = X - QY, R < Y.95869587#..normalize R.9588mov.l L_SCR1(%a6),%d0 # new biased expo of R9589tst.l %d19590bne.b HiR_not095919592HiR_0:9593mov.l %d2,%d19594clr.l %d29595sub.l &32,%d09596clr.l %d69597bfffo %d1{&0:&32},%d69598lsl.l %d6,%d19599sub.l %d6,%d0 # (D0,D1,D2) is normalized9600# ...with bias $7FFD9601bra.b Get_Mod96029603HiR_not0:9604clr.l %d69605bfffo %d1{&0:&32},%d69606bmi.b Get_Mod # already normalized9607sub.l %d6,%d09608lsl.l %d6,%d19609mov.l %d2,%d7 # a copy of D29610lsl.l %d6,%d29611neg.l %d69612add.l &32,%d69613lsr.l %d6,%d79614or.l %d7,%d1 # (D0,D1,D2) normalized96159616#9617Get_Mod:9618cmp.l %d0,&0x000041FE9619bge.b No_Scale9620Do_Scale:9621mov.w %d0,R(%a6)9622mov.l %d1,R_Hi(%a6)9623mov.l %d2,R_Lo(%a6)9624mov.l L_SCR1(%a6),%d69625mov.w %d6,Y(%a6)9626mov.l %d4,Y_Hi(%a6)9627mov.l %d5,Y_Lo(%a6)9628fmov.x R(%a6),%fp0 # no exception9629mov.b &1,Sc_Flag(%a6)9630bra.b ModOrRem9631No_Scale:9632mov.l %d1,R_Hi(%a6)9633mov.l %d2,R_Lo(%a6)9634sub.l &0x3FFE,%d09635mov.w %d0,R(%a6)9636mov.l L_SCR1(%a6),%d69637sub.l &0x3FFE,%d69638mov.l %d6,L_SCR1(%a6)9639fmov.x R(%a6),%fp09640mov.w %d6,Y(%a6)9641mov.l %d4,Y_Hi(%a6)9642mov.l %d5,Y_Lo(%a6)9643clr.b Sc_Flag(%a6)96449645#9646ModOrRem:9647tst.b Mod_Flag(%a6)9648beq.b Fix_Sign96499650mov.l L_SCR1(%a6),%d6 # new biased expo(Y)9651subq.l &1,%d6 # biased expo(Y/2)9652cmp.l %d0,%d69653blt.b Fix_Sign9654bgt.b Last_Sub96559656cmp.l %d1,%d49657bne.b Not_EQ9658cmp.l %d2,%d59659bne.b Not_EQ9660bra.w Tie_Case96619662Not_EQ:9663bcs.b Fix_Sign96649665Last_Sub:9666#9667fsub.x Y(%a6),%fp0 # no exceptions9668addq.l &1,%d3 # Q := Q + 196699670#9671Fix_Sign:9672#..Get sign of X9673mov.w SignX(%a6),%d69674bge.b Get_Q9675fneg.x %fp096769677#..Get Q9678#9679Get_Q:9680clr.l %d69681mov.w SignQ(%a6),%d6 # D6 is sign(Q)9682mov.l &8,%d79683lsr.l %d7,%d69684and.l &0x0000007F,%d3 # 7 bits of Q9685or.l %d6,%d3 # sign and bits of Q9686# swap %d39687# fmov.l %fpsr,%d69688# and.l &0xFF00FFFF,%d69689# or.l %d3,%d69690# fmov.l %d6,%fpsr # put Q in fpsr9691mov.b %d3,FPSR_QBYTE(%a6) # put Q in fpsr96929693#9694Restore:9695movm.l (%sp)+,&0xfc # {%d2-%d7}9696mov.l (%sp)+,%d09697fmov.l %d0,%fpcr9698tst.b Sc_Flag(%a6)9699beq.b Finish9700mov.b &FMUL_OP,%d1 # last inst is MUL9701fmul.x Scale(%pc),%fp0 # may cause underflow9702bra t_catch29703# the '040 package did this apparently to see if the dst operand for the9704# preceding fmul was a denorm. but, it better not have been since the9705# algorithm just got done playing with fp0 and expected no exceptions9706# as a result. trust me...9707# bra t_avoid_unsupp # check for denorm as a9708# ;result of the scaling97099710Finish:9711mov.b &FMOV_OP,%d1 # last inst is MOVE9712fmov.x %fp0,%fp0 # capture exceptions & round9713bra t_catch297149715Rem_is_0:9716#..R = 2^(-j)X - Q Y = Y, thus R = 0 and quotient = 2^j (Q+1)9717addq.l &1,%d39718cmp.l %d0,&8 # D0 is j9719bge.b Q_Big97209721lsl.l %d0,%d39722bra.b Set_R_097239724Q_Big:9725clr.l %d397269727Set_R_0:9728fmov.s &0x00000000,%fp09729clr.b Sc_Flag(%a6)9730bra.w Fix_Sign97319732Tie_Case:9733#..Check parity of Q9734mov.l %d3,%d69735and.l &0x00000001,%d69736tst.l %d69737beq.w Fix_Sign # Q is even97389739#..Q is odd, Q := Q + 1, signX := -signX9740addq.l &1,%d39741mov.w SignX(%a6),%d69742eor.l &0x00008000,%d69743mov.w %d6,SignX(%a6)9744bra.w Fix_Sign97459746#########################################################################9747# XDEF **************************************************************** #9748# tag(): return the optype of the input ext fp number #9749# #9750# This routine is used by the 060FPLSP. #9751# #9752# XREF **************************************************************** #9753# None #9754# #9755# INPUT *************************************************************** #9756# a0 = pointer to extended precision operand #9757# #9758# OUTPUT ************************************************************** #9759# d0 = value of type tag #9760# one of: NORM, INF, QNAN, SNAN, DENORM, ZERO #9761# #9762# ALGORITHM *********************************************************** #9763# Simply test the exponent, j-bit, and mantissa values to #9764# determine the type of operand. #9765# If it's an unnormalized zero, alter the operand and force it #9766# to be a normal zero. #9767# #9768#########################################################################97699770global tag9771tag:9772mov.w FTEMP_EX(%a0), %d0 # extract exponent9773andi.w &0x7fff, %d0 # strip off sign9774cmpi.w %d0, &0x7fff # is (EXP == MAX)?9775beq.b inf_or_nan_x9776not_inf_or_nan_x:9777btst &0x7,FTEMP_HI(%a0)9778beq.b not_norm_x9779is_norm_x:9780mov.b &NORM, %d09781rts9782not_norm_x:9783tst.w %d0 # is exponent = 0?9784bne.b is_unnorm_x9785not_unnorm_x:9786tst.l FTEMP_HI(%a0)9787bne.b is_denorm_x9788tst.l FTEMP_LO(%a0)9789bne.b is_denorm_x9790is_zero_x:9791mov.b &ZERO, %d09792rts9793is_denorm_x:9794mov.b &DENORM, %d09795rts9796is_unnorm_x:9797bsr.l unnorm_fix # convert to norm,denorm,or zero9798rts9799is_unnorm_reg_x:9800mov.b &UNNORM, %d09801rts9802inf_or_nan_x:9803tst.l FTEMP_LO(%a0)9804bne.b is_nan_x9805mov.l FTEMP_HI(%a0), %d09806and.l &0x7fffffff, %d0 # msb is a don't care!9807bne.b is_nan_x9808is_inf_x:9809mov.b &INF, %d09810rts9811is_nan_x:9812mov.b &QNAN, %d09813rts98149815#############################################################98169817qnan: long 0x7fff0000, 0xffffffff, 0xffffffff98189819#########################################################################9820# XDEF **************************************************************** #9821# t_dz(): Handle 060FPLSP dz exception for "flogn" emulation. #9822# t_dz2(): Handle 060FPLSP dz exception for "fatanh" emulation. #9823# #9824# These rouitnes are used by the 060FPLSP package. #9825# #9826# XREF **************************************************************** #9827# None #9828# #9829# INPUT *************************************************************** #9830# a0 = pointer to extended precision source operand. #9831# #9832# OUTPUT ************************************************************** #9833# fp0 = default DZ result. #9834# #9835# ALGORITHM *********************************************************** #9836# Transcendental emulation for the 060FPLSP has detected that #9837# a DZ exception should occur for the instruction. If DZ is disabled, #9838# return the default result. #9839# If DZ is enabled, the dst operand should be returned unscathed #9840# in fp0 while fp1 is used to create a DZ exception so that the #9841# operating system can log that such an event occurred. #9842# #9843#########################################################################98449845global t_dz9846t_dz:9847tst.b SRC_EX(%a0) # check sign for neg or pos9848bpl.b dz_pinf # branch if pos sign98499850global t_dz29851t_dz2:9852ori.l &dzinf_mask+neg_mask,USER_FPSR(%a6) # set N/I/DZ/ADZ98539854btst &dz_bit,FPCR_ENABLE(%a6)9855bne.b dz_minf_ena98569857# dz is disabled. return a -INF.9858fmov.s &0xff800000,%fp0 # return -INF9859rts98609861# dz is enabled. create a dz exception so the user can record it9862# but use fp1 instead. return the dst operand unscathed in fp0.9863dz_minf_ena:9864fmovm.x EXC_FP0(%a6),&0x80 # return fp0 unscathed9865fmov.l USER_FPCR(%a6),%fpcr9866fmov.s &0xbf800000,%fp1 # load -19867fdiv.s &0x00000000,%fp1 # -1 / 09868rts98699870dz_pinf:9871ori.l &dzinf_mask,USER_FPSR(%a6) # set I/DZ/ADZ98729873btst &dz_bit,FPCR_ENABLE(%a6)9874bne.b dz_pinf_ena98759876# dz is disabled. return a +INF.9877fmov.s &0x7f800000,%fp0 # return +INF9878rts98799880# dz is enabled. create a dz exception so the user can record it9881# but use fp1 instead. return the dst operand unscathed in fp0.9882dz_pinf_ena:9883fmovm.x EXC_FP0(%a6),&0x80 # return fp0 unscathed9884fmov.l USER_FPCR(%a6),%fpcr9885fmov.s &0x3f800000,%fp1 # load +19886fdiv.s &0x00000000,%fp1 # +1 / 09887rts98889889#########################################################################9890# XDEF **************************************************************** #9891# t_operr(): Handle 060FPLSP OPERR exception during emulation. #9892# #9893# This routine is used by the 060FPLSP package. #9894# #9895# XREF **************************************************************** #9896# None. #9897# #9898# INPUT *************************************************************** #9899# fp1 = source operand #9900# #9901# OUTPUT ************************************************************** #9902# fp0 = default result #9903# fp1 = unchanged #9904# #9905# ALGORITHM *********************************************************** #9906# An operand error should occur as the result of transcendental #9907# emulation in the 060FPLSP. If OPERR is disabled, just return a NAN #9908# in fp0. If OPERR is enabled, return the dst operand unscathed in fp0 #9909# and the source operand in fp1. Use fp2 to create an OPERR exception #9910# so that the operating system can log the event. #9911# #9912#########################################################################99139914global t_operr9915t_operr:9916ori.l &opnan_mask,USER_FPSR(%a6) # set NAN/OPERR/AIOP99179918btst &operr_bit,FPCR_ENABLE(%a6)9919bne.b operr_ena99209921# operr is disabled. return a QNAN in fp09922fmovm.x qnan(%pc),&0x80 # return QNAN9923rts99249925# operr is enabled. create an operr exception so the user can record it9926# but use fp2 instead. return the dst operand unscathed in fp0.9927operr_ena:9928fmovm.x EXC_FP0(%a6),&0x80 # return fp0 unscathed9929fmov.l USER_FPCR(%a6),%fpcr9930fmovm.x &0x04,-(%sp) # save fp29931fmov.s &0x7f800000,%fp2 # load +INF9932fmul.s &0x00000000,%fp2 # +INF x 09933fmovm.x (%sp)+,&0x20 # restore fp29934rts99359936pls_huge:9937long 0x7ffe0000,0xffffffff,0xffffffff9938mns_huge:9939long 0xfffe0000,0xffffffff,0xffffffff9940pls_tiny:9941long 0x00000000,0x80000000,0x000000009942mns_tiny:9943long 0x80000000,0x80000000,0x0000000099449945#########################################################################9946# XDEF **************************************************************** #9947# t_unfl(): Handle 060FPLSP underflow exception during emulation. #9948# t_unfl2(): Handle 060FPLSP underflow exception during #9949# emulation. result always positive. #9950# #9951# This routine is used by the 060FPLSP package. #9952# #9953# XREF **************************************************************** #9954# None. #9955# #9956# INPUT *************************************************************** #9957# a0 = pointer to extended precision source operand #9958# #9959# OUTPUT ************************************************************** #9960# fp0 = default underflow result #9961# #9962# ALGORITHM *********************************************************** #9963# An underflow should occur as the result of transcendental #9964# emulation in the 060FPLSP. Create an underflow by using "fmul" #9965# and two very small numbers of appropriate sign so the operating #9966# system can log the event. #9967# #9968#########################################################################99699970global t_unfl9971t_unfl:9972tst.b SRC_EX(%a0)9973bpl.b unf_pos99749975global t_unfl29976t_unfl2:9977ori.l &unfinx_mask+neg_mask,USER_FPSR(%a6) # set N/UNFL/INEX2/AUNFL/AINEX99789979fmov.l USER_FPCR(%a6),%fpcr9980fmovm.x mns_tiny(%pc),&0x809981fmul.x pls_tiny(%pc),%fp099829983fmov.l %fpsr,%d09984rol.l &0x8,%d09985mov.b %d0,FPSR_CC(%a6)9986rts9987unf_pos:9988ori.w &unfinx_mask,FPSR_EXCEPT(%a6) # set UNFL/INEX2/AUNFL/AINEX99899990fmov.l USER_FPCR(%a6),%fpcr9991fmovm.x pls_tiny(%pc),&0x809992fmul.x %fp0,%fp099939994fmov.l %fpsr,%d09995rol.l &0x8,%d09996mov.b %d0,FPSR_CC(%a6)9997rts99989999#########################################################################10000# XDEF **************************************************************** #10001# t_ovfl(): Handle 060FPLSP overflow exception during emulation. #10002# (monadic) #10003# t_ovfl2(): Handle 060FPLSP overflow exception during #10004# emulation. result always positive. (dyadic) #10005# t_ovfl_sc(): Handle 060FPLSP overflow exception during #10006# emulation for "fscale". #10007# #10008# This routine is used by the 060FPLSP package. #10009# #10010# XREF **************************************************************** #10011# None. #10012# #10013# INPUT *************************************************************** #10014# a0 = pointer to extended precision source operand #10015# #10016# OUTPUT ************************************************************** #10017# fp0 = default underflow result #10018# #10019# ALGORITHM *********************************************************** #10020# An overflow should occur as the result of transcendental #10021# emulation in the 060FPLSP. Create an overflow by using "fmul" #10022# and two very lareg numbers of appropriate sign so the operating #10023# system can log the event. #10024# For t_ovfl_sc() we take special care not to lose the INEX2 bit. #10025# #10026#########################################################################1002710028global t_ovfl_sc10029t_ovfl_sc:10030ori.l &ovfl_inx_mask,USER_FPSR(%a6) # set OVFL/AOVFL/AINEX1003110032mov.b %d0,%d1 # fetch rnd prec,mode10033andi.b &0xc0,%d1 # extract prec10034beq.w ovfl_work1003510036# dst op is a DENORM. we have to normalize the mantissa to see if the10037# result would be inexact for the given precision. make a copy of the10038# dst so we don't screw up the version passed to us.10039mov.w LOCAL_EX(%a0),FP_SCR0_EX(%a6)10040mov.l LOCAL_HI(%a0),FP_SCR0_HI(%a6)10041mov.l LOCAL_LO(%a0),FP_SCR0_LO(%a6)10042lea FP_SCR0(%a6),%a0 # pass ptr to FP_SCR010043movm.l &0xc080,-(%sp) # save d0-d1/a010044bsr.l norm # normalize mantissa10045movm.l (%sp)+,&0x0103 # restore d0-d1/a01004610047cmpi.b %d1,&0x40 # is precision sgl?10048bne.b ovfl_sc_dbl # no; dbl10049ovfl_sc_sgl:10050tst.l LOCAL_LO(%a0) # is lo lw of sgl set?10051bne.b ovfl_sc_inx # yes10052tst.b 3+LOCAL_HI(%a0) # is lo byte of hi lw set?10053bne.b ovfl_sc_inx # yes10054bra.w ovfl_work # don't set INEX210055ovfl_sc_dbl:10056mov.l LOCAL_LO(%a0),%d1 # are any of lo 11 bits of10057andi.l &0x7ff,%d1 # dbl mantissa set?10058beq.w ovfl_work # no; don't set INEX210059ovfl_sc_inx:10060ori.l &inex2_mask,USER_FPSR(%a6) # set INEX210061bra.b ovfl_work # continue1006210063global t_ovfl10064t_ovfl:10065ori.w &ovfinx_mask,FPSR_EXCEPT(%a6) # set OVFL/INEX2/AOVFL/AINEX10066ovfl_work:10067tst.b SRC_EX(%a0)10068bpl.b ovfl_p10069ovfl_m:10070fmov.l USER_FPCR(%a6),%fpcr10071fmovm.x mns_huge(%pc),&0x8010072fmul.x pls_huge(%pc),%fp01007310074fmov.l %fpsr,%d010075rol.l &0x8,%d010076ori.b &neg_mask,%d010077mov.b %d0,FPSR_CC(%a6)10078rts10079ovfl_p:10080fmov.l USER_FPCR(%a6),%fpcr10081fmovm.x pls_huge(%pc),&0x8010082fmul.x pls_huge(%pc),%fp01008310084fmov.l %fpsr,%d010085rol.l &0x8,%d010086mov.b %d0,FPSR_CC(%a6)10087rts1008810089global t_ovfl210090t_ovfl2:10091ori.w &ovfinx_mask,FPSR_EXCEPT(%a6) # set OVFL/INEX2/AOVFL/AINEX10092fmov.l USER_FPCR(%a6),%fpcr10093fmovm.x pls_huge(%pc),&0x8010094fmul.x pls_huge(%pc),%fp01009510096fmov.l %fpsr,%d010097rol.l &0x8,%d010098mov.b %d0,FPSR_CC(%a6)10099rts1010010101#########################################################################10102# XDEF **************************************************************** #10103# t_catch(): Handle 060FPLSP OVFL,UNFL,or INEX2 exception during #10104# emulation. #10105# t_catch2(): Handle 060FPLSP OVFL,UNFL,or INEX2 exception during #10106# emulation. #10107# #10108# These routines are used by the 060FPLSP package. #10109# #10110# XREF **************************************************************** #10111# None. #10112# #10113# INPUT *************************************************************** #10114# fp0 = default underflow or overflow result #10115# #10116# OUTPUT ************************************************************** #10117# fp0 = default result #10118# #10119# ALGORITHM *********************************************************** #10120# If an overflow or underflow occurred during the last #10121# instruction of transcendental 060FPLSP emulation, then it has already #10122# occurred and has been logged. Now we need to see if an inexact #10123# exception should occur. #10124# #10125#########################################################################1012610127global t_catch210128t_catch2:10129fmov.l %fpsr,%d010130or.l %d0,USER_FPSR(%a6)10131bra.b inx2_work1013210133global t_catch10134t_catch:10135fmov.l %fpsr,%d010136or.l %d0,USER_FPSR(%a6)1013710138#########################################################################10139# XDEF **************************************************************** #10140# t_inx2(): Handle inexact 060FPLSP exception during emulation. #10141# t_pinx2(): Handle inexact 060FPLSP exception for "+" results. #10142# t_minx2(): Handle inexact 060FPLSP exception for "-" results. #10143# #10144# XREF **************************************************************** #10145# None. #10146# #10147# INPUT *************************************************************** #10148# fp0 = default result #10149# #10150# OUTPUT ************************************************************** #10151# fp0 = default result #10152# #10153# ALGORITHM *********************************************************** #10154# The last instruction of transcendental emulation for the #10155# 060FPLSP should be inexact. So, if inexact is enabled, then we create #10156# the event here by adding a large and very small number together #10157# so that the operating system can log the event. #10158# Must check, too, if the result was zero, in which case we just #10159# set the FPSR bits and return. #10160# #10161#########################################################################1016210163global t_inx210164t_inx2:10165fblt.w t_minx210166fbeq.w inx2_zero1016710168global t_pinx210169t_pinx2:10170ori.w &inx2a_mask,FPSR_EXCEPT(%a6) # set INEX2/AINEX10171bra.b inx2_work1017210173global t_minx210174t_minx2:10175ori.l &inx2a_mask+neg_mask,USER_FPSR(%a6)1017610177inx2_work:10178btst &inex2_bit,FPCR_ENABLE(%a6) # is inexact enabled?10179bne.b inx2_work_ena # yes10180rts10181inx2_work_ena:10182fmov.l USER_FPCR(%a6),%fpcr # insert user's exceptions10183fmov.s &0x3f800000,%fp1 # load +110184fadd.x pls_tiny(%pc),%fp1 # cause exception10185rts1018610187inx2_zero:10188mov.b &z_bmask,FPSR_CC(%a6)10189ori.w &inx2a_mask,2+USER_FPSR(%a6) # set INEX/AINEX10190rts1019110192#########################################################################10193# XDEF **************************************************************** #10194# t_extdnrm(): Handle DENORM inputs in 060FPLSP. #10195# t_resdnrm(): Handle DENORM inputs in 060FPLSP for "fscale". #10196# #10197# This routine is used by the 060FPLSP package. #10198# #10199# XREF **************************************************************** #10200# None. #10201# #10202# INPUT *************************************************************** #10203# a0 = pointer to extended precision input operand #10204# #10205# OUTPUT ************************************************************** #10206# fp0 = default result #10207# #10208# ALGORITHM *********************************************************** #10209# For all functions that have a denormalized input and that #10210# f(x)=x, this is the entry point. #10211# DENORM value is moved using "fmove" which triggers an exception #10212# if enabled so the operating system can log the event. #10213# #10214#########################################################################1021510216global t_extdnrm10217t_extdnrm:10218fmov.l USER_FPCR(%a6),%fpcr10219fmov.x SRC_EX(%a0),%fp010220fmov.l %fpsr,%d010221ori.l &unfinx_mask,%d010222or.l %d0,USER_FPSR(%a6)10223rts1022410225global t_resdnrm10226t_resdnrm:10227fmov.l USER_FPCR(%a6),%fpcr10228fmov.x SRC_EX(%a0),%fp010229fmov.l %fpsr,%d010230or.l %d0,USER_FPSR(%a6)10231rts1023210233##########################################1023410235#10236# sto_cos:10237# This is used by fsincos library emulation. The correct10238# values are already in fp0 and fp1 so we do nothing here.10239#10240global sto_cos10241sto_cos:10242rts1024310244##########################################1024510246#10247# dst_qnan --- force result when destination is a NaN10248#10249global dst_qnan10250dst_qnan:10251fmov.x DST(%a1),%fp010252tst.b DST_EX(%a1)10253bmi.b dst_qnan_m10254dst_qnan_p:10255mov.b &nan_bmask,FPSR_CC(%a6)10256rts10257dst_qnan_m:10258mov.b &nan_bmask+neg_bmask,FPSR_CC(%a6)10259rts1026010261#10262# src_qnan --- force result when source is a NaN10263#10264global src_qnan10265src_qnan:10266fmov.x SRC(%a0),%fp010267tst.b SRC_EX(%a0)10268bmi.b src_qnan_m10269src_qnan_p:10270mov.b &nan_bmask,FPSR_CC(%a6)10271rts10272src_qnan_m:10273mov.b &nan_bmask+neg_bmask,FPSR_CC(%a6)10274rts1027510276##########################################1027710278#10279# Native instruction support10280#10281# Some systems may need entry points even for 68060 native10282# instructions. These routines are provided for10283# convenience.10284#10285global _fadds_10286_fadds_:10287fmov.l %fpcr,-(%sp) # save fpcr10288fmov.l &0x00000000,%fpcr # clear fpcr for load10289fmov.s 0x8(%sp),%fp0 # load sgl dst10290fmov.l (%sp)+,%fpcr # restore fpcr10291fadd.s 0x8(%sp),%fp0 # fadd w/ sgl src10292rts1029310294global _faddd_10295_faddd_:10296fmov.l %fpcr,-(%sp) # save fpcr10297fmov.l &0x00000000,%fpcr # clear fpcr for load10298fmov.d 0x8(%sp),%fp0 # load dbl dst10299fmov.l (%sp)+,%fpcr # restore fpcr10300fadd.d 0xc(%sp),%fp0 # fadd w/ dbl src10301rts1030210303global _faddx_10304_faddx_:10305fmovm.x 0x4(%sp),&0x80 # load ext dst10306fadd.x 0x10(%sp),%fp0 # fadd w/ ext src10307rts1030810309global _fsubs_10310_fsubs_:10311fmov.l %fpcr,-(%sp) # save fpcr10312fmov.l &0x00000000,%fpcr # clear fpcr for load10313fmov.s 0x8(%sp),%fp0 # load sgl dst10314fmov.l (%sp)+,%fpcr # restore fpcr10315fsub.s 0x8(%sp),%fp0 # fsub w/ sgl src10316rts1031710318global _fsubd_10319_fsubd_:10320fmov.l %fpcr,-(%sp) # save fpcr10321fmov.l &0x00000000,%fpcr # clear fpcr for load10322fmov.d 0x8(%sp),%fp0 # load dbl dst10323fmov.l (%sp)+,%fpcr # restore fpcr10324fsub.d 0xc(%sp),%fp0 # fsub w/ dbl src10325rts1032610327global _fsubx_10328_fsubx_:10329fmovm.x 0x4(%sp),&0x80 # load ext dst10330fsub.x 0x10(%sp),%fp0 # fsub w/ ext src10331rts1033210333global _fmuls_10334_fmuls_:10335fmov.l %fpcr,-(%sp) # save fpcr10336fmov.l &0x00000000,%fpcr # clear fpcr for load10337fmov.s 0x8(%sp),%fp0 # load sgl dst10338fmov.l (%sp)+,%fpcr # restore fpcr10339fmul.s 0x8(%sp),%fp0 # fmul w/ sgl src10340rts1034110342global _fmuld_10343_fmuld_:10344fmov.l %fpcr,-(%sp) # save fpcr10345fmov.l &0x00000000,%fpcr # clear fpcr for load10346fmov.d 0x8(%sp),%fp0 # load dbl dst10347fmov.l (%sp)+,%fpcr # restore fpcr10348fmul.d 0xc(%sp),%fp0 # fmul w/ dbl src10349rts1035010351global _fmulx_10352_fmulx_:10353fmovm.x 0x4(%sp),&0x80 # load ext dst10354fmul.x 0x10(%sp),%fp0 # fmul w/ ext src10355rts1035610357global _fdivs_10358_fdivs_:10359fmov.l %fpcr,-(%sp) # save fpcr10360fmov.l &0x00000000,%fpcr # clear fpcr for load10361fmov.s 0x8(%sp),%fp0 # load sgl dst10362fmov.l (%sp)+,%fpcr # restore fpcr10363fdiv.s 0x8(%sp),%fp0 # fdiv w/ sgl src10364rts1036510366global _fdivd_10367_fdivd_:10368fmov.l %fpcr,-(%sp) # save fpcr10369fmov.l &0x00000000,%fpcr # clear fpcr for load10370fmov.d 0x8(%sp),%fp0 # load dbl dst10371fmov.l (%sp)+,%fpcr # restore fpcr10372fdiv.d 0xc(%sp),%fp0 # fdiv w/ dbl src10373rts1037410375global _fdivx_10376_fdivx_:10377fmovm.x 0x4(%sp),&0x80 # load ext dst10378fdiv.x 0x10(%sp),%fp0 # fdiv w/ ext src10379rts1038010381global _fabss_10382_fabss_:10383fabs.s 0x4(%sp),%fp0 # fabs w/ sgl src10384rts1038510386global _fabsd_10387_fabsd_:10388fabs.d 0x4(%sp),%fp0 # fabs w/ dbl src10389rts1039010391global _fabsx_10392_fabsx_:10393fabs.x 0x4(%sp),%fp0 # fabs w/ ext src10394rts1039510396global _fnegs_10397_fnegs_:10398fneg.s 0x4(%sp),%fp0 # fneg w/ sgl src10399rts1040010401global _fnegd_10402_fnegd_:10403fneg.d 0x4(%sp),%fp0 # fneg w/ dbl src10404rts1040510406global _fnegx_10407_fnegx_:10408fneg.x 0x4(%sp),%fp0 # fneg w/ ext src10409rts1041010411global _fsqrts_10412_fsqrts_:10413fsqrt.s 0x4(%sp),%fp0 # fsqrt w/ sgl src10414rts1041510416global _fsqrtd_10417_fsqrtd_:10418fsqrt.d 0x4(%sp),%fp0 # fsqrt w/ dbl src10419rts1042010421global _fsqrtx_10422_fsqrtx_:10423fsqrt.x 0x4(%sp),%fp0 # fsqrt w/ ext src10424rts1042510426global _fints_10427_fints_:10428fint.s 0x4(%sp),%fp0 # fint w/ sgl src10429rts1043010431global _fintd_10432_fintd_:10433fint.d 0x4(%sp),%fp0 # fint w/ dbl src10434rts1043510436global _fintx_10437_fintx_:10438fint.x 0x4(%sp),%fp0 # fint w/ ext src10439rts1044010441global _fintrzs_10442_fintrzs_:10443fintrz.s 0x4(%sp),%fp0 # fintrz w/ sgl src10444rts1044510446global _fintrzd_10447_fintrzd_:10448fintrz.d 0x4(%sp),%fp0 # fintrx w/ dbl src10449rts1045010451global _fintrzx_10452_fintrzx_:10453fintrz.x 0x4(%sp),%fp0 # fintrz w/ ext src10454rts1045510456########################################################################1045710458#########################################################################10459# src_zero(): Return signed zero according to sign of src operand. #10460#########################################################################10461global src_zero10462src_zero:10463tst.b SRC_EX(%a0) # get sign of src operand10464bmi.b ld_mzero # if neg, load neg zero1046510466#10467# ld_pzero(): return a positive zero.10468#10469global ld_pzero10470ld_pzero:10471fmov.s &0x00000000,%fp0 # load +010472mov.b &z_bmask,FPSR_CC(%a6) # set 'Z' ccode bit10473rts1047410475# ld_mzero(): return a negative zero.10476global ld_mzero10477ld_mzero:10478fmov.s &0x80000000,%fp0 # load -010479mov.b &neg_bmask+z_bmask,FPSR_CC(%a6) # set 'N','Z' ccode bits10480rts1048110482#########################################################################10483# dst_zero(): Return signed zero according to sign of dst operand. #10484#########################################################################10485global dst_zero10486dst_zero:10487tst.b DST_EX(%a1) # get sign of dst operand10488bmi.b ld_mzero # if neg, load neg zero10489bra.b ld_pzero # load positive zero1049010491#########################################################################10492# src_inf(): Return signed inf according to sign of src operand. #10493#########################################################################10494global src_inf10495src_inf:10496tst.b SRC_EX(%a0) # get sign of src operand10497bmi.b ld_minf # if negative branch1049810499#10500# ld_pinf(): return a positive infinity.10501#10502global ld_pinf10503ld_pinf:10504fmov.s &0x7f800000,%fp0 # load +INF10505mov.b &inf_bmask,FPSR_CC(%a6) # set 'INF' ccode bit10506rts1050710508#10509# ld_minf():return a negative infinity.10510#10511global ld_minf10512ld_minf:10513fmov.s &0xff800000,%fp0 # load -INF10514mov.b &neg_bmask+inf_bmask,FPSR_CC(%a6) # set 'N','I' ccode bits10515rts1051610517#########################################################################10518# dst_inf(): Return signed inf according to sign of dst operand. #10519#########################################################################10520global dst_inf10521dst_inf:10522tst.b DST_EX(%a1) # get sign of dst operand10523bmi.b ld_minf # if negative branch10524bra.b ld_pinf1052510526global szr_inf10527#################################################################10528# szr_inf(): Return +ZERO for a negative src operand or #10529# +INF for a positive src operand. #10530# Routine used for fetox, ftwotox, and ftentox. #10531#################################################################10532szr_inf:10533tst.b SRC_EX(%a0) # check sign of source10534bmi.b ld_pzero10535bra.b ld_pinf1053610537#########################################################################10538# sopr_inf(): Return +INF for a positive src operand or #10539# jump to operand error routine for a negative src operand. #10540# Routine used for flogn, flognp1, flog10, and flog2. #10541#########################################################################10542global sopr_inf10543sopr_inf:10544tst.b SRC_EX(%a0) # check sign of source10545bmi.w t_operr10546bra.b ld_pinf1054710548#################################################################10549# setoxm1i(): Return minus one for a negative src operand or #10550# positive infinity for a positive src operand. #10551# Routine used for fetoxm1. #10552#################################################################10553global setoxm1i10554setoxm1i:10555tst.b SRC_EX(%a0) # check sign of source10556bmi.b ld_mone10557bra.b ld_pinf1055810559#########################################################################10560# src_one(): Return signed one according to sign of src operand. #10561#########################################################################10562global src_one10563src_one:10564tst.b SRC_EX(%a0) # check sign of source10565bmi.b ld_mone1056610567#10568# ld_pone(): return positive one.10569#10570global ld_pone10571ld_pone:10572fmov.s &0x3f800000,%fp0 # load +110573clr.b FPSR_CC(%a6)10574rts1057510576#10577# ld_mone(): return negative one.10578#10579global ld_mone10580ld_mone:10581fmov.s &0xbf800000,%fp0 # load -110582mov.b &neg_bmask,FPSR_CC(%a6) # set 'N' ccode bit10583rts1058410585ppiby2: long 0x3fff0000, 0xc90fdaa2, 0x2168c23510586mpiby2: long 0xbfff0000, 0xc90fdaa2, 0x2168c2351058710588#################################################################10589# spi_2(): Return signed PI/2 according to sign of src operand. #10590#################################################################10591global spi_210592spi_2:10593tst.b SRC_EX(%a0) # check sign of source10594bmi.b ld_mpi21059510596#10597# ld_ppi2(): return positive PI/2.10598#10599global ld_ppi210600ld_ppi2:10601fmov.l %d0,%fpcr10602fmov.x ppiby2(%pc),%fp0 # load +pi/210603bra.w t_pinx2 # set INEX21060410605#10606# ld_mpi2(): return negative PI/2.10607#10608global ld_mpi210609ld_mpi2:10610fmov.l %d0,%fpcr10611fmov.x mpiby2(%pc),%fp0 # load -pi/210612bra.w t_minx2 # set INEX21061310614####################################################10615# The following routines give support for fsincos. #10616####################################################1061710618#10619# ssincosz(): When the src operand is ZERO, store a one in the10620# cosine register and return a ZERO in fp0 w/ the same sign10621# as the src operand.10622#10623global ssincosz10624ssincosz:10625fmov.s &0x3f800000,%fp110626tst.b SRC_EX(%a0) # test sign10627bpl.b sincoszp10628fmov.s &0x80000000,%fp0 # return sin result in fp010629mov.b &z_bmask+neg_bmask,FPSR_CC(%a6)10630rts10631sincoszp:10632fmov.s &0x00000000,%fp0 # return sin result in fp010633mov.b &z_bmask,FPSR_CC(%a6)10634rts1063510636#10637# ssincosi(): When the src operand is INF, store a QNAN in the cosine10638# register and jump to the operand error routine for negative10639# src operands.10640#10641global ssincosi10642ssincosi:10643fmov.x qnan(%pc),%fp1 # load NAN10644bra.w t_operr1064510646#10647# ssincosqnan(): When the src operand is a QNAN, store the QNAN in the cosine10648# register and branch to the src QNAN routine.10649#10650global ssincosqnan10651ssincosqnan:10652fmov.x LOCAL_EX(%a0),%fp110653bra.w src_qnan1065410655########################################################################1065610657global smod_sdnrm10658global smod_snorm10659smod_sdnrm:10660smod_snorm:10661mov.b DTAG(%a6),%d110662beq.l smod10663cmpi.b %d1,&ZERO10664beq.w smod_zro10665cmpi.b %d1,&INF10666beq.l t_operr10667cmpi.b %d1,&DENORM10668beq.l smod10669bra.l dst_qnan1067010671global smod_szero10672smod_szero:10673mov.b DTAG(%a6),%d110674beq.l t_operr10675cmpi.b %d1,&ZERO10676beq.l t_operr10677cmpi.b %d1,&INF10678beq.l t_operr10679cmpi.b %d1,&DENORM10680beq.l t_operr10681bra.l dst_qnan1068210683global smod_sinf10684smod_sinf:10685mov.b DTAG(%a6),%d110686beq.l smod_fpn10687cmpi.b %d1,&ZERO10688beq.l smod_zro10689cmpi.b %d1,&INF10690beq.l t_operr10691cmpi.b %d1,&DENORM10692beq.l smod_fpn10693bra.l dst_qnan1069410695smod_zro:10696srem_zro:10697mov.b SRC_EX(%a0),%d1 # get src sign10698mov.b DST_EX(%a1),%d0 # get dst sign10699eor.b %d0,%d1 # get qbyte sign10700andi.b &0x80,%d110701mov.b %d1,FPSR_QBYTE(%a6)10702tst.b %d010703bpl.w ld_pzero10704bra.w ld_mzero1070510706smod_fpn:10707srem_fpn:10708clr.b FPSR_QBYTE(%a6)10709mov.l %d0,-(%sp)10710mov.b SRC_EX(%a0),%d1 # get src sign10711mov.b DST_EX(%a1),%d0 # get dst sign10712eor.b %d0,%d1 # get qbyte sign10713andi.b &0x80,%d110714mov.b %d1,FPSR_QBYTE(%a6)10715cmpi.b DTAG(%a6),&DENORM10716bne.b smod_nrm10717lea DST(%a1),%a010718mov.l (%sp)+,%d010719bra t_resdnrm10720smod_nrm:10721fmov.l (%sp)+,%fpcr10722fmov.x DST(%a1),%fp010723tst.b DST_EX(%a1)10724bmi.b smod_nrm_neg10725rts1072610727smod_nrm_neg:10728mov.b &neg_bmask,FPSR_CC(%a6) # set 'N' code10729rts1073010731#########################################################################10732global srem_snorm10733global srem_sdnrm10734srem_sdnrm:10735srem_snorm:10736mov.b DTAG(%a6),%d110737beq.l srem10738cmpi.b %d1,&ZERO10739beq.w srem_zro10740cmpi.b %d1,&INF10741beq.l t_operr10742cmpi.b %d1,&DENORM10743beq.l srem10744bra.l dst_qnan1074510746global srem_szero10747srem_szero:10748mov.b DTAG(%a6),%d110749beq.l t_operr10750cmpi.b %d1,&ZERO10751beq.l t_operr10752cmpi.b %d1,&INF10753beq.l t_operr10754cmpi.b %d1,&DENORM10755beq.l t_operr10756bra.l dst_qnan1075710758global srem_sinf10759srem_sinf:10760mov.b DTAG(%a6),%d110761beq.w srem_fpn10762cmpi.b %d1,&ZERO10763beq.w srem_zro10764cmpi.b %d1,&INF10765beq.l t_operr10766cmpi.b %d1,&DENORM10767beq.l srem_fpn10768bra.l dst_qnan1076910770#########################################################################1077110772global sscale_snorm10773global sscale_sdnrm10774sscale_snorm:10775sscale_sdnrm:10776mov.b DTAG(%a6),%d110777beq.l sscale10778cmpi.b %d1,&ZERO10779beq.l dst_zero10780cmpi.b %d1,&INF10781beq.l dst_inf10782cmpi.b %d1,&DENORM10783beq.l sscale10784bra.l dst_qnan1078510786global sscale_szero10787sscale_szero:10788mov.b DTAG(%a6),%d110789beq.l sscale10790cmpi.b %d1,&ZERO10791beq.l dst_zero10792cmpi.b %d1,&INF10793beq.l dst_inf10794cmpi.b %d1,&DENORM10795beq.l sscale10796bra.l dst_qnan1079710798global sscale_sinf10799sscale_sinf:10800mov.b DTAG(%a6),%d110801beq.l t_operr10802cmpi.b %d1,&QNAN10803beq.l dst_qnan10804bra.l t_operr1080510806########################################################################1080710808global sop_sqnan10809sop_sqnan:10810mov.b DTAG(%a6),%d110811cmpi.b %d1,&QNAN10812beq.l dst_qnan10813bra.l src_qnan1081410815#########################################################################10816# norm(): normalize the mantissa of an extended precision input. the #10817# input operand should not be normalized already. #10818# #10819# XDEF **************************************************************** #10820# norm() #10821# #10822# XREF **************************************************************** #10823# none #10824# #10825# INPUT *************************************************************** #10826# a0 = pointer fp extended precision operand to normalize #10827# #10828# OUTPUT ************************************************************** #10829# d0 = number of bit positions the mantissa was shifted #10830# a0 = the input operand's mantissa is normalized; the exponent #10831# is unchanged. #10832# #10833#########################################################################10834global norm10835norm:10836mov.l %d2, -(%sp) # create some temp regs10837mov.l %d3, -(%sp)1083810839mov.l FTEMP_HI(%a0), %d0 # load hi(mantissa)10840mov.l FTEMP_LO(%a0), %d1 # load lo(mantissa)1084110842bfffo %d0{&0:&32}, %d2 # how many places to shift?10843beq.b norm_lo # hi(man) is all zeroes!1084410845norm_hi:10846lsl.l %d2, %d0 # left shift hi(man)10847bfextu %d1{&0:%d2}, %d3 # extract lo bits1084810849or.l %d3, %d0 # create hi(man)10850lsl.l %d2, %d1 # create lo(man)1085110852mov.l %d0, FTEMP_HI(%a0) # store new hi(man)10853mov.l %d1, FTEMP_LO(%a0) # store new lo(man)1085410855mov.l %d2, %d0 # return shift amount1085610857mov.l (%sp)+, %d3 # restore temp regs10858mov.l (%sp)+, %d21085910860rts1086110862norm_lo:10863bfffo %d1{&0:&32}, %d2 # how many places to shift?10864lsl.l %d2, %d1 # shift lo(man)10865add.l &32, %d2 # add 32 to shft amount1086610867mov.l %d1, FTEMP_HI(%a0) # store hi(man)10868clr.l FTEMP_LO(%a0) # lo(man) is now zero1086910870mov.l %d2, %d0 # return shift amount1087110872mov.l (%sp)+, %d3 # restore temp regs10873mov.l (%sp)+, %d21087410875rts1087610877#########################################################################10878# unnorm_fix(): - changes an UNNORM to one of NORM, DENORM, or ZERO #10879# - returns corresponding optype tag #10880# #10881# XDEF **************************************************************** #10882# unnorm_fix() #10883# #10884# XREF **************************************************************** #10885# norm() - normalize the mantissa #10886# #10887# INPUT *************************************************************** #10888# a0 = pointer to unnormalized extended precision number #10889# #10890# OUTPUT ************************************************************** #10891# d0 = optype tag - is corrected to one of NORM, DENORM, or ZERO #10892# a0 = input operand has been converted to a norm, denorm, or #10893# zero; both the exponent and mantissa are changed. #10894# #10895#########################################################################1089610897global unnorm_fix10898unnorm_fix:10899bfffo FTEMP_HI(%a0){&0:&32}, %d0 # how many shifts are needed?10900bne.b unnorm_shift # hi(man) is not all zeroes1090110902#10903# hi(man) is all zeroes so see if any bits in lo(man) are set10904#10905unnorm_chk_lo:10906bfffo FTEMP_LO(%a0){&0:&32}, %d0 # is operand really a zero?10907beq.w unnorm_zero # yes1090810909add.w &32, %d0 # no; fix shift distance1091010911#10912# d0 = # shifts needed for complete normalization10913#10914unnorm_shift:10915clr.l %d1 # clear top word10916mov.w FTEMP_EX(%a0), %d1 # extract exponent10917and.w &0x7fff, %d1 # strip off sgn1091810919cmp.w %d0, %d1 # will denorm push exp < 0?10920bgt.b unnorm_nrm_zero # yes; denorm only until exp = 01092110922#10923# exponent would not go < 0. therefore, number stays normalized10924#10925sub.w %d0, %d1 # shift exponent value10926mov.w FTEMP_EX(%a0), %d0 # load old exponent10927and.w &0x8000, %d0 # save old sign10928or.w %d0, %d1 # {sgn,new exp}10929mov.w %d1, FTEMP_EX(%a0) # insert new exponent1093010931bsr.l norm # normalize UNNORM1093210933mov.b &NORM, %d0 # return new optype tag10934rts1093510936#10937# exponent would go < 0, so only denormalize until exp = 010938#10939unnorm_nrm_zero:10940cmp.b %d1, &32 # is exp <= 32?10941bgt.b unnorm_nrm_zero_lrg # no; go handle large exponent1094210943bfextu FTEMP_HI(%a0){%d1:&32}, %d0 # extract new hi(man)10944mov.l %d0, FTEMP_HI(%a0) # save new hi(man)1094510946mov.l FTEMP_LO(%a0), %d0 # fetch old lo(man)10947lsl.l %d1, %d0 # extract new lo(man)10948mov.l %d0, FTEMP_LO(%a0) # save new lo(man)1094910950and.w &0x8000, FTEMP_EX(%a0) # set exp = 01095110952mov.b &DENORM, %d0 # return new optype tag10953rts1095410955#10956# only mantissa bits set are in lo(man)10957#10958unnorm_nrm_zero_lrg:10959sub.w &32, %d1 # adjust shft amt by 321096010961mov.l FTEMP_LO(%a0), %d0 # fetch old lo(man)10962lsl.l %d1, %d0 # left shift lo(man)1096310964mov.l %d0, FTEMP_HI(%a0) # store new hi(man)10965clr.l FTEMP_LO(%a0) # lo(man) = 01096610967and.w &0x8000, FTEMP_EX(%a0) # set exp = 01096810969mov.b &DENORM, %d0 # return new optype tag10970rts1097110972#10973# whole mantissa is zero so this UNNORM is actually a zero10974#10975unnorm_zero:10976and.w &0x8000, FTEMP_EX(%a0) # force exponent to zero1097710978mov.b &ZERO, %d0 # fix optype tag10979rts109801098110982