[BACK]Return to fpsp.s CVS log [TXT][DIR] Up to [local] / sys / arch / m68k / 060sp

Annotation of sys/arch/m68k/060sp/fpsp.s, Revision 1.1.1.1

1.1       nbrk        1: #
                      2: # $OpenBSD: fpsp.s,v 1.9 2007/04/10 17:47:54 miod Exp $
                      3: # $NetBSD: fpsp.s,v 1.2 1996/05/15 19:48:03 is Exp $
                      4: #
                      5:
                      6: #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                      7: # MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
                      8: # M68000 Hi-Performance Microprocessor Division
                      9: # M68060 Software Package Production Release
                     10: #
                     11: # M68060 Software Package Copyright (C) 1993, 1994, 1995, 1996 Motorola Inc.
                     12: # All rights reserved.
                     13: #
                     14: # THE SOFTWARE is provided on an "AS IS" basis and without warranty.
                     15: # To the maximum extent permitted by applicable law,
                     16: # MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
                     17: # INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS
                     18: # FOR A PARTICULAR PURPOSE and any warranty against infringement with
                     19: # regard to the SOFTWARE (INCLUDING ANY MODIFIED VERSIONS THEREOF)
                     20: # and any accompanying written materials.
                     21: #
                     22: # To the maximum extent permitted by applicable law,
                     23: # IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
                     24: # (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS,
                     25: # BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS)
                     26: # ARISING OF THE USE OR INABILITY TO USE THE SOFTWARE.
                     27: #
                     28: # Motorola assumes no responsibility for the maintenance and support
                     29: # of the SOFTWARE.
                     30: #
                     31: # You are hereby granted a copyright license to use, modify, and distribute the
                     32: # SOFTWARE so long as this entire notice is retained without alteration
                     33: # in any modified and/or redistributed versions, and that such modified
                     34: # versions are clearly identified as such.
                     35: # No licenses are granted by implication, estoppel or otherwise under any
                     36: # patents or trademarks of Motorola, Inc.
                     37: #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                     38:
                     39: #
                     40: # freal.s:
                     41: #      This file is appended to the top of the 060FPSP package
                     42: # and contains the entry points into the package. The user, in
                     43: # effect, branches to one of the branch table entries located
                     44: # after _060FPSP_TABLE.
                     45: #      Also, subroutine stubs exist in this file (_fpsp_done for
                     46: # example) that are referenced by the FPSP package itself in order
                     47: # to call a given routine. The stub routine actually performs the
                     48: # callout. The FPSP code does a "bsr" to the stub routine. This
                     49: # extra layer of hierarchy adds a slight performance penalty but
                     50: # it makes the FPSP code easier to read and more mainatinable.
                     51: #
                     52:
                     53: set    _off_bsun,      0x00
                     54: set    _off_snan,      0x04
                     55: set    _off_operr,     0x08
                     56: set    _off_ovfl,      0x0c
                     57: set    _off_unfl,      0x10
                     58: set    _off_dz,        0x14
                     59: set    _off_inex,      0x18
                     60: set    _off_fline,     0x1c
                     61: set    _off_fpu_dis,   0x20
                     62: set    _off_trap,      0x24
                     63: set    _off_trace,     0x28
                     64: set    _off_access,    0x2c
                     65: set    _off_done,      0x30
                     66:
                     67: set    _off_imr,       0x40
                     68: set    _off_dmr,       0x44
                     69: set    _off_dmw,       0x48
                     70: set    _off_irw,       0x4c
                     71: set    _off_irl,       0x50
                     72: set    _off_drb,       0x54
                     73: set    _off_drw,       0x58
                     74: set    _off_drl,       0x5c
                     75: set    _off_dwb,       0x60
                     76: set    _off_dww,       0x64
                     77: set    _off_dwl,       0x68
                     78:
                     79: _060FPSP_TABLE:
                     80:
                     81: ###############################################################
                     82:
                     83: # Here's the table of ENTRY POINTS for those linking the package.
                     84:        bra.l           _fpsp_snan
                     85:        short           0x0000
                     86:        bra.l           _fpsp_operr
                     87:        short           0x0000
                     88:        bra.l           _fpsp_ovfl
                     89:        short           0x0000
                     90:        bra.l           _fpsp_unfl
                     91:        short           0x0000
                     92:        bra.l           _fpsp_dz
                     93:        short           0x0000
                     94:        bra.l           _fpsp_inex
                     95:        short           0x0000
                     96:        bra.l           _fpsp_fline
                     97:        short           0x0000
                     98:        bra.l           _fpsp_unsupp
                     99:        short           0x0000
                    100:        bra.l           _fpsp_effadd
                    101:        short           0x0000
                    102:
                    103:        space           56
                    104:
                    105: ###############################################################
                    106:        global          _fpsp_done
                    107: _fpsp_done:
                    108:        mov.l           %d0,-(%sp)
                    109:        mov.l           (_060FPSP_TABLE-0x80+_off_done,%pc),%d0
                    110:        pea.l           (_060FPSP_TABLE-0x80,%pc,%d0)
                    111:        mov.l           0x4(%sp),%d0
                    112:        rtd             &0x4
                    113:
                    114:        global          _real_ovfl
                    115: _real_ovfl:
                    116:        mov.l           %d0,-(%sp)
                    117:        mov.l           (_060FPSP_TABLE-0x80+_off_ovfl,%pc),%d0
                    118:        pea.l           (_060FPSP_TABLE-0x80,%pc,%d0)
                    119:        mov.l           0x4(%sp),%d0
                    120:        rtd             &0x4
                    121:
                    122:        global          _real_unfl
                    123: _real_unfl:
                    124:        mov.l           %d0,-(%sp)
                    125:        mov.l           (_060FPSP_TABLE-0x80+_off_unfl,%pc),%d0
                    126:        pea.l           (_060FPSP_TABLE-0x80,%pc,%d0)
                    127:        mov.l           0x4(%sp),%d0
                    128:        rtd             &0x4
                    129:
                    130:        global          _real_inex
                    131: _real_inex:
                    132:        mov.l           %d0,-(%sp)
                    133:        mov.l           (_060FPSP_TABLE-0x80+_off_inex,%pc),%d0
                    134:        pea.l           (_060FPSP_TABLE-0x80,%pc,%d0)
                    135:        mov.l           0x4(%sp),%d0
                    136:        rtd             &0x4
                    137:
                    138:        global          _real_bsun
                    139: _real_bsun:
                    140:        mov.l           %d0,-(%sp)
                    141:        mov.l           (_060FPSP_TABLE-0x80+_off_bsun,%pc),%d0
                    142:        pea.l           (_060FPSP_TABLE-0x80,%pc,%d0)
                    143:        mov.l           0x4(%sp),%d0
                    144:        rtd             &0x4
                    145:
                    146:        global          _real_operr
                    147: _real_operr:
                    148:        mov.l           %d0,-(%sp)
                    149:        mov.l           (_060FPSP_TABLE-0x80+_off_operr,%pc),%d0
                    150:        pea.l           (_060FPSP_TABLE-0x80,%pc,%d0)
                    151:        mov.l           0x4(%sp),%d0
                    152:        rtd             &0x4
                    153:
                    154:        global          _real_snan
                    155: _real_snan:
                    156:        mov.l           %d0,-(%sp)
                    157:        mov.l           (_060FPSP_TABLE-0x80+_off_snan,%pc),%d0
                    158:        pea.l           (_060FPSP_TABLE-0x80,%pc,%d0)
                    159:        mov.l           0x4(%sp),%d0
                    160:        rtd             &0x4
                    161:
                    162:        global          _real_dz
                    163: _real_dz:
                    164:        mov.l           %d0,-(%sp)
                    165:        mov.l           (_060FPSP_TABLE-0x80+_off_dz,%pc),%d0
                    166:        pea.l           (_060FPSP_TABLE-0x80,%pc,%d0)
                    167:        mov.l           0x4(%sp),%d0
                    168:        rtd             &0x4
                    169:
                    170:        global          _real_fline
                    171: _real_fline:
                    172:        mov.l           %d0,-(%sp)
                    173:        mov.l           (_060FPSP_TABLE-0x80+_off_fline,%pc),%d0
                    174:        pea.l           (_060FPSP_TABLE-0x80,%pc,%d0)
                    175:        mov.l           0x4(%sp),%d0
                    176:        rtd             &0x4
                    177:
                    178:        global          _real_fpu_disabled
                    179: _real_fpu_disabled:
                    180:        mov.l           %d0,-(%sp)
                    181:        mov.l           (_060FPSP_TABLE-0x80+_off_fpu_dis,%pc),%d0
                    182:        pea.l           (_060FPSP_TABLE-0x80,%pc,%d0)
                    183:        mov.l           0x4(%sp),%d0
                    184:        rtd             &0x4
                    185:
                    186:        global          _real_trap
                    187: _real_trap:
                    188:        mov.l           %d0,-(%sp)
                    189:        mov.l           (_060FPSP_TABLE-0x80+_off_trap,%pc),%d0
                    190:        pea.l           (_060FPSP_TABLE-0x80,%pc,%d0)
                    191:        mov.l           0x4(%sp),%d0
                    192:        rtd             &0x4
                    193:
                    194:        global          _real_trace
                    195: _real_trace:
                    196:        mov.l           %d0,-(%sp)
                    197:        mov.l           (_060FPSP_TABLE-0x80+_off_trace,%pc),%d0
                    198:        pea.l           (_060FPSP_TABLE-0x80,%pc,%d0)
                    199:        mov.l           0x4(%sp),%d0
                    200:        rtd             &0x4
                    201:
                    202:        global          _real_access
                    203: _real_access:
                    204:        mov.l           %d0,-(%sp)
                    205:        mov.l           (_060FPSP_TABLE-0x80+_off_access,%pc),%d0
                    206:        pea.l           (_060FPSP_TABLE-0x80,%pc,%d0)
                    207:        mov.l           0x4(%sp),%d0
                    208:        rtd             &0x4
                    209:
                    210: #######################################
                    211:
                    212:        global          _imem_read
                    213: _imem_read:
                    214:        mov.l           %d0,-(%sp)
                    215:        mov.l           (_060FPSP_TABLE-0x80+_off_imr,%pc),%d0
                    216:        pea.l           (_060FPSP_TABLE-0x80,%pc,%d0)
                    217:        mov.l           0x4(%sp),%d0
                    218:        rtd             &0x4
                    219:
                    220:        global          _dmem_read
                    221: _dmem_read:
                    222:        mov.l           %d0,-(%sp)
                    223:        mov.l           (_060FPSP_TABLE-0x80+_off_dmr,%pc),%d0
                    224:        pea.l           (_060FPSP_TABLE-0x80,%pc,%d0)
                    225:        mov.l           0x4(%sp),%d0
                    226:        rtd             &0x4
                    227:
                    228:        global          _dmem_write
                    229: _dmem_write:
                    230:        mov.l           %d0,-(%sp)
                    231:        mov.l           (_060FPSP_TABLE-0x80+_off_dmw,%pc),%d0
                    232:        pea.l           (_060FPSP_TABLE-0x80,%pc,%d0)
                    233:        mov.l           0x4(%sp),%d0
                    234:        rtd             &0x4
                    235:
                    236:        global          _imem_read_word
                    237: _imem_read_word:
                    238:        mov.l           %d0,-(%sp)
                    239:        mov.l           (_060FPSP_TABLE-0x80+_off_irw,%pc),%d0
                    240:        pea.l           (_060FPSP_TABLE-0x80,%pc,%d0)
                    241:        mov.l           0x4(%sp),%d0
                    242:        rtd             &0x4
                    243:
                    244:        global          _imem_read_long
                    245: _imem_read_long:
                    246:        mov.l           %d0,-(%sp)
                    247:        mov.l           (_060FPSP_TABLE-0x80+_off_irl,%pc),%d0
                    248:        pea.l           (_060FPSP_TABLE-0x80,%pc,%d0)
                    249:        mov.l           0x4(%sp),%d0
                    250:        rtd             &0x4
                    251:
                    252:        global          _dmem_read_byte
                    253: _dmem_read_byte:
                    254:        mov.l           %d0,-(%sp)
                    255:        mov.l           (_060FPSP_TABLE-0x80+_off_drb,%pc),%d0
                    256:        pea.l           (_060FPSP_TABLE-0x80,%pc,%d0)
                    257:        mov.l           0x4(%sp),%d0
                    258:        rtd             &0x4
                    259:
                    260:        global          _dmem_read_word
                    261: _dmem_read_word:
                    262:        mov.l           %d0,-(%sp)
                    263:        mov.l           (_060FPSP_TABLE-0x80+_off_drw,%pc),%d0
                    264:        pea.l           (_060FPSP_TABLE-0x80,%pc,%d0)
                    265:        mov.l           0x4(%sp),%d0
                    266:        rtd             &0x4
                    267:
                    268:        global          _dmem_read_long
                    269: _dmem_read_long:
                    270:        mov.l           %d0,-(%sp)
                    271:        mov.l           (_060FPSP_TABLE-0x80+_off_drl,%pc),%d0
                    272:        pea.l           (_060FPSP_TABLE-0x80,%pc,%d0)
                    273:        mov.l           0x4(%sp),%d0
                    274:        rtd             &0x4
                    275:
                    276:        global          _dmem_write_byte
                    277: _dmem_write_byte:
                    278:        mov.l           %d0,-(%sp)
                    279:        mov.l           (_060FPSP_TABLE-0x80+_off_dwb,%pc),%d0
                    280:        pea.l           (_060FPSP_TABLE-0x80,%pc,%d0)
                    281:        mov.l           0x4(%sp),%d0
                    282:        rtd             &0x4
                    283:
                    284:        global          _dmem_write_word
                    285: _dmem_write_word:
                    286:        mov.l           %d0,-(%sp)
                    287:        mov.l           (_060FPSP_TABLE-0x80+_off_dww,%pc),%d0
                    288:        pea.l           (_060FPSP_TABLE-0x80,%pc,%d0)
                    289:        mov.l           0x4(%sp),%d0
                    290:        rtd             &0x4
                    291:
                    292:        global          _dmem_write_long
                    293: _dmem_write_long:
                    294:        mov.l           %d0,-(%sp)
                    295:        mov.l           (_060FPSP_TABLE-0x80+_off_dwl,%pc),%d0
                    296:        pea.l           (_060FPSP_TABLE-0x80,%pc,%d0)
                    297:        mov.l           0x4(%sp),%d0
                    298:        rtd             &0x4
                    299:
                    300: #
                    301: # This file contains a set of define statements for constants
                    302: # in order to promote readability within the corecode itself.
                    303: #
                    304:
                    305: set LOCAL_SIZE,                192                     # stack frame size(bytes)
                    306: set LV,                        -LOCAL_SIZE             # stack offset
                    307:
                    308: set EXC_SR,            0x4                     # stack status register
                    309: set EXC_PC,            0x6                     # stack pc
                    310: set EXC_VOFF,          0xa                     # stacked vector offset
                    311: set EXC_EA,            0xc                     # stacked <ea>
                    312:
                    313: set EXC_FP,            0x0                     # frame pointer
                    314:
                    315: set EXC_AREGS,         -68                     # offset of all address regs
                    316: set EXC_DREGS,         -100                    # offset of all data regs
                    317: set EXC_FPREGS,                -36                     # offset of all fp regs
                    318:
                    319: set EXC_A7,            EXC_AREGS+(7*4)         # offset of saved a7
                    320: set OLD_A7,            EXC_AREGS+(6*4)         # extra copy of saved a7
                    321: set EXC_A6,            EXC_AREGS+(6*4)         # offset of saved a6
                    322: set EXC_A5,            EXC_AREGS+(5*4)
                    323: set EXC_A4,            EXC_AREGS+(4*4)
                    324: set EXC_A3,            EXC_AREGS+(3*4)
                    325: set EXC_A2,            EXC_AREGS+(2*4)
                    326: set EXC_A1,            EXC_AREGS+(1*4)
                    327: set EXC_A0,            EXC_AREGS+(0*4)
                    328: set EXC_D7,            EXC_DREGS+(7*4)
                    329: set EXC_D6,            EXC_DREGS+(6*4)
                    330: set EXC_D5,            EXC_DREGS+(5*4)
                    331: set EXC_D4,            EXC_DREGS+(4*4)
                    332: set EXC_D3,            EXC_DREGS+(3*4)
                    333: set EXC_D2,            EXC_DREGS+(2*4)
                    334: set EXC_D1,            EXC_DREGS+(1*4)
                    335: set EXC_D0,            EXC_DREGS+(0*4)
                    336:
                    337: set EXC_FP0,           EXC_FPREGS+(0*12)       # offset of saved fp0
                    338: set EXC_FP1,           EXC_FPREGS+(1*12)       # offset of saved fp1
                    339: set EXC_FP2,           EXC_FPREGS+(2*12)       # offset of saved fp2 (not used)
                    340:
                    341: set FP_SCR1,           LV+80                   # fp scratch 1
                    342: set FP_SCR1_EX,        FP_SCR1+0
                    343: set FP_SCR1_SGN,       FP_SCR1+2
                    344: set FP_SCR1_HI,        FP_SCR1+4
                    345: set FP_SCR1_LO,        FP_SCR1+8
                    346:
                    347: set FP_SCR0,           LV+68                   # fp scratch 0
                    348: set FP_SCR0_EX,        FP_SCR0+0
                    349: set FP_SCR0_SGN,       FP_SCR0+2
                    350: set FP_SCR0_HI,        FP_SCR0+4
                    351: set FP_SCR0_LO,        FP_SCR0+8
                    352:
                    353: set FP_DST,            LV+56                   # fp destination operand
                    354: set FP_DST_EX,                 FP_DST+0
                    355: set FP_DST_SGN,                FP_DST+2
                    356: set FP_DST_HI,                 FP_DST+4
                    357: set FP_DST_LO,                 FP_DST+8
                    358:
                    359: set FP_SRC,            LV+44                   # fp source operand
                    360: set FP_SRC_EX,                 FP_SRC+0
                    361: set FP_SRC_SGN,                FP_SRC+2
                    362: set FP_SRC_HI,                 FP_SRC+4
                    363: set FP_SRC_LO,                 FP_SRC+8
                    364:
                    365: set USER_FPIAR,                LV+40                   # FP instr address register
                    366:
                    367: set USER_FPSR,         LV+36                   # FP status register
                    368: set FPSR_CC,           USER_FPSR+0             # FPSR condition codes
                    369: set FPSR_QBYTE,                USER_FPSR+1             # FPSR qoutient byte
                    370: set FPSR_EXCEPT,       USER_FPSR+2             # FPSR exception status byte
                    371: set FPSR_AEXCEPT,      USER_FPSR+3             # FPSR accrued exception byte
                    372:
                    373: set USER_FPCR,         LV+32                   # FP control register
                    374: set FPCR_ENABLE,       USER_FPCR+2             # FPCR exception enable
                    375: set FPCR_MODE,         USER_FPCR+3             # FPCR rounding mode control
                    376:
                    377: set L_SCR3,            LV+28                   # integer scratch 3
                    378: set L_SCR2,            LV+24                   # integer scratch 2
                    379: set L_SCR1,            LV+20                   # integer scratch 1
                    380:
                    381: set STORE_FLG,         LV+19                   # flag: operand store (ie. not fcmp/ftst)
                    382:
                    383: set EXC_TEMP2,         LV+24                   # temporary space
                    384: set EXC_TEMP,          LV+16                   # temporary space
                    385:
                    386: set DTAG,              LV+15                   # destination operand type
                    387: set STAG,              LV+14                   # source operand type
                    388:
                    389: set SPCOND_FLG,                LV+10                   # flag: special case (see below)
                    390:
                    391: set EXC_CC,            LV+8                    # saved condition codes
                    392: set EXC_EXTWPTR,       LV+4                    # saved current PC (active)
                    393: set EXC_EXTWORD,       LV+2                    # saved extension word
                    394: set EXC_CMDREG,                LV+2                    # saved extension word
                    395: set EXC_OPWORD,                LV+0                    # saved operation word
                    396:
                    397: ################################
                    398:
                    399: # Helpful macros
                    400:
                    401: set FTEMP,             0                       # offsets within an
                    402: set FTEMP_EX,          0                       # extended precision
                    403: set FTEMP_SGN,         2                       # value saved in memory.
                    404: set FTEMP_HI,          4
                    405: set FTEMP_LO,          8
                    406: set FTEMP_GRS,         12
                    407:
                    408: set LOCAL,             0                       # offsets within an
                    409: set LOCAL_EX,          0                       # extended precision
                    410: set LOCAL_SGN,         2                       # value saved in memory.
                    411: set LOCAL_HI,          4
                    412: set LOCAL_LO,          8
                    413: set LOCAL_GRS,         12
                    414:
                    415: set DST,               0                       # offsets within an
                    416: set DST_EX,            0                       # extended precision
                    417: set DST_HI,            4                       # value saved in memory.
                    418: set DST_LO,            8
                    419:
                    420: set SRC,               0                       # offsets within an
                    421: set SRC_EX,            0                       # extended precision
                    422: set SRC_HI,            4                       # value saved in memory.
                    423: set SRC_LO,            8
                    424:
                    425: set SGL_LO,            0x3f81                  # min sgl prec exponent
                    426: set SGL_HI,            0x407e                  # max sgl prec exponent
                    427: set DBL_LO,            0x3c01                  # min dbl prec exponent
                    428: set DBL_HI,            0x43fe                  # max dbl prec exponent
                    429: set EXT_LO,            0x0                     # min ext prec exponent
                    430: set EXT_HI,            0x7ffe                  # max ext prec exponent
                    431:
                    432: set EXT_BIAS,          0x3fff                  # extended precision bias
                    433: set SGL_BIAS,          0x007f                  # single precision bias
                    434: set DBL_BIAS,          0x03ff                  # double precision bias
                    435:
                    436: set NORM,              0x00                    # operand type for STAG/DTAG
                    437: set ZERO,              0x01                    # operand type for STAG/DTAG
                    438: set INF,               0x02                    # operand type for STAG/DTAG
                    439: set QNAN,              0x03                    # operand type for STAG/DTAG
                    440: set DENORM,            0x04                    # operand type for STAG/DTAG
                    441: set SNAN,              0x05                    # operand type for STAG/DTAG
                    442: set UNNORM,            0x06                    # operand type for STAG/DTAG
                    443:
                    444: ##################
                    445: # FPSR/FPCR bits #
                    446: ##################
                    447: set neg_bit,           0x3                     # negative result
                    448: set z_bit,             0x2                     # zero result
                    449: set inf_bit,           0x1                     # infinite result
                    450: set nan_bit,           0x0                     # NAN result
                    451:
                    452: set q_sn_bit,          0x7                     # sign bit of quotient byte
                    453:
                    454: set bsun_bit,          7                       # branch on unordered
                    455: set snan_bit,          6                       # signalling NAN
                    456: set operr_bit,         5                       # operand error
                    457: set ovfl_bit,          4                       # overflow
                    458: set unfl_bit,          3                       # underflow
                    459: set dz_bit,            2                       # divide by zero
                    460: set inex2_bit,         1                       # inexact result 2
                    461: set inex1_bit,         0                       # inexact result 1
                    462:
                    463: set aiop_bit,          7                       # accrued inexact operation bit
                    464: set aovfl_bit,         6                       # accrued overflow bit
                    465: set aunfl_bit,         5                       # accrued underflow bit
                    466: set adz_bit,           4                       # accrued dz bit
                    467: set ainex_bit,         3                       # accrued inexact bit
                    468:
                    469: #############################
                    470: # FPSR individual bit masks #
                    471: #############################
                    472: set neg_mask,          0x08000000              # negative bit mask (lw)
                    473: set inf_mask,          0x02000000              # infinity bit mask (lw)
                    474: set z_mask,            0x04000000              # zero bit mask (lw)
                    475: set nan_mask,          0x01000000              # nan bit mask (lw)
                    476:
                    477: set neg_bmask,         0x08                    # negative bit mask (byte)
                    478: set inf_bmask,         0x02                    # infinity bit mask (byte)
                    479: set z_bmask,           0x04                    # zero bit mask (byte)
                    480: set nan_bmask,         0x01                    # nan bit mask (byte)
                    481:
                    482: set bsun_mask,         0x00008000              # bsun exception mask
                    483: set snan_mask,         0x00004000              # snan exception mask
                    484: set operr_mask,                0x00002000              # operr exception mask
                    485: set ovfl_mask,         0x00001000              # overflow exception mask
                    486: set unfl_mask,         0x00000800              # underflow exception mask
                    487: set dz_mask,           0x00000400              # dz exception mask
                    488: set inex2_mask,                0x00000200              # inex2 exception mask
                    489: set inex1_mask,                0x00000100              # inex1 exception mask
                    490:
                    491: set aiop_mask,         0x00000080              # accrued illegal operation
                    492: set aovfl_mask,                0x00000040              # accrued overflow
                    493: set aunfl_mask,                0x00000020              # accrued underflow
                    494: set adz_mask,          0x00000010              # accrued divide by zero
                    495: set ainex_mask,                0x00000008              # accrued inexact
                    496:
                    497: ######################################
                    498: # FPSR combinations used in the FPSP #
                    499: ######################################
                    500: set dzinf_mask,                inf_mask+dz_mask+adz_mask
                    501: set opnan_mask,                nan_mask+operr_mask+aiop_mask
                    502: set nzi_mask,          0x01ffffff              #clears N, Z, and I
                    503: set unfinx_mask,       unfl_mask+inex2_mask+aunfl_mask+ainex_mask
                    504: set unf2inx_mask,      unfl_mask+inex2_mask+ainex_mask
                    505: set ovfinx_mask,       ovfl_mask+inex2_mask+aovfl_mask+ainex_mask
                    506: set inx1a_mask,                inex1_mask+ainex_mask
                    507: set inx2a_mask,                inex2_mask+ainex_mask
                    508: set snaniop_mask,      nan_mask+snan_mask+aiop_mask
                    509: set snaniop2_mask,     snan_mask+aiop_mask
                    510: set naniop_mask,       nan_mask+aiop_mask
                    511: set neginf_mask,       neg_mask+inf_mask
                    512: set infaiop_mask,      inf_mask+aiop_mask
                    513: set negz_mask,         neg_mask+z_mask
                    514: set opaop_mask,                operr_mask+aiop_mask
                    515: set unfl_inx_mask,     unfl_mask+aunfl_mask+ainex_mask
                    516: set ovfl_inx_mask,     ovfl_mask+aovfl_mask+ainex_mask
                    517:
                    518: #########
                    519: # misc. #
                    520: #########
                    521: set rnd_stky_bit,      29                      # stky bit pos in longword
                    522:
                    523: set sign_bit,          0x7                     # sign bit
                    524: set signan_bit,                0x6                     # signalling nan bit
                    525:
                    526: set sgl_thresh,                0x3f81                  # minimum sgl exponent
                    527: set dbl_thresh,                0x3c01                  # minimum dbl exponent
                    528:
                    529: set x_mode,            0x0                     # extended precision
                    530: set s_mode,            0x4                     # single precision
                    531: set d_mode,            0x8                     # double precision
                    532:
                    533: set rn_mode,           0x0                     # round-to-nearest
                    534: set rz_mode,           0x1                     # round-to-zero
                    535: set rm_mode,           0x2                     # round-tp-minus-infinity
                    536: set rp_mode,           0x3                     # round-to-plus-infinity
                    537:
                    538: set mantissalen,       64                      # length of mantissa in bits
                    539:
                    540: set BYTE,              1                       # len(byte) == 1 byte
                    541: set WORD,              2                       # len(word) == 2 bytes
                    542: set LONG,              4                       # len(longword) == 2 bytes
                    543:
                    544: set BSUN_VEC,          0xc0                    # bsun    vector offset
                    545: set INEX_VEC,          0xc4                    # inexact vector offset
                    546: set DZ_VEC,            0xc8                    # dz      vector offset
                    547: set UNFL_VEC,          0xcc                    # unfl    vector offset
                    548: set OPERR_VEC,         0xd0                    # operr   vector offset
                    549: set OVFL_VEC,          0xd4                    # ovfl    vector offset
                    550: set SNAN_VEC,          0xd8                    # snan    vector offset
                    551:
                    552: ###########################
                    553: # SPecial CONDition FLaGs #
                    554: ###########################
                    555: set ftrapcc_flg,       0x01                    # flag bit: ftrapcc exception
                    556: set fbsun_flg,         0x02                    # flag bit: bsun exception
                    557: set mia7_flg,          0x04                    # flag bit: (a7)+ <ea>
                    558: set mda7_flg,          0x08                    # flag bit: -(a7) <ea>
                    559: set fmovm_flg,         0x40                    # flag bit: fmovm instruction
                    560: set immed_flg,         0x80                    # flag bit: &<data> <ea>
                    561:
                    562: set ftrapcc_bit,       0x0
                    563: set fbsun_bit,         0x1
                    564: set mia7_bit,          0x2
                    565: set mda7_bit,          0x3
                    566: set immed_bit,         0x7
                    567:
                    568: ##################################
                    569: # TRANSCENDENTAL "LAST-OP" FLAGS #
                    570: ##################################
                    571: set FMUL_OP,           0x0                     # fmul instr performed last
                    572: set FDIV_OP,           0x1                     # fdiv performed last
                    573: set FADD_OP,           0x2                     # fadd performed last
                    574: set FMOV_OP,           0x3                     # fmov performed last
                    575:
                    576: #############
                    577: # CONSTANTS #
                    578: #############
                    579: T1:    long            0x40C62D38,0xD3D64634   # 16381 LOG2 LEAD
                    580: T2:    long            0x3D6F90AE,0xB1E75CC7   # 16381 LOG2 TRAIL
                    581:
                    582: PI:    long            0x40000000,0xC90FDAA2,0x2168C235,0x00000000
                    583: PIBY2: long            0x3FFF0000,0xC90FDAA2,0x2168C235,0x00000000
                    584:
                    585: TWOBYPI:
                    586:        long            0x3FE45F30,0x6DC9C883
                    587:
                    588: #########################################################################
                    589: # XDEF ****************************************************************        #
                    590: #      _fpsp_ovfl(): 060FPSP entry point for FP Overflow exception.    #
                    591: #                                                                      #
                    592: #      This handler should be the first code executed upon taking the  #
                    593: #      FP Overflow exception in an operating system.                   #
                    594: #                                                                      #
                    595: # XREF ****************************************************************        #
                    596: #      _imem_read_long() - read instruction longword                   #
                    597: #      fix_skewed_ops() - adjust src operand in fsave frame            #
                    598: #      set_tag_x() - determine optype of src/dst operands              #
                    599: #      store_fpreg() - store opclass 0 or 2 result to FP regfile       #
                    600: #      unnorm_fix() - change UNNORM operands to NORM or ZERO           #
                    601: #      load_fpn2() - load dst operand from FP regfile                  #
                    602: #      fout() - emulate an opclass 3 instruction                       #
                    603: #      tbl_unsupp - add of table of emulation routines for opclass 0,2 #
                    604: #      _fpsp_done() - "callout" for 060FPSP exit (all work done!)      #
                    605: #      _real_ovfl() - "callout" for Overflow exception enabled code    #
                    606: #      _real_inex() - "callout" for Inexact exception enabled code     #
                    607: #      _real_trace() - "callout" for Trace exception code              #
                    608: #                                                                      #
                    609: # INPUT ***************************************************************        #
                    610: #      - The system stack contains the FP Ovfl exception stack frame   #
                    611: #      - The fsave frame contains the source operand                   #
                    612: #                                                                      #
                    613: # OUTPUT **************************************************************        #
                    614: #      Overflow Exception enabled:                                     #
                    615: #      - The system stack is unchanged                                 #
                    616: #      - The fsave frame contains the adjusted src op for opclass 0,2  #
                    617: #      Overflow Exception disabled:                                    #
                    618: #      - The system stack is unchanged                                 #
                    619: #      - The "exception present" flag in the fsave frame is cleared    #
                    620: #                                                                      #
                    621: # ALGORITHM ***********************************************************        #
                    622: #      On the 060, if an FP overflow is present as the result of any   #
                    623: # instruction, the 060 will take an overflow exception whether the     #
                    624: # exception is enabled or disabled in the FPCR. For the disabled case,         #
                    625: # This handler emulates the instruction to determine what the correct  #
                    626: # default result should be for the operation. This default result is   #
                    627: # then stored in either the FP regfile, data regfile, or memory.       #
                    628: # Finally, the handler exits through the "callout" _fpsp_done()        #
                    629: # denoting that no exceptional conditions exist within the machine.    #
                    630: #      If the exception is enabled, then this handler must create the  #
                    631: # exceptional operand and plave it in the fsave state frame, and store #
                    632: # the default result (only if the instruction is opclass 3). For       #
                    633: # exceptions enabled, this handler must exit through the "callout"     #
                    634: # _real_ovfl() so that the operating system enabled overflow handler   #
                    635: # can handle this case.                                                        #
                    636: #      Two other conditions exist. First, if overflow was disabled     #
                    637: # but the inexact exception was enabled, this handler must exit        #
                    638: # through the "callout" _real_inex() regardless of whether the result  #
                    639: # was inexact.                                                         #
                    640: #      Also, in the case of an opclass three instruction where         #
                    641: # overflow was disabled and the trace exception was enabled, this      #
                    642: # handler must exit through the "callout" _real_trace().               #
                    643: #                                                                      #
                    644: #########################################################################
                    645:
                    646:        global          _fpsp_ovfl
                    647: _fpsp_ovfl:
                    648:
                    649: #$#    sub.l           &24,%sp                 # make room for src/dst
                    650:
                    651:        link.w          %a6,&-LOCAL_SIZE        # init stack frame
                    652:
                    653:        fsave           FP_SRC(%a6)             # grab the "busy" frame
                    654:
                    655:        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
                    656:        fmovm.l         %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
                    657:        fmovm.x         &0xc0,EXC_FPREGS(%a6)   # save fp0-fp1 on stack
                    658:
                    659: # the FPIAR holds the "current PC" of the faulting instruction
                    660:        mov.l           USER_FPIAR(%a6),EXC_EXTWPTR(%a6)
                    661:        mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
                    662:        addq.l          &0x4,EXC_EXTWPTR(%a6)   # incr instruction ptr
                    663:        bsr.l           _imem_read_long         # fetch the instruction words
                    664:        mov.l           %d0,EXC_OPWORD(%a6)
                    665:
                    666: ##############################################################################
                    667:
                    668:        btst            &0x5,EXC_CMDREG(%a6)    # is instr an fmove out?
                    669:        bne.w           fovfl_out
                    670:
                    671:
                    672:        lea             FP_SRC(%a6),%a0         # pass: ptr to src op
                    673:        bsr.l           fix_skewed_ops          # fix src op
                    674:
                    675: # since, I believe, only NORMs and DENORMs can come through here,
                    676: # maybe we can avoid the subroutine call.
                    677:        lea             FP_SRC(%a6),%a0         # pass: ptr to src op
                    678:        bsr.l           set_tag_x               # tag the operand type
                    679:        mov.b           %d0,STAG(%a6)           # maybe NORM,DENORM
                    680:
                    681: # bit five of the fp extension word separates the monadic and dyadic operations
                    682: # that can pass through fpsp_ovfl(). remember that fcmp, ftst, and fsincos
                    683: # will never take this exception.
                    684:        btst            &0x5,1+EXC_CMDREG(%a6)  # is operation monadic or dyadic?
                    685:        beq.b           fovfl_extract           # monadic
                    686:
                    687:        bfextu          EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg
                    688:        bsr.l           load_fpn2               # load dst into FP_DST
                    689:
                    690:        lea             FP_DST(%a6),%a0         # pass: ptr to dst op
                    691:        bsr.l           set_tag_x               # tag the operand type
                    692:        cmpi.b          %d0,&UNNORM             # is operand an UNNORM?
                    693:        bne.b           fovfl_op2_done          # no
                    694:        bsr.l           unnorm_fix              # yes; convert to NORM,DENORM,or ZERO
                    695: fovfl_op2_done:
                    696:        mov.b           %d0,DTAG(%a6)           # save dst optype tag
                    697:
                    698: fovfl_extract:
                    699:
                    700: #$#    mov.l           FP_SRC_EX(%a6),TRAP_SRCOP_EX(%a6)
                    701: #$#    mov.l           FP_SRC_HI(%a6),TRAP_SRCOP_HI(%a6)
                    702: #$#    mov.l           FP_SRC_LO(%a6),TRAP_SRCOP_LO(%a6)
                    703: #$#    mov.l           FP_DST_EX(%a6),TRAP_DSTOP_EX(%a6)
                    704: #$#    mov.l           FP_DST_HI(%a6),TRAP_DSTOP_HI(%a6)
                    705: #$#    mov.l           FP_DST_LO(%a6),TRAP_DSTOP_LO(%a6)
                    706:
                    707:        clr.l           %d0
                    708:        mov.b           FPCR_MODE(%a6),%d0      # pass rnd prec/mode
                    709:
                    710:        mov.b           1+EXC_CMDREG(%a6),%d1
                    711:        andi.w          &0x007f,%d1             # extract extension
                    712:
                    713:        andi.l          &0x00ff01ff,USER_FPSR(%a6) # zero all but accured field
                    714:
                    715:        fmov.l          &0x0,%fpcr              # zero current control regs
                    716:        fmov.l          &0x0,%fpsr
                    717:
                    718:        lea             FP_SRC(%a6),%a0
                    719:        lea             FP_DST(%a6),%a1
                    720:
                    721: # maybe we can make these entry points ONLY the OVFL entry points of each routine.
                    722:        mov.l           (tbl_unsupp.l,%pc,%d1.w*4),%d1 # fetch routine addr
                    723:        jsr             (tbl_unsupp.l,%pc,%d1.l*1)
                    724:
                    725: # the operation has been emulated. the result is in fp0.
                    726: # the EXOP, if an exception occurred, is in fp1.
                    727: # we must save the default result regardless of whether
                    728: # traps are enabled or disabled.
                    729:        bfextu          EXC_CMDREG(%a6){&6:&3},%d0
                    730:        bsr.l           store_fpreg
                    731:
                    732: # the exceptional possibilities we have left ourselves with are ONLY overflow
                    733: # and inexact. and, the inexact is such that overflow occurred and was disabled
                    734: # but inexact was enabled.
                    735:        btst            &ovfl_bit,FPCR_ENABLE(%a6)
                    736:        bne.b           fovfl_ovfl_on
                    737:
                    738:        btst            &inex2_bit,FPCR_ENABLE(%a6)
                    739:        bne.b           fovfl_inex_on
                    740:
                    741:        fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0-fp1
                    742:        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
                    743:        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
                    744:
                    745:        unlk            %a6
                    746: #$#    add.l           &24,%sp
                    747:        bra.l           _fpsp_done
                    748:
                    749: # overflow is enabled AND overflow, of course, occurred. so, we have the EXOP
                    750: # in fp1. now, simply jump to _real_ovfl()!
                    751: fovfl_ovfl_on:
                    752:        fmovm.x         &0x40,FP_SRC(%a6)       # save EXOP (fp1) to stack
                    753:
                    754:        mov.w           &0xe005,2+FP_SRC(%a6)   # save exc status
                    755:
                    756:        fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0-fp1
                    757:        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
                    758:        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
                    759:
                    760:        frestore        FP_SRC(%a6)             # do this after fmovm,other f<op>s!
                    761:
                    762:        unlk            %a6
                    763:
                    764:        bra.l           _real_ovfl
                    765:
                    766: # overflow occurred but is disabled. meanwhile, inexact is enabled. therefore,
                    767: # we must jump to real_inex().
                    768: fovfl_inex_on:
                    769:
                    770:        fmovm.x         &0x40,FP_SRC(%a6)       # save EXOP (fp1) to stack
                    771:
                    772:        mov.b           &0xc4,1+EXC_VOFF(%a6)   # vector offset = 0xc4
                    773:        mov.w           &0xe001,2+FP_SRC(%a6)   # save exc status
                    774:
                    775:        fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0-fp1
                    776:        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
                    777:        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
                    778:
                    779:        frestore        FP_SRC(%a6)             # do this after fmovm,other f<op>s!
                    780:
                    781:        unlk            %a6
                    782:
                    783:        bra.l           _real_inex
                    784:
                    785: ########################################################################
                    786: fovfl_out:
                    787:
                    788:
                    789: #$#    mov.l           FP_SRC_EX(%a6),TRAP_SRCOP_EX(%a6)
                    790: #$#    mov.l           FP_SRC_HI(%a6),TRAP_SRCOP_HI(%a6)
                    791: #$#    mov.l           FP_SRC_LO(%a6),TRAP_SRCOP_LO(%a6)
                    792:
                    793: # the src operand is definitely a NORM(!), so tag it as such
                    794:        mov.b           &NORM,STAG(%a6)         # set src optype tag
                    795:
                    796:        clr.l           %d0
                    797:        mov.b           FPCR_MODE(%a6),%d0      # pass rnd prec/mode
                    798:
                    799:        and.l           &0xffff00ff,USER_FPSR(%a6) # zero all but accured field
                    800:
                    801:        fmov.l          &0x0,%fpcr              # zero current control regs
                    802:        fmov.l          &0x0,%fpsr
                    803:
                    804:        lea             FP_SRC(%a6),%a0         # pass ptr to src operand
                    805:
                    806:        bsr.l           fout
                    807:
                    808:        btst            &ovfl_bit,FPCR_ENABLE(%a6)
                    809:        bne.w           fovfl_ovfl_on
                    810:
                    811:        btst            &inex2_bit,FPCR_ENABLE(%a6)
                    812:        bne.w           fovfl_inex_on
                    813:
                    814:        fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0-fp1
                    815:        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
                    816:        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
                    817:
                    818:        unlk            %a6
                    819: #$#    add.l           &24,%sp
                    820:
                    821:        btst            &0x7,(%sp)              # is trace on?
                    822:        beq.l           _fpsp_done              # no
                    823:
                    824:        fmov.l          %fpiar,0x8(%sp)         # "Current PC" is in FPIAR
                    825:        mov.w           &0x2024,0x6(%sp)        # stk fmt = 0x2; voff = 0x024
                    826:        bra.l           _real_trace
                    827:
                    828: #########################################################################
                    829: # XDEF ****************************************************************        #
                    830: #      _fpsp_unfl(): 060FPSP entry point for FP Underflow exception.   #
                    831: #                                                                      #
                    832: #      This handler should be the first code executed upon taking the  #
                    833: #      FP Underflow exception in an operating system.                  #
                    834: #                                                                      #
                    835: # XREF ****************************************************************        #
                    836: #      _imem_read_long() - read instruction longword                   #
                    837: #      fix_skewed_ops() - adjust src operand in fsave frame            #
                    838: #      set_tag_x() - determine optype of src/dst operands              #
                    839: #      store_fpreg() - store opclass 0 or 2 result to FP regfile       #
                    840: #      unnorm_fix() - change UNNORM operands to NORM or ZERO           #
                    841: #      load_fpn2() - load dst operand from FP regfile                  #
                    842: #      fout() - emulate an opclass 3 instruction                       #
                    843: #      tbl_unsupp - add of table of emulation routines for opclass 0,2 #
                    844: #      _fpsp_done() - "callout" for 060FPSP exit (all work done!)      #
                    845: #      _real_ovfl() - "callout" for Overflow exception enabled code    #
                    846: #      _real_inex() - "callout" for Inexact exception enabled code     #
                    847: #      _real_trace() - "callout" for Trace exception code              #
                    848: #                                                                      #
                    849: # INPUT ***************************************************************        #
                    850: #      - The system stack contains the FP Unfl exception stack frame   #
                    851: #      - The fsave frame contains the source operand                   #
                    852: #                                                                      #
                    853: # OUTPUT **************************************************************        #
                    854: #      Underflow Exception enabled:                                    #
                    855: #      - The system stack is unchanged                                 #
                    856: #      - The fsave frame contains the adjusted src op for opclass 0,2  #
                    857: #      Underflow Exception disabled:                                   #
                    858: #      - The system stack is unchanged                                 #
                    859: #      - The "exception present" flag in the fsave frame is cleared    #
                    860: #                                                                      #
                    861: # ALGORITHM ***********************************************************        #
                    862: #      On the 060, if an FP underflow is present as the result of any  #
                    863: # instruction, the 060 will take an underflow exception whether the    #
                    864: # exception is enabled or disabled in the FPCR. For the disabled case,         #
                    865: # This handler emulates the instruction to determine what the correct  #
                    866: # default result should be for the operation. This default result is   #
                    867: # then stored in either the FP regfile, data regfile, or memory.       #
                    868: # Finally, the handler exits through the "callout" _fpsp_done()        #
                    869: # denoting that no exceptional conditions exist within the machine.    #
                    870: #      If the exception is enabled, then this handler must create the  #
                    871: # exceptional operand and plave it in the fsave state frame, and store #
                    872: # the default result (only if the instruction is opclass 3). For       #
                    873: # exceptions enabled, this handler must exit through the "callout"     #
                    874: # _real_unfl() so that the operating system enabled overflow handler   #
                    875: # can handle this case.                                                        #
                    876: #      Two other conditions exist. First, if underflow was disabled    #
                    877: # but the inexact exception was enabled and the result was inexact,    #
                    878: # this handler must exit through the "callout" _real_inex().           #
                    879: # was inexact.                                                         #
                    880: #      Also, in the case of an opclass three instruction where         #
                    881: # underflow was disabled and the trace exception was enabled, this     #
                    882: # handler must exit through the "callout" _real_trace().               #
                    883: #                                                                      #
                    884: #########################################################################
                    885:
                    886:        global          _fpsp_unfl
                    887: _fpsp_unfl:
                    888:
                    889: #$#    sub.l           &24,%sp                 # make room for src/dst
                    890:
                    891:        link.w          %a6,&-LOCAL_SIZE        # init stack frame
                    892:
                    893:        fsave           FP_SRC(%a6)             # grab the "busy" frame
                    894:
                    895:        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
                    896:        fmovm.l         %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
                    897:        fmovm.x         &0xc0,EXC_FPREGS(%a6)   # save fp0-fp1 on stack
                    898:
                    899: # the FPIAR holds the "current PC" of the faulting instruction
                    900:        mov.l           USER_FPIAR(%a6),EXC_EXTWPTR(%a6)
                    901:        mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
                    902:        addq.l          &0x4,EXC_EXTWPTR(%a6)   # incr instruction ptr
                    903:        bsr.l           _imem_read_long         # fetch the instruction words
                    904:        mov.l           %d0,EXC_OPWORD(%a6)
                    905:
                    906: ##############################################################################
                    907:
                    908:        btst            &0x5,EXC_CMDREG(%a6)    # is instr an fmove out?
                    909:        bne.w           funfl_out
                    910:
                    911:
                    912:        lea             FP_SRC(%a6),%a0         # pass: ptr to src op
                    913:        bsr.l           fix_skewed_ops          # fix src op
                    914:
                    915:        lea             FP_SRC(%a6),%a0         # pass: ptr to src op
                    916:        bsr.l           set_tag_x               # tag the operand type
                    917:        mov.b           %d0,STAG(%a6)           # maybe NORM,DENORM
                    918:
                    919: # bit five of the fp ext word separates the monadic and dyadic operations
                    920: # that can pass through fpsp_unfl(). remember that fcmp, and ftst
                    921: # will never take this exception.
                    922:        btst            &0x5,1+EXC_CMDREG(%a6)  # is op monadic or dyadic?
                    923:        beq.b           funfl_extract           # monadic
                    924:
                    925: # now, what's left that's not dyadic is fsincos. we can distinguish it
                    926: # from all dyadics by the '0110xxx pattern
                    927:        btst            &0x4,1+EXC_CMDREG(%a6)  # is op an fsincos?
                    928:        bne.b           funfl_extract           # yes
                    929:
                    930:        bfextu          EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg
                    931:        bsr.l           load_fpn2               # load dst into FP_DST
                    932:
                    933:        lea             FP_DST(%a6),%a0         # pass: ptr to dst op
                    934:        bsr.l           set_tag_x               # tag the operand type
                    935:        cmpi.b          %d0,&UNNORM             # is operand an UNNORM?
                    936:        bne.b           funfl_op2_done          # no
                    937:        bsr.l           unnorm_fix              # yes; convert to NORM,DENORM,or ZERO
                    938: funfl_op2_done:
                    939:        mov.b           %d0,DTAG(%a6)           # save dst optype tag
                    940:
                    941: funfl_extract:
                    942:
                    943: #$#    mov.l           FP_SRC_EX(%a6),TRAP_SRCOP_EX(%a6)
                    944: #$#    mov.l           FP_SRC_HI(%a6),TRAP_SRCOP_HI(%a6)
                    945: #$#    mov.l           FP_SRC_LO(%a6),TRAP_SRCOP_LO(%a6)
                    946: #$#    mov.l           FP_DST_EX(%a6),TRAP_DSTOP_EX(%a6)
                    947: #$#    mov.l           FP_DST_HI(%a6),TRAP_DSTOP_HI(%a6)
                    948: #$#    mov.l           FP_DST_LO(%a6),TRAP_DSTOP_LO(%a6)
                    949:
                    950:        clr.l           %d0
                    951:        mov.b           FPCR_MODE(%a6),%d0      # pass rnd prec/mode
                    952:
                    953:        mov.b           1+EXC_CMDREG(%a6),%d1
                    954:        andi.w          &0x007f,%d1             # extract extension
                    955:
                    956:        andi.l          &0x00ff01ff,USER_FPSR(%a6)
                    957:
                    958:        fmov.l          &0x0,%fpcr              # zero current control regs
                    959:        fmov.l          &0x0,%fpsr
                    960:
                    961:        lea             FP_SRC(%a6),%a0
                    962:        lea             FP_DST(%a6),%a1
                    963:
                    964: # maybe we can make these entry points ONLY the OVFL entry points of each routine.
                    965:        mov.l           (tbl_unsupp.l,%pc,%d1.w*4),%d1 # fetch routine addr
                    966:        jsr             (tbl_unsupp.l,%pc,%d1.l*1)
                    967:
                    968:        bfextu          EXC_CMDREG(%a6){&6:&3},%d0
                    969:        bsr.l           store_fpreg
                    970:
                    971: # The `060 FPU multiplier hardware is such that if the result of a
                    972: # multiply operation is the smallest possible normalized number
                    973: # (0x00000000_80000000_00000000), then the machine will take an
                    974: # underflow exception. Since this is incorrect, we need to check
                    975: # if our emulation, after re-doing the operation, decided that
                    976: # no underflow was called for. We do these checks only in
                    977: # funfl_{unfl,inex}_on() because w/ both exceptions disabled, this
                    978: # special case will simply exit gracefully with the correct result.
                    979:
                    980: # the exceptional possibilities we have left ourselves with are ONLY overflow
                    981: # and inexact. and, the inexact is such that overflow occurred and was disabled
                    982: # but inexact was enabled.
                    983:        btst            &unfl_bit,FPCR_ENABLE(%a6)
                    984:        bne.b           funfl_unfl_on
                    985:
                    986: funfl_chkinex:
                    987:        btst            &inex2_bit,FPCR_ENABLE(%a6)
                    988:        bne.b           funfl_inex_on
                    989:
                    990: funfl_exit:
                    991:        fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0-fp1
                    992:        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
                    993:        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
                    994:
                    995:        unlk            %a6
                    996: #$#    add.l           &24,%sp
                    997:        bra.l           _fpsp_done
                    998:
                    999: # overflow is enabled AND overflow, of course, occurred. so, we have the EXOP
                   1000: # in fp1 (don't forget to save fp0). what to do now?
                   1001: # well, we simply have to get to go to _real_unfl()!
                   1002: funfl_unfl_on:
                   1003:
                   1004: # The `060 FPU multiplier hardware is such that if the result of a
                   1005: # multiply operation is the smallest possible normalized number
                   1006: # (0x00000000_80000000_00000000), then the machine will take an
                   1007: # underflow exception. Since this is incorrect, we check here to see
                   1008: # if our emulation, after re-doing the operation, decided that
                   1009: # no underflow was called for.
                   1010:        btst            &unfl_bit,FPSR_EXCEPT(%a6)
                   1011:        beq.w           funfl_chkinex
                   1012:
                   1013: funfl_unfl_on2:
                   1014:        fmovm.x         &0x40,FP_SRC(%a6)       # save EXOP (fp1) to stack
                   1015:
                   1016:        mov.w           &0xe003,2+FP_SRC(%a6)   # save exc status
                   1017:
                   1018:        fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0-fp1
                   1019:        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
                   1020:        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
                   1021:
                   1022:        frestore        FP_SRC(%a6)             # do this after fmovm,other f<op>s!
                   1023:
                   1024:        unlk            %a6
                   1025:
                   1026:        bra.l           _real_unfl
                   1027:
                   1028: # undeflow occurred but is disabled. meanwhile, inexact is enabled. therefore,
                   1029: # we must jump to real_inex().
                   1030: funfl_inex_on:
                   1031:
                   1032: # The `060 FPU multiplier hardware is such that if the result of a
                   1033: # multiply operation is the smallest possible normalized number
                   1034: # (0x00000000_80000000_00000000), then the machine will take an
                   1035: # underflow exception.
                   1036: # But, whether bogus or not, if inexact is enabled AND it occurred,
                   1037: # then we have to branch to real_inex.
                   1038:
                   1039:        btst            &inex2_bit,FPSR_EXCEPT(%a6)
                   1040:        beq.w           funfl_exit
                   1041:
                   1042: funfl_inex_on2:
                   1043:
                   1044:        fmovm.x         &0x40,FP_SRC(%a6)       # save EXOP to stack
                   1045:
                   1046:        mov.b           &0xc4,1+EXC_VOFF(%a6)   # vector offset = 0xc4
                   1047:        mov.w           &0xe001,2+FP_SRC(%a6)   # save exc status
                   1048:
                   1049:        fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0-fp1
                   1050:        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
                   1051:        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
                   1052:
                   1053:        frestore        FP_SRC(%a6)             # do this after fmovm,other f<op>s!
                   1054:
                   1055:        unlk            %a6
                   1056:
                   1057:        bra.l           _real_inex
                   1058:
                   1059: #######################################################################
                   1060: funfl_out:
                   1061:
                   1062:
                   1063: #$#    mov.l           FP_SRC_EX(%a6),TRAP_SRCOP_EX(%a6)
                   1064: #$#    mov.l           FP_SRC_HI(%a6),TRAP_SRCOP_HI(%a6)
                   1065: #$#    mov.l           FP_SRC_LO(%a6),TRAP_SRCOP_LO(%a6)
                   1066:
                   1067: # the src operand is definitely a NORM(!), so tag it as such
                   1068:        mov.b           &NORM,STAG(%a6)         # set src optype tag
                   1069:
                   1070:        clr.l           %d0
                   1071:        mov.b           FPCR_MODE(%a6),%d0      # pass rnd prec/mode
                   1072:
                   1073:        and.l           &0xffff00ff,USER_FPSR(%a6) # zero all but accured field
                   1074:
                   1075:        fmov.l          &0x0,%fpcr              # zero current control regs
                   1076:        fmov.l          &0x0,%fpsr
                   1077:
                   1078:        lea             FP_SRC(%a6),%a0         # pass ptr to src operand
                   1079:
                   1080:        bsr.l           fout
                   1081:
                   1082:        btst            &unfl_bit,FPCR_ENABLE(%a6)
                   1083:        bne.w           funfl_unfl_on2
                   1084:
                   1085:        btst            &inex2_bit,FPCR_ENABLE(%a6)
                   1086:        bne.w           funfl_inex_on2
                   1087:
                   1088:        fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0-fp1
                   1089:        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
                   1090:        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
                   1091:
                   1092:        unlk            %a6
                   1093: #$#    add.l           &24,%sp
                   1094:
                   1095:        btst            &0x7,(%sp)              # is trace on?
                   1096:        beq.l           _fpsp_done              # no
                   1097:
                   1098:        fmov.l          %fpiar,0x8(%sp)         # "Current PC" is in FPIAR
                   1099:        mov.w           &0x2024,0x6(%sp)        # stk fmt = 0x2; voff = 0x024
                   1100:        bra.l           _real_trace
                   1101:
                   1102: #########################################################################
                   1103: # XDEF ****************************************************************        #
                   1104: #      _fpsp_unsupp(): 060FPSP entry point for FP "Unimplemented       #
                   1105: #                      Data Type" exception.                           #
                   1106: #                                                                      #
                   1107: #      This handler should be the first code executed upon taking the  #
                   1108: #      FP Unimplemented Data Type exception in an operating system.    #
                   1109: #                                                                      #
                   1110: # XREF ****************************************************************        #
                   1111: #      _imem_read_{word,long}() - read instruction word/longword       #
                   1112: #      fix_skewed_ops() - adjust src operand in fsave frame            #
                   1113: #      set_tag_x() - determine optype of src/dst operands              #
                   1114: #      store_fpreg() - store opclass 0 or 2 result to FP regfile       #
                   1115: #      unnorm_fix() - change UNNORM operands to NORM or ZERO           #
                   1116: #      load_fpn2() - load dst operand from FP regfile                  #
                   1117: #      load_fpn1() - load src operand from FP regfile                  #
                   1118: #      fout() - emulate an opclass 3 instruction                       #
                   1119: #      tbl_unsupp - add of table of emulation routines for opclass 0,2 #
                   1120: #      _real_inex() - "callout" to operating system inexact handler    #
                   1121: #      _fpsp_done() - "callout" for exit; work all done                #
                   1122: #      _real_trace() - "callout" for Trace enabled exception           #
                   1123: #      funimp_skew() - adjust fsave src ops to "incorrect" value       #
                   1124: #      _real_snan() - "callout" for SNAN exception                     #
                   1125: #      _real_operr() - "callout" for OPERR exception                   #
                   1126: #      _real_ovfl() - "callout" for OVFL exception                     #
                   1127: #      _real_unfl() - "callout" for UNFL exception                     #
                   1128: #      get_packed() - fetch packed operand from memory                 #
                   1129: #                                                                      #
                   1130: # INPUT ***************************************************************        #
                   1131: #      - The system stack contains the "Unimp Data Type" stk frame     #
                   1132: #      - The fsave frame contains the ssrc op (for UNNORM/DENORM)      #
                   1133: #                                                                      #
                   1134: # OUTPUT **************************************************************        #
                   1135: #      If Inexact exception (opclass 3):                               #
                   1136: #      - The system stack is changed to an Inexact exception stk frame #
                   1137: #      If SNAN exception (opclass 3):                                  #
                   1138: #      - The system stack is changed to an SNAN exception stk frame    #
                   1139: #      If OPERR exception (opclass 3):                                 #
                   1140: #      - The system stack is changed to an OPERR exception stk frame   #
                   1141: #      If OVFL exception (opclass 3):                                  #
                   1142: #      - The system stack is changed to an OVFL exception stk frame    #
                   1143: #      If UNFL exception (opclass 3):                                  #
                   1144: #      - The system stack is changed to an UNFL exception stack frame  #
                   1145: #      If Trace exception enabled:                                     #
                   1146: #      - The system stack is changed to a Trace exception stack frame  #
                   1147: #      Else: (normal case)                                             #
                   1148: #      - Correct result has been stored as appropriate                 #
                   1149: #                                                                      #
                   1150: # ALGORITHM ***********************************************************        #
                   1151: #      Two main instruction types can enter here: (1) DENORM or UNNORM #
                   1152: # unimplemented data types. These can be either opclass 0,2 or 3       #
                   1153: # instructions, and (2) PACKED unimplemented data format instructions  #
                   1154: # also of opclasses 0,2, or 3.                                         #
                   1155: #      For UNNORM/DENORM opclass 0 and 2, the handler fetches the src  #
                   1156: # operand from the fsave state frame and the dst operand (if dyadic)   #
                   1157: # from the FP register file. The instruction is then emulated by       #
                   1158: # choosing an emulation routine from a table of routines indexed by    #
                   1159: # instruction type. Once the instruction has been emulated and result  #
                   1160: # saved, then we check to see if any enabled exceptions resulted from  #
                   1161: # instruction emulation. If none, then we exit through the "callout"   #
                   1162: # _fpsp_done(). If there is an enabled FP exception, then we insert    #
                   1163: # this exception into the FPU in the fsave state frame and then exit   #
                   1164: # through _fpsp_done().                                                        #
                   1165: #      PACKED opclass 0 and 2 is similar in how the instruction is     #
                   1166: # emulated and exceptions handled. The differences occur in how the    #
                   1167: # handler loads the packed op (by calling get_packed() routine) and    #
                   1168: # by the fact that a Trace exception could be pending for PACKED ops.  #
                   1169: # If a Trace exception is pending, then the current exception stack    #
                   1170: # frame is changed to a Trace exception stack frame and an exit is     #
                   1171: # made through _real_trace().                                          #
                   1172: #      For UNNORM/DENORM opclass 3, the actual move out to memory is   #
                   1173: # performed by calling the routine fout(). If no exception should occur        #
                   1174: # as the result of emulation, then an exit either occurs through       #
                   1175: # _fpsp_done() or through _real_trace() if a Trace exception is pending        #
                   1176: # (a Trace stack frame must be created here, too). If an FP exception  #
                   1177: # should occur, then we must create an exception stack frame of that   #
                   1178: # type and jump to either _real_snan(), _real_operr(), _real_inex(),   #
                   1179: # _real_unfl(), or _real_ovfl() as appropriate. PACKED opclass 3       #
                   1180: # emulation is performed in a similar manner.                          #
                   1181: #                                                                      #
                   1182: #########################################################################
                   1183:
                   1184: #
                   1185: # (1) DENORM and UNNORM (unimplemented) data types:
                   1186: #
                   1187: #                              post-instruction
                   1188: #                              *****************
                   1189: #                              *      EA       *
                   1190: #       pre-instruction        *               *
                   1191: #      *****************       *****************
                   1192: #      * 0x0 *  0x0dc  *       * 0x3 *  0x0dc  *
                   1193: #      *****************       *****************
                   1194: #      *     Next      *       *     Next      *
                   1195: #      *      PC       *       *      PC       *
                   1196: #      *****************       *****************
                   1197: #      *      SR       *       *      SR       *
                   1198: #      *****************       *****************
                   1199: #
                   1200: # (2) PACKED format (unsupported) opclasses two and three:
                   1201: #      *****************
                   1202: #      *      EA       *
                   1203: #      *               *
                   1204: #      *****************
                   1205: #      * 0x2 *  0x0dc  *
                   1206: #      *****************
                   1207: #      *     Next      *
                   1208: #      *      PC       *
                   1209: #      *****************
                   1210: #      *      SR       *
                   1211: #      *****************
                   1212: #
                   1213:        global          _fpsp_unsupp
                   1214: _fpsp_unsupp:
                   1215:
                   1216:        link.w          %a6,&-LOCAL_SIZE        # init stack frame
                   1217:
                   1218:        fsave           FP_SRC(%a6)             # save fp state
                   1219:
                   1220:        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
                   1221:        fmovm.l         %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
                   1222:        fmovm.x         &0xc0,EXC_FPREGS(%a6)   # save fp0-fp1 on stack
                   1223:
                   1224:        btst            &0x5,EXC_SR(%a6)        # user or supervisor mode?
                   1225:        bne.b           fu_s
                   1226: fu_u:
                   1227:        mov.l           %usp,%a0                # fetch user stack pointer
                   1228:        mov.l           %a0,EXC_A7(%a6)         # save on stack
                   1229:        bra.b           fu_cont
                   1230: # if the exception is an opclass zero or two unimplemented data type
                   1231: # exception, then the a7' calculated here is wrong since it doesn't
                   1232: # stack an ea. however, we don't need an a7' for this case anyways.
                   1233: fu_s:
                   1234:        lea             0x4+EXC_EA(%a6),%a0     # load old a7'
                   1235:        mov.l           %a0,EXC_A7(%a6)         # save on stack
                   1236:
                   1237: fu_cont:
                   1238:
                   1239: # the FPIAR holds the "current PC" of the faulting instruction
                   1240: # the FPIAR should be set correctly for ALL exceptions passing through
                   1241: # this point.
                   1242:        mov.l           USER_FPIAR(%a6),EXC_EXTWPTR(%a6)
                   1243:        mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
                   1244:        addq.l          &0x4,EXC_EXTWPTR(%a6)   # incr instruction ptr
                   1245:        bsr.l           _imem_read_long         # fetch the instruction words
                   1246:        mov.l           %d0,EXC_OPWORD(%a6)     # store OPWORD and EXTWORD
                   1247:
                   1248: ############################
                   1249:
                   1250:        clr.b           SPCOND_FLG(%a6)         # clear special condition flag
                   1251:
                   1252: # Separate opclass three (fpn-to-mem) ops since they have a different
                   1253: # stack frame and protocol.
                   1254:        btst            &0x5,EXC_CMDREG(%a6)    # is it an fmove out?
                   1255:        bne.w           fu_out                  # yes
                   1256:
                   1257: # Separate packed opclass two instructions.
                   1258:        bfextu          EXC_CMDREG(%a6){&0:&6},%d0
                   1259:        cmpi.b          %d0,&0x13
                   1260:        beq.w           fu_in_pack
                   1261:
                   1262:
                   1263: # I'm not sure at this point what FPSR bits are valid for this instruction.
                   1264: # so, since the emulation routines re-create them anyways, zero exception field
                   1265:        andi.l          &0x00ff00ff,USER_FPSR(%a6) # zero exception field
                   1266:
                   1267:        fmov.l          &0x0,%fpcr              # zero current control regs
                   1268:        fmov.l          &0x0,%fpsr
                   1269:
                   1270: # Opclass two w/ memory-to-fpn operation will have an incorrect extended
                   1271: # precision format if the src format was single or double and the
                   1272: # source data type was an INF, NAN, DENORM, or UNNORM
                   1273:        lea             FP_SRC(%a6),%a0         # pass ptr to input
                   1274:        bsr.l           fix_skewed_ops
                   1275:
                   1276: # we don't know whether the src operand or the dst operand (or both) is the
                   1277: # UNNORM or DENORM. call the function that tags the operand type. if the
                   1278: # input is an UNNORM, then convert it to a NORM, DENORM, or ZERO.
                   1279:        lea             FP_SRC(%a6),%a0         # pass: ptr to src op
                   1280:        bsr.l           set_tag_x               # tag the operand type
                   1281:        cmpi.b          %d0,&UNNORM             # is operand an UNNORM?
                   1282:        bne.b           fu_op2                  # no
                   1283:        bsr.l           unnorm_fix              # yes; convert to NORM,DENORM,or ZERO
                   1284:
                   1285: fu_op2:
                   1286:        mov.b           %d0,STAG(%a6)           # save src optype tag
                   1287:
                   1288:        bfextu          EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg
                   1289:
                   1290: # bit five of the fp extension word separates the monadic and dyadic operations
                   1291: # at this point
                   1292:        btst            &0x5,1+EXC_CMDREG(%a6)  # is operation monadic or dyadic?
                   1293:        beq.b           fu_extract              # monadic
                   1294:        cmpi.b          1+EXC_CMDREG(%a6),&0x3a # is operation an ftst?
                   1295:        beq.b           fu_extract              # yes, so it's monadic, too
                   1296:
                   1297:        bsr.l           load_fpn2               # load dst into FP_DST
                   1298:
                   1299:        lea             FP_DST(%a6),%a0         # pass: ptr to dst op
                   1300:        bsr.l           set_tag_x               # tag the operand type
                   1301:        cmpi.b          %d0,&UNNORM             # is operand an UNNORM?
                   1302:        bne.b           fu_op2_done             # no
                   1303:        bsr.l           unnorm_fix              # yes; convert to NORM,DENORM,or ZERO
                   1304: fu_op2_done:
                   1305:        mov.b           %d0,DTAG(%a6)           # save dst optype tag
                   1306:
                   1307: fu_extract:
                   1308:        clr.l           %d0
                   1309:        mov.b           FPCR_MODE(%a6),%d0      # fetch rnd mode/prec
                   1310:
                   1311:        bfextu          1+EXC_CMDREG(%a6){&1:&7},%d1 # extract extension
                   1312:
                   1313:        lea             FP_SRC(%a6),%a0
                   1314:        lea             FP_DST(%a6),%a1
                   1315:
                   1316:        mov.l           (tbl_unsupp.l,%pc,%d1.l*4),%d1 # fetch routine addr
                   1317:        jsr             (tbl_unsupp.l,%pc,%d1.l*1)
                   1318:
                   1319: #
                   1320: # Exceptions in order of precedence:
                   1321: #      BSUN    : none
                   1322: #      SNAN    : all dyadic ops
                   1323: #      OPERR   : fsqrt(-NORM)
                   1324: #      OVFL    : all except ftst,fcmp
                   1325: #      UNFL    : all except ftst,fcmp
                   1326: #      DZ      : fdiv
                   1327: #      INEX2   : all except ftst,fcmp
                   1328: #      INEX1   : none (packed doesn't go through here)
                   1329: #
                   1330:
                   1331: # we determine the highest priority exception(if any) set by the
                   1332: # emulation routine that has also been enabled by the user.
                   1333:        mov.b           FPCR_ENABLE(%a6),%d0    # fetch exceptions set
                   1334:        bne.b           fu_in_ena               # some are enabled
                   1335:
                   1336: fu_in_cont:
                   1337: # fcmp and ftst do not store any result.
                   1338:        mov.b           1+EXC_CMDREG(%a6),%d0   # fetch extension
                   1339:        andi.b          &0x38,%d0               # extract bits 3-5
                   1340:        cmpi.b          %d0,&0x38               # is instr fcmp or ftst?
                   1341:        beq.b           fu_in_exit              # yes
                   1342:
                   1343:        bfextu          EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg
                   1344:        bsr.l           store_fpreg             # store the result
                   1345:
                   1346: fu_in_exit:
                   1347:
                   1348:        fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0/fp1
                   1349:        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
                   1350:        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
                   1351:
                   1352:        unlk            %a6
                   1353:
                   1354:        bra.l           _fpsp_done
                   1355:
                   1356: fu_in_ena:
                   1357:        and.b           FPSR_EXCEPT(%a6),%d0    # keep only ones enabled
                   1358:        bfffo           %d0{&24:&8},%d0         # find highest priority exception
                   1359:        bne.b           fu_in_exc               # there is at least one set
                   1360:
                   1361: #
                   1362: # No exceptions occurred that were also enabled. Now:
                   1363: #
                   1364: #      if (OVFL && ovfl_disabled && inexact_enabled) {
                   1365: #          branch to _real_inex() (even if the result was exact!);
                   1366: #      } else {
                   1367: #          save the result in the proper fp reg (unless the op is fcmp or ftst);
                   1368: #          return;
                   1369: #      }
                   1370: #
                   1371:        btst            &ovfl_bit,FPSR_EXCEPT(%a6) # was overflow set?
                   1372:        beq.b           fu_in_cont              # no
                   1373:
                   1374: fu_in_ovflchk:
                   1375:        btst            &inex2_bit,FPCR_ENABLE(%a6) # was inexact enabled?
                   1376:        beq.b           fu_in_cont              # no
                   1377:        bra.w           fu_in_exc_ovfl          # go insert overflow frame
                   1378:
                   1379: #
                   1380: # An exception occurred and that exception was enabled:
                   1381: #
                   1382: #      shift enabled exception field into lo byte of d0;
                   1383: #      if (((INEX2 || INEX1) && inex_enabled && OVFL && ovfl_disabled) ||
                   1384: #          ((INEX2 || INEX1) && inex_enabled && UNFL && unfl_disabled)) {
                   1385: #              /*
                   1386: #               * this is the case where we must call _real_inex() now or else
                   1387: #               * there will be no other way to pass it the exceptional operand
                   1388: #               */
                   1389: #              call _real_inex();
                   1390: #      } else {
                   1391: #              restore exc state (SNAN||OPERR||OVFL||UNFL||DZ||INEX) into the FPU;
                   1392: #      }
                   1393: #
                   1394: fu_in_exc:
                   1395:        subi.l          &24,%d0                 # fix offset to be 0-8
                   1396:        cmpi.b          %d0,&0x6                # is exception INEX? (6)
                   1397:        bne.b           fu_in_exc_exit          # no
                   1398:
                   1399: # the enabled exception was inexact
                   1400:        btst            &unfl_bit,FPSR_EXCEPT(%a6) # did disabled underflow occur?
                   1401:        bne.w           fu_in_exc_unfl          # yes
                   1402:        btst            &ovfl_bit,FPSR_EXCEPT(%a6) # did disabled overflow occur?
                   1403:        bne.w           fu_in_exc_ovfl          # yes
                   1404:
                   1405: # here, we insert the correct fsave status value into the fsave frame for the
                   1406: # corresponding exception. the operand in the fsave frame should be the original
                   1407: # src operand.
                   1408: fu_in_exc_exit:
                   1409:        mov.l           %d0,-(%sp)              # save d0
                   1410:        bsr.l           funimp_skew             # skew sgl or dbl inputs
                   1411:        mov.l           (%sp)+,%d0              # restore d0
                   1412:
                   1413:        mov.w           (tbl_except.b,%pc,%d0.w*2),2+FP_SRC(%a6) # create exc status
                   1414:
                   1415:        fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0/fp1
                   1416:        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
                   1417:        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
                   1418:
                   1419:        frestore        FP_SRC(%a6)             # restore src op
                   1420:
                   1421:        unlk            %a6
                   1422:
                   1423:        bra.l           _fpsp_done
                   1424:
                   1425: tbl_except:
                   1426:        short           0xe000,0xe006,0xe004,0xe005
                   1427:        short           0xe003,0xe002,0xe001,0xe001
                   1428:
                   1429: fu_in_exc_unfl:
                   1430:        mov.w           &0x4,%d0
                   1431:        bra.b           fu_in_exc_exit
                   1432: fu_in_exc_ovfl:
                   1433:        mov.w           &0x03,%d0
                   1434:        bra.b           fu_in_exc_exit
                   1435:
                   1436: # If the input operand to this operation was opclass two and a single
                   1437: # or double precision denorm, inf, or nan, the operand needs to be
                   1438: # "corrected" in order to have the proper equivalent extended precision
                   1439: # number.
                   1440:        global          fix_skewed_ops
                   1441: fix_skewed_ops:
                   1442:        bfextu          EXC_CMDREG(%a6){&0:&6},%d0 # extract opclass,src fmt
                   1443:        cmpi.b          %d0,&0x11               # is class = 2 & fmt = sgl?
                   1444:        beq.b           fso_sgl                 # yes
                   1445:        cmpi.b          %d0,&0x15               # is class = 2 & fmt = dbl?
                   1446:        beq.b           fso_dbl                 # yes
                   1447:        rts                                     # no
                   1448:
                   1449: fso_sgl:
                   1450:        mov.w           LOCAL_EX(%a0),%d0       # fetch src exponent
                   1451:        andi.w          &0x7fff,%d0             # strip sign
                   1452:        cmpi.w          %d0,&0x3f80             # is |exp| == $3f80?
                   1453:        beq.b           fso_sgl_dnrm_zero       # yes
                   1454:        cmpi.w          %d0,&0x407f             # no; is |exp| == $407f?
                   1455:        beq.b           fso_infnan              # yes
                   1456:        rts                                     # no
                   1457:
                   1458: fso_sgl_dnrm_zero:
                   1459:        andi.l          &0x7fffffff,LOCAL_HI(%a0) # clear j-bit
                   1460:        beq.b           fso_zero                # it's a skewed zero
                   1461: fso_sgl_dnrm:
                   1462: # here, we count on norm not to alter a0...
                   1463:        bsr.l           norm                    # normalize mantissa
                   1464:        neg.w           %d0                     # -shft amt
                   1465:        addi.w          &0x3f81,%d0             # adjust new exponent
                   1466:        andi.w          &0x8000,LOCAL_EX(%a0)   # clear old exponent
                   1467:        or.w            %d0,LOCAL_EX(%a0)       # insert new exponent
                   1468:        rts
                   1469:
                   1470: fso_zero:
                   1471:        andi.w          &0x8000,LOCAL_EX(%a0)   # clear bogus exponent
                   1472:        rts
                   1473:
                   1474: fso_infnan:
                   1475:        andi.b          &0x7f,LOCAL_HI(%a0)     # clear j-bit
                   1476:        ori.w           &0x7fff,LOCAL_EX(%a0)   # make exponent = $7fff
                   1477:        rts
                   1478:
                   1479: fso_dbl:
                   1480:        mov.w           LOCAL_EX(%a0),%d0       # fetch src exponent
                   1481:        andi.w          &0x7fff,%d0             # strip sign
                   1482:        cmpi.w          %d0,&0x3c00             # is |exp| == $3c00?
                   1483:        beq.b           fso_dbl_dnrm_zero       # yes
                   1484:        cmpi.w          %d0,&0x43ff             # no; is |exp| == $43ff?
                   1485:        beq.b           fso_infnan              # yes
                   1486:        rts                                     # no
                   1487:
                   1488: fso_dbl_dnrm_zero:
                   1489:        andi.l          &0x7fffffff,LOCAL_HI(%a0) # clear j-bit
                   1490:        bne.b           fso_dbl_dnrm            # it's a skewed denorm
                   1491:        tst.l           LOCAL_LO(%a0)           # is it a zero?
                   1492:        beq.b           fso_zero                # yes
                   1493: fso_dbl_dnrm:
                   1494: # here, we count on norm not to alter a0...
                   1495:        bsr.l           norm                    # normalize mantissa
                   1496:        neg.w           %d0                     # -shft amt
                   1497:        addi.w          &0x3c01,%d0             # adjust new exponent
                   1498:        andi.w          &0x8000,LOCAL_EX(%a0)   # clear old exponent
                   1499:        or.w            %d0,LOCAL_EX(%a0)       # insert new exponent
                   1500:        rts
                   1501:
                   1502: #################################################################
                   1503:
                   1504: # fmove out took an unimplemented data type exception.
                   1505: # the src operand is in FP_SRC. Call _fout() to write out the result and
                   1506: # to determine which exceptions, if any, to take.
                   1507: fu_out:
                   1508:
                   1509: # Separate packed move outs from the UNNORM and DENORM move outs.
                   1510:        bfextu          EXC_CMDREG(%a6){&3:&3},%d0
                   1511:        cmpi.b          %d0,&0x3
                   1512:        beq.w           fu_out_pack
                   1513:        cmpi.b          %d0,&0x7
                   1514:        beq.w           fu_out_pack
                   1515:
                   1516:
                   1517: # I'm not sure at this point what FPSR bits are valid for this instruction.
                   1518: # so, since the emulation routines re-create them anyways, zero exception field.
                   1519: # fmove out doesn't affect ccodes.
                   1520:        and.l           &0xffff00ff,USER_FPSR(%a6) # zero exception field
                   1521:
                   1522:        fmov.l          &0x0,%fpcr              # zero current control regs
                   1523:        fmov.l          &0x0,%fpsr
                   1524:
                   1525: # the src can ONLY be a DENORM or an UNNORM! so, don't make any big subroutine
                   1526: # call here. just figure out what it is...
                   1527:        mov.w           FP_SRC_EX(%a6),%d0      # get exponent
                   1528:        andi.w          &0x7fff,%d0             # strip sign
                   1529:        beq.b           fu_out_denorm           # it's a DENORM
                   1530:
                   1531:        lea             FP_SRC(%a6),%a0
                   1532:        bsr.l           unnorm_fix              # yes; fix it
                   1533:
                   1534:        mov.b           %d0,STAG(%a6)
                   1535:
                   1536:        bra.b           fu_out_cont
                   1537: fu_out_denorm:
                   1538:        mov.b           &DENORM,STAG(%a6)
                   1539: fu_out_cont:
                   1540:
                   1541:        clr.l           %d0
                   1542:        mov.b           FPCR_MODE(%a6),%d0      # fetch rnd mode/prec
                   1543:
                   1544:        lea             FP_SRC(%a6),%a0         # pass ptr to src operand
                   1545:
                   1546:        mov.l           (%a6),EXC_A6(%a6)       # in case a6 changes
                   1547:        bsr.l           fout                    # call fmove out routine
                   1548:
                   1549: # Exceptions in order of precedence:
                   1550: #      BSUN    : none
                   1551: #      SNAN    : none
                   1552: #      OPERR   : fmove.{b,w,l} out of large UNNORM
                   1553: #      OVFL    : fmove.{s,d}
                   1554: #      UNFL    : fmove.{s,d,x}
                   1555: #      DZ      : none
                   1556: #      INEX2   : all
                   1557: #      INEX1   : none (packed doesn't travel through here)
                   1558:
                   1559: # determine the highest priority exception(if any) set by the
                   1560: # emulation routine that has also been enabled by the user.
                   1561:        mov.b           FPCR_ENABLE(%a6),%d0    # fetch exceptions enabled
                   1562:        bne.w           fu_out_ena              # some are enabled
                   1563:
                   1564: fu_out_done:
                   1565:
                   1566:        mov.l           EXC_A6(%a6),(%a6)       # in case a6 changed
                   1567:
                   1568: # on extended precision opclass three instructions using pre-decrement or
                   1569: # post-increment addressing mode, the address register is not updated. is the
                   1570: # address register was the stack pointer used from user mode, then let's update
                   1571: # it here. if it was used from supervisor mode, then we have to handle this
                   1572: # as a special case.
                   1573:        btst            &0x5,EXC_SR(%a6)
                   1574:        bne.b           fu_out_done_s
                   1575:
                   1576:        mov.l           EXC_A7(%a6),%a0         # restore a7
                   1577:        mov.l           %a0,%usp
                   1578:
                   1579: fu_out_done_cont:
                   1580:        fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0/fp1
                   1581:        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
                   1582:        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
                   1583:
                   1584:        unlk            %a6
                   1585:
                   1586:        btst            &0x7,(%sp)              # is trace on?
                   1587:        bne.b           fu_out_trace            # yes
                   1588:
                   1589:        bra.l           _fpsp_done
                   1590:
                   1591: # is the ea mode pre-decrement of the stack pointer from supervisor mode?
                   1592: # ("fmov.x fpm,-(a7)") if so,
                   1593: fu_out_done_s:
                   1594:        cmpi.b          SPCOND_FLG(%a6),&mda7_flg
                   1595:        bne.b           fu_out_done_cont
                   1596:
                   1597: # the extended precision result is still in fp0. but, we need to save it
                   1598: # somewhere on the stack until we can copy it to its final resting place.
                   1599: # here, we're counting on the top of the stack to be the old place-holders
                   1600: # for fp0/fp1 which have already been restored. that way, we can write
                   1601: # over those destinations with the shifted stack frame.
                   1602:        fmovm.x         &0x80,FP_SRC(%a6)       # put answer on stack
                   1603:
                   1604:        fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0/fp1
                   1605:        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
                   1606:        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
                   1607:
                   1608:        mov.l           (%a6),%a6               # restore frame pointer
                   1609:
                   1610:        mov.l           LOCAL_SIZE+EXC_SR(%sp),LOCAL_SIZE+EXC_SR-0xc(%sp)
                   1611:        mov.l           LOCAL_SIZE+2+EXC_PC(%sp),LOCAL_SIZE+2+EXC_PC-0xc(%sp)
                   1612:
                   1613: # now, copy the result to the proper place on the stack
                   1614:        mov.l           LOCAL_SIZE+FP_SRC_EX(%sp),LOCAL_SIZE+EXC_SR+0x0(%sp)
                   1615:        mov.l           LOCAL_SIZE+FP_SRC_HI(%sp),LOCAL_SIZE+EXC_SR+0x4(%sp)
                   1616:        mov.l           LOCAL_SIZE+FP_SRC_LO(%sp),LOCAL_SIZE+EXC_SR+0x8(%sp)
                   1617:
                   1618:        add.l           &LOCAL_SIZE-0x8,%sp
                   1619:
                   1620:        btst            &0x7,(%sp)
                   1621:        bne.b           fu_out_trace
                   1622:
                   1623:        bra.l           _fpsp_done
                   1624:
                   1625: fu_out_ena:
                   1626:        and.b           FPSR_EXCEPT(%a6),%d0    # keep only ones enabled
                   1627:        bfffo           %d0{&24:&8},%d0         # find highest priority exception
                   1628:        bne.b           fu_out_exc              # there is at least one set
                   1629:
                   1630: # no exceptions were set.
                   1631: # if a disabled overflow occurred and inexact was enabled but the result
                   1632: # was exact, then a branch to _real_inex() is made.
                   1633:        btst            &ovfl_bit,FPSR_EXCEPT(%a6) # was overflow set?
                   1634:        beq.w           fu_out_done             # no
                   1635:
                   1636: fu_out_ovflchk:
                   1637:        btst            &inex2_bit,FPCR_ENABLE(%a6) # was inexact enabled?
                   1638:        beq.w           fu_out_done             # no
                   1639:        bra.w           fu_inex                 # yes
                   1640:
                   1641: #
                   1642: # The fp move out that took the "Unimplemented Data Type" exception was
                   1643: # being traced. Since the stack frames are similar, get the "current" PC
                   1644: # from FPIAR and put it in the trace stack frame then jump to _real_trace().
                   1645: #
                   1646: #                UNSUPP FRAME             TRACE FRAME
                   1647: #              *****************       *****************
                   1648: #              *      EA       *       *    Current    *
                   1649: #              *               *       *      PC       *
                   1650: #              *****************       *****************
                   1651: #              * 0x3 *  0x0dc  *       * 0x2 *  0x024  *
                   1652: #              *****************       *****************
                   1653: #              *     Next      *       *     Next      *
                   1654: #              *      PC       *       *      PC       *
                   1655: #              *****************       *****************
                   1656: #              *      SR       *       *      SR       *
                   1657: #              *****************       *****************
                   1658: #
                   1659: fu_out_trace:
                   1660:        mov.w           &0x2024,0x6(%sp)
                   1661:        fmov.l          %fpiar,0x8(%sp)
                   1662:        bra.l           _real_trace
                   1663:
                   1664: # an exception occurred and that exception was enabled.
                   1665: fu_out_exc:
                   1666:        subi.l          &24,%d0                 # fix offset to be 0-8
                   1667:
                   1668: # we don't mess with the existing fsave frame. just re-insert it and
                   1669: # jump to the "_real_{}()" handler...
                   1670:        mov.w           (tbl_fu_out.b,%pc,%d0.w*2),%d0
                   1671:        jmp             (tbl_fu_out.b,%pc,%d0.w*1)
                   1672:
                   1673:        swbeg           &0x8
                   1674: tbl_fu_out:
                   1675:        short           tbl_fu_out      - tbl_fu_out    # BSUN can't happen
                   1676:        short           tbl_fu_out      - tbl_fu_out    # SNAN can't happen
                   1677:        short           fu_operr        - tbl_fu_out    # OPERR
                   1678:        short           fu_ovfl         - tbl_fu_out    # OVFL
                   1679:        short           fu_unfl         - tbl_fu_out    # UNFL
                   1680:        short           tbl_fu_out      - tbl_fu_out    # DZ can't happen
                   1681:        short           fu_inex         - tbl_fu_out    # INEX2
                   1682:        short           tbl_fu_out      - tbl_fu_out    # INEX1 won't make it here
                   1683:
                   1684: # for snan,operr,ovfl,unfl, src op is still in FP_SRC so just
                   1685: # frestore it.
                   1686: fu_snan:
                   1687:        fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0/fp1
                   1688:        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
                   1689:        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
                   1690:
                   1691:        mov.w           &0x30d8,EXC_VOFF(%a6)   # vector offset = 0xd8
                   1692:        mov.w           &0xe006,2+FP_SRC(%a6)
                   1693:
                   1694:        frestore        FP_SRC(%a6)
                   1695:
                   1696:        unlk            %a6
                   1697:
                   1698:
                   1699:        bra.l           _real_snan
                   1700:
                   1701: fu_operr:
                   1702:        fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0/fp1
                   1703:        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
                   1704:        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
                   1705:
                   1706:        mov.w           &0x30d0,EXC_VOFF(%a6)   # vector offset = 0xd0
                   1707:        mov.w           &0xe004,2+FP_SRC(%a6)
                   1708:
                   1709:        frestore        FP_SRC(%a6)
                   1710:
                   1711:        unlk            %a6
                   1712:
                   1713:
                   1714:        bra.l           _real_operr
                   1715:
                   1716: fu_ovfl:
                   1717:        fmovm.x         &0x40,FP_SRC(%a6)       # save EXOP to the stack
                   1718:
                   1719:        fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0/fp1
                   1720:        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
                   1721:        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
                   1722:
                   1723:        mov.w           &0x30d4,EXC_VOFF(%a6)   # vector offset = 0xd4
                   1724:        mov.w           &0xe005,2+FP_SRC(%a6)
                   1725:
                   1726:        frestore        FP_SRC(%a6)             # restore EXOP
                   1727:
                   1728:        unlk            %a6
                   1729:
                   1730:        bra.l           _real_ovfl
                   1731:
                   1732: # underflow can happen for extended precision. extended precision opclass
                   1733: # three instruction exceptions don't update the stack pointer. so, if the
                   1734: # exception occurred from user mode, then simply update a7 and exit normally.
                   1735: # if the exception occurred from supervisor mode, check if
                   1736: fu_unfl:
                   1737:        mov.l           EXC_A6(%a6),(%a6)       # restore a6
                   1738:
                   1739:        btst            &0x5,EXC_SR(%a6)
                   1740:        bne.w           fu_unfl_s
                   1741:
                   1742:        mov.l           EXC_A7(%a6),%a0         # restore a7 whether we need
                   1743:        mov.l           %a0,%usp                # to or not...
                   1744:
                   1745: fu_unfl_cont:
                   1746:        fmovm.x         &0x40,FP_SRC(%a6)       # save EXOP to the stack
                   1747:
                   1748:        fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0/fp1
                   1749:        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
                   1750:        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
                   1751:
                   1752:        mov.w           &0x30cc,EXC_VOFF(%a6)   # vector offset = 0xcc
                   1753:        mov.w           &0xe003,2+FP_SRC(%a6)
                   1754:
                   1755:        frestore        FP_SRC(%a6)             # restore EXOP
                   1756:
                   1757:        unlk            %a6
                   1758:
                   1759:        bra.l           _real_unfl
                   1760:
                   1761: fu_unfl_s:
                   1762:        cmpi.b          SPCOND_FLG(%a6),&mda7_flg # was the <ea> mode -(sp)?
                   1763:        bne.b           fu_unfl_cont
                   1764:
                   1765: # the extended precision result is still in fp0. but, we need to save it
                   1766: # somewhere on the stack until we can copy it to its final resting place
                   1767: # (where the exc frame is currently). make sure it's not at the top of the
                   1768: # frame or it will get overwritten when the exc stack frame is shifted "down".
                   1769:        fmovm.x         &0x80,FP_SRC(%a6)       # put answer on stack
                   1770:        fmovm.x         &0x40,FP_DST(%a6)       # put EXOP on stack
                   1771:
                   1772:        fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0/fp1
                   1773:        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
                   1774:        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
                   1775:
                   1776:        mov.w           &0x30cc,EXC_VOFF(%a6)   # vector offset = 0xcc
                   1777:        mov.w           &0xe003,2+FP_DST(%a6)
                   1778:
                   1779:        frestore        FP_DST(%a6)             # restore EXOP
                   1780:
                   1781:        mov.l           (%a6),%a6               # restore frame pointer
                   1782:
                   1783:        mov.l           LOCAL_SIZE+EXC_SR(%sp),LOCAL_SIZE+EXC_SR-0xc(%sp)
                   1784:        mov.l           LOCAL_SIZE+2+EXC_PC(%sp),LOCAL_SIZE+2+EXC_PC-0xc(%sp)
                   1785:        mov.l           LOCAL_SIZE+EXC_EA(%sp),LOCAL_SIZE+EXC_EA-0xc(%sp)
                   1786:
                   1787: # now, copy the result to the proper place on the stack
                   1788:        mov.l           LOCAL_SIZE+FP_SRC_EX(%sp),LOCAL_SIZE+EXC_SR+0x0(%sp)
                   1789:        mov.l           LOCAL_SIZE+FP_SRC_HI(%sp),LOCAL_SIZE+EXC_SR+0x4(%sp)
                   1790:        mov.l           LOCAL_SIZE+FP_SRC_LO(%sp),LOCAL_SIZE+EXC_SR+0x8(%sp)
                   1791:
                   1792:        add.l           &LOCAL_SIZE-0x8,%sp
                   1793:
                   1794:        bra.l           _real_unfl
                   1795:
                   1796: # fmove in and out enter here.
                   1797: fu_inex:
                   1798:        fmovm.x         &0x40,FP_SRC(%a6)       # save EXOP to the stack
                   1799:
                   1800:        fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0/fp1
                   1801:        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
                   1802:        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
                   1803:
                   1804:        mov.w           &0x30c4,EXC_VOFF(%a6)   # vector offset = 0xc4
                   1805:        mov.w           &0xe001,2+FP_SRC(%a6)
                   1806:
                   1807:        frestore        FP_SRC(%a6)             # restore EXOP
                   1808:
                   1809:        unlk            %a6
                   1810:
                   1811:
                   1812:        bra.l           _real_inex
                   1813:
                   1814: #########################################################################
                   1815: #########################################################################
                   1816: fu_in_pack:
                   1817:
                   1818:
                   1819: # I'm not sure at this point what FPSR bits are valid for this instruction.
                   1820: # so, since the emulation routines re-create them anyways, zero exception field
                   1821:        andi.l          &0x0ff00ff,USER_FPSR(%a6) # zero exception field
                   1822:
                   1823:        fmov.l          &0x0,%fpcr              # zero current control regs
                   1824:        fmov.l          &0x0,%fpsr
                   1825:
                   1826:        bsr.l           get_packed              # fetch packed src operand
                   1827:
                   1828:        lea             FP_SRC(%a6),%a0         # pass ptr to src
                   1829:        bsr.l           set_tag_x               # set src optype tag
                   1830:
                   1831:        mov.b           %d0,STAG(%a6)           # save src optype tag
                   1832:
                   1833:        bfextu          EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg
                   1834:
                   1835: # bit five of the fp extension word separates the monadic and dyadic operations
                   1836: # at this point
                   1837:        btst            &0x5,1+EXC_CMDREG(%a6)  # is operation monadic or dyadic?
                   1838:        beq.b           fu_extract_p            # monadic
                   1839:        cmpi.b          1+EXC_CMDREG(%a6),&0x3a # is operation an ftst?
                   1840:        beq.b           fu_extract_p            # yes, so it's monadic, too
                   1841:
                   1842:        bsr.l           load_fpn2               # load dst into FP_DST
                   1843:
                   1844:        lea             FP_DST(%a6),%a0         # pass: ptr to dst op
                   1845:        bsr.l           set_tag_x               # tag the operand type
                   1846:        cmpi.b          %d0,&UNNORM             # is operand an UNNORM?
                   1847:        bne.b           fu_op2_done_p           # no
                   1848:        bsr.l           unnorm_fix              # yes; convert to NORM,DENORM,or ZERO
                   1849: fu_op2_done_p:
                   1850:        mov.b           %d0,DTAG(%a6)           # save dst optype tag
                   1851:
                   1852: fu_extract_p:
                   1853:        clr.l           %d0
                   1854:        mov.b           FPCR_MODE(%a6),%d0      # fetch rnd mode/prec
                   1855:
                   1856:        bfextu          1+EXC_CMDREG(%a6){&1:&7},%d1 # extract extension
                   1857:
                   1858:        lea             FP_SRC(%a6),%a0
                   1859:        lea             FP_DST(%a6),%a1
                   1860:
                   1861:        mov.l           (tbl_unsupp.l,%pc,%d1.l*4),%d1 # fetch routine addr
                   1862:        jsr             (tbl_unsupp.l,%pc,%d1.l*1)
                   1863:
                   1864: #
                   1865: # Exceptions in order of precedence:
                   1866: #      BSUN    : none
                   1867: #      SNAN    : all dyadic ops
                   1868: #      OPERR   : fsqrt(-NORM)
                   1869: #      OVFL    : all except ftst,fcmp
                   1870: #      UNFL    : all except ftst,fcmp
                   1871: #      DZ      : fdiv
                   1872: #      INEX2   : all except ftst,fcmp
                   1873: #      INEX1   : all
                   1874: #
                   1875:
                   1876: # we determine the highest priority exception(if any) set by the
                   1877: # emulation routine that has also been enabled by the user.
                   1878:        mov.b           FPCR_ENABLE(%a6),%d0    # fetch exceptions enabled
                   1879:        bne.w           fu_in_ena_p             # some are enabled
                   1880:
                   1881: fu_in_cont_p:
                   1882: # fcmp and ftst do not store any result.
                   1883:        mov.b           1+EXC_CMDREG(%a6),%d0   # fetch extension
                   1884:        andi.b          &0x38,%d0               # extract bits 3-5
                   1885:        cmpi.b          %d0,&0x38               # is instr fcmp or ftst?
                   1886:        beq.b           fu_in_exit_p            # yes
                   1887:
                   1888:        bfextu          EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg
                   1889:        bsr.l           store_fpreg             # store the result
                   1890:
                   1891: fu_in_exit_p:
                   1892:
                   1893:        btst            &0x5,EXC_SR(%a6)        # user or supervisor?
                   1894:        bne.w           fu_in_exit_s_p          # supervisor
                   1895:
                   1896:        mov.l           EXC_A7(%a6),%a0         # update user a7
                   1897:        mov.l           %a0,%usp
                   1898:
                   1899: fu_in_exit_cont_p:
                   1900:        fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0/fp1
                   1901:        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
                   1902:        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
                   1903:
                   1904:        unlk            %a6                     # unravel stack frame
                   1905:
                   1906:        btst            &0x7,(%sp)              # is trace on?
                   1907:        bne.w           fu_trace_p              # yes
                   1908:
                   1909:        bra.l           _fpsp_done              # exit to os
                   1910:
                   1911: # the exception occurred in supervisor mode. check to see if the
                   1912: # addressing mode was (a7)+. if so, we'll need to shift the
                   1913: # stack frame "up".
                   1914: fu_in_exit_s_p:
                   1915:        btst            &mia7_bit,SPCOND_FLG(%a6) # was ea mode (a7)+
                   1916:        beq.b           fu_in_exit_cont_p       # no
                   1917:
                   1918:        fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0/fp1
                   1919:        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
                   1920:        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
                   1921:
                   1922:        unlk            %a6                     # unravel stack frame
                   1923:
                   1924: # shift the stack frame "up". we don't really care about the <ea> field.
                   1925:        mov.l           0x4(%sp),0x10(%sp)
                   1926:        mov.l           0x0(%sp),0xc(%sp)
                   1927:        add.l           &0xc,%sp
                   1928:
                   1929:        btst            &0x7,(%sp)              # is trace on?
                   1930:        bne.w           fu_trace_p              # yes
                   1931:
                   1932:        bra.l           _fpsp_done              # exit to os
                   1933:
                   1934: fu_in_ena_p:
                   1935:        and.b           FPSR_EXCEPT(%a6),%d0    # keep only ones enabled & set
                   1936:        bfffo           %d0{&24:&8},%d0         # find highest priority exception
                   1937:        bne.b           fu_in_exc_p             # at least one was set
                   1938:
                   1939: #
                   1940: # No exceptions occurred that were also enabled. Now:
                   1941: #
                   1942: #      if (OVFL && ovfl_disabled && inexact_enabled) {
                   1943: #          branch to _real_inex() (even if the result was exact!);
                   1944: #      } else {
                   1945: #          save the result in the proper fp reg (unless the op is fcmp or ftst);
                   1946: #          return;
                   1947: #      }
                   1948: #
                   1949:        btst            &ovfl_bit,FPSR_EXCEPT(%a6) # was overflow set?
                   1950:        beq.w           fu_in_cont_p            # no
                   1951:
                   1952: fu_in_ovflchk_p:
                   1953:        btst            &inex2_bit,FPCR_ENABLE(%a6) # was inexact enabled?
                   1954:        beq.w           fu_in_cont_p            # no
                   1955:        bra.w           fu_in_exc_ovfl_p        # do _real_inex() now
                   1956:
                   1957: #
                   1958: # An exception occurred and that exception was enabled:
                   1959: #
                   1960: #      shift enabled exception field into lo byte of d0;
                   1961: #      if (((INEX2 || INEX1) && inex_enabled && OVFL && ovfl_disabled) ||
                   1962: #          ((INEX2 || INEX1) && inex_enabled && UNFL && unfl_disabled)) {
                   1963: #              /*
                   1964: #               * this is the case where we must call _real_inex() now or else
                   1965: #               * there will be no other way to pass it the exceptional operand
                   1966: #               */
                   1967: #              call _real_inex();
                   1968: #      } else {
                   1969: #              restore exc state (SNAN||OPERR||OVFL||UNFL||DZ||INEX) into the FPU;
                   1970: #      }
                   1971: #
                   1972: fu_in_exc_p:
                   1973:        subi.l          &24,%d0                 # fix offset to be 0-8
                   1974:        cmpi.b          %d0,&0x6                # is exception INEX? (6 or 7)
                   1975:        blt.b           fu_in_exc_exit_p        # no
                   1976:
                   1977: # the enabled exception was inexact
                   1978:        btst            &unfl_bit,FPSR_EXCEPT(%a6) # did disabled underflow occur?
                   1979:        bne.w           fu_in_exc_unfl_p        # yes
                   1980:        btst            &ovfl_bit,FPSR_EXCEPT(%a6) # did disabled overflow occur?
                   1981:        bne.w           fu_in_exc_ovfl_p        # yes
                   1982:
                   1983: # here, we insert the correct fsave status value into the fsave frame for the
                   1984: # corresponding exception. the operand in the fsave frame should be the original
                   1985: # src operand.
                   1986: # as a reminder for future predicted pain and agony, we are passing in fsave the
                   1987: # "non-skewed" operand for cases of sgl and dbl src INFs,NANs, and DENORMs.
                   1988: # this is INCORRECT for enabled SNAN which would give to the user the skewed SNAN!!!
                   1989: fu_in_exc_exit_p:
                   1990:        btst            &0x5,EXC_SR(%a6)        # user or supervisor?
                   1991:        bne.w           fu_in_exc_exit_s_p      # supervisor
                   1992:
                   1993:        mov.l           EXC_A7(%a6),%a0         # update user a7
                   1994:        mov.l           %a0,%usp
                   1995:
                   1996: fu_in_exc_exit_cont_p:
                   1997:        mov.w           (tbl_except_p.b,%pc,%d0.w*2),2+FP_SRC(%a6)
                   1998:
                   1999:        fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0/fp1
                   2000:        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
                   2001:        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
                   2002:
                   2003:        frestore        FP_SRC(%a6)             # restore src op
                   2004:
                   2005:        unlk            %a6
                   2006:
                   2007:        btst            &0x7,(%sp)              # is trace enabled?
                   2008:        bne.w           fu_trace_p              # yes
                   2009:
                   2010:        bra.l           _fpsp_done
                   2011:
                   2012: tbl_except_p:
                   2013:        short           0xe000,0xe006,0xe004,0xe005
                   2014:        short           0xe003,0xe002,0xe001,0xe001
                   2015:
                   2016: fu_in_exc_ovfl_p:
                   2017:        mov.w           &0x3,%d0
                   2018:        bra.w           fu_in_exc_exit_p
                   2019:
                   2020: fu_in_exc_unfl_p:
                   2021:        mov.w           &0x4,%d0
                   2022:        bra.w           fu_in_exc_exit_p
                   2023:
                   2024: fu_in_exc_exit_s_p:
                   2025:        btst            &mia7_bit,SPCOND_FLG(%a6)
                   2026:        beq.b           fu_in_exc_exit_cont_p
                   2027:
                   2028:        mov.w           (tbl_except_p.b,%pc,%d0.w*2),2+FP_SRC(%a6)
                   2029:
                   2030:        fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0/fp1
                   2031:        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
                   2032:        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
                   2033:
                   2034:        frestore        FP_SRC(%a6)             # restore src op
                   2035:
                   2036:        unlk            %a6                     # unravel stack frame
                   2037:
                   2038: # shift stack frame "up". who cares about <ea> field.
                   2039:        mov.l           0x4(%sp),0x10(%sp)
                   2040:        mov.l           0x0(%sp),0xc(%sp)
                   2041:        add.l           &0xc,%sp
                   2042:
                   2043:        btst            &0x7,(%sp)              # is trace on?
                   2044:        bne.b           fu_trace_p              # yes
                   2045:
                   2046:        bra.l           _fpsp_done              # exit to os
                   2047:
                   2048: #
                   2049: # The opclass two PACKED instruction that took an "Unimplemented Data Type"
                   2050: # exception was being traced. Make the "current" PC the FPIAR and put it in the
                   2051: # trace stack frame then jump to _real_trace().
                   2052: #
                   2053: #                UNSUPP FRAME             TRACE FRAME
                   2054: #              *****************       *****************
                   2055: #              *      EA       *       *    Current    *
                   2056: #              *               *       *      PC       *
                   2057: #              *****************       *****************
                   2058: #              * 0x2 * 0x0dc   *       * 0x2 *  0x024  *
                   2059: #              *****************       *****************
                   2060: #              *     Next      *       *     Next      *
                   2061: #              *      PC       *       *      PC       *
                   2062: #              *****************       *****************
                   2063: #              *      SR       *       *      SR       *
                   2064: #              *****************       *****************
                   2065: fu_trace_p:
                   2066:        mov.w           &0x2024,0x6(%sp)
                   2067:        fmov.l          %fpiar,0x8(%sp)
                   2068:
                   2069:        bra.l           _real_trace
                   2070:
                   2071: #########################################################
                   2072: #########################################################
                   2073: fu_out_pack:
                   2074:
                   2075:
                   2076: # I'm not sure at this point what FPSR bits are valid for this instruction.
                   2077: # so, since the emulation routines re-create them anyways, zero exception field.
                   2078: # fmove out doesn't affect ccodes.
                   2079:        and.l           &0xffff00ff,USER_FPSR(%a6) # zero exception field
                   2080:
                   2081:        fmov.l          &0x0,%fpcr              # zero current control regs
                   2082:        fmov.l          &0x0,%fpsr
                   2083:
                   2084:        bfextu          EXC_CMDREG(%a6){&6:&3},%d0
                   2085:        bsr.l           load_fpn1
                   2086:
                   2087: # unlike other opclass 3, unimplemented data type exceptions, packed must be
                   2088: # able to detect all operand types.
                   2089:        lea             FP_SRC(%a6),%a0
                   2090:        bsr.l           set_tag_x               # tag the operand type
                   2091:        cmpi.b          %d0,&UNNORM             # is operand an UNNORM?
                   2092:        bne.b           fu_op2_p                # no
                   2093:        bsr.l           unnorm_fix              # yes; convert to NORM,DENORM,or ZERO
                   2094:
                   2095: fu_op2_p:
                   2096:        mov.b           %d0,STAG(%a6)           # save src optype tag
                   2097:
                   2098:        clr.l           %d0
                   2099:        mov.b           FPCR_MODE(%a6),%d0      # fetch rnd mode/prec
                   2100:
                   2101:        lea             FP_SRC(%a6),%a0         # pass ptr to src operand
                   2102:
                   2103:        mov.l           (%a6),EXC_A6(%a6)       # in case a6 changes
                   2104:        bsr.l           fout                    # call fmove out routine
                   2105:
                   2106: # Exceptions in order of precedence:
                   2107: #      BSUN    : no
                   2108: #      SNAN    : yes
                   2109: #      OPERR   : if ((k_factor > +17) || (dec. exp exceeds 3 digits))
                   2110: #      OVFL    : no
                   2111: #      UNFL    : no
                   2112: #      DZ      : no
                   2113: #      INEX2   : yes
                   2114: #      INEX1   : no
                   2115:
                   2116: # determine the highest priority exception(if any) set by the
                   2117: # emulation routine that has also been enabled by the user.
                   2118:        mov.b           FPCR_ENABLE(%a6),%d0    # fetch exceptions enabled
                   2119:        bne.w           fu_out_ena_p            # some are enabled
                   2120:
                   2121: fu_out_exit_p:
                   2122:        mov.l           EXC_A6(%a6),(%a6)       # restore a6
                   2123:
                   2124:        btst            &0x5,EXC_SR(%a6)        # user or supervisor?
                   2125:        bne.b           fu_out_exit_s_p         # supervisor
                   2126:
                   2127:        mov.l           EXC_A7(%a6),%a0         # update user a7
                   2128:        mov.l           %a0,%usp
                   2129:
                   2130: fu_out_exit_cont_p:
                   2131:        fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0/fp1
                   2132:        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
                   2133:        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
                   2134:
                   2135:        unlk            %a6                     # unravel stack frame
                   2136:
                   2137:        btst            &0x7,(%sp)              # is trace on?
                   2138:        bne.w           fu_trace_p              # yes
                   2139:
                   2140:        bra.l           _fpsp_done              # exit to os
                   2141:
                   2142: # the exception occurred in supervisor mode. check to see if the
                   2143: # addressing mode was -(a7). if so, we'll need to shift the
                   2144: # stack frame "down".
                   2145: fu_out_exit_s_p:
                   2146:        btst            &mda7_bit,SPCOND_FLG(%a6) # was ea mode -(a7)
                   2147:        beq.b           fu_out_exit_cont_p      # no
                   2148:
                   2149:        fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0/fp1
                   2150:        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
                   2151:        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
                   2152:
                   2153:        mov.l           (%a6),%a6               # restore frame pointer
                   2154:
                   2155:        mov.l           LOCAL_SIZE+EXC_SR(%sp),LOCAL_SIZE+EXC_SR-0xc(%sp)
                   2156:        mov.l           LOCAL_SIZE+2+EXC_PC(%sp),LOCAL_SIZE+2+EXC_PC-0xc(%sp)
                   2157:
                   2158: # now, copy the result to the proper place on the stack
                   2159:        mov.l           LOCAL_SIZE+FP_DST_EX(%sp),LOCAL_SIZE+EXC_SR+0x0(%sp)
                   2160:        mov.l           LOCAL_SIZE+FP_DST_HI(%sp),LOCAL_SIZE+EXC_SR+0x4(%sp)
                   2161:        mov.l           LOCAL_SIZE+FP_DST_LO(%sp),LOCAL_SIZE+EXC_SR+0x8(%sp)
                   2162:
                   2163:        add.l           &LOCAL_SIZE-0x8,%sp
                   2164:
                   2165:        btst            &0x7,(%sp)
                   2166:        bne.w           fu_trace_p
                   2167:
                   2168:        bra.l           _fpsp_done
                   2169:
                   2170: fu_out_ena_p:
                   2171:        and.b           FPSR_EXCEPT(%a6),%d0    # keep only ones enabled
                   2172:        bfffo           %d0{&24:&8},%d0         # find highest priority exception
                   2173:        beq.w           fu_out_exit_p
                   2174:
                   2175:        mov.l           EXC_A6(%a6),(%a6)       # restore a6
                   2176:
                   2177: # an exception occurred and that exception was enabled.
                   2178: # the only exception possible on packed move out are INEX, OPERR, and SNAN.
                   2179: fu_out_exc_p:
                   2180:        cmpi.b          %d0,&0x1a
                   2181:        bgt.w           fu_inex_p2
                   2182:        beq.w           fu_operr_p
                   2183:
                   2184: fu_snan_p:
                   2185:        btst            &0x5,EXC_SR(%a6)
                   2186:        bne.b           fu_snan_s_p
                   2187:
                   2188:        mov.l           EXC_A7(%a6),%a0
                   2189:        mov.l           %a0,%usp
                   2190:        bra.w           fu_snan
                   2191:
                   2192: fu_snan_s_p:
                   2193:        cmpi.b          SPCOND_FLG(%a6),&mda7_flg
                   2194:        bne.w           fu_snan
                   2195:
                   2196: # the instruction was "fmove.p fpn,-(a7)" from supervisor mode.
                   2197: # the strategy is to move the exception frame "down" 12 bytes. then, we
                   2198: # can store the default result where the exception frame was.
                   2199:        fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0/fp1
                   2200:        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
                   2201:        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
                   2202:
                   2203:        mov.w           &0x30d8,EXC_VOFF(%a6)   # vector offset = 0xd0
                   2204:        mov.w           &0xe006,2+FP_SRC(%a6)   # set fsave status
                   2205:
                   2206:        frestore        FP_SRC(%a6)             # restore src operand
                   2207:
                   2208:        mov.l           (%a6),%a6               # restore frame pointer
                   2209:
                   2210:        mov.l           LOCAL_SIZE+EXC_SR(%sp),LOCAL_SIZE+EXC_SR-0xc(%sp)
                   2211:        mov.l           LOCAL_SIZE+2+EXC_PC(%sp),LOCAL_SIZE+2+EXC_PC-0xc(%sp)
                   2212:        mov.l           LOCAL_SIZE+EXC_EA(%sp),LOCAL_SIZE+EXC_EA-0xc(%sp)
                   2213:
                   2214: # now, we copy the default result to its proper location
                   2215:        mov.l           LOCAL_SIZE+FP_DST_EX(%sp),LOCAL_SIZE+0x4(%sp)
                   2216:        mov.l           LOCAL_SIZE+FP_DST_HI(%sp),LOCAL_SIZE+0x8(%sp)
                   2217:        mov.l           LOCAL_SIZE+FP_DST_LO(%sp),LOCAL_SIZE+0xc(%sp)
                   2218:
                   2219:        add.l           &LOCAL_SIZE-0x8,%sp
                   2220:
                   2221:
                   2222:        bra.l           _real_snan
                   2223:
                   2224: fu_operr_p:
                   2225:        btst            &0x5,EXC_SR(%a6)
                   2226:        bne.w           fu_operr_p_s
                   2227:
                   2228:        mov.l           EXC_A7(%a6),%a0
                   2229:        mov.l           %a0,%usp
                   2230:        bra.w           fu_operr
                   2231:
                   2232: fu_operr_p_s:
                   2233:        cmpi.b          SPCOND_FLG(%a6),&mda7_flg
                   2234:        bne.w           fu_operr
                   2235:
                   2236: # the instruction was "fmove.p fpn,-(a7)" from supervisor mode.
                   2237: # the strategy is to move the exception frame "down" 12 bytes. then, we
                   2238: # can store the default result where the exception frame was.
                   2239:        fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0/fp1
                   2240:        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
                   2241:        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
                   2242:
                   2243:        mov.w           &0x30d0,EXC_VOFF(%a6)   # vector offset = 0xd0
                   2244:        mov.w           &0xe004,2+FP_SRC(%a6)   # set fsave status
                   2245:
                   2246:        frestore        FP_SRC(%a6)             # restore src operand
                   2247:
                   2248:        mov.l           (%a6),%a6               # restore frame pointer
                   2249:
                   2250:        mov.l           LOCAL_SIZE+EXC_SR(%sp),LOCAL_SIZE+EXC_SR-0xc(%sp)
                   2251:        mov.l           LOCAL_SIZE+2+EXC_PC(%sp),LOCAL_SIZE+2+EXC_PC-0xc(%sp)
                   2252:        mov.l           LOCAL_SIZE+EXC_EA(%sp),LOCAL_SIZE+EXC_EA-0xc(%sp)
                   2253:
                   2254: # now, we copy the default result to its proper location
                   2255:        mov.l           LOCAL_SIZE+FP_DST_EX(%sp),LOCAL_SIZE+0x4(%sp)
                   2256:        mov.l           LOCAL_SIZE+FP_DST_HI(%sp),LOCAL_SIZE+0x8(%sp)
                   2257:        mov.l           LOCAL_SIZE+FP_DST_LO(%sp),LOCAL_SIZE+0xc(%sp)
                   2258:
                   2259:        add.l           &LOCAL_SIZE-0x8,%sp
                   2260:
                   2261:
                   2262:        bra.l           _real_operr
                   2263:
                   2264: fu_inex_p2:
                   2265:        btst            &0x5,EXC_SR(%a6)
                   2266:        bne.w           fu_inex_s_p2
                   2267:
                   2268:        mov.l           EXC_A7(%a6),%a0
                   2269:        mov.l           %a0,%usp
                   2270:        bra.w           fu_inex
                   2271:
                   2272: fu_inex_s_p2:
                   2273:        cmpi.b          SPCOND_FLG(%a6),&mda7_flg
                   2274:        bne.w           fu_inex
                   2275:
                   2276: # the instruction was "fmove.p fpn,-(a7)" from supervisor mode.
                   2277: # the strategy is to move the exception frame "down" 12 bytes. then, we
                   2278: # can store the default result where the exception frame was.
                   2279:        fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0/fp1
                   2280:        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
                   2281:        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
                   2282:
                   2283:        mov.w           &0x30c4,EXC_VOFF(%a6)   # vector offset = 0xc4
                   2284:        mov.w           &0xe001,2+FP_SRC(%a6)   # set fsave status
                   2285:
                   2286:        frestore        FP_SRC(%a6)             # restore src operand
                   2287:
                   2288:        mov.l           (%a6),%a6               # restore frame pointer
                   2289:
                   2290:        mov.l           LOCAL_SIZE+EXC_SR(%sp),LOCAL_SIZE+EXC_SR-0xc(%sp)
                   2291:        mov.l           LOCAL_SIZE+2+EXC_PC(%sp),LOCAL_SIZE+2+EXC_PC-0xc(%sp)
                   2292:        mov.l           LOCAL_SIZE+EXC_EA(%sp),LOCAL_SIZE+EXC_EA-0xc(%sp)
                   2293:
                   2294: # now, we copy the default result to its proper location
                   2295:        mov.l           LOCAL_SIZE+FP_DST_EX(%sp),LOCAL_SIZE+0x4(%sp)
                   2296:        mov.l           LOCAL_SIZE+FP_DST_HI(%sp),LOCAL_SIZE+0x8(%sp)
                   2297:        mov.l           LOCAL_SIZE+FP_DST_LO(%sp),LOCAL_SIZE+0xc(%sp)
                   2298:
                   2299:        add.l           &LOCAL_SIZE-0x8,%sp
                   2300:
                   2301:
                   2302:        bra.l           _real_inex
                   2303:
                   2304: #########################################################################
                   2305:
                   2306: #
                   2307: # if we're stuffing a source operand back into an fsave frame then we
                   2308: # have to make sure that for single or double source operands that the
                   2309: # format stuffed is as weird as the hardware usually makes it.
                   2310: #
                   2311:        global          funimp_skew
                   2312: funimp_skew:
                   2313:        bfextu          EXC_EXTWORD(%a6){&3:&3},%d0 # extract src specifier
                   2314:        cmpi.b          %d0,&0x1                # was src sgl?
                   2315:        beq.b           funimp_skew_sgl         # yes
                   2316:        cmpi.b          %d0,&0x5                # was src dbl?
                   2317:        beq.b           funimp_skew_dbl         # yes
                   2318:        rts
                   2319:
                   2320: funimp_skew_sgl:
                   2321:        mov.w           FP_SRC_EX(%a6),%d0      # fetch DENORM exponent
                   2322:        andi.w          &0x7fff,%d0             # strip sign
                   2323:        beq.b           funimp_skew_sgl_not
                   2324:        cmpi.w          %d0,&0x3f80
                   2325:        bgt.b           funimp_skew_sgl_not
                   2326:        neg.w           %d0                     # make exponent negative
                   2327:        addi.w          &0x3f81,%d0             # find amt to shift
                   2328:        mov.l           FP_SRC_HI(%a6),%d1      # fetch DENORM hi(man)
                   2329:        lsr.l           %d0,%d1                 # shift it
                   2330:        bset            &31,%d1                 # set j-bit
                   2331:        mov.l           %d1,FP_SRC_HI(%a6)      # insert new hi(man)
                   2332:        andi.w          &0x8000,FP_SRC_EX(%a6)  # clear old exponent
                   2333:        ori.w           &0x3f80,FP_SRC_EX(%a6)  # insert new "skewed" exponent
                   2334: funimp_skew_sgl_not:
                   2335:        rts
                   2336:
                   2337: funimp_skew_dbl:
                   2338:        mov.w           FP_SRC_EX(%a6),%d0      # fetch DENORM exponent
                   2339:        andi.w          &0x7fff,%d0             # strip sign
                   2340:        beq.b           funimp_skew_dbl_not
                   2341:        cmpi.w          %d0,&0x3c00
                   2342:        bgt.b           funimp_skew_dbl_not
                   2343:
                   2344:        tst.b           FP_SRC_EX(%a6)          # make "internal format"
                   2345:        smi.b           0x2+FP_SRC(%a6)
                   2346:        mov.w           %d0,FP_SRC_EX(%a6)      # insert exponent with cleared sign
                   2347:        clr.l           %d0                     # clear g,r,s
                   2348:        lea             FP_SRC(%a6),%a0         # pass ptr to src op
                   2349:        mov.w           &0x3c01,%d1             # pass denorm threshold
                   2350:        bsr.l           dnrm_lp                 # denorm it
                   2351:        mov.w           &0x3c00,%d0             # new exponent
                   2352:        tst.b           0x2+FP_SRC(%a6)         # is sign set?
                   2353:        beq.b           fss_dbl_denorm_done     # no
                   2354:        bset            &15,%d0                 # set sign
                   2355: fss_dbl_denorm_done:
                   2356:        bset            &0x7,FP_SRC_HI(%a6)     # set j-bit
                   2357:        mov.w           %d0,FP_SRC_EX(%a6)      # insert new exponent
                   2358: funimp_skew_dbl_not:
                   2359:        rts
                   2360:
                   2361: #########################################################################
                   2362:        global          _mem_write2
                   2363: _mem_write2:
                   2364:        btst            &0x5,EXC_SR(%a6)
                   2365:        beq.l           _dmem_write
                   2366:        mov.l           0x0(%a0),FP_DST_EX(%a6)
                   2367:        mov.l           0x4(%a0),FP_DST_HI(%a6)
                   2368:        mov.l           0x8(%a0),FP_DST_LO(%a6)
                   2369:        clr.l           %d1
                   2370:        rts
                   2371:
                   2372: #########################################################################
                   2373: # XDEF ****************************************************************        #
                   2374: #      _fpsp_effadd(): 060FPSP entry point for FP "Unimplemented       #
                   2375: #                      effective address" exception.                   #
                   2376: #                                                                      #
                   2377: #      This handler should be the first code executed upon taking the  #
                   2378: #      FP Unimplemented Effective Address exception in an operating    #
                   2379: #      system.                                                         #
                   2380: #                                                                      #
                   2381: # XREF ****************************************************************        #
                   2382: #      _imem_read_long() - read instruction longword                   #
                   2383: #      fix_skewed_ops() - adjust src operand in fsave frame            #
                   2384: #      set_tag_x() - determine optype of src/dst operands              #
                   2385: #      store_fpreg() - store opclass 0 or 2 result to FP regfile       #
                   2386: #      unnorm_fix() - change UNNORM operands to NORM or ZERO           #
                   2387: #      load_fpn2() - load dst operand from FP regfile                  #
                   2388: #      tbl_unsupp - add of table of emulation routines for opclass 0,2 #
                   2389: #      decbin() - convert packed data to FP binary data                #
                   2390: #      _real_fpu_disabled() - "callout" for "FPU disabled" exception   #
                   2391: #      _real_access() - "callout" for access error exception           #
                   2392: #      _mem_read() - read extended immediate operand from memory       #
                   2393: #      _fpsp_done() - "callout" for exit; work all done                #
                   2394: #      _real_trace() - "callout" for Trace enabled exception           #
                   2395: #      fmovm_dynamic() - emulate dynamic fmovm instruction             #
                   2396: #      fmovm_ctrl() - emulate fmovm control instruction                #
                   2397: #                                                                      #
                   2398: # INPUT ***************************************************************        #
                   2399: #      - The system stack contains the "Unimplemented <ea>" stk frame  #
                   2400: #                                                                      #
                   2401: # OUTPUT **************************************************************        #
                   2402: #      If access error:                                                #
                   2403: #      - The system stack is changed to an access error stack frame    #
                   2404: #      If FPU disabled:                                                #
                   2405: #      - The system stack is changed to an FPU disabled stack frame    #
                   2406: #      If Trace exception enabled:                                     #
                   2407: #      - The system stack is changed to a Trace exception stack frame  #
                   2408: #      Else: (normal case)                                             #
                   2409: #      - None (correct result has been stored as appropriate)          #
                   2410: #                                                                      #
                   2411: # ALGORITHM ***********************************************************        #
                   2412: #      This exception handles 3 types of operations:                   #
                   2413: # (1) FP Instructions using extended precision or packed immediate     #
                   2414: #     addressing mode.                                                 #
                   2415: # (2) The "fmovm.x" instruction w/ dynamic register specification.     #
                   2416: # (3) The "fmovm.l" instruction w/ 2 or 3 control registers.           #
                   2417: #                                                                      #
                   2418: #      For immediate data operations, the data is read in w/ a         #
                   2419: # _mem_read() "callout", converted to FP binary (if packed), and used  #
                   2420: # as the source operand to the instruction specified by the instruction        #
                   2421: # word. If no FP exception should be reported ads a result of the      #
                   2422: # emulation, then the result is stored to the destination register and #
                   2423: # the handler exits through _fpsp_done(). If an enabled exc has been   #
                   2424: # signalled as a result of emulation, then an fsave state frame                #
                   2425: # corresponding to the FP exception type must be entered into the 060  #
                   2426: # FPU before exiting. In either the enabled or disabled cases, we      #
                   2427: # must also check if a Trace exception is pending, in which case, we   #
                   2428: # must create a Trace exception stack frame from the current exception #
                   2429: # stack frame. If no Trace is pending, we simply exit through          #
                   2430: # _fpsp_done().                                                                #
                   2431: #      For "fmovm.x", call the routine fmovm_dynamic() which will      #
                   2432: # decode and emulate the instruction. No FP exceptions can be pending  #
                   2433: # as a result of this operation emulation. A Trace exception can be    #
                   2434: # pending, though, which means the current stack frame must be changed #
                   2435: # to a Trace stack frame and an exit made through _real_trace().       #
                   2436: # For the case of "fmovm.x Dn,-(a7)", where the offending instruction  #
                   2437: # was executed from supervisor mode, this handler must store the FP    #
                   2438: # register file values to the system stack by itself since             #
                   2439: # fmovm_dynamic() can't handle this. A normal exit is made through     #
                   2440: # fpsp_done().                                                         #
                   2441: #      For "fmovm.l", fmovm_ctrl() is used to emulate the instruction. #
                   2442: # Again, a Trace exception may be pending and an exit made through     #
                   2443: # _real_trace(). Else, a normal exit is made through _fpsp_done().     #
                   2444: #                                                                      #
                   2445: #      Before any of the above is attempted, it must be checked to     #
                   2446: # see if the FPU is disabled. Since the "Unimp <ea>" exception is taken        #
                   2447: # before the "FPU disabled" exception, but the "FPU disabled" exception        #
                   2448: # has higher priority, we check the disabled bit in the PCR. If set,   #
                   2449: # then we must create an 8 word "FPU disabled" exception stack frame   #
                   2450: # from the current 4 word exception stack frame. This includes                 #
                   2451: # reproducing the effective address of the instruction to put on the   #
                   2452: # new stack frame.                                                     #
                   2453: #                                                                      #
                   2454: #      In the process of all emulation work, if a _mem_read()          #
                   2455: # "callout" returns a failing result indicating an access error, then  #
                   2456: # we must create an access error stack frame from the current stack    #
                   2457: # frame. This information includes a faulting address and a fault-     #
                   2458: # status-longword. These are created within this handler.              #
                   2459: #                                                                      #
                   2460: #########################################################################
                   2461:
                   2462:        global          _fpsp_effadd
                   2463: _fpsp_effadd:
                   2464:
                   2465: # This exception type takes priority over the "Line F Emulator"
                   2466: # exception. Therefore, the FPU could be disabled when entering here.
                   2467: # So, we must check to see if it's disabled and handle that case separately.
                   2468:        mov.l           %d0,-(%sp)              # save d0
                   2469:        movc            %pcr,%d0                # load proc cr
                   2470:        btst            &0x1,%d0                # is FPU disabled?
                   2471:        bne.w           iea_disabled            # yes
                   2472:        mov.l           (%sp)+,%d0              # restore d0
                   2473:
                   2474:        link            %a6,&-LOCAL_SIZE        # init stack frame
                   2475:
                   2476:        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
                   2477:        fmovm.l         %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
                   2478:        fmovm.x         &0xc0,EXC_FPREGS(%a6)   # save fp0-fp1 on stack
                   2479:
                   2480: # PC of instruction that took the exception is the PC in the frame
                   2481:        mov.l           EXC_PC(%a6),EXC_EXTWPTR(%a6)
                   2482:
                   2483:        mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
                   2484:        addq.l          &0x4,EXC_EXTWPTR(%a6)   # incr instruction ptr
                   2485:        bsr.l           _imem_read_long         # fetch the instruction words
                   2486:        mov.l           %d0,EXC_OPWORD(%a6)     # store OPWORD and EXTWORD
                   2487:
                   2488: #########################################################################
                   2489:
                   2490:        tst.w           %d0                     # is operation fmovem?
                   2491:        bmi.w           iea_fmovm               # yes
                   2492:
                   2493: #
                   2494: # here, we will have:
                   2495: #      fabs    fdabs   fsabs           facos           fmod
                   2496: #      fadd    fdadd   fsadd           fasin           frem
                   2497: #      fcmp                            fatan           fscale
                   2498: #      fdiv    fddiv   fsdiv           fatanh          fsin
                   2499: #      fint                            fcos            fsincos
                   2500: #      fintrz                          fcosh           fsinh
                   2501: #      fmove   fdmove  fsmove          fetox           ftan
                   2502: #      fmul    fdmul   fsmul           fetoxm1         ftanh
                   2503: #      fneg    fdneg   fsneg           fgetexp         ftentox
                   2504: #      fsgldiv                         fgetman         ftwotox
                   2505: #      fsglmul                         flog10
                   2506: #      fsqrt                           flog2
                   2507: #      fsub    fdsub   fssub           flogn
                   2508: #      ftst                            flognp1
                   2509: # which can all use f<op>.{x,p}
                   2510: # so, now it's immediate data extended precision AND PACKED FORMAT!
                   2511: #
                   2512: iea_op:
                   2513:        andi.l          &0x00ff00ff,USER_FPSR(%a6)
                   2514:
                   2515:        btst            &0xa,%d0                # is src fmt x or p?
                   2516:        bne.b           iea_op_pack             # packed
                   2517:
                   2518:
                   2519:        mov.l           EXC_EXTWPTR(%a6),%a0    # pass: ptr to #<data>
                   2520:        lea             FP_SRC(%a6),%a1         # pass: ptr to super addr
                   2521:        mov.l           &0xc,%d0                # pass: 12 bytes
                   2522:        bsr.l           _imem_read              # read extended immediate
                   2523:
                   2524:        tst.l           %d1                     # did ifetch fail?
                   2525:        bne.w           iea_iacc                # yes
                   2526:
                   2527:        bra.b           iea_op_setsrc
                   2528:
                   2529: iea_op_pack:
                   2530:
                   2531:        mov.l           EXC_EXTWPTR(%a6),%a0    # pass: ptr to #<data>
                   2532:        lea             FP_SRC(%a6),%a1         # pass: ptr to super dst
                   2533:        mov.l           &0xc,%d0                # pass: 12 bytes
                   2534:        bsr.l           _imem_read              # read packed operand
                   2535:
                   2536:        tst.l           %d1                     # did ifetch fail?
                   2537:        bne.w           iea_iacc                # yes
                   2538:
                   2539: # The packed operand is an INF or a NAN if the exponent field is all ones.
                   2540:        bfextu          FP_SRC(%a6){&1:&15},%d0 # get exp
                   2541:        cmpi.w          %d0,&0x7fff             # INF or NAN?
                   2542:        beq.b           iea_op_setsrc           # operand is an INF or NAN
                   2543:
                   2544: # The packed operand is a zero if the mantissa is all zero, else it's
                   2545: # a normal packed op.
                   2546:        mov.b           3+FP_SRC(%a6),%d0       # get byte 4
                   2547:        andi.b          &0x0f,%d0               # clear all but last nybble
                   2548:        bne.b           iea_op_gp_not_spec      # not a zero
                   2549:        tst.l           FP_SRC_HI(%a6)          # is lw 2 zero?
                   2550:        bne.b           iea_op_gp_not_spec      # not a zero
                   2551:        tst.l           FP_SRC_LO(%a6)          # is lw 3 zero?
                   2552:        beq.b           iea_op_setsrc           # operand is a ZERO
                   2553: iea_op_gp_not_spec:
                   2554:        lea             FP_SRC(%a6),%a0         # pass: ptr to packed op
                   2555:        bsr.l           decbin                  # convert to extended
                   2556:        fmovm.x         &0x80,FP_SRC(%a6)       # make this the srcop
                   2557:
                   2558: iea_op_setsrc:
                   2559:        addi.l          &0xc,EXC_EXTWPTR(%a6)   # update extension word pointer
                   2560:
                   2561: # FP_SRC now holds the src operand.
                   2562:        lea             FP_SRC(%a6),%a0         # pass: ptr to src op
                   2563:        bsr.l           set_tag_x               # tag the operand type
                   2564:        mov.b           %d0,STAG(%a6)           # could be ANYTHING!!!
                   2565:        cmpi.b          %d0,&UNNORM             # is operand an UNNORM?
                   2566:        bne.b           iea_op_getdst           # no
                   2567:        bsr.l           unnorm_fix              # yes; convert to NORM/DENORM/ZERO
                   2568:        mov.b           %d0,STAG(%a6)           # set new optype tag
                   2569: iea_op_getdst:
                   2570:        clr.b           STORE_FLG(%a6)          # clear "store result" boolean
                   2571:
                   2572:        btst            &0x5,1+EXC_CMDREG(%a6)  # is operation monadic or dyadic?
                   2573:        beq.b           iea_op_extract          # monadic
                   2574:        btst            &0x4,1+EXC_CMDREG(%a6)  # is operation fsincos,ftst,fcmp?
                   2575:        bne.b           iea_op_spec             # yes
                   2576:
                   2577: iea_op_loaddst:
                   2578:        bfextu          EXC_CMDREG(%a6){&6:&3},%d0 # fetch dst regno
                   2579:        bsr.l           load_fpn2               # load dst operand
                   2580:
                   2581:        lea             FP_DST(%a6),%a0         # pass: ptr to dst op
                   2582:        bsr.l           set_tag_x               # tag the operand type
                   2583:        mov.b           %d0,DTAG(%a6)           # could be ANYTHING!!!
                   2584:        cmpi.b          %d0,&UNNORM             # is operand an UNNORM?
                   2585:        bne.b           iea_op_extract          # no
                   2586:        bsr.l           unnorm_fix              # yes; convert to NORM/DENORM/ZERO
                   2587:        mov.b           %d0,DTAG(%a6)           # set new optype tag
                   2588:        bra.b           iea_op_extract
                   2589:
                   2590: # the operation is fsincos, ftst, or fcmp. only fcmp is dyadic
                   2591: iea_op_spec:
                   2592:        btst            &0x3,1+EXC_CMDREG(%a6)  # is operation fsincos?
                   2593:        beq.b           iea_op_extract          # yes
                   2594: # now, we're left with ftst and fcmp. so, first let's tag them so that they don't
                   2595: # store a result. then, only fcmp will branch back and pick up a dst operand.
                   2596:        st              STORE_FLG(%a6)          # don't store a final result
                   2597:        btst            &0x1,1+EXC_CMDREG(%a6)  # is operation fcmp?
                   2598:        beq.b           iea_op_loaddst          # yes
                   2599:
                   2600: iea_op_extract:
                   2601:        clr.l           %d0
                   2602:        mov.b           FPCR_MODE(%a6),%d0      # pass: rnd mode,prec
                   2603:
                   2604:        mov.b           1+EXC_CMDREG(%a6),%d1
                   2605:        andi.w          &0x007f,%d1             # extract extension
                   2606:
                   2607:        fmov.l          &0x0,%fpcr
                   2608:        fmov.l          &0x0,%fpsr
                   2609:
                   2610:        lea             FP_SRC(%a6),%a0
                   2611:        lea             FP_DST(%a6),%a1
                   2612:
                   2613:        mov.l           (tbl_unsupp.l,%pc,%d1.w*4),%d1 # fetch routine addr
                   2614:        jsr             (tbl_unsupp.l,%pc,%d1.l*1)
                   2615:
                   2616: #
                   2617: # Exceptions in order of precedence:
                   2618: #      BSUN    : none
                   2619: #      SNAN    : all operations
                   2620: #      OPERR   : all reg-reg or mem-reg operations that can normally operr
                   2621: #      OVFL    : same as OPERR
                   2622: #      UNFL    : same as OPERR
                   2623: #      DZ      : same as OPERR
                   2624: #      INEX2   : same as OPERR
                   2625: #      INEX1   : all packed immediate operations
                   2626: #
                   2627:
                   2628: # we determine the highest priority exception(if any) set by the
                   2629: # emulation routine that has also been enabled by the user.
                   2630:        mov.b           FPCR_ENABLE(%a6),%d0    # fetch exceptions enabled
                   2631:        bne.b           iea_op_ena              # some are enabled
                   2632:
                   2633: # now, we save the result, unless, of course, the operation was ftst or fcmp.
                   2634: # these don't save results.
                   2635: iea_op_save:
                   2636:        tst.b           STORE_FLG(%a6)          # does this op store a result?
                   2637:        bne.b           iea_op_exit1            # exit with no frestore
                   2638:
                   2639: iea_op_store:
                   2640:        bfextu          EXC_CMDREG(%a6){&6:&3},%d0 # fetch dst regno
                   2641:        bsr.l           store_fpreg             # store the result
                   2642:
                   2643: iea_op_exit1:
                   2644:        mov.l           EXC_PC(%a6),USER_FPIAR(%a6) # set FPIAR to "Current PC"
                   2645:        mov.l           EXC_EXTWPTR(%a6),EXC_PC(%a6) # set "Next PC" in exc frame
                   2646:
                   2647:        fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0-fp1
                   2648:        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
                   2649:        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
                   2650:
                   2651:        unlk            %a6                     # unravel the frame
                   2652:
                   2653:        btst            &0x7,(%sp)              # is trace on?
                   2654:        bne.w           iea_op_trace            # yes
                   2655:
                   2656:        bra.l           _fpsp_done              # exit to os
                   2657:
                   2658: iea_op_ena:
                   2659:        and.b           FPSR_EXCEPT(%a6),%d0    # keep only ones enable and set
                   2660:        bfffo           %d0{&24:&8},%d0         # find highest priority exception
                   2661:        bne.b           iea_op_exc              # at least one was set
                   2662:
                   2663: # no exception occurred. now, did a disabled, exact overflow occur with inexact
                   2664: # enabled? if so, then we have to stuff an overflow frame into the FPU.
                   2665:        btst            &ovfl_bit,FPSR_EXCEPT(%a6) # did overflow occur?
                   2666:        beq.b           iea_op_save
                   2667:
                   2668: iea_op_ovfl:
                   2669:        btst            &inex2_bit,FPCR_ENABLE(%a6) # is inexact enabled?
                   2670:        beq.b           iea_op_store            # no
                   2671:        bra.b           iea_op_exc_ovfl         # yes
                   2672:
                   2673: # an enabled exception occurred. we have to insert the exception type back into
                   2674: # the machine.
                   2675: iea_op_exc:
                   2676:        subi.l          &24,%d0                 # fix offset to be 0-8
                   2677:        cmpi.b          %d0,&0x6                # is exception INEX?
                   2678:        bne.b           iea_op_exc_force        # no
                   2679:
                   2680: # the enabled exception was inexact. so, if it occurs with an overflow
                   2681: # or underflow that was disabled, then we have to force an overflow or
                   2682: # underflow frame.
                   2683:        btst            &ovfl_bit,FPSR_EXCEPT(%a6) # did overflow occur?
                   2684:        bne.b           iea_op_exc_ovfl         # yes
                   2685:        btst            &unfl_bit,FPSR_EXCEPT(%a6) # did underflow occur?
                   2686:        bne.b           iea_op_exc_unfl         # yes
                   2687:
                   2688: iea_op_exc_force:
                   2689:        mov.w           (tbl_iea_except.b,%pc,%d0.w*2),2+FP_SRC(%a6)
                   2690:        bra.b           iea_op_exit2            # exit with frestore
                   2691:
                   2692: tbl_iea_except:
                   2693:        short           0xe002, 0xe006, 0xe004, 0xe005
                   2694:        short           0xe003, 0xe002, 0xe001, 0xe001
                   2695:
                   2696: iea_op_exc_ovfl:
                   2697:        mov.w           &0xe005,2+FP_SRC(%a6)
                   2698:        bra.b           iea_op_exit2
                   2699:
                   2700: iea_op_exc_unfl:
                   2701:        mov.w           &0xe003,2+FP_SRC(%a6)
                   2702:
                   2703: iea_op_exit2:
                   2704:        mov.l           EXC_PC(%a6),USER_FPIAR(%a6) # set FPIAR to "Current PC"
                   2705:        mov.l           EXC_EXTWPTR(%a6),EXC_PC(%a6) # set "Next PC" in exc frame
                   2706:
                   2707:        fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0-fp1
                   2708:        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
                   2709:        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
                   2710:
                   2711:        frestore        FP_SRC(%a6)             # restore exceptional state
                   2712:
                   2713:        unlk            %a6                     # unravel the frame
                   2714:
                   2715:        btst            &0x7,(%sp)              # is trace on?
                   2716:        bne.b           iea_op_trace            # yes
                   2717:
                   2718:        bra.l           _fpsp_done              # exit to os
                   2719:
                   2720: #
                   2721: # The opclass two instruction that took an "Unimplemented Effective Address"
                   2722: # exception was being traced. Make the "current" PC the FPIAR and put it in
                   2723: # the trace stack frame then jump to _real_trace().
                   2724: #
                   2725: #               UNIMP EA FRAME            TRACE FRAME
                   2726: #              *****************       *****************
                   2727: #              * 0x0 *  0x0f0  *       *    Current    *
                   2728: #              *****************       *      PC       *
                   2729: #              *    Current    *       *****************
                   2730: #              *      PC       *       * 0x2 *  0x024  *
                   2731: #              *****************       *****************
                   2732: #              *      SR       *       *     Next      *
                   2733: #              *****************       *      PC       *
                   2734: #                                      *****************
                   2735: #                                      *      SR       *
                   2736: #                                      *****************
                   2737: iea_op_trace:
                   2738:        mov.l           (%sp),-(%sp)            # shift stack frame "down"
                   2739:        mov.w           0x8(%sp),0x4(%sp)
                   2740:        mov.w           &0x2024,0x6(%sp)        # stk fmt = 0x2; voff = 0x024
                   2741:        fmov.l          %fpiar,0x8(%sp)         # "Current PC" is in FPIAR
                   2742:
                   2743:        bra.l           _real_trace
                   2744:
                   2745: #########################################################################
                   2746: iea_fmovm:
                   2747:        btst            &14,%d0                 # ctrl or data reg
                   2748:        beq.w           iea_fmovm_ctrl
                   2749:
                   2750: iea_fmovm_data:
                   2751:
                   2752:        btst            &0x5,EXC_SR(%a6)        # user or supervisor mode
                   2753:        bne.b           iea_fmovm_data_s
                   2754:
                   2755: iea_fmovm_data_u:
                   2756:        mov.l           %usp,%a0
                   2757:        mov.l           %a0,EXC_A7(%a6)         # store current a7
                   2758:        bsr.l           fmovm_dynamic           # do dynamic fmovm
                   2759:        mov.l           EXC_A7(%a6),%a0         # load possibly new a7
                   2760:        mov.l           %a0,%usp                # update usp
                   2761:        bra.w           iea_fmovm_exit
                   2762:
                   2763: iea_fmovm_data_s:
                   2764:        clr.b           SPCOND_FLG(%a6)
                   2765:        lea             0x2+EXC_VOFF(%a6),%a0
                   2766:        mov.l           %a0,EXC_A7(%a6)
                   2767:        bsr.l           fmovm_dynamic           # do dynamic fmovm
                   2768:
                   2769:        cmpi.b          SPCOND_FLG(%a6),&mda7_flg
                   2770:        beq.w           iea_fmovm_data_predec
                   2771:        cmpi.b          SPCOND_FLG(%a6),&mia7_flg
                   2772:        bne.w           iea_fmovm_exit
                   2773:
                   2774: # right now, d0 = the size.
                   2775: # the data has been fetched from the supervisor stack, but we have not
                   2776: # incremented the stack pointer by the appropriate number of bytes.
                   2777: # do it here.
                   2778: iea_fmovm_data_postinc:
                   2779:        btst            &0x7,EXC_SR(%a6)
                   2780:        bne.b           iea_fmovm_data_pi_trace
                   2781:
                   2782:        mov.w           EXC_SR(%a6),(EXC_SR,%a6,%d0)
                   2783:        mov.l           EXC_EXTWPTR(%a6),(EXC_PC,%a6,%d0)
                   2784:        mov.w           &0x00f0,(EXC_VOFF,%a6,%d0)
                   2785:
                   2786:        lea             (EXC_SR,%a6,%d0),%a0
                   2787:        mov.l           %a0,EXC_SR(%a6)
                   2788:
                   2789:        fmovm.x         EXC_FP0(%a6),&0xc0      # restore fp0-fp1
                   2790:        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
                   2791:        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
                   2792:
                   2793:        unlk            %a6
                   2794:        mov.l           (%sp)+,%sp
                   2795:        bra.l           _fpsp_done
                   2796:
                   2797: iea_fmovm_data_pi_trace:
                   2798:        mov.w           EXC_SR(%a6),(EXC_SR-0x4,%a6,%d0)
                   2799:        mov.l           EXC_EXTWPTR(%a6),(EXC_PC-0x4,%a6,%d0)
                   2800:        mov.w           &0x2024,(EXC_VOFF-0x4,%a6,%d0)
                   2801:        mov.l           EXC_PC(%a6),(EXC_VOFF+0x2-0x4,%a6,%d0)
                   2802:
                   2803:        lea             (EXC_SR-0x4,%a6,%d0),%a0
                   2804:        mov.l           %a0,EXC_SR(%a6)
                   2805:
                   2806:        fmovm.x         EXC_FP0(%a6),&0xc0      # restore fp0-fp1
                   2807:        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
                   2808:        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
                   2809:
                   2810:        unlk            %a6
                   2811:        mov.l           (%sp)+,%sp
                   2812:        bra.l           _real_trace
                   2813:
                   2814: # right now, d1 = size and d0 = the strg.
                   2815: iea_fmovm_data_predec:
                   2816:        mov.b           %d1,EXC_VOFF(%a6)       # store strg
                   2817:        mov.b           %d0,0x1+EXC_VOFF(%a6)   # store size
                   2818:
                   2819:        fmovm.x         EXC_FP0(%a6),&0xc0      # restore fp0-fp1
                   2820:        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
                   2821:        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
                   2822:
                   2823:        mov.l           (%a6),-(%sp)            # make a copy of a6
                   2824:        mov.l           %d0,-(%sp)              # save d0
                   2825:        mov.l           %d1,-(%sp)              # save d1
                   2826:        mov.l           EXC_EXTWPTR(%a6),-(%sp) # make a copy of Next PC
                   2827:
                   2828:        clr.l           %d0
                   2829:        mov.b           0x1+EXC_VOFF(%a6),%d0   # fetch size
                   2830:        neg.l           %d0                     # get negative of size
                   2831:
                   2832:        btst            &0x7,EXC_SR(%a6)        # is trace enabled?
                   2833:        beq.b           iea_fmovm_data_p2
                   2834:
                   2835:        mov.w           EXC_SR(%a6),(EXC_SR-0x4,%a6,%d0)
                   2836:        mov.l           EXC_PC(%a6),(EXC_VOFF-0x2,%a6,%d0)
                   2837:        mov.l           (%sp)+,(EXC_PC-0x4,%a6,%d0)
                   2838:        mov.w           &0x2024,(EXC_VOFF-0x4,%a6,%d0)
                   2839:
                   2840:        pea             (%a6,%d0)               # create final sp
                   2841:        bra.b           iea_fmovm_data_p3
                   2842:
                   2843: iea_fmovm_data_p2:
                   2844:        mov.w           EXC_SR(%a6),(EXC_SR,%a6,%d0)
                   2845:        mov.l           (%sp)+,(EXC_PC,%a6,%d0)
                   2846:        mov.w           &0x00f0,(EXC_VOFF,%a6,%d0)
                   2847:
                   2848:        pea             (0x4,%a6,%d0)           # create final sp
                   2849:
                   2850: iea_fmovm_data_p3:
                   2851:        clr.l           %d1
                   2852:        mov.b           EXC_VOFF(%a6),%d1       # fetch strg
                   2853:
                   2854:        tst.b           %d1
                   2855:        bpl.b           fm_1
                   2856:        fmovm.x         &0x80,(0x4+0x8,%a6,%d0)
                   2857:        addi.l          &0xc,%d0
                   2858: fm_1:
                   2859:        lsl.b           &0x1,%d1
                   2860:        bpl.b           fm_2
                   2861:        fmovm.x         &0x40,(0x4+0x8,%a6,%d0)
                   2862:        addi.l          &0xc,%d0
                   2863: fm_2:
                   2864:        lsl.b           &0x1,%d1
                   2865:        bpl.b           fm_3
                   2866:        fmovm.x         &0x20,(0x4+0x8,%a6,%d0)
                   2867:        addi.l          &0xc,%d0
                   2868: fm_3:
                   2869:        lsl.b           &0x1,%d1
                   2870:        bpl.b           fm_4
                   2871:        fmovm.x         &0x10,(0x4+0x8,%a6,%d0)
                   2872:        addi.l          &0xc,%d0
                   2873: fm_4:
                   2874:        lsl.b           &0x1,%d1
                   2875:        bpl.b           fm_5
                   2876:        fmovm.x         &0x08,(0x4+0x8,%a6,%d0)
                   2877:        addi.l          &0xc,%d0
                   2878: fm_5:
                   2879:        lsl.b           &0x1,%d1
                   2880:        bpl.b           fm_6
                   2881:        fmovm.x         &0x04,(0x4+0x8,%a6,%d0)
                   2882:        addi.l          &0xc,%d0
                   2883: fm_6:
                   2884:        lsl.b           &0x1,%d1
                   2885:        bpl.b           fm_7
                   2886:        fmovm.x         &0x02,(0x4+0x8,%a6,%d0)
                   2887:        addi.l          &0xc,%d0
                   2888: fm_7:
                   2889:        lsl.b           &0x1,%d1
                   2890:        bpl.b           fm_end
                   2891:        fmovm.x         &0x01,(0x4+0x8,%a6,%d0)
                   2892: fm_end:
                   2893:        mov.l           0x4(%sp),%d1
                   2894:        mov.l           0x8(%sp),%d0
                   2895:        mov.l           0xc(%sp),%a6
                   2896:        mov.l           (%sp)+,%sp
                   2897:
                   2898:        btst            &0x7,(%sp)              # is trace enabled?
                   2899:        beq.l           _fpsp_done
                   2900:        bra.l           _real_trace
                   2901:
                   2902: #########################################################################
                   2903: iea_fmovm_ctrl:
                   2904:
                   2905:        bsr.l           fmovm_ctrl              # load ctrl regs
                   2906:
                   2907: iea_fmovm_exit:
                   2908:        fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0-fp1
                   2909:        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
                   2910:        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
                   2911:
                   2912:        btst            &0x7,EXC_SR(%a6)        # is trace on?
                   2913:        bne.b           iea_fmovm_trace         # yes
                   2914:
                   2915:        mov.l           EXC_EXTWPTR(%a6),EXC_PC(%a6) # set Next PC
                   2916:
                   2917:        unlk            %a6                     # unravel the frame
                   2918:
                   2919:        bra.l           _fpsp_done              # exit to os
                   2920:
                   2921: #
                   2922: # The control reg instruction that took an "Unimplemented Effective Address"
                   2923: # exception was being traced. The "Current PC" for the trace frame is the
                   2924: # PC stacked for Unimp EA. The "Next PC" is in EXC_EXTWPTR.
                   2925: # After fixing the stack frame, jump to _real_trace().
                   2926: #
                   2927: #               UNIMP EA FRAME            TRACE FRAME
                   2928: #              *****************       *****************
                   2929: #              * 0x0 *  0x0f0  *       *    Current    *
                   2930: #              *****************       *      PC       *
                   2931: #              *    Current    *       *****************
                   2932: #              *      PC       *       * 0x2 *  0x024  *
                   2933: #              *****************       *****************
                   2934: #              *      SR       *       *     Next      *
                   2935: #              *****************       *      PC       *
                   2936: #                                      *****************
                   2937: #                                      *      SR       *
                   2938: #                                      *****************
                   2939: # this ain't a pretty solution, but it works:
                   2940: # -restore a6 (not with unlk)
                   2941: # -shift stack frame down over where old a6 used to be
                   2942: # -add LOCAL_SIZE to stack pointer
                   2943: iea_fmovm_trace:
                   2944:        mov.l           (%a6),%a6               # restore frame pointer
                   2945:        mov.w           EXC_SR+LOCAL_SIZE(%sp),0x0+LOCAL_SIZE(%sp)
                   2946:        mov.l           EXC_PC+LOCAL_SIZE(%sp),0x8+LOCAL_SIZE(%sp)
                   2947:        mov.l           EXC_EXTWPTR+LOCAL_SIZE(%sp),0x2+LOCAL_SIZE(%sp)
                   2948:        mov.w           &0x2024,0x6+LOCAL_SIZE(%sp) # stk fmt = 0x2; voff = 0x024
                   2949:        add.l           &LOCAL_SIZE,%sp         # clear stack frame
                   2950:
                   2951:        bra.l           _real_trace
                   2952:
                   2953: #########################################################################
                   2954: # The FPU is disabled and so we should really have taken the "Line
                   2955: # F Emulator" exception. So, here we create an 8-word stack frame
                   2956: # from our 4-word stack frame. This means we must calculate the length
                   2957: # of the faulting instruction to get the "next PC". This is trivial for
                   2958: # immediate operands but requires some extra work for fmovm dynamic
                   2959: # which can use most addressing modes.
                   2960: iea_disabled:
                   2961:        mov.l           (%sp)+,%d0              # restore d0
                   2962:
                   2963:        link            %a6,&-LOCAL_SIZE        # init stack frame
                   2964:
                   2965:        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
                   2966:
                   2967: # PC of instruction that took the exception is the PC in the frame
                   2968:        mov.l           EXC_PC(%a6),EXC_EXTWPTR(%a6)
                   2969:        mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
                   2970:        addq.l          &0x4,EXC_EXTWPTR(%a6)   # incr instruction ptr
                   2971:        bsr.l           _imem_read_long         # fetch the instruction words
                   2972:        mov.l           %d0,EXC_OPWORD(%a6)     # store OPWORD and EXTWORD
                   2973:
                   2974:        tst.w           %d0                     # is instr fmovm?
                   2975:        bmi.b           iea_dis_fmovm           # yes
                   2976: # instruction is using an extended precision immediate operand. therefore,
                   2977: # the total instruction length is 16 bytes.
                   2978: iea_dis_immed:
                   2979:        mov.l           &0x10,%d0               # 16 bytes of instruction
                   2980:        bra.b           iea_dis_cont
                   2981: iea_dis_fmovm:
                   2982:        btst            &0xe,%d0                # is instr fmovm ctrl
                   2983:        bne.b           iea_dis_fmovm_data      # no
                   2984: # the instruction is a fmovm.l with 2 or 3 registers.
                   2985:        bfextu          %d0{&19:&3},%d1
                   2986:        mov.l           &0xc,%d0
                   2987:        cmpi.b          %d1,&0x7                # move all regs?
                   2988:        bne.b           iea_dis_cont
                   2989:        addq.l          &0x4,%d0
                   2990:        bra.b           iea_dis_cont
                   2991: # the instruction is an fmovm.x dynamic which can use many addressing
                   2992: # modes and thus can have several different total instruction lengths.
                   2993: # call fmovm_calc_ea which will go through the ea calc process and,
                   2994: # as a by-product, will tell us how long the instruction is.
                   2995: iea_dis_fmovm_data:
                   2996:        clr.l           %d0
                   2997:        bsr.l           fmovm_calc_ea
                   2998:        mov.l           EXC_EXTWPTR(%a6),%d0
                   2999:        sub.l           EXC_PC(%a6),%d0
                   3000: iea_dis_cont:
                   3001:        mov.w           %d0,EXC_VOFF(%a6)       # store stack shift value
                   3002:
                   3003:        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
                   3004:
                   3005:        unlk            %a6
                   3006:
                   3007: # here, we actually create the 8-word frame from the 4-word frame,
                   3008: # with the "next PC" as additional info.
                   3009: # the <ea> field is let as undefined.
                   3010:        subq.l          &0x8,%sp                # make room for new stack
                   3011:        mov.l           %d0,-(%sp)              # save d0
                   3012:        mov.w           0xc(%sp),0x4(%sp)       # move SR
                   3013:        mov.l           0xe(%sp),0x6(%sp)       # move Current PC
                   3014:        clr.l           %d0
                   3015:        mov.w           0x12(%sp),%d0
                   3016:        mov.l           0x6(%sp),0x10(%sp)      # move Current PC
                   3017:        add.l           %d0,0x6(%sp)            # make Next PC
                   3018:        mov.w           &0x402c,0xa(%sp)        # insert offset,frame format
                   3019:        mov.l           (%sp)+,%d0              # restore d0
                   3020:
                   3021:        bra.l           _real_fpu_disabled
                   3022:
                   3023: ##########
                   3024:
                   3025: iea_iacc:
                   3026:        movc            %pcr,%d0
                   3027:        btst            &0x1,%d0
                   3028:        bne.b           iea_iacc_cont
                   3029:        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
                   3030:        fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0-fp1 on stack
                   3031: iea_iacc_cont:
                   3032:        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
                   3033:
                   3034:        unlk            %a6
                   3035:
                   3036:        subq.w          &0x8,%sp                # make stack frame bigger
                   3037:        mov.l           0x8(%sp),(%sp)          # store SR,hi(PC)
                   3038:        mov.w           0xc(%sp),0x4(%sp)       # store lo(PC)
                   3039:        mov.w           &0x4008,0x6(%sp)        # store voff
                   3040:        mov.l           0x2(%sp),0x8(%sp)       # store ea
                   3041:        mov.l           &0x09428001,0xc(%sp)    # store fslw
                   3042:
                   3043: iea_acc_done:
                   3044:        btst            &0x5,(%sp)              # user or supervisor mode?
                   3045:        beq.b           iea_acc_done2           # user
                   3046:        bset            &0x2,0xd(%sp)           # set supervisor TM bit
                   3047:
                   3048: iea_acc_done2:
                   3049:        bra.l           _real_access
                   3050:
                   3051: iea_dacc:
                   3052:        lea             -LOCAL_SIZE(%a6),%sp
                   3053:
                   3054:        movc            %pcr,%d1
                   3055:        btst            &0x1,%d1
                   3056:        bne.b           iea_dacc_cont
                   3057:        fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0-fp1 on stack
                   3058:        fmovm.l         LOCAL_SIZE+USER_FPCR(%sp),%fpcr,%fpsr,%fpiar # restore ctrl regs
                   3059: iea_dacc_cont:
                   3060:        mov.l           (%a6),%a6
                   3061:
                   3062:        mov.l           0x4+LOCAL_SIZE(%sp),-0x8+0x4+LOCAL_SIZE(%sp)
                   3063:        mov.w           0x8+LOCAL_SIZE(%sp),-0x8+0x8+LOCAL_SIZE(%sp)
                   3064:        mov.w           &0x4008,-0x8+0xa+LOCAL_SIZE(%sp)
                   3065:        mov.l           %a0,-0x8+0xc+LOCAL_SIZE(%sp)
                   3066:        mov.w           %d0,-0x8+0x10+LOCAL_SIZE(%sp)
                   3067:        mov.w           &0x0001,-0x8+0x12+LOCAL_SIZE(%sp)
                   3068:
                   3069:        movm.l          LOCAL_SIZE+EXC_DREGS(%sp),&0x0303 # restore d0-d1/a0-a1
                   3070:        add.w           &LOCAL_SIZE-0x4,%sp
                   3071:
                   3072:        bra.b           iea_acc_done
                   3073:
                   3074: #########################################################################
                   3075: # XDEF ****************************************************************        #
                   3076: #      _fpsp_operr(): 060FPSP entry point for FP Operr exception.      #
                   3077: #                                                                      #
                   3078: #      This handler should be the first code executed upon taking the  #
                   3079: #      FP Operand Error exception in an operating system.              #
                   3080: #                                                                      #
                   3081: # XREF ****************************************************************        #
                   3082: #      _imem_read_long() - read instruction longword                   #
                   3083: #      fix_skewed_ops() - adjust src operand in fsave frame            #
                   3084: #      _real_operr() - "callout" to operating system operr handler     #
                   3085: #      _dmem_write_{byte,word,long}() - store data to mem (opclass 3)  #
                   3086: #      store_dreg_{b,w,l}() - store data to data regfile (opclass 3)   #
                   3087: #      facc_out_{b,w,l}() - store to memory took access error (opcl 3) #
                   3088: #                                                                      #
                   3089: # INPUT ***************************************************************        #
                   3090: #      - The system stack contains the FP Operr exception frame        #
                   3091: #      - The fsave frame contains the source operand                   #
                   3092: #                                                                      #
                   3093: # OUTPUT **************************************************************        #
                   3094: #      No access error:                                                #
                   3095: #      - The system stack is unchanged                                 #
                   3096: #      - The fsave frame contains the adjusted src op for opclass 0,2  #
                   3097: #                                                                      #
                   3098: # ALGORITHM ***********************************************************        #
                   3099: #      In a system where the FP Operr exception is enabled, the goal   #
                   3100: # is to get to the handler specified at _real_operr(). But, on the 060,        #
                   3101: # for opclass zero and two instruction taking this exception, the      #
                   3102: # input operand in the fsave frame may be incorrect for some cases     #
                   3103: # and needs to be corrected. This handler calls fix_skewed_ops() to    #
                   3104: # do just this and then exits through _real_operr().                   #
                   3105: #      For opclass 3 instructions, the 060 doesn't store the default   #
                   3106: # operr result out to memory or data register file as it should.       #
                   3107: # This code must emulate the move out before finally exiting through   #
                   3108: # _real_inex(). The move out, if to memory, is performed using                 #
                   3109: # _mem_write() "callout" routines that may return a failing result.    #
                   3110: # In this special case, the handler must exit through facc_out()       #
                   3111: # which creates an access error stack frame from the current operr     #
                   3112: # stack frame.                                                         #
                   3113: #                                                                      #
                   3114: #########################################################################
                   3115:
                   3116:        global          _fpsp_operr
                   3117: _fpsp_operr:
                   3118:
                   3119:        link.w          %a6,&-LOCAL_SIZE        # init stack frame
                   3120:
                   3121:        fsave           FP_SRC(%a6)             # grab the "busy" frame
                   3122:
                   3123:        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
                   3124:        fmovm.l         %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
                   3125:        fmovm.x         &0xc0,EXC_FPREGS(%a6)   # save fp0-fp1 on stack
                   3126:
                   3127: # the FPIAR holds the "current PC" of the faulting instruction
                   3128:        mov.l           USER_FPIAR(%a6),EXC_EXTWPTR(%a6)
                   3129:
                   3130:        mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
                   3131:        addq.l          &0x4,EXC_EXTWPTR(%a6)   # incr instruction ptr
                   3132:        bsr.l           _imem_read_long         # fetch the instruction words
                   3133:        mov.l           %d0,EXC_OPWORD(%a6)
                   3134:
                   3135: ##############################################################################
                   3136:
                   3137:        btst            &13,%d0                 # is instr an fmove out?
                   3138:        bne.b           foperr_out              # fmove out
                   3139:
                   3140:
                   3141: # here, we simply see if the operand in the fsave frame needs to be "unskewed".
                   3142: # this would be the case for opclass two operations with a source infinity or
                   3143: # denorm operand in the sgl or dbl format. NANs also become skewed, but can't
                   3144: # cause an operr so we don't need to check for them here.
                   3145:        lea             FP_SRC(%a6),%a0         # pass: ptr to src op
                   3146:        bsr.l           fix_skewed_ops          # fix src op
                   3147:
                   3148: foperr_exit:
                   3149:        fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0-fp1
                   3150:        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
                   3151:        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
                   3152:
                   3153:        frestore        FP_SRC(%a6)
                   3154:
                   3155:        unlk            %a6
                   3156:        bra.l           _real_operr
                   3157:
                   3158: ########################################################################
                   3159:
                   3160: #
                   3161: # the hardware does not save the default result to memory on enabled
                   3162: # operand error exceptions. we do this here before passing control to
                   3163: # the user operand error handler.
                   3164: #
                   3165: # byte, word, and long destination format operations can pass
                   3166: # through here. we simply need to test the sign of the src
                   3167: # operand and save the appropriate minimum or maximum integer value
                   3168: # to the effective address as pointed to by the stacked effective address.
                   3169: #
                   3170: # although packed opclass three operations can take operand error
                   3171: # exceptions, they won't pass through here since they are caught
                   3172: # first by the unsupported data format exception handler. that handler
                   3173: # sends them directly to _real_operr() if necessary.
                   3174: #
                   3175: foperr_out:
                   3176:
                   3177:        mov.w           FP_SRC_EX(%a6),%d1      # fetch exponent
                   3178:        andi.w          &0x7fff,%d1
                   3179:        cmpi.w          %d1,&0x7fff
                   3180:        bne.b           foperr_out_not_qnan
                   3181: # the operand is either an infinity or a QNAN.
                   3182:        tst.l           FP_SRC_LO(%a6)
                   3183:        bne.b           foperr_out_qnan
                   3184:        mov.l           FP_SRC_HI(%a6),%d1
                   3185:        andi.l          &0x7fffffff,%d1
                   3186:        beq.b           foperr_out_not_qnan
                   3187: foperr_out_qnan:
                   3188:        mov.l           FP_SRC_HI(%a6),L_SCR1(%a6)
                   3189:        bra.b           foperr_out_jmp
                   3190:
                   3191: foperr_out_not_qnan:
                   3192:        mov.l           &0x7fffffff,%d1
                   3193:        tst.b           FP_SRC_EX(%a6)
                   3194:        bpl.b           foperr_out_not_qnan2
                   3195:        addq.l          &0x1,%d1
                   3196: foperr_out_not_qnan2:
                   3197:        mov.l           %d1,L_SCR1(%a6)
                   3198:
                   3199: foperr_out_jmp:
                   3200:        bfextu          %d0{&19:&3},%d0         # extract dst format field
                   3201:        mov.b           1+EXC_OPWORD(%a6),%d1   # extract <ea> mode,reg
                   3202:        mov.w           (tbl_operr.b,%pc,%d0.w*2),%a0
                   3203:        jmp             (tbl_operr.b,%pc,%a0)
                   3204:
                   3205: tbl_operr:
                   3206:        short           foperr_out_l - tbl_operr # long word integer
                   3207:        short           tbl_operr    - tbl_operr # sgl prec shouldn't happen
                   3208:        short           tbl_operr    - tbl_operr # ext prec shouldn't happen
                   3209:        short           foperr_exit  - tbl_operr # packed won't enter here
                   3210:        short           foperr_out_w - tbl_operr # word integer
                   3211:        short           tbl_operr    - tbl_operr # dbl prec shouldn't happen
                   3212:        short           foperr_out_b - tbl_operr # byte integer
                   3213:        short           tbl_operr    - tbl_operr # packed won't enter here
                   3214:
                   3215: foperr_out_b:
                   3216:        mov.b           L_SCR1(%a6),%d0         # load positive default result
                   3217:        cmpi.b          %d1,&0x7                # is <ea> mode a data reg?
                   3218:        ble.b           foperr_out_b_save_dn    # yes
                   3219:        mov.l           EXC_EA(%a6),%a0         # pass: <ea> of default result
                   3220:        bsr.l           _dmem_write_byte        # write the default result
                   3221:
                   3222:        tst.l           %d1                     # did dstore fail?
                   3223:        bne.l           facc_out_b              # yes
                   3224:
                   3225:        bra.w           foperr_exit
                   3226: foperr_out_b_save_dn:
                   3227:        andi.w          &0x0007,%d1
                   3228:        bsr.l           store_dreg_b            # store result to regfile
                   3229:        bra.w           foperr_exit
                   3230:
                   3231: foperr_out_w:
                   3232:        mov.w           L_SCR1(%a6),%d0         # load positive default result
                   3233:        cmpi.b          %d1,&0x7                # is <ea> mode a data reg?
                   3234:        ble.b           foperr_out_w_save_dn    # yes
                   3235:        mov.l           EXC_EA(%a6),%a0         # pass: <ea> of default result
                   3236:        bsr.l           _dmem_write_word        # write the default result
                   3237:
                   3238:        tst.l           %d1                     # did dstore fail?
                   3239:        bne.l           facc_out_w              # yes
                   3240:
                   3241:        bra.w           foperr_exit
                   3242: foperr_out_w_save_dn:
                   3243:        andi.w          &0x0007,%d1
                   3244:        bsr.l           store_dreg_w            # store result to regfile
                   3245:        bra.w           foperr_exit
                   3246:
                   3247: foperr_out_l:
                   3248:        mov.l           L_SCR1(%a6),%d0         # load positive default result
                   3249:        cmpi.b          %d1,&0x7                # is <ea> mode a data reg?
                   3250:        ble.b           foperr_out_l_save_dn    # yes
                   3251:        mov.l           EXC_EA(%a6),%a0         # pass: <ea> of default result
                   3252:        bsr.l           _dmem_write_long        # write the default result
                   3253:
                   3254:        tst.l           %d1                     # did dstore fail?
                   3255:        bne.l           facc_out_l              # yes
                   3256:
                   3257:        bra.w           foperr_exit
                   3258: foperr_out_l_save_dn:
                   3259:        andi.w          &0x0007,%d1
                   3260:        bsr.l           store_dreg_l            # store result to regfile
                   3261:        bra.w           foperr_exit
                   3262:
                   3263: #########################################################################
                   3264: # XDEF ****************************************************************        #
                   3265: #      _fpsp_snan(): 060FPSP entry point for FP SNAN exception.        #
                   3266: #                                                                      #
                   3267: #      This handler should be the first code executed upon taking the  #
                   3268: #      FP Signalling NAN exception in an operating system.             #
                   3269: #                                                                      #
                   3270: # XREF ****************************************************************        #
                   3271: #      _imem_read_long() - read instruction longword                   #
                   3272: #      fix_skewed_ops() - adjust src operand in fsave frame            #
                   3273: #      _real_snan() - "callout" to operating system SNAN handler       #
                   3274: #      _dmem_write_{byte,word,long}() - store data to mem (opclass 3)  #
                   3275: #      store_dreg_{b,w,l}() - store data to data regfile (opclass 3)   #
                   3276: #      facc_out_{b,w,l,d,x}() - store to mem took acc error (opcl 3)   #
                   3277: #      _calc_ea_fout() - fix An if <ea> is -() or ()+; also get <ea>   #
                   3278: #                                                                      #
                   3279: # INPUT ***************************************************************        #
                   3280: #      - The system stack contains the FP SNAN exception frame         #
                   3281: #      - The fsave frame contains the source operand                   #
                   3282: #                                                                      #
                   3283: # OUTPUT **************************************************************        #
                   3284: #      No access error:                                                #
                   3285: #      - The system stack is unchanged                                 #
                   3286: #      - The fsave frame contains the adjusted src op for opclass 0,2  #
                   3287: #                                                                      #
                   3288: # ALGORITHM ***********************************************************        #
                   3289: #      In a system where the FP SNAN exception is enabled, the goal    #
                   3290: # is to get to the handler specified at _real_snan(). But, on the 060, #
                   3291: # for opclass zero and two instructions taking this exception, the     #
                   3292: # input operand in the fsave frame may be incorrect for some cases     #
                   3293: # and needs to be corrected. This handler calls fix_skewed_ops() to    #
                   3294: # do just this and then exits through _real_snan().                    #
                   3295: #      For opclass 3 instructions, the 060 doesn't store the default   #
                   3296: # SNAN result out to memory or data register file as it should.                #
                   3297: # This code must emulate the move out before finally exiting through   #
                   3298: # _real_snan(). The move out, if to memory, is performed using                 #
                   3299: # _mem_write() "callout" routines that may return a failing result.    #
                   3300: # In this special case, the handler must exit through facc_out()       #
                   3301: # which creates an access error stack frame from the current SNAN      #
                   3302: # stack frame.                                                         #
                   3303: #      For the case of an extended precision opclass 3 instruction,    #
                   3304: # if the effective addressing mode was -() or ()+, then the address    #
                   3305: # register must get updated by calling _calc_ea_fout(). If the <ea>    #
                   3306: # was -(a7) from supervisor mode, then the exception frame currently   #
                   3307: # on the system stack must be carefully moved "down" to make room      #
                   3308: # for the operand being moved.                                         #
                   3309: #                                                                      #
                   3310: #########################################################################
                   3311:
                   3312:        global          _fpsp_snan
                   3313: _fpsp_snan:
                   3314:
                   3315:        link.w          %a6,&-LOCAL_SIZE        # init stack frame
                   3316:
                   3317:        fsave           FP_SRC(%a6)             # grab the "busy" frame
                   3318:
                   3319:        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
                   3320:        fmovm.l         %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
                   3321:        fmovm.x         &0xc0,EXC_FPREGS(%a6)   # save fp0-fp1 on stack
                   3322:
                   3323: # the FPIAR holds the "current PC" of the faulting instruction
                   3324:        mov.l           USER_FPIAR(%a6),EXC_EXTWPTR(%a6)
                   3325:
                   3326:        mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
                   3327:        addq.l          &0x4,EXC_EXTWPTR(%a6)   # incr instruction ptr
                   3328:        bsr.l           _imem_read_long         # fetch the instruction words
                   3329:        mov.l           %d0,EXC_OPWORD(%a6)
                   3330:
                   3331: ##############################################################################
                   3332:
                   3333:        btst            &13,%d0                 # is instr an fmove out?
                   3334:        bne.w           fsnan_out               # fmove out
                   3335:
                   3336:
                   3337: # here, we simply see if the operand in the fsave frame needs to be "unskewed".
                   3338: # this would be the case for opclass two operations with a source infinity or
                   3339: # denorm operand in the sgl or dbl format. NANs also become skewed and must be
                   3340: # fixed here.
                   3341:        lea             FP_SRC(%a6),%a0         # pass: ptr to src op
                   3342:        bsr.l           fix_skewed_ops          # fix src op
                   3343:
                   3344: fsnan_exit:
                   3345:        fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0-fp1
                   3346:        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
                   3347:        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
                   3348:
                   3349:        frestore        FP_SRC(%a6)
                   3350:
                   3351:        unlk            %a6
                   3352:        bra.l           _real_snan
                   3353:
                   3354: ########################################################################
                   3355:
                   3356: #
                   3357: # the hardware does not save the default result to memory on enabled
                   3358: # snan exceptions. we do this here before passing control to
                   3359: # the user snan handler.
                   3360: #
                   3361: # byte, word, long, and packed destination format operations can pass
                   3362: # through here. since packed format operations already were handled by
                   3363: # fpsp_unsupp(), then we need to do nothing else for them here.
                   3364: # for byte, word, and long, we simply need to test the sign of the src
                   3365: # operand and save the appropriate minimum or maximum integer value
                   3366: # to the effective address as pointed to by the stacked effective address.
                   3367: #
                   3368: fsnan_out:
                   3369:
                   3370:        bfextu          %d0{&19:&3},%d0         # extract dst format field
                   3371:        mov.b           1+EXC_OPWORD(%a6),%d1   # extract <ea> mode,reg
                   3372:        mov.w           (tbl_snan.b,%pc,%d0.w*2),%a0
                   3373:        jmp             (tbl_snan.b,%pc,%a0)
                   3374:
                   3375: tbl_snan:
                   3376:        short           fsnan_out_l - tbl_snan # long word integer
                   3377:        short           fsnan_out_s - tbl_snan # sgl prec shouldn't happen
                   3378:        short           fsnan_out_x - tbl_snan # ext prec shouldn't happen
                   3379:        short           tbl_snan    - tbl_snan # packed needs no help
                   3380:        short           fsnan_out_w - tbl_snan # word integer
                   3381:        short           fsnan_out_d - tbl_snan # dbl prec shouldn't happen
                   3382:        short           fsnan_out_b - tbl_snan # byte integer
                   3383:        short           tbl_snan    - tbl_snan # packed needs no help
                   3384:
                   3385: fsnan_out_b:
                   3386:        mov.b           FP_SRC_HI(%a6),%d0      # load upper byte of SNAN
                   3387:        bset            &6,%d0                  # set SNAN bit
                   3388:        cmpi.b          %d1,&0x7                # is <ea> mode a data reg?
                   3389:        ble.b           fsnan_out_b_dn          # yes
                   3390:        mov.l           EXC_EA(%a6),%a0         # pass: <ea> of default result
                   3391:        bsr.l           _dmem_write_byte        # write the default result
                   3392:
                   3393:        tst.l           %d1                     # did dstore fail?
                   3394:        bne.l           facc_out_b              # yes
                   3395:
                   3396:        bra.w           fsnan_exit
                   3397: fsnan_out_b_dn:
                   3398:        andi.w          &0x0007,%d1
                   3399:        bsr.l           store_dreg_b            # store result to regfile
                   3400:        bra.w           fsnan_exit
                   3401:
                   3402: fsnan_out_w:
                   3403:        mov.w           FP_SRC_HI(%a6),%d0      # load upper word of SNAN
                   3404:        bset            &14,%d0                 # set SNAN bit
                   3405:        cmpi.b          %d1,&0x7                # is <ea> mode a data reg?
                   3406:        ble.b           fsnan_out_w_dn          # yes
                   3407:        mov.l           EXC_EA(%a6),%a0         # pass: <ea> of default result
                   3408:        bsr.l           _dmem_write_word        # write the default result
                   3409:
                   3410:        tst.l           %d1                     # did dstore fail?
                   3411:        bne.l           facc_out_w              # yes
                   3412:
                   3413:        bra.w           fsnan_exit
                   3414: fsnan_out_w_dn:
                   3415:        andi.w          &0x0007,%d1
                   3416:        bsr.l           store_dreg_w            # store result to regfile
                   3417:        bra.w           fsnan_exit
                   3418:
                   3419: fsnan_out_l:
                   3420:        mov.l           FP_SRC_HI(%a6),%d0      # load upper longword of SNAN
                   3421:        bset            &30,%d0                 # set SNAN bit
                   3422:        cmpi.b          %d1,&0x7                # is <ea> mode a data reg?
                   3423:        ble.b           fsnan_out_l_dn          # yes
                   3424:        mov.l           EXC_EA(%a6),%a0         # pass: <ea> of default result
                   3425:        bsr.l           _dmem_write_long        # write the default result
                   3426:
                   3427:        tst.l           %d1                     # did dstore fail?
                   3428:        bne.l           facc_out_l              # yes
                   3429:
                   3430:        bra.w           fsnan_exit
                   3431: fsnan_out_l_dn:
                   3432:        andi.w          &0x0007,%d1
                   3433:        bsr.l           store_dreg_l            # store result to regfile
                   3434:        bra.w           fsnan_exit
                   3435:
                   3436: fsnan_out_s:
                   3437:        cmpi.b          %d1,&0x7                # is <ea> mode a data reg?
                   3438:        ble.b           fsnan_out_d_dn          # yes
                   3439:        mov.l           FP_SRC_EX(%a6),%d0      # fetch SNAN sign
                   3440:        andi.l          &0x80000000,%d0         # keep sign
                   3441:        ori.l           &0x7fc00000,%d0         # insert new exponent,SNAN bit
                   3442:        mov.l           FP_SRC_HI(%a6),%d1      # load mantissa
                   3443:        lsr.l           &0x8,%d1                # shift mantissa for sgl
                   3444:        or.l            %d1,%d0                 # create sgl SNAN
                   3445:        mov.l           EXC_EA(%a6),%a0         # pass: <ea> of default result
                   3446:        bsr.l           _dmem_write_long        # write the default result
                   3447:
                   3448:        tst.l           %d1                     # did dstore fail?
                   3449:        bne.l           facc_out_l              # yes
                   3450:
                   3451:        bra.w           fsnan_exit
                   3452: fsnan_out_d_dn:
                   3453:        mov.l           FP_SRC_EX(%a6),%d0      # fetch SNAN sign
                   3454:        andi.l          &0x80000000,%d0         # keep sign
                   3455:        ori.l           &0x7fc00000,%d0         # insert new exponent,SNAN bit
                   3456:        mov.l           %d1,-(%sp)
                   3457:        mov.l           FP_SRC_HI(%a6),%d1      # load mantissa
                   3458:        lsr.l           &0x8,%d1                # shift mantissa for sgl
                   3459:        or.l            %d1,%d0                 # create sgl SNAN
                   3460:        mov.l           (%sp)+,%d1
                   3461:        andi.w          &0x0007,%d1
                   3462:        bsr.l           store_dreg_l            # store result to regfile
                   3463:        bra.w           fsnan_exit
                   3464:
                   3465: fsnan_out_d:
                   3466:        mov.l           FP_SRC_EX(%a6),%d0      # fetch SNAN sign
                   3467:        andi.l          &0x80000000,%d0         # keep sign
                   3468:        ori.l           &0x7ff80000,%d0         # insert new exponent,SNAN bit
                   3469:        mov.l           FP_SRC_HI(%a6),%d1      # load hi mantissa
                   3470:        mov.l           %d0,FP_SCR0_EX(%a6)     # store to temp space
                   3471:        mov.l           &11,%d0                 # load shift amt
                   3472:        lsr.l           %d0,%d1
                   3473:        or.l            %d1,FP_SCR0_EX(%a6)     # create dbl hi
                   3474:        mov.l           FP_SRC_HI(%a6),%d1      # load hi mantissa
                   3475:        andi.l          &0x000007ff,%d1
                   3476:        ror.l           %d0,%d1
                   3477:        mov.l           %d1,FP_SCR0_HI(%a6)     # store to temp space
                   3478:        mov.l           FP_SRC_LO(%a6),%d1      # load lo mantissa
                   3479:        lsr.l           %d0,%d1
                   3480:        or.l            %d1,FP_SCR0_HI(%a6)     # create dbl lo
                   3481:        lea             FP_SCR0(%a6),%a0        # pass: ptr to operand
                   3482:        mov.l           EXC_EA(%a6),%a1         # pass: dst addr
                   3483:        movq.l          &0x8,%d0                # pass: size of 8 bytes
                   3484:        bsr.l           _dmem_write             # write the default result
                   3485:
                   3486:        tst.l           %d1                     # did dstore fail?
                   3487:        bne.l           facc_out_d              # yes
                   3488:
                   3489:        bra.w           fsnan_exit
                   3490:
                   3491: # for extended precision, if the addressing mode is pre-decrement or
                   3492: # post-increment, then the address register did not get updated.
                   3493: # in addition, for pre-decrement, the stacked <ea> is incorrect.
                   3494: fsnan_out_x:
                   3495:        clr.b           SPCOND_FLG(%a6)         # clear special case flag
                   3496:
                   3497:        mov.w           FP_SRC_EX(%a6),FP_SCR0_EX(%a6)
                   3498:        clr.w           2+FP_SCR0(%a6)
                   3499:        mov.l           FP_SRC_HI(%a6),%d0
                   3500:        bset            &30,%d0
                   3501:        mov.l           %d0,FP_SCR0_HI(%a6)
                   3502:        mov.l           FP_SRC_LO(%a6),FP_SCR0_LO(%a6)
                   3503:
                   3504:        btst            &0x5,EXC_SR(%a6)        # supervisor mode exception?
                   3505:        bne.b           fsnan_out_x_s           # yes
                   3506:
                   3507:        mov.l           %usp,%a0                # fetch user stack pointer
                   3508:        mov.l           %a0,EXC_A7(%a6)         # save on stack for calc_ea()
                   3509:        mov.l           (%a6),EXC_A6(%a6)
                   3510:
                   3511:        bsr.l           _calc_ea_fout           # find the correct ea,update An
                   3512:        mov.l           %a0,%a1
                   3513:        mov.l           %a0,EXC_EA(%a6)         # stack correct <ea>
                   3514:
                   3515:        mov.l           EXC_A7(%a6),%a0
                   3516:        mov.l           %a0,%usp                # restore user stack pointer
                   3517:        mov.l           EXC_A6(%a6),(%a6)
                   3518:
                   3519: fsnan_out_x_save:
                   3520:        lea             FP_SCR0(%a6),%a0        # pass: ptr to operand
                   3521:        movq.l          &0xc,%d0                # pass: size of extended
                   3522:        bsr.l           _dmem_write             # write the default result
                   3523:
                   3524:        tst.l           %d1                     # did dstore fail?
                   3525:        bne.l           facc_out_x              # yes
                   3526:
                   3527:        bra.w           fsnan_exit
                   3528:
                   3529: fsnan_out_x_s:
                   3530:        mov.l           (%a6),EXC_A6(%a6)
                   3531:
                   3532:        bsr.l           _calc_ea_fout           # find the correct ea,update An
                   3533:        mov.l           %a0,%a1
                   3534:        mov.l           %a0,EXC_EA(%a6)         # stack correct <ea>
                   3535:
                   3536:        mov.l           EXC_A6(%a6),(%a6)
                   3537:
                   3538:        cmpi.b          SPCOND_FLG(%a6),&mda7_flg # is <ea> mode -(a7)?
                   3539:        bne.b           fsnan_out_x_save        # no
                   3540:
                   3541: # the operation was "fmove.x SNAN,-(a7)" from supervisor mode.
                   3542:        fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0-fp1
                   3543:        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
                   3544:        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
                   3545:
                   3546:        frestore        FP_SRC(%a6)
                   3547:
                   3548:        mov.l           EXC_A6(%a6),%a6         # restore frame pointer
                   3549:
                   3550:        mov.l           LOCAL_SIZE+EXC_SR(%sp),LOCAL_SIZE+EXC_SR-0xc(%sp)
                   3551:        mov.l           LOCAL_SIZE+EXC_PC+0x2(%sp),LOCAL_SIZE+EXC_PC+0x2-0xc(%sp)
                   3552:        mov.l           LOCAL_SIZE+EXC_EA(%sp),LOCAL_SIZE+EXC_EA-0xc(%sp)
                   3553:
                   3554:        mov.l           LOCAL_SIZE+FP_SCR0_EX(%sp),LOCAL_SIZE+EXC_SR(%sp)
                   3555:        mov.l           LOCAL_SIZE+FP_SCR0_HI(%sp),LOCAL_SIZE+EXC_PC+0x2(%sp)
                   3556:        mov.l           LOCAL_SIZE+FP_SCR0_LO(%sp),LOCAL_SIZE+EXC_EA(%sp)
                   3557:
                   3558:        add.l           &LOCAL_SIZE-0x8,%sp
                   3559:
                   3560:        bra.l           _real_snan
                   3561:
                   3562: #########################################################################
                   3563: # XDEF ****************************************************************        #
                   3564: #      _fpsp_inex(): 060FPSP entry point for FP Inexact exception.     #
                   3565: #                                                                      #
                   3566: #      This handler should be the first code executed upon taking the  #
                   3567: #      FP Inexact exception in an operating system.                    #
                   3568: #                                                                      #
                   3569: # XREF ****************************************************************        #
                   3570: #      _imem_read_long() - read instruction longword                   #
                   3571: #      fix_skewed_ops() - adjust src operand in fsave frame            #
                   3572: #      set_tag_x() - determine optype of src/dst operands              #
                   3573: #      store_fpreg() - store opclass 0 or 2 result to FP regfile       #
                   3574: #      unnorm_fix() - change UNNORM operands to NORM or ZERO           #
                   3575: #      load_fpn2() - load dst operand from FP regfile                  #
                   3576: #      smovcr() - emulate an "fmovcr" instruction                      #
                   3577: #      fout() - emulate an opclass 3 instruction                       #
                   3578: #      tbl_unsupp - add of table of emulation routines for opclass 0,2 #
                   3579: #      _real_inex() - "callout" to operating system inexact handler    #
                   3580: #                                                                      #
                   3581: # INPUT ***************************************************************        #
                   3582: #      - The system stack contains the FP Inexact exception frame      #
                   3583: #      - The fsave frame contains the source operand                   #
                   3584: #                                                                      #
                   3585: # OUTPUT **************************************************************        #
                   3586: #      - The system stack is unchanged                                 #
                   3587: #      - The fsave frame contains the adjusted src op for opclass 0,2  #
                   3588: #                                                                      #
                   3589: # ALGORITHM ***********************************************************        #
                   3590: #      In a system where the FP Inexact exception is enabled, the goal #
                   3591: # is to get to the handler specified at _real_inex(). But, on the 060, #
                   3592: # for opclass zero and two instruction taking this exception, the      #
                   3593: # hardware doesn't store the correct result to the destination FP      #
                   3594: # register as did the '040 and '881/2. This handler must emulate the   #
                   3595: # instruction in order to get this value and then store it to the      #
                   3596: # correct register before calling _real_inex().                                #
                   3597: #      For opclass 3 instructions, the 060 doesn't store the default   #
                   3598: # inexact result out to memory or data register file as it should.     #
                   3599: # This code must emulate the move out by calling fout() before finally #
                   3600: # exiting through _real_inex().                                                #
                   3601: #                                                                      #
                   3602: #########################################################################
                   3603:
                   3604:        global          _fpsp_inex
                   3605: _fpsp_inex:
                   3606:
                   3607:        link.w          %a6,&-LOCAL_SIZE        # init stack frame
                   3608:
                   3609:        fsave           FP_SRC(%a6)             # grab the "busy" frame
                   3610:
                   3611:        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
                   3612:        fmovm.l         %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
                   3613:        fmovm.x         &0xc0,EXC_FPREGS(%a6)   # save fp0-fp1 on stack
                   3614:
                   3615: # the FPIAR holds the "current PC" of the faulting instruction
                   3616:        mov.l           USER_FPIAR(%a6),EXC_EXTWPTR(%a6)
                   3617:
                   3618:        mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
                   3619:        addq.l          &0x4,EXC_EXTWPTR(%a6)   # incr instruction ptr
                   3620:        bsr.l           _imem_read_long         # fetch the instruction words
                   3621:        mov.l           %d0,EXC_OPWORD(%a6)
                   3622:
                   3623: ##############################################################################
                   3624:
                   3625:        btst            &13,%d0                 # is instr an fmove out?
                   3626:        bne.w           finex_out               # fmove out
                   3627:
                   3628:
                   3629: # the hardware, for "fabs" and "fneg" w/ a long source format, puts the
                   3630: # longword integer directly into the upper longword of the mantissa along
                   3631: # w/ an exponent value of 0x401e. we convert this to extended precision here.
                   3632:        bfextu          %d0{&19:&3},%d0         # fetch instr size
                   3633:        bne.b           finex_cont              # instr size is not long
                   3634:        cmpi.w          FP_SRC_EX(%a6),&0x401e  # is exponent 0x401e?
                   3635:        bne.b           finex_cont              # no
                   3636:        fmov.l          &0x0,%fpcr
                   3637:        fmov.l          FP_SRC_HI(%a6),%fp0     # load integer src
                   3638:        fmov.x          %fp0,FP_SRC(%a6)        # store integer as extended precision
                   3639:        mov.w           &0xe001,0x2+FP_SRC(%a6)
                   3640:
                   3641: finex_cont:
                   3642:        lea             FP_SRC(%a6),%a0         # pass: ptr to src op
                   3643:        bsr.l           fix_skewed_ops          # fix src op
                   3644:
                   3645: # Here, we zero the ccode and exception byte field since we're going to
                   3646: # emulate the whole instruction. Notice, though, that we don't kill the
                   3647: # INEX1 bit. This is because a packed op has long since been converted
                   3648: # to extended before arriving here. Therefore, we need to retain the
                   3649: # INEX1 bit from when the operand was first converted.
                   3650:        andi.l          &0x00ff01ff,USER_FPSR(%a6) # zero all but accured field
                   3651:
                   3652:        fmov.l          &0x0,%fpcr              # zero current control regs
                   3653:        fmov.l          &0x0,%fpsr
                   3654:
                   3655:        bfextu          EXC_EXTWORD(%a6){&0:&6},%d1 # extract upper 6 of cmdreg
                   3656:        cmpi.b          %d1,&0x17               # is op an fmovecr?
                   3657:        beq.w           finex_fmovcr            # yes
                   3658:
                   3659:        lea             FP_SRC(%a6),%a0         # pass: ptr to src op
                   3660:        bsr.l           set_tag_x               # tag the operand type
                   3661:        mov.b           %d0,STAG(%a6)           # maybe NORM,DENORM
                   3662:
                   3663: # bits four and five of the fp extension word separate the monadic and dyadic
                   3664: # operations that can pass through fpsp_inex(). remember that fcmp and ftst
                   3665: # will never take this exception, but fsincos will.
                   3666:        btst            &0x5,1+EXC_CMDREG(%a6)  # is operation monadic or dyadic?
                   3667:        beq.b           finex_extract           # monadic
                   3668:
                   3669:        btst            &0x4,1+EXC_CMDREG(%a6)  # is operation an fsincos?
                   3670:        bne.b           finex_extract           # yes
                   3671:
                   3672:        bfextu          EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg
                   3673:        bsr.l           load_fpn2               # load dst into FP_DST
                   3674:
                   3675:        lea             FP_DST(%a6),%a0         # pass: ptr to dst op
                   3676:        bsr.l           set_tag_x               # tag the operand type
                   3677:        cmpi.b          %d0,&UNNORM             # is operand an UNNORM?
                   3678:        bne.b           finex_op2_done          # no
                   3679:        bsr.l           unnorm_fix              # yes; convert to NORM,DENORM,or ZERO
                   3680: finex_op2_done:
                   3681:        mov.b           %d0,DTAG(%a6)           # save dst optype tag
                   3682:
                   3683: finex_extract:
                   3684:        clr.l           %d0
                   3685:        mov.b           FPCR_MODE(%a6),%d0      # pass rnd prec/mode
                   3686:
                   3687:        mov.b           1+EXC_CMDREG(%a6),%d1
                   3688:        andi.w          &0x007f,%d1             # extract extension
                   3689:
                   3690:        lea             FP_SRC(%a6),%a0
                   3691:        lea             FP_DST(%a6),%a1
                   3692:
                   3693:        mov.l           (tbl_unsupp.l,%pc,%d1.w*4),%d1 # fetch routine addr
                   3694:        jsr             (tbl_unsupp.l,%pc,%d1.l*1)
                   3695:
                   3696: # the operation has been emulated. the result is in fp0.
                   3697: finex_save:
                   3698:        bfextu          EXC_CMDREG(%a6){&6:&3},%d0
                   3699:        bsr.l           store_fpreg
                   3700:
                   3701: finex_exit:
                   3702:        fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0-fp1
                   3703:        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
                   3704:        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
                   3705:
                   3706:        frestore        FP_SRC(%a6)
                   3707:
                   3708:        unlk            %a6
                   3709:        bra.l           _real_inex
                   3710:
                   3711: finex_fmovcr:
                   3712:        clr.l           %d0
                   3713:        mov.b           FPCR_MODE(%a6),%d0      # pass rnd prec,mode
                   3714:        mov.b           1+EXC_CMDREG(%a6),%d1
                   3715:        andi.l          &0x0000007f,%d1         # pass rom offset
                   3716:        bsr.l           smovcr
                   3717:        bra.b           finex_save
                   3718:
                   3719: ########################################################################
                   3720:
                   3721: #
                   3722: # the hardware does not save the default result to memory on enabled
                   3723: # inexact exceptions. we do this here before passing control to
                   3724: # the user inexact handler.
                   3725: #
                   3726: # byte, word, and long destination format operations can pass
                   3727: # through here. so can double and single precision.
                   3728: # although packed opclass three operations can take inexact
                   3729: # exceptions, they won't pass through here since they are caught
                   3730: # first by the unsupported data format exception handler. that handler
                   3731: # sends them directly to _real_inex() if necessary.
                   3732: #
                   3733: finex_out:
                   3734:
                   3735:        mov.b           &NORM,STAG(%a6)         # src is a NORM
                   3736:
                   3737:        clr.l           %d0
                   3738:        mov.b           FPCR_MODE(%a6),%d0      # pass rnd prec,mode
                   3739:
                   3740:        andi.l          &0xffff00ff,USER_FPSR(%a6) # zero exception field
                   3741:
                   3742:        lea             FP_SRC(%a6),%a0         # pass ptr to src operand
                   3743:
                   3744:        bsr.l           fout                    # store the default result
                   3745:
                   3746:        bra.b           finex_exit
                   3747:
                   3748: #########################################################################
                   3749: # XDEF ****************************************************************        #
                   3750: #      _fpsp_dz(): 060FPSP entry point for FP DZ exception.            #
                   3751: #                                                                      #
                   3752: #      This handler should be the first code executed upon taking      #
                   3753: #      the FP DZ exception in an operating system.                     #
                   3754: #                                                                      #
                   3755: # XREF ****************************************************************        #
                   3756: #      _imem_read_long() - read instruction longword from memory       #
                   3757: #      fix_skewed_ops() - adjust fsave operand                         #
                   3758: #      _real_dz() - "callout" exit point from FP DZ handler            #
                   3759: #                                                                      #
                   3760: # INPUT ***************************************************************        #
                   3761: #      - The system stack contains the FP DZ exception stack.          #
                   3762: #      - The fsave frame contains the source operand.                  #
                   3763: #                                                                      #
                   3764: # OUTPUT **************************************************************        #
                   3765: #      - The system stack contains the FP DZ exception stack.          #
                   3766: #      - The fsave frame contains the adjusted source operand.         #
                   3767: #                                                                      #
                   3768: # ALGORITHM ***********************************************************        #
                   3769: #      In a system where the DZ exception is enabled, the goal is to   #
                   3770: # get to the handler specified at _real_dz(). But, on the 060, when the        #
                   3771: # exception is taken, the input operand in the fsave state frame may   #
                   3772: # be incorrect for some cases and need to be adjusted. So, this package        #
                   3773: # adjusts the operand using fix_skewed_ops() and then branches to      #
                   3774: # _real_dz().                                                          #
                   3775: #                                                                      #
                   3776: #########################################################################
                   3777:
                   3778:        global          _fpsp_dz
                   3779: _fpsp_dz:
                   3780:
                   3781:        link.w          %a6,&-LOCAL_SIZE        # init stack frame
                   3782:
                   3783:        fsave           FP_SRC(%a6)             # grab the "busy" frame
                   3784:
                   3785:        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
                   3786:        fmovm.l         %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
                   3787:        fmovm.x         &0xc0,EXC_FPREGS(%a6)   # save fp0-fp1 on stack
                   3788:
                   3789: # the FPIAR holds the "current PC" of the faulting instruction
                   3790:        mov.l           USER_FPIAR(%a6),EXC_EXTWPTR(%a6)
                   3791:
                   3792:        mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
                   3793:        addq.l          &0x4,EXC_EXTWPTR(%a6)   # incr instruction ptr
                   3794:        bsr.l           _imem_read_long         # fetch the instruction words
                   3795:        mov.l           %d0,EXC_OPWORD(%a6)
                   3796:
                   3797: ##############################################################################
                   3798:
                   3799:
                   3800: # here, we simply see if the operand in the fsave frame needs to be "unskewed".
                   3801: # this would be the case for opclass two operations with a source zero
                   3802: # in the sgl or dbl format.
                   3803:        lea             FP_SRC(%a6),%a0         # pass: ptr to src op
                   3804:        bsr.l           fix_skewed_ops          # fix src op
                   3805:
                   3806: fdz_exit:
                   3807:        fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0-fp1
                   3808:        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
                   3809:        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
                   3810:
                   3811:        frestore        FP_SRC(%a6)
                   3812:
                   3813:        unlk            %a6
                   3814:        bra.l           _real_dz
                   3815:
                   3816: #########################################################################
                   3817: # XDEF ****************************************************************        #
                   3818: #      _fpsp_fline(): 060FPSP entry point for "Line F emulator" exc.   #
                   3819: #                                                                      #
                   3820: #      This handler should be the first code executed upon taking the  #
                   3821: #      "Line F Emulator" exception in an operating system.             #
                   3822: #                                                                      #
                   3823: # XREF ****************************************************************        #
                   3824: #      _fpsp_unimp() - handle "FP Unimplemented" exceptions            #
                   3825: #      _real_fpu_disabled() - handle "FPU disabled" exceptions         #
                   3826: #      _real_fline() - handle "FLINE" exceptions                       #
                   3827: #      _imem_read_long() - read instruction longword                   #
                   3828: #                                                                      #
                   3829: # INPUT ***************************************************************        #
                   3830: #      - The system stack contains a "Line F Emulator" exception       #
                   3831: #        stack frame.                                                  #
                   3832: #                                                                      #
                   3833: # OUTPUT **************************************************************        #
                   3834: #      - The system stack is unchanged                                 #
                   3835: #                                                                      #
                   3836: # ALGORITHM ***********************************************************        #
                   3837: #      When a "Line F Emulator" exception occurs, there are 3 possible #
                   3838: # exception types, denoted by the exception stack frame format number: #
                   3839: #      (1) FPU unimplemented instruction (6 word stack frame)          #
                   3840: #      (2) FPU disabled (8 word stack frame)                           #
                   3841: #      (3) Line F (4 word stack frame)                                 #
                   3842: #                                                                      #
                   3843: #      This module determines which and forks the flow off to the      #
                   3844: # appropriate "callout" (for "disabled" and "Line F") or to the                #
                   3845: # correct emulation code (for "FPU unimplemented").                    #
                   3846: #      This code also must check for "fmovecr" instructions w/ a       #
                   3847: # non-zero <ea> field. These may get flagged as "Line F" but should    #
                   3848: # really be flagged as "FPU Unimplemented". (This is a "feature" on    #
                   3849: # the '060.                                                            #
                   3850: #                                                                      #
                   3851: #########################################################################
                   3852:
                   3853:        global          _fpsp_fline
                   3854: _fpsp_fline:
                   3855:
                   3856: # check to see if this exception is a "FP Unimplemented Instruction"
                   3857: # exception. if so, branch directly to that handler's entry point.
                   3858:        cmpi.w          0x6(%sp),&0x202c
                   3859:        beq.l           _fpsp_unimp
                   3860:
                   3861: # check to see if the FPU is disabled. if so, jump to the OS entry
                   3862: # point for that condition.
                   3863:        cmpi.w          0x6(%sp),&0x402c
                   3864:        beq.l           _real_fpu_disabled
                   3865:
                   3866: # the exception was an "F-Line Illegal" exception. we check to see
                   3867: # if the F-Line instruction is an "fmovecr" w/ a non-zero <ea>. if
                   3868: # so, convert the F-Line exception stack frame to an FP Unimplemented
                   3869: # Instruction exception stack frame else branch to the OS entry
                   3870: # point for the F-Line exception handler.
                   3871:        link.w          %a6,&-LOCAL_SIZE        # init stack frame
                   3872:
                   3873:        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
                   3874:
                   3875:        mov.l           EXC_PC(%a6),EXC_EXTWPTR(%a6)
                   3876:        mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
                   3877:        addq.l          &0x4,EXC_EXTWPTR(%a6)   # incr instruction ptr
                   3878:        bsr.l           _imem_read_long         # fetch instruction words
                   3879:
                   3880:        bfextu          %d0{&0:&10},%d1         # is it an fmovecr?
                   3881:        cmpi.w          %d1,&0x03c8
                   3882:        bne.b           fline_fline             # no
                   3883:
                   3884:        bfextu          %d0{&16:&6},%d1         # is it an fmovecr?
                   3885:        cmpi.b          %d1,&0x17
                   3886:        bne.b           fline_fline             # no
                   3887:
                   3888: # it's an fmovecr w/ a non-zero <ea> that has entered through
                   3889: # the F-Line Illegal exception.
                   3890: # so, we need to convert the F-Line exception stack frame into an
                   3891: # FP Unimplemented Instruction stack frame and jump to that entry
                   3892: # point.
                   3893: #
                   3894: # but, if the FPU is disabled, then we need to jump to the FPU disabled
                   3895: # entry point.
                   3896:        movc            %pcr,%d0
                   3897:        btst            &0x1,%d0
                   3898:        beq.b           fline_fmovcr
                   3899:
                   3900:        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
                   3901:
                   3902:        unlk            %a6
                   3903:
                   3904:        sub.l           &0x8,%sp                # make room for "Next PC", <ea>
                   3905:        mov.w           0x8(%sp),(%sp)
                   3906:        mov.l           0xa(%sp),0x2(%sp)       # move "Current PC"
                   3907:        mov.w           &0x402c,0x6(%sp)
                   3908:        mov.l           0x2(%sp),0xc(%sp)
                   3909:        addq.l          &0x4,0x2(%sp)           # set "Next PC"
                   3910:
                   3911:        bra.l           _real_fpu_disabled
                   3912:
                   3913: fline_fmovcr:
                   3914:        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
                   3915:
                   3916:        unlk            %a6
                   3917:
                   3918:        fmov.l          0x2(%sp),%fpiar         # set current PC
                   3919:        addq.l          &0x4,0x2(%sp)           # set Next PC
                   3920:
                   3921:        mov.l           (%sp),-(%sp)
                   3922:        mov.l           0x8(%sp),0x4(%sp)
                   3923:        mov.b           &0x20,0x6(%sp)
                   3924:
                   3925:        bra.l           _fpsp_unimp
                   3926:
                   3927: fline_fline:
                   3928:        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
                   3929:
                   3930:        unlk            %a6
                   3931:
                   3932:        bra.l           _real_fline
                   3933:
                   3934: #########################################################################
                   3935: # XDEF ****************************************************************        #
                   3936: #      _fpsp_unimp(): 060FPSP entry point for FP "Unimplemented        #
                   3937: #                     Instruction" exception.                          #
                   3938: #                                                                      #
                   3939: #      This handler should be the first code executed upon taking the  #
                   3940: #      FP Unimplemented Instruction exception in an operating system.  #
                   3941: #                                                                      #
                   3942: # XREF ****************************************************************        #
                   3943: #      _imem_read_{word,long}() - read instruction word/longword       #
                   3944: #      load_fop() - load src/dst ops from memory and/or FP regfile     #
                   3945: #      store_fpreg() - store opclass 0 or 2 result to FP regfile       #
                   3946: #      tbl_trans - addr of table of emulation routines for trnscndls   #
                   3947: #      _real_access() - "callout" for access error exception           #
                   3948: #      _fpsp_done() - "callout" for exit; work all done                #
                   3949: #      _real_trace() - "callout" for Trace enabled exception           #
                   3950: #      smovcr() - emulate "fmovecr" instruction                        #
                   3951: #      funimp_skew() - adjust fsave src ops to "incorrect" value       #
                   3952: #      _ftrapcc() - emulate an "ftrapcc" instruction                   #
                   3953: #      _fdbcc() - emulate an "fdbcc" instruction                       #
                   3954: #      _fscc() - emulate an "fscc" instruction                         #
                   3955: #      _real_trap() - "callout" for Trap exception                     #
                   3956: #      _real_bsun() - "callout" for enabled Bsun exception             #
                   3957: #                                                                      #
                   3958: # INPUT ***************************************************************        #
                   3959: #      - The system stack contains the "Unimplemented Instr" stk frame #
                   3960: #                                                                      #
                   3961: # OUTPUT **************************************************************        #
                   3962: #      If access error:                                                #
                   3963: #      - The system stack is changed to an access error stack frame    #
                   3964: #      If Trace exception enabled:                                     #
                   3965: #      - The system stack is changed to a Trace exception stack frame  #
                   3966: #      Else: (normal case)                                             #
                   3967: #      - Correct result has been stored as appropriate                 #
                   3968: #                                                                      #
                   3969: # ALGORITHM ***********************************************************        #
                   3970: #      There are two main cases of instructions that may enter here to #
                   3971: # be emulated: (1) the FPgen instructions, most of which were also     #
                   3972: # unimplemented on the 040, and (2) "ftrapcc", "fscc", and "fdbcc".    #
                   3973: #      For the first set, this handler calls the routine load_fop()    #
                   3974: # to load the source and destination (for dyadic) operands to be used  #
                   3975: # for instruction emulation. The correct emulation routine is then     #
                   3976: # chosen by decoding the instruction type and indexing into an                 #
                   3977: # emulation subroutine index table. After emulation returns, this      #
                   3978: # handler checks to see if an exception should occur as a result of the #
                   3979: # FP instruction emulation. If so, then an FP exception of the correct #
                   3980: # type is inserted into the FPU state frame using the "frestore"       #
                   3981: # instruction before exiting through _fpsp_done(). In either the       #
                   3982: # exceptional or non-exceptional cases, we must check to see if the    #
                   3983: # Trace exception is enabled. If so, then we must create a Trace       #
                   3984: # exception frame from the current exception frame and exit through    #
                   3985: # _real_trace().                                                       #
                   3986: #      For "fdbcc", "ftrapcc", and "fscc", the emulation subroutines   #
                   3987: # _fdbcc(), _ftrapcc(), and _fscc() respectively are used. All three   #
                   3988: # may flag that a BSUN exception should be taken. If so, then the      #
                   3989: # current exception stack frame is converted into a BSUN exception     #
                   3990: # stack frame and an exit is made through _real_bsun(). If the         #
                   3991: # instruction was "ftrapcc" and a Trap exception should result, a Trap #
                   3992: # exception stack frame is created from the current frame and an exit  #
                   3993: # is made through _real_trap(). If a Trace exception is pending, then  #
                   3994: # a Trace exception frame is created from the current frame and a jump #
                   3995: # is made to _real_trace(). Finally, if none of these conditions exist,        #
                   3996: # then the handler exits though the callout _fpsp_done().              #
                   3997: #                                                                      #
                   3998: #      In any of the above scenarios, if a _mem_read() or _mem_write() #
                   3999: # "callout" returns a failing value, then an access error stack frame  #
                   4000: # is created from the current stack frame and an exit is made through  #
                   4001: # _real_access().                                                      #
                   4002: #                                                                      #
                   4003: #########################################################################
                   4004:
                   4005: #
                   4006: # FP UNIMPLEMENTED INSTRUCTION STACK FRAME:
                   4007: #
                   4008: #      *****************
                   4009: #      *               * => <ea> of fp unimp instr.
                   4010: #      -      EA       -
                   4011: #      *               *
                   4012: #      *****************
                   4013: #      * 0x2 *  0x02c  * => frame format and vector offset(vector #11)
                   4014: #      *****************
                   4015: #      *               *
                   4016: #      -    Next PC    - => PC of instr to execute after exc handling
                   4017: #      *               *
                   4018: #      *****************
                   4019: #      *      SR       * => SR at the time the exception was taken
                   4020: #      *****************
                   4021: #
                   4022: # Note: the !NULL bit does not get set in the fsave frame when the
                   4023: # machine encounters an fp unimp exception. Therefore, it must be set
                   4024: # before leaving this handler.
                   4025: #
                   4026:        global          _fpsp_unimp
                   4027: _fpsp_unimp:
                   4028:
                   4029:        link.w          %a6,&-LOCAL_SIZE        # init stack frame
                   4030:
                   4031:        movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
                   4032:        fmovm.l         %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
                   4033:        fmovm.x         &0xc0,EXC_FPREGS(%a6)   # save fp0-fp1
                   4034:
                   4035:        btst            &0x5,EXC_SR(%a6)        # user mode exception?
                   4036:        bne.b           funimp_s                # no; supervisor mode
                   4037:
                   4038: # save the value of the user stack pointer onto the stack frame
                   4039: funimp_u:
                   4040:        mov.l           %usp,%a0                # fetch user stack pointer
                   4041:        mov.l           %a0,EXC_A7(%a6)         # store in stack frame
                   4042:        bra.b           funimp_cont
                   4043:
                   4044: # store the value of the supervisor stack pointer BEFORE the exc occurred.
                   4045: # old_sp is address just above stacked effective address.
                   4046: funimp_s:
                   4047:        lea             4+EXC_EA(%a6),%a0       # load old a7'
                   4048:        mov.l           %a0,EXC_A7(%a6)         # store a7'
                   4049:        mov.l           %a0,OLD_A7(%a6)         # make a copy
                   4050:
                   4051: funimp_cont:
                   4052:
                   4053: # the FPIAR holds the "current PC" of the faulting instruction.
                   4054:        mov.l           USER_FPIAR(%a6),EXC_EXTWPTR(%a6)
                   4055:
                   4056:        mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
                   4057:        addq.l          &0x4,EXC_EXTWPTR(%a6)   # incr instruction ptr
                   4058:        bsr.l           _imem_read_long         # fetch the instruction words
                   4059:        mov.l           %d0,EXC_OPWORD(%a6)
                   4060:
                   4061: ############################################################################
                   4062:
                   4063:        fmov.l          &0x0,%fpcr              # clear FPCR
                   4064:        fmov.l          &0x0,%fpsr              # clear FPSR
                   4065:
                   4066:        clr.b           SPCOND_FLG(%a6)         # clear "special case" flag
                   4067:
                   4068: # Divide the fp instructions into 8 types based on the TYPE field in
                   4069: # bits 6-8 of the opword(classes 6,7 are undefined).
                   4070: # (for the '060, only two types  can take this exception)
                   4071: #      bftst           %d0{&7:&3}              # test TYPE
                   4072:        btst            &22,%d0                 # type 0 or 1 ?
                   4073:        bne.w           funimp_misc             # type 1
                   4074:
                   4075: #########################################
                   4076: # TYPE == 0: General instructions      #
                   4077: #########################################
                   4078: funimp_gen:
                   4079:
                   4080:        clr.b           STORE_FLG(%a6)          # clear "store result" flag
                   4081:
                   4082: # clear the ccode byte and exception status byte
                   4083:        andi.l          &0x00ff00ff,USER_FPSR(%a6)
                   4084:
                   4085:        bfextu          %d0{&16:&6},%d1         # extract upper 6 of cmdreg
                   4086:        cmpi.b          %d1,&0x17               # is op an fmovecr?
                   4087:        beq.w           funimp_fmovcr           # yes
                   4088:
                   4089: funimp_gen_op:
                   4090:        bsr.l           _load_fop               # load
                   4091:
                   4092:        clr.l           %d0
                   4093:        mov.b           FPCR_MODE(%a6),%d0      # fetch rnd mode
                   4094:
                   4095:        mov.b           1+EXC_CMDREG(%a6),%d1
                   4096:        andi.w          &0x003f,%d1             # extract extension bits
                   4097:        lsl.w           &0x3,%d1                # shift right 3 bits
                   4098:        or.b            STAG(%a6),%d1           # insert src optag bits
                   4099:
                   4100:        lea             FP_DST(%a6),%a1         # pass dst ptr in a1
                   4101:        lea             FP_SRC(%a6),%a0         # pass src ptr in a0
                   4102:
                   4103:        mov.w           (tbl_trans.w,%pc,%d1.w*2),%d1
                   4104:        jsr             (tbl_trans.w,%pc,%d1.w*1) # emulate
                   4105:
                   4106: funimp_fsave:
                   4107:        mov.b           FPCR_ENABLE(%a6),%d0    # fetch exceptions enabled
                   4108:        bne.w           funimp_ena              # some are enabled
                   4109:
                   4110: funimp_store:
                   4111:        bfextu          EXC_CMDREG(%a6){&6:&3},%d0 # fetch Dn
                   4112:        bsr.l           store_fpreg             # store result to fp regfile
                   4113:
                   4114: funimp_gen_exit:
                   4115:        fmovm.x         EXC_FP0(%a6),&0xc0      # restore fp0-fp1
                   4116:        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
                   4117:        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
                   4118:
                   4119: funimp_gen_exit_cmp:
                   4120:        cmpi.b          SPCOND_FLG(%a6),&mia7_flg # was the ea mode (sp)+ ?
                   4121:        beq.b           funimp_gen_exit_a7      # yes
                   4122:
                   4123:        cmpi.b          SPCOND_FLG(%a6),&mda7_flg # was the ea mode -(sp) ?
                   4124:        beq.b           funimp_gen_exit_a7      # yes
                   4125:
                   4126: funimp_gen_exit_cont:
                   4127:        unlk            %a6
                   4128:
                   4129: funimp_gen_exit_cont2:
                   4130:        btst            &0x7,(%sp)              # is trace on?
                   4131:        beq.l           _fpsp_done              # no
                   4132:
                   4133: # this catches a problem with the case where an exception will be re-inserted
                   4134: # into the machine. the frestore has already been executed...so, the fmov.l
                   4135: # alone of the control register would trigger an unwanted exception.
                   4136: # until I feel like fixing this, we'll sidestep the exception.
                   4137:        fsave           -(%sp)
                   4138:        fmov.l          %fpiar,0x14(%sp)        # "Current PC" is in FPIAR
                   4139:        frestore        (%sp)+
                   4140:        mov.w           &0x2024,0x6(%sp)        # stk fmt = 0x2; voff = 0x24
                   4141:        bra.l           _real_trace
                   4142:
                   4143: funimp_gen_exit_a7:
                   4144:        btst            &0x5,EXC_SR(%a6)        # supervisor or user mode?
                   4145:        bne.b           funimp_gen_exit_a7_s    # supervisor
                   4146:
                   4147:        mov.l           %a0,-(%sp)
                   4148:        mov.l           EXC_A7(%a6),%a0
                   4149:        mov.l           %a0,%usp
                   4150:        mov.l           (%sp)+,%a0
                   4151:        bra.b           funimp_gen_exit_cont
                   4152:
                   4153: # if the instruction was executed from supervisor mode and the addressing
                   4154: # mode was (a7)+, then the stack frame for the rte must be shifted "up"
                   4155: # "n" bytes where "n" is the size of the src operand type.
                   4156: # f<op>.{b,w,l,s,d,x,p}
                   4157: funimp_gen_exit_a7_s:
                   4158:        mov.l           %d0,-(%sp)              # save d0
                   4159:        mov.l           EXC_A7(%a6),%d0         # load new a7'
                   4160:        sub.l           OLD_A7(%a6),%d0         # subtract old a7'
                   4161:        mov.l           0x2+EXC_PC(%a6),(0x2+EXC_PC,%a6,%d0) # shift stack frame
                   4162:        mov.l           EXC_SR(%a6),(EXC_SR,%a6,%d0) # shift stack frame
                   4163:        mov.w           %d0,EXC_SR(%a6)         # store incr number
                   4164:        mov.l           (%sp)+,%d0              # restore d0
                   4165:
                   4166:        unlk            %a6
                   4167:
                   4168:        add.w           (%sp),%sp               # stack frame shifted
                   4169:        bra.b           funimp_gen_exit_cont2
                   4170:
                   4171: ######################
                   4172: # fmovecr.x #ccc,fpn #
                   4173: ######################
                   4174: funimp_fmovcr:
                   4175:        clr.l           %d0
                   4176:        mov.b           FPCR_MODE(%a6),%d0
                   4177:        mov.b           1+EXC_CMDREG(%a6),%d1
                   4178:        andi.l          &0x0000007f,%d1         # pass rom offset in d1
                   4179:        bsr.l           smovcr
                   4180:        bra.w           funimp_fsave
                   4181:
                   4182: #########################################################################
                   4183:
                   4184: #
                   4185: # the user has enabled some exceptions. we figure not to see this too
                   4186: # often so that's why it gets lower priority.
                   4187: #
                   4188: funimp_ena:
                   4189:
                   4190: # was an exception set that was also enabled?
                   4191:        and.b           FPSR_EXCEPT(%a6),%d0    # keep only ones enabled and set
                   4192:        bfffo           %d0{&24:&8},%d0         # find highest priority exception
                   4193:        bne.b           funimp_exc              # at least one was set
                   4194:
                   4195: # no exception that was enabled was set BUT if we got an exact overflow
                   4196: # and overflow wasn't enabled but inexact was (yech!) then this is
                   4197: # an inexact exception; otherwise, return to normal non-exception flow.
                   4198:        btst            &ovfl_bit,FPSR_EXCEPT(%a6) # did overflow occur?
                   4199:        beq.w           funimp_store            # no; return to normal flow
                   4200:
                   4201: # the overflow w/ exact result happened but was inexact set in the FPCR?
                   4202: funimp_ovfl:
                   4203:        btst            &inex2_bit,FPCR_ENABLE(%a6) # is inexact enabled?
                   4204:        beq.w           funimp_store            # no; return to normal flow
                   4205:        bra.b           funimp_exc_ovfl         # yes
                   4206:
                   4207: # some exception happened that was actually enabled.
                   4208: # we'll insert this new exception into the FPU and then return.
                   4209: funimp_exc:
                   4210:        subi.l          &24,%d0                 # fix offset to be 0-8
                   4211:        cmpi.b          %d0,&0x6                # is exception INEX?
                   4212:        bne.b           funimp_exc_force        # no
                   4213:
                   4214: # the enabled exception was inexact. so, if it occurs with an overflow
                   4215: # or underflow that was disabled, then we have to force an overflow or
                   4216: # underflow frame. the eventual overflow or underflow handler will see that
                   4217: # it's actually an inexact and act appropriately. this is the only easy
                   4218: # way to have the EXOP available for the enabled inexact handler when
                   4219: # a disabled overflow or underflow has also happened.
                   4220:        btst            &ovfl_bit,FPSR_EXCEPT(%a6) # did overflow occur?
                   4221:        bne.b           funimp_exc_ovfl         # yes
                   4222:        btst            &unfl_bit,FPSR_EXCEPT(%a6) # did underflow occur?
                   4223:        bne.b           funimp_exc_unfl         # yes
                   4224:
                   4225: # force the fsave exception status bits to signal an exception of the
                   4226: # appropriate type. don't forget to "skew" the source operand in case we
                   4227: # "unskewed" the one the hardware initially gave us.
                   4228: funimp_exc_force:
                   4229:        mov.l           %d0,-(%sp)              # save d0
                   4230:        bsr.l           funimp_skew             # check for special case
                   4231:        mov.l           (%sp)+,%d0              # restore d0
                   4232:        mov.w           (tbl_funimp_except.b,%pc,%d0.w*2),2+FP_SRC(%a6)
                   4233:        bra.b           funimp_gen_exit2        # exit with frestore
                   4234:
                   4235: tbl_funimp_except:
                   4236:        short           0xe002, 0xe006, 0xe004, 0xe005
                   4237:        short           0xe003, 0xe002, 0xe001, 0xe001
                   4238:
                   4239: # insert an overflow frame
                   4240: funimp_exc_ovfl:
                   4241:        bsr.l           funimp_skew             # check for special case
                   4242:        mov.w           &0xe005,2+FP_SRC(%a6)
                   4243:        bra.b           funimp_gen_exit2
                   4244:
                   4245: # insert an underflow frame
                   4246: funimp_exc_unfl:
                   4247:        bsr.l           funimp_skew             # check for special case
                   4248:        mov.w           &0xe003,2+FP_SRC(%a6)
                   4249:
                   4250: # this is the general exit point for an enabled exception that will be
                   4251: # restored into the machine for the instruction just emulated.
                   4252: funimp_gen_exit2:
                   4253:        fmovm.x         EXC_FP0(%a6),&0xc0      # restore fp0-fp1
                   4254:        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
                   4255:        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
                   4256:
                   4257:        frestore        FP_SRC(%a6)             # insert exceptional status
                   4258:
                   4259:        bra.w           funimp_gen_exit_cmp
                   4260:
                   4261: ############################################################################
                   4262:
                   4263: #
                   4264: # TYPE == 1: FDB<cc>, FS<cc>, FTRAP<cc>
                   4265: #
                   4266: # These instructions were implemented on the '881/2 and '040 in hardware but
                   4267: # are emulated in software on the '060.
                   4268: #
                   4269: funimp_misc:
                   4270:        bfextu          %d0{&10:&3},%d1         # extract mode field
                   4271:        cmpi.b          %d1,&0x1                # is it an fdb<cc>?
                   4272:        beq.w           funimp_fdbcc            # yes
                   4273:        cmpi.b          %d1,&0x7                # is it an fs<cc>?
                   4274:        bne.w           funimp_fscc             # yes
                   4275:        bfextu          %d0{&13:&3},%d1
                   4276:        cmpi.b          %d1,&0x2                # is it an fs<cc>?
                   4277:        blt.w           funimp_fscc             # yes
                   4278:
                   4279: #########################
                   4280: # ftrap<cc>            #
                   4281: # ftrap<cc>.w #<data>  #
                   4282: # ftrap<cc>.l #<data>  #
                   4283: #########################
                   4284: funimp_ftrapcc:
                   4285:
                   4286:        bsr.l           _ftrapcc                # FTRAP<cc>()
                   4287:
                   4288:        cmpi.b          SPCOND_FLG(%a6),&fbsun_flg # is enabled bsun occurring?
                   4289:        beq.w           funimp_bsun             # yes
                   4290:
                   4291:        cmpi.b          SPCOND_FLG(%a6),&ftrapcc_flg # should a trap occur?
                   4292:        bne.w           funimp_done             # no
                   4293:
                   4294: #       FP UNIMP FRAME            TRAP  FRAME
                   4295: #      *****************       *****************
                   4296: #      **    <EA>     **       **  Current PC **
                   4297: #      *****************       *****************
                   4298: #      * 0x2 *  0x02c  *       * 0x2 *  0x01c  *
                   4299: #      *****************       *****************
                   4300: #      **   Next PC   **       **   Next PC   **
                   4301: #      *****************       *****************
                   4302: #      *      SR       *       *      SR       *
                   4303: #      *****************       *****************
                   4304: #          (6 words)               (6 words)
                   4305: #
                   4306: # the ftrapcc instruction should take a trap. so, here we must create a
                   4307: # trap stack frame from an unimplemented fp instruction stack frame and
                   4308: # jump to the user supplied entry point for the trap exception
                   4309: funimp_ftrapcc_tp:
                   4310:        mov.l           USER_FPIAR(%a6),EXC_EA(%a6) # Address = Current PC
                   4311:        mov.w           &0x201c,EXC_VOFF(%a6)   # Vector Offset = 0x01c
                   4312:
                   4313:        fmovm.x         EXC_FP0(%a6),&0xc0      # restore fp0-fp1
                   4314:        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
                   4315:        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
                   4316:
                   4317:        unlk            %a6
                   4318:        bra.l           _real_trap
                   4319:
                   4320: #########################
                   4321: # fdb<cc> Dn,<label>   #
                   4322: #########################
                   4323: funimp_fdbcc:
                   4324:
                   4325:        mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
                   4326:        addq.l          &0x2,EXC_EXTWPTR(%a6)   # incr instruction ptr
                   4327:        bsr.l           _imem_read_word         # read displacement
                   4328:
                   4329:        tst.l           %d1                     # did ifetch fail?
                   4330:        bne.w           funimp_iacc             # yes
                   4331:
                   4332:        ext.l           %d0                     # sign extend displacement
                   4333:
                   4334:        bsr.l           _fdbcc                  # FDB<cc>()
                   4335:
                   4336:        cmpi.b          SPCOND_FLG(%a6),&fbsun_flg # is enabled bsun occurring?
                   4337:        beq.w           funimp_bsun
                   4338:
                   4339:        bra.w           funimp_done             # branch to finish
                   4340:
                   4341: #################
                   4342: # fs<cc>.b <ea>        #
                   4343: #################
                   4344: funimp_fscc:
                   4345:
                   4346:        bsr.l           _fscc                   # FS<cc>()
                   4347:
                   4348: # I am assuming here that an "fs<cc>.b -(An)" or "fs<cc>.b (An)+" instruction
                   4349: # does not need to update "An" before taking a bsun exception.
                   4350:        cmpi.b          SPCOND_FLG(%a6),&fbsun_flg # is enabled bsun occurring?
                   4351:        beq.w           funimp_bsun
                   4352:
                   4353:        btst            &0x5,EXC_SR(%a6)        # yes; is it a user mode exception?
                   4354:        bne.b           funimp_fscc_s           # no
                   4355:
                   4356: funimp_fscc_u:
                   4357:        mov.l           EXC_A7(%a6),%a0         # yes; set new USP
                   4358:        mov.l           %a0,%usp
                   4359:        bra.w           funimp_done             # branch to finish
                   4360:
                   4361: # remember, I'm assuming that post-increment is bogus...(it IS!!!)
                   4362: # so, the least significant WORD of the stacked effective address got
                   4363: # overwritten by the "fs<cc> -(An)". We must shift the stack frame "down"
                   4364: # so that the rte will work correctly without destroying the result.
                   4365: # even though the operation size is byte, the stack ptr is decr by 2.
                   4366: #
                   4367: # remember, also, this instruction may be traced.
                   4368: funimp_fscc_s:
                   4369:        cmpi.b          SPCOND_FLG(%a6),&mda7_flg # was a7 modified?
                   4370:        bne.w           funimp_done             # no
                   4371:
                   4372:        fmovm.x         EXC_FP0(%a6),&0xc0      # restore fp0-fp1
                   4373:        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
                   4374:        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
                   4375:
                   4376:        unlk            %a6
                   4377:
                   4378:        btst            &0x7,(%sp)              # is trace enabled?
                   4379:        bne.b           funimp_fscc_s_trace     # yes
                   4380:
                   4381:        subq.l          &0x2,%sp
                   4382:        mov.l           0x2(%sp),(%sp)          # shift SR,hi(PC) "down"
                   4383:        mov.l           0x6(%sp),0x4(%sp)       # shift lo(PC),voff "down"
                   4384:        bra.l           _fpsp_done
                   4385:
                   4386: funimp_fscc_s_trace:
                   4387:        subq.l          &0x2,%sp
                   4388:        mov.l           0x2(%sp),(%sp)          # shift SR,hi(PC) "down"
                   4389:        mov.w           0x6(%sp),0x4(%sp)       # shift lo(PC)
                   4390:        mov.w           &0x2024,0x6(%sp)        # fmt/voff = $2024
                   4391:        fmov.l          %fpiar,0x8(%sp)         # insert "current PC"
                   4392:
                   4393:        bra.l           _real_trace
                   4394:
                   4395: #
                   4396: # The ftrap<cc>, fs<cc>, or fdb<cc> is to take an enabled bsun. we must convert
                   4397: # the fp unimplemented instruction exception stack frame into a bsun stack frame,
                   4398: # restore a bsun exception into the machine, and branch to the user
                   4399: # supplied bsun hook.
                   4400: #
                   4401: #       FP UNIMP FRAME            BSUN FRAME
                   4402: #      *****************       *****************
                   4403: #      **    <EA>     **       * 0x0 * 0x0c0   *
                   4404: #      *****************       *****************
                   4405: #      * 0x2 *  0x02c  *       ** Current PC  **
                   4406: #      *****************       *****************
                   4407: #      **   Next PC   **       *      SR       *
                   4408: #      *****************       *****************
                   4409: #      *      SR       *           (4 words)
                   4410: #      *****************
                   4411: #          (6 words)
                   4412: #
                   4413: funimp_bsun:
                   4414:        mov.w           &0x00c0,2+EXC_EA(%a6)   # Fmt = 0x0; Vector Offset = 0x0c0
                   4415:        mov.l           USER_FPIAR(%a6),EXC_VOFF(%a6) # PC = Current PC
                   4416:        mov.w           EXC_SR(%a6),2+EXC_PC(%a6) # shift SR "up"
                   4417:
                   4418:        mov.w           &0xe000,2+FP_SRC(%a6)   # bsun exception enabled
                   4419:
                   4420:        fmovm.x         EXC_FP0(%a6),&0xc0      # restore fp0-fp1
                   4421:        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
                   4422:        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
                   4423:
                   4424:        frestore        FP_SRC(%a6)             # restore bsun exception
                   4425:
                   4426:        unlk            %a6
                   4427:
                   4428:        addq.l          &0x4,%sp                # erase sludge
                   4429:
                   4430:        bra.l           _real_bsun              # branch to user bsun hook
                   4431:
                   4432: #
                   4433: # all ftrapcc/fscc/fdbcc processing has been completed. unwind the stack frame
                   4434: # and return.
                   4435: #
                   4436: # as usual, we have to check for trace mode being on here. since instructions
                   4437: # modifying the supervisor stack frame don't pass through here, this is a
                   4438: # relatively easy task.
                   4439: #
                   4440: funimp_done:
                   4441:        fmovm.x         EXC_FP0(%a6),&0xc0      # restore fp0-fp1
                   4442:        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
                   4443:        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
                   4444:
                   4445:        unlk            %a6
                   4446:
                   4447:        btst            &0x7,(%sp)              # is trace enabled?
                   4448:        bne.b           funimp_trace            # yes
                   4449:
                   4450:        bra.l           _fpsp_done
                   4451:
                   4452: #       FP UNIMP FRAME           TRACE  FRAME
                   4453: #      *****************       *****************
                   4454: #      **    <EA>     **       **  Current PC **
                   4455: #      *****************       *****************
                   4456: #      * 0x2 *  0x02c  *       * 0x2 *  0x024  *
                   4457: #      *****************       *****************
                   4458: #      **   Next PC   **       **   Next PC   **
                   4459: #      *****************       *****************
                   4460: #      *      SR       *       *      SR       *
                   4461: #      *****************       *****************
                   4462: #          (6 words)               (6 words)
                   4463: #
                   4464: # the fscc instruction should take a trace trap. so, here we must create a
                   4465: # trace stack frame from an unimplemented fp instruction stack frame and
                   4466: # jump to the user supplied entry point for the trace exception
                   4467: funimp_trace:
                   4468:        fmov.l          %fpiar,0x8(%sp)         # current PC is in fpiar
                   4469:        mov.b           &0x24,0x7(%sp)          # vector offset = 0x024
                   4470:
                   4471:        bra.l           _real_trace
                   4472:
                   4473: ################################################################
                   4474:
                   4475:        global          tbl_trans
                   4476:        swbeg           &0x1c0
                   4477: tbl_trans:
                   4478:        short           tbl_trans - tbl_trans   # $00-0 fmovecr all
                   4479:        short           tbl_trans - tbl_trans   # $00-1 fmovecr all
                   4480:        short           tbl_trans - tbl_trans   # $00-2 fmovecr all
                   4481:        short           tbl_trans - tbl_trans   # $00-3 fmovecr all
                   4482:        short           tbl_trans - tbl_trans   # $00-4 fmovecr all
                   4483:        short           tbl_trans - tbl_trans   # $00-5 fmovecr all
                   4484:        short           tbl_trans - tbl_trans   # $00-6 fmovecr all
                   4485:        short           tbl_trans - tbl_trans   # $00-7 fmovecr all
                   4486:
                   4487:        short           tbl_trans - tbl_trans   # $01-0 fint norm
                   4488:        short           tbl_trans - tbl_trans   # $01-1 fint zero
                   4489:        short           tbl_trans - tbl_trans   # $01-2 fint inf
                   4490:        short           tbl_trans - tbl_trans   # $01-3 fint qnan
                   4491:        short           tbl_trans - tbl_trans   # $01-5 fint denorm
                   4492:        short           tbl_trans - tbl_trans   # $01-4 fint snan
                   4493:        short           tbl_trans - tbl_trans   # $01-6 fint unnorm
                   4494:        short           tbl_trans - tbl_trans   # $01-7 ERROR
                   4495:
                   4496:        short           ssinh    - tbl_trans    # $02-0 fsinh norm
                   4497:        short           src_zero - tbl_trans    # $02-1 fsinh zero
                   4498:        short           src_inf  - tbl_trans    # $02-2 fsinh inf
                   4499:        short           src_qnan - tbl_trans    # $02-3 fsinh qnan
                   4500:        short           ssinhd   - tbl_trans    # $02-5 fsinh denorm
                   4501:        short           src_snan - tbl_trans    # $02-4 fsinh snan
                   4502:        short           tbl_trans - tbl_trans   # $02-6 fsinh unnorm
                   4503:        short           tbl_trans - tbl_trans   # $02-7 ERROR
                   4504:
                   4505:        short           tbl_trans - tbl_trans   # $03-0 fintrz norm
                   4506:        short           tbl_trans - tbl_trans   # $03-1 fintrz zero
                   4507:        short           tbl_trans - tbl_trans   # $03-2 fintrz inf
                   4508:        short           tbl_trans - tbl_trans   # $03-3 fintrz qnan
                   4509:        short           tbl_trans - tbl_trans   # $03-5 fintrz denorm
                   4510:        short           tbl_trans - tbl_trans   # $03-4 fintrz snan
                   4511:        short           tbl_trans - tbl_trans   # $03-6 fintrz unnorm
                   4512:        short           tbl_trans - tbl_trans   # $03-7 ERROR
                   4513:
                   4514:        short           tbl_trans - tbl_trans   # $04-0 fsqrt norm
                   4515:        short           tbl_trans - tbl_trans   # $04-1 fsqrt zero
                   4516:        short           tbl_trans - tbl_trans   # $04-2 fsqrt inf
                   4517:        short           tbl_trans - tbl_trans   # $04-3 fsqrt qnan
                   4518:        short           tbl_trans - tbl_trans   # $04-5 fsqrt denorm
                   4519:        short           tbl_trans - tbl_trans   # $04-4 fsqrt snan
                   4520:        short           tbl_trans - tbl_trans   # $04-6 fsqrt unnorm
                   4521:        short           tbl_trans - tbl_trans   # $04-7 ERROR
                   4522:
                   4523:        short           tbl_trans - tbl_trans   # $05-0 ERROR
                   4524:        short           tbl_trans - tbl_trans   # $05-1 ERROR
                   4525:        short           tbl_trans - tbl_trans   # $05-2 ERROR
                   4526:        short           tbl_trans - tbl_trans   # $05-3 ERROR
                   4527:        short           tbl_trans - tbl_trans   # $05-4 ERROR
                   4528:        short           tbl_trans - tbl_trans   # $05-5 ERROR
                   4529:        short           tbl_trans - tbl_trans   # $05-6 ERROR
                   4530:        short           tbl_trans - tbl_trans   # $05-7 ERROR
                   4531:
                   4532:        short           slognp1  - tbl_trans    # $06-0 flognp1 norm
                   4533:        short           src_zero - tbl_trans    # $06-1 flognp1 zero
                   4534:        short           sopr_inf - tbl_trans    # $06-2 flognp1 inf
                   4535:        short           src_qnan - tbl_trans    # $06-3 flognp1 qnan
                   4536:        short           slognp1d - tbl_trans    # $06-5 flognp1 denorm
                   4537:        short           src_snan - tbl_trans    # $06-4 flognp1 snan
                   4538:        short           tbl_trans - tbl_trans   # $06-6 flognp1 unnorm
                   4539:        short           tbl_trans - tbl_trans   # $06-7 ERROR
                   4540:
                   4541:        short           tbl_trans - tbl_trans   # $07-0 ERROR
                   4542:        short           tbl_trans - tbl_trans   # $07-1 ERROR
                   4543:        short           tbl_trans - tbl_trans   # $07-2 ERROR
                   4544:        short           tbl_trans - tbl_trans   # $07-3 ERROR
                   4545:        short           tbl_trans - tbl_trans   # $07-4 ERROR
                   4546:        short           tbl_trans - tbl_trans   # $07-5 ERROR
                   4547:        short           tbl_trans - tbl_trans   # $07-6 ERROR
                   4548:        short           tbl_trans - tbl_trans   # $07-7 ERROR
                   4549:
                   4550:        short           setoxm1  - tbl_trans    # $08-0 fetoxm1 norm
                   4551:        short           src_zero - tbl_trans    # $08-1 fetoxm1 zero
                   4552:        short           setoxm1i - tbl_trans    # $08-2 fetoxm1 inf
                   4553:        short           src_qnan - tbl_trans    # $08-3 fetoxm1 qnan
                   4554:        short           setoxm1d - tbl_trans    # $08-5 fetoxm1 denorm
                   4555:        short           src_snan - tbl_trans    # $08-4 fetoxm1 snan
                   4556:        short           tbl_trans - tbl_trans   # $08-6 fetoxm1 unnorm
                   4557:        short           tbl_trans - tbl_trans   # $08-7 ERROR
                   4558:
                   4559:        short           stanh    - tbl_trans    # $09-0 ftanh norm
                   4560:        short           src_zero - tbl_trans    # $09-1 ftanh zero
                   4561:        short           src_one  - tbl_trans    # $09-2 ftanh inf
                   4562:        short           src_qnan - tbl_trans    # $09-3 ftanh qnan
                   4563:        short           stanhd   - tbl_trans    # $09-5 ftanh denorm
                   4564:        short           src_snan - tbl_trans    # $09-4 ftanh snan
                   4565:        short           tbl_trans - tbl_trans   # $09-6 ftanh unnorm
                   4566:        short           tbl_trans - tbl_trans   # $09-7 ERROR
                   4567:
                   4568:        short           satan    - tbl_trans    # $0a-0 fatan norm
                   4569:        short           src_zero - tbl_trans    # $0a-1 fatan zero
                   4570:        short           spi_2    - tbl_trans    # $0a-2 fatan inf
                   4571:        short           src_qnan - tbl_trans    # $0a-3 fatan qnan
                   4572:        short           satand   - tbl_trans    # $0a-5 fatan denorm
                   4573:        short           src_snan - tbl_trans    # $0a-4 fatan snan
                   4574:        short           tbl_trans - tbl_trans   # $0a-6 fatan unnorm
                   4575:        short           tbl_trans - tbl_trans   # $0a-7 ERROR
                   4576:
                   4577:        short           tbl_trans - tbl_trans   # $0b-0 ERROR
                   4578:        short           tbl_trans - tbl_trans   # $0b-1 ERROR
                   4579:        short           tbl_trans - tbl_trans   # $0b-2 ERROR
                   4580:        short           tbl_trans - tbl_trans   # $0b-3 ERROR
                   4581:        short           tbl_trans - tbl_trans   # $0b-4 ERROR
                   4582:        short           tbl_trans - tbl_trans   # $0b-5 ERROR
                   4583:        short           tbl_trans - tbl_trans   # $0b-6 ERROR
                   4584:        short           tbl_trans - tbl_trans   # $0b-7 ERROR
                   4585:
                   4586:        short           sasin    - tbl_trans    # $0c-0 fasin norm
                   4587:        short           src_zero - tbl_trans    # $0c-1 fasin zero
                   4588:        short           t_operr  - tbl_trans    # $0c-2 fasin inf
                   4589:        short           src_qnan - tbl_trans    # $0c-3 fasin qnan
                   4590:        short           sasind   - tbl_trans    # $0c-5 fasin denorm
                   4591:        short           src_snan - tbl_trans    # $0c-4 fasin snan
                   4592:        short           tbl_trans - tbl_trans   # $0c-6 fasin unnorm
                   4593:        short           tbl_trans - tbl_trans   # $0c-7 ERROR
                   4594:
                   4595:        short           satanh   - tbl_trans    # $0d-0 fatanh norm
                   4596:        short           src_zero - tbl_trans    # $0d-1 fatanh zero
                   4597:        short           t_operr  - tbl_trans    # $0d-2 fatanh inf
                   4598:        short           src_qnan - tbl_trans    # $0d-3 fatanh qnan
                   4599:        short           satanhd  - tbl_trans    # $0d-5 fatanh denorm
                   4600:        short           src_snan - tbl_trans    # $0d-4 fatanh snan
                   4601:        short           tbl_trans - tbl_trans   # $0d-6 fatanh unnorm
                   4602:        short           tbl_trans - tbl_trans   # $0d-7 ERROR
                   4603:
                   4604:        short           ssin     - tbl_trans    # $0e-0 fsin norm
                   4605:        short           src_zero - tbl_trans    # $0e-1 fsin zero
                   4606:        short           t_operr  - tbl_trans    # $0e-2 fsin inf
                   4607:        short           src_qnan - tbl_trans    # $0e-3 fsin qnan
                   4608:        short           ssind    - tbl_trans    # $0e-5 fsin denorm
                   4609:        short           src_snan - tbl_trans    # $0e-4 fsin snan
                   4610:        short           tbl_trans - tbl_trans   # $0e-6 fsin unnorm
                   4611:        short           tbl_trans - tbl_trans   # $0e-7 ERROR
                   4612:
                   4613:        short           stan     - tbl_trans    # $0f-0 ftan norm
                   4614:        short           src_zero - tbl_trans    # $0f-1 ftan zero
                   4615:        short           t_operr  - tbl_trans    # $0f-2 ftan inf
                   4616:        short           src_qnan - tbl_trans    # $0f-3 ftan qnan
                   4617:        short           stand    - tbl_trans    # $0f-5 ftan denorm
                   4618:        short           src_snan - tbl_trans    # $0f-4 ftan snan
                   4619:        short           tbl_trans - tbl_trans   # $0f-6 ftan unnorm
                   4620:        short           tbl_trans - tbl_trans   # $0f-7 ERROR
                   4621:
                   4622:        short           setox    - tbl_trans    # $10-0 fetox norm
                   4623:        short           ld_pone  - tbl_trans    # $10-1 fetox zero
                   4624:        short           szr_inf  - tbl_trans    # $10-2 fetox inf
                   4625:        short           src_qnan - tbl_trans    # $10-3 fetox qnan
                   4626:        short           setoxd   - tbl_trans    # $10-5 fetox denorm
                   4627:        short           src_snan - tbl_trans    # $10-4 fetox snan
                   4628:        short           tbl_trans - tbl_trans   # $10-6 fetox unnorm
                   4629:        short           tbl_trans - tbl_trans   # $10-7 ERROR
                   4630:
                   4631:        short           stwotox  - tbl_trans    # $11-0 ftwotox norm
                   4632:        short           ld_pone  - tbl_trans    # $11-1 ftwotox zero
                   4633:        short           szr_inf  - tbl_trans    # $11-2 ftwotox inf
                   4634:        short           src_qnan - tbl_trans    # $11-3 ftwotox qnan
                   4635:        short           stwotoxd - tbl_trans    # $11-5 ftwotox denorm
                   4636:        short           src_snan - tbl_trans    # $11-4 ftwotox snan
                   4637:        short           tbl_trans - tbl_trans   # $11-6 ftwotox unnorm
                   4638:        short           tbl_trans - tbl_trans   # $11-7 ERROR
                   4639:
                   4640:        short           stentox  - tbl_trans    # $12-0 ftentox norm
                   4641:        short           ld_pone  - tbl_trans    # $12-1 ftentox zero
                   4642:        short           szr_inf  - tbl_trans    # $12-2 ftentox inf
                   4643:        short           src_qnan - tbl_trans    # $12-3 ftentox qnan
                   4644:        short           stentoxd - tbl_trans    # $12-5 ftentox denorm
                   4645:        short           src_snan - tbl_trans    # $12-4 ftentox snan
                   4646:        short           tbl_trans - tbl_trans   # $12-6 ftentox unnorm
                   4647:        short           tbl_trans - tbl_trans   # $12-7 ERROR
                   4648:
                   4649:        short           tbl_trans - tbl_trans   # $13-0 ERROR
                   4650:        short           tbl_trans - tbl_trans   # $13-1 ERROR
                   4651:        short           tbl_trans - tbl_trans   # $13-2 ERROR
                   4652:        short           tbl_trans - tbl_trans   # $13-3 ERROR
                   4653:        short           tbl_trans - tbl_trans   # $13-4 ERROR
                   4654:        short           tbl_trans - tbl_trans   # $13-5 ERROR
                   4655:        short           tbl_trans - tbl_trans   # $13-6 ERROR
                   4656:        short           tbl_trans - tbl_trans   # $13-7 ERROR
                   4657:
                   4658:        short           slogn    - tbl_trans    # $14-0 flogn norm
                   4659:        short           t_dz2    - tbl_trans    # $14-1 flogn zero
                   4660:        short           sopr_inf - tbl_trans    # $14-2 flogn inf
                   4661:        short           src_qnan - tbl_trans    # $14-3 flogn qnan
                   4662:        short           slognd   - tbl_trans    # $14-5 flogn denorm
                   4663:        short           src_snan - tbl_trans    # $14-4 flogn snan
                   4664:        short           tbl_trans - tbl_trans   # $14-6 flogn unnorm
                   4665:        short           tbl_trans - tbl_trans   # $14-7 ERROR
                   4666:
                   4667:        short           slog10   - tbl_trans    # $15-0 flog10 norm
                   4668:        short           t_dz2    - tbl_trans    # $15-1 flog10 zero
                   4669:        short           sopr_inf - tbl_trans    # $15-2 flog10 inf
                   4670:        short           src_qnan - tbl_trans    # $15-3 flog10 qnan
                   4671:        short           slog10d  - tbl_trans    # $15-5 flog10 denorm
                   4672:        short           src_snan - tbl_trans    # $15-4 flog10 snan
                   4673:        short           tbl_trans - tbl_trans   # $15-6 flog10 unnorm
                   4674:        short           tbl_trans - tbl_trans   # $15-7 ERROR
                   4675:
                   4676:        short           slog2    - tbl_trans    # $16-0 flog2 norm
                   4677:        short           t_dz2    - tbl_trans    # $16-1 flog2 zero
                   4678:        short           sopr_inf - tbl_trans    # $16-2 flog2 inf
                   4679:        short           src_qnan - tbl_trans    # $16-3 flog2 qnan
                   4680:        short           slog2d   - tbl_trans    # $16-5 flog2 denorm
                   4681:        short           src_snan - tbl_trans    # $16-4 flog2 snan
                   4682:        short           tbl_trans - tbl_trans   # $16-6 flog2 unnorm
                   4683:        short           tbl_trans - tbl_trans   # $16-7 ERROR
                   4684:
                   4685:        short           tbl_trans - tbl_trans   # $17-0 ERROR
                   4686:        short           tbl_trans - tbl_trans   # $17-1 ERROR
                   4687:        short           tbl_trans - tbl_trans   # $17-2 ERROR
                   4688:        short           tbl_trans - tbl_trans   # $17-3 ERROR
                   4689:        short           tbl_trans - tbl_trans   # $17-4 ERROR
                   4690:        short           tbl_trans - tbl_trans   # $17-5 ERROR
                   4691:        short           tbl_trans - tbl_trans   # $17-6 ERROR
                   4692:        short           tbl_trans - tbl_trans   # $17-7 ERROR
                   4693:
                   4694:        short           tbl_trans - tbl_trans   # $18-0 fabs norm
                   4695:        short           tbl_trans - tbl_trans   # $18-1 fabs zero
                   4696:        short           tbl_trans - tbl_trans   # $18-2 fabs inf
                   4697:        short           tbl_trans - tbl_trans   # $18-3 fabs qnan
                   4698:        short           tbl_trans - tbl_trans   # $18-5 fabs denorm
                   4699:        short           tbl_trans - tbl_trans   # $18-4 fabs snan
                   4700:        short           tbl_trans - tbl_trans   # $18-6 fabs unnorm
                   4701:        short           tbl_trans - tbl_trans   # $18-7 ERROR
                   4702:
                   4703:        short           scosh    - tbl_trans    # $19-0 fcosh norm
                   4704:        short           ld_pone  - tbl_trans    # $19-1 fcosh zero
                   4705:        short           ld_pinf  - tbl_trans    # $19-2 fcosh inf
                   4706:        short           src_qnan - tbl_trans    # $19-3 fcosh qnan
                   4707:        short           scoshd   - tbl_trans    # $19-5 fcosh denorm
                   4708:        short           src_snan - tbl_trans    # $19-4 fcosh snan
                   4709:        short           tbl_trans - tbl_trans   # $19-6 fcosh unnorm
                   4710:        short           tbl_trans - tbl_trans   # $19-7 ERROR
                   4711:
                   4712:        short           tbl_trans - tbl_trans   # $1a-0 fneg norm
                   4713:        short           tbl_trans - tbl_trans   # $1a-1 fneg zero
                   4714:        short           tbl_trans - tbl_trans   # $1a-2 fneg inf
                   4715:        short           tbl_trans - tbl_trans   # $1a-3 fneg qnan
                   4716:        short           tbl_trans - tbl_trans   # $1a-5 fneg denorm
                   4717:        short           tbl_trans - tbl_trans   # $1a-4 fneg snan
                   4718:        short           tbl_trans - tbl_trans   # $1a-6 fneg unnorm
                   4719:        short           tbl_trans - tbl_trans   # $1a-7 ERROR
                   4720:
                   4721:        short           tbl_trans - tbl_trans   # $1b-0 ERROR
                   4722:        short           tbl_trans - tbl_trans   # $1b-1 ERROR
                   4723:        short           tbl_trans - tbl_trans   # $1b-2 ERROR
                   4724:        short           tbl_trans - tbl_trans   # $1b-3 ERROR
                   4725:        short           tbl_trans - tbl_trans   # $1b-4 ERROR
                   4726:        short           tbl_trans - tbl_trans   # $1b-5 ERROR
                   4727:        short           tbl_trans - tbl_trans   # $1b-6 ERROR
                   4728:        short           tbl_trans - tbl_trans   # $1b-7 ERROR
                   4729:
                   4730:        short           sacos    - tbl_trans    # $1c-0 facos norm
                   4731:        short           ld_ppi2  - tbl_trans    # $1c-1 facos zero
                   4732:        short           t_operr  - tbl_trans    # $1c-2 facos inf
                   4733:        short           src_qnan - tbl_trans    # $1c-3 facos qnan
                   4734:        short           sacosd   - tbl_trans    # $1c-5 facos denorm
                   4735:        short           src_snan - tbl_trans    # $1c-4 facos snan
                   4736:        short           tbl_trans - tbl_trans   # $1c-6 facos unnorm
                   4737:        short           tbl_trans - tbl_trans   # $1c-7 ERROR
                   4738:
                   4739:        short           scos     - tbl_trans    # $1d-0 fcos norm
                   4740:        short           ld_pone  - tbl_trans    # $1d-1 fcos zero
                   4741:        short           t_operr  - tbl_trans    # $1d-2 fcos inf
                   4742:        short           src_qnan - tbl_trans    # $1d-3 fcos qnan
                   4743:        short           scosd    - tbl_trans    # $1d-5 fcos denorm
                   4744:        short           src_snan - tbl_trans    # $1d-4 fcos snan
                   4745:        short           tbl_trans - tbl_trans   # $1d-6 fcos unnorm
                   4746:        short           tbl_trans - tbl_trans   # $1d-7 ERROR
                   4747:
                   4748:        short           sgetexp  - tbl_trans    # $1e-0 fgetexp norm
                   4749:        short           src_zero - tbl_trans    # $1e-1 fgetexp zero
                   4750:        short           t_operr  - tbl_trans    # $1e-2 fgetexp inf
                   4751:        short           src_qnan - tbl_trans    # $1e-3 fgetexp qnan
                   4752:        short           sgetexpd - tbl_trans    # $1e-5 fgetexp denorm
                   4753:        short           src_snan - tbl_trans    # $1e-4 fgetexp snan
                   4754:        short           tbl_trans - tbl_trans   # $1e-6 fgetexp unnorm
                   4755:        short           tbl_trans - tbl_trans   # $1e-7 ERROR
                   4756:
                   4757:        short           sgetman  - tbl_trans    # $1f-0 fgetman norm
                   4758:        short           src_zero - tbl_trans    # $1f-1 fgetman zero
                   4759:        short           t_operr  - tbl_trans    # $1f-2 fgetman inf
                   4760:        short           src_qnan - tbl_trans    # $1f-3 fgetman qnan
                   4761:        short           sgetmand - tbl_trans    # $1f-5 fgetman denorm
                   4762:        short           src_snan - tbl_trans    # $1f-4 fgetman snan
                   4763:        short           tbl_trans - tbl_trans   # $1f-6 fgetman unnorm
                   4764:        short           tbl_trans - tbl_trans   # $1f-7 ERROR
                   4765:
                   4766:        short           tbl_trans - tbl_trans   # $20-0 fdiv norm
                   4767:        short           tbl_trans - tbl_trans   # $20-1 fdiv zero
                   4768:        short           tbl_trans - tbl_trans   # $20-2 fdiv inf
                   4769:        short           tbl_trans - tbl_trans   # $20-3 fdiv qnan
                   4770:        short           tbl_trans - tbl_trans   # $20-5 fdiv denorm
                   4771:        short           tbl_trans - tbl_trans   # $20-4 fdiv snan
                   4772:        short           tbl_trans - tbl_trans   # $20-6 fdiv unnorm
                   4773:        short           tbl_trans - tbl_trans   # $20-7 ERROR
                   4774:
                   4775:        short           smod_snorm - tbl_trans  # $21-0 fmod norm
                   4776:        short           smod_szero - tbl_trans  # $21-1 fmod zero
                   4777:        short           smod_sinf - tbl_trans   # $21-2 fmod inf
                   4778:        short           sop_sqnan - tbl_trans   # $21-3 fmod qnan
                   4779:        short           smod_sdnrm - tbl_trans  # $21-5 fmod denorm
                   4780:        short           sop_ssnan - tbl_trans   # $21-4 fmod snan
                   4781:        short           tbl_trans - tbl_trans   # $21-6 fmod unnorm
                   4782:        short           tbl_trans - tbl_trans   # $21-7 ERROR
                   4783:
                   4784:        short           tbl_trans - tbl_trans   # $22-0 fadd norm
                   4785:        short           tbl_trans - tbl_trans   # $22-1 fadd zero
                   4786:        short           tbl_trans - tbl_trans   # $22-2 fadd inf
                   4787:        short           tbl_trans - tbl_trans   # $22-3 fadd qnan
                   4788:        short           tbl_trans - tbl_trans   # $22-5 fadd denorm
                   4789:        short           tbl_trans - tbl_trans   # $22-4 fadd snan
                   4790:        short           tbl_trans - tbl_trans   # $22-6 fadd unnorm
                   4791:        short           tbl_trans - tbl_trans   # $22-7 ERROR
                   4792:
                   4793:        short           tbl_trans - tbl_trans   # $23-0 fmul norm
                   4794:        short           tbl_trans - tbl_trans   # $23-1 fmul zero
                   4795:        short           tbl_trans - tbl_trans   # $23-2 fmul inf
                   4796:        short           tbl_trans - tbl_trans   # $23-3 fmul qnan
                   4797:        short           tbl_trans - tbl_trans   # $23-5 fmul denorm
                   4798:        short           tbl_trans - tbl_trans   # $23-4 fmul snan
                   4799:        short           tbl_trans - tbl_trans   # $23-6 fmul unnorm
                   4800:        short           tbl_trans - tbl_trans   # $23-7 ERROR
                   4801:
                   4802:        short           tbl_trans - tbl_trans   # $24-0 fsgldiv norm
                   4803:        short           tbl_trans - tbl_trans   # $24-1 fsgldiv zero
                   4804:        short           tbl_trans - tbl_trans   # $24-2 fsgldiv inf
                   4805:        short           tbl_trans - tbl_trans   # $24-3 fsgldiv qnan
                   4806:        short           tbl_trans - tbl_trans   # $24-5 fsgldiv denorm
                   4807:        short           tbl_trans - tbl_trans   # $24-4 fsgldiv snan
                   4808:        short           tbl_trans - tbl_trans   # $24-6 fsgldiv unnorm
                   4809:        short           tbl_trans - tbl_trans   # $24-7 ERROR
                   4810:
                   4811:        short           srem_snorm - tbl_trans  # $25-0 frem norm
                   4812:        short           srem_szero - tbl_trans  # $25-1 frem zero
                   4813:        short           srem_sinf - tbl_trans   # $25-2 frem inf
                   4814:        short           sop_sqnan - tbl_trans   # $25-3 frem qnan
                   4815:        short           srem_sdnrm - tbl_trans  # $25-5 frem denorm
                   4816:        short           sop_ssnan - tbl_trans   # $25-4 frem snan
                   4817:        short           tbl_trans - tbl_trans   # $25-6 frem unnorm
                   4818:        short           tbl_trans - tbl_trans   # $25-7 ERROR
                   4819:
                   4820:        short           sscale_snorm - tbl_trans # $26-0 fscale norm
                   4821:        short           sscale_szero - tbl_trans # $26-1 fscale zero
                   4822:        short           sscale_sinf - tbl_trans # $26-2 fscale inf
                   4823:        short           sop_sqnan - tbl_trans   # $26-3 fscale qnan
                   4824:        short           sscale_sdnrm - tbl_trans # $26-5 fscale denorm
                   4825:        short           sop_ssnan - tbl_trans   # $26-4 fscale snan
                   4826:        short           tbl_trans - tbl_trans   # $26-6 fscale unnorm
                   4827:        short           tbl_trans - tbl_trans   # $26-7 ERROR
                   4828:
                   4829:        short           tbl_trans - tbl_trans   # $27-0 fsglmul norm
                   4830:        short           tbl_trans - tbl_trans   # $27-1 fsglmul zero
                   4831:        short           tbl_trans - tbl_trans   # $27-2 fsglmul inf
                   4832:        short           tbl_trans - tbl_trans   # $27-3 fsglmul qnan
                   4833:        short           tbl_trans - tbl_trans   # $27-5 fsglmul denorm
                   4834:        short           tbl_trans - tbl_trans   # $27-4 fsglmul snan
                   4835:        short           tbl_trans - tbl_trans   # $27-6 fsglmul unnorm
                   4836:        short           tbl_trans - tbl_trans   # $27-7 ERROR
                   4837:
                   4838:        short           tbl_trans - tbl_trans   # $28-0 fsub norm
                   4839:        short           tbl_trans - tbl_trans   # $28-1 fsub zero
                   4840:        short           tbl_trans - tbl_trans   # $28-2 fsub inf
                   4841:        short           tbl_trans - tbl_trans   # $28-3 fsub qnan
                   4842:        short           tbl_trans - tbl_trans   # $28-5 fsub denorm
                   4843:        short           tbl_trans - tbl_trans   # $28-4 fsub snan
                   4844:        short           tbl_trans - tbl_trans   # $28-6 fsub unnorm
                   4845:        short           tbl_trans - tbl_trans   # $28-7 ERROR
                   4846:
                   4847:        short           tbl_trans - tbl_trans   # $29-0 ERROR
                   4848:        short           tbl_trans - tbl_trans   # $29-1 ERROR
                   4849:        short           tbl_trans - tbl_trans   # $29-2 ERROR
                   4850:        short           tbl_trans - tbl_trans   # $29-3 ERROR
                   4851:        short           tbl_trans - tbl_trans   # $29-4 ERROR
                   4852:        short           tbl_trans - tbl_trans   # $29-5 ERROR
                   4853:        short           tbl_trans - tbl_trans   # $29-6 ERROR
                   4854:        short           tbl_trans - tbl_trans   # $29-7 ERROR
                   4855:
                   4856:        short           tbl_trans - tbl_trans   # $2a-0 ERROR
                   4857:        short           tbl_trans - tbl_trans   # $2a-1 ERROR
                   4858:        short           tbl_trans - tbl_trans   # $2a-2 ERROR
                   4859:        short           tbl_trans - tbl_trans   # $2a-3 ERROR
                   4860:        short           tbl_trans - tbl_trans   # $2a-4 ERROR
                   4861:        short           tbl_trans - tbl_trans   # $2a-5 ERROR
                   4862:        short           tbl_trans - tbl_trans   # $2a-6 ERROR
                   4863:        short           tbl_trans - tbl_trans   # $2a-7 ERROR
                   4864:
                   4865:        short           tbl_trans - tbl_trans   # $2b-0 ERROR
                   4866:        short           tbl_trans - tbl_trans   # $2b-1 ERROR
                   4867:        short           tbl_trans - tbl_trans   # $2b-2 ERROR
                   4868:        short           tbl_trans - tbl_trans   # $2b-3 ERROR
                   4869:        short           tbl_trans - tbl_trans   # $2b-4 ERROR
                   4870:        short           tbl_trans - tbl_trans   # $2b-5 ERROR
                   4871:        short           tbl_trans - tbl_trans   # $2b-6 ERROR
                   4872:        short           tbl_trans - tbl_trans   # $2b-7 ERROR
                   4873:
                   4874:        short           tbl_trans - tbl_trans   # $2c-0 ERROR
                   4875:        short           tbl_trans - tbl_trans   # $2c-1 ERROR
                   4876:        short           tbl_trans - tbl_trans   # $2c-2 ERROR
                   4877:        short           tbl_trans - tbl_trans   # $2c-3 ERROR
                   4878:        short           tbl_trans - tbl_trans   # $2c-4 ERROR
                   4879:        short           tbl_trans - tbl_trans   # $2c-5 ERROR
                   4880:        short           tbl_trans - tbl_trans   # $2c-6 ERROR
                   4881:        short           tbl_trans - tbl_trans   # $2c-7 ERROR
                   4882:
                   4883:        short           tbl_trans - tbl_trans   # $2d-0 ERROR
                   4884:        short           tbl_trans - tbl_trans   # $2d-1 ERROR
                   4885:        short           tbl_trans - tbl_trans   # $2d-2 ERROR
                   4886:        short           tbl_trans - tbl_trans   # $2d-3 ERROR
                   4887:        short           tbl_trans - tbl_trans   # $2d-4 ERROR
                   4888:        short           tbl_trans - tbl_trans   # $2d-5 ERROR
                   4889:        short           tbl_trans - tbl_trans   # $2d-6 ERROR
                   4890:        short           tbl_trans - tbl_trans   # $2d-7 ERROR
                   4891:
                   4892:        short           tbl_trans - tbl_trans   # $2e-0 ERROR
                   4893:        short           tbl_trans - tbl_trans   # $2e-1 ERROR
                   4894:        short           tbl_trans - tbl_trans   # $2e-2 ERROR
                   4895:        short           tbl_trans - tbl_trans   # $2e-3 ERROR
                   4896:        short           tbl_trans - tbl_trans   # $2e-4 ERROR
                   4897:        short           tbl_trans - tbl_trans   # $2e-5 ERROR
                   4898:        short           tbl_trans - tbl_trans   # $2e-6 ERROR
                   4899:        short           tbl_trans - tbl_trans   # $2e-7 ERROR
                   4900:
                   4901:        short           tbl_trans - tbl_trans   # $2f-0 ERROR
                   4902:        short           tbl_trans - tbl_trans   # $2f-1 ERROR
                   4903:        short           tbl_trans - tbl_trans   # $2f-2 ERROR
                   4904:        short           tbl_trans - tbl_trans   # $2f-3 ERROR
                   4905:        short           tbl_trans - tbl_trans   # $2f-4 ERROR
                   4906:        short           tbl_trans - tbl_trans   # $2f-5 ERROR
                   4907:        short           tbl_trans - tbl_trans   # $2f-6 ERROR
                   4908:        short           tbl_trans - tbl_trans   # $2f-7 ERROR
                   4909:
                   4910:        short           ssincos  - tbl_trans    # $30-0 fsincos norm
                   4911:        short           ssincosz - tbl_trans    # $30-1 fsincos zero
                   4912:        short           ssincosi - tbl_trans    # $30-2 fsincos inf
                   4913:        short           ssincosqnan - tbl_trans # $30-3 fsincos qnan
                   4914:        short           ssincosd - tbl_trans    # $30-5 fsincos denorm
                   4915:        short           ssincossnan - tbl_trans # $30-4 fsincos snan
                   4916:        short           tbl_trans - tbl_trans   # $30-6 fsincos unnorm
                   4917:        short           tbl_trans - tbl_trans   # $30-7 ERROR
                   4918:
                   4919:        short           ssincos  - tbl_trans    # $31-0 fsincos norm
                   4920:        short           ssincosz - tbl_trans    # $31-1 fsincos zero
                   4921:        short           ssincosi - tbl_trans    # $31-2 fsincos inf
                   4922:        short           ssincosqnan - tbl_trans # $31-3 fsincos qnan
                   4923:        short           ssincosd - tbl_trans    # $31-5 fsincos denorm
                   4924:        short           ssincossnan - tbl_trans # $31-4 fsincos snan
                   4925:        short           tbl_trans - tbl_trans   # $31-6 fsincos unnorm
                   4926:        short           tbl_trans - tbl_trans   # $31-7 ERROR
                   4927:
                   4928:        short           ssincos  - tbl_trans    # $32-0 fsincos norm
                   4929:        short           ssincosz - tbl_trans    # $32-1 fsincos zero
                   4930:        short           ssincosi - tbl_trans    # $32-2 fsincos inf
                   4931:        short           ssincosqnan - tbl_trans # $32-3 fsincos qnan
                   4932:        short           ssincosd - tbl_trans    # $32-5 fsincos denorm
                   4933:        short           ssincossnan - tbl_trans # $32-4 fsincos snan
                   4934:        short           tbl_trans - tbl_trans   # $32-6 fsincos unnorm
                   4935:        short           tbl_trans - tbl_trans   # $32-7 ERROR
                   4936:
                   4937:        short           ssincos  - tbl_trans    # $33-0 fsincos norm
                   4938:        short           ssincosz - tbl_trans    # $33-1 fsincos zero
                   4939:        short           ssincosi - tbl_trans    # $33-2 fsincos inf
                   4940:        short           ssincosqnan - tbl_trans # $33-3 fsincos qnan
                   4941:        short           ssincosd - tbl_trans    # $33-5 fsincos denorm
                   4942:        short           ssincossnan - tbl_trans # $33-4 fsincos snan
                   4943:        short           tbl_trans - tbl_trans   # $33-6 fsincos unnorm
                   4944:        short           tbl_trans - tbl_trans   # $33-7 ERROR
                   4945:
                   4946:        short           ssincos  - tbl_trans    # $34-0 fsincos norm
                   4947:        short           ssincosz - tbl_trans    # $34-1 fsincos zero
                   4948:        short           ssincosi - tbl_trans    # $34-2 fsincos inf
                   4949:        short           ssincosqnan - tbl_trans # $34-3 fsincos qnan
                   4950:        short           ssincosd - tbl_trans    # $34-5 fsincos denorm
                   4951:        short           ssincossnan - tbl_trans # $34-4 fsincos snan
                   4952:        short           tbl_trans - tbl_trans   # $34-6 fsincos unnorm
                   4953:        short           tbl_trans - tbl_trans   # $34-7 ERROR
                   4954:
                   4955:        short           ssincos  - tbl_trans    # $35-0 fsincos norm
                   4956:        short           ssincosz - tbl_trans    # $35-1 fsincos zero
                   4957:        short           ssincosi - tbl_trans    # $35-2 fsincos inf
                   4958:        short           ssincosqnan - tbl_trans # $35-3 fsincos qnan
                   4959:        short           ssincosd - tbl_trans    # $35-5 fsincos denorm
                   4960:        short           ssincossnan - tbl_trans # $35-4 fsincos snan
                   4961:        short           tbl_trans - tbl_trans   # $35-6 fsincos unnorm
                   4962:        short           tbl_trans - tbl_trans   # $35-7 ERROR
                   4963:
                   4964:        short           ssincos  - tbl_trans    # $36-0 fsincos norm
                   4965:        short           ssincosz - tbl_trans    # $36-1 fsincos zero
                   4966:        short           ssincosi - tbl_trans    # $36-2 fsincos inf
                   4967:        short           ssincosqnan - tbl_trans # $36-3 fsincos qnan
                   4968:        short           ssincosd - tbl_trans    # $36-5 fsincos denorm
                   4969:        short           ssincossnan - tbl_trans # $36-4 fsincos snan
                   4970:        short           tbl_trans - tbl_trans   # $36-6 fsincos unnorm
                   4971:        short           tbl_trans - tbl_trans   # $36-7 ERROR
                   4972:
                   4973:        short           ssincos  - tbl_trans    # $37-0 fsincos norm
                   4974:        short           ssincosz - tbl_trans    # $37-1 fsincos zero
                   4975:        short           ssincosi - tbl_trans    # $37-2 fsincos inf
                   4976:        short           ssincosqnan - tbl_trans # $37-3 fsincos qnan
                   4977:        short           ssincosd - tbl_trans    # $37-5 fsincos denorm
                   4978:        short           ssincossnan - tbl_trans # $37-4 fsincos snan
                   4979:        short           tbl_trans - tbl_trans   # $37-6 fsincos unnorm
                   4980:        short           tbl_trans - tbl_trans   # $37-7 ERROR
                   4981:
                   4982: ##########
                   4983:
                   4984: # the instruction fetch access for the displacement word for the
                   4985: # fdbcc emulation failed. here, we create an access error frame
                   4986: # from the current frame and branch to _real_access().
                   4987: funimp_iacc:
                   4988:        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
                   4989:        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
                   4990:        fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0-fp1
                   4991:
                   4992:        mov.l           USER_FPIAR(%a6),EXC_PC(%a6) # store current PC
                   4993:
                   4994:        unlk            %a6
                   4995:
                   4996:        mov.l           (%sp),-(%sp)            # store SR,hi(PC)
                   4997:        mov.w           0x8(%sp),0x4(%sp)       # store lo(PC)
                   4998:        mov.w           &0x4008,0x6(%sp)        # store voff
                   4999:        mov.l           0x2(%sp),0x8(%sp)       # store EA
                   5000:        mov.l           &0x09428001,0xc(%sp)    # store FSLW
                   5001:
                   5002:        btst            &0x5,(%sp)              # user or supervisor mode?
                   5003:        beq.b           funimp_iacc_end         # user
                   5004:        bset            &0x2,0xd(%sp)           # set supervisor TM bit
                   5005:
                   5006: funimp_iacc_end:
                   5007:        bra.l           _real_access
                   5008:
                   5009: #########################################################################
                   5010: # ssin():     computes the sine of a normalized input                  #
                   5011: # ssind():    computes the sine of a denormalized input                        #
                   5012: # scos():     computes the cosine of a normalized input                        #
                   5013: # scosd():    computes the cosine of a denormalized input              #
                   5014: # ssincos():  computes the sine and cosine of a normalized input       #
                   5015: # ssincosd(): computes the sine and cosine of a denormalized input     #
                   5016: #                                                                      #
                   5017: # INPUT *************************************************************** #
                   5018: #      a0 = pointer to extended precision input                        #
                   5019: #      d0 = round precision,mode                                       #
                   5020: #                                                                      #
                   5021: # OUTPUT ************************************************************** #
                   5022: #      fp0 = sin(X) or cos(X)                                          #
                   5023: #                                                                      #
                   5024: #    For ssincos(X):                                                   #
                   5025: #      fp0 = sin(X)                                                    #
                   5026: #      fp1 = cos(X)                                                    #
                   5027: #                                                                      #
                   5028: # ACCURACY and MONOTONICITY ******************************************* #
                   5029: #      The returned result is within 1 ulp in 64 significant bit, i.e. #
                   5030: #      within 0.5001 ulp to 53 bits if the result is subsequently      #
                   5031: #      rounded to double precision. The result is provably monotonic   #
                   5032: #      in double precision.                                            #
                   5033: #                                                                      #
                   5034: # ALGORITHM ***********************************************************        #
                   5035: #                                                                      #
                   5036: #      SIN and COS:                                                    #
                   5037: #      1. If SIN is invoked, set AdjN := 0; otherwise, set AdjN := 1.  #
                   5038: #                                                                      #
                   5039: #      2. If |X| >= 15Pi or |X| < 2**(-40), go to 7.                   #
                   5040: #                                                                      #
                   5041: #      3. Decompose X as X = N(Pi/2) + r where |r| <= Pi/4. Let        #
                   5042: #              k = N mod 4, so in particular, k = 0,1,2,or 3.          #
                   5043: #              Overwrite k by k := k + AdjN.                           #
                   5044: #                                                                      #
                   5045: #      4. If k is even, go to 6.                                       #
                   5046: #                                                                      #
                   5047: #      5. (k is odd) Set j := (k-1)/2, sgn := (-1)**j.                 #
                   5048: #              Return sgn*cos(r) where cos(r) is approximated by an    #
                   5049: #              even polynomial in r, 1 + r*r*(B1+s*(B2+ ... + s*B8)),  #
                   5050: #              s = r*r.                                                #
                   5051: #              Exit.                                                   #
                   5052: #                                                                      #
                   5053: #      6. (k is even) Set j := k/2, sgn := (-1)**j. Return sgn*sin(r)  #
                   5054: #              where sin(r) is approximated by an odd polynomial in r  #
                   5055: #              r + r*s*(A1+s*(A2+ ... + s*A7)),        s = r*r.        #
                   5056: #              Exit.                                                   #
                   5057: #                                                                      #
                   5058: #      7. If |X| > 1, go to 9.                                         #
                   5059: #                                                                      #
                   5060: #      8. (|X|<2**(-40)) If SIN is invoked, return X;                  #
                   5061: #              otherwise return 1.                                     #
                   5062: #                                                                      #
                   5063: #      9. Overwrite X by X := X rem 2Pi. Now that |X| <= Pi,           #
                   5064: #              go back to 3.                                           #
                   5065: #                                                                      #
                   5066: #      SINCOS:                                                         #
                   5067: #      1. If |X| >= 15Pi or |X| < 2**(-40), go to 6.                   #
                   5068: #                                                                      #
                   5069: #      2. Decompose X as X = N(Pi/2) + r where |r| <= Pi/4. Let        #
                   5070: #              k = N mod 4, so in particular, k = 0,1,2,or 3.          #
                   5071: #                                                                      #
                   5072: #      3. If k is even, go to 5.                                       #
                   5073: #                                                                      #
                   5074: #      4. (k is odd) Set j1 := (k-1)/2, j2 := j1 (EOR) (k mod 2), ie.  #
                   5075: #              j1 exclusive or with the l.s.b. of k.                   #
                   5076: #              sgn1 := (-1)**j1, sgn2 := (-1)**j2.                     #
                   5077: #              SIN(X) = sgn1 * cos(r) and COS(X) = sgn2*sin(r) where   #
                   5078: #              sin(r) and cos(r) are computed as odd and even          #
                   5079: #              polynomials in r, respectively. Exit                    #
                   5080: #                                                                      #
                   5081: #      5. (k is even) Set j1 := k/2, sgn1 := (-1)**j1.                 #
                   5082: #              SIN(X) = sgn1 * sin(r) and COS(X) = sgn1*cos(r) where   #
                   5083: #              sin(r) and cos(r) are computed as odd and even          #
                   5084: #              polynomials in r, respectively. Exit                    #
                   5085: #                                                                      #
                   5086: #      6. If |X| > 1, go to 8.                                         #
                   5087: #                                                                      #
                   5088: #      7. (|X|<2**(-40)) SIN(X) = X and COS(X) = 1. Exit.              #
                   5089: #                                                                      #
                   5090: #      8. Overwrite X by X := X rem 2Pi. Now that |X| <= Pi,           #
                   5091: #              go back to 2.                                           #
                   5092: #                                                                      #
                   5093: #########################################################################
                   5094:
                   5095: SINA7: long            0xBD6AAA77,0xCCC994F5
                   5096: SINA6: long            0x3DE61209,0x7AAE8DA1
                   5097: SINA5: long            0xBE5AE645,0x2A118AE4
                   5098: SINA4: long            0x3EC71DE3,0xA5341531
                   5099: SINA3: long            0xBF2A01A0,0x1A018B59,0x00000000,0x00000000
                   5100: SINA2: long            0x3FF80000,0x88888888,0x888859AF,0x00000000
                   5101: SINA1: long            0xBFFC0000,0xAAAAAAAA,0xAAAAAA99,0x00000000
                   5102:
                   5103: COSB8: long            0x3D2AC4D0,0xD6011EE3
                   5104: COSB7: long            0xBDA9396F,0x9F45AC19
                   5105: COSB6: long            0x3E21EED9,0x0612C972
                   5106: COSB5: long            0xBE927E4F,0xB79D9FCF
                   5107: COSB4: long            0x3EFA01A0,0x1A01D423,0x00000000,0x00000000
                   5108: COSB3: long            0xBFF50000,0xB60B60B6,0x0B61D438,0x00000000
                   5109: COSB2: long            0x3FFA0000,0xAAAAAAAA,0xAAAAAB5E
                   5110: COSB1: long            0xBF000000
                   5111:
                   5112:        set             INARG,FP_SCR0
                   5113:
                   5114:        set             X,FP_SCR0
                   5115: #      set             XDCARE,X+2
                   5116:        set             XFRAC,X+4
                   5117:
                   5118:        set             RPRIME,FP_SCR0
                   5119:        set             SPRIME,FP_SCR1
                   5120:
                   5121:        set             POSNEG1,L_SCR1
                   5122:        set             TWOTO63,L_SCR1
                   5123:
                   5124:        set             ENDFLAG,L_SCR2
                   5125:        set             INT,L_SCR2
                   5126:
                   5127:        set             ADJN,L_SCR3
                   5128:
                   5129: ############################################
                   5130:        global          ssin
                   5131: ssin:
                   5132:        mov.l           &0,ADJN(%a6)            # yes; SET ADJN TO 0
                   5133:        bra.b           SINBGN
                   5134:
                   5135: ############################################
                   5136:        global          scos
                   5137: scos:
                   5138:        mov.l           &1,ADJN(%a6)            # yes; SET ADJN TO 1
                   5139:
                   5140: ############################################
                   5141: SINBGN:
                   5142: #--SAVE FPCR, FP1. CHECK IF |X| IS TOO SMALL OR LARGE
                   5143:
                   5144:        fmov.x          (%a0),%fp0              # LOAD INPUT
                   5145:        fmov.x          %fp0,X(%a6)             # save input at X
                   5146:
                   5147: # "COMPACTIFY" X
                   5148:        mov.l           (%a0),%d1               # put exp in hi word
                   5149:        mov.w           4(%a0),%d1              # fetch hi(man)
                   5150:        and.l           &0x7FFFFFFF,%d1         # strip sign
                   5151:
                   5152:        cmpi.l          %d1,&0x3FD78000         # is |X| >= 2**(-40)?
                   5153:        bge.b           SOK1                    # no
                   5154:        bra.w           SINSM                   # yes; input is very small
                   5155:
                   5156: SOK1:
                   5157:        cmp.l           %d1,&0x4004BC7E         # is |X| < 15 PI?
                   5158:        blt.b           SINMAIN                 # no
                   5159:        bra.w           SREDUCEX                # yes; input is very large
                   5160:
                   5161: #--THIS IS THE USUAL CASE, |X| <= 15 PI.
                   5162: #--THE ARGUMENT REDUCTION IS DONE BY TABLE LOOK UP.
                   5163: SINMAIN:
                   5164:        fmov.x          %fp0,%fp1
                   5165:        fmul.d          TWOBYPI(%pc),%fp1       # X*2/PI
                   5166:
                   5167:        lea             PITBL+0x200(%pc),%a1    # TABLE OF N*PI/2, N = -32,...,32
                   5168:
                   5169:        fmov.l          %fp1,INT(%a6)           # CONVERT TO INTEGER
                   5170:
                   5171:        mov.l           INT(%a6),%d1            # make a copy of N
                   5172:        asl.l           &4,%d1                  # N *= 16
                   5173:        add.l           %d1,%a1                 # tbl_addr = a1 + (N*16)
                   5174:
                   5175: # A1 IS THE ADDRESS OF N*PIBY2
                   5176: # ...WHICH IS IN TWO PIECES Y1 & Y2
                   5177:        fsub.x          (%a1)+,%fp0             # X-Y1
                   5178:        fsub.s          (%a1),%fp0              # fp0 = R = (X-Y1)-Y2
                   5179:
                   5180: SINCONT:
                   5181: #--continuation from REDUCEX
                   5182:
                   5183: #--GET N+ADJN AND SEE IF SIN(R) OR COS(R) IS NEEDED
                   5184:        mov.l           INT(%a6),%d1
                   5185:        add.l           ADJN(%a6),%d1           # SEE IF D0 IS ODD OR EVEN
                   5186:        ror.l           &1,%d1                  # D0 WAS ODD IFF D0 IS NEGATIVE
                   5187:        cmp.l           %d1,&0
                   5188:        blt.w           COSPOLY
                   5189:
                   5190: #--LET J BE THE LEAST SIG. BIT OF D0, LET SGN := (-1)**J.
                   5191: #--THEN WE RETURN      SGN*SIN(R). SGN*SIN(R) IS COMPUTED BY
                   5192: #--R' + R'*S*(A1 + S(A2 + S(A3 + S(A4 + ... + SA7)))), WHERE
                   5193: #--R' = SGN*R, S=R*R. THIS CAN BE REWRITTEN AS
                   5194: #--R' + R'*S*( [A1+T(A3+T(A5+TA7))] + [S(A2+T(A4+TA6))])
                   5195: #--WHERE T=S*S.
                   5196: #--NOTE THAT A3 THROUGH A7 ARE STORED IN DOUBLE PRECISION
                   5197: #--WHILE A1 AND A2 ARE IN DOUBLE-EXTENDED FORMAT.
                   5198: SINPOLY:
                   5199:        fmovm.x         &0x0c,-(%sp)            # save fp2/fp3
                   5200:
                   5201:        fmov.x          %fp0,X(%a6)             # X IS R
                   5202:        fmul.x          %fp0,%fp0               # FP0 IS S
                   5203:
                   5204:        fmov.d          SINA7(%pc),%fp3
                   5205:        fmov.d          SINA6(%pc),%fp2
                   5206:
                   5207:        fmov.x          %fp0,%fp1
                   5208:        fmul.x          %fp1,%fp1               # FP1 IS T
                   5209:
                   5210:        ror.l           &1,%d1
                   5211:        and.l           &0x80000000,%d1
                   5212: # ...LEAST SIG. BIT OF D0 IN SIGN POSITION
                   5213:        eor.l           %d1,X(%a6)              # X IS NOW R'= SGN*R
                   5214:
                   5215:        fmul.x          %fp1,%fp3               # TA7
                   5216:        fmul.x          %fp1,%fp2               # TA6
                   5217:
                   5218:        fadd.d          SINA5(%pc),%fp3         # A5+TA7
                   5219:        fadd.d          SINA4(%pc),%fp2         # A4+TA6
                   5220:
                   5221:        fmul.x          %fp1,%fp3               # T(A5+TA7)
                   5222:        fmul.x          %fp1,%fp2               # T(A4+TA6)
                   5223:
                   5224:        fadd.d          SINA3(%pc),%fp3         # A3+T(A5+TA7)
                   5225:        fadd.x          SINA2(%pc),%fp2         # A2+T(A4+TA6)
                   5226:
                   5227:        fmul.x          %fp3,%fp1               # T(A3+T(A5+TA7))
                   5228:
                   5229:        fmul.x          %fp0,%fp2               # S(A2+T(A4+TA6))
                   5230:        fadd.x          SINA1(%pc),%fp1         # A1+T(A3+T(A5+TA7))
                   5231:        fmul.x          X(%a6),%fp0             # R'*S
                   5232:
                   5233:        fadd.x          %fp2,%fp1               # [A1+T(A3+T(A5+TA7))]+[S(A2+T(A4+TA6))]
                   5234:
                   5235:        fmul.x          %fp1,%fp0               # SIN(R')-R'
                   5236:
                   5237:        fmovm.x         (%sp)+,&0x30            # restore fp2/fp3
                   5238:
                   5239:        fmov.l          %d0,%fpcr               # restore users round mode,prec
                   5240:        fadd.x          X(%a6),%fp0             # last inst - possible exception set
                   5241:        bra             t_inx2
                   5242:
                   5243: #--LET J BE THE LEAST SIG. BIT OF D0, LET SGN := (-1)**J.
                   5244: #--THEN WE RETURN      SGN*COS(R). SGN*COS(R) IS COMPUTED BY
                   5245: #--SGN + S'*(B1 + S(B2 + S(B3 + S(B4 + ... + SB8)))), WHERE
                   5246: #--S=R*R AND S'=SGN*S. THIS CAN BE REWRITTEN AS
                   5247: #--SGN + S'*([B1+T(B3+T(B5+TB7))] + [S(B2+T(B4+T(B6+TB8)))])
                   5248: #--WHERE T=S*S.
                   5249: #--NOTE THAT B4 THROUGH B8 ARE STORED IN DOUBLE PRECISION
                   5250: #--WHILE B2 AND B3 ARE IN DOUBLE-EXTENDED FORMAT, B1 IS -1/2
                   5251: #--AND IS THEREFORE STORED AS SINGLE PRECISION.
                   5252: COSPOLY:
                   5253:        fmovm.x         &0x0c,-(%sp)            # save fp2/fp3
                   5254:
                   5255:        fmul.x          %fp0,%fp0               # FP0 IS S
                   5256:
                   5257:        fmov.d          COSB8(%pc),%fp2
                   5258:        fmov.d          COSB7(%pc),%fp3
                   5259:
                   5260:        fmov.x          %fp0,%fp1
                   5261:        fmul.x          %fp1,%fp1               # FP1 IS T
                   5262:
                   5263:        fmov.x          %fp0,X(%a6)             # X IS S
                   5264:        ror.l           &1,%d1
                   5265:        and.l           &0x80000000,%d1
                   5266: # ...LEAST SIG. BIT OF D0 IN SIGN POSITION
                   5267:
                   5268:        fmul.x          %fp1,%fp2               # TB8
                   5269:
                   5270:        eor.l           %d1,X(%a6)              # X IS NOW S'= SGN*S
                   5271:        and.l           &0x80000000,%d1
                   5272:
                   5273:        fmul.x          %fp1,%fp3               # TB7
                   5274:
                   5275:        or.l            &0x3F800000,%d1         # D0 IS SGN IN SINGLE
                   5276:        mov.l           %d1,POSNEG1(%a6)
                   5277:
                   5278:        fadd.d          COSB6(%pc),%fp2         # B6+TB8
                   5279:        fadd.d          COSB5(%pc),%fp3         # B5+TB7
                   5280:
                   5281:        fmul.x          %fp1,%fp2               # T(B6+TB8)
                   5282:        fmul.x          %fp1,%fp3               # T(B5+TB7)
                   5283:
                   5284:        fadd.d          COSB4(%pc),%fp2         # B4+T(B6+TB8)
                   5285:        fadd.x          COSB3(%pc),%fp3         # B3+T(B5+TB7)
                   5286:
                   5287:        fmul.x          %fp1,%fp2               # T(B4+T(B6+TB8))
                   5288:        fmul.x          %fp3,%fp1               # T(B3+T(B5+TB7))
                   5289:
                   5290:        fadd.x          COSB2(%pc),%fp2         # B2+T(B4+T(B6+TB8))
                   5291:        fadd.s          COSB1(%pc),%fp1         # B1+T(B3+T(B5+TB7))
                   5292:
                   5293:        fmul.x          %fp2,%fp0               # S(B2+T(B4+T(B6+TB8)))
                   5294:
                   5295:        fadd.x          %fp1,%fp0
                   5296:
                   5297:        fmul.x          X(%a6),%fp0
                   5298:
                   5299:        fmovm.x         (%sp)+,&0x30            # restore fp2/fp3
                   5300:
                   5301:        fmov.l          %d0,%fpcr               # restore users round mode,prec
                   5302:        fadd.s          POSNEG1(%a6),%fp0       # last inst - possible exception set
                   5303:        bra             t_inx2
                   5304:
                   5305: ##############################################
                   5306:
                   5307: # SINe: Big OR Small?
                   5308: #--IF |X| > 15PI, WE USE THE GENERAL ARGUMENT REDUCTION.
                   5309: #--IF |X| < 2**(-40), RETURN X OR 1.
                   5310: SINBORS:
                   5311:        cmp.l           %d1,&0x3FFF8000
                   5312:        bgt.l           SREDUCEX
                   5313:
                   5314: SINSM:
                   5315:        mov.l           ADJN(%a6),%d1
                   5316:        cmp.l           %d1,&0
                   5317:        bgt.b           COSTINY
                   5318:
                   5319: # here, the operation may underflow iff the precision is sgl or dbl.
                   5320: # extended denorms are handled through another entry point.
                   5321: SINTINY:
                   5322: #      mov.w           &0x0000,XDCARE(%a6)     # JUST IN CASE
                   5323:
                   5324:        fmov.l          %d0,%fpcr               # restore users round mode,prec
                   5325:        mov.b           &FMOV_OP,%d1            # last inst is MOVE
                   5326:        fmov.x          X(%a6),%fp0             # last inst - possible exception set
                   5327:        bra             t_catch
                   5328:
                   5329: COSTINY:
                   5330:        fmov.s          &0x3F800000,%fp0        # fp0 = 1.0
                   5331:        fmov.l          %d0,%fpcr               # restore users round mode,prec
                   5332:        fadd.s          &0x80800000,%fp0        # last inst - possible exception set
                   5333:        bra             t_pinx2
                   5334:
                   5335: ################################################
                   5336:        global          ssind
                   5337: #--SIN(X) = X FOR DENORMALIZED X
                   5338: ssind:
                   5339:        bra             t_extdnrm
                   5340:
                   5341: ############################################
                   5342:        global          scosd
                   5343: #--COS(X) = 1 FOR DENORMALIZED X
                   5344: scosd:
                   5345:        fmov.s          &0x3F800000,%fp0        # fp0 = 1.0
                   5346:        bra             t_pinx2
                   5347:
                   5348: ##################################################
                   5349:
                   5350:        global          ssincos
                   5351: ssincos:
                   5352: #--SET ADJN TO 4
                   5353:        mov.l           &4,ADJN(%a6)
                   5354:
                   5355:        fmov.x          (%a0),%fp0              # LOAD INPUT
                   5356:        fmov.x          %fp0,X(%a6)
                   5357:
                   5358:        mov.l           (%a0),%d1
                   5359:        mov.w           4(%a0),%d1
                   5360:        and.l           &0x7FFFFFFF,%d1         # COMPACTIFY X
                   5361:
                   5362:        cmp.l           %d1,&0x3FD78000         # |X| >= 2**(-40)?
                   5363:        bge.b           SCOK1
                   5364:        bra.w           SCSM
                   5365:
                   5366: SCOK1:
                   5367:        cmp.l           %d1,&0x4004BC7E         # |X| < 15 PI?
                   5368:        blt.b           SCMAIN
                   5369:        bra.w           SREDUCEX
                   5370:
                   5371:
                   5372: #--THIS IS THE USUAL CASE, |X| <= 15 PI.
                   5373: #--THE ARGUMENT REDUCTION IS DONE BY TABLE LOOK UP.
                   5374: SCMAIN:
                   5375:        fmov.x          %fp0,%fp1
                   5376:
                   5377:        fmul.d          TWOBYPI(%pc),%fp1       # X*2/PI
                   5378:
                   5379:        lea             PITBL+0x200(%pc),%a1    # TABLE OF N*PI/2, N = -32,...,32
                   5380:
                   5381:        fmov.l          %fp1,INT(%a6)           # CONVERT TO INTEGER
                   5382:
                   5383:        mov.l           INT(%a6),%d1
                   5384:        asl.l           &4,%d1
                   5385:        add.l           %d1,%a1                 # ADDRESS OF N*PIBY2, IN Y1, Y2
                   5386:
                   5387:        fsub.x          (%a1)+,%fp0             # X-Y1
                   5388:        fsub.s          (%a1),%fp0              # FP0 IS R = (X-Y1)-Y2
                   5389:
                   5390: SCCONT:
                   5391: #--continuation point from REDUCEX
                   5392:
                   5393:        mov.l           INT(%a6),%d1
                   5394:        ror.l           &1,%d1
                   5395:        cmp.l           %d1,&0                  # D0 < 0 IFF N IS ODD
                   5396:        bge.w           NEVEN
                   5397:
                   5398: SNODD:
                   5399: #--REGISTERS SAVED SO FAR: D0, A0, FP2.
                   5400:        fmovm.x         &0x04,-(%sp)            # save fp2
                   5401:
                   5402:        fmov.x          %fp0,RPRIME(%a6)
                   5403:        fmul.x          %fp0,%fp0               # FP0 IS S = R*R
                   5404:        fmov.d          SINA7(%pc),%fp1         # A7
                   5405:        fmov.d          COSB8(%pc),%fp2         # B8
                   5406:        fmul.x          %fp0,%fp1               # SA7
                   5407:        fmul.x          %fp0,%fp2               # SB8
                   5408:
                   5409:        mov.l           %d2,-(%sp)
                   5410:        mov.l           %d1,%d2
                   5411:        ror.l           &1,%d2
                   5412:        and.l           &0x80000000,%d2
                   5413:        eor.l           %d1,%d2
                   5414:        and.l           &0x80000000,%d2
                   5415:
                   5416:        fadd.d          SINA6(%pc),%fp1         # A6+SA7
                   5417:        fadd.d          COSB7(%pc),%fp2         # B7+SB8
                   5418:
                   5419:        fmul.x          %fp0,%fp1               # S(A6+SA7)
                   5420:        eor.l           %d2,RPRIME(%a6)
                   5421:        mov.l           (%sp)+,%d2
                   5422:        fmul.x          %fp0,%fp2               # S(B7+SB8)
                   5423:        ror.l           &1,%d1
                   5424:        and.l           &0x80000000,%d1
                   5425:        mov.l           &0x3F800000,POSNEG1(%a6)
                   5426:        eor.l           %d1,POSNEG1(%a6)
                   5427:
                   5428:        fadd.d          SINA5(%pc),%fp1         # A5+S(A6+SA7)
                   5429:        fadd.d          COSB6(%pc),%fp2         # B6+S(B7+SB8)
                   5430:
                   5431:        fmul.x          %fp0,%fp1               # S(A5+S(A6+SA7))
                   5432:        fmul.x          %fp0,%fp2               # S(B6+S(B7+SB8))
                   5433:        fmov.x          %fp0,SPRIME(%a6)
                   5434:
                   5435:        fadd.d          SINA4(%pc),%fp1         # A4+S(A5+S(A6+SA7))
                   5436:        eor.l           %d1,SPRIME(%a6)
                   5437:        fadd.d          COSB5(%pc),%fp2         # B5+S(B6+S(B7+SB8))
                   5438:
                   5439:        fmul.x          %fp0,%fp1               # S(A4+...)
                   5440:        fmul.x          %fp0,%fp2               # S(B5+...)
                   5441:
                   5442:        fadd.d          SINA3(%pc),%fp1         # A3+S(A4+...)
                   5443:        fadd.d          COSB4(%pc),%fp2         # B4+S(B5+...)
                   5444:
                   5445:        fmul.x          %fp0,%fp1               # S(A3+...)
                   5446:        fmul.x          %fp0,%fp2               # S(B4+...)
                   5447:
                   5448:        fadd.x          SINA2(%pc),%fp1         # A2+S(A3+...)
                   5449:        fadd.x          COSB3(%pc),%fp2         # B3+S(B4+...)
                   5450:
                   5451:        fmul.x          %fp0,%fp1               # S(A2+...)
                   5452:        fmul.x          %fp0,%fp2               # S(B3+...)
                   5453:
                   5454:        fadd.x          SINA1(%pc),%fp1         # A1+S(A2+...)
                   5455:        fadd.x          COSB2(%pc),%fp2         # B2+S(B3+...)
                   5456:
                   5457:        fmul.x          %fp0,%fp1               # S(A1+...)
                   5458:        fmul.x          %fp2,%fp0               # S(B2+...)
                   5459:
                   5460:        fmul.x          RPRIME(%a6),%fp1        # R'S(A1+...)
                   5461:        fadd.s          COSB1(%pc),%fp0         # B1+S(B2...)
                   5462:        fmul.x          SPRIME(%a6),%fp0        # S'(B1+S(B2+...))
                   5463:
                   5464:        fmovm.x         (%sp)+,&0x20            # restore fp2
                   5465:
                   5466:        fmov.l          %d0,%fpcr
                   5467:        fadd.x          RPRIME(%a6),%fp1        # COS(X)
                   5468:        bsr             sto_cos                 # store cosine result
                   5469:        fadd.s          POSNEG1(%a6),%fp0       # SIN(X)
                   5470:        bra             t_inx2
                   5471:
                   5472: NEVEN:
                   5473: #--REGISTERS SAVED SO FAR: FP2.
                   5474:        fmovm.x         &0x04,-(%sp)            # save fp2
                   5475:
                   5476:        fmov.x          %fp0,RPRIME(%a6)
                   5477:        fmul.x          %fp0,%fp0               # FP0 IS S = R*R
                   5478:
                   5479:        fmov.d          COSB8(%pc),%fp1         # B8
                   5480:        fmov.d          SINA7(%pc),%fp2         # A7
                   5481:
                   5482:        fmul.x          %fp0,%fp1               # SB8
                   5483:        fmov.x          %fp0,SPRIME(%a6)
                   5484:        fmul.x          %fp0,%fp2               # SA7
                   5485:
                   5486:        ror.l           &1,%d1
                   5487:        and.l           &0x80000000,%d1
                   5488:
                   5489:        fadd.d          COSB7(%pc),%fp1         # B7+SB8
                   5490:        fadd.d          SINA6(%pc),%fp2         # A6+SA7
                   5491:
                   5492:        eor.l           %d1,RPRIME(%a6)
                   5493:        eor.l           %d1,SPRIME(%a6)
                   5494:
                   5495:        fmul.x          %fp0,%fp1               # S(B7+SB8)
                   5496:
                   5497:        or.l            &0x3F800000,%d1
                   5498:        mov.l           %d1,POSNEG1(%a6)
                   5499:
                   5500:        fmul.x          %fp0,%fp2               # S(A6+SA7)
                   5501:
                   5502:        fadd.d          COSB6(%pc),%fp1         # B6+S(B7+SB8)
                   5503:        fadd.d          SINA5(%pc),%fp2         # A5+S(A6+SA7)
                   5504:
                   5505:        fmul.x          %fp0,%fp1               # S(B6+S(B7+SB8))
                   5506:        fmul.x          %fp0,%fp2               # S(A5+S(A6+SA7))
                   5507:
                   5508:        fadd.d          COSB5(%pc),%fp1         # B5+S(B6+S(B7+SB8))
                   5509:        fadd.d          SINA4(%pc),%fp2         # A4+S(A5+S(A6+SA7))
                   5510:
                   5511:        fmul.x          %fp0,%fp1               # S(B5+...)
                   5512:        fmul.x          %fp0,%fp2               # S(A4+...)
                   5513:
                   5514:        fadd.d          COSB4(%pc),%fp1         # B4+S(B5+...)
                   5515:        fadd.d          SINA3(%pc),%fp2         # A3+S(A4+...)
                   5516:
                   5517:        fmul.x          %fp0,%fp1               # S(B4+...)
                   5518:        fmul.x          %fp0,%fp2               # S(A3+...)
                   5519:
                   5520:        fadd.x          COSB3(%pc),%fp1         # B3+S(B4+...)
                   5521:        fadd.x          SINA2(%pc),%fp2         # A2+S(A3+...)
                   5522:
                   5523:        fmul.x          %fp0,%fp1               # S(B3+...)
                   5524:        fmul.x          %fp0,%fp2               # S(A2+...)
                   5525:
                   5526:        fadd.x          COSB2(%pc),%fp1         # B2+S(B3+...)
                   5527:        fadd.x          SINA1(%pc),%fp2         # A1+S(A2+...)
                   5528:
                   5529:        fmul.x          %fp0,%fp1               # S(B2+...)
                   5530:        fmul.x          %fp2,%fp0               # s(a1+...)
                   5531:
                   5532:
                   5533:        fadd.s          COSB1(%pc),%fp1         # B1+S(B2...)
                   5534:        fmul.x          RPRIME(%a6),%fp0        # R'S(A1+...)
                   5535:        fmul.x          SPRIME(%a6),%fp1        # S'(B1+S(B2+...))
                   5536:
                   5537:        fmovm.x         (%sp)+,&0x20            # restore fp2
                   5538:
                   5539:        fmov.l          %d0,%fpcr
                   5540:        fadd.s          POSNEG1(%a6),%fp1       # COS(X)
                   5541:        bsr             sto_cos                 # store cosine result
                   5542:        fadd.x          RPRIME(%a6),%fp0        # SIN(X)
                   5543:        bra             t_inx2
                   5544:
                   5545: ################################################
                   5546:
                   5547: SCBORS:
                   5548:        cmp.l           %d1,&0x3FFF8000
                   5549:        bgt.w           SREDUCEX
                   5550:
                   5551: ################################################
                   5552:
                   5553: SCSM:
                   5554: #      mov.w           &0x0000,XDCARE(%a6)
                   5555:        fmov.s          &0x3F800000,%fp1
                   5556:
                   5557:        fmov.l          %d0,%fpcr
                   5558:        fsub.s          &0x00800000,%fp1
                   5559:        bsr             sto_cos                 # store cosine result
                   5560:        fmov.l          %fpcr,%d0               # d0 must have fpcr,too
                   5561:        mov.b           &FMOV_OP,%d1            # last inst is MOVE
                   5562:        fmov.x          X(%a6),%fp0
                   5563:        bra             t_catch
                   5564:
                   5565: ##############################################
                   5566:
                   5567:        global          ssincosd
                   5568: #--SIN AND COS OF X FOR DENORMALIZED X
                   5569: ssincosd:
                   5570:        mov.l           %d0,-(%sp)              # save d0
                   5571:        fmov.s          &0x3F800000,%fp1
                   5572:        bsr             sto_cos                 # store cosine result
                   5573:        mov.l           (%sp)+,%d0              # restore d0
                   5574:        bra             t_extdnrm
                   5575:
                   5576: ############################################
                   5577:
                   5578: #--WHEN REDUCEX IS USED, THE CODE WILL INEVITABLY BE SLOW.
                   5579: #--THIS REDUCTION METHOD, HOWEVER, IS MUCH FASTER THAN USING
                   5580: #--THE REMAINDER INSTRUCTION WHICH IS NOW IN SOFTWARE.
                   5581: SREDUCEX:
                   5582:        fmovm.x         &0x3c,-(%sp)            # save {fp2-fp5}
                   5583:        mov.l           %d2,-(%sp)              # save d2
                   5584:        fmov.s          &0x00000000,%fp1        # fp1 = 0
                   5585:
                   5586: #--If compact form of abs(arg) in d0=$7ffeffff, argument is so large that
                   5587: #--there is a danger of unwanted overflow in first LOOP iteration.  In this
                   5588: #--case, reduce argument by one remainder step to make subsequent reduction
                   5589: #--safe.
                   5590:        cmp.l           %d1,&0x7ffeffff         # is arg dangerously large?
                   5591:        bne.b           SLOOP                   # no
                   5592:
                   5593: # yes; create 2**16383*PI/2
                   5594:        mov.w           &0x7ffe,FP_SCR0_EX(%a6)
                   5595:        mov.l           &0xc90fdaa2,FP_SCR0_HI(%a6)
                   5596:        clr.l           FP_SCR0_LO(%a6)
                   5597:
                   5598: # create low half of 2**16383*PI/2 at FP_SCR1
                   5599:        mov.w           &0x7fdc,FP_SCR1_EX(%a6)
                   5600:        mov.l           &0x85a308d3,FP_SCR1_HI(%a6)
                   5601:        clr.l           FP_SCR1_LO(%a6)
                   5602:
                   5603:        ftest.x         %fp0                    # test sign of argument
                   5604:        fblt.w          sred_neg
                   5605:
                   5606:        or.b            &0x80,FP_SCR0_EX(%a6)   # positive arg
                   5607:        or.b            &0x80,FP_SCR1_EX(%a6)
                   5608: sred_neg:
                   5609:        fadd.x          FP_SCR0(%a6),%fp0       # high part of reduction is exact
                   5610:        fmov.x          %fp0,%fp1               # save high result in fp1
                   5611:        fadd.x          FP_SCR1(%a6),%fp0       # low part of reduction
                   5612:        fsub.x          %fp0,%fp1               # determine low component of result
                   5613:        fadd.x          FP_SCR1(%a6),%fp1       # fp0/fp1 are reduced argument.
                   5614:
                   5615: #--ON ENTRY, FP0 IS X, ON RETURN, FP0 IS X REM PI/2, |X| <= PI/4.
                   5616: #--integer quotient will be stored in N
                   5617: #--Intermeditate remainder is 66-bit long; (R,r) in (FP0,FP1)
                   5618: SLOOP:
                   5619:        fmov.x          %fp0,INARG(%a6)         # +-2**K * F, 1 <= F < 2
                   5620:        mov.w           INARG(%a6),%d1
                   5621:        mov.l           %d1,%a1                 # save a copy of D0
                   5622:        and.l           &0x00007FFF,%d1
                   5623:        sub.l           &0x00003FFF,%d1         # d0 = K
                   5624:        cmp.l           %d1,&28
                   5625:        ble.b           SLASTLOOP
                   5626: SCONTLOOP:
                   5627:        sub.l           &27,%d1                 # d0 = L := K-27
                   5628:        mov.b           &0,ENDFLAG(%a6)
                   5629:        bra.b           SWORK
                   5630: SLASTLOOP:
                   5631:        clr.l           %d1                     # d0 = L := 0
                   5632:        mov.b           &1,ENDFLAG(%a6)
                   5633:
                   5634: SWORK:
                   5635: #--FIND THE REMAINDER OF (R,r) W.R.T.  2**L * (PI/2). L IS SO CHOSEN
                   5636: #--THAT        INT( X * (2/PI) / 2**(L) ) < 2**29.
                   5637:
                   5638: #--CREATE 2**(-L) * (2/PI), SIGN(INARG)*2**(63),
                   5639: #--2**L * (PIby2_1), 2**L * (PIby2_2)
                   5640:
                   5641:        mov.l           &0x00003FFE,%d2         # BIASED EXP OF 2/PI
                   5642:        sub.l           %d1,%d2                 # BIASED EXP OF 2**(-L)*(2/PI)
                   5643:
                   5644:        mov.l           &0xA2F9836E,FP_SCR0_HI(%a6)
                   5645:        mov.l           &0x4E44152A,FP_SCR0_LO(%a6)
                   5646:        mov.w           %d2,FP_SCR0_EX(%a6)     # FP_SCR0 = 2**(-L)*(2/PI)
                   5647:
                   5648:        fmov.x          %fp0,%fp2
                   5649:        fmul.x          FP_SCR0(%a6),%fp2       # fp2 = X * 2**(-L)*(2/PI)
                   5650:
                   5651: #--WE MUST NOW FIND INT(FP2). SINCE WE NEED THIS VALUE IN
                   5652: #--FLOATING POINT FORMAT, THE TWO FMOVE'S      FMOVE.L FP <--> N
                   5653: #--WILL BE TOO INEFFICIENT. THE WAY AROUND IT IS THAT
                   5654: #--(SIGN(INARG)*2**63  +       FP2) - SIGN(INARG)*2**63 WILL GIVE
                   5655: #--US THE DESIRED VALUE IN FLOATING POINT.
                   5656:        mov.l           %a1,%d2
                   5657:        swap            %d2
                   5658:        and.l           &0x80000000,%d2
                   5659:        or.l            &0x5F000000,%d2         # d2 = SIGN(INARG)*2**63 IN SGL
                   5660:        mov.l           %d2,TWOTO63(%a6)
                   5661:        fadd.s          TWOTO63(%a6),%fp2       # THE FRACTIONAL PART OF FP1 IS ROUNDED
                   5662:        fsub.s          TWOTO63(%a6),%fp2       # fp2 = N
                   5663: #      fint.x          %fp2
                   5664:
                   5665: #--CREATING 2**(L)*Piby2_1 and 2**(L)*Piby2_2
                   5666:        mov.l           %d1,%d2                 # d2 = L
                   5667:
                   5668:        add.l           &0x00003FFF,%d2         # BIASED EXP OF 2**L * (PI/2)
                   5669:        mov.w           %d2,FP_SCR0_EX(%a6)
                   5670:        mov.l           &0xC90FDAA2,FP_SCR0_HI(%a6)
                   5671:        clr.l           FP_SCR0_LO(%a6)         # FP_SCR0 = 2**(L) * Piby2_1
                   5672:
                   5673:        add.l           &0x00003FDD,%d1
                   5674:        mov.w           %d1,FP_SCR1_EX(%a6)
                   5675:        mov.l           &0x85A308D3,FP_SCR1_HI(%a6)
                   5676:        clr.l           FP_SCR1_LO(%a6)         # FP_SCR1 = 2**(L) * Piby2_2
                   5677:
                   5678:        mov.b           ENDFLAG(%a6),%d1
                   5679:
                   5680: #--We are now ready to perform (R+r) - N*P1 - N*P2, P1 = 2**(L) * Piby2_1 and
                   5681: #--P2 = 2**(L) * Piby2_2
                   5682:        fmov.x          %fp2,%fp4               # fp4 = N
                   5683:        fmul.x          FP_SCR0(%a6),%fp4       # fp4 = W = N*P1
                   5684:        fmov.x          %fp2,%fp5               # fp5 = N
                   5685:        fmul.x          FP_SCR1(%a6),%fp5       # fp5 = w = N*P2
                   5686:        fmov.x          %fp4,%fp3               # fp3 = W = N*P1
                   5687:
                   5688: #--we want P+p = W+w  but  |p| <= half ulp of P
                   5689: #--Then, we need to compute  A := R-P   and  a := r-p
                   5690:        fadd.x          %fp5,%fp3               # fp3 = P
                   5691:        fsub.x          %fp3,%fp4               # fp4 = W-P
                   5692:
                   5693:        fsub.x          %fp3,%fp0               # fp0 = A := R - P
                   5694:        fadd.x          %fp5,%fp4               # fp4 = p = (W-P)+w
                   5695:
                   5696:        fmov.x          %fp0,%fp3               # fp3 = A
                   5697:        fsub.x          %fp4,%fp1               # fp1 = a := r - p
                   5698:
                   5699: #--Now we need to normalize (A,a) to  "new (R,r)" where R+r = A+a but
                   5700: #--|r| <= half ulp of R.
                   5701:        fadd.x          %fp1,%fp0               # fp0 = R := A+a
                   5702: #--No need to calculate r if this is the last loop
                   5703:        cmp.b           %d1,&0
                   5704:        bgt.w           SRESTORE
                   5705:
                   5706: #--Need to calculate r
                   5707:        fsub.x          %fp0,%fp3               # fp3 = A-R
                   5708:        fadd.x          %fp3,%fp1               # fp1 = r := (A-R)+a
                   5709:        bra.w           SLOOP
                   5710:
                   5711: SRESTORE:
                   5712:        fmov.l          %fp2,INT(%a6)
                   5713:        mov.l           (%sp)+,%d2              # restore d2
                   5714:        fmovm.x         (%sp)+,&0x3c            # restore {fp2-fp5}
                   5715:
                   5716:        mov.l           ADJN(%a6),%d1
                   5717:        cmp.l           %d1,&4
                   5718:
                   5719:        blt.w           SINCONT
                   5720:        bra.w           SCCONT
                   5721:
                   5722: #########################################################################
                   5723: # stan():  computes the tangent of a normalized input                  #
                   5724: # stand(): computes the tangent of a denormalized input                        #
                   5725: #                                                                      #
                   5726: # INPUT *************************************************************** #
                   5727: #      a0 = pointer to extended precision input                        #
                   5728: #      d0 = round precision,mode                                       #
                   5729: #                                                                      #
                   5730: # OUTPUT ************************************************************** #
                   5731: #      fp0 = tan(X)                                                    #
                   5732: #                                                                      #
                   5733: # ACCURACY and MONOTONICITY ******************************************* #
                   5734: #      The returned result is within 3 ulp in 64 significant bit, i.e. #
                   5735: #      within 0.5001 ulp to 53 bits if the result is subsequently      #
                   5736: #      rounded to double precision. The result is provably monotonic   #
                   5737: #      in double precision.                                            #
                   5738: #                                                                      #
                   5739: # ALGORITHM *********************************************************** #
                   5740: #                                                                      #
                   5741: #      1. If |X| >= 15Pi or |X| < 2**(-40), go to 6.                   #
                   5742: #                                                                      #
                   5743: #      2. Decompose X as X = N(Pi/2) + r where |r| <= Pi/4. Let        #
                   5744: #              k = N mod 2, so in particular, k = 0 or 1.              #
                   5745: #                                                                      #
                   5746: #      3. If k is odd, go to 5.                                        #
                   5747: #                                                                      #
                   5748: #      4. (k is even) Tan(X) = tan(r) and tan(r) is approximated by a  #
                   5749: #              rational function U/V where                             #
                   5750: #              U = r + r*s*(P1 + s*(P2 + s*P3)), and                   #
                   5751: #              V = 1 + s*(Q1 + s*(Q2 + s*(Q3 + s*Q4))),  s = r*r.      #
                   5752: #              Exit.                                                   #
                   5753: #                                                                      #
                   5754: #      4. (k is odd) Tan(X) = -cot(r). Since tan(r) is approximated by #
                   5755: #              a rational function U/V where                           #
                   5756: #              U = r + r*s*(P1 + s*(P2 + s*P3)), and                   #
                   5757: #              V = 1 + s*(Q1 + s*(Q2 + s*(Q3 + s*Q4))), s = r*r,       #
                   5758: #              -Cot(r) = -V/U. Exit.                                   #
                   5759: #                                                                      #
                   5760: #      6. If |X| > 1, go to 8.                                         #
                   5761: #                                                                      #
                   5762: #      7. (|X|<2**(-40)) Tan(X) = X. Exit.                             #
                   5763: #                                                                      #
                   5764: #      8. Overwrite X by X := X rem 2Pi. Now that |X| <= Pi, go back   #
                   5765: #              to 2.                                                   #
                   5766: #                                                                      #
                   5767: #########################################################################
                   5768:
                   5769: TANQ4:
                   5770:        long            0x3EA0B759,0xF50F8688
                   5771: TANP3:
                   5772:        long            0xBEF2BAA5,0xA8924F04
                   5773:
                   5774: TANQ3:
                   5775:        long            0xBF346F59,0xB39BA65F,0x00000000,0x00000000
                   5776:
                   5777: TANP2:
                   5778:        long            0x3FF60000,0xE073D3FC,0x199C4A00,0x00000000
                   5779:
                   5780: TANQ2:
                   5781:        long            0x3FF90000,0xD23CD684,0x15D95FA1,0x00000000
                   5782:
                   5783: TANP1:
                   5784:        long            0xBFFC0000,0x8895A6C5,0xFB423BCA,0x00000000
                   5785:
                   5786: TANQ1:
                   5787:        long            0xBFFD0000,0xEEF57E0D,0xA84BC8CE,0x00000000
                   5788:
                   5789: INVTWOPI:
                   5790:        long            0x3FFC0000,0xA2F9836E,0x4E44152A,0x00000000
                   5791:
                   5792: TWOPI1:
                   5793:        long            0x40010000,0xC90FDAA2,0x00000000,0x00000000
                   5794: TWOPI2:
                   5795:        long            0x3FDF0000,0x85A308D4,0x00000000,0x00000000
                   5796:
                   5797: #--N*PI/2, -32 <= N <= 32, IN A LEADING TERM IN EXT. AND TRAILING
                   5798: #--TERM IN SGL. NOTE THAT PI IS 64-BIT LONG, THUS N*PI/2 IS AT
                   5799: #--MOST 69 BITS LONG.
                   5800: #      global          PITBL
                   5801: PITBL:
                   5802:        long            0xC0040000,0xC90FDAA2,0x2168C235,0x21800000
                   5803:        long            0xC0040000,0xC2C75BCD,0x105D7C23,0xA0D00000
                   5804:        long            0xC0040000,0xBC7EDCF7,0xFF523611,0xA1E80000
                   5805:        long            0xC0040000,0xB6365E22,0xEE46F000,0x21480000
                   5806:        long            0xC0040000,0xAFEDDF4D,0xDD3BA9EE,0xA1200000
                   5807:        long            0xC0040000,0xA9A56078,0xCC3063DD,0x21FC0000
                   5808:        long            0xC0040000,0xA35CE1A3,0xBB251DCB,0x21100000
                   5809:        long            0xC0040000,0x9D1462CE,0xAA19D7B9,0xA1580000
                   5810:        long            0xC0040000,0x96CBE3F9,0x990E91A8,0x21E00000
                   5811:        long            0xC0040000,0x90836524,0x88034B96,0x20B00000
                   5812:        long            0xC0040000,0x8A3AE64F,0x76F80584,0xA1880000
                   5813:        long            0xC0040000,0x83F2677A,0x65ECBF73,0x21C40000
                   5814:        long            0xC0030000,0xFB53D14A,0xA9C2F2C2,0x20000000
                   5815:        long            0xC0030000,0xEEC2D3A0,0x87AC669F,0x21380000
                   5816:        long            0xC0030000,0xE231D5F6,0x6595DA7B,0xA1300000
                   5817:        long            0xC0030000,0xD5A0D84C,0x437F4E58,0x9FC00000
                   5818:        long            0xC0030000,0xC90FDAA2,0x2168C235,0x21000000
                   5819:        long            0xC0030000,0xBC7EDCF7,0xFF523611,0xA1680000
                   5820:        long            0xC0030000,0xAFEDDF4D,0xDD3BA9EE,0xA0A00000
                   5821:        long            0xC0030000,0xA35CE1A3,0xBB251DCB,0x20900000
                   5822:        long            0xC0030000,0x96CBE3F9,0x990E91A8,0x21600000
                   5823:        long            0xC0030000,0x8A3AE64F,0x76F80584,0xA1080000
                   5824:        long            0xC0020000,0xFB53D14A,0xA9C2F2C2,0x1F800000
                   5825:        long            0xC0020000,0xE231D5F6,0x6595DA7B,0xA0B00000
                   5826:        long            0xC0020000,0xC90FDAA2,0x2168C235,0x20800000
                   5827:        long            0xC0020000,0xAFEDDF4D,0xDD3BA9EE,0xA0200000
                   5828:        long            0xC0020000,0x96CBE3F9,0x990E91A8,0x20E00000
                   5829:        long            0xC0010000,0xFB53D14A,0xA9C2F2C2,0x1F000000
                   5830:        long            0xC0010000,0xC90FDAA2,0x2168C235,0x20000000
                   5831:        long            0xC0010000,0x96CBE3F9,0x990E91A8,0x20600000
                   5832:        long            0xC0000000,0xC90FDAA2,0x2168C235,0x1F800000
                   5833:        long            0xBFFF0000,0xC90FDAA2,0x2168C235,0x1F000000
                   5834:        long            0x00000000,0x00000000,0x00000000,0x00000000
                   5835:        long            0x3FFF0000,0xC90FDAA2,0x2168C235,0x9F000000
                   5836:        long            0x40000000,0xC90FDAA2,0x2168C235,0x9F800000
                   5837:        long            0x40010000,0x96CBE3F9,0x990E91A8,0xA0600000
                   5838:        long            0x40010000,0xC90FDAA2,0x2168C235,0xA0000000
                   5839:        long            0x40010000,0xFB53D14A,0xA9C2F2C2,0x9F000000
                   5840:        long            0x40020000,0x96CBE3F9,0x990E91A8,0xA0E00000
                   5841:        long            0x40020000,0xAFEDDF4D,0xDD3BA9EE,0x20200000
                   5842:        long            0x40020000,0xC90FDAA2,0x2168C235,0xA0800000
                   5843:        long            0x40020000,0xE231D5F6,0x6595DA7B,0x20B00000
                   5844:        long            0x40020000,0xFB53D14A,0xA9C2F2C2,0x9F800000
                   5845:        long            0x40030000,0x8A3AE64F,0x76F80584,0x21080000
                   5846:        long            0x40030000,0x96CBE3F9,0x990E91A8,0xA1600000
                   5847:        long            0x40030000,0xA35CE1A3,0xBB251DCB,0xA0900000
                   5848:        long            0x40030000,0xAFEDDF4D,0xDD3BA9EE,0x20A00000
                   5849:        long            0x40030000,0xBC7EDCF7,0xFF523611,0x21680000
                   5850:        long            0x40030000,0xC90FDAA2,0x2168C235,0xA1000000
                   5851:        long            0x40030000,0xD5A0D84C,0x437F4E58,0x1FC00000
                   5852:        long            0x40030000,0xE231D5F6,0x6595DA7B,0x21300000
                   5853:        long            0x40030000,0xEEC2D3A0,0x87AC669F,0xA1380000
                   5854:        long            0x40030000,0xFB53D14A,0xA9C2F2C2,0xA0000000
                   5855:        long            0x40040000,0x83F2677A,0x65ECBF73,0xA1C40000
                   5856:        long            0x40040000,0x8A3AE64F,0x76F80584,0x21880000
                   5857:        long            0x40040000,0x90836524,0x88034B96,0xA0B00000
                   5858:        long            0x40040000,0x96CBE3F9,0x990E91A8,0xA1E00000
                   5859:        long            0x40040000,0x9D1462CE,0xAA19D7B9,0x21580000
                   5860:        long            0x40040000,0xA35CE1A3,0xBB251DCB,0xA1100000
                   5861:        long            0x40040000,0xA9A56078,0xCC3063DD,0xA1FC0000
                   5862:        long            0x40040000,0xAFEDDF4D,0xDD3BA9EE,0x21200000
                   5863:        long            0x40040000,0xB6365E22,0xEE46F000,0xA1480000
                   5864:        long            0x40040000,0xBC7EDCF7,0xFF523611,0x21E80000
                   5865:        long            0x40040000,0xC2C75BCD,0x105D7C23,0x20D00000
                   5866:        long            0x40040000,0xC90FDAA2,0x2168C235,0xA1800000
                   5867:
                   5868:        set             INARG,FP_SCR0
                   5869:
                   5870:        set             TWOTO63,L_SCR1
                   5871:        set             INT,L_SCR1
                   5872:        set             ENDFLAG,L_SCR2
                   5873:
                   5874:        global          stan
                   5875: stan:
                   5876:        fmov.x          (%a0),%fp0              # LOAD INPUT
                   5877:
                   5878:        mov.l           (%a0),%d1
                   5879:        mov.w           4(%a0),%d1
                   5880:        and.l           &0x7FFFFFFF,%d1
                   5881:
                   5882:        cmp.l           %d1,&0x3FD78000         # |X| >= 2**(-40)?
                   5883:        bge.b           TANOK1
                   5884:        bra.w           TANSM
                   5885: TANOK1:
                   5886:        cmp.l           %d1,&0x4004BC7E         # |X| < 15 PI?
                   5887:        blt.b           TANMAIN
                   5888:        bra.w           REDUCEX
                   5889:
                   5890: TANMAIN:
                   5891: #--THIS IS THE USUAL CASE, |X| <= 15 PI.
                   5892: #--THE ARGUMENT REDUCTION IS DONE BY TABLE LOOK UP.
                   5893:        fmov.x          %fp0,%fp1
                   5894:        fmul.d          TWOBYPI(%pc),%fp1       # X*2/PI
                   5895:
                   5896:        lea.l           PITBL+0x200(%pc),%a1    # TABLE OF N*PI/2, N = -32,...,32
                   5897:
                   5898:        fmov.l          %fp1,%d1                # CONVERT TO INTEGER
                   5899:
                   5900:        asl.l           &4,%d1
                   5901:        add.l           %d1,%a1                 # ADDRESS N*PIBY2 IN Y1, Y2
                   5902:
                   5903:        fsub.x          (%a1)+,%fp0             # X-Y1
                   5904:
                   5905:        fsub.s          (%a1),%fp0              # FP0 IS R = (X-Y1)-Y2
                   5906:
                   5907:        ror.l           &5,%d1
                   5908:        and.l           &0x80000000,%d1         # D0 WAS ODD IFF D0 < 0
                   5909:
                   5910: TANCONT:
                   5911:        fmovm.x         &0x0c,-(%sp)            # save fp2,fp3
                   5912:
                   5913:        cmp.l           %d1,&0
                   5914:        blt.w           NODD
                   5915:
                   5916:        fmov.x          %fp0,%fp1
                   5917:        fmul.x          %fp1,%fp1               # S = R*R
                   5918:
                   5919:        fmov.d          TANQ4(%pc),%fp3
                   5920:        fmov.d          TANP3(%pc),%fp2
                   5921:
                   5922:        fmul.x          %fp1,%fp3               # SQ4
                   5923:        fmul.x          %fp1,%fp2               # SP3
                   5924:
                   5925:        fadd.d          TANQ3(%pc),%fp3         # Q3+SQ4
                   5926:        fadd.x          TANP2(%pc),%fp2         # P2+SP3
                   5927:
                   5928:        fmul.x          %fp1,%fp3               # S(Q3+SQ4)
                   5929:        fmul.x          %fp1,%fp2               # S(P2+SP3)
                   5930:
                   5931:        fadd.x          TANQ2(%pc),%fp3         # Q2+S(Q3+SQ4)
                   5932:        fadd.x          TANP1(%pc),%fp2         # P1+S(P2+SP3)
                   5933:
                   5934:        fmul.x          %fp1,%fp3               # S(Q2+S(Q3+SQ4))
                   5935:        fmul.x          %fp1,%fp2               # S(P1+S(P2+SP3))
                   5936:
                   5937:        fadd.x          TANQ1(%pc),%fp3         # Q1+S(Q2+S(Q3+SQ4))
                   5938:        fmul.x          %fp0,%fp2               # RS(P1+S(P2+SP3))
                   5939:
                   5940:        fmul.x          %fp3,%fp1               # S(Q1+S(Q2+S(Q3+SQ4)))
                   5941:
                   5942:        fadd.x          %fp2,%fp0               # R+RS(P1+S(P2+SP3))
                   5943:
                   5944:        fadd.s          &0x3F800000,%fp1        # 1+S(Q1+...)
                   5945:
                   5946:        fmovm.x         (%sp)+,&0x30            # restore fp2,fp3
                   5947:
                   5948:        fmov.l          %d0,%fpcr               # restore users round mode,prec
                   5949:        fdiv.x          %fp1,%fp0               # last inst - possible exception set
                   5950:        bra             t_inx2
                   5951:
                   5952: NODD:
                   5953:        fmov.x          %fp0,%fp1
                   5954:        fmul.x          %fp0,%fp0               # S = R*R
                   5955:
                   5956:        fmov.d          TANQ4(%pc),%fp3
                   5957:        fmov.d          TANP3(%pc),%fp2
                   5958:
                   5959:        fmul.x          %fp0,%fp3               # SQ4
                   5960:        fmul.x          %fp0,%fp2               # SP3
                   5961:
                   5962:        fadd.d          TANQ3(%pc),%fp3         # Q3+SQ4
                   5963:        fadd.x          TANP2(%pc),%fp2         # P2+SP3
                   5964:
                   5965:        fmul.x          %fp0,%fp3               # S(Q3+SQ4)
                   5966:        fmul.x          %fp0,%fp2               # S(P2+SP3)
                   5967:
                   5968:        fadd.x          TANQ2(%pc),%fp3         # Q2+S(Q3+SQ4)
                   5969:        fadd.x          TANP1(%pc),%fp2         # P1+S(P2+SP3)
                   5970:
                   5971:        fmul.x          %fp0,%fp3               # S(Q2+S(Q3+SQ4))
                   5972:        fmul.x          %fp0,%fp2               # S(P1+S(P2+SP3))
                   5973:
                   5974:        fadd.x          TANQ1(%pc),%fp3         # Q1+S(Q2+S(Q3+SQ4))
                   5975:        fmul.x          %fp1,%fp2               # RS(P1+S(P2+SP3))
                   5976:
                   5977:        fmul.x          %fp3,%fp0               # S(Q1+S(Q2+S(Q3+SQ4)))
                   5978:
                   5979:        fadd.x          %fp2,%fp1               # R+RS(P1+S(P2+SP3))
                   5980:        fadd.s          &0x3F800000,%fp0        # 1+S(Q1+...)
                   5981:
                   5982:        fmovm.x         (%sp)+,&0x30            # restore fp2,fp3
                   5983:
                   5984:        fmov.x          %fp1,-(%sp)
                   5985:        eor.l           &0x80000000,(%sp)
                   5986:
                   5987:        fmov.l          %d0,%fpcr               # restore users round mode,prec
                   5988:        fdiv.x          (%sp)+,%fp0             # last inst - possible exception set
                   5989:        bra             t_inx2
                   5990:
                   5991: TANBORS:
                   5992: #--IF |X| > 15PI, WE USE THE GENERAL ARGUMENT REDUCTION.
                   5993: #--IF |X| < 2**(-40), RETURN X OR 1.
                   5994:        cmp.l           %d1,&0x3FFF8000
                   5995:        bgt.b           REDUCEX
                   5996:
                   5997: TANSM:
                   5998:        fmov.x          %fp0,-(%sp)
                   5999:        fmov.l          %d0,%fpcr               # restore users round mode,prec
                   6000:        mov.b           &FMOV_OP,%d1            # last inst is MOVE
                   6001:        fmov.x          (%sp)+,%fp0             # last inst - posibble exception set
                   6002:        bra             t_catch
                   6003:
                   6004:        global          stand
                   6005: #--TAN(X) = X FOR DENORMALIZED X
                   6006: stand:
                   6007:        bra             t_extdnrm
                   6008:
                   6009: #--WHEN REDUCEX IS USED, THE CODE WILL INEVITABLY BE SLOW.
                   6010: #--THIS REDUCTION METHOD, HOWEVER, IS MUCH FASTER THAN USING
                   6011: #--THE REMAINDER INSTRUCTION WHICH IS NOW IN SOFTWARE.
                   6012: REDUCEX:
                   6013:        fmovm.x         &0x3c,-(%sp)            # save {fp2-fp5}
                   6014:        mov.l           %d2,-(%sp)              # save d2
                   6015:        fmov.s          &0x00000000,%fp1        # fp1 = 0
                   6016:
                   6017: #--If compact form of abs(arg) in d0=$7ffeffff, argument is so large that
                   6018: #--there is a danger of unwanted overflow in first LOOP iteration.  In this
                   6019: #--case, reduce argument by one remainder step to make subsequent reduction
                   6020: #--safe.
                   6021:        cmp.l           %d1,&0x7ffeffff         # is arg dangerously large?
                   6022:        bne.b           LOOP                    # no
                   6023:
                   6024: # yes; create 2**16383*PI/2
                   6025:        mov.w           &0x7ffe,FP_SCR0_EX(%a6)
                   6026:        mov.l           &0xc90fdaa2,FP_SCR0_HI(%a6)
                   6027:        clr.l           FP_SCR0_LO(%a6)
                   6028:
                   6029: # create low half of 2**16383*PI/2 at FP_SCR1
                   6030:        mov.w           &0x7fdc,FP_SCR1_EX(%a6)
                   6031:        mov.l           &0x85a308d3,FP_SCR1_HI(%a6)
                   6032:        clr.l           FP_SCR1_LO(%a6)
                   6033:
                   6034:        ftest.x         %fp0                    # test sign of argument
                   6035:        fblt.w          red_neg
                   6036:
                   6037:        or.b            &0x80,FP_SCR0_EX(%a6)   # positive arg
                   6038:        or.b            &0x80,FP_SCR1_EX(%a6)
                   6039: red_neg:
                   6040:        fadd.x          FP_SCR0(%a6),%fp0       # high part of reduction is exact
                   6041:        fmov.x          %fp0,%fp1               # save high result in fp1
                   6042:        fadd.x          FP_SCR1(%a6),%fp0       # low part of reduction
                   6043:        fsub.x          %fp0,%fp1               # determine low component of result
                   6044:        fadd.x          FP_SCR1(%a6),%fp1       # fp0/fp1 are reduced argument.
                   6045:
                   6046: #--ON ENTRY, FP0 IS X, ON RETURN, FP0 IS X REM PI/2, |X| <= PI/4.
                   6047: #--integer quotient will be stored in N
                   6048: #--Intermeditate remainder is 66-bit long; (R,r) in (FP0,FP1)
                   6049: LOOP:
                   6050:        fmov.x          %fp0,INARG(%a6)         # +-2**K * F, 1 <= F < 2
                   6051:        mov.w           INARG(%a6),%d1
                   6052:        mov.l           %d1,%a1                 # save a copy of D0
                   6053:        and.l           &0x00007FFF,%d1
                   6054:        sub.l           &0x00003FFF,%d1         # d0 = K
                   6055:        cmp.l           %d1,&28
                   6056:        ble.b           LASTLOOP
                   6057: CONTLOOP:
                   6058:        sub.l           &27,%d1                 # d0 = L := K-27
                   6059:        mov.b           &0,ENDFLAG(%a6)
                   6060:        bra.b           WORK
                   6061: LASTLOOP:
                   6062:        clr.l           %d1                     # d0 = L := 0
                   6063:        mov.b           &1,ENDFLAG(%a6)
                   6064:
                   6065: WORK:
                   6066: #--FIND THE REMAINDER OF (R,r) W.R.T.  2**L * (PI/2). L IS SO CHOSEN
                   6067: #--THAT        INT( X * (2/PI) / 2**(L) ) < 2**29.
                   6068:
                   6069: #--CREATE 2**(-L) * (2/PI), SIGN(INARG)*2**(63),
                   6070: #--2**L * (PIby2_1), 2**L * (PIby2_2)
                   6071:
                   6072:        mov.l           &0x00003FFE,%d2         # BIASED EXP OF 2/PI
                   6073:        sub.l           %d1,%d2                 # BIASED EXP OF 2**(-L)*(2/PI)
                   6074:
                   6075:        mov.l           &0xA2F9836E,FP_SCR0_HI(%a6)
                   6076:        mov.l           &0x4E44152A,FP_SCR0_LO(%a6)
                   6077:        mov.w           %d2,FP_SCR0_EX(%a6)     # FP_SCR0 = 2**(-L)*(2/PI)
                   6078:
                   6079:        fmov.x          %fp0,%fp2
                   6080:        fmul.x          FP_SCR0(%a6),%fp2       # fp2 = X * 2**(-L)*(2/PI)
                   6081:
                   6082: #--WE MUST NOW FIND INT(FP2). SINCE WE NEED THIS VALUE IN
                   6083: #--FLOATING POINT FORMAT, THE TWO FMOVE'S      FMOVE.L FP <--> N
                   6084: #--WILL BE TOO INEFFICIENT. THE WAY AROUND IT IS THAT
                   6085: #--(SIGN(INARG)*2**63  +       FP2) - SIGN(INARG)*2**63 WILL GIVE
                   6086: #--US THE DESIRED VALUE IN FLOATING POINT.
                   6087:        mov.l           %a1,%d2
                   6088:        swap            %d2
                   6089:        and.l           &0x80000000,%d2
                   6090:        or.l            &0x5F000000,%d2         # d2 = SIGN(INARG)*2**63 IN SGL
                   6091:        mov.l           %d2,TWOTO63(%a6)
                   6092:        fadd.s          TWOTO63(%a6),%fp2       # THE FRACTIONAL PART OF FP1 IS ROUNDED
                   6093:        fsub.s          TWOTO63(%a6),%fp2       # fp2 = N
                   6094: #      fintrz.x        %fp2,%fp2
                   6095:
                   6096: #--CREATING 2**(L)*Piby2_1 and 2**(L)*Piby2_2
                   6097:        mov.l           %d1,%d2                 # d2 = L
                   6098:
                   6099:        add.l           &0x00003FFF,%d2         # BIASED EXP OF 2**L * (PI/2)
                   6100:        mov.w           %d2,FP_SCR0_EX(%a6)
                   6101:        mov.l           &0xC90FDAA2,FP_SCR0_HI(%a6)
                   6102:        clr.l           FP_SCR0_LO(%a6)         # FP_SCR0 = 2**(L) * Piby2_1
                   6103:
                   6104:        add.l           &0x00003FDD,%d1
                   6105:        mov.w           %d1,FP_SCR1_EX(%a6)
                   6106:        mov.l           &0x85A308D3,FP_SCR1_HI(%a6)
                   6107:        clr.l           FP_SCR1_LO(%a6)         # FP_SCR1 = 2**(L) * Piby2_2
                   6108:
                   6109:        mov.b           ENDFLAG(%a6),%d1
                   6110:
                   6111: #--We are now ready to perform (R+r) - N*P1 - N*P2, P1 = 2**(L) * Piby2_1 and
                   6112: #--P2 = 2**(L) * Piby2_2
                   6113:        fmov.x          %fp2,%fp4               # fp4 = N
                   6114:        fmul.x          FP_SCR0(%a6),%fp4       # fp4 = W = N*P1
                   6115:        fmov.x          %fp2,%fp5               # fp5 = N
                   6116:        fmul.x          FP_SCR1(%a6),%fp5       # fp5 = w = N*P2
                   6117:        fmov.x          %fp4,%fp3               # fp3 = W = N*P1
                   6118:
                   6119: #--we want P+p = W+w  but  |p| <= half ulp of P
                   6120: #--Then, we need to compute  A := R-P   and  a := r-p
                   6121:        fadd.x          %fp5,%fp3               # fp3 = P
                   6122:        fsub.x          %fp3,%fp4               # fp4 = W-P
                   6123:
                   6124:        fsub.x          %fp3,%fp0               # fp0 = A := R - P
                   6125:        fadd.x          %fp5,%fp4               # fp4 = p = (W-P)+w
                   6126:
                   6127:        fmov.x          %fp0,%fp3               # fp3 = A
                   6128:        fsub.x          %fp4,%fp1               # fp1 = a := r - p
                   6129:
                   6130: #--Now we need to normalize (A,a) to  "new (R,r)" where R+r = A+a but
                   6131: #--|r| <= half ulp of R.
                   6132:        fadd.x          %fp1,%fp0               # fp0 = R := A+a
                   6133: #--No need to calculate r if this is the last loop
                   6134:        cmp.b           %d1,&0
                   6135:        bgt.w           RESTORE
                   6136:
                   6137: #--Need to calculate r
                   6138:        fsub.x          %fp0,%fp3               # fp3 = A-R
                   6139:        fadd.x          %fp3,%fp1               # fp1 = r := (A-R)+a
                   6140:        bra.w           LOOP
                   6141:
                   6142: RESTORE:
                   6143:        fmov.l          %fp2,INT(%a6)
                   6144:        mov.l           (%sp)+,%d2              # restore d2
                   6145:        fmovm.x         (%sp)+,&0x3c            # restore {fp2-fp5}
                   6146:
                   6147:        mov.l           INT(%a6),%d1
                   6148:        ror.l           &1,%d1
                   6149:
                   6150:        bra.w           TANCONT
                   6151:
                   6152: #########################################################################
                   6153: # satan():  computes the arctangent of a normalized number             #
                   6154: # satand(): computes the arctangent of a denormalized number           #
                   6155: #                                                                      #
                   6156: # INPUT        *************************************************************** #
                   6157: #      a0 = pointer to extended precision input                        #
                   6158: #      d0 = round precision,mode                                       #
                   6159: #                                                                      #
                   6160: # OUTPUT ************************************************************** #
                   6161: #      fp0 = arctan(X)                                                 #
                   6162: #                                                                      #
                   6163: # ACCURACY and MONOTONICITY ******************************************* #
                   6164: #      The returned result is within 2 ulps in 64 significant bit,     #
                   6165: #      i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
                   6166: #      rounded to double precision. The result is provably monotonic   #
                   6167: #      in double precision.                                            #
                   6168: #                                                                      #
                   6169: # ALGORITHM *********************************************************** #
                   6170: #      Step 1. If |X| >= 16 or |X| < 1/16, go to Step 5.               #
                   6171: #                                                                      #
                   6172: #      Step 2. Let X = sgn * 2**k * 1.xxxxxxxx...x.                    #
                   6173: #              Note that k = -4, -3,..., or 3.                         #
                   6174: #              Define F = sgn * 2**k * 1.xxxx1, i.e. the first 5       #
                   6175: #              significant bits of X with a bit-1 attached at the 6-th #
                   6176: #              bit position. Define u to be u = (X-F) / (1 + X*F).     #
                   6177: #                                                                      #
                   6178: #      Step 3. Approximate arctan(u) by a polynomial poly.             #
                   6179: #                                                                      #
                   6180: #      Step 4. Return arctan(F) + poly, arctan(F) is fetched from a    #
                   6181: #              table of values calculated beforehand. Exit.            #
                   6182: #                                                                      #
                   6183: #      Step 5. If |X| >= 16, go to Step 7.                             #
                   6184: #                                                                      #
                   6185: #      Step 6. Approximate arctan(X) by an odd polynomial in X. Exit.  #
                   6186: #                                                                      #
                   6187: #      Step 7. Define X' = -1/X. Approximate arctan(X') by an odd      #
                   6188: #              polynomial in X'.                                       #
                   6189: #              Arctan(X) = sign(X)*Pi/2 + arctan(X'). Exit.            #
                   6190: #                                                                      #
                   6191: #########################################################################
                   6192:
                   6193: ATANA3:        long            0xBFF6687E,0x314987D8
                   6194: ATANA2:        long            0x4002AC69,0x34A26DB3
                   6195: ATANA1:        long            0xBFC2476F,0x4E1DA28E
                   6196:
                   6197: ATANB6:        long            0x3FB34444,0x7F876989
                   6198: ATANB5:        long            0xBFB744EE,0x7FAF45DB
                   6199: ATANB4:        long            0x3FBC71C6,0x46940220
                   6200: ATANB3:        long            0xBFC24924,0x921872F9
                   6201: ATANB2:        long            0x3FC99999,0x99998FA9
                   6202: ATANB1:        long            0xBFD55555,0x55555555
                   6203:
                   6204: ATANC5:        long            0xBFB70BF3,0x98539E6A
                   6205: ATANC4:        long            0x3FBC7187,0x962D1D7D
                   6206: ATANC3:        long            0xBFC24924,0x827107B8
                   6207: ATANC2:        long            0x3FC99999,0x9996263E
                   6208: ATANC1:        long            0xBFD55555,0x55555536
                   6209:
                   6210: PPIBY2:        long            0x3FFF0000,0xC90FDAA2,0x2168C235,0x00000000
                   6211: NPIBY2:        long            0xBFFF0000,0xC90FDAA2,0x2168C235,0x00000000
                   6212:
                   6213: PTINY: long            0x00010000,0x80000000,0x00000000,0x00000000
                   6214: NTINY: long            0x80010000,0x80000000,0x00000000,0x00000000
                   6215:
                   6216: ATANTBL:
                   6217:        long            0x3FFB0000,0x83D152C5,0x060B7A51,0x00000000
                   6218:        long            0x3FFB0000,0x8BC85445,0x65498B8B,0x00000000
                   6219:        long            0x3FFB0000,0x93BE4060,0x17626B0D,0x00000000
                   6220:        long            0x3FFB0000,0x9BB3078D,0x35AEC202,0x00000000
                   6221:        long            0x3FFB0000,0xA3A69A52,0x5DDCE7DE,0x00000000
                   6222:        long            0x3FFB0000,0xAB98E943,0x62765619,0x00000000
                   6223:        long            0x3FFB0000,0xB389E502,0xF9C59862,0x00000000
                   6224:        long            0x3FFB0000,0xBB797E43,0x6B09E6FB,0x00000000
                   6225:        long            0x3FFB0000,0xC367A5C7,0x39E5F446,0x00000000
                   6226:        long            0x3FFB0000,0xCB544C61,0xCFF7D5C6,0x00000000
                   6227:        long            0x3FFB0000,0xD33F62F8,0x2488533E,0x00000000
                   6228:        long            0x3FFB0000,0xDB28DA81,0x62404C77,0x00000000
                   6229:        long            0x3FFB0000,0xE310A407,0x8AD34F18,0x00000000
                   6230:        long            0x3FFB0000,0xEAF6B0A8,0x188EE1EB,0x00000000
                   6231:        long            0x3FFB0000,0xF2DAF194,0x9DBE79D5,0x00000000
                   6232:        long            0x3FFB0000,0xFABD5813,0x61D47E3E,0x00000000
                   6233:        long            0x3FFC0000,0x8346AC21,0x0959ECC4,0x00000000
                   6234:        long            0x3FFC0000,0x8B232A08,0x304282D8,0x00000000
                   6235:        long            0x3FFC0000,0x92FB70B8,0xD29AE2F9,0x00000000
                   6236:        long            0x3FFC0000,0x9ACF476F,0x5CCD1CB4,0x00000000
                   6237:        long            0x3FFC0000,0xA29E7630,0x4954F23F,0x00000000
                   6238:        long            0x3FFC0000,0xAA68C5D0,0x8AB85230,0x00000000
                   6239:        long            0x3FFC0000,0xB22DFFFD,0x9D539F83,0x00000000
                   6240:        long            0x3FFC0000,0xB9EDEF45,0x3E900EA5,0x00000000
                   6241:        long            0x3FFC0000,0xC1A85F1C,0xC75E3EA5,0x00000000
                   6242:        long            0x3FFC0000,0xC95D1BE8,0x28138DE6,0x00000000
                   6243:        long            0x3FFC0000,0xD10BF300,0x840D2DE4,0x00000000
                   6244:        long            0x3FFC0000,0xD8B4B2BA,0x6BC05E7A,0x00000000
                   6245:        long            0x3FFC0000,0xE0572A6B,0xB42335F6,0x00000000
                   6246:        long            0x3FFC0000,0xE7F32A70,0xEA9CAA8F,0x00000000
                   6247:        long            0x3FFC0000,0xEF888432,0x64ECEFAA,0x00000000
                   6248:        long            0x3FFC0000,0xF7170A28,0xECC06666,0x00000000
                   6249:        long            0x3FFD0000,0x812FD288,0x332DAD32,0x00000000
                   6250:        long            0x3FFD0000,0x88A8D1B1,0x218E4D64,0x00000000
                   6251:        long            0x3FFD0000,0x9012AB3F,0x23E4AEE8,0x00000000
                   6252:        long            0x3FFD0000,0x976CC3D4,0x11E7F1B9,0x00000000
                   6253:        long            0x3FFD0000,0x9EB68949,0x3889A227,0x00000000
                   6254:        long            0x3FFD0000,0xA5EF72C3,0x4487361B,0x00000000
                   6255:        long            0x3FFD0000,0xAD1700BA,0xF07A7227,0x00000000
                   6256:        long            0x3FFD0000,0xB42CBCFA,0xFD37EFB7,0x00000000
                   6257:        long            0x3FFD0000,0xBB303A94,0x0BA80F89,0x00000000
                   6258:        long            0x3FFD0000,0xC22115C6,0xFCAEBBAF,0x00000000
                   6259:        long            0x3FFD0000,0xC8FEF3E6,0x86331221,0x00000000
                   6260:        long            0x3FFD0000,0xCFC98330,0xB4000C70,0x00000000
                   6261:        long            0x3FFD0000,0xD6807AA1,0x102C5BF9,0x00000000
                   6262:        long            0x3FFD0000,0xDD2399BC,0x31252AA3,0x00000000
                   6263:        long            0x3FFD0000,0xE3B2A855,0x6B8FC517,0x00000000
                   6264:        long            0x3FFD0000,0xEA2D764F,0x64315989,0x00000000
                   6265:        long            0x3FFD0000,0xF3BF5BF8,0xBAD1A21D,0x00000000
                   6266:        long            0x3FFE0000,0x801CE39E,0x0D205C9A,0x00000000
                   6267:        long            0x3FFE0000,0x8630A2DA,0xDA1ED066,0x00000000
                   6268:        long            0x3FFE0000,0x8C1AD445,0xF3E09B8C,0x00000000
                   6269:        long            0x3FFE0000,0x91DB8F16,0x64F350E2,0x00000000
                   6270:        long            0x3FFE0000,0x97731420,0x365E538C,0x00000000
                   6271:        long            0x3FFE0000,0x9CE1C8E6,0xA0B8CDBA,0x00000000
                   6272:        long            0x3FFE0000,0xA22832DB,0xCADAAE09,0x00000000
                   6273:        long            0x3FFE0000,0xA746F2DD,0xB7602294,0x00000000
                   6274:        long            0x3FFE0000,0xAC3EC0FB,0x997DD6A2,0x00000000
                   6275:        long            0x3FFE0000,0xB110688A,0xEBDC6F6A,0x00000000
                   6276:        long            0x3FFE0000,0xB5BCC490,0x59ECC4B0,0x00000000
                   6277:        long            0x3FFE0000,0xBA44BC7D,0xD470782F,0x00000000
                   6278:        long            0x3FFE0000,0xBEA94144,0xFD049AAC,0x00000000
                   6279:        long            0x3FFE0000,0xC2EB4ABB,0x661628B6,0x00000000
                   6280:        long            0x3FFE0000,0xC70BD54C,0xE602EE14,0x00000000
                   6281:        long            0x3FFE0000,0xCD000549,0xADEC7159,0x00000000
                   6282:        long            0x3FFE0000,0xD48457D2,0xD8EA4EA3,0x00000000
                   6283:        long            0x3FFE0000,0xDB948DA7,0x12DECE3B,0x00000000
                   6284:        long            0x3FFE0000,0xE23855F9,0x69E8096A,0x00000000
                   6285:        long            0x3FFE0000,0xE8771129,0xC4353259,0x00000000
                   6286:        long            0x3FFE0000,0xEE57C16E,0x0D379C0D,0x00000000
                   6287:        long            0x3FFE0000,0xF3E10211,0xA87C3779,0x00000000
                   6288:        long            0x3FFE0000,0xF919039D,0x758B8D41,0x00000000
                   6289:        long            0x3FFE0000,0xFE058B8F,0x64935FB3,0x00000000
                   6290:        long            0x3FFF0000,0x8155FB49,0x7B685D04,0x00000000
                   6291:        long            0x3FFF0000,0x83889E35,0x49D108E1,0x00000000
                   6292:        long            0x3FFF0000,0x859CFA76,0x511D724B,0x00000000
                   6293:        long            0x3FFF0000,0x87952ECF,0xFF8131E7,0x00000000
                   6294:        long            0x3FFF0000,0x89732FD1,0x9557641B,0x00000000
                   6295:        long            0x3FFF0000,0x8B38CAD1,0x01932A35,0x00000000
                   6296:        long            0x3FFF0000,0x8CE7A8D8,0x301EE6B5,0x00000000
                   6297:        long            0x3FFF0000,0x8F46A39E,0x2EAE5281,0x00000000
                   6298:        long            0x3FFF0000,0x922DA7D7,0x91888487,0x00000000
                   6299:        long            0x3FFF0000,0x94D19FCB,0xDEDF5241,0x00000000
                   6300:        long            0x3FFF0000,0x973AB944,0x19D2A08B,0x00000000
                   6301:        long            0x3FFF0000,0x996FF00E,0x08E10B96,0x00000000
                   6302:        long            0x3FFF0000,0x9B773F95,0x12321DA7,0x00000000
                   6303:        long            0x3FFF0000,0x9D55CC32,0x0F935624,0x00000000
                   6304:        long            0x3FFF0000,0x9F100575,0x006CC571,0x00000000
                   6305:        long            0x3FFF0000,0xA0A9C290,0xD97CC06C,0x00000000
                   6306:        long            0x3FFF0000,0xA22659EB,0xEBC0630A,0x00000000
                   6307:        long            0x3FFF0000,0xA388B4AF,0xF6EF0EC9,0x00000000
                   6308:        long            0x3FFF0000,0xA4D35F10,0x61D292C4,0x00000000
                   6309:        long            0x3FFF0000,0xA60895DC,0xFBE3187E,0x00000000
                   6310:        long            0x3FFF0000,0xA72A51DC,0x7367BEAC,0x00000000
                   6311:        long            0x3FFF0000,0xA83A5153,0x0956168F,0x00000000
                   6312:        long            0x3FFF0000,0xA93A2007,0x7539546E,0x00000000
                   6313:        long            0x3FFF0000,0xAA9E7245,0x023B2605,0x00000000
                   6314:        long            0x3FFF0000,0xAC4C84BA,0x6FE4D58F,0x00000000
                   6315:        long            0x3FFF0000,0xADCE4A4A,0x606B9712,0x00000000
                   6316:        long            0x3FFF0000,0xAF2A2DCD,0x8D263C9C,0x00000000
                   6317:        long            0x3FFF0000,0xB0656F81,0xF22265C7,0x00000000
                   6318:        long            0x3FFF0000,0xB1846515,0x0F71496A,0x00000000
                   6319:        long            0x3FFF0000,0xB28AAA15,0x6F9ADA35,0x00000000
                   6320:        long            0x3FFF0000,0xB37B44FF,0x3766B895,0x00000000
                   6321:        long            0x3FFF0000,0xB458C3DC,0xE9630433,0x00000000
                   6322:        long            0x3FFF0000,0xB525529D,0x562246BD,0x00000000
                   6323:        long            0x3FFF0000,0xB5E2CCA9,0x5F9D88CC,0x00000000
                   6324:        long            0x3FFF0000,0xB692CADA,0x7ACA1ADA,0x00000000
                   6325:        long            0x3FFF0000,0xB736AEA7,0xA6925838,0x00000000
                   6326:        long            0x3FFF0000,0xB7CFAB28,0x7E9F7B36,0x00000000
                   6327:        long            0x3FFF0000,0xB85ECC66,0xCB219835,0x00000000
                   6328:        long            0x3FFF0000,0xB8E4FD5A,0x20A593DA,0x00000000
                   6329:        long            0x3FFF0000,0xB99F41F6,0x4AFF9BB5,0x00000000
                   6330:        long            0x3FFF0000,0xBA7F1E17,0x842BBE7B,0x00000000
                   6331:        long            0x3FFF0000,0xBB471285,0x7637E17D,0x00000000
                   6332:        long            0x3FFF0000,0xBBFABE8A,0x4788DF6F,0x00000000
                   6333:        long            0x3FFF0000,0xBC9D0FAD,0x2B689D79,0x00000000
                   6334:        long            0x3FFF0000,0xBD306A39,0x471ECD86,0x00000000
                   6335:        long            0x3FFF0000,0xBDB6C731,0x856AF18A,0x00000000
                   6336:        long            0x3FFF0000,0xBE31CAC5,0x02E80D70,0x00000000
                   6337:        long            0x3FFF0000,0xBEA2D55C,0xE33194E2,0x00000000
                   6338:        long            0x3FFF0000,0xBF0B10B7,0xC03128F0,0x00000000
                   6339:        long            0x3FFF0000,0xBF6B7A18,0xDACB778D,0x00000000
                   6340:        long            0x3FFF0000,0xBFC4EA46,0x63FA18F6,0x00000000
                   6341:        long            0x3FFF0000,0xC0181BDE,0x8B89A454,0x00000000
                   6342:        long            0x3FFF0000,0xC065B066,0xCFBF6439,0x00000000
                   6343:        long            0x3FFF0000,0xC0AE345F,0x56340AE6,0x00000000
                   6344:        long            0x3FFF0000,0xC0F22291,0x9CB9E6A7,0x00000000
                   6345:
                   6346:        set             X,FP_SCR0
                   6347:        set             XDCARE,X+2
                   6348:        set             XFRAC,X+4
                   6349:        set             XFRACLO,X+8
                   6350:
                   6351:        set             ATANF,FP_SCR1
                   6352:        set             ATANFHI,ATANF+4
                   6353:        set             ATANFLO,ATANF+8
                   6354:
                   6355:        global          satan
                   6356: #--ENTRY POINT FOR ATAN(X), HERE X IS FINITE, NON-ZERO, AND NOT NAN'S
                   6357: satan:
                   6358:        fmov.x          (%a0),%fp0              # LOAD INPUT
                   6359:
                   6360:        mov.l           (%a0),%d1
                   6361:        mov.w           4(%a0),%d1
                   6362:        fmov.x          %fp0,X(%a6)
                   6363:        and.l           &0x7FFFFFFF,%d1
                   6364:
                   6365:        cmp.l           %d1,&0x3FFB8000         # |X| >= 1/16?
                   6366:        bge.b           ATANOK1
                   6367:        bra.w           ATANSM
                   6368:
                   6369: ATANOK1:
                   6370:        cmp.l           %d1,&0x4002FFFF         # |X| < 16 ?
                   6371:        ble.b           ATANMAIN
                   6372:        bra.w           ATANBIG
                   6373:
                   6374: #--THE MOST LIKELY CASE, |X| IN [1/16, 16). WE USE TABLE TECHNIQUE
                   6375: #--THE IDEA IS ATAN(X) = ATAN(F) + ATAN( [X-F] / [1+XF] ).
                   6376: #--SO IF F IS CHOSEN TO BE CLOSE TO X AND ATAN(F) IS STORED IN
                   6377: #--A TABLE, ALL WE NEED IS TO APPROXIMATE ATAN(U) WHERE
                   6378: #--U = (X-F)/(1+XF) IS SMALL (REMEMBER F IS CLOSE TO X). IT IS
                   6379: #--TRUE THAT A DIVIDE IS NOW NEEDED, BUT THE APPROXIMATION FOR
                   6380: #--ATAN(U) IS A VERY SHORT POLYNOMIAL AND THE INDEXING TO
                   6381: #--FETCH F AND SAVING OF REGISTERS CAN BE ALL HIDED UNDER THE
                   6382: #--DIVIDE. IN THE END THIS METHOD IS MUCH FASTER THAN A TRADITIONAL
                   6383: #--ONE. NOTE ALSO THAT THE TRADITIONAL SCHEME THAT APPROXIMATE
                   6384: #--ATAN(X) DIRECTLY WILL NEED TO USE A RATIONAL APPROXIMATION
                   6385: #--(DIVISION NEEDED) ANYWAY BECAUSE A POLYNOMIAL APPROXIMATION
                   6386: #--WILL INVOLVE A VERY LONG POLYNOMIAL.
                   6387:
                   6388: #--NOW WE SEE X AS +-2^K * 1.BBBBBBB....B <- 1. + 63 BITS
                   6389: #--WE CHOSE F TO BE +-2^K * 1.BBBB1
                   6390: #--THAT IS IT MATCHES THE EXPONENT AND FIRST 5 BITS OF X, THE
                   6391: #--SIXTH BITS IS SET TO BE 1. SINCE K = -4, -3, ..., 3, THERE
                   6392: #--ARE ONLY 8 TIMES 16 = 2^7 = 128 |F|'S. SINCE ATAN(-|F|) IS
                   6393: #-- -ATAN(|F|), WE NEED TO STORE ONLY ATAN(|F|).
                   6394:
                   6395: ATANMAIN:
                   6396:
                   6397:        and.l           &0xF8000000,XFRAC(%a6)  # FIRST 5 BITS
                   6398:        or.l            &0x04000000,XFRAC(%a6)  # SET 6-TH BIT TO 1
                   6399:        mov.l           &0x00000000,XFRACLO(%a6) # LOCATION OF X IS NOW F
                   6400:
                   6401:        fmov.x          %fp0,%fp1               # FP1 IS X
                   6402:        fmul.x          X(%a6),%fp1             # FP1 IS X*F, NOTE THAT X*F > 0
                   6403:        fsub.x          X(%a6),%fp0             # FP0 IS X-F
                   6404:        fadd.s          &0x3F800000,%fp1        # FP1 IS 1 + X*F
                   6405:        fdiv.x          %fp1,%fp0               # FP0 IS U = (X-F)/(1+X*F)
                   6406:
                   6407: #--WHILE THE DIVISION IS TAKING ITS TIME, WE FETCH ATAN(|F|)
                   6408: #--CREATE ATAN(F) AND STORE IT IN ATANF, AND
                   6409: #--SAVE REGISTERS FP2.
                   6410:
                   6411:        mov.l           %d2,-(%sp)              # SAVE d2 TEMPORARILY
                   6412:        mov.l           %d1,%d2                 # THE EXP AND 16 BITS OF X
                   6413:        and.l           &0x00007800,%d1         # 4 VARYING BITS OF F'S FRACTION
                   6414:        and.l           &0x7FFF0000,%d2         # EXPONENT OF F
                   6415:        sub.l           &0x3FFB0000,%d2         # K+4
                   6416:        asr.l           &1,%d2
                   6417:        add.l           %d2,%d1                 # THE 7 BITS IDENTIFYING F
                   6418:        asr.l           &7,%d1                  # INDEX INTO TBL OF ATAN(|F|)
                   6419:        lea             ATANTBL(%pc),%a1
                   6420:        add.l           %d1,%a1                 # ADDRESS OF ATAN(|F|)
                   6421:        mov.l           (%a1)+,ATANF(%a6)
                   6422:        mov.l           (%a1)+,ATANFHI(%a6)
                   6423:        mov.l           (%a1)+,ATANFLO(%a6)     # ATANF IS NOW ATAN(|F|)
                   6424:        mov.l           X(%a6),%d1              # LOAD SIGN AND EXPO. AGAIN
                   6425:        and.l           &0x80000000,%d1         # SIGN(F)
                   6426:        or.l            %d1,ATANF(%a6)          # ATANF IS NOW SIGN(F)*ATAN(|F|)
                   6427:        mov.l           (%sp)+,%d2              # RESTORE d2
                   6428:
                   6429: #--THAT'S ALL I HAVE TO DO FOR NOW,
                   6430: #--BUT ALAS, THE DIVIDE IS STILL CRANKING!
                   6431:
                   6432: #--U IN FP0, WE ARE NOW READY TO COMPUTE ATAN(U) AS
                   6433: #--U + A1*U*V*(A2 + V*(A3 + V)), V = U*U
                   6434: #--THE POLYNOMIAL MAY LOOK STRANGE, BUT IS NEVERTHELESS CORRECT.
                   6435: #--THE NATURAL FORM IS U + U*V*(A1 + V*(A2 + V*A3))
                   6436: #--WHAT WE HAVE HERE IS MERELY A1 = A3, A2 = A1/A3, A3 = A2/A3.
                   6437: #--THE REASON FOR THIS REARRANGEMENT IS TO MAKE THE INDEPENDENT
                   6438: #--PARTS A1*U*V AND (A2 + ... STUFF) MORE LOAD-BALANCED
                   6439:
                   6440:        fmovm.x         &0x04,-(%sp)            # save fp2
                   6441:
                   6442:        fmov.x          %fp0,%fp1
                   6443:        fmul.x          %fp1,%fp1
                   6444:        fmov.d          ATANA3(%pc),%fp2
                   6445:        fadd.x          %fp1,%fp2               # A3+V
                   6446:        fmul.x          %fp1,%fp2               # V*(A3+V)
                   6447:        fmul.x          %fp0,%fp1               # U*V
                   6448:        fadd.d          ATANA2(%pc),%fp2        # A2+V*(A3+V)
                   6449:        fmul.d          ATANA1(%pc),%fp1        # A1*U*V
                   6450:        fmul.x          %fp2,%fp1               # A1*U*V*(A2+V*(A3+V))
                   6451:        fadd.x          %fp1,%fp0               # ATAN(U), FP1 RELEASED
                   6452:
                   6453:        fmovm.x         (%sp)+,&0x20            # restore fp2
                   6454:
                   6455:        fmov.l          %d0,%fpcr               # restore users rnd mode,prec
                   6456:        fadd.x          ATANF(%a6),%fp0         # ATAN(X)
                   6457:        bra             t_inx2
                   6458:
                   6459: ATANBORS:
                   6460: #--|X| IS IN d0 IN COMPACT FORM. FP1, d0 SAVED.
                   6461: #--FP0 IS X AND |X| <= 1/16 OR |X| >= 16.
                   6462:        cmp.l           %d1,&0x3FFF8000
                   6463:        bgt.w           ATANBIG                 # I.E. |X| >= 16
                   6464:
                   6465: ATANSM:
                   6466: #--|X| <= 1/16
                   6467: #--IF |X| < 2^(-40), RETURN X AS ANSWER. OTHERWISE, APPROXIMATE
                   6468: #--ATAN(X) BY X + X*Y*(B1+Y*(B2+Y*(B3+Y*(B4+Y*(B5+Y*B6)))))
                   6469: #--WHICH IS X + X*Y*( [B1+Z*(B3+Z*B5)] + [Y*(B2+Z*(B4+Z*B6)] )
                   6470: #--WHERE Y = X*X, AND Z = Y*Y.
                   6471:
                   6472:        cmp.l           %d1,&0x3FD78000
                   6473:        blt.w           ATANTINY
                   6474:
                   6475: #--COMPUTE POLYNOMIAL
                   6476:        fmovm.x         &0x0c,-(%sp)            # save fp2/fp3
                   6477:
                   6478:        fmul.x          %fp0,%fp0               # FPO IS Y = X*X
                   6479:
                   6480:        fmov.x          %fp0,%fp1
                   6481:        fmul.x          %fp1,%fp1               # FP1 IS Z = Y*Y
                   6482:
                   6483:        fmov.d          ATANB6(%pc),%fp2
                   6484:        fmov.d          ATANB5(%pc),%fp3
                   6485:
                   6486:        fmul.x          %fp1,%fp2               # Z*B6
                   6487:        fmul.x          %fp1,%fp3               # Z*B5
                   6488:
                   6489:        fadd.d          ATANB4(%pc),%fp2        # B4+Z*B6
                   6490:        fadd.d          ATANB3(%pc),%fp3        # B3+Z*B5
                   6491:
                   6492:        fmul.x          %fp1,%fp2               # Z*(B4+Z*B6)
                   6493:        fmul.x          %fp3,%fp1               # Z*(B3+Z*B5)
                   6494:
                   6495:        fadd.d          ATANB2(%pc),%fp2        # B2+Z*(B4+Z*B6)
                   6496:        fadd.d          ATANB1(%pc),%fp1        # B1+Z*(B3+Z*B5)
                   6497:
                   6498:        fmul.x          %fp0,%fp2               # Y*(B2+Z*(B4+Z*B6))
                   6499:        fmul.x          X(%a6),%fp0             # X*Y
                   6500:
                   6501:        fadd.x          %fp2,%fp1               # [B1+Z*(B3+Z*B5)]+[Y*(B2+Z*(B4+Z*B6))]
                   6502:
                   6503:        fmul.x          %fp1,%fp0               # X*Y*([B1+Z*(B3+Z*B5)]+[Y*(B2+Z*(B4+Z*B6))])
                   6504:
                   6505:        fmovm.x         (%sp)+,&0x30            # restore fp2/fp3
                   6506:
                   6507:        fmov.l          %d0,%fpcr               # restore users rnd mode,prec
                   6508:        fadd.x          X(%a6),%fp0
                   6509:        bra             t_inx2
                   6510:
                   6511: ATANTINY:
                   6512: #--|X| < 2^(-40), ATAN(X) = X
                   6513:
                   6514:        fmov.l          %d0,%fpcr               # restore users rnd mode,prec
                   6515:        mov.b           &FMOV_OP,%d1            # last inst is MOVE
                   6516:        fmov.x          X(%a6),%fp0             # last inst - possible exception set
                   6517:
                   6518:        bra             t_catch
                   6519:
                   6520: ATANBIG:
                   6521: #--IF |X| > 2^(100), RETURN    SIGN(X)*(PI/2 - TINY). OTHERWISE,
                   6522: #--RETURN SIGN(X)*PI/2 + ATAN(-1/X).
                   6523:        cmp.l           %d1,&0x40638000
                   6524:        bgt.w           ATANHUGE
                   6525:
                   6526: #--APPROXIMATE ATAN(-1/X) BY
                   6527: #--X'+X'*Y*(C1+Y*(C2+Y*(C3+Y*(C4+Y*C5)))), X' = -1/X, Y = X'*X'
                   6528: #--THIS CAN BE RE-WRITTEN AS
                   6529: #--X'+X'*Y*( [C1+Z*(C3+Z*C5)] + [Y*(C2+Z*C4)] ), Z = Y*Y.
                   6530:
                   6531:        fmovm.x         &0x0c,-(%sp)            # save fp2/fp3
                   6532:
                   6533:        fmov.s          &0xBF800000,%fp1        # LOAD -1
                   6534:        fdiv.x          %fp0,%fp1               # FP1 IS -1/X
                   6535:
                   6536: #--DIVIDE IS STILL CRANKING
                   6537:
                   6538:        fmov.x          %fp1,%fp0               # FP0 IS X'
                   6539:        fmul.x          %fp0,%fp0               # FP0 IS Y = X'*X'
                   6540:        fmov.x          %fp1,X(%a6)             # X IS REALLY X'
                   6541:
                   6542:        fmov.x          %fp0,%fp1
                   6543:        fmul.x          %fp1,%fp1               # FP1 IS Z = Y*Y
                   6544:
                   6545:        fmov.d          ATANC5(%pc),%fp3
                   6546:        fmov.d          ATANC4(%pc),%fp2
                   6547:
                   6548:        fmul.x          %fp1,%fp3               # Z*C5
                   6549:        fmul.x          %fp1,%fp2               # Z*B4
                   6550:
                   6551:        fadd.d          ATANC3(%pc),%fp3        # C3+Z*C5
                   6552:        fadd.d          ATANC2(%pc),%fp2        # C2+Z*C4
                   6553:
                   6554:        fmul.x          %fp3,%fp1               # Z*(C3+Z*C5), FP3 RELEASED
                   6555:        fmul.x          %fp0,%fp2               # Y*(C2+Z*C4)
                   6556:
                   6557:        fadd.d          ATANC1(%pc),%fp1        # C1+Z*(C3+Z*C5)
                   6558:        fmul.x          X(%a6),%fp0             # X'*Y
                   6559:
                   6560:        fadd.x          %fp2,%fp1               # [Y*(C2+Z*C4)]+[C1+Z*(C3+Z*C5)]
                   6561:
                   6562:        fmul.x          %fp1,%fp0               # X'*Y*([B1+Z*(B3+Z*B5)]
                   6563: #                                      ...     +[Y*(B2+Z*(B4+Z*B6))])
                   6564:        fadd.x          X(%a6),%fp0
                   6565:
                   6566:        fmovm.x         (%sp)+,&0x30            # restore fp2/fp3
                   6567:
                   6568:        fmov.l          %d0,%fpcr               # restore users rnd mode,prec
                   6569:        tst.b           (%a0)
                   6570:        bpl.b           pos_big
                   6571:
                   6572: neg_big:
                   6573:        fadd.x          NPIBY2(%pc),%fp0
                   6574:        bra             t_minx2
                   6575:
                   6576: pos_big:
                   6577:        fadd.x          PPIBY2(%pc),%fp0
                   6578:        bra             t_pinx2
                   6579:
                   6580: ATANHUGE:
                   6581: #--RETURN SIGN(X)*(PIBY2 - TINY) = SIGN(X)*PIBY2 - SIGN(X)*TINY
                   6582:        tst.b           (%a0)
                   6583:        bpl.b           pos_huge
                   6584:
                   6585: neg_huge:
                   6586:        fmov.x          NPIBY2(%pc),%fp0
                   6587:        fmov.l          %d0,%fpcr
                   6588:        fadd.x          PTINY(%pc),%fp0
                   6589:        bra             t_minx2
                   6590:
                   6591: pos_huge:
                   6592:        fmov.x          PPIBY2(%pc),%fp0
                   6593:        fmov.l          %d0,%fpcr
                   6594:        fadd.x          NTINY(%pc),%fp0
                   6595:        bra             t_pinx2
                   6596:
                   6597:        global          satand
                   6598: #--ENTRY POINT FOR ATAN(X) FOR DENORMALIZED ARGUMENT
                   6599: satand:
                   6600:        bra             t_extdnrm
                   6601:
                   6602: #########################################################################
                   6603: # sasin():  computes the inverse sine of a normalized input            #
                   6604: # sasind(): computes the inverse sine of a denormalized input          #
                   6605: #                                                                      #
                   6606: # INPUT ***************************************************************        #
                   6607: #      a0 = pointer to extended precision input                        #
                   6608: #      d0 = round precision,mode                                       #
                   6609: #                                                                      #
                   6610: # OUTPUT **************************************************************        #
                   6611: #      fp0 = arcsin(X)                                                 #
                   6612: #                                                                      #
                   6613: # ACCURACY and MONOTONICITY *******************************************        #
                   6614: #      The returned result is within 3 ulps in 64 significant bit,     #
                   6615: #      i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
                   6616: #      rounded to double precision. The result is provably monotonic   #
                   6617: #      in double precision.                                            #
                   6618: #                                                                      #
                   6619: # ALGORITHM ***********************************************************        #
                   6620: #                                                                      #
                   6621: #      ASIN                                                            #
                   6622: #      1. If |X| >= 1, go to 3.                                        #
                   6623: #                                                                      #
                   6624: #      2. (|X| < 1) Calculate asin(X) by                               #
                   6625: #              z := sqrt( [1-X][1+X] )                                 #
                   6626: #              asin(X) = atan( x / z ).                                #
                   6627: #              Exit.                                                   #
                   6628: #                                                                      #
                   6629: #      3. If |X| > 1, go to 5.                                         #
                   6630: #                                                                      #
                   6631: #      4. (|X| = 1) sgn := sign(X), return asin(X) := sgn * Pi/2. Exit.#
                   6632: #                                                                      #
                   6633: #      5. (|X| > 1) Generate an invalid operation by 0 * infinity.     #
                   6634: #              Exit.                                                   #
                   6635: #                                                                      #
                   6636: #########################################################################
                   6637:
                   6638:        global          sasin
                   6639: sasin:
                   6640:        fmov.x          (%a0),%fp0              # LOAD INPUT
                   6641:
                   6642:        mov.l           (%a0),%d1
                   6643:        mov.w           4(%a0),%d1
                   6644:        and.l           &0x7FFFFFFF,%d1
                   6645:        cmp.l           %d1,&0x3FFF8000
                   6646:        bge.b           ASINBIG
                   6647:
                   6648: # This catch is added here for the '060 QSP. Originally, the call to
                   6649: # satan() would handle this case by causing the exception which would
                   6650: # not be caught until gen_except(). Now, with the exceptions being
                   6651: # detected inside of satan(), the exception would have been handled there
                   6652: # instead of inside sasin() as expected.
                   6653:        cmp.l           %d1,&0x3FD78000
                   6654:        blt.w           ASINTINY
                   6655:
                   6656: #--THIS IS THE USUAL CASE, |X| < 1
                   6657: #--ASIN(X) = ATAN( X / SQRT( (1-X)(1+X) ) )
                   6658:
                   6659: ASINMAIN:
                   6660:        fmov.s          &0x3F800000,%fp1
                   6661:        fsub.x          %fp0,%fp1               # 1-X
                   6662:        fmovm.x         &0x4,-(%sp)             #  {fp2}
                   6663:        fmov.s          &0x3F800000,%fp2
                   6664:        fadd.x          %fp0,%fp2               # 1+X
                   6665:        fmul.x          %fp2,%fp1               # (1+X)(1-X)
                   6666:        fmovm.x         (%sp)+,&0x20            #  {fp2}
                   6667:        fsqrt.x         %fp1                    # SQRT([1-X][1+X])
                   6668:        fdiv.x          %fp1,%fp0               # X/SQRT([1-X][1+X])
                   6669:        fmovm.x         &0x01,-(%sp)            # save X/SQRT(...)
                   6670:        lea             (%sp),%a0               # pass ptr to X/SQRT(...)
                   6671:        bsr             satan
                   6672:        add.l           &0xc,%sp                # clear X/SQRT(...) from stack
                   6673:        bra             t_inx2
                   6674:
                   6675: ASINBIG:
                   6676:        fabs.x          %fp0                    # |X|
                   6677:        fcmp.s          %fp0,&0x3F800000
                   6678:        fbgt            t_operr                 # cause an operr exception
                   6679:
                   6680: #--|X| = 1, ASIN(X) = +- PI/2.
                   6681: ASINONE:
                   6682:        fmov.x          PIBY2(%pc),%fp0
                   6683:        mov.l           (%a0),%d1
                   6684:        and.l           &0x80000000,%d1         # SIGN BIT OF X
                   6685:        or.l            &0x3F800000,%d1         # +-1 IN SGL FORMAT
                   6686:        mov.l           %d1,-(%sp)              # push SIGN(X) IN SGL-FMT
                   6687:        fmov.l          %d0,%fpcr
                   6688:        fmul.s          (%sp)+,%fp0
                   6689:        bra             t_inx2
                   6690:
                   6691: #--|X| < 2^(-40), ATAN(X) = X
                   6692: ASINTINY:
                   6693:        fmov.l          %d0,%fpcr               # restore users rnd mode,prec
                   6694:        mov.b           &FMOV_OP,%d1            # last inst is MOVE
                   6695:        fmov.x          (%a0),%fp0              # last inst - possible exception
                   6696:        bra             t_catch
                   6697:
                   6698:        global          sasind
                   6699: #--ASIN(X) = X FOR DENORMALIZED X
                   6700: sasind:
                   6701:        bra             t_extdnrm
                   6702:
                   6703: #########################################################################
                   6704: # sacos():  computes the inverse cosine of a normalized input          #
                   6705: # sacosd(): computes the inverse cosine of a denormalized input                #
                   6706: #                                                                      #
                   6707: # INPUT ***************************************************************        #
                   6708: #      a0 = pointer to extended precision input                        #
                   6709: #      d0 = round precision,mode                                       #
                   6710: #                                                                      #
                   6711: # OUTPUT ************************************************************** #
                   6712: #      fp0 = arccos(X)                                                 #
                   6713: #                                                                      #
                   6714: # ACCURACY and MONOTONICITY *******************************************        #
                   6715: #      The returned result is within 3 ulps in 64 significant bit,     #
                   6716: #      i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
                   6717: #      rounded to double precision. The result is provably monotonic   #
                   6718: #      in double precision.                                            #
                   6719: #                                                                      #
                   6720: # ALGORITHM *********************************************************** #
                   6721: #                                                                      #
                   6722: #      ACOS                                                            #
                   6723: #      1. If |X| >= 1, go to 3.                                        #
                   6724: #                                                                      #
                   6725: #      2. (|X| < 1) Calculate acos(X) by                               #
                   6726: #              z := (1-X) / (1+X)                                      #
                   6727: #              acos(X) = 2 * atan( sqrt(z) ).                          #
                   6728: #              Exit.                                                   #
                   6729: #                                                                      #
                   6730: #      3. If |X| > 1, go to 5.                                         #
                   6731: #                                                                      #
                   6732: #      4. (|X| = 1) If X > 0, return 0. Otherwise, return Pi. Exit.    #
                   6733: #                                                                      #
                   6734: #      5. (|X| > 1) Generate an invalid operation by 0 * infinity.     #
                   6735: #              Exit.                                                   #
                   6736: #                                                                      #
                   6737: #########################################################################
                   6738:
                   6739:        global          sacos
                   6740: sacos:
                   6741:        fmov.x          (%a0),%fp0              # LOAD INPUT
                   6742:
                   6743:        mov.l           (%a0),%d1               # pack exp w/ upper 16 fraction
                   6744:        mov.w           4(%a0),%d1
                   6745:        and.l           &0x7FFFFFFF,%d1
                   6746:        cmp.l           %d1,&0x3FFF8000
                   6747:        bge.b           ACOSBIG
                   6748:
                   6749: #--THIS IS THE USUAL CASE, |X| < 1
                   6750: #--ACOS(X) = 2 * ATAN( SQRT( (1-X)/(1+X) ) )
                   6751:
                   6752: ACOSMAIN:
                   6753:        fmov.s          &0x3F800000,%fp1
                   6754:        fadd.x          %fp0,%fp1               # 1+X
                   6755:        fneg.x          %fp0                    # -X
                   6756:        fadd.s          &0x3F800000,%fp0        # 1-X
                   6757:        fdiv.x          %fp1,%fp0               # (1-X)/(1+X)
                   6758:        fsqrt.x         %fp0                    # SQRT((1-X)/(1+X))
                   6759:        mov.l           %d0,-(%sp)              # save original users fpcr
                   6760:        clr.l           %d0
                   6761:        fmovm.x         &0x01,-(%sp)            # save SQRT(...) to stack
                   6762:        lea             (%sp),%a0               # pass ptr to sqrt
                   6763:        bsr             satan                   # ATAN(SQRT([1-X]/[1+X]))
                   6764:        add.l           &0xc,%sp                # clear SQRT(...) from stack
                   6765:
                   6766:        fmov.l          (%sp)+,%fpcr            # restore users round prec,mode
                   6767:        fadd.x          %fp0,%fp0               # 2 * ATAN( STUFF )
                   6768:        bra             t_pinx2
                   6769:
                   6770: ACOSBIG:
                   6771:        fabs.x          %fp0
                   6772:        fcmp.s          %fp0,&0x3F800000
                   6773:        fbgt            t_operr                 # cause an operr exception
                   6774:
                   6775: #--|X| = 1, ACOS(X) = 0 OR PI
                   6776:        tst.b           (%a0)                   # is X positive or negative?
                   6777:        bpl.b           ACOSP1
                   6778:
                   6779: #--X = -1
                   6780: #Returns PI and inexact exception
                   6781: ACOSM1:
                   6782:        fmov.x          PI(%pc),%fp0            # load PI
                   6783:        fmov.l          %d0,%fpcr               # load round mode,prec
                   6784:        fadd.s          &0x00800000,%fp0        # add a small value
                   6785:        bra             t_pinx2
                   6786:
                   6787: ACOSP1:
                   6788:        bra             ld_pzero                # answer is positive zero
                   6789:
                   6790:        global          sacosd
                   6791: #--ACOS(X) = PI/2 FOR DENORMALIZED X
                   6792: sacosd:
                   6793:        fmov.l          %d0,%fpcr               # load user's rnd mode/prec
                   6794:        fmov.x          PIBY2(%pc),%fp0
                   6795:        bra             t_pinx2
                   6796:
                   6797: #########################################################################
                   6798: # setox():    computes the exponential for a normalized input          #
                   6799: # setoxd():   computes the exponential for a denormalized input                #
                   6800: # setoxm1():  computes the exponential minus 1 for a normalized input  #
                   6801: # setoxm1d(): computes the exponential minus 1 for a denormalized input        #
                   6802: #                                                                      #
                   6803: # INPUT        *************************************************************** #
                   6804: #      a0 = pointer to extended precision input                        #
                   6805: #      d0 = round precision,mode                                       #
                   6806: #                                                                      #
                   6807: # OUTPUT ************************************************************** #
                   6808: #      fp0 = exp(X) or exp(X)-1                                        #
                   6809: #                                                                      #
                   6810: # ACCURACY and MONOTONICITY ******************************************* #
                   6811: #      The returned result is within 0.85 ulps in 64 significant bit,  #
                   6812: #      i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
                   6813: #      rounded to double precision. The result is provably monotonic   #
                   6814: #      in double precision.                                            #
                   6815: #                                                                      #
                   6816: # ALGORITHM and IMPLEMENTATION **************************************** #
                   6817: #                                                                      #
                   6818: #      setoxd                                                          #
                   6819: #      ------                                                          #
                   6820: #      Step 1. Set ans := 1.0                                          #
                   6821: #                                                                      #
                   6822: #      Step 2. Return  ans := ans + sign(X)*2^(-126). Exit.            #
                   6823: #      Notes:  This will always generate one exception -- inexact.     #
                   6824: #                                                                      #
                   6825: #                                                                      #
                   6826: #      setox                                                           #
                   6827: #      -----                                                           #
                   6828: #                                                                      #
                   6829: #      Step 1. Filter out extreme cases of input argument.             #
                   6830: #              1.1     If |X| >= 2^(-65), go to Step 1.3.              #
                   6831: #              1.2     Go to Step 7.                                   #
                   6832: #              1.3     If |X| < 16380 log(2), go to Step 2.            #
                   6833: #              1.4     Go to Step 8.                                   #
                   6834: #      Notes:  The usual case should take the branches 1.1 -> 1.3 -> 2.#
                   6835: #              To avoid the use of floating-point comparisons, a       #
                   6836: #              compact representation of |X| is used. This format is a #
                   6837: #              32-bit integer, the upper (more significant) 16 bits    #
                   6838: #              are the sign and biased exponent field of |X|; the      #
                   6839: #              lower 16 bits are the 16 most significant fraction      #
                   6840: #              (including the explicit bit) bits of |X|. Consequently, #
                   6841: #              the comparisons in Steps 1.1 and 1.3 can be performed   #
                   6842: #              by integer comparison. Note also that the constant      #
                   6843: #              16380 log(2) used in Step 1.3 is also in the compact    #
                   6844: #              form. Thus taking the branch to Step 2 guarantees       #
                   6845: #              |X| < 16380 log(2). There is no harm to have a small    #
                   6846: #              number of cases where |X| is less than, but close to,   #
                   6847: #              16380 log(2) and the branch to Step 9 is taken.         #
                   6848: #                                                                      #
                   6849: #      Step 2. Calculate N = round-to-nearest-int( X * 64/log2 ).      #
                   6850: #              2.1     Set AdjFlag := 0 (indicates the branch 1.3 -> 2 #
                   6851: #                      was taken)                                      #
                   6852: #              2.2     N := round-to-nearest-integer( X * 64/log2 ).   #
                   6853: #              2.3     Calculate       J = N mod 64; so J = 0,1,2,..., #
                   6854: #                      or 63.                                          #
                   6855: #              2.4     Calculate       M = (N - J)/64; so N = 64M + J. #
                   6856: #              2.5     Calculate the address of the stored value of    #
                   6857: #                      2^(J/64).                                       #
                   6858: #              2.6     Create the value Scale = 2^M.                   #
                   6859: #      Notes:  The calculation in 2.2 is really performed by           #
                   6860: #                      Z := X * constant                               #
                   6861: #                      N := round-to-nearest-integer(Z)                #
                   6862: #              where                                                   #
                   6863: #                      constant := single-precision( 64/log 2 ).       #
                   6864: #                                                                      #
                   6865: #              Using a single-precision constant avoids memory         #
                   6866: #              access. Another effect of using a single-precision      #
                   6867: #              "constant" is that the calculated value Z is            #
                   6868: #                                                                      #
                   6869: #                      Z = X*(64/log2)*(1+eps), |eps| <= 2^(-24).      #
                   6870: #                                                                      #
                   6871: #              This error has to be considered later in Steps 3 and 4. #
                   6872: #                                                                      #
                   6873: #      Step 3. Calculate X - N*log2/64.                                #
                   6874: #              3.1     R := X + N*L1,                                  #
                   6875: #                              where L1 := single-precision(-log2/64). #
                   6876: #              3.2     R := R + N*L2,                                  #
                   6877: #                              L2 := extended-precision(-log2/64 - L1).#
                   6878: #      Notes:  a) The way L1 and L2 are chosen ensures L1+L2           #
                   6879: #              approximate the value -log2/64 to 88 bits of accuracy.  #
                   6880: #              b) N*L1 is exact because N is no longer than 22 bits    #
                   6881: #              and L1 is no longer than 24 bits.                       #
                   6882: #              c) The calculation X+N*L1 is also exact due to          #
                   6883: #              cancellation. Thus, R is practically X+N(L1+L2) to full #
                   6884: #              64 bits.                                                #
                   6885: #              d) It is important to estimate how large can |R| be     #
                   6886: #              after Step 3.2.                                         #
                   6887: #                                                                      #
                   6888: #              N = rnd-to-int( X*64/log2 (1+eps) ), |eps|<=2^(-24)     #
                   6889: #              X*64/log2 (1+eps)       =       N + f,  |f| <= 0.5      #
                   6890: #              X*64/log2 - N   =       f - eps*X 64/log2               #
                   6891: #              X - N*log2/64   =       f*log2/64 - eps*X               #
                   6892: #                                                                      #
                   6893: #                                                                      #
                   6894: #              Now |X| <= 16446 log2, thus                             #
                   6895: #                                                                      #
                   6896: #                      |X - N*log2/64| <= (0.5 + 16446/2^(18))*log2/64 #
                   6897: #                                      <= 0.57 log2/64.                #
                   6898: #               This bound will be used in Step 4.                     #
                   6899: #                                                                      #
                   6900: #      Step 4. Approximate exp(R)-1 by a polynomial                    #
                   6901: #              p = R + R*R*(A1 + R*(A2 + R*(A3 + R*(A4 + R*A5))))      #
                   6902: #      Notes:  a) In order to reduce memory access, the coefficients   #
                   6903: #              are made as "short" as possible: A1 (which is 1/2), A4  #
                   6904: #              and A5 are single precision; A2 and A3 are double       #
                   6905: #              precision.                                              #
                   6906: #              b) Even with the restrictions above,                    #
                   6907: #                 |p - (exp(R)-1)| < 2^(-68.8) for all |R| <= 0.0062.  #
                   6908: #              Note that 0.0062 is slightly bigger than 0.57 log2/64.  #
                   6909: #              c) To fully utilize the pipeline, p is separated into   #
                   6910: #              two independent pieces of roughly equal complexities    #
                   6911: #                      p = [ R + R*S*(A2 + S*A4) ]     +               #
                   6912: #                              [ S*(A1 + S*(A3 + S*A5)) ]              #
                   6913: #              where S = R*R.                                          #
                   6914: #                                                                      #
                   6915: #      Step 5. Compute 2^(J/64)*exp(R) = 2^(J/64)*(1+p) by             #
                   6916: #                              ans := T + ( T*p + t)                   #
                   6917: #              where T and t are the stored values for 2^(J/64).       #
                   6918: #      Notes:  2^(J/64) is stored as T and t where T+t approximates    #
                   6919: #              2^(J/64) to roughly 85 bits; T is in extended precision #
                   6920: #              and t is in single precision. Note also that T is       #
                   6921: #              rounded to 62 bits so that the last two bits of T are   #
                   6922: #              zero. The reason for such a special form is that T-1,   #
                   6923: #              T-2, and T-8 will all be exact --- a property that will #
                   6924: #              give much more accurate computation of the function     #
                   6925: #              EXPM1.                                                  #
                   6926: #                                                                      #
                   6927: #      Step 6. Reconstruction of exp(X)                                #
                   6928: #                      exp(X) = 2^M * 2^(J/64) * exp(R).               #
                   6929: #              6.1     If AdjFlag = 0, go to 6.3                       #
                   6930: #              6.2     ans := ans * AdjScale                           #
                   6931: #              6.3     Restore the user FPCR                           #
                   6932: #              6.4     Return ans := ans * Scale. Exit.                #
                   6933: #      Notes:  If AdjFlag = 0, we have X = Mlog2 + Jlog2/64 + R,       #
                   6934: #              |M| <= 16380, and Scale = 2^M. Moreover, exp(X) will    #
                   6935: #              neither overflow nor underflow. If AdjFlag = 1, that    #
                   6936: #              means that                                              #
                   6937: #                      X = (M1+M)log2 + Jlog2/64 + R, |M1+M| >= 16380. #
                   6938: #              Hence, exp(X) may overflow or underflow or neither.     #
                   6939: #              When that is the case, AdjScale = 2^(M1) where M1 is    #
                   6940: #              approximately M. Thus 6.2 will never cause              #
                   6941: #              over/underflow. Possible exception in 6.4 is overflow   #
                   6942: #              or underflow. The inexact exception is not generated in #
                   6943: #              6.4. Although one can argue that the inexact flag       #
                   6944: #              should always be raised, to simulate that exception     #
                   6945: #              cost to much than the flag is worth in practical uses.  #
                   6946: #                                                                      #
                   6947: #      Step 7. Return 1 + X.                                           #
                   6948: #              7.1     ans := X                                        #
                   6949: #              7.2     Restore user FPCR.                              #
                   6950: #              7.3     Return ans := 1 + ans. Exit                     #
                   6951: #      Notes:  For non-zero X, the inexact exception will always be    #
                   6952: #              raised by 7.3. That is the only exception raised by 7.3.#
                   6953: #              Note also that we use the FMOVEM instruction to move X  #
                   6954: #              in Step 7.1 to avoid unnecessary trapping. (Although    #
                   6955: #              the FMOVEM may not seem relevant since X is normalized, #
                   6956: #              the precaution will be useful in the library version of #
                   6957: #              this code where the separate entry for denormalized     #
                   6958: #              inputs will be done away with.)                         #
                   6959: #                                                                      #
                   6960: #      Step 8. Handle exp(X) where |X| >= 16380log2.                   #
                   6961: #              8.1     If |X| > 16480 log2, go to Step 9.              #
                   6962: #              (mimic 2.2 - 2.6)                                       #
                   6963: #              8.2     N := round-to-integer( X * 64/log2 )            #
                   6964: #              8.3     Calculate J = N mod 64, J = 0,1,...,63          #
                   6965: #              8.4     K := (N-J)/64, M1 := truncate(K/2), M = K-M1,   #
                   6966: #                      AdjFlag := 1.                                   #
                   6967: #              8.5     Calculate the address of the stored value       #
                   6968: #                      2^(J/64).                                       #
                   6969: #              8.6     Create the values Scale = 2^M, AdjScale = 2^M1. #
                   6970: #              8.7     Go to Step 3.                                   #
                   6971: #      Notes:  Refer to notes for 2.2 - 2.6.                           #
                   6972: #                                                                      #
                   6973: #      Step 9. Handle exp(X), |X| > 16480 log2.                        #
                   6974: #              9.1     If X < 0, go to 9.3                             #
                   6975: #              9.2     ans := Huge, go to 9.4                          #
                   6976: #              9.3     ans := Tiny.                                    #
                   6977: #              9.4     Restore user FPCR.                              #
                   6978: #              9.5     Return ans := ans * ans. Exit.                  #
                   6979: #      Notes:  Exp(X) will surely overflow or underflow, depending on  #
                   6980: #              X's sign. "Huge" and "Tiny" are respectively large/tiny #
                   6981: #              extended-precision numbers whose square over/underflow  #
                   6982: #              with an inexact result. Thus, 9.5 always raises the     #
                   6983: #              inexact together with either overflow or underflow.     #
                   6984: #                                                                      #
                   6985: #      setoxm1d                                                        #
                   6986: #      --------                                                        #
                   6987: #                                                                      #
                   6988: #      Step 1. Set ans := 0                                            #
                   6989: #                                                                      #
                   6990: #      Step 2. Return  ans := X + ans. Exit.                           #
                   6991: #      Notes:  This will return X with the appropriate rounding        #
                   6992: #               precision prescribed by the user FPCR.                 #
                   6993: #                                                                      #
                   6994: #      setoxm1                                                         #
                   6995: #      -------                                                         #
                   6996: #                                                                      #
                   6997: #      Step 1. Check |X|                                               #
                   6998: #              1.1     If |X| >= 1/4, go to Step 1.3.                  #
                   6999: #              1.2     Go to Step 7.                                   #
                   7000: #              1.3     If |X| < 70 log(2), go to Step 2.               #
                   7001: #              1.4     Go to Step 10.                                  #
                   7002: #      Notes:  The usual case should take the branches 1.1 -> 1.3 -> 2.#
                   7003: #              However, it is conceivable |X| can be small very often  #
                   7004: #              because EXPM1 is intended to evaluate exp(X)-1          #
                   7005: #              accurately when |X| is small. For further details on    #
                   7006: #              the comparisons, see the notes on Step 1 of setox.      #
                   7007: #                                                                      #
                   7008: #      Step 2. Calculate N = round-to-nearest-int( X * 64/log2 ).      #
                   7009: #              2.1     N := round-to-nearest-integer( X * 64/log2 ).   #
                   7010: #              2.2     Calculate       J = N mod 64; so J = 0,1,2,..., #
                   7011: #                      or 63.                                          #
                   7012: #              2.3     Calculate       M = (N - J)/64; so N = 64M + J. #
                   7013: #              2.4     Calculate the address of the stored value of    #
                   7014: #                      2^(J/64).                                       #
                   7015: #              2.5     Create the values Sc = 2^M and                  #
                   7016: #                      OnebySc := -2^(-M).                             #
                   7017: #      Notes:  See the notes on Step 2 of setox.                       #
                   7018: #                                                                      #
                   7019: #      Step 3. Calculate X - N*log2/64.                                #
                   7020: #              3.1     R := X + N*L1,                                  #
                   7021: #                              where L1 := single-precision(-log2/64). #
                   7022: #              3.2     R := R + N*L2,                                  #
                   7023: #                              L2 := extended-precision(-log2/64 - L1).#
                   7024: #      Notes:  Applying the analysis of Step 3 of setox in this case   #
                   7025: #              shows that |R| <= 0.0055 (note that |X| <= 70 log2 in   #
                   7026: #              this case).                                             #
                   7027: #                                                                      #
                   7028: #      Step 4. Approximate exp(R)-1 by a polynomial                    #
                   7029: #                      p = R+R*R*(A1+R*(A2+R*(A3+R*(A4+R*(A5+R*A6))))) #
                   7030: #      Notes:  a) In order to reduce memory access, the coefficients   #
                   7031: #              are made as "short" as possible: A1 (which is 1/2), A5  #
                   7032: #              and A6 are single precision; A2, A3 and A4 are double   #
                   7033: #              precision.                                              #
                   7034: #              b) Even with the restriction above,                     #
                   7035: #                      |p - (exp(R)-1)| <      |R| * 2^(-72.7)         #
                   7036: #              for all |R| <= 0.0055.                                  #
                   7037: #              c) To fully utilize the pipeline, p is separated into   #
                   7038: #              two independent pieces of roughly equal complexity      #
                   7039: #                      p = [ R*S*(A2 + S*(A4 + S*A6)) ]        +       #
                   7040: #                              [ R + S*(A1 + S*(A3 + S*A5)) ]          #
                   7041: #              where S = R*R.                                          #
                   7042: #                                                                      #
                   7043: #      Step 5. Compute 2^(J/64)*p by                                   #
                   7044: #                              p := T*p                                #
                   7045: #              where T and t are the stored values for 2^(J/64).       #
                   7046: #      Notes:  2^(J/64) is stored as T and t where T+t approximates    #
                   7047: #              2^(J/64) to roughly 85 bits; T is in extended precision #
                   7048: #              and t is in single precision. Note also that T is       #
                   7049: #              rounded to 62 bits so that the last two bits of T are   #
                   7050: #              zero. The reason for such a special form is that T-1,   #
                   7051: #              T-2, and T-8 will all be exact --- a property that will #
                   7052: #              be exploited in Step 6 below. The total relative error  #
                   7053: #              in p is no bigger than 2^(-67.7) compared to the final  #
                   7054: #              result.                                                 #
                   7055: #                                                                      #
                   7056: #      Step 6. Reconstruction of exp(X)-1                              #
                   7057: #                      exp(X)-1 = 2^M * ( 2^(J/64) + p - 2^(-M) ).     #
                   7058: #              6.1     If M <= 63, go to Step 6.3.                     #
                   7059: #              6.2     ans := T + (p + (t + OnebySc)). Go to 6.6       #
                   7060: #              6.3     If M >= -3, go to 6.5.                          #
                   7061: #              6.4     ans := (T + (p + t)) + OnebySc. Go to 6.6       #
                   7062: #              6.5     ans := (T + OnebySc) + (p + t).                 #
                   7063: #              6.6     Restore user FPCR.                              #
                   7064: #              6.7     Return ans := Sc * ans. Exit.                   #
                   7065: #      Notes:  The various arrangements of the expressions give        #
                   7066: #              accurate evaluations.                                   #
                   7067: #                                                                      #
                   7068: #      Step 7. exp(X)-1 for |X| < 1/4.                                 #
                   7069: #              7.1     If |X| >= 2^(-65), go to Step 9.                #
                   7070: #              7.2     Go to Step 8.                                   #
                   7071: #                                                                      #
                   7072: #      Step 8. Calculate exp(X)-1, |X| < 2^(-65).                      #
                   7073: #              8.1     If |X| < 2^(-16312), goto 8.3                   #
                   7074: #              8.2     Restore FPCR; return ans := X - 2^(-16382).     #
                   7075: #                      Exit.                                           #
                   7076: #              8.3     X := X * 2^(140).                               #
                   7077: #              8.4     Restore FPCR; ans := ans - 2^(-16382).          #
                   7078: #               Return ans := ans*2^(140). Exit                        #
                   7079: #      Notes:  The idea is to return "X - tiny" under the user         #
                   7080: #              precision and rounding modes. To avoid unnecessary      #
                   7081: #              inefficiency, we stay away from denormalized numbers    #
                   7082: #              the best we can. For |X| >= 2^(-16312), the             #
                   7083: #              straightforward 8.2 generates the inexact exception as  #
                   7084: #              the case warrants.                                      #
                   7085: #                                                                      #
                   7086: #      Step 9. Calculate exp(X)-1, |X| < 1/4, by a polynomial          #
                   7087: #                      p = X + X*X*(B1 + X*(B2 + ... + X*B12))         #
                   7088: #      Notes:  a) In order to reduce memory access, the coefficients   #
                   7089: #              are made as "short" as possible: B1 (which is 1/2), B9  #
                   7090: #              to B12 are single precision; B3 to B8 are double        #
                   7091: #              precision; and B2 is double extended.                   #
                   7092: #              b) Even with the restriction above,                     #
                   7093: #                      |p - (exp(X)-1)| < |X| 2^(-70.6)                #
                   7094: #              for all |X| <= 0.251.                                   #
                   7095: #              Note that 0.251 is slightly bigger than 1/4.            #
                   7096: #              c) To fully preserve accuracy, the polynomial is        #
                   7097: #              computed as                                             #
                   7098: #                      X + ( S*B1 +    Q ) where S = X*X and           #
                   7099: #                      Q       =       X*S*(B2 + X*(B3 + ... + X*B12)) #
                   7100: #              d) To fully utilize the pipeline, Q is separated into   #
                   7101: #              two independent pieces of roughly equal complexity      #
                   7102: #                      Q = [ X*S*(B2 + S*(B4 + ... + S*B12)) ] +       #
                   7103: #                              [ S*S*(B3 + S*(B5 + ... + S*B11)) ]     #
                   7104: #                                                                      #
                   7105: #      Step 10. Calculate exp(X)-1 for |X| >= 70 log 2.                #
                   7106: #              10.1 If X >= 70log2 , exp(X) - 1 = exp(X) for all       #
                   7107: #              practical purposes. Therefore, go to Step 1 of setox.   #
                   7108: #              10.2 If X <= -70log2, exp(X) - 1 = -1 for all practical #
                   7109: #              purposes.                                               #
                   7110: #              ans := -1                                               #
                   7111: #              Restore user FPCR                                       #
                   7112: #              Return ans := ans + 2^(-126). Exit.                     #
                   7113: #      Notes:  10.2 will always create an inexact and return -1 + tiny #
                   7114: #              in the user rounding precision and mode.                #
                   7115: #                                                                      #
                   7116: #########################################################################
                   7117:
                   7118: L2:    long            0x3FDC0000,0x82E30865,0x4361C4C6,0x00000000
                   7119:
                   7120: EEXPA3:        long            0x3FA55555,0x55554CC1
                   7121: EEXPA2:        long            0x3FC55555,0x55554A54
                   7122:
                   7123: EM1A4: long            0x3F811111,0x11174385
                   7124: EM1A3: long            0x3FA55555,0x55554F5A
                   7125:
                   7126: EM1A2: long            0x3FC55555,0x55555555,0x00000000,0x00000000
                   7127:
                   7128: EM1B8: long            0x3EC71DE3,0xA5774682
                   7129: EM1B7: long            0x3EFA01A0,0x19D7CB68
                   7130:
                   7131: EM1B6: long            0x3F2A01A0,0x1A019DF3
                   7132: EM1B5: long            0x3F56C16C,0x16C170E2
                   7133:
                   7134: EM1B4: long            0x3F811111,0x11111111
                   7135: EM1B3: long            0x3FA55555,0x55555555
                   7136:
                   7137: EM1B2: long            0x3FFC0000,0xAAAAAAAA,0xAAAAAAAB
                   7138:        long            0x00000000
                   7139:
                   7140: TWO140:        long            0x48B00000,0x00000000
                   7141: TWON140:
                   7142:        long            0x37300000,0x00000000
                   7143:
                   7144: EEXPTBL:
                   7145:        long            0x3FFF0000,0x80000000,0x00000000,0x00000000
                   7146:        long            0x3FFF0000,0x8164D1F3,0xBC030774,0x9F841A9B
                   7147:        long            0x3FFF0000,0x82CD8698,0xAC2BA1D8,0x9FC1D5B9
                   7148:        long            0x3FFF0000,0x843A28C3,0xACDE4048,0xA0728369
                   7149:        long            0x3FFF0000,0x85AAC367,0xCC487B14,0x1FC5C95C
                   7150:        long            0x3FFF0000,0x871F6196,0x9E8D1010,0x1EE85C9F
                   7151:        long            0x3FFF0000,0x88980E80,0x92DA8528,0x9FA20729
                   7152:        long            0x3FFF0000,0x8A14D575,0x496EFD9C,0xA07BF9AF
                   7153:        long            0x3FFF0000,0x8B95C1E3,0xEA8BD6E8,0xA0020DCF
                   7154:        long            0x3FFF0000,0x8D1ADF5B,0x7E5BA9E4,0x205A63DA
                   7155:        long            0x3FFF0000,0x8EA4398B,0x45CD53C0,0x1EB70051
                   7156:        long            0x3FFF0000,0x9031DC43,0x1466B1DC,0x1F6EB029
                   7157:        long            0x3FFF0000,0x91C3D373,0xAB11C338,0xA0781494
                   7158:        long            0x3FFF0000,0x935A2B2F,0x13E6E92C,0x9EB319B0
                   7159:        long            0x3FFF0000,0x94F4EFA8,0xFEF70960,0x2017457D
                   7160:        long            0x3FFF0000,0x96942D37,0x20185A00,0x1F11D537
                   7161:        long            0x3FFF0000,0x9837F051,0x8DB8A970,0x9FB952DD
                   7162:        long            0x3FFF0000,0x99E04593,0x20B7FA64,0x1FE43087
                   7163:        long            0x3FFF0000,0x9B8D39B9,0xD54E5538,0x1FA2A818
                   7164:        long            0x3FFF0000,0x9D3ED9A7,0x2CFFB750,0x1FDE494D
                   7165:        long            0x3FFF0000,0x9EF53260,0x91A111AC,0x20504890
                   7166:        long            0x3FFF0000,0xA0B0510F,0xB9714FC4,0xA073691C
                   7167:        long            0x3FFF0000,0xA2704303,0x0C496818,0x1F9B7A05
                   7168:        long            0x3FFF0000,0xA43515AE,0x09E680A0,0xA0797126
                   7169:        long            0x3FFF0000,0xA5FED6A9,0xB15138EC,0xA071A140
                   7170:        long            0x3FFF0000,0xA7CD93B4,0xE9653568,0x204F62DA
                   7171:        long            0x3FFF0000,0xA9A15AB4,0xEA7C0EF8,0x1F283C4A
                   7172:        long            0x3FFF0000,0xAB7A39B5,0xA93ED338,0x9F9A7FDC
                   7173:        long            0x3FFF0000,0xAD583EEA,0x42A14AC8,0xA05B3FAC
                   7174:        long            0x3FFF0000,0xAF3B78AD,0x690A4374,0x1FDF2610
                   7175:        long            0x3FFF0000,0xB123F581,0xD2AC2590,0x9F705F90
                   7176:        long            0x3FFF0000,0xB311C412,0xA9112488,0x201F678A
                   7177:        long            0x3FFF0000,0xB504F333,0xF9DE6484,0x1F32FB13
                   7178:        long            0x3FFF0000,0xB6FD91E3,0x28D17790,0x20038B30
                   7179:        long            0x3FFF0000,0xB8FBAF47,0x62FB9EE8,0x200DC3CC
                   7180:        long            0x3FFF0000,0xBAFF5AB2,0x133E45FC,0x9F8B2AE6
                   7181:        long            0x3FFF0000,0xBD08A39F,0x580C36C0,0xA02BBF70
                   7182:        long            0x3FFF0000,0xBF1799B6,0x7A731084,0xA00BF518
                   7183:        long            0x3FFF0000,0xC12C4CCA,0x66709458,0xA041DD41
                   7184:        long            0x3FFF0000,0xC346CCDA,0x24976408,0x9FDF137B
                   7185:        long            0x3FFF0000,0xC5672A11,0x5506DADC,0x201F1568
                   7186:        long            0x3FFF0000,0xC78D74C8,0xABB9B15C,0x1FC13A2E
                   7187:        long            0x3FFF0000,0xC9B9BD86,0x6E2F27A4,0xA03F8F03
                   7188:        long            0x3FFF0000,0xCBEC14FE,0xF2727C5C,0x1FF4907D
                   7189:        long            0x3FFF0000,0xCE248C15,0x1F8480E4,0x9E6E53E4
                   7190:        long            0x3FFF0000,0xD06333DA,0xEF2B2594,0x1FD6D45C
                   7191:        long            0x3FFF0000,0xD2A81D91,0xF12AE45C,0xA076EDB9
                   7192:        long            0x3FFF0000,0xD4F35AAB,0xCFEDFA20,0x9FA6DE21
                   7193:        long            0x3FFF0000,0xD744FCCA,0xD69D6AF4,0x1EE69A2F
                   7194:        long            0x3FFF0000,0xD99D15C2,0x78AFD7B4,0x207F439F
                   7195:        long            0x3FFF0000,0xDBFBB797,0xDAF23754,0x201EC207
                   7196:        long            0x3FFF0000,0xDE60F482,0x5E0E9124,0x9E8BE175
                   7197:        long            0x3FFF0000,0xE0CCDEEC,0x2A94E110,0x20032C4B
                   7198:        long            0x3FFF0000,0xE33F8972,0xBE8A5A50,0x2004DFF5
                   7199:        long            0x3FFF0000,0xE5B906E7,0x7C8348A8,0x1E72F47A
                   7200:        long            0x3FFF0000,0xE8396A50,0x3C4BDC68,0x1F722F22
                   7201:        long            0x3FFF0000,0xEAC0C6E7,0xDD243930,0xA017E945
                   7202:        long            0x3FFF0000,0xED4F301E,0xD9942B84,0x1F401A5B
                   7203:        long            0x3FFF0000,0xEFE4B99B,0xDCDAF5CC,0x9FB9A9E3
                   7204:        long            0x3FFF0000,0xF281773C,0x59FFB138,0x20744C05
                   7205:        long            0x3FFF0000,0xF5257D15,0x2486CC2C,0x1F773A19
                   7206:        long            0x3FFF0000,0xF7D0DF73,0x0AD13BB8,0x1FFE90D5
                   7207:        long            0x3FFF0000,0xFA83B2DB,0x722A033C,0xA041ED22
                   7208:        long            0x3FFF0000,0xFD3E0C0C,0xF486C174,0x1F853F3A
                   7209:
                   7210:        set             ADJFLAG,L_SCR2
                   7211:        set             SCALE,FP_SCR0
                   7212:        set             ADJSCALE,FP_SCR1
                   7213:        set             SC,FP_SCR0
                   7214:        set             ONEBYSC,FP_SCR1
                   7215:
                   7216:        global          setox
                   7217: setox:
                   7218: #--entry point for EXP(X), here X is finite, non-zero, and not NaN's
                   7219:
                   7220: #--Step 1.
                   7221:        mov.l           (%a0),%d1               # load part of input X
                   7222:        and.l           &0x7FFF0000,%d1         # biased expo. of X
                   7223:        cmp.l           %d1,&0x3FBE0000         # 2^(-65)
                   7224:        bge.b           EXPC1                   # normal case
                   7225:        bra             EXPSM
                   7226:
                   7227: EXPC1:
                   7228: #--The case |X| >= 2^(-65)
                   7229:        mov.w           4(%a0),%d1              # expo. and partial sig. of |X|
                   7230:        cmp.l           %d1,&0x400CB167         # 16380 log2 trunc. 16 bits
                   7231:        blt.b           EXPMAIN                 # normal case
                   7232:        bra             EEXPBIG
                   7233:
                   7234: EXPMAIN:
                   7235: #--Step 2.
                   7236: #--This is the normal branch:  2^(-65) <= |X| < 16380 log2.
                   7237:        fmov.x          (%a0),%fp0              # load input from (a0)
                   7238:
                   7239:        fmov.x          %fp0,%fp1
                   7240:        fmul.s          &0x42B8AA3B,%fp0        # 64/log2 * X
                   7241:        fmovm.x         &0xc,-(%sp)             # save fp2 {%fp2/%fp3}
                   7242:        mov.l           &0,ADJFLAG(%a6)
                   7243:        fmov.l          %fp0,%d1                # N = int( X * 64/log2 )
                   7244:        lea             EEXPTBL(%pc),%a1
                   7245:        fmov.l          %d1,%fp0                # convert to floating-format
                   7246:
                   7247:        mov.l           %d1,L_SCR1(%a6)         # save N temporarily
                   7248:        and.l           &0x3F,%d1               # D0 is J = N mod 64
                   7249:        lsl.l           &4,%d1
                   7250:        add.l           %d1,%a1                 # address of 2^(J/64)
                   7251:        mov.l           L_SCR1(%a6),%d1
                   7252:        asr.l           &6,%d1                  # D0 is M
                   7253:        add.w           &0x3FFF,%d1             # biased expo. of 2^(M)
                   7254:        mov.w           L2(%pc),L_SCR1(%a6)     # prefetch L2, no need in CB
                   7255:
                   7256: EXPCONT1:
                   7257: #--Step 3.
                   7258: #--fp1,fp2 saved on the stack. fp0 is N, fp1 is X,
                   7259: #--a0 points to 2^(J/64), D0 is biased expo. of 2^(M)
                   7260:        fmov.x          %fp0,%fp2
                   7261:        fmul.s          &0xBC317218,%fp0        # N * L1, L1 = lead(-log2/64)
                   7262:        fmul.x          L2(%pc),%fp2            # N * L2, L1+L2 = -log2/64
                   7263:        fadd.x          %fp1,%fp0               # X + N*L1
                   7264:        fadd.x          %fp2,%fp0               # fp0 is R, reduced arg.
                   7265:
                   7266: #--Step 4.
                   7267: #--WE NOW COMPUTE EXP(R)-1 BY A POLYNOMIAL
                   7268: #-- R + R*R*(A1 + R*(A2 + R*(A3 + R*(A4 + R*A5))))
                   7269: #--TO FULLY UTILIZE THE PIPELINE, WE COMPUTE S = R*R
                   7270: #--[R+R*S*(A2+S*A4)] + [S*(A1+S*(A3+S*A5))]
                   7271:
                   7272:        fmov.x          %fp0,%fp1
                   7273:        fmul.x          %fp1,%fp1               # fp1 IS S = R*R
                   7274:
                   7275:        fmov.s          &0x3AB60B70,%fp2        # fp2 IS A5
                   7276:
                   7277:        fmul.x          %fp1,%fp2               # fp2 IS S*A5
                   7278:        fmov.x          %fp1,%fp3
                   7279:        fmul.s          &0x3C088895,%fp3        # fp3 IS S*A4
                   7280:
                   7281:        fadd.d          EEXPA3(%pc),%fp2        # fp2 IS A3+S*A5
                   7282:        fadd.d          EEXPA2(%pc),%fp3        # fp3 IS A2+S*A4
                   7283:
                   7284:        fmul.x          %fp1,%fp2               # fp2 IS S*(A3+S*A5)
                   7285:        mov.w           %d1,SCALE(%a6)          # SCALE is 2^(M) in extended
                   7286:        mov.l           &0x80000000,SCALE+4(%a6)
                   7287:        clr.l           SCALE+8(%a6)
                   7288:
                   7289:        fmul.x          %fp1,%fp3               # fp3 IS S*(A2+S*A4)
                   7290:
                   7291:        fadd.s          &0x3F000000,%fp2        # fp2 IS A1+S*(A3+S*A5)
                   7292:        fmul.x          %fp0,%fp3               # fp3 IS R*S*(A2+S*A4)
                   7293:
                   7294:        fmul.x          %fp1,%fp2               # fp2 IS S*(A1+S*(A3+S*A5))
                   7295:        fadd.x          %fp3,%fp0               # fp0 IS R+R*S*(A2+S*A4),
                   7296:
                   7297:        fmov.x          (%a1)+,%fp1             # fp1 is lead. pt. of 2^(J/64)
                   7298:        fadd.x          %fp2,%fp0               # fp0 is EXP(R) - 1
                   7299:
                   7300: #--Step 5
                   7301: #--final reconstruction process
                   7302: #--EXP(X) = 2^M * ( 2^(J/64) + 2^(J/64)*(EXP(R)-1) )
                   7303:
                   7304:        fmul.x          %fp1,%fp0               # 2^(J/64)*(Exp(R)-1)
                   7305:        fmovm.x         (%sp)+,&0x30            # fp2 restored {%fp2/%fp3}
                   7306:        fadd.s          (%a1),%fp0              # accurate 2^(J/64)
                   7307:
                   7308:        fadd.x          %fp1,%fp0               # 2^(J/64) + 2^(J/64)*...
                   7309:        mov.l           ADJFLAG(%a6),%d1
                   7310:
                   7311: #--Step 6
                   7312:        tst.l           %d1
                   7313:        beq.b           NORMAL
                   7314: ADJUST:
                   7315:        fmul.x          ADJSCALE(%a6),%fp0
                   7316: NORMAL:
                   7317:        fmov.l          %d0,%fpcr               # restore user FPCR
                   7318:        mov.b           &FMUL_OP,%d1            # last inst is MUL
                   7319:        fmul.x          SCALE(%a6),%fp0         # multiply 2^(M)
                   7320:        bra             t_catch
                   7321:
                   7322: EXPSM:
                   7323: #--Step 7
                   7324:        fmovm.x         (%a0),&0x80             # load X
                   7325:        fmov.l          %d0,%fpcr
                   7326:        fadd.s          &0x3F800000,%fp0        # 1+X in user mode
                   7327:        bra             t_pinx2
                   7328:
                   7329: EEXPBIG:
                   7330: #--Step 8
                   7331:        cmp.l           %d1,&0x400CB27C         # 16480 log2
                   7332:        bgt.b           EXP2BIG
                   7333: #--Steps 8.2 -- 8.6
                   7334:        fmov.x          (%a0),%fp0              # load input from (a0)
                   7335:
                   7336:        fmov.x          %fp0,%fp1
                   7337:        fmul.s          &0x42B8AA3B,%fp0        # 64/log2 * X
                   7338:        fmovm.x         &0xc,-(%sp)             # save fp2 {%fp2/%fp3}
                   7339:        mov.l           &1,ADJFLAG(%a6)
                   7340:        fmov.l          %fp0,%d1                # N = int( X * 64/log2 )
                   7341:        lea             EEXPTBL(%pc),%a1
                   7342:        fmov.l          %d1,%fp0                # convert to floating-format
                   7343:        mov.l           %d1,L_SCR1(%a6)         # save N temporarily
                   7344:        and.l           &0x3F,%d1               # D0 is J = N mod 64
                   7345:        lsl.l           &4,%d1
                   7346:        add.l           %d1,%a1                 # address of 2^(J/64)
                   7347:        mov.l           L_SCR1(%a6),%d1
                   7348:        asr.l           &6,%d1                  # D0 is K
                   7349:        mov.l           %d1,L_SCR1(%a6)         # save K temporarily
                   7350:        asr.l           &1,%d1                  # D0 is M1
                   7351:        sub.l           %d1,L_SCR1(%a6)         # a1 is M
                   7352:        add.w           &0x3FFF,%d1             # biased expo. of 2^(M1)
                   7353:        mov.w           %d1,ADJSCALE(%a6)       # ADJSCALE := 2^(M1)
                   7354:        mov.l           &0x80000000,ADJSCALE+4(%a6)
                   7355:        clr.l           ADJSCALE+8(%a6)
                   7356:        mov.l           L_SCR1(%a6),%d1         # D0 is M
                   7357:        add.w           &0x3FFF,%d1             # biased expo. of 2^(M)
                   7358:        bra.w           EXPCONT1                # go back to Step 3
                   7359:
                   7360: EXP2BIG:
                   7361: #--Step 9
                   7362:        tst.b           (%a0)                   # is X positive or negative?
                   7363:        bmi             t_unfl2
                   7364:        bra             t_ovfl2
                   7365:
                   7366:        global          setoxd
                   7367: setoxd:
                   7368: #--entry point for EXP(X), X is denormalized
                   7369:        mov.l           (%a0),-(%sp)
                   7370:        andi.l          &0x80000000,(%sp)
                   7371:        ori.l           &0x00800000,(%sp)       # sign(X)*2^(-126)
                   7372:
                   7373:        fmov.s          &0x3F800000,%fp0
                   7374:
                   7375:        fmov.l          %d0,%fpcr
                   7376:        fadd.s          (%sp)+,%fp0
                   7377:        bra             t_pinx2
                   7378:
                   7379:        global          setoxm1
                   7380: setoxm1:
                   7381: #--entry point for EXPM1(X), here X is finite, non-zero, non-NaN
                   7382:
                   7383: #--Step 1.
                   7384: #--Step 1.1
                   7385:        mov.l           (%a0),%d1               # load part of input X
                   7386:        and.l           &0x7FFF0000,%d1         # biased expo. of X
                   7387:        cmp.l           %d1,&0x3FFD0000         # 1/4
                   7388:        bge.b           EM1CON1                 # |X| >= 1/4
                   7389:        bra             EM1SM
                   7390:
                   7391: EM1CON1:
                   7392: #--Step 1.3
                   7393: #--The case |X| >= 1/4
                   7394:        mov.w           4(%a0),%d1              # expo. and partial sig. of |X|
                   7395:        cmp.l           %d1,&0x4004C215         # 70log2 rounded up to 16 bits
                   7396:        ble.b           EM1MAIN                 # 1/4 <= |X| <= 70log2
                   7397:        bra             EM1BIG
                   7398:
                   7399: EM1MAIN:
                   7400: #--Step 2.
                   7401: #--This is the case:   1/4 <= |X| <= 70 log2.
                   7402:        fmov.x          (%a0),%fp0              # load input from (a0)
                   7403:
                   7404:        fmov.x          %fp0,%fp1
                   7405:        fmul.s          &0x42B8AA3B,%fp0        # 64/log2 * X
                   7406:        fmovm.x         &0xc,-(%sp)             # save fp2 {%fp2/%fp3}
                   7407:        fmov.l          %fp0,%d1                # N = int( X * 64/log2 )
                   7408:        lea             EEXPTBL(%pc),%a1
                   7409:        fmov.l          %d1,%fp0                # convert to floating-format
                   7410:
                   7411:        mov.l           %d1,L_SCR1(%a6)         # save N temporarily
                   7412:        and.l           &0x3F,%d1               # D0 is J = N mod 64
                   7413:        lsl.l           &4,%d1
                   7414:        add.l           %d1,%a1                 # address of 2^(J/64)
                   7415:        mov.l           L_SCR1(%a6),%d1
                   7416:        asr.l           &6,%d1                  # D0 is M
                   7417:        mov.l           %d1,L_SCR1(%a6)         # save a copy of M
                   7418:
                   7419: #--Step 3.
                   7420: #--fp1,fp2 saved on the stack. fp0 is N, fp1 is X,
                   7421: #--a0 points to 2^(J/64), D0 and a1 both contain M
                   7422:        fmov.x          %fp0,%fp2
                   7423:        fmul.s          &0xBC317218,%fp0        # N * L1, L1 = lead(-log2/64)
                   7424:        fmul.x          L2(%pc),%fp2            # N * L2, L1+L2 = -log2/64
                   7425:        fadd.x          %fp1,%fp0               # X + N*L1
                   7426:        fadd.x          %fp2,%fp0               # fp0 is R, reduced arg.
                   7427:        add.w           &0x3FFF,%d1             # D0 is biased expo. of 2^M
                   7428:
                   7429: #--Step 4.
                   7430: #--WE NOW COMPUTE EXP(R)-1 BY A POLYNOMIAL
                   7431: #-- R + R*R*(A1 + R*(A2 + R*(A3 + R*(A4 + R*(A5 + R*A6)))))
                   7432: #--TO FULLY UTILIZE THE PIPELINE, WE COMPUTE S = R*R
                   7433: #--[R*S*(A2+S*(A4+S*A6))] + [R+S*(A1+S*(A3+S*A5))]
                   7434:
                   7435:        fmov.x          %fp0,%fp1
                   7436:        fmul.x          %fp1,%fp1               # fp1 IS S = R*R
                   7437:
                   7438:        fmov.s          &0x3950097B,%fp2        # fp2 IS a6
                   7439:
                   7440:        fmul.x          %fp1,%fp2               # fp2 IS S*A6
                   7441:        fmov.x          %fp1,%fp3
                   7442:        fmul.s          &0x3AB60B6A,%fp3        # fp3 IS S*A5
                   7443:
                   7444:        fadd.d          EM1A4(%pc),%fp2         # fp2 IS A4+S*A6
                   7445:        fadd.d          EM1A3(%pc),%fp3         # fp3 IS A3+S*A5
                   7446:        mov.w           %d1,SC(%a6)             # SC is 2^(M) in extended
                   7447:        mov.l           &0x80000000,SC+4(%a6)
                   7448:        clr.l           SC+8(%a6)
                   7449:
                   7450:        fmul.x          %fp1,%fp2               # fp2 IS S*(A4+S*A6)
                   7451:        mov.l           L_SCR1(%a6),%d1         # D0 is M
                   7452:        neg.w           %d1                     # D0 is -M
                   7453:        fmul.x          %fp1,%fp3               # fp3 IS S*(A3+S*A5)
                   7454:        add.w           &0x3FFF,%d1             # biased expo. of 2^(-M)
                   7455:        fadd.d          EM1A2(%pc),%fp2         # fp2 IS A2+S*(A4+S*A6)
                   7456:        fadd.s          &0x3F000000,%fp3        # fp3 IS A1+S*(A3+S*A5)
                   7457:
                   7458:        fmul.x          %fp1,%fp2               # fp2 IS S*(A2+S*(A4+S*A6))
                   7459:        or.w            &0x8000,%d1             # signed/expo. of -2^(-M)
                   7460:        mov.w           %d1,ONEBYSC(%a6)        # OnebySc is -2^(-M)
                   7461:        mov.l           &0x80000000,ONEBYSC+4(%a6)
                   7462:        clr.l           ONEBYSC+8(%a6)
                   7463:        fmul.x          %fp3,%fp1               # fp1 IS S*(A1+S*(A3+S*A5))
                   7464:
                   7465:        fmul.x          %fp0,%fp2               # fp2 IS R*S*(A2+S*(A4+S*A6))
                   7466:        fadd.x          %fp1,%fp0               # fp0 IS R+S*(A1+S*(A3+S*A5))
                   7467:
                   7468:        fadd.x          %fp2,%fp0               # fp0 IS EXP(R)-1
                   7469:
                   7470:        fmovm.x         (%sp)+,&0x30            # fp2 restored {%fp2/%fp3}
                   7471:
                   7472: #--Step 5
                   7473: #--Compute 2^(J/64)*p
                   7474:
                   7475:        fmul.x          (%a1),%fp0              # 2^(J/64)*(Exp(R)-1)
                   7476:
                   7477: #--Step 6
                   7478: #--Step 6.1
                   7479:        mov.l           L_SCR1(%a6),%d1         # retrieve M
                   7480:        cmp.l           %d1,&63
                   7481:        ble.b           MLE63
                   7482: #--Step 6.2    M >= 64
                   7483:        fmov.s          12(%a1),%fp1            # fp1 is t
                   7484:        fadd.x          ONEBYSC(%a6),%fp1       # fp1 is t+OnebySc
                   7485:        fadd.x          %fp1,%fp0               # p+(t+OnebySc), fp1 released
                   7486:        fadd.x          (%a1),%fp0              # T+(p+(t+OnebySc))
                   7487:        bra             EM1SCALE
                   7488: MLE63:
                   7489: #--Step 6.3    M <= 63
                   7490:        cmp.l           %d1,&-3
                   7491:        bge.b           MGEN3
                   7492: MLTN3:
                   7493: #--Step 6.4    M <= -4
                   7494:        fadd.s          12(%a1),%fp0            # p+t
                   7495:        fadd.x          (%a1),%fp0              # T+(p+t)
                   7496:        fadd.x          ONEBYSC(%a6),%fp0       # OnebySc + (T+(p+t))
                   7497:        bra             EM1SCALE
                   7498: MGEN3:
                   7499: #--Step 6.5    -3 <= M <= 63
                   7500:        fmov.x          (%a1)+,%fp1             # fp1 is T
                   7501:        fadd.s          (%a1),%fp0              # fp0 is p+t
                   7502:        fadd.x          ONEBYSC(%a6),%fp1       # fp1 is T+OnebySc
                   7503:        fadd.x          %fp1,%fp0               # (T+OnebySc)+(p+t)
                   7504:
                   7505: EM1SCALE:
                   7506: #--Step 6.6
                   7507:        fmov.l          %d0,%fpcr
                   7508:        fmul.x          SC(%a6),%fp0
                   7509:        bra             t_inx2
                   7510:
                   7511: EM1SM:
                   7512: #--Step 7      |X| < 1/4.
                   7513:        cmp.l           %d1,&0x3FBE0000         # 2^(-65)
                   7514:        bge.b           EM1POLY
                   7515:
                   7516: EM1TINY:
                   7517: #--Step 8      |X| < 2^(-65)
                   7518:        cmp.l           %d1,&0x00330000         # 2^(-16312)
                   7519:        blt.b           EM12TINY
                   7520: #--Step 8.2
                   7521:        mov.l           &0x80010000,SC(%a6)     # SC is -2^(-16382)
                   7522:        mov.l           &0x80000000,SC+4(%a6)
                   7523:        clr.l           SC+8(%a6)
                   7524:        fmov.x          (%a0),%fp0
                   7525:        fmov.l          %d0,%fpcr
                   7526:        mov.b           &FADD_OP,%d1            # last inst is ADD
                   7527:        fadd.x          SC(%a6),%fp0
                   7528:        bra             t_catch
                   7529:
                   7530: EM12TINY:
                   7531: #--Step 8.3
                   7532:        fmov.x          (%a0),%fp0
                   7533:        fmul.d          TWO140(%pc),%fp0
                   7534:        mov.l           &0x80010000,SC(%a6)
                   7535:        mov.l           &0x80000000,SC+4(%a6)
                   7536:        clr.l           SC+8(%a6)
                   7537:        fadd.x          SC(%a6),%fp0
                   7538:        fmov.l          %d0,%fpcr
                   7539:        mov.b           &FMUL_OP,%d1            # last inst is MUL
                   7540:        fmul.d          TWON140(%pc),%fp0
                   7541:        bra             t_catch
                   7542:
                   7543: EM1POLY:
                   7544: #--Step 9      exp(X)-1 by a simple polynomial
                   7545:        fmov.x          (%a0),%fp0              # fp0 is X
                   7546:        fmul.x          %fp0,%fp0               # fp0 is S := X*X
                   7547:        fmovm.x         &0xc,-(%sp)             # save fp2 {%fp2/%fp3}
                   7548:        fmov.s          &0x2F30CAA8,%fp1        # fp1 is B12
                   7549:        fmul.x          %fp0,%fp1               # fp1 is S*B12
                   7550:        fmov.s          &0x310F8290,%fp2        # fp2 is B11
                   7551:        fadd.s          &0x32D73220,%fp1        # fp1 is B10+S*B12
                   7552:
                   7553:        fmul.x          %fp0,%fp2               # fp2 is S*B11
                   7554:        fmul.x          %fp0,%fp1               # fp1 is S*(B10 + ...
                   7555:
                   7556:        fadd.s          &0x3493F281,%fp2        # fp2 is B9+S*...
                   7557:        fadd.d          EM1B8(%pc),%fp1         # fp1 is B8+S*...
                   7558:
                   7559:        fmul.x          %fp0,%fp2               # fp2 is S*(B9+...
                   7560:        fmul.x          %fp0,%fp1               # fp1 is S*(B8+...
                   7561:
                   7562:        fadd.d          EM1B7(%pc),%fp2         # fp2 is B7+S*...
                   7563:        fadd.d          EM1B6(%pc),%fp1         # fp1 is B6+S*...
                   7564:
                   7565:        fmul.x          %fp0,%fp2               # fp2 is S*(B7+...
                   7566:        fmul.x          %fp0,%fp1               # fp1 is S*(B6+...
                   7567:
                   7568:        fadd.d          EM1B5(%pc),%fp2         # fp2 is B5+S*...
                   7569:        fadd.d          EM1B4(%pc),%fp1         # fp1 is B4+S*...
                   7570:
                   7571:        fmul.x          %fp0,%fp2               # fp2 is S*(B5+...
                   7572:        fmul.x          %fp0,%fp1               # fp1 is S*(B4+...
                   7573:
                   7574:        fadd.d          EM1B3(%pc),%fp2         # fp2 is B3+S*...
                   7575:        fadd.x          EM1B2(%pc),%fp1         # fp1 is B2+S*...
                   7576:
                   7577:        fmul.x          %fp0,%fp2               # fp2 is S*(B3+...
                   7578:        fmul.x          %fp0,%fp1               # fp1 is S*(B2+...
                   7579:
                   7580:        fmul.x          %fp0,%fp2               # fp2 is S*S*(B3+...)
                   7581:        fmul.x          (%a0),%fp1              # fp1 is X*S*(B2...
                   7582:
                   7583:        fmul.s          &0x3F000000,%fp0        # fp0 is S*B1
                   7584:        fadd.x          %fp2,%fp1               # fp1 is Q
                   7585:
                   7586:        fmovm.x         (%sp)+,&0x30            # fp2 restored {%fp2/%fp3}
                   7587:
                   7588:        fadd.x          %fp1,%fp0               # fp0 is S*B1+Q
                   7589:
                   7590:        fmov.l          %d0,%fpcr
                   7591:        fadd.x          (%a0),%fp0
                   7592:        bra             t_inx2
                   7593:
                   7594: EM1BIG:
                   7595: #--Step 10     |X| > 70 log2
                   7596:        mov.l           (%a0),%d1
                   7597:        cmp.l           %d1,&0
                   7598:        bgt.w           EXPC1
                   7599: #--Step 10.2
                   7600:        fmov.s          &0xBF800000,%fp0        # fp0 is -1
                   7601:        fmov.l          %d0,%fpcr
                   7602:        fadd.s          &0x00800000,%fp0        # -1 + 2^(-126)
                   7603:        bra             t_minx2
                   7604:
                   7605:        global          setoxm1d
                   7606: setoxm1d:
                   7607: #--entry point for EXPM1(X), here X is denormalized
                   7608: #--Step 0.
                   7609:        bra             t_extdnrm
                   7610:
                   7611: #########################################################################
                   7612: # sgetexp():  returns the exponent portion of the input argument.      #
                   7613: #            The exponent bias is removed and the exponent value is    #
                   7614: #            returned as an extended precision number in fp0.          #
                   7615: # sgetexpd(): handles denormalized numbers.                            #
                   7616: #                                                                      #
                   7617: # sgetman():  extracts the mantissa of the input argument. The                 #
                   7618: #            mantissa is converted to an extended precision number w/  #
                   7619: #            an exponent of $3fff and is returned in fp0. The range of #
                   7620: #            the result is [1.0 - 2.0).                                #
                   7621: # sgetmand(): handles denormalized numbers.                            #
                   7622: #                                                                      #
                   7623: # INPUT *************************************************************** #
                   7624: #      a0  = pointer to extended precision input                       #
                   7625: #                                                                      #
                   7626: # OUTPUT ************************************************************** #
                   7627: #      fp0 = exponent(X) or mantissa(X)                                #
                   7628: #                                                                      #
                   7629: #########################################################################
                   7630:
                   7631:        global          sgetexp
                   7632: sgetexp:
                   7633:        mov.w           SRC_EX(%a0),%d0         # get the exponent
                   7634:        bclr            &0xf,%d0                # clear the sign bit
                   7635:        subi.w          &0x3fff,%d0             # subtract off the bias
                   7636:        fmov.w          %d0,%fp0                # return exp in fp0
                   7637:        blt.b           sgetexpn                # it's negative
                   7638:        rts
                   7639:
                   7640: sgetexpn:
                   7641:        mov.b           &neg_bmask,FPSR_CC(%a6) # set 'N' ccode bit
                   7642:        rts
                   7643:
                   7644:        global          sgetexpd
                   7645: sgetexpd:
                   7646:        bsr.l           norm                    # normalize
                   7647:        neg.w           %d0                     # new exp = -(shft amt)
                   7648:        subi.w          &0x3fff,%d0             # subtract off the bias
                   7649:        fmov.w          %d0,%fp0                # return exp in fp0
                   7650:        mov.b           &neg_bmask,FPSR_CC(%a6) # set 'N' ccode bit
                   7651:        rts
                   7652:
                   7653:        global          sgetman
                   7654: sgetman:
                   7655:        mov.w           SRC_EX(%a0),%d0         # get the exp
                   7656:        ori.w           &0x7fff,%d0             # clear old exp
                   7657:        bclr            &0xe,%d0                # make it the new exp +-3fff
                   7658:
                   7659: # here, we build the result in a tmp location so as not to disturb the input
                   7660:        mov.l           SRC_HI(%a0),FP_SCR0_HI(%a6) # copy to tmp loc
                   7661:        mov.l           SRC_LO(%a0),FP_SCR0_LO(%a6) # copy to tmp loc
                   7662:        mov.w           %d0,FP_SCR0_EX(%a6)     # insert new exponent
                   7663:        fmov.x          FP_SCR0(%a6),%fp0       # put new value back in fp0
                   7664:        bmi.b           sgetmann                # it's negative
                   7665:        rts
                   7666:
                   7667: sgetmann:
                   7668:        mov.b           &neg_bmask,FPSR_CC(%a6) # set 'N' ccode bit
                   7669:        rts
                   7670:
                   7671: #
                   7672: # For denormalized numbers, shift the mantissa until the j-bit = 1,
                   7673: # then load the exponent with +/1 $3fff.
                   7674: #
                   7675:        global          sgetmand
                   7676: sgetmand:
                   7677:        bsr.l           norm                    # normalize exponent
                   7678:        bra.b           sgetman
                   7679:
                   7680: #########################################################################
                   7681: # scosh():  computes the hyperbolic cosine of a normalized input       #
                   7682: # scoshd(): computes the hyperbolic cosine of a denormalized input     #
                   7683: #                                                                      #
                   7684: # INPUT ***************************************************************        #
                   7685: #      a0 = pointer to extended precision input                        #
                   7686: #      d0 = round precision,mode                                       #
                   7687: #                                                                      #
                   7688: # OUTPUT **************************************************************        #
                   7689: #      fp0 = cosh(X)                                                   #
                   7690: #                                                                      #
                   7691: # ACCURACY and MONOTONICITY *******************************************        #
                   7692: #      The returned result is within 3 ulps in 64 significant bit,     #
                   7693: #      i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
                   7694: #      rounded to double precision. The result is provably monotonic   #
                   7695: #      in double precision.                                            #
                   7696: #                                                                      #
                   7697: # ALGORITHM ***********************************************************        #
                   7698: #                                                                      #
                   7699: #      COSH                                                            #
                   7700: #      1. If |X| > 16380 log2, go to 3.                                #
                   7701: #                                                                      #
                   7702: #      2. (|X| <= 16380 log2) Cosh(X) is obtained by the formulae      #
                   7703: #              y = |X|, z = exp(Y), and                                #
                   7704: #              cosh(X) = (1/2)*( z + 1/z ).                            #
                   7705: #              Exit.                                                   #
                   7706: #                                                                      #
                   7707: #      3. (|X| > 16380 log2). If |X| > 16480 log2, go to 5.            #
                   7708: #                                                                      #
                   7709: #      4. (16380 log2 < |X| <= 16480 log2)                             #
                   7710: #              cosh(X) = sign(X) * exp(|X|)/2.                         #
                   7711: #              However, invoking exp(|X|) may cause premature          #
                   7712: #              overflow. Thus, we calculate sinh(X) as follows:        #
                   7713: #              Y       := |X|                                          #
                   7714: #              Fact    :=      2**(16380)                              #
                   7715: #              Y'      := Y - 16381 log2                               #
                   7716: #              cosh(X) := Fact * exp(Y').                              #
                   7717: #              Exit.                                                   #
                   7718: #                                                                      #
                   7719: #      5. (|X| > 16480 log2) sinh(X) must overflow. Return             #
                   7720: #              Huge*Huge to generate overflow and an infinity with     #
                   7721: #              the appropriate sign. Huge is the largest finite number #
                   7722: #              in extended format. Exit.                               #
                   7723: #                                                                      #
                   7724: #########################################################################
                   7725:
                   7726: TWO16380:
                   7727:        long            0x7FFB0000,0x80000000,0x00000000,0x00000000
                   7728:
                   7729:        global          scosh
                   7730: scosh:
                   7731:        fmov.x          (%a0),%fp0              # LOAD INPUT
                   7732:
                   7733:        mov.l           (%a0),%d1
                   7734:        mov.w           4(%a0),%d1
                   7735:        and.l           &0x7FFFFFFF,%d1
                   7736:        cmp.l           %d1,&0x400CB167
                   7737:        bgt.b           COSHBIG
                   7738:
                   7739: #--THIS IS THE USUAL CASE, |X| < 16380 LOG2
                   7740: #--COSH(X) = (1/2) * ( EXP(X) + 1/EXP(X) )
                   7741:
                   7742:        fabs.x          %fp0                    # |X|
                   7743:
                   7744:        mov.l           %d0,-(%sp)
                   7745:        clr.l           %d0
                   7746:        fmovm.x         &0x01,-(%sp)            # save |X| to stack
                   7747:        lea             (%sp),%a0               # pass ptr to |X|
                   7748:        bsr             setox                   # FP0 IS EXP(|X|)
                   7749:        add.l           &0xc,%sp                # erase |X| from stack
                   7750:        fmul.s          &0x3F000000,%fp0        # (1/2)EXP(|X|)
                   7751:        mov.l           (%sp)+,%d0
                   7752:
                   7753:        fmov.s          &0x3E800000,%fp1        # (1/4)
                   7754:        fdiv.x          %fp0,%fp1               # 1/(2 EXP(|X|))
                   7755:
                   7756:        fmov.l          %d0,%fpcr
                   7757:        mov.b           &FADD_OP,%d1            # last inst is ADD
                   7758:        fadd.x          %fp1,%fp0
                   7759:        bra             t_catch
                   7760:
                   7761: COSHBIG:
                   7762:        cmp.l           %d1,&0x400CB2B3
                   7763:        bgt.b           COSHHUGE
                   7764:
                   7765:        fabs.x          %fp0
                   7766:        fsub.d          T1(%pc),%fp0            # (|X|-16381LOG2_LEAD)
                   7767:        fsub.d          T2(%pc),%fp0            # |X| - 16381 LOG2, ACCURATE
                   7768:
                   7769:        mov.l           %d0,-(%sp)
                   7770:        clr.l           %d0
                   7771:        fmovm.x         &0x01,-(%sp)            # save fp0 to stack
                   7772:        lea             (%sp),%a0               # pass ptr to fp0
                   7773:        bsr             setox
                   7774:        add.l           &0xc,%sp                # clear fp0 from stack
                   7775:        mov.l           (%sp)+,%d0
                   7776:
                   7777:        fmov.l          %d0,%fpcr
                   7778:        mov.b           &FMUL_OP,%d1            # last inst is MUL
                   7779:        fmul.x          TWO16380(%pc),%fp0
                   7780:        bra             t_catch
                   7781:
                   7782: COSHHUGE:
                   7783:        bra             t_ovfl2
                   7784:
                   7785:        global          scoshd
                   7786: #--COSH(X) = 1 FOR DENORMALIZED X
                   7787: scoshd:
                   7788:        fmov.s          &0x3F800000,%fp0
                   7789:
                   7790:        fmov.l          %d0,%fpcr
                   7791:        fadd.s          &0x00800000,%fp0
                   7792:        bra             t_pinx2
                   7793:
                   7794: #########################################################################
                   7795: # ssinh():  computes the hyperbolic sine of a normalized input         #
                   7796: # ssinhd(): computes the hyperbolic sine of a denormalized input       #
                   7797: #                                                                      #
                   7798: # INPUT *************************************************************** #
                   7799: #      a0 = pointer to extended precision input                        #
                   7800: #      d0 = round precision,mode                                       #
                   7801: #                                                                      #
                   7802: # OUTPUT ************************************************************** #
                   7803: #      fp0 = sinh(X)                                                   #
                   7804: #                                                                      #
                   7805: # ACCURACY and MONOTONICITY *******************************************        #
                   7806: #      The returned result is within 3 ulps in 64 significant bit,     #
                   7807: #      i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
                   7808: #      rounded to double precision. The result is provably monotonic   #
                   7809: #      in double precision.                                            #
                   7810: #                                                                      #
                   7811: # ALGORITHM *********************************************************** #
                   7812: #                                                                      #
                   7813: #       SINH                                                           #
                   7814: #       1. If |X| > 16380 log2, go to 3.                               #
                   7815: #                                                                      #
                   7816: #       2. (|X| <= 16380 log2) Sinh(X) is obtained by the formula      #
                   7817: #               y = |X|, sgn = sign(X), and z = expm1(Y),              #
                   7818: #               sinh(X) = sgn*(1/2)*( z + z/(1+z) ).                   #
                   7819: #          Exit.                                                       #
                   7820: #                                                                      #
                   7821: #       3. If |X| > 16480 log2, go to 5.                               #
                   7822: #                                                                      #
                   7823: #       4. (16380 log2 < |X| <= 16480 log2)                            #
                   7824: #               sinh(X) = sign(X) * exp(|X|)/2.                                #
                   7825: #          However, invoking exp(|X|) may cause premature overflow.    #
                   7826: #          Thus, we calculate sinh(X) as follows:                      #
                   7827: #             Y       := |X|                                           #
                   7828: #             sgn     := sign(X)                                       #
                   7829: #             sgnFact := sgn * 2**(16380)                              #
                   7830: #             Y'      := Y - 16381 log2                                        #
                   7831: #             sinh(X) := sgnFact * exp(Y').                            #
                   7832: #          Exit.                                                       #
                   7833: #                                                                      #
                   7834: #       5. (|X| > 16480 log2) sinh(X) must overflow. Return            #
                   7835: #          sign(X)*Huge*Huge to generate overflow and an infinity with #
                   7836: #          the appropriate sign. Huge is the largest finite number in  #
                   7837: #          extended format. Exit.                                      #
                   7838: #                                                                      #
                   7839: #########################################################################
                   7840:
                   7841:        global          ssinh
                   7842: ssinh:
                   7843:        fmov.x          (%a0),%fp0              # LOAD INPUT
                   7844:
                   7845:        mov.l           (%a0),%d1
                   7846:        mov.w           4(%a0),%d1
                   7847:        mov.l           %d1,%a1                 # save (compacted) operand
                   7848:        and.l           &0x7FFFFFFF,%d1
                   7849:        cmp.l           %d1,&0x400CB167
                   7850:        bgt.b           SINHBIG
                   7851:
                   7852: #--THIS IS THE USUAL CASE, |X| < 16380 LOG2
                   7853: #--Y = |X|, Z = EXPM1(Y), SINH(X) = SIGN(X)*(1/2)*( Z + Z/(1+Z) )
                   7854:
                   7855:        fabs.x          %fp0                    # Y = |X|
                   7856:
                   7857:        movm.l          &0x8040,-(%sp)          # {a1/d0}
                   7858:        fmovm.x         &0x01,-(%sp)            # save Y on stack
                   7859:        lea             (%sp),%a0               # pass ptr to Y
                   7860:        clr.l           %d0
                   7861:        bsr             setoxm1                 # FP0 IS Z = EXPM1(Y)
                   7862:        add.l           &0xc,%sp                # clear Y from stack
                   7863:        fmov.l          &0,%fpcr
                   7864:        movm.l          (%sp)+,&0x0201          # {a1/d0}
                   7865:
                   7866:        fmov.x          %fp0,%fp1
                   7867:        fadd.s          &0x3F800000,%fp1        # 1+Z
                   7868:        fmov.x          %fp0,-(%sp)
                   7869:        fdiv.x          %fp1,%fp0               # Z/(1+Z)
                   7870:        mov.l           %a1,%d1
                   7871:        and.l           &0x80000000,%d1
                   7872:        or.l            &0x3F000000,%d1
                   7873:        fadd.x          (%sp)+,%fp0
                   7874:        mov.l           %d1,-(%sp)
                   7875:
                   7876:        fmov.l          %d0,%fpcr
                   7877:        mov.b           &FMUL_OP,%d1            # last inst is MUL
                   7878:        fmul.s          (%sp)+,%fp0             # last fp inst - possible exceptions set
                   7879:        bra             t_catch
                   7880:
                   7881: SINHBIG:
                   7882:        cmp.l           %d1,&0x400CB2B3
                   7883:        bgt             t_ovfl
                   7884:        fabs.x          %fp0
                   7885:        fsub.d          T1(%pc),%fp0            # (|X|-16381LOG2_LEAD)
                   7886:        mov.l           &0,-(%sp)
                   7887:        mov.l           &0x80000000,-(%sp)
                   7888:        mov.l           %a1,%d1
                   7889:        and.l           &0x80000000,%d1
                   7890:        or.l            &0x7FFB0000,%d1
                   7891:        mov.l           %d1,-(%sp)              # EXTENDED FMT
                   7892:        fsub.d          T2(%pc),%fp0            # |X| - 16381 LOG2, ACCURATE
                   7893:
                   7894:        mov.l           %d0,-(%sp)
                   7895:        clr.l           %d0
                   7896:        fmovm.x         &0x01,-(%sp)            # save fp0 on stack
                   7897:        lea             (%sp),%a0               # pass ptr to fp0
                   7898:        bsr             setox
                   7899:        add.l           &0xc,%sp                # clear fp0 from stack
                   7900:
                   7901:        mov.l           (%sp)+,%d0
                   7902:        fmov.l          %d0,%fpcr
                   7903:        mov.b           &FMUL_OP,%d1            # last inst is MUL
                   7904:        fmul.x          (%sp)+,%fp0             # possible exception
                   7905:        bra             t_catch
                   7906:
                   7907:        global          ssinhd
                   7908: #--SINH(X) = X FOR DENORMALIZED X
                   7909: ssinhd:
                   7910:        bra             t_extdnrm
                   7911:
                   7912: #########################################################################
                   7913: # stanh():  computes the hyperbolic tangent of a normalized input      #
                   7914: # stanhd(): computes the hyperbolic tangent of a denormalized input    #
                   7915: #                                                                      #
                   7916: # INPUT ***************************************************************        #
                   7917: #      a0 = pointer to extended precision input                        #
                   7918: #      d0 = round precision,mode                                       #
                   7919: #                                                                      #
                   7920: # OUTPUT **************************************************************        #
                   7921: #      fp0 = tanh(X)                                                   #
                   7922: #                                                                      #
                   7923: # ACCURACY and MONOTONICITY *******************************************        #
                   7924: #      The returned result is within 3 ulps in 64 significant bit,     #
                   7925: #      i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
                   7926: #      rounded to double precision. The result is provably monotonic   #
                   7927: #      in double precision.                                            #
                   7928: #                                                                      #
                   7929: # ALGORITHM ***********************************************************        #
                   7930: #                                                                      #
                   7931: #      TANH                                                            #
                   7932: #      1. If |X| >= (5/2) log2 or |X| <= 2**(-40), go to 3.            #
                   7933: #                                                                      #
                   7934: #      2. (2**(-40) < |X| < (5/2) log2) Calculate tanh(X) by           #
                   7935: #              sgn := sign(X), y := 2|X|, z := expm1(Y), and           #
                   7936: #              tanh(X) = sgn*( z/(2+z) ).                              #
                   7937: #              Exit.                                                   #
                   7938: #                                                                      #
                   7939: #      3. (|X| <= 2**(-40) or |X| >= (5/2) log2). If |X| < 1,          #
                   7940: #              go to 7.                                                #
                   7941: #                                                                      #
                   7942: #      4. (|X| >= (5/2) log2) If |X| >= 50 log2, go to 6.              #
                   7943: #                                                                      #
                   7944: #      5. ((5/2) log2 <= |X| < 50 log2) Calculate tanh(X) by           #
                   7945: #              sgn := sign(X), y := 2|X|, z := exp(Y),                 #
                   7946: #              tanh(X) = sgn - [ sgn*2/(1+z) ].                        #
                   7947: #              Exit.                                                   #
                   7948: #                                                                      #
                   7949: #      6. (|X| >= 50 log2) Tanh(X) = +-1 (round to nearest). Thus, we  #
                   7950: #              calculate Tanh(X) by                                    #
                   7951: #              sgn := sign(X), Tiny := 2**(-126),                      #
                   7952: #              tanh(X) := sgn - sgn*Tiny.                              #
                   7953: #              Exit.                                                   #
                   7954: #                                                                      #
                   7955: #      7. (|X| < 2**(-40)). Tanh(X) = X.       Exit.                   #
                   7956: #                                                                      #
                   7957: #########################################################################
                   7958:
                   7959:        set             X,FP_SCR0
                   7960:        set             XFRAC,X+4
                   7961:
                   7962:        set             SGN,L_SCR3
                   7963:
                   7964:        set             V,FP_SCR0
                   7965:
                   7966:        global          stanh
                   7967: stanh:
                   7968:        fmov.x          (%a0),%fp0              # LOAD INPUT
                   7969:
                   7970:        fmov.x          %fp0,X(%a6)
                   7971:        mov.l           (%a0),%d1
                   7972:        mov.w           4(%a0),%d1
                   7973:        mov.l           %d1,X(%a6)
                   7974:        and.l           &0x7FFFFFFF,%d1
                   7975:        cmp.l           %d1, &0x3fd78000        # is |X| < 2^(-40)?
                   7976:        blt.w           TANHBORS                # yes
                   7977:        cmp.l           %d1, &0x3fffddce        # is |X| > (5/2)LOG2?
                   7978:        bgt.w           TANHBORS                # yes
                   7979:
                   7980: #--THIS IS THE USUAL CASE
                   7981: #--Y = 2|X|, Z = EXPM1(Y), TANH(X) = SIGN(X) * Z / (Z+2).
                   7982:
                   7983:        mov.l           X(%a6),%d1
                   7984:        mov.l           %d1,SGN(%a6)
                   7985:        and.l           &0x7FFF0000,%d1
                   7986:        add.l           &0x00010000,%d1         # EXPONENT OF 2|X|
                   7987:        mov.l           %d1,X(%a6)
                   7988:        and.l           &0x80000000,SGN(%a6)
                   7989:        fmov.x          X(%a6),%fp0             # FP0 IS Y = 2|X|
                   7990:
                   7991:        mov.l           %d0,-(%sp)
                   7992:        clr.l           %d0
                   7993:        fmovm.x         &0x1,-(%sp)             # save Y on stack
                   7994:        lea             (%sp),%a0               # pass ptr to Y
                   7995:        bsr             setoxm1                 # FP0 IS Z = EXPM1(Y)
                   7996:        add.l           &0xc,%sp                # clear Y from stack
                   7997:        mov.l           (%sp)+,%d0
                   7998:
                   7999:        fmov.x          %fp0,%fp1
                   8000:        fadd.s          &0x40000000,%fp1        # Z+2
                   8001:        mov.l           SGN(%a6),%d1
                   8002:        fmov.x          %fp1,V(%a6)
                   8003:        eor.l           %d1,V(%a6)
                   8004:
                   8005:        fmov.l          %d0,%fpcr               # restore users round prec,mode
                   8006:        fdiv.x          V(%a6),%fp0
                   8007:        bra             t_inx2
                   8008:
                   8009: TANHBORS:
                   8010:        cmp.l           %d1,&0x3FFF8000
                   8011:        blt.w           TANHSM
                   8012:
                   8013:        cmp.l           %d1,&0x40048AA1
                   8014:        bgt.w           TANHHUGE
                   8015:
                   8016: #-- (5/2) LOG2 < |X| < 50 LOG2,
                   8017: #--TANH(X) = 1 - (2/[EXP(2X)+1]). LET Y = 2|X|, SGN = SIGN(X),
                   8018: #--TANH(X) = SGN -     SGN*2/[EXP(Y)+1].
                   8019:
                   8020:        mov.l           X(%a6),%d1
                   8021:        mov.l           %d1,SGN(%a6)
                   8022:        and.l           &0x7FFF0000,%d1
                   8023:        add.l           &0x00010000,%d1         # EXPO OF 2|X|
                   8024:        mov.l           %d1,X(%a6)              # Y = 2|X|
                   8025:        and.l           &0x80000000,SGN(%a6)
                   8026:        mov.l           SGN(%a6),%d1
                   8027:        fmov.x          X(%a6),%fp0             # Y = 2|X|
                   8028:
                   8029:        mov.l           %d0,-(%sp)
                   8030:        clr.l           %d0
                   8031:        fmovm.x         &0x01,-(%sp)            # save Y on stack
                   8032:        lea             (%sp),%a0               # pass ptr to Y
                   8033:        bsr             setox                   # FP0 IS EXP(Y)
                   8034:        add.l           &0xc,%sp                # clear Y from stack
                   8035:        mov.l           (%sp)+,%d0
                   8036:        mov.l           SGN(%a6),%d1
                   8037:        fadd.s          &0x3F800000,%fp0        # EXP(Y)+1
                   8038:
                   8039:        eor.l           &0xC0000000,%d1         # -SIGN(X)*2
                   8040:        fmov.s          %d1,%fp1                # -SIGN(X)*2 IN SGL FMT
                   8041:        fdiv.x          %fp0,%fp1               # -SIGN(X)2 / [EXP(Y)+1 ]
                   8042:
                   8043:        mov.l           SGN(%a6),%d1
                   8044:        or.l            &0x3F800000,%d1         # SGN
                   8045:        fmov.s          %d1,%fp0                # SGN IN SGL FMT
                   8046:
                   8047:        fmov.l          %d0,%fpcr               # restore users round prec,mode
                   8048:        mov.b           &FADD_OP,%d1            # last inst is ADD
                   8049:        fadd.x          %fp1,%fp0
                   8050:        bra             t_inx2
                   8051:
                   8052: TANHSM:
                   8053:        fmov.l          %d0,%fpcr               # restore users round prec,mode
                   8054:        mov.b           &FMOV_OP,%d1            # last inst is MOVE
                   8055:        fmov.x          X(%a6),%fp0             # last inst - possible exception set
                   8056:        bra             t_catch
                   8057:
                   8058: #---RETURN SGN(X) - SGN(X)EPS
                   8059: TANHHUGE:
                   8060:        mov.l           X(%a6),%d1
                   8061:        and.l           &0x80000000,%d1
                   8062:        or.l            &0x3F800000,%d1
                   8063:        fmov.s          %d1,%fp0
                   8064:        and.l           &0x80000000,%d1
                   8065:        eor.l           &0x80800000,%d1         # -SIGN(X)*EPS
                   8066:
                   8067:        fmov.l          %d0,%fpcr               # restore users round prec,mode
                   8068:        fadd.s          %d1,%fp0
                   8069:        bra             t_inx2
                   8070:
                   8071:        global          stanhd
                   8072: #--TANH(X) = X FOR DENORMALIZED X
                   8073: stanhd:
                   8074:        bra             t_extdnrm
                   8075:
                   8076: #########################################################################
                   8077: # slogn():    computes the natural logarithm of a normalized input     #
                   8078: # slognd():   computes the natural logarithm of a denormalized input   #
                   8079: # slognp1():  computes the log(1+X) of a normalized input              #
                   8080: # slognp1d(): computes the log(1+X) of a denormalized input            #
                   8081: #                                                                      #
                   8082: # INPUT ***************************************************************        #
                   8083: #      a0 = pointer to extended precision input                        #
                   8084: #      d0 = round precision,mode                                       #
                   8085: #                                                                      #
                   8086: # OUTPUT **************************************************************        #
                   8087: #      fp0 = log(X) or log(1+X)                                        #
                   8088: #                                                                      #
                   8089: # ACCURACY and MONOTONICITY *******************************************        #
                   8090: #      The returned result is within 2 ulps in 64 significant bit,     #
                   8091: #      i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
                   8092: #      rounded to double precision. The result is provably monotonic   #
                   8093: #      in double precision.                                            #
                   8094: #                                                                      #
                   8095: # ALGORITHM ***********************************************************        #
                   8096: #      LOGN:                                                           #
                   8097: #      Step 1. If |X-1| < 1/16, approximate log(X) by an odd           #
                   8098: #              polynomial in u, where u = 2(X-1)/(X+1). Otherwise,     #
                   8099: #              move on to Step 2.                                      #
                   8100: #                                                                      #
                   8101: #      Step 2. X = 2**k * Y where 1 <= Y < 2. Define F to be the first #
                   8102: #              seven significant bits of Y plus 2**(-7), i.e.          #
                   8103: #              F = 1.xxxxxx1 in base 2 where the six "x" match those   #
                   8104: #              of Y. Note that |Y-F| <= 2**(-7).                       #
                   8105: #                                                                      #
                   8106: #      Step 3. Define u = (Y-F)/F. Approximate log(1+u) by a           #
                   8107: #              polynomial in u, log(1+u) = poly.                       #
                   8108: #                                                                      #
                   8109: #      Step 4. Reconstruct                                             #
                   8110: #              log(X) = log( 2**k * Y ) = k*log(2) + log(F) + log(1+u) #
                   8111: #              by k*log(2) + (log(F) + poly). The values of log(F) are #
                   8112: #              calculated beforehand and stored in the program.        #
                   8113: #                                                                      #
                   8114: #      lognp1:                                                         #
                   8115: #      Step 1: If |X| < 1/16, approximate log(1+X) by an odd           #
                   8116: #              polynomial in u where u = 2X/(2+X). Otherwise, move on  #
                   8117: #              to Step 2.                                              #
                   8118: #                                                                      #
                   8119: #      Step 2: Let 1+X = 2**k * Y, where 1 <= Y < 2. Define F as done  #
                   8120: #              in Step 2 of the algorithm for LOGN and compute         #
                   8121: #              log(1+X) as k*log(2) + log(F) + poly where poly         #
                   8122: #              approximates log(1+u), u = (Y-F)/F.                     #
                   8123: #                                                                      #
                   8124: #      Implementation Notes:                                           #
                   8125: #      Note 1. There are 64 different possible values for F, thus 64   #
                   8126: #              log(F)'s need to be tabulated. Moreover, the values of  #
                   8127: #              1/F are also tabulated so that the division in (Y-F)/F  #
                   8128: #              can be performed by a multiplication.                   #
                   8129: #                                                                      #
                   8130: #      Note 2. In Step 2 of lognp1, in order to preserved accuracy,    #
                   8131: #              the value Y-F has to be calculated carefully when       #
                   8132: #              1/2 <= X < 3/2.                                         #
                   8133: #                                                                      #
                   8134: #      Note 3. To fully exploit the pipeline, polynomials are usually  #
                   8135: #              separated into two parts evaluated independently before #
                   8136: #              being added up.                                         #
                   8137: #                                                                      #
                   8138: #########################################################################
                   8139: LOGOF2:
                   8140:        long            0x3FFE0000,0xB17217F7,0xD1CF79AC,0x00000000
                   8141:
                   8142: one:
                   8143:        long            0x3F800000
                   8144: zero:
                   8145:        long            0x00000000
                   8146: infty:
                   8147:        long            0x7F800000
                   8148: negone:
                   8149:        long            0xBF800000
                   8150:
                   8151: LOGA6:
                   8152:        long            0x3FC2499A,0xB5E4040B
                   8153: LOGA5:
                   8154:        long            0xBFC555B5,0x848CB7DB
                   8155:
                   8156: LOGA4:
                   8157:        long            0x3FC99999,0x987D8730
                   8158: LOGA3:
                   8159:        long            0xBFCFFFFF,0xFF6F7E97
                   8160:
                   8161: LOGA2:
                   8162:        long            0x3FD55555,0x555555A4
                   8163: LOGA1:
                   8164:        long            0xBFE00000,0x00000008
                   8165:
                   8166: LOGB5:
                   8167:        long            0x3F175496,0xADD7DAD6
                   8168: LOGB4:
                   8169:        long            0x3F3C71C2,0xFE80C7E0
                   8170:
                   8171: LOGB3:
                   8172:        long            0x3F624924,0x928BCCFF
                   8173: LOGB2:
                   8174:        long            0x3F899999,0x999995EC
                   8175:
                   8176: LOGB1:
                   8177:        long            0x3FB55555,0x55555555
                   8178: TWO:
                   8179:        long            0x40000000,0x00000000
                   8180:
                   8181: LTHOLD:
                   8182:        long            0x3f990000,0x80000000,0x00000000,0x00000000
                   8183:
                   8184: LOGTBL:
                   8185:        long            0x3FFE0000,0xFE03F80F,0xE03F80FE,0x00000000
                   8186:        long            0x3FF70000,0xFF015358,0x833C47E2,0x00000000
                   8187:        long            0x3FFE0000,0xFA232CF2,0x52138AC0,0x00000000
                   8188:        long            0x3FF90000,0xBDC8D83E,0xAD88D549,0x00000000
                   8189:        long            0x3FFE0000,0xF6603D98,0x0F6603DA,0x00000000
                   8190:        long            0x3FFA0000,0x9CF43DCF,0xF5EAFD48,0x00000000
                   8191:        long            0x3FFE0000,0xF2B9D648,0x0F2B9D65,0x00000000
                   8192:        long            0x3FFA0000,0xDA16EB88,0xCB8DF614,0x00000000
                   8193:        long            0x3FFE0000,0xEF2EB71F,0xC4345238,0x00000000
                   8194:        long            0x3FFB0000,0x8B29B775,0x1BD70743,0x00000000
                   8195:        long            0x3FFE0000,0xEBBDB2A5,0xC1619C8C,0x00000000
                   8196:        long            0x3FFB0000,0xA8D839F8,0x30C1FB49,0x00000000
                   8197:        long            0x3FFE0000,0xE865AC7B,0x7603A197,0x00000000
                   8198:        long            0x3FFB0000,0xC61A2EB1,0x8CD907AD,0x00000000
                   8199:        long            0x3FFE0000,0xE525982A,0xF70C880E,0x00000000
                   8200:        long            0x3FFB0000,0xE2F2A47A,0xDE3A18AF,0x00000000
                   8201:        long            0x3FFE0000,0xE1FC780E,0x1FC780E2,0x00000000
                   8202:        long            0x3FFB0000,0xFF64898E,0xDF55D551,0x00000000
                   8203:        long            0x3FFE0000,0xDEE95C4C,0xA037BA57,0x00000000
                   8204:        long            0x3FFC0000,0x8DB956A9,0x7B3D0148,0x00000000
                   8205:        long            0x3FFE0000,0xDBEB61EE,0xD19C5958,0x00000000
                   8206:        long            0x3FFC0000,0x9B8FE100,0xF47BA1DE,0x00000000
                   8207:        long            0x3FFE0000,0xD901B203,0x6406C80E,0x00000000
                   8208:        long            0x3FFC0000,0xA9372F1D,0x0DA1BD17,0x00000000
                   8209:        long            0x3FFE0000,0xD62B80D6,0x2B80D62C,0x00000000
                   8210:        long            0x3FFC0000,0xB6B07F38,0xCE90E46B,0x00000000
                   8211:        long            0x3FFE0000,0xD3680D36,0x80D3680D,0x00000000
                   8212:        long            0x3FFC0000,0xC3FD0329,0x06488481,0x00000000
                   8213:        long            0x3FFE0000,0xD0B69FCB,0xD2580D0B,0x00000000
                   8214:        long            0x3FFC0000,0xD11DE0FF,0x15AB18CA,0x00000000
                   8215:        long            0x3FFE0000,0xCE168A77,0x25080CE1,0x00000000
                   8216:        long            0x3FFC0000,0xDE1433A1,0x6C66B150,0x00000000
                   8217:        long            0x3FFE0000,0xCB8727C0,0x65C393E0,0x00000000
                   8218:        long            0x3FFC0000,0xEAE10B5A,0x7DDC8ADD,0x00000000
                   8219:        long            0x3FFE0000,0xC907DA4E,0x871146AD,0x00000000
                   8220:        long            0x3FFC0000,0xF7856E5E,0xE2C9B291,0x00000000
                   8221:        long            0x3FFE0000,0xC6980C69,0x80C6980C,0x00000000
                   8222:        long            0x3FFD0000,0x82012CA5,0xA68206D7,0x00000000
                   8223:        long            0x3FFE0000,0xC4372F85,0x5D824CA6,0x00000000
                   8224:        long            0x3FFD0000,0x882C5FCD,0x7256A8C5,0x00000000
                   8225:        long            0x3FFE0000,0xC1E4BBD5,0x95F6E947,0x00000000
                   8226:        long            0x3FFD0000,0x8E44C60B,0x4CCFD7DE,0x00000000
                   8227:        long            0x3FFE0000,0xBFA02FE8,0x0BFA02FF,0x00000000
                   8228:        long            0x3FFD0000,0x944AD09E,0xF4351AF6,0x00000000
                   8229:        long            0x3FFE0000,0xBD691047,0x07661AA3,0x00000000
                   8230:        long            0x3FFD0000,0x9A3EECD4,0xC3EAA6B2,0x00000000
                   8231:        long            0x3FFE0000,0xBB3EE721,0xA54D880C,0x00000000
                   8232:        long            0x3FFD0000,0xA0218434,0x353F1DE8,0x00000000
                   8233:        long            0x3FFE0000,0xB92143FA,0x36F5E02E,0x00000000
                   8234:        long            0x3FFD0000,0xA5F2FCAB,0xBBC506DA,0x00000000
                   8235:        long            0x3FFE0000,0xB70FBB5A,0x19BE3659,0x00000000
                   8236:        long            0x3FFD0000,0xABB3B8BA,0x2AD362A5,0x00000000
                   8237:        long            0x3FFE0000,0xB509E68A,0x9B94821F,0x00000000
                   8238:        long            0x3FFD0000,0xB1641795,0xCE3CA97B,0x00000000
                   8239:        long            0x3FFE0000,0xB30F6352,0x8917C80B,0x00000000
                   8240:        long            0x3FFD0000,0xB7047551,0x5D0F1C61,0x00000000
                   8241:        long            0x3FFE0000,0xB11FD3B8,0x0B11FD3C,0x00000000
                   8242:        long            0x3FFD0000,0xBC952AFE,0xEA3D13E1,0x00000000
                   8243:        long            0x3FFE0000,0xAF3ADDC6,0x80AF3ADE,0x00000000
                   8244:        long            0x3FFD0000,0xC2168ED0,0xF458BA4A,0x00000000
                   8245:        long            0x3FFE0000,0xAD602B58,0x0AD602B6,0x00000000
                   8246:        long            0x3FFD0000,0xC788F439,0xB3163BF1,0x00000000
                   8247:        long            0x3FFE0000,0xAB8F69E2,0x8359CD11,0x00000000
                   8248:        long            0x3FFD0000,0xCCECAC08,0xBF04565D,0x00000000
                   8249:        long            0x3FFE0000,0xA9C84A47,0xA07F5638,0x00000000
                   8250:        long            0x3FFD0000,0xD2420487,0x2DD85160,0x00000000
                   8251:        long            0x3FFE0000,0xA80A80A8,0x0A80A80B,0x00000000
                   8252:        long            0x3FFD0000,0xD7894992,0x3BC3588A,0x00000000
                   8253:        long            0x3FFE0000,0xA655C439,0x2D7B73A8,0x00000000
                   8254:        long            0x3FFD0000,0xDCC2C4B4,0x9887DACC,0x00000000
                   8255:        long            0x3FFE0000,0xA4A9CF1D,0x96833751,0x00000000
                   8256:        long            0x3FFD0000,0xE1EEBD3E,0x6D6A6B9E,0x00000000
                   8257:        long            0x3FFE0000,0xA3065E3F,0xAE7CD0E0,0x00000000
                   8258:        long            0x3FFD0000,0xE70D785C,0x2F9F5BDC,0x00000000
                   8259:        long            0x3FFE0000,0xA16B312E,0xA8FC377D,0x00000000
                   8260:        long            0x3FFD0000,0xEC1F392C,0x5179F283,0x00000000
                   8261:        long            0x3FFE0000,0x9FD809FD,0x809FD80A,0x00000000
                   8262:        long            0x3FFD0000,0xF12440D3,0xE36130E6,0x00000000
                   8263:        long            0x3FFE0000,0x9E4CAD23,0xDD5F3A20,0x00000000
                   8264:        long            0x3FFD0000,0xF61CCE92,0x346600BB,0x00000000
                   8265:        long            0x3FFE0000,0x9CC8E160,0xC3FB19B9,0x00000000
                   8266:        long            0x3FFD0000,0xFB091FD3,0x8145630A,0x00000000
                   8267:        long            0x3FFE0000,0x9B4C6F9E,0xF03A3CAA,0x00000000
                   8268:        long            0x3FFD0000,0xFFE97042,0xBFA4C2AD,0x00000000
                   8269:        long            0x3FFE0000,0x99D722DA,0xBDE58F06,0x00000000
                   8270:        long            0x3FFE0000,0x825EFCED,0x49369330,0x00000000
                   8271:        long            0x3FFE0000,0x9868C809,0x868C8098,0x00000000
                   8272:        long            0x3FFE0000,0x84C37A7A,0xB9A905C9,0x00000000
                   8273:        long            0x3FFE0000,0x97012E02,0x5C04B809,0x00000000
                   8274:        long            0x3FFE0000,0x87224C2E,0x8E645FB7,0x00000000
                   8275:        long            0x3FFE0000,0x95A02568,0x095A0257,0x00000000
                   8276:        long            0x3FFE0000,0x897B8CAC,0x9F7DE298,0x00000000
                   8277:        long            0x3FFE0000,0x94458094,0x45809446,0x00000000
                   8278:        long            0x3FFE0000,0x8BCF55DE,0xC4CD05FE,0x00000000
                   8279:        long            0x3FFE0000,0x92F11384,0x0497889C,0x00000000
                   8280:        long            0x3FFE0000,0x8E1DC0FB,0x89E125E5,0x00000000
                   8281:        long            0x3FFE0000,0x91A2B3C4,0xD5E6F809,0x00000000
                   8282:        long            0x3FFE0000,0x9066E68C,0x955B6C9B,0x00000000
                   8283:        long            0x3FFE0000,0x905A3863,0x3E06C43B,0x00000000
                   8284:        long            0x3FFE0000,0x92AADE74,0xC7BE59E0,0x00000000
                   8285:        long            0x3FFE0000,0x8F1779D9,0xFDC3A219,0x00000000
                   8286:        long            0x3FFE0000,0x94E9BFF6,0x15845643,0x00000000
                   8287:        long            0x3FFE0000,0x8DDA5202,0x37694809,0x00000000
                   8288:        long            0x3FFE0000,0x9723A1B7,0x20134203,0x00000000
                   8289:        long            0x3FFE0000,0x8CA29C04,0x6514E023,0x00000000
                   8290:        long            0x3FFE0000,0x995899C8,0x90EB8990,0x00000000
                   8291:        long            0x3FFE0000,0x8B70344A,0x139BC75A,0x00000000
                   8292:        long            0x3FFE0000,0x9B88BDAA,0x3A3DAE2F,0x00000000
                   8293:        long            0x3FFE0000,0x8A42F870,0x5669DB46,0x00000000
                   8294:        long            0x3FFE0000,0x9DB4224F,0xFFE1157C,0x00000000
                   8295:        long            0x3FFE0000,0x891AC73A,0xE9819B50,0x00000000
                   8296:        long            0x3FFE0000,0x9FDADC26,0x8B7A12DA,0x00000000
                   8297:        long            0x3FFE0000,0x87F78087,0xF78087F8,0x00000000
                   8298:        long            0x3FFE0000,0xA1FCFF17,0xCE733BD4,0x00000000
                   8299:        long            0x3FFE0000,0x86D90544,0x7A34ACC6,0x00000000
                   8300:        long            0x3FFE0000,0xA41A9E8F,0x5446FB9F,0x00000000
                   8301:        long            0x3FFE0000,0x85BF3761,0x2CEE3C9B,0x00000000
                   8302:        long            0x3FFE0000,0xA633CD7E,0x6771CD8B,0x00000000
                   8303:        long            0x3FFE0000,0x84A9F9C8,0x084A9F9D,0x00000000
                   8304:        long            0x3FFE0000,0xA8489E60,0x0B435A5E,0x00000000
                   8305:        long            0x3FFE0000,0x83993052,0x3FBE3368,0x00000000
                   8306:        long            0x3FFE0000,0xAA59233C,0xCCA4BD49,0x00000000
                   8307:        long            0x3FFE0000,0x828CBFBE,0xB9A020A3,0x00000000
                   8308:        long            0x3FFE0000,0xAC656DAE,0x6BCC4985,0x00000000
                   8309:        long            0x3FFE0000,0x81848DA8,0xFAF0D277,0x00000000
                   8310:        long            0x3FFE0000,0xAE6D8EE3,0x60BB2468,0x00000000
                   8311:        long            0x3FFE0000,0x80808080,0x80808081,0x00000000
                   8312:        long            0x3FFE0000,0xB07197A2,0x3C46C654,0x00000000
                   8313:
                   8314:        set             ADJK,L_SCR1
                   8315:
                   8316:        set             X,FP_SCR0
                   8317:        set             XDCARE,X+2
                   8318:        set             XFRAC,X+4
                   8319:
                   8320:        set             F,FP_SCR1
                   8321:        set             FFRAC,F+4
                   8322:
                   8323:        set             KLOG2,FP_SCR0
                   8324:
                   8325:        set             SAVEU,FP_SCR0
                   8326:
                   8327:        global          slogn
                   8328: #--ENTRY POINT FOR LOG(X) FOR X FINITE, NON-ZERO, NOT NAN'S
                   8329: slogn:
                   8330:        fmov.x          (%a0),%fp0              # LOAD INPUT
                   8331:        mov.l           &0x00000000,ADJK(%a6)
                   8332:
                   8333: LOGBGN:
                   8334: #--FPCR SAVED AND CLEARED, INPUT IS 2^(ADJK)*FP0, FP0 CONTAINS
                   8335: #--A FINITE, NON-ZERO, NORMALIZED NUMBER.
                   8336:
                   8337:        mov.l           (%a0),%d1
                   8338:        mov.w           4(%a0),%d1
                   8339:
                   8340:        mov.l           (%a0),X(%a6)
                   8341:        mov.l           4(%a0),X+4(%a6)
                   8342:        mov.l           8(%a0),X+8(%a6)
                   8343:
                   8344:        cmp.l           %d1,&0                  # CHECK IF X IS NEGATIVE
                   8345:        blt.w           LOGNEG                  # LOG OF NEGATIVE ARGUMENT IS INVALID
                   8346: # X IS POSITIVE, CHECK IF X IS NEAR 1
                   8347:        cmp.l           %d1,&0x3ffef07d         # IS X < 15/16?
                   8348:        blt.b           LOGMAIN                 # YES
                   8349:        cmp.l           %d1,&0x3fff8841         # IS X > 17/16?
                   8350:        ble.w           LOGNEAR1                # NO
                   8351:
                   8352: LOGMAIN:
                   8353: #--THIS SHOULD BE THE USUAL CASE, X NOT VERY CLOSE TO 1
                   8354:
                   8355: #--X = 2^(K) * Y, 1 <= Y < 2. THUS, Y = 1.XXXXXXXX....XX IN BINARY.
                   8356: #--WE DEFINE F = 1.XXXXXX1, I.E. FIRST 7 BITS OF Y AND ATTACH A 1.
                   8357: #--THE IDEA IS THAT LOG(X) = K*LOG2 + LOG(Y)
                   8358: #--                     = K*LOG2 + LOG(F) + LOG(1 + (Y-F)/F).
                   8359: #--NOTE THAT U = (Y-F)/F IS VERY SMALL AND THUS APPROXIMATING
                   8360: #--LOG(1+U) CAN BE VERY EFFICIENT.
                   8361: #--ALSO NOTE THAT THE VALUE 1/F IS STORED IN A TABLE SO THAT NO
                   8362: #--DIVISION IS NEEDED TO CALCULATE (Y-F)/F.
                   8363:
                   8364: #--GET K, Y, F, AND ADDRESS OF 1/F.
                   8365:        asr.l           &8,%d1
                   8366:        asr.l           &8,%d1                  # SHIFTED 16 BITS, BIASED EXPO. OF X
                   8367:        sub.l           &0x3FFF,%d1             # THIS IS K
                   8368:        add.l           ADJK(%a6),%d1           # ADJUST K, ORIGINAL INPUT MAY BE  DENORM.
                   8369:        lea             LOGTBL(%pc),%a0         # BASE ADDRESS OF 1/F AND LOG(F)
                   8370:        fmov.l          %d1,%fp1                # CONVERT K TO FLOATING-POINT FORMAT
                   8371:
                   8372: #--WHILE THE CONVERSION IS GOING ON, WE GET F AND ADDRESS OF 1/F
                   8373:        mov.l           &0x3FFF0000,X(%a6)      # X IS NOW Y, I.E. 2^(-K)*X
                   8374:        mov.l           XFRAC(%a6),FFRAC(%a6)
                   8375:        and.l           &0xFE000000,FFRAC(%a6)  # FIRST 7 BITS OF Y
                   8376:        or.l            &0x01000000,FFRAC(%a6)  # GET F: ATTACH A 1 AT THE EIGHTH BIT
                   8377:        mov.l           FFRAC(%a6),%d1  # READY TO GET ADDRESS OF 1/F
                   8378:        and.l           &0x7E000000,%d1
                   8379:        asr.l           &8,%d1
                   8380:        asr.l           &8,%d1
                   8381:        asr.l           &4,%d1                  # SHIFTED 20, D0 IS THE DISPLACEMENT
                   8382:        add.l           %d1,%a0                 # A0 IS THE ADDRESS FOR 1/F
                   8383:
                   8384:        fmov.x          X(%a6),%fp0
                   8385:        mov.l           &0x3fff0000,F(%a6)
                   8386:        clr.l           F+8(%a6)
                   8387:        fsub.x          F(%a6),%fp0             # Y-F
                   8388:        fmovm.x         &0xc,-(%sp)             # SAVE FP2-3 WHILE FP0 IS NOT READY
                   8389: #--SUMMARY: FP0 IS Y-F, A0 IS ADDRESS OF 1/F, FP1 IS K
                   8390: #--REGISTERS SAVED: FPCR, FP1, FP2
                   8391:
                   8392: LP1CONT1:
                   8393: #--AN RE-ENTRY POINT FOR LOGNP1
                   8394:        fmul.x          (%a0),%fp0              # FP0 IS U = (Y-F)/F
                   8395:        fmul.x          LOGOF2(%pc),%fp1        # GET K*LOG2 WHILE FP0 IS NOT READY
                   8396:        fmov.x          %fp0,%fp2
                   8397:        fmul.x          %fp2,%fp2               # FP2 IS V=U*U
                   8398:        fmov.x          %fp1,KLOG2(%a6)         # PUT K*LOG2 IN MEMEORY, FREE FP1
                   8399:
                   8400: #--LOG(1+U) IS APPROXIMATED BY
                   8401: #--U + V*(A1+U*(A2+U*(A3+U*(A4+U*(A5+U*A6))))) WHICH IS
                   8402: #--[U + V*(A1+V*(A3+V*A5))]  +  [U*V*(A2+V*(A4+V*A6))]
                   8403:
                   8404:        fmov.x          %fp2,%fp3
                   8405:        fmov.x          %fp2,%fp1
                   8406:
                   8407:        fmul.d          LOGA6(%pc),%fp1         # V*A6
                   8408:        fmul.d          LOGA5(%pc),%fp2         # V*A5
                   8409:
                   8410:        fadd.d          LOGA4(%pc),%fp1         # A4+V*A6
                   8411:        fadd.d          LOGA3(%pc),%fp2         # A3+V*A5
                   8412:
                   8413:        fmul.x          %fp3,%fp1               # V*(A4+V*A6)
                   8414:        fmul.x          %fp3,%fp2               # V*(A3+V*A5)
                   8415:
                   8416:        fadd.d          LOGA2(%pc),%fp1         # A2+V*(A4+V*A6)
                   8417:        fadd.d          LOGA1(%pc),%fp2         # A1+V*(A3+V*A5)
                   8418:
                   8419:        fmul.x          %fp3,%fp1               # V*(A2+V*(A4+V*A6))
                   8420:        add.l           &16,%a0                 # ADDRESS OF LOG(F)
                   8421:        fmul.x          %fp3,%fp2               # V*(A1+V*(A3+V*A5))
                   8422:
                   8423:        fmul.x          %fp0,%fp1               # U*V*(A2+V*(A4+V*A6))
                   8424:        fadd.x          %fp2,%fp0               # U+V*(A1+V*(A3+V*A5))
                   8425:
                   8426:        fadd.x          (%a0),%fp1              # LOG(F)+U*V*(A2+V*(A4+V*A6))
                   8427:        fmovm.x         (%sp)+,&0x30            # RESTORE FP2-3
                   8428:        fadd.x          %fp1,%fp0               # FP0 IS LOG(F) + LOG(1+U)
                   8429:
                   8430:        fmov.l          %d0,%fpcr
                   8431:        fadd.x          KLOG2(%a6),%fp0         # FINAL ADD
                   8432:        bra             t_inx2
                   8433:
                   8434:
                   8435: LOGNEAR1:
                   8436:
                   8437: # if the input is exactly equal to one, then exit through ld_pzero.
                   8438: # if these 2 lines weren't here, the correct answer would be returned
                   8439: # but the INEX2 bit would be set.
                   8440:        fcmp.b          %fp0,&0x1               # is it equal to one?
                   8441:        fbeq.l          ld_pzero                # yes
                   8442:
                   8443: #--REGISTERS SAVED: FPCR, FP1. FP0 CONTAINS THE INPUT.
                   8444:        fmov.x          %fp0,%fp1
                   8445:        fsub.s          one(%pc),%fp1           # FP1 IS X-1
                   8446:        fadd.s          one(%pc),%fp0           # FP0 IS X+1
                   8447:        fadd.x          %fp1,%fp1               # FP1 IS 2(X-1)
                   8448: #--LOG(X) = LOG(1+U/2)-LOG(1-U/2) WHICH IS AN ODD POLYNOMIAL
                   8449: #--IN U, U = 2(X-1)/(X+1) = FP1/FP0
                   8450:
                   8451: LP1CONT2:
                   8452: #--THIS IS AN RE-ENTRY POINT FOR LOGNP1
                   8453:        fdiv.x          %fp0,%fp1               # FP1 IS U
                   8454:        fmovm.x         &0xc,-(%sp)             # SAVE FP2-3
                   8455: #--REGISTERS SAVED ARE NOW FPCR,FP1,FP2,FP3
                   8456: #--LET V=U*U, W=V*V, CALCULATE
                   8457: #--U + U*V*(B1 + V*(B2 + V*(B3 + V*(B4 + V*B5)))) BY
                   8458: #--U + U*V*(  [B1 + W*(B3 + W*B5)]  +  [V*(B2 + W*B4)]  )
                   8459:        fmov.x          %fp1,%fp0
                   8460:        fmul.x          %fp0,%fp0               # FP0 IS V
                   8461:        fmov.x          %fp1,SAVEU(%a6)         # STORE U IN MEMORY, FREE FP1
                   8462:        fmov.x          %fp0,%fp1
                   8463:        fmul.x          %fp1,%fp1               # FP1 IS W
                   8464:
                   8465:        fmov.d          LOGB5(%pc),%fp3
                   8466:        fmov.d          LOGB4(%pc),%fp2
                   8467:
                   8468:        fmul.x          %fp1,%fp3               # W*B5
                   8469:        fmul.x          %fp1,%fp2               # W*B4
                   8470:
                   8471:        fadd.d          LOGB3(%pc),%fp3         # B3+W*B5
                   8472:        fadd.d          LOGB2(%pc),%fp2         # B2+W*B4
                   8473:
                   8474:        fmul.x          %fp3,%fp1               # W*(B3+W*B5), FP3 RELEASED
                   8475:
                   8476:        fmul.x          %fp0,%fp2               # V*(B2+W*B4)
                   8477:
                   8478:        fadd.d          LOGB1(%pc),%fp1         # B1+W*(B3+W*B5)
                   8479:        fmul.x          SAVEU(%a6),%fp0         # FP0 IS U*V
                   8480:
                   8481:        fadd.x          %fp2,%fp1               # B1+W*(B3+W*B5) + V*(B2+W*B4), FP2 RELEASED
                   8482:        fmovm.x         (%sp)+,&0x30            # FP2-3 RESTORED
                   8483:
                   8484:        fmul.x          %fp1,%fp0               # U*V*( [B1+W*(B3+W*B5)] + [V*(B2+W*B4)] )
                   8485:
                   8486:        fmov.l          %d0,%fpcr
                   8487:        fadd.x          SAVEU(%a6),%fp0
                   8488:        bra             t_inx2
                   8489:
                   8490: #--REGISTERS SAVED FPCR. LOG(-VE) IS INVALID
                   8491: LOGNEG:
                   8492:        bra             t_operr
                   8493:
                   8494:        global          slognd
                   8495: slognd:
                   8496: #--ENTRY POINT FOR LOG(X) FOR DENORMALIZED INPUT
                   8497:
                   8498:        mov.l           &-100,ADJK(%a6)         # INPUT = 2^(ADJK) * FP0
                   8499:
                   8500: #----normalize the input value by left shifting k bits (k to be determined
                   8501: #----below), adjusting exponent and storing -k to  ADJK
                   8502: #----the value TWOTO100 is no longer needed.
                   8503: #----Note that this code assumes the denormalized input is NON-ZERO.
                   8504:
                   8505:        movm.l          &0x3f00,-(%sp)          # save some registers  {d2-d7}
                   8506:        mov.l           (%a0),%d3               # D3 is exponent of smallest norm. #
                   8507:        mov.l           4(%a0),%d4
                   8508:        mov.l           8(%a0),%d5              # (D4,D5) is (Hi_X,Lo_X)
                   8509:        clr.l           %d2                     # D2 used for holding K
                   8510:
                   8511:        tst.l           %d4
                   8512:        bne.b           Hi_not0
                   8513:
                   8514: Hi_0:
                   8515:        mov.l           %d5,%d4
                   8516:        clr.l           %d5
                   8517:        mov.l           &32,%d2
                   8518:        clr.l           %d6
                   8519:        bfffo           %d4{&0:&32},%d6
                   8520:        lsl.l           %d6,%d4
                   8521:        add.l           %d6,%d2                 # (D3,D4,D5) is normalized
                   8522:
                   8523:        mov.l           %d3,X(%a6)
                   8524:        mov.l           %d4,XFRAC(%a6)
                   8525:        mov.l           %d5,XFRAC+4(%a6)
                   8526:        neg.l           %d2
                   8527:        mov.l           %d2,ADJK(%a6)
                   8528:        fmov.x          X(%a6),%fp0
                   8529:        movm.l          (%sp)+,&0xfc            # restore registers {d2-d7}
                   8530:        lea             X(%a6),%a0
                   8531:        bra.w           LOGBGN                  # begin regular log(X)
                   8532:
                   8533: Hi_not0:
                   8534:        clr.l           %d6
                   8535:        bfffo           %d4{&0:&32},%d6         # find first 1
                   8536:        mov.l           %d6,%d2                 # get k
                   8537:        lsl.l           %d6,%d4
                   8538:        mov.l           %d5,%d7                 # a copy of D5
                   8539:        lsl.l           %d6,%d5
                   8540:        neg.l           %d6
                   8541:        add.l           &32,%d6
                   8542:        lsr.l           %d6,%d7
                   8543:        or.l            %d7,%d4                 # (D3,D4,D5) normalized
                   8544:
                   8545:        mov.l           %d3,X(%a6)
                   8546:        mov.l           %d4,XFRAC(%a6)
                   8547:        mov.l           %d5,XFRAC+4(%a6)
                   8548:        neg.l           %d2
                   8549:        mov.l           %d2,ADJK(%a6)
                   8550:        fmov.x          X(%a6),%fp0
                   8551:        movm.l          (%sp)+,&0xfc            # restore registers {d2-d7}
                   8552:        lea             X(%a6),%a0
                   8553:        bra.w           LOGBGN                  # begin regular log(X)
                   8554:
                   8555:        global          slognp1
                   8556: #--ENTRY POINT FOR LOG(1+X) FOR X FINITE, NON-ZERO, NOT NAN'S
                   8557: slognp1:
                   8558:        fmov.x          (%a0),%fp0              # LOAD INPUT
                   8559:        fabs.x          %fp0                    # test magnitude
                   8560:        fcmp.x          %fp0,LTHOLD(%pc)        # compare with min threshold
                   8561:        fbgt.w          LP1REAL                 # if greater, continue
                   8562:        fmov.l          %d0,%fpcr
                   8563:        mov.b           &FMOV_OP,%d1            # last inst is MOVE
                   8564:        fmov.x          (%a0),%fp0              # return signed argument
                   8565:        bra             t_catch
                   8566:
                   8567: LP1REAL:
                   8568:        fmov.x          (%a0),%fp0              # LOAD INPUT
                   8569:        mov.l           &0x00000000,ADJK(%a6)
                   8570:        fmov.x          %fp0,%fp1               # FP1 IS INPUT Z
                   8571:        fadd.s          one(%pc),%fp0           # X := ROUND(1+Z)
                   8572:        fmov.x          %fp0,X(%a6)
                   8573:        mov.w           XFRAC(%a6),XDCARE(%a6)
                   8574:        mov.l           X(%a6),%d1
                   8575:        cmp.l           %d1,&0
                   8576:        ble.w           LP1NEG0                 # LOG OF ZERO OR -VE
                   8577:        cmp.l           %d1,&0x3ffe8000         # IS BOUNDS [1/2,3/2]?
                   8578:        blt.w           LOGMAIN
                   8579:        cmp.l           %d1,&0x3fffc000
                   8580:        bgt.w           LOGMAIN
                   8581: #--IF 1+Z > 3/2 OR 1+Z < 1/2, THEN X, WHICH IS ROUNDING 1+Z,
                   8582: #--CONTAINS AT LEAST 63 BITS OF INFORMATION OF Z. IN THAT CASE,
                   8583: #--SIMPLY INVOKE LOG(X) FOR LOG(1+Z).
                   8584:
                   8585: LP1NEAR1:
                   8586: #--NEXT SEE IF EXP(-1/16) < X < EXP(1/16)
                   8587:        cmp.l           %d1,&0x3ffef07d
                   8588:        blt.w           LP1CARE
                   8589:        cmp.l           %d1,&0x3fff8841
                   8590:        bgt.w           LP1CARE
                   8591:
                   8592: LP1ONE16:
                   8593: #--EXP(-1/16) < X < EXP(1/16). LOG(1+Z) = LOG(1+U/2) - LOG(1-U/2)
                   8594: #--WHERE U = 2Z/(2+Z) = 2Z/(1+X).
                   8595:        fadd.x          %fp1,%fp1               # FP1 IS 2Z
                   8596:        fadd.s          one(%pc),%fp0           # FP0 IS 1+X
                   8597: #--U = FP1/FP0
                   8598:        bra.w           LP1CONT2
                   8599:
                   8600: LP1CARE:
                   8601: #--HERE WE USE THE USUAL TABLE DRIVEN APPROACH. CARE HAS TO BE
                   8602: #--TAKEN BECAUSE 1+Z CAN HAVE 67 BITS OF INFORMATION AND WE MUST
                   8603: #--PRESERVE ALL THE INFORMATION. BECAUSE 1+Z IS IN [1/2,3/2],
                   8604: #--THERE ARE ONLY TWO CASES.
                   8605: #--CASE 1: 1+Z < 1, THEN K = -1 AND Y-F = (2-F) + 2Z
                   8606: #--CASE 2: 1+Z > 1, THEN K = 0  AND Y-F = (1-F) + Z
                   8607: #--ON RETURNING TO LP1CONT1, WE MUST HAVE K IN FP1, ADDRESS OF
                   8608: #--(1/F) IN A0, Y-F IN FP0, AND FP2 SAVED.
                   8609:
                   8610:        mov.l           XFRAC(%a6),FFRAC(%a6)
                   8611:        and.l           &0xFE000000,FFRAC(%a6)
                   8612:        or.l            &0x01000000,FFRAC(%a6)  # F OBTAINED
                   8613:        cmp.l           %d1,&0x3FFF8000         # SEE IF 1+Z > 1
                   8614:        bge.b           KISZERO
                   8615:
                   8616: KISNEG1:
                   8617:        fmov.s          TWO(%pc),%fp0
                   8618:        mov.l           &0x3fff0000,F(%a6)
                   8619:        clr.l           F+8(%a6)
                   8620:        fsub.x          F(%a6),%fp0             # 2-F
                   8621:        mov.l           FFRAC(%a6),%d1
                   8622:        and.l           &0x7E000000,%d1
                   8623:        asr.l           &8,%d1
                   8624:        asr.l           &8,%d1
                   8625:        asr.l           &4,%d1                  # D0 CONTAINS DISPLACEMENT FOR 1/F
                   8626:        fadd.x          %fp1,%fp1               # GET 2Z
                   8627:        fmovm.x         &0xc,-(%sp)             # SAVE FP2  {%fp2/%fp3}
                   8628:        fadd.x          %fp1,%fp0               # FP0 IS Y-F = (2-F)+2Z
                   8629:        lea             LOGTBL(%pc),%a0         # A0 IS ADDRESS OF 1/F
                   8630:        add.l           %d1,%a0
                   8631:        fmov.s          negone(%pc),%fp1        # FP1 IS K = -1
                   8632:        bra.w           LP1CONT1
                   8633:
                   8634: KISZERO:
                   8635:        fmov.s          one(%pc),%fp0
                   8636:        mov.l           &0x3fff0000,F(%a6)
                   8637:        clr.l           F+8(%a6)
                   8638:        fsub.x          F(%a6),%fp0             # 1-F
                   8639:        mov.l           FFRAC(%a6),%d1
                   8640:        and.l           &0x7E000000,%d1
                   8641:        asr.l           &8,%d1
                   8642:        asr.l           &8,%d1
                   8643:        asr.l           &4,%d1
                   8644:        fadd.x          %fp1,%fp0               # FP0 IS Y-F
                   8645:        fmovm.x         &0xc,-(%sp)             # FP2 SAVED {%fp2/%fp3}
                   8646:        lea             LOGTBL(%pc),%a0
                   8647:        add.l           %d1,%a0                 # A0 IS ADDRESS OF 1/F
                   8648:        fmov.s          zero(%pc),%fp1          # FP1 IS K = 0
                   8649:        bra.w           LP1CONT1
                   8650:
                   8651: LP1NEG0:
                   8652: #--FPCR SAVED. D0 IS X IN COMPACT FORM.
                   8653:        cmp.l           %d1,&0
                   8654:        blt.b           LP1NEG
                   8655: LP1ZERO:
                   8656:        fmov.s          negone(%pc),%fp0
                   8657:
                   8658:        fmov.l          %d0,%fpcr
                   8659:        bra             t_dz
                   8660:
                   8661: LP1NEG:
                   8662:        fmov.s          zero(%pc),%fp0
                   8663:
                   8664:        fmov.l          %d0,%fpcr
                   8665:        bra             t_operr
                   8666:
                   8667:        global          slognp1d
                   8668: #--ENTRY POINT FOR LOG(1+Z) FOR DENORMALIZED INPUT
                   8669: # Simply return the denorm
                   8670: slognp1d:
                   8671:        bra             t_extdnrm
                   8672:
                   8673: #########################################################################
                   8674: # satanh():  computes the inverse hyperbolic tangent of a norm input   #
                   8675: # satanhd(): computes the inverse hyperbolic tangent of a denorm input #
                   8676: #                                                                      #
                   8677: # INPUT ***************************************************************        #
                   8678: #      a0 = pointer to extended precision input                        #
                   8679: #      d0 = round precision,mode                                       #
                   8680: #                                                                      #
                   8681: # OUTPUT **************************************************************        #
                   8682: #      fp0 = arctanh(X)                                                #
                   8683: #                                                                      #
                   8684: # ACCURACY and MONOTONICITY *******************************************        #
                   8685: #      The returned result is within 3 ulps in 64 significant bit,     #
                   8686: #      i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
                   8687: #      rounded to double precision. The result is provably monotonic   #
                   8688: #      in double precision.                                            #
                   8689: #                                                                      #
                   8690: # ALGORITHM ***********************************************************        #
                   8691: #                                                                      #
                   8692: #      ATANH                                                           #
                   8693: #      1. If |X| >= 1, go to 3.                                        #
                   8694: #                                                                      #
                   8695: #      2. (|X| < 1) Calculate atanh(X) by                              #
                   8696: #              sgn := sign(X)                                          #
                   8697: #              y := |X|                                                #
                   8698: #              z := 2y/(1-y)                                           #
                   8699: #              atanh(X) := sgn * (1/2) * logp1(z)                      #
                   8700: #              Exit.                                                   #
                   8701: #                                                                      #
                   8702: #      3. If |X| > 1, go to 5.                                         #
                   8703: #                                                                      #
                   8704: #      4. (|X| = 1) Generate infinity with an appropriate sign and     #
                   8705: #              divide-by-zero by                                       #
                   8706: #              sgn := sign(X)                                          #
                   8707: #              atan(X) := sgn / (+0).                                  #
                   8708: #              Exit.                                                   #
                   8709: #                                                                      #
                   8710: #      5. (|X| > 1) Generate an invalid operation by 0 * infinity.     #
                   8711: #              Exit.                                                   #
                   8712: #                                                                      #
                   8713: #########################################################################
                   8714:
                   8715:        global          satanh
                   8716: satanh:
                   8717:        mov.l           (%a0),%d1
                   8718:        mov.w           4(%a0),%d1
                   8719:        and.l           &0x7FFFFFFF,%d1
                   8720:        cmp.l           %d1,&0x3FFF8000
                   8721:        bge.b           ATANHBIG
                   8722:
                   8723: #--THIS IS THE USUAL CASE, |X| < 1
                   8724: #--Y = |X|, Z = 2Y/(1-Y), ATANH(X) = SIGN(X) * (1/2) * LOG1P(Z).
                   8725:
                   8726:        fabs.x          (%a0),%fp0              # Y = |X|
                   8727:        fmov.x          %fp0,%fp1
                   8728:        fneg.x          %fp1                    # -Y
                   8729:        fadd.x          %fp0,%fp0               # 2Y
                   8730:        fadd.s          &0x3F800000,%fp1        # 1-Y
                   8731:        fdiv.x          %fp1,%fp0               # 2Y/(1-Y)
                   8732:        mov.l           (%a0),%d1
                   8733:        and.l           &0x80000000,%d1
                   8734:        or.l            &0x3F000000,%d1         # SIGN(X)*HALF
                   8735:        mov.l           %d1,-(%sp)
                   8736:
                   8737:        mov.l           %d0,-(%sp)              # save rnd prec,mode
                   8738:        clr.l           %d0                     # pass ext prec,RN
                   8739:        fmovm.x         &0x01,-(%sp)            # save Z on stack
                   8740:        lea             (%sp),%a0               # pass ptr to Z
                   8741:        bsr             slognp1                 # LOG1P(Z)
                   8742:        add.l           &0xc,%sp                # clear Z from stack
                   8743:
                   8744:        mov.l           (%sp)+,%d0              # fetch old prec,mode
                   8745:        fmov.l          %d0,%fpcr               # load it
                   8746:        mov.b           &FMUL_OP,%d1            # last inst is MUL
                   8747:        fmul.s          (%sp)+,%fp0
                   8748:        bra             t_catch
                   8749:
                   8750: ATANHBIG:
                   8751:        fabs.x          (%a0),%fp0              # |X|
                   8752:        fcmp.s          %fp0,&0x3F800000
                   8753:        fbgt            t_operr
                   8754:        bra             t_dz
                   8755:
                   8756:        global          satanhd
                   8757: #--ATANH(X) = X FOR DENORMALIZED X
                   8758: satanhd:
                   8759:        bra             t_extdnrm
                   8760:
                   8761: #########################################################################
                   8762: # slog10():  computes the base-10 logarithm of a normalized input      #
                   8763: # slog10d(): computes the base-10 logarithm of a denormalized input    #
                   8764: # slog2():   computes the base-2 logarithm of a normalized input       #
                   8765: # slog2d():  computes the base-2 logarithm of a denormalized input     #
                   8766: #                                                                      #
                   8767: # INPUT *************************************************************** #
                   8768: #      a0 = pointer to extended precision input                        #
                   8769: #      d0 = round precision,mode                                       #
                   8770: #                                                                      #
                   8771: # OUTPUT **************************************************************        #
                   8772: #      fp0 = log_10(X) or log_2(X)                                     #
                   8773: #                                                                      #
                   8774: # ACCURACY and MONOTONICITY *******************************************        #
                   8775: #      The returned result is within 1.7 ulps in 64 significant bit,   #
                   8776: #      i.e. within 0.5003 ulp to 53 bits if the result is subsequently #
                   8777: #      rounded to double precision. The result is provably monotonic   #
                   8778: #      in double precision.                                            #
                   8779: #                                                                      #
                   8780: # ALGORITHM ***********************************************************        #
                   8781: #                                                                      #
                   8782: #       slog10d:                                                       #
                   8783: #                                                                      #
                   8784: #       Step 0.        If X < 0, create a NaN and raise the invalid operation  #
                   8785: #               flag. Otherwise, save FPCR in D1; set FpCR to default. #
                   8786: #       Notes:  Default means round-to-nearest mode, no floating-point #
                   8787: #               traps, and precision control = double extended.                #
                   8788: #                                                                      #
                   8789: #       Step 1. Call slognd to obtain Y = log(X), the natural log of X.        #
                   8790: #       Notes:  Even if X is denormalized, log(X) is always normalized.        #
                   8791: #                                                                      #
                   8792: #       Step 2.  Compute log_10(X) = log(X) * (1/log(10)).             #
                   8793: #            2.1 Restore the user FPCR                                 #
                   8794: #            2.2 Return ans := Y * INV_L10.                            #
                   8795: #                                                                      #
                   8796: #       slog10:                                                        #
                   8797: #                                                                      #
                   8798: #       Step 0. If X < 0, create a NaN and raise the invalid operation #
                   8799: #               flag. Otherwise, save FPCR in D1; set FpCR to default. #
                   8800: #       Notes:  Default means round-to-nearest mode, no floating-point #
                   8801: #               traps, and precision control = double extended.                #
                   8802: #                                                                      #
                   8803: #       Step 1. Call sLogN to obtain Y = log(X), the natural log of X. #
                   8804: #                                                                      #
                   8805: #       Step 2.   Compute log_10(X) = log(X) * (1/log(10)).            #
                   8806: #            2.1  Restore the user FPCR                                        #
                   8807: #            2.2  Return ans := Y * INV_L10.                           #
                   8808: #                                                                      #
                   8809: #       sLog2d:                                                                #
                   8810: #                                                                      #
                   8811: #       Step 0. If X < 0, create a NaN and raise the invalid operation #
                   8812: #               flag. Otherwise, save FPCR in D1; set FpCR to default. #
                   8813: #       Notes:  Default means round-to-nearest mode, no floating-point #
                   8814: #               traps, and precision control = double extended.                #
                   8815: #                                                                      #
                   8816: #       Step 1. Call slognd to obtain Y = log(X), the natural log of X.        #
                   8817: #       Notes:  Even if X is denormalized, log(X) is always normalized.        #
                   8818: #                                                                      #
                   8819: #       Step 2.   Compute log_10(X) = log(X) * (1/log(2)).             #
                   8820: #            2.1  Restore the user FPCR                                        #
                   8821: #            2.2  Return ans := Y * INV_L2.                            #
                   8822: #                                                                      #
                   8823: #       sLog2:                                                         #
                   8824: #                                                                      #
                   8825: #       Step 0. If X < 0, create a NaN and raise the invalid operation #
                   8826: #               flag. Otherwise, save FPCR in D1; set FpCR to default. #
                   8827: #       Notes:  Default means round-to-nearest mode, no floating-point #
                   8828: #               traps, and precision control = double extended.                #
                   8829: #                                                                      #
                   8830: #       Step 1. If X is not an integer power of two, i.e., X != 2^k,   #
                   8831: #               go to Step 3.                                          #
                   8832: #                                                                      #
                   8833: #       Step 2.   Return k.                                            #
                   8834: #            2.1  Get integer k, X = 2^k.                              #
                   8835: #            2.2  Restore the user FPCR.                               #
                   8836: #            2.3  Return ans := convert-to-double-extended(k).         #
                   8837: #                                                                      #
                   8838: #       Step 3. Call sLogN to obtain Y = log(X), the natural log of X. #
                   8839: #                                                                      #
                   8840: #       Step 4.   Compute log_2(X) = log(X) * (1/log(2)).              #
                   8841: #            4.1  Restore the user FPCR                                        #
                   8842: #            4.2  Return ans := Y * INV_L2.                            #
                   8843: #                                                                      #
                   8844: #########################################################################
                   8845:
                   8846: INV_L10:
                   8847:        long            0x3FFD0000,0xDE5BD8A9,0x37287195,0x00000000
                   8848:
                   8849: INV_L2:
                   8850:        long            0x3FFF0000,0xB8AA3B29,0x5C17F0BC,0x00000000
                   8851:
                   8852:        global          slog10
                   8853: #--entry point for Log10(X), X is normalized
                   8854: slog10:
                   8855:        fmov.b          &0x1,%fp0
                   8856:        fcmp.x          %fp0,(%a0)              # if operand == 1,
                   8857:        fbeq.l          ld_pzero                # return an EXACT zero
                   8858:
                   8859:        mov.l           (%a0),%d1
                   8860:        blt.w           invalid
                   8861:        mov.l           %d0,-(%sp)
                   8862:        clr.l           %d0
                   8863:        bsr             slogn                   # log(X), X normal.
                   8864:        fmov.l          (%sp)+,%fpcr
                   8865:        fmul.x          INV_L10(%pc),%fp0
                   8866:        bra             t_inx2
                   8867:
                   8868:        global          slog10d
                   8869: #--entry point for Log10(X), X is denormalized
                   8870: slog10d:
                   8871:        mov.l           (%a0),%d1
                   8872:        blt.w           invalid
                   8873:        mov.l           %d0,-(%sp)
                   8874:        clr.l           %d0
                   8875:        bsr             slognd                  # log(X), X denorm.
                   8876:        fmov.l          (%sp)+,%fpcr
                   8877:        fmul.x          INV_L10(%pc),%fp0
                   8878:        bra             t_minx2
                   8879:
                   8880:        global          slog2
                   8881: #--entry point for Log2(X), X is normalized
                   8882: slog2:
                   8883:        mov.l           (%a0),%d1
                   8884:        blt.w           invalid
                   8885:
                   8886:        mov.l           8(%a0),%d1
                   8887:        bne.b           continue                # X is not 2^k
                   8888:
                   8889:        mov.l           4(%a0),%d1
                   8890:        and.l           &0x7FFFFFFF,%d1
                   8891:        bne.b           continue
                   8892:
                   8893: #--X = 2^k.
                   8894:        mov.w           (%a0),%d1
                   8895:        and.l           &0x00007FFF,%d1
                   8896:        sub.l           &0x3FFF,%d1
                   8897:        beq.l           ld_pzero
                   8898:        fmov.l          %d0,%fpcr
                   8899:        fmov.l          %d1,%fp0
                   8900:        bra             t_inx2
                   8901:
                   8902: continue:
                   8903:        mov.l           %d0,-(%sp)
                   8904:        clr.l           %d0
                   8905:        bsr             slogn                   # log(X), X normal.
                   8906:        fmov.l          (%sp)+,%fpcr
                   8907:        fmul.x          INV_L2(%pc),%fp0
                   8908:        bra             t_inx2
                   8909:
                   8910: invalid:
                   8911:        bra             t_operr
                   8912:
                   8913:        global          slog2d
                   8914: #--entry point for Log2(X), X is denormalized
                   8915: slog2d:
                   8916:        mov.l           (%a0),%d1
                   8917:        blt.w           invalid
                   8918:        mov.l           %d0,-(%sp)
                   8919:        clr.l           %d0
                   8920:        bsr             slognd                  # log(X), X denorm.
                   8921:        fmov.l          (%sp)+,%fpcr
                   8922:        fmul.x          INV_L2(%pc),%fp0
                   8923:        bra             t_minx2
                   8924:
                   8925: #########################################################################
                   8926: # stwotox():  computes 2**X for a normalized input                     #
                   8927: # stwotoxd(): computes 2**X for a denormalized input                   #
                   8928: # stentox():  computes 10**X for a normalized input                    #
                   8929: # stentoxd(): computes 10**X for a denormalized input                  #
                   8930: #                                                                      #
                   8931: # INPUT ***************************************************************        #
                   8932: #      a0 = pointer to extended precision input                        #
                   8933: #      d0 = round precision,mode                                       #
                   8934: #                                                                      #
                   8935: # OUTPUT **************************************************************        #
                   8936: #      fp0 = 2**X or 10**X                                             #
                   8937: #                                                                      #
                   8938: # ACCURACY and MONOTONICITY *******************************************        #
                   8939: #      The returned result is within 2 ulps in 64 significant bit,     #
                   8940: #      i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
                   8941: #      rounded to double precision. The result is provably monotonic   #
                   8942: #      in double precision.                                            #
                   8943: #                                                                      #
                   8944: # ALGORITHM ***********************************************************        #
                   8945: #                                                                      #
                   8946: #      twotox                                                          #
                   8947: #      1. If |X| > 16480, go to ExpBig.                                #
                   8948: #                                                                      #
                   8949: #      2. If |X| < 2**(-70), go to ExpSm.                              #
                   8950: #                                                                      #
                   8951: #      3. Decompose X as X = N/64 + r where |r| <= 1/128. Furthermore  #
                   8952: #              decompose N as                                          #
                   8953: #               N = 64(M + M') + j,  j = 0,1,2,...,63.                 #
                   8954: #                                                                      #
                   8955: #      4. Overwrite r := r * log2. Then                                #
                   8956: #              2**X = 2**(M') * 2**(M) * 2**(j/64) * exp(r).           #
                   8957: #              Go to expr to compute that expression.                  #
                   8958: #                                                                      #
                   8959: #      tentox                                                          #
                   8960: #      1. If |X| > 16480*log_10(2) (base 10 log of 2), go to ExpBig.   #
                   8961: #                                                                      #
                   8962: #      2. If |X| < 2**(-70), go to ExpSm.                              #
                   8963: #                                                                      #
                   8964: #      3. Set y := X*log_2(10)*64 (base 2 log of 10). Set              #
                   8965: #              N := round-to-int(y). Decompose N as                    #
                   8966: #               N = 64(M + M') + j,  j = 0,1,2,...,63.                 #
                   8967: #                                                                      #
                   8968: #      4. Define r as                                                  #
                   8969: #              r := ((X - N*L1)-N*L2) * L10                            #
                   8970: #              where L1, L2 are the leading and trailing parts of      #
                   8971: #              log_10(2)/64 and L10 is the natural log of 10. Then     #
                   8972: #              10**X = 2**(M') * 2**(M) * 2**(j/64) * exp(r).          #
                   8973: #              Go to expr to compute that expression.                  #
                   8974: #                                                                      #
                   8975: #      expr                                                            #
                   8976: #      1. Fetch 2**(j/64) from table as Fact1 and Fact2.               #
                   8977: #                                                                      #
                   8978: #      2. Overwrite Fact1 and Fact2 by                                 #
                   8979: #              Fact1 := 2**(M) * Fact1                                 #
                   8980: #              Fact2 := 2**(M) * Fact2                                 #
                   8981: #              Thus Fact1 + Fact2 = 2**(M) * 2**(j/64).                #
                   8982: #                                                                      #
                   8983: #      3. Calculate P where 1 + P approximates exp(r):                 #
                   8984: #              P = r + r*r*(A1+r*(A2+...+r*A5)).                       #
                   8985: #                                                                      #
                   8986: #      4. Let AdjFact := 2**(M'). Return                               #
                   8987: #              AdjFact * ( Fact1 + ((Fact1*P) + Fact2) ).              #
                   8988: #              Exit.                                                   #
                   8989: #                                                                      #
                   8990: #      ExpBig                                                          #
                   8991: #      1. Generate overflow by Huge * Huge if X > 0; otherwise,        #
                   8992: #              generate underflow by Tiny * Tiny.                      #
                   8993: #                                                                      #
                   8994: #      ExpSm                                                           #
                   8995: #      1. Return 1 + X.                                                #
                   8996: #                                                                      #
                   8997: #########################################################################
                   8998:
                   8999: L2TEN64:
                   9000:        long            0x406A934F,0x0979A371   # 64LOG10/LOG2
                   9001: L10TWO1:
                   9002:        long            0x3F734413,0x509F8000   # LOG2/64LOG10
                   9003:
                   9004: L10TWO2:
                   9005:        long            0xBFCD0000,0xC0219DC1,0xDA994FD2,0x00000000
                   9006:
                   9007: LOG10: long            0x40000000,0x935D8DDD,0xAAA8AC17,0x00000000
                   9008:
                   9009: LOG2:  long            0x3FFE0000,0xB17217F7,0xD1CF79AC,0x00000000
                   9010:
                   9011: EXPA5: long            0x3F56C16D,0x6F7BD0B2
                   9012: EXPA4: long            0x3F811112,0x302C712C
                   9013: EXPA3: long            0x3FA55555,0x55554CC1
                   9014: EXPA2: long            0x3FC55555,0x55554A54
                   9015: EXPA1: long            0x3FE00000,0x00000000,0x00000000,0x00000000
                   9016:
                   9017: TEXPTBL:
                   9018:        long            0x3FFF0000,0x80000000,0x00000000,0x3F738000
                   9019:        long            0x3FFF0000,0x8164D1F3,0xBC030773,0x3FBEF7CA
                   9020:        long            0x3FFF0000,0x82CD8698,0xAC2BA1D7,0x3FBDF8A9
                   9021:        long            0x3FFF0000,0x843A28C3,0xACDE4046,0x3FBCD7C9
                   9022:        long            0x3FFF0000,0x85AAC367,0xCC487B15,0xBFBDE8DA
                   9023:        long            0x3FFF0000,0x871F6196,0x9E8D1010,0x3FBDE85C
                   9024:        long            0x3FFF0000,0x88980E80,0x92DA8527,0x3FBEBBF1
                   9025:        long            0x3FFF0000,0x8A14D575,0x496EFD9A,0x3FBB80CA
                   9026:        long            0x3FFF0000,0x8B95C1E3,0xEA8BD6E7,0xBFBA8373
                   9027:        long            0x3FFF0000,0x8D1ADF5B,0x7E5BA9E6,0xBFBE9670
                   9028:        long            0x3FFF0000,0x8EA4398B,0x45CD53C0,0x3FBDB700
                   9029:        long            0x3FFF0000,0x9031DC43,0x1466B1DC,0x3FBEEEB0
                   9030:        long            0x3FFF0000,0x91C3D373,0xAB11C336,0x3FBBFD6D
                   9031:        long            0x3FFF0000,0x935A2B2F,0x13E6E92C,0xBFBDB319
                   9032:        long            0x3FFF0000,0x94F4EFA8,0xFEF70961,0x3FBDBA2B
                   9033:        long            0x3FFF0000,0x96942D37,0x20185A00,0x3FBE91D5
                   9034:        long            0x3FFF0000,0x9837F051,0x8DB8A96F,0x3FBE8D5A
                   9035:        long            0x3FFF0000,0x99E04593,0x20B7FA65,0xBFBCDE7B
                   9036:        long            0x3FFF0000,0x9B8D39B9,0xD54E5539,0xBFBEBAAF
                   9037:        long            0x3FFF0000,0x9D3ED9A7,0x2CFFB751,0xBFBD86DA
                   9038:        long            0x3FFF0000,0x9EF53260,0x91A111AE,0xBFBEBEDD
                   9039:        long            0x3FFF0000,0xA0B0510F,0xB9714FC2,0x3FBCC96E
                   9040:        long            0x3FFF0000,0xA2704303,0x0C496819,0xBFBEC90B
                   9041:        long            0x3FFF0000,0xA43515AE,0x09E6809E,0x3FBBD1DB
                   9042:        long            0x3FFF0000,0xA5FED6A9,0xB15138EA,0x3FBCE5EB
                   9043:        long            0x3FFF0000,0xA7CD93B4,0xE965356A,0xBFBEC274
                   9044:        long            0x3FFF0000,0xA9A15AB4,0xEA7C0EF8,0x3FBEA83C
                   9045:        long            0x3FFF0000,0xAB7A39B5,0xA93ED337,0x3FBECB00
                   9046:        long            0x3FFF0000,0xAD583EEA,0x42A14AC6,0x3FBE9301
                   9047:        long            0x3FFF0000,0xAF3B78AD,0x690A4375,0xBFBD8367
                   9048:        long            0x3FFF0000,0xB123F581,0xD2AC2590,0xBFBEF05F
                   9049:        long            0x3FFF0000,0xB311C412,0xA9112489,0x3FBDFB3C
                   9050:        long            0x3FFF0000,0xB504F333,0xF9DE6484,0x3FBEB2FB
                   9051:        long            0x3FFF0000,0xB6FD91E3,0x28D17791,0x3FBAE2CB
                   9052:        long            0x3FFF0000,0xB8FBAF47,0x62FB9EE9,0x3FBCDC3C
                   9053:        long            0x3FFF0000,0xBAFF5AB2,0x133E45FB,0x3FBEE9AA
                   9054:        long            0x3FFF0000,0xBD08A39F,0x580C36BF,0xBFBEAEFD
                   9055:        long            0x3FFF0000,0xBF1799B6,0x7A731083,0xBFBCBF51
                   9056:        long            0x3FFF0000,0xC12C4CCA,0x66709456,0x3FBEF88A
                   9057:        long            0x3FFF0000,0xC346CCDA,0x24976407,0x3FBD83B2
                   9058:        long            0x3FFF0000,0xC5672A11,0x5506DADD,0x3FBDF8AB
                   9059:        long            0x3FFF0000,0xC78D74C8,0xABB9B15D,0xBFBDFB17
                   9060:        long            0x3FFF0000,0xC9B9BD86,0x6E2F27A3,0xBFBEFE3C
                   9061:        long            0x3FFF0000,0xCBEC14FE,0xF2727C5D,0xBFBBB6F8
                   9062:        long            0x3FFF0000,0xCE248C15,0x1F8480E4,0xBFBCEE53
                   9063:        long            0x3FFF0000,0xD06333DA,0xEF2B2595,0xBFBDA4AE
                   9064:        long            0x3FFF0000,0xD2A81D91,0xF12AE45A,0x3FBC9124
                   9065:        long            0x3FFF0000,0xD4F35AAB,0xCFEDFA1F,0x3FBEB243
                   9066:        long            0x3FFF0000,0xD744FCCA,0xD69D6AF4,0x3FBDE69A
                   9067:        long            0x3FFF0000,0xD99D15C2,0x78AFD7B6,0xBFB8BC61
                   9068:        long            0x3FFF0000,0xDBFBB797,0xDAF23755,0x3FBDF610
                   9069:        long            0x3FFF0000,0xDE60F482,0x5E0E9124,0xBFBD8BE1
                   9070:        long            0x3FFF0000,0xE0CCDEEC,0x2A94E111,0x3FBACB12
                   9071:        long            0x3FFF0000,0xE33F8972,0xBE8A5A51,0x3FBB9BFE
                   9072:        long            0x3FFF0000,0xE5B906E7,0x7C8348A8,0x3FBCF2F4
                   9073:        long            0x3FFF0000,0xE8396A50,0x3C4BDC68,0x3FBEF22F
                   9074:        long            0x3FFF0000,0xEAC0C6E7,0xDD24392F,0xBFBDBF4A
                   9075:        long            0x3FFF0000,0xED4F301E,0xD9942B84,0x3FBEC01A
                   9076:        long            0x3FFF0000,0xEFE4B99B,0xDCDAF5CB,0x3FBE8CAC
                   9077:        long            0x3FFF0000,0xF281773C,0x59FFB13A,0xBFBCBB3F
                   9078:        long            0x3FFF0000,0xF5257D15,0x2486CC2C,0x3FBEF73A
                   9079:        long            0x3FFF0000,0xF7D0DF73,0x0AD13BB9,0xBFB8B795
                   9080:        long            0x3FFF0000,0xFA83B2DB,0x722A033A,0x3FBEF84B
                   9081:        long            0x3FFF0000,0xFD3E0C0C,0xF486C175,0xBFBEF581
                   9082:
                   9083:        set             INT,L_SCR1
                   9084:
                   9085:        set             X,FP_SCR0
                   9086:        set             XDCARE,X+2
                   9087:        set             XFRAC,X+4
                   9088:
                   9089:        set             ADJFACT,FP_SCR0
                   9090:
                   9091:        set             FACT1,FP_SCR0
                   9092:        set             FACT1HI,FACT1+4
                   9093:        set             FACT1LOW,FACT1+8
                   9094:
                   9095:        set             FACT2,FP_SCR1
                   9096:        set             FACT2HI,FACT2+4
                   9097:        set             FACT2LOW,FACT2+8
                   9098:
                   9099:        global          stwotox
                   9100: #--ENTRY POINT FOR 2**(X), HERE X IS FINITE, NON-ZERO, AND NOT NAN'S
                   9101: stwotox:
                   9102:        fmovm.x         (%a0),&0x80             # LOAD INPUT
                   9103:
                   9104:        mov.l           (%a0),%d1
                   9105:        mov.w           4(%a0),%d1
                   9106:        fmov.x          %fp0,X(%a6)
                   9107:        and.l           &0x7FFFFFFF,%d1
                   9108:
                   9109:        cmp.l           %d1,&0x3FB98000         # |X| >= 2**(-70)?
                   9110:        bge.b           TWOOK1
                   9111:        bra.w           EXPBORS
                   9112:
                   9113: TWOOK1:
                   9114:        cmp.l           %d1,&0x400D80C0         # |X| > 16480?
                   9115:        ble.b           TWOMAIN
                   9116:        bra.w           EXPBORS
                   9117:
                   9118: TWOMAIN:
                   9119: #--USUAL CASE, 2^(-70) <= |X| <= 16480
                   9120:
                   9121:        fmov.x          %fp0,%fp1
                   9122:        fmul.s          &0x42800000,%fp1        # 64 * X
                   9123:        fmov.l          %fp1,INT(%a6)           # N = ROUND-TO-INT(64 X)
                   9124:        mov.l           %d2,-(%sp)
                   9125:        lea             TEXPTBL(%pc),%a1        # LOAD ADDRESS OF TABLE OF 2^(J/64)
                   9126:        fmov.l          INT(%a6),%fp1           # N --> FLOATING FMT
                   9127:        mov.l           INT(%a6),%d1
                   9128:        mov.l           %d1,%d2
                   9129:        and.l           &0x3F,%d1               # D0 IS J
                   9130:        asl.l           &4,%d1                  # DISPLACEMENT FOR 2^(J/64)
                   9131:        add.l           %d1,%a1                 # ADDRESS FOR 2^(J/64)
                   9132:        asr.l           &6,%d2                  # d2 IS L, N = 64L + J
                   9133:        mov.l           %d2,%d1
                   9134:        asr.l           &1,%d1                  # D0 IS M
                   9135:        sub.l           %d1,%d2                 # d2 IS M', N = 64(M+M') + J
                   9136:        add.l           &0x3FFF,%d2
                   9137:
                   9138: #--SUMMARY: a1 IS ADDRESS FOR THE LEADING PORTION OF 2^(J/64),
                   9139: #--D0 IS M WHERE N = 64(M+M') + J. NOTE THAT |M| <= 16140 BY DESIGN.
                   9140: #--ADJFACT = 2^(M').
                   9141: #--REGISTERS SAVED SO FAR ARE (IN ORDER) FPCR, D0, FP1, a1, AND FP2.
                   9142:
                   9143:        fmovm.x         &0x0c,-(%sp)            # save fp2/fp3
                   9144:
                   9145:        fmul.s          &0x3C800000,%fp1        # (1/64)*N
                   9146:        mov.l           (%a1)+,FACT1(%a6)
                   9147:        mov.l           (%a1)+,FACT1HI(%a6)
                   9148:        mov.l           (%a1)+,FACT1LOW(%a6)
                   9149:        mov.w           (%a1)+,FACT2(%a6)
                   9150:
                   9151:        fsub.x          %fp1,%fp0               # X - (1/64)*INT(64 X)
                   9152:
                   9153:        mov.w           (%a1)+,FACT2HI(%a6)
                   9154:        clr.w           FACT2HI+2(%a6)
                   9155:        clr.l           FACT2LOW(%a6)
                   9156:        add.w           %d1,FACT1(%a6)
                   9157:        fmul.x          LOG2(%pc),%fp0          # FP0 IS R
                   9158:        add.w           %d1,FACT2(%a6)
                   9159:
                   9160:        bra.w           expr
                   9161:
                   9162: EXPBORS:
                   9163: #--FPCR, D0 SAVED
                   9164:        cmp.l           %d1,&0x3FFF8000
                   9165:        bgt.b           TEXPBIG
                   9166:
                   9167: #--|X| IS SMALL, RETURN 1 + X
                   9168:
                   9169:        fmov.l          %d0,%fpcr               # restore users round prec,mode
                   9170:        fadd.s          &0x3F800000,%fp0        # RETURN 1 + X
                   9171:        bra             t_pinx2
                   9172:
                   9173: TEXPBIG:
                   9174: #--|X| IS LARGE, GENERATE OVERFLOW IF X > 0; ELSE GENERATE UNDERFLOW
                   9175: #--REGISTERS SAVE SO FAR ARE FPCR AND  D0
                   9176:        mov.l           X(%a6),%d1
                   9177:        cmp.l           %d1,&0
                   9178:        blt.b           EXPNEG
                   9179:
                   9180:        bra             t_ovfl2                 # t_ovfl expects positive value
                   9181:
                   9182: EXPNEG:
                   9183:        bra             t_unfl2                 # t_unfl expects positive value
                   9184:
                   9185:        global          stwotoxd
                   9186: stwotoxd:
                   9187: #--ENTRY POINT FOR 2**(X) FOR DENORMALIZED ARGUMENT
                   9188:
                   9189:        fmov.l          %d0,%fpcr               # set user's rounding mode/precision
                   9190:        fmov.s          &0x3F800000,%fp0        # RETURN 1 + X
                   9191:        mov.l           (%a0),%d1
                   9192:        or.l            &0x00800001,%d1
                   9193:        fadd.s          %d1,%fp0
                   9194:        bra             t_pinx2
                   9195:
                   9196:        global          stentox
                   9197: #--ENTRY POINT FOR 10**(X), HERE X IS FINITE, NON-ZERO, AND NOT NAN'S
                   9198: stentox:
                   9199:        fmovm.x         (%a0),&0x80             # LOAD INPUT
                   9200:
                   9201:        mov.l           (%a0),%d1
                   9202:        mov.w           4(%a0),%d1
                   9203:        fmov.x          %fp0,X(%a6)
                   9204:        and.l           &0x7FFFFFFF,%d1
                   9205:
                   9206:        cmp.l           %d1,&0x3FB98000         # |X| >= 2**(-70)?
                   9207:        bge.b           TENOK1
                   9208:        bra.w           EXPBORS
                   9209:
                   9210: TENOK1:
                   9211:        cmp.l           %d1,&0x400B9B07         # |X| <= 16480*log2/log10 ?
                   9212:        ble.b           TENMAIN
                   9213:        bra.w           EXPBORS
                   9214:
                   9215: TENMAIN:
                   9216: #--USUAL CASE, 2^(-70) <= |X| <= 16480 LOG 2 / LOG 10
                   9217:
                   9218:        fmov.x          %fp0,%fp1
                   9219:        fmul.d          L2TEN64(%pc),%fp1       # X*64*LOG10/LOG2
                   9220:        fmov.l          %fp1,INT(%a6)           # N=INT(X*64*LOG10/LOG2)
                   9221:        mov.l           %d2,-(%sp)
                   9222:        lea             TEXPTBL(%pc),%a1        # LOAD ADDRESS OF TABLE OF 2^(J/64)
                   9223:        fmov.l          INT(%a6),%fp1           # N --> FLOATING FMT
                   9224:        mov.l           INT(%a6),%d1
                   9225:        mov.l           %d1,%d2
                   9226:        and.l           &0x3F,%d1               # D0 IS J
                   9227:        asl.l           &4,%d1                  # DISPLACEMENT FOR 2^(J/64)
                   9228:        add.l           %d1,%a1                 # ADDRESS FOR 2^(J/64)
                   9229:        asr.l           &6,%d2                  # d2 IS L, N = 64L + J
                   9230:        mov.l           %d2,%d1
                   9231:        asr.l           &1,%d1                  # D0 IS M
                   9232:        sub.l           %d1,%d2                 # d2 IS M', N = 64(M+M') + J
                   9233:        add.l           &0x3FFF,%d2
                   9234:
                   9235: #--SUMMARY: a1 IS ADDRESS FOR THE LEADING PORTION OF 2^(J/64),
                   9236: #--D0 IS M WHERE N = 64(M+M') + J. NOTE THAT |M| <= 16140 BY DESIGN.
                   9237: #--ADJFACT = 2^(M').
                   9238: #--REGISTERS SAVED SO FAR ARE (IN ORDER) FPCR, D0, FP1, a1, AND FP2.
                   9239:        fmovm.x         &0x0c,-(%sp)            # save fp2/fp3
                   9240:
                   9241:        fmov.x          %fp1,%fp2
                   9242:
                   9243:        fmul.d          L10TWO1(%pc),%fp1       # N*(LOG2/64LOG10)_LEAD
                   9244:        mov.l           (%a1)+,FACT1(%a6)
                   9245:
                   9246:        fmul.x          L10TWO2(%pc),%fp2       # N*(LOG2/64LOG10)_TRAIL
                   9247:
                   9248:        mov.l           (%a1)+,FACT1HI(%a6)
                   9249:        mov.l           (%a1)+,FACT1LOW(%a6)
                   9250:        fsub.x          %fp1,%fp0               # X - N L_LEAD
                   9251:        mov.w           (%a1)+,FACT2(%a6)
                   9252:
                   9253:        fsub.x          %fp2,%fp0               # X - N L_TRAIL
                   9254:
                   9255:        mov.w           (%a1)+,FACT2HI(%a6)
                   9256:        clr.w           FACT2HI+2(%a6)
                   9257:        clr.l           FACT2LOW(%a6)
                   9258:
                   9259:        fmul.x          LOG10(%pc),%fp0         # FP0 IS R
                   9260:        add.w           %d1,FACT1(%a6)
                   9261:        add.w           %d1,FACT2(%a6)
                   9262:
                   9263: expr:
                   9264: #--FPCR, FP2, FP3 ARE SAVED IN ORDER AS SHOWN.
                   9265: #--ADJFACT CONTAINS 2**(M'), FACT1 + FACT2 = 2**(M) * 2**(J/64).
                   9266: #--FP0 IS R. THE FOLLOWING CODE COMPUTES
                   9267: #--    2**(M'+M) * 2**(J/64) * EXP(R)
                   9268:
                   9269:        fmov.x          %fp0,%fp1
                   9270:        fmul.x          %fp1,%fp1               # FP1 IS S = R*R
                   9271:
                   9272:        fmov.d          EXPA5(%pc),%fp2         # FP2 IS A5
                   9273:        fmov.d          EXPA4(%pc),%fp3         # FP3 IS A4
                   9274:
                   9275:        fmul.x          %fp1,%fp2               # FP2 IS S*A5
                   9276:        fmul.x          %fp1,%fp3               # FP3 IS S*A4
                   9277:
                   9278:        fadd.d          EXPA3(%pc),%fp2         # FP2 IS A3+S*A5
                   9279:        fadd.d          EXPA2(%pc),%fp3         # FP3 IS A2+S*A4
                   9280:
                   9281:        fmul.x          %fp1,%fp2               # FP2 IS S*(A3+S*A5)
                   9282:        fmul.x          %fp1,%fp3               # FP3 IS S*(A2+S*A4)
                   9283:
                   9284:        fadd.d          EXPA1(%pc),%fp2         # FP2 IS A1+S*(A3+S*A5)
                   9285:        fmul.x          %fp0,%fp3               # FP3 IS R*S*(A2+S*A4)
                   9286:
                   9287:        fmul.x          %fp1,%fp2               # FP2 IS S*(A1+S*(A3+S*A5))
                   9288:        fadd.x          %fp3,%fp0               # FP0 IS R+R*S*(A2+S*A4)
                   9289:        fadd.x          %fp2,%fp0               # FP0 IS EXP(R) - 1
                   9290:
                   9291:        fmovm.x         (%sp)+,&0x30            # restore fp2/fp3
                   9292:
                   9293: #--FINAL RECONSTRUCTION PROCESS
                   9294: #--EXP(X) = 2^M*2^(J/64) + 2^M*2^(J/64)*(EXP(R)-1)  -  (1 OR 0)
                   9295:
                   9296:        fmul.x          FACT1(%a6),%fp0
                   9297:        fadd.x          FACT2(%a6),%fp0
                   9298:        fadd.x          FACT1(%a6),%fp0
                   9299:
                   9300:        fmov.l          %d0,%fpcr               # restore users round prec,mode
                   9301:        mov.w           %d2,ADJFACT(%a6)        # INSERT EXPONENT
                   9302:        mov.l           (%sp)+,%d2
                   9303:        mov.l           &0x80000000,ADJFACT+4(%a6)
                   9304:        clr.l           ADJFACT+8(%a6)
                   9305:        mov.b           &FMUL_OP,%d1            # last inst is MUL
                   9306:        fmul.x          ADJFACT(%a6),%fp0       # FINAL ADJUSTMENT
                   9307:        bra             t_catch
                   9308:
                   9309:        global          stentoxd
                   9310: stentoxd:
                   9311: #--ENTRY POINT FOR 10**(X) FOR DENORMALIZED ARGUMENT
                   9312:
                   9313:        fmov.l          %d0,%fpcr               # set user's rounding mode/precision
                   9314:        fmov.s          &0x3F800000,%fp0        # RETURN 1 + X
                   9315:        mov.l           (%a0),%d1
                   9316:        or.l            &0x00800001,%d1
                   9317:        fadd.s          %d1,%fp0
                   9318:        bra             t_pinx2
                   9319:
                   9320: #########################################################################
                   9321: # smovcr(): returns the ROM constant at the offset specified in d1     #
                   9322: #          rounded to the mode and precision specified in d0.          #
                   9323: #                                                                      #
                   9324: # INPUT        *************************************************************** #
                   9325: #      d0 = rnd prec,mode                                              #
                   9326: #      d1 = ROM offset                                                 #
                   9327: #                                                                      #
                   9328: # OUTPUT **************************************************************        #
                   9329: #      fp0 = the ROM constant rounded to the user's rounding mode,prec #
                   9330: #                                                                      #
                   9331: #########################################################################
                   9332:
                   9333:        global          smovcr
                   9334: smovcr:
                   9335:        mov.l           %d1,-(%sp)              # save rom offset for a sec
                   9336:
                   9337:        lsr.b           &0x4,%d0                # shift ctrl bits to lo
                   9338:        mov.l           %d0,%d1                 # make a copy
                   9339:        andi.w          &0x3,%d1                # extract rnd mode
                   9340:        andi.w          &0xc,%d0                # extract rnd prec
                   9341:        swap            %d0                     # put rnd prec in hi
                   9342:        mov.w           %d1,%d0                 # put rnd mode in lo
                   9343:
                   9344:        mov.l           (%sp)+,%d1              # get rom offset
                   9345:
                   9346: #
                   9347: # check range of offset
                   9348: #
                   9349:        tst.b           %d1                     # if zero, offset is to pi
                   9350:        beq.b           pi_tbl                  # it is pi
                   9351:        cmpi.b          %d1,&0x0a               # check range $01 - $0a
                   9352:        ble.b           z_val                   # if in this range, return zero
                   9353:        cmpi.b          %d1,&0x0e               # check range $0b - $0e
                   9354:        ble.b           sm_tbl                  # valid constants in this range
                   9355:        cmpi.b          %d1,&0x2f               # check range $10 - $2f
                   9356:        ble.b           z_val                   # if in this range, return zero
                   9357:        cmpi.b          %d1,&0x3f               # check range $30 - $3f
                   9358:        ble.b           bg_tbl                  # valid constants in this range
                   9359:
                   9360: z_val:
                   9361:        bra.l           ld_pzero                # return a zero
                   9362:
                   9363: #
                   9364: # the answer is PI rounded to the proper precision.
                   9365: #
                   9366: # fetch a pointer to the answer table relating to the proper rounding
                   9367: # precision.
                   9368: #
                   9369: pi_tbl:
                   9370:        tst.b           %d0                     # is rmode RN?
                   9371:        bne.b           pi_not_rn               # no
                   9372: pi_rn:
                   9373:        lea.l           PIRN(%pc),%a0           # yes; load PI RN table addr
                   9374:        bra.w           set_finx
                   9375: pi_not_rn:
                   9376:        cmpi.b          %d0,&rp_mode            # is rmode RP?
                   9377:        beq.b           pi_rp                   # yes
                   9378: pi_rzrm:
                   9379:        lea.l           PIRZRM(%pc),%a0         # no; load PI RZ,RM table addr
                   9380:        bra.b           set_finx
                   9381: pi_rp:
                   9382:        lea.l           PIRP(%pc),%a0           # load PI RP table addr
                   9383:        bra.b           set_finx
                   9384:
                   9385: #
                   9386: # the answer is one of:
                   9387: #      $0B     log10(2)        (inexact)
                   9388: #      $0C     e               (inexact)
                   9389: #      $0D     log2(e)         (inexact)
                   9390: #      $0E     log10(e)        (exact)
                   9391: #
                   9392: # fetch a pointer to the answer table relating to the proper rounding
                   9393: # precision.
                   9394: #
                   9395: sm_tbl:
                   9396:        subi.b          &0xb,%d1                # make offset in 0-4 range
                   9397:        tst.b           %d0                     # is rmode RN?
                   9398:        bne.b           sm_not_rn               # no
                   9399: sm_rn:
                   9400:        lea.l           SMALRN(%pc),%a0         # yes; load RN table addr
                   9401: sm_tbl_cont:
                   9402:        cmpi.b          %d1,&0x2                # is result log10(e)?
                   9403:        ble.b           set_finx                # no; answer is inexact
                   9404:        bra.b           no_finx                 # yes; answer is exact
                   9405: sm_not_rn:
                   9406:        cmpi.b          %d0,&rp_mode            # is rmode RP?
                   9407:        beq.b           sm_rp                   # yes
                   9408: sm_rzrm:
                   9409:        lea.l           SMALRZRM(%pc),%a0       # no; load RZ,RM table addr
                   9410:        bra.b           sm_tbl_cont
                   9411: sm_rp:
                   9412:        lea.l           SMALRP(%pc),%a0         # load RP table addr
                   9413:        bra.b           sm_tbl_cont
                   9414:
                   9415: #
                   9416: # the answer is one of:
                   9417: #      $30     ln(2)           (inexact)
                   9418: #      $31     ln(10)          (inexact)
                   9419: #      $32     10^0            (exact)
                   9420: #      $33     10^1            (exact)
                   9421: #      $34     10^2            (exact)
                   9422: #      $35     10^4            (exact)
                   9423: #      $36     10^8            (exact)
                   9424: #      $37     10^16           (exact)
                   9425: #      $38     10^32           (inexact)
                   9426: #      $39     10^64           (inexact)
                   9427: #      $3A     10^128          (inexact)
                   9428: #      $3B     10^256          (inexact)
                   9429: #      $3C     10^512          (inexact)
                   9430: #      $3D     10^1024         (inexact)
                   9431: #      $3E     10^2048         (inexact)
                   9432: #      $3F     10^4096         (inexact)
                   9433: #
                   9434: # fetch a pointer to the answer table relating to the proper rounding
                   9435: # precision.
                   9436: #
                   9437: bg_tbl:
                   9438:        subi.b          &0x30,%d1               # make offset in 0-f range
                   9439:        tst.b           %d0                     # is rmode RN?
                   9440:        bne.b           bg_not_rn               # no
                   9441: bg_rn:
                   9442:        lea.l           BIGRN(%pc),%a0          # yes; load RN table addr
                   9443: bg_tbl_cont:
                   9444:        cmpi.b          %d1,&0x1                # is offset <= $31?
                   9445:        ble.b           set_finx                # yes; answer is inexact
                   9446:        cmpi.b          %d1,&0x7                # is $32 <= offset <= $37?
                   9447:        ble.b           no_finx                 # yes; answer is exact
                   9448:        bra.b           set_finx                # no; answer is inexact
                   9449: bg_not_rn:
                   9450:        cmpi.b          %d0,&rp_mode            # is rmode RP?
                   9451:        beq.b           bg_rp                   # yes
                   9452: bg_rzrm:
                   9453:        lea.l           BIGRZRM(%pc),%a0        # no; load RZ,RM table addr
                   9454:        bra.b           bg_tbl_cont
                   9455: bg_rp:
                   9456:        lea.l           BIGRP(%pc),%a0          # load RP table addr
                   9457:        bra.b           bg_tbl_cont
                   9458:
                   9459: # answer is inexact, so set INEX2 and AINEX in the user's FPSR.
                   9460: set_finx:
                   9461:        ori.l           &inx2a_mask,USER_FPSR(%a6) # set INEX2/AINEX
                   9462: no_finx:
                   9463:        mulu.w          &0xc,%d1                # offset points into tables
                   9464:        swap            %d0                     # put rnd prec in lo word
                   9465:        tst.b           %d0                     # is precision extended?
                   9466:
                   9467:        bne.b           not_ext                 # if xprec, do not call round
                   9468:
                   9469: # Precision is extended
                   9470:        fmovm.x         (%a0,%d1.w),&0x80       # return result in fp0
                   9471:        rts
                   9472:
                   9473: # Precision is single or double
                   9474: not_ext:
                   9475:        swap            %d0                     # rnd prec in upper word
                   9476:
                   9477: # call round() to round the answer to the proper precision.
                   9478: # exponents out of range for single or double DO NOT cause underflow
                   9479: # or overflow.
                   9480:        mov.w           0x0(%a0,%d1.w),FP_SCR1_EX(%a6) # load first word
                   9481:        mov.l           0x4(%a0,%d1.w),FP_SCR1_HI(%a6) # load second word
                   9482:        mov.l           0x8(%a0,%d1.w),FP_SCR1_LO(%a6) # load third word
                   9483:        mov.l           %d0,%d1
                   9484:        clr.l           %d0                     # clear g,r,s
                   9485:        lea             FP_SCR1(%a6),%a0        # pass ptr to answer
                   9486:        clr.w           LOCAL_SGN(%a0)          # sign always positive
                   9487:        bsr.l           _round                  # round the mantissa
                   9488:
                   9489:        fmovm.x         (%a0),&0x80             # return rounded result in fp0
                   9490:        rts
                   9491:
                   9492:        align           0x4
                   9493:
                   9494: PIRN:  long            0x40000000,0xc90fdaa2,0x2168c235        # pi
                   9495: PIRZRM:        long            0x40000000,0xc90fdaa2,0x2168c234        # pi
                   9496: PIRP:  long            0x40000000,0xc90fdaa2,0x2168c235        # pi
                   9497:
                   9498: SMALRN:        long            0x3ffd0000,0x9a209a84,0xfbcff798        # log10(2)
                   9499:        long            0x40000000,0xadf85458,0xa2bb4a9a        # e
                   9500:        long            0x3fff0000,0xb8aa3b29,0x5c17f0bc        # log2(e)
                   9501:        long            0x3ffd0000,0xde5bd8a9,0x37287195        # log10(e)
                   9502:        long            0x00000000,0x00000000,0x00000000        # 0.0
                   9503:
                   9504: SMALRZRM:
                   9505:        long            0x3ffd0000,0x9a209a84,0xfbcff798        # log10(2)
                   9506:        long            0x40000000,0xadf85458,0xa2bb4a9a        # e
                   9507:        long            0x3fff0000,0xb8aa3b29,0x5c17f0bb        # log2(e)
                   9508:        long            0x3ffd0000,0xde5bd8a9,0x37287195        # log10(e)
                   9509:        long            0x00000000,0x00000000,0x00000000        # 0.0
                   9510:
                   9511: SMALRP:        long            0x3ffd0000,0x9a209a84,0xfbcff799        # log10(2)
                   9512:        long            0x40000000,0xadf85458,0xa2bb4a9b        # e
                   9513:        long            0x3fff0000,0xb8aa3b29,0x5c17f0bc        # log2(e)
                   9514:        long            0x3ffd0000,0xde5bd8a9,0x37287195        # log10(e)
                   9515:        long            0x00000000,0x00000000,0x00000000        # 0.0
                   9516:
                   9517: BIGRN: long            0x3ffe0000,0xb17217f7,0xd1cf79ac        # ln(2)
                   9518:        long            0x40000000,0x935d8ddd,0xaaa8ac17        # ln(10)
                   9519:
                   9520:        long            0x3fff0000,0x80000000,0x00000000        # 10 ^ 0
                   9521:        long            0x40020000,0xA0000000,0x00000000        # 10 ^ 1
                   9522:        long            0x40050000,0xC8000000,0x00000000        # 10 ^ 2
                   9523:        long            0x400C0000,0x9C400000,0x00000000        # 10 ^ 4
                   9524:        long            0x40190000,0xBEBC2000,0x00000000        # 10 ^ 8
                   9525:        long            0x40340000,0x8E1BC9BF,0x04000000        # 10 ^ 16
                   9526:        long            0x40690000,0x9DC5ADA8,0x2B70B59E        # 10 ^ 32
                   9527:        long            0x40D30000,0xC2781F49,0xFFCFA6D5        # 10 ^ 64
                   9528:        long            0x41A80000,0x93BA47C9,0x80E98CE0        # 10 ^ 128
                   9529:        long            0x43510000,0xAA7EEBFB,0x9DF9DE8E        # 10 ^ 256
                   9530:        long            0x46A30000,0xE319A0AE,0xA60E91C7        # 10 ^ 512
                   9531:        long            0x4D480000,0xC9767586,0x81750C17        # 10 ^ 1024
                   9532:        long            0x5A920000,0x9E8B3B5D,0xC53D5DE5        # 10 ^ 2048
                   9533:        long            0x75250000,0xC4605202,0x8A20979B        # 10 ^ 4096
                   9534:
                   9535: BIGRZRM:
                   9536:        long            0x3ffe0000,0xb17217f7,0xd1cf79ab        # ln(2)
                   9537:        long            0x40000000,0x935d8ddd,0xaaa8ac16        # ln(10)
                   9538:
                   9539:        long            0x3fff0000,0x80000000,0x00000000        # 10 ^ 0
                   9540:        long            0x40020000,0xA0000000,0x00000000        # 10 ^ 1
                   9541:        long            0x40050000,0xC8000000,0x00000000        # 10 ^ 2
                   9542:        long            0x400C0000,0x9C400000,0x00000000        # 10 ^ 4
                   9543:        long            0x40190000,0xBEBC2000,0x00000000        # 10 ^ 8
                   9544:        long            0x40340000,0x8E1BC9BF,0x04000000        # 10 ^ 16
                   9545:        long            0x40690000,0x9DC5ADA8,0x2B70B59D        # 10 ^ 32
                   9546:        long            0x40D30000,0xC2781F49,0xFFCFA6D5        # 10 ^ 64
                   9547:        long            0x41A80000,0x93BA47C9,0x80E98CDF        # 10 ^ 128
                   9548:        long            0x43510000,0xAA7EEBFB,0x9DF9DE8D        # 10 ^ 256
                   9549:        long            0x46A30000,0xE319A0AE,0xA60E91C6        # 10 ^ 512
                   9550:        long            0x4D480000,0xC9767586,0x81750C17        # 10 ^ 1024
                   9551:        long            0x5A920000,0x9E8B3B5D,0xC53D5DE4        # 10 ^ 2048
                   9552:        long            0x75250000,0xC4605202,0x8A20979A        # 10 ^ 4096
                   9553:
                   9554: BIGRP:
                   9555:        long            0x3ffe0000,0xb17217f7,0xd1cf79ac        # ln(2)
                   9556:        long            0x40000000,0x935d8ddd,0xaaa8ac17        # ln(10)
                   9557:
                   9558:        long            0x3fff0000,0x80000000,0x00000000        # 10 ^ 0
                   9559:        long            0x40020000,0xA0000000,0x00000000        # 10 ^ 1
                   9560:        long            0x40050000,0xC8000000,0x00000000        # 10 ^ 2
                   9561:        long            0x400C0000,0x9C400000,0x00000000        # 10 ^ 4
                   9562:        long            0x40190000,0xBEBC2000,0x00000000        # 10 ^ 8
                   9563:        long            0x40340000,0x8E1BC9BF,0x04000000        # 10 ^ 16
                   9564:        long            0x40690000,0x9DC5ADA8,0x2B70B59E        # 10 ^ 32
                   9565:        long            0x40D30000,0xC2781F49,0xFFCFA6D6        # 10 ^ 64
                   9566:        long            0x41A80000,0x93BA47C9,0x80E98CE0        # 10 ^ 128
                   9567:        long            0x43510000,0xAA7EEBFB,0x9DF9DE8E        # 10 ^ 256
                   9568:        long            0x46A30000,0xE319A0AE,0xA60E91C7        # 10 ^ 512
                   9569:        long            0x4D480000,0xC9767586,0x81750C18        # 10 ^ 1024
                   9570:        long            0x5A920000,0x9E8B3B5D,0xC53D5DE5        # 10 ^ 2048
                   9571:        long            0x75250000,0xC4605202,0x8A20979B        # 10 ^ 4096
                   9572:
                   9573: #########################################################################
                   9574: # sscale(): computes the destination operand scaled by the source      #
                   9575: #          operand. If the absoulute value of the source operand is    #
                   9576: #          >= 2^14, an overflow or underflow is returned.              #
                   9577: #                                                                      #
                   9578: # INPUT *************************************************************** #
                   9579: #      a0  = pointer to double-extended source operand X               #
                   9580: #      a1  = pointer to double-extended destination operand Y          #
                   9581: #                                                                      #
                   9582: # OUTPUT ************************************************************** #
                   9583: #      fp0 =  scale(X,Y)                                               #
                   9584: #                                                                      #
                   9585: #########################################################################
                   9586:
                   9587: set    SIGN,           L_SCR1
                   9588:
                   9589:        global          sscale
                   9590: sscale:
                   9591:        mov.l           %d0,-(%sp)              # store off ctrl bits for now
                   9592:
                   9593:        mov.w           DST_EX(%a1),%d1         # get dst exponent
                   9594:        smi.b           SIGN(%a6)               # use SIGN to hold dst sign
                   9595:        andi.l          &0x00007fff,%d1         # strip sign from dst exp
                   9596:
                   9597:        mov.w           SRC_EX(%a0),%d0         # check src bounds
                   9598:        andi.w          &0x7fff,%d0             # clr src sign bit
                   9599:        cmpi.w          %d0,&0x3fff             # is src ~ ZERO?
                   9600:        blt.w           src_small               # yes
                   9601:        cmpi.w          %d0,&0x400c             # no; is src too big?
                   9602:        bgt.w           src_out                 # yes
                   9603:
                   9604: #
                   9605: # Source is within 2^14 range.
                   9606: #
                   9607: src_ok:
                   9608:        fintrz.x        SRC(%a0),%fp0           # calc int of src
                   9609:        fmov.l          %fp0,%d0                # int src to d0
                   9610: # don't want any accrued bits from the fintrz showing up later since
                   9611: # we may need to read the fpsr for the last fp op in t_catch2().
                   9612:        fmov.l          &0x0,%fpsr
                   9613:
                   9614:        tst.b           DST_HI(%a1)             # is dst denormalized?
                   9615:        bmi.b           sok_norm
                   9616:
                   9617: # the dst is a DENORM. normalize the DENORM and add the adjustment to
                   9618: # the src value. then, jump to the norm part of the routine.
                   9619: sok_dnrm:
                   9620:        mov.l           %d0,-(%sp)              # save src for now
                   9621:
                   9622:        mov.w           DST_EX(%a1),FP_SCR0_EX(%a6) # make a copy
                   9623:        mov.l           DST_HI(%a1),FP_SCR0_HI(%a6)
                   9624:        mov.l           DST_LO(%a1),FP_SCR0_LO(%a6)
                   9625:
                   9626:        lea             FP_SCR0(%a6),%a0        # pass ptr to DENORM
                   9627:        bsr.l           norm                    # normalize the DENORM
                   9628:        neg.l           %d0
                   9629:        add.l           (%sp)+,%d0              # add adjustment to src
                   9630:
                   9631:        fmovm.x         FP_SCR0(%a6),&0x80      # load normalized DENORM
                   9632:
                   9633:        cmpi.w          %d0,&-0x3fff            # is the shft amt really low?
                   9634:        bge.b           sok_norm2               # thank goodness no
                   9635:
                   9636: # the multiply factor that we're trying to create should be a denorm
                   9637: # for the multiply to work. therefore, we're going to actually do a
                   9638: # multiply with a denorm which will cause an unimplemented data type
                   9639: # exception to be put into the machine which will be caught and corrected
                   9640: # later. we don't do this with the DENORMs above because this method
                   9641: # is slower. but, don't fret, I don't see it being used much either.
                   9642:        fmov.l          (%sp)+,%fpcr            # restore user fpcr
                   9643:        mov.l           &0x80000000,%d1         # load normalized mantissa
                   9644:        subi.l          &-0x3fff,%d0            # how many should we shift?
                   9645:        neg.l           %d0                     # make it positive
                   9646:        cmpi.b          %d0,&0x20               # is it > 32?
                   9647:        bge.b           sok_dnrm_32             # yes
                   9648:        lsr.l           %d0,%d1                 # no; bit stays in upper lw
                   9649:        clr.l           -(%sp)                  # insert zero low mantissa
                   9650:        mov.l           %d1,-(%sp)              # insert new high mantissa
                   9651:        clr.l           -(%sp)                  # make zero exponent
                   9652:        bra.b           sok_norm_cont
                   9653: sok_dnrm_32:
                   9654:        subi.b          &0x20,%d0               # get shift count
                   9655:        lsr.l           %d0,%d1                 # make low mantissa longword
                   9656:        mov.l           %d1,-(%sp)              # insert new low mantissa
                   9657:        clr.l           -(%sp)                  # insert zero high mantissa
                   9658:        clr.l           -(%sp)                  # make zero exponent
                   9659:        bra.b           sok_norm_cont
                   9660:
                   9661: # the src will force the dst to a DENORM value or worse. so, let's
                   9662: # create an fp multiply that will create the result.
                   9663: sok_norm:
                   9664:        fmovm.x         DST(%a1),&0x80          # load fp0 with normalized src
                   9665: sok_norm2:
                   9666:        fmov.l          (%sp)+,%fpcr            # restore user fpcr
                   9667:
                   9668:        addi.w          &0x3fff,%d0             # turn src amt into exp value
                   9669:        swap            %d0                     # put exponent in high word
                   9670:        clr.l           -(%sp)                  # insert new exponent
                   9671:        mov.l           &0x80000000,-(%sp)      # insert new high mantissa
                   9672:        mov.l           %d0,-(%sp)              # insert new lo mantissa
                   9673:
                   9674: sok_norm_cont:
                   9675:        fmov.l          %fpcr,%d0               # d0 needs fpcr for t_catch2
                   9676:        mov.b           &FMUL_OP,%d1            # last inst is MUL
                   9677:        fmul.x          (%sp)+,%fp0             # do the multiply
                   9678:        bra             t_catch2                # catch any exceptions
                   9679:
                   9680: #
                   9681: # Source is outside of 2^14 range.  Test the sign and branch
                   9682: # to the appropriate exception handler.
                   9683: #
                   9684: src_out:
                   9685:        mov.l           (%sp)+,%d0              # restore ctrl bits
                   9686:        exg             %a0,%a1                 # swap src,dst ptrs
                   9687:        tst.b           SRC_EX(%a1)             # is src negative?
                   9688:        bmi             t_unfl                  # yes; underflow
                   9689:        bra             t_ovfl_sc               # no; overflow
                   9690:
                   9691: #
                   9692: # The source input is below 1, so we check for denormalized numbers
                   9693: # and set unfl.
                   9694: #
                   9695: src_small:
                   9696:        tst.b           DST_HI(%a1)             # is dst denormalized?
                   9697:        bpl.b           ssmall_done             # yes
                   9698:
                   9699:        mov.l           (%sp)+,%d0
                   9700:        fmov.l          %d0,%fpcr               # no; load control bits
                   9701:        mov.b           &FMOV_OP,%d1            # last inst is MOVE
                   9702:        fmov.x          DST(%a1),%fp0           # simply return dest
                   9703:        bra             t_catch2
                   9704: ssmall_done:
                   9705:        mov.l           (%sp)+,%d0              # load control bits into d1
                   9706:        mov.l           %a1,%a0                 # pass ptr to dst
                   9707:        bra             t_resdnrm
                   9708:
                   9709: #########################################################################
                   9710: # smod(): computes the fp MOD of the input values X,Y.                 #
                   9711: # srem(): computes the fp (IEEE) REM of the input values X,Y.          #
                   9712: #                                                                      #
                   9713: # INPUT *************************************************************** #
                   9714: #      a0 = pointer to extended precision input X                      #
                   9715: #      a1 = pointer to extended precision input Y                      #
                   9716: #      d0 = round precision,mode                                       #
                   9717: #                                                                      #
                   9718: #      The input operands X and Y can be either normalized or          #
                   9719: #      denormalized.                                                   #
                   9720: #                                                                      #
                   9721: # OUTPUT ************************************************************** #
                   9722: #      fp0 = FREM(X,Y) or FMOD(X,Y)                                    #
                   9723: #                                                                      #
                   9724: # ALGORITHM *********************************************************** #
                   9725: #                                                                      #
                   9726: #       Step 1.  Save and strip signs of X and Y: signX := sign(X),    #
                   9727: #                signY := sign(Y), X := |X|, Y := |Y|,                         #
                   9728: #                signQ := signX EOR signY. Record whether MOD or REM   #
                   9729: #                is requested.                                         #
                   9730: #                                                                      #
                   9731: #       Step 2.  Set L := expo(X)-expo(Y), k := 0, Q := 0.             #
                   9732: #                If (L < 0) then                                       #
                   9733: #                   R := X, go to Step 4.                              #
                   9734: #                else                                                  #
                   9735: #                   R := 2^(-L)X, j := L.                              #
                   9736: #                endif                                                 #
                   9737: #                                                                      #
                   9738: #       Step 3.  Perform MOD(X,Y)                                      #
                   9739: #            3.1 If R = Y, go to Step 9.                               #
                   9740: #            3.2 If R > Y, then { R := R - Y, Q := Q + 1}              #
                   9741: #            3.3 If j = 0, go to Step 4.                               #
                   9742: #            3.4 k := k + 1, j := j - 1, Q := 2Q, R := 2R. Go to       #
                   9743: #                Step 3.1.                                             #
                   9744: #                                                                      #
                   9745: #       Step 4.  At this point, R = X - QY = MOD(X,Y). Set             #
                   9746: #                Last_Subtract := false (used in Step 7 below). If     #
                   9747: #                MOD is requested, go to Step 6.                       #
                   9748: #                                                                      #
                   9749: #       Step 5.  R = MOD(X,Y), but REM(X,Y) is requested.              #
                   9750: #            5.1 If R < Y/2, then R = MOD(X,Y) = REM(X,Y). Go to       #
                   9751: #                Step 6.                                               #
                   9752: #            5.2 If R > Y/2, then { set Last_Subtract := true,         #
                   9753: #                Q := Q + 1, Y := signY*Y }. Go to Step 6.             #
                   9754: #            5.3 This is the tricky case of R = Y/2. If Q is odd,      #
                   9755: #                then { Q := Q + 1, signX := -signX }.                 #
                   9756: #                                                                      #
                   9757: #       Step 6.  R := signX*R.                                         #
                   9758: #                                                                      #
                   9759: #       Step 7.  If Last_Subtract = true, R := R - Y.                  #
                   9760: #                                                                      #
                   9761: #       Step 8.  Return signQ, last 7 bits of Q, and R as required.    #
                   9762: #                                                                      #
                   9763: #       Step 9.  At this point, R = 2^(-j)*X - Q Y = Y. Thus,          #
                   9764: #                X = 2^(j)*(Q+1)Y. set Q := 2^(j)*(Q+1),               #
                   9765: #                R := 0. Return signQ, last 7 bits of Q, and R.                #
                   9766: #                                                                      #
                   9767: #########################################################################
                   9768:
                   9769:        set             Mod_Flag,L_SCR3
                   9770:        set             Sc_Flag,L_SCR3+1
                   9771:
                   9772:        set             SignY,L_SCR2
                   9773:        set             SignX,L_SCR2+2
                   9774:        set             SignQ,L_SCR3+2
                   9775:
                   9776:        set             Y,FP_SCR0
                   9777:        set             Y_Hi,Y+4
                   9778:        set             Y_Lo,Y+8
                   9779:
                   9780:        set             R,FP_SCR1
                   9781:        set             R_Hi,R+4
                   9782:        set             R_Lo,R+8
                   9783:
                   9784: Scale:
                   9785:        long            0x00010000,0x80000000,0x00000000,0x00000000
                   9786:
                   9787:        global          smod
                   9788: smod:
                   9789:        clr.b           FPSR_QBYTE(%a6)
                   9790:        mov.l           %d0,-(%sp)              # save ctrl bits
                   9791:        clr.b           Mod_Flag(%a6)
                   9792:        bra.b           Mod_Rem
                   9793:
                   9794:        global          srem
                   9795: srem:
                   9796:        clr.b           FPSR_QBYTE(%a6)
                   9797:        mov.l           %d0,-(%sp)              # save ctrl bits
                   9798:        mov.b           &0x1,Mod_Flag(%a6)
                   9799:
                   9800: Mod_Rem:
                   9801: #..Save sign of X and Y
                   9802:        movm.l          &0x3f00,-(%sp)          # save data registers
                   9803:        mov.w           SRC_EX(%a0),%d3
                   9804:        mov.w           %d3,SignY(%a6)
                   9805:        and.l           &0x00007FFF,%d3         # Y := |Y|
                   9806:
                   9807: #
                   9808:        mov.l           SRC_HI(%a0),%d4
                   9809:        mov.l           SRC_LO(%a0),%d5         # (D3,D4,D5) is |Y|
                   9810:
                   9811:        tst.l           %d3
                   9812:        bne.b           Y_Normal
                   9813:
                   9814:        mov.l           &0x00003FFE,%d3         # $3FFD + 1
                   9815:        tst.l           %d4
                   9816:        bne.b           HiY_not0
                   9817:
                   9818: HiY_0:
                   9819:        mov.l           %d5,%d4
                   9820:        clr.l           %d5
                   9821:        sub.l           &32,%d3
                   9822:        clr.l           %d6
                   9823:        bfffo           %d4{&0:&32},%d6
                   9824:        lsl.l           %d6,%d4
                   9825:        sub.l           %d6,%d3                 # (D3,D4,D5) is normalized
                   9826: #                                              ...with bias $7FFD
                   9827:        bra.b           Chk_X
                   9828:
                   9829: HiY_not0:
                   9830:        clr.l           %d6
                   9831:        bfffo           %d4{&0:&32},%d6
                   9832:        sub.l           %d6,%d3
                   9833:        lsl.l           %d6,%d4
                   9834:        mov.l           %d5,%d7                 # a copy of D5
                   9835:        lsl.l           %d6,%d5
                   9836:        neg.l           %d6
                   9837:        add.l           &32,%d6
                   9838:        lsr.l           %d6,%d7
                   9839:        or.l            %d7,%d4                 # (D3,D4,D5) normalized
                   9840: #                                       ...with bias $7FFD
                   9841:        bra.b           Chk_X
                   9842:
                   9843: Y_Normal:
                   9844:        add.l           &0x00003FFE,%d3         # (D3,D4,D5) normalized
                   9845: #                                       ...with bias $7FFD
                   9846:
                   9847: Chk_X:
                   9848:        mov.w           DST_EX(%a1),%d0
                   9849:        mov.w           %d0,SignX(%a6)
                   9850:        mov.w           SignY(%a6),%d1
                   9851:        eor.l           %d0,%d1
                   9852:        and.l           &0x00008000,%d1
                   9853:        mov.w           %d1,SignQ(%a6)          # sign(Q) obtained
                   9854:        and.l           &0x00007FFF,%d0
                   9855:        mov.l           DST_HI(%a1),%d1
                   9856:        mov.l           DST_LO(%a1),%d2         # (D0,D1,D2) is |X|
                   9857:        tst.l           %d0
                   9858:        bne.b           X_Normal
                   9859:        mov.l           &0x00003FFE,%d0
                   9860:        tst.l           %d1
                   9861:        bne.b           HiX_not0
                   9862:
                   9863: HiX_0:
                   9864:        mov.l           %d2,%d1
                   9865:        clr.l           %d2
                   9866:        sub.l           &32,%d0
                   9867:        clr.l           %d6
                   9868:        bfffo           %d1{&0:&32},%d6
                   9869:        lsl.l           %d6,%d1
                   9870:        sub.l           %d6,%d0                 # (D0,D1,D2) is normalized
                   9871: #                                       ...with bias $7FFD
                   9872:        bra.b           Init
                   9873:
                   9874: HiX_not0:
                   9875:        clr.l           %d6
                   9876:        bfffo           %d1{&0:&32},%d6
                   9877:        sub.l           %d6,%d0
                   9878:        lsl.l           %d6,%d1
                   9879:        mov.l           %d2,%d7                 # a copy of D2
                   9880:        lsl.l           %d6,%d2
                   9881:        neg.l           %d6
                   9882:        add.l           &32,%d6
                   9883:        lsr.l           %d6,%d7
                   9884:        or.l            %d7,%d1                 # (D0,D1,D2) normalized
                   9885: #                                       ...with bias $7FFD
                   9886:        bra.b           Init
                   9887:
                   9888: X_Normal:
                   9889:        add.l           &0x00003FFE,%d0         # (D0,D1,D2) normalized
                   9890: #                                       ...with bias $7FFD
                   9891:
                   9892: Init:
                   9893: #
                   9894:        mov.l           %d3,L_SCR1(%a6)         # save biased exp(Y)
                   9895:        mov.l           %d0,-(%sp)              # save biased exp(X)
                   9896:        sub.l           %d3,%d0                 # L := expo(X)-expo(Y)
                   9897:
                   9898:        clr.l           %d6                     # D6 := carry <- 0
                   9899:        clr.l           %d3                     # D3 is Q
                   9900:        mov.l           &0,%a1                  # A1 is k; j+k=L, Q=0
                   9901:
                   9902: #..(Carry,D1,D2) is R
                   9903:        tst.l           %d0
                   9904:        bge.b           Mod_Loop_pre
                   9905:
                   9906: #..expo(X) < expo(Y). Thus X = mod(X,Y)
                   9907: #
                   9908:        mov.l           (%sp)+,%d0              # restore d0
                   9909:        bra.w           Get_Mod
                   9910:
                   9911: Mod_Loop_pre:
                   9912:        addq.l          &0x4,%sp                # erase exp(X)
                   9913: #..At this point  R = 2^(-L)X; Q = 0; k = 0; and  k+j = L
                   9914: Mod_Loop:
                   9915:        tst.l           %d6                     # test carry bit
                   9916:        bgt.b           R_GT_Y
                   9917:
                   9918: #..At this point carry = 0, R = (D1,D2), Y = (D4,D5)
                   9919:        cmp.l           %d1,%d4                 # compare hi(R) and hi(Y)
                   9920:        bne.b           R_NE_Y
                   9921:        cmp.l           %d2,%d5                 # compare lo(R) and lo(Y)
                   9922:        bne.b           R_NE_Y
                   9923:
                   9924: #..At this point, R = Y
                   9925:        bra.w           Rem_is_0
                   9926:
                   9927: R_NE_Y:
                   9928: #..use the borrow of the previous compare
                   9929:        bcs.b           R_LT_Y                  # borrow is set iff R < Y
                   9930:
                   9931: R_GT_Y:
                   9932: #..If Carry is set, then Y < (Carry,D1,D2) < 2Y. Otherwise, Carry = 0
                   9933: #..and Y < (D1,D2) < 2Y. Either way, perform R - Y
                   9934:        sub.l           %d5,%d2                 # lo(R) - lo(Y)
                   9935:        subx.l          %d4,%d1                 # hi(R) - hi(Y)
                   9936:        clr.l           %d6                     # clear carry
                   9937:        addq.l          &1,%d3                  # Q := Q + 1
                   9938:
                   9939: R_LT_Y:
                   9940: #..At this point, Carry=0, R < Y. R = 2^(k-L)X - QY; k+j = L; j >= 0.
                   9941:        tst.l           %d0                     # see if j = 0.
                   9942:        beq.b           PostLoop
                   9943:
                   9944:        add.l           %d3,%d3                 # Q := 2Q
                   9945:        add.l           %d2,%d2                 # lo(R) = 2lo(R)
                   9946:        roxl.l          &1,%d1                  # hi(R) = 2hi(R) + carry
                   9947:        scs             %d6                     # set Carry if 2(R) overflows
                   9948:        addq.l          &1,%a1                  # k := k+1
                   9949:        subq.l          &1,%d0                  # j := j - 1
                   9950: #..At this point, R=(Carry,D1,D2) = 2^(k-L)X - QY, j+k=L, j >= 0, R < 2Y.
                   9951:
                   9952:        bra.b           Mod_Loop
                   9953:
                   9954: PostLoop:
                   9955: #..k = L, j = 0, Carry = 0, R = (D1,D2) = X - QY, R < Y.
                   9956:
                   9957: #..normalize R.
                   9958:        mov.l           L_SCR1(%a6),%d0         # new biased expo of R
                   9959:        tst.l           %d1
                   9960:        bne.b           HiR_not0
                   9961:
                   9962: HiR_0:
                   9963:        mov.l           %d2,%d1
                   9964:        clr.l           %d2
                   9965:        sub.l           &32,%d0
                   9966:        clr.l           %d6
                   9967:        bfffo           %d1{&0:&32},%d6
                   9968:        lsl.l           %d6,%d1
                   9969:        sub.l           %d6,%d0                 # (D0,D1,D2) is normalized
                   9970: #                                       ...with bias $7FFD
                   9971:        bra.b           Get_Mod
                   9972:
                   9973: HiR_not0:
                   9974:        clr.l           %d6
                   9975:        bfffo           %d1{&0:&32},%d6
                   9976:        bmi.b           Get_Mod                 # already normalized
                   9977:        sub.l           %d6,%d0
                   9978:        lsl.l           %d6,%d1
                   9979:        mov.l           %d2,%d7                 # a copy of D2
                   9980:        lsl.l           %d6,%d2
                   9981:        neg.l           %d6
                   9982:        add.l           &32,%d6
                   9983:        lsr.l           %d6,%d7
                   9984:        or.l            %d7,%d1                 # (D0,D1,D2) normalized
                   9985:
                   9986: #
                   9987: Get_Mod:
                   9988:        cmp.l           %d0,&0x000041FE
                   9989:        bge.b           No_Scale
                   9990: Do_Scale:
                   9991:        mov.w           %d0,R(%a6)
                   9992:        mov.l           %d1,R_Hi(%a6)
                   9993:        mov.l           %d2,R_Lo(%a6)
                   9994:        mov.l           L_SCR1(%a6),%d6
                   9995:        mov.w           %d6,Y(%a6)
                   9996:        mov.l           %d4,Y_Hi(%a6)
                   9997:        mov.l           %d5,Y_Lo(%a6)
                   9998:        fmov.x          R(%a6),%fp0             # no exception
                   9999:        mov.b           &1,Sc_Flag(%a6)
                   10000:        bra.b           ModOrRem
                   10001: No_Scale:
                   10002:        mov.l           %d1,R_Hi(%a6)
                   10003:        mov.l           %d2,R_Lo(%a6)
                   10004:        sub.l           &0x3FFE,%d0
                   10005:        mov.w           %d0,R(%a6)
                   10006:        mov.l           L_SCR1(%a6),%d6
                   10007:        sub.l           &0x3FFE,%d6
                   10008:        mov.l           %d6,L_SCR1(%a6)
                   10009:        fmov.x          R(%a6),%fp0
                   10010:        mov.w           %d6,Y(%a6)
                   10011:        mov.l           %d4,Y_Hi(%a6)
                   10012:        mov.l           %d5,Y_Lo(%a6)
                   10013:        clr.b           Sc_Flag(%a6)
                   10014:
                   10015: #
                   10016: ModOrRem:
                   10017:        tst.b           Mod_Flag(%a6)
                   10018:        beq.b           Fix_Sign
                   10019:
                   10020:        mov.l           L_SCR1(%a6),%d6         # new biased expo(Y)
                   10021:        subq.l          &1,%d6                  # biased expo(Y/2)
                   10022:        cmp.l           %d0,%d6
                   10023:        blt.b           Fix_Sign
                   10024:        bgt.b           Last_Sub
                   10025:
                   10026:        cmp.l           %d1,%d4
                   10027:        bne.b           Not_EQ
                   10028:        cmp.l           %d2,%d5
                   10029:        bne.b           Not_EQ
                   10030:        bra.w           Tie_Case
                   10031:
                   10032: Not_EQ:
                   10033:        bcs.b           Fix_Sign
                   10034:
                   10035: Last_Sub:
                   10036: #
                   10037:        fsub.x          Y(%a6),%fp0             # no exceptions
                   10038:        addq.l          &1,%d3                  # Q := Q + 1
                   10039:
                   10040: #
                   10041: Fix_Sign:
                   10042: #..Get sign of X
                   10043:        mov.w           SignX(%a6),%d6
                   10044:        bge.b           Get_Q
                   10045:        fneg.x          %fp0
                   10046:
                   10047: #..Get Q
                   10048: #
                   10049: Get_Q:
                   10050:        clr.l           %d6
                   10051:        mov.w           SignQ(%a6),%d6          # D6 is sign(Q)
                   10052:        mov.l           &8,%d7
                   10053:        lsr.l           %d7,%d6
                   10054:        and.l           &0x0000007F,%d3         # 7 bits of Q
                   10055:        or.l            %d6,%d3                 # sign and bits of Q
                   10056: #      swap            %d3
                   10057: #      fmov.l          %fpsr,%d6
                   10058: #      and.l           &0xFF00FFFF,%d6
                   10059: #      or.l            %d3,%d6
                   10060: #      fmov.l          %d6,%fpsr               # put Q in fpsr
                   10061:        mov.b           %d3,FPSR_QBYTE(%a6)     # put Q in fpsr
                   10062:
                   10063: #
                   10064: Restore:
                   10065:        movm.l          (%sp)+,&0xfc            #  {%d2-%d7}
                   10066:        mov.l           (%sp)+,%d0
                   10067:        fmov.l          %d0,%fpcr
                   10068:        tst.b           Sc_Flag(%a6)
                   10069:        beq.b           Finish
                   10070:        mov.b           &FMUL_OP,%d1            # last inst is MUL
                   10071:        fmul.x          Scale(%pc),%fp0         # may cause underflow
                   10072:        bra             t_catch2
                   10073: # the '040 package did this apparently to see if the dst operand for the
                   10074: # preceding fmul was a denorm. but, it better not have been since the
                   10075: # algorithm just got done playing with fp0 and expected no exceptions
                   10076: # as a result. trust me...
                   10077: #      bra             t_avoid_unsupp          # check for denorm as a
                   10078: #                                              ;result of the scaling
                   10079:
                   10080: Finish:
                   10081:        mov.b           &FMOV_OP,%d1            # last inst is MOVE
                   10082:        fmov.x          %fp0,%fp0               # capture exceptions & round
                   10083:        bra             t_catch2
                   10084:
                   10085: Rem_is_0:
                   10086: #..R = 2^(-j)X - Q Y = Y, thus R = 0 and quotient = 2^j (Q+1)
                   10087:        addq.l          &1,%d3
                   10088:        cmp.l           %d0,&8                  # D0 is j
                   10089:        bge.b           Q_Big
                   10090:
                   10091:        lsl.l           %d0,%d3
                   10092:        bra.b           Set_R_0
                   10093:
                   10094: Q_Big:
                   10095:        clr.l           %d3
                   10096:
                   10097: Set_R_0:
                   10098:        fmov.s          &0x00000000,%fp0
                   10099:        clr.b           Sc_Flag(%a6)
                   10100:        bra.w           Fix_Sign
                   10101:
                   10102: Tie_Case:
                   10103: #..Check parity of Q
                   10104:        mov.l           %d3,%d6
                   10105:        and.l           &0x00000001,%d6
                   10106:        tst.l           %d6
                   10107:        beq.w           Fix_Sign                # Q is even
                   10108:
                   10109: #..Q is odd, Q := Q + 1, signX := -signX
                   10110:        addq.l          &1,%d3
                   10111:        mov.w           SignX(%a6),%d6
                   10112:        eor.l           &0x00008000,%d6
                   10113:        mov.w           %d6,SignX(%a6)
                   10114:        bra.w           Fix_Sign
                   10115:
                   10116: qnan:  long            0x7fff0000, 0xffffffff, 0xffffffff
                   10117:
                   10118: #########################################################################
                   10119: # XDEF ****************************************************************        #
                   10120: #      t_dz(): Handle DZ exception during transcendental emulation.    #
                   10121: #              Sets N bit according to sign of source operand.         #
                   10122: #      t_dz2(): Handle DZ exception during transcendental emulation.   #
                   10123: #               Sets N bit always.                                     #
                   10124: #                                                                      #
                   10125: # XREF ****************************************************************        #
                   10126: #      None                                                            #
                   10127: #                                                                      #
                   10128: # INPUT ***************************************************************        #
                   10129: #      a0 = pointer to source operand                                  #
                   10130: #                                                                      #
                   10131: # OUTPUT **************************************************************        #
                   10132: #      fp0 = default result                                            #
                   10133: #                                                                      #
                   10134: # ALGORITHM ***********************************************************        #
                   10135: #      - Store properly signed INF into fp0.                           #
                   10136: #      - Set FPSR exception status dz bit, ccode inf bit, and          #
                   10137: #        accrued dz bit.                                               #
                   10138: #                                                                      #
                   10139: #########################################################################
                   10140:
                   10141:        global          t_dz
                   10142: t_dz:
                   10143:        tst.b           SRC_EX(%a0)             # no; is src negative?
                   10144:        bmi.b           t_dz2                   # yes
                   10145:
                   10146: dz_pinf:
                   10147:        fmov.s          &0x7f800000,%fp0        # return +INF in fp0
                   10148:        ori.l           &dzinf_mask,USER_FPSR(%a6) # set I/DZ/ADZ
                   10149:        rts
                   10150:
                   10151:        global          t_dz2
                   10152: t_dz2:
                   10153:        fmov.s          &0xff800000,%fp0        # return -INF in fp0
                   10154:        ori.l           &dzinf_mask+neg_mask,USER_FPSR(%a6) # set N/I/DZ/ADZ
                   10155:        rts
                   10156:
                   10157: #################################################################
                   10158: # OPERR exception:                                             #
                   10159: #      - set FPSR exception status operr bit, condition code   #
                   10160: #        nan bit; Store default NAN into fp0                   #
                   10161: #################################################################
                   10162:        global          t_operr
                   10163: t_operr:
                   10164:        ori.l           &opnan_mask,USER_FPSR(%a6) # set NaN/OPERR/AIOP
                   10165:        fmovm.x         qnan(%pc),&0x80         # return default NAN in fp0
                   10166:        rts
                   10167:
                   10168: #################################################################
                   10169: # Extended DENORM:                                             #
                   10170: #      - For all functions that have a denormalized input and  #
                   10171: #        that f(x)=x, this is the entry point.                 #
                   10172: #      - we only return the EXOP here if either underflow or   #
                   10173: #        inexact is enabled.                                   #
                   10174: #################################################################
                   10175:
                   10176: # Entry point for scale w/ extended denorm. The function does
                   10177: # NOT set INEX2/AUNFL/AINEX.
                   10178:        global          t_resdnrm
                   10179: t_resdnrm:
                   10180:        ori.l           &unfl_mask,USER_FPSR(%a6) # set UNFL
                   10181:        bra.b           xdnrm_con
                   10182:
                   10183:        global          t_extdnrm
                   10184: t_extdnrm:
                   10185:        ori.l           &unfinx_mask,USER_FPSR(%a6) # set UNFL/INEX2/AUNFL/AINEX
                   10186:
                   10187: xdnrm_con:
                   10188:        mov.l           %a0,%a1                 # make copy of src ptr
                   10189:        mov.l           %d0,%d1                 # make copy of rnd prec,mode
                   10190:        andi.b          &0xc0,%d1               # extended precision?
                   10191:        bne.b           xdnrm_sd                # no
                   10192:
                   10193: # result precision is extended.
                   10194:        tst.b           LOCAL_EX(%a0)           # is denorm negative?
                   10195:        bpl.b           xdnrm_exit              # no
                   10196:
                   10197:        bset            &neg_bit,FPSR_CC(%a6)   # yes; set 'N' ccode bit
                   10198:        bra.b           xdnrm_exit
                   10199:
                   10200: # result precision is single or double
                   10201: xdnrm_sd:
                   10202:        mov.l           %a1,-(%sp)
                   10203:        tst.b           LOCAL_EX(%a0)           # is denorm pos or neg?
                   10204:        smi.b           %d1                     # set d0 accodingly
                   10205:        bsr.l           unf_sub
                   10206:        mov.l           (%sp)+,%a1
                   10207: xdnrm_exit:
                   10208:        fmovm.x         (%a0),&0x80             # return default result in fp0
                   10209:
                   10210:        mov.b           FPCR_ENABLE(%a6),%d0
                   10211:        andi.b          &0x0a,%d0               # is UNFL or INEX enabled?
                   10212:        bne.b           xdnrm_ena               # yes
                   10213:        rts
                   10214:
                   10215: ################
                   10216: # unfl enabled #
                   10217: ################
                   10218: # we have a DENORM that needs to be converted into an EXOP.
                   10219: # so, normalize the mantissa, add 0x6000 to the new exponent,
                   10220: # and return the result in fp1.
                   10221: xdnrm_ena:
                   10222:        mov.w           LOCAL_EX(%a1),FP_SCR0_EX(%a6)
                   10223:        mov.l           LOCAL_HI(%a1),FP_SCR0_HI(%a6)
                   10224:        mov.l           LOCAL_LO(%a1),FP_SCR0_LO(%a6)
                   10225:
                   10226:        lea             FP_SCR0(%a6),%a0
                   10227:        bsr.l           norm                    # normalize mantissa
                   10228:        addi.l          &0x6000,%d0             # add extra bias
                   10229:        andi.w          &0x8000,FP_SCR0_EX(%a6) # keep old sign
                   10230:        or.w            %d0,FP_SCR0_EX(%a6)     # insert new exponent
                   10231:
                   10232:        fmovm.x         FP_SCR0(%a6),&0x40      # return EXOP in fp1
                   10233:        rts
                   10234:
                   10235: #################################################################
                   10236: # UNFL exception:                                              #
                   10237: #      - This routine is for cases where even an EXOP isn't    #
                   10238: #        large enough to hold the range of this result.        #
                   10239: #        In such a case, the EXOP equals zero.                 #
                   10240: #      - Return the default result to the proper precision     #
                   10241: #        with the sign of this result being the same as that   #
                   10242: #        of the src operand.                                   #
                   10243: #      - t_unfl2() is provided to force the result sign to     #
                   10244: #        positive which is the desired result for fetox().     #
                   10245: #################################################################
                   10246:        global          t_unfl
                   10247: t_unfl:
                   10248:        ori.l           &unfinx_mask,USER_FPSR(%a6) # set UNFL/INEX2/AUNFL/AINEX
                   10249:
                   10250:        tst.b           (%a0)                   # is result pos or neg?
                   10251:        smi.b           %d1                     # set d1 accordingly
                   10252:        bsr.l           unf_sub                 # calc default unfl result
                   10253:        fmovm.x         (%a0),&0x80             # return default result in fp0
                   10254:
                   10255:        fmov.s          &0x00000000,%fp1        # return EXOP in fp1
                   10256:        rts
                   10257:
                   10258: # t_unfl2 ALWAYS tells unf_sub to create a positive result
                   10259:        global          t_unfl2
                   10260: t_unfl2:
                   10261:        ori.l           &unfinx_mask,USER_FPSR(%a6) # set UNFL/INEX2/AUNFL/AINEX
                   10262:
                   10263:        sf.b            %d1                     # set d0 to represent positive
                   10264:        bsr.l           unf_sub                 # calc default unfl result
                   10265:        fmovm.x         (%a0),&0x80             # return default result in fp0
                   10266:
                   10267:        fmov.s          &0x0000000,%fp1         # return EXOP in fp1
                   10268:        rts
                   10269:
                   10270: #################################################################
                   10271: # OVFL exception:                                              #
                   10272: #      - This routine is for cases where even an EXOP isn't    #
                   10273: #        large enough to hold the range of this result.        #
                   10274: #      - Return the default result to the proper precision     #
                   10275: #        with the sign of this result being the same as that   #
                   10276: #        of the src operand.                                   #
                   10277: #      - t_ovfl2() is provided to force the result sign to     #
                   10278: #        positive which is the desired result for fcosh().     #
                   10279: #      - t_ovfl_sc() is provided for scale() which only sets   #
                   10280: #        the inexact bits if the number is inexact for the     #
                   10281: #        precision indicated.                                  #
                   10282: #################################################################
                   10283:
                   10284:        global          t_ovfl_sc
                   10285: t_ovfl_sc:
                   10286:        ori.l           &ovfl_inx_mask,USER_FPSR(%a6) # set OVFL/AOVFL/AINEX
                   10287:
                   10288:        mov.b           %d0,%d1                 # fetch rnd mode/prec
                   10289:        andi.b          &0xc0,%d1               # extract rnd prec
                   10290:        beq.b           ovfl_work               # prec is extended
                   10291:
                   10292:        tst.b           LOCAL_HI(%a0)           # is dst a DENORM?
                   10293:        bmi.b           ovfl_sc_norm            # no
                   10294:
                   10295: # dst op is a DENORM. we have to normalize the mantissa to see if the
                   10296: # result would be inexact for the given precision. make a copy of the
                   10297: # dst so we don't screw up the version passed to us.
                   10298:        mov.w           LOCAL_EX(%a0),FP_SCR0_EX(%a6)
                   10299:        mov.l           LOCAL_HI(%a0),FP_SCR0_HI(%a6)
                   10300:        mov.l           LOCAL_LO(%a0),FP_SCR0_LO(%a6)
                   10301:        lea             FP_SCR0(%a6),%a0        # pass ptr to FP_SCR0
                   10302:        movm.l          &0xc080,-(%sp)          # save d0-d1/a0
                   10303:        bsr.l           norm                    # normalize mantissa
                   10304:        movm.l          (%sp)+,&0x0103          # restore d0-d1/a0
                   10305:
                   10306: ovfl_sc_norm:
                   10307:        cmpi.b          %d1,&0x40               # is prec dbl?
                   10308:        bne.b           ovfl_sc_dbl             # no; sgl
                   10309: ovfl_sc_sgl:
                   10310:        tst.l           LOCAL_LO(%a0)           # is lo lw of sgl set?
                   10311:        bne.b           ovfl_sc_inx             # yes
                   10312:        tst.b           3+LOCAL_HI(%a0)         # is lo byte of hi lw set?
                   10313:        bne.b           ovfl_sc_inx             # yes
                   10314:        bra.b           ovfl_work               # don't set INEX2
                   10315: ovfl_sc_dbl:
                   10316:        mov.l           LOCAL_LO(%a0),%d1       # are any of lo 11 bits of
                   10317:        andi.l          &0x7ff,%d1              # dbl mantissa set?
                   10318:        beq.b           ovfl_work               # no; don't set INEX2
                   10319: ovfl_sc_inx:
                   10320:        ori.l           &inex2_mask,USER_FPSR(%a6) # set INEX2
                   10321:        bra.b           ovfl_work               # continue
                   10322:
                   10323:        global          t_ovfl
                   10324: t_ovfl:
                   10325:        ori.l           &ovfinx_mask,USER_FPSR(%a6) # set OVFL/INEX2/AOVFL/AINEX
                   10326:
                   10327: ovfl_work:
                   10328:        tst.b           LOCAL_EX(%a0)           # what is the sign?
                   10329:        smi.b           %d1                     # set d1 accordingly
                   10330:        bsr.l           ovf_res                 # calc default ovfl result
                   10331:        mov.b           %d0,FPSR_CC(%a6)        # insert new ccodes
                   10332:        fmovm.x         (%a0),&0x80             # return default result in fp0
                   10333:
                   10334:        fmov.s          &0x00000000,%fp1        # return EXOP in fp1
                   10335:        rts
                   10336:
                   10337: # t_ovfl2 ALWAYS tells ovf_res to create a positive result
                   10338:        global          t_ovfl2
                   10339: t_ovfl2:
                   10340:        ori.l           &ovfinx_mask,USER_FPSR(%a6) # set OVFL/INEX2/AOVFL/AINEX
                   10341:
                   10342:        sf.b            %d1                     # clear sign flag for positive
                   10343:        bsr.l           ovf_res                 # calc default ovfl result
                   10344:        mov.b           %d0,FPSR_CC(%a6)        # insert new ccodes
                   10345:        fmovm.x         (%a0),&0x80             # return default result in fp0
                   10346:
                   10347:        fmov.s          &0x00000000,%fp1        # return EXOP in fp1
                   10348:        rts
                   10349:
                   10350: #################################################################
                   10351: # t_catch():                                                   #
                   10352: #      - the last operation of a transcendental emulation      #
                   10353: #        routine may have caused an underflow or overflow.     #
                   10354: #        we find out if this occurred by doing an fsave and    #
                   10355: #        checking the exception bit. if one did occur, then we #
                   10356: #        jump to fgen_except() which creates the default       #
                   10357: #        result and EXOP for us.                               #
                   10358: #################################################################
                   10359:        global          t_catch
                   10360: t_catch:
                   10361:
                   10362:        fsave           -(%sp)
                   10363:        tst.b           0x2(%sp)
                   10364:        bmi.b           catch
                   10365:        add.l           &0xc,%sp
                   10366:
                   10367: #################################################################
                   10368: # INEX2 exception:                                             #
                   10369: #      - The inex2 and ainex bits are set.                     #
                   10370: #################################################################
                   10371:        global          t_inx2
                   10372: t_inx2:
                   10373:        fblt.w          t_minx2
                   10374:        fbeq.w          inx2_zero
                   10375:
                   10376:        global          t_pinx2
                   10377: t_pinx2:
                   10378:        ori.w           &inx2a_mask,2+USER_FPSR(%a6) # set INEX2/AINEX
                   10379:        rts
                   10380:
                   10381:        global          t_minx2
                   10382: t_minx2:
                   10383:        ori.l           &inx2a_mask+neg_mask,USER_FPSR(%a6) # set N/INEX2/AINEX
                   10384:        rts
                   10385:
                   10386: inx2_zero:
                   10387:        mov.b           &z_bmask,FPSR_CC(%a6)
                   10388:        ori.w           &inx2a_mask,2+USER_FPSR(%a6) # set INEX2/AINEX
                   10389:        rts
                   10390:
                   10391: # an underflow or overflow exception occurred.
                   10392: # we must set INEX/AINEX since the fmul/fdiv/fmov emulation may not!
                   10393: catch:
                   10394:        ori.w           &inx2a_mask,FPSR_EXCEPT(%a6)
                   10395: catch2:
                   10396:        bsr.l           fgen_except
                   10397:        add.l           &0xc,%sp
                   10398:        rts
                   10399:
                   10400:        global          t_catch2
                   10401: t_catch2:
                   10402:
                   10403:        fsave           -(%sp)
                   10404:
                   10405:        tst.b           0x2(%sp)
                   10406:        bmi.b           catch2
                   10407:        add.l           &0xc,%sp
                   10408:
                   10409:        fmov.l          %fpsr,%d0
                   10410:        or.l            %d0,USER_FPSR(%a6)
                   10411:
                   10412:        rts
                   10413:
                   10414: #########################################################################
                   10415:
                   10416: #########################################################################
                   10417: # unf_res(): underflow default result calculation for transcendentals  #
                   10418: #                                                                      #
                   10419: # INPUT:                                                               #
                   10420: #      d0   : rnd mode,precision                                       #
                   10421: #      d1.b : sign bit of result ('11111111 = (-) ; '00000000 = (+))   #
                   10422: # OUTPUT:                                                              #
                   10423: #      a0   : points to result (in instruction memory)                 #
                   10424: #########################################################################
                   10425: unf_sub:
                   10426:        ori.l           &unfinx_mask,USER_FPSR(%a6)
                   10427:
                   10428:        andi.w          &0x10,%d1               # keep sign bit in 4th spot
                   10429:
                   10430:        lsr.b           &0x4,%d0                # shift rnd prec,mode to lo bits
                   10431:        andi.b          &0xf,%d0                # strip hi rnd mode bit
                   10432:        or.b            %d1,%d0                 # concat {sgn,mode,prec}
                   10433:
                   10434:        mov.l           %d0,%d1                 # make a copy
                   10435:        lsl.b           &0x1,%d1                # mult index 2 by 2
                   10436:
                   10437:        mov.b           (tbl_unf_cc.b,%pc,%d0.w*1),FPSR_CC(%a6) # insert ccode bits
                   10438:        lea             (tbl_unf_result.b,%pc,%d1.w*8),%a0 # grab result ptr
                   10439:        rts
                   10440:
                   10441: tbl_unf_cc:
                   10442:        byte            0x4, 0x4, 0x4, 0x0
                   10443:        byte            0x4, 0x4, 0x4, 0x0
                   10444:        byte            0x4, 0x4, 0x4, 0x0
                   10445:        byte            0x0, 0x0, 0x0, 0x0
                   10446:        byte            0x8+0x4, 0x8+0x4, 0x8, 0x8+0x4
                   10447:        byte            0x8+0x4, 0x8+0x4, 0x8, 0x8+0x4
                   10448:        byte            0x8+0x4, 0x8+0x4, 0x8, 0x8+0x4
                   10449:
                   10450: tbl_unf_result:
                   10451:        long            0x00000000, 0x00000000, 0x00000000, 0x0 # ZERO;ext
                   10452:        long            0x00000000, 0x00000000, 0x00000000, 0x0 # ZERO;ext
                   10453:        long            0x00000000, 0x00000000, 0x00000000, 0x0 # ZERO;ext
                   10454:        long            0x00000000, 0x00000000, 0x00000001, 0x0 # MIN; ext
                   10455:
                   10456:        long            0x3f810000, 0x00000000, 0x00000000, 0x0 # ZERO;sgl
                   10457:        long            0x3f810000, 0x00000000, 0x00000000, 0x0 # ZERO;sgl
                   10458:        long            0x3f810000, 0x00000000, 0x00000000, 0x0 # ZERO;sgl
                   10459:        long            0x3f810000, 0x00000100, 0x00000000, 0x0 # MIN; sgl
                   10460:
                   10461:        long            0x3c010000, 0x00000000, 0x00000000, 0x0 # ZERO;dbl
                   10462:        long            0x3c010000, 0x00000000, 0x00000000, 0x0 # ZER0;dbl
                   10463:        long            0x3c010000, 0x00000000, 0x00000000, 0x0 # ZERO;dbl
                   10464:        long            0x3c010000, 0x00000000, 0x00000800, 0x0 # MIN; dbl
                   10465:
                   10466:        long            0x0,0x0,0x0,0x0
                   10467:        long            0x0,0x0,0x0,0x0
                   10468:        long            0x0,0x0,0x0,0x0
                   10469:        long            0x0,0x0,0x0,0x0
                   10470:
                   10471:        long            0x80000000, 0x00000000, 0x00000000, 0x0 # ZERO;ext
                   10472:        long            0x80000000, 0x00000000, 0x00000000, 0x0 # ZERO;ext
                   10473:        long            0x80000000, 0x00000000, 0x00000001, 0x0 # MIN; ext
                   10474:        long            0x80000000, 0x00000000, 0x00000000, 0x0 # ZERO;ext
                   10475:
                   10476:        long            0xbf810000, 0x00000000, 0x00000000, 0x0 # ZERO;sgl
                   10477:        long            0xbf810000, 0x00000000, 0x00000000, 0x0 # ZERO;sgl
                   10478:        long            0xbf810000, 0x00000100, 0x00000000, 0x0 # MIN; sgl
                   10479:        long            0xbf810000, 0x00000000, 0x00000000, 0x0 # ZERO;sgl
                   10480:
                   10481:        long            0xbc010000, 0x00000000, 0x00000000, 0x0 # ZERO;dbl
                   10482:        long            0xbc010000, 0x00000000, 0x00000000, 0x0 # ZERO;dbl
                   10483:        long            0xbc010000, 0x00000000, 0x00000800, 0x0 # MIN; dbl
                   10484:        long            0xbc010000, 0x00000000, 0x00000000, 0x0 # ZERO;dbl
                   10485:
                   10486: ############################################################
                   10487:
                   10488: #########################################################################
                   10489: # src_zero(): Return signed zero according to sign of src operand.     #
                   10490: #########################################################################
                   10491:        global          src_zero
                   10492: src_zero:
                   10493:        tst.b           SRC_EX(%a0)             # get sign of src operand
                   10494:        bmi.b           ld_mzero                # if neg, load neg zero
                   10495:
                   10496: #
                   10497: # ld_pzero(): return a positive zero.
                   10498: #
                   10499:        global          ld_pzero
                   10500: ld_pzero:
                   10501:        fmov.s          &0x00000000,%fp0        # load +0
                   10502:        mov.b           &z_bmask,FPSR_CC(%a6)   # set 'Z' ccode bit
                   10503:        rts
                   10504:
                   10505: # ld_mzero(): return a negative zero.
                   10506:        global          ld_mzero
                   10507: ld_mzero:
                   10508:        fmov.s          &0x80000000,%fp0        # load -0
                   10509:        mov.b           &neg_bmask+z_bmask,FPSR_CC(%a6) # set 'N','Z' ccode bits
                   10510:        rts
                   10511:
                   10512: #########################################################################
                   10513: # dst_zero(): Return signed zero according to sign of dst operand.     #
                   10514: #########################################################################
                   10515:        global          dst_zero
                   10516: dst_zero:
                   10517:        tst.b           DST_EX(%a1)             # get sign of dst operand
                   10518:        bmi.b           ld_mzero                # if neg, load neg zero
                   10519:        bra.b           ld_pzero                # load positive zero
                   10520:
                   10521: #########################################################################
                   10522: # src_inf(): Return signed inf according to sign of src operand.       #
                   10523: #########################################################################
                   10524:        global          src_inf
                   10525: src_inf:
                   10526:        tst.b           SRC_EX(%a0)             # get sign of src operand
                   10527:        bmi.b           ld_minf                 # if negative branch
                   10528:
                   10529: #
                   10530: # ld_pinf(): return a positive infinity.
                   10531: #
                   10532:        global          ld_pinf
                   10533: ld_pinf:
                   10534:        fmov.s          &0x7f800000,%fp0        # load +INF
                   10535:        mov.b           &inf_bmask,FPSR_CC(%a6) # set 'INF' ccode bit
                   10536:        rts
                   10537:
                   10538: #
                   10539: # ld_minf():return a negative infinity.
                   10540: #
                   10541:        global          ld_minf
                   10542: ld_minf:
                   10543:        fmov.s          &0xff800000,%fp0        # load -INF
                   10544:        mov.b           &neg_bmask+inf_bmask,FPSR_CC(%a6) # set 'N','I' ccode bits
                   10545:        rts
                   10546:
                   10547: #########################################################################
                   10548: # dst_inf(): Return signed inf according to sign of dst operand.       #
                   10549: #########################################################################
                   10550:        global          dst_inf
                   10551: dst_inf:
                   10552:        tst.b           DST_EX(%a1)             # get sign of dst operand
                   10553:        bmi.b           ld_minf                 # if negative branch
                   10554:        bra.b           ld_pinf
                   10555:
                   10556:        global          szr_inf
                   10557: #################################################################
                   10558: # szr_inf(): Return +ZERO for a negative src operand or                #
                   10559: #                  +INF for a positive src operand.            #
                   10560: #           Routine used for fetox, ftwotox, and ftentox.      #
                   10561: #################################################################
                   10562: szr_inf:
                   10563:        tst.b           SRC_EX(%a0)             # check sign of source
                   10564:        bmi.b           ld_pzero
                   10565:        bra.b           ld_pinf
                   10566:
                   10567: #########################################################################
                   10568: # sopr_inf(): Return +INF for a positive src operand or                        #
                   10569: #            jump to operand error routine for a negative src operand. #
                   10570: #            Routine used for flogn, flognp1, flog10, and flog2.       #
                   10571: #########################################################################
                   10572:        global          sopr_inf
                   10573: sopr_inf:
                   10574:        tst.b           SRC_EX(%a0)             # check sign of source
                   10575:        bmi.w           t_operr
                   10576:        bra.b           ld_pinf
                   10577:
                   10578: #################################################################
                   10579: # setoxm1i(): Return minus one for a negative src operand or   #
                   10580: #            positive infinity for a positive src operand.     #
                   10581: #            Routine used for fetoxm1.                         #
                   10582: #################################################################
                   10583:        global          setoxm1i
                   10584: setoxm1i:
                   10585:        tst.b           SRC_EX(%a0)             # check sign of source
                   10586:        bmi.b           ld_mone
                   10587:        bra.b           ld_pinf
                   10588:
                   10589: #########################################################################
                   10590: # src_one(): Return signed one according to sign of src operand.       #
                   10591: #########################################################################
                   10592:        global          src_one
                   10593: src_one:
                   10594:        tst.b           SRC_EX(%a0)             # check sign of source
                   10595:        bmi.b           ld_mone
                   10596:
                   10597: #
                   10598: # ld_pone(): return positive one.
                   10599: #
                   10600:        global          ld_pone
                   10601: ld_pone:
                   10602:        fmov.s          &0x3f800000,%fp0        # load +1
                   10603:        clr.b           FPSR_CC(%a6)
                   10604:        rts
                   10605:
                   10606: #
                   10607: # ld_mone(): return negative one.
                   10608: #
                   10609:        global          ld_mone
                   10610: ld_mone:
                   10611:        fmov.s          &0xbf800000,%fp0        # load -1
                   10612:        mov.b           &neg_bmask,FPSR_CC(%a6) # set 'N' ccode bit
                   10613:        rts
                   10614:
                   10615: ppiby2:        long            0x3fff0000, 0xc90fdaa2, 0x2168c235
                   10616: mpiby2:        long            0xbfff0000, 0xc90fdaa2, 0x2168c235
                   10617:
                   10618: #################################################################
                   10619: # spi_2(): Return signed PI/2 according to sign of src operand.        #
                   10620: #################################################################
                   10621:        global          spi_2
                   10622: spi_2:
                   10623:        tst.b           SRC_EX(%a0)             # check sign of source
                   10624:        bmi.b           ld_mpi2
                   10625:
                   10626: #
                   10627: # ld_ppi2(): return positive PI/2.
                   10628: #
                   10629:        global          ld_ppi2
                   10630: ld_ppi2:
                   10631:        fmov.l          %d0,%fpcr
                   10632:        fmov.x          ppiby2(%pc),%fp0        # load +pi/2
                   10633:        bra.w           t_pinx2                 # set INEX2
                   10634:
                   10635: #
                   10636: # ld_mpi2(): return negative PI/2.
                   10637: #
                   10638:        global          ld_mpi2
                   10639: ld_mpi2:
                   10640:        fmov.l          %d0,%fpcr
                   10641:        fmov.x          mpiby2(%pc),%fp0        # load -pi/2
                   10642:        bra.w           t_minx2                 # set INEX2
                   10643:
                   10644: ####################################################
                   10645: # The following routines give support for fsincos. #
                   10646: ####################################################
                   10647:
                   10648: #
                   10649: # ssincosz(): When the src operand is ZERO, store a one in the
                   10650: #            cosine register and return a ZERO in fp0 w/ the same sign
                   10651: #            as the src operand.
                   10652: #
                   10653:        global          ssincosz
                   10654: ssincosz:
                   10655:        fmov.s          &0x3f800000,%fp1
                   10656:        tst.b           SRC_EX(%a0)             # test sign
                   10657:        bpl.b           sincoszp
                   10658:        fmov.s          &0x80000000,%fp0        # return sin result in fp0
                   10659:        mov.b           &z_bmask+neg_bmask,FPSR_CC(%a6)
                   10660:        bra.b           sto_cos                 # store cosine result
                   10661: sincoszp:
                   10662:        fmov.s          &0x00000000,%fp0        # return sin result in fp0
                   10663:        mov.b           &z_bmask,FPSR_CC(%a6)
                   10664:        bra.b           sto_cos                 # store cosine result
                   10665:
                   10666: #
                   10667: # ssincosi(): When the src operand is INF, store a QNAN in the cosine
                   10668: #            register and jump to the operand error routine for negative
                   10669: #            src operands.
                   10670: #
                   10671:        global          ssincosi
                   10672: ssincosi:
                   10673:        fmov.x          qnan(%pc),%fp1          # load NAN
                   10674:        bsr.l           sto_cos                 # store cosine result
                   10675:        bra.w           t_operr
                   10676:
                   10677: #
                   10678: # ssincosqnan(): When the src operand is a QNAN, store the QNAN in the cosine
                   10679: #               register and branch to the src QNAN routine.
                   10680: #
                   10681:        global          ssincosqnan
                   10682: ssincosqnan:
                   10683:        fmov.x          LOCAL_EX(%a0),%fp1
                   10684:        bsr.l           sto_cos
                   10685:        bra.w           src_qnan
                   10686:
                   10687: #
                   10688: # ssincossnan(): When the src operand is an SNAN, store the SNAN w/ the SNAN bit set
                   10689: #               in the cosine register and branch to the src SNAN routine.
                   10690: #
                   10691:        global          ssincossnan
                   10692: ssincossnan:
                   10693:        fmov.x          LOCAL_EX(%a0),%fp1
                   10694:        bsr.l           sto_cos
                   10695:        bra.w           src_snan
                   10696:
                   10697: ########################################################################
                   10698:
                   10699: #########################################################################
                   10700: # sto_cos(): store fp1 to the fpreg designated by the CMDREG dst field.        #
                   10701: #           fp1 holds the result of the cosine portion of ssincos().   #
                   10702: #           the value in fp1 will not take any exceptions when moved.  #
                   10703: # INPUT:                                                               #
                   10704: #      fp1 : fp value to store                                         #
                   10705: # MODIFIED:                                                            #
                   10706: #      d0                                                              #
                   10707: #########################################################################
                   10708:        global          sto_cos
                   10709: sto_cos:
                   10710:        mov.b           1+EXC_CMDREG(%a6),%d0
                   10711:        andi.w          &0x7,%d0
                   10712:        mov.w           (tbl_sto_cos.b,%pc,%d0.w*2),%d0
                   10713:        jmp             (tbl_sto_cos.b,%pc,%d0.w*1)
                   10714:
                   10715: tbl_sto_cos:
                   10716:        short           sto_cos_0 - tbl_sto_cos
                   10717:        short           sto_cos_1 - tbl_sto_cos
                   10718:        short           sto_cos_2 - tbl_sto_cos
                   10719:        short           sto_cos_3 - tbl_sto_cos
                   10720:        short           sto_cos_4 - tbl_sto_cos
                   10721:        short           sto_cos_5 - tbl_sto_cos
                   10722:        short           sto_cos_6 - tbl_sto_cos
                   10723:        short           sto_cos_7 - tbl_sto_cos
                   10724:
                   10725: sto_cos_0:
                   10726:        fmovm.x         &0x40,EXC_FP0(%a6)
                   10727:        rts
                   10728: sto_cos_1:
                   10729:        fmovm.x         &0x40,EXC_FP1(%a6)
                   10730:        rts
                   10731: sto_cos_2:
                   10732:        fmov.x          %fp1,%fp2
                   10733:        rts
                   10734: sto_cos_3:
                   10735:        fmov.x          %fp1,%fp3
                   10736:        rts
                   10737: sto_cos_4:
                   10738:        fmov.x          %fp1,%fp4
                   10739:        rts
                   10740: sto_cos_5:
                   10741:        fmov.x          %fp1,%fp5
                   10742:        rts
                   10743: sto_cos_6:
                   10744:        fmov.x          %fp1,%fp6
                   10745:        rts
                   10746: sto_cos_7:
                   10747:        fmov.x          %fp1,%fp7
                   10748:        rts
                   10749:
                   10750: ##################################################################
                   10751:        global          smod_sdnrm
                   10752:        global          smod_snorm
                   10753: smod_sdnrm:
                   10754: smod_snorm:
                   10755:        mov.b           DTAG(%a6),%d1
                   10756:        beq.l           smod
                   10757:        cmpi.b          %d1,&ZERO
                   10758:        beq.w           smod_zro
                   10759:        cmpi.b          %d1,&INF
                   10760:        beq.l           t_operr
                   10761:        cmpi.b          %d1,&DENORM
                   10762:        beq.l           smod
                   10763:        cmpi.b          %d1,&SNAN
                   10764:        beq.l           dst_snan
                   10765:        bra.l           dst_qnan
                   10766:
                   10767:        global          smod_szero
                   10768: smod_szero:
                   10769:        mov.b           DTAG(%a6),%d1
                   10770:        beq.l           t_operr
                   10771:        cmpi.b          %d1,&ZERO
                   10772:        beq.l           t_operr
                   10773:        cmpi.b          %d1,&INF
                   10774:        beq.l           t_operr
                   10775:        cmpi.b          %d1,&DENORM
                   10776:        beq.l           t_operr
                   10777:        cmpi.b          %d1,&QNAN
                   10778:        beq.l           dst_qnan
                   10779:        bra.l           dst_snan
                   10780:
                   10781:        global          smod_sinf
                   10782: smod_sinf:
                   10783:        mov.b           DTAG(%a6),%d1
                   10784:        beq.l           smod_fpn
                   10785:        cmpi.b          %d1,&ZERO
                   10786:        beq.l           smod_zro
                   10787:        cmpi.b          %d1,&INF
                   10788:        beq.l           t_operr
                   10789:        cmpi.b          %d1,&DENORM
                   10790:        beq.l           smod_fpn
                   10791:        cmpi.b          %d1,&QNAN
                   10792:        beq.l           dst_qnan
                   10793:        bra.l           dst_snan
                   10794:
                   10795: smod_zro:
                   10796: srem_zro:
                   10797:        mov.b           SRC_EX(%a0),%d1         # get src sign
                   10798:        mov.b           DST_EX(%a1),%d0         # get dst sign
                   10799:        eor.b           %d0,%d1                 # get qbyte sign
                   10800:        andi.b          &0x80,%d1
                   10801:        mov.b           %d1,FPSR_QBYTE(%a6)
                   10802:        tst.b           %d0
                   10803:        bpl.w           ld_pzero
                   10804:        bra.w           ld_mzero
                   10805:
                   10806: smod_fpn:
                   10807: srem_fpn:
                   10808:        clr.b           FPSR_QBYTE(%a6)
                   10809:        mov.l           %d0,-(%sp)
                   10810:        mov.b           SRC_EX(%a0),%d1         # get src sign
                   10811:        mov.b           DST_EX(%a1),%d0         # get dst sign
                   10812:        eor.b           %d0,%d1                 # get qbyte sign
                   10813:        andi.b          &0x80,%d1
                   10814:        mov.b           %d1,FPSR_QBYTE(%a6)
                   10815:        cmpi.b          DTAG(%a6),&DENORM
                   10816:        bne.b           smod_nrm
                   10817:        lea             DST(%a1),%a0
                   10818:        mov.l           (%sp)+,%d0
                   10819:        bra             t_resdnrm
                   10820: smod_nrm:
                   10821:        fmov.l          (%sp)+,%fpcr
                   10822:        fmov.x          DST(%a1),%fp0
                   10823:        tst.b           DST_EX(%a1)
                   10824:        bmi.b           smod_nrm_neg
                   10825:        rts
                   10826:
                   10827: smod_nrm_neg:
                   10828:        mov.b           &neg_bmask,FPSR_CC(%a6) # set 'N' ccode
                   10829:        rts
                   10830:
                   10831: #########################################################################
                   10832:        global          srem_snorm
                   10833:        global          srem_sdnrm
                   10834: srem_sdnrm:
                   10835: srem_snorm:
                   10836:        mov.b           DTAG(%a6),%d1
                   10837:        beq.l           srem
                   10838:        cmpi.b          %d1,&ZERO
                   10839:        beq.w           srem_zro
                   10840:        cmpi.b          %d1,&INF
                   10841:        beq.l           t_operr
                   10842:        cmpi.b          %d1,&DENORM
                   10843:        beq.l           srem
                   10844:        cmpi.b          %d1,&QNAN
                   10845:        beq.l           dst_qnan
                   10846:        bra.l           dst_snan
                   10847:
                   10848:        global          srem_szero
                   10849: srem_szero:
                   10850:        mov.b           DTAG(%a6),%d1
                   10851:        beq.l           t_operr
                   10852:        cmpi.b          %d1,&ZERO
                   10853:        beq.l           t_operr
                   10854:        cmpi.b          %d1,&INF
                   10855:        beq.l           t_operr
                   10856:        cmpi.b          %d1,&DENORM
                   10857:        beq.l           t_operr
                   10858:        cmpi.b          %d1,&QNAN
                   10859:        beq.l           dst_qnan
                   10860:        bra.l           dst_snan
                   10861:
                   10862:        global          srem_sinf
                   10863: srem_sinf:
                   10864:        mov.b           DTAG(%a6),%d1
                   10865:        beq.w           srem_fpn
                   10866:        cmpi.b          %d1,&ZERO
                   10867:        beq.w           srem_zro
                   10868:        cmpi.b          %d1,&INF
                   10869:        beq.l           t_operr
                   10870:        cmpi.b          %d1,&DENORM
                   10871:        beq.l           srem_fpn
                   10872:        cmpi.b          %d1,&QNAN
                   10873:        beq.l           dst_qnan
                   10874:        bra.l           dst_snan
                   10875:
                   10876: #########################################################################
                   10877:        global          sscale_snorm
                   10878:        global          sscale_sdnrm
                   10879: sscale_snorm:
                   10880: sscale_sdnrm:
                   10881:        mov.b           DTAG(%a6),%d1
                   10882:        beq.l           sscale
                   10883:        cmpi.b          %d1,&ZERO
                   10884:        beq.l           dst_zero
                   10885:        cmpi.b          %d1,&INF
                   10886:        beq.l           dst_inf
                   10887:        cmpi.b          %d1,&DENORM
                   10888:        beq.l           sscale
                   10889:        cmpi.b          %d1,&QNAN
                   10890:        beq.l           dst_qnan
                   10891:        bra.l           dst_snan
                   10892:
                   10893:        global          sscale_szero
                   10894: sscale_szero:
                   10895:        mov.b           DTAG(%a6),%d1
                   10896:        beq.l           sscale
                   10897:        cmpi.b          %d1,&ZERO
                   10898:        beq.l           dst_zero
                   10899:        cmpi.b          %d1,&INF
                   10900:        beq.l           dst_inf
                   10901:        cmpi.b          %d1,&DENORM
                   10902:        beq.l           sscale
                   10903:        cmpi.b          %d1,&QNAN
                   10904:        beq.l           dst_qnan
                   10905:        bra.l           dst_snan
                   10906:
                   10907:        global          sscale_sinf
                   10908: sscale_sinf:
                   10909:        mov.b           DTAG(%a6),%d1
                   10910:        beq.l           t_operr
                   10911:        cmpi.b          %d1,&QNAN
                   10912:        beq.l           dst_qnan
                   10913:        cmpi.b          %d1,&SNAN
                   10914:        beq.l           dst_snan
                   10915:        bra.l           t_operr
                   10916:
                   10917: ########################################################################
                   10918:
                   10919: #
                   10920: # sop_sqnan(): The src op for frem/fmod/fscale was a QNAN.
                   10921: #
                   10922:        global          sop_sqnan
                   10923: sop_sqnan:
                   10924:        mov.b           DTAG(%a6),%d1
                   10925:        cmpi.b          %d1,&QNAN
                   10926:        beq.b           dst_qnan
                   10927:        cmpi.b          %d1,&SNAN
                   10928:        beq.b           dst_snan
                   10929:        bra.b           src_qnan
                   10930:
                   10931: #
                   10932: # sop_ssnan(): The src op for frem/fmod/fscale was an SNAN.
                   10933: #
                   10934:        global          sop_ssnan
                   10935: sop_ssnan:
                   10936:        mov.b           DTAG(%a6),%d1
                   10937:        cmpi.b          %d1,&QNAN
                   10938:        beq.b           dst_qnan_src_snan
                   10939:        cmpi.b          %d1,&SNAN
                   10940:        beq.b           dst_snan
                   10941:        bra.b           src_snan
                   10942:
                   10943: dst_qnan_src_snan:
                   10944:        ori.l           &snaniop_mask,USER_FPSR(%a6) # set NAN/SNAN/AIOP
                   10945:        bra.b           dst_qnan
                   10946:
                   10947: #
                   10948: # dst_qnan(): Return the dst SNAN w/ the SNAN bit set.
                   10949: #
                   10950:        global          dst_snan
                   10951: dst_snan:
                   10952:        fmov.x          DST(%a1),%fp0           # the fmove sets the SNAN bit
                   10953:        fmov.l          %fpsr,%d0               # catch resulting status
                   10954:        or.l            %d0,USER_FPSR(%a6)      # store status
                   10955:        rts
                   10956:
                   10957: #
                   10958: # dst_qnan(): Return the dst QNAN.
                   10959: #
                   10960:        global          dst_qnan
                   10961: dst_qnan:
                   10962:        fmov.x          DST(%a1),%fp0           # return the non-signalling nan
                   10963:        tst.b           DST_EX(%a1)             # set ccodes according to QNAN sign
                   10964:        bmi.b           dst_qnan_m
                   10965: dst_qnan_p:
                   10966:        mov.b           &nan_bmask,FPSR_CC(%a6)
                   10967:        rts
                   10968: dst_qnan_m:
                   10969:        mov.b           &neg_bmask+nan_bmask,FPSR_CC(%a6)
                   10970:        rts
                   10971:
                   10972: #
                   10973: # src_snan(): Return the src SNAN w/ the SNAN bit set.
                   10974: #
                   10975:        global          src_snan
                   10976: src_snan:
                   10977:        fmov.x          SRC(%a0),%fp0           # the fmove sets the SNAN bit
                   10978:        fmov.l          %fpsr,%d0               # catch resulting status
                   10979:        or.l            %d0,USER_FPSR(%a6)      # store status
                   10980:        rts
                   10981:
                   10982: #
                   10983: # src_qnan(): Return the src QNAN.
                   10984: #
                   10985:        global          src_qnan
                   10986: src_qnan:
                   10987:        fmov.x          SRC(%a0),%fp0           # return the non-signalling nan
                   10988:        tst.b           SRC_EX(%a0)             # set ccodes according to QNAN sign
                   10989:        bmi.b           dst_qnan_m
                   10990: src_qnan_p:
                   10991:        mov.b           &nan_bmask,FPSR_CC(%a6)
                   10992:        rts
                   10993: src_qnan_m:
                   10994:        mov.b           &neg_bmask+nan_bmask,FPSR_CC(%a6)
                   10995:        rts
                   10996:
                   10997: #
                   10998: # fkern2.s:
                   10999: #      These entry points are used by the exception handler
                   11000: # routines where an instruction is selected by an index into
                   11001: # a large jump table corresponding to a given instruction which
                   11002: # has been decoded. Flow continues here where we now decode
                   11003: # further accoding to the source operand type.
                   11004: #
                   11005:
                   11006:        global          fsinh
                   11007: fsinh:
                   11008:        mov.b           STAG(%a6),%d1
                   11009:        beq.l           ssinh
                   11010:        cmpi.b          %d1,&ZERO
                   11011:        beq.l           src_zero
                   11012:        cmpi.b          %d1,&INF
                   11013:        beq.l           src_inf
                   11014:        cmpi.b          %d1,&DENORM
                   11015:        beq.l           ssinhd
                   11016:        cmpi.b          %d1,&QNAN
                   11017:        beq.l           src_qnan
                   11018:        bra.l           src_snan
                   11019:
                   11020:        global          flognp1
                   11021: flognp1:
                   11022:        mov.b           STAG(%a6),%d1
                   11023:        beq.l           slognp1
                   11024:        cmpi.b          %d1,&ZERO
                   11025:        beq.l           src_zero
                   11026:        cmpi.b          %d1,&INF
                   11027:        beq.l           sopr_inf
                   11028:        cmpi.b          %d1,&DENORM
                   11029:        beq.l           slognp1d
                   11030:        cmpi.b          %d1,&QNAN
                   11031:        beq.l           src_qnan
                   11032:        bra.l           src_snan
                   11033:
                   11034:        global          fetoxm1
                   11035: fetoxm1:
                   11036:        mov.b           STAG(%a6),%d1
                   11037:        beq.l           setoxm1
                   11038:        cmpi.b          %d1,&ZERO
                   11039:        beq.l           src_zero
                   11040:        cmpi.b          %d1,&INF
                   11041:        beq.l           setoxm1i
                   11042:        cmpi.b          %d1,&DENORM
                   11043:        beq.l           setoxm1d
                   11044:        cmpi.b          %d1,&QNAN
                   11045:        beq.l           src_qnan
                   11046:        bra.l           src_snan
                   11047:
                   11048:        global          ftanh
                   11049: ftanh:
                   11050:        mov.b           STAG(%a6),%d1
                   11051:        beq.l           stanh
                   11052:        cmpi.b          %d1,&ZERO
                   11053:        beq.l           src_zero
                   11054:        cmpi.b          %d1,&INF
                   11055:        beq.l           src_one
                   11056:        cmpi.b          %d1,&DENORM
                   11057:        beq.l           stanhd
                   11058:        cmpi.b          %d1,&QNAN
                   11059:        beq.l           src_qnan
                   11060:        bra.l           src_snan
                   11061:
                   11062:        global          fatan
                   11063: fatan:
                   11064:        mov.b           STAG(%a6),%d1
                   11065:        beq.l           satan
                   11066:        cmpi.b          %d1,&ZERO
                   11067:        beq.l           src_zero
                   11068:        cmpi.b          %d1,&INF
                   11069:        beq.l           spi_2
                   11070:        cmpi.b          %d1,&DENORM
                   11071:        beq.l           satand
                   11072:        cmpi.b          %d1,&QNAN
                   11073:        beq.l           src_qnan
                   11074:        bra.l           src_snan
                   11075:
                   11076:        global          fasin
                   11077: fasin:
                   11078:        mov.b           STAG(%a6),%d1
                   11079:        beq.l           sasin
                   11080:        cmpi.b          %d1,&ZERO
                   11081:        beq.l           src_zero
                   11082:        cmpi.b          %d1,&INF
                   11083:        beq.l           t_operr
                   11084:        cmpi.b          %d1,&DENORM
                   11085:        beq.l           sasind
                   11086:        cmpi.b          %d1,&QNAN
                   11087:        beq.l           src_qnan
                   11088:        bra.l           src_snan
                   11089:
                   11090:        global          fatanh
                   11091: fatanh:
                   11092:        mov.b           STAG(%a6),%d1
                   11093:        beq.l           satanh
                   11094:        cmpi.b          %d1,&ZERO
                   11095:        beq.l           src_zero
                   11096:        cmpi.b          %d1,&INF
                   11097:        beq.l           t_operr
                   11098:        cmpi.b          %d1,&DENORM
                   11099:        beq.l           satanhd
                   11100:        cmpi.b          %d1,&QNAN
                   11101:        beq.l           src_qnan
                   11102:        bra.l           src_snan
                   11103:
                   11104:        global          fsine
                   11105: fsine:
                   11106:        mov.b           STAG(%a6),%d1
                   11107:        beq.l           ssin
                   11108:        cmpi.b          %d1,&ZERO
                   11109:        beq.l           src_zero
                   11110:        cmpi.b          %d1,&INF
                   11111:        beq.l           t_operr
                   11112:        cmpi.b          %d1,&DENORM
                   11113:        beq.l           ssind
                   11114:        cmpi.b          %d1,&QNAN
                   11115:        beq.l           src_qnan
                   11116:        bra.l           src_snan
                   11117:
                   11118:        global          ftan
                   11119: ftan:
                   11120:        mov.b           STAG(%a6),%d1
                   11121:        beq.l           stan
                   11122:        cmpi.b          %d1,&ZERO
                   11123:        beq.l           src_zero
                   11124:        cmpi.b          %d1,&INF
                   11125:        beq.l           t_operr
                   11126:        cmpi.b          %d1,&DENORM
                   11127:        beq.l           stand
                   11128:        cmpi.b          %d1,&QNAN
                   11129:        beq.l           src_qnan
                   11130:        bra.l           src_snan
                   11131:
                   11132:        global          fetox
                   11133: fetox:
                   11134:        mov.b           STAG(%a6),%d1
                   11135:        beq.l           setox
                   11136:        cmpi.b          %d1,&ZERO
                   11137:        beq.l           ld_pone
                   11138:        cmpi.b          %d1,&INF
                   11139:        beq.l           szr_inf
                   11140:        cmpi.b          %d1,&DENORM
                   11141:        beq.l           setoxd
                   11142:        cmpi.b          %d1,&QNAN
                   11143:        beq.l           src_qnan
                   11144:        bra.l           src_snan
                   11145:
                   11146:        global          ftwotox
                   11147: ftwotox:
                   11148:        mov.b           STAG(%a6),%d1
                   11149:        beq.l           stwotox
                   11150:        cmpi.b          %d1,&ZERO
                   11151:        beq.l           ld_pone
                   11152:        cmpi.b          %d1,&INF
                   11153:        beq.l           szr_inf
                   11154:        cmpi.b          %d1,&DENORM
                   11155:        beq.l           stwotoxd
                   11156:        cmpi.b          %d1,&QNAN
                   11157:        beq.l           src_qnan
                   11158:        bra.l           src_snan
                   11159:
                   11160:        global          ftentox
                   11161: ftentox:
                   11162:        mov.b           STAG(%a6),%d1
                   11163:        beq.l           stentox
                   11164:        cmpi.b          %d1,&ZERO
                   11165:        beq.l           ld_pone
                   11166:        cmpi.b          %d1,&INF
                   11167:        beq.l           szr_inf
                   11168:        cmpi.b          %d1,&DENORM
                   11169:        beq.l           stentoxd
                   11170:        cmpi.b          %d1,&QNAN
                   11171:        beq.l           src_qnan
                   11172:        bra.l           src_snan
                   11173:
                   11174:        global          flogn
                   11175: flogn:
                   11176:        mov.b           STAG(%a6),%d1
                   11177:        beq.l           slogn
                   11178:        cmpi.b          %d1,&ZERO
                   11179:        beq.l           t_dz2
                   11180:        cmpi.b          %d1,&INF
                   11181:        beq.l           sopr_inf
                   11182:        cmpi.b          %d1,&DENORM
                   11183:        beq.l           slognd
                   11184:        cmpi.b          %d1,&QNAN
                   11185:        beq.l           src_qnan
                   11186:        bra.l           src_snan
                   11187:
                   11188:        global          flog10
                   11189: flog10:
                   11190:        mov.b           STAG(%a6),%d1
                   11191:        beq.l           slog10
                   11192:        cmpi.b          %d1,&ZERO
                   11193:        beq.l           t_dz2
                   11194:        cmpi.b          %d1,&INF
                   11195:        beq.l           sopr_inf
                   11196:        cmpi.b          %d1,&DENORM
                   11197:        beq.l           slog10d
                   11198:        cmpi.b          %d1,&QNAN
                   11199:        beq.l           src_qnan
                   11200:        bra.l           src_snan
                   11201:
                   11202:        global          flog2
                   11203: flog2:
                   11204:        mov.b           STAG(%a6),%d1
                   11205:        beq.l           slog2
                   11206:        cmpi.b          %d1,&ZERO
                   11207:        beq.l           t_dz2
                   11208:        cmpi.b          %d1,&INF
                   11209:        beq.l           sopr_inf
                   11210:        cmpi.b          %d1,&DENORM
                   11211:        beq.l           slog2d
                   11212:        cmpi.b          %d1,&QNAN
                   11213:        beq.l           src_qnan
                   11214:        bra.l           src_snan
                   11215:
                   11216:        global          fcosh
                   11217: fcosh:
                   11218:        mov.b           STAG(%a6),%d1
                   11219:        beq.l           scosh
                   11220:        cmpi.b          %d1,&ZERO
                   11221:        beq.l           ld_pone
                   11222:        cmpi.b          %d1,&INF
                   11223:        beq.l           ld_pinf
                   11224:        cmpi.b          %d1,&DENORM
                   11225:        beq.l           scoshd
                   11226:        cmpi.b          %d1,&QNAN
                   11227:        beq.l           src_qnan
                   11228:        bra.l           src_snan
                   11229:
                   11230:        global          facos
                   11231: facos:
                   11232:        mov.b           STAG(%a6),%d1
                   11233:        beq.l           sacos
                   11234:        cmpi.b          %d1,&ZERO
                   11235:        beq.l           ld_ppi2
                   11236:        cmpi.b          %d1,&INF
                   11237:        beq.l           t_operr
                   11238:        cmpi.b          %d1,&DENORM
                   11239:        beq.l           sacosd
                   11240:        cmpi.b          %d1,&QNAN
                   11241:        beq.l           src_qnan
                   11242:        bra.l           src_snan
                   11243:
                   11244:        global          fcos
                   11245: fcos:
                   11246:        mov.b           STAG(%a6),%d1
                   11247:        beq.l           scos
                   11248:        cmpi.b          %d1,&ZERO
                   11249:        beq.l           ld_pone
                   11250:        cmpi.b          %d1,&INF
                   11251:        beq.l           t_operr
                   11252:        cmpi.b          %d1,&DENORM
                   11253:        beq.l           scosd
                   11254:        cmpi.b          %d1,&QNAN
                   11255:        beq.l           src_qnan
                   11256:        bra.l           src_snan
                   11257:
                   11258:        global          fgetexp
                   11259: fgetexp:
                   11260:        mov.b           STAG(%a6),%d1
                   11261:        beq.l           sgetexp
                   11262:        cmpi.b          %d1,&ZERO
                   11263:        beq.l           src_zero
                   11264:        cmpi.b          %d1,&INF
                   11265:        beq.l           t_operr
                   11266:        cmpi.b          %d1,&DENORM
                   11267:        beq.l           sgetexpd
                   11268:        cmpi.b          %d1,&QNAN
                   11269:        beq.l           src_qnan
                   11270:        bra.l           src_snan
                   11271:
                   11272:        global          fgetman
                   11273: fgetman:
                   11274:        mov.b           STAG(%a6),%d1
                   11275:        beq.l           sgetman
                   11276:        cmpi.b          %d1,&ZERO
                   11277:        beq.l           src_zero
                   11278:        cmpi.b          %d1,&INF
                   11279:        beq.l           t_operr
                   11280:        cmpi.b          %d1,&DENORM
                   11281:        beq.l           sgetmand
                   11282:        cmpi.b          %d1,&QNAN
                   11283:        beq.l           src_qnan
                   11284:        bra.l           src_snan
                   11285:
                   11286:        global          fsincos
                   11287: fsincos:
                   11288:        mov.b           STAG(%a6),%d1
                   11289:        beq.l           ssincos
                   11290:        cmpi.b          %d1,&ZERO
                   11291:        beq.l           ssincosz
                   11292:        cmpi.b          %d1,&INF
                   11293:        beq.l           ssincosi
                   11294:        cmpi.b          %d1,&DENORM
                   11295:        beq.l           ssincosd
                   11296:        cmpi.b          %d1,&QNAN
                   11297:        beq.l           ssincosqnan
                   11298:        bra.l           ssincossnan
                   11299:
                   11300:        global          fmod
                   11301: fmod:
                   11302:        mov.b           STAG(%a6),%d1
                   11303:        beq.l           smod_snorm
                   11304:        cmpi.b          %d1,&ZERO
                   11305:        beq.l           smod_szero
                   11306:        cmpi.b          %d1,&INF
                   11307:        beq.l           smod_sinf
                   11308:        cmpi.b          %d1,&DENORM
                   11309:        beq.l           smod_sdnrm
                   11310:        cmpi.b          %d1,&QNAN
                   11311:        beq.l           sop_sqnan
                   11312:        bra.l           sop_ssnan
                   11313:
                   11314:        global          frem
                   11315: frem:
                   11316:        mov.b           STAG(%a6),%d1
                   11317:        beq.l           srem_snorm
                   11318:        cmpi.b          %d1,&ZERO
                   11319:        beq.l           srem_szero
                   11320:        cmpi.b          %d1,&INF
                   11321:        beq.l           srem_sinf
                   11322:        cmpi.b          %d1,&DENORM
                   11323:        beq.l           srem_sdnrm
                   11324:        cmpi.b          %d1,&QNAN
                   11325:        beq.l           sop_sqnan
                   11326:        bra.l           sop_ssnan
                   11327:
                   11328:        global          fscale
                   11329: fscale:
                   11330:        mov.b           STAG(%a6),%d1
                   11331:        beq.l           sscale_snorm
                   11332:        cmpi.b          %d1,&ZERO
                   11333:        beq.l           sscale_szero
                   11334:        cmpi.b          %d1,&INF
                   11335:        beq.l           sscale_sinf
                   11336:        cmpi.b          %d1,&DENORM
                   11337:        beq.l           sscale_sdnrm
                   11338:        cmpi.b          %d1,&QNAN
                   11339:        beq.l           sop_sqnan
                   11340:        bra.l           sop_ssnan
                   11341:
                   11342: #########################################################################
                   11343: # XDEF ****************************************************************        #
                   11344: #      fgen_except(): catch an exception during transcendental         #
                   11345: #                     emulation                                        #
                   11346: #                                                                      #
                   11347: # XREF ****************************************************************        #
                   11348: #      fmul() - emulate a multiply instruction                         #
                   11349: #      fadd() - emulate an add instruction                             #
                   11350: #      fin() - emulate an fmove instruction                            #
                   11351: #                                                                      #
                   11352: # INPUT ***************************************************************        #
                   11353: #      fp0 = destination operand                                       #
                   11354: #      d0  = type of instruction that took exception                   #
                   11355: #      fsave frame = source operand                                    #
                   11356: #                                                                      #
                   11357: # OUTPUT **************************************************************        #
                   11358: #      fp0 = result                                                    #
                   11359: #      fp1 = EXOP                                                      #
                   11360: #                                                                      #
                   11361: # ALGORITHM ***********************************************************        #
                   11362: #      An exception occurred on the last instruction of the            #
                   11363: # transcendental emulation. hopefully, this won't be happening much    #
                   11364: # because it will be VERY slow.                                                #
                   11365: #      The only exceptions capable of passing through here are         #
                   11366: # Overflow, Underflow, and Unsupported Data Type.                      #
                   11367: #                                                                      #
                   11368: #########################################################################
                   11369:
                   11370:        global          fgen_except
                   11371: fgen_except:
                   11372:        cmpi.b          0x3(%sp),&0x7           # is exception UNSUPP?
                   11373:        beq.b           fge_unsupp              # yes
                   11374:
                   11375:        mov.b           &NORM,STAG(%a6)
                   11376:
                   11377: fge_cont:
                   11378:        mov.b           &NORM,DTAG(%a6)
                   11379:
                   11380: # ok, I have a problem with putting the dst op at FP_DST. the emulation
                   11381: # routines aren't supposed to alter the operands but we've just squashed
                   11382: # FP_DST here...
                   11383:
                   11384: # 8/17/93 - this turns out to be more of a "cleanliness" standpoint
                   11385: # then a potential bug. to begin with, only the dyadic functions
                   11386: # frem,fmod, and fscale would get the dst trashed here. But, for
                   11387: # the 060SP, the FP_DST is never used again anyways.
                   11388:        fmovm.x         &0x80,FP_DST(%a6)       # dst op is in fp0
                   11389:
                   11390:        lea             0x4(%sp),%a0            # pass: ptr to src op
                   11391:        lea             FP_DST(%a6),%a1         # pass: ptr to dst op
                   11392:
                   11393:        cmpi.b          %d1,&FMOV_OP
                   11394:        beq.b           fge_fin                 # it was an "fmov"
                   11395:        cmpi.b          %d1,&FADD_OP
                   11396:        beq.b           fge_fadd                # it was an "fadd"
                   11397: fge_fmul:
                   11398:        bsr.l           fmul
                   11399:        rts
                   11400: fge_fadd:
                   11401:        bsr.l           fadd
                   11402:        rts
                   11403: fge_fin:
                   11404:        bsr.l           fin
                   11405:        rts
                   11406:
                   11407: fge_unsupp:
                   11408:        mov.b           &DENORM,STAG(%a6)
                   11409:        bra.b           fge_cont
                   11410:
                   11411: #
                   11412: # This table holds the offsets of the emulation routines for each individual
                   11413: # math operation relative to the address of this table. Included are
                   11414: # routines like fadd/fmul/fabs as well as the transcendentals.
                   11415: # The location within the table is determined by the extension bits of the
                   11416: # operation longword.
                   11417: #
                   11418:
                   11419:        swbeg           &109
                   11420: tbl_unsupp:
                   11421:        long            fin             - tbl_unsupp    # 00: fmove
                   11422:        long            fint            - tbl_unsupp    # 01: fint
                   11423:        long            fsinh           - tbl_unsupp    # 02: fsinh
                   11424:        long            fintrz          - tbl_unsupp    # 03: fintrz
                   11425:        long            fsqrt           - tbl_unsupp    # 04: fsqrt
                   11426:        long            tbl_unsupp      - tbl_unsupp
                   11427:        long            flognp1         - tbl_unsupp    # 06: flognp1
                   11428:        long            tbl_unsupp      - tbl_unsupp
                   11429:        long            fetoxm1         - tbl_unsupp    # 08: fetoxm1
                   11430:        long            ftanh           - tbl_unsupp    # 09: ftanh
                   11431:        long            fatan           - tbl_unsupp    # 0a: fatan
                   11432:        long            tbl_unsupp      - tbl_unsupp
                   11433:        long            fasin           - tbl_unsupp    # 0c: fasin
                   11434:        long            fatanh          - tbl_unsupp    # 0d: fatanh
                   11435:        long            fsine           - tbl_unsupp    # 0e: fsin
                   11436:        long            ftan            - tbl_unsupp    # 0f: ftan
                   11437:        long            fetox           - tbl_unsupp    # 10: fetox
                   11438:        long            ftwotox         - tbl_unsupp    # 11: ftwotox
                   11439:        long            ftentox         - tbl_unsupp    # 12: ftentox
                   11440:        long            tbl_unsupp      - tbl_unsupp
                   11441:        long            flogn           - tbl_unsupp    # 14: flogn
                   11442:        long            flog10          - tbl_unsupp    # 15: flog10
                   11443:        long            flog2           - tbl_unsupp    # 16: flog2
                   11444:        long            tbl_unsupp      - tbl_unsupp
                   11445:        long            fabs            - tbl_unsupp    # 18: fabs
                   11446:        long            fcosh           - tbl_unsupp    # 19: fcosh
                   11447:        long            fneg            - tbl_unsupp    # 1a: fneg
                   11448:        long            tbl_unsupp      - tbl_unsupp
                   11449:        long            facos           - tbl_unsupp    # 1c: facos
                   11450:        long            fcos            - tbl_unsupp    # 1d: fcos
                   11451:        long            fgetexp         - tbl_unsupp    # 1e: fgetexp
                   11452:        long            fgetman         - tbl_unsupp    # 1f: fgetman
                   11453:        long            fdiv            - tbl_unsupp    # 20: fdiv
                   11454:        long            fmod            - tbl_unsupp    # 21: fmod
                   11455:        long            fadd            - tbl_unsupp    # 22: fadd
                   11456:        long            fmul            - tbl_unsupp    # 23: fmul
                   11457:        long            fsgldiv         - tbl_unsupp    # 24: fsgldiv
                   11458:        long            frem            - tbl_unsupp    # 25: frem
                   11459:        long            fscale          - tbl_unsupp    # 26: fscale
                   11460:        long            fsglmul         - tbl_unsupp    # 27: fsglmul
                   11461:        long            fsub            - tbl_unsupp    # 28: fsub
                   11462:        long            tbl_unsupp      - tbl_unsupp
                   11463:        long            tbl_unsupp      - tbl_unsupp
                   11464:        long            tbl_unsupp      - tbl_unsupp
                   11465:        long            tbl_unsupp      - tbl_unsupp
                   11466:        long            tbl_unsupp      - tbl_unsupp
                   11467:        long            tbl_unsupp      - tbl_unsupp
                   11468:        long            tbl_unsupp      - tbl_unsupp
                   11469:        long            fsincos         - tbl_unsupp    # 30: fsincos
                   11470:        long            fsincos         - tbl_unsupp    # 31: fsincos
                   11471:        long            fsincos         - tbl_unsupp    # 32: fsincos
                   11472:        long            fsincos         - tbl_unsupp    # 33: fsincos
                   11473:        long            fsincos         - tbl_unsupp    # 34: fsincos
                   11474:        long            fsincos         - tbl_unsupp    # 35: fsincos
                   11475:        long            fsincos         - tbl_unsupp    # 36: fsincos
                   11476:        long            fsincos         - tbl_unsupp    # 37: fsincos
                   11477:        long            fcmp            - tbl_unsupp    # 38: fcmp
                   11478:        long            tbl_unsupp      - tbl_unsupp
                   11479:        long            ftst            - tbl_unsupp    # 3a: ftst
                   11480:        long            tbl_unsupp      - tbl_unsupp
                   11481:        long            tbl_unsupp      - tbl_unsupp
                   11482:        long            tbl_unsupp      - tbl_unsupp
                   11483:        long            tbl_unsupp      - tbl_unsupp
                   11484:        long            tbl_unsupp      - tbl_unsupp
                   11485:        long            fsin            - tbl_unsupp    # 40: fsmove
                   11486:        long            fssqrt          - tbl_unsupp    # 41: fssqrt
                   11487:        long            tbl_unsupp      - tbl_unsupp
                   11488:        long            tbl_unsupp      - tbl_unsupp
                   11489:        long            fdin            - tbl_unsupp    # 44: fdmove
                   11490:        long            fdsqrt          - tbl_unsupp    # 45: fdsqrt
                   11491:        long            tbl_unsupp      - tbl_unsupp
                   11492:        long            tbl_unsupp      - tbl_unsupp
                   11493:        long            tbl_unsupp      - tbl_unsupp
                   11494:        long            tbl_unsupp      - tbl_unsupp
                   11495:        long            tbl_unsupp      - tbl_unsupp
                   11496:        long            tbl_unsupp      - tbl_unsupp
                   11497:        long            tbl_unsupp      - tbl_unsupp
                   11498:        long            tbl_unsupp      - tbl_unsupp
                   11499:        long            tbl_unsupp      - tbl_unsupp
                   11500:        long            tbl_unsupp      - tbl_unsupp
                   11501:        long            tbl_unsupp      - tbl_unsupp
                   11502:        long            tbl_unsupp      - tbl_unsupp
                   11503:        long            tbl_unsupp      - tbl_unsupp
                   11504:        long            tbl_unsupp      - tbl_unsupp
                   11505:        long            tbl_unsupp      - tbl_unsupp
                   11506:        long            tbl_unsupp      - tbl_unsupp
                   11507:        long            tbl_unsupp      - tbl_unsupp
                   11508:        long            tbl_unsupp      - tbl_unsupp
                   11509:        long            fsabs           - tbl_unsupp    # 58: fsabs
                   11510:        long            tbl_unsupp      - tbl_unsupp
                   11511:        long            fsneg           - tbl_unsupp    # 5a: fsneg
                   11512:        long            tbl_unsupp      - tbl_unsupp
                   11513:        long            fdabs           - tbl_unsupp    # 5c: fdabs
                   11514:        long            tbl_unsupp      - tbl_unsupp
                   11515:        long            fdneg           - tbl_unsupp    # 5e: fdneg
                   11516:        long            tbl_unsupp      - tbl_unsupp
                   11517:        long            fsdiv           - tbl_unsupp    # 60: fsdiv
                   11518:        long            tbl_unsupp      - tbl_unsupp
                   11519:        long            fsadd           - tbl_unsupp    # 62: fsadd
                   11520:        long            fsmul           - tbl_unsupp    # 63: fsmul
                   11521:        long            fddiv           - tbl_unsupp    # 64: fddiv
                   11522:        long            tbl_unsupp      - tbl_unsupp
                   11523:        long            fdadd           - tbl_unsupp    # 66: fdadd
                   11524:        long            fdmul           - tbl_unsupp    # 67: fdmul
                   11525:        long            fssub           - tbl_unsupp    # 68: fssub
                   11526:        long            tbl_unsupp      - tbl_unsupp
                   11527:        long            tbl_unsupp      - tbl_unsupp
                   11528:        long            tbl_unsupp      - tbl_unsupp
                   11529:        long            fdsub           - tbl_unsupp    # 6c: fdsub
                   11530:
                   11531: #########################################################################
                   11532: # XDEF ****************************************************************        #
                   11533: #      fmul(): emulates the fmul instruction                           #
                   11534: #      fsmul(): emulates the fsmul instruction                         #
                   11535: #      fdmul(): emulates the fdmul instruction                         #
                   11536: #                                                                      #
                   11537: # XREF ****************************************************************        #
                   11538: #      scale_to_zero_src() - scale src exponent to zero                #
                   11539: #      scale_to_zero_dst() - scale dst exponent to zero                #
                   11540: #      unf_res() - return default underflow result                     #
                   11541: #      ovf_res() - return default overflow result                      #
                   11542: #      res_qnan() - return QNAN result                                 #
                   11543: #      res_snan() - return SNAN result                                 #
                   11544: #                                                                      #
                   11545: # INPUT ***************************************************************        #
                   11546: #      a0 = pointer to extended precision source operand               #
                   11547: #      a1 = pointer to extended precision destination operand          #
                   11548: #      d0  rnd prec,mode                                               #
                   11549: #                                                                      #
                   11550: # OUTPUT **************************************************************        #
                   11551: #      fp0 = result                                                    #
                   11552: #      fp1 = EXOP (if exception occurred)                              #
                   11553: #                                                                      #
                   11554: # ALGORITHM ***********************************************************        #
                   11555: #      Handle NANs, infinities, and zeroes as special cases. Divide    #
                   11556: # norms/denorms into ext/sgl/dbl precision.                            #
                   11557: #      For norms/denorms, scale the exponents such that a multiply     #
                   11558: # instruction won't cause an exception. Use the regular fmul to                #
                   11559: # compute a result. Check if the regular operands would have taken     #
                   11560: # an exception. If so, return the default overflow/underflow result    #
                   11561: # and return the EXOP if exceptions are enabled. Else, scale the       #
                   11562: # result operand to the proper exponent.                               #
                   11563: #                                                                      #
                   11564: #########################################################################
                   11565:
                   11566:        align           0x10
                   11567: tbl_fmul_ovfl:
                   11568:        long            0x3fff - 0x7ffe         # ext_max
                   11569:        long            0x3fff - 0x407e         # sgl_max
                   11570:        long            0x3fff - 0x43fe         # dbl_max
                   11571: tbl_fmul_unfl:
                   11572:        long            0x3fff + 0x0001         # ext_unfl
                   11573:        long            0x3fff - 0x3f80         # sgl_unfl
                   11574:        long            0x3fff - 0x3c00         # dbl_unfl
                   11575:
                   11576:        global          fsmul
                   11577: fsmul:
                   11578:        andi.b          &0x30,%d0               # clear rnd prec
                   11579:        ori.b           &s_mode*0x10,%d0        # insert sgl prec
                   11580:        bra.b           fmul
                   11581:
                   11582:        global          fdmul
                   11583: fdmul:
                   11584:        andi.b          &0x30,%d0
                   11585:        ori.b           &d_mode*0x10,%d0        # insert dbl prec
                   11586:
                   11587:        global          fmul
                   11588: fmul:
                   11589:        mov.l           %d0,L_SCR3(%a6)         # store rnd info
                   11590:
                   11591:        clr.w           %d1
                   11592:        mov.b           DTAG(%a6),%d1
                   11593:        lsl.b           &0x3,%d1
                   11594:        or.b            STAG(%a6),%d1           # combine src tags
                   11595:        bne.w           fmul_not_norm           # optimize on non-norm input
                   11596:
                   11597: fmul_norm:
                   11598:        mov.w           DST_EX(%a1),FP_SCR1_EX(%a6)
                   11599:        mov.l           DST_HI(%a1),FP_SCR1_HI(%a6)
                   11600:        mov.l           DST_LO(%a1),FP_SCR1_LO(%a6)
                   11601:
                   11602:        mov.w           SRC_EX(%a0),FP_SCR0_EX(%a6)
                   11603:        mov.l           SRC_HI(%a0),FP_SCR0_HI(%a6)
                   11604:        mov.l           SRC_LO(%a0),FP_SCR0_LO(%a6)
                   11605:
                   11606:        bsr.l           scale_to_zero_src       # scale src exponent
                   11607:        mov.l           %d0,-(%sp)              # save scale factor 1
                   11608:
                   11609:        bsr.l           scale_to_zero_dst       # scale dst exponent
                   11610:
                   11611:        add.l           %d0,(%sp)               # SCALE_FACTOR = scale1 + scale2
                   11612:
                   11613:        mov.w           2+L_SCR3(%a6),%d1       # fetch precision
                   11614:        lsr.b           &0x6,%d1                # shift to lo bits
                   11615:        mov.l           (%sp)+,%d0              # load S.F.
                   11616:        cmp.l           %d0,(tbl_fmul_ovfl.w,%pc,%d1.w*4) # would result ovfl?
                   11617:        beq.w           fmul_may_ovfl           # result may rnd to overflow
                   11618:        blt.w           fmul_ovfl               # result will overflow
                   11619:
                   11620:        cmp.l           %d0,(tbl_fmul_unfl.w,%pc,%d1.w*4) # would result unfl?
                   11621:        beq.w           fmul_may_unfl           # result may rnd to no unfl
                   11622:        bgt.w           fmul_unfl               # result will underflow
                   11623:
                   11624: #
                   11625: # NORMAL:
                   11626: # - the result of the multiply operation will neither overflow nor underflow.
                   11627: # - do the multiply to the proper precision and rounding mode.
                   11628: # - scale the result exponent using the scale factor. if both operands were
                   11629: # normalized then we really don't need to go through this scaling. but for now,
                   11630: # this will do.
                   11631: #
                   11632: fmul_normal:
                   11633:        fmovm.x         FP_SCR1(%a6),&0x80      # load dst operand
                   11634:
                   11635:        fmov.l          L_SCR3(%a6),%fpcr       # set FPCR
                   11636:        fmov.l          &0x0,%fpsr              # clear FPSR
                   11637:
                   11638:        fmul.x          FP_SCR0(%a6),%fp0       # execute multiply
                   11639:
                   11640:        fmov.l          %fpsr,%d1               # save status
                   11641:        fmov.l          &0x0,%fpcr              # clear FPCR
                   11642:
                   11643:        or.l            %d1,USER_FPSR(%a6)      # save INEX2,N
                   11644:
                   11645: fmul_normal_exit:
                   11646:        fmovm.x         &0x80,FP_SCR0(%a6)      # store out result
                   11647:        mov.l           %d2,-(%sp)              # save d2
                   11648:        mov.w           FP_SCR0_EX(%a6),%d1     # load {sgn,exp}
                   11649:        mov.l           %d1,%d2                 # make a copy
                   11650:        andi.l          &0x7fff,%d1             # strip sign
                   11651:        andi.w          &0x8000,%d2             # keep old sign
                   11652:        sub.l           %d0,%d1                 # add scale factor
                   11653:        or.w            %d2,%d1                 # concat old sign,new exp
                   11654:        mov.w           %d1,FP_SCR0_EX(%a6)     # insert new exponent
                   11655:        mov.l           (%sp)+,%d2              # restore d2
                   11656:        fmovm.x         FP_SCR0(%a6),&0x80      # return default result in fp0
                   11657:        rts
                   11658:
                   11659: #
                   11660: # OVERFLOW:
                   11661: # - the result of the multiply operation is an overflow.
                   11662: # - do the multiply to the proper precision and rounding mode in order to
                   11663: # set the inexact bits.
                   11664: # - calculate the default result and return it in fp0.
                   11665: # - if overflow or inexact is enabled, we need a multiply result rounded to
                   11666: # extended precision. if the original operation was extended, then we have this
                   11667: # result. if the original operation was single or double, we have to do another
                   11668: # multiply using extended precision and the correct rounding mode. the result
                   11669: # of this operation then has its exponent scaled by -0x6000 to create the
                   11670: # exceptional operand.
                   11671: #
                   11672: fmul_ovfl:
                   11673:        fmovm.x         FP_SCR1(%a6),&0x80      # load dst operand
                   11674:
                   11675:        fmov.l          L_SCR3(%a6),%fpcr       # set FPCR
                   11676:        fmov.l          &0x0,%fpsr              # clear FPSR
                   11677:
                   11678:        fmul.x          FP_SCR0(%a6),%fp0       # execute multiply
                   11679:
                   11680:        fmov.l          %fpsr,%d1               # save status
                   11681:        fmov.l          &0x0,%fpcr              # clear FPCR
                   11682:
                   11683:        or.l            %d1,USER_FPSR(%a6)      # save INEX2,N
                   11684:
                   11685: # save setting this until now because this is where fmul_may_ovfl may jump in
                   11686: fmul_ovfl_tst:
                   11687:        or.l            &ovfl_inx_mask,USER_FPSR(%a6) # set ovfl/aovfl/ainex
                   11688:
                   11689:        mov.b           FPCR_ENABLE(%a6),%d1
                   11690:        andi.b          &0x13,%d1               # is OVFL or INEX enabled?
                   11691:        bne.b           fmul_ovfl_ena           # yes
                   11692:
                   11693: # calculate the default result
                   11694: fmul_ovfl_dis:
                   11695:        btst            &neg_bit,FPSR_CC(%a6)   # is result negative?
                   11696:        sne             %d1                     # set sign param accordingly
                   11697:        mov.l           L_SCR3(%a6),%d0         # pass rnd prec,mode
                   11698:        bsr.l           ovf_res                 # calculate default result
                   11699:        or.b            %d0,FPSR_CC(%a6)        # set INF,N if applicable
                   11700:        fmovm.x         (%a0),&0x80             # return default result in fp0
                   11701:        rts
                   11702:
                   11703: #
                   11704: # OVFL is enabled; Create EXOP:
                   11705: # - if precision is extended, then we have the EXOP. simply bias the exponent
                   11706: # with an extra -0x6000. if the precision is single or double, we need to
                   11707: # calculate a result rounded to extended precision.
                   11708: #
                   11709: fmul_ovfl_ena:
                   11710:        mov.l           L_SCR3(%a6),%d1
                   11711:        andi.b          &0xc0,%d1               # test the rnd prec
                   11712:        bne.b           fmul_ovfl_ena_sd        # it's sgl or dbl
                   11713:
                   11714: fmul_ovfl_ena_cont:
                   11715:        fmovm.x         &0x80,FP_SCR0(%a6)      # move result to stack
                   11716:
                   11717:        mov.l           %d2,-(%sp)              # save d2
                   11718:        mov.w           FP_SCR0_EX(%a6),%d1     # fetch {sgn,exp}
                   11719:        mov.w           %d1,%d2                 # make a copy
                   11720:        andi.l          &0x7fff,%d1             # strip sign
                   11721:        sub.l           %d0,%d1                 # add scale factor
                   11722:        subi.l          &0x6000,%d1             # subtract bias
                   11723:        andi.w          &0x7fff,%d1             # clear sign bit
                   11724:        andi.w          &0x8000,%d2             # keep old sign
                   11725:        or.w            %d2,%d1                 # concat old sign,new exp
                   11726:        mov.w           %d1,FP_SCR0_EX(%a6)     # insert new exponent
                   11727:        mov.l           (%sp)+,%d2              # restore d2
                   11728:        fmovm.x         FP_SCR0(%a6),&0x40      # return EXOP in fp1
                   11729:        bra.b           fmul_ovfl_dis
                   11730:
                   11731: fmul_ovfl_ena_sd:
                   11732:        fmovm.x         FP_SCR1(%a6),&0x80      # load dst operand
                   11733:
                   11734:        mov.l           L_SCR3(%a6),%d1
                   11735:        andi.b          &0x30,%d1               # keep rnd mode only
                   11736:        fmov.l          %d1,%fpcr               # set FPCR
                   11737:
                   11738:        fmul.x          FP_SCR0(%a6),%fp0       # execute multiply
                   11739:
                   11740:        fmov.l          &0x0,%fpcr              # clear FPCR
                   11741:        bra.b           fmul_ovfl_ena_cont
                   11742:
                   11743: #
                   11744: # may OVERFLOW:
                   11745: # - the result of the multiply operation MAY overflow.
                   11746: # - do the multiply to the proper precision and rounding mode in order to
                   11747: # set the inexact bits.
                   11748: # - calculate the default result and return it in fp0.
                   11749: #
                   11750: fmul_may_ovfl:
                   11751:        fmovm.x         FP_SCR1(%a6),&0x80      # load dst op
                   11752:
                   11753:        fmov.l          L_SCR3(%a6),%fpcr       # set FPCR
                   11754:        fmov.l          &0x0,%fpsr              # clear FPSR
                   11755:
                   11756:        fmul.x          FP_SCR0(%a6),%fp0       # execute multiply
                   11757:
                   11758:        fmov.l          %fpsr,%d1               # save status
                   11759:        fmov.l          &0x0,%fpcr              # clear FPCR
                   11760:
                   11761:        or.l            %d1,USER_FPSR(%a6)      # save INEX2,N
                   11762:
                   11763:        fabs.x          %fp0,%fp1               # make a copy of result
                   11764:        fcmp.b          %fp1,&0x2               # is |result| >= 2.b?
                   11765:        fbge.w          fmul_ovfl_tst           # yes; overflow has occurred
                   11766:
                   11767: # no, it didn't overflow; we have correct result
                   11768:        bra.w           fmul_normal_exit
                   11769:
                   11770: #
                   11771: # UNDERFLOW:
                   11772: # - the result of the multiply operation is an underflow.
                   11773: # - do the multiply to the proper precision and rounding mode in order to
                   11774: # set the inexact bits.
                   11775: # - calculate the default result and return it in fp0.
                   11776: # - if overflow or inexact is enabled, we need a multiply result rounded to
                   11777: # extended precision. if the original operation was extended, then we have this
                   11778: # result. if the original operation was single or double, we have to do another
                   11779: # multiply using extended precision and the correct rounding mode. the result
                   11780: # of this operation then has its exponent scaled by -0x6000 to create the
                   11781: # exceptional operand.
                   11782: #
                   11783: fmul_unfl:
                   11784:        bset            &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
                   11785:
                   11786: # for fun, let's use only extended precision, round to zero. then, let
                   11787: # the unf_res() routine figure out all the rest.
                   11788: # will we get the correct answer.
                   11789:        fmovm.x         FP_SCR1(%a6),&0x80      # load dst operand
                   11790:
                   11791:        fmov.l          &rz_mode*0x10,%fpcr     # set FPCR
                   11792:        fmov.l          &0x0,%fpsr              # clear FPSR
                   11793:
                   11794:        fmul.x          FP_SCR0(%a6),%fp0       # execute multiply
                   11795:
                   11796:        fmov.l          %fpsr,%d1               # save status
                   11797:        fmov.l          &0x0,%fpcr              # clear FPCR
                   11798:
                   11799:        or.l            %d1,USER_FPSR(%a6)      # save INEX2,N
                   11800:
                   11801:        mov.b           FPCR_ENABLE(%a6),%d1
                   11802:        andi.b          &0x0b,%d1               # is UNFL or INEX enabled?
                   11803:        bne.b           fmul_unfl_ena           # yes
                   11804:
                   11805: fmul_unfl_dis:
                   11806:        fmovm.x         &0x80,FP_SCR0(%a6)      # store out result
                   11807:
                   11808:        lea             FP_SCR0(%a6),%a0        # pass: result addr
                   11809:        mov.l           L_SCR3(%a6),%d1         # pass: rnd prec,mode
                   11810:        bsr.l           unf_res                 # calculate default result
                   11811:        or.b            %d0,FPSR_CC(%a6)        # unf_res2 may have set 'Z'
                   11812:        fmovm.x         FP_SCR0(%a6),&0x80      # return default result in fp0
                   11813:        rts
                   11814:
                   11815: #
                   11816: # UNFL is enabled.
                   11817: #
                   11818: fmul_unfl_ena:
                   11819:        fmovm.x         FP_SCR1(%a6),&0x40      # load dst op
                   11820:
                   11821:        mov.l           L_SCR3(%a6),%d1
                   11822:        andi.b          &0xc0,%d1               # is precision extended?
                   11823:        bne.b           fmul_unfl_ena_sd        # no, sgl or dbl
                   11824:
                   11825: # if the rnd mode is anything but RZ, then we have to re-do the above
                   11826: # multiplication because we used RZ for all.
                   11827:        fmov.l          L_SCR3(%a6),%fpcr       # set FPCR
                   11828:
                   11829: fmul_unfl_ena_cont:
                   11830:        fmov.l          &0x0,%fpsr              # clear FPSR
                   11831:
                   11832:        fmul.x          FP_SCR0(%a6),%fp1       # execute multiply
                   11833:
                   11834:        fmov.l          &0x0,%fpcr              # clear FPCR
                   11835:
                   11836:        fmovm.x         &0x40,FP_SCR0(%a6)      # save result to stack
                   11837:        mov.l           %d2,-(%sp)              # save d2
                   11838:        mov.w           FP_SCR0_EX(%a6),%d1     # fetch {sgn,exp}
                   11839:        mov.l           %d1,%d2                 # make a copy
                   11840:        andi.l          &0x7fff,%d1             # strip sign
                   11841:        andi.w          &0x8000,%d2             # keep old sign
                   11842:        sub.l           %d0,%d1                 # add scale factor
                   11843:        addi.l          &0x6000,%d1             # add bias
                   11844:        andi.w          &0x7fff,%d1
                   11845:        or.w            %d2,%d1                 # concat old sign,new exp
                   11846:        mov.w           %d1,FP_SCR0_EX(%a6)     # insert new exponent
                   11847:        mov.l           (%sp)+,%d2              # restore d2
                   11848:        fmovm.x         FP_SCR0(%a6),&0x40      # return EXOP in fp1
                   11849:        bra.w           fmul_unfl_dis
                   11850:
                   11851: fmul_unfl_ena_sd:
                   11852:        mov.l           L_SCR3(%a6),%d1
                   11853:        andi.b          &0x30,%d1               # use only rnd mode
                   11854:        fmov.l          %d1,%fpcr               # set FPCR
                   11855:
                   11856:        bra.b           fmul_unfl_ena_cont
                   11857:
                   11858: # MAY UNDERFLOW:
                   11859: # -use the correct rounding mode and precision. this code favors operations
                   11860: # that do not underflow.
                   11861: fmul_may_unfl:
                   11862:        fmovm.x         FP_SCR1(%a6),&0x80      # load dst operand
                   11863:
                   11864:        fmov.l          L_SCR3(%a6),%fpcr       # set FPCR
                   11865:        fmov.l          &0x0,%fpsr              # clear FPSR
                   11866:
                   11867:        fmul.x          FP_SCR0(%a6),%fp0       # execute multiply
                   11868:
                   11869:        fmov.l          %fpsr,%d1               # save status
                   11870:        fmov.l          &0x0,%fpcr              # clear FPCR
                   11871:
                   11872:        or.l            %d1,USER_FPSR(%a6)      # save INEX2,N
                   11873:
                   11874:        fabs.x          %fp0,%fp1               # make a copy of result
                   11875:        fcmp.b          %fp1,&0x2               # is |result| > 2.b?
                   11876:        fbgt.w          fmul_normal_exit        # no; no underflow occurred
                   11877:        fblt.w          fmul_unfl               # yes; underflow occurred
                   11878:
                   11879: #
                   11880: # we still don't know if underflow occurred. result is ~ equal to 2. but,
                   11881: # we don't know if the result was an underflow that rounded up to a 2 or
                   11882: # a normalized number that rounded down to a 2. so, redo the entire operation
                   11883: # using RZ as the rounding mode to see what the pre-rounded result is.
                   11884: # this case should be relatively rare.
                   11885: #
                   11886:        fmovm.x         FP_SCR1(%a6),&0x40      # load dst operand
                   11887:
                   11888:        mov.l           L_SCR3(%a6),%d1
                   11889:        andi.b          &0xc0,%d1               # keep rnd prec
                   11890:        ori.b           &rz_mode*0x10,%d1       # insert RZ
                   11891:
                   11892:        fmov.l          %d1,%fpcr               # set FPCR
                   11893:        fmov.l          &0x0,%fpsr              # clear FPSR
                   11894:
                   11895:        fmul.x          FP_SCR0(%a6),%fp1       # execute multiply
                   11896:
                   11897:        fmov.l          &0x0,%fpcr              # clear FPCR
                   11898:        fabs.x          %fp1                    # make absolute value
                   11899:        fcmp.b          %fp1,&0x2               # is |result| < 2.b?
                   11900:        fbge.w          fmul_normal_exit        # no; no underflow occurred
                   11901:        bra.w           fmul_unfl               # yes, underflow occurred
                   11902:
                   11903: ################################################################################
                   11904:
                   11905: #
                   11906: # Multiply: inputs are not both normalized; what are they?
                   11907: #
                   11908: fmul_not_norm:
                   11909:        mov.w           (tbl_fmul_op.b,%pc,%d1.w*2),%d1
                   11910:        jmp             (tbl_fmul_op.b,%pc,%d1.w)
                   11911:
                   11912:        swbeg           &48
                   11913: tbl_fmul_op:
                   11914:        short           fmul_norm       - tbl_fmul_op # NORM x NORM
                   11915:        short           fmul_zero       - tbl_fmul_op # NORM x ZERO
                   11916:        short           fmul_inf_src    - tbl_fmul_op # NORM x INF
                   11917:        short           fmul_res_qnan   - tbl_fmul_op # NORM x QNAN
                   11918:        short           fmul_norm       - tbl_fmul_op # NORM x DENORM
                   11919:        short           fmul_res_snan   - tbl_fmul_op # NORM x SNAN
                   11920:        short           tbl_fmul_op     - tbl_fmul_op #
                   11921:        short           tbl_fmul_op     - tbl_fmul_op #
                   11922:
                   11923:        short           fmul_zero       - tbl_fmul_op # ZERO x NORM
                   11924:        short           fmul_zero       - tbl_fmul_op # ZERO x ZERO
                   11925:        short           fmul_res_operr  - tbl_fmul_op # ZERO x INF
                   11926:        short           fmul_res_qnan   - tbl_fmul_op # ZERO x QNAN
                   11927:        short           fmul_zero       - tbl_fmul_op # ZERO x DENORM
                   11928:        short           fmul_res_snan   - tbl_fmul_op # ZERO x SNAN
                   11929:        short           tbl_fmul_op     - tbl_fmul_op #
                   11930:        short           tbl_fmul_op     - tbl_fmul_op #
                   11931:
                   11932:        short           fmul_inf_dst    - tbl_fmul_op # INF x NORM
                   11933:        short           fmul_res_operr  - tbl_fmul_op # INF x ZERO
                   11934:        short           fmul_inf_dst    - tbl_fmul_op # INF x INF
                   11935:        short           fmul_res_qnan   - tbl_fmul_op # INF x QNAN
                   11936:        short           fmul_inf_dst    - tbl_fmul_op # INF x DENORM
                   11937:        short           fmul_res_snan   - tbl_fmul_op # INF x SNAN
                   11938:        short           tbl_fmul_op     - tbl_fmul_op #
                   11939:        short           tbl_fmul_op     - tbl_fmul_op #
                   11940:
                   11941:        short           fmul_res_qnan   - tbl_fmul_op # QNAN x NORM
                   11942:        short           fmul_res_qnan   - tbl_fmul_op # QNAN x ZERO
                   11943:        short           fmul_res_qnan   - tbl_fmul_op # QNAN x INF
                   11944:        short           fmul_res_qnan   - tbl_fmul_op # QNAN x QNAN
                   11945:        short           fmul_res_qnan   - tbl_fmul_op # QNAN x DENORM
                   11946:        short           fmul_res_snan   - tbl_fmul_op # QNAN x SNAN
                   11947:        short           tbl_fmul_op     - tbl_fmul_op #
                   11948:        short           tbl_fmul_op     - tbl_fmul_op #
                   11949:
                   11950:        short           fmul_norm       - tbl_fmul_op # NORM x NORM
                   11951:        short           fmul_zero       - tbl_fmul_op # NORM x ZERO
                   11952:        short           fmul_inf_src    - tbl_fmul_op # NORM x INF
                   11953:        short           fmul_res_qnan   - tbl_fmul_op # NORM x QNAN
                   11954:        short           fmul_norm       - tbl_fmul_op # NORM x DENORM
                   11955:        short           fmul_res_snan   - tbl_fmul_op # NORM x SNAN
                   11956:        short           tbl_fmul_op     - tbl_fmul_op #
                   11957:        short           tbl_fmul_op     - tbl_fmul_op #
                   11958:
                   11959:        short           fmul_res_snan   - tbl_fmul_op # SNAN x NORM
                   11960:        short           fmul_res_snan   - tbl_fmul_op # SNAN x ZERO
                   11961:        short           fmul_res_snan   - tbl_fmul_op # SNAN x INF
                   11962:        short           fmul_res_snan   - tbl_fmul_op # SNAN x QNAN
                   11963:        short           fmul_res_snan   - tbl_fmul_op # SNAN x DENORM
                   11964:        short           fmul_res_snan   - tbl_fmul_op # SNAN x SNAN
                   11965:        short           tbl_fmul_op     - tbl_fmul_op #
                   11966:        short           tbl_fmul_op     - tbl_fmul_op #
                   11967:
                   11968: fmul_res_operr:
                   11969:        bra.l           res_operr
                   11970: fmul_res_snan:
                   11971:        bra.l           res_snan
                   11972: fmul_res_qnan:
                   11973:        bra.l           res_qnan
                   11974:
                   11975: #
                   11976: # Multiply: (Zero x Zero) || (Zero x norm) || (Zero x denorm)
                   11977: #
                   11978:        global          fmul_zero               # global for fsglmul
                   11979: fmul_zero:
                   11980:        mov.b           SRC_EX(%a0),%d0         # exclusive or the signs
                   11981:        mov.b           DST_EX(%a1),%d1
                   11982:        eor.b           %d0,%d1
                   11983:        bpl.b           fmul_zero_p             # result ZERO is pos.
                   11984: fmul_zero_n:
                   11985:        fmov.s          &0x80000000,%fp0        # load -ZERO
                   11986:        mov.b           &z_bmask+neg_bmask,FPSR_CC(%a6) # set Z/N
                   11987:        rts
                   11988: fmul_zero_p:
                   11989:        fmov.s          &0x00000000,%fp0        # load +ZERO
                   11990:        mov.b           &z_bmask,FPSR_CC(%a6)   # set Z
                   11991:        rts
                   11992:
                   11993: #
                   11994: # Multiply: (inf x inf) || (inf x norm) || (inf x denorm)
                   11995: #
                   11996: # Note: The j-bit for an infinity is a don't-care. However, to be
                   11997: # strictly compatible w/ the 68881/882, we make sure to return an
                   11998: # INF w/ the j-bit set if the input INF j-bit was set. Destination
                   11999: # INFs take priority.
                   12000: #
                   12001:        global          fmul_inf_dst            # global for fsglmul
                   12002: fmul_inf_dst:
                   12003:        fmovm.x         DST(%a1),&0x80          # return INF result in fp0
                   12004:        mov.b           SRC_EX(%a0),%d0         # exclusive or the signs
                   12005:        mov.b           DST_EX(%a1),%d1
                   12006:        eor.b           %d0,%d1
                   12007:        bpl.b           fmul_inf_dst_p          # result INF is pos.
                   12008: fmul_inf_dst_n:
                   12009:        fabs.x          %fp0                    # clear result sign
                   12010:        fneg.x          %fp0                    # set result sign
                   12011:        mov.b           &inf_bmask+neg_bmask,FPSR_CC(%a6) # set INF/N
                   12012:        rts
                   12013: fmul_inf_dst_p:
                   12014:        fabs.x          %fp0                    # clear result sign
                   12015:        mov.b           &inf_bmask,FPSR_CC(%a6) # set INF
                   12016:        rts
                   12017:
                   12018:        global          fmul_inf_src            # global for fsglmul
                   12019: fmul_inf_src:
                   12020:        fmovm.x         SRC(%a0),&0x80          # return INF result in fp0
                   12021:        mov.b           SRC_EX(%a0),%d0         # exclusive or the signs
                   12022:        mov.b           DST_EX(%a1),%d1
                   12023:        eor.b           %d0,%d1
                   12024:        bpl.b           fmul_inf_dst_p          # result INF is pos.
                   12025:        bra.b           fmul_inf_dst_n
                   12026:
                   12027: #########################################################################
                   12028: # XDEF ****************************************************************        #
                   12029: #      fin(): emulates the fmove instruction                           #
                   12030: #      fsin(): emulates the fsmove instruction                         #
                   12031: #      fdin(): emulates the fdmove instruction                         #
                   12032: #                                                                      #
                   12033: # XREF ****************************************************************        #
                   12034: #      norm() - normalize mantissa for EXOP on denorm                  #
                   12035: #      scale_to_zero_src() - scale src exponent to zero                #
                   12036: #      ovf_res() - return default overflow result                      #
                   12037: #      unf_res() - return default underflow result                     #
                   12038: #      res_qnan_1op() - return QNAN result                             #
                   12039: #      res_snan_1op() - return SNAN result                             #
                   12040: #                                                                      #
                   12041: # INPUT ***************************************************************        #
                   12042: #      a0 = pointer to extended precision source operand               #
                   12043: #      d0 = round prec/mode                                            #
                   12044: #                                                                      #
                   12045: # OUTPUT **************************************************************        #
                   12046: #      fp0 = result                                                    #
                   12047: #      fp1 = EXOP (if exception occurred)                              #
                   12048: #                                                                      #
                   12049: # ALGORITHM ***********************************************************        #
                   12050: #      Handle NANs, infinities, and zeroes as special cases. Divide    #
                   12051: # norms into extended, single, and double precision.                   #
                   12052: #      Norms can be emulated w/ a regular fmove instruction. For       #
                   12053: # sgl/dbl, must scale exponent and perform an "fmove". Check to see    #
                   12054: # if the result would have overflowed/underflowed. If so, use unf_res()        #
                   12055: # or ovf_res() to return the default result. Also return EXOP if       #
                   12056: # exception is enabled. If no exception, return the default result.    #
                   12057: #      Unnorms don't pass through here.                                #
                   12058: #                                                                      #
                   12059: #########################################################################
                   12060:
                   12061:        global          fsin
                   12062: fsin:
                   12063:        andi.b          &0x30,%d0               # clear rnd prec
                   12064:        ori.b           &s_mode*0x10,%d0        # insert sgl precision
                   12065:        bra.b           fin
                   12066:
                   12067:        global          fdin
                   12068: fdin:
                   12069:        andi.b          &0x30,%d0               # clear rnd prec
                   12070:        ori.b           &d_mode*0x10,%d0        # insert dbl precision
                   12071:
                   12072:        global          fin
                   12073: fin:
                   12074:        mov.l           %d0,L_SCR3(%a6)         # store rnd info
                   12075:
                   12076:        mov.b           STAG(%a6),%d1           # fetch src optype tag
                   12077:        bne.w           fin_not_norm            # optimize on non-norm input
                   12078:
                   12079: #
                   12080: # FP MOVE IN: NORMs and DENORMs ONLY!
                   12081: #
                   12082: fin_norm:
                   12083:        andi.b          &0xc0,%d0               # is precision extended?
                   12084:        bne.w           fin_not_ext             # no, so go handle dbl or sgl
                   12085:
                   12086: #
                   12087: # precision selected is extended. so...we cannot get an underflow
                   12088: # or overflow because of rounding to the correct precision. so...
                   12089: # skip the scaling and unscaling...
                   12090: #
                   12091:        tst.b           SRC_EX(%a0)             # is the operand negative?
                   12092:        bpl.b           fin_norm_done           # no
                   12093:        bset            &neg_bit,FPSR_CC(%a6)   # yes, so set 'N' ccode bit
                   12094: fin_norm_done:
                   12095:        fmovm.x         SRC(%a0),&0x80          # return result in fp0
                   12096:        rts
                   12097:
                   12098: #
                   12099: # for an extended precision DENORM, the UNFL exception bit is set
                   12100: # the accrued bit is NOT set in this instance(no inexactness!)
                   12101: #
                   12102: fin_denorm:
                   12103:        andi.b          &0xc0,%d0               # is precision extended?
                   12104:        bne.w           fin_not_ext             # no, so go handle dbl or sgl
                   12105:
                   12106:        bset            &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
                   12107:        tst.b           SRC_EX(%a0)             # is the operand negative?
                   12108:        bpl.b           fin_denorm_done         # no
                   12109:        bset            &neg_bit,FPSR_CC(%a6)   # yes, so set 'N' ccode bit
                   12110: fin_denorm_done:
                   12111:        fmovm.x         SRC(%a0),&0x80          # return result in fp0
                   12112:        btst            &unfl_bit,FPCR_ENABLE(%a6) # is UNFL enabled?
                   12113:        bne.b           fin_denorm_unfl_ena     # yes
                   12114:        rts
                   12115:
                   12116: #
                   12117: # the input is an extended DENORM and underflow is enabled in the FPCR.
                   12118: # normalize the mantissa and add the bias of 0x6000 to the resulting negative
                   12119: # exponent and insert back into the operand.
                   12120: #
                   12121: fin_denorm_unfl_ena:
                   12122:        mov.w           SRC_EX(%a0),FP_SCR0_EX(%a6)
                   12123:        mov.l           SRC_HI(%a0),FP_SCR0_HI(%a6)
                   12124:        mov.l           SRC_LO(%a0),FP_SCR0_LO(%a6)
                   12125:        lea             FP_SCR0(%a6),%a0        # pass: ptr to operand
                   12126:        bsr.l           norm                    # normalize result
                   12127:        neg.w           %d0                     # new exponent = -(shft val)
                   12128:        addi.w          &0x6000,%d0             # add new bias to exponent
                   12129:        mov.w           FP_SCR0_EX(%a6),%d1     # fetch old sign,exp
                   12130:        andi.w          &0x8000,%d1             # keep old sign
                   12131:        andi.w          &0x7fff,%d0             # clear sign position
                   12132:        or.w            %d1,%d0                 # concat new exo,old sign
                   12133:        mov.w           %d0,FP_SCR0_EX(%a6)     # insert new exponent
                   12134:        fmovm.x         FP_SCR0(%a6),&0x40      # return EXOP in fp1
                   12135:        rts
                   12136:
                   12137: #
                   12138: # operand is to be rounded to single or double precision
                   12139: #
                   12140: fin_not_ext:
                   12141:        cmpi.b          %d0,&s_mode*0x10        # separate sgl/dbl prec
                   12142:        bne.b           fin_dbl
                   12143:
                   12144: #
                   12145: # operand is to be rounded to single precision
                   12146: #
                   12147: fin_sgl:
                   12148:        mov.w           SRC_EX(%a0),FP_SCR0_EX(%a6)
                   12149:        mov.l           SRC_HI(%a0),FP_SCR0_HI(%a6)
                   12150:        mov.l           SRC_LO(%a0),FP_SCR0_LO(%a6)
                   12151:        bsr.l           scale_to_zero_src       # calculate scale factor
                   12152:
                   12153:        cmpi.l          %d0,&0x3fff-0x3f80      # will move in underflow?
                   12154:        bge.w           fin_sd_unfl             # yes; go handle underflow
                   12155:        cmpi.l          %d0,&0x3fff-0x407e      # will move in overflow?
                   12156:        beq.w           fin_sd_may_ovfl         # maybe; go check
                   12157:        blt.w           fin_sd_ovfl             # yes; go handle overflow
                   12158:
                   12159: #
                   12160: # operand will NOT overflow or underflow when moved into the fp reg file
                   12161: #
                   12162: fin_sd_normal:
                   12163:        fmov.l          &0x0,%fpsr              # clear FPSR
                   12164:        fmov.l          L_SCR3(%a6),%fpcr       # set FPCR
                   12165:
                   12166:        fmov.x          FP_SCR0(%a6),%fp0       # perform move
                   12167:
                   12168:        fmov.l          %fpsr,%d1               # save FPSR
                   12169:        fmov.l          &0x0,%fpcr              # clear FPCR
                   12170:
                   12171:        or.l            %d1,USER_FPSR(%a6)      # save INEX2,N
                   12172:
                   12173: fin_sd_normal_exit:
                   12174:        mov.l           %d2,-(%sp)              # save d2
                   12175:        fmovm.x         &0x80,FP_SCR0(%a6)      # store out result
                   12176:        mov.w           FP_SCR0_EX(%a6),%d1     # load {sgn,exp}
                   12177:        mov.w           %d1,%d2                 # make a copy
                   12178:        andi.l          &0x7fff,%d1             # strip sign
                   12179:        sub.l           %d0,%d1                 # add scale factor
                   12180:        andi.w          &0x8000,%d2             # keep old sign
                   12181:        or.w            %d1,%d2                 # concat old sign,new exponent
                   12182:        mov.w           %d2,FP_SCR0_EX(%a6)     # insert new exponent
                   12183:        mov.l           (%sp)+,%d2              # restore d2
                   12184:        fmovm.x         FP_SCR0(%a6),&0x80      # return result in fp0
                   12185:        rts
                   12186:
                   12187: #
                   12188: # operand is to be rounded to double precision
                   12189: #
                   12190: fin_dbl:
                   12191:        mov.w           SRC_EX(%a0),FP_SCR0_EX(%a6)
                   12192:        mov.l           SRC_HI(%a0),FP_SCR0_HI(%a6)
                   12193:        mov.l           SRC_LO(%a0),FP_SCR0_LO(%a6)
                   12194:        bsr.l           scale_to_zero_src       # calculate scale factor
                   12195:
                   12196:        cmpi.l          %d0,&0x3fff-0x3c00      # will move in underflow?
                   12197:        bge.w           fin_sd_unfl             # yes; go handle underflow
                   12198:        cmpi.l          %d0,&0x3fff-0x43fe      # will move in overflow?
                   12199:        beq.w           fin_sd_may_ovfl         # maybe; go check
                   12200:        blt.w           fin_sd_ovfl             # yes; go handle overflow
                   12201:        bra.w           fin_sd_normal           # no; ho handle normalized op
                   12202:
                   12203: #
                   12204: # operand WILL underflow when moved in to the fp register file
                   12205: #
                   12206: fin_sd_unfl:
                   12207:        bset            &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
                   12208:
                   12209:        tst.b           FP_SCR0_EX(%a6)         # is operand negative?
                   12210:        bpl.b           fin_sd_unfl_tst
                   12211:        bset            &neg_bit,FPSR_CC(%a6)   # set 'N' ccode bit
                   12212:
                   12213: # if underflow or inexact is enabled, then go calculate the EXOP first.
                   12214: fin_sd_unfl_tst:
                   12215:        mov.b           FPCR_ENABLE(%a6),%d1
                   12216:        andi.b          &0x0b,%d1               # is UNFL or INEX enabled?
                   12217:        bne.b           fin_sd_unfl_ena         # yes
                   12218:
                   12219: fin_sd_unfl_dis:
                   12220:        lea             FP_SCR0(%a6),%a0        # pass: result addr
                   12221:        mov.l           L_SCR3(%a6),%d1         # pass: rnd prec,mode
                   12222:        bsr.l           unf_res                 # calculate default result
                   12223:        or.b            %d0,FPSR_CC(%a6)        # unf_res may have set 'Z'
                   12224:        fmovm.x         FP_SCR0(%a6),&0x80      # return default result in fp0
                   12225:        rts
                   12226:
                   12227: #
                   12228: # operand will underflow AND underflow or inexact is enabled.
                   12229: # therefore, we must return the result rounded to extended precision.
                   12230: #
                   12231: fin_sd_unfl_ena:
                   12232:        mov.l           FP_SCR0_HI(%a6),FP_SCR1_HI(%a6)
                   12233:        mov.l           FP_SCR0_LO(%a6),FP_SCR1_LO(%a6)
                   12234:        mov.w           FP_SCR0_EX(%a6),%d1     # load current exponent
                   12235:
                   12236:        mov.l           %d2,-(%sp)              # save d2
                   12237:        mov.w           %d1,%d2                 # make a copy
                   12238:        andi.l          &0x7fff,%d1             # strip sign
                   12239:        sub.l           %d0,%d1                 # subtract scale factor
                   12240:        andi.w          &0x8000,%d2             # extract old sign
                   12241:        addi.l          &0x6000,%d1             # add new bias
                   12242:        andi.w          &0x7fff,%d1
                   12243:        or.w            %d1,%d2                 # concat old sign,new exp
                   12244:        mov.w           %d2,FP_SCR1_EX(%a6)     # insert new exponent
                   12245:        fmovm.x         FP_SCR1(%a6),&0x40      # return EXOP in fp1
                   12246:        mov.l           (%sp)+,%d2              # restore d2
                   12247:        bra.b           fin_sd_unfl_dis
                   12248:
                   12249: #
                   12250: # operand WILL overflow.
                   12251: #
                   12252: fin_sd_ovfl:
                   12253:        fmov.l          &0x0,%fpsr              # clear FPSR
                   12254:        fmov.l          L_SCR3(%a6),%fpcr       # set FPCR
                   12255:
                   12256:        fmov.x          FP_SCR0(%a6),%fp0       # perform move
                   12257:
                   12258:        fmov.l          &0x0,%fpcr              # clear FPCR
                   12259:        fmov.l          %fpsr,%d1               # save FPSR
                   12260:
                   12261:        or.l            %d1,USER_FPSR(%a6)      # save INEX2,N
                   12262:
                   12263: fin_sd_ovfl_tst:
                   12264:        or.l            &ovfl_inx_mask,USER_FPSR(%a6) # set ovfl/aovfl/ainex
                   12265:
                   12266:        mov.b           FPCR_ENABLE(%a6),%d1
                   12267:        andi.b          &0x13,%d1               # is OVFL or INEX enabled?
                   12268:        bne.b           fin_sd_ovfl_ena         # yes
                   12269:
                   12270: #
                   12271: # OVFL is not enabled; therefore, we must create the default result by
                   12272: # calling ovf_res().
                   12273: #
                   12274: fin_sd_ovfl_dis:
                   12275:        btst            &neg_bit,FPSR_CC(%a6)   # is result negative?
                   12276:        sne             %d1                     # set sign param accordingly
                   12277:        mov.l           L_SCR3(%a6),%d0         # pass: prec,mode
                   12278:        bsr.l           ovf_res                 # calculate default result
                   12279:        or.b            %d0,FPSR_CC(%a6)        # set INF,N if applicable
                   12280:        fmovm.x         (%a0),&0x80             # return default result in fp0
                   12281:        rts
                   12282:
                   12283: #
                   12284: # OVFL is enabled.
                   12285: # the INEX2 bit has already been updated by the round to the correct precision.
                   12286: # now, round to extended(and don't alter the FPSR).
                   12287: #
                   12288: fin_sd_ovfl_ena:
                   12289:        mov.l           %d2,-(%sp)              # save d2
                   12290:        mov.w           FP_SCR0_EX(%a6),%d1     # fetch {sgn,exp}
                   12291:        mov.l           %d1,%d2                 # make a copy
                   12292:        andi.l          &0x7fff,%d1             # strip sign
                   12293:        andi.w          &0x8000,%d2             # keep old sign
                   12294:        sub.l           %d0,%d1                 # add scale factor
                   12295:        sub.l           &0x6000,%d1             # subtract bias
                   12296:        andi.w          &0x7fff,%d1
                   12297:        or.w            %d2,%d1
                   12298:        mov.w           %d1,FP_SCR0_EX(%a6)     # insert new exponent
                   12299:        mov.l           (%sp)+,%d2              # restore d2
                   12300:        fmovm.x         FP_SCR0(%a6),&0x40      # return EXOP in fp1
                   12301:        bra.b           fin_sd_ovfl_dis
                   12302:
                   12303: #
                   12304: # the move in MAY overflow. so...
                   12305: #
                   12306: fin_sd_may_ovfl:
                   12307:        fmov.l          &0x0,%fpsr              # clear FPSR
                   12308:        fmov.l          L_SCR3(%a6),%fpcr       # set FPCR
                   12309:
                   12310:        fmov.x          FP_SCR0(%a6),%fp0       # perform the move
                   12311:
                   12312:        fmov.l          %fpsr,%d1               # save status
                   12313:        fmov.l          &0x0,%fpcr              # clear FPCR
                   12314:
                   12315:        or.l            %d1,USER_FPSR(%a6)      # save INEX2,N
                   12316:
                   12317:        fabs.x          %fp0,%fp1               # make a copy of result
                   12318:        fcmp.b          %fp1,&0x2               # is |result| >= 2.b?
                   12319:        fbge.w          fin_sd_ovfl_tst         # yes; overflow has occurred
                   12320:
                   12321: # no, it didn't overflow; we have correct result
                   12322:        bra.w           fin_sd_normal_exit
                   12323:
                   12324: ##########################################################################
                   12325:
                   12326: #
                   12327: # operand is not a NORM: check its optype and branch accordingly
                   12328: #
                   12329: fin_not_norm:
                   12330:        cmpi.b          %d1,&DENORM             # weed out DENORM
                   12331:        beq.w           fin_denorm
                   12332:        cmpi.b          %d1,&SNAN               # weed out SNANs
                   12333:        beq.l           res_snan_1op
                   12334:        cmpi.b          %d1,&QNAN               # weed out QNANs
                   12335:        beq.l           res_qnan_1op
                   12336:
                   12337: #
                   12338: # do the fmove in; at this point, only possible ops are ZERO and INF.
                   12339: # use fmov to determine ccodes.
                   12340: # prec:mode should be zero at this point but it won't affect answer anyways.
                   12341: #
                   12342:        fmov.x          SRC(%a0),%fp0           # do fmove in
                   12343:        fmov.l          %fpsr,%d0               # no exceptions possible
                   12344:        rol.l           &0x8,%d0                # put ccodes in lo byte
                   12345:        mov.b           %d0,FPSR_CC(%a6)        # insert correct ccodes
                   12346:        rts
                   12347:
                   12348: #########################################################################
                   12349: # XDEF ****************************************************************        #
                   12350: #      fdiv(): emulates the fdiv instruction                           #
                   12351: #      fsdiv(): emulates the fsdiv instruction                         #
                   12352: #      fddiv(): emulates the fddiv instruction                         #
                   12353: #                                                                      #
                   12354: # XREF ****************************************************************        #
                   12355: #      scale_to_zero_src() - scale src exponent to zero                #
                   12356: #      scale_to_zero_dst() - scale dst exponent to zero                #
                   12357: #      unf_res() - return default underflow result                     #
                   12358: #      ovf_res() - return default overflow result                      #
                   12359: #      res_qnan() - return QNAN result                                 #
                   12360: #      res_snan() - return SNAN result                                 #
                   12361: #                                                                      #
                   12362: # INPUT ***************************************************************        #
                   12363: #      a0 = pointer to extended precision source operand               #
                   12364: #      a1 = pointer to extended precision destination operand          #
                   12365: #      d0  rnd prec,mode                                               #
                   12366: #                                                                      #
                   12367: # OUTPUT **************************************************************        #
                   12368: #      fp0 = result                                                    #
                   12369: #      fp1 = EXOP (if exception occurred)                              #
                   12370: #                                                                      #
                   12371: # ALGORITHM ***********************************************************        #
                   12372: #      Handle NANs, infinities, and zeroes as special cases. Divide    #
                   12373: # norms/denorms into ext/sgl/dbl precision.                            #
                   12374: #      For norms/denorms, scale the exponents such that a divide       #
                   12375: # instruction won't cause an exception. Use the regular fdiv to                #
                   12376: # compute a result. Check if the regular operands would have taken     #
                   12377: # an exception. If so, return the default overflow/underflow result    #
                   12378: # and return the EXOP if exceptions are enabled. Else, scale the       #
                   12379: # result operand to the proper exponent.                               #
                   12380: #                                                                      #
                   12381: #########################################################################
                   12382:
                   12383:        align           0x10
                   12384: tbl_fdiv_unfl:
                   12385:        long            0x3fff - 0x0000         # ext_unfl
                   12386:        long            0x3fff - 0x3f81         # sgl_unfl
                   12387:        long            0x3fff - 0x3c01         # dbl_unfl
                   12388:
                   12389: tbl_fdiv_ovfl:
                   12390:        long            0x3fff - 0x7ffe         # ext overflow exponent
                   12391:        long            0x3fff - 0x407e         # sgl overflow exponent
                   12392:        long            0x3fff - 0x43fe         # dbl overflow exponent
                   12393:
                   12394:        global          fsdiv
                   12395: fsdiv:
                   12396:        andi.b          &0x30,%d0               # clear rnd prec
                   12397:        ori.b           &s_mode*0x10,%d0        # insert sgl prec
                   12398:        bra.b           fdiv
                   12399:
                   12400:        global          fddiv
                   12401: fddiv:
                   12402:        andi.b          &0x30,%d0               # clear rnd prec
                   12403:        ori.b           &d_mode*0x10,%d0        # insert dbl prec
                   12404:
                   12405:        global          fdiv
                   12406: fdiv:
                   12407:        mov.l           %d0,L_SCR3(%a6)         # store rnd info
                   12408:
                   12409:        clr.w           %d1
                   12410:        mov.b           DTAG(%a6),%d1
                   12411:        lsl.b           &0x3,%d1
                   12412:        or.b            STAG(%a6),%d1           # combine src tags
                   12413:
                   12414:        bne.w           fdiv_not_norm           # optimize on non-norm input
                   12415:
                   12416: #
                   12417: # DIVIDE: NORMs and DENORMs ONLY!
                   12418: #
                   12419: fdiv_norm:
                   12420:        mov.w           DST_EX(%a1),FP_SCR1_EX(%a6)
                   12421:        mov.l           DST_HI(%a1),FP_SCR1_HI(%a6)
                   12422:        mov.l           DST_LO(%a1),FP_SCR1_LO(%a6)
                   12423:
                   12424:        mov.w           SRC_EX(%a0),FP_SCR0_EX(%a6)
                   12425:        mov.l           SRC_HI(%a0),FP_SCR0_HI(%a6)
                   12426:        mov.l           SRC_LO(%a0),FP_SCR0_LO(%a6)
                   12427:
                   12428:        bsr.l           scale_to_zero_src       # scale src exponent
                   12429:        mov.l           %d0,-(%sp)              # save scale factor 1
                   12430:
                   12431:        bsr.l           scale_to_zero_dst       # scale dst exponent
                   12432:
                   12433:        neg.l           (%sp)                   # SCALE FACTOR = scale1 - scale2
                   12434:        add.l           %d0,(%sp)
                   12435:
                   12436:        mov.w           2+L_SCR3(%a6),%d1       # fetch precision
                   12437:        lsr.b           &0x6,%d1                # shift to lo bits
                   12438:        mov.l           (%sp)+,%d0              # load S.F.
                   12439:        cmp.l           %d0,(tbl_fdiv_ovfl.b,%pc,%d1.w*4) # will result overflow?
                   12440:        ble.w           fdiv_may_ovfl           # result will overflow
                   12441:
                   12442:        cmp.l           %d0,(tbl_fdiv_unfl.w,%pc,%d1.w*4) # will result underflow?
                   12443:        beq.w           fdiv_may_unfl           # maybe
                   12444:        bgt.w           fdiv_unfl               # yes; go handle underflow
                   12445:
                   12446: fdiv_normal:
                   12447:        fmovm.x         FP_SCR1(%a6),&0x80      # load dst op
                   12448:
                   12449:        fmov.l          L_SCR3(%a6),%fpcr       # save FPCR
                   12450:        fmov.l          &0x0,%fpsr              # clear FPSR
                   12451:
                   12452:        fdiv.x          FP_SCR0(%a6),%fp0       # perform divide
                   12453:
                   12454:        fmov.l          %fpsr,%d1               # save FPSR
                   12455:        fmov.l          &0x0,%fpcr              # clear FPCR
                   12456:
                   12457:        or.l            %d1,USER_FPSR(%a6)      # save INEX2,N
                   12458:
                   12459: fdiv_normal_exit:
                   12460:        fmovm.x         &0x80,FP_SCR0(%a6)      # store result on stack
                   12461:        mov.l           %d2,-(%sp)              # store d2
                   12462:        mov.w           FP_SCR0_EX(%a6),%d1     # load {sgn,exp}
                   12463:        mov.l           %d1,%d2                 # make a copy
                   12464:        andi.l          &0x7fff,%d1             # strip sign
                   12465:        andi.w          &0x8000,%d2             # keep old sign
                   12466:        sub.l           %d0,%d1                 # add scale factor
                   12467:        or.w            %d2,%d1                 # concat old sign,new exp
                   12468:        mov.w           %d1,FP_SCR0_EX(%a6)     # insert new exponent
                   12469:        mov.l           (%sp)+,%d2              # restore d2
                   12470:        fmovm.x         FP_SCR0(%a6),&0x80      # return result in fp0
                   12471:        rts
                   12472:
                   12473: tbl_fdiv_ovfl2:
                   12474:        long            0x7fff
                   12475:        long            0x407f
                   12476:        long            0x43ff
                   12477:
                   12478: fdiv_no_ovfl:
                   12479:        mov.l           (%sp)+,%d0              # restore scale factor
                   12480:        bra.b           fdiv_normal_exit
                   12481:
                   12482: fdiv_may_ovfl:
                   12483:        mov.l           %d0,-(%sp)              # save scale factor
                   12484:
                   12485:        fmovm.x         FP_SCR1(%a6),&0x80      # load dst op
                   12486:
                   12487:        fmov.l          L_SCR3(%a6),%fpcr       # set FPCR
                   12488:        fmov.l          &0x0,%fpsr              # set FPSR
                   12489:
                   12490:        fdiv.x          FP_SCR0(%a6),%fp0       # execute divide
                   12491:
                   12492:        fmov.l          %fpsr,%d0
                   12493:        fmov.l          &0x0,%fpcr
                   12494:
                   12495:        or.l            %d0,USER_FPSR(%a6)      # save INEX,N
                   12496:
                   12497:        fmovm.x         &0x01,-(%sp)            # save result to stack
                   12498:        mov.w           (%sp),%d0               # fetch new exponent
                   12499:        add.l           &0xc,%sp                # clear result from stack
                   12500:        andi.l          &0x7fff,%d0             # strip sign
                   12501:        sub.l           (%sp),%d0               # add scale factor
                   12502:        cmp.l           %d0,(tbl_fdiv_ovfl2.b,%pc,%d1.w*4)
                   12503:        blt.b           fdiv_no_ovfl
                   12504:        mov.l           (%sp)+,%d0
                   12505:
                   12506: fdiv_ovfl_tst:
                   12507:        or.l            &ovfl_inx_mask,USER_FPSR(%a6) # set ovfl/aovfl/ainex
                   12508:
                   12509:        mov.b           FPCR_ENABLE(%a6),%d1
                   12510:        andi.b          &0x13,%d1               # is OVFL or INEX enabled?
                   12511:        bne.b           fdiv_ovfl_ena           # yes
                   12512:
                   12513: fdiv_ovfl_dis:
                   12514:        btst            &neg_bit,FPSR_CC(%a6)   # is result negative?
                   12515:        sne             %d1                     # set sign param accordingly
                   12516:        mov.l           L_SCR3(%a6),%d0         # pass prec:rnd
                   12517:        bsr.l           ovf_res                 # calculate default result
                   12518:        or.b            %d0,FPSR_CC(%a6)        # set INF if applicable
                   12519:        fmovm.x         (%a0),&0x80             # return default result in fp0
                   12520:        rts
                   12521:
                   12522: fdiv_ovfl_ena:
                   12523:        mov.l           L_SCR3(%a6),%d1
                   12524:        andi.b          &0xc0,%d1               # is precision extended?
                   12525:        bne.b           fdiv_ovfl_ena_sd        # no, do sgl or dbl
                   12526:
                   12527: fdiv_ovfl_ena_cont:
                   12528:        fmovm.x         &0x80,FP_SCR0(%a6)      # move result to stack
                   12529:
                   12530:        mov.l           %d2,-(%sp)              # save d2
                   12531:        mov.w           FP_SCR0_EX(%a6),%d1     # fetch {sgn,exp}
                   12532:        mov.w           %d1,%d2                 # make a copy
                   12533:        andi.l          &0x7fff,%d1             # strip sign
                   12534:        sub.l           %d0,%d1                 # add scale factor
                   12535:        subi.l          &0x6000,%d1             # subtract bias
                   12536:        andi.w          &0x7fff,%d1             # clear sign bit
                   12537:        andi.w          &0x8000,%d2             # keep old sign
                   12538:        or.w            %d2,%d1                 # concat old sign,new exp
                   12539:        mov.w           %d1,FP_SCR0_EX(%a6)     # insert new exponent
                   12540:        mov.l           (%sp)+,%d2              # restore d2
                   12541:        fmovm.x         FP_SCR0(%a6),&0x40      # return EXOP in fp1
                   12542:        bra.b           fdiv_ovfl_dis
                   12543:
                   12544: fdiv_ovfl_ena_sd:
                   12545:        fmovm.x         FP_SCR1(%a6),&0x80      # load dst operand
                   12546:
                   12547:        mov.l           L_SCR3(%a6),%d1
                   12548:        andi.b          &0x30,%d1               # keep rnd mode
                   12549:        fmov.l          %d1,%fpcr               # set FPCR
                   12550:
                   12551:        fdiv.x          FP_SCR0(%a6),%fp0       # execute divide
                   12552:
                   12553:        fmov.l          &0x0,%fpcr              # clear FPCR
                   12554:        bra.b           fdiv_ovfl_ena_cont
                   12555:
                   12556: fdiv_unfl:
                   12557:        bset            &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
                   12558:
                   12559:        fmovm.x         FP_SCR1(%a6),&0x80      # load dst op
                   12560:
                   12561:        fmov.l          &rz_mode*0x10,%fpcr     # set FPCR
                   12562:        fmov.l          &0x0,%fpsr              # clear FPSR
                   12563:
                   12564:        fdiv.x          FP_SCR0(%a6),%fp0       # execute divide
                   12565:
                   12566:        fmov.l          %fpsr,%d1               # save status
                   12567:        fmov.l          &0x0,%fpcr              # clear FPCR
                   12568:
                   12569:        or.l            %d1,USER_FPSR(%a6)      # save INEX2,N
                   12570:
                   12571:        mov.b           FPCR_ENABLE(%a6),%d1
                   12572:        andi.b          &0x0b,%d1               # is UNFL or INEX enabled?
                   12573:        bne.b           fdiv_unfl_ena           # yes
                   12574:
                   12575: fdiv_unfl_dis:
                   12576:        fmovm.x         &0x80,FP_SCR0(%a6)      # store out result
                   12577:
                   12578:        lea             FP_SCR0(%a6),%a0        # pass: result addr
                   12579:        mov.l           L_SCR3(%a6),%d1         # pass: rnd prec,mode
                   12580:        bsr.l           unf_res                 # calculate default result
                   12581:        or.b            %d0,FPSR_CC(%a6)        # 'Z' may have been set
                   12582:        fmovm.x         FP_SCR0(%a6),&0x80      # return default result in fp0
                   12583:        rts
                   12584:
                   12585: #
                   12586: # UNFL is enabled.
                   12587: #
                   12588: fdiv_unfl_ena:
                   12589:        fmovm.x         FP_SCR1(%a6),&0x40      # load dst op
                   12590:
                   12591:        mov.l           L_SCR3(%a6),%d1
                   12592:        andi.b          &0xc0,%d1               # is precision extended?
                   12593:        bne.b           fdiv_unfl_ena_sd        # no, sgl or dbl
                   12594:
                   12595:        fmov.l          L_SCR3(%a6),%fpcr       # set FPCR
                   12596:
                   12597: fdiv_unfl_ena_cont:
                   12598:        fmov.l          &0x0,%fpsr              # clear FPSR
                   12599:
                   12600:        fdiv.x          FP_SCR0(%a6),%fp1       # execute divide
                   12601:
                   12602:        fmov.l          &0x0,%fpcr              # clear FPCR
                   12603:
                   12604:        fmovm.x         &0x40,FP_SCR0(%a6)      # save result to stack
                   12605:        mov.l           %d2,-(%sp)              # save d2
                   12606:        mov.w           FP_SCR0_EX(%a6),%d1     # fetch {sgn,exp}
                   12607:        mov.l           %d1,%d2                 # make a copy
                   12608:        andi.l          &0x7fff,%d1             # strip sign
                   12609:        andi.w          &0x8000,%d2             # keep old sign
                   12610:        sub.l           %d0,%d1                 # add scale factor
                   12611:        addi.l          &0x6000,%d1             # add bias
                   12612:        andi.w          &0x7fff,%d1
                   12613:        or.w            %d2,%d1                 # concat old sign,new exp
                   12614:        mov.w           %d1,FP_SCR0_EX(%a6)     # insert new exp
                   12615:        mov.l           (%sp)+,%d2              # restore d2
                   12616:        fmovm.x         FP_SCR0(%a6),&0x40      # return EXOP in fp1
                   12617:        bra.w           fdiv_unfl_dis
                   12618:
                   12619: fdiv_unfl_ena_sd:
                   12620:        mov.l           L_SCR3(%a6),%d1
                   12621:        andi.b          &0x30,%d1               # use only rnd mode
                   12622:        fmov.l          %d1,%fpcr               # set FPCR
                   12623:
                   12624:        bra.b           fdiv_unfl_ena_cont
                   12625:
                   12626: #
                   12627: # the divide operation MAY underflow:
                   12628: #
                   12629: fdiv_may_unfl:
                   12630:        fmovm.x         FP_SCR1(%a6),&0x80      # load dst op
                   12631:
                   12632:        fmov.l          L_SCR3(%a6),%fpcr       # set FPCR
                   12633:        fmov.l          &0x0,%fpsr              # clear FPSR
                   12634:
                   12635:        fdiv.x          FP_SCR0(%a6),%fp0       # execute divide
                   12636:
                   12637:        fmov.l          %fpsr,%d1               # save status
                   12638:        fmov.l          &0x0,%fpcr              # clear FPCR
                   12639:
                   12640:        or.l            %d1,USER_FPSR(%a6)      # save INEX2,N
                   12641:
                   12642:        fabs.x          %fp0,%fp1               # make a copy of result
                   12643:        fcmp.b          %fp1,&0x1               # is |result| > 1.b?
                   12644:        fbgt.w          fdiv_normal_exit        # no; no underflow occurred
                   12645:        fblt.w          fdiv_unfl               # yes; underflow occurred
                   12646:
                   12647: #
                   12648: # we still don't know if underflow occurred. result is ~ equal to 1. but,
                   12649: # we don't know if the result was an underflow that rounded up to a 1
                   12650: # or a normalized number that rounded down to a 1. so, redo the entire
                   12651: # operation using RZ as the rounding mode to see what the pre-rounded
                   12652: # result is. this case should be relatively rare.
                   12653: #
                   12654:        fmovm.x         FP_SCR1(%a6),&0x40      # load dst op into fp1
                   12655:
                   12656:        mov.l           L_SCR3(%a6),%d1
                   12657:        andi.b          &0xc0,%d1               # keep rnd prec
                   12658:        ori.b           &rz_mode*0x10,%d1       # insert RZ
                   12659:
                   12660:        fmov.l          %d1,%fpcr               # set FPCR
                   12661:        fmov.l          &0x0,%fpsr              # clear FPSR
                   12662:
                   12663:        fdiv.x          FP_SCR0(%a6),%fp1       # execute divide
                   12664:
                   12665:        fmov.l          &0x0,%fpcr              # clear FPCR
                   12666:        fabs.x          %fp1                    # make absolute value
                   12667:        fcmp.b          %fp1,&0x1               # is |result| < 1.b?
                   12668:        fbge.w          fdiv_normal_exit        # no; no underflow occurred
                   12669:        bra.w           fdiv_unfl               # yes; underflow occurred
                   12670:
                   12671: ############################################################################
                   12672:
                   12673: #
                   12674: # Divide: inputs are not both normalized; what are they?
                   12675: #
                   12676: fdiv_not_norm:
                   12677:        mov.w           (tbl_fdiv_op.b,%pc,%d1.w*2),%d1
                   12678:        jmp             (tbl_fdiv_op.b,%pc,%d1.w*1)
                   12679:
                   12680:        swbeg           &48
                   12681: tbl_fdiv_op:
                   12682:        short           fdiv_norm       - tbl_fdiv_op # NORM / NORM
                   12683:        short           fdiv_inf_load   - tbl_fdiv_op # NORM / ZERO
                   12684:        short           fdiv_zero_load  - tbl_fdiv_op # NORM / INF
                   12685:        short           fdiv_res_qnan   - tbl_fdiv_op # NORM / QNAN
                   12686:        short           fdiv_norm       - tbl_fdiv_op # NORM / DENORM
                   12687:        short           fdiv_res_snan   - tbl_fdiv_op # NORM / SNAN
                   12688:        short           tbl_fdiv_op     - tbl_fdiv_op #
                   12689:        short           tbl_fdiv_op     - tbl_fdiv_op #
                   12690:
                   12691:        short           fdiv_zero_load  - tbl_fdiv_op # ZERO / NORM
                   12692:        short           fdiv_res_operr  - tbl_fdiv_op # ZERO / ZERO
                   12693:        short           fdiv_zero_load  - tbl_fdiv_op # ZERO / INF
                   12694:        short           fdiv_res_qnan   - tbl_fdiv_op # ZERO / QNAN
                   12695:        short           fdiv_zero_load  - tbl_fdiv_op # ZERO / DENORM
                   12696:        short           fdiv_res_snan   - tbl_fdiv_op # ZERO / SNAN
                   12697:        short           tbl_fdiv_op     - tbl_fdiv_op #
                   12698:        short           tbl_fdiv_op     - tbl_fdiv_op #
                   12699:
                   12700:        short           fdiv_inf_dst    - tbl_fdiv_op # INF / NORM
                   12701:        short           fdiv_inf_dst    - tbl_fdiv_op # INF / ZERO
                   12702:        short           fdiv_res_operr  - tbl_fdiv_op # INF / INF
                   12703:        short           fdiv_res_qnan   - tbl_fdiv_op # INF / QNAN
                   12704:        short           fdiv_inf_dst    - tbl_fdiv_op # INF / DENORM
                   12705:        short           fdiv_res_snan   - tbl_fdiv_op # INF / SNAN
                   12706:        short           tbl_fdiv_op     - tbl_fdiv_op #
                   12707:        short           tbl_fdiv_op     - tbl_fdiv_op #
                   12708:
                   12709:        short           fdiv_res_qnan   - tbl_fdiv_op # QNAN / NORM
                   12710:        short           fdiv_res_qnan   - tbl_fdiv_op # QNAN / ZERO
                   12711:        short           fdiv_res_qnan   - tbl_fdiv_op # QNAN / INF
                   12712:        short           fdiv_res_qnan   - tbl_fdiv_op # QNAN / QNAN
                   12713:        short           fdiv_res_qnan   - tbl_fdiv_op # QNAN / DENORM
                   12714:        short           fdiv_res_snan   - tbl_fdiv_op # QNAN / SNAN
                   12715:        short           tbl_fdiv_op     - tbl_fdiv_op #
                   12716:        short           tbl_fdiv_op     - tbl_fdiv_op #
                   12717:
                   12718:        short           fdiv_norm       - tbl_fdiv_op # DENORM / NORM
                   12719:        short           fdiv_inf_load   - tbl_fdiv_op # DENORM / ZERO
                   12720:        short           fdiv_zero_load  - tbl_fdiv_op # DENORM / INF
                   12721:        short           fdiv_res_qnan   - tbl_fdiv_op # DENORM / QNAN
                   12722:        short           fdiv_norm       - tbl_fdiv_op # DENORM / DENORM
                   12723:        short           fdiv_res_snan   - tbl_fdiv_op # DENORM / SNAN
                   12724:        short           tbl_fdiv_op     - tbl_fdiv_op #
                   12725:        short           tbl_fdiv_op     - tbl_fdiv_op #
                   12726:
                   12727:        short           fdiv_res_snan   - tbl_fdiv_op # SNAN / NORM
                   12728:        short           fdiv_res_snan   - tbl_fdiv_op # SNAN / ZERO
                   12729:        short           fdiv_res_snan   - tbl_fdiv_op # SNAN / INF
                   12730:        short           fdiv_res_snan   - tbl_fdiv_op # SNAN / QNAN
                   12731:        short           fdiv_res_snan   - tbl_fdiv_op # SNAN / DENORM
                   12732:        short           fdiv_res_snan   - tbl_fdiv_op # SNAN / SNAN
                   12733:        short           tbl_fdiv_op     - tbl_fdiv_op #
                   12734:        short           tbl_fdiv_op     - tbl_fdiv_op #
                   12735:
                   12736: fdiv_res_qnan:
                   12737:        bra.l           res_qnan
                   12738: fdiv_res_snan:
                   12739:        bra.l           res_snan
                   12740: fdiv_res_operr:
                   12741:        bra.l           res_operr
                   12742:
                   12743:        global          fdiv_zero_load          # global for fsgldiv
                   12744: fdiv_zero_load:
                   12745:        mov.b           SRC_EX(%a0),%d0         # result sign is exclusive
                   12746:        mov.b           DST_EX(%a1),%d1         # or of input signs.
                   12747:        eor.b           %d0,%d1
                   12748:        bpl.b           fdiv_zero_load_p        # result is positive
                   12749:        fmov.s          &0x80000000,%fp0        # load a -ZERO
                   12750:        mov.b           &z_bmask+neg_bmask,FPSR_CC(%a6) # set Z/N
                   12751:        rts
                   12752: fdiv_zero_load_p:
                   12753:        fmov.s          &0x00000000,%fp0        # load a +ZERO
                   12754:        mov.b           &z_bmask,FPSR_CC(%a6)   # set Z
                   12755:        rts
                   12756:
                   12757: #
                   12758: # The destination was In Range and the source was a ZERO. The result,
                   12759: # therefore, is an INF w/ the proper sign.
                   12760: # So, determine the sign and return a new INF (w/ the j-bit cleared).
                   12761: #
                   12762:        global          fdiv_inf_load           # global for fsgldiv
                   12763: fdiv_inf_load:
                   12764:        ori.w           &dz_mask+adz_mask,2+USER_FPSR(%a6) # no; set DZ/ADZ
                   12765:        mov.b           SRC_EX(%a0),%d0         # load both signs
                   12766:        mov.b           DST_EX(%a1),%d1
                   12767:        eor.b           %d0,%d1
                   12768:        bpl.b           fdiv_inf_load_p         # result is positive
                   12769:        fmov.s          &0xff800000,%fp0        # make result -INF
                   12770:        mov.b           &inf_bmask+neg_bmask,FPSR_CC(%a6) # set INF/N
                   12771:        rts
                   12772: fdiv_inf_load_p:
                   12773:        fmov.s          &0x7f800000,%fp0        # make result +INF
                   12774:        mov.b           &inf_bmask,FPSR_CC(%a6) # set INF
                   12775:        rts
                   12776:
                   12777: #
                   12778: # The destination was an INF w/ an In Range or ZERO source, the result is
                   12779: # an INF w/ the proper sign.
                   12780: # The 68881/882 returns the destination INF w/ the new sign(if the j-bit of the
                   12781: # dst INF is set, then then j-bit of the result INF is also set).
                   12782: #
                   12783:        global          fdiv_inf_dst            # global for fsgldiv
                   12784: fdiv_inf_dst:
                   12785:        mov.b           DST_EX(%a1),%d0         # load both signs
                   12786:        mov.b           SRC_EX(%a0),%d1
                   12787:        eor.b           %d0,%d1
                   12788:        bpl.b           fdiv_inf_dst_p          # result is positive
                   12789:
                   12790:        fmovm.x         DST(%a1),&0x80          # return result in fp0
                   12791:        fabs.x          %fp0                    # clear sign bit
                   12792:        fneg.x          %fp0                    # set sign bit
                   12793:        mov.b           &inf_bmask+neg_bmask,FPSR_CC(%a6) # set INF/NEG
                   12794:        rts
                   12795:
                   12796: fdiv_inf_dst_p:
                   12797:        fmovm.x         DST(%a1),&0x80          # return result in fp0
                   12798:        fabs.x          %fp0                    # return positive INF
                   12799:        mov.b           &inf_bmask,FPSR_CC(%a6) # set INF
                   12800:        rts
                   12801:
                   12802: #########################################################################
                   12803: # XDEF ****************************************************************        #
                   12804: #      fneg(): emulates the fneg instruction                           #
                   12805: #      fsneg(): emulates the fsneg instruction                         #
                   12806: #      fdneg(): emulates the fdneg instruction                         #
                   12807: #                                                                      #
                   12808: # XREF ****************************************************************        #
                   12809: #      norm() - normalize a denorm to provide EXOP                     #
                   12810: #      scale_to_zero_src() - scale sgl/dbl source exponent             #
                   12811: #      ovf_res() - return default overflow result                      #
                   12812: #      unf_res() - return default underflow result                     #
                   12813: #      res_qnan_1op() - return QNAN result                             #
                   12814: #      res_snan_1op() - return SNAN result                             #
                   12815: #                                                                      #
                   12816: # INPUT ***************************************************************        #
                   12817: #      a0 = pointer to extended precision source operand               #
                   12818: #      d0 = rnd prec,mode                                              #
                   12819: #                                                                      #
                   12820: # OUTPUT **************************************************************        #
                   12821: #      fp0 = result                                                    #
                   12822: #      fp1 = EXOP (if exception occurred)                              #
                   12823: #                                                                      #
                   12824: # ALGORITHM ***********************************************************        #
                   12825: #      Handle NANs, zeroes, and infinities as special cases. Separate  #
                   12826: # norms/denorms into ext/sgl/dbl precisions. Extended precision can be #
                   12827: # emulated by simply setting sign bit. Sgl/dbl operands must be scaled #
                   12828: # and an actual fneg performed to see if overflow/underflow would have #
                   12829: # occurred. If so, return default underflow/overflow result. Else,     #
                   12830: # scale the result exponent and return result. FPSR gets set based on  #
                   12831: # the result value.                                                    #
                   12832: #                                                                      #
                   12833: #########################################################################
                   12834:
                   12835:        global          fsneg
                   12836: fsneg:
                   12837:        andi.b          &0x30,%d0               # clear rnd prec
                   12838:        ori.b           &s_mode*0x10,%d0        # insert sgl precision
                   12839:        bra.b           fneg
                   12840:
                   12841:        global          fdneg
                   12842: fdneg:
                   12843:        andi.b          &0x30,%d0               # clear rnd prec
                   12844:        ori.b           &d_mode*0x10,%d0        # insert dbl prec
                   12845:
                   12846:        global          fneg
                   12847: fneg:
                   12848:        mov.l           %d0,L_SCR3(%a6)         # store rnd info
                   12849:        mov.b           STAG(%a6),%d1
                   12850:        bne.w           fneg_not_norm           # optimize on non-norm input
                   12851:
                   12852: #
                   12853: # NEGATE SIGN : norms and denorms ONLY!
                   12854: #
                   12855: fneg_norm:
                   12856:        andi.b          &0xc0,%d0               # is precision extended?
                   12857:        bne.w           fneg_not_ext            # no; go handle sgl or dbl
                   12858:
                   12859: #
                   12860: # precision selected is extended. so...we can not get an underflow
                   12861: # or overflow because of rounding to the correct precision. so...
                   12862: # skip the scaling and unscaling...
                   12863: #
                   12864:        mov.l           SRC_HI(%a0),FP_SCR0_HI(%a6)
                   12865:        mov.l           SRC_LO(%a0),FP_SCR0_LO(%a6)
                   12866:        mov.w           SRC_EX(%a0),%d0
                   12867:        eori.w          &0x8000,%d0             # negate sign
                   12868:        bpl.b           fneg_norm_load          # sign is positive
                   12869:        mov.b           &neg_bmask,FPSR_CC(%a6) # set 'N' ccode bit
                   12870: fneg_norm_load:
                   12871:        mov.w           %d0,FP_SCR0_EX(%a6)
                   12872:        fmovm.x         FP_SCR0(%a6),&0x80      # return result in fp0
                   12873:        rts
                   12874:
                   12875: #
                   12876: # for an extended precision DENORM, the UNFL exception bit is set
                   12877: # the accrued bit is NOT set in this instance(no inexactness!)
                   12878: #
                   12879: fneg_denorm:
                   12880:        andi.b          &0xc0,%d0               # is precision extended?
                   12881:        bne.b           fneg_not_ext            # no; go handle sgl or dbl
                   12882:
                   12883:        bset            &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
                   12884:
                   12885:        mov.l           SRC_HI(%a0),FP_SCR0_HI(%a6)
                   12886:        mov.l           SRC_LO(%a0),FP_SCR0_LO(%a6)
                   12887:        mov.w           SRC_EX(%a0),%d0
                   12888:        eori.w          &0x8000,%d0             # negate sign
                   12889:        bpl.b           fneg_denorm_done        # no
                   12890:        mov.b           &neg_bmask,FPSR_CC(%a6) # yes, set 'N' ccode bit
                   12891: fneg_denorm_done:
                   12892:        mov.w           %d0,FP_SCR0_EX(%a6)
                   12893:        fmovm.x         FP_SCR0(%a6),&0x80      # return default result in fp0
                   12894:
                   12895:        btst            &unfl_bit,FPCR_ENABLE(%a6) # is UNFL enabled?
                   12896:        bne.b           fneg_ext_unfl_ena       # yes
                   12897:        rts
                   12898:
                   12899: #
                   12900: # the input is an extended DENORM and underflow is enabled in the FPCR.
                   12901: # normalize the mantissa and add the bias of 0x6000 to the resulting negative
                   12902: # exponent and insert back into the operand.
                   12903: #
                   12904: fneg_ext_unfl_ena:
                   12905:        lea             FP_SCR0(%a6),%a0        # pass: ptr to operand
                   12906:        bsr.l           norm                    # normalize result
                   12907:        neg.w           %d0                     # new exponent = -(shft val)
                   12908:        addi.w          &0x6000,%d0             # add new bias to exponent
                   12909:        mov.w           FP_SCR0_EX(%a6),%d1     # fetch old sign,exp
                   12910:        andi.w          &0x8000,%d1             # keep old sign
                   12911:        andi.w          &0x7fff,%d0             # clear sign position
                   12912:        or.w            %d1,%d0                 # concat old sign, new exponent
                   12913:        mov.w           %d0,FP_SCR0_EX(%a6)     # insert new exponent
                   12914:        fmovm.x         FP_SCR0(%a6),&0x40      # return EXOP in fp1
                   12915:        rts
                   12916:
                   12917: #
                   12918: # operand is either single or double
                   12919: #
                   12920: fneg_not_ext:
                   12921:        cmpi.b          %d0,&s_mode*0x10        # separate sgl/dbl prec
                   12922:        bne.b           fneg_dbl
                   12923:
                   12924: #
                   12925: # operand is to be rounded to single precision
                   12926: #
                   12927: fneg_sgl:
                   12928:        mov.w           SRC_EX(%a0),FP_SCR0_EX(%a6)
                   12929:        mov.l           SRC_HI(%a0),FP_SCR0_HI(%a6)
                   12930:        mov.l           SRC_LO(%a0),FP_SCR0_LO(%a6)
                   12931:        bsr.l           scale_to_zero_src       # calculate scale factor
                   12932:
                   12933:        cmpi.l          %d0,&0x3fff-0x3f80      # will move in underflow?
                   12934:        bge.w           fneg_sd_unfl            # yes; go handle underflow
                   12935:        cmpi.l          %d0,&0x3fff-0x407e      # will move in overflow?
                   12936:        beq.w           fneg_sd_may_ovfl        # maybe; go check
                   12937:        blt.w           fneg_sd_ovfl            # yes; go handle overflow
                   12938:
                   12939: #
                   12940: # operand will NOT overflow or underflow when moved in to the fp reg file
                   12941: #
                   12942: fneg_sd_normal:
                   12943:        fmov.l          &0x0,%fpsr              # clear FPSR
                   12944:        fmov.l          L_SCR3(%a6),%fpcr       # set FPCR
                   12945:
                   12946:        fneg.x          FP_SCR0(%a6),%fp0       # perform negation
                   12947:
                   12948:        fmov.l          %fpsr,%d1               # save FPSR
                   12949:        fmov.l          &0x0,%fpcr              # clear FPCR
                   12950:
                   12951:        or.l            %d1,USER_FPSR(%a6)      # save INEX2,N
                   12952:
                   12953: fneg_sd_normal_exit:
                   12954:        mov.l           %d2,-(%sp)              # save d2
                   12955:        fmovm.x         &0x80,FP_SCR0(%a6)      # store out result
                   12956:        mov.w           FP_SCR0_EX(%a6),%d1     # load sgn,exp
                   12957:        mov.w           %d1,%d2                 # make a copy
                   12958:        andi.l          &0x7fff,%d1             # strip sign
                   12959:        sub.l           %d0,%d1                 # add scale factor
                   12960:        andi.w          &0x8000,%d2             # keep old sign
                   12961:        or.w            %d1,%d2                 # concat old sign,new exp
                   12962:        mov.w           %d2,FP_SCR0_EX(%a6)     # insert new exponent
                   12963:        mov.l           (%sp)+,%d2              # restore d2
                   12964:        fmovm.x         FP_SCR0(%a6),&0x80      # return result in fp0
                   12965:        rts
                   12966:
                   12967: #
                   12968: # operand is to be rounded to double precision
                   12969: #
                   12970: fneg_dbl:
                   12971:        mov.w           SRC_EX(%a0),FP_SCR0_EX(%a6)
                   12972:        mov.l           SRC_HI(%a0),FP_SCR0_HI(%a6)
                   12973:        mov.l           SRC_LO(%a0),FP_SCR0_LO(%a6)
                   12974:        bsr.l           scale_to_zero_src       # calculate scale factor
                   12975:
                   12976:        cmpi.l          %d0,&0x3fff-0x3c00      # will move in underflow?
                   12977:        bge.b           fneg_sd_unfl            # yes; go handle underflow
                   12978:        cmpi.l          %d0,&0x3fff-0x43fe      # will move in overflow?
                   12979:        beq.w           fneg_sd_may_ovfl        # maybe; go check
                   12980:        blt.w           fneg_sd_ovfl            # yes; go handle overflow
                   12981:        bra.w           fneg_sd_normal          # no; ho handle normalized op
                   12982:
                   12983: #
                   12984: # operand WILL underflow when moved in to the fp register file
                   12985: #
                   12986: fneg_sd_unfl:
                   12987:        bset            &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
                   12988:
                   12989:        eori.b          &0x80,FP_SCR0_EX(%a6)   # negate sign
                   12990:        bpl.b           fneg_sd_unfl_tst
                   12991:        bset            &neg_bit,FPSR_CC(%a6)   # set 'N' ccode bit
                   12992:
                   12993: # if underflow or inexact is enabled, go calculate EXOP first.
                   12994: fneg_sd_unfl_tst:
                   12995:        mov.b           FPCR_ENABLE(%a6),%d1
                   12996:        andi.b          &0x0b,%d1               # is UNFL or INEX enabled?
                   12997:        bne.b           fneg_sd_unfl_ena        # yes
                   12998:
                   12999: fneg_sd_unfl_dis:
                   13000:        lea             FP_SCR0(%a6),%a0        # pass: result addr
                   13001:        mov.l           L_SCR3(%a6),%d1         # pass: rnd prec,mode
                   13002:        bsr.l           unf_res                 # calculate default result
                   13003:        or.b            %d0,FPSR_CC(%a6)        # unf_res may have set 'Z'
                   13004:        fmovm.x         FP_SCR0(%a6),&0x80      # return default result in fp0
                   13005:        rts
                   13006:
                   13007: #
                   13008: # operand will underflow AND underflow is enabled.
                   13009: # therefore, we must return the result rounded to extended precision.
                   13010: #
                   13011: fneg_sd_unfl_ena:
                   13012:        mov.l           FP_SCR0_HI(%a6),FP_SCR1_HI(%a6)
                   13013:        mov.l           FP_SCR0_LO(%a6),FP_SCR1_LO(%a6)
                   13014:        mov.w           FP_SCR0_EX(%a6),%d1     # load current exponent
                   13015:
                   13016:        mov.l           %d2,-(%sp)              # save d2
                   13017:        mov.l           %d1,%d2                 # make a copy
                   13018:        andi.l          &0x7fff,%d1             # strip sign
                   13019:        andi.w          &0x8000,%d2             # keep old sign
                   13020:        sub.l           %d0,%d1                 # subtract scale factor
                   13021:        addi.l          &0x6000,%d1             # add new bias
                   13022:        andi.w          &0x7fff,%d1
                   13023:        or.w            %d2,%d1                 # concat new sign,new exp
                   13024:        mov.w           %d1,FP_SCR1_EX(%a6)     # insert new exp
                   13025:        fmovm.x         FP_SCR1(%a6),&0x40      # return EXOP in fp1
                   13026:        mov.l           (%sp)+,%d2              # restore d2
                   13027:        bra.b           fneg_sd_unfl_dis
                   13028:
                   13029: #
                   13030: # operand WILL overflow.
                   13031: #
                   13032: fneg_sd_ovfl:
                   13033:        fmov.l          &0x0,%fpsr              # clear FPSR
                   13034:        fmov.l          L_SCR3(%a6),%fpcr       # set FPCR
                   13035:
                   13036:        fneg.x          FP_SCR0(%a6),%fp0       # perform negation
                   13037:
                   13038:        fmov.l          &0x0,%fpcr              # clear FPCR
                   13039:        fmov.l          %fpsr,%d1               # save FPSR
                   13040:
                   13041:        or.l            %d1,USER_FPSR(%a6)      # save INEX2,N
                   13042:
                   13043: fneg_sd_ovfl_tst:
                   13044:        or.l            &ovfl_inx_mask,USER_FPSR(%a6) # set ovfl/aovfl/ainex
                   13045:
                   13046:        mov.b           FPCR_ENABLE(%a6),%d1
                   13047:        andi.b          &0x13,%d1               # is OVFL or INEX enabled?
                   13048:        bne.b           fneg_sd_ovfl_ena        # yes
                   13049:
                   13050: #
                   13051: # OVFL is not enabled; therefore, we must create the default result by
                   13052: # calling ovf_res().
                   13053: #
                   13054: fneg_sd_ovfl_dis:
                   13055:        btst            &neg_bit,FPSR_CC(%a6)   # is result negative?
                   13056:        sne             %d1                     # set sign param accordingly
                   13057:        mov.l           L_SCR3(%a6),%d0         # pass: prec,mode
                   13058:        bsr.l           ovf_res                 # calculate default result
                   13059:        or.b            %d0,FPSR_CC(%a6)        # set INF,N if applicable
                   13060:        fmovm.x         (%a0),&0x80             # return default result in fp0
                   13061:        rts
                   13062:
                   13063: #
                   13064: # OVFL is enabled.
                   13065: # the INEX2 bit has already been updated by the round to the correct precision.
                   13066: # now, round to extended(and don't alter the FPSR).
                   13067: #
                   13068: fneg_sd_ovfl_ena:
                   13069:        mov.l           %d2,-(%sp)              # save d2
                   13070:        mov.w           FP_SCR0_EX(%a6),%d1     # fetch {sgn,exp}
                   13071:        mov.l           %d1,%d2                 # make a copy
                   13072:        andi.l          &0x7fff,%d1             # strip sign
                   13073:        andi.w          &0x8000,%d2             # keep old sign
                   13074:        sub.l           %d0,%d1                 # add scale factor
                   13075:        subi.l          &0x6000,%d1             # subtract bias
                   13076:        andi.w          &0x7fff,%d1
                   13077:        or.w            %d2,%d1                 # concat sign,exp
                   13078:        mov.w           %d1,FP_SCR0_EX(%a6)     # insert new exponent
                   13079:        fmovm.x         FP_SCR0(%a6),&0x40      # return EXOP in fp1
                   13080:        mov.l           (%sp)+,%d2              # restore d2
                   13081:        bra.b           fneg_sd_ovfl_dis
                   13082:
                   13083: #
                   13084: # the move in MAY underflow. so...
                   13085: #
                   13086: fneg_sd_may_ovfl:
                   13087:        fmov.l          &0x0,%fpsr              # clear FPSR
                   13088:        fmov.l          L_SCR3(%a6),%fpcr       # set FPCR
                   13089:
                   13090:        fneg.x          FP_SCR0(%a6),%fp0       # perform negation
                   13091:
                   13092:        fmov.l          %fpsr,%d1               # save status
                   13093:        fmov.l          &0x0,%fpcr              # clear FPCR
                   13094:
                   13095:        or.l            %d1,USER_FPSR(%a6)      # save INEX2,N
                   13096:
                   13097:        fabs.x          %fp0,%fp1               # make a copy of result
                   13098:        fcmp.b          %fp1,&0x2               # is |result| >= 2.b?
                   13099:        fbge.w          fneg_sd_ovfl_tst        # yes; overflow has occurred
                   13100:
                   13101: # no, it didn't overflow; we have correct result
                   13102:        bra.w           fneg_sd_normal_exit
                   13103:
                   13104: ##########################################################################
                   13105:
                   13106: #
                   13107: # input is not normalized; what is it?
                   13108: #
                   13109: fneg_not_norm:
                   13110:        cmpi.b          %d1,&DENORM             # weed out DENORM
                   13111:        beq.w           fneg_denorm
                   13112:        cmpi.b          %d1,&SNAN               # weed out SNAN
                   13113:        beq.l           res_snan_1op
                   13114:        cmpi.b          %d1,&QNAN               # weed out QNAN
                   13115:        beq.l           res_qnan_1op
                   13116:
                   13117: #
                   13118: # do the fneg; at this point, only possible ops are ZERO and INF.
                   13119: # use fneg to determine ccodes.
                   13120: # prec:mode should be zero at this point but it won't affect answer anyways.
                   13121: #
                   13122:        fneg.x          SRC_EX(%a0),%fp0        # do fneg
                   13123:        fmov.l          %fpsr,%d0
                   13124:        rol.l           &0x8,%d0                # put ccodes in lo byte
                   13125:        mov.b           %d0,FPSR_CC(%a6)        # insert correct ccodes
                   13126:        rts
                   13127:
                   13128: #########################################################################
                   13129: # XDEF ****************************************************************        #
                   13130: #      ftst(): emulates the ftest instruction                          #
                   13131: #                                                                      #
                   13132: # XREF ****************************************************************        #
                   13133: #      res{s,q}nan_1op() - set NAN result for monadic instruction      #
                   13134: #                                                                      #
                   13135: # INPUT ***************************************************************        #
                   13136: #      a0 = pointer to extended precision source operand               #
                   13137: #                                                                      #
                   13138: # OUTPUT **************************************************************        #
                   13139: #      none                                                            #
                   13140: #                                                                      #
                   13141: # ALGORITHM ***********************************************************        #
                   13142: #      Check the source operand tag (STAG) and set the FPCR according  #
                   13143: # to the operand type and sign.                                                #
                   13144: #                                                                      #
                   13145: #########################################################################
                   13146:
                   13147:        global          ftst
                   13148: ftst:
                   13149:        mov.b           STAG(%a6),%d1
                   13150:        bne.b           ftst_not_norm           # optimize on non-norm input
                   13151:
                   13152: #
                   13153: # Norm:
                   13154: #
                   13155: ftst_norm:
                   13156:        tst.b           SRC_EX(%a0)             # is operand negative?
                   13157:        bmi.b           ftst_norm_m             # yes
                   13158:        rts
                   13159: ftst_norm_m:
                   13160:        mov.b           &neg_bmask,FPSR_CC(%a6) # set 'N' ccode bit
                   13161:        rts
                   13162:
                   13163: #
                   13164: # input is not normalized; what is it?
                   13165: #
                   13166: ftst_not_norm:
                   13167:        cmpi.b          %d1,&ZERO               # weed out ZERO
                   13168:        beq.b           ftst_zero
                   13169:        cmpi.b          %d1,&INF                # weed out INF
                   13170:        beq.b           ftst_inf
                   13171:        cmpi.b          %d1,&SNAN               # weed out SNAN
                   13172:        beq.l           res_snan_1op
                   13173:        cmpi.b          %d1,&QNAN               # weed out QNAN
                   13174:        beq.l           res_qnan_1op
                   13175:
                   13176: #
                   13177: # Denorm:
                   13178: #
                   13179: ftst_denorm:
                   13180:        tst.b           SRC_EX(%a0)             # is operand negative?
                   13181:        bmi.b           ftst_denorm_m           # yes
                   13182:        rts
                   13183: ftst_denorm_m:
                   13184:        mov.b           &neg_bmask,FPSR_CC(%a6) # set 'N' ccode bit
                   13185:        rts
                   13186:
                   13187: #
                   13188: # Infinity:
                   13189: #
                   13190: ftst_inf:
                   13191:        tst.b           SRC_EX(%a0)             # is operand negative?
                   13192:        bmi.b           ftst_inf_m              # yes
                   13193: ftst_inf_p:
                   13194:        mov.b           &inf_bmask,FPSR_CC(%a6) # set 'I' ccode bit
                   13195:        rts
                   13196: ftst_inf_m:
                   13197:        mov.b           &inf_bmask+neg_bmask,FPSR_CC(%a6) # set 'I','N' ccode bits
                   13198:        rts
                   13199:
                   13200: #
                   13201: # Zero:
                   13202: #
                   13203: ftst_zero:
                   13204:        tst.b           SRC_EX(%a0)             # is operand negative?
                   13205:        bmi.b           ftst_zero_m             # yes
                   13206: ftst_zero_p:
                   13207:        mov.b           &z_bmask,FPSR_CC(%a6)   # set 'N' ccode bit
                   13208:        rts
                   13209: ftst_zero_m:
                   13210:        mov.b           &z_bmask+neg_bmask,FPSR_CC(%a6) # set 'Z','N' ccode bits
                   13211:        rts
                   13212:
                   13213: #########################################################################
                   13214: # XDEF ****************************************************************        #
                   13215: #      fint(): emulates the fint instruction                           #
                   13216: #                                                                      #
                   13217: # XREF ****************************************************************        #
                   13218: #      res_{s,q}nan_1op() - set NAN result for monadic operation       #
                   13219: #                                                                      #
                   13220: # INPUT ***************************************************************        #
                   13221: #      a0 = pointer to extended precision source operand               #
                   13222: #      d0 = round precision/mode                                       #
                   13223: #                                                                      #
                   13224: # OUTPUT **************************************************************        #
                   13225: #      fp0 = result                                                    #
                   13226: #                                                                      #
                   13227: # ALGORITHM ***********************************************************        #
                   13228: #      Separate according to operand type. Unnorms don't pass through  #
                   13229: # here. For norms, load the rounding mode/prec, execute a "fint", then         #
                   13230: # store the resulting FPSR bits.                                       #
                   13231: #      For denorms, force the j-bit to a one and do the same as for    #
                   13232: # norms. Denorms are so low that the answer will either be a zero or a         #
                   13233: # one.                                                                 #
                   13234: #      For zeroes/infs/NANs, return the same while setting the FPSR    #
                   13235: # as appropriate.                                                      #
                   13236: #                                                                      #
                   13237: #########################################################################
                   13238:
                   13239:        global          fint
                   13240: fint:
                   13241:        mov.b           STAG(%a6),%d1
                   13242:        bne.b           fint_not_norm           # optimize on non-norm input
                   13243:
                   13244: #
                   13245: # Norm:
                   13246: #
                   13247: fint_norm:
                   13248:        andi.b          &0x30,%d0               # set prec = ext
                   13249:
                   13250:        fmov.l          %d0,%fpcr               # set FPCR
                   13251:        fmov.l          &0x0,%fpsr              # clear FPSR
                   13252:
                   13253:        fint.x          SRC(%a0),%fp0           # execute fint
                   13254:
                   13255:        fmov.l          &0x0,%fpcr              # clear FPCR
                   13256:        fmov.l          %fpsr,%d0               # save FPSR
                   13257:        or.l            %d0,USER_FPSR(%a6)      # set exception bits
                   13258:
                   13259:        rts
                   13260:
                   13261: #
                   13262: # input is not normalized; what is it?
                   13263: #
                   13264: fint_not_norm:
                   13265:        cmpi.b          %d1,&ZERO               # weed out ZERO
                   13266:        beq.b           fint_zero
                   13267:        cmpi.b          %d1,&INF                # weed out INF
                   13268:        beq.b           fint_inf
                   13269:        cmpi.b          %d1,&DENORM             # weed out DENORM
                   13270:        beq.b           fint_denorm
                   13271:        cmpi.b          %d1,&SNAN               # weed out SNAN
                   13272:        beq.l           res_snan_1op
                   13273:        bra.l           res_qnan_1op            # weed out QNAN
                   13274:
                   13275: #
                   13276: # Denorm:
                   13277: #
                   13278: # for DENORMs, the result will be either (+/-)ZERO or (+/-)1.
                   13279: # also, the INEX2 and AINEX exception bits will be set.
                   13280: # so, we could either set these manually or force the DENORM
                   13281: # to a very small NORM and ship it to the NORM routine.
                   13282: # I do the latter.
                   13283: #
                   13284: fint_denorm:
                   13285:        mov.w           SRC_EX(%a0),FP_SCR0_EX(%a6) # copy sign, zero exp
                   13286:        mov.b           &0x80,FP_SCR0_HI(%a6)   # force DENORM ==> small NORM
                   13287:        lea             FP_SCR0(%a6),%a0
                   13288:        bra.b           fint_norm
                   13289:
                   13290: #
                   13291: # Zero:
                   13292: #
                   13293: fint_zero:
                   13294:        tst.b           SRC_EX(%a0)             # is ZERO negative?
                   13295:        bmi.b           fint_zero_m             # yes
                   13296: fint_zero_p:
                   13297:        fmov.s          &0x00000000,%fp0        # return +ZERO in fp0
                   13298:        mov.b           &z_bmask,FPSR_CC(%a6)   # set 'Z' ccode bit
                   13299:        rts
                   13300: fint_zero_m:
                   13301:        fmov.s          &0x80000000,%fp0        # return -ZERO in fp0
                   13302:        mov.b           &z_bmask+neg_bmask,FPSR_CC(%a6) # set 'Z','N' ccode bits
                   13303:        rts
                   13304:
                   13305: #
                   13306: # Infinity:
                   13307: #
                   13308: fint_inf:
                   13309:        fmovm.x         SRC(%a0),&0x80          # return result in fp0
                   13310:        tst.b           SRC_EX(%a0)             # is INF negative?
                   13311:        bmi.b           fint_inf_m              # yes
                   13312: fint_inf_p:
                   13313:        mov.b           &inf_bmask,FPSR_CC(%a6) # set 'I' ccode bit
                   13314:        rts
                   13315: fint_inf_m:
                   13316:        mov.b           &inf_bmask+neg_bmask,FPSR_CC(%a6) # set 'N','I' ccode bits
                   13317:        rts
                   13318:
                   13319: #########################################################################
                   13320: # XDEF ****************************************************************        #
                   13321: #      fintrz(): emulates the fintrz instruction                       #
                   13322: #                                                                      #
                   13323: # XREF ****************************************************************        #
                   13324: #      res_{s,q}nan_1op() - set NAN result for monadic operation       #
                   13325: #                                                                      #
                   13326: # INPUT ***************************************************************        #
                   13327: #      a0 = pointer to extended precision source operand               #
                   13328: #      d0 = round precision/mode                                       #
                   13329: #                                                                      #
                   13330: # OUTPUT **************************************************************        #
                   13331: #      fp0 = result                                                    #
                   13332: #                                                                      #
                   13333: # ALGORITHM ***********************************************************        #
                   13334: #      Separate according to operand type. Unnorms don't pass through  #
                   13335: # here. For norms, load the rounding mode/prec, execute a "fintrz",    #
                   13336: # then store the resulting FPSR bits.                                  #
                   13337: #      For denorms, force the j-bit to a one and do the same as for    #
                   13338: # norms. Denorms are so low that the answer will either be a zero or a #
                   13339: # one.                                                                 #
                   13340: #      For zeroes/infs/NANs, return the same while setting the FPSR    #
                   13341: # as appropriate.                                                      #
                   13342: #                                                                      #
                   13343: #########################################################################
                   13344:
                   13345:        global          fintrz
                   13346: fintrz:
                   13347:        mov.b           STAG(%a6),%d1
                   13348:        bne.b           fintrz_not_norm         # optimize on non-norm input
                   13349:
                   13350: #
                   13351: # Norm:
                   13352: #
                   13353: fintrz_norm:
                   13354:        fmov.l          &0x0,%fpsr              # clear FPSR
                   13355:
                   13356:        fintrz.x        SRC(%a0),%fp0           # execute fintrz
                   13357:
                   13358:        fmov.l          %fpsr,%d0               # save FPSR
                   13359:        or.l            %d0,USER_FPSR(%a6)      # set exception bits
                   13360:
                   13361:        rts
                   13362:
                   13363: #
                   13364: # input is not normalized; what is it?
                   13365: #
                   13366: fintrz_not_norm:
                   13367:        cmpi.b          %d1,&ZERO               # weed out ZERO
                   13368:        beq.b           fintrz_zero
                   13369:        cmpi.b          %d1,&INF                # weed out INF
                   13370:        beq.b           fintrz_inf
                   13371:        cmpi.b          %d1,&DENORM             # weed out DENORM
                   13372:        beq.b           fintrz_denorm
                   13373:        cmpi.b          %d1,&SNAN               # weed out SNAN
                   13374:        beq.l           res_snan_1op
                   13375:        bra.l           res_qnan_1op            # weed out QNAN
                   13376:
                   13377: #
                   13378: # Denorm:
                   13379: #
                   13380: # for DENORMs, the result will be (+/-)ZERO.
                   13381: # also, the INEX2 and AINEX exception bits will be set.
                   13382: # so, we could either set these manually or force the DENORM
                   13383: # to a very small NORM and ship it to the NORM routine.
                   13384: # I do the latter.
                   13385: #
                   13386: fintrz_denorm:
                   13387:        mov.w           SRC_EX(%a0),FP_SCR0_EX(%a6) # copy sign, zero exp
                   13388:        mov.b           &0x80,FP_SCR0_HI(%a6)   # force DENORM ==> small NORM
                   13389:        lea             FP_SCR0(%a6),%a0
                   13390:        bra.b           fintrz_norm
                   13391:
                   13392: #
                   13393: # Zero:
                   13394: #
                   13395: fintrz_zero:
                   13396:        tst.b           SRC_EX(%a0)             # is ZERO negative?
                   13397:        bmi.b           fintrz_zero_m           # yes
                   13398: fintrz_zero_p:
                   13399:        fmov.s          &0x00000000,%fp0        # return +ZERO in fp0
                   13400:        mov.b           &z_bmask,FPSR_CC(%a6)   # set 'Z' ccode bit
                   13401:        rts
                   13402: fintrz_zero_m:
                   13403:        fmov.s          &0x80000000,%fp0        # return -ZERO in fp0
                   13404:        mov.b           &z_bmask+neg_bmask,FPSR_CC(%a6) # set 'Z','N' ccode bits
                   13405:        rts
                   13406:
                   13407: #
                   13408: # Infinity:
                   13409: #
                   13410: fintrz_inf:
                   13411:        fmovm.x         SRC(%a0),&0x80          # return result in fp0
                   13412:        tst.b           SRC_EX(%a0)             # is INF negative?
                   13413:        bmi.b           fintrz_inf_m            # yes
                   13414: fintrz_inf_p:
                   13415:        mov.b           &inf_bmask,FPSR_CC(%a6) # set 'I' ccode bit
                   13416:        rts
                   13417: fintrz_inf_m:
                   13418:        mov.b           &inf_bmask+neg_bmask,FPSR_CC(%a6) # set 'N','I' ccode bits
                   13419:        rts
                   13420:
                   13421: #########################################################################
                   13422: # XDEF ****************************************************************        #
                   13423: #      fabs():  emulates the fabs instruction                          #
                   13424: #      fsabs(): emulates the fsabs instruction                         #
                   13425: #      fdabs(): emulates the fdabs instruction                         #
                   13426: #                                                                      #
                   13427: # XREF **************************************************************** #
                   13428: #      norm() - normalize denorm mantissa to provide EXOP              #
                   13429: #      scale_to_zero_src() - make exponent. = 0; get scale factor      #
                   13430: #      unf_res() - calculate underflow result                          #
                   13431: #      ovf_res() - calculate overflow result                           #
                   13432: #      res_{s,q}nan_1op() - set NAN result for monadic operation       #
                   13433: #                                                                      #
                   13434: # INPUT *************************************************************** #
                   13435: #      a0 = pointer to extended precision source operand               #
                   13436: #      d0 = rnd precision/mode                                         #
                   13437: #                                                                      #
                   13438: # OUTPUT ************************************************************** #
                   13439: #      fp0 = result                                                    #
                   13440: #      fp1 = EXOP (if exception occurred)                              #
                   13441: #                                                                      #
                   13442: # ALGORITHM ***********************************************************        #
                   13443: #      Handle NANs, infinities, and zeroes as special cases. Divide    #
                   13444: # norms into extended, single, and double precision.                   #
                   13445: #      Simply clear sign for extended precision norm. Ext prec denorm  #
                   13446: # gets an EXOP created for it since it's an underflow.                 #
                   13447: #      Double and single precision can overflow and underflow. First,  #
                   13448: # scale the operand such that the exponent is zero. Perform an "fabs"  #
                   13449: # using the correct rnd mode/prec. Check to see if the original        #
                   13450: # exponent would take an exception. If so, use unf_res() or ovf_res()  #
                   13451: # to calculate the default result. Also, create the EXOP for the       #
                   13452: # exceptional case. If no exception should occur, insert the correct   #
                   13453: # result exponent and return.                                          #
                   13454: #      Unnorms don't pass through here.                                #
                   13455: #                                                                      #
                   13456: #########################################################################
                   13457:
                   13458:        global          fsabs
                   13459: fsabs:
                   13460:        andi.b          &0x30,%d0               # clear rnd prec
                   13461:        ori.b           &s_mode*0x10,%d0        # insert sgl precision
                   13462:        bra.b           fabs
                   13463:
                   13464:        global          fdabs
                   13465: fdabs:
                   13466:        andi.b          &0x30,%d0               # clear rnd prec
                   13467:        ori.b           &d_mode*0x10,%d0        # insert dbl precision
                   13468:
                   13469:        global          fabs
                   13470: fabs:
                   13471:        mov.l           %d0,L_SCR3(%a6)         # store rnd info
                   13472:        mov.b           STAG(%a6),%d1
                   13473:        bne.w           fabs_not_norm           # optimize on non-norm input
                   13474:
                   13475: #
                   13476: # ABSOLUTE VALUE: norms and denorms ONLY!
                   13477: #
                   13478: fabs_norm:
                   13479:        andi.b          &0xc0,%d0               # is precision extended?
                   13480:        bne.b           fabs_not_ext            # no; go handle sgl or dbl
                   13481:
                   13482: #
                   13483: # precision selected is extended. so...we can not get an underflow
                   13484: # or overflow because of rounding to the correct precision. so...
                   13485: # skip the scaling and unscaling...
                   13486: #
                   13487:        mov.l           SRC_HI(%a0),FP_SCR0_HI(%a6)
                   13488:        mov.l           SRC_LO(%a0),FP_SCR0_LO(%a6)
                   13489:        mov.w           SRC_EX(%a0),%d1
                   13490:        bclr            &15,%d1                 # force absolute value
                   13491:        mov.w           %d1,FP_SCR0_EX(%a6)     # insert exponent
                   13492:        fmovm.x         FP_SCR0(%a6),&0x80      # return result in fp0
                   13493:        rts
                   13494:
                   13495: #
                   13496: # for an extended precision DENORM, the UNFL exception bit is set
                   13497: # the accrued bit is NOT set in this instance(no inexactness!)
                   13498: #
                   13499: fabs_denorm:
                   13500:        andi.b          &0xc0,%d0               # is precision extended?
                   13501:        bne.b           fabs_not_ext            # no
                   13502:
                   13503:        bset            &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
                   13504:
                   13505:        mov.l           SRC_HI(%a0),FP_SCR0_HI(%a6)
                   13506:        mov.l           SRC_LO(%a0),FP_SCR0_LO(%a6)
                   13507:        mov.w           SRC_EX(%a0),%d0
                   13508:        bclr            &15,%d0                 # clear sign
                   13509:        mov.w           %d0,FP_SCR0_EX(%a6)     # insert exponent
                   13510:
                   13511:        fmovm.x         FP_SCR0(%a6),&0x80      # return default result in fp0
                   13512:
                   13513:        btst            &unfl_bit,FPCR_ENABLE(%a6) # is UNFL enabled?
                   13514:        bne.b           fabs_ext_unfl_ena
                   13515:        rts
                   13516:
                   13517: #
                   13518: # the input is an extended DENORM and underflow is enabled in the FPCR.
                   13519: # normalize the mantissa and add the bias of 0x6000 to the resulting negative
                   13520: # exponent and insert back into the operand.
                   13521: #
                   13522: fabs_ext_unfl_ena:
                   13523:        lea             FP_SCR0(%a6),%a0        # pass: ptr to operand
                   13524:        bsr.l           norm                    # normalize result
                   13525:        neg.w           %d0                     # new exponent = -(shft val)
                   13526:        addi.w          &0x6000,%d0             # add new bias to exponent
                   13527:        mov.w           FP_SCR0_EX(%a6),%d1     # fetch old sign,exp
                   13528:        andi.w          &0x8000,%d1             # keep old sign
                   13529:        andi.w          &0x7fff,%d0             # clear sign position
                   13530:        or.w            %d1,%d0                 # concat old sign, new exponent
                   13531:        mov.w           %d0,FP_SCR0_EX(%a6)     # insert new exponent
                   13532:        fmovm.x         FP_SCR0(%a6),&0x40      # return EXOP in fp1
                   13533:        rts
                   13534:
                   13535: #
                   13536: # operand is either single or double
                   13537: #
                   13538: fabs_not_ext:
                   13539:        cmpi.b          %d0,&s_mode*0x10        # separate sgl/dbl prec
                   13540:        bne.b           fabs_dbl
                   13541:
                   13542: #
                   13543: # operand is to be rounded to single precision
                   13544: #
                   13545: fabs_sgl:
                   13546:        mov.w           SRC_EX(%a0),FP_SCR0_EX(%a6)
                   13547:        mov.l           SRC_HI(%a0),FP_SCR0_HI(%a6)
                   13548:        mov.l           SRC_LO(%a0),FP_SCR0_LO(%a6)
                   13549:        bsr.l           scale_to_zero_src       # calculate scale factor
                   13550:
                   13551:        cmpi.l          %d0,&0x3fff-0x3f80      # will move in underflow?
                   13552:        bge.w           fabs_sd_unfl            # yes; go handle underflow
                   13553:        cmpi.l          %d0,&0x3fff-0x407e      # will move in overflow?
                   13554:        beq.w           fabs_sd_may_ovfl        # maybe; go check
                   13555:        blt.w           fabs_sd_ovfl            # yes; go handle overflow
                   13556:
                   13557: #
                   13558: # operand will NOT overflow or underflow when moved in to the fp reg file
                   13559: #
                   13560: fabs_sd_normal:
                   13561:        fmov.l          &0x0,%fpsr              # clear FPSR
                   13562:        fmov.l          L_SCR3(%a6),%fpcr       # set FPCR
                   13563:
                   13564:        fabs.x          FP_SCR0(%a6),%fp0       # perform absolute
                   13565:
                   13566:        fmov.l          %fpsr,%d1               # save FPSR
                   13567:        fmov.l          &0x0,%fpcr              # clear FPCR
                   13568:
                   13569:        or.l            %d1,USER_FPSR(%a6)      # save INEX2,N
                   13570:
                   13571: fabs_sd_normal_exit:
                   13572:        mov.l           %d2,-(%sp)              # save d2
                   13573:        fmovm.x         &0x80,FP_SCR0(%a6)      # store out result
                   13574:        mov.w           FP_SCR0_EX(%a6),%d1     # load sgn,exp
                   13575:        mov.l           %d1,%d2                 # make a copy
                   13576:        andi.l          &0x7fff,%d1             # strip sign
                   13577:        sub.l           %d0,%d1                 # add scale factor
                   13578:        andi.w          &0x8000,%d2             # keep old sign
                   13579:        or.w            %d1,%d2                 # concat old sign,new exp
                   13580:        mov.w           %d2,FP_SCR0_EX(%a6)     # insert new exponent
                   13581:        mov.l           (%sp)+,%d2              # restore d2
                   13582:        fmovm.x         FP_SCR0(%a6),&0x80      # return result in fp0
                   13583:        rts
                   13584:
                   13585: #
                   13586: # operand is to be rounded to double precision
                   13587: #
                   13588: fabs_dbl:
                   13589:        mov.w           SRC_EX(%a0),FP_SCR0_EX(%a6)
                   13590:        mov.l           SRC_HI(%a0),FP_SCR0_HI(%a6)
                   13591:        mov.l           SRC_LO(%a0),FP_SCR0_LO(%a6)
                   13592:        bsr.l           scale_to_zero_src       # calculate scale factor
                   13593:
                   13594:        cmpi.l          %d0,&0x3fff-0x3c00      # will move in underflow?
                   13595:        bge.b           fabs_sd_unfl            # yes; go handle underflow
                   13596:        cmpi.l          %d0,&0x3fff-0x43fe      # will move in overflow?
                   13597:        beq.w           fabs_sd_may_ovfl        # maybe; go check
                   13598:        blt.w           fabs_sd_ovfl            # yes; go handle overflow
                   13599:        bra.w           fabs_sd_normal          # no; ho handle normalized op
                   13600:
                   13601: #
                   13602: # operand WILL underflow when moved in to the fp register file
                   13603: #
                   13604: fabs_sd_unfl:
                   13605:        bset            &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
                   13606:
                   13607:        bclr            &0x7,FP_SCR0_EX(%a6)    # force absolute value
                   13608:
                   13609: # if underflow or inexact is enabled, go calculate EXOP first.
                   13610:        mov.b           FPCR_ENABLE(%a6),%d1
                   13611:        andi.b          &0x0b,%d1               # is UNFL or INEX enabled?
                   13612:        bne.b           fabs_sd_unfl_ena        # yes
                   13613:
                   13614: fabs_sd_unfl_dis:
                   13615:        lea             FP_SCR0(%a6),%a0        # pass: result addr
                   13616:        mov.l           L_SCR3(%a6),%d1         # pass: rnd prec,mode
                   13617:        bsr.l           unf_res                 # calculate default result
                   13618:        or.b            %d0,FPSR_CC(%a6)        # set possible 'Z' ccode
                   13619:        fmovm.x         FP_SCR0(%a6),&0x80      # return default result in fp0
                   13620:        rts
                   13621:
                   13622: #
                   13623: # operand will underflow AND underflow is enabled.
                   13624: # therefore, we must return the result rounded to extended precision.
                   13625: #
                   13626: fabs_sd_unfl_ena:
                   13627:        mov.l           FP_SCR0_HI(%a6),FP_SCR1_HI(%a6)
                   13628:        mov.l           FP_SCR0_LO(%a6),FP_SCR1_LO(%a6)
                   13629:        mov.w           FP_SCR0_EX(%a6),%d1     # load current exponent
                   13630:
                   13631:        mov.l           %d2,-(%sp)              # save d2
                   13632:        mov.l           %d1,%d2                 # make a copy
                   13633:        andi.l          &0x7fff,%d1             # strip sign
                   13634:        andi.w          &0x8000,%d2             # keep old sign
                   13635:        sub.l           %d0,%d1                 # subtract scale factor
                   13636:        addi.l          &0x6000,%d1             # add new bias
                   13637:        andi.w          &0x7fff,%d1
                   13638:        or.w            %d2,%d1                 # concat new sign,new exp
                   13639:        mov.w           %d1,FP_SCR1_EX(%a6)     # insert new exp
                   13640:        fmovm.x         FP_SCR1(%a6),&0x40      # return EXOP in fp1
                   13641:        mov.l           (%sp)+,%d2              # restore d2
                   13642:        bra.b           fabs_sd_unfl_dis
                   13643:
                   13644: #
                   13645: # operand WILL overflow.
                   13646: #
                   13647: fabs_sd_ovfl:
                   13648:        fmov.l          &0x0,%fpsr              # clear FPSR
                   13649:        fmov.l          L_SCR3(%a6),%fpcr       # set FPCR
                   13650:
                   13651:        fabs.x          FP_SCR0(%a6),%fp0       # perform absolute
                   13652:
                   13653:        fmov.l          &0x0,%fpcr              # clear FPCR
                   13654:        fmov.l          %fpsr,%d1               # save FPSR
                   13655:
                   13656:        or.l            %d1,USER_FPSR(%a6)      # save INEX2,N
                   13657:
                   13658: fabs_sd_ovfl_tst:
                   13659:        or.l            &ovfl_inx_mask,USER_FPSR(%a6) # set ovfl/aovfl/ainex
                   13660:
                   13661:        mov.b           FPCR_ENABLE(%a6),%d1
                   13662:        andi.b          &0x13,%d1               # is OVFL or INEX enabled?
                   13663:        bne.b           fabs_sd_ovfl_ena        # yes
                   13664:
                   13665: #
                   13666: # OVFL is not enabled; therefore, we must create the default result by
                   13667: # calling ovf_res().
                   13668: #
                   13669: fabs_sd_ovfl_dis:
                   13670:        btst            &neg_bit,FPSR_CC(%a6)   # is result negative?
                   13671:        sne             %d1                     # set sign param accordingly
                   13672:        mov.l           L_SCR3(%a6),%d0         # pass: prec,mode
                   13673:        bsr.l           ovf_res                 # calculate default result
                   13674:        or.b            %d0,FPSR_CC(%a6)        # set INF,N if applicable
                   13675:        fmovm.x         (%a0),&0x80             # return default result in fp0
                   13676:        rts
                   13677:
                   13678: #
                   13679: # OVFL is enabled.
                   13680: # the INEX2 bit has already been updated by the round to the correct precision.
                   13681: # now, round to extended(and don't alter the FPSR).
                   13682: #
                   13683: fabs_sd_ovfl_ena:
                   13684:        mov.l           %d2,-(%sp)              # save d2
                   13685:        mov.w           FP_SCR0_EX(%a6),%d1     # fetch {sgn,exp}
                   13686:        mov.l           %d1,%d2                 # make a copy
                   13687:        andi.l          &0x7fff,%d1             # strip sign
                   13688:        andi.w          &0x8000,%d2             # keep old sign
                   13689:        sub.l           %d0,%d1                 # add scale factor
                   13690:        subi.l          &0x6000,%d1             # subtract bias
                   13691:        andi.w          &0x7fff,%d1
                   13692:        or.w            %d2,%d1                 # concat sign,exp
                   13693:        mov.w           %d1,FP_SCR0_EX(%a6)     # insert new exponent
                   13694:        fmovm.x         FP_SCR0(%a6),&0x40      # return EXOP in fp1
                   13695:        mov.l           (%sp)+,%d2              # restore d2
                   13696:        bra.b           fabs_sd_ovfl_dis
                   13697:
                   13698: #
                   13699: # the move in MAY underflow. so...
                   13700: #
                   13701: fabs_sd_may_ovfl:
                   13702:        fmov.l          &0x0,%fpsr              # clear FPSR
                   13703:        fmov.l          L_SCR3(%a6),%fpcr       # set FPCR
                   13704:
                   13705:        fabs.x          FP_SCR0(%a6),%fp0       # perform absolute
                   13706:
                   13707:        fmov.l          %fpsr,%d1               # save status
                   13708:        fmov.l          &0x0,%fpcr              # clear FPCR
                   13709:
                   13710:        or.l            %d1,USER_FPSR(%a6)      # save INEX2,N
                   13711:
                   13712:        fabs.x          %fp0,%fp1               # make a copy of result
                   13713:        fcmp.b          %fp1,&0x2               # is |result| >= 2.b?
                   13714:        fbge.w          fabs_sd_ovfl_tst        # yes; overflow has occurred
                   13715:
                   13716: # no, it didn't overflow; we have correct result
                   13717:        bra.w           fabs_sd_normal_exit
                   13718:
                   13719: ##########################################################################
                   13720:
                   13721: #
                   13722: # input is not normalized; what is it?
                   13723: #
                   13724: fabs_not_norm:
                   13725:        cmpi.b          %d1,&DENORM             # weed out DENORM
                   13726:        beq.w           fabs_denorm
                   13727:        cmpi.b          %d1,&SNAN               # weed out SNAN
                   13728:        beq.l           res_snan_1op
                   13729:        cmpi.b          %d1,&QNAN               # weed out QNAN
                   13730:        beq.l           res_qnan_1op
                   13731:
                   13732:        fabs.x          SRC(%a0),%fp0           # force absolute value
                   13733:
                   13734:        cmpi.b          %d1,&INF                # weed out INF
                   13735:        beq.b           fabs_inf
                   13736: fabs_zero:
                   13737:        mov.b           &z_bmask,FPSR_CC(%a6)   # set 'Z' ccode bit
                   13738:        rts
                   13739: fabs_inf:
                   13740:        mov.b           &inf_bmask,FPSR_CC(%a6) # set 'I' ccode bit
                   13741:        rts
                   13742:
                   13743: #########################################################################
                   13744: # XDEF ****************************************************************        #
                   13745: #      fcmp(): fp compare op routine                                   #
                   13746: #                                                                      #
                   13747: # XREF ****************************************************************        #
                   13748: #      res_qnan() - return QNAN result                                 #
                   13749: #      res_snan() - return SNAN result                                 #
                   13750: #                                                                      #
                   13751: # INPUT ***************************************************************        #
                   13752: #      a0 = pointer to extended precision source operand               #
                   13753: #      a1 = pointer to extended precision destination operand          #
                   13754: #      d0 = round prec/mode                                            #
                   13755: #                                                                      #
                   13756: # OUTPUT ************************************************************** #
                   13757: #      None                                                            #
                   13758: #                                                                      #
                   13759: # ALGORITHM ***********************************************************        #
                   13760: #      Handle NANs and denorms as special cases. For everything else,  #
                   13761: # just use the actual fcmp instruction to produce the correct condition        #
                   13762: # codes.                                                               #
                   13763: #                                                                      #
                   13764: #########################################################################
                   13765:
                   13766:        global          fcmp
                   13767: fcmp:
                   13768:        clr.w           %d1
                   13769:        mov.b           DTAG(%a6),%d1
                   13770:        lsl.b           &0x3,%d1
                   13771:        or.b            STAG(%a6),%d1
                   13772:        bne.b           fcmp_not_norm           # optimize on non-norm input
                   13773:
                   13774: #
                   13775: # COMPARE FP OPs : NORMs, ZEROs, INFs, and "corrected" DENORMs
                   13776: #
                   13777: fcmp_norm:
                   13778:        fmovm.x         DST(%a1),&0x80          # load dst op
                   13779:
                   13780:        fcmp.x          %fp0,SRC(%a0)           # do compare
                   13781:
                   13782:        fmov.l          %fpsr,%d0               # save FPSR
                   13783:        rol.l           &0x8,%d0                # extract ccode bits
                   13784:        mov.b           %d0,FPSR_CC(%a6)        # set ccode bits(no exc bits are set)
                   13785:
                   13786:        rts
                   13787:
                   13788: #
                   13789: # fcmp: inputs are not both normalized; what are they?
                   13790: #
                   13791: fcmp_not_norm:
                   13792:        mov.w           (tbl_fcmp_op.b,%pc,%d1.w*2),%d1
                   13793:        jmp             (tbl_fcmp_op.b,%pc,%d1.w*1)
                   13794:
                   13795:        swbeg           &48
                   13796: tbl_fcmp_op:
                   13797:        short           fcmp_norm       - tbl_fcmp_op # NORM - NORM
                   13798:        short           fcmp_norm       - tbl_fcmp_op # NORM - ZERO
                   13799:        short           fcmp_norm       - tbl_fcmp_op # NORM - INF
                   13800:        short           fcmp_res_qnan   - tbl_fcmp_op # NORM - QNAN
                   13801:        short           fcmp_nrm_dnrm   - tbl_fcmp_op # NORM - DENORM
                   13802:        short           fcmp_res_snan   - tbl_fcmp_op # NORM - SNAN
                   13803:        short           tbl_fcmp_op     - tbl_fcmp_op #
                   13804:        short           tbl_fcmp_op     - tbl_fcmp_op #
                   13805:
                   13806:        short           fcmp_norm       - tbl_fcmp_op # ZERO - NORM
                   13807:        short           fcmp_norm       - tbl_fcmp_op # ZERO - ZERO
                   13808:        short           fcmp_norm       - tbl_fcmp_op # ZERO - INF
                   13809:        short           fcmp_res_qnan   - tbl_fcmp_op # ZERO - QNAN
                   13810:        short           fcmp_dnrm_s     - tbl_fcmp_op # ZERO - DENORM
                   13811:        short           fcmp_res_snan   - tbl_fcmp_op # ZERO - SNAN
                   13812:        short           tbl_fcmp_op     - tbl_fcmp_op #
                   13813:        short           tbl_fcmp_op     - tbl_fcmp_op #
                   13814:
                   13815:        short           fcmp_norm       - tbl_fcmp_op # INF - NORM
                   13816:        short           fcmp_norm       - tbl_fcmp_op # INF - ZERO
                   13817:        short           fcmp_norm       - tbl_fcmp_op # INF - INF
                   13818:        short           fcmp_res_qnan   - tbl_fcmp_op # INF - QNAN
                   13819:        short           fcmp_dnrm_s     - tbl_fcmp_op # INF - DENORM
                   13820:        short           fcmp_res_snan   - tbl_fcmp_op # INF - SNAN
                   13821:        short           tbl_fcmp_op     - tbl_fcmp_op #
                   13822:        short           tbl_fcmp_op     - tbl_fcmp_op #
                   13823:
                   13824:        short           fcmp_res_qnan   - tbl_fcmp_op # QNAN - NORM
                   13825:        short           fcmp_res_qnan   - tbl_fcmp_op # QNAN - ZERO
                   13826:        short           fcmp_res_qnan   - tbl_fcmp_op # QNAN - INF
                   13827:        short           fcmp_res_qnan   - tbl_fcmp_op # QNAN - QNAN
                   13828:        short           fcmp_res_qnan   - tbl_fcmp_op # QNAN - DENORM
                   13829:        short           fcmp_res_snan   - tbl_fcmp_op # QNAN - SNAN
                   13830:        short           tbl_fcmp_op     - tbl_fcmp_op #
                   13831:        short           tbl_fcmp_op     - tbl_fcmp_op #
                   13832:
                   13833:        short           fcmp_dnrm_nrm   - tbl_fcmp_op # DENORM - NORM
                   13834:        short           fcmp_dnrm_d     - tbl_fcmp_op # DENORM - ZERO
                   13835:        short           fcmp_dnrm_d     - tbl_fcmp_op # DENORM - INF
                   13836:        short           fcmp_res_qnan   - tbl_fcmp_op # DENORM - QNAN
                   13837:        short           fcmp_dnrm_sd    - tbl_fcmp_op # DENORM - DENORM
                   13838:        short           fcmp_res_snan   - tbl_fcmp_op # DENORM - SNAN
                   13839:        short           tbl_fcmp_op     - tbl_fcmp_op #
                   13840:        short           tbl_fcmp_op     - tbl_fcmp_op #
                   13841:
                   13842:        short           fcmp_res_snan   - tbl_fcmp_op # SNAN - NORM
                   13843:        short           fcmp_res_snan   - tbl_fcmp_op # SNAN - ZERO
                   13844:        short           fcmp_res_snan   - tbl_fcmp_op # SNAN - INF
                   13845:        short           fcmp_res_snan   - tbl_fcmp_op # SNAN - QNAN
                   13846:        short           fcmp_res_snan   - tbl_fcmp_op # SNAN - DENORM
                   13847:        short           fcmp_res_snan   - tbl_fcmp_op # SNAN - SNAN
                   13848:        short           tbl_fcmp_op     - tbl_fcmp_op #
                   13849:        short           tbl_fcmp_op     - tbl_fcmp_op #
                   13850:
                   13851: # unlike all other functions for QNAN and SNAN, fcmp does NOT set the
                   13852: # 'N' bit for a negative QNAN or SNAN input so we must squelch it here.
                   13853: fcmp_res_qnan:
                   13854:        bsr.l           res_qnan
                   13855:        andi.b          &0xf7,FPSR_CC(%a6)
                   13856:        rts
                   13857: fcmp_res_snan:
                   13858:        bsr.l           res_snan
                   13859:        andi.b          &0xf7,FPSR_CC(%a6)
                   13860:        rts
                   13861:
                   13862: #
                   13863: # DENORMs are a little more difficult.
                   13864: # If you have a 2 DENORMs, then you can just force the j-bit to a one
                   13865: # and use the fcmp_norm routine.
                   13866: # If you have a DENORM and an INF or ZERO, just force the DENORM's j-bit to a one
                   13867: # and use the fcmp_norm routine.
                   13868: # If you have a DENORM and a NORM with opposite signs, then use fcmp_norm, also.
                   13869: # But with a DENORM and a NORM of the same sign, the neg bit is set if the
                   13870: # (1) signs are (+) and the DENORM is the dst or
                   13871: # (2) signs are (-) and the DENORM is the src
                   13872: #
                   13873:
                   13874: fcmp_dnrm_s:
                   13875:        mov.w           SRC_EX(%a0),FP_SCR0_EX(%a6)
                   13876:        mov.l           SRC_HI(%a0),%d0
                   13877:        bset            &31,%d0                 # DENORM src; make into small norm
                   13878:        mov.l           %d0,FP_SCR0_HI(%a6)
                   13879:        mov.l           SRC_LO(%a0),FP_SCR0_LO(%a6)
                   13880:        lea             FP_SCR0(%a6),%a0
                   13881:        bra.w           fcmp_norm
                   13882:
                   13883: fcmp_dnrm_d:
                   13884:        mov.l           DST_EX(%a1),FP_SCR0_EX(%a6)
                   13885:        mov.l           DST_HI(%a1),%d0
                   13886:        bset            &31,%d0                 # DENORM src; make into small norm
                   13887:        mov.l           %d0,FP_SCR0_HI(%a6)
                   13888:        mov.l           DST_LO(%a1),FP_SCR0_LO(%a6)
                   13889:        lea             FP_SCR0(%a6),%a1
                   13890:        bra.w           fcmp_norm
                   13891:
                   13892: fcmp_dnrm_sd:
                   13893:        mov.w           DST_EX(%a1),FP_SCR1_EX(%a6)
                   13894:        mov.w           SRC_EX(%a0),FP_SCR0_EX(%a6)
                   13895:        mov.l           DST_HI(%a1),%d0
                   13896:        bset            &31,%d0                 # DENORM dst; make into small norm
                   13897:        mov.l           %d0,FP_SCR1_HI(%a6)
                   13898:        mov.l           SRC_HI(%a0),%d0
                   13899:        bset            &31,%d0                 # DENORM dst; make into small norm
                   13900:        mov.l           %d0,FP_SCR0_HI(%a6)
                   13901:        mov.l           DST_LO(%a1),FP_SCR1_LO(%a6)
                   13902:        mov.l           SRC_LO(%a0),FP_SCR0_LO(%a6)
                   13903:        lea             FP_SCR1(%a6),%a1
                   13904:        lea             FP_SCR0(%a6),%a0
                   13905:        bra.w           fcmp_norm
                   13906:
                   13907: fcmp_nrm_dnrm:
                   13908:        mov.b           SRC_EX(%a0),%d0         # determine if like signs
                   13909:        mov.b           DST_EX(%a1),%d1
                   13910:        eor.b           %d0,%d1
                   13911:        bmi.w           fcmp_dnrm_s
                   13912:
                   13913: # signs are the same, so must determine the answer ourselves.
                   13914:        tst.b           %d0                     # is src op negative?
                   13915:        bmi.b           fcmp_nrm_dnrm_m         # yes
                   13916:        rts
                   13917: fcmp_nrm_dnrm_m:
                   13918:        mov.b           &neg_bmask,FPSR_CC(%a6) # set 'Z' ccode bit
                   13919:        rts
                   13920:
                   13921: fcmp_dnrm_nrm:
                   13922:        mov.b           SRC_EX(%a0),%d0         # determine if like signs
                   13923:        mov.b           DST_EX(%a1),%d1
                   13924:        eor.b           %d0,%d1
                   13925:        bmi.w           fcmp_dnrm_d
                   13926:
                   13927: # signs are the same, so must determine the answer ourselves.
                   13928:        tst.b           %d0                     # is src op negative?
                   13929:        bpl.b           fcmp_dnrm_nrm_m         # no
                   13930:        rts
                   13931: fcmp_dnrm_nrm_m:
                   13932:        mov.b           &neg_bmask,FPSR_CC(%a6) # set 'Z' ccode bit
                   13933:        rts
                   13934:
                   13935: #########################################################################
                   13936: # XDEF ****************************************************************        #
                   13937: #      fsglmul(): emulates the fsglmul instruction                     #
                   13938: #                                                                      #
                   13939: # XREF ****************************************************************        #
                   13940: #      scale_to_zero_src() - scale src exponent to zero                #
                   13941: #      scale_to_zero_dst() - scale dst exponent to zero                #
                   13942: #      unf_res4() - return default underflow result for sglop          #
                   13943: #      ovf_res() - return default overflow result                      #
                   13944: #      res_qnan() - return QNAN result                                 #
                   13945: #      res_snan() - return SNAN result                                 #
                   13946: #                                                                      #
                   13947: # INPUT ***************************************************************        #
                   13948: #      a0 = pointer to extended precision source operand               #
                   13949: #      a1 = pointer to extended precision destination operand          #
                   13950: #      d0  rnd prec,mode                                               #
                   13951: #                                                                      #
                   13952: # OUTPUT **************************************************************        #
                   13953: #      fp0 = result                                                    #
                   13954: #      fp1 = EXOP (if exception occurred)                              #
                   13955: #                                                                      #
                   13956: # ALGORITHM ***********************************************************        #
                   13957: #      Handle NANs, infinities, and zeroes as special cases. Divide    #
                   13958: # norms/denorms into ext/sgl/dbl precision.                            #
                   13959: #      For norms/denorms, scale the exponents such that a multiply     #
                   13960: # instruction won't cause an exception. Use the regular fsglmul to     #
                   13961: # compute a result. Check if the regular operands would have taken     #
                   13962: # an exception. If so, return the default overflow/underflow result    #
                   13963: # and return the EXOP if exceptions are enabled. Else, scale the       #
                   13964: # result operand to the proper exponent.                               #
                   13965: #                                                                      #
                   13966: #########################################################################
                   13967:
                   13968:        global          fsglmul
                   13969: fsglmul:
                   13970:        mov.l           %d0,L_SCR3(%a6)         # store rnd info
                   13971:
                   13972:        clr.w           %d1
                   13973:        mov.b           DTAG(%a6),%d1
                   13974:        lsl.b           &0x3,%d1
                   13975:        or.b            STAG(%a6),%d1
                   13976:
                   13977:        bne.w           fsglmul_not_norm        # optimize on non-norm input
                   13978:
                   13979: fsglmul_norm:
                   13980:        mov.w           DST_EX(%a1),FP_SCR1_EX(%a6)
                   13981:        mov.l           DST_HI(%a1),FP_SCR1_HI(%a6)
                   13982:        mov.l           DST_LO(%a1),FP_SCR1_LO(%a6)
                   13983:
                   13984:        mov.w           SRC_EX(%a0),FP_SCR0_EX(%a6)
                   13985:        mov.l           SRC_HI(%a0),FP_SCR0_HI(%a6)
                   13986:        mov.l           SRC_LO(%a0),FP_SCR0_LO(%a6)
                   13987:
                   13988:        bsr.l           scale_to_zero_src       # scale exponent
                   13989:        mov.l           %d0,-(%sp)              # save scale factor 1
                   13990:
                   13991:        bsr.l           scale_to_zero_dst       # scale dst exponent
                   13992:
                   13993:        add.l           (%sp)+,%d0              # SCALE_FACTOR = scale1 + scale2
                   13994:
                   13995:        cmpi.l          %d0,&0x3fff-0x7ffe      # would result ovfl?
                   13996:        beq.w           fsglmul_may_ovfl        # result may rnd to overflow
                   13997:        blt.w           fsglmul_ovfl            # result will overflow
                   13998:
                   13999:        cmpi.l          %d0,&0x3fff+0x0001      # would result unfl?
                   14000:        beq.w           fsglmul_may_unfl        # result may rnd to no unfl
                   14001:        bgt.w           fsglmul_unfl            # result will underflow
                   14002:
                   14003: fsglmul_normal:
                   14004:        fmovm.x         FP_SCR1(%a6),&0x80      # load dst op
                   14005:
                   14006:        fmov.l          L_SCR3(%a6),%fpcr       # set FPCR
                   14007:        fmov.l          &0x0,%fpsr              # clear FPSR
                   14008:
                   14009:        fsglmul.x       FP_SCR0(%a6),%fp0       # execute sgl multiply
                   14010:
                   14011:        fmov.l          %fpsr,%d1               # save status
                   14012:        fmov.l          &0x0,%fpcr              # clear FPCR
                   14013:
                   14014:        or.l            %d1,USER_FPSR(%a6)      # save INEX2,N
                   14015:
                   14016: fsglmul_normal_exit:
                   14017:        fmovm.x         &0x80,FP_SCR0(%a6)      # store out result
                   14018:        mov.l           %d2,-(%sp)              # save d2
                   14019:        mov.w           FP_SCR0_EX(%a6),%d1     # load {sgn,exp}
                   14020:        mov.l           %d1,%d2                 # make a copy
                   14021:        andi.l          &0x7fff,%d1             # strip sign
                   14022:        andi.w          &0x8000,%d2             # keep old sign
                   14023:        sub.l           %d0,%d1                 # add scale factor
                   14024:        or.w            %d2,%d1                 # concat old sign,new exp
                   14025:        mov.w           %d1,FP_SCR0_EX(%a6)     # insert new exponent
                   14026:        mov.l           (%sp)+,%d2              # restore d2
                   14027:        fmovm.x         FP_SCR0(%a6),&0x80      # return result in fp0
                   14028:        rts
                   14029:
                   14030: fsglmul_ovfl:
                   14031:        fmovm.x         FP_SCR1(%a6),&0x80      # load dst op
                   14032:
                   14033:        fmov.l          L_SCR3(%a6),%fpcr       # set FPCR
                   14034:        fmov.l          &0x0,%fpsr              # clear FPSR
                   14035:
                   14036:        fsglmul.x       FP_SCR0(%a6),%fp0       # execute sgl multiply
                   14037:
                   14038:        fmov.l          %fpsr,%d1               # save status
                   14039:        fmov.l          &0x0,%fpcr              # clear FPCR
                   14040:
                   14041:        or.l            %d1,USER_FPSR(%a6)      # save INEX2,N
                   14042:
                   14043: fsglmul_ovfl_tst:
                   14044:
                   14045: # save setting this until now because this is where fsglmul_may_ovfl may jump in
                   14046:        or.l            &ovfl_inx_mask, USER_FPSR(%a6) # set ovfl/aovfl/ainex
                   14047:
                   14048:        mov.b           FPCR_ENABLE(%a6),%d1
                   14049:        andi.b          &0x13,%d1               # is OVFL or INEX enabled?
                   14050:        bne.b           fsglmul_ovfl_ena        # yes
                   14051:
                   14052: fsglmul_ovfl_dis:
                   14053:        btst            &neg_bit,FPSR_CC(%a6)   # is result negative?
                   14054:        sne             %d1                     # set sign param accordingly
                   14055:        mov.l           L_SCR3(%a6),%d0         # pass prec:rnd
                   14056:        andi.b          &0x30,%d0               # force prec = ext
                   14057:        bsr.l           ovf_res                 # calculate default result
                   14058:        or.b            %d0,FPSR_CC(%a6)        # set INF,N if applicable
                   14059:        fmovm.x         (%a0),&0x80             # return default result in fp0
                   14060:        rts
                   14061:
                   14062: fsglmul_ovfl_ena:
                   14063:        fmovm.x         &0x80,FP_SCR0(%a6)      # move result to stack
                   14064:
                   14065:        mov.l           %d2,-(%sp)              # save d2
                   14066:        mov.w           FP_SCR0_EX(%a6),%d1     # fetch {sgn,exp}
                   14067:        mov.l           %d1,%d2                 # make a copy
                   14068:        andi.l          &0x7fff,%d1             # strip sign
                   14069:        sub.l           %d0,%d1                 # add scale factor
                   14070:        subi.l          &0x6000,%d1             # subtract bias
                   14071:        andi.w          &0x7fff,%d1
                   14072:        andi.w          &0x8000,%d2             # keep old sign
                   14073:        or.w            %d2,%d1                 # concat old sign,new exp
                   14074:        mov.w           %d1,FP_SCR0_EX(%a6)     # insert new exponent
                   14075:        mov.l           (%sp)+,%d2              # restore d2
                   14076:        fmovm.x         FP_SCR0(%a6),&0x40      # return EXOP in fp1
                   14077:        bra.b           fsglmul_ovfl_dis
                   14078:
                   14079: fsglmul_may_ovfl:
                   14080:        fmovm.x         FP_SCR1(%a6),&0x80      # load dst op
                   14081:
                   14082:        fmov.l          L_SCR3(%a6),%fpcr       # set FPCR
                   14083:        fmov.l          &0x0,%fpsr              # clear FPSR
                   14084:
                   14085:        fsglmul.x       FP_SCR0(%a6),%fp0       # execute sgl multiply
                   14086:
                   14087:        fmov.l          %fpsr,%d1               # save status
                   14088:        fmov.l          &0x0,%fpcr              # clear FPCR
                   14089:
                   14090:        or.l            %d1,USER_FPSR(%a6)      # save INEX2,N
                   14091:
                   14092:        fabs.x          %fp0,%fp1               # make a copy of result
                   14093:        fcmp.b          %fp1,&0x2               # is |result| >= 2.b?
                   14094:        fbge.w          fsglmul_ovfl_tst        # yes; overflow has occurred
                   14095:
                   14096: # no, it didn't overflow; we have correct result
                   14097:        bra.w           fsglmul_normal_exit
                   14098:
                   14099: fsglmul_unfl:
                   14100:        bset            &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
                   14101:
                   14102:        fmovm.x         FP_SCR1(%a6),&0x80      # load dst op
                   14103:
                   14104:        fmov.l          &rz_mode*0x10,%fpcr     # set FPCR
                   14105:        fmov.l          &0x0,%fpsr              # clear FPSR
                   14106:
                   14107:        fsglmul.x       FP_SCR0(%a6),%fp0       # execute sgl multiply
                   14108:
                   14109:        fmov.l          %fpsr,%d1               # save status
                   14110:        fmov.l          &0x0,%fpcr              # clear FPCR
                   14111:
                   14112:        or.l            %d1,USER_FPSR(%a6)      # save INEX2,N
                   14113:
                   14114:        mov.b           FPCR_ENABLE(%a6),%d1
                   14115:        andi.b          &0x0b,%d1               # is UNFL or INEX enabled?
                   14116:        bne.b           fsglmul_unfl_ena        # yes
                   14117:
                   14118: fsglmul_unfl_dis:
                   14119:        fmovm.x         &0x80,FP_SCR0(%a6)      # store out result
                   14120:
                   14121:        lea             FP_SCR0(%a6),%a0        # pass: result addr
                   14122:        mov.l           L_SCR3(%a6),%d1         # pass: rnd prec,mode
                   14123:        bsr.l           unf_res4                # calculate default result
                   14124:        or.b            %d0,FPSR_CC(%a6)        # 'Z' bit may have been set
                   14125:        fmovm.x         FP_SCR0(%a6),&0x80      # return default result in fp0
                   14126:        rts
                   14127:
                   14128: #
                   14129: # UNFL is enabled.
                   14130: #
                   14131: fsglmul_unfl_ena:
                   14132:        fmovm.x         FP_SCR1(%a6),&0x40      # load dst op
                   14133:
                   14134:        fmov.l          L_SCR3(%a6),%fpcr       # set FPCR
                   14135:        fmov.l          &0x0,%fpsr              # clear FPSR
                   14136:
                   14137:        fsglmul.x       FP_SCR0(%a6),%fp1       # execute sgl multiply
                   14138:
                   14139:        fmov.l          &0x0,%fpcr              # clear FPCR
                   14140:
                   14141:        fmovm.x         &0x40,FP_SCR0(%a6)      # save result to stack
                   14142:        mov.l           %d2,-(%sp)              # save d2
                   14143:        mov.w           FP_SCR0_EX(%a6),%d1     # fetch {sgn,exp}
                   14144:        mov.l           %d1,%d2                 # make a copy
                   14145:        andi.l          &0x7fff,%d1             # strip sign
                   14146:        andi.w          &0x8000,%d2             # keep old sign
                   14147:        sub.l           %d0,%d1                 # add scale factor
                   14148:        addi.l          &0x6000,%d1             # add bias
                   14149:        andi.w          &0x7fff,%d1
                   14150:        or.w            %d2,%d1                 # concat old sign,new exp
                   14151:        mov.w           %d1,FP_SCR0_EX(%a6)     # insert new exponent
                   14152:        mov.l           (%sp)+,%d2              # restore d2
                   14153:        fmovm.x         FP_SCR0(%a6),&0x40      # return EXOP in fp1
                   14154:        bra.w           fsglmul_unfl_dis
                   14155:
                   14156: fsglmul_may_unfl:
                   14157:        fmovm.x         FP_SCR1(%a6),&0x80      # load dst op
                   14158:
                   14159:        fmov.l          L_SCR3(%a6),%fpcr       # set FPCR
                   14160:        fmov.l          &0x0,%fpsr              # clear FPSR
                   14161:
                   14162:        fsglmul.x       FP_SCR0(%a6),%fp0       # execute sgl multiply
                   14163:
                   14164:        fmov.l          %fpsr,%d1               # save status
                   14165:        fmov.l          &0x0,%fpcr              # clear FPCR
                   14166:
                   14167:        or.l            %d1,USER_FPSR(%a6)      # save INEX2,N
                   14168:
                   14169:        fabs.x          %fp0,%fp1               # make a copy of result
                   14170:        fcmp.b          %fp1,&0x2               # is |result| > 2.b?
                   14171:        fbgt.w          fsglmul_normal_exit     # no; no underflow occurred
                   14172:        fblt.w          fsglmul_unfl            # yes; underflow occurred
                   14173:
                   14174: #
                   14175: # we still don't know if underflow occurred. result is ~ equal to 2. but,
                   14176: # we don't know if the result was an underflow that rounded up to a 2 or
                   14177: # a normalized number that rounded down to a 2. so, redo the entire operation
                   14178: # using RZ as the rounding mode to see what the pre-rounded result is.
                   14179: # this case should be relatively rare.
                   14180: #
                   14181:        fmovm.x         FP_SCR1(%a6),&0x40      # load dst op into fp1
                   14182:
                   14183:        mov.l           L_SCR3(%a6),%d1
                   14184:        andi.b          &0xc0,%d1               # keep rnd prec
                   14185:        ori.b           &rz_mode*0x10,%d1       # insert RZ
                   14186:
                   14187:        fmov.l          %d1,%fpcr               # set FPCR
                   14188:        fmov.l          &0x0,%fpsr              # clear FPSR
                   14189:
                   14190:        fsglmul.x       FP_SCR0(%a6),%fp1       # execute sgl multiply
                   14191:
                   14192:        fmov.l          &0x0,%fpcr              # clear FPCR
                   14193:        fabs.x          %fp1                    # make absolute value
                   14194:        fcmp.b          %fp1,&0x2               # is |result| < 2.b?
                   14195:        fbge.w          fsglmul_normal_exit     # no; no underflow occurred
                   14196:        bra.w           fsglmul_unfl            # yes, underflow occurred
                   14197:
                   14198: ##############################################################################
                   14199:
                   14200: #
                   14201: # Single Precision Multiply: inputs are not both normalized; what are they?
                   14202: #
                   14203: fsglmul_not_norm:
                   14204:        mov.w           (tbl_fsglmul_op.b,%pc,%d1.w*2),%d1
                   14205:        jmp             (tbl_fsglmul_op.b,%pc,%d1.w*1)
                   14206:
                   14207:        swbeg           &48
                   14208: tbl_fsglmul_op:
                   14209:        short           fsglmul_norm            - tbl_fsglmul_op # NORM x NORM
                   14210:        short           fsglmul_zero            - tbl_fsglmul_op # NORM x ZERO
                   14211:        short           fsglmul_inf_src         - tbl_fsglmul_op # NORM x INF
                   14212:        short           fsglmul_res_qnan        - tbl_fsglmul_op # NORM x QNAN
                   14213:        short           fsglmul_norm            - tbl_fsglmul_op # NORM x DENORM
                   14214:        short           fsglmul_res_snan        - tbl_fsglmul_op # NORM x SNAN
                   14215:        short           tbl_fsglmul_op          - tbl_fsglmul_op #
                   14216:        short           tbl_fsglmul_op          - tbl_fsglmul_op #
                   14217:
                   14218:        short           fsglmul_zero            - tbl_fsglmul_op # ZERO x NORM
                   14219:        short           fsglmul_zero            - tbl_fsglmul_op # ZERO x ZERO
                   14220:        short           fsglmul_res_operr       - tbl_fsglmul_op # ZERO x INF
                   14221:        short           fsglmul_res_qnan        - tbl_fsglmul_op # ZERO x QNAN
                   14222:        short           fsglmul_zero            - tbl_fsglmul_op # ZERO x DENORM
                   14223:        short           fsglmul_res_snan        - tbl_fsglmul_op # ZERO x SNAN
                   14224:        short           tbl_fsglmul_op          - tbl_fsglmul_op #
                   14225:        short           tbl_fsglmul_op          - tbl_fsglmul_op #
                   14226:
                   14227:        short           fsglmul_inf_dst         - tbl_fsglmul_op # INF x NORM
                   14228:        short           fsglmul_res_operr       - tbl_fsglmul_op # INF x ZERO
                   14229:        short           fsglmul_inf_dst         - tbl_fsglmul_op # INF x INF
                   14230:        short           fsglmul_res_qnan        - tbl_fsglmul_op # INF x QNAN
                   14231:        short           fsglmul_inf_dst         - tbl_fsglmul_op # INF x DENORM
                   14232:        short           fsglmul_res_snan        - tbl_fsglmul_op # INF x SNAN
                   14233:        short           tbl_fsglmul_op          - tbl_fsglmul_op #
                   14234:        short           tbl_fsglmul_op          - tbl_fsglmul_op #
                   14235:
                   14236:        short           fsglmul_res_qnan        - tbl_fsglmul_op # QNAN x NORM
                   14237:        short           fsglmul_res_qnan        - tbl_fsglmul_op # QNAN x ZERO
                   14238:        short           fsglmul_res_qnan        - tbl_fsglmul_op # QNAN x INF
                   14239:        short           fsglmul_res_qnan        - tbl_fsglmul_op # QNAN x QNAN
                   14240:        short           fsglmul_res_qnan        - tbl_fsglmul_op # QNAN x DENORM
                   14241:        short           fsglmul_res_snan        - tbl_fsglmul_op # QNAN x SNAN
                   14242:        short           tbl_fsglmul_op          - tbl_fsglmul_op #
                   14243:        short           tbl_fsglmul_op          - tbl_fsglmul_op #
                   14244:
                   14245:        short           fsglmul_norm            - tbl_fsglmul_op # NORM x NORM
                   14246:        short           fsglmul_zero            - tbl_fsglmul_op # NORM x ZERO
                   14247:        short           fsglmul_inf_src         - tbl_fsglmul_op # NORM x INF
                   14248:        short           fsglmul_res_qnan        - tbl_fsglmul_op # NORM x QNAN
                   14249:        short           fsglmul_norm            - tbl_fsglmul_op # NORM x DENORM
                   14250:        short           fsglmul_res_snan        - tbl_fsglmul_op # NORM x SNAN
                   14251:        short           tbl_fsglmul_op          - tbl_fsglmul_op #
                   14252:        short           tbl_fsglmul_op          - tbl_fsglmul_op #
                   14253:
                   14254:        short           fsglmul_res_snan        - tbl_fsglmul_op # SNAN x NORM
                   14255:        short           fsglmul_res_snan        - tbl_fsglmul_op # SNAN x ZERO
                   14256:        short           fsglmul_res_snan        - tbl_fsglmul_op # SNAN x INF
                   14257:        short           fsglmul_res_snan        - tbl_fsglmul_op # SNAN x QNAN
                   14258:        short           fsglmul_res_snan        - tbl_fsglmul_op # SNAN x DENORM
                   14259:        short           fsglmul_res_snan        - tbl_fsglmul_op # SNAN x SNAN
                   14260:        short           tbl_fsglmul_op          - tbl_fsglmul_op #
                   14261:        short           tbl_fsglmul_op          - tbl_fsglmul_op #
                   14262:
                   14263: fsglmul_res_operr:
                   14264:        bra.l           res_operr
                   14265: fsglmul_res_snan:
                   14266:        bra.l           res_snan
                   14267: fsglmul_res_qnan:
                   14268:        bra.l           res_qnan
                   14269: fsglmul_zero:
                   14270:        bra.l           fmul_zero
                   14271: fsglmul_inf_src:
                   14272:        bra.l           fmul_inf_src
                   14273: fsglmul_inf_dst:
                   14274:        bra.l           fmul_inf_dst
                   14275:
                   14276: #########################################################################
                   14277: # XDEF ****************************************************************        #
                   14278: #      fsgldiv(): emulates the fsgldiv instruction                     #
                   14279: #                                                                      #
                   14280: # XREF ****************************************************************        #
                   14281: #      scale_to_zero_src() - scale src exponent to zero                #
                   14282: #      scale_to_zero_dst() - scale dst exponent to zero                #
                   14283: #      unf_res4() - return default underflow result for sglop          #
                   14284: #      ovf_res() - return default overflow result                      #
                   14285: #      res_qnan() - return QNAN result                                 #
                   14286: #      res_snan() - return SNAN result                                 #
                   14287: #                                                                      #
                   14288: # INPUT ***************************************************************        #
                   14289: #      a0 = pointer to extended precision source operand               #
                   14290: #      a1 = pointer to extended precision destination operand          #
                   14291: #      d0  rnd prec,mode                                               #
                   14292: #                                                                      #
                   14293: # OUTPUT **************************************************************        #
                   14294: #      fp0 = result                                                    #
                   14295: #      fp1 = EXOP (if exception occurred)                              #
                   14296: #                                                                      #
                   14297: # ALGORITHM ***********************************************************        #
                   14298: #      Handle NANs, infinities, and zeroes as special cases. Divide    #
                   14299: # norms/denorms into ext/sgl/dbl precision.                            #
                   14300: #      For norms/denorms, scale the exponents such that a divide       #
                   14301: # instruction won't cause an exception. Use the regular fsgldiv to     #
                   14302: # compute a result. Check if the regular operands would have taken     #
                   14303: # an exception. If so, return the default overflow/underflow result    #
                   14304: # and return the EXOP if exceptions are enabled. Else, scale the       #
                   14305: # result operand to the proper exponent.                               #
                   14306: #                                                                      #
                   14307: #########################################################################
                   14308:
                   14309:        global          fsgldiv
                   14310: fsgldiv:
                   14311:        mov.l           %d0,L_SCR3(%a6)         # store rnd info
                   14312:
                   14313:        clr.w           %d1
                   14314:        mov.b           DTAG(%a6),%d1
                   14315:        lsl.b           &0x3,%d1
                   14316:        or.b            STAG(%a6),%d1           # combine src tags
                   14317:
                   14318:        bne.w           fsgldiv_not_norm        # optimize on non-norm input
                   14319:
                   14320: #
                   14321: # DIVIDE: NORMs and DENORMs ONLY!
                   14322: #
                   14323: fsgldiv_norm:
                   14324:        mov.w           DST_EX(%a1),FP_SCR1_EX(%a6)
                   14325:        mov.l           DST_HI(%a1),FP_SCR1_HI(%a6)
                   14326:        mov.l           DST_LO(%a1),FP_SCR1_LO(%a6)
                   14327:
                   14328:        mov.w           SRC_EX(%a0),FP_SCR0_EX(%a6)
                   14329:        mov.l           SRC_HI(%a0),FP_SCR0_HI(%a6)
                   14330:        mov.l           SRC_LO(%a0),FP_SCR0_LO(%a6)
                   14331:
                   14332:        bsr.l           scale_to_zero_src       # calculate scale factor 1
                   14333:        mov.l           %d0,-(%sp)              # save scale factor 1
                   14334:
                   14335:        bsr.l           scale_to_zero_dst       # calculate scale factor 2
                   14336:
                   14337:        neg.l           (%sp)                   # S.F. = scale1 - scale2
                   14338:        add.l           %d0,(%sp)
                   14339:
                   14340:        mov.w           2+L_SCR3(%a6),%d1       # fetch precision,mode
                   14341:        lsr.b           &0x6,%d1
                   14342:        mov.l           (%sp)+,%d0
                   14343:        cmpi.l          %d0,&0x3fff-0x7ffe
                   14344:        ble.w           fsgldiv_may_ovfl
                   14345:
                   14346:        cmpi.l          %d0,&0x3fff-0x0000      # will result underflow?
                   14347:        beq.w           fsgldiv_may_unfl        # maybe
                   14348:        bgt.w           fsgldiv_unfl            # yes; go handle underflow
                   14349:
                   14350: fsgldiv_normal:
                   14351:        fmovm.x         FP_SCR1(%a6),&0x80      # load dst op
                   14352:
                   14353:        fmov.l          L_SCR3(%a6),%fpcr       # save FPCR
                   14354:        fmov.l          &0x0,%fpsr              # clear FPSR
                   14355:
                   14356:        fsgldiv.x       FP_SCR0(%a6),%fp0       # perform sgl divide
                   14357:
                   14358:        fmov.l          %fpsr,%d1               # save FPSR
                   14359:        fmov.l          &0x0,%fpcr              # clear FPCR
                   14360:
                   14361:        or.l            %d1,USER_FPSR(%a6)      # save INEX2,N
                   14362:
                   14363: fsgldiv_normal_exit:
                   14364:        fmovm.x         &0x80,FP_SCR0(%a6)      # store result on stack
                   14365:        mov.l           %d2,-(%sp)              # save d2
                   14366:        mov.w           FP_SCR0_EX(%a6),%d1     # load {sgn,exp}
                   14367:        mov.l           %d1,%d2                 # make a copy
                   14368:        andi.l          &0x7fff,%d1             # strip sign
                   14369:        andi.w          &0x8000,%d2             # keep old sign
                   14370:        sub.l           %d0,%d1                 # add scale factor
                   14371:        or.w            %d2,%d1                 # concat old sign,new exp
                   14372:        mov.w           %d1,FP_SCR0_EX(%a6)     # insert new exponent
                   14373:        mov.l           (%sp)+,%d2              # restore d2
                   14374:        fmovm.x         FP_SCR0(%a6),&0x80      # return result in fp0
                   14375:        rts
                   14376:
                   14377: fsgldiv_may_ovfl:
                   14378:        fmovm.x         FP_SCR1(%a6),&0x80      # load dst op
                   14379:
                   14380:        fmov.l          L_SCR3(%a6),%fpcr       # set FPCR
                   14381:        fmov.l          &0x0,%fpsr              # set FPSR
                   14382:
                   14383:        fsgldiv.x       FP_SCR0(%a6),%fp0       # execute divide
                   14384:
                   14385:        fmov.l          %fpsr,%d1
                   14386:        fmov.l          &0x0,%fpcr
                   14387:
                   14388:        or.l            %d1,USER_FPSR(%a6)      # save INEX,N
                   14389:
                   14390:        fmovm.x         &0x01,-(%sp)            # save result to stack
                   14391:        mov.w           (%sp),%d1               # fetch new exponent
                   14392:        add.l           &0xc,%sp                # clear result
                   14393:        andi.l          &0x7fff,%d1             # strip sign
                   14394:        sub.l           %d0,%d1                 # add scale factor
                   14395:        cmp.l           %d1,&0x7fff             # did divide overflow?
                   14396:        blt.b           fsgldiv_normal_exit
                   14397:
                   14398: fsgldiv_ovfl_tst:
                   14399:        or.w            &ovfl_inx_mask,2+USER_FPSR(%a6) # set ovfl/aovfl/ainex
                   14400:
                   14401:        mov.b           FPCR_ENABLE(%a6),%d1
                   14402:        andi.b          &0x13,%d1               # is OVFL or INEX enabled?
                   14403:        bne.b           fsgldiv_ovfl_ena        # yes
                   14404:
                   14405: fsgldiv_ovfl_dis:
                   14406:        btst            &neg_bit,FPSR_CC(%a6)   # is result negative
                   14407:        sne             %d1                     # set sign param accordingly
                   14408:        mov.l           L_SCR3(%a6),%d0         # pass prec:rnd
                   14409:        andi.b          &0x30,%d0               # kill precision
                   14410:        bsr.l           ovf_res                 # calculate default result
                   14411:        or.b            %d0,FPSR_CC(%a6)        # set INF if applicable
                   14412:        fmovm.x         (%a0),&0x80             # return default result in fp0
                   14413:        rts
                   14414:
                   14415: fsgldiv_ovfl_ena:
                   14416:        fmovm.x         &0x80,FP_SCR0(%a6)      # move result to stack
                   14417:
                   14418:        mov.l           %d2,-(%sp)              # save d2
                   14419:        mov.w           FP_SCR0_EX(%a6),%d1     # fetch {sgn,exp}
                   14420:        mov.l           %d1,%d2                 # make a copy
                   14421:        andi.l          &0x7fff,%d1             # strip sign
                   14422:        andi.w          &0x8000,%d2             # keep old sign
                   14423:        sub.l           %d0,%d1                 # add scale factor
                   14424:        subi.l          &0x6000,%d1             # subtract new bias
                   14425:        andi.w          &0x7fff,%d1             # clear ms bit
                   14426:        or.w            %d2,%d1                 # concat old sign,new exp
                   14427:        mov.w           %d1,FP_SCR0_EX(%a6)     # insert new exponent
                   14428:        mov.l           (%sp)+,%d2              # restore d2
                   14429:        fmovm.x         FP_SCR0(%a6),&0x40      # return EXOP in fp1
                   14430:        bra.b           fsgldiv_ovfl_dis
                   14431:
                   14432: fsgldiv_unfl:
                   14433:        bset            &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
                   14434:
                   14435:        fmovm.x         FP_SCR1(%a6),&0x80      # load dst op
                   14436:
                   14437:        fmov.l          &rz_mode*0x10,%fpcr     # set FPCR
                   14438:        fmov.l          &0x0,%fpsr              # clear FPSR
                   14439:
                   14440:        fsgldiv.x       FP_SCR0(%a6),%fp0       # execute sgl divide
                   14441:
                   14442:        fmov.l          %fpsr,%d1               # save status
                   14443:        fmov.l          &0x0,%fpcr              # clear FPCR
                   14444:
                   14445:        or.l            %d1,USER_FPSR(%a6)      # save INEX2,N
                   14446:
                   14447:        mov.b           FPCR_ENABLE(%a6),%d1
                   14448:        andi.b          &0x0b,%d1               # is UNFL or INEX enabled?
                   14449:        bne.b           fsgldiv_unfl_ena        # yes
                   14450:
                   14451: fsgldiv_unfl_dis:
                   14452:        fmovm.x         &0x80,FP_SCR0(%a6)      # store out result
                   14453:
                   14454:        lea             FP_SCR0(%a6),%a0        # pass: result addr
                   14455:        mov.l           L_SCR3(%a6),%d1         # pass: rnd prec,mode
                   14456:        bsr.l           unf_res4                # calculate default result
                   14457:        or.b            %d0,FPSR_CC(%a6)        # 'Z' bit may have been set
                   14458:        fmovm.x         FP_SCR0(%a6),&0x80      # return default result in fp0
                   14459:        rts
                   14460:
                   14461: #
                   14462: # UNFL is enabled.
                   14463: #
                   14464: fsgldiv_unfl_ena:
                   14465:        fmovm.x         FP_SCR1(%a6),&0x40      # load dst op
                   14466:
                   14467:        fmov.l          L_SCR3(%a6),%fpcr       # set FPCR
                   14468:        fmov.l          &0x0,%fpsr              # clear FPSR
                   14469:
                   14470:        fsgldiv.x       FP_SCR0(%a6),%fp1       # execute sgl divide
                   14471:
                   14472:        fmov.l          &0x0,%fpcr              # clear FPCR
                   14473:
                   14474:        fmovm.x         &0x40,FP_SCR0(%a6)      # save result to stack
                   14475:        mov.l           %d2,-(%sp)              # save d2
                   14476:        mov.w           FP_SCR0_EX(%a6),%d1     # fetch {sgn,exp}
                   14477:        mov.l           %d1,%d2                 # make a copy
                   14478:        andi.l          &0x7fff,%d1             # strip sign
                   14479:        andi.w          &0x8000,%d2             # keep old sign
                   14480:        sub.l           %d0,%d1                 # add scale factor
                   14481:        addi.l          &0x6000,%d1             # add bias
                   14482:        andi.w          &0x7fff,%d1             # clear top bit
                   14483:        or.w            %d2,%d1                 # concat old sign, new exp
                   14484:        mov.w           %d1,FP_SCR0_EX(%a6)     # insert new exponent
                   14485:        mov.l           (%sp)+,%d2              # restore d2
                   14486:        fmovm.x         FP_SCR0(%a6),&0x40      # return EXOP in fp1
                   14487:        bra.b           fsgldiv_unfl_dis
                   14488:
                   14489: #
                   14490: # the divide operation MAY underflow:
                   14491: #
                   14492: fsgldiv_may_unfl:
                   14493:        fmovm.x         FP_SCR1(%a6),&0x80      # load dst op
                   14494:
                   14495:        fmov.l          L_SCR3(%a6),%fpcr       # set FPCR
                   14496:        fmov.l          &0x0,%fpsr              # clear FPSR
                   14497:
                   14498:        fsgldiv.x       FP_SCR0(%a6),%fp0       # execute sgl divide
                   14499:
                   14500:        fmov.l          %fpsr,%d1               # save status
                   14501:        fmov.l          &0x0,%fpcr              # clear FPCR
                   14502:
                   14503:        or.l            %d1,USER_FPSR(%a6)      # save INEX2,N
                   14504:
                   14505:        fabs.x          %fp0,%fp1               # make a copy of result
                   14506:        fcmp.b          %fp1,&0x1               # is |result| > 1.b?
                   14507:        fbgt.w          fsgldiv_normal_exit     # no; no underflow occurred
                   14508:        fblt.w          fsgldiv_unfl            # yes; underflow occurred
                   14509:
                   14510: #
                   14511: # we still don't know if underflow occurred. result is ~ equal to 1. but,
                   14512: # we don't know if the result was an underflow that rounded up to a 1
                   14513: # or a normalized number that rounded down to a 1. so, redo the entire
                   14514: # operation using RZ as the rounding mode to see what the pre-rounded
                   14515: # result is. this case should be relatively rare.
                   14516: #
                   14517:        fmovm.x         FP_SCR1(%a6),&0x40      # load dst op into %fp1
                   14518:
                   14519:        clr.l           %d1                     # clear scratch register
                   14520:        ori.b           &rz_mode*0x10,%d1       # force RZ rnd mode
                   14521:
                   14522:        fmov.l          %d1,%fpcr               # set FPCR
                   14523:        fmov.l          &0x0,%fpsr              # clear FPSR
                   14524:
                   14525:        fsgldiv.x       FP_SCR0(%a6),%fp1       # execute sgl divide
                   14526:
                   14527:        fmov.l          &0x0,%fpcr              # clear FPCR
                   14528:        fabs.x          %fp1                    # make absolute value
                   14529:        fcmp.b          %fp1,&0x1               # is |result| < 1.b?
                   14530:        fbge.w          fsgldiv_normal_exit     # no; no underflow occurred
                   14531:        bra.w           fsgldiv_unfl            # yes; underflow occurred
                   14532:
                   14533: ############################################################################
                   14534:
                   14535: #
                   14536: # Divide: inputs are not both normalized; what are they?
                   14537: #
                   14538: fsgldiv_not_norm:
                   14539:        mov.w           (tbl_fsgldiv_op.b,%pc,%d1.w*2),%d1
                   14540:        jmp             (tbl_fsgldiv_op.b,%pc,%d1.w*1)
                   14541:
                   14542:        swbeg           &48
                   14543: tbl_fsgldiv_op:
                   14544:        short           fsgldiv_norm            - tbl_fsgldiv_op # NORM / NORM
                   14545:        short           fsgldiv_inf_load        - tbl_fsgldiv_op # NORM / ZERO
                   14546:        short           fsgldiv_zero_load       - tbl_fsgldiv_op # NORM / INF
                   14547:        short           fsgldiv_res_qnan        - tbl_fsgldiv_op # NORM / QNAN
                   14548:        short           fsgldiv_norm            - tbl_fsgldiv_op # NORM / DENORM
                   14549:        short           fsgldiv_res_snan        - tbl_fsgldiv_op # NORM / SNAN
                   14550:        short           tbl_fsgldiv_op          - tbl_fsgldiv_op #
                   14551:        short           tbl_fsgldiv_op          - tbl_fsgldiv_op #
                   14552:
                   14553:        short           fsgldiv_zero_load       - tbl_fsgldiv_op # ZERO / NORM
                   14554:        short           fsgldiv_res_operr       - tbl_fsgldiv_op # ZERO / ZERO
                   14555:        short           fsgldiv_zero_load       - tbl_fsgldiv_op # ZERO / INF
                   14556:        short           fsgldiv_res_qnan        - tbl_fsgldiv_op # ZERO / QNAN
                   14557:        short           fsgldiv_zero_load       - tbl_fsgldiv_op # ZERO / DENORM
                   14558:        short           fsgldiv_res_snan        - tbl_fsgldiv_op # ZERO / SNAN
                   14559:        short           tbl_fsgldiv_op          - tbl_fsgldiv_op #
                   14560:        short           tbl_fsgldiv_op          - tbl_fsgldiv_op #
                   14561:
                   14562:        short           fsgldiv_inf_dst         - tbl_fsgldiv_op # INF / NORM
                   14563:        short           fsgldiv_inf_dst         - tbl_fsgldiv_op # INF / ZERO
                   14564:        short           fsgldiv_res_operr       - tbl_fsgldiv_op # INF / INF
                   14565:        short           fsgldiv_res_qnan        - tbl_fsgldiv_op # INF / QNAN
                   14566:        short           fsgldiv_inf_dst         - tbl_fsgldiv_op # INF / DENORM
                   14567:        short           fsgldiv_res_snan        - tbl_fsgldiv_op # INF / SNAN
                   14568:        short           tbl_fsgldiv_op          - tbl_fsgldiv_op #
                   14569:        short           tbl_fsgldiv_op          - tbl_fsgldiv_op #
                   14570:
                   14571:        short           fsgldiv_res_qnan        - tbl_fsgldiv_op # QNAN / NORM
                   14572:        short           fsgldiv_res_qnan        - tbl_fsgldiv_op # QNAN / ZERO
                   14573:        short           fsgldiv_res_qnan        - tbl_fsgldiv_op # QNAN / INF
                   14574:        short           fsgldiv_res_qnan        - tbl_fsgldiv_op # QNAN / QNAN
                   14575:        short           fsgldiv_res_qnan        - tbl_fsgldiv_op # QNAN / DENORM
                   14576:        short           fsgldiv_res_snan        - tbl_fsgldiv_op # QNAN / SNAN
                   14577:        short           tbl_fsgldiv_op          - tbl_fsgldiv_op #
                   14578:        short           tbl_fsgldiv_op          - tbl_fsgldiv_op #
                   14579:
                   14580:        short           fsgldiv_norm            - tbl_fsgldiv_op # DENORM / NORM
                   14581:        short           fsgldiv_inf_load        - tbl_fsgldiv_op # DENORM / ZERO
                   14582:        short           fsgldiv_zero_load       - tbl_fsgldiv_op # DENORM / INF
                   14583:        short           fsgldiv_res_qnan        - tbl_fsgldiv_op # DENORM / QNAN
                   14584:        short           fsgldiv_norm            - tbl_fsgldiv_op # DENORM / DENORM
                   14585:        short           fsgldiv_res_snan        - tbl_fsgldiv_op # DENORM / SNAN
                   14586:        short           tbl_fsgldiv_op          - tbl_fsgldiv_op #
                   14587:        short           tbl_fsgldiv_op          - tbl_fsgldiv_op #
                   14588:
                   14589:        short           fsgldiv_res_snan        - tbl_fsgldiv_op # SNAN / NORM
                   14590:        short           fsgldiv_res_snan        - tbl_fsgldiv_op # SNAN / ZERO
                   14591:        short           fsgldiv_res_snan        - tbl_fsgldiv_op # SNAN / INF
                   14592:        short           fsgldiv_res_snan        - tbl_fsgldiv_op # SNAN / QNAN
                   14593:        short           fsgldiv_res_snan        - tbl_fsgldiv_op # SNAN / DENORM
                   14594:        short           fsgldiv_res_snan        - tbl_fsgldiv_op # SNAN / SNAN
                   14595:        short           tbl_fsgldiv_op          - tbl_fsgldiv_op #
                   14596:        short           tbl_fsgldiv_op          - tbl_fsgldiv_op #
                   14597:
                   14598: fsgldiv_res_qnan:
                   14599:        bra.l           res_qnan
                   14600: fsgldiv_res_snan:
                   14601:        bra.l           res_snan
                   14602: fsgldiv_res_operr:
                   14603:        bra.l           res_operr
                   14604: fsgldiv_inf_load:
                   14605:        bra.l           fdiv_inf_load
                   14606: fsgldiv_zero_load:
                   14607:        bra.l           fdiv_zero_load
                   14608: fsgldiv_inf_dst:
                   14609:        bra.l           fdiv_inf_dst
                   14610:
                   14611: #########################################################################
                   14612: # XDEF ****************************************************************        #
                   14613: #      fadd(): emulates the fadd instruction                           #
                   14614: #      fsadd(): emulates the fadd instruction                          #
                   14615: #      fdadd(): emulates the fdadd instruction                         #
                   14616: #                                                                      #
                   14617: # XREF ****************************************************************        #
                   14618: #      addsub_scaler2() - scale the operands so they won't take exc    #
                   14619: #      ovf_res() - return default overflow result                      #
                   14620: #      unf_res() - return default underflow result                     #
                   14621: #      res_qnan() - set QNAN result                                    #
                   14622: #      res_snan() - set SNAN result                                    #
                   14623: #      res_operr() - set OPERR result                                  #
                   14624: #      scale_to_zero_src() - set src operand exponent equal to zero    #
                   14625: #      scale_to_zero_dst() - set dst operand exponent equal to zero    #
                   14626: #                                                                      #
                   14627: # INPUT ***************************************************************        #
                   14628: #      a0 = pointer to extended precision source operand               #
                   14629: #      a1 = pointer to extended precision destination operand          #
                   14630: #                                                                      #
                   14631: # OUTPUT **************************************************************        #
                   14632: #      fp0 = result                                                    #
                   14633: #      fp1 = EXOP (if exception occurred)                              #
                   14634: #                                                                      #
                   14635: # ALGORITHM ***********************************************************        #
                   14636: #      Handle NANs, infinities, and zeroes as special cases. Divide    #
                   14637: # norms into extended, single, and double precision.                   #
                   14638: #      Do addition after scaling exponents such that exception won't   #
                   14639: # occur. Then, check result exponent to see if exception would have    #
                   14640: # occurred. If so, return default result and maybe EXOP. Else, insert  #
                   14641: # the correct result exponent and return. Set FPSR bits as appropriate.        #
                   14642: #                                                                      #
                   14643: #########################################################################
                   14644:
                   14645:        global          fsadd
                   14646: fsadd:
                   14647:        andi.b          &0x30,%d0               # clear rnd prec
                   14648:        ori.b           &s_mode*0x10,%d0        # insert sgl prec
                   14649:        bra.b           fadd
                   14650:
                   14651:        global          fdadd
                   14652: fdadd:
                   14653:        andi.b          &0x30,%d0               # clear rnd prec
                   14654:        ori.b           &d_mode*0x10,%d0        # insert dbl prec
                   14655:
                   14656:        global          fadd
                   14657: fadd:
                   14658:        mov.l           %d0,L_SCR3(%a6)         # store rnd info
                   14659:
                   14660:        clr.w           %d1
                   14661:        mov.b           DTAG(%a6),%d1
                   14662:        lsl.b           &0x3,%d1
                   14663:        or.b            STAG(%a6),%d1           # combine src tags
                   14664:
                   14665:        bne.w           fadd_not_norm           # optimize on non-norm input
                   14666:
                   14667: #
                   14668: # ADD: norms and denorms
                   14669: #
                   14670: fadd_norm:
                   14671:        bsr.l           addsub_scaler2          # scale exponents
                   14672:
                   14673: fadd_zero_entry:
                   14674:        fmovm.x         FP_SCR1(%a6),&0x80      # load dst op
                   14675:
                   14676:        fmov.l          &0x0,%fpsr              # clear FPSR
                   14677:        fmov.l          L_SCR3(%a6),%fpcr       # set FPCR
                   14678:
                   14679:        fadd.x          FP_SCR0(%a6),%fp0       # execute add
                   14680:
                   14681:        fmov.l          &0x0,%fpcr              # clear FPCR
                   14682:        fmov.l          %fpsr,%d1               # fetch INEX2,N,Z
                   14683:
                   14684:        or.l            %d1,USER_FPSR(%a6)      # save exc and ccode bits
                   14685:
                   14686:        fbeq.w          fadd_zero_exit          # if result is zero, end now
                   14687:
                   14688:        mov.l           %d2,-(%sp)              # save d2
                   14689:
                   14690:        fmovm.x         &0x01,-(%sp)            # save result to stack
                   14691:
                   14692:        mov.w           2+L_SCR3(%a6),%d1
                   14693:        lsr.b           &0x6,%d1
                   14694:
                   14695:        mov.w           (%sp),%d2               # fetch new sign, exp
                   14696:        andi.l          &0x7fff,%d2             # strip sign
                   14697:        sub.l           %d0,%d2                 # add scale factor
                   14698:
                   14699:        cmp.l           %d2,(tbl_fadd_ovfl.b,%pc,%d1.w*4) # is it an overflow?
                   14700:        bge.b           fadd_ovfl               # yes
                   14701:
                   14702:        cmp.l           %d2,(tbl_fadd_unfl.b,%pc,%d1.w*4) # is it an underflow?
                   14703:        blt.w           fadd_unfl               # yes
                   14704:        beq.w           fadd_may_unfl           # maybe; go find out
                   14705:
                   14706: fadd_normal:
                   14707:        mov.w           (%sp),%d1
                   14708:        andi.w          &0x8000,%d1             # keep sign
                   14709:        or.w            %d2,%d1                 # concat sign,new exp
                   14710:        mov.w           %d1,(%sp)               # insert new exponent
                   14711:
                   14712:        fmovm.x         (%sp)+,&0x80            # return result in fp0
                   14713:
                   14714:        mov.l           (%sp)+,%d2              # restore d2
                   14715:        rts
                   14716:
                   14717: fadd_zero_exit:
                   14718: #      fmov.s          &0x00000000,%fp0        # return zero in fp0
                   14719:        rts
                   14720:
                   14721: tbl_fadd_ovfl:
                   14722:        long            0x7fff                  # ext ovfl
                   14723:        long            0x407f                  # sgl ovfl
                   14724:        long            0x43ff                  # dbl ovfl
                   14725:
                   14726: tbl_fadd_unfl:
                   14727:        long            0x0000                  # ext unfl
                   14728:        long            0x3f81                  # sgl unfl
                   14729:        long            0x3c01                  # dbl unfl
                   14730:
                   14731: fadd_ovfl:
                   14732:        or.l            &ovfl_inx_mask,USER_FPSR(%a6) # set ovfl/aovfl/ainex
                   14733:
                   14734:        mov.b           FPCR_ENABLE(%a6),%d1
                   14735:        andi.b          &0x13,%d1               # is OVFL or INEX enabled?
                   14736:        bne.b           fadd_ovfl_ena           # yes
                   14737:
                   14738:        add.l           &0xc,%sp
                   14739: fadd_ovfl_dis:
                   14740:        btst            &neg_bit,FPSR_CC(%a6)   # is result negative?
                   14741:        sne             %d1                     # set sign param accordingly
                   14742:        mov.l           L_SCR3(%a6),%d0         # pass prec:rnd
                   14743:        bsr.l           ovf_res                 # calculate default result
                   14744:        or.b            %d0,FPSR_CC(%a6)        # set INF,N if applicable
                   14745:        fmovm.x         (%a0),&0x80             # return default result in fp0
                   14746:        mov.l           (%sp)+,%d2              # restore d2
                   14747:        rts
                   14748:
                   14749: fadd_ovfl_ena:
                   14750:        mov.b           L_SCR3(%a6),%d1
                   14751:        andi.b          &0xc0,%d1               # is precision extended?
                   14752:        bne.b           fadd_ovfl_ena_sd        # no; prec = sgl or dbl
                   14753:
                   14754: fadd_ovfl_ena_cont:
                   14755:        mov.w           (%sp),%d1
                   14756:        andi.w          &0x8000,%d1             # keep sign
                   14757:        subi.l          &0x6000,%d2             # add extra bias
                   14758:        andi.w          &0x7fff,%d2
                   14759:        or.w            %d2,%d1                 # concat sign,new exp
                   14760:        mov.w           %d1,(%sp)               # insert new exponent
                   14761:
                   14762:        fmovm.x         (%sp)+,&0x40            # return EXOP in fp1
                   14763:        bra.b           fadd_ovfl_dis
                   14764:
                   14765: fadd_ovfl_ena_sd:
                   14766:        fmovm.x         FP_SCR1(%a6),&0x80      # load dst op
                   14767:
                   14768:        mov.l           L_SCR3(%a6),%d1
                   14769:        andi.b          &0x30,%d1               # keep rnd mode
                   14770:        fmov.l          %d1,%fpcr               # set FPCR
                   14771:
                   14772:        fadd.x          FP_SCR0(%a6),%fp0       # execute add
                   14773:
                   14774:        fmov.l          &0x0,%fpcr              # clear FPCR
                   14775:
                   14776:        add.l           &0xc,%sp
                   14777:        fmovm.x         &0x01,-(%sp)
                   14778:        bra.b           fadd_ovfl_ena_cont
                   14779:
                   14780: fadd_unfl:
                   14781:        bset            &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
                   14782:
                   14783:        add.l           &0xc,%sp
                   14784:
                   14785:        fmovm.x         FP_SCR1(%a6),&0x80      # load dst op
                   14786:
                   14787:        fmov.l          &rz_mode*0x10,%fpcr     # set FPCR
                   14788:        fmov.l          &0x0,%fpsr              # clear FPSR
                   14789:
                   14790:        fadd.x          FP_SCR0(%a6),%fp0       # execute add
                   14791:
                   14792:        fmov.l          &0x0,%fpcr              # clear FPCR
                   14793:        fmov.l          %fpsr,%d1               # save status
                   14794:
                   14795:        or.l            %d1,USER_FPSR(%a6)      # save INEX,N
                   14796:
                   14797:        mov.b           FPCR_ENABLE(%a6),%d1
                   14798:        andi.b          &0x0b,%d1               # is UNFL or INEX enabled?
                   14799:        bne.b           fadd_unfl_ena           # yes
                   14800:
                   14801: fadd_unfl_dis:
                   14802:        fmovm.x         &0x80,FP_SCR0(%a6)      # store out result
                   14803:
                   14804:        lea             FP_SCR0(%a6),%a0        # pass: result addr
                   14805:        mov.l           L_SCR3(%a6),%d1         # pass: rnd prec,mode
                   14806:        bsr.l           unf_res                 # calculate default result
                   14807:        or.b            %d0,FPSR_CC(%a6)        # 'Z' bit may have been set
                   14808:        fmovm.x         FP_SCR0(%a6),&0x80      # return default result in fp0
                   14809:        mov.l           (%sp)+,%d2              # restore d2
                   14810:        rts
                   14811:
                   14812: fadd_unfl_ena:
                   14813:        fmovm.x         FP_SCR1(%a6),&0x40      # load dst op
                   14814:
                   14815:        mov.l           L_SCR3(%a6),%d1
                   14816:        andi.b          &0xc0,%d1               # is precision extended?
                   14817:        bne.b           fadd_unfl_ena_sd        # no; sgl or dbl
                   14818:
                   14819:        fmov.l          L_SCR3(%a6),%fpcr       # set FPCR
                   14820:
                   14821: fadd_unfl_ena_cont:
                   14822:        fmov.l          &0x0,%fpsr              # clear FPSR
                   14823:
                   14824:        fadd.x          FP_SCR0(%a6),%fp1       # execute multiply
                   14825:
                   14826:        fmov.l          &0x0,%fpcr              # clear FPCR
                   14827:
                   14828:        fmovm.x         &0x40,FP_SCR0(%a6)      # save result to stack
                   14829:        mov.w           FP_SCR0_EX(%a6),%d1     # fetch {sgn,exp}
                   14830:        mov.l           %d1,%d2                 # make a copy
                   14831:        andi.l          &0x7fff,%d1             # strip sign
                   14832:        andi.w          &0x8000,%d2             # keep old sign
                   14833:        sub.l           %d0,%d1                 # add scale factor
                   14834:        addi.l          &0x6000,%d1             # add new bias
                   14835:        andi.w          &0x7fff,%d1             # clear top bit
                   14836:        or.w            %d2,%d1                 # concat sign,new exp
                   14837:        mov.w           %d1,FP_SCR0_EX(%a6)     # insert new exponent
                   14838:        fmovm.x         FP_SCR0(%a6),&0x40      # return EXOP in fp1
                   14839:        bra.w           fadd_unfl_dis
                   14840:
                   14841: fadd_unfl_ena_sd:
                   14842:        mov.l           L_SCR3(%a6),%d1
                   14843:        andi.b          &0x30,%d1               # use only rnd mode
                   14844:        fmov.l          %d1,%fpcr               # set FPCR
                   14845:
                   14846:        bra.b           fadd_unfl_ena_cont
                   14847:
                   14848: #
                   14849: # result is equal to the smallest normalized number in the selected precision
                   14850: # if the precision is extended, this result could not have come from an
                   14851: # underflow that rounded up.
                   14852: #
                   14853: fadd_may_unfl:
                   14854:        mov.l           L_SCR3(%a6),%d1
                   14855:        andi.b          &0xc0,%d1
                   14856:        beq.w           fadd_normal             # yes; no underflow occurred
                   14857:
                   14858:        mov.l           0x4(%sp),%d1            # extract hi(man)
                   14859:        cmpi.l          %d1,&0x80000000         # is hi(man) = 0x80000000?
                   14860:        bne.w           fadd_normal             # no; no underflow occurred
                   14861:
                   14862:        tst.l           0x8(%sp)                # is lo(man) = 0x0?
                   14863:        bne.w           fadd_normal             # no; no underflow occurred
                   14864:
                   14865:        btst            &inex2_bit,FPSR_EXCEPT(%a6) # is INEX2 set?
                   14866:        beq.w           fadd_normal             # no; no underflow occurred
                   14867:
                   14868: #
                   14869: # ok, so now the result has a exponent equal to the smallest normalized
                   14870: # exponent for the selected precision. also, the mantissa is equal to
                   14871: # 0x8000000000000000 and this mantissa is the result of rounding non-zero
                   14872: # g,r,s.
                   14873: # now, we must determine whether the pre-rounded result was an underflow
                   14874: # rounded "up" or a normalized number rounded "down".
                   14875: # so, we do this be re-executing the add using RZ as the rounding mode and
                   14876: # seeing if the new result is smaller or equal to the current result.
                   14877: #
                   14878:        fmovm.x         FP_SCR1(%a6),&0x40      # load dst op into fp1
                   14879:
                   14880:        mov.l           L_SCR3(%a6),%d1
                   14881:        andi.b          &0xc0,%d1               # keep rnd prec
                   14882:        ori.b           &rz_mode*0x10,%d1       # insert rnd mode
                   14883:        fmov.l          %d1,%fpcr               # set FPCR
                   14884:        fmov.l          &0x0,%fpsr              # clear FPSR
                   14885:
                   14886:        fadd.x          FP_SCR0(%a6),%fp1       # execute add
                   14887:
                   14888:        fmov.l          &0x0,%fpcr              # clear FPCR
                   14889:
                   14890:        fabs.x          %fp0                    # compare absolute values
                   14891:        fabs.x          %fp1
                   14892:        fcmp.x          %fp0,%fp1               # is first result > second?
                   14893:
                   14894:        fbgt.w          fadd_unfl               # yes; it's an underflow
                   14895:        bra.w           fadd_normal             # no; it's not an underflow
                   14896:
                   14897: ##########################################################################
                   14898:
                   14899: #
                   14900: # Add: inputs are not both normalized; what are they?
                   14901: #
                   14902: fadd_not_norm:
                   14903:        mov.w           (tbl_fadd_op.b,%pc,%d1.w*2),%d1
                   14904:        jmp             (tbl_fadd_op.b,%pc,%d1.w*1)
                   14905:
                   14906:        swbeg           &48
                   14907: tbl_fadd_op:
                   14908:        short           fadd_norm       - tbl_fadd_op # NORM + NORM
                   14909:        short           fadd_zero_src   - tbl_fadd_op # NORM + ZERO
                   14910:        short           fadd_inf_src    - tbl_fadd_op # NORM + INF
                   14911:        short           fadd_res_qnan   - tbl_fadd_op # NORM + QNAN
                   14912:        short           fadd_norm       - tbl_fadd_op # NORM + DENORM
                   14913:        short           fadd_res_snan   - tbl_fadd_op # NORM + SNAN
                   14914:        short           tbl_fadd_op     - tbl_fadd_op #
                   14915:        short           tbl_fadd_op     - tbl_fadd_op #
                   14916:
                   14917:        short           fadd_zero_dst   - tbl_fadd_op # ZERO + NORM
                   14918:        short           fadd_zero_2     - tbl_fadd_op # ZERO + ZERO
                   14919:        short           fadd_inf_src    - tbl_fadd_op # ZERO + INF
                   14920:        short           fadd_res_qnan   - tbl_fadd_op # NORM + QNAN
                   14921:        short           fadd_zero_dst   - tbl_fadd_op # ZERO + DENORM
                   14922:        short           fadd_res_snan   - tbl_fadd_op # NORM + SNAN
                   14923:        short           tbl_fadd_op     - tbl_fadd_op #
                   14924:        short           tbl_fadd_op     - tbl_fadd_op #
                   14925:
                   14926:        short           fadd_inf_dst    - tbl_fadd_op # INF + NORM
                   14927:        short           fadd_inf_dst    - tbl_fadd_op # INF + ZERO
                   14928:        short           fadd_inf_2      - tbl_fadd_op # INF + INF
                   14929:        short           fadd_res_qnan   - tbl_fadd_op # NORM + QNAN
                   14930:        short           fadd_inf_dst    - tbl_fadd_op # INF + DENORM
                   14931:        short           fadd_res_snan   - tbl_fadd_op # NORM + SNAN
                   14932:        short           tbl_fadd_op     - tbl_fadd_op #
                   14933:        short           tbl_fadd_op     - tbl_fadd_op #
                   14934:
                   14935:        short           fadd_res_qnan   - tbl_fadd_op # QNAN + NORM
                   14936:        short           fadd_res_qnan   - tbl_fadd_op # QNAN + ZERO
                   14937:        short           fadd_res_qnan   - tbl_fadd_op # QNAN + INF
                   14938:        short           fadd_res_qnan   - tbl_fadd_op # QNAN + QNAN
                   14939:        short           fadd_res_qnan   - tbl_fadd_op # QNAN + DENORM
                   14940:        short           fadd_res_snan   - tbl_fadd_op # QNAN + SNAN
                   14941:        short           tbl_fadd_op     - tbl_fadd_op #
                   14942:        short           tbl_fadd_op     - tbl_fadd_op #
                   14943:
                   14944:        short           fadd_norm       - tbl_fadd_op # DENORM + NORM
                   14945:        short           fadd_zero_src   - tbl_fadd_op # DENORM + ZERO
                   14946:        short           fadd_inf_src    - tbl_fadd_op # DENORM + INF
                   14947:        short           fadd_res_qnan   - tbl_fadd_op # NORM + QNAN
                   14948:        short           fadd_norm       - tbl_fadd_op # DENORM + DENORM
                   14949:        short           fadd_res_snan   - tbl_fadd_op # NORM + SNAN
                   14950:        short           tbl_fadd_op     - tbl_fadd_op #
                   14951:        short           tbl_fadd_op     - tbl_fadd_op #
                   14952:
                   14953:        short           fadd_res_snan   - tbl_fadd_op # SNAN + NORM
                   14954:        short           fadd_res_snan   - tbl_fadd_op # SNAN + ZERO
                   14955:        short           fadd_res_snan   - tbl_fadd_op # SNAN + INF
                   14956:        short           fadd_res_snan   - tbl_fadd_op # SNAN + QNAN
                   14957:        short           fadd_res_snan   - tbl_fadd_op # SNAN + DENORM
                   14958:        short           fadd_res_snan   - tbl_fadd_op # SNAN + SNAN
                   14959:        short           tbl_fadd_op     - tbl_fadd_op #
                   14960:        short           tbl_fadd_op     - tbl_fadd_op #
                   14961:
                   14962: fadd_res_qnan:
                   14963:        bra.l           res_qnan
                   14964: fadd_res_snan:
                   14965:        bra.l           res_snan
                   14966:
                   14967: #
                   14968: # both operands are ZEROes
                   14969: #
                   14970: fadd_zero_2:
                   14971:        mov.b           SRC_EX(%a0),%d0         # are the signs opposite
                   14972:        mov.b           DST_EX(%a1),%d1
                   14973:        eor.b           %d0,%d1
                   14974:        bmi.w           fadd_zero_2_chk_rm      # weed out (-ZERO)+(+ZERO)
                   14975:
                   14976: # the signs are the same. so determine whether they are positive or negative
                   14977: # and return the appropriately signed zero.
                   14978:        tst.b           %d0                     # are ZEROes positive or negative?
                   14979:        bmi.b           fadd_zero_rm            # negative
                   14980:        fmov.s          &0x00000000,%fp0        # return +ZERO
                   14981:        mov.b           &z_bmask,FPSR_CC(%a6)   # set Z
                   14982:        rts
                   14983:
                   14984: #
                   14985: # the ZEROes have opposite signs:
                   14986: # - therefore, we return +ZERO if the rounding modes are RN,RZ, or RP.
                   14987: # - -ZERO is returned in the case of RM.
                   14988: #
                   14989: fadd_zero_2_chk_rm:
                   14990:        mov.b           3+L_SCR3(%a6),%d1
                   14991:        andi.b          &0x30,%d1               # extract rnd mode
                   14992:        cmpi.b          %d1,&rm_mode*0x10       # is rnd mode == RM?
                   14993:        beq.b           fadd_zero_rm            # yes
                   14994:        fmov.s          &0x00000000,%fp0        # return +ZERO
                   14995:        mov.b           &z_bmask,FPSR_CC(%a6)   # set Z
                   14996:        rts
                   14997:
                   14998: fadd_zero_rm:
                   14999:        fmov.s          &0x80000000,%fp0        # return -ZERO
                   15000:        mov.b           &neg_bmask+z_bmask,FPSR_CC(%a6) # set NEG/Z
                   15001:        rts
                   15002:
                   15003: #
                   15004: # one operand is a ZERO and the other is a DENORM or NORM. scale
                   15005: # the DENORM or NORM and jump to the regular fadd routine.
                   15006: #
                   15007: fadd_zero_dst:
                   15008:        mov.w           SRC_EX(%a0),FP_SCR0_EX(%a6)
                   15009:        mov.l           SRC_HI(%a0),FP_SCR0_HI(%a6)
                   15010:        mov.l           SRC_LO(%a0),FP_SCR0_LO(%a6)
                   15011:        bsr.l           scale_to_zero_src       # scale the operand
                   15012:        clr.w           FP_SCR1_EX(%a6)
                   15013:        clr.l           FP_SCR1_HI(%a6)
                   15014:        clr.l           FP_SCR1_LO(%a6)
                   15015:        bra.w           fadd_zero_entry         # go execute fadd
                   15016:
                   15017: fadd_zero_src:
                   15018:        mov.w           DST_EX(%a1),FP_SCR1_EX(%a6)
                   15019:        mov.l           DST_HI(%a1),FP_SCR1_HI(%a6)
                   15020:        mov.l           DST_LO(%a1),FP_SCR1_LO(%a6)
                   15021:        bsr.l           scale_to_zero_dst       # scale the operand
                   15022:        clr.w           FP_SCR0_EX(%a6)
                   15023:        clr.l           FP_SCR0_HI(%a6)
                   15024:        clr.l           FP_SCR0_LO(%a6)
                   15025:        bra.w           fadd_zero_entry         # go execute fadd
                   15026:
                   15027: #
                   15028: # both operands are INFs. an OPERR will result if the INFs have
                   15029: # different signs. else, an INF of the same sign is returned
                   15030: #
                   15031: fadd_inf_2:
                   15032:        mov.b           SRC_EX(%a0),%d0         # exclusive or the signs
                   15033:        mov.b           DST_EX(%a1),%d1
                   15034:        eor.b           %d1,%d0
                   15035:        bmi.l           res_operr               # weed out (-INF)+(+INF)
                   15036:
                   15037: # ok, so it's not an OPERR. but, we do have to remember to return the
                   15038: # src INF since that's where the 881/882 gets the j-bit from...
                   15039:
                   15040: #
                   15041: # operands are INF and one of {ZERO, INF, DENORM, NORM}
                   15042: #
                   15043: fadd_inf_src:
                   15044:        fmovm.x         SRC(%a0),&0x80          # return src INF
                   15045:        tst.b           SRC_EX(%a0)             # is INF positive?
                   15046:        bpl.b           fadd_inf_done           # yes; we're done
                   15047:        mov.b           &neg_bmask+inf_bmask,FPSR_CC(%a6) # set INF/NEG
                   15048:        rts
                   15049:
                   15050: #
                   15051: # operands are INF and one of {ZERO, INF, DENORM, NORM}
                   15052: #
                   15053: fadd_inf_dst:
                   15054:        fmovm.x         DST(%a1),&0x80          # return dst INF
                   15055:        tst.b           DST_EX(%a1)             # is INF positive?
                   15056:        bpl.b           fadd_inf_done           # yes; we're done
                   15057:        mov.b           &neg_bmask+inf_bmask,FPSR_CC(%a6) # set INF/NEG
                   15058:        rts
                   15059:
                   15060: fadd_inf_done:
                   15061:        mov.b           &inf_bmask,FPSR_CC(%a6) # set INF
                   15062:        rts
                   15063:
                   15064: #########################################################################
                   15065: # XDEF ****************************************************************        #
                   15066: #      fsub(): emulates the fsub instruction                           #
                   15067: #      fssub(): emulates the fssub instruction                         #
                   15068: #      fdsub(): emulates the fdsub instruction                         #
                   15069: #                                                                      #
                   15070: # XREF ****************************************************************        #
                   15071: #      addsub_scaler2() - scale the operands so they won't take exc    #
                   15072: #      ovf_res() - return default overflow result                      #
                   15073: #      unf_res() - return default underflow result                     #
                   15074: #      res_qnan() - set QNAN result                                    #
                   15075: #      res_snan() - set SNAN result                                    #
                   15076: #      res_operr() - set OPERR result                                  #
                   15077: #      scale_to_zero_src() - set src operand exponent equal to zero    #
                   15078: #      scale_to_zero_dst() - set dst operand exponent equal to zero    #
                   15079: #                                                                      #
                   15080: # INPUT ***************************************************************        #
                   15081: #      a0 = pointer to extended precision source operand               #
                   15082: #      a1 = pointer to extended precision destination operand          #
                   15083: #                                                                      #
                   15084: # OUTPUT **************************************************************        #
                   15085: #      fp0 = result                                                    #
                   15086: #      fp1 = EXOP (if exception occurred)                              #
                   15087: #                                                                      #
                   15088: # ALGORITHM ***********************************************************        #
                   15089: #      Handle NANs, infinities, and zeroes as special cases. Divide    #
                   15090: # norms into extended, single, and double precision.                   #
                   15091: #      Do subtraction after scaling exponents such that exception won't#
                   15092: # occur. Then, check result exponent to see if exception would have    #
                   15093: # occurred. If so, return default result and maybe EXOP. Else, insert  #
                   15094: # the correct result exponent and return. Set FPSR bits as appropriate.        #
                   15095: #                                                                      #
                   15096: #########################################################################
                   15097:
                   15098:        global          fssub
                   15099: fssub:
                   15100:        andi.b          &0x30,%d0               # clear rnd prec
                   15101:        ori.b           &s_mode*0x10,%d0        # insert sgl prec
                   15102:        bra.b           fsub
                   15103:
                   15104:        global          fdsub
                   15105: fdsub:
                   15106:        andi.b          &0x30,%d0               # clear rnd prec
                   15107:        ori.b           &d_mode*0x10,%d0        # insert dbl prec
                   15108:
                   15109:        global          fsub
                   15110: fsub:
                   15111:        mov.l           %d0,L_SCR3(%a6)         # store rnd info
                   15112:
                   15113:        clr.w           %d1
                   15114:        mov.b           DTAG(%a6),%d1
                   15115:        lsl.b           &0x3,%d1
                   15116:        or.b            STAG(%a6),%d1           # combine src tags
                   15117:
                   15118:        bne.w           fsub_not_norm           # optimize on non-norm input
                   15119:
                   15120: #
                   15121: # SUB: norms and denorms
                   15122: #
                   15123: fsub_norm:
                   15124:        bsr.l           addsub_scaler2          # scale exponents
                   15125:
                   15126: fsub_zero_entry:
                   15127:        fmovm.x         FP_SCR1(%a6),&0x80      # load dst op
                   15128:
                   15129:        fmov.l          &0x0,%fpsr              # clear FPSR
                   15130:        fmov.l          L_SCR3(%a6),%fpcr       # set FPCR
                   15131:
                   15132:        fsub.x          FP_SCR0(%a6),%fp0       # execute subtract
                   15133:
                   15134:        fmov.l          &0x0,%fpcr              # clear FPCR
                   15135:        fmov.l          %fpsr,%d1               # fetch INEX2, N, Z
                   15136:
                   15137:        or.l            %d1,USER_FPSR(%a6)      # save exc and ccode bits
                   15138:
                   15139:        fbeq.w          fsub_zero_exit          # if result zero, end now
                   15140:
                   15141:        mov.l           %d2,-(%sp)              # save d2
                   15142:
                   15143:        fmovm.x         &0x01,-(%sp)            # save result to stack
                   15144:
                   15145:        mov.w           2+L_SCR3(%a6),%d1
                   15146:        lsr.b           &0x6,%d1
                   15147:
                   15148:        mov.w           (%sp),%d2               # fetch new exponent
                   15149:        andi.l          &0x7fff,%d2             # strip sign
                   15150:        sub.l           %d0,%d2                 # add scale factor
                   15151:
                   15152:        cmp.l           %d2,(tbl_fsub_ovfl.b,%pc,%d1.w*4) # is it an overflow?
                   15153:        bge.b           fsub_ovfl               # yes
                   15154:
                   15155:        cmp.l           %d2,(tbl_fsub_unfl.b,%pc,%d1.w*4) # is it an underflow?
                   15156:        blt.w           fsub_unfl               # yes
                   15157:        beq.w           fsub_may_unfl           # maybe; go find out
                   15158:
                   15159: fsub_normal:
                   15160:        mov.w           (%sp),%d1
                   15161:        andi.w          &0x8000,%d1             # keep sign
                   15162:        or.w            %d2,%d1                 # insert new exponent
                   15163:        mov.w           %d1,(%sp)               # insert new exponent
                   15164:
                   15165:        fmovm.x         (%sp)+,&0x80            # return result in fp0
                   15166:
                   15167:        mov.l           (%sp)+,%d2              # restore d2
                   15168:        rts
                   15169:
                   15170: fsub_zero_exit:
                   15171: #      fmov.s          &0x00000000,%fp0        # return zero in fp0
                   15172:        rts
                   15173:
                   15174: tbl_fsub_ovfl:
                   15175:        long            0x7fff                  # ext ovfl
                   15176:        long            0x407f                  # sgl ovfl
                   15177:        long            0x43ff                  # dbl ovfl
                   15178:
                   15179: tbl_fsub_unfl:
                   15180:        long            0x0000                  # ext unfl
                   15181:        long            0x3f81                  # sgl unfl
                   15182:        long            0x3c01                  # dbl unfl
                   15183:
                   15184: fsub_ovfl:
                   15185:        or.l            &ovfl_inx_mask,USER_FPSR(%a6) # set ovfl/aovfl/ainex
                   15186:
                   15187:        mov.b           FPCR_ENABLE(%a6),%d1
                   15188:        andi.b          &0x13,%d1               # is OVFL or INEX enabled?
                   15189:        bne.b           fsub_ovfl_ena           # yes
                   15190:
                   15191:        add.l           &0xc,%sp
                   15192: fsub_ovfl_dis:
                   15193:        btst            &neg_bit,FPSR_CC(%a6)   # is result negative?
                   15194:        sne             %d1                     # set sign param accordingly
                   15195:        mov.l           L_SCR3(%a6),%d0         # pass prec:rnd
                   15196:        bsr.l           ovf_res                 # calculate default result
                   15197:        or.b            %d0,FPSR_CC(%a6)        # set INF,N if applicable
                   15198:        fmovm.x         (%a0),&0x80             # return default result in fp0
                   15199:        mov.l           (%sp)+,%d2              # restore d2
                   15200:        rts
                   15201:
                   15202: fsub_ovfl_ena:
                   15203:        mov.b           L_SCR3(%a6),%d1
                   15204:        andi.b          &0xc0,%d1               # is precision extended?
                   15205:        bne.b           fsub_ovfl_ena_sd        # no
                   15206:
                   15207: fsub_ovfl_ena_cont:
                   15208:        mov.w           (%sp),%d1               # fetch {sgn,exp}
                   15209:        andi.w          &0x8000,%d1             # keep sign
                   15210:        subi.l          &0x6000,%d2             # subtract new bias
                   15211:        andi.w          &0x7fff,%d2             # clear top bit
                   15212:        or.w            %d2,%d1                 # concat sign,exp
                   15213:        mov.w           %d1,(%sp)               # insert new exponent
                   15214:
                   15215:        fmovm.x         (%sp)+,&0x40            # return EXOP in fp1
                   15216:        bra.b           fsub_ovfl_dis
                   15217:
                   15218: fsub_ovfl_ena_sd:
                   15219:        fmovm.x         FP_SCR1(%a6),&0x80      # load dst op
                   15220:
                   15221:        mov.l           L_SCR3(%a6),%d1
                   15222:        andi.b          &0x30,%d1               # clear rnd prec
                   15223:        fmov.l          %d1,%fpcr               # set FPCR
                   15224:
                   15225:        fsub.x          FP_SCR0(%a6),%fp0       # execute subtract
                   15226:
                   15227:        fmov.l          &0x0,%fpcr              # clear FPCR
                   15228:
                   15229:        add.l           &0xc,%sp
                   15230:        fmovm.x         &0x01,-(%sp)
                   15231:        bra.b           fsub_ovfl_ena_cont
                   15232:
                   15233: fsub_unfl:
                   15234:        bset            &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
                   15235:
                   15236:        add.l           &0xc,%sp
                   15237:
                   15238:        fmovm.x         FP_SCR1(%a6),&0x80      # load dst op
                   15239:
                   15240:        fmov.l          &rz_mode*0x10,%fpcr     # set FPCR
                   15241:        fmov.l          &0x0,%fpsr              # clear FPSR
                   15242:
                   15243:        fsub.x          FP_SCR0(%a6),%fp0       # execute subtract
                   15244:
                   15245:        fmov.l          &0x0,%fpcr              # clear FPCR
                   15246:        fmov.l          %fpsr,%d1               # save status
                   15247:
                   15248:        or.l            %d1,USER_FPSR(%a6)
                   15249:
                   15250:        mov.b           FPCR_ENABLE(%a6),%d1
                   15251:        andi.b          &0x0b,%d1               # is UNFL or INEX enabled?
                   15252:        bne.b           fsub_unfl_ena           # yes
                   15253:
                   15254: fsub_unfl_dis:
                   15255:        fmovm.x         &0x80,FP_SCR0(%a6)      # store out result
                   15256:
                   15257:        lea             FP_SCR0(%a6),%a0        # pass: result addr
                   15258:        mov.l           L_SCR3(%a6),%d1         # pass: rnd prec,mode
                   15259:        bsr.l           unf_res                 # calculate default result
                   15260:        or.b            %d0,FPSR_CC(%a6)        # 'Z' may have been set
                   15261:        fmovm.x         FP_SCR0(%a6),&0x80      # return default result in fp0
                   15262:        mov.l           (%sp)+,%d2              # restore d2
                   15263:        rts
                   15264:
                   15265: fsub_unfl_ena:
                   15266:        fmovm.x         FP_SCR1(%a6),&0x40
                   15267:
                   15268:        mov.l           L_SCR3(%a6),%d1
                   15269:        andi.b          &0xc0,%d1               # is precision extended?
                   15270:        bne.b           fsub_unfl_ena_sd        # no
                   15271:
                   15272:        fmov.l          L_SCR3(%a6),%fpcr       # set FPCR
                   15273:
                   15274: fsub_unfl_ena_cont:
                   15275:        fmov.l          &0x0,%fpsr              # clear FPSR
                   15276:
                   15277:        fsub.x          FP_SCR0(%a6),%fp1       # execute subtract
                   15278:
                   15279:        fmov.l          &0x0,%fpcr              # clear FPCR
                   15280:
                   15281:        fmovm.x         &0x40,FP_SCR0(%a6)      # store result to stack
                   15282:        mov.w           FP_SCR0_EX(%a6),%d1     # fetch {sgn,exp}
                   15283:        mov.l           %d1,%d2                 # make a copy
                   15284:        andi.l          &0x7fff,%d1             # strip sign
                   15285:        andi.w          &0x8000,%d2             # keep old sign
                   15286:        sub.l           %d0,%d1                 # add scale factor
                   15287:        addi.l          &0x6000,%d1             # subtract new bias
                   15288:        andi.w          &0x7fff,%d1             # clear top bit
                   15289:        or.w            %d2,%d1                 # concat sgn,exp
                   15290:        mov.w           %d1,FP_SCR0_EX(%a6)     # insert new exponent
                   15291:        fmovm.x         FP_SCR0(%a6),&0x40      # return EXOP in fp1
                   15292:        bra.w           fsub_unfl_dis
                   15293:
                   15294: fsub_unfl_ena_sd:
                   15295:        mov.l           L_SCR3(%a6),%d1
                   15296:        andi.b          &0x30,%d1               # clear rnd prec
                   15297:        fmov.l          %d1,%fpcr               # set FPCR
                   15298:
                   15299:        bra.b           fsub_unfl_ena_cont
                   15300:
                   15301: #
                   15302: # result is equal to the smallest normalized number in the selected precision
                   15303: # if the precision is extended, this result could not have come from an
                   15304: # underflow that rounded up.
                   15305: #
                   15306: fsub_may_unfl:
                   15307:        mov.l           L_SCR3(%a6),%d1
                   15308:        andi.b          &0xc0,%d1               # fetch rnd prec
                   15309:        beq.w           fsub_normal             # yes; no underflow occurred
                   15310:
                   15311:        mov.l           0x4(%sp),%d1
                   15312:        cmpi.l          %d1,&0x80000000         # is hi(man) = 0x80000000?
                   15313:        bne.w           fsub_normal             # no; no underflow occurred
                   15314:
                   15315:        tst.l           0x8(%sp)                # is lo(man) = 0x0?
                   15316:        bne.w           fsub_normal             # no; no underflow occurred
                   15317:
                   15318:        btst            &inex2_bit,FPSR_EXCEPT(%a6) # is INEX2 set?
                   15319:        beq.w           fsub_normal             # no; no underflow occurred
                   15320:
                   15321: #
                   15322: # ok, so now the result has a exponent equal to the smallest normalized
                   15323: # exponent for the selected precision. also, the mantissa is equal to
                   15324: # 0x8000000000000000 and this mantissa is the result of rounding non-zero
                   15325: # g,r,s.
                   15326: # now, we must determine whether the pre-rounded result was an underflow
                   15327: # rounded "up" or a normalized number rounded "down".
                   15328: # so, we do this be re-executing the add using RZ as the rounding mode and
                   15329: # seeing if the new result is smaller or equal to the current result.
                   15330: #
                   15331:        fmovm.x         FP_SCR1(%a6),&0x40      # load dst op into fp1
                   15332:
                   15333:        mov.l           L_SCR3(%a6),%d1
                   15334:        andi.b          &0xc0,%d1               # keep rnd prec
                   15335:        ori.b           &rz_mode*0x10,%d1       # insert rnd mode
                   15336:        fmov.l          %d1,%fpcr               # set FPCR
                   15337:        fmov.l          &0x0,%fpsr              # clear FPSR
                   15338:
                   15339:        fsub.x          FP_SCR0(%a6),%fp1       # execute subtract
                   15340:
                   15341:        fmov.l          &0x0,%fpcr              # clear FPCR
                   15342:
                   15343:        fabs.x          %fp0                    # compare absolute values
                   15344:        fabs.x          %fp1
                   15345:        fcmp.x          %fp0,%fp1               # is first result > second?
                   15346:
                   15347:        fbgt.w          fsub_unfl               # yes; it's an underflow
                   15348:        bra.w           fsub_normal             # no; it's not an underflow
                   15349:
                   15350: ##########################################################################
                   15351:
                   15352: #
                   15353: # Sub: inputs are not both normalized; what are they?
                   15354: #
                   15355: fsub_not_norm:
                   15356:        mov.w           (tbl_fsub_op.b,%pc,%d1.w*2),%d1
                   15357:        jmp             (tbl_fsub_op.b,%pc,%d1.w*1)
                   15358:
                   15359:        swbeg           &48
                   15360: tbl_fsub_op:
                   15361:        short           fsub_norm       - tbl_fsub_op # NORM - NORM
                   15362:        short           fsub_zero_src   - tbl_fsub_op # NORM - ZERO
                   15363:        short           fsub_inf_src    - tbl_fsub_op # NORM - INF
                   15364:        short           fsub_res_qnan   - tbl_fsub_op # NORM - QNAN
                   15365:        short           fsub_norm       - tbl_fsub_op # NORM - DENORM
                   15366:        short           fsub_res_snan   - tbl_fsub_op # NORM - SNAN
                   15367:        short           tbl_fsub_op     - tbl_fsub_op #
                   15368:        short           tbl_fsub_op     - tbl_fsub_op #
                   15369:
                   15370:        short           fsub_zero_dst   - tbl_fsub_op # ZERO - NORM
                   15371:        short           fsub_zero_2     - tbl_fsub_op # ZERO - ZERO
                   15372:        short           fsub_inf_src    - tbl_fsub_op # ZERO - INF
                   15373:        short           fsub_res_qnan   - tbl_fsub_op # NORM - QNAN
                   15374:        short           fsub_zero_dst   - tbl_fsub_op # ZERO - DENORM
                   15375:        short           fsub_res_snan   - tbl_fsub_op # NORM - SNAN
                   15376:        short           tbl_fsub_op     - tbl_fsub_op #
                   15377:        short           tbl_fsub_op     - tbl_fsub_op #
                   15378:
                   15379:        short           fsub_inf_dst    - tbl_fsub_op # INF - NORM
                   15380:        short           fsub_inf_dst    - tbl_fsub_op # INF - ZERO
                   15381:        short           fsub_inf_2      - tbl_fsub_op # INF - INF
                   15382:        short           fsub_res_qnan   - tbl_fsub_op # NORM - QNAN
                   15383:        short           fsub_inf_dst    - tbl_fsub_op # INF - DENORM
                   15384:        short           fsub_res_snan   - tbl_fsub_op # NORM - SNAN
                   15385:        short           tbl_fsub_op     - tbl_fsub_op #
                   15386:        short           tbl_fsub_op     - tbl_fsub_op #
                   15387:
                   15388:        short           fsub_res_qnan   - tbl_fsub_op # QNAN - NORM
                   15389:        short           fsub_res_qnan   - tbl_fsub_op # QNAN - ZERO
                   15390:        short           fsub_res_qnan   - tbl_fsub_op # QNAN - INF
                   15391:        short           fsub_res_qnan   - tbl_fsub_op # QNAN - QNAN
                   15392:        short           fsub_res_qnan   - tbl_fsub_op # QNAN - DENORM
                   15393:        short           fsub_res_snan   - tbl_fsub_op # QNAN - SNAN
                   15394:        short           tbl_fsub_op     - tbl_fsub_op #
                   15395:        short           tbl_fsub_op     - tbl_fsub_op #
                   15396:
                   15397:        short           fsub_norm       - tbl_fsub_op # DENORM - NORM
                   15398:        short           fsub_zero_src   - tbl_fsub_op # DENORM - ZERO
                   15399:        short           fsub_inf_src    - tbl_fsub_op # DENORM - INF
                   15400:        short           fsub_res_qnan   - tbl_fsub_op # NORM - QNAN
                   15401:        short           fsub_norm       - tbl_fsub_op # DENORM - DENORM
                   15402:        short           fsub_res_snan   - tbl_fsub_op # NORM - SNAN
                   15403:        short           tbl_fsub_op     - tbl_fsub_op #
                   15404:        short           tbl_fsub_op     - tbl_fsub_op #
                   15405:
                   15406:        short           fsub_res_snan   - tbl_fsub_op # SNAN - NORM
                   15407:        short           fsub_res_snan   - tbl_fsub_op # SNAN - ZERO
                   15408:        short           fsub_res_snan   - tbl_fsub_op # SNAN - INF
                   15409:        short           fsub_res_snan   - tbl_fsub_op # SNAN - QNAN
                   15410:        short           fsub_res_snan   - tbl_fsub_op # SNAN - DENORM
                   15411:        short           fsub_res_snan   - tbl_fsub_op # SNAN - SNAN
                   15412:        short           tbl_fsub_op     - tbl_fsub_op #
                   15413:        short           tbl_fsub_op     - tbl_fsub_op #
                   15414:
                   15415: fsub_res_qnan:
                   15416:        bra.l           res_qnan
                   15417: fsub_res_snan:
                   15418:        bra.l           res_snan
                   15419:
                   15420: #
                   15421: # both operands are ZEROes
                   15422: #
                   15423: fsub_zero_2:
                   15424:        mov.b           SRC_EX(%a0),%d0
                   15425:        mov.b           DST_EX(%a1),%d1
                   15426:        eor.b           %d1,%d0
                   15427:        bpl.b           fsub_zero_2_chk_rm
                   15428:
                   15429: # the signs are opposite, so, return a ZERO w/ the sign of the dst ZERO
                   15430:        tst.b           %d0                     # is dst negative?
                   15431:        bmi.b           fsub_zero_2_rm          # yes
                   15432:        fmov.s          &0x00000000,%fp0        # no; return +ZERO
                   15433:        mov.b           &z_bmask,FPSR_CC(%a6)   # set Z
                   15434:        rts
                   15435:
                   15436: #
                   15437: # the ZEROes have the same signs:
                   15438: # - therefore, we return +ZERO if the rounding mode is RN,RZ, or RP
                   15439: # - -ZERO is returned in the case of RM.
                   15440: #
                   15441: fsub_zero_2_chk_rm:
                   15442:        mov.b           3+L_SCR3(%a6),%d1
                   15443:        andi.b          &0x30,%d1               # extract rnd mode
                   15444:        cmpi.b          %d1,&rm_mode*0x10       # is rnd mode = RM?
                   15445:        beq.b           fsub_zero_2_rm          # yes
                   15446:        fmov.s          &0x00000000,%fp0        # no; return +ZERO
                   15447:        mov.b           &z_bmask,FPSR_CC(%a6)   # set Z
                   15448:        rts
                   15449:
                   15450: fsub_zero_2_rm:
                   15451:        fmov.s          &0x80000000,%fp0        # return -ZERO
                   15452:        mov.b           &z_bmask+neg_bmask,FPSR_CC(%a6) # set Z/NEG
                   15453:        rts
                   15454:
                   15455: #
                   15456: # one operand is a ZERO and the other is a DENORM or a NORM.
                   15457: # scale the DENORM or NORM and jump to the regular fsub routine.
                   15458: #
                   15459: fsub_zero_dst:
                   15460:        mov.w           SRC_EX(%a0),FP_SCR0_EX(%a6)
                   15461:        mov.l           SRC_HI(%a0),FP_SCR0_HI(%a6)
                   15462:        mov.l           SRC_LO(%a0),FP_SCR0_LO(%a6)
                   15463:        bsr.l           scale_to_zero_src       # scale the operand
                   15464:        clr.w           FP_SCR1_EX(%a6)
                   15465:        clr.l           FP_SCR1_HI(%a6)
                   15466:        clr.l           FP_SCR1_LO(%a6)
                   15467:        bra.w           fsub_zero_entry         # go execute fsub
                   15468:
                   15469: fsub_zero_src:
                   15470:        mov.w           DST_EX(%a1),FP_SCR1_EX(%a6)
                   15471:        mov.l           DST_HI(%a1),FP_SCR1_HI(%a6)
                   15472:        mov.l           DST_LO(%a1),FP_SCR1_LO(%a6)
                   15473:        bsr.l           scale_to_zero_dst       # scale the operand
                   15474:        clr.w           FP_SCR0_EX(%a6)
                   15475:        clr.l           FP_SCR0_HI(%a6)
                   15476:        clr.l           FP_SCR0_LO(%a6)
                   15477:        bra.w           fsub_zero_entry         # go execute fsub
                   15478:
                   15479: #
                   15480: # both operands are INFs. an OPERR will result if the INFs have the
                   15481: # same signs. else,
                   15482: #
                   15483: fsub_inf_2:
                   15484:        mov.b           SRC_EX(%a0),%d0         # exclusive or the signs
                   15485:        mov.b           DST_EX(%a1),%d1
                   15486:        eor.b           %d1,%d0
                   15487:        bpl.l           res_operr               # weed out (-INF)+(+INF)
                   15488:
                   15489: # ok, so it's not an OPERR. but we do have to remember to return
                   15490: # the src INF since that's where the 881/882 gets the j-bit.
                   15491:
                   15492: fsub_inf_src:
                   15493:        fmovm.x         SRC(%a0),&0x80          # return src INF
                   15494:        fneg.x          %fp0                    # invert sign
                   15495:        fbge.w          fsub_inf_done           # sign is now positive
                   15496:        mov.b           &neg_bmask+inf_bmask,FPSR_CC(%a6) # set INF/NEG
                   15497:        rts
                   15498:
                   15499: fsub_inf_dst:
                   15500:        fmovm.x         DST(%a1),&0x80          # return dst INF
                   15501:        tst.b           DST_EX(%a1)             # is INF negative?
                   15502:        bpl.b           fsub_inf_done           # no
                   15503:        mov.b           &neg_bmask+inf_bmask,FPSR_CC(%a6) # set INF/NEG
                   15504:        rts
                   15505:
                   15506: fsub_inf_done:
                   15507:        mov.b           &inf_bmask,FPSR_CC(%a6) # set INF
                   15508:        rts
                   15509:
                   15510: #########################################################################
                   15511: # XDEF ****************************************************************        #
                   15512: #      fsqrt(): emulates the fsqrt instruction                         #
                   15513: #      fssqrt(): emulates the fssqrt instruction                       #
                   15514: #      fdsqrt(): emulates the fdsqrt instruction                       #
                   15515: #                                                                      #
                   15516: # XREF ****************************************************************        #
                   15517: #      scale_sqrt() - scale the source operand                         #
                   15518: #      unf_res() - return default underflow result                     #
                   15519: #      ovf_res() - return default overflow result                      #
                   15520: #      res_qnan_1op() - return QNAN result                             #
                   15521: #      res_snan_1op() - return SNAN result                             #
                   15522: #                                                                      #
                   15523: # INPUT ***************************************************************        #
                   15524: #      a0 = pointer to extended precision source operand               #
                   15525: #      d0  rnd prec,mode                                               #
                   15526: #                                                                      #
                   15527: # OUTPUT **************************************************************        #
                   15528: #      fp0 = result                                                    #
                   15529: #      fp1 = EXOP (if exception occurred)                              #
                   15530: #                                                                      #
                   15531: # ALGORITHM ***********************************************************        #
                   15532: #      Handle NANs, infinities, and zeroes as special cases. Divide    #
                   15533: # norms/denorms into ext/sgl/dbl precision.                            #
                   15534: #      For norms/denorms, scale the exponents such that a sqrt         #
                   15535: # instruction won't cause an exception. Use the regular fsqrt to       #
                   15536: # compute a result. Check if the regular operands would have taken     #
                   15537: # an exception. If so, return the default overflow/underflow result    #
                   15538: # and return the EXOP if exceptions are enabled. Else, scale the       #
                   15539: # result operand to the proper exponent.                               #
                   15540: #                                                                      #
                   15541: #########################################################################
                   15542:
                   15543:        global          fssqrt
                   15544: fssqrt:
                   15545:        andi.b          &0x30,%d0               # clear rnd prec
                   15546:        ori.b           &s_mode*0x10,%d0        # insert sgl precision
                   15547:        bra.b           fsqrt
                   15548:
                   15549:        global          fdsqrt
                   15550: fdsqrt:
                   15551:        andi.b          &0x30,%d0               # clear rnd prec
                   15552:        ori.b           &d_mode*0x10,%d0        # insert dbl precision
                   15553:
                   15554:        global          fsqrt
                   15555: fsqrt:
                   15556:        mov.l           %d0,L_SCR3(%a6)         # store rnd info
                   15557:        clr.w           %d1
                   15558:        mov.b           STAG(%a6),%d1
                   15559:        bne.w           fsqrt_not_norm          # optimize on non-norm input
                   15560:
                   15561: #
                   15562: # SQUARE ROOT: norms and denorms ONLY!
                   15563: #
                   15564: fsqrt_norm:
                   15565:        tst.b           SRC_EX(%a0)             # is operand negative?
                   15566:        bmi.l           res_operr               # yes
                   15567:
                   15568:        andi.b          &0xc0,%d0               # is precision extended?
                   15569:        bne.b           fsqrt_not_ext           # no; go handle sgl or dbl
                   15570:
                   15571:        fmov.l          L_SCR3(%a6),%fpcr       # set FPCR
                   15572:        fmov.l          &0x0,%fpsr              # clear FPSR
                   15573:
                   15574:        fsqrt.x         (%a0),%fp0              # execute square root
                   15575:
                   15576:        fmov.l          %fpsr,%d1
                   15577:        or.l            %d1,USER_FPSR(%a6)      # set N,INEX
                   15578:
                   15579:        rts
                   15580:
                   15581: fsqrt_denorm:
                   15582:        tst.b           SRC_EX(%a0)             # is operand negative?
                   15583:        bmi.l           res_operr               # yes
                   15584:
                   15585:        andi.b          &0xc0,%d0               # is precision extended?
                   15586:        bne.b           fsqrt_not_ext           # no; go handle sgl or dbl
                   15587:
                   15588:        mov.w           SRC_EX(%a0),FP_SCR0_EX(%a6)
                   15589:        mov.l           SRC_HI(%a0),FP_SCR0_HI(%a6)
                   15590:        mov.l           SRC_LO(%a0),FP_SCR0_LO(%a6)
                   15591:
                   15592:        bsr.l           scale_sqrt              # calculate scale factor
                   15593:
                   15594:        bra.w           fsqrt_sd_normal
                   15595:
                   15596: #
                   15597: # operand is either single or double
                   15598: #
                   15599: fsqrt_not_ext:
                   15600:        cmpi.b          %d0,&s_mode*0x10        # separate sgl/dbl prec
                   15601:        bne.w           fsqrt_dbl
                   15602:
                   15603: #
                   15604: # operand is to be rounded to single precision
                   15605: #
                   15606: fsqrt_sgl:
                   15607:        mov.w           SRC_EX(%a0),FP_SCR0_EX(%a6)
                   15608:        mov.l           SRC_HI(%a0),FP_SCR0_HI(%a6)
                   15609:        mov.l           SRC_LO(%a0),FP_SCR0_LO(%a6)
                   15610:
                   15611:        bsr.l           scale_sqrt              # calculate scale factor
                   15612:
                   15613:        cmpi.l          %d0,&0x3fff-0x3f81      # will move in underflow?
                   15614:        beq.w           fsqrt_sd_may_unfl
                   15615:        bgt.w           fsqrt_sd_unfl           # yes; go handle underflow
                   15616:        cmpi.l          %d0,&0x3fff-0x407f      # will move in overflow?
                   15617:        beq.w           fsqrt_sd_may_ovfl       # maybe; go check
                   15618:        blt.w           fsqrt_sd_ovfl           # yes; go handle overflow
                   15619:
                   15620: #
                   15621: # operand will NOT overflow or underflow when moved in to the fp reg file
                   15622: #
                   15623: fsqrt_sd_normal:
                   15624:        fmov.l          &0x0,%fpsr              # clear FPSR
                   15625:        fmov.l          L_SCR3(%a6),%fpcr       # set FPCR
                   15626:
                   15627:        fsqrt.x         FP_SCR0(%a6),%fp0       # perform absolute
                   15628:
                   15629:        fmov.l          %fpsr,%d1               # save FPSR
                   15630:        fmov.l          &0x0,%fpcr              # clear FPCR
                   15631:
                   15632:        or.l            %d1,USER_FPSR(%a6)      # save INEX2,N
                   15633:
                   15634: fsqrt_sd_normal_exit:
                   15635:        mov.l           %d2,-(%sp)              # save d2
                   15636:        fmovm.x         &0x80,FP_SCR0(%a6)      # store out result
                   15637:        mov.w           FP_SCR0_EX(%a6),%d1     # load sgn,exp
                   15638:        mov.l           %d1,%d2                 # make a copy
                   15639:        andi.l          &0x7fff,%d1             # strip sign
                   15640:        sub.l           %d0,%d1                 # add scale factor
                   15641:        andi.w          &0x8000,%d2             # keep old sign
                   15642:        or.w            %d1,%d2                 # concat old sign,new exp
                   15643:        mov.w           %d2,FP_SCR0_EX(%a6)     # insert new exponent
                   15644:        mov.l           (%sp)+,%d2              # restore d2
                   15645:        fmovm.x         FP_SCR0(%a6),&0x80      # return result in fp0
                   15646:        rts
                   15647:
                   15648: #
                   15649: # operand is to be rounded to double precision
                   15650: #
                   15651: fsqrt_dbl:
                   15652:        mov.w           SRC_EX(%a0),FP_SCR0_EX(%a6)
                   15653:        mov.l           SRC_HI(%a0),FP_SCR0_HI(%a6)
                   15654:        mov.l           SRC_LO(%a0),FP_SCR0_LO(%a6)
                   15655:
                   15656:        bsr.l           scale_sqrt              # calculate scale factor
                   15657:
                   15658:        cmpi.l          %d0,&0x3fff-0x3c01      # will move in underflow?
                   15659:        beq.w           fsqrt_sd_may_unfl
                   15660:        bgt.b           fsqrt_sd_unfl           # yes; go handle underflow
                   15661:        cmpi.l          %d0,&0x3fff-0x43ff      # will move in overflow?
                   15662:        beq.w           fsqrt_sd_may_ovfl       # maybe; go check
                   15663:        blt.w           fsqrt_sd_ovfl           # yes; go handle overflow
                   15664:        bra.w           fsqrt_sd_normal         # no; ho handle normalized op
                   15665:
                   15666: # we're on the line here and the distinguishing characteristic is whether
                   15667: # the exponent is 3fff or 3ffe. if it's 3ffe, then it's a safe number
                   15668: # elsewise fall through to underflow.
                   15669: fsqrt_sd_may_unfl:
                   15670:        btst            &0x0,1+FP_SCR0_EX(%a6)  # is exponent 0x3fff?
                   15671:        bne.w           fsqrt_sd_normal         # yes, so no underflow
                   15672:
                   15673: #
                   15674: # operand WILL underflow when moved in to the fp register file
                   15675: #
                   15676: fsqrt_sd_unfl:
                   15677:        bset            &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
                   15678:
                   15679:        fmov.l          &rz_mode*0x10,%fpcr     # set FPCR
                   15680:        fmov.l          &0x0,%fpsr              # clear FPSR
                   15681:
                   15682:        fsqrt.x         FP_SCR0(%a6),%fp0       # execute square root
                   15683:
                   15684:        fmov.l          %fpsr,%d1               # save status
                   15685:        fmov.l          &0x0,%fpcr              # clear FPCR
                   15686:
                   15687:        or.l            %d1,USER_FPSR(%a6)      # save INEX2,N
                   15688:
                   15689: # if underflow or inexact is enabled, go calculate EXOP first.
                   15690:        mov.b           FPCR_ENABLE(%a6),%d1
                   15691:        andi.b          &0x0b,%d1               # is UNFL or INEX enabled?
                   15692:        bne.b           fsqrt_sd_unfl_ena       # yes
                   15693:
                   15694: fsqrt_sd_unfl_dis:
                   15695:        fmovm.x         &0x80,FP_SCR0(%a6)      # store out result
                   15696:
                   15697:        lea             FP_SCR0(%a6),%a0        # pass: result addr
                   15698:        mov.l           L_SCR3(%a6),%d1         # pass: rnd prec,mode
                   15699:        bsr.l           unf_res                 # calculate default result
                   15700:        or.b            %d0,FPSR_CC(%a6)        # set possible 'Z' ccode
                   15701:        fmovm.x         FP_SCR0(%a6),&0x80      # return default result in fp0
                   15702:        rts
                   15703:
                   15704: #
                   15705: # operand will underflow AND underflow is enabled.
                   15706: # therefore, we must return the result rounded to extended precision.
                   15707: #
                   15708: fsqrt_sd_unfl_ena:
                   15709:        mov.l           FP_SCR0_HI(%a6),FP_SCR1_HI(%a6)
                   15710:        mov.l           FP_SCR0_LO(%a6),FP_SCR1_LO(%a6)
                   15711:        mov.w           FP_SCR0_EX(%a6),%d1     # load current exponent
                   15712:
                   15713:        mov.l           %d2,-(%sp)              # save d2
                   15714:        mov.l           %d1,%d2                 # make a copy
                   15715:        andi.l          &0x7fff,%d1             # strip sign
                   15716:        andi.w          &0x8000,%d2             # keep old sign
                   15717:        sub.l           %d0,%d1                 # subtract scale factor
                   15718:        addi.l          &0x6000,%d1             # add new bias
                   15719:        andi.w          &0x7fff,%d1
                   15720:        or.w            %d2,%d1                 # concat new sign,new exp
                   15721:        mov.w           %d1,FP_SCR1_EX(%a6)     # insert new exp
                   15722:        fmovm.x         FP_SCR1(%a6),&0x40      # return EXOP in fp1
                   15723:        mov.l           (%sp)+,%d2              # restore d2
                   15724:        bra.b           fsqrt_sd_unfl_dis
                   15725:
                   15726: #
                   15727: # operand WILL overflow.
                   15728: #
                   15729: fsqrt_sd_ovfl:
                   15730:        fmov.l          &0x0,%fpsr              # clear FPSR
                   15731:        fmov.l          L_SCR3(%a6),%fpcr       # set FPCR
                   15732:
                   15733:        fsqrt.x         FP_SCR0(%a6),%fp0       # perform square root
                   15734:
                   15735:        fmov.l          &0x0,%fpcr              # clear FPCR
                   15736:        fmov.l          %fpsr,%d1               # save FPSR
                   15737:
                   15738:        or.l            %d1,USER_FPSR(%a6)      # save INEX2,N
                   15739:
                   15740: fsqrt_sd_ovfl_tst:
                   15741:        or.l            &ovfl_inx_mask,USER_FPSR(%a6) # set ovfl/aovfl/ainex
                   15742:
                   15743:        mov.b           FPCR_ENABLE(%a6),%d1
                   15744:        andi.b          &0x13,%d1               # is OVFL or INEX enabled?
                   15745:        bne.b           fsqrt_sd_ovfl_ena       # yes
                   15746:
                   15747: #
                   15748: # OVFL is not enabled; therefore, we must create the default result by
                   15749: # calling ovf_res().
                   15750: #
                   15751: fsqrt_sd_ovfl_dis:
                   15752:        btst            &neg_bit,FPSR_CC(%a6)   # is result negative?
                   15753:        sne             %d1                     # set sign param accordingly
                   15754:        mov.l           L_SCR3(%a6),%d0         # pass: prec,mode
                   15755:        bsr.l           ovf_res                 # calculate default result
                   15756:        or.b            %d0,FPSR_CC(%a6)        # set INF,N if applicable
                   15757:        fmovm.x         (%a0),&0x80             # return default result in fp0
                   15758:        rts
                   15759:
                   15760: #
                   15761: # OVFL is enabled.
                   15762: # the INEX2 bit has already been updated by the round to the correct precision.
                   15763: # now, round to extended(and don't alter the FPSR).
                   15764: #
                   15765: fsqrt_sd_ovfl_ena:
                   15766:        mov.l           %d2,-(%sp)              # save d2
                   15767:        mov.w           FP_SCR0_EX(%a6),%d1     # fetch {sgn,exp}
                   15768:        mov.l           %d1,%d2                 # make a copy
                   15769:        andi.l          &0x7fff,%d1             # strip sign
                   15770:        andi.w          &0x8000,%d2             # keep old sign
                   15771:        sub.l           %d0,%d1                 # add scale factor
                   15772:        subi.l          &0x6000,%d1             # subtract bias
                   15773:        andi.w          &0x7fff,%d1
                   15774:        or.w            %d2,%d1                 # concat sign,exp
                   15775:        mov.w           %d1,FP_SCR0_EX(%a6)     # insert new exponent
                   15776:        fmovm.x         FP_SCR0(%a6),&0x40      # return EXOP in fp1
                   15777:        mov.l           (%sp)+,%d2              # restore d2
                   15778:        bra.b           fsqrt_sd_ovfl_dis
                   15779:
                   15780: #
                   15781: # the move in MAY underflow. so...
                   15782: #
                   15783: fsqrt_sd_may_ovfl:
                   15784:        btst            &0x0,1+FP_SCR0_EX(%a6)  # is exponent 0x3fff?
                   15785:        bne.w           fsqrt_sd_ovfl           # yes, so overflow
                   15786:
                   15787:        fmov.l          &0x0,%fpsr              # clear FPSR
                   15788:        fmov.l          L_SCR3(%a6),%fpcr       # set FPCR
                   15789:
                   15790:        fsqrt.x         FP_SCR0(%a6),%fp0       # perform absolute
                   15791:
                   15792:        fmov.l          %fpsr,%d1               # save status
                   15793:        fmov.l          &0x0,%fpcr              # clear FPCR
                   15794:
                   15795:        or.l            %d1,USER_FPSR(%a6)      # save INEX2,N
                   15796:
                   15797:        fmov.x          %fp0,%fp1               # make a copy of result
                   15798:        fcmp.b          %fp1,&0x1               # is |result| >= 1.b?
                   15799:        fbge.w          fsqrt_sd_ovfl_tst       # yes; overflow has occurred
                   15800:
                   15801: # no, it didn't overflow; we have correct result
                   15802:        bra.w           fsqrt_sd_normal_exit
                   15803:
                   15804: ##########################################################################
                   15805:
                   15806: #
                   15807: # input is not normalized; what is it?
                   15808: #
                   15809: fsqrt_not_norm:
                   15810:        cmpi.b          %d1,&DENORM             # weed out DENORM
                   15811:        beq.w           fsqrt_denorm
                   15812:        cmpi.b          %d1,&ZERO               # weed out ZERO
                   15813:        beq.b           fsqrt_zero
                   15814:        cmpi.b          %d1,&INF                # weed out INF
                   15815:        beq.b           fsqrt_inf
                   15816:        cmpi.b          %d1,&SNAN               # weed out SNAN
                   15817:        beq.l           res_snan_1op
                   15818:        bra.l           res_qnan_1op
                   15819:
                   15820: #
                   15821: #      fsqrt(+0) = +0
                   15822: #      fsqrt(-0) = -0
                   15823: #      fsqrt(+INF) = +INF
                   15824: #      fsqrt(-INF) = OPERR
                   15825: #
                   15826: fsqrt_zero:
                   15827:        tst.b           SRC_EX(%a0)             # is ZERO positive or negative?
                   15828:        bmi.b           fsqrt_zero_m            # negative
                   15829: fsqrt_zero_p:
                   15830:        fmov.s          &0x00000000,%fp0        # return +ZERO
                   15831:        mov.b           &z_bmask,FPSR_CC(%a6)   # set 'Z' ccode bit
                   15832:        rts
                   15833: fsqrt_zero_m:
                   15834:        fmov.s          &0x80000000,%fp0        # return -ZERO
                   15835:        mov.b           &z_bmask+neg_bmask,FPSR_CC(%a6) # set 'Z','N' ccode bits
                   15836:        rts
                   15837:
                   15838: fsqrt_inf:
                   15839:        tst.b           SRC_EX(%a0)             # is INF positive or negative?
                   15840:        bmi.l           res_operr               # negative
                   15841: fsqrt_inf_p:
                   15842:        fmovm.x         SRC(%a0),&0x80          # return +INF in fp0
                   15843:        mov.b           &inf_bmask,FPSR_CC(%a6) # set 'I' ccode bit
                   15844:        rts
                   15845:
                   15846: ##########################################################################
                   15847:
                   15848: #########################################################################
                   15849: # XDEF ****************************************************************        #
                   15850: #      addsub_scaler2(): scale inputs to fadd/fsub such that no        #
                   15851: #                        OVFL/UNFL exceptions will result              #
                   15852: #                                                                      #
                   15853: # XREF ****************************************************************        #
                   15854: #      norm() - normalize mantissa after adjusting exponent            #
                   15855: #                                                                      #
                   15856: # INPUT ***************************************************************        #
                   15857: #      FP_SRC(a6) = fp op1(src)                                        #
                   15858: #      FP_DST(a6) = fp op2(dst)                                        #
                   15859: #                                                                      #
                   15860: # OUTPUT **************************************************************        #
                   15861: #      FP_SRC(a6) = fp op1 scaled(src)                                 #
                   15862: #      FP_DST(a6) = fp op2 scaled(dst)                                 #
                   15863: #      d0         = scale amount                                       #
                   15864: #                                                                      #
                   15865: # ALGORITHM ***********************************************************        #
                   15866: #      If the DST exponent is > the SRC exponent, set the DST exponent #
                   15867: # equal to 0x3fff and scale the SRC exponent by the value that the     #
                   15868: # DST exponent was scaled by. If the SRC exponent is greater or equal, #
                   15869: # do the opposite. Return this scale factor in d0.                     #
                   15870: #      If the two exponents differ by > the number of mantissa bits    #
                   15871: # plus two, then set the smallest exponent to a very small value as a  #
                   15872: # quick shortcut.                                                      #
                   15873: #                                                                      #
                   15874: #########################################################################
                   15875:
                   15876:        global          addsub_scaler2
                   15877: addsub_scaler2:
                   15878:        mov.l           SRC_HI(%a0),FP_SCR0_HI(%a6)
                   15879:        mov.l           DST_HI(%a1),FP_SCR1_HI(%a6)
                   15880:        mov.l           SRC_LO(%a0),FP_SCR0_LO(%a6)
                   15881:        mov.l           DST_LO(%a1),FP_SCR1_LO(%a6)
                   15882:        mov.w           SRC_EX(%a0),%d0
                   15883:        mov.w           DST_EX(%a1),%d1
                   15884:        mov.w           %d0,FP_SCR0_EX(%a6)
                   15885:        mov.w           %d1,FP_SCR1_EX(%a6)
                   15886:
                   15887:        andi.w          &0x7fff,%d0
                   15888:        andi.w          &0x7fff,%d1
                   15889:        mov.w           %d0,L_SCR1(%a6)         # store src exponent
                   15890:        mov.w           %d1,2+L_SCR1(%a6)       # store dst exponent
                   15891:
                   15892:        cmp.w           %d0, %d1                # is src exp >= dst exp?
                   15893:        bge.l           src_exp_ge2
                   15894:
                   15895: # dst exp is >  src exp; scale dst to exp = 0x3fff
                   15896: dst_exp_gt2:
                   15897:        bsr.l           scale_to_zero_dst
                   15898:        mov.l           %d0,-(%sp)              # save scale factor
                   15899:
                   15900:        cmpi.b          STAG(%a6),&DENORM       # is dst denormalized?
                   15901:        bne.b           cmpexp12
                   15902:
                   15903:        lea             FP_SCR0(%a6),%a0
                   15904:        bsr.l           norm                    # normalize the denorm; result is new exp
                   15905:        neg.w           %d0                     # new exp = -(shft val)
                   15906:        mov.w           %d0,L_SCR1(%a6)         # inset new exp
                   15907:
                   15908: cmpexp12:
                   15909:        mov.w           2+L_SCR1(%a6),%d0
                   15910:        subi.w          &mantissalen+2,%d0      # subtract mantissalen+2 from larger exp
                   15911:
                   15912:        cmp.w           %d0,L_SCR1(%a6)         # is difference >= len(mantissa)+2?
                   15913:        bge.b           quick_scale12
                   15914:
                   15915:        mov.w           L_SCR1(%a6),%d0
                   15916:        add.w           0x2(%sp),%d0            # scale src exponent by scale factor
                   15917:        mov.w           FP_SCR0_EX(%a6),%d1
                   15918:        and.w           &0x8000,%d1
                   15919:        or.w            %d1,%d0                 # concat {sgn,new exp}
                   15920:        mov.w           %d0,FP_SCR0_EX(%a6)     # insert new dst exponent
                   15921:
                   15922:        mov.l           (%sp)+,%d0              # return SCALE factor
                   15923:        rts
                   15924:
                   15925: quick_scale12:
                   15926:        andi.w          &0x8000,FP_SCR0_EX(%a6) # zero src exponent
                   15927:        bset            &0x0,1+FP_SCR0_EX(%a6)  # set exp = 1
                   15928:
                   15929:        mov.l           (%sp)+,%d0              # return SCALE factor
                   15930:        rts
                   15931:
                   15932: # src exp is >= dst exp; scale src to exp = 0x3fff
                   15933: src_exp_ge2:
                   15934:        bsr.l           scale_to_zero_src
                   15935:        mov.l           %d0,-(%sp)              # save scale factor
                   15936:
                   15937:        cmpi.b          DTAG(%a6),&DENORM       # is dst denormalized?
                   15938:        bne.b           cmpexp22
                   15939:        lea             FP_SCR1(%a6),%a0
                   15940:        bsr.l           norm                    # normalize the denorm; result is new exp
                   15941:        neg.w           %d0                     # new exp = -(shft val)
                   15942:        mov.w           %d0,2+L_SCR1(%a6)       # inset new exp
                   15943:
                   15944: cmpexp22:
                   15945:        mov.w           L_SCR1(%a6),%d0
                   15946:        subi.w          &mantissalen+2,%d0      # subtract mantissalen+2 from larger exp
                   15947:
                   15948:        cmp.w           %d0,2+L_SCR1(%a6)       # is difference >= len(mantissa)+2?
                   15949:        bge.b           quick_scale22
                   15950:
                   15951:        mov.w           2+L_SCR1(%a6),%d0
                   15952:        add.w           0x2(%sp),%d0            # scale dst exponent by scale factor
                   15953:        mov.w           FP_SCR1_EX(%a6),%d1
                   15954:        andi.w          &0x8000,%d1
                   15955:        or.w            %d1,%d0                 # concat {sgn,new exp}
                   15956:        mov.w           %d0,FP_SCR1_EX(%a6)     # insert new dst exponent
                   15957:
                   15958:        mov.l           (%sp)+,%d0              # return SCALE factor
                   15959:        rts
                   15960:
                   15961: quick_scale22:
                   15962:        andi.w          &0x8000,FP_SCR1_EX(%a6) # zero dst exponent
                   15963:        bset            &0x0,1+FP_SCR1_EX(%a6)  # set exp = 1
                   15964:
                   15965:        mov.l           (%sp)+,%d0              # return SCALE factor
                   15966:        rts
                   15967:
                   15968: ##########################################################################
                   15969:
                   15970: #########################################################################
                   15971: # XDEF ****************************************************************        #
                   15972: #      scale_to_zero_src(): scale the exponent of extended precision   #
                   15973: #                           value at FP_SCR0(a6).                      #
                   15974: #                                                                      #
                   15975: # XREF ****************************************************************        #
                   15976: #      norm() - normalize the mantissa if the operand was a DENORM     #
                   15977: #                                                                      #
                   15978: # INPUT ***************************************************************        #
                   15979: #      FP_SCR0(a6) = extended precision operand to be scaled           #
                   15980: #                                                                      #
                   15981: # OUTPUT **************************************************************        #
                   15982: #      FP_SCR0(a6) = scaled extended precision operand                 #
                   15983: #      d0          = scale value                                       #
                   15984: #                                                                      #
                   15985: # ALGORITHM ***********************************************************        #
                   15986: #      Set the exponent of the input operand to 0x3fff. Save the value #
                   15987: # of the difference between the original and new exponent. Then,       #
                   15988: # normalize the operand if it was a DENORM. Add this normalization     #
                   15989: # value to the previous value. Return the result.                      #
                   15990: #                                                                      #
                   15991: #########################################################################
                   15992:
                   15993:        global          scale_to_zero_src
                   15994: scale_to_zero_src:
                   15995:        mov.w           FP_SCR0_EX(%a6),%d1     # extract operand's {sgn,exp}
                   15996:        mov.w           %d1,%d0                 # make a copy
                   15997:
                   15998:        andi.l          &0x7fff,%d1             # extract operand's exponent
                   15999:
                   16000:        andi.w          &0x8000,%d0             # extract operand's sgn
                   16001:        or.w            &0x3fff,%d0             # insert new operand's exponent(=0)
                   16002:
                   16003:        mov.w           %d0,FP_SCR0_EX(%a6)     # insert biased exponent
                   16004:
                   16005:        cmpi.b          STAG(%a6),&DENORM       # is operand normalized?
                   16006:        beq.b           stzs_denorm             # normalize the DENORM
                   16007:
                   16008: stzs_norm:
                   16009:        mov.l           &0x3fff,%d0
                   16010:        sub.l           %d1,%d0                 # scale = BIAS + (-exp)
                   16011:
                   16012:        rts
                   16013:
                   16014: stzs_denorm:
                   16015:        lea             FP_SCR0(%a6),%a0        # pass ptr to src op
                   16016:        bsr.l           norm                    # normalize denorm
                   16017:        neg.l           %d0                     # new exponent = -(shft val)
                   16018:        mov.l           %d0,%d1                 # prepare for op_norm call
                   16019:        bra.b           stzs_norm               # finish scaling
                   16020:
                   16021: ###
                   16022:
                   16023: #########################################################################
                   16024: # XDEF ****************************************************************        #
                   16025: #      scale_sqrt(): scale the input operand exponent so a subsequent  #
                   16026: #                    fsqrt operation won't take an exception.          #
                   16027: #                                                                      #
                   16028: # XREF ****************************************************************        #
                   16029: #      norm() - normalize the mantissa if the operand was a DENORM     #
                   16030: #                                                                      #
                   16031: # INPUT ***************************************************************        #
                   16032: #      FP_SCR0(a6) = extended precision operand to be scaled           #
                   16033: #                                                                      #
                   16034: # OUTPUT **************************************************************        #
                   16035: #      FP_SCR0(a6) = scaled extended precision operand                 #
                   16036: #      d0          = scale value                                       #
                   16037: #                                                                      #
                   16038: # ALGORITHM ***********************************************************        #
                   16039: #      If the input operand is a DENORM, normalize it.                 #
                   16040: #      If the exponent of the input operand is even, set the exponent  #
                   16041: # to 0x3ffe and return a scale factor of "(exp-0x3ffe)/2". If the      #
                   16042: # exponent of the input operand is off, set the exponent to ox3fff and #
                   16043: # return a scale factor of "(exp-0x3fff)/2".                           #
                   16044: #                                                                      #
                   16045: #########################################################################
                   16046:
                   16047:        global          scale_sqrt
                   16048: scale_sqrt:
                   16049:        cmpi.b          STAG(%a6),&DENORM       # is operand normalized?
                   16050:        beq.b           ss_denorm               # normalize the DENORM
                   16051:
                   16052:        mov.w           FP_SCR0_EX(%a6),%d1     # extract operand's {sgn,exp}
                   16053:        andi.l          &0x7fff,%d1             # extract operand's exponent
                   16054:
                   16055:        andi.w          &0x8000,FP_SCR0_EX(%a6) # extract operand's sgn
                   16056:
                   16057:        btst            &0x0,%d1                # is exp even or odd?
                   16058:        beq.b           ss_norm_even
                   16059:
                   16060:        ori.w           &0x3fff,FP_SCR0_EX(%a6) # insert new operand's exponent(=0)
                   16061:
                   16062:        mov.l           &0x3fff,%d0
                   16063:        sub.l           %d1,%d0                 # scale = BIAS + (-exp)
                   16064:        asr.l           &0x1,%d0                # divide scale factor by 2
                   16065:        rts
                   16066:
                   16067: ss_norm_even:
                   16068:        ori.w           &0x3ffe,FP_SCR0_EX(%a6) # insert new operand's exponent(=0)
                   16069:
                   16070:        mov.l           &0x3ffe,%d0
                   16071:        sub.l           %d1,%d0                 # scale = BIAS + (-exp)
                   16072:        asr.l           &0x1,%d0                # divide scale factor by 2
                   16073:        rts
                   16074:
                   16075: ss_denorm:
                   16076:        lea             FP_SCR0(%a6),%a0        # pass ptr to src op
                   16077:        bsr.l           norm                    # normalize denorm
                   16078:
                   16079:        btst            &0x0,%d0                # is exp even or odd?
                   16080:        beq.b           ss_denorm_even
                   16081:
                   16082:        ori.w           &0x3fff,FP_SCR0_EX(%a6) # insert new operand's exponent(=0)
                   16083:
                   16084:        add.l           &0x3fff,%d0
                   16085:        asr.l           &0x1,%d0                # divide scale factor by 2
                   16086:        rts
                   16087:
                   16088: ss_denorm_even:
                   16089:        ori.w           &0x3ffe,FP_SCR0_EX(%a6) # insert new operand's exponent(=0)
                   16090:
                   16091:        add.l           &0x3ffe,%d0
                   16092:        asr.l           &0x1,%d0                # divide scale factor by 2
                   16093:        rts
                   16094:
                   16095: ###
                   16096:
                   16097: #########################################################################
                   16098: # XDEF ****************************************************************        #
                   16099: #      scale_to_zero_dst(): scale the exponent of extended precision   #
                   16100: #                           value at FP_SCR1(a6).                      #
                   16101: #                                                                      #
                   16102: # XREF ****************************************************************        #
                   16103: #      norm() - normalize the mantissa if the operand was a DENORM     #
                   16104: #                                                                      #
                   16105: # INPUT ***************************************************************        #
                   16106: #      FP_SCR1(a6) = extended precision operand to be scaled           #
                   16107: #                                                                      #
                   16108: # OUTPUT **************************************************************        #
                   16109: #      FP_SCR1(a6) = scaled extended precision operand                 #
                   16110: #      d0          = scale value                                       #
                   16111: #                                                                      #
                   16112: # ALGORITHM ***********************************************************        #
                   16113: #      Set the exponent of the input operand to 0x3fff. Save the value #
                   16114: # of the difference between the original and new exponent. Then,       #
                   16115: # normalize the operand if it was a DENORM. Add this normalization     #
                   16116: # value to the previous value. Return the result.                      #
                   16117: #                                                                      #
                   16118: #########################################################################
                   16119:
                   16120:        global          scale_to_zero_dst
                   16121: scale_to_zero_dst:
                   16122:        mov.w           FP_SCR1_EX(%a6),%d1     # extract operand's {sgn,exp}
                   16123:        mov.w           %d1,%d0                 # make a copy
                   16124:
                   16125:        andi.l          &0x7fff,%d1             # extract operand's exponent
                   16126:
                   16127:        andi.w          &0x8000,%d0             # extract operand's sgn
                   16128:        or.w            &0x3fff,%d0             # insert new operand's exponent(=0)
                   16129:
                   16130:        mov.w           %d0,FP_SCR1_EX(%a6)     # insert biased exponent
                   16131:
                   16132:        cmpi.b          DTAG(%a6),&DENORM       # is operand normalized?
                   16133:        beq.b           stzd_denorm             # normalize the DENORM
                   16134:
                   16135: stzd_norm:
                   16136:        mov.l           &0x3fff,%d0
                   16137:        sub.l           %d1,%d0                 # scale = BIAS + (-exp)
                   16138:        rts
                   16139:
                   16140: stzd_denorm:
                   16141:        lea             FP_SCR1(%a6),%a0        # pass ptr to dst op
                   16142:        bsr.l           norm                    # normalize denorm
                   16143:        neg.l           %d0                     # new exponent = -(shft val)
                   16144:        mov.l           %d0,%d1                 # prepare for op_norm call
                   16145:        bra.b           stzd_norm               # finish scaling
                   16146:
                   16147: ##########################################################################
                   16148:
                   16149: #########################################################################
                   16150: # XDEF ****************************************************************        #
                   16151: #      res_qnan(): return default result w/ QNAN operand for dyadic    #
                   16152: #      res_snan(): return default result w/ SNAN operand for dyadic    #
                   16153: #      res_qnan_1op(): return dflt result w/ QNAN operand for monadic  #
                   16154: #      res_snan_1op(): return dflt result w/ SNAN operand for monadic  #
                   16155: #                                                                      #
                   16156: # XREF ****************************************************************        #
                   16157: #      None                                                            #
                   16158: #                                                                      #
                   16159: # INPUT ***************************************************************        #
                   16160: #      FP_SRC(a6) = pointer to extended precision src operand          #
                   16161: #      FP_DST(a6) = pointer to extended precision dst operand          #
                   16162: #                                                                      #
                   16163: # OUTPUT **************************************************************        #
                   16164: #      fp0 = default result                                            #
                   16165: #                                                                      #
                   16166: # ALGORITHM ***********************************************************        #
                   16167: #      If either operand (but not both operands) of an operation is a  #
                   16168: # nonsignalling NAN, then that NAN is returned as the result. If both  #
                   16169: # operands are nonsignalling NANs, then the destination operand        #
                   16170: # nonsignalling NAN is returned as the result.                         #
                   16171: #      If either operand to an operation is a signalling NAN (SNAN),   #
                   16172: # then, the SNAN bit is set in the FPSR EXC byte. If the SNAN trap     #
                   16173: # enable bit is set in the FPCR, then the trap is taken and the        #
                   16174: # destination is not modified. If the SNAN trap enable bit is not set, #
                   16175: # then the SNAN is converted to a nonsignalling NAN (by setting the    #
                   16176: # SNAN bit in the operand to one), and the operation continues as      #
                   16177: # described in the preceding paragraph, for nonsignalling NANs.                #
                   16178: #      Make sure the appropriate FPSR bits are set before exiting.     #
                   16179: #                                                                      #
                   16180: #########################################################################
                   16181:
                   16182:        global          res_qnan
                   16183:        global          res_snan
                   16184: res_qnan:
                   16185: res_snan:
                   16186:        cmp.b           DTAG(%a6), &SNAN        # is the dst an SNAN?
                   16187:        beq.b           dst_snan2
                   16188:        cmp.b           DTAG(%a6), &QNAN        # is the dst a  QNAN?
                   16189:        beq.b           dst_qnan2
                   16190: src_nan:
                   16191:        cmp.b           STAG(%a6), &QNAN
                   16192:        beq.b           src_qnan2
                   16193:        global          res_snan_1op
                   16194: res_snan_1op:
                   16195: src_snan2:
                   16196:        bset            &0x6, FP_SRC_HI(%a6)    # set SNAN bit
                   16197:        or.l            &nan_mask+aiop_mask+snan_mask, USER_FPSR(%a6)
                   16198:        lea             FP_SRC(%a6), %a0
                   16199:        bra.b           nan_comp
                   16200:        global          res_qnan_1op
                   16201: res_qnan_1op:
                   16202: src_qnan2:
                   16203:        or.l            &nan_mask, USER_FPSR(%a6)
                   16204:        lea             FP_SRC(%a6), %a0
                   16205:        bra.b           nan_comp
                   16206: dst_snan2:
                   16207:        or.l            &nan_mask+aiop_mask+snan_mask, USER_FPSR(%a6)
                   16208:        bset            &0x6, FP_DST_HI(%a6)    # set SNAN bit
                   16209:        lea             FP_DST(%a6), %a0
                   16210:        bra.b           nan_comp
                   16211: dst_qnan2:
                   16212:        lea             FP_DST(%a6), %a0
                   16213:        cmp.b           STAG(%a6), &SNAN
                   16214:        bne             nan_done
                   16215:        or.l            &aiop_mask+snan_mask, USER_FPSR(%a6)
                   16216: nan_done:
                   16217:        or.l            &nan_mask, USER_FPSR(%a6)
                   16218: nan_comp:
                   16219:        btst            &0x7, FTEMP_EX(%a0)     # is NAN neg?
                   16220:        beq.b           nan_not_neg
                   16221:        or.l            &neg_mask, USER_FPSR(%a6)
                   16222: nan_not_neg:
                   16223:        fmovm.x         (%a0), &0x80
                   16224:        rts
                   16225:
                   16226: #########################################################################
                   16227: # XDEF ****************************************************************        #
                   16228: #      res_operr(): return default result during operand error         #
                   16229: #                                                                      #
                   16230: # XREF ****************************************************************        #
                   16231: #      None                                                            #
                   16232: #                                                                      #
                   16233: # INPUT ***************************************************************        #
                   16234: #      None                                                            #
                   16235: #                                                                      #
                   16236: # OUTPUT **************************************************************        #
                   16237: #      fp0 = default operand error result                              #
                   16238: #                                                                      #
                   16239: # ALGORITHM ***********************************************************        #
                   16240: #      An nonsignalling NAN is returned as the default result when     #
                   16241: # an operand error occurs for the following cases:                     #
                   16242: #                                                                      #
                   16243: #      Multiply: (Infinity x Zero)                                     #
                   16244: #      Divide  : (Zero / Zero) || (Infinity / Infinity)                #
                   16245: #                                                                      #
                   16246: #########################################################################
                   16247:
                   16248:        global          res_operr
                   16249: res_operr:
                   16250:        or.l            &nan_mask+operr_mask+aiop_mask, USER_FPSR(%a6)
                   16251:        fmovm.x         nan_return(%pc), &0x80
                   16252:        rts
                   16253:
                   16254: nan_return:
                   16255:        long            0x7fff0000, 0xffffffff, 0xffffffff
                   16256:
                   16257: #########################################################################
                   16258: # fdbcc(): routine to emulate the fdbcc instruction                    #
                   16259: #                                                                      #
                   16260: # XDEF **************************************************************** #
                   16261: #      _fdbcc()                                                        #
                   16262: #                                                                      #
                   16263: # XREF **************************************************************** #
                   16264: #      fetch_dreg() - fetch Dn value                                   #
                   16265: #      store_dreg_l() - store updated Dn value                         #
                   16266: #                                                                      #
                   16267: # INPUT ***************************************************************        #
                   16268: #      d0 = displacement                                               #
                   16269: #                                                                      #
                   16270: # OUTPUT ************************************************************** #
                   16271: #      none                                                            #
                   16272: #                                                                      #
                   16273: # ALGORITHM ***********************************************************        #
                   16274: #      This routine checks which conditional predicate is specified by #
                   16275: # the stacked fdbcc instruction opcode and then branches to a routine  #
                   16276: # for that predicate. The corresponding fbcc instruction is then used  #
                   16277: # to see whether the condition (specified by the stacked FPSR) is true #
                   16278: # or false.                                                            #
                   16279: #      If a BSUN exception should be indicated, the BSUN and ABSUN     #
                   16280: # bits are set in the stacked FPSR. If the BSUN exception is enabled,  #
                   16281: # the fbsun_flg is set in the SPCOND_FLG location on the stack. If an  #
                   16282: # enabled BSUN should not be flagged and the predicate is true, then   #
                   16283: # Dn is fetched and decremented by one. If Dn is not equal to -1, add  #
                   16284: # the displacement value to the stacked PC so that when an "rte" is    #
                   16285: # finally executed, the branch occurs.                                 #
                   16286: #                                                                      #
                   16287: #########################################################################
                   16288:        global          _fdbcc
                   16289: _fdbcc:
                   16290:        mov.l           %d0,L_SCR1(%a6)         # save displacement
                   16291:
                   16292:        mov.w           EXC_CMDREG(%a6),%d0     # fetch predicate
                   16293:
                   16294:        clr.l           %d1                     # clear scratch reg
                   16295:        mov.b           FPSR_CC(%a6),%d1        # fetch fp ccodes
                   16296:        ror.l           &0x8,%d1                # rotate to top byte
                   16297:        fmov.l          %d1,%fpsr               # insert into FPSR
                   16298:
                   16299:        mov.w           (tbl_fdbcc.b,%pc,%d0.w*2),%d1 # load table
                   16300:        jmp             (tbl_fdbcc.b,%pc,%d1.w) # jump to fdbcc routine
                   16301:
                   16302: tbl_fdbcc:
                   16303:        short           fdbcc_f         -       tbl_fdbcc       # 00
                   16304:        short           fdbcc_eq        -       tbl_fdbcc       # 01
                   16305:        short           fdbcc_ogt       -       tbl_fdbcc       # 02
                   16306:        short           fdbcc_oge       -       tbl_fdbcc       # 03
                   16307:        short           fdbcc_olt       -       tbl_fdbcc       # 04
                   16308:        short           fdbcc_ole       -       tbl_fdbcc       # 05
                   16309:        short           fdbcc_ogl       -       tbl_fdbcc       # 06
                   16310:        short           fdbcc_or        -       tbl_fdbcc       # 07
                   16311:        short           fdbcc_un        -       tbl_fdbcc       # 08
                   16312:        short           fdbcc_ueq       -       tbl_fdbcc       # 09
                   16313:        short           fdbcc_ugt       -       tbl_fdbcc       # 10
                   16314:        short           fdbcc_uge       -       tbl_fdbcc       # 11
                   16315:        short           fdbcc_ult       -       tbl_fdbcc       # 12
                   16316:        short           fdbcc_ule       -       tbl_fdbcc       # 13
                   16317:        short           fdbcc_neq       -       tbl_fdbcc       # 14
                   16318:        short           fdbcc_t         -       tbl_fdbcc       # 15
                   16319:        short           fdbcc_sf        -       tbl_fdbcc       # 16
                   16320:        short           fdbcc_seq       -       tbl_fdbcc       # 17
                   16321:        short           fdbcc_gt        -       tbl_fdbcc       # 18
                   16322:        short           fdbcc_ge        -       tbl_fdbcc       # 19
                   16323:        short           fdbcc_lt        -       tbl_fdbcc       # 20
                   16324:        short           fdbcc_le        -       tbl_fdbcc       # 21
                   16325:        short           fdbcc_gl        -       tbl_fdbcc       # 22
                   16326:        short           fdbcc_gle       -       tbl_fdbcc       # 23
                   16327:        short           fdbcc_ngle      -       tbl_fdbcc       # 24
                   16328:        short           fdbcc_ngl       -       tbl_fdbcc       # 25
                   16329:        short           fdbcc_nle       -       tbl_fdbcc       # 26
                   16330:        short           fdbcc_nlt       -       tbl_fdbcc       # 27
                   16331:        short           fdbcc_nge       -       tbl_fdbcc       # 28
                   16332:        short           fdbcc_ngt       -       tbl_fdbcc       # 29
                   16333:        short           fdbcc_sneq      -       tbl_fdbcc       # 30
                   16334:        short           fdbcc_st        -       tbl_fdbcc       # 31
                   16335:
                   16336: #########################################################################
                   16337: #                                                                      #
                   16338: # IEEE Nonaware tests                                                  #
                   16339: #                                                                      #
                   16340: # For the IEEE nonaware tests, only the false branch changes the       #
                   16341: # counter. However, the true branch may set bsun so we check to see    #
                   16342: # if the NAN bit is set, in which case BSUN and AIOP will be set.      #
                   16343: #                                                                      #
                   16344: # The cases EQ and NE are shared by the Aware and Nonaware groups      #
                   16345: # and are incapable of setting the BSUN exception bit.                 #
                   16346: #                                                                      #
                   16347: # Typically, only one of the two possible branch directions could      #
                   16348: # have the NAN bit set.                                                        #
                   16349: # (This is assuming the mutual exclusiveness of FPSR cc bit groupings  #
                   16350: #  is preserved.)                                                      #
                   16351: #                                                                      #
                   16352: #########################################################################
                   16353:
                   16354: #
                   16355: # equal:
                   16356: #
                   16357: #      Z
                   16358: #
                   16359: fdbcc_eq:
                   16360:        fbeq.w          fdbcc_eq_yes            # equal?
                   16361: fdbcc_eq_no:
                   16362:        bra.w           fdbcc_false             # no; go handle counter
                   16363: fdbcc_eq_yes:
                   16364:        rts
                   16365:
                   16366: #
                   16367: # not equal:
                   16368: #      _
                   16369: #      Z
                   16370: #
                   16371: fdbcc_neq:
                   16372:        fbneq.w         fdbcc_neq_yes           # not equal?
                   16373: fdbcc_neq_no:
                   16374:        bra.w           fdbcc_false             # no; go handle counter
                   16375: fdbcc_neq_yes:
                   16376:        rts
                   16377:
                   16378: #
                   16379: # greater than:
                   16380: #      _______
                   16381: #      NANvZvN
                   16382: #
                   16383: fdbcc_gt:
                   16384:        fbgt.w          fdbcc_gt_yes            # greater than?
                   16385:        btst            &nan_bit, FPSR_CC(%a6)  # is NAN set in cc?
                   16386:        beq.w           fdbcc_false             # no;go handle counter
                   16387:        ori.l           &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
                   16388:        btst            &bsun_bit, FPCR_ENABLE(%a6) # is BSUN enabled?
                   16389:        bne.w           fdbcc_bsun              # yes; we have an exception
                   16390:        bra.w           fdbcc_false             # no; go handle counter
                   16391: fdbcc_gt_yes:
                   16392:        rts                                     # do nothing
                   16393:
                   16394: #
                   16395: # not greater than:
                   16396: #
                   16397: #      NANvZvN
                   16398: #
                   16399: fdbcc_ngt:
                   16400:        fbngt.w         fdbcc_ngt_yes           # not greater than?
                   16401: fdbcc_ngt_no:
                   16402:        bra.w           fdbcc_false             # no; go handle counter
                   16403: fdbcc_ngt_yes:
                   16404:        btst            &nan_bit, FPSR_CC(%a6)  # is NAN set in cc?
                   16405:        beq.b           fdbcc_ngt_done          # no;go finish
                   16406:        ori.l           &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
                   16407:        btst            &bsun_bit, FPCR_ENABLE(%a6) # is BSUN enabled?
                   16408:        bne.w           fdbcc_bsun              # yes; we have an exception
                   16409: fdbcc_ngt_done:
                   16410:        rts                                     # no; do nothing
                   16411:
                   16412: #
                   16413: # greater than or equal:
                   16414: #         _____
                   16415: #      Zv(NANvN)
                   16416: #
                   16417: fdbcc_ge:
                   16418:        fbge.w          fdbcc_ge_yes            # greater than or equal?
                   16419: fdbcc_ge_no:
                   16420:        btst            &nan_bit, FPSR_CC(%a6)  # is NAN set in cc?
                   16421:        beq.w           fdbcc_false             # no;go handle counter
                   16422:        ori.l           &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
                   16423:        btst            &bsun_bit, FPCR_ENABLE(%a6) # is BSUN enabled?
                   16424:        bne.w           fdbcc_bsun              # yes; we have an exception
                   16425:        bra.w           fdbcc_false             # no; go handle counter
                   16426: fdbcc_ge_yes:
                   16427:        btst            &nan_bit, FPSR_CC(%a6)  # is NAN set in cc?
                   16428:        beq.b           fdbcc_ge_yes_done       # no;go do nothing
                   16429:        ori.l           &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
                   16430:        btst            &bsun_bit, FPCR_ENABLE(%a6) # is BSUN enabled?
                   16431:        bne.w           fdbcc_bsun              # yes; we have an exception
                   16432: fdbcc_ge_yes_done:
                   16433:        rts                                     # do nothing
                   16434:
                   16435: #
                   16436: # not (greater than or equal):
                   16437: #             _
                   16438: #      NANv(N^Z)
                   16439: #
                   16440: fdbcc_nge:
                   16441:        fbnge.w         fdbcc_nge_yes           # not (greater than or equal)?
                   16442: fdbcc_nge_no:
                   16443:        bra.w           fdbcc_false             # no; go handle counter
                   16444: fdbcc_nge_yes:
                   16445:        btst            &nan_bit, FPSR_CC(%a6)  # is NAN set in cc?
                   16446:        beq.b           fdbcc_nge_done          # no;go finish
                   16447:        ori.l           &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
                   16448:        btst            &bsun_bit, FPCR_ENABLE(%a6) # is BSUN enabled?
                   16449:        bne.w           fdbcc_bsun              # yes; we have an exception
                   16450: fdbcc_nge_done:
                   16451:        rts                                     # no; do nothing
                   16452:
                   16453: #
                   16454: # less than:
                   16455: #         _____
                   16456: #      N^(NANvZ)
                   16457: #
                   16458: fdbcc_lt:
                   16459:        fblt.w          fdbcc_lt_yes            # less than?
                   16460: fdbcc_lt_no:
                   16461:        btst            &nan_bit, FPSR_CC(%a6)  # is NAN set in cc?
                   16462:        beq.w           fdbcc_false             # no; go handle counter
                   16463:        ori.l           &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
                   16464:        btst            &bsun_bit, FPCR_ENABLE(%a6) # is BSUN enabled?
                   16465:        bne.w           fdbcc_bsun              # yes; we have an exception
                   16466:        bra.w           fdbcc_false             # no; go handle counter
                   16467: fdbcc_lt_yes:
                   16468:        rts                                     # do nothing
                   16469:
                   16470: #
                   16471: # not less than:
                   16472: #             _
                   16473: #      NANv(ZvN)
                   16474: #
                   16475: fdbcc_nlt:
                   16476:        fbnlt.w         fdbcc_nlt_yes           # not less than?
                   16477: fdbcc_nlt_no:
                   16478:        bra.w           fdbcc_false             # no; go handle counter
                   16479: fdbcc_nlt_yes:
                   16480:        btst            &nan_bit, FPSR_CC(%a6)  # is NAN set in cc?
                   16481:        beq.b           fdbcc_nlt_done          # no;go finish
                   16482:        ori.l           &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
                   16483:        btst            &bsun_bit, FPCR_ENABLE(%a6) # is BSUN enabled?
                   16484:        bne.w           fdbcc_bsun              # yes; we have an exception
                   16485: fdbcc_nlt_done:
                   16486:        rts                                     # no; do nothing
                   16487:
                   16488: #
                   16489: # less than or equal:
                   16490: #           ___
                   16491: #      Zv(N^NAN)
                   16492: #
                   16493: fdbcc_le:
                   16494:        fble.w          fdbcc_le_yes            # less than or equal?
                   16495: fdbcc_le_no:
                   16496:        btst            &nan_bit, FPSR_CC(%a6)  # is NAN set in cc?
                   16497:        beq.w           fdbcc_false             # no; go handle counter
                   16498:        ori.l           &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
                   16499:        btst            &bsun_bit, FPCR_ENABLE(%a6) # is BSUN enabled?
                   16500:        bne.w           fdbcc_bsun              # yes; we have an exception
                   16501:        bra.w           fdbcc_false             # no; go handle counter
                   16502: fdbcc_le_yes:
                   16503:        btst            &nan_bit, FPSR_CC(%a6)  # is NAN set in cc?
                   16504:        beq.b           fdbcc_le_yes_done       # no; go do nothing
                   16505:        ori.l           &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
                   16506:        btst            &bsun_bit, FPCR_ENABLE(%a6) # is BSUN enabled?
                   16507:        bne.w           fdbcc_bsun              # yes; we have an exception
                   16508: fdbcc_le_yes_done:
                   16509:        rts                                     # do nothing
                   16510:
                   16511: #
                   16512: # not (less than or equal):
                   16513: #           ___
                   16514: #      NANv(NvZ)
                   16515: #
                   16516: fdbcc_nle:
                   16517:        fbnle.w         fdbcc_nle_yes           # not (less than or equal)?
                   16518: fdbcc_nle_no:
                   16519:        bra.w           fdbcc_false             # no; go handle counter
                   16520: fdbcc_nle_yes:
                   16521:        btst            &nan_bit, FPSR_CC(%a6)  # is NAN set in cc?
                   16522:        beq.w           fdbcc_nle_done          # no; go finish
                   16523:        ori.l           &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
                   16524:        btst            &bsun_bit, FPCR_ENABLE(%a6) # is BSUN enabled?
                   16525:        bne.w           fdbcc_bsun              # yes; we have an exception
                   16526: fdbcc_nle_done:
                   16527:        rts                                     # no; do nothing
                   16528:
                   16529: #
                   16530: # greater or less than:
                   16531: #      _____
                   16532: #      NANvZ
                   16533: #
                   16534: fdbcc_gl:
                   16535:        fbgl.w          fdbcc_gl_yes            # greater or less than?
                   16536: fdbcc_gl_no:
                   16537:        btst            &nan_bit, FPSR_CC(%a6)  # is NAN set in cc?
                   16538:        beq.w           fdbcc_false             # no; handle counter
                   16539:        ori.l           &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
                   16540:        btst            &bsun_bit, FPCR_ENABLE(%a6) # is BSUN enabled?
                   16541:        bne.w           fdbcc_bsun              # yes; we have an exception
                   16542:        bra.w           fdbcc_false             # no; go handle counter
                   16543: fdbcc_gl_yes:
                   16544:        rts                                     # do nothing
                   16545:
                   16546: #
                   16547: # not (greater or less than):
                   16548: #
                   16549: #      NANvZ
                   16550: #
                   16551: fdbcc_ngl:
                   16552:        fbngl.w         fdbcc_ngl_yes           # not (greater or less than)?
                   16553: fdbcc_ngl_no:
                   16554:        bra.w           fdbcc_false             # no; go handle counter
                   16555: fdbcc_ngl_yes:
                   16556:        btst            &nan_bit, FPSR_CC(%a6)  # is NAN set in cc?
                   16557:        beq.b           fdbcc_ngl_done          # no; go finish
                   16558:        ori.l           &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
                   16559:        btst            &bsun_bit, FPCR_ENABLE(%a6) # is BSUN enabled?
                   16560:        bne.w           fdbcc_bsun              # yes; we have an exception
                   16561: fdbcc_ngl_done:
                   16562:        rts                                     # no; do nothing
                   16563:
                   16564: #
                   16565: # greater, less, or equal:
                   16566: #      ___
                   16567: #      NAN
                   16568: #
                   16569: fdbcc_gle:
                   16570:        fbgle.w         fdbcc_gle_yes           # greater, less, or equal?
                   16571: fdbcc_gle_no:
                   16572:        ori.l           &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
                   16573:        btst            &bsun_bit, FPCR_ENABLE(%a6) # is BSUN enabled?
                   16574:        bne.w           fdbcc_bsun              # yes; we have an exception
                   16575:        bra.w           fdbcc_false             # no; go handle counter
                   16576: fdbcc_gle_yes:
                   16577:        rts                                     # do nothing
                   16578:
                   16579: #
                   16580: # not (greater, less, or equal):
                   16581: #
                   16582: #      NAN
                   16583: #
                   16584: fdbcc_ngle:
                   16585:        fbngle.w        fdbcc_ngle_yes          # not (greater, less, or equal)?
                   16586: fdbcc_ngle_no:
                   16587:        bra.w           fdbcc_false             # no; go handle counter
                   16588: fdbcc_ngle_yes:
                   16589:        ori.l           &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
                   16590:        btst            &bsun_bit, FPCR_ENABLE(%a6) # is BSUN enabled?
                   16591:        bne.w           fdbcc_bsun              # yes; we have an exception
                   16592:        rts                                     # no; do nothing
                   16593:
                   16594: #########################################################################
                   16595: #                                                                      #
                   16596: # Miscellaneous tests                                                  #
                   16597: #                                                                      #
                   16598: # For the IEEE miscellaneous tests, all but fdbf and fdbt can set bsun. #
                   16599: #                                                                      #
                   16600: #########################################################################
                   16601:
                   16602: #
                   16603: # false:
                   16604: #
                   16605: #      False
                   16606: #
                   16607: fdbcc_f:                                       # no bsun possible
                   16608:        bra.w           fdbcc_false             # go handle counter
                   16609:
                   16610: #
                   16611: # true:
                   16612: #
                   16613: #      True
                   16614: #
                   16615: fdbcc_t:                                       # no bsun possible
                   16616:        rts                                     # do nothing
                   16617:
                   16618: #
                   16619: # signalling false:
                   16620: #
                   16621: #      False
                   16622: #
                   16623: fdbcc_sf:
                   16624:        btst            &nan_bit, FPSR_CC(%a6)  # is NAN set?
                   16625:        beq.w           fdbcc_false             # no;go handle counter
                   16626:        ori.l           &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
                   16627:        btst            &bsun_bit, FPCR_ENABLE(%a6) # is BSUN enabled?
                   16628:        bne.w           fdbcc_bsun              # yes; we have an exception
                   16629:        bra.w           fdbcc_false             # go handle counter
                   16630:
                   16631: #
                   16632: # signalling true:
                   16633: #
                   16634: #      True
                   16635: #
                   16636: fdbcc_st:
                   16637:        btst            &nan_bit, FPSR_CC(%a6)  # is NAN set?
                   16638:        beq.b           fdbcc_st_done           # no;go finish
                   16639:        ori.l           &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
                   16640:        btst            &bsun_bit, FPCR_ENABLE(%a6) # is BSUN enabled?
                   16641:        bne.w           fdbcc_bsun              # yes; we have an exception
                   16642: fdbcc_st_done:
                   16643:        rts
                   16644:
                   16645: #
                   16646: # signalling equal:
                   16647: #
                   16648: #      Z
                   16649: #
                   16650: fdbcc_seq:
                   16651:        fbseq.w         fdbcc_seq_yes           # signalling equal?
                   16652: fdbcc_seq_no:
                   16653:        btst            &nan_bit, FPSR_CC(%a6)  # is NAN set?
                   16654:        beq.w           fdbcc_false             # no;go handle counter
                   16655:        ori.l           &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
                   16656:        btst            &bsun_bit, FPCR_ENABLE(%a6) # is BSUN enabled?
                   16657:        bne.w           fdbcc_bsun              # yes; we have an exception
                   16658:        bra.w           fdbcc_false             # go handle counter
                   16659: fdbcc_seq_yes:
                   16660:        btst            &nan_bit, FPSR_CC(%a6)  # is NAN set?
                   16661:        beq.b           fdbcc_seq_yes_done      # no;go do nothing
                   16662:        ori.l           &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
                   16663:        btst            &bsun_bit, FPCR_ENABLE(%a6) # is BSUN enabled?
                   16664:        bne.w           fdbcc_bsun              # yes; we have an exception
                   16665: fdbcc_seq_yes_done:
                   16666:        rts                                     # yes; do nothing
                   16667:
                   16668: #
                   16669: # signalling not equal:
                   16670: #      _
                   16671: #      Z
                   16672: #
                   16673: fdbcc_sneq:
                   16674:        fbsneq.w        fdbcc_sneq_yes          # signalling not equal?
                   16675: fdbcc_sneq_no:
                   16676:        btst            &nan_bit, FPSR_CC(%a6)  # is NAN set?
                   16677:        beq.w           fdbcc_false             # no;go handle counter
                   16678:        ori.l           &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
                   16679:        btst            &bsun_bit, FPCR_ENABLE(%a6) # is BSUN enabled?
                   16680:        bne.w           fdbcc_bsun              # yes; we have an exception
                   16681:        bra.w           fdbcc_false             # go handle counter
                   16682: fdbcc_sneq_yes:
                   16683:        btst            &nan_bit, FPSR_CC(%a6)  # set BSUN exc bit
                   16684:        beq.w           fdbcc_sneq_done         # no;go finish
                   16685:        ori.l           &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
                   16686:        btst            &bsun_bit, FPCR_ENABLE(%a6) # is BSUN enabled?
                   16687:        bne.w           fdbcc_bsun              # yes; we have an exception
                   16688: fdbcc_sneq_done:
                   16689:        rts
                   16690:
                   16691: #########################################################################
                   16692: #                                                                      #
                   16693: # IEEE Aware tests                                                     #
                   16694: #                                                                      #
                   16695: # For the IEEE aware tests, action is only taken if the result is false.#
                   16696: # Therefore, the opposite branch type is used to jump to the decrement #
                   16697: # routine.                                                             #
                   16698: # The BSUN exception will not be set for any of these tests.           #
                   16699: #                                                                      #
                   16700: #########################################################################
                   16701:
                   16702: #
                   16703: # ordered greater than:
                   16704: #      _______
                   16705: #      NANvZvN
                   16706: #
                   16707: fdbcc_ogt:
                   16708:        fbogt.w         fdbcc_ogt_yes           # ordered greater than?
                   16709: fdbcc_ogt_no:
                   16710:        bra.w           fdbcc_false             # no; go handle counter
                   16711: fdbcc_ogt_yes:
                   16712:        rts                                     # yes; do nothing
                   16713:
                   16714: #
                   16715: # unordered or less or equal:
                   16716: #      _______
                   16717: #      NANvZvN
                   16718: #
                   16719: fdbcc_ule:
                   16720:        fbule.w         fdbcc_ule_yes           # unordered or less or equal?
                   16721: fdbcc_ule_no:
                   16722:        bra.w           fdbcc_false             # no; go handle counter
                   16723: fdbcc_ule_yes:
                   16724:        rts                                     # yes; do nothing
                   16725:
                   16726: #
                   16727: # ordered greater than or equal:
                   16728: #         _____
                   16729: #      Zv(NANvN)
                   16730: #
                   16731: fdbcc_oge:
                   16732:        fboge.w         fdbcc_oge_yes           # ordered greater than or equal?
                   16733: fdbcc_oge_no:
                   16734:        bra.w           fdbcc_false             # no; go handle counter
                   16735: fdbcc_oge_yes:
                   16736:        rts                                     # yes; do nothing
                   16737:
                   16738: #
                   16739: # unordered or less than:
                   16740: #             _
                   16741: #      NANv(N^Z)
                   16742: #
                   16743: fdbcc_ult:
                   16744:        fbult.w         fdbcc_ult_yes           # unordered or less than?
                   16745: fdbcc_ult_no:
                   16746:        bra.w           fdbcc_false             # no; go handle counter
                   16747: fdbcc_ult_yes:
                   16748:        rts                                     # yes; do nothing
                   16749:
                   16750: #
                   16751: # ordered less than:
                   16752: #         _____
                   16753: #      N^(NANvZ)
                   16754: #
                   16755: fdbcc_olt:
                   16756:        fbolt.w         fdbcc_olt_yes           # ordered less than?
                   16757: fdbcc_olt_no:
                   16758:        bra.w           fdbcc_false             # no; go handle counter
                   16759: fdbcc_olt_yes:
                   16760:        rts                                     # yes; do nothing
                   16761:
                   16762: #
                   16763: # unordered or greater or equal:
                   16764: #
                   16765: #      NANvZvN
                   16766: #
                   16767: fdbcc_uge:
                   16768:        fbuge.w         fdbcc_uge_yes           # unordered or greater than?
                   16769: fdbcc_uge_no:
                   16770:        bra.w           fdbcc_false             # no; go handle counter
                   16771: fdbcc_uge_yes:
                   16772:        rts                                     # yes; do nothing
                   16773:
                   16774: #
                   16775: # ordered less than or equal:
                   16776: #           ___
                   16777: #      Zv(N^NAN)
                   16778: #
                   16779: fdbcc_ole:
                   16780:        fbole.w         fdbcc_ole_yes           # ordered greater or less than?
                   16781: fdbcc_ole_no:
                   16782:        bra.w           fdbcc_false             # no; go handle counter
                   16783: fdbcc_ole_yes:
                   16784:        rts                                     # yes; do nothing
                   16785:
                   16786: #
                   16787: # unordered or greater than:
                   16788: #           ___
                   16789: #      NANv(NvZ)
                   16790: #
                   16791: fdbcc_ugt:
                   16792:        fbugt.w         fdbcc_ugt_yes           # unordered or greater than?
                   16793: fdbcc_ugt_no:
                   16794:        bra.w           fdbcc_false             # no; go handle counter
                   16795: fdbcc_ugt_yes:
                   16796:        rts                                     # yes; do nothing
                   16797:
                   16798: #
                   16799: # ordered greater or less than:
                   16800: #      _____
                   16801: #      NANvZ
                   16802: #
                   16803: fdbcc_ogl:
                   16804:        fbogl.w         fdbcc_ogl_yes           # ordered greater or less than?
                   16805: fdbcc_ogl_no:
                   16806:        bra.w           fdbcc_false             # no; go handle counter
                   16807: fdbcc_ogl_yes:
                   16808:        rts                                     # yes; do nothing
                   16809:
                   16810: #
                   16811: # unordered or equal:
                   16812: #
                   16813: #      NANvZ
                   16814: #
                   16815: fdbcc_ueq:
                   16816:        fbueq.w         fdbcc_ueq_yes           # unordered or equal?
                   16817: fdbcc_ueq_no:
                   16818:        bra.w           fdbcc_false             # no; go handle counter
                   16819: fdbcc_ueq_yes:
                   16820:        rts                                     # yes; do nothing
                   16821:
                   16822: #
                   16823: # ordered:
                   16824: #      ___
                   16825: #      NAN
                   16826: #
                   16827: fdbcc_or:
                   16828:        fbor.w          fdbcc_or_yes            # ordered?
                   16829: fdbcc_or_no:
                   16830:        bra.w           fdbcc_false             # no; go handle counter
                   16831: fdbcc_or_yes:
                   16832:        rts                                     # yes; do nothing
                   16833:
                   16834: #
                   16835: # unordered:
                   16836: #
                   16837: #      NAN
                   16838: #
                   16839: fdbcc_un:
                   16840:        fbun.w          fdbcc_un_yes            # unordered?
                   16841: fdbcc_un_no:
                   16842:        bra.w           fdbcc_false             # no; go handle counter
                   16843: fdbcc_un_yes:
                   16844:        rts                                     # yes; do nothing
                   16845:
                   16846: #######################################################################
                   16847:
                   16848: #
                   16849: # the bsun exception bit was not set.
                   16850: #
                   16851: # (1) subtract 1 from the count register
                   16852: # (2) if (cr == -1) then
                   16853: #      pc = pc of next instruction
                   16854: #     else
                   16855: #      pc += sign_ext(16-bit displacement)
                   16856: #
                   16857: fdbcc_false:
                   16858:        mov.b           1+EXC_OPWORD(%a6), %d1  # fetch lo opword
                   16859:        andi.w          &0x7, %d1               # extract count register
                   16860:
                   16861:        bsr.l           fetch_dreg              # fetch count value
                   16862: # make sure that d0 isn't corrupted between calls...
                   16863:
                   16864:        subq.w          &0x1, %d0               # Dn - 1 -> Dn
                   16865:
                   16866:        bsr.l           store_dreg_l            # store new count value
                   16867:
                   16868:        cmpi.w          %d0, &-0x1              # is (Dn == -1)?
                   16869:        bne.b           fdbcc_false_cont        # no;
                   16870:        rts
                   16871:
                   16872: fdbcc_false_cont:
                   16873:        mov.l           L_SCR1(%a6),%d0         # fetch displacement
                   16874:        add.l           USER_FPIAR(%a6),%d0     # add instruction PC
                   16875:        addq.l          &0x4,%d0                # add instruction length
                   16876:        mov.l           %d0,EXC_PC(%a6)         # set new PC
                   16877:        rts
                   16878:
                   16879: # the emulation routine set bsun and BSUN was enabled. have to
                   16880: # fix stack and jump to the bsun handler.
                   16881: # let the caller of this routine shift the stack frame up to
                   16882: # eliminate the effective address field.
                   16883: fdbcc_bsun:
                   16884:        mov.b           &fbsun_flg,SPCOND_FLG(%a6)
                   16885:        rts
                   16886:
                   16887: #########################################################################
                   16888: # ftrapcc(): routine to emulate the ftrapcc instruction                        #
                   16889: #                                                                      #
                   16890: # XDEF ****************************************************************        #
                   16891: #      _ftrapcc()                                                      #
                   16892: #                                                                      #
                   16893: # XREF ****************************************************************        #
                   16894: #      none                                                            #
                   16895: #                                                                      #
                   16896: # INPUT *************************************************************** #
                   16897: #      none                                                            #
                   16898: #                                                                      #
                   16899: # OUTPUT ************************************************************** #
                   16900: #      none                                                            #
                   16901: #                                                                      #
                   16902: # ALGORITHM *********************************************************** #
                   16903: #      This routine checks which conditional predicate is specified by #
                   16904: # the stacked ftrapcc instruction opcode and then branches to a routine        #
                   16905: # for that predicate. The corresponding fbcc instruction is then used  #
                   16906: # to see whether the condition (specified by the stacked FPSR) is true #
                   16907: # or false.                                                            #
                   16908: #      If a BSUN exception should be indicated, the BSUN and ABSUN     #
                   16909: # bits are set in the stacked FPSR. If the BSUN exception is enabled,  #
                   16910: # the fbsun_flg is set in the SPCOND_FLG location on the stack. If an  #
                   16911: # enabled BSUN should not be flagged and the predicate is true, then   #
                   16912: # the ftrapcc_flg is set in the SPCOND_FLG location. These special     #
                   16913: # flags indicate to the calling routine to emulate the exceptional     #
                   16914: # condition.                                                           #
                   16915: #                                                                      #
                   16916: #########################################################################
                   16917:
                   16918:        global          _ftrapcc
                   16919: _ftrapcc:
                   16920:        mov.w           EXC_CMDREG(%a6),%d0     # fetch predicate
                   16921:
                   16922:        clr.l           %d1                     # clear scratch reg
                   16923:        mov.b           FPSR_CC(%a6),%d1        # fetch fp ccodes
                   16924:        ror.l           &0x8,%d1                # rotate to top byte
                   16925:        fmov.l          %d1,%fpsr               # insert into FPSR
                   16926:
                   16927:        mov.w           (tbl_ftrapcc.b,%pc,%d0.w*2), %d1 # load table
                   16928:        jmp             (tbl_ftrapcc.b,%pc,%d1.w) # jump to ftrapcc routine
                   16929:
                   16930: tbl_ftrapcc:
                   16931:        short           ftrapcc_f       -       tbl_ftrapcc     # 00
                   16932:        short           ftrapcc_eq      -       tbl_ftrapcc     # 01
                   16933:        short           ftrapcc_ogt     -       tbl_ftrapcc     # 02
                   16934:        short           ftrapcc_oge     -       tbl_ftrapcc     # 03
                   16935:        short           ftrapcc_olt     -       tbl_ftrapcc     # 04
                   16936:        short           ftrapcc_ole     -       tbl_ftrapcc     # 05
                   16937:        short           ftrapcc_ogl     -       tbl_ftrapcc     # 06
                   16938:        short           ftrapcc_or      -       tbl_ftrapcc     # 07
                   16939:        short           ftrapcc_un      -       tbl_ftrapcc     # 08
                   16940:        short           ftrapcc_ueq     -       tbl_ftrapcc     # 09
                   16941:        short           ftrapcc_ugt     -       tbl_ftrapcc     # 10
                   16942:        short           ftrapcc_uge     -       tbl_ftrapcc     # 11
                   16943:        short           ftrapcc_ult     -       tbl_ftrapcc     # 12
                   16944:        short           ftrapcc_ule     -       tbl_ftrapcc     # 13
                   16945:        short           ftrapcc_neq     -       tbl_ftrapcc     # 14
                   16946:        short           ftrapcc_t       -       tbl_ftrapcc     # 15
                   16947:        short           ftrapcc_sf      -       tbl_ftrapcc     # 16
                   16948:        short           ftrapcc_seq     -       tbl_ftrapcc     # 17
                   16949:        short           ftrapcc_gt      -       tbl_ftrapcc     # 18
                   16950:        short           ftrapcc_ge      -       tbl_ftrapcc     # 19
                   16951:        short           ftrapcc_lt      -       tbl_ftrapcc     # 20
                   16952:        short           ftrapcc_le      -       tbl_ftrapcc     # 21
                   16953:        short           ftrapcc_gl      -       tbl_ftrapcc     # 22
                   16954:        short           ftrapcc_gle     -       tbl_ftrapcc     # 23
                   16955:        short           ftrapcc_ngle    -       tbl_ftrapcc     # 24
                   16956:        short           ftrapcc_ngl     -       tbl_ftrapcc     # 25
                   16957:        short           ftrapcc_nle     -       tbl_ftrapcc     # 26
                   16958:        short           ftrapcc_nlt     -       tbl_ftrapcc     # 27
                   16959:        short           ftrapcc_nge     -       tbl_ftrapcc     # 28
                   16960:        short           ftrapcc_ngt     -       tbl_ftrapcc     # 29
                   16961:        short           ftrapcc_sneq    -       tbl_ftrapcc     # 30
                   16962:        short           ftrapcc_st      -       tbl_ftrapcc     # 31
                   16963:
                   16964: #########################################################################
                   16965: #                                                                      #
                   16966: # IEEE Nonaware tests                                                  #
                   16967: #                                                                      #
                   16968: # For the IEEE nonaware tests, we set the result based on the          #
                   16969: # floating point condition codes. In addition, we check to see         #
                   16970: # if the NAN bit is set, in which case BSUN and AIOP will be set.      #
                   16971: #                                                                      #
                   16972: # The cases EQ and NE are shared by the Aware and Nonaware groups      #
                   16973: # and are incapable of setting the BSUN exception bit.                 #
                   16974: #                                                                      #
                   16975: # Typically, only one of the two possible branch directions could      #
                   16976: # have the NAN bit set.                                                        #
                   16977: #                                                                      #
                   16978: #########################################################################
                   16979:
                   16980: #
                   16981: # equal:
                   16982: #
                   16983: #      Z
                   16984: #
                   16985: ftrapcc_eq:
                   16986:        fbeq.w          ftrapcc_trap            # equal?
                   16987: ftrapcc_eq_no:
                   16988:        rts                                     # do nothing
                   16989:
                   16990: #
                   16991: # not equal:
                   16992: #      _
                   16993: #      Z
                   16994: #
                   16995: ftrapcc_neq:
                   16996:        fbneq.w         ftrapcc_trap            # not equal?
                   16997: ftrapcc_neq_no:
                   16998:        rts                                     # do nothing
                   16999:
                   17000: #
                   17001: # greater than:
                   17002: #      _______
                   17003: #      NANvZvN
                   17004: #
                   17005: ftrapcc_gt:
                   17006:        fbgt.w          ftrapcc_trap            # greater than?
                   17007: ftrapcc_gt_no:
                   17008:        btst            &nan_bit, FPSR_CC(%a6)  # is NAN set in cc?
                   17009:        beq.b           ftrapcc_gt_done         # no
                   17010:        ori.l           &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
                   17011:        btst            &bsun_bit, FPCR_ENABLE(%a6) # was BSUN set?
                   17012:        bne.w           ftrapcc_bsun            # yes
                   17013: ftrapcc_gt_done:
                   17014:        rts                                     # no; do nothing
                   17015:
                   17016: #
                   17017: # not greater than:
                   17018: #
                   17019: #      NANvZvN
                   17020: #
                   17021: ftrapcc_ngt:
                   17022:        fbngt.w         ftrapcc_ngt_yes         # not greater than?
                   17023: ftrapcc_ngt_no:
                   17024:        rts                                     # do nothing
                   17025: ftrapcc_ngt_yes:
                   17026:        btst            &nan_bit, FPSR_CC(%a6)  # is NAN set in cc?
                   17027:        beq.w           ftrapcc_trap            # no; go take trap
                   17028:        ori.l           &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
                   17029:        btst            &bsun_bit, FPCR_ENABLE(%a6) # was BSUN set?
                   17030:        bne.w           ftrapcc_bsun            # yes
                   17031:        bra.w           ftrapcc_trap            # no; go take trap
                   17032:
                   17033: #
                   17034: # greater than or equal:
                   17035: #         _____
                   17036: #      Zv(NANvN)
                   17037: #
                   17038: ftrapcc_ge:
                   17039:        fbge.w          ftrapcc_ge_yes          # greater than or equal?
                   17040: ftrapcc_ge_no:
                   17041:        btst            &nan_bit, FPSR_CC(%a6)  # is NAN set in cc?
                   17042:        beq.b           ftrapcc_ge_done         # no; go finish
                   17043:        ori.l           &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
                   17044:        btst            &bsun_bit, FPCR_ENABLE(%a6) # was BSUN set?
                   17045:        bne.w           ftrapcc_bsun            # yes
                   17046: ftrapcc_ge_done:
                   17047:        rts                                     # no; do nothing
                   17048: ftrapcc_ge_yes:
                   17049:        btst            &nan_bit, FPSR_CC(%a6)  # is NAN set in cc?
                   17050:        beq.w           ftrapcc_trap            # no; go take trap
                   17051:        ori.l           &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
                   17052:        btst            &bsun_bit, FPCR_ENABLE(%a6) # was BSUN set?
                   17053:        bne.w           ftrapcc_bsun            # yes
                   17054:        bra.w           ftrapcc_trap            # no; go take trap
                   17055:
                   17056: #
                   17057: # not (greater than or equal):
                   17058: #             _
                   17059: #      NANv(N^Z)
                   17060: #
                   17061: ftrapcc_nge:
                   17062:        fbnge.w         ftrapcc_nge_yes         # not (greater than or equal)?
                   17063: ftrapcc_nge_no:
                   17064:        rts                                     # do nothing
                   17065: ftrapcc_nge_yes:
                   17066:        btst            &nan_bit, FPSR_CC(%a6)  # is NAN set in cc?
                   17067:        beq.w           ftrapcc_trap            # no; go take trap
                   17068:        ori.l           &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
                   17069:        btst            &bsun_bit, FPCR_ENABLE(%a6) # was BSUN set?
                   17070:        bne.w           ftrapcc_bsun            # yes
                   17071:        bra.w           ftrapcc_trap            # no; go take trap
                   17072:
                   17073: #
                   17074: # less than:
                   17075: #         _____
                   17076: #      N^(NANvZ)
                   17077: #
                   17078: ftrapcc_lt:
                   17079:        fblt.w          ftrapcc_trap            # less than?
                   17080: ftrapcc_lt_no:
                   17081:        btst            &nan_bit, FPSR_CC(%a6)  # is NAN set in cc?
                   17082:        beq.b           ftrapcc_lt_done         # no; go finish
                   17083:        ori.l           &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
                   17084:        btst            &bsun_bit, FPCR_ENABLE(%a6) # was BSUN set?
                   17085:        bne.w           ftrapcc_bsun            # yes
                   17086: ftrapcc_lt_done:
                   17087:        rts                                     # no; do nothing
                   17088:
                   17089: #
                   17090: # not less than:
                   17091: #             _
                   17092: #      NANv(ZvN)
                   17093: #
                   17094: ftrapcc_nlt:
                   17095:        fbnlt.w         ftrapcc_nlt_yes         # not less than?
                   17096: ftrapcc_nlt_no:
                   17097:        rts                                     # do nothing
                   17098: ftrapcc_nlt_yes:
                   17099:        btst            &nan_bit, FPSR_CC(%a6)  # is NAN set in cc?
                   17100:        beq.w           ftrapcc_trap            # no; go take trap
                   17101:        ori.l           &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
                   17102:        btst            &bsun_bit, FPCR_ENABLE(%a6) # was BSUN set?
                   17103:        bne.w           ftrapcc_bsun            # yes
                   17104:        bra.w           ftrapcc_trap            # no; go take trap
                   17105:
                   17106: #
                   17107: # less than or equal:
                   17108: #           ___
                   17109: #      Zv(N^NAN)
                   17110: #
                   17111: ftrapcc_le:
                   17112:        fble.w          ftrapcc_le_yes          # less than or equal?
                   17113: ftrapcc_le_no:
                   17114:        btst            &nan_bit, FPSR_CC(%a6)  # is NAN set in cc?
                   17115:        beq.b           ftrapcc_le_done         # no; go finish
                   17116:        ori.l           &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
                   17117:        btst            &bsun_bit, FPCR_ENABLE(%a6) # was BSUN set?
                   17118:        bne.w           ftrapcc_bsun            # yes
                   17119: ftrapcc_le_done:
                   17120:        rts                                     # no; do nothing
                   17121: ftrapcc_le_yes:
                   17122:        btst            &nan_bit, FPSR_CC(%a6)  # is NAN set in cc?
                   17123:        beq.w           ftrapcc_trap            # no; go take trap
                   17124:        ori.l           &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
                   17125:        btst            &bsun_bit, FPCR_ENABLE(%a6) # was BSUN set?
                   17126:        bne.w           ftrapcc_bsun            # yes
                   17127:        bra.w           ftrapcc_trap            # no; go take trap
                   17128:
                   17129: #
                   17130: # not (less than or equal):
                   17131: #           ___
                   17132: #      NANv(NvZ)
                   17133: #
                   17134: ftrapcc_nle:
                   17135:        fbnle.w         ftrapcc_nle_yes         # not (less than or equal)?
                   17136: ftrapcc_nle_no:
                   17137:        rts                                     # do nothing
                   17138: ftrapcc_nle_yes:
                   17139:        btst            &nan_bit, FPSR_CC(%a6)  # is NAN set in cc?
                   17140:        beq.w           ftrapcc_trap            # no; go take trap
                   17141:        ori.l           &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
                   17142:        btst            &bsun_bit, FPCR_ENABLE(%a6) # was BSUN set?
                   17143:        bne.w           ftrapcc_bsun            # yes
                   17144:        bra.w           ftrapcc_trap            # no; go take trap
                   17145:
                   17146: #
                   17147: # greater or less than:
                   17148: #      _____
                   17149: #      NANvZ
                   17150: #
                   17151: ftrapcc_gl:
                   17152:        fbgl.w          ftrapcc_trap            # greater or less than?
                   17153: ftrapcc_gl_no:
                   17154:        btst            &nan_bit, FPSR_CC(%a6)  # is NAN set in cc?
                   17155:        beq.b           ftrapcc_gl_done         # no; go finish
                   17156:        ori.l           &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
                   17157:        btst            &bsun_bit, FPCR_ENABLE(%a6) # was BSUN set?
                   17158:        bne.w           ftrapcc_bsun            # yes
                   17159: ftrapcc_gl_done:
                   17160:        rts                                     # no; do nothing
                   17161:
                   17162: #
                   17163: # not (greater or less than):
                   17164: #
                   17165: #      NANvZ
                   17166: #
                   17167: ftrapcc_ngl:
                   17168:        fbngl.w         ftrapcc_ngl_yes         # not (greater or less than)?
                   17169: ftrapcc_ngl_no:
                   17170:        rts                                     # do nothing
                   17171: ftrapcc_ngl_yes:
                   17172:        btst            &nan_bit, FPSR_CC(%a6)  # is NAN set in cc?
                   17173:        beq.w           ftrapcc_trap            # no; go take trap
                   17174:        ori.l           &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
                   17175:        btst            &bsun_bit, FPCR_ENABLE(%a6) # was BSUN set?
                   17176:        bne.w           ftrapcc_bsun            # yes
                   17177:        bra.w           ftrapcc_trap            # no; go take trap
                   17178:
                   17179: #
                   17180: # greater, less, or equal:
                   17181: #      ___
                   17182: #      NAN
                   17183: #
                   17184: ftrapcc_gle:
                   17185:        fbgle.w         ftrapcc_trap            # greater, less, or equal?
                   17186: ftrapcc_gle_no:
                   17187:        ori.l           &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
                   17188:        btst            &bsun_bit, FPCR_ENABLE(%a6) # was BSUN set?
                   17189:        bne.w           ftrapcc_bsun            # yes
                   17190:        rts                                     # no; do nothing
                   17191:
                   17192: #
                   17193: # not (greater, less, or equal):
                   17194: #
                   17195: #      NAN
                   17196: #
                   17197: ftrapcc_ngle:
                   17198:        fbngle.w        ftrapcc_ngle_yes        # not (greater, less, or equal)?
                   17199: ftrapcc_ngle_no:
                   17200:        rts                                     # do nothing
                   17201: ftrapcc_ngle_yes:
                   17202:        ori.l           &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
                   17203:        btst            &bsun_bit, FPCR_ENABLE(%a6) # was BSUN set?
                   17204:        bne.w           ftrapcc_bsun            # yes
                   17205:        bra.w           ftrapcc_trap            # no; go take trap
                   17206:
                   17207: #########################################################################
                   17208: #                                                                      #
                   17209: # Miscellaneous tests                                                  #
                   17210: #                                                                      #
                   17211: # For the IEEE aware tests, we only have to set the result based on the        #
                   17212: # floating point condition codes. The BSUN exception will not be       #
                   17213: # set for any of these tests.                                          #
                   17214: #                                                                      #
                   17215: #########################################################################
                   17216:
                   17217: #
                   17218: # false:
                   17219: #
                   17220: #      False
                   17221: #
                   17222: ftrapcc_f:
                   17223:        rts                                     # do nothing
                   17224:
                   17225: #
                   17226: # true:
                   17227: #
                   17228: #      True
                   17229: #
                   17230: ftrapcc_t:
                   17231:        bra.w           ftrapcc_trap            # go take trap
                   17232:
                   17233: #
                   17234: # signalling false:
                   17235: #
                   17236: #      False
                   17237: #
                   17238: ftrapcc_sf:
                   17239:        btst            &nan_bit, FPSR_CC(%a6)  # set BSUN exc bit
                   17240:        beq.b           ftrapcc_sf_done         # no; go finish
                   17241:        ori.l           &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
                   17242:        btst            &bsun_bit, FPCR_ENABLE(%a6) # was BSUN set?
                   17243:        bne.w           ftrapcc_bsun            # yes
                   17244: ftrapcc_sf_done:
                   17245:        rts                                     # no; do nothing
                   17246:
                   17247: #
                   17248: # signalling true:
                   17249: #
                   17250: #      True
                   17251: #
                   17252: ftrapcc_st:
                   17253:        btst            &nan_bit, FPSR_CC(%a6)  # set BSUN exc bit
                   17254:        beq.w           ftrapcc_trap            # no; go take trap
                   17255:        ori.l           &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
                   17256:        btst            &bsun_bit, FPCR_ENABLE(%a6) # was BSUN set?
                   17257:        bne.w           ftrapcc_bsun            # yes
                   17258:        bra.w           ftrapcc_trap            # no; go take trap
                   17259:
                   17260: #
                   17261: # signalling equal:
                   17262: #
                   17263: #      Z
                   17264: #
                   17265: ftrapcc_seq:
                   17266:        fbseq.w         ftrapcc_seq_yes         # signalling equal?
                   17267: ftrapcc_seq_no:
                   17268:        btst            &nan_bit, FPSR_CC(%a6)  # set BSUN exc bit
                   17269:        beq.w           ftrapcc_seq_done        # no; go finish
                   17270:        ori.l           &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
                   17271:        btst            &bsun_bit, FPCR_ENABLE(%a6) # was BSUN set?
                   17272:        bne.w           ftrapcc_bsun            # yes
                   17273: ftrapcc_seq_done:
                   17274:        rts                                     # no; do nothing
                   17275: ftrapcc_seq_yes:
                   17276:        btst            &nan_bit, FPSR_CC(%a6)  # set BSUN exc bit
                   17277:        beq.w           ftrapcc_trap            # no; go take trap
                   17278:        ori.l           &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
                   17279:        btst            &bsun_bit, FPCR_ENABLE(%a6) # was BSUN set?
                   17280:        bne.w           ftrapcc_bsun            # yes
                   17281:        bra.w           ftrapcc_trap            # no; go take trap
                   17282:
                   17283: #
                   17284: # signalling not equal:
                   17285: #      _
                   17286: #      Z
                   17287: #
                   17288: ftrapcc_sneq:
                   17289:        fbsneq.w        ftrapcc_sneq_yes        # signalling equal?
                   17290: ftrapcc_sneq_no:
                   17291:        btst            &nan_bit, FPSR_CC(%a6)  # set BSUN exc bit
                   17292:        beq.w           ftrapcc_sneq_no_done    # no; go finish
                   17293:        ori.l           &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
                   17294:        btst            &bsun_bit, FPCR_ENABLE(%a6) # was BSUN set?
                   17295:        bne.w           ftrapcc_bsun            # yes
                   17296: ftrapcc_sneq_no_done:
                   17297:        rts                                     # do nothing
                   17298: ftrapcc_sneq_yes:
                   17299:        btst            &nan_bit, FPSR_CC(%a6)  # set BSUN exc bit
                   17300:        beq.w           ftrapcc_trap            # no; go take trap
                   17301:        ori.l           &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
                   17302:        btst            &bsun_bit, FPCR_ENABLE(%a6) # was BSUN set?
                   17303:        bne.w           ftrapcc_bsun            # yes
                   17304:        bra.w           ftrapcc_trap            # no; go take trap
                   17305:
                   17306: #########################################################################
                   17307: #                                                                      #
                   17308: # IEEE Aware tests                                                     #
                   17309: #                                                                      #
                   17310: # For the IEEE aware tests, we only have to set the result based on the        #
                   17311: # floating point condition codes. The BSUN exception will not be       #
                   17312: # set for any of these tests.                                          #
                   17313: #                                                                      #
                   17314: #########################################################################
                   17315:
                   17316: #
                   17317: # ordered greater than:
                   17318: #      _______
                   17319: #      NANvZvN
                   17320: #
                   17321: ftrapcc_ogt:
                   17322:        fbogt.w         ftrapcc_trap            # ordered greater than?
                   17323: ftrapcc_ogt_no:
                   17324:        rts                                     # do nothing
                   17325:
                   17326: #
                   17327: # unordered or less or equal:
                   17328: #      _______
                   17329: #      NANvZvN
                   17330: #
                   17331: ftrapcc_ule:
                   17332:        fbule.w         ftrapcc_trap            # unordered or less or equal?
                   17333: ftrapcc_ule_no:
                   17334:        rts                                     # do nothing
                   17335:
                   17336: #
                   17337: # ordered greater than or equal:
                   17338: #         _____
                   17339: #      Zv(NANvN)
                   17340: #
                   17341: ftrapcc_oge:
                   17342:        fboge.w         ftrapcc_trap            # ordered greater than or equal?
                   17343: ftrapcc_oge_no:
                   17344:        rts                                     # do nothing
                   17345:
                   17346: #
                   17347: # unordered or less than:
                   17348: #             _
                   17349: #      NANv(N^Z)
                   17350: #
                   17351: ftrapcc_ult:
                   17352:        fbult.w         ftrapcc_trap            # unordered or less than?
                   17353: ftrapcc_ult_no:
                   17354:        rts                                     # do nothing
                   17355:
                   17356: #
                   17357: # ordered less than:
                   17358: #         _____
                   17359: #      N^(NANvZ)
                   17360: #
                   17361: ftrapcc_olt:
                   17362:        fbolt.w         ftrapcc_trap            # ordered less than?
                   17363: ftrapcc_olt_no:
                   17364:        rts                                     # do nothing
                   17365:
                   17366: #
                   17367: # unordered or greater or equal:
                   17368: #
                   17369: #      NANvZvN
                   17370: #
                   17371: ftrapcc_uge:
                   17372:        fbuge.w         ftrapcc_trap            # unordered or greater than?
                   17373: ftrapcc_uge_no:
                   17374:        rts                                     # do nothing
                   17375:
                   17376: #
                   17377: # ordered less than or equal:
                   17378: #           ___
                   17379: #      Zv(N^NAN)
                   17380: #
                   17381: ftrapcc_ole:
                   17382:        fbole.w         ftrapcc_trap            # ordered greater or less than?
                   17383: ftrapcc_ole_no:
                   17384:        rts                                     # do nothing
                   17385:
                   17386: #
                   17387: # unordered or greater than:
                   17388: #           ___
                   17389: #      NANv(NvZ)
                   17390: #
                   17391: ftrapcc_ugt:
                   17392:        fbugt.w         ftrapcc_trap            # unordered or greater than?
                   17393: ftrapcc_ugt_no:
                   17394:        rts                                     # do nothing
                   17395:
                   17396: #
                   17397: # ordered greater or less than:
                   17398: #      _____
                   17399: #      NANvZ
                   17400: #
                   17401: ftrapcc_ogl:
                   17402:        fbogl.w         ftrapcc_trap            # ordered greater or less than?
                   17403: ftrapcc_ogl_no:
                   17404:        rts                                     # do nothing
                   17405:
                   17406: #
                   17407: # unordered or equal:
                   17408: #
                   17409: #      NANvZ
                   17410: #
                   17411: ftrapcc_ueq:
                   17412:        fbueq.w         ftrapcc_trap            # unordered or equal?
                   17413: ftrapcc_ueq_no:
                   17414:        rts                                     # do nothing
                   17415:
                   17416: #
                   17417: # ordered:
                   17418: #      ___
                   17419: #      NAN
                   17420: #
                   17421: ftrapcc_or:
                   17422:        fbor.w          ftrapcc_trap            # ordered?
                   17423: ftrapcc_or_no:
                   17424:        rts                                     # do nothing
                   17425:
                   17426: #
                   17427: # unordered:
                   17428: #
                   17429: #      NAN
                   17430: #
                   17431: ftrapcc_un:
                   17432:        fbun.w          ftrapcc_trap            # unordered?
                   17433: ftrapcc_un_no:
                   17434:        rts                                     # do nothing
                   17435:
                   17436: #######################################################################
                   17437:
                   17438: # the bsun exception bit was not set.
                   17439: # we will need to jump to the ftrapcc vector. the stack frame
                   17440: # is the same size as that of the fp unimp instruction. the
                   17441: # only difference is that the <ea> field should hold the PC
                   17442: # of the ftrapcc instruction and the vector offset field
                   17443: # should denote the ftrapcc trap.
                   17444: ftrapcc_trap:
                   17445:        mov.b           &ftrapcc_flg,SPCOND_FLG(%a6)
                   17446:        rts
                   17447:
                   17448: # the emulation routine set bsun and BSUN was enabled. have to
                   17449: # fix stack and jump to the bsun handler.
                   17450: # let the caller of this routine shift the stack frame up to
                   17451: # eliminate the effective address field.
                   17452: ftrapcc_bsun:
                   17453:        mov.b           &fbsun_flg,SPCOND_FLG(%a6)
                   17454:        rts
                   17455:
                   17456: #########################################################################
                   17457: # fscc(): routine to emulate the fscc instruction                      #
                   17458: #                                                                      #
                   17459: # XDEF **************************************************************** #
                   17460: #      _fscc()                                                         #
                   17461: #                                                                      #
                   17462: # XREF **************************************************************** #
                   17463: #      store_dreg_b() - store result to data register file             #
                   17464: #      dec_areg() - decrement an areg for -(an) mode                   #
                   17465: #      inc_areg() - increment an areg for (an)+ mode                   #
                   17466: #      _dmem_write_byte() - store result to memory                     #
                   17467: #                                                                      #
                   17468: # INPUT ***************************************************************        #
                   17469: #      none                                                            #
                   17470: #                                                                      #
                   17471: # OUTPUT ************************************************************** #
                   17472: #      none                                                            #
                   17473: #                                                                      #
                   17474: # ALGORITHM ***********************************************************        #
                   17475: #      This routine checks which conditional predicate is specified by #
                   17476: # the stacked fscc instruction opcode and then branches to a routine   #
                   17477: # for that predicate. The corresponding fbcc instruction is then used  #
                   17478: # to see whether the condition (specified by the stacked FPSR) is true #
                   17479: # or false.                                                            #
                   17480: #      If a BSUN exception should be indicated, the BSUN and ABSUN     #
                   17481: # bits are set in the stacked FPSR. If the BSUN exception is enabled,  #
                   17482: # the fbsun_flg is set in the SPCOND_FLG location on the stack. If an  #
                   17483: # enabled BSUN should not be flagged and the predicate is true, then   #
                   17484: # the result is stored to the data register file or memory             #
                   17485: #                                                                      #
                   17486: #########################################################################
                   17487:
                   17488:        global          _fscc
                   17489: _fscc:
                   17490:        mov.w           EXC_CMDREG(%a6),%d0     # fetch predicate
                   17491:
                   17492:        clr.l           %d1                     # clear scratch reg
                   17493:        mov.b           FPSR_CC(%a6),%d1        # fetch fp ccodes
                   17494:        ror.l           &0x8,%d1                # rotate to top byte
                   17495:        fmov.l          %d1,%fpsr               # insert into FPSR
                   17496:
                   17497:        mov.w           (tbl_fscc.b,%pc,%d0.w*2),%d1 # load table
                   17498:        jmp             (tbl_fscc.b,%pc,%d1.w)  # jump to fscc routine
                   17499:
                   17500: tbl_fscc:
                   17501:        short           fscc_f          -       tbl_fscc        # 00
                   17502:        short           fscc_eq         -       tbl_fscc        # 01
                   17503:        short           fscc_ogt        -       tbl_fscc        # 02
                   17504:        short           fscc_oge        -       tbl_fscc        # 03
                   17505:        short           fscc_olt        -       tbl_fscc        # 04
                   17506:        short           fscc_ole        -       tbl_fscc        # 05
                   17507:        short           fscc_ogl        -       tbl_fscc        # 06
                   17508:        short           fscc_or         -       tbl_fscc        # 07
                   17509:        short           fscc_un         -       tbl_fscc        # 08
                   17510:        short           fscc_ueq        -       tbl_fscc        # 09
                   17511:        short           fscc_ugt        -       tbl_fscc        # 10
                   17512:        short           fscc_uge        -       tbl_fscc        # 11
                   17513:        short           fscc_ult        -       tbl_fscc        # 12
                   17514:        short           fscc_ule        -       tbl_fscc        # 13
                   17515:        short           fscc_neq        -       tbl_fscc        # 14
                   17516:        short           fscc_t          -       tbl_fscc        # 15
                   17517:        short           fscc_sf         -       tbl_fscc        # 16
                   17518:        short           fscc_seq        -       tbl_fscc        # 17
                   17519:        short           fscc_gt         -       tbl_fscc        # 18
                   17520:        short           fscc_ge         -       tbl_fscc        # 19
                   17521:        short           fscc_lt         -       tbl_fscc        # 20
                   17522:        short           fscc_le         -       tbl_fscc        # 21
                   17523:        short           fscc_gl         -       tbl_fscc        # 22
                   17524:        short           fscc_gle        -       tbl_fscc        # 23
                   17525:        short           fscc_ngle       -       tbl_fscc        # 24
                   17526:        short           fscc_ngl        -       tbl_fscc        # 25
                   17527:        short           fscc_nle        -       tbl_fscc        # 26
                   17528:        short           fscc_nlt        -       tbl_fscc        # 27
                   17529:        short           fscc_nge        -       tbl_fscc        # 28
                   17530:        short           fscc_ngt        -       tbl_fscc        # 29
                   17531:        short           fscc_sneq       -       tbl_fscc        # 30
                   17532:        short           fscc_st         -       tbl_fscc        # 31
                   17533:
                   17534: #########################################################################
                   17535: #                                                                      #
                   17536: # IEEE Nonaware tests                                                  #
                   17537: #                                                                      #
                   17538: # For the IEEE nonaware tests, we set the result based on the          #
                   17539: # floating point condition codes. In addition, we check to see         #
                   17540: # if the NAN bit is set, in which case BSUN and AIOP will be set.      #
                   17541: #                                                                      #
                   17542: # The cases EQ and NE are shared by the Aware and Nonaware groups      #
                   17543: # and are incapable of setting the BSUN exception bit.                 #
                   17544: #                                                                      #
                   17545: # Typically, only one of the two possible branch directions could      #
                   17546: # have the NAN bit set.                                                        #
                   17547: #                                                                      #
                   17548: #########################################################################
                   17549:
                   17550: #
                   17551: # equal:
                   17552: #
                   17553: #      Z
                   17554: #
                   17555: fscc_eq:
                   17556:        fbeq.w          fscc_eq_yes             # equal?
                   17557: fscc_eq_no:
                   17558:        clr.b           %d0                     # set false
                   17559:        bra.w           fscc_done               # go finish
                   17560: fscc_eq_yes:
                   17561:        st              %d0                     # set true
                   17562:        bra.w           fscc_done               # go finish
                   17563:
                   17564: #
                   17565: # not equal:
                   17566: #      _
                   17567: #      Z
                   17568: #
                   17569: fscc_neq:
                   17570:        fbneq.w         fscc_neq_yes            # not equal?
                   17571: fscc_neq_no:
                   17572:        clr.b           %d0                     # set false
                   17573:        bra.w           fscc_done               # go finish
                   17574: fscc_neq_yes:
                   17575:        st              %d0                     # set true
                   17576:        bra.w           fscc_done               # go finish
                   17577:
                   17578: #
                   17579: # greater than:
                   17580: #      _______
                   17581: #      NANvZvN
                   17582: #
                   17583: fscc_gt:
                   17584:        fbgt.w          fscc_gt_yes             # greater than?
                   17585: fscc_gt_no:
                   17586:        clr.b           %d0                     # set false
                   17587:        btst            &nan_bit, FPSR_CC(%a6)  # is NAN set in cc?
                   17588:        beq.w           fscc_done               # no;go finish
                   17589:        ori.l           &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
                   17590:        bra.w           fscc_chk_bsun           # go finish
                   17591: fscc_gt_yes:
                   17592:        st              %d0                     # set true
                   17593:        bra.w           fscc_done               # go finish
                   17594:
                   17595: #
                   17596: # not greater than:
                   17597: #
                   17598: #      NANvZvN
                   17599: #
                   17600: fscc_ngt:
                   17601:        fbngt.w         fscc_ngt_yes            # not greater than?
                   17602: fscc_ngt_no:
                   17603:        clr.b           %d0                     # set false
                   17604:        bra.w           fscc_done               # go finish
                   17605: fscc_ngt_yes:
                   17606:        st              %d0                     # set true
                   17607:        btst            &nan_bit, FPSR_CC(%a6)  # is NAN set in cc?
                   17608:        beq.w           fscc_done               # no;go finish
                   17609:        ori.l           &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
                   17610:        bra.w           fscc_chk_bsun           # go finish
                   17611:
                   17612: #
                   17613: # greater than or equal:
                   17614: #         _____
                   17615: #      Zv(NANvN)
                   17616: #
                   17617: fscc_ge:
                   17618:        fbge.w          fscc_ge_yes             # greater than or equal?
                   17619: fscc_ge_no:
                   17620:        clr.b           %d0                     # set false
                   17621:        btst            &nan_bit, FPSR_CC(%a6)  # is NAN set in cc?
                   17622:        beq.w           fscc_done               # no;go finish
                   17623:        ori.l           &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
                   17624:        bra.w           fscc_chk_bsun           # go finish
                   17625: fscc_ge_yes:
                   17626:        st              %d0                     # set true
                   17627:        btst            &nan_bit, FPSR_CC(%a6)  # is NAN set in cc?
                   17628:        beq.w           fscc_done               # no;go finish
                   17629:        ori.l           &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
                   17630:        bra.w           fscc_chk_bsun           # go finish
                   17631:
                   17632: #
                   17633: # not (greater than or equal):
                   17634: #             _
                   17635: #      NANv(N^Z)
                   17636: #
                   17637: fscc_nge:
                   17638:        fbnge.w         fscc_nge_yes            # not (greater than or equal)?
                   17639: fscc_nge_no:
                   17640:        clr.b           %d0                     # set false
                   17641:        bra.w           fscc_done               # go finish
                   17642: fscc_nge_yes:
                   17643:        st              %d0                     # set true
                   17644:        btst            &nan_bit, FPSR_CC(%a6)  # is NAN set in cc?
                   17645:        beq.w           fscc_done               # no;go finish
                   17646:        ori.l           &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
                   17647:        bra.w           fscc_chk_bsun           # go finish
                   17648:
                   17649: #
                   17650: # less than:
                   17651: #         _____
                   17652: #      N^(NANvZ)
                   17653: #
                   17654: fscc_lt:
                   17655:        fblt.w          fscc_lt_yes             # less than?
                   17656: fscc_lt_no:
                   17657:        clr.b           %d0                     # set false
                   17658:        btst            &nan_bit, FPSR_CC(%a6)  # is NAN set in cc?
                   17659:        beq.w           fscc_done               # no;go finish
                   17660:        ori.l           &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
                   17661:        bra.w           fscc_chk_bsun           # go finish
                   17662: fscc_lt_yes:
                   17663:        st              %d0                     # set true
                   17664:        bra.w           fscc_done               # go finish
                   17665:
                   17666: #
                   17667: # not less than:
                   17668: #             _
                   17669: #      NANv(ZvN)
                   17670: #
                   17671: fscc_nlt:
                   17672:        fbnlt.w         fscc_nlt_yes            # not less than?
                   17673: fscc_nlt_no:
                   17674:        clr.b           %d0                     # set false
                   17675:        bra.w           fscc_done               # go finish
                   17676: fscc_nlt_yes:
                   17677:        st              %d0                     # set true
                   17678:        btst            &nan_bit, FPSR_CC(%a6)  # is NAN set in cc?
                   17679:        beq.w           fscc_done               # no;go finish
                   17680:        ori.l           &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
                   17681:        bra.w           fscc_chk_bsun           # go finish
                   17682:
                   17683: #
                   17684: # less than or equal:
                   17685: #           ___
                   17686: #      Zv(N^NAN)
                   17687: #
                   17688: fscc_le:
                   17689:        fble.w          fscc_le_yes             # less than or equal?
                   17690: fscc_le_no:
                   17691:        clr.b           %d0                     # set false
                   17692:        btst            &nan_bit, FPSR_CC(%a6)  # is NAN set in cc?
                   17693:        beq.w           fscc_done               # no;go finish
                   17694:        ori.l           &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
                   17695:        bra.w           fscc_chk_bsun           # go finish
                   17696: fscc_le_yes:
                   17697:        st              %d0                     # set true
                   17698:        btst            &nan_bit, FPSR_CC(%a6)  # is NAN set in cc?
                   17699:        beq.w           fscc_done               # no;go finish
                   17700:        ori.l           &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
                   17701:        bra.w           fscc_chk_bsun           # go finish
                   17702:
                   17703: #
                   17704: # not (less than or equal):
                   17705: #           ___
                   17706: #      NANv(NvZ)
                   17707: #
                   17708: fscc_nle:
                   17709:        fbnle.w         fscc_nle_yes            # not (less than or equal)?
                   17710: fscc_nle_no:
                   17711:        clr.b           %d0                     # set false
                   17712:        bra.w           fscc_done               # go finish
                   17713: fscc_nle_yes:
                   17714:        st              %d0                     # set true
                   17715:        btst            &nan_bit, FPSR_CC(%a6)  # is NAN set in cc?
                   17716:        beq.w           fscc_done               # no;go finish
                   17717:        ori.l           &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
                   17718:        bra.w           fscc_chk_bsun           # go finish
                   17719:
                   17720: #
                   17721: # greater or less than:
                   17722: #      _____
                   17723: #      NANvZ
                   17724: #
                   17725: fscc_gl:
                   17726:        fbgl.w          fscc_gl_yes             # greater or less than?
                   17727: fscc_gl_no:
                   17728:        clr.b           %d0                     # set false
                   17729:        btst            &nan_bit, FPSR_CC(%a6)  # is NAN set in cc?
                   17730:        beq.w           fscc_done               # no;go finish
                   17731:        ori.l           &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
                   17732:        bra.w           fscc_chk_bsun           # go finish
                   17733: fscc_gl_yes:
                   17734:        st              %d0                     # set true
                   17735:        bra.w           fscc_done               # go finish
                   17736:
                   17737: #
                   17738: # not (greater or less than):
                   17739: #
                   17740: #      NANvZ
                   17741: #
                   17742: fscc_ngl:
                   17743:        fbngl.w         fscc_ngl_yes            # not (greater or less than)?
                   17744: fscc_ngl_no:
                   17745:        clr.b           %d0                     # set false
                   17746:        bra.w           fscc_done               # go finish
                   17747: fscc_ngl_yes:
                   17748:        st              %d0                     # set true
                   17749:        btst            &nan_bit, FPSR_CC(%a6)  # is NAN set in cc?
                   17750:        beq.w           fscc_done               # no;go finish
                   17751:        ori.l           &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
                   17752:        bra.w           fscc_chk_bsun           # go finish
                   17753:
                   17754: #
                   17755: # greater, less, or equal:
                   17756: #      ___
                   17757: #      NAN
                   17758: #
                   17759: fscc_gle:
                   17760:        fbgle.w         fscc_gle_yes            # greater, less, or equal?
                   17761: fscc_gle_no:
                   17762:        clr.b           %d0                     # set false
                   17763:        ori.l           &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
                   17764:        bra.w           fscc_chk_bsun           # go finish
                   17765: fscc_gle_yes:
                   17766:        st              %d0                     # set true
                   17767:        bra.w           fscc_done               # go finish
                   17768:
                   17769: #
                   17770: # not (greater, less, or equal):
                   17771: #
                   17772: #      NAN
                   17773: #
                   17774: fscc_ngle:
                   17775:        fbngle.w                fscc_ngle_yes   # not (greater, less, or equal)?
                   17776: fscc_ngle_no:
                   17777:        clr.b           %d0                     # set false
                   17778:        bra.w           fscc_done               # go finish
                   17779: fscc_ngle_yes:
                   17780:        st              %d0                     # set true
                   17781:        ori.l           &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
                   17782:        bra.w           fscc_chk_bsun           # go finish
                   17783:
                   17784: #########################################################################
                   17785: #                                                                      #
                   17786: # Miscellaneous tests                                                  #
                   17787: #                                                                      #
                   17788: # For the IEEE aware tests, we only have to set the result based on the        #
                   17789: # floating point condition codes. The BSUN exception will not be       #
                   17790: # set for any of these tests.                                          #
                   17791: #                                                                      #
                   17792: #########################################################################
                   17793:
                   17794: #
                   17795: # false:
                   17796: #
                   17797: #      False
                   17798: #
                   17799: fscc_f:
                   17800:        clr.b           %d0                     # set false
                   17801:        bra.w           fscc_done               # go finish
                   17802:
                   17803: #
                   17804: # true:
                   17805: #
                   17806: #      True
                   17807: #
                   17808: fscc_t:
                   17809:        st              %d0                     # set true
                   17810:        bra.w           fscc_done               # go finish
                   17811:
                   17812: #
                   17813: # signalling false:
                   17814: #
                   17815: #      False
                   17816: #
                   17817: fscc_sf:
                   17818:        clr.b           %d0                     # set false
                   17819:        btst            &nan_bit, FPSR_CC(%a6)  # set BSUN exc bit
                   17820:        beq.w           fscc_done               # no;go finish
                   17821:        ori.l           &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
                   17822:        bra.w           fscc_chk_bsun           # go finish
                   17823:
                   17824: #
                   17825: # signalling true:
                   17826: #
                   17827: #      True
                   17828: #
                   17829: fscc_st:
                   17830:        st              %d0                     # set false
                   17831:        btst            &nan_bit, FPSR_CC(%a6)  # set BSUN exc bit
                   17832:        beq.w           fscc_done               # no;go finish
                   17833:        ori.l           &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
                   17834:        bra.w           fscc_chk_bsun           # go finish
                   17835:
                   17836: #
                   17837: # signalling equal:
                   17838: #
                   17839: #      Z
                   17840: #
                   17841: fscc_seq:
                   17842:        fbseq.w         fscc_seq_yes            # signalling equal?
                   17843: fscc_seq_no:
                   17844:        clr.b           %d0                     # set false
                   17845:        btst            &nan_bit, FPSR_CC(%a6)  # set BSUN exc bit
                   17846:        beq.w           fscc_done               # no;go finish
                   17847:        ori.l           &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
                   17848:        bra.w           fscc_chk_bsun           # go finish
                   17849: fscc_seq_yes:
                   17850:        st              %d0                     # set true
                   17851:        btst            &nan_bit, FPSR_CC(%a6)  # set BSUN exc bit
                   17852:        beq.w           fscc_done               # no;go finish
                   17853:        ori.l           &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
                   17854:        bra.w           fscc_chk_bsun           # go finish
                   17855:
                   17856: #
                   17857: # signalling not equal:
                   17858: #      _
                   17859: #      Z
                   17860: #
                   17861: fscc_sneq:
                   17862:        fbsneq.w        fscc_sneq_yes           # signalling equal?
                   17863: fscc_sneq_no:
                   17864:        clr.b           %d0                     # set false
                   17865:        btst            &nan_bit, FPSR_CC(%a6)  # set BSUN exc bit
                   17866:        beq.w           fscc_done               # no;go finish
                   17867:        ori.l           &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
                   17868:        bra.w           fscc_chk_bsun           # go finish
                   17869: fscc_sneq_yes:
                   17870:        st              %d0                     # set true
                   17871:        btst            &nan_bit, FPSR_CC(%a6)  # set BSUN exc bit
                   17872:        beq.w           fscc_done               # no;go finish
                   17873:        ori.l           &bsun_mask+aiop_mask, USER_FPSR(%a6) # set BSUN exc bit
                   17874:        bra.w           fscc_chk_bsun           # go finish
                   17875:
                   17876: #########################################################################
                   17877: #                                                                      #
                   17878: # IEEE Aware tests                                                     #
                   17879: #                                                                      #
                   17880: # For the IEEE aware tests, we only have to set the result based on the        #
                   17881: # floating point condition codes. The BSUN exception will not be       #
                   17882: # set for any of these tests.                                          #
                   17883: #                                                                      #
                   17884: #########################################################################
                   17885:
                   17886: #
                   17887: # ordered greater than:
                   17888: #      _______
                   17889: #      NANvZvN
                   17890: #
                   17891: fscc_ogt:
                   17892:        fbogt.w         fscc_ogt_yes            # ordered greater than?
                   17893: fscc_ogt_no:
                   17894:        clr.b           %d0                     # set false
                   17895:        bra.w           fscc_done               # go finish
                   17896: fscc_ogt_yes:
                   17897:        st              %d0                     # set true
                   17898:        bra.w           fscc_done               # go finish
                   17899:
                   17900: #
                   17901: # unordered or less or equal:
                   17902: #      _______
                   17903: #      NANvZvN
                   17904: #
                   17905: fscc_ule:
                   17906:        fbule.w         fscc_ule_yes            # unordered or less or equal?
                   17907: fscc_ule_no:
                   17908:        clr.b           %d0                     # set false
                   17909:        bra.w           fscc_done               # go finish
                   17910: fscc_ule_yes:
                   17911:        st              %d0                     # set true
                   17912:        bra.w           fscc_done               # go finish
                   17913:
                   17914: #
                   17915: # ordered greater than or equal:
                   17916: #         _____
                   17917: #      Zv(NANvN)
                   17918: #
                   17919: fscc_oge:
                   17920:        fboge.w         fscc_oge_yes            # ordered greater than or equal?
                   17921: fscc_oge_no:
                   17922:        clr.b           %d0                     # set false
                   17923:        bra.w           fscc_done               # go finish
                   17924: fscc_oge_yes:
                   17925:        st              %d0                     # set true
                   17926:        bra.w           fscc_done               # go finish
                   17927:
                   17928: #
                   17929: # unordered or less than:
                   17930: #             _
                   17931: #      NANv(N^Z)
                   17932: #
                   17933: fscc_ult:
                   17934:        fbult.w         fscc_ult_yes            # unordered or less than?
                   17935: fscc_ult_no:
                   17936:        clr.b           %d0                     # set false
                   17937:        bra.w           fscc_done               # go finish
                   17938: fscc_ult_yes:
                   17939:        st              %d0                     # set true
                   17940:        bra.w           fscc_done               # go finish
                   17941:
                   17942: #
                   17943: # ordered less than:
                   17944: #         _____
                   17945: #      N^(NANvZ)
                   17946: #
                   17947: fscc_olt:
                   17948:        fbolt.w         fscc_olt_yes            # ordered less than?
                   17949: fscc_olt_no:
                   17950:        clr.b           %d0                     # set false
                   17951:        bra.w           fscc_done               # go finish
                   17952: fscc_olt_yes:
                   17953:        st              %d0                     # set true
                   17954:        bra.w           fscc_done               # go finish
                   17955:
                   17956: #
                   17957: # unordered or greater or equal:
                   17958: #
                   17959: #      NANvZvN
                   17960: #
                   17961: fscc_uge:
                   17962:        fbuge.w         fscc_uge_yes            # unordered or greater than?
                   17963: fscc_uge_no:
                   17964:        clr.b           %d0                     # set false
                   17965:        bra.w           fscc_done               # go finish
                   17966: fscc_uge_yes:
                   17967:        st              %d0                     # set true
                   17968:        bra.w           fscc_done               # go finish
                   17969:
                   17970: #
                   17971: # ordered less than or equal:
                   17972: #           ___
                   17973: #      Zv(N^NAN)
                   17974: #
                   17975: fscc_ole:
                   17976:        fbole.w         fscc_ole_yes            # ordered greater or less than?
                   17977: fscc_ole_no:
                   17978:        clr.b           %d0                     # set false
                   17979:        bra.w           fscc_done               # go finish
                   17980: fscc_ole_yes:
                   17981:        st              %d0                     # set true
                   17982:        bra.w           fscc_done               # go finish
                   17983:
                   17984: #
                   17985: # unordered or greater than:
                   17986: #           ___
                   17987: #      NANv(NvZ)
                   17988: #
                   17989: fscc_ugt:
                   17990:        fbugt.w         fscc_ugt_yes            # unordered or greater than?
                   17991: fscc_ugt_no:
                   17992:        clr.b           %d0                     # set false
                   17993:        bra.w           fscc_done               # go finish
                   17994: fscc_ugt_yes:
                   17995:        st              %d0                     # set true
                   17996:        bra.w           fscc_done               # go finish
                   17997:
                   17998: #
                   17999: # ordered greater or less than:
                   18000: #      _____
                   18001: #      NANvZ
                   18002: #
                   18003: fscc_ogl:
                   18004:        fbogl.w         fscc_ogl_yes            # ordered greater or less than?
                   18005: fscc_ogl_no:
                   18006:        clr.b           %d0                     # set false
                   18007:        bra.w           fscc_done               # go finish
                   18008: fscc_ogl_yes:
                   18009:        st              %d0                     # set true
                   18010:        bra.w           fscc_done               # go finish
                   18011:
                   18012: #
                   18013: # unordered or equal:
                   18014: #
                   18015: #      NANvZ
                   18016: #
                   18017: fscc_ueq:
                   18018:        fbueq.w         fscc_ueq_yes            # unordered or equal?
                   18019: fscc_ueq_no:
                   18020:        clr.b           %d0                     # set false
                   18021:        bra.w           fscc_done               # go finish
                   18022: fscc_ueq_yes:
                   18023:        st              %d0                     # set true
                   18024:        bra.w           fscc_done               # go finish
                   18025:
                   18026: #
                   18027: # ordered:
                   18028: #      ___
                   18029: #      NAN
                   18030: #
                   18031: fscc_or:
                   18032:        fbor.w          fscc_or_yes             # ordered?
                   18033: fscc_or_no:
                   18034:        clr.b           %d0                     # set false
                   18035:        bra.w           fscc_done               # go finish
                   18036: fscc_or_yes:
                   18037:        st              %d0                     # set true
                   18038:        bra.w           fscc_done               # go finish
                   18039:
                   18040: #
                   18041: # unordered:
                   18042: #
                   18043: #      NAN
                   18044: #
                   18045: fscc_un:
                   18046:        fbun.w          fscc_un_yes             # unordered?
                   18047: fscc_un_no:
                   18048:        clr.b           %d0                     # set false
                   18049:        bra.w           fscc_done               # go finish
                   18050: fscc_un_yes:
                   18051:        st              %d0                     # set true
                   18052:        bra.w           fscc_done               # go finish
                   18053:
                   18054: #######################################################################
                   18055:
                   18056: #
                   18057: # the bsun exception bit was set. now, check to see is BSUN
                   18058: # is enabled. if so, don't store result and correct stack frame
                   18059: # for a bsun exception.
                   18060: #
                   18061: fscc_chk_bsun:
                   18062:        btst            &bsun_bit,FPCR_ENABLE(%a6) # was BSUN set?
                   18063:        bne.w           fscc_bsun
                   18064:
                   18065: #
                   18066: # the bsun exception bit was not set.
                   18067: # the result has been selected.
                   18068: # now, check to see if the result is to be stored in the data register
                   18069: # file or in memory.
                   18070: #
                   18071: fscc_done:
                   18072:        mov.l           %d0,%a0                 # save result for a moment
                   18073:
                   18074:        mov.b           1+EXC_OPWORD(%a6),%d1   # fetch lo opword
                   18075:        mov.l           %d1,%d0                 # make a copy
                   18076:        andi.b          &0x38,%d1               # extract src mode
                   18077:
                   18078:        bne.b           fscc_mem_op             # it's a memory operation
                   18079:
                   18080:        mov.l           %d0,%d1
                   18081:        andi.w          &0x7,%d1                # pass index in d1
                   18082:        mov.l           %a0,%d0                 # pass result in d0
                   18083:        bsr.l           store_dreg_b            # save result in regfile
                   18084:        rts
                   18085:
                   18086: #
                   18087: # the stacked <ea> is correct with the exception of:
                   18088: #      -> Dn : <ea> is garbage
                   18089: #
                   18090: # if the addressing mode is post-increment or pre-decrement,
                   18091: # then the address registers have not been updated.
                   18092: #
                   18093: fscc_mem_op:
                   18094:        cmpi.b          %d1,&0x18               # is <ea> (An)+ ?
                   18095:        beq.b           fscc_mem_inc            # yes
                   18096:        cmpi.b          %d1,&0x20               # is <ea> -(An) ?
                   18097:        beq.b           fscc_mem_dec            # yes
                   18098:
                   18099:        mov.l           %a0,%d0                 # pass result in d0
                   18100:        mov.l           EXC_EA(%a6),%a0         # fetch <ea>
                   18101:        bsr.l           _dmem_write_byte        # write result byte
                   18102:
                   18103:        tst.l           %d1                     # did dstore fail?
                   18104:        bne.w           fscc_err                # yes
                   18105:
                   18106:        rts
                   18107:
                   18108: # addresing mode is post-increment. write the result byte. if the write
                   18109: # fails then don't update the address register. if write passes then
                   18110: # call inc_areg() to update the address register.
                   18111: fscc_mem_inc:
                   18112:        mov.l           %a0,%d0                 # pass result in d0
                   18113:        mov.l           EXC_EA(%a6),%a0         # fetch <ea>
                   18114:        bsr.l           _dmem_write_byte        # write result byte
                   18115:
                   18116:        tst.l           %d1                     # did dstore fail?
                   18117:        bne.w           fscc_err                # yes
                   18118:
                   18119:        mov.b           0x1+EXC_OPWORD(%a6),%d1 # fetch opword
                   18120:        andi.w          &0x7,%d1                # pass index in d1
                   18121:        movq.l          &0x1,%d0                # pass amt to inc by
                   18122:        bsr.l           inc_areg                # increment address register
                   18123:
                   18124:        rts
                   18125:
                   18126: # addressing mode is pre-decrement. write the result byte. if the write
                   18127: # fails then don't update the address register. if the write passes then
                   18128: # call dec_areg() to update the address register.
                   18129: fscc_mem_dec:
                   18130:        mov.l           %a0,%d0                 # pass result in d0
                   18131:        mov.l           EXC_EA(%a6),%a0         # fetch <ea>
                   18132:        bsr.l           _dmem_write_byte        # write result byte
                   18133:
                   18134:        tst.l           %d1                     # did dstore fail?
                   18135:        bne.w           fscc_err                # yes
                   18136:
                   18137:        mov.b           0x1+EXC_OPWORD(%a6),%d1 # fetch opword
                   18138:        andi.w          &0x7,%d1                # pass index in d1
                   18139:        movq.l          &0x1,%d0                # pass amt to dec by
                   18140:        bsr.l           dec_areg                # decrement address register
                   18141:
                   18142:        rts
                   18143:
                   18144: # the emulation routine set bsun and BSUN was enabled. have to
                   18145: # fix stack and jump to the bsun handler.
                   18146: # let the caller of this routine shift the stack frame up to
                   18147: # eliminate the effective address field.
                   18148: fscc_bsun:
                   18149:        mov.b           &fbsun_flg,SPCOND_FLG(%a6)
                   18150:        rts
                   18151:
                   18152: # the byte write to memory has failed. pass the failing effective address
                   18153: # and a FSLW to funimp_dacc().
                   18154: fscc_err:
                   18155:        mov.w           &0x00a1,EXC_VOFF(%a6)
                   18156:        bra.l           facc_finish
                   18157:
                   18158: #########################################################################
                   18159: # XDEF ****************************************************************        #
                   18160: #      fmovm_dynamic(): emulate "fmovm" dynamic instruction            #
                   18161: #                                                                      #
                   18162: # XREF ****************************************************************        #
                   18163: #      fetch_dreg() - fetch data register                              #
                   18164: #      {i,d,}mem_read() - fetch data from memory                       #
                   18165: #      _mem_write() - write data to memory                             #
                   18166: #      iea_iacc() - instruction memory access error occurred           #
                   18167: #      iea_dacc() - data memory access error occurred                  #
                   18168: #      restore() - restore An index regs if access error occurred      #
                   18169: #                                                                      #
                   18170: # INPUT ***************************************************************        #
                   18171: #      None                                                            #
                   18172: #                                                                      #
                   18173: # OUTPUT **************************************************************        #
                   18174: #      If instr is "fmovm Dn,-(A7)" from supervisor mode,              #
                   18175: #              d0 = size of dump                                       #
                   18176: #              d1 = Dn                                                 #
                   18177: #      Else if instruction access error,                               #
                   18178: #              d0 = FSLW                                               #
                   18179: #      Else if data access error,                                      #
                   18180: #              d0 = FSLW                                               #
                   18181: #              a0 = address of fault                                   #
                   18182: #      Else                                                            #
                   18183: #              none.                                                   #
                   18184: #                                                                      #
                   18185: # ALGORITHM ***********************************************************        #
                   18186: #      The effective address must be calculated since this is entered  #
                   18187: # from an "Unimplemented Effective Address" exception handler. So, we  #
                   18188: # have our own fcalc_ea() routine here. If an access error is flagged  #
                   18189: # by a _{i,d,}mem_read() call, we must exit through the special                #
                   18190: # handler.                                                             #
                   18191: #      The data register is determined and its value loaded to get the #
                   18192: # string of FP registers affected. This value is used as an index into #
                   18193: # a lookup table such that we can determine the number of bytes                #
                   18194: # involved.                                                            #
                   18195: #      If the instruction is "fmovm.x <ea>,Dn", a _mem_read() is used  #
                   18196: # to read in all FP values. Again, _mem_read() may fail and require a  #
                   18197: # special exit.                                                        #
                   18198: #      If the instruction is "fmovm.x DN,<ea>", a _mem_write() is used #
                   18199: # to write all FP values. _mem_write() may also fail.                  #
                   18200: #      If the instruction is "fmovm.x DN,-(a7)" from supervisor mode,  #
                   18201: # then we return the size of the dump and the string to the caller     #
                   18202: # so that the move can occur outside of this routine. This special     #
                   18203: # case is required so that moves to the system stack are handled       #
                   18204: # correctly.                                                           #
                   18205: #                                                                      #
                   18206: # DYNAMIC:                                                             #
                   18207: #      fmovm.x dn, <ea>                                                #
                   18208: #      fmovm.x <ea>, dn                                                #
                   18209: #                                                                      #
                   18210: #            <WORD 1>                <WORD2>                           #
                   18211: #      1111 0010 00 |<ea>|     11@& 1000 0$$$ 0000                     #
                   18212: #                                                                      #
                   18213: #      & = (0): predecrement addressing mode                           #
                   18214: #          (1): postincrement or control addressing mode               #
                   18215: #      @ = (0): move listed regs from memory to the FPU                #
                   18216: #          (1): move listed regs from the FPU to memory                #
                   18217: #      $$$    : index of data register holding reg select mask         #
                   18218: #                                                                      #
                   18219: # NOTES:                                                               #
                   18220: #      If the data register holds a zero, then the                     #
                   18221: #      instruction is a nop.                                           #
                   18222: #                                                                      #
                   18223: #########################################################################
                   18224:
                   18225:        global          fmovm_dynamic
                   18226: fmovm_dynamic:
                   18227:
                   18228: # extract the data register in which the bit string resides...
                   18229:        mov.b           1+EXC_EXTWORD(%a6),%d1  # fetch extword
                   18230:        andi.w          &0x70,%d1               # extract reg bits
                   18231:        lsr.b           &0x4,%d1                # shift into lo bits
                   18232:
                   18233: # fetch the bit string into d0...
                   18234:        bsr.l           fetch_dreg              # fetch reg string
                   18235:
                   18236:        andi.l          &0x000000ff,%d0         # keep only lo byte
                   18237:
                   18238:        mov.l           %d0,-(%sp)              # save strg
                   18239:        mov.b           (tbl_fmovm_size.w,%pc,%d0),%d0
                   18240:        mov.l           %d0,-(%sp)              # save size
                   18241:        bsr.l           fmovm_calc_ea           # calculate <ea>
                   18242:        mov.l           (%sp)+,%d0              # restore size
                   18243:        mov.l           (%sp)+,%d1              # restore strg
                   18244:
                   18245: # if the bit string is a zero, then the operation is a no-op
                   18246: # but, make sure that we've calculated ea and advanced the opword pointer
                   18247:        beq.w           fmovm_data_done
                   18248:
                   18249: # separate move ins from move outs...
                   18250:        btst            &0x5,EXC_EXTWORD(%a6)   # is it a move in or out?
                   18251:        beq.w           fmovm_data_in           # it's a move out
                   18252:
                   18253: #############
                   18254: # MOVE OUT: #
                   18255: #############
                   18256: fmovm_data_out:
                   18257:        btst            &0x4,EXC_EXTWORD(%a6)   # control or predecrement?
                   18258:        bne.w           fmovm_out_ctrl          # control
                   18259:
                   18260: ############################
                   18261: fmovm_out_predec:
                   18262: # for predecrement mode, the bit string is the opposite of both control
                   18263: # operations and postincrement mode. (bit7 = FP7 ... bit0 = FP0)
                   18264: # here, we convert it to be just like the others...
                   18265:        mov.b           (tbl_fmovm_convert.w,%pc,%d1.w*1),%d1
                   18266:
                   18267:        btst            &0x5,EXC_SR(%a6)        # user or supervisor mode?
                   18268:        beq.b           fmovm_out_ctrl          # user
                   18269:
                   18270: fmovm_out_predec_s:
                   18271:        cmpi.b          SPCOND_FLG(%a6),&mda7_flg # is <ea> mode -(a7)?
                   18272:        bne.b           fmovm_out_ctrl
                   18273:
                   18274: # the operation was unfortunately an: fmovm.x dn,-(sp)
                   18275: # called from supervisor mode.
                   18276: # we're also passing "size" and "strg" back to the calling routine
                   18277:        rts
                   18278:
                   18279: ############################
                   18280: fmovm_out_ctrl:
                   18281:        mov.l           %a0,%a1                 # move <ea> to a1
                   18282:
                   18283:        sub.l           %d0,%sp                 # subtract size of dump
                   18284:        lea             (%sp),%a0
                   18285:
                   18286:        tst.b           %d1                     # should FP0 be moved?
                   18287:        bpl.b           fmovm_out_ctrl_fp1      # no
                   18288:
                   18289:        mov.l           0x0+EXC_FP0(%a6),(%a0)+ # yes
                   18290:        mov.l           0x4+EXC_FP0(%a6),(%a0)+
                   18291:        mov.l           0x8+EXC_FP0(%a6),(%a0)+
                   18292:
                   18293: fmovm_out_ctrl_fp1:
                   18294:        lsl.b           &0x1,%d1                # should FP1 be moved?
                   18295:        bpl.b           fmovm_out_ctrl_fp2      # no
                   18296:
                   18297:        mov.l           0x0+EXC_FP1(%a6),(%a0)+ # yes
                   18298:        mov.l           0x4+EXC_FP1(%a6),(%a0)+
                   18299:        mov.l           0x8+EXC_FP1(%a6),(%a0)+
                   18300:
                   18301: fmovm_out_ctrl_fp2:
                   18302:        lsl.b           &0x1,%d1                # should FP2 be moved?
                   18303:        bpl.b           fmovm_out_ctrl_fp3      # no
                   18304:
                   18305:        fmovm.x         &0x20,(%a0)             # yes
                   18306:        add.l           &0xc,%a0
                   18307:
                   18308: fmovm_out_ctrl_fp3:
                   18309:        lsl.b           &0x1,%d1                # should FP3 be moved?
                   18310:        bpl.b           fmovm_out_ctrl_fp4      # no
                   18311:
                   18312:        fmovm.x         &0x10,(%a0)             # yes
                   18313:        add.l           &0xc,%a0
                   18314:
                   18315: fmovm_out_ctrl_fp4:
                   18316:        lsl.b           &0x1,%d1                # should FP4 be moved?
                   18317:        bpl.b           fmovm_out_ctrl_fp5      # no
                   18318:
                   18319:        fmovm.x         &0x08,(%a0)             # yes
                   18320:        add.l           &0xc,%a0
                   18321:
                   18322: fmovm_out_ctrl_fp5:
                   18323:        lsl.b           &0x1,%d1                # should FP5 be moved?
                   18324:        bpl.b           fmovm_out_ctrl_fp6      # no
                   18325:
                   18326:        fmovm.x         &0x04,(%a0)             # yes
                   18327:        add.l           &0xc,%a0
                   18328:
                   18329: fmovm_out_ctrl_fp6:
                   18330:        lsl.b           &0x1,%d1                # should FP6 be moved?
                   18331:        bpl.b           fmovm_out_ctrl_fp7      # no
                   18332:
                   18333:        fmovm.x         &0x02,(%a0)             # yes
                   18334:        add.l           &0xc,%a0
                   18335:
                   18336: fmovm_out_ctrl_fp7:
                   18337:        lsl.b           &0x1,%d1                # should FP7 be moved?
                   18338:        bpl.b           fmovm_out_ctrl_done     # no
                   18339:
                   18340:        fmovm.x         &0x01,(%a0)             # yes
                   18341:        add.l           &0xc,%a0
                   18342:
                   18343: fmovm_out_ctrl_done:
                   18344:        mov.l           %a1,L_SCR1(%a6)
                   18345:
                   18346:        lea             (%sp),%a0               # pass: supervisor src
                   18347:        mov.l           %d0,-(%sp)              # save size
                   18348:        bsr.l           _dmem_write             # copy data to user mem
                   18349:
                   18350:        mov.l           (%sp)+,%d0
                   18351:        add.l           %d0,%sp                 # clear fpreg data from stack
                   18352:
                   18353:        tst.l           %d1                     # did dstore err?
                   18354:        bne.w           fmovm_out_err           # yes
                   18355:
                   18356:        rts
                   18357:
                   18358: ############
                   18359: # MOVE IN: #
                   18360: ############
                   18361: fmovm_data_in:
                   18362:        mov.l           %a0,L_SCR1(%a6)
                   18363:
                   18364:        sub.l           %d0,%sp                 # make room for fpregs
                   18365:        lea             (%sp),%a1
                   18366:
                   18367:        mov.l           %d1,-(%sp)              # save bit string for later
                   18368:        mov.l           %d0,-(%sp)              # save # of bytes
                   18369:
                   18370:        bsr.l           _dmem_read              # copy data from user mem
                   18371:
                   18372:        mov.l           (%sp)+,%d0              # retrieve # of bytes
                   18373:
                   18374:        tst.l           %d1                     # did dfetch fail?
                   18375:        bne.w           fmovm_in_err            # yes
                   18376:
                   18377:        mov.l           (%sp)+,%d1              # load bit string
                   18378:
                   18379:        lea             (%sp),%a0               # addr of stack
                   18380:
                   18381:        tst.b           %d1                     # should FP0 be moved?
                   18382:        bpl.b           fmovm_data_in_fp1       # no
                   18383:
                   18384:        mov.l           (%a0)+,0x0+EXC_FP0(%a6) # yes
                   18385:        mov.l           (%a0)+,0x4+EXC_FP0(%a6)
                   18386:        mov.l           (%a0)+,0x8+EXC_FP0(%a6)
                   18387:
                   18388: fmovm_data_in_fp1:
                   18389:        lsl.b           &0x1,%d1                # should FP1 be moved?
                   18390:        bpl.b           fmovm_data_in_fp2       # no
                   18391:
                   18392:        mov.l           (%a0)+,0x0+EXC_FP1(%a6) # yes
                   18393:        mov.l           (%a0)+,0x4+EXC_FP1(%a6)
                   18394:        mov.l           (%a0)+,0x8+EXC_FP1(%a6)
                   18395:
                   18396: fmovm_data_in_fp2:
                   18397:        lsl.b           &0x1,%d1                # should FP2 be moved?
                   18398:        bpl.b           fmovm_data_in_fp3       # no
                   18399:
                   18400:        fmovm.x         (%a0)+,&0x20            # yes
                   18401:
                   18402: fmovm_data_in_fp3:
                   18403:        lsl.b           &0x1,%d1                # should FP3 be moved?
                   18404:        bpl.b           fmovm_data_in_fp4       # no
                   18405:
                   18406:        fmovm.x         (%a0)+,&0x10            # yes
                   18407:
                   18408: fmovm_data_in_fp4:
                   18409:        lsl.b           &0x1,%d1                # should FP4 be moved?
                   18410:        bpl.b           fmovm_data_in_fp5       # no
                   18411:
                   18412:        fmovm.x         (%a0)+,&0x08            # yes
                   18413:
                   18414: fmovm_data_in_fp5:
                   18415:        lsl.b           &0x1,%d1                # should FP5 be moved?
                   18416:        bpl.b           fmovm_data_in_fp6       # no
                   18417:
                   18418:        fmovm.x         (%a0)+,&0x04            # yes
                   18419:
                   18420: fmovm_data_in_fp6:
                   18421:        lsl.b           &0x1,%d1                # should FP6 be moved?
                   18422:        bpl.b           fmovm_data_in_fp7       # no
                   18423:
                   18424:        fmovm.x         (%a0)+,&0x02            # yes
                   18425:
                   18426: fmovm_data_in_fp7:
                   18427:        lsl.b           &0x1,%d1                # should FP7 be moved?
                   18428:        bpl.b           fmovm_data_in_done      # no
                   18429:
                   18430:        fmovm.x         (%a0)+,&0x01            # yes
                   18431:
                   18432: fmovm_data_in_done:
                   18433:        add.l           %d0,%sp                 # remove fpregs from stack
                   18434:        rts
                   18435:
                   18436: #####################################
                   18437:
                   18438: fmovm_data_done:
                   18439:        rts
                   18440:
                   18441: ##############################################################################
                   18442:
                   18443: #
                   18444: # table indexed by the operation's bit string that gives the number
                   18445: # of bytes that will be moved.
                   18446: #
                   18447: # number of bytes = (# of 1's in bit string) * 12(bytes/fpreg)
                   18448: #
                   18449: tbl_fmovm_size:
                   18450:        byte    0x00,0x0c,0x0c,0x18,0x0c,0x18,0x18,0x24
                   18451:        byte    0x0c,0x18,0x18,0x24,0x18,0x24,0x24,0x30
                   18452:        byte    0x0c,0x18,0x18,0x24,0x18,0x24,0x24,0x30
                   18453:        byte    0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
                   18454:        byte    0x0c,0x18,0x18,0x24,0x18,0x24,0x24,0x30
                   18455:        byte    0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
                   18456:        byte    0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
                   18457:        byte    0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
                   18458:        byte    0x0c,0x18,0x18,0x24,0x18,0x24,0x24,0x30
                   18459:        byte    0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
                   18460:        byte    0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
                   18461:        byte    0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
                   18462:        byte    0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
                   18463:        byte    0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
                   18464:        byte    0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
                   18465:        byte    0x30,0x3c,0x3c,0x48,0x3c,0x48,0x48,0x54
                   18466:        byte    0x0c,0x18,0x18,0x24,0x18,0x24,0x24,0x30
                   18467:        byte    0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
                   18468:        byte    0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
                   18469:        byte    0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
                   18470:        byte    0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
                   18471:        byte    0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
                   18472:        byte    0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
                   18473:        byte    0x30,0x3c,0x3c,0x48,0x3c,0x48,0x48,0x54
                   18474:        byte    0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
                   18475:        byte    0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
                   18476:        byte    0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
                   18477:        byte    0x30,0x3c,0x3c,0x48,0x3c,0x48,0x48,0x54
                   18478:        byte    0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
                   18479:        byte    0x30,0x3c,0x3c,0x48,0x3c,0x48,0x48,0x54
                   18480:        byte    0x30,0x3c,0x3c,0x48,0x3c,0x48,0x48,0x54
                   18481:        byte    0x3c,0x48,0x48,0x54,0x48,0x54,0x54,0x60
                   18482:
                   18483: #
                   18484: # table to convert a pre-decrement bit string into a post-increment
                   18485: # or control bit string.
                   18486: # ex:  0x00    ==>     0x00
                   18487: #      0x01    ==>     0x80
                   18488: #      0x02    ==>     0x40
                   18489: #              .
                   18490: #              .
                   18491: #      0xfd    ==>     0xbf
                   18492: #      0xfe    ==>     0x7f
                   18493: #      0xff    ==>     0xff
                   18494: #
                   18495: tbl_fmovm_convert:
                   18496:        byte    0x00,0x80,0x40,0xc0,0x20,0xa0,0x60,0xe0
                   18497:        byte    0x10,0x90,0x50,0xd0,0x30,0xb0,0x70,0xf0
                   18498:        byte    0x08,0x88,0x48,0xc8,0x28,0xa8,0x68,0xe8
                   18499:        byte    0x18,0x98,0x58,0xd8,0x38,0xb8,0x78,0xf8
                   18500:        byte    0x04,0x84,0x44,0xc4,0x24,0xa4,0x64,0xe4
                   18501:        byte    0x14,0x94,0x54,0xd4,0x34,0xb4,0x74,0xf4
                   18502:        byte    0x0c,0x8c,0x4c,0xcc,0x2c,0xac,0x6c,0xec
                   18503:        byte    0x1c,0x9c,0x5c,0xdc,0x3c,0xbc,0x7c,0xfc
                   18504:        byte    0x02,0x82,0x42,0xc2,0x22,0xa2,0x62,0xe2
                   18505:        byte    0x12,0x92,0x52,0xd2,0x32,0xb2,0x72,0xf2
                   18506:        byte    0x0a,0x8a,0x4a,0xca,0x2a,0xaa,0x6a,0xea
                   18507:        byte    0x1a,0x9a,0x5a,0xda,0x3a,0xba,0x7a,0xfa
                   18508:        byte    0x06,0x86,0x46,0xc6,0x26,0xa6,0x66,0xe6
                   18509:        byte    0x16,0x96,0x56,0xd6,0x36,0xb6,0x76,0xf6
                   18510:        byte    0x0e,0x8e,0x4e,0xce,0x2e,0xae,0x6e,0xee
                   18511:        byte    0x1e,0x9e,0x5e,0xde,0x3e,0xbe,0x7e,0xfe
                   18512:        byte    0x01,0x81,0x41,0xc1,0x21,0xa1,0x61,0xe1
                   18513:        byte    0x11,0x91,0x51,0xd1,0x31,0xb1,0x71,0xf1
                   18514:        byte    0x09,0x89,0x49,0xc9,0x29,0xa9,0x69,0xe9
                   18515:        byte    0x19,0x99,0x59,0xd9,0x39,0xb9,0x79,0xf9
                   18516:        byte    0x05,0x85,0x45,0xc5,0x25,0xa5,0x65,0xe5
                   18517:        byte    0x15,0x95,0x55,0xd5,0x35,0xb5,0x75,0xf5
                   18518:        byte    0x0d,0x8d,0x4d,0xcd,0x2d,0xad,0x6d,0xed
                   18519:        byte    0x1d,0x9d,0x5d,0xdd,0x3d,0xbd,0x7d,0xfd
                   18520:        byte    0x03,0x83,0x43,0xc3,0x23,0xa3,0x63,0xe3
                   18521:        byte    0x13,0x93,0x53,0xd3,0x33,0xb3,0x73,0xf3
                   18522:        byte    0x0b,0x8b,0x4b,0xcb,0x2b,0xab,0x6b,0xeb
                   18523:        byte    0x1b,0x9b,0x5b,0xdb,0x3b,0xbb,0x7b,0xfb
                   18524:        byte    0x07,0x87,0x47,0xc7,0x27,0xa7,0x67,0xe7
                   18525:        byte    0x17,0x97,0x57,0xd7,0x37,0xb7,0x77,0xf7
                   18526:        byte    0x0f,0x8f,0x4f,0xcf,0x2f,0xaf,0x6f,0xef
                   18527:        byte    0x1f,0x9f,0x5f,0xdf,0x3f,0xbf,0x7f,0xff
                   18528:
                   18529:        global          fmovm_calc_ea
                   18530: ###############################################
                   18531: # _fmovm_calc_ea: calculate effective address #
                   18532: ###############################################
                   18533: fmovm_calc_ea:
                   18534:        mov.l           %d0,%a0                 # move # bytes to a0
                   18535:
                   18536: # currently, MODE and REG are taken from the EXC_OPWORD. this could be
                   18537: # easily changed if they were inputs passed in registers.
                   18538:        mov.w           EXC_OPWORD(%a6),%d0     # fetch opcode word
                   18539:        mov.w           %d0,%d1                 # make a copy
                   18540:
                   18541:        andi.w          &0x3f,%d0               # extract mode field
                   18542:        andi.l          &0x7,%d1                # extract reg  field
                   18543:
                   18544: # jump to the corresponding function for each {MODE,REG} pair.
                   18545:        mov.w           (tbl_fea_mode.b,%pc,%d0.w*2),%d0 # fetch jmp distance
                   18546:        jmp             (tbl_fea_mode.b,%pc,%d0.w*1) # jmp to correct ea mode
                   18547:
                   18548:        swbeg           &64
                   18549: tbl_fea_mode:
                   18550:        short           tbl_fea_mode    -       tbl_fea_mode
                   18551:        short           tbl_fea_mode    -       tbl_fea_mode
                   18552:        short           tbl_fea_mode    -       tbl_fea_mode
                   18553:        short           tbl_fea_mode    -       tbl_fea_mode
                   18554:        short           tbl_fea_mode    -       tbl_fea_mode
                   18555:        short           tbl_fea_mode    -       tbl_fea_mode
                   18556:        short           tbl_fea_mode    -       tbl_fea_mode
                   18557:        short           tbl_fea_mode    -       tbl_fea_mode
                   18558:
                   18559:        short           tbl_fea_mode    -       tbl_fea_mode
                   18560:        short           tbl_fea_mode    -       tbl_fea_mode
                   18561:        short           tbl_fea_mode    -       tbl_fea_mode
                   18562:        short           tbl_fea_mode    -       tbl_fea_mode
                   18563:        short           tbl_fea_mode    -       tbl_fea_mode
                   18564:        short           tbl_fea_mode    -       tbl_fea_mode
                   18565:        short           tbl_fea_mode    -       tbl_fea_mode
                   18566:        short           tbl_fea_mode    -       tbl_fea_mode
                   18567:
                   18568:        short           faddr_ind_a0    -       tbl_fea_mode
                   18569:        short           faddr_ind_a1    -       tbl_fea_mode
                   18570:        short           faddr_ind_a2    -       tbl_fea_mode
                   18571:        short           faddr_ind_a3    -       tbl_fea_mode
                   18572:        short           faddr_ind_a4    -       tbl_fea_mode
                   18573:        short           faddr_ind_a5    -       tbl_fea_mode
                   18574:        short           faddr_ind_a6    -       tbl_fea_mode
                   18575:        short           faddr_ind_a7    -       tbl_fea_mode
                   18576:
                   18577:        short           faddr_ind_p_a0  -       tbl_fea_mode
                   18578:        short           faddr_ind_p_a1  -       tbl_fea_mode
                   18579:        short           faddr_ind_p_a2  -       tbl_fea_mode
                   18580:        short           faddr_ind_p_a3  -       tbl_fea_mode
                   18581:        short           faddr_ind_p_a4  -       tbl_fea_mode
                   18582:        short           faddr_ind_p_a5  -       tbl_fea_mode
                   18583:        short           faddr_ind_p_a6  -       tbl_fea_mode
                   18584:        short           faddr_ind_p_a7  -       tbl_fea_mode
                   18585:
                   18586:        short           faddr_ind_m_a0  -       tbl_fea_mode
                   18587:        short           faddr_ind_m_a1  -       tbl_fea_mode
                   18588:        short           faddr_ind_m_a2  -       tbl_fea_mode
                   18589:        short           faddr_ind_m_a3  -       tbl_fea_mode
                   18590:        short           faddr_ind_m_a4  -       tbl_fea_mode
                   18591:        short           faddr_ind_m_a5  -       tbl_fea_mode
                   18592:        short           faddr_ind_m_a6  -       tbl_fea_mode
                   18593:        short           faddr_ind_m_a7  -       tbl_fea_mode
                   18594:
                   18595:        short           faddr_ind_disp_a0       -       tbl_fea_mode
                   18596:        short           faddr_ind_disp_a1       -       tbl_fea_mode
                   18597:        short           faddr_ind_disp_a2       -       tbl_fea_mode
                   18598:        short           faddr_ind_disp_a3       -       tbl_fea_mode
                   18599:        short           faddr_ind_disp_a4       -       tbl_fea_mode
                   18600:        short           faddr_ind_disp_a5       -       tbl_fea_mode
                   18601:        short           faddr_ind_disp_a6       -       tbl_fea_mode
                   18602:        short           faddr_ind_disp_a7       -       tbl_fea_mode
                   18603:
                   18604:        short           faddr_ind_ext   -       tbl_fea_mode
                   18605:        short           faddr_ind_ext   -       tbl_fea_mode
                   18606:        short           faddr_ind_ext   -       tbl_fea_mode
                   18607:        short           faddr_ind_ext   -       tbl_fea_mode
                   18608:        short           faddr_ind_ext   -       tbl_fea_mode
                   18609:        short           faddr_ind_ext   -       tbl_fea_mode
                   18610:        short           faddr_ind_ext   -       tbl_fea_mode
                   18611:        short           faddr_ind_ext   -       tbl_fea_mode
                   18612:
                   18613:        short           fabs_short      -       tbl_fea_mode
                   18614:        short           fabs_long       -       tbl_fea_mode
                   18615:        short           fpc_ind         -       tbl_fea_mode
                   18616:        short           fpc_ind_ext     -       tbl_fea_mode
                   18617:        short           tbl_fea_mode    -       tbl_fea_mode
                   18618:        short           tbl_fea_mode    -       tbl_fea_mode
                   18619:        short           tbl_fea_mode    -       tbl_fea_mode
                   18620:        short           tbl_fea_mode    -       tbl_fea_mode
                   18621:
                   18622: ###################################
                   18623: # Address register indirect: (An) #
                   18624: ###################################
                   18625: faddr_ind_a0:
                   18626:        mov.l           EXC_DREGS+0x8(%a6),%a0  # Get current a0
                   18627:        rts
                   18628:
                   18629: faddr_ind_a1:
                   18630:        mov.l           EXC_DREGS+0xc(%a6),%a0  # Get current a1
                   18631:        rts
                   18632:
                   18633: faddr_ind_a2:
                   18634:        mov.l           %a2,%a0                 # Get current a2
                   18635:        rts
                   18636:
                   18637: faddr_ind_a3:
                   18638:        mov.l           %a3,%a0                 # Get current a3
                   18639:        rts
                   18640:
                   18641: faddr_ind_a4:
                   18642:        mov.l           %a4,%a0                 # Get current a4
                   18643:        rts
                   18644:
                   18645: faddr_ind_a5:
                   18646:        mov.l           %a5,%a0                 # Get current a5
                   18647:        rts
                   18648:
                   18649: faddr_ind_a6:
                   18650:        mov.l           (%a6),%a0               # Get current a6
                   18651:        rts
                   18652:
                   18653: faddr_ind_a7:
                   18654:        mov.l           EXC_A7(%a6),%a0         # Get current a7
                   18655:        rts
                   18656:
                   18657: #####################################################
                   18658: # Address register indirect w/ postincrement: (An)+ #
                   18659: #####################################################
                   18660: faddr_ind_p_a0:
                   18661:        mov.l           EXC_DREGS+0x8(%a6),%d0  # Get current a0
                   18662:        mov.l           %d0,%d1
                   18663:        add.l           %a0,%d1                 # Increment
                   18664:        mov.l           %d1,EXC_DREGS+0x8(%a6)  # Save incr value
                   18665:        mov.l           %d0,%a0
                   18666:        rts
                   18667:
                   18668: faddr_ind_p_a1:
                   18669:        mov.l           EXC_DREGS+0xc(%a6),%d0  # Get current a1
                   18670:        mov.l           %d0,%d1
                   18671:        add.l           %a0,%d1                 # Increment
                   18672:        mov.l           %d1,EXC_DREGS+0xc(%a6)  # Save incr value
                   18673:        mov.l           %d0,%a0
                   18674:        rts
                   18675:
                   18676: faddr_ind_p_a2:
                   18677:        mov.l           %a2,%d0                 # Get current a2
                   18678:        mov.l           %d0,%d1
                   18679:        add.l           %a0,%d1                 # Increment
                   18680:        mov.l           %d1,%a2                 # Save incr value
                   18681:        mov.l           %d0,%a0
                   18682:        rts
                   18683:
                   18684: faddr_ind_p_a3:
                   18685:        mov.l           %a3,%d0                 # Get current a3
                   18686:        mov.l           %d0,%d1
                   18687:        add.l           %a0,%d1                 # Increment
                   18688:        mov.l           %d1,%a3                 # Save incr value
                   18689:        mov.l           %d0,%a0
                   18690:        rts
                   18691:
                   18692: faddr_ind_p_a4:
                   18693:        mov.l           %a4,%d0                 # Get current a4
                   18694:        mov.l           %d0,%d1
                   18695:        add.l           %a0,%d1                 # Increment
                   18696:        mov.l           %d1,%a4                 # Save incr value
                   18697:        mov.l           %d0,%a0
                   18698:        rts
                   18699:
                   18700: faddr_ind_p_a5:
                   18701:        mov.l           %a5,%d0                 # Get current a5
                   18702:        mov.l           %d0,%d1
                   18703:        add.l           %a0,%d1                 # Increment
                   18704:        mov.l           %d1,%a5                 # Save incr value
                   18705:        mov.l           %d0,%a0
                   18706:        rts
                   18707:
                   18708: faddr_ind_p_a6:
                   18709:        mov.l           (%a6),%d0               # Get current a6
                   18710:        mov.l           %d0,%d1
                   18711:        add.l           %a0,%d1                 # Increment
                   18712:        mov.l           %d1,(%a6)               # Save incr value
                   18713:        mov.l           %d0,%a0
                   18714:        rts
                   18715:
                   18716: faddr_ind_p_a7:
                   18717:        mov.b           &mia7_flg,SPCOND_FLG(%a6) # set "special case" flag
                   18718:
                   18719:        mov.l           EXC_A7(%a6),%d0         # Get current a7
                   18720:        mov.l           %d0,%d1
                   18721:        add.l           %a0,%d1                 # Increment
                   18722:        mov.l           %d1,EXC_A7(%a6)         # Save incr value
                   18723:        mov.l           %d0,%a0
                   18724:        rts
                   18725:
                   18726: ####################################################
                   18727: # Address register indirect w/ predecrement: -(An) #
                   18728: ####################################################
                   18729: faddr_ind_m_a0:
                   18730:        mov.l           EXC_DREGS+0x8(%a6),%d0  # Get current a0
                   18731:        sub.l           %a0,%d0                 # Decrement
                   18732:        mov.l           %d0,EXC_DREGS+0x8(%a6)  # Save decr value
                   18733:        mov.l           %d0,%a0
                   18734:        rts
                   18735:
                   18736: faddr_ind_m_a1:
                   18737:        mov.l           EXC_DREGS+0xc(%a6),%d0  # Get current a1
                   18738:        sub.l           %a0,%d0                 # Decrement
                   18739:        mov.l           %d0,EXC_DREGS+0xc(%a6)  # Save decr value
                   18740:        mov.l           %d0,%a0
                   18741:        rts
                   18742:
                   18743: faddr_ind_m_a2:
                   18744:        mov.l           %a2,%d0                 # Get current a2
                   18745:        sub.l           %a0,%d0                 # Decrement
                   18746:        mov.l           %d0,%a2                 # Save decr value
                   18747:        mov.l           %d0,%a0
                   18748:        rts
                   18749:
                   18750: faddr_ind_m_a3:
                   18751:        mov.l           %a3,%d0                 # Get current a3
                   18752:        sub.l           %a0,%d0                 # Decrement
                   18753:        mov.l           %d0,%a3                 # Save decr value
                   18754:        mov.l           %d0,%a0
                   18755:        rts
                   18756:
                   18757: faddr_ind_m_a4:
                   18758:        mov.l           %a4,%d0                 # Get current a4
                   18759:        sub.l           %a0,%d0                 # Decrement
                   18760:        mov.l           %d0,%a4                 # Save decr value
                   18761:        mov.l           %d0,%a0
                   18762:        rts
                   18763:
                   18764: faddr_ind_m_a5:
                   18765:        mov.l           %a5,%d0                 # Get current a5
                   18766:        sub.l           %a0,%d0                 # Decrement
                   18767:        mov.l           %d0,%a5                 # Save decr value
                   18768:        mov.l           %d0,%a0
                   18769:        rts
                   18770:
                   18771: faddr_ind_m_a6:
                   18772:        mov.l           (%a6),%d0               # Get current a6
                   18773:        sub.l           %a0,%d0                 # Decrement
                   18774:        mov.l           %d0,(%a6)               # Save decr value
                   18775:        mov.l           %d0,%a0
                   18776:        rts
                   18777:
                   18778: faddr_ind_m_a7:
                   18779:        mov.b           &mda7_flg,SPCOND_FLG(%a6) # set "special case" flag
                   18780:
                   18781:        mov.l           EXC_A7(%a6),%d0         # Get current a7
                   18782:        sub.l           %a0,%d0                 # Decrement
                   18783:        mov.l           %d0,EXC_A7(%a6)         # Save decr value
                   18784:        mov.l           %d0,%a0
                   18785:        rts
                   18786:
                   18787: ########################################################
                   18788: # Address register indirect w/ displacement: (d16, An) #
                   18789: ########################################################
                   18790: faddr_ind_disp_a0:
                   18791:        mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
                   18792:        addq.l          &0x2,EXC_EXTWPTR(%a6)   # incr instruction ptr
                   18793:        bsr.l           _imem_read_word
                   18794:
                   18795:        tst.l           %d1                     # did ifetch fail?
                   18796:        bne.l           iea_iacc                # yes
                   18797:
                   18798:        mov.w           %d0,%a0                 # sign extend displacement
                   18799:
                   18800:        add.l           EXC_DREGS+0x8(%a6),%a0  # a0 + d16
                   18801:        rts
                   18802:
                   18803: faddr_ind_disp_a1:
                   18804:        mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
                   18805:        addq.l          &0x2,EXC_EXTWPTR(%a6)   # incr instruction ptr
                   18806:        bsr.l           _imem_read_word
                   18807:
                   18808:        tst.l           %d1                     # did ifetch fail?
                   18809:        bne.l           iea_iacc                # yes
                   18810:
                   18811:        mov.w           %d0,%a0                 # sign extend displacement
                   18812:
                   18813:        add.l           EXC_DREGS+0xc(%a6),%a0  # a1 + d16
                   18814:        rts
                   18815:
                   18816: faddr_ind_disp_a2:
                   18817:        mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
                   18818:        addq.l          &0x2,EXC_EXTWPTR(%a6)   # incr instruction ptr
                   18819:        bsr.l           _imem_read_word
                   18820:
                   18821:        tst.l           %d1                     # did ifetch fail?
                   18822:        bne.l           iea_iacc                # yes
                   18823:
                   18824:        mov.w           %d0,%a0                 # sign extend displacement
                   18825:
                   18826:        add.l           %a2,%a0                 # a2 + d16
                   18827:        rts
                   18828:
                   18829: faddr_ind_disp_a3:
                   18830:        mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
                   18831:        addq.l          &0x2,EXC_EXTWPTR(%a6)   # incr instruction ptr
                   18832:        bsr.l           _imem_read_word
                   18833:
                   18834:        tst.l           %d1                     # did ifetch fail?
                   18835:        bne.l           iea_iacc                # yes
                   18836:
                   18837:        mov.w           %d0,%a0                 # sign extend displacement
                   18838:
                   18839:        add.l           %a3,%a0                 # a3 + d16
                   18840:        rts
                   18841:
                   18842: faddr_ind_disp_a4:
                   18843:        mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
                   18844:        addq.l          &0x2,EXC_EXTWPTR(%a6)   # incr instruction ptr
                   18845:        bsr.l           _imem_read_word
                   18846:
                   18847:        tst.l           %d1                     # did ifetch fail?
                   18848:        bne.l           iea_iacc                # yes
                   18849:
                   18850:        mov.w           %d0,%a0                 # sign extend displacement
                   18851:
                   18852:        add.l           %a4,%a0                 # a4 + d16
                   18853:        rts
                   18854:
                   18855: faddr_ind_disp_a5:
                   18856:        mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
                   18857:        addq.l          &0x2,EXC_EXTWPTR(%a6)   # incr instruction ptr
                   18858:        bsr.l           _imem_read_word
                   18859:
                   18860:        tst.l           %d1                     # did ifetch fail?
                   18861:        bne.l           iea_iacc                # yes
                   18862:
                   18863:        mov.w           %d0,%a0                 # sign extend displacement
                   18864:
                   18865:        add.l           %a5,%a0                 # a5 + d16
                   18866:        rts
                   18867:
                   18868: faddr_ind_disp_a6:
                   18869:        mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
                   18870:        addq.l          &0x2,EXC_EXTWPTR(%a6)   # incr instruction ptr
                   18871:        bsr.l           _imem_read_word
                   18872:
                   18873:        tst.l           %d1                     # did ifetch fail?
                   18874:        bne.l           iea_iacc                # yes
                   18875:
                   18876:        mov.w           %d0,%a0                 # sign extend displacement
                   18877:
                   18878:        add.l           (%a6),%a0               # a6 + d16
                   18879:        rts
                   18880:
                   18881: faddr_ind_disp_a7:
                   18882:        mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
                   18883:        addq.l          &0x2,EXC_EXTWPTR(%a6)   # incr instruction ptr
                   18884:        bsr.l           _imem_read_word
                   18885:
                   18886:        tst.l           %d1                     # did ifetch fail?
                   18887:        bne.l           iea_iacc                # yes
                   18888:
                   18889:        mov.w           %d0,%a0                 # sign extend displacement
                   18890:
                   18891:        add.l           EXC_A7(%a6),%a0         # a7 + d16
                   18892:        rts
                   18893:
                   18894: ########################################################################
                   18895: # Address register indirect w/ index(8-bit displacement): (d8, An, Xn) #
                   18896: #    "       "         "    w/   "  (base displacement): (bd, An, Xn)  #
                   18897: # Memory indirect postindexed: ([bd, An], Xn, od)                     #
                   18898: # Memory indirect preindexed: ([bd, An, Xn], od)                      #
                   18899: ########################################################################
                   18900: faddr_ind_ext:
                   18901:        addq.l          &0x8,%d1
                   18902:        bsr.l           fetch_dreg              # fetch base areg
                   18903:        mov.l           %d0,-(%sp)
                   18904:
                   18905:        mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
                   18906:        addq.l          &0x2,EXC_EXTWPTR(%a6)   # incr instruction ptr
                   18907:        bsr.l           _imem_read_word         # fetch extword in d0
                   18908:
                   18909:        tst.l           %d1                     # did ifetch fail?
                   18910:        bne.l           iea_iacc                # yes
                   18911:
                   18912:        mov.l           (%sp)+,%a0
                   18913:
                   18914:        btst            &0x8,%d0
                   18915:        bne.w           fcalc_mem_ind
                   18916:
                   18917:        mov.l           %d0,L_SCR1(%a6)         # hold opword
                   18918:
                   18919:        mov.l           %d0,%d1
                   18920:        rol.w           &0x4,%d1
                   18921:        andi.w          &0xf,%d1                # extract index regno
                   18922:
                   18923: # count on fetch_dreg() not to alter a0...
                   18924:        bsr.l           fetch_dreg              # fetch index
                   18925:
                   18926:        mov.l           %d2,-(%sp)              # save d2
                   18927:        mov.l           L_SCR1(%a6),%d2         # fetch opword
                   18928:
                   18929:        btst            &0xb,%d2                # is it word or long?
                   18930:        bne.b           faii8_long
                   18931:        ext.l           %d0                     # sign extend word index
                   18932: faii8_long:
                   18933:        mov.l           %d2,%d1
                   18934:        rol.w           &0x7,%d1
                   18935:        andi.l          &0x3,%d1                # extract scale value
                   18936:
                   18937:        lsl.l           %d1,%d0                 # shift index by scale
                   18938:
                   18939:        extb.l          %d2                     # sign extend displacement
                   18940:        add.l           %d2,%d0                 # index + disp
                   18941:        add.l           %d0,%a0                 # An + (index + disp)
                   18942:
                   18943:        mov.l           (%sp)+,%d2              # restore old d2
                   18944:        rts
                   18945:
                   18946: ###########################
                   18947: # Absolute short: (XXX).W #
                   18948: ###########################
                   18949: fabs_short:
                   18950:        mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
                   18951:        addq.l          &0x2,EXC_EXTWPTR(%a6)   # incr instruction ptr
                   18952:        bsr.l           _imem_read_word         # fetch short address
                   18953:
                   18954:        tst.l           %d1                     # did ifetch fail?
                   18955:        bne.l           iea_iacc                # yes
                   18956:
                   18957:        mov.w           %d0,%a0                 # return <ea> in a0
                   18958:        rts
                   18959:
                   18960: ##########################
                   18961: # Absolute long: (XXX).L #
                   18962: ##########################
                   18963: fabs_long:
                   18964:        mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
                   18965:        addq.l          &0x4,EXC_EXTWPTR(%a6)   # incr instruction ptr
                   18966:        bsr.l           _imem_read_long         # fetch long address
                   18967:
                   18968:        tst.l           %d1                     # did ifetch fail?
                   18969:        bne.l           iea_iacc                # yes
                   18970:
                   18971:        mov.l           %d0,%a0                 # return <ea> in a0
                   18972:        rts
                   18973:
                   18974: #######################################################
                   18975: # Program counter indirect w/ displacement: (d16, PC) #
                   18976: #######################################################
                   18977: fpc_ind:
                   18978:        mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
                   18979:        addq.l          &0x2,EXC_EXTWPTR(%a6)   # incr instruction ptr
                   18980:        bsr.l           _imem_read_word         # fetch word displacement
                   18981:
                   18982:        tst.l           %d1                     # did ifetch fail?
                   18983:        bne.l           iea_iacc                # yes
                   18984:
                   18985:        mov.w           %d0,%a0                 # sign extend displacement
                   18986:
                   18987:        add.l           EXC_EXTWPTR(%a6),%a0    # pc + d16
                   18988:
                   18989: # _imem_read_word() increased the extwptr by 2. need to adjust here.
                   18990:        subq.l          &0x2,%a0                # adjust <ea>
                   18991:        rts
                   18992:
                   18993: ##########################################################
                   18994: # PC indirect w/ index(8-bit displacement): (d8, PC, An) #
                   18995: # "     "     w/   "  (base displacement): (bd, PC, An)  #
                   18996: # PC memory indirect postindexed: ([bd, PC], Xn, od)     #
                   18997: # PC memory indirect preindexed: ([bd, PC, Xn], od)      #
                   18998: ##########################################################
                   18999: fpc_ind_ext:
                   19000:        mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
                   19001:        addq.l          &0x2,EXC_EXTWPTR(%a6)   # incr instruction ptr
                   19002:        bsr.l           _imem_read_word         # fetch ext word
                   19003:
                   19004:        tst.l           %d1                     # did ifetch fail?
                   19005:        bne.l           iea_iacc                # yes
                   19006:
                   19007:        mov.l           EXC_EXTWPTR(%a6),%a0    # put base in a0
                   19008:        subq.l          &0x2,%a0                # adjust base
                   19009:
                   19010:        btst            &0x8,%d0                # is disp only 8 bits?
                   19011:        bne.w           fcalc_mem_ind           # calc memory indirect
                   19012:
                   19013:        mov.l           %d0,L_SCR1(%a6)         # store opword
                   19014:
                   19015:        mov.l           %d0,%d1                 # make extword copy
                   19016:        rol.w           &0x4,%d1                # rotate reg num into place
                   19017:        andi.w          &0xf,%d1                # extract register number
                   19018:
                   19019: # count on fetch_dreg() not to alter a0...
                   19020:        bsr.l           fetch_dreg              # fetch index
                   19021:
                   19022:        mov.l           %d2,-(%sp)              # save d2
                   19023:        mov.l           L_SCR1(%a6),%d2         # fetch opword
                   19024:
                   19025:        btst            &0xb,%d2                # is index word or long?
                   19026:        bne.b           fpii8_long              # long
                   19027:        ext.l           %d0                     # sign extend word index
                   19028: fpii8_long:
                   19029:        mov.l           %d2,%d1
                   19030:        rol.w           &0x7,%d1                # rotate scale value into place
                   19031:        andi.l          &0x3,%d1                # extract scale value
                   19032:
                   19033:        lsl.l           %d1,%d0                 # shift index by scale
                   19034:
                   19035:        extb.l          %d2                     # sign extend displacement
                   19036:        add.l           %d2,%d0                 # disp + index
                   19037:        add.l           %d0,%a0                 # An + (index + disp)
                   19038:
                   19039:        mov.l           (%sp)+,%d2              # restore temp register
                   19040:        rts
                   19041:
                   19042: # d2 = index
                   19043: # d3 = base
                   19044: # d4 = od
                   19045: # d5 = extword
                   19046: fcalc_mem_ind:
                   19047:        btst            &0x6,%d0                # is the index suppressed?
                   19048:        beq.b           fcalc_index
                   19049:
                   19050:        movm.l          &0x3c00,-(%sp)          # save d2-d5
                   19051:
                   19052:        mov.l           %d0,%d5                 # put extword in d5
                   19053:        mov.l           %a0,%d3                 # put base in d3
                   19054:
                   19055:        clr.l           %d2                     # yes, so index = 0
                   19056:        bra.b           fbase_supp_ck
                   19057:
                   19058: # index:
                   19059: fcalc_index:
                   19060:        mov.l           %d0,L_SCR1(%a6)         # save d0 (opword)
                   19061:        bfextu          %d0{&16:&4},%d1         # fetch dreg index
                   19062:        bsr.l           fetch_dreg
                   19063:
                   19064:        movm.l          &0x3c00,-(%sp)          # save d2-d5
                   19065:        mov.l           %d0,%d2                 # put index in d2
                   19066:        mov.l           L_SCR1(%a6),%d5
                   19067:        mov.l           %a0,%d3
                   19068:
                   19069:        btst            &0xb,%d5                # is index word or long?
                   19070:        bne.b           fno_ext
                   19071:        ext.l           %d2
                   19072:
                   19073: fno_ext:
                   19074:        bfextu          %d5{&21:&2},%d0
                   19075:        lsl.l           %d0,%d2
                   19076:
                   19077: # base address (passed as parameter in d3):
                   19078: # we clear the value here if it should actually be suppressed.
                   19079: fbase_supp_ck:
                   19080:        btst            &0x7,%d5                # is the bd suppressed?
                   19081:        beq.b           fno_base_sup
                   19082:        clr.l           %d3
                   19083:
                   19084: # base displacement:
                   19085: fno_base_sup:
                   19086:        bfextu          %d5{&26:&2},%d0         # get bd size
                   19087: #      beq.l           fmovm_error             # if (size == 0) it's reserved
                   19088:
                   19089:        cmpi.b          %d0,&0x2
                   19090:        blt.b           fno_bd
                   19091:        beq.b           fget_word_bd
                   19092:
                   19093:        mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
                   19094:        addq.l          &0x4,EXC_EXTWPTR(%a6)   # incr instruction ptr
                   19095:        bsr.l           _imem_read_long
                   19096:
                   19097:        tst.l           %d1                     # did ifetch fail?
                   19098:        bne.l           fcea_iacc               # yes
                   19099:
                   19100:        bra.b           fchk_ind
                   19101:
                   19102: fget_word_bd:
                   19103:        mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
                   19104:        addq.l          &0x2,EXC_EXTWPTR(%a6)   # incr instruction ptr
                   19105:        bsr.l           _imem_read_word
                   19106:
                   19107:        tst.l           %d1                     # did ifetch fail?
                   19108:        bne.l           fcea_iacc               # yes
                   19109:
                   19110:        ext.l           %d0                     # sign extend bd
                   19111:
                   19112: fchk_ind:
                   19113:        add.l           %d0,%d3                 # base += bd
                   19114:
                   19115: # outer displacement:
                   19116: fno_bd:
                   19117:        bfextu          %d5{&30:&2},%d0         # is od suppressed?
                   19118:        beq.w           faii_bd
                   19119:
                   19120:        cmpi.b          %d0,&0x2
                   19121:        blt.b           fnull_od
                   19122:        beq.b           fword_od
                   19123:
                   19124:        mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
                   19125:        addq.l          &0x4,EXC_EXTWPTR(%a6)   # incr instruction ptr
                   19126:        bsr.l           _imem_read_long
                   19127:
                   19128:        tst.l           %d1                     # did ifetch fail?
                   19129:        bne.l           fcea_iacc               # yes
                   19130:
                   19131:        bra.b           fadd_them
                   19132:
                   19133: fword_od:
                   19134:        mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
                   19135:        addq.l          &0x2,EXC_EXTWPTR(%a6)   # incr instruction ptr
                   19136:        bsr.l           _imem_read_word
                   19137:
                   19138:        tst.l           %d1                     # did ifetch fail?
                   19139:        bne.l           fcea_iacc               # yes
                   19140:
                   19141:        ext.l           %d0                     # sign extend od
                   19142:        bra.b           fadd_them
                   19143:
                   19144: fnull_od:
                   19145:        clr.l           %d0
                   19146:
                   19147: fadd_them:
                   19148:        mov.l           %d0,%d4
                   19149:
                   19150:        btst            &0x2,%d5                # pre or post indexing?
                   19151:        beq.b           fpre_indexed
                   19152:
                   19153:        mov.l           %d3,%a0
                   19154:        bsr.l           _dmem_read_long
                   19155:
                   19156:        tst.l           %d1                     # did dfetch fail?
                   19157:        bne.w           fcea_err                # yes
                   19158:
                   19159:        add.l           %d2,%d0                 # <ea> += index
                   19160:        add.l           %d4,%d0                 # <ea> += od
                   19161:        bra.b           fdone_ea
                   19162:
                   19163: fpre_indexed:
                   19164:        add.l           %d2,%d3                 # preindexing
                   19165:        mov.l           %d3,%a0
                   19166:        bsr.l           _dmem_read_long
                   19167:
                   19168:        tst.l           %d1                     # did dfetch fail?
                   19169:        bne.w           fcea_err                # yes
                   19170:
                   19171:        add.l           %d4,%d0                 # ea += od
                   19172:        bra.b           fdone_ea
                   19173:
                   19174: faii_bd:
                   19175:        add.l           %d2,%d3                 # ea = (base + bd) + index
                   19176:        mov.l           %d3,%d0
                   19177: fdone_ea:
                   19178:        mov.l           %d0,%a0
                   19179:
                   19180:        movm.l          (%sp)+,&0x003c          # restore d2-d5
                   19181:        rts
                   19182:
                   19183: #########################################################
                   19184: fcea_err:
                   19185:        mov.l           %d3,%a0
                   19186:
                   19187:        movm.l          (%sp)+,&0x003c          # restore d2-d5
                   19188:        mov.w           &0x0101,%d0
                   19189:        bra.l           iea_dacc
                   19190:
                   19191: fcea_iacc:
                   19192:        movm.l          (%sp)+,&0x003c          # restore d2-d5
                   19193:        bra.l           iea_iacc
                   19194:
                   19195: fmovm_out_err:
                   19196:        bsr.l           restore
                   19197:        mov.w           &0x00e1,%d0
                   19198:        bra.b           fmovm_err
                   19199:
                   19200: fmovm_in_err:
                   19201:        bsr.l           restore
                   19202:        mov.w           &0x0161,%d0
                   19203:
                   19204: fmovm_err:
                   19205:        mov.l           L_SCR1(%a6),%a0
                   19206:        bra.l           iea_dacc
                   19207:
                   19208: #########################################################################
                   19209: # XDEF ****************************************************************        #
                   19210: #      fmovm_ctrl(): emulate fmovm.l of control registers instr        #
                   19211: #                                                                      #
                   19212: # XREF ****************************************************************        #
                   19213: #      _imem_read_long() - read longword from memory                   #
                   19214: #      iea_iacc() - _imem_read_long() failed; error recovery           #
                   19215: #                                                                      #
                   19216: # INPUT ***************************************************************        #
                   19217: #      None                                                            #
                   19218: #                                                                      #
                   19219: # OUTPUT **************************************************************        #
                   19220: #      If _imem_read_long() doesn't fail:                              #
                   19221: #              USER_FPCR(a6)  = new FPCR value                         #
                   19222: #              USER_FPSR(a6)  = new FPSR value                         #
                   19223: #              USER_FPIAR(a6) = new FPIAR value                        #
                   19224: #                                                                      #
                   19225: # ALGORITHM ***********************************************************        #
                   19226: #      Decode the instruction type by looking at the extension word    #
                   19227: # in order to see how many control registers to fetch from memory.     #
                   19228: # Fetch them using _imem_read_long(). If this fetch fails, exit through        #
                   19229: # the special access error exit handler iea_iacc().                    #
                   19230: #                                                                      #
                   19231: # Instruction word decoding:                                           #
                   19232: #                                                                      #
                   19233: #      fmovem.l #<data>, {FPIAR&|FPCR&|FPSR}                           #
                   19234: #                                                                      #
                   19235: #              WORD1                   WORD2                           #
                   19236: #      1111 0010 00 111100     100$ $$00 0000 0000                     #
                   19237: #                                                                      #
                   19238: #      $$$ (100): FPCR                                                 #
                   19239: #          (010): FPSR                                                 #
                   19240: #          (001): FPIAR                                                #
                   19241: #          (000): FPIAR                                                #
                   19242: #                                                                      #
                   19243: #########################################################################
                   19244:
                   19245:        global          fmovm_ctrl
                   19246: fmovm_ctrl:
                   19247:        mov.b           EXC_EXTWORD(%a6),%d0    # fetch reg select bits
                   19248:        cmpi.b          %d0,&0x9c               # fpcr & fpsr & fpiar ?
                   19249:        beq.w           fctrl_in_7              # yes
                   19250:        cmpi.b          %d0,&0x98               # fpcr & fpsr ?
                   19251:        beq.w           fctrl_in_6              # yes
                   19252:        cmpi.b          %d0,&0x94               # fpcr & fpiar ?
                   19253:        beq.b           fctrl_in_5              # yes
                   19254:
                   19255: # fmovem.l #<data>, fpsr/fpiar
                   19256: fctrl_in_3:
                   19257:        mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
                   19258:        addq.l          &0x4,EXC_EXTWPTR(%a6)   # incr instruction ptr
                   19259:        bsr.l           _imem_read_long         # fetch FPSR from mem
                   19260:
                   19261:        tst.l           %d1                     # did ifetch fail?
                   19262:        bne.l           iea_iacc                # yes
                   19263:
                   19264:        mov.l           %d0,USER_FPSR(%a6)      # store new FPSR to stack
                   19265:        mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
                   19266:        addq.l          &0x4,EXC_EXTWPTR(%a6)   # incr instruction ptr
                   19267:        bsr.l           _imem_read_long         # fetch FPIAR from mem
                   19268:
                   19269:        tst.l           %d1                     # did ifetch fail?
                   19270:        bne.l           iea_iacc                # yes
                   19271:
                   19272:        mov.l           %d0,USER_FPIAR(%a6)     # store new FPIAR to stack
                   19273:        rts
                   19274:
                   19275: # fmovem.l #<data>, fpcr/fpiar
                   19276: fctrl_in_5:
                   19277:        mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
                   19278:        addq.l          &0x4,EXC_EXTWPTR(%a6)   # incr instruction ptr
                   19279:        bsr.l           _imem_read_long         # fetch FPCR from mem
                   19280:
                   19281:        tst.l           %d1                     # did ifetch fail?
                   19282:        bne.l           iea_iacc                # yes
                   19283:
                   19284:        mov.l           %d0,USER_FPCR(%a6)      # store new FPCR to stack
                   19285:        mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
                   19286:        addq.l          &0x4,EXC_EXTWPTR(%a6)   # incr instruction ptr
                   19287:        bsr.l           _imem_read_long         # fetch FPIAR from mem
                   19288:
                   19289:        tst.l           %d1                     # did ifetch fail?
                   19290:        bne.l           iea_iacc                # yes
                   19291:
                   19292:        mov.l           %d0,USER_FPIAR(%a6)     # store new FPIAR to stack
                   19293:        rts
                   19294:
                   19295: # fmovem.l #<data>, fpcr/fpsr
                   19296: fctrl_in_6:
                   19297:        mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
                   19298:        addq.l          &0x4,EXC_EXTWPTR(%a6)   # incr instruction ptr
                   19299:        bsr.l           _imem_read_long         # fetch FPCR from mem
                   19300:
                   19301:        tst.l           %d1                     # did ifetch fail?
                   19302:        bne.l           iea_iacc                # yes
                   19303:
                   19304:        mov.l           %d0,USER_FPCR(%a6)      # store new FPCR to mem
                   19305:        mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
                   19306:        addq.l          &0x4,EXC_EXTWPTR(%a6)   # incr instruction ptr
                   19307:        bsr.l           _imem_read_long         # fetch FPSR from mem
                   19308:
                   19309:        tst.l           %d1                     # did ifetch fail?
                   19310:        bne.l           iea_iacc                # yes
                   19311:
                   19312:        mov.l           %d0,USER_FPSR(%a6)      # store new FPSR to mem
                   19313:        rts
                   19314:
                   19315: # fmovem.l #<data>, fpcr/fpsr/fpiar
                   19316: fctrl_in_7:
                   19317:        mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
                   19318:        addq.l          &0x4,EXC_EXTWPTR(%a6)   # incr instruction ptr
                   19319:        bsr.l           _imem_read_long         # fetch FPCR from mem
                   19320:
                   19321:        tst.l           %d1                     # did ifetch fail?
                   19322:        bne.l           iea_iacc                # yes
                   19323:
                   19324:        mov.l           %d0,USER_FPCR(%a6)      # store new FPCR to mem
                   19325:        mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
                   19326:        addq.l          &0x4,EXC_EXTWPTR(%a6)   # incr instruction ptr
                   19327:        bsr.l           _imem_read_long         # fetch FPSR from mem
                   19328:
                   19329:        tst.l           %d1                     # did ifetch fail?
                   19330:        bne.l           iea_iacc                # yes
                   19331:
                   19332:        mov.l           %d0,USER_FPSR(%a6)      # store new FPSR to mem
                   19333:        mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
                   19334:        addq.l          &0x4,EXC_EXTWPTR(%a6)   # incr instruction ptr
                   19335:        bsr.l           _imem_read_long         # fetch FPIAR from mem
                   19336:
                   19337:        tst.l           %d1                     # did ifetch fail?
                   19338:        bne.l           iea_iacc                # yes
                   19339:
                   19340:        mov.l           %d0,USER_FPIAR(%a6)     # store new FPIAR to mem
                   19341:        rts
                   19342:
                   19343: #########################################################################
                   19344: # XDEF ****************************************************************        #
                   19345: #      _dcalc_ea(): calc correct <ea> from <ea> stacked on exception   #
                   19346: #                                                                      #
                   19347: # XREF ****************************************************************        #
                   19348: #      inc_areg() - increment an address register                      #
                   19349: #      dec_areg() - decrement an address register                      #
                   19350: #                                                                      #
                   19351: # INPUT ***************************************************************        #
                   19352: #      d0 = number of bytes to adjust <ea> by                          #
                   19353: #                                                                      #
                   19354: # OUTPUT **************************************************************        #
                   19355: #      None                                                            #
                   19356: #                                                                      #
                   19357: # ALGORITHM ***********************************************************        #
                   19358: # "Dummy" CALCulate Effective Address:                                 #
                   19359: #      The stacked <ea> for FP unimplemented instructions and opclass  #
                   19360: #      two packed instructions is correct with the exception of...     #
                   19361: #                                                                      #
                   19362: #      1) -(An)   : The register is not updated regardless of size.    #
                   19363: #                   Also, for extended precision and packed, the       #
                   19364: #                   stacked <ea> value is 8 bytes too big              #
                   19365: #      2) (An)+   : The register is not updated.                       #
                   19366: #      3) #<data> : The upper longword of the immediate operand is     #
                   19367: #                   stacked b,w,l and s sizes are completely stacked.  #
                   19368: #                   d,x, and p are not.                                #
                   19369: #                                                                      #
                   19370: #########################################################################
                   19371:
                   19372:        global          _dcalc_ea
                   19373: _dcalc_ea:
                   19374:        mov.l           %d0, %a0                # move # bytes to %a0
                   19375:
                   19376:        mov.b           1+EXC_OPWORD(%a6), %d0  # fetch opcode word
                   19377:        mov.l           %d0, %d1                # make a copy
                   19378:
                   19379:        andi.w          &0x38, %d0              # extract mode field
                   19380:        andi.l          &0x7, %d1               # extract reg  field
                   19381:
                   19382:        cmpi.b          %d0,&0x18               # is mode (An)+ ?
                   19383:        beq.b           dcea_pi                 # yes
                   19384:
                   19385:        cmpi.b          %d0,&0x20               # is mode -(An) ?
                   19386:        beq.b           dcea_pd                 # yes
                   19387:
                   19388:        or.w            %d1,%d0                 # concat mode,reg
                   19389:        cmpi.b          %d0,&0x3c               # is mode #<data>?
                   19390:
                   19391:        beq.b           dcea_imm                # yes
                   19392:
                   19393:        mov.l           EXC_EA(%a6),%a0         # return <ea>
                   19394:        rts
                   19395:
                   19396: # need to set immediate data flag here since we'll need to do
                   19397: # an imem_read to fetch this later.
                   19398: dcea_imm:
                   19399:        mov.b           &immed_flg,SPCOND_FLG(%a6)
                   19400:        lea             ([USER_FPIAR,%a6],0x4),%a0 # no; return <ea>
                   19401:        rts
                   19402:
                   19403: # here, the <ea> is stacked correctly. however, we must update the
                   19404: # address register...
                   19405: dcea_pi:
                   19406:        mov.l           %a0,%d0                 # pass amt to inc by
                   19407:        bsr.l           inc_areg                # inc addr register
                   19408:
                   19409:        mov.l           EXC_EA(%a6),%a0         # stacked <ea> is correct
                   19410:        rts
                   19411:
                   19412: # the <ea> is stacked correctly for all but extended and packed which
                   19413: # the <ea>s are 8 bytes too large.
                   19414: # it would make no sense to have a pre-decrement to a7 in supervisor
                   19415: # mode so we don't even worry about this tricky case here : )
                   19416: dcea_pd:
                   19417:        mov.l           %a0,%d0                 # pass amt to dec by
                   19418:        bsr.l           dec_areg                # dec addr register
                   19419:
                   19420:        mov.l           EXC_EA(%a6),%a0         # stacked <ea> is correct
                   19421:
                   19422:        cmpi.b          %d0,&0xc                # is opsize ext or packed?
                   19423:        beq.b           dcea_pd2                # yes
                   19424:        rts
                   19425: dcea_pd2:
                   19426:        sub.l           &0x8,%a0                # correct <ea>
                   19427:        mov.l           %a0,EXC_EA(%a6)         # put correct <ea> on stack
                   19428:        rts
                   19429:
                   19430: #########################################################################
                   19431: # XDEF ****************************************************************        #
                   19432: #      _calc_ea_fout(): calculate correct stacked <ea> for extended    #
                   19433: #                       and packed data opclass 3 operations.          #
                   19434: #                                                                      #
                   19435: # XREF ****************************************************************        #
                   19436: #      None                                                            #
                   19437: #                                                                      #
                   19438: # INPUT ***************************************************************        #
                   19439: #      None                                                            #
                   19440: #                                                                      #
                   19441: # OUTPUT **************************************************************        #
                   19442: #      a0 = return correct effective address                           #
                   19443: #                                                                      #
                   19444: # ALGORITHM ***********************************************************        #
                   19445: #      For opclass 3 extended and packed data operations, the <ea>     #
                   19446: # stacked for the exception is incorrect for -(an) and (an)+ addressing        #
                   19447: # modes. Also, while we're at it, the index register itself must get   #
                   19448: # updated.                                                             #
                   19449: #      So, for -(an), we must subtract 8 off of the stacked <ea> value #
                   19450: # and return that value as the correct <ea> and store that value in An.        #
                   19451: # For (an)+, the stacked <ea> is correct but we must adjust An by +12. #
                   19452: #                                                                      #
                   19453: #########################################################################
                   19454:
                   19455: # This calc_ea is currently used to retrieve the correct <ea>
                   19456: # for fmove outs of type extended and packed.
                   19457:        global          _calc_ea_fout
                   19458: _calc_ea_fout:
                   19459:        mov.b           1+EXC_OPWORD(%a6),%d0   # fetch opcode word
                   19460:        mov.l           %d0,%d1                 # make a copy
                   19461:
                   19462:        andi.w          &0x38,%d0               # extract mode field
                   19463:        andi.l          &0x7,%d1                # extract reg  field
                   19464:
                   19465:        cmpi.b          %d0,&0x18               # is mode (An)+ ?
                   19466:        beq.b           ceaf_pi                 # yes
                   19467:
                   19468:        cmpi.b          %d0,&0x20               # is mode -(An) ?
                   19469:        beq.w           ceaf_pd                 # yes
                   19470:
                   19471:        mov.l           EXC_EA(%a6),%a0         # stacked <ea> is correct
                   19472:        rts
                   19473:
                   19474: # (An)+ : extended and packed fmove out
                   19475: #      : stacked <ea> is correct
                   19476: #      : "An" not updated
                   19477: ceaf_pi:
                   19478:        mov.w           (tbl_ceaf_pi.b,%pc,%d1.w*2),%d1
                   19479:        mov.l           EXC_EA(%a6),%a0
                   19480:        jmp             (tbl_ceaf_pi.b,%pc,%d1.w*1)
                   19481:
                   19482:        swbeg           &0x8
                   19483: tbl_ceaf_pi:
                   19484:        short           ceaf_pi0 - tbl_ceaf_pi
                   19485:        short           ceaf_pi1 - tbl_ceaf_pi
                   19486:        short           ceaf_pi2 - tbl_ceaf_pi
                   19487:        short           ceaf_pi3 - tbl_ceaf_pi
                   19488:        short           ceaf_pi4 - tbl_ceaf_pi
                   19489:        short           ceaf_pi5 - tbl_ceaf_pi
                   19490:        short           ceaf_pi6 - tbl_ceaf_pi
                   19491:        short           ceaf_pi7 - tbl_ceaf_pi
                   19492:
                   19493: ceaf_pi0:
                   19494:        addi.l          &0xc,EXC_DREGS+0x8(%a6)
                   19495:        rts
                   19496: ceaf_pi1:
                   19497:        addi.l          &0xc,EXC_DREGS+0xc(%a6)
                   19498:        rts
                   19499: ceaf_pi2:
                   19500:        add.l           &0xc,%a2
                   19501:        rts
                   19502: ceaf_pi3:
                   19503:        add.l           &0xc,%a3
                   19504:        rts
                   19505: ceaf_pi4:
                   19506:        add.l           &0xc,%a4
                   19507:        rts
                   19508: ceaf_pi5:
                   19509:        add.l           &0xc,%a5
                   19510:        rts
                   19511: ceaf_pi6:
                   19512:        addi.l          &0xc,EXC_A6(%a6)
                   19513:        rts
                   19514: ceaf_pi7:
                   19515:        mov.b           &mia7_flg,SPCOND_FLG(%a6)
                   19516:        addi.l          &0xc,EXC_A7(%a6)
                   19517:        rts
                   19518:
                   19519: # -(An) : extended and packed fmove out
                   19520: #      : stacked <ea> = actual <ea> + 8
                   19521: #      : "An" not updated
                   19522: ceaf_pd:
                   19523:        mov.w           (tbl_ceaf_pd.b,%pc,%d1.w*2),%d1
                   19524:        mov.l           EXC_EA(%a6),%a0
                   19525:        sub.l           &0x8,%a0
                   19526:        sub.l           &0x8,EXC_EA(%a6)
                   19527:        jmp             (tbl_ceaf_pd.b,%pc,%d1.w*1)
                   19528:
                   19529:        swbeg           &0x8
                   19530: tbl_ceaf_pd:
                   19531:        short           ceaf_pd0 - tbl_ceaf_pd
                   19532:        short           ceaf_pd1 - tbl_ceaf_pd
                   19533:        short           ceaf_pd2 - tbl_ceaf_pd
                   19534:        short           ceaf_pd3 - tbl_ceaf_pd
                   19535:        short           ceaf_pd4 - tbl_ceaf_pd
                   19536:        short           ceaf_pd5 - tbl_ceaf_pd
                   19537:        short           ceaf_pd6 - tbl_ceaf_pd
                   19538:        short           ceaf_pd7 - tbl_ceaf_pd
                   19539:
                   19540: ceaf_pd0:
                   19541:        mov.l           %a0,EXC_DREGS+0x8(%a6)
                   19542:        rts
                   19543: ceaf_pd1:
                   19544:        mov.l           %a0,EXC_DREGS+0xc(%a6)
                   19545:        rts
                   19546: ceaf_pd2:
                   19547:        mov.l           %a0,%a2
                   19548:        rts
                   19549: ceaf_pd3:
                   19550:        mov.l           %a0,%a3
                   19551:        rts
                   19552: ceaf_pd4:
                   19553:        mov.l           %a0,%a4
                   19554:        rts
                   19555: ceaf_pd5:
                   19556:        mov.l           %a0,%a5
                   19557:        rts
                   19558: ceaf_pd6:
                   19559:        mov.l           %a0,EXC_A6(%a6)
                   19560:        rts
                   19561: ceaf_pd7:
                   19562:        mov.l           %a0,EXC_A7(%a6)
                   19563:        mov.b           &mda7_flg,SPCOND_FLG(%a6)
                   19564:        rts
                   19565:
                   19566: #########################################################################
                   19567: # XDEF ****************************************************************        #
                   19568: #      _load_fop(): load operand for unimplemented FP exception        #
                   19569: #                                                                      #
                   19570: # XREF ****************************************************************        #
                   19571: #      set_tag_x() - determine ext prec optype tag                     #
                   19572: #      set_tag_s() - determine sgl prec optype tag                     #
                   19573: #      set_tag_d() - determine dbl prec optype tag                     #
                   19574: #      unnorm_fix() - convert normalized number to denorm or zero      #
                   19575: #      norm() - normalize a denormalized number                        #
                   19576: #      get_packed() - fetch a packed operand from memory               #
                   19577: #      _dcalc_ea() - calculate <ea>, fixing An in process              #
                   19578: #                                                                      #
                   19579: #      _imem_read_{word,long}() - read from instruction memory         #
                   19580: #      _dmem_read() - read from data memory                            #
                   19581: #      _dmem_read_{byte,word,long}() - read from data memory           #
                   19582: #                                                                      #
                   19583: #      facc_in_{b,w,l,d,x}() - mem read failed; special exit point     #
                   19584: #                                                                      #
                   19585: # INPUT ***************************************************************        #
                   19586: #      None                                                            #
                   19587: #                                                                      #
                   19588: # OUTPUT **************************************************************        #
                   19589: #      If memory access doesn't fail:                                  #
                   19590: #              FP_SRC(a6) = source operand in extended precision       #
                   19591: #              FP_DST(a6) = destination operand in extended precision  #
                   19592: #                                                                      #
                   19593: # ALGORITHM ***********************************************************        #
                   19594: #      This is called from the Unimplemented FP exception handler in   #
                   19595: # order to load the source and maybe destination operand into          #
                   19596: # FP_SRC(a6) and FP_DST(a6). If the instruction was opclass zero, load #
                   19597: # the source and destination from the FP register file. Set the optype #
                   19598: # tags for both if dyadic, one for monadic. If a number is an UNNORM,  #
                   19599: # convert it to a DENORM or a ZERO.                                    #
                   19600: #      If the instruction is opclass two (memory->reg), then fetch     #
                   19601: # the destination from the register file and the source operand from   #
                   19602: # memory. Tag and fix both as above w/ opclass zero instructions.      #
                   19603: #      If the source operand is byte,word,long, or single, it may be   #
                   19604: # in the data register file. If it's actually out in memory, use one of        #
                   19605: # the mem_read() routines to fetch it. If the mem_read() access returns        #
                   19606: # a failing value, exit through the special facc_in() routine which    #
                   19607: # will create an acess error exception frame from the current exception #
                   19608: # frame.                                                               #
                   19609: #      Immediate data and regular data accesses are separated because  #
                   19610: # if an immediate data access fails, the resulting fault status                #
                   19611: # longword stacked for the access error exception must have the        #
                   19612: # instruction bit set.                                                 #
                   19613: #                                                                      #
                   19614: #########################################################################
                   19615:
                   19616:        global          _load_fop
                   19617: _load_fop:
                   19618:
                   19619: #  15     13 12 10  9 7  6       0
                   19620: # /        \ /   \ /  \ /         \
                   19621: # ---------------------------------
                   19622: # | opclass | RX  | RY | EXTENSION |  (2nd word of general FP instruction)
                   19623: # ---------------------------------
                   19624: #
                   19625:
                   19626: #      bfextu          EXC_CMDREG(%a6){&0:&3}, %d0 # extract opclass
                   19627: #      cmpi.b          %d0, &0x2               # which class is it? ('000,'010,'011)
                   19628: #      beq.w           op010                   # handle <ea> -> fpn
                   19629: #      bgt.w           op011                   # handle fpn -> <ea>
                   19630:
                   19631: # we're not using op011 for now...
                   19632:        btst            &0x6,EXC_CMDREG(%a6)
                   19633:        bne.b           op010
                   19634:
                   19635: ############################
                   19636: # OPCLASS '000: reg -> reg #
                   19637: ############################
                   19638: op000:
                   19639:        mov.b           1+EXC_CMDREG(%a6),%d0   # fetch extension word lo
                   19640:        btst            &0x5,%d0                # testing extension bits
                   19641:        beq.b           op000_src               # (bit 5 == 0) => monadic
                   19642:        btst            &0x4,%d0                # (bit 5 == 1)
                   19643:        beq.b           op000_dst               # (bit 4 == 0) => dyadic
                   19644:        and.w           &0x007f,%d0             # extract extension bits {6:0}
                   19645:        cmpi.w          %d0,&0x0038             # is it an fcmp (dyadic) ?
                   19646:        bne.b           op000_src               # it's an fcmp
                   19647:
                   19648: op000_dst:
                   19649:        bfextu          EXC_CMDREG(%a6){&6:&3}, %d0 # extract dst field
                   19650:        bsr.l           load_fpn2               # fetch dst fpreg into FP_DST
                   19651:
                   19652:        bsr.l           set_tag_x               # get dst optype tag
                   19653:
                   19654:        cmpi.b          %d0, &UNNORM            # is dst fpreg an UNNORM?
                   19655:        beq.b           op000_dst_unnorm        # yes
                   19656: op000_dst_cont:
                   19657:        mov.b           %d0, DTAG(%a6)          # store the dst optype tag
                   19658:
                   19659: op000_src:
                   19660:        bfextu          EXC_CMDREG(%a6){&3:&3}, %d0 # extract src field
                   19661:        bsr.l           load_fpn1               # fetch src fpreg into FP_SRC
                   19662:
                   19663:        bsr.l           set_tag_x               # get src optype tag
                   19664:
                   19665:        cmpi.b          %d0, &UNNORM            # is src fpreg an UNNORM?
                   19666:        beq.b           op000_src_unnorm        # yes
                   19667: op000_src_cont:
                   19668:        mov.b           %d0, STAG(%a6)          # store the src optype tag
                   19669:        rts
                   19670:
                   19671: op000_dst_unnorm:
                   19672:        bsr.l           unnorm_fix              # fix the dst UNNORM
                   19673:        bra.b           op000_dst_cont
                   19674: op000_src_unnorm:
                   19675:        bsr.l           unnorm_fix              # fix the src UNNORM
                   19676:        bra.b           op000_src_cont
                   19677:
                   19678: #############################
                   19679: # OPCLASS '010: <ea> -> reg #
                   19680: #############################
                   19681: op010:
                   19682:        mov.w           EXC_CMDREG(%a6),%d0     # fetch extension word
                   19683:        btst            &0x5,%d0                # testing extension bits
                   19684:        beq.b           op010_src               # (bit 5 == 0) => monadic
                   19685:        btst            &0x4,%d0                # (bit 5 == 1)
                   19686:        beq.b           op010_dst               # (bit 4 == 0) => dyadic
                   19687:        and.w           &0x007f,%d0             # extract extension bits {6:0}
                   19688:        cmpi.w          %d0,&0x0038             # is it an fcmp (dyadic) ?
                   19689:        bne.b           op010_src               # it's an fcmp
                   19690:
                   19691: op010_dst:
                   19692:        bfextu          EXC_CMDREG(%a6){&6:&3}, %d0 # extract dst field
                   19693:        bsr.l           load_fpn2               # fetch dst fpreg ptr
                   19694:
                   19695:        bsr.l           set_tag_x               # get dst type tag
                   19696:
                   19697:        cmpi.b          %d0, &UNNORM            # is dst fpreg an UNNORM?
                   19698:        beq.b           op010_dst_unnorm        # yes
                   19699: op010_dst_cont:
                   19700:        mov.b           %d0, DTAG(%a6)          # store the dst optype tag
                   19701:
                   19702: op010_src:
                   19703:        bfextu          EXC_CMDREG(%a6){&3:&3}, %d0 # extract src type field
                   19704:
                   19705:        bfextu          EXC_OPWORD(%a6){&10:&3}, %d1 # extract <ea> mode field
                   19706:        bne.w           fetch_from_mem          # src op is in memory
                   19707:
                   19708: op010_dreg:
                   19709:        clr.b           STAG(%a6)               # either NORM or ZERO
                   19710:        bfextu          EXC_OPWORD(%a6){&13:&3}, %d1 # extract src reg field
                   19711:
                   19712:        mov.w           (tbl_op010_dreg.b,%pc,%d0.w*2), %d0 # jmp based on optype
                   19713:        jmp             (tbl_op010_dreg.b,%pc,%d0.w*1) # fetch src from dreg
                   19714:
                   19715: op010_dst_unnorm:
                   19716:        bsr.l           unnorm_fix              # fix the dst UNNORM
                   19717:        bra.b           op010_dst_cont
                   19718:
                   19719:        swbeg           &0x8
                   19720: tbl_op010_dreg:
                   19721:        short           opd_long        - tbl_op010_dreg
                   19722:        short           opd_sgl         - tbl_op010_dreg
                   19723:        short           tbl_op010_dreg  - tbl_op010_dreg
                   19724:        short           tbl_op010_dreg  - tbl_op010_dreg
                   19725:        short           opd_word        - tbl_op010_dreg
                   19726:        short           tbl_op010_dreg  - tbl_op010_dreg
                   19727:        short           opd_byte        - tbl_op010_dreg
                   19728:        short           tbl_op010_dreg  - tbl_op010_dreg
                   19729:
                   19730: #
                   19731: # LONG: can be either NORM or ZERO...
                   19732: #
                   19733: opd_long:
                   19734:        bsr.l           fetch_dreg              # fetch long in d0
                   19735:        fmov.l          %d0, %fp0               # load a long
                   19736:        fmovm.x         &0x80, FP_SRC(%a6)      # return src op in FP_SRC
                   19737:        fbeq.w          opd_long_zero           # long is a ZERO
                   19738:        rts
                   19739: opd_long_zero:
                   19740:        mov.b           &ZERO, STAG(%a6)        # set ZERO optype flag
                   19741:        rts
                   19742:
                   19743: #
                   19744: # WORD: can be either NORM or ZERO...
                   19745: #
                   19746: opd_word:
                   19747:        bsr.l           fetch_dreg              # fetch word in d0
                   19748:        fmov.w          %d0, %fp0               # load a word
                   19749:        fmovm.x         &0x80, FP_SRC(%a6)      # return src op in FP_SRC
                   19750:        fbeq.w          opd_word_zero           # WORD is a ZERO
                   19751:        rts
                   19752: opd_word_zero:
                   19753:        mov.b           &ZERO, STAG(%a6)        # set ZERO optype flag
                   19754:        rts
                   19755:
                   19756: #
                   19757: # BYTE: can be either NORM or ZERO...
                   19758: #
                   19759: opd_byte:
                   19760:        bsr.l           fetch_dreg              # fetch word in d0
                   19761:        fmov.b          %d0, %fp0               # load a byte
                   19762:        fmovm.x         &0x80, FP_SRC(%a6)      # return src op in FP_SRC
                   19763:        fbeq.w          opd_byte_zero           # byte is a ZERO
                   19764:        rts
                   19765: opd_byte_zero:
                   19766:        mov.b           &ZERO, STAG(%a6)        # set ZERO optype flag
                   19767:        rts
                   19768:
                   19769: #
                   19770: # SGL: can be either NORM, DENORM, ZERO, INF, QNAN or SNAN but not UNNORM
                   19771: #
                   19772: # separate SNANs and DENORMs so they can be loaded w/ special care.
                   19773: # all others can simply be moved "in" using fmove.
                   19774: #
                   19775: opd_sgl:
                   19776:        bsr.l           fetch_dreg              # fetch sgl in d0
                   19777:        mov.l           %d0,L_SCR1(%a6)
                   19778:
                   19779:        lea             L_SCR1(%a6), %a0        # pass: ptr to the sgl
                   19780:        bsr.l           set_tag_s               # determine sgl type
                   19781:        mov.b           %d0, STAG(%a6)          # save the src tag
                   19782:
                   19783:        cmpi.b          %d0, &SNAN              # is it an SNAN?
                   19784:        beq.w           get_sgl_snan            # yes
                   19785:
                   19786:        cmpi.b          %d0, &DENORM            # is it a DENORM?
                   19787:        beq.w           get_sgl_denorm          # yes
                   19788:
                   19789:        fmov.s          (%a0), %fp0             # no, so can load it regular
                   19790:        fmovm.x         &0x80, FP_SRC(%a6)      # return src op in FP_SRC
                   19791:        rts
                   19792:
                   19793: ##############################################################################
                   19794:
                   19795: #########################################################################
                   19796: # fetch_from_mem():                                                    #
                   19797: # - src is out in memory. must:                                                #
                   19798: #      (1) calc ea - must read AFTER you know the src type since       #
                   19799: #                    if the ea is -() or ()+, need to know # of bytes. #
                   19800: #      (2) read it in from either user or supervisor space             #
                   19801: #      (3) if (b || w || l) then simply read in                        #
                   19802: #          if (s || d || x) then check for SNAN,UNNORM,DENORM          #
                   19803: #          if (packed) then punt for now                               #
                   19804: # INPUT:                                                               #
                   19805: #      %d0 : src type field                                            #
                   19806: #########################################################################
                   19807: fetch_from_mem:
                   19808:        clr.b           STAG(%a6)               # either NORM or ZERO
                   19809:
                   19810:        mov.w           (tbl_fp_type.b,%pc,%d0.w*2), %d0 # index by src type field
                   19811:        jmp             (tbl_fp_type.b,%pc,%d0.w*1)
                   19812:
                   19813:        swbeg           &0x8
                   19814: tbl_fp_type:
                   19815:        short           load_long       - tbl_fp_type
                   19816:        short           load_sgl        - tbl_fp_type
                   19817:        short           load_ext        - tbl_fp_type
                   19818:        short           load_packed     - tbl_fp_type
                   19819:        short           load_word       - tbl_fp_type
                   19820:        short           load_dbl        - tbl_fp_type
                   19821:        short           load_byte       - tbl_fp_type
                   19822:        short           tbl_fp_type     - tbl_fp_type
                   19823:
                   19824: #########################################
                   19825: # load a LONG into %fp0:               #
                   19826: #      -number can't fault             #
                   19827: #      (1) calc ea                     #
                   19828: #      (2) read 4 bytes into L_SCR1    #
                   19829: #      (3) fmov.l into %fp0            #
                   19830: #########################################
                   19831: load_long:
                   19832:        movq.l          &0x4, %d0               # pass: 4 (bytes)
                   19833:        bsr.l           _dcalc_ea               # calc <ea>; <ea> in %a0
                   19834:
                   19835:        cmpi.b          SPCOND_FLG(%a6),&immed_flg
                   19836:        beq.b           load_long_immed
                   19837:
                   19838:        bsr.l           _dmem_read_long         # fetch src operand from memory
                   19839:
                   19840:        tst.l           %d1                     # did dfetch fail?
                   19841:        bne.l           facc_in_l               # yes
                   19842:
                   19843: load_long_cont:
                   19844:        fmov.l          %d0, %fp0               # read into %fp0;convert to xprec
                   19845:        fmovm.x         &0x80, FP_SRC(%a6)      # return src op in FP_SRC
                   19846:
                   19847:        fbeq.w          load_long_zero          # src op is a ZERO
                   19848:        rts
                   19849: load_long_zero:
                   19850:        mov.b           &ZERO, STAG(%a6)        # set optype tag to ZERO
                   19851:        rts
                   19852:
                   19853: load_long_immed:
                   19854:        bsr.l           _imem_read_long         # fetch src operand immed data
                   19855:
                   19856:        tst.l           %d1                     # did ifetch fail?
                   19857:        bne.l           funimp_iacc             # yes
                   19858:        bra.b           load_long_cont
                   19859:
                   19860: #########################################
                   19861: # load a WORD into %fp0:               #
                   19862: #      -number can't fault             #
                   19863: #      (1) calc ea                     #
                   19864: #      (2) read 2 bytes into L_SCR1    #
                   19865: #      (3) fmov.w into %fp0            #
                   19866: #########################################
                   19867: load_word:
                   19868:        movq.l          &0x2, %d0               # pass: 2 (bytes)
                   19869:        bsr.l           _dcalc_ea               # calc <ea>; <ea> in %a0
                   19870:
                   19871:        cmpi.b          SPCOND_FLG(%a6),&immed_flg
                   19872:        beq.b           load_word_immed
                   19873:
                   19874:        bsr.l           _dmem_read_word         # fetch src operand from memory
                   19875:
                   19876:        tst.l           %d1                     # did dfetch fail?
                   19877:        bne.l           facc_in_w               # yes
                   19878:
                   19879: load_word_cont:
                   19880:        fmov.w          %d0, %fp0               # read into %fp0;convert to xprec
                   19881:        fmovm.x         &0x80, FP_SRC(%a6)      # return src op in FP_SRC
                   19882:
                   19883:        fbeq.w          load_word_zero          # src op is a ZERO
                   19884:        rts
                   19885: load_word_zero:
                   19886:        mov.b           &ZERO, STAG(%a6)        # set optype tag to ZERO
                   19887:        rts
                   19888:
                   19889: load_word_immed:
                   19890:        bsr.l           _imem_read_word         # fetch src operand immed data
                   19891:
                   19892:        tst.l           %d1                     # did ifetch fail?
                   19893:        bne.l           funimp_iacc             # yes
                   19894:        bra.b           load_word_cont
                   19895:
                   19896: #########################################
                   19897: # load a BYTE into %fp0:               #
                   19898: #      -number can't fault             #
                   19899: #      (1) calc ea                     #
                   19900: #      (2) read 1 byte into L_SCR1     #
                   19901: #      (3) fmov.b into %fp0            #
                   19902: #########################################
                   19903: load_byte:
                   19904:        movq.l          &0x1, %d0               # pass: 1 (byte)
                   19905:        bsr.l           _dcalc_ea               # calc <ea>; <ea> in %a0
                   19906:
                   19907:        cmpi.b          SPCOND_FLG(%a6),&immed_flg
                   19908:        beq.b           load_byte_immed
                   19909:
                   19910:        bsr.l           _dmem_read_byte         # fetch src operand from memory
                   19911:
                   19912:        tst.l           %d1                     # did dfetch fail?
                   19913:        bne.l           facc_in_b               # yes
                   19914:
                   19915: load_byte_cont:
                   19916:        fmov.b          %d0, %fp0               # read into %fp0;convert to xprec
                   19917:        fmovm.x         &0x80, FP_SRC(%a6)      # return src op in FP_SRC
                   19918:
                   19919:        fbeq.w          load_byte_zero          # src op is a ZERO
                   19920:        rts
                   19921: load_byte_zero:
                   19922:        mov.b           &ZERO, STAG(%a6)        # set optype tag to ZERO
                   19923:        rts
                   19924:
                   19925: load_byte_immed:
                   19926:        bsr.l           _imem_read_word         # fetch src operand immed data
                   19927:
                   19928:        tst.l           %d1                     # did ifetch fail?
                   19929:        bne.l           funimp_iacc             # yes
                   19930:        bra.b           load_byte_cont
                   19931:
                   19932: #########################################
                   19933: # load a SGL into %fp0:                        #
                   19934: #      -number can't fault             #
                   19935: #      (1) calc ea                     #
                   19936: #      (2) read 4 bytes into L_SCR1    #
                   19937: #      (3) fmov.s into %fp0            #
                   19938: #########################################
                   19939: load_sgl:
                   19940:        movq.l          &0x4, %d0               # pass: 4 (bytes)
                   19941:        bsr.l           _dcalc_ea               # calc <ea>; <ea> in %a0
                   19942:
                   19943:        cmpi.b          SPCOND_FLG(%a6),&immed_flg
                   19944:        beq.b           load_sgl_immed
                   19945:
                   19946:        bsr.l           _dmem_read_long         # fetch src operand from memory
                   19947:        mov.l           %d0, L_SCR1(%a6)        # store src op on stack
                   19948:
                   19949:        tst.l           %d1                     # did dfetch fail?
                   19950:        bne.l           facc_in_l               # yes
                   19951:
                   19952: load_sgl_cont:
                   19953:        lea             L_SCR1(%a6), %a0        # pass: ptr to sgl src op
                   19954:        bsr.l           set_tag_s               # determine src type tag
                   19955:        mov.b           %d0, STAG(%a6)          # save src optype tag on stack
                   19956:
                   19957:        cmpi.b          %d0, &DENORM            # is it a sgl DENORM?
                   19958:        beq.w           get_sgl_denorm          # yes
                   19959:
                   19960:        cmpi.b          %d0, &SNAN              # is it a sgl SNAN?
                   19961:        beq.w           get_sgl_snan            # yes
                   19962:
                   19963:        fmov.s          L_SCR1(%a6), %fp0       # read into %fp0;convert to xprec
                   19964:        fmovm.x         &0x80, FP_SRC(%a6)      # return src op in FP_SRC
                   19965:        rts
                   19966:
                   19967: load_sgl_immed:
                   19968:        bsr.l           _imem_read_long         # fetch src operand immed data
                   19969:
                   19970:        tst.l           %d1                     # did ifetch fail?
                   19971:        bne.l           funimp_iacc             # yes
                   19972:        bra.b           load_sgl_cont
                   19973:
                   19974: # must convert sgl denorm format to an Xprec denorm fmt suitable for
                   19975: # normalization...
                   19976: # %a0 : points to sgl denorm
                   19977: get_sgl_denorm:
                   19978:        clr.w           FP_SRC_EX(%a6)
                   19979:        bfextu          (%a0){&9:&23}, %d0      # fetch sgl hi(_mantissa)
                   19980:        lsl.l           &0x8, %d0
                   19981:        mov.l           %d0, FP_SRC_HI(%a6)     # set ext hi(_mantissa)
                   19982:        clr.l           FP_SRC_LO(%a6)          # set ext lo(_mantissa)
                   19983:
                   19984:        clr.w           FP_SRC_EX(%a6)
                   19985:        btst            &0x7, (%a0)             # is sgn bit set?
                   19986:        beq.b           sgl_dnrm_norm
                   19987:        bset            &0x7, FP_SRC_EX(%a6)    # set sgn of xprec value
                   19988:
                   19989: sgl_dnrm_norm:
                   19990:        lea             FP_SRC(%a6), %a0
                   19991:        bsr.l           norm                    # normalize number
                   19992:        mov.w           &0x3f81, %d1            # xprec exp = 0x3f81
                   19993:        sub.w           %d0, %d1                # exp = 0x3f81 - shft amt.
                   19994:        or.w            %d1, FP_SRC_EX(%a6)     # {sgn,exp}
                   19995:
                   19996:        mov.b           &NORM, STAG(%a6)        # fix src type tag
                   19997:        rts
                   19998:
                   19999: # convert sgl to ext SNAN
                   20000: # %a0 : points to sgl SNAN
                   20001: get_sgl_snan:
                   20002:        mov.w           &0x7fff, FP_SRC_EX(%a6) # set exp of SNAN
                   20003:        bfextu          (%a0){&9:&23}, %d0
                   20004:        lsl.l           &0x8, %d0               # extract and insert hi(man)
                   20005:        mov.l           %d0, FP_SRC_HI(%a6)
                   20006:        clr.l           FP_SRC_LO(%a6)
                   20007:
                   20008:        btst            &0x7, (%a0)             # see if sign of SNAN is set
                   20009:        beq.b           no_sgl_snan_sgn
                   20010:        bset            &0x7, FP_SRC_EX(%a6)
                   20011: no_sgl_snan_sgn:
                   20012:        rts
                   20013:
                   20014: #########################################
                   20015: # load a DBL into %fp0:                        #
                   20016: #      -number can't fault             #
                   20017: #      (1) calc ea                     #
                   20018: #      (2) read 8 bytes into L_SCR(1,2)#
                   20019: #      (3) fmov.d into %fp0            #
                   20020: #########################################
                   20021: load_dbl:
                   20022:        movq.l          &0x8, %d0               # pass: 8 (bytes)
                   20023:        bsr.l           _dcalc_ea               # calc <ea>; <ea> in %a0
                   20024:
                   20025:        cmpi.b          SPCOND_FLG(%a6),&immed_flg
                   20026:        beq.b           load_dbl_immed
                   20027:
                   20028:        lea             L_SCR1(%a6), %a1        # pass: ptr to input dbl tmp space
                   20029:        movq.l          &0x8, %d0               # pass: # bytes to read
                   20030:        bsr.l           _dmem_read              # fetch src operand from memory
                   20031:
                   20032:        tst.l           %d1                     # did dfetch fail?
                   20033:        bne.l           facc_in_d               # yes
                   20034:
                   20035: load_dbl_cont:
                   20036:        lea             L_SCR1(%a6), %a0        # pass: ptr to input dbl
                   20037:        bsr.l           set_tag_d               # determine src type tag
                   20038:        mov.b           %d0, STAG(%a6)          # set src optype tag
                   20039:
                   20040:        cmpi.b          %d0, &DENORM            # is it a dbl DENORM?
                   20041:        beq.w           get_dbl_denorm          # yes
                   20042:
                   20043:        cmpi.b          %d0, &SNAN              # is it a dbl SNAN?
                   20044:        beq.w           get_dbl_snan            # yes
                   20045:
                   20046:        fmov.d          L_SCR1(%a6), %fp0       # read into %fp0;convert to xprec
                   20047:        fmovm.x         &0x80, FP_SRC(%a6)      # return src op in FP_SRC
                   20048:        rts
                   20049:
                   20050: load_dbl_immed:
                   20051:        lea             L_SCR1(%a6), %a1        # pass: ptr to input dbl tmp space
                   20052:        movq.l          &0x8, %d0               # pass: # bytes to read
                   20053:        bsr.l           _imem_read              # fetch src operand from memory
                   20054:
                   20055:        tst.l           %d1                     # did ifetch fail?
                   20056:        bne.l           funimp_iacc             # yes
                   20057:        bra.b           load_dbl_cont
                   20058:
                   20059: # must convert dbl denorm format to an Xprec denorm fmt suitable for
                   20060: # normalization...
                   20061: # %a0 : loc. of dbl denorm
                   20062: get_dbl_denorm:
                   20063:        clr.w           FP_SRC_EX(%a6)
                   20064:        bfextu          (%a0){&12:&31}, %d0     # fetch hi(_mantissa)
                   20065:        mov.l           %d0, FP_SRC_HI(%a6)
                   20066:        bfextu          4(%a0){&11:&21}, %d0    # fetch lo(_mantissa)
                   20067:        mov.l           &0xb, %d1
                   20068:        lsl.l           %d1, %d0
                   20069:        mov.l           %d0, FP_SRC_LO(%a6)
                   20070:
                   20071:        btst            &0x7, (%a0)             # is sgn bit set?
                   20072:        beq.b           dbl_dnrm_norm
                   20073:        bset            &0x7, FP_SRC_EX(%a6)    # set sgn of xprec value
                   20074:
                   20075: dbl_dnrm_norm:
                   20076:        lea             FP_SRC(%a6), %a0
                   20077:        bsr.l           norm                    # normalize number
                   20078:        mov.w           &0x3c01, %d1            # xprec exp = 0x3c01
                   20079:        sub.w           %d0, %d1                # exp = 0x3c01 - shft amt.
                   20080:        or.w            %d1, FP_SRC_EX(%a6)     # {sgn,exp}
                   20081:
                   20082:        mov.b           &NORM, STAG(%a6)        # fix src type tag
                   20083:        rts
                   20084:
                   20085: # convert dbl to ext SNAN
                   20086: # %a0 : points to dbl SNAN
                   20087: get_dbl_snan:
                   20088:        mov.w           &0x7fff, FP_SRC_EX(%a6) # set exp of SNAN
                   20089:
                   20090:        bfextu          (%a0){&12:&31}, %d0     # fetch hi(_mantissa)
                   20091:        mov.l           %d0, FP_SRC_HI(%a6)
                   20092:        bfextu          4(%a0){&11:&21}, %d0    # fetch lo(_mantissa)
                   20093:        mov.l           &0xb, %d1
                   20094:        lsl.l           %d1, %d0
                   20095:        mov.l           %d0, FP_SRC_LO(%a6)
                   20096:
                   20097:        btst            &0x7, (%a0)             # see if sign of SNAN is set
                   20098:        beq.b           no_dbl_snan_sgn
                   20099:        bset            &0x7, FP_SRC_EX(%a6)
                   20100: no_dbl_snan_sgn:
                   20101:        rts
                   20102:
                   20103: #################################################
                   20104: # load a Xprec into %fp0:                      #
                   20105: #      -number can't fault                     #
                   20106: #      (1) calc ea                             #
                   20107: #      (2) read 12 bytes into L_SCR(1,2)       #
                   20108: #      (3) fmov.x into %fp0                    #
                   20109: #################################################
                   20110: load_ext:
                   20111:        mov.l           &0xc, %d0               # pass: 12 (bytes)
                   20112:        bsr.l           _dcalc_ea               # calc <ea>
                   20113:
                   20114:        lea             FP_SRC(%a6), %a1        # pass: ptr to input ext tmp space
                   20115:        mov.l           &0xc, %d0               # pass: # of bytes to read
                   20116:        bsr.l           _dmem_read              # fetch src operand from memory
                   20117:
                   20118:        tst.l           %d1                     # did dfetch fail?
                   20119:        bne.l           facc_in_x               # yes
                   20120:
                   20121:        lea             FP_SRC(%a6), %a0        # pass: ptr to src op
                   20122:        bsr.l           set_tag_x               # determine src type tag
                   20123:
                   20124:        cmpi.b          %d0, &UNNORM            # is the src op an UNNORM?
                   20125:        beq.b           load_ext_unnorm         # yes
                   20126:
                   20127:        mov.b           %d0, STAG(%a6)          # store the src optype tag
                   20128:        rts
                   20129:
                   20130: load_ext_unnorm:
                   20131:        bsr.l           unnorm_fix              # fix the src UNNORM
                   20132:        mov.b           %d0, STAG(%a6)          # store the src optype tag
                   20133:        rts
                   20134:
                   20135: #################################################
                   20136: # load a packed into %fp0:                     #
                   20137: #      -number can't fault                     #
                   20138: #      (1) calc ea                             #
                   20139: #      (2) read 12 bytes into L_SCR(1,2,3)     #
                   20140: #      (3) fmov.x into %fp0                    #
                   20141: #################################################
                   20142: load_packed:
                   20143:        bsr.l           get_packed
                   20144:
                   20145:        lea             FP_SRC(%a6),%a0         # pass ptr to src op
                   20146:        bsr.l           set_tag_x               # determine src type tag
                   20147:        cmpi.b          %d0,&UNNORM             # is the src op an UNNORM ZERO?
                   20148:        beq.b           load_packed_unnorm      # yes
                   20149:
                   20150:        mov.b           %d0,STAG(%a6)           # store the src optype tag
                   20151:        rts
                   20152:
                   20153: load_packed_unnorm:
                   20154:        bsr.l           unnorm_fix              # fix the UNNORM ZERO
                   20155:        mov.b           %d0,STAG(%a6)           # store the src optype tag
                   20156:        rts
                   20157:
                   20158: #########################################################################
                   20159: # XDEF ****************************************************************        #
                   20160: #      fout(): move from fp register to memory or data register        #
                   20161: #                                                                      #
                   20162: # XREF ****************************************************************        #
                   20163: #      _round() - needed to create EXOP for sgl/dbl precision          #
                   20164: #      norm() - needed to create EXOP for extended precision           #
                   20165: #      ovf_res() - create default overflow result for sgl/dbl precision#
                   20166: #      unf_res() - create default underflow result for sgl/dbl prec.   #
                   20167: #      dst_dbl() - create rounded dbl precision result.                #
                   20168: #      dst_sgl() - create rounded sgl precision result.                #
                   20169: #      fetch_dreg() - fetch dynamic k-factor reg for packed.           #
                   20170: #      bindec() - convert FP binary number to packed number.           #
                   20171: #      _mem_write() - write data to memory.                            #
                   20172: #      _mem_write2() - write data to memory unless supv mode -(a7) exc.#
                   20173: #      _dmem_write_{byte,word,long}() - write data to memory.          #
                   20174: #      store_dreg_{b,w,l}() - store data to data register file.        #
                   20175: #      facc_out_{b,w,l,d,x}() - data access error occurred.            #
                   20176: #                                                                      #
                   20177: # INPUT ***************************************************************        #
                   20178: #      a0 = pointer to extended precision source operand               #
                   20179: #      d0 = round prec,mode                                            #
                   20180: #                                                                      #
                   20181: # OUTPUT **************************************************************        #
                   20182: #      fp0 : intermediate underflow or overflow result if              #
                   20183: #            OVFL/UNFL occurred for a sgl or dbl operand               #
                   20184: #                                                                      #
                   20185: # ALGORITHM ***********************************************************        #
                   20186: #      This routine is accessed by many handlers that need to do an    #
                   20187: # opclass three move of an operand out to memory.                      #
                   20188: #      Decode an fmove out (opclass 3) instruction to determine if     #
                   20189: # it's b,w,l,s,d,x, or p in size. b,w,l can be stored to either a data #
                   20190: # register or memory. The algorithm uses a standard "fmove" to create  #
                   20191: # the rounded result. Also, since exceptions are disabled, this also   #
                   20192: # create the correct OPERR default result if appropriate.              #
                   20193: #      For sgl or dbl precision, overflow or underflow can occur. If   #
                   20194: # either occurs and is enabled, the EXOP.                              #
                   20195: #      For extended precision, the stacked <ea> must be fixed along    #
                   20196: # w/ the address index register as appropriate w/ _calc_ea_fout(). If  #
                   20197: # the source is a denorm and if underflow is enabled, an EXOP must be  #
                   20198: # created.                                                             #
                   20199: #      For packed, the k-factor must be fetched from the instruction   #
                   20200: # word or a data register. The <ea> must be fixed as w/ extended       #
                   20201: # precision. Then, bindec() is called to create the appropriate        #
                   20202: # packed result.                                                       #
                   20203: #      If at any time an access error is flagged by one of the move-   #
                   20204: # to-memory routines, then a special exit must be made so that the     #
                   20205: # access error can be handled properly.                                        #
                   20206: #                                                                      #
                   20207: #########################################################################
                   20208:
                   20209:        global          fout
                   20210: fout:
                   20211:        bfextu          EXC_CMDREG(%a6){&3:&3},%d1 # extract dst fmt
                   20212:        mov.w           (tbl_fout.b,%pc,%d1.w*2),%a1 # use as index
                   20213:        jmp             (tbl_fout.b,%pc,%a1)    # jump to routine
                   20214:
                   20215:        swbeg           &0x8
                   20216: tbl_fout:
                   20217:        short           fout_long       -       tbl_fout
                   20218:        short           fout_sgl        -       tbl_fout
                   20219:        short           fout_ext        -       tbl_fout
                   20220:        short           fout_pack       -       tbl_fout
                   20221:        short           fout_word       -       tbl_fout
                   20222:        short           fout_dbl        -       tbl_fout
                   20223:        short           fout_byte       -       tbl_fout
                   20224:        short           fout_pack       -       tbl_fout
                   20225:
                   20226: #################################################################
                   20227: # fmove.b out ###################################################
                   20228: #################################################################
                   20229:
                   20230: # Only "Unimplemented Data Type" exceptions enter here. The operand
                   20231: # is either a DENORM or a NORM.
                   20232: fout_byte:
                   20233:        tst.b           STAG(%a6)               # is operand normalized?
                   20234:        bne.b           fout_byte_denorm        # no
                   20235:
                   20236:        fmovm.x         SRC(%a0),&0x80          # load value
                   20237:
                   20238: fout_byte_norm:
                   20239:        fmov.l          %d0,%fpcr               # insert rnd prec,mode
                   20240:
                   20241:        fmov.b          %fp0,%d0                # exec move out w/ correct rnd mode
                   20242:
                   20243:        fmov.l          &0x0,%fpcr              # clear FPCR
                   20244:        fmov.l          %fpsr,%d1               # fetch FPSR
                   20245:        or.w            %d1,2+USER_FPSR(%a6)    # save new exc,accrued bits
                   20246:
                   20247:        mov.b           1+EXC_OPWORD(%a6),%d1   # extract dst mode
                   20248:        andi.b          &0x38,%d1               # is mode == 0? (Dreg dst)
                   20249:        beq.b           fout_byte_dn            # must save to integer regfile
                   20250:
                   20251:        mov.l           EXC_EA(%a6),%a0         # stacked <ea> is correct
                   20252:        bsr.l           _dmem_write_byte        # write byte
                   20253:
                   20254:        tst.l           %d1                     # did dstore fail?
                   20255:        bne.l           facc_out_b              # yes
                   20256:
                   20257:        rts
                   20258:
                   20259: fout_byte_dn:
                   20260:        mov.b           1+EXC_OPWORD(%a6),%d1   # extract Dn
                   20261:        andi.w          &0x7,%d1
                   20262:        bsr.l           store_dreg_b
                   20263:        rts
                   20264:
                   20265: fout_byte_denorm:
                   20266:        mov.l           SRC_EX(%a0),%d1
                   20267:        andi.l          &0x80000000,%d1         # keep DENORM sign
                   20268:        ori.l           &0x00800000,%d1         # make smallest sgl
                   20269:        fmov.s          %d1,%fp0
                   20270:        bra.b           fout_byte_norm
                   20271:
                   20272: #################################################################
                   20273: # fmove.w out ###################################################
                   20274: #################################################################
                   20275:
                   20276: # Only "Unimplemented Data Type" exceptions enter here. The operand
                   20277: # is either a DENORM or a NORM.
                   20278: fout_word:
                   20279:        tst.b           STAG(%a6)               # is operand normalized?
                   20280:        bne.b           fout_word_denorm        # no
                   20281:
                   20282:        fmovm.x         SRC(%a0),&0x80          # load value
                   20283:
                   20284: fout_word_norm:
                   20285:        fmov.l          %d0,%fpcr               # insert rnd prec:mode
                   20286:
                   20287:        fmov.w          %fp0,%d0                # exec move out w/ correct rnd mode
                   20288:
                   20289:        fmov.l          &0x0,%fpcr              # clear FPCR
                   20290:        fmov.l          %fpsr,%d1               # fetch FPSR
                   20291:        or.w            %d1,2+USER_FPSR(%a6)    # save new exc,accrued bits
                   20292:
                   20293:        mov.b           1+EXC_OPWORD(%a6),%d1   # extract dst mode
                   20294:        andi.b          &0x38,%d1               # is mode == 0? (Dreg dst)
                   20295:        beq.b           fout_word_dn            # must save to integer regfile
                   20296:
                   20297:        mov.l           EXC_EA(%a6),%a0         # stacked <ea> is correct
                   20298:        bsr.l           _dmem_write_word        # write word
                   20299:
                   20300:        tst.l           %d1                     # did dstore fail?
                   20301:        bne.l           facc_out_w              # yes
                   20302:
                   20303:        rts
                   20304:
                   20305: fout_word_dn:
                   20306:        mov.b           1+EXC_OPWORD(%a6),%d1   # extract Dn
                   20307:        andi.w          &0x7,%d1
                   20308:        bsr.l           store_dreg_w
                   20309:        rts
                   20310:
                   20311: fout_word_denorm:
                   20312:        mov.l           SRC_EX(%a0),%d1
                   20313:        andi.l          &0x80000000,%d1         # keep DENORM sign
                   20314:        ori.l           &0x00800000,%d1         # make smallest sgl
                   20315:        fmov.s          %d1,%fp0
                   20316:        bra.b           fout_word_norm
                   20317:
                   20318: #################################################################
                   20319: # fmove.l out ###################################################
                   20320: #################################################################
                   20321:
                   20322: # Only "Unimplemented Data Type" exceptions enter here. The operand
                   20323: # is either a DENORM or a NORM.
                   20324: fout_long:
                   20325:        tst.b           STAG(%a6)               # is operand normalized?
                   20326:        bne.b           fout_long_denorm        # no
                   20327:
                   20328:        fmovm.x         SRC(%a0),&0x80          # load value
                   20329:
                   20330: fout_long_norm:
                   20331:        fmov.l          %d0,%fpcr               # insert rnd prec:mode
                   20332:
                   20333:        fmov.l          %fp0,%d0                # exec move out w/ correct rnd mode
                   20334:
                   20335:        fmov.l          &0x0,%fpcr              # clear FPCR
                   20336:        fmov.l          %fpsr,%d1               # fetch FPSR
                   20337:        or.w            %d1,2+USER_FPSR(%a6)    # save new exc,accrued bits
                   20338:
                   20339: fout_long_write:
                   20340:        mov.b           1+EXC_OPWORD(%a6),%d1   # extract dst mode
                   20341:        andi.b          &0x38,%d1               # is mode == 0? (Dreg dst)
                   20342:        beq.b           fout_long_dn            # must save to integer regfile
                   20343:
                   20344:        mov.l           EXC_EA(%a6),%a0         # stacked <ea> is correct
                   20345:        bsr.l           _dmem_write_long        # write long
                   20346:
                   20347:        tst.l           %d1                     # did dstore fail?
                   20348:        bne.l           facc_out_l              # yes
                   20349:
                   20350:        rts
                   20351:
                   20352: fout_long_dn:
                   20353:        mov.b           1+EXC_OPWORD(%a6),%d1   # extract Dn
                   20354:        andi.w          &0x7,%d1
                   20355:        bsr.l           store_dreg_l
                   20356:        rts
                   20357:
                   20358: fout_long_denorm:
                   20359:        mov.l           SRC_EX(%a0),%d1
                   20360:        andi.l          &0x80000000,%d1         # keep DENORM sign
                   20361:        ori.l           &0x00800000,%d1         # make smallest sgl
                   20362:        fmov.s          %d1,%fp0
                   20363:        bra.b           fout_long_norm
                   20364:
                   20365: #################################################################
                   20366: # fmove.x out ###################################################
                   20367: #################################################################
                   20368:
                   20369: # Only "Unimplemented Data Type" exceptions enter here. The operand
                   20370: # is either a DENORM or a NORM.
                   20371: # The DENORM causes an Underflow exception.
                   20372: fout_ext:
                   20373:
                   20374: # we copy the extended precision result to FP_SCR0 so that the reserved
                   20375: # 16-bit field gets zeroed. we do this since we promise not to disturb
                   20376: # what's at SRC(a0).
                   20377:        mov.w           SRC_EX(%a0),FP_SCR0_EX(%a6)
                   20378:        clr.w           2+FP_SCR0_EX(%a6)       # clear reserved field
                   20379:        mov.l           SRC_HI(%a0),FP_SCR0_HI(%a6)
                   20380:        mov.l           SRC_LO(%a0),FP_SCR0_LO(%a6)
                   20381:
                   20382:        fmovm.x         SRC(%a0),&0x80          # return result
                   20383:
                   20384:        bsr.l           _calc_ea_fout           # fix stacked <ea>
                   20385:
                   20386:        mov.l           %a0,%a1                 # pass: dst addr
                   20387:        lea             FP_SCR0(%a6),%a0        # pass: src addr
                   20388:        mov.l           &0xc,%d0                # pass: opsize is 12 bytes
                   20389:
                   20390: # we must not yet write the extended precision data to the stack
                   20391: # in the pre-decrement case from supervisor mode or else we'll corrupt
                   20392: # the stack frame. so, leave it in FP_SRC for now and deal with it later...
                   20393:        cmpi.b          SPCOND_FLG(%a6),&mda7_flg
                   20394:        beq.b           fout_ext_a7
                   20395:
                   20396:        bsr.l           _dmem_write             # write ext prec number to memory
                   20397:
                   20398:        tst.l           %d1                     # did dstore fail?
                   20399:        bne.w           fout_ext_err            # yes
                   20400:
                   20401:        tst.b           STAG(%a6)               # is operand normalized?
                   20402:        bne.b           fout_ext_denorm         # no
                   20403:        rts
                   20404:
                   20405: # the number is a DENORM. must set the underflow exception bit
                   20406: fout_ext_denorm:
                   20407:        bset            &unfl_bit,FPSR_EXCEPT(%a6) # set underflow exc bit
                   20408:
                   20409:        mov.b           FPCR_ENABLE(%a6),%d0
                   20410:        andi.b          &0x0a,%d0               # is UNFL or INEX enabled?
                   20411:        bne.b           fout_ext_exc            # yes
                   20412:        rts
                   20413:
                   20414: # we don't want to do the write if the exception occurred in supervisor mode
                   20415: # so _mem_write2() handles this for us.
                   20416: fout_ext_a7:
                   20417:        bsr.l           _mem_write2             # write ext prec number to memory
                   20418:
                   20419:        tst.l           %d1                     # did dstore fail?
                   20420:        bne.w           fout_ext_err            # yes
                   20421:
                   20422:        tst.b           STAG(%a6)               # is operand normalized?
                   20423:        bne.b           fout_ext_denorm         # no
                   20424:        rts
                   20425:
                   20426: fout_ext_exc:
                   20427:        lea             FP_SCR0(%a6),%a0
                   20428:        bsr.l           norm                    # normalize the mantissa
                   20429:        neg.w           %d0                     # new exp = -(shft amt)
                   20430:        andi.w          &0x7fff,%d0
                   20431:        andi.w          &0x8000,FP_SCR0_EX(%a6) # keep only old sign
                   20432:        or.w            %d0,FP_SCR0_EX(%a6)     # insert new exponent
                   20433:        fmovm.x         FP_SCR0(%a6),&0x40      # return EXOP in fp1
                   20434:        rts
                   20435:
                   20436: fout_ext_err:
                   20437:        mov.l           EXC_A6(%a6),(%a6)       # fix stacked a6
                   20438:        bra.l           facc_out_x
                   20439:
                   20440: #########################################################################
                   20441: # fmove.s out ###########################################################
                   20442: #########################################################################
                   20443: fout_sgl:
                   20444:        andi.b          &0x30,%d0               # clear rnd prec
                   20445:        ori.b           &s_mode*0x10,%d0        # insert sgl prec
                   20446:        mov.l           %d0,L_SCR3(%a6)         # save rnd prec,mode on stack
                   20447:
                   20448: #
                   20449: # operand is a normalized number. first, we check to see if the move out
                   20450: # would cause either an underflow or overflow. these cases are handled
                   20451: # separately. otherwise, set the FPCR to the proper rounding mode and
                   20452: # execute the move.
                   20453: #
                   20454:        mov.w           SRC_EX(%a0),%d0         # extract exponent
                   20455:        andi.w          &0x7fff,%d0             # strip sign
                   20456:
                   20457:        cmpi.w          %d0,&SGL_HI             # will operand overflow?
                   20458:        bgt.w           fout_sgl_ovfl           # yes; go handle OVFL
                   20459:        beq.w           fout_sgl_may_ovfl       # maybe; go handle possible OVFL
                   20460:        cmpi.w          %d0,&SGL_LO             # will operand underflow?
                   20461:        blt.w           fout_sgl_unfl           # yes; go handle underflow
                   20462:
                   20463: #
                   20464: # NORMs(in range) can be stored out by a simple "fmov.s"
                   20465: # Unnormalized inputs can come through this point.
                   20466: #
                   20467: fout_sgl_exg:
                   20468:        fmovm.x         SRC(%a0),&0x80          # fetch fop from stack
                   20469:
                   20470:        fmov.l          L_SCR3(%a6),%fpcr       # set FPCR
                   20471:        fmov.l          &0x0,%fpsr              # clear FPSR
                   20472:
                   20473:        fmov.s          %fp0,%d0                # store does convert and round
                   20474:
                   20475:        fmov.l          &0x0,%fpcr              # clear FPCR
                   20476:        fmov.l          %fpsr,%d1               # save FPSR
                   20477:
                   20478:        or.w            %d1,2+USER_FPSR(%a6)    # set possible inex2/ainex
                   20479:
                   20480: fout_sgl_exg_write:
                   20481:        mov.b           1+EXC_OPWORD(%a6),%d1   # extract dst mode
                   20482:        andi.b          &0x38,%d1               # is mode == 0? (Dreg dst)
                   20483:        beq.b           fout_sgl_exg_write_dn   # must save to integer regfile
                   20484:
                   20485:        mov.l           EXC_EA(%a6),%a0         # stacked <ea> is correct
                   20486:        bsr.l           _dmem_write_long        # write long
                   20487:
                   20488:        tst.l           %d1                     # did dstore fail?
                   20489:        bne.l           facc_out_l              # yes
                   20490:
                   20491:        rts
                   20492:
                   20493: fout_sgl_exg_write_dn:
                   20494:        mov.b           1+EXC_OPWORD(%a6),%d1   # extract Dn
                   20495:        andi.w          &0x7,%d1
                   20496:        bsr.l           store_dreg_l
                   20497:        rts
                   20498:
                   20499: #
                   20500: # here, we know that the operand would UNFL if moved out to single prec,
                   20501: # so, denorm and round and then use generic store single routine to
                   20502: # write the value to memory.
                   20503: #
                   20504: fout_sgl_unfl:
                   20505:        bset            &unfl_bit,FPSR_EXCEPT(%a6) # set UNFL
                   20506:
                   20507:        mov.w           SRC_EX(%a0),FP_SCR0_EX(%a6)
                   20508:        mov.l           SRC_HI(%a0),FP_SCR0_HI(%a6)
                   20509:        mov.l           SRC_LO(%a0),FP_SCR0_LO(%a6)
                   20510:        mov.l           %a0,-(%sp)
                   20511:
                   20512:        clr.l           %d0                     # pass: S.F. = 0
                   20513:
                   20514:        cmpi.b          STAG(%a6),&DENORM       # fetch src optype tag
                   20515:        bne.b           fout_sgl_unfl_cont      # let DENORMs fall through
                   20516:
                   20517:        lea             FP_SCR0(%a6),%a0
                   20518:        bsr.l           norm                    # normalize the DENORM
                   20519:
                   20520: fout_sgl_unfl_cont:
                   20521:        lea             FP_SCR0(%a6),%a0        # pass: ptr to operand
                   20522:        mov.l           L_SCR3(%a6),%d1         # pass: rnd prec,mode
                   20523:        bsr.l           unf_res                 # calc default underflow result
                   20524:
                   20525:        lea             FP_SCR0(%a6),%a0        # pass: ptr to fop
                   20526:        bsr.l           dst_sgl                 # convert to single prec
                   20527:
                   20528:        mov.b           1+EXC_OPWORD(%a6),%d1   # extract dst mode
                   20529:        andi.b          &0x38,%d1               # is mode == 0? (Dreg dst)
                   20530:        beq.b           fout_sgl_unfl_dn        # must save to integer regfile
                   20531:
                   20532:        mov.l           EXC_EA(%a6),%a0         # stacked <ea> is correct
                   20533:        bsr.l           _dmem_write_long        # write long
                   20534:
                   20535:        tst.l           %d1                     # did dstore fail?
                   20536:        bne.l           facc_out_l              # yes
                   20537:
                   20538:        bra.b           fout_sgl_unfl_chkexc
                   20539:
                   20540: fout_sgl_unfl_dn:
                   20541:        mov.b           1+EXC_OPWORD(%a6),%d1   # extract Dn
                   20542:        andi.w          &0x7,%d1
                   20543:        bsr.l           store_dreg_l
                   20544:
                   20545: fout_sgl_unfl_chkexc:
                   20546:        mov.b           FPCR_ENABLE(%a6),%d1
                   20547:        andi.b          &0x0a,%d1               # is UNFL or INEX enabled?
                   20548:        bne.w           fout_sd_exc_unfl        # yes
                   20549:        addq.l          &0x4,%sp
                   20550:        rts
                   20551:
                   20552: #
                   20553: # it's definitely an overflow so call ovf_res to get the correct answer
                   20554: #
                   20555: fout_sgl_ovfl:
                   20556:        tst.b           3+SRC_HI(%a0)           # is result inexact?
                   20557:        bne.b           fout_sgl_ovfl_inex2
                   20558:        tst.l           SRC_LO(%a0)             # is result inexact?
                   20559:        bne.b           fout_sgl_ovfl_inex2
                   20560:        ori.w           &ovfl_inx_mask,2+USER_FPSR(%a6) # set ovfl/aovfl/ainex
                   20561:        bra.b           fout_sgl_ovfl_cont
                   20562: fout_sgl_ovfl_inex2:
                   20563:        ori.w           &ovfinx_mask,2+USER_FPSR(%a6) # set ovfl/aovfl/ainex/inex2
                   20564:
                   20565: fout_sgl_ovfl_cont:
                   20566:        mov.l           %a0,-(%sp)
                   20567:
                   20568: # call ovf_res() w/ sgl prec and the correct rnd mode to create the default
                   20569: # overflow result. DON'T save the returned ccodes from ovf_res() since
                   20570: # fmove out doesn't alter them.
                   20571:        tst.b           SRC_EX(%a0)             # is operand negative?
                   20572:        smi             %d1                     # set if so
                   20573:        mov.l           L_SCR3(%a6),%d0         # pass: sgl prec,rnd mode
                   20574:        bsr.l           ovf_res                 # calc OVFL result
                   20575:        fmovm.x         (%a0),&0x80             # load default overflow result
                   20576:        fmov.s          %fp0,%d0                # store to single
                   20577:
                   20578:        mov.b           1+EXC_OPWORD(%a6),%d1   # extract dst mode
                   20579:        andi.b          &0x38,%d1               # is mode == 0? (Dreg dst)
                   20580:        beq.b           fout_sgl_ovfl_dn        # must save to integer regfile
                   20581:
                   20582:        mov.l           EXC_EA(%a6),%a0         # stacked <ea> is correct
                   20583:        bsr.l           _dmem_write_long        # write long
                   20584:
                   20585:        tst.l           %d1                     # did dstore fail?
                   20586:        bne.l           facc_out_l              # yes
                   20587:
                   20588:        bra.b           fout_sgl_ovfl_chkexc
                   20589:
                   20590: fout_sgl_ovfl_dn:
                   20591:        mov.b           1+EXC_OPWORD(%a6),%d1   # extract Dn
                   20592:        andi.w          &0x7,%d1
                   20593:        bsr.l           store_dreg_l
                   20594:
                   20595: fout_sgl_ovfl_chkexc:
                   20596:        mov.b           FPCR_ENABLE(%a6),%d1
                   20597:        andi.b          &0x0a,%d1               # is UNFL or INEX enabled?
                   20598:        bne.w           fout_sd_exc_ovfl        # yes
                   20599:        addq.l          &0x4,%sp
                   20600:        rts
                   20601:
                   20602: #
                   20603: # move out MAY overflow:
                   20604: # (1) force the exp to 0x3fff
                   20605: # (2) do a move w/ appropriate rnd mode
                   20606: # (3) if exp still equals zero, then insert original exponent
                   20607: #      for the correct result.
                   20608: #     if exp now equals one, then it overflowed so call ovf_res.
                   20609: #
                   20610: fout_sgl_may_ovfl:
                   20611:        mov.w           SRC_EX(%a0),%d1         # fetch current sign
                   20612:        andi.w          &0x8000,%d1             # keep it,clear exp
                   20613:        ori.w           &0x3fff,%d1             # insert exp = 0
                   20614:        mov.w           %d1,FP_SCR0_EX(%a6)     # insert scaled exp
                   20615:        mov.l           SRC_HI(%a0),FP_SCR0_HI(%a6) # copy hi(man)
                   20616:        mov.l           SRC_LO(%a0),FP_SCR0_LO(%a6) # copy lo(man)
                   20617:
                   20618:        fmov.l          L_SCR3(%a6),%fpcr       # set FPCR
                   20619:
                   20620:        fmov.x          FP_SCR0(%a6),%fp0       # force fop to be rounded
                   20621:        fmov.l          &0x0,%fpcr              # clear FPCR
                   20622:
                   20623:        fabs.x          %fp0                    # need absolute value
                   20624:        fcmp.b          %fp0,&0x2               # did exponent increase?
                   20625:        fblt.w          fout_sgl_exg            # no; go finish NORM
                   20626:        bra.w           fout_sgl_ovfl           # yes; go handle overflow
                   20627:
                   20628: ################
                   20629:
                   20630: fout_sd_exc_unfl:
                   20631:        mov.l           (%sp)+,%a0
                   20632:
                   20633:        mov.w           SRC_EX(%a0),FP_SCR0_EX(%a6)
                   20634:        mov.l           SRC_HI(%a0),FP_SCR0_HI(%a6)
                   20635:        mov.l           SRC_LO(%a0),FP_SCR0_LO(%a6)
                   20636:
                   20637:        cmpi.b          STAG(%a6),&DENORM       # was src a DENORM?
                   20638:        bne.b           fout_sd_exc_cont        # no
                   20639:
                   20640:        lea             FP_SCR0(%a6),%a0
                   20641:        bsr.l           norm
                   20642:        neg.l           %d0
                   20643:        andi.w          &0x7fff,%d0
                   20644:        bfins           %d0,FP_SCR0_EX(%a6){&1:&15}
                   20645:        bra.b           fout_sd_exc_cont
                   20646:
                   20647: fout_sd_exc:
                   20648: fout_sd_exc_ovfl:
                   20649:        mov.l           (%sp)+,%a0              # restore a0
                   20650:
                   20651:        mov.w           SRC_EX(%a0),FP_SCR0_EX(%a6)
                   20652:        mov.l           SRC_HI(%a0),FP_SCR0_HI(%a6)
                   20653:        mov.l           SRC_LO(%a0),FP_SCR0_LO(%a6)
                   20654:
                   20655: fout_sd_exc_cont:
                   20656:        bclr            &0x7,FP_SCR0_EX(%a6)    # clear sign bit
                   20657:        sne.b           2+FP_SCR0_EX(%a6)       # set internal sign bit
                   20658:        lea             FP_SCR0(%a6),%a0        # pass: ptr to DENORM
                   20659:
                   20660:        mov.b           3+L_SCR3(%a6),%d1
                   20661:        lsr.b           &0x4,%d1
                   20662:        andi.w          &0x0c,%d1
                   20663:        swap            %d1
                   20664:        mov.b           3+L_SCR3(%a6),%d1
                   20665:        lsr.b           &0x4,%d1
                   20666:        andi.w          &0x03,%d1
                   20667:        clr.l           %d0                     # pass: zero g,r,s
                   20668:        bsr.l           _round                  # round the DENORM
                   20669:
                   20670:        tst.b           2+FP_SCR0_EX(%a6)       # is EXOP negative?
                   20671:        beq.b           fout_sd_exc_done        # no
                   20672:        bset            &0x7,FP_SCR0_EX(%a6)    # yes
                   20673:
                   20674: fout_sd_exc_done:
                   20675:        fmovm.x         FP_SCR0(%a6),&0x40      # return EXOP in fp1
                   20676:        rts
                   20677:
                   20678: #################################################################
                   20679: # fmove.d out ###################################################
                   20680: #################################################################
                   20681: fout_dbl:
                   20682:        andi.b          &0x30,%d0               # clear rnd prec
                   20683:        ori.b           &d_mode*0x10,%d0        # insert dbl prec
                   20684:        mov.l           %d0,L_SCR3(%a6)         # save rnd prec,mode on stack
                   20685:
                   20686: #
                   20687: # operand is a normalized number. first, we check to see if the move out
                   20688: # would cause either an underflow or overflow. these cases are handled
                   20689: # separately. otherwise, set the FPCR to the proper rounding mode and
                   20690: # execute the move.
                   20691: #
                   20692:        mov.w           SRC_EX(%a0),%d0         # extract exponent
                   20693:        andi.w          &0x7fff,%d0             # strip sign
                   20694:
                   20695:        cmpi.w          %d0,&DBL_HI             # will operand overflow?
                   20696:        bgt.w           fout_dbl_ovfl           # yes; go handle OVFL
                   20697:        beq.w           fout_dbl_may_ovfl       # maybe; go handle possible OVFL
                   20698:        cmpi.w          %d0,&DBL_LO             # will operand underflow?
                   20699:        blt.w           fout_dbl_unfl           # yes; go handle underflow
                   20700:
                   20701: #
                   20702: # NORMs(in range) can be stored out by a simple "fmov.d"
                   20703: # Unnormalized inputs can come through this point.
                   20704: #
                   20705: fout_dbl_exg:
                   20706:        fmovm.x         SRC(%a0),&0x80          # fetch fop from stack
                   20707:
                   20708:        fmov.l          L_SCR3(%a6),%fpcr       # set FPCR
                   20709:        fmov.l          &0x0,%fpsr              # clear FPSR
                   20710:
                   20711:        fmov.d          %fp0,L_SCR1(%a6)        # store does convert and round
                   20712:
                   20713:        fmov.l          &0x0,%fpcr              # clear FPCR
                   20714:        fmov.l          %fpsr,%d0               # save FPSR
                   20715:
                   20716:        or.w            %d0,2+USER_FPSR(%a6)    # set possible inex2/ainex
                   20717:
                   20718:        mov.l           EXC_EA(%a6),%a1         # pass: dst addr
                   20719:        lea             L_SCR1(%a6),%a0         # pass: src addr
                   20720:        movq.l          &0x8,%d0                # pass: opsize is 8 bytes
                   20721:        bsr.l           _dmem_write             # store dbl fop to memory
                   20722:
                   20723:        tst.l           %d1                     # did dstore fail?
                   20724:        bne.l           facc_out_d              # yes
                   20725:
                   20726:        rts                                     # no; so we're finished
                   20727:
                   20728: #
                   20729: # here, we know that the operand would UNFL if moved out to double prec,
                   20730: # so, denorm and round and then use generic store double routine to
                   20731: # write the value to memory.
                   20732: #
                   20733: fout_dbl_unfl:
                   20734:        bset            &unfl_bit,FPSR_EXCEPT(%a6) # set UNFL
                   20735:
                   20736:        mov.w           SRC_EX(%a0),FP_SCR0_EX(%a6)
                   20737:        mov.l           SRC_HI(%a0),FP_SCR0_HI(%a6)
                   20738:        mov.l           SRC_LO(%a0),FP_SCR0_LO(%a6)
                   20739:        mov.l           %a0,-(%sp)
                   20740:
                   20741:        clr.l           %d0                     # pass: S.F. = 0
                   20742:
                   20743:        cmpi.b          STAG(%a6),&DENORM       # fetch src optype tag
                   20744:        bne.b           fout_dbl_unfl_cont      # let DENORMs fall through
                   20745:
                   20746:        lea             FP_SCR0(%a6),%a0
                   20747:        bsr.l           norm                    # normalize the DENORM
                   20748:
                   20749: fout_dbl_unfl_cont:
                   20750:        lea             FP_SCR0(%a6),%a0        # pass: ptr to operand
                   20751:        mov.l           L_SCR3(%a6),%d1         # pass: rnd prec,mode
                   20752:        bsr.l           unf_res                 # calc default underflow result
                   20753:
                   20754:        lea             FP_SCR0(%a6),%a0        # pass: ptr to fop
                   20755:        bsr.l           dst_dbl                 # convert to single prec
                   20756:        mov.l           %d0,L_SCR1(%a6)
                   20757:        mov.l           %d1,L_SCR2(%a6)
                   20758:
                   20759:        mov.l           EXC_EA(%a6),%a1         # pass: dst addr
                   20760:        lea             L_SCR1(%a6),%a0         # pass: src addr
                   20761:        movq.l          &0x8,%d0                # pass: opsize is 8 bytes
                   20762:        bsr.l           _dmem_write             # store dbl fop to memory
                   20763:
                   20764:        tst.l           %d1                     # did dstore fail?
                   20765:        bne.l           facc_out_d              # yes
                   20766:
                   20767:        mov.b           FPCR_ENABLE(%a6),%d1
                   20768:        andi.b          &0x0a,%d1               # is UNFL or INEX enabled?
                   20769:        bne.w           fout_sd_exc_unfl        # yes
                   20770:        addq.l          &0x4,%sp
                   20771:        rts
                   20772:
                   20773: #
                   20774: # it's definitely an overflow so call ovf_res to get the correct answer
                   20775: #
                   20776: fout_dbl_ovfl:
                   20777:        mov.w           2+SRC_LO(%a0),%d0
                   20778:        andi.w          &0x7ff,%d0
                   20779:        bne.b           fout_dbl_ovfl_inex2
                   20780:
                   20781:        ori.w           &ovfl_inx_mask,2+USER_FPSR(%a6) # set ovfl/aovfl/ainex
                   20782:        bra.b           fout_dbl_ovfl_cont
                   20783: fout_dbl_ovfl_inex2:
                   20784:        ori.w           &ovfinx_mask,2+USER_FPSR(%a6) # set ovfl/aovfl/ainex/inex2
                   20785:
                   20786: fout_dbl_ovfl_cont:
                   20787:        mov.l           %a0,-(%sp)
                   20788:
                   20789: # call ovf_res() w/ dbl prec and the correct rnd mode to create the default
                   20790: # overflow result. DON'T save the returned ccodes from ovf_res() since
                   20791: # fmove out doesn't alter them.
                   20792:        tst.b           SRC_EX(%a0)             # is operand negative?
                   20793:        smi             %d1                     # set if so
                   20794:        mov.l           L_SCR3(%a6),%d0         # pass: dbl prec,rnd mode
                   20795:        bsr.l           ovf_res                 # calc OVFL result
                   20796:        fmovm.x         (%a0),&0x80             # load default overflow result
                   20797:        fmov.d          %fp0,L_SCR1(%a6)        # store to double
                   20798:
                   20799:        mov.l           EXC_EA(%a6),%a1         # pass: dst addr
                   20800:        lea             L_SCR1(%a6),%a0         # pass: src addr
                   20801:        movq.l          &0x8,%d0                # pass: opsize is 8 bytes
                   20802:        bsr.l           _dmem_write             # store dbl fop to memory
                   20803:
                   20804:        tst.l           %d1                     # did dstore fail?
                   20805:        bne.l           facc_out_d              # yes
                   20806:
                   20807:        mov.b           FPCR_ENABLE(%a6),%d1
                   20808:        andi.b          &0x0a,%d1               # is UNFL or INEX enabled?
                   20809:        bne.w           fout_sd_exc_ovfl        # yes
                   20810:        addq.l          &0x4,%sp
                   20811:        rts
                   20812:
                   20813: #
                   20814: # move out MAY overflow:
                   20815: # (1) force the exp to 0x3fff
                   20816: # (2) do a move w/ appropriate rnd mode
                   20817: # (3) if exp still equals zero, then insert original exponent
                   20818: #      for the correct result.
                   20819: #     if exp now equals one, then it overflowed so call ovf_res.
                   20820: #
                   20821: fout_dbl_may_ovfl:
                   20822:        mov.w           SRC_EX(%a0),%d1         # fetch current sign
                   20823:        andi.w          &0x8000,%d1             # keep it,clear exp
                   20824:        ori.w           &0x3fff,%d1             # insert exp = 0
                   20825:        mov.w           %d1,FP_SCR0_EX(%a6)     # insert scaled exp
                   20826:        mov.l           SRC_HI(%a0),FP_SCR0_HI(%a6) # copy hi(man)
                   20827:        mov.l           SRC_LO(%a0),FP_SCR0_LO(%a6) # copy lo(man)
                   20828:
                   20829:        fmov.l          L_SCR3(%a6),%fpcr       # set FPCR
                   20830:
                   20831:        fmov.x          FP_SCR0(%a6),%fp0       # force fop to be rounded
                   20832:        fmov.l          &0x0,%fpcr              # clear FPCR
                   20833:
                   20834:        fabs.x          %fp0                    # need absolute value
                   20835:        fcmp.b          %fp0,&0x2               # did exponent increase?
                   20836:        fblt.w          fout_dbl_exg            # no; go finish NORM
                   20837:        bra.w           fout_dbl_ovfl           # yes; go handle overflow
                   20838:
                   20839: #########################################################################
                   20840: # XDEF ****************************************************************        #
                   20841: #      dst_dbl(): create double precision value from extended prec.    #
                   20842: #                                                                      #
                   20843: # XREF ****************************************************************        #
                   20844: #      None                                                            #
                   20845: #                                                                      #
                   20846: # INPUT ***************************************************************        #
                   20847: #      a0 = pointer to source operand in extended precision            #
                   20848: #                                                                      #
                   20849: # OUTPUT **************************************************************        #
                   20850: #      d0 = hi(double precision result)                                #
                   20851: #      d1 = lo(double precision result)                                #
                   20852: #                                                                      #
                   20853: # ALGORITHM ***********************************************************        #
                   20854: #                                                                      #
                   20855: #  Changes extended precision to double precision.                     #
                   20856: #  Note: no attempt is made to round the extended value to double.     #
                   20857: #      dbl_sign = ext_sign                                             #
                   20858: #      dbl_exp = ext_exp - $3fff(ext bias) + $7ff(dbl bias)            #
                   20859: #      get rid of ext integer bit                                      #
                   20860: #      dbl_mant = ext_mant{62:12}                                      #
                   20861: #                                                                      #
                   20862: #              ---------------   ---------------    ---------------    #
                   20863: #  extended ->  |s|    exp    |   |1| ms mant   |    | ls mant     |   #
                   20864: #              ---------------   ---------------    ---------------    #
                   20865: #               95         64    63 62       32      31     11   0     #
                   20866: #                                   |                       |          #
                   20867: #                                   |                       |          #
                   20868: #                                   |                       |          #
                   20869: #                                   v                       v          #
                   20870: #                            ---------------   ---------------         #
                   20871: #  double   ->               |s|exp| mant  |   |  mant       |         #
                   20872: #                            ---------------   ---------------         #
                   20873: #                            63     51   32   31              0        #
                   20874: #                                                                      #
                   20875: #########################################################################
                   20876:
                   20877: dst_dbl:
                   20878:        clr.l           %d0                     # clear d0
                   20879:        mov.w           FTEMP_EX(%a0),%d0       # get exponent
                   20880:        subi.w          &EXT_BIAS,%d0           # subtract extended precision bias
                   20881:        addi.w          &DBL_BIAS,%d0           # add double precision bias
                   20882:        tst.b           FTEMP_HI(%a0)           # is number a denorm?
                   20883:        bmi.b           dst_get_dupper          # no
                   20884:        subq.w          &0x1,%d0                # yes; denorm bias = DBL_BIAS - 1
                   20885: dst_get_dupper:
                   20886:        swap            %d0                     # d0 now in upper word
                   20887:        lsl.l           &0x4,%d0                # d0 in proper place for dbl prec exp
                   20888:        tst.b           FTEMP_EX(%a0)           # test sign
                   20889:        bpl.b           dst_get_dman            # if positive, go process mantissa
                   20890:        bset            &0x1f,%d0               # if negative, set sign
                   20891: dst_get_dman:
                   20892:        mov.l           FTEMP_HI(%a0),%d1       # get ms mantissa
                   20893:        bfextu          %d1{&1:&20},%d1         # get upper 20 bits of ms
                   20894:        or.l            %d1,%d0                 # put these bits in ms word of double
                   20895:        mov.l           %d0,L_SCR1(%a6)         # put the new exp back on the stack
                   20896:        mov.l           FTEMP_HI(%a0),%d1       # get ms mantissa
                   20897:        mov.l           &21,%d0                 # load shift count
                   20898:        lsl.l           %d0,%d1                 # put lower 11 bits in upper bits
                   20899:        mov.l           %d1,L_SCR2(%a6)         # build lower lword in memory
                   20900:        mov.l           FTEMP_LO(%a0),%d1       # get ls mantissa
                   20901:        bfextu          %d1{&0:&21},%d0         # get ls 21 bits of double
                   20902:        mov.l           L_SCR2(%a6),%d1
                   20903:        or.l            %d0,%d1                 # put them in double result
                   20904:        mov.l           L_SCR1(%a6),%d0
                   20905:        rts
                   20906:
                   20907: #########################################################################
                   20908: # XDEF ****************************************************************        #
                   20909: #      dst_sgl(): create single precision value from extended prec     #
                   20910: #                                                                      #
                   20911: # XREF ****************************************************************        #
                   20912: #                                                                      #
                   20913: # INPUT ***************************************************************        #
                   20914: #      a0 = pointer to source operand in extended precision            #
                   20915: #                                                                      #
                   20916: # OUTPUT **************************************************************        #
                   20917: #      d0 = single precision result                                    #
                   20918: #                                                                      #
                   20919: # ALGORITHM ***********************************************************        #
                   20920: #                                                                      #
                   20921: # Changes extended precision to single precision.                      #
                   20922: #      sgl_sign = ext_sign                                             #
                   20923: #      sgl_exp = ext_exp - $3fff(ext bias) + $7f(sgl bias)             #
                   20924: #      get rid of ext integer bit                                      #
                   20925: #      sgl_mant = ext_mant{62:12}                                      #
                   20926: #                                                                      #
                   20927: #              ---------------   ---------------    ---------------    #
                   20928: #  extended ->  |s|    exp    |   |1| ms mant   |    | ls mant     |   #
                   20929: #              ---------------   ---------------    ---------------    #
                   20930: #               95         64    63 62    40 32      31     12   0     #
                   20931: #                                   |     |                            #
                   20932: #                                   |     |                            #
                   20933: #                                   |     |                            #
                   20934: #                                   v     v                            #
                   20935: #                            ---------------                           #
                   20936: #  single   ->               |s|exp| mant  |                           #
                   20937: #                            ---------------                           #
                   20938: #                            31     22     0                           #
                   20939: #                                                                      #
                   20940: #########################################################################
                   20941:
                   20942: dst_sgl:
                   20943:        clr.l           %d0
                   20944:        mov.w           FTEMP_EX(%a0),%d0       # get exponent
                   20945:        subi.w          &EXT_BIAS,%d0           # subtract extended precision bias
                   20946:        addi.w          &SGL_BIAS,%d0           # add single precision bias
                   20947:        tst.b           FTEMP_HI(%a0)           # is number a denorm?
                   20948:        bmi.b           dst_get_supper          # no
                   20949:        subq.w          &0x1,%d0                # yes; denorm bias = SGL_BIAS - 1
                   20950: dst_get_supper:
                   20951:        swap            %d0                     # put exp in upper word of d0
                   20952:        lsl.l           &0x7,%d0                # shift it into single exp bits
                   20953:        tst.b           FTEMP_EX(%a0)           # test sign
                   20954:        bpl.b           dst_get_sman            # if positive, continue
                   20955:        bset            &0x1f,%d0               # if negative, put in sign first
                   20956: dst_get_sman:
                   20957:        mov.l           FTEMP_HI(%a0),%d1       # get ms mantissa
                   20958:        andi.l          &0x7fffff00,%d1         # get upper 23 bits of ms
                   20959:        lsr.l           &0x8,%d1                # and put them flush right
                   20960:        or.l            %d1,%d0                 # put these bits in ms word of single
                   20961:        rts
                   20962:
                   20963: ##############################################################################
                   20964: fout_pack:
                   20965:        bsr.l           _calc_ea_fout           # fetch the <ea>
                   20966:        mov.l           %a0,-(%sp)
                   20967:
                   20968:        mov.b           STAG(%a6),%d0           # fetch input type
                   20969:        bne.w           fout_pack_not_norm      # input is not NORM
                   20970:
                   20971: fout_pack_norm:
                   20972:        btst            &0x4,EXC_CMDREG(%a6)    # static or dynamic?
                   20973:        beq.b           fout_pack_s             # static
                   20974:
                   20975: fout_pack_d:
                   20976:        mov.b           1+EXC_CMDREG(%a6),%d1   # fetch dynamic reg
                   20977:        lsr.b           &0x4,%d1
                   20978:        andi.w          &0x7,%d1
                   20979:
                   20980:        bsr.l           fetch_dreg              # fetch Dn w/ k-factor
                   20981:
                   20982:        bra.b           fout_pack_type
                   20983: fout_pack_s:
                   20984:        mov.b           1+EXC_CMDREG(%a6),%d0   # fetch static field
                   20985:
                   20986: fout_pack_type:
                   20987:        bfexts          %d0{&25:&7},%d0         # extract k-factor
                   20988:        mov.l   %d0,-(%sp)
                   20989:
                   20990:        lea             FP_SRC(%a6),%a0         # pass: ptr to input
                   20991:
                   20992: # bindec is currently scrambling FP_SRC for denorm inputs.
                   20993: # we'll have to change this, but for now, tough luck!!!
                   20994:        bsr.l           bindec                  # convert xprec to packed
                   20995:
                   20996: #      andi.l          &0xcfff000f,FP_SCR0(%a6) # clear unused fields
                   20997:        andi.l          &0xcffff00f,FP_SCR0(%a6) # clear unused fields
                   20998:
                   20999:        mov.l   (%sp)+,%d0
                   21000:
                   21001:        tst.b           3+FP_SCR0_EX(%a6)
                   21002:        bne.b           fout_pack_set
                   21003:        tst.l           FP_SCR0_HI(%a6)
                   21004:        bne.b           fout_pack_set
                   21005:        tst.l           FP_SCR0_LO(%a6)
                   21006:        bne.b           fout_pack_set
                   21007:
                   21008: # add the extra condition that only if the k-factor was zero, too, should
                   21009: # we zero the exponent
                   21010:        tst.l           %d0
                   21011:        bne.b           fout_pack_set
                   21012: # "mantissa" is all zero which means that the answer is zero. but, the '040
                   21013: # algorithm allows the exponent to be non-zero. the 881/2 do not. therefore,
                   21014: # if the mantissa is zero, I will zero the exponent, too.
                   21015: # the question now is whether the exponents sign bit is allowed to be non-zero
                   21016: # for a zero, also...
                   21017:        andi.w          &0xf000,FP_SCR0(%a6)
                   21018:
                   21019: fout_pack_set:
                   21020:
                   21021:        lea             FP_SCR0(%a6),%a0        # pass: src addr
                   21022:
                   21023: fout_pack_write:
                   21024:        mov.l           (%sp)+,%a1              # pass: dst addr
                   21025:        mov.l           &0xc,%d0                # pass: opsize is 12 bytes
                   21026:
                   21027:        cmpi.b          SPCOND_FLG(%a6),&mda7_flg
                   21028:        beq.b           fout_pack_a7
                   21029:
                   21030:        bsr.l           _dmem_write             # write ext prec number to memory
                   21031:
                   21032:        tst.l           %d1                     # did dstore fail?
                   21033:        bne.w           fout_ext_err            # yes
                   21034:
                   21035:        rts
                   21036:
                   21037: # we don't want to do the write if the exception occurred in supervisor mode
                   21038: # so _mem_write2() handles this for us.
                   21039: fout_pack_a7:
                   21040:        bsr.l           _mem_write2             # write ext prec number to memory
                   21041:
                   21042:        tst.l           %d1                     # did dstore fail?
                   21043:        bne.w           fout_ext_err            # yes
                   21044:
                   21045:        rts
                   21046:
                   21047: fout_pack_not_norm:
                   21048:        cmpi.b          %d0,&DENORM             # is it a DENORM?
                   21049:        beq.w           fout_pack_norm          # yes
                   21050:        lea             FP_SRC(%a6),%a0
                   21051:        clr.w           2+FP_SRC_EX(%a6)
                   21052:        cmpi.b          %d0,&SNAN               # is it an SNAN?
                   21053:        beq.b           fout_pack_snan          # yes
                   21054:        bra.b           fout_pack_write         # no
                   21055:
                   21056: fout_pack_snan:
                   21057:        ori.w           &snaniop2_mask,FPSR_EXCEPT(%a6) # set SNAN/AIOP
                   21058:        bset            &0x6,FP_SRC_HI(%a6)     # set snan bit
                   21059:        bra.b           fout_pack_write
                   21060:
                   21061: #########################################################################
                   21062: # XDEF ****************************************************************        #
                   21063: #      fetch_dreg(): fetch register according to index in d1           #
                   21064: #                                                                      #
                   21065: # XREF ****************************************************************        #
                   21066: #      None                                                            #
                   21067: #                                                                      #
                   21068: # INPUT ***************************************************************        #
                   21069: #      d1 = index of register to fetch from                            #
                   21070: #                                                                      #
                   21071: # OUTPUT **************************************************************        #
                   21072: #      d0 = value of register fetched                                  #
                   21073: #                                                                      #
                   21074: # ALGORITHM ***********************************************************        #
                   21075: #      According to the index value in d1 which can range from zero    #
                   21076: # to fifteen, load the corresponding register file value (where        #
                   21077: # address register indexes start at 8). D0/D1/A0/A1/A6/A7 are on the   #
                   21078: # stack. The rest should still be in their original places.            #
                   21079: #                                                                      #
                   21080: #########################################################################
                   21081:
                   21082: # this routine leaves d1 intact for subsequent store_dreg calls.
                   21083:        global          fetch_dreg
                   21084: fetch_dreg:
                   21085:        mov.w           (tbl_fdreg.b,%pc,%d1.w*2),%d0
                   21086:        jmp             (tbl_fdreg.b,%pc,%d0.w*1)
                   21087:
                   21088: tbl_fdreg:
                   21089:        short           fdreg0 - tbl_fdreg
                   21090:        short           fdreg1 - tbl_fdreg
                   21091:        short           fdreg2 - tbl_fdreg
                   21092:        short           fdreg3 - tbl_fdreg
                   21093:        short           fdreg4 - tbl_fdreg
                   21094:        short           fdreg5 - tbl_fdreg
                   21095:        short           fdreg6 - tbl_fdreg
                   21096:        short           fdreg7 - tbl_fdreg
                   21097:        short           fdreg8 - tbl_fdreg
                   21098:        short           fdreg9 - tbl_fdreg
                   21099:        short           fdrega - tbl_fdreg
                   21100:        short           fdregb - tbl_fdreg
                   21101:        short           fdregc - tbl_fdreg
                   21102:        short           fdregd - tbl_fdreg
                   21103:        short           fdrege - tbl_fdreg
                   21104:        short           fdregf - tbl_fdreg
                   21105:
                   21106: fdreg0:
                   21107:        mov.l           EXC_DREGS+0x0(%a6),%d0
                   21108:        rts
                   21109: fdreg1:
                   21110:        mov.l           EXC_DREGS+0x4(%a6),%d0
                   21111:        rts
                   21112: fdreg2:
                   21113:        mov.l           %d2,%d0
                   21114:        rts
                   21115: fdreg3:
                   21116:        mov.l           %d3,%d0
                   21117:        rts
                   21118: fdreg4:
                   21119:        mov.l           %d4,%d0
                   21120:        rts
                   21121: fdreg5:
                   21122:        mov.l           %d5,%d0
                   21123:        rts
                   21124: fdreg6:
                   21125:        mov.l           %d6,%d0
                   21126:        rts
                   21127: fdreg7:
                   21128:        mov.l           %d7,%d0
                   21129:        rts
                   21130: fdreg8:
                   21131:        mov.l           EXC_DREGS+0x8(%a6),%d0
                   21132:        rts
                   21133: fdreg9:
                   21134:        mov.l           EXC_DREGS+0xc(%a6),%d0
                   21135:        rts
                   21136: fdrega:
                   21137:        mov.l           %a2,%d0
                   21138:        rts
                   21139: fdregb:
                   21140:        mov.l           %a3,%d0
                   21141:        rts
                   21142: fdregc:
                   21143:        mov.l           %a4,%d0
                   21144:        rts
                   21145: fdregd:
                   21146:        mov.l           %a5,%d0
                   21147:        rts
                   21148: fdrege:
                   21149:        mov.l           (%a6),%d0
                   21150:        rts
                   21151: fdregf:
                   21152:        mov.l           EXC_A7(%a6),%d0
                   21153:        rts
                   21154:
                   21155: #########################################################################
                   21156: # XDEF ****************************************************************        #
                   21157: #      store_dreg_l(): store longword to data register specified by d1 #
                   21158: #                                                                      #
                   21159: # XREF ****************************************************************        #
                   21160: #      None                                                            #
                   21161: #                                                                      #
                   21162: # INPUT ***************************************************************        #
                   21163: #      d0 = longowrd value to store                                    #
                   21164: #      d1 = index of register to fetch from                            #
                   21165: #                                                                      #
                   21166: # OUTPUT **************************************************************        #
                   21167: #      (data register is updated)                                      #
                   21168: #                                                                      #
                   21169: # ALGORITHM ***********************************************************        #
                   21170: #      According to the index value in d1, store the longword value    #
                   21171: # in d0 to the corresponding data register. D0/D1 are on the stack     #
                   21172: # while the rest are in their initial places.                          #
                   21173: #                                                                      #
                   21174: #########################################################################
                   21175:
                   21176:        global          store_dreg_l
                   21177: store_dreg_l:
                   21178:        mov.w           (tbl_sdregl.b,%pc,%d1.w*2),%d1
                   21179:        jmp             (tbl_sdregl.b,%pc,%d1.w*1)
                   21180:
                   21181: tbl_sdregl:
                   21182:        short           sdregl0 - tbl_sdregl
                   21183:        short           sdregl1 - tbl_sdregl
                   21184:        short           sdregl2 - tbl_sdregl
                   21185:        short           sdregl3 - tbl_sdregl
                   21186:        short           sdregl4 - tbl_sdregl
                   21187:        short           sdregl5 - tbl_sdregl
                   21188:        short           sdregl6 - tbl_sdregl
                   21189:        short           sdregl7 - tbl_sdregl
                   21190:
                   21191: sdregl0:
                   21192:        mov.l           %d0,EXC_DREGS+0x0(%a6)
                   21193:        rts
                   21194: sdregl1:
                   21195:        mov.l           %d0,EXC_DREGS+0x4(%a6)
                   21196:        rts
                   21197: sdregl2:
                   21198:        mov.l           %d0,%d2
                   21199:        rts
                   21200: sdregl3:
                   21201:        mov.l           %d0,%d3
                   21202:        rts
                   21203: sdregl4:
                   21204:        mov.l           %d0,%d4
                   21205:        rts
                   21206: sdregl5:
                   21207:        mov.l           %d0,%d5
                   21208:        rts
                   21209: sdregl6:
                   21210:        mov.l           %d0,%d6
                   21211:        rts
                   21212: sdregl7:
                   21213:        mov.l           %d0,%d7
                   21214:        rts
                   21215:
                   21216: #########################################################################
                   21217: # XDEF ****************************************************************        #
                   21218: #      store_dreg_w(): store word to data register specified by d1     #
                   21219: #                                                                      #
                   21220: # XREF ****************************************************************        #
                   21221: #      None                                                            #
                   21222: #                                                                      #
                   21223: # INPUT ***************************************************************        #
                   21224: #      d0 = word value to store                                        #
                   21225: #      d1 = index of register to fetch from                            #
                   21226: #                                                                      #
                   21227: # OUTPUT **************************************************************        #
                   21228: #      (data register is updated)                                      #
                   21229: #                                                                      #
                   21230: # ALGORITHM ***********************************************************        #
                   21231: #      According to the index value in d1, store the word value        #
                   21232: # in d0 to the corresponding data register. D0/D1 are on the stack     #
                   21233: # while the rest are in their initial places.                          #
                   21234: #                                                                      #
                   21235: #########################################################################
                   21236:
                   21237:        global          store_dreg_w
                   21238: store_dreg_w:
                   21239:        mov.w           (tbl_sdregw.b,%pc,%d1.w*2),%d1
                   21240:        jmp             (tbl_sdregw.b,%pc,%d1.w*1)
                   21241:
                   21242: tbl_sdregw:
                   21243:        short           sdregw0 - tbl_sdregw
                   21244:        short           sdregw1 - tbl_sdregw
                   21245:        short           sdregw2 - tbl_sdregw
                   21246:        short           sdregw3 - tbl_sdregw
                   21247:        short           sdregw4 - tbl_sdregw
                   21248:        short           sdregw5 - tbl_sdregw
                   21249:        short           sdregw6 - tbl_sdregw
                   21250:        short           sdregw7 - tbl_sdregw
                   21251:
                   21252: sdregw0:
                   21253:        mov.w           %d0,2+EXC_DREGS+0x0(%a6)
                   21254:        rts
                   21255: sdregw1:
                   21256:        mov.w           %d0,2+EXC_DREGS+0x4(%a6)
                   21257:        rts
                   21258: sdregw2:
                   21259:        mov.w           %d0,%d2
                   21260:        rts
                   21261: sdregw3:
                   21262:        mov.w           %d0,%d3
                   21263:        rts
                   21264: sdregw4:
                   21265:        mov.w           %d0,%d4
                   21266:        rts
                   21267: sdregw5:
                   21268:        mov.w           %d0,%d5
                   21269:        rts
                   21270: sdregw6:
                   21271:        mov.w           %d0,%d6
                   21272:        rts
                   21273: sdregw7:
                   21274:        mov.w           %d0,%d7
                   21275:        rts
                   21276:
                   21277: #########################################################################
                   21278: # XDEF ****************************************************************        #
                   21279: #      store_dreg_b(): store byte to data register specified by d1     #
                   21280: #                                                                      #
                   21281: # XREF ****************************************************************        #
                   21282: #      None                                                            #
                   21283: #                                                                      #
                   21284: # INPUT ***************************************************************        #
                   21285: #      d0 = byte value to store                                        #
                   21286: #      d1 = index of register to fetch from                            #
                   21287: #                                                                      #
                   21288: # OUTPUT **************************************************************        #
                   21289: #      (data register is updated)                                      #
                   21290: #                                                                      #
                   21291: # ALGORITHM ***********************************************************        #
                   21292: #      According to the index value in d1, store the byte value        #
                   21293: # in d0 to the corresponding data register. D0/D1 are on the stack     #
                   21294: # while the rest are in their initial places.                          #
                   21295: #                                                                      #
                   21296: #########################################################################
                   21297:
                   21298:        global          store_dreg_b
                   21299: store_dreg_b:
                   21300:        mov.w           (tbl_sdregb.b,%pc,%d1.w*2),%d1
                   21301:        jmp             (tbl_sdregb.b,%pc,%d1.w*1)
                   21302:
                   21303: tbl_sdregb:
                   21304:        short           sdregb0 - tbl_sdregb
                   21305:        short           sdregb1 - tbl_sdregb
                   21306:        short           sdregb2 - tbl_sdregb
                   21307:        short           sdregb3 - tbl_sdregb
                   21308:        short           sdregb4 - tbl_sdregb
                   21309:        short           sdregb5 - tbl_sdregb
                   21310:        short           sdregb6 - tbl_sdregb
                   21311:        short           sdregb7 - tbl_sdregb
                   21312:
                   21313: sdregb0:
                   21314:        mov.b           %d0,3+EXC_DREGS+0x0(%a6)
                   21315:        rts
                   21316: sdregb1:
                   21317:        mov.b           %d0,3+EXC_DREGS+0x4(%a6)
                   21318:        rts
                   21319: sdregb2:
                   21320:        mov.b           %d0,%d2
                   21321:        rts
                   21322: sdregb3:
                   21323:        mov.b           %d0,%d3
                   21324:        rts
                   21325: sdregb4:
                   21326:        mov.b           %d0,%d4
                   21327:        rts
                   21328: sdregb5:
                   21329:        mov.b           %d0,%d5
                   21330:        rts
                   21331: sdregb6:
                   21332:        mov.b           %d0,%d6
                   21333:        rts
                   21334: sdregb7:
                   21335:        mov.b           %d0,%d7
                   21336:        rts
                   21337:
                   21338: #########################################################################
                   21339: # XDEF ****************************************************************        #
                   21340: #      inc_areg(): increment an address register by the value in d0    #
                   21341: #                                                                      #
                   21342: # XREF ****************************************************************        #
                   21343: #      None                                                            #
                   21344: #                                                                      #
                   21345: # INPUT ***************************************************************        #
                   21346: #      d0 = amount to increment by                                     #
                   21347: #      d1 = index of address register to increment                     #
                   21348: #                                                                      #
                   21349: # OUTPUT **************************************************************        #
                   21350: #      (address register is updated)                                   #
                   21351: #                                                                      #
                   21352: # ALGORITHM ***********************************************************        #
                   21353: #      Typically used for an instruction w/ a post-increment <ea>,     #
                   21354: # this routine adds the increment value in d0 to the address register  #
                   21355: # specified by d1. A0/A1/A6/A7 reside on the stack. The rest reside    #
                   21356: # in their original places.                                            #
                   21357: #      For a7, if the increment amount is one, then we have to         #
                   21358: # increment by two. For any a7 update, set the mia7_flag so that if    #
                   21359: # an access error exception occurs later in emulation, this address    #
                   21360: # register update can be undone.                                       #
                   21361: #                                                                      #
                   21362: #########################################################################
                   21363:
                   21364:        global          inc_areg
                   21365: inc_areg:
                   21366:        mov.w           (tbl_iareg.b,%pc,%d1.w*2),%d1
                   21367:        jmp             (tbl_iareg.b,%pc,%d1.w*1)
                   21368:
                   21369: tbl_iareg:
                   21370:        short           iareg0 - tbl_iareg
                   21371:        short           iareg1 - tbl_iareg
                   21372:        short           iareg2 - tbl_iareg
                   21373:        short           iareg3 - tbl_iareg
                   21374:        short           iareg4 - tbl_iareg
                   21375:        short           iareg5 - tbl_iareg
                   21376:        short           iareg6 - tbl_iareg
                   21377:        short           iareg7 - tbl_iareg
                   21378:
                   21379: iareg0:        add.l           %d0,EXC_DREGS+0x8(%a6)
                   21380:        rts
                   21381: iareg1:        add.l           %d0,EXC_DREGS+0xc(%a6)
                   21382:        rts
                   21383: iareg2:        add.l           %d0,%a2
                   21384:        rts
                   21385: iareg3:        add.l           %d0,%a3
                   21386:        rts
                   21387: iareg4:        add.l           %d0,%a4
                   21388:        rts
                   21389: iareg5:        add.l           %d0,%a5
                   21390:        rts
                   21391: iareg6:        add.l           %d0,(%a6)
                   21392:        rts
                   21393: iareg7:        mov.b           &mia7_flg,SPCOND_FLG(%a6)
                   21394:        cmpi.b          %d0,&0x1
                   21395:        beq.b           iareg7b
                   21396:        add.l           %d0,EXC_A7(%a6)
                   21397:        rts
                   21398: iareg7b:
                   21399:        addq.l          &0x2,EXC_A7(%a6)
                   21400:        rts
                   21401:
                   21402: #########################################################################
                   21403: # XDEF ****************************************************************        #
                   21404: #      dec_areg(): decrement an address register by the value in d0    #
                   21405: #                                                                      #
                   21406: # XREF ****************************************************************        #
                   21407: #      None                                                            #
                   21408: #                                                                      #
                   21409: # INPUT ***************************************************************        #
                   21410: #      d0 = amount to decrement by                                     #
                   21411: #      d1 = index of address register to decrement                     #
                   21412: #                                                                      #
                   21413: # OUTPUT **************************************************************        #
                   21414: #      (address register is updated)                                   #
                   21415: #                                                                      #
                   21416: # ALGORITHM ***********************************************************        #
                   21417: #      Typically used for an instruction w/ a pre-decrement <ea>,      #
                   21418: # this routine adds the decrement value in d0 to the address register  #
                   21419: # specified by d1. A0/A1/A6/A7 reside on the stack. The rest reside    #
                   21420: # in their original places.                                            #
                   21421: #      For a7, if the decrement amount is one, then we have to         #
                   21422: # decrement by two. For any a7 update, set the mda7_flag so that if    #
                   21423: # an access error exception occurs later in emulation, this address    #
                   21424: # register update can be undone.                                       #
                   21425: #                                                                      #
                   21426: #########################################################################
                   21427:
                   21428:        global          dec_areg
                   21429: dec_areg:
                   21430:        mov.w           (tbl_dareg.b,%pc,%d1.w*2),%d1
                   21431:        jmp             (tbl_dareg.b,%pc,%d1.w*1)
                   21432:
                   21433: tbl_dareg:
                   21434:        short           dareg0 - tbl_dareg
                   21435:        short           dareg1 - tbl_dareg
                   21436:        short           dareg2 - tbl_dareg
                   21437:        short           dareg3 - tbl_dareg
                   21438:        short           dareg4 - tbl_dareg
                   21439:        short           dareg5 - tbl_dareg
                   21440:        short           dareg6 - tbl_dareg
                   21441:        short           dareg7 - tbl_dareg
                   21442:
                   21443: dareg0:        sub.l           %d0,EXC_DREGS+0x8(%a6)
                   21444:        rts
                   21445: dareg1:        sub.l           %d0,EXC_DREGS+0xc(%a6)
                   21446:        rts
                   21447: dareg2:        sub.l           %d0,%a2
                   21448:        rts
                   21449: dareg3:        sub.l           %d0,%a3
                   21450:        rts
                   21451: dareg4:        sub.l           %d0,%a4
                   21452:        rts
                   21453: dareg5:        sub.l           %d0,%a5
                   21454:        rts
                   21455: dareg6:        sub.l           %d0,(%a6)
                   21456:        rts
                   21457: dareg7:        mov.b           &mda7_flg,SPCOND_FLG(%a6)
                   21458:        cmpi.b          %d0,&0x1
                   21459:        beq.b           dareg7b
                   21460:        sub.l           %d0,EXC_A7(%a6)
                   21461:        rts
                   21462: dareg7b:
                   21463:        subq.l          &0x2,EXC_A7(%a6)
                   21464:        rts
                   21465:
                   21466: ##############################################################################
                   21467:
                   21468: #########################################################################
                   21469: # XDEF ****************************************************************        #
                   21470: #      load_fpn1(): load FP register value into FP_SRC(a6).            #
                   21471: #                                                                      #
                   21472: # XREF ****************************************************************        #
                   21473: #      None                                                            #
                   21474: #                                                                      #
                   21475: # INPUT ***************************************************************        #
                   21476: #      d0 = index of FP register to load                               #
                   21477: #                                                                      #
                   21478: # OUTPUT **************************************************************        #
                   21479: #      FP_SRC(a6) = value loaded from FP register file                 #
                   21480: #                                                                      #
                   21481: # ALGORITHM ***********************************************************        #
                   21482: #      Using the index in d0, load FP_SRC(a6) with a number from the   #
                   21483: # FP register file.                                                    #
                   21484: #                                                                      #
                   21485: #########################################################################
                   21486:
                   21487:        global          load_fpn1
                   21488: load_fpn1:
                   21489:        mov.w           (tbl_load_fpn1.b,%pc,%d0.w*2), %d0
                   21490:        jmp             (tbl_load_fpn1.b,%pc,%d0.w*1)
                   21491:
                   21492: tbl_load_fpn1:
                   21493:        short           load_fpn1_0 - tbl_load_fpn1
                   21494:        short           load_fpn1_1 - tbl_load_fpn1
                   21495:        short           load_fpn1_2 - tbl_load_fpn1
                   21496:        short           load_fpn1_3 - tbl_load_fpn1
                   21497:        short           load_fpn1_4 - tbl_load_fpn1
                   21498:        short           load_fpn1_5 - tbl_load_fpn1
                   21499:        short           load_fpn1_6 - tbl_load_fpn1
                   21500:        short           load_fpn1_7 - tbl_load_fpn1
                   21501:
                   21502: load_fpn1_0:
                   21503:        mov.l           0+EXC_FP0(%a6), 0+FP_SRC(%a6)
                   21504:        mov.l           4+EXC_FP0(%a6), 4+FP_SRC(%a6)
                   21505:        mov.l           8+EXC_FP0(%a6), 8+FP_SRC(%a6)
                   21506:        lea             FP_SRC(%a6), %a0
                   21507:        rts
                   21508: load_fpn1_1:
                   21509:        mov.l           0+EXC_FP1(%a6), 0+FP_SRC(%a6)
                   21510:        mov.l           4+EXC_FP1(%a6), 4+FP_SRC(%a6)
                   21511:        mov.l           8+EXC_FP1(%a6), 8+FP_SRC(%a6)
                   21512:        lea             FP_SRC(%a6), %a0
                   21513:        rts
                   21514: load_fpn1_2:
                   21515:        fmovm.x         &0x20, FP_SRC(%a6)
                   21516:        lea             FP_SRC(%a6), %a0
                   21517:        rts
                   21518: load_fpn1_3:
                   21519:        fmovm.x         &0x10, FP_SRC(%a6)
                   21520:        lea             FP_SRC(%a6), %a0
                   21521:        rts
                   21522: load_fpn1_4:
                   21523:        fmovm.x         &0x08, FP_SRC(%a6)
                   21524:        lea             FP_SRC(%a6), %a0
                   21525:        rts
                   21526: load_fpn1_5:
                   21527:        fmovm.x         &0x04, FP_SRC(%a6)
                   21528:        lea             FP_SRC(%a6), %a0
                   21529:        rts
                   21530: load_fpn1_6:
                   21531:        fmovm.x         &0x02, FP_SRC(%a6)
                   21532:        lea             FP_SRC(%a6), %a0
                   21533:        rts
                   21534: load_fpn1_7:
                   21535:        fmovm.x         &0x01, FP_SRC(%a6)
                   21536:        lea             FP_SRC(%a6), %a0
                   21537:        rts
                   21538:
                   21539: #############################################################################
                   21540:
                   21541: #########################################################################
                   21542: # XDEF ****************************************************************        #
                   21543: #      load_fpn2(): load FP register value into FP_DST(a6).            #
                   21544: #                                                                      #
                   21545: # XREF ****************************************************************        #
                   21546: #      None                                                            #
                   21547: #                                                                      #
                   21548: # INPUT ***************************************************************        #
                   21549: #      d0 = index of FP register to load                               #
                   21550: #                                                                      #
                   21551: # OUTPUT **************************************************************        #
                   21552: #      FP_DST(a6) = value loaded from FP register file                 #
                   21553: #                                                                      #
                   21554: # ALGORITHM ***********************************************************        #
                   21555: #      Using the index in d0, load FP_DST(a6) with a number from the   #
                   21556: # FP register file.                                                    #
                   21557: #                                                                      #
                   21558: #########################################################################
                   21559:
                   21560:        global          load_fpn2
                   21561: load_fpn2:
                   21562:        mov.w           (tbl_load_fpn2.b,%pc,%d0.w*2), %d0
                   21563:        jmp             (tbl_load_fpn2.b,%pc,%d0.w*1)
                   21564:
                   21565: tbl_load_fpn2:
                   21566:        short           load_fpn2_0 - tbl_load_fpn2
                   21567:        short           load_fpn2_1 - tbl_load_fpn2
                   21568:        short           load_fpn2_2 - tbl_load_fpn2
                   21569:        short           load_fpn2_3 - tbl_load_fpn2
                   21570:        short           load_fpn2_4 - tbl_load_fpn2
                   21571:        short           load_fpn2_5 - tbl_load_fpn2
                   21572:        short           load_fpn2_6 - tbl_load_fpn2
                   21573:        short           load_fpn2_7 - tbl_load_fpn2
                   21574:
                   21575: load_fpn2_0:
                   21576:        mov.l           0+EXC_FP0(%a6), 0+FP_DST(%a6)
                   21577:        mov.l           4+EXC_FP0(%a6), 4+FP_DST(%a6)
                   21578:        mov.l           8+EXC_FP0(%a6), 8+FP_DST(%a6)
                   21579:        lea             FP_DST(%a6), %a0
                   21580:        rts
                   21581: load_fpn2_1:
                   21582:        mov.l           0+EXC_FP1(%a6), 0+FP_DST(%a6)
                   21583:        mov.l           4+EXC_FP1(%a6), 4+FP_DST(%a6)
                   21584:        mov.l           8+EXC_FP1(%a6), 8+FP_DST(%a6)
                   21585:        lea             FP_DST(%a6), %a0
                   21586:        rts
                   21587: load_fpn2_2:
                   21588:        fmovm.x         &0x20, FP_DST(%a6)
                   21589:        lea             FP_DST(%a6), %a0
                   21590:        rts
                   21591: load_fpn2_3:
                   21592:        fmovm.x         &0x10, FP_DST(%a6)
                   21593:        lea             FP_DST(%a6), %a0
                   21594:        rts
                   21595: load_fpn2_4:
                   21596:        fmovm.x         &0x08, FP_DST(%a6)
                   21597:        lea             FP_DST(%a6), %a0
                   21598:        rts
                   21599: load_fpn2_5:
                   21600:        fmovm.x         &0x04, FP_DST(%a6)
                   21601:        lea             FP_DST(%a6), %a0
                   21602:        rts
                   21603: load_fpn2_6:
                   21604:        fmovm.x         &0x02, FP_DST(%a6)
                   21605:        lea             FP_DST(%a6), %a0
                   21606:        rts
                   21607: load_fpn2_7:
                   21608:        fmovm.x         &0x01, FP_DST(%a6)
                   21609:        lea             FP_DST(%a6), %a0
                   21610:        rts
                   21611:
                   21612: #############################################################################
                   21613:
                   21614: #########################################################################
                   21615: # XDEF ****************************************************************        #
                   21616: #      store_fpreg(): store an fp value to the fpreg designated d0.    #
                   21617: #                                                                      #
                   21618: # XREF ****************************************************************        #
                   21619: #      None                                                            #
                   21620: #                                                                      #
                   21621: # INPUT ***************************************************************        #
                   21622: #      fp0 = extended precision value to store                         #
                   21623: #      d0  = index of floating-point register                          #
                   21624: #                                                                      #
                   21625: # OUTPUT **************************************************************        #
                   21626: #      None                                                            #
                   21627: #                                                                      #
                   21628: # ALGORITHM ***********************************************************        #
                   21629: #      Store the value in fp0 to the FP register designated by the     #
                   21630: # value in d0. The FP number can be DENORM or SNAN so we have to be    #
                   21631: # careful that we don't take an exception here.                                #
                   21632: #                                                                      #
                   21633: #########################################################################
                   21634:
                   21635:        global          store_fpreg
                   21636: store_fpreg:
                   21637:        mov.w           (tbl_store_fpreg.b,%pc,%d0.w*2), %d0
                   21638:        jmp             (tbl_store_fpreg.b,%pc,%d0.w*1)
                   21639:
                   21640: tbl_store_fpreg:
                   21641:        short           store_fpreg_0 - tbl_store_fpreg
                   21642:        short           store_fpreg_1 - tbl_store_fpreg
                   21643:        short           store_fpreg_2 - tbl_store_fpreg
                   21644:        short           store_fpreg_3 - tbl_store_fpreg
                   21645:        short           store_fpreg_4 - tbl_store_fpreg
                   21646:        short           store_fpreg_5 - tbl_store_fpreg
                   21647:        short           store_fpreg_6 - tbl_store_fpreg
                   21648:        short           store_fpreg_7 - tbl_store_fpreg
                   21649:
                   21650: store_fpreg_0:
                   21651:        fmovm.x         &0x80, EXC_FP0(%a6)
                   21652:        rts
                   21653: store_fpreg_1:
                   21654:        fmovm.x         &0x80, EXC_FP1(%a6)
                   21655:        rts
                   21656: store_fpreg_2:
                   21657:        fmovm.x         &0x01, -(%sp)
                   21658:        fmovm.x         (%sp)+, &0x20
                   21659:        rts
                   21660: store_fpreg_3:
                   21661:        fmovm.x         &0x01, -(%sp)
                   21662:        fmovm.x         (%sp)+, &0x10
                   21663:        rts
                   21664: store_fpreg_4:
                   21665:        fmovm.x         &0x01, -(%sp)
                   21666:        fmovm.x         (%sp)+, &0x08
                   21667:        rts
                   21668: store_fpreg_5:
                   21669:        fmovm.x         &0x01, -(%sp)
                   21670:        fmovm.x         (%sp)+, &0x04
                   21671:        rts
                   21672: store_fpreg_6:
                   21673:        fmovm.x         &0x01, -(%sp)
                   21674:        fmovm.x         (%sp)+, &0x02
                   21675:        rts
                   21676: store_fpreg_7:
                   21677:        fmovm.x         &0x01, -(%sp)
                   21678:        fmovm.x         (%sp)+, &0x01
                   21679:        rts
                   21680:
                   21681: #########################################################################
                   21682: # XDEF ****************************************************************        #
                   21683: #      _denorm(): denormalize an intermediate result                   #
                   21684: #                                                                      #
                   21685: # XREF ****************************************************************        #
                   21686: #      None                                                            #
                   21687: #                                                                      #
                   21688: # INPUT *************************************************************** #
                   21689: #      a0 = points to the operand to be denormalized                   #
                   21690: #              (in the internal extended format)                       #
                   21691: #                                                                      #
                   21692: #      d0 = rounding precision                                         #
                   21693: #                                                                      #
                   21694: # OUTPUT **************************************************************        #
                   21695: #      a0 = pointer to the denormalized result                         #
                   21696: #              (in the internal extended format)                       #
                   21697: #                                                                      #
                   21698: #      d0 = guard,round,sticky                                         #
                   21699: #                                                                      #
                   21700: # ALGORITHM ***********************************************************        #
                   21701: #      According to the exponent underflow threshold for the given     #
                   21702: # precision, shift the mantissa bits to the right in order raise the   #
                   21703: # exponent of the operand to the threshold value. While shifting the   #
                   21704: # mantissa bits right, maintain the value of the guard, round, and     #
                   21705: # sticky bits.                                                         #
                   21706: # other notes:                                                         #
                   21707: #      (1) _denorm() is called by the underflow routines               #
                   21708: #      (2) _denorm() does NOT affect the status register               #
                   21709: #                                                                      #
                   21710: #########################################################################
                   21711:
                   21712: #
                   21713: # table of exponent threshold values for each precision
                   21714: #
                   21715: tbl_thresh:
                   21716:        short           0x0
                   21717:        short           sgl_thresh
                   21718:        short           dbl_thresh
                   21719:
                   21720:        global          _denorm
                   21721: _denorm:
                   21722: #
                   21723: # Load the exponent threshold for the precision selected and check
                   21724: # to see if (threshold - exponent) is > 65 in which case we can
                   21725: # simply calculate the sticky bit and zero the mantissa. otherwise
                   21726: # we have to call the denormalization routine.
                   21727: #
                   21728:        lsr.b           &0x2, %d0               # shift prec to lo bits
                   21729:        mov.w           (tbl_thresh.b,%pc,%d0.w*2), %d1 # load prec threshold
                   21730:        mov.w           %d1, %d0                # copy d1 into d0
                   21731:        sub.w           FTEMP_EX(%a0), %d0      # diff = threshold - exp
                   21732:        cmpi.w          %d0, &66                # is diff > 65? (mant + g,r bits)
                   21733:        bpl.b           denorm_set_stky         # yes; just calc sticky
                   21734:
                   21735:        clr.l           %d0                     # clear g,r,s
                   21736:        btst            &inex2_bit, FPSR_EXCEPT(%a6) # yes; was INEX2 set?
                   21737:        beq.b           denorm_call             # no; don't change anything
                   21738:        bset            &29, %d0                # yes; set sticky bit
                   21739:
                   21740: denorm_call:
                   21741:        bsr.l           dnrm_lp                 # denormalize the number
                   21742:        rts
                   21743:
                   21744: #
                   21745: # all bit would have been shifted off during the denorm so simply
                   21746: # calculate if the sticky should be set and clear the entire mantissa.
                   21747: #
                   21748: denorm_set_stky:
                   21749:        mov.l           &0x20000000, %d0        # set sticky bit in return value
                   21750:        mov.w           %d1, FTEMP_EX(%a0)      # load exp with threshold
                   21751:        clr.l           FTEMP_HI(%a0)           # set d1 = 0 (ms mantissa)
                   21752:        clr.l           FTEMP_LO(%a0)           # set d2 = 0 (ms mantissa)
                   21753:        rts
                   21754:
                   21755: #                                                                      #
                   21756: # dnrm_lp(): normalize exponent/mantissa to specified threshold                #
                   21757: #                                                                      #
                   21758: # INPUT:                                                               #
                   21759: #      %a0        : points to the operand to be denormalized           #
                   21760: #      %d0{31:29} : initial guard,round,sticky                         #
                   21761: #      %d1{15:0}  : denormalization threshold                          #
                   21762: # OUTPUT:                                                              #
                   21763: #      %a0        : points to the denormalized operand                 #
                   21764: #      %d0{31:29} : final guard,round,sticky                           #
                   21765: #                                                                      #
                   21766:
                   21767: # *** Local Equates *** #
                   21768: set    GRS,            L_SCR2                  # g,r,s temp storage
                   21769: set    FTEMP_LO2,      L_SCR1                  # FTEMP_LO copy
                   21770:
                   21771:        global          dnrm_lp
                   21772: dnrm_lp:
                   21773:
                   21774: #
                   21775: # make a copy of FTEMP_LO and place the g,r,s bits directly after it
                   21776: # in memory so as to make the bitfield extraction for denormalization easier.
                   21777: #
                   21778:        mov.l           FTEMP_LO(%a0), FTEMP_LO2(%a6) # make FTEMP_LO copy
                   21779:        mov.l           %d0, GRS(%a6)           # place g,r,s after it
                   21780:
                   21781: #
                   21782: # check to see how much less than the underflow threshold the operand
                   21783: # exponent is.
                   21784: #
                   21785:        mov.l           %d1, %d0                # copy the denorm threshold
                   21786:        sub.w           FTEMP_EX(%a0), %d1      # d1 = threshold - uns exponent
                   21787:        ble.b           dnrm_no_lp              # d1 <= 0
                   21788:        cmpi.w          %d1, &0x20              # is ( 0 <= d1 < 32) ?
                   21789:        blt.b           case_1                  # yes
                   21790:        cmpi.w          %d1, &0x40              # is (32 <= d1 < 64) ?
                   21791:        blt.b           case_2                  # yes
                   21792:        bra.w           case_3                  # (d1 >= 64)
                   21793:
                   21794: #
                   21795: # No normalization necessary
                   21796: #
                   21797: dnrm_no_lp:
                   21798:        mov.l           GRS(%a6), %d0           # restore original g,r,s
                   21799:        rts
                   21800:
                   21801: #
                   21802: # case (0<d1<32)
                   21803: #
                   21804: # %d0 = denorm threshold
                   21805: # %d1 = "n" = amt to shift
                   21806: #
                   21807: #      ---------------------------------------------------------
                   21808: #      |     FTEMP_HI    |     FTEMP_LO     |grs000.........000|
                   21809: #      ---------------------------------------------------------
                   21810: #      <-(32 - n)-><-(n)-><-(32 - n)-><-(n)-><-(32 - n)-><-(n)->
                   21811: #      \          \                  \                  \
                   21812: #       \          \                  \                  \
                   21813: #        \          \                  \                  \
                   21814: #         \          \                  \                  \
                   21815: #          \          \                  \                  \
                   21816: #           \          \                  \                  \
                   21817: #            \          \                  \                  \
                   21818: #             \          \                  \                  \
                   21819: #      <-(n)-><-(32 - n)-><------(32)-------><------(32)------->
                   21820: #      ---------------------------------------------------------
                   21821: #      |0.....0| NEW_HI  |  NEW_FTEMP_LO     |grs              |
                   21822: #      ---------------------------------------------------------
                   21823: #
                   21824: case_1:
                   21825:        mov.l           %d2, -(%sp)             # create temp storage
                   21826:
                   21827:        mov.w           %d0, FTEMP_EX(%a0)      # exponent = denorm threshold
                   21828:        mov.l           &32, %d0
                   21829:        sub.w           %d1, %d0                # %d0 = 32 - %d1
                   21830:
                   21831:        cmpi.w          %d1, &29                # is shft amt >= 29
                   21832:        blt.b           case1_extract           # no; no fix needed
                   21833:        mov.b           GRS(%a6), %d2
                   21834:        or.b            %d2, 3+FTEMP_LO2(%a6)
                   21835:
                   21836: case1_extract:
                   21837:        bfextu          FTEMP_HI(%a0){&0:%d0}, %d2 # %d2 = new FTEMP_HI
                   21838:        bfextu          FTEMP_HI(%a0){%d0:&32}, %d1 # %d1 = new FTEMP_LO
                   21839:        bfextu          FTEMP_LO2(%a6){%d0:&32}, %d0 # %d0 = new G,R,S
                   21840:
                   21841:        mov.l           %d2, FTEMP_HI(%a0)      # store new FTEMP_HI
                   21842:        mov.l           %d1, FTEMP_LO(%a0)      # store new FTEMP_LO
                   21843:
                   21844:        bftst           %d0{&2:&30}             # were bits shifted off?
                   21845:        beq.b           case1_sticky_clear      # no; go finish
                   21846:        bset            &rnd_stky_bit, %d0      # yes; set sticky bit
                   21847:
                   21848: case1_sticky_clear:
                   21849:        and.l           &0xe0000000, %d0        # clear all but G,R,S
                   21850:        mov.l           (%sp)+, %d2             # restore temp register
                   21851:        rts
                   21852:
                   21853: #
                   21854: # case (32<=d1<64)
                   21855: #
                   21856: # %d0 = denorm threshold
                   21857: # %d1 = "n" = amt to shift
                   21858: #
                   21859: #      ---------------------------------------------------------
                   21860: #      |     FTEMP_HI    |     FTEMP_LO     |grs000.........000|
                   21861: #      ---------------------------------------------------------
                   21862: #      <-(32 - n)-><-(n)-><-(32 - n)-><-(n)-><-(32 - n)-><-(n)->
                   21863: #      \          \                  \
                   21864: #       \          \                  \
                   21865: #        \          \                  -------------------
                   21866: #         \          --------------------                 \
                   21867: #          -------------------           \                 \
                   21868: #                             \           \                 \
                   21869: #                              \           \                 \
                   21870: #                               \           \                 \
                   21871: #      <-------(32)------><-(n)-><-(32 - n)-><------(32)------->
                   21872: #      ---------------------------------------------------------
                   21873: #      |0...............0|0....0| NEW_LO     |grs              |
                   21874: #      ---------------------------------------------------------
                   21875: #
                   21876: case_2:
                   21877:        mov.l           %d2, -(%sp)             # create temp storage
                   21878:
                   21879:        mov.w           %d0, FTEMP_EX(%a0)      # exponent = denorm threshold
                   21880:        subi.w          &0x20, %d1              # %d1 now between 0 and 32
                   21881:        mov.l           &0x20, %d0
                   21882:        sub.w           %d1, %d0                # %d0 = 32 - %d1
                   21883:
                   21884: # subtle step here; or in the g,r,s at the bottom of FTEMP_LO to minimize
                   21885: # the number of bits to check for the sticky detect.
                   21886: # it only plays a role in shift amounts of 61-63.
                   21887:        mov.b           GRS(%a6), %d2
                   21888:        or.b            %d2, 3+FTEMP_LO2(%a6)
                   21889:
                   21890:        bfextu          FTEMP_HI(%a0){&0:%d0}, %d2 # %d2 = new FTEMP_LO
                   21891:        bfextu          FTEMP_HI(%a0){%d0:&32}, %d1 # %d1 = new G,R,S
                   21892:
                   21893:        bftst           %d1{&2:&30}             # were any bits shifted off?
                   21894:        bne.b           case2_set_sticky        # yes; set sticky bit
                   21895:        bftst           FTEMP_LO2(%a6){%d0:&31} # were any bits shifted off?
                   21896:        bne.b           case2_set_sticky        # yes; set sticky bit
                   21897:
                   21898:        mov.l           %d1, %d0                # move new G,R,S to %d0
                   21899:        bra.b           case2_end
                   21900:
                   21901: case2_set_sticky:
                   21902:        mov.l           %d1, %d0                # move new G,R,S to %d0
                   21903:        bset            &rnd_stky_bit, %d0      # set sticky bit
                   21904:
                   21905: case2_end:
                   21906:        clr.l           FTEMP_HI(%a0)           # store FTEMP_HI = 0
                   21907:        mov.l           %d2, FTEMP_LO(%a0)      # store FTEMP_LO
                   21908:        and.l           &0xe0000000, %d0        # clear all but G,R,S
                   21909:
                   21910:        mov.l           (%sp)+,%d2              # restore temp register
                   21911:        rts
                   21912:
                   21913: #
                   21914: # case (d1>=64)
                   21915: #
                   21916: # %d0 = denorm threshold
                   21917: # %d1 = amt to shift
                   21918: #
                   21919: case_3:
                   21920:        mov.w           %d0, FTEMP_EX(%a0)      # insert denorm threshold
                   21921:
                   21922:        cmpi.w          %d1, &65                # is shift amt > 65?
                   21923:        blt.b           case3_64                # no; it's == 64
                   21924:        beq.b           case3_65                # no; it's == 65
                   21925:
                   21926: #
                   21927: # case (d1>65)
                   21928: #
                   21929: # Shift value is > 65 and out of range. All bits are shifted off.
                   21930: # Return a zero mantissa with the sticky bit set
                   21931: #
                   21932:        clr.l           FTEMP_HI(%a0)           # clear hi(mantissa)
                   21933:        clr.l           FTEMP_LO(%a0)           # clear lo(mantissa)
                   21934:        mov.l           &0x20000000, %d0        # set sticky bit
                   21935:        rts
                   21936:
                   21937: #
                   21938: # case (d1 == 64)
                   21939: #
                   21940: #      ---------------------------------------------------------
                   21941: #      |     FTEMP_HI    |     FTEMP_LO     |grs000.........000|
                   21942: #      ---------------------------------------------------------
                   21943: #      <-------(32)------>
                   21944: #      \                  \
                   21945: #       \                  \
                   21946: #        \                  \
                   21947: #         \                  ------------------------------
                   21948: #          -------------------------------                 \
                   21949: #                                         \                 \
                   21950: #                                          \                 \
                   21951: #                                           \                 \
                   21952: #                                            <-------(32)------>
                   21953: #      ---------------------------------------------------------
                   21954: #      |0...............0|0................0|grs               |
                   21955: #      ---------------------------------------------------------
                   21956: #
                   21957: case3_64:
                   21958:        mov.l           FTEMP_HI(%a0), %d0      # fetch hi(mantissa)
                   21959:        mov.l           %d0, %d1                # make a copy
                   21960:        and.l           &0xc0000000, %d0        # extract G,R
                   21961:        and.l           &0x3fffffff, %d1        # extract other bits
                   21962:
                   21963:        bra.b           case3_complete
                   21964:
                   21965: #
                   21966: # case (d1 == 65)
                   21967: #
                   21968: #      ---------------------------------------------------------
                   21969: #      |     FTEMP_HI    |     FTEMP_LO     |grs000.........000|
                   21970: #      ---------------------------------------------------------
                   21971: #      <-------(32)------>
                   21972: #      \                  \
                   21973: #       \                  \
                   21974: #        \                  \
                   21975: #         \                  ------------------------------
                   21976: #          --------------------------------                \
                   21977: #                                          \                \
                   21978: #                                           \                \
                   21979: #                                            \                \
                   21980: #                                             <-------(31)----->
                   21981: #      ---------------------------------------------------------
                   21982: #      |0...............0|0................0|0rs               |
                   21983: #      ---------------------------------------------------------
                   21984: #
                   21985: case3_65:
                   21986:        mov.l           FTEMP_HI(%a0), %d0      # fetch hi(mantissa)
                   21987:        and.l           &0x80000000, %d0        # extract R bit
                   21988:        lsr.l           &0x1, %d0               # shift high bit into R bit
                   21989:        and.l           &0x7fffffff, %d1        # extract other bits
                   21990:
                   21991: case3_complete:
                   21992: # last operation done was an "and" of the bits shifted off so the condition
                   21993: # codes are already set so branch accordingly.
                   21994:        bne.b           case3_set_sticky        # yes; go set new sticky
                   21995:        tst.l           FTEMP_LO(%a0)           # were any bits shifted off?
                   21996:        bne.b           case3_set_sticky        # yes; go set new sticky
                   21997:        tst.b           GRS(%a6)                # were any bits shifted off?
                   21998:        bne.b           case3_set_sticky        # yes; go set new sticky
                   21999:
                   22000: #
                   22001: # no bits were shifted off so don't set the sticky bit.
                   22002: # the guard and
                   22003: # the entire mantissa is zero.
                   22004: #
                   22005:        clr.l           FTEMP_HI(%a0)           # clear hi(mantissa)
                   22006:        clr.l           FTEMP_LO(%a0)           # clear lo(mantissa)
                   22007:        rts
                   22008:
                   22009: #
                   22010: # some bits were shifted off so set the sticky bit.
                   22011: # the entire mantissa is zero.
                   22012: #
                   22013: case3_set_sticky:
                   22014:        bset            &rnd_stky_bit,%d0       # set new sticky bit
                   22015:        clr.l           FTEMP_HI(%a0)           # clear hi(mantissa)
                   22016:        clr.l           FTEMP_LO(%a0)           # clear lo(mantissa)
                   22017:        rts
                   22018:
                   22019: #########################################################################
                   22020: # XDEF ****************************************************************        #
                   22021: #      _round(): round result according to precision/mode              #
                   22022: #                                                                      #
                   22023: # XREF ****************************************************************        #
                   22024: #      None                                                            #
                   22025: #                                                                      #
                   22026: # INPUT ***************************************************************        #
                   22027: #      a0        = ptr to input operand in internal extended format    #
                   22028: #      d1(hi)    = contains rounding precision:                        #
                   22029: #                      ext = $0000xxxx                                 #
                   22030: #                      sgl = $0004xxxx                                 #
                   22031: #                      dbl = $0008xxxx                                 #
                   22032: #      d1(lo)    = contains rounding mode:                             #
                   22033: #                      RN  = $xxxx0000                                 #
                   22034: #                      RZ  = $xxxx0001                                 #
                   22035: #                      RM  = $xxxx0002                                 #
                   22036: #                      RP  = $xxxx0003                                 #
                   22037: #      d0{31:29} = contains the g,r,s bits (extended)                  #
                   22038: #                                                                      #
                   22039: # OUTPUT **************************************************************        #
                   22040: #      a0 = pointer to rounded result                                  #
                   22041: #                                                                      #
                   22042: # ALGORITHM ***********************************************************        #
                   22043: #      On return the value pointed to by a0 is correctly rounded,      #
                   22044: #      a0 is preserved and the g-r-s bits in d0 are cleared.           #
                   22045: #      The result is not typed - the tag field is invalid.  The        #
                   22046: #      result is still in the internal extended format.                #
                   22047: #                                                                      #
                   22048: #      The INEX bit of USER_FPSR will be set if the rounded result was #
                   22049: #      inexact (i.e. if any of the g-r-s bits were set).               #
                   22050: #                                                                      #
                   22051: #########################################################################
                   22052:
                   22053:        global          _round
                   22054: _round:
                   22055: #
                   22056: # ext_grs() looks at the rounding precision and sets the appropriate
                   22057: # G,R,S bits.
                   22058: # If (G,R,S == 0) then result is exact and round is done, else set
                   22059: # the inex flag in status reg and continue.
                   22060: #
                   22061:        bsr.l           ext_grs                 # extract G,R,S
                   22062:
                   22063:        tst.l           %d0                     # are G,R,S zero?
                   22064:        beq.w           truncate                # yes; round is complete
                   22065:
                   22066:        or.w            &inx2a_mask, 2+USER_FPSR(%a6) # set inex2/ainex
                   22067:
                   22068: #
                   22069: # Use rounding mode as an index into a jump table for these modes.
                   22070: # All of the following assumes grs != 0.
                   22071: #
                   22072:        mov.w           (tbl_mode.b,%pc,%d1.w*2), %a1 # load jump offset
                   22073:        jmp             (tbl_mode.b,%pc,%a1)    # jmp to rnd mode handler
                   22074:
                   22075: tbl_mode:
                   22076:        short           rnd_near - tbl_mode
                   22077:        short           truncate - tbl_mode     # RZ always truncates
                   22078:        short           rnd_mnus - tbl_mode
                   22079:        short           rnd_plus - tbl_mode
                   22080:
                   22081: #################################################################
                   22082: #      ROUND PLUS INFINITY                                     #
                   22083: #                                                              #
                   22084: #      If sign of fp number = 0 (positive), then add 1 to l.   #
                   22085: #################################################################
                   22086: rnd_plus:
                   22087:        tst.b           FTEMP_SGN(%a0)          # check for sign
                   22088:        bmi.w           truncate                # if positive then truncate
                   22089:
                   22090:        mov.l           &0xffffffff, %d0        # force g,r,s to be all f's
                   22091:        swap            %d1                     # set up d1 for round prec.
                   22092:
                   22093:        cmpi.b          %d1, &s_mode            # is prec = sgl?
                   22094:        beq.w           add_sgl                 # yes
                   22095:        bgt.w           add_dbl                 # no; it's dbl
                   22096:        bra.w           add_ext                 # no; it's ext
                   22097:
                   22098: #################################################################
                   22099: #      ROUND MINUS INFINITY                                    #
                   22100: #                                                              #
                   22101: #      If sign of fp number = 1 (negative), then add 1 to l.   #
                   22102: #################################################################
                   22103: rnd_mnus:
                   22104:        tst.b           FTEMP_SGN(%a0)          # check for sign
                   22105:        bpl.w           truncate                # if negative then truncate
                   22106:
                   22107:        mov.l           &0xffffffff, %d0        # force g,r,s to be all f's
                   22108:        swap            %d1                     # set up d1 for round prec.
                   22109:
                   22110:        cmpi.b          %d1, &s_mode            # is prec = sgl?
                   22111:        beq.w           add_sgl                 # yes
                   22112:        bgt.w           add_dbl                 # no; it's dbl
                   22113:        bra.w           add_ext                 # no; it's ext
                   22114:
                   22115: #################################################################
                   22116: #      ROUND NEAREST                                           #
                   22117: #                                                              #
                   22118: #      If (g=1), then add 1 to l and if (r=s=0), then clear l  #
                   22119: #      Note that this will round to even in case of a tie.     #
                   22120: #################################################################
                   22121: rnd_near:
                   22122:        asl.l           &0x1, %d0               # shift g-bit to c-bit
                   22123:        bcc.w           truncate                # if (g=1) then
                   22124:
                   22125:        swap            %d1                     # set up d1 for round prec.
                   22126:
                   22127:        cmpi.b          %d1, &s_mode            # is prec = sgl?
                   22128:        beq.w           add_sgl                 # yes
                   22129:        bgt.w           add_dbl                 # no; it's dbl
                   22130:        bra.w           add_ext                 # no; it's ext
                   22131:
                   22132: # *** LOCAL EQUATES ***
                   22133: set    ad_1_sgl,       0x00000100      # constant to add 1 to l-bit in sgl prec
                   22134: set    ad_1_dbl,       0x00000800      # constant to add 1 to l-bit in dbl prec
                   22135:
                   22136: #########################
                   22137: #      ADD SINGLE      #
                   22138: #########################
                   22139: add_sgl:
                   22140:        add.l           &ad_1_sgl, FTEMP_HI(%a0)
                   22141:        bcc.b           scc_clr                 # no mantissa overflow
                   22142:        roxr.w          FTEMP_HI(%a0)           # shift v-bit back in
                   22143:        roxr.w          FTEMP_HI+2(%a0)         # shift v-bit back in
                   22144:        add.w           &0x1, FTEMP_EX(%a0)     # and incr exponent
                   22145: scc_clr:
                   22146:        tst.l           %d0                     # test for rs = 0
                   22147:        bne.b           sgl_done
                   22148:        and.w           &0xfe00, FTEMP_HI+2(%a0) # clear the l-bit
                   22149: sgl_done:
                   22150:        and.l           &0xffffff00, FTEMP_HI(%a0) # truncate bits beyond sgl limit
                   22151:        clr.l           FTEMP_LO(%a0)           # clear d2
                   22152:        rts
                   22153:
                   22154: #########################
                   22155: #      ADD EXTENDED    #
                   22156: #########################
                   22157: add_ext:
                   22158:        addq.l          &1,FTEMP_LO(%a0)        # add 1 to l-bit
                   22159:        bcc.b           xcc_clr                 # test for carry out
                   22160:        addq.l          &1,FTEMP_HI(%a0)        # propagate carry
                   22161:        bcc.b           xcc_clr
                   22162:        roxr.w          FTEMP_HI(%a0)           # mant is 0 so restore v-bit
                   22163:        roxr.w          FTEMP_HI+2(%a0)         # mant is 0 so restore v-bit
                   22164:        roxr.w          FTEMP_LO(%a0)
                   22165:        roxr.w          FTEMP_LO+2(%a0)
                   22166:        add.w           &0x1,FTEMP_EX(%a0)      # and inc exp
                   22167: xcc_clr:
                   22168:        tst.l           %d0                     # test rs = 0
                   22169:        bne.b           add_ext_done
                   22170:        and.b           &0xfe,FTEMP_LO+3(%a0)   # clear the l bit
                   22171: add_ext_done:
                   22172:        rts
                   22173:
                   22174: #########################
                   22175: #      ADD DOUBLE      #
                   22176: #########################
                   22177: add_dbl:
                   22178:        add.l           &ad_1_dbl, FTEMP_LO(%a0) # add 1 to lsb
                   22179:        bcc.b           dcc_clr                 # no carry
                   22180:        addq.l          &0x1, FTEMP_HI(%a0)     # propagate carry
                   22181:        bcc.b           dcc_clr                 # no carry
                   22182:
                   22183:        roxr.w          FTEMP_HI(%a0)           # mant is 0 so restore v-bit
                   22184:        roxr.w          FTEMP_HI+2(%a0)         # mant is 0 so restore v-bit
                   22185:        roxr.w          FTEMP_LO(%a0)
                   22186:        roxr.w          FTEMP_LO+2(%a0)
                   22187:        addq.w          &0x1, FTEMP_EX(%a0)     # incr exponent
                   22188: dcc_clr:
                   22189:        tst.l           %d0                     # test for rs = 0
                   22190:        bne.b           dbl_done
                   22191:        and.w           &0xf000, FTEMP_LO+2(%a0) # clear the l-bit
                   22192:
                   22193: dbl_done:
                   22194:        and.l           &0xfffff800,FTEMP_LO(%a0) # truncate bits beyond dbl limit
                   22195:        rts
                   22196:
                   22197: ###########################
                   22198: # Truncate all other bits #
                   22199: ###########################
                   22200: truncate:
                   22201:        swap            %d1                     # select rnd prec
                   22202:
                   22203:        cmpi.b          %d1, &s_mode            # is prec sgl?
                   22204:        beq.w           sgl_done                # yes
                   22205:        bgt.b           dbl_done                # no; it's dbl
                   22206:        rts                                     # no; it's ext
                   22207:
                   22208:
                   22209: #
                   22210: # ext_grs(): extract guard, round and sticky bits according to
                   22211: #           rounding precision.
                   22212: #
                   22213: # INPUT
                   22214: #      d0         = extended precision g,r,s (in d0{31:29})
                   22215: #      d1         = {PREC,ROUND}
                   22216: # OUTPUT
                   22217: #      d0{31:29}  = guard, round, sticky
                   22218: #
                   22219: # The ext_grs extract the guard/round/sticky bits according to the
                   22220: # selected rounding precision. It is called by the round subroutine
                   22221: # only.  All registers except d0 are kept intact. d0 becomes an
                   22222: # updated guard,round,sticky in d0{31:29}
                   22223: #
                   22224: # Notes: the ext_grs uses the round PREC, and therefore has to swap d1
                   22225: #       prior to usage, and needs to restore d1 to original. this
                   22226: #       routine is tightly tied to the round routine and not meant to
                   22227: #       uphold standard subroutine calling practices.
                   22228: #
                   22229:
                   22230: ext_grs:
                   22231:        swap            %d1                     # have d1.w point to round precision
                   22232:        tst.b           %d1                     # is rnd prec = extended?
                   22233:        bne.b           ext_grs_not_ext         # no; go handle sgl or dbl
                   22234:
                   22235: #
                   22236: # %d0 actually already hold g,r,s since _round() had it before calling
                   22237: # this function. so, as long as we don't disturb it, we are "returning" it.
                   22238: #
                   22239: ext_grs_ext:
                   22240:        swap            %d1                     # yes; return to correct positions
                   22241:        rts
                   22242:
                   22243: ext_grs_not_ext:
                   22244:        movm.l          &0x3000, -(%sp)         # make some temp registers {d2/d3}
                   22245:
                   22246:        cmpi.b          %d1, &s_mode            # is rnd prec = sgl?
                   22247:        bne.b           ext_grs_dbl             # no; go handle dbl
                   22248:
                   22249: #
                   22250: # sgl:
                   22251: #      96              64        40    32              0
                   22252: #      -----------------------------------------------------
                   22253: #      | EXP   |XXXXXXX|         |xx   |               |grs|
                   22254: #      -----------------------------------------------------
                   22255: #                      <--(24)--->nn\                     /
                   22256: #                                 ee ---------------------
                   22257: #                                 ww           |
                   22258: #                                              v
                   22259: #                                 gr      new sticky
                   22260: #
                   22261: ext_grs_sgl:
                   22262:        bfextu          FTEMP_HI(%a0){&24:&2}, %d3 # sgl prec. g-r are 2 bits right
                   22263:        mov.l           &30, %d2                # of the sgl prec. limits
                   22264:        lsl.l           %d2, %d3                # shift g-r bits to MSB of d3
                   22265:        mov.l           FTEMP_HI(%a0), %d2      # get word 2 for s-bit test
                   22266:        and.l           &0x0000003f, %d2        # s bit is the or of all other
                   22267:        bne.b           ext_grs_st_stky         # bits to the right of g-r
                   22268:        tst.l           FTEMP_LO(%a0)           # test lower mantissa
                   22269:        bne.b           ext_grs_st_stky         # if any are set, set sticky
                   22270:        tst.l           %d0                     # test original g,r,s
                   22271:        bne.b           ext_grs_st_stky         # if any are set, set sticky
                   22272:        bra.b           ext_grs_end_sd          # if words 3 and 4 are clr, exit
                   22273:
                   22274: #
                   22275: # dbl:
                   22276: #      96              64              32       11     0
                   22277: #      -----------------------------------------------------
                   22278: #      | EXP   |XXXXXXX|               |        |xx    |grs|
                   22279: #      -----------------------------------------------------
                   22280: #                                                nn\       /
                   22281: #                                                ee -------
                   22282: #                                                ww    |
                   22283: #                                                      v
                   22284: #                                                gr    new sticky
                   22285: #
                   22286: ext_grs_dbl:
                   22287:        bfextu          FTEMP_LO(%a0){&21:&2}, %d3 # dbl-prec. g-r are 2 bits right
                   22288:        mov.l           &30, %d2                # of the dbl prec. limits
                   22289:        lsl.l           %d2, %d3                # shift g-r bits to the MSB of d3
                   22290:        mov.l           FTEMP_LO(%a0), %d2      # get lower mantissa  for s-bit test
                   22291:        and.l           &0x000001ff, %d2        # s bit is the or-ing of all
                   22292:        bne.b           ext_grs_st_stky         # other bits to the right of g-r
                   22293:        tst.l           %d0                     # test word original g,r,s
                   22294:        bne.b           ext_grs_st_stky         # if any are set, set sticky
                   22295:        bra.b           ext_grs_end_sd          # if clear, exit
                   22296:
                   22297: ext_grs_st_stky:
                   22298:        bset            &rnd_stky_bit, %d3      # set sticky bit
                   22299: ext_grs_end_sd:
                   22300:        mov.l           %d3, %d0                # return grs to d0
                   22301:
                   22302:        movm.l          (%sp)+, &0xc            # restore scratch registers {d2/d3}
                   22303:
                   22304:        swap            %d1                     # restore d1 to original
                   22305:        rts
                   22306:
                   22307: #########################################################################
                   22308: # norm(): normalize the mantissa of an extended precision input. the   #
                   22309: #        input operand should not be normalized already.               #
                   22310: #                                                                      #
                   22311: # XDEF ****************************************************************        #
                   22312: #      norm()                                                          #
                   22313: #                                                                      #
                   22314: # XREF **************************************************************** #
                   22315: #      none                                                            #
                   22316: #                                                                      #
                   22317: # INPUT *************************************************************** #
                   22318: #      a0 = pointer fp extended precision operand to normalize         #
                   22319: #                                                                      #
                   22320: # OUTPUT ************************************************************** #
                   22321: #      d0 = number of bit positions the mantissa was shifted           #
                   22322: #      a0 = the input operand's mantissa is normalized; the exponent   #
                   22323: #           is unchanged.                                              #
                   22324: #                                                                      #
                   22325: #########################################################################
                   22326:        global          norm
                   22327: norm:
                   22328:        mov.l           %d2, -(%sp)             # create some temp regs
                   22329:        mov.l           %d3, -(%sp)
                   22330:
                   22331:        mov.l           FTEMP_HI(%a0), %d0      # load hi(mantissa)
                   22332:        mov.l           FTEMP_LO(%a0), %d1      # load lo(mantissa)
                   22333:
                   22334:        bfffo           %d0{&0:&32}, %d2        # how many places to shift?
                   22335:        beq.b           norm_lo                 # hi(man) is all zeroes!
                   22336:
                   22337: norm_hi:
                   22338:        lsl.l           %d2, %d0                # left shift hi(man)
                   22339:        bfextu          %d1{&0:%d2}, %d3        # extract lo bits
                   22340:
                   22341:        or.l            %d3, %d0                # create hi(man)
                   22342:        lsl.l           %d2, %d1                # create lo(man)
                   22343:
                   22344:        mov.l           %d0, FTEMP_HI(%a0)      # store new hi(man)
                   22345:        mov.l           %d1, FTEMP_LO(%a0)      # store new lo(man)
                   22346:
                   22347:        mov.l           %d2, %d0                # return shift amount
                   22348:
                   22349:        mov.l           (%sp)+, %d3             # restore temp regs
                   22350:        mov.l           (%sp)+, %d2
                   22351:
                   22352:        rts
                   22353:
                   22354: norm_lo:
                   22355:        bfffo           %d1{&0:&32}, %d2        # how many places to shift?
                   22356:        lsl.l           %d2, %d1                # shift lo(man)
                   22357:        add.l           &32, %d2                # add 32 to shft amount
                   22358:
                   22359:        mov.l           %d1, FTEMP_HI(%a0)      # store hi(man)
                   22360:        clr.l           FTEMP_LO(%a0)           # lo(man) is now zero
                   22361:
                   22362:        mov.l           %d2, %d0                # return shift amount
                   22363:
                   22364:        mov.l           (%sp)+, %d3             # restore temp regs
                   22365:        mov.l           (%sp)+, %d2
                   22366:
                   22367:        rts
                   22368:
                   22369: #########################################################################
                   22370: # unnorm_fix(): - changes an UNNORM to one of NORM, DENORM, or ZERO    #
                   22371: #              - returns corresponding optype tag                      #
                   22372: #                                                                      #
                   22373: # XDEF ****************************************************************        #
                   22374: #      unnorm_fix()                                                    #
                   22375: #                                                                      #
                   22376: # XREF **************************************************************** #
                   22377: #      norm() - normalize the mantissa                                 #
                   22378: #                                                                      #
                   22379: # INPUT *************************************************************** #
                   22380: #      a0 = pointer to unnormalized extended precision number          #
                   22381: #                                                                      #
                   22382: # OUTPUT ************************************************************** #
                   22383: #      d0 = optype tag - is corrected to one of NORM, DENORM, or ZERO  #
                   22384: #      a0 = input operand has been converted to a norm, denorm, or     #
                   22385: #           zero; both the exponent and mantissa are changed.          #
                   22386: #                                                                      #
                   22387: #########################################################################
                   22388:
                   22389:        global          unnorm_fix
                   22390: unnorm_fix:
                   22391:        bfffo           FTEMP_HI(%a0){&0:&32}, %d0 # how many shifts are needed?
                   22392:        bne.b           unnorm_shift            # hi(man) is not all zeroes
                   22393:
                   22394: #
                   22395: # hi(man) is all zeroes so see if any bits in lo(man) are set
                   22396: #
                   22397: unnorm_chk_lo:
                   22398:        bfffo           FTEMP_LO(%a0){&0:&32}, %d0 # is operand really a zero?
                   22399:        beq.w           unnorm_zero             # yes
                   22400:
                   22401:        add.w           &32, %d0                # no; fix shift distance
                   22402:
                   22403: #
                   22404: # d0 = # shifts needed for complete normalization
                   22405: #
                   22406: unnorm_shift:
                   22407:        clr.l           %d1                     # clear top word
                   22408:        mov.w           FTEMP_EX(%a0), %d1      # extract exponent
                   22409:        and.w           &0x7fff, %d1            # strip off sgn
                   22410:
                   22411:        cmp.w           %d0, %d1                # will denorm push exp < 0?
                   22412:        bgt.b           unnorm_nrm_zero         # yes; denorm only until exp = 0
                   22413:
                   22414: #
                   22415: # exponent would not go < 0. therefore, number stays normalized
                   22416: #
                   22417:        sub.w           %d0, %d1                # shift exponent value
                   22418:        mov.w           FTEMP_EX(%a0), %d0      # load old exponent
                   22419:        and.w           &0x8000, %d0            # save old sign
                   22420:        or.w            %d0, %d1                # {sgn,new exp}
                   22421:        mov.w           %d1, FTEMP_EX(%a0)      # insert new exponent
                   22422:
                   22423:        bsr.l           norm                    # normalize UNNORM
                   22424:
                   22425:        mov.b           &NORM, %d0              # return new optype tag
                   22426:        rts
                   22427:
                   22428: #
                   22429: # exponent would go < 0, so only denormalize until exp = 0
                   22430: #
                   22431: unnorm_nrm_zero:
                   22432:        cmp.b           %d1, &32                # is exp <= 32?
                   22433:        bgt.b           unnorm_nrm_zero_lrg     # no; go handle large exponent
                   22434:
                   22435:        bfextu          FTEMP_HI(%a0){%d1:&32}, %d0 # extract new hi(man)
                   22436:        mov.l           %d0, FTEMP_HI(%a0)      # save new hi(man)
                   22437:
                   22438:        mov.l           FTEMP_LO(%a0), %d0      # fetch old lo(man)
                   22439:        lsl.l           %d1, %d0                # extract new lo(man)
                   22440:        mov.l           %d0, FTEMP_LO(%a0)      # save new lo(man)
                   22441:
                   22442:        and.w           &0x8000, FTEMP_EX(%a0)  # set exp = 0
                   22443:
                   22444:        mov.b           &DENORM, %d0            # return new optype tag
                   22445:        rts
                   22446:
                   22447: #
                   22448: # only mantissa bits set are in lo(man)
                   22449: #
                   22450: unnorm_nrm_zero_lrg:
                   22451:        sub.w           &32, %d1                # adjust shft amt by 32
                   22452:
                   22453:        mov.l           FTEMP_LO(%a0), %d0      # fetch old lo(man)
                   22454:        lsl.l           %d1, %d0                # left shift lo(man)
                   22455:
                   22456:        mov.l           %d0, FTEMP_HI(%a0)      # store new hi(man)
                   22457:        clr.l           FTEMP_LO(%a0)           # lo(man) = 0
                   22458:
                   22459:        and.w           &0x8000, FTEMP_EX(%a0)  # set exp = 0
                   22460:
                   22461:        mov.b           &DENORM, %d0            # return new optype tag
                   22462:        rts
                   22463:
                   22464: #
                   22465: # whole mantissa is zero so this UNNORM is actually a zero
                   22466: #
                   22467: unnorm_zero:
                   22468:        and.w           &0x8000, FTEMP_EX(%a0)  # force exponent to zero
                   22469:
                   22470:        mov.b           &ZERO, %d0              # fix optype tag
                   22471:        rts
                   22472:
                   22473: #########################################################################
                   22474: # XDEF ****************************************************************        #
                   22475: #      set_tag_x(): return the optype of the input ext fp number       #
                   22476: #                                                                      #
                   22477: # XREF ****************************************************************        #
                   22478: #      None                                                            #
                   22479: #                                                                      #
                   22480: # INPUT ***************************************************************        #
                   22481: #      a0 = pointer to extended precision operand                      #
                   22482: #                                                                      #
                   22483: # OUTPUT **************************************************************        #
                   22484: #      d0 = value of type tag                                          #
                   22485: #              one of: NORM, INF, QNAN, SNAN, DENORM, UNNORM, ZERO     #
                   22486: #                                                                      #
                   22487: # ALGORITHM ***********************************************************        #
                   22488: #      Simply test the exponent, j-bit, and mantissa values to         #
                   22489: # determine the type of operand.                                       #
                   22490: #      If it's an unnormalized zero, alter the operand and force it    #
                   22491: # to be a normal zero.                                                 #
                   22492: #                                                                      #
                   22493: #########################################################################
                   22494:
                   22495:        global          set_tag_x
                   22496: set_tag_x:
                   22497:        mov.w           FTEMP_EX(%a0), %d0      # extract exponent
                   22498:        andi.w          &0x7fff, %d0            # strip off sign
                   22499:        cmpi.w          %d0, &0x7fff            # is (EXP == MAX)?
                   22500:        beq.b           inf_or_nan_x
                   22501: not_inf_or_nan_x:
                   22502:        btst            &0x7,FTEMP_HI(%a0)
                   22503:        beq.b           not_norm_x
                   22504: is_norm_x:
                   22505:        mov.b           &NORM, %d0
                   22506:        rts
                   22507: not_norm_x:
                   22508:        tst.w           %d0                     # is exponent = 0?
                   22509:        bne.b           is_unnorm_x
                   22510: not_unnorm_x:
                   22511:        tst.l           FTEMP_HI(%a0)
                   22512:        bne.b           is_denorm_x
                   22513:        tst.l           FTEMP_LO(%a0)
                   22514:        bne.b           is_denorm_x
                   22515: is_zero_x:
                   22516:        mov.b           &ZERO, %d0
                   22517:        rts
                   22518: is_denorm_x:
                   22519:        mov.b           &DENORM, %d0
                   22520:        rts
                   22521: # must distinguish now "Unnormalized zeroes" which we
                   22522: # must convert to zero.
                   22523: is_unnorm_x:
                   22524:        tst.l           FTEMP_HI(%a0)
                   22525:        bne.b           is_unnorm_reg_x
                   22526:        tst.l           FTEMP_LO(%a0)
                   22527:        bne.b           is_unnorm_reg_x
                   22528: # it's an "unnormalized zero". let's convert it to an actual zero...
                   22529:        andi.w          &0x8000,FTEMP_EX(%a0)   # clear exponent
                   22530:        mov.b           &ZERO, %d0
                   22531:        rts
                   22532: is_unnorm_reg_x:
                   22533:        mov.b           &UNNORM, %d0
                   22534:        rts
                   22535: inf_or_nan_x:
                   22536:        tst.l           FTEMP_LO(%a0)
                   22537:        bne.b           is_nan_x
                   22538:        mov.l           FTEMP_HI(%a0), %d0
                   22539:        and.l           &0x7fffffff, %d0        # msb is a don't care!
                   22540:        bne.b           is_nan_x
                   22541: is_inf_x:
                   22542:        mov.b           &INF, %d0
                   22543:        rts
                   22544: is_nan_x:
                   22545:        btst            &0x6, FTEMP_HI(%a0)
                   22546:        beq.b           is_snan_x
                   22547:        mov.b           &QNAN, %d0
                   22548:        rts
                   22549: is_snan_x:
                   22550:        mov.b           &SNAN, %d0
                   22551:        rts
                   22552:
                   22553: #########################################################################
                   22554: # XDEF ****************************************************************        #
                   22555: #      set_tag_d(): return the optype of the input dbl fp number       #
                   22556: #                                                                      #
                   22557: # XREF ****************************************************************        #
                   22558: #      None                                                            #
                   22559: #                                                                      #
                   22560: # INPUT ***************************************************************        #
                   22561: #      a0 = points to double precision operand                         #
                   22562: #                                                                      #
                   22563: # OUTPUT **************************************************************        #
                   22564: #      d0 = value of type tag                                          #
                   22565: #              one of: NORM, INF, QNAN, SNAN, DENORM, ZERO             #
                   22566: #                                                                      #
                   22567: # ALGORITHM ***********************************************************        #
                   22568: #      Simply test the exponent, j-bit, and mantissa values to         #
                   22569: # determine the type of operand.                                       #
                   22570: #                                                                      #
                   22571: #########################################################################
                   22572:
                   22573:        global          set_tag_d
                   22574: set_tag_d:
                   22575:        mov.l           FTEMP(%a0), %d0
                   22576:        mov.l           %d0, %d1
                   22577:
                   22578:        andi.l          &0x7ff00000, %d0
                   22579:        beq.b           zero_or_denorm_d
                   22580:
                   22581:        cmpi.l          %d0, &0x7ff00000
                   22582:        beq.b           inf_or_nan_d
                   22583:
                   22584: is_norm_d:
                   22585:        mov.b           &NORM, %d0
                   22586:        rts
                   22587: zero_or_denorm_d:
                   22588:        and.l           &0x000fffff, %d1
                   22589:        bne             is_denorm_d
                   22590:        tst.l           4+FTEMP(%a0)
                   22591:        bne             is_denorm_d
                   22592: is_zero_d:
                   22593:        mov.b           &ZERO, %d0
                   22594:        rts
                   22595: is_denorm_d:
                   22596:        mov.b           &DENORM, %d0
                   22597:        rts
                   22598: inf_or_nan_d:
                   22599:        and.l           &0x000fffff, %d1
                   22600:        bne             is_nan_d
                   22601:        tst.l           4+FTEMP(%a0)
                   22602:        bne             is_nan_d
                   22603: is_inf_d:
                   22604:        mov.b           &INF, %d0
                   22605:        rts
                   22606: is_nan_d:
                   22607:        btst            &19, %d1
                   22608:        bne             is_qnan_d
                   22609: is_snan_d:
                   22610:        mov.b           &SNAN, %d0
                   22611:        rts
                   22612: is_qnan_d:
                   22613:        mov.b           &QNAN, %d0
                   22614:        rts
                   22615:
                   22616: #########################################################################
                   22617: # XDEF ****************************************************************        #
                   22618: #      set_tag_s(): return the optype of the input sgl fp number       #
                   22619: #                                                                      #
                   22620: # XREF ****************************************************************        #
                   22621: #      None                                                            #
                   22622: #                                                                      #
                   22623: # INPUT ***************************************************************        #
                   22624: #      a0 = pointer to single precision operand                        #
                   22625: #                                                                      #
                   22626: # OUTPUT **************************************************************        #
                   22627: #      d0 = value of type tag                                          #
                   22628: #              one of: NORM, INF, QNAN, SNAN, DENORM, ZERO             #
                   22629: #                                                                      #
                   22630: # ALGORITHM ***********************************************************        #
                   22631: #      Simply test the exponent, j-bit, and mantissa values to         #
                   22632: # determine the type of operand.                                       #
                   22633: #                                                                      #
                   22634: #########################################################################
                   22635:
                   22636:        global          set_tag_s
                   22637: set_tag_s:
                   22638:        mov.l           FTEMP(%a0), %d0
                   22639:        mov.l           %d0, %d1
                   22640:
                   22641:        andi.l          &0x7f800000, %d0
                   22642:        beq.b           zero_or_denorm_s
                   22643:
                   22644:        cmpi.l          %d0, &0x7f800000
                   22645:        beq.b           inf_or_nan_s
                   22646:
                   22647: is_norm_s:
                   22648:        mov.b           &NORM, %d0
                   22649:        rts
                   22650: zero_or_denorm_s:
                   22651:        and.l           &0x007fffff, %d1
                   22652:        bne             is_denorm_s
                   22653: is_zero_s:
                   22654:        mov.b           &ZERO, %d0
                   22655:        rts
                   22656: is_denorm_s:
                   22657:        mov.b           &DENORM, %d0
                   22658:        rts
                   22659: inf_or_nan_s:
                   22660:        and.l           &0x007fffff, %d1
                   22661:        bne             is_nan_s
                   22662: is_inf_s:
                   22663:        mov.b           &INF, %d0
                   22664:        rts
                   22665: is_nan_s:
                   22666:        btst            &22, %d1
                   22667:        bne             is_qnan_s
                   22668: is_snan_s:
                   22669:        mov.b           &SNAN, %d0
                   22670:        rts
                   22671: is_qnan_s:
                   22672:        mov.b           &QNAN, %d0
                   22673:        rts
                   22674:
                   22675: #########################################################################
                   22676: # XDEF ****************************************************************        #
                   22677: #      unf_res(): routine to produce default underflow result of a     #
                   22678: #                 scaled extended precision number; this is used by    #
                   22679: #                 fadd/fdiv/fmul/etc. emulation routines.              #
                   22680: #      unf_res4(): same as above but for fsglmul/fsgldiv which use     #
                   22681: #                  single round prec and extended prec mode.           #
                   22682: #                                                                      #
                   22683: # XREF ****************************************************************        #
                   22684: #      _denorm() - denormalize according to scale factor               #
                   22685: #      _round() - round denormalized number according to rnd prec      #
                   22686: #                                                                      #
                   22687: # INPUT ***************************************************************        #
                   22688: #      a0 = pointer to extended precision operand                      #
                   22689: #      d0 = scale factor                                               #
                   22690: #      d1 = rounding precision/mode                                    #
                   22691: #                                                                      #
                   22692: # OUTPUT **************************************************************        #
                   22693: #      a0 = pointer to default underflow result in extended precision  #
                   22694: #      d0.b = result FPSR_cc which caller may or may not want to save  #
                   22695: #                                                                      #
                   22696: # ALGORITHM ***********************************************************        #
                   22697: #      Convert the input operand to "internal format" which means the  #
                   22698: # exponent is extended to 16 bits and the sign is stored in the unused #
                   22699: # portion of the extended precision operand. Denormalize the number    #
                   22700: # according to the scale factor passed in d0. Then, round the          #
                   22701: # denormalized result.                                                 #
                   22702: #      Set the FPSR_exc bits as appropriate but return the cc bits in  #
                   22703: # d0 in case the caller doesn't want to save them (as is the case for  #
                   22704: # fmove out).                                                          #
                   22705: #      unf_res4() for fsglmul/fsgldiv forces the denorm to extended    #
                   22706: # precision and the rounding mode to single.                           #
                   22707: #                                                                      #
                   22708: #########################################################################
                   22709:        global          unf_res
                   22710: unf_res:
                   22711:        mov.l           %d1, -(%sp)             # save rnd prec,mode on stack
                   22712:
                   22713:        btst            &0x7, FTEMP_EX(%a0)     # make "internal" format
                   22714:        sne             FTEMP_SGN(%a0)
                   22715:
                   22716:        mov.w           FTEMP_EX(%a0), %d1      # extract exponent
                   22717:        and.w           &0x7fff, %d1
                   22718:        sub.w           %d0, %d1
                   22719:        mov.w           %d1, FTEMP_EX(%a0)      # insert 16 bit exponent
                   22720:
                   22721:        mov.l           %a0, -(%sp)             # save operand ptr during calls
                   22722:
                   22723:        mov.l           0x4(%sp),%d0            # pass rnd prec.
                   22724:        andi.w          &0x00c0,%d0
                   22725:        lsr.w           &0x4,%d0
                   22726:        bsr.l           _denorm                 # denorm result
                   22727:
                   22728:        mov.l           (%sp),%a0
                   22729:        mov.w           0x6(%sp),%d1            # load prec:mode into %d1
                   22730:        andi.w          &0xc0,%d1               # extract rnd prec
                   22731:        lsr.w           &0x4,%d1
                   22732:        swap            %d1
                   22733:        mov.w           0x6(%sp),%d1
                   22734:        andi.w          &0x30,%d1
                   22735:        lsr.w           &0x4,%d1
                   22736:        bsr.l           _round                  # round the denorm
                   22737:
                   22738:        mov.l           (%sp)+, %a0
                   22739:
                   22740: # result is now rounded properly. convert back to normal format
                   22741:        bclr            &0x7, FTEMP_EX(%a0)     # clear sgn first; may have residue
                   22742:        tst.b           FTEMP_SGN(%a0)          # is "internal result" sign set?
                   22743:        beq.b           unf_res_chkifzero       # no; result is positive
                   22744:        bset            &0x7, FTEMP_EX(%a0)     # set result sgn
                   22745:        clr.b           FTEMP_SGN(%a0)          # clear temp sign
                   22746:
                   22747: # the number may have become zero after rounding. set ccodes accordingly.
                   22748: unf_res_chkifzero:
                   22749:        clr.l           %d0
                   22750:        tst.l           FTEMP_HI(%a0)           # is value now a zero?
                   22751:        bne.b           unf_res_cont            # no
                   22752:        tst.l           FTEMP_LO(%a0)
                   22753:        bne.b           unf_res_cont            # no
                   22754: #      bset            &z_bit, FPSR_CC(%a6)    # yes; set zero ccode bit
                   22755:        bset            &z_bit, %d0             # yes; set zero ccode bit
                   22756:
                   22757: unf_res_cont:
                   22758:
                   22759: #
                   22760: # can inex1 also be set along with unfl and inex2???
                   22761: #
                   22762: # we know that underflow has occurred. aunfl should be set if INEX2 is also set.
                   22763: #
                   22764:        btst            &inex2_bit, FPSR_EXCEPT(%a6) # is INEX2 set?
                   22765:        beq.b           unf_res_end             # no
                   22766:        bset            &aunfl_bit, FPSR_AEXCEPT(%a6) # yes; set aunfl
                   22767:
                   22768: unf_res_end:
                   22769:        add.l           &0x4, %sp               # clear stack
                   22770:        rts
                   22771:
                   22772: # unf_res() for fsglmul() and fsgldiv().
                   22773:        global          unf_res4
                   22774: unf_res4:
                   22775:        mov.l           %d1,-(%sp)              # save rnd prec,mode on stack
                   22776:
                   22777:        btst            &0x7,FTEMP_EX(%a0)      # make "internal" format
                   22778:        sne             FTEMP_SGN(%a0)
                   22779:
                   22780:        mov.w           FTEMP_EX(%a0),%d1       # extract exponent
                   22781:        and.w           &0x7fff,%d1
                   22782:        sub.w           %d0,%d1
                   22783:        mov.w           %d1,FTEMP_EX(%a0)       # insert 16 bit exponent
                   22784:
                   22785:        mov.l           %a0,-(%sp)              # save operand ptr during calls
                   22786:
                   22787:        clr.l           %d0                     # force rnd prec = ext
                   22788:        bsr.l           _denorm                 # denorm result
                   22789:
                   22790:        mov.l           (%sp),%a0
                   22791:        mov.w           &s_mode,%d1             # force rnd prec = sgl
                   22792:        swap            %d1
                   22793:        mov.w           0x6(%sp),%d1            # load rnd mode
                   22794:        andi.w          &0x30,%d1               # extract rnd prec
                   22795:        lsr.w           &0x4,%d1
                   22796:        bsr.l           _round                  # round the denorm
                   22797:
                   22798:        mov.l           (%sp)+,%a0
                   22799:
                   22800: # result is now rounded properly. convert back to normal format
                   22801:        bclr            &0x7,FTEMP_EX(%a0)      # clear sgn first; may have residue
                   22802:        tst.b           FTEMP_SGN(%a0)          # is "internal result" sign set?
                   22803:        beq.b           unf_res4_chkifzero      # no; result is positive
                   22804:        bset            &0x7,FTEMP_EX(%a0)      # set result sgn
                   22805:        clr.b           FTEMP_SGN(%a0)          # clear temp sign
                   22806:
                   22807: # the number may have become zero after rounding. set ccodes accordingly.
                   22808: unf_res4_chkifzero:
                   22809:        clr.l           %d0
                   22810:        tst.l           FTEMP_HI(%a0)           # is value now a zero?
                   22811:        bne.b           unf_res4_cont           # no
                   22812:        tst.l           FTEMP_LO(%a0)
                   22813:        bne.b           unf_res4_cont           # no
                   22814: #      bset            &z_bit,FPSR_CC(%a6)     # yes; set zero ccode bit
                   22815:        bset            &z_bit,%d0              # yes; set zero ccode bit
                   22816:
                   22817: unf_res4_cont:
                   22818:
                   22819: #
                   22820: # can inex1 also be set along with unfl and inex2???
                   22821: #
                   22822: # we know that underflow has occurred. aunfl should be set if INEX2 is also set.
                   22823: #
                   22824:        btst            &inex2_bit,FPSR_EXCEPT(%a6) # is INEX2 set?
                   22825:        beq.b           unf_res4_end            # no
                   22826:        bset            &aunfl_bit,FPSR_AEXCEPT(%a6) # yes; set aunfl
                   22827:
                   22828: unf_res4_end:
                   22829:        add.l           &0x4,%sp                # clear stack
                   22830:        rts
                   22831:
                   22832: #########################################################################
                   22833: # XDEF ****************************************************************        #
                   22834: #      ovf_res(): routine to produce the default overflow result of    #
                   22835: #                 an overflowing number.                               #
                   22836: #      ovf_res2(): same as above but the rnd mode/prec are passed      #
                   22837: #                  differently.                                        #
                   22838: #                                                                      #
                   22839: # XREF ****************************************************************        #
                   22840: #      none                                                            #
                   22841: #                                                                      #
                   22842: # INPUT ***************************************************************        #
                   22843: #      d1.b    = '-1' => (-); '0' => (+)                               #
                   22844: #   ovf_res():                                                         #
                   22845: #      d0      = rnd mode/prec                                         #
                   22846: #   ovf_res2():                                                                #
                   22847: #      hi(d0)  = rnd prec                                              #
                   22848: #      lo(d0)  = rnd mode                                              #
                   22849: #                                                                      #
                   22850: # OUTPUT **************************************************************        #
                   22851: #      a0      = points to extended precision result                   #
                   22852: #      d0.b    = condition code bits                                   #
                   22853: #                                                                      #
                   22854: # ALGORITHM ***********************************************************        #
                   22855: #      The default overflow result can be determined by the sign of    #
                   22856: # the result and the rounding mode/prec in effect. These bits are      #
                   22857: # concatenated together to create an index into the default result     #
                   22858: # table. A pointer to the correct result is returned in a0. The                #
                   22859: # resulting condition codes are returned in d0 in case the caller      #
                   22860: # doesn't want FPSR_cc altered (as is the case for fmove out).         #
                   22861: #                                                                      #
                   22862: #########################################################################
                   22863:
                   22864:        global          ovf_res
                   22865: ovf_res:
                   22866:        andi.w          &0x10,%d1               # keep result sign
                   22867:        lsr.b           &0x4,%d0                # shift prec/mode
                   22868:        or.b            %d0,%d1                 # concat the two
                   22869:        mov.w           %d1,%d0                 # make a copy
                   22870:        lsl.b           &0x1,%d1                # multiply d1 by 2
                   22871:        bra.b           ovf_res_load
                   22872:
                   22873:        global          ovf_res2
                   22874: ovf_res2:
                   22875:        and.w           &0x10, %d1              # keep result sign
                   22876:        or.b            %d0, %d1                # insert rnd mode
                   22877:        swap            %d0
                   22878:        or.b            %d0, %d1                # insert rnd prec
                   22879:        mov.w           %d1, %d0                # make a copy
                   22880:        lsl.b           &0x1, %d1               # shift left by 1
                   22881:
                   22882: #
                   22883: # use the rounding mode, precision, and result sign as in index into the
                   22884: # two tables below to fetch the default result and the result ccodes.
                   22885: #
                   22886: ovf_res_load:
                   22887:        mov.b           (tbl_ovfl_cc.b,%pc,%d0.w*1), %d0 # fetch result ccodes
                   22888:        lea             (tbl_ovfl_result.b,%pc,%d1.w*8), %a0 # return result ptr
                   22889:
                   22890:        rts
                   22891:
                   22892: tbl_ovfl_cc:
                   22893:        byte            0x2, 0x0, 0x0, 0x2
                   22894:        byte            0x2, 0x0, 0x0, 0x2
                   22895:        byte            0x2, 0x0, 0x0, 0x2
                   22896:        byte            0x0, 0x0, 0x0, 0x0
                   22897:        byte            0x2+0x8, 0x8, 0x2+0x8, 0x8
                   22898:        byte            0x2+0x8, 0x8, 0x2+0x8, 0x8
                   22899:        byte            0x2+0x8, 0x8, 0x2+0x8, 0x8
                   22900:
                   22901: tbl_ovfl_result:
                   22902:        long            0x7fff0000,0x00000000,0x00000000,0x00000000 # +INF; RN
                   22903:        long            0x7ffe0000,0xffffffff,0xffffffff,0x00000000 # +EXT; RZ
                   22904:        long            0x7ffe0000,0xffffffff,0xffffffff,0x00000000 # +EXT; RM
                   22905:        long            0x7fff0000,0x00000000,0x00000000,0x00000000 # +INF; RP
                   22906:
                   22907:        long            0x7fff0000,0x00000000,0x00000000,0x00000000 # +INF; RN
                   22908:        long            0x407e0000,0xffffff00,0x00000000,0x00000000 # +SGL; RZ
                   22909:        long            0x407e0000,0xffffff00,0x00000000,0x00000000 # +SGL; RM
                   22910:        long            0x7fff0000,0x00000000,0x00000000,0x00000000 # +INF; RP
                   22911:
                   22912:        long            0x7fff0000,0x00000000,0x00000000,0x00000000 # +INF; RN
                   22913:        long            0x43fe0000,0xffffffff,0xfffff800,0x00000000 # +DBL; RZ
                   22914:        long            0x43fe0000,0xffffffff,0xfffff800,0x00000000 # +DBL; RM
                   22915:        long            0x7fff0000,0x00000000,0x00000000,0x00000000 # +INF; RP
                   22916:
                   22917:        long            0x00000000,0x00000000,0x00000000,0x00000000
                   22918:        long            0x00000000,0x00000000,0x00000000,0x00000000
                   22919:        long            0x00000000,0x00000000,0x00000000,0x00000000
                   22920:        long            0x00000000,0x00000000,0x00000000,0x00000000
                   22921:
                   22922:        long            0xffff0000,0x00000000,0x00000000,0x00000000 # -INF; RN
                   22923:        long            0xfffe0000,0xffffffff,0xffffffff,0x00000000 # -EXT; RZ
                   22924:        long            0xffff0000,0x00000000,0x00000000,0x00000000 # -INF; RM
                   22925:        long            0xfffe0000,0xffffffff,0xffffffff,0x00000000 # -EXT; RP
                   22926:
                   22927:        long            0xffff0000,0x00000000,0x00000000,0x00000000 # -INF; RN
                   22928:        long            0xc07e0000,0xffffff00,0x00000000,0x00000000 # -SGL; RZ
                   22929:        long            0xffff0000,0x00000000,0x00000000,0x00000000 # -INF; RM
                   22930:        long            0xc07e0000,0xffffff00,0x00000000,0x00000000 # -SGL; RP
                   22931:
                   22932:        long            0xffff0000,0x00000000,0x00000000,0x00000000 # -INF; RN
                   22933:        long            0xc3fe0000,0xffffffff,0xfffff800,0x00000000 # -DBL; RZ
                   22934:        long            0xffff0000,0x00000000,0x00000000,0x00000000 # -INF; RM
                   22935:        long            0xc3fe0000,0xffffffff,0xfffff800,0x00000000 # -DBL; RP
                   22936:
                   22937: #########################################################################
                   22938: # XDEF ****************************************************************        #
                   22939: #      get_packed(): fetch a packed operand from memory and then       #
                   22940: #                    convert it to a floating-point binary number.     #
                   22941: #                                                                      #
                   22942: # XREF ****************************************************************        #
                   22943: #      _dcalc_ea() - calculate the correct <ea>                        #
                   22944: #      _mem_read() - fetch the packed operand from memory              #
                   22945: #      facc_in_x() - the fetch failed so jump to special exit code     #
                   22946: #      decbin()    - convert packed to binary extended precision       #
                   22947: #                                                                      #
                   22948: # INPUT ***************************************************************        #
                   22949: #      None                                                            #
                   22950: #                                                                      #
                   22951: # OUTPUT **************************************************************        #
                   22952: #      If no failure on _mem_read():                                   #
                   22953: #      FP_SRC(a6) = packed operand now as a binary FP number           #
                   22954: #                                                                      #
                   22955: # ALGORITHM ***********************************************************        #
                   22956: #      Get the correct <ea> which is the value on the exception stack  #
                   22957: # frame w/ maybe a correction factor if the <ea> is -(an) or (an)+.    #
                   22958: # Then, fetch the operand from memory. If the fetch fails, exit                #
                   22959: # through facc_in_x().                                                 #
                   22960: #      If the packed operand is a ZERO,NAN, or INF, convert it to      #
                   22961: # its binary representation here. Else, call decbin() which will       #
                   22962: # convert the packed value to an extended precision binary value.      #
                   22963: #                                                                      #
                   22964: #########################################################################
                   22965:
                   22966: # the stacked <ea> for packed is correct except for -(An).
                   22967: # the base reg must be updated for both -(An) and (An)+.
                   22968:        global          get_packed
                   22969: get_packed:
                   22970:        mov.l           &0xc,%d0                # packed is 12 bytes
                   22971:        bsr.l           _dcalc_ea               # fetch <ea>; correct An
                   22972:
                   22973:        lea             FP_SRC(%a6),%a1         # pass: ptr to super dst
                   22974:        mov.l           &0xc,%d0                # pass: 12 bytes
                   22975:        bsr.l           _dmem_read              # read packed operand
                   22976:
                   22977:        tst.l           %d1                     # did dfetch fail?
                   22978:        bne.l           facc_in_x               # yes
                   22979:
                   22980: # The packed operand is an INF or a NAN if the exponent field is all ones.
                   22981:        bfextu          FP_SRC(%a6){&1:&15},%d0 # get exp
                   22982:        cmpi.w          %d0,&0x7fff             # INF or NAN?
                   22983:        bne.b           gp_try_zero             # no
                   22984:        rts                                     # operand is an INF or NAN
                   22985:
                   22986: # The packed operand is a zero if the mantissa is all zero, else it's
                   22987: # a normal packed op.
                   22988: gp_try_zero:
                   22989:        mov.b           3+FP_SRC(%a6),%d0       # get byte 4
                   22990:        andi.b          &0x0f,%d0               # clear all but last nybble
                   22991:        bne.b           gp_not_spec             # not a zero
                   22992:        tst.l           FP_SRC_HI(%a6)          # is lw 2 zero?
                   22993:        bne.b           gp_not_spec             # not a zero
                   22994:        tst.l           FP_SRC_LO(%a6)          # is lw 3 zero?
                   22995:        bne.b           gp_not_spec             # not a zero
                   22996:        rts                                     # operand is a ZERO
                   22997: gp_not_spec:
                   22998:        lea             FP_SRC(%a6),%a0         # pass: ptr to packed op
                   22999:        bsr.l           decbin                  # convert to extended
                   23000:        fmovm.x         &0x80,FP_SRC(%a6)       # make this the srcop
                   23001:        rts
                   23002:
                   23003: #########################################################################
                   23004: # decbin(): Converts normalized packed bcd value pointed to by register        #
                   23005: #          a0 to extended-precision value in fp0.                      #
                   23006: #                                                                      #
                   23007: # INPUT ***************************************************************        #
                   23008: #      a0 = pointer to normalized packed bcd value                     #
                   23009: #                                                                      #
                   23010: # OUTPUT **************************************************************        #
                   23011: #      fp0 = exact fp representation of the packed bcd value.          #
                   23012: #                                                                      #
                   23013: # ALGORITHM ***********************************************************        #
                   23014: #      Expected is a normal bcd (i.e. non-exceptional; all inf, zero,  #
                   23015: #      and NaN operands are dispatched without entering this routine)  #
                   23016: #      value in 68881/882 format at location (a0).                     #
                   23017: #                                                                      #
                   23018: #      A1. Convert the bcd exponent to binary by successive adds and   #
                   23019: #      muls. Set the sign according to SE. Subtract 16 to compensate   #
                   23020: #      for the mantissa which is to be interpreted as 17 integer       #
                   23021: #      digits, rather than 1 integer and 16 fraction digits.           #
                   23022: #      Note: this operation can never overflow.                        #
                   23023: #                                                                      #
                   23024: #      A2. Convert the bcd mantissa to binary by successive            #
                   23025: #      adds and muls in FP0. Set the sign according to SM.             #
                   23026: #      The mantissa digits will be converted with the decimal point    #
                   23027: #      assumed following the least-significant digit.                  #
                   23028: #      Note: this operation can never overflow.                        #
                   23029: #                                                                      #
                   23030: #      A3. Count the number of leading/trailing zeros in the           #
                   23031: #      bcd string.  If SE is positive, count the leading zeros;        #
                   23032: #      if negative, count the trailing zeros.  Set the adjusted        #
                   23033: #      exponent equal to the exponent from A1 and the zero count       #
                   23034: #      added if SM = 1 and subtracted if SM = 0.  Scale the            #
                   23035: #      mantissa the equivalent of forcing in the bcd value:            #
                   23036: #                                                                      #
                   23037: #      SM = 0  a non-zero digit in the integer position                #
                   23038: #      SM = 1  a non-zero digit in Mant0, lsd of the fraction          #
                   23039: #                                                                      #
                   23040: #      this will insure that any value, regardless of its              #
                   23041: #      representation (ex. 0.1E2, 1E1, 10E0, 100E-1), is converted     #
                   23042: #      consistently.                                                   #
                   23043: #                                                                      #
                   23044: #      A4. Calculate the factor 10^exp in FP1 using a table of         #
                   23045: #      10^(2^n) values.  To reduce the error in forming factors        #
                   23046: #      greater than 10^27, a directed rounding scheme is used with     #
                   23047: #      tables rounded to RN, RM, and RP, according to the table        #
                   23048: #      in the comments of the pwrten section.                          #
                   23049: #                                                                      #
                   23050: #      A5. Form the final binary number by scaling the mantissa by     #
                   23051: #      the exponent factor.  This is done by multiplying the           #
                   23052: #      mantissa in FP0 by the factor in FP1 if the adjusted            #
                   23053: #      exponent sign is positive, and dividing FP0 by FP1 if           #
                   23054: #      it is negative.                                                 #
                   23055: #                                                                      #
                   23056: #      Clean up and return. Check if the final mul or div was inexact. #
                   23057: #      If so, set INEX1 in USER_FPSR.                                  #
                   23058: #                                                                      #
                   23059: #########################################################################
                   23060:
                   23061: #
                   23062: #      PTENRN, PTENRM, and PTENRP are arrays of powers of 10 rounded
                   23063: #      to nearest, minus, and plus, respectively.  The tables include
                   23064: #      10**{1,2,4,8,16,32,64,128,256,512,1024,2048,4096}.  No rounding
                   23065: #      is required until the power is greater than 27, however, all
                   23066: #      tables include the first 5 for ease of indexing.
                   23067: #
                   23068: RTABLE:
                   23069:        byte            0,0,0,0
                   23070:        byte            2,3,2,3
                   23071:        byte            2,3,3,2
                   23072:        byte            3,2,2,3
                   23073:
                   23074:        set             FNIBS,7
                   23075:        set             FSTRT,0
                   23076:
                   23077:        set             ESTRT,4
                   23078:        set             EDIGITS,2
                   23079:
                   23080:        global          decbin
                   23081: decbin:
                   23082:        mov.l           0x0(%a0),FP_SCR0_EX(%a6) # make a copy of input
                   23083:        mov.l           0x4(%a0),FP_SCR0_HI(%a6) # so we don't alter it
                   23084:        mov.l           0x8(%a0),FP_SCR0_LO(%a6)
                   23085:
                   23086:        lea             FP_SCR0(%a6),%a0
                   23087:
                   23088:        movm.l          &0x3c00,-(%sp)          # save d2-d5
                   23089:        fmovm.x         &0x1,-(%sp)             # save fp1
                   23090: #
                   23091: # Calculate exponent:
                   23092: #  1. Copy bcd value in memory for use as a working copy.
                   23093: #  2. Calculate absolute value of exponent in d1 by mul and add.
                   23094: #  3. Correct for exponent sign.
                   23095: #  4. Subtract 16 to compensate for interpreting the mant as all integer digits.
                   23096: #     (i.e., all digits assumed left of the decimal point.)
                   23097: #
                   23098: # Register usage:
                   23099: #
                   23100: #  calc_e:
                   23101: #      (*)  d0: temp digit storage
                   23102: #      (*)  d1: accumulator for binary exponent
                   23103: #      (*)  d2: digit count
                   23104: #      (*)  d3: offset pointer
                   23105: #      ( )  d4: first word of bcd
                   23106: #      ( )  a0: pointer to working bcd value
                   23107: #      ( )  a6: pointer to original bcd value
                   23108: #      (*)  FP_SCR1: working copy of original bcd value
                   23109: #      (*)  L_SCR1: copy of original exponent word
                   23110: #
                   23111: calc_e:
                   23112:        mov.l           &EDIGITS,%d2            # # of nibbles (digits) in fraction part
                   23113:        mov.l           &ESTRT,%d3              # counter to pick up digits
                   23114:        mov.l           (%a0),%d4               # get first word of bcd
                   23115:        clr.l           %d1                     # zero d1 for accumulator
                   23116: e_gd:
                   23117:        mulu.l          &0xa,%d1                # mul partial product by one digit place
                   23118:        bfextu          %d4{%d3:&4},%d0         # get the digit and zero extend into d0
                   23119:        add.l           %d0,%d1                 # d1 = d1 + d0
                   23120:        addq.b          &4,%d3                  # advance d3 to the next digit
                   23121:        dbf.w           %d2,e_gd                # if we have used all 3 digits, exit loop
                   23122:        btst            &30,%d4                 # get SE
                   23123:        beq.b           e_pos                   # don't negate if pos
                   23124:        neg.l           %d1                     # negate before subtracting
                   23125: e_pos:
                   23126:        sub.l           &16,%d1                 # sub to compensate for shift of mant
                   23127:        bge.b           e_save                  # if still pos, do not neg
                   23128:        neg.l           %d1                     # now negative, make pos and set SE
                   23129:        or.l            &0x40000000,%d4         # set SE in d4,
                   23130:        or.l            &0x40000000,(%a0)       # and in working bcd
                   23131: e_save:
                   23132:        mov.l           %d1,-(%sp)              # save exp on stack
                   23133: #
                   23134: #
                   23135: # Calculate mantissa:
                   23136: #  1. Calculate absolute value of mantissa in fp0 by mul and add.
                   23137: #  2. Correct for mantissa sign.
                   23138: #     (i.e., all digits assumed left of the decimal point.)
                   23139: #
                   23140: # Register usage:
                   23141: #
                   23142: #  calc_m:
                   23143: #      (*)  d0: temp digit storage
                   23144: #      (*)  d1: lword counter
                   23145: #      (*)  d2: digit count
                   23146: #      (*)  d3: offset pointer
                   23147: #      ( )  d4: words 2 and 3 of bcd
                   23148: #      ( )  a0: pointer to working bcd value
                   23149: #      ( )  a6: pointer to original bcd value
                   23150: #      (*) fp0: mantissa accumulator
                   23151: #      ( )  FP_SCR1: working copy of original bcd value
                   23152: #      ( )  L_SCR1: copy of original exponent word
                   23153: #
                   23154: calc_m:
                   23155:        mov.l           &1,%d1                  # word counter, init to 1
                   23156:        fmov.s          &0x00000000,%fp0        # accumulator
                   23157: #
                   23158: #
                   23159: #  Since the packed number has a long word between the first & second parts,
                   23160: #  get the integer digit then skip down & get the rest of the
                   23161: #  mantissa.  We will unroll the loop once.
                   23162: #
                   23163:        bfextu          (%a0){&28:&4},%d0       # integer part is ls digit in long word
                   23164:        fadd.b          %d0,%fp0                # add digit to sum in fp0
                   23165: #
                   23166: #
                   23167: #  Get the rest of the mantissa.
                   23168: #
                   23169: loadlw:
                   23170:        mov.l           (%a0,%d1.L*4),%d4       # load mantissa lonqword into d4
                   23171:        mov.l           &FSTRT,%d3              # counter to pick up digits
                   23172:        mov.l           &FNIBS,%d2              # reset number of digits per a0 ptr
                   23173: md2b:
                   23174:        fmul.s          &0x41200000,%fp0        # fp0 = fp0 * 10
                   23175:        bfextu          %d4{%d3:&4},%d0         # get the digit and zero extend
                   23176:        fadd.b          %d0,%fp0                # fp0 = fp0 + digit
                   23177: #
                   23178: #
                   23179: #  If all the digits (8) in that long word have been converted (d2=0),
                   23180: #  then inc d1 (=2) to point to the next long word and reset d3 to 0
                   23181: #  to initialize the digit offset, and set d2 to 7 for the digit count;
                   23182: #  else continue with this long word.
                   23183: #
                   23184:        addq.b          &4,%d3                  # advance d3 to the next digit
                   23185:        dbf.w           %d2,md2b                # check for last digit in this lw
                   23186: nextlw:
                   23187:        addq.l          &1,%d1                  # inc lw pointer in mantissa
                   23188:        cmp.l           %d1,&2                  # test for last lw
                   23189:        ble.b           loadlw                  # if not, get last one
                   23190: #
                   23191: #  Check the sign of the mant and make the value in fp0 the same sign.
                   23192: #
                   23193: m_sign:
                   23194:        btst            &31,(%a0)               # test sign of the mantissa
                   23195:        beq.b           ap_st_z                 # if clear, go to append/strip zeros
                   23196:        fneg.x          %fp0                    # if set, negate fp0
                   23197: #
                   23198: # Append/strip zeros:
                   23199: #
                   23200: #  For adjusted exponents which have an absolute value greater than 27*,
                   23201: #  this routine calculates the amount needed to normalize the mantissa
                   23202: #  for the adjusted exponent.  That number is subtracted from the exp
                   23203: #  if the exp was positive, and added if it was negative.  The purpose
                   23204: #  of this is to reduce the value of the exponent and the possibility
                   23205: #  of error in calculation of pwrten.
                   23206: #
                   23207: #  1. Branch on the sign of the adjusted exponent.
                   23208: #  2p.(positive exp)
                   23209: #   2. Check M16 and the digits in lwords 2 and 3 in descending order.
                   23210: #   3. Add one for each zero encountered until a non-zero digit.
                   23211: #   4. Subtract the count from the exp.
                   23212: #   5. Check if the exp has crossed zero in #3 above; make the exp abs
                   23213: #         and set SE.
                   23214: #      6. Multiply the mantissa by 10**count.
                   23215: #  2n.(negative exp)
                   23216: #   2. Check the digits in lwords 3 and 2 in descending order.
                   23217: #   3. Add one for each zero encountered until a non-zero digit.
                   23218: #   4. Add the count to the exp.
                   23219: #   5. Check if the exp has crossed zero in #3 above; clear SE.
                   23220: #   6. Divide the mantissa by 10**count.
                   23221: #
                   23222: #  *Why 27?  If the adjusted exponent is within -28 < expA < 28, than
                   23223: #   any adjustment due to append/strip zeros will drive the resultane
                   23224: #   exponent towards zero.  Since all pwrten constants with a power
                   23225: #   of 27 or less are exact, there is no need to use this routine to
                   23226: #   attempt to lessen the resultant exponent.
                   23227: #
                   23228: # Register usage:
                   23229: #
                   23230: #  ap_st_z:
                   23231: #      (*)  d0: temp digit storage
                   23232: #      (*)  d1: zero count
                   23233: #      (*)  d2: digit count
                   23234: #      (*)  d3: offset pointer
                   23235: #      ( )  d4: first word of bcd
                   23236: #      (*)  d5: lword counter
                   23237: #      ( )  a0: pointer to working bcd value
                   23238: #      ( )  FP_SCR1: working copy of original bcd value
                   23239: #      ( )  L_SCR1: copy of original exponent word
                   23240: #
                   23241: #
                   23242: # First check the absolute value of the exponent to see if this
                   23243: # routine is necessary.  If so, then check the sign of the exponent
                   23244: # and do append (+) or strip (-) zeros accordingly.
                   23245: # This section handles a positive adjusted exponent.
                   23246: #
                   23247: ap_st_z:
                   23248:        mov.l           (%sp),%d1               # load expA for range test
                   23249:        cmp.l           %d1,&27                 # test is with 27
                   23250:        ble.w           pwrten                  # if abs(expA) <28, skip ap/st zeros
                   23251:        btst            &30,(%a0)               # check sign of exp
                   23252:        bne.b           ap_st_n                 # if neg, go to neg side
                   23253:        clr.l           %d1                     # zero count reg
                   23254:        mov.l           (%a0),%d4               # load lword 1 to d4
                   23255:        bfextu          %d4{&28:&4},%d0         # get M16 in d0
                   23256:        bne.b           ap_p_fx                 # if M16 is non-zero, go fix exp
                   23257:        addq.l          &1,%d1                  # inc zero count
                   23258:        mov.l           &1,%d5                  # init lword counter
                   23259:        mov.l           (%a0,%d5.L*4),%d4       # get lword 2 to d4
                   23260:        bne.b           ap_p_cl                 # if lw 2 is zero, skip it
                   23261:        addq.l          &8,%d1                  # and inc count by 8
                   23262:        addq.l          &1,%d5                  # inc lword counter
                   23263:        mov.l           (%a0,%d5.L*4),%d4       # get lword 3 to d4
                   23264: ap_p_cl:
                   23265:        clr.l           %d3                     # init offset reg
                   23266:        mov.l           &7,%d2                  # init digit counter
                   23267: ap_p_gd:
                   23268:        bfextu          %d4{%d3:&4},%d0         # get digit
                   23269:        bne.b           ap_p_fx                 # if non-zero, go to fix exp
                   23270:        addq.l          &4,%d3                  # point to next digit
                   23271:        addq.l          &1,%d1                  # inc digit counter
                   23272:        dbf.w           %d2,ap_p_gd             # get next digit
                   23273: ap_p_fx:
                   23274:        mov.l           %d1,%d0                 # copy counter to d2
                   23275:        mov.l           (%sp),%d1               # get adjusted exp from memory
                   23276:        sub.l           %d0,%d1                 # subtract count from exp
                   23277:        bge.b           ap_p_fm                 # if still pos, go to pwrten
                   23278:        neg.l           %d1                     # now its neg; get abs
                   23279:        mov.l           (%a0),%d4               # load lword 1 to d4
                   23280:        or.l            &0x40000000,%d4         # and set SE in d4
                   23281:        or.l            &0x40000000,(%a0)       # and in memory
                   23282: #
                   23283: # Calculate the mantissa multiplier to compensate for the striping of
                   23284: # zeros from the mantissa.
                   23285: #
                   23286: ap_p_fm:
                   23287:        lea.l           PTENRN(%pc),%a1         # get address of power-of-ten table
                   23288:        clr.l           %d3                     # init table index
                   23289:        fmov.s          &0x3f800000,%fp1        # init fp1 to 1
                   23290:        mov.l           &3,%d2                  # init d2 to count bits in counter
                   23291: ap_p_el:
                   23292:        asr.l           &1,%d0                  # shift lsb into carry
                   23293:        bcc.b           ap_p_en                 # if 1, mul fp1 by pwrten factor
                   23294:        fmul.x          (%a1,%d3),%fp1          # mul by 10**(d3_bit_no)
                   23295: ap_p_en:
                   23296:        add.l           &12,%d3                 # inc d3 to next rtable entry
                   23297:        tst.l           %d0                     # check if d0 is zero
                   23298:        bne.b           ap_p_el                 # if not, get next bit
                   23299:        fmul.x          %fp1,%fp0               # mul mantissa by 10**(no_bits_shifted)
                   23300:        bra.b           pwrten                  # go calc pwrten
                   23301: #
                   23302: # This section handles a negative adjusted exponent.
                   23303: #
                   23304: ap_st_n:
                   23305:        clr.l           %d1                     # clr counter
                   23306:        mov.l           &2,%d5                  # set up d5 to point to lword 3
                   23307:        mov.l           (%a0,%d5.L*4),%d4       # get lword 3
                   23308:        bne.b           ap_n_cl                 # if not zero, check digits
                   23309:        sub.l           &1,%d5                  # dec d5 to point to lword 2
                   23310:        addq.l          &8,%d1                  # inc counter by 8
                   23311:        mov.l           (%a0,%d5.L*4),%d4       # get lword 2
                   23312: ap_n_cl:
                   23313:        mov.l           &28,%d3                 # point to last digit
                   23314:        mov.l           &7,%d2                  # init digit counter
                   23315: ap_n_gd:
                   23316:        bfextu          %d4{%d3:&4},%d0         # get digit
                   23317:        bne.b           ap_n_fx                 # if non-zero, go to exp fix
                   23318:        subq.l          &4,%d3                  # point to previous digit
                   23319:        addq.l          &1,%d1                  # inc digit counter
                   23320:        dbf.w           %d2,ap_n_gd             # get next digit
                   23321: ap_n_fx:
                   23322:        mov.l           %d1,%d0                 # copy counter to d0
                   23323:        mov.l           (%sp),%d1               # get adjusted exp from memory
                   23324:        sub.l           %d0,%d1                 # subtract count from exp
                   23325:        bgt.b           ap_n_fm                 # if still pos, go fix mantissa
                   23326:        neg.l           %d1                     # take abs of exp and clr SE
                   23327:        mov.l           (%a0),%d4               # load lword 1 to d4
                   23328:        and.l           &0xbfffffff,%d4         # and clr SE in d4
                   23329:        and.l           &0xbfffffff,(%a0)       # and in memory
                   23330: #
                   23331: # Calculate the mantissa multiplier to compensate for the appending of
                   23332: # zeros to the mantissa.
                   23333: #
                   23334: ap_n_fm:
                   23335:        lea.l           PTENRN(%pc),%a1         # get address of power-of-ten table
                   23336:        clr.l           %d3                     # init table index
                   23337:        fmov.s          &0x3f800000,%fp1        # init fp1 to 1
                   23338:        mov.l           &3,%d2                  # init d2 to count bits in counter
                   23339: ap_n_el:
                   23340:        asr.l           &1,%d0                  # shift lsb into carry
                   23341:        bcc.b           ap_n_en                 # if 1, mul fp1 by pwrten factor
                   23342:        fmul.x          (%a1,%d3),%fp1          # mul by 10**(d3_bit_no)
                   23343: ap_n_en:
                   23344:        add.l           &12,%d3                 # inc d3 to next rtable entry
                   23345:        tst.l           %d0                     # check if d0 is zero
                   23346:        bne.b           ap_n_el                 # if not, get next bit
                   23347:        fdiv.x          %fp1,%fp0               # div mantissa by 10**(no_bits_shifted)
                   23348: #
                   23349: #
                   23350: # Calculate power-of-ten factor from adjusted and shifted exponent.
                   23351: #
                   23352: # Register usage:
                   23353: #
                   23354: #  pwrten:
                   23355: #      (*)  d0: temp
                   23356: #      ( )  d1: exponent
                   23357: #      (*)  d2: {FPCR[6:5],SM,SE} as index in RTABLE; temp
                   23358: #      (*)  d3: FPCR work copy
                   23359: #      ( )  d4: first word of bcd
                   23360: #      (*)  a1: RTABLE pointer
                   23361: #  calc_p:
                   23362: #      (*)  d0: temp
                   23363: #      ( )  d1: exponent
                   23364: #      (*)  d3: PWRTxx table index
                   23365: #      ( )  a0: pointer to working copy of bcd
                   23366: #      (*)  a1: PWRTxx pointer
                   23367: #      (*) fp1: power-of-ten accumulator
                   23368: #
                   23369: # Pwrten calculates the exponent factor in the selected rounding mode
                   23370: # according to the following table:
                   23371: #
                   23372: #      Sign of Mant  Sign of Exp  Rounding Mode  PWRTEN Rounding Mode
                   23373: #
                   23374: #      ANY       ANY   RN      RN
                   23375: #
                   23376: #       +         +    RP      RP
                   23377: #       -         +    RP      RM
                   23378: #       +         -    RP      RM
                   23379: #       -         -    RP      RP
                   23380: #
                   23381: #       +         +    RM      RM
                   23382: #       -         +    RM      RP
                   23383: #       +         -    RM      RP
                   23384: #       -         -    RM      RM
                   23385: #
                   23386: #       +         +    RZ      RM
                   23387: #       -         +    RZ      RM
                   23388: #       +         -    RZ      RP
                   23389: #       -         -    RZ      RP
                   23390: #
                   23391: #
                   23392: pwrten:
                   23393:        mov.l           USER_FPCR(%a6),%d3      # get user's FPCR
                   23394:        bfextu          %d3{&26:&2},%d2         # isolate rounding mode bits
                   23395:        mov.l           (%a0),%d4               # reload 1st bcd word to d4
                   23396:        asl.l           &2,%d2                  # format d2 to be
                   23397:        bfextu          %d4{&0:&2},%d0          # {FPCR[6],FPCR[5],SM,SE}
                   23398:        add.l           %d0,%d2                 # in d2 as index into RTABLE
                   23399:        lea.l           RTABLE(%pc),%a1         # load rtable base
                   23400:        mov.b           (%a1,%d2),%d0           # load new rounding bits from table
                   23401:        clr.l           %d3                     # clear d3 to force no exc and extended
                   23402:        bfins           %d0,%d3{&26:&2}         # stuff new rounding bits in FPCR
                   23403:        fmov.l          %d3,%fpcr               # write new FPCR
                   23404:        asr.l           &1,%d0                  # write correct PTENxx table
                   23405:        bcc.b           not_rp                  # to a1
                   23406:        lea.l           PTENRP(%pc),%a1         # it is RP
                   23407:        bra.b           calc_p                  # go to init section
                   23408: not_rp:
                   23409:        asr.l           &1,%d0                  # keep checking
                   23410:        bcc.b           not_rm
                   23411:        lea.l           PTENRM(%pc),%a1         # it is RM
                   23412:        bra.b           calc_p                  # go to init section
                   23413: not_rm:
                   23414:        lea.l           PTENRN(%pc),%a1         # it is RN
                   23415: calc_p:
                   23416:        mov.l           %d1,%d0                 # copy exp to d0;use d0
                   23417:        bpl.b           no_neg                  # if exp is negative,
                   23418:        neg.l           %d0                     # invert it
                   23419:        or.l            &0x40000000,(%a0)       # and set SE bit
                   23420: no_neg:
                   23421:        clr.l           %d3                     # table index
                   23422:        fmov.s          &0x3f800000,%fp1        # init fp1 to 1
                   23423: e_loop:
                   23424:        asr.l           &1,%d0                  # shift next bit into carry
                   23425:        bcc.b           e_next                  # if zero, skip the mul
                   23426:        fmul.x          (%a1,%d3),%fp1          # mul by 10**(d3_bit_no)
                   23427: e_next:
                   23428:        add.l           &12,%d3                 # inc d3 to next rtable entry
                   23429:        tst.l           %d0                     # check if d0 is zero
                   23430:        bne.b           e_loop                  # not zero, continue shifting
                   23431: #
                   23432: #
                   23433: #  Check the sign of the adjusted exp and make the value in fp0 the
                   23434: #  same sign. If the exp was pos then multiply fp1*fp0;
                   23435: #  else divide fp0/fp1.
                   23436: #
                   23437: # Register Usage:
                   23438: #  norm:
                   23439: #      ( )  a0: pointer to working bcd value
                   23440: #      (*) fp0: mantissa accumulator
                   23441: #      ( ) fp1: scaling factor - 10**(abs(exp))
                   23442: #
                   23443: pnorm:
                   23444:        btst            &30,(%a0)               # test the sign of the exponent
                   23445:        beq.b           mul                     # if clear, go to multiply
                   23446: div:
                   23447:        fdiv.x          %fp1,%fp0               # exp is negative, so divide mant by exp
                   23448:        bra.b           end_dec
                   23449: mul:
                   23450:        fmul.x          %fp1,%fp0               # exp is positive, so multiply by exp
                   23451: #
                   23452: #
                   23453: # Clean up and return with result in fp0.
                   23454: #
                   23455: # If the final mul/div in decbin incurred an inex exception,
                   23456: # it will be inex2, but will be reported as inex1 by get_op.
                   23457: #
                   23458: end_dec:
                   23459:        fmov.l          %fpsr,%d0               # get status register
                   23460:        bclr            &inex2_bit+8,%d0        # test for inex2 and clear it
                   23461:        beq.b           no_exc                  # skip this if no exc
                   23462:        ori.w           &inx1a_mask,2+USER_FPSR(%a6) # set INEX1/AINEX
                   23463: no_exc:
                   23464:        add.l           &0x4,%sp                # clear 1 lw param
                   23465:        fmovm.x         (%sp)+,&0x40            # restore fp1
                   23466:        movm.l          (%sp)+,&0x3c            # restore d2-d5
                   23467:        fmov.l          &0x0,%fpcr
                   23468:        fmov.l          &0x0,%fpsr
                   23469:        rts
                   23470:
                   23471: #########################################################################
                   23472: # bindec(): Converts an input in extended precision format to bcd format#
                   23473: #                                                                      #
                   23474: # INPUT ***************************************************************        #
                   23475: #      a0 = pointer to the input extended precision value in memory.   #
                   23476: #           the input may be either normalized, unnormalized, or       #
                   23477: #           denormalized.                                              #
                   23478: #      d0 = contains the k-factor sign-extended to 32-bits.            #
                   23479: #                                                                      #
                   23480: # OUTPUT **************************************************************        #
                   23481: #      FP_SCR0(a6) = bcd format result on the stack.                   #
                   23482: #                                                                      #
                   23483: # ALGORITHM ***********************************************************        #
                   23484: #                                                                      #
                   23485: #      A1.     Set RM and size ext;  Set SIGMA = sign of input.        #
                   23486: #              The k-factor is saved for use in d7. Clear the          #
                   23487: #              BINDEC_FLG for separating normalized/denormalized       #
                   23488: #              input.  If input is unnormalized or denormalized,       #
                   23489: #              normalize it.                                           #
                   23490: #                                                                      #
                   23491: #      A2.     Set X = abs(input).                                     #
                   23492: #                                                                      #
                   23493: #      A3.     Compute ILOG.                                           #
                   23494: #              ILOG is the log base 10 of the input value.  It is      #
                   23495: #              approximated by adding e + 0.f when the original        #
                   23496: #              value is viewed as 2^^e * 1.f in extended precision.    #
                   23497: #              This value is stored in d6.                             #
                   23498: #                                                                      #
                   23499: #      A4.     Clr INEX bit.                                           #
                   23500: #              The operation in A3 above may have set INEX2.           #
                   23501: #                                                                      #
                   23502: #      A5.     Set ICTR = 0;                                           #
                   23503: #              ICTR is a flag used in A13.  It must be set before the  #
                   23504: #              loop entry A6.                                          #
                   23505: #                                                                      #
                   23506: #      A6.     Calculate LEN.                                          #
                   23507: #              LEN is the number of digits to be displayed.  The       #
                   23508: #              k-factor can dictate either the total number of digits, #
                   23509: #              if it is a positive number, or the number of digits     #
                   23510: #              after the decimal point which are to be included as     #
                   23511: #              significant.  See the 68882 manual for examples.        #
                   23512: #              If LEN is computed to be greater than 17, set OPERR in  #
                   23513: #              USER_FPSR.  LEN is stored in d4.                        #
                   23514: #                                                                      #
                   23515: #      A7.     Calculate SCALE.                                        #
                   23516: #              SCALE is equal to 10^ISCALE, where ISCALE is the number #
                   23517: #              of decimal places needed to insure LEN integer digits   #
                   23518: #              in the output before conversion to bcd. LAMBDA is the   #
                   23519: #              sign of ISCALE, used in A9. Fp1 contains                #
                   23520: #              10^^(abs(ISCALE)) using a rounding mode which is a      #
                   23521: #              function of the original rounding mode and the signs    #
                   23522: #              of ISCALE and X.  A table is given in the code.         #
                   23523: #                                                                      #
                   23524: #      A8.     Clr INEX; Force RZ.                                     #
                   23525: #              The operation in A3 above may have set INEX2.           #
                   23526: #              RZ mode is forced for the scaling operation to insure   #
                   23527: #              only one rounding error.  The grs bits are collected in #
                   23528: #              the INEX flag for use in A10.                           #
                   23529: #                                                                      #
                   23530: #      A9.     Scale X -> Y.                                           #
                   23531: #              The mantissa is scaled to the desired number of         #
                   23532: #              significant digits.  The excess digits are collected    #
                   23533: #              in INEX2.                                               #
                   23534: #                                                                      #
                   23535: #      A10.    Or in INEX.                                             #
                   23536: #              If INEX is set, round error occurred.  This is          #
                   23537: #              compensated for by 'or-ing' in the INEX2 flag to        #
                   23538: #              the lsb of Y.                                           #
                   23539: #                                                                      #
                   23540: #      A11.    Restore original FPCR; set size ext.                    #
                   23541: #              Perform FINT operation in the user's rounding mode.     #
                   23542: #              Keep the size to extended.                              #
                   23543: #                                                                      #
                   23544: #      A12.    Calculate YINT = FINT(Y) according to user's rounding   #
                   23545: #              mode.  The FPSP routine sintd0 is used.  The output     #
                   23546: #              is in fp0.                                              #
                   23547: #                                                                      #
                   23548: #      A13.    Check for LEN digits.                                   #
                   23549: #              If the int operation results in more than LEN digits,   #
                   23550: #              or less than LEN -1 digits, adjust ILOG and repeat from #
                   23551: #              A6.  This test occurs only on the first pass.  If the   #
                   23552: #              result is exactly 10^LEN, decrement ILOG and divide     #
                   23553: #              the mantissa by 10.                                     #
                   23554: #                                                                      #
                   23555: #      A14.    Convert the mantissa to bcd.                            #
                   23556: #              The binstr routine is used to convert the LEN digit     #
                   23557: #              mantissa to bcd in memory.  The input to binstr is      #
                   23558: #              to be a fraction; i.e. (mantissa)/10^LEN and adjusted   #
                   23559: #              such that the decimal point is to the left of bit 63.   #
                   23560: #              The bcd digits are stored in the correct position in    #
                   23561: #              the final string area in memory.                        #
                   23562: #                                                                      #
                   23563: #      A15.    Convert the exponent to bcd.                            #
                   23564: #              As in A14 above, the exp is converted to bcd and the    #
                   23565: #              digits are stored in the final string.                  #
                   23566: #              Test the length of the final exponent string.  If the   #
                   23567: #              length is 4, set operr.                                 #
                   23568: #                                                                      #
                   23569: #      A16.    Write sign bits to final string.                        #
                   23570: #                                                                      #
                   23571: #########################################################################
                   23572:
                   23573: set    BINDEC_FLG,     EXC_TEMP        # DENORM flag
                   23574:
                   23575: # Constants in extended precision
                   23576: PLOG2:
                   23577:        long            0x3FFD0000,0x9A209A84,0xFBCFF798,0x00000000
                   23578: PLOG2UP1:
                   23579:        long            0x3FFD0000,0x9A209A84,0xFBCFF799,0x00000000
                   23580:
                   23581: # Constants in single precision
                   23582: FONE:
                   23583:        long            0x3F800000,0x00000000,0x00000000,0x00000000
                   23584: FTWO:
                   23585:        long            0x40000000,0x00000000,0x00000000,0x00000000
                   23586: FTEN:
                   23587:        long            0x41200000,0x00000000,0x00000000,0x00000000
                   23588: F4933:
                   23589:        long            0x459A2800,0x00000000,0x00000000,0x00000000
                   23590:
                   23591: RBDTBL:
                   23592:        byte            0,0,0,0
                   23593:        byte            3,3,2,2
                   23594:        byte            3,2,2,3
                   23595:        byte            2,3,3,2
                   23596:
                   23597: #      Implementation Notes:
                   23598: #
                   23599: #      The registers are used as follows:
                   23600: #
                   23601: #              d0: scratch; LEN input to binstr
                   23602: #              d1: scratch
                   23603: #              d2: upper 32-bits of mantissa for binstr
                   23604: #              d3: scratch;lower 32-bits of mantissa for binstr
                   23605: #              d4: LEN
                   23606: #                      d5: LAMBDA/ICTR
                   23607: #              d6: ILOG
                   23608: #              d7: k-factor
                   23609: #              a0: ptr for original operand/final result
                   23610: #              a1: scratch pointer
                   23611: #              a2: pointer to FP_X; abs(original value) in ext
                   23612: #              fp0: scratch
                   23613: #              fp1: scratch
                   23614: #              fp2: scratch
                   23615: #              F_SCR1:
                   23616: #              F_SCR2:
                   23617: #              L_SCR1:
                   23618: #              L_SCR2:
                   23619:
                   23620:        global          bindec
                   23621: bindec:
                   23622:        movm.l          &0x3f20,-(%sp)  #  {%d2-%d7/%a2}
                   23623:        fmovm.x         &0x7,-(%sp)     #  {%fp0-%fp2}
                   23624:
                   23625: # A1. Set RM and size ext. Set SIGMA = sign input;
                   23626: #     The k-factor is saved for use in d7.  Clear BINDEC_FLG for
                   23627: #     separating  normalized/denormalized input.  If the input
                   23628: #     is a denormalized number, set the BINDEC_FLG memory word
                   23629: #     to signal denorm.  If the input is unnormalized, normalize
                   23630: #     the input and test for denormalized result.
                   23631: #
                   23632:        fmov.l          &rm_mode*0x10,%fpcr     # set RM and ext
                   23633:        mov.l           (%a0),L_SCR2(%a6)       # save exponent for sign check
                   23634:        mov.l           %d0,%d7         # move k-factor to d7
                   23635:
                   23636:        clr.b           BINDEC_FLG(%a6) # clr norm/denorm flag
                   23637:        cmpi.b          STAG(%a6),&DENORM # is input a DENORM?
                   23638:        bne.w           A2_str          # no; input is a NORM
                   23639:
                   23640: #
                   23641: # Normalize the denorm
                   23642: #
                   23643: un_de_norm:
                   23644:        mov.w           (%a0),%d0
                   23645:        and.w           &0x7fff,%d0     # strip sign of normalized exp
                   23646:        mov.l           4(%a0),%d1
                   23647:        mov.l           8(%a0),%d2
                   23648: norm_loop:
                   23649:        sub.w           &1,%d0
                   23650:        lsl.l           &1,%d2
                   23651:        roxl.l          &1,%d1
                   23652:        tst.l           %d1
                   23653:        bge.b           norm_loop
                   23654: #
                   23655: # Test if the normalized input is denormalized
                   23656: #
                   23657:        tst.w           %d0
                   23658:        bgt.b           pos_exp         # if greater than zero, it is a norm
                   23659:        st              BINDEC_FLG(%a6) # set flag for denorm
                   23660: pos_exp:
                   23661:        and.w           &0x7fff,%d0     # strip sign of normalized exp
                   23662:        mov.w           %d0,(%a0)
                   23663:        mov.l           %d1,4(%a0)
                   23664:        mov.l           %d2,8(%a0)
                   23665:
                   23666: # A2. Set X = abs(input).
                   23667: #
                   23668: A2_str:
                   23669:        mov.l           (%a0),FP_SCR1(%a6)      # move input to work space
                   23670:        mov.l           4(%a0),FP_SCR1+4(%a6)   # move input to work space
                   23671:        mov.l           8(%a0),FP_SCR1+8(%a6)   # move input to work space
                   23672:        and.l           &0x7fffffff,FP_SCR1(%a6)        # create abs(X)
                   23673:
                   23674: # A3. Compute ILOG.
                   23675: #     ILOG is the log base 10 of the input value.  It is approx-
                   23676: #     imated by adding e + 0.f when the original value is viewed
                   23677: #     as 2^^e * 1.f in extended precision.  This value is stored
                   23678: #     in d6.
                   23679: #
                   23680: # Register usage:
                   23681: #      Input/Output
                   23682: #      d0: k-factor/exponent
                   23683: #      d2: x/x
                   23684: #      d3: x/x
                   23685: #      d4: x/x
                   23686: #      d5: x/x
                   23687: #      d6: x/ILOG
                   23688: #      d7: k-factor/Unchanged
                   23689: #      a0: ptr for original operand/final result
                   23690: #      a1: x/x
                   23691: #      a2: x/x
                   23692: #      fp0: x/float(ILOG)
                   23693: #      fp1: x/x
                   23694: #      fp2: x/x
                   23695: #      F_SCR1:x/x
                   23696: #      F_SCR2:Abs(X)/Abs(X) with $3fff exponent
                   23697: #      L_SCR1:x/x
                   23698: #      L_SCR2:first word of X packed/Unchanged
                   23699:
                   23700:        tst.b           BINDEC_FLG(%a6) # check for denorm
                   23701:        beq.b           A3_cont         # if clr, continue with norm
                   23702:        mov.l           &-4933,%d6      # force ILOG = -4933
                   23703:        bra.b           A4_str
                   23704: A3_cont:
                   23705:        mov.w           FP_SCR1(%a6),%d0        # move exp to d0
                   23706:        mov.w           &0x3fff,FP_SCR1(%a6)    # replace exponent with 0x3fff
                   23707:        fmov.x          FP_SCR1(%a6),%fp0       # now fp0 has 1.f
                   23708:        sub.w           &0x3fff,%d0     # strip off bias
                   23709:        fadd.w          %d0,%fp0        # add in exp
                   23710:        fsub.s          FONE(%pc),%fp0  # subtract off 1.0
                   23711:        fbge.w          pos_res         # if pos, branch
                   23712:        fmul.x          PLOG2UP1(%pc),%fp0      # if neg, mul by LOG2UP1
                   23713:        fmov.l          %fp0,%d6        # put ILOG in d6 as a lword
                   23714:        bra.b           A4_str          # go move out ILOG
                   23715: pos_res:
                   23716:        fmul.x          PLOG2(%pc),%fp0 # if pos, mul by LOG2
                   23717:        fmov.l          %fp0,%d6        # put ILOG in d6 as a lword
                   23718:
                   23719:
                   23720: # A4. Clr INEX bit.
                   23721: #     The operation in A3 above may have set INEX2.
                   23722:
                   23723: A4_str:
                   23724:        fmov.l          &0,%fpsr        # zero all of fpsr - nothing needed
                   23725:
                   23726:
                   23727: # A5. Set ICTR = 0;
                   23728: #     ICTR is a flag used in A13.  It must be set before the
                   23729: #     loop entry A6. The lower word of d5 is used for ICTR.
                   23730:
                   23731:        clr.w           %d5             # clear ICTR
                   23732:
                   23733: # A6. Calculate LEN.
                   23734: #     LEN is the number of digits to be displayed.  The k-factor
                   23735: #     can dictate either the total number of digits, if it is
                   23736: #     a positive number, or the number of digits after the
                   23737: #     original decimal point which are to be included as
                   23738: #     significant.  See the 68882 manual for examples.
                   23739: #     If LEN is computed to be greater than 17, set OPERR in
                   23740: #     USER_FPSR.  LEN is stored in d4.
                   23741: #
                   23742: # Register usage:
                   23743: #      Input/Output
                   23744: #      d0: exponent/Unchanged
                   23745: #      d2: x/x/scratch
                   23746: #      d3: x/x
                   23747: #      d4: exc picture/LEN
                   23748: #      d5: ICTR/Unchanged
                   23749: #      d6: ILOG/Unchanged
                   23750: #      d7: k-factor/Unchanged
                   23751: #      a0: ptr for original operand/final result
                   23752: #      a1: x/x
                   23753: #      a2: x/x
                   23754: #      fp0: float(ILOG)/Unchanged
                   23755: #      fp1: x/x
                   23756: #      fp2: x/x
                   23757: #      F_SCR1:x/x
                   23758: #      F_SCR2:Abs(X) with $3fff exponent/Unchanged
                   23759: #      L_SCR1:x/x
                   23760: #      L_SCR2:first word of X packed/Unchanged
                   23761:
                   23762: A6_str:
                   23763:        tst.l           %d7             # branch on sign of k
                   23764:        ble.b           k_neg           # if k <= 0, LEN = ILOG + 1 - k
                   23765:        mov.l           %d7,%d4         # if k > 0, LEN = k
                   23766:        bra.b           len_ck          # skip to LEN check
                   23767: k_neg:
                   23768:        mov.l           %d6,%d4         # first load ILOG to d4
                   23769:        sub.l           %d7,%d4         # subtract off k
                   23770:        addq.l          &1,%d4          # add in the 1
                   23771: len_ck:
                   23772:        tst.l           %d4             # LEN check: branch on sign of LEN
                   23773:        ble.b           LEN_ng          # if neg, set LEN = 1
                   23774:        cmp.l           %d4,&17         # test if LEN > 17
                   23775:        ble.b           A7_str          # if not, forget it
                   23776:        mov.l           &17,%d4         # set max LEN = 17
                   23777:        tst.l           %d7             # if negative, never set OPERR
                   23778:        ble.b           A7_str          # if positive, continue
                   23779:        or.l            &opaop_mask,USER_FPSR(%a6)      # set OPERR & AIOP in USER_FPSR
                   23780:        bra.b           A7_str          # finished here
                   23781: LEN_ng:
                   23782:        mov.l           &1,%d4          # min LEN is 1
                   23783:
                   23784:
                   23785: # A7. Calculate SCALE.
                   23786: #     SCALE is equal to 10^ISCALE, where ISCALE is the number
                   23787: #     of decimal places needed to insure LEN integer digits
                   23788: #     in the output before conversion to bcd. LAMBDA is the sign
                   23789: #     of ISCALE, used in A9.  Fp1 contains 10^^(abs(ISCALE)) using
                   23790: #     the rounding mode as given in the following table (see
                   23791: #     Coonen, p. 7.23 as ref.; however, the SCALE variable is
                   23792: #     of opposite sign in bindec.sa from Coonen).
                   23793: #
                   23794: #      Initial                                 USE
                   23795: #      FPCR[6:5]       LAMBDA  SIGN(X)         FPCR[6:5]
                   23796: #      ----------------------------------------------
                   23797: #       RN     00         0       0            00/0    RN
                   23798: #       RN     00         0       1            00/0    RN
                   23799: #       RN     00         1       0            00/0    RN
                   23800: #       RN     00         1       1            00/0    RN
                   23801: #       RZ     01         0       0            11/3    RP
                   23802: #       RZ     01         0       1            11/3    RP
                   23803: #       RZ     01         1       0            10/2    RM
                   23804: #       RZ     01         1       1            10/2    RM
                   23805: #       RM     10         0       0            11/3    RP
                   23806: #       RM     10         0       1            10/2    RM
                   23807: #       RM     10         1       0            10/2    RM
                   23808: #       RM     10         1       1            11/3    RP
                   23809: #       RP     11         0       0            10/2    RM
                   23810: #       RP     11         0       1            11/3    RP
                   23811: #       RP     11         1       0            11/3    RP
                   23812: #       RP     11         1       1            10/2    RM
                   23813: #
                   23814: # Register usage:
                   23815: #      Input/Output
                   23816: #      d0: exponent/scratch - final is 0
                   23817: #      d2: x/0 or 24 for A9
                   23818: #      d3: x/scratch - offset ptr into PTENRM array
                   23819: #      d4: LEN/Unchanged
                   23820: #      d5: 0/ICTR:LAMBDA
                   23821: #      d6: ILOG/ILOG or k if ((k<=0)&(ILOG<k))
                   23822: #      d7: k-factor/Unchanged
                   23823: #      a0: ptr for original operand/final result
                   23824: #      a1: x/ptr to PTENRM array
                   23825: #      a2: x/x
                   23826: #      fp0: float(ILOG)/Unchanged
                   23827: #      fp1: x/10^ISCALE
                   23828: #      fp2: x/x
                   23829: #      F_SCR1:x/x
                   23830: #      F_SCR2:Abs(X) with $3fff exponent/Unchanged
                   23831: #      L_SCR1:x/x
                   23832: #      L_SCR2:first word of X packed/Unchanged
                   23833:
                   23834: A7_str:
                   23835:        tst.l           %d7             # test sign of k
                   23836:        bgt.b           k_pos           # if pos and > 0, skip this
                   23837:        cmp.l           %d7,%d6         # test k - ILOG
                   23838:        blt.b           k_pos           # if ILOG >= k, skip this
                   23839:        mov.l           %d7,%d6         # if ((k<0) & (ILOG < k)) ILOG = k
                   23840: k_pos:
                   23841:        mov.l           %d6,%d0         # calc ILOG + 1 - LEN in d0
                   23842:        addq.l          &1,%d0          # add the 1
                   23843:        sub.l           %d4,%d0         # sub off LEN
                   23844:        swap            %d5             # use upper word of d5 for LAMBDA
                   23845:        clr.w           %d5             # set it zero initially
                   23846:        clr.w           %d2             # set up d2 for very small case
                   23847:        tst.l           %d0             # test sign of ISCALE
                   23848:        bge.b           iscale          # if pos, skip next inst
                   23849:        addq.w          &1,%d5          # if neg, set LAMBDA true
                   23850:        cmp.l           %d0,&0xffffecd4 # test iscale <= -4908
                   23851:        bgt.b           no_inf          # if false, skip rest
                   23852:        add.l           &24,%d0         # add in 24 to iscale
                   23853:        mov.l           &24,%d2         # put 24 in d2 for A9
                   23854: no_inf:
                   23855:        neg.l           %d0             # and take abs of ISCALE
                   23856: iscale:
                   23857:        fmov.s          FONE(%pc),%fp1  # init fp1 to 1
                   23858:        bfextu          USER_FPCR(%a6){&26:&2},%d1      # get initial rmode bits
                   23859:        lsl.w           &1,%d1          # put them in bits 2:1
                   23860:        add.w           %d5,%d1         # add in LAMBDA
                   23861:        lsl.w           &1,%d1          # put them in bits 3:1
                   23862:        tst.l           L_SCR2(%a6)     # test sign of original x
                   23863:        bge.b           x_pos           # if pos, don't set bit 0
                   23864:        addq.l          &1,%d1          # if neg, set bit 0
                   23865: x_pos:
                   23866:        lea.l           RBDTBL(%pc),%a2 # load rbdtbl base
                   23867:        mov.b           (%a2,%d1),%d3   # load d3 with new rmode
                   23868:        lsl.l           &4,%d3          # put bits in proper position
                   23869:        fmov.l          %d3,%fpcr       # load bits into fpu
                   23870:        lsr.l           &4,%d3          # put bits in proper position
                   23871:        tst.b           %d3             # decode new rmode for pten table
                   23872:        bne.b           not_rn          # if zero, it is RN
                   23873:        lea.l           PTENRN(%pc),%a1 # load a1 with RN table base
                   23874:        bra.b           rmode           # exit decode
                   23875: not_rn:
                   23876:        lsr.b           &1,%d3          # get lsb in carry
                   23877:        bcc.b           not_rp2         # if carry clear, it is RM
                   23878:        lea.l           PTENRP(%pc),%a1 # load a1 with RP table base
                   23879:        bra.b           rmode           # exit decode
                   23880: not_rp2:
                   23881:        lea.l           PTENRM(%pc),%a1 # load a1 with RM table base
                   23882: rmode:
                   23883:        clr.l           %d3             # clr table index
                   23884: e_loop2:
                   23885:        lsr.l           &1,%d0          # shift next bit into carry
                   23886:        bcc.b           e_next2         # if zero, skip the mul
                   23887:        fmul.x          (%a1,%d3),%fp1  # mul by 10**(d3_bit_no)
                   23888: e_next2:
                   23889:        add.l           &12,%d3         # inc d3 to next pwrten table entry
                   23890:        tst.l           %d0             # test if ISCALE is zero
                   23891:        bne.b           e_loop2         # if not, loop
                   23892:
                   23893: # A8. Clr INEX; Force RZ.
                   23894: #     The operation in A3 above may have set INEX2.
                   23895: #     RZ mode is forced for the scaling operation to insure
                   23896: #     only one rounding error.  The grs bits are collected in
                   23897: #     the INEX flag for use in A10.
                   23898: #
                   23899: # Register usage:
                   23900: #      Input/Output
                   23901:
                   23902:        fmov.l          &0,%fpsr        # clr INEX
                   23903:        fmov.l          &rz_mode*0x10,%fpcr     # set RZ rounding mode
                   23904:
                   23905: # A9. Scale X -> Y.
                   23906: #     The mantissa is scaled to the desired number of significant
                   23907: #     digits.  The excess digits are collected in INEX2. If mul,
                   23908: #     Check d2 for excess 10 exponential value.  If not zero,
                   23909: #     the iscale value would have caused the pwrten calculation
                   23910: #     to overflow.  Only a negative iscale can cause this, so
                   23911: #     multiply by 10^(d2), which is now only allowed to be 24,
                   23912: #     with a multiply by 10^8 and 10^16, which is exact since
                   23913: #     10^24 is exact.  If the input was denormalized, we must
                   23914: #     create a busy stack frame with the mul command and the
                   23915: #     two operands, and allow the fpu to complete the multiply.
                   23916: #
                   23917: # Register usage:
                   23918: #      Input/Output
                   23919: #      d0: FPCR with RZ mode/Unchanged
                   23920: #      d2: 0 or 24/unchanged
                   23921: #      d3: x/x
                   23922: #      d4: LEN/Unchanged
                   23923: #      d5: ICTR:LAMBDA
                   23924: #      d6: ILOG/Unchanged
                   23925: #      d7: k-factor/Unchanged
                   23926: #      a0: ptr for original operand/final result
                   23927: #      a1: ptr to PTENRM array/Unchanged
                   23928: #      a2: x/x
                   23929: #      fp0: float(ILOG)/X adjusted for SCALE (Y)
                   23930: #      fp1: 10^ISCALE/Unchanged
                   23931: #      fp2: x/x
                   23932: #      F_SCR1:x/x
                   23933: #      F_SCR2:Abs(X) with $3fff exponent/Unchanged
                   23934: #      L_SCR1:x/x
                   23935: #      L_SCR2:first word of X packed/Unchanged
                   23936:
                   23937: A9_str:
                   23938:        fmov.x          (%a0),%fp0      # load X from memory
                   23939:        fabs.x          %fp0            # use abs(X)
                   23940:        tst.w           %d5             # LAMBDA is in lower word of d5
                   23941:        bne.b           sc_mul          # if neg (LAMBDA = 1), scale by mul
                   23942:        fdiv.x          %fp1,%fp0       # calculate X / SCALE -> Y to fp0
                   23943:        bra.w           A10_st          # branch to A10
                   23944:
                   23945: sc_mul:
                   23946:        tst.b           BINDEC_FLG(%a6) # check for denorm
                   23947:        beq.w           A9_norm         # if norm, continue with mul
                   23948:
                   23949: # for DENORM, we must calculate:
                   23950: #      fp0 = input_op * 10^ISCALE * 10^24
                   23951: # since the input operand is a DENORM, we can't multiply it directly.
                   23952: # so, we do the multiplication of the exponents and mantissas separately.
                   23953: # in this way, we avoid underflow on intermediate stages of the
                   23954: # multiplication and guarantee a result without exception.
                   23955:        fmovm.x         &0x2,-(%sp)     # save 10^ISCALE to stack
                   23956:
                   23957:        mov.w           (%sp),%d3       # grab exponent
                   23958:        andi.w          &0x7fff,%d3     # clear sign
                   23959:        ori.w           &0x8000,(%a0)   # make DENORM exp negative
                   23960:        add.w           (%a0),%d3       # add DENORM exp to 10^ISCALE exp
                   23961:        subi.w          &0x3fff,%d3     # subtract BIAS
                   23962:        add.w           36(%a1),%d3
                   23963:        subi.w          &0x3fff,%d3     # subtract BIAS
                   23964:        add.w           48(%a1),%d3
                   23965:        subi.w          &0x3fff,%d3     # subtract BIAS
                   23966:
                   23967:        bmi.w           sc_mul_err      # is result is DENORM, punt!!!
                   23968:
                   23969:        andi.w          &0x8000,(%sp)   # keep sign
                   23970:        or.w            %d3,(%sp)       # insert new exponent
                   23971:        andi.w          &0x7fff,(%a0)   # clear sign bit on DENORM again
                   23972:        mov.l           0x8(%a0),-(%sp) # put input op mantissa on stk
                   23973:        mov.l           0x4(%a0),-(%sp)
                   23974:        mov.l           &0x3fff0000,-(%sp) # force exp to zero
                   23975:        fmovm.x         (%sp)+,&0x80    # load normalized DENORM into fp0
                   23976:        fmul.x          (%sp)+,%fp0
                   23977:
                   23978: #      fmul.x  36(%a1),%fp0    # multiply fp0 by 10^8
                   23979: #      fmul.x  48(%a1),%fp0    # multiply fp0 by 10^16
                   23980:        mov.l           36+8(%a1),-(%sp) # get 10^8 mantissa
                   23981:        mov.l           36+4(%a1),-(%sp)
                   23982:        mov.l           &0x3fff0000,-(%sp) # force exp to zero
                   23983:        mov.l           48+8(%a1),-(%sp) # get 10^16 mantissa
                   23984:        mov.l           48+4(%a1),-(%sp)
                   23985:        mov.l           &0x3fff0000,-(%sp)# force exp to zero
                   23986:        fmul.x          (%sp)+,%fp0     # multiply fp0 by 10^8
                   23987:        fmul.x          (%sp)+,%fp0     # multiply fp0 by 10^16
                   23988:        bra.b           A10_st
                   23989:
                   23990: sc_mul_err:
                   23991:        bra.b           sc_mul_err
                   23992:
                   23993: A9_norm:
                   23994:        tst.w           %d2             # test for small exp case
                   23995:        beq.b           A9_con          # if zero, continue as normal
                   23996:        fmul.x          36(%a1),%fp0    # multiply fp0 by 10^8
                   23997:        fmul.x          48(%a1),%fp0    # multiply fp0 by 10^16
                   23998: A9_con:
                   23999:        fmul.x          %fp1,%fp0       # calculate X * SCALE -> Y to fp0
                   24000:
                   24001: # A10. Or in INEX.
                   24002: #      If INEX is set, round error occurred.  This is compensated
                   24003: #      for by 'or-ing' in the INEX2 flag to the lsb of Y.
                   24004: #
                   24005: # Register usage:
                   24006: #      Input/Output
                   24007: #      d0: FPCR with RZ mode/FPSR with INEX2 isolated
                   24008: #      d2: x/x
                   24009: #      d3: x/x
                   24010: #      d4: LEN/Unchanged
                   24011: #      d5: ICTR:LAMBDA
                   24012: #      d6: ILOG/Unchanged
                   24013: #      d7: k-factor/Unchanged
                   24014: #      a0: ptr for original operand/final result
                   24015: #      a1: ptr to PTENxx array/Unchanged
                   24016: #      a2: x/ptr to FP_SCR1(a6)
                   24017: #      fp0: Y/Y with lsb adjusted
                   24018: #      fp1: 10^ISCALE/Unchanged
                   24019: #      fp2: x/x
                   24020:
                   24021: A10_st:
                   24022:        fmov.l          %fpsr,%d0       # get FPSR
                   24023:        fmov.x          %fp0,FP_SCR1(%a6)       # move Y to memory
                   24024:        lea.l           FP_SCR1(%a6),%a2        # load a2 with ptr to FP_SCR1
                   24025:        btst            &9,%d0          # check if INEX2 set
                   24026:        beq.b           A11_st          # if clear, skip rest
                   24027:        or.l            &1,8(%a2)       # or in 1 to lsb of mantissa
                   24028:        fmov.x          FP_SCR1(%a6),%fp0       # write adjusted Y back to fpu
                   24029:
                   24030:
                   24031: # A11. Restore original FPCR; set size ext.
                   24032: #      Perform FINT operation in the user's rounding mode.  Keep
                   24033: #      the size to extended.  The sintdo entry point in the sint
                   24034: #      routine expects the FPCR value to be in USER_FPCR for
                   24035: #      mode and precision.  The original FPCR is saved in L_SCR1.
                   24036:
                   24037: A11_st:
                   24038:        mov.l           USER_FPCR(%a6),L_SCR1(%a6)      # save it for later
                   24039:        and.l           &0x00000030,USER_FPCR(%a6)      # set size to ext,
                   24040: #                                      ;block exceptions
                   24041:
                   24042:
                   24043: # A12. Calculate YINT = FINT(Y) according to user's rounding mode.
                   24044: #      The FPSP routine sintd0 is used.  The output is in fp0.
                   24045: #
                   24046: # Register usage:
                   24047: #      Input/Output
                   24048: #      d0: FPSR with AINEX cleared/FPCR with size set to ext
                   24049: #      d2: x/x/scratch
                   24050: #      d3: x/x
                   24051: #      d4: LEN/Unchanged
                   24052: #      d5: ICTR:LAMBDA/Unchanged
                   24053: #      d6: ILOG/Unchanged
                   24054: #      d7: k-factor/Unchanged
                   24055: #      a0: ptr for original operand/src ptr for sintdo
                   24056: #      a1: ptr to PTENxx array/Unchanged
                   24057: #      a2: ptr to FP_SCR1(a6)/Unchanged
                   24058: #      a6: temp pointer to FP_SCR1(a6) - orig value saved and restored
                   24059: #      fp0: Y/YINT
                   24060: #      fp1: 10^ISCALE/Unchanged
                   24061: #      fp2: x/x
                   24062: #      F_SCR1:x/x
                   24063: #      F_SCR2:Y adjusted for inex/Y with original exponent
                   24064: #      L_SCR1:x/original USER_FPCR
                   24065: #      L_SCR2:first word of X packed/Unchanged
                   24066:
                   24067: A12_st:
                   24068:        movm.l  &0xc0c0,-(%sp)  # save regs used by sintd0       {%d0-%d1/%a0-%a1}
                   24069:        mov.l   L_SCR1(%a6),-(%sp)
                   24070:        mov.l   L_SCR2(%a6),-(%sp)
                   24071:
                   24072:        lea.l           FP_SCR1(%a6),%a0        # a0 is ptr to FP_SCR1(a6)
                   24073:        fmov.x          %fp0,(%a0)      # move Y to memory at FP_SCR1(a6)
                   24074:        tst.l           L_SCR2(%a6)     # test sign of original operand
                   24075:        bge.b           do_fint12               # if pos, use Y
                   24076:        or.l            &0x80000000,(%a0)       # if neg, use -Y
                   24077: do_fint12:
                   24078:        mov.l   USER_FPSR(%a6),-(%sp)
                   24079: #      bsr     sintdo          # sint routine returns int in fp0
                   24080:
                   24081:        fmov.l  USER_FPCR(%a6),%fpcr
                   24082:        fmov.l  &0x0,%fpsr                      # clear the AEXC bits!!!
                   24083: ##     mov.l           USER_FPCR(%a6),%d0      # ext prec/keep rnd mode
                   24084: ##     andi.l          &0x00000030,%d0
                   24085: ##     fmov.l          %d0,%fpcr
                   24086:        fint.x          FP_SCR1(%a6),%fp0       # do fint()
                   24087:        fmov.l  %fpsr,%d0
                   24088:        or.w    %d0,FPSR_EXCEPT(%a6)
                   24089: ##     fmov.l          &0x0,%fpcr
                   24090: ##     fmov.l          %fpsr,%d0               # don't keep ccodes
                   24091: ##     or.w            %d0,FPSR_EXCEPT(%a6)
                   24092:
                   24093:        mov.b   (%sp),USER_FPSR(%a6)
                   24094:        add.l   &4,%sp
                   24095:
                   24096:        mov.l   (%sp)+,L_SCR2(%a6)
                   24097:        mov.l   (%sp)+,L_SCR1(%a6)
                   24098:        movm.l  (%sp)+,&0x303   # restore regs used by sint      {%d0-%d1/%a0-%a1}
                   24099:
                   24100:        mov.l   L_SCR2(%a6),FP_SCR1(%a6)        # restore original exponent
                   24101:        mov.l   L_SCR1(%a6),USER_FPCR(%a6)      # restore user's FPCR
                   24102:
                   24103: # A13. Check for LEN digits.
                   24104: #      If the int operation results in more than LEN digits,
                   24105: #      or less than LEN -1 digits, adjust ILOG and repeat from
                   24106: #      A6.  This test occurs only on the first pass.  If the
                   24107: #      result is exactly 10^LEN, decrement ILOG and divide
                   24108: #      the mantissa by 10.  The calculation of 10^LEN cannot
                   24109: #      be inexact, since all powers of ten upto 10^27 are exact
                   24110: #      in extended precision, so the use of a previous power-of-ten
                   24111: #      table will introduce no error.
                   24112: #
                   24113: #
                   24114: # Register usage:
                   24115: #      Input/Output
                   24116: #      d0: FPCR with size set to ext/scratch final = 0
                   24117: #      d2: x/x
                   24118: #      d3: x/scratch final = x
                   24119: #      d4: LEN/LEN adjusted
                   24120: #      d5: ICTR:LAMBDA/LAMBDA:ICTR
                   24121: #      d6: ILOG/ILOG adjusted
                   24122: #      d7: k-factor/Unchanged
                   24123: #      a0: pointer into memory for packed bcd string formation
                   24124: #      a1: ptr to PTENxx array/Unchanged
                   24125: #      a2: ptr to FP_SCR1(a6)/Unchanged
                   24126: #      fp0: int portion of Y/abs(YINT) adjusted
                   24127: #      fp1: 10^ISCALE/Unchanged
                   24128: #      fp2: x/10^LEN
                   24129: #      F_SCR1:x/x
                   24130: #      F_SCR2:Y with original exponent/Unchanged
                   24131: #      L_SCR1:original USER_FPCR/Unchanged
                   24132: #      L_SCR2:first word of X packed/Unchanged
                   24133:
                   24134: A13_st:
                   24135:        swap            %d5             # put ICTR in lower word of d5
                   24136:        tst.w           %d5             # check if ICTR = 0
                   24137:        bne             not_zr          # if non-zero, go to second test
                   24138: #
                   24139: # Compute 10^(LEN-1)
                   24140: #
                   24141:        fmov.s          FONE(%pc),%fp2  # init fp2 to 1.0
                   24142:        mov.l           %d4,%d0         # put LEN in d0
                   24143:        subq.l          &1,%d0          # d0 = LEN -1
                   24144:        clr.l           %d3             # clr table index
                   24145: l_loop:
                   24146:        lsr.l           &1,%d0          # shift next bit into carry
                   24147:        bcc.b           l_next          # if zero, skip the mul
                   24148:        fmul.x          (%a1,%d3),%fp2  # mul by 10**(d3_bit_no)
                   24149: l_next:
                   24150:        add.l           &12,%d3         # inc d3 to next pwrten table entry
                   24151:        tst.l           %d0             # test if LEN is zero
                   24152:        bne.b           l_loop          # if not, loop
                   24153: #
                   24154: # 10^LEN-1 is computed for this test and A14.  If the input was
                   24155: # denormalized, check only the case in which YINT > 10^LEN.
                   24156: #
                   24157:        tst.b           BINDEC_FLG(%a6) # check if input was norm
                   24158:        beq.b           A13_con         # if norm, continue with checking
                   24159:        fabs.x          %fp0            # take abs of YINT
                   24160:        bra             test_2
                   24161: #
                   24162: # Compare abs(YINT) to 10^(LEN-1) and 10^LEN
                   24163: #
                   24164: A13_con:
                   24165:        fabs.x          %fp0            # take abs of YINT
                   24166:        fcmp.x          %fp0,%fp2       # compare abs(YINT) with 10^(LEN-1)
                   24167:        fbge.w          test_2          # if greater, do next test
                   24168:        subq.l          &1,%d6          # subtract 1 from ILOG
                   24169:        mov.w           &1,%d5          # set ICTR
                   24170:        fmov.l          &rm_mode*0x10,%fpcr     # set rmode to RM
                   24171:        fmul.s          FTEN(%pc),%fp2  # compute 10^LEN
                   24172:        bra.w           A6_str          # return to A6 and recompute YINT
                   24173: test_2:
                   24174:        fmul.s          FTEN(%pc),%fp2  # compute 10^LEN
                   24175:        fcmp.x          %fp0,%fp2       # compare abs(YINT) with 10^LEN
                   24176:        fblt.w          A14_st          # if less, all is ok, go to A14
                   24177:        fbgt.w          fix_ex          # if greater, fix and redo
                   24178:        fdiv.s          FTEN(%pc),%fp0  # if equal, divide by 10
                   24179:        addq.l          &1,%d6          # and inc ILOG
                   24180:        bra.b           A14_st          # and continue elsewhere
                   24181: fix_ex:
                   24182:        addq.l          &1,%d6          # increment ILOG by 1
                   24183:        mov.w           &1,%d5          # set ICTR
                   24184:        fmov.l          &rm_mode*0x10,%fpcr     # set rmode to RM
                   24185:        bra.w           A6_str          # return to A6 and recompute YINT
                   24186: #
                   24187: # Since ICTR <> 0, we have already been through one adjustment,
                   24188: # and shouldn't have another; this is to check if abs(YINT) = 10^LEN
                   24189: # 10^LEN is again computed using whatever table is in a1 since the
                   24190: # value calculated cannot be inexact.
                   24191: #
                   24192: not_zr:
                   24193:        fmov.s          FONE(%pc),%fp2  # init fp2 to 1.0
                   24194:        mov.l           %d4,%d0         # put LEN in d0
                   24195:        clr.l           %d3             # clr table index
                   24196: z_loop:
                   24197:        lsr.l           &1,%d0          # shift next bit into carry
                   24198:        bcc.b           z_next          # if zero, skip the mul
                   24199:        fmul.x          (%a1,%d3),%fp2  # mul by 10**(d3_bit_no)
                   24200: z_next:
                   24201:        add.l           &12,%d3         # inc d3 to next pwrten table entry
                   24202:        tst.l           %d0             # test if LEN is zero
                   24203:        bne.b           z_loop          # if not, loop
                   24204:        fabs.x          %fp0            # get abs(YINT)
                   24205:        fcmp.x          %fp0,%fp2       # check if abs(YINT) = 10^LEN
                   24206:        fbneq.w         A14_st          # if not, skip this
                   24207:        fdiv.s          FTEN(%pc),%fp0  # divide abs(YINT) by 10
                   24208:        addq.l          &1,%d6          # and inc ILOG by 1
                   24209:        addq.l          &1,%d4          # and inc LEN
                   24210:        fmul.s          FTEN(%pc),%fp2  # if LEN++, the get 10^^LEN
                   24211:
                   24212: # A14. Convert the mantissa to bcd.
                   24213: #      The binstr routine is used to convert the LEN digit
                   24214: #      mantissa to bcd in memory.  The input to binstr is
                   24215: #      to be a fraction; i.e. (mantissa)/10^LEN and adjusted
                   24216: #      such that the decimal point is to the left of bit 63.
                   24217: #      The bcd digits are stored in the correct position in
                   24218: #      the final string area in memory.
                   24219: #
                   24220: #
                   24221: # Register usage:
                   24222: #      Input/Output
                   24223: #      d0: x/LEN call to binstr - final is 0
                   24224: #      d1: x/0
                   24225: #      d2: x/ms 32-bits of mant of abs(YINT)
                   24226: #      d3: x/ls 32-bits of mant of abs(YINT)
                   24227: #      d4: LEN/Unchanged
                   24228: #      d5: ICTR:LAMBDA/LAMBDA:ICTR
                   24229: #      d6: ILOG
                   24230: #      d7: k-factor/Unchanged
                   24231: #      a0: pointer into memory for packed bcd string formation
                   24232: #          /ptr to first mantissa byte in result string
                   24233: #      a1: ptr to PTENxx array/Unchanged
                   24234: #      a2: ptr to FP_SCR1(a6)/Unchanged
                   24235: #      fp0: int portion of Y/abs(YINT) adjusted
                   24236: #      fp1: 10^ISCALE/Unchanged
                   24237: #      fp2: 10^LEN/Unchanged
                   24238: #      F_SCR1:x/Work area for final result
                   24239: #      F_SCR2:Y with original exponent/Unchanged
                   24240: #      L_SCR1:original USER_FPCR/Unchanged
                   24241: #      L_SCR2:first word of X packed/Unchanged
                   24242:
                   24243: A14_st:
                   24244:        fmov.l          &rz_mode*0x10,%fpcr     # force rz for conversion
                   24245:        fdiv.x          %fp2,%fp0       # divide abs(YINT) by 10^LEN
                   24246:        lea.l           FP_SCR0(%a6),%a0
                   24247:        fmov.x          %fp0,(%a0)      # move abs(YINT)/10^LEN to memory
                   24248:        mov.l           4(%a0),%d2      # move 2nd word of FP_RES to d2
                   24249:        mov.l           8(%a0),%d3      # move 3rd word of FP_RES to d3
                   24250:        clr.l           4(%a0)          # zero word 2 of FP_RES
                   24251:        clr.l           8(%a0)          # zero word 3 of FP_RES
                   24252:        mov.l           (%a0),%d0       # move exponent to d0
                   24253:        swap            %d0             # put exponent in lower word
                   24254:        beq.b           no_sft          # if zero, don't shift
                   24255:        sub.l           &0x3ffd,%d0     # sub bias less 2 to make fract
                   24256:        tst.l           %d0             # check if > 1
                   24257:        bgt.b           no_sft          # if so, don't shift
                   24258:        neg.l           %d0             # make exp positive
                   24259: m_loop:
                   24260:        lsr.l           &1,%d2          # shift d2:d3 right, add 0s
                   24261:        roxr.l          &1,%d3          # the number of places
                   24262:        dbf.w           %d0,m_loop      # given in d0
                   24263: no_sft:
                   24264:        tst.l           %d2             # check for mantissa of zero
                   24265:        bne.b           no_zr           # if not, go on
                   24266:        tst.l           %d3             # continue zero check
                   24267:        beq.b           zer_m           # if zero, go directly to binstr
                   24268: no_zr:
                   24269:        clr.l           %d1             # put zero in d1 for addx
                   24270:        add.l           &0x00000080,%d3 # inc at bit 7
                   24271:        addx.l          %d1,%d2         # continue inc
                   24272:        and.l           &0xffffff80,%d3 # strip off lsb not used by 882
                   24273: zer_m:
                   24274:        mov.l           %d4,%d0         # put LEN in d0 for binstr call
                   24275:        addq.l          &3,%a0          # a0 points to M16 byte in result
                   24276:        bsr             binstr          # call binstr to convert mant
                   24277:
                   24278:
                   24279: # A15. Convert the exponent to bcd.
                   24280: #      As in A14 above, the exp is converted to bcd and the
                   24281: #      digits are stored in the final string.
                   24282: #
                   24283: #      Digits are stored in L_SCR1(a6) on return from BINDEC as:
                   24284: #
                   24285: #       32               16 15                0
                   24286: #      -----------------------------------------
                   24287: #      |  0 | e3 | e2 | e1 | e4 |  X |  X |  X |
                   24288: #      -----------------------------------------
                   24289: #
                   24290: # And are moved into their proper places in FP_SCR0.  If digit e4
                   24291: # is non-zero, OPERR is signaled.  In all cases, all 4 digits are
                   24292: # written as specified in the 881/882 manual for packed decimal.
                   24293: #
                   24294: # Register usage:
                   24295: #      Input/Output
                   24296: #      d0: x/LEN call to binstr - final is 0
                   24297: #      d1: x/scratch (0);shift count for final exponent packing
                   24298: #      d2: x/ms 32-bits of exp fraction/scratch
                   24299: #      d3: x/ls 32-bits of exp fraction
                   24300: #      d4: LEN/Unchanged
                   24301: #      d5: ICTR:LAMBDA/LAMBDA:ICTR
                   24302: #      d6: ILOG
                   24303: #      d7: k-factor/Unchanged
                   24304: #      a0: ptr to result string/ptr to L_SCR1(a6)
                   24305: #      a1: ptr to PTENxx array/Unchanged
                   24306: #      a2: ptr to FP_SCR1(a6)/Unchanged
                   24307: #      fp0: abs(YINT) adjusted/float(ILOG)
                   24308: #      fp1: 10^ISCALE/Unchanged
                   24309: #      fp2: 10^LEN/Unchanged
                   24310: #      F_SCR1:Work area for final result/BCD result
                   24311: #      F_SCR2:Y with original exponent/ILOG/10^4
                   24312: #      L_SCR1:original USER_FPCR/Exponent digits on return from binstr
                   24313: #      L_SCR2:first word of X packed/Unchanged
                   24314:
                   24315: A15_st:
                   24316:        tst.b           BINDEC_FLG(%a6) # check for denorm
                   24317:        beq.b           not_denorm
                   24318:        ftest.x         %fp0            # test for zero
                   24319:        fbeq.w          den_zero        # if zero, use k-factor or 4933
                   24320:        fmov.l          %d6,%fp0        # float ILOG
                   24321:        fabs.x          %fp0            # get abs of ILOG
                   24322:        bra.b           convrt
                   24323: den_zero:
                   24324:        tst.l           %d7             # check sign of the k-factor
                   24325:        blt.b           use_ilog        # if negative, use ILOG
                   24326:        fmov.s          F4933(%pc),%fp0 # force exponent to 4933
                   24327:        bra.b           convrt          # do it
                   24328: use_ilog:
                   24329:        fmov.l          %d6,%fp0        # float ILOG
                   24330:        fabs.x          %fp0            # get abs of ILOG
                   24331:        bra.b           convrt
                   24332: not_denorm:
                   24333:        ftest.x         %fp0            # test for zero
                   24334:        fbneq.w         not_zero        # if zero, force exponent
                   24335:        fmov.s          FONE(%pc),%fp0  # force exponent to 1
                   24336:        bra.b           convrt          # do it
                   24337: not_zero:
                   24338:        fmov.l          %d6,%fp0        # float ILOG
                   24339:        fabs.x          %fp0            # get abs of ILOG
                   24340: convrt:
                   24341:        fdiv.x          24(%a1),%fp0    # compute ILOG/10^4
                   24342:        fmov.x          %fp0,FP_SCR1(%a6)       # store fp0 in memory
                   24343:        mov.l           4(%a2),%d2      # move word 2 to d2
                   24344:        mov.l           8(%a2),%d3      # move word 3 to d3
                   24345:        mov.w           (%a2),%d0       # move exp to d0
                   24346:        beq.b           x_loop_fin      # if zero, skip the shift
                   24347:        sub.w           &0x3ffd,%d0     # subtract off bias
                   24348:        neg.w           %d0             # make exp positive
                   24349: x_loop:
                   24350:        lsr.l           &1,%d2          # shift d2:d3 right
                   24351:        roxr.l          &1,%d3          # the number of places
                   24352:        dbf.w           %d0,x_loop      # given in d0
                   24353: x_loop_fin:
                   24354:        clr.l           %d1             # put zero in d1 for addx
                   24355:        add.l           &0x00000080,%d3 # inc at bit 6
                   24356:        addx.l          %d1,%d2         # continue inc
                   24357:        and.l           &0xffffff80,%d3 # strip off lsb not used by 882
                   24358:        mov.l           &4,%d0          # put 4 in d0 for binstr call
                   24359:        lea.l           L_SCR1(%a6),%a0 # a0 is ptr to L_SCR1 for exp digits
                   24360:        bsr             binstr          # call binstr to convert exp
                   24361:        mov.l           L_SCR1(%a6),%d0 # load L_SCR1 lword to d0
                   24362:        mov.l           &12,%d1         # use d1 for shift count
                   24363:        lsr.l           %d1,%d0         # shift d0 right by 12
                   24364:        bfins           %d0,FP_SCR0(%a6){&4:&12}        # put e3:e2:e1 in FP_SCR0
                   24365:        lsr.l           %d1,%d0         # shift d0 right by 12
                   24366:        bfins           %d0,FP_SCR0(%a6){&16:&4}        # put e4 in FP_SCR0
                   24367:        tst.b           %d0             # check if e4 is zero
                   24368:        beq.b           A16_st          # if zero, skip rest
                   24369:        or.l            &opaop_mask,USER_FPSR(%a6)      # set OPERR & AIOP in USER_FPSR
                   24370:
                   24371:
                   24372: # A16. Write sign bits to final string.
                   24373: #         Sigma is bit 31 of initial value; RHO is bit 31 of d6 (ILOG).
                   24374: #
                   24375: # Register usage:
                   24376: #      Input/Output
                   24377: #      d0: x/scratch - final is x
                   24378: #      d2: x/x
                   24379: #      d3: x/x
                   24380: #      d4: LEN/Unchanged
                   24381: #      d5: ICTR:LAMBDA/LAMBDA:ICTR
                   24382: #      d6: ILOG/ILOG adjusted
                   24383: #      d7: k-factor/Unchanged
                   24384: #      a0: ptr to L_SCR1(a6)/Unchanged
                   24385: #      a1: ptr to PTENxx array/Unchanged
                   24386: #      a2: ptr to FP_SCR1(a6)/Unchanged
                   24387: #      fp0: float(ILOG)/Unchanged
                   24388: #      fp1: 10^ISCALE/Unchanged
                   24389: #      fp2: 10^LEN/Unchanged
                   24390: #      F_SCR1:BCD result with correct signs
                   24391: #      F_SCR2:ILOG/10^4
                   24392: #      L_SCR1:Exponent digits on return from binstr
                   24393: #      L_SCR2:first word of X packed/Unchanged
                   24394:
                   24395: A16_st:
                   24396:        clr.l           %d0             # clr d0 for collection of signs
                   24397:        and.b           &0x0f,FP_SCR0(%a6)      # clear first nibble of FP_SCR0
                   24398:        tst.l           L_SCR2(%a6)     # check sign of original mantissa
                   24399:        bge.b           mant_p          # if pos, don't set SM
                   24400:        mov.l           &2,%d0          # move 2 in to d0 for SM
                   24401: mant_p:
                   24402:        tst.l           %d6             # check sign of ILOG
                   24403:        bge.b           wr_sgn          # if pos, don't set SE
                   24404:        addq.l          &1,%d0          # set bit 0 in d0 for SE
                   24405: wr_sgn:
                   24406:        bfins           %d0,FP_SCR0(%a6){&0:&2} # insert SM and SE into FP_SCR0
                   24407:
                   24408: # Clean up and restore all registers used.
                   24409:
                   24410:        fmov.l          &0,%fpsr        # clear possible inex2/ainex bits
                   24411:        fmovm.x         (%sp)+,&0xe0    #  {%fp0-%fp2}
                   24412:        movm.l          (%sp)+,&0x4fc   #  {%d2-%d7/%a2}
                   24413:        rts
                   24414:
                   24415:        global          PTENRN
                   24416: PTENRN:
                   24417:        long            0x40020000,0xA0000000,0x00000000        # 10 ^ 1
                   24418:        long            0x40050000,0xC8000000,0x00000000        # 10 ^ 2
                   24419:        long            0x400C0000,0x9C400000,0x00000000        # 10 ^ 4
                   24420:        long            0x40190000,0xBEBC2000,0x00000000        # 10 ^ 8
                   24421:        long            0x40340000,0x8E1BC9BF,0x04000000        # 10 ^ 16
                   24422:        long            0x40690000,0x9DC5ADA8,0x2B70B59E        # 10 ^ 32
                   24423:        long            0x40D30000,0xC2781F49,0xFFCFA6D5        # 10 ^ 64
                   24424:        long            0x41A80000,0x93BA47C9,0x80E98CE0        # 10 ^ 128
                   24425:        long            0x43510000,0xAA7EEBFB,0x9DF9DE8E        # 10 ^ 256
                   24426:        long            0x46A30000,0xE319A0AE,0xA60E91C7        # 10 ^ 512
                   24427:        long            0x4D480000,0xC9767586,0x81750C17        # 10 ^ 1024
                   24428:        long            0x5A920000,0x9E8B3B5D,0xC53D5DE5        # 10 ^ 2048
                   24429:        long            0x75250000,0xC4605202,0x8A20979B        # 10 ^ 4096
                   24430:
                   24431:        global          PTENRP
                   24432: PTENRP:
                   24433:        long            0x40020000,0xA0000000,0x00000000        # 10 ^ 1
                   24434:        long            0x40050000,0xC8000000,0x00000000        # 10 ^ 2
                   24435:        long            0x400C0000,0x9C400000,0x00000000        # 10 ^ 4
                   24436:        long            0x40190000,0xBEBC2000,0x00000000        # 10 ^ 8
                   24437:        long            0x40340000,0x8E1BC9BF,0x04000000        # 10 ^ 16
                   24438:        long            0x40690000,0x9DC5ADA8,0x2B70B59E        # 10 ^ 32
                   24439:        long            0x40D30000,0xC2781F49,0xFFCFA6D6        # 10 ^ 64
                   24440:        long            0x41A80000,0x93BA47C9,0x80E98CE0        # 10 ^ 128
                   24441:        long            0x43510000,0xAA7EEBFB,0x9DF9DE8E        # 10 ^ 256
                   24442:        long            0x46A30000,0xE319A0AE,0xA60E91C7        # 10 ^ 512
                   24443:        long            0x4D480000,0xC9767586,0x81750C18        # 10 ^ 1024
                   24444:        long            0x5A920000,0x9E8B3B5D,0xC53D5DE5        # 10 ^ 2048
                   24445:        long            0x75250000,0xC4605202,0x8A20979B        # 10 ^ 4096
                   24446:
                   24447:        global          PTENRM
                   24448: PTENRM:
                   24449:        long            0x40020000,0xA0000000,0x00000000        # 10 ^ 1
                   24450:        long            0x40050000,0xC8000000,0x00000000        # 10 ^ 2
                   24451:        long            0x400C0000,0x9C400000,0x00000000        # 10 ^ 4
                   24452:        long            0x40190000,0xBEBC2000,0x00000000        # 10 ^ 8
                   24453:        long            0x40340000,0x8E1BC9BF,0x04000000        # 10 ^ 16
                   24454:        long            0x40690000,0x9DC5ADA8,0x2B70B59D        # 10 ^ 32
                   24455:        long            0x40D30000,0xC2781F49,0xFFCFA6D5        # 10 ^ 64
                   24456:        long            0x41A80000,0x93BA47C9,0x80E98CDF        # 10 ^ 128
                   24457:        long            0x43510000,0xAA7EEBFB,0x9DF9DE8D        # 10 ^ 256
                   24458:        long            0x46A30000,0xE319A0AE,0xA60E91C6        # 10 ^ 512
                   24459:        long            0x4D480000,0xC9767586,0x81750C17        # 10 ^ 1024
                   24460:        long            0x5A920000,0x9E8B3B5D,0xC53D5DE4        # 10 ^ 2048
                   24461:        long            0x75250000,0xC4605202,0x8A20979A        # 10 ^ 4096
                   24462:
                   24463: #########################################################################
                   24464: # binstr(): Converts a 64-bit binary integer to bcd.                   #
                   24465: #                                                                      #
                   24466: # INPUT *************************************************************** #
                   24467: #      d2:d3 = 64-bit binary integer                                   #
                   24468: #      d0    = desired length (LEN)                                    #
                   24469: #      a0    = pointer to start in memory for bcd characters           #
                   24470: #              (This pointer must point to byte 4 of the first         #
                   24471: #               lword of the packed decimal memory string.)            #
                   24472: #                                                                      #
                   24473: # OUTPUT ************************************************************** #
                   24474: #      a0 = pointer to LEN bcd digits representing the 64-bit integer. #
                   24475: #                                                                      #
                   24476: # ALGORITHM ***********************************************************        #
                   24477: #      The 64-bit binary is assumed to have a decimal point before     #
                   24478: #      bit 63.  The fraction is multiplied by 10 using a mul by 2      #
                   24479: #      shift and a mul by 8 shift.  The bits shifted out of the        #
                   24480: #      msb form a decimal digit.  This process is iterated until       #
                   24481: #      LEN digits are formed.                                          #
                   24482: #                                                                      #
                   24483: # A1. Init d7 to 1.  D7 is the byte digit counter, and if 1, the       #
                   24484: #     digit formed will be assumed the least significant.  This is     #
                   24485: #     to force the first byte formed to have a 0 in the upper 4 bits.  #
                   24486: #                                                                      #
                   24487: # A2. Beginning of the loop:                                           #
                   24488: #     Copy the fraction in d2:d3 to d4:d5.                             #
                   24489: #                                                                      #
                   24490: # A3. Multiply the fraction in d2:d3 by 8 using bit-field              #
                   24491: #     extracts and shifts.  The three msbs from d2 will go into d1.    #
                   24492: #                                                                      #
                   24493: # A4. Multiply the fraction in d4:d5 by 2 using shifts.  The msb       #
                   24494: #     will be collected by the carry.                                  #
                   24495: #                                                                      #
                   24496: # A5. Add using the carry the 64-bit quantities in d2:d3 and d4:d5     #
                   24497: #     into d2:d3.  D1 will contain the bcd digit formed.               #
                   24498: #                                                                      #
                   24499: # A6. Test d7.  If zero, the digit formed is the ms digit.  If non-    #
                   24500: #     zero, it is the ls digit.  Put the digit in its place in the     #
                   24501: #     upper word of d0.  If it is the ls digit, write the word         #
                   24502: #     from d0 to memory.                                               #
                   24503: #                                                                      #
                   24504: # A7. Decrement d6 (LEN counter) and repeat the loop until zero.       #
                   24505: #                                                                      #
                   24506: #########################################################################
                   24507:
                   24508: #      Implementation Notes:
                   24509: #
                   24510: #      The registers are used as follows:
                   24511: #
                   24512: #              d0: LEN counter
                   24513: #              d1: temp used to form the digit
                   24514: #              d2: upper 32-bits of fraction for mul by 8
                   24515: #              d3: lower 32-bits of fraction for mul by 8
                   24516: #              d4: upper 32-bits of fraction for mul by 2
                   24517: #              d5: lower 32-bits of fraction for mul by 2
                   24518: #              d6: temp for bit-field extracts
                   24519: #              d7: byte digit formation word;digit count {0,1}
                   24520: #              a0: pointer into memory for packed bcd string formation
                   24521: #
                   24522:
                   24523:        global          binstr
                   24524: binstr:
                   24525:        movm.l          &0xff00,-(%sp)  #  {%d0-%d7}
                   24526:
                   24527: #
                   24528: # A1: Init d7
                   24529: #
                   24530:        mov.l           &1,%d7          # init d7 for second digit
                   24531:        subq.l          &1,%d0          # for dbf d0 would have LEN+1 passes
                   24532: #
                   24533: # A2. Copy d2:d3 to d4:d5.  Start loop.
                   24534: #
                   24535: loop:
                   24536:        mov.l           %d2,%d4         # copy the fraction before muls
                   24537:        mov.l           %d3,%d5         # to d4:d5
                   24538: #
                   24539: # A3. Multiply d2:d3 by 8; extract msbs into d1.
                   24540: #
                   24541:        bfextu          %d2{&0:&3},%d1  # copy 3 msbs of d2 into d1
                   24542:        asl.l           &3,%d2          # shift d2 left by 3 places
                   24543:        bfextu          %d3{&0:&3},%d6  # copy 3 msbs of d3 into d6
                   24544:        asl.l           &3,%d3          # shift d3 left by 3 places
                   24545:        or.l            %d6,%d2         # or in msbs from d3 into d2
                   24546: #
                   24547: # A4. Multiply d4:d5 by 2; add carry out to d1.
                   24548: #
                   24549:        asl.l           &1,%d5          # mul d5 by 2
                   24550:        roxl.l          &1,%d4          # mul d4 by 2
                   24551:        swap            %d6             # put 0 in d6 lower word
                   24552:        addx.w          %d6,%d1         # add in extend from mul by 2
                   24553: #
                   24554: # A5. Add mul by 8 to mul by 2.  D1 contains the digit formed.
                   24555: #
                   24556:        add.l           %d5,%d3         # add lower 32 bits
                   24557:        nop                             # ERRATA FIX #13 (Rev. 1.2 6/6/90)
                   24558:        addx.l          %d4,%d2         # add with extend upper 32 bits
                   24559:        nop                             # ERRATA FIX #13 (Rev. 1.2 6/6/90)
                   24560:        addx.w          %d6,%d1         # add in extend from add to d1
                   24561:        swap            %d6             # with d6 = 0; put 0 in upper word
                   24562: #
                   24563: # A6. Test d7 and branch.
                   24564: #
                   24565:        tst.w           %d7             # if zero, store digit & to loop
                   24566:        beq.b           first_d         # if non-zero, form byte & write
                   24567: sec_d:
                   24568:        swap            %d7             # bring first digit to word d7b
                   24569:        asl.w           &4,%d7          # first digit in upper 4 bits d7b
                   24570:        add.w           %d1,%d7         # add in ls digit to d7b
                   24571:        mov.b           %d7,(%a0)+      # store d7b byte in memory
                   24572:        swap            %d7             # put LEN counter in word d7a
                   24573:        clr.w           %d7             # set d7a to signal no digits done
                   24574:        dbf.w           %d0,loop        # do loop some more!
                   24575:        bra.b           end_bstr        # finished, so exit
                   24576: first_d:
                   24577:        swap            %d7             # put digit word in d7b
                   24578:        mov.w           %d1,%d7         # put new digit in d7b
                   24579:        swap            %d7             # put LEN counter in word d7a
                   24580:        addq.w          &1,%d7          # set d7a to signal first digit done
                   24581:        dbf.w           %d0,loop        # do loop some more!
                   24582:        swap            %d7             # put last digit in string
                   24583:        lsl.w           &4,%d7          # move it to upper 4 bits
                   24584:        mov.b           %d7,(%a0)+      # store it in memory string
                   24585: #
                   24586: # Clean up and return with result in fp0.
                   24587: #
                   24588: end_bstr:
                   24589:        movm.l          (%sp)+,&0xff    #  {%d0-%d7}
                   24590:        rts
                   24591:
                   24592: #########################################################################
                   24593: # XDEF ****************************************************************        #
                   24594: #      facc_in_b(): dmem_read_byte failed                              #
                   24595: #      facc_in_w(): dmem_read_word failed                              #
                   24596: #      facc_in_l(): dmem_read_long failed                              #
                   24597: #      facc_in_d(): dmem_read of dbl prec failed                       #
                   24598: #      facc_in_x(): dmem_read of ext prec failed                       #
                   24599: #                                                                      #
                   24600: #      facc_out_b(): dmem_write_byte failed                            #
                   24601: #      facc_out_w(): dmem_write_word failed                            #
                   24602: #      facc_out_l(): dmem_write_long failed                            #
                   24603: #      facc_out_d(): dmem_write of dbl prec failed                     #
                   24604: #      facc_out_x(): dmem_write of ext prec failed                     #
                   24605: #                                                                      #
                   24606: # XREF ****************************************************************        #
                   24607: #      _real_access() - exit through access error handler              #
                   24608: #                                                                      #
                   24609: # INPUT ***************************************************************        #
                   24610: #      None                                                            #
                   24611: #                                                                      #
                   24612: # OUTPUT **************************************************************        #
                   24613: #      None                                                            #
                   24614: #                                                                      #
                   24615: # ALGORITHM ***********************************************************        #
                   24616: #      Flow jumps here when an FP data fetch call gets an error        #
                   24617: # result. This means the operating system wants an access error frame  #
                   24618: # made out of the current exception stack frame.                       #
                   24619: #      So, we first call restore() which makes sure that any updated   #
                   24620: # -(an)+ register gets returned to its pre-exception value and then    #
                   24621: # we change the stack to an access error stack frame.                  #
                   24622: #                                                                      #
                   24623: #########################################################################
                   24624:
                   24625: facc_in_b:
                   24626:        movq.l          &0x1,%d0                        # one byte
                   24627:        bsr.w           restore                         # fix An
                   24628:
                   24629:        mov.w           &0x0121,EXC_VOFF(%a6)           # set FSLW
                   24630:        bra.w           facc_finish
                   24631:
                   24632: facc_in_w:
                   24633:        movq.l          &0x2,%d0                        # two bytes
                   24634:        bsr.w           restore                         # fix An
                   24635:
                   24636:        mov.w           &0x0141,EXC_VOFF(%a6)           # set FSLW
                   24637:        bra.b           facc_finish
                   24638:
                   24639: facc_in_l:
                   24640:        movq.l          &0x4,%d0                        # four bytes
                   24641:        bsr.w           restore                         # fix An
                   24642:
                   24643:        mov.w           &0x0101,EXC_VOFF(%a6)           # set FSLW
                   24644:        bra.b           facc_finish
                   24645:
                   24646: facc_in_d:
                   24647:        movq.l          &0x8,%d0                        # eight bytes
                   24648:        bsr.w           restore                         # fix An
                   24649:
                   24650:        mov.w           &0x0161,EXC_VOFF(%a6)           # set FSLW
                   24651:        bra.b           facc_finish
                   24652:
                   24653: facc_in_x:
                   24654:        movq.l          &0xc,%d0                        # twelve bytes
                   24655:        bsr.w           restore                         # fix An
                   24656:
                   24657:        mov.w           &0x0161,EXC_VOFF(%a6)           # set FSLW
                   24658:        bra.b           facc_finish
                   24659:
                   24660: ################################################################
                   24661:
                   24662: facc_out_b:
                   24663:        movq.l          &0x1,%d0                        # one byte
                   24664:        bsr.w           restore                         # restore An
                   24665:
                   24666:        mov.w           &0x00a1,EXC_VOFF(%a6)           # set FSLW
                   24667:        bra.b           facc_finish
                   24668:
                   24669: facc_out_w:
                   24670:        movq.l          &0x2,%d0                        # two bytes
                   24671:        bsr.w           restore                         # restore An
                   24672:
                   24673:        mov.w           &0x00c1,EXC_VOFF(%a6)           # set FSLW
                   24674:        bra.b           facc_finish
                   24675:
                   24676: facc_out_l:
                   24677:        movq.l          &0x4,%d0                        # four bytes
                   24678:        bsr.w           restore                         # restore An
                   24679:
                   24680:        mov.w           &0x0081,EXC_VOFF(%a6)           # set FSLW
                   24681:        bra.b           facc_finish
                   24682:
                   24683: facc_out_d:
                   24684:        movq.l          &0x8,%d0                        # eight bytes
                   24685:        bsr.w           restore                         # restore An
                   24686:
                   24687:        mov.w           &0x00e1,EXC_VOFF(%a6)           # set FSLW
                   24688:        bra.b           facc_finish
                   24689:
                   24690: facc_out_x:
                   24691:        mov.l           &0xc,%d0                        # twelve bytes
                   24692:        bsr.w           restore                         # restore An
                   24693:
                   24694:        mov.w           &0x00e1,EXC_VOFF(%a6)           # set FSLW
                   24695:
                   24696: # here's where we actually create the access error frame from the
                   24697: # current exception stack frame.
                   24698: facc_finish:
                   24699:        mov.l           USER_FPIAR(%a6),EXC_PC(%a6) # store current PC
                   24700:
                   24701:        fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0-fp1
                   24702:        fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
                   24703:        movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
                   24704:
                   24705:        unlk            %a6
                   24706:
                   24707:        mov.l           (%sp),-(%sp)            # store SR, hi(PC)
                   24708:        mov.l           0x8(%sp),0x4(%sp)       # store lo(PC)
                   24709:        mov.l           0xc(%sp),0x8(%sp)       # store EA
                   24710:        mov.l           &0x00000001,0xc(%sp)    # store FSLW
                   24711:        mov.w           0x6(%sp),0xc(%sp)       # fix FSLW (size)
                   24712:        mov.w           &0x4008,0x6(%sp)        # store voff
                   24713:
                   24714:        btst            &0x5,(%sp)              # supervisor or user mode?
                   24715:        beq.b           facc_out2               # user
                   24716:        bset            &0x2,0xd(%sp)           # set supervisor TM bit
                   24717:
                   24718: facc_out2:
                   24719:        bra.l           _real_access
                   24720:
                   24721: ##################################################################
                   24722:
                   24723: # if the effective addressing mode was predecrement or postincrement,
                   24724: # the emulation has already changed its value to the correct post-
                   24725: # instruction value. but since we're exiting to the access error
                   24726: # handler, then AN must be returned to its pre-instruction value.
                   24727: # we do that here.
                   24728: restore:
                   24729:        mov.b           EXC_OPWORD+0x1(%a6),%d1
                   24730:        andi.b          &0x38,%d1               # extract opmode
                   24731:        cmpi.b          %d1,&0x18               # postinc?
                   24732:        beq.w           rest_inc
                   24733:        cmpi.b          %d1,&0x20               # predec?
                   24734:        beq.w           rest_dec
                   24735:        rts
                   24736:
                   24737: rest_inc:
                   24738:        mov.b           EXC_OPWORD+0x1(%a6),%d1
                   24739:        andi.w          &0x0007,%d1             # fetch An
                   24740:
                   24741:        mov.w           (tbl_rest_inc.b,%pc,%d1.w*2),%d1
                   24742:        jmp             (tbl_rest_inc.b,%pc,%d1.w*1)
                   24743:
                   24744: tbl_rest_inc:
                   24745:        short           ri_a0 - tbl_rest_inc
                   24746:        short           ri_a1 - tbl_rest_inc
                   24747:        short           ri_a2 - tbl_rest_inc
                   24748:        short           ri_a3 - tbl_rest_inc
                   24749:        short           ri_a4 - tbl_rest_inc
                   24750:        short           ri_a5 - tbl_rest_inc
                   24751:        short           ri_a6 - tbl_rest_inc
                   24752:        short           ri_a7 - tbl_rest_inc
                   24753:
                   24754: ri_a0:
                   24755:        sub.l           %d0,EXC_DREGS+0x8(%a6)  # fix stacked a0
                   24756:        rts
                   24757: ri_a1:
                   24758:        sub.l           %d0,EXC_DREGS+0xc(%a6)  # fix stacked a1
                   24759:        rts
                   24760: ri_a2:
                   24761:        sub.l           %d0,%a2                 # fix a2
                   24762:        rts
                   24763: ri_a3:
                   24764:        sub.l           %d0,%a3                 # fix a3
                   24765:        rts
                   24766: ri_a4:
                   24767:        sub.l           %d0,%a4                 # fix a4
                   24768:        rts
                   24769: ri_a5:
                   24770:        sub.l           %d0,%a5                 # fix a5
                   24771:        rts
                   24772: ri_a6:
                   24773:        sub.l           %d0,(%a6)               # fix stacked a6
                   24774:        rts
                   24775: # if it's a fmove out instruction, we don't have to fix a7
                   24776: # because we hadn't changed it yet. if it's an opclass two
                   24777: # instruction (data moved in) and the exception was in supervisor
                   24778: # mode, then also also wasn't updated. if it was user mode, then
                   24779: # restore the correct a7 which is in the USP currently.
                   24780: ri_a7:
                   24781:        cmpi.b          EXC_VOFF(%a6),&0x30     # move in or out?
                   24782:        bne.b           ri_a7_done              # out
                   24783:
                   24784:        btst            &0x5,EXC_SR(%a6)        # user or supervisor?
                   24785:        bne.b           ri_a7_done              # supervisor
                   24786:        movc            %usp,%a0                # restore USP
                   24787:        sub.l           %d0,%a0
                   24788:        movc            %a0,%usp
                   24789: ri_a7_done:
                   24790:        rts
                   24791:
                   24792: # need to invert adjustment value if the <ea> was predec
                   24793: rest_dec:
                   24794:        neg.l           %d0
                   24795:        bra.b           rest_inc

CVSweb