linux/arch/m68k/ifpsp060/src/fplsp.S
<<
>>
Prefs
   1~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
   3M68000 Hi-Performance Microprocessor Division
   4M68060 Software Package
   5Production Release P1.00 -- October 10, 1994
   6
   7M68060 Software Package Copyright © 1993, 1994 Motorola Inc.  All rights reserved.
   8
   9THE SOFTWARE is provided on an "AS IS" basis and without warranty.
  10To the maximum extent permitted by applicable law,
  11MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
  12INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
  13and any warranty against infringement with regard to the SOFTWARE
  14(INCLUDING ANY MODIFIED VERSIONS THEREOF) and any accompanying written materials.
  15
  16To the maximum extent permitted by applicable law,
  17IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
  18(INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS,
  19BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS)
  20ARISING OF THE USE OR INABILITY TO USE THE SOFTWARE.
  21Motorola assumes no responsibility for the maintenance and support of the SOFTWARE.
  22
  23You are hereby granted a copyright license to use, modify, and distribute the SOFTWARE
  24so long as this entire notice is retained without alteration in any modified and/or
  25redistributed versions, and that such modified versions are clearly identified as such.
  26No licenses are granted by implication, estoppel or otherwise under any patents
  27or trademarks of Motorola, Inc.
  28~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  29#
  30# lfptop.s:
  31#       This file is appended to the top of the 060ILSP package
  32# and contains the entry points into the package. The user, in
  33# effect, branches to one of the branch table entries located here.
  34#
  35
  36        bra.l   _facoss_
  37        short   0x0000
  38        bra.l   _facosd_
  39        short   0x0000
  40        bra.l   _facosx_
  41        short   0x0000
  42
  43        bra.l   _fasins_
  44        short   0x0000
  45        bra.l   _fasind_
  46        short   0x0000
  47        bra.l   _fasinx_
  48        short   0x0000
  49
  50        bra.l   _fatans_
  51        short   0x0000
  52        bra.l   _fatand_
  53        short   0x0000
  54        bra.l   _fatanx_
  55        short   0x0000
  56
  57        bra.l   _fatanhs_
  58        short   0x0000
  59        bra.l   _fatanhd_
  60        short   0x0000
  61        bra.l   _fatanhx_
  62        short   0x0000
  63
  64        bra.l   _fcoss_
  65        short   0x0000
  66        bra.l   _fcosd_
  67        short   0x0000
  68        bra.l   _fcosx_
  69        short   0x0000
  70
  71        bra.l   _fcoshs_
  72        short   0x0000
  73        bra.l   _fcoshd_
  74        short   0x0000
  75        bra.l   _fcoshx_
  76        short   0x0000
  77
  78        bra.l   _fetoxs_
  79        short   0x0000
  80        bra.l   _fetoxd_
  81        short   0x0000
  82        bra.l   _fetoxx_
  83        short   0x0000
  84
  85        bra.l   _fetoxm1s_
  86        short   0x0000
  87        bra.l   _fetoxm1d_
  88        short   0x0000
  89        bra.l   _fetoxm1x_
  90        short   0x0000
  91
  92        bra.l   _fgetexps_
  93        short   0x0000
  94        bra.l   _fgetexpd_
  95        short   0x0000
  96        bra.l   _fgetexpx_
  97        short   0x0000
  98
  99        bra.l   _fgetmans_
 100        short   0x0000
 101        bra.l   _fgetmand_
 102        short   0x0000
 103        bra.l   _fgetmanx_
 104        short   0x0000
 105
 106        bra.l   _flog10s_
 107        short   0x0000
 108        bra.l   _flog10d_
 109        short   0x0000
 110        bra.l   _flog10x_
 111        short   0x0000
 112
 113        bra.l   _flog2s_
 114        short   0x0000
 115        bra.l   _flog2d_
 116        short   0x0000
 117        bra.l   _flog2x_
 118        short   0x0000
 119
 120        bra.l   _flogns_
 121        short   0x0000
 122        bra.l   _flognd_
 123        short   0x0000
 124        bra.l   _flognx_
 125        short   0x0000
 126
 127        bra.l   _flognp1s_
 128        short   0x0000
 129        bra.l   _flognp1d_
 130        short   0x0000
 131        bra.l   _flognp1x_
 132        short   0x0000
 133
 134        bra.l   _fmods_
 135        short   0x0000
 136        bra.l   _fmodd_
 137        short   0x0000
 138        bra.l   _fmodx_
 139        short   0x0000
 140
 141        bra.l   _frems_
 142        short   0x0000
 143        bra.l   _fremd_
 144        short   0x0000
 145        bra.l   _fremx_
 146        short   0x0000
 147
 148        bra.l   _fscales_
 149        short   0x0000
 150        bra.l   _fscaled_
 151        short   0x0000
 152        bra.l   _fscalex_
 153        short   0x0000
 154
 155        bra.l   _fsins_
 156        short   0x0000
 157        bra.l   _fsind_
 158        short   0x0000
 159        bra.l   _fsinx_
 160        short   0x0000
 161
 162        bra.l   _fsincoss_
 163        short   0x0000
 164        bra.l   _fsincosd_
 165        short   0x0000
 166        bra.l   _fsincosx_
 167        short   0x0000
 168
 169        bra.l   _fsinhs_
 170        short   0x0000
 171        bra.l   _fsinhd_
 172        short   0x0000
 173        bra.l   _fsinhx_
 174        short   0x0000
 175
 176        bra.l   _ftans_
 177        short   0x0000
 178        bra.l   _ftand_
 179        short   0x0000
 180        bra.l   _ftanx_
 181        short   0x0000
 182
 183        bra.l   _ftanhs_
 184        short   0x0000
 185        bra.l   _ftanhd_
 186        short   0x0000
 187        bra.l   _ftanhx_
 188        short   0x0000
 189
 190        bra.l   _ftentoxs_
 191        short   0x0000
 192        bra.l   _ftentoxd_
 193        short   0x0000
 194        bra.l   _ftentoxx_
 195        short   0x0000
 196
 197        bra.l   _ftwotoxs_
 198        short   0x0000
 199        bra.l   _ftwotoxd_
 200        short   0x0000
 201        bra.l   _ftwotoxx_
 202        short   0x0000
 203
 204        bra.l   _fabss_
 205        short   0x0000
 206        bra.l   _fabsd_
 207        short   0x0000
 208        bra.l   _fabsx_
 209        short   0x0000
 210
 211        bra.l   _fadds_
 212        short   0x0000
 213        bra.l   _faddd_
 214        short   0x0000
 215        bra.l   _faddx_
 216        short   0x0000
 217
 218        bra.l   _fdivs_
 219        short   0x0000
 220        bra.l   _fdivd_
 221        short   0x0000
 222        bra.l   _fdivx_
 223        short   0x0000
 224
 225        bra.l   _fints_
 226        short   0x0000
 227        bra.l   _fintd_
 228        short   0x0000
 229        bra.l   _fintx_
 230        short   0x0000
 231
 232        bra.l   _fintrzs_
 233        short   0x0000
 234        bra.l   _fintrzd_
 235        short   0x0000
 236        bra.l   _fintrzx_
 237        short   0x0000
 238
 239        bra.l   _fmuls_
 240        short   0x0000
 241        bra.l   _fmuld_
 242        short   0x0000
 243        bra.l   _fmulx_
 244        short   0x0000
 245
 246        bra.l   _fnegs_
 247        short   0x0000
 248        bra.l   _fnegd_
 249        short   0x0000
 250        bra.l   _fnegx_
 251        short   0x0000
 252
 253        bra.l   _fsqrts_
 254        short   0x0000
 255        bra.l   _fsqrtd_
 256        short   0x0000
 257        bra.l   _fsqrtx_
 258        short   0x0000
 259
 260        bra.l   _fsubs_
 261        short   0x0000
 262        bra.l   _fsubd_
 263        short   0x0000
 264        bra.l   _fsubx_
 265        short   0x0000
 266
 267# leave room for future possible additions
 268        align   0x400
 269
 270#
 271# This file contains a set of define statements for constants
 272# in order to promote readability within the corecode itself.
 273#
 274
 275set LOCAL_SIZE,         192                     # stack frame size(bytes)
 276set LV,                 -LOCAL_SIZE             # stack offset
 277
 278set EXC_SR,             0x4                     # stack status register
 279set EXC_PC,             0x6                     # stack pc
 280set EXC_VOFF,           0xa                     # stacked vector offset
 281set EXC_EA,             0xc                     # stacked <ea>
 282
 283set EXC_FP,             0x0                     # frame pointer
 284
 285set EXC_AREGS,          -68                     # offset of all address regs
 286set EXC_DREGS,          -100                    # offset of all data regs
 287set EXC_FPREGS,         -36                     # offset of all fp regs
 288
 289set EXC_A7,             EXC_AREGS+(7*4)         # offset of saved a7
 290set OLD_A7,             EXC_AREGS+(6*4)         # extra copy of saved a7
 291set EXC_A6,             EXC_AREGS+(6*4)         # offset of saved a6
 292set EXC_A5,             EXC_AREGS+(5*4)
 293set EXC_A4,             EXC_AREGS+(4*4)
 294set EXC_A3,             EXC_AREGS+(3*4)
 295set EXC_A2,             EXC_AREGS+(2*4)
 296set EXC_A1,             EXC_AREGS+(1*4)
 297set EXC_A0,             EXC_AREGS+(0*4)
 298set EXC_D7,             EXC_DREGS+(7*4)
 299set EXC_D6,             EXC_DREGS+(6*4)
 300set EXC_D5,             EXC_DREGS+(5*4)
 301set EXC_D4,             EXC_DREGS+(4*4)
 302set EXC_D3,             EXC_DREGS+(3*4)
 303set EXC_D2,             EXC_DREGS+(2*4)
 304set EXC_D1,             EXC_DREGS+(1*4)
 305set EXC_D0,             EXC_DREGS+(0*4)
 306
 307set EXC_FP0,            EXC_FPREGS+(0*12)       # offset of saved fp0
 308set EXC_FP1,            EXC_FPREGS+(1*12)       # offset of saved fp1
 309set EXC_FP2,            EXC_FPREGS+(2*12)       # offset of saved fp2 (not used)
 310
 311set FP_SCR1,            LV+80                   # fp scratch 1
 312set FP_SCR1_EX,         FP_SCR1+0
 313set FP_SCR1_SGN,        FP_SCR1+2
 314set FP_SCR1_HI,         FP_SCR1+4
 315set FP_SCR1_LO,         FP_SCR1+8
 316
 317set FP_SCR0,            LV+68                   # fp scratch 0
 318set FP_SCR0_EX,         FP_SCR0+0
 319set FP_SCR0_SGN,        FP_SCR0+2
 320set FP_SCR0_HI,         FP_SCR0+4
 321set FP_SCR0_LO,         FP_SCR0+8
 322
 323set FP_DST,             LV+56                   # fp destination operand
 324set FP_DST_EX,          FP_DST+0
 325set FP_DST_SGN,         FP_DST+2
 326set FP_DST_HI,          FP_DST+4
 327set FP_DST_LO,          FP_DST+8
 328
 329set FP_SRC,             LV+44                   # fp source operand
 330set FP_SRC_EX,          FP_SRC+0
 331set FP_SRC_SGN,         FP_SRC+2
 332set FP_SRC_HI,          FP_SRC+4
 333set FP_SRC_LO,          FP_SRC+8
 334
 335set USER_FPIAR,         LV+40                   # FP instr address register
 336
 337set USER_FPSR,          LV+36                   # FP status register
 338set FPSR_CC,            USER_FPSR+0             # FPSR condition codes
 339set FPSR_QBYTE,         USER_FPSR+1             # FPSR qoutient byte
 340set FPSR_EXCEPT,        USER_FPSR+2             # FPSR exception status byte
 341set FPSR_AEXCEPT,       USER_FPSR+3             # FPSR accrued exception byte
 342
 343set USER_FPCR,          LV+32                   # FP control register
 344set FPCR_ENABLE,        USER_FPCR+2             # FPCR exception enable
 345set FPCR_MODE,          USER_FPCR+3             # FPCR rounding mode control
 346
 347set L_SCR3,             LV+28                   # integer scratch 3
 348set L_SCR2,             LV+24                   # integer scratch 2
 349set L_SCR1,             LV+20                   # integer scratch 1
 350
 351set STORE_FLG,          LV+19                   # flag: operand store (ie. not fcmp/ftst)
 352
 353set EXC_TEMP2,          LV+24                   # temporary space
 354set EXC_TEMP,           LV+16                   # temporary space
 355
 356set DTAG,               LV+15                   # destination operand type
 357set STAG,               LV+14                   # source operand type
 358
 359set SPCOND_FLG,         LV+10                   # flag: special case (see below)
 360
 361set EXC_CC,             LV+8                    # saved condition codes
 362set EXC_EXTWPTR,        LV+4                    # saved current PC (active)
 363set EXC_EXTWORD,        LV+2                    # saved extension word
 364set EXC_CMDREG,         LV+2                    # saved extension word
 365set EXC_OPWORD,         LV+0                    # saved operation word
 366
 367################################
 368
 369# Helpful macros
 370
 371set FTEMP,              0                       # offsets within an
 372set FTEMP_EX,           0                       # extended precision
 373set FTEMP_SGN,          2                       # value saved in memory.
 374set FTEMP_HI,           4
 375set FTEMP_LO,           8
 376set FTEMP_GRS,          12
 377
 378set LOCAL,              0                       # offsets within an
 379set LOCAL_EX,           0                       # extended precision
 380set LOCAL_SGN,          2                       # value saved in memory.
 381set LOCAL_HI,           4
 382set LOCAL_LO,           8
 383set LOCAL_GRS,          12
 384
 385set DST,                0                       # offsets within an
 386set DST_EX,             0                       # extended precision
 387set DST_HI,             4                       # value saved in memory.
 388set DST_LO,             8
 389
 390set SRC,                0                       # offsets within an
 391set SRC_EX,             0                       # extended precision
 392set SRC_HI,             4                       # value saved in memory.
 393set SRC_LO,             8
 394
 395set SGL_LO,             0x3f81                  # min sgl prec exponent
 396set SGL_HI,             0x407e                  # max sgl prec exponent
 397set DBL_LO,             0x3c01                  # min dbl prec exponent
 398set DBL_HI,             0x43fe                  # max dbl prec exponent
 399set EXT_LO,             0x0                     # min ext prec exponent
 400set EXT_HI,             0x7ffe                  # max ext prec exponent
 401
 402set EXT_BIAS,           0x3fff                  # extended precision bias
 403set SGL_BIAS,           0x007f                  # single precision bias
 404set DBL_BIAS,           0x03ff                  # double precision bias
 405
 406set NORM,               0x00                    # operand type for STAG/DTAG
 407set ZERO,               0x01                    # operand type for STAG/DTAG
 408set INF,                0x02                    # operand type for STAG/DTAG
 409set QNAN,               0x03                    # operand type for STAG/DTAG
 410set DENORM,             0x04                    # operand type for STAG/DTAG
 411set SNAN,               0x05                    # operand type for STAG/DTAG
 412set UNNORM,             0x06                    # operand type for STAG/DTAG
 413
 414##################
 415# FPSR/FPCR bits #
 416##################
 417set neg_bit,            0x3                     # negative result
 418set z_bit,              0x2                     # zero result
 419set inf_bit,            0x1                     # infinite result
 420set nan_bit,            0x0                     # NAN result
 421
 422set q_sn_bit,           0x7                     # sign bit of quotient byte
 423
 424set bsun_bit,           7                       # branch on unordered
 425set snan_bit,           6                       # signalling NAN
 426set operr_bit,          5                       # operand error
 427set ovfl_bit,           4                       # overflow
 428set unfl_bit,           3                       # underflow
 429set dz_bit,             2                       # divide by zero
 430set inex2_bit,          1                       # inexact result 2
 431set inex1_bit,          0                       # inexact result 1
 432
 433set aiop_bit,           7                       # accrued inexact operation bit
 434set aovfl_bit,          6                       # accrued overflow bit
 435set aunfl_bit,          5                       # accrued underflow bit
 436set adz_bit,            4                       # accrued dz bit
 437set ainex_bit,          3                       # accrued inexact bit
 438
 439#############################
 440# FPSR individual bit masks #
 441#############################
 442set neg_mask,           0x08000000              # negative bit mask (lw)
 443set inf_mask,           0x02000000              # infinity bit mask (lw)
 444set z_mask,             0x04000000              # zero bit mask (lw)
 445set nan_mask,           0x01000000              # nan bit mask (lw)
 446
 447set neg_bmask,          0x08                    # negative bit mask (byte)
 448set inf_bmask,          0x02                    # infinity bit mask (byte)
 449set z_bmask,            0x04                    # zero bit mask (byte)
 450set nan_bmask,          0x01                    # nan bit mask (byte)
 451
 452set bsun_mask,          0x00008000              # bsun exception mask
 453set snan_mask,          0x00004000              # snan exception mask
 454set operr_mask,         0x00002000              # operr exception mask
 455set ovfl_mask,          0x00001000              # overflow exception mask
 456set unfl_mask,          0x00000800              # underflow exception mask
 457set dz_mask,            0x00000400              # dz exception mask
 458set inex2_mask,         0x00000200              # inex2 exception mask
 459set inex1_mask,         0x00000100              # inex1 exception mask
 460
 461set aiop_mask,          0x00000080              # accrued illegal operation
 462set aovfl_mask,         0x00000040              # accrued overflow
 463set aunfl_mask,         0x00000020              # accrued underflow
 464set adz_mask,           0x00000010              # accrued divide by zero
 465set ainex_mask,         0x00000008              # accrued inexact
 466
 467######################################
 468# FPSR combinations used in the FPSP #
 469######################################
 470set dzinf_mask,         inf_mask+dz_mask+adz_mask
 471set opnan_mask,         nan_mask+operr_mask+aiop_mask
 472set nzi_mask,           0x01ffffff              #clears N, Z, and I
 473set unfinx_mask,        unfl_mask+inex2_mask+aunfl_mask+ainex_mask
 474set unf2inx_mask,       unfl_mask+inex2_mask+ainex_mask
 475set ovfinx_mask,        ovfl_mask+inex2_mask+aovfl_mask+ainex_mask
 476set inx1a_mask,         inex1_mask+ainex_mask
 477set inx2a_mask,         inex2_mask+ainex_mask
 478set snaniop_mask,       nan_mask+snan_mask+aiop_mask
 479set snaniop2_mask,      snan_mask+aiop_mask
 480set naniop_mask,        nan_mask+aiop_mask
 481set neginf_mask,        neg_mask+inf_mask
 482set infaiop_mask,       inf_mask+aiop_mask
 483set negz_mask,          neg_mask+z_mask
 484set opaop_mask,         operr_mask+aiop_mask
 485set unfl_inx_mask,      unfl_mask+aunfl_mask+ainex_mask
 486set ovfl_inx_mask,      ovfl_mask+aovfl_mask+ainex_mask
 487
 488#########
 489# misc. #
 490#########
 491set rnd_stky_bit,       29                      # stky bit pos in longword
 492
 493set sign_bit,           0x7                     # sign bit
 494set signan_bit,         0x6                     # signalling nan bit
 495
 496set sgl_thresh,         0x3f81                  # minimum sgl exponent
 497set dbl_thresh,         0x3c01                  # minimum dbl exponent
 498
 499set x_mode,             0x0                     # extended precision
 500set s_mode,             0x4                     # single precision
 501set d_mode,             0x8                     # double precision
 502
 503set rn_mode,            0x0                     # round-to-nearest
 504set rz_mode,            0x1                     # round-to-zero
 505set rm_mode,            0x2                     # round-tp-minus-infinity
 506set rp_mode,            0x3                     # round-to-plus-infinity
 507
 508set mantissalen,        64                      # length of mantissa in bits
 509
 510set BYTE,               1                       # len(byte) == 1 byte
 511set WORD,               2                       # len(word) == 2 bytes
 512set LONG,               4                       # len(longword) == 2 bytes
 513
 514set BSUN_VEC,           0xc0                    # bsun    vector offset
 515set INEX_VEC,           0xc4                    # inexact vector offset
 516set DZ_VEC,             0xc8                    # dz      vector offset
 517set UNFL_VEC,           0xcc                    # unfl    vector offset
 518set OPERR_VEC,          0xd0                    # operr   vector offset
 519set OVFL_VEC,           0xd4                    # ovfl    vector offset
 520set SNAN_VEC,           0xd8                    # snan    vector offset
 521
 522###########################
 523# SPecial CONDition FLaGs #
 524###########################
 525set ftrapcc_flg,        0x01                    # flag bit: ftrapcc exception
 526set fbsun_flg,          0x02                    # flag bit: bsun exception
 527set mia7_flg,           0x04                    # flag bit: (a7)+ <ea>
 528set mda7_flg,           0x08                    # flag bit: -(a7) <ea>
 529set fmovm_flg,          0x40                    # flag bit: fmovm instruction
 530set immed_flg,          0x80                    # flag bit: &<data> <ea>
 531
 532set ftrapcc_bit,        0x0
 533set fbsun_bit,          0x1
 534set mia7_bit,           0x2
 535set mda7_bit,           0x3
 536set immed_bit,          0x7
 537
 538##################################
 539# TRANSCENDENTAL "LAST-OP" FLAGS #
 540##################################
 541set FMUL_OP,            0x0                     # fmul instr performed last
 542set FDIV_OP,            0x1                     # fdiv performed last
 543set FADD_OP,            0x2                     # fadd performed last
 544set FMOV_OP,            0x3                     # fmov performed last
 545
 546#############
 547# CONSTANTS #
 548#############
 549T1:     long            0x40C62D38,0xD3D64634   # 16381 LOG2 LEAD
 550T2:     long            0x3D6F90AE,0xB1E75CC7   # 16381 LOG2 TRAIL
 551
 552PI:     long            0x40000000,0xC90FDAA2,0x2168C235,0x00000000
 553PIBY2:  long            0x3FFF0000,0xC90FDAA2,0x2168C235,0x00000000
 554
 555TWOBYPI:
 556        long            0x3FE45F30,0x6DC9C883
 557
 558#########################################################################
 559# MONADIC TEMPLATE                                                      #
 560#########################################################################
 561        global          _fsins_
 562_fsins_:
 563        link            %a6,&-LOCAL_SIZE
 564
 565        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
 566        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
 567        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
 568
 569        fmov.l          &0x0,%fpcr              # zero FPCR
 570
 571#
 572#       copy, convert, and tag input argument
 573#
 574        fmov.s          0x8(%a6),%fp0           # load sgl input
 575        fmov.x          %fp0,FP_SRC(%a6)
 576        lea             FP_SRC(%a6),%a0
 577        bsr.l           tag                     # fetch operand type
 578        mov.b           %d0,STAG(%a6)
 579        mov.b           %d0,%d1
 580
 581        andi.l          &0x00ff00ff,USER_FPSR(%a6)
 582
 583        clr.l           %d0
 584        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
 585
 586        tst.b           %d1
 587        bne.b           _L0_2s
 588        bsr.l           ssin                    # operand is a NORM
 589        bra.b           _L0_6s
 590_L0_2s:
 591        cmpi.b          %d1,&ZERO               # is operand a ZERO?
 592        bne.b           _L0_3s                  # no
 593        bsr.l           src_zero                        # yes
 594        bra.b           _L0_6s
 595_L0_3s:
 596        cmpi.b          %d1,&INF                # is operand an INF?
 597        bne.b           _L0_4s                  # no
 598        bsr.l           t_operr                 # yes
 599        bra.b           _L0_6s
 600_L0_4s:
 601        cmpi.b          %d1,&QNAN               # is operand a QNAN?
 602        bne.b           _L0_5s                  # no
 603        bsr.l           src_qnan                        # yes
 604        bra.b           _L0_6s
 605_L0_5s:
 606        bsr.l           ssind                   # operand is a DENORM
 607_L0_6s:
 608
 609#
 610#       Result is now in FP0
 611#
 612        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
 613        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
 614        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
 615        unlk            %a6
 616        rts
 617
 618        global          _fsind_
 619_fsind_:
 620        link            %a6,&-LOCAL_SIZE
 621
 622        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
 623        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
 624        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
 625
 626        fmov.l          &0x0,%fpcr              # zero FPCR
 627
 628#
 629#       copy, convert, and tag input argument
 630#
 631        fmov.d          0x8(%a6),%fp0           # load dbl input
 632        fmov.x          %fp0,FP_SRC(%a6)
 633        lea             FP_SRC(%a6),%a0
 634        bsr.l           tag                     # fetch operand type
 635        mov.b           %d0,STAG(%a6)
 636        mov.b           %d0,%d1
 637
 638        andi.l          &0x00ff00ff,USER_FPSR(%a6)
 639
 640        clr.l           %d0
 641        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
 642
 643        mov.b           %d1,STAG(%a6)
 644        tst.b           %d1
 645        bne.b           _L0_2d
 646        bsr.l           ssin                    # operand is a NORM
 647        bra.b           _L0_6d
 648_L0_2d:
 649        cmpi.b          %d1,&ZERO               # is operand a ZERO?
 650        bne.b           _L0_3d                  # no
 651        bsr.l           src_zero                        # yes
 652        bra.b           _L0_6d
 653_L0_3d:
 654        cmpi.b          %d1,&INF                # is operand an INF?
 655        bne.b           _L0_4d                  # no
 656        bsr.l           t_operr                 # yes
 657        bra.b           _L0_6d
 658_L0_4d:
 659        cmpi.b          %d1,&QNAN               # is operand a QNAN?
 660        bne.b           _L0_5d                  # no
 661        bsr.l           src_qnan                        # yes
 662        bra.b           _L0_6d
 663_L0_5d:
 664        bsr.l           ssind                   # operand is a DENORM
 665_L0_6d:
 666
 667#
 668#       Result is now in FP0
 669#
 670        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
 671        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
 672        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
 673        unlk            %a6
 674        rts
 675
 676        global          _fsinx_
 677_fsinx_:
 678        link            %a6,&-LOCAL_SIZE
 679
 680        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
 681        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
 682        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
 683
 684        fmov.l          &0x0,%fpcr              # zero FPCR
 685
 686#
 687#       copy, convert, and tag input argument
 688#
 689        lea             FP_SRC(%a6),%a0
 690        mov.l           0x8+0x0(%a6),0x0(%a0)   # load ext input
 691        mov.l           0x8+0x4(%a6),0x4(%a0)
 692        mov.l           0x8+0x8(%a6),0x8(%a0)
 693        bsr.l           tag                     # fetch operand type
 694        mov.b           %d0,STAG(%a6)
 695        mov.b           %d0,%d1
 696
 697        andi.l          &0x00ff00ff,USER_FPSR(%a6)
 698
 699        clr.l           %d0
 700        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
 701
 702        tst.b           %d1
 703        bne.b           _L0_2x
 704        bsr.l           ssin                    # operand is a NORM
 705        bra.b           _L0_6x
 706_L0_2x:
 707        cmpi.b          %d1,&ZERO               # is operand a ZERO?
 708        bne.b           _L0_3x                  # no
 709        bsr.l           src_zero                        # yes
 710        bra.b           _L0_6x
 711_L0_3x:
 712        cmpi.b          %d1,&INF                # is operand an INF?
 713        bne.b           _L0_4x                  # no
 714        bsr.l           t_operr                 # yes
 715        bra.b           _L0_6x
 716_L0_4x:
 717        cmpi.b          %d1,&QNAN               # is operand a QNAN?
 718        bne.b           _L0_5x                  # no
 719        bsr.l           src_qnan                        # yes
 720        bra.b           _L0_6x
 721_L0_5x:
 722        bsr.l           ssind                   # operand is a DENORM
 723_L0_6x:
 724
 725#
 726#       Result is now in FP0
 727#
 728        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
 729        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
 730        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
 731        unlk            %a6
 732        rts
 733
 734
 735#########################################################################
 736# MONADIC TEMPLATE                                                      #
 737#########################################################################
 738        global          _fcoss_
 739_fcoss_:
 740        link            %a6,&-LOCAL_SIZE
 741
 742        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
 743        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
 744        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
 745
 746        fmov.l          &0x0,%fpcr              # zero FPCR
 747
 748#
 749#       copy, convert, and tag input argument
 750#
 751        fmov.s          0x8(%a6),%fp0           # load sgl input
 752        fmov.x          %fp0,FP_SRC(%a6)
 753        lea             FP_SRC(%a6),%a0
 754        bsr.l           tag                     # fetch operand type
 755        mov.b           %d0,STAG(%a6)
 756        mov.b           %d0,%d1
 757
 758        andi.l          &0x00ff00ff,USER_FPSR(%a6)
 759
 760        clr.l           %d0
 761        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
 762
 763        tst.b           %d1
 764        bne.b           _L1_2s
 765        bsr.l           scos                    # operand is a NORM
 766        bra.b           _L1_6s
 767_L1_2s:
 768        cmpi.b          %d1,&ZERO               # is operand a ZERO?
 769        bne.b           _L1_3s                  # no
 770        bsr.l           ld_pone                 # yes
 771        bra.b           _L1_6s
 772_L1_3s:
 773        cmpi.b          %d1,&INF                # is operand an INF?
 774        bne.b           _L1_4s                  # no
 775        bsr.l           t_operr                 # yes
 776        bra.b           _L1_6s
 777_L1_4s:
 778        cmpi.b          %d1,&QNAN               # is operand a QNAN?
 779        bne.b           _L1_5s                  # no
 780        bsr.l           src_qnan                        # yes
 781        bra.b           _L1_6s
 782_L1_5s:
 783        bsr.l           scosd                   # operand is a DENORM
 784_L1_6s:
 785
 786#
 787#       Result is now in FP0
 788#
 789        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
 790        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
 791        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
 792        unlk            %a6
 793        rts
 794
 795        global          _fcosd_
 796_fcosd_:
 797        link            %a6,&-LOCAL_SIZE
 798
 799        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
 800        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
 801        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
 802
 803        fmov.l          &0x0,%fpcr              # zero FPCR
 804
 805#
 806#       copy, convert, and tag input argument
 807#
 808        fmov.d          0x8(%a6),%fp0           # load dbl input
 809        fmov.x          %fp0,FP_SRC(%a6)
 810        lea             FP_SRC(%a6),%a0
 811        bsr.l           tag                     # fetch operand type
 812        mov.b           %d0,STAG(%a6)
 813        mov.b           %d0,%d1
 814
 815        andi.l          &0x00ff00ff,USER_FPSR(%a6)
 816
 817        clr.l           %d0
 818        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
 819
 820        mov.b           %d1,STAG(%a6)
 821        tst.b           %d1
 822        bne.b           _L1_2d
 823        bsr.l           scos                    # operand is a NORM
 824        bra.b           _L1_6d
 825_L1_2d:
 826        cmpi.b          %d1,&ZERO               # is operand a ZERO?
 827        bne.b           _L1_3d                  # no
 828        bsr.l           ld_pone                 # yes
 829        bra.b           _L1_6d
 830_L1_3d:
 831        cmpi.b          %d1,&INF                # is operand an INF?
 832        bne.b           _L1_4d                  # no
 833        bsr.l           t_operr                 # yes
 834        bra.b           _L1_6d
 835_L1_4d:
 836        cmpi.b          %d1,&QNAN               # is operand a QNAN?
 837        bne.b           _L1_5d                  # no
 838        bsr.l           src_qnan                        # yes
 839        bra.b           _L1_6d
 840_L1_5d:
 841        bsr.l           scosd                   # operand is a DENORM
 842_L1_6d:
 843
 844#
 845#       Result is now in FP0
 846#
 847        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
 848        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
 849        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
 850        unlk            %a6
 851        rts
 852
 853        global          _fcosx_
 854_fcosx_:
 855        link            %a6,&-LOCAL_SIZE
 856
 857        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
 858        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
 859        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
 860
 861        fmov.l          &0x0,%fpcr              # zero FPCR
 862
 863#
 864#       copy, convert, and tag input argument
 865#
 866        lea             FP_SRC(%a6),%a0
 867        mov.l           0x8+0x0(%a6),0x0(%a0)   # load ext input
 868        mov.l           0x8+0x4(%a6),0x4(%a0)
 869        mov.l           0x8+0x8(%a6),0x8(%a0)
 870        bsr.l           tag                     # fetch operand type
 871        mov.b           %d0,STAG(%a6)
 872        mov.b           %d0,%d1
 873
 874        andi.l          &0x00ff00ff,USER_FPSR(%a6)
 875
 876        clr.l           %d0
 877        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
 878
 879        tst.b           %d1
 880        bne.b           _L1_2x
 881        bsr.l           scos                    # operand is a NORM
 882        bra.b           _L1_6x
 883_L1_2x:
 884        cmpi.b          %d1,&ZERO               # is operand a ZERO?
 885        bne.b           _L1_3x                  # no
 886        bsr.l           ld_pone                 # yes
 887        bra.b           _L1_6x
 888_L1_3x:
 889        cmpi.b          %d1,&INF                # is operand an INF?
 890        bne.b           _L1_4x                  # no
 891        bsr.l           t_operr                 # yes
 892        bra.b           _L1_6x
 893_L1_4x:
 894        cmpi.b          %d1,&QNAN               # is operand a QNAN?
 895        bne.b           _L1_5x                  # no
 896        bsr.l           src_qnan                        # yes
 897        bra.b           _L1_6x
 898_L1_5x:
 899        bsr.l           scosd                   # operand is a DENORM
 900_L1_6x:
 901
 902#
 903#       Result is now in FP0
 904#
 905        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
 906        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
 907        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
 908        unlk            %a6
 909        rts
 910
 911
 912#########################################################################
 913# MONADIC TEMPLATE                                                      #
 914#########################################################################
 915        global          _fsinhs_
 916_fsinhs_:
 917        link            %a6,&-LOCAL_SIZE
 918
 919        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
 920        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
 921        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
 922
 923        fmov.l          &0x0,%fpcr              # zero FPCR
 924
 925#
 926#       copy, convert, and tag input argument
 927#
 928        fmov.s          0x8(%a6),%fp0           # load sgl input
 929        fmov.x          %fp0,FP_SRC(%a6)
 930        lea             FP_SRC(%a6),%a0
 931        bsr.l           tag                     # fetch operand type
 932        mov.b           %d0,STAG(%a6)
 933        mov.b           %d0,%d1
 934
 935        andi.l          &0x00ff00ff,USER_FPSR(%a6)
 936
 937        clr.l           %d0
 938        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
 939
 940        tst.b           %d1
 941        bne.b           _L2_2s
 942        bsr.l           ssinh                   # operand is a NORM
 943        bra.b           _L2_6s
 944_L2_2s:
 945        cmpi.b          %d1,&ZERO               # is operand a ZERO?
 946        bne.b           _L2_3s                  # no
 947        bsr.l           src_zero                        # yes
 948        bra.b           _L2_6s
 949_L2_3s:
 950        cmpi.b          %d1,&INF                # is operand an INF?
 951        bne.b           _L2_4s                  # no
 952        bsr.l           src_inf                 # yes
 953        bra.b           _L2_6s
 954_L2_4s:
 955        cmpi.b          %d1,&QNAN               # is operand a QNAN?
 956        bne.b           _L2_5s                  # no
 957        bsr.l           src_qnan                        # yes
 958        bra.b           _L2_6s
 959_L2_5s:
 960        bsr.l           ssinhd                  # operand is a DENORM
 961_L2_6s:
 962
 963#
 964#       Result is now in FP0
 965#
 966        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
 967        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
 968        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
 969        unlk            %a6
 970        rts
 971
 972        global          _fsinhd_
 973_fsinhd_:
 974        link            %a6,&-LOCAL_SIZE
 975
 976        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
 977        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
 978        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
 979
 980        fmov.l          &0x0,%fpcr              # zero FPCR
 981
 982#
 983#       copy, convert, and tag input argument
 984#
 985        fmov.d          0x8(%a6),%fp0           # load dbl input
 986        fmov.x          %fp0,FP_SRC(%a6)
 987        lea             FP_SRC(%a6),%a0
 988        bsr.l           tag                     # fetch operand type
 989        mov.b           %d0,STAG(%a6)
 990        mov.b           %d0,%d1
 991
 992        andi.l          &0x00ff00ff,USER_FPSR(%a6)
 993
 994        clr.l           %d0
 995        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
 996
 997        mov.b           %d1,STAG(%a6)
 998        tst.b           %d1
 999        bne.b           _L2_2d
1000        bsr.l           ssinh                   # operand is a NORM
1001        bra.b           _L2_6d
1002_L2_2d:
1003        cmpi.b          %d1,&ZERO               # is operand a ZERO?
1004        bne.b           _L2_3d                  # no
1005        bsr.l           src_zero                        # yes
1006        bra.b           _L2_6d
1007_L2_3d:
1008        cmpi.b          %d1,&INF                # is operand an INF?
1009        bne.b           _L2_4d                  # no
1010        bsr.l           src_inf                 # yes
1011        bra.b           _L2_6d
1012_L2_4d:
1013        cmpi.b          %d1,&QNAN               # is operand a QNAN?
1014        bne.b           _L2_5d                  # no
1015        bsr.l           src_qnan                        # yes
1016        bra.b           _L2_6d
1017_L2_5d:
1018        bsr.l           ssinhd                  # operand is a DENORM
1019_L2_6d:
1020
1021#
1022#       Result is now in FP0
1023#
1024        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
1025        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1026        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
1027        unlk            %a6
1028        rts
1029
1030        global          _fsinhx_
1031_fsinhx_:
1032        link            %a6,&-LOCAL_SIZE
1033
1034        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
1035        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1036        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
1037
1038        fmov.l          &0x0,%fpcr              # zero FPCR
1039
1040#
1041#       copy, convert, and tag input argument
1042#
1043        lea             FP_SRC(%a6),%a0
1044        mov.l           0x8+0x0(%a6),0x0(%a0)   # load ext input
1045        mov.l           0x8+0x4(%a6),0x4(%a0)
1046        mov.l           0x8+0x8(%a6),0x8(%a0)
1047        bsr.l           tag                     # fetch operand type
1048        mov.b           %d0,STAG(%a6)
1049        mov.b           %d0,%d1
1050
1051        andi.l          &0x00ff00ff,USER_FPSR(%a6)
1052
1053        clr.l           %d0
1054        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
1055
1056        tst.b           %d1
1057        bne.b           _L2_2x
1058        bsr.l           ssinh                   # operand is a NORM
1059        bra.b           _L2_6x
1060_L2_2x:
1061        cmpi.b          %d1,&ZERO               # is operand a ZERO?
1062        bne.b           _L2_3x                  # no
1063        bsr.l           src_zero                        # yes
1064        bra.b           _L2_6x
1065_L2_3x:
1066        cmpi.b          %d1,&INF                # is operand an INF?
1067        bne.b           _L2_4x                  # no
1068        bsr.l           src_inf                 # yes
1069        bra.b           _L2_6x
1070_L2_4x:
1071        cmpi.b          %d1,&QNAN               # is operand a QNAN?
1072        bne.b           _L2_5x                  # no
1073        bsr.l           src_qnan                        # yes
1074        bra.b           _L2_6x
1075_L2_5x:
1076        bsr.l           ssinhd                  # operand is a DENORM
1077_L2_6x:
1078
1079#
1080#       Result is now in FP0
1081#
1082        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
1083        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1084        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
1085        unlk            %a6
1086        rts
1087
1088
1089#########################################################################
1090# MONADIC TEMPLATE                                                      #
1091#########################################################################
1092        global          _flognp1s_
1093_flognp1s_:
1094        link            %a6,&-LOCAL_SIZE
1095
1096        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
1097        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1098        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
1099
1100        fmov.l          &0x0,%fpcr              # zero FPCR
1101
1102#
1103#       copy, convert, and tag input argument
1104#
1105        fmov.s          0x8(%a6),%fp0           # load sgl input
1106        fmov.x          %fp0,FP_SRC(%a6)
1107        lea             FP_SRC(%a6),%a0
1108        bsr.l           tag                     # fetch operand type
1109        mov.b           %d0,STAG(%a6)
1110        mov.b           %d0,%d1
1111
1112        andi.l          &0x00ff00ff,USER_FPSR(%a6)
1113
1114        clr.l           %d0
1115        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
1116
1117        tst.b           %d1
1118        bne.b           _L3_2s
1119        bsr.l           slognp1                 # operand is a NORM
1120        bra.b           _L3_6s
1121_L3_2s:
1122        cmpi.b          %d1,&ZERO               # is operand a ZERO?
1123        bne.b           _L3_3s                  # no
1124        bsr.l           src_zero                        # yes
1125        bra.b           _L3_6s
1126_L3_3s:
1127        cmpi.b          %d1,&INF                # is operand an INF?
1128        bne.b           _L3_4s                  # no
1129        bsr.l           sopr_inf                        # yes
1130        bra.b           _L3_6s
1131_L3_4s:
1132        cmpi.b          %d1,&QNAN               # is operand a QNAN?
1133        bne.b           _L3_5s                  # no
1134        bsr.l           src_qnan                        # yes
1135        bra.b           _L3_6s
1136_L3_5s:
1137        bsr.l           slognp1d                        # operand is a DENORM
1138_L3_6s:
1139
1140#
1141#       Result is now in FP0
1142#
1143        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
1144        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1145        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
1146        unlk            %a6
1147        rts
1148
1149        global          _flognp1d_
1150_flognp1d_:
1151        link            %a6,&-LOCAL_SIZE
1152
1153        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
1154        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1155        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
1156
1157        fmov.l          &0x0,%fpcr              # zero FPCR
1158
1159#
1160#       copy, convert, and tag input argument
1161#
1162        fmov.d          0x8(%a6),%fp0           # load dbl input
1163        fmov.x          %fp0,FP_SRC(%a6)
1164        lea             FP_SRC(%a6),%a0
1165        bsr.l           tag                     # fetch operand type
1166        mov.b           %d0,STAG(%a6)
1167        mov.b           %d0,%d1
1168
1169        andi.l          &0x00ff00ff,USER_FPSR(%a6)
1170
1171        clr.l           %d0
1172        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
1173
1174        mov.b           %d1,STAG(%a6)
1175        tst.b           %d1
1176        bne.b           _L3_2d
1177        bsr.l           slognp1                 # operand is a NORM
1178        bra.b           _L3_6d
1179_L3_2d:
1180        cmpi.b          %d1,&ZERO               # is operand a ZERO?
1181        bne.b           _L3_3d                  # no
1182        bsr.l           src_zero                        # yes
1183        bra.b           _L3_6d
1184_L3_3d:
1185        cmpi.b          %d1,&INF                # is operand an INF?
1186        bne.b           _L3_4d                  # no
1187        bsr.l           sopr_inf                        # yes
1188        bra.b           _L3_6d
1189_L3_4d:
1190        cmpi.b          %d1,&QNAN               # is operand a QNAN?
1191        bne.b           _L3_5d                  # no
1192        bsr.l           src_qnan                        # yes
1193        bra.b           _L3_6d
1194_L3_5d:
1195        bsr.l           slognp1d                        # operand is a DENORM
1196_L3_6d:
1197
1198#
1199#       Result is now in FP0
1200#
1201        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
1202        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1203        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
1204        unlk            %a6
1205        rts
1206
1207        global          _flognp1x_
1208_flognp1x_:
1209        link            %a6,&-LOCAL_SIZE
1210
1211        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
1212        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1213        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
1214
1215        fmov.l          &0x0,%fpcr              # zero FPCR
1216
1217#
1218#       copy, convert, and tag input argument
1219#
1220        lea             FP_SRC(%a6),%a0
1221        mov.l           0x8+0x0(%a6),0x0(%a0)   # load ext input
1222        mov.l           0x8+0x4(%a6),0x4(%a0)
1223        mov.l           0x8+0x8(%a6),0x8(%a0)
1224        bsr.l           tag                     # fetch operand type
1225        mov.b           %d0,STAG(%a6)
1226        mov.b           %d0,%d1
1227
1228        andi.l          &0x00ff00ff,USER_FPSR(%a6)
1229
1230        clr.l           %d0
1231        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
1232
1233        tst.b           %d1
1234        bne.b           _L3_2x
1235        bsr.l           slognp1                 # operand is a NORM
1236        bra.b           _L3_6x
1237_L3_2x:
1238        cmpi.b          %d1,&ZERO               # is operand a ZERO?
1239        bne.b           _L3_3x                  # no
1240        bsr.l           src_zero                        # yes
1241        bra.b           _L3_6x
1242_L3_3x:
1243        cmpi.b          %d1,&INF                # is operand an INF?
1244        bne.b           _L3_4x                  # no
1245        bsr.l           sopr_inf                        # yes
1246        bra.b           _L3_6x
1247_L3_4x:
1248        cmpi.b          %d1,&QNAN               # is operand a QNAN?
1249        bne.b           _L3_5x                  # no
1250        bsr.l           src_qnan                        # yes
1251        bra.b           _L3_6x
1252_L3_5x:
1253        bsr.l           slognp1d                        # operand is a DENORM
1254_L3_6x:
1255
1256#
1257#       Result is now in FP0
1258#
1259        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
1260        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1261        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
1262        unlk            %a6
1263        rts
1264
1265
1266#########################################################################
1267# MONADIC TEMPLATE                                                      #
1268#########################################################################
1269        global          _fetoxm1s_
1270_fetoxm1s_:
1271        link            %a6,&-LOCAL_SIZE
1272
1273        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
1274        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1275        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
1276
1277        fmov.l          &0x0,%fpcr              # zero FPCR
1278
1279#
1280#       copy, convert, and tag input argument
1281#
1282        fmov.s          0x8(%a6),%fp0           # load sgl input
1283        fmov.x          %fp0,FP_SRC(%a6)
1284        lea             FP_SRC(%a6),%a0
1285        bsr.l           tag                     # fetch operand type
1286        mov.b           %d0,STAG(%a6)
1287        mov.b           %d0,%d1
1288
1289        andi.l          &0x00ff00ff,USER_FPSR(%a6)
1290
1291        clr.l           %d0
1292        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
1293
1294        tst.b           %d1
1295        bne.b           _L4_2s
1296        bsr.l           setoxm1                 # operand is a NORM
1297        bra.b           _L4_6s
1298_L4_2s:
1299        cmpi.b          %d1,&ZERO               # is operand a ZERO?
1300        bne.b           _L4_3s                  # no
1301        bsr.l           src_zero                        # yes
1302        bra.b           _L4_6s
1303_L4_3s:
1304        cmpi.b          %d1,&INF                # is operand an INF?
1305        bne.b           _L4_4s                  # no
1306        bsr.l           setoxm1i                        # yes
1307        bra.b           _L4_6s
1308_L4_4s:
1309        cmpi.b          %d1,&QNAN               # is operand a QNAN?
1310        bne.b           _L4_5s                  # no
1311        bsr.l           src_qnan                        # yes
1312        bra.b           _L4_6s
1313_L4_5s:
1314        bsr.l           setoxm1d                        # operand is a DENORM
1315_L4_6s:
1316
1317#
1318#       Result is now in FP0
1319#
1320        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
1321        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1322        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
1323        unlk            %a6
1324        rts
1325
1326        global          _fetoxm1d_
1327_fetoxm1d_:
1328        link            %a6,&-LOCAL_SIZE
1329
1330        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
1331        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1332        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
1333
1334        fmov.l          &0x0,%fpcr              # zero FPCR
1335
1336#
1337#       copy, convert, and tag input argument
1338#
1339        fmov.d          0x8(%a6),%fp0           # load dbl input
1340        fmov.x          %fp0,FP_SRC(%a6)
1341        lea             FP_SRC(%a6),%a0
1342        bsr.l           tag                     # fetch operand type
1343        mov.b           %d0,STAG(%a6)
1344        mov.b           %d0,%d1
1345
1346        andi.l          &0x00ff00ff,USER_FPSR(%a6)
1347
1348        clr.l           %d0
1349        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
1350
1351        mov.b           %d1,STAG(%a6)
1352        tst.b           %d1
1353        bne.b           _L4_2d
1354        bsr.l           setoxm1                 # operand is a NORM
1355        bra.b           _L4_6d
1356_L4_2d:
1357        cmpi.b          %d1,&ZERO               # is operand a ZERO?
1358        bne.b           _L4_3d                  # no
1359        bsr.l           src_zero                        # yes
1360        bra.b           _L4_6d
1361_L4_3d:
1362        cmpi.b          %d1,&INF                # is operand an INF?
1363        bne.b           _L4_4d                  # no
1364        bsr.l           setoxm1i                        # yes
1365        bra.b           _L4_6d
1366_L4_4d:
1367        cmpi.b          %d1,&QNAN               # is operand a QNAN?
1368        bne.b           _L4_5d                  # no
1369        bsr.l           src_qnan                        # yes
1370        bra.b           _L4_6d
1371_L4_5d:
1372        bsr.l           setoxm1d                        # operand is a DENORM
1373_L4_6d:
1374
1375#
1376#       Result is now in FP0
1377#
1378        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
1379        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1380        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
1381        unlk            %a6
1382        rts
1383
1384        global          _fetoxm1x_
1385_fetoxm1x_:
1386        link            %a6,&-LOCAL_SIZE
1387
1388        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
1389        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1390        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
1391
1392        fmov.l          &0x0,%fpcr              # zero FPCR
1393
1394#
1395#       copy, convert, and tag input argument
1396#
1397        lea             FP_SRC(%a6),%a0
1398        mov.l           0x8+0x0(%a6),0x0(%a0)   # load ext input
1399        mov.l           0x8+0x4(%a6),0x4(%a0)
1400        mov.l           0x8+0x8(%a6),0x8(%a0)
1401        bsr.l           tag                     # fetch operand type
1402        mov.b           %d0,STAG(%a6)
1403        mov.b           %d0,%d1
1404
1405        andi.l          &0x00ff00ff,USER_FPSR(%a6)
1406
1407        clr.l           %d0
1408        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
1409
1410        tst.b           %d1
1411        bne.b           _L4_2x
1412        bsr.l           setoxm1                 # operand is a NORM
1413        bra.b           _L4_6x
1414_L4_2x:
1415        cmpi.b          %d1,&ZERO               # is operand a ZERO?
1416        bne.b           _L4_3x                  # no
1417        bsr.l           src_zero                        # yes
1418        bra.b           _L4_6x
1419_L4_3x:
1420        cmpi.b          %d1,&INF                # is operand an INF?
1421        bne.b           _L4_4x                  # no
1422        bsr.l           setoxm1i                        # yes
1423        bra.b           _L4_6x
1424_L4_4x:
1425        cmpi.b          %d1,&QNAN               # is operand a QNAN?
1426        bne.b           _L4_5x                  # no
1427        bsr.l           src_qnan                        # yes
1428        bra.b           _L4_6x
1429_L4_5x:
1430        bsr.l           setoxm1d                        # operand is a DENORM
1431_L4_6x:
1432
1433#
1434#       Result is now in FP0
1435#
1436        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
1437        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1438        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
1439        unlk            %a6
1440        rts
1441
1442
1443#########################################################################
1444# MONADIC TEMPLATE                                                      #
1445#########################################################################
1446        global          _ftanhs_
1447_ftanhs_:
1448        link            %a6,&-LOCAL_SIZE
1449
1450        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
1451        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1452        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
1453
1454        fmov.l          &0x0,%fpcr              # zero FPCR
1455
1456#
1457#       copy, convert, and tag input argument
1458#
1459        fmov.s          0x8(%a6),%fp0           # load sgl input
1460        fmov.x          %fp0,FP_SRC(%a6)
1461        lea             FP_SRC(%a6),%a0
1462        bsr.l           tag                     # fetch operand type
1463        mov.b           %d0,STAG(%a6)
1464        mov.b           %d0,%d1
1465
1466        andi.l          &0x00ff00ff,USER_FPSR(%a6)
1467
1468        clr.l           %d0
1469        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
1470
1471        tst.b           %d1
1472        bne.b           _L5_2s
1473        bsr.l           stanh                   # operand is a NORM
1474        bra.b           _L5_6s
1475_L5_2s:
1476        cmpi.b          %d1,&ZERO               # is operand a ZERO?
1477        bne.b           _L5_3s                  # no
1478        bsr.l           src_zero                        # yes
1479        bra.b           _L5_6s
1480_L5_3s:
1481        cmpi.b          %d1,&INF                # is operand an INF?
1482        bne.b           _L5_4s                  # no
1483        bsr.l           src_one                 # yes
1484        bra.b           _L5_6s
1485_L5_4s:
1486        cmpi.b          %d1,&QNAN               # is operand a QNAN?
1487        bne.b           _L5_5s                  # no
1488        bsr.l           src_qnan                        # yes
1489        bra.b           _L5_6s
1490_L5_5s:
1491        bsr.l           stanhd                  # operand is a DENORM
1492_L5_6s:
1493
1494#
1495#       Result is now in FP0
1496#
1497        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
1498        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1499        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
1500        unlk            %a6
1501        rts
1502
1503        global          _ftanhd_
1504_ftanhd_:
1505        link            %a6,&-LOCAL_SIZE
1506
1507        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
1508        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1509        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
1510
1511        fmov.l          &0x0,%fpcr              # zero FPCR
1512
1513#
1514#       copy, convert, and tag input argument
1515#
1516        fmov.d          0x8(%a6),%fp0           # load dbl input
1517        fmov.x          %fp0,FP_SRC(%a6)
1518        lea             FP_SRC(%a6),%a0
1519        bsr.l           tag                     # fetch operand type
1520        mov.b           %d0,STAG(%a6)
1521        mov.b           %d0,%d1
1522
1523        andi.l          &0x00ff00ff,USER_FPSR(%a6)
1524
1525        clr.l           %d0
1526        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
1527
1528        mov.b           %d1,STAG(%a6)
1529        tst.b           %d1
1530        bne.b           _L5_2d
1531        bsr.l           stanh                   # operand is a NORM
1532        bra.b           _L5_6d
1533_L5_2d:
1534        cmpi.b          %d1,&ZERO               # is operand a ZERO?
1535        bne.b           _L5_3d                  # no
1536        bsr.l           src_zero                        # yes
1537        bra.b           _L5_6d
1538_L5_3d:
1539        cmpi.b          %d1,&INF                # is operand an INF?
1540        bne.b           _L5_4d                  # no
1541        bsr.l           src_one                 # yes
1542        bra.b           _L5_6d
1543_L5_4d:
1544        cmpi.b          %d1,&QNAN               # is operand a QNAN?
1545        bne.b           _L5_5d                  # no
1546        bsr.l           src_qnan                        # yes
1547        bra.b           _L5_6d
1548_L5_5d:
1549        bsr.l           stanhd                  # operand is a DENORM
1550_L5_6d:
1551
1552#
1553#       Result is now in FP0
1554#
1555        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
1556        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1557        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
1558        unlk            %a6
1559        rts
1560
1561        global          _ftanhx_
1562_ftanhx_:
1563        link            %a6,&-LOCAL_SIZE
1564
1565        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
1566        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1567        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
1568
1569        fmov.l          &0x0,%fpcr              # zero FPCR
1570
1571#
1572#       copy, convert, and tag input argument
1573#
1574        lea             FP_SRC(%a6),%a0
1575        mov.l           0x8+0x0(%a6),0x0(%a0)   # load ext input
1576        mov.l           0x8+0x4(%a6),0x4(%a0)
1577        mov.l           0x8+0x8(%a6),0x8(%a0)
1578        bsr.l           tag                     # fetch operand type
1579        mov.b           %d0,STAG(%a6)
1580        mov.b           %d0,%d1
1581
1582        andi.l          &0x00ff00ff,USER_FPSR(%a6)
1583
1584        clr.l           %d0
1585        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
1586
1587        tst.b           %d1
1588        bne.b           _L5_2x
1589        bsr.l           stanh                   # operand is a NORM
1590        bra.b           _L5_6x
1591_L5_2x:
1592        cmpi.b          %d1,&ZERO               # is operand a ZERO?
1593        bne.b           _L5_3x                  # no
1594        bsr.l           src_zero                        # yes
1595        bra.b           _L5_6x
1596_L5_3x:
1597        cmpi.b          %d1,&INF                # is operand an INF?
1598        bne.b           _L5_4x                  # no
1599        bsr.l           src_one                 # yes
1600        bra.b           _L5_6x
1601_L5_4x:
1602        cmpi.b          %d1,&QNAN               # is operand a QNAN?
1603        bne.b           _L5_5x                  # no
1604        bsr.l           src_qnan                        # yes
1605        bra.b           _L5_6x
1606_L5_5x:
1607        bsr.l           stanhd                  # operand is a DENORM
1608_L5_6x:
1609
1610#
1611#       Result is now in FP0
1612#
1613        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
1614        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1615        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
1616        unlk            %a6
1617        rts
1618
1619
1620#########################################################################
1621# MONADIC TEMPLATE                                                      #
1622#########################################################################
1623        global          _fatans_
1624_fatans_:
1625        link            %a6,&-LOCAL_SIZE
1626
1627        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
1628        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1629        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
1630
1631        fmov.l          &0x0,%fpcr              # zero FPCR
1632
1633#
1634#       copy, convert, and tag input argument
1635#
1636        fmov.s          0x8(%a6),%fp0           # load sgl input
1637        fmov.x          %fp0,FP_SRC(%a6)
1638        lea             FP_SRC(%a6),%a0
1639        bsr.l           tag                     # fetch operand type
1640        mov.b           %d0,STAG(%a6)
1641        mov.b           %d0,%d1
1642
1643        andi.l          &0x00ff00ff,USER_FPSR(%a6)
1644
1645        clr.l           %d0
1646        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
1647
1648        tst.b           %d1
1649        bne.b           _L6_2s
1650        bsr.l           satan                   # operand is a NORM
1651        bra.b           _L6_6s
1652_L6_2s:
1653        cmpi.b          %d1,&ZERO               # is operand a ZERO?
1654        bne.b           _L6_3s                  # no
1655        bsr.l           src_zero                        # yes
1656        bra.b           _L6_6s
1657_L6_3s:
1658        cmpi.b          %d1,&INF                # is operand an INF?
1659        bne.b           _L6_4s                  # no
1660        bsr.l           spi_2                   # yes
1661        bra.b           _L6_6s
1662_L6_4s:
1663        cmpi.b          %d1,&QNAN               # is operand a QNAN?
1664        bne.b           _L6_5s                  # no
1665        bsr.l           src_qnan                        # yes
1666        bra.b           _L6_6s
1667_L6_5s:
1668        bsr.l           satand                  # operand is a DENORM
1669_L6_6s:
1670
1671#
1672#       Result is now in FP0
1673#
1674        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
1675        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1676        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
1677        unlk            %a6
1678        rts
1679
1680        global          _fatand_
1681_fatand_:
1682        link            %a6,&-LOCAL_SIZE
1683
1684        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
1685        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1686        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
1687
1688        fmov.l          &0x0,%fpcr              # zero FPCR
1689
1690#
1691#       copy, convert, and tag input argument
1692#
1693        fmov.d          0x8(%a6),%fp0           # load dbl input
1694        fmov.x          %fp0,FP_SRC(%a6)
1695        lea             FP_SRC(%a6),%a0
1696        bsr.l           tag                     # fetch operand type
1697        mov.b           %d0,STAG(%a6)
1698        mov.b           %d0,%d1
1699
1700        andi.l          &0x00ff00ff,USER_FPSR(%a6)
1701
1702        clr.l           %d0
1703        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
1704
1705        mov.b           %d1,STAG(%a6)
1706        tst.b           %d1
1707        bne.b           _L6_2d
1708        bsr.l           satan                   # operand is a NORM
1709        bra.b           _L6_6d
1710_L6_2d:
1711        cmpi.b          %d1,&ZERO               # is operand a ZERO?
1712        bne.b           _L6_3d                  # no
1713        bsr.l           src_zero                        # yes
1714        bra.b           _L6_6d
1715_L6_3d:
1716        cmpi.b          %d1,&INF                # is operand an INF?
1717        bne.b           _L6_4d                  # no
1718        bsr.l           spi_2                   # yes
1719        bra.b           _L6_6d
1720_L6_4d:
1721        cmpi.b          %d1,&QNAN               # is operand a QNAN?
1722        bne.b           _L6_5d                  # no
1723        bsr.l           src_qnan                        # yes
1724        bra.b           _L6_6d
1725_L6_5d:
1726        bsr.l           satand                  # operand is a DENORM
1727_L6_6d:
1728
1729#
1730#       Result is now in FP0
1731#
1732        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
1733        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1734        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
1735        unlk            %a6
1736        rts
1737
1738        global          _fatanx_
1739_fatanx_:
1740        link            %a6,&-LOCAL_SIZE
1741
1742        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
1743        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1744        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
1745
1746        fmov.l          &0x0,%fpcr              # zero FPCR
1747
1748#
1749#       copy, convert, and tag input argument
1750#
1751        lea             FP_SRC(%a6),%a0
1752        mov.l           0x8+0x0(%a6),0x0(%a0)   # load ext input
1753        mov.l           0x8+0x4(%a6),0x4(%a0)
1754        mov.l           0x8+0x8(%a6),0x8(%a0)
1755        bsr.l           tag                     # fetch operand type
1756        mov.b           %d0,STAG(%a6)
1757        mov.b           %d0,%d1
1758
1759        andi.l          &0x00ff00ff,USER_FPSR(%a6)
1760
1761        clr.l           %d0
1762        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
1763
1764        tst.b           %d1
1765        bne.b           _L6_2x
1766        bsr.l           satan                   # operand is a NORM
1767        bra.b           _L6_6x
1768_L6_2x:
1769        cmpi.b          %d1,&ZERO               # is operand a ZERO?
1770        bne.b           _L6_3x                  # no
1771        bsr.l           src_zero                        # yes
1772        bra.b           _L6_6x
1773_L6_3x:
1774        cmpi.b          %d1,&INF                # is operand an INF?
1775        bne.b           _L6_4x                  # no
1776        bsr.l           spi_2                   # yes
1777        bra.b           _L6_6x
1778_L6_4x:
1779        cmpi.b          %d1,&QNAN               # is operand a QNAN?
1780        bne.b           _L6_5x                  # no
1781        bsr.l           src_qnan                        # yes
1782        bra.b           _L6_6x
1783_L6_5x:
1784        bsr.l           satand                  # operand is a DENORM
1785_L6_6x:
1786
1787#
1788#       Result is now in FP0
1789#
1790        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
1791        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1792        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
1793        unlk            %a6
1794        rts
1795
1796
1797#########################################################################
1798# MONADIC TEMPLATE                                                      #
1799#########################################################################
1800        global          _fasins_
1801_fasins_:
1802        link            %a6,&-LOCAL_SIZE
1803
1804        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
1805        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1806        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
1807
1808        fmov.l          &0x0,%fpcr              # zero FPCR
1809
1810#
1811#       copy, convert, and tag input argument
1812#
1813        fmov.s          0x8(%a6),%fp0           # load sgl input
1814        fmov.x          %fp0,FP_SRC(%a6)
1815        lea             FP_SRC(%a6),%a0
1816        bsr.l           tag                     # fetch operand type
1817        mov.b           %d0,STAG(%a6)
1818        mov.b           %d0,%d1
1819
1820        andi.l          &0x00ff00ff,USER_FPSR(%a6)
1821
1822        clr.l           %d0
1823        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
1824
1825        tst.b           %d1
1826        bne.b           _L7_2s
1827        bsr.l           sasin                   # operand is a NORM
1828        bra.b           _L7_6s
1829_L7_2s:
1830        cmpi.b          %d1,&ZERO               # is operand a ZERO?
1831        bne.b           _L7_3s                  # no
1832        bsr.l           src_zero                        # yes
1833        bra.b           _L7_6s
1834_L7_3s:
1835        cmpi.b          %d1,&INF                # is operand an INF?
1836        bne.b           _L7_4s                  # no
1837        bsr.l           t_operr                 # yes
1838        bra.b           _L7_6s
1839_L7_4s:
1840        cmpi.b          %d1,&QNAN               # is operand a QNAN?
1841        bne.b           _L7_5s                  # no
1842        bsr.l           src_qnan                        # yes
1843        bra.b           _L7_6s
1844_L7_5s:
1845        bsr.l           sasind                  # operand is a DENORM
1846_L7_6s:
1847
1848#
1849#       Result is now in FP0
1850#
1851        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
1852        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1853        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
1854        unlk            %a6
1855        rts
1856
1857        global          _fasind_
1858_fasind_:
1859        link            %a6,&-LOCAL_SIZE
1860
1861        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
1862        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1863        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
1864
1865        fmov.l          &0x0,%fpcr              # zero FPCR
1866
1867#
1868#       copy, convert, and tag input argument
1869#
1870        fmov.d          0x8(%a6),%fp0           # load dbl input
1871        fmov.x          %fp0,FP_SRC(%a6)
1872        lea             FP_SRC(%a6),%a0
1873        bsr.l           tag                     # fetch operand type
1874        mov.b           %d0,STAG(%a6)
1875        mov.b           %d0,%d1
1876
1877        andi.l          &0x00ff00ff,USER_FPSR(%a6)
1878
1879        clr.l           %d0
1880        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
1881
1882        mov.b           %d1,STAG(%a6)
1883        tst.b           %d1
1884        bne.b           _L7_2d
1885        bsr.l           sasin                   # operand is a NORM
1886        bra.b           _L7_6d
1887_L7_2d:
1888        cmpi.b          %d1,&ZERO               # is operand a ZERO?
1889        bne.b           _L7_3d                  # no
1890        bsr.l           src_zero                        # yes
1891        bra.b           _L7_6d
1892_L7_3d:
1893        cmpi.b          %d1,&INF                # is operand an INF?
1894        bne.b           _L7_4d                  # no
1895        bsr.l           t_operr                 # yes
1896        bra.b           _L7_6d
1897_L7_4d:
1898        cmpi.b          %d1,&QNAN               # is operand a QNAN?
1899        bne.b           _L7_5d                  # no
1900        bsr.l           src_qnan                        # yes
1901        bra.b           _L7_6d
1902_L7_5d:
1903        bsr.l           sasind                  # operand is a DENORM
1904_L7_6d:
1905
1906#
1907#       Result is now in FP0
1908#
1909        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
1910        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1911        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
1912        unlk            %a6
1913        rts
1914
1915        global          _fasinx_
1916_fasinx_:
1917        link            %a6,&-LOCAL_SIZE
1918
1919        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
1920        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1921        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
1922
1923        fmov.l          &0x0,%fpcr              # zero FPCR
1924
1925#
1926#       copy, convert, and tag input argument
1927#
1928        lea             FP_SRC(%a6),%a0
1929        mov.l           0x8+0x0(%a6),0x0(%a0)   # load ext input
1930        mov.l           0x8+0x4(%a6),0x4(%a0)
1931        mov.l           0x8+0x8(%a6),0x8(%a0)
1932        bsr.l           tag                     # fetch operand type
1933        mov.b           %d0,STAG(%a6)
1934        mov.b           %d0,%d1
1935
1936        andi.l          &0x00ff00ff,USER_FPSR(%a6)
1937
1938        clr.l           %d0
1939        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
1940
1941        tst.b           %d1
1942        bne.b           _L7_2x
1943        bsr.l           sasin                   # operand is a NORM
1944        bra.b           _L7_6x
1945_L7_2x:
1946        cmpi.b          %d1,&ZERO               # is operand a ZERO?
1947        bne.b           _L7_3x                  # no
1948        bsr.l           src_zero                        # yes
1949        bra.b           _L7_6x
1950_L7_3x:
1951        cmpi.b          %d1,&INF                # is operand an INF?
1952        bne.b           _L7_4x                  # no
1953        bsr.l           t_operr                 # yes
1954        bra.b           _L7_6x
1955_L7_4x:
1956        cmpi.b          %d1,&QNAN               # is operand a QNAN?
1957        bne.b           _L7_5x                  # no
1958        bsr.l           src_qnan                        # yes
1959        bra.b           _L7_6x
1960_L7_5x:
1961        bsr.l           sasind                  # operand is a DENORM
1962_L7_6x:
1963
1964#
1965#       Result is now in FP0
1966#
1967        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
1968        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1969        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
1970        unlk            %a6
1971        rts
1972
1973
1974#########################################################################
1975# MONADIC TEMPLATE                                                      #
1976#########################################################################
1977        global          _fatanhs_
1978_fatanhs_:
1979        link            %a6,&-LOCAL_SIZE
1980
1981        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
1982        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1983        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
1984
1985        fmov.l          &0x0,%fpcr              # zero FPCR
1986
1987#
1988#       copy, convert, and tag input argument
1989#
1990        fmov.s          0x8(%a6),%fp0           # load sgl input
1991        fmov.x          %fp0,FP_SRC(%a6)
1992        lea             FP_SRC(%a6),%a0
1993        bsr.l           tag                     # fetch operand type
1994        mov.b           %d0,STAG(%a6)
1995        mov.b           %d0,%d1
1996
1997        andi.l          &0x00ff00ff,USER_FPSR(%a6)
1998
1999        clr.l           %d0
2000        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
2001
2002        tst.b           %d1
2003        bne.b           _L8_2s
2004        bsr.l           satanh                  # operand is a NORM
2005        bra.b           _L8_6s
2006_L8_2s:
2007        cmpi.b          %d1,&ZERO               # is operand a ZERO?
2008        bne.b           _L8_3s                  # no
2009        bsr.l           src_zero                        # yes
2010        bra.b           _L8_6s
2011_L8_3s:
2012        cmpi.b          %d1,&INF                # is operand an INF?
2013        bne.b           _L8_4s                  # no
2014        bsr.l           t_operr                 # yes
2015        bra.b           _L8_6s
2016_L8_4s:
2017        cmpi.b          %d1,&QNAN               # is operand a QNAN?
2018        bne.b           _L8_5s                  # no
2019        bsr.l           src_qnan                        # yes
2020        bra.b           _L8_6s
2021_L8_5s:
2022        bsr.l           satanhd                 # operand is a DENORM
2023_L8_6s:
2024
2025#
2026#       Result is now in FP0
2027#
2028        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
2029        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2030        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
2031        unlk            %a6
2032        rts
2033
2034        global          _fatanhd_
2035_fatanhd_:
2036        link            %a6,&-LOCAL_SIZE
2037
2038        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
2039        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2040        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
2041
2042        fmov.l          &0x0,%fpcr              # zero FPCR
2043
2044#
2045#       copy, convert, and tag input argument
2046#
2047        fmov.d          0x8(%a6),%fp0           # load dbl input
2048        fmov.x          %fp0,FP_SRC(%a6)
2049        lea             FP_SRC(%a6),%a0
2050        bsr.l           tag                     # fetch operand type
2051        mov.b           %d0,STAG(%a6)
2052        mov.b           %d0,%d1
2053
2054        andi.l          &0x00ff00ff,USER_FPSR(%a6)
2055
2056        clr.l           %d0
2057        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
2058
2059        mov.b           %d1,STAG(%a6)
2060        tst.b           %d1
2061        bne.b           _L8_2d
2062        bsr.l           satanh                  # operand is a NORM
2063        bra.b           _L8_6d
2064_L8_2d:
2065        cmpi.b          %d1,&ZERO               # is operand a ZERO?
2066        bne.b           _L8_3d                  # no
2067        bsr.l           src_zero                        # yes
2068        bra.b           _L8_6d
2069_L8_3d:
2070        cmpi.b          %d1,&INF                # is operand an INF?
2071        bne.b           _L8_4d                  # no
2072        bsr.l           t_operr                 # yes
2073        bra.b           _L8_6d
2074_L8_4d:
2075        cmpi.b          %d1,&QNAN               # is operand a QNAN?
2076        bne.b           _L8_5d                  # no
2077        bsr.l           src_qnan                        # yes
2078        bra.b           _L8_6d
2079_L8_5d:
2080        bsr.l           satanhd                 # operand is a DENORM
2081_L8_6d:
2082
2083#
2084#       Result is now in FP0
2085#
2086        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
2087        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2088        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
2089        unlk            %a6
2090        rts
2091
2092        global          _fatanhx_
2093_fatanhx_:
2094        link            %a6,&-LOCAL_SIZE
2095
2096        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
2097        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2098        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
2099
2100        fmov.l          &0x0,%fpcr              # zero FPCR
2101
2102#
2103#       copy, convert, and tag input argument
2104#
2105        lea             FP_SRC(%a6),%a0
2106        mov.l           0x8+0x0(%a6),0x0(%a0)   # load ext input
2107        mov.l           0x8+0x4(%a6),0x4(%a0)
2108        mov.l           0x8+0x8(%a6),0x8(%a0)
2109        bsr.l           tag                     # fetch operand type
2110        mov.b           %d0,STAG(%a6)
2111        mov.b           %d0,%d1
2112
2113        andi.l          &0x00ff00ff,USER_FPSR(%a6)
2114
2115        clr.l           %d0
2116        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
2117
2118        tst.b           %d1
2119        bne.b           _L8_2x
2120        bsr.l           satanh                  # operand is a NORM
2121        bra.b           _L8_6x
2122_L8_2x:
2123        cmpi.b          %d1,&ZERO               # is operand a ZERO?
2124        bne.b           _L8_3x                  # no
2125        bsr.l           src_zero                        # yes
2126        bra.b           _L8_6x
2127_L8_3x:
2128        cmpi.b          %d1,&INF                # is operand an INF?
2129        bne.b           _L8_4x                  # no
2130        bsr.l           t_operr                 # yes
2131        bra.b           _L8_6x
2132_L8_4x:
2133        cmpi.b          %d1,&QNAN               # is operand a QNAN?
2134        bne.b           _L8_5x                  # no
2135        bsr.l           src_qnan                        # yes
2136        bra.b           _L8_6x
2137_L8_5x:
2138        bsr.l           satanhd                 # operand is a DENORM
2139_L8_6x:
2140
2141#
2142#       Result is now in FP0
2143#
2144        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
2145        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2146        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
2147        unlk            %a6
2148        rts
2149
2150
2151#########################################################################
2152# MONADIC TEMPLATE                                                      #
2153#########################################################################
2154        global          _ftans_
2155_ftans_:
2156        link            %a6,&-LOCAL_SIZE
2157
2158        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
2159        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2160        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
2161
2162        fmov.l          &0x0,%fpcr              # zero FPCR
2163
2164#
2165#       copy, convert, and tag input argument
2166#
2167        fmov.s          0x8(%a6),%fp0           # load sgl input
2168        fmov.x          %fp0,FP_SRC(%a6)
2169        lea             FP_SRC(%a6),%a0
2170        bsr.l           tag                     # fetch operand type
2171        mov.b           %d0,STAG(%a6)
2172        mov.b           %d0,%d1
2173
2174        andi.l          &0x00ff00ff,USER_FPSR(%a6)
2175
2176        clr.l           %d0
2177        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
2178
2179        tst.b           %d1
2180        bne.b           _L9_2s
2181        bsr.l           stan                    # operand is a NORM
2182        bra.b           _L9_6s
2183_L9_2s:
2184        cmpi.b          %d1,&ZERO               # is operand a ZERO?
2185        bne.b           _L9_3s                  # no
2186        bsr.l           src_zero                        # yes
2187        bra.b           _L9_6s
2188_L9_3s:
2189        cmpi.b          %d1,&INF                # is operand an INF?
2190        bne.b           _L9_4s                  # no
2191        bsr.l           t_operr                 # yes
2192        bra.b           _L9_6s
2193_L9_4s:
2194        cmpi.b          %d1,&QNAN               # is operand a QNAN?
2195        bne.b           _L9_5s                  # no
2196        bsr.l           src_qnan                        # yes
2197        bra.b           _L9_6s
2198_L9_5s:
2199        bsr.l           stand                   # operand is a DENORM
2200_L9_6s:
2201
2202#
2203#       Result is now in FP0
2204#
2205        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
2206        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2207        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
2208        unlk            %a6
2209        rts
2210
2211        global          _ftand_
2212_ftand_:
2213        link            %a6,&-LOCAL_SIZE
2214
2215        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
2216        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2217        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
2218
2219        fmov.l          &0x0,%fpcr              # zero FPCR
2220
2221#
2222#       copy, convert, and tag input argument
2223#
2224        fmov.d          0x8(%a6),%fp0           # load dbl input
2225        fmov.x          %fp0,FP_SRC(%a6)
2226        lea             FP_SRC(%a6),%a0
2227        bsr.l           tag                     # fetch operand type
2228        mov.b           %d0,STAG(%a6)
2229        mov.b           %d0,%d1
2230
2231        andi.l          &0x00ff00ff,USER_FPSR(%a6)
2232
2233        clr.l           %d0
2234        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
2235
2236        mov.b           %d1,STAG(%a6)
2237        tst.b           %d1
2238        bne.b           _L9_2d
2239        bsr.l           stan                    # operand is a NORM
2240        bra.b           _L9_6d
2241_L9_2d:
2242        cmpi.b          %d1,&ZERO               # is operand a ZERO?
2243        bne.b           _L9_3d                  # no
2244        bsr.l           src_zero                        # yes
2245        bra.b           _L9_6d
2246_L9_3d:
2247        cmpi.b          %d1,&INF                # is operand an INF?
2248        bne.b           _L9_4d                  # no
2249        bsr.l           t_operr                 # yes
2250        bra.b           _L9_6d
2251_L9_4d:
2252        cmpi.b          %d1,&QNAN               # is operand a QNAN?
2253        bne.b           _L9_5d                  # no
2254        bsr.l           src_qnan                        # yes
2255        bra.b           _L9_6d
2256_L9_5d:
2257        bsr.l           stand                   # operand is a DENORM
2258_L9_6d:
2259
2260#
2261#       Result is now in FP0
2262#
2263        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
2264        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2265        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
2266        unlk            %a6
2267        rts
2268
2269        global          _ftanx_
2270_ftanx_:
2271        link            %a6,&-LOCAL_SIZE
2272
2273        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
2274        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2275        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
2276
2277        fmov.l          &0x0,%fpcr              # zero FPCR
2278
2279#
2280#       copy, convert, and tag input argument
2281#
2282        lea             FP_SRC(%a6),%a0
2283        mov.l           0x8+0x0(%a6),0x0(%a0)   # load ext input
2284        mov.l           0x8+0x4(%a6),0x4(%a0)
2285        mov.l           0x8+0x8(%a6),0x8(%a0)
2286        bsr.l           tag                     # fetch operand type
2287        mov.b           %d0,STAG(%a6)
2288        mov.b           %d0,%d1
2289
2290        andi.l          &0x00ff00ff,USER_FPSR(%a6)
2291
2292        clr.l           %d0
2293        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
2294
2295        tst.b           %d1
2296        bne.b           _L9_2x
2297        bsr.l           stan                    # operand is a NORM
2298        bra.b           _L9_6x
2299_L9_2x:
2300        cmpi.b          %d1,&ZERO               # is operand a ZERO?
2301        bne.b           _L9_3x                  # no
2302        bsr.l           src_zero                        # yes
2303        bra.b           _L9_6x
2304_L9_3x:
2305        cmpi.b          %d1,&INF                # is operand an INF?
2306        bne.b           _L9_4x                  # no
2307        bsr.l           t_operr                 # yes
2308        bra.b           _L9_6x
2309_L9_4x:
2310        cmpi.b          %d1,&QNAN               # is operand a QNAN?
2311        bne.b           _L9_5x                  # no
2312        bsr.l           src_qnan                        # yes
2313        bra.b           _L9_6x
2314_L9_5x:
2315        bsr.l           stand                   # operand is a DENORM
2316_L9_6x:
2317
2318#
2319#       Result is now in FP0
2320#
2321        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
2322        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2323        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
2324        unlk            %a6
2325        rts
2326
2327
2328#########################################################################
2329# MONADIC TEMPLATE                                                      #
2330#########################################################################
2331        global          _fetoxs_
2332_fetoxs_:
2333        link            %a6,&-LOCAL_SIZE
2334
2335        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
2336        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2337        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
2338
2339        fmov.l          &0x0,%fpcr              # zero FPCR
2340
2341#
2342#       copy, convert, and tag input argument
2343#
2344        fmov.s          0x8(%a6),%fp0           # load sgl input
2345        fmov.x          %fp0,FP_SRC(%a6)
2346        lea             FP_SRC(%a6),%a0
2347        bsr.l           tag                     # fetch operand type
2348        mov.b           %d0,STAG(%a6)
2349        mov.b           %d0,%d1
2350
2351        andi.l          &0x00ff00ff,USER_FPSR(%a6)
2352
2353        clr.l           %d0
2354        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
2355
2356        tst.b           %d1
2357        bne.b           _L10_2s
2358        bsr.l           setox                   # operand is a NORM
2359        bra.b           _L10_6s
2360_L10_2s:
2361        cmpi.b          %d1,&ZERO               # is operand a ZERO?
2362        bne.b           _L10_3s                 # no
2363        bsr.l           ld_pone                 # yes
2364        bra.b           _L10_6s
2365_L10_3s:
2366        cmpi.b          %d1,&INF                # is operand an INF?
2367        bne.b           _L10_4s                 # no
2368        bsr.l           szr_inf                 # yes
2369        bra.b           _L10_6s
2370_L10_4s:
2371        cmpi.b          %d1,&QNAN               # is operand a QNAN?
2372        bne.b           _L10_5s                 # no
2373        bsr.l           src_qnan                        # yes
2374        bra.b           _L10_6s
2375_L10_5s:
2376        bsr.l           setoxd                  # operand is a DENORM
2377_L10_6s:
2378
2379#
2380#       Result is now in FP0
2381#
2382        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
2383        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2384        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
2385        unlk            %a6
2386        rts
2387
2388        global          _fetoxd_
2389_fetoxd_:
2390        link            %a6,&-LOCAL_SIZE
2391
2392        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
2393        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2394        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
2395
2396        fmov.l          &0x0,%fpcr              # zero FPCR
2397
2398#
2399#       copy, convert, and tag input argument
2400#
2401        fmov.d          0x8(%a6),%fp0           # load dbl input
2402        fmov.x          %fp0,FP_SRC(%a6)
2403        lea             FP_SRC(%a6),%a0
2404        bsr.l           tag                     # fetch operand type
2405        mov.b           %d0,STAG(%a6)
2406        mov.b           %d0,%d1
2407
2408        andi.l          &0x00ff00ff,USER_FPSR(%a6)
2409
2410        clr.l           %d0
2411        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
2412
2413        mov.b           %d1,STAG(%a6)
2414        tst.b           %d1
2415        bne.b           _L10_2d
2416        bsr.l           setox                   # operand is a NORM
2417        bra.b           _L10_6d
2418_L10_2d:
2419        cmpi.b          %d1,&ZERO               # is operand a ZERO?
2420        bne.b           _L10_3d                 # no
2421        bsr.l           ld_pone                 # yes
2422        bra.b           _L10_6d
2423_L10_3d:
2424        cmpi.b          %d1,&INF                # is operand an INF?
2425        bne.b           _L10_4d                 # no
2426        bsr.l           szr_inf                 # yes
2427        bra.b           _L10_6d
2428_L10_4d:
2429        cmpi.b          %d1,&QNAN               # is operand a QNAN?
2430        bne.b           _L10_5d                 # no
2431        bsr.l           src_qnan                        # yes
2432        bra.b           _L10_6d
2433_L10_5d:
2434        bsr.l           setoxd                  # operand is a DENORM
2435_L10_6d:
2436
2437#
2438#       Result is now in FP0
2439#
2440        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
2441        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2442        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
2443        unlk            %a6
2444        rts
2445
2446        global          _fetoxx_
2447_fetoxx_:
2448        link            %a6,&-LOCAL_SIZE
2449
2450        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
2451        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2452        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
2453
2454        fmov.l          &0x0,%fpcr              # zero FPCR
2455
2456#
2457#       copy, convert, and tag input argument
2458#
2459        lea             FP_SRC(%a6),%a0
2460        mov.l           0x8+0x0(%a6),0x0(%a0)   # load ext input
2461        mov.l           0x8+0x4(%a6),0x4(%a0)
2462        mov.l           0x8+0x8(%a6),0x8(%a0)
2463        bsr.l           tag                     # fetch operand type
2464        mov.b           %d0,STAG(%a6)
2465        mov.b           %d0,%d1
2466
2467        andi.l          &0x00ff00ff,USER_FPSR(%a6)
2468
2469        clr.l           %d0
2470        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
2471
2472        tst.b           %d1
2473        bne.b           _L10_2x
2474        bsr.l           setox                   # operand is a NORM
2475        bra.b           _L10_6x
2476_L10_2x:
2477        cmpi.b          %d1,&ZERO               # is operand a ZERO?
2478        bne.b           _L10_3x                 # no
2479        bsr.l           ld_pone                 # yes
2480        bra.b           _L10_6x
2481_L10_3x:
2482        cmpi.b          %d1,&INF                # is operand an INF?
2483        bne.b           _L10_4x                 # no
2484        bsr.l           szr_inf                 # yes
2485        bra.b           _L10_6x
2486_L10_4x:
2487        cmpi.b          %d1,&QNAN               # is operand a QNAN?
2488        bne.b           _L10_5x                 # no
2489        bsr.l           src_qnan                        # yes
2490        bra.b           _L10_6x
2491_L10_5x:
2492        bsr.l           setoxd                  # operand is a DENORM
2493_L10_6x:
2494
2495#
2496#       Result is now in FP0
2497#
2498        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
2499        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2500        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
2501        unlk            %a6
2502        rts
2503
2504
2505#########################################################################
2506# MONADIC TEMPLATE                                                      #
2507#########################################################################
2508        global          _ftwotoxs_
2509_ftwotoxs_:
2510        link            %a6,&-LOCAL_SIZE
2511
2512        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
2513        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2514        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
2515
2516        fmov.l          &0x0,%fpcr              # zero FPCR
2517
2518#
2519#       copy, convert, and tag input argument
2520#
2521        fmov.s          0x8(%a6),%fp0           # load sgl input
2522        fmov.x          %fp0,FP_SRC(%a6)
2523        lea             FP_SRC(%a6),%a0
2524        bsr.l           tag                     # fetch operand type
2525        mov.b           %d0,STAG(%a6)
2526        mov.b           %d0,%d1
2527
2528        andi.l          &0x00ff00ff,USER_FPSR(%a6)
2529
2530        clr.l           %d0
2531        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
2532
2533        tst.b           %d1
2534        bne.b           _L11_2s
2535        bsr.l           stwotox                 # operand is a NORM
2536        bra.b           _L11_6s
2537_L11_2s:
2538        cmpi.b          %d1,&ZERO               # is operand a ZERO?
2539        bne.b           _L11_3s                 # no
2540        bsr.l           ld_pone                 # yes
2541        bra.b           _L11_6s
2542_L11_3s:
2543        cmpi.b          %d1,&INF                # is operand an INF?
2544        bne.b           _L11_4s                 # no
2545        bsr.l           szr_inf                 # yes
2546        bra.b           _L11_6s
2547_L11_4s:
2548        cmpi.b          %d1,&QNAN               # is operand a QNAN?
2549        bne.b           _L11_5s                 # no
2550        bsr.l           src_qnan                        # yes
2551        bra.b           _L11_6s
2552_L11_5s:
2553        bsr.l           stwotoxd                        # operand is a DENORM
2554_L11_6s:
2555
2556#
2557#       Result is now in FP0
2558#
2559        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
2560        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2561        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
2562        unlk            %a6
2563        rts
2564
2565        global          _ftwotoxd_
2566_ftwotoxd_:
2567        link            %a6,&-LOCAL_SIZE
2568
2569        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
2570        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2571        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
2572
2573        fmov.l          &0x0,%fpcr              # zero FPCR
2574
2575#
2576#       copy, convert, and tag input argument
2577#
2578        fmov.d          0x8(%a6),%fp0           # load dbl input
2579        fmov.x          %fp0,FP_SRC(%a6)
2580        lea             FP_SRC(%a6),%a0
2581        bsr.l           tag                     # fetch operand type
2582        mov.b           %d0,STAG(%a6)
2583        mov.b           %d0,%d1
2584
2585        andi.l          &0x00ff00ff,USER_FPSR(%a6)
2586
2587        clr.l           %d0
2588        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
2589
2590        mov.b           %d1,STAG(%a6)
2591        tst.b           %d1
2592        bne.b           _L11_2d
2593        bsr.l           stwotox                 # operand is a NORM
2594        bra.b           _L11_6d
2595_L11_2d:
2596        cmpi.b          %d1,&ZERO               # is operand a ZERO?
2597        bne.b           _L11_3d                 # no
2598        bsr.l           ld_pone                 # yes
2599        bra.b           _L11_6d
2600_L11_3d:
2601        cmpi.b          %d1,&INF                # is operand an INF?
2602        bne.b           _L11_4d                 # no
2603        bsr.l           szr_inf                 # yes
2604        bra.b           _L11_6d
2605_L11_4d:
2606        cmpi.b          %d1,&QNAN               # is operand a QNAN?
2607        bne.b           _L11_5d                 # no
2608        bsr.l           src_qnan                        # yes
2609        bra.b           _L11_6d
2610_L11_5d:
2611        bsr.l           stwotoxd                        # operand is a DENORM
2612_L11_6d:
2613
2614#
2615#       Result is now in FP0
2616#
2617        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
2618        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2619        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
2620        unlk            %a6
2621        rts
2622
2623        global          _ftwotoxx_
2624_ftwotoxx_:
2625        link            %a6,&-LOCAL_SIZE
2626
2627        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
2628        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2629        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
2630
2631        fmov.l          &0x0,%fpcr              # zero FPCR
2632
2633#
2634#       copy, convert, and tag input argument
2635#
2636        lea             FP_SRC(%a6),%a0
2637        mov.l           0x8+0x0(%a6),0x0(%a0)   # load ext input
2638        mov.l           0x8+0x4(%a6),0x4(%a0)
2639        mov.l           0x8+0x8(%a6),0x8(%a0)
2640        bsr.l           tag                     # fetch operand type
2641        mov.b           %d0,STAG(%a6)
2642        mov.b           %d0,%d1
2643
2644        andi.l          &0x00ff00ff,USER_FPSR(%a6)
2645
2646        clr.l           %d0
2647        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
2648
2649        tst.b           %d1
2650        bne.b           _L11_2x
2651        bsr.l           stwotox                 # operand is a NORM
2652        bra.b           _L11_6x
2653_L11_2x:
2654        cmpi.b          %d1,&ZERO               # is operand a ZERO?
2655        bne.b           _L11_3x                 # no
2656        bsr.l           ld_pone                 # yes
2657        bra.b           _L11_6x
2658_L11_3x:
2659        cmpi.b          %d1,&INF                # is operand an INF?
2660        bne.b           _L11_4x                 # no
2661        bsr.l           szr_inf                 # yes
2662        bra.b           _L11_6x
2663_L11_4x:
2664        cmpi.b          %d1,&QNAN               # is operand a QNAN?
2665        bne.b           _L11_5x                 # no
2666        bsr.l           src_qnan                        # yes
2667        bra.b           _L11_6x
2668_L11_5x:
2669        bsr.l           stwotoxd                        # operand is a DENORM
2670_L11_6x:
2671
2672#
2673#       Result is now in FP0
2674#
2675        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
2676        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2677        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
2678        unlk            %a6
2679        rts
2680
2681
2682#########################################################################
2683# MONADIC TEMPLATE                                                      #
2684#########################################################################
2685        global          _ftentoxs_
2686_ftentoxs_:
2687        link            %a6,&-LOCAL_SIZE
2688
2689        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
2690        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2691        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
2692
2693        fmov.l          &0x0,%fpcr              # zero FPCR
2694
2695#
2696#       copy, convert, and tag input argument
2697#
2698        fmov.s          0x8(%a6),%fp0           # load sgl input
2699        fmov.x          %fp0,FP_SRC(%a6)
2700        lea             FP_SRC(%a6),%a0
2701        bsr.l           tag                     # fetch operand type
2702        mov.b           %d0,STAG(%a6)
2703        mov.b           %d0,%d1
2704
2705        andi.l          &0x00ff00ff,USER_FPSR(%a6)
2706
2707        clr.l           %d0
2708        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
2709
2710        tst.b           %d1
2711        bne.b           _L12_2s
2712        bsr.l           stentox                 # operand is a NORM
2713        bra.b           _L12_6s
2714_L12_2s:
2715        cmpi.b          %d1,&ZERO               # is operand a ZERO?
2716        bne.b           _L12_3s                 # no
2717        bsr.l           ld_pone                 # yes
2718        bra.b           _L12_6s
2719_L12_3s:
2720        cmpi.b          %d1,&INF                # is operand an INF?
2721        bne.b           _L12_4s                 # no
2722        bsr.l           szr_inf                 # yes
2723        bra.b           _L12_6s
2724_L12_4s:
2725        cmpi.b          %d1,&QNAN               # is operand a QNAN?
2726        bne.b           _L12_5s                 # no
2727        bsr.l           src_qnan                        # yes
2728        bra.b           _L12_6s
2729_L12_5s:
2730        bsr.l           stentoxd                        # operand is a DENORM
2731_L12_6s:
2732
2733#
2734#       Result is now in FP0
2735#
2736        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
2737        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2738        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
2739        unlk            %a6
2740        rts
2741
2742        global          _ftentoxd_
2743_ftentoxd_:
2744        link            %a6,&-LOCAL_SIZE
2745
2746        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
2747        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2748        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
2749
2750        fmov.l          &0x0,%fpcr              # zero FPCR
2751
2752#
2753#       copy, convert, and tag input argument
2754#
2755        fmov.d          0x8(%a6),%fp0           # load dbl input
2756        fmov.x          %fp0,FP_SRC(%a6)
2757        lea             FP_SRC(%a6),%a0
2758        bsr.l           tag                     # fetch operand type
2759        mov.b           %d0,STAG(%a6)
2760        mov.b           %d0,%d1
2761
2762        andi.l          &0x00ff00ff,USER_FPSR(%a6)
2763
2764        clr.l           %d0
2765        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
2766
2767        mov.b           %d1,STAG(%a6)
2768        tst.b           %d1
2769        bne.b           _L12_2d
2770        bsr.l           stentox                 # operand is a NORM
2771        bra.b           _L12_6d
2772_L12_2d:
2773        cmpi.b          %d1,&ZERO               # is operand a ZERO?
2774        bne.b           _L12_3d                 # no
2775        bsr.l           ld_pone                 # yes
2776        bra.b           _L12_6d
2777_L12_3d:
2778        cmpi.b          %d1,&INF                # is operand an INF?
2779        bne.b           _L12_4d                 # no
2780        bsr.l           szr_inf                 # yes
2781        bra.b           _L12_6d
2782_L12_4d:
2783        cmpi.b          %d1,&QNAN               # is operand a QNAN?
2784        bne.b           _L12_5d                 # no
2785        bsr.l           src_qnan                        # yes
2786        bra.b           _L12_6d
2787_L12_5d:
2788        bsr.l           stentoxd                        # operand is a DENORM
2789_L12_6d:
2790
2791#
2792#       Result is now in FP0
2793#
2794        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
2795        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2796        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
2797        unlk            %a6
2798        rts
2799
2800        global          _ftentoxx_
2801_ftentoxx_:
2802        link            %a6,&-LOCAL_SIZE
2803
2804        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
2805        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2806        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
2807
2808        fmov.l          &0x0,%fpcr              # zero FPCR
2809
2810#
2811#       copy, convert, and tag input argument
2812#
2813        lea             FP_SRC(%a6),%a0
2814        mov.l           0x8+0x0(%a6),0x0(%a0)   # load ext input
2815        mov.l           0x8+0x4(%a6),0x4(%a0)
2816        mov.l           0x8+0x8(%a6),0x8(%a0)
2817        bsr.l           tag                     # fetch operand type
2818        mov.b           %d0,STAG(%a6)
2819        mov.b           %d0,%d1
2820
2821        andi.l          &0x00ff00ff,USER_FPSR(%a6)
2822
2823        clr.l           %d0
2824        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
2825
2826        tst.b           %d1
2827        bne.b           _L12_2x
2828        bsr.l           stentox                 # operand is a NORM
2829        bra.b           _L12_6x
2830_L12_2x:
2831        cmpi.b          %d1,&ZERO               # is operand a ZERO?
2832        bne.b           _L12_3x                 # no
2833        bsr.l           ld_pone                 # yes
2834        bra.b           _L12_6x
2835_L12_3x:
2836        cmpi.b          %d1,&INF                # is operand an INF?
2837        bne.b           _L12_4x                 # no
2838        bsr.l           szr_inf                 # yes
2839        bra.b           _L12_6x
2840_L12_4x:
2841        cmpi.b          %d1,&QNAN               # is operand a QNAN?
2842        bne.b           _L12_5x                 # no
2843        bsr.l           src_qnan                        # yes
2844        bra.b           _L12_6x
2845_L12_5x:
2846        bsr.l           stentoxd                        # operand is a DENORM
2847_L12_6x:
2848
2849#
2850#       Result is now in FP0
2851#
2852        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
2853        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2854        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
2855        unlk            %a6
2856        rts
2857
2858
2859#########################################################################
2860# MONADIC TEMPLATE                                                      #
2861#########################################################################
2862        global          _flogns_
2863_flogns_:
2864        link            %a6,&-LOCAL_SIZE
2865
2866        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
2867        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2868        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
2869
2870        fmov.l          &0x0,%fpcr              # zero FPCR
2871
2872#
2873#       copy, convert, and tag input argument
2874#
2875        fmov.s          0x8(%a6),%fp0           # load sgl input
2876        fmov.x          %fp0,FP_SRC(%a6)
2877        lea             FP_SRC(%a6),%a0
2878        bsr.l           tag                     # fetch operand type
2879        mov.b           %d0,STAG(%a6)
2880        mov.b           %d0,%d1
2881
2882        andi.l          &0x00ff00ff,USER_FPSR(%a6)
2883
2884        clr.l           %d0
2885        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
2886
2887        tst.b           %d1
2888        bne.b           _L13_2s
2889        bsr.l           slogn                   # operand is a NORM
2890        bra.b           _L13_6s
2891_L13_2s:
2892        cmpi.b          %d1,&ZERO               # is operand a ZERO?
2893        bne.b           _L13_3s                 # no
2894        bsr.l           t_dz2                   # yes
2895        bra.b           _L13_6s
2896_L13_3s:
2897        cmpi.b          %d1,&INF                # is operand an INF?
2898        bne.b           _L13_4s                 # no
2899        bsr.l           sopr_inf                        # yes
2900        bra.b           _L13_6s
2901_L13_4s:
2902        cmpi.b          %d1,&QNAN               # is operand a QNAN?
2903        bne.b           _L13_5s                 # no
2904        bsr.l           src_qnan                        # yes
2905        bra.b           _L13_6s
2906_L13_5s:
2907        bsr.l           slognd                  # operand is a DENORM
2908_L13_6s:
2909
2910#
2911#       Result is now in FP0
2912#
2913        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
2914        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2915        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
2916        unlk            %a6
2917        rts
2918
2919        global          _flognd_
2920_flognd_:
2921        link            %a6,&-LOCAL_SIZE
2922
2923        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
2924        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2925        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
2926
2927        fmov.l          &0x0,%fpcr              # zero FPCR
2928
2929#
2930#       copy, convert, and tag input argument
2931#
2932        fmov.d          0x8(%a6),%fp0           # load dbl input
2933        fmov.x          %fp0,FP_SRC(%a6)
2934        lea             FP_SRC(%a6),%a0
2935        bsr.l           tag                     # fetch operand type
2936        mov.b           %d0,STAG(%a6)
2937        mov.b           %d0,%d1
2938
2939        andi.l          &0x00ff00ff,USER_FPSR(%a6)
2940
2941        clr.l           %d0
2942        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
2943
2944        mov.b           %d1,STAG(%a6)
2945        tst.b           %d1
2946        bne.b           _L13_2d
2947        bsr.l           slogn                   # operand is a NORM
2948        bra.b           _L13_6d
2949_L13_2d:
2950        cmpi.b          %d1,&ZERO               # is operand a ZERO?
2951        bne.b           _L13_3d                 # no
2952        bsr.l           t_dz2                   # yes
2953        bra.b           _L13_6d
2954_L13_3d:
2955        cmpi.b          %d1,&INF                # is operand an INF?
2956        bne.b           _L13_4d                 # no
2957        bsr.l           sopr_inf                        # yes
2958        bra.b           _L13_6d
2959_L13_4d:
2960        cmpi.b          %d1,&QNAN               # is operand a QNAN?
2961        bne.b           _L13_5d                 # no
2962        bsr.l           src_qnan                        # yes
2963        bra.b           _L13_6d
2964_L13_5d:
2965        bsr.l           slognd                  # operand is a DENORM
2966_L13_6d:
2967
2968#
2969#       Result is now in FP0
2970#
2971        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
2972        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2973        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
2974        unlk            %a6
2975        rts
2976
2977        global          _flognx_
2978_flognx_:
2979        link            %a6,&-LOCAL_SIZE
2980
2981        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
2982        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2983        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
2984
2985        fmov.l          &0x0,%fpcr              # zero FPCR
2986
2987#
2988#       copy, convert, and tag input argument
2989#
2990        lea             FP_SRC(%a6),%a0
2991        mov.l           0x8+0x0(%a6),0x0(%a0)   # load ext input
2992        mov.l           0x8+0x4(%a6),0x4(%a0)
2993        mov.l           0x8+0x8(%a6),0x8(%a0)
2994        bsr.l           tag                     # fetch operand type
2995        mov.b           %d0,STAG(%a6)
2996        mov.b           %d0,%d1
2997
2998        andi.l          &0x00ff00ff,USER_FPSR(%a6)
2999
3000        clr.l           %d0
3001        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
3002
3003        tst.b           %d1
3004        bne.b           _L13_2x
3005        bsr.l           slogn                   # operand is a NORM
3006        bra.b           _L13_6x
3007_L13_2x:
3008        cmpi.b          %d1,&ZERO               # is operand a ZERO?
3009        bne.b           _L13_3x                 # no
3010        bsr.l           t_dz2                   # yes
3011        bra.b           _L13_6x
3012_L13_3x:
3013        cmpi.b          %d1,&INF                # is operand an INF?
3014        bne.b           _L13_4x                 # no
3015        bsr.l           sopr_inf                        # yes
3016        bra.b           _L13_6x
3017_L13_4x:
3018        cmpi.b          %d1,&QNAN               # is operand a QNAN?
3019        bne.b           _L13_5x                 # no
3020        bsr.l           src_qnan                        # yes
3021        bra.b           _L13_6x
3022_L13_5x:
3023        bsr.l           slognd                  # operand is a DENORM
3024_L13_6x:
3025
3026#
3027#       Result is now in FP0
3028#
3029        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
3030        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3031        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
3032        unlk            %a6
3033        rts
3034
3035
3036#########################################################################
3037# MONADIC TEMPLATE                                                      #
3038#########################################################################
3039        global          _flog10s_
3040_flog10s_:
3041        link            %a6,&-LOCAL_SIZE
3042
3043        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
3044        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3045        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
3046
3047        fmov.l          &0x0,%fpcr              # zero FPCR
3048
3049#
3050#       copy, convert, and tag input argument
3051#
3052        fmov.s          0x8(%a6),%fp0           # load sgl input
3053        fmov.x          %fp0,FP_SRC(%a6)
3054        lea             FP_SRC(%a6),%a0
3055        bsr.l           tag                     # fetch operand type
3056        mov.b           %d0,STAG(%a6)
3057        mov.b           %d0,%d1
3058
3059        andi.l          &0x00ff00ff,USER_FPSR(%a6)
3060
3061        clr.l           %d0
3062        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
3063
3064        tst.b           %d1
3065        bne.b           _L14_2s
3066        bsr.l           slog10                  # operand is a NORM
3067        bra.b           _L14_6s
3068_L14_2s:
3069        cmpi.b          %d1,&ZERO               # is operand a ZERO?
3070        bne.b           _L14_3s                 # no
3071        bsr.l           t_dz2                   # yes
3072        bra.b           _L14_6s
3073_L14_3s:
3074        cmpi.b          %d1,&INF                # is operand an INF?
3075        bne.b           _L14_4s                 # no
3076        bsr.l           sopr_inf                        # yes
3077        bra.b           _L14_6s
3078_L14_4s:
3079        cmpi.b          %d1,&QNAN               # is operand a QNAN?
3080        bne.b           _L14_5s                 # no
3081        bsr.l           src_qnan                        # yes
3082        bra.b           _L14_6s
3083_L14_5s:
3084        bsr.l           slog10d                 # operand is a DENORM
3085_L14_6s:
3086
3087#
3088#       Result is now in FP0
3089#
3090        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
3091        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3092        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
3093        unlk            %a6
3094        rts
3095
3096        global          _flog10d_
3097_flog10d_:
3098        link            %a6,&-LOCAL_SIZE
3099
3100        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
3101        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3102        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
3103
3104        fmov.l          &0x0,%fpcr              # zero FPCR
3105
3106#
3107#       copy, convert, and tag input argument
3108#
3109        fmov.d          0x8(%a6),%fp0           # load dbl input
3110        fmov.x          %fp0,FP_SRC(%a6)
3111        lea             FP_SRC(%a6),%a0
3112        bsr.l           tag                     # fetch operand type
3113        mov.b           %d0,STAG(%a6)
3114        mov.b           %d0,%d1
3115
3116        andi.l          &0x00ff00ff,USER_FPSR(%a6)
3117
3118        clr.l           %d0
3119        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
3120
3121        mov.b           %d1,STAG(%a6)
3122        tst.b           %d1
3123        bne.b           _L14_2d
3124        bsr.l           slog10                  # operand is a NORM
3125        bra.b           _L14_6d
3126_L14_2d:
3127        cmpi.b          %d1,&ZERO               # is operand a ZERO?
3128        bne.b           _L14_3d                 # no
3129        bsr.l           t_dz2                   # yes
3130        bra.b           _L14_6d
3131_L14_3d:
3132        cmpi.b          %d1,&INF                # is operand an INF?
3133        bne.b           _L14_4d                 # no
3134        bsr.l           sopr_inf                        # yes
3135        bra.b           _L14_6d
3136_L14_4d:
3137        cmpi.b          %d1,&QNAN               # is operand a QNAN?
3138        bne.b           _L14_5d                 # no
3139        bsr.l           src_qnan                        # yes
3140        bra.b           _L14_6d
3141_L14_5d:
3142        bsr.l           slog10d                 # operand is a DENORM
3143_L14_6d:
3144
3145#
3146#       Result is now in FP0
3147#
3148        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
3149        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3150        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
3151        unlk            %a6
3152        rts
3153
3154        global          _flog10x_
3155_flog10x_:
3156        link            %a6,&-LOCAL_SIZE
3157
3158        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
3159        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3160        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
3161
3162        fmov.l          &0x0,%fpcr              # zero FPCR
3163
3164#
3165#       copy, convert, and tag input argument
3166#
3167        lea             FP_SRC(%a6),%a0
3168        mov.l           0x8+0x0(%a6),0x0(%a0)   # load ext input
3169        mov.l           0x8+0x4(%a6),0x4(%a0)
3170        mov.l           0x8+0x8(%a6),0x8(%a0)
3171        bsr.l           tag                     # fetch operand type
3172        mov.b           %d0,STAG(%a6)
3173        mov.b           %d0,%d1
3174
3175        andi.l          &0x00ff00ff,USER_FPSR(%a6)
3176
3177        clr.l           %d0
3178        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
3179
3180        tst.b           %d1
3181        bne.b           _L14_2x
3182        bsr.l           slog10                  # operand is a NORM
3183        bra.b           _L14_6x
3184_L14_2x:
3185        cmpi.b          %d1,&ZERO               # is operand a ZERO?
3186        bne.b           _L14_3x                 # no
3187        bsr.l           t_dz2                   # yes
3188        bra.b           _L14_6x
3189_L14_3x:
3190        cmpi.b          %d1,&INF                # is operand an INF?
3191        bne.b           _L14_4x                 # no
3192        bsr.l           sopr_inf                        # yes
3193        bra.b           _L14_6x
3194_L14_4x:
3195        cmpi.b          %d1,&QNAN               # is operand a QNAN?
3196        bne.b           _L14_5x                 # no
3197        bsr.l           src_qnan                        # yes
3198        bra.b           _L14_6x
3199_L14_5x:
3200        bsr.l           slog10d                 # operand is a DENORM
3201_L14_6x:
3202
3203#
3204#       Result is now in FP0
3205#
3206        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
3207        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3208        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
3209        unlk            %a6
3210        rts
3211
3212
3213#########################################################################
3214# MONADIC TEMPLATE                                                      #
3215#########################################################################
3216        global          _flog2s_
3217_flog2s_:
3218        link            %a6,&-LOCAL_SIZE
3219
3220        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
3221        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3222        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
3223
3224        fmov.l          &0x0,%fpcr              # zero FPCR
3225
3226#
3227#       copy, convert, and tag input argument
3228#
3229        fmov.s          0x8(%a6),%fp0           # load sgl input
3230        fmov.x          %fp0,FP_SRC(%a6)
3231        lea             FP_SRC(%a6),%a0
3232        bsr.l           tag                     # fetch operand type
3233        mov.b           %d0,STAG(%a6)
3234        mov.b           %d0,%d1
3235
3236        andi.l          &0x00ff00ff,USER_FPSR(%a6)
3237
3238        clr.l           %d0
3239        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
3240
3241        tst.b           %d1
3242        bne.b           _L15_2s
3243        bsr.l           slog2                   # operand is a NORM
3244        bra.b           _L15_6s
3245_L15_2s:
3246        cmpi.b          %d1,&ZERO               # is operand a ZERO?
3247        bne.b           _L15_3s                 # no
3248        bsr.l           t_dz2                   # yes
3249        bra.b           _L15_6s
3250_L15_3s:
3251        cmpi.b          %d1,&INF                # is operand an INF?
3252        bne.b           _L15_4s                 # no
3253        bsr.l           sopr_inf                        # yes
3254        bra.b           _L15_6s
3255_L15_4s:
3256        cmpi.b          %d1,&QNAN               # is operand a QNAN?
3257        bne.b           _L15_5s                 # no
3258        bsr.l           src_qnan                        # yes
3259        bra.b           _L15_6s
3260_L15_5s:
3261        bsr.l           slog2d                  # operand is a DENORM
3262_L15_6s:
3263
3264#
3265#       Result is now in FP0
3266#
3267        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
3268        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3269        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
3270        unlk            %a6
3271        rts
3272
3273        global          _flog2d_
3274_flog2d_:
3275        link            %a6,&-LOCAL_SIZE
3276
3277        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
3278        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3279        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
3280
3281        fmov.l          &0x0,%fpcr              # zero FPCR
3282
3283#
3284#       copy, convert, and tag input argument
3285#
3286        fmov.d          0x8(%a6),%fp0           # load dbl input
3287        fmov.x          %fp0,FP_SRC(%a6)
3288        lea             FP_SRC(%a6),%a0
3289        bsr.l           tag                     # fetch operand type
3290        mov.b           %d0,STAG(%a6)
3291        mov.b           %d0,%d1
3292
3293        andi.l          &0x00ff00ff,USER_FPSR(%a6)
3294
3295        clr.l           %d0
3296        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
3297
3298        mov.b           %d1,STAG(%a6)
3299        tst.b           %d1
3300        bne.b           _L15_2d
3301        bsr.l           slog2                   # operand is a NORM
3302        bra.b           _L15_6d
3303_L15_2d:
3304        cmpi.b          %d1,&ZERO               # is operand a ZERO?
3305        bne.b           _L15_3d                 # no
3306        bsr.l           t_dz2                   # yes
3307        bra.b           _L15_6d
3308_L15_3d:
3309        cmpi.b          %d1,&INF                # is operand an INF?
3310        bne.b           _L15_4d                 # no
3311        bsr.l           sopr_inf                        # yes
3312        bra.b           _L15_6d
3313_L15_4d:
3314        cmpi.b          %d1,&QNAN               # is operand a QNAN?
3315        bne.b           _L15_5d                 # no
3316        bsr.l           src_qnan                        # yes
3317        bra.b           _L15_6d
3318_L15_5d:
3319        bsr.l           slog2d                  # operand is a DENORM
3320_L15_6d:
3321
3322#
3323#       Result is now in FP0
3324#
3325        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
3326        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3327        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
3328        unlk            %a6
3329        rts
3330
3331        global          _flog2x_
3332_flog2x_:
3333        link            %a6,&-LOCAL_SIZE
3334
3335        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
3336        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3337        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
3338
3339        fmov.l          &0x0,%fpcr              # zero FPCR
3340
3341#
3342#       copy, convert, and tag input argument
3343#
3344        lea             FP_SRC(%a6),%a0
3345        mov.l           0x8+0x0(%a6),0x0(%a0)   # load ext input
3346        mov.l           0x8+0x4(%a6),0x4(%a0)
3347        mov.l           0x8+0x8(%a6),0x8(%a0)
3348        bsr.l           tag                     # fetch operand type
3349        mov.b           %d0,STAG(%a6)
3350        mov.b           %d0,%d1
3351
3352        andi.l          &0x00ff00ff,USER_FPSR(%a6)
3353
3354        clr.l           %d0
3355        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
3356
3357        tst.b           %d1
3358        bne.b           _L15_2x
3359        bsr.l           slog2                   # operand is a NORM
3360        bra.b           _L15_6x
3361_L15_2x:
3362        cmpi.b          %d1,&ZERO               # is operand a ZERO?
3363        bne.b           _L15_3x                 # no
3364        bsr.l           t_dz2                   # yes
3365        bra.b           _L15_6x
3366_L15_3x:
3367        cmpi.b          %d1,&INF                # is operand an INF?
3368        bne.b           _L15_4x                 # no
3369        bsr.l           sopr_inf                        # yes
3370        bra.b           _L15_6x
3371_L15_4x:
3372        cmpi.b          %d1,&QNAN               # is operand a QNAN?
3373        bne.b           _L15_5x                 # no
3374        bsr.l           src_qnan                        # yes
3375        bra.b           _L15_6x
3376_L15_5x:
3377        bsr.l           slog2d                  # operand is a DENORM
3378_L15_6x:
3379
3380#
3381#       Result is now in FP0
3382#
3383        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
3384        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3385        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
3386        unlk            %a6
3387        rts
3388
3389
3390#########################################################################
3391# MONADIC TEMPLATE                                                      #
3392#########################################################################
3393        global          _fcoshs_
3394_fcoshs_:
3395        link            %a6,&-LOCAL_SIZE
3396
3397        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
3398        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3399        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
3400
3401        fmov.l          &0x0,%fpcr              # zero FPCR
3402
3403#
3404#       copy, convert, and tag input argument
3405#
3406        fmov.s          0x8(%a6),%fp0           # load sgl input
3407        fmov.x          %fp0,FP_SRC(%a6)
3408        lea             FP_SRC(%a6),%a0
3409        bsr.l           tag                     # fetch operand type
3410        mov.b           %d0,STAG(%a6)
3411        mov.b           %d0,%d1
3412
3413        andi.l          &0x00ff00ff,USER_FPSR(%a6)
3414
3415        clr.l           %d0
3416        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
3417
3418        tst.b           %d1
3419        bne.b           _L16_2s
3420        bsr.l           scosh                   # operand is a NORM
3421        bra.b           _L16_6s
3422_L16_2s:
3423        cmpi.b          %d1,&ZERO               # is operand a ZERO?
3424        bne.b           _L16_3s                 # no
3425        bsr.l           ld_pone                 # yes
3426        bra.b           _L16_6s
3427_L16_3s:
3428        cmpi.b          %d1,&INF                # is operand an INF?
3429        bne.b           _L16_4s                 # no
3430        bsr.l           ld_pinf                 # yes
3431        bra.b           _L16_6s
3432_L16_4s:
3433        cmpi.b          %d1,&QNAN               # is operand a QNAN?
3434        bne.b           _L16_5s                 # no
3435        bsr.l           src_qnan                        # yes
3436        bra.b           _L16_6s
3437_L16_5s:
3438        bsr.l           scoshd                  # operand is a DENORM
3439_L16_6s:
3440
3441#
3442#       Result is now in FP0
3443#
3444        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
3445        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3446        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
3447        unlk            %a6
3448        rts
3449
3450        global          _fcoshd_
3451_fcoshd_:
3452        link            %a6,&-LOCAL_SIZE
3453
3454        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
3455        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3456        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
3457
3458        fmov.l          &0x0,%fpcr              # zero FPCR
3459
3460#
3461#       copy, convert, and tag input argument
3462#
3463        fmov.d          0x8(%a6),%fp0           # load dbl input
3464        fmov.x          %fp0,FP_SRC(%a6)
3465        lea             FP_SRC(%a6),%a0
3466        bsr.l           tag                     # fetch operand type
3467        mov.b           %d0,STAG(%a6)
3468        mov.b           %d0,%d1
3469
3470        andi.l          &0x00ff00ff,USER_FPSR(%a6)
3471
3472        clr.l           %d0
3473        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
3474
3475        mov.b           %d1,STAG(%a6)
3476        tst.b           %d1
3477        bne.b           _L16_2d
3478        bsr.l           scosh                   # operand is a NORM
3479        bra.b           _L16_6d
3480_L16_2d:
3481        cmpi.b          %d1,&ZERO               # is operand a ZERO?
3482        bne.b           _L16_3d                 # no
3483        bsr.l           ld_pone                 # yes
3484        bra.b           _L16_6d
3485_L16_3d:
3486        cmpi.b          %d1,&INF                # is operand an INF?
3487        bne.b           _L16_4d                 # no
3488        bsr.l           ld_pinf                 # yes
3489        bra.b           _L16_6d
3490_L16_4d:
3491        cmpi.b          %d1,&QNAN               # is operand a QNAN?
3492        bne.b           _L16_5d                 # no
3493        bsr.l           src_qnan                        # yes
3494        bra.b           _L16_6d
3495_L16_5d:
3496        bsr.l           scoshd                  # operand is a DENORM
3497_L16_6d:
3498
3499#
3500#       Result is now in FP0
3501#
3502        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
3503        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3504        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
3505        unlk            %a6
3506        rts
3507
3508        global          _fcoshx_
3509_fcoshx_:
3510        link            %a6,&-LOCAL_SIZE
3511
3512        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
3513        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3514        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
3515
3516        fmov.l          &0x0,%fpcr              # zero FPCR
3517
3518#
3519#       copy, convert, and tag input argument
3520#
3521        lea             FP_SRC(%a6),%a0
3522        mov.l           0x8+0x0(%a6),0x0(%a0)   # load ext input
3523        mov.l           0x8+0x4(%a6),0x4(%a0)
3524        mov.l           0x8+0x8(%a6),0x8(%a0)
3525        bsr.l           tag                     # fetch operand type
3526        mov.b           %d0,STAG(%a6)
3527        mov.b           %d0,%d1
3528
3529        andi.l          &0x00ff00ff,USER_FPSR(%a6)
3530
3531        clr.l           %d0
3532        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
3533
3534        tst.b           %d1
3535        bne.b           _L16_2x
3536        bsr.l           scosh                   # operand is a NORM
3537        bra.b           _L16_6x
3538_L16_2x:
3539        cmpi.b          %d1,&ZERO               # is operand a ZERO?
3540        bne.b           _L16_3x                 # no
3541        bsr.l           ld_pone                 # yes
3542        bra.b           _L16_6x
3543_L16_3x:
3544        cmpi.b          %d1,&INF                # is operand an INF?
3545        bne.b           _L16_4x                 # no
3546        bsr.l           ld_pinf                 # yes
3547        bra.b           _L16_6x
3548_L16_4x:
3549        cmpi.b          %d1,&QNAN               # is operand a QNAN?
3550        bne.b           _L16_5x                 # no
3551        bsr.l           src_qnan                        # yes
3552        bra.b           _L16_6x
3553_L16_5x:
3554        bsr.l           scoshd                  # operand is a DENORM
3555_L16_6x:
3556
3557#
3558#       Result is now in FP0
3559#
3560        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
3561        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3562        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
3563        unlk            %a6
3564        rts
3565
3566
3567#########################################################################
3568# MONADIC TEMPLATE                                                      #
3569#########################################################################
3570        global          _facoss_
3571_facoss_:
3572        link            %a6,&-LOCAL_SIZE
3573
3574        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
3575        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3576        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
3577
3578        fmov.l          &0x0,%fpcr              # zero FPCR
3579
3580#
3581#       copy, convert, and tag input argument
3582#
3583        fmov.s          0x8(%a6),%fp0           # load sgl input
3584        fmov.x          %fp0,FP_SRC(%a6)
3585        lea             FP_SRC(%a6),%a0
3586        bsr.l           tag                     # fetch operand type
3587        mov.b           %d0,STAG(%a6)
3588        mov.b           %d0,%d1
3589
3590        andi.l          &0x00ff00ff,USER_FPSR(%a6)
3591
3592        clr.l           %d0
3593        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
3594
3595        tst.b           %d1
3596        bne.b           _L17_2s
3597        bsr.l           sacos                   # operand is a NORM
3598        bra.b           _L17_6s
3599_L17_2s:
3600        cmpi.b          %d1,&ZERO               # is operand a ZERO?
3601        bne.b           _L17_3s                 # no
3602        bsr.l           ld_ppi2                 # yes
3603        bra.b           _L17_6s
3604_L17_3s:
3605        cmpi.b          %d1,&INF                # is operand an INF?
3606        bne.b           _L17_4s                 # no
3607        bsr.l           t_operr                 # yes
3608        bra.b           _L17_6s
3609_L17_4s:
3610        cmpi.b          %d1,&QNAN               # is operand a QNAN?
3611        bne.b           _L17_5s                 # no
3612        bsr.l           src_qnan                        # yes
3613        bra.b           _L17_6s
3614_L17_5s:
3615        bsr.l           sacosd                  # operand is a DENORM
3616_L17_6s:
3617
3618#
3619#       Result is now in FP0
3620#
3621        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
3622        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3623        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
3624        unlk            %a6
3625        rts
3626
3627        global          _facosd_
3628_facosd_:
3629        link            %a6,&-LOCAL_SIZE
3630
3631        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
3632        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3633        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
3634
3635        fmov.l          &0x0,%fpcr              # zero FPCR
3636
3637#
3638#       copy, convert, and tag input argument
3639#
3640        fmov.d          0x8(%a6),%fp0           # load dbl input
3641        fmov.x          %fp0,FP_SRC(%a6)
3642        lea             FP_SRC(%a6),%a0
3643        bsr.l           tag                     # fetch operand type
3644        mov.b           %d0,STAG(%a6)
3645        mov.b           %d0,%d1
3646
3647        andi.l          &0x00ff00ff,USER_FPSR(%a6)
3648
3649        clr.l           %d0
3650        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
3651
3652        mov.b           %d1,STAG(%a6)
3653        tst.b           %d1
3654        bne.b           _L17_2d
3655        bsr.l           sacos                   # operand is a NORM
3656        bra.b           _L17_6d
3657_L17_2d:
3658        cmpi.b          %d1,&ZERO               # is operand a ZERO?
3659        bne.b           _L17_3d                 # no
3660        bsr.l           ld_ppi2                 # yes
3661        bra.b           _L17_6d
3662_L17_3d:
3663        cmpi.b          %d1,&INF                # is operand an INF?
3664        bne.b           _L17_4d                 # no
3665        bsr.l           t_operr                 # yes
3666        bra.b           _L17_6d
3667_L17_4d:
3668        cmpi.b          %d1,&QNAN               # is operand a QNAN?
3669        bne.b           _L17_5d                 # no
3670        bsr.l           src_qnan                        # yes
3671        bra.b           _L17_6d
3672_L17_5d:
3673        bsr.l           sacosd                  # operand is a DENORM
3674_L17_6d:
3675
3676#
3677#       Result is now in FP0
3678#
3679        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
3680        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3681        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
3682        unlk            %a6
3683        rts
3684
3685        global          _facosx_
3686_facosx_:
3687        link            %a6,&-LOCAL_SIZE
3688
3689        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
3690        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3691        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
3692
3693        fmov.l          &0x0,%fpcr              # zero FPCR
3694
3695#
3696#       copy, convert, and tag input argument
3697#
3698        lea             FP_SRC(%a6),%a0
3699        mov.l           0x8+0x0(%a6),0x0(%a0)   # load ext input
3700        mov.l           0x8+0x4(%a6),0x4(%a0)
3701        mov.l           0x8+0x8(%a6),0x8(%a0)
3702        bsr.l           tag                     # fetch operand type
3703        mov.b           %d0,STAG(%a6)
3704        mov.b           %d0,%d1
3705
3706        andi.l          &0x00ff00ff,USER_FPSR(%a6)
3707
3708        clr.l           %d0
3709        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
3710
3711        tst.b           %d1
3712        bne.b           _L17_2x
3713        bsr.l           sacos                   # operand is a NORM
3714        bra.b           _L17_6x
3715_L17_2x:
3716        cmpi.b          %d1,&ZERO               # is operand a ZERO?
3717        bne.b           _L17_3x                 # no
3718        bsr.l           ld_ppi2                 # yes
3719        bra.b           _L17_6x
3720_L17_3x:
3721        cmpi.b          %d1,&INF                # is operand an INF?
3722        bne.b           _L17_4x                 # no
3723        bsr.l           t_operr                 # yes
3724        bra.b           _L17_6x
3725_L17_4x:
3726        cmpi.b          %d1,&QNAN               # is operand a QNAN?
3727        bne.b           _L17_5x                 # no
3728        bsr.l           src_qnan                        # yes
3729        bra.b           _L17_6x
3730_L17_5x:
3731        bsr.l           sacosd                  # operand is a DENORM
3732_L17_6x:
3733
3734#
3735#       Result is now in FP0
3736#
3737        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
3738        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3739        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
3740        unlk            %a6
3741        rts
3742
3743
3744#########################################################################
3745# MONADIC TEMPLATE                                                      #
3746#########################################################################
3747        global          _fgetexps_
3748_fgetexps_:
3749        link            %a6,&-LOCAL_SIZE
3750
3751        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
3752        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3753        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
3754
3755        fmov.l          &0x0,%fpcr              # zero FPCR
3756
3757#
3758#       copy, convert, and tag input argument
3759#
3760        fmov.s          0x8(%a6),%fp0           # load sgl input
3761        fmov.x          %fp0,FP_SRC(%a6)
3762        lea             FP_SRC(%a6),%a0
3763        bsr.l           tag                     # fetch operand type
3764        mov.b           %d0,STAG(%a6)
3765        mov.b           %d0,%d1
3766
3767        andi.l          &0x00ff00ff,USER_FPSR(%a6)
3768
3769        clr.l           %d0
3770        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
3771
3772        tst.b           %d1
3773        bne.b           _L18_2s
3774        bsr.l           sgetexp                 # operand is a NORM
3775        bra.b           _L18_6s
3776_L18_2s:
3777        cmpi.b          %d1,&ZERO               # is operand a ZERO?
3778        bne.b           _L18_3s                 # no
3779        bsr.l           src_zero                        # yes
3780        bra.b           _L18_6s
3781_L18_3s:
3782        cmpi.b          %d1,&INF                # is operand an INF?
3783        bne.b           _L18_4s                 # no
3784        bsr.l           t_operr                 # yes
3785        bra.b           _L18_6s
3786_L18_4s:
3787        cmpi.b          %d1,&QNAN               # is operand a QNAN?
3788        bne.b           _L18_5s                 # no
3789        bsr.l           src_qnan                        # yes
3790        bra.b           _L18_6s
3791_L18_5s:
3792        bsr.l           sgetexpd                        # operand is a DENORM
3793_L18_6s:
3794
3795#
3796#       Result is now in FP0
3797#
3798        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
3799        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3800        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
3801        unlk            %a6
3802        rts
3803
3804        global          _fgetexpd_
3805_fgetexpd_:
3806        link            %a6,&-LOCAL_SIZE
3807
3808        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
3809        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3810        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
3811
3812        fmov.l          &0x0,%fpcr              # zero FPCR
3813
3814#
3815#       copy, convert, and tag input argument
3816#
3817        fmov.d          0x8(%a6),%fp0           # load dbl input
3818        fmov.x          %fp0,FP_SRC(%a6)
3819        lea             FP_SRC(%a6),%a0
3820        bsr.l           tag                     # fetch operand type
3821        mov.b           %d0,STAG(%a6)
3822        mov.b           %d0,%d1
3823
3824        andi.l          &0x00ff00ff,USER_FPSR(%a6)
3825
3826        clr.l           %d0
3827        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
3828
3829        mov.b           %d1,STAG(%a6)
3830        tst.b           %d1
3831        bne.b           _L18_2d
3832        bsr.l           sgetexp                 # operand is a NORM
3833        bra.b           _L18_6d
3834_L18_2d:
3835        cmpi.b          %d1,&ZERO               # is operand a ZERO?
3836        bne.b           _L18_3d                 # no
3837        bsr.l           src_zero                        # yes
3838        bra.b           _L18_6d
3839_L18_3d:
3840        cmpi.b          %d1,&INF                # is operand an INF?
3841        bne.b           _L18_4d                 # no
3842        bsr.l           t_operr                 # yes
3843        bra.b           _L18_6d
3844_L18_4d:
3845        cmpi.b          %d1,&QNAN               # is operand a QNAN?
3846        bne.b           _L18_5d                 # no
3847        bsr.l           src_qnan                        # yes
3848        bra.b           _L18_6d
3849_L18_5d:
3850        bsr.l           sgetexpd                        # operand is a DENORM
3851_L18_6d:
3852
3853#
3854#       Result is now in FP0
3855#
3856        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
3857        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3858        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
3859        unlk            %a6
3860        rts
3861
3862        global          _fgetexpx_
3863_fgetexpx_:
3864        link            %a6,&-LOCAL_SIZE
3865
3866        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
3867        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3868        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
3869
3870        fmov.l          &0x0,%fpcr              # zero FPCR
3871
3872#
3873#       copy, convert, and tag input argument
3874#
3875        lea             FP_SRC(%a6),%a0
3876        mov.l           0x8+0x0(%a6),0x0(%a0)   # load ext input
3877        mov.l           0x8+0x4(%a6),0x4(%a0)
3878        mov.l           0x8+0x8(%a6),0x8(%a0)
3879        bsr.l           tag                     # fetch operand type
3880        mov.b           %d0,STAG(%a6)
3881        mov.b           %d0,%d1
3882
3883        andi.l          &0x00ff00ff,USER_FPSR(%a6)
3884
3885        clr.l           %d0
3886        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
3887
3888        tst.b           %d1
3889        bne.b           _L18_2x
3890        bsr.l           sgetexp                 # operand is a NORM
3891        bra.b           _L18_6x
3892_L18_2x:
3893        cmpi.b          %d1,&ZERO               # is operand a ZERO?
3894        bne.b           _L18_3x                 # no
3895        bsr.l           src_zero                        # yes
3896        bra.b           _L18_6x
3897_L18_3x:
3898        cmpi.b          %d1,&INF                # is operand an INF?
3899        bne.b           _L18_4x                 # no
3900        bsr.l           t_operr                 # yes
3901        bra.b           _L18_6x
3902_L18_4x:
3903        cmpi.b          %d1,&QNAN               # is operand a QNAN?
3904        bne.b           _L18_5x                 # no
3905        bsr.l           src_qnan                        # yes
3906        bra.b           _L18_6x
3907_L18_5x:
3908        bsr.l           sgetexpd                        # operand is a DENORM
3909_L18_6x:
3910
3911#
3912#       Result is now in FP0
3913#
3914        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
3915        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3916        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
3917        unlk            %a6
3918        rts
3919
3920
3921#########################################################################
3922# MONADIC TEMPLATE                                                      #
3923#########################################################################
3924        global          _fgetmans_
3925_fgetmans_:
3926        link            %a6,&-LOCAL_SIZE
3927
3928        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
3929        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3930        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
3931
3932        fmov.l          &0x0,%fpcr              # zero FPCR
3933
3934#
3935#       copy, convert, and tag input argument
3936#
3937        fmov.s          0x8(%a6),%fp0           # load sgl input
3938        fmov.x          %fp0,FP_SRC(%a6)
3939        lea             FP_SRC(%a6),%a0
3940        bsr.l           tag                     # fetch operand type
3941        mov.b           %d0,STAG(%a6)
3942        mov.b           %d0,%d1
3943
3944        andi.l          &0x00ff00ff,USER_FPSR(%a6)
3945
3946        clr.l           %d0
3947        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
3948
3949        tst.b           %d1
3950        bne.b           _L19_2s
3951        bsr.l           sgetman                 # operand is a NORM
3952        bra.b           _L19_6s
3953_L19_2s:
3954        cmpi.b          %d1,&ZERO               # is operand a ZERO?
3955        bne.b           _L19_3s                 # no
3956        bsr.l           src_zero                        # yes
3957        bra.b           _L19_6s
3958_L19_3s:
3959        cmpi.b          %d1,&INF                # is operand an INF?
3960        bne.b           _L19_4s                 # no
3961        bsr.l           t_operr                 # yes
3962        bra.b           _L19_6s
3963_L19_4s:
3964        cmpi.b          %d1,&QNAN               # is operand a QNAN?
3965        bne.b           _L19_5s                 # no
3966        bsr.l           src_qnan                        # yes
3967        bra.b           _L19_6s
3968_L19_5s:
3969        bsr.l           sgetmand                        # operand is a DENORM
3970_L19_6s:
3971
3972#
3973#       Result is now in FP0
3974#
3975        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
3976        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3977        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
3978        unlk            %a6
3979        rts
3980
3981        global          _fgetmand_
3982_fgetmand_:
3983        link            %a6,&-LOCAL_SIZE
3984
3985        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
3986        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3987        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
3988
3989        fmov.l          &0x0,%fpcr              # zero FPCR
3990
3991#
3992#       copy, convert, and tag input argument
3993#
3994        fmov.d          0x8(%a6),%fp0           # load dbl input
3995        fmov.x          %fp0,FP_SRC(%a6)
3996        lea             FP_SRC(%a6),%a0
3997        bsr.l           tag                     # fetch operand type
3998        mov.b           %d0,STAG(%a6)
3999        mov.b           %d0,%d1
4000
4001        andi.l          &0x00ff00ff,USER_FPSR(%a6)
4002
4003        clr.l           %d0
4004        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
4005
4006        mov.b           %d1,STAG(%a6)
4007        tst.b           %d1
4008        bne.b           _L19_2d
4009        bsr.l           sgetman                 # operand is a NORM
4010        bra.b           _L19_6d
4011_L19_2d:
4012        cmpi.b          %d1,&ZERO               # is operand a ZERO?
4013        bne.b           _L19_3d                 # no
4014        bsr.l           src_zero                        # yes
4015        bra.b           _L19_6d
4016_L19_3d:
4017        cmpi.b          %d1,&INF                # is operand an INF?
4018        bne.b           _L19_4d                 # no
4019        bsr.l           t_operr                 # yes
4020        bra.b           _L19_6d
4021_L19_4d:
4022        cmpi.b          %d1,&QNAN               # is operand a QNAN?
4023        bne.b           _L19_5d                 # no
4024        bsr.l           src_qnan                        # yes
4025        bra.b           _L19_6d
4026_L19_5d:
4027        bsr.l           sgetmand                        # operand is a DENORM
4028_L19_6d:
4029
4030#
4031#       Result is now in FP0
4032#
4033        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
4034        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4035        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
4036        unlk            %a6
4037        rts
4038
4039        global          _fgetmanx_
4040_fgetmanx_:
4041        link            %a6,&-LOCAL_SIZE
4042
4043        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
4044        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4045        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
4046
4047        fmov.l          &0x0,%fpcr              # zero FPCR
4048
4049#
4050#       copy, convert, and tag input argument
4051#
4052        lea             FP_SRC(%a6),%a0
4053        mov.l           0x8+0x0(%a6),0x0(%a0)   # load ext input
4054        mov.l           0x8+0x4(%a6),0x4(%a0)
4055        mov.l           0x8+0x8(%a6),0x8(%a0)
4056        bsr.l           tag                     # fetch operand type
4057        mov.b           %d0,STAG(%a6)
4058        mov.b           %d0,%d1
4059
4060        andi.l          &0x00ff00ff,USER_FPSR(%a6)
4061
4062        clr.l           %d0
4063        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
4064
4065        tst.b           %d1
4066        bne.b           _L19_2x
4067        bsr.l           sgetman                 # operand is a NORM
4068        bra.b           _L19_6x
4069_L19_2x:
4070        cmpi.b          %d1,&ZERO               # is operand a ZERO?
4071        bne.b           _L19_3x                 # no
4072        bsr.l           src_zero                        # yes
4073        bra.b           _L19_6x
4074_L19_3x:
4075        cmpi.b          %d1,&INF                # is operand an INF?
4076        bne.b           _L19_4x                 # no
4077        bsr.l           t_operr                 # yes
4078        bra.b           _L19_6x
4079_L19_4x:
4080        cmpi.b          %d1,&QNAN               # is operand a QNAN?
4081        bne.b           _L19_5x                 # no
4082        bsr.l           src_qnan                        # yes
4083        bra.b           _L19_6x
4084_L19_5x:
4085        bsr.l           sgetmand                        # operand is a DENORM
4086_L19_6x:
4087
4088#
4089#       Result is now in FP0
4090#
4091        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
4092        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4093        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
4094        unlk            %a6
4095        rts
4096
4097
4098#########################################################################
4099# MONADIC TEMPLATE                                                      #
4100#########################################################################
4101        global          _fsincoss_
4102_fsincoss_:
4103        link            %a6,&-LOCAL_SIZE
4104
4105        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
4106        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4107        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
4108
4109        fmov.l          &0x0,%fpcr              # zero FPCR
4110
4111#
4112#       copy, convert, and tag input argument
4113#
4114        fmov.s          0x8(%a6),%fp0           # load sgl input
4115        fmov.x          %fp0,FP_SRC(%a6)
4116        lea             FP_SRC(%a6),%a0
4117        bsr.l           tag                     # fetch operand type
4118        mov.b           %d0,STAG(%a6)
4119        mov.b           %d0,%d1
4120
4121        andi.l          &0x00ff00ff,USER_FPSR(%a6)
4122
4123        clr.l           %d0
4124        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
4125
4126        tst.b           %d1
4127        bne.b           _L20_2s
4128        bsr.l           ssincos                 # operand is a NORM
4129        bra.b           _L20_6s
4130_L20_2s:
4131        cmpi.b          %d1,&ZERO               # is operand a ZERO?
4132        bne.b           _L20_3s                 # no
4133        bsr.l           ssincosz                        # yes
4134        bra.b           _L20_6s
4135_L20_3s:
4136        cmpi.b          %d1,&INF                # is operand an INF?
4137        bne.b           _L20_4s                 # no
4138        bsr.l           ssincosi                        # yes
4139        bra.b           _L20_6s
4140_L20_4s:
4141        cmpi.b          %d1,&QNAN               # is operand a QNAN?
4142        bne.b           _L20_5s                 # no
4143        bsr.l           ssincosqnan                     # yes
4144        bra.b           _L20_6s
4145_L20_5s:
4146        bsr.l           ssincosd                        # operand is a DENORM
4147_L20_6s:
4148
4149#
4150#       Result is now in FP0
4151#
4152        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
4153        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4154        fmovm.x         &0x03,-(%sp)            # store off fp0/fp1
4155        fmovm.x         (%sp)+,&0x40            # fp0 now in fp1
4156        fmovm.x         (%sp)+,&0x80            # fp1 now in fp0
4157        unlk            %a6
4158        rts
4159
4160        global          _fsincosd_
4161_fsincosd_:
4162        link            %a6,&-LOCAL_SIZE
4163
4164        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
4165        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4166        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
4167
4168        fmov.l          &0x0,%fpcr              # zero FPCR
4169
4170#
4171#       copy, convert, and tag input argument
4172#
4173        fmov.d          0x8(%a6),%fp0           # load dbl input
4174        fmov.x          %fp0,FP_SRC(%a6)
4175        lea             FP_SRC(%a6),%a0
4176        bsr.l           tag                     # fetch operand type
4177        mov.b           %d0,STAG(%a6)
4178        mov.b           %d0,%d1
4179
4180        andi.l          &0x00ff00ff,USER_FPSR(%a6)
4181
4182        clr.l           %d0
4183        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
4184
4185        mov.b           %d1,STAG(%a6)
4186        tst.b           %d1
4187        bne.b           _L20_2d
4188        bsr.l           ssincos                 # operand is a NORM
4189        bra.b           _L20_6d
4190_L20_2d:
4191        cmpi.b          %d1,&ZERO               # is operand a ZERO?
4192        bne.b           _L20_3d                 # no
4193        bsr.l           ssincosz                        # yes
4194        bra.b           _L20_6d
4195_L20_3d:
4196        cmpi.b          %d1,&INF                # is operand an INF?
4197        bne.b           _L20_4d                 # no
4198        bsr.l           ssincosi                        # yes
4199        bra.b           _L20_6d
4200_L20_4d:
4201        cmpi.b          %d1,&QNAN               # is operand a QNAN?
4202        bne.b           _L20_5d                 # no
4203        bsr.l           ssincosqnan                     # yes
4204        bra.b           _L20_6d
4205_L20_5d:
4206        bsr.l           ssincosd                        # operand is a DENORM
4207_L20_6d:
4208
4209#
4210#       Result is now in FP0
4211#
4212        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
4213        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4214        fmovm.x         &0x03,-(%sp)            # store off fp0/fp1
4215        fmovm.x         (%sp)+,&0x40            # fp0 now in fp1
4216        fmovm.x         (%sp)+,&0x80            # fp1 now in fp0
4217        unlk            %a6
4218        rts
4219
4220        global          _fsincosx_
4221_fsincosx_:
4222        link            %a6,&-LOCAL_SIZE
4223
4224        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
4225        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4226        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
4227
4228        fmov.l          &0x0,%fpcr              # zero FPCR
4229
4230#
4231#       copy, convert, and tag input argument
4232#
4233        lea             FP_SRC(%a6),%a0
4234        mov.l           0x8+0x0(%a6),0x0(%a0)   # load ext input
4235        mov.l           0x8+0x4(%a6),0x4(%a0)
4236        mov.l           0x8+0x8(%a6),0x8(%a0)
4237        bsr.l           tag                     # fetch operand type
4238        mov.b           %d0,STAG(%a6)
4239        mov.b           %d0,%d1
4240
4241        andi.l          &0x00ff00ff,USER_FPSR(%a6)
4242
4243        clr.l           %d0
4244        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
4245
4246        tst.b           %d1
4247        bne.b           _L20_2x
4248        bsr.l           ssincos                 # operand is a NORM
4249        bra.b           _L20_6x
4250_L20_2x:
4251        cmpi.b          %d1,&ZERO               # is operand a ZERO?
4252        bne.b           _L20_3x                 # no
4253        bsr.l           ssincosz                        # yes
4254        bra.b           _L20_6x
4255_L20_3x:
4256        cmpi.b          %d1,&INF                # is operand an INF?
4257        bne.b           _L20_4x                 # no
4258        bsr.l           ssincosi                        # yes
4259        bra.b           _L20_6x
4260_L20_4x:
4261        cmpi.b          %d1,&QNAN               # is operand a QNAN?
4262        bne.b           _L20_5x                 # no
4263        bsr.l           ssincosqnan                     # yes
4264        bra.b           _L20_6x
4265_L20_5x:
4266        bsr.l           ssincosd                        # operand is a DENORM
4267_L20_6x:
4268
4269#
4270#       Result is now in FP0
4271#
4272        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
4273        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4274        fmovm.x         &0x03,-(%sp)            # store off fp0/fp1
4275        fmovm.x         (%sp)+,&0x40            # fp0 now in fp1
4276        fmovm.x         (%sp)+,&0x80            # fp1 now in fp0
4277        unlk            %a6
4278        rts
4279
4280
4281#########################################################################
4282# DYADIC TEMPLATE                                                       #
4283#########################################################################
4284        global          _frems_
4285_frems_:
4286        link            %a6,&-LOCAL_SIZE
4287
4288        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
4289        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4290        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
4291
4292        fmov.l          &0x0,%fpcr              # zero FPCR
4293
4294#
4295#       copy, convert, and tag input argument
4296#
4297        fmov.s          0x8(%a6),%fp0           # load sgl dst
4298        fmov.x          %fp0,FP_DST(%a6)
4299        lea             FP_DST(%a6),%a0
4300        bsr.l           tag                     # fetch operand type
4301        mov.b           %d0,DTAG(%a6)
4302
4303        fmov.s          0xc(%a6),%fp0           # load sgl src
4304        fmov.x          %fp0,FP_SRC(%a6)
4305        lea             FP_SRC(%a6),%a0
4306        bsr.l           tag                     # fetch operand type
4307        mov.b           %d0,STAG(%a6)
4308        mov.l           %d0,%d1
4309
4310        andi.l          &0x00ff00ff,USER_FPSR(%a6)
4311
4312        clr.l           %d0
4313        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
4314
4315        lea             FP_SRC(%a6),%a0         # pass ptr to src
4316        lea             FP_DST(%a6),%a1         # pass ptr to dst
4317
4318        tst.b           %d1
4319        bne.b           _L21_2s
4320        bsr.l           srem_snorm                      # operand is a NORM
4321        bra.b           _L21_6s
4322_L21_2s:
4323        cmpi.b          %d1,&ZERO               # is operand a ZERO?
4324        bne.b           _L21_3s                 # no
4325        bsr.l           srem_szero                      # yes
4326        bra.b           _L21_6s
4327_L21_3s:
4328        cmpi.b          %d1,&INF                # is operand an INF?
4329        bne.b           _L21_4s                 # no
4330        bsr.l           srem_sinf                       # yes
4331        bra.b           _L21_6s
4332_L21_4s:
4333        cmpi.b          %d1,&QNAN               # is operand a QNAN?
4334        bne.b           _L21_5s                 # no
4335        bsr.l           sop_sqnan                       # yes
4336        bra.b           _L21_6s
4337_L21_5s:
4338        bsr.l           srem_sdnrm                      # operand is a DENORM
4339_L21_6s:
4340
4341#
4342#       Result is now in FP0
4343#
4344        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
4345        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4346        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
4347        unlk            %a6
4348        rts
4349
4350        global          _fremd_
4351_fremd_:
4352        link            %a6,&-LOCAL_SIZE
4353
4354        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
4355        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4356        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
4357
4358        fmov.l          &0x0,%fpcr              # zero FPCR
4359
4360#
4361#       copy, convert, and tag input argument
4362#
4363        fmov.d          0x8(%a6),%fp0           # load dbl dst
4364        fmov.x          %fp0,FP_DST(%a6)
4365        lea             FP_DST(%a6),%a0
4366        bsr.l           tag                     # fetch operand type
4367        mov.b           %d0,DTAG(%a6)
4368
4369        fmov.d          0x10(%a6),%fp0          # load dbl src
4370        fmov.x          %fp0,FP_SRC(%a6)
4371        lea             FP_SRC(%a6),%a0
4372        bsr.l           tag                     # fetch operand type
4373        mov.b           %d0,STAG(%a6)
4374        mov.l           %d0,%d1
4375
4376        andi.l          &0x00ff00ff,USER_FPSR(%a6)
4377
4378        clr.l           %d0
4379        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
4380
4381        lea             FP_SRC(%a6),%a0         # pass ptr to src
4382        lea             FP_DST(%a6),%a1         # pass ptr to dst
4383
4384        tst.b           %d1
4385        bne.b           _L21_2d
4386        bsr.l           srem_snorm                      # operand is a NORM
4387        bra.b           _L21_6d
4388_L21_2d:
4389        cmpi.b          %d1,&ZERO               # is operand a ZERO?
4390        bne.b           _L21_3d                 # no
4391        bsr.l           srem_szero                      # yes
4392        bra.b           _L21_6d
4393_L21_3d:
4394        cmpi.b          %d1,&INF                # is operand an INF?
4395        bne.b           _L21_4d                 # no
4396        bsr.l           srem_sinf                       # yes
4397        bra.b           _L21_6d
4398_L21_4d:
4399        cmpi.b          %d1,&QNAN               # is operand a QNAN?
4400        bne.b           _L21_5d                 # no
4401        bsr.l           sop_sqnan                       # yes
4402        bra.b           _L21_6d
4403_L21_5d:
4404        bsr.l           srem_sdnrm                      # operand is a DENORM
4405_L21_6d:
4406
4407#
4408#       Result is now in FP0
4409#
4410        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
4411        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4412        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
4413        unlk            %a6
4414        rts
4415
4416        global          _fremx_
4417_fremx_:
4418        link            %a6,&-LOCAL_SIZE
4419
4420        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
4421        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4422        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
4423
4424        fmov.l          &0x0,%fpcr              # zero FPCR
4425
4426#
4427#       copy, convert, and tag input argument
4428#
4429        lea             FP_DST(%a6),%a0
4430        mov.l           0x8+0x0(%a6),0x0(%a0)   # load ext dst
4431        mov.l           0x8+0x4(%a6),0x4(%a0)
4432        mov.l           0x8+0x8(%a6),0x8(%a0)
4433        bsr.l           tag                     # fetch operand type
4434        mov.b           %d0,DTAG(%a6)
4435
4436        lea             FP_SRC(%a6),%a0
4437        mov.l           0x14+0x0(%a6),0x0(%a0)  # load ext src
4438        mov.l           0x14+0x4(%a6),0x4(%a0)
4439        mov.l           0x14+0x8(%a6),0x8(%a0)
4440        bsr.l           tag                     # fetch operand type
4441        mov.b           %d0,STAG(%a6)
4442        mov.l           %d0,%d1
4443
4444        andi.l          &0x00ff00ff,USER_FPSR(%a6)
4445
4446        clr.l           %d0
4447        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
4448
4449        lea             FP_SRC(%a6),%a0         # pass ptr to src
4450        lea             FP_DST(%a6),%a1         # pass ptr to dst
4451
4452        tst.b           %d1
4453        bne.b           _L21_2x
4454        bsr.l           srem_snorm                      # operand is a NORM
4455        bra.b           _L21_6x
4456_L21_2x:
4457        cmpi.b          %d1,&ZERO               # is operand a ZERO?
4458        bne.b           _L21_3x                 # no
4459        bsr.l           srem_szero                      # yes
4460        bra.b           _L21_6x
4461_L21_3x:
4462        cmpi.b          %d1,&INF                # is operand an INF?
4463        bne.b           _L21_4x                 # no
4464        bsr.l           srem_sinf                       # yes
4465        bra.b           _L21_6x
4466_L21_4x:
4467        cmpi.b          %d1,&QNAN               # is operand a QNAN?
4468        bne.b           _L21_5x                 # no
4469        bsr.l           sop_sqnan                       # yes
4470        bra.b           _L21_6x
4471_L21_5x:
4472        bsr.l           srem_sdnrm                      # operand is a DENORM
4473_L21_6x:
4474
4475#
4476#       Result is now in FP0
4477#
4478        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
4479        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4480        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
4481        unlk            %a6
4482        rts
4483
4484
4485#########################################################################
4486# DYADIC TEMPLATE                                                       #
4487#########################################################################
4488        global          _fmods_
4489_fmods_:
4490        link            %a6,&-LOCAL_SIZE
4491
4492        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
4493        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4494        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
4495
4496        fmov.l          &0x0,%fpcr              # zero FPCR
4497
4498#
4499#       copy, convert, and tag input argument
4500#
4501        fmov.s          0x8(%a6),%fp0           # load sgl dst
4502        fmov.x          %fp0,FP_DST(%a6)
4503        lea             FP_DST(%a6),%a0
4504        bsr.l           tag                     # fetch operand type
4505        mov.b           %d0,DTAG(%a6)
4506
4507        fmov.s          0xc(%a6),%fp0           # load sgl src
4508        fmov.x          %fp0,FP_SRC(%a6)
4509        lea             FP_SRC(%a6),%a0
4510        bsr.l           tag                     # fetch operand type
4511        mov.b           %d0,STAG(%a6)
4512        mov.l           %d0,%d1
4513
4514        andi.l          &0x00ff00ff,USER_FPSR(%a6)
4515
4516        clr.l           %d0
4517        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
4518
4519        lea             FP_SRC(%a6),%a0         # pass ptr to src
4520        lea             FP_DST(%a6),%a1         # pass ptr to dst
4521
4522        tst.b           %d1
4523        bne.b           _L22_2s
4524        bsr.l           smod_snorm                      # operand is a NORM
4525        bra.b           _L22_6s
4526_L22_2s:
4527        cmpi.b          %d1,&ZERO               # is operand a ZERO?
4528        bne.b           _L22_3s                 # no
4529        bsr.l           smod_szero                      # yes
4530        bra.b           _L22_6s
4531_L22_3s:
4532        cmpi.b          %d1,&INF                # is operand an INF?
4533        bne.b           _L22_4s                 # no
4534        bsr.l           smod_sinf                       # yes
4535        bra.b           _L22_6s
4536_L22_4s:
4537        cmpi.b          %d1,&QNAN               # is operand a QNAN?
4538        bne.b           _L22_5s                 # no
4539        bsr.l           sop_sqnan                       # yes
4540        bra.b           _L22_6s
4541_L22_5s:
4542        bsr.l           smod_sdnrm                      # operand is a DENORM
4543_L22_6s:
4544
4545#
4546#       Result is now in FP0
4547#
4548        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
4549        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4550        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
4551        unlk            %a6
4552        rts
4553
4554        global          _fmodd_
4555_fmodd_:
4556        link            %a6,&-LOCAL_SIZE
4557
4558        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
4559        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4560        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
4561
4562        fmov.l          &0x0,%fpcr              # zero FPCR
4563
4564#
4565#       copy, convert, and tag input argument
4566#
4567        fmov.d          0x8(%a6),%fp0           # load dbl dst
4568        fmov.x          %fp0,FP_DST(%a6)
4569        lea             FP_DST(%a6),%a0
4570        bsr.l           tag                     # fetch operand type
4571        mov.b           %d0,DTAG(%a6)
4572
4573        fmov.d          0x10(%a6),%fp0          # load dbl src
4574        fmov.x          %fp0,FP_SRC(%a6)
4575        lea             FP_SRC(%a6),%a0
4576        bsr.l           tag                     # fetch operand type
4577        mov.b           %d0,STAG(%a6)
4578        mov.l           %d0,%d1
4579
4580        andi.l          &0x00ff00ff,USER_FPSR(%a6)
4581
4582        clr.l           %d0
4583        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
4584
4585        lea             FP_SRC(%a6),%a0         # pass ptr to src
4586        lea             FP_DST(%a6),%a1         # pass ptr to dst
4587
4588        tst.b           %d1
4589        bne.b           _L22_2d
4590        bsr.l           smod_snorm                      # operand is a NORM
4591        bra.b           _L22_6d
4592_L22_2d:
4593        cmpi.b          %d1,&ZERO               # is operand a ZERO?
4594        bne.b           _L22_3d                 # no
4595        bsr.l           smod_szero                      # yes
4596        bra.b           _L22_6d
4597_L22_3d:
4598        cmpi.b          %d1,&INF                # is operand an INF?
4599        bne.b           _L22_4d                 # no
4600        bsr.l           smod_sinf                       # yes
4601        bra.b           _L22_6d
4602_L22_4d:
4603        cmpi.b          %d1,&QNAN               # is operand a QNAN?
4604        bne.b           _L22_5d                 # no
4605        bsr.l           sop_sqnan                       # yes
4606        bra.b           _L22_6d
4607_L22_5d:
4608        bsr.l           smod_sdnrm                      # operand is a DENORM
4609_L22_6d:
4610
4611#
4612#       Result is now in FP0
4613#
4614        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
4615        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4616        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
4617        unlk            %a6
4618        rts
4619
4620        global          _fmodx_
4621_fmodx_:
4622        link            %a6,&-LOCAL_SIZE
4623
4624        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
4625        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4626        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
4627
4628        fmov.l          &0x0,%fpcr              # zero FPCR
4629
4630#
4631#       copy, convert, and tag input argument
4632#
4633        lea             FP_DST(%a6),%a0
4634        mov.l           0x8+0x0(%a6),0x0(%a0)   # load ext dst
4635        mov.l           0x8+0x4(%a6),0x4(%a0)
4636        mov.l           0x8+0x8(%a6),0x8(%a0)
4637        bsr.l           tag                     # fetch operand type
4638        mov.b           %d0,DTAG(%a6)
4639
4640        lea             FP_SRC(%a6),%a0
4641        mov.l           0x14+0x0(%a6),0x0(%a0)  # load ext src
4642        mov.l           0x14+0x4(%a6),0x4(%a0)
4643        mov.l           0x14+0x8(%a6),0x8(%a0)
4644        bsr.l           tag                     # fetch operand type
4645        mov.b           %d0,STAG(%a6)
4646        mov.l           %d0,%d1
4647
4648        andi.l          &0x00ff00ff,USER_FPSR(%a6)
4649
4650        clr.l           %d0
4651        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
4652
4653        lea             FP_SRC(%a6),%a0         # pass ptr to src
4654        lea             FP_DST(%a6),%a1         # pass ptr to dst
4655
4656        tst.b           %d1
4657        bne.b           _L22_2x
4658        bsr.l           smod_snorm                      # operand is a NORM
4659        bra.b           _L22_6x
4660_L22_2x:
4661        cmpi.b          %d1,&ZERO               # is operand a ZERO?
4662        bne.b           _L22_3x                 # no
4663        bsr.l           smod_szero                      # yes
4664        bra.b           _L22_6x
4665_L22_3x:
4666        cmpi.b          %d1,&INF                # is operand an INF?
4667        bne.b           _L22_4x                 # no
4668        bsr.l           smod_sinf                       # yes
4669        bra.b           _L22_6x
4670_L22_4x:
4671        cmpi.b          %d1,&QNAN               # is operand a QNAN?
4672        bne.b           _L22_5x                 # no
4673        bsr.l           sop_sqnan                       # yes
4674        bra.b           _L22_6x
4675_L22_5x:
4676        bsr.l           smod_sdnrm                      # operand is a DENORM
4677_L22_6x:
4678
4679#
4680#       Result is now in FP0
4681#
4682        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
4683        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4684        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
4685        unlk            %a6
4686        rts
4687
4688
4689#########################################################################
4690# DYADIC TEMPLATE                                                       #
4691#########################################################################
4692        global          _fscales_
4693_fscales_:
4694        link            %a6,&-LOCAL_SIZE
4695
4696        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
4697        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4698        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
4699
4700        fmov.l          &0x0,%fpcr              # zero FPCR
4701
4702#
4703#       copy, convert, and tag input argument
4704#
4705        fmov.s          0x8(%a6),%fp0           # load sgl dst
4706        fmov.x          %fp0,FP_DST(%a6)
4707        lea             FP_DST(%a6),%a0
4708        bsr.l           tag                     # fetch operand type
4709        mov.b           %d0,DTAG(%a6)
4710
4711        fmov.s          0xc(%a6),%fp0           # load sgl src
4712        fmov.x          %fp0,FP_SRC(%a6)
4713        lea             FP_SRC(%a6),%a0
4714        bsr.l           tag                     # fetch operand type
4715        mov.b           %d0,STAG(%a6)
4716        mov.l           %d0,%d1
4717
4718        andi.l          &0x00ff00ff,USER_FPSR(%a6)
4719
4720        clr.l           %d0
4721        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
4722
4723        lea             FP_SRC(%a6),%a0         # pass ptr to src
4724        lea             FP_DST(%a6),%a1         # pass ptr to dst
4725
4726        tst.b           %d1
4727        bne.b           _L23_2s
4728        bsr.l           sscale_snorm                    # operand is a NORM
4729        bra.b           _L23_6s
4730_L23_2s:
4731        cmpi.b          %d1,&ZERO               # is operand a ZERO?
4732        bne.b           _L23_3s                 # no
4733        bsr.l           sscale_szero                    # yes
4734        bra.b           _L23_6s
4735_L23_3s:
4736        cmpi.b          %d1,&INF                # is operand an INF?
4737        bne.b           _L23_4s                 # no
4738        bsr.l           sscale_sinf                     # yes
4739        bra.b           _L23_6s
4740_L23_4s:
4741        cmpi.b          %d1,&QNAN               # is operand a QNAN?
4742        bne.b           _L23_5s                 # no
4743        bsr.l           sop_sqnan                       # yes
4744        bra.b           _L23_6s
4745_L23_5s:
4746        bsr.l           sscale_sdnrm                    # operand is a DENORM
4747_L23_6s:
4748
4749#
4750#       Result is now in FP0
4751#
4752        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
4753        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4754        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
4755        unlk            %a6
4756        rts
4757
4758        global          _fscaled_
4759_fscaled_:
4760        link            %a6,&-LOCAL_SIZE
4761
4762        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
4763        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4764        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
4765
4766        fmov.l          &0x0,%fpcr              # zero FPCR
4767
4768#
4769#       copy, convert, and tag input argument
4770#
4771        fmov.d          0x8(%a6),%fp0           # load dbl dst
4772        fmov.x          %fp0,FP_DST(%a6)
4773        lea             FP_DST(%a6),%a0
4774        bsr.l           tag                     # fetch operand type
4775        mov.b           %d0,DTAG(%a6)
4776
4777        fmov.d          0x10(%a6),%fp0          # load dbl src
4778        fmov.x          %fp0,FP_SRC(%a6)
4779        lea             FP_SRC(%a6),%a0
4780        bsr.l           tag                     # fetch operand type
4781        mov.b           %d0,STAG(%a6)
4782        mov.l           %d0,%d1
4783
4784        andi.l          &0x00ff00ff,USER_FPSR(%a6)
4785
4786        clr.l           %d0
4787        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
4788
4789        lea             FP_SRC(%a6),%a0         # pass ptr to src
4790        lea             FP_DST(%a6),%a1         # pass ptr to dst
4791
4792        tst.b           %d1
4793        bne.b           _L23_2d
4794        bsr.l           sscale_snorm                    # operand is a NORM
4795        bra.b           _L23_6d
4796_L23_2d:
4797        cmpi.b          %d1,&ZERO               # is operand a ZERO?
4798        bne.b           _L23_3d                 # no
4799        bsr.l           sscale_szero                    # yes
4800        bra.b           _L23_6d
4801_L23_3d:
4802        cmpi.b          %d1,&INF                # is operand an INF?
4803        bne.b           _L23_4d                 # no
4804        bsr.l           sscale_sinf                     # yes
4805        bra.b           _L23_6d
4806_L23_4d:
4807        cmpi.b          %d1,&QNAN               # is operand a QNAN?
4808        bne.b           _L23_5d                 # no
4809        bsr.l           sop_sqnan                       # yes
4810        bra.b           _L23_6d
4811_L23_5d:
4812        bsr.l           sscale_sdnrm                    # operand is a DENORM
4813_L23_6d:
4814
4815#
4816#       Result is now in FP0
4817#
4818        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
4819        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4820        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
4821        unlk            %a6
4822        rts
4823
4824        global          _fscalex_
4825_fscalex_:
4826        link            %a6,&-LOCAL_SIZE
4827
4828        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
4829        fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4830        fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
4831
4832        fmov.l          &0x0,%fpcr              # zero FPCR
4833
4834#
4835#       copy, convert, and tag input argument
4836#
4837        lea             FP_DST(%a6),%a0
4838        mov.l           0x8+0x0(%a6),0x0(%a0)   # load ext dst
4839        mov.l           0x8+0x4(%a6),0x4(%a0)
4840        mov.l           0x8+0x8(%a6),0x8(%a0)
4841        bsr.l           tag                     # fetch operand type
4842        mov.b           %d0,DTAG(%a6)
4843
4844        lea             FP_SRC(%a6),%a0
4845        mov.l           0x14+0x0(%a6),0x0(%a0)  # load ext src
4846        mov.l           0x14+0x4(%a6),0x4(%a0)
4847        mov.l           0x14+0x8(%a6),0x8(%a0)
4848        bsr.l           tag                     # fetch operand type
4849        mov.b           %d0,STAG(%a6)
4850        mov.l           %d0,%d1
4851
4852        andi.l          &0x00ff00ff,USER_FPSR(%a6)
4853
4854        clr.l           %d0
4855        mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
4856
4857        lea             FP_SRC(%a6),%a0         # pass ptr to src
4858        lea             FP_DST(%a6),%a1         # pass ptr to dst
4859
4860        tst.b           %d1
4861        bne.b           _L23_2x
4862        bsr.l           sscale_snorm                    # operand is a NORM
4863        bra.b           _L23_6x
4864_L23_2x:
4865        cmpi.b          %d1,&ZERO               # is operand a ZERO?
4866        bne.b           _L23_3x                 # no
4867        bsr.l           sscale_szero                    # yes
4868        bra.b           _L23_6x
4869_L23_3x:
4870        cmpi.b          %d1,&INF                # is operand an INF?
4871        bne.b           _L23_4x                 # no
4872        bsr.l           sscale_sinf                     # yes
4873        bra.b           _L23_6x
4874_L23_4x:
4875        cmpi.b          %d1,&QNAN               # is operand a QNAN?
4876        bne.b           _L23_5x                 # no
4877        bsr.l           sop_sqnan                       # yes
4878        bra.b           _L23_6x
4879_L23_5x:
4880        bsr.l           sscale_sdnrm                    # operand is a DENORM
4881_L23_6x:
4882
4883#
4884#       Result is now in FP0
4885#
4886        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
4887        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4888        fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
4889        unlk            %a6
4890        rts
4891
4892
4893#########################################################################
4894# ssin():     computes the sine of a normalized input                   #
4895# ssind():    computes the sine of a denormalized input                 #
4896# scos():     computes the cosine of a normalized input                 #
4897# scosd():    computes the cosine of a denormalized input               #
4898# ssincos():  computes the sine and cosine of a normalized input        #
4899# ssincosd(): computes the sine and cosine of a denormalized input      #
4900#                                                                       #
4901# INPUT *************************************************************** #
4902#       a0 = pointer to extended precision input                        #
4903#       d0 = round precision,mode                                       #
4904#                                                                       #
4905# OUTPUT ************************************************************** #
4906#       fp0 = sin(X) or cos(X)                                          #
4907#                                                                       #
4908#    For ssincos(X):                                                    #
4909#       fp0 = sin(X)                                                    #
4910#       fp1 = cos(X)                                                    #
4911#                                                                       #
4912# ACCURACY and MONOTONICITY ******************************************* #
4913#       The returned result is within 1 ulp in 64 significant bit, i.e. #
4914#       within 0.5001 ulp to 53 bits if the result is subsequently      #
4915#       rounded to double precision. The result is provably monotonic   #
4916#       in double precision.                                            #
4917#                                                                       #
4918# ALGORITHM *********************************************************** #
4919#                                                                       #
4920#       SIN and COS:                                                    #
4921#       1. If SIN is invoked, set AdjN := 0; otherwise, set AdjN := 1.  #
4922#                                                                       #
4923#       2. If |X| >= 15Pi or |X| < 2**(-40), go to 7.                   #
4924#                                                                       #
4925#       3. Decompose X as X = N(Pi/2) + r where |r| <= Pi/4. Let        #
4926#               k = N mod 4, so in particular, k = 0,1,2,or 3.          #
4927#               Overwrite k by k := k + AdjN.                           #
4928#                                                                       #
4929#       4. If k is even, go to 6.                                       #
4930#                                                                       #
4931#       5. (k is odd) Set j := (k-1)/2, sgn := (-1)**j.                 #
4932#               Return sgn*cos(r) where cos(r) is approximated by an    #
4933#               even polynomial in r, 1 + r*r*(B1+s*(B2+ ... + s*B8)),  #
4934#               s = r*r.                                                #
4935#               Exit.                                                   #
4936#                                                                       #
4937#       6. (k is even) Set j := k/2, sgn := (-1)**j. Return sgn*sin(r)  #
4938#               where sin(r) is approximated by an odd polynomial in r  #
4939#               r + r*s*(A1+s*(A2+ ... + s*A7)),        s = r*r.        #
4940#               Exit.                                                   #
4941#                                                                       #
4942#       7. If |X| > 1, go to 9.                                         #
4943#                                                                       #
4944#       8. (|X|<2**(-40)) If SIN is invoked, return X;                  #
4945#               otherwise return 1.                                     #
4946#                                                                       #
4947#       9. Overwrite X by X := X rem 2Pi. Now that |X| <= Pi,           #
4948#               go back to 3.                                           #
4949#                                                                       #
4950#       SINCOS:                                                         #
4951#       1. If |X| >= 15Pi or |X| < 2**(-40), go to 6.                   #
4952#                                                                       #
4953#       2. Decompose X as X = N(Pi/2) + r where |r| <= Pi/4. Let        #
4954#               k = N mod 4, so in particular, k = 0,1,2,or 3.          #
4955#                                                                       #
4956#       3. If k is even, go to 5.                                       #
4957#                                                                       #
4958#       4. (k is odd) Set j1 := (k-1)/2, j2 := j1 (EOR) (k mod 2), ie.  #
4959#               j1 exclusive or with the l.s.b. of k.                   #
4960#               sgn1 := (-1)**j1, sgn2 := (-1)**j2.                     #
4961#               SIN(X) = sgn1 * cos(r) and COS(X) = sgn2*sin(r) where   #
4962#               sin(r) and cos(r) are computed as odd and even          #
4963#               polynomials in r, respectively. Exit                    #
4964#                                                                       #
4965#       5. (k is even) Set j1 := k/2, sgn1 := (-1)**j1.                 #
4966#               SIN(X) = sgn1 * sin(r) and COS(X) = sgn1*cos(r) where   #
4967#               sin(r) and cos(r) are computed as odd and even          #
4968#               polynomials in r, respectively. Exit                    #
4969#                                                                       #
4970#       6. If |X| > 1, go to 8.                                         #
4971#                                                                       #
4972#       7. (|X|<2**(-40)) SIN(X) = X and COS(X) = 1. Exit.              #
4973#                                                                       #
4974#       8. Overwrite X by X := X rem 2Pi. Now that |X| <= Pi,           #
4975#               go back to 2.                                           #
4976#                                                                       #
4977#########################################################################
4978
4979SINA7:  long            0xBD6AAA77,0xCCC994F5
4980SINA6:  long            0x3DE61209,0x7AAE8DA1
4981SINA5:  long            0xBE5AE645,0x2A118AE4
4982SINA4:  long            0x3EC71DE3,0xA5341531
4983SINA3:  long            0xBF2A01A0,0x1A018B59,0x00000000,0x00000000
4984SINA2:  long            0x3FF80000,0x88888888,0x888859AF,0x00000000
4985SINA1:  long            0xBFFC0000,0xAAAAAAAA,0xAAAAAA99,0x00000000
4986
4987COSB8:  long            0x3D2AC4D0,0xD6011EE3
4988COSB7:  long            0xBDA9396F,0x9F45AC19
4989COSB6:  long            0x3E21EED9,0x0612C972
4990COSB5:  long            0xBE927E4F,0xB79D9FCF
4991COSB4:  long            0x3EFA01A0,0x1A01D423,0x00000000,0x00000000
4992COSB3:  long            0xBFF50000,0xB60B60B6,0x0B61D438,0x00000000
4993COSB2:  long            0x3FFA0000,0xAAAAAAAA,0xAAAAAB5E
4994COSB1:  long            0xBF000000
4995
4996        set             INARG,FP_SCR0
4997
4998        set             X,FP_SCR0
4999#       set             XDCARE,X+2
5000        set             XFRAC,X+4
5001
5002        set             RPRIME,FP_SCR0
5003        set             SPRIME,FP_SCR1
5004
5005        set             POSNEG1,L_SCR1
5006        set             TWOTO63,L_SCR1
5007
5008        set             ENDFLAG,L_SCR2
5009        set             INT,L_SCR2
5010
5011        set             ADJN,L_SCR3
5012
5013############################################
5014        global          ssin
5015ssin:
5016        mov.l           &0,ADJN(%a6)            # yes; SET ADJN TO 0
5017        bra.b           SINBGN
5018
5019############################################
5020        global          scos
5021scos:
5022        mov.l           &1,ADJN(%a6)            # yes; SET ADJN TO 1
5023
5024############################################
5025SINBGN:
5026#--SAVE FPCR, FP1. CHECK IF |X| IS TOO SMALL OR LARGE
5027
5028        fmov.x          (%a0),%fp0              # LOAD INPUT
5029        fmov.x          %fp0,X(%a6)             # save input at X
5030
5031# "COMPACTIFY" X
5032        mov.l           (%a0),%d1               # put exp in hi word
5033        mov.w           4(%a0),%d1              # fetch hi(man)
5034        and.l           &0x7FFFFFFF,%d1         # strip sign
5035
5036        cmpi.l          %d1,&0x3FD78000         # is |X| >= 2**(-40)?
5037        bge.b           SOK1                    # no
5038        bra.w           SINSM                   # yes; input is very small
5039
5040SOK1:
5041        cmp.l           %d1,&0x4004BC7E         # is |X| < 15 PI?
5042        blt.b           SINMAIN                 # no
5043        bra.w           SREDUCEX                # yes; input is very large
5044
5045#--THIS IS THE USUAL CASE, |X| <= 15 PI.
5046#--THE ARGUMENT REDUCTION IS DONE BY TABLE LOOK UP.
5047SINMAIN:
5048        fmov.x          %fp0,%fp1
5049        fmul.d          TWOBYPI(%pc),%fp1       # X*2/PI
5050
5051        lea             PITBL+0x200(%pc),%a1    # TABLE OF N*PI/2, N = -32,...,32
5052
5053        fmov.l          %fp1,INT(%a6)           # CONVERT TO INTEGER
5054
5055        mov.l           INT(%a6),%d1            # make a copy of N
5056        asl.l           &4,%d1                  # N *= 16
5057        add.l           %d1,%a1                 # tbl_addr = a1 + (N*16)
5058
5059# A1 IS THE ADDRESS OF N*PIBY2
5060# ...WHICH IS IN TWO PIECES Y1 & Y2
5061        fsub.x          (%a1)+,%fp0             # X-Y1
5062        fsub.s          (%a1),%fp0              # fp0 = R = (X-Y1)-Y2
5063
5064SINCONT:
5065#--continuation from REDUCEX
5066
5067#--GET N+ADJN AND SEE IF SIN(R) OR COS(R) IS NEEDED
5068        mov.l           INT(%a6),%d1
5069        add.l           ADJN(%a6),%d1           # SEE IF D0 IS ODD OR EVEN
5070        ror.l           &1,%d1                  # D0 WAS ODD IFF D0 IS NEGATIVE
5071        cmp.l           %d1,&0
5072        blt.w           COSPOLY
5073
5074#--LET J BE THE LEAST SIG. BIT OF D0, LET SGN := (-1)**J.
5075#--THEN WE RETURN       SGN*SIN(R). SGN*SIN(R) IS COMPUTED BY
5076#--R' + R'*S*(A1 + S(A2 + S(A3 + S(A4 + ... + SA7)))), WHERE
5077#--R' = SGN*R, S=R*R. THIS CAN BE REWRITTEN AS
5078#--R' + R'*S*( [A1+T(A3+T(A5+TA7))] + [S(A2+T(A4+TA6))])
5079#--WHERE T=S*S.
5080#--NOTE THAT A3 THROUGH A7 ARE STORED IN DOUBLE PRECISION
5081#--WHILE A1 AND A2 ARE IN DOUBLE-EXTENDED FORMAT.
5082SINPOLY:
5083        fmovm.x         &0x0c,-(%sp)            # save fp2/fp3
5084
5085        fmov.x          %fp0,X(%a6)             # X IS R
5086        fmul.x          %fp0,%fp0               # FP0 IS S
5087
5088        fmov.d          SINA7(%pc),%fp3
5089        fmov.d          SINA6(%pc),%fp2
5090
5091        fmov.x          %fp0,%fp1
5092        fmul.x          %fp1,%fp1               # FP1 IS T
5093
5094        ror.l           &1,%d1
5095        and.l           &0x80000000,%d1
5096# ...LEAST SIG. BIT OF D0 IN SIGN POSITION
5097        eor.l           %d1,X(%a6)              # X IS NOW R'= SGN*R
5098
5099        fmul.x          %fp1,%fp3               # TA7
5100        fmul.x          %fp1,%fp2               # TA6
5101
5102        fadd.d          SINA5(%pc),%fp3         # A5+TA7
5103        fadd.d          SINA4(%pc),%fp2         # A4+TA6
5104
5105        fmul.x          %fp1,%fp3               # T(A5+TA7)
5106        fmul.x          %fp1,%fp2               # T(A4+TA6)
5107
5108        fadd.d          SINA3(%pc),%fp3         # A3+T(A5+TA7)
5109        fadd.x          SINA2(%pc),%fp2         # A2+T(A4+TA6)
5110
5111        fmul.x          %fp3,%fp1               # T(A3+T(A5+TA7))
5112
5113        fmul.x          %fp0,%fp2               # S(A2+T(A4+TA6))
5114        fadd.x          SINA1(%pc),%fp1         # A1+T(A3+T(A5+TA7))
5115        fmul.x          X(%a6),%fp0             # R'*S
5116
5117        fadd.x          %fp2,%fp1               # [A1+T(A3+T(A5+TA7))]+[S(A2+T(A4+TA6))]
5118
5119        fmul.x          %fp1,%fp0               # SIN(R')-R'
5120
5121        fmovm.x         (%sp)+,&0x30            # restore fp2/fp3
5122
5123        fmov.l          %d0,%fpcr               # restore users round mode,prec
5124        fadd.x          X(%a6),%fp0             # last inst - possible exception set
5125        bra             t_inx2
5126
5127#--LET J BE THE LEAST SIG. BIT OF D0, LET SGN := (-1)**J.
5128#--THEN WE RETURN       SGN*COS(R). SGN*COS(R) IS COMPUTED BY
5129#--SGN + S'*(B1 + S(B2 + S(B3 + S(B4 + ... + SB8)))), WHERE
5130#--S=R*R AND S'=SGN*S. THIS CAN BE REWRITTEN AS
5131#--SGN + S'*([B1+T(B3+T(B5+TB7))] + [S(B2+T(B4+T(B6+TB8)))])
5132#--WHERE T=S*S.
5133#--NOTE THAT B4 THROUGH B8 ARE STORED IN DOUBLE PRECISION
5134#--WHILE B2 AND B3 ARE IN DOUBLE-EXTENDED FORMAT, B1 IS -1/2
5135#--AND IS THEREFORE STORED AS SINGLE PRECISION.
5136COSPOLY:
5137        fmovm.x         &0x0c,-(%sp)            # save fp2/fp3
5138
5139        fmul.x          %fp0,%fp0               # FP0 IS S
5140
5141        fmov.d          COSB8(%pc),%fp2
5142        fmov.d          COSB7(%pc),%fp3
5143
5144        fmov.x          %fp0,%fp1
5145        fmul.x          %fp1,%fp1               # FP1 IS T
5146
5147        fmov.x          %fp0,X(%a6)             # X IS S
5148        ror.l           &1,%d1
5149        and.l           &0x80000000,%d1
5150# ...LEAST SIG. BIT OF D0 IN SIGN POSITION
5151
5152        fmul.x          %fp1,%fp2               # TB8
5153
5154        eor.l           %d1,X(%a6)              # X IS NOW S'= SGN*S
5155        and.l           &0x80000000,%d1
5156
5157        fmul.x          %fp1,%fp3               # TB7
5158
5159        or.l            &0x3F800000,%d1         # D0 IS SGN IN SINGLE
5160        mov.l           %d1,POSNEG1(%a6)
5161
5162        fadd.d          COSB6(%pc),%fp2         # B6+TB8
5163        fadd.d          COSB5(%pc),%fp3         # B5+TB7
5164
5165        fmul.x          %fp1,%fp2               # T(B6+TB8)
5166        fmul.x          %fp1,%fp3               # T(B5+TB7)
5167
5168        fadd.d          COSB4(%pc),%fp2         # B4+T(B6+TB8)
5169        fadd.x          COSB3(%pc),%fp3         # B3+T(B5+TB7)
5170
5171        fmul.x          %fp1,%fp2               # T(B4+T(B6+TB8))
5172        fmul.x          %fp3,%fp1               # T(B3+T(B5+TB7))
5173
5174        fadd.x          COSB2(%pc),%fp2         # B2+T(B4+T(B6+TB8))
5175        fadd.s          COSB1(%pc),%fp1         # B1+T(B3+T(B5+TB7))
5176
5177        fmul.x          %fp2,%fp0               # S(B2+T(B4+T(B6+TB8)))
5178
5179        fadd.x          %fp1,%fp0
5180
5181        fmul.x          X(%a6),%fp0
5182
5183        fmovm.x         (%sp)+,&0x30            # restore fp2/fp3
5184
5185        fmov.l          %d0,%fpcr               # restore users round mode,prec
5186        fadd.s          POSNEG1(%a6),%fp0       # last inst - possible exception set
5187        bra             t_inx2
5188
5189##############################################
5190
5191# SINe: Big OR Small?
5192#--IF |X| > 15PI, WE USE THE GENERAL ARGUMENT REDUCTION.
5193#--IF |X| < 2**(-40), RETURN X OR 1.
5194SINBORS:
5195        cmp.l           %d1,&0x3FFF8000
5196        bgt.l           SREDUCEX
5197
5198SINSM:
5199        mov.l           ADJN(%a6),%d1
5200        cmp.l           %d1,&0
5201        bgt.b           COSTINY
5202
5203# here, the operation may underflow iff the precision is sgl or dbl.
5204# extended denorms are handled through another entry point.
5205SINTINY:
5206#       mov.w           &0x0000,XDCARE(%a6)     # JUST IN CASE
5207
5208        fmov.l          %d0,%fpcr               # restore users round mode,prec
5209        mov.b           &FMOV_OP,%d1            # last inst is MOVE
5210        fmov.x          X(%a6),%fp0             # last inst - possible exception set
5211        bra             t_catch
5212
5213COSTINY:
5214        fmov.s          &0x3F800000,%fp0        # fp0 = 1.0
5215        fmov.l          %d0,%fpcr               # restore users round mode,prec
5216        fadd.s          &0x80800000,%fp0        # last inst - possible exception set
5217        bra             t_pinx2
5218
5219################################################
5220        global          ssind
5221#--SIN(X) = X FOR DENORMALIZED X
5222ssind:
5223        bra             t_extdnrm
5224
5225############################################
5226        global          scosd
5227#--COS(X) = 1 FOR DENORMALIZED X
5228scosd:
5229        fmov.s          &0x3F800000,%fp0        # fp0 = 1.0
5230        bra             t_pinx2
5231
5232##################################################
5233
5234        global          ssincos
5235ssincos:
5236#--SET ADJN TO 4
5237        mov.l           &4,ADJN(%a6)
5238
5239        fmov.x          (%a0),%fp0              # LOAD INPUT
5240        fmov.x          %fp0,X(%a6)
5241
5242        mov.l           (%a0),%d1
5243        mov.w           4(%a0),%d1
5244        and.l           &0x7FFFFFFF,%d1         # COMPACTIFY X
5245
5246        cmp.l           %d1,&0x3FD78000         # |X| >= 2**(-40)?
5247        bge.b           SCOK1
5248        bra.w           SCSM
5249
5250SCOK1:
5251        cmp.l           %d1,&0x4004BC7E         # |X| < 15 PI?
5252        blt.b           SCMAIN
5253        bra.w           SREDUCEX
5254
5255
5256#--THIS IS THE USUAL CASE, |X| <= 15 PI.
5257#--THE ARGUMENT REDUCTION IS DONE BY TABLE LOOK UP.
5258SCMAIN:
5259        fmov.x          %fp0,%fp1
5260
5261        fmul.d          TWOBYPI(%pc),%fp1       # X*2/PI
5262
5263        lea             PITBL+0x200(%pc),%a1    # TABLE OF N*PI/2, N = -32,...,32
5264
5265        fmov.l          %fp1,INT(%a6)           # CONVERT TO INTEGER
5266
5267        mov.l           INT(%a6),%d1
5268        asl.l           &4,%d1
5269        add.l           %d1,%a1                 # ADDRESS OF N*PIBY2, IN Y1, Y2
5270
5271        fsub.x          (%a1)+,%fp0             # X-Y1
5272        fsub.s          (%a1),%fp0              # FP0 IS R = (X-Y1)-Y2
5273
5274SCCONT:
5275#--continuation point from REDUCEX
5276
5277        mov.l           INT(%a6),%d1
5278        ror.l           &1,%d1
5279        cmp.l           %d1,&0                  # D0 < 0 IFF N IS ODD
5280        bge.w           NEVEN
5281
5282SNODD:
5283#--REGISTERS SAVED SO FAR: D0, A0, FP2.
5284        fmovm.x         &0x04,-(%sp)            # save fp2
5285
5286        fmov.x          %fp0,RPRIME(%a6)
5287        fmul.x          %fp0,%fp0               # FP0 IS S = R*R
5288        fmov.d          SINA7(%pc),%fp1         # A7
5289        fmov.d          COSB8(%pc),%fp2         # B8
5290        fmul.x          %fp0,%fp1               # SA7
5291        fmul.x          %fp0,%fp2               # SB8
5292
5293        mov.l           %d2,-(%sp)
5294        mov.l           %d1,%d2
5295        ror.l           &1,%d2
5296        and.l           &0x80000000,%d2
5297        eor.l           %d1,%d2
5298        and.l           &0x80000000,%d2
5299
5300        fadd.d          SINA6(%pc),%fp1         # A6+SA7
5301        fadd.d          COSB7(%pc),%fp2         # B7+SB8
5302
5303        fmul.x          %fp0,%fp1               # S(A6+SA7)
5304        eor.l           %d2,RPRIME(%a6)
5305        mov.l           (%sp)+,%d2
5306        fmul.x          %fp0,%fp2               # S(B7+SB8)
5307        ror.l           &1,%d1
5308        and.l           &0x80000000,%d1
5309        mov.l           &0x3F800000,POSNEG1(%a6)
5310        eor.l           %d1,POSNEG1(%a6)
5311
5312        fadd.d          SINA5(%pc),%fp1         # A5+S(A6+SA7)
5313        fadd.d          COSB6(%pc),%fp2         # B6+S(B7+SB8)
5314
5315        fmul.x          %fp0,%fp1               # S(A5+S(A6+SA7))
5316        fmul.x          %fp0,%fp2               # S(B6+S(B7+SB8))
5317        fmov.x          %fp0,SPRIME(%a6)
5318
5319        fadd.d          SINA4(%pc),%fp1         # A4+S(A5+S(A6+SA7))
5320        eor.l           %d1,SPRIME(%a6)
5321        fadd.d          COSB5(%pc),%fp2         # B5+S(B6+S(B7+SB8))
5322
5323        fmul.x          %fp0,%fp1               # S(A4+...)
5324        fmul.x          %fp0,%fp2               # S(B5+...)
5325
5326        fadd.d          SINA3(%pc),%fp1         # A3+S(A4+...)
5327        fadd.d          COSB4(%pc),%fp2         # B4+S(B5+...)
5328
5329        fmul.x          %fp0,%fp1               # S(A3+...)
5330        fmul.x          %fp0,%fp2               # S(B4+...)
5331
5332        fadd.x          SINA2(%pc),%fp1         # A2+S(A3+...)
5333        fadd.x          COSB3(%pc),%fp2         # B3+S(B4+...)
5334
5335        fmul.x          %fp0,%fp1               # S(A2+...)
5336        fmul.x          %fp0,%fp2               # S(B3+...)
5337
5338        fadd.x          SINA1(%pc),%fp1         # A1+S(A2+...)
5339        fadd.x          COSB2(%pc),%fp2         # B2+S(B3+...)
5340
5341        fmul.x          %fp0,%fp1               # S(A1+...)
5342        fmul.x          %fp2,%fp0               # S(B2+...)
5343
5344        fmul.x          RPRIME(%a6),%fp1        # R'S(A1+...)
5345        fadd.s          COSB1(%pc),%fp0         # B1+S(B2...)
5346        fmul.x          SPRIME(%a6),%fp0        # S'(B1+S(B2+...))
5347
5348        fmovm.x         (%sp)+,&0x20            # restore fp2
5349
5350        fmov.l          %d0,%fpcr
5351        fadd.x          RPRIME(%a6),%fp1        # COS(X)
5352        bsr             sto_cos                 # store cosine result
5353        fadd.s          POSNEG1(%a6),%fp0       # SIN(X)
5354        bra             t_inx2
5355
5356NEVEN:
5357#--REGISTERS SAVED SO FAR: FP2.
5358        fmovm.x         &0x04,-(%sp)            # save fp2
5359
5360        fmov.x          %fp0,RPRIME(%a6)
5361        fmul.x          %fp0,%fp0               # FP0 IS S = R*R
5362
5363        fmov.d          COSB8(%pc),%fp1         # B8
5364        fmov.d          SINA7(%pc),%fp2         # A7
5365
5366        fmul.x          %fp0,%fp1               # SB8
5367        fmov.x          %fp0,SPRIME(%a6)
5368        fmul.x          %fp0,%fp2               # SA7
5369
5370        ror.l           &1,%d1
5371        and.l           &0x80000000,%d1
5372
5373        fadd.d          COSB7(%pc),%fp1         # B7+SB8
5374        fadd.d          SINA6(%pc),%fp2         # A6+SA7
5375
5376        eor.l           %d1,RPRIME(%a6)
5377        eor.l           %d1,SPRIME(%a6)
5378
5379        fmul.x          %fp0,%fp1               # S(B7+SB8)
5380
5381        or.l            &0x3F800000,%d1
5382        mov.l           %d1,POSNEG1(%a6)
5383
5384        fmul.x          %fp0,%fp2               # S(A6+SA7)
5385
5386        fadd.d          COSB6(%pc),%fp1         # B6+S(B7+SB8)
5387        fadd.d          SINA5(%pc),%fp2         # A5+S(A6+SA7)
5388
5389        fmul.x          %fp0,%fp1               # S(B6+S(B7+SB8))
5390        fmul.x          %fp0,%fp2               # S(A5+S(A6+SA7))
5391
5392        fadd.d          COSB5(%pc),%fp1         # B5+S(B6+S(B7+SB8))
5393        fadd.d          SINA4(%pc),%fp2         # A4+S(A5+S(A6+SA7))
5394
5395        fmul.x          %fp0,%fp1               # S(B5+...)
5396        fmul.x          %fp0,%fp2               # S(A4+...)
5397
5398        fadd.d          COSB4(%pc),%fp1         # B4+S(B5+...)
5399        fadd.d          SINA3(%pc),%fp2         # A3+S(A4+...)
5400
5401        fmul.x          %fp0,%fp1               # S(B4+...)
5402        fmul.x          %fp0,%fp2               # S(A3+...)
5403
5404        fadd.x          COSB3(%pc),%fp1         # B3+S(B4+...)
5405        fadd.x          SINA2(%pc),%fp2         # A2+S(A3+...)
5406
5407        fmul.x          %fp0,%fp1               # S(B3+...)
5408        fmul.x          %fp0,%fp2               # S(A2+...)
5409
5410        fadd.x          COSB2(%pc),%fp1         # B2+S(B3+...)
5411        fadd.x          SINA1(%pc),%fp2         # A1+S(A2+...)
5412
5413        fmul.x          %fp0,%fp1               # S(B2+...)
5414        fmul.x          %fp2,%fp0               # s(a1+...)
5415
5416
5417        fadd.s          COSB1(%pc),%fp1         # B1+S(B2...)
5418        fmul.x          RPRIME(%a6),%fp0        # R'S(A1+...)
5419        fmul.x          SPRIME(%a6),%fp1        # S'(B1+S(B2+...))
5420
5421        fmovm.x         (%sp)+,&0x20            # restore fp2
5422
5423        fmov.l          %d0,%fpcr
5424        fadd.s          POSNEG1(%a6),%fp1       # COS(X)
5425        bsr             sto_cos                 # store cosine result
5426        fadd.x          RPRIME(%a6),%fp0        # SIN(X)
5427        bra             t_inx2
5428
5429################################################
5430
5431SCBORS:
5432        cmp.l           %d1,&0x3FFF8000
5433        bgt.w           SREDUCEX
5434
5435################################################
5436
5437SCSM:
5438#       mov.w           &0x0000,XDCARE(%a6)
5439        fmov.s          &0x3F800000,%fp1
5440
5441        fmov.l          %d0,%fpcr
5442        fsub.s          &0x00800000,%fp1
5443        bsr             sto_cos                 # store cosine result
5444        fmov.l          %fpcr,%d0               # d0 must have fpcr,too
5445        mov.b           &FMOV_OP,%d1            # last inst is MOVE
5446        fmov.x          X(%a6),%fp0
5447        bra             t_catch
5448
5449##############################################
5450
5451        global          ssincosd
5452#--SIN AND COS OF X FOR DENORMALIZED X
5453ssincosd:
5454        mov.l           %d0,-(%sp)              # save d0
5455        fmov.s          &0x3F800000,%fp1
5456        bsr             sto_cos                 # store cosine result
5457        mov.l           (%sp)+,%d0              # restore d0
5458        bra             t_extdnrm
5459
5460############################################
5461
5462#--WHEN REDUCEX IS USED, THE CODE WILL INEVITABLY BE SLOW.
5463#--THIS REDUCTION METHOD, HOWEVER, IS MUCH FASTER THAN USING
5464#--THE REMAINDER INSTRUCTION WHICH IS NOW IN SOFTWARE.
5465SREDUCEX:
5466        fmovm.x         &0x3c,-(%sp)            # save {fp2-fp5}
5467        mov.l           %d2,-(%sp)              # save d2
5468        fmov.s          &0x00000000,%fp1        # fp1 = 0
5469
5470#--If compact form of abs(arg) in d0=$7ffeffff, argument is so large that
5471#--there is a danger of unwanted overflow in first LOOP iteration.  In this
5472#--case, reduce argument by one remainder step to make subsequent reduction
5473#--safe.
5474        cmp.l           %d1,&0x7ffeffff         # is arg dangerously large?
5475        bne.b           SLOOP                   # no
5476
5477# yes; create 2**16383*PI/2
5478        mov.w           &0x7ffe,FP_SCR0_EX(%a6)
5479        mov.l           &0xc90fdaa2,FP_SCR0_HI(%a6)
5480        clr.l           FP_SCR0_LO(%a6)
5481
5482# create low half of 2**16383*PI/2 at FP_SCR1
5483        mov.w           &0x7fdc,FP_SCR1_EX(%a6)
5484        mov.l           &0x85a308d3,FP_SCR1_HI(%a6)
5485        clr.l           FP_SCR1_LO(%a6)
5486
5487        ftest.x         %fp0                    # test sign of argument
5488        fblt.w          sred_neg
5489
5490        or.b            &0x80,FP_SCR0_EX(%a6)   # positive arg
5491        or.b            &0x80,FP_SCR1_EX(%a6)
5492sred_neg:
5493        fadd.x          FP_SCR0(%a6),%fp0       # high part of reduction is exact
5494        fmov.x          %fp0,%fp1               # save high result in fp1
5495        fadd.x          FP_SCR1(%a6),%fp0       # low part of reduction
5496        fsub.x          %fp0,%fp1               # determine low component of result
5497        fadd.x          FP_SCR1(%a6),%fp1       # fp0/fp1 are reduced argument.
5498
5499#--ON ENTRY, FP0 IS X, ON RETURN, FP0 IS X REM PI/2, |X| <= PI/4.
5500#--integer quotient will be stored in N
5501#--Intermeditate remainder is 66-bit long; (R,r) in (FP0,FP1)
5502SLOOP:
5503        fmov.x          %fp0,INARG(%a6)         # +-2**K * F, 1 <= F < 2
5504        mov.w           INARG(%a6),%d1
5505        mov.l           %d1,%a1                 # save a copy of D0
5506        and.l           &0x00007FFF,%d1
5507        sub.l           &0x00003FFF,%d1         # d0 = K
5508        cmp.l           %d1,&28
5509        ble.b           SLASTLOOP
5510SCONTLOOP:
5511        sub.l           &27,%d1                 # d0 = L := K-27
5512        mov.b           &0,ENDFLAG(%a6)
5513        bra.b           SWORK
5514SLASTLOOP:
5515        clr.l           %d1                     # d0 = L := 0
5516        mov.b           &1,ENDFLAG(%a6)
5517
5518SWORK:
5519#--FIND THE REMAINDER OF (R,r) W.R.T.   2**L * (PI/2). L IS SO CHOSEN
5520#--THAT INT( X * (2/PI) / 2**(L) ) < 2**29.
5521
5522#--CREATE 2**(-L) * (2/PI), SIGN(INARG)*2**(63),
5523#--2**L * (PIby2_1), 2**L * (PIby2_2)
5524
5525        mov.l           &0x00003FFE,%d2         # BIASED EXP OF 2/PI
5526        sub.l           %d1,%d2                 # BIASED EXP OF 2**(-L)*(2/PI)
5527
5528        mov.l           &0xA2F9836E,FP_SCR0_HI(%a6)
5529        mov.l           &0x4E44152A,FP_SCR0_LO(%a6)
5530        mov.w           %d2,FP_SCR0_EX(%a6)     # FP_SCR0 = 2**(-L)*(2/PI)
5531
5532        fmov.x          %fp0,%fp2
5533        fmul.x          FP_SCR0(%a6),%fp2       # fp2 = X * 2**(-L)*(2/PI)
5534
5535#--WE MUST NOW FIND INT(FP2). SINCE WE NEED THIS VALUE IN
5536#--FLOATING POINT FORMAT, THE TWO FMOVE'S       FMOVE.L FP <--> N
5537#--WILL BE TOO INEFFICIENT. THE WAY AROUND IT IS THAT
5538#--(SIGN(INARG)*2**63   +       FP2) - SIGN(INARG)*2**63 WILL GIVE
5539#--US THE DESIRED VALUE IN FLOATING POINT.
5540        mov.l           %a1,%d2
5541        swap            %d2
5542        and.l           &0x80000000,%d2
5543        or.l            &0x5F000000,%d2         # d2 = SIGN(INARG)*2**63 IN SGL
5544        mov.l           %d2,TWOTO63(%a6)
5545        fadd.s          TWOTO63(%a6),%fp2       # THE FRACTIONAL PART OF FP1 IS ROUNDED
5546        fsub.s          TWOTO63(%a6),%fp2       # fp2 = N
5547#       fint.x          %fp2
5548
5549#--CREATING 2**(L)*Piby2_1 and 2**(L)*Piby2_2
5550        mov.l           %d1,%d2                 # d2 = L
5551
5552        add.l           &0x00003FFF,%d2         # BIASED EXP OF 2**L * (PI/2)
5553        mov.w           %d2,FP_SCR0_EX(%a6)
5554        mov.l           &0xC90FDAA2,FP_SCR0_HI(%a6)
5555        clr.l           FP_SCR0_LO(%a6)         # FP_SCR0 = 2**(L) * Piby2_1
5556
5557        add.l           &0x00003FDD,%d1
5558        mov.w           %d1,FP_SCR1_EX(%a6)
5559        mov.l           &0x85A308D3,FP_SCR1_HI(%a6)
5560        clr.l           FP_SCR1_LO(%a6)         # FP_SCR1 = 2**(L) * Piby2_2
5561
5562        mov.b           ENDFLAG(%a6),%d1
5563
5564#--We are now ready to perform (R+r) - N*P1 - N*P2, P1 = 2**(L) * Piby2_1 and
5565#--P2 = 2**(L) * Piby2_2
5566        fmov.x          %fp2,%fp4               # fp4 = N
5567        fmul.x          FP_SCR0(%a6),%fp4       # fp4 = W = N*P1
5568        fmov.x          %fp2,%fp5               # fp5 = N
5569        fmul.x          FP_SCR1(%a6),%fp5       # fp5 = w = N*P2
5570        fmov.x          %fp4,%fp3               # fp3 = W = N*P1
5571
5572#--we want P+p = W+w  but  |p| <= half ulp of P
5573#--Then, we need to compute  A := R-P   and  a := r-p
5574        fadd.x          %fp5,%fp3               # fp3 = P
5575        fsub.x          %fp3,%fp4               # fp4 = W-P
5576
5577        fsub.x          %fp3,%fp0               # fp0 = A := R - P
5578        fadd.x          %fp5,%fp4               # fp4 = p = (W-P)+w
5579
5580        fmov.x          %fp0,%fp3               # fp3 = A
5581        fsub.x          %fp4,%fp1               # fp1 = a := r - p
5582
5583#--Now we need to normalize (A,a) to  "new (R,r)" where R+r = A+a but
5584#--|r| <= half ulp of R.
5585        fadd.x          %fp1,%fp0               # fp0 = R := A+a
5586#--No need to calculate r if this is the last loop
5587        cmp.b           %d1,&0
5588        bgt.w           SRESTORE
5589
5590#--Need to calculate r
5591        fsub.x          %fp0,%fp3               # fp3 = A-R
5592        fadd.x          %fp3,%fp1               # fp1 = r := (A-R)+a
5593        bra.w           SLOOP
5594
5595SRESTORE:
5596        fmov.l          %fp2,INT(%a6)
5597        mov.l           (%sp)+,%d2              # restore d2
5598        fmovm.x         (%sp)+,&0x3c            # restore {fp2-fp5}
5599
5600        mov.l           ADJN(%a6),%d1
5601        cmp.l           %d1,&4
5602
5603        blt.w           SINCONT
5604        bra.w           SCCONT
5605
5606#########################################################################
5607# stan():  computes the tangent of a normalized input                   #
5608# stand(): computes the tangent of a denormalized input                 #
5609#                                                                       #
5610# INPUT *************************************************************** #
5611#       a0 = pointer to extended precision input                        #
5612#       d0 = round precision,mode                                       #
5613#                                                                       #
5614# OUTPUT ************************************************************** #
5615#       fp0 = tan(X)                                                    #
5616#                                                                       #
5617# ACCURACY and MONOTONICITY ******************************************* #
5618#       The returned result is within 3 ulp in 64 significant bit, i.e. #
5619#       within 0.5001 ulp to 53 bits if the result is subsequently      #
5620#       rounded to double precision. The result is provably monotonic   #
5621#       in double precision.                                            #
5622#                                                                       #
5623# ALGORITHM *********************************************************** #
5624#                                                                       #
5625#       1. If |X| >= 15Pi or |X| < 2**(-40), go to 6.                   #
5626#                                                                       #
5627#       2. Decompose X as X = N(Pi/2) + r where |r| <= Pi/4. Let        #
5628#               k = N mod 2, so in particular, k = 0 or 1.              #
5629#                                                                       #
5630#       3. If k is odd, go to 5.                                        #
5631#                                                                       #
5632#       4. (k is even) Tan(X) = tan(r) and tan(r) is approximated by a  #
5633#               rational function U/V where                             #
5634#               U = r + r*s*(P1 + s*(P2 + s*P3)), and                   #
5635#               V = 1 + s*(Q1 + s*(Q2 + s*(Q3 + s*Q4))),  s = r*r.      #
5636#               Exit.                                                   #
5637#                                                                       #
5638#       4. (k is odd) Tan(X) = -cot(r). Since tan(r) is approximated by #
5639#               a rational function U/V where                           #
5640#               U = r + r*s*(P1 + s*(P2 + s*P3)), and                   #
5641#               V = 1 + s*(Q1 + s*(Q2 + s*(Q3 + s*Q4))), s = r*r,       #
5642#               -Cot(r) = -V/U. Exit.                                   #
5643#                                                                       #
5644#       6. If |X| > 1, go to 8.                                         #
5645#                                                                       #
5646#       7. (|X|<2**(-40)) Tan(X) = X. Exit.                             #
5647#                                                                       #
5648#       8. Overwrite X by X := X rem 2Pi. Now that |X| <= Pi, go back   #
5649#               to 2.                                                   #
5650#                                                                       #
5651#########################################################################
5652
5653TANQ4:
5654        long            0x3EA0B759,0xF50F8688
5655TANP3:
5656        long            0xBEF2BAA5,0xA8924F04
5657
5658TANQ3:
5659        long            0xBF346F59,0xB39BA65F,0x00000000,0x00000000
5660
5661TANP2:
5662        long            0x3FF60000,0xE073D3FC,0x199C4A00,0x00000000
5663
5664TANQ2:
5665        long            0x3FF90000,0xD23CD684,0x15D95FA1,0x00000000
5666
5667TANP1:
5668        long            0xBFFC0000,0x8895A6C5,0xFB423BCA,0x00000000
5669
5670TANQ1:
5671        long            0xBFFD0000,0xEEF57E0D,0xA84BC8CE,0x00000000
5672
5673INVTWOPI:
5674        long            0x3FFC0000,0xA2F9836E,0x4E44152A,0x00000000
5675
5676TWOPI1:
5677        long            0x40010000,0xC90FDAA2,0x00000000,0x00000000
5678TWOPI2:
5679        long            0x3FDF0000,0x85A308D4,0x00000000,0x00000000
5680
5681#--N*PI/2, -32 <= N <= 32, IN A LEADING TERM IN EXT. AND TRAILING
5682#--TERM IN SGL. NOTE THAT PI IS 64-BIT LONG, THUS N*PI/2 IS AT
5683#--MOST 69 BITS LONG.
5684#       global          PITBL
5685PITBL:
5686        long            0xC0040000,0xC90FDAA2,0x2168C235,0x21800000
5687        long            0xC0040000,0xC2C75BCD,0x105D7C23,0xA0D00000
5688        long            0xC0040000,0xBC7EDCF7,0xFF523611,0xA1E80000
5689        long            0xC0040000,0xB6365E22,0xEE46F000,0x21480000
5690        long            0xC0040000,0xAFEDDF4D,0xDD3BA9EE,0xA1200000
5691        long            0xC0040000,0xA9A56078,0xCC3063DD,0x21FC0000
5692        long            0xC0040000,0xA35CE1A3,0xBB251DCB,0x21100000
5693        long            0xC0040000,0x9D1462CE,0xAA19D7B9,0xA1580000
5694        long            0xC0040000,0x96CBE3F9,0x990E91A8,0x21E00000
5695        long            0xC0040000,0x90836524,0x88034B96,0x20B00000
5696        long            0xC0040000,0x8A3AE64F,0x76F80584,0xA1880000
5697        long            0xC0040000,0x83F2677A,0x65ECBF73,0x21C40000
5698        long            0xC0030000,0xFB53D14A,0xA9C2F2C2,0x20000000
5699        long            0xC0030000,0xEEC2D3A0,0x87AC669F,0x21380000
5700        long            0xC0030000,0xE231D5F6,0x6595DA7B,0xA1300000
5701        long            0xC0030000,0xD5A0D84C,0x437F4E58,0x9FC00000
5702        long            0xC0030000,0xC90FDAA2,0x2168C235,0x21000000
5703        long            0xC0030000,0xBC7EDCF7,0xFF523611,0xA1680000
5704        long            0xC0030000,0xAFEDDF4D,0xDD3BA9EE,0xA0A00000
5705        long            0xC0030000,0xA35CE1A3,0xBB251DCB,0x20900000
5706        long            0xC0030000,0x96CBE3F9,0x990E91A8,0x21600000
5707        long            0xC0030000,0x8A3AE64F,0x76F80584,0xA1080000
5708        long            0xC0020000,0xFB53D14A,0xA9C2F2C2,0x1F800000
5709        long            0xC0020000,0xE231D5F6,0x6595DA7B,0xA0B00000
5710        long            0xC0020000,0xC90FDAA2,0x2168C235,0x20800000
5711        long            0xC0020000,0xAFEDDF4D,0xDD3BA9EE,0xA0200000
5712        long            0xC0020000,0x96CBE3F9,0x990E91A8,0x20E00000
5713        long            0xC0010000,0xFB53D14A,0xA9C2F2C2,0x1F000000
5714        long            0xC0010000,0xC90FDAA2,0x2168C235,0x20000000
5715        long            0xC0010000,0x96CBE3F9,0x990E91A8,0x20600000
5716        long            0xC0000000,0xC90FDAA2,0x2168C235,0x1F800000
5717        long            0xBFFF0000,0xC90FDAA2,0x2168C235,0x1F000000
5718        long            0x00000000,0x00000000,0x00000000,0x00000000
5719        long            0x3FFF0000,0xC90FDAA2,0x2168C235,0x9F000000
5720        long            0x40000000,0xC90FDAA2,0x2168C235,0x9F800000
5721        long            0x40010000,0x96CBE3F9,0x990E91A8,0xA0600000
5722        long            0x40010000,0xC90FDAA2,0x2168C235,0xA0000000
5723        long            0x40010000,0xFB53D14A,0xA9C2F2C2,0x9F000000
5724        long            0x40020000,0x96CBE3F9,0x990E91A8,0xA0E00000
5725        long            0x40020000,0xAFEDDF4D,0xDD3BA9EE,0x20200000
5726        long            0x40020000,0xC90FDAA2,0x2168C235,0xA0800000
5727        long            0x40020000,0xE231D5F6,0x6595DA7B,0x20B00000
5728        long            0x40020000,0xFB53D14A,0xA9C2F2C2,0x9F800000
5729        long            0x40030000,0x8A3AE64F,0x76F80584,0x21080000
5730        long            0x40030000,0x96CBE3F9,0x990E91A8,0xA1600000
5731        long            0x40030000,0xA35CE1A3,0xBB251DCB,0xA0900000
5732        long            0x40030000,0xAFEDDF4D,0xDD3BA9EE,0x20A00000
5733        long            0x40030000,0xBC7EDCF7,0xFF523611,0x21680000
5734        long            0x40030000,0xC90FDAA2,0x2168C235,0xA1000000
5735        long            0x40030000,0xD5A0D84C,0x437F4E58,0x1FC00000
5736        long            0x40030000,0xE231D5F6,0x6595DA7B,0x21300000
5737        long            0x40030000,0xEEC2D3A0,0x87AC669F,0xA1380000
5738        long            0x40030000,0xFB53D14A,0xA9C2F2C2,0xA0000000
5739        long            0x40040000,0x83F2677A,0x65ECBF73,0xA1C40000
5740        long            0x40040000,0x8A3AE64F,0x76F80584,0x21880000
5741        long            0x40040000,0x90836524,0x88034B96,0xA0B00000
5742        long            0x40040000,0x96CBE3F9,0x990E91A8,0xA1E00000
5743        long            0x40040000,0x9D1462CE,0xAA19D7B9,0x21580000
5744        long            0x40040000,0xA35CE1A3,0xBB251DCB,0xA1100000
5745        long            0x40040000,0xA9A56078,0xCC3063DD,0xA1FC0000
5746        long            0x40040000,0xAFEDDF4D,0xDD3BA9EE,0x21200000
5747        long            0x40040000,0xB6365E22,0xEE46F000,0xA1480000
5748        long            0x40040000,0xBC7EDCF7,0xFF523611,0x21E80000
5749        long            0x40040000,0xC2C75BCD,0x105D7C23,0x20D00000
5750        long            0x40040000,0xC90FDAA2,0x2168C235,0xA1800000
5751
5752        set             INARG,FP_SCR0
5753
5754        set             TWOTO63,L_SCR1
5755        set             INT,L_SCR1
5756        set             ENDFLAG,L_SCR2
5757
5758        global          stan
5759stan:
5760        fmov.x          (%a0),%fp0              # LOAD INPUT
5761
5762        mov.l           (%a0),%d1
5763        mov.w           4(%a0),%d1
5764        and.l           &0x7FFFFFFF,%d1
5765
5766        cmp.l           %d1,&0x3FD78000         # |X| >= 2**(-40)?
5767        bge.b           TANOK1
5768        bra.w           TANSM
5769TANOK1:
5770        cmp.l           %d1,&0x4004BC7E         # |X| < 15 PI?
5771        blt.b           TANMAIN
5772        bra.w           REDUCEX
5773
5774TANMAIN:
5775#--THIS IS THE USUAL CASE, |X| <= 15 PI.
5776#--THE ARGUMENT REDUCTION IS DONE BY TABLE LOOK UP.
5777        fmov.x          %fp0,%fp1
5778        fmul.d          TWOBYPI(%pc),%fp1       # X*2/PI
5779
5780        lea.l           PITBL+0x200(%pc),%a1    # TABLE OF N*PI/2, N = -32,...,32
5781
5782        fmov.l          %fp1,%d1                # CONVERT TO INTEGER
5783
5784        asl.l           &4,%d1
5785        add.l           %d1,%a1                 # ADDRESS N*PIBY2 IN Y1, Y2
5786
5787        fsub.x          (%a1)+,%fp0             # X-Y1
5788
5789        fsub.s          (%a1),%fp0              # FP0 IS R = (X-Y1)-Y2
5790
5791        ror.l           &5,%d1
5792        and.l           &0x80000000,%d1         # D0 WAS ODD IFF D0 < 0
5793
5794TANCONT:
5795        fmovm.x         &0x0c,-(%sp)            # save fp2,fp3
5796
5797        cmp.l           %d1,&0
5798        blt.w           NODD
5799
5800        fmov.x          %fp0,%fp1
5801        fmul.x          %fp1,%fp1               # S = R*R
5802
5803        fmov.d          TANQ4(%pc),%fp3
5804        fmov.d          TANP3(%pc),%fp2
5805
5806        fmul.x          %fp1,%fp3               # SQ4
5807        fmul.x          %fp1,%fp2               # SP3
5808
5809        fadd.d          TANQ3(%pc),%fp3         # Q3+SQ4
5810        fadd.x          TANP2(%pc),%fp2         # P2+SP3
5811
5812        fmul.x          %fp1,%fp3               # S(Q3+SQ4)
5813        fmul.x          %fp1,%fp2               # S(P2+SP3)
5814
5815        fadd.x          TANQ2(%pc),%fp3         # Q2+S(Q3+SQ4)
5816        fadd.x          TANP1(%pc),%fp2         # P1+S(P2+SP3)
5817
5818        fmul.x          %fp1,%fp3               # S(Q2+S(Q3+SQ4))
5819        fmul.x          %fp1,%fp2               # S(P1+S(P2+SP3))
5820
5821        fadd.x          TANQ1(%pc),%fp3         # Q1+S(Q2+S(Q3+SQ4))
5822        fmul.x          %fp0,%fp2               # RS(P1+S(P2+SP3))
5823
5824        fmul.x          %fp3,%fp1               # S(Q1+S(Q2+S(Q3+SQ4)))
5825
5826        fadd.x          %fp2,%fp0               # R+RS(P1+S(P2+SP3))
5827
5828        fadd.s          &0x3F800000,%fp1        # 1+S(Q1+...)
5829
5830        fmovm.x         (%sp)+,&0x30            # restore fp2,fp3
5831
5832        fmov.l          %d0,%fpcr               # restore users round mode,prec
5833        fdiv.x          %fp1,%fp0               # last inst - possible exception set
5834        bra             t_inx2
5835
5836NODD:
5837        fmov.x          %fp0,%fp1
5838        fmul.x          %fp0,%fp0               # S = R*R
5839
5840        fmov.d          TANQ4(%pc),%fp3
5841        fmov.d          TANP3(%pc),%fp2
5842
5843        fmul.x          %fp0,%fp3               # SQ4
5844        fmul.x          %fp0,%fp2               # SP3
5845
5846        fadd.d          TANQ3(%pc),%fp3         # Q3+SQ4
5847        fadd.x          TANP2(%pc),%fp2         # P2+SP3
5848
5849        fmul.x          %fp0,%fp3               # S(Q3+SQ4)
5850        fmul.x          %fp0,%fp2               # S(P2+SP3)
5851
5852        fadd.x          TANQ2(%pc),%fp3         # Q2+S(Q3+SQ4)
5853        fadd.x          TANP1(%pc),%fp2         # P1+S(P2+SP3)
5854
5855        fmul.x          %fp0,%fp3               # S(Q2+S(Q3+SQ4))
5856        fmul.x          %fp0,%fp2               # S(P1+S(P2+SP3))
5857
5858        fadd.x          TANQ1(%pc),%fp3         # Q1+S(Q2+S(Q3+SQ4))
5859        fmul.x          %fp1,%fp2               # RS(P1+S(P2+SP3))
5860
5861        fmul.x          %fp3,%fp0               # S(Q1+S(Q2+S(Q3+SQ4)))
5862
5863        fadd.x          %fp2,%fp1               # R+RS(P1+S(P2+SP3))
5864        fadd.s          &0x3F800000,%fp0        # 1+S(Q1+...)
5865
5866        fmovm.x         (%sp)+,&0x30            # restore fp2,fp3
5867
5868        fmov.x          %fp1,-(%sp)
5869        eor.l           &0x80000000,(%sp)
5870
5871        fmov.l          %d0,%fpcr               # restore users round mode,prec
5872        fdiv.x          (%sp)+,%fp0             # last inst - possible exception set
5873        bra             t_inx2
5874
5875TANBORS:
5876#--IF |X| > 15PI, WE USE THE GENERAL ARGUMENT REDUCTION.
5877#--IF |X| < 2**(-40), RETURN X OR 1.
5878        cmp.l           %d1,&0x3FFF8000
5879        bgt.b           REDUCEX
5880
5881TANSM:
5882        fmov.x          %fp0,-(%sp)
5883        fmov.l          %d0,%fpcr               # restore users round mode,prec
5884        mov.b           &FMOV_OP,%d1            # last inst is MOVE
5885        fmov.x          (%sp)+,%fp0             # last inst - posibble exception set
5886        bra             t_catch
5887
5888        global          stand
5889#--TAN(X) = X FOR DENORMALIZED X
5890stand:
5891        bra             t_extdnrm
5892
5893#--WHEN REDUCEX IS USED, THE CODE WILL INEVITABLY BE SLOW.
5894#--THIS REDUCTION METHOD, HOWEVER, IS MUCH FASTER THAN USING
5895#--THE REMAINDER INSTRUCTION WHICH IS NOW IN SOFTWARE.
5896REDUCEX:
5897        fmovm.x         &0x3c,-(%sp)            # save {fp2-fp5}
5898        mov.l           %d2,-(%sp)              # save d2
5899        fmov.s          &0x00000000,%fp1        # fp1 = 0
5900
5901#--If compact form of abs(arg) in d0=$7ffeffff, argument is so large that
5902#--there is a danger of unwanted overflow in first LOOP iteration.  In this
5903#--case, reduce argument by one remainder step to make subsequent reduction
5904#--safe.
5905        cmp.l           %d1,&0x7ffeffff         # is arg dangerously large?
5906        bne.b           LOOP                    # no
5907
5908# yes; create 2**16383*PI/2
5909        mov.w           &0x7ffe,FP_SCR0_EX(%a6)
5910        mov.l           &0xc90fdaa2,FP_SCR0_HI(%a6)
5911        clr.l           FP_SCR0_LO(%a6)
5912
5913# create low half of 2**16383*PI/2 at FP_SCR1
5914        mov.w           &0x7fdc,FP_SCR1_EX(%a6)
5915        mov.l           &0x85a308d3,FP_SCR1_HI(%a6)
5916        clr.l           FP_SCR1_LO(%a6)
5917
5918        ftest.x         %fp0                    # test sign of argument
5919        fblt.w          red_neg
5920
5921        or.b            &0x80,FP_SCR0_EX(%a6)   # positive arg
5922        or.b            &0x80,FP_SCR1_EX(%a6)
5923red_neg:
5924        fadd.x          FP_SCR0(%a6),%fp0       # high part of reduction is exact
5925        fmov.x          %fp0,%fp1               # save high result in fp1
5926        fadd.x          FP_SCR1(%a6),%fp0       # low part of reduction
5927        fsub.x          %fp0,%fp1               # determine low component of result
5928        fadd.x          FP_SCR1(%a6),%fp1       # fp0/fp1 are reduced argument.
5929
5930#--ON ENTRY, FP0 IS X, ON RETURN, FP0 IS X REM PI/2, |X| <= PI/4.
5931#--integer quotient will be stored in N
5932#--Intermeditate remainder is 66-bit long; (R,r) in (FP0,FP1)
5933LOOP:
5934        fmov.x          %fp0,INARG(%a6)         # +-2**K * F, 1 <= F < 2
5935        mov.w           INARG(%a6),%d1
5936        mov.l           %d1,%a1                 # save a copy of D0
5937        and.l           &0x00007FFF,%d1
5938        sub.l           &0x00003FFF,%d1         # d0 = K
5939        cmp.l           %d1,&28
5940        ble.b           LASTLOOP
5941CONTLOOP:
5942        sub.l           &27,%d1                 # d0 = L := K-27
5943        mov.b           &0,ENDFLAG(%a6)
5944        bra.b           WORK
5945LASTLOOP:
5946        clr.l           %d1                     # d0 = L := 0
5947        mov.b           &1,ENDFLAG(%a6)
5948
5949WORK:
5950#--FIND THE REMAINDER OF (R,r) W.R.T.   2**L * (PI/2). L IS SO CHOSEN
5951#--THAT INT( X * (2/PI) / 2**(L) ) < 2**29.
5952
5953#--CREATE 2**(-L) * (2/PI), SIGN(INARG)*2**(63),
5954#--2**L * (PIby2_1), 2**L * (PIby2_2)
5955
5956        mov.l           &0x00003FFE,%d2         # BIASED EXP OF 2/PI
5957        sub.l           %d1,%d2                 # BIASED EXP OF 2**(-L)*(2/PI)
5958
5959        mov.l           &0xA2F9836E,FP_SCR0_HI(%a6)
5960        mov.l           &0x4E44152A,FP_SCR0_LO(%a6)
5961        mov.w           %d2,FP_SCR0_EX(%a6)     # FP_SCR0 = 2**(-L)*(2/PI)
5962
5963        fmov.x          %fp0,%fp2
5964        fmul.x          FP_SCR0(%a6),%fp2       # fp2 = X * 2**(-L)*(2/PI)
5965
5966#--WE MUST NOW FIND INT(FP2). SINCE WE NEED THIS VALUE IN
5967#--FLOATING POINT FORMAT, THE TWO FMOVE'S       FMOVE.L FP <--> N
5968#--WILL BE TOO INEFFICIENT. THE WAY AROUND IT IS THAT
5969#--(SIGN(INARG)*2**63   +       FP2) - SIGN(INARG)*2**63 WILL GIVE
5970#--US THE DESIRED VALUE IN FLOATING POINT.
5971        mov.l           %a1,%d2
5972        swap            %d2
5973        and.l           &0x80000000,%d2
5974        or.l            &0x5F000000,%d2         # d2 = SIGN(INARG)*2**63 IN SGL
5975        mov.l           %d2,TWOTO63(%a6)
5976        fadd.s          TWOTO63(%a6),%fp2       # THE FRACTIONAL PART OF FP1 IS ROUNDED
5977        fsub.s          TWOTO63(%a6),%fp2       # fp2 = N
5978#       fintrz.x        %fp2,%fp2
5979
5980#--CREATING 2**(L)*Piby2_1 and 2**(L)*Piby2_2
5981        mov.l           %d1,%d2                 # d2 = L
5982
5983        add.l           &0x00003FFF,%d2         # BIASED EXP OF 2**L * (PI/2)
5984        mov.w           %d2,FP_SCR0_EX(%a6)
5985        mov.l           &0xC90FDAA2,FP_SCR0_HI(%a6)
5986        clr.l           FP_SCR0_LO(%a6)         # FP_SCR0 = 2**(L) * Piby2_1
5987
5988        add.l           &0x00003FDD,%d1
5989        mov.w           %d1,FP_SCR1_EX(%a6)
5990        mov.l           &0x85A308D3,FP_SCR1_HI(%a6)
5991        clr.l           FP_SCR1_LO(%a6)         # FP_SCR1 = 2**(L) * Piby2_2
5992
5993        mov.b           ENDFLAG(%a6),%d1
5994
5995#--We are now ready to perform (R+r) - N*P1 - N*P2, P1 = 2**(L) * Piby2_1 and
5996#--P2 = 2**(L) * Piby2_2
5997        fmov.x          %fp2,%fp4               # fp4 = N
5998        fmul.x          FP_SCR0(%a6),%fp4       # fp4 = W = N*P1
5999        fmov.x          %fp2,%fp5               # fp5 = N
6000        fmul.x          FP_SCR1(%a6),%fp5       # fp5 = w = N*P2
6001        fmov.x          %fp4,%fp3               # fp3 = W = N*P1
6002
6003#--we want P+p = W+w  but  |p| <= half ulp of P
6004#--Then, we need to compute  A := R-P   and  a := r-p
6005        fadd.x          %fp5,%fp3               # fp3 = P
6006        fsub.x          %fp3,%fp4               # fp4 = W-P
6007
6008        fsub.x          %fp3,%fp0               # fp0 = A := R - P
6009        fadd.x          %fp5,%fp4               # fp4 = p = (W-P)+w
6010
6011        fmov.x          %fp0,%fp3               # fp3 = A
6012        fsub.x          %fp4,%fp1               # fp1 = a := r - p
6013
6014#--Now we need to normalize (A,a) to  "new (R,r)" where R+r = A+a but
6015#--|r| <= half ulp of R.
6016        fadd.x          %fp1,%fp0               # fp0 = R := A+a
6017#--No need to calculate r if this is the last loop
6018        cmp.b           %d1,&0
6019        bgt.w           RESTORE
6020
6021#--Need to calculate r
6022        fsub.x          %fp0,%fp3               # fp3 = A-R
6023        fadd.x          %fp3,%fp1               # fp1 = r := (A-R)+a
6024        bra.w           LOOP
6025
6026RESTORE:
6027        fmov.l          %fp2,INT(%a6)
6028        mov.l           (%sp)+,%d2              # restore d2
6029        fmovm.x         (%sp)+,&0x3c            # restore {fp2-fp5}
6030
6031        mov.l           INT(%a6),%d1
6032        ror.l           &1,%d1
6033
6034        bra.w           TANCONT
6035
6036#########################################################################
6037# satan():  computes the arctangent of a normalized number              #
6038# satand(): computes the arctangent of a denormalized number            #
6039#                                                                       #
6040# INPUT *************************************************************** #
6041#       a0 = pointer to extended precision input                        #
6042#       d0 = round precision,mode                                       #
6043#                                                                       #
6044# OUTPUT ************************************************************** #
6045#       fp0 = arctan(X)                                                 #
6046#                                                                       #
6047# ACCURACY and MONOTONICITY ******************************************* #
6048#       The returned result is within 2 ulps in 64 significant bit,     #
6049#       i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
6050#       rounded to double precision. The result is provably monotonic   #
6051#       in double precision.                                            #
6052#                                                                       #
6053# ALGORITHM *********************************************************** #
6054#       Step 1. If |X| >= 16 or |X| < 1/16, go to Step 5.               #
6055#                                                                       #
6056#       Step 2. Let X = sgn * 2**k * 1.xxxxxxxx...x.                    #
6057#               Note that k = -4, -3,..., or 3.                         #
6058#               Define F = sgn * 2**k * 1.xxxx1, i.e. the first 5       #
6059#               significant bits of X with a bit-1 attached at the 6-th #
6060#               bit position. Define u to be u = (X-F) / (1 + X*F).     #
6061#                                                                       #
6062#       Step 3. Approximate arctan(u) by a polynomial poly.             #
6063#                                                                       #
6064#       Step 4. Return arctan(F) + poly, arctan(F) is fetched from a    #
6065#               table of values calculated beforehand. Exit.            #
6066#                                                                       #
6067#       Step 5. If |X| >= 16, go to Step 7.                             #
6068#                                                                       #
6069#       Step 6. Approximate arctan(X) by an odd polynomial in X. Exit.  #
6070#                                                                       #
6071#       Step 7. Define X' = -1/X. Approximate arctan(X') by an odd      #
6072#               polynomial in X'.                                       #
6073#               Arctan(X) = sign(X)*Pi/2 + arctan(X'). Exit.            #
6074#                                                                       #
6075#########################################################################
6076
6077ATANA3: long            0xBFF6687E,0x314987D8
6078ATANA2: long            0x4002AC69,0x34A26DB3
6079ATANA1: long            0xBFC2476F,0x4E1DA28E
6080
6081ATANB6: long            0x3FB34444,0x7F876989
6082ATANB5: long            0xBFB744EE,0x7FAF45DB
6083ATANB4: long            0x3FBC71C6,0x46940220
6084ATANB3: long            0xBFC24924,0x921872F9
6085ATANB2: long            0x3FC99999,0x99998FA9
6086ATANB1: long            0xBFD55555,0x55555555
6087
6088ATANC5: long            0xBFB70BF3,0x98539E6A
6089ATANC4: long            0x3FBC7187,0x962D1D7D
6090ATANC3: long            0xBFC24924,0x827107B8
6091ATANC2: long            0x3FC99999,0x9996263E
6092ATANC1: long            0xBFD55555,0x55555536
6093
6094PPIBY2: long            0x3FFF0000,0xC90FDAA2,0x2168C235,0x00000000
6095NPIBY2: long            0xBFFF0000,0xC90FDAA2,0x2168C235,0x00000000
6096
6097PTINY:  long            0x00010000,0x80000000,0x00000000,0x00000000
6098NTINY:  long            0x80010000,0x80000000,0x00000000,0x00000000
6099
6100ATANTBL:
6101        long            0x3FFB0000,0x83D152C5,0x060B7A51,0x00000000
6102        long            0x3FFB0000,0x8BC85445,0x65498B8B,0x00000000
6103        long            0x3FFB0000,0x93BE4060,0x17626B0D,0x00000000
6104        long            0x3FFB0000,0x9BB3078D,0x35AEC202,0x00000000
6105        long            0x3FFB0000,0xA3A69A52,0x5DDCE7DE,0x00000000
6106        long            0x3FFB0000,0xAB98E943,0x62765619,0x00000000
6107        long            0x3FFB0000,0xB389E502,0xF9C59862,0x00000000
6108        long            0x3FFB0000,0xBB797E43,0x6B09E6FB,0x00000000
6109        long            0x3FFB0000,0xC367A5C7,0x39E5F446,0x00000000
6110        long            0x3FFB0000,0xCB544C61,0xCFF7D5C6,0x00000000
6111        long            0x3FFB0000,0xD33F62F8,0x2488533E,0x00000000
6112        long            0x3FFB0000,0xDB28DA81,0x62404C77,0x00000000
6113        long            0x3FFB0000,0xE310A407,0x8AD34F18,0x00000000
6114        long            0x3FFB0000,0xEAF6B0A8,0x188EE1EB,0x00000000
6115        long            0x3FFB0000,0xF2DAF194,0x9DBE79D5,0x00000000
6116        long            0x3FFB0000,0xFABD5813,0x61D47E3E,0x00000000
6117        long            0x3FFC0000,0x8346AC21,0x0959ECC4,0x00000000
6118        long            0x3FFC0000,0x8B232A08,0x304282D8,0x00000000
6119        long            0x3FFC0000,0x92FB70B8,0xD29AE2F9,0x00000000
6120        long            0x3FFC0000,0x9ACF476F,0x5CCD1CB4,0x00000000
6121        long            0x3FFC0000,0xA29E7630,0x4954F23F,0x00000000
6122        long            0x3FFC0000,0xAA68C5D0,0x8AB85230,0x00000000
6123        long            0x3FFC0000,0xB22DFFFD,0x9D539F83,0x00000000
6124        long            0x3FFC0000,0xB9EDEF45,0x3E900EA5,0x00000000
6125        long            0x3FFC0000,0xC1A85F1C,0xC75E3EA5,0x00000000
6126        long            0x3FFC0000,0xC95D1BE8,0x28138DE6,0x00000000
6127        long            0x3FFC0000,0xD10BF300,0x840D2DE4,0x00000000
6128        long            0x3FFC0000,0xD8B4B2BA,0x6BC05E7A,0x00000000
6129        long            0x3FFC0000,0xE0572A6B,0xB42335F6,0x00000000
6130        long            0x3FFC0000,0xE7F32A70,0xEA9CAA8F,0x00000000
6131        long            0x3FFC0000,0xEF888432,0x64ECEFAA,0x00000000
6132        long            0x3FFC0000,0xF7170A28,0xECC06666,0x00000000
6133        long            0x3FFD0000,0x812FD288,0x332DAD32,0x00000000
6134        long            0x3FFD0000,0x88A8D1B1,0x218E4D64,0x00000000
6135        long            0x3FFD0000,0x9012AB3F,0x23E4AEE8,0x00000000
6136        long            0x3FFD0000,0x976CC3D4,0x11E7F1B9,0x00000000
6137        long            0x3FFD0000,0x9EB68949,0x3889A227,0x00000000
6138        long            0x3FFD0000,0xA5EF72C3,0x4487361B,0x00000000
6139        long            0x3FFD0000,0xAD1700BA,0xF07A7227,0x00000000
6140        long            0x3FFD0000,0xB42CBCFA,0xFD37EFB7,0x00000000
6141        long            0x3FFD0000,0xBB303A94,0x0BA80F89,0x00000000
6142        long            0x3FFD0000,0xC22115C6,0xFCAEBBAF,0x00000000
6143        long            0x3FFD0000,0xC8FEF3E6,0x86331221,0x00000000
6144        long            0x3FFD0000,0xCFC98330,0xB4000C70,0x00000000
6145        long            0x3FFD0000,0xD6807AA1,0x102C5BF9,0x00000000
6146        long            0x3FFD0000,0xDD2399BC,0x31252AA3,0x00000000
6147        long            0x3FFD0000,0xE3B2A855,0x6B8FC517,0x00000000
6148        long            0x3FFD0000,0xEA2D764F,0x64315989,0x00000000
6149        long            0x3FFD0000,0xF3BF5BF8,0xBAD1A21D,0x00000000
6150        long            0x3FFE0000,0x801CE39E,0x0D205C9A,0x00000000
6151        long            0x3FFE0000,0x8630A2DA,0xDA1ED066,0x00000000
6152        long            0x3FFE0000,0x8C1AD445,0xF3E09B8C,0x00000000
6153        long            0x3FFE0000,0x91DB8F16,0x64F350E2,0x00000000
6154        long            0x3FFE0000,0x97731420,0x365E538C,0x00000000
6155        long            0x3FFE0000,0x9CE1C8E6,0xA0B8CDBA,0x00000000
6156        long            0x3FFE0000,0xA22832DB,0xCADAAE09,0x00000000
6157        long            0x3FFE0000,0xA746F2DD,0xB7602294,0x00000000
6158        long            0x3FFE0000,0xAC3EC0FB,0x997DD6A2,0x00000000
6159        long            0x3FFE0000,0xB110688A,0xEBDC6F6A,0x00000000
6160        long            0x3FFE0000,0xB5BCC490,0x59ECC4B0,0x00000000
6161        long            0x3FFE0000,0xBA44BC7D,0xD470782F,0x00000000
6162        long            0x3FFE0000,0xBEA94144,0xFD049AAC,0x00000000
6163        long            0x3FFE0000,0xC2EB4ABB,0x661628B6,0x00000000
6164        long            0x3FFE0000,0xC70BD54C,0xE602EE14,0x00000000
6165        long            0x3FFE0000,0xCD000549,0xADEC7159,0x00000000
6166        long            0x3FFE0000,0xD48457D2,0xD8EA4EA3,0x00000000
6167        long            0x3FFE0000,0xDB948DA7,0x12DECE3B,0x00000000
6168        long            0x3FFE0000,0xE23855F9,0x69E8096A,0x00000000
6169        long            0x3FFE0000,0xE8771129,0xC4353259,0x00000000
6170        long            0x3FFE0000,0xEE57C16E,0x0D379C0D,0x00000000
6171        long            0x3FFE0000,0xF3E10211,0xA87C3779,0x00000000
6172        long            0x3FFE0000,0xF919039D,0x758B8D41,0x00000000
6173        long            0x3FFE0000,0xFE058B8F,0x64935FB3,0x00000000
6174        long            0x3FFF0000,0x8155FB49,0x7B685D04,0x00000000
6175        long            0x3FFF0000,0x83889E35,0x49D108E1,0x00000000
6176        long            0x3FFF0000,0x859CFA76,0x511D724B,0x00000000
6177        long            0x3FFF0000,0x87952ECF,0xFF8131E7,0x00000000
6178        long            0x3FFF0000,0x89732FD1,0x9557641B,0x00000000
6179        long            0x3FFF0000,0x8B38CAD1,0x01932A35,0x00000000
6180        long            0x3FFF0000,0x8CE7A8D8,0x301EE6B5,0x00000000
6181        long            0x3FFF0000,0x8F46A39E,0x2EAE5281,0x00000000
6182        long            0x3FFF0000,0x922DA7D7,0x91888487,0x00000000
6183        long            0x3FFF0000,0x94D19FCB,0xDEDF5241,0x00000000
6184        long            0x3FFF0000,0x973AB944,0x19D2A08B,0x00000000
6185        long            0x3FFF0000,0x996FF00E,0x08E10B96,0x00000000
6186        long            0x3FFF0000,0x9B773F95,0x12321DA7,0x00000000
6187        long            0x3FFF0000,0x9D55CC32,0x0F935624,0x00000000
6188        long            0x3FFF0000,0x9F100575,0x006CC571,0x00000000
6189        long            0x3FFF0000,0xA0A9C290,0xD97CC06C,0x00000000
6190        long            0x3FFF0000,0xA22659EB,0xEBC0630A,0x00000000
6191        long            0x3FFF0000,0xA388B4AF,0xF6EF0EC9,0x00000000
6192        long            0x3FFF0000,0xA4D35F10,0x61D292C4,0x00000000
6193        long            0x3FFF0000,0xA60895DC,0xFBE3187E,0x00000000
6194        long            0x3FFF0000,0xA72A51DC,0x7367BEAC,0x00000000
6195        long            0x3FFF0000,0xA83A5153,0x0956168F,0x00000000
6196        long            0x3FFF0000,0xA93A2007,0x7539546E,0x00000000
6197        long            0x3FFF0000,0xAA9E7245,0x023B2605,0x00000000
6198        long            0x3FFF0000,0xAC4C84BA,0x6FE4D58F,0x00000000
6199        long            0x3FFF0000,0xADCE4A4A,0x606B9712,0x00000000
6200        long            0x3FFF0000,0xAF2A2DCD,0x8D263C9C,0x00000000
6201        long            0x3FFF0000,0xB0656F81,0xF22265C7,0x00000000
6202        long            0x3FFF0000,0xB1846515,0x0F71496A,0x00000000
6203        long            0x3FFF0000,0xB28AAA15,0x6F9ADA35,0x00000000
6204        long            0x3FFF0000,0xB37B44FF,0x3766B895,0x00000000
6205        long            0x3FFF0000,0xB458C3DC,0xE9630433,0x00000000
6206        long            0x3FFF0000,0xB525529D,0x562246BD,0x00000000
6207        long            0x3FFF0000,0xB5E2CCA9,0x5F9D88CC,0x00000000
6208        long            0x3FFF0000,0xB692CADA,0x7ACA1ADA,0x00000000
6209        long            0x3FFF0000,0xB736AEA7,0xA6925838,0x00000000
6210        long            0x3FFF0000,0xB7CFAB28,0x7E9F7B36,0x00000000
6211        long            0x3FFF0000,0xB85ECC66,0xCB219835,0x00000000
6212        long            0x3FFF0000,0xB8E4FD5A,0x20A593DA,0x00000000
6213        long            0x3FFF0000,0xB99F41F6,0x4AFF9BB5,0x00000000
6214        long            0x3FFF0000,0xBA7F1E17,0x842BBE7B,0x00000000
6215        long            0x3FFF0000,0xBB471285,0x7637E17D,0x00000000
6216        long            0x3FFF0000,0xBBFABE8A,0x4788DF6F,0x00000000
6217        long            0x3FFF0000,0xBC9D0FAD,0x2B689D79,0x00000000
6218        long            0x3FFF0000,0xBD306A39,0x471ECD86,0x00000000
6219        long            0x3FFF0000,0xBDB6C731,0x856AF18A,0x00000000
6220        long            0x3FFF0000,0xBE31CAC5,0x02E80D70,0x00000000
6221        long            0x3FFF0000,0xBEA2D55C,0xE33194E2,0x00000000
6222        long            0x3FFF0000,0xBF0B10B7,0xC03128F0,0x00000000
6223        long            0x3FFF0000,0xBF6B7A18,0xDACB778D,0x00000000
6224        long            0x3FFF0000,0xBFC4EA46,0x63FA18F6,0x00000000
6225        long            0x3FFF0000,0xC0181BDE,0x8B89A454,0x00000000
6226        long            0x3FFF0000,0xC065B066,0xCFBF6439,0x00000000
6227        long            0x3FFF0000,0xC0AE345F,0x56340AE6,0x00000000
6228        long            0x3FFF0000,0xC0F22291,0x9CB9E6A7,0x00000000
6229
6230        set             X,FP_SCR0
6231        set             XDCARE,X+2
6232        set             XFRAC,X+4
6233        set             XFRACLO,X+8
6234
6235        set             ATANF,FP_SCR1
6236        set             ATANFHI,ATANF+4
6237        set             ATANFLO,ATANF+8
6238
6239        global          satan
6240#--ENTRY POINT FOR ATAN(X), HERE X IS FINITE, NON-ZERO, AND NOT NAN'S
6241satan:
6242        fmov.x          (%a0),%fp0              # LOAD INPUT
6243
6244        mov.l           (%a0),%d1
6245        mov.w           4(%a0),%d1
6246        fmov.x          %fp0,X(%a6)
6247        and.l           &0x7FFFFFFF,%d1
6248
6249        cmp.l           %d1,&0x3FFB8000         # |X| >= 1/16?
6250        bge.b           ATANOK1
6251        bra.w           ATANSM
6252
6253ATANOK1:
6254        cmp.l           %d1,&0x4002FFFF         # |X| < 16 ?
6255        ble.b           ATANMAIN
6256        bra.w           ATANBIG
6257
6258#--THE MOST LIKELY CASE, |X| IN [1/16, 16). WE USE TABLE TECHNIQUE
6259#--THE IDEA IS ATAN(X) = ATAN(F) + ATAN( [X-F] / [1+XF] ).
6260#--SO IF F IS CHOSEN TO BE CLOSE TO X AND ATAN(F) IS STORED IN
6261#--A TABLE, ALL WE NEED IS TO APPROXIMATE ATAN(U) WHERE
6262#--U = (X-F)/(1+XF) IS SMALL (REMEMBER F IS CLOSE TO X). IT IS
6263#--TRUE THAT A DIVIDE IS NOW NEEDED, BUT THE APPROXIMATION FOR
6264#--ATAN(U) IS A VERY SHORT POLYNOMIAL AND THE INDEXING TO
6265#--FETCH F AND SAVING OF REGISTERS CAN BE ALL HIDED UNDER THE
6266#--DIVIDE. IN THE END THIS METHOD IS MUCH FASTER THAN A TRADITIONAL
6267#--ONE. NOTE ALSO THAT THE TRADITIONAL SCHEME THAT APPROXIMATE
6268#--ATAN(X) DIRECTLY WILL NEED TO USE A RATIONAL APPROXIMATION
6269#--(DIVISION NEEDED) ANYWAY BECAUSE A POLYNOMIAL APPROXIMATION
6270#--WILL INVOLVE A VERY LONG POLYNOMIAL.
6271
6272#--NOW WE SEE X AS +-2^K * 1.BBBBBBB....B <- 1. + 63 BITS
6273#--WE CHOSE F TO BE +-2^K * 1.BBBB1
6274#--THAT IS IT MATCHES THE EXPONENT AND FIRST 5 BITS OF X, THE
6275#--SIXTH BITS IS SET TO BE 1. SINCE K = -4, -3, ..., 3, THERE
6276#--ARE ONLY 8 TIMES 16 = 2^7 = 128 |F|'S. SINCE ATAN(-|F|) IS
6277#-- -ATAN(|F|), WE NEED TO STORE ONLY ATAN(|F|).
6278
6279ATANMAIN:
6280
6281        and.l           &0xF8000000,XFRAC(%a6)  # FIRST 5 BITS
6282        or.l            &0x04000000,XFRAC(%a6)  # SET 6-TH BIT TO 1
6283        mov.l           &0x00000000,XFRACLO(%a6) # LOCATION OF X IS NOW F
6284
6285        fmov.x          %fp0,%fp1               # FP1 IS X
6286        fmul.x          X(%a6),%fp1             # FP1 IS X*F, NOTE THAT X*F > 0
6287        fsub.x          X(%a6),%fp0             # FP0 IS X-F
6288        fadd.s          &0x3F800000,%fp1        # FP1 IS 1 + X*F
6289        fdiv.x          %fp1,%fp0               # FP0 IS U = (X-F)/(1+X*F)
6290
6291#--WHILE THE DIVISION IS TAKING ITS TIME, WE FETCH ATAN(|F|)
6292#--CREATE ATAN(F) AND STORE IT IN ATANF, AND
6293#--SAVE REGISTERS FP2.
6294
6295        mov.l           %d2,-(%sp)              # SAVE d2 TEMPORARILY
6296        mov.l           %d1,%d2                 # THE EXP AND 16 BITS OF X
6297        and.l           &0x00007800,%d1         # 4 VARYING BITS OF F'S FRACTION
6298        and.l           &0x7FFF0000,%d2         # EXPONENT OF F
6299        sub.l           &0x3FFB0000,%d2         # K+4
6300        asr.l           &1,%d2
6301        add.l           %d2,%d1                 # THE 7 BITS IDENTIFYING F
6302        asr.l           &7,%d1                  # INDEX INTO TBL OF ATAN(|F|)
6303        lea             ATANTBL(%pc),%a1
6304        add.l           %d1,%a1                 # ADDRESS OF ATAN(|F|)
6305        mov.l           (%a1)+,ATANF(%a6)
6306        mov.l           (%a1)+,ATANFHI(%a6)
6307        mov.l           (%a1)+,ATANFLO(%a6)     # ATANF IS NOW ATAN(|F|)
6308        mov.l           X(%a6),%d1              # LOAD SIGN AND EXPO. AGAIN
6309        and.l           &0x80000000,%d1         # SIGN(F)
6310        or.l            %d1,ATANF(%a6)          # ATANF IS NOW SIGN(F)*ATAN(|F|)
6311        mov.l           (%sp)+,%d2              # RESTORE d2
6312
6313#--THAT'S ALL I HAVE TO DO FOR NOW,
6314#--BUT ALAS, THE DIVIDE IS STILL CRANKING!
6315
6316#--U IN FP0, WE ARE NOW READY TO COMPUTE ATAN(U) AS
6317#--U + A1*U*V*(A2 + V*(A3 + V)), V = U*U
6318#--THE POLYNOMIAL MAY LOOK STRANGE, BUT IS NEVERTHELESS CORRECT.
6319#--THE NATURAL FORM IS U + U*V*(A1 + V*(A2 + V*A3))
6320#--WHAT WE HAVE HERE IS MERELY  A1 = A3, A2 = A1/A3, A3 = A2/A3.
6321#--THE REASON FOR THIS REARRANGEMENT IS TO MAKE THE INDEPENDENT
6322#--PARTS A1*U*V AND (A2 + ... STUFF) MORE LOAD-BALANCED
6323
6324        fmovm.x         &0x04,-(%sp)            # save fp2
6325
6326        fmov.x          %fp0,%fp1
6327        fmul.x          %fp1,%fp1
6328        fmov.d          ATANA3(%pc),%fp2
6329        fadd.x          %fp1,%fp2               # A3+V
6330        fmul.x          %fp1,%fp2               # V*(A3+V)
6331        fmul.x          %fp0,%fp1               # U*V
6332        fadd.d          ATANA2(%pc),%fp2        # A2+V*(A3+V)
6333        fmul.d          ATANA1(%pc),%fp1        # A1*U*V
6334        fmul.x          %fp2,%fp1               # A1*U*V*(A2+V*(A3+V))
6335        fadd.x          %fp1,%fp0               # ATAN(U), FP1 RELEASED
6336
6337        fmovm.x         (%sp)+,&0x20            # restore fp2
6338
6339        fmov.l          %d0,%fpcr               # restore users rnd mode,prec
6340        fadd.x          ATANF(%a6),%fp0         # ATAN(X)
6341        bra             t_inx2
6342
6343ATANBORS:
6344#--|X| IS IN d0 IN COMPACT FORM. FP1, d0 SAVED.
6345#--FP0 IS X AND |X| <= 1/16 OR |X| >= 16.
6346        cmp.l           %d1,&0x3FFF8000
6347        bgt.w           ATANBIG                 # I.E. |X| >= 16
6348
6349ATANSM:
6350#--|X| <= 1/16
6351#--IF |X| < 2^(-40), RETURN X AS ANSWER. OTHERWISE, APPROXIMATE
6352#--ATAN(X) BY X + X*Y*(B1+Y*(B2+Y*(B3+Y*(B4+Y*(B5+Y*B6)))))
6353#--WHICH IS X + X*Y*( [B1+Z*(B3+Z*B5)] + [Y*(B2+Z*(B4+Z*B6)] )
6354#--WHERE Y = X*X, AND Z = Y*Y.
6355
6356        cmp.l           %d1,&0x3FD78000
6357        blt.w           ATANTINY
6358
6359#--COMPUTE POLYNOMIAL
6360        fmovm.x         &0x0c,-(%sp)            # save fp2/fp3
6361
6362        fmul.x          %fp0,%fp0               # FPO IS Y = X*X
6363
6364        fmov.x          %fp0,%fp1
6365        fmul.x          %fp1,%fp1               # FP1 IS Z = Y*Y
6366
6367        fmov.d          ATANB6(%pc),%fp2
6368        fmov.d          ATANB5(%pc),%fp3
6369
6370        fmul.x          %fp1,%fp2               # Z*B6
6371        fmul.x          %fp1,%fp3               # Z*B5
6372
6373        fadd.d          ATANB4(%pc),%fp2        # B4+Z*B6
6374        fadd.d          ATANB3(%pc),%fp3        # B3+Z*B5
6375
6376        fmul.x          %fp1,%fp2               # Z*(B4+Z*B6)
6377        fmul.x          %fp3,%fp1               # Z*(B3+Z*B5)
6378
6379        fadd.d          ATANB2(%pc),%fp2        # B2+Z*(B4+Z*B6)
6380        fadd.d          ATANB1(%pc),%fp1        # B1+Z*(B3+Z*B5)
6381
6382        fmul.x          %fp0,%fp2               # Y*(B2+Z*(B4+Z*B6))
6383        fmul.x          X(%a6),%fp0             # X*Y
6384
6385        fadd.x          %fp2,%fp1               # [B1+Z*(B3+Z*B5)]+[Y*(B2+Z*(B4+Z*B6))]
6386
6387        fmul.x          %fp1,%fp0               # X*Y*([B1+Z*(B3+Z*B5)]+[Y*(B2+Z*(B4+Z*B6))])
6388
6389        fmovm.x         (%sp)+,&0x30            # restore fp2/fp3
6390
6391        fmov.l          %d0,%fpcr               # restore users rnd mode,prec
6392        fadd.x          X(%a6),%fp0
6393        bra             t_inx2
6394
6395ATANTINY:
6396#--|X| < 2^(-40), ATAN(X) = X
6397
6398        fmov.l          %d0,%fpcr               # restore users rnd mode,prec
6399        mov.b           &FMOV_OP,%d1            # last inst is MOVE
6400        fmov.x          X(%a6),%fp0             # last inst - possible exception set
6401
6402        bra             t_catch
6403
6404ATANBIG:
6405#--IF |X| > 2^(100), RETURN     SIGN(X)*(PI/2 - TINY). OTHERWISE,
6406#--RETURN SIGN(X)*PI/2 + ATAN(-1/X).
6407        cmp.l           %d1,&0x40638000
6408        bgt.w           ATANHUGE
6409
6410#--APPROXIMATE ATAN(-1/X) BY
6411#--X'+X'*Y*(C1+Y*(C2+Y*(C3+Y*(C4+Y*C5)))), X' = -1/X, Y = X'*X'
6412#--THIS CAN BE RE-WRITTEN AS
6413#--X'+X'*Y*( [C1+Z*(C3+Z*C5)] + [Y*(C2+Z*C4)] ), Z = Y*Y.
6414
6415        fmovm.x         &0x0c,-(%sp)            # save fp2/fp3
6416
6417        fmov.s          &0xBF800000,%fp1        # LOAD -1
6418        fdiv.x          %fp0,%fp1               # FP1 IS -1/X
6419
6420#--DIVIDE IS STILL CRANKING
6421
6422        fmov.x          %fp1,%fp0               # FP0 IS X'
6423        fmul.x          %fp0,%fp0               # FP0 IS Y = X'*X'
6424        fmov.x          %fp1,X(%a6)             # X IS REALLY X'
6425
6426        fmov.x          %fp0,%fp1
6427        fmul.x          %fp1,%fp1               # FP1 IS Z = Y*Y
6428
6429        fmov.d          ATANC5(%pc),%fp3
6430        fmov.d          ATANC4(%pc),%fp2
6431
6432        fmul.x          %fp1,%fp3               # Z*C5
6433        fmul.x          %fp1,%fp2               # Z*B4
6434
6435        fadd.d          ATANC3(%pc),%fp3        # C3+Z*C5
6436        fadd.d          ATANC2(%pc),%fp2        # C2+Z*C4
6437
6438        fmul.x          %fp3,%fp1               # Z*(C3+Z*C5), FP3 RELEASED
6439        fmul.x          %fp0,%fp2               # Y*(C2+Z*C4)
6440
6441        fadd.d          ATANC1(%pc),%fp1        # C1+Z*(C3+Z*C5)
6442        fmul.x          X(%a6),%fp0             # X'*Y
6443
6444        fadd.x          %fp2,%fp1               # [Y*(C2+Z*C4)]+[C1+Z*(C3+Z*C5)]
6445
6446        fmul.x          %fp1,%fp0               # X'*Y*([B1+Z*(B3+Z*B5)]
6447#                                       ...     +[Y*(B2+Z*(B4+Z*B6))])
6448        fadd.x          X(%a6),%fp0
6449
6450        fmovm.x         (%sp)+,&0x30            # restore fp2/fp3
6451
6452        fmov.l          %d0,%fpcr               # restore users rnd mode,prec
6453        tst.b           (%a0)
6454        bpl.b           pos_big
6455
6456neg_big:
6457        fadd.x          NPIBY2(%pc),%fp0
6458        bra             t_minx2
6459
6460pos_big:
6461        fadd.x          PPIBY2(%pc),%fp0
6462        bra             t_pinx2
6463
6464ATANHUGE:
6465#--RETURN SIGN(X)*(PIBY2 - TINY) = SIGN(X)*PIBY2 - SIGN(X)*TINY
6466        tst.b           (%a0)
6467        bpl.b           pos_huge
6468
6469neg_huge:
6470        fmov.x          NPIBY2(%pc),%fp0
6471        fmov.l          %d0,%fpcr
6472        fadd.x          PTINY(%pc),%fp0
6473        bra             t_minx2
6474
6475pos_huge:
6476        fmov.x          PPIBY2(%pc),%fp0
6477        fmov.l          %d0,%fpcr
6478        fadd.x          NTINY(%pc),%fp0
6479        bra             t_pinx2
6480
6481        global          satand
6482#--ENTRY POINT FOR ATAN(X) FOR DENORMALIZED ARGUMENT
6483satand:
6484        bra             t_extdnrm
6485
6486#########################################################################
6487# sasin():  computes the inverse sine of a normalized input             #
6488# sasind(): computes the inverse sine of a denormalized input           #
6489#                                                                       #
6490# INPUT *************************************************************** #
6491#       a0 = pointer to extended precision input                        #
6492#       d0 = round precision,mode                                       #
6493#                                                                       #
6494# OUTPUT ************************************************************** #
6495#       fp0 = arcsin(X)                                                 #
6496#                                                                       #
6497# ACCURACY and MONOTONICITY ******************************************* #
6498#       The returned result is within 3 ulps in 64 significant bit,     #
6499#       i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
6500#       rounded to double precision. The result is provably monotonic   #
6501#       in double precision.                                            #
6502#                                                                       #
6503# ALGORITHM *********************************************************** #
6504#                                                                       #
6505#       ASIN                                                            #
6506#       1. If |X| >= 1, go to 3.                                        #
6507#                                                                       #
6508#       2. (|X| < 1) Calculate asin(X) by                               #
6509#               z := sqrt( [1-X][1+X] )                                 #
6510#               asin(X) = atan( x / z ).                                #
6511#               Exit.                                                   #
6512#                                                                       #
6513#       3. If |X| > 1, go to 5.                                         #
6514#                                                                       #
6515#       4. (|X| = 1) sgn := sign(X), return asin(X) := sgn * Pi/2. Exit.#
6516#                                                                       #
6517#       5. (|X| > 1) Generate an invalid operation by 0 * infinity.     #
6518#               Exit.                                                   #
6519#                                                                       #
6520#########################################################################
6521
6522        global          sasin
6523sasin:
6524        fmov.x          (%a0),%fp0              # LOAD INPUT
6525
6526        mov.l           (%a0),%d1
6527        mov.w           4(%a0),%d1
6528        and.l           &0x7FFFFFFF,%d1
6529        cmp.l           %d1,&0x3FFF8000
6530        bge.b           ASINBIG
6531
6532# This catch is added here for the '060 QSP. Originally, the call to
6533# satan() would handle this case by causing the exception which would
6534# not be caught until gen_except(). Now, with the exceptions being
6535# detected inside of satan(), the exception would have been handled there
6536# instead of inside sasin() as expected.
6537        cmp.l           %d1,&0x3FD78000
6538        blt.w           ASINTINY
6539
6540#--THIS IS THE USUAL CASE, |X| < 1
6541#--ASIN(X) = ATAN( X / SQRT( (1-X)(1+X) ) )
6542
6543ASINMAIN:
6544        fmov.s          &0x3F800000,%fp1
6545        fsub.x          %fp0,%fp1               # 1-X
6546        fmovm.x         &0x4,-(%sp)             #  {fp2}
6547        fmov.s          &0x3F800000,%fp2
6548        fadd.x          %fp0,%fp2               # 1+X
6549        fmul.x          %fp2,%fp1               # (1+X)(1-X)
6550        fmovm.x         (%sp)+,&0x20            #  {fp2}
6551        fsqrt.x         %fp1                    # SQRT([1-X][1+X])
6552        fdiv.x          %fp1,%fp0               # X/SQRT([1-X][1+X])
6553        fmovm.x         &0x01,-(%sp)            # save X/SQRT(...)
6554        lea             (%sp),%a0               # pass ptr to X/SQRT(...)
6555        bsr             satan
6556        add.l           &0xc,%sp                # clear X/SQRT(...) from stack
6557        bra             t_inx2
6558
6559ASINBIG:
6560        fabs.x          %fp0                    # |X|
6561        fcmp.s          %fp0,&0x3F800000
6562        fbgt            t_operr                 # cause an operr exception
6563
6564#--|X| = 1, ASIN(X) = +- PI/2.
6565ASINONE:
6566        fmov.x          PIBY2(%pc),%fp0
6567        mov.l           (%a0),%d1
6568        and.l           &0x80000000,%d1         # SIGN BIT OF X
6569        or.l            &0x3F800000,%d1         # +-1 IN SGL FORMAT
6570        mov.l           %d1,-(%sp)              # push SIGN(X) IN SGL-FMT
6571        fmov.l          %d0,%fpcr
6572        fmul.s          (%sp)+,%fp0
6573        bra             t_inx2
6574
6575#--|X| < 2^(-40), ATAN(X) = X
6576ASINTINY:
6577        fmov.l          %d0,%fpcr               # restore users rnd mode,prec
6578        mov.b           &FMOV_OP,%d1            # last inst is MOVE
6579        fmov.x          (%a0),%fp0              # last inst - possible exception
6580        bra             t_catch
6581
6582        global          sasind
6583#--ASIN(X) = X FOR DENORMALIZED X
6584sasind:
6585        bra             t_extdnrm
6586
6587#########################################################################
6588# sacos():  computes the inverse cosine of a normalized input           #
6589# sacosd(): computes the inverse cosine of a denormalized input         #
6590#                                                                       #
6591# INPUT *************************************************************** #
6592#       a0 = pointer to extended precision input                        #
6593#       d0 = round precision,mode                                       #
6594#                                                                       #
6595# OUTPUT ************************************************************** #
6596#       fp0 = arccos(X)                                                 #
6597#                                                                       #
6598# ACCURACY and MONOTONICITY ******************************************* #
6599#       The returned result is within 3 ulps in 64 significant bit,     #
6600#       i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
6601#       rounded to double precision. The result is provably monotonic   #
6602#       in double precision.                                            #
6603#                                                                       #
6604# ALGORITHM *********************************************************** #
6605#                                                                       #
6606#       ACOS                                                            #
6607#       1. If |X| >= 1, go to 3.                                        #
6608#                                                                       #
6609#       2. (|X| < 1) Calculate acos(X) by                               #
6610#               z := (1-X) / (1+X)                                      #
6611#               acos(X) = 2 * atan( sqrt(z) ).                          #
6612#               Exit.                                                   #
6613#                                                                       #
6614#       3. If |X| > 1, go to 5.                                         #
6615#                                                                       #
6616#       4. (|X| = 1) If X > 0, return 0. Otherwise, return Pi. Exit.    #
6617#                                                                       #
6618#       5. (|X| > 1) Generate an invalid operation by 0 * infinity.     #
6619#               Exit.                                                   #
6620#                                                                       #
6621#########################################################################
6622
6623        global          sacos
6624sacos:
6625        fmov.x          (%a0),%fp0              # LOAD INPUT
6626
6627        mov.l           (%a0),%d1               # pack exp w/ upper 16 fraction
6628        mov.w           4(%a0),%d1
6629        and.l           &0x7FFFFFFF,%d1
6630        cmp.l           %d1,&0x3FFF8000
6631        bge.b           ACOSBIG
6632
6633#--THIS IS THE USUAL CASE, |X| < 1
6634#--ACOS(X) = 2 * ATAN(  SQRT( (1-X)/(1+X) ) )
6635
6636ACOSMAIN:
6637        fmov.s          &0x3F800000,%fp1
6638        fadd.x          %fp0,%fp1               # 1+X
6639        fneg.x          %fp0                    # -X
6640        fadd.s          &0x3F800000,%fp0        # 1-X
6641        fdiv.x          %fp1,%fp0               # (1-X)/(1+X)
6642        fsqrt.x         %fp0                    # SQRT((1-X)/(1+X))
6643        mov.l           %d0,-(%sp)              # save original users fpcr
6644        clr.l           %d0
6645        fmovm.x         &0x01,-(%sp)            # save SQRT(...) to stack
6646        lea             (%sp),%a0               # pass ptr to sqrt
6647        bsr             satan                   # ATAN(SQRT([1-X]/[1+X]))
6648        add.l           &0xc,%sp                # clear SQRT(...) from stack
6649
6650        fmov.l          (%sp)+,%fpcr            # restore users round prec,mode
6651        fadd.x          %fp0,%fp0               # 2 * ATAN( STUFF )
6652        bra             t_pinx2
6653
6654ACOSBIG:
6655        fabs.x          %fp0
6656        fcmp.s          %fp0,&0x3F800000
6657        fbgt            t_operr                 # cause an operr exception
6658
6659#--|X| = 1, ACOS(X) = 0 OR PI
6660        tst.b           (%a0)                   # is X positive or negative?
6661        bpl.b           ACOSP1
6662
6663#--X = -1
6664#Returns PI and inexact exception
6665ACOSM1:
6666        fmov.x          PI(%pc),%fp0            # load PI
6667        fmov.l          %d0,%fpcr               # load round mode,prec
6668        fadd.s          &0x00800000,%fp0        # add a small value
6669        bra             t_pinx2
6670
6671ACOSP1:
6672        bra             ld_pzero                # answer is positive zero
6673
6674        global          sacosd
6675#--ACOS(X) = PI/2 FOR DENORMALIZED X
6676sacosd:
6677        fmov.l          %d0,%fpcr               # load user's rnd mode/prec
6678        fmov.x          PIBY2(%pc),%fp0
6679        bra             t_pinx2
6680
6681#########################################################################
6682# setox():    computes the exponential for a normalized input           #
6683# setoxd():   computes the exponential for a denormalized input         #
6684# setoxm1():  computes the exponential minus 1 for a normalized input   #
6685# setoxm1d(): computes the exponential minus 1 for a denormalized input #
6686#                                                                       #
6687# INPUT *************************************************************** #
6688#       a0 = pointer to extended precision input                        #
6689#       d0 = round precision,mode                                       #
6690#                                                                       #
6691# OUTPUT ************************************************************** #
6692#       fp0 = exp(X) or exp(X)-1                                        #
6693#                                                                       #
6694# ACCURACY and MONOTONICITY ******************************************* #
6695#       The returned result is within 0.85 ulps in 64 significant bit,  #
6696#       i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
6697#       rounded to double precision. The result is provably monotonic   #
6698#       in double precision.                                            #
6699#                                                                       #
6700# ALGORITHM and IMPLEMENTATION **************************************** #
6701#                                                                       #
6702#       setoxd                                                          #
6703#       ------                                                          #
6704#       Step 1. Set ans := 1.0                                          #
6705#                                                                       #
6706#       Step 2. Return  ans := ans + sign(X)*2^(-126). Exit.            #
6707#       Notes:  This will always generate one exception -- inexact.     #
6708#                                                                       #
6709#                                                                       #
6710#       setox                                                           #
6711#       -----                                                           #
6712#                                                                       #
6713#       Step 1. Filter out extreme cases of input argument.             #
6714#               1.1     If |X| >= 2^(-65), go to Step 1.3.              #
6715#               1.2     Go to Step 7.                                   #
6716#               1.3     If |X| < 16380 log(2), go to Step 2.            #
6717#               1.4     Go to Step 8.                                   #
6718#       Notes:  The usual case should take the branches 1.1 -> 1.3 -> 2.#
6719#               To avoid the use of floating-point comparisons, a       #
6720#               compact representation of |X| is used. This format is a #
6721#               32-bit integer, the upper (more significant) 16 bits    #
6722#               are the sign and biased exponent field of |X|; the      #
6723#               lower 16 bits are the 16 most significant fraction      #
6724#               (including the explicit bit) bits of |X|. Consequently, #
6725#               the comparisons in Steps 1.1 and 1.3 can be performed   #
6726#               by integer comparison. Note also that the constant      #
6727#               16380 log(2) used in Step 1.3 is also in the compact    #
6728#               form. Thus taking the branch to Step 2 guarantees       #
6729#               |X| < 16380 log(2). There is no harm to have a small    #
6730#               number of cases where |X| is less than, but close to,   #
6731#               16380 log(2) and the branch to Step 9 is taken.         #
6732#                                                                       #
6733#       Step 2. Calculate N = round-to-nearest-int( X * 64/log2 ).      #
6734#               2.1     Set AdjFlag := 0 (indicates the branch 1.3 -> 2 #
6735#                       was taken)                                      #
6736#               2.2     N := round-to-nearest-integer( X * 64/log2 ).   #
6737#               2.3     Calculate       J = N mod 64; so J = 0,1,2,..., #
6738#                       or 63.                                          #
6739#               2.4     Calculate       M = (N - J)/64; so N = 64M + J. #
6740#               2.5     Calculate the address of the stored value of    #
6741#                       2^(J/64).                                       #
6742#               2.6     Create the value Scale = 2^M.                   #
6743#       Notes:  The calculation in 2.2 is really performed by           #
6744#                       Z := X * constant                               #
6745#                       N := round-to-nearest-integer(Z)                #
6746#               where                                                   #
6747#                       constant := single-precision( 64/log 2 ).       #
6748#                                                                       #
6749#               Using a single-precision constant avoids memory         #
6750#               access. Another effect of using a single-precision      #
6751#               "constant" is that the calculated value Z is            #
6752#                                                                       #
6753#                       Z = X*(64/log2)*(1+eps), |eps| <= 2^(-24).      #
6754#                                                                       #
6755#               This error has to be considered later in Steps 3 and 4. #
6756#                                                                       #
6757#       Step 3. Calculate X - N*log2/64.                                #
6758#               3.1     R := X + N*L1,                                  #
6759#                               where L1 := single-precision(-log2/64). #
6760#               3.2     R := R + N*L2,                                  #
6761#                               L2 := extended-precision(-log2/64 - L1).#
6762#       Notes:  a) The way L1 and L2 are chosen ensures L1+L2           #
6763#               approximate the value -log2/64 to 88 bits of accuracy.  #
6764#               b) N*L1 is exact because N is no longer than 22 bits    #
6765#               and L1 is no longer than 24 bits.                       #
6766#               c) The calculation X+N*L1 is also exact due to          #
6767#               cancellation. Thus, R is practically X+N(L1+L2) to full #
6768#               64 bits.                                                #
6769#               d) It is important to estimate how large can |R| be     #
6770#               after Step 3.2.                                         #
6771#                                                                       #
6772#               N = rnd-to-int( X*64/log2 (1+eps) ), |eps|<=2^(-24)     #
6773#               X*64/log2 (1+eps)       =       N + f,  |f| <= 0.5      #
6774#               X*64/log2 - N   =       f - eps*X 64/log2               #
6775#               X - N*log2/64   =       f*log2/64 - eps*X               #
6776#                                                                       #
6777#                                                                       #
6778#               Now |X| <= 16446 log2, thus                             #
6779#                                                                       #
6780#                       |X - N*log2/64| <= (0.5 + 16446/2^(18))*log2/64 #
6781#                                       <= 0.57 log2/64.                #
6782#                This bound will be used in Step 4.                     #
6783#                                                                       #
6784#       Step 4. Approximate exp(R)-1 by a polynomial                    #
6785#               p = R + R*R*(A1 + R*(A2 + R*(A3 + R*(A4 + R*A5))))      #
6786#       Notes:  a) In order to reduce memory access, the coefficients   #
6787#               are made as "short" as possible: A1 (which is 1/2), A4  #
6788#               and A5 are single precision; A2 and A3 are double       #
6789#               precision.                                              #
6790#               b) Even with the restrictions above,                    #
6791#                  |p - (exp(R)-1)| < 2^(-68.8) for all |R| <= 0.0062.  #
6792#               Note that 0.0062 is slightly bigger than 0.57 log2/64.  #
6793#               c) To fully utilize the pipeline, p is separated into   #
6794#               two independent pieces of roughly equal complexities    #
6795#                       p = [ R + R*S*(A2 + S*A4) ]     +               #
6796#                               [ S*(A1 + S*(A3 + S*A5)) ]              #
6797#               where S = R*R.                                          #
6798#                                                                       #
6799#       Step 5. Compute 2^(J/64)*exp(R) = 2^(J/64)*(1+p) by             #
6800#                               ans := T + ( T*p + t)                   #
6801#               where T and t are the stored values for 2^(J/64).       #
6802#       Notes:  2^(J/64) is stored as T and t where T+t approximates    #
6803#               2^(J/64) to roughly 85 bits; T is in extended precision #
6804#               and t is in single precision. Note also that T is       #
6805#               rounded to 62 bits so that the last two bits of T are   #
6806#               zero. The reason for such a special form is that T-1,   #
6807#               T-2, and T-8 will all be exact --- a property that will #
6808#               give much more accurate computation of the function     #
6809#               EXPM1.                                                  #
6810#                                                                       #
6811#       Step 6. Reconstruction of exp(X)                                #
6812#                       exp(X) = 2^M * 2^(J/64) * exp(R).               #
6813#               6.1     If AdjFlag = 0, go to 6.3                       #
6814#               6.2     ans := ans * AdjScale                           #
6815#               6.3     Restore the user FPCR                           #
6816#               6.4     Return ans := ans * Scale. Exit.                #
6817#       Notes:  If AdjFlag = 0, we have X = Mlog2 + Jlog2/64 + R,       #
6818#               |M| <= 16380, and Scale = 2^M. Moreover, exp(X) will    #
6819#               neither overflow nor underflow. If AdjFlag = 1, that    #
6820#               means that                                              #
6821#                       X = (M1+M)log2 + Jlog2/64 + R, |M1+M| >= 16380. #
6822#               Hence, exp(X) may overflow or underflow or neither.     #
6823#               When that is the case, AdjScale = 2^(M1) where M1 is    #
6824#               approximately M. Thus 6.2 will never cause              #
6825#               over/underflow. Possible exception in 6.4 is overflow   #
6826#               or underflow. The inexact exception is not generated in #
6827#               6.4. Although one can argue that the inexact flag       #
6828#               should always be raised, to simulate that exception     #
6829#               cost to much than the flag is worth in practical uses.  #
6830#                                                                       #
6831#       Step 7. Return 1 + X.                                           #
6832#               7.1     ans := X                                        #
6833#               7.2     Restore user FPCR.                              #
6834#               7.3     Return ans := 1 + ans. Exit                     #
6835#       Notes:  For non-zero X, the inexact exception will always be    #
6836#               raised by 7.3. That is the only exception raised by 7.3.#
6837#               Note also that we use the FMOVEM instruction to move X  #
6838#               in Step 7.1 to avoid unnecessary trapping. (Although    #
6839#               the FMOVEM may not seem relevant since X is normalized, #
6840#               the precaution will be useful in the library version of #
6841#               this code where the separate entry for denormalized     #
6842#               inputs will be done away with.)                         #
6843#                                                                       #
6844#       Step 8. Handle exp(X) where |X| >= 16380log2.                   #
6845#               8.1     If |X| > 16480 log2, go to Step 9.              #
6846#               (mimic 2.2 - 2.6)                                       #
6847#               8.2     N := round-to-integer( X * 64/log2 )            #
6848#               8.3     Calculate J = N mod 64, J = 0,1,...,63          #
6849#               8.4     K := (N-J)/64, M1 := truncate(K/2), M = K-M1,   #
6850#                       AdjFlag := 1.                                   #
6851#               8.5     Calculate the address of the stored value       #
6852#                       2^(J/64).                                       #
6853#               8.6     Create the values Scale = 2^M, AdjScale = 2^M1. #
6854#               8.7     Go to Step 3.                                   #
6855#       Notes:  Refer to notes for 2.2 - 2.6.                           #
6856#                                                                       #
6857#       Step 9. Handle exp(X), |X| > 16480 log2.                        #
6858#               9.1     If X < 0, go to 9.3                             #
6859#               9.2     ans := Huge, go to 9.4                          #
6860#               9.3     ans := Tiny.                                    #
6861#               9.4     Restore user FPCR.                              #
6862#               9.5     Return ans := ans * ans. Exit.                  #
6863#       Notes:  Exp(X) will surely overflow or underflow, depending on  #
6864#               X's sign. "Huge" and "Tiny" are respectively large/tiny #
6865#               extended-precision numbers whose square over/underflow  #
6866#               with an inexact result. Thus, 9.5 always raises the     #
6867#               inexact together with either overflow or underflow.     #
6868#                                                                       #
6869#       setoxm1d                                                        #
6870#       --------                                                        #
6871#                                                                       #
6872#       Step 1. Set ans := 0                                            #
6873#                                                                       #
6874#       Step 2. Return  ans := X + ans. Exit.                           #
6875#       Notes:  This will return X with the appropriate rounding        #
6876#                precision prescribed by the user FPCR.                 #
6877#                                                                       #
6878#       setoxm1                                                         #
6879#       -------                                                         #
6880#                                                                       #
6881#       Step 1. Check |X|                                               #
6882#               1.1     If |X| >= 1/4, go to Step 1.3.                  #
6883#               1.2     Go to Step 7.                                   #
6884#               1.3     If |X| < 70 log(2), go to Step 2.               #
6885#               1.4     Go to Step 10.                                  #
6886#       Notes:  The usual case should take the branches 1.1 -> 1.3 -> 2.#
6887#               However, it is conceivable |X| can be small very often  #
6888#               because EXPM1 is intended to evaluate exp(X)-1          #
6889#               accurately when |X| is small. For further details on    #
6890#               the comparisons, see the notes on Step 1 of setox.      #
6891#                                                                       #
6892#       Step 2. Calculate N = round-to-nearest-int( X * 64/log2 ).      #
6893#               2.1     N := round-to-nearest-integer( X * 64/log2 ).   #
6894#               2.2     Calculate       J = N mod 64; so J = 0,1,2,..., #
6895#                       or 63.                                          #
6896#               2.3     Calculate       M = (N - J)/64; so N = 64M + J. #
6897#               2.4     Calculate the address of the stored value of    #
6898#                       2^(J/64).                                       #
6899#               2.5     Create the values Sc = 2^M and                  #
6900#                       OnebySc := -2^(-M).                             #
6901#       Notes:  See the notes on Step 2 of setox.                       #
6902#                                                                       #
6903#       Step 3. Calculate X - N*log2/64.                                #
6904#               3.1     R := X + N*L1,                                  #
6905#                               where L1 := single-precision(-log2/64). #
6906#               3.2     R := R + N*L2,                                  #
6907#                               L2 := extended-precision(-log2/64 - L1).#
6908#       Notes:  Applying the analysis of Step 3 of setox in this case   #
6909#               shows that |R| <= 0.0055 (note that |X| <= 70 log2 in   #
6910#               this case).                                             #
6911#                                                                       #
6912#       Step 4. Approximate exp(R)-1 by a polynomial                    #
6913#                       p = R+R*R*(A1+R*(A2+R*(A3+R*(A4+R*(A5+R*A6))))) #
6914#       Notes:  a) In order to reduce memory access, the coefficients   #
6915#               are made as "short" as possible: A1 (which is 1/2), A5  #
6916#               and A6 are single precision; A2, A3 and A4 are double   #
6917#               precision.                                              #
6918#               b) Even with the restriction above,                     #
6919#                       |p - (exp(R)-1)| <      |R| * 2^(-72.7)         #
6920#               for all |R| <= 0.0055.                                  #
6921#               c) To fully utilize the pipeline, p is separated into   #
6922#               two independent pieces of roughly equal complexity      #
6923#                       p = [ R*S*(A2 + S*(A4 + S*A6)) ]        +       #
6924#                               [ R + S*(A1 + S*(A3 + S*A5)) ]          #
6925#               where S = R*R.                                          #
6926#                                                                       #
6927#       Step 5. Compute 2^(J/64)*p by                                   #
6928#                               p := T*p                                #
6929#               where T and t are the stored values for 2^(J/64).       #
6930#       Notes:  2^(J/64) is stored as T and t where T+t approximates    #
6931#               2^(J/64) to roughly 85 bits; T is in extended precision #
6932#               and t is in single precision. Note also that T is       #
6933#               rounded to 62 bits so that the last two bits of T are   #
6934#               zero. The reason for such a special form is that T-1,   #
6935#               T-2, and T-8 will all be exact --- a property that will #
6936#               be exploited in Step 6 below. The total relative error  #
6937#               in p is no bigger than 2^(-67.7) compared to the final  #
6938#               result.                                                 #
6939#                                                                       #
6940#       Step 6. Reconstruction of exp(X)-1                              #
6941#                       exp(X)-1 = 2^M * ( 2^(J/64) + p - 2^(-M) ).     #
6942#               6.1     If M <= 63, go to Step 6.3.                     #
6943#               6.2     ans := T + (p + (t + OnebySc)). Go to 6.6       #
6944#               6.3     If M >= -3, go to 6.5.                          #
6945#               6.4     ans := (T + (p + t)) + OnebySc. Go to 6.6       #
6946#               6.5     ans := (T + OnebySc) + (p + t).                 #
6947#               6.6     Restore user FPCR.                              #
6948#               6.7     Return ans := Sc * ans. Exit.                   #
6949#       Notes:  The various arrangements of the expressions give        #
6950#               accurate evaluations.                                   #
6951#                                                                       #
6952#       Step 7. exp(X)-1 for |X| < 1/4.                                 #
6953#               7.1     If |X| >= 2^(-65), go to Step 9.                #
6954#               7.2     Go to Step 8.                                   #
6955#                                                                       #
6956#       Step 8. Calculate exp(X)-1, |X| < 2^(-65).                      #
6957#               8.1     If |X| < 2^(-16312), goto 8.3                   #
6958#               8.2     Restore FPCR; return ans := X - 2^(-16382).     #
6959#                       Exit.                                           #
6960#               8.3     X := X * 2^(140).                               #
6961#               8.4     Restore FPCR; ans := ans - 2^(-16382).          #
6962#                Return ans := ans*2^(140). Exit                        #
6963#       Notes:  The idea is to return "X - tiny" under the user         #
6964#               precision and rounding modes. To avoid unnecessary      #
6965#               inefficiency, we stay away from denormalized numbers    #
6966#               the best we can. For |X| >= 2^(-16312), the             #
6967#               straightforward 8.2 generates the inexact exception as  #
6968#               the case warrants.                                      #
6969#                                                                       #
6970#       Step 9. Calculate exp(X)-1, |X| < 1/4, by a polynomial          #
6971#                       p = X + X*X*(B1 + X*(B2 + ... + X*B12))         #
6972#       Notes:  a) In order to reduce memory access, the coefficients   #
6973#               are made as "short" as possible: B1 (which is 1/2), B9  #
6974#               to B12 are single precision; B3 to B8 are double        #
6975#               precision; and B2 is double extended.                   #
6976#               b) Even with the restriction above,                     #
6977#                       |p - (exp(X)-1)| < |X| 2^(-70.6)                #
6978#               for all |X| <= 0.251.                                   #
6979#               Note that 0.251 is slightly bigger than 1/4.            #
6980#               c) To fully preserve accuracy, the polynomial is        #
6981#               computed as                                             #
6982#                       X + ( S*B1 +    Q ) where S = X*X and           #
6983#                       Q       =       X*S*(B2 + X*(B3 + ... + X*B12)) #
6984#               d) To fully utilize the pipeline, Q is separated into   #
6985#               two independent pieces of roughly equal complexity      #
6986#                       Q = [ X*S*(B2 + S*(B4 + ... + S*B12)) ] +       #
6987#                               [ S*S*(B3 + S*(B5 + ... + S*B11)) ]     #
6988#                                                                       #
6989#       Step 10. Calculate exp(X)-1 for |X| >= 70 log 2.                #
6990#               10.1 If X >= 70log2 , exp(X) - 1 = exp(X) for all       #
6991#               practical purposes. Therefore, go to Step 1 of setox.   #
6992#               10.2 If X <= -70log2, exp(X) - 1 = -1 for all practical #
6993#               purposes.                                               #
6994#               ans := -1                                               #
6995#               Restore user FPCR                                       #
6996#               Return ans := ans + 2^(-126). Exit.                     #
6997#       Notes:  10.2 will always create an inexact and return -1 + tiny #
6998#               in the user rounding precision and mode.                #
6999#                                                                       #
7000#########################################################################
7001
7002L2:     long            0x3FDC0000,0x82E30865,0x4361C4C6,0x00000000
7003
7004EEXPA3: long            0x3FA55555,0x55554CC1
7005EEXPA2: long            0x3FC55555,0x55554A54
7006
7007EM1A4:  long            0x3F811111,0x11174385
7008EM1A3:  long            0x3FA55555,0x55554F5A
7009
7010EM1A2:  long            0x3FC55555,0x55555555,0x00000000,0x00000000
7011
7012EM1B8:  long            0x3EC71DE3,0xA5774682
7013EM1B7:  long            0x3EFA01A0,0x19D7CB68
7014
7015EM1B6:  long            0x3F2A01A0,0x1A019DF3
7016EM1B5:  long            0x3F56C16C,0x16C170E2
7017
7018EM1B4:  long            0x3F811111,0x11111111
7019EM1B3:  long            0x3FA55555,0x55555555
7020
7021EM1B2:  long            0x3FFC0000,0xAAAAAAAA,0xAAAAAAAB
7022        long            0x00000000
7023
7024TWO140: long            0x48B00000,0x00000000
7025TWON140:
7026        long            0x37300000,0x00000000
7027
7028EEXPTBL:
7029        long            0x3FFF0000,0x80000000,0x00000000,0x00000000
7030        long            0x3FFF0000,0x8164D1F3,0xBC030774,0x9F841A9B
7031        long            0x3FFF0000,0x82CD8698,0xAC2BA1D8,0x9FC1D5B9
7032        long            0x3FFF0000,0x843A28C3,0xACDE4048,0xA0728369
7033        long            0x3FFF0000,0x85AAC367,0xCC487B14,0x1FC5C95C
7034        long            0x3FFF0000,0x871F6196,0x9E8D1010,0x1EE85C9F
7035        long            0x3FFF0000,0x88980E80,0x92DA8528,0x9FA20729
7036        long            0x3FFF0000,0x8A14D575,0x496EFD9C,0xA07BF9AF
7037        long            0x3FFF0000,0x8B95C1E3,0xEA8BD6E8,0xA0020DCF
7038        long            0x3FFF0000,0x8D1ADF5B,0x7E5BA9E4,0x205A63DA
7039        long            0x3FFF0000,0x8EA4398B,0x45CD53C0,0x1EB70051
7040        long            0x3FFF0000,0x9031DC43,0x1466B1DC,0x1F6EB029
7041        long            0x3FFF0000,0x91C3D373,0xAB11C338,0xA0781494
7042        long            0x3FFF0000,0x935A2B2F,0x13E6E92C,0x9EB319B0
7043        long            0x3FFF0000,0x94F4EFA8,0xFEF70960,0x2017457D
7044        long            0x3FFF0000,0x96942D37,0x20185A00,0x1F11D537
7045        long            0x3FFF0000,0x9837F051,0x8DB8A970,0x9FB952DD
7046        long            0x3FFF0000,0x99E04593,0x20B7FA64,0x1FE43087
7047        long            0x3FFF0000,0x9B8D39B9,0xD54E5538,0x1FA2A818
7048        long            0x3FFF0000,0x9D3ED9A7,0x2CFFB750,0x1FDE494D
7049        long            0x3FFF0000,0x9EF53260,0x91A111AC,0x20504890
7050        long            0x3FFF0000,0xA0B0510F,0xB9714FC4,0xA073691C
7051        long            0x3FFF0000,0xA2704303,0x0C496818,0x1F9B7A05
7052        long            0x3FFF0000,0xA43515AE,0x09E680A0,0xA0797126
7053        long            0x3FFF0000,0xA5FED6A9,0xB15138EC,0xA071A140
7054        long            0x3FFF0000,0xA7CD93B4,0xE9653568,0x204F62DA
7055        long            0x3FFF0000,0xA9A15AB4,0xEA7C0EF8,0x1F283C4A
7056        long            0x3FFF0000,0xAB7A39B5,0xA93ED338,0x9F9A7FDC
7057        long            0x3FFF0000,0xAD583EEA,0x42A14AC8,0xA05B3FAC
7058        long            0x3FFF0000,0xAF3B78AD,0x690A4374,0x1FDF2610
7059        long            0x3FFF0000,0xB123F581,0xD2AC2590,0x9F705F90
7060        long            0x3FFF0000,0xB311C412,0xA9112488,0x201F678A
7061        long            0x3FFF0000,0xB504F333,0xF9DE6484,0x1F32FB13
7062        long            0x3FFF0000,0xB6FD91E3,0x28D17790,0x20038B30
7063        long            0x3FFF0000,0xB8FBAF47,0x62FB9EE8,0x200DC3CC
7064        long            0x3FFF0000,0xBAFF5AB2,0x133E45FC,0x9F8B2AE6
7065        long            0x3FFF0000,0xBD08A39F,0x580C36C0,0xA02BBF70
7066        long            0x3FFF0000,0xBF1799B6,0x7A731084,0xA00BF518
7067        long            0x3FFF0000,0xC12C4CCA,0x66709458,0xA041DD41
7068        long            0x3FFF0000,0xC346CCDA,0x24976408,0x9FDF137B
7069        long            0x3FFF0000,0xC5672A11,0x5506DADC,0x201F1568
7070        long            0x3FFF0000,0xC78D74C8,0xABB9B15C,0x1FC13A2E
7071        long            0x3FFF0000,0xC9B9BD86,0x6E2F27A4,0xA03F8F03
7072        long            0x3FFF0000,0xCBEC14FE,0xF2727C5C,0x1FF4907D
7073        long            0x3FFF0000,0xCE248C15,0x1F8480E4,0x9E6E53E4
7074        long            0x3FFF0000,0xD06333DA,0xEF2B2594,0x1FD6D45C
7075        long            0x3FFF0000,0xD2A81D91,0xF12AE45C,0xA076EDB9
7076        long            0x3FFF0000,0xD4F35AAB,0xCFEDFA20,0x9FA6DE21
7077        long            0x3FFF0000,0xD744FCCA,0xD69D6AF4,0x1EE69A2F
7078        long            0x3FFF0000,0xD99D15C2,0x78AFD7B4,0x207F439F
7079        long            0x3FFF0000,0xDBFBB797,0xDAF23754,0x201EC207
7080        long            0x3FFF0000,0xDE60F482,0x5E0E9124,0x9E8BE175
7081        long            0x3FFF0000,0xE0CCDEEC,0x2A94E110,0x20032C4B
7082        long            0x3FFF0000,0xE33F8972,0xBE8A5A50,0x2004DFF5
7083        long            0x3FFF0000,0xE5B906E7,0x7C8348A8,0x1E72F47A
7084        long            0x3FFF0000,0xE8396A50,0x3C4BDC68,0x1F722F22
7085        long            0x3FFF0000,0xEAC0C6E7,0xDD243930,0xA017E945
7086        long            0x3FFF0000,0xED4F301E,0xD9942B84,0x1F401A5B
7087        long            0x3FFF0000,0xEFE4B99B,0xDCDAF5CC,0x9FB9A9E3
7088        long            0x3FFF0000,0xF281773C,0x59FFB138,0x20744C05
7089        long            0x3FFF0000,0xF5257D15,0x2486CC2C,0x1F773A19
7090        long            0x3FFF0000,0xF7D0DF73,0x0AD13BB8,0x1FFE90D5
7091        long            0x3FFF0000,0xFA83B2DB,0x722A033C,0xA041ED22
7092        long            0x3FFF0000,0xFD3E0C0C,0xF486C174,0x1F853F3A
7093
7094        set             ADJFLAG,L_SCR2
7095        set             SCALE,FP_SCR0
7096        set             ADJSCALE,FP_SCR1
7097        set             SC,FP_SCR0
7098        set             ONEBYSC,FP_SCR1
7099
7100        global          setox
7101setox:
7102#--entry point for EXP(X), here X is finite, non-zero, and not NaN's
7103
7104#--Step 1.
7105        mov.l           (%a0),%d1               # load part of input X
7106        and.l           &0x7FFF0000,%d1         # biased expo. of X
7107        cmp.l           %d1,&0x3FBE0000         # 2^(-65)
7108        bge.b           EXPC1                   # normal case
7109        bra             EXPSM
7110
7111EXPC1:
7112#--The case |X| >= 2^(-65)
7113        mov.w           4(%a0),%d1              # expo. and partial sig. of |X|
7114        cmp.l           %d1,&0x400CB167         # 16380 log2 trunc. 16 bits
7115        blt.b           EXPMAIN                 # normal case
7116        bra             EEXPBIG
7117
7118EXPMAIN:
7119#--Step 2.
7120#--This is the normal branch:   2^(-65) <= |X| < 16380 log2.
7121        fmov.x          (%a0),%fp0              # load input from (a0)
7122
7123        fmov.x          %fp0,%fp1
7124        fmul.s          &0x42B8AA3B,%fp0        # 64/log2 * X
7125        fmovm.x         &0xc,-(%sp)             # save fp2 {%fp2/%fp3}
7126        mov.l           &0,ADJFLAG(%a6)
7127        fmov.l          %fp0,%d1                # N = int( X * 64/log2 )
7128        lea             EEXPTBL(%pc),%a1
7129        fmov.l          %d1,%fp0                # convert to floating-format
7130
7131        mov.l           %d1,L_SCR1(%a6)         # save N temporarily
7132        and.l           &0x3F,%d1               # D0 is J = N mod 64
7133        lsl.l           &4,%d1
7134        add.l           %d1,%a1                 # address of 2^(J/64)
7135        mov.l           L_SCR1(%a6),%d1
7136        asr.l           &6,%d1                  # D0 is M
7137        add.w           &0x3FFF,%d1             # biased expo. of 2^(M)
7138        mov.w           L2(%pc),L_SCR1(%a6)     # prefetch L2, no need in CB
7139
7140EXPCONT1:
7141#--Step 3.
7142#--fp1,fp2 saved on the stack. fp0 is N, fp1 is X,
7143#--a0 points to 2^(J/64), D0 is biased expo. of 2^(M)
7144        fmov.x          %fp0,%fp2
7145        fmul.s          &0xBC317218,%fp0        # N * L1, L1 = lead(-log2/64)
7146        fmul.x          L2(%pc),%fp2            # N * L2, L1+L2 = -log2/64
7147        fadd.x          %fp1,%fp0               # X + N*L1
7148        fadd.x          %fp2,%fp0               # fp0 is R, reduced arg.
7149
7150#--Step 4.
7151#--WE NOW COMPUTE EXP(R)-1 BY A POLYNOMIAL
7152#-- R + R*R*(A1 + R*(A2 + R*(A3 + R*(A4 + R*A5))))
7153#--TO FULLY UTILIZE THE PIPELINE, WE COMPUTE S = R*R
7154#--[R+R*S*(A2+S*A4)] + [S*(A1+S*(A3+S*A5))]
7155
7156        fmov.x          %fp0,%fp1
7157        fmul.x          %fp1,%fp1               # fp1 IS S = R*R
7158
7159        fmov.s          &0x3AB60B70,%fp2        # fp2 IS A5
7160
7161        fmul.x          %fp1,%fp2               # fp2 IS S*A5
7162        fmov.x          %fp1,%fp3
7163        fmul.s          &0x3C088895,%fp3        # fp3 IS S*A4
7164
7165        fadd.d          EEXPA3(%pc),%fp2        # fp2 IS A3+S*A5
7166        fadd.d          EEXPA2(%pc),%fp3        # fp3 IS A2+S*A4
7167
7168        fmul.x          %fp1,%fp2               # fp2 IS S*(A3+S*A5)
7169        mov.w           %d1,SCALE(%a6)          # SCALE is 2^(M) in extended
7170        mov.l           &0x80000000,SCALE+4(%a6)
7171        clr.l           SCALE+8(%a6)
7172
7173        fmul.x          %fp1,%fp3               # fp3 IS S*(A2+S*A4)
7174
7175        fadd.s          &0x3F000000,%fp2        # fp2 IS A1+S*(A3+S*A5)
7176        fmul.x          %fp0,%fp3               # fp3 IS R*S*(A2+S*A4)
7177
7178        fmul.x          %fp1,%fp2               # fp2 IS S*(A1+S*(A3+S*A5))
7179        fadd.x          %fp3,%fp0               # fp0 IS R+R*S*(A2+S*A4),
7180
7181        fmov.x          (%a1)+,%fp1             # fp1 is lead. pt. of 2^(J/64)
7182        fadd.x          %fp2,%fp0               # fp0 is EXP(R) - 1
7183
7184#--Step 5
7185#--final reconstruction process
7186#--EXP(X) = 2^M * ( 2^(J/64) + 2^(J/64)*(EXP(R)-1) )
7187
7188        fmul.x          %fp1,%fp0               # 2^(J/64)*(Exp(R)-1)
7189        fmovm.x         (%sp)+,&0x30            # fp2 restored {%fp2/%fp3}
7190        fadd.s          (%a1),%fp0              # accurate 2^(J/64)
7191
7192        fadd.x          %fp1,%fp0               # 2^(J/64) + 2^(J/64)*...
7193        mov.l           ADJFLAG(%a6),%d1
7194
7195#--Step 6
7196        tst.l           %d1
7197        beq.b           NORMAL
7198ADJUST:
7199        fmul.x          ADJSCALE(%a6),%fp0
7200NORMAL:
7201        fmov.l          %d0,%fpcr               # restore user FPCR
7202        mov.b           &FMUL_OP,%d1            # last inst is MUL
7203        fmul.x          SCALE(%a6),%fp0         # multiply 2^(M)
7204        bra             t_catch
7205
7206EXPSM:
7207#--Step 7
7208        fmovm.x         (%a0),&0x80             # load X
7209        fmov.l          %d0,%fpcr
7210        fadd.s          &0x3F800000,%fp0        # 1+X in user mode
7211        bra             t_pinx2
7212
7213EEXPBIG:
7214#--Step 8
7215        cmp.l           %d1,&0x400CB27C         # 16480 log2
7216        bgt.b           EXP2BIG
7217#--Steps 8.2 -- 8.6
7218        fmov.x          (%a0),%fp0              # load input from (a0)
7219
7220        fmov.x          %fp0,%fp1
7221        fmul.s          &0x42B8AA3B,%fp0        # 64/log2 * X
7222        fmovm.x         &0xc,-(%sp)             # save fp2 {%fp2/%fp3}
7223        mov.l           &1,ADJFLAG(%a6)
7224        fmov.l          %fp0,%d1                # N = int( X * 64/log2 )
7225        lea             EEXPTBL(%pc),%a1
7226        fmov.l          %d1,%fp0                # convert to floating-format
7227        mov.l           %d1,L_SCR1(%a6)         # save N temporarily
7228        and.l           &0x3F,%d1               # D0 is J = N mod 64
7229        lsl.l           &4,%d1
7230        add.l           %d1,%a1                 # address of 2^(J/64)
7231        mov.l           L_SCR1(%a6),%d1
7232        asr.l           &6,%d1                  # D0 is K
7233        mov.l           %d1,L_SCR1(%a6)         # save K temporarily
7234        asr.l           &1,%d1                  # D0 is M1
7235        sub.l           %d1,L_SCR1(%a6)         # a1 is M
7236        add.w           &0x3FFF,%d1             # biased expo. of 2^(M1)
7237        mov.w           %d1,ADJSCALE(%a6)       # ADJSCALE := 2^(M1)
7238        mov.l           &0x80000000,ADJSCALE+4(%a6)
7239        clr.l           ADJSCALE+8(%a6)
7240        mov.l           L_SCR1(%a6),%d1         # D0 is M
7241        add.w           &0x3FFF,%d1             # biased expo. of 2^(M)
7242        bra.w           EXPCONT1                # go back to Step 3
7243
7244EXP2BIG:
7245#--Step 9
7246        tst.b           (%a0)                   # is X positive or negative?
7247        bmi             t_unfl2
7248        bra             t_ovfl2
7249
7250        global          setoxd
7251setoxd:
7252#--entry point for EXP(X), X is denormalized
7253        mov.l           (%a0),-(%sp)
7254        andi.l          &0x80000000,(%sp)
7255        ori.l           &0x00800000,(%sp)       # sign(X)*2^(-126)
7256
7257        fmov.s          &0x3F800000,%fp0
7258
7259        fmov.l          %d0,%fpcr
7260        fadd.s          (%sp)+,%fp0
7261        bra             t_pinx2
7262
7263        global          setoxm1
7264setoxm1:
7265#--entry point for EXPM1(X), here X is finite, non-zero, non-NaN
7266
7267#--Step 1.
7268#--Step 1.1
7269        mov.l           (%a0),%d1               # load part of input X
7270        and.l           &0x7FFF0000,%d1         # biased expo. of X
7271        cmp.l           %d1,&0x3FFD0000         # 1/4
7272        bge.b           EM1CON1                 # |X| >= 1/4
7273        bra             EM1SM
7274
7275EM1CON1:
7276#--Step 1.3
7277#--The case |X| >= 1/4
7278        mov.w           4(%a0),%d1              # expo. and partial sig. of |X|
7279        cmp.l           %d1,&0x4004C215         # 70log2 rounded up to 16 bits
7280        ble.b           EM1MAIN                 # 1/4 <= |X| <= 70log2
7281        bra             EM1BIG
7282
7283EM1MAIN:
7284#--Step 2.
7285#--This is the case:    1/4 <= |X| <= 70 log2.
7286        fmov.x          (%a0),%fp0              # load input from (a0)
7287
7288        fmov.x          %fp0,%fp1
7289        fmul.s          &0x42B8AA3B,%fp0        # 64/log2 * X
7290        fmovm.x         &0xc,-(%sp)             # save fp2 {%fp2/%fp3}
7291        fmov.l          %fp0,%d1                # N = int( X * 64/log2 )
7292        lea             EEXPTBL(%pc),%a1
7293        fmov.l          %d1,%fp0                # convert to floating-format
7294
7295        mov.l           %d1,L_SCR1(%a6)         # save N temporarily
7296        and.l           &0x3F,%d1               # D0 is J = N mod 64
7297        lsl.l           &4,%d1
7298        add.l           %d1,%a1                 # address of 2^(J/64)
7299        mov.l           L_SCR1(%a6),%d1
7300        asr.l           &6,%d1                  # D0 is M
7301        mov.l           %d1,L_SCR1(%a6)         # save a copy of M
7302
7303#--Step 3.
7304#--fp1,fp2 saved on the stack. fp0 is N, fp1 is X,
7305#--a0 points to 2^(J/64), D0 and a1 both contain M
7306        fmov.x          %fp0,%fp2
7307        fmul.s          &0xBC317218,%fp0        # N * L1, L1 = lead(-log2/64)
7308        fmul.x          L2(%pc),%fp2            # N * L2, L1+L2 = -log2/64
7309        fadd.x          %fp1,%fp0               # X + N*L1
7310        fadd.x          %fp2,%fp0               # fp0 is R, reduced arg.
7311        add.w           &0x3FFF,%d1             # D0 is biased expo. of 2^M
7312
7313#--Step 4.
7314#--WE NOW COMPUTE EXP(R)-1 BY A POLYNOMIAL
7315#-- R + R*R*(A1 + R*(A2 + R*(A3 + R*(A4 + R*(A5 + R*A6)))))
7316#--TO FULLY UTILIZE THE PIPELINE, WE COMPUTE S = R*R
7317#--[R*S*(A2+S*(A4+S*A6))] + [R+S*(A1+S*(A3+S*A5))]
7318
7319        fmov.x          %fp0,%fp1
7320        fmul.x          %fp1,%fp1               # fp1 IS S = R*R
7321
7322        fmov.s          &0x3950097B,%fp2        # fp2 IS a6
7323
7324        fmul.x          %fp1,%fp2               # fp2 IS S*A6
7325        fmov.x          %fp1,%fp3
7326        fmul.s          &0x3AB60B6A,%fp3        # fp3 IS S*A5
7327
7328        fadd.d          EM1A4(%pc),%fp2         # fp2 IS A4+S*A6
7329        fadd.d          EM1A3(%pc),%fp3         # fp3 IS A3+S*A5
7330        mov.w           %d1,SC(%a6)             # SC is 2^(M) in extended
7331        mov.l           &0x80000000,SC+4(%a6)
7332        clr.l           SC+8(%a6)
7333
7334        fmul.x          %fp1,%fp2               # fp2 IS S*(A4+S*A6)
7335        mov.l           L_SCR1(%a6),%d1         # D0 is M
7336        neg.w           %d1                     # D0 is -M
7337        fmul.x          %fp1,%fp3               # fp3 IS S*(A3+S*A5)
7338        add.w           &0x3FFF,%d1             # biased expo. of 2^(-M)
7339        fadd.d          EM1A2(%pc),%fp2         # fp2 IS A2+S*(A4+S*A6)
7340        fadd.s          &0x3F000000,%fp3        # fp3 IS A1+S*(A3+S*A5)
7341
7342        fmul.x          %fp1,%fp2               # fp2 IS S*(A2+S*(A4+S*A6))
7343        or.w            &0x8000,%d1             # signed/expo. of -2^(-M)
7344        mov.w           %d1,ONEBYSC(%a6)        # OnebySc is -2^(-M)
7345        mov.l           &0x80000000,ONEBYSC+4(%a6)
7346        clr.l           ONEBYSC+8(%a6)
7347        fmul.x          %fp3,%fp1               # fp1 IS S*(A1+S*(A3+S*A5))
7348
7349        fmul.x          %fp0,%fp2               # fp2 IS R*S*(A2+S*(A4+S*A6))
7350        fadd.x          %fp1,%fp0               # fp0 IS R+S*(A1+S*(A3+S*A5))
7351
7352        fadd.x          %fp2,%fp0               # fp0 IS EXP(R)-1
7353
7354        fmovm.x         (%sp)+,&0x30            # fp2 restored {%fp2/%fp3}
7355
7356#--Step 5
7357#--Compute 2^(J/64)*p
7358
7359        fmul.x          (%a1),%fp0              # 2^(J/64)*(Exp(R)-1)
7360
7361#--Step 6
7362#--Step 6.1
7363        mov.l           L_SCR1(%a6),%d1         # retrieve M
7364        cmp.l           %d1,&63
7365        ble.b           MLE63
7366#--Step 6.2     M >= 64
7367        fmov.s          12(%a1),%fp1            # fp1 is t
7368        fadd.x          ONEBYSC(%a6),%fp1       # fp1 is t+OnebySc
7369        fadd.x          %fp1,%fp0               # p+(t+OnebySc), fp1 released
7370        fadd.x          (%a1),%fp0              # T+(p+(t+OnebySc))
7371        bra             EM1SCALE
7372MLE63:
7373#--Step 6.3     M <= 63
7374        cmp.l           %d1,&-3
7375        bge.b           MGEN3
7376MLTN3:
7377#--Step 6.4     M <= -4
7378        fadd.s          12(%a1),%fp0            # p+t
7379        fadd.x          (%a1),%fp0              # T+(p+t)
7380        fadd.x          ONEBYSC(%a6),%fp0       # OnebySc + (T+(p+t))
7381        bra             EM1SCALE
7382MGEN3:
7383#--Step 6.5     -3 <= M <= 63
7384        fmov.x          (%a1)+,%fp1             # fp1 is T
7385        fadd.s          (%a1),%fp0              # fp0 is p+t
7386        fadd.x          ONEBYSC(%a6),%fp1       # fp1 is T+OnebySc
7387        fadd.x          %fp1,%fp0               # (T+OnebySc)+(p+t)
7388
7389EM1SCALE:
7390#--Step 6.6
7391        fmov.l          %d0,%fpcr
7392        fmul.x          SC(%a6),%fp0
7393        bra             t_inx2
7394
7395EM1SM:
7396#--Step 7       |X| < 1/4.
7397        cmp.l           %d1,&0x3FBE0000         # 2^(-65)
7398        bge.b           EM1POLY
7399
7400EM1TINY:
7401#--Step 8       |X| < 2^(-65)
7402        cmp.l           %d1,&0x00330000         # 2^(-16312)
7403        blt.b           EM12TINY
7404#--Step 8.2
7405        mov.l           &0x80010000,SC(%a6)     # SC is -2^(-16382)
7406        mov.l           &0x80000000,SC+4(%a6)
7407        clr.l           SC+8(%a6)
7408        fmov.x          (%a0),%fp0
7409        fmov.l          %d0,%fpcr
7410        mov.b           &FADD_OP,%d1            # last inst is ADD
7411        fadd.x          SC(%a6),%fp0
7412        bra             t_catch
7413
7414EM12TINY:
7415#--Step 8.3
7416        fmov.x          (%a0),%fp0
7417        fmul.d          TWO140(%pc),%fp0
7418        mov.l           &0x80010000,SC(%a6)
7419        mov.l           &0x80000000,SC+4(%a6)
7420        clr.l           SC+8(%a6)
7421        fadd.x          SC(%a6),%fp0
7422        fmov.l          %d0,%fpcr
7423        mov.b           &FMUL_OP,%d1            # last inst is MUL
7424        fmul.d          TWON140(%pc),%fp0
7425        bra             t_catch
7426
7427EM1POLY:
7428#--Step 9       exp(X)-1 by a simple polynomial
7429        fmov.x          (%a0),%fp0              # fp0 is X
7430        fmul.x          %fp0,%fp0               # fp0 is S := X*X
7431        fmovm.x         &0xc,-(%sp)             # save fp2 {%fp2/%fp3}
7432        fmov.s          &0x2F30CAA8,%fp1        # fp1 is B12
7433        fmul.x          %fp0,%fp1               # fp1 is S*B12
7434        fmov.s          &0x310F8290,%fp2        # fp2 is B11
7435        fadd.s          &0x32D73220,%fp1        # fp1 is B10+S*B12
7436
7437        fmul.x          %fp0,%fp2               # fp2 is S*B11
7438        fmul.x          %fp0,%fp1               # fp1 is S*(B10 + ...
7439
7440        fadd.s          &0x3493F281,%fp2        # fp2 is B9+S*...
7441        fadd.d          EM1B8(%pc),%fp1         # fp1 is B8+S*...
7442
7443        fmul.x          %fp0,%fp2               # fp2 is S*(B9+...
7444        fmul.x          %fp0,%fp1               # fp1 is S*(B8+...
7445
7446        fadd.d          EM1B7(%pc),%fp2         # fp2 is B7+S*...
7447        fadd.d          EM1B6(%pc),%fp1         # fp1 is B6+S*...
7448
7449        fmul.x          %fp0,%fp2               # fp2 is S*(B7+...
7450        fmul.x          %fp0,%fp1               # fp1 is S*(B6+...
7451
7452        fadd.d          EM1B5(%pc),%fp2         # fp2 is B5+S*...
7453        fadd.d          EM1B4(%pc),%fp1         # fp1 is B4+S*...
7454
7455        fmul.x          %fp0,%fp2               # fp2 is S*(B5+...
7456        fmul.x          %fp0,%fp1               # fp1 is S*(B4+...
7457
7458        fadd.d          EM1B3(%pc),%fp2         # fp2 is B3+S*...
7459        fadd.x          EM1B2(%pc),%fp1         # fp1 is B2+S*...
7460
7461        fmul.x          %fp0,%fp2               # fp2 is S*(B3+...
7462        fmul.x          %fp0,%fp1               # fp1 is S*(B2+...
7463
7464        fmul.x          %fp0,%fp2               # fp2 is S*S*(B3+...)
7465        fmul.x          (%a0),%fp1              # fp1 is X*S*(B2...
7466
7467        fmul.s          &0x3F000000,%fp0        # fp0 is S*B1
7468        fadd.x          %fp2,%fp1               # fp1 is Q
7469
7470        fmovm.x         (%sp)+,&0x30            # fp2 restored {%fp2/%fp3}
7471
7472        fadd.x          %fp1,%fp0               # fp0 is S*B1+Q
7473
7474        fmov.l          %d0,%fpcr
7475        fadd.x          (%a0),%fp0
7476        bra             t_inx2
7477
7478EM1BIG:
7479#--Step 10      |X| > 70 log2
7480        mov.l           (%a0),%d1
7481        cmp.l           %d1,&0
7482        bgt.w           EXPC1
7483#--Step 10.2
7484        fmov.s          &0xBF800000,%fp0        # fp0 is -1
7485        fmov.l          %d0,%fpcr
7486        fadd.s          &0x00800000,%fp0        # -1 + 2^(-126)
7487        bra             t_minx2
7488
7489        global          setoxm1d
7490setoxm1d:
7491#--entry point for EXPM1(X), here X is denormalized
7492#--Step 0.
7493        bra             t_extdnrm
7494
7495#########################################################################
7496# sgetexp():  returns the exponent portion of the input argument.       #
7497#             The exponent bias is removed and the exponent value is    #
7498#             returned as an extended precision number in fp0.          #
7499# sgetexpd(): handles denormalized numbers.                             #
7500#                                                                       #
7501# sgetman():  extracts the mantissa of the input argument. The          #
7502#             mantissa is converted to an extended precision number w/  #
7503#             an exponent of $3fff and is returned in fp0. The range of #
7504#             the result is [1.0 - 2.0).                                #
7505# sgetmand(): handles denormalized numbers.                             #
7506#                                                                       #
7507# INPUT *************************************************************** #
7508#       a0  = pointer to extended precision input                       #
7509#                                                                       #
7510# OUTPUT ************************************************************** #
7511#       fp0 = exponent(X) or mantissa(X)                                #
7512#                                                                       #
7513#########################################################################
7514
7515        global          sgetexp
7516sgetexp:
7517        mov.w           SRC_EX(%a0),%d0         # get the exponent
7518        bclr            &0xf,%d0                # clear the sign bit
7519        subi.w          &0x3fff,%d0             # subtract off the bias
7520        fmov.w          %d0,%fp0                # return exp in fp0
7521        blt.b           sgetexpn                # it's negative
7522        rts
7523
7524sgetexpn:
7525        mov.b           &neg_bmask,FPSR_CC(%a6) # set 'N' ccode bit
7526        rts
7527
7528        global          sgetexpd
7529sgetexpd:
7530        bsr.l           norm                    # normalize
7531        neg.w           %d0                     # new exp = -(shft amt)
7532        subi.w          &0x3fff,%d0             # subtract off the bias
7533        fmov.w          %d0,%fp0                # return exp in fp0
7534        mov.b           &neg_bmask,FPSR_CC(%a6) # set 'N' ccode bit
7535        rts
7536
7537        global          sgetman
7538sgetman:
7539        mov.w           SRC_EX(%a0),%d0         # get the exp
7540        ori.w           &0x7fff,%d0             # clear old exp
7541        bclr            &0xe,%d0                # make it the new exp +-3fff
7542
7543# here, we build the result in a tmp location so as not to disturb the input
7544        mov.l           SRC_HI(%a0),FP_SCR0_HI(%a6) # copy to tmp loc
7545        mov.l           SRC_LO(%a0),FP_SCR0_LO(%a6) # copy to tmp loc
7546        mov.w           %d0,FP_SCR0_EX(%a6)     # insert new exponent
7547        fmov.x          FP_SCR0(%a6),%fp0       # put new value back in fp0
7548        bmi.b           sgetmann                # it's negative
7549        rts
7550
7551sgetmann:
7552        mov.b           &neg_bmask,FPSR_CC(%a6) # set 'N' ccode bit
7553        rts
7554
7555#
7556# For denormalized numbers, shift the mantissa until the j-bit = 1,
7557# then load the exponent with +/1 $3fff.
7558#
7559        global          sgetmand
7560sgetmand:
7561        bsr.l           norm                    # normalize exponent
7562        bra.b           sgetman
7563
7564#########################################################################
7565# scosh():  computes the hyperbolic cosine of a normalized input        #
7566# scoshd(): computes the hyperbolic cosine of a denormalized input      #
7567#                                                                       #
7568# INPUT *************************************************************** #
7569#       a0 = pointer to extended precision input                        #
7570#       d0 = round precision,mode                                       #
7571#                                                                       #
7572# OUTPUT ************************************************************** #
7573#       fp0 = cosh(X)                                                   #
7574#                                                                       #
7575# ACCURACY and MONOTONICITY ******************************************* #
7576#       The returned result is within 3 ulps in 64 significant bit,     #
7577#       i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
7578#       rounded to double precision. The result is provably monotonic   #
7579#       in double precision.                                            #
7580#                                                                       #
7581# ALGORITHM *********************************************************** #
7582#                                                                       #
7583#       COSH                                                            #
7584#       1. If |X| > 16380 log2, go to 3.                                #
7585#                                                                       #
7586#       2. (|X| <= 16380 log2) Cosh(X) is obtained by the formulae      #
7587#               y = |X|, z = exp(Y), and                                #
7588#               cosh(X) = (1/2)*( z + 1/z ).                            #
7589#               Exit.                                                   #
7590#                                                                       #
7591#       3. (|X| > 16380 log2). If |X| > 16480 log2, go to 5.            #
7592#                                                                       #
7593#       4. (16380 log2 < |X| <= 16480 log2)                             #
7594#               cosh(X) = sign(X) * exp(|X|)/2.                         #
7595#               However, invoking exp(|X|) may cause premature          #
7596#               overflow. Thus, we calculate sinh(X) as follows:        #
7597#               Y       := |X|                                          #
7598#               Fact    :=      2**(16380)                              #
7599#               Y'      := Y - 16381 log2                               #
7600#               cosh(X) := Fact * exp(Y').                              #
7601#               Exit.                                                   #
7602#                                                                       #
7603#       5. (|X| > 16480 log2) sinh(X) must overflow. Return             #
7604#               Huge*Huge to generate overflow and an infinity with     #
7605#               the appropriate sign. Huge is the largest finite number #
7606#               in extended format. Exit.                               #
7607#                                                                       #
7608#########################################################################
7609
7610TWO16380:
7611        long            0x7FFB0000,0x80000000,0x00000000,0x00000000
7612
7613        global          scosh
7614scosh:
7615        fmov.x          (%a0),%fp0              # LOAD INPUT
7616
7617        mov.l           (%a0),%d1
7618        mov.w           4(%a0),%d1
7619        and.l           &0x7FFFFFFF,%d1
7620        cmp.l           %d1,&0x400CB167
7621        bgt.b           COSHBIG
7622
7623#--THIS IS THE USUAL CASE, |X| < 16380 LOG2
7624#--COSH(X) = (1/2) * ( EXP(X) + 1/EXP(X) )
7625
7626        fabs.x          %fp0                    # |X|
7627
7628        mov.l           %d0,-(%sp)
7629        clr.l           %d0
7630        fmovm.x         &0x01,-(%sp)            # save |X| to stack
7631        lea             (%sp),%a0               # pass ptr to |X|
7632        bsr             setox                   # FP0 IS EXP(|X|)
7633        add.l           &0xc,%sp                # erase |X| from stack
7634        fmul.s          &0x3F000000,%fp0        # (1/2)EXP(|X|)
7635        mov.l           (%sp)+,%d0
7636
7637        fmov.s          &0x3E800000,%fp1        # (1/4)
7638        fdiv.x          %fp0,%fp1               # 1/(2 EXP(|X|))
7639
7640        fmov.l          %d0,%fpcr
7641        mov.b           &FADD_OP,%d1            # last inst is ADD
7642        fadd.x          %fp1,%fp0
7643        bra             t_catch
7644
7645COSHBIG:
7646        cmp.l           %d1,&0x400CB2B3
7647        bgt.b           COSHHUGE
7648
7649        fabs.x          %fp0
7650        fsub.d          T1(%pc),%fp0            # (|X|-16381LOG2_LEAD)
7651        fsub.d          T2(%pc),%fp0            # |X| - 16381 LOG2, ACCURATE
7652
7653        mov.l           %d0,-(%sp)
7654        clr.l           %d0
7655        fmovm.x         &0x01,-(%sp)            # save fp0 to stack
7656        lea             (%sp),%a0               # pass ptr to fp0
7657        bsr             setox
7658        add.l           &0xc,%sp                # clear fp0 from stack
7659        mov.l           (%sp)+,%d0
7660
7661        fmov.l          %d0,%fpcr
7662        mov.b           &FMUL_OP,%d1            # last inst is MUL
7663        fmul.x          TWO16380(%pc),%fp0
7664        bra             t_catch
7665
7666COSHHUGE:
7667        bra             t_ovfl2
7668
7669        global          scoshd
7670#--COSH(X) = 1 FOR DENORMALIZED X
7671scoshd:
7672        fmov.s          &0x3F800000,%fp0
7673
7674        fmov.l          %d0,%fpcr
7675        fadd.s          &0x00800000,%fp0
7676        bra             t_pinx2
7677
7678#########################################################################
7679# ssinh():  computes the hyperbolic sine of a normalized input          #
7680# ssinhd(): computes the hyperbolic sine of a denormalized input        #
7681#                                                                       #
7682# INPUT *************************************************************** #
7683#       a0 = pointer to extended precision input                        #
7684#       d0 = round precision,mode                                       #
7685#                                                                       #
7686# OUTPUT ************************************************************** #
7687#       fp0 = sinh(X)                                                   #
7688#                                                                       #
7689# ACCURACY and MONOTONICITY ******************************************* #
7690#       The returned result is within 3 ulps in 64 significant bit,     #
7691#       i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
7692#       rounded to double precision. The result is provably monotonic   #
7693#       in double precision.                                            #
7694#                                                                       #
7695# ALGORITHM *********************************************************** #
7696#                                                                       #
7697#       SINH                                                            #
7698#       1. If |X| > 16380 log2, go to 3.                                #
7699#                                                                       #
7700#       2. (|X| <= 16380 log2) Sinh(X) is obtained by the formula       #
7701#               y = |X|, sgn = sign(X), and z = expm1(Y),               #
7702#               sinh(X) = sgn*(1/2)*( z + z/(1+z) ).                    #
7703#          Exit.                                                        #
7704#                                                                       #
7705#       3. If |X| > 16480 log2, go to 5.                                #
7706#                                                                       #
7707#       4. (16380 log2 < |X| <= 16480 log2)                             #
7708#               sinh(X) = sign(X) * exp(|X|)/2.                         #
7709#          However, invoking exp(|X|) may cause premature overflow.     #
7710#          Thus, we calculate sinh(X) as follows:                       #
7711#             Y       := |X|                                            #
7712#             sgn     := sign(X)                                        #
7713#             sgnFact := sgn * 2**(16380)                               #
7714#             Y'      := Y - 16381 log2                                 #
7715#             sinh(X) := sgnFact * exp(Y').                             #
7716#          Exit.                                                        #
7717#                                                                       #
7718#       5. (|X| > 16480 log2) sinh(X) must overflow. Return             #
7719#          sign(X)*Huge*Huge to generate overflow and an infinity with  #
7720#          the appropriate sign. Huge is the largest finite number in   #
7721#          extended format. Exit.                                       #
7722#                                                                       #
7723#########################################################################
7724
7725        global          ssinh
7726ssinh:
7727        fmov.x          (%a0),%fp0              # LOAD INPUT
7728
7729        mov.l           (%a0),%d1
7730        mov.w           4(%a0),%d1
7731        mov.l           %d1,%a1                 # save (compacted) operand
7732        and.l           &0x7FFFFFFF,%d1
7733        cmp.l           %d1,&0x400CB167
7734        bgt.b           SINHBIG
7735
7736#--THIS IS THE USUAL CASE, |X| < 16380 LOG2
7737#--Y = |X|, Z = EXPM1(Y), SINH(X) = SIGN(X)*(1/2)*( Z + Z/(1+Z) )
7738
7739        fabs.x          %fp0                    # Y = |X|
7740
7741        movm.l          &0x8040,-(%sp)          # {a1/d0}
7742        fmovm.x         &0x01,-(%sp)            # save Y on stack
7743        lea             (%sp),%a0               # pass ptr to Y
7744        clr.l           %d0
7745        bsr             setoxm1                 # FP0 IS Z = EXPM1(Y)
7746        add.l           &0xc,%sp                # clear Y from stack
7747        fmov.l          &0,%fpcr
7748        movm.l          (%sp)+,&0x0201          # {a1/d0}
7749
7750        fmov.x          %fp0,%fp1
7751        fadd.s          &0x3F800000,%fp1        # 1+Z
7752        fmov.x          %fp0,-(%sp)
7753        fdiv.x          %fp1,%fp0               # Z/(1+Z)
7754        mov.l           %a1,%d1
7755        and.l           &0x80000000,%d1
7756        or.l            &0x3F000000,%d1
7757        fadd.x          (%sp)+,%fp0
7758        mov.l           %d1,-(%sp)
7759
7760        fmov.l          %d0,%fpcr
7761        mov.b           &FMUL_OP,%d1            # last inst is MUL
7762        fmul.s          (%sp)+,%fp0             # last fp inst - possible exceptions set
7763        bra             t_catch
7764
7765SINHBIG:
7766        cmp.l           %d1,&0x400CB2B3
7767        bgt             t_ovfl
7768        fabs.x          %fp0
7769        fsub.d          T1(%pc),%fp0            # (|X|-16381LOG2_LEAD)
7770        mov.l           &0,-(%sp)
7771        mov.l           &0x80000000,-(%sp)
7772        mov.l           %a1,%d1
7773        and.l           &0x80000000,%d1
7774        or.l            &0x7FFB0000,%d1
7775        mov.l           %d1,-(%sp)              # EXTENDED FMT
7776        fsub.d          T2(%pc),%fp0            # |X| - 16381 LOG2, ACCURATE
7777
7778        mov.l           %d0,-(%sp)
7779        clr.l           %d0
7780        fmovm.x         &0x01,-(%sp)            # save fp0 on stack
7781        lea             (%sp),%a0               # pass ptr to fp0
7782        bsr             setox
7783        add.l           &0xc,%sp                # clear fp0 from stack
7784
7785        mov.l           (%sp)+,%d0
7786        fmov.l          %d0,%fpcr
7787        mov.b           &FMUL_OP,%d1            # last inst is MUL
7788        fmul.x          (%sp)+,%fp0             # possible exception
7789        bra             t_catch
7790
7791        global          ssinhd
7792#--SINH(X) = X FOR DENORMALIZED X
7793ssinhd:
7794        bra             t_extdnrm
7795
7796#########################################################################
7797# stanh():  computes the hyperbolic tangent of a normalized input       #
7798# stanhd(): computes the hyperbolic tangent of a denormalized input     #
7799#                                                                       #
7800# INPUT *************************************************************** #
7801#       a0 = pointer to extended precision input                        #
7802#       d0 = round precision,mode                                       #
7803#                                                                       #
7804# OUTPUT ************************************************************** #
7805#       fp0 = tanh(X)                                                   #
7806#                                                                       #
7807# ACCURACY and MONOTONICITY ******************************************* #
7808#       The returned result is within 3 ulps in 64 significant bit,     #
7809#       i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
7810#       rounded to double precision. The result is provably monotonic   #
7811#       in double precision.                                            #
7812#                                                                       #
7813# ALGORITHM *********************************************************** #
7814#                                                                       #
7815#       TANH                                                            #
7816#       1. If |X| >= (5/2) log2 or |X| <= 2**(-40), go to 3.            #
7817#                                                                       #
7818#       2. (2**(-40) < |X| < (5/2) log2) Calculate tanh(X) by           #
7819#               sgn := sign(X), y := 2|X|, z := expm1(Y), and           #
7820#               tanh(X) = sgn*( z/(2+z) ).                              #
7821#               Exit.                                                   #
7822#                                                                       #
7823#       3. (|X| <= 2**(-40) or |X| >= (5/2) log2). If |X| < 1,          #
7824#               go to 7.                                                #
7825#                                                                       #
7826#       4. (|X| >= (5/2) log2) If |X| >= 50 log2, go to 6.              #
7827#                                                                       #
7828#       5. ((5/2) log2 <= |X| < 50 log2) Calculate tanh(X) by           #
7829#               sgn := sign(X), y := 2|X|, z := exp(Y),                 #
7830#               tanh(X) = sgn - [ sgn*2/(1+z) ].                        #
7831#               Exit.                                                   #
7832#                                                                       #
7833#       6. (|X| >= 50 log2) Tanh(X) = +-1 (round to nearest). Thus, we  #
7834#               calculate Tanh(X) by                                    #
7835#               sgn := sign(X), Tiny := 2**(-126),                      #
7836#               tanh(X) := sgn - sgn*Tiny.                              #
7837#               Exit.                                                   #
7838#                                                                       #
7839#       7. (|X| < 2**(-40)). Tanh(X) = X.       Exit.                   #
7840#                                                                       #
7841#########################################################################
7842
7843        set             X,FP_SCR0
7844        set             XFRAC,X+4
7845
7846        set             SGN,L_SCR3
7847
7848        set             V,FP_SCR0
7849
7850        global          stanh
7851stanh:
7852        fmov.x          (%a0),%fp0              # LOAD INPUT
7853
7854        fmov.x          %fp0,X(%a6)
7855        mov.l           (%a0),%d1
7856        mov.w           4(%a0),%d1
7857        mov.l           %d1,X(%a6)
7858        and.l           &0x7FFFFFFF,%d1
7859        cmp.l           %d1, &0x3fd78000        # is |X| < 2^(-40)?
7860        blt.w           TANHBORS                # yes
7861        cmp.l           %d1, &0x3fffddce        # is |X| > (5/2)LOG2?
7862        bgt.w           TANHBORS                # yes
7863
7864#--THIS IS THE USUAL CASE
7865#--Y = 2|X|, Z = EXPM1(Y), TANH(X) = SIGN(X) * Z / (Z+2).
7866
7867        mov.l           X(%a6),%d1
7868        mov.l           %d1,SGN(%a6)
7869        and.l           &0x7FFF0000,%d1
7870        add.l           &0x00010000,%d1         # EXPONENT OF 2|X|
7871        mov.l           %d1,X(%a6)
7872        and.l           &0x80000000,SGN(%a6)
7873        fmov.x          X(%a6),%fp0             # FP0 IS Y = 2|X|
7874
7875        mov.l           %d0,-(%sp)
7876        clr.l           %d0
7877        fmovm.x         &0x1,-(%sp)             # save Y on stack
7878        lea             (%sp),%a0               # pass ptr to Y
7879        bsr             setoxm1                 # FP0 IS Z = EXPM1(Y)
7880        add.l           &0xc,%sp                # clear Y from stack
7881        mov.l           (%sp)+,%d0
7882
7883        fmov.x          %fp0,%fp1
7884        fadd.s          &0x40000000,%fp1        # Z+2
7885        mov.l           SGN(%a6),%d1
7886        fmov.x          %fp1,V(%a6)
7887        eor.l           %d1,V(%a6)
7888
7889        fmov.l          %d0,%fpcr               # restore users round prec,mode
7890        fdiv.x          V(%a6),%fp0
7891        bra             t_inx2
7892
7893TANHBORS:
7894        cmp.l           %d1,&0x3FFF8000
7895        blt.w           TANHSM
7896
7897        cmp.l           %d1,&0x40048AA1
7898        bgt.w           TANHHUGE
7899
7900#-- (5/2) LOG2 < |X| < 50 LOG2,
7901#--TANH(X) = 1 - (2/[EXP(2X)+1]). LET Y = 2|X|, SGN = SIGN(X),
7902#--TANH(X) = SGN -      SGN*2/[EXP(Y)+1].
7903
7904        mov.l           X(%a6),%d1
7905        mov.l           %d1,SGN(%a6)
7906        and.l           &0x7FFF0000,%d1
7907        add.l           &0x00010000,%d1         # EXPO OF 2|X|
7908        mov.l           %d1,X(%a6)              # Y = 2|X|
7909        and.l           &0x80000000,SGN(%a6)
7910        mov.l           SGN(%a6),%d1
7911        fmov.x          X(%a6),%fp0             # Y = 2|X|
7912
7913        mov.l           %d0,-(%sp)
7914        clr.l           %d0
7915        fmovm.x         &0x01,-(%sp)            # save Y on stack
7916        lea             (%sp),%a0               # pass ptr to Y
7917        bsr             setox                   # FP0 IS EXP(Y)
7918        add.l           &0xc,%sp                # clear Y from stack
7919        mov.l           (%sp)+,%d0
7920        mov.l           SGN(%a6),%d1
7921        fadd.s          &0x3F800000,%fp0        # EXP(Y)+1
7922
7923        eor.l           &0xC0000000,%d1         # -SIGN(X)*2
7924        fmov.s          %d1,%fp1                # -SIGN(X)*2 IN SGL FMT
7925        fdiv.x          %fp0,%fp1               # -SIGN(X)2 / [EXP(Y)+1 ]
7926
7927        mov.l           SGN(%a6),%d1
7928        or.l            &0x3F800000,%d1         # SGN
7929        fmov.s          %d1,%fp0                # SGN IN SGL FMT
7930
7931        fmov.l          %d0,%fpcr               # restore users round prec,mode
7932        mov.b           &FADD_OP,%d1            # last inst is ADD
7933        fadd.x          %fp1,%fp0
7934        bra             t_inx2
7935
7936TANHSM:
7937        fmov.l          %d0,%fpcr               # restore users round prec,mode
7938        mov.b           &FMOV_OP,%d1            # last inst is MOVE
7939        fmov.x          X(%a6),%fp0             # last inst - possible exception set
7940        bra             t_catch
7941
7942#---RETURN SGN(X) - SGN(X)EPS
7943TANHHUGE:
7944        mov.l           X(%a6),%d1
7945        and.l           &0x80000000,%d1
7946        or.l            &0x3F800000,%d1
7947        fmov.s          %d1,%fp0
7948        and.l           &0x80000000,%d1
7949        eor.l           &0x80800000,%d1         # -SIGN(X)*EPS
7950
7951        fmov.l          %d0,%fpcr               # restore users round prec,mode
7952        fadd.s          %d1,%fp0
7953        bra             t_inx2
7954
7955        global          stanhd
7956#--TANH(X) = X FOR DENORMALIZED X
7957stanhd:
7958        bra             t_extdnrm
7959
7960#########################################################################
7961# slogn():    computes the natural logarithm of a normalized input      #
7962# slognd():   computes the natural logarithm of a denormalized input    #
7963# slognp1():  computes the log(1+X) of a normalized input               #
7964# slognp1d(): computes the log(1+X) of a denormalized input             #
7965#                                                                       #
7966# INPUT *************************************************************** #
7967#       a0 = pointer to extended precision input                        #
7968#       d0 = round precision,mode                                       #
7969#                                                                       #
7970# OUTPUT ************************************************************** #
7971#       fp0 = log(X) or log(1+X)                                        #
7972#                                                                       #
7973# ACCURACY and MONOTONICITY ******************************************* #
7974#       The returned result is within 2 ulps in 64 significant bit,     #
7975#       i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
7976#       rounded to double precision. The result is provably monotonic   #
7977#       in double precision.                                            #
7978#                                                                       #
7979# ALGORITHM *********************************************************** #
7980#       LOGN:                                                           #
7981#       Step 1. If |X-1| < 1/16, approximate log(X) by an odd           #
7982#               polynomial in u, where u = 2(X-1)/(X+1). Otherwise,     #
7983#               move on to Step 2.                                      #
7984#                                                                       #
7985#       Step 2. X = 2**k * Y where 1 <= Y < 2. Define F to be the first #
7986#               seven significant bits of Y plus 2**(-7), i.e.          #
7987#               F = 1.xxxxxx1 in base 2 where the six "x" match those   #
7988#               of Y. Note that |Y-F| <= 2**(-7).                       #
7989#                                                                       #
7990#       Step 3. Define u = (Y-F)/F. Approximate log(1+u) by a           #
7991#               polynomial in u, log(1+u) = poly.                       #
7992#                                                                       #
7993#       Step 4. Reconstruct                                             #
7994#               log(X) = log( 2**k * Y ) = k*log(2) + log(F) + log(1+u) #
7995#               by k*log(2) + (log(F) + poly). The values of log(F) are #
7996#               calculated beforehand and stored in the program.        #
7997#                                                                       #
7998#       lognp1:                                                         #
7999#       Step 1: If |X| < 1/16, approximate log(1+X) by an odd           #
8000#               polynomial in u where u = 2X/(2+X). Otherwise, move on  #
8001#               to Step 2.                                              #
8002#                                                                       #
8003#       Step 2: Let 1+X = 2**k * Y, where 1 <= Y < 2. Define F as done  #
8004#               in Step 2 of the algorithm for LOGN and compute         #
8005#               log(1+X) as k*log(2) + log(F) + poly where poly         #
8006#               approximates log(1+u), u = (Y-F)/F.                     #
8007#                                                                       #
8008#       Implementation Notes:                                           #
8009#       Note 1. There are 64 different possible values for F, thus 64   #
8010#               log(F)'s need to be tabulated. Moreover, the values of  #
8011#               1/F are also tabulated so that the division in (Y-F)/F  #
8012#               can be performed by a multiplication.                   #
8013#                                                                       #
8014#       Note 2. In Step 2 of lognp1, in order to preserved accuracy,    #
8015#               the value Y-F has to be calculated carefully when       #
8016#               1/2 <= X < 3/2.                                         #
8017#                                                                       #
8018#       Note 3. To fully exploit the pipeline, polynomials are usually  #
8019#               separated into two parts evaluated independently before #
8020#               being added up.                                         #
8021#                                                                       #
8022#########################################################################
8023LOGOF2:
8024        long            0x3FFE0000,0xB17217F7,0xD1CF79AC,0x00000000
8025
8026one:
8027        long            0x3F800000
8028zero:
8029        long            0x00000000
8030infty:
8031        long            0x7F800000
8032negone:
8033        long            0xBF800000
8034
8035LOGA6:
8036        long            0x3FC2499A,0xB5E4040B
8037LOGA5:
8038        long            0xBFC555B5,0x848CB7DB
8039
8040LOGA4:
8041        long            0x3FC99999,0x987D8730
8042LOGA3:
8043        long            0xBFCFFFFF,0xFF6F7E97
8044
8045LOGA2:
8046        long            0x3FD55555,0x555555A4
8047LOGA1:
8048        long            0xBFE00000,0x00000008
8049
8050LOGB5:
8051        long            0x3F175496,0xADD7DAD6
8052LOGB4:
8053        long            0x3F3C71C2,0xFE80C7E0
8054
8055LOGB3:
8056        long            0x3F624924,0x928BCCFF
8057LOGB2:
8058        long            0x3F899999,0x999995EC
8059
8060LOGB1:
8061        long            0x3FB55555,0x55555555
8062TWO:
8063        long            0x40000000,0x00000000
8064
8065LTHOLD:
8066        long            0x3f990000,0x80000000,0x00000000,0x00000000
8067
8068LOGTBL:
8069        long            0x3FFE0000,0xFE03F80F,0xE03F80FE,0x00000000
8070        long            0x3FF70000,0xFF015358,0x833C47E2,0x00000000
8071        long            0x3FFE0000,0xFA232CF2,0x52138AC0,0x00000000
8072        long            0x3FF90000,0xBDC8D83E,0xAD88D549,0x00000000
8073        long            0x3FFE0000,0xF6603D98,0x0F6603DA,0x00000000
8074        long            0x3FFA0000,0x9CF43DCF,0xF5EAFD48,0x00000000
8075        long            0x3FFE0000,0xF2B9D648,0x0F2B9D65,0x00000000
8076        long            0x3FFA0000,0xDA16EB88,0xCB8DF614,0x00000000
8077        long            0x3FFE0000,0xEF2EB71F,0xC4345238,0x00000000
8078        long            0x3FFB0000,0x8B29B775,0x1BD70743,0x00000000
8079        long            0x3FFE0000,0xEBBDB2A5,0xC1619C8C,0x00000000
8080        long            0x3FFB0000,0xA8D839F8,0x30C1FB49,0x00000000
8081        long            0x3FFE0000,0xE865AC7B,0x7603A197,0x00000000
8082        long            0x3FFB0000,0xC61A2EB1,0x8CD907AD,0x00000000
8083        long            0x3FFE0000,0xE525982A,0xF70C880E,0x00000000
8084        long            0x3FFB0000,0xE2F2A47A,0xDE3A18AF,0x00000000
8085        long            0x3FFE0000,0xE1FC780E,0x1FC780E2,0x00000000
8086        long            0x3FFB0000,0xFF64898E,0xDF55D551,0x00000000
8087        long            0x3FFE0000,0xDEE95C4C,0xA037BA57,0x00000000
8088        long            0x3FFC0000,0x8DB956A9,0x7B3D0148,0x00000000
8089        long            0x3FFE0000,0xDBEB61EE,0xD19C5958,0x00000000
8090        long            0x3FFC0000,0x9B8FE100,0xF47BA1DE,0x00000000
8091        long            0x3FFE0000,0xD901B203,0x6406C80E,0x00000000
8092        long            0x3FFC0000,0xA9372F1D,0x0DA1BD17,0x00000000
8093        long            0x3FFE0000,0xD62B80D6,0x2B80D62C,0x00000000
8094        long            0x3FFC0000,0xB6B07F38,0xCE90E46B,0x00000000
8095        long            0x3FFE0000,0xD3680D36,0x80D3680D,0x00000000
8096        long            0x3FFC0000,0xC3FD0329,0x06488481,0x00000000
8097        long            0x3FFE0000,0xD0B69FCB,0xD2580D0B,0x00000000
8098        long            0x3FFC0000,0xD11DE0FF,0x15AB18CA,0x00000000
8099        long            0x3FFE0000,0xCE168A77,0x25080CE1,0x00000000
8100        long            0x3FFC0000,0xDE1433A1,0x6C66B150,0x00000000
8101        long            0x3FFE0000,0xCB8727C0,0x65C393E0,0x00000000
8102        long            0x3FFC0000,0xEAE10B5A,0x7DDC8ADD,0x00000000
8103        long            0x3FFE0000,0xC907DA4E,0x871146AD,0x00000000
8104        long            0x3FFC0000,0xF7856E5E,0xE2C9B291,0x00000000
8105        long            0x3FFE0000,0xC6980C69,0x80C6980C,0x00000000
8106        long            0x3FFD0000,0x82012CA5,0xA68206D7,0x00000000
8107        long            0x3FFE0000,0xC4372F85,0x5D824CA6,0x00000000
8108        long            0x3FFD0000,0x882C5FCD,0x7256A8C5,0x00000000
8109        long            0x3FFE0000,0xC1E4BBD5,0x95F6E947,0x00000000
8110        long            0x3FFD0000,0x8E44C60B,0x4CCFD7DE,0x00000000
8111        long            0x3FFE0000,0xBFA02FE8,0x0BFA02FF,0x00000000
8112        long            0x3FFD0000,0x944AD09E,0xF4351AF6,0x00000000
8113        long            0x3FFE0000,0xBD691047,0x07661AA3,0x00000000
8114        long            0x3FFD0000,0x9A3EECD4,0xC3EAA6B2,0x00000000
8115        long            0x3FFE0000,0xBB3EE721,0xA54D880C,0x00000000
8116        long            0x3FFD0000,0xA0218434,0x353F1DE8,0x00000000
8117        long            0x3FFE0000,0xB92143FA,0x36F5E02E,0x00000000
8118        long            0x3FFD0000,0xA5F2FCAB,0xBBC506DA,0x00000000
8119        long            0x3FFE0000,0xB70FBB5A,0x19BE3659,0x00000000
8120        long            0x3FFD0000,0xABB3B8BA,0x2AD362A5,0x00000000
8121        long            0x3FFE0000,0xB509E68A,0x9B94821F,0x00000000
8122        long            0x3FFD0000,0xB1641795,0xCE3CA97B,0x00000000
8123        long            0x3FFE0000,0xB30F6352,0x8917C80B,0x00000000
8124        long            0x3FFD0000,0xB7047551,0x5D0F1C61,0x00000000
8125        long            0x3FFE0000,0xB11FD3B8,0x0B11FD3C,0x00000000
8126        long            0x3FFD0000,0xBC952AFE,0xEA3D13E1,0x00000000
8127        long            0x3FFE0000,0xAF3ADDC6,0x80AF3ADE,0x00000000
8128        long            0x3FFD0000,0xC2168ED0,0xF458BA4A,0x00000000
8129        long            0x3FFE0000,0xAD602B58,0x0AD602B6,0x00000000
8130        long            0x3FFD0000,0xC788F439,0xB3163BF1,0x00000000
8131        long            0x3FFE0000,0xAB8F69E2,0x8359CD11,0x00000000
8132        long            0x3FFD0000,0xCCECAC08,0xBF04565D,0x00000000
8133        long            0x3FFE0000,0xA9C84A47,0xA07F5638,0x00000000
8134        long            0x3FFD0000,0xD2420487,0x2DD85160,0x00000000
8135        long            0x3FFE0000,0xA80A80A8,0x0A80A80B,0x00000000
8136        long            0x3FFD0000,0xD7894992,0x3BC3588A,0x00000000
8137        long            0x3FFE0000,0xA655C439,0x2D7B73A8,0x00000000
8138        long            0x3FFD0000,0xDCC2C4B4,0x9887DACC,0x00000000
8139        long            0x3FFE0000,0xA4A9CF1D,0x96833751,0x00000000
8140        long            0x3FFD0000,0xE1EEBD3E,0x6D6A6B9E,0x00000000
8141        long            0x3FFE0000,0xA3065E3F,0xAE7CD0E0,0x00000000
8142        long            0x3FFD0000,0xE70D785C,0x2F9F5BDC,0x00000000
8143        long            0x3FFE0000,0xA16B312E,0xA8FC377D,0x00000000
8144        long            0x3FFD0000,0xEC1F392C,0x5179F283,0x00000000
8145        long            0x3FFE0000,0x9FD809FD,0x809FD80A,0x00000000
8146        long            0x3FFD0000,0xF12440D3,0xE36130E6,0x00000000
8147        long            0x3FFE0000,0x9E4CAD23,0xDD5F3A20,0x00000000
8148        long            0x3FFD0000,0xF61CCE92,0x346600BB,0x00000000
8149        long            0x3FFE0000,0x9CC8E160,0xC3FB19B9,0x00000000
8150        long            0x3FFD0000,0xFB091FD3,0x8145630A,0x00000000
8151        long            0x3FFE0000,0x9B4C6F9E,0xF03A3CAA,0x00000000
8152        long            0x3FFD0000,0xFFE97042,0xBFA4C2AD,0x00000000
8153        long            0x3FFE0000,0x99D722DA,0xBDE58F06,0x00000000
8154        long            0x3FFE0000,0x825EFCED,0x49369330,0x00000000
8155        long            0x3FFE0000,0x9868C809,0x868C8098,0x00000000
8156        long            0x3FFE0000,0x84C37A7A,0xB9A905C9,0x00000000
8157        long            0x3FFE0000,0x97012E02,0x5C04B809,0x00000000
8158        long            0x3FFE0000,0x87224C2E,0x8E645FB7,0x00000000
8159        long            0x3FFE0000,0x95A02568,0x095A0257,0x00000000
8160        long            0x3FFE0000,0x897B8CAC,0x9F7DE298,0x00000000
8161        long            0x3FFE0000,0x94458094,0x45809446,0x00000000
8162        long            0x3FFE0000,0x8BCF55DE,0xC4CD05FE,0x00000000
8163        long            0x3FFE0000,0x92F11384,0x0497889C,0x00000000
8164        long            0x3FFE0000,0x8E1DC0FB,0x89E125E5,0x00000000
8165        long            0x3FFE0000,0x91A2B3C4,0xD5E6F809,0x00000000
8166        long            0x3FFE0000,0x9066E68C,0x955B6C9B,0x00000000
8167        long            0x3FFE0000,0x905A3863,0x3E06C43B,0x00000000
8168        long            0x3FFE0000,0x92AADE74,0xC7BE59E0,0x00000000
8169        long            0x3FFE0000,0x8F1779D9,0xFDC3A219,0x00000000
8170        long            0x3FFE0000,0x94E9BFF6,0x15845643,0x00000000
8171        long            0x3FFE0000,0x8DDA5202,0x37694809,0x00000000
8172        long            0x3FFE0000,0x9723A1B7,0x20134203,0x00000000
8173        long            0x3FFE0000,0x8CA29C04,0x6514E023,0x00000000
8174        long            0x3FFE0000,0x995899C8,0x90EB8990,0x00000000
8175        long            0x3FFE0000,0x8B70344A,0x139BC75A,0x00000000
8176        long            0x3FFE0000,0x9B88BDAA,0x3A3DAE2F,0x00000000
8177        long            0x3FFE0000,0x8A42F870,0x5669DB46,0x00000000
8178        long            0x3FFE0000,0x9DB4224F,0xFFE1157C,0x00000000
8179        long            0x3FFE0000,0x891AC73A,0xE9819B50,0x00000000
8180        long            0x3FFE0000,0x9FDADC26,0x8B7A12DA,0x00000000
8181        long            0x3FFE0000,0x87F78087,0xF78087F8,0x00000000
8182        long            0x3FFE0000,0xA1FCFF17,0xCE733BD4,0x00000000
8183        long            0x3FFE0000,0x86D90544,0x7A34ACC6,0x00000000
8184        long            0x3FFE0000,0xA41A9E8F,0x5446FB9F,0x00000000
8185        long            0x3FFE0000,0x85BF3761,0x2CEE3C9B,0x00000000
8186        long            0x3FFE0000,0xA633CD7E,0x6771CD8B,0x00000000
8187        long            0x3FFE0000,0x84A9F9C8,0x084A9F9D,0x00000000
8188        long            0x3FFE0000,0xA8489E60,0x0B435A5E,0x00000000
8189        long            0x3FFE0000,0x83993052,0x3FBE3368,0x00000000
8190        long            0x3FFE0000,0xAA59233C,0xCCA4BD49,0x00000000
8191        long            0x3FFE0000,0x828CBFBE,0xB9A020A3,0x00000000
8192        long            0x3FFE0000,0xAC656DAE,0x6BCC4985,0x00000000
8193        long            0x3FFE0000,0x81848DA8,0xFAF0D277,0x00000000
8194        long            0x3FFE0000,0xAE6D8EE3,0x60BB2468,0x00000000
8195        long            0x3FFE0000,0x80808080,0x80808081,0x00000000
8196        long            0x3FFE0000,0xB07197A2,0x3C46C654,0x00000000
8197
8198        set             ADJK,L_SCR1
8199
8200        set             X,FP_SCR0
8201        set             XDCARE,X+2
8202        set             XFRAC,X+4
8203
8204        set             F,FP_SCR1
8205        set             FFRAC,F+4
8206
8207        set             KLOG2,FP_SCR0
8208
8209        set             SAVEU,FP_SCR0
8210
8211        global          slogn
8212#--ENTRY POINT FOR LOG(X) FOR X FINITE, NON-ZERO, NOT NAN'S
8213slogn:
8214        fmov.x          (%a0),%fp0              # LOAD INPUT
8215        mov.l           &0x00000000,ADJK(%a6)
8216
8217LOGBGN:
8218#--FPCR SAVED AND CLEARED, INPUT IS 2^(ADJK)*FP0, FP0 CONTAINS
8219#--A FINITE, NON-ZERO, NORMALIZED NUMBER.
8220
8221        mov.l           (%a0),%d1
8222        mov.w           4(%a0),%d1
8223
8224        mov.l           (%a0),X(%a6)
8225        mov.l           4(%a0),X+4(%a6)
8226        mov.l           8(%a0),X+8(%a6)
8227
8228        cmp.l           %d1,&0                  # CHECK IF X IS NEGATIVE
8229        blt.w           LOGNEG                  # LOG OF NEGATIVE ARGUMENT IS INVALID
8230# X IS POSITIVE, CHECK IF X IS NEAR 1
8231        cmp.l           %d1,&0x3ffef07d         # IS X < 15/16?
8232        blt.b           LOGMAIN                 # YES
8233        cmp.l           %d1,&0x3fff8841         # IS X > 17/16?
8234        ble.w           LOGNEAR1                # NO
8235
8236LOGMAIN:
8237#--THIS SHOULD BE THE USUAL CASE, X NOT VERY CLOSE TO 1
8238
8239#--X = 2^(K) * Y, 1 <= Y < 2. THUS, Y = 1.XXXXXXXX....XX IN BINARY.
8240#--WE DEFINE F = 1.XXXXXX1, I.E. FIRST 7 BITS OF Y AND ATTACH A 1.
8241#--THE IDEA IS THAT LOG(X) = K*LOG2 + LOG(Y)
8242#--                      = K*LOG2 + LOG(F) + LOG(1 + (Y-F)/F).
8243#--NOTE THAT U = (Y-F)/F IS VERY SMALL AND THUS APPROXIMATING
8244#--LOG(1+U) CAN BE VERY EFFICIENT.
8245#--ALSO NOTE THAT THE VALUE 1/F IS STORED IN A TABLE SO THAT NO
8246#--DIVISION IS NEEDED TO CALCULATE (Y-F)/F.
8247
8248#--GET K, Y, F, AND ADDRESS OF 1/F.
8249        asr.l           &8,%d1
8250        asr.l           &8,%d1                  # SHIFTED 16 BITS, BIASED EXPO. OF X
8251        sub.l           &0x3FFF,%d1             # THIS IS K
8252        add.l           ADJK(%a6),%d1           # ADJUST K, ORIGINAL INPUT MAY BE  DENORM.
8253        lea             LOGTBL(%pc),%a0         # BASE ADDRESS OF 1/F AND LOG(F)
8254        fmov.l          %d1,%fp1                # CONVERT K TO FLOATING-POINT FORMAT
8255
8256#--WHILE THE CONVERSION IS GOING ON, WE GET F AND ADDRESS OF 1/F
8257        mov.l           &0x3FFF0000,X(%a6)      # X IS NOW Y, I.E. 2^(-K)*X
8258        mov.l           XFRAC(%a6),FFRAC(%a6)
8259        and.l           &0xFE000000,FFRAC(%a6)  # FIRST 7 BITS OF Y
8260        or.l            &0x01000000,FFRAC(%a6)  # GET F: ATTACH A 1 AT THE EIGHTH BIT
8261        mov.l           FFRAC(%a6),%d1  # READY TO GET ADDRESS OF 1/F
8262        and.l           &0x7E000000,%d1
8263        asr.l           &8,%d1
8264        asr.l           &8,%d1
8265        asr.l           &4,%d1                  # SHIFTED 20, D0 IS THE DISPLACEMENT
8266        add.l           %d1,%a0                 # A0 IS THE ADDRESS FOR 1/F
8267
8268        fmov.x          X(%a6),%fp0
8269        mov.l           &0x3fff0000,F(%a6)
8270        clr.l           F+8(%a6)
8271        fsub.x          F(%a6),%fp0             # Y-F
8272        fmovm.x         &0xc,-(%sp)             # SAVE FP2-3 WHILE FP0 IS NOT READY
8273#--SUMMARY: FP0 IS Y-F, A0 IS ADDRESS OF 1/F, FP1 IS K
8274#--REGISTERS SAVED: FPCR, FP1, FP2
8275
8276LP1CONT1:
8277#--AN RE-ENTRY POINT FOR LOGNP1
8278        fmul.x          (%a0),%fp0              # FP0 IS U = (Y-F)/F
8279        fmul.x          LOGOF2(%pc),%fp1        # GET K*LOG2 WHILE FP0 IS NOT READY
8280        fmov.x          %fp0,%fp2
8281        fmul.x          %fp2,%fp2               # FP2 IS V=U*U
8282        fmov.x          %fp1,KLOG2(%a6)         # PUT K*LOG2 IN MEMEORY, FREE FP1
8283
8284#--LOG(1+U) IS APPROXIMATED BY
8285#--U + V*(A1+U*(A2+U*(A3+U*(A4+U*(A5+U*A6))))) WHICH IS
8286#--[U + V*(A1+V*(A3+V*A5))]  +  [U*V*(A2+V*(A4+V*A6))]
8287
8288        fmov.x          %fp2,%fp3
8289        fmov.x          %fp2,%fp1
8290
8291        fmul.d          LOGA6(%pc),%fp1         # V*A6
8292        fmul.d          LOGA5(%pc),%fp2         # V*A5
8293
8294        fadd.d          LOGA4(%pc),%fp1         # A4+V*A6
8295        fadd.d          LOGA3(%pc),%fp2         # A3+V*A5
8296
8297        fmul.x          %fp3,%fp1               # V*(A4+V*A6)
8298        fmul.x          %fp3,%fp2               # V*(A3+V*A5)
8299
8300        fadd.d          LOGA2(%pc),%fp1         # A2+V*(A4+V*A6)
8301        fadd.d          LOGA1(%pc),%fp2         # A1+V*(A3+V*A5)
8302
8303        fmul.x          %fp3,%fp1               # V*(A2+V*(A4+V*A6))
8304        add.l           &16,%a0                 # ADDRESS OF LOG(F)
8305        fmul.x          %fp3,%fp2               # V*(A1+V*(A3+V*A5))
8306
8307        fmul.x          %fp0,%fp1               # U*V*(A2+V*(A4+V*A6))
8308        fadd.x          %fp2,%fp0               # U+V*(A1+V*(A3+V*A5))
8309
8310        fadd.x          (%a0),%fp1              # LOG(F)+U*V*(A2+V*(A4+V*A6))
8311        fmovm.x         (%sp)+,&0x30            # RESTORE FP2-3
8312        fadd.x          %fp1,%fp0               # FP0 IS LOG(F) + LOG(1+U)
8313
8314        fmov.l          %d0,%fpcr
8315        fadd.x          KLOG2(%a6),%fp0         # FINAL ADD
8316        bra             t_inx2
8317
8318
8319LOGNEAR1:
8320
8321# if the input is exactly equal to one, then exit through ld_pzero.
8322# if these 2 lines weren't here, the correct answer would be returned
8323# but the INEX2 bit would be set.
8324        fcmp.b          %fp0,&0x1               # is it equal to one?
8325        fbeq.l          ld_pzero                # yes
8326
8327#--REGISTERS SAVED: FPCR, FP1. FP0 CONTAINS THE INPUT.
8328        fmov.x          %fp0,%fp1
8329        fsub.s          one(%pc),%fp1           # FP1 IS X-1
8330        fadd.s          one(%pc),%fp0           # FP0 IS X+1
8331        fadd.x          %fp1,%fp1               # FP1 IS 2(X-1)
8332#--LOG(X) = LOG(1+U/2)-LOG(1-U/2) WHICH IS AN ODD POLYNOMIAL
8333#--IN U, U = 2(X-1)/(X+1) = FP1/FP0
8334
8335LP1CONT2:
8336#--THIS IS AN RE-ENTRY POINT FOR LOGNP1
8337        fdiv.x          %fp0,%fp1               # FP1 IS U
8338        fmovm.x         &0xc,-(%sp)             # SAVE FP2-3
8339#--REGISTERS SAVED ARE NOW FPCR,FP1,FP2,FP3
8340#--LET V=U*U, W=V*V, CALCULATE
8341#--U + U*V*(B1 + V*(B2 + V*(B3 + V*(B4 + V*B5)))) BY
8342#--U + U*V*(  [B1 + W*(B3 + W*B5)]  +  [V*(B2 + W*B4)]  )
8343        fmov.x          %fp1,%fp0
8344        fmul.x          %fp0,%fp0               # FP0 IS V
8345        fmov.x          %fp1,SAVEU(%a6)         # STORE U IN MEMORY, FREE FP1
8346        fmov.x          %fp0,%fp1
8347        fmul.x          %fp1,%fp1               # FP1 IS W
8348
8349        fmov.d          LOGB5(%pc),%fp3
8350        fmov.d          LOGB4(%pc),%fp2
8351
8352        fmul.x          %fp1,%fp3               # W*B5
8353        fmul.x          %fp1,%fp2               # W*B4
8354
8355        fadd.d          LOGB3(%pc),%fp3         # B3+W*B5
8356        fadd.d          LOGB2(%pc),%fp2         # B2+W*B4
8357
8358        fmul.x          %fp3,%fp1               # W*(B3+W*B5), FP3 RELEASED
8359
8360        fmul.x          %fp0,%fp2               # V*(B2+W*B4)
8361
8362        fadd.d          LOGB1(%pc),%fp1         # B1+W*(B3+W*B5)
8363        fmul.x          SAVEU(%a6),%fp0         # FP0 IS U*V
8364
8365        fadd.x          %fp2,%fp1               # B1+W*(B3+W*B5) + V*(B2+W*B4), FP2 RELEASED
8366        fmovm.x         (%sp)+,&0x30            # FP2-3 RESTORED
8367
8368        fmul.x          %fp1,%fp0               # U*V*( [B1+W*(B3+W*B5)] + [V*(B2+W*B4)] )
8369
8370        fmov.l          %d0,%fpcr
8371        fadd.x          SAVEU(%a6),%fp0
8372        bra             t_inx2
8373
8374#--REGISTERS SAVED FPCR. LOG(-VE) IS INVALID
8375LOGNEG:
8376        bra             t_operr
8377
8378        global          slognd
8379slognd:
8380#--ENTRY POINT FOR LOG(X) FOR DENORMALIZED INPUT
8381
8382        mov.l           &-100,ADJK(%a6)         # INPUT = 2^(ADJK) * FP0
8383
8384#----normalize the input value by left shifting k bits (k to be determined
8385#----below), adjusting exponent and storing -k to  ADJK
8386#----the value TWOTO100 is no longer needed.
8387#----Note that this code assumes the denormalized input is NON-ZERO.
8388
8389        movm.l          &0x3f00,-(%sp)          # save some registers  {d2-d7}
8390        mov.l           (%a0),%d3               # D3 is exponent of smallest norm. #
8391        mov.l           4(%a0),%d4
8392        mov.l           8(%a0),%d5              # (D4,D5) is (Hi_X,Lo_X)
8393        clr.l           %d2                     # D2 used for holding K
8394
8395        tst.l           %d4
8396        bne.b           Hi_not0
8397
8398Hi_0:
8399        mov.l           %d5,%d4
8400        clr.l           %d5
8401        mov.l           &32,%d2
8402        clr.l           %d6
8403        bfffo           %d4{&0:&32},%d6
8404        lsl.l           %d6,%d4
8405        add.l           %d6,%d2                 # (D3,D4,D5) is normalized
8406
8407        mov.l           %d3,X(%a6)
8408        mov.l           %d4,XFRAC(%a6)
8409        mov.l           %d5,XFRAC+4(%a6)
8410        neg.l           %d2
8411        mov.l           %d2,ADJK(%a6)
8412        fmov.x          X(%a6),%fp0
8413        movm.l          (%sp)+,&0xfc            # restore registers {d2-d7}
8414        lea             X(%a6),%a0
8415        bra.w           LOGBGN                  # begin regular log(X)
8416
8417Hi_not0:
8418        clr.l           %d6
8419        bfffo           %d4{&0:&32},%d6         # find first 1
8420        mov.l           %d6,%d2                 # get k
8421        lsl.l           %d6,%d4
8422        mov.l           %d5,%d7                 # a copy of D5
8423        lsl.l           %d6,%d5
8424        neg.l           %d6
8425        add.l           &32,%d6
8426        lsr.l           %d6,%d7
8427        or.l            %d7,%d4                 # (D3,D4,D5) normalized
8428
8429        mov.l           %d3,X(%a6)
8430        mov.l           %d4,XFRAC(%a6)
8431        mov.l           %d5,XFRAC+4(%a6)
8432        neg.l           %d2
8433        mov.l           %d2,ADJK(%a6)
8434        fmov.x          X(%a6),%fp0
8435        movm.l          (%sp)+,&0xfc            # restore registers {d2-d7}
8436        lea             X(%a6),%a0
8437        bra.w           LOGBGN                  # begin regular log(X)
8438
8439        global          slognp1
8440#--ENTRY POINT FOR LOG(1+X) FOR X FINITE, NON-ZERO, NOT NAN'S
8441slognp1:
8442        fmov.x          (%a0),%fp0              # LOAD INPUT
8443        fabs.x          %fp0                    # test magnitude
8444        fcmp.x          %fp0,LTHOLD(%pc)        # compare with min threshold
8445        fbgt.w          LP1REAL                 # if greater, continue
8446        fmov.l          %d0,%fpcr
8447        mov.b           &FMOV_OP,%d1            # last inst is MOVE
8448        fmov.x          (%a0),%fp0              # return signed argument
8449        bra             t_catch
8450
8451LP1REAL:
8452        fmov.x          (%a0),%fp0              # LOAD INPUT
8453        mov.l           &0x00000000,ADJK(%a6)
8454        fmov.x          %fp0,%fp1               # FP1 IS INPUT Z
8455        fadd.s          one(%pc),%fp0           # X := ROUND(1+Z)
8456        fmov.x          %fp0,X(%a6)
8457        mov.w           XFRAC(%a6),XDCARE(%a6)
8458        mov.l           X(%a6),%d1
8459        cmp.l           %d1,&0
8460        ble.w           LP1NEG0                 # LOG OF ZERO OR -VE
8461        cmp.l           %d1,&0x3ffe8000         # IS BOUNDS [1/2,3/2]?
8462        blt.w           LOGMAIN
8463        cmp.l           %d1,&0x3fffc000
8464        bgt.w           LOGMAIN
8465#--IF 1+Z > 3/2 OR 1+Z < 1/2, THEN X, WHICH IS ROUNDING 1+Z,
8466#--CONTAINS AT LEAST 63 BITS OF INFORMATION OF Z. IN THAT CASE,
8467#--SIMPLY INVOKE LOG(X) FOR LOG(1+Z).
8468
8469LP1NEAR1:
8470#--NEXT SEE IF EXP(-1/16) < X < EXP(1/16)
8471        cmp.l           %d1,&0x3ffef07d
8472        blt.w           LP1CARE
8473        cmp.l           %d1,&0x3fff8841
8474        bgt.w           LP1CARE
8475
8476LP1ONE16:
8477#--EXP(-1/16) < X < EXP(1/16). LOG(1+Z) = LOG(1+U/2) - LOG(1-U/2)
8478#--WHERE U = 2Z/(2+Z) = 2Z/(1+X).
8479        fadd.x          %fp1,%fp1               # FP1 IS 2Z
8480        fadd.s          one(%pc),%fp0           # FP0 IS 1+X
8481#--U = FP1/FP0
8482        bra.w           LP1CONT2
8483
8484LP1CARE:
8485#--HERE WE USE THE USUAL TABLE DRIVEN APPROACH. CARE HAS TO BE
8486#--TAKEN BECAUSE 1+Z CAN HAVE 67 BITS OF INFORMATION AND WE MUST
8487#--PRESERVE ALL THE INFORMATION. BECAUSE 1+Z IS IN [1/2,3/2],
8488#--THERE ARE ONLY TWO CASES.
8489#--CASE 1: 1+Z < 1, THEN K = -1 AND Y-F = (2-F) + 2Z
8490#--CASE 2: 1+Z > 1, THEN K = 0  AND Y-F = (1-F) + Z
8491#--ON RETURNING TO LP1CONT1, WE MUST HAVE K IN FP1, ADDRESS OF
8492#--(1/F) IN A0, Y-F IN FP0, AND FP2 SAVED.
8493
8494        mov.l           XFRAC(%a6),FFRAC(%a6)
8495        and.l           &0xFE000000,FFRAC(%a6)
8496        or.l            &0x01000000,FFRAC(%a6)  # F OBTAINED
8497        cmp.l           %d1,&0x3FFF8000         # SEE IF 1+Z > 1
8498        bge.b           KISZERO
8499
8500KISNEG1:
8501        fmov.s          TWO(%pc),%fp0
8502        mov.l           &0x3fff0000,F(%a6)
8503        clr.l           F+8(%a6)
8504        fsub.x          F(%a6),%fp0             # 2-F
8505        mov.l           FFRAC(%a6),%d1
8506        and.l           &0x7E000000,%d1
8507        asr.l           &8,%d1
8508        asr.l           &8,%d1
8509        asr.l           &4,%d1                  # D0 CONTAINS DISPLACEMENT FOR 1/F
8510        fadd.x          %fp1,%fp1               # GET 2Z
8511        fmovm.x         &0xc,-(%sp)             # SAVE FP2  {%fp2/%fp3}
8512        fadd.x          %fp1,%fp0               # FP0 IS Y-F = (2-F)+2Z
8513        lea             LOGTBL(%pc),%a0         # A0 IS ADDRESS OF 1/F
8514        add.l           %d1,%a0
8515        fmov.s          negone(%pc),%fp1        # FP1 IS K = -1
8516        bra.w           LP1CONT1
8517
8518KISZERO:
8519        fmov.s          one(%pc),%fp0
8520        mov.l           &0x3fff0000,F(%a6)
8521        clr.l           F+8(%a6)
8522        fsub.x          F(%a6),%fp0             # 1-F
8523        mov.l           FFRAC(%a6),%d1
8524        and.l           &0x7E000000,%d1
8525        asr.l           &8,%d1
8526        asr.l           &8,%d1
8527        asr.l           &4,%d1
8528        fadd.x          %fp1,%fp0               # FP0 IS Y-F
8529        fmovm.x         &0xc,-(%sp)             # FP2 SAVED {%fp2/%fp3}
8530        lea             LOGTBL(%pc),%a0
8531        add.l           %d1,%a0                 # A0 IS ADDRESS OF 1/F
8532        fmov.s          zero(%pc),%fp1          # FP1 IS K = 0
8533        bra.w           LP1CONT1
8534
8535LP1NEG0:
8536#--FPCR SAVED. D0 IS X IN COMPACT FORM.
8537        cmp.l           %d1,&0
8538        blt.b           LP1NEG
8539LP1ZERO:
8540        fmov.s          negone(%pc),%fp0
8541
8542        fmov.l          %d0,%fpcr
8543        bra             t_dz
8544
8545LP1NEG:
8546        fmov.s          zero(%pc),%fp0
8547
8548        fmov.l          %d0,%fpcr
8549        bra             t_operr
8550
8551        global          slognp1d
8552#--ENTRY POINT FOR LOG(1+Z) FOR DENORMALIZED INPUT
8553# Simply return the denorm
8554slognp1d:
8555        bra             t_extdnrm
8556
8557#########################################################################
8558# satanh():  computes the inverse hyperbolic tangent of a norm input    #
8559# satanhd(): computes the inverse hyperbolic tangent of a denorm input  #
8560#                                                                       #
8561# INPUT *************************************************************** #
8562#       a0 = pointer to extended precision input                        #
8563#       d0 = round precision,mode                                       #
8564#                                                                       #
8565# OUTPUT ************************************************************** #
8566#       fp0 = arctanh(X)                                                #
8567#                                                                       #
8568# ACCURACY and MONOTONICITY ******************************************* #
8569#       The returned result is within 3 ulps in 64 significant bit,     #
8570#       i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
8571#       rounded to double precision. The result is provably monotonic   #
8572#       in double precision.                                            #
8573#                                                                       #
8574# ALGORITHM *********************************************************** #
8575#                                                                       #
8576#       ATANH                                                           #
8577#       1. If |X| >= 1, go to 3.                                        #
8578#                                                                       #
8579#       2. (|X| < 1) Calculate atanh(X) by                              #
8580#               sgn := sign(X)                                          #
8581#               y := |X|                                                #
8582#               z := 2y/(1-y)                                           #
8583#               atanh(X) := sgn * (1/2) * logp1(z)                      #
8584#               Exit.                                                   #
8585#                                                                       #
8586#       3. If |X| > 1, go to 5.                                         #
8587#                                                                       #
8588#       4. (|X| = 1) Generate infinity with an appropriate sign and     #
8589#               divide-by-zero by                                       #
8590#               sgn := sign(X)                                          #
8591#               atan(X) := sgn / (+0).                                  #
8592#               Exit.                                                   #
8593#                                                                       #
8594#       5. (|X| > 1) Generate an invalid operation by 0 * infinity.     #
8595#               Exit.                                                   #
8596#                                                                       #
8597#########################################################################
8598
8599        global          satanh
8600satanh:
8601        mov.l           (%a0),%d1
8602        mov.w           4(%a0),%d1
8603        and.l           &0x7FFFFFFF,%d1
8604        cmp.l           %d1,&0x3FFF8000
8605        bge.b           ATANHBIG
8606
8607#--THIS IS THE USUAL CASE, |X| < 1
8608#--Y = |X|, Z = 2Y/(1-Y), ATANH(X) = SIGN(X) * (1/2) * LOG1P(Z).
8609
8610        fabs.x          (%a0),%fp0              # Y = |X|
8611        fmov.x          %fp0,%fp1
8612        fneg.x          %fp1                    # -Y
8613        fadd.x          %fp0,%fp0               # 2Y
8614        fadd.s          &0x3F800000,%fp1        # 1-Y
8615        fdiv.x          %fp1,%fp0               # 2Y/(1-Y)
8616        mov.l           (%a0),%d1
8617        and.l           &0x80000000,%d1
8618        or.l            &0x3F000000,%d1         # SIGN(X)*HALF
8619        mov.l           %d1,-(%sp)
8620
8621        mov.l           %d0,-(%sp)              # save rnd prec,mode
8622        clr.l           %d0                     # pass ext prec,RN
8623        fmovm.x         &0x01,-(%sp)            # save Z on stack
8624        lea             (%sp),%a0               # pass ptr to Z
8625        bsr             slognp1                 # LOG1P(Z)
8626        add.l           &0xc,%sp                # clear Z from stack
8627
8628        mov.l           (%sp)+,%d0              # fetch old prec,mode
8629        fmov.l          %d0,%fpcr               # load it
8630        mov.b           &FMUL_OP,%d1            # last inst is MUL
8631        fmul.s          (%sp)+,%fp0
8632        bra             t_catch
8633
8634ATANHBIG:
8635        fabs.x          (%a0),%fp0              # |X|
8636        fcmp.s          %fp0,&0x3F800000
8637        fbgt            t_operr
8638        bra             t_dz
8639
8640        global          satanhd
8641#--ATANH(X) = X FOR DENORMALIZED X
8642satanhd:
8643        bra             t_extdnrm
8644
8645#########################################################################
8646# slog10():  computes the base-10 logarithm of a normalized input       #
8647# slog10d(): computes the base-10 logarithm of a denormalized input     #
8648# slog2():   computes the base-2 logarithm of a normalized input        #
8649# slog2d():  computes the base-2 logarithm of a denormalized input      #
8650#                                                                       #
8651# INPUT *************************************************************** #
8652#       a0 = pointer to extended precision input                        #
8653#       d0 = round precision,mode                                       #
8654#                                                                       #
8655# OUTPUT ************************************************************** #
8656#       fp0 = log_10(X) or log_2(X)                                     #
8657#                                                                       #
8658# ACCURACY and MONOTONICITY ******************************************* #
8659#       The returned result is within 1.7 ulps in 64 significant bit,   #
8660#       i.e. within 0.5003 ulp to 53 bits if the result is subsequently #
8661#       rounded to double precision. The result is provably monotonic   #
8662#       in double precision.                                            #
8663#                                                                       #
8664# ALGORITHM *********************************************************** #
8665#                                                                       #
8666#       slog10d:                                                        #
8667#                                                                       #
8668#       Step 0. If X < 0, create a NaN and raise the invalid operation  #
8669#               flag. Otherwise, save FPCR in D1; set FpCR to default.  #
8670#       Notes:  Default means round-to-nearest mode, no floating-point  #
8671#               traps, and precision control = double extended.         #
8672#                                                                       #
8673#       Step 1. Call slognd to obtain Y = log(X), the natural log of X. #
8674#       Notes:  Even if X is denormalized, log(X) is always normalized. #
8675#                                                                       #
8676#       Step 2.  Compute log_10(X) = log(X) * (1/log(10)).              #
8677#            2.1 Restore the user FPCR                                  #
8678#            2.2 Return ans := Y * INV_L10.                             #
8679#                                                                       #
8680#       slog10:                                                         #
8681#                                                                       #
8682#       Step 0. If X < 0, create a NaN and raise the invalid operation  #
8683#               flag. Otherwise, save FPCR in D1; set FpCR to default.  #
8684#       Notes:  Default means round-to-nearest mode, no floating-point  #
8685#               traps, and precision control = double extended.         #
8686#                                                                       #
8687#       Step 1. Call sLogN to obtain Y = log(X), the natural log of X.  #
8688#                                                                       #
8689#       Step 2.   Compute log_10(X) = log(X) * (1/log(10)).             #
8690#            2.1  Restore the user FPCR                                 #
8691#            2.2  Return ans := Y * INV_L10.                            #
8692#                                                                       #
8693#       sLog2d:                                                         #
8694#                                                                       #
8695#       Step 0. If X < 0, create a NaN and raise the invalid operation  #
8696#               flag. Otherwise, save FPCR in D1; set FpCR to default.  #
8697#       Notes:  Default means round-to-nearest mode, no floating-point  #
8698#               traps, and precision control = double extended.         #
8699#                                                                       #
8700#       Step 1. Call slognd to obtain Y = log(X), the natural log of X. #
8701#       Notes:  Even if X is denormalized, log(X) is always normalized. #
8702#                                                                       #
8703#       Step 2.   Compute log_10(X) = log(X) * (1/log(2)).              #
8704#            2.1  Restore the user FPCR                                 #
8705#            2.2  Return ans := Y * INV_L2.                             #
8706#                                                                       #
8707#       sLog2:                                                          #
8708#                                                                       #
8709#       Step 0. If X < 0, create a NaN and raise the invalid operation  #
8710#               flag. Otherwise, save FPCR in D1; set FpCR to default.  #
8711#       Notes:  Default means round-to-nearest mode, no floating-point  #
8712#               traps, and precision control = double extended.         #
8713#                                                                       #
8714#       Step 1. If X is not an integer power of two, i.e., X != 2^k,    #
8715#               go to Step 3.                                           #
8716#                                                                       #
8717#       Step 2.   Return k.                                             #
8718#            2.1  Get integer k, X = 2^k.                               #
8719#            2.2  Restore the user FPCR.                                #
8720#            2.3  Return ans := convert-to-double-extended(k).          #
8721#                                                                       #
8722#       Step 3. Call sLogN to obtain Y = log(X), the natural log of X.  #
8723#                                                                       #
8724#       Step 4.   Compute log_2(X) = log(X) * (1/log(2)).               #
8725#            4.1  Restore the user FPCR                                 #
8726#            4.2  Return ans := Y * INV_L2.                             #
8727#                                                                       #
8728#########################################################################
8729
8730INV_L10:
8731        long            0x3FFD0000,0xDE5BD8A9,0x37287195,0x00000000
8732
8733INV_L2:
8734        long            0x3FFF0000,0xB8AA3B29,0x5C17F0BC,0x00000000
8735
8736        global          slog10
8737#--entry point for Log10(X), X is normalized
8738slog10:
8739        fmov.b          &0x1,%fp0
8740        fcmp.x          %fp0,(%a0)              # if operand == 1,
8741        fbeq.l          ld_pzero                # return an EXACT zero
8742
8743        mov.l           (%a0),%d1
8744        blt.w           invalid
8745        mov.l           %d0,-(%sp)
8746        clr.l           %d0
8747        bsr             slogn                   # log(X), X normal.
8748        fmov.l          (%sp)+,%fpcr
8749        fmul.x          INV_L10(%pc),%fp0
8750        bra             t_inx2
8751
8752        global          slog10d
8753#--entry point for Log10(X), X is denormalized
8754slog10d:
8755        mov.l           (%a0),%d1
8756        blt.w           invalid
8757        mov.l           %d0,-(%sp)
8758        clr.l           %d0
8759        bsr             slognd                  # log(X), X denorm.
8760        fmov.l          (%sp)+,%fpcr
8761        fmul.x          INV_L10(%pc),%fp0
8762        bra             t_minx2
8763
8764        global          slog2
8765#--entry point for Log2(X), X is normalized
8766slog2:
8767        mov.l           (%a0),%d1
8768        blt.w           invalid
8769
8770        mov.l           8(%a0),%d1
8771        bne.b           continue                # X is not 2^k
8772
8773        mov.l           4(%a0),%d1
8774        and.l           &0x7FFFFFFF,%d1
8775        bne.b           continue
8776
8777#--X = 2^k.
8778        mov.w           (%a0),%d1
8779        and.l           &0x00007FFF,%d1
8780        sub.l           &0x3FFF,%d1
8781        beq.l           ld_pzero
8782        fmov.l          %d0,%fpcr
8783        fmov.l          %d1,%fp0
8784        bra             t_inx2
8785
8786continue:
8787        mov.l           %d0,-(%sp)
8788        clr.l           %d0
8789        bsr             slogn                   # log(X), X normal.
8790        fmov.l          (%sp)+,%fpcr
8791        fmul.x          INV_L2(%pc),%fp0
8792        bra             t_inx2
8793
8794invalid:
8795        bra             t_operr
8796
8797        global          slog2d
8798#--entry point for Log2(X), X is denormalized
8799slog2d:
8800        mov.l           (%a0),%d1
8801        blt.w           invalid
8802        mov.l           %d0,-(%sp)
8803        clr.l           %d0
8804        bsr             slognd                  # log(X), X denorm.
8805        fmov.l          (%sp)+,%fpcr
8806        fmul.x          INV_L2(%pc),%fp0
8807        bra             t_minx2
8808
8809#########################################################################
8810# stwotox():  computes 2**X for a normalized input                      #
8811# stwotoxd(): computes 2**X for a denormalized input                    #
8812# stentox():  computes 10**X for a normalized input                     #
8813# stentoxd(): computes 10**X for a denormalized input                   #
8814#                                                                       #
8815# INPUT *************************************************************** #
8816#       a0 = pointer to extended precision input                        #
8817#       d0 = round precision,mode                                       #
8818#                                                                       #
8819# OUTPUT ************************************************************** #
8820#       fp0 = 2**X or 10**X                                             #
8821#                                                                       #
8822# ACCURACY and MONOTONICITY ******************************************* #
8823#       The returned result is within 2 ulps in 64 significant bit,     #
8824#       i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
8825#       rounded to double precision. The result is provably monotonic   #
8826#       in double precision.                                            #
8827#                                                                       #
8828# ALGORITHM *********************************************************** #
8829#                                                                       #
8830#       twotox                                                          #
8831#       1. If |X| > 16480, go to ExpBig.                                #
8832#                                                                       #
8833#       2. If |X| < 2**(-70), go to ExpSm.                              #
8834#                                                                       #
8835#       3. Decompose X as X = N/64 + r where |r| <= 1/128. Furthermore  #
8836#               decompose N as                                          #
8837#                N = 64(M + M') + j,  j = 0,1,2,...,63.                 #
8838#                                                                       #
8839#       4. Overwrite r := r * log2. Then                                #
8840#               2**X = 2**(M') * 2**(M) * 2**(j/64) * exp(r).           #
8841#               Go to expr to compute that expression.                  #
8842#                                                                       #
8843#       tentox                                                          #
8844#       1. If |X| > 16480*log_10(2) (base 10 log of 2), go to ExpBig.   #
8845#                                                                       #
8846#       2. If |X| < 2**(-70), go to ExpSm.                              #
8847#                                                                       #
8848#       3. Set y := X*log_2(10)*64 (base 2 log of 10). Set              #
8849#               N := round-to-int(y). Decompose N as                    #
8850#                N = 64(M + M') + j,  j = 0,1,2,...,63.                 #
8851#                                                                       #
8852#       4. Define r as                                                  #
8853#               r := ((X - N*L1)-N*L2) * L10                            #
8854#               where L1, L2 are the leading and trailing parts of      #
8855#               log_10(2)/64 and L10 is the natural log of 10. Then     #
8856#               10**X = 2**(M') * 2**(M) * 2**(j/64) * exp(r).          #
8857#               Go to expr to compute that expression.                  #
8858#                                                                       #
8859#       expr                                                            #
8860#       1. Fetch 2**(j/64) from table as Fact1 and Fact2.               #
8861#                                                                       #
8862#       2. Overwrite Fact1 and Fact2 by                                 #
8863#               Fact1 := 2**(M) * Fact1                                 #
8864#               Fact2 := 2**(M) * Fact2                                 #
8865#               Thus Fact1 + Fact2 = 2**(M) * 2**(j/64).                #
8866#                                                                       #
8867#       3. Calculate P where 1 + P approximates exp(r):                 #
8868#               P = r + r*r*(A1+r*(A2+...+r*A5)).                       #
8869#                                                                       #
8870#       4. Let AdjFact := 2**(M'). Return                               #
8871#               AdjFact * ( Fact1 + ((Fact1*P) + Fact2) ).              #
8872#               Exit.                                                   #
8873#                                                                       #
8874#       ExpBig                                                          #
8875#       1. Generate overflow by Huge * Huge if X > 0; otherwise,        #
8876#               generate underflow by Tiny * Tiny.                      #
8877#                                                                       #
8878#       ExpSm                                                           #
8879#       1. Return 1 + X.                                                #
8880#                                                                       #
8881#########################################################################
8882
8883L2TEN64:
8884        long            0x406A934F,0x0979A371   # 64LOG10/LOG2
8885L10TWO1:
8886        long            0x3F734413,0x509F8000   # LOG2/64LOG10
8887
8888L10TWO2:
8889        long            0xBFCD0000,0xC0219DC1,0xDA994FD2,0x00000000
8890
8891LOG10:  long            0x40000000,0x935D8DDD,0xAAA8AC17,0x00000000
8892
8893LOG2:   long            0x3FFE0000,0xB17217F7,0xD1CF79AC,0x00000000
8894
8895EXPA5:  long            0x3F56C16D,0x6F7BD0B2
8896EXPA4:  long            0x3F811112,0x302C712C
8897EXPA3:  long            0x3FA55555,0x55554CC1
8898EXPA2:  long            0x3FC55555,0x55554A54
8899EXPA1:  long            0x3FE00000,0x00000000,0x00000000,0x00000000
8900
8901TEXPTBL:
8902        long            0x3FFF0000,0x80000000,0x00000000,0x3F738000
8903        long            0x3FFF0000,0x8164D1F3,0xBC030773,0x3FBEF7CA
8904        long            0x3FFF0000,0x82CD8698,0xAC2BA1D7,0x3FBDF8A9
8905        long            0x3FFF0000,0x843A28C3,0xACDE4046,0x3FBCD7C9
8906        long            0x3FFF0000,0x85AAC367,0xCC487B15,0xBFBDE8DA
8907        long            0x3FFF0000,0x871F6196,0x9E8D1010,0x3FBDE85C
8908        long            0x3FFF0000,0x88980E80,0x92DA8527,0x3FBEBBF1
8909        long            0x3FFF0000,0x8A14D575,0x496EFD9A,0x3FBB80CA
8910        long            0x3FFF0000,0x8B95C1E3,0xEA8BD6E7,0xBFBA8373
8911        long            0x3FFF0000,0x8D1ADF5B,0x7E5BA9E6,0xBFBE9670
8912        long            0x3FFF0000,0x8EA4398B,0x45CD53C0,0x3FBDB700
8913        long            0x3FFF0000,0x9031DC43,0x1466B1DC,0x3FBEEEB0
8914        long            0x3FFF0000,0x91C3D373,0xAB11C336,0x3FBBFD6D
8915        long            0x3FFF0000,0x935A2B2F,0x13E6E92C,0xBFBDB319
8916        long            0x3FFF0000,0x94F4EFA8,0xFEF70961,0x3FBDBA2B
8917        long            0x3FFF0000,0x96942D37,0x20185A00,0x3FBE91D5
8918        long            0x3FFF0000,0x9837F051,0x8DB8A96F,0x3FBE8D5A
8919        long            0x3FFF0000,0x99E04593,0x20B7FA65,0xBFBCDE7B
8920        long            0x3FFF0000,0x9B8D39B9,0xD54E5539,0xBFBEBAAF
8921        long            0x3FFF0000,0x9D3ED9A7,0x2CFFB751,0xBFBD86DA
8922        long            0x3FFF0000,0x9EF53260,0x91A111AE,0xBFBEBEDD
8923        long            0x3FFF0000,0xA0B0510F,0xB9714FC2,0x3FBCC96E
8924        long            0x3FFF0000,0xA2704303,0x0C496819,0xBFBEC90B
8925        long            0x3FFF0000,0xA43515AE,0x09E6809E,0x3FBBD1DB
8926        long            0x3FFF0000,0xA5FED6A9,0xB15138EA,0x3FBCE5EB
8927        long            0x3FFF0000,0xA7CD93B4,0xE965356A,0xBFBEC274
8928        long            0x3FFF0000,0xA9A15AB4,0xEA7C0EF8,0x3FBEA83C
8929        long            0x3FFF0000,0xAB7A39B5,0xA93ED337,0x3FBECB00
8930        long            0x3FFF0000,0xAD583EEA,0x42A14AC6,0x3FBE9301
8931        long            0x3FFF0000,0xAF3B78AD,0x690A4375,0xBFBD8367
8932        long            0x3FFF0000,0xB123F581,0xD2AC2590,0xBFBEF05F
8933        long            0x3FFF0000,0xB311C412,0xA9112489,0x3FBDFB3C
8934        long            0x3FFF0000,0xB504F333,0xF9DE6484,0x3FBEB2FB
8935        long            0x3FFF0000,0xB6FD91E3,0x28D17791,0x3FBAE2CB
8936        long            0x3FFF0000,0xB8FBAF47,0x62FB9EE9,0x3FBCDC3C
8937        long            0x3FFF0000,0xBAFF5AB2,0x133E45FB,0x3FBEE9AA
8938        long            0x3FFF0000,0xBD08A39F,0x580C36BF,0xBFBEAEFD
8939        long            0x3FFF0000,0xBF1799B6,0x7A731083,0xBFBCBF51
8940        long            0x3FFF0000,0xC12C4CCA,0x66709456,0x3FBEF88A
8941        long            0x3FFF0000,0xC346CCDA,0x24976407,0x3FBD83B2
8942        long            0x3FFF0000,0xC5672A11,0x5506DADD,0x3FBDF8AB
8943        long            0x3FFF0000,0xC78D74C8,0xABB9B15D,0xBFBDFB17
8944        long            0x3FFF0000,0xC9B9BD86,0x6E2F27A3,0xBFBEFE3C
8945        long            0x3FFF0000,0xCBEC14FE,0xF2727C5D,0xBFBBB6F8
8946        long            0x3FFF0000,0xCE248C15,0x1F8480E4,0xBFBCEE53
8947        long            0x3FFF0000,0xD06333DA,0xEF2B2595,0xBFBDA4AE
8948        long            0x3FFF0000,0xD2A81D91,0xF12AE45A,0x3FBC9124
8949        long            0x3FFF0000,0xD4F35AAB,0xCFEDFA1F,0x3FBEB243
8950        long            0x3FFF0000,0xD744FCCA,0xD69D6AF4,0x3FBDE69A
8951        long            0x3FFF0000,0xD99D15C2,0x78AFD7B6,0xBFB8BC61
8952        long            0x3FFF0000,0xDBFBB797,0xDAF23755,0x3FBDF610
8953        long            0x3FFF0000,0xDE60F482,0x5E0E9124,0xBFBD8BE1
8954        long            0x3FFF0000,0xE0CCDEEC,0x2A94E111,0x3FBACB12
8955        long            0x3FFF0000,0xE33F8972,0xBE8A5A51,0x3FBB9BFE
8956        long            0x3FFF0000,0xE5B906E7,0x7C8348A8,0x3FBCF2F4
8957        long            0x3FFF0000,0xE8396A50,0x3C4BDC68,0x3FBEF22F
8958        long            0x3FFF0000,0xEAC0C6E7,0xDD24392F,0xBFBDBF4A
8959        long            0x3FFF0000,0xED4F301E,0xD9942B84,0x3FBEC01A
8960        long            0x3FFF0000,0xEFE4B99B,0xDCDAF5CB,0x3FBE8CAC
8961        long            0x3FFF0000,0xF281773C,0x59FFB13A,0xBFBCBB3F
8962        long            0x3FFF0000,0xF5257D15,0x2486CC2C,0x3FBEF73A
8963        long            0x3FFF0000,0xF7D0DF73,0x0AD13BB9,0xBFB8B795
8964        long            0x3FFF0000,0xFA83B2DB,0x722A033A,0x3FBEF84B
8965        long            0x3FFF0000,0xFD3E0C0C,0xF486C175,0xBFBEF581
8966
8967        set             INT,L_SCR1
8968
8969        set             X,FP_SCR0
8970        set             XDCARE,X+2
8971        set             XFRAC,X+4
8972
8973        set             ADJFACT,FP_SCR0
8974
8975        set             FACT1,FP_SCR0
8976        set             FACT1HI,FACT1+4
8977        set             FACT1LOW,FACT1+8
8978
8979        set             FACT2,FP_SCR1
8980        set             FACT2HI,FACT2+4
8981        set             FACT2LOW,FACT2+8
8982
8983        global          stwotox
8984#--ENTRY POINT FOR 2**(X), HERE X IS FINITE, NON-ZERO, AND NOT NAN'S
8985stwotox:
8986        fmovm.x         (%a0),&0x80             # LOAD INPUT
8987
8988        mov.l           (%a0),%d1
8989        mov.w           4(%a0),%d1
8990        fmov.x          %fp0,X(%a6)
8991        and.l           &0x7FFFFFFF,%d1
8992
8993        cmp.l           %d1,&0x3FB98000         # |X| >= 2**(-70)?
8994        bge.b           TWOOK1
8995        bra.w           EXPBORS
8996
8997TWOOK1:
8998        cmp.l           %d1,&0x400D80C0         # |X| > 16480?
8999        ble.b           TWOMAIN
9000        bra.w           EXPBORS
9001
9002TWOMAIN:
9003#--USUAL CASE, 2^(-70) <= |X| <= 16480
9004
9005        fmov.x          %fp0,%fp1
9006        fmul.s          &0x42800000,%fp1        # 64 * X
9007        fmov.l          %fp1,INT(%a6)           # N = ROUND-TO-INT(64 X)
9008        mov.l           %d2,-(%sp)
9009        lea             TEXPTBL(%pc),%a1        # LOAD ADDRESS OF TABLE OF 2^(J/64)
9010        fmov.l          INT(%a6),%fp1           # N --> FLOATING FMT
9011        mov.l           INT(%a6),%d1
9012        mov.l           %d1,%d2
9013        and.l           &0x3F,%d1               # D0 IS J
9014        asl.l           &4,%d1                  # DISPLACEMENT FOR 2^(J/64)
9015        add.l           %d1,%a1                 # ADDRESS FOR 2^(J/64)
9016        asr.l           &6,%d2                  # d2 IS L, N = 64L + J
9017        mov.l           %d2,%d1
9018        asr.l           &1,%d1                  # D0 IS M
9019        sub.l           %d1,%d2                 # d2 IS M', N = 64(M+M') + J
9020        add.l           &0x3FFF,%d2
9021
9022#--SUMMARY: a1 IS ADDRESS FOR THE LEADING PORTION OF 2^(J/64),
9023#--D0 IS M WHERE N = 64(M+M') + J. NOTE THAT |M| <= 16140 BY DESIGN.
9024#--ADJFACT = 2^(M').
9025#--REGISTERS SAVED SO FAR ARE (IN ORDER) FPCR, D0, FP1, a1, AND FP2.
9026
9027        fmovm.x         &0x0c,-(%sp)            # save fp2/fp3
9028
9029        fmul.s          &0x3C800000,%fp1        # (1/64)*N
9030        mov.l           (%a1)+,FACT1(%a6)
9031        mov.l           (%a1)+,FACT1HI(%a6)
9032        mov.l           (%a1)+,FACT1LOW(%a6)
9033        mov.w           (%a1)+,FACT2(%a6)
9034
9035        fsub.x          %fp1,%fp0               # X - (1/64)*INT(64 X)
9036
9037        mov.w           (%a1)+,FACT2HI(%a6)
9038        clr.w           FACT2HI+2(%a6)
9039        clr.l           FACT2LOW(%a6)
9040        add.w           %d1,FACT1(%a6)
9041        fmul.x          LOG2(%pc),%fp0          # FP0 IS R
9042        add.w           %d1,FACT2(%a6)
9043
9044        bra.w           expr
9045
9046EXPBORS:
9047#--FPCR, D0 SAVED
9048        cmp.l           %d1,&0x3FFF8000
9049        bgt.b           TEXPBIG
9050
9051#--|X| IS SMALL, RETURN 1 + X
9052
9053        fmov.l          %d0,%fpcr               # restore users round prec,mode
9054        fadd.s          &0x3F800000,%fp0        # RETURN 1 + X
9055        bra             t_pinx2
9056
9057TEXPBIG:
9058#--|X| IS LARGE, GENERATE OVERFLOW IF X > 0; ELSE GENERATE UNDERFLOW
9059#--REGISTERS SAVE SO FAR ARE FPCR AND  D0
9060        mov.l           X(%a6),%d1
9061        cmp.l           %d1,&0
9062        blt.b           EXPNEG
9063
9064        bra             t_ovfl2                 # t_ovfl expects positive value
9065
9066EXPNEG:
9067        bra             t_unfl2                 # t_unfl expects positive value
9068
9069        global          stwotoxd
9070stwotoxd:
9071#--ENTRY POINT FOR 2**(X) FOR DENORMALIZED ARGUMENT
9072
9073        fmov.l          %d0,%fpcr               # set user's rounding mode/precision
9074        fmov.s          &0x3F800000,%fp0        # RETURN 1 + X
9075        mov.l           (%a0),%d1
9076        or.l            &0x00800001,%d1
9077        fadd.s          %d1,%fp0
9078        bra             t_pinx2
9079
9080        global          stentox
9081#--ENTRY POINT FOR 10**(X), HERE X IS FINITE, NON-ZERO, AND NOT NAN'S
9082stentox:
9083        fmovm.x         (%a0),&0x80             # LOAD INPUT
9084
9085        mov.l           (%a0),%d1
9086        mov.w           4(%a0),%d1
9087        fmov.x          %fp0,X(%a6)
9088        and.l           &0x7FFFFFFF,%d1
9089
9090        cmp.l           %d1,&0x3FB98000         # |X| >= 2**(-70)?
9091        bge.b           TENOK1
9092        bra.w           EXPBORS
9093
9094TENOK1:
9095        cmp.l           %d1,&0x400B9B07         # |X| <= 16480*log2/log10 ?
9096        ble.b           TENMAIN
9097        bra.w           EXPBORS
9098
9099TENMAIN:
9100#--USUAL CASE, 2^(-70) <= |X| <= 16480 LOG 2 / LOG 10
9101
9102        fmov.x          %fp0,%fp1
9103        fmul.d          L2TEN64(%pc),%fp1       # X*64*LOG10/LOG2
9104        fmov.l          %fp1,INT(%a6)           # N=INT(X*64*LOG10/LOG2)
9105        mov.l           %d2,-(%sp)
9106        lea             TEXPTBL(%pc),%a1        # LOAD ADDRESS OF TABLE OF 2^(J/64)
9107        fmov.l          INT(%a6),%fp1           # N --> FLOATING FMT
9108        mov.l           INT(%a6),%d1
9109        mov.l           %d1,%d2
9110        and.l           &0x3F,%d1               # D0 IS J
9111        asl.l           &4,%d1                  # DISPLACEMENT FOR 2^(J/64)
9112        add.l           %d1,%a1                 # ADDRESS FOR 2^(J/64)
9113        asr.l           &6,%d2                  # d2 IS L, N = 64L + J
9114        mov.l           %d2,%d1
9115        asr.l           &1,%d1                  # D0 IS M
9116        sub.l           %d1,%d2                 # d2 IS M', N = 64(M+M') + J
9117        add.l           &0x3FFF,%d2
9118
9119#--SUMMARY: a1 IS ADDRESS FOR THE LEADING PORTION OF 2^(J/64),
9120#--D0 IS M WHERE N = 64(M+M') + J. NOTE THAT |M| <= 16140 BY DESIGN.
9121#--ADJFACT = 2^(M').
9122#--REGISTERS SAVED SO FAR ARE (IN ORDER) FPCR, D0, FP1, a1, AND FP2.
9123        fmovm.x         &0x0c,-(%sp)            # save fp2/fp3
9124
9125        fmov.x          %fp1,%fp2
9126
9127        fmul.d          L10TWO1(%pc),%fp1       # N*(LOG2/64LOG10)_LEAD
9128        mov.l           (%a1)+,FACT1(%a6)
9129
9130        fmul.x          L10TWO2(%pc),%fp2       # N*(LOG2/64LOG10)_TRAIL
9131
9132        mov.l           (%a1)+,FACT1HI(%a6)
9133        mov.l           (%a1)+,FACT1LOW(%a6)
9134        fsub.x          %fp1,%fp0               # X - N L_LEAD
9135        mov.w           (%a1)+,FACT2(%a6)
9136
9137        fsub.x          %fp2,%fp0               # X - N L_TRAIL
9138
9139        mov.w           (%a1)+,FACT2HI(%a6)
9140        clr.w           FACT2HI+2(%a6)
9141        clr.l           FACT2LOW(%a6)
9142
9143        fmul.x          LOG10(%pc),%fp0         # FP0 IS R
9144        add.w           %d1,FACT1(%a6)
9145        add.w           %d1,FACT2(%a6)
9146
9147expr:
9148#--FPCR, FP2, FP3 ARE SAVED IN ORDER AS SHOWN.
9149#--ADJFACT CONTAINS 2**(M'), FACT1 + FACT2 = 2**(M) * 2**(J/64).
9150#--FP0 IS R. THE FOLLOWING CODE COMPUTES
9151#--     2**(M'+M) * 2**(J/64) * EXP(R)
9152
9153        fmov.x          %fp0,%fp1
9154        fmul.x          %fp1,%fp1               # FP1 IS S = R*R
9155
9156        fmov.d          EXPA5(%pc),%fp2         # FP2 IS A5
9157        fmov.d          EXPA4(%pc),%fp3         # FP3 IS A4
9158
9159        fmul.x          %fp1,%fp2               # FP2 IS S*A5
9160        fmul.x          %fp1,%fp3               # FP3 IS S*A4
9161
9162        fadd.d          EXPA3(%pc),%fp2         # FP2 IS A3+S*A5
9163        fadd.d          EXPA2(%pc),%fp3         # FP3 IS A2+S*A4
9164
9165        fmul.x          %fp1,%fp2               # FP2 IS S*(A3+S*A5)
9166        fmul.x          %fp1,%fp3               # FP3 IS S*(A2+S*A4)
9167
9168        fadd.d          EXPA1(%pc),%fp2         # FP2 IS A1+S*(A3+S*A5)
9169        fmul.x          %fp0,%fp3               # FP3 IS R*S*(A2+S*A4)
9170
9171        fmul.x          %fp1,%fp2               # FP2 IS S*(A1+S*(A3+S*A5))
9172        fadd.x          %fp3,%fp0               # FP0 IS R+R*S*(A2+S*A4)
9173        fadd.x          %fp2,%fp0               # FP0 IS EXP(R) - 1
9174
9175        fmovm.x         (%sp)+,&0x30            # restore fp2/fp3
9176
9177#--FINAL RECONSTRUCTION PROCESS
9178#--EXP(X) = 2^M*2^(J/64) + 2^M*2^(J/64)*(EXP(R)-1)  -  (1 OR 0)
9179
9180        fmul.x          FACT1(%a6),%fp0
9181        fadd.x          FACT2(%a6),%fp0
9182        fadd.x          FACT1(%a6),%fp0
9183
9184        fmov.l          %d0,%fpcr               # restore users round prec,mode
9185        mov.w           %d2,ADJFACT(%a6)        # INSERT EXPONENT
9186        mov.l           (%sp)+,%d2
9187        mov.l           &0x80000000,ADJFACT+4(%a6)
9188        clr.l           ADJFACT+8(%a6)
9189        mov.b           &FMUL_OP,%d1            # last inst is MUL
9190        fmul.x          ADJFACT(%a6),%fp0       # FINAL ADJUSTMENT
9191        bra             t_catch
9192
9193        global          stentoxd
9194stentoxd:
9195#--ENTRY POINT FOR 10**(X) FOR DENORMALIZED ARGUMENT
9196
9197        fmov.l          %d0,%fpcr               # set user's rounding mode/precision
9198        fmov.s          &0x3F800000,%fp0        # RETURN 1 + X
9199        mov.l           (%a0),%d1
9200        or.l            &0x00800001,%d1
9201        fadd.s          %d1,%fp0
9202        bra             t_pinx2
9203
9204#########################################################################
9205# sscale(): computes the destination operand scaled by the source       #
9206#           operand. If the absoulute value of the source operand is    #
9207#           >= 2^14, an overflow or underflow is returned.              #
9208#                                                                       #
9209# INPUT *************************************************************** #
9210#       a0  = pointer to double-extended source operand X               #
9211#       a1  = pointer to double-extended destination operand Y          #
9212#                                                                       #
9213# OUTPUT ************************************************************** #
9214#       fp0 =  scale(X,Y)                                               #
9215#                                                                       #
9216#########################################################################
9217
9218set     SIGN,           L_SCR1
9219
9220        global          sscale
9221sscale:
9222        mov.l           %d0,-(%sp)              # store off ctrl bits for now
9223
9224        mov.w           DST_EX(%a1),%d1         # get dst exponent
9225        smi.b           SIGN(%a6)               # use SIGN to hold dst sign
9226        andi.l          &0x00007fff,%d1         # strip sign from dst exp
9227
9228        mov.w           SRC_EX(%a0),%d0         # check src bounds
9229        andi.w          &0x7fff,%d0             # clr src sign bit
9230        cmpi.w          %d0,&0x3fff             # is src ~ ZERO?
9231        blt.w           src_small               # yes
9232        cmpi.w          %d0,&0x400c             # no; is src too big?
9233        bgt.w           src_out                 # yes
9234
9235#
9236# Source is within 2^14 range.
9237#
9238src_ok:
9239        fintrz.x        SRC(%a0),%fp0           # calc int of src
9240        fmov.l          %fp0,%d0                # int src to d0
9241# don't want any accrued bits from the fintrz showing up later since
9242# we may need to read the fpsr for the last fp op in t_catch2().
9243        fmov.l          &0x0,%fpsr
9244
9245        tst.b           DST_HI(%a1)             # is dst denormalized?
9246        bmi.b           sok_norm
9247
9248# the dst is a DENORM. normalize the DENORM and add the adjustment to
9249# the src value. then, jump to the norm part of the routine.
9250sok_dnrm:
9251        mov.l           %d0,-(%sp)              # save src for now
9252
9253        mov.w           DST_EX(%a1),FP_SCR0_EX(%a6) # make a copy
9254        mov.l           DST_HI(%a1),FP_SCR0_HI(%a6)
9255        mov.l           DST_LO(%a1),FP_SCR0_LO(%a6)
9256
9257        lea             FP_SCR0(%a6),%a0        # pass ptr to DENORM
9258        bsr.l           norm                    # normalize the DENORM
9259        neg.l           %d0
9260        add.l           (%sp)+,%d0              # add adjustment to src
9261
9262        fmovm.x         FP_SCR0(%a6),&0x80      # load normalized DENORM
9263
9264        cmpi.w          %d0,&-0x3fff            # is the shft amt really low?
9265        bge.b           sok_norm2               # thank goodness no
9266
9267# the multiply factor that we're trying to create should be a denorm
9268# for the multiply to work. therefore, we're going to actually do a
9269# multiply with a denorm which will cause an unimplemented data type
9270# exception to be put into the machine which will be caught and corrected
9271# later. we don't do this with the DENORMs above because this method
9272# is slower. but, don't fret, I don't see it being used much either.
9273        fmov.l          (%sp)+,%fpcr            # restore user fpcr
9274        mov.l           &0x80000000,%d1         # load normalized mantissa
9275        subi.l          &-0x3fff,%d0            # how many should we shift?
9276        neg.l           %d0                     # make it positive
9277        cmpi.b          %d0,&0x20               # is it > 32?
9278        bge.b           sok_dnrm_32             # yes
9279        lsr.l           %d0,%d1                 # no; bit stays in upper lw
9280        clr.l           -(%sp)                  # insert zero low mantissa
9281        mov.l           %d1,-(%sp)              # insert new high mantissa
9282        clr.l           -(%sp)                  # make zero exponent
9283        bra.b           sok_norm_cont
9284sok_dnrm_32:
9285        subi.b          &0x20,%d0               # get shift count
9286        lsr.l           %d0,%d1                 # make low mantissa longword
9287        mov.l           %d1,-(%sp)              # insert new low mantissa
9288        clr.l           -(%sp)                  # insert zero high mantissa
9289        clr.l           -(%sp)                  # make zero exponent
9290        bra.b           sok_norm_cont
9291
9292# the src will force the dst to a DENORM value or worse. so, let's
9293# create an fp multiply that will create the result.
9294sok_norm:
9295        fmovm.x         DST(%a1),&0x80          # load fp0 with normalized src
9296sok_norm2:
9297        fmov.l          (%sp)+,%fpcr            # restore user fpcr
9298
9299        addi.w          &0x3fff,%d0             # turn src amt into exp value
9300        swap            %d0                     # put exponent in high word
9301        clr.l           -(%sp)                  # insert new exponent
9302        mov.l           &0x80000000,-(%sp)      # insert new high mantissa
9303        mov.l           %d0,-(%sp)              # insert new lo mantissa
9304
9305sok_norm_cont:
9306        fmov.l          %fpcr,%d0               # d0 needs fpcr for t_catch2
9307        mov.b           &FMUL_OP,%d1            # last inst is MUL
9308        fmul.x          (%sp)+,%fp0             # do the multiply
9309        bra             t_catch2                # catch any exceptions
9310
9311#
9312# Source is outside of 2^14 range.  Test the sign and branch
9313# to the appropriate exception handler.
9314#
9315src_out:
9316        mov.l           (%sp)+,%d0              # restore ctrl bits
9317        exg             %a0,%a1                 # swap src,dst ptrs
9318        tst.b           SRC_EX(%a1)             # is src negative?
9319        bmi             t_unfl                  # yes; underflow
9320        bra             t_ovfl_sc               # no; overflow
9321
9322#
9323# The source input is below 1, so we check for denormalized numbers
9324# and set unfl.
9325#
9326src_small:
9327        tst.b           DST_HI(%a1)             # is dst denormalized?
9328        bpl.b           ssmall_done             # yes
9329
9330        mov.l           (%sp)+,%d0
9331        fmov.l          %d0,%fpcr               # no; load control bits
9332        mov.b           &FMOV_OP,%d1            # last inst is MOVE
9333        fmov.x          DST(%a1),%fp0           # simply return dest
9334        bra             t_catch2
9335ssmall_done:
9336        mov.l           (%sp)+,%d0              # load control bits into d1
9337        mov.l           %a1,%a0                 # pass ptr to dst
9338        bra             t_resdnrm
9339
9340#########################################################################
9341# smod(): computes the fp MOD of the input values X,Y.                  #
9342# srem(): computes the fp (IEEE) REM of the input values X,Y.           #
9343#                                                                       #
9344# INPUT *************************************************************** #
9345#       a0 = pointer to extended precision input X                      #
9346#       a1 = pointer to extended precision input Y                      #
9347#       d0 = round precision,mode                                       #
9348#                                                                       #
9349#       The input operands X and Y can be either normalized or          #
9350#       denormalized.                                                   #
9351#                                                                       #
9352# OUTPUT ************************************************************** #
9353#      fp0 = FREM(X,Y) or FMOD(X,Y)                                     #
9354#                                                                       #
9355# ALGORITHM *********************************************************** #
9356#                                                                       #
9357#       Step 1.  Save and strip signs of X and Y: signX := sign(X),     #
9358#                signY := sign(Y), X := |X|, Y := |Y|,                  #
9359#                signQ := signX EOR signY. Record whether MOD or REM    #
9360#                is requested.                                          #
9361#                                                                       #
9362#       Step 2.  Set L := expo(X)-expo(Y), k := 0, Q := 0.              #
9363#                If (L < 0) then                                        #
9364#                   R := X, go to Step 4.                               #
9365#                else                                                   #
9366#                   R := 2^(-L)X, j := L.                               #
9367#                endif                                                  #
9368#                                                                       #
9369#       Step 3.  Perform MOD(X,Y)                                       #
9370#            3.1 If R = Y, go to Step 9.                                #
9371#            3.2 If R > Y, then { R := R - Y, Q := Q + 1}               #
9372#            3.3 If j = 0, go to Step 4.                                #
9373#            3.4 k := k + 1, j := j - 1, Q := 2Q, R := 2R. Go to        #
9374#                Step 3.1.                                              #
9375#                                                                       #
9376#       Step 4.  At this point, R = X - QY = MOD(X,Y). Set              #
9377#                Last_Subtract := false (used in Step 7 below). If      #
9378#                MOD is requested, go to Step 6.                        #
9379#                                                                       #
9380#       Step 5.  R = MOD(X,Y), but REM(X,Y) is requested.               #
9381#            5.1 If R < Y/2, then R = MOD(X,Y) = REM(X,Y). Go to        #
9382#                Step 6.                                                #
9383#            5.2 If R > Y/2, then { set Last_Subtract := true,          #
9384#                Q := Q + 1, Y := signY*Y }. Go to Step 6.              #
9385#            5.3 This is the tricky case of R = Y/2. If Q is odd,       #
9386#                then { Q := Q + 1, signX := -signX }.                  #
9387#                                                                       #
9388#       Step 6.  R := signX*R.                                          #
9389#                                                                       #
9390#       Step 7.  If Last_Subtract = true, R := R - Y.                   #
9391#                                                                       #
9392#       Step 8.  Return signQ, last 7 bits of Q, and R as required.     #
9393#                                                                       #
9394#       Step 9.  At this point, R = 2^(-j)*X - Q Y = Y. Thus,           #
9395#                X = 2^(j)*(Q+1)Y. set Q := 2^(j)*(Q+1),                #
9396#                R := 0. Return signQ, last 7 bits of Q, and R.         #
9397#                                                                       #
9398#########################################################################
9399
9400        set             Mod_Flag,L_SCR3
9401        set             Sc_Flag,L_SCR3+1
9402
9403        set             SignY,L_SCR2
9404        set             SignX,L_SCR2+2
9405        set             SignQ,L_SCR3+2
9406
9407        set             Y,FP_SCR0
9408        set             Y_Hi,Y+4
9409        set             Y_Lo,Y+8
9410
9411        set             R,FP_SCR1
9412        set             R_Hi,R+4
9413        set             R_Lo,R+8
9414
9415Scale:
9416        long            0x00010000,0x80000000,0x00000000,0x00000000
9417
9418        global          smod
9419smod:
9420        clr.b           FPSR_QBYTE(%a6)
9421        mov.l           %d0,-(%sp)              # save ctrl bits
9422        clr.b           Mod_Flag(%a6)
9423        bra.b           Mod_Rem
9424
9425        global          srem
9426srem:
9427        clr.b           FPSR_QBYTE(%a6)
9428        mov.l           %d0,-(%sp)              # save ctrl bits
9429        mov.b           &0x1,Mod_Flag(%a6)
9430
9431Mod_Rem:
9432#..Save sign of X and Y
9433        movm.l          &0x3f00,-(%sp)          # save data registers
9434        mov.w           SRC_EX(%a0),%d3
9435        mov.w           %d3,SignY(%a6)
9436        and.l           &0x00007FFF,%d3         # Y := |Y|
9437
9438#
9439        mov.l           SRC_HI(%a0),%d4
9440        mov.l           SRC_LO(%a0),%d5         # (D3,D4,D5) is |Y|
9441
9442        tst.l           %d3
9443        bne.b           Y_Normal
9444
9445        mov.l           &0x00003FFE,%d3         # $3FFD + 1
9446        tst.l           %d4
9447        bne.b           HiY_not0
9448
9449HiY_0:
9450        mov.l           %d5,%d4
9451        clr.l           %d5
9452        sub.l           &32,%d3
9453        clr.l           %d6
9454        bfffo           %d4{&0:&32},%d6
9455        lsl.l           %d6,%d4
9456        sub.l           %d6,%d3                 # (D3,D4,D5) is normalized
9457#                                               ...with bias $7FFD
9458        bra.b           Chk_X
9459
9460HiY_not0:
9461        clr.l           %d6
9462        bfffo           %d4{&0:&32},%d6
9463        sub.l           %d6,%d3
9464        lsl.l           %d6,%d4
9465        mov.l           %d5,%d7                 # a copy of D5
9466        lsl.l           %d6,%d5
9467        neg.l           %d6
9468        add.l           &32,%d6
9469        lsr.l           %d6,%d7
9470        or.l            %d7,%d4                 # (D3,D4,D5) normalized
9471#                                       ...with bias $7FFD
9472        bra.b           Chk_X
9473
9474Y_Normal:
9475        add.l           &0x00003FFE,%d3         # (D3,D4,D5) normalized
9476#                                       ...with bias $7FFD
9477
9478Chk_X:
9479        mov.w           DST_EX(%a1),%d0
9480        mov.w           %d0,SignX(%a6)
9481        mov.w           SignY(%a6),%d1
9482        eor.l           %d0,%d1
9483        and.l           &0x00008000,%d1
9484        mov.w           %d1,SignQ(%a6)          # sign(Q) obtained
9485        and.l           &0x00007FFF,%d0
9486        mov.l           DST_HI(%a1),%d1
9487        mov.l           DST_LO(%a1),%d2         # (D0,D1,D2) is |X|
9488        tst.l           %d0
9489        bne.b           X_Normal
9490        mov.l           &0x00003FFE,%d0
9491        tst.l           %d1
9492        bne.b           HiX_not0
9493
9494HiX_0:
9495        mov.l           %d2,%d1
9496        clr.l           %d2
9497        sub.l           &32,%d0
9498        clr.l           %d6
9499        bfffo           %d1{&0:&32},%d6
9500        lsl.l           %d6,%d1
9501        sub.l           %d6,%d0                 # (D0,D1,D2) is normalized
9502#                                       ...with bias $7FFD
9503        bra.b           Init
9504
9505HiX_not0:
9506        clr.l           %d6
9507        bfffo           %d1{&0:&32},%d6
9508        sub.l           %d6,%d0
9509        lsl.l           %d6,%d1
9510        mov.l           %d2,%d7                 # a copy of D2
9511        lsl.l           %d6,%d2
9512        neg.l           %d6
9513        add.l           &32,%d6
9514        lsr.l           %d6,%d7
9515        or.l            %d7,%d1                 # (D0,D1,D2) normalized
9516#                                       ...with bias $7FFD
9517        bra.b           Init
9518
9519X_Normal:
9520        add.l           &0x00003FFE,%d0         # (D0,D1,D2) normalized
9521#                                       ...with bias $7FFD
9522
9523Init:
9524#
9525        mov.l           %d3,L_SCR1(%a6)         # save biased exp(Y)
9526        mov.l           %d0,-(%sp)              # save biased exp(X)
9527        sub.l           %d3,%d0                 # L := expo(X)-expo(Y)
9528
9529        clr.l           %d6                     # D6 := carry <- 0
9530        clr.l           %d3                     # D3 is Q
9531        mov.l           &0,%a1                  # A1 is k; j+k=L, Q=0
9532
9533#..(Carry,D1,D2) is R
9534        tst.l           %d0
9535        bge.b           Mod_Loop_pre
9536
9537#..expo(X) < expo(Y). Thus X = mod(X,Y)
9538#
9539        mov.l           (%sp)+,%d0              # restore d0
9540        bra.w           Get_Mod
9541
9542Mod_Loop_pre:
9543        addq.l          &0x4,%sp                # erase exp(X)
9544#..At this point  R = 2^(-L)X; Q = 0; k = 0; and  k+j = L
9545Mod_Loop:
9546        tst.l           %d6                     # test carry bit
9547        bgt.b           R_GT_Y
9548
9549#..At this point carry = 0, R = (D1,D2), Y = (D4,D5)
9550        cmp.l           %d1,%d4                 # compare hi(R) and hi(Y)
9551        bne.b           R_NE_Y
9552        cmp.l           %d2,%d5                 # compare lo(R) and lo(Y)
9553        bne.b           R_NE_Y
9554
9555#..At this point, R = Y
9556        bra.w           Rem_is_0
9557
9558R_NE_Y:
9559#..use the borrow of the previous compare
9560        bcs.b           R_LT_Y                  # borrow is set iff R < Y
9561
9562R_GT_Y:
9563#..If Carry is set, then Y < (Carry,D1,D2) < 2Y. Otherwise, Carry = 0
9564#..and Y < (D1,D2) < 2Y. Either way, perform R - Y
9565        sub.l           %d5,%d2                 # lo(R) - lo(Y)
9566        subx.l          %d4,%d1                 # hi(R) - hi(Y)
9567        clr.l           %d6                     # clear carry
9568        addq.l          &1,%d3                  # Q := Q + 1
9569
9570R_LT_Y:
9571#..At this point, Carry=0, R < Y. R = 2^(k-L)X - QY; k+j = L; j >= 0.
9572        tst.l           %d0                     # see if j = 0.
9573        beq.b           PostLoop
9574
9575        add.l           %d3,%d3                 # Q := 2Q
9576        add.l           %d2,%d2                 # lo(R) = 2lo(R)
9577        roxl.l          &1,%d1                  # hi(R) = 2hi(R) + carry
9578        scs             %d6                     # set Carry if 2(R) overflows
9579        addq.l          &1,%a1                  # k := k+1
9580        subq.l          &1,%d0                  # j := j - 1
9581#..At this point, R=(Carry,D1,D2) = 2^(k-L)X - QY, j+k=L, j >= 0, R < 2Y.
9582
9583        bra.b           Mod_Loop
9584
9585PostLoop:
9586#..k = L, j = 0, Carry = 0, R = (D1,D2) = X - QY, R < Y.
9587
9588#..normalize R.
9589        mov.l           L_SCR1(%a6),%d0         # new biased expo of R
9590        tst.l           %d1
9591        bne.b           HiR_not0
9592
9593HiR_0:
9594        mov.l           %d2,%d1
9595        clr.l           %d2
9596        sub.l           &32,%d0
9597        clr.l           %d6
9598        bfffo           %d1{&0:&32},%d6
9599        lsl.l           %d6,%d1
9600        sub.l           %d6,%d0                 # (D0,D1,D2) is normalized
9601#                                       ...with bias $7FFD
9602        bra.b           Get_Mod
9603
9604HiR_not0:
9605        clr.l           %d6
9606        bfffo           %d1{&0:&32},%d6
9607        bmi.b           Get_Mod                 # already normalized
9608        sub.l           %d6,%d0
9609        lsl.l           %d6,%d1
9610        mov.l           %d2,%d7                 # a copy of D2
9611        lsl.l           %d6,%d2
9612        neg.l           %d6
9613        add.l           &32,%d6
9614        lsr.l           %d6,%d7
9615        or.l            %d7,%d1                 # (D0,D1,D2) normalized
9616
9617#
9618Get_Mod:
9619        cmp.l           %d0,&0x000041FE
9620        bge.b           No_Scale
9621Do_Scale:
9622        mov.w           %d0,R(%a6)
9623        mov.l           %d1,R_Hi(%a6)
9624        mov.l           %d2,R_Lo(%a6)
9625        mov.l           L_SCR1(%a6),%d6
9626        mov.w           %d6,Y(%a6)
9627        mov.l           %d4,Y_Hi(%a6)
9628        mov.l           %d5,Y_Lo(%a6)
9629        fmov.x          R(%a6),%fp0             # no exception
9630        mov.b           &1,Sc_Flag(%a6)
9631        bra.b           ModOrRem
9632No_Scale:
9633        mov.l           %d1,R_Hi(%a6)
9634        mov.l           %d2,R_Lo(%a6)
9635        sub.l           &0x3FFE,%d0
9636        mov.w           %d0,R(%a6)
9637        mov.l           L_SCR1(%a6),%d6
9638        sub.l           &0x3FFE,%d6
9639        mov.l           %d6,L_SCR1(%a6)
9640        fmov.x          R(%a6),%fp0
9641        mov.w           %d6,Y(%a6)
9642        mov.l           %d4,Y_Hi(%a6)
9643        mov.l           %d5,Y_Lo(%a6)
9644        clr.b           Sc_Flag(%a6)
9645
9646#
9647ModOrRem:
9648        tst.b           Mod_Flag(%a6)
9649        beq.b           Fix_Sign
9650
9651        mov.l           L_SCR1(%a6),%d6         # new biased expo(Y)
9652        subq.l          &1,%d6                  # biased expo(Y/2)
9653        cmp.l           %d0,%d6
9654        blt.b           Fix_Sign
9655        bgt.b           Last_Sub
9656
9657        cmp.l           %d1,%d4
9658        bne.b           Not_EQ
9659        cmp.l           %d2,%d5
9660        bne.b           Not_EQ
9661        bra.w           Tie_Case
9662
9663Not_EQ:
9664        bcs.b           Fix_Sign
9665
9666Last_Sub:
9667#
9668        fsub.x          Y(%a6),%fp0             # no exceptions
9669        addq.l          &1,%d3                  # Q := Q + 1
9670
9671#
9672Fix_Sign:
9673#..Get sign of X
9674        mov.w           SignX(%a6),%d6
9675        bge.b           Get_Q
9676        fneg.x          %fp0
9677
9678#..Get Q
9679#
9680Get_Q:
9681        clr.l           %d6
9682        mov.w           SignQ(%a6),%d6          # D6 is sign(Q)
9683        mov.l           &8,%d7
9684        lsr.l           %d7,%d6
9685        and.l           &0x0000007F,%d3         # 7 bits of Q
9686        or.l            %d6,%d3                 # sign and bits of Q
9687#       swap            %d3
9688#       fmov.l          %fpsr,%d6
9689#       and.l           &0xFF00FFFF,%d6
9690#       or.l            %d3,%d6
9691#       fmov.l          %d6,%fpsr               # put Q in fpsr
9692        mov.b           %d3,FPSR_QBYTE(%a6)     # put Q in fpsr
9693
9694#
9695Restore:
9696        movm.l          (%sp)+,&0xfc            #  {%d2-%d7}
9697        mov.l           (%sp)+,%d0
9698        fmov.l          %d0,%fpcr
9699        tst.b           Sc_Flag(%a6)
9700        beq.b           Finish
9701        mov.b           &FMUL_OP,%d1            # last inst is MUL
9702        fmul.x          Scale(%pc),%fp0         # may cause underflow
9703        bra             t_catch2
9704# the '040 package did this apparently to see if the dst operand for the
9705# preceding fmul was a denorm. but, it better not have been since the
9706# algorithm just got done playing with fp0 and expected no exceptions
9707# as a result. trust me...
9708#       bra             t_avoid_unsupp          # check for denorm as a
9709#                                               ;result of the scaling
9710
9711Finish:
9712        mov.b           &FMOV_OP,%d1            # last inst is MOVE
9713        fmov.x          %fp0,%fp0               # capture exceptions & round
9714        bra             t_catch2
9715
9716Rem_is_0:
9717#..R = 2^(-j)X - Q Y = Y, thus R = 0 and quotient = 2^j (Q+1)
9718        addq.l          &1,%d3
9719        cmp.l           %d0,&8                  # D0 is j
9720        bge.b           Q_Big
9721
9722        lsl.l           %d0,%d3
9723        bra.b           Set_R_0
9724
9725Q_Big:
9726        clr.l           %d3
9727
9728Set_R_0:
9729        fmov.s          &0x00000000,%fp0
9730        clr.b           Sc_Flag(%a6)
9731        bra.w           Fix_Sign
9732
9733Tie_Case:
9734#..Check parity of Q
9735        mov.l           %d3,%d6
9736        and.l           &0x00000001,%d6
9737        tst.l           %d6
9738        beq.w           Fix_Sign                # Q is even
9739
9740#..Q is odd, Q := Q + 1, signX := -signX
9741        addq.l          &1,%d3
9742        mov.w           SignX(%a6),%d6
9743        eor.l           &0x00008000,%d6
9744        mov.w           %d6,SignX(%a6)
9745        bra.w           Fix_Sign
9746
9747#########################################################################
9748# XDEF **************************************************************** #
9749#       tag(): return the optype of the input ext fp number             #
9750#                                                                       #
9751#       This routine is used by the 060FPLSP.                           #
9752#                                                                       #
9753# XREF **************************************************************** #
9754#       None                                                            #
9755#                                                                       #
9756# INPUT *************************************************************** #
9757#       a0 = pointer to extended precision operand                      #
9758#                                                                       #
9759# OUTPUT ************************************************************** #
9760#       d0 = value of type tag                                          #
9761#               one of: NORM, INF, QNAN, SNAN, DENORM, ZERO             #
9762#                                                                       #
9763# ALGORITHM *********************************************************** #
9764#       Simply test the exponent, j-bit, and mantissa values to         #
9765# determine the type of operand.                                        #
9766#       If it's an unnormalized zero, alter the operand and force it    #
9767# to be a normal zero.                                                  #
9768#                                                                       #
9769#########################################################################
9770
9771        global          tag
9772tag:
9773        mov.w           FTEMP_EX(%a0), %d0      # extract exponent
9774        andi.w          &0x7fff, %d0            # strip off sign
9775        cmpi.w          %d0, &0x7fff            # is (EXP == MAX)?
9776        beq.b           inf_or_nan_x
9777not_inf_or_nan_x:
9778        btst            &0x7,FTEMP_HI(%a0)
9779        beq.b           not_norm_x
9780is_norm_x:
9781        mov.b           &NORM, %d0
9782        rts
9783not_norm_x:
9784        tst.w           %d0                     # is exponent = 0?
9785        bne.b           is_unnorm_x
9786not_unnorm_x:
9787        tst.l           FTEMP_HI(%a0)
9788        bne.b           is_denorm_x
9789        tst.l           FTEMP_LO(%a0)
9790        bne.b           is_denorm_x
9791is_zero_x:
9792        mov.b           &ZERO, %d0
9793        rts
9794is_denorm_x:
9795        mov.b           &DENORM, %d0
9796        rts
9797is_unnorm_x:
9798        bsr.l           unnorm_fix              # convert to norm,denorm,or zero
9799        rts
9800is_unnorm_reg_x:
9801        mov.b           &UNNORM, %d0
9802        rts
9803inf_or_nan_x:
9804        tst.l           FTEMP_LO(%a0)
9805        bne.b           is_nan_x
9806        mov.l           FTEMP_HI(%a0), %d0
9807        and.l           &0x7fffffff, %d0        # msb is a don't care!
9808        bne.b           is_nan_x
9809is_inf_x:
9810        mov.b           &INF, %d0
9811        rts
9812is_nan_x:
9813        mov.b           &QNAN, %d0
9814        rts
9815
9816#############################################################
9817
9818qnan:   long            0x7fff0000, 0xffffffff, 0xffffffff
9819
9820#########################################################################
9821# XDEF **************************************************************** #
9822#       t_dz(): Handle 060FPLSP dz exception for "flogn" emulation.     #
9823#       t_dz2(): Handle 060FPLSP dz exception for "fatanh" emulation.   #
9824#                                                                       #
9825#       These rouitnes are used by the 060FPLSP package.                #
9826#                                                                       #
9827# XREF **************************************************************** #
9828#       None                                                            #
9829#                                                                       #
9830# INPUT *************************************************************** #
9831#       a0 = pointer to extended precision source operand.              #
9832#                                                                       #
9833# OUTPUT ************************************************************** #
9834#       fp0 = default DZ result.                                        #
9835#                                                                       #
9836# ALGORITHM *********************************************************** #
9837#       Transcendental emulation for the 060FPLSP has detected that     #
9838# a DZ exception should occur for the instruction. If DZ is disabled,   #
9839# return the default result.                                            #
9840#       If DZ is enabled, the dst operand should be returned unscathed  #
9841# in fp0 while fp1 is used to create a DZ exception so that the         #
9842# operating system can log that such an event occurred.                 #
9843#                                                                       #
9844#########################################################################
9845
9846        global          t_dz
9847t_dz:
9848        tst.b           SRC_EX(%a0)             # check sign for neg or pos
9849        bpl.b           dz_pinf                 # branch if pos sign
9850
9851        global          t_dz2
9852t_dz2:
9853        ori.l           &dzinf_mask+neg_mask,USER_FPSR(%a6) # set N/I/DZ/ADZ
9854
9855        btst            &dz_bit,FPCR_ENABLE(%a6)
9856        bne.b           dz_minf_ena
9857
9858# dz is disabled. return a -INF.
9859        fmov.s          &0xff800000,%fp0        # return -INF
9860        rts
9861
9862# dz is enabled. create a dz exception so the user can record it
9863# but use fp1 instead. return the dst operand unscathed in fp0.
9864dz_minf_ena:
9865        fmovm.x         EXC_FP0(%a6),&0x80      # return fp0 unscathed
9866        fmov.l          USER_FPCR(%a6),%fpcr
9867        fmov.s          &0xbf800000,%fp1        # load -1
9868        fdiv.s          &0x00000000,%fp1        # -1 / 0
9869        rts
9870
9871dz_pinf:
9872        ori.l           &dzinf_mask,USER_FPSR(%a6) # set I/DZ/ADZ
9873
9874        btst            &dz_bit,FPCR_ENABLE(%a6)
9875        bne.b           dz_pinf_ena
9876
9877# dz is disabled. return a +INF.
9878        fmov.s          &0x7f800000,%fp0        # return +INF
9879        rts
9880
9881# dz is enabled. create a dz exception so the user can record it
9882# but use fp1 instead. return the dst operand unscathed in fp0.
9883dz_pinf_ena:
9884        fmovm.x         EXC_FP0(%a6),&0x80      # return fp0 unscathed
9885        fmov.l          USER_FPCR(%a6),%fpcr
9886        fmov.s          &0x3f800000,%fp1        # load +1
9887        fdiv.s          &0x00000000,%fp1        # +1 / 0
9888        rts
9889
9890#########################################################################
9891# XDEF **************************************************************** #
9892#       t_operr(): Handle 060FPLSP OPERR exception during emulation.    #
9893#                                                                       #
9894#       This routine is used by the 060FPLSP package.                   #
9895#                                                                       #
9896# XREF **************************************************************** #
9897#       None.                                                           #
9898#                                                                       #
9899# INPUT *************************************************************** #
9900#       fp1 = source operand                                            #
9901#                                                                       #
9902# OUTPUT ************************************************************** #
9903#       fp0 = default result                                            #
9904#       fp1 = unchanged                                                 #
9905#                                                                       #
9906# ALGORITHM *********************************************************** #
9907#       An operand error should occur as the result of transcendental   #
9908# emulation in the 060FPLSP. If OPERR is disabled, just return a NAN    #
9909# in fp0. If OPERR is enabled, return the dst operand unscathed in fp0  #
9910# and the source operand in fp1. Use fp2 to create an OPERR exception   #
9911# so that the operating system can log the event.                       #
9912#                                                                       #
9913#########################################################################
9914
9915        global          t_operr
9916t_operr:
9917        ori.l           &opnan_mask,USER_FPSR(%a6) # set NAN/OPERR/AIOP
9918
9919        btst            &operr_bit,FPCR_ENABLE(%a6)
9920        bne.b           operr_ena
9921
9922# operr is disabled. return a QNAN in fp0
9923        fmovm.x         qnan(%pc),&0x80         # return QNAN
9924        rts
9925
9926# operr is enabled. create an operr exception so the user can record it
9927# but use fp2 instead. return the dst operand unscathed in fp0.
9928operr_ena:
9929        fmovm.x         EXC_FP0(%a6),&0x80      # return fp0 unscathed
9930        fmov.l          USER_FPCR(%a6),%fpcr
9931        fmovm.x         &0x04,-(%sp)            # save fp2
9932        fmov.s          &0x7f800000,%fp2        # load +INF
9933        fmul.s          &0x00000000,%fp2        # +INF x 0
9934        fmovm.x         (%sp)+,&0x20            # restore fp2
9935        rts
9936
9937pls_huge:
9938        long            0x7ffe0000,0xffffffff,0xffffffff
9939mns_huge:
9940        long            0xfffe0000,0xffffffff,0xffffffff
9941pls_tiny:
9942        long            0x00000000,0x80000000,0x00000000
9943mns_tiny:
9944        long            0x80000000,0x80000000,0x00000000
9945
9946#########################################################################
9947# XDEF **************************************************************** #
9948#       t_unfl(): Handle 060FPLSP underflow exception during emulation. #
9949#       t_unfl2(): Handle 060FPLSP underflow exception during           #
9950#                  emulation. result always positive.                   #
9951#                                                                       #
9952#       This routine is used by the 060FPLSP package.                   #
9953#                                                                       #
9954# XREF **************************************************************** #
9955#       None.                                                           #
9956#                                                                       #
9957# INPUT *************************************************************** #
9958#       a0 = pointer to extended precision source operand               #
9959#                                                                       #
9960# OUTPUT ************************************************************** #
9961#       fp0 = default underflow result                                  #
9962#                                                                       #
9963# ALGORITHM *********************************************************** #
9964#       An underflow should occur as the result of transcendental       #
9965# emulation in the 060FPLSP. Create an underflow by using "fmul"        #
9966# and two very small numbers of appropriate sign so the operating       #
9967# system can log the event.                                             #
9968#                                                                       #
9969#########################################################################
9970
9971        global          t_unfl
9972t_unfl:
9973        tst.b           SRC_EX(%a0)
9974        bpl.b           unf_pos
9975
9976        global          t_unfl2
9977t_unfl2:
9978        ori.l           &unfinx_mask+neg_mask,USER_FPSR(%a6) # set N/UNFL/INEX2/AUNFL/AINEX
9979
9980        fmov.l          USER_FPCR(%a6),%fpcr
9981        fmovm.x         mns_tiny(%pc),&0x80
9982        fmul.x          pls_tiny(%pc),%fp0
9983
9984        fmov.l          %fpsr,%d0
9985        rol.l           &0x8,%d0
9986        mov.b           %d0,FPSR_CC(%a6)
9987        rts
9988unf_pos:
9989        ori.w           &unfinx_mask,FPSR_EXCEPT(%a6) # set UNFL/INEX2/AUNFL/AINEX
9990
9991        fmov.l          USER_FPCR(%a6),%fpcr
9992        fmovm.x         pls_tiny(%pc),&0x80
9993        fmul.x          %fp0,%fp0
9994
9995        fmov.l          %fpsr,%d0
9996        rol.l           &0x8,%d0
9997        mov.b           %d0,FPSR_CC(%a6)
9998        rts
9999
10000#########################################################################
10001# XDEF **************************************************************** #
10002#       t_ovfl(): Handle 060FPLSP overflow exception during emulation.  #
10003#                 (monadic)                                             #
10004#       t_ovfl2(): Handle 060FPLSP overflow exception during            #
10005#                  emulation. result always positive. (dyadic)          #
10006#       t_ovfl_sc(): Handle 060FPLSP overflow exception during          #
10007#                    emulation for "fscale".                            #
10008#                                                                       #
10009#       This routine is used by the 060FPLSP package.                   #
10010#                                                                       #
10011# XREF **************************************************************** #
10012#       None.                                                           #
10013#                                                                       #
10014# INPUT *************************************************************** #
10015#       a0 = pointer to extended precision source operand               #
10016#                                                                       #
10017# OUTPUT ************************************************************** #
10018#       fp0 = default underflow result                                  #
10019#                                                                       #
10020# ALGORITHM *********************************************************** #
10021#       An overflow should occur as the result of transcendental        #
10022# emulation in the 060FPLSP. Create an overflow by using "fmul"         #
10023# and two very lareg numbers of appropriate sign so the operating       #
10024# system can log the event.                                             #
10025#       For t_ovfl_sc() we take special care not to lose the INEX2 bit. #
10026#                                                                       #
10027#########################################################################
10028
10029        global          t_ovfl_sc
10030t_ovfl_sc:
10031        ori.l           &ovfl_inx_mask,USER_FPSR(%a6) # set OVFL/AOVFL/AINEX
10032
10033        mov.b           %d0,%d1                 # fetch rnd prec,mode
10034        andi.b          &0xc0,%d1               # extract prec
10035        beq.w           ovfl_work
10036
10037# dst op is a DENORM. we have to normalize the mantissa to see if the
10038# result would be inexact for the given precision. make a copy of the
10039# dst so we don't screw up the version passed to us.
10040        mov.w           LOCAL_EX(%a0),FP_SCR0_EX(%a6)
10041        mov.l           LOCAL_HI(%a0),FP_SCR0_HI(%a6)
10042        mov.l           LOCAL_LO(%a0),FP_SCR0_LO(%a6)
10043        lea             FP_SCR0(%a6),%a0        # pass ptr to FP_SCR0
10044        movm.l          &0xc080,-(%sp)          # save d0-d1/a0
10045        bsr.l           norm                    # normalize mantissa
10046        movm.l          (%sp)+,&0x0103          # restore d0-d1/a0
10047
10048        cmpi.b          %d1,&0x40               # is precision sgl?
10049        bne.b           ovfl_sc_dbl             # no; dbl
10050ovfl_sc_sgl:
10051        tst.l           LOCAL_LO(%a0)           # is lo lw of sgl set?
10052        bne.b           ovfl_sc_inx             # yes
10053        tst.b           3+LOCAL_HI(%a0)         # is lo byte of hi lw set?
10054        bne.b           ovfl_sc_inx             # yes
10055        bra.w           ovfl_work               # don't set INEX2
10056ovfl_sc_dbl:
10057        mov.l           LOCAL_LO(%a0),%d1       # are any of lo 11 bits of
10058        andi.l          &0x7ff,%d1              # dbl mantissa set?
10059        beq.w           ovfl_work               # no; don't set INEX2
10060ovfl_sc_inx:
10061        ori.l           &inex2_mask,USER_FPSR(%a6) # set INEX2
10062        bra.b           ovfl_work               # continue
10063
10064        global          t_ovfl
10065t_ovfl:
10066        ori.w           &ovfinx_mask,FPSR_EXCEPT(%a6) # set OVFL/INEX2/AOVFL/AINEX
10067ovfl_work:
10068        tst.b           SRC_EX(%a0)
10069        bpl.b           ovfl_p
10070ovfl_m:
10071        fmov.l          USER_FPCR(%a6),%fpcr
10072        fmovm.x         mns_huge(%pc),&0x80
10073        fmul.x          pls_huge(%pc),%fp0
10074
10075        fmov.l          %fpsr,%d0
10076        rol.l           &0x8,%d0
10077        ori.b           &neg_mask,%d0
10078        mov.b           %d0,FPSR_CC(%a6)
10079        rts
10080ovfl_p:
10081        fmov.l          USER_FPCR(%a6),%fpcr
10082        fmovm.x         pls_huge(%pc),&0x80
10083        fmul.x          pls_huge(%pc),%fp0
10084
10085        fmov.l          %fpsr,%d0
10086        rol.l           &0x8,%d0
10087        mov.b           %d0,FPSR_CC(%a6)
10088        rts
10089
10090        global          t_ovfl2
10091t_ovfl2:
10092        ori.w           &ovfinx_mask,FPSR_EXCEPT(%a6) # set OVFL/INEX2/AOVFL/AINEX
10093        fmov.l          USER_FPCR(%a6),%fpcr
10094        fmovm.x         pls_huge(%pc),&0x80
10095        fmul.x          pls_huge(%pc),%fp0
10096
10097        fmov.l          %fpsr,%d0
10098        rol.l           &0x8,%d0
10099        mov.b           %d0,FPSR_CC(%a6)
10100        rts
10101
10102#########################################################################
10103# XDEF **************************************************************** #
10104#       t_catch(): Handle 060FPLSP OVFL,UNFL,or INEX2 exception during  #
10105#                  emulation.                                           #
10106#       t_catch2(): Handle 060FPLSP OVFL,UNFL,or INEX2 exception during #
10107#                   emulation.                                          #
10108#                                                                       #
10109#       These routines are used by the 060FPLSP package.                #
10110#                                                                       #
10111# XREF **************************************************************** #
10112#       None.                                                           #
10113#                                                                       #
10114# INPUT *************************************************************** #
10115#       fp0 = default underflow or overflow result                      #
10116#                                                                       #
10117# OUTPUT ************************************************************** #
10118#       fp0 = default result                                            #
10119#                                                                       #
10120# ALGORITHM *********************************************************** #
10121#       If an overflow or underflow occurred during the last            #
10122# instruction of transcendental 060FPLSP emulation, then it has already #
10123# occurred and has been logged. Now we need to see if an inexact        #
10124# exception should occur.                                               #
10125#                                                                       #
10126#########################################################################
10127
10128        global          t_catch2
10129t_catch2:
10130        fmov.l          %fpsr,%d0
10131        or.l            %d0,USER_FPSR(%a6)
10132        bra.b           inx2_work
10133
10134        global          t_catch
10135t_catch:
10136        fmov.l          %fpsr,%d0
10137        or.l            %d0,USER_FPSR(%a6)
10138
10139#########################################################################
10140# XDEF **************************************************************** #
10141#       t_inx2(): Handle inexact 060FPLSP exception during emulation.   #
10142#       t_pinx2(): Handle inexact 060FPLSP exception for "+" results.   #
10143#       t_minx2(): Handle inexact 060FPLSP exception for "-" results.   #
10144#                                                                       #
10145# XREF **************************************************************** #
10146#       None.                                                           #
10147#                                                                       #
10148# INPUT *************************************************************** #
10149#       fp0 = default result                                            #
10150#                                                                       #
10151# OUTPUT ************************************************************** #
10152#       fp0 = default result                                            #
10153#                                                                       #
10154# ALGORITHM *********************************************************** #
10155#       The last instruction of transcendental emulation for the        #
10156# 060FPLSP should be inexact. So, if inexact is enabled, then we create #
10157# the event here by adding a large and very small number together       #
10158# so that the operating system can log the event.                       #
10159#       Must check, too, if the result was zero, in which case we just  #
10160# set the FPSR bits and return.                                         #
10161#                                                                       #
10162#########################################################################
10163
10164        global          t_inx2
10165t_inx2:
10166        fblt.w          t_minx2
10167        fbeq.w          inx2_zero
10168
10169        global          t_pinx2
10170t_pinx2:
10171        ori.w           &inx2a_mask,FPSR_EXCEPT(%a6) # set INEX2/AINEX
10172        bra.b           inx2_work
10173
10174        global          t_minx2
10175t_minx2:
10176        ori.l           &inx2a_mask+neg_mask,USER_FPSR(%a6)
10177
10178inx2_work:
10179        btst            &inex2_bit,FPCR_ENABLE(%a6) # is inexact enabled?
10180        bne.b           inx2_work_ena           # yes
10181        rts
10182inx2_work_ena:
10183        fmov.l          USER_FPCR(%a6),%fpcr    # insert user's exceptions
10184        fmov.s          &0x3f800000,%fp1        # load +1
10185        fadd.x          pls_tiny(%pc),%fp1      # cause exception
10186        rts
10187
10188inx2_zero:
10189        mov.b           &z_bmask,FPSR_CC(%a6)
10190        ori.w           &inx2a_mask,2+USER_FPSR(%a6) # set INEX/AINEX
10191        rts
10192
10193#########################################################################
10194# XDEF **************************************************************** #
10195#       t_extdnrm(): Handle DENORM inputs in 060FPLSP.                  #
10196#       t_resdnrm(): Handle DENORM inputs in 060FPLSP for "fscale".     #
10197#                                                                       #
10198#       This routine is used by the 060FPLSP package.                   #
10199#                                                                       #
10200# XREF **************************************************************** #
10201#       None.                                                           #
10202#                                                                       #
10203# INPUT *************************************************************** #
10204#       a0 = pointer to extended precision input operand                #
10205#                                                                       #
10206# OUTPUT ************************************************************** #
10207#       fp0 = default result                                            #
10208#                                                                       #
10209# ALGORITHM *********************************************************** #
10210#       For all functions that have a denormalized input and that       #
10211# f(x)=x, this is the entry point.                                      #
10212#       DENORM value is moved using "fmove" which triggers an exception #
10213# if enabled so the operating system can log the event.                 #
10214#                                                                       #
10215#########################################################################
10216
10217        global          t_extdnrm
10218t_extdnrm:
10219        fmov.l          USER_FPCR(%a6),%fpcr
10220        fmov.x          SRC_EX(%a0),%fp0
10221        fmov.l          %fpsr,%d0
10222        ori.l           &unfinx_mask,%d0
10223        or.l            %d0,USER_FPSR(%a6)
10224        rts
10225
10226        global          t_resdnrm
10227t_resdnrm:
10228        fmov.l          USER_FPCR(%a6),%fpcr
10229        fmov.x          SRC_EX(%a0),%fp0
10230        fmov.l          %fpsr,%d0
10231        or.l            %d0,USER_FPSR(%a6)
10232        rts
10233
10234##########################################
10235
10236#
10237# sto_cos:
10238#       This is used by fsincos library emulation. The correct
10239# values are already in fp0 and fp1 so we do nothing here.
10240#
10241        global          sto_cos
10242sto_cos:
10243        rts
10244
10245##########################################
10246
10247#
10248#       dst_qnan --- force result when destination is a NaN
10249#
10250        global          dst_qnan
10251dst_qnan:
10252        fmov.x          DST(%a1),%fp0
10253        tst.b           DST_EX(%a1)
10254        bmi.b           dst_qnan_m
10255dst_qnan_p:
10256        mov.b           &nan_bmask,FPSR_CC(%a6)
10257        rts
10258dst_qnan_m:
10259        mov.b           &nan_bmask+neg_bmask,FPSR_CC(%a6)
10260        rts
10261
10262#
10263#       src_qnan --- force result when source is a NaN
10264#
10265        global          src_qnan
10266src_qnan:
10267        fmov.x          SRC(%a0),%fp0
10268        tst.b           SRC_EX(%a0)
10269        bmi.b           src_qnan_m
10270src_qnan_p:
10271        mov.b           &nan_bmask,FPSR_CC(%a6)
10272        rts
10273src_qnan_m:
10274        mov.b           &nan_bmask+neg_bmask,FPSR_CC(%a6)
10275        rts
10276
10277##########################################
10278
10279#
10280#       Native instruction support
10281#
10282#       Some systems may need entry points even for 68060 native
10283#       instructions.  These routines are provided for
10284#       convenience.
10285#
10286        global          _fadds_
10287_fadds_:
10288        fmov.l          %fpcr,-(%sp)            # save fpcr
10289        fmov.l          &0x00000000,%fpcr       # clear fpcr for load
10290        fmov.s          0x8(%sp),%fp0           # load sgl dst
10291        fmov.l          (%sp)+,%fpcr            # restore fpcr
10292        fadd.s          0x8(%sp),%fp0           # fadd w/ sgl src
10293        rts
10294
10295        global          _faddd_
10296_faddd_:
10297        fmov.l          %fpcr,-(%sp)            # save fpcr
10298        fmov.l          &0x00000000,%fpcr       # clear fpcr for load
10299        fmov.d          0x8(%sp),%fp0           # load dbl dst
10300        fmov.l          (%sp)+,%fpcr            # restore fpcr
10301        fadd.d          0xc(%sp),%fp0           # fadd w/ dbl src
10302        rts
10303
10304        global          _faddx_
10305_faddx_:
10306        fmovm.x         0x4(%sp),&0x80          # load ext dst
10307        fadd.x          0x10(%sp),%fp0          # fadd w/ ext src
10308        rts
10309
10310        global          _fsubs_
10311_fsubs_:
10312        fmov.l          %fpcr,-(%sp)            # save fpcr
10313        fmov.l          &0x00000000,%fpcr       # clear fpcr for load
10314        fmov.s          0x8(%sp),%fp0           # load sgl dst
10315        fmov.l          (%sp)+,%fpcr            # restore fpcr
10316        fsub.s          0x8(%sp),%fp0           # fsub w/ sgl src
10317        rts
10318
10319        global          _fsubd_
10320_fsubd_:
10321        fmov.l          %fpcr,-(%sp)            # save fpcr
10322        fmov.l          &0x00000000,%fpcr       # clear fpcr for load
10323        fmov.d          0x8(%sp),%fp0           # load dbl dst
10324        fmov.l          (%sp)+,%fpcr            # restore fpcr
10325        fsub.d          0xc(%sp),%fp0           # fsub w/ dbl src
10326        rts
10327
10328        global          _fsubx_
10329_fsubx_:
10330        fmovm.x         0x4(%sp),&0x80          # load ext dst
10331        fsub.x          0x10(%sp),%fp0          # fsub w/ ext src
10332        rts
10333
10334        global          _fmuls_
10335_fmuls_:
10336        fmov.l          %fpcr,-(%sp)            # save fpcr
10337        fmov.l          &0x00000000,%fpcr       # clear fpcr for load
10338        fmov.s          0x8(%sp),%fp0           # load sgl dst
10339        fmov.l          (%sp)+,%fpcr            # restore fpcr
10340        fmul.s          0x8(%sp),%fp0           # fmul w/ sgl src
10341        rts
10342
10343        global          _fmuld_
10344_fmuld_:
10345        fmov.l          %fpcr,-(%sp)            # save fpcr
10346        fmov.l          &0x00000000,%fpcr       # clear fpcr for load
10347        fmov.d          0x8(%sp),%fp0           # load dbl dst
10348        fmov.l          (%sp)+,%fpcr            # restore fpcr
10349        fmul.d          0xc(%sp),%fp0           # fmul w/ dbl src
10350        rts
10351
10352        global          _fmulx_
10353_fmulx_:
10354        fmovm.x         0x4(%sp),&0x80          # load ext dst
10355        fmul.x          0x10(%sp),%fp0          # fmul w/ ext src
10356        rts
10357
10358        global          _fdivs_
10359_fdivs_:
10360        fmov.l          %fpcr,-(%sp)            # save fpcr
10361        fmov.l          &0x00000000,%fpcr       # clear fpcr for load
10362        fmov.s          0x8(%sp),%fp0           # load sgl dst
10363        fmov.l          (%sp)+,%fpcr            # restore fpcr
10364        fdiv.s          0x8(%sp),%fp0           # fdiv w/ sgl src
10365        rts
10366
10367        global          _fdivd_
10368_fdivd_:
10369        fmov.l          %fpcr,-(%sp)            # save fpcr
10370        fmov.l          &0x00000000,%fpcr       # clear fpcr for load
10371        fmov.d          0x8(%sp),%fp0           # load dbl dst
10372        fmov.l          (%sp)+,%fpcr            # restore fpcr
10373        fdiv.d          0xc(%sp),%fp0           # fdiv w/ dbl src
10374        rts
10375
10376        global          _fdivx_
10377_fdivx_:
10378        fmovm.x         0x4(%sp),&0x80          # load ext dst
10379        fdiv.x          0x10(%sp),%fp0          # fdiv w/ ext src
10380        rts
10381
10382        global          _fabss_
10383_fabss_:
10384        fabs.s          0x4(%sp),%fp0           # fabs w/ sgl src
10385        rts
10386
10387        global          _fabsd_
10388_fabsd_:
10389        fabs.d          0x4(%sp),%fp0           # fabs w/ dbl src
10390        rts
10391
10392        global          _fabsx_
10393_fabsx_:
10394        fabs.x          0x4(%sp),%fp0           # fabs w/ ext src
10395        rts
10396
10397        global          _fnegs_
10398_fnegs_:
10399        fneg.s          0x4(%sp),%fp0           # fneg w/ sgl src
10400        rts
10401
10402        global          _fnegd_
10403_fnegd_:
10404        fneg.d          0x4(%sp),%fp0           # fneg w/ dbl src
10405        rts
10406
10407        global          _fnegx_
10408_fnegx_:
10409        fneg.x          0x4(%sp),%fp0           # fneg w/ ext src
10410        rts
10411
10412        global          _fsqrts_
10413_fsqrts_:
10414        fsqrt.s         0x4(%sp),%fp0           # fsqrt w/ sgl src
10415        rts
10416
10417        global          _fsqrtd_
10418_fsqrtd_:
10419        fsqrt.d         0x4(%sp),%fp0           # fsqrt w/ dbl src
10420        rts
10421
10422        global          _fsqrtx_
10423_fsqrtx_:
10424        fsqrt.x         0x4(%sp),%fp0           # fsqrt w/ ext src
10425        rts
10426
10427        global          _fints_
10428_fints_:
10429        fint.s          0x4(%sp),%fp0           # fint w/ sgl src
10430        rts
10431
10432        global          _fintd_
10433_fintd_:
10434        fint.d          0x4(%sp),%fp0           # fint w/ dbl src
10435        rts
10436
10437        global          _fintx_
10438_fintx_:
10439        fint.x          0x4(%sp),%fp0           # fint w/ ext src
10440        rts
10441
10442        global          _fintrzs_
10443_fintrzs_:
10444        fintrz.s        0x4(%sp),%fp0           # fintrz w/ sgl src
10445        rts
10446
10447        global          _fintrzd_
10448_fintrzd_:
10449        fintrz.d        0x4(%sp),%fp0           # fintrx w/ dbl src
10450        rts
10451
10452        global          _fintrzx_
10453_fintrzx_:
10454        fintrz.x        0x4(%sp),%fp0           # fintrz w/ ext src
10455        rts
10456
10457########################################################################
10458
10459#########################################################################
10460# src_zero(): Return signed zero according to sign of src operand.      #
10461#########################################################################
10462        global          src_zero
10463src_zero:
10464        tst.b           SRC_EX(%a0)             # get sign of src operand
10465        bmi.b           ld_mzero                # if neg, load neg zero
10466
10467#
10468# ld_pzero(): return a positive zero.
10469#
10470        global          ld_pzero
10471ld_pzero:
10472        fmov.s          &0x00000000,%fp0        # load +0
10473        mov.b           &z_bmask,FPSR_CC(%a6)   # set 'Z' ccode bit
10474        rts
10475
10476# ld_mzero(): return a negative zero.
10477        global          ld_mzero
10478ld_mzero:
10479        fmov.s          &0x80000000,%fp0        # load -0
10480        mov.b           &neg_bmask+z_bmask,FPSR_CC(%a6) # set 'N','Z' ccode bits
10481        rts
10482
10483#########################################################################
10484# dst_zero(): Return signed zero according to sign of dst operand.      #
10485#########################################################################
10486        global          dst_zero
10487dst_zero:
10488        tst.b           DST_EX(%a1)             # get sign of dst operand
10489        bmi.b           ld_mzero                # if neg, load neg zero
10490        bra.b           ld_pzero                # load positive zero
10491
10492#########################################################################
10493# src_inf(): Return signed inf according to sign of src operand.        #
10494#########################################################################
10495        global          src_inf
10496src_inf:
10497        tst.b           SRC_EX(%a0)             # get sign of src operand
10498        bmi.b           ld_minf                 # if negative branch
10499
10500#
10501# ld_pinf(): return a positive infinity.
10502#
10503        global          ld_pinf
10504ld_pinf:
10505        fmov.s          &0x7f800000,%fp0        # load +INF
10506        mov.b           &inf_bmask,FPSR_CC(%a6) # set 'INF' ccode bit
10507        rts
10508
10509#
10510# ld_minf():return a negative infinity.
10511#
10512        global          ld_minf
10513ld_minf:
10514        fmov.s          &0xff800000,%fp0        # load -INF
10515        mov.b           &neg_bmask+inf_bmask,FPSR_CC(%a6) # set 'N','I' ccode bits
10516        rts
10517
10518#########################################################################
10519# dst_inf(): Return signed inf according to sign of dst operand.        #
10520#########################################################################
10521        global          dst_inf
10522dst_inf:
10523        tst.b           DST_EX(%a1)             # get sign of dst operand
10524        bmi.b           ld_minf                 # if negative branch
10525        bra.b           ld_pinf
10526
10527        global          szr_inf
10528#################################################################
10529# szr_inf(): Return +ZERO for a negative src operand or         #
10530#                   +INF for a positive src operand.            #
10531#            Routine used for fetox, ftwotox, and ftentox.      #
10532#################################################################
10533szr_inf:
10534        tst.b           SRC_EX(%a0)             # check sign of source
10535        bmi.b           ld_pzero
10536        bra.b           ld_pinf
10537
10538#########################################################################
10539# sopr_inf(): Return +INF for a positive src operand or                 #
10540#             jump to operand error routine for a negative src operand. #
10541#             Routine used for flogn, flognp1, flog10, and flog2.       #
10542#########################################################################
10543        global          sopr_inf
10544sopr_inf:
10545        tst.b           SRC_EX(%a0)             # check sign of source
10546        bmi.w           t_operr
10547        bra.b           ld_pinf
10548
10549#################################################################
10550# setoxm1i(): Return minus one for a negative src operand or    #
10551#             positive infinity for a positive src operand.     #
10552#             Routine used for fetoxm1.                         #
10553#################################################################
10554        global          setoxm1i
10555setoxm1i:
10556        tst.b           SRC_EX(%a0)             # check sign of source
10557        bmi.b           ld_mone
10558        bra.b           ld_pinf
10559
10560#########################################################################
10561# src_one(): Return signed one according to sign of src operand.        #
10562#########################################################################
10563        global          src_one
10564src_one:
10565        tst.b           SRC_EX(%a0)             # check sign of source
10566        bmi.b           ld_mone
10567
10568#
10569# ld_pone(): return positive one.
10570#
10571        global          ld_pone
10572ld_pone:
10573        fmov.s          &0x3f800000,%fp0        # load +1
10574        clr.b           FPSR_CC(%a6)
10575        rts
10576
10577#
10578# ld_mone(): return negative one.
10579#
10580        global          ld_mone
10581ld_mone:
10582        fmov.s          &0xbf800000,%fp0        # load -1
10583        mov.b           &neg_bmask,FPSR_CC(%a6) # set 'N' ccode bit
10584        rts
10585
10586ppiby2: long            0x3fff0000, 0xc90fdaa2, 0x2168c235
10587mpiby2: long            0xbfff0000, 0xc90fdaa2, 0x2168c235
10588
10589#################################################################
10590# spi_2(): Return signed PI/2 according to sign of src operand. #
10591#################################################################
10592        global          spi_2
10593spi_2:
10594        tst.b           SRC_EX(%a0)             # check sign of source
10595        bmi.b           ld_mpi2
10596
10597#
10598# ld_ppi2(): return positive PI/2.
10599#
10600        global          ld_ppi2
10601ld_ppi2:
10602        fmov.l          %d0,%fpcr
10603        fmov.x          ppiby2(%pc),%fp0        # load +pi/2
10604        bra.w           t_pinx2                 # set INEX2
10605
10606#
10607# ld_mpi2(): return negative PI/2.
10608#
10609        global          ld_mpi2
10610ld_mpi2:
10611        fmov.l          %d0,%fpcr
10612        fmov.x          mpiby2(%pc),%fp0        # load -pi/2
10613        bra.w           t_minx2                 # set INEX2
10614
10615####################################################
10616# The following routines give support for fsincos. #
10617####################################################
10618
10619#
10620# ssincosz(): When the src operand is ZERO, store a one in the
10621#             cosine register and return a ZERO in fp0 w/ the same sign
10622#             as the src operand.
10623#
10624        global          ssincosz
10625ssincosz:
10626        fmov.s          &0x3f800000,%fp1
10627        tst.b           SRC_EX(%a0)             # test sign
10628        bpl.b           sincoszp
10629        fmov.s          &0x80000000,%fp0        # return sin result in fp0
10630        mov.b           &z_bmask+neg_bmask,FPSR_CC(%a6)
10631        rts
10632sincoszp:
10633        fmov.s          &0x00000000,%fp0        # return sin result in fp0
10634        mov.b           &z_bmask,FPSR_CC(%a6)
10635        rts
10636
10637#
10638# ssincosi(): When the src operand is INF, store a QNAN in the cosine
10639#             register and jump to the operand error routine for negative
10640#             src operands.
10641#
10642        global          ssincosi
10643ssincosi:
10644        fmov.x          qnan(%pc),%fp1          # load NAN
10645        bra.w           t_operr
10646
10647#
10648# ssincosqnan(): When the src operand is a QNAN, store the QNAN in the cosine
10649#                register and branch to the src QNAN routine.
10650#
10651        global          ssincosqnan
10652ssincosqnan:
10653        fmov.x          LOCAL_EX(%a0),%fp1
10654        bra.w           src_qnan
10655
10656########################################################################
10657
10658        global          smod_sdnrm
10659        global          smod_snorm
10660smod_sdnrm:
10661smod_snorm:
10662        mov.b           DTAG(%a6),%d1
10663        beq.l           smod
10664        cmpi.b          %d1,&ZERO
10665        beq.w           smod_zro
10666        cmpi.b          %d1,&INF
10667        beq.l           t_operr
10668        cmpi.b          %d1,&DENORM
10669        beq.l           smod
10670        bra.l           dst_qnan
10671
10672        global          smod_szero
10673smod_szero:
10674        mov.b           DTAG(%a6),%d1
10675        beq.l           t_operr
10676        cmpi.b          %d1,&ZERO
10677        beq.l           t_operr
10678        cmpi.b          %d1,&INF
10679        beq.l           t_operr
10680        cmpi.b          %d1,&DENORM
10681        beq.l           t_operr
10682        bra.l           dst_qnan
10683
10684        global          smod_sinf
10685smod_sinf:
10686        mov.b           DTAG(%a6),%d1
10687        beq.l           smod_fpn
10688        cmpi.b          %d1,&ZERO
10689        beq.l           smod_zro
10690        cmpi.b          %d1,&INF
10691        beq.l           t_operr
10692        cmpi.b          %d1,&DENORM
10693        beq.l           smod_fpn
10694        bra.l           dst_qnan
10695
10696smod_zro:
10697srem_zro:
10698        mov.b           SRC_EX(%a0),%d1         # get src sign
10699        mov.b           DST_EX(%a1),%d0         # get dst sign
10700        eor.b           %d0,%d1                 # get qbyte sign
10701        andi.b          &0x80,%d1
10702        mov.b           %d1,FPSR_QBYTE(%a6)
10703        tst.b           %d0
10704        bpl.w           ld_pzero
10705        bra.w           ld_mzero
10706
10707smod_fpn:
10708srem_fpn:
10709        clr.b           FPSR_QBYTE(%a6)
10710        mov.l           %d0,-(%sp)
10711        mov.b           SRC_EX(%a0),%d1         # get src sign
10712        mov.b           DST_EX(%a1),%d0         # get dst sign
10713        eor.b           %d0,%d1                 # get qbyte sign
10714        andi.b          &0x80,%d1
10715        mov.b           %d1,FPSR_QBYTE(%a6)
10716        cmpi.b          DTAG(%a6),&DENORM
10717        bne.b           smod_nrm
10718        lea             DST(%a1),%a0
10719        mov.l           (%sp)+,%d0
10720        bra             t_resdnrm
10721smod_nrm:
10722        fmov.l          (%sp)+,%fpcr
10723        fmov.x          DST(%a1),%fp0
10724        tst.b           DST_EX(%a1)
10725        bmi.b           smod_nrm_neg
10726        rts
10727
10728smod_nrm_neg:
10729        mov.b           &neg_bmask,FPSR_CC(%a6) # set 'N' code
10730        rts
10731
10732#########################################################################
10733        global          srem_snorm
10734        global          srem_sdnrm
10735srem_sdnrm:
10736srem_snorm:
10737        mov.b           DTAG(%a6),%d1
10738        beq.l           srem
10739        cmpi.b          %d1,&ZERO
10740        beq.w           srem_zro
10741        cmpi.b          %d1,&INF
10742        beq.l           t_operr
10743        cmpi.b          %d1,&DENORM
10744        beq.l           srem
10745        bra.l           dst_qnan
10746
10747        global          srem_szero
10748srem_szero:
10749        mov.b           DTAG(%a6),%d1
10750        beq.l           t_operr
10751        cmpi.b          %d1,&ZERO
10752        beq.l           t_operr
10753        cmpi.b          %d1,&INF
10754        beq.l           t_operr
10755        cmpi.b          %d1,&DENORM
10756        beq.l           t_operr
10757        bra.l           dst_qnan
10758
10759        global          srem_sinf
10760srem_sinf:
10761        mov.b           DTAG(%a6),%d1
10762        beq.w           srem_fpn
10763        cmpi.b          %d1,&ZERO
10764        beq.w           srem_zro
10765        cmpi.b          %d1,&INF
10766        beq.l           t_operr
10767        cmpi.b          %d1,&DENORM
10768        beq.l           srem_fpn
10769        bra.l           dst_qnan
10770
10771#########################################################################
10772
10773        global          sscale_snorm
10774        global          sscale_sdnrm
10775sscale_snorm:
10776sscale_sdnrm:
10777        mov.b           DTAG(%a6),%d1
10778        beq.l           sscale
10779        cmpi.b          %d1,&ZERO
10780        beq.l           dst_zero
10781        cmpi.b          %d1,&INF
10782        beq.l           dst_inf
10783        cmpi.b          %d1,&DENORM
10784        beq.l           sscale
10785        bra.l           dst_qnan
10786
10787        global          sscale_szero
10788sscale_szero:
10789        mov.b           DTAG(%a6),%d1
10790        beq.l           sscale
10791        cmpi.b          %d1,&ZERO
10792        beq.l           dst_zero
10793        cmpi.b          %d1,&INF
10794        beq.l           dst_inf
10795        cmpi.b          %d1,&DENORM
10796        beq.l           sscale
10797        bra.l           dst_qnan
10798
10799        global          sscale_sinf
10800sscale_sinf:
10801        mov.b           DTAG(%a6),%d1
10802        beq.l           t_operr
10803        cmpi.b          %d1,&QNAN
10804        beq.l           dst_qnan
10805        bra.l           t_operr
10806
10807########################################################################
10808
10809        global          sop_sqnan
10810sop_sqnan:
10811        mov.b           DTAG(%a6),%d1
10812        cmpi.b          %d1,&QNAN
10813        beq.l           dst_qnan
10814        bra.l           src_qnan
10815
10816#########################################################################
10817# norm(): normalize the mantissa of an extended precision input. the    #
10818#         input operand should not be normalized already.               #
10819#                                                                       #
10820# XDEF **************************************************************** #
10821#       norm()                                                          #
10822#                                                                       #
10823# XREF **************************************************************** #
10824#       none                                                            #
10825#                                                                       #
10826# INPUT *************************************************************** #
10827#       a0 = pointer fp extended precision operand to normalize         #
10828#                                                                       #
10829# OUTPUT ************************************************************** #
10830#       d0 = number of bit positions the mantissa was shifted           #
10831#       a0 = the input operand's mantissa is normalized; the exponent   #
10832#            is unchanged.                                              #
10833#                                                                       #
10834#########################################################################
10835        global          norm
10836norm:
10837        mov.l           %d2, -(%sp)             # create some temp regs
10838        mov.l           %d3, -(%sp)
10839
10840        mov.l           FTEMP_HI(%a0), %d0      # load hi(mantissa)
10841        mov.l           FTEMP_LO(%a0), %d1      # load lo(mantissa)
10842
10843        bfffo           %d0{&0:&32}, %d2        # how many places to shift?
10844        beq.b           norm_lo                 # hi(man) is all zeroes!
10845
10846norm_hi:
10847        lsl.l           %d2, %d0                # left shift hi(man)
10848        bfextu          %d1{&0:%d2}, %d3        # extract lo bits
10849
10850        or.l            %d3, %d0                # create hi(man)
10851        lsl.l           %d2, %d1                # create lo(man)
10852
10853        mov.l           %d0, FTEMP_HI(%a0)      # store new hi(man)
10854        mov.l           %d1, FTEMP_LO(%a0)      # store new lo(man)
10855
10856        mov.l           %d2, %d0                # return shift amount
10857
10858        mov.l           (%sp)+, %d3             # restore temp regs
10859        mov.l           (%sp)+, %d2
10860
10861        rts
10862
10863norm_lo:
10864        bfffo           %d1{&0:&32}, %d2        # how many places to shift?
10865        lsl.l           %d2, %d1                # shift lo(man)
10866        add.l           &32, %d2                # add 32 to shft amount
10867
10868        mov.l           %d1, FTEMP_HI(%a0)      # store hi(man)
10869        clr.l           FTEMP_LO(%a0)           # lo(man) is now zero
10870
10871        mov.l           %d2, %d0                # return shift amount
10872
10873        mov.l           (%sp)+, %d3             # restore temp regs
10874        mov.l           (%sp)+, %d2
10875
10876        rts
10877
10878#########################################################################
10879# unnorm_fix(): - changes an UNNORM to one of NORM, DENORM, or ZERO     #
10880#               - returns corresponding optype tag                      #
10881#                                                                       #
10882# XDEF **************************************************************** #
10883#       unnorm_fix()                                                    #
10884#                                                                       #
10885# XREF **************************************************************** #
10886#       norm() - normalize the mantissa                                 #
10887#                                                                       #
10888# INPUT *************************************************************** #
10889#       a0 = pointer to unnormalized extended precision number          #
10890#                                                                       #
10891# OUTPUT ************************************************************** #
10892#       d0 = optype tag - is corrected to one of NORM, DENORM, or ZERO  #
10893#       a0 = input operand has been converted to a norm, denorm, or     #
10894#            zero; both the exponent and mantissa are changed.          #
10895#                                                                       #
10896#########################################################################
10897
10898        global          unnorm_fix
10899unnorm_fix:
10900        bfffo           FTEMP_HI(%a0){&0:&32}, %d0 # how many shifts are needed?
10901        bne.b           unnorm_shift            # hi(man) is not all zeroes
10902
10903#
10904# hi(man) is all zeroes so see if any bits in lo(man) are set
10905#
10906unnorm_chk_lo:
10907        bfffo           FTEMP_LO(%a0){&0:&32}, %d0 # is operand really a zero?
10908        beq.w           unnorm_zero             # yes
10909
10910        add.w           &32, %d0                # no; fix shift distance
10911
10912#
10913# d0 = # shifts needed for complete normalization
10914#
10915unnorm_shift:
10916        clr.l           %d1                     # clear top word
10917        mov.w           FTEMP_EX(%a0), %d1      # extract exponent
10918        and.w           &0x7fff, %d1            # strip off sgn
10919
10920        cmp.w           %d0, %d1                # will denorm push exp < 0?
10921        bgt.b           unnorm_nrm_zero         # yes; denorm only until exp = 0
10922
10923#
10924# exponent would not go < 0. therefore, number stays normalized
10925#
10926        sub.w           %d0, %d1                # shift exponent value
10927        mov.w           FTEMP_EX(%a0), %d0      # load old exponent
10928        and.w           &0x8000, %d0            # save old sign
10929        or.w            %d0, %d1                # {sgn,new exp}
10930        mov.w           %d1, FTEMP_EX(%a0)      # insert new exponent
10931
10932        bsr.l           norm                    # normalize UNNORM
10933
10934        mov.b           &NORM, %d0              # return new optype tag
10935        rts
10936
10937#
10938# exponent would go < 0, so only denormalize until exp = 0
10939#
10940unnorm_nrm_zero:
10941        cmp.b           %d1, &32                # is exp <= 32?
10942        bgt.b           unnorm_nrm_zero_lrg     # no; go handle large exponent
10943
10944        bfextu          FTEMP_HI(%a0){%d1:&32}, %d0 # extract new hi(man)
10945        mov.l           %d0, FTEMP_HI(%a0)      # save new hi(man)
10946
10947        mov.l           FTEMP_LO(%a0), %d0      # fetch old lo(man)
10948        lsl.l           %d1, %d0                # extract new lo(man)
10949        mov.l           %d0, FTEMP_LO(%a0)      # save new lo(man)
10950
10951        and.w           &0x8000, FTEMP_EX(%a0)  # set exp = 0
10952
10953        mov.b           &DENORM, %d0            # return new optype tag
10954        rts
10955
10956#
10957# only mantissa bits set are in lo(man)
10958#
10959unnorm_nrm_zero_lrg:
10960        sub.w           &32, %d1                # adjust shft amt by 32
10961
10962        mov.l           FTEMP_LO(%a0), %d0      # fetch old lo(man)
10963        lsl.l           %d1, %d0                # left shift lo(man)
10964
10965        mov.l           %d0, FTEMP_HI(%a0)      # store new hi(man)
10966        clr.l           FTEMP_LO(%a0)           # lo(man) = 0
10967
10968        and.w           &0x8000, FTEMP_EX(%a0)  # set exp = 0
10969
10970        mov.b           &DENORM, %d0            # return new optype tag
10971        rts
10972
10973#
10974# whole mantissa is zero so this UNNORM is actually a zero
10975#
10976unnorm_zero:
10977        and.w           &0x8000, FTEMP_EX(%a0)  # force exponent to zero
10978
10979        mov.b           &ZERO, %d0              # fix optype tag
10980        rts
10981