Home | History | Annotate | Line # | Download | only in dist
      1  1.1        is #
      2  1.4  christos # $NetBSD: pfpsp.s,v 1.4 2005/12/11 12:17:52 christos Exp $
      3  1.1        is #
      4  1.1        is 
      5  1.1        is #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      6  1.1        is # MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
      7  1.1        is # M68000 Hi-Performance Microprocessor Division
      8  1.1        is # M68060 Software Package Production Release
      9  1.1        is #
     10  1.1        is # M68060 Software Package Copyright (C) 1993, 1994, 1995, 1996 Motorola Inc.
     11  1.1        is # All rights reserved.
     12  1.1        is #
     13  1.1        is # THE SOFTWARE is provided on an "AS IS" basis and without warranty.
     14  1.1        is # To the maximum extent permitted by applicable law,
     15  1.1        is # MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
     16  1.1        is # INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS
     17  1.1        is # FOR A PARTICULAR PURPOSE and any warranty against infringement with
     18  1.1        is # regard to the SOFTWARE (INCLUDING ANY MODIFIED VERSIONS THEREOF)
     19  1.1        is # and any accompanying written materials.
     20  1.1        is #
     21  1.1        is # To the maximum extent permitted by applicable law,
     22  1.1        is # IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
     23  1.1        is # (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS,
     24  1.1        is # BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS)
     25  1.1        is # ARISING OF THE USE OR INABILITY TO USE THE SOFTWARE.
     26  1.1        is #
     27  1.1        is # Motorola assumes no responsibility for the maintenance and support
     28  1.1        is # of the SOFTWARE.
     29  1.1        is #
     30  1.1        is # You are hereby granted a copyright license to use, modify, and distribute the
     31  1.1        is # SOFTWARE so long as this entire notice is retained without alteration
     32  1.1        is # in any modified and/or redistributed versions, and that such modified
     33  1.1        is # versions are clearly identified as such.
     34  1.1        is # No licenses are granted by implication, estoppel or otherwise under any
     35  1.1        is # patents or trademarks of Motorola, Inc.
     36  1.1        is #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     37  1.1        is 
     38  1.1        is #
     39  1.1        is # freal.s:
     40  1.1        is #	This file is appended to the top of the 060FPSP package
     41  1.1        is # and contains the entry points into the package. The user, in
     42  1.1        is # effect, branches to one of the branch table entries located
     43  1.1        is # after _060FPSP_TABLE.
     44  1.1        is #	Also, subroutine stubs exist in this file (_fpsp_done for
     45  1.1        is # example) that are referenced by the FPSP package itself in order
     46  1.1        is # to call a given routine. The stub routine actually performs the
     47  1.1        is # callout. The FPSP code does a "bsr" to the stub routine. This
     48  1.1        is # extra layer of hierarchy adds a slight performance penalty but
     49  1.1        is # it makes the FPSP code easier to read and more mainatinable.
     50  1.1        is #
     51  1.1        is 
     52  1.1        is set	_off_bsun,	0x00
     53  1.1        is set	_off_snan,	0x04
     54  1.1        is set	_off_operr,	0x08
     55  1.1        is set	_off_ovfl,	0x0c
     56  1.1        is set	_off_unfl,	0x10
     57  1.1        is set	_off_dz,	0x14
     58  1.1        is set	_off_inex,	0x18
     59  1.1        is set	_off_fline,	0x1c
     60  1.1        is set	_off_fpu_dis,	0x20
     61  1.1        is set	_off_trap,	0x24
     62  1.1        is set	_off_trace,	0x28
     63  1.1        is set	_off_access,	0x2c
     64  1.1        is set	_off_done,	0x30
     65  1.1        is 
     66  1.1        is set	_off_imr,	0x40
     67  1.1        is set	_off_dmr,	0x44
     68  1.1        is set	_off_dmw,	0x48
     69  1.1        is set	_off_irw,	0x4c
     70  1.1        is set	_off_irl,	0x50
     71  1.1        is set	_off_drb,	0x54
     72  1.1        is set	_off_drw,	0x58
     73  1.1        is set	_off_drl,	0x5c
     74  1.1        is set	_off_dwb,	0x60
     75  1.1        is set	_off_dww,	0x64
     76  1.1        is set	_off_dwl,	0x68
     77  1.1        is 
     78  1.1        is _060FPSP_TABLE:
     79  1.1        is 
     80  1.1        is ###############################################################
     81  1.1        is 
     82  1.1        is # Here's the table of ENTRY POINTS for those linking the package.
     83  1.1        is 	bra.l		_fpsp_snan
     84  1.1        is 	short		0x0000
     85  1.1        is 	bra.l		_fpsp_operr
     86  1.1        is 	short		0x0000
     87  1.1        is 	bra.l		_fpsp_ovfl
     88  1.1        is 	short		0x0000
     89  1.1        is 	bra.l		_fpsp_unfl
     90  1.1        is 	short		0x0000
     91  1.1        is 	bra.l		_fpsp_dz
     92  1.1        is 	short		0x0000
     93  1.1        is 	bra.l		_fpsp_inex
     94  1.1        is 	short		0x0000
     95  1.1        is 	bra.l		_fpsp_fline
     96  1.1        is 	short		0x0000
     97  1.1        is 	bra.l		_fpsp_unsupp
     98  1.1        is 	short		0x0000
     99  1.1        is 	bra.l		_fpsp_effadd
    100  1.1        is 	short		0x0000
    101  1.1        is 
    102  1.1        is 	space 		56
    103  1.1        is 
    104  1.1        is ###############################################################
    105  1.1        is 	global		_fpsp_done
    106  1.1        is _fpsp_done:
    107  1.1        is 	mov.l		%d0,-(%sp)
    108  1.1        is 	mov.l		(_060FPSP_TABLE-0x80+_off_done,%pc),%d0
    109  1.1        is 	pea.l		(_060FPSP_TABLE-0x80,%pc,%d0)
    110  1.1        is 	mov.l		0x4(%sp),%d0
    111  1.1        is 	rtd		&0x4
    112  1.1        is 
    113  1.1        is 	global		_real_ovfl
    114  1.1        is _real_ovfl:
    115  1.1        is 	mov.l		%d0,-(%sp)
    116  1.1        is 	mov.l		(_060FPSP_TABLE-0x80+_off_ovfl,%pc),%d0
    117  1.1        is 	pea.l		(_060FPSP_TABLE-0x80,%pc,%d0)
    118  1.1        is 	mov.l		0x4(%sp),%d0
    119  1.1        is 	rtd		&0x4
    120  1.1        is 
    121  1.1        is 	global		_real_unfl
    122  1.1        is _real_unfl:
    123  1.1        is 	mov.l		%d0,-(%sp)
    124  1.1        is 	mov.l		(_060FPSP_TABLE-0x80+_off_unfl,%pc),%d0
    125  1.1        is 	pea.l		(_060FPSP_TABLE-0x80,%pc,%d0)
    126  1.1        is 	mov.l		0x4(%sp),%d0
    127  1.1        is 	rtd		&0x4
    128  1.1        is 
    129  1.1        is 	global		_real_inex
    130  1.1        is _real_inex:
    131  1.1        is 	mov.l		%d0,-(%sp)
    132  1.1        is 	mov.l		(_060FPSP_TABLE-0x80+_off_inex,%pc),%d0
    133  1.1        is 	pea.l		(_060FPSP_TABLE-0x80,%pc,%d0)
    134  1.1        is 	mov.l		0x4(%sp),%d0
    135  1.1        is 	rtd		&0x4
    136  1.1        is 
    137  1.1        is 	global		_real_bsun
    138  1.1        is _real_bsun:
    139  1.1        is 	mov.l		%d0,-(%sp)
    140  1.1        is 	mov.l		(_060FPSP_TABLE-0x80+_off_bsun,%pc),%d0
    141  1.1        is 	pea.l		(_060FPSP_TABLE-0x80,%pc,%d0)
    142  1.1        is 	mov.l		0x4(%sp),%d0
    143  1.1        is 	rtd		&0x4
    144  1.1        is 
    145  1.1        is 	global		_real_operr
    146  1.1        is _real_operr:
    147  1.1        is 	mov.l		%d0,-(%sp)
    148  1.1        is 	mov.l		(_060FPSP_TABLE-0x80+_off_operr,%pc),%d0
    149  1.1        is 	pea.l		(_060FPSP_TABLE-0x80,%pc,%d0)
    150  1.1        is 	mov.l		0x4(%sp),%d0
    151  1.1        is 	rtd		&0x4
    152  1.1        is 
    153  1.1        is 	global		_real_snan
    154  1.1        is _real_snan:
    155  1.1        is 	mov.l		%d0,-(%sp)
    156  1.1        is 	mov.l		(_060FPSP_TABLE-0x80+_off_snan,%pc),%d0
    157  1.1        is 	pea.l		(_060FPSP_TABLE-0x80,%pc,%d0)
    158  1.1        is 	mov.l		0x4(%sp),%d0
    159  1.1        is 	rtd		&0x4
    160  1.1        is 
    161  1.1        is 	global		_real_dz
    162  1.1        is _real_dz:
    163  1.1        is 	mov.l		%d0,-(%sp)
    164  1.1        is 	mov.l		(_060FPSP_TABLE-0x80+_off_dz,%pc),%d0
    165  1.1        is 	pea.l		(_060FPSP_TABLE-0x80,%pc,%d0)
    166  1.1        is 	mov.l		0x4(%sp),%d0
    167  1.1        is 	rtd		&0x4
    168  1.1        is 
    169  1.1        is 	global		_real_fline
    170  1.1        is _real_fline:
    171  1.1        is 	mov.l		%d0,-(%sp)
    172  1.1        is 	mov.l		(_060FPSP_TABLE-0x80+_off_fline,%pc),%d0
    173  1.1        is 	pea.l		(_060FPSP_TABLE-0x80,%pc,%d0)
    174  1.1        is 	mov.l		0x4(%sp),%d0
    175  1.1        is 	rtd		&0x4
    176  1.1        is 
    177  1.1        is 	global		_real_fpu_disabled
    178  1.1        is _real_fpu_disabled:
    179  1.1        is 	mov.l		%d0,-(%sp)
    180  1.1        is 	mov.l		(_060FPSP_TABLE-0x80+_off_fpu_dis,%pc),%d0
    181  1.1        is 	pea.l		(_060FPSP_TABLE-0x80,%pc,%d0)
    182  1.1        is 	mov.l		0x4(%sp),%d0
    183  1.1        is 	rtd		&0x4
    184  1.1        is 
    185  1.1        is 	global		_real_trap
    186  1.1        is _real_trap:
    187  1.1        is 	mov.l		%d0,-(%sp)
    188  1.1        is 	mov.l		(_060FPSP_TABLE-0x80+_off_trap,%pc),%d0
    189  1.1        is 	pea.l		(_060FPSP_TABLE-0x80,%pc,%d0)
    190  1.1        is 	mov.l		0x4(%sp),%d0
    191  1.1        is 	rtd		&0x4
    192  1.1        is 
    193  1.1        is 	global		_real_trace
    194  1.1        is _real_trace:
    195  1.1        is 	mov.l		%d0,-(%sp)
    196  1.1        is 	mov.l		(_060FPSP_TABLE-0x80+_off_trace,%pc),%d0
    197  1.1        is 	pea.l		(_060FPSP_TABLE-0x80,%pc,%d0)
    198  1.1        is 	mov.l		0x4(%sp),%d0
    199  1.1        is 	rtd		&0x4
    200  1.1        is 
    201  1.1        is 	global		_real_access
    202  1.1        is _real_access:
    203  1.1        is 	mov.l		%d0,-(%sp)
    204  1.1        is 	mov.l		(_060FPSP_TABLE-0x80+_off_access,%pc),%d0
    205  1.1        is 	pea.l		(_060FPSP_TABLE-0x80,%pc,%d0)
    206  1.1        is 	mov.l		0x4(%sp),%d0
    207  1.1        is 	rtd		&0x4
    208  1.1        is 
    209  1.1        is #######################################
    210  1.1        is 
    211  1.1        is 	global		_imem_read
    212  1.1        is _imem_read:
    213  1.1        is 	mov.l		%d0,-(%sp)
    214  1.1        is 	mov.l		(_060FPSP_TABLE-0x80+_off_imr,%pc),%d0
    215  1.1        is 	pea.l		(_060FPSP_TABLE-0x80,%pc,%d0)
    216  1.1        is 	mov.l		0x4(%sp),%d0
    217  1.1        is 	rtd		&0x4
    218  1.1        is 
    219  1.1        is 	global		_dmem_read
    220  1.1        is _dmem_read:
    221  1.1        is 	mov.l		%d0,-(%sp)
    222  1.1        is 	mov.l		(_060FPSP_TABLE-0x80+_off_dmr,%pc),%d0
    223  1.1        is 	pea.l		(_060FPSP_TABLE-0x80,%pc,%d0)
    224  1.1        is 	mov.l		0x4(%sp),%d0
    225  1.1        is 	rtd		&0x4
    226  1.1        is 
    227  1.1        is 	global		_dmem_write
    228  1.1        is _dmem_write:
    229  1.1        is 	mov.l		%d0,-(%sp)
    230  1.1        is 	mov.l		(_060FPSP_TABLE-0x80+_off_dmw,%pc),%d0
    231  1.1        is 	pea.l		(_060FPSP_TABLE-0x80,%pc,%d0)
    232  1.1        is 	mov.l		0x4(%sp),%d0
    233  1.1        is 	rtd		&0x4
    234  1.1        is 
    235  1.1        is 	global		_imem_read_word
    236  1.1        is _imem_read_word:
    237  1.1        is 	mov.l		%d0,-(%sp)
    238  1.1        is 	mov.l		(_060FPSP_TABLE-0x80+_off_irw,%pc),%d0
    239  1.1        is 	pea.l		(_060FPSP_TABLE-0x80,%pc,%d0)
    240  1.1        is 	mov.l		0x4(%sp),%d0
    241  1.1        is 	rtd		&0x4
    242  1.1        is 
    243  1.1        is 	global		_imem_read_long
    244  1.1        is _imem_read_long:
    245  1.1        is 	mov.l		%d0,-(%sp)
    246  1.1        is 	mov.l		(_060FPSP_TABLE-0x80+_off_irl,%pc),%d0
    247  1.1        is 	pea.l		(_060FPSP_TABLE-0x80,%pc,%d0)
    248  1.1        is 	mov.l		0x4(%sp),%d0
    249  1.1        is 	rtd		&0x4
    250  1.1        is 
    251  1.1        is 	global		_dmem_read_byte
    252  1.1        is _dmem_read_byte:
    253  1.1        is 	mov.l		%d0,-(%sp)
    254  1.1        is 	mov.l		(_060FPSP_TABLE-0x80+_off_drb,%pc),%d0
    255  1.1        is 	pea.l		(_060FPSP_TABLE-0x80,%pc,%d0)
    256  1.1        is 	mov.l		0x4(%sp),%d0
    257  1.1        is 	rtd		&0x4
    258  1.1        is 
    259  1.1        is 	global		_dmem_read_word
    260  1.1        is _dmem_read_word:
    261  1.1        is 	mov.l		%d0,-(%sp)
    262  1.1        is 	mov.l		(_060FPSP_TABLE-0x80+_off_drw,%pc),%d0
    263  1.1        is 	pea.l		(_060FPSP_TABLE-0x80,%pc,%d0)
    264  1.1        is 	mov.l		0x4(%sp),%d0
    265  1.1        is 	rtd		&0x4
    266  1.1        is 
    267  1.1        is 	global		_dmem_read_long
    268  1.1        is _dmem_read_long:
    269  1.1        is 	mov.l		%d0,-(%sp)
    270  1.1        is 	mov.l		(_060FPSP_TABLE-0x80+_off_drl,%pc),%d0
    271  1.1        is 	pea.l		(_060FPSP_TABLE-0x80,%pc,%d0)
    272  1.1        is 	mov.l		0x4(%sp),%d0
    273  1.1        is 	rtd		&0x4
    274  1.1        is 
    275  1.1        is 	global		_dmem_write_byte
    276  1.1        is _dmem_write_byte:
    277  1.1        is 	mov.l		%d0,-(%sp)
    278  1.1        is 	mov.l		(_060FPSP_TABLE-0x80+_off_dwb,%pc),%d0
    279  1.1        is 	pea.l		(_060FPSP_TABLE-0x80,%pc,%d0)
    280  1.1        is 	mov.l		0x4(%sp),%d0
    281  1.1        is 	rtd		&0x4
    282  1.1        is 
    283  1.1        is 	global		_dmem_write_word
    284  1.1        is _dmem_write_word:
    285  1.1        is 	mov.l		%d0,-(%sp)
    286  1.1        is 	mov.l		(_060FPSP_TABLE-0x80+_off_dww,%pc),%d0
    287  1.1        is 	pea.l		(_060FPSP_TABLE-0x80,%pc,%d0)
    288  1.1        is 	mov.l		0x4(%sp),%d0
    289  1.1        is 	rtd		&0x4
    290  1.1        is 
    291  1.1        is 	global		_dmem_write_long
    292  1.1        is _dmem_write_long:
    293  1.1        is 	mov.l		%d0,-(%sp)
    294  1.1        is 	mov.l		(_060FPSP_TABLE-0x80+_off_dwl,%pc),%d0
    295  1.1        is 	pea.l		(_060FPSP_TABLE-0x80,%pc,%d0)
    296  1.1        is 	mov.l		0x4(%sp),%d0
    297  1.1        is 	rtd		&0x4
    298  1.1        is 
    299  1.1        is #
    300  1.1        is # This file contains a set of define statements for constants
    301  1.1        is # in order to promote readability within the corecode itself.
    302  1.1        is #
    303  1.1        is 
    304  1.1        is set LOCAL_SIZE,		192			# stack frame size(bytes)
    305  1.1        is set LV,			-LOCAL_SIZE		# stack offset
    306  1.1        is 
    307  1.1        is set EXC_SR,		0x4			# stack status register
    308  1.1        is set EXC_PC,		0x6			# stack pc
    309  1.1        is set EXC_VOFF,		0xa			# stacked vector offset
    310  1.1        is set EXC_EA,		0xc			# stacked <ea>
    311  1.1        is 
    312  1.1        is set EXC_FP,		0x0			# frame pointer
    313  1.1        is 
    314  1.1        is set EXC_AREGS,		-68			# offset of all address regs
    315  1.1        is set EXC_DREGS,		-100			# offset of all data regs
    316  1.1        is set EXC_FPREGS,		-36			# offset of all fp regs
    317  1.1        is 
    318  1.1        is set EXC_A7,		EXC_AREGS+(7*4)		# offset of saved a7
    319  1.1        is set OLD_A7,		EXC_AREGS+(6*4)		# extra copy of saved a7
    320  1.1        is set EXC_A6,		EXC_AREGS+(6*4)		# offset of saved a6
    321  1.1        is set EXC_A5,		EXC_AREGS+(5*4)
    322  1.1        is set EXC_A4,		EXC_AREGS+(4*4)
    323  1.1        is set EXC_A3,		EXC_AREGS+(3*4)
    324  1.1        is set EXC_A2,		EXC_AREGS+(2*4)
    325  1.1        is set EXC_A1,		EXC_AREGS+(1*4)
    326  1.1        is set EXC_A0,		EXC_AREGS+(0*4)
    327  1.1        is set EXC_D7,		EXC_DREGS+(7*4)
    328  1.1        is set EXC_D6,		EXC_DREGS+(6*4)
    329  1.1        is set EXC_D5,		EXC_DREGS+(5*4)
    330  1.1        is set EXC_D4,		EXC_DREGS+(4*4)
    331  1.1        is set EXC_D3,		EXC_DREGS+(3*4)
    332  1.1        is set EXC_D2,		EXC_DREGS+(2*4)
    333  1.1        is set EXC_D1,		EXC_DREGS+(1*4)
    334  1.1        is set EXC_D0,		EXC_DREGS+(0*4)
    335  1.1        is 
    336  1.1        is set EXC_FP0, 		EXC_FPREGS+(0*12)	# offset of saved fp0
    337  1.1        is set EXC_FP1, 		EXC_FPREGS+(1*12)	# offset of saved fp1
    338  1.1        is set EXC_FP2, 		EXC_FPREGS+(2*12)	# offset of saved fp2 (not used)
    339  1.1        is 
    340  1.1        is set FP_SCR1, 		LV+80			# fp scratch 1
    341  1.1        is set FP_SCR1_EX, 	FP_SCR1+0
    342  1.1        is set FP_SCR1_SGN,	FP_SCR1+2
    343  1.1        is set FP_SCR1_HI, 	FP_SCR1+4
    344  1.1        is set FP_SCR1_LO, 	FP_SCR1+8
    345  1.1        is 
    346  1.1        is set FP_SCR0, 		LV+68			# fp scratch 0
    347  1.1        is set FP_SCR0_EX, 	FP_SCR0+0
    348  1.1        is set FP_SCR0_SGN,	FP_SCR0+2
    349  1.1        is set FP_SCR0_HI, 	FP_SCR0+4
    350  1.1        is set FP_SCR0_LO, 	FP_SCR0+8
    351  1.1        is 
    352  1.1        is set FP_DST, 		LV+56			# fp destination operand
    353  1.1        is set FP_DST_EX, 		FP_DST+0
    354  1.1        is set FP_DST_SGN,		FP_DST+2
    355  1.1        is set FP_DST_HI, 		FP_DST+4
    356  1.1        is set FP_DST_LO, 		FP_DST+8
    357  1.1        is 
    358  1.1        is set FP_SRC, 		LV+44			# fp source operand
    359  1.1        is set FP_SRC_EX, 		FP_SRC+0
    360  1.1        is set FP_SRC_SGN,		FP_SRC+2
    361  1.1        is set FP_SRC_HI, 		FP_SRC+4
    362  1.1        is set FP_SRC_LO, 		FP_SRC+8
    363  1.1        is 
    364  1.1        is set USER_FPIAR,		LV+40			# FP instr address register
    365  1.1        is 
    366  1.1        is set USER_FPSR,		LV+36			# FP status register
    367  1.1        is set FPSR_CC,		USER_FPSR+0		# FPSR condition codes
    368  1.1        is set FPSR_QBYTE,		USER_FPSR+1		# FPSR qoutient byte
    369  1.1        is set FPSR_EXCEPT,	USER_FPSR+2		# FPSR exception status byte
    370  1.1        is set FPSR_AEXCEPT,	USER_FPSR+3		# FPSR accrued exception byte
    371  1.1        is 
    372  1.1        is set USER_FPCR,		LV+32			# FP control register
    373  1.1        is set FPCR_ENABLE,	USER_FPCR+2		# FPCR exception enable
    374  1.1        is set FPCR_MODE,		USER_FPCR+3		# FPCR rounding mode control
    375  1.1        is 
    376  1.1        is set L_SCR3,		LV+28			# integer scratch 3
    377  1.1        is set L_SCR2,		LV+24			# integer scratch 2
    378  1.1        is set L_SCR1,		LV+20			# integer scratch 1
    379  1.1        is 
    380  1.1        is set STORE_FLG,		LV+19			# flag: operand store (ie. not fcmp/ftst)
    381  1.1        is 
    382  1.1        is set EXC_TEMP2,		LV+24			# temporary space
    383  1.1        is set EXC_TEMP,		LV+16			# temporary space
    384  1.1        is 
    385  1.1        is set DTAG,		LV+15			# destination operand type
    386  1.1        is set STAG, 		LV+14			# source operand type
    387  1.1        is 
    388  1.1        is set SPCOND_FLG,		LV+10			# flag: special case (see below)
    389  1.1        is 
    390  1.1        is set EXC_CC,		LV+8			# saved condition codes
    391  1.1        is set EXC_EXTWPTR,	LV+4			# saved current PC (active)
    392  1.1        is set EXC_EXTWORD,	LV+2			# saved extension word
    393  1.1        is set EXC_CMDREG,		LV+2			# saved extension word
    394  1.1        is set EXC_OPWORD,		LV+0			# saved operation word
    395  1.1        is 
    396  1.1        is ################################
    397  1.1        is 
    398  1.1        is # Helpful macros
    399  1.1        is 
    400  1.1        is set FTEMP,		0			# offsets within an
    401  1.1        is set FTEMP_EX, 		0			# extended precision
    402  1.1        is set FTEMP_SGN,		2			# value saved in memory.
    403  1.1        is set FTEMP_HI, 		4
    404  1.1        is set FTEMP_LO, 		8
    405  1.1        is set FTEMP_GRS,		12
    406  1.1        is 
    407  1.1        is set LOCAL,		0			# offsets within an
    408  1.1        is set LOCAL_EX, 		0			# extended precision
    409  1.1        is set LOCAL_SGN,		2			# value saved in memory.
    410  1.1        is set LOCAL_HI, 		4
    411  1.1        is set LOCAL_LO, 		8
    412  1.1        is set LOCAL_GRS,		12
    413  1.1        is 
    414  1.1        is set DST,		0			# offsets within an
    415  1.1        is set DST_EX,		0			# extended precision
    416  1.1        is set DST_HI,		4			# value saved in memory.
    417  1.1        is set DST_LO,		8
    418  1.1        is 
    419  1.1        is set SRC,		0			# offsets within an
    420  1.1        is set SRC_EX,		0			# extended precision
    421  1.1        is set SRC_HI,		4			# value saved in memory.
    422  1.1        is set SRC_LO,		8
    423  1.1        is 
    424  1.1        is set SGL_LO,		0x3f81			# min sgl prec exponent
    425  1.1        is set SGL_HI,		0x407e			# max sgl prec exponent
    426  1.1        is set DBL_LO,		0x3c01			# min dbl prec exponent
    427  1.1        is set DBL_HI,		0x43fe			# max dbl prec exponent
    428  1.1        is set EXT_LO,		0x0			# min ext prec exponent
    429  1.1        is set EXT_HI,		0x7ffe			# max ext prec exponent
    430  1.1        is 
    431  1.1        is set EXT_BIAS,		0x3fff			# extended precision bias
    432  1.1        is set SGL_BIAS,		0x007f			# single precision bias
    433  1.1        is set DBL_BIAS,		0x03ff			# double precision bias
    434  1.1        is 
    435  1.1        is set NORM,		0x00			# operand type for STAG/DTAG
    436  1.1        is set ZERO,		0x01			# operand type for STAG/DTAG
    437  1.1        is set INF,		0x02			# operand type for STAG/DTAG
    438  1.1        is set QNAN,		0x03			# operand type for STAG/DTAG
    439  1.1        is set DENORM,		0x04			# operand type for STAG/DTAG
    440  1.1        is set SNAN,		0x05			# operand type for STAG/DTAG
    441  1.1        is set UNNORM,		0x06			# operand type for STAG/DTAG
    442  1.1        is 
    443  1.1        is ##################
    444  1.1        is # FPSR/FPCR bits #
    445  1.1        is ##################
    446  1.1        is set neg_bit,		0x3			# negative result
    447  1.1        is set z_bit,		0x2			# zero result
    448  1.1        is set inf_bit,		0x1			# infinite result
    449  1.1        is set nan_bit,		0x0			# NAN result
    450  1.1        is 
    451  1.1        is set q_sn_bit,		0x7			# sign bit of quotient byte
    452  1.1        is 
    453  1.1        is set bsun_bit,		7			# branch on unordered
    454  1.1        is set snan_bit,		6			# signalling NAN
    455  1.1        is set operr_bit,		5			# operand error
    456  1.1        is set ovfl_bit,		4			# overflow
    457  1.1        is set unfl_bit,		3			# underflow
    458  1.1        is set dz_bit,		2			# divide by zero
    459  1.1        is set inex2_bit,		1			# inexact result 2
    460  1.1        is set inex1_bit,		0			# inexact result 1
    461  1.1        is 
    462  1.1        is set aiop_bit,		7			# accrued inexact operation bit
    463  1.1        is set aovfl_bit,		6			# accrued overflow bit
    464  1.1        is set aunfl_bit,		5			# accrued underflow bit
    465  1.1        is set adz_bit,		4			# accrued dz bit
    466  1.1        is set ainex_bit,		3			# accrued inexact bit
    467  1.1        is 
    468  1.1        is #############################
    469  1.1        is # FPSR individual bit masks #
    470  1.1        is #############################
    471  1.1        is set neg_mask,		0x08000000		# negative bit mask (lw)
    472  1.1        is set inf_mask,		0x02000000		# infinity bit mask (lw)
    473  1.1        is set z_mask,		0x04000000		# zero bit mask (lw)
    474  1.1        is set nan_mask,		0x01000000		# nan bit mask (lw)
    475  1.1        is 
    476  1.1        is set neg_bmask,		0x08			# negative bit mask (byte)
    477  1.1        is set inf_bmask,		0x02			# infinity bit mask (byte)
    478  1.1        is set z_bmask,		0x04			# zero bit mask (byte)
    479  1.1        is set nan_bmask,		0x01			# nan bit mask (byte)
    480  1.1        is 
    481  1.1        is set bsun_mask,		0x00008000		# bsun exception mask
    482  1.1        is set snan_mask,		0x00004000		# snan exception mask
    483  1.1        is set operr_mask,		0x00002000		# operr exception mask
    484  1.1        is set ovfl_mask,		0x00001000		# overflow exception mask
    485  1.1        is set unfl_mask,		0x00000800		# underflow exception mask
    486  1.1        is set dz_mask,		0x00000400		# dz exception mask
    487  1.1        is set inex2_mask,		0x00000200		# inex2 exception mask
    488  1.1        is set inex1_mask,		0x00000100		# inex1 exception mask
    489  1.1        is 
    490  1.1        is set aiop_mask,		0x00000080		# accrued illegal operation
    491  1.1        is set aovfl_mask,		0x00000040		# accrued overflow
    492  1.1        is set aunfl_mask,		0x00000020		# accrued underflow
    493  1.1        is set adz_mask,		0x00000010		# accrued divide by zero
    494  1.1        is set ainex_mask,		0x00000008		# accrued inexact
    495  1.1        is 
    496  1.1        is ######################################
    497  1.1        is # FPSR combinations used in the FPSP #
    498  1.1        is ######################################
    499  1.1        is set dzinf_mask,		inf_mask+dz_mask+adz_mask
    500  1.1        is set opnan_mask,		nan_mask+operr_mask+aiop_mask
    501  1.1        is set nzi_mask,		0x01ffffff 		#clears N, Z, and I
    502  1.1        is set unfinx_mask,	unfl_mask+inex2_mask+aunfl_mask+ainex_mask
    503  1.1        is set unf2inx_mask,	unfl_mask+inex2_mask+ainex_mask
    504  1.1        is set ovfinx_mask,	ovfl_mask+inex2_mask+aovfl_mask+ainex_mask
    505  1.1        is set inx1a_mask,		inex1_mask+ainex_mask
    506  1.1        is set inx2a_mask,		inex2_mask+ainex_mask
    507  1.1        is set snaniop_mask, 	nan_mask+snan_mask+aiop_mask
    508  1.1        is set snaniop2_mask,	snan_mask+aiop_mask
    509  1.1        is set naniop_mask,	nan_mask+aiop_mask
    510  1.1        is set neginf_mask,	neg_mask+inf_mask
    511  1.1        is set infaiop_mask, 	inf_mask+aiop_mask
    512  1.1        is set negz_mask,		neg_mask+z_mask
    513  1.1        is set opaop_mask,		operr_mask+aiop_mask
    514  1.1        is set unfl_inx_mask,	unfl_mask+aunfl_mask+ainex_mask
    515  1.1        is set ovfl_inx_mask,	ovfl_mask+aovfl_mask+ainex_mask
    516  1.1        is 
    517  1.1        is #########
    518  1.1        is # misc. #
    519  1.1        is #########
    520  1.1        is set rnd_stky_bit,	29			# stky bit pos in longword
    521  1.1        is 
    522  1.1        is set sign_bit,		0x7			# sign bit
    523  1.1        is set signan_bit,		0x6			# signalling nan bit
    524  1.1        is 
    525  1.1        is set sgl_thresh,		0x3f81			# minimum sgl exponent
    526  1.1        is set dbl_thresh,		0x3c01			# minimum dbl exponent
    527  1.1        is 
    528  1.1        is set x_mode,		0x0			# extended precision
    529  1.1        is set s_mode,		0x4			# single precision
    530  1.1        is set d_mode,		0x8			# double precision
    531  1.1        is 
    532  1.1        is set rn_mode,		0x0			# round-to-nearest
    533  1.1        is set rz_mode,		0x1			# round-to-zero
    534  1.1        is set rm_mode,		0x2			# round-tp-minus-infinity
    535  1.1        is set rp_mode,		0x3			# round-to-plus-infinity
    536  1.1        is 
    537  1.1        is set mantissalen,	64			# length of mantissa in bits
    538  1.1        is 
    539  1.1        is set BYTE,		1			# len(byte) == 1 byte
    540  1.1        is set WORD, 		2			# len(word) == 2 bytes
    541  1.1        is set LONG, 		4			# len(longword) == 2 bytes
    542  1.1        is 
    543  1.1        is set BSUN_VEC,		0xc0			# bsun    vector offset
    544  1.1        is set INEX_VEC,		0xc4			# inexact vector offset
    545  1.1        is set DZ_VEC,		0xc8			# dz      vector offset
    546  1.1        is set UNFL_VEC,		0xcc			# unfl    vector offset
    547  1.1        is set OPERR_VEC,		0xd0			# operr   vector offset
    548  1.1        is set OVFL_VEC,		0xd4			# ovfl    vector offset
    549  1.1        is set SNAN_VEC,		0xd8			# snan    vector offset
    550  1.1        is 
    551  1.1        is ###########################
    552  1.1        is # SPecial CONDition FLaGs #
    553  1.1        is ###########################
    554  1.1        is set ftrapcc_flg,	0x01			# flag bit: ftrapcc exception
    555  1.1        is set fbsun_flg,		0x02			# flag bit: bsun exception
    556  1.1        is set mia7_flg,		0x04			# flag bit: (a7)+ <ea>
    557  1.1        is set mda7_flg,		0x08			# flag bit: -(a7) <ea>
    558  1.1        is set fmovm_flg,		0x40			# flag bit: fmovm instruction
    559  1.1        is set immed_flg,		0x80			# flag bit: &<data> <ea>
    560  1.1        is 
    561  1.1        is set ftrapcc_bit,	0x0
    562  1.1        is set fbsun_bit,		0x1
    563  1.1        is set mia7_bit,		0x2
    564  1.1        is set mda7_bit,		0x3
    565  1.1        is set immed_bit,		0x7
    566  1.1        is 
    567  1.1        is ##################################
    568  1.1        is # TRANSCENDENTAL "LAST-OP" FLAGS #
    569  1.1        is ##################################
    570  1.1        is set FMUL_OP,		0x0			# fmul instr performed last
    571  1.1        is set FDIV_OP,		0x1			# fdiv performed last
    572  1.1        is set FADD_OP,		0x2			# fadd performed last
    573  1.1        is set FMOV_OP,		0x3			# fmov performed last
    574  1.1        is 
    575  1.1        is #############
    576  1.1        is # CONSTANTS #
    577  1.1        is #############
    578  1.1        is T1:	long		0x40C62D38,0xD3D64634	# 16381 LOG2 LEAD
    579  1.1        is T2:	long		0x3D6F90AE,0xB1E75CC7	# 16381 LOG2 TRAIL
    580  1.1        is 
    581  1.1        is PI:	long		0x40000000,0xC90FDAA2,0x2168C235,0x00000000
    582  1.1        is PIBY2:	long		0x3FFF0000,0xC90FDAA2,0x2168C235,0x00000000
    583  1.1        is 
    584  1.1        is TWOBYPI:
    585  1.1        is 	long		0x3FE45F30,0x6DC9C883
    586  1.1        is 
    587  1.1        is #########################################################################
    588  1.1        is # XDEF ****************************************************************	#
    589  1.1        is #	_fpsp_ovfl(): 060FPSP entry point for FP Overflow exception.	#
    590  1.1        is #									#
    591  1.1        is #	This handler should be the first code executed upon taking the	#
    592  1.1        is #	FP Overflow exception in an operating system.			#
    593  1.1        is #									#
    594  1.1        is # XREF ****************************************************************	#
    595  1.1        is #	_imem_read_long() - read instruction longword			#
    596  1.1        is #	fix_skewed_ops() - adjust src operand in fsave frame		#
    597  1.1        is #	set_tag_x() - determine optype of src/dst operands		#
    598  1.1        is #	store_fpreg() - store opclass 0 or 2 result to FP regfile	#
    599  1.1        is #	unnorm_fix() - change UNNORM operands to NORM or ZERO		#
    600  1.1        is #	load_fpn2() - load dst operand from FP regfile			#
    601  1.1        is #	fout() - emulate an opclass 3 instruction			#
    602  1.1        is #	tbl_unsupp - add of table of emulation routines for opclass 0,2	#
    603  1.1        is #	_fpsp_done() - "callout" for 060FPSP exit (all work done!)	#
    604  1.1        is #	_real_ovfl() - "callout" for Overflow exception enabled code	#
    605  1.1        is #	_real_inex() - "callout" for Inexact exception enabled code	#
    606  1.1        is #	_real_trace() - "callout" for Trace exception code		#
    607  1.1        is #									#
    608  1.1        is # INPUT ***************************************************************	#
    609  1.1        is #	- The system stack contains the FP Ovfl exception stack frame	#
    610  1.1        is #	- The fsave frame contains the source operand			#
    611  1.1        is # 									#
    612  1.1        is # OUTPUT **************************************************************	#
    613  1.1        is #	Overflow Exception enabled:					#
    614  1.1        is #	- The system stack is unchanged					#
    615  1.1        is #	- The fsave frame contains the adjusted src op for opclass 0,2	#
    616  1.1        is #	Overflow Exception disabled:					#
    617  1.1        is #	- The system stack is unchanged					#
    618  1.1        is #	- The "exception present" flag in the fsave frame is cleared	#
    619  1.1        is #									#
    620  1.1        is # ALGORITHM ***********************************************************	#
    621  1.1        is #	On the 060, if an FP overflow is present as the result of any	#
    622  1.1        is # instruction, the 060 will take an overflow exception whether the 	#
    623  1.1        is # exception is enabled or disabled in the FPCR. For the disabled case, 	#
    624  1.1        is # This handler emulates the instruction to determine what the correct	#
    625  1.1        is # default result should be for the operation. This default result is	#
    626  1.1        is # then stored in either the FP regfile, data regfile, or memory. 	#
    627  1.1        is # Finally, the handler exits through the "callout" _fpsp_done() 	#
    628  1.1        is # denoting that no exceptional conditions exist within the machine.	#
    629  1.1        is # 	If the exception is enabled, then this handler must create the	#
    630  1.1        is # exceptional operand and plave it in the fsave state frame, and store	#
    631  1.1        is # the default result (only if the instruction is opclass 3). For 	#
    632  1.1        is # exceptions enabled, this handler must exit through the "callout" 	#
    633  1.1        is # _real_ovfl() so that the operating system enabled overflow handler	#
    634  1.1        is # can handle this case.							#
    635  1.1        is #	Two other conditions exist. First, if overflow was disabled 	#
    636  1.1        is # but the inexact exception was enabled, this handler must exit 	#
    637  1.1        is # through the "callout" _real_inex() regardless of whether the result	#
    638  1.1        is # was inexact.								#
    639  1.1        is #	Also, in the case of an opclass three instruction where 	#
    640  1.1        is # overflow was disabled and the trace exception was enabled, this	#
    641  1.1        is # handler must exit through the "callout" _real_trace().		#
    642  1.1        is #									#
    643  1.1        is #########################################################################
    644  1.1        is 
    645  1.1        is 	global		_fpsp_ovfl
    646  1.1        is _fpsp_ovfl:
    647  1.1        is 
    648  1.1        is #$#	sub.l		&24,%sp			# make room for src/dst
    649  1.1        is 
    650  1.1        is 	link.w		%a6,&-LOCAL_SIZE	# init stack frame
    651  1.1        is 
    652  1.1        is 	fsave		FP_SRC(%a6)		# grab the "busy" frame
    653  1.1        is 
    654  1.1        is  	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
    655  1.1        is 	fmovm.l		%fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
    656  1.1        is  	fmovm.x		&0xc0,EXC_FPREGS(%a6)	# save fp0-fp1 on stack
    657  1.1        is 
    658  1.1        is # the FPIAR holds the "current PC" of the faulting instruction
    659  1.1        is 	mov.l		USER_FPIAR(%a6),EXC_EXTWPTR(%a6)
    660  1.1        is 	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
    661  1.1        is 	addq.l		&0x4,EXC_EXTWPTR(%a6)	# incr instruction ptr
    662  1.1        is 	bsr.l		_imem_read_long		# fetch the instruction words
    663  1.1        is 	mov.l		%d0,EXC_OPWORD(%a6)
    664  1.1        is 
    665  1.1        is ##############################################################################
    666  1.1        is 
    667  1.1        is 	btst		&0x5,EXC_CMDREG(%a6)	# is instr an fmove out?
    668  1.1        is 	bne.w		fovfl_out
    669  1.1        is 
    670  1.1        is 
    671  1.1        is 	lea		FP_SRC(%a6),%a0		# pass: ptr to src op
    672  1.1        is 	bsr.l		fix_skewed_ops		# fix src op
    673  1.1        is 
    674  1.1        is # since, I believe, only NORMs and DENORMs can come through here,
    675  1.1        is # maybe we can avoid the subroutine call.
    676  1.1        is 	lea		FP_SRC(%a6),%a0		# pass: ptr to src op
    677  1.1        is 	bsr.l		set_tag_x		# tag the operand type
    678  1.1        is 	mov.b		%d0,STAG(%a6)		# maybe NORM,DENORM
    679  1.1        is 
    680  1.1        is # bit five of the fp extension word separates the monadic and dyadic operations
    681  1.1        is # that can pass through fpsp_ovfl(). remember that fcmp, ftst, and fsincos
    682  1.1        is # will never take this exception.
    683  1.1        is 	btst		&0x5,1+EXC_CMDREG(%a6)	# is operation monadic or dyadic?
    684  1.1        is 	beq.b		fovfl_extract		# monadic
    685  1.1        is 
    686  1.1        is 	bfextu		EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg
    687  1.1        is 	bsr.l		load_fpn2		# load dst into FP_DST
    688  1.1        is 
    689  1.1        is 	lea		FP_DST(%a6),%a0		# pass: ptr to dst op
    690  1.1        is 	bsr.l		set_tag_x		# tag the operand type
    691  1.1        is 	cmpi.b		%d0,&UNNORM		# is operand an UNNORM?
    692  1.1        is 	bne.b		fovfl_op2_done		# no
    693  1.1        is 	bsr.l		unnorm_fix		# yes; convert to NORM,DENORM,or ZERO
    694  1.1        is fovfl_op2_done:
    695  1.1        is 	mov.b		%d0,DTAG(%a6)		# save dst optype tag
    696  1.1        is 
    697  1.1        is fovfl_extract:
    698  1.1        is 
    699  1.1        is #$#	mov.l		FP_SRC_EX(%a6),TRAP_SRCOP_EX(%a6)
    700  1.1        is #$#	mov.l		FP_SRC_HI(%a6),TRAP_SRCOP_HI(%a6)
    701  1.1        is #$#	mov.l		FP_SRC_LO(%a6),TRAP_SRCOP_LO(%a6)
    702  1.1        is #$#	mov.l		FP_DST_EX(%a6),TRAP_DSTOP_EX(%a6)
    703  1.1        is #$#	mov.l		FP_DST_HI(%a6),TRAP_DSTOP_HI(%a6)
    704  1.1        is #$#	mov.l		FP_DST_LO(%a6),TRAP_DSTOP_LO(%a6)
    705  1.1        is 
    706  1.1        is 	clr.l		%d0
    707  1.1        is 	mov.b		FPCR_MODE(%a6),%d0	# pass rnd prec/mode
    708  1.1        is 
    709  1.1        is 	mov.b		1+EXC_CMDREG(%a6),%d1
    710  1.1        is 	andi.w		&0x007f,%d1		# extract extension
    711  1.1        is 
    712  1.1        is 	andi.l		&0x00ff01ff,USER_FPSR(%a6) # zero all but accured field
    713  1.1        is 
    714  1.1        is 	fmov.l		&0x0,%fpcr		# zero current control regs
    715  1.1        is 	fmov.l		&0x0,%fpsr
    716  1.1        is 
    717  1.1        is 	lea		FP_SRC(%a6),%a0
    718  1.1        is 	lea		FP_DST(%a6),%a1
    719  1.1        is 
    720  1.1        is # maybe we can make these entry points ONLY the OVFL entry points of each routine.
    721  1.1        is 	mov.l		(tbl_unsupp.l,%pc,%d1.w*4),%d1 # fetch routine addr
    722  1.1        is 	jsr		(tbl_unsupp.l,%pc,%d1.l*1)
    723  1.1        is 
    724  1.1        is # the operation has been emulated. the result is in fp0.
    725  1.1        is # the EXOP, if an exception occurred, is in fp1.
    726  1.1        is # we must save the default result regardless of whether
    727  1.1        is # traps are enabled or disabled.
    728  1.1        is 	bfextu		EXC_CMDREG(%a6){&6:&3},%d0
    729  1.1        is 	bsr.l		store_fpreg
    730  1.1        is 
    731  1.1        is # the exceptional possibilities we have left ourselves with are ONLY overflow
    732  1.1        is # and inexact. and, the inexact is such that overflow occurred and was disabled
    733  1.1        is # but inexact was enabled.
    734  1.1        is 	btst		&ovfl_bit,FPCR_ENABLE(%a6)
    735  1.1        is 	bne.b		fovfl_ovfl_on
    736  1.1        is 
    737  1.1        is 	btst		&inex2_bit,FPCR_ENABLE(%a6)
    738  1.1        is 	bne.b		fovfl_inex_on
    739  1.1        is 
    740  1.1        is 	fmovm.x		EXC_FPREGS(%a6),&0xc0	# restore fp0-fp1
    741  1.1        is 	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
    742  1.1        is 	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
    743  1.1        is 
    744  1.1        is 	unlk		%a6
    745  1.1        is #$#	add.l		&24,%sp
    746  1.1        is 	bra.l		_fpsp_done
    747  1.1        is 
    748  1.1        is # overflow is enabled AND overflow, of course, occurred. so, we have the EXOP
    749  1.1        is # in fp1. now, simply jump to _real_ovfl()!
    750  1.1        is fovfl_ovfl_on:
    751  1.1        is 	fmovm.x		&0x40,FP_SRC(%a6)	# save EXOP (fp1) to stack
    752  1.1        is 
    753  1.1        is 	mov.w		&0xe005,2+FP_SRC(%a6) 	# save exc status
    754  1.1        is 
    755  1.1        is 	fmovm.x		EXC_FPREGS(%a6),&0xc0	# restore fp0-fp1
    756  1.1        is 	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
    757  1.1        is 	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
    758  1.1        is 
    759  1.1        is 	frestore	FP_SRC(%a6)		# do this after fmovm,other f<op>s!
    760  1.1        is 
    761  1.1        is 	unlk		%a6
    762  1.1        is 
    763  1.1        is 	bra.l		_real_ovfl
    764  1.1        is 
    765  1.1        is # overflow occurred but is disabled. meanwhile, inexact is enabled. therefore,
    766  1.1        is # we must jump to real_inex().
    767  1.1        is fovfl_inex_on:
    768  1.1        is 
    769  1.1        is 	fmovm.x		&0x40,FP_SRC(%a6) 	# save EXOP (fp1) to stack
    770  1.1        is 
    771  1.1        is 	mov.b		&0xc4,1+EXC_VOFF(%a6)	# vector offset = 0xc4
    772  1.1        is 	mov.w		&0xe001,2+FP_SRC(%a6) 	# save exc status
    773  1.1        is 
    774  1.1        is 	fmovm.x		EXC_FPREGS(%a6),&0xc0	# restore fp0-fp1
    775  1.1        is 	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
    776  1.1        is 	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
    777  1.1        is 
    778  1.1        is 	frestore	FP_SRC(%a6)		# do this after fmovm,other f<op>s!
    779  1.1        is 
    780  1.1        is 	unlk		%a6
    781  1.1        is 
    782  1.1        is 	bra.l		_real_inex
    783  1.1        is 
    784  1.1        is ########################################################################
    785  1.1        is fovfl_out:
    786  1.1        is 
    787  1.1        is 
    788  1.1        is #$#	mov.l		FP_SRC_EX(%a6),TRAP_SRCOP_EX(%a6)
    789  1.1        is #$#	mov.l		FP_SRC_HI(%a6),TRAP_SRCOP_HI(%a6)
    790  1.1        is #$#	mov.l		FP_SRC_LO(%a6),TRAP_SRCOP_LO(%a6)
    791  1.1        is 
    792  1.1        is # the src operand is definitely a NORM(!), so tag it as such
    793  1.1        is 	mov.b		&NORM,STAG(%a6)		# set src optype tag
    794  1.1        is 
    795  1.1        is 	clr.l		%d0
    796  1.1        is 	mov.b		FPCR_MODE(%a6),%d0	# pass rnd prec/mode
    797  1.1        is 
    798  1.1        is 	and.l		&0xffff00ff,USER_FPSR(%a6) # zero all but accured field
    799  1.1        is 
    800  1.1        is 	fmov.l		&0x0,%fpcr		# zero current control regs
    801  1.1        is 	fmov.l		&0x0,%fpsr
    802  1.1        is 
    803  1.1        is 	lea		FP_SRC(%a6),%a0		# pass ptr to src operand
    804  1.1        is 
    805  1.1        is 	bsr.l		fout
    806  1.1        is 
    807  1.1        is 	btst		&ovfl_bit,FPCR_ENABLE(%a6)
    808  1.1        is 	bne.w		fovfl_ovfl_on
    809  1.1        is 
    810  1.1        is 	btst		&inex2_bit,FPCR_ENABLE(%a6)
    811  1.1        is 	bne.w		fovfl_inex_on
    812  1.1        is 
    813  1.1        is 	fmovm.x		EXC_FPREGS(%a6),&0xc0	# restore fp0-fp1
    814  1.1        is 	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
    815  1.1        is 	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
    816  1.1        is 
    817  1.1        is 	unlk		%a6
    818  1.1        is #$#	add.l		&24,%sp
    819  1.1        is 
    820  1.1        is 	btst		&0x7,(%sp)		# is trace on?
    821  1.1        is 	beq.l		_fpsp_done		# no
    822  1.1        is 
    823  1.1        is 	fmov.l		%fpiar,0x8(%sp)		# "Current PC" is in FPIAR
    824  1.1        is 	mov.w		&0x2024,0x6(%sp)	# stk fmt = 0x2; voff = 0x024
    825  1.1        is 	bra.l		_real_trace
    826  1.1        is 
    827  1.1        is #########################################################################
    828  1.1        is # XDEF ****************************************************************	#
    829  1.1        is #	_fpsp_unfl(): 060FPSP entry point for FP Underflow exception.	#
    830  1.1        is #									#
    831  1.1        is #	This handler should be the first code executed upon taking the	#
    832  1.1        is #	FP Underflow exception in an operating system.			#
    833  1.1        is #									#
    834  1.1        is # XREF ****************************************************************	#
    835  1.1        is #	_imem_read_long() - read instruction longword			#
    836  1.1        is #	fix_skewed_ops() - adjust src operand in fsave frame		#
    837  1.1        is #	set_tag_x() - determine optype of src/dst operands		#
    838  1.1        is #	store_fpreg() - store opclass 0 or 2 result to FP regfile	#
    839  1.1        is #	unnorm_fix() - change UNNORM operands to NORM or ZERO		#
    840  1.1        is #	load_fpn2() - load dst operand from FP regfile			#
    841  1.1        is #	fout() - emulate an opclass 3 instruction			#
    842  1.1        is #	tbl_unsupp - add of table of emulation routines for opclass 0,2	#
    843  1.1        is #	_fpsp_done() - "callout" for 060FPSP exit (all work done!)	#
    844  1.1        is #	_real_ovfl() - "callout" for Overflow exception enabled code	#
    845  1.1        is #	_real_inex() - "callout" for Inexact exception enabled code	#
    846  1.1        is #	_real_trace() - "callout" for Trace exception code		#
    847  1.1        is #									#
    848  1.1        is # INPUT ***************************************************************	#
    849  1.1        is #	- The system stack contains the FP Unfl exception stack frame	#
    850  1.1        is #	- The fsave frame contains the source operand			#
    851  1.1        is # 									#
    852  1.1        is # OUTPUT **************************************************************	#
    853  1.1        is #	Underflow Exception enabled:					#
    854  1.1        is #	- The system stack is unchanged					#
    855  1.1        is #	- The fsave frame contains the adjusted src op for opclass 0,2	#
    856  1.1        is #	Underflow Exception disabled:					#
    857  1.1        is #	- The system stack is unchanged					#
    858  1.1        is #	- The "exception present" flag in the fsave frame is cleared	#
    859  1.1        is #									#
    860  1.1        is # ALGORITHM ***********************************************************	#
    861  1.1        is #	On the 060, if an FP underflow is present as the result of any	#
    862  1.1        is # instruction, the 060 will take an underflow exception whether the 	#
    863  1.1        is # exception is enabled or disabled in the FPCR. For the disabled case, 	#
    864  1.1        is # This handler emulates the instruction to determine what the correct	#
    865  1.1        is # default result should be for the operation. This default result is	#
    866  1.1        is # then stored in either the FP regfile, data regfile, or memory. 	#
    867  1.1        is # Finally, the handler exits through the "callout" _fpsp_done() 	#
    868  1.1        is # denoting that no exceptional conditions exist within the machine.	#
    869  1.1        is # 	If the exception is enabled, then this handler must create the	#
    870  1.1        is # exceptional operand and plave it in the fsave state frame, and store	#
    871  1.1        is # the default result (only if the instruction is opclass 3). For 	#
    872  1.1        is # exceptions enabled, this handler must exit through the "callout" 	#
    873  1.1        is # _real_unfl() so that the operating system enabled overflow handler	#
    874  1.1        is # can handle this case.							#
    875  1.1        is #	Two other conditions exist. First, if underflow was disabled 	#
    876  1.1        is # but the inexact exception was enabled and the result was inexact, 	#
    877  1.1        is # this handler must exit through the "callout" _real_inex().		#
    878  1.1        is # was inexact.								#
    879  1.1        is #	Also, in the case of an opclass three instruction where 	#
    880  1.1        is # underflow was disabled and the trace exception was enabled, this	#
    881  1.1        is # handler must exit through the "callout" _real_trace().		#
    882  1.1        is #									#
    883  1.1        is #########################################################################
    884  1.1        is 
    885  1.1        is 	global		_fpsp_unfl
    886  1.1        is _fpsp_unfl:
    887  1.1        is 
    888  1.1        is #$#	sub.l		&24,%sp			# make room for src/dst
    889  1.1        is 
    890  1.1        is 	link.w		%a6,&-LOCAL_SIZE	# init stack frame
    891  1.1        is 
    892  1.1        is 	fsave		FP_SRC(%a6)		# grab the "busy" frame
    893  1.1        is 
    894  1.1        is  	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
    895  1.1        is 	fmovm.l		%fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
    896  1.1        is  	fmovm.x		&0xc0,EXC_FPREGS(%a6)	# save fp0-fp1 on stack
    897  1.1        is 
    898  1.1        is # the FPIAR holds the "current PC" of the faulting instruction
    899  1.1        is 	mov.l		USER_FPIAR(%a6),EXC_EXTWPTR(%a6)
    900  1.1        is 	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
    901  1.1        is 	addq.l		&0x4,EXC_EXTWPTR(%a6)	# incr instruction ptr
    902  1.1        is 	bsr.l		_imem_read_long		# fetch the instruction words
    903  1.1        is 	mov.l		%d0,EXC_OPWORD(%a6)
    904  1.1        is 
    905  1.1        is ##############################################################################
    906  1.1        is 
    907  1.1        is 	btst		&0x5,EXC_CMDREG(%a6)	# is instr an fmove out?
    908  1.1        is 	bne.w		funfl_out
    909  1.1        is 
    910  1.1        is 
    911  1.1        is 	lea		FP_SRC(%a6),%a0		# pass: ptr to src op
    912  1.1        is 	bsr.l		fix_skewed_ops		# fix src op
    913  1.1        is 
    914  1.1        is 	lea		FP_SRC(%a6),%a0		# pass: ptr to src op
    915  1.1        is 	bsr.l		set_tag_x		# tag the operand type
    916  1.1        is 	mov.b		%d0,STAG(%a6)		# maybe NORM,DENORM
    917  1.1        is 
    918  1.1        is # bit five of the fp ext word separates the monadic and dyadic operations
    919  1.1        is # that can pass through fpsp_unfl(). remember that fcmp, and ftst
    920  1.1        is # will never take this exception.
    921  1.1        is 	btst		&0x5,1+EXC_CMDREG(%a6)	# is op monadic or dyadic?
    922  1.1        is 	beq.b		funfl_extract		# monadic
    923  1.1        is 
    924  1.1        is # now, what's left that's not dyadic is fsincos. we can distinguish it
    925  1.1        is # from all dyadics by the '0110xxx pattern
    926  1.1        is 	btst		&0x4,1+EXC_CMDREG(%a6)	# is op an fsincos?
    927  1.1        is 	bne.b		funfl_extract		# yes
    928  1.1        is 
    929  1.1        is 	bfextu		EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg
    930  1.1        is 	bsr.l		load_fpn2		# load dst into FP_DST
    931  1.1        is 
    932  1.1        is 	lea		FP_DST(%a6),%a0		# pass: ptr to dst op
    933  1.1        is 	bsr.l		set_tag_x		# tag the operand type
    934  1.1        is 	cmpi.b		%d0,&UNNORM		# is operand an UNNORM?
    935  1.1        is 	bne.b		funfl_op2_done		# no
    936  1.1        is 	bsr.l		unnorm_fix		# yes; convert to NORM,DENORM,or ZERO
    937  1.1        is funfl_op2_done:
    938  1.1        is 	mov.b		%d0,DTAG(%a6)		# save dst optype tag
    939  1.1        is 
    940  1.1        is funfl_extract:
    941  1.1        is 
    942  1.1        is #$#	mov.l		FP_SRC_EX(%a6),TRAP_SRCOP_EX(%a6)
    943  1.1        is #$#	mov.l		FP_SRC_HI(%a6),TRAP_SRCOP_HI(%a6)
    944  1.1        is #$#	mov.l		FP_SRC_LO(%a6),TRAP_SRCOP_LO(%a6)
    945  1.1        is #$#	mov.l		FP_DST_EX(%a6),TRAP_DSTOP_EX(%a6)
    946  1.1        is #$#	mov.l		FP_DST_HI(%a6),TRAP_DSTOP_HI(%a6)
    947  1.1        is #$#	mov.l		FP_DST_LO(%a6),TRAP_DSTOP_LO(%a6)
    948  1.1        is 
    949  1.1        is 	clr.l		%d0
    950  1.1        is 	mov.b		FPCR_MODE(%a6),%d0	# pass rnd prec/mode
    951  1.1        is 
    952  1.1        is 	mov.b		1+EXC_CMDREG(%a6),%d1
    953  1.1        is 	andi.w		&0x007f,%d1		# extract extension
    954  1.1        is 
    955  1.1        is 	andi.l		&0x00ff01ff,USER_FPSR(%a6)
    956  1.1        is 
    957  1.1        is 	fmov.l		&0x0,%fpcr		# zero current control regs
    958  1.1        is 	fmov.l		&0x0,%fpsr
    959  1.1        is 
    960  1.1        is 	lea		FP_SRC(%a6),%a0
    961  1.1        is 	lea		FP_DST(%a6),%a1
    962  1.1        is 
    963  1.1        is # maybe we can make these entry points ONLY the OVFL entry points of each routine.
    964  1.1        is 	mov.l		(tbl_unsupp.l,%pc,%d1.w*4),%d1 # fetch routine addr
    965  1.1        is 	jsr		(tbl_unsupp.l,%pc,%d1.l*1)
    966  1.1        is 
    967  1.1        is 	bfextu		EXC_CMDREG(%a6){&6:&3},%d0
    968  1.1        is 	bsr.l		store_fpreg
    969  1.1        is 
    970  1.1        is # The `060 FPU multiplier hardware is such that if the result of a
    971  1.1        is # multiply operation is the smallest possible normalized number
    972  1.1        is # (0x00000000_80000000_00000000), then the machine will take an
    973  1.1        is # underflow exception. Since this is incorrect, we need to check
    974  1.1        is # if our emulation, after re-doing the operation, decided that
    975  1.1        is # no underflow was called for. We do these checks only in
    976  1.1        is # funfl_{unfl,inex}_on() because w/ both exceptions disabled, this
    977  1.1        is # special case will simply exit gracefully with the correct result.
    978  1.1        is 
    979  1.1        is # the exceptional possibilities we have left ourselves with are ONLY overflow
    980  1.1        is # and inexact. and, the inexact is such that overflow occurred and was disabled
    981  1.1        is # but inexact was enabled.
    982  1.1        is 	btst		&unfl_bit,FPCR_ENABLE(%a6)
    983  1.1        is 	bne.b		funfl_unfl_on
    984  1.1        is 
    985  1.1        is funfl_chkinex:
    986  1.1        is 	btst		&inex2_bit,FPCR_ENABLE(%a6)
    987  1.1        is 	bne.b		funfl_inex_on
    988  1.1        is 
    989  1.1        is funfl_exit:
    990  1.1        is 	fmovm.x		EXC_FPREGS(%a6),&0xc0	# restore fp0-fp1
    991  1.1        is 	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
    992  1.1        is 	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
    993  1.1        is 
    994  1.1        is 	unlk		%a6
    995  1.1        is #$#	add.l		&24,%sp
    996  1.1        is 	bra.l		_fpsp_done
    997  1.1        is 
    998  1.1        is # overflow is enabled AND overflow, of course, occurred. so, we have the EXOP
    999  1.1        is # in fp1 (don't forget to save fp0). what to do now?
   1000  1.1        is # well, we simply have to get to go to _real_unfl()!
   1001  1.1        is funfl_unfl_on:
   1002  1.1        is 
   1003  1.1        is # The `060 FPU multiplier hardware is such that if the result of a
   1004  1.1        is # multiply operation is the smallest possible normalized number
   1005  1.1        is # (0x00000000_80000000_00000000), then the machine will take an
   1006  1.1        is # underflow exception. Since this is incorrect, we check here to see
   1007  1.1        is # if our emulation, after re-doing the operation, decided that
   1008  1.1        is # no underflow was called for.
   1009  1.1        is 	btst		&unfl_bit,FPSR_EXCEPT(%a6)
   1010  1.1        is 	beq.w		funfl_chkinex
   1011  1.1        is 
   1012  1.1        is funfl_unfl_on2:
   1013  1.1        is 	fmovm.x		&0x40,FP_SRC(%a6)	# save EXOP (fp1) to stack
   1014  1.1        is 
   1015  1.1        is 	mov.w		&0xe003,2+FP_SRC(%a6) 	# save exc status
   1016  1.1        is 
   1017  1.1        is 	fmovm.x		EXC_FPREGS(%a6),&0xc0	# restore fp0-fp1
   1018  1.1        is 	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
   1019  1.1        is 	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
   1020  1.1        is 
   1021  1.1        is 	frestore	FP_SRC(%a6)		# do this after fmovm,other f<op>s!
   1022  1.1        is 
   1023  1.1        is 	unlk		%a6
   1024  1.1        is 
   1025  1.1        is 	bra.l		_real_unfl
   1026  1.1        is 
   1027  1.1        is # undeflow occurred but is disabled. meanwhile, inexact is enabled. therefore,
   1028  1.1        is # we must jump to real_inex().
   1029  1.1        is funfl_inex_on:
   1030  1.1        is 
   1031  1.1        is # The `060 FPU multiplier hardware is such that if the result of a
   1032  1.1        is # multiply operation is the smallest possible normalized number
   1033  1.1        is # (0x00000000_80000000_00000000), then the machine will take an
   1034  1.1        is # underflow exception.
   1035  1.1        is # But, whether bogus or not, if inexact is enabled AND it occurred,
   1036  1.1        is # then we have to branch to real_inex.
   1037  1.1        is 
   1038  1.1        is 	btst		&inex2_bit,FPSR_EXCEPT(%a6)
   1039  1.1        is 	beq.w		funfl_exit
   1040  1.1        is 
   1041  1.1        is funfl_inex_on2:
   1042  1.1        is 
   1043  1.1        is 	fmovm.x		&0x40,FP_SRC(%a6) 	# save EXOP to stack
   1044  1.1        is 
   1045  1.1        is 	mov.b		&0xc4,1+EXC_VOFF(%a6)	# vector offset = 0xc4
   1046  1.1        is 	mov.w		&0xe001,2+FP_SRC(%a6) 	# save exc status
   1047  1.1        is 
   1048  1.1        is 	fmovm.x		EXC_FPREGS(%a6),&0xc0	# restore fp0-fp1
   1049  1.1        is 	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
   1050  1.1        is 	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
   1051  1.1        is 
   1052  1.1        is 	frestore	FP_SRC(%a6)		# do this after fmovm,other f<op>s!
   1053  1.1        is 
   1054  1.1        is 	unlk		%a6
   1055  1.1        is 
   1056  1.1        is 	bra.l		_real_inex
   1057  1.1        is 
   1058  1.1        is #######################################################################
   1059  1.1        is funfl_out:
   1060  1.1        is 
   1061  1.1        is 
   1062  1.1        is #$#	mov.l		FP_SRC_EX(%a6),TRAP_SRCOP_EX(%a6)
   1063  1.1        is #$#	mov.l		FP_SRC_HI(%a6),TRAP_SRCOP_HI(%a6)
   1064  1.1        is #$#	mov.l		FP_SRC_LO(%a6),TRAP_SRCOP_LO(%a6)
   1065  1.1        is 
   1066  1.1        is # the src operand is definitely a NORM(!), so tag it as such
   1067  1.1        is 	mov.b		&NORM,STAG(%a6)		# set src optype tag
   1068  1.1        is 
   1069  1.1        is 	clr.l		%d0
   1070  1.1        is 	mov.b		FPCR_MODE(%a6),%d0	# pass rnd prec/mode
   1071  1.1        is 
   1072  1.1        is 	and.l		&0xffff00ff,USER_FPSR(%a6) # zero all but accured field
   1073  1.1        is 
   1074  1.1        is 	fmov.l		&0x0,%fpcr		# zero current control regs
   1075  1.1        is 	fmov.l		&0x0,%fpsr
   1076  1.1        is 
   1077  1.1        is 	lea		FP_SRC(%a6),%a0		# pass ptr to src operand
   1078  1.1        is 
   1079  1.1        is 	bsr.l		fout
   1080  1.1        is 
   1081  1.1        is 	btst		&unfl_bit,FPCR_ENABLE(%a6)
   1082  1.1        is 	bne.w		funfl_unfl_on2
   1083  1.1        is 
   1084  1.1        is 	btst		&inex2_bit,FPCR_ENABLE(%a6)
   1085  1.1        is 	bne.w		funfl_inex_on2
   1086  1.1        is 
   1087  1.1        is 	fmovm.x		EXC_FPREGS(%a6),&0xc0	# restore fp0-fp1
   1088  1.1        is 	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
   1089  1.1        is 	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
   1090  1.1        is 
   1091  1.1        is 	unlk		%a6
   1092  1.1        is #$#	add.l		&24,%sp
   1093  1.1        is 
   1094  1.1        is 	btst		&0x7,(%sp)		# is trace on?
   1095  1.1        is 	beq.l		_fpsp_done		# no
   1096  1.1        is 
   1097  1.1        is 	fmov.l		%fpiar,0x8(%sp)		# "Current PC" is in FPIAR
   1098  1.1        is 	mov.w		&0x2024,0x6(%sp)	# stk fmt = 0x2; voff = 0x024
   1099  1.1        is 	bra.l		_real_trace
   1100  1.1        is 
   1101  1.1        is #########################################################################
   1102  1.1        is # XDEF ****************************************************************	#
   1103  1.1        is #	_fpsp_unsupp(): 060FPSP entry point for FP "Unimplemented	#
   1104  1.1        is #		        Data Type" exception.				#
   1105  1.1        is #									#
   1106  1.1        is #	This handler should be the first code executed upon taking the	#
   1107  1.1        is #	FP Unimplemented Data Type exception in an operating system.	#
   1108  1.1        is #									#
   1109  1.1        is # XREF ****************************************************************	#
   1110  1.1        is #	_imem_read_{word,long}() - read instruction word/longword	#
   1111  1.1        is #	fix_skewed_ops() - adjust src operand in fsave frame		#
   1112  1.1        is #	set_tag_x() - determine optype of src/dst operands		#
   1113  1.1        is #	store_fpreg() - store opclass 0 or 2 result to FP regfile	#
   1114  1.1        is #	unnorm_fix() - change UNNORM operands to NORM or ZERO		#
   1115  1.1        is #	load_fpn2() - load dst operand from FP regfile			#
   1116  1.1        is #	load_fpn1() - load src operand from FP regfile			#
   1117  1.1        is #	fout() - emulate an opclass 3 instruction			#
   1118  1.1        is #	tbl_unsupp - add of table of emulation routines for opclass 0,2	#
   1119  1.1        is #	_real_inex() - "callout" to operating system inexact handler	#
   1120  1.1        is #	_fpsp_done() - "callout" for exit; work all done		#
   1121  1.1        is #	_real_trace() - "callout" for Trace enabled exception		#
   1122  1.1        is #	funimp_skew() - adjust fsave src ops to "incorrect" value	#
   1123  1.1        is #	_real_snan() - "callout" for SNAN exception			#
   1124  1.1        is #	_real_operr() - "callout" for OPERR exception			#
   1125  1.1        is #	_real_ovfl() - "callout" for OVFL exception			#
   1126  1.1        is #	_real_unfl() - "callout" for UNFL exception			#
   1127  1.1        is #	get_packed() - fetch packed operand from memory			#
   1128  1.1        is #									#
   1129  1.1        is # INPUT ***************************************************************	#
   1130  1.1        is #	- The system stack contains the "Unimp Data Type" stk frame	#
   1131  1.1        is #	- The fsave frame contains the ssrc op (for UNNORM/DENORM)	#
   1132  1.1        is # 									#
   1133  1.1        is # OUTPUT **************************************************************	#
   1134  1.1        is #	If Inexact exception (opclass 3):				#
   1135  1.1        is #	- The system stack is changed to an Inexact exception stk frame	#
   1136  1.1        is #	If SNAN exception (opclass 3):					#
   1137  1.1        is #	- The system stack is changed to an SNAN exception stk frame	#
   1138  1.1        is #	If OPERR exception (opclass 3):					#
   1139  1.1        is #	- The system stack is changed to an OPERR exception stk frame	#
   1140  1.1        is #	If OVFL exception (opclass 3):					#
   1141  1.1        is #	- The system stack is changed to an OVFL exception stk frame	#
   1142  1.1        is #	If UNFL exception (opclass 3):					#
   1143  1.1        is #	- The system stack is changed to an UNFL exception stack frame	#
   1144  1.1        is #	If Trace exception enabled:					#
   1145  1.1        is #	- The system stack is changed to a Trace exception stack frame	#
   1146  1.1        is #	Else: (normal case)						#
   1147  1.1        is #	- Correct result has been stored as appropriate			#
   1148  1.1        is #									#
   1149  1.1        is # ALGORITHM ***********************************************************	#
   1150  1.1        is #	Two main instruction types can enter here: (1) DENORM or UNNORM	#
   1151  1.1        is # unimplemented data types. These can be either opclass 0,2 or 3 	#
   1152  1.1        is # instructions, and (2) PACKED unimplemented data format instructions	#
   1153  1.1        is # also of opclasses 0,2, or 3.						#
   1154  1.1        is #	For UNNORM/DENORM opclass 0 and 2, the handler fetches the src	#
   1155  1.1        is # operand from the fsave state frame and the dst operand (if dyadic)	#
   1156  1.1        is # from the FP register file. The instruction is then emulated by 	#
   1157  1.1        is # choosing an emulation routine from a table of routines indexed by	#
   1158  1.1        is # instruction type. Once the instruction has been emulated and result	#
   1159  1.1        is # saved, then we check to see if any enabled exceptions resulted from	#
   1160  1.1        is # instruction emulation. If none, then we exit through the "callout"	#
   1161  1.1        is # _fpsp_done(). If there is an enabled FP exception, then we insert	#
   1162  1.1        is # this exception into the FPU in the fsave state frame and then exit	#
   1163  1.1        is # through _fpsp_done().							#
   1164  1.1        is #	PACKED opclass 0 and 2 is similar in how the instruction is	#
   1165  1.1        is # emulated and exceptions handled. The differences occur in how the	#
   1166  1.1        is # handler loads the packed op (by calling get_packed() routine) and	#
   1167  1.1        is # by the fact that a Trace exception could be pending for PACKED ops.	#
   1168  1.1        is # If a Trace exception is pending, then the current exception stack	#
   1169  1.1        is # frame is changed to a Trace exception stack frame and an exit is	#
   1170  1.1        is # made through _real_trace().						#
   1171  1.1        is #	For UNNORM/DENORM opclass 3, the actual move out to memory is	#
   1172  1.1        is # performed by calling the routine fout(). If no exception should occur	#
   1173  1.1        is # as the result of emulation, then an exit either occurs through	#
   1174  1.1        is # _fpsp_done() or through _real_trace() if a Trace exception is pending	#
   1175  1.1        is # (a Trace stack frame must be created here, too). If an FP exception	#
   1176  1.1        is # should occur, then we must create an exception stack frame of that	#
   1177  1.1        is # type and jump to either _real_snan(), _real_operr(), _real_inex(),	#
   1178  1.1        is # _real_unfl(), or _real_ovfl() as appropriate. PACKED opclass 3 	#
   1179  1.1        is # emulation is performed in a similar manner.				#
   1180  1.1        is #									#
   1181  1.1        is #########################################################################
   1182  1.1        is 
   1183  1.1        is #
   1184  1.1        is # (1) DENORM and UNNORM (unimplemented) data types:
   1185  1.1        is #
   1186  1.1        is #				post-instruction
   1187  1.1        is #				*****************
   1188  1.1        is #				*      EA	*
   1189  1.1        is #	 pre-instruction	*		*
   1190  1.1        is # 	*****************	*****************
   1191  1.1        is #	* 0x0 *  0x0dc  *	* 0x3 *  0x0dc  *
   1192  1.1        is #	*****************	*****************
   1193  1.1        is #	*     Next	*	*     Next	*
   1194  1.1        is #	*      PC	*	*      PC	*
   1195  1.1        is #	*****************	*****************
   1196  1.1        is #	*      SR	*	*      SR	*
   1197  1.1        is #	*****************	*****************
   1198  1.1        is #
   1199  1.1        is # (2) PACKED format (unsupported) opclasses two and three:
   1200  1.1        is #	*****************
   1201  1.1        is #	*      EA	*
   1202  1.1        is #	*		*
   1203  1.1        is #	*****************
   1204  1.1        is #	* 0x2 *  0x0dc	*
   1205  1.1        is #	*****************
   1206  1.1        is #	*     Next	*
   1207  1.1        is #	*      PC	*
   1208  1.1        is #	*****************
   1209  1.1        is #	*      SR	*
   1210  1.1        is #	*****************
   1211  1.1        is #
   1212  1.1        is 	global		_fpsp_unsupp
   1213  1.1        is _fpsp_unsupp:
   1214  1.1        is 
   1215  1.1        is 	link.w		%a6,&-LOCAL_SIZE	# init stack frame
   1216  1.1        is 
   1217  1.1        is 	fsave		FP_SRC(%a6)		# save fp state
   1218  1.1        is 
   1219  1.1        is  	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
   1220  1.1        is 	fmovm.l		%fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
   1221  1.1        is  	fmovm.x		&0xc0,EXC_FPREGS(%a6)	# save fp0-fp1 on stack
   1222  1.1        is 
   1223  1.1        is 	btst		&0x5,EXC_SR(%a6)	# user or supervisor mode?
   1224  1.1        is 	bne.b		fu_s
   1225  1.1        is fu_u:
   1226  1.1        is 	mov.l		%usp,%a0		# fetch user stack pointer
   1227  1.1        is 	mov.l		%a0,EXC_A7(%a6)		# save on stack
   1228  1.1        is 	bra.b		fu_cont
   1229  1.1        is # if the exception is an opclass zero or two unimplemented data type
   1230  1.1        is # exception, then the a7' calculated here is wrong since it doesn't
   1231  1.1        is # stack an ea. however, we don't need an a7' for this case anyways.
   1232  1.1        is fu_s:
   1233  1.1        is 	lea		0x4+EXC_EA(%a6),%a0	# load old a7'
   1234  1.1        is 	mov.l		%a0,EXC_A7(%a6)		# save on stack
   1235  1.1        is 
   1236  1.1        is fu_cont:
   1237  1.1        is 
   1238  1.1        is # the FPIAR holds the "current PC" of the faulting instruction
   1239  1.1        is # the FPIAR should be set correctly for ALL exceptions passing through
   1240  1.1        is # this point.
   1241  1.1        is 	mov.l		USER_FPIAR(%a6),EXC_EXTWPTR(%a6)
   1242  1.1        is 	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
   1243  1.1        is 	addq.l		&0x4,EXC_EXTWPTR(%a6)	# incr instruction ptr
   1244  1.1        is 	bsr.l		_imem_read_long		# fetch the instruction words
   1245  1.1        is 	mov.l		%d0,EXC_OPWORD(%a6)	# store OPWORD and EXTWORD
   1246  1.1        is 
   1247  1.1        is ############################
   1248  1.1        is 
   1249  1.1        is 	clr.b		SPCOND_FLG(%a6)		# clear special condition flag
   1250  1.1        is 
   1251  1.1        is # Separate opclass three (fpn-to-mem) ops since they have a different
   1252  1.1        is # stack frame and protocol.
   1253  1.1        is 	btst		&0x5,EXC_CMDREG(%a6)	# is it an fmove out?
   1254  1.1        is 	bne.w		fu_out			# yes
   1255  1.1        is 
   1256  1.1        is # Separate packed opclass two instructions.
   1257  1.1        is 	bfextu		EXC_CMDREG(%a6){&0:&6},%d0
   1258  1.1        is 	cmpi.b		%d0,&0x13
   1259  1.1        is 	beq.w		fu_in_pack
   1260  1.1        is 
   1261  1.1        is 
   1262  1.1        is # I'm not sure at this point what FPSR bits are valid for this instruction.
   1263  1.1        is # so, since the emulation routines re-create them anyways, zero exception field
   1264  1.1        is 	andi.l		&0x00ff00ff,USER_FPSR(%a6) # zero exception field
   1265  1.1        is 
   1266  1.1        is 	fmov.l		&0x0,%fpcr		# zero current control regs
   1267  1.1        is 	fmov.l		&0x0,%fpsr
   1268  1.1        is 
   1269  1.1        is # Opclass two w/ memory-to-fpn operation will have an incorrect extended
   1270  1.1        is # precision format if the src format was single or double and the
   1271  1.1        is # source data type was an INF, NAN, DENORM, or UNNORM
   1272  1.1        is 	lea		FP_SRC(%a6),%a0		# pass ptr to input
   1273  1.1        is 	bsr.l		fix_skewed_ops
   1274  1.1        is 
   1275  1.1        is # we don't know whether the src operand or the dst operand (or both) is the
   1276  1.1        is # UNNORM or DENORM. call the function that tags the operand type. if the
   1277  1.1        is # input is an UNNORM, then convert it to a NORM, DENORM, or ZERO.
   1278  1.1        is 	lea		FP_SRC(%a6),%a0		# pass: ptr to src op
   1279  1.1        is 	bsr.l		set_tag_x		# tag the operand type
   1280  1.1        is 	cmpi.b		%d0,&UNNORM		# is operand an UNNORM?
   1281  1.1        is 	bne.b		fu_op2			# no
   1282  1.1        is 	bsr.l		unnorm_fix		# yes; convert to NORM,DENORM,or ZERO
   1283  1.1        is 
   1284  1.1        is fu_op2:
   1285  1.1        is 	mov.b		%d0,STAG(%a6)		# save src optype tag
   1286  1.1        is 
   1287  1.1        is 	bfextu		EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg
   1288  1.1        is 
   1289  1.1        is # bit five of the fp extension word separates the monadic and dyadic operations
   1290  1.1        is # at this point
   1291  1.1        is 	btst		&0x5,1+EXC_CMDREG(%a6)	# is operation monadic or dyadic?
   1292  1.1        is 	beq.b		fu_extract		# monadic
   1293  1.1        is 	cmpi.b		1+EXC_CMDREG(%a6),&0x3a	# is operation an ftst?
   1294  1.1        is 	beq.b		fu_extract		# yes, so it's monadic, too
   1295  1.1        is 
   1296  1.1        is 	bsr.l		load_fpn2		# load dst into FP_DST
   1297  1.1        is 
   1298  1.1        is 	lea		FP_DST(%a6),%a0		# pass: ptr to dst op
   1299  1.1        is 	bsr.l		set_tag_x		# tag the operand type
   1300  1.1        is 	cmpi.b		%d0,&UNNORM		# is operand an UNNORM?
   1301  1.1        is 	bne.b		fu_op2_done		# no
   1302  1.1        is 	bsr.l		unnorm_fix		# yes; convert to NORM,DENORM,or ZERO
   1303  1.1        is fu_op2_done:
   1304  1.1        is 	mov.b		%d0,DTAG(%a6)		# save dst optype tag
   1305  1.1        is 
   1306  1.1        is fu_extract:
   1307  1.1        is 	clr.l		%d0
   1308  1.1        is 	mov.b		FPCR_MODE(%a6),%d0	# fetch rnd mode/prec
   1309  1.1        is 
   1310  1.1        is 	bfextu		1+EXC_CMDREG(%a6){&1:&7},%d1 # extract extension
   1311  1.1        is 
   1312  1.1        is 	lea		FP_SRC(%a6),%a0
   1313  1.1        is 	lea		FP_DST(%a6),%a1
   1314  1.1        is 
   1315  1.1        is 	mov.l		(tbl_unsupp.l,%pc,%d1.l*4),%d1 # fetch routine addr
   1316  1.1        is 	jsr		(tbl_unsupp.l,%pc,%d1.l*1)
   1317  1.1        is 
   1318  1.1        is #
   1319  1.1        is # Exceptions in order of precedence:
   1320  1.1        is # 	BSUN	: none
   1321  1.1        is #	SNAN	: all dyadic ops
   1322  1.1        is #	OPERR	: fsqrt(-NORM)
   1323  1.1        is #	OVFL	: all except ftst,fcmp
   1324  1.1        is #	UNFL	: all except ftst,fcmp
   1325  1.1        is #	DZ	: fdiv
   1326  1.1        is # 	INEX2	: all except ftst,fcmp
   1327  1.1        is #	INEX1	: none (packed doesn't go through here)
   1328  1.1        is #
   1329  1.1        is 
   1330  1.1        is # we determine the highest priority exception(if any) set by the
   1331  1.1        is # emulation routine that has also been enabled by the user.
   1332  1.1        is 	mov.b		FPCR_ENABLE(%a6),%d0	# fetch exceptions set
   1333  1.1        is 	bne.b		fu_in_ena		# some are enabled
   1334  1.1        is 
   1335  1.1        is fu_in_cont:
   1336  1.1        is # fcmp and ftst do not store any result.
   1337  1.1        is 	mov.b		1+EXC_CMDREG(%a6),%d0	# fetch extension
   1338  1.1        is 	andi.b		&0x38,%d0		# extract bits 3-5
   1339  1.1        is 	cmpi.b		%d0,&0x38		# is instr fcmp or ftst?
   1340  1.1        is 	beq.b		fu_in_exit		# yes
   1341  1.1        is 
   1342  1.1        is 	bfextu		EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg
   1343  1.1        is 	bsr.l		store_fpreg		# store the result
   1344  1.1        is 
   1345  1.1        is fu_in_exit:
   1346  1.1        is 
   1347  1.1        is 	fmovm.x		EXC_FPREGS(%a6),&0xc0	# restore fp0/fp1
   1348  1.1        is 	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
   1349  1.1        is 	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
   1350  1.1        is 
   1351  1.1        is 	unlk		%a6
   1352  1.1        is 
   1353  1.1        is 	bra.l		_fpsp_done
   1354  1.1        is 
   1355  1.1        is fu_in_ena:
   1356  1.1        is 	and.b		FPSR_EXCEPT(%a6),%d0	# keep only ones enabled
   1357  1.1        is 	bfffo		%d0{&24:&8},%d0		# find highest priority exception
   1358  1.1        is 	bne.b		fu_in_exc		# there is at least one set
   1359  1.1        is 
   1360  1.1        is #
   1361  1.1        is # No exceptions occurred that were also enabled. Now:
   1362  1.1        is #
   1363  1.1        is #   	if (OVFL && ovfl_disabled && inexact_enabled) {
   1364  1.1        is #	    branch to _real_inex() (even if the result was exact!);
   1365  1.1        is #     	} else {
   1366  1.1        is #	    save the result in the proper fp reg (unless the op is fcmp or ftst);
   1367  1.1        is #	    return;
   1368  1.1        is #     	}
   1369  1.1        is #
   1370  1.1        is 	btst		&ovfl_bit,FPSR_EXCEPT(%a6) # was overflow set?
   1371  1.1        is 	beq.b		fu_in_cont		# no
   1372  1.1        is 
   1373  1.1        is fu_in_ovflchk:
   1374  1.1        is 	btst		&inex2_bit,FPCR_ENABLE(%a6) # was inexact enabled?
   1375  1.1        is 	beq.b		fu_in_cont		# no
   1376  1.1        is 	bra.w		fu_in_exc_ovfl		# go insert overflow frame
   1377  1.1        is 
   1378  1.1        is #
   1379  1.1        is # An exception occurred and that exception was enabled:
   1380  1.1        is #
   1381  1.1        is #	shift enabled exception field into lo byte of d0;
   1382  1.1        is #	if (((INEX2 || INEX1) && inex_enabled && OVFL && ovfl_disabled) ||
   1383  1.1        is #	    ((INEX2 || INEX1) && inex_enabled && UNFL && unfl_disabled)) {
   1384  1.1        is #		/*
   1385  1.1        is #		 * this is the case where we must call _real_inex() now or else
   1386  1.1        is #		 * there will be no other way to pass it the exceptional operand
   1387  1.1        is #		 */
   1388  1.1        is #		call _real_inex();
   1389  1.1        is #	} else {
   1390  1.1        is #		restore exc state (SNAN||OPERR||OVFL||UNFL||DZ||INEX) into the FPU;
   1391  1.1        is #	}
   1392  1.1        is #
   1393  1.1        is fu_in_exc:
   1394  1.1        is 	subi.l		&24,%d0			# fix offset to be 0-8
   1395  1.1        is 	cmpi.b		%d0,&0x6		# is exception INEX? (6)
   1396  1.1        is 	bne.b		fu_in_exc_exit		# no
   1397  1.1        is 
   1398  1.1        is # the enabled exception was inexact
   1399  1.1        is 	btst		&unfl_bit,FPSR_EXCEPT(%a6) # did disabled underflow occur?
   1400  1.1        is 	bne.w		fu_in_exc_unfl		# yes
   1401  1.1        is 	btst		&ovfl_bit,FPSR_EXCEPT(%a6) # did disabled overflow occur?
   1402  1.1        is 	bne.w		fu_in_exc_ovfl		# yes
   1403  1.1        is 
   1404  1.1        is # here, we insert the correct fsave status value into the fsave frame for the
   1405  1.1        is # corresponding exception. the operand in the fsave frame should be the original
   1406  1.1        is # src operand.
   1407  1.1        is fu_in_exc_exit:
   1408  1.1        is 	mov.l		%d0,-(%sp)		# save d0
   1409  1.1        is 	bsr.l		funimp_skew		# skew sgl or dbl inputs
   1410  1.1        is 	mov.l		(%sp)+,%d0		# restore d0
   1411  1.1        is 
   1412  1.1        is 	mov.w		(tbl_except.b,%pc,%d0.w*2),2+FP_SRC(%a6) # create exc status
   1413  1.1        is 
   1414  1.1        is 	fmovm.x		EXC_FPREGS(%a6),&0xc0	# restore fp0/fp1
   1415  1.1        is 	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
   1416  1.1        is 	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
   1417  1.1        is 
   1418  1.1        is 	frestore	FP_SRC(%a6)		# restore src op
   1419  1.1        is 
   1420  1.1        is 	unlk		%a6
   1421  1.1        is 
   1422  1.1        is 	bra.l		_fpsp_done
   1423  1.1        is 
   1424  1.1        is tbl_except:
   1425  1.1        is 	short		0xe000,0xe006,0xe004,0xe005
   1426  1.1        is 	short		0xe003,0xe002,0xe001,0xe001
   1427  1.1        is 
   1428  1.1        is fu_in_exc_unfl:
   1429  1.1        is 	mov.w		&0x4,%d0
   1430  1.1        is 	bra.b		fu_in_exc_exit
   1431  1.1        is fu_in_exc_ovfl:
   1432  1.1        is 	mov.w		&0x03,%d0
   1433  1.1        is 	bra.b		fu_in_exc_exit
   1434  1.1        is 
   1435  1.1        is # If the input operand to this operation was opclass two and a single
   1436  1.1        is # or double precision denorm, inf, or nan, the operand needs to be
   1437  1.1        is # "corrected" in order to have the proper equivalent extended precision
   1438  1.1        is # number.
   1439  1.1        is 	global		fix_skewed_ops
   1440  1.1        is fix_skewed_ops:
   1441  1.1        is 	bfextu		EXC_CMDREG(%a6){&0:&6},%d0 # extract opclass,src fmt
   1442  1.1        is 	cmpi.b		%d0,&0x11		# is class = 2 & fmt = sgl?
   1443  1.1        is 	beq.b		fso_sgl			# yes
   1444  1.1        is 	cmpi.b		%d0,&0x15		# is class = 2 & fmt = dbl?
   1445  1.1        is 	beq.b		fso_dbl			# yes
   1446  1.1        is 	rts					# no
   1447  1.1        is 
   1448  1.1        is fso_sgl:
   1449  1.1        is 	mov.w		LOCAL_EX(%a0),%d0	# fetch src exponent
   1450  1.1        is 	andi.w		&0x7fff,%d0		# strip sign
   1451  1.1        is 	cmpi.w		%d0,&0x3f80		# is |exp| == $3f80?
   1452  1.1        is 	beq.b		fso_sgl_dnrm_zero	# yes
   1453  1.1        is 	cmpi.w		%d0,&0x407f		# no; is |exp| == $407f?
   1454  1.1        is 	beq.b		fso_infnan		# yes
   1455  1.1        is 	rts					# no
   1456  1.1        is 
   1457  1.1        is fso_sgl_dnrm_zero:
   1458  1.1        is 	andi.l		&0x7fffffff,LOCAL_HI(%a0) # clear j-bit
   1459  1.1        is 	beq.b		fso_zero		# it's a skewed zero
   1460  1.1        is fso_sgl_dnrm:
   1461  1.1        is # here, we count on norm not to alter a0...
   1462  1.1        is 	bsr.l		norm			# normalize mantissa
   1463  1.1        is 	neg.w		%d0			# -shft amt
   1464  1.1        is 	addi.w		&0x3f81,%d0		# adjust new exponent
   1465  1.1        is 	andi.w		&0x8000,LOCAL_EX(%a0) 	# clear old exponent
   1466  1.1        is 	or.w		%d0,LOCAL_EX(%a0)	# insert new exponent
   1467  1.1        is 	rts
   1468  1.1        is 
   1469  1.1        is fso_zero:
   1470  1.1        is 	andi.w		&0x8000,LOCAL_EX(%a0)	# clear bogus exponent
   1471  1.1        is 	rts
   1472  1.1        is 
   1473  1.1        is fso_infnan:
   1474  1.1        is 	andi.b		&0x7f,LOCAL_HI(%a0) 	# clear j-bit
   1475  1.1        is 	ori.w		&0x7fff,LOCAL_EX(%a0)	# make exponent = $7fff
   1476  1.1        is 	rts
   1477  1.1        is 
   1478  1.1        is fso_dbl:
   1479  1.1        is 	mov.w		LOCAL_EX(%a0),%d0	# fetch src exponent
   1480  1.1        is 	andi.w		&0x7fff,%d0		# strip sign
   1481  1.1        is 	cmpi.w		%d0,&0x3c00		# is |exp| == $3c00?
   1482  1.1        is 	beq.b		fso_dbl_dnrm_zero	# yes
   1483  1.1        is 	cmpi.w		%d0,&0x43ff		# no; is |exp| == $43ff?
   1484  1.1        is 	beq.b		fso_infnan		# yes
   1485  1.1        is 	rts					# no
   1486  1.1        is 
   1487  1.1        is fso_dbl_dnrm_zero:
   1488  1.1        is 	andi.l		&0x7fffffff,LOCAL_HI(%a0) # clear j-bit
   1489  1.1        is 	bne.b		fso_dbl_dnrm		# it's a skewed denorm
   1490  1.1        is 	tst.l		LOCAL_LO(%a0)		# is it a zero?
   1491  1.1        is 	beq.b		fso_zero		# yes
   1492  1.1        is fso_dbl_dnrm:
   1493  1.1        is # here, we count on norm not to alter a0...
   1494  1.1        is 	bsr.l		norm			# normalize mantissa
   1495  1.1        is 	neg.w		%d0			# -shft amt
   1496  1.1        is 	addi.w		&0x3c01,%d0		# adjust new exponent
   1497  1.1        is 	andi.w		&0x8000,LOCAL_EX(%a0) 	# clear old exponent
   1498  1.1        is 	or.w		%d0,LOCAL_EX(%a0)	# insert new exponent
   1499  1.1        is 	rts
   1500  1.1        is 
   1501  1.1        is #################################################################
   1502  1.1        is 
   1503  1.1        is # fmove out took an unimplemented data type exception.
   1504  1.1        is # the src operand is in FP_SRC. Call _fout() to write out the result and
   1505  1.1        is # to determine which exceptions, if any, to take.
   1506  1.1        is fu_out:
   1507  1.1        is 
   1508  1.1        is # Separate packed move outs from the UNNORM and DENORM move outs.
   1509  1.1        is 	bfextu		EXC_CMDREG(%a6){&3:&3},%d0
   1510  1.1        is 	cmpi.b		%d0,&0x3
   1511  1.1        is 	beq.w		fu_out_pack
   1512  1.1        is 	cmpi.b		%d0,&0x7
   1513  1.1        is 	beq.w		fu_out_pack
   1514  1.1        is 
   1515  1.1        is 
   1516  1.1        is # I'm not sure at this point what FPSR bits are valid for this instruction.
   1517  1.1        is # so, since the emulation routines re-create them anyways, zero exception field.
   1518  1.1        is # fmove out doesn't affect ccodes.
   1519  1.1        is 	and.l		&0xffff00ff,USER_FPSR(%a6) # zero exception field
   1520  1.1        is 
   1521  1.1        is 	fmov.l		&0x0,%fpcr		# zero current control regs
   1522  1.1        is 	fmov.l		&0x0,%fpsr
   1523  1.1        is 
   1524  1.1        is # the src can ONLY be a DENORM or an UNNORM! so, don't make any big subroutine
   1525  1.1        is # call here. just figure out what it is...
   1526  1.1        is 	mov.w		FP_SRC_EX(%a6),%d0	# get exponent
   1527  1.1        is 	andi.w		&0x7fff,%d0		# strip sign
   1528  1.1        is 	beq.b		fu_out_denorm		# it's a DENORM
   1529  1.1        is 
   1530  1.1        is 	lea		FP_SRC(%a6),%a0
   1531  1.1        is 	bsr.l		unnorm_fix		# yes; fix it
   1532  1.1        is 
   1533  1.1        is 	mov.b		%d0,STAG(%a6)
   1534  1.1        is 
   1535  1.1        is 	bra.b		fu_out_cont
   1536  1.1        is fu_out_denorm:
   1537  1.1        is 	mov.b		&DENORM,STAG(%a6)
   1538  1.1        is fu_out_cont:
   1539  1.1        is 
   1540  1.1        is 	clr.l		%d0
   1541  1.1        is 	mov.b		FPCR_MODE(%a6),%d0	# fetch rnd mode/prec
   1542  1.1        is 
   1543  1.1        is 	lea		FP_SRC(%a6),%a0		# pass ptr to src operand
   1544  1.1        is 
   1545  1.1        is 	mov.l		(%a6),EXC_A6(%a6)	# in case a6 changes
   1546  1.1        is 	bsr.l		fout			# call fmove out routine
   1547  1.1        is 
   1548  1.1        is # Exceptions in order of precedence:
   1549  1.1        is # 	BSUN	: none
   1550  1.1        is #	SNAN	: none
   1551  1.1        is #	OPERR	: fmove.{b,w,l} out of large UNNORM
   1552  1.1        is #	OVFL	: fmove.{s,d}
   1553  1.1        is #	UNFL	: fmove.{s,d,x}
   1554  1.1        is #	DZ	: none
   1555  1.1        is # 	INEX2	: all
   1556  1.1        is #	INEX1	: none (packed doesn't travel through here)
   1557  1.1        is 
   1558  1.1        is # determine the highest priority exception(if any) set by the
   1559  1.1        is # emulation routine that has also been enabled by the user.
   1560  1.1        is 	mov.b		FPCR_ENABLE(%a6),%d0	# fetch exceptions enabled
   1561  1.1        is 	bne.w		fu_out_ena		# some are enabled
   1562  1.1        is 
   1563  1.1        is fu_out_done:
   1564  1.1        is 
   1565  1.1        is 	mov.l		EXC_A6(%a6),(%a6)	# in case a6 changed
   1566  1.1        is 
   1567  1.1        is # on extended precision opclass three instructions using pre-decrement or
   1568  1.1        is # post-increment addressing mode, the address register is not updated. is the
   1569  1.1        is # address register was the stack pointer used from user mode, then let's update
   1570  1.1        is # it here. if it was used from supervisor mode, then we have to handle this
   1571  1.1        is # as a special case.
   1572  1.1        is 	btst		&0x5,EXC_SR(%a6)
   1573  1.1        is 	bne.b		fu_out_done_s
   1574  1.1        is 
   1575  1.1        is 	mov.l		EXC_A7(%a6),%a0		# restore a7
   1576  1.1        is 	mov.l		%a0,%usp
   1577  1.1        is 
   1578  1.1        is fu_out_done_cont:
   1579  1.1        is 	fmovm.x		EXC_FPREGS(%a6),&0xc0	# restore fp0/fp1
   1580  1.1        is 	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
   1581  1.1        is 	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
   1582  1.1        is 
   1583  1.1        is 	unlk		%a6
   1584  1.1        is 
   1585  1.1        is 	btst		&0x7,(%sp)		# is trace on?
   1586  1.1        is 	bne.b		fu_out_trace		# yes
   1587  1.1        is 
   1588  1.1        is 	bra.l		_fpsp_done
   1589  1.1        is 
   1590  1.1        is # is the ea mode pre-decrement of the stack pointer from supervisor mode?
   1591  1.1        is # ("fmov.x fpm,-(a7)") if so,
   1592  1.1        is fu_out_done_s:
   1593  1.1        is 	cmpi.b		SPCOND_FLG(%a6),&mda7_flg
   1594  1.1        is 	bne.b		fu_out_done_cont
   1595  1.1        is 
   1596  1.1        is # the extended precision result is still in fp0. but, we need to save it
   1597  1.1        is # somewhere on the stack until we can copy it to its final resting place.
   1598  1.1        is # here, we're counting on the top of the stack to be the old place-holders
   1599  1.1        is # for fp0/fp1 which have already been restored. that way, we can write
   1600  1.1        is # over those destinations with the shifted stack frame.
   1601  1.1        is 	fmovm.x		&0x80,FP_SRC(%a6)	# put answer on stack
   1602  1.1        is 
   1603  1.1        is 	fmovm.x		EXC_FPREGS(%a6),&0xc0	# restore fp0/fp1
   1604  1.1        is 	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
   1605  1.1        is 	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
   1606  1.1        is 
   1607  1.1        is 	mov.l		(%a6),%a6		# restore frame pointer
   1608  1.1        is 
   1609  1.1        is 	mov.l		LOCAL_SIZE+EXC_SR(%sp),LOCAL_SIZE+EXC_SR-0xc(%sp)
   1610  1.1        is 	mov.l		LOCAL_SIZE+2+EXC_PC(%sp),LOCAL_SIZE+2+EXC_PC-0xc(%sp)
   1611  1.1        is 
   1612  1.1        is # now, copy the result to the proper place on the stack
   1613  1.1        is 	mov.l		LOCAL_SIZE+FP_SRC_EX(%sp),LOCAL_SIZE+EXC_SR+0x0(%sp)
   1614  1.1        is 	mov.l		LOCAL_SIZE+FP_SRC_HI(%sp),LOCAL_SIZE+EXC_SR+0x4(%sp)
   1615  1.1        is 	mov.l		LOCAL_SIZE+FP_SRC_LO(%sp),LOCAL_SIZE+EXC_SR+0x8(%sp)
   1616  1.1        is 
   1617  1.1        is 	add.l		&LOCAL_SIZE-0x8,%sp
   1618  1.1        is 
   1619  1.1        is 	btst		&0x7,(%sp)
   1620  1.1        is 	bne.b		fu_out_trace
   1621  1.1        is 
   1622  1.1        is 	bra.l		_fpsp_done
   1623  1.1        is 
   1624  1.1        is fu_out_ena:
   1625  1.1        is 	and.b		FPSR_EXCEPT(%a6),%d0	# keep only ones enabled
   1626  1.1        is 	bfffo		%d0{&24:&8},%d0		# find highest priority exception
   1627  1.1        is 	bne.b		fu_out_exc		# there is at least one set
   1628  1.1        is 
   1629  1.1        is # no exceptions were set.
   1630  1.1        is # if a disabled overflow occurred and inexact was enabled but the result
   1631  1.1        is # was exact, then a branch to _real_inex() is made.
   1632  1.1        is 	btst		&ovfl_bit,FPSR_EXCEPT(%a6) # was overflow set?
   1633  1.1        is 	beq.w		fu_out_done		# no
   1634  1.1        is 
   1635  1.1        is fu_out_ovflchk:
   1636  1.1        is 	btst		&inex2_bit,FPCR_ENABLE(%a6) # was inexact enabled?
   1637  1.1        is 	beq.w		fu_out_done		# no
   1638  1.1        is 	bra.w		fu_inex			# yes
   1639  1.1        is 
   1640  1.1        is #
   1641  1.1        is # The fp move out that took the "Unimplemented Data Type" exception was
   1642  1.1        is # being traced. Since the stack frames are similar, get the "current" PC
   1643  1.1        is # from FPIAR and put it in the trace stack frame then jump to _real_trace().
   1644  1.1        is #
   1645  1.1        is #		  UNSUPP FRAME		   TRACE FRAME
   1646  1.1        is # 		*****************	*****************
   1647  1.1        is #		*      EA	*	*    Current	*
   1648  1.1        is #		*		*	*      PC	*
   1649  1.1        is #		*****************	*****************
   1650  1.1        is #		* 0x3 *  0x0dc	*	* 0x2 *  0x024	*
   1651  1.1        is #		*****************	*****************
   1652  1.1        is #		*     Next	*	*     Next	*
   1653  1.1        is #		*      PC	*	*      PC	*
   1654  1.1        is #		*****************	*****************
   1655  1.1        is #		*      SR	*	*      SR	*
   1656  1.1        is #		*****************	*****************
   1657  1.1        is #
   1658  1.1        is fu_out_trace:
   1659  1.1        is 	mov.w		&0x2024,0x6(%sp)
   1660  1.1        is 	fmov.l		%fpiar,0x8(%sp)
   1661  1.1        is 	bra.l		_real_trace
   1662  1.1        is 
   1663  1.1        is # an exception occurred and that exception was enabled.
   1664  1.1        is fu_out_exc:
   1665  1.1        is 	subi.l		&24,%d0			# fix offset to be 0-8
   1666  1.1        is 
   1667  1.1        is # we don't mess with the existing fsave frame. just re-insert it and
   1668  1.1        is # jump to the "_real_{}()" handler...
   1669  1.1        is 	mov.w		(tbl_fu_out.b,%pc,%d0.w*2),%d0
   1670  1.1        is 	jmp		(tbl_fu_out.b,%pc,%d0.w*1)
   1671  1.1        is 
   1672  1.1        is 	swbeg		&0x8
   1673  1.1        is tbl_fu_out:
   1674  1.1        is 	short		tbl_fu_out	- tbl_fu_out	# BSUN can't happen
   1675  1.1        is 	short		tbl_fu_out 	- tbl_fu_out	# SNAN can't happen
   1676  1.1        is 	short		fu_operr	- tbl_fu_out	# OPERR
   1677  1.1        is 	short		fu_ovfl 	- tbl_fu_out	# OVFL
   1678  1.1        is 	short		fu_unfl 	- tbl_fu_out	# UNFL
   1679  1.1        is 	short		tbl_fu_out	- tbl_fu_out	# DZ can't happen
   1680  1.1        is 	short		fu_inex 	- tbl_fu_out	# INEX2
   1681  1.1        is 	short		tbl_fu_out	- tbl_fu_out	# INEX1 won't make it here
   1682  1.1        is 
   1683  1.1        is # for snan,operr,ovfl,unfl, src op is still in FP_SRC so just
   1684  1.1        is # frestore it.
   1685  1.1        is fu_snan:
   1686  1.1        is 	fmovm.x		EXC_FPREGS(%a6),&0xc0	# restore fp0/fp1
   1687  1.1        is 	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
   1688  1.1        is 	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
   1689  1.1        is 
   1690  1.1        is 	mov.w		&0x30d8,EXC_VOFF(%a6)	# vector offset = 0xd8
   1691  1.1        is 	mov.w		&0xe006,2+FP_SRC(%a6)
   1692  1.1        is 
   1693  1.1        is 	frestore	FP_SRC(%a6)
   1694  1.1        is 
   1695  1.1        is 	unlk		%a6
   1696  1.1        is 
   1697  1.1        is 
   1698  1.1        is 	bra.l		_real_snan
   1699  1.1        is 
   1700  1.1        is fu_operr:
   1701  1.1        is 	fmovm.x		EXC_FPREGS(%a6),&0xc0	# restore fp0/fp1
   1702  1.1        is 	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
   1703  1.1        is 	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
   1704  1.1        is 
   1705  1.1        is 	mov.w		&0x30d0,EXC_VOFF(%a6)	# vector offset = 0xd0
   1706  1.1        is 	mov.w		&0xe004,2+FP_SRC(%a6)
   1707  1.1        is 
   1708  1.1        is 	frestore	FP_SRC(%a6)
   1709  1.1        is 
   1710  1.1        is 	unlk		%a6
   1711  1.1        is 
   1712  1.1        is 
   1713  1.1        is 	bra.l		_real_operr
   1714  1.1        is 
   1715  1.1        is fu_ovfl:
   1716  1.1        is 	fmovm.x		&0x40,FP_SRC(%a6)	# save EXOP to the stack
   1717  1.1        is 
   1718  1.1        is 	fmovm.x		EXC_FPREGS(%a6),&0xc0	# restore fp0/fp1
   1719  1.1        is 	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
   1720  1.1        is 	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
   1721  1.1        is 
   1722  1.1        is 	mov.w		&0x30d4,EXC_VOFF(%a6)	# vector offset = 0xd4
   1723  1.1        is 	mov.w		&0xe005,2+FP_SRC(%a6)
   1724  1.1        is 
   1725  1.1        is 	frestore	FP_SRC(%a6)		# restore EXOP
   1726  1.1        is 
   1727  1.1        is 	unlk		%a6
   1728  1.1        is 
   1729  1.1        is 	bra.l		_real_ovfl
   1730  1.1        is 
   1731  1.1        is # underflow can happen for extended precision. extended precision opclass
   1732  1.1        is # three instruction exceptions don't update the stack pointer. so, if the
   1733  1.1        is # exception occurred from user mode, then simply update a7 and exit normally.
   1734  1.1        is # if the exception occurred from supervisor mode, check if
   1735  1.1        is fu_unfl:
   1736  1.1        is 	mov.l		EXC_A6(%a6),(%a6)	# restore a6
   1737  1.1        is 
   1738  1.1        is 	btst		&0x5,EXC_SR(%a6)
   1739  1.1        is 	bne.w		fu_unfl_s
   1740  1.1        is 
   1741  1.1        is 	mov.l		EXC_A7(%a6),%a0		# restore a7 whether we need
   1742  1.1        is 	mov.l		%a0,%usp		# to or not...
   1743  1.1        is 
   1744  1.1        is fu_unfl_cont:
   1745  1.1        is 	fmovm.x		&0x40,FP_SRC(%a6)	# save EXOP to the stack
   1746  1.1        is 
   1747  1.1        is 	fmovm.x		EXC_FPREGS(%a6),&0xc0	# restore fp0/fp1
   1748  1.1        is 	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
   1749  1.1        is 	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
   1750  1.1        is 
   1751  1.1        is 	mov.w		&0x30cc,EXC_VOFF(%a6)	# vector offset = 0xcc
   1752  1.1        is 	mov.w		&0xe003,2+FP_SRC(%a6)
   1753  1.1        is 
   1754  1.1        is 	frestore	FP_SRC(%a6)		# restore EXOP
   1755  1.1        is 
   1756  1.1        is 	unlk		%a6
   1757  1.1        is 
   1758  1.1        is 	bra.l		_real_unfl
   1759  1.1        is 
   1760  1.1        is fu_unfl_s:
   1761  1.1        is 	cmpi.b		SPCOND_FLG(%a6),&mda7_flg # was the <ea> mode -(sp)?
   1762  1.1        is 	bne.b		fu_unfl_cont
   1763  1.1        is 
   1764  1.1        is # the extended precision result is still in fp0. but, we need to save it
   1765  1.1        is # somewhere on the stack until we can copy it to its final resting place
   1766  1.1        is # (where the exc frame is currently). make sure it's not at the top of the
   1767  1.1        is # frame or it will get overwritten when the exc stack frame is shifted "down".
   1768  1.1        is 	fmovm.x		&0x80,FP_SRC(%a6)	# put answer on stack
   1769  1.1        is 	fmovm.x		&0x40,FP_DST(%a6)	# put EXOP on stack
   1770  1.1        is 
   1771  1.1        is 	fmovm.x		EXC_FPREGS(%a6),&0xc0	# restore fp0/fp1
   1772  1.1        is 	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
   1773  1.1        is 	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
   1774  1.1        is 
   1775  1.1        is 	mov.w		&0x30cc,EXC_VOFF(%a6)	# vector offset = 0xcc
   1776  1.1        is 	mov.w		&0xe003,2+FP_DST(%a6)
   1777  1.1        is 
   1778  1.1        is 	frestore	FP_DST(%a6)		# restore EXOP
   1779  1.1        is 
   1780  1.1        is 	mov.l		(%a6),%a6		# restore frame pointer
   1781  1.1        is 
   1782  1.1        is 	mov.l		LOCAL_SIZE+EXC_SR(%sp),LOCAL_SIZE+EXC_SR-0xc(%sp)
   1783  1.1        is 	mov.l		LOCAL_SIZE+2+EXC_PC(%sp),LOCAL_SIZE+2+EXC_PC-0xc(%sp)
   1784  1.1        is 	mov.l		LOCAL_SIZE+EXC_EA(%sp),LOCAL_SIZE+EXC_EA-0xc(%sp)
   1785  1.1        is 
   1786  1.1        is # now, copy the result to the proper place on the stack
   1787  1.1        is 	mov.l		LOCAL_SIZE+FP_SRC_EX(%sp),LOCAL_SIZE+EXC_SR+0x0(%sp)
   1788  1.1        is 	mov.l		LOCAL_SIZE+FP_SRC_HI(%sp),LOCAL_SIZE+EXC_SR+0x4(%sp)
   1789  1.1        is 	mov.l		LOCAL_SIZE+FP_SRC_LO(%sp),LOCAL_SIZE+EXC_SR+0x8(%sp)
   1790  1.1        is 
   1791  1.1        is 	add.l		&LOCAL_SIZE-0x8,%sp
   1792  1.1        is 
   1793  1.1        is 	bra.l		_real_unfl
   1794  1.1        is 
   1795  1.1        is # fmove in and out enter here.
   1796  1.1        is fu_inex:
   1797  1.1        is 	fmovm.x		&0x40,FP_SRC(%a6)	# save EXOP to the stack
   1798  1.1        is 
   1799  1.1        is 	fmovm.x		EXC_FPREGS(%a6),&0xc0	# restore fp0/fp1
   1800  1.1        is 	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
   1801  1.1        is 	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
   1802  1.1        is 
   1803  1.1        is 	mov.w		&0x30c4,EXC_VOFF(%a6)	# vector offset = 0xc4
   1804  1.1        is 	mov.w		&0xe001,2+FP_SRC(%a6)
   1805  1.1        is 
   1806  1.1        is 	frestore	FP_SRC(%a6)		# restore EXOP
   1807  1.1        is 
   1808  1.1        is 	unlk		%a6
   1809  1.1        is 
   1810  1.1        is 
   1811  1.1        is 	bra.l		_real_inex
   1812  1.1        is 
   1813  1.1        is #########################################################################
   1814  1.1        is #########################################################################
   1815  1.1        is fu_in_pack:
   1816  1.1        is 
   1817  1.1        is 
   1818  1.1        is # I'm not sure at this point what FPSR bits are valid for this instruction.
   1819  1.1        is # so, since the emulation routines re-create them anyways, zero exception field
   1820  1.1        is 	andi.l		&0x0ff00ff,USER_FPSR(%a6) # zero exception field
   1821  1.1        is 
   1822  1.1        is 	fmov.l		&0x0,%fpcr		# zero current control regs
   1823  1.1        is 	fmov.l		&0x0,%fpsr
   1824  1.1        is 
   1825  1.1        is 	bsr.l		get_packed		# fetch packed src operand
   1826  1.1        is 
   1827  1.1        is 	lea		FP_SRC(%a6),%a0		# pass ptr to src
   1828  1.1        is 	bsr.l		set_tag_x		# set src optype tag
   1829  1.1        is 
   1830  1.1        is 	mov.b		%d0,STAG(%a6)		# save src optype tag
   1831  1.1        is 
   1832  1.1        is 	bfextu		EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg
   1833  1.1        is 
   1834  1.1        is # bit five of the fp extension word separates the monadic and dyadic operations
   1835  1.1        is # at this point
   1836  1.1        is 	btst		&0x5,1+EXC_CMDREG(%a6)	# is operation monadic or dyadic?
   1837  1.1        is 	beq.b		fu_extract_p		# monadic
   1838  1.1        is 	cmpi.b		1+EXC_CMDREG(%a6),&0x3a	# is operation an ftst?
   1839  1.1        is 	beq.b		fu_extract_p		# yes, so it's monadic, too
   1840  1.1        is 
   1841  1.1        is 	bsr.l		load_fpn2		# load dst into FP_DST
   1842  1.1        is 
   1843  1.1        is 	lea		FP_DST(%a6),%a0		# pass: ptr to dst op
   1844  1.1        is 	bsr.l		set_tag_x		# tag the operand type
   1845  1.1        is 	cmpi.b		%d0,&UNNORM		# is operand an UNNORM?
   1846  1.1        is 	bne.b		fu_op2_done_p		# no
   1847  1.1        is 	bsr.l		unnorm_fix		# yes; convert to NORM,DENORM,or ZERO
   1848  1.1        is fu_op2_done_p:
   1849  1.1        is 	mov.b		%d0,DTAG(%a6)		# save dst optype tag
   1850  1.1        is 
   1851  1.1        is fu_extract_p:
   1852  1.1        is 	clr.l		%d0
   1853  1.1        is 	mov.b		FPCR_MODE(%a6),%d0	# fetch rnd mode/prec
   1854  1.1        is 
   1855  1.1        is 	bfextu		1+EXC_CMDREG(%a6){&1:&7},%d1 # extract extension
   1856  1.1        is 
   1857  1.1        is 	lea		FP_SRC(%a6),%a0
   1858  1.1        is 	lea		FP_DST(%a6),%a1
   1859  1.1        is 
   1860  1.1        is 	mov.l		(tbl_unsupp.l,%pc,%d1.l*4),%d1 # fetch routine addr
   1861  1.1        is 	jsr		(tbl_unsupp.l,%pc,%d1.l*1)
   1862  1.1        is 
   1863  1.1        is #
   1864  1.1        is # Exceptions in order of precedence:
   1865  1.1        is # 	BSUN	: none
   1866  1.1        is #	SNAN	: all dyadic ops
   1867  1.1        is #	OPERR	: fsqrt(-NORM)
   1868  1.1        is #	OVFL	: all except ftst,fcmp
   1869  1.1        is #	UNFL	: all except ftst,fcmp
   1870  1.1        is #	DZ	: fdiv
   1871  1.1        is # 	INEX2	: all except ftst,fcmp
   1872  1.1        is #	INEX1	: all
   1873  1.1        is #
   1874  1.1        is 
   1875  1.1        is # we determine the highest priority exception(if any) set by the
   1876  1.1        is # emulation routine that has also been enabled by the user.
   1877  1.1        is 	mov.b		FPCR_ENABLE(%a6),%d0	# fetch exceptions enabled
   1878  1.1        is 	bne.w		fu_in_ena_p		# some are enabled
   1879  1.1        is 
   1880  1.1        is fu_in_cont_p:
   1881  1.1        is # fcmp and ftst do not store any result.
   1882  1.1        is 	mov.b		1+EXC_CMDREG(%a6),%d0	# fetch extension
   1883  1.1        is 	andi.b		&0x38,%d0		# extract bits 3-5
   1884  1.1        is 	cmpi.b		%d0,&0x38		# is instr fcmp or ftst?
   1885  1.1        is 	beq.b		fu_in_exit_p		# yes
   1886  1.1        is 
   1887  1.1        is 	bfextu		EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg
   1888  1.1        is 	bsr.l		store_fpreg		# store the result
   1889  1.1        is 
   1890  1.1        is fu_in_exit_p:
   1891  1.1        is 
   1892  1.1        is 	btst		&0x5,EXC_SR(%a6)	# user or supervisor?
   1893  1.1        is 	bne.w		fu_in_exit_s_p		# supervisor
   1894  1.1        is 
   1895  1.1        is 	mov.l		EXC_A7(%a6),%a0		# update user a7
   1896  1.1        is 	mov.l		%a0,%usp
   1897  1.1        is 
   1898  1.1        is fu_in_exit_cont_p:
   1899  1.1        is 	fmovm.x		EXC_FPREGS(%a6),&0xc0	# restore fp0/fp1
   1900  1.1        is 	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
   1901  1.1        is 	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
   1902  1.1        is 
   1903  1.1        is 	unlk		%a6			# unravel stack frame
   1904  1.1        is 
   1905  1.1        is 	btst		&0x7,(%sp)		# is trace on?
   1906  1.1        is 	bne.w		fu_trace_p		# yes
   1907  1.1        is 
   1908  1.1        is 	bra.l		_fpsp_done		# exit to os
   1909  1.1        is 
   1910  1.1        is # the exception occurred in supervisor mode. check to see if the
   1911  1.1        is # addressing mode was (a7)+. if so, we'll need to shift the
   1912  1.1        is # stack frame "up".
   1913  1.1        is fu_in_exit_s_p:
   1914  1.1        is 	btst		&mia7_bit,SPCOND_FLG(%a6) # was ea mode (a7)+
   1915  1.1        is 	beq.b		fu_in_exit_cont_p	# no
   1916  1.1        is 
   1917  1.1        is 	fmovm.x		EXC_FPREGS(%a6),&0xc0	# restore fp0/fp1
   1918  1.1        is 	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
   1919  1.1        is 	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
   1920  1.1        is 
   1921  1.1        is 	unlk		%a6			# unravel stack frame
   1922  1.1        is 
   1923  1.1        is # shift the stack frame "up". we don't really care about the <ea> field.
   1924  1.1        is 	mov.l		0x4(%sp),0x10(%sp)
   1925  1.1        is 	mov.l		0x0(%sp),0xc(%sp)
   1926  1.1        is 	add.l		&0xc,%sp
   1927  1.1        is 
   1928  1.1        is 	btst		&0x7,(%sp)		# is trace on?
   1929  1.1        is 	bne.w		fu_trace_p		# yes
   1930  1.1        is 
   1931  1.1        is 	bra.l		_fpsp_done		# exit to os
   1932  1.1        is 
   1933  1.1        is fu_in_ena_p:
   1934  1.1        is 	and.b		FPSR_EXCEPT(%a6),%d0	# keep only ones enabled & set
   1935  1.1        is 	bfffo		%d0{&24:&8},%d0		# find highest priority exception
   1936  1.1        is 	bne.b		fu_in_exc_p		# at least one was set
   1937  1.1        is 
   1938  1.1        is #
   1939  1.1        is # No exceptions occurred that were also enabled. Now:
   1940  1.1        is #
   1941  1.1        is #   	if (OVFL && ovfl_disabled && inexact_enabled) {
   1942  1.1        is #	    branch to _real_inex() (even if the result was exact!);
   1943  1.1        is #     	} else {
   1944  1.1        is #	    save the result in the proper fp reg (unless the op is fcmp or ftst);
   1945  1.1        is #	    return;
   1946  1.1        is #     	}
   1947  1.1        is #
   1948  1.1        is 	btst		&ovfl_bit,FPSR_EXCEPT(%a6) # was overflow set?
   1949  1.1        is 	beq.w		fu_in_cont_p		# no
   1950  1.1        is 
   1951  1.1        is fu_in_ovflchk_p:
   1952  1.1        is 	btst		&inex2_bit,FPCR_ENABLE(%a6) # was inexact enabled?
   1953  1.1        is 	beq.w		fu_in_cont_p		# no
   1954  1.1        is 	bra.w		fu_in_exc_ovfl_p	# do _real_inex() now
   1955  1.1        is 
   1956  1.1        is #
   1957  1.1        is # An exception occurred and that exception was enabled:
   1958  1.1        is #
   1959  1.1        is #	shift enabled exception field into lo byte of d0;
   1960  1.1        is #	if (((INEX2 || INEX1) && inex_enabled && OVFL && ovfl_disabled) ||
   1961  1.1        is #	    ((INEX2 || INEX1) && inex_enabled && UNFL && unfl_disabled)) {
   1962  1.1        is #		/*
   1963  1.1        is #		 * this is the case where we must call _real_inex() now or else
   1964  1.1        is #		 * there will be no other way to pass it the exceptional operand
   1965  1.1        is #		 */
   1966  1.1        is #		call _real_inex();
   1967  1.1        is #	} else {
   1968  1.1        is #		restore exc state (SNAN||OPERR||OVFL||UNFL||DZ||INEX) into the FPU;
   1969  1.1        is #	}
   1970  1.1        is #
   1971  1.1        is fu_in_exc_p:
   1972  1.1        is 	subi.l		&24,%d0			# fix offset to be 0-8
   1973  1.1        is 	cmpi.b		%d0,&0x6		# is exception INEX? (6 or 7)
   1974  1.1        is 	blt.b		fu_in_exc_exit_p	# no
   1975  1.1        is 
   1976  1.1        is # the enabled exception was inexact
   1977  1.1        is 	btst		&unfl_bit,FPSR_EXCEPT(%a6) # did disabled underflow occur?
   1978  1.1        is 	bne.w		fu_in_exc_unfl_p	# yes
   1979  1.1        is 	btst		&ovfl_bit,FPSR_EXCEPT(%a6) # did disabled overflow occur?
   1980  1.1        is 	bne.w		fu_in_exc_ovfl_p	# yes
   1981  1.1        is 
   1982  1.1        is # here, we insert the correct fsave status value into the fsave frame for the
   1983  1.1        is # corresponding exception. the operand in the fsave frame should be the original
   1984  1.1        is # src operand.
   1985  1.1        is # as a reminder for future predicted pain and agony, we are passing in fsave the
   1986  1.1        is # "non-skewed" operand for cases of sgl and dbl src INFs,NANs, and DENORMs.
   1987  1.1        is # this is INCORRECT for enabled SNAN which would give to the user the skewed SNAN!!!
   1988  1.1        is fu_in_exc_exit_p:
   1989  1.1        is 	btst		&0x5,EXC_SR(%a6)	# user or supervisor?
   1990  1.1        is 	bne.w		fu_in_exc_exit_s_p	# supervisor
   1991  1.1        is 
   1992  1.1        is 	mov.l		EXC_A7(%a6),%a0		# update user a7
   1993  1.1        is 	mov.l		%a0,%usp
   1994  1.1        is 
   1995  1.1        is fu_in_exc_exit_cont_p:
   1996  1.1        is 	mov.w		(tbl_except_p.b,%pc,%d0.w*2),2+FP_SRC(%a6)
   1997  1.1        is 
   1998  1.1        is 	fmovm.x		EXC_FPREGS(%a6),&0xc0	# restore fp0/fp1
   1999  1.1        is 	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
   2000  1.1        is 	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
   2001  1.1        is 
   2002  1.1        is 	frestore	FP_SRC(%a6)		# restore src op
   2003  1.1        is 
   2004  1.1        is 	unlk		%a6
   2005  1.1        is 
   2006  1.1        is 	btst		&0x7,(%sp)		# is trace enabled?
   2007  1.1        is 	bne.w		fu_trace_p		# yes
   2008  1.1        is 
   2009  1.1        is 	bra.l		_fpsp_done
   2010  1.1        is 
   2011  1.1        is tbl_except_p:
   2012  1.1        is 	short		0xe000,0xe006,0xe004,0xe005
   2013  1.1        is 	short		0xe003,0xe002,0xe001,0xe001
   2014  1.1        is 
   2015  1.1        is fu_in_exc_ovfl_p:
   2016  1.1        is 	mov.w		&0x3,%d0
   2017  1.1        is 	bra.w		fu_in_exc_exit_p
   2018  1.1        is 
   2019  1.1        is fu_in_exc_unfl_p:
   2020  1.1        is 	mov.w		&0x4,%d0
   2021  1.1        is 	bra.w		fu_in_exc_exit_p
   2022  1.1        is 
   2023  1.1        is fu_in_exc_exit_s_p:
   2024  1.1        is 	btst		&mia7_bit,SPCOND_FLG(%a6)
   2025  1.1        is 	beq.b		fu_in_exc_exit_cont_p
   2026  1.1        is 
   2027  1.1        is 	mov.w		(tbl_except_p.b,%pc,%d0.w*2),2+FP_SRC(%a6)
   2028  1.1        is 
   2029  1.1        is 	fmovm.x		EXC_FPREGS(%a6),&0xc0	# restore fp0/fp1
   2030  1.1        is 	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
   2031  1.1        is 	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
   2032  1.1        is 
   2033  1.1        is 	frestore	FP_SRC(%a6)		# restore src op
   2034  1.1        is 
   2035  1.1        is 	unlk		%a6			# unravel stack frame
   2036  1.1        is 
   2037  1.1        is # shift stack frame "up". who cares about <ea> field.
   2038  1.1        is 	mov.l		0x4(%sp),0x10(%sp)
   2039  1.1        is 	mov.l		0x0(%sp),0xc(%sp)
   2040  1.1        is 	add.l		&0xc,%sp
   2041  1.1        is 
   2042  1.1        is 	btst		&0x7,(%sp)		# is trace on?
   2043  1.1        is 	bne.b		fu_trace_p		# yes
   2044  1.1        is 
   2045  1.1        is 	bra.l		_fpsp_done		# exit to os
   2046  1.1        is 
   2047  1.1        is #
   2048  1.1        is # The opclass two PACKED instruction that took an "Unimplemented Data Type"
   2049  1.1        is # exception was being traced. Make the "current" PC the FPIAR and put it in the
   2050  1.1        is # trace stack frame then jump to _real_trace().
   2051  1.1        is #
   2052  1.1        is #		  UNSUPP FRAME		   TRACE FRAME
   2053  1.1        is #		*****************	*****************
   2054  1.1        is #		*      EA	*	*    Current	*
   2055  1.1        is #		*		*	*      PC	*
   2056  1.1        is #		*****************	*****************
   2057  1.1        is #		* 0x2 *	0x0dc	* 	* 0x2 *  0x024	*
   2058  1.1        is #		*****************	*****************
   2059  1.1        is #		*     Next	*	*     Next	*
   2060  1.1        is #		*      PC	*      	*      PC	*
   2061  1.1        is #		*****************	*****************
   2062  1.1        is #		*      SR	*	*      SR	*
   2063  1.1        is #		*****************	*****************
   2064  1.1        is fu_trace_p:
   2065  1.1        is 	mov.w		&0x2024,0x6(%sp)
   2066  1.1        is 	fmov.l		%fpiar,0x8(%sp)
   2067  1.1        is 
   2068  1.1        is 	bra.l		_real_trace
   2069  1.1        is 
   2070  1.1        is #########################################################
   2071  1.1        is #########################################################
   2072  1.1        is fu_out_pack:
   2073  1.1        is 
   2074  1.1        is 
   2075  1.1        is # I'm not sure at this point what FPSR bits are valid for this instruction.
   2076  1.1        is # so, since the emulation routines re-create them anyways, zero exception field.
   2077  1.1        is # fmove out doesn't affect ccodes.
   2078  1.1        is 	and.l		&0xffff00ff,USER_FPSR(%a6) # zero exception field
   2079  1.1        is 
   2080  1.1        is 	fmov.l		&0x0,%fpcr		# zero current control regs
   2081  1.1        is 	fmov.l		&0x0,%fpsr
   2082  1.1        is 
   2083  1.1        is 	bfextu		EXC_CMDREG(%a6){&6:&3},%d0
   2084  1.1        is 	bsr.l		load_fpn1
   2085  1.1        is 
   2086  1.1        is # unlike other opclass 3, unimplemented data type exceptions, packed must be
   2087  1.1        is # able to detect all operand types.
   2088  1.1        is 	lea		FP_SRC(%a6),%a0
   2089  1.1        is 	bsr.l		set_tag_x		# tag the operand type
   2090  1.1        is 	cmpi.b		%d0,&UNNORM		# is operand an UNNORM?
   2091  1.1        is 	bne.b		fu_op2_p		# no
   2092  1.1        is 	bsr.l		unnorm_fix		# yes; convert to NORM,DENORM,or ZERO
   2093  1.1        is 
   2094  1.1        is fu_op2_p:
   2095  1.1        is 	mov.b		%d0,STAG(%a6)		# save src optype tag
   2096  1.1        is 
   2097  1.1        is 	clr.l		%d0
   2098  1.1        is 	mov.b		FPCR_MODE(%a6),%d0	# fetch rnd mode/prec
   2099  1.1        is 
   2100  1.1        is 	lea		FP_SRC(%a6),%a0		# pass ptr to src operand
   2101  1.1        is 
   2102  1.1        is 	mov.l		(%a6),EXC_A6(%a6)	# in case a6 changes
   2103  1.1        is 	bsr.l		fout			# call fmove out routine
   2104  1.1        is 
   2105  1.1        is # Exceptions in order of precedence:
   2106  1.1        is # 	BSUN	: no
   2107  1.1        is #	SNAN	: yes
   2108  1.1        is #	OPERR	: if ((k_factor > +17) || (dec. exp exceeds 3 digits))
   2109  1.1        is #	OVFL	: no
   2110  1.1        is #	UNFL	: no
   2111  1.1        is #	DZ	: no
   2112  1.1        is # 	INEX2	: yes
   2113  1.1        is #	INEX1	: no
   2114  1.1        is 
   2115  1.1        is # determine the highest priority exception(if any) set by the
   2116  1.1        is # emulation routine that has also been enabled by the user.
   2117  1.1        is 	mov.b		FPCR_ENABLE(%a6),%d0	# fetch exceptions enabled
   2118  1.1        is 	bne.w		fu_out_ena_p		# some are enabled
   2119  1.1        is 
   2120  1.1        is fu_out_exit_p:
   2121  1.1        is 	mov.l		EXC_A6(%a6),(%a6)	# restore a6
   2122  1.1        is 
   2123  1.1        is 	btst		&0x5,EXC_SR(%a6)	# user or supervisor?
   2124  1.1        is 	bne.b		fu_out_exit_s_p		# supervisor
   2125  1.1        is 
   2126  1.1        is 	mov.l		EXC_A7(%a6),%a0		# update user a7
   2127  1.1        is 	mov.l		%a0,%usp
   2128  1.1        is 
   2129  1.1        is fu_out_exit_cont_p:
   2130  1.1        is 	fmovm.x		EXC_FPREGS(%a6),&0xc0	# restore fp0/fp1
   2131  1.1        is 	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
   2132  1.1        is 	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
   2133  1.1        is 
   2134  1.1        is 	unlk		%a6			# unravel stack frame
   2135  1.1        is 
   2136  1.1        is 	btst		&0x7,(%sp)		# is trace on?
   2137  1.1        is 	bne.w		fu_trace_p		# yes
   2138  1.1        is 
   2139  1.1        is 	bra.l		_fpsp_done		# exit to os
   2140  1.1        is 
   2141  1.1        is # the exception occurred in supervisor mode. check to see if the
   2142  1.1        is # addressing mode was -(a7). if so, we'll need to shift the
   2143  1.1        is # stack frame "down".
   2144  1.1        is fu_out_exit_s_p:
   2145  1.1        is 	btst		&mda7_bit,SPCOND_FLG(%a6) # was ea mode -(a7)
   2146  1.1        is 	beq.b		fu_out_exit_cont_p	# no
   2147  1.1        is 
   2148  1.1        is 	fmovm.x		EXC_FPREGS(%a6),&0xc0	# restore fp0/fp1
   2149  1.1        is 	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
   2150  1.1        is 	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
   2151  1.1        is 
   2152  1.1        is 	mov.l		(%a6),%a6		# restore frame pointer
   2153  1.1        is 
   2154  1.1        is 	mov.l		LOCAL_SIZE+EXC_SR(%sp),LOCAL_SIZE+EXC_SR-0xc(%sp)
   2155  1.1        is 	mov.l		LOCAL_SIZE+2+EXC_PC(%sp),LOCAL_SIZE+2+EXC_PC-0xc(%sp)
   2156  1.1        is 
   2157  1.1        is # now, copy the result to the proper place on the stack
   2158  1.1        is 	mov.l		LOCAL_SIZE+FP_DST_EX(%sp),LOCAL_SIZE+EXC_SR+0x0(%sp)
   2159  1.1        is 	mov.l		LOCAL_SIZE+FP_DST_HI(%sp),LOCAL_SIZE+EXC_SR+0x4(%sp)
   2160  1.1        is 	mov.l		LOCAL_SIZE+FP_DST_LO(%sp),LOCAL_SIZE+EXC_SR+0x8(%sp)
   2161  1.1        is 
   2162  1.1        is 	add.l		&LOCAL_SIZE-0x8,%sp
   2163  1.1        is 
   2164  1.1        is 	btst		&0x7,(%sp)
   2165  1.1        is 	bne.w		fu_trace_p
   2166  1.1        is 
   2167  1.1        is 	bra.l		_fpsp_done
   2168  1.1        is 
   2169  1.1        is fu_out_ena_p:
   2170  1.1        is 	and.b		FPSR_EXCEPT(%a6),%d0	# keep only ones enabled
   2171  1.1        is 	bfffo		%d0{&24:&8},%d0		# find highest priority exception
   2172  1.1        is 	beq.w		fu_out_exit_p
   2173  1.1        is 
   2174  1.1        is 	mov.l		EXC_A6(%a6),(%a6)	# restore a6
   2175  1.1        is 
   2176  1.1        is # an exception occurred and that exception was enabled.
   2177  1.1        is # the only exception possible on packed move out are INEX, OPERR, and SNAN.
   2178  1.1        is fu_out_exc_p:
   2179  1.1        is 	cmpi.b		%d0,&0x1a
   2180  1.1        is 	bgt.w		fu_inex_p2
   2181  1.1        is 	beq.w		fu_operr_p
   2182  1.1        is 
   2183  1.1        is fu_snan_p:
   2184  1.1        is 	btst		&0x5,EXC_SR(%a6)
   2185  1.1        is 	bne.b		fu_snan_s_p
   2186  1.1        is 
   2187  1.1        is 	mov.l		EXC_A7(%a6),%a0
   2188  1.1        is 	mov.l		%a0,%usp
   2189  1.1        is 	bra.w		fu_snan
   2190  1.1        is 
   2191  1.1        is fu_snan_s_p:
   2192  1.1        is 	cmpi.b		SPCOND_FLG(%a6),&mda7_flg
   2193  1.1        is 	bne.w		fu_snan
   2194  1.1        is 
   2195  1.1        is # the instruction was "fmove.p fpn,-(a7)" from supervisor mode.
   2196  1.1        is # the strategy is to move the exception frame "down" 12 bytes. then, we
   2197  1.1        is # can store the default result where the exception frame was.
   2198  1.1        is 	fmovm.x		EXC_FPREGS(%a6),&0xc0	# restore fp0/fp1
   2199  1.1        is 	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
   2200  1.1        is 	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
   2201  1.1        is 
   2202  1.1        is 	mov.w		&0x30d8,EXC_VOFF(%a6)	# vector offset = 0xd0
   2203  1.1        is 	mov.w		&0xe006,2+FP_SRC(%a6) 	# set fsave status
   2204  1.1        is 
   2205  1.1        is 	frestore	FP_SRC(%a6)		# restore src operand
   2206  1.1        is 
   2207  1.1        is 	mov.l		(%a6),%a6		# restore frame pointer
   2208  1.1        is 
   2209  1.1        is 	mov.l		LOCAL_SIZE+EXC_SR(%sp),LOCAL_SIZE+EXC_SR-0xc(%sp)
   2210  1.1        is 	mov.l		LOCAL_SIZE+2+EXC_PC(%sp),LOCAL_SIZE+2+EXC_PC-0xc(%sp)
   2211  1.1        is 	mov.l		LOCAL_SIZE+EXC_EA(%sp),LOCAL_SIZE+EXC_EA-0xc(%sp)
   2212  1.1        is 
   2213  1.1        is # now, we copy the default result to it's proper location
   2214  1.1        is 	mov.l		LOCAL_SIZE+FP_DST_EX(%sp),LOCAL_SIZE+0x4(%sp)
   2215  1.1        is 	mov.l		LOCAL_SIZE+FP_DST_HI(%sp),LOCAL_SIZE+0x8(%sp)
   2216  1.1        is 	mov.l		LOCAL_SIZE+FP_DST_LO(%sp),LOCAL_SIZE+0xc(%sp)
   2217  1.1        is 
   2218  1.1        is 	add.l		&LOCAL_SIZE-0x8,%sp
   2219  1.1        is 
   2220  1.1        is 
   2221  1.1        is 	bra.l		_real_snan
   2222  1.1        is 
   2223  1.1        is fu_operr_p:
   2224  1.1        is 	btst		&0x5,EXC_SR(%a6)
   2225  1.1        is 	bne.w		fu_operr_p_s
   2226  1.1        is 
   2227  1.1        is 	mov.l		EXC_A7(%a6),%a0
   2228  1.1        is 	mov.l		%a0,%usp
   2229  1.1        is 	bra.w		fu_operr
   2230  1.1        is 
   2231  1.1        is fu_operr_p_s:
   2232  1.1        is 	cmpi.b		SPCOND_FLG(%a6),&mda7_flg
   2233  1.1        is 	bne.w		fu_operr
   2234  1.1        is 
   2235  1.1        is # the instruction was "fmove.p fpn,-(a7)" from supervisor mode.
   2236  1.1        is # the strategy is to move the exception frame "down" 12 bytes. then, we
   2237  1.1        is # can store the default result where the exception frame was.
   2238  1.1        is 	fmovm.x		EXC_FPREGS(%a6),&0xc0	# restore fp0/fp1
   2239  1.1        is 	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
   2240  1.1        is 	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
   2241  1.1        is 
   2242  1.1        is 	mov.w		&0x30d0,EXC_VOFF(%a6)	# vector offset = 0xd0
   2243  1.1        is 	mov.w		&0xe004,2+FP_SRC(%a6) 	# set fsave status
   2244  1.1        is 
   2245  1.1        is 	frestore	FP_SRC(%a6)		# restore src operand
   2246  1.1        is 
   2247  1.1        is 	mov.l		(%a6),%a6		# restore frame pointer
   2248  1.1        is 
   2249  1.1        is 	mov.l		LOCAL_SIZE+EXC_SR(%sp),LOCAL_SIZE+EXC_SR-0xc(%sp)
   2250  1.1        is 	mov.l		LOCAL_SIZE+2+EXC_PC(%sp),LOCAL_SIZE+2+EXC_PC-0xc(%sp)
   2251  1.1        is 	mov.l		LOCAL_SIZE+EXC_EA(%sp),LOCAL_SIZE+EXC_EA-0xc(%sp)
   2252  1.1        is 
   2253  1.1        is # now, we copy the default result to it's proper location
   2254  1.1        is 	mov.l		LOCAL_SIZE+FP_DST_EX(%sp),LOCAL_SIZE+0x4(%sp)
   2255  1.1        is 	mov.l		LOCAL_SIZE+FP_DST_HI(%sp),LOCAL_SIZE+0x8(%sp)
   2256  1.1        is 	mov.l		LOCAL_SIZE+FP_DST_LO(%sp),LOCAL_SIZE+0xc(%sp)
   2257  1.1        is 
   2258  1.1        is 	add.l		&LOCAL_SIZE-0x8,%sp
   2259  1.1        is 
   2260  1.1        is 
   2261  1.1        is 	bra.l		_real_operr
   2262  1.1        is 
   2263  1.1        is fu_inex_p2:
   2264  1.1        is 	btst		&0x5,EXC_SR(%a6)
   2265  1.1        is 	bne.w		fu_inex_s_p2
   2266  1.1        is 
   2267  1.1        is 	mov.l		EXC_A7(%a6),%a0
   2268  1.1        is 	mov.l		%a0,%usp
   2269  1.1        is 	bra.w		fu_inex
   2270  1.1        is 
   2271  1.1        is fu_inex_s_p2:
   2272  1.1        is 	cmpi.b		SPCOND_FLG(%a6),&mda7_flg
   2273  1.1        is 	bne.w		fu_inex
   2274  1.1        is 
   2275  1.1        is # the instruction was "fmove.p fpn,-(a7)" from supervisor mode.
   2276  1.1        is # the strategy is to move the exception frame "down" 12 bytes. then, we
   2277  1.1        is # can store the default result where the exception frame was.
   2278  1.1        is 	fmovm.x		EXC_FPREGS(%a6),&0xc0	# restore fp0/fp1
   2279  1.1        is 	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
   2280  1.1        is 	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
   2281  1.1        is 
   2282  1.1        is 	mov.w		&0x30c4,EXC_VOFF(%a6) 	# vector offset = 0xc4
   2283  1.1        is 	mov.w		&0xe001,2+FP_SRC(%a6) 	# set fsave status
   2284  1.1        is 
   2285  1.1        is 	frestore	FP_SRC(%a6)		# restore src operand
   2286  1.1        is 
   2287  1.1        is 	mov.l		(%a6),%a6		# restore frame pointer
   2288  1.1        is 
   2289  1.1        is 	mov.l		LOCAL_SIZE+EXC_SR(%sp),LOCAL_SIZE+EXC_SR-0xc(%sp)
   2290  1.1        is 	mov.l		LOCAL_SIZE+2+EXC_PC(%sp),LOCAL_SIZE+2+EXC_PC-0xc(%sp)
   2291  1.1        is 	mov.l		LOCAL_SIZE+EXC_EA(%sp),LOCAL_SIZE+EXC_EA-0xc(%sp)
   2292  1.1        is 
   2293  1.1        is # now, we copy the default result to it's proper location
   2294  1.1        is 	mov.l		LOCAL_SIZE+FP_DST_EX(%sp),LOCAL_SIZE+0x4(%sp)
   2295  1.1        is 	mov.l		LOCAL_SIZE+FP_DST_HI(%sp),LOCAL_SIZE+0x8(%sp)
   2296  1.1        is 	mov.l		LOCAL_SIZE+FP_DST_LO(%sp),LOCAL_SIZE+0xc(%sp)
   2297  1.1        is 
   2298  1.1        is 	add.l		&LOCAL_SIZE-0x8,%sp
   2299  1.1        is 
   2300  1.1        is 
   2301  1.1        is 	bra.l		_real_inex
   2302  1.1        is 
   2303  1.1        is #########################################################################
   2304  1.1        is 
   2305  1.1        is #
   2306  1.1        is # if we're stuffing a source operand back into an fsave frame then we
   2307  1.1        is # have to make sure that for single or double source operands that the
   2308  1.1        is # format stuffed is as weird as the hardware usually makes it.
   2309  1.1        is #
   2310  1.1        is 	global		funimp_skew
   2311  1.1        is funimp_skew:
   2312  1.1        is 	bfextu		EXC_EXTWORD(%a6){&3:&3},%d0 # extract src specifier
   2313  1.1        is 	cmpi.b		%d0,&0x1		# was src sgl?
   2314  1.1        is 	beq.b		funimp_skew_sgl		# yes
   2315  1.1        is 	cmpi.b		%d0,&0x5		# was src dbl?
   2316  1.1        is 	beq.b		funimp_skew_dbl		# yes
   2317  1.1        is 	rts
   2318  1.1        is 
   2319  1.1        is funimp_skew_sgl:
   2320  1.1        is 	mov.w		FP_SRC_EX(%a6),%d0	# fetch DENORM exponent
   2321  1.1        is 	andi.w		&0x7fff,%d0		# strip sign
   2322  1.1        is 	beq.b		funimp_skew_sgl_not
   2323  1.1        is 	cmpi.w		%d0,&0x3f80
   2324  1.1        is 	bgt.b		funimp_skew_sgl_not
   2325  1.1        is 	neg.w		%d0			# make exponent negative
   2326  1.1        is 	addi.w		&0x3f81,%d0		# find amt to shift
   2327  1.1        is 	mov.l		FP_SRC_HI(%a6),%d1	# fetch DENORM hi(man)
   2328  1.1        is 	lsr.l		%d0,%d1			# shift it
   2329  1.1        is 	bset		&31,%d1			# set j-bit
   2330  1.1        is 	mov.l		%d1,FP_SRC_HI(%a6)	# insert new hi(man)
   2331  1.1        is 	andi.w		&0x8000,FP_SRC_EX(%a6)	# clear old exponent
   2332  1.1        is 	ori.w		&0x3f80,FP_SRC_EX(%a6)	# insert new "skewed" exponent
   2333  1.1        is funimp_skew_sgl_not:
   2334  1.1        is 	rts
   2335  1.1        is 
   2336  1.1        is funimp_skew_dbl:
   2337  1.1        is 	mov.w		FP_SRC_EX(%a6),%d0	# fetch DENORM exponent
   2338  1.1        is 	andi.w		&0x7fff,%d0		# strip sign
   2339  1.1        is 	beq.b		funimp_skew_dbl_not
   2340  1.1        is 	cmpi.w		%d0,&0x3c00
   2341  1.1        is 	bgt.b		funimp_skew_dbl_not
   2342  1.1        is 
   2343  1.1        is 	tst.b		FP_SRC_EX(%a6)		# make "internal format"
   2344  1.1        is 	smi.b		0x2+FP_SRC(%a6)
   2345  1.1        is 	mov.w		%d0,FP_SRC_EX(%a6)	# insert exponent with cleared sign
   2346  1.1        is 	clr.l		%d0			# clear g,r,s
   2347  1.1        is 	lea		FP_SRC(%a6),%a0		# pass ptr to src op
   2348  1.1        is 	mov.w		&0x3c01,%d1		# pass denorm threshold
   2349  1.1        is 	bsr.l		dnrm_lp			# denorm it
   2350  1.1        is 	mov.w		&0x3c00,%d0		# new exponent
   2351  1.1        is 	tst.b		0x2+FP_SRC(%a6)		# is sign set?
   2352  1.1        is 	beq.b		fss_dbl_denorm_done	# no
   2353  1.1        is 	bset		&15,%d0			# set sign
   2354  1.1        is fss_dbl_denorm_done:
   2355  1.1        is 	bset		&0x7,FP_SRC_HI(%a6)	# set j-bit
   2356  1.1        is 	mov.w		%d0,FP_SRC_EX(%a6)	# insert new exponent
   2357  1.1        is funimp_skew_dbl_not:
   2358  1.1        is 	rts
   2359  1.1        is 
   2360  1.1        is #########################################################################
   2361  1.1        is 	global		_mem_write2
   2362  1.1        is _mem_write2:
   2363  1.1        is 	btst		&0x5,EXC_SR(%a6)
   2364  1.1        is 	beq.l		_dmem_write
   2365  1.1        is 	mov.l		0x0(%a0),FP_DST_EX(%a6)
   2366  1.1        is 	mov.l		0x4(%a0),FP_DST_HI(%a6)
   2367  1.1        is 	mov.l		0x8(%a0),FP_DST_LO(%a6)
   2368  1.1        is 	clr.l		%d1
   2369  1.1        is 	rts
   2370  1.1        is 
   2371  1.1        is #########################################################################
   2372  1.1        is # XDEF ****************************************************************	#
   2373  1.1        is #	_fpsp_effadd(): 060FPSP entry point for FP "Unimplemented	#
   2374  1.1        is #		     	effective address" exception.			#
   2375  1.1        is #									#
   2376  1.1        is #	This handler should be the first code executed upon taking the	#
   2377  1.1        is #	FP Unimplemented Effective Address exception in an operating	#
   2378  1.1        is #	system.								#
   2379  1.1        is #									#
   2380  1.1        is # XREF ****************************************************************	#
   2381  1.1        is #	_imem_read_long() - read instruction longword			#
   2382  1.1        is #	fix_skewed_ops() - adjust src operand in fsave frame		#
   2383  1.1        is #	set_tag_x() - determine optype of src/dst operands		#
   2384  1.1        is #	store_fpreg() - store opclass 0 or 2 result to FP regfile	#
   2385  1.1        is #	unnorm_fix() - change UNNORM operands to NORM or ZERO		#
   2386  1.1        is #	load_fpn2() - load dst operand from FP regfile			#
   2387  1.1        is #	tbl_unsupp - add of table of emulation routines for opclass 0,2	#
   2388  1.1        is #	decbin() - convert packed data to FP binary data		#
   2389  1.1        is #	_real_fpu_disabled() - "callout" for "FPU disabled" exception	#
   2390  1.1        is #	_real_access() - "callout" for access error exception		#
   2391  1.1        is #	_mem_read() - read extended immediate operand from memory	#
   2392  1.1        is #	_fpsp_done() - "callout" for exit; work all done		#
   2393  1.1        is #	_real_trace() - "callout" for Trace enabled exception		#
   2394  1.1        is #	fmovm_dynamic() - emulate dynamic fmovm instruction		#
   2395  1.1        is #	fmovm_ctrl() - emulate fmovm control instruction		#
   2396  1.1        is #									#
   2397  1.1        is # INPUT ***************************************************************	#
   2398  1.1        is #	- The system stack contains the "Unimplemented <ea>" stk frame	#
   2399  1.1        is # 									#
   2400  1.1        is # OUTPUT **************************************************************	#
   2401  1.1        is #	If access error:						#
   2402  1.1        is #	- The system stack is changed to an access error stack frame	#
   2403  1.1        is #	If FPU disabled:						#
   2404  1.1        is #	- The system stack is changed to an FPU disabled stack frame	#
   2405  1.1        is #	If Trace exception enabled:					#
   2406  1.1        is #	- The system stack is changed to a Trace exception stack frame	#
   2407  1.1        is #	Else: (normal case)						#
   2408  1.1        is #	- None (correct result has been stored as appropriate)		#
   2409  1.1        is #									#
   2410  1.1        is # ALGORITHM ***********************************************************	#
   2411  1.1        is #	This exception handles 3 types of operations:			#
   2412  1.1        is # (1) FP Instructions using extended precision or packed immediate	#
   2413  1.1        is #     addressing mode.							#
   2414  1.1        is # (2) The "fmovm.x" instruction w/ dynamic register specification.	#
   2415  1.1        is # (3) The "fmovm.l" instruction w/ 2 or 3 control registers.		#
   2416  1.1        is #									#
   2417  1.1        is #	For immediate data operations, the data is read in w/ a		#
   2418  1.1        is # _mem_read() "callout", converted to FP binary (if packed), and used	#
   2419  1.1        is # as the source operand to the instruction specified by the instruction	#
   2420  1.1        is # word. If no FP exception should be reported ads a result of the 	#
   2421  1.1        is # emulation, then the result is stored to the destination register and	#
   2422  1.1        is # the handler exits through _fpsp_done(). If an enabled exc has been	#
   2423  1.1        is # signalled as a result of emulation, then an fsave state frame		#
   2424  1.1        is # corresponding to the FP exception type must be entered into the 060	#
   2425  1.1        is # FPU before exiting. In either the enabled or disabled cases, we 	#
   2426  1.1        is # must also check if a Trace exception is pending, in which case, we	#
   2427  1.1        is # must create a Trace exception stack frame from the current exception	#
   2428  1.1        is # stack frame. If no Trace is pending, we simply exit through		#
   2429  1.1        is # _fpsp_done().								#
   2430  1.1        is #	For "fmovm.x", call the routine fmovm_dynamic() which will 	#
   2431  1.1        is # decode and emulate the instruction. No FP exceptions can be pending	#
   2432  1.1        is # as a result of this operation emulation. A Trace exception can be	#
   2433  1.1        is # pending, though, which means the current stack frame must be changed	#
   2434  1.1        is # to a Trace stack frame and an exit made through _real_trace().	#
   2435  1.1        is # For the case of "fmovm.x Dn,-(a7)", where the offending instruction	#
   2436  1.1        is # was executed from supervisor mode, this handler must store the FP	#
   2437  1.1        is # register file values to the system stack by itself since		#
   2438  1.1        is # fmovm_dynamic() can't handle this. A normal exit is made through	#
   2439  1.1        is # fpsp_done().								#
   2440  1.1        is #	For "fmovm.l", fmovm_ctrl() is used to emulate the instruction.	#
   2441  1.1        is # Again, a Trace exception may be pending and an exit made through	#
   2442  1.1        is # _real_trace(). Else, a normal exit is made through _fpsp_done().	#
   2443  1.1        is #									#
   2444  1.1        is #	Before any of the above is attempted, it must be checked to	#
   2445  1.1        is # see if the FPU is disabled. Since the "Unimp <ea>" exception is taken	#
   2446  1.1        is # before the "FPU disabled" exception, but the "FPU disabled" exception	#
   2447  1.1        is # has higher priority, we check the disabled bit in the PCR. If set,	#
   2448  1.1        is # then we must create an 8 word "FPU disabled" exception stack frame	#
   2449  1.1        is # from the current 4 word exception stack frame. This includes 		#
   2450  1.1        is # reproducing the effective address of the instruction to put on the 	#
   2451  1.1        is # new stack frame.							#
   2452  1.1        is #									#
   2453  1.1        is # 	In the process of all emulation work, if a _mem_read()		#
   2454  1.1        is # "callout" returns a failing result indicating an access error, then	#
   2455  1.1        is # we must create an access error stack frame from the current stack	#
   2456  1.1        is # frame. This information includes a faulting address and a fault-	#
   2457  1.1        is # status-longword. These are created within this handler.		#
   2458  1.1        is #									#
   2459  1.1        is #########################################################################
   2460  1.1        is 
   2461  1.1        is 	global		_fpsp_effadd
   2462  1.1        is _fpsp_effadd:
   2463  1.1        is 
   2464  1.1        is # This exception type takes priority over the "Line F Emulator"
   2465  1.1        is # exception. Therefore, the FPU could be disabled when entering here.
   2466  1.1        is # So, we must check to see if it's disabled and handle that case separately.
   2467  1.1        is 	mov.l		%d0,-(%sp)		# save d0
   2468  1.1        is 	movc		%pcr,%d0		# load proc cr
   2469  1.1        is 	btst		&0x1,%d0		# is FPU disabled?
   2470  1.1        is 	bne.w		iea_disabled		# yes
   2471  1.1        is 	mov.l		(%sp)+,%d0		# restore d0
   2472  1.1        is 
   2473  1.1        is 	link		%a6,&-LOCAL_SIZE	# init stack frame
   2474  1.1        is 
   2475  1.1        is 	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
   2476  1.1        is 	fmovm.l		%fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
   2477  1.1        is 	fmovm.x		&0xc0,EXC_FPREGS(%a6)	# save fp0-fp1 on stack
   2478  1.1        is 
   2479  1.1        is # PC of instruction that took the exception is the PC in the frame
   2480  1.1        is 	mov.l		EXC_PC(%a6),EXC_EXTWPTR(%a6)
   2481  1.1        is 
   2482  1.1        is 	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
   2483  1.1        is 	addq.l		&0x4,EXC_EXTWPTR(%a6)	# incr instruction ptr
   2484  1.1        is 	bsr.l		_imem_read_long		# fetch the instruction words
   2485  1.1        is 	mov.l		%d0,EXC_OPWORD(%a6)	# store OPWORD and EXTWORD
   2486  1.1        is 
   2487  1.1        is #########################################################################
   2488  1.1        is 
   2489  1.1        is 	tst.w		%d0			# is operation fmovem?
   2490  1.1        is 	bmi.w		iea_fmovm		# yes
   2491  1.1        is 
   2492  1.1        is #
   2493  1.1        is # here, we will have:
   2494  1.1        is # 	fabs	fdabs	fsabs		facos		fmod
   2495  1.1        is #	fadd	fdadd	fsadd		fasin		frem
   2496  1.1        is # 	fcmp				fatan		fscale
   2497  1.1        is #	fdiv	fddiv	fsdiv		fatanh		fsin
   2498  1.1        is #	fint				fcos		fsincos
   2499  1.1        is #	fintrz				fcosh		fsinh
   2500  1.1        is #	fmove	fdmove	fsmove		fetox		ftan
   2501  1.1        is # 	fmul	fdmul	fsmul		fetoxm1		ftanh
   2502  1.1        is #	fneg	fdneg	fsneg		fgetexp		ftentox
   2503  1.1        is #	fsgldiv				fgetman		ftwotox
   2504  1.1        is # 	fsglmul				flog10
   2505  1.1        is # 	fsqrt				flog2
   2506  1.1        is #	fsub	fdsub	fssub		flogn
   2507  1.1        is #	ftst				flognp1
   2508  1.1        is # which can all use f<op>.{x,p}
   2509  1.1        is # so, now it's immediate data extended precision AND PACKED FORMAT!
   2510  1.1        is #
   2511  1.1        is iea_op:
   2512  1.1        is 	andi.l		&0x00ff00ff,USER_FPSR(%a6)
   2513  1.1        is 
   2514  1.1        is 	btst		&0xa,%d0		# is src fmt x or p?
   2515  1.1        is 	bne.b		iea_op_pack		# packed
   2516  1.1        is 
   2517  1.1        is 
   2518  1.1        is 	mov.l		EXC_EXTWPTR(%a6),%a0	# pass: ptr to #<data>
   2519  1.1        is 	lea		FP_SRC(%a6),%a1		# pass: ptr to super addr
   2520  1.1        is 	mov.l		&0xc,%d0		# pass: 12 bytes
   2521  1.1        is 	bsr.l		_imem_read		# read extended immediate
   2522  1.1        is 
   2523  1.1        is 	tst.l		%d1			# did ifetch fail?
   2524  1.1        is 	bne.w		iea_iacc		# yes
   2525  1.1        is 
   2526  1.1        is 	bra.b		iea_op_setsrc
   2527  1.1        is 
   2528  1.1        is iea_op_pack:
   2529  1.1        is 
   2530  1.1        is 	mov.l		EXC_EXTWPTR(%a6),%a0	# pass: ptr to #<data>
   2531  1.1        is 	lea		FP_SRC(%a6),%a1		# pass: ptr to super dst
   2532  1.1        is 	mov.l		&0xc,%d0		# pass: 12 bytes
   2533  1.1        is 	bsr.l		_imem_read		# read packed operand
   2534  1.1        is 
   2535  1.1        is 	tst.l		%d1			# did ifetch fail?
   2536  1.1        is 	bne.w		iea_iacc		# yes
   2537  1.1        is 
   2538  1.1        is # The packed operand is an INF or a NAN if the exponent field is all ones.
   2539  1.1        is 	bfextu		FP_SRC(%a6){&1:&15},%d0	# get exp
   2540  1.1        is 	cmpi.w		%d0,&0x7fff		# INF or NAN?
   2541  1.1        is 	beq.b		iea_op_setsrc		# operand is an INF or NAN
   2542  1.1        is 
   2543  1.1        is # The packed operand is a zero if the mantissa is all zero, else it's
   2544  1.1        is # a normal packed op.
   2545  1.1        is 	mov.b		3+FP_SRC(%a6),%d0	# get byte 4
   2546  1.1        is 	andi.b		&0x0f,%d0		# clear all but last nybble
   2547  1.1        is 	bne.b		iea_op_gp_not_spec	# not a zero
   2548  1.1        is 	tst.l		FP_SRC_HI(%a6)		# is lw 2 zero?
   2549  1.1        is 	bne.b		iea_op_gp_not_spec	# not a zero
   2550  1.1        is 	tst.l		FP_SRC_LO(%a6)		# is lw 3 zero?
   2551  1.1        is 	beq.b		iea_op_setsrc		# operand is a ZERO
   2552  1.1        is iea_op_gp_not_spec:
   2553  1.1        is 	lea		FP_SRC(%a6),%a0		# pass: ptr to packed op
   2554  1.1        is 	bsr.l		decbin			# convert to extended
   2555  1.1        is 	fmovm.x		&0x80,FP_SRC(%a6)	# make this the srcop
   2556  1.1        is 
   2557  1.1        is iea_op_setsrc:
   2558  1.1        is 	addi.l		&0xc,EXC_EXTWPTR(%a6)	# update extension word pointer
   2559  1.1        is 
   2560  1.1        is # FP_SRC now holds the src operand.
   2561  1.1        is 	lea		FP_SRC(%a6),%a0		# pass: ptr to src op
   2562  1.1        is 	bsr.l		set_tag_x		# tag the operand type
   2563  1.1        is 	mov.b		%d0,STAG(%a6)		# could be ANYTHING!!!
   2564  1.1        is 	cmpi.b		%d0,&UNNORM		# is operand an UNNORM?
   2565  1.1        is 	bne.b		iea_op_getdst		# no
   2566  1.1        is 	bsr.l		unnorm_fix		# yes; convert to NORM/DENORM/ZERO
   2567  1.1        is 	mov.b		%d0,STAG(%a6)		# set new optype tag
   2568  1.1        is iea_op_getdst:
   2569  1.1        is 	clr.b		STORE_FLG(%a6)		# clear "store result" boolean
   2570  1.1        is 
   2571  1.1        is 	btst		&0x5,1+EXC_CMDREG(%a6)	# is operation monadic or dyadic?
   2572  1.1        is 	beq.b		iea_op_extract		# monadic
   2573  1.1        is 	btst		&0x4,1+EXC_CMDREG(%a6)	# is operation fsincos,ftst,fcmp?
   2574  1.1        is 	bne.b		iea_op_spec		# yes
   2575  1.1        is 
   2576  1.1        is iea_op_loaddst:
   2577  1.1        is 	bfextu		EXC_CMDREG(%a6){&6:&3},%d0 # fetch dst regno
   2578  1.1        is 	bsr.l		load_fpn2		# load dst operand
   2579  1.1        is 
   2580  1.1        is 	lea		FP_DST(%a6),%a0		# pass: ptr to dst op
   2581  1.1        is 	bsr.l		set_tag_x		# tag the operand type
   2582  1.1        is 	mov.b		%d0,DTAG(%a6)		# could be ANYTHING!!!
   2583  1.1        is 	cmpi.b		%d0,&UNNORM		# is operand an UNNORM?
   2584  1.1        is 	bne.b		iea_op_extract		# no
   2585  1.1        is 	bsr.l		unnorm_fix		# yes; convert to NORM/DENORM/ZERO
   2586  1.1        is 	mov.b		%d0,DTAG(%a6)		# set new optype tag
   2587  1.1        is 	bra.b		iea_op_extract
   2588  1.1        is 
   2589  1.1        is # the operation is fsincos, ftst, or fcmp. only fcmp is dyadic
   2590  1.1        is iea_op_spec:
   2591  1.1        is 	btst		&0x3,1+EXC_CMDREG(%a6)	# is operation fsincos?
   2592  1.1        is 	beq.b		iea_op_extract		# yes
   2593  1.1        is # now, we're left with ftst and fcmp. so, first let's tag them so that they don't
   2594  1.1        is # store a result. then, only fcmp will branch back and pick up a dst operand.
   2595  1.1        is 	st		STORE_FLG(%a6)		# don't store a final result
   2596  1.1        is 	btst		&0x1,1+EXC_CMDREG(%a6)	# is operation fcmp?
   2597  1.1        is 	beq.b		iea_op_loaddst		# yes
   2598  1.1        is 
   2599  1.1        is iea_op_extract:
   2600  1.1        is 	clr.l		%d0
   2601  1.1        is 	mov.b		FPCR_MODE(%a6),%d0	# pass: rnd mode,prec
   2602  1.1        is 
   2603  1.1        is 	mov.b		1+EXC_CMDREG(%a6),%d1
   2604  1.1        is 	andi.w		&0x007f,%d1		# extract extension
   2605  1.1        is 
   2606  1.1        is 	fmov.l		&0x0,%fpcr
   2607  1.1        is 	fmov.l		&0x0,%fpsr
   2608  1.1        is 
   2609  1.1        is 	lea		FP_SRC(%a6),%a0
   2610  1.1        is 	lea		FP_DST(%a6),%a1
   2611  1.1        is 
   2612  1.1        is 	mov.l		(tbl_unsupp.l,%pc,%d1.w*4),%d1 # fetch routine addr
   2613  1.1        is 	jsr		(tbl_unsupp.l,%pc,%d1.l*1)
   2614  1.1        is 
   2615  1.1        is #
   2616  1.1        is # Exceptions in order of precedence:
   2617  1.1        is #	BSUN	: none
   2618  1.1        is #	SNAN	: all operations
   2619  1.1        is #	OPERR	: all reg-reg or mem-reg operations that can normally operr
   2620  1.1        is #	OVFL	: same as OPERR
   2621  1.1        is #	UNFL	: same as OPERR
   2622  1.1        is #	DZ	: same as OPERR
   2623  1.1        is #	INEX2	: same as OPERR
   2624  1.1        is #	INEX1	: all packed immediate operations
   2625  1.1        is #
   2626  1.1        is 
   2627  1.1        is # we determine the highest priority exception(if any) set by the
   2628  1.1        is # emulation routine that has also been enabled by the user.
   2629  1.1        is 	mov.b		FPCR_ENABLE(%a6),%d0	# fetch exceptions enabled
   2630  1.1        is 	bne.b		iea_op_ena		# some are enabled
   2631  1.1        is 
   2632  1.1        is # now, we save the result, unless, of course, the operation was ftst or fcmp.
   2633  1.1        is # these don't save results.
   2634  1.1        is iea_op_save:
   2635  1.1        is 	tst.b		STORE_FLG(%a6)		# does this op store a result?
   2636  1.1        is 	bne.b		iea_op_exit1		# exit with no frestore
   2637  1.1        is 
   2638  1.1        is iea_op_store:
   2639  1.1        is 	bfextu		EXC_CMDREG(%a6){&6:&3},%d0 # fetch dst regno
   2640  1.1        is 	bsr.l		store_fpreg		# store the result
   2641  1.1        is 
   2642  1.1        is iea_op_exit1:
   2643  1.1        is 	mov.l		EXC_PC(%a6),USER_FPIAR(%a6) # set FPIAR to "Current PC"
   2644  1.1        is 	mov.l		EXC_EXTWPTR(%a6),EXC_PC(%a6) # set "Next PC" in exc frame
   2645  1.1        is 
   2646  1.1        is 	fmovm.x		EXC_FPREGS(%a6),&0xc0	# restore fp0-fp1
   2647  1.1        is 	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
   2648  1.1        is 	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
   2649  1.1        is 
   2650  1.1        is 	unlk		%a6			# unravel the frame
   2651  1.1        is 
   2652  1.1        is 	btst		&0x7,(%sp)		# is trace on?
   2653  1.1        is 	bne.w		iea_op_trace		# yes
   2654  1.1        is 
   2655  1.1        is 	bra.l		_fpsp_done		# exit to os
   2656  1.1        is 
   2657  1.1        is iea_op_ena:
   2658  1.1        is 	and.b		FPSR_EXCEPT(%a6),%d0	# keep only ones enable and set
   2659  1.1        is 	bfffo		%d0{&24:&8},%d0		# find highest priority exception
   2660  1.1        is 	bne.b		iea_op_exc		# at least one was set
   2661  1.1        is 
   2662  1.1        is # no exception occurred. now, did a disabled, exact overflow occur with inexact
   2663  1.1        is # enabled? if so, then we have to stuff an overflow frame into the FPU.
   2664  1.1        is 	btst		&ovfl_bit,FPSR_EXCEPT(%a6) # did overflow occur?
   2665  1.1        is 	beq.b		iea_op_save
   2666  1.1        is 
   2667  1.1        is iea_op_ovfl:
   2668  1.1        is 	btst		&inex2_bit,FPCR_ENABLE(%a6) # is inexact enabled?
   2669  1.1        is 	beq.b		iea_op_store		# no
   2670  1.1        is 	bra.b		iea_op_exc_ovfl		# yes
   2671  1.1        is 
   2672  1.1        is # an enabled exception occurred. we have to insert the exception type back into
   2673  1.1        is # the machine.
   2674  1.1        is iea_op_exc:
   2675  1.1        is 	subi.l		&24,%d0			# fix offset to be 0-8
   2676  1.1        is 	cmpi.b		%d0,&0x6		# is exception INEX?
   2677  1.1        is 	bne.b		iea_op_exc_force	# no
   2678  1.1        is 
   2679  1.1        is # the enabled exception was inexact. so, if it occurs with an overflow
   2680  1.1        is # or underflow that was disabled, then we have to force an overflow or
   2681  1.1        is # underflow frame.
   2682  1.1        is 	btst		&ovfl_bit,FPSR_EXCEPT(%a6) # did overflow occur?
   2683  1.1        is 	bne.b		iea_op_exc_ovfl		# yes
   2684  1.1        is 	btst		&unfl_bit,FPSR_EXCEPT(%a6) # did underflow occur?
   2685  1.1        is 	bne.b		iea_op_exc_unfl		# yes
   2686  1.1        is 
   2687  1.1        is iea_op_exc_force:
   2688  1.1        is 	mov.w		(tbl_iea_except.b,%pc,%d0.w*2),2+FP_SRC(%a6)
   2689  1.1        is 	bra.b		iea_op_exit2		# exit with frestore
   2690  1.1        is 
   2691  1.1        is tbl_iea_except:
   2692  1.1        is 	short		0xe002, 0xe006, 0xe004, 0xe005
   2693  1.1        is 	short		0xe003, 0xe002, 0xe001, 0xe001
   2694  1.1        is 
   2695  1.1        is iea_op_exc_ovfl:
   2696  1.1        is 	mov.w		&0xe005,2+FP_SRC(%a6)
   2697  1.1        is 	bra.b		iea_op_exit2
   2698  1.1        is 
   2699  1.1        is iea_op_exc_unfl:
   2700  1.1        is 	mov.w		&0xe003,2+FP_SRC(%a6)
   2701  1.1        is 
   2702  1.1        is iea_op_exit2:
   2703  1.1        is 	mov.l		EXC_PC(%a6),USER_FPIAR(%a6) # set FPIAR to "Current PC"
   2704  1.1        is 	mov.l		EXC_EXTWPTR(%a6),EXC_PC(%a6) # set "Next PC" in exc frame
   2705  1.1        is 
   2706  1.1        is 	fmovm.x		EXC_FPREGS(%a6),&0xc0	# restore fp0-fp1
   2707  1.1        is 	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
   2708  1.1        is 	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
   2709  1.1        is 
   2710  1.1        is 	frestore 	FP_SRC(%a6)		# restore exceptional state
   2711  1.1        is 
   2712  1.1        is 	unlk		%a6			# unravel the frame
   2713  1.1        is 
   2714  1.1        is 	btst		&0x7,(%sp)		# is trace on?
   2715  1.1        is 	bne.b		iea_op_trace		# yes
   2716  1.1        is 
   2717  1.1        is 	bra.l		_fpsp_done		# exit to os
   2718  1.1        is 
   2719  1.1        is #
   2720  1.1        is # The opclass two instruction that took an "Unimplemented Effective Address"
   2721  1.1        is # exception was being traced. Make the "current" PC the FPIAR and put it in
   2722  1.1        is # the trace stack frame then jump to _real_trace().
   2723  1.1        is #
   2724  1.1        is #		 UNIMP EA FRAME		   TRACE FRAME
   2725  1.1        is #		*****************	*****************
   2726  1.1        is #		* 0x0 *  0x0f0	*	*    Current	*
   2727  1.1        is #		*****************	*      PC	*
   2728  1.1        is #		*    Current	*	*****************
   2729  1.1        is #		*      PC	*	* 0x2 *  0x024	*
   2730  1.1        is #		*****************	*****************
   2731  1.1        is #		*      SR	*	*     Next	*
   2732  1.1        is #		*****************	*      PC	*
   2733  1.1        is #					*****************
   2734  1.1        is #					*      SR	*
   2735  1.1        is #					*****************
   2736  1.1        is iea_op_trace:
   2737  1.1        is 	mov.l		(%sp),-(%sp)		# shift stack frame "down"
   2738  1.1        is 	mov.w		0x8(%sp),0x4(%sp)
   2739  1.1        is 	mov.w		&0x2024,0x6(%sp)	# stk fmt = 0x2; voff = 0x024
   2740  1.1        is 	fmov.l		%fpiar,0x8(%sp)		# "Current PC" is in FPIAR
   2741  1.1        is 
   2742  1.1        is 	bra.l		_real_trace
   2743  1.1        is 
   2744  1.1        is #########################################################################
   2745  1.1        is iea_fmovm:
   2746  1.1        is 	btst		&14,%d0			# ctrl or data reg
   2747  1.1        is 	beq.w		iea_fmovm_ctrl
   2748  1.1        is 
   2749  1.1        is iea_fmovm_data:
   2750  1.1        is 
   2751  1.1        is 	btst		&0x5,EXC_SR(%a6)	# user or supervisor mode
   2752  1.1        is 	bne.b		iea_fmovm_data_s
   2753  1.1        is 
   2754  1.1        is iea_fmovm_data_u:
   2755  1.1        is 	mov.l		%usp,%a0
   2756  1.1        is 	mov.l		%a0,EXC_A7(%a6)		# store current a7
   2757  1.1        is 	bsr.l		fmovm_dynamic		# do dynamic fmovm
   2758  1.1        is 	mov.l		EXC_A7(%a6),%a0		# load possibly new a7
   2759  1.1        is 	mov.l		%a0,%usp		# update usp
   2760  1.1        is 	bra.w		iea_fmovm_exit
   2761  1.1        is 
   2762  1.1        is iea_fmovm_data_s:
   2763  1.1        is 	clr.b		SPCOND_FLG(%a6)
   2764  1.1        is 	lea		0x2+EXC_VOFF(%a6),%a0
   2765  1.1        is 	mov.l		%a0,EXC_A7(%a6)
   2766  1.1        is 	bsr.l		fmovm_dynamic		# do dynamic fmovm
   2767  1.1        is 
   2768  1.1        is 	cmpi.b		SPCOND_FLG(%a6),&mda7_flg
   2769  1.1        is 	beq.w		iea_fmovm_data_predec
   2770  1.1        is 	cmpi.b		SPCOND_FLG(%a6),&mia7_flg
   2771  1.1        is 	bne.w		iea_fmovm_exit
   2772  1.1        is 
   2773  1.1        is # right now, d0 = the size.
   2774  1.1        is # the data has been fetched from the supervisor stack, but we have not
   2775  1.1        is # incremented the stack pointer by the appropriate number of bytes.
   2776  1.1        is # do it here.
   2777  1.1        is iea_fmovm_data_postinc:
   2778  1.1        is 	btst		&0x7,EXC_SR(%a6)
   2779  1.1        is 	bne.b		iea_fmovm_data_pi_trace
   2780  1.1        is 
   2781  1.1        is 	mov.w		EXC_SR(%a6),(EXC_SR,%a6,%d0)
   2782  1.1        is 	mov.l		EXC_EXTWPTR(%a6),(EXC_PC,%a6,%d0)
   2783  1.1        is 	mov.w		&0x00f0,(EXC_VOFF,%a6,%d0)
   2784  1.1        is 
   2785  1.1        is 	lea		(EXC_SR,%a6,%d0),%a0
   2786  1.1        is 	mov.l		%a0,EXC_SR(%a6)
   2787  1.1        is 
   2788  1.1        is 	fmovm.x		EXC_FP0(%a6),&0xc0	# restore fp0-fp1
   2789  1.1        is 	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
   2790  1.1        is  	movm.l		EXC_DREGS(%a6),&0x0303 	# restore d0-d1/a0-a1
   2791  1.1        is 
   2792  1.1        is 	unlk		%a6
   2793  1.1        is 	mov.l		(%sp)+,%sp
   2794  1.1        is 	bra.l		_fpsp_done
   2795  1.1        is 
   2796  1.1        is iea_fmovm_data_pi_trace:
   2797  1.1        is 	mov.w		EXC_SR(%a6),(EXC_SR-0x4,%a6,%d0)
   2798  1.1        is 	mov.l		EXC_EXTWPTR(%a6),(EXC_PC-0x4,%a6,%d0)
   2799  1.1        is 	mov.w		&0x2024,(EXC_VOFF-0x4,%a6,%d0)
   2800  1.1        is 	mov.l		EXC_PC(%a6),(EXC_VOFF+0x2-0x4,%a6,%d0)
   2801  1.1        is 
   2802  1.1        is 	lea		(EXC_SR-0x4,%a6,%d0),%a0
   2803  1.1        is 	mov.l		%a0,EXC_SR(%a6)
   2804  1.1        is 
   2805  1.1        is 	fmovm.x		EXC_FP0(%a6),&0xc0	# restore fp0-fp1
   2806  1.1        is 	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
   2807  1.1        is  	movm.l		EXC_DREGS(%a6),&0x0303 	# restore d0-d1/a0-a1
   2808  1.1        is 
   2809  1.1        is 	unlk		%a6
   2810  1.1        is 	mov.l		(%sp)+,%sp
   2811  1.1        is 	bra.l		_real_trace
   2812  1.1        is 
   2813  1.1        is # right now, d1 = size and d0 = the strg.
   2814  1.1        is iea_fmovm_data_predec:
   2815  1.1        is 	mov.b		%d1,EXC_VOFF(%a6)	# store strg
   2816  1.1        is 	mov.b		%d0,0x1+EXC_VOFF(%a6)	# store size
   2817  1.1        is 
   2818  1.1        is 	fmovm.x		EXC_FP0(%a6),&0xc0	# restore fp0-fp1
   2819  1.1        is 	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
   2820  1.1        is  	movm.l		EXC_DREGS(%a6),&0x0303 	# restore d0-d1/a0-a1
   2821  1.1        is 
   2822  1.1        is 	mov.l		(%a6),-(%sp)		# make a copy of a6
   2823  1.1        is 	mov.l		%d0,-(%sp)		# save d0
   2824  1.1        is 	mov.l		%d1,-(%sp)		# save d1
   2825  1.1        is 	mov.l		EXC_EXTWPTR(%a6),-(%sp)	# make a copy of Next PC
   2826  1.1        is 
   2827  1.1        is 	clr.l		%d0
   2828  1.1        is 	mov.b		0x1+EXC_VOFF(%a6),%d0	# fetch size
   2829  1.1        is 	neg.l		%d0			# get negative of size
   2830  1.1        is 
   2831  1.1        is 	btst		&0x7,EXC_SR(%a6)	# is trace enabled?
   2832  1.1        is 	beq.b		iea_fmovm_data_p2
   2833  1.1        is 
   2834  1.1        is 	mov.w		EXC_SR(%a6),(EXC_SR-0x4,%a6,%d0)
   2835  1.1        is 	mov.l		EXC_PC(%a6),(EXC_VOFF-0x2,%a6,%d0)
   2836  1.1        is 	mov.l		(%sp)+,(EXC_PC-0x4,%a6,%d0)
   2837  1.1        is 	mov.w		&0x2024,(EXC_VOFF-0x4,%a6,%d0)
   2838  1.1        is 
   2839  1.1        is 	pea		(%a6,%d0)		# create final sp
   2840  1.1        is 	bra.b		iea_fmovm_data_p3
   2841  1.1        is 
   2842  1.1        is iea_fmovm_data_p2:
   2843  1.1        is 	mov.w		EXC_SR(%a6),(EXC_SR,%a6,%d0)
   2844  1.1        is 	mov.l		(%sp)+,(EXC_PC,%a6,%d0)
   2845  1.1        is 	mov.w		&0x00f0,(EXC_VOFF,%a6,%d0)
   2846  1.1        is 
   2847  1.1        is 	pea		(0x4,%a6,%d0)		# create final sp
   2848  1.1        is 
   2849  1.1        is iea_fmovm_data_p3:
   2850  1.1        is 	clr.l		%d1
   2851  1.1        is 	mov.b		EXC_VOFF(%a6),%d1	# fetch strg
   2852  1.1        is 
   2853  1.1        is 	tst.b		%d1
   2854  1.1        is 	bpl.b		fm_1
   2855  1.1        is 	fmovm.x		&0x80,(0x4+0x8,%a6,%d0)
   2856  1.1        is 	addi.l		&0xc,%d0
   2857  1.1        is fm_1:
   2858  1.1        is 	lsl.b		&0x1,%d1
   2859  1.1        is 	bpl.b		fm_2
   2860  1.1        is 	fmovm.x		&0x40,(0x4+0x8,%a6,%d0)
   2861  1.1        is 	addi.l		&0xc,%d0
   2862  1.1        is fm_2:
   2863  1.1        is 	lsl.b		&0x1,%d1
   2864  1.1        is 	bpl.b		fm_3
   2865  1.1        is 	fmovm.x		&0x20,(0x4+0x8,%a6,%d0)
   2866  1.1        is 	addi.l		&0xc,%d0
   2867  1.1        is fm_3:
   2868  1.1        is 	lsl.b		&0x1,%d1
   2869  1.1        is 	bpl.b		fm_4
   2870  1.1        is 	fmovm.x		&0x10,(0x4+0x8,%a6,%d0)
   2871  1.1        is 	addi.l		&0xc,%d0
   2872  1.1        is fm_4:
   2873  1.1        is 	lsl.b		&0x1,%d1
   2874  1.1        is 	bpl.b		fm_5
   2875  1.1        is 	fmovm.x		&0x08,(0x4+0x8,%a6,%d0)
   2876  1.1        is 	addi.l		&0xc,%d0
   2877  1.1        is fm_5:
   2878  1.1        is 	lsl.b		&0x1,%d1
   2879  1.1        is 	bpl.b		fm_6
   2880  1.1        is 	fmovm.x		&0x04,(0x4+0x8,%a6,%d0)
   2881  1.1        is 	addi.l		&0xc,%d0
   2882  1.1        is fm_6:
   2883  1.1        is 	lsl.b		&0x1,%d1
   2884  1.1        is 	bpl.b		fm_7
   2885  1.1        is 	fmovm.x		&0x02,(0x4+0x8,%a6,%d0)
   2886  1.1        is 	addi.l		&0xc,%d0
   2887  1.1        is fm_7:
   2888  1.1        is 	lsl.b		&0x1,%d1
   2889  1.1        is 	bpl.b		fm_end
   2890  1.1        is 	fmovm.x		&0x01,(0x4+0x8,%a6,%d0)
   2891  1.1        is fm_end:
   2892  1.1        is 	mov.l		0x4(%sp),%d1
   2893  1.1        is 	mov.l		0x8(%sp),%d0
   2894  1.1        is 	mov.l		0xc(%sp),%a6
   2895  1.1        is 	mov.l		(%sp)+,%sp
   2896  1.1        is 
   2897  1.1        is 	btst		&0x7,(%sp)		# is trace enabled?
   2898  1.1        is 	beq.l		_fpsp_done
   2899  1.1        is 	bra.l		_real_trace
   2900  1.1        is 
   2901  1.1        is #########################################################################
   2902  1.1        is iea_fmovm_ctrl:
   2903  1.1        is 
   2904  1.1        is 	bsr.l		fmovm_ctrl		# load ctrl regs
   2905  1.1        is 
   2906  1.1        is iea_fmovm_exit:
   2907  1.1        is 	fmovm.x		EXC_FPREGS(%a6),&0xc0	# restore fp0-fp1
   2908  1.1        is 	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
   2909  1.1        is 	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
   2910  1.1        is 
   2911  1.1        is 	btst		&0x7,EXC_SR(%a6)	# is trace on?
   2912  1.1        is 	bne.b		iea_fmovm_trace		# yes
   2913  1.1        is 
   2914  1.1        is 	mov.l		EXC_EXTWPTR(%a6),EXC_PC(%a6) # set Next PC
   2915  1.1        is 
   2916  1.1        is 	unlk		%a6			# unravel the frame
   2917  1.1        is 
   2918  1.1        is 	bra.l		_fpsp_done		# exit to os
   2919  1.1        is 
   2920  1.1        is #
   2921  1.1        is # The control reg instruction that took an "Unimplemented Effective Address"
   2922  1.1        is # exception was being traced. The "Current PC" for the trace frame is the
   2923  1.1        is # PC stacked for Unimp EA. The "Next PC" is in EXC_EXTWPTR.
   2924  1.1        is # After fixing the stack frame, jump to _real_trace().
   2925  1.1        is #
   2926  1.1        is #		 UNIMP EA FRAME		   TRACE FRAME
   2927  1.1        is #		*****************	*****************
   2928  1.1        is #		* 0x0 *  0x0f0	*	*    Current	*
   2929  1.1        is #		*****************	*      PC	*
   2930  1.1        is #		*    Current	*	*****************
   2931  1.1        is #		*      PC	*	* 0x2 *  0x024	*
   2932  1.1        is #		*****************	*****************
   2933  1.1        is #		*      SR	*	*     Next	*
   2934  1.1        is #		*****************	*      PC	*
   2935  1.1        is #					*****************
   2936  1.1        is #					*      SR	*
   2937  1.1        is #					*****************
   2938  1.1        is # this ain't a pretty solution, but it works:
   2939  1.1        is # -restore a6 (not with unlk)
   2940  1.1        is # -shift stack frame down over where old a6 used to be
   2941  1.1        is # -add LOCAL_SIZE to stack pointer
   2942  1.1        is iea_fmovm_trace:
   2943  1.1        is 	mov.l		(%a6),%a6		# restore frame pointer
   2944  1.1        is 	mov.w		EXC_SR+LOCAL_SIZE(%sp),0x0+LOCAL_SIZE(%sp)
   2945  1.1        is 	mov.l		EXC_PC+LOCAL_SIZE(%sp),0x8+LOCAL_SIZE(%sp)
   2946  1.1        is 	mov.l		EXC_EXTWPTR+LOCAL_SIZE(%sp),0x2+LOCAL_SIZE(%sp)
   2947  1.1        is 	mov.w		&0x2024,0x6+LOCAL_SIZE(%sp) # stk fmt = 0x2; voff = 0x024
   2948  1.1        is 	add.l		&LOCAL_SIZE,%sp		# clear stack frame
   2949  1.1        is 
   2950  1.1        is 	bra.l		_real_trace
   2951  1.1        is 
   2952  1.1        is #########################################################################
   2953  1.1        is # The FPU is disabled and so we should really have taken the "Line
   2954  1.1        is # F Emulator" exception. So, here we create an 8-word stack frame
   2955  1.1        is # from our 4-word stack frame. This means we must calculate the length
   2956  1.1        is # of the faulting instruction to get the "next PC". This is trivial for
   2957  1.1        is # immediate operands but requires some extra work for fmovm dynamic
   2958  1.1        is # which can use most addressing modes.
   2959  1.1        is iea_disabled:
   2960  1.1        is 	mov.l		(%sp)+,%d0		# restore d0
   2961  1.1        is 
   2962  1.1        is 	link		%a6,&-LOCAL_SIZE	# init stack frame
   2963  1.1        is 
   2964  1.1        is 	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
   2965  1.1        is 
   2966  1.1        is # PC of instruction that took the exception is the PC in the frame
   2967  1.1        is 	mov.l		EXC_PC(%a6),EXC_EXTWPTR(%a6)
   2968  1.1        is 	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
   2969  1.1        is 	addq.l		&0x4,EXC_EXTWPTR(%a6)	# incr instruction ptr
   2970  1.1        is 	bsr.l		_imem_read_long		# fetch the instruction words
   2971  1.1        is 	mov.l		%d0,EXC_OPWORD(%a6)	# store OPWORD and EXTWORD
   2972  1.1        is 
   2973  1.1        is 	tst.w		%d0			# is instr fmovm?
   2974  1.1        is 	bmi.b		iea_dis_fmovm		# yes
   2975  1.1        is # instruction is using an extended precision immediate operand. therefore,
   2976  1.1        is # the total instruction length is 16 bytes.
   2977  1.1        is iea_dis_immed:
   2978  1.1        is 	mov.l		&0x10,%d0		# 16 bytes of instruction
   2979  1.1        is 	bra.b		iea_dis_cont
   2980  1.1        is iea_dis_fmovm:
   2981  1.1        is 	btst		&0xe,%d0		# is instr fmovm ctrl
   2982  1.1        is 	bne.b		iea_dis_fmovm_data	# no
   2983  1.1        is # the instruction is a fmovm.l with 2 or 3 registers.
   2984  1.1        is 	bfextu		%d0{&19:&3},%d1
   2985  1.1        is 	mov.l		&0xc,%d0
   2986  1.1        is 	cmpi.b		%d1,&0x7		# move all regs?
   2987  1.1        is 	bne.b		iea_dis_cont
   2988  1.1        is 	addq.l		&0x4,%d0
   2989  1.1        is 	bra.b		iea_dis_cont
   2990  1.1        is # the instruction is an fmovm.x dynamic which can use many addressing
   2991  1.1        is # modes and thus can have several different total instruction lengths.
   2992  1.1        is # call fmovm_calc_ea which will go through the ea calc process and,
   2993  1.1        is # as a by-product, will tell us how long the instruction is.
   2994  1.1        is iea_dis_fmovm_data:
   2995  1.1        is 	clr.l		%d0
   2996  1.1        is 	bsr.l		fmovm_calc_ea
   2997  1.1        is 	mov.l		EXC_EXTWPTR(%a6),%d0
   2998  1.1        is 	sub.l		EXC_PC(%a6),%d0
   2999  1.1        is iea_dis_cont:
   3000  1.1        is 	mov.w		%d0,EXC_VOFF(%a6)	# store stack shift value
   3001  1.1        is 
   3002  1.1        is 	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
   3003  1.1        is 
   3004  1.1        is 	unlk		%a6
   3005  1.1        is 
   3006  1.1        is # here, we actually create the 8-word frame from the 4-word frame,
   3007  1.1        is # with the "next PC" as additional info.
   3008  1.1        is # the <ea> field is let as undefined.
   3009  1.1        is 	subq.l		&0x8,%sp		# make room for new stack
   3010  1.1        is 	mov.l		%d0,-(%sp)		# save d0
   3011  1.1        is 	mov.w		0xc(%sp),0x4(%sp)	# move SR
   3012  1.1        is 	mov.l		0xe(%sp),0x6(%sp)	# move Current PC
   3013  1.1        is 	clr.l		%d0
   3014  1.1        is 	mov.w		0x12(%sp),%d0
   3015  1.1        is 	mov.l		0x6(%sp),0x10(%sp)	# move Current PC
   3016  1.1        is 	add.l		%d0,0x6(%sp)		# make Next PC
   3017  1.1        is 	mov.w		&0x402c,0xa(%sp)	# insert offset,frame format
   3018  1.1        is 	mov.l		(%sp)+,%d0		# restore d0
   3019  1.1        is 
   3020  1.1        is 	bra.l		_real_fpu_disabled
   3021  1.1        is 
   3022  1.1        is ##########
   3023  1.1        is 
   3024  1.1        is iea_iacc:
   3025  1.1        is 	movc		%pcr,%d0
   3026  1.1        is 	btst		&0x1,%d0
   3027  1.1        is 	bne.b		iea_iacc_cont
   3028  1.1        is 	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
   3029  1.1        is 	fmovm.x		EXC_FPREGS(%a6),&0xc0	# restore fp0-fp1 on stack
   3030  1.1        is iea_iacc_cont:
   3031  1.1        is 	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
   3032  1.1        is 
   3033  1.1        is 	unlk		%a6
   3034  1.1        is 
   3035  1.1        is 	subq.w		&0x8,%sp		# make stack frame bigger
   3036  1.1        is 	mov.l		0x8(%sp),(%sp)		# store SR,hi(PC)
   3037  1.1        is 	mov.w		0xc(%sp),0x4(%sp)	# store lo(PC)
   3038  1.1        is 	mov.w		&0x4008,0x6(%sp)	# store voff
   3039  1.1        is 	mov.l		0x2(%sp),0x8(%sp)	# store ea
   3040  1.1        is 	mov.l		&0x09428001,0xc(%sp)	# store fslw
   3041  1.1        is 
   3042  1.1        is iea_acc_done:
   3043  1.1        is 	btst		&0x5,(%sp)		# user or supervisor mode?
   3044  1.1        is 	beq.b		iea_acc_done2		# user
   3045  1.1        is 	bset		&0x2,0xd(%sp)		# set supervisor TM bit
   3046  1.1        is 
   3047  1.1        is iea_acc_done2:
   3048  1.1        is 	bra.l		_real_access
   3049  1.1        is 
   3050  1.1        is iea_dacc:
   3051  1.1        is 	lea		-LOCAL_SIZE(%a6),%sp
   3052  1.1        is 
   3053  1.1        is 	movc		%pcr,%d1
   3054  1.1        is 	btst		&0x1,%d1
   3055  1.1        is 	bne.b		iea_dacc_cont
   3056  1.1        is 	fmovm.x		EXC_FPREGS(%a6),&0xc0	# restore fp0-fp1 on stack
   3057  1.1        is 	fmovm.l		LOCAL_SIZE+USER_FPCR(%sp),%fpcr,%fpsr,%fpiar # restore ctrl regs
   3058  1.1        is iea_dacc_cont:
   3059  1.1        is 	mov.l		(%a6),%a6
   3060  1.1        is 
   3061  1.1        is 	mov.l		0x4+LOCAL_SIZE(%sp),-0x8+0x4+LOCAL_SIZE(%sp)
   3062  1.1        is 	mov.w		0x8+LOCAL_SIZE(%sp),-0x8+0x8+LOCAL_SIZE(%sp)
   3063  1.1        is 	mov.w		&0x4008,-0x8+0xa+LOCAL_SIZE(%sp)
   3064  1.1        is 	mov.l		%a0,-0x8+0xc+LOCAL_SIZE(%sp)
   3065  1.1        is 	mov.w		%d0,-0x8+0x10+LOCAL_SIZE(%sp)
   3066  1.1        is 	mov.w		&0x0001,-0x8+0x12+LOCAL_SIZE(%sp)
   3067  1.1        is 
   3068  1.1        is 	movm.l		LOCAL_SIZE+EXC_DREGS(%sp),&0x0303 # restore d0-d1/a0-a1
   3069  1.1        is 	add.w		&LOCAL_SIZE-0x4,%sp
   3070  1.1        is 
   3071  1.1        is 	bra.b		iea_acc_done
   3072  1.1        is 
   3073  1.1        is #########################################################################
   3074  1.1        is # XDEF ****************************************************************	#
   3075  1.1        is #	_fpsp_operr(): 060FPSP entry point for FP Operr exception.	#
   3076  1.1        is #									#
   3077  1.1        is #	This handler should be the first code executed upon taking the	#
   3078  1.1        is # 	FP Operand Error exception in an operating system.		#
   3079  1.1        is #									#
   3080  1.1        is # XREF ****************************************************************	#
   3081  1.1        is #	_imem_read_long() - read instruction longword			#
   3082  1.1        is #	fix_skewed_ops() - adjust src operand in fsave frame		#
   3083  1.1        is #	_real_operr() - "callout" to operating system operr handler	#
   3084  1.1        is #	_dmem_write_{byte,word,long}() - store data to mem (opclass 3)	#
   3085  1.1        is #	store_dreg_{b,w,l}() - store data to data regfile (opclass 3)	#
   3086  1.1        is #	facc_out_{b,w,l}() - store to memory took access error (opcl 3)	#
   3087  1.1        is #									#
   3088  1.1        is # INPUT ***************************************************************	#
   3089  1.1        is #	- The system stack contains the FP Operr exception frame	#
   3090  1.1        is #	- The fsave frame contains the source operand			#
   3091  1.1        is # 									#
   3092  1.1        is # OUTPUT **************************************************************	#
   3093  1.1        is #	No access error:						#
   3094  1.1        is #	- The system stack is unchanged					#
   3095  1.1        is #	- The fsave frame contains the adjusted src op for opclass 0,2	#
   3096  1.1        is #									#
   3097  1.1        is # ALGORITHM ***********************************************************	#
   3098  1.1        is #	In a system where the FP Operr exception is enabled, the goal	#
   3099  1.1        is # is to get to the handler specified at _real_operr(). But, on the 060,	#
   3100  1.1        is # for opclass zero and two instruction taking this exception, the 	#
   3101  1.1        is # input operand in the fsave frame may be incorrect for some cases	#
   3102  1.1        is # and needs to be corrected. This handler calls fix_skewed_ops() to	#
   3103  1.1        is # do just this and then exits through _real_operr().			#
   3104  1.1        is #	For opclass 3 instructions, the 060 doesn't store the default	#
   3105  1.1        is # operr result out to memory or data register file as it should.	#
   3106  1.1        is # This code must emulate the move out before finally exiting through	#
   3107  1.1        is # _real_inex(). The move out, if to memory, is performed using 		#
   3108  1.1        is # _mem_write() "callout" routines that may return a failing result.	#
   3109  1.1        is # In this special case, the handler must exit through facc_out() 	#
   3110  1.1        is # which creates an access error stack frame from the current operr	#
   3111  1.1        is # stack frame.								#
   3112  1.1        is #									#
   3113  1.1        is #########################################################################
   3114  1.1        is 
   3115  1.1        is 	global		_fpsp_operr
   3116  1.1        is _fpsp_operr:
   3117  1.1        is 
   3118  1.1        is 	link.w		%a6,&-LOCAL_SIZE	# init stack frame
   3119  1.1        is 
   3120  1.1        is 	fsave		FP_SRC(%a6)		# grab the "busy" frame
   3121  1.1        is 
   3122  1.1        is  	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
   3123  1.1        is 	fmovm.l		%fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
   3124  1.1        is  	fmovm.x		&0xc0,EXC_FPREGS(%a6)	# save fp0-fp1 on stack
   3125  1.1        is 
   3126  1.1        is # the FPIAR holds the "current PC" of the faulting instruction
   3127  1.1        is 	mov.l		USER_FPIAR(%a6),EXC_EXTWPTR(%a6)
   3128  1.1        is 
   3129  1.1        is 	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
   3130  1.1        is 	addq.l		&0x4,EXC_EXTWPTR(%a6)	# incr instruction ptr
   3131  1.1        is 	bsr.l		_imem_read_long		# fetch the instruction words
   3132  1.1        is 	mov.l		%d0,EXC_OPWORD(%a6)
   3133  1.1        is 
   3134  1.1        is ##############################################################################
   3135  1.1        is 
   3136  1.1        is 	btst		&13,%d0			# is instr an fmove out?
   3137  1.1        is 	bne.b		foperr_out		# fmove out
   3138  1.1        is 
   3139  1.1        is 
   3140  1.1        is # here, we simply see if the operand in the fsave frame needs to be "unskewed".
   3141  1.1        is # this would be the case for opclass two operations with a source infinity or
   3142  1.1        is # denorm operand in the sgl or dbl format. NANs also become skewed, but can't
   3143  1.1        is # cause an operr so we don't need to check for them here.
   3144  1.1        is 	lea		FP_SRC(%a6),%a0		# pass: ptr to src op
   3145  1.1        is 	bsr.l		fix_skewed_ops		# fix src op
   3146  1.1        is 
   3147  1.1        is foperr_exit:
   3148  1.1        is 	fmovm.x		EXC_FPREGS(%a6),&0xc0	# restore fp0-fp1
   3149  1.1        is 	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
   3150  1.1        is 	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
   3151  1.1        is 
   3152  1.1        is 	frestore	FP_SRC(%a6)
   3153  1.1        is 
   3154  1.1        is 	unlk		%a6
   3155  1.1        is 	bra.l		_real_operr
   3156  1.1        is 
   3157  1.1        is ########################################################################
   3158  1.1        is 
   3159  1.1        is #
   3160  1.1        is # the hardware does not save the default result to memory on enabled
   3161  1.1        is # operand error exceptions. we do this here before passing control to
   3162  1.1        is # the user operand error handler.
   3163  1.1        is #
   3164  1.1        is # byte, word, and long destination format operations can pass
   3165  1.1        is # through here. we simply need to test the sign of the src
   3166  1.1        is # operand and save the appropriate minimum or maximum integer value
   3167  1.1        is # to the effective address as pointed to by the stacked effective address.
   3168  1.1        is #
   3169  1.1        is # although packed opclass three operations can take operand error
   3170  1.1        is # exceptions, they won't pass through here since they are caught
   3171  1.1        is # first by the unsupported data format exception handler. that handler
   3172  1.1        is # sends them directly to _real_operr() if necessary.
   3173  1.1        is #
   3174  1.1        is foperr_out:
   3175  1.1        is 
   3176  1.1        is 	mov.w		FP_SRC_EX(%a6),%d1	# fetch exponent
   3177  1.1        is 	andi.w		&0x7fff,%d1
   3178  1.1        is 	cmpi.w		%d1,&0x7fff
   3179  1.1        is 	bne.b		foperr_out_not_qnan
   3180  1.1        is # the operand is either an infinity or a QNAN.
   3181  1.1        is 	tst.l		FP_SRC_LO(%a6)
   3182  1.1        is 	bne.b		foperr_out_qnan
   3183  1.1        is 	mov.l		FP_SRC_HI(%a6),%d1
   3184  1.1        is 	andi.l		&0x7fffffff,%d1
   3185  1.1        is 	beq.b		foperr_out_not_qnan
   3186  1.1        is foperr_out_qnan:
   3187  1.1        is 	mov.l		FP_SRC_HI(%a6),L_SCR1(%a6)
   3188  1.1        is 	bra.b		foperr_out_jmp
   3189  1.1        is 
   3190  1.1        is foperr_out_not_qnan:
   3191  1.1        is 	mov.l		&0x7fffffff,%d1
   3192  1.1        is 	tst.b		FP_SRC_EX(%a6)
   3193  1.1        is 	bpl.b		foperr_out_not_qnan2
   3194  1.1        is 	addq.l		&0x1,%d1
   3195  1.1        is foperr_out_not_qnan2:
   3196  1.1        is 	mov.l		%d1,L_SCR1(%a6)
   3197  1.1        is 
   3198  1.1        is foperr_out_jmp:
   3199  1.1        is 	bfextu		%d0{&19:&3},%d0		# extract dst format field
   3200  1.1        is 	mov.b		1+EXC_OPWORD(%a6),%d1	# extract <ea> mode,reg
   3201  1.1        is 	mov.w		(tbl_operr.b,%pc,%d0.w*2),%a0
   3202  1.1        is 	jmp		(tbl_operr.b,%pc,%a0)
   3203  1.1        is 
   3204  1.1        is tbl_operr:
   3205  1.1        is 	short		foperr_out_l - tbl_operr # long word integer
   3206  1.1        is 	short		tbl_operr    - tbl_operr # sgl prec shouldn't happen
   3207  1.1        is 	short		tbl_operr    - tbl_operr # ext prec shouldn't happen
   3208  1.1        is 	short		foperr_exit  - tbl_operr # packed won't enter here
   3209  1.1        is 	short		foperr_out_w - tbl_operr # word integer
   3210  1.1        is 	short		tbl_operr    - tbl_operr # dbl prec shouldn't happen
   3211  1.1        is 	short		foperr_out_b - tbl_operr # byte integer
   3212  1.1        is 	short		tbl_operr    - tbl_operr # packed won't enter here
   3213  1.1        is 
   3214  1.1        is foperr_out_b:
   3215  1.1        is 	mov.b		L_SCR1(%a6),%d0		# load positive default result
   3216  1.1        is 	cmpi.b		%d1,&0x7		# is <ea> mode a data reg?
   3217  1.1        is 	ble.b		foperr_out_b_save_dn	# yes
   3218  1.1        is 	mov.l		EXC_EA(%a6),%a0		# pass: <ea> of default result
   3219  1.1        is 	bsr.l		_dmem_write_byte	# write the default result
   3220  1.1        is 
   3221  1.1        is 	tst.l		%d1			# did dstore fail?
   3222  1.1        is 	bne.l		facc_out_b		# yes
   3223  1.1        is 
   3224  1.1        is 	bra.w		foperr_exit
   3225  1.1        is foperr_out_b_save_dn:
   3226  1.1        is 	andi.w		&0x0007,%d1
   3227  1.1        is 	bsr.l		store_dreg_b		# store result to regfile
   3228  1.1        is 	bra.w		foperr_exit
   3229  1.1        is 
   3230  1.1        is foperr_out_w:
   3231  1.1        is 	mov.w		L_SCR1(%a6),%d0		# load positive default result
   3232  1.1        is 	cmpi.b		%d1,&0x7		# is <ea> mode a data reg?
   3233  1.1        is 	ble.b		foperr_out_w_save_dn	# yes
   3234  1.1        is 	mov.l		EXC_EA(%a6),%a0		# pass: <ea> of default result
   3235  1.1        is 	bsr.l		_dmem_write_word	# write the default result
   3236  1.1        is 
   3237  1.1        is 	tst.l		%d1			# did dstore fail?
   3238  1.1        is 	bne.l		facc_out_w		# yes
   3239  1.1        is 
   3240  1.1        is 	bra.w		foperr_exit
   3241  1.1        is foperr_out_w_save_dn:
   3242  1.1        is 	andi.w		&0x0007,%d1
   3243  1.1        is 	bsr.l		store_dreg_w		# store result to regfile
   3244  1.1        is 	bra.w		foperr_exit
   3245  1.1        is 
   3246  1.1        is foperr_out_l:
   3247  1.1        is 	mov.l		L_SCR1(%a6),%d0		# load positive default result
   3248  1.1        is 	cmpi.b		%d1,&0x7		# is <ea> mode a data reg?
   3249  1.1        is 	ble.b		foperr_out_l_save_dn	# yes
   3250  1.1        is 	mov.l		EXC_EA(%a6),%a0		# pass: <ea> of default result
   3251  1.1        is 	bsr.l		_dmem_write_long	# write the default result
   3252  1.1        is 
   3253  1.1        is 	tst.l		%d1			# did dstore fail?
   3254  1.1        is 	bne.l		facc_out_l		# yes
   3255  1.1        is 
   3256  1.1        is 	bra.w		foperr_exit
   3257  1.1        is foperr_out_l_save_dn:
   3258  1.1        is 	andi.w		&0x0007,%d1
   3259  1.1        is 	bsr.l		store_dreg_l		# store result to regfile
   3260  1.1        is 	bra.w		foperr_exit
   3261  1.1        is 
   3262  1.1        is #########################################################################
   3263  1.1        is # XDEF ****************************************************************	#
   3264  1.1        is #	_fpsp_snan(): 060FPSP entry point for FP SNAN exception.	#
   3265  1.1        is #									#
   3266  1.1        is #	This handler should be the first code executed upon taking the	#
   3267  1.1        is # 	FP Signalling NAN exception in an operating system.		#
   3268  1.1        is #									#
   3269  1.1        is # XREF ****************************************************************	#
   3270  1.1        is #	_imem_read_long() - read instruction longword			#
   3271  1.1        is #	fix_skewed_ops() - adjust src operand in fsave frame		#
   3272  1.1        is #	_real_snan() - "callout" to operating system SNAN handler	#
   3273  1.1        is #	_dmem_write_{byte,word,long}() - store data to mem (opclass 3)	#
   3274  1.1        is #	store_dreg_{b,w,l}() - store data to data regfile (opclass 3)	#
   3275  1.1        is #	facc_out_{b,w,l,d,x}() - store to mem took acc error (opcl 3)	#
   3276  1.1        is #	_calc_ea_fout() - fix An if <ea> is -() or ()+; also get <ea>	#
   3277  1.1        is #									#
   3278  1.1        is # INPUT ***************************************************************	#
   3279  1.1        is #	- The system stack contains the FP SNAN exception frame		#
   3280  1.1        is #	- The fsave frame contains the source operand			#
   3281  1.1        is # 									#
   3282  1.1        is # OUTPUT **************************************************************	#
   3283  1.1        is #	No access error:						#
   3284  1.1        is #	- The system stack is unchanged					#
   3285  1.1        is #	- The fsave frame contains the adjusted src op for opclass 0,2	#
   3286  1.1        is #									#
   3287  1.1        is # ALGORITHM ***********************************************************	#
   3288  1.1        is #	In a system where the FP SNAN exception is enabled, the goal	#
   3289  1.1        is # is to get to the handler specified at _real_snan(). But, on the 060,	#
   3290  1.1        is # for opclass zero and two instructions taking this exception, the 	#
   3291  1.1        is # input operand in the fsave frame may be incorrect for some cases	#
   3292  1.1        is # and needs to be corrected. This handler calls fix_skewed_ops() to	#
   3293  1.1        is # do just this and then exits through _real_snan().			#
   3294  1.1        is #	For opclass 3 instructions, the 060 doesn't store the default	#
   3295  1.1        is # SNAN result out to memory or data register file as it should.		#
   3296  1.1        is # This code must emulate the move out before finally exiting through	#
   3297  1.1        is # _real_snan(). The move out, if to memory, is performed using 		#
   3298  1.1        is # _mem_write() "callout" routines that may return a failing result.	#
   3299  1.1        is # In this special case, the handler must exit through facc_out() 	#
   3300  1.1        is # which creates an access error stack frame from the current SNAN	#
   3301  1.1        is # stack frame.								#
   3302  1.1        is #	For the case of an extended precision opclass 3 instruction,	#
   3303  1.1        is # if the effective addressing mode was -() or ()+, then the address	#
   3304  1.1        is # register must get updated by calling _calc_ea_fout(). If the <ea>	#
   3305  1.1        is # was -(a7) from supervisor mode, then the exception frame currently	#
   3306  1.1        is # on the system stack must be carefully moved "down" to make room	#
   3307  1.1        is # for the operand being moved.						#
   3308  1.1        is #									#
   3309  1.1        is #########################################################################
   3310  1.1        is 
   3311  1.1        is 	global		_fpsp_snan
   3312  1.1        is _fpsp_snan:
   3313  1.1        is 
   3314  1.1        is 	link.w		%a6,&-LOCAL_SIZE	# init stack frame
   3315  1.1        is 
   3316  1.1        is 	fsave		FP_SRC(%a6)		# grab the "busy" frame
   3317  1.1        is 
   3318  1.1        is  	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
   3319  1.1        is 	fmovm.l		%fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
   3320  1.1        is  	fmovm.x		&0xc0,EXC_FPREGS(%a6)	# save fp0-fp1 on stack
   3321  1.1        is 
   3322  1.1        is # the FPIAR holds the "current PC" of the faulting instruction
   3323  1.1        is 	mov.l		USER_FPIAR(%a6),EXC_EXTWPTR(%a6)
   3324  1.1        is 
   3325  1.1        is 	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
   3326  1.1        is 	addq.l		&0x4,EXC_EXTWPTR(%a6)	# incr instruction ptr
   3327  1.1        is 	bsr.l		_imem_read_long		# fetch the instruction words
   3328  1.1        is 	mov.l		%d0,EXC_OPWORD(%a6)
   3329  1.1        is 
   3330  1.1        is ##############################################################################
   3331  1.1        is 
   3332  1.1        is 	btst		&13,%d0			# is instr an fmove out?
   3333  1.1        is 	bne.w		fsnan_out		# fmove out
   3334  1.1        is 
   3335  1.1        is 
   3336  1.1        is # here, we simply see if the operand in the fsave frame needs to be "unskewed".
   3337  1.1        is # this would be the case for opclass two operations with a source infinity or
   3338  1.1        is # denorm operand in the sgl or dbl format. NANs also become skewed and must be
   3339  1.1        is # fixed here.
   3340  1.1        is 	lea		FP_SRC(%a6),%a0		# pass: ptr to src op
   3341  1.1        is 	bsr.l		fix_skewed_ops		# fix src op
   3342  1.1        is 
   3343  1.1        is fsnan_exit:
   3344  1.1        is 	fmovm.x		EXC_FPREGS(%a6),&0xc0	# restore fp0-fp1
   3345  1.1        is 	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
   3346  1.1        is 	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
   3347  1.1        is 
   3348  1.1        is 	frestore	FP_SRC(%a6)
   3349  1.1        is 
   3350  1.1        is 	unlk		%a6
   3351  1.1        is 	bra.l		_real_snan
   3352  1.1        is 
   3353  1.1        is ########################################################################
   3354  1.1        is 
   3355  1.1        is #
   3356  1.1        is # the hardware does not save the default result to memory on enabled
   3357  1.1        is # snan exceptions. we do this here before passing control to
   3358  1.1        is # the user snan handler.
   3359  1.1        is #
   3360  1.1        is # byte, word, long, and packed destination format operations can pass
   3361  1.1        is # through here. since packed format operations already were handled by
   3362  1.1        is # fpsp_unsupp(), then we need to do nothing else for them here.
   3363  1.1        is # for byte, word, and long, we simply need to test the sign of the src
   3364  1.1        is # operand and save the appropriate minimum or maximum integer value
   3365  1.1        is # to the effective address as pointed to by the stacked effective address.
   3366  1.1        is #
   3367  1.1        is fsnan_out:
   3368  1.1        is 
   3369  1.1        is 	bfextu		%d0{&19:&3},%d0		# extract dst format field
   3370  1.1        is 	mov.b		1+EXC_OPWORD(%a6),%d1	# extract <ea> mode,reg
   3371  1.1        is 	mov.w		(tbl_snan.b,%pc,%d0.w*2),%a0
   3372  1.1        is 	jmp		(tbl_snan.b,%pc,%a0)
   3373  1.1        is 
   3374  1.1        is tbl_snan:
   3375  1.1        is 	short		fsnan_out_l - tbl_snan # long word integer
   3376  1.1        is 	short		fsnan_out_s - tbl_snan # sgl prec shouldn't happen
   3377  1.1        is 	short		fsnan_out_x - tbl_snan # ext prec shouldn't happen
   3378  1.1        is 	short		tbl_snan    - tbl_snan # packed needs no help
   3379  1.1        is 	short		fsnan_out_w - tbl_snan # word integer
   3380  1.1        is 	short		fsnan_out_d - tbl_snan # dbl prec shouldn't happen
   3381  1.1        is 	short		fsnan_out_b - tbl_snan # byte integer
   3382  1.1        is 	short		tbl_snan    - tbl_snan # packed needs no help
   3383  1.1        is 
   3384  1.1        is fsnan_out_b:
   3385  1.1        is 	mov.b		FP_SRC_HI(%a6),%d0	# load upper byte of SNAN
   3386  1.1        is 	bset		&6,%d0			# set SNAN bit
   3387  1.1        is 	cmpi.b		%d1,&0x7		# is <ea> mode a data reg?
   3388  1.1        is 	ble.b		fsnan_out_b_dn		# yes
   3389  1.1        is 	mov.l		EXC_EA(%a6),%a0		# pass: <ea> of default result
   3390  1.1        is 	bsr.l		_dmem_write_byte	# write the default result
   3391  1.1        is 
   3392  1.1        is 	tst.l		%d1			# did dstore fail?
   3393  1.1        is 	bne.l		facc_out_b		# yes
   3394  1.1        is 
   3395  1.1        is 	bra.w		fsnan_exit
   3396  1.1        is fsnan_out_b_dn:
   3397  1.1        is 	andi.w		&0x0007,%d1
   3398  1.1        is 	bsr.l		store_dreg_b		# store result to regfile
   3399  1.1        is 	bra.w		fsnan_exit
   3400  1.1        is 
   3401  1.1        is fsnan_out_w:
   3402  1.1        is 	mov.w		FP_SRC_HI(%a6),%d0	# load upper word of SNAN
   3403  1.1        is 	bset		&14,%d0			# set SNAN bit
   3404  1.1        is 	cmpi.b		%d1,&0x7		# is <ea> mode a data reg?
   3405  1.1        is 	ble.b		fsnan_out_w_dn		# yes
   3406  1.1        is 	mov.l		EXC_EA(%a6),%a0		# pass: <ea> of default result
   3407  1.1        is 	bsr.l		_dmem_write_word	# write the default result
   3408  1.1        is 
   3409  1.1        is 	tst.l		%d1			# did dstore fail?
   3410  1.1        is 	bne.l		facc_out_w		# yes
   3411  1.1        is 
   3412  1.1        is 	bra.w		fsnan_exit
   3413  1.1        is fsnan_out_w_dn:
   3414  1.1        is 	andi.w		&0x0007,%d1
   3415  1.1        is 	bsr.l		store_dreg_w		# store result to regfile
   3416  1.1        is 	bra.w		fsnan_exit
   3417  1.1        is 
   3418  1.1        is fsnan_out_l:
   3419  1.1        is 	mov.l		FP_SRC_HI(%a6),%d0	# load upper longword of SNAN
   3420  1.1        is 	bset		&30,%d0			# set SNAN bit
   3421  1.1        is 	cmpi.b		%d1,&0x7		# is <ea> mode a data reg?
   3422  1.1        is 	ble.b		fsnan_out_l_dn		# yes
   3423  1.1        is 	mov.l		EXC_EA(%a6),%a0		# pass: <ea> of default result
   3424  1.1        is 	bsr.l		_dmem_write_long	# write the default result
   3425  1.1        is 
   3426  1.1        is 	tst.l		%d1			# did dstore fail?
   3427  1.1        is 	bne.l		facc_out_l		# yes
   3428  1.1        is 
   3429  1.1        is 	bra.w		fsnan_exit
   3430  1.1        is fsnan_out_l_dn:
   3431  1.1        is 	andi.w		&0x0007,%d1
   3432  1.1        is 	bsr.l		store_dreg_l		# store result to regfile
   3433  1.1        is 	bra.w		fsnan_exit
   3434  1.1        is 
   3435  1.1        is fsnan_out_s:
   3436  1.1        is 	cmpi.b		%d1,&0x7		# is <ea> mode a data reg?
   3437  1.1        is 	ble.b		fsnan_out_d_dn		# yes
   3438  1.1        is 	mov.l		FP_SRC_EX(%a6),%d0	# fetch SNAN sign
   3439  1.1        is 	andi.l		&0x80000000,%d0		# keep sign
   3440  1.1        is 	ori.l		&0x7fc00000,%d0		# insert new exponent,SNAN bit
   3441  1.1        is 	mov.l		FP_SRC_HI(%a6),%d1	# load mantissa
   3442  1.1        is 	lsr.l		&0x8,%d1		# shift mantissa for sgl
   3443  1.1        is 	or.l		%d1,%d0			# create sgl SNAN
   3444  1.1        is 	mov.l		EXC_EA(%a6),%a0		# pass: <ea> of default result
   3445  1.1        is 	bsr.l		_dmem_write_long	# write the default result
   3446  1.1        is 
   3447  1.1        is 	tst.l		%d1			# did dstore fail?
   3448  1.1        is 	bne.l		facc_out_l		# yes
   3449  1.1        is 
   3450  1.1        is 	bra.w		fsnan_exit
   3451  1.1        is fsnan_out_d_dn:
   3452  1.1        is 	mov.l		FP_SRC_EX(%a6),%d0	# fetch SNAN sign
   3453  1.1        is 	andi.l		&0x80000000,%d0		# keep sign
   3454  1.1        is 	ori.l		&0x7fc00000,%d0		# insert new exponent,SNAN bit
   3455  1.1        is 	mov.l		%d1,-(%sp)
   3456  1.1        is 	mov.l		FP_SRC_HI(%a6),%d1	# load mantissa
   3457  1.1        is 	lsr.l		&0x8,%d1		# shift mantissa for sgl
   3458  1.1        is 	or.l		%d1,%d0			# create sgl SNAN
   3459  1.1        is 	mov.l		(%sp)+,%d1
   3460  1.1        is 	andi.w		&0x0007,%d1
   3461  1.1        is 	bsr.l		store_dreg_l		# store result to regfile
   3462  1.1        is 	bra.w		fsnan_exit
   3463  1.1        is 
   3464  1.1        is fsnan_out_d:
   3465  1.1        is 	mov.l		FP_SRC_EX(%a6),%d0	# fetch SNAN sign
   3466  1.1        is 	andi.l		&0x80000000,%d0		# keep sign
   3467  1.1        is 	ori.l		&0x7ff80000,%d0		# insert new exponent,SNAN bit
   3468  1.1        is 	mov.l		FP_SRC_HI(%a6),%d1	# load hi mantissa
   3469  1.1        is 	mov.l		%d0,FP_SCR0_EX(%a6)	# store to temp space
   3470  1.1        is 	mov.l		&11,%d0			# load shift amt
   3471  1.1        is 	lsr.l		%d0,%d1
   3472  1.1        is 	or.l		%d1,FP_SCR0_EX(%a6)	# create dbl hi
   3473  1.1        is 	mov.l		FP_SRC_HI(%a6),%d1	# load hi mantissa
   3474  1.1        is 	andi.l		&0x000007ff,%d1
   3475  1.1        is 	ror.l		%d0,%d1
   3476  1.1        is 	mov.l		%d1,FP_SCR0_HI(%a6)	# store to temp space
   3477  1.1        is 	mov.l		FP_SRC_LO(%a6),%d1	# load lo mantissa
   3478  1.1        is 	lsr.l		%d0,%d1
   3479  1.1        is 	or.l		%d1,FP_SCR0_HI(%a6)	# create dbl lo
   3480  1.1        is 	lea		FP_SCR0(%a6),%a0	# pass: ptr to operand
   3481  1.1        is 	mov.l		EXC_EA(%a6),%a1		# pass: dst addr
   3482  1.1        is 	movq.l		&0x8,%d0		# pass: size of 8 bytes
   3483  1.1        is 	bsr.l		_dmem_write		# write the default result
   3484  1.1        is 
   3485  1.1        is 	tst.l		%d1			# did dstore fail?
   3486  1.1        is 	bne.l		facc_out_d		# yes
   3487  1.1        is 
   3488  1.1        is 	bra.w		fsnan_exit
   3489  1.1        is 
   3490  1.1        is # for extended precision, if the addressing mode is pre-decrement or
   3491  1.1        is # post-increment, then the address register did not get updated.
   3492  1.1        is # in addition, for pre-decrement, the stacked <ea> is incorrect.
   3493  1.1        is fsnan_out_x:
   3494  1.1        is 	clr.b		SPCOND_FLG(%a6)		# clear special case flag
   3495  1.1        is 
   3496  1.1        is 	mov.w		FP_SRC_EX(%a6),FP_SCR0_EX(%a6)
   3497  1.1        is 	clr.w		2+FP_SCR0(%a6)
   3498  1.1        is 	mov.l		FP_SRC_HI(%a6),%d0
   3499  1.1        is 	bset		&30,%d0
   3500  1.1        is 	mov.l		%d0,FP_SCR0_HI(%a6)
   3501  1.1        is 	mov.l		FP_SRC_LO(%a6),FP_SCR0_LO(%a6)
   3502  1.1        is 
   3503  1.1        is 	btst		&0x5,EXC_SR(%a6)	# supervisor mode exception?
   3504  1.1        is 	bne.b		fsnan_out_x_s		# yes
   3505  1.1        is 
   3506  1.1        is 	mov.l		%usp,%a0		# fetch user stack pointer
   3507  1.1        is 	mov.l		%a0,EXC_A7(%a6)		# save on stack for calc_ea()
   3508  1.1        is 	mov.l		(%a6),EXC_A6(%a6)
   3509  1.1        is 
   3510  1.1        is 	bsr.l		_calc_ea_fout		# find the correct ea,update An
   3511  1.1        is 	mov.l		%a0,%a1
   3512  1.1        is 	mov.l		%a0,EXC_EA(%a6)		# stack correct <ea>
   3513  1.1        is 
   3514  1.1        is 	mov.l		EXC_A7(%a6),%a0
   3515  1.1        is 	mov.l		%a0,%usp		# restore user stack pointer
   3516  1.1        is 	mov.l		EXC_A6(%a6),(%a6)
   3517  1.1        is 
   3518  1.1        is fsnan_out_x_save:
   3519  1.1        is 	lea		FP_SCR0(%a6),%a0	# pass: ptr to operand
   3520  1.1        is 	movq.l		&0xc,%d0		# pass: size of extended
   3521  1.1        is 	bsr.l		_dmem_write		# write the default result
   3522  1.1        is 
   3523  1.1        is 	tst.l		%d1			# did dstore fail?
   3524  1.1        is 	bne.l		facc_out_x		# yes
   3525  1.1        is 
   3526  1.1        is 	bra.w		fsnan_exit
   3527  1.1        is 
   3528  1.1        is fsnan_out_x_s:
   3529  1.1        is 	mov.l		(%a6),EXC_A6(%a6)
   3530  1.1        is 
   3531  1.1        is 	bsr.l		_calc_ea_fout		# find the correct ea,update An
   3532  1.1        is 	mov.l		%a0,%a1
   3533  1.1        is 	mov.l		%a0,EXC_EA(%a6)		# stack correct <ea>
   3534  1.1        is 
   3535  1.1        is 	mov.l		EXC_A6(%a6),(%a6)
   3536  1.1        is 
   3537  1.1        is 	cmpi.b		SPCOND_FLG(%a6),&mda7_flg # is <ea> mode -(a7)?
   3538  1.1        is 	bne.b		fsnan_out_x_save	# no
   3539  1.1        is 
   3540  1.1        is # the operation was "fmove.x SNAN,-(a7)" from supervisor mode.
   3541  1.1        is 	fmovm.x		EXC_FPREGS(%a6),&0xc0	# restore fp0-fp1
   3542  1.1        is 	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
   3543  1.1        is 	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
   3544  1.1        is 
   3545  1.1        is 	frestore	FP_SRC(%a6)
   3546  1.1        is 
   3547  1.1        is 	mov.l		EXC_A6(%a6),%a6		# restore frame pointer
   3548  1.1        is 
   3549  1.1        is 	mov.l		LOCAL_SIZE+EXC_SR(%sp),LOCAL_SIZE+EXC_SR-0xc(%sp)
   3550  1.1        is 	mov.l		LOCAL_SIZE+EXC_PC+0x2(%sp),LOCAL_SIZE+EXC_PC+0x2-0xc(%sp)
   3551  1.1        is 	mov.l		LOCAL_SIZE+EXC_EA(%sp),LOCAL_SIZE+EXC_EA-0xc(%sp)
   3552  1.1        is 
   3553  1.1        is 	mov.l		LOCAL_SIZE+FP_SCR0_EX(%sp),LOCAL_SIZE+EXC_SR(%sp)
   3554  1.1        is 	mov.l		LOCAL_SIZE+FP_SCR0_HI(%sp),LOCAL_SIZE+EXC_PC+0x2(%sp)
   3555  1.1        is 	mov.l		LOCAL_SIZE+FP_SCR0_LO(%sp),LOCAL_SIZE+EXC_EA(%sp)
   3556  1.1        is 
   3557  1.1        is 	add.l		&LOCAL_SIZE-0x8,%sp
   3558  1.1        is 
   3559  1.1        is 	bra.l		_real_snan
   3560  1.1        is 
   3561  1.1        is #########################################################################
   3562  1.1        is # XDEF ****************************************************************	#
   3563  1.1        is #	_fpsp_inex(): 060FPSP entry point for FP Inexact exception.	#
   3564  1.1        is #									#
   3565  1.1        is #	This handler should be the first code executed upon taking the	#
   3566  1.1        is # 	FP Inexact exception in an operating system.			#
   3567  1.1        is #									#
   3568  1.1        is # XREF ****************************************************************	#
   3569  1.1        is #	_imem_read_long() - read instruction longword			#
   3570  1.1        is #	fix_skewed_ops() - adjust src operand in fsave frame		#
   3571  1.1        is #	set_tag_x() - determine optype of src/dst operands		#
   3572  1.1        is #	store_fpreg() - store opclass 0 or 2 result to FP regfile	#
   3573  1.1        is #	unnorm_fix() - change UNNORM operands to NORM or ZERO		#
   3574  1.1        is #	load_fpn2() - load dst operand from FP regfile			#
   3575  1.1        is #	smovcr() - emulate an "fmovcr" instruction			#
   3576  1.1        is #	fout() - emulate an opclass 3 instruction			#
   3577  1.1        is #	tbl_unsupp - add of table of emulation routines for opclass 0,2	#
   3578  1.1        is #	_real_inex() - "callout" to operating system inexact handler	#
   3579  1.1        is #									#
   3580  1.1        is # INPUT ***************************************************************	#
   3581  1.1        is #	- The system stack contains the FP Inexact exception frame	#
   3582  1.1        is #	- The fsave frame contains the source operand			#
   3583  1.1        is # 									#
   3584  1.1        is # OUTPUT **************************************************************	#
   3585  1.1        is #	- The system stack is unchanged					#
   3586  1.1        is #	- The fsave frame contains the adjusted src op for opclass 0,2	#
   3587  1.1        is #									#
   3588  1.1        is # ALGORITHM ***********************************************************	#
   3589  1.1        is #	In a system where the FP Inexact exception is enabled, the goal	#
   3590  1.1        is # is to get to the handler specified at _real_inex(). But, on the 060,	#
   3591  1.1        is # for opclass zero and two instruction taking this exception, the 	#
   3592  1.1        is # hardware doesn't store the correct result to the destination FP	#
   3593  1.1        is # register as did the '040 and '881/2. This handler must emulate the 	#
   3594  1.1        is # instruction in order to get this value and then store it to the 	#
   3595  1.1        is # correct register before calling _real_inex().				#
   3596  1.1        is #	For opclass 3 instructions, the 060 doesn't store the default	#
   3597  1.1        is # inexact result out to memory or data register file as it should.	#
   3598  1.1        is # This code must emulate the move out by calling fout() before finally	#
   3599  1.1        is # exiting through _real_inex().						#
   3600  1.1        is #									#
   3601  1.1        is #########################################################################
   3602  1.1        is 
   3603  1.1        is 	global		_fpsp_inex
   3604  1.1        is _fpsp_inex:
   3605  1.1        is 
   3606  1.1        is 	link.w		%a6,&-LOCAL_SIZE	# init stack frame
   3607  1.1        is 
   3608  1.1        is 	fsave		FP_SRC(%a6)		# grab the "busy" frame
   3609  1.1        is 
   3610  1.1        is  	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
   3611  1.1        is 	fmovm.l		%fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
   3612  1.1        is  	fmovm.x		&0xc0,EXC_FPREGS(%a6)	# save fp0-fp1 on stack
   3613  1.1        is 
   3614  1.1        is # the FPIAR holds the "current PC" of the faulting instruction
   3615  1.1        is 	mov.l		USER_FPIAR(%a6),EXC_EXTWPTR(%a6)
   3616  1.1        is 
   3617  1.1        is 	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
   3618  1.1        is 	addq.l		&0x4,EXC_EXTWPTR(%a6)	# incr instruction ptr
   3619  1.1        is 	bsr.l		_imem_read_long		# fetch the instruction words
   3620  1.1        is 	mov.l		%d0,EXC_OPWORD(%a6)
   3621  1.1        is 
   3622  1.1        is ##############################################################################
   3623  1.1        is 
   3624  1.1        is 	btst		&13,%d0			# is instr an fmove out?
   3625  1.1        is 	bne.w		finex_out		# fmove out
   3626  1.1        is 
   3627  1.1        is 
   3628  1.1        is # the hardware, for "fabs" and "fneg" w/ a long source format, puts the
   3629  1.1        is # longword integer directly into the upper longword of the mantissa along
   3630  1.1        is # w/ an exponent value of 0x401e. we convert this to extended precision here.
   3631  1.1        is 	bfextu		%d0{&19:&3},%d0		# fetch instr size
   3632  1.1        is 	bne.b		finex_cont		# instr size is not long
   3633  1.1        is 	cmpi.w		FP_SRC_EX(%a6),&0x401e	# is exponent 0x401e?
   3634  1.1        is 	bne.b		finex_cont		# no
   3635  1.1        is 	fmov.l		&0x0,%fpcr
   3636  1.1        is 	fmov.l		FP_SRC_HI(%a6),%fp0	# load integer src
   3637  1.1        is 	fmov.x		%fp0,FP_SRC(%a6)	# store integer as extended precision
   3638  1.1        is 	mov.w		&0xe001,0x2+FP_SRC(%a6)
   3639  1.1        is 
   3640  1.1        is finex_cont:
   3641  1.1        is 	lea		FP_SRC(%a6),%a0		# pass: ptr to src op
   3642  1.1        is 	bsr.l		fix_skewed_ops		# fix src op
   3643  1.1        is 
   3644  1.1        is # Here, we zero the ccode and exception byte field since we're going to
   3645  1.1        is # emulate the whole instruction. Notice, though, that we don't kill the
   3646  1.1        is # INEX1 bit. This is because a packed op has long since been converted
   3647  1.1        is # to extended before arriving here. Therefore, we need to retain the
   3648  1.1        is # INEX1 bit from when the operand was first converted.
   3649  1.1        is 	andi.l		&0x00ff01ff,USER_FPSR(%a6) # zero all but accured field
   3650  1.1        is 
   3651  1.1        is 	fmov.l		&0x0,%fpcr		# zero current control regs
   3652  1.1        is 	fmov.l		&0x0,%fpsr
   3653  1.1        is 
   3654  1.1        is 	bfextu		EXC_EXTWORD(%a6){&0:&6},%d1 # extract upper 6 of cmdreg
   3655  1.1        is 	cmpi.b		%d1,&0x17		# is op an fmovecr?
   3656  1.1        is 	beq.w		finex_fmovcr		# yes
   3657  1.1        is 
   3658  1.1        is 	lea		FP_SRC(%a6),%a0		# pass: ptr to src op
   3659  1.1        is 	bsr.l		set_tag_x		# tag the operand type
   3660  1.1        is 	mov.b		%d0,STAG(%a6)		# maybe NORM,DENORM
   3661  1.1        is 
   3662  1.1        is # bits four and five of the fp extension word separate the monadic and dyadic
   3663  1.1        is # operations that can pass through fpsp_inex(). remember that fcmp and ftst
   3664  1.1        is # will never take this exception, but fsincos will.
   3665  1.1        is 	btst		&0x5,1+EXC_CMDREG(%a6)	# is operation monadic or dyadic?
   3666  1.1        is 	beq.b		finex_extract		# monadic
   3667  1.1        is 
   3668  1.1        is 	btst		&0x4,1+EXC_CMDREG(%a6)	# is operation an fsincos?
   3669  1.1        is 	bne.b		finex_extract		# yes
   3670  1.1        is 
   3671  1.1        is 	bfextu		EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg
   3672  1.1        is 	bsr.l		load_fpn2		# load dst into FP_DST
   3673  1.1        is 
   3674  1.1        is 	lea		FP_DST(%a6),%a0		# pass: ptr to dst op
   3675  1.1        is 	bsr.l		set_tag_x		# tag the operand type
   3676  1.1        is 	cmpi.b		%d0,&UNNORM		# is operand an UNNORM?
   3677  1.1        is 	bne.b		finex_op2_done		# no
   3678  1.1        is 	bsr.l		unnorm_fix		# yes; convert to NORM,DENORM,or ZERO
   3679  1.1        is finex_op2_done:
   3680  1.1        is 	mov.b		%d0,DTAG(%a6)		# save dst optype tag
   3681  1.1        is 
   3682  1.1        is finex_extract:
   3683  1.1        is 	clr.l		%d0
   3684  1.1        is 	mov.b		FPCR_MODE(%a6),%d0	# pass rnd prec/mode
   3685  1.1        is 
   3686  1.1        is 	mov.b		1+EXC_CMDREG(%a6),%d1
   3687  1.1        is 	andi.w		&0x007f,%d1		# extract extension
   3688  1.1        is 
   3689  1.1        is 	lea		FP_SRC(%a6),%a0
   3690  1.1        is 	lea		FP_DST(%a6),%a1
   3691  1.1        is 
   3692  1.1        is 	mov.l		(tbl_unsupp.l,%pc,%d1.w*4),%d1 # fetch routine addr
   3693  1.1        is 	jsr		(tbl_unsupp.l,%pc,%d1.l*1)
   3694  1.1        is 
   3695  1.1        is # the operation has been emulated. the result is in fp0.
   3696  1.1        is finex_save:
   3697  1.1        is 	bfextu		EXC_CMDREG(%a6){&6:&3},%d0
   3698  1.1        is 	bsr.l		store_fpreg
   3699  1.1        is 
   3700  1.1        is finex_exit:
   3701  1.1        is 	fmovm.x		EXC_FPREGS(%a6),&0xc0	# restore fp0-fp1
   3702  1.1        is 	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
   3703  1.1        is 	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
   3704  1.1        is 
   3705  1.1        is 	frestore	FP_SRC(%a6)
   3706  1.1        is 
   3707  1.1        is 	unlk		%a6
   3708  1.1        is 	bra.l		_real_inex
   3709  1.1        is 
   3710  1.1        is finex_fmovcr:
   3711  1.1        is 	clr.l		%d0
   3712  1.1        is 	mov.b		FPCR_MODE(%a6),%d0	# pass rnd prec,mode
   3713  1.1        is 	mov.b		1+EXC_CMDREG(%a6),%d1
   3714  1.1        is 	andi.l		&0x0000007f,%d1		# pass rom offset
   3715  1.1        is 	bsr.l		smovcr
   3716  1.1        is 	bra.b		finex_save
   3717  1.1        is 
   3718  1.1        is ########################################################################
   3719  1.1        is 
   3720  1.1        is #
   3721  1.1        is # the hardware does not save the default result to memory on enabled
   3722  1.1        is # inexact exceptions. we do this here before passing control to
   3723  1.1        is # the user inexact handler.
   3724  1.1        is #
   3725  1.1        is # byte, word, and long destination format operations can pass
   3726  1.1        is # through here. so can double and single precision.
   3727  1.1        is # although packed opclass three operations can take inexact
   3728  1.1        is # exceptions, they won't pass through here since they are caught
   3729  1.1        is # first by the unsupported data format exception handler. that handler
   3730  1.1        is # sends them directly to _real_inex() if necessary.
   3731  1.1        is #
   3732  1.1        is finex_out:
   3733  1.1        is 
   3734  1.1        is 	mov.b		&NORM,STAG(%a6)		# src is a NORM
   3735  1.1        is 
   3736  1.1        is 	clr.l		%d0
   3737  1.1        is 	mov.b		FPCR_MODE(%a6),%d0	# pass rnd prec,mode
   3738  1.1        is 
   3739  1.1        is 	andi.l		&0xffff00ff,USER_FPSR(%a6) # zero exception field
   3740  1.1        is 
   3741  1.1        is 	lea		FP_SRC(%a6),%a0		# pass ptr to src operand
   3742  1.1        is 
   3743  1.1        is 	bsr.l		fout			# store the default result
   3744  1.1        is 
   3745  1.1        is 	bra.b		finex_exit
   3746  1.1        is 
   3747  1.1        is #########################################################################
   3748  1.1        is # XDEF ****************************************************************	#
   3749  1.1        is #	_fpsp_dz(): 060FPSP entry point for FP DZ exception.		#
   3750  1.1        is #									#
   3751  1.1        is #	This handler should be the first code executed upon taking	#
   3752  1.1        is #	the FP DZ exception in an operating system.			#
   3753  1.1        is #									#
   3754  1.1        is # XREF ****************************************************************	#
   3755  1.1        is #	_imem_read_long() - read instruction longword from memory	#
   3756  1.1        is #	fix_skewed_ops() - adjust fsave operand				#
   3757  1.1        is #	_real_dz() - "callout" exit point from FP DZ handler		#
   3758  1.1        is #									#
   3759  1.1        is # INPUT ***************************************************************	#
   3760  1.1        is #	- The system stack contains the FP DZ exception stack.		#
   3761  1.1        is #	- The fsave frame contains the source operand.			#
   3762  1.1        is # 									#
   3763  1.1        is # OUTPUT **************************************************************	#
   3764  1.1        is #	- The system stack contains the FP DZ exception stack.		#
   3765  1.1        is #	- The fsave frame contains the adjusted source operand.		#
   3766  1.1        is #									#
   3767  1.1        is # ALGORITHM ***********************************************************	#
   3768  1.1        is #	In a system where the DZ exception is enabled, the goal is to	#
   3769  1.1        is # get to the handler specified at _real_dz(). But, on the 060, when the	#
   3770  1.1        is # exception is taken, the input operand in the fsave state frame may	#
   3771  1.1        is # be incorrect for some cases and need to be adjusted. So, this package	#
   3772  1.1        is # adjusts the operand using fix_skewed_ops() and then branches to	#
   3773  1.1        is # _real_dz(). 								#
   3774  1.1        is #									#
   3775  1.1        is #########################################################################
   3776  1.1        is 
   3777  1.1        is 	global		_fpsp_dz
   3778  1.1        is _fpsp_dz:
   3779  1.1        is 
   3780  1.1        is 	link.w		%a6,&-LOCAL_SIZE	# init stack frame
   3781  1.1        is 
   3782  1.1        is 	fsave		FP_SRC(%a6)		# grab the "busy" frame
   3783  1.1        is 
   3784  1.1        is  	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
   3785  1.1        is 	fmovm.l		%fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
   3786  1.1        is  	fmovm.x		&0xc0,EXC_FPREGS(%a6)	# save fp0-fp1 on stack
   3787  1.1        is 
   3788  1.1        is # the FPIAR holds the "current PC" of the faulting instruction
   3789  1.1        is 	mov.l		USER_FPIAR(%a6),EXC_EXTWPTR(%a6)
   3790  1.1        is 
   3791  1.1        is 	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
   3792  1.1        is 	addq.l		&0x4,EXC_EXTWPTR(%a6)	# incr instruction ptr
   3793  1.1        is 	bsr.l		_imem_read_long		# fetch the instruction words
   3794  1.1        is 	mov.l		%d0,EXC_OPWORD(%a6)
   3795  1.1        is 
   3796  1.1        is ##############################################################################
   3797  1.1        is 
   3798  1.1        is 
   3799  1.1        is # here, we simply see if the operand in the fsave frame needs to be "unskewed".
   3800  1.1        is # this would be the case for opclass two operations with a source zero
   3801  1.1        is # in the sgl or dbl format.
   3802  1.1        is 	lea		FP_SRC(%a6),%a0		# pass: ptr to src op
   3803  1.1        is 	bsr.l		fix_skewed_ops		# fix src op
   3804  1.1        is 
   3805  1.1        is fdz_exit:
   3806  1.1        is 	fmovm.x		EXC_FPREGS(%a6),&0xc0	# restore fp0-fp1
   3807  1.1        is 	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
   3808  1.1        is 	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
   3809  1.1        is 
   3810  1.1        is 	frestore	FP_SRC(%a6)
   3811  1.1        is 
   3812  1.1        is 	unlk		%a6
   3813  1.1        is 	bra.l		_real_dz
   3814  1.1        is 
   3815  1.1        is #########################################################################
   3816  1.1        is # XDEF ****************************************************************	#
   3817  1.1        is #	_fpsp_fline(): 060FPSP entry point for "Line F emulator"	#
   3818  1.1        is #		       exception when the "reduced" version of the 	#
   3819  1.1        is #		       FPSP is implemented that does not emulate	#
   3820  1.1        is #		       FP unimplemented instructions.			#
   3821  1.1        is #									#
   3822  1.1        is #	This handler should be the first code executed upon taking a	#
   3823  1.1        is #	"Line F Emulator" exception in an operating system integrating	#
   3824  1.1        is #	the reduced version of 060FPSP.					#
   3825  1.1        is #									#
   3826  1.1        is # XREF ****************************************************************	#
   3827  1.1        is #	_real_fpu_disabled() - Handle "FPU disabled" exceptions		#
   3828  1.1        is #	_real_fline() - Handle all other cases (treated equally)	#
   3829  1.1        is #									#
   3830  1.1        is # INPUT ***************************************************************	#
   3831  1.1        is #	- The system stack contains a "Line F Emulator" exception	#
   3832  1.1        is #	  stack frame.							#
   3833  1.1        is # 									#
   3834  1.1        is # OUTPUT **************************************************************	#
   3835  1.1        is #	- The system stack is unchanged.				#
   3836  1.1        is #									#
   3837  1.1        is # ALGORITHM ***********************************************************	#
   3838  1.1        is # 	When a "Line F Emulator" exception occurs in a system where	#
   3839  1.1        is # "FPU Unimplemented" instructions will not be emulated, the exception	#
   3840  1.1        is # can occur because then FPU is disabled or the instruction is to be	#
   3841  1.1        is # classifed as "Line F". This module determines which case exists and	#
   3842  1.1        is # calls the appropriate "callout".					#
   3843  1.1        is #									#
   3844  1.1        is #########################################################################
   3845  1.1        is 
   3846  1.1        is 	global		_fpsp_fline
   3847  1.1        is _fpsp_fline:
   3848  1.1        is 
   3849  1.1        is # check to see if the FPU is disabled. if so, jump to the OS entry
   3850  1.1        is # point for that condition.
   3851  1.1        is 	cmpi.w		0x6(%sp),&0x402c
   3852  1.1        is 	beq.l		_real_fpu_disabled
   3853  1.1        is 
   3854  1.1        is 	bra.l		_real_fline
   3855  1.1        is 
   3856  1.1        is #########################################################################
   3857  1.1        is # XDEF ****************************************************************	#
   3858  1.1        is #	_dcalc_ea(): calc correct <ea> from <ea> stacked on exception	#
   3859  1.1        is #									#
   3860  1.1        is # XREF ****************************************************************	#
   3861  1.1        is #	inc_areg() - increment an address register			#
   3862  1.1        is #	dec_areg() - decrement an address register			#
   3863  1.1        is #									#
   3864  1.1        is # INPUT ***************************************************************	#
   3865  1.1        is #	d0 = number of bytes to adjust <ea> by				#
   3866  1.1        is # 									#
   3867  1.1        is # OUTPUT **************************************************************	#
   3868  1.1        is #	None								#
   3869  1.1        is #									#
   3870  1.1        is # ALGORITHM ***********************************************************	#
   3871  1.1        is # "Dummy" CALCulate Effective Address:					#
   3872  1.1        is # 	The stacked <ea> for FP unimplemented instructions and opclass	#
   3873  1.1        is #	two packed instructions is correct with the exception of...	#
   3874  1.1        is #									#
   3875  1.1        is #	1) -(An)   : The register is not updated regardless of size.	#
   3876  1.1        is #		     Also, for extended precision and packed, the 	#
   3877  1.1        is #		     stacked <ea> value is 8 bytes too big		#
   3878  1.1        is #	2) (An)+   : The register is not updated.			#
   3879  1.1        is #	3) #<data> : The upper longword of the immediate operand is 	#
   3880  1.1        is #		     stacked b,w,l and s sizes are completely stacked. 	#
   3881  1.1        is #		     d,x, and p are not.				#
   3882  1.1        is #									#
   3883  1.1        is #########################################################################
   3884  1.1        is 
   3885  1.1        is 	global		_dcalc_ea
   3886  1.1        is _dcalc_ea:
   3887  1.1        is 	mov.l		%d0, %a0		# move # bytes to %a0
   3888  1.1        is 
   3889  1.1        is 	mov.b		1+EXC_OPWORD(%a6), %d0	# fetch opcode word
   3890  1.1        is 	mov.l		%d0, %d1		# make a copy
   3891  1.1        is 
   3892  1.1        is 	andi.w		&0x38, %d0		# extract mode field
   3893  1.1        is 	andi.l		&0x7, %d1		# extract reg  field
   3894  1.1        is 
   3895  1.1        is 	cmpi.b		%d0,&0x18		# is mode (An)+ ?
   3896  1.1        is 	beq.b		dcea_pi			# yes
   3897  1.1        is 
   3898  1.1        is 	cmpi.b		%d0,&0x20		# is mode -(An) ?
   3899  1.1        is 	beq.b		dcea_pd			# yes
   3900  1.1        is 
   3901  1.1        is 	or.w		%d1,%d0			# concat mode,reg
   3902  1.1        is 	cmpi.b		%d0,&0x3c		# is mode #<data>?
   3903  1.1        is 
   3904  1.1        is 	beq.b		dcea_imm		# yes
   3905  1.1        is 
   3906  1.1        is 	mov.l		EXC_EA(%a6),%a0		# return <ea>
   3907  1.1        is 	rts
   3908  1.1        is 
   3909  1.1        is # need to set immediate data flag here since we'll need to do
   3910  1.1        is # an imem_read to fetch this later.
   3911  1.1        is dcea_imm:
   3912  1.1        is 	mov.b		&immed_flg,SPCOND_FLG(%a6)
   3913  1.1        is 	lea		([USER_FPIAR,%a6],0x4),%a0 # no; return <ea>
   3914  1.1        is 	rts
   3915  1.1        is 
   3916  1.1        is # here, the <ea> is stacked correctly. however, we must update the
   3917  1.1        is # address register...
   3918  1.1        is dcea_pi:
   3919  1.1        is 	mov.l		%a0,%d0			# pass amt to inc by
   3920  1.1        is 	bsr.l		inc_areg		# inc addr register
   3921  1.1        is 
   3922  1.1        is 	mov.l		EXC_EA(%a6),%a0		# stacked <ea> is correct
   3923  1.1        is 	rts
   3924  1.1        is 
   3925  1.1        is # the <ea> is stacked correctly for all but extended and packed which
   3926  1.1        is # the <ea>s are 8 bytes too large.
   3927  1.1        is # it would make no sense to have a pre-decrement to a7 in supervisor
   3928  1.1        is # mode so we don't even worry about this tricky case here : )
   3929  1.1        is dcea_pd:
   3930  1.1        is 	mov.l		%a0,%d0			# pass amt to dec by
   3931  1.1        is 	bsr.l		dec_areg		# dec addr register
   3932  1.1        is 
   3933  1.1        is 	mov.l		EXC_EA(%a6),%a0		# stacked <ea> is correct
   3934  1.1        is 
   3935  1.1        is 	cmpi.b		%d0,&0xc		# is opsize ext or packed?
   3936  1.1        is 	beq.b		dcea_pd2		# yes
   3937  1.1        is 	rts
   3938  1.1        is dcea_pd2:
   3939  1.1        is 	sub.l		&0x8,%a0		# correct <ea>
   3940  1.1        is 	mov.l		%a0,EXC_EA(%a6)		# put correct <ea> on stack
   3941  1.1        is 	rts
   3942  1.1        is 
   3943  1.1        is #########################################################################
   3944  1.1        is # XDEF ****************************************************************	#
   3945  1.1        is # 	_calc_ea_fout(): calculate correct stacked <ea> for extended	#
   3946  1.1        is #			 and packed data opclass 3 operations.		#
   3947  1.1        is #									#
   3948  1.1        is # XREF ****************************************************************	#
   3949  1.1        is #	None								#
   3950  1.1        is #									#
   3951  1.1        is # INPUT ***************************************************************	#
   3952  1.1        is #	None								#
   3953  1.1        is # 									#
   3954  1.1        is # OUTPUT **************************************************************	#
   3955  1.1        is #	a0 = return correct effective address				#
   3956  1.1        is #									#
   3957  1.1        is # ALGORITHM ***********************************************************	#
   3958  1.1        is #	For opclass 3 extended and packed data operations, the <ea>	#
   3959  1.1        is # stacked for the exception is incorrect for -(an) and (an)+ addressing	#
   3960  1.1        is # modes. Also, while we're at it, the index register itself must get 	#
   3961  1.1        is # updated.								#
   3962  1.1        is # 	So, for -(an), we must subtract 8 off of the stacked <ea> value	#
   3963  1.1        is # and return that value as the correct <ea> and store that value in An.	#
   3964  1.1        is # For (an)+, the stacked <ea> is correct but we must adjust An by +12.	#
   3965  1.1        is #									#
   3966  1.1        is #########################################################################
   3967  1.1        is 
   3968  1.1        is # This calc_ea is currently used to retrieve the correct <ea>
   3969  1.1        is # for fmove outs of type extended and packed.
   3970  1.1        is 	global		_calc_ea_fout
   3971  1.1        is _calc_ea_fout:
   3972  1.1        is 	mov.b		1+EXC_OPWORD(%a6),%d0	# fetch opcode word
   3973  1.1        is 	mov.l		%d0,%d1			# make a copy
   3974  1.1        is 
   3975  1.1        is 	andi.w		&0x38,%d0		# extract mode field
   3976  1.1        is 	andi.l		&0x7,%d1		# extract reg  field
   3977  1.1        is 
   3978  1.1        is 	cmpi.b		%d0,&0x18		# is mode (An)+ ?
   3979  1.1        is 	beq.b		ceaf_pi			# yes
   3980  1.1        is 
   3981  1.1        is 	cmpi.b		%d0,&0x20		# is mode -(An) ?
   3982  1.1        is 	beq.w		ceaf_pd			# yes
   3983  1.1        is 
   3984  1.1        is 	mov.l		EXC_EA(%a6),%a0		# stacked <ea> is correct
   3985  1.1        is 	rts
   3986  1.1        is 
   3987  1.1        is # (An)+ : extended and packed fmove out
   3988  1.1        is #	: stacked <ea> is correct
   3989  1.1        is #	: "An" not updated
   3990  1.1        is ceaf_pi:
   3991  1.1        is 	mov.w		(tbl_ceaf_pi.b,%pc,%d1.w*2),%d1
   3992  1.1        is 	mov.l		EXC_EA(%a6),%a0
   3993  1.1        is 	jmp		(tbl_ceaf_pi.b,%pc,%d1.w*1)
   3994  1.1        is 
   3995  1.1        is 	swbeg		&0x8
   3996  1.1        is tbl_ceaf_pi:
   3997  1.1        is 	short		ceaf_pi0 - tbl_ceaf_pi
   3998  1.1        is 	short		ceaf_pi1 - tbl_ceaf_pi
   3999  1.1        is 	short		ceaf_pi2 - tbl_ceaf_pi
   4000  1.1        is 	short		ceaf_pi3 - tbl_ceaf_pi
   4001  1.1        is 	short		ceaf_pi4 - tbl_ceaf_pi
   4002  1.1        is 	short		ceaf_pi5 - tbl_ceaf_pi
   4003  1.1        is 	short		ceaf_pi6 - tbl_ceaf_pi
   4004  1.1        is 	short		ceaf_pi7 - tbl_ceaf_pi
   4005  1.1        is 
   4006  1.1        is ceaf_pi0:
   4007  1.1        is 	addi.l		&0xc,EXC_DREGS+0x8(%a6)
   4008  1.1        is 	rts
   4009  1.1        is ceaf_pi1:
   4010  1.1        is 	addi.l		&0xc,EXC_DREGS+0xc(%a6)
   4011  1.1        is 	rts
   4012  1.1        is ceaf_pi2:
   4013  1.1        is 	add.l		&0xc,%a2
   4014  1.1        is 	rts
   4015  1.1        is ceaf_pi3:
   4016  1.1        is 	add.l		&0xc,%a3
   4017  1.1        is 	rts
   4018  1.1        is ceaf_pi4:
   4019  1.1        is 	add.l		&0xc,%a4
   4020  1.1        is 	rts
   4021  1.1        is ceaf_pi5:
   4022  1.1        is 	add.l		&0xc,%a5
   4023  1.1        is 	rts
   4024  1.1        is ceaf_pi6:
   4025  1.1        is 	addi.l		&0xc,EXC_A6(%a6)
   4026  1.1        is 	rts
   4027  1.1        is ceaf_pi7:
   4028  1.1        is 	mov.b		&mia7_flg,SPCOND_FLG(%a6)
   4029  1.1        is 	addi.l		&0xc,EXC_A7(%a6)
   4030  1.1        is 	rts
   4031  1.1        is 
   4032  1.1        is # -(An) : extended and packed fmove out
   4033  1.1        is #	: stacked <ea> = actual <ea> + 8
   4034  1.1        is #	: "An" not updated
   4035  1.1        is ceaf_pd:
   4036  1.1        is 	mov.w		(tbl_ceaf_pd.b,%pc,%d1.w*2),%d1
   4037  1.1        is 	mov.l		EXC_EA(%a6),%a0
   4038  1.1        is 	sub.l		&0x8,%a0
   4039  1.1        is 	sub.l		&0x8,EXC_EA(%a6)
   4040  1.1        is 	jmp		(tbl_ceaf_pd.b,%pc,%d1.w*1)
   4041  1.1        is 
   4042  1.1        is 	swbeg		&0x8
   4043  1.1        is tbl_ceaf_pd:
   4044  1.1        is 	short		ceaf_pd0 - tbl_ceaf_pd
   4045  1.1        is 	short		ceaf_pd1 - tbl_ceaf_pd
   4046  1.1        is 	short		ceaf_pd2 - tbl_ceaf_pd
   4047  1.1        is 	short		ceaf_pd3 - tbl_ceaf_pd
   4048  1.1        is 	short		ceaf_pd4 - tbl_ceaf_pd
   4049  1.1        is 	short		ceaf_pd5 - tbl_ceaf_pd
   4050  1.1        is 	short		ceaf_pd6 - tbl_ceaf_pd
   4051  1.1        is 	short		ceaf_pd7 - tbl_ceaf_pd
   4052  1.1        is 
   4053  1.1        is ceaf_pd0:
   4054  1.1        is 	mov.l		%a0,EXC_DREGS+0x8(%a6)
   4055  1.1        is 	rts
   4056  1.1        is ceaf_pd1:
   4057  1.1        is 	mov.l		%a0,EXC_DREGS+0xc(%a6)
   4058  1.1        is 	rts
   4059  1.1        is ceaf_pd2:
   4060  1.1        is 	mov.l		%a0,%a2
   4061  1.1        is 	rts
   4062  1.1        is ceaf_pd3:
   4063  1.1        is 	mov.l		%a0,%a3
   4064  1.1        is 	rts
   4065  1.1        is ceaf_pd4:
   4066  1.1        is 	mov.l		%a0,%a4
   4067  1.1        is 	rts
   4068  1.1        is ceaf_pd5:
   4069  1.1        is 	mov.l		%a0,%a5
   4070  1.1        is 	rts
   4071  1.1        is ceaf_pd6:
   4072  1.1        is 	mov.l		%a0,EXC_A6(%a6)
   4073  1.1        is 	rts
   4074  1.1        is ceaf_pd7:
   4075  1.1        is 	mov.l		%a0,EXC_A7(%a6)
   4076  1.1        is 	mov.b		&mda7_flg,SPCOND_FLG(%a6)
   4077  1.1        is 	rts
   4078  1.1        is 
   4079  1.1        is #
   4080  1.1        is # This table holds the offsets of the emulation routines for each individual
   4081  1.1        is # math operation relative to the address of this table. Included are
   4082  1.1        is # routines like fadd/fmul/fabs. The transcendentals ARE NOT. This is because
   4083  1.1        is # this table is for the version if the 060FPSP without transcendentals.
   4084  1.1        is # The location within the table is determined by the extension bits of the
   4085  1.1        is # operation longword.
   4086  1.1        is #
   4087  1.1        is 
   4088  1.1        is 	swbeg		&109
   4089  1.1        is tbl_unsupp:
   4090  1.1        is 	long		fin	 	- tbl_unsupp	# 00: fmove
   4091  1.1        is 	long		fint	 	- tbl_unsupp	# 01: fint
   4092  1.1        is 	long		tbl_unsupp 	- tbl_unsupp	# 02: fsinh
   4093  1.1        is 	long		fintrz	 	- tbl_unsupp	# 03: fintrz
   4094  1.1        is 	long		fsqrt	 	- tbl_unsupp	# 04: fsqrt
   4095  1.1        is 	long		tbl_unsupp	- tbl_unsupp
   4096  1.1        is 	long		tbl_unsupp	- tbl_unsupp	# 06: flognp1
   4097  1.1        is 	long		tbl_unsupp	- tbl_unsupp
   4098  1.1        is 	long		tbl_unsupp	- tbl_unsupp	# 08: fetoxm1
   4099  1.1        is 	long		tbl_unsupp	- tbl_unsupp	# 09: ftanh
   4100  1.1        is 	long		tbl_unsupp	- tbl_unsupp	# 0a: fatan
   4101  1.1        is 	long		tbl_unsupp	- tbl_unsupp
   4102  1.1        is 	long		tbl_unsupp	- tbl_unsupp	# 0c: fasin
   4103  1.1        is 	long		tbl_unsupp	- tbl_unsupp	# 0d: fatanh
   4104  1.1        is 	long		tbl_unsupp	- tbl_unsupp	# 0e: fsin
   4105  1.1        is 	long		tbl_unsupp	- tbl_unsupp	# 0f: ftan
   4106  1.1        is 	long		tbl_unsupp	- tbl_unsupp	# 10: fetox
   4107  1.1        is 	long		tbl_unsupp	- tbl_unsupp	# 11: ftwotox
   4108  1.1        is 	long		tbl_unsupp	- tbl_unsupp	# 12: ftentox
   4109  1.1        is 	long		tbl_unsupp	- tbl_unsupp
   4110  1.1        is 	long		tbl_unsupp	- tbl_unsupp	# 14: flogn
   4111  1.1        is 	long		tbl_unsupp	- tbl_unsupp	# 15: flog10
   4112  1.1        is 	long		tbl_unsupp	- tbl_unsupp	# 16: flog2
   4113  1.1        is 	long		tbl_unsupp	- tbl_unsupp
   4114  1.1        is 	long		fabs		- tbl_unsupp 	# 18: fabs
   4115  1.1        is 	long		tbl_unsupp	- tbl_unsupp	# 19: fcosh
   4116  1.1        is 	long		fneg		- tbl_unsupp 	# 1a: fneg
   4117  1.1        is 	long		tbl_unsupp	- tbl_unsupp
   4118  1.1        is 	long		tbl_unsupp	- tbl_unsupp	# 1c: facos
   4119  1.1        is 	long		tbl_unsupp	- tbl_unsupp	# 1d: fcos
   4120  1.1        is 	long		tbl_unsupp	- tbl_unsupp	# 1e: fgetexp
   4121  1.1        is 	long		tbl_unsupp	- tbl_unsupp	# 1f: fgetman
   4122  1.1        is 	long		fdiv		- tbl_unsupp 	# 20: fdiv
   4123  1.1        is 	long		tbl_unsupp	- tbl_unsupp	# 21: fmod
   4124  1.1        is 	long		fadd		- tbl_unsupp 	# 22: fadd
   4125  1.1        is 	long		fmul		- tbl_unsupp 	# 23: fmul
   4126  1.1        is 	long		fsgldiv		- tbl_unsupp 	# 24: fsgldiv
   4127  1.1        is 	long		tbl_unsupp	- tbl_unsupp	# 25: frem
   4128  1.1        is 	long		tbl_unsupp	- tbl_unsupp	# 26: fscale
   4129  1.1        is 	long		fsglmul		- tbl_unsupp 	# 27: fsglmul
   4130  1.1        is 	long		fsub		- tbl_unsupp 	# 28: fsub
   4131  1.1        is 	long		tbl_unsupp	- tbl_unsupp
   4132  1.1        is 	long		tbl_unsupp	- tbl_unsupp
   4133  1.1        is 	long		tbl_unsupp	- tbl_unsupp
   4134  1.1        is 	long		tbl_unsupp	- tbl_unsupp
   4135  1.1        is 	long		tbl_unsupp	- tbl_unsupp
   4136  1.1        is 	long		tbl_unsupp	- tbl_unsupp
   4137  1.1        is 	long		tbl_unsupp	- tbl_unsupp
   4138  1.1        is 	long		tbl_unsupp	- tbl_unsupp	# 30: fsincos
   4139  1.1        is 	long		tbl_unsupp	- tbl_unsupp	# 31: fsincos
   4140  1.1        is 	long		tbl_unsupp	- tbl_unsupp	# 32: fsincos
   4141  1.1        is 	long		tbl_unsupp	- tbl_unsupp	# 33: fsincos
   4142  1.1        is 	long		tbl_unsupp	- tbl_unsupp	# 34: fsincos
   4143  1.1        is 	long		tbl_unsupp	- tbl_unsupp	# 35: fsincos
   4144  1.1        is 	long		tbl_unsupp	- tbl_unsupp	# 36: fsincos
   4145  1.1        is 	long		tbl_unsupp	- tbl_unsupp	# 37: fsincos
   4146  1.1        is 	long		fcmp		- tbl_unsupp 	# 38: fcmp
   4147  1.1        is 	long		tbl_unsupp	- tbl_unsupp
   4148  1.1        is 	long		ftst		- tbl_unsupp 	# 3a: ftst
   4149  1.1        is 	long		tbl_unsupp	- tbl_unsupp
   4150  1.1        is 	long		tbl_unsupp	- tbl_unsupp
   4151  1.1        is 	long		tbl_unsupp	- tbl_unsupp
   4152  1.1        is 	long		tbl_unsupp	- tbl_unsupp
   4153  1.1        is 	long		tbl_unsupp	- tbl_unsupp
   4154  1.1        is 	long		fsin		- tbl_unsupp 	# 40: fsmove
   4155  1.1        is 	long		fssqrt		- tbl_unsupp 	# 41: fssqrt
   4156  1.1        is 	long		tbl_unsupp	- tbl_unsupp
   4157  1.1        is 	long		tbl_unsupp	- tbl_unsupp
   4158  1.1        is 	long		fdin		- tbl_unsupp	# 44: fdmove
   4159  1.1        is 	long		fdsqrt		- tbl_unsupp 	# 45: fdsqrt
   4160  1.1        is 	long		tbl_unsupp	- tbl_unsupp
   4161  1.1        is 	long		tbl_unsupp	- tbl_unsupp
   4162  1.1        is 	long		tbl_unsupp	- tbl_unsupp
   4163  1.1        is 	long		tbl_unsupp	- tbl_unsupp
   4164  1.1        is 	long		tbl_unsupp	- tbl_unsupp
   4165  1.1        is 	long		tbl_unsupp	- tbl_unsupp
   4166  1.1        is 	long		tbl_unsupp	- tbl_unsupp
   4167  1.1        is 	long		tbl_unsupp	- tbl_unsupp
   4168  1.1        is 	long		tbl_unsupp	- tbl_unsupp
   4169  1.1        is 	long		tbl_unsupp	- tbl_unsupp
   4170  1.1        is 	long		tbl_unsupp	- tbl_unsupp
   4171  1.1        is 	long		tbl_unsupp	- tbl_unsupp
   4172  1.1        is 	long		tbl_unsupp	- tbl_unsupp
   4173  1.1        is 	long		tbl_unsupp	- tbl_unsupp
   4174  1.1        is 	long		tbl_unsupp	- tbl_unsupp
   4175  1.1        is 	long		tbl_unsupp	- tbl_unsupp
   4176  1.1        is 	long		tbl_unsupp	- tbl_unsupp
   4177  1.1        is 	long		tbl_unsupp	- tbl_unsupp
   4178  1.1        is 	long		fsabs		- tbl_unsupp 	# 58: fsabs
   4179  1.1        is 	long		tbl_unsupp	- tbl_unsupp
   4180  1.1        is 	long		fsneg		- tbl_unsupp 	# 5a: fsneg
   4181  1.1        is 	long		tbl_unsupp	- tbl_unsupp
   4182  1.1        is 	long		fdabs		- tbl_unsupp	# 5c: fdabs
   4183  1.1        is 	long		tbl_unsupp	- tbl_unsupp
   4184  1.1        is 	long		fdneg		- tbl_unsupp 	# 5e: fdneg
   4185  1.1        is 	long		tbl_unsupp	- tbl_unsupp
   4186  1.1        is 	long		fsdiv		- tbl_unsupp	# 60: fsdiv
   4187  1.1        is 	long		tbl_unsupp	- tbl_unsupp
   4188  1.1        is 	long		fsadd		- tbl_unsupp	# 62: fsadd
   4189  1.1        is 	long		fsmul		- tbl_unsupp	# 63: fsmul
   4190  1.1        is 	long		fddiv		- tbl_unsupp 	# 64: fddiv
   4191  1.1        is 	long		tbl_unsupp	- tbl_unsupp
   4192  1.1        is 	long		fdadd		- tbl_unsupp	# 66: fdadd
   4193  1.1        is 	long		fdmul		- tbl_unsupp 	# 67: fdmul
   4194  1.1        is 	long		fssub		- tbl_unsupp	# 68: fssub
   4195  1.1        is 	long		tbl_unsupp	- tbl_unsupp
   4196  1.1        is 	long		tbl_unsupp	- tbl_unsupp
   4197  1.1        is 	long		tbl_unsupp	- tbl_unsupp
   4198  1.1        is 	long		fdsub		- tbl_unsupp 	# 6c: fdsub
   4199  1.1        is 
   4200  1.1        is #################################################
   4201  1.1        is # Add this here so non-fp modules can compile.
   4202  1.1        is # (smovcr is called from fpsp_inex.)
   4203  1.1        is 	global		smovcr
   4204  1.1        is smovcr:
   4205  1.1        is 	bra.b		smovcr
   4206  1.1        is 
   4207  1.1        is #########################################################################
   4208  1.1        is # XDEF ****************************************************************	#
   4209  1.1        is #	fmovm_dynamic(): emulate "fmovm" dynamic instruction		#
   4210  1.1        is #									#
   4211  1.1        is # XREF ****************************************************************	#
   4212  1.1        is #	fetch_dreg() - fetch data register				#
   4213  1.1        is #	{i,d,}mem_read() - fetch data from memory			#
   4214  1.1        is #	_mem_write() - write data to memory				#
   4215  1.1        is #	iea_iacc() - instruction memory access error occurred		#
   4216  1.1        is #	iea_dacc() - data memory access error occurred			#
   4217  1.1        is #	restore() - restore An index regs if access error occurred	#
   4218  1.1        is #									#
   4219  1.1        is # INPUT ***************************************************************	#
   4220  1.1        is #	None								#
   4221  1.1        is # 									#
   4222  1.1        is # OUTPUT **************************************************************	#
   4223  1.1        is #	If instr is "fmovm Dn,-(A7)" from supervisor mode,		#
   4224  1.1        is #		d0 = size of dump					#
   4225  1.1        is #		d1 = Dn							#
   4226  1.1        is #	Else if instruction access error,				#
   4227  1.1        is #		d0 = FSLW						#
   4228  1.1        is #	Else if data access error,					#
   4229  1.1        is #		d0 = FSLW						#
   4230  1.1        is #		a0 = address of fault					#
   4231  1.1        is #	Else								#
   4232  1.1        is #		none.							#
   4233  1.1        is #									#
   4234  1.1        is # ALGORITHM ***********************************************************	#
   4235  1.1        is #	The effective address must be calculated since this is entered	#
   4236  1.1        is # from an "Unimplemented Effective Address" exception handler. So, we	#
   4237  1.1        is # have our own fcalc_ea() routine here. If an access error is flagged	#
   4238  1.1        is # by a _{i,d,}mem_read() call, we must exit through the special		#
   4239  1.1        is # handler.								#
   4240  1.1        is #	The data register is determined and its value loaded to get the	#
   4241  1.1        is # string of FP registers affected. This value is used as an index into	#
   4242  1.1        is # a lookup table such that we can determine the number of bytes		#
   4243  1.1        is # involved. 								#
   4244  1.1        is #	If the instruction is "fmovm.x <ea>,Dn", a _mem_read() is used	#
   4245  1.1        is # to read in all FP values. Again, _mem_read() may fail and require a	#
   4246  1.1        is # special exit. 							#
   4247  1.1        is #	If the instruction is "fmovm.x DN,<ea>", a _mem_write() is used	#
   4248  1.1        is # to write all FP values. _mem_write() may also fail.			#
   4249  1.1        is # 	If the instruction is "fmovm.x DN,-(a7)" from supervisor mode,	#
   4250  1.1        is # then we return the size of the dump and the string to the caller	#
   4251  1.1        is # so that the move can occur outside of this routine. This special	#
   4252  1.1        is # case is required so that moves to the system stack are handled	#
   4253  1.1        is # correctly.								#
   4254  1.1        is #									#
   4255  1.1        is # DYNAMIC:								#
   4256  1.1        is # 	fmovm.x	dn, <ea>						#
   4257  1.1        is # 	fmovm.x	<ea>, dn						#
   4258  1.1        is #									#
   4259  1.1        is #	      <WORD 1>		      <WORD2>				#
   4260  1.1        is #	1111 0010 00 |<ea>|	11@& 1000 0$$$ 0000			#
   4261  1.1        is #					  				#
   4262  1.1        is #	& = (0): predecrement addressing mode				#
   4263  1.1        is #	    (1): postincrement or control addressing mode		#
   4264  1.1        is #	@ = (0): move listed regs from memory to the FPU		#
   4265  1.1        is #	    (1): move listed regs from the FPU to memory		#
   4266  1.1        is #	$$$    : index of data register holding reg select mask		#
   4267  1.1        is #									#
   4268  1.1        is # NOTES:								#
   4269  1.1        is #	If the data register holds a zero, then the			#
   4270  1.1        is #	instruction is a nop.						#
   4271  1.1        is #									#
   4272  1.1        is #########################################################################
   4273  1.1        is 
   4274  1.1        is 	global		fmovm_dynamic
   4275  1.1        is fmovm_dynamic:
   4276  1.1        is 
   4277  1.1        is # extract the data register in which the bit string resides...
   4278  1.1        is 	mov.b		1+EXC_EXTWORD(%a6),%d1	# fetch extword
   4279  1.1        is 	andi.w		&0x70,%d1		# extract reg bits
   4280  1.1        is 	lsr.b		&0x4,%d1		# shift into lo bits
   4281  1.1        is 
   4282  1.1        is # fetch the bit string into d0...
   4283  1.1        is 	bsr.l		fetch_dreg		# fetch reg string
   4284  1.1        is 
   4285  1.1        is 	andi.l		&0x000000ff,%d0		# keep only lo byte
   4286  1.1        is 
   4287  1.1        is 	mov.l		%d0,-(%sp)		# save strg
   4288  1.1        is 	mov.b		(tbl_fmovm_size.w,%pc,%d0),%d0
   4289  1.1        is 	mov.l		%d0,-(%sp)		# save size
   4290  1.1        is 	bsr.l		fmovm_calc_ea		# calculate <ea>
   4291  1.1        is 	mov.l		(%sp)+,%d0		# restore size
   4292  1.1        is 	mov.l		(%sp)+,%d1		# restore strg
   4293  1.1        is 
   4294  1.1        is # if the bit string is a zero, then the operation is a no-op
   4295  1.1        is # but, make sure that we've calculated ea and advanced the opword pointer
   4296  1.1        is 	beq.w		fmovm_data_done
   4297  1.1        is 
   4298  1.1        is # separate move ins from move outs...
   4299  1.1        is 	btst		&0x5,EXC_EXTWORD(%a6)	# is it a move in or out?
   4300  1.1        is 	beq.w		fmovm_data_in		# it's a move out
   4301  1.1        is 
   4302  1.1        is #############
   4303  1.1        is # MOVE OUT: #
   4304  1.1        is #############
   4305  1.1        is fmovm_data_out:
   4306  1.1        is 	btst		&0x4,EXC_EXTWORD(%a6)	# control or predecrement?
   4307  1.1        is 	bne.w		fmovm_out_ctrl		# control
   4308  1.1        is 
   4309  1.1        is ############################
   4310  1.1        is fmovm_out_predec:
   4311  1.1        is # for predecrement mode, the bit string is the opposite of both control
   4312  1.1        is # operations and postincrement mode. (bit7 = FP7 ... bit0 = FP0)
   4313  1.1        is # here, we convert it to be just like the others...
   4314  1.1        is 	mov.b		(tbl_fmovm_convert.w,%pc,%d1.w*1),%d1
   4315  1.1        is 
   4316  1.1        is 	btst		&0x5,EXC_SR(%a6)	# user or supervisor mode?
   4317  1.1        is 	beq.b		fmovm_out_ctrl		# user
   4318  1.1        is 
   4319  1.1        is fmovm_out_predec_s:
   4320  1.1        is 	cmpi.b		SPCOND_FLG(%a6),&mda7_flg # is <ea> mode -(a7)?
   4321  1.1        is 	bne.b		fmovm_out_ctrl
   4322  1.1        is 
   4323  1.1        is # the operation was unfortunately an: fmovm.x dn,-(sp)
   4324  1.1        is # called from supervisor mode.
   4325  1.1        is # we're also passing "size" and "strg" back to the calling routine
   4326  1.1        is 	rts
   4327  1.1        is 
   4328  1.1        is ############################
   4329  1.1        is fmovm_out_ctrl:
   4330  1.1        is 	mov.l		%a0,%a1			# move <ea> to a1
   4331  1.1        is 
   4332  1.1        is 	sub.l		%d0,%sp			# subtract size of dump
   4333  1.1        is 	lea		(%sp),%a0
   4334  1.1        is 
   4335  1.1        is 	tst.b		%d1			# should FP0 be moved?
   4336  1.1        is 	bpl.b		fmovm_out_ctrl_fp1	# no
   4337  1.1        is 
   4338  1.1        is 	mov.l		0x0+EXC_FP0(%a6),(%a0)+	# yes
   4339  1.1        is 	mov.l		0x4+EXC_FP0(%a6),(%a0)+
   4340  1.1        is 	mov.l		0x8+EXC_FP0(%a6),(%a0)+
   4341  1.1        is 
   4342  1.1        is fmovm_out_ctrl_fp1:
   4343  1.1        is 	lsl.b		&0x1,%d1		# should FP1 be moved?
   4344  1.1        is 	bpl.b		fmovm_out_ctrl_fp2	# no
   4345  1.1        is 
   4346  1.1        is 	mov.l		0x0+EXC_FP1(%a6),(%a0)+	# yes
   4347  1.1        is 	mov.l		0x4+EXC_FP1(%a6),(%a0)+
   4348  1.1        is 	mov.l		0x8+EXC_FP1(%a6),(%a0)+
   4349  1.1        is 
   4350  1.1        is fmovm_out_ctrl_fp2:
   4351  1.1        is 	lsl.b		&0x1,%d1		# should FP2 be moved?
   4352  1.1        is 	bpl.b		fmovm_out_ctrl_fp3	# no
   4353  1.1        is 
   4354  1.1        is 	fmovm.x		&0x20,(%a0)		# yes
   4355  1.1        is 	add.l		&0xc,%a0
   4356  1.1        is 
   4357  1.1        is fmovm_out_ctrl_fp3:
   4358  1.1        is 	lsl.b		&0x1,%d1		# should FP3 be moved?
   4359  1.1        is 	bpl.b		fmovm_out_ctrl_fp4	# no
   4360  1.1        is 
   4361  1.1        is 	fmovm.x		&0x10,(%a0)		# yes
   4362  1.1        is 	add.l		&0xc,%a0
   4363  1.1        is 
   4364  1.1        is fmovm_out_ctrl_fp4:
   4365  1.1        is 	lsl.b		&0x1,%d1		# should FP4 be moved?
   4366  1.1        is 	bpl.b		fmovm_out_ctrl_fp5	# no
   4367  1.1        is 
   4368  1.1        is 	fmovm.x		&0x08,(%a0)		# yes
   4369  1.1        is 	add.l		&0xc,%a0
   4370  1.1        is 
   4371  1.1        is fmovm_out_ctrl_fp5:
   4372  1.1        is 	lsl.b		&0x1,%d1		# should FP5 be moved?
   4373  1.1        is 	bpl.b		fmovm_out_ctrl_fp6	# no
   4374  1.1        is 
   4375  1.1        is 	fmovm.x		&0x04,(%a0)		# yes
   4376  1.1        is 	add.l		&0xc,%a0
   4377  1.1        is 
   4378  1.1        is fmovm_out_ctrl_fp6:
   4379  1.1        is 	lsl.b		&0x1,%d1		# should FP6 be moved?
   4380  1.1        is 	bpl.b		fmovm_out_ctrl_fp7	# no
   4381  1.1        is 
   4382  1.1        is 	fmovm.x		&0x02,(%a0)		# yes
   4383  1.1        is 	add.l		&0xc,%a0
   4384  1.1        is 
   4385  1.1        is fmovm_out_ctrl_fp7:
   4386  1.1        is 	lsl.b		&0x1,%d1		# should FP7 be moved?
   4387  1.1        is 	bpl.b		fmovm_out_ctrl_done	# no
   4388  1.1        is 
   4389  1.1        is 	fmovm.x		&0x01,(%a0)		# yes
   4390  1.1        is 	add.l		&0xc,%a0
   4391  1.1        is 
   4392  1.1        is fmovm_out_ctrl_done:
   4393  1.1        is 	mov.l		%a1,L_SCR1(%a6)
   4394  1.1        is 
   4395  1.1        is 	lea		(%sp),%a0		# pass: supervisor src
   4396  1.1        is 	mov.l		%d0,-(%sp)		# save size
   4397  1.1        is 	bsr.l		_dmem_write		# copy data to user mem
   4398  1.1        is 
   4399  1.1        is 	mov.l		(%sp)+,%d0
   4400  1.1        is 	add.l		%d0,%sp			# clear fpreg data from stack
   4401  1.1        is 
   4402  1.1        is 	tst.l		%d1			# did dstore err?
   4403  1.1        is 	bne.w		fmovm_out_err		# yes
   4404  1.1        is 
   4405  1.1        is 	rts
   4406  1.1        is 
   4407  1.1        is ############
   4408  1.1        is # MOVE IN: #
   4409  1.1        is ############
   4410  1.1        is fmovm_data_in:
   4411  1.1        is 	mov.l		%a0,L_SCR1(%a6)
   4412  1.1        is 
   4413  1.1        is 	sub.l		%d0,%sp			# make room for fpregs
   4414  1.1        is 	lea		(%sp),%a1
   4415  1.1        is 
   4416  1.1        is 	mov.l		%d1,-(%sp)		# save bit string for later
   4417  1.1        is 	mov.l		%d0,-(%sp)		# save # of bytes
   4418  1.1        is 
   4419  1.1        is 	bsr.l		_dmem_read		# copy data from user mem
   4420  1.1        is 
   4421  1.1        is 	mov.l		(%sp)+,%d0		# retrieve # of bytes
   4422  1.1        is 
   4423  1.1        is 	tst.l		%d1			# did dfetch fail?
   4424  1.1        is 	bne.w		fmovm_in_err		# yes
   4425  1.1        is 
   4426  1.1        is 	mov.l		(%sp)+,%d1		# load bit string
   4427  1.1        is 
   4428  1.1        is 	lea		(%sp),%a0		# addr of stack
   4429  1.1        is 
   4430  1.1        is 	tst.b		%d1			# should FP0 be moved?
   4431  1.1        is 	bpl.b		fmovm_data_in_fp1	# no
   4432  1.1        is 
   4433  1.1        is 	mov.l		(%a0)+,0x0+EXC_FP0(%a6)	# yes
   4434  1.1        is 	mov.l		(%a0)+,0x4+EXC_FP0(%a6)
   4435  1.1        is 	mov.l		(%a0)+,0x8+EXC_FP0(%a6)
   4436  1.1        is 
   4437  1.1        is fmovm_data_in_fp1:
   4438  1.1        is 	lsl.b		&0x1,%d1		# should FP1 be moved?
   4439  1.1        is 	bpl.b		fmovm_data_in_fp2	# no
   4440  1.1        is 
   4441  1.1        is 	mov.l		(%a0)+,0x0+EXC_FP1(%a6)	# yes
   4442  1.1        is 	mov.l		(%a0)+,0x4+EXC_FP1(%a6)
   4443  1.1        is 	mov.l		(%a0)+,0x8+EXC_FP1(%a6)
   4444  1.1        is 
   4445  1.1        is fmovm_data_in_fp2:
   4446  1.1        is 	lsl.b		&0x1,%d1		# should FP2 be moved?
   4447  1.1        is 	bpl.b		fmovm_data_in_fp3	# no
   4448  1.1        is 
   4449  1.1        is 	fmovm.x		(%a0)+,&0x20		# yes
   4450  1.1        is 
   4451  1.1        is fmovm_data_in_fp3:
   4452  1.1        is 	lsl.b		&0x1,%d1		# should FP3 be moved?
   4453  1.1        is 	bpl.b		fmovm_data_in_fp4	# no
   4454  1.1        is 
   4455  1.1        is 	fmovm.x		(%a0)+,&0x10		# yes
   4456  1.1        is 
   4457  1.1        is fmovm_data_in_fp4:
   4458  1.1        is 	lsl.b		&0x1,%d1		# should FP4 be moved?
   4459  1.1        is 	bpl.b		fmovm_data_in_fp5	# no
   4460  1.1        is 
   4461  1.1        is 	fmovm.x		(%a0)+,&0x08		# yes
   4462  1.1        is 
   4463  1.1        is fmovm_data_in_fp5:
   4464  1.1        is 	lsl.b		&0x1,%d1		# should FP5 be moved?
   4465  1.1        is 	bpl.b		fmovm_data_in_fp6	# no
   4466  1.1        is 
   4467  1.1        is 	fmovm.x		(%a0)+,&0x04		# yes
   4468  1.1        is 
   4469  1.1        is fmovm_data_in_fp6:
   4470  1.1        is 	lsl.b		&0x1,%d1		# should FP6 be moved?
   4471  1.1        is 	bpl.b		fmovm_data_in_fp7	# no
   4472  1.1        is 
   4473  1.1        is 	fmovm.x		(%a0)+,&0x02		# yes
   4474  1.1        is 
   4475  1.1        is fmovm_data_in_fp7:
   4476  1.1        is 	lsl.b		&0x1,%d1		# should FP7 be moved?
   4477  1.1        is 	bpl.b		fmovm_data_in_done	# no
   4478  1.1        is 
   4479  1.1        is 	fmovm.x		(%a0)+,&0x01		# yes
   4480  1.1        is 
   4481  1.1        is fmovm_data_in_done:
   4482  1.1        is 	add.l		%d0,%sp			# remove fpregs from stack
   4483  1.1        is 	rts
   4484  1.1        is 
   4485  1.1        is #####################################
   4486  1.1        is 
   4487  1.1        is fmovm_data_done:
   4488  1.1        is 	rts
   4489  1.1        is 
   4490  1.1        is ##############################################################################
   4491  1.1        is 
   4492  1.1        is #
   4493  1.1        is # table indexed by the operation's bit string that gives the number
   4494  1.1        is # of bytes that will be moved.
   4495  1.1        is #
   4496  1.1        is # number of bytes = (# of 1's in bit string) * 12(bytes/fpreg)
   4497  1.1        is #
   4498  1.1        is tbl_fmovm_size:
   4499  1.1        is 	byte	0x00,0x0c,0x0c,0x18,0x0c,0x18,0x18,0x24
   4500  1.1        is 	byte	0x0c,0x18,0x18,0x24,0x18,0x24,0x24,0x30
   4501  1.1        is 	byte	0x0c,0x18,0x18,0x24,0x18,0x24,0x24,0x30
   4502  1.1        is 	byte	0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
   4503  1.1        is 	byte	0x0c,0x18,0x18,0x24,0x18,0x24,0x24,0x30
   4504  1.1        is 	byte	0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
   4505  1.1        is 	byte	0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
   4506  1.1        is 	byte	0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
   4507  1.1        is 	byte	0x0c,0x18,0x18,0x24,0x18,0x24,0x24,0x30
   4508  1.1        is 	byte	0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
   4509  1.1        is 	byte	0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
   4510  1.1        is 	byte	0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
   4511  1.1        is 	byte	0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
   4512  1.1        is 	byte	0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
   4513  1.1        is 	byte	0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
   4514  1.1        is 	byte	0x30,0x3c,0x3c,0x48,0x3c,0x48,0x48,0x54
   4515  1.1        is 	byte	0x0c,0x18,0x18,0x24,0x18,0x24,0x24,0x30
   4516  1.1        is 	byte	0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
   4517  1.1        is 	byte	0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
   4518  1.1        is 	byte	0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
   4519  1.1        is 	byte	0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
   4520  1.1        is 	byte	0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
   4521  1.1        is 	byte	0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
   4522  1.1        is 	byte	0x30,0x3c,0x3c,0x48,0x3c,0x48,0x48,0x54
   4523  1.1        is 	byte	0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
   4524  1.1        is 	byte	0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
   4525  1.1        is 	byte	0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
   4526  1.1        is 	byte	0x30,0x3c,0x3c,0x48,0x3c,0x48,0x48,0x54
   4527  1.1        is 	byte	0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
   4528  1.1        is 	byte	0x30,0x3c,0x3c,0x48,0x3c,0x48,0x48,0x54
   4529  1.1        is 	byte	0x30,0x3c,0x3c,0x48,0x3c,0x48,0x48,0x54
   4530  1.1        is 	byte	0x3c,0x48,0x48,0x54,0x48,0x54,0x54,0x60
   4531  1.1        is 
   4532  1.1        is #
   4533  1.1        is # table to convert a pre-decrement bit string into a post-increment
   4534  1.1        is # or control bit string.
   4535  1.1        is # ex: 	0x00	==>	0x00
   4536  1.1        is #	0x01	==>	0x80
   4537  1.1        is #	0x02	==>	0x40
   4538  1.1        is #		.
   4539  1.1        is #		.
   4540  1.1        is #	0xfd	==>	0xbf
   4541  1.1        is #	0xfe	==>	0x7f
   4542  1.1        is #	0xff	==>	0xff
   4543  1.1        is #
   4544  1.1        is tbl_fmovm_convert:
   4545  1.1        is 	byte	0x00,0x80,0x40,0xc0,0x20,0xa0,0x60,0xe0
   4546  1.1        is 	byte	0x10,0x90,0x50,0xd0,0x30,0xb0,0x70,0xf0
   4547  1.1        is 	byte	0x08,0x88,0x48,0xc8,0x28,0xa8,0x68,0xe8
   4548  1.1        is 	byte	0x18,0x98,0x58,0xd8,0x38,0xb8,0x78,0xf8
   4549  1.1        is 	byte	0x04,0x84,0x44,0xc4,0x24,0xa4,0x64,0xe4
   4550  1.1        is 	byte	0x14,0x94,0x54,0xd4,0x34,0xb4,0x74,0xf4
   4551  1.1        is 	byte	0x0c,0x8c,0x4c,0xcc,0x2c,0xac,0x6c,0xec
   4552  1.1        is 	byte	0x1c,0x9c,0x5c,0xdc,0x3c,0xbc,0x7c,0xfc
   4553  1.1        is 	byte	0x02,0x82,0x42,0xc2,0x22,0xa2,0x62,0xe2
   4554  1.1        is 	byte	0x12,0x92,0x52,0xd2,0x32,0xb2,0x72,0xf2
   4555  1.1        is 	byte	0x0a,0x8a,0x4a,0xca,0x2a,0xaa,0x6a,0xea
   4556  1.1        is 	byte	0x1a,0x9a,0x5a,0xda,0x3a,0xba,0x7a,0xfa
   4557  1.1        is 	byte	0x06,0x86,0x46,0xc6,0x26,0xa6,0x66,0xe6
   4558  1.1        is 	byte	0x16,0x96,0x56,0xd6,0x36,0xb6,0x76,0xf6
   4559  1.1        is 	byte	0x0e,0x8e,0x4e,0xce,0x2e,0xae,0x6e,0xee
   4560  1.1        is 	byte	0x1e,0x9e,0x5e,0xde,0x3e,0xbe,0x7e,0xfe
   4561  1.1        is 	byte	0x01,0x81,0x41,0xc1,0x21,0xa1,0x61,0xe1
   4562  1.1        is 	byte	0x11,0x91,0x51,0xd1,0x31,0xb1,0x71,0xf1
   4563  1.1        is 	byte	0x09,0x89,0x49,0xc9,0x29,0xa9,0x69,0xe9
   4564  1.1        is 	byte	0x19,0x99,0x59,0xd9,0x39,0xb9,0x79,0xf9
   4565  1.1        is 	byte	0x05,0x85,0x45,0xc5,0x25,0xa5,0x65,0xe5
   4566  1.1        is 	byte	0x15,0x95,0x55,0xd5,0x35,0xb5,0x75,0xf5
   4567  1.1        is 	byte	0x0d,0x8d,0x4d,0xcd,0x2d,0xad,0x6d,0xed
   4568  1.1        is 	byte	0x1d,0x9d,0x5d,0xdd,0x3d,0xbd,0x7d,0xfd
   4569  1.1        is 	byte	0x03,0x83,0x43,0xc3,0x23,0xa3,0x63,0xe3
   4570  1.1        is 	byte	0x13,0x93,0x53,0xd3,0x33,0xb3,0x73,0xf3
   4571  1.1        is 	byte	0x0b,0x8b,0x4b,0xcb,0x2b,0xab,0x6b,0xeb
   4572  1.1        is 	byte	0x1b,0x9b,0x5b,0xdb,0x3b,0xbb,0x7b,0xfb
   4573  1.1        is 	byte	0x07,0x87,0x47,0xc7,0x27,0xa7,0x67,0xe7
   4574  1.1        is 	byte	0x17,0x97,0x57,0xd7,0x37,0xb7,0x77,0xf7
   4575  1.1        is 	byte	0x0f,0x8f,0x4f,0xcf,0x2f,0xaf,0x6f,0xef
   4576  1.1        is 	byte	0x1f,0x9f,0x5f,0xdf,0x3f,0xbf,0x7f,0xff
   4577  1.1        is 
   4578  1.1        is 	global		fmovm_calc_ea
   4579  1.1        is ###############################################
   4580  1.1        is # _fmovm_calc_ea: calculate effective address #
   4581  1.1        is ###############################################
   4582  1.1        is fmovm_calc_ea:
   4583  1.1        is 	mov.l		%d0,%a0			# move # bytes to a0
   4584  1.1        is 
   4585  1.1        is # currently, MODE and REG are taken from the EXC_OPWORD. this could be
   4586  1.1        is # easily changed if they were inputs passed in registers.
   4587  1.1        is 	mov.w		EXC_OPWORD(%a6),%d0	# fetch opcode word
   4588  1.1        is 	mov.w		%d0,%d1			# make a copy
   4589  1.1        is 
   4590  1.1        is 	andi.w		&0x3f,%d0		# extract mode field
   4591  1.1        is 	andi.l		&0x7,%d1		# extract reg  field
   4592  1.1        is 
   4593  1.1        is # jump to the corresponding function for each {MODE,REG} pair.
   4594  1.1        is 	mov.w		(tbl_fea_mode.b,%pc,%d0.w*2),%d0 # fetch jmp distance
   4595  1.1        is 	jmp		(tbl_fea_mode.b,%pc,%d0.w*1) # jmp to correct ea mode
   4596  1.1        is 
   4597  1.1        is 	swbeg		&64
   4598  1.1        is tbl_fea_mode:
   4599  1.1        is 	short		tbl_fea_mode	-	tbl_fea_mode
   4600  1.1        is 	short		tbl_fea_mode	-	tbl_fea_mode
   4601  1.1        is 	short		tbl_fea_mode	-	tbl_fea_mode
   4602  1.1        is 	short		tbl_fea_mode	-	tbl_fea_mode
   4603  1.1        is 	short		tbl_fea_mode	-	tbl_fea_mode
   4604  1.1        is 	short		tbl_fea_mode	-	tbl_fea_mode
   4605  1.1        is 	short		tbl_fea_mode	-	tbl_fea_mode
   4606  1.1        is 	short		tbl_fea_mode	-	tbl_fea_mode
   4607  1.1        is 
   4608  1.1        is 	short		tbl_fea_mode	-	tbl_fea_mode
   4609  1.1        is 	short		tbl_fea_mode	-	tbl_fea_mode
   4610  1.1        is 	short		tbl_fea_mode	-	tbl_fea_mode
   4611  1.1        is 	short		tbl_fea_mode	-	tbl_fea_mode
   4612  1.1        is 	short		tbl_fea_mode	-	tbl_fea_mode
   4613  1.1        is 	short		tbl_fea_mode	-	tbl_fea_mode
   4614  1.1        is 	short		tbl_fea_mode	-	tbl_fea_mode
   4615  1.1        is 	short		tbl_fea_mode	-	tbl_fea_mode
   4616  1.1        is 
   4617  1.1        is 	short		faddr_ind_a0	- 	tbl_fea_mode
   4618  1.1        is 	short		faddr_ind_a1	- 	tbl_fea_mode
   4619  1.1        is 	short		faddr_ind_a2	- 	tbl_fea_mode
   4620  1.1        is 	short		faddr_ind_a3 	- 	tbl_fea_mode
   4621  1.1        is 	short		faddr_ind_a4 	- 	tbl_fea_mode
   4622  1.1        is 	short		faddr_ind_a5 	- 	tbl_fea_mode
   4623  1.1        is 	short		faddr_ind_a6 	- 	tbl_fea_mode
   4624  1.1        is 	short		faddr_ind_a7 	- 	tbl_fea_mode
   4625  1.1        is 
   4626  1.1        is 	short		faddr_ind_p_a0	- 	tbl_fea_mode
   4627  1.1        is 	short		faddr_ind_p_a1 	- 	tbl_fea_mode
   4628  1.1        is 	short		faddr_ind_p_a2 	- 	tbl_fea_mode
   4629  1.1        is 	short		faddr_ind_p_a3 	- 	tbl_fea_mode
   4630  1.1        is 	short		faddr_ind_p_a4 	- 	tbl_fea_mode
   4631  1.1        is 	short		faddr_ind_p_a5 	- 	tbl_fea_mode
   4632  1.1        is 	short		faddr_ind_p_a6 	- 	tbl_fea_mode
   4633  1.1        is 	short		faddr_ind_p_a7 	- 	tbl_fea_mode
   4634  1.1        is 
   4635  1.1        is 	short		faddr_ind_m_a0 	- 	tbl_fea_mode
   4636  1.1        is 	short		faddr_ind_m_a1 	- 	tbl_fea_mode
   4637  1.1        is 	short		faddr_ind_m_a2 	- 	tbl_fea_mode
   4638  1.1        is 	short		faddr_ind_m_a3 	- 	tbl_fea_mode
   4639  1.1        is 	short		faddr_ind_m_a4 	- 	tbl_fea_mode
   4640  1.1        is 	short		faddr_ind_m_a5 	- 	tbl_fea_mode
   4641  1.1        is 	short		faddr_ind_m_a6 	- 	tbl_fea_mode
   4642  1.1        is 	short		faddr_ind_m_a7 	- 	tbl_fea_mode
   4643  1.1        is 
   4644  1.1        is 	short		faddr_ind_disp_a0	- 	tbl_fea_mode
   4645  1.1        is 	short		faddr_ind_disp_a1 	- 	tbl_fea_mode
   4646  1.1        is 	short		faddr_ind_disp_a2 	- 	tbl_fea_mode
   4647  1.1        is 	short		faddr_ind_disp_a3 	- 	tbl_fea_mode
   4648  1.1        is 	short		faddr_ind_disp_a4 	- 	tbl_fea_mode
   4649  1.1        is 	short		faddr_ind_disp_a5 	- 	tbl_fea_mode
   4650  1.1        is 	short		faddr_ind_disp_a6 	- 	tbl_fea_mode
   4651  1.1        is 	short		faddr_ind_disp_a7	-	tbl_fea_mode
   4652  1.1        is 
   4653  1.1        is 	short		faddr_ind_ext 	- 	tbl_fea_mode
   4654  1.1        is 	short		faddr_ind_ext 	- 	tbl_fea_mode
   4655  1.1        is 	short		faddr_ind_ext 	- 	tbl_fea_mode
   4656  1.1        is 	short		faddr_ind_ext 	- 	tbl_fea_mode
   4657  1.1        is 	short		faddr_ind_ext 	- 	tbl_fea_mode
   4658  1.1        is 	short		faddr_ind_ext 	- 	tbl_fea_mode
   4659  1.1        is 	short		faddr_ind_ext 	- 	tbl_fea_mode
   4660  1.1        is 	short		faddr_ind_ext 	- 	tbl_fea_mode
   4661  1.1        is 
   4662  1.1        is 	short		fabs_short	- 	tbl_fea_mode
   4663  1.1        is 	short		fabs_long	- 	tbl_fea_mode
   4664  1.1        is 	short		fpc_ind		- 	tbl_fea_mode
   4665  1.1        is 	short		fpc_ind_ext	- 	tbl_fea_mode
   4666  1.1        is 	short		tbl_fea_mode	- 	tbl_fea_mode
   4667  1.1        is 	short		tbl_fea_mode	- 	tbl_fea_mode
   4668  1.1        is 	short		tbl_fea_mode	- 	tbl_fea_mode
   4669  1.1        is 	short		tbl_fea_mode	- 	tbl_fea_mode
   4670  1.1        is 
   4671  1.1        is ###################################
   4672  1.1        is # Address register indirect: (An) #
   4673  1.1        is ###################################
   4674  1.1        is faddr_ind_a0:
   4675  1.1        is 	mov.l		EXC_DREGS+0x8(%a6),%a0	# Get current a0
   4676  1.1        is 	rts
   4677  1.1        is 
   4678  1.1        is faddr_ind_a1:
   4679  1.1        is 	mov.l		EXC_DREGS+0xc(%a6),%a0	# Get current a1
   4680  1.1        is 	rts
   4681  1.1        is 
   4682  1.1        is faddr_ind_a2:
   4683  1.1        is 	mov.l		%a2,%a0			# Get current a2
   4684  1.1        is 	rts
   4685  1.1        is 
   4686  1.1        is faddr_ind_a3:
   4687  1.1        is 	mov.l		%a3,%a0			# Get current a3
   4688  1.1        is 	rts
   4689  1.1        is 
   4690  1.1        is faddr_ind_a4:
   4691  1.1        is 	mov.l		%a4,%a0			# Get current a4
   4692  1.1        is 	rts
   4693  1.1        is 
   4694  1.1        is faddr_ind_a5:
   4695  1.1        is 	mov.l		%a5,%a0			# Get current a5
   4696  1.1        is 	rts
   4697  1.1        is 
   4698  1.1        is faddr_ind_a6:
   4699  1.1        is 	mov.l		(%a6),%a0		# Get current a6
   4700  1.1        is 	rts
   4701  1.1        is 
   4702  1.1        is faddr_ind_a7:
   4703  1.1        is 	mov.l		EXC_A7(%a6),%a0		# Get current a7
   4704  1.1        is 	rts
   4705  1.1        is 
   4706  1.1        is #####################################################
   4707  1.1        is # Address register indirect w/ postincrement: (An)+ #
   4708  1.1        is #####################################################
   4709  1.1        is faddr_ind_p_a0:
   4710  1.1        is 	mov.l		EXC_DREGS+0x8(%a6),%d0	# Get current a0
   4711  1.1        is 	mov.l		%d0,%d1
   4712  1.1        is 	add.l		%a0,%d1			# Increment
   4713  1.1        is 	mov.l		%d1,EXC_DREGS+0x8(%a6)	# Save incr value
   4714  1.1        is 	mov.l		%d0,%a0
   4715  1.1        is 	rts
   4716  1.1        is 
   4717  1.1        is faddr_ind_p_a1:
   4718  1.1        is 	mov.l		EXC_DREGS+0xc(%a6),%d0	# Get current a1
   4719  1.1        is 	mov.l		%d0,%d1
   4720  1.1        is 	add.l		%a0,%d1			# Increment
   4721  1.1        is 	mov.l		%d1,EXC_DREGS+0xc(%a6)	# Save incr value
   4722  1.1        is 	mov.l		%d0,%a0
   4723  1.1        is 	rts
   4724  1.1        is 
   4725  1.1        is faddr_ind_p_a2:
   4726  1.1        is 	mov.l		%a2,%d0			# Get current a2
   4727  1.1        is 	mov.l		%d0,%d1
   4728  1.1        is 	add.l		%a0,%d1			# Increment
   4729  1.1        is 	mov.l		%d1,%a2			# Save incr value
   4730  1.1        is 	mov.l		%d0,%a0
   4731  1.1        is 	rts
   4732  1.1        is 
   4733  1.1        is faddr_ind_p_a3:
   4734  1.1        is 	mov.l		%a3,%d0			# Get current a3
   4735  1.1        is 	mov.l		%d0,%d1
   4736  1.1        is 	add.l		%a0,%d1			# Increment
   4737  1.1        is 	mov.l		%d1,%a3			# Save incr value
   4738  1.1        is 	mov.l		%d0,%a0
   4739  1.1        is 	rts
   4740  1.1        is 
   4741  1.1        is faddr_ind_p_a4:
   4742  1.1        is 	mov.l		%a4,%d0			# Get current a4
   4743  1.1        is 	mov.l		%d0,%d1
   4744  1.1        is 	add.l		%a0,%d1			# Increment
   4745  1.1        is 	mov.l		%d1,%a4			# Save incr value
   4746  1.1        is 	mov.l		%d0,%a0
   4747  1.1        is 	rts
   4748  1.1        is 
   4749  1.1        is faddr_ind_p_a5:
   4750  1.1        is 	mov.l		%a5,%d0			# Get current a5
   4751  1.1        is 	mov.l		%d0,%d1
   4752  1.1        is 	add.l		%a0,%d1			# Increment
   4753  1.1        is 	mov.l		%d1,%a5			# Save incr value
   4754  1.1        is 	mov.l		%d0,%a0
   4755  1.1        is 	rts
   4756  1.1        is 
   4757  1.1        is faddr_ind_p_a6:
   4758  1.1        is 	mov.l		(%a6),%d0		# Get current a6
   4759  1.1        is 	mov.l		%d0,%d1
   4760  1.1        is 	add.l		%a0,%d1			# Increment
   4761  1.1        is 	mov.l		%d1,(%a6)		# Save incr value
   4762  1.1        is 	mov.l		%d0,%a0
   4763  1.1        is 	rts
   4764  1.1        is 
   4765  1.1        is faddr_ind_p_a7:
   4766  1.1        is 	mov.b		&mia7_flg,SPCOND_FLG(%a6) # set "special case" flag
   4767  1.1        is 
   4768  1.1        is 	mov.l		EXC_A7(%a6),%d0		# Get current a7
   4769  1.1        is 	mov.l		%d0,%d1
   4770  1.1        is 	add.l		%a0,%d1			# Increment
   4771  1.1        is 	mov.l		%d1,EXC_A7(%a6)		# Save incr value
   4772  1.1        is 	mov.l		%d0,%a0
   4773  1.1        is 	rts
   4774  1.1        is 
   4775  1.1        is ####################################################
   4776  1.1        is # Address register indirect w/ predecrement: -(An) #
   4777  1.1        is ####################################################
   4778  1.1        is faddr_ind_m_a0:
   4779  1.1        is 	mov.l		EXC_DREGS+0x8(%a6),%d0	# Get current a0
   4780  1.1        is 	sub.l		%a0,%d0			# Decrement
   4781  1.1        is 	mov.l		%d0,EXC_DREGS+0x8(%a6)	# Save decr value
   4782  1.1        is 	mov.l		%d0,%a0
   4783  1.1        is 	rts
   4784  1.1        is 
   4785  1.1        is faddr_ind_m_a1:
   4786  1.1        is 	mov.l		EXC_DREGS+0xc(%a6),%d0	# Get current a1
   4787  1.1        is 	sub.l		%a0,%d0			# Decrement
   4788  1.1        is 	mov.l		%d0,EXC_DREGS+0xc(%a6)	# Save decr value
   4789  1.1        is 	mov.l		%d0,%a0
   4790  1.1        is 	rts
   4791  1.1        is 
   4792  1.1        is faddr_ind_m_a2:
   4793  1.1        is 	mov.l		%a2,%d0			# Get current a2
   4794  1.1        is 	sub.l		%a0,%d0			# Decrement
   4795  1.1        is 	mov.l		%d0,%a2			# Save decr value
   4796  1.1        is 	mov.l		%d0,%a0
   4797  1.1        is 	rts
   4798  1.1        is 
   4799  1.1        is faddr_ind_m_a3:
   4800  1.1        is 	mov.l		%a3,%d0			# Get current a3
   4801  1.1        is 	sub.l		%a0,%d0			# Decrement
   4802  1.1        is 	mov.l		%d0,%a3			# Save decr value
   4803  1.1        is 	mov.l		%d0,%a0
   4804  1.1        is 	rts
   4805  1.1        is 
   4806  1.1        is faddr_ind_m_a4:
   4807  1.1        is 	mov.l		%a4,%d0			# Get current a4
   4808  1.1        is 	sub.l		%a0,%d0			# Decrement
   4809  1.1        is 	mov.l		%d0,%a4			# Save decr value
   4810  1.1        is 	mov.l		%d0,%a0
   4811  1.1        is 	rts
   4812  1.1        is 
   4813  1.1        is faddr_ind_m_a5:
   4814  1.1        is 	mov.l		%a5,%d0			# Get current a5
   4815  1.1        is 	sub.l		%a0,%d0			# Decrement
   4816  1.1        is 	mov.l		%d0,%a5			# Save decr value
   4817  1.1        is 	mov.l		%d0,%a0
   4818  1.1        is 	rts
   4819  1.1        is 
   4820  1.1        is faddr_ind_m_a6:
   4821  1.1        is 	mov.l		(%a6),%d0		# Get current a6
   4822  1.1        is 	sub.l		%a0,%d0			# Decrement
   4823  1.1        is 	mov.l		%d0,(%a6)		# Save decr value
   4824  1.1        is 	mov.l		%d0,%a0
   4825  1.1        is 	rts
   4826  1.1        is 
   4827  1.1        is faddr_ind_m_a7:
   4828  1.1        is 	mov.b		&mda7_flg,SPCOND_FLG(%a6) # set "special case" flag
   4829  1.1        is 
   4830  1.1        is 	mov.l		EXC_A7(%a6),%d0		# Get current a7
   4831  1.1        is 	sub.l		%a0,%d0			# Decrement
   4832  1.1        is 	mov.l		%d0,EXC_A7(%a6)		# Save decr value
   4833  1.1        is 	mov.l		%d0,%a0
   4834  1.1        is 	rts
   4835  1.1        is 
   4836  1.1        is ########################################################
   4837  1.1        is # Address register indirect w/ displacement: (d16, An) #
   4838  1.1        is ########################################################
   4839  1.1        is faddr_ind_disp_a0:
   4840  1.1        is 	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
   4841  1.1        is 	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
   4842  1.1        is 	bsr.l		_imem_read_word
   4843  1.1        is 
   4844  1.1        is 	tst.l		%d1			# did ifetch fail?
   4845  1.1        is 	bne.l		iea_iacc		# yes
   4846  1.1        is 
   4847  1.1        is 	mov.w		%d0,%a0			# sign extend displacement
   4848  1.1        is 
   4849  1.1        is 	add.l		EXC_DREGS+0x8(%a6),%a0	# a0 + d16
   4850  1.1        is 	rts
   4851  1.1        is 
   4852  1.1        is faddr_ind_disp_a1:
   4853  1.1        is 	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
   4854  1.1        is 	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
   4855  1.1        is 	bsr.l		_imem_read_word
   4856  1.1        is 
   4857  1.1        is 	tst.l		%d1			# did ifetch fail?
   4858  1.1        is 	bne.l		iea_iacc		# yes
   4859  1.1        is 
   4860  1.1        is 	mov.w		%d0,%a0			# sign extend displacement
   4861  1.1        is 
   4862  1.1        is 	add.l		EXC_DREGS+0xc(%a6),%a0	# a1 + d16
   4863  1.1        is 	rts
   4864  1.1        is 
   4865  1.1        is faddr_ind_disp_a2:
   4866  1.1        is 	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
   4867  1.1        is 	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
   4868  1.1        is 	bsr.l		_imem_read_word
   4869  1.1        is 
   4870  1.1        is 	tst.l		%d1			# did ifetch fail?
   4871  1.1        is 	bne.l		iea_iacc		# yes
   4872  1.1        is 
   4873  1.1        is 	mov.w		%d0,%a0			# sign extend displacement
   4874  1.1        is 
   4875  1.1        is 	add.l		%a2,%a0			# a2 + d16
   4876  1.1        is 	rts
   4877  1.1        is 
   4878  1.1        is faddr_ind_disp_a3:
   4879  1.1        is 	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
   4880  1.1        is 	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
   4881  1.1        is 	bsr.l		_imem_read_word
   4882  1.1        is 
   4883  1.1        is 	tst.l		%d1			# did ifetch fail?
   4884  1.1        is 	bne.l		iea_iacc		# yes
   4885  1.1        is 
   4886  1.1        is 	mov.w		%d0,%a0			# sign extend displacement
   4887  1.1        is 
   4888  1.1        is 	add.l		%a3,%a0			# a3 + d16
   4889  1.1        is 	rts
   4890  1.1        is 
   4891  1.1        is faddr_ind_disp_a4:
   4892  1.1        is 	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
   4893  1.1        is 	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
   4894  1.1        is 	bsr.l		_imem_read_word
   4895  1.1        is 
   4896  1.1        is 	tst.l		%d1			# did ifetch fail?
   4897  1.1        is 	bne.l		iea_iacc		# yes
   4898  1.1        is 
   4899  1.1        is 	mov.w		%d0,%a0			# sign extend displacement
   4900  1.1        is 
   4901  1.1        is 	add.l		%a4,%a0			# a4 + d16
   4902  1.1        is 	rts
   4903  1.1        is 
   4904  1.1        is faddr_ind_disp_a5:
   4905  1.1        is 	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
   4906  1.1        is 	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
   4907  1.1        is 	bsr.l		_imem_read_word
   4908  1.1        is 
   4909  1.1        is 	tst.l		%d1			# did ifetch fail?
   4910  1.1        is 	bne.l		iea_iacc		# yes
   4911  1.1        is 
   4912  1.1        is 	mov.w		%d0,%a0			# sign extend displacement
   4913  1.1        is 
   4914  1.1        is 	add.l		%a5,%a0			# a5 + d16
   4915  1.1        is 	rts
   4916  1.1        is 
   4917  1.1        is faddr_ind_disp_a6:
   4918  1.1        is 	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
   4919  1.1        is 	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
   4920  1.1        is 	bsr.l		_imem_read_word
   4921  1.1        is 
   4922  1.1        is 	tst.l		%d1			# did ifetch fail?
   4923  1.1        is 	bne.l		iea_iacc		# yes
   4924  1.1        is 
   4925  1.1        is 	mov.w		%d0,%a0			# sign extend displacement
   4926  1.1        is 
   4927  1.1        is 	add.l		(%a6),%a0		# a6 + d16
   4928  1.1        is 	rts
   4929  1.1        is 
   4930  1.1        is faddr_ind_disp_a7:
   4931  1.1        is 	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
   4932  1.1        is 	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
   4933  1.1        is 	bsr.l		_imem_read_word
   4934  1.1        is 
   4935  1.1        is 	tst.l		%d1			# did ifetch fail?
   4936  1.1        is 	bne.l		iea_iacc		# yes
   4937  1.1        is 
   4938  1.1        is 	mov.w		%d0,%a0			# sign extend displacement
   4939  1.1        is 
   4940  1.1        is 	add.l		EXC_A7(%a6),%a0		# a7 + d16
   4941  1.1        is 	rts
   4942  1.1        is 
   4943  1.1        is ########################################################################
   4944  1.1        is # Address register indirect w/ index(8-bit displacement): (d8, An, Xn) #
   4945  1.1        is #    "       "         "    w/   "  (base displacement): (bd, An, Xn)  #
   4946  1.1        is # Memory indirect postindexed: ([bd, An], Xn, od)		       #
   4947  1.1        is # Memory indirect preindexed: ([bd, An, Xn], od)		       #
   4948  1.1        is ########################################################################
   4949  1.1        is faddr_ind_ext:
   4950  1.1        is 	addq.l		&0x8,%d1
   4951  1.1        is 	bsr.l		fetch_dreg		# fetch base areg
   4952  1.1        is 	mov.l		%d0,-(%sp)
   4953  1.1        is 
   4954  1.1        is 	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
   4955  1.1        is 	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
   4956  1.1        is 	bsr.l		_imem_read_word		# fetch extword in d0
   4957  1.1        is 
   4958  1.1        is 	tst.l		%d1			# did ifetch fail?
   4959  1.1        is 	bne.l		iea_iacc		# yes
   4960  1.1        is 
   4961  1.1        is 	mov.l		(%sp)+,%a0
   4962  1.1        is 
   4963  1.1        is 	btst		&0x8,%d0
   4964  1.1        is 	bne.w		fcalc_mem_ind
   4965  1.1        is 
   4966  1.1        is 	mov.l		%d0,L_SCR1(%a6)		# hold opword
   4967  1.1        is 
   4968  1.1        is 	mov.l		%d0,%d1
   4969  1.1        is 	rol.w		&0x4,%d1
   4970  1.1        is 	andi.w		&0xf,%d1		# extract index regno
   4971  1.1        is 
   4972  1.1        is # count on fetch_dreg() not to alter a0...
   4973  1.1        is 	bsr.l		fetch_dreg		# fetch index
   4974  1.1        is 
   4975  1.1        is 	mov.l		%d2,-(%sp)		# save d2
   4976  1.1        is 	mov.l		L_SCR1(%a6),%d2		# fetch opword
   4977  1.1        is 
   4978  1.1        is 	btst		&0xb,%d2		# is it word or long?
   4979  1.1        is 	bne.b		faii8_long
   4980  1.1        is 	ext.l		%d0			# sign extend word index
   4981  1.1        is faii8_long:
   4982  1.1        is 	mov.l		%d2,%d1
   4983  1.1        is 	rol.w		&0x7,%d1
   4984  1.1        is 	andi.l		&0x3,%d1		# extract scale value
   4985  1.1        is 
   4986  1.1        is 	lsl.l		%d1,%d0			# shift index by scale
   4987  1.1        is 
   4988  1.1        is 	extb.l		%d2			# sign extend displacement
   4989  1.1        is 	add.l		%d2,%d0			# index + disp
   4990  1.1        is 	add.l		%d0,%a0			# An + (index + disp)
   4991  1.1        is 
   4992  1.1        is 	mov.l		(%sp)+,%d2		# restore old d2
   4993  1.1        is 	rts
   4994  1.1        is 
   4995  1.1        is ###########################
   4996  1.1        is # Absolute short: (XXX).W #
   4997  1.1        is ###########################
   4998  1.1        is fabs_short:
   4999  1.1        is 	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
   5000  1.1        is 	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
   5001  1.1        is 	bsr.l		_imem_read_word		# fetch short address
   5002  1.1        is 
   5003  1.1        is 	tst.l		%d1			# did ifetch fail?
   5004  1.1        is 	bne.l		iea_iacc		# yes
   5005  1.1        is 
   5006  1.1        is 	mov.w		%d0,%a0			# return <ea> in a0
   5007  1.1        is 	rts
   5008  1.1        is 
   5009  1.1        is ##########################
   5010  1.1        is # Absolute long: (XXX).L #
   5011  1.1        is ##########################
   5012  1.1        is fabs_long:
   5013  1.1        is 	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
   5014  1.1        is 	addq.l		&0x4,EXC_EXTWPTR(%a6)	# incr instruction ptr
   5015  1.1        is 	bsr.l		_imem_read_long		# fetch long address
   5016  1.1        is 
   5017  1.1        is 	tst.l		%d1			# did ifetch fail?
   5018  1.1        is 	bne.l		iea_iacc		# yes
   5019  1.1        is 
   5020  1.1        is 	mov.l		%d0,%a0			# return <ea> in a0
   5021  1.1        is 	rts
   5022  1.1        is 
   5023  1.1        is #######################################################
   5024  1.1        is # Program counter indirect w/ displacement: (d16, PC) #
   5025  1.1        is #######################################################
   5026  1.1        is fpc_ind:
   5027  1.1        is 	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
   5028  1.1        is 	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
   5029  1.1        is 	bsr.l		_imem_read_word		# fetch word displacement
   5030  1.1        is 
   5031  1.1        is 	tst.l		%d1			# did ifetch fail?
   5032  1.1        is 	bne.l		iea_iacc		# yes
   5033  1.1        is 
   5034  1.1        is 	mov.w		%d0,%a0			# sign extend displacement
   5035  1.1        is 
   5036  1.1        is 	add.l		EXC_EXTWPTR(%a6),%a0	# pc + d16
   5037  1.1        is 
   5038  1.1        is # _imem_read_word() increased the extwptr by 2. need to adjust here.
   5039  1.1        is 	subq.l		&0x2,%a0		# adjust <ea>
   5040  1.1        is 	rts
   5041  1.1        is 
   5042  1.1        is ##########################################################
   5043  1.1        is # PC indirect w/ index(8-bit displacement): (d8, PC, An) #
   5044  1.1        is # "     "     w/   "  (base displacement): (bd, PC, An)  #
   5045  1.1        is # PC memory indirect postindexed: ([bd, PC], Xn, od)     #
   5046  1.1        is # PC memory indirect preindexed: ([bd, PC, Xn], od)      #
   5047  1.1        is ##########################################################
   5048  1.1        is fpc_ind_ext:
   5049  1.1        is 	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
   5050  1.1        is 	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
   5051  1.1        is 	bsr.l		_imem_read_word		# fetch ext word
   5052  1.1        is 
   5053  1.1        is 	tst.l		%d1			# did ifetch fail?
   5054  1.1        is 	bne.l		iea_iacc		# yes
   5055  1.1        is 
   5056  1.1        is 	mov.l		EXC_EXTWPTR(%a6),%a0	# put base in a0
   5057  1.1        is 	subq.l		&0x2,%a0		# adjust base
   5058  1.1        is 
   5059  1.1        is 	btst		&0x8,%d0		# is disp only 8 bits?
   5060  1.1        is 	bne.w		fcalc_mem_ind		# calc memory indirect
   5061  1.1        is 
   5062  1.1        is 	mov.l		%d0,L_SCR1(%a6)		# store opword
   5063  1.1        is 
   5064  1.1        is 	mov.l		%d0,%d1			# make extword copy
   5065  1.1        is 	rol.w		&0x4,%d1		# rotate reg num into place
   5066  1.1        is 	andi.w		&0xf,%d1		# extract register number
   5067  1.1        is 
   5068  1.1        is # count on fetch_dreg() not to alter a0...
   5069  1.1        is 	bsr.l		fetch_dreg		# fetch index
   5070  1.1        is 
   5071  1.1        is 	mov.l		%d2,-(%sp)		# save d2
   5072  1.1        is 	mov.l		L_SCR1(%a6),%d2		# fetch opword
   5073  1.1        is 
   5074  1.1        is 	btst		&0xb,%d2		# is index word or long?
   5075  1.1        is 	bne.b		fpii8_long		# long
   5076  1.1        is 	ext.l		%d0			# sign extend word index
   5077  1.1        is fpii8_long:
   5078  1.1        is 	mov.l		%d2,%d1
   5079  1.1        is 	rol.w		&0x7,%d1		# rotate scale value into place
   5080  1.1        is 	andi.l		&0x3,%d1		# extract scale value
   5081  1.1        is 
   5082  1.1        is 	lsl.l		%d1,%d0			# shift index by scale
   5083  1.1        is 
   5084  1.1        is 	extb.l		%d2			# sign extend displacement
   5085  1.1        is 	add.l		%d2,%d0			# disp + index
   5086  1.1        is 	add.l		%d0,%a0			# An + (index + disp)
   5087  1.1        is 
   5088  1.1        is 	mov.l		(%sp)+,%d2		# restore temp register
   5089  1.1        is 	rts
   5090  1.1        is 
   5091  1.1        is # d2 = index
   5092  1.1        is # d3 = base
   5093  1.1        is # d4 = od
   5094  1.1        is # d5 = extword
   5095  1.1        is fcalc_mem_ind:
   5096  1.1        is 	btst		&0x6,%d0		# is the index suppressed?
   5097  1.1        is 	beq.b		fcalc_index
   5098  1.1        is 
   5099  1.1        is 	movm.l		&0x3c00,-(%sp)		# save d2-d5
   5100  1.1        is 
   5101  1.1        is 	mov.l		%d0,%d5			# put extword in d5
   5102  1.1        is 	mov.l		%a0,%d3			# put base in d3
   5103  1.1        is 
   5104  1.1        is 	clr.l		%d2			# yes, so index = 0
   5105  1.1        is 	bra.b		fbase_supp_ck
   5106  1.1        is 
   5107  1.1        is # index:
   5108  1.1        is fcalc_index:
   5109  1.1        is 	mov.l		%d0,L_SCR1(%a6)		# save d0 (opword)
   5110  1.1        is 	bfextu		%d0{&16:&4},%d1		# fetch dreg index
   5111  1.1        is 	bsr.l		fetch_dreg
   5112  1.1        is 
   5113  1.1        is 	movm.l		&0x3c00,-(%sp)		# save d2-d5
   5114  1.1        is 	mov.l		%d0,%d2			# put index in d2
   5115  1.1        is 	mov.l		L_SCR1(%a6),%d5
   5116  1.1        is 	mov.l		%a0,%d3
   5117  1.1        is 
   5118  1.1        is 	btst		&0xb,%d5		# is index word or long?
   5119  1.1        is 	bne.b		fno_ext
   5120  1.1        is 	ext.l		%d2
   5121  1.1        is 
   5122  1.1        is fno_ext:
   5123  1.1        is 	bfextu		%d5{&21:&2},%d0
   5124  1.1        is 	lsl.l		%d0,%d2
   5125  1.1        is 
   5126  1.1        is # base address (passed as parameter in d3):
   5127  1.1        is # we clear the value here if it should actually be suppressed.
   5128  1.1        is fbase_supp_ck:
   5129  1.1        is 	btst		&0x7,%d5		# is the bd suppressed?
   5130  1.1        is 	beq.b		fno_base_sup
   5131  1.1        is 	clr.l		%d3
   5132  1.1        is 
   5133  1.1        is # base displacement:
   5134  1.1        is fno_base_sup:
   5135  1.1        is 	bfextu		%d5{&26:&2},%d0		# get bd size
   5136  1.1        is #	beq.l		fmovm_error		# if (size == 0) it's reserved
   5137  1.1        is 
   5138  1.1        is 	cmpi.b	 	%d0,&0x2
   5139  1.1        is 	blt.b		fno_bd
   5140  1.1        is 	beq.b		fget_word_bd
   5141  1.1        is 
   5142  1.1        is 	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
   5143  1.1        is 	addq.l		&0x4,EXC_EXTWPTR(%a6)	# incr instruction ptr
   5144  1.1        is 	bsr.l		_imem_read_long
   5145  1.1        is 
   5146  1.1        is 	tst.l		%d1			# did ifetch fail?
   5147  1.1        is 	bne.l		fcea_iacc		# yes
   5148  1.1        is 
   5149  1.1        is 	bra.b		fchk_ind
   5150  1.1        is 
   5151  1.1        is fget_word_bd:
   5152  1.1        is 	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
   5153  1.1        is 	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
   5154  1.1        is 	bsr.l		_imem_read_word
   5155  1.1        is 
   5156  1.1        is 	tst.l		%d1			# did ifetch fail?
   5157  1.1        is 	bne.l		fcea_iacc		# yes
   5158  1.1        is 
   5159  1.1        is 	ext.l		%d0			# sign extend bd
   5160  1.1        is 
   5161  1.1        is fchk_ind:
   5162  1.1        is 	add.l		%d0,%d3			# base += bd
   5163  1.1        is 
   5164  1.1        is # outer displacement:
   5165  1.1        is fno_bd:
   5166  1.1        is 	bfextu		%d5{&30:&2},%d0		# is od suppressed?
   5167  1.1        is 	beq.w		faii_bd
   5168  1.1        is 
   5169  1.1        is 	cmpi.b	 	%d0,&0x2
   5170  1.1        is 	blt.b		fnull_od
   5171  1.1        is 	beq.b		fword_od
   5172  1.1        is 
   5173  1.1        is 	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
   5174  1.1        is 	addq.l		&0x4,EXC_EXTWPTR(%a6)	# incr instruction ptr
   5175  1.1        is 	bsr.l		_imem_read_long
   5176  1.1        is 
   5177  1.1        is 	tst.l		%d1			# did ifetch fail?
   5178  1.1        is 	bne.l		fcea_iacc		# yes
   5179  1.1        is 
   5180  1.1        is 	bra.b 		fadd_them
   5181  1.1        is 
   5182  1.1        is fword_od:
   5183  1.1        is 	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
   5184  1.1        is 	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
   5185  1.1        is 	bsr.l		_imem_read_word
   5186  1.1        is 
   5187  1.1        is 	tst.l		%d1			# did ifetch fail?
   5188  1.1        is 	bne.l		fcea_iacc		# yes
   5189  1.1        is 
   5190  1.1        is 	ext.l		%d0			# sign extend od
   5191  1.1        is 	bra.b		fadd_them
   5192  1.1        is 
   5193  1.1        is fnull_od:
   5194  1.1        is 	clr.l		%d0
   5195  1.1        is 
   5196  1.1        is fadd_them:
   5197  1.1        is 	mov.l		%d0,%d4
   5198  1.1        is 
   5199  1.1        is 	btst		&0x2,%d5		# pre or post indexing?
   5200  1.1        is 	beq.b		fpre_indexed
   5201  1.1        is 
   5202  1.1        is 	mov.l		%d3,%a0
   5203  1.1        is 	bsr.l		_dmem_read_long
   5204  1.1        is 
   5205  1.1        is 	tst.l		%d1			# did dfetch fail?
   5206  1.1        is 	bne.w		fcea_err		# yes
   5207  1.1        is 
   5208  1.1        is 	add.l		%d2,%d0			# <ea> += index
   5209  1.1        is 	add.l		%d4,%d0			# <ea> += od
   5210  1.1        is 	bra.b		fdone_ea
   5211  1.1        is 
   5212  1.1        is fpre_indexed:
   5213  1.1        is 	add.l		%d2,%d3			# preindexing
   5214  1.1        is 	mov.l		%d3,%a0
   5215  1.1        is 	bsr.l		_dmem_read_long
   5216  1.1        is 
   5217  1.1        is 	tst.l		%d1			# did dfetch fail?
   5218  1.1        is 	bne.w		fcea_err		# yes
   5219  1.1        is 
   5220  1.1        is 	add.l		%d4,%d0			# ea += od
   5221  1.1        is 	bra.b		fdone_ea
   5222  1.1        is 
   5223  1.1        is faii_bd:
   5224  1.1        is 	add.l		%d2,%d3			# ea = (base + bd) + index
   5225  1.1        is 	mov.l		%d3,%d0
   5226  1.1        is fdone_ea:
   5227  1.1        is 	mov.l		%d0,%a0
   5228  1.1        is 
   5229  1.1        is 	movm.l		(%sp)+,&0x003c		# restore d2-d5
   5230  1.1        is 	rts
   5231  1.1        is 
   5232  1.1        is #########################################################
   5233  1.1        is fcea_err:
   5234  1.1        is 	mov.l		%d3,%a0
   5235  1.1        is 
   5236  1.1        is 	movm.l		(%sp)+,&0x003c		# restore d2-d5
   5237  1.1        is 	mov.w		&0x0101,%d0
   5238  1.1        is 	bra.l		iea_dacc
   5239  1.1        is 
   5240  1.1        is fcea_iacc:
   5241  1.1        is 	movm.l		(%sp)+,&0x003c		# restore d2-d5
   5242  1.1        is 	bra.l		iea_iacc
   5243  1.1        is 
   5244  1.1        is fmovm_out_err:
   5245  1.1        is 	bsr.l		restore
   5246  1.1        is 	mov.w		&0x00e1,%d0
   5247  1.1        is 	bra.b		fmovm_err
   5248  1.1        is 
   5249  1.1        is fmovm_in_err:
   5250  1.1        is 	bsr.l		restore
   5251  1.1        is 	mov.w		&0x0161,%d0
   5252  1.1        is 
   5253  1.1        is fmovm_err:
   5254  1.1        is 	mov.l		L_SCR1(%a6),%a0
   5255  1.1        is 	bra.l		iea_dacc
   5256  1.1        is 
   5257  1.1        is #########################################################################
   5258  1.1        is # XDEF ****************************************************************	#
   5259  1.1        is # 	fmovm_ctrl(): emulate fmovm.l of control registers instr	#
   5260  1.1        is #									#
   5261  1.1        is # XREF ****************************************************************	#
   5262  1.1        is #	_imem_read_long() - read longword from memory			#
   5263  1.1        is #	iea_iacc() - _imem_read_long() failed; error recovery		#
   5264  1.1        is #									#
   5265  1.1        is # INPUT ***************************************************************	#
   5266  1.1        is #	None								#
   5267  1.1        is # 									#
   5268  1.1        is # OUTPUT **************************************************************	#
   5269  1.1        is #	If _imem_read_long() doesn't fail:				#
   5270  1.1        is #		USER_FPCR(a6)  = new FPCR value				#
   5271  1.1        is #		USER_FPSR(a6)  = new FPSR value				#
   5272  1.1        is #		USER_FPIAR(a6) = new FPIAR value			#
   5273  1.1        is #									#
   5274  1.1        is # ALGORITHM ***********************************************************	#
   5275  1.1        is # 	Decode the instruction type by looking at the extension word 	#
   5276  1.1        is # in order to see how many control registers to fetch from memory.	#
   5277  1.1        is # Fetch them using _imem_read_long(). If this fetch fails, exit through	#
   5278  1.1        is # the special access error exit handler iea_iacc().			#
   5279  1.1        is #									#
   5280  1.1        is # Instruction word decoding:						#
   5281  1.1        is #									#
   5282  1.1        is # 	fmovem.l #<data>, {FPIAR&|FPCR&|FPSR}				#
   5283  1.1        is #									#
   5284  1.1        is #		WORD1			WORD2				#
   5285  1.1        is #	1111 0010 00 111100	100$ $$00 0000 0000			#
   5286  1.1        is #									#
   5287  1.1        is #	$$$ (100): FPCR							#
   5288  1.1        is #	    (010): FPSR							#
   5289  1.1        is #	    (001): FPIAR						#
   5290  1.1        is #	    (000): FPIAR						#
   5291  1.1        is #									#
   5292  1.1        is #########################################################################
   5293  1.1        is 
   5294  1.1        is 	global		fmovm_ctrl
   5295  1.1        is fmovm_ctrl:
   5296  1.1        is 	mov.b		EXC_EXTWORD(%a6),%d0	# fetch reg select bits
   5297  1.1        is 	cmpi.b		%d0,&0x9c		# fpcr & fpsr & fpiar ?
   5298  1.1        is 	beq.w		fctrl_in_7		# yes
   5299  1.1        is 	cmpi.b		%d0,&0x98		# fpcr & fpsr ?
   5300  1.1        is 	beq.w		fctrl_in_6		# yes
   5301  1.1        is 	cmpi.b		%d0,&0x94		# fpcr & fpiar ?
   5302  1.1        is 	beq.b		fctrl_in_5		# yes
   5303  1.1        is 
   5304  1.1        is # fmovem.l #<data>, fpsr/fpiar
   5305  1.1        is fctrl_in_3:
   5306  1.1        is 	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
   5307  1.1        is 	addq.l		&0x4,EXC_EXTWPTR(%a6)	# incr instruction ptr
   5308  1.1        is 	bsr.l		_imem_read_long		# fetch FPSR from mem
   5309  1.1        is 
   5310  1.1        is 	tst.l		%d1			# did ifetch fail?
   5311  1.1        is 	bne.l		iea_iacc		# yes
   5312  1.1        is 
   5313  1.1        is 	mov.l		%d0,USER_FPSR(%a6)	# store new FPSR to stack
   5314  1.1        is 	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
   5315  1.1        is 	addq.l		&0x4,EXC_EXTWPTR(%a6)	# incr instruction ptr
   5316  1.1        is 	bsr.l		_imem_read_long		# fetch FPIAR from mem
   5317  1.1        is 
   5318  1.1        is 	tst.l		%d1			# did ifetch fail?
   5319  1.1        is 	bne.l		iea_iacc		# yes
   5320  1.1        is 
   5321  1.1        is 	mov.l		%d0,USER_FPIAR(%a6)	# store new FPIAR to stack
   5322  1.1        is 	rts
   5323  1.1        is 
   5324  1.1        is # fmovem.l #<data>, fpcr/fpiar
   5325  1.1        is fctrl_in_5:
   5326  1.1        is 	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
   5327  1.1        is 	addq.l		&0x4,EXC_EXTWPTR(%a6)	# incr instruction ptr
   5328  1.1        is 	bsr.l		_imem_read_long		# fetch FPCR from mem
   5329  1.1        is 
   5330  1.1        is 	tst.l		%d1			# did ifetch fail?
   5331  1.1        is 	bne.l		iea_iacc		# yes
   5332  1.1        is 
   5333  1.1        is 	mov.l		%d0,USER_FPCR(%a6)	# store new FPCR to stack
   5334  1.1        is 	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
   5335  1.1        is 	addq.l		&0x4,EXC_EXTWPTR(%a6)	# incr instruction ptr
   5336  1.1        is 	bsr.l		_imem_read_long		# fetch FPIAR from mem
   5337  1.1        is 
   5338  1.1        is 	tst.l		%d1			# did ifetch fail?
   5339  1.1        is 	bne.l		iea_iacc		# yes
   5340  1.1        is 
   5341  1.1        is 	mov.l		%d0,USER_FPIAR(%a6)	# store new FPIAR to stack
   5342  1.1        is 	rts
   5343  1.1        is 
   5344  1.1        is # fmovem.l #<data>, fpcr/fpsr
   5345  1.1        is fctrl_in_6:
   5346  1.1        is 	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
   5347  1.1        is 	addq.l		&0x4,EXC_EXTWPTR(%a6)	# incr instruction ptr
   5348  1.1        is 	bsr.l		_imem_read_long		# fetch FPCR from mem
   5349  1.1        is 
   5350  1.1        is 	tst.l		%d1			# did ifetch fail?
   5351  1.1        is 	bne.l		iea_iacc		# yes
   5352  1.1        is 
   5353  1.1        is 	mov.l		%d0,USER_FPCR(%a6)	# store new FPCR to mem
   5354  1.1        is 	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
   5355  1.1        is 	addq.l		&0x4,EXC_EXTWPTR(%a6)	# incr instruction ptr
   5356  1.1        is 	bsr.l		_imem_read_long		# fetch FPSR from mem
   5357  1.1        is 
   5358  1.1        is 	tst.l		%d1			# did ifetch fail?
   5359  1.1        is 	bne.l		iea_iacc		# yes
   5360  1.1        is 
   5361  1.1        is 	mov.l		%d0,USER_FPSR(%a6)	# store new FPSR to mem
   5362  1.1        is 	rts
   5363  1.1        is 
   5364  1.1        is # fmovem.l #<data>, fpcr/fpsr/fpiar
   5365  1.1        is fctrl_in_7:
   5366  1.1        is 	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
   5367  1.1        is 	addq.l		&0x4,EXC_EXTWPTR(%a6)	# incr instruction ptr
   5368  1.1        is 	bsr.l		_imem_read_long		# fetch FPCR from mem
   5369  1.1        is 
   5370  1.1        is 	tst.l		%d1			# did ifetch fail?
   5371  1.1        is 	bne.l		iea_iacc		# yes
   5372  1.1        is 
   5373  1.1        is 	mov.l		%d0,USER_FPCR(%a6)	# store new FPCR to mem
   5374  1.1        is 	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
   5375  1.1        is 	addq.l		&0x4,EXC_EXTWPTR(%a6)	# incr instruction ptr
   5376  1.1        is 	bsr.l		_imem_read_long		# fetch FPSR from mem
   5377  1.1        is 
   5378  1.1        is 	tst.l		%d1			# did ifetch fail?
   5379  1.1        is 	bne.l		iea_iacc		# yes
   5380  1.1        is 
   5381  1.1        is 	mov.l		%d0,USER_FPSR(%a6)	# store new FPSR to mem
   5382  1.1        is 	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
   5383  1.1        is 	addq.l		&0x4,EXC_EXTWPTR(%a6)	# incr instruction ptr
   5384  1.1        is 	bsr.l		_imem_read_long		# fetch FPIAR from mem
   5385  1.1        is 
   5386  1.1        is 	tst.l		%d1			# did ifetch fail?
   5387  1.1        is 	bne.l		iea_iacc		# yes
   5388  1.1        is 
   5389  1.1        is 	mov.l		%d0,USER_FPIAR(%a6)	# store new FPIAR to mem
   5390  1.1        is 	rts
   5391  1.1        is 
   5392  1.1        is ##########################################################################
   5393  1.1        is 
   5394  1.1        is #########################################################################
   5395  1.1        is # XDEF ****************************************************************	#
   5396  1.1        is #	addsub_scaler2(): scale inputs to fadd/fsub such that no	#
   5397  1.1        is #			  OVFL/UNFL exceptions will result		#
   5398  1.1        is #									#
   5399  1.1        is # XREF ****************************************************************	#
   5400  1.1        is #	norm() - normalize mantissa after adjusting exponent		#
   5401  1.1        is #									#
   5402  1.1        is # INPUT ***************************************************************	#
   5403  1.1        is #	FP_SRC(a6) = fp op1(src)					#
   5404  1.1        is #	FP_DST(a6) = fp op2(dst)					#
   5405  1.1        is # 									#
   5406  1.1        is # OUTPUT **************************************************************	#
   5407  1.1        is #	FP_SRC(a6) = fp op1 scaled(src)					#
   5408  1.1        is #	FP_DST(a6) = fp op2 scaled(dst)					#
   5409  1.1        is #	d0         = scale amount					#
   5410  1.1        is #									#
   5411  1.1        is # ALGORITHM ***********************************************************	#
   5412  1.1        is # 	If the DST exponent is > the SRC exponent, set the DST exponent	#
   5413  1.1        is # equal to 0x3fff and scale the SRC exponent by the value that the	#
   5414  1.1        is # DST exponent was scaled by. If the SRC exponent is greater or equal,	#
   5415  1.1        is # do the opposite. Return this scale factor in d0.			#
   5416  1.1        is #	If the two exponents differ by > the number of mantissa bits	#
   5417  1.1        is # plus two, then set the smallest exponent to a very small value as a	#
   5418  1.1        is # quick shortcut.							#
   5419  1.1        is #									#
   5420  1.1        is #########################################################################
   5421  1.1        is 
   5422  1.1        is 	global		addsub_scaler2
   5423  1.1        is addsub_scaler2:
   5424  1.1        is 	mov.l		SRC_HI(%a0),FP_SCR0_HI(%a6)
   5425  1.1        is 	mov.l		DST_HI(%a1),FP_SCR1_HI(%a6)
   5426  1.1        is 	mov.l		SRC_LO(%a0),FP_SCR0_LO(%a6)
   5427  1.1        is 	mov.l		DST_LO(%a1),FP_SCR1_LO(%a6)
   5428  1.1        is 	mov.w		SRC_EX(%a0),%d0
   5429  1.1        is 	mov.w		DST_EX(%a1),%d1
   5430  1.1        is 	mov.w		%d0,FP_SCR0_EX(%a6)
   5431  1.1        is 	mov.w		%d1,FP_SCR1_EX(%a6)
   5432  1.1        is 
   5433  1.1        is 	andi.w		&0x7fff,%d0
   5434  1.1        is 	andi.w		&0x7fff,%d1
   5435  1.1        is 	mov.w		%d0,L_SCR1(%a6)		# store src exponent
   5436  1.1        is 	mov.w		%d1,2+L_SCR1(%a6)	# store dst exponent
   5437  1.1        is 
   5438  1.1        is 	cmp.w		%d0, %d1		# is src exp >= dst exp?
   5439  1.1        is 	bge.l		src_exp_ge2
   5440  1.1        is 
   5441  1.1        is # dst exp is >  src exp; scale dst to exp = 0x3fff
   5442  1.1        is dst_exp_gt2:
   5443  1.1        is 	bsr.l		scale_to_zero_dst
   5444  1.1        is 	mov.l		%d0,-(%sp)		# save scale factor
   5445  1.1        is 
   5446  1.1        is 	cmpi.b		STAG(%a6),&DENORM	# is dst denormalized?
   5447  1.1        is 	bne.b		cmpexp12
   5448  1.1        is 
   5449  1.1        is 	lea		FP_SCR0(%a6),%a0
   5450  1.1        is 	bsr.l		norm			# normalize the denorm; result is new exp
   5451  1.1        is 	neg.w		%d0			# new exp = -(shft val)
   5452  1.1        is 	mov.w		%d0,L_SCR1(%a6)		# inset new exp
   5453  1.1        is 
   5454  1.1        is cmpexp12:
   5455  1.1        is 	mov.w		2+L_SCR1(%a6),%d0
   5456  1.1        is 	subi.w		&mantissalen+2,%d0	# subtract mantissalen+2 from larger exp
   5457  1.1        is 
   5458  1.1        is 	cmp.w		%d0,L_SCR1(%a6)		# is difference >= len(mantissa)+2?
   5459  1.1        is 	bge.b		quick_scale12
   5460  1.1        is 
   5461  1.1        is 	mov.w		L_SCR1(%a6),%d0
   5462  1.1        is 	add.w		0x2(%sp),%d0		# scale src exponent by scale factor
   5463  1.1        is 	mov.w		FP_SCR0_EX(%a6),%d1
   5464  1.1        is 	and.w		&0x8000,%d1
   5465  1.1        is 	or.w		%d1,%d0			# concat {sgn,new exp}
   5466  1.1        is 	mov.w		%d0,FP_SCR0_EX(%a6)	# insert new dst exponent
   5467  1.1        is 
   5468  1.1        is 	mov.l		(%sp)+,%d0		# return SCALE factor
   5469  1.1        is 	rts
   5470  1.1        is 
   5471  1.1        is quick_scale12:
   5472  1.1        is 	andi.w		&0x8000,FP_SCR0_EX(%a6)	# zero src exponent
   5473  1.1        is 	bset		&0x0,1+FP_SCR0_EX(%a6)	# set exp = 1
   5474  1.1        is 
   5475  1.1        is 	mov.l		(%sp)+,%d0		# return SCALE factor
   5476  1.1        is 	rts
   5477  1.1        is 
   5478  1.1        is # src exp is >= dst exp; scale src to exp = 0x3fff
   5479  1.1        is src_exp_ge2:
   5480  1.1        is 	bsr.l		scale_to_zero_src
   5481  1.1        is 	mov.l		%d0,-(%sp)		# save scale factor
   5482  1.1        is 
   5483  1.1        is 	cmpi.b		DTAG(%a6),&DENORM	# is dst denormalized?
   5484  1.1        is 	bne.b		cmpexp22
   5485  1.1        is 	lea		FP_SCR1(%a6),%a0
   5486  1.1        is 	bsr.l		norm			# normalize the denorm; result is new exp
   5487  1.1        is 	neg.w		%d0			# new exp = -(shft val)
   5488  1.1        is 	mov.w		%d0,2+L_SCR1(%a6)	# inset new exp
   5489  1.1        is 
   5490  1.1        is cmpexp22:
   5491  1.1        is 	mov.w		L_SCR1(%a6),%d0
   5492  1.1        is 	subi.w		&mantissalen+2,%d0	# subtract mantissalen+2 from larger exp
   5493  1.1        is 
   5494  1.1        is 	cmp.w		%d0,2+L_SCR1(%a6)	# is difference >= len(mantissa)+2?
   5495  1.1        is 	bge.b		quick_scale22
   5496  1.1        is 
   5497  1.1        is 	mov.w		2+L_SCR1(%a6),%d0
   5498  1.1        is 	add.w		0x2(%sp),%d0		# scale dst exponent by scale factor
   5499  1.1        is 	mov.w		FP_SCR1_EX(%a6),%d1
   5500  1.1        is 	andi.w		&0x8000,%d1
   5501  1.1        is 	or.w		%d1,%d0			# concat {sgn,new exp}
   5502  1.1        is 	mov.w		%d0,FP_SCR1_EX(%a6)	# insert new dst exponent
   5503  1.1        is 
   5504  1.1        is 	mov.l		(%sp)+,%d0		# return SCALE factor
   5505  1.1        is 	rts
   5506  1.1        is 
   5507  1.1        is quick_scale22:
   5508  1.1        is 	andi.w		&0x8000,FP_SCR1_EX(%a6)	# zero dst exponent
   5509  1.1        is 	bset		&0x0,1+FP_SCR1_EX(%a6)	# set exp = 1
   5510  1.1        is 
   5511  1.1        is 	mov.l		(%sp)+,%d0		# return SCALE factor
   5512  1.1        is 	rts
   5513  1.1        is 
   5514  1.1        is ##########################################################################
   5515  1.1        is 
   5516  1.1        is #########################################################################
   5517  1.1        is # XDEF ****************************************************************	#
   5518  1.1        is #	scale_to_zero_src(): scale the exponent of extended precision	#
   5519  1.1        is #			     value at FP_SCR0(a6).			#
   5520  1.1        is #									#
   5521  1.1        is # XREF ****************************************************************	#
   5522  1.1        is #	norm() - normalize the mantissa if the operand was a DENORM	#
   5523  1.1        is #									#
   5524  1.1        is # INPUT ***************************************************************	#
   5525  1.1        is #	FP_SCR0(a6) = extended precision operand to be scaled		#
   5526  1.1        is # 									#
   5527  1.1        is # OUTPUT **************************************************************	#
   5528  1.1        is #	FP_SCR0(a6) = scaled extended precision operand			#
   5529  1.1        is #	d0	    = scale value					#
   5530  1.1        is #									#
   5531  1.1        is # ALGORITHM ***********************************************************	#
   5532  1.1        is # 	Set the exponent of the input operand to 0x3fff. Save the value	#
   5533  1.1        is # of the difference between the original and new exponent. Then, 	#
   5534  1.1        is # normalize the operand if it was a DENORM. Add this normalization	#
   5535  1.1        is # value to the previous value. Return the result.			#
   5536  1.1        is #									#
   5537  1.1        is #########################################################################
   5538  1.1        is 
   5539  1.1        is 	global		scale_to_zero_src
   5540  1.1        is scale_to_zero_src:
   5541  1.1        is 	mov.w		FP_SCR0_EX(%a6),%d1	# extract operand's {sgn,exp}
   5542  1.1        is 	mov.w		%d1,%d0			# make a copy
   5543  1.1        is 
   5544  1.1        is 	andi.l		&0x7fff,%d1		# extract operand's exponent
   5545  1.1        is 
   5546  1.1        is 	andi.w		&0x8000,%d0		# extract operand's sgn
   5547  1.1        is 	or.w		&0x3fff,%d0		# insert new operand's exponent(=0)
   5548  1.1        is 
   5549  1.1        is 	mov.w		%d0,FP_SCR0_EX(%a6)	# insert biased exponent
   5550  1.1        is 
   5551  1.1        is 	cmpi.b		STAG(%a6),&DENORM	# is operand normalized?
   5552  1.1        is 	beq.b		stzs_denorm		# normalize the DENORM
   5553  1.1        is 
   5554  1.1        is stzs_norm:
   5555  1.1        is 	mov.l		&0x3fff,%d0
   5556  1.1        is 	sub.l		%d1,%d0			# scale = BIAS + (-exp)
   5557  1.1        is 
   5558  1.1        is 	rts
   5559  1.1        is 
   5560  1.1        is stzs_denorm:
   5561  1.1        is 	lea		FP_SCR0(%a6),%a0	# pass ptr to src op
   5562  1.1        is 	bsr.l		norm			# normalize denorm
   5563  1.1        is 	neg.l		%d0			# new exponent = -(shft val)
   5564  1.1        is 	mov.l		%d0,%d1			# prepare for op_norm call
   5565  1.1        is 	bra.b		stzs_norm		# finish scaling
   5566  1.1        is 
   5567  1.1        is ###
   5568  1.1        is 
   5569  1.1        is #########################################################################
   5570  1.1        is # XDEF ****************************************************************	#
   5571  1.1        is #	scale_sqrt(): scale the input operand exponent so a subsequent	#
   5572  1.1        is #		      fsqrt operation won't take an exception.		#
   5573  1.1        is #									#
   5574  1.1        is # XREF ****************************************************************	#
   5575  1.1        is #	norm() - normalize the mantissa if the operand was a DENORM	#
   5576  1.1        is #									#
   5577  1.1        is # INPUT ***************************************************************	#
   5578  1.1        is #	FP_SCR0(a6) = extended precision operand to be scaled		#
   5579  1.1        is # 									#
   5580  1.1        is # OUTPUT **************************************************************	#
   5581  1.1        is #	FP_SCR0(a6) = scaled extended precision operand			#
   5582  1.1        is #	d0	    = scale value					#
   5583  1.1        is #									#
   5584  1.1        is # ALGORITHM ***********************************************************	#
   5585  1.1        is #	If the input operand is a DENORM, normalize it.			#
   5586  1.1        is # 	If the exponent of the input operand is even, set the exponent	#
   5587  1.1        is # to 0x3ffe and return a scale factor of "(exp-0x3ffe)/2". If the 	#
   5588  1.1        is # exponent of the input operand is off, set the exponent to ox3fff and	#
   5589  1.1        is # return a scale factor of "(exp-0x3fff)/2". 				#
   5590  1.1        is #									#
   5591  1.1        is #########################################################################
   5592  1.1        is 
   5593  1.1        is 	global		scale_sqrt
   5594  1.1        is scale_sqrt:
   5595  1.1        is 	cmpi.b		STAG(%a6),&DENORM	# is operand normalized?
   5596  1.1        is 	beq.b		ss_denorm		# normalize the DENORM
   5597  1.1        is 
   5598  1.1        is 	mov.w		FP_SCR0_EX(%a6),%d1	# extract operand's {sgn,exp}
   5599  1.1        is 	andi.l		&0x7fff,%d1		# extract operand's exponent
   5600  1.1        is 
   5601  1.1        is 	andi.w		&0x8000,FP_SCR0_EX(%a6)	# extract operand's sgn
   5602  1.1        is 
   5603  1.1        is 	btst		&0x0,%d1		# is exp even or odd?
   5604  1.1        is 	beq.b		ss_norm_even
   5605  1.1        is 
   5606  1.1        is 	ori.w		&0x3fff,FP_SCR0_EX(%a6)	# insert new operand's exponent(=0)
   5607  1.1        is 
   5608  1.1        is 	mov.l		&0x3fff,%d0
   5609  1.1        is 	sub.l		%d1,%d0			# scale = BIAS + (-exp)
   5610  1.1        is 	asr.l		&0x1,%d0		# divide scale factor by 2
   5611  1.1        is 	rts
   5612  1.1        is 
   5613  1.1        is ss_norm_even:
   5614  1.1        is 	ori.w		&0x3ffe,FP_SCR0_EX(%a6)	# insert new operand's exponent(=0)
   5615  1.1        is 
   5616  1.1        is 	mov.l		&0x3ffe,%d0
   5617  1.1        is 	sub.l		%d1,%d0			# scale = BIAS + (-exp)
   5618  1.1        is 	asr.l		&0x1,%d0		# divide scale factor by 2
   5619  1.1        is 	rts
   5620  1.1        is 
   5621  1.1        is ss_denorm:
   5622  1.1        is 	lea		FP_SCR0(%a6),%a0	# pass ptr to src op
   5623  1.1        is 	bsr.l		norm			# normalize denorm
   5624  1.1        is 
   5625  1.1        is 	btst		&0x0,%d0		# is exp even or odd?
   5626  1.1        is 	beq.b		ss_denorm_even
   5627  1.1        is 
   5628  1.1        is 	ori.w		&0x3fff,FP_SCR0_EX(%a6)	# insert new operand's exponent(=0)
   5629  1.1        is 
   5630  1.1        is 	add.l		&0x3fff,%d0
   5631  1.1        is 	asr.l		&0x1,%d0		# divide scale factor by 2
   5632  1.1        is 	rts
   5633  1.1        is 
   5634  1.1        is ss_denorm_even:
   5635  1.1        is 	ori.w		&0x3ffe,FP_SCR0_EX(%a6)	# insert new operand's exponent(=0)
   5636  1.1        is 
   5637  1.1        is 	add.l		&0x3ffe,%d0
   5638  1.1        is 	asr.l		&0x1,%d0		# divide scale factor by 2
   5639  1.1        is 	rts
   5640  1.1        is 
   5641  1.1        is ###
   5642  1.1        is 
   5643  1.1        is #########################################################################
   5644  1.1        is # XDEF ****************************************************************	#
   5645  1.1        is #	scale_to_zero_dst(): scale the exponent of extended precision	#
   5646  1.1        is #			     value at FP_SCR1(a6).			#
   5647  1.1        is #									#
   5648  1.1        is # XREF ****************************************************************	#
   5649  1.1        is #	norm() - normalize the mantissa if the operand was a DENORM	#
   5650  1.1        is #									#
   5651  1.1        is # INPUT ***************************************************************	#
   5652  1.1        is #	FP_SCR1(a6) = extended precision operand to be scaled		#
   5653  1.1        is # 									#
   5654  1.1        is # OUTPUT **************************************************************	#
   5655  1.1        is #	FP_SCR1(a6) = scaled extended precision operand			#
   5656  1.1        is #	d0	    = scale value					#
   5657  1.1        is #									#
   5658  1.1        is # ALGORITHM ***********************************************************	#
   5659  1.1        is # 	Set the exponent of the input operand to 0x3fff. Save the value	#
   5660  1.1        is # of the difference between the original and new exponent. Then, 	#
   5661  1.1        is # normalize the operand if it was a DENORM. Add this normalization	#
   5662  1.1        is # value to the previous value. Return the result.			#
   5663  1.1        is #									#
   5664  1.1        is #########################################################################
   5665  1.1        is 
   5666  1.1        is 	global		scale_to_zero_dst
   5667  1.1        is scale_to_zero_dst:
   5668  1.1        is 	mov.w		FP_SCR1_EX(%a6),%d1	# extract operand's {sgn,exp}
   5669  1.1        is 	mov.w		%d1,%d0			# make a copy
   5670  1.1        is 
   5671  1.1        is 	andi.l		&0x7fff,%d1		# extract operand's exponent
   5672  1.1        is 
   5673  1.1        is 	andi.w		&0x8000,%d0		# extract operand's sgn
   5674  1.1        is 	or.w		&0x3fff,%d0		# insert new operand's exponent(=0)
   5675  1.1        is 
   5676  1.1        is 	mov.w		%d0,FP_SCR1_EX(%a6)	# insert biased exponent
   5677  1.1        is 
   5678  1.1        is 	cmpi.b		DTAG(%a6),&DENORM	# is operand normalized?
   5679  1.1        is 	beq.b		stzd_denorm		# normalize the DENORM
   5680  1.1        is 
   5681  1.1        is stzd_norm:
   5682  1.1        is 	mov.l		&0x3fff,%d0
   5683  1.1        is 	sub.l		%d1,%d0			# scale = BIAS + (-exp)
   5684  1.1        is 	rts
   5685  1.1        is 
   5686  1.1        is stzd_denorm:
   5687  1.1        is 	lea		FP_SCR1(%a6),%a0	# pass ptr to dst op
   5688  1.1        is 	bsr.l		norm			# normalize denorm
   5689  1.1        is 	neg.l		%d0			# new exponent = -(shft val)
   5690  1.1        is 	mov.l		%d0,%d1			# prepare for op_norm call
   5691  1.1        is 	bra.b		stzd_norm		# finish scaling
   5692  1.1        is 
   5693  1.1        is ##########################################################################
   5694  1.1        is 
   5695  1.1        is #########################################################################
   5696  1.1        is # XDEF ****************************************************************	#
   5697  1.1        is #	res_qnan(): return default result w/ QNAN operand for dyadic	#
   5698  1.1        is #	res_snan(): return default result w/ SNAN operand for dyadic	#
   5699  1.1        is #	res_qnan_1op(): return dflt result w/ QNAN operand for monadic	#
   5700  1.1        is #	res_snan_1op(): return dflt result w/ SNAN operand for monadic	#
   5701  1.1        is #									#
   5702  1.1        is # XREF ****************************************************************	#
   5703  1.1        is #	None								#
   5704  1.1        is #									#
   5705  1.1        is # INPUT ***************************************************************	#
   5706  1.1        is #	FP_SRC(a6) = pointer to extended precision src operand		#
   5707  1.1        is #	FP_DST(a6) = pointer to extended precision dst operand		#
   5708  1.1        is # 									#
   5709  1.1        is # OUTPUT **************************************************************	#
   5710  1.1        is #	fp0 = default result						#
   5711  1.1        is #									#
   5712  1.1        is # ALGORITHM ***********************************************************	#
   5713  1.1        is # 	If either operand (but not both operands) of an operation is a	#
   5714  1.1        is # nonsignalling NAN, then that NAN is returned as the result. If both	#
   5715  1.1        is # operands are nonsignalling NANs, then the destination operand 	#
   5716  1.1        is # nonsignalling NAN is returned as the result.				#
   5717  1.1        is # 	If either operand to an operation is a signalling NAN (SNAN),	#
   5718  1.1        is # then, the SNAN bit is set in the FPSR EXC byte. If the SNAN trap	#
   5719  1.1        is # enable bit is set in the FPCR, then the trap is taken and the 	#
   5720  1.1        is # destination is not modified. If the SNAN trap enable bit is not set,	#
   5721  1.1        is # then the SNAN is converted to a nonsignalling NAN (by setting the 	#
   5722  1.1        is # SNAN bit in the operand to one), and the operation continues as 	#
   5723  1.1        is # described in the preceding paragraph, for nonsignalling NANs.		#
   5724  1.1        is #	Make sure the appropriate FPSR bits are set before exiting.	#
   5725  1.1        is #									#
   5726  1.1        is #########################################################################
   5727  1.1        is 
   5728  1.1        is 	global		res_qnan
   5729  1.1        is 	global		res_snan
   5730  1.1        is res_qnan:
   5731  1.1        is res_snan:
   5732  1.1        is 	cmp.b		DTAG(%a6), &SNAN	# is the dst an SNAN?
   5733  1.1        is 	beq.b		dst_snan2
   5734  1.1        is 	cmp.b		DTAG(%a6), &QNAN	# is the dst a  QNAN?
   5735  1.1        is 	beq.b		dst_qnan2
   5736  1.1        is src_nan:
   5737  1.1        is 	cmp.b		STAG(%a6), &QNAN
   5738  1.1        is 	beq.b		src_qnan2
   5739  1.1        is 	global		res_snan_1op
   5740  1.1        is res_snan_1op:
   5741  1.1        is src_snan2:
   5742  1.1        is 	bset		&0x6, FP_SRC_HI(%a6)	# set SNAN bit
   5743  1.1        is 	or.l		&nan_mask+aiop_mask+snan_mask, USER_FPSR(%a6)
   5744  1.1        is 	lea		FP_SRC(%a6), %a0
   5745  1.1        is 	bra.b		nan_comp
   5746  1.1        is 	global		res_qnan_1op
   5747  1.1        is res_qnan_1op:
   5748  1.1        is src_qnan2:
   5749  1.1        is 	or.l		&nan_mask, USER_FPSR(%a6)
   5750  1.1        is 	lea		FP_SRC(%a6), %a0
   5751  1.1        is 	bra.b		nan_comp
   5752  1.1        is dst_snan2:
   5753  1.1        is 	or.l		&nan_mask+aiop_mask+snan_mask, USER_FPSR(%a6)
   5754  1.1        is 	bset		&0x6, FP_DST_HI(%a6)	# set SNAN bit
   5755  1.1        is 	lea		FP_DST(%a6), %a0
   5756  1.1        is 	bra.b		nan_comp
   5757  1.1        is dst_qnan2:
   5758  1.1        is 	lea		FP_DST(%a6), %a0
   5759  1.1        is 	cmp.b		STAG(%a6), &SNAN
   5760  1.1        is 	bne		nan_done
   5761  1.1        is 	or.l		&aiop_mask+snan_mask, USER_FPSR(%a6)
   5762  1.1        is nan_done:
   5763  1.1        is 	or.l		&nan_mask, USER_FPSR(%a6)
   5764  1.1        is nan_comp:
   5765  1.1        is 	btst		&0x7, FTEMP_EX(%a0)	# is NAN neg?
   5766  1.1        is 	beq.b		nan_not_neg
   5767  1.1        is 	or.l		&neg_mask, USER_FPSR(%a6)
   5768  1.1        is nan_not_neg:
   5769  1.1        is 	fmovm.x		(%a0), &0x80
   5770  1.1        is 	rts
   5771  1.1        is 
   5772  1.1        is #########################################################################
   5773  1.1        is # XDEF ****************************************************************	#
   5774  1.1        is # 	res_operr(): return default result during operand error		#
   5775  1.1        is #									#
   5776  1.1        is # XREF ****************************************************************	#
   5777  1.1        is #	None								#
   5778  1.1        is #									#
   5779  1.1        is # INPUT ***************************************************************	#
   5780  1.1        is #	None								#
   5781  1.1        is # 									#
   5782  1.1        is # OUTPUT **************************************************************	#
   5783  1.1        is #	fp0 = default operand error result				#
   5784  1.1        is #									#
   5785  1.1        is # ALGORITHM ***********************************************************	#
   5786  1.1        is #	An nonsignalling NAN is returned as the default result when	#
   5787  1.1        is # an operand error occurs for the following cases:			#
   5788  1.1        is #									#
   5789  1.1        is # 	Multiply: (Infinity x Zero)					#
   5790  1.1        is # 	Divide  : (Zero / Zero) || (Infinity / Infinity)		#
   5791  1.1        is #									#
   5792  1.1        is #########################################################################
   5793  1.1        is 
   5794  1.1        is 	global		res_operr
   5795  1.1        is res_operr:
   5796  1.1        is 	or.l		&nan_mask+operr_mask+aiop_mask, USER_FPSR(%a6)
   5797  1.1        is 	fmovm.x		nan_return(%pc), &0x80
   5798  1.1        is 	rts
   5799  1.1        is 
   5800  1.1        is nan_return:
   5801  1.1        is 	long		0x7fff0000, 0xffffffff, 0xffffffff
   5802  1.1        is 
   5803  1.1        is #########################################################################
   5804  1.1        is # XDEF ****************************************************************	#
   5805  1.1        is # 	_denorm(): denormalize an intermediate result			#
   5806  1.1        is #									#
   5807  1.1        is # XREF ****************************************************************	#
   5808  1.1        is #	None								#
   5809  1.1        is #									#
   5810  1.1        is # INPUT *************************************************************** #
   5811  1.1        is #	a0 = points to the operand to be denormalized			#
   5812  1.1        is #		(in the internal extended format)			#
   5813  1.1        is #		 							#
   5814  1.1        is #	d0 = rounding precision						#
   5815  1.1        is #									#
   5816  1.1        is # OUTPUT **************************************************************	#
   5817  1.1        is #	a0 = pointer to the denormalized result				#
   5818  1.1        is #		(in the internal extended format)			#
   5819  1.1        is #									#
   5820  1.1        is #	d0 = guard,round,sticky						#
   5821  1.1        is #									#
   5822  1.1        is # ALGORITHM ***********************************************************	#
   5823  1.1        is # 	According to the exponent underflow threshold for the given	#
   5824  1.1        is # precision, shift the mantissa bits to the right in order raise the	#
   5825  1.1        is # exponent of the operand to the threshold value. While shifting the 	#
   5826  1.1        is # mantissa bits right, maintain the value of the guard, round, and 	#
   5827  1.1        is # sticky bits.								#
   5828  1.1        is # other notes:								#
   5829  1.1        is #	(1) _denorm() is called by the underflow routines		#
   5830  1.1        is #	(2) _denorm() does NOT affect the status register		#
   5831  1.1        is #									#
   5832  1.1        is #########################################################################
   5833  1.1        is 
   5834  1.1        is #
   5835  1.1        is # table of exponent threshold values for each precision
   5836  1.1        is #
   5837  1.1        is tbl_thresh:
   5838  1.1        is 	short		0x0
   5839  1.1        is 	short		sgl_thresh
   5840  1.1        is 	short		dbl_thresh
   5841  1.1        is 
   5842  1.1        is 	global		_denorm
   5843  1.1        is _denorm:
   5844  1.1        is #
   5845  1.1        is # Load the exponent threshold for the precision selected and check
   5846  1.1        is # to see if (threshold - exponent) is > 65 in which case we can
   5847  1.1        is # simply calculate the sticky bit and zero the mantissa. otherwise
   5848  1.1        is # we have to call the denormalization routine.
   5849  1.1        is #
   5850  1.1        is 	lsr.b		&0x2, %d0		# shift prec to lo bits
   5851  1.1        is 	mov.w		(tbl_thresh.b,%pc,%d0.w*2), %d1 # load prec threshold
   5852  1.1        is 	mov.w		%d1, %d0		# copy d1 into d0
   5853  1.1        is 	sub.w		FTEMP_EX(%a0), %d0	# diff = threshold - exp
   5854  1.1        is 	cmpi.w		%d0, &66		# is diff > 65? (mant + g,r bits)
   5855  1.1        is 	bpl.b		denorm_set_stky		# yes; just calc sticky
   5856  1.1        is 
   5857  1.1        is 	clr.l		%d0			# clear g,r,s
   5858  1.1        is 	btst		&inex2_bit, FPSR_EXCEPT(%a6) # yes; was INEX2 set?
   5859  1.1        is 	beq.b		denorm_call		# no; don't change anything
   5860  1.1        is 	bset		&29, %d0		# yes; set sticky bit
   5861  1.1        is 
   5862  1.1        is denorm_call:
   5863  1.1        is 	bsr.l		dnrm_lp			# denormalize the number
   5864  1.1        is 	rts
   5865  1.1        is 
   5866  1.1        is #
   5867  1.1        is # all bit would have been shifted off during the denorm so simply
   5868  1.1        is # calculate if the sticky should be set and clear the entire mantissa.
   5869  1.1        is #
   5870  1.1        is denorm_set_stky:
   5871  1.1        is 	mov.l		&0x20000000, %d0	# set sticky bit in return value
   5872  1.1        is 	mov.w		%d1, FTEMP_EX(%a0)	# load exp with threshold
   5873  1.1        is 	clr.l		FTEMP_HI(%a0)		# set d1 = 0 (ms mantissa)
   5874  1.1        is 	clr.l		FTEMP_LO(%a0)		# set d2 = 0 (ms mantissa)
   5875  1.1        is 	rts
   5876  1.1        is 
   5877  1.1        is #									#
   5878  1.1        is # dnrm_lp(): normalize exponent/mantissa to specified threshhold	#
   5879  1.1        is #									#
   5880  1.1        is # INPUT:								#
   5881  1.1        is #	%a0	   : points to the operand to be denormalized		#
   5882  1.1        is #	%d0{31:29} : initial guard,round,sticky				#
   5883  1.1        is #	%d1{15:0}  : denormalization threshold				#
   5884  1.1        is # OUTPUT:								#
   5885  1.1        is #	%a0	   : points to the denormalized operand		 	#
   5886  1.1        is #	%d0{31:29} : final guard,round,sticky				#
   5887  1.1        is #									#
   5888  1.1        is 
   5889  1.1        is # *** Local Equates *** #
   5890  1.1        is set	GRS,		L_SCR2			# g,r,s temp storage
   5891  1.1        is set	FTEMP_LO2,	L_SCR1			# FTEMP_LO copy
   5892  1.1        is 
   5893  1.1        is 	global		dnrm_lp
   5894  1.1        is dnrm_lp:
   5895  1.1        is 
   5896  1.1        is #
   5897  1.1        is # make a copy of FTEMP_LO and place the g,r,s bits directly after it
   5898  1.1        is # in memory so as to make the bitfield extraction for denormalization easier.
   5899  1.1        is #
   5900  1.1        is 	mov.l		FTEMP_LO(%a0), FTEMP_LO2(%a6) # make FTEMP_LO copy
   5901  1.1        is 	mov.l		%d0, GRS(%a6)		# place g,r,s after it
   5902  1.1        is 
   5903  1.1        is #
   5904  1.1        is # check to see how much less than the underflow threshold the operand
   5905  1.1        is # exponent is.
   5906  1.1        is #
   5907  1.1        is 	mov.l		%d1, %d0		# copy the denorm threshold
   5908  1.1        is 	sub.w		FTEMP_EX(%a0), %d1	# d1 = threshold - uns exponent
   5909  1.1        is 	ble.b		dnrm_no_lp		# d1 <= 0
   5910  1.1        is 	cmpi.w		%d1, &0x20		# is ( 0 <= d1 < 32) ?
   5911  1.1        is 	blt.b		case_1			# yes
   5912  1.1        is 	cmpi.w		%d1, &0x40		# is (32 <= d1 < 64) ?
   5913  1.1        is 	blt.b		case_2			# yes
   5914  1.1        is 	bra.w		case_3			# (d1 >= 64)
   5915  1.1        is 
   5916  1.1        is #
   5917  1.1        is # No normalization necessary
   5918  1.1        is #
   5919  1.1        is dnrm_no_lp:
   5920  1.1        is 	mov.l		GRS(%a6), %d0 		# restore original g,r,s
   5921  1.1        is 	rts
   5922  1.1        is 
   5923  1.1        is #
   5924  1.1        is # case (0<d1<32)
   5925  1.1        is #
   5926  1.1        is # %d0 = denorm threshold
   5927  1.1        is # %d1 = "n" = amt to shift
   5928  1.1        is #
   5929  1.1        is #	---------------------------------------------------------
   5930  1.1        is #	|     FTEMP_HI	  |    	FTEMP_LO     |grs000.........000|
   5931  1.1        is #	---------------------------------------------------------
   5932  1.1        is #	<-(32 - n)-><-(n)-><-(32 - n)-><-(n)-><-(32 - n)-><-(n)->
   5933  1.1        is #	\	   \		      \			 \
   5934  1.1        is #	 \	    \		       \		  \
   5935  1.1        is #	  \	     \			\		   \
   5936  1.1        is #	   \	      \			 \		    \
   5937  1.1        is #	    \	       \		  \		     \
   5938  1.1        is #	     \		\		   \		      \
   5939  1.1        is #	      \		 \		    \		       \
   5940  1.1        is #	       \	  \		     \			\
   5941  1.1        is #	<-(n)-><-(32 - n)-><------(32)-------><------(32)------->
   5942  1.1        is #	---------------------------------------------------------
   5943  1.1        is #	|0.....0| NEW_HI  |  NEW_FTEMP_LO     |grs		|
   5944  1.1        is #	---------------------------------------------------------
   5945  1.1        is #
   5946  1.1        is case_1:
   5947  1.1        is 	mov.l		%d2, -(%sp)		# create temp storage
   5948  1.1        is 
   5949  1.1        is 	mov.w		%d0, FTEMP_EX(%a0)	# exponent = denorm threshold
   5950  1.1        is 	mov.l		&32, %d0
   5951  1.1        is 	sub.w		%d1, %d0		# %d0 = 32 - %d1
   5952  1.1        is 
   5953  1.1        is 	cmpi.w		%d1, &29		# is shft amt >= 29
   5954  1.1        is 	blt.b		case1_extract		# no; no fix needed
   5955  1.1        is 	mov.b		GRS(%a6), %d2
   5956  1.1        is 	or.b		%d2, 3+FTEMP_LO2(%a6)
   5957  1.1        is 
   5958  1.1        is case1_extract:
   5959  1.1        is 	bfextu		FTEMP_HI(%a0){&0:%d0}, %d2 # %d2 = new FTEMP_HI
   5960  1.1        is 	bfextu		FTEMP_HI(%a0){%d0:&32}, %d1 # %d1 = new FTEMP_LO
   5961  1.1        is 	bfextu		FTEMP_LO2(%a6){%d0:&32}, %d0 # %d0 = new G,R,S
   5962  1.1        is 
   5963  1.1        is 	mov.l		%d2, FTEMP_HI(%a0)	# store new FTEMP_HI
   5964  1.1        is 	mov.l		%d1, FTEMP_LO(%a0)	# store new FTEMP_LO
   5965  1.1        is 
   5966  1.1        is 	bftst		%d0{&2:&30}		# were bits shifted off?
   5967  1.1        is 	beq.b		case1_sticky_clear	# no; go finish
   5968  1.1        is 	bset		&rnd_stky_bit, %d0	# yes; set sticky bit
   5969  1.1        is 
   5970  1.1        is case1_sticky_clear:
   5971  1.1        is 	and.l		&0xe0000000, %d0	# clear all but G,R,S
   5972  1.1        is 	mov.l		(%sp)+, %d2		# restore temp register
   5973  1.1        is 	rts
   5974  1.1        is 
   5975  1.1        is #
   5976  1.1        is # case (32<=d1<64)
   5977  1.1        is #
   5978  1.1        is # %d0 = denorm threshold
   5979  1.1        is # %d1 = "n" = amt to shift
   5980  1.1        is #
   5981  1.1        is #	---------------------------------------------------------
   5982  1.1        is #	|     FTEMP_HI	  |    	FTEMP_LO     |grs000.........000|
   5983  1.1        is #	---------------------------------------------------------
   5984  1.1        is #	<-(32 - n)-><-(n)-><-(32 - n)-><-(n)-><-(32 - n)-><-(n)->
   5985  1.1        is #	\	   \		      \
   5986  1.1        is #	 \	    \		       \
   5987  1.1        is #	  \	     \			-------------------
   5988  1.1        is #	   \	      --------------------		   \
   5989  1.1        is #	    -------------------	  	  \		    \
   5990  1.1        is #	     		       \	   \		     \
   5991  1.1        is #	      		 	\     	    \		      \
   5992  1.1        is #	       		  	 \	     \		       \
   5993  1.1        is #	<-------(32)------><-(n)-><-(32 - n)-><------(32)------->
   5994  1.1        is #	---------------------------------------------------------
   5995  1.1        is #	|0...............0|0....0| NEW_LO     |grs		|
   5996  1.1        is #	---------------------------------------------------------
   5997  1.1        is #
   5998  1.1        is case_2:
   5999  1.1        is 	mov.l		%d2, -(%sp)		# create temp storage
   6000  1.1        is 
   6001  1.1        is 	mov.w		%d0, FTEMP_EX(%a0)	# exponent = denorm threshold
   6002  1.1        is 	subi.w		&0x20, %d1		# %d1 now between 0 and 32
   6003  1.1        is 	mov.l		&0x20, %d0
   6004  1.1        is 	sub.w		%d1, %d0		# %d0 = 32 - %d1
   6005  1.1        is 
   6006  1.1        is # subtle step here; or in the g,r,s at the bottom of FTEMP_LO to minimize
   6007  1.1        is # the number of bits to check for the sticky detect.
   6008  1.1        is # it only plays a role in shift amounts of 61-63.
   6009  1.1        is 	mov.b		GRS(%a6), %d2
   6010  1.1        is 	or.b		%d2, 3+FTEMP_LO2(%a6)
   6011  1.1        is 
   6012  1.1        is 	bfextu		FTEMP_HI(%a0){&0:%d0}, %d2 # %d2 = new FTEMP_LO
   6013  1.1        is 	bfextu		FTEMP_HI(%a0){%d0:&32}, %d1 # %d1 = new G,R,S
   6014  1.1        is 
   6015  1.1        is 	bftst		%d1{&2:&30}		# were any bits shifted off?
   6016  1.1        is 	bne.b		case2_set_sticky	# yes; set sticky bit
   6017  1.1        is 	bftst		FTEMP_LO2(%a6){%d0:&31}	# were any bits shifted off?
   6018  1.1        is 	bne.b		case2_set_sticky	# yes; set sticky bit
   6019  1.1        is 
   6020  1.1        is 	mov.l		%d1, %d0		# move new G,R,S to %d0
   6021  1.1        is 	bra.b		case2_end
   6022  1.1        is 
   6023  1.1        is case2_set_sticky:
   6024  1.1        is 	mov.l		%d1, %d0		# move new G,R,S to %d0
   6025  1.1        is 	bset		&rnd_stky_bit, %d0	# set sticky bit
   6026  1.1        is 
   6027  1.1        is case2_end:
   6028  1.1        is 	clr.l		FTEMP_HI(%a0)		# store FTEMP_HI = 0
   6029  1.1        is 	mov.l		%d2, FTEMP_LO(%a0)	# store FTEMP_LO
   6030  1.1        is 	and.l		&0xe0000000, %d0	# clear all but G,R,S
   6031  1.1        is 
   6032  1.1        is 	mov.l		(%sp)+,%d2		# restore temp register
   6033  1.1        is 	rts
   6034  1.1        is 
   6035  1.1        is #
   6036  1.1        is # case (d1>=64)
   6037  1.1        is #
   6038  1.1        is # %d0 = denorm threshold
   6039  1.1        is # %d1 = amt to shift
   6040  1.1        is #
   6041  1.1        is case_3:
   6042  1.1        is 	mov.w		%d0, FTEMP_EX(%a0)	# insert denorm threshold
   6043  1.1        is 
   6044  1.1        is 	cmpi.w		%d1, &65		# is shift amt > 65?
   6045  1.1        is 	blt.b		case3_64		# no; it's == 64
   6046  1.1        is 	beq.b		case3_65		# no; it's == 65
   6047  1.1        is 
   6048  1.1        is #
   6049  1.1        is # case (d1>65)
   6050  1.1        is #
   6051  1.1        is # Shift value is > 65 and out of range. All bits are shifted off.
   6052  1.1        is # Return a zero mantissa with the sticky bit set
   6053  1.1        is #
   6054  1.1        is 	clr.l		FTEMP_HI(%a0)		# clear hi(mantissa)
   6055  1.1        is 	clr.l		FTEMP_LO(%a0)		# clear lo(mantissa)
   6056  1.1        is 	mov.l		&0x20000000, %d0	# set sticky bit
   6057  1.1        is 	rts
   6058  1.1        is 
   6059  1.1        is #
   6060  1.1        is # case (d1 == 64)
   6061  1.1        is #
   6062  1.1        is #	---------------------------------------------------------
   6063  1.1        is #	|     FTEMP_HI	  |    	FTEMP_LO     |grs000.........000|
   6064  1.1        is #	---------------------------------------------------------
   6065  1.1        is #	<-------(32)------>
   6066  1.1        is #	\	   	   \
   6067  1.1        is #	 \	    	    \
   6068  1.1        is #	  \	     	     \
   6069  1.1        is #	   \	      	      ------------------------------
   6070  1.1        is #	    -------------------------------		    \
   6071  1.1        is #	     		       		   \		     \
   6072  1.1        is #	      		 	     	    \		      \
   6073  1.1        is #	       		  	 	     \		       \
   6074  1.1        is #					      <-------(32)------>
   6075  1.1        is #	---------------------------------------------------------
   6076  1.1        is #	|0...............0|0................0|grs		|
   6077  1.1        is #	---------------------------------------------------------
   6078  1.1        is #
   6079  1.1        is case3_64:
   6080  1.1        is 	mov.l		FTEMP_HI(%a0), %d0	# fetch hi(mantissa)
   6081  1.1        is 	mov.l		%d0, %d1		# make a copy
   6082  1.1        is 	and.l		&0xc0000000, %d0	# extract G,R
   6083  1.1        is 	and.l		&0x3fffffff, %d1	# extract other bits
   6084  1.1        is 
   6085  1.1        is 	bra.b		case3_complete
   6086  1.1        is 
   6087  1.1        is #
   6088  1.1        is # case (d1 == 65)
   6089  1.1        is #
   6090  1.1        is #	---------------------------------------------------------
   6091  1.1        is #	|     FTEMP_HI	  |    	FTEMP_LO     |grs000.........000|
   6092  1.1        is #	---------------------------------------------------------
   6093  1.1        is #	<-------(32)------>
   6094  1.1        is #	\	   	   \
   6095  1.1        is #	 \	    	    \
   6096  1.1        is #	  \	     	     \
   6097  1.1        is #	   \	      	      ------------------------------
   6098  1.1        is #	    --------------------------------		    \
   6099  1.1        is #	     		       		    \		     \
   6100  1.1        is #	      		 	     	     \		      \
   6101  1.1        is #	       		  	 	      \		       \
   6102  1.1        is #					       <-------(31)----->
   6103  1.1        is #	---------------------------------------------------------
   6104  1.1        is #	|0...............0|0................0|0rs		|
   6105  1.1        is #	---------------------------------------------------------
   6106  1.1        is #
   6107  1.1        is case3_65:
   6108  1.1        is 	mov.l		FTEMP_HI(%a0), %d0	# fetch hi(mantissa)
   6109  1.1        is 	and.l		&0x80000000, %d0	# extract R bit
   6110  1.1        is 	lsr.l		&0x1, %d0		# shift high bit into R bit
   6111  1.1        is 	and.l		&0x7fffffff, %d1	# extract other bits
   6112  1.1        is 
   6113  1.1        is case3_complete:
   6114  1.1        is # last operation done was an "and" of the bits shifted off so the condition
   6115  1.1        is # codes are already set so branch accordingly.
   6116  1.1        is 	bne.b		case3_set_sticky	# yes; go set new sticky
   6117  1.1        is 	tst.l		FTEMP_LO(%a0)		# were any bits shifted off?
   6118  1.1        is 	bne.b		case3_set_sticky	# yes; go set new sticky
   6119  1.1        is 	tst.b		GRS(%a6)		# were any bits shifted off?
   6120  1.1        is 	bne.b		case3_set_sticky	# yes; go set new sticky
   6121  1.1        is 
   6122  1.1        is #
   6123  1.1        is # no bits were shifted off so don't set the sticky bit.
   6124  1.1        is # the guard and
   6125  1.1        is # the entire mantissa is zero.
   6126  1.1        is #
   6127  1.1        is 	clr.l		FTEMP_HI(%a0)		# clear hi(mantissa)
   6128  1.1        is 	clr.l		FTEMP_LO(%a0)		# clear lo(mantissa)
   6129  1.1        is 	rts
   6130  1.1        is 
   6131  1.1        is #
   6132  1.1        is # some bits were shifted off so set the sticky bit.
   6133  1.1        is # the entire mantissa is zero.
   6134  1.1        is #
   6135  1.1        is case3_set_sticky:
   6136  1.1        is 	bset		&rnd_stky_bit,%d0	# set new sticky bit
   6137  1.1        is 	clr.l		FTEMP_HI(%a0)		# clear hi(mantissa)
   6138  1.1        is 	clr.l		FTEMP_LO(%a0)		# clear lo(mantissa)
   6139  1.1        is 	rts
   6140  1.1        is 
   6141  1.1        is #########################################################################
   6142  1.1        is # XDEF ****************************************************************	#
   6143  1.1        is #	_round(): round result according to precision/mode		#
   6144  1.1        is #									#
   6145  1.1        is # XREF ****************************************************************	#
   6146  1.1        is #	None								#
   6147  1.1        is #									#
   6148  1.1        is # INPUT ***************************************************************	#
   6149  1.1        is #	a0	  = ptr to input operand in internal extended format 	#
   6150  1.1        is #	d1(hi)    = contains rounding precision:			#
   6151  1.1        is #			ext = $0000xxxx					#
   6152  1.1        is #			sgl = $0004xxxx					#
   6153  1.1        is #			dbl = $0008xxxx					#
   6154  1.1        is #	d1(lo)	  = contains rounding mode:				#
   6155  1.1        is #			RN  = $xxxx0000					#
   6156  1.1        is #			RZ  = $xxxx0001					#
   6157  1.1        is #			RM  = $xxxx0002					#
   6158  1.1        is #			RP  = $xxxx0003					#
   6159  1.1        is #	d0{31:29} = contains the g,r,s bits (extended)			#
   6160  1.1        is #									#
   6161  1.1        is # OUTPUT **************************************************************	#
   6162  1.1        is #	a0 = pointer to rounded result					#
   6163  1.1        is #									#
   6164  1.1        is # ALGORITHM ***********************************************************	#
   6165  1.1        is #	On return the value pointed to by a0 is correctly rounded,	#
   6166  1.1        is #	a0 is preserved and the g-r-s bits in d0 are cleared.		#
   6167  1.1        is #	The result is not typed - the tag field is invalid.  The	#
   6168  1.1        is #	result is still in the internal extended format.		#
   6169  1.1        is #									#
   6170  1.1        is #	The INEX bit of USER_FPSR will be set if the rounded result was	#
   6171  1.1        is #	inexact (i.e. if any of the g-r-s bits were set).		#
   6172  1.1        is #									#
   6173  1.1        is #########################################################################
   6174  1.1        is 
   6175  1.1        is 	global		_round
   6176  1.1        is _round:
   6177  1.1        is #
   6178  1.1        is # ext_grs() looks at the rounding precision and sets the appropriate
   6179  1.1        is # G,R,S bits.
   6180  1.1        is # If (G,R,S == 0) then result is exact and round is done, else set
   6181  1.1        is # the inex flag in status reg and continue.
   6182  1.1        is #
   6183  1.1        is 	bsr.l		ext_grs			# extract G,R,S
   6184  1.1        is 
   6185  1.1        is 	tst.l		%d0			# are G,R,S zero?
   6186  1.1        is 	beq.w		truncate		# yes; round is complete
   6187  1.1        is 
   6188  1.1        is 	or.w		&inx2a_mask, 2+USER_FPSR(%a6) # set inex2/ainex
   6189  1.1        is 
   6190  1.1        is #
   6191  1.1        is # Use rounding mode as an index into a jump table for these modes.
   6192  1.1        is # All of the following assumes grs != 0.
   6193  1.1        is #
   6194  1.1        is 	mov.w		(tbl_mode.b,%pc,%d1.w*2), %a1 # load jump offset
   6195  1.1        is 	jmp		(tbl_mode.b,%pc,%a1)	# jmp to rnd mode handler
   6196  1.1        is 
   6197  1.1        is tbl_mode:
   6198  1.1        is 	short		rnd_near - tbl_mode
   6199  1.1        is 	short		truncate - tbl_mode	# RZ always truncates
   6200  1.1        is 	short		rnd_mnus - tbl_mode
   6201  1.1        is 	short		rnd_plus - tbl_mode
   6202  1.1        is 
   6203  1.1        is #################################################################
   6204  1.1        is #	ROUND PLUS INFINITY					#
   6205  1.1        is #								#
   6206  1.1        is #	If sign of fp number = 0 (positive), then add 1 to l.	#
   6207  1.1        is #################################################################
   6208  1.1        is rnd_plus:
   6209  1.1        is 	tst.b		FTEMP_SGN(%a0)		# check for sign
   6210  1.1        is 	bmi.w		truncate		# if positive then truncate
   6211  1.1        is 
   6212  1.1        is 	mov.l		&0xffffffff, %d0	# force g,r,s to be all f's
   6213  1.1        is 	swap		%d1			# set up d1 for round prec.
   6214  1.1        is 
   6215  1.1        is 	cmpi.b		%d1, &s_mode		# is prec = sgl?
   6216  1.1        is 	beq.w		add_sgl			# yes
   6217  1.1        is 	bgt.w		add_dbl			# no; it's dbl
   6218  1.1        is 	bra.w		add_ext			# no; it's ext
   6219  1.1        is 
   6220  1.1        is #################################################################
   6221  1.1        is #	ROUND MINUS INFINITY					#
   6222  1.1        is #								#
   6223  1.1        is #	If sign of fp number = 1 (negative), then add 1 to l.	#
   6224  1.1        is #################################################################
   6225  1.1        is rnd_mnus:
   6226  1.1        is 	tst.b		FTEMP_SGN(%a0)		# check for sign
   6227  1.1        is 	bpl.w		truncate		# if negative then truncate
   6228  1.1        is 
   6229  1.1        is 	mov.l		&0xffffffff, %d0	# force g,r,s to be all f's
   6230  1.1        is 	swap		%d1			# set up d1 for round prec.
   6231  1.1        is 
   6232  1.1        is 	cmpi.b		%d1, &s_mode		# is prec = sgl?
   6233  1.1        is 	beq.w		add_sgl			# yes
   6234  1.1        is 	bgt.w		add_dbl			# no; it's dbl
   6235  1.1        is 	bra.w		add_ext			# no; it's ext
   6236  1.1        is 
   6237  1.1        is #################################################################
   6238  1.1        is #	ROUND NEAREST						#
   6239  1.1        is #								#
   6240  1.1        is #	If (g=1), then add 1 to l and if (r=s=0), then clear l	#
   6241  1.1        is #	Note that this will round to even in case of a tie.	#
   6242  1.1        is #################################################################
   6243  1.1        is rnd_near:
   6244  1.1        is 	asl.l		&0x1, %d0		# shift g-bit to c-bit
   6245  1.1        is 	bcc.w		truncate		# if (g=1) then
   6246  1.1        is 
   6247  1.1        is 	swap		%d1			# set up d1 for round prec.
   6248  1.1        is 
   6249  1.1        is 	cmpi.b		%d1, &s_mode		# is prec = sgl?
   6250  1.1        is 	beq.w		add_sgl			# yes
   6251  1.1        is 	bgt.w		add_dbl			# no; it's dbl
   6252  1.1        is 	bra.w		add_ext			# no; it's ext
   6253  1.1        is 
   6254  1.1        is # *** LOCAL EQUATES ***
   6255  1.1        is set	ad_1_sgl,	0x00000100	# constant to add 1 to l-bit in sgl prec
   6256  1.1        is set	ad_1_dbl,	0x00000800	# constant to add 1 to l-bit in dbl prec
   6257  1.1        is 
   6258  1.1        is #########################
   6259  1.1        is #	ADD SINGLE	#
   6260  1.1        is #########################
   6261  1.1        is add_sgl:
   6262  1.1        is 	add.l		&ad_1_sgl, FTEMP_HI(%a0)
   6263  1.1        is 	bcc.b		scc_clr			# no mantissa overflow
   6264  1.1        is 	roxr.w		FTEMP_HI(%a0)		# shift v-bit back in
   6265  1.1        is 	roxr.w		FTEMP_HI+2(%a0)		# shift v-bit back in
   6266  1.1        is 	add.w		&0x1, FTEMP_EX(%a0)	# and incr exponent
   6267  1.1        is scc_clr:
   6268  1.1        is 	tst.l		%d0			# test for rs = 0
   6269  1.1        is 	bne.b		sgl_done
   6270  1.1        is 	and.w		&0xfe00, FTEMP_HI+2(%a0) # clear the l-bit
   6271  1.1        is sgl_done:
   6272  1.1        is 	and.l		&0xffffff00, FTEMP_HI(%a0) # truncate bits beyond sgl limit
   6273  1.1        is 	clr.l		FTEMP_LO(%a0)		# clear d2
   6274  1.1        is 	rts
   6275  1.1        is 
   6276  1.1        is #########################
   6277  1.1        is #	ADD EXTENDED	#
   6278  1.1        is #########################
   6279  1.1        is add_ext:
   6280  1.1        is 	addq.l		&1,FTEMP_LO(%a0)	# add 1 to l-bit
   6281  1.1        is 	bcc.b		xcc_clr			# test for carry out
   6282  1.1        is 	addq.l		&1,FTEMP_HI(%a0)	# propogate carry
   6283  1.1        is 	bcc.b		xcc_clr
   6284  1.1        is 	roxr.w		FTEMP_HI(%a0)		# mant is 0 so restore v-bit
   6285  1.1        is 	roxr.w		FTEMP_HI+2(%a0)		# mant is 0 so restore v-bit
   6286  1.1        is 	roxr.w		FTEMP_LO(%a0)
   6287  1.1        is 	roxr.w		FTEMP_LO+2(%a0)
   6288  1.1        is 	add.w		&0x1,FTEMP_EX(%a0)	# and inc exp
   6289  1.1        is xcc_clr:
   6290  1.1        is 	tst.l		%d0			# test rs = 0
   6291  1.1        is 	bne.b		add_ext_done
   6292  1.1        is 	and.b		&0xfe,FTEMP_LO+3(%a0)	# clear the l bit
   6293  1.1        is add_ext_done:
   6294  1.1        is 	rts
   6295  1.1        is 
   6296  1.1        is #########################
   6297  1.1        is #	ADD DOUBLE	#
   6298  1.1        is #########################
   6299  1.1        is add_dbl:
   6300  1.1        is 	add.l		&ad_1_dbl, FTEMP_LO(%a0) # add 1 to lsb
   6301  1.1        is 	bcc.b		dcc_clr			# no carry
   6302  1.1        is 	addq.l		&0x1, FTEMP_HI(%a0)	# propogate carry
   6303  1.1        is 	bcc.b		dcc_clr			# no carry
   6304  1.1        is 
   6305  1.1        is 	roxr.w		FTEMP_HI(%a0)		# mant is 0 so restore v-bit
   6306  1.1        is 	roxr.w		FTEMP_HI+2(%a0)		# mant is 0 so restore v-bit
   6307  1.1        is 	roxr.w		FTEMP_LO(%a0)
   6308  1.1        is 	roxr.w		FTEMP_LO+2(%a0)
   6309  1.1        is 	addq.w		&0x1, FTEMP_EX(%a0)	# incr exponent
   6310  1.1        is dcc_clr:
   6311  1.1        is 	tst.l		%d0			# test for rs = 0
   6312  1.1        is 	bne.b		dbl_done
   6313  1.1        is 	and.w		&0xf000, FTEMP_LO+2(%a0) # clear the l-bit
   6314  1.1        is 
   6315  1.1        is dbl_done:
   6316  1.1        is 	and.l		&0xfffff800,FTEMP_LO(%a0) # truncate bits beyond dbl limit
   6317  1.1        is 	rts
   6318  1.1        is 
   6319  1.1        is ###########################
   6320  1.1        is # Truncate all other bits #
   6321  1.1        is ###########################
   6322  1.1        is truncate:
   6323  1.1        is 	swap		%d1			# select rnd prec
   6324  1.1        is 
   6325  1.1        is 	cmpi.b		%d1, &s_mode		# is prec sgl?
   6326  1.1        is 	beq.w		sgl_done		# yes
   6327  1.1        is 	bgt.b		dbl_done		# no; it's dbl
   6328  1.1        is 	rts					# no; it's ext
   6329  1.1        is 
   6330  1.1        is 
   6331  1.1        is #
   6332  1.1        is # ext_grs(): extract guard, round and sticky bits according to
   6333  1.1        is #	     rounding precision.
   6334  1.1        is #
   6335  1.1        is # INPUT
   6336  1.1        is #	d0	   = extended precision g,r,s (in d0{31:29})
   6337  1.1        is #	d1 	   = {PREC,ROUND}
   6338  1.1        is # OUTPUT
   6339  1.1        is #	d0{31:29}  = guard, round, sticky
   6340  1.1        is #
   6341  1.1        is # The ext_grs extract the guard/round/sticky bits according to the
   6342  1.1        is # selected rounding precision. It is called by the round subroutine
   6343  1.1        is # only.  All registers except d0 are kept intact. d0 becomes an
   6344  1.1        is # updated guard,round,sticky in d0{31:29}
   6345  1.1        is #
   6346  1.1        is # Notes: the ext_grs uses the round PREC, and therefore has to swap d1
   6347  1.1        is #	 prior to usage, and needs to restore d1 to original. this
   6348  1.1        is #	 routine is tightly tied to the round routine and not meant to
   6349  1.1        is #	 uphold standard subroutine calling practices.
   6350  1.1        is #
   6351  1.1        is 
   6352  1.1        is ext_grs:
   6353  1.1        is 	swap		%d1			# have d1.w point to round precision
   6354  1.1        is 	tst.b		%d1			# is rnd prec = extended?
   6355  1.1        is 	bne.b		ext_grs_not_ext		# no; go handle sgl or dbl
   6356  1.1        is 
   6357  1.1        is #
   6358  1.1        is # %d0 actually already hold g,r,s since _round() had it before calling
   6359  1.1        is # this function. so, as long as we don't disturb it, we are "returning" it.
   6360  1.1        is #
   6361  1.1        is ext_grs_ext:
   6362  1.1        is 	swap		%d1			# yes; return to correct positions
   6363  1.1        is 	rts
   6364  1.1        is 
   6365  1.1        is ext_grs_not_ext:
   6366  1.1        is 	movm.l		&0x3000, -(%sp)		# make some temp registers {d2/d3}
   6367  1.1        is 
   6368  1.1        is 	cmpi.b		%d1, &s_mode		# is rnd prec = sgl?
   6369  1.1        is 	bne.b		ext_grs_dbl		# no; go handle dbl
   6370  1.1        is 
   6371  1.1        is #
   6372  1.1        is # sgl:
   6373  1.1        is #	96		64	  40	32		0
   6374  1.1        is #	-----------------------------------------------------
   6375  1.1        is #	| EXP	|XXXXXXX|	  |xx	|		|grs|
   6376  1.1        is #	-----------------------------------------------------
   6377  1.1        is #			<--(24)--->nn\			   /
   6378  1.1        is #				   ee ---------------------
   6379  1.1        is #				   ww		|
   6380  1.1        is #						v
   6381  1.1        is #				   gr	   new sticky
   6382  1.1        is #
   6383  1.1        is ext_grs_sgl:
   6384  1.1        is 	bfextu		FTEMP_HI(%a0){&24:&2}, %d3 # sgl prec. g-r are 2 bits right
   6385  1.1        is 	mov.l		&30, %d2		# of the sgl prec. limits
   6386  1.1        is 	lsl.l		%d2, %d3		# shift g-r bits to MSB of d3
   6387  1.1        is 	mov.l		FTEMP_HI(%a0), %d2	# get word 2 for s-bit test
   6388  1.1        is 	and.l		&0x0000003f, %d2	# s bit is the or of all other
   6389  1.1        is 	bne.b		ext_grs_st_stky		# bits to the right of g-r
   6390  1.1        is 	tst.l		FTEMP_LO(%a0)		# test lower mantissa
   6391  1.1        is 	bne.b		ext_grs_st_stky		# if any are set, set sticky
   6392  1.1        is 	tst.l		%d0			# test original g,r,s
   6393  1.1        is 	bne.b		ext_grs_st_stky		# if any are set, set sticky
   6394  1.1        is 	bra.b		ext_grs_end_sd		# if words 3 and 4 are clr, exit
   6395  1.1        is 
   6396  1.1        is #
   6397  1.1        is # dbl:
   6398  1.1        is #	96		64	  	32	 11	0
   6399  1.1        is #	-----------------------------------------------------
   6400  1.1        is #	| EXP	|XXXXXXX|	  	|	 |xx	|grs|
   6401  1.1        is #	-----------------------------------------------------
   6402  1.1        is #						  nn\	    /
   6403  1.1        is #						  ee -------
   6404  1.1        is #						  ww	|
   6405  1.1        is #							v
   6406  1.1        is #						  gr	new sticky
   6407  1.1        is #
   6408  1.1        is ext_grs_dbl:
   6409  1.1        is 	bfextu		FTEMP_LO(%a0){&21:&2}, %d3 # dbl-prec. g-r are 2 bits right
   6410  1.1        is 	mov.l		&30, %d2		# of the dbl prec. limits
   6411  1.1        is 	lsl.l		%d2, %d3		# shift g-r bits to the MSB of d3
   6412  1.1        is 	mov.l		FTEMP_LO(%a0), %d2	# get lower mantissa  for s-bit test
   6413  1.1        is 	and.l		&0x000001ff, %d2	# s bit is the or-ing of all
   6414  1.1        is 	bne.b		ext_grs_st_stky		# other bits to the right of g-r
   6415  1.1        is 	tst.l		%d0			# test word original g,r,s
   6416  1.1        is 	bne.b		ext_grs_st_stky		# if any are set, set sticky
   6417  1.1        is 	bra.b		ext_grs_end_sd		# if clear, exit
   6418  1.1        is 
   6419  1.1        is ext_grs_st_stky:
   6420  1.1        is 	bset		&rnd_stky_bit, %d3	# set sticky bit
   6421  1.1        is ext_grs_end_sd:
   6422  1.1        is 	mov.l		%d3, %d0		# return grs to d0
   6423  1.1        is 
   6424  1.1        is 	movm.l		(%sp)+, &0xc		# restore scratch registers {d2/d3}
   6425  1.1        is 
   6426  1.1        is 	swap		%d1			# restore d1 to original
   6427  1.1        is 	rts
   6428  1.1        is 
   6429  1.1        is #########################################################################
   6430  1.1        is # norm(): normalize the mantissa of an extended precision input. the	#
   6431  1.1        is #	  input operand should not be normalized already.		#
   6432  1.1        is #									#
   6433  1.1        is # XDEF ****************************************************************	#
   6434  1.1        is #	norm()								#
   6435  1.1        is #									#
   6436  1.1        is # XREF **************************************************************** #
   6437  1.1        is #	none								#
   6438  1.1        is #									#
   6439  1.1        is # INPUT *************************************************************** #
   6440  1.1        is #	a0 = pointer fp extended precision operand to normalize		#
   6441  1.1        is #									#
   6442  1.1        is # OUTPUT ************************************************************** #
   6443  1.1        is # 	d0 = number of bit positions the mantissa was shifted		#
   6444  1.1        is #	a0 = the input operand's mantissa is normalized; the exponent	#
   6445  1.1        is #	     is unchanged.						#
   6446  1.1        is #									#
   6447  1.1        is #########################################################################
   6448  1.1        is 	global		norm
   6449  1.1        is norm:
   6450  1.1        is 	mov.l		%d2, -(%sp)		# create some temp regs
   6451  1.1        is 	mov.l		%d3, -(%sp)
   6452  1.1        is 
   6453  1.1        is 	mov.l		FTEMP_HI(%a0), %d0	# load hi(mantissa)
   6454  1.1        is 	mov.l		FTEMP_LO(%a0), %d1	# load lo(mantissa)
   6455  1.1        is 
   6456  1.1        is 	bfffo		%d0{&0:&32}, %d2	# how many places to shift?
   6457  1.1        is 	beq.b		norm_lo			# hi(man) is all zeroes!
   6458  1.1        is 
   6459  1.1        is norm_hi:
   6460  1.1        is 	lsl.l		%d2, %d0		# left shift hi(man)
   6461  1.1        is 	bfextu		%d1{&0:%d2}, %d3	# extract lo bits
   6462  1.1        is 
   6463  1.1        is 	or.l		%d3, %d0		# create hi(man)
   6464  1.1        is 	lsl.l		%d2, %d1		# create lo(man)
   6465  1.1        is 
   6466  1.1        is 	mov.l		%d0, FTEMP_HI(%a0)	# store new hi(man)
   6467  1.1        is 	mov.l		%d1, FTEMP_LO(%a0)	# store new lo(man)
   6468  1.1        is 
   6469  1.1        is 	mov.l		%d2, %d0		# return shift amount
   6470  1.1        is 
   6471  1.1        is 	mov.l		(%sp)+, %d3		# restore temp regs
   6472  1.1        is 	mov.l		(%sp)+, %d2
   6473  1.1        is 
   6474  1.1        is 	rts
   6475  1.1        is 
   6476  1.1        is norm_lo:
   6477  1.1        is 	bfffo		%d1{&0:&32}, %d2	# how many places to shift?
   6478  1.1        is 	lsl.l		%d2, %d1		# shift lo(man)
   6479  1.1        is 	add.l		&32, %d2		# add 32 to shft amount
   6480  1.1        is 
   6481  1.1        is 	mov.l		%d1, FTEMP_HI(%a0)	# store hi(man)
   6482  1.1        is 	clr.l		FTEMP_LO(%a0)		# lo(man) is now zero
   6483  1.1        is 
   6484  1.1        is 	mov.l		%d2, %d0		# return shift amount
   6485  1.1        is 
   6486  1.1        is 	mov.l		(%sp)+, %d3		# restore temp regs
   6487  1.1        is 	mov.l		(%sp)+, %d2
   6488  1.1        is 
   6489  1.1        is 	rts
   6490  1.1        is 
   6491  1.1        is #########################################################################
   6492  1.1        is # unnorm_fix(): - changes an UNNORM to one of NORM, DENORM, or ZERO	#
   6493  1.1        is #		- returns corresponding optype tag			#
   6494  1.1        is #									#
   6495  1.1        is # XDEF ****************************************************************	#
   6496  1.1        is #	unnorm_fix()							#
   6497  1.1        is #									#
   6498  1.1        is # XREF **************************************************************** #
   6499  1.1        is #	norm() - normalize the mantissa					#
   6500  1.1        is #									#
   6501  1.1        is # INPUT *************************************************************** #
   6502  1.1        is #	a0 = pointer to unnormalized extended precision number		#
   6503  1.1        is #									#
   6504  1.1        is # OUTPUT ************************************************************** #
   6505  1.1        is #	d0 = optype tag - is corrected to one of NORM, DENORM, or ZERO	#
   6506  1.1        is #	a0 = input operand has been converted to a norm, denorm, or	#
   6507  1.1        is #	     zero; both the exponent and mantissa are changed.		#
   6508  1.1        is #									#
   6509  1.1        is #########################################################################
   6510  1.1        is 
   6511  1.1        is 	global		unnorm_fix
   6512  1.1        is unnorm_fix:
   6513  1.1        is 	bfffo		FTEMP_HI(%a0){&0:&32}, %d0 # how many shifts are needed?
   6514  1.1        is 	bne.b		unnorm_shift		# hi(man) is not all zeroes
   6515  1.1        is 
   6516  1.1        is #
   6517  1.1        is # hi(man) is all zeroes so see if any bits in lo(man) are set
   6518  1.1        is #
   6519  1.1        is unnorm_chk_lo:
   6520  1.1        is 	bfffo		FTEMP_LO(%a0){&0:&32}, %d0 # is operand really a zero?
   6521  1.1        is 	beq.w		unnorm_zero		# yes
   6522  1.1        is 
   6523  1.1        is 	add.w		&32, %d0		# no; fix shift distance
   6524  1.1        is 
   6525  1.1        is #
   6526  1.1        is # d0 = # shifts needed for complete normalization
   6527  1.1        is #
   6528  1.1        is unnorm_shift:
   6529  1.1        is 	clr.l		%d1			# clear top word
   6530  1.1        is 	mov.w		FTEMP_EX(%a0), %d1	# extract exponent
   6531  1.1        is 	and.w		&0x7fff, %d1		# strip off sgn
   6532  1.1        is 
   6533  1.1        is 	cmp.w		%d0, %d1		# will denorm push exp < 0?
   6534  1.1        is 	bgt.b		unnorm_nrm_zero		# yes; denorm only until exp = 0
   6535  1.1        is 
   6536  1.1        is #
   6537  1.1        is # exponent would not go < 0. therefore, number stays normalized
   6538  1.1        is #
   6539  1.1        is 	sub.w		%d0, %d1		# shift exponent value
   6540  1.1        is 	mov.w		FTEMP_EX(%a0), %d0	# load old exponent
   6541  1.1        is 	and.w		&0x8000, %d0		# save old sign
   6542  1.1        is 	or.w		%d0, %d1		# {sgn,new exp}
   6543  1.1        is 	mov.w		%d1, FTEMP_EX(%a0)	# insert new exponent
   6544  1.1        is 
   6545  1.1        is 	bsr.l		norm			# normalize UNNORM
   6546  1.1        is 
   6547  1.1        is 	mov.b		&NORM, %d0		# return new optype tag
   6548  1.1        is 	rts
   6549  1.1        is 
   6550  1.1        is #
   6551  1.1        is # exponent would go < 0, so only denormalize until exp = 0
   6552  1.1        is #
   6553  1.1        is unnorm_nrm_zero:
   6554  1.1        is 	cmp.b		%d1, &32		# is exp <= 32?
   6555  1.1        is 	bgt.b		unnorm_nrm_zero_lrg	# no; go handle large exponent
   6556  1.1        is 
   6557  1.1        is 	bfextu		FTEMP_HI(%a0){%d1:&32}, %d0 # extract new hi(man)
   6558  1.1        is 	mov.l		%d0, FTEMP_HI(%a0)	# save new hi(man)
   6559  1.1        is 
   6560  1.1        is 	mov.l		FTEMP_LO(%a0), %d0	# fetch old lo(man)
   6561  1.1        is 	lsl.l		%d1, %d0		# extract new lo(man)
   6562  1.1        is 	mov.l		%d0, FTEMP_LO(%a0)	# save new lo(man)
   6563  1.1        is 
   6564  1.1        is 	and.w		&0x8000, FTEMP_EX(%a0)	# set exp = 0
   6565  1.1        is 
   6566  1.1        is 	mov.b		&DENORM, %d0		# return new optype tag
   6567  1.1        is 	rts
   6568  1.1        is 
   6569  1.1        is #
   6570  1.1        is # only mantissa bits set are in lo(man)
   6571  1.1        is #
   6572  1.1        is unnorm_nrm_zero_lrg:
   6573  1.1        is 	sub.w		&32, %d1		# adjust shft amt by 32
   6574  1.1        is 
   6575  1.1        is 	mov.l		FTEMP_LO(%a0), %d0	# fetch old lo(man)
   6576  1.1        is 	lsl.l		%d1, %d0		# left shift lo(man)
   6577  1.1        is 
   6578  1.1        is 	mov.l		%d0, FTEMP_HI(%a0)	# store new hi(man)
   6579  1.1        is 	clr.l		FTEMP_LO(%a0)		# lo(man) = 0
   6580  1.1        is 
   6581  1.1        is 	and.w		&0x8000, FTEMP_EX(%a0)	# set exp = 0
   6582  1.1        is 
   6583  1.1        is 	mov.b		&DENORM, %d0		# return new optype tag
   6584  1.1        is 	rts
   6585  1.1        is 
   6586  1.1        is #
   6587  1.1        is # whole mantissa is zero so this UNNORM is actually a zero
   6588  1.1        is #
   6589  1.1        is unnorm_zero:
   6590  1.1        is 	and.w		&0x8000, FTEMP_EX(%a0) 	# force exponent to zero
   6591  1.1        is 
   6592  1.1        is 	mov.b		&ZERO, %d0		# fix optype tag
   6593  1.1        is 	rts
   6594  1.1        is 
   6595  1.1        is #########################################################################
   6596  1.1        is # XDEF ****************************************************************	#
   6597  1.1        is # 	set_tag_x(): return the optype of the input ext fp number	#
   6598  1.1        is #									#
   6599  1.1        is # XREF ****************************************************************	#
   6600  1.1        is #	None								#
   6601  1.1        is #									#
   6602  1.1        is # INPUT ***************************************************************	#
   6603  1.1        is #	a0 = pointer to extended precision operand			#
   6604  1.1        is # 									#
   6605  1.1        is # OUTPUT **************************************************************	#
   6606  1.1        is #	d0 = value of type tag						#
   6607  1.1        is # 		one of: NORM, INF, QNAN, SNAN, DENORM, UNNORM, ZERO	#
   6608  1.1        is #									#
   6609  1.1        is # ALGORITHM ***********************************************************	#
   6610  1.1        is #	Simply test the exponent, j-bit, and mantissa values to 	#
   6611  1.1        is # determine the type of operand.					#
   6612  1.1        is #	If it's an unnormalized zero, alter the operand and force it	#
   6613  1.1        is # to be a normal zero.							#
   6614  1.1        is #									#
   6615  1.1        is #########################################################################
   6616  1.1        is 
   6617  1.1        is 	global		set_tag_x
   6618  1.1        is set_tag_x:
   6619  1.1        is 	mov.w		FTEMP_EX(%a0), %d0	# extract exponent
   6620  1.1        is 	andi.w		&0x7fff, %d0		# strip off sign
   6621  1.1        is 	cmpi.w		%d0, &0x7fff		# is (EXP == MAX)?
   6622  1.1        is 	beq.b		inf_or_nan_x
   6623  1.1        is not_inf_or_nan_x:
   6624  1.1        is 	btst		&0x7,FTEMP_HI(%a0)
   6625  1.1        is 	beq.b		not_norm_x
   6626  1.1        is is_norm_x:
   6627  1.1        is 	mov.b		&NORM, %d0
   6628  1.1        is 	rts
   6629  1.1        is not_norm_x:
   6630  1.1        is 	tst.w		%d0			# is exponent = 0?
   6631  1.1        is 	bne.b		is_unnorm_x
   6632  1.1        is not_unnorm_x:
   6633  1.1        is 	tst.l		FTEMP_HI(%a0)
   6634  1.1        is 	bne.b		is_denorm_x
   6635  1.1        is 	tst.l		FTEMP_LO(%a0)
   6636  1.1        is 	bne.b		is_denorm_x
   6637  1.1        is is_zero_x:
   6638  1.1        is 	mov.b		&ZERO, %d0
   6639  1.1        is 	rts
   6640  1.1        is is_denorm_x:
   6641  1.1        is 	mov.b		&DENORM, %d0
   6642  1.1        is 	rts
   6643  1.1        is # must distinguish now "Unnormalized zeroes" which we
   6644  1.1        is # must convert to zero.
   6645  1.1        is is_unnorm_x:
   6646  1.1        is 	tst.l		FTEMP_HI(%a0)
   6647  1.1        is 	bne.b		is_unnorm_reg_x
   6648  1.1        is 	tst.l		FTEMP_LO(%a0)
   6649  1.1        is 	bne.b		is_unnorm_reg_x
   6650  1.1        is # it's an "unnormalized zero". let's convert it to an actual zero...
   6651  1.1        is 	andi.w		&0x8000,FTEMP_EX(%a0)	# clear exponent
   6652  1.1        is 	mov.b		&ZERO, %d0
   6653  1.1        is 	rts
   6654  1.1        is is_unnorm_reg_x:
   6655  1.1        is 	mov.b		&UNNORM, %d0
   6656  1.1        is 	rts
   6657  1.1        is inf_or_nan_x:
   6658  1.1        is 	tst.l		FTEMP_LO(%a0)
   6659  1.1        is 	bne.b		is_nan_x
   6660  1.1        is 	mov.l		FTEMP_HI(%a0), %d0
   6661  1.1        is 	and.l		&0x7fffffff, %d0	# msb is a don't care!
   6662  1.1        is 	bne.b		is_nan_x
   6663  1.1        is is_inf_x:
   6664  1.1        is 	mov.b		&INF, %d0
   6665  1.1        is 	rts
   6666  1.1        is is_nan_x:
   6667  1.1        is 	btst		&0x6, FTEMP_HI(%a0)
   6668  1.1        is 	beq.b		is_snan_x
   6669  1.1        is 	mov.b		&QNAN, %d0
   6670  1.1        is 	rts
   6671  1.1        is is_snan_x:
   6672  1.1        is 	mov.b		&SNAN, %d0
   6673  1.1        is 	rts
   6674  1.1        is 
   6675  1.1        is #########################################################################
   6676  1.1        is # XDEF ****************************************************************	#
   6677  1.1        is # 	set_tag_d(): return the optype of the input dbl fp number	#
   6678  1.1        is #									#
   6679  1.1        is # XREF ****************************************************************	#
   6680  1.1        is #	None								#
   6681  1.1        is #									#
   6682  1.1        is # INPUT ***************************************************************	#
   6683  1.1        is #	a0 = points to double precision operand				#
   6684  1.1        is # 									#
   6685  1.1        is # OUTPUT **************************************************************	#
   6686  1.1        is #	d0 = value of type tag						#
   6687  1.1        is # 		one of: NORM, INF, QNAN, SNAN, DENORM, ZERO		#
   6688  1.1        is #									#
   6689  1.1        is # ALGORITHM ***********************************************************	#
   6690  1.1        is #	Simply test the exponent, j-bit, and mantissa values to 	#
   6691  1.1        is # determine the type of operand.					#
   6692  1.1        is #									#
   6693  1.1        is #########################################################################
   6694  1.1        is 
   6695  1.1        is 	global		set_tag_d
   6696  1.1        is set_tag_d:
   6697  1.1        is 	mov.l		FTEMP(%a0), %d0
   6698  1.1        is 	mov.l		%d0, %d1
   6699  1.1        is 
   6700  1.1        is 	andi.l		&0x7ff00000, %d0
   6701  1.1        is 	beq.b		zero_or_denorm_d
   6702  1.1        is 
   6703  1.1        is 	cmpi.l		%d0, &0x7ff00000
   6704  1.1        is 	beq.b		inf_or_nan_d
   6705  1.1        is 
   6706  1.1        is is_norm_d:
   6707  1.1        is 	mov.b		&NORM, %d0
   6708  1.1        is 	rts
   6709  1.1        is zero_or_denorm_d:
   6710  1.1        is 	and.l		&0x000fffff, %d1
   6711  1.1        is 	bne		is_denorm_d
   6712  1.1        is 	tst.l		4+FTEMP(%a0)
   6713  1.1        is 	bne		is_denorm_d
   6714  1.1        is is_zero_d:
   6715  1.1        is 	mov.b		&ZERO, %d0
   6716  1.1        is 	rts
   6717  1.1        is is_denorm_d:
   6718  1.1        is 	mov.b		&DENORM, %d0
   6719  1.1        is 	rts
   6720  1.1        is inf_or_nan_d:
   6721  1.1        is 	and.l		&0x000fffff, %d1
   6722  1.1        is 	bne		is_nan_d
   6723  1.1        is 	tst.l		4+FTEMP(%a0)
   6724  1.1        is 	bne		is_nan_d
   6725  1.1        is is_inf_d:
   6726  1.1        is 	mov.b		&INF, %d0
   6727  1.1        is 	rts
   6728  1.1        is is_nan_d:
   6729  1.1        is 	btst		&19, %d1
   6730  1.1        is 	bne		is_qnan_d
   6731  1.1        is is_snan_d:
   6732  1.1        is 	mov.b		&SNAN, %d0
   6733  1.1        is 	rts
   6734  1.1        is is_qnan_d:
   6735  1.1        is 	mov.b		&QNAN, %d0
   6736  1.1        is 	rts
   6737  1.1        is 
   6738  1.1        is #########################################################################
   6739  1.1        is # XDEF ****************************************************************	#
   6740  1.1        is # 	set_tag_s(): return the optype of the input sgl fp number	#
   6741  1.1        is #									#
   6742  1.1        is # XREF ****************************************************************	#
   6743  1.1        is #	None								#
   6744  1.1        is #									#
   6745  1.1        is # INPUT ***************************************************************	#
   6746  1.1        is #	a0 = pointer to single precision operand			#
   6747  1.1        is # 									#
   6748  1.1        is # OUTPUT **************************************************************	#
   6749  1.1        is #	d0 = value of type tag						#
   6750  1.1        is # 		one of: NORM, INF, QNAN, SNAN, DENORM, ZERO		#
   6751  1.1        is #									#
   6752  1.1        is # ALGORITHM ***********************************************************	#
   6753  1.1        is #	Simply test the exponent, j-bit, and mantissa values to 	#
   6754  1.1        is # determine the type of operand.					#
   6755  1.1        is #									#
   6756  1.1        is #########################################################################
   6757  1.1        is 
   6758  1.1        is 	global		set_tag_s
   6759  1.1        is set_tag_s:
   6760  1.1        is 	mov.l		FTEMP(%a0), %d0
   6761  1.1        is 	mov.l		%d0, %d1
   6762  1.1        is 
   6763  1.1        is 	andi.l		&0x7f800000, %d0
   6764  1.1        is 	beq.b		zero_or_denorm_s
   6765  1.1        is 
   6766  1.1        is 	cmpi.l		%d0, &0x7f800000
   6767  1.1        is 	beq.b		inf_or_nan_s
   6768  1.1        is 
   6769  1.1        is is_norm_s:
   6770  1.1        is 	mov.b		&NORM, %d0
   6771  1.1        is 	rts
   6772  1.1        is zero_or_denorm_s:
   6773  1.1        is 	and.l		&0x007fffff, %d1
   6774  1.1        is 	bne		is_denorm_s
   6775  1.1        is is_zero_s:
   6776  1.1        is 	mov.b		&ZERO, %d0
   6777  1.1        is 	rts
   6778  1.1        is is_denorm_s:
   6779  1.1        is 	mov.b		&DENORM, %d0
   6780  1.1        is 	rts
   6781  1.1        is inf_or_nan_s:
   6782  1.1        is 	and.l		&0x007fffff, %d1
   6783  1.1        is 	bne		is_nan_s
   6784  1.1        is is_inf_s:
   6785  1.1        is 	mov.b		&INF, %d0
   6786  1.1        is 	rts
   6787  1.1        is is_nan_s:
   6788  1.1        is 	btst		&22, %d1
   6789  1.1        is 	bne		is_qnan_s
   6790  1.1        is is_snan_s:
   6791  1.1        is 	mov.b		&SNAN, %d0
   6792  1.1        is 	rts
   6793  1.1        is is_qnan_s:
   6794  1.1        is 	mov.b		&QNAN, %d0
   6795  1.1        is 	rts
   6796  1.1        is 
   6797  1.1        is #########################################################################
   6798  1.1        is # XDEF ****************************************************************	#
   6799  1.1        is # 	unf_res(): routine to produce default underflow result of a 	#
   6800  1.1        is #	 	   scaled extended precision number; this is used by 	#
   6801  1.1        is #		   fadd/fdiv/fmul/etc. emulation routines.		#
   6802  1.1        is # 	unf_res4(): same as above but for fsglmul/fsgldiv which use	#
   6803  1.1        is #		    single round prec and extended prec mode.		#
   6804  1.1        is #									#
   6805  1.1        is # XREF ****************************************************************	#
   6806  1.1        is #	_denorm() - denormalize according to scale factor		#
   6807  1.1        is # 	_round() - round denormalized number according to rnd prec	#
   6808  1.1        is #									#
   6809  1.1        is # INPUT ***************************************************************	#
   6810  1.1        is #	a0 = pointer to extended precison operand			#
   6811  1.1        is #	d0 = scale factor						#
   6812  1.1        is #	d1 = rounding precision/mode					#
   6813  1.1        is #									#
   6814  1.1        is # OUTPUT **************************************************************	#
   6815  1.1        is #	a0 = pointer to default underflow result in extended precision	#
   6816  1.1        is #	d0.b = result FPSR_cc which caller may or may not want to save	#
   6817  1.1        is #									#
   6818  1.1        is # ALGORITHM ***********************************************************	#
   6819  1.1        is # 	Convert the input operand to "internal format" which means the	#
   6820  1.1        is # exponent is extended to 16 bits and the sign is stored in the unused	#
   6821  1.1        is # portion of the extended precison operand. Denormalize the number	#
   6822  1.1        is # according to the scale factor passed in d0. Then, round the 		#
   6823  1.1        is # denormalized result.							#
   6824  1.1        is # 	Set the FPSR_exc bits as appropriate but return the cc bits in	#
   6825  1.1        is # d0 in case the caller doesn't want to save them (as is the case for	#
   6826  1.1        is # fmove out).								#
   6827  1.1        is # 	unf_res4() for fsglmul/fsgldiv forces the denorm to extended	#
   6828  1.1        is # precision and the rounding mode to single.				#
   6829  1.1        is #									#
   6830  1.1        is #########################################################################
   6831  1.1        is 	global		unf_res
   6832  1.1        is unf_res:
   6833  1.1        is 	mov.l		%d1, -(%sp)		# save rnd prec,mode on stack
   6834  1.1        is 
   6835  1.1        is 	btst		&0x7, FTEMP_EX(%a0)	# make "internal" format
   6836  1.1        is 	sne		FTEMP_SGN(%a0)
   6837  1.1        is 
   6838  1.1        is 	mov.w		FTEMP_EX(%a0), %d1	# extract exponent
   6839  1.1        is 	and.w		&0x7fff, %d1
   6840  1.1        is 	sub.w		%d0, %d1
   6841  1.1        is 	mov.w		%d1, FTEMP_EX(%a0)	# insert 16 bit exponent
   6842  1.1        is 
   6843  1.1        is 	mov.l		%a0, -(%sp)		# save operand ptr during calls
   6844  1.1        is 
   6845  1.1        is 	mov.l		0x4(%sp),%d0		# pass rnd prec.
   6846  1.1        is 	andi.w		&0x00c0,%d0
   6847  1.1        is 	lsr.w		&0x4,%d0
   6848  1.1        is 	bsr.l		_denorm			# denorm result
   6849  1.1        is 
   6850  1.1        is 	mov.l		(%sp),%a0
   6851  1.1        is 	mov.w		0x6(%sp),%d1		# load prec:mode into %d1
   6852  1.1        is 	andi.w		&0xc0,%d1		# extract rnd prec
   6853  1.1        is 	lsr.w		&0x4,%d1
   6854  1.1        is 	swap		%d1
   6855  1.1        is 	mov.w		0x6(%sp),%d1
   6856  1.1        is 	andi.w		&0x30,%d1
   6857  1.1        is 	lsr.w		&0x4,%d1
   6858  1.1        is 	bsr.l		_round			# round the denorm
   6859  1.1        is 
   6860  1.1        is 	mov.l		(%sp)+, %a0
   6861  1.1        is 
   6862  1.1        is # result is now rounded properly. convert back to normal format
   6863  1.1        is 	bclr		&0x7, FTEMP_EX(%a0)	# clear sgn first; may have residue
   6864  1.1        is 	tst.b		FTEMP_SGN(%a0)		# is "internal result" sign set?
   6865  1.1        is 	beq.b		unf_res_chkifzero	# no; result is positive
   6866  1.1        is 	bset		&0x7, FTEMP_EX(%a0)	# set result sgn
   6867  1.1        is 	clr.b		FTEMP_SGN(%a0)		# clear temp sign
   6868  1.1        is 
   6869  1.1        is # the number may have become zero after rounding. set ccodes accordingly.
   6870  1.1        is unf_res_chkifzero:
   6871  1.1        is 	clr.l		%d0
   6872  1.1        is 	tst.l		FTEMP_HI(%a0)		# is value now a zero?
   6873  1.1        is 	bne.b		unf_res_cont		# no
   6874  1.1        is 	tst.l		FTEMP_LO(%a0)
   6875  1.1        is 	bne.b		unf_res_cont		# no
   6876  1.1        is #	bset		&z_bit, FPSR_CC(%a6)	# yes; set zero ccode bit
   6877  1.1        is 	bset		&z_bit, %d0		# yes; set zero ccode bit
   6878  1.1        is 
   6879  1.1        is unf_res_cont:
   6880  1.1        is 
   6881  1.1        is #
   6882  1.1        is # can inex1 also be set along with unfl and inex2???
   6883  1.1        is #
   6884  1.1        is # we know that underflow has occurred. aunfl should be set if INEX2 is also set.
   6885  1.1        is #
   6886  1.1        is 	btst		&inex2_bit, FPSR_EXCEPT(%a6) # is INEX2 set?
   6887  1.1        is 	beq.b		unf_res_end		# no
   6888  1.1        is 	bset		&aunfl_bit, FPSR_AEXCEPT(%a6) # yes; set aunfl
   6889  1.1        is 
   6890  1.1        is unf_res_end:
   6891  1.1        is 	add.l		&0x4, %sp		# clear stack
   6892  1.1        is 	rts
   6893  1.1        is 
   6894  1.1        is # unf_res() for fsglmul() and fsgldiv().
   6895  1.1        is 	global		unf_res4
   6896  1.1        is unf_res4:
   6897  1.1        is 	mov.l		%d1,-(%sp)		# save rnd prec,mode on stack
   6898  1.1        is 
   6899  1.1        is 	btst		&0x7,FTEMP_EX(%a0)	# make "internal" format
   6900  1.1        is 	sne		FTEMP_SGN(%a0)
   6901  1.1        is 
   6902  1.1        is 	mov.w		FTEMP_EX(%a0),%d1	# extract exponent
   6903  1.1        is 	and.w		&0x7fff,%d1
   6904  1.1        is 	sub.w		%d0,%d1
   6905  1.1        is 	mov.w		%d1,FTEMP_EX(%a0)	# insert 16 bit exponent
   6906  1.1        is 
   6907  1.1        is 	mov.l		%a0,-(%sp)		# save operand ptr during calls
   6908  1.1        is 
   6909  1.1        is 	clr.l		%d0			# force rnd prec = ext
   6910  1.1        is 	bsr.l		_denorm			# denorm result
   6911  1.1        is 
   6912  1.1        is 	mov.l		(%sp),%a0
   6913  1.1        is 	mov.w		&s_mode,%d1		# force rnd prec = sgl
   6914  1.1        is 	swap		%d1
   6915  1.1        is 	mov.w		0x6(%sp),%d1		# load rnd mode
   6916  1.1        is 	andi.w		&0x30,%d1		# extract rnd prec
   6917  1.1        is 	lsr.w		&0x4,%d1
   6918  1.1        is 	bsr.l		_round			# round the denorm
   6919  1.1        is 
   6920  1.1        is 	mov.l		(%sp)+,%a0
   6921  1.1        is 
   6922  1.1        is # result is now rounded properly. convert back to normal format
   6923  1.1        is 	bclr		&0x7,FTEMP_EX(%a0)	# clear sgn first; may have residue
   6924  1.1        is 	tst.b		FTEMP_SGN(%a0)		# is "internal result" sign set?
   6925  1.1        is 	beq.b		unf_res4_chkifzero	# no; result is positive
   6926  1.1        is 	bset		&0x7,FTEMP_EX(%a0)	# set result sgn
   6927  1.1        is 	clr.b		FTEMP_SGN(%a0)		# clear temp sign
   6928  1.1        is 
   6929  1.1        is # the number may have become zero after rounding. set ccodes accordingly.
   6930  1.1        is unf_res4_chkifzero:
   6931  1.1        is 	clr.l		%d0
   6932  1.1        is 	tst.l		FTEMP_HI(%a0)		# is value now a zero?
   6933  1.1        is 	bne.b		unf_res4_cont		# no
   6934  1.1        is 	tst.l		FTEMP_LO(%a0)
   6935  1.1        is 	bne.b		unf_res4_cont		# no
   6936  1.1        is #	bset		&z_bit,FPSR_CC(%a6)	# yes; set zero ccode bit
   6937  1.1        is 	bset		&z_bit,%d0		# yes; set zero ccode bit
   6938  1.1        is 
   6939  1.1        is unf_res4_cont:
   6940  1.1        is 
   6941  1.1        is #
   6942  1.1        is # can inex1 also be set along with unfl and inex2???
   6943  1.1        is #
   6944  1.1        is # we know that underflow has occurred. aunfl should be set if INEX2 is also set.
   6945  1.1        is #
   6946  1.1        is 	btst		&inex2_bit,FPSR_EXCEPT(%a6) # is INEX2 set?
   6947  1.1        is 	beq.b		unf_res4_end		# no
   6948  1.1        is 	bset		&aunfl_bit,FPSR_AEXCEPT(%a6) # yes; set aunfl
   6949  1.1        is 
   6950  1.1        is unf_res4_end:
   6951  1.1        is 	add.l		&0x4,%sp		# clear stack
   6952  1.1        is 	rts
   6953  1.1        is 
   6954  1.1        is #########################################################################
   6955  1.1        is # XDEF ****************************************************************	#
   6956  1.1        is #	ovf_res(): routine to produce the default overflow result of	#
   6957  1.1        is #		   an overflowing number.				#
   6958  1.1        is #	ovf_res2(): same as above but the rnd mode/prec are passed	#
   6959  1.1        is #		    differently.					#
   6960  1.1        is #									#
   6961  1.1        is # XREF ****************************************************************	#
   6962  1.1        is #	none								#
   6963  1.1        is #									#
   6964  1.1        is # INPUT ***************************************************************	#
   6965  1.1        is #	d1.b 	= '-1' => (-); '0' => (+)				#
   6966  1.1        is #   ovf_res():								#
   6967  1.1        is #	d0 	= rnd mode/prec						#
   6968  1.1        is #   ovf_res2():								#
   6969  1.1        is #	hi(d0) 	= rnd prec						#
   6970  1.1        is #	lo(d0)	= rnd mode						#
   6971  1.1        is #									#
   6972  1.1        is # OUTPUT **************************************************************	#
   6973  1.1        is #	a0   	= points to extended precision result			#
   6974  1.1        is #	d0.b 	= condition code bits					#
   6975  1.1        is #									#
   6976  1.1        is # ALGORITHM ***********************************************************	#
   6977  1.1        is #	The default overflow result can be determined by the sign of	#
   6978  1.1        is # the result and the rounding mode/prec in effect. These bits are	#
   6979  1.1        is # concatenated together to create an index into the default result 	#
   6980  1.1        is # table. A pointer to the correct result is returned in a0. The		#
   6981  1.1        is # resulting condition codes are returned in d0 in case the caller 	#
   6982  1.1        is # doesn't want FPSR_cc altered (as is the case for fmove out).		#
   6983  1.1        is #									#
   6984  1.1        is #########################################################################
   6985  1.1        is 
   6986  1.1        is 	global		ovf_res
   6987  1.1        is ovf_res:
   6988  1.1        is 	andi.w		&0x10,%d1		# keep result sign
   6989  1.1        is 	lsr.b		&0x4,%d0		# shift prec/mode
   6990  1.1        is 	or.b		%d0,%d1			# concat the two
   6991  1.1        is 	mov.w		%d1,%d0			# make a copy
   6992  1.1        is 	lsl.b		&0x1,%d1		# multiply d1 by 2
   6993  1.1        is 	bra.b		ovf_res_load
   6994  1.1        is 
   6995  1.1        is 	global		ovf_res2
   6996  1.1        is ovf_res2:
   6997  1.1        is 	and.w		&0x10, %d1		# keep result sign
   6998  1.1        is 	or.b		%d0, %d1		# insert rnd mode
   6999  1.1        is 	swap		%d0
   7000  1.1        is 	or.b		%d0, %d1		# insert rnd prec
   7001  1.1        is 	mov.w		%d1, %d0		# make a copy
   7002  1.1        is 	lsl.b		&0x1, %d1		# shift left by 1
   7003  1.1        is 
   7004  1.1        is #
   7005  1.1        is # use the rounding mode, precision, and result sign as in index into the
   7006  1.1        is # two tables below to fetch the default result and the result ccodes.
   7007  1.1        is #
   7008  1.1        is ovf_res_load:
   7009  1.1        is 	mov.b		(tbl_ovfl_cc.b,%pc,%d0.w*1), %d0 # fetch result ccodes
   7010  1.1        is 	lea		(tbl_ovfl_result.b,%pc,%d1.w*8), %a0 # return result ptr
   7011  1.1        is 
   7012  1.1        is 	rts
   7013  1.1        is 
   7014  1.1        is tbl_ovfl_cc:
   7015  1.1        is 	byte		0x2, 0x0, 0x0, 0x2
   7016  1.1        is 	byte		0x2, 0x0, 0x0, 0x2
   7017  1.1        is 	byte		0x2, 0x0, 0x0, 0x2
   7018  1.1        is 	byte		0x0, 0x0, 0x0, 0x0
   7019  1.1        is 	byte		0x2+0x8, 0x8, 0x2+0x8, 0x8
   7020  1.1        is 	byte		0x2+0x8, 0x8, 0x2+0x8, 0x8
   7021  1.1        is 	byte		0x2+0x8, 0x8, 0x2+0x8, 0x8
   7022  1.1        is 
   7023  1.1        is tbl_ovfl_result:
   7024  1.1        is 	long		0x7fff0000,0x00000000,0x00000000,0x00000000 # +INF; RN
   7025  1.1        is 	long		0x7ffe0000,0xffffffff,0xffffffff,0x00000000 # +EXT; RZ
   7026  1.1        is 	long		0x7ffe0000,0xffffffff,0xffffffff,0x00000000 # +EXT; RM
   7027  1.1        is 	long		0x7fff0000,0x00000000,0x00000000,0x00000000 # +INF; RP
   7028  1.1        is 
   7029  1.1        is 	long		0x7fff0000,0x00000000,0x00000000,0x00000000 # +INF; RN
   7030  1.1        is 	long		0x407e0000,0xffffff00,0x00000000,0x00000000 # +SGL; RZ
   7031  1.1        is 	long		0x407e0000,0xffffff00,0x00000000,0x00000000 # +SGL; RM
   7032  1.1        is 	long		0x7fff0000,0x00000000,0x00000000,0x00000000 # +INF; RP
   7033  1.1        is 
   7034  1.1        is 	long		0x7fff0000,0x00000000,0x00000000,0x00000000 # +INF; RN
   7035  1.1        is 	long		0x43fe0000,0xffffffff,0xfffff800,0x00000000 # +DBL; RZ
   7036  1.1        is 	long		0x43fe0000,0xffffffff,0xfffff800,0x00000000 # +DBL; RM
   7037  1.1        is 	long		0x7fff0000,0x00000000,0x00000000,0x00000000 # +INF; RP
   7038  1.1        is 
   7039  1.1        is 	long		0x00000000,0x00000000,0x00000000,0x00000000
   7040  1.1        is 	long		0x00000000,0x00000000,0x00000000,0x00000000
   7041  1.1        is 	long		0x00000000,0x00000000,0x00000000,0x00000000
   7042  1.1        is 	long		0x00000000,0x00000000,0x00000000,0x00000000
   7043  1.1        is 
   7044  1.1        is 	long		0xffff0000,0x00000000,0x00000000,0x00000000 # -INF; RN
   7045  1.1        is 	long		0xfffe0000,0xffffffff,0xffffffff,0x00000000 # -EXT; RZ
   7046  1.1        is 	long		0xffff0000,0x00000000,0x00000000,0x00000000 # -INF; RM
   7047  1.1        is 	long		0xfffe0000,0xffffffff,0xffffffff,0x00000000 # -EXT; RP
   7048  1.1        is 
   7049  1.1        is 	long		0xffff0000,0x00000000,0x00000000,0x00000000 # -INF; RN
   7050  1.1        is 	long		0xc07e0000,0xffffff00,0x00000000,0x00000000 # -SGL; RZ
   7051  1.1        is 	long		0xffff0000,0x00000000,0x00000000,0x00000000 # -INF; RM
   7052  1.1        is 	long		0xc07e0000,0xffffff00,0x00000000,0x00000000 # -SGL; RP
   7053  1.1        is 
   7054  1.1        is 	long		0xffff0000,0x00000000,0x00000000,0x00000000 # -INF; RN
   7055  1.1        is 	long		0xc3fe0000,0xffffffff,0xfffff800,0x00000000 # -DBL; RZ
   7056  1.1        is 	long		0xffff0000,0x00000000,0x00000000,0x00000000 # -INF; RM
   7057  1.1        is 	long		0xc3fe0000,0xffffffff,0xfffff800,0x00000000 # -DBL; RP
   7058  1.1        is 
   7059  1.1        is #########################################################################
   7060  1.1        is # XDEF ****************************************************************	#
   7061  1.1        is # 	fout(): move from fp register to memory or data register	#
   7062  1.1        is #									#
   7063  1.1        is # XREF ****************************************************************	#
   7064  1.1        is #	_round() - needed to create EXOP for sgl/dbl precision		#
   7065  1.1        is #	norm() - needed to create EXOP for extended precision		#
   7066  1.1        is #	ovf_res() - create default overflow result for sgl/dbl precision#
   7067  1.1        is #	unf_res() - create default underflow result for sgl/dbl prec.	#
   7068  1.1        is #	dst_dbl() - create rounded dbl precision result.		#
   7069  1.1        is #	dst_sgl() - create rounded sgl precision result.		#
   7070  1.1        is #	fetch_dreg() - fetch dynamic k-factor reg for packed.		#
   7071  1.1        is #	bindec() - convert FP binary number to packed number.		#
   7072  1.1        is #	_mem_write() - write data to memory.				#
   7073  1.1        is #	_mem_write2() - write data to memory unless supv mode -(a7) exc.#
   7074  1.1        is #	_dmem_write_{byte,word,long}() - write data to memory.		#
   7075  1.1        is #	store_dreg_{b,w,l}() - store data to data register file.	#
   7076  1.1        is #	facc_out_{b,w,l,d,x}() - data access error occurred.		#
   7077  1.1        is #									#
   7078  1.1        is # INPUT ***************************************************************	#
   7079  1.1        is #	a0 = pointer to extended precision source operand		#
   7080  1.1        is #	d0 = round prec,mode						#
   7081  1.1        is # 									#
   7082  1.1        is # OUTPUT **************************************************************	#
   7083  1.1        is #	fp0 : intermediate underflow or overflow result if		#
   7084  1.1        is #	      OVFL/UNFL occurred for a sgl or dbl operand		#
   7085  1.1        is #									#
   7086  1.1        is # ALGORITHM ***********************************************************	#
   7087  1.1        is #	This routine is accessed by many handlers that need to do an	#
   7088  1.1        is # opclass three move of an operand out to memory.			#
   7089  1.1        is #	Decode an fmove out (opclass 3) instruction to determine if	#
   7090  1.1        is # it's b,w,l,s,d,x, or p in size. b,w,l can be stored to either a data	#
   7091  1.1        is # register or memory. The algorithm uses a standard "fmove" to create	#
   7092  1.1        is # the rounded result. Also, since exceptions are disabled, this also	#
   7093  1.1        is # create the correct OPERR default result if appropriate.		#
   7094  1.1        is #	For sgl or dbl precision, overflow or underflow can occur. If	#
   7095  1.1        is # either occurs and is enabled, the EXOP.				#
   7096  1.1        is #	For extended precision, the stacked <ea> must be fixed along	#
   7097  1.1        is # w/ the address index register as appropriate w/ _calc_ea_fout(). If	#
   7098  1.1        is # the source is a denorm and if underflow is enabled, an EXOP must be	#
   7099  1.1        is # created.								#
   7100  1.1        is # 	For packed, the k-factor must be fetched from the instruction	#
   7101  1.1        is # word or a data register. The <ea> must be fixed as w/ extended 	#
   7102  1.1        is # precision. Then, bindec() is called to create the appropriate 	#
   7103  1.1        is # packed result.							#
   7104  1.1        is #	If at any time an access error is flagged by one of the move-	#
   7105  1.1        is # to-memory routines, then a special exit must be made so that the	#
   7106  1.1        is # access error can be handled properly.					#
   7107  1.1        is #									#
   7108  1.1        is #########################################################################
   7109  1.1        is 
   7110  1.1        is 	global		fout
   7111  1.1        is fout:
   7112  1.1        is 	bfextu		EXC_CMDREG(%a6){&3:&3},%d1 # extract dst fmt
   7113  1.1        is 	mov.w		(tbl_fout.b,%pc,%d1.w*2),%a1 # use as index
   7114  1.1        is 	jmp		(tbl_fout.b,%pc,%a1)	# jump to routine
   7115  1.1        is 
   7116  1.1        is 	swbeg		&0x8
   7117  1.1        is tbl_fout:
   7118  1.1        is 	short		fout_long	-	tbl_fout
   7119  1.1        is 	short		fout_sgl	-	tbl_fout
   7120  1.1        is 	short		fout_ext	-	tbl_fout
   7121  1.1        is 	short		fout_pack	-	tbl_fout
   7122  1.1        is 	short		fout_word	-	tbl_fout
   7123  1.1        is 	short		fout_dbl	-	tbl_fout
   7124  1.1        is 	short		fout_byte	-	tbl_fout
   7125  1.1        is 	short		fout_pack	-	tbl_fout
   7126  1.1        is 
   7127  1.1        is #################################################################
   7128  1.1        is # fmove.b out ###################################################
   7129  1.1        is #################################################################
   7130  1.1        is 
   7131  1.1        is # Only "Unimplemented Data Type" exceptions enter here. The operand
   7132  1.1        is # is either a DENORM or a NORM.
   7133  1.1        is fout_byte:
   7134  1.1        is 	tst.b		STAG(%a6)		# is operand normalized?
   7135  1.1        is 	bne.b		fout_byte_denorm	# no
   7136  1.1        is 
   7137  1.1        is 	fmovm.x		SRC(%a0),&0x80		# load value
   7138  1.1        is 
   7139  1.1        is fout_byte_norm:
   7140  1.1        is 	fmov.l		%d0,%fpcr		# insert rnd prec,mode
   7141  1.1        is 
   7142  1.1        is 	fmov.b		%fp0,%d0		# exec move out w/ correct rnd mode
   7143  1.1        is 
   7144  1.1        is 	fmov.l		&0x0,%fpcr		# clear FPCR
   7145  1.1        is 	fmov.l		%fpsr,%d1		# fetch FPSR
   7146  1.1        is 	or.w		%d1,2+USER_FPSR(%a6)	# save new exc,accrued bits
   7147  1.1        is 
   7148  1.1        is 	mov.b		1+EXC_OPWORD(%a6),%d1	# extract dst mode
   7149  1.1        is 	andi.b		&0x38,%d1		# is mode == 0? (Dreg dst)
   7150  1.1        is 	beq.b		fout_byte_dn		# must save to integer regfile
   7151  1.1        is 
   7152  1.1        is 	mov.l		EXC_EA(%a6),%a0		# stacked <ea> is correct
   7153  1.1        is 	bsr.l		_dmem_write_byte	# write byte
   7154  1.1        is 
   7155  1.1        is 	tst.l		%d1			# did dstore fail?
   7156  1.1        is 	bne.l		facc_out_b		# yes
   7157  1.1        is 
   7158  1.1        is 	rts
   7159  1.1        is 
   7160  1.1        is fout_byte_dn:
   7161  1.1        is 	mov.b		1+EXC_OPWORD(%a6),%d1	# extract Dn
   7162  1.1        is 	andi.w		&0x7,%d1
   7163  1.1        is 	bsr.l		store_dreg_b
   7164  1.1        is 	rts
   7165  1.1        is 
   7166  1.1        is fout_byte_denorm:
   7167  1.1        is 	mov.l		SRC_EX(%a0),%d1
   7168  1.1        is 	andi.l		&0x80000000,%d1		# keep DENORM sign
   7169  1.1        is 	ori.l		&0x00800000,%d1		# make smallest sgl
   7170  1.1        is 	fmov.s		%d1,%fp0
   7171  1.1        is 	bra.b		fout_byte_norm
   7172  1.1        is 
   7173  1.1        is #################################################################
   7174  1.1        is # fmove.w out ###################################################
   7175  1.1        is #################################################################
   7176  1.1        is 
   7177  1.1        is # Only "Unimplemented Data Type" exceptions enter here. The operand
   7178  1.1        is # is either a DENORM or a NORM.
   7179  1.1        is fout_word:
   7180  1.1        is 	tst.b		STAG(%a6)		# is operand normalized?
   7181  1.1        is 	bne.b		fout_word_denorm	# no
   7182  1.1        is 
   7183  1.1        is 	fmovm.x		SRC(%a0),&0x80		# load value
   7184  1.1        is 
   7185  1.1        is fout_word_norm:
   7186  1.1        is 	fmov.l		%d0,%fpcr		# insert rnd prec:mode
   7187  1.1        is 
   7188  1.1        is 	fmov.w		%fp0,%d0		# exec move out w/ correct rnd mode
   7189  1.1        is 
   7190  1.1        is 	fmov.l		&0x0,%fpcr		# clear FPCR
   7191  1.1        is 	fmov.l		%fpsr,%d1		# fetch FPSR
   7192  1.1        is 	or.w		%d1,2+USER_FPSR(%a6)	# save new exc,accrued bits
   7193  1.1        is 
   7194  1.1        is 	mov.b		1+EXC_OPWORD(%a6),%d1	# extract dst mode
   7195  1.1        is 	andi.b		&0x38,%d1		# is mode == 0? (Dreg dst)
   7196  1.1        is 	beq.b		fout_word_dn		# must save to integer regfile
   7197  1.1        is 
   7198  1.1        is 	mov.l		EXC_EA(%a6),%a0		# stacked <ea> is correct
   7199  1.1        is 	bsr.l		_dmem_write_word	# write word
   7200  1.1        is 
   7201  1.1        is 	tst.l		%d1			# did dstore fail?
   7202  1.1        is 	bne.l		facc_out_w		# yes
   7203  1.1        is 
   7204  1.1        is 	rts
   7205  1.1        is 
   7206  1.1        is fout_word_dn:
   7207  1.1        is 	mov.b		1+EXC_OPWORD(%a6),%d1	# extract Dn
   7208  1.1        is 	andi.w		&0x7,%d1
   7209  1.1        is 	bsr.l		store_dreg_w
   7210  1.1        is 	rts
   7211  1.1        is 
   7212  1.1        is fout_word_denorm:
   7213  1.1        is 	mov.l		SRC_EX(%a0),%d1
   7214  1.1        is 	andi.l		&0x80000000,%d1		# keep DENORM sign
   7215  1.1        is 	ori.l		&0x00800000,%d1		# make smallest sgl
   7216  1.1        is 	fmov.s		%d1,%fp0
   7217  1.1        is 	bra.b		fout_word_norm
   7218  1.1        is 
   7219  1.1        is #################################################################
   7220  1.1        is # fmove.l out ###################################################
   7221  1.1        is #################################################################
   7222  1.1        is 
   7223  1.1        is # Only "Unimplemented Data Type" exceptions enter here. The operand
   7224  1.1        is # is either a DENORM or a NORM.
   7225  1.1        is fout_long:
   7226  1.1        is 	tst.b		STAG(%a6)		# is operand normalized?
   7227  1.1        is 	bne.b		fout_long_denorm	# no
   7228  1.1        is 
   7229  1.1        is 	fmovm.x		SRC(%a0),&0x80		# load value
   7230  1.1        is 
   7231  1.1        is fout_long_norm:
   7232  1.1        is 	fmov.l		%d0,%fpcr		# insert rnd prec:mode
   7233  1.1        is 
   7234  1.1        is 	fmov.l		%fp0,%d0		# exec move out w/ correct rnd mode
   7235  1.1        is 
   7236  1.1        is 	fmov.l		&0x0,%fpcr		# clear FPCR
   7237  1.1        is 	fmov.l		%fpsr,%d1		# fetch FPSR
   7238  1.1        is 	or.w		%d1,2+USER_FPSR(%a6)	# save new exc,accrued bits
   7239  1.1        is 
   7240  1.1        is fout_long_write:
   7241  1.1        is 	mov.b		1+EXC_OPWORD(%a6),%d1	# extract dst mode
   7242  1.1        is 	andi.b		&0x38,%d1		# is mode == 0? (Dreg dst)
   7243  1.1        is 	beq.b		fout_long_dn		# must save to integer regfile
   7244  1.1        is 
   7245  1.1        is 	mov.l		EXC_EA(%a6),%a0		# stacked <ea> is correct
   7246  1.1        is 	bsr.l		_dmem_write_long	# write long
   7247  1.1        is 
   7248  1.1        is 	tst.l		%d1			# did dstore fail?
   7249  1.1        is 	bne.l		facc_out_l		# yes
   7250  1.1        is 
   7251  1.1        is 	rts
   7252  1.1        is 
   7253  1.1        is fout_long_dn:
   7254  1.1        is 	mov.b		1+EXC_OPWORD(%a6),%d1	# extract Dn
   7255  1.1        is 	andi.w		&0x7,%d1
   7256  1.1        is 	bsr.l		store_dreg_l
   7257  1.1        is 	rts
   7258  1.1        is 
   7259  1.1        is fout_long_denorm:
   7260  1.1        is 	mov.l		SRC_EX(%a0),%d1
   7261  1.1        is 	andi.l		&0x80000000,%d1		# keep DENORM sign
   7262  1.1        is 	ori.l		&0x00800000,%d1		# make smallest sgl
   7263  1.1        is 	fmov.s		%d1,%fp0
   7264  1.1        is 	bra.b		fout_long_norm
   7265  1.1        is 
   7266  1.1        is #################################################################
   7267  1.1        is # fmove.x out ###################################################
   7268  1.1        is #################################################################
   7269  1.1        is 
   7270  1.1        is # Only "Unimplemented Data Type" exceptions enter here. The operand
   7271  1.1        is # is either a DENORM or a NORM.
   7272  1.1        is # The DENORM causes an Underflow exception.
   7273  1.1        is fout_ext:
   7274  1.1        is 
   7275  1.1        is # we copy the extended precision result to FP_SCR0 so that the reserved
   7276  1.1        is # 16-bit field gets zeroed. we do this since we promise not to disturb
   7277  1.1        is # what's at SRC(a0).
   7278  1.1        is 	mov.w		SRC_EX(%a0),FP_SCR0_EX(%a6)
   7279  1.1        is 	clr.w		2+FP_SCR0_EX(%a6)	# clear reserved field
   7280  1.1        is 	mov.l		SRC_HI(%a0),FP_SCR0_HI(%a6)
   7281  1.1        is 	mov.l		SRC_LO(%a0),FP_SCR0_LO(%a6)
   7282  1.1        is 
   7283  1.1        is 	fmovm.x		SRC(%a0),&0x80		# return result
   7284  1.1        is 
   7285  1.1        is 	bsr.l		_calc_ea_fout		# fix stacked <ea>
   7286  1.1        is 
   7287  1.1        is 	mov.l		%a0,%a1			# pass: dst addr
   7288  1.1        is 	lea		FP_SCR0(%a6),%a0	# pass: src addr
   7289  1.1        is 	mov.l		&0xc,%d0		# pass: opsize is 12 bytes
   7290  1.1        is 
   7291  1.1        is # we must not yet write the extended precision data to the stack
   7292  1.1        is # in the pre-decrement case from supervisor mode or else we'll corrupt
   7293  1.1        is # the stack frame. so, leave it in FP_SRC for now and deal with it later...
   7294  1.1        is 	cmpi.b		SPCOND_FLG(%a6),&mda7_flg
   7295  1.1        is 	beq.b		fout_ext_a7
   7296  1.1        is 
   7297  1.1        is 	bsr.l		_dmem_write		# write ext prec number to memory
   7298  1.1        is 
   7299  1.1        is 	tst.l		%d1			# did dstore fail?
   7300  1.1        is 	bne.w		fout_ext_err		# yes
   7301  1.1        is 
   7302  1.1        is 	tst.b		STAG(%a6)		# is operand normalized?
   7303  1.1        is 	bne.b		fout_ext_denorm		# no
   7304  1.1        is 	rts
   7305  1.1        is 
   7306  1.1        is # the number is a DENORM. must set the underflow exception bit
   7307  1.1        is fout_ext_denorm:
   7308  1.1        is 	bset		&unfl_bit,FPSR_EXCEPT(%a6) # set underflow exc bit
   7309  1.1        is 
   7310  1.1        is 	mov.b		FPCR_ENABLE(%a6),%d0
   7311  1.1        is 	andi.b		&0x0a,%d0		# is UNFL or INEX enabled?
   7312  1.1        is 	bne.b		fout_ext_exc		# yes
   7313  1.1        is 	rts
   7314  1.1        is 
   7315  1.1        is # we don't want to do the write if the exception occurred in supervisor mode
   7316  1.1        is # so _mem_write2() handles this for us.
   7317  1.1        is fout_ext_a7:
   7318  1.1        is 	bsr.l		_mem_write2		# write ext prec number to memory
   7319  1.1        is 
   7320  1.1        is 	tst.l		%d1			# did dstore fail?
   7321  1.1        is 	bne.w		fout_ext_err		# yes
   7322  1.1        is 
   7323  1.1        is 	tst.b		STAG(%a6)		# is operand normalized?
   7324  1.1        is 	bne.b		fout_ext_denorm		# no
   7325  1.1        is 	rts
   7326  1.1        is 
   7327  1.1        is fout_ext_exc:
   7328  1.1        is 	lea		FP_SCR0(%a6),%a0
   7329  1.1        is 	bsr.l		norm			# normalize the mantissa
   7330  1.1        is 	neg.w		%d0			# new exp = -(shft amt)
   7331  1.1        is 	andi.w		&0x7fff,%d0
   7332  1.1        is 	andi.w		&0x8000,FP_SCR0_EX(%a6)	# keep only old sign
   7333  1.1        is 	or.w		%d0,FP_SCR0_EX(%a6)	# insert new exponent
   7334  1.1        is 	fmovm.x		FP_SCR0(%a6),&0x40	# return EXOP in fp1
   7335  1.1        is 	rts
   7336  1.1        is 
   7337  1.1        is fout_ext_err:
   7338  1.1        is 	mov.l		EXC_A6(%a6),(%a6)	# fix stacked a6
   7339  1.1        is 	bra.l		facc_out_x
   7340  1.1        is 
   7341  1.1        is #########################################################################
   7342  1.1        is # fmove.s out ###########################################################
   7343  1.1        is #########################################################################
   7344  1.1        is fout_sgl:
   7345  1.1        is 	andi.b		&0x30,%d0		# clear rnd prec
   7346  1.1        is 	ori.b		&s_mode*0x10,%d0	# insert sgl prec
   7347  1.1        is 	mov.l		%d0,L_SCR3(%a6)		# save rnd prec,mode on stack
   7348  1.1        is 
   7349  1.1        is #
   7350  1.1        is # operand is a normalized number. first, we check to see if the move out
   7351  1.1        is # would cause either an underflow or overflow. these cases are handled
   7352  1.1        is # separately. otherwise, set the FPCR to the proper rounding mode and
   7353  1.1        is # execute the move.
   7354  1.1        is #
   7355  1.1        is 	mov.w		SRC_EX(%a0),%d0		# extract exponent
   7356  1.1        is 	andi.w		&0x7fff,%d0		# strip sign
   7357  1.1        is 
   7358  1.1        is 	cmpi.w		%d0,&SGL_HI		# will operand overflow?
   7359  1.1        is 	bgt.w		fout_sgl_ovfl		# yes; go handle OVFL
   7360  1.1        is 	beq.w		fout_sgl_may_ovfl	# maybe; go handle possible OVFL
   7361  1.1        is 	cmpi.w		%d0,&SGL_LO		# will operand underflow?
   7362  1.1        is 	blt.w		fout_sgl_unfl		# yes; go handle underflow
   7363  1.1        is 
   7364  1.1        is #
   7365  1.1        is # NORMs(in range) can be stored out by a simple "fmov.s"
   7366  1.1        is # Unnormalized inputs can come through this point.
   7367  1.1        is #
   7368  1.1        is fout_sgl_exg:
   7369  1.1        is 	fmovm.x		SRC(%a0),&0x80		# fetch fop from stack
   7370  1.1        is 
   7371  1.1        is 	fmov.l		L_SCR3(%a6),%fpcr	# set FPCR
   7372  1.1        is 	fmov.l		&0x0,%fpsr		# clear FPSR
   7373  1.1        is 
   7374  1.1        is 	fmov.s		%fp0,%d0		# store does convert and round
   7375  1.1        is 
   7376  1.1        is 	fmov.l		&0x0,%fpcr		# clear FPCR
   7377  1.1        is 	fmov.l		%fpsr,%d1		# save FPSR
   7378  1.1        is 
   7379  1.1        is 	or.w		%d1,2+USER_FPSR(%a6) 	# set possible inex2/ainex
   7380  1.1        is 
   7381  1.1        is fout_sgl_exg_write:
   7382  1.1        is 	mov.b		1+EXC_OPWORD(%a6),%d1	# extract dst mode
   7383  1.1        is 	andi.b		&0x38,%d1		# is mode == 0? (Dreg dst)
   7384  1.1        is 	beq.b		fout_sgl_exg_write_dn	# must save to integer regfile
   7385  1.1        is 
   7386  1.1        is 	mov.l		EXC_EA(%a6),%a0		# stacked <ea> is correct
   7387  1.1        is 	bsr.l		_dmem_write_long	# write long
   7388  1.1        is 
   7389  1.1        is 	tst.l		%d1			# did dstore fail?
   7390  1.1        is 	bne.l		facc_out_l		# yes
   7391  1.1        is 
   7392  1.1        is 	rts
   7393  1.1        is 
   7394  1.1        is fout_sgl_exg_write_dn:
   7395  1.1        is 	mov.b		1+EXC_OPWORD(%a6),%d1	# extract Dn
   7396  1.1        is 	andi.w		&0x7,%d1
   7397  1.1        is 	bsr.l		store_dreg_l
   7398  1.1        is 	rts
   7399  1.1        is 
   7400  1.1        is #
   7401  1.1        is # here, we know that the operand would UNFL if moved out to single prec,
   7402  1.1        is # so, denorm and round and then use generic store single routine to
   7403  1.1        is # write the value to memory.
   7404  1.1        is #
   7405  1.1        is fout_sgl_unfl:
   7406  1.1        is 	bset		&unfl_bit,FPSR_EXCEPT(%a6) # set UNFL
   7407  1.1        is 
   7408  1.1        is 	mov.w		SRC_EX(%a0),FP_SCR0_EX(%a6)
   7409  1.1        is 	mov.l		SRC_HI(%a0),FP_SCR0_HI(%a6)
   7410  1.1        is 	mov.l		SRC_LO(%a0),FP_SCR0_LO(%a6)
   7411  1.1        is 	mov.l		%a0,-(%sp)
   7412  1.1        is 
   7413  1.1        is 	clr.l		%d0			# pass: S.F. = 0
   7414  1.1        is 
   7415  1.1        is 	cmpi.b		STAG(%a6),&DENORM	# fetch src optype tag
   7416  1.1        is 	bne.b		fout_sgl_unfl_cont	# let DENORMs fall through
   7417  1.1        is 
   7418  1.1        is 	lea		FP_SCR0(%a6),%a0
   7419  1.1        is 	bsr.l		norm			# normalize the DENORM
   7420  1.1        is 
   7421  1.1        is fout_sgl_unfl_cont:
   7422  1.1        is 	lea		FP_SCR0(%a6),%a0	# pass: ptr to operand
   7423  1.1        is 	mov.l		L_SCR3(%a6),%d1		# pass: rnd prec,mode
   7424  1.1        is 	bsr.l		unf_res			# calc default underflow result
   7425  1.1        is 
   7426  1.1        is 	lea		FP_SCR0(%a6),%a0	# pass: ptr to fop
   7427  1.1        is 	bsr.l		dst_sgl			# convert to single prec
   7428  1.1        is 
   7429  1.1        is 	mov.b		1+EXC_OPWORD(%a6),%d1	# extract dst mode
   7430  1.1        is 	andi.b		&0x38,%d1		# is mode == 0? (Dreg dst)
   7431  1.1        is 	beq.b		fout_sgl_unfl_dn	# must save to integer regfile
   7432  1.1        is 
   7433  1.1        is 	mov.l		EXC_EA(%a6),%a0		# stacked <ea> is correct
   7434  1.1        is 	bsr.l		_dmem_write_long	# write long
   7435  1.1        is 
   7436  1.1        is 	tst.l		%d1			# did dstore fail?
   7437  1.1        is 	bne.l		facc_out_l		# yes
   7438  1.1        is 
   7439  1.1        is 	bra.b		fout_sgl_unfl_chkexc
   7440  1.1        is 
   7441  1.1        is fout_sgl_unfl_dn:
   7442  1.1        is 	mov.b		1+EXC_OPWORD(%a6),%d1	# extract Dn
   7443  1.1        is 	andi.w		&0x7,%d1
   7444  1.1        is 	bsr.l		store_dreg_l
   7445  1.1        is 
   7446  1.1        is fout_sgl_unfl_chkexc:
   7447  1.1        is 	mov.b		FPCR_ENABLE(%a6),%d1
   7448  1.1        is 	andi.b		&0x0a,%d1		# is UNFL or INEX enabled?
   7449  1.1        is 	bne.w		fout_sd_exc_unfl	# yes
   7450  1.1        is 	addq.l		&0x4,%sp
   7451  1.1        is 	rts
   7452  1.1        is 
   7453  1.1        is #
   7454  1.1        is # it's definitely an overflow so call ovf_res to get the correct answer
   7455  1.1        is #
   7456  1.1        is fout_sgl_ovfl:
   7457  1.1        is 	tst.b		3+SRC_HI(%a0)		# is result inexact?
   7458  1.1        is 	bne.b		fout_sgl_ovfl_inex2
   7459  1.1        is 	tst.l		SRC_LO(%a0)		# is result inexact?
   7460  1.1        is 	bne.b		fout_sgl_ovfl_inex2
   7461  1.1        is 	ori.w		&ovfl_inx_mask,2+USER_FPSR(%a6) # set ovfl/aovfl/ainex
   7462  1.1        is 	bra.b		fout_sgl_ovfl_cont
   7463  1.1        is fout_sgl_ovfl_inex2:
   7464  1.1        is 	ori.w		&ovfinx_mask,2+USER_FPSR(%a6) # set ovfl/aovfl/ainex/inex2
   7465  1.1        is 
   7466  1.1        is fout_sgl_ovfl_cont:
   7467  1.1        is 	mov.l		%a0,-(%sp)
   7468  1.1        is 
   7469  1.1        is # call ovf_res() w/ sgl prec and the correct rnd mode to create the default
   7470  1.1        is # overflow result. DON'T save the returned ccodes from ovf_res() since
   7471  1.1        is # fmove out doesn't alter them.
   7472  1.1        is 	tst.b		SRC_EX(%a0)		# is operand negative?
   7473  1.1        is 	smi		%d1			# set if so
   7474  1.1        is 	mov.l		L_SCR3(%a6),%d0		# pass: sgl prec,rnd mode
   7475  1.1        is 	bsr.l		ovf_res			# calc OVFL result
   7476  1.1        is 	fmovm.x		(%a0),&0x80		# load default overflow result
   7477  1.1        is 	fmov.s		%fp0,%d0		# store to single
   7478  1.1        is 
   7479  1.1        is 	mov.b		1+EXC_OPWORD(%a6),%d1	# extract dst mode
   7480  1.1        is 	andi.b		&0x38,%d1		# is mode == 0? (Dreg dst)
   7481  1.1        is 	beq.b		fout_sgl_ovfl_dn	# must save to integer regfile
   7482  1.1        is 
   7483  1.1        is 	mov.l		EXC_EA(%a6),%a0		# stacked <ea> is correct
   7484  1.1        is 	bsr.l		_dmem_write_long	# write long
   7485  1.1        is 
   7486  1.1        is 	tst.l		%d1			# did dstore fail?
   7487  1.1        is 	bne.l		facc_out_l		# yes
   7488  1.1        is 
   7489  1.1        is 	bra.b		fout_sgl_ovfl_chkexc
   7490  1.1        is 
   7491  1.1        is fout_sgl_ovfl_dn:
   7492  1.1        is 	mov.b		1+EXC_OPWORD(%a6),%d1	# extract Dn
   7493  1.1        is 	andi.w		&0x7,%d1
   7494  1.1        is 	bsr.l		store_dreg_l
   7495  1.1        is 
   7496  1.1        is fout_sgl_ovfl_chkexc:
   7497  1.1        is 	mov.b		FPCR_ENABLE(%a6),%d1
   7498  1.1        is 	andi.b		&0x0a,%d1		# is UNFL or INEX enabled?
   7499  1.1        is 	bne.w		fout_sd_exc_ovfl	# yes
   7500  1.1        is 	addq.l		&0x4,%sp
   7501  1.1        is 	rts
   7502  1.1        is 
   7503  1.1        is #
   7504  1.1        is # move out MAY overflow:
   7505  1.1        is # (1) force the exp to 0x3fff
   7506  1.1        is # (2) do a move w/ appropriate rnd mode
   7507  1.1        is # (3) if exp still equals zero, then insert original exponent
   7508  1.1        is #	for the correct result.
   7509  1.1        is #     if exp now equals one, then it overflowed so call ovf_res.
   7510  1.1        is #
   7511  1.1        is fout_sgl_may_ovfl:
   7512  1.1        is 	mov.w		SRC_EX(%a0),%d1		# fetch current sign
   7513  1.1        is 	andi.w		&0x8000,%d1		# keep it,clear exp
   7514  1.1        is 	ori.w		&0x3fff,%d1		# insert exp = 0
   7515  1.1        is 	mov.w		%d1,FP_SCR0_EX(%a6)	# insert scaled exp
   7516  1.1        is 	mov.l		SRC_HI(%a0),FP_SCR0_HI(%a6) # copy hi(man)
   7517  1.1        is 	mov.l		SRC_LO(%a0),FP_SCR0_LO(%a6) # copy lo(man)
   7518  1.1        is 
   7519  1.1        is 	fmov.l		L_SCR3(%a6),%fpcr	# set FPCR
   7520  1.1        is 
   7521  1.1        is 	fmov.x		FP_SCR0(%a6),%fp0	# force fop to be rounded
   7522  1.1        is 	fmov.l		&0x0,%fpcr		# clear FPCR
   7523  1.1        is 
   7524  1.1        is 	fabs.x		%fp0			# need absolute value
   7525  1.1        is 	fcmp.b		%fp0,&0x2		# did exponent increase?
   7526  1.1        is 	fblt.w		fout_sgl_exg		# no; go finish NORM
   7527  1.1        is 	bra.w		fout_sgl_ovfl		# yes; go handle overflow
   7528  1.1        is 
   7529  1.1        is ################
   7530  1.1        is 
   7531  1.1        is fout_sd_exc_unfl:
   7532  1.1        is 	mov.l		(%sp)+,%a0
   7533  1.1        is 
   7534  1.1        is 	mov.w		SRC_EX(%a0),FP_SCR0_EX(%a6)
   7535  1.1        is 	mov.l		SRC_HI(%a0),FP_SCR0_HI(%a6)
   7536  1.1        is 	mov.l		SRC_LO(%a0),FP_SCR0_LO(%a6)
   7537  1.1        is 
   7538  1.1        is 	cmpi.b		STAG(%a6),&DENORM	# was src a DENORM?
   7539  1.1        is 	bne.b		fout_sd_exc_cont	# no
   7540  1.1        is 
   7541  1.1        is 	lea		FP_SCR0(%a6),%a0
   7542  1.1        is 	bsr.l		norm
   7543  1.1        is 	neg.l		%d0
   7544  1.1        is 	andi.w		&0x7fff,%d0
   7545  1.1        is 	bfins		%d0,FP_SCR0_EX(%a6){&1:&15}
   7546  1.1        is 	bra.b		fout_sd_exc_cont
   7547  1.1        is 
   7548  1.1        is fout_sd_exc:
   7549  1.1        is fout_sd_exc_ovfl:
   7550  1.1        is 	mov.l		(%sp)+,%a0		# restore a0
   7551  1.1        is 
   7552  1.1        is 	mov.w		SRC_EX(%a0),FP_SCR0_EX(%a6)
   7553  1.1        is 	mov.l		SRC_HI(%a0),FP_SCR0_HI(%a6)
   7554  1.1        is 	mov.l		SRC_LO(%a0),FP_SCR0_LO(%a6)
   7555  1.1        is 
   7556  1.1        is fout_sd_exc_cont:
   7557  1.1        is 	bclr		&0x7,FP_SCR0_EX(%a6)	# clear sign bit
   7558  1.1        is 	sne.b		2+FP_SCR0_EX(%a6)	# set internal sign bit
   7559  1.1        is 	lea		FP_SCR0(%a6),%a0	# pass: ptr to DENORM
   7560  1.1        is 
   7561  1.1        is 	mov.b		3+L_SCR3(%a6),%d1
   7562  1.1        is 	lsr.b		&0x4,%d1
   7563  1.1        is 	andi.w		&0x0c,%d1
   7564  1.1        is 	swap		%d1
   7565  1.1        is 	mov.b		3+L_SCR3(%a6),%d1
   7566  1.1        is 	lsr.b		&0x4,%d1
   7567  1.1        is 	andi.w		&0x03,%d1
   7568  1.1        is 	clr.l		%d0			# pass: zero g,r,s
   7569  1.1        is 	bsr.l		_round			# round the DENORM
   7570  1.1        is 
   7571  1.1        is 	tst.b		2+FP_SCR0_EX(%a6)	# is EXOP negative?
   7572  1.1        is 	beq.b		fout_sd_exc_done	# no
   7573  1.1        is 	bset		&0x7,FP_SCR0_EX(%a6)	# yes
   7574  1.1        is 
   7575  1.1        is fout_sd_exc_done:
   7576  1.1        is 	fmovm.x		FP_SCR0(%a6),&0x40	# return EXOP in fp1
   7577  1.1        is 	rts
   7578  1.1        is 
   7579  1.1        is #################################################################
   7580  1.1        is # fmove.d out ###################################################
   7581  1.1        is #################################################################
   7582  1.1        is fout_dbl:
   7583  1.1        is 	andi.b		&0x30,%d0		# clear rnd prec
   7584  1.1        is 	ori.b		&d_mode*0x10,%d0	# insert dbl prec
   7585  1.1        is 	mov.l		%d0,L_SCR3(%a6)		# save rnd prec,mode on stack
   7586  1.1        is 
   7587  1.1        is #
   7588  1.1        is # operand is a normalized number. first, we check to see if the move out
   7589  1.1        is # would cause either an underflow or overflow. these cases are handled
   7590  1.1        is # separately. otherwise, set the FPCR to the proper rounding mode and
   7591  1.1        is # execute the move.
   7592  1.1        is #
   7593  1.1        is 	mov.w		SRC_EX(%a0),%d0		# extract exponent
   7594  1.1        is 	andi.w		&0x7fff,%d0		# strip sign
   7595  1.1        is 
   7596  1.1        is 	cmpi.w		%d0,&DBL_HI		# will operand overflow?
   7597  1.1        is 	bgt.w		fout_dbl_ovfl		# yes; go handle OVFL
   7598  1.1        is 	beq.w		fout_dbl_may_ovfl	# maybe; go handle possible OVFL
   7599  1.1        is 	cmpi.w		%d0,&DBL_LO		# will operand underflow?
   7600  1.1        is 	blt.w		fout_dbl_unfl		# yes; go handle underflow
   7601  1.1        is 
   7602  1.1        is #
   7603  1.1        is # NORMs(in range) can be stored out by a simple "fmov.d"
   7604  1.1        is # Unnormalized inputs can come through this point.
   7605  1.1        is #
   7606  1.1        is fout_dbl_exg:
   7607  1.1        is 	fmovm.x		SRC(%a0),&0x80		# fetch fop from stack
   7608  1.1        is 
   7609  1.1        is 	fmov.l		L_SCR3(%a6),%fpcr	# set FPCR
   7610  1.1        is 	fmov.l		&0x0,%fpsr		# clear FPSR
   7611  1.1        is 
   7612  1.1        is 	fmov.d		%fp0,L_SCR1(%a6)	# store does convert and round
   7613  1.1        is 
   7614  1.1        is 	fmov.l		&0x0,%fpcr		# clear FPCR
   7615  1.1        is 	fmov.l		%fpsr,%d0		# save FPSR
   7616  1.1        is 
   7617  1.1        is 	or.w		%d0,2+USER_FPSR(%a6) 	# set possible inex2/ainex
   7618  1.1        is 
   7619  1.1        is 	mov.l		EXC_EA(%a6),%a1		# pass: dst addr
   7620  1.1        is 	lea		L_SCR1(%a6),%a0		# pass: src addr
   7621  1.1        is 	movq.l		&0x8,%d0		# pass: opsize is 8 bytes
   7622  1.1        is 	bsr.l		_dmem_write		# store dbl fop to memory
   7623  1.1        is 
   7624  1.1        is 	tst.l		%d1			# did dstore fail?
   7625  1.1        is 	bne.l		facc_out_d		# yes
   7626  1.1        is 
   7627  1.1        is 	rts					# no; so we're finished
   7628  1.1        is 
   7629  1.1        is #
   7630  1.1        is # here, we know that the operand would UNFL if moved out to double prec,
   7631  1.1        is # so, denorm and round and then use generic store double routine to
   7632  1.1        is # write the value to memory.
   7633  1.1        is #
   7634  1.1        is fout_dbl_unfl:
   7635  1.1        is 	bset		&unfl_bit,FPSR_EXCEPT(%a6) # set UNFL
   7636  1.1        is 
   7637  1.1        is 	mov.w		SRC_EX(%a0),FP_SCR0_EX(%a6)
   7638  1.1        is 	mov.l		SRC_HI(%a0),FP_SCR0_HI(%a6)
   7639  1.1        is 	mov.l		SRC_LO(%a0),FP_SCR0_LO(%a6)
   7640  1.1        is 	mov.l		%a0,-(%sp)
   7641  1.1        is 
   7642  1.1        is 	clr.l		%d0			# pass: S.F. = 0
   7643  1.1        is 
   7644  1.1        is 	cmpi.b		STAG(%a6),&DENORM	# fetch src optype tag
   7645  1.1        is 	bne.b		fout_dbl_unfl_cont	# let DENORMs fall through
   7646  1.1        is 
   7647  1.1        is 	lea		FP_SCR0(%a6),%a0
   7648  1.1        is 	bsr.l		norm			# normalize the DENORM
   7649  1.1        is 
   7650  1.1        is fout_dbl_unfl_cont:
   7651  1.1        is 	lea		FP_SCR0(%a6),%a0	# pass: ptr to operand
   7652  1.1        is 	mov.l		L_SCR3(%a6),%d1		# pass: rnd prec,mode
   7653  1.1        is 	bsr.l		unf_res			# calc default underflow result
   7654  1.1        is 
   7655  1.1        is 	lea		FP_SCR0(%a6),%a0	# pass: ptr to fop
   7656  1.1        is 	bsr.l		dst_dbl			# convert to single prec
   7657  1.1        is 	mov.l		%d0,L_SCR1(%a6)
   7658  1.1        is 	mov.l		%d1,L_SCR2(%a6)
   7659  1.1        is 
   7660  1.1        is 	mov.l		EXC_EA(%a6),%a1		# pass: dst addr
   7661  1.1        is 	lea		L_SCR1(%a6),%a0		# pass: src addr
   7662  1.1        is 	movq.l		&0x8,%d0		# pass: opsize is 8 bytes
   7663  1.1        is 	bsr.l		_dmem_write		# store dbl fop to memory
   7664  1.1        is 
   7665  1.1        is 	tst.l		%d1			# did dstore fail?
   7666  1.1        is 	bne.l		facc_out_d		# yes
   7667  1.1        is 
   7668  1.1        is 	mov.b		FPCR_ENABLE(%a6),%d1
   7669  1.1        is 	andi.b		&0x0a,%d1		# is UNFL or INEX enabled?
   7670  1.1        is 	bne.w		fout_sd_exc_unfl	# yes
   7671  1.1        is 	addq.l		&0x4,%sp
   7672  1.1        is 	rts
   7673  1.1        is 
   7674  1.1        is #
   7675  1.1        is # it's definitely an overflow so call ovf_res to get the correct answer
   7676  1.1        is #
   7677  1.1        is fout_dbl_ovfl:
   7678  1.1        is 	mov.w		2+SRC_LO(%a0),%d0
   7679  1.1        is 	andi.w		&0x7ff,%d0
   7680  1.1        is 	bne.b		fout_dbl_ovfl_inex2
   7681  1.1        is 
   7682  1.1        is 	ori.w		&ovfl_inx_mask,2+USER_FPSR(%a6) # set ovfl/aovfl/ainex
   7683  1.1        is 	bra.b		fout_dbl_ovfl_cont
   7684  1.1        is fout_dbl_ovfl_inex2:
   7685  1.1        is 	ori.w		&ovfinx_mask,2+USER_FPSR(%a6) # set ovfl/aovfl/ainex/inex2
   7686  1.1        is 
   7687  1.1        is fout_dbl_ovfl_cont:
   7688  1.1        is 	mov.l		%a0,-(%sp)
   7689  1.1        is 
   7690  1.1        is # call ovf_res() w/ dbl prec and the correct rnd mode to create the default
   7691  1.1        is # overflow result. DON'T save the returned ccodes from ovf_res() since
   7692  1.1        is # fmove out doesn't alter them.
   7693  1.1        is 	tst.b		SRC_EX(%a0)		# is operand negative?
   7694  1.1        is 	smi		%d1			# set if so
   7695  1.1        is 	mov.l		L_SCR3(%a6),%d0		# pass: dbl prec,rnd mode
   7696  1.1        is 	bsr.l		ovf_res			# calc OVFL result
   7697  1.1        is 	fmovm.x		(%a0),&0x80		# load default overflow result
   7698  1.1        is 	fmov.d		%fp0,L_SCR1(%a6)	# store to double
   7699  1.1        is 
   7700  1.1        is 	mov.l		EXC_EA(%a6),%a1		# pass: dst addr
   7701  1.1        is 	lea		L_SCR1(%a6),%a0		# pass: src addr
   7702  1.1        is 	movq.l		&0x8,%d0		# pass: opsize is 8 bytes
   7703  1.1        is 	bsr.l		_dmem_write		# store dbl fop to memory
   7704  1.1        is 
   7705  1.1        is 	tst.l		%d1			# did dstore fail?
   7706  1.1        is 	bne.l		facc_out_d		# yes
   7707  1.1        is 
   7708  1.1        is 	mov.b		FPCR_ENABLE(%a6),%d1
   7709  1.1        is 	andi.b		&0x0a,%d1		# is UNFL or INEX enabled?
   7710  1.1        is 	bne.w		fout_sd_exc_ovfl	# yes
   7711  1.1        is 	addq.l		&0x4,%sp
   7712  1.1        is 	rts
   7713  1.1        is 
   7714  1.1        is #
   7715  1.1        is # move out MAY overflow:
   7716  1.1        is # (1) force the exp to 0x3fff
   7717  1.1        is # (2) do a move w/ appropriate rnd mode
   7718  1.1        is # (3) if exp still equals zero, then insert original exponent
   7719  1.1        is #	for the correct result.
   7720  1.1        is #     if exp now equals one, then it overflowed so call ovf_res.
   7721  1.1        is #
   7722  1.1        is fout_dbl_may_ovfl:
   7723  1.1        is 	mov.w		SRC_EX(%a0),%d1		# fetch current sign
   7724  1.1        is 	andi.w		&0x8000,%d1		# keep it,clear exp
   7725  1.1        is 	ori.w		&0x3fff,%d1		# insert exp = 0
   7726  1.1        is 	mov.w		%d1,FP_SCR0_EX(%a6)	# insert scaled exp
   7727  1.1        is 	mov.l		SRC_HI(%a0),FP_SCR0_HI(%a6) # copy hi(man)
   7728  1.1        is 	mov.l		SRC_LO(%a0),FP_SCR0_LO(%a6) # copy lo(man)
   7729  1.1        is 
   7730  1.1        is 	fmov.l		L_SCR3(%a6),%fpcr	# set FPCR
   7731  1.1        is 
   7732  1.1        is 	fmov.x		FP_SCR0(%a6),%fp0	# force fop to be rounded
   7733  1.1        is 	fmov.l		&0x0,%fpcr		# clear FPCR
   7734  1.1        is 
   7735  1.1        is 	fabs.x		%fp0			# need absolute value
   7736  1.1        is 	fcmp.b		%fp0,&0x2		# did exponent increase?
   7737  1.1        is 	fblt.w		fout_dbl_exg		# no; go finish NORM
   7738  1.1        is 	bra.w		fout_dbl_ovfl		# yes; go handle overflow
   7739  1.1        is 
   7740  1.1        is #########################################################################
   7741  1.1        is # XDEF ****************************************************************	#
   7742  1.1        is # 	dst_dbl(): create double precision value from extended prec.	#
   7743  1.1        is #									#
   7744  1.1        is # XREF ****************************************************************	#
   7745  1.1        is #	None								#
   7746  1.1        is #									#
   7747  1.1        is # INPUT ***************************************************************	#
   7748  1.1        is #	a0 = pointer to source operand in extended precision		#
   7749  1.1        is # 									#
   7750  1.1        is # OUTPUT **************************************************************	#
   7751  1.1        is #	d0 = hi(double precision result)				#
   7752  1.1        is #	d1 = lo(double precision result)				#
   7753  1.1        is #									#
   7754  1.1        is # ALGORITHM ***********************************************************	#
   7755  1.1        is #									#
   7756  1.1        is #  Changes extended precision to double precision.			#
   7757  1.1        is #  Note: no attempt is made to round the extended value to double.	#
   7758  1.1        is #	dbl_sign = ext_sign						#
   7759  1.1        is #	dbl_exp = ext_exp - $3fff(ext bias) + $7ff(dbl bias)		#
   7760  1.1        is #	get rid of ext integer bit					#
   7761  1.1        is #	dbl_mant = ext_mant{62:12}					#
   7762  1.1        is #									#
   7763  1.1        is #	    	---------------   ---------------    ---------------	#
   7764  1.1        is #  extended ->  |s|    exp    |   |1| ms mant   |    | ls mant     |	#
   7765  1.1        is #	    	---------------   ---------------    ---------------	#
   7766  1.1        is #	   	 95	    64    63 62	      32      31     11	  0	#
   7767  1.1        is #				     |			     |		#
   7768  1.1        is #				     |			     |		#
   7769  1.1        is #				     |			     |		#
   7770  1.1        is #		 	             v   		     v		#
   7771  1.1        is #	    		      ---------------   ---------------		#
   7772  1.1        is #  double   ->  	      |s|exp| mant  |   |  mant       |		#
   7773  1.1        is #	    		      ---------------   ---------------		#
   7774  1.1        is #	   	 	      63     51   32   31	       0	#
   7775  1.1        is #									#
   7776  1.1        is #########################################################################
   7777  1.1        is 
   7778  1.1        is dst_dbl:
   7779  1.1        is 	clr.l		%d0			# clear d0
   7780  1.1        is 	mov.w		FTEMP_EX(%a0),%d0	# get exponent
   7781  1.1        is 	subi.w		&EXT_BIAS,%d0		# subtract extended precision bias
   7782  1.1        is 	addi.w		&DBL_BIAS,%d0		# add double precision bias
   7783  1.1        is 	tst.b		FTEMP_HI(%a0)		# is number a denorm?
   7784  1.1        is 	bmi.b		dst_get_dupper		# no
   7785  1.1        is 	subq.w		&0x1,%d0		# yes; denorm bias = DBL_BIAS - 1
   7786  1.1        is dst_get_dupper:
   7787  1.1        is 	swap		%d0			# d0 now in upper word
   7788  1.1        is 	lsl.l		&0x4,%d0		# d0 in proper place for dbl prec exp
   7789  1.1        is 	tst.b		FTEMP_EX(%a0)		# test sign
   7790  1.1        is 	bpl.b		dst_get_dman		# if postive, go process mantissa
   7791  1.1        is 	bset		&0x1f,%d0		# if negative, set sign
   7792  1.1        is dst_get_dman:
   7793  1.1        is 	mov.l		FTEMP_HI(%a0),%d1	# get ms mantissa
   7794  1.1        is 	bfextu		%d1{&1:&20},%d1		# get upper 20 bits of ms
   7795  1.1        is 	or.l		%d1,%d0			# put these bits in ms word of double
   7796  1.1        is 	mov.l		%d0,L_SCR1(%a6)		# put the new exp back on the stack
   7797  1.1        is 	mov.l		FTEMP_HI(%a0),%d1	# get ms mantissa
   7798  1.1        is 	mov.l		&21,%d0			# load shift count
   7799  1.1        is 	lsl.l		%d0,%d1			# put lower 11 bits in upper bits
   7800  1.1        is 	mov.l		%d1,L_SCR2(%a6)		# build lower lword in memory
   7801  1.1        is 	mov.l		FTEMP_LO(%a0),%d1	# get ls mantissa
   7802  1.1        is 	bfextu		%d1{&0:&21},%d0		# get ls 21 bits of double
   7803  1.1        is 	mov.l		L_SCR2(%a6),%d1
   7804  1.1        is 	or.l		%d0,%d1			# put them in double result
   7805  1.1        is 	mov.l		L_SCR1(%a6),%d0
   7806  1.1        is 	rts
   7807  1.1        is 
   7808  1.1        is #########################################################################
   7809  1.1        is # XDEF ****************************************************************	#
   7810  1.1        is # 	dst_sgl(): create single precision value from extended prec	#
   7811  1.1        is #									#
   7812  1.1        is # XREF ****************************************************************	#
   7813  1.1        is #									#
   7814  1.1        is # INPUT ***************************************************************	#
   7815  1.1        is #	a0 = pointer to source operand in extended precision		#
   7816  1.1        is # 									#
   7817  1.1        is # OUTPUT **************************************************************	#
   7818  1.1        is #	d0 = single precision result					#
   7819  1.1        is #									#
   7820  1.1        is # ALGORITHM ***********************************************************	#
   7821  1.1        is #									#
   7822  1.1        is # Changes extended precision to single precision.			#
   7823  1.1        is #	sgl_sign = ext_sign						#
   7824  1.1        is #	sgl_exp = ext_exp - $3fff(ext bias) + $7f(sgl bias)		#
   7825  1.1        is #	get rid of ext integer bit					#
   7826  1.1        is #	sgl_mant = ext_mant{62:12}					#
   7827  1.1        is #									#
   7828  1.1        is #	    	---------------   ---------------    ---------------	#
   7829  1.1        is #  extended ->  |s|    exp    |   |1| ms mant   |    | ls mant     |	#
   7830  1.1        is #	    	---------------   ---------------    ---------------	#
   7831  1.1        is #	   	 95	    64    63 62	   40 32      31     12	  0	#
   7832  1.1        is #				     |	   |				#
   7833  1.1        is #				     |	   |				#
   7834  1.1        is #				     |	   |				#
   7835  1.1        is #		 	             v     v				#
   7836  1.1        is #	    		      ---------------				#
   7837  1.1        is #  single   ->  	      |s|exp| mant  |				#
   7838  1.1        is #	    		      ---------------				#
   7839  1.1        is #	   	 	      31     22     0				#
   7840  1.1        is #									#
   7841  1.1        is #########################################################################
   7842  1.1        is 
   7843  1.1        is dst_sgl:
   7844  1.1        is 	clr.l		%d0
   7845  1.1        is 	mov.w		FTEMP_EX(%a0),%d0	# get exponent
   7846  1.1        is 	subi.w		&EXT_BIAS,%d0		# subtract extended precision bias
   7847  1.1        is 	addi.w		&SGL_BIAS,%d0		# add single precision bias
   7848  1.1        is 	tst.b		FTEMP_HI(%a0)		# is number a denorm?
   7849  1.1        is 	bmi.b		dst_get_supper		# no
   7850  1.1        is 	subq.w		&0x1,%d0		# yes; denorm bias = SGL_BIAS - 1
   7851  1.1        is dst_get_supper:
   7852  1.1        is 	swap		%d0			# put exp in upper word of d0
   7853  1.1        is 	lsl.l		&0x7,%d0		# shift it into single exp bits
   7854  1.1        is 	tst.b		FTEMP_EX(%a0)		# test sign
   7855  1.1        is 	bpl.b		dst_get_sman		# if positive, continue
   7856  1.1        is 	bset		&0x1f,%d0		# if negative, put in sign first
   7857  1.1        is dst_get_sman:
   7858  1.1        is 	mov.l		FTEMP_HI(%a0),%d1	# get ms mantissa
   7859  1.1        is 	andi.l		&0x7fffff00,%d1		# get upper 23 bits of ms
   7860  1.1        is 	lsr.l		&0x8,%d1		# and put them flush right
   7861  1.1        is 	or.l		%d1,%d0			# put these bits in ms word of single
   7862  1.1        is 	rts
   7863  1.1        is 
   7864  1.1        is ##############################################################################
   7865  1.1        is fout_pack:
   7866  1.1        is 	bsr.l		_calc_ea_fout		# fetch the <ea>
   7867  1.1        is 	mov.l		%a0,-(%sp)
   7868  1.1        is 
   7869  1.1        is 	mov.b		STAG(%a6),%d0		# fetch input type
   7870  1.1        is 	bne.w		fout_pack_not_norm	# input is not NORM
   7871  1.1        is 
   7872  1.1        is fout_pack_norm:
   7873  1.1        is 	btst		&0x4,EXC_CMDREG(%a6)	# static or dynamic?
   7874  1.1        is 	beq.b		fout_pack_s		# static
   7875  1.1        is 
   7876  1.1        is fout_pack_d:
   7877  1.1        is 	mov.b		1+EXC_CMDREG(%a6),%d1	# fetch dynamic reg
   7878  1.1        is 	lsr.b		&0x4,%d1
   7879  1.1        is 	andi.w		&0x7,%d1
   7880  1.1        is 
   7881  1.1        is 	bsr.l		fetch_dreg		# fetch Dn w/ k-factor
   7882  1.1        is 
   7883  1.1        is 	bra.b		fout_pack_type
   7884  1.1        is fout_pack_s:
   7885  1.1        is 	mov.b		1+EXC_CMDREG(%a6),%d0	# fetch static field
   7886  1.1        is 
   7887  1.1        is fout_pack_type:
   7888  1.1        is 	bfexts		%d0{&25:&7},%d0		# extract k-factor
   7889  1.1        is 	mov.l	%d0,-(%sp)
   7890  1.1        is 
   7891  1.1        is 	lea		FP_SRC(%a6),%a0		# pass: ptr to input
   7892  1.1        is 
   7893  1.1        is # bindec is currently scrambling FP_SRC for denorm inputs.
   7894  1.1        is # we'll have to change this, but for now, tough luck!!!
   7895  1.1        is 	bsr.l		bindec			# convert xprec to packed
   7896  1.1        is 
   7897  1.1        is #	andi.l		&0xcfff000f,FP_SCR0(%a6) # clear unused fields
   7898  1.1        is 	andi.l		&0xcffff00f,FP_SCR0(%a6) # clear unused fields
   7899  1.1        is 
   7900  1.1        is 	mov.l	(%sp)+,%d0
   7901  1.1        is 
   7902  1.1        is 	tst.b		3+FP_SCR0_EX(%a6)
   7903  1.1        is 	bne.b		fout_pack_set
   7904  1.1        is 	tst.l		FP_SCR0_HI(%a6)
   7905  1.1        is 	bne.b		fout_pack_set
   7906  1.1        is 	tst.l		FP_SCR0_LO(%a6)
   7907  1.1        is 	bne.b		fout_pack_set
   7908  1.1        is 
   7909  1.1        is # add the extra condition that only if the k-factor was zero, too, should
   7910  1.1        is # we zero the exponent
   7911  1.1        is 	tst.l		%d0
   7912  1.1        is 	bne.b		fout_pack_set
   7913  1.1        is # "mantissa" is all zero which means that the answer is zero. but, the '040
   7914  1.1        is # algorithm allows the exponent to be non-zero. the 881/2 do not. therefore,
   7915  1.1        is # if the mantissa is zero, I will zero the exponent, too.
   7916  1.1        is # the question now is whether the exponents sign bit is allowed to be non-zero
   7917  1.1        is # for a zero, also...
   7918  1.1        is 	andi.w		&0xf000,FP_SCR0(%a6)
   7919  1.1        is 
   7920  1.1        is fout_pack_set:
   7921  1.1        is 
   7922  1.1        is 	lea		FP_SCR0(%a6),%a0	# pass: src addr
   7923  1.1        is 
   7924  1.1        is fout_pack_write:
   7925  1.1        is 	mov.l		(%sp)+,%a1		# pass: dst addr
   7926  1.1        is 	mov.l		&0xc,%d0		# pass: opsize is 12 bytes
   7927  1.1        is 
   7928  1.1        is 	cmpi.b		SPCOND_FLG(%a6),&mda7_flg
   7929  1.1        is 	beq.b		fout_pack_a7
   7930  1.1        is 
   7931  1.1        is 	bsr.l		_dmem_write		# write ext prec number to memory
   7932  1.1        is 
   7933  1.1        is 	tst.l		%d1			# did dstore fail?
   7934  1.1        is 	bne.w		fout_ext_err		# yes
   7935  1.1        is 
   7936  1.1        is 	rts
   7937  1.1        is 
   7938  1.1        is # we don't want to do the write if the exception occurred in supervisor mode
   7939  1.1        is # so _mem_write2() handles this for us.
   7940  1.1        is fout_pack_a7:
   7941  1.1        is 	bsr.l		_mem_write2		# write ext prec number to memory
   7942  1.1        is 
   7943  1.1        is 	tst.l		%d1			# did dstore fail?
   7944  1.1        is 	bne.w		fout_ext_err		# yes
   7945  1.1        is 
   7946  1.1        is 	rts
   7947  1.1        is 
   7948  1.1        is fout_pack_not_norm:
   7949  1.1        is 	cmpi.b		%d0,&DENORM		# is it a DENORM?
   7950  1.1        is 	beq.w		fout_pack_norm		# yes
   7951  1.1        is 	lea		FP_SRC(%a6),%a0
   7952  1.1        is 	clr.w		2+FP_SRC_EX(%a6)
   7953  1.1        is 	cmpi.b		%d0,&SNAN		# is it an SNAN?
   7954  1.1        is 	beq.b		fout_pack_snan		# yes
   7955  1.1        is 	bra.b		fout_pack_write		# no
   7956  1.1        is 
   7957  1.1        is fout_pack_snan:
   7958  1.1        is 	ori.w		&snaniop2_mask,FPSR_EXCEPT(%a6) # set SNAN/AIOP
   7959  1.1        is 	bset		&0x6,FP_SRC_HI(%a6)	# set snan bit
   7960  1.1        is 	bra.b		fout_pack_write
   7961  1.1        is 
   7962  1.1        is #########################################################################
   7963  1.1        is # XDEF ****************************************************************	#
   7964  1.1        is # 	fmul(): emulates the fmul instruction				#
   7965  1.1        is #	fsmul(): emulates the fsmul instruction				#
   7966  1.1        is #	fdmul(): emulates the fdmul instruction				#
   7967  1.1        is #									#
   7968  1.1        is # XREF ****************************************************************	#
   7969  1.1        is #	scale_to_zero_src() - scale src exponent to zero		#
   7970  1.1        is #	scale_to_zero_dst() - scale dst exponent to zero		#
   7971  1.1        is #	unf_res() - return default underflow result			#
   7972  1.1        is #	ovf_res() - return default overflow result			#
   7973  1.1        is # 	res_qnan() - return QNAN result					#
   7974  1.1        is # 	res_snan() - return SNAN result					#
   7975  1.1        is #									#
   7976  1.1        is # INPUT ***************************************************************	#
   7977  1.1        is #	a0 = pointer to extended precision source operand		#
   7978  1.1        is #	a1 = pointer to extended precision destination operand		#
   7979  1.1        is #	d0  rnd prec,mode						#
   7980  1.1        is #									#
   7981  1.1        is # OUTPUT **************************************************************	#
   7982  1.1        is #	fp0 = result							#
   7983  1.1        is #	fp1 = EXOP (if exception occurred)				#
   7984  1.1        is #									#
   7985  1.1        is # ALGORITHM ***********************************************************	#
   7986  1.1        is #	Handle NANs, infinities, and zeroes as special cases. Divide	#
   7987  1.1        is # norms/denorms into ext/sgl/dbl precision.				#
   7988  1.1        is #	For norms/denorms, scale the exponents such that a multiply	#
   7989  1.1        is # instruction won't cause an exception. Use the regular fmul to		#
   7990  1.1        is # compute a result. Check if the regular operands would have taken	#
   7991  1.1        is # an exception. If so, return the default overflow/underflow result	#
   7992  1.1        is # and return the EXOP if exceptions are enabled. Else, scale the 	#
   7993  1.1        is # result operand to the proper exponent.				#
   7994  1.1        is #									#
   7995  1.1        is #########################################################################
   7996  1.1        is 
   7997  1.1        is 	align 		0x10
   7998  1.1        is tbl_fmul_ovfl:
   7999  1.1        is 	long		0x3fff - 0x7ffe		# ext_max
   8000  1.1        is 	long		0x3fff - 0x407e		# sgl_max
   8001  1.1        is 	long		0x3fff - 0x43fe		# dbl_max
   8002  1.1        is tbl_fmul_unfl:
   8003  1.1        is 	long		0x3fff + 0x0001		# ext_unfl
   8004  1.1        is 	long		0x3fff - 0x3f80		# sgl_unfl
   8005  1.1        is 	long		0x3fff - 0x3c00		# dbl_unfl
   8006  1.1        is 
   8007  1.1        is 	global		fsmul
   8008  1.1        is fsmul:
   8009  1.1        is 	andi.b		&0x30,%d0		# clear rnd prec
   8010  1.1        is 	ori.b		&s_mode*0x10,%d0	# insert sgl prec
   8011  1.1        is 	bra.b		fmul
   8012  1.1        is 
   8013  1.1        is 	global		fdmul
   8014  1.1        is fdmul:
   8015  1.1        is 	andi.b		&0x30,%d0
   8016  1.1        is 	ori.b		&d_mode*0x10,%d0	# insert dbl prec
   8017  1.1        is 
   8018  1.1        is 	global		fmul
   8019  1.1        is fmul:
   8020  1.1        is 	mov.l		%d0,L_SCR3(%a6)		# store rnd info
   8021  1.1        is 
   8022  1.1        is 	clr.w		%d1
   8023  1.1        is 	mov.b		DTAG(%a6),%d1
   8024  1.1        is 	lsl.b		&0x3,%d1
   8025  1.1        is 	or.b		STAG(%a6),%d1		# combine src tags
   8026  1.1        is 	bne.w		fmul_not_norm		# optimize on non-norm input
   8027  1.1        is 
   8028  1.1        is fmul_norm:
   8029  1.1        is 	mov.w		DST_EX(%a1),FP_SCR1_EX(%a6)
   8030  1.1        is 	mov.l		DST_HI(%a1),FP_SCR1_HI(%a6)
   8031  1.1        is 	mov.l		DST_LO(%a1),FP_SCR1_LO(%a6)
   8032  1.1        is 
   8033  1.1        is 	mov.w		SRC_EX(%a0),FP_SCR0_EX(%a6)
   8034  1.1        is 	mov.l		SRC_HI(%a0),FP_SCR0_HI(%a6)
   8035  1.1        is 	mov.l		SRC_LO(%a0),FP_SCR0_LO(%a6)
   8036  1.1        is 
   8037  1.1        is 	bsr.l		scale_to_zero_src	# scale src exponent
   8038  1.1        is 	mov.l		%d0,-(%sp)		# save scale factor 1
   8039  1.1        is 
   8040  1.1        is 	bsr.l		scale_to_zero_dst	# scale dst exponent
   8041  1.1        is 
   8042  1.1        is 	add.l		%d0,(%sp)		# SCALE_FACTOR = scale1 + scale2
   8043  1.1        is 
   8044  1.1        is 	mov.w		2+L_SCR3(%a6),%d1	# fetch precision
   8045  1.1        is 	lsr.b		&0x6,%d1		# shift to lo bits
   8046  1.1        is 	mov.l		(%sp)+,%d0		# load S.F.
   8047  1.1        is 	cmp.l		%d0,(tbl_fmul_ovfl.w,%pc,%d1.w*4) # would result ovfl?
   8048  1.1        is 	beq.w		fmul_may_ovfl		# result may rnd to overflow
   8049  1.1        is 	blt.w		fmul_ovfl		# result will overflow
   8050  1.1        is 
   8051  1.1        is 	cmp.l		%d0,(tbl_fmul_unfl.w,%pc,%d1.w*4) # would result unfl?
   8052  1.1        is 	beq.w		fmul_may_unfl		# result may rnd to no unfl
   8053  1.1        is 	bgt.w		fmul_unfl		# result will underflow
   8054  1.1        is 
   8055  1.1        is #
   8056  1.1        is # NORMAL:
   8057  1.1        is # - the result of the multiply operation will neither overflow nor underflow.
   8058  1.1        is # - do the multiply to the proper precision and rounding mode.
   8059  1.1        is # - scale the result exponent using the scale factor. if both operands were
   8060  1.1        is # normalized then we really don't need to go through this scaling. but for now,
   8061  1.1        is # this will do.
   8062  1.1        is #
   8063  1.1        is fmul_normal:
   8064  1.1        is 	fmovm.x		FP_SCR1(%a6),&0x80	# load dst operand
   8065  1.1        is 
   8066  1.1        is 	fmov.l		L_SCR3(%a6),%fpcr	# set FPCR
   8067  1.1        is 	fmov.l		&0x0,%fpsr		# clear FPSR
   8068  1.1        is 
   8069  1.1        is 	fmul.x		FP_SCR0(%a6),%fp0	# execute multiply
   8070  1.1        is 
   8071  1.1        is 	fmov.l		%fpsr,%d1		# save status
   8072  1.1        is 	fmov.l		&0x0,%fpcr		# clear FPCR
   8073  1.1        is 
   8074  1.1        is 	or.l		%d1,USER_FPSR(%a6)	# save INEX2,N
   8075  1.1        is 
   8076  1.1        is fmul_normal_exit:
   8077  1.1        is 	fmovm.x		&0x80,FP_SCR0(%a6)	# store out result
   8078  1.1        is 	mov.l		%d2,-(%sp)		# save d2
   8079  1.1        is 	mov.w		FP_SCR0_EX(%a6),%d1	# load {sgn,exp}
   8080  1.1        is 	mov.l		%d1,%d2			# make a copy
   8081  1.1        is 	andi.l		&0x7fff,%d1		# strip sign
   8082  1.1        is 	andi.w		&0x8000,%d2		# keep old sign
   8083  1.1        is 	sub.l		%d0,%d1			# add scale factor
   8084  1.1        is 	or.w		%d2,%d1			# concat old sign,new exp
   8085  1.1        is 	mov.w		%d1,FP_SCR0_EX(%a6)	# insert new exponent
   8086  1.1        is 	mov.l		(%sp)+,%d2		# restore d2
   8087  1.1        is 	fmovm.x		FP_SCR0(%a6),&0x80	# return default result in fp0
   8088  1.1        is 	rts
   8089  1.1        is 
   8090  1.1        is #
   8091  1.1        is # OVERFLOW:
   8092  1.1        is # - the result of the multiply operation is an overflow.
   8093  1.1        is # - do the multiply to the proper precision and rounding mode in order to
   8094  1.1        is # set the inexact bits.
   8095  1.1        is # - calculate the default result and return it in fp0.
   8096  1.1        is # - if overflow or inexact is enabled, we need a multiply result rounded to
   8097  1.1        is # extended precision. if the original operation was extended, then we have this
   8098  1.1        is # result. if the original operation was single or double, we have to do another
   8099  1.1        is # multiply using extended precision and the correct rounding mode. the result
   8100  1.1        is # of this operation then has its exponent scaled by -0x6000 to create the
   8101  1.1        is # exceptional operand.
   8102  1.1        is #
   8103  1.1        is fmul_ovfl:
   8104  1.1        is 	fmovm.x		FP_SCR1(%a6),&0x80	# load dst operand
   8105  1.1        is 
   8106  1.1        is 	fmov.l		L_SCR3(%a6),%fpcr	# set FPCR
   8107  1.1        is 	fmov.l		&0x0,%fpsr		# clear FPSR
   8108  1.1        is 
   8109  1.1        is 	fmul.x		FP_SCR0(%a6),%fp0	# execute multiply
   8110  1.1        is 
   8111  1.1        is 	fmov.l		%fpsr,%d1		# save status
   8112  1.1        is 	fmov.l		&0x0,%fpcr		# clear FPCR
   8113  1.1        is 
   8114  1.1        is 	or.l		%d1,USER_FPSR(%a6)	# save INEX2,N
   8115  1.1        is 
   8116  1.1        is # save setting this until now because this is where fmul_may_ovfl may jump in
   8117  1.1        is fmul_ovfl_tst:
   8118  1.1        is 	or.l		&ovfl_inx_mask,USER_FPSR(%a6) # set ovfl/aovfl/ainex
   8119  1.1        is 
   8120  1.1        is 	mov.b		FPCR_ENABLE(%a6),%d1
   8121  1.1        is 	andi.b		&0x13,%d1		# is OVFL or INEX enabled?
   8122  1.1        is 	bne.b		fmul_ovfl_ena		# yes
   8123  1.1        is 
   8124  1.1        is # calculate the default result
   8125  1.1        is fmul_ovfl_dis:
   8126  1.1        is 	btst		&neg_bit,FPSR_CC(%a6)	# is result negative?
   8127  1.1        is 	sne		%d1			# set sign param accordingly
   8128  1.1        is 	mov.l		L_SCR3(%a6),%d0		# pass rnd prec,mode
   8129  1.1        is 	bsr.l		ovf_res			# calculate default result
   8130  1.1        is 	or.b		%d0,FPSR_CC(%a6)	# set INF,N if applicable
   8131  1.1        is 	fmovm.x		(%a0),&0x80		# return default result in fp0
   8132  1.1        is 	rts
   8133  1.1        is 
   8134  1.1        is #
   8135  1.1        is # OVFL is enabled; Create EXOP:
   8136  1.1        is # - if precision is extended, then we have the EXOP. simply bias the exponent
   8137  1.1        is # with an extra -0x6000. if the precision is single or double, we need to
   8138  1.1        is # calculate a result rounded to extended precision.
   8139  1.1        is #
   8140  1.1        is fmul_ovfl_ena:
   8141  1.1        is 	mov.l		L_SCR3(%a6),%d1
   8142  1.1        is 	andi.b		&0xc0,%d1		# test the rnd prec
   8143  1.1        is 	bne.b		fmul_ovfl_ena_sd	# it's sgl or dbl
   8144  1.1        is 
   8145  1.1        is fmul_ovfl_ena_cont:
   8146  1.1        is 	fmovm.x		&0x80,FP_SCR0(%a6)	# move result to stack
   8147  1.1        is 
   8148  1.1        is 	mov.l		%d2,-(%sp)		# save d2
   8149  1.1        is 	mov.w		FP_SCR0_EX(%a6),%d1	# fetch {sgn,exp}
   8150  1.1        is 	mov.w		%d1,%d2			# make a copy
   8151  1.1        is 	andi.l		&0x7fff,%d1		# strip sign
   8152  1.1        is 	sub.l		%d0,%d1			# add scale factor
   8153  1.1        is 	subi.l		&0x6000,%d1		# subtract bias
   8154  1.1        is 	andi.w		&0x7fff,%d1		# clear sign bit
   8155  1.1        is 	andi.w		&0x8000,%d2		# keep old sign
   8156  1.1        is 	or.w		%d2,%d1			# concat old sign,new exp
   8157  1.1        is 	mov.w		%d1,FP_SCR0_EX(%a6)	# insert new exponent
   8158  1.1        is 	mov.l		(%sp)+,%d2		# restore d2
   8159  1.1        is 	fmovm.x		FP_SCR0(%a6),&0x40	# return EXOP in fp1
   8160  1.1        is 	bra.b		fmul_ovfl_dis
   8161  1.1        is 
   8162  1.1        is fmul_ovfl_ena_sd:
   8163  1.1        is 	fmovm.x		FP_SCR1(%a6),&0x80	# load dst operand
   8164  1.1        is 
   8165  1.1        is 	mov.l		L_SCR3(%a6),%d1
   8166  1.1        is 	andi.b		&0x30,%d1		# keep rnd mode only
   8167  1.1        is 	fmov.l		%d1,%fpcr		# set FPCR
   8168  1.1        is 
   8169  1.1        is 	fmul.x		FP_SCR0(%a6),%fp0	# execute multiply
   8170  1.1        is 
   8171  1.1        is 	fmov.l		&0x0,%fpcr		# clear FPCR
   8172  1.1        is 	bra.b		fmul_ovfl_ena_cont
   8173  1.1        is 
   8174  1.1        is #
   8175  1.1        is # may OVERFLOW:
   8176  1.1        is # - the result of the multiply operation MAY overflow.
   8177  1.1        is # - do the multiply to the proper precision and rounding mode in order to
   8178  1.1        is # set the inexact bits.
   8179  1.1        is # - calculate the default result and return it in fp0.
   8180  1.1        is #
   8181  1.1        is fmul_may_ovfl:
   8182  1.1        is 	fmovm.x		FP_SCR1(%a6),&0x80	# load dst op
   8183  1.1        is 
   8184  1.1        is 	fmov.l		L_SCR3(%a6),%fpcr	# set FPCR
   8185  1.1        is 	fmov.l		&0x0,%fpsr		# clear FPSR
   8186  1.1        is 
   8187  1.1        is 	fmul.x		FP_SCR0(%a6),%fp0	# execute multiply
   8188  1.1        is 
   8189  1.1        is 	fmov.l		%fpsr,%d1		# save status
   8190  1.1        is 	fmov.l		&0x0,%fpcr		# clear FPCR
   8191  1.1        is 
   8192  1.1        is 	or.l		%d1,USER_FPSR(%a6)	# save INEX2,N
   8193  1.1        is 
   8194  1.1        is 	fabs.x		%fp0,%fp1		# make a copy of result
   8195  1.1        is 	fcmp.b		%fp1,&0x2		# is |result| >= 2.b?
   8196  1.1        is 	fbge.w		fmul_ovfl_tst		# yes; overflow has occurred
   8197  1.1        is 
   8198  1.1        is # no, it didn't overflow; we have correct result
   8199  1.1        is 	bra.w		fmul_normal_exit
   8200  1.1        is 
   8201  1.1        is #
   8202  1.1        is # UNDERFLOW:
   8203  1.1        is # - the result of the multiply operation is an underflow.
   8204  1.1        is # - do the multiply to the proper precision and rounding mode in order to
   8205  1.1        is # set the inexact bits.
   8206  1.1        is # - calculate the default result and return it in fp0.
   8207  1.1        is # - if overflow or inexact is enabled, we need a multiply result rounded to
   8208  1.1        is # extended precision. if the original operation was extended, then we have this
   8209  1.1        is # result. if the original operation was single or double, we have to do another
   8210  1.1        is # multiply using extended precision and the correct rounding mode. the result
   8211  1.1        is # of this operation then has its exponent scaled by -0x6000 to create the
   8212  1.1        is # exceptional operand.
   8213  1.1        is #
   8214  1.1        is fmul_unfl:
   8215  1.1        is 	bset		&unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
   8216  1.1        is 
   8217  1.1        is # for fun, let's use only extended precision, round to zero. then, let
   8218  1.1        is # the unf_res() routine figure out all the rest.
   8219  1.1        is # will we get the correct answer.
   8220  1.1        is 	fmovm.x		FP_SCR1(%a6),&0x80	# load dst operand
   8221  1.1        is 
   8222  1.1        is 	fmov.l		&rz_mode*0x10,%fpcr	# set FPCR
   8223  1.1        is 	fmov.l		&0x0,%fpsr		# clear FPSR
   8224  1.1        is 
   8225  1.1        is 	fmul.x		FP_SCR0(%a6),%fp0	# execute multiply
   8226  1.1        is 
   8227  1.1        is 	fmov.l		%fpsr,%d1		# save status
   8228  1.1        is 	fmov.l		&0x0,%fpcr		# clear FPCR
   8229  1.1        is 
   8230  1.1        is 	or.l		%d1,USER_FPSR(%a6)	# save INEX2,N
   8231  1.1        is 
   8232  1.1        is 	mov.b		FPCR_ENABLE(%a6),%d1
   8233  1.1        is 	andi.b		&0x0b,%d1		# is UNFL or INEX enabled?
   8234  1.1        is 	bne.b		fmul_unfl_ena		# yes
   8235  1.1        is 
   8236  1.1        is fmul_unfl_dis:
   8237  1.1        is 	fmovm.x		&0x80,FP_SCR0(%a6)	# store out result
   8238  1.1        is 
   8239  1.1        is 	lea		FP_SCR0(%a6),%a0	# pass: result addr
   8240  1.1        is 	mov.l		L_SCR3(%a6),%d1		# pass: rnd prec,mode
   8241  1.1        is 	bsr.l		unf_res			# calculate default result
   8242  1.1        is 	or.b		%d0,FPSR_CC(%a6)	# unf_res2 may have set 'Z'
   8243  1.1        is 	fmovm.x		FP_SCR0(%a6),&0x80	# return default result in fp0
   8244  1.1        is 	rts
   8245  1.1        is 
   8246  1.1        is #
   8247  1.1        is # UNFL is enabled.
   8248  1.1        is #
   8249  1.1        is fmul_unfl_ena:
   8250  1.1        is 	fmovm.x		FP_SCR1(%a6),&0x40	# load dst op
   8251  1.1        is 
   8252  1.1        is 	mov.l		L_SCR3(%a6),%d1
   8253  1.1        is 	andi.b		&0xc0,%d1		# is precision extended?
   8254  1.1        is 	bne.b		fmul_unfl_ena_sd	# no, sgl or dbl
   8255  1.1        is 
   8256  1.1        is # if the rnd mode is anything but RZ, then we have to re-do the above
   8257  1.3       wiz # multiplication because we used RZ for all.
   8258  1.1        is 	fmov.l		L_SCR3(%a6),%fpcr	# set FPCR
   8259  1.1        is 
   8260  1.1        is fmul_unfl_ena_cont:
   8261  1.1        is 	fmov.l		&0x0,%fpsr		# clear FPSR
   8262  1.1        is 
   8263  1.1        is 	fmul.x		FP_SCR0(%a6),%fp1	# execute multiply
   8264  1.1        is 
   8265  1.1        is 	fmov.l		&0x0,%fpcr		# clear FPCR
   8266  1.1        is 
   8267  1.1        is 	fmovm.x		&0x40,FP_SCR0(%a6)	# save result to stack
   8268  1.1        is 	mov.l		%d2,-(%sp)		# save d2
   8269  1.1        is 	mov.w		FP_SCR0_EX(%a6),%d1	# fetch {sgn,exp}
   8270  1.1        is 	mov.l		%d1,%d2			# make a copy
   8271  1.1        is 	andi.l		&0x7fff,%d1		# strip sign
   8272  1.1        is 	andi.w		&0x8000,%d2		# keep old sign
   8273  1.1        is 	sub.l		%d0,%d1			# add scale factor
   8274  1.1        is 	addi.l		&0x6000,%d1		# add bias
   8275  1.1        is 	andi.w		&0x7fff,%d1
   8276  1.1        is 	or.w		%d2,%d1			# concat old sign,new exp
   8277  1.1        is 	mov.w		%d1,FP_SCR0_EX(%a6)	# insert new exponent
   8278  1.1        is 	mov.l		(%sp)+,%d2		# restore d2
   8279  1.1        is 	fmovm.x		FP_SCR0(%a6),&0x40	# return EXOP in fp1
   8280  1.1        is 	bra.w		fmul_unfl_dis
   8281  1.1        is 
   8282  1.1        is fmul_unfl_ena_sd:
   8283  1.1        is 	mov.l		L_SCR3(%a6),%d1
   8284  1.1        is 	andi.b		&0x30,%d1		# use only rnd mode
   8285  1.1        is 	fmov.l		%d1,%fpcr		# set FPCR
   8286  1.1        is 
   8287  1.1        is 	bra.b		fmul_unfl_ena_cont
   8288  1.1        is 
   8289  1.1        is # MAY UNDERFLOW:
   8290  1.1        is # -use the correct rounding mode and precision. this code favors operations
   8291  1.1        is # that do not underflow.
   8292  1.1        is fmul_may_unfl:
   8293  1.1        is 	fmovm.x		FP_SCR1(%a6),&0x80	# load dst operand
   8294  1.1        is 
   8295  1.1        is 	fmov.l		L_SCR3(%a6),%fpcr	# set FPCR
   8296  1.1        is 	fmov.l		&0x0,%fpsr		# clear FPSR
   8297  1.1        is 
   8298  1.1        is 	fmul.x		FP_SCR0(%a6),%fp0	# execute multiply
   8299  1.1        is 
   8300  1.1        is 	fmov.l		%fpsr,%d1		# save status
   8301  1.1        is 	fmov.l		&0x0,%fpcr		# clear FPCR
   8302  1.1        is 
   8303  1.1        is 	or.l		%d1,USER_FPSR(%a6)	# save INEX2,N
   8304  1.1        is 
   8305  1.1        is 	fabs.x		%fp0,%fp1		# make a copy of result
   8306  1.1        is 	fcmp.b		%fp1,&0x2		# is |result| > 2.b?
   8307  1.1        is 	fbgt.w		fmul_normal_exit	# no; no underflow occurred
   8308  1.1        is 	fblt.w		fmul_unfl		# yes; underflow occurred
   8309  1.1        is 
   8310  1.1        is #
   8311  1.1        is # we still don't know if underflow occurred. result is ~ equal to 2. but,
   8312  1.1        is # we don't know if the result was an underflow that rounded up to a 2 or
   8313  1.1        is # a normalized number that rounded down to a 2. so, redo the entire operation
   8314  1.1        is # using RZ as the rounding mode to see what the pre-rounded result is.
   8315  1.1        is # this case should be relatively rare.
   8316  1.1        is #
   8317  1.1        is 	fmovm.x		FP_SCR1(%a6),&0x40	# load dst operand
   8318  1.1        is 
   8319  1.1        is 	mov.l		L_SCR3(%a6),%d1
   8320  1.1        is 	andi.b		&0xc0,%d1		# keep rnd prec
   8321  1.1        is 	ori.b		&rz_mode*0x10,%d1	# insert RZ
   8322  1.1        is 
   8323  1.1        is 	fmov.l		%d1,%fpcr		# set FPCR
   8324  1.1        is 	fmov.l		&0x0,%fpsr		# clear FPSR
   8325  1.1        is 
   8326  1.1        is 	fmul.x		FP_SCR0(%a6),%fp1	# execute multiply
   8327  1.1        is 
   8328  1.1        is 	fmov.l		&0x0,%fpcr		# clear FPCR
   8329  1.1        is 	fabs.x		%fp1			# make absolute value
   8330  1.1        is 	fcmp.b		%fp1,&0x2		# is |result| < 2.b?
   8331  1.1        is 	fbge.w		fmul_normal_exit	# no; no underflow occurred
   8332  1.1        is 	bra.w		fmul_unfl		# yes, underflow occurred
   8333  1.1        is 
   8334  1.1        is ################################################################################
   8335  1.1        is 
   8336  1.1        is #
   8337  1.1        is # Multiply: inputs are not both normalized; what are they?
   8338  1.1        is #
   8339  1.1        is fmul_not_norm:
   8340  1.1        is 	mov.w		(tbl_fmul_op.b,%pc,%d1.w*2),%d1
   8341  1.1        is 	jmp		(tbl_fmul_op.b,%pc,%d1.w)
   8342  1.1        is 
   8343  1.1        is 	swbeg		&48
   8344  1.1        is tbl_fmul_op:
   8345  1.1        is 	short		fmul_norm	- tbl_fmul_op # NORM x NORM
   8346  1.1        is 	short		fmul_zero	- tbl_fmul_op # NORM x ZERO
   8347  1.1        is 	short		fmul_inf_src	- tbl_fmul_op # NORM x INF
   8348  1.1        is 	short		fmul_res_qnan	- tbl_fmul_op # NORM x QNAN
   8349  1.1        is 	short		fmul_norm	- tbl_fmul_op # NORM x DENORM
   8350  1.1        is 	short		fmul_res_snan	- tbl_fmul_op # NORM x SNAN
   8351  1.1        is 	short		tbl_fmul_op	- tbl_fmul_op #
   8352  1.1        is 	short		tbl_fmul_op	- tbl_fmul_op #
   8353  1.1        is 
   8354  1.1        is 	short		fmul_zero	- tbl_fmul_op # ZERO x NORM
   8355  1.1        is 	short		fmul_zero	- tbl_fmul_op # ZERO x ZERO
   8356  1.1        is 	short		fmul_res_operr	- tbl_fmul_op # ZERO x INF
   8357  1.1        is 	short		fmul_res_qnan	- tbl_fmul_op # ZERO x QNAN
   8358  1.1        is 	short		fmul_zero	- tbl_fmul_op # ZERO x DENORM
   8359  1.1        is 	short		fmul_res_snan	- tbl_fmul_op # ZERO x SNAN
   8360  1.1        is 	short		tbl_fmul_op	- tbl_fmul_op #
   8361  1.1        is 	short		tbl_fmul_op	- tbl_fmul_op #
   8362  1.1        is 
   8363  1.1        is 	short		fmul_inf_dst	- tbl_fmul_op # INF x NORM
   8364  1.1        is 	short		fmul_res_operr	- tbl_fmul_op # INF x ZERO
   8365  1.1        is 	short		fmul_inf_dst	- tbl_fmul_op # INF x INF
   8366  1.1        is 	short		fmul_res_qnan	- tbl_fmul_op # INF x QNAN
   8367  1.1        is 	short		fmul_inf_dst	- tbl_fmul_op # INF x DENORM
   8368  1.1        is 	short		fmul_res_snan	- tbl_fmul_op # INF x SNAN
   8369  1.1        is 	short		tbl_fmul_op	- tbl_fmul_op #
   8370  1.1        is 	short		tbl_fmul_op	- tbl_fmul_op #
   8371  1.1        is 
   8372  1.1        is 	short		fmul_res_qnan	- tbl_fmul_op # QNAN x NORM
   8373  1.1        is 	short		fmul_res_qnan	- tbl_fmul_op # QNAN x ZERO
   8374  1.1        is 	short		fmul_res_qnan	- tbl_fmul_op # QNAN x INF
   8375  1.1        is 	short		fmul_res_qnan	- tbl_fmul_op # QNAN x QNAN
   8376  1.1        is 	short		fmul_res_qnan	- tbl_fmul_op # QNAN x DENORM
   8377  1.1        is 	short		fmul_res_snan	- tbl_fmul_op # QNAN x SNAN
   8378  1.1        is 	short		tbl_fmul_op	- tbl_fmul_op #
   8379  1.1        is 	short		tbl_fmul_op	- tbl_fmul_op #
   8380  1.1        is 
   8381  1.1        is 	short		fmul_norm	- tbl_fmul_op # NORM x NORM
   8382  1.1        is 	short		fmul_zero	- tbl_fmul_op # NORM x ZERO
   8383  1.1        is 	short		fmul_inf_src	- tbl_fmul_op # NORM x INF
   8384  1.1        is 	short		fmul_res_qnan	- tbl_fmul_op # NORM x QNAN
   8385  1.1        is 	short		fmul_norm	- tbl_fmul_op # NORM x DENORM
   8386  1.1        is 	short		fmul_res_snan	- tbl_fmul_op # NORM x SNAN
   8387  1.1        is 	short		tbl_fmul_op	- tbl_fmul_op #
   8388  1.1        is 	short		tbl_fmul_op	- tbl_fmul_op #
   8389  1.1        is 
   8390  1.1        is 	short		fmul_res_snan	- tbl_fmul_op # SNAN x NORM
   8391  1.1        is 	short		fmul_res_snan	- tbl_fmul_op # SNAN x ZERO
   8392  1.1        is 	short		fmul_res_snan	- tbl_fmul_op # SNAN x INF
   8393  1.1        is 	short		fmul_res_snan	- tbl_fmul_op # SNAN x QNAN
   8394  1.1        is 	short		fmul_res_snan	- tbl_fmul_op # SNAN x DENORM
   8395  1.1        is 	short		fmul_res_snan	- tbl_fmul_op # SNAN x SNAN
   8396  1.1        is 	short		tbl_fmul_op	- tbl_fmul_op #
   8397  1.1        is 	short		tbl_fmul_op	- tbl_fmul_op #
   8398  1.1        is 
   8399  1.1        is fmul_res_operr:
   8400  1.1        is 	bra.l		res_operr
   8401  1.1        is fmul_res_snan:
   8402  1.1        is 	bra.l		res_snan
   8403  1.1        is fmul_res_qnan:
   8404  1.1        is 	bra.l		res_qnan
   8405  1.1        is 
   8406  1.1        is #
   8407  1.1        is # Multiply: (Zero x Zero) || (Zero x norm) || (Zero x denorm)
   8408  1.1        is #
   8409  1.1        is 	global		fmul_zero		# global for fsglmul
   8410  1.1        is fmul_zero:
   8411  1.1        is 	mov.b		SRC_EX(%a0),%d0		# exclusive or the signs
   8412  1.1        is 	mov.b		DST_EX(%a1),%d1
   8413  1.1        is 	eor.b		%d0,%d1
   8414  1.1        is 	bpl.b		fmul_zero_p		# result ZERO is pos.
   8415  1.1        is fmul_zero_n:
   8416  1.1        is 	fmov.s		&0x80000000,%fp0	# load -ZERO
   8417  1.1        is 	mov.b		&z_bmask+neg_bmask,FPSR_CC(%a6) # set Z/N
   8418  1.1        is 	rts
   8419  1.1        is fmul_zero_p:
   8420  1.1        is 	fmov.s		&0x00000000,%fp0	# load +ZERO
   8421  1.1        is 	mov.b		&z_bmask,FPSR_CC(%a6)	# set Z
   8422  1.1        is 	rts
   8423  1.1        is 
   8424  1.1        is #
   8425  1.1        is # Multiply: (inf x inf) || (inf x norm) || (inf x denorm)
   8426  1.1        is #
   8427  1.1        is # Note: The j-bit for an infinity is a don't-care. However, to be
   8428  1.1        is # strictly compatible w/ the 68881/882, we make sure to return an
   8429  1.1        is # INF w/ the j-bit set if the input INF j-bit was set. Destination
   8430  1.1        is # INFs take priority.
   8431  1.1        is #
   8432  1.1        is 	global		fmul_inf_dst		# global for fsglmul
   8433  1.1        is fmul_inf_dst:
   8434  1.1        is 	fmovm.x		DST(%a1),&0x80		# return INF result in fp0
   8435  1.1        is 	mov.b		SRC_EX(%a0),%d0		# exclusive or the signs
   8436  1.1        is 	mov.b		DST_EX(%a1),%d1
   8437  1.1        is 	eor.b		%d0,%d1
   8438  1.1        is 	bpl.b		fmul_inf_dst_p		# result INF is pos.
   8439  1.1        is fmul_inf_dst_n:
   8440  1.1        is 	fabs.x		%fp0			# clear result sign
   8441  1.1        is 	fneg.x		%fp0			# set result sign
   8442  1.1        is 	mov.b		&inf_bmask+neg_bmask,FPSR_CC(%a6) # set INF/N
   8443  1.1        is 	rts
   8444  1.1        is fmul_inf_dst_p:
   8445  1.1        is 	fabs.x		%fp0			# clear result sign
   8446  1.1        is 	mov.b		&inf_bmask,FPSR_CC(%a6)	# set INF
   8447  1.1        is 	rts
   8448  1.1        is 
   8449  1.1        is 	global		fmul_inf_src		# global for fsglmul
   8450  1.1        is fmul_inf_src:
   8451  1.1        is 	fmovm.x		SRC(%a0),&0x80		# return INF result in fp0
   8452  1.1        is 	mov.b		SRC_EX(%a0),%d0		# exclusive or the signs
   8453  1.1        is 	mov.b		DST_EX(%a1),%d1
   8454  1.1        is 	eor.b		%d0,%d1
   8455  1.1        is 	bpl.b		fmul_inf_dst_p		# result INF is pos.
   8456  1.1        is 	bra.b		fmul_inf_dst_n
   8457  1.1        is 
   8458  1.1        is #########################################################################
   8459  1.1        is # XDEF ****************************************************************	#
   8460  1.1        is #	fin(): emulates the fmove instruction				#
   8461  1.1        is #	fsin(): emulates the fsmove instruction				#
   8462  1.1        is #	fdin(): emulates the fdmove instruction				#
   8463  1.1        is #									#
   8464  1.1        is # XREF ****************************************************************	#
   8465  1.1        is #	norm() - normalize mantissa for EXOP on denorm			#
   8466  1.1        is #	scale_to_zero_src() - scale src exponent to zero		#
   8467  1.1        is #	ovf_res() - return default overflow result			#
   8468  1.1        is # 	unf_res() - return default underflow result			#
   8469  1.1        is #	res_qnan_1op() - return QNAN result				#
   8470  1.1        is #	res_snan_1op() - return SNAN result				#
   8471  1.1        is #									#
   8472  1.1        is # INPUT ***************************************************************	#
   8473  1.1        is #	a0 = pointer to extended precision source operand		#
   8474  1.1        is #	d0 = round prec/mode						#
   8475  1.1        is # 									#
   8476  1.1        is # OUTPUT **************************************************************	#
   8477  1.1        is #	fp0 = result							#
   8478  1.1        is #	fp1 = EXOP (if exception occurred)				#
   8479  1.1        is #									#
   8480  1.1        is # ALGORITHM ***********************************************************	#
   8481  1.1        is # 	Handle NANs, infinities, and zeroes as special cases. Divide	#
   8482  1.1        is # norms into extended, single, and double precision.			#
   8483  1.1        is # 	Norms can be emulated w/ a regular fmove instruction. For	#
   8484  1.1        is # sgl/dbl, must scale exponent and perform an "fmove". Check to see	#
   8485  1.1        is # if the result would have overflowed/underflowed. If so, use unf_res()	#
   8486  1.1        is # or ovf_res() to return the default result. Also return EXOP if	#
   8487  1.1        is # exception is enabled. If no exception, return the default result.	#
   8488  1.1        is #	Unnorms don't pass through here.				#
   8489  1.1        is #									#
   8490  1.1        is #########################################################################
   8491  1.1        is 
   8492  1.1        is 	global		fsin
   8493  1.1        is fsin:
   8494  1.1        is 	andi.b		&0x30,%d0		# clear rnd prec
   8495  1.1        is 	ori.b		&s_mode*0x10,%d0	# insert sgl precision
   8496  1.1        is 	bra.b		fin
   8497  1.1        is 
   8498  1.1        is 	global		fdin
   8499  1.1        is fdin:
   8500  1.1        is 	andi.b		&0x30,%d0		# clear rnd prec
   8501  1.1        is 	ori.b		&d_mode*0x10,%d0	# insert dbl precision
   8502  1.1        is 
   8503  1.1        is 	global		fin
   8504  1.1        is fin:
   8505  1.1        is 	mov.l		%d0,L_SCR3(%a6)		# store rnd info
   8506  1.1        is 
   8507  1.1        is 	mov.b		STAG(%a6),%d1		# fetch src optype tag
   8508  1.1        is 	bne.w		fin_not_norm		# optimize on non-norm input
   8509  1.1        is 
   8510  1.1        is #
   8511  1.1        is # FP MOVE IN: NORMs and DENORMs ONLY!
   8512  1.1        is #
   8513  1.1        is fin_norm:
   8514  1.1        is 	andi.b		&0xc0,%d0		# is precision extended?
   8515  1.1        is 	bne.w		fin_not_ext		# no, so go handle dbl or sgl
   8516  1.1        is 
   8517  1.1        is #
   8518  1.1        is # precision selected is extended. so...we cannot get an underflow
   8519  1.1        is # or overflow because of rounding to the correct precision. so...
   8520  1.1        is # skip the scaling and unscaling...
   8521  1.1        is #
   8522  1.1        is 	tst.b		SRC_EX(%a0)		# is the operand negative?
   8523  1.1        is 	bpl.b		fin_norm_done		# no
   8524  1.1        is 	bset		&neg_bit,FPSR_CC(%a6)	# yes, so set 'N' ccode bit
   8525  1.1        is fin_norm_done:
   8526  1.1        is 	fmovm.x		SRC(%a0),&0x80		# return result in fp0
   8527  1.1        is 	rts
   8528  1.1        is 
   8529  1.1        is #
   8530  1.1        is # for an extended precision DENORM, the UNFL exception bit is set
   8531  1.1        is # the accrued bit is NOT set in this instance(no inexactness!)
   8532  1.1        is #
   8533  1.1        is fin_denorm:
   8534  1.1        is 	andi.b		&0xc0,%d0		# is precision extended?
   8535  1.1        is 	bne.w		fin_not_ext		# no, so go handle dbl or sgl
   8536  1.1        is 
   8537  1.1        is 	bset		&unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
   8538  1.1        is 	tst.b		SRC_EX(%a0)		# is the operand negative?
   8539  1.1        is 	bpl.b		fin_denorm_done		# no
   8540  1.1        is 	bset		&neg_bit,FPSR_CC(%a6)	# yes, so set 'N' ccode bit
   8541  1.1        is fin_denorm_done:
   8542  1.1        is 	fmovm.x		SRC(%a0),&0x80		# return result in fp0
   8543  1.1        is 	btst		&unfl_bit,FPCR_ENABLE(%a6) # is UNFL enabled?
   8544  1.1        is 	bne.b		fin_denorm_unfl_ena	# yes
   8545  1.1        is 	rts
   8546  1.1        is 
   8547  1.1        is #
   8548  1.1        is # the input is an extended DENORM and underflow is enabled in the FPCR.
   8549  1.1        is # normalize the mantissa and add the bias of 0x6000 to the resulting negative
   8550  1.1        is # exponent and insert back into the operand.
   8551  1.1        is #
   8552  1.1        is fin_denorm_unfl_ena:
   8553  1.1        is 	mov.w		SRC_EX(%a0),FP_SCR0_EX(%a6)
   8554  1.1        is 	mov.l		SRC_HI(%a0),FP_SCR0_HI(%a6)
   8555  1.1        is 	mov.l		SRC_LO(%a0),FP_SCR0_LO(%a6)
   8556  1.1        is 	lea		FP_SCR0(%a6),%a0	# pass: ptr to operand
   8557  1.1        is 	bsr.l		norm			# normalize result
   8558  1.1        is 	neg.w		%d0			# new exponent = -(shft val)
   8559  1.1        is 	addi.w		&0x6000,%d0		# add new bias to exponent
   8560  1.1        is 	mov.w		FP_SCR0_EX(%a6),%d1	# fetch old sign,exp
   8561  1.1        is 	andi.w		&0x8000,%d1		# keep old sign
   8562  1.1        is 	andi.w		&0x7fff,%d0		# clear sign position
   8563  1.1        is 	or.w		%d1,%d0			# concat new exo,old sign
   8564  1.1        is 	mov.w		%d0,FP_SCR0_EX(%a6)	# insert new exponent
   8565  1.1        is 	fmovm.x		FP_SCR0(%a6),&0x40	# return EXOP in fp1
   8566  1.1        is 	rts
   8567  1.1        is 
   8568  1.1        is #
   8569  1.1        is # operand is to be rounded to single or double precision
   8570  1.1        is #
   8571  1.1        is fin_not_ext:
   8572  1.1        is 	cmpi.b		%d0,&s_mode*0x10 	# separate sgl/dbl prec
   8573  1.1        is 	bne.b		fin_dbl
   8574  1.1        is 
   8575  1.1        is #
   8576  1.1        is # operand is to be rounded to single precision
   8577  1.1        is #
   8578  1.1        is fin_sgl:
   8579  1.1        is 	mov.w		SRC_EX(%a0),FP_SCR0_EX(%a6)
   8580  1.1        is 	mov.l		SRC_HI(%a0),FP_SCR0_HI(%a6)
   8581  1.1        is 	mov.l		SRC_LO(%a0),FP_SCR0_LO(%a6)
   8582  1.1        is 	bsr.l		scale_to_zero_src	# calculate scale factor
   8583  1.1        is 
   8584  1.1        is 	cmpi.l		%d0,&0x3fff-0x3f80	# will move in underflow?
   8585  1.1        is 	bge.w		fin_sd_unfl		# yes; go handle underflow
   8586  1.1        is 	cmpi.l		%d0,&0x3fff-0x407e	# will move in overflow?
   8587  1.1        is 	beq.w		fin_sd_may_ovfl		# maybe; go check
   8588  1.1        is 	blt.w		fin_sd_ovfl		# yes; go handle overflow
   8589  1.1        is 
   8590  1.1        is #
   8591  1.1        is # operand will NOT overflow or underflow when moved into the fp reg file
   8592  1.1        is #
   8593  1.1        is fin_sd_normal:
   8594  1.1        is 	fmov.l		&0x0,%fpsr		# clear FPSR
   8595  1.1        is 	fmov.l		L_SCR3(%a6),%fpcr	# set FPCR
   8596  1.1        is 
   8597  1.1        is 	fmov.x		FP_SCR0(%a6),%fp0	# perform move
   8598  1.1        is 
   8599  1.1        is 	fmov.l		%fpsr,%d1		# save FPSR
   8600  1.1        is 	fmov.l		&0x0,%fpcr		# clear FPCR
   8601  1.1        is 
   8602  1.1        is 	or.l		%d1,USER_FPSR(%a6)	# save INEX2,N
   8603  1.1        is 
   8604  1.1        is fin_sd_normal_exit:
   8605  1.1        is 	mov.l		%d2,-(%sp)		# save d2
   8606  1.1        is 	fmovm.x		&0x80,FP_SCR0(%a6)	# store out result
   8607  1.1        is 	mov.w		FP_SCR0_EX(%a6),%d1	# load {sgn,exp}
   8608  1.1        is 	mov.w		%d1,%d2			# make a copy
   8609  1.1        is 	andi.l		&0x7fff,%d1		# strip sign
   8610  1.1        is 	sub.l		%d0,%d1			# add scale factor
   8611  1.1        is 	andi.w		&0x8000,%d2		# keep old sign
   8612  1.1        is 	or.w		%d1,%d2			# concat old sign,new exponent
   8613  1.1        is 	mov.w		%d2,FP_SCR0_EX(%a6)	# insert new exponent
   8614  1.1        is 	mov.l		(%sp)+,%d2		# restore d2
   8615  1.1        is 	fmovm.x		FP_SCR0(%a6),&0x80	# return result in fp0
   8616  1.1        is 	rts
   8617  1.1        is 
   8618  1.1        is #
   8619  1.1        is # operand is to be rounded to double precision
   8620  1.1        is #
   8621  1.1        is fin_dbl:
   8622  1.1        is 	mov.w		SRC_EX(%a0),FP_SCR0_EX(%a6)
   8623  1.1        is 	mov.l		SRC_HI(%a0),FP_SCR0_HI(%a6)
   8624  1.1        is 	mov.l		SRC_LO(%a0),FP_SCR0_LO(%a6)
   8625  1.1        is 	bsr.l		scale_to_zero_src	# calculate scale factor
   8626  1.1        is 
   8627  1.1        is 	cmpi.l		%d0,&0x3fff-0x3c00	# will move in underflow?
   8628  1.1        is 	bge.w		fin_sd_unfl		# yes; go handle underflow
   8629  1.1        is 	cmpi.l		%d0,&0x3fff-0x43fe	# will move in overflow?
   8630  1.1        is 	beq.w		fin_sd_may_ovfl		# maybe; go check
   8631  1.1        is 	blt.w		fin_sd_ovfl		# yes; go handle overflow
   8632  1.1        is 	bra.w		fin_sd_normal		# no; ho handle normalized op
   8633  1.1        is 
   8634  1.1        is #
   8635  1.1        is # operand WILL underflow when moved in to the fp register file
   8636  1.1        is #
   8637  1.1        is fin_sd_unfl:
   8638  1.1        is 	bset		&unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
   8639  1.1        is 
   8640  1.1        is 	tst.b		FP_SCR0_EX(%a6)		# is operand negative?
   8641  1.1        is 	bpl.b		fin_sd_unfl_tst
   8642  1.1        is 	bset		&neg_bit,FPSR_CC(%a6)	# set 'N' ccode bit
   8643  1.1        is 
   8644  1.1        is # if underflow or inexact is enabled, then go calculate the EXOP first.
   8645  1.1        is fin_sd_unfl_tst:
   8646  1.1        is 	mov.b		FPCR_ENABLE(%a6),%d1
   8647  1.1        is 	andi.b		&0x0b,%d1		# is UNFL or INEX enabled?
   8648  1.1        is 	bne.b		fin_sd_unfl_ena		# yes
   8649  1.1        is 
   8650  1.1        is fin_sd_unfl_dis:
   8651  1.1        is 	lea		FP_SCR0(%a6),%a0	# pass: result addr
   8652  1.1        is 	mov.l		L_SCR3(%a6),%d1		# pass: rnd prec,mode
   8653  1.1        is 	bsr.l		unf_res			# calculate default result
   8654  1.1        is 	or.b		%d0,FPSR_CC(%a6)	# unf_res may have set 'Z'
   8655  1.1        is 	fmovm.x		FP_SCR0(%a6),&0x80	# return default result in fp0
   8656  1.1        is 	rts
   8657  1.1        is 
   8658  1.1        is #
   8659  1.1        is # operand will underflow AND underflow or inexact is enabled.
   8660  1.1        is # therefore, we must return the result rounded to extended precision.
   8661  1.1        is #
   8662  1.1        is fin_sd_unfl_ena:
   8663  1.1        is 	mov.l		FP_SCR0_HI(%a6),FP_SCR1_HI(%a6)
   8664  1.1        is 	mov.l		FP_SCR0_LO(%a6),FP_SCR1_LO(%a6)
   8665  1.1        is 	mov.w		FP_SCR0_EX(%a6),%d1	# load current exponent
   8666  1.1        is 
   8667  1.1        is 	mov.l		%d2,-(%sp)		# save d2
   8668  1.1        is 	mov.w		%d1,%d2			# make a copy
   8669  1.1        is 	andi.l		&0x7fff,%d1		# strip sign
   8670  1.1        is 	sub.l		%d0,%d1			# subtract scale factor
   8671  1.1        is 	andi.w		&0x8000,%d2		# extract old sign
   8672  1.1        is 	addi.l		&0x6000,%d1		# add new bias
   8673  1.1        is 	andi.w		&0x7fff,%d1
   8674  1.1        is 	or.w		%d1,%d2			# concat old sign,new exp
   8675  1.1        is 	mov.w		%d2,FP_SCR1_EX(%a6)	# insert new exponent
   8676  1.1        is 	fmovm.x		FP_SCR1(%a6),&0x40	# return EXOP in fp1
   8677  1.1        is 	mov.l		(%sp)+,%d2		# restore d2
   8678  1.1        is 	bra.b		fin_sd_unfl_dis
   8679  1.1        is 
   8680  1.1        is #
   8681  1.1        is # operand WILL overflow.
   8682  1.1        is #
   8683  1.1        is fin_sd_ovfl:
   8684  1.1        is 	fmov.l		&0x0,%fpsr		# clear FPSR
   8685  1.1        is 	fmov.l		L_SCR3(%a6),%fpcr	# set FPCR
   8686  1.1        is 
   8687  1.1        is 	fmov.x		FP_SCR0(%a6),%fp0	# perform move
   8688  1.1        is 
   8689  1.1        is 	fmov.l		&0x0,%fpcr		# clear FPCR
   8690  1.1        is 	fmov.l		%fpsr,%d1		# save FPSR
   8691  1.1        is 
   8692  1.1        is 	or.l		%d1,USER_FPSR(%a6)	# save INEX2,N
   8693  1.1        is 
   8694  1.1        is fin_sd_ovfl_tst:
   8695  1.1        is 	or.l		&ovfl_inx_mask,USER_FPSR(%a6) # set ovfl/aovfl/ainex
   8696  1.1        is 
   8697  1.1        is 	mov.b		FPCR_ENABLE(%a6),%d1
   8698  1.1        is 	andi.b		&0x13,%d1		# is OVFL or INEX enabled?
   8699  1.1        is 	bne.b		fin_sd_ovfl_ena		# yes
   8700  1.1        is 
   8701  1.1        is #
   8702  1.1        is # OVFL is not enabled; therefore, we must create the default result by
   8703  1.1        is # calling ovf_res().
   8704  1.1        is #
   8705  1.1        is fin_sd_ovfl_dis:
   8706  1.1        is 	btst		&neg_bit,FPSR_CC(%a6)	# is result negative?
   8707  1.1        is 	sne		%d1			# set sign param accordingly
   8708  1.1        is 	mov.l		L_SCR3(%a6),%d0		# pass: prec,mode
   8709  1.1        is 	bsr.l		ovf_res			# calculate default result
   8710  1.1        is 	or.b		%d0,FPSR_CC(%a6)	# set INF,N if applicable
   8711  1.1        is 	fmovm.x		(%a0),&0x80		# return default result in fp0
   8712  1.1        is 	rts
   8713  1.1        is 
   8714  1.1        is #
   8715  1.1        is # OVFL is enabled.
   8716  1.1        is # the INEX2 bit has already been updated by the round to the correct precision.
   8717  1.1        is # now, round to extended(and don't alter the FPSR).
   8718  1.1        is #
   8719  1.1        is fin_sd_ovfl_ena:
   8720  1.1        is 	mov.l		%d2,-(%sp)		# save d2
   8721  1.1        is 	mov.w		FP_SCR0_EX(%a6),%d1	# fetch {sgn,exp}
   8722  1.1        is 	mov.l		%d1,%d2			# make a copy
   8723  1.1        is 	andi.l		&0x7fff,%d1		# strip sign
   8724  1.1        is 	andi.w		&0x8000,%d2		# keep old sign
   8725  1.1        is 	sub.l		%d0,%d1			# add scale factor
   8726  1.1        is 	sub.l		&0x6000,%d1		# subtract bias
   8727  1.1        is 	andi.w		&0x7fff,%d1
   8728  1.1        is 	or.w		%d2,%d1
   8729  1.1        is 	mov.w		%d1,FP_SCR0_EX(%a6)	# insert new exponent
   8730  1.1        is 	mov.l		(%sp)+,%d2		# restore d2
   8731  1.1        is 	fmovm.x		FP_SCR0(%a6),&0x40	# return EXOP in fp1
   8732  1.1        is 	bra.b		fin_sd_ovfl_dis
   8733  1.1        is 
   8734  1.1        is #
   8735  1.1        is # the move in MAY overflow. so...
   8736  1.1        is #
   8737  1.1        is fin_sd_may_ovfl:
   8738  1.1        is 	fmov.l		&0x0,%fpsr		# clear FPSR
   8739  1.1        is 	fmov.l		L_SCR3(%a6),%fpcr	# set FPCR
   8740  1.1        is 
   8741  1.1        is 	fmov.x		FP_SCR0(%a6),%fp0	# perform the move
   8742  1.1        is 
   8743  1.1        is 	fmov.l		%fpsr,%d1		# save status
   8744  1.1        is 	fmov.l		&0x0,%fpcr		# clear FPCR
   8745  1.1        is 
   8746  1.1        is 	or.l		%d1,USER_FPSR(%a6)	# save INEX2,N
   8747  1.1        is 
   8748  1.1        is 	fabs.x		%fp0,%fp1		# make a copy of result
   8749  1.1        is 	fcmp.b		%fp1,&0x2		# is |result| >= 2.b?
   8750  1.1        is 	fbge.w		fin_sd_ovfl_tst		# yes; overflow has occurred
   8751  1.1        is 
   8752  1.1        is # no, it didn't overflow; we have correct result
   8753  1.1        is 	bra.w		fin_sd_normal_exit
   8754  1.1        is 
   8755  1.1        is ##########################################################################
   8756  1.1        is 
   8757  1.1        is #
   8758  1.1        is # operand is not a NORM: check its optype and branch accordingly
   8759  1.1        is #
   8760  1.1        is fin_not_norm:
   8761  1.1        is 	cmpi.b		%d1,&DENORM		# weed out DENORM
   8762  1.1        is 	beq.w		fin_denorm
   8763  1.1        is 	cmpi.b		%d1,&SNAN		# weed out SNANs
   8764  1.1        is 	beq.l		res_snan_1op
   8765  1.1        is 	cmpi.b		%d1,&QNAN		# weed out QNANs
   8766  1.1        is 	beq.l		res_qnan_1op
   8767  1.1        is 
   8768  1.1        is #
   8769  1.1        is # do the fmove in; at this point, only possible ops are ZERO and INF.
   8770  1.1        is # use fmov to determine ccodes.
   8771  1.1        is # prec:mode should be zero at this point but it won't affect answer anyways.
   8772  1.1        is #
   8773  1.1        is 	fmov.x		SRC(%a0),%fp0		# do fmove in
   8774  1.1        is 	fmov.l		%fpsr,%d0		# no exceptions possible
   8775  1.1        is 	rol.l		&0x8,%d0		# put ccodes in lo byte
   8776  1.1        is 	mov.b		%d0,FPSR_CC(%a6)	# insert correct ccodes
   8777  1.1        is 	rts
   8778  1.1        is 
   8779  1.1        is #########################################################################
   8780  1.1        is # XDEF ****************************************************************	#
   8781  1.1        is # 	fdiv(): emulates the fdiv instruction				#
   8782  1.1        is #	fsdiv(): emulates the fsdiv instruction				#
   8783  1.1        is #	fddiv(): emulates the fddiv instruction				#
   8784  1.1        is #									#
   8785  1.1        is # XREF ****************************************************************	#
   8786  1.1        is #	scale_to_zero_src() - scale src exponent to zero		#
   8787  1.1        is #	scale_to_zero_dst() - scale dst exponent to zero		#
   8788  1.1        is #	unf_res() - return default underflow result			#
   8789  1.1        is #	ovf_res() - return default overflow result			#
   8790  1.1        is # 	res_qnan() - return QNAN result					#
   8791  1.1        is # 	res_snan() - return SNAN result					#
   8792  1.1        is #									#
   8793  1.1        is # INPUT ***************************************************************	#
   8794  1.1        is #	a0 = pointer to extended precision source operand		#
   8795  1.1        is #	a1 = pointer to extended precision destination operand		#
   8796  1.1        is #	d0  rnd prec,mode						#
   8797  1.1        is #									#
   8798  1.1        is # OUTPUT **************************************************************	#
   8799  1.1        is #	fp0 = result							#
   8800  1.1        is #	fp1 = EXOP (if exception occurred)				#
   8801  1.1        is #									#
   8802  1.1        is # ALGORITHM ***********************************************************	#
   8803  1.1        is #	Handle NANs, infinities, and zeroes as special cases. Divide	#
   8804  1.1        is # norms/denorms into ext/sgl/dbl precision.				#
   8805  1.1        is #	For norms/denorms, scale the exponents such that a divide	#
   8806  1.1        is # instruction won't cause an exception. Use the regular fdiv to		#
   8807  1.1        is # compute a result. Check if the regular operands would have taken	#
   8808  1.1        is # an exception. If so, return the default overflow/underflow result	#
   8809  1.1        is # and return the EXOP if exceptions are enabled. Else, scale the 	#
   8810  1.1        is # result operand to the proper exponent.				#
   8811  1.1        is #									#
   8812  1.1        is #########################################################################
   8813  1.1        is 
   8814  1.1        is 	align		0x10
   8815  1.1        is tbl_fdiv_unfl:
   8816  1.1        is 	long		0x3fff - 0x0000		# ext_unfl
   8817  1.1        is 	long		0x3fff - 0x3f81		# sgl_unfl
   8818  1.1        is 	long		0x3fff - 0x3c01		# dbl_unfl
   8819  1.1        is 
   8820  1.1        is tbl_fdiv_ovfl:
   8821  1.1        is 	long		0x3fff - 0x7ffe		# ext overflow exponent
   8822  1.1        is 	long		0x3fff - 0x407e		# sgl overflow exponent
   8823  1.1        is 	long		0x3fff - 0x43fe		# dbl overflow exponent
   8824  1.1        is 
   8825  1.1        is 	global		fsdiv
   8826  1.1        is fsdiv:
   8827  1.1        is 	andi.b		&0x30,%d0		# clear rnd prec
   8828  1.1        is 	ori.b		&s_mode*0x10,%d0	# insert sgl prec
   8829  1.1        is 	bra.b		fdiv
   8830  1.1        is 
   8831  1.1        is 	global		fddiv
   8832  1.1        is fddiv:
   8833  1.1        is 	andi.b		&0x30,%d0		# clear rnd prec
   8834  1.1        is 	ori.b		&d_mode*0x10,%d0	# insert dbl prec
   8835  1.1        is 
   8836  1.1        is 	global		fdiv
   8837  1.1        is fdiv:
   8838  1.1        is 	mov.l		%d0,L_SCR3(%a6)		# store rnd info
   8839  1.1        is 
   8840  1.1        is 	clr.w		%d1
   8841  1.1        is 	mov.b		DTAG(%a6),%d1
   8842  1.1        is 	lsl.b		&0x3,%d1
   8843  1.1        is 	or.b		STAG(%a6),%d1		# combine src tags
   8844  1.1        is 
   8845  1.1        is 	bne.w		fdiv_not_norm		# optimize on non-norm input
   8846  1.1        is 
   8847  1.1        is #
   8848  1.1        is # DIVIDE: NORMs and DENORMs ONLY!
   8849  1.1        is #
   8850  1.1        is fdiv_norm:
   8851  1.1        is 	mov.w		DST_EX(%a1),FP_SCR1_EX(%a6)
   8852  1.1        is 	mov.l		DST_HI(%a1),FP_SCR1_HI(%a6)
   8853  1.1        is 	mov.l		DST_LO(%a1),FP_SCR1_LO(%a6)
   8854  1.1        is 
   8855  1.1        is 	mov.w		SRC_EX(%a0),FP_SCR0_EX(%a6)
   8856  1.1        is 	mov.l		SRC_HI(%a0),FP_SCR0_HI(%a6)
   8857  1.1        is 	mov.l		SRC_LO(%a0),FP_SCR0_LO(%a6)
   8858  1.1        is 
   8859  1.1        is 	bsr.l		scale_to_zero_src	# scale src exponent
   8860  1.1        is 	mov.l		%d0,-(%sp)		# save scale factor 1
   8861  1.1        is 
   8862  1.1        is 	bsr.l		scale_to_zero_dst	# scale dst exponent
   8863  1.1        is 
   8864  1.1        is 	neg.l		(%sp)			# SCALE FACTOR = scale1 - scale2
   8865  1.1        is 	add.l		%d0,(%sp)
   8866  1.1        is 
   8867  1.1        is 	mov.w		2+L_SCR3(%a6),%d1	# fetch precision
   8868  1.1        is 	lsr.b		&0x6,%d1		# shift to lo bits
   8869  1.1        is 	mov.l		(%sp)+,%d0		# load S.F.
   8870  1.1        is 	cmp.l		%d0,(tbl_fdiv_ovfl.b,%pc,%d1.w*4) # will result overflow?
   8871  1.1        is 	ble.w		fdiv_may_ovfl		# result will overflow
   8872  1.1        is 
   8873  1.1        is 	cmp.l		%d0,(tbl_fdiv_unfl.w,%pc,%d1.w*4) # will result underflow?
   8874  1.1        is 	beq.w		fdiv_may_unfl		# maybe
   8875  1.1        is 	bgt.w		fdiv_unfl		# yes; go handle underflow
   8876  1.1        is 
   8877  1.1        is fdiv_normal:
   8878  1.1        is 	fmovm.x		FP_SCR1(%a6),&0x80	# load dst op
   8879  1.1        is 
   8880  1.1        is 	fmov.l		L_SCR3(%a6),%fpcr	# save FPCR
   8881  1.1        is 	fmov.l		&0x0,%fpsr		# clear FPSR
   8882  1.1        is 
   8883  1.1        is 	fdiv.x		FP_SCR0(%a6),%fp0	# perform divide
   8884  1.1        is 
   8885  1.1        is 	fmov.l		%fpsr,%d1		# save FPSR
   8886  1.1        is 	fmov.l		&0x0,%fpcr		# clear FPCR
   8887  1.1        is 
   8888  1.1        is 	or.l		%d1,USER_FPSR(%a6)	# save INEX2,N
   8889  1.1        is 
   8890  1.1        is fdiv_normal_exit:
   8891  1.1        is 	fmovm.x		&0x80,FP_SCR0(%a6)	# store result on stack
   8892  1.1        is 	mov.l		%d2,-(%sp)		# store d2
   8893  1.1        is 	mov.w		FP_SCR0_EX(%a6),%d1	# load {sgn,exp}
   8894  1.1        is 	mov.l		%d1,%d2			# make a copy
   8895  1.1        is 	andi.l		&0x7fff,%d1		# strip sign
   8896  1.1        is 	andi.w		&0x8000,%d2		# keep old sign
   8897  1.1        is 	sub.l		%d0,%d1			# add scale factor
   8898  1.1        is 	or.w		%d2,%d1			# concat old sign,new exp
   8899  1.1        is 	mov.w		%d1,FP_SCR0_EX(%a6)	# insert new exponent
   8900  1.1        is 	mov.l		(%sp)+,%d2		# restore d2
   8901  1.1        is 	fmovm.x		FP_SCR0(%a6),&0x80	# return result in fp0
   8902  1.1        is 	rts
   8903  1.1        is 
   8904  1.1        is tbl_fdiv_ovfl2:
   8905  1.1        is 	long		0x7fff
   8906  1.1        is 	long		0x407f
   8907  1.1        is 	long		0x43ff
   8908  1.1        is 
   8909  1.1        is fdiv_no_ovfl:
   8910  1.1        is 	mov.l		(%sp)+,%d0		# restore scale factor
   8911  1.1        is 	bra.b		fdiv_normal_exit
   8912  1.1        is 
   8913  1.1        is fdiv_may_ovfl:
   8914  1.1        is 	mov.l		%d0,-(%sp)		# save scale factor
   8915  1.1        is 
   8916  1.1        is 	fmovm.x		FP_SCR1(%a6),&0x80	# load dst op
   8917  1.1        is 
   8918  1.1        is 	fmov.l		L_SCR3(%a6),%fpcr	# set FPCR
   8919  1.1        is 	fmov.l		&0x0,%fpsr		# set FPSR
   8920  1.1        is 
   8921  1.1        is 	fdiv.x		FP_SCR0(%a6),%fp0	# execute divide
   8922  1.1        is 
   8923  1.1        is 	fmov.l		%fpsr,%d0
   8924  1.1        is 	fmov.l		&0x0,%fpcr
   8925  1.1        is 
   8926  1.1        is 	or.l		%d0,USER_FPSR(%a6)	# save INEX,N
   8927  1.1        is 
   8928  1.1        is 	fmovm.x		&0x01,-(%sp)		# save result to stack
   8929  1.1        is 	mov.w		(%sp),%d0		# fetch new exponent
   8930  1.1        is 	add.l		&0xc,%sp		# clear result from stack
   8931  1.1        is 	andi.l		&0x7fff,%d0		# strip sign
   8932  1.1        is 	sub.l		(%sp),%d0		# add scale factor
   8933  1.1        is 	cmp.l		%d0,(tbl_fdiv_ovfl2.b,%pc,%d1.w*4)
   8934  1.1        is 	blt.b		fdiv_no_ovfl
   8935  1.1        is 	mov.l		(%sp)+,%d0
   8936  1.1        is 
   8937  1.1        is fdiv_ovfl_tst:
   8938  1.1        is 	or.l		&ovfl_inx_mask,USER_FPSR(%a6) # set ovfl/aovfl/ainex
   8939  1.1        is 
   8940  1.1        is 	mov.b		FPCR_ENABLE(%a6),%d1
   8941  1.1        is 	andi.b		&0x13,%d1		# is OVFL or INEX enabled?
   8942  1.1        is 	bne.b		fdiv_ovfl_ena		# yes
   8943  1.1        is 
   8944  1.1        is fdiv_ovfl_dis:
   8945  1.1        is 	btst		&neg_bit,FPSR_CC(%a6) 	# is result negative?
   8946  1.1        is 	sne		%d1			# set sign param accordingly
   8947  1.1        is 	mov.l		L_SCR3(%a6),%d0		# pass prec:rnd
   8948  1.1        is 	bsr.l		ovf_res			# calculate default result
   8949  1.1        is 	or.b		%d0,FPSR_CC(%a6)	# set INF if applicable
   8950  1.1        is 	fmovm.x		(%a0),&0x80		# return default result in fp0
   8951  1.1        is 	rts
   8952  1.1        is 
   8953  1.1        is fdiv_ovfl_ena:
   8954  1.1        is 	mov.l		L_SCR3(%a6),%d1
   8955  1.1        is 	andi.b		&0xc0,%d1		# is precision extended?
   8956  1.1        is 	bne.b		fdiv_ovfl_ena_sd	# no, do sgl or dbl
   8957  1.1        is 
   8958  1.1        is fdiv_ovfl_ena_cont:
   8959  1.1        is 	fmovm.x		&0x80,FP_SCR0(%a6)	# move result to stack
   8960  1.1        is 
   8961  1.1        is 	mov.l		%d2,-(%sp)		# save d2
   8962  1.1        is 	mov.w		FP_SCR0_EX(%a6),%d1	# fetch {sgn,exp}
   8963  1.1        is 	mov.w		%d1,%d2			# make a copy
   8964  1.1        is 	andi.l		&0x7fff,%d1		# strip sign
   8965  1.1        is 	sub.l		%d0,%d1			# add scale factor
   8966  1.1        is 	subi.l		&0x6000,%d1		# subtract bias
   8967  1.1        is 	andi.w		&0x7fff,%d1		# clear sign bit
   8968  1.1        is 	andi.w		&0x8000,%d2		# keep old sign
   8969  1.1        is 	or.w		%d2,%d1			# concat old sign,new exp
   8970  1.1        is 	mov.w		%d1,FP_SCR0_EX(%a6)	# insert new exponent
   8971  1.1        is 	mov.l		(%sp)+,%d2		# restore d2
   8972  1.1        is 	fmovm.x		FP_SCR0(%a6),&0x40	# return EXOP in fp1
   8973  1.1        is 	bra.b		fdiv_ovfl_dis
   8974  1.1        is 
   8975  1.1        is fdiv_ovfl_ena_sd:
   8976  1.1        is 	fmovm.x		FP_SCR1(%a6),&0x80	# load dst operand
   8977  1.1        is 
   8978  1.1        is 	mov.l		L_SCR3(%a6),%d1
   8979  1.1        is 	andi.b		&0x30,%d1		# keep rnd mode
   8980  1.1        is 	fmov.l		%d1,%fpcr		# set FPCR
   8981  1.1        is 
   8982  1.1        is 	fdiv.x		FP_SCR0(%a6),%fp0	# execute divide
   8983  1.1        is 
   8984  1.1        is 	fmov.l		&0x0,%fpcr		# clear FPCR
   8985  1.1        is 	bra.b		fdiv_ovfl_ena_cont
   8986  1.1        is 
   8987  1.1        is fdiv_unfl:
   8988  1.1        is 	bset		&unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
   8989  1.1        is 
   8990  1.1        is 	fmovm.x		FP_SCR1(%a6),&0x80	# load dst op
   8991  1.1        is 
   8992  1.1        is 	fmov.l		&rz_mode*0x10,%fpcr	# set FPCR
   8993  1.1        is 	fmov.l		&0x0,%fpsr		# clear FPSR
   8994  1.1        is 
   8995  1.1        is 	fdiv.x		FP_SCR0(%a6),%fp0	# execute divide
   8996  1.1        is 
   8997  1.1        is 	fmov.l		%fpsr,%d1		# save status
   8998  1.1        is 	fmov.l		&0x0,%fpcr		# clear FPCR
   8999  1.1        is 
   9000  1.1        is 	or.l		%d1,USER_FPSR(%a6)	# save INEX2,N
   9001  1.1        is 
   9002  1.1        is 	mov.b		FPCR_ENABLE(%a6),%d1
   9003  1.1        is 	andi.b		&0x0b,%d1		# is UNFL or INEX enabled?
   9004  1.1        is 	bne.b		fdiv_unfl_ena		# yes
   9005  1.1        is 
   9006  1.1        is fdiv_unfl_dis:
   9007  1.1        is 	fmovm.x		&0x80,FP_SCR0(%a6)	# store out result
   9008  1.1        is 
   9009  1.1        is 	lea		FP_SCR0(%a6),%a0	# pass: result addr
   9010  1.1        is 	mov.l		L_SCR3(%a6),%d1		# pass: rnd prec,mode
   9011  1.1        is 	bsr.l		unf_res			# calculate default result
   9012  1.1        is 	or.b		%d0,FPSR_CC(%a6)	# 'Z' may have been set
   9013  1.1        is 	fmovm.x		FP_SCR0(%a6),&0x80	# return default result in fp0
   9014  1.1        is 	rts
   9015  1.1        is 
   9016  1.1        is #
   9017  1.1        is # UNFL is enabled.
   9018  1.1        is #
   9019  1.1        is fdiv_unfl_ena:
   9020  1.1        is 	fmovm.x		FP_SCR1(%a6),&0x40	# load dst op
   9021  1.1        is 
   9022  1.1        is 	mov.l		L_SCR3(%a6),%d1
   9023  1.1        is 	andi.b		&0xc0,%d1		# is precision extended?
   9024  1.1        is 	bne.b		fdiv_unfl_ena_sd	# no, sgl or dbl
   9025  1.1        is 
   9026  1.1        is 	fmov.l		L_SCR3(%a6),%fpcr	# set FPCR
   9027  1.1        is 
   9028  1.1        is fdiv_unfl_ena_cont:
   9029  1.1        is 	fmov.l		&0x0,%fpsr		# clear FPSR
   9030  1.1        is 
   9031  1.1        is 	fdiv.x		FP_SCR0(%a6),%fp1	# execute divide
   9032  1.1        is 
   9033  1.1        is 	fmov.l		&0x0,%fpcr		# clear FPCR
   9034  1.1        is 
   9035  1.1        is 	fmovm.x		&0x40,FP_SCR0(%a6)	# save result to stack
   9036  1.1        is 	mov.l		%d2,-(%sp)		# save d2
   9037  1.1        is 	mov.w		FP_SCR0_EX(%a6),%d1	# fetch {sgn,exp}
   9038  1.1        is 	mov.l		%d1,%d2			# make a copy
   9039  1.1        is 	andi.l		&0x7fff,%d1		# strip sign
   9040  1.1        is 	andi.w		&0x8000,%d2		# keep old sign
   9041  1.1        is 	sub.l		%d0,%d1			# add scale factoer
   9042  1.1        is 	addi.l		&0x6000,%d1		# add bias
   9043  1.1        is 	andi.w		&0x7fff,%d1
   9044  1.1        is 	or.w		%d2,%d1			# concat old sign,new exp
   9045  1.1        is 	mov.w		%d1,FP_SCR0_EX(%a6)	# insert new exp
   9046  1.1        is 	mov.l		(%sp)+,%d2		# restore d2
   9047  1.1        is 	fmovm.x		FP_SCR0(%a6),&0x40	# return EXOP in fp1
   9048  1.1        is 	bra.w		fdiv_unfl_dis
   9049  1.1        is 
   9050  1.1        is fdiv_unfl_ena_sd:
   9051  1.1        is 	mov.l		L_SCR3(%a6),%d1
   9052  1.1        is 	andi.b		&0x30,%d1		# use only rnd mode
   9053  1.1        is 	fmov.l		%d1,%fpcr		# set FPCR
   9054  1.1        is 
   9055  1.1        is 	bra.b		fdiv_unfl_ena_cont
   9056  1.1        is 
   9057  1.1        is #
   9058  1.1        is # the divide operation MAY underflow:
   9059  1.1        is #
   9060  1.1        is fdiv_may_unfl:
   9061  1.1        is 	fmovm.x		FP_SCR1(%a6),&0x80	# load dst op
   9062  1.1        is 
   9063  1.1        is 	fmov.l		L_SCR3(%a6),%fpcr	# set FPCR
   9064  1.1        is 	fmov.l		&0x0,%fpsr		# clear FPSR
   9065  1.1        is 
   9066  1.1        is 	fdiv.x		FP_SCR0(%a6),%fp0	# execute divide
   9067  1.1        is 
   9068  1.1        is 	fmov.l		%fpsr,%d1		# save status
   9069  1.1        is 	fmov.l		&0x0,%fpcr		# clear FPCR
   9070  1.1        is 
   9071  1.1        is 	or.l		%d1,USER_FPSR(%a6)	# save INEX2,N
   9072  1.1        is 
   9073  1.1        is 	fabs.x		%fp0,%fp1		# make a copy of result
   9074  1.1        is 	fcmp.b		%fp1,&0x1		# is |result| > 1.b?
   9075  1.1        is 	fbgt.w		fdiv_normal_exit	# no; no underflow occurred
   9076  1.1        is 	fblt.w		fdiv_unfl		# yes; underflow occurred
   9077  1.1        is 
   9078  1.1        is #
   9079  1.1        is # we still don't know if underflow occurred. result is ~ equal to 1. but,
   9080  1.1        is # we don't know if the result was an underflow that rounded up to a 1
   9081  1.1        is # or a normalized number that rounded down to a 1. so, redo the entire
   9082  1.1        is # operation using RZ as the rounding mode to see what the pre-rounded
   9083  1.1        is # result is. this case should be relatively rare.
   9084  1.1        is #
   9085  1.1        is 	fmovm.x		FP_SCR1(%a6),&0x40	# load dst op into fp1
   9086  1.1        is 
   9087  1.1        is 	mov.l		L_SCR3(%a6),%d1
   9088  1.1        is 	andi.b		&0xc0,%d1		# keep rnd prec
   9089  1.1        is 	ori.b		&rz_mode*0x10,%d1	# insert RZ
   9090  1.1        is 
   9091  1.1        is 	fmov.l		%d1,%fpcr		# set FPCR
   9092  1.1        is 	fmov.l		&0x0,%fpsr		# clear FPSR
   9093  1.1        is 
   9094  1.1        is 	fdiv.x		FP_SCR0(%a6),%fp1	# execute divide
   9095  1.1        is 
   9096  1.1        is 	fmov.l		&0x0,%fpcr		# clear FPCR
   9097  1.1        is 	fabs.x		%fp1			# make absolute value
   9098  1.1        is 	fcmp.b		%fp1,&0x1		# is |result| < 1.b?
   9099  1.1        is 	fbge.w		fdiv_normal_exit	# no; no underflow occurred
   9100  1.1        is 	bra.w		fdiv_unfl		# yes; underflow occurred
   9101  1.1        is 
   9102  1.1        is ############################################################################
   9103  1.1        is 
   9104  1.1        is #
   9105  1.1        is # Divide: inputs are not both normalized; what are they?
   9106  1.1        is #
   9107  1.1        is fdiv_not_norm:
   9108  1.1        is 	mov.w		(tbl_fdiv_op.b,%pc,%d1.w*2),%d1
   9109  1.1        is 	jmp		(tbl_fdiv_op.b,%pc,%d1.w*1)
   9110  1.1        is 
   9111  1.1        is 	swbeg		&48
   9112  1.1        is tbl_fdiv_op:
   9113  1.1        is 	short		fdiv_norm	- tbl_fdiv_op # NORM / NORM
   9114  1.1        is 	short		fdiv_inf_load	- tbl_fdiv_op # NORM / ZERO
   9115  1.1        is 	short		fdiv_zero_load	- tbl_fdiv_op # NORM / INF
   9116  1.1        is 	short		fdiv_res_qnan	- tbl_fdiv_op # NORM / QNAN
   9117  1.1        is 	short		fdiv_norm	- tbl_fdiv_op # NORM / DENORM
   9118  1.1        is 	short		fdiv_res_snan	- tbl_fdiv_op # NORM / SNAN
   9119  1.1        is 	short		tbl_fdiv_op	- tbl_fdiv_op #
   9120  1.1        is 	short		tbl_fdiv_op	- tbl_fdiv_op #
   9121  1.1        is 
   9122  1.1        is 	short		fdiv_zero_load	- tbl_fdiv_op # ZERO / NORM
   9123  1.1        is 	short		fdiv_res_operr	- tbl_fdiv_op # ZERO / ZERO
   9124  1.1        is 	short		fdiv_zero_load	- tbl_fdiv_op # ZERO / INF
   9125  1.1        is 	short		fdiv_res_qnan	- tbl_fdiv_op # ZERO / QNAN
   9126  1.1        is 	short		fdiv_zero_load	- tbl_fdiv_op # ZERO / DENORM
   9127  1.1        is 	short		fdiv_res_snan	- tbl_fdiv_op # ZERO / SNAN
   9128  1.1        is 	short		tbl_fdiv_op	- tbl_fdiv_op #
   9129  1.1        is 	short		tbl_fdiv_op	- tbl_fdiv_op #
   9130  1.1        is 
   9131  1.1        is 	short		fdiv_inf_dst	- tbl_fdiv_op # INF / NORM
   9132  1.1        is 	short		fdiv_inf_dst	- tbl_fdiv_op # INF / ZERO
   9133  1.1        is 	short		fdiv_res_operr	- tbl_fdiv_op # INF / INF
   9134  1.1        is 	short		fdiv_res_qnan	- tbl_fdiv_op # INF / QNAN
   9135  1.1        is 	short		fdiv_inf_dst	- tbl_fdiv_op # INF / DENORM
   9136  1.1        is 	short		fdiv_res_snan	- tbl_fdiv_op # INF / SNAN
   9137  1.1        is 	short		tbl_fdiv_op	- tbl_fdiv_op #
   9138  1.1        is 	short		tbl_fdiv_op	- tbl_fdiv_op #
   9139  1.1        is 
   9140  1.1        is 	short		fdiv_res_qnan	- tbl_fdiv_op # QNAN / NORM
   9141  1.1        is 	short		fdiv_res_qnan	- tbl_fdiv_op # QNAN / ZERO
   9142  1.1        is 	short		fdiv_res_qnan	- tbl_fdiv_op # QNAN / INF
   9143  1.1        is 	short		fdiv_res_qnan	- tbl_fdiv_op # QNAN / QNAN
   9144  1.1        is 	short		fdiv_res_qnan	- tbl_fdiv_op # QNAN / DENORM
   9145  1.1        is 	short		fdiv_res_snan	- tbl_fdiv_op # QNAN / SNAN
   9146  1.1        is 	short		tbl_fdiv_op	- tbl_fdiv_op #
   9147  1.1        is 	short		tbl_fdiv_op	- tbl_fdiv_op #
   9148  1.1        is 
   9149  1.1        is 	short		fdiv_norm	- tbl_fdiv_op # DENORM / NORM
   9150  1.1        is 	short		fdiv_inf_load	- tbl_fdiv_op # DENORM / ZERO
   9151  1.1        is 	short		fdiv_zero_load	- tbl_fdiv_op # DENORM / INF
   9152  1.1        is 	short		fdiv_res_qnan	- tbl_fdiv_op # DENORM / QNAN
   9153  1.1        is 	short		fdiv_norm	- tbl_fdiv_op # DENORM / DENORM
   9154  1.1        is 	short		fdiv_res_snan	- tbl_fdiv_op # DENORM / SNAN
   9155  1.1        is 	short		tbl_fdiv_op	- tbl_fdiv_op #
   9156  1.1        is 	short		tbl_fdiv_op	- tbl_fdiv_op #
   9157  1.1        is 
   9158  1.1        is 	short		fdiv_res_snan	- tbl_fdiv_op # SNAN / NORM
   9159  1.1        is 	short		fdiv_res_snan	- tbl_fdiv_op # SNAN / ZERO
   9160  1.1        is 	short		fdiv_res_snan	- tbl_fdiv_op # SNAN / INF
   9161  1.1        is 	short		fdiv_res_snan	- tbl_fdiv_op # SNAN / QNAN
   9162  1.1        is 	short		fdiv_res_snan	- tbl_fdiv_op # SNAN / DENORM
   9163  1.1        is 	short		fdiv_res_snan	- tbl_fdiv_op # SNAN / SNAN
   9164  1.1        is 	short		tbl_fdiv_op	- tbl_fdiv_op #
   9165  1.1        is 	short		tbl_fdiv_op	- tbl_fdiv_op #
   9166  1.1        is 
   9167  1.1        is fdiv_res_qnan:
   9168  1.1        is 	bra.l		res_qnan
   9169  1.1        is fdiv_res_snan:
   9170  1.1        is 	bra.l		res_snan
   9171  1.1        is fdiv_res_operr:
   9172  1.1        is 	bra.l		res_operr
   9173  1.1        is 
   9174  1.1        is 	global		fdiv_zero_load		# global for fsgldiv
   9175  1.1        is fdiv_zero_load:
   9176  1.1        is 	mov.b		SRC_EX(%a0),%d0		# result sign is exclusive
   9177  1.1        is 	mov.b		DST_EX(%a1),%d1		# or of input signs.
   9178  1.1        is 	eor.b		%d0,%d1
   9179  1.1        is 	bpl.b		fdiv_zero_load_p	# result is positive
   9180  1.1        is 	fmov.s		&0x80000000,%fp0	# load a -ZERO
   9181  1.1        is 	mov.b		&z_bmask+neg_bmask,FPSR_CC(%a6)	# set Z/N
   9182  1.1        is 	rts
   9183  1.1        is fdiv_zero_load_p:
   9184  1.1        is 	fmov.s		&0x00000000,%fp0	# load a +ZERO
   9185  1.1        is 	mov.b		&z_bmask,FPSR_CC(%a6)	# set Z
   9186  1.1        is 	rts
   9187  1.1        is 
   9188  1.1        is #
   9189  1.1        is # The destination was In Range and the source was a ZERO. The result,
   9190  1.1        is # therefore, is an INF w/ the proper sign.
   9191  1.1        is # So, determine the sign and return a new INF (w/ the j-bit cleared).
   9192  1.1        is #
   9193  1.1        is 	global		fdiv_inf_load		# global for fsgldiv
   9194  1.1        is fdiv_inf_load:
   9195  1.1        is 	ori.w		&dz_mask+adz_mask,2+USER_FPSR(%a6) # no; set DZ/ADZ
   9196  1.1        is 	mov.b		SRC_EX(%a0),%d0		# load both signs
   9197  1.1        is 	mov.b		DST_EX(%a1),%d1
   9198  1.1        is 	eor.b		%d0,%d1
   9199  1.1        is 	bpl.b		fdiv_inf_load_p		# result is positive
   9200  1.1        is 	fmov.s		&0xff800000,%fp0	# make result -INF
   9201  1.1        is 	mov.b		&inf_bmask+neg_bmask,FPSR_CC(%a6) # set INF/N
   9202  1.1        is 	rts
   9203  1.1        is fdiv_inf_load_p:
   9204  1.1        is 	fmov.s		&0x7f800000,%fp0	# make result +INF
   9205  1.1        is 	mov.b		&inf_bmask,FPSR_CC(%a6)	# set INF
   9206  1.1        is 	rts
   9207  1.1        is 
   9208  1.1        is #
   9209  1.1        is # The destination was an INF w/ an In Range or ZERO source, the result is
   9210  1.1        is # an INF w/ the proper sign.
   9211  1.1        is # The 68881/882 returns the destination INF w/ the new sign(if the j-bit of the
   9212  1.1        is # dst INF is set, then then j-bit of the result INF is also set).
   9213  1.1        is #
   9214  1.1        is 	global		fdiv_inf_dst		# global for fsgldiv
   9215  1.1        is fdiv_inf_dst:
   9216  1.1        is 	mov.b		DST_EX(%a1),%d0		# load both signs
   9217  1.1        is 	mov.b		SRC_EX(%a0),%d1
   9218  1.1        is 	eor.b		%d0,%d1
   9219  1.1        is 	bpl.b		fdiv_inf_dst_p		# result is positive
   9220  1.1        is 
   9221  1.1        is 	fmovm.x		DST(%a1),&0x80		# return result in fp0
   9222  1.1        is 	fabs.x		%fp0			# clear sign bit
   9223  1.1        is 	fneg.x		%fp0			# set sign bit
   9224  1.1        is 	mov.b		&inf_bmask+neg_bmask,FPSR_CC(%a6) # set INF/NEG
   9225  1.1        is 	rts
   9226  1.1        is 
   9227  1.1        is fdiv_inf_dst_p:
   9228  1.1        is 	fmovm.x		DST(%a1),&0x80		# return result in fp0
   9229  1.1        is 	fabs.x		%fp0			# return positive INF
   9230  1.1        is 	mov.b		&inf_bmask,FPSR_CC(%a6) # set INF
   9231  1.1        is 	rts
   9232  1.1        is 
   9233  1.1        is #########################################################################
   9234  1.1        is # XDEF ****************************************************************	#
   9235  1.1        is #	fneg(): emulates the fneg instruction				#
   9236  1.1        is #	fsneg(): emulates the fsneg instruction				#
   9237  1.1        is #	fdneg(): emulates the fdneg instruction				#
   9238  1.1        is #									#
   9239  1.1        is # XREF ****************************************************************	#
   9240  1.1        is # 	norm() - normalize a denorm to provide EXOP			#
   9241  1.1        is #	scale_to_zero_src() - scale sgl/dbl source exponent		#
   9242  1.1        is #	ovf_res() - return default overflow result			#
   9243  1.1        is #	unf_res() - return default underflow result			#
   9244  1.1        is # 	res_qnan_1op() - return QNAN result				#
   9245  1.1        is #	res_snan_1op() - return SNAN result				#
   9246  1.1        is #									#
   9247  1.1        is # INPUT ***************************************************************	#
   9248  1.1        is #	a0 = pointer to extended precision source operand		#
   9249  1.1        is #	d0 = rnd prec,mode						#
   9250  1.1        is #									#
   9251  1.1        is # OUTPUT **************************************************************	#
   9252  1.1        is #	fp0 = result							#
   9253  1.1        is #	fp1 = EXOP (if exception occurred)				#
   9254  1.1        is #									#
   9255  1.1        is # ALGORITHM ***********************************************************	#
   9256  1.1        is #	Handle NANs, zeroes, and infinities as special cases. Separate	#
   9257  1.1        is # norms/denorms into ext/sgl/dbl precisions. Extended precision can be	#
   9258  1.1        is # emulated by simply setting sign bit. Sgl/dbl operands must be scaled	#
   9259  1.1        is # and an actual fneg performed to see if overflow/underflow would have	#
   9260  1.1        is # occurred. If so, return default underflow/overflow result. Else,	#
   9261  1.1        is # scale the result exponent and return result. FPSR gets set based on	#
   9262  1.1        is # the result value.							#
   9263  1.1        is #									#
   9264  1.1        is #########################################################################
   9265  1.1        is 
   9266  1.1        is 	global		fsneg
   9267  1.1        is fsneg:
   9268  1.1        is 	andi.b		&0x30,%d0		# clear rnd prec
   9269  1.1        is 	ori.b		&s_mode*0x10,%d0	# insert sgl precision
   9270  1.1        is 	bra.b		fneg
   9271  1.1        is 
   9272  1.1        is 	global		fdneg
   9273  1.1        is fdneg:
   9274  1.1        is 	andi.b		&0x30,%d0		# clear rnd prec
   9275  1.1        is 	ori.b		&d_mode*0x10,%d0	# insert dbl prec
   9276  1.1        is 
   9277  1.1        is 	global		fneg
   9278  1.1        is fneg:
   9279  1.1        is 	mov.l		%d0,L_SCR3(%a6)		# store rnd info
   9280  1.1        is 	mov.b		STAG(%a6),%d1
   9281  1.1        is 	bne.w		fneg_not_norm		# optimize on non-norm input
   9282  1.1        is 
   9283  1.1        is #
   9284  1.1        is # NEGATE SIGN : norms and denorms ONLY!
   9285  1.1        is #
   9286  1.1        is fneg_norm:
   9287  1.1        is 	andi.b		&0xc0,%d0		# is precision extended?
   9288  1.1        is 	bne.w		fneg_not_ext		# no; go handle sgl or dbl
   9289  1.1        is 
   9290  1.1        is #
   9291  1.1        is # precision selected is extended. so...we can not get an underflow
   9292  1.1        is # or overflow because of rounding to the correct precision. so...
   9293  1.1        is # skip the scaling and unscaling...
   9294  1.1        is #
   9295  1.1        is 	mov.l		SRC_HI(%a0),FP_SCR0_HI(%a6)
   9296  1.1        is 	mov.l		SRC_LO(%a0),FP_SCR0_LO(%a6)
   9297  1.1        is 	mov.w		SRC_EX(%a0),%d0
   9298  1.1        is 	eori.w		&0x8000,%d0		# negate sign
   9299  1.1        is 	bpl.b		fneg_norm_load		# sign is positive
   9300  1.1        is 	mov.b		&neg_bmask,FPSR_CC(%a6)	# set 'N' ccode bit
   9301  1.1        is fneg_norm_load:
   9302  1.1        is 	mov.w		%d0,FP_SCR0_EX(%a6)
   9303  1.1        is 	fmovm.x		FP_SCR0(%a6),&0x80	# return result in fp0
   9304  1.1        is 	rts
   9305  1.1        is 
   9306  1.1        is #
   9307  1.1        is # for an extended precision DENORM, the UNFL exception bit is set
   9308  1.1        is # the accrued bit is NOT set in this instance(no inexactness!)
   9309  1.1        is #
   9310  1.1        is fneg_denorm:
   9311  1.1        is 	andi.b		&0xc0,%d0		# is precision extended?
   9312  1.1        is 	bne.b		fneg_not_ext		# no; go handle sgl or dbl
   9313  1.1        is 
   9314  1.1        is 	bset		&unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
   9315  1.1        is 
   9316  1.1        is 	mov.l		SRC_HI(%a0),FP_SCR0_HI(%a6)
   9317  1.1        is 	mov.l		SRC_LO(%a0),FP_SCR0_LO(%a6)
   9318  1.1        is 	mov.w		SRC_EX(%a0),%d0
   9319  1.1        is 	eori.w		&0x8000,%d0		# negate sign
   9320  1.1        is 	bpl.b		fneg_denorm_done	# no
   9321  1.1        is 	mov.b		&neg_bmask,FPSR_CC(%a6)	# yes, set 'N' ccode bit
   9322  1.1        is fneg_denorm_done:
   9323  1.1        is 	mov.w		%d0,FP_SCR0_EX(%a6)
   9324  1.1        is 	fmovm.x		FP_SCR0(%a6),&0x80	# return default result in fp0
   9325  1.1        is 
   9326  1.1        is 	btst		&unfl_bit,FPCR_ENABLE(%a6) # is UNFL enabled?
   9327  1.1        is 	bne.b		fneg_ext_unfl_ena	# yes
   9328  1.1        is 	rts
   9329  1.1        is 
   9330  1.1        is #
   9331  1.1        is # the input is an extended DENORM and underflow is enabled in the FPCR.
   9332  1.1        is # normalize the mantissa and add the bias of 0x6000 to the resulting negative
   9333  1.1        is # exponent and insert back into the operand.
   9334  1.1        is #
   9335  1.1        is fneg_ext_unfl_ena:
   9336  1.1        is 	lea		FP_SCR0(%a6),%a0	# pass: ptr to operand
   9337  1.1        is 	bsr.l		norm			# normalize result
   9338  1.1        is 	neg.w		%d0			# new exponent = -(shft val)
   9339  1.1        is 	addi.w		&0x6000,%d0		# add new bias to exponent
   9340  1.1        is 	mov.w		FP_SCR0_EX(%a6),%d1	# fetch old sign,exp
   9341  1.1        is 	andi.w		&0x8000,%d1	 	# keep old sign
   9342  1.1        is 	andi.w		&0x7fff,%d0		# clear sign position
   9343  1.1        is 	or.w		%d1,%d0			# concat old sign, new exponent
   9344  1.1        is 	mov.w		%d0,FP_SCR0_EX(%a6)	# insert new exponent
   9345  1.1        is 	fmovm.x		FP_SCR0(%a6),&0x40	# return EXOP in fp1
   9346  1.1        is 	rts
   9347  1.1        is 
   9348  1.1        is #
   9349  1.1        is # operand is either single or double
   9350  1.1        is #
   9351  1.1        is fneg_not_ext:
   9352  1.1        is 	cmpi.b		%d0,&s_mode*0x10	# separate sgl/dbl prec
   9353  1.1        is 	bne.b		fneg_dbl
   9354  1.1        is 
   9355  1.1        is #
   9356  1.1        is # operand is to be rounded to single precision
   9357  1.1        is #
   9358  1.1        is fneg_sgl:
   9359  1.1        is 	mov.w		SRC_EX(%a0),FP_SCR0_EX(%a6)
   9360  1.1        is 	mov.l		SRC_HI(%a0),FP_SCR0_HI(%a6)
   9361  1.1        is 	mov.l		SRC_LO(%a0),FP_SCR0_LO(%a6)
   9362  1.1        is 	bsr.l		scale_to_zero_src	# calculate scale factor
   9363  1.1        is 
   9364  1.1        is 	cmpi.l		%d0,&0x3fff-0x3f80	# will move in underflow?
   9365  1.1        is 	bge.w		fneg_sd_unfl		# yes; go handle underflow
   9366  1.1        is 	cmpi.l		%d0,&0x3fff-0x407e	# will move in overflow?
   9367  1.1        is 	beq.w		fneg_sd_may_ovfl	# maybe; go check
   9368  1.1        is 	blt.w		fneg_sd_ovfl		# yes; go handle overflow
   9369  1.1        is 
   9370  1.1        is #
   9371  1.1        is # operand will NOT overflow or underflow when moved in to the fp reg file
   9372  1.1        is #
   9373  1.1        is fneg_sd_normal:
   9374  1.1        is 	fmov.l		&0x0,%fpsr		# clear FPSR
   9375  1.1        is 	fmov.l		L_SCR3(%a6),%fpcr	# set FPCR
   9376  1.1        is 
   9377  1.1        is 	fneg.x		FP_SCR0(%a6),%fp0	# perform negation
   9378  1.1        is 
   9379  1.1        is 	fmov.l		%fpsr,%d1		# save FPSR
   9380  1.1        is 	fmov.l		&0x0,%fpcr		# clear FPCR
   9381  1.1        is 
   9382  1.1        is 	or.l		%d1,USER_FPSR(%a6)	# save INEX2,N
   9383  1.1        is 
   9384  1.1        is fneg_sd_normal_exit:
   9385  1.1        is 	mov.l		%d2,-(%sp)		# save d2
   9386  1.1        is 	fmovm.x		&0x80,FP_SCR0(%a6)	# store out result
   9387  1.1        is 	mov.w		FP_SCR0_EX(%a6),%d1	# load sgn,exp
   9388  1.1        is 	mov.w		%d1,%d2			# make a copy
   9389  1.1        is 	andi.l		&0x7fff,%d1		# strip sign
   9390  1.1        is 	sub.l		%d0,%d1			# add scale factor
   9391  1.1        is 	andi.w		&0x8000,%d2		# keep old sign
   9392  1.1        is 	or.w		%d1,%d2			# concat old sign,new exp
   9393  1.1        is 	mov.w		%d2,FP_SCR0_EX(%a6)	# insert new exponent
   9394  1.1        is 	mov.l		(%sp)+,%d2		# restore d2
   9395  1.1        is 	fmovm.x		FP_SCR0(%a6),&0x80	# return result in fp0
   9396  1.1        is 	rts
   9397  1.1        is 
   9398  1.1        is #
   9399  1.1        is # operand is to be rounded to double precision
   9400  1.1        is #
   9401  1.1        is fneg_dbl:
   9402  1.1        is 	mov.w		SRC_EX(%a0),FP_SCR0_EX(%a6)
   9403  1.1        is 	mov.l		SRC_HI(%a0),FP_SCR0_HI(%a6)
   9404  1.1        is 	mov.l		SRC_LO(%a0),FP_SCR0_LO(%a6)
   9405  1.1        is 	bsr.l		scale_to_zero_src	# calculate scale factor
   9406  1.1        is 
   9407  1.1        is 	cmpi.l		%d0,&0x3fff-0x3c00	# will move in underflow?
   9408  1.1        is 	bge.b		fneg_sd_unfl		# yes; go handle underflow
   9409  1.1        is 	cmpi.l		%d0,&0x3fff-0x43fe	# will move in overflow?
   9410  1.1        is 	beq.w		fneg_sd_may_ovfl	# maybe; go check
   9411  1.1        is 	blt.w		fneg_sd_ovfl		# yes; go handle overflow
   9412  1.1        is 	bra.w		fneg_sd_normal		# no; ho handle normalized op
   9413  1.1        is 
   9414  1.1        is #
   9415  1.1        is # operand WILL underflow when moved in to the fp register file
   9416  1.1        is #
   9417  1.1        is fneg_sd_unfl:
   9418  1.1        is 	bset		&unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
   9419  1.1        is 
   9420  1.1        is 	eori.b		&0x80,FP_SCR0_EX(%a6)	# negate sign
   9421  1.1        is 	bpl.b		fneg_sd_unfl_tst
   9422  1.1        is 	bset		&neg_bit,FPSR_CC(%a6)	# set 'N' ccode bit
   9423  1.1        is 
   9424  1.1        is # if underflow or inexact is enabled, go calculate EXOP first.
   9425  1.1        is fneg_sd_unfl_tst:
   9426  1.1        is 	mov.b		FPCR_ENABLE(%a6),%d1
   9427  1.1        is 	andi.b		&0x0b,%d1		# is UNFL or INEX enabled?
   9428  1.1        is 	bne.b		fneg_sd_unfl_ena	# yes
   9429  1.1        is 
   9430  1.1        is fneg_sd_unfl_dis:
   9431  1.1        is 	lea		FP_SCR0(%a6),%a0	# pass: result addr
   9432  1.1        is 	mov.l		L_SCR3(%a6),%d1		# pass: rnd prec,mode
   9433  1.1        is 	bsr.l		unf_res			# calculate default result
   9434  1.1        is 	or.b		%d0,FPSR_CC(%a6)	# unf_res may have set 'Z'
   9435  1.1        is 	fmovm.x		FP_SCR0(%a6),&0x80	# return default result in fp0
   9436  1.1        is 	rts
   9437  1.1        is 
   9438  1.1        is #
   9439  1.1        is # operand will underflow AND underflow is enabled.
   9440  1.1        is # therefore, we must return the result rounded to extended precision.
   9441  1.1        is #
   9442  1.1        is fneg_sd_unfl_ena:
   9443  1.1        is 	mov.l		FP_SCR0_HI(%a6),FP_SCR1_HI(%a6)
   9444  1.1        is 	mov.l		FP_SCR0_LO(%a6),FP_SCR1_LO(%a6)
   9445  1.1        is 	mov.w		FP_SCR0_EX(%a6),%d1	# load current exponent
   9446  1.1        is 
   9447  1.1        is 	mov.l		%d2,-(%sp)		# save d2
   9448  1.1        is 	mov.l		%d1,%d2			# make a copy
   9449  1.1        is 	andi.l		&0x7fff,%d1		# strip sign
   9450  1.1        is 	andi.w		&0x8000,%d2		# keep old sign
   9451  1.1        is 	sub.l		%d0,%d1			# subtract scale factor
   9452  1.1        is 	addi.l		&0x6000,%d1		# add new bias
   9453  1.1        is 	andi.w		&0x7fff,%d1
   9454  1.1        is 	or.w		%d2,%d1			# concat new sign,new exp
   9455  1.1        is 	mov.w		%d1,FP_SCR1_EX(%a6)	# insert new exp
   9456  1.1        is 	fmovm.x		FP_SCR1(%a6),&0x40	# return EXOP in fp1
   9457  1.1        is 	mov.l		(%sp)+,%d2		# restore d2
   9458  1.1        is 	bra.b		fneg_sd_unfl_dis
   9459  1.1        is 
   9460  1.1        is #
   9461  1.1        is # operand WILL overflow.
   9462  1.1        is #
   9463  1.1        is fneg_sd_ovfl:
   9464  1.1        is 	fmov.l		&0x0,%fpsr		# clear FPSR
   9465  1.1        is 	fmov.l		L_SCR3(%a6),%fpcr	# set FPCR
   9466  1.1        is 
   9467  1.1        is 	fneg.x		FP_SCR0(%a6),%fp0	# perform negation
   9468  1.1        is 
   9469  1.1        is 	fmov.l		&0x0,%fpcr		# clear FPCR
   9470  1.1        is 	fmov.l		%fpsr,%d1		# save FPSR
   9471  1.1        is 
   9472  1.1        is 	or.l		%d1,USER_FPSR(%a6)	# save INEX2,N
   9473  1.1        is 
   9474  1.1        is fneg_sd_ovfl_tst:
   9475  1.1        is 	or.l		&ovfl_inx_mask,USER_FPSR(%a6) # set ovfl/aovfl/ainex
   9476  1.1        is 
   9477  1.1        is 	mov.b		FPCR_ENABLE(%a6),%d1
   9478  1.1        is 	andi.b		&0x13,%d1		# is OVFL or INEX enabled?
   9479  1.1        is 	bne.b		fneg_sd_ovfl_ena	# yes
   9480  1.1        is 
   9481  1.1        is #
   9482  1.1        is # OVFL is not enabled; therefore, we must create the default result by
   9483  1.1        is # calling ovf_res().
   9484  1.1        is #
   9485  1.1        is fneg_sd_ovfl_dis:
   9486  1.1        is 	btst		&neg_bit,FPSR_CC(%a6)	# is result negative?
   9487  1.1        is 	sne		%d1			# set sign param accordingly
   9488  1.1        is 	mov.l		L_SCR3(%a6),%d0		# pass: prec,mode
   9489  1.1        is 	bsr.l		ovf_res			# calculate default result
   9490  1.1        is 	or.b		%d0,FPSR_CC(%a6)	# set INF,N if applicable
   9491  1.1        is 	fmovm.x		(%a0),&0x80		# return default result in fp0
   9492  1.1        is 	rts
   9493  1.1        is 
   9494  1.1        is #
   9495  1.1        is # OVFL is enabled.
   9496  1.1        is # the INEX2 bit has already been updated by the round to the correct precision.
   9497  1.1        is # now, round to extended(and don't alter the FPSR).
   9498  1.1        is #
   9499  1.1        is fneg_sd_ovfl_ena:
   9500  1.1        is 	mov.l		%d2,-(%sp)		# save d2
   9501  1.1        is 	mov.w		FP_SCR0_EX(%a6),%d1	# fetch {sgn,exp}
   9502  1.1        is 	mov.l		%d1,%d2			# make a copy
   9503  1.1        is 	andi.l		&0x7fff,%d1		# strip sign
   9504  1.1        is 	andi.w		&0x8000,%d2		# keep old sign
   9505  1.1        is 	sub.l		%d0,%d1			# add scale factor
   9506  1.1        is 	subi.l		&0x6000,%d1		# subtract bias
   9507  1.1        is 	andi.w		&0x7fff,%d1
   9508  1.1        is 	or.w		%d2,%d1			# concat sign,exp
   9509  1.1        is 	mov.w		%d1,FP_SCR0_EX(%a6)	# insert new exponent
   9510  1.1        is 	fmovm.x		FP_SCR0(%a6),&0x40	# return EXOP in fp1
   9511  1.1        is 	mov.l		(%sp)+,%d2		# restore d2
   9512  1.1        is 	bra.b		fneg_sd_ovfl_dis
   9513  1.1        is 
   9514  1.1        is #
   9515  1.1        is # the move in MAY underflow. so...
   9516  1.1        is #
   9517  1.1        is fneg_sd_may_ovfl:
   9518  1.1        is 	fmov.l		&0x0,%fpsr		# clear FPSR
   9519  1.1        is 	fmov.l		L_SCR3(%a6),%fpcr	# set FPCR
   9520  1.1        is 
   9521  1.1        is 	fneg.x		FP_SCR0(%a6),%fp0	# perform negation
   9522  1.1        is 
   9523  1.1        is 	fmov.l		%fpsr,%d1		# save status
   9524  1.1        is 	fmov.l		&0x0,%fpcr		# clear FPCR
   9525  1.1        is 
   9526  1.1        is 	or.l		%d1,USER_FPSR(%a6)	# save INEX2,N
   9527  1.1        is 
   9528  1.1        is 	fabs.x		%fp0,%fp1		# make a copy of result
   9529  1.1        is 	fcmp.b		%fp1,&0x2		# is |result| >= 2.b?
   9530  1.1        is 	fbge.w		fneg_sd_ovfl_tst	# yes; overflow has occurred
   9531  1.1        is 
   9532  1.1        is # no, it didn't overflow; we have correct result
   9533  1.1        is 	bra.w		fneg_sd_normal_exit
   9534  1.1        is 
   9535  1.1        is ##########################################################################
   9536  1.1        is 
   9537  1.1        is #
   9538  1.1        is # input is not normalized; what is it?
   9539  1.1        is #
   9540  1.1        is fneg_not_norm:
   9541  1.1        is 	cmpi.b		%d1,&DENORM		# weed out DENORM
   9542  1.1        is 	beq.w		fneg_denorm
   9543  1.1        is 	cmpi.b		%d1,&SNAN		# weed out SNAN
   9544  1.1        is 	beq.l		res_snan_1op
   9545  1.1        is 	cmpi.b		%d1,&QNAN		# weed out QNAN
   9546  1.1        is 	beq.l		res_qnan_1op
   9547  1.1        is 
   9548  1.1        is #
   9549  1.1        is # do the fneg; at this point, only possible ops are ZERO and INF.
   9550  1.1        is # use fneg to determine ccodes.
   9551  1.1        is # prec:mode should be zero at this point but it won't affect answer anyways.
   9552  1.1        is #
   9553  1.1        is 	fneg.x		SRC_EX(%a0),%fp0	# do fneg
   9554  1.1        is 	fmov.l		%fpsr,%d0
   9555  1.1        is 	rol.l		&0x8,%d0		# put ccodes in lo byte
   9556  1.1        is 	mov.b		%d0,FPSR_CC(%a6)	# insert correct ccodes
   9557  1.1        is 	rts
   9558  1.1        is 
   9559  1.1        is #########################################################################
   9560  1.1        is # XDEF ****************************************************************	#
   9561  1.1        is # 	ftst(): emulates the ftest instruction				#
   9562  1.1        is #									#
   9563  1.1        is # XREF ****************************************************************	#
   9564  1.1        is # 	res{s,q}nan_1op() - set NAN result for monadic instruction	#
   9565  1.1        is #									#
   9566  1.1        is # INPUT ***************************************************************	#
   9567  1.1        is # 	a0 = pointer to extended precision source operand		#
   9568  1.1        is #									#
   9569  1.1        is # OUTPUT **************************************************************	#
   9570  1.1        is #	none								#
   9571  1.1        is #									#
   9572  1.1        is # ALGORITHM ***********************************************************	#
   9573  1.1        is # 	Check the source operand tag (STAG) and set the FPCR according	#
   9574  1.1        is # to the operand type and sign.						#
   9575  1.1        is #									#
   9576  1.1        is #########################################################################
   9577  1.1        is 
   9578  1.1        is 	global		ftst
   9579  1.1        is ftst:
   9580  1.1        is 	mov.b		STAG(%a6),%d1
   9581  1.1        is 	bne.b		ftst_not_norm		# optimize on non-norm input
   9582  1.1        is 
   9583  1.1        is #
   9584  1.1        is # Norm:
   9585  1.1        is #
   9586  1.1        is ftst_norm:
   9587  1.1        is 	tst.b		SRC_EX(%a0)		# is operand negative?
   9588  1.1        is 	bmi.b		ftst_norm_m		# yes
   9589  1.1        is 	rts
   9590  1.1        is ftst_norm_m:
   9591  1.1        is 	mov.b		&neg_bmask,FPSR_CC(%a6)	# set 'N' ccode bit
   9592  1.1        is 	rts
   9593  1.1        is 
   9594  1.1        is #
   9595  1.1        is # input is not normalized; what is it?
   9596  1.1        is #
   9597  1.1        is ftst_not_norm:
   9598  1.1        is 	cmpi.b		%d1,&ZERO		# weed out ZERO
   9599  1.1        is 	beq.b		ftst_zero
   9600  1.1        is 	cmpi.b		%d1,&INF		# weed out INF
   9601  1.1        is 	beq.b		ftst_inf
   9602  1.1        is 	cmpi.b		%d1,&SNAN		# weed out SNAN
   9603  1.1        is 	beq.l		res_snan_1op
   9604  1.1        is 	cmpi.b		%d1,&QNAN		# weed out QNAN
   9605  1.1        is 	beq.l		res_qnan_1op
   9606  1.1        is 
   9607  1.1        is #
   9608  1.1        is # Denorm:
   9609  1.1        is #
   9610  1.1        is ftst_denorm:
   9611  1.1        is 	tst.b		SRC_EX(%a0)		# is operand negative?
   9612  1.1        is 	bmi.b		ftst_denorm_m		# yes
   9613  1.1        is 	rts
   9614  1.1        is ftst_denorm_m:
   9615  1.1        is 	mov.b		&neg_bmask,FPSR_CC(%a6)	# set 'N' ccode bit
   9616  1.1        is 	rts
   9617  1.1        is 
   9618  1.1        is #
   9619  1.1        is # Infinity:
   9620  1.1        is #
   9621  1.1        is ftst_inf:
   9622  1.1        is 	tst.b		SRC_EX(%a0)		# is operand negative?
   9623  1.1        is 	bmi.b		ftst_inf_m		# yes
   9624  1.1        is ftst_inf_p:
   9625  1.1        is 	mov.b		&inf_bmask,FPSR_CC(%a6)	# set 'I' ccode bit
   9626  1.1        is 	rts
   9627  1.1        is ftst_inf_m:
   9628  1.1        is 	mov.b		&inf_bmask+neg_bmask,FPSR_CC(%a6) # set 'I','N' ccode bits
   9629  1.1        is 	rts
   9630  1.1        is 
   9631  1.1        is #
   9632  1.1        is # Zero:
   9633  1.1        is #
   9634  1.1        is ftst_zero:
   9635  1.1        is 	tst.b		SRC_EX(%a0)		# is operand negative?
   9636  1.1        is 	bmi.b		ftst_zero_m		# yes
   9637  1.1        is ftst_zero_p:
   9638  1.1        is 	mov.b		&z_bmask,FPSR_CC(%a6)	# set 'N' ccode bit
   9639  1.1        is 	rts
   9640  1.1        is ftst_zero_m:
   9641  1.1        is 	mov.b		&z_bmask+neg_bmask,FPSR_CC(%a6)	# set 'Z','N' ccode bits
   9642  1.1        is 	rts
   9643  1.1        is 
   9644  1.1        is #########################################################################
   9645  1.1        is # XDEF ****************************************************************	#
   9646  1.1        is #	fint(): emulates the fint instruction				#
   9647  1.1        is #									#
   9648  1.1        is # XREF ****************************************************************	#
   9649  1.1        is #	res_{s,q}nan_1op() - set NAN result for monadic operation	#
   9650  1.1        is #									#
   9651  1.1        is # INPUT ***************************************************************	#
   9652  1.1        is #	a0 = pointer to extended precision source operand		#
   9653  1.1        is #	d0 = round precision/mode					#
   9654  1.1        is #									#
   9655  1.1        is # OUTPUT **************************************************************	#
   9656  1.1        is #	fp0 = result							#
   9657  1.1        is #									#
   9658  1.1        is # ALGORITHM ***********************************************************	#
   9659  1.1        is # 	Separate according to operand type. Unnorms don't pass through 	#
   9660  1.1        is # here. For norms, load the rounding mode/prec, execute a "fint", then 	#
   9661  1.1        is # store the resulting FPSR bits.					#
   9662  1.1        is # 	For denorms, force the j-bit to a one and do the same as for	#
   9663  1.1        is # norms. Denorms are so low that the answer will either be a zero or a 	#
   9664  1.1        is # one.									#
   9665  1.1        is # 	For zeroes/infs/NANs, return the same while setting the FPSR	#
   9666  1.1        is # as appropriate.							#
   9667  1.1        is #									#
   9668  1.1        is #########################################################################
   9669  1.1        is 
   9670  1.1        is 	global		fint
   9671  1.1        is fint:
   9672  1.1        is 	mov.b		STAG(%a6),%d1
   9673  1.1        is 	bne.b		fint_not_norm		# optimize on non-norm input
   9674  1.1        is 
   9675  1.1        is #
   9676  1.1        is # Norm:
   9677  1.1        is #
   9678  1.1        is fint_norm:
   9679  1.1        is 	andi.b		&0x30,%d0		# set prec = ext
   9680  1.1        is 
   9681  1.1        is 	fmov.l		%d0,%fpcr		# set FPCR
   9682  1.1        is 	fmov.l		&0x0,%fpsr		# clear FPSR
   9683  1.1        is 
   9684  1.1        is 	fint.x 		SRC(%a0),%fp0		# execute fint
   9685  1.1        is 
   9686  1.1        is 	fmov.l		&0x0,%fpcr		# clear FPCR
   9687  1.1        is 	fmov.l		%fpsr,%d0		# save FPSR
   9688  1.1        is 	or.l		%d0,USER_FPSR(%a6)	# set exception bits
   9689  1.1        is 
   9690  1.1        is 	rts
   9691  1.1        is 
   9692  1.1        is #
   9693  1.1        is # input is not normalized; what is it?
   9694  1.1        is #
   9695  1.1        is fint_not_norm:
   9696  1.1        is 	cmpi.b		%d1,&ZERO		# weed out ZERO
   9697  1.1        is 	beq.b		fint_zero
   9698  1.1        is 	cmpi.b		%d1,&INF		# weed out INF
   9699  1.1        is 	beq.b		fint_inf
   9700  1.1        is 	cmpi.b		%d1,&DENORM		# weed out DENORM
   9701  1.1        is 	beq.b		fint_denorm
   9702  1.1        is 	cmpi.b		%d1,&SNAN		# weed out SNAN
   9703  1.1        is 	beq.l		res_snan_1op
   9704  1.1        is 	bra.l		res_qnan_1op		# weed out QNAN
   9705  1.1        is 
   9706  1.1        is #
   9707  1.1        is # Denorm:
   9708  1.1        is #
   9709  1.1        is # for DENORMs, the result will be either (+/-)ZERO or (+/-)1.
   9710  1.1        is # also, the INEX2 and AINEX exception bits will be set.
   9711  1.1        is # so, we could either set these manually or force the DENORM
   9712  1.1        is # to a very small NORM and ship it to the NORM routine.
   9713  1.1        is # I do the latter.
   9714  1.1        is #
   9715  1.1        is fint_denorm:
   9716  1.1        is 	mov.w		SRC_EX(%a0),FP_SCR0_EX(%a6) # copy sign, zero exp
   9717  1.1        is 	mov.b		&0x80,FP_SCR0_HI(%a6)	# force DENORM ==> small NORM
   9718  1.1        is 	lea		FP_SCR0(%a6),%a0
   9719  1.1        is 	bra.b		fint_norm
   9720  1.1        is 
   9721  1.1        is #
   9722  1.1        is # Zero:
   9723  1.1        is #
   9724  1.1        is fint_zero:
   9725  1.1        is 	tst.b		SRC_EX(%a0)		# is ZERO negative?
   9726  1.1        is 	bmi.b		fint_zero_m		# yes
   9727  1.1        is fint_zero_p:
   9728  1.1        is 	fmov.s		&0x00000000,%fp0	# return +ZERO in fp0
   9729  1.1        is 	mov.b		&z_bmask,FPSR_CC(%a6)	# set 'Z' ccode bit
   9730  1.1        is 	rts
   9731  1.1        is fint_zero_m:
   9732  1.1        is 	fmov.s		&0x80000000,%fp0	# return -ZERO in fp0
   9733  1.1        is 	mov.b		&z_bmask+neg_bmask,FPSR_CC(%a6) # set 'Z','N' ccode bits
   9734  1.1        is 	rts
   9735  1.1        is 
   9736  1.1        is #
   9737  1.1        is # Infinity:
   9738  1.1        is #
   9739  1.1        is fint_inf:
   9740  1.1        is 	fmovm.x		SRC(%a0),&0x80		# return result in fp0
   9741  1.1        is 	tst.b		SRC_EX(%a0)		# is INF negative?
   9742  1.1        is 	bmi.b		fint_inf_m		# yes
   9743  1.1        is fint_inf_p:
   9744  1.1        is 	mov.b		&inf_bmask,FPSR_CC(%a6)	# set 'I' ccode bit
   9745  1.1        is 	rts
   9746  1.1        is fint_inf_m:
   9747  1.1        is 	mov.b		&inf_bmask+neg_bmask,FPSR_CC(%a6) # set 'N','I' ccode bits
   9748  1.1        is 	rts
   9749  1.1        is 
   9750  1.1        is #########################################################################
   9751  1.1        is # XDEF ****************************************************************	#
   9752  1.1        is #	fintrz(): emulates the fintrz instruction			#
   9753  1.1        is #									#
   9754  1.1        is # XREF ****************************************************************	#
   9755  1.1        is #	res_{s,q}nan_1op() - set NAN result for monadic operation	#
   9756  1.1        is #									#
   9757  1.1        is # INPUT ***************************************************************	#
   9758  1.1        is #	a0 = pointer to extended precision source operand		#
   9759  1.1        is #	d0 = round precision/mode					#
   9760  1.1        is #									#
   9761  1.1        is # OUTPUT **************************************************************	#
   9762  1.1        is # 	fp0 = result							#
   9763  1.1        is #									#
   9764  1.1        is # ALGORITHM ***********************************************************	#
   9765  1.1        is #	Separate according to operand type. Unnorms don't pass through	#
   9766  1.1        is # here. For norms, load the rounding mode/prec, execute a "fintrz", 	#
   9767  1.1        is # then store the resulting FPSR bits.					#
   9768  1.1        is # 	For denorms, force the j-bit to a one and do the same as for	#
   9769  1.1        is # norms. Denorms are so low that the answer will either be a zero or a	#
   9770  1.1        is # one.									#
   9771  1.1        is # 	For zeroes/infs/NANs, return the same while setting the FPSR	#
   9772  1.1        is # as appropriate.							#
   9773  1.1        is #									#
   9774  1.1        is #########################################################################
   9775  1.1        is 
   9776  1.1        is 	global		fintrz
   9777  1.1        is fintrz:
   9778  1.1        is 	mov.b		STAG(%a6),%d1
   9779  1.1        is 	bne.b		fintrz_not_norm		# optimize on non-norm input
   9780  1.1        is 
   9781  1.1        is #
   9782  1.1        is # Norm:
   9783  1.1        is #
   9784  1.1        is fintrz_norm:
   9785  1.1        is 	fmov.l		&0x0,%fpsr		# clear FPSR
   9786  1.1        is 
   9787  1.1        is 	fintrz.x	SRC(%a0),%fp0		# execute fintrz
   9788  1.1        is 
   9789  1.1        is 	fmov.l		%fpsr,%d0		# save FPSR
   9790  1.1        is 	or.l		%d0,USER_FPSR(%a6)	# set exception bits
   9791  1.1        is 
   9792  1.1        is 	rts
   9793  1.1        is 
   9794  1.1        is #
   9795  1.1        is # input is not normalized; what is it?
   9796  1.1        is #
   9797  1.1        is fintrz_not_norm:
   9798  1.1        is 	cmpi.b		%d1,&ZERO		# weed out ZERO
   9799  1.1        is 	beq.b		fintrz_zero
   9800  1.1        is 	cmpi.b		%d1,&INF		# weed out INF
   9801  1.1        is 	beq.b		fintrz_inf
   9802  1.1        is 	cmpi.b		%d1,&DENORM		# weed out DENORM
   9803  1.1        is 	beq.b		fintrz_denorm
   9804  1.1        is 	cmpi.b		%d1,&SNAN		# weed out SNAN
   9805  1.1        is 	beq.l		res_snan_1op
   9806  1.1        is 	bra.l		res_qnan_1op		# weed out QNAN
   9807  1.1        is 
   9808  1.1        is #
   9809  1.1        is # Denorm:
   9810  1.1        is #
   9811  1.1        is # for DENORMs, the result will be (+/-)ZERO.
   9812  1.1        is # also, the INEX2 and AINEX exception bits will be set.
   9813  1.1        is # so, we could either set these manually or force the DENORM
   9814  1.1        is # to a very small NORM and ship it to the NORM routine.
   9815  1.1        is # I do the latter.
   9816  1.1        is #
   9817  1.1        is fintrz_denorm:
   9818  1.1        is 	mov.w		SRC_EX(%a0),FP_SCR0_EX(%a6) # copy sign, zero exp
   9819  1.1        is 	mov.b		&0x80,FP_SCR0_HI(%a6)	# force DENORM ==> small NORM
   9820  1.1        is 	lea		FP_SCR0(%a6),%a0
   9821  1.1        is 	bra.b		fintrz_norm
   9822  1.1        is 
   9823  1.1        is #
   9824  1.1        is # Zero:
   9825  1.1        is #
   9826  1.1        is fintrz_zero:
   9827  1.1        is 	tst.b		SRC_EX(%a0)		# is ZERO negative?
   9828  1.1        is 	bmi.b		fintrz_zero_m		# yes
   9829  1.1        is fintrz_zero_p:
   9830  1.1        is 	fmov.s		&0x00000000,%fp0	# return +ZERO in fp0
   9831  1.1        is 	mov.b		&z_bmask,FPSR_CC(%a6)	# set 'Z' ccode bit
   9832  1.1        is 	rts
   9833  1.1        is fintrz_zero_m:
   9834  1.1        is 	fmov.s		&0x80000000,%fp0	# return -ZERO in fp0
   9835  1.1        is 	mov.b		&z_bmask+neg_bmask,FPSR_CC(%a6) # set 'Z','N' ccode bits
   9836  1.1        is 	rts
   9837  1.1        is 
   9838  1.1        is #
   9839  1.1        is # Infinity:
   9840  1.1        is #
   9841  1.1        is fintrz_inf:
   9842  1.1        is 	fmovm.x		SRC(%a0),&0x80		# return result in fp0
   9843  1.1        is 	tst.b		SRC_EX(%a0)		# is INF negative?
   9844  1.1        is 	bmi.b		fintrz_inf_m		# yes
   9845  1.1        is fintrz_inf_p:
   9846  1.1        is 	mov.b		&inf_bmask,FPSR_CC(%a6)	# set 'I' ccode bit
   9847  1.1        is 	rts
   9848  1.1        is fintrz_inf_m:
   9849  1.1        is 	mov.b		&inf_bmask+neg_bmask,FPSR_CC(%a6) # set 'N','I' ccode bits
   9850  1.1        is 	rts
   9851  1.1        is 
   9852  1.1        is #########################################################################
   9853  1.1        is # XDEF ****************************************************************	#
   9854  1.1        is #	fabs():  emulates the fabs instruction				#
   9855  1.1        is #	fsabs(): emulates the fsabs instruction				#
   9856  1.1        is #	fdabs(): emulates the fdabs instruction				#
   9857  1.1        is #									#
   9858  1.1        is # XREF **************************************************************** #
   9859  1.1        is #	norm() - normalize denorm mantissa to provide EXOP		#
   9860  1.1        is #	scale_to_zero_src() - make exponent. = 0; get scale factor	#
   9861  1.1        is #	unf_res() - calculate underflow result				#
   9862  1.1        is #	ovf_res() - calculate overflow result				#
   9863  1.1        is #	res_{s,q}nan_1op() - set NAN result for monadic operation	#
   9864  1.1        is #									#
   9865  1.1        is # INPUT *************************************************************** #
   9866  1.1        is #	a0 = pointer to extended precision source operand		#
   9867  1.1        is #	d0 = rnd precision/mode						#
   9868  1.1        is #									#
   9869  1.1        is # OUTPUT ************************************************************** #
   9870  1.1        is #	fp0 = result							#
   9871  1.1        is #	fp1 = EXOP (if exception occurred)				#
   9872  1.1        is #									#
   9873  1.1        is # ALGORITHM ***********************************************************	#
   9874  1.1        is #	Handle NANs, infinities, and zeroes as special cases. Divide	#
   9875  1.1        is # norms into extended, single, and double precision. 			#
   9876  1.1        is # 	Simply clear sign for extended precision norm. Ext prec denorm	#
   9877  1.1        is # gets an EXOP created for it since it's an underflow.			#
   9878  1.1        is #	Double and single precision can overflow and underflow. First,	#
   9879  1.1        is # scale the operand such that the exponent is zero. Perform an "fabs"	#
   9880  1.1        is # using the correct rnd mode/prec. Check to see if the original 	#
   9881  1.1        is # exponent would take an exception. If so, use unf_res() or ovf_res()	#
   9882  1.1        is # to calculate the default result. Also, create the EXOP for the	#
   9883  1.1        is # exceptional case. If no exception should occur, insert the correct 	#
   9884  1.1        is # result exponent and return.						#
   9885  1.1        is # 	Unnorms don't pass through here.				#
   9886  1.1        is #									#
   9887  1.1        is #########################################################################
   9888  1.1        is 
   9889  1.1        is 	global		fsabs
   9890  1.1        is fsabs:
   9891  1.1        is 	andi.b		&0x30,%d0		# clear rnd prec
   9892  1.1        is 	ori.b		&s_mode*0x10,%d0	# insert sgl precision
   9893  1.1        is 	bra.b		fabs
   9894  1.1        is 
   9895  1.1        is 	global		fdabs
   9896  1.1        is fdabs:
   9897  1.1        is 	andi.b		&0x30,%d0		# clear rnd prec
   9898  1.1        is 	ori.b		&d_mode*0x10,%d0	# insert dbl precision
   9899  1.1        is 
   9900  1.1        is 	global		fabs
   9901  1.1        is fabs:
   9902  1.1        is 	mov.l		%d0,L_SCR3(%a6)		# store rnd info
   9903  1.1        is 	mov.b		STAG(%a6),%d1
   9904  1.1        is 	bne.w		fabs_not_norm		# optimize on non-norm input
   9905  1.1        is 
   9906  1.1        is #
   9907  1.1        is # ABSOLUTE VALUE: norms and denorms ONLY!
   9908  1.1        is #
   9909  1.1        is fabs_norm:
   9910  1.1        is 	andi.b		&0xc0,%d0		# is precision extended?
   9911  1.1        is 	bne.b		fabs_not_ext		# no; go handle sgl or dbl
   9912  1.1        is 
   9913  1.1        is #
   9914  1.1        is # precision selected is extended. so...we can not get an underflow
   9915  1.1        is # or overflow because of rounding to the correct precision. so...
   9916  1.1        is # skip the scaling and unscaling...
   9917  1.1        is #
   9918  1.1        is 	mov.l		SRC_HI(%a0),FP_SCR0_HI(%a6)
   9919  1.1        is 	mov.l		SRC_LO(%a0),FP_SCR0_LO(%a6)
   9920  1.1        is 	mov.w		SRC_EX(%a0),%d1
   9921  1.1        is 	bclr		&15,%d1			# force absolute value
   9922  1.1        is 	mov.w		%d1,FP_SCR0_EX(%a6)	# insert exponent
   9923  1.1        is 	fmovm.x		FP_SCR0(%a6),&0x80	# return result in fp0
   9924  1.1        is 	rts
   9925  1.1        is 
   9926  1.1        is #
   9927  1.1        is # for an extended precision DENORM, the UNFL exception bit is set
   9928  1.1        is # the accrued bit is NOT set in this instance(no inexactness!)
   9929  1.1        is #
   9930  1.1        is fabs_denorm:
   9931  1.1        is 	andi.b		&0xc0,%d0		# is precision extended?
   9932  1.1        is 	bne.b		fabs_not_ext		# no
   9933  1.1        is 
   9934  1.1        is 	bset		&unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
   9935  1.1        is 
   9936  1.1        is 	mov.l		SRC_HI(%a0),FP_SCR0_HI(%a6)
   9937  1.1        is 	mov.l		SRC_LO(%a0),FP_SCR0_LO(%a6)
   9938  1.1        is 	mov.w		SRC_EX(%a0),%d0
   9939  1.1        is 	bclr		&15,%d0			# clear sign
   9940  1.1        is 	mov.w		%d0,FP_SCR0_EX(%a6)	# insert exponent
   9941  1.1        is 
   9942  1.1        is 	fmovm.x		FP_SCR0(%a6),&0x80	# return default result in fp0
   9943  1.1        is 
   9944  1.1        is 	btst		&unfl_bit,FPCR_ENABLE(%a6) # is UNFL enabled?
   9945  1.1        is 	bne.b		fabs_ext_unfl_ena
   9946  1.1        is 	rts
   9947  1.1        is 
   9948  1.1        is #
   9949  1.1        is # the input is an extended DENORM and underflow is enabled in the FPCR.
   9950  1.1        is # normalize the mantissa and add the bias of 0x6000 to the resulting negative
   9951  1.1        is # exponent and insert back into the operand.
   9952  1.1        is #
   9953  1.1        is fabs_ext_unfl_ena:
   9954  1.1        is 	lea		FP_SCR0(%a6),%a0	# pass: ptr to operand
   9955  1.1        is 	bsr.l		norm			# normalize result
   9956  1.1        is 	neg.w		%d0			# new exponent = -(shft val)
   9957  1.1        is 	addi.w		&0x6000,%d0		# add new bias to exponent
   9958  1.1        is 	mov.w		FP_SCR0_EX(%a6),%d1	# fetch old sign,exp
   9959  1.1        is 	andi.w		&0x8000,%d1		# keep old sign
   9960  1.1        is 	andi.w		&0x7fff,%d0		# clear sign position
   9961  1.1        is 	or.w		%d1,%d0			# concat old sign, new exponent
   9962  1.1        is 	mov.w		%d0,FP_SCR0_EX(%a6)	# insert new exponent
   9963  1.1        is 	fmovm.x		FP_SCR0(%a6),&0x40	# return EXOP in fp1
   9964  1.1        is 	rts
   9965  1.1        is 
   9966  1.1        is #
   9967  1.1        is # operand is either single or double
   9968  1.1        is #
   9969  1.1        is fabs_not_ext:
   9970  1.1        is 	cmpi.b		%d0,&s_mode*0x10	# separate sgl/dbl prec
   9971  1.1        is 	bne.b		fabs_dbl
   9972  1.1        is 
   9973  1.1        is #
   9974  1.1        is # operand is to be rounded to single precision
   9975  1.1        is #
   9976  1.1        is fabs_sgl:
   9977  1.1        is 	mov.w		SRC_EX(%a0),FP_SCR0_EX(%a6)
   9978  1.1        is 	mov.l		SRC_HI(%a0),FP_SCR0_HI(%a6)
   9979  1.1        is 	mov.l		SRC_LO(%a0),FP_SCR0_LO(%a6)
   9980  1.1        is 	bsr.l		scale_to_zero_src	# calculate scale factor
   9981  1.1        is 
   9982  1.1        is 	cmpi.l		%d0,&0x3fff-0x3f80	# will move in underflow?
   9983  1.1        is 	bge.w		fabs_sd_unfl		# yes; go handle underflow
   9984  1.1        is 	cmpi.l		%d0,&0x3fff-0x407e	# will move in overflow?
   9985  1.1        is 	beq.w		fabs_sd_may_ovfl	# maybe; go check
   9986  1.1        is 	blt.w		fabs_sd_ovfl		# yes; go handle overflow
   9987  1.1        is 
   9988  1.1        is #
   9989  1.1        is # operand will NOT overflow or underflow when moved in to the fp reg file
   9990  1.1        is #
   9991  1.1        is fabs_sd_normal:
   9992  1.1        is 	fmov.l		&0x0,%fpsr		# clear FPSR
   9993  1.1        is 	fmov.l		L_SCR3(%a6),%fpcr	# set FPCR
   9994  1.1        is 
   9995  1.1        is 	fabs.x		FP_SCR0(%a6),%fp0	# perform absolute
   9996  1.1        is 
   9997  1.1        is 	fmov.l		%fpsr,%d1		# save FPSR
   9998  1.1        is 	fmov.l		&0x0,%fpcr		# clear FPCR
   9999  1.1        is 
   10000  1.1        is 	or.l		%d1,USER_FPSR(%a6)	# save INEX2,N
   10001  1.1        is 
   10002  1.1        is fabs_sd_normal_exit:
   10003  1.1        is 	mov.l		%d2,-(%sp)		# save d2
   10004  1.1        is 	fmovm.x		&0x80,FP_SCR0(%a6)	# store out result
   10005  1.1        is 	mov.w		FP_SCR0_EX(%a6),%d1	# load sgn,exp
   10006  1.1        is 	mov.l		%d1,%d2			# make a copy
   10007  1.1        is 	andi.l		&0x7fff,%d1		# strip sign
   10008  1.1        is 	sub.l		%d0,%d1			# add scale factor
   10009  1.1        is 	andi.w		&0x8000,%d2		# keep old sign
   10010  1.1        is 	or.w		%d1,%d2			# concat old sign,new exp
   10011  1.1        is 	mov.w		%d2,FP_SCR0_EX(%a6)	# insert new exponent
   10012  1.1        is 	mov.l		(%sp)+,%d2		# restore d2
   10013  1.1        is 	fmovm.x		FP_SCR0(%a6),&0x80	# return result in fp0
   10014  1.1        is 	rts
   10015  1.1        is 
   10016  1.1        is #
   10017  1.1        is # operand is to be rounded to double precision
   10018  1.1        is #
   10019  1.1        is fabs_dbl:
   10020  1.1        is 	mov.w		SRC_EX(%a0),FP_SCR0_EX(%a6)
   10021  1.1        is 	mov.l		SRC_HI(%a0),FP_SCR0_HI(%a6)
   10022  1.1        is 	mov.l		SRC_LO(%a0),FP_SCR0_LO(%a6)
   10023  1.1        is 	bsr.l		scale_to_zero_src	# calculate scale factor
   10024  1.1        is 
   10025  1.1        is 	cmpi.l		%d0,&0x3fff-0x3c00	# will move in underflow?
   10026  1.1        is 	bge.b		fabs_sd_unfl		# yes; go handle underflow
   10027  1.1        is 	cmpi.l		%d0,&0x3fff-0x43fe	# will move in overflow?
   10028  1.1        is 	beq.w		fabs_sd_may_ovfl	# maybe; go check
   10029  1.1        is 	blt.w		fabs_sd_ovfl		# yes; go handle overflow
   10030  1.1        is 	bra.w		fabs_sd_normal		# no; ho handle normalized op
   10031  1.1        is 
   10032  1.1        is #
   10033  1.1        is # operand WILL underflow when moved in to the fp register file
   10034  1.1        is #
   10035  1.1        is fabs_sd_unfl:
   10036  1.1        is 	bset		&unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
   10037  1.1        is 
   10038  1.1        is 	bclr		&0x7,FP_SCR0_EX(%a6)	# force absolute value
   10039  1.1        is 
   10040  1.1        is # if underflow or inexact is enabled, go calculate EXOP first.
   10041  1.1        is 	mov.b		FPCR_ENABLE(%a6),%d1
   10042  1.1        is 	andi.b		&0x0b,%d1		# is UNFL or INEX enabled?
   10043  1.1        is 	bne.b		fabs_sd_unfl_ena	# yes
   10044  1.1        is 
   10045  1.1        is fabs_sd_unfl_dis:
   10046  1.1        is 	lea		FP_SCR0(%a6),%a0	# pass: result addr
   10047  1.1        is 	mov.l		L_SCR3(%a6),%d1		# pass: rnd prec,mode
   10048  1.1        is 	bsr.l		unf_res			# calculate default result
   10049  1.1        is 	or.b		%d0,FPSR_CC(%a6)	# set possible 'Z' ccode
   10050  1.1        is 	fmovm.x		FP_SCR0(%a6),&0x80	# return default result in fp0
   10051  1.1        is 	rts
   10052  1.1        is 
   10053  1.1        is #
   10054  1.1        is # operand will underflow AND underflow is enabled.
   10055  1.1        is # therefore, we must return the result rounded to extended precision.
   10056  1.1        is #
   10057  1.1        is fabs_sd_unfl_ena:
   10058  1.1        is 	mov.l		FP_SCR0_HI(%a6),FP_SCR1_HI(%a6)
   10059  1.1        is 	mov.l		FP_SCR0_LO(%a6),FP_SCR1_LO(%a6)
   10060  1.1        is 	mov.w		FP_SCR0_EX(%a6),%d1	# load current exponent
   10061  1.1        is 
   10062  1.1        is 	mov.l		%d2,-(%sp)		# save d2
   10063  1.1        is 	mov.l		%d1,%d2			# make a copy
   10064  1.1        is 	andi.l		&0x7fff,%d1		# strip sign
   10065  1.1        is 	andi.w		&0x8000,%d2		# keep old sign
   10066  1.1        is 	sub.l		%d0,%d1			# subtract scale factor
   10067  1.1        is 	addi.l		&0x6000,%d1		# add new bias
   10068  1.1        is 	andi.w		&0x7fff,%d1
   10069  1.1        is 	or.w		%d2,%d1			# concat new sign,new exp
   10070  1.1        is 	mov.w		%d1,FP_SCR1_EX(%a6)	# insert new exp
   10071  1.1        is 	fmovm.x		FP_SCR1(%a6),&0x40	# return EXOP in fp1
   10072  1.1        is 	mov.l		(%sp)+,%d2		# restore d2
   10073  1.1        is 	bra.b		fabs_sd_unfl_dis
   10074  1.1        is 
   10075  1.1        is #
   10076  1.1        is # operand WILL overflow.
   10077  1.1        is #
   10078  1.1        is fabs_sd_ovfl:
   10079  1.1        is 	fmov.l		&0x0,%fpsr		# clear FPSR
   10080  1.1        is 	fmov.l		L_SCR3(%a6),%fpcr	# set FPCR
   10081  1.1        is 
   10082  1.1        is 	fabs.x		FP_SCR0(%a6),%fp0	# perform absolute
   10083  1.1        is 
   10084  1.1        is 	fmov.l		&0x0,%fpcr		# clear FPCR
   10085  1.1        is 	fmov.l		%fpsr,%d1		# save FPSR
   10086  1.1        is 
   10087  1.1        is 	or.l		%d1,USER_FPSR(%a6)	# save INEX2,N
   10088  1.1        is 
   10089  1.1        is fabs_sd_ovfl_tst:
   10090  1.1        is 	or.l		&ovfl_inx_mask,USER_FPSR(%a6) # set ovfl/aovfl/ainex
   10091  1.1        is 
   10092  1.1        is 	mov.b		FPCR_ENABLE(%a6),%d1
   10093  1.1        is 	andi.b		&0x13,%d1		# is OVFL or INEX enabled?
   10094  1.1        is 	bne.b		fabs_sd_ovfl_ena	# yes
   10095  1.1        is 
   10096  1.1        is #
   10097  1.1        is # OVFL is not enabled; therefore, we must create the default result by
   10098  1.1        is # calling ovf_res().
   10099  1.1        is #
   10100  1.1        is fabs_sd_ovfl_dis:
   10101  1.1        is 	btst		&neg_bit,FPSR_CC(%a6)	# is result negative?
   10102  1.1        is 	sne		%d1			# set sign param accordingly
   10103  1.1        is 	mov.l		L_SCR3(%a6),%d0		# pass: prec,mode
   10104  1.1        is 	bsr.l		ovf_res			# calculate default result
   10105  1.1        is 	or.b		%d0,FPSR_CC(%a6)	# set INF,N if applicable
   10106  1.1        is 	fmovm.x		(%a0),&0x80		# return default result in fp0
   10107  1.1        is 	rts
   10108  1.1        is 
   10109  1.1        is #
   10110  1.1        is # OVFL is enabled.
   10111  1.1        is # the INEX2 bit has already been updated by the round to the correct precision.
   10112  1.1        is # now, round to extended(and don't alter the FPSR).
   10113  1.1        is #
   10114  1.1        is fabs_sd_ovfl_ena:
   10115  1.1        is 	mov.l		%d2,-(%sp)		# save d2
   10116  1.1        is 	mov.w		FP_SCR0_EX(%a6),%d1	# fetch {sgn,exp}
   10117  1.1        is 	mov.l		%d1,%d2			# make a copy
   10118  1.1        is 	andi.l		&0x7fff,%d1		# strip sign
   10119  1.1        is 	andi.w		&0x8000,%d2		# keep old sign
   10120  1.1        is 	sub.l		%d0,%d1			# add scale factor
   10121  1.1        is 	subi.l		&0x6000,%d1		# subtract bias
   10122  1.1        is 	andi.w		&0x7fff,%d1
   10123  1.1        is 	or.w		%d2,%d1			# concat sign,exp
   10124  1.1        is 	mov.w		%d1,FP_SCR0_EX(%a6)	# insert new exponent
   10125  1.1        is 	fmovm.x		FP_SCR0(%a6),&0x40	# return EXOP in fp1
   10126  1.1        is 	mov.l		(%sp)+,%d2		# restore d2
   10127  1.1        is 	bra.b		fabs_sd_ovfl_dis
   10128  1.1        is 
   10129  1.1        is #
   10130  1.1        is # the move in MAY underflow. so...
   10131  1.1        is #
   10132  1.1        is fabs_sd_may_ovfl:
   10133  1.1        is 	fmov.l		&0x0,%fpsr		# clear FPSR
   10134  1.1        is 	fmov.l		L_SCR3(%a6),%fpcr	# set FPCR
   10135  1.1        is 
   10136  1.1        is 	fabs.x		FP_SCR0(%a6),%fp0	# perform absolute
   10137  1.1        is 
   10138  1.1        is 	fmov.l		%fpsr,%d1		# save status
   10139  1.1        is 	fmov.l		&0x0,%fpcr		# clear FPCR
   10140  1.1        is 
   10141  1.1        is 	or.l		%d1,USER_FPSR(%a6)	# save INEX2,N
   10142  1.1        is 
   10143  1.1        is 	fabs.x		%fp0,%fp1		# make a copy of result
   10144  1.1        is 	fcmp.b		%fp1,&0x2		# is |result| >= 2.b?
   10145  1.1        is 	fbge.w		fabs_sd_ovfl_tst	# yes; overflow has occurred
   10146  1.1        is 
   10147  1.1        is # no, it didn't overflow; we have correct result
   10148  1.1        is 	bra.w		fabs_sd_normal_exit
   10149  1.1        is 
   10150  1.1        is ##########################################################################
   10151  1.1        is 
   10152  1.1        is #
   10153  1.1        is # input is not normalized; what is it?
   10154  1.1        is #
   10155  1.1        is fabs_not_norm:
   10156  1.1        is 	cmpi.b		%d1,&DENORM		# weed out DENORM
   10157  1.1        is 	beq.w		fabs_denorm
   10158  1.1        is 	cmpi.b		%d1,&SNAN		# weed out SNAN
   10159  1.1        is 	beq.l		res_snan_1op
   10160  1.1        is 	cmpi.b		%d1,&QNAN		# weed out QNAN
   10161  1.1        is 	beq.l		res_qnan_1op
   10162  1.1        is 
   10163  1.1        is 	fabs.x		SRC(%a0),%fp0		# force absolute value
   10164  1.1        is 
   10165  1.1        is 	cmpi.b		%d1,&INF		# weed out INF
   10166  1.1        is 	beq.b		fabs_inf
   10167  1.1        is fabs_zero:
   10168  1.1        is 	mov.b		&z_bmask,FPSR_CC(%a6)	# set 'Z' ccode bit
   10169  1.1        is 	rts
   10170  1.1        is fabs_inf:
   10171  1.1        is 	mov.b		&inf_bmask,FPSR_CC(%a6)	# set 'I' ccode bit
   10172  1.1        is 	rts
   10173  1.1        is 
   10174  1.1        is #########################################################################
   10175  1.1        is # XDEF ****************************************************************	#
   10176  1.1        is # 	fcmp(): fp compare op routine					#
   10177  1.1        is #									#
   10178  1.1        is # XREF ****************************************************************	#
   10179  1.1        is # 	res_qnan() - return QNAN result					#
   10180  1.1        is #	res_snan() - return SNAN result					#
   10181  1.1        is #									#
   10182  1.1        is # INPUT ***************************************************************	#
   10183  1.1        is #	a0 = pointer to extended precision source operand		#
   10184  1.1        is #	a1 = pointer to extended precision destination operand		#
   10185  1.1        is #	d0 = round prec/mode						#
   10186  1.1        is #									#
   10187  1.1        is # OUTPUT ************************************************************** #
   10188  1.1        is #	None								#
   10189  1.1        is #									#
   10190  1.1        is # ALGORITHM ***********************************************************	#
   10191  1.1        is # 	Handle NANs and denorms as special cases. For everything else,	#
   10192  1.1        is # just use the actual fcmp instruction to produce the correct condition	#
   10193  1.1        is # codes.								#
   10194  1.1        is #									#
   10195  1.1        is #########################################################################
   10196  1.1        is 
   10197  1.1        is 	global		fcmp
   10198  1.1        is fcmp:
   10199  1.1        is 	clr.w		%d1
   10200  1.1        is 	mov.b		DTAG(%a6),%d1
   10201  1.1        is 	lsl.b		&0x3,%d1
   10202  1.1        is 	or.b		STAG(%a6),%d1
   10203  1.1        is 	bne.b		fcmp_not_norm		# optimize on non-norm input
   10204  1.1        is 
   10205  1.1        is #
   10206  1.1        is # COMPARE FP OPs : NORMs, ZEROs, INFs, and "corrected" DENORMs
   10207  1.1        is #
   10208  1.1        is fcmp_norm:
   10209  1.1        is 	fmovm.x		DST(%a1),&0x80		# load dst op
   10210  1.1        is 
   10211  1.1        is 	fcmp.x 		%fp0,SRC(%a0)		# do compare
   10212  1.1        is 
   10213  1.1        is 	fmov.l		%fpsr,%d0		# save FPSR
   10214  1.1        is 	rol.l		&0x8,%d0		# extract ccode bits
   10215  1.1        is 	mov.b		%d0,FPSR_CC(%a6)	# set ccode bits(no exc bits are set)
   10216  1.1        is 
   10217  1.1        is 	rts
   10218  1.1        is 
   10219  1.1        is #
   10220  1.1        is # fcmp: inputs are not both normalized; what are they?
   10221  1.1        is #
   10222  1.1        is fcmp_not_norm:
   10223  1.1        is 	mov.w		(tbl_fcmp_op.b,%pc,%d1.w*2),%d1
   10224  1.1        is 	jmp		(tbl_fcmp_op.b,%pc,%d1.w*1)
   10225  1.1        is 
   10226  1.1        is 	swbeg		&48
   10227  1.1        is tbl_fcmp_op:
   10228  1.1        is 	short		fcmp_norm	- tbl_fcmp_op # NORM - NORM
   10229  1.1        is 	short		fcmp_norm	- tbl_fcmp_op # NORM - ZERO
   10230  1.1        is 	short		fcmp_norm	- tbl_fcmp_op # NORM - INF
   10231  1.1        is 	short		fcmp_res_qnan	- tbl_fcmp_op # NORM - QNAN
   10232  1.1        is 	short		fcmp_nrm_dnrm 	- tbl_fcmp_op # NORM - DENORM
   10233  1.1        is 	short		fcmp_res_snan	- tbl_fcmp_op # NORM - SNAN
   10234  1.1        is 	short		tbl_fcmp_op	- tbl_fcmp_op #
   10235  1.1        is 	short		tbl_fcmp_op	- tbl_fcmp_op #
   10236  1.1        is 
   10237  1.1        is 	short		fcmp_norm	- tbl_fcmp_op # ZERO - NORM
   10238  1.1        is 	short		fcmp_norm	- tbl_fcmp_op # ZERO - ZERO
   10239  1.1        is 	short		fcmp_norm	- tbl_fcmp_op # ZERO - INF
   10240  1.1        is 	short		fcmp_res_qnan	- tbl_fcmp_op # ZERO - QNAN
   10241  1.1        is 	short		fcmp_dnrm_s	- tbl_fcmp_op # ZERO - DENORM
   10242  1.1        is 	short		fcmp_res_snan	- tbl_fcmp_op # ZERO - SNAN
   10243  1.1        is 	short		tbl_fcmp_op	- tbl_fcmp_op #
   10244  1.1        is 	short		tbl_fcmp_op	- tbl_fcmp_op #
   10245  1.1        is 
   10246  1.1        is 	short		fcmp_norm	- tbl_fcmp_op # INF - NORM
   10247  1.1        is 	short		fcmp_norm	- tbl_fcmp_op # INF - ZERO
   10248  1.1        is 	short		fcmp_norm	- tbl_fcmp_op # INF - INF
   10249  1.1        is 	short		fcmp_res_qnan	- tbl_fcmp_op # INF - QNAN
   10250  1.1        is 	short		fcmp_dnrm_s	- tbl_fcmp_op # INF - DENORM
   10251  1.1        is 	short		fcmp_res_snan	- tbl_fcmp_op # INF - SNAN
   10252  1.1        is 	short		tbl_fcmp_op	- tbl_fcmp_op #
   10253  1.1        is 	short		tbl_fcmp_op	- tbl_fcmp_op #
   10254  1.1        is 
   10255  1.1        is 	short		fcmp_res_qnan	- tbl_fcmp_op # QNAN - NORM
   10256  1.1        is 	short		fcmp_res_qnan	- tbl_fcmp_op # QNAN - ZERO
   10257  1.1        is 	short		fcmp_res_qnan	- tbl_fcmp_op # QNAN - INF
   10258  1.1        is 	short		fcmp_res_qnan	- tbl_fcmp_op # QNAN - QNAN
   10259  1.1        is 	short		fcmp_res_qnan	- tbl_fcmp_op # QNAN - DENORM
   10260  1.1        is 	short		fcmp_res_snan	- tbl_fcmp_op # QNAN - SNAN
   10261  1.1        is 	short		tbl_fcmp_op	- tbl_fcmp_op #
   10262  1.1        is 	short		tbl_fcmp_op	- tbl_fcmp_op #
   10263  1.1        is 
   10264  1.1        is 	short		fcmp_dnrm_nrm	- tbl_fcmp_op # DENORM - NORM
   10265  1.1        is 	short		fcmp_dnrm_d	- tbl_fcmp_op # DENORM - ZERO
   10266  1.1        is 	short		fcmp_dnrm_d	- tbl_fcmp_op # DENORM - INF
   10267  1.1        is 	short		fcmp_res_qnan	- tbl_fcmp_op # DENORM - QNAN
   10268  1.1        is 	short		fcmp_dnrm_sd	- tbl_fcmp_op # DENORM - DENORM
   10269  1.1        is 	short		fcmp_res_snan	- tbl_fcmp_op # DENORM - SNAN
   10270  1.1        is 	short		tbl_fcmp_op	- tbl_fcmp_op #
   10271  1.1        is 	short		tbl_fcmp_op	- tbl_fcmp_op #
   10272  1.1        is 
   10273  1.1        is 	short		fcmp_res_snan	- tbl_fcmp_op # SNAN - NORM
   10274  1.1        is 	short		fcmp_res_snan	- tbl_fcmp_op # SNAN - ZERO
   10275  1.1        is 	short		fcmp_res_snan	- tbl_fcmp_op # SNAN - INF
   10276  1.1        is 	short		fcmp_res_snan	- tbl_fcmp_op # SNAN - QNAN
   10277  1.1        is 	short		fcmp_res_snan	- tbl_fcmp_op # SNAN - DENORM
   10278  1.1        is 	short		fcmp_res_snan	- tbl_fcmp_op # SNAN - SNAN
   10279  1.1        is 	short		tbl_fcmp_op	- tbl_fcmp_op #
   10280  1.1        is 	short		tbl_fcmp_op	- tbl_fcmp_op #
   10281  1.1        is 
   10282  1.1        is # unlike all other functions for QNAN and SNAN, fcmp does NOT set the
   10283  1.1        is # 'N' bit for a negative QNAN or SNAN input so we must squelch it here.
   10284  1.1        is fcmp_res_qnan:
   10285  1.1        is 	bsr.l		res_qnan
   10286  1.1        is 	andi.b		&0xf7,FPSR_CC(%a6)
   10287  1.1        is 	rts
   10288  1.1        is fcmp_res_snan:
   10289  1.1        is 	bsr.l		res_snan
   10290  1.1        is 	andi.b		&0xf7,FPSR_CC(%a6)
   10291  1.1        is 	rts
   10292  1.1        is 
   10293  1.1        is #
   10294  1.1        is # DENORMs are a little more difficult.
   10295  1.1        is # If you have a 2 DENORMs, then you can just force the j-bit to a one
   10296  1.1        is # and use the fcmp_norm routine.
   10297  1.1        is # If you have a DENORM and an INF or ZERO, just force the DENORM's j-bit to a one
   10298  1.1        is # and use the fcmp_norm routine.
   10299  1.1        is # If you have a DENORM and a NORM with opposite signs, then use fcmp_norm, also.
   10300  1.1        is # But with a DENORM and a NORM of the same sign, the neg bit is set if the
   10301  1.1        is # (1) signs are (+) and the DENORM is the dst or
   10302  1.1        is # (2) signs are (-) and the DENORM is the src
   10303  1.1        is #
   10304  1.1        is 
   10305  1.1        is fcmp_dnrm_s:
   10306  1.1        is 	mov.w		SRC_EX(%a0),FP_SCR0_EX(%a6)
   10307  1.1        is 	mov.l		SRC_HI(%a0),%d0
   10308  1.1        is 	bset		&31,%d0			# DENORM src; make into small norm
   10309  1.1        is 	mov.l		%d0,FP_SCR0_HI(%a6)
   10310  1.1        is 	mov.l		SRC_LO(%a0),FP_SCR0_LO(%a6)
   10311  1.1        is 	lea		FP_SCR0(%a6),%a0
   10312  1.1        is 	bra.w		fcmp_norm
   10313  1.1        is 
   10314  1.1        is fcmp_dnrm_d:
   10315  1.1        is 	mov.l		DST_EX(%a1),FP_SCR0_EX(%a6)
   10316  1.1        is 	mov.l		DST_HI(%a1),%d0
   10317  1.1        is 	bset		&31,%d0			# DENORM src; make into small norm
   10318  1.1        is 	mov.l		%d0,FP_SCR0_HI(%a6)
   10319  1.1        is 	mov.l		DST_LO(%a1),FP_SCR0_LO(%a6)
   10320  1.1        is 	lea		FP_SCR0(%a6),%a1
   10321  1.1        is 	bra.w		fcmp_norm
   10322  1.1        is 
   10323  1.1        is fcmp_dnrm_sd:
   10324  1.1        is 	mov.w		DST_EX(%a1),FP_SCR1_EX(%a6)
   10325  1.1        is 	mov.w		SRC_EX(%a0),FP_SCR0_EX(%a6)
   10326  1.1        is 	mov.l		DST_HI(%a1),%d0
   10327  1.1        is 	bset		&31,%d0			# DENORM dst; make into small norm
   10328  1.1        is 	mov.l		%d0,FP_SCR1_HI(%a6)
   10329  1.1        is 	mov.l		SRC_HI(%a0),%d0
   10330  1.1        is 	bset		&31,%d0			# DENORM dst; make into small norm
   10331  1.1        is 	mov.l		%d0,FP_SCR0_HI(%a6)
   10332  1.1        is 	mov.l		DST_LO(%a1),FP_SCR1_LO(%a6)
   10333  1.1        is 	mov.l		SRC_LO(%a0),FP_SCR0_LO(%a6)
   10334  1.1        is 	lea		FP_SCR1(%a6),%a1
   10335  1.1        is 	lea		FP_SCR0(%a6),%a0
   10336  1.1        is 	bra.w		fcmp_norm
   10337  1.1        is 
   10338  1.1        is fcmp_nrm_dnrm:
   10339  1.1        is 	mov.b		SRC_EX(%a0),%d0		# determine if like signs
   10340  1.1        is 	mov.b		DST_EX(%a1),%d1
   10341  1.1        is 	eor.b		%d0,%d1
   10342  1.1        is 	bmi.w		fcmp_dnrm_s
   10343  1.1        is 
   10344  1.1        is # signs are the same, so must determine the answer ourselves.
   10345  1.1        is 	tst.b		%d0			# is src op negative?
   10346  1.1        is 	bmi.b		fcmp_nrm_dnrm_m		# yes
   10347  1.1        is 	rts
   10348  1.1        is fcmp_nrm_dnrm_m:
   10349  1.1        is 	mov.b		&neg_bmask,FPSR_CC(%a6)	# set 'Z' ccode bit
   10350  1.1        is 	rts
   10351  1.1        is 
   10352  1.1        is fcmp_dnrm_nrm:
   10353  1.1        is 	mov.b		SRC_EX(%a0),%d0		# determine if like signs
   10354  1.1        is 	mov.b		DST_EX(%a1),%d1
   10355  1.1        is 	eor.b		%d0,%d1
   10356  1.1        is 	bmi.w		fcmp_dnrm_d
   10357  1.1        is 
   10358  1.1        is # signs are the same, so must determine the answer ourselves.
   10359  1.1        is 	tst.b		%d0			# is src op negative?
   10360  1.1        is 	bpl.b		fcmp_dnrm_nrm_m		# no
   10361  1.1        is 	rts
   10362  1.1        is fcmp_dnrm_nrm_m:
   10363  1.1        is 	mov.b		&neg_bmask,FPSR_CC(%a6)	# set 'Z' ccode bit
   10364  1.1        is 	rts
   10365  1.1        is 
   10366  1.1        is #########################################################################
   10367  1.1        is # XDEF ****************************************************************	#
   10368  1.1        is # 	fsglmul(): emulates the fsglmul instruction			#
   10369  1.1        is #									#
   10370  1.1        is # XREF ****************************************************************	#
   10371  1.1        is #	scale_to_zero_src() - scale src exponent to zero		#
   10372  1.1        is #	scale_to_zero_dst() - scale dst exponent to zero		#
   10373  1.1        is #	unf_res4() - return default underflow result for sglop		#
   10374  1.1        is #	ovf_res() - return default overflow result			#
   10375  1.1        is # 	res_qnan() - return QNAN result					#
   10376  1.1        is # 	res_snan() - return SNAN result					#
   10377  1.1        is #									#
   10378  1.1        is # INPUT ***************************************************************	#
   10379  1.1        is #	a0 = pointer to extended precision source operand		#
   10380  1.1        is #	a1 = pointer to extended precision destination operand		#
   10381  1.1        is #	d0  rnd prec,mode						#
   10382  1.1        is #									#
   10383  1.1        is # OUTPUT **************************************************************	#
   10384  1.1        is #	fp0 = result							#
   10385  1.1        is #	fp1 = EXOP (if exception occurred)				#
   10386  1.1        is #									#
   10387  1.1        is # ALGORITHM ***********************************************************	#
   10388  1.1        is #	Handle NANs, infinities, and zeroes as special cases. Divide	#
   10389  1.1        is # norms/denorms into ext/sgl/dbl precision.				#
   10390  1.1        is #	For norms/denorms, scale the exponents such that a multiply	#
   10391  1.1        is # instruction won't cause an exception. Use the regular fsglmul to	#
   10392  1.1        is # compute a result. Check if the regular operands would have taken	#
   10393  1.1        is # an exception. If so, return the default overflow/underflow result	#
   10394  1.1        is # and return the EXOP if exceptions are enabled. Else, scale the 	#
   10395  1.1        is # result operand to the proper exponent.				#
   10396  1.1        is #									#
   10397  1.1        is #########################################################################
   10398  1.1        is 
   10399  1.1        is 	global		fsglmul
   10400  1.1        is fsglmul:
   10401  1.1        is 	mov.l		%d0,L_SCR3(%a6)		# store rnd info
   10402  1.1        is 
   10403  1.1        is 	clr.w		%d1
   10404  1.1        is 	mov.b		DTAG(%a6),%d1
   10405  1.1        is 	lsl.b		&0x3,%d1
   10406  1.1        is 	or.b		STAG(%a6),%d1
   10407  1.1        is 
   10408  1.1        is 	bne.w		fsglmul_not_norm	# optimize on non-norm input
   10409  1.1        is 
   10410  1.1        is fsglmul_norm:
   10411  1.1        is 	mov.w		DST_EX(%a1),FP_SCR1_EX(%a6)
   10412  1.1        is 	mov.l		DST_HI(%a1),FP_SCR1_HI(%a6)
   10413  1.1        is 	mov.l		DST_LO(%a1),FP_SCR1_LO(%a6)
   10414  1.1        is 
   10415  1.1        is 	mov.w		SRC_EX(%a0),FP_SCR0_EX(%a6)
   10416  1.1        is 	mov.l		SRC_HI(%a0),FP_SCR0_HI(%a6)
   10417  1.1        is 	mov.l		SRC_LO(%a0),FP_SCR0_LO(%a6)
   10418  1.1        is 
   10419  1.1        is 	bsr.l		scale_to_zero_src	# scale exponent
   10420  1.1        is 	mov.l		%d0,-(%sp)		# save scale factor 1
   10421  1.1        is 
   10422  1.1        is 	bsr.l		scale_to_zero_dst	# scale dst exponent
   10423  1.1        is 
   10424  1.1        is 	add.l		(%sp)+,%d0		# SCALE_FACTOR = scale1 + scale2
   10425  1.1        is 
   10426  1.1        is 	cmpi.l		%d0,&0x3fff-0x7ffe 	# would result ovfl?
   10427  1.1        is 	beq.w		fsglmul_may_ovfl	# result may rnd to overflow
   10428  1.1        is 	blt.w		fsglmul_ovfl		# result will overflow
   10429  1.1        is 
   10430  1.1        is 	cmpi.l		%d0,&0x3fff+0x0001 	# would result unfl?
   10431  1.1        is 	beq.w		fsglmul_may_unfl	# result may rnd to no unfl
   10432  1.1        is 	bgt.w		fsglmul_unfl		# result will underflow
   10433  1.1        is 
   10434  1.1        is fsglmul_normal:
   10435  1.1        is 	fmovm.x		FP_SCR1(%a6),&0x80	# load dst op
   10436  1.1        is 
   10437  1.1        is 	fmov.l		L_SCR3(%a6),%fpcr	# set FPCR
   10438  1.1        is 	fmov.l		&0x0,%fpsr		# clear FPSR
   10439  1.1        is 
   10440  1.1        is 	fsglmul.x	FP_SCR0(%a6),%fp0	# execute sgl multiply
   10441  1.1        is 
   10442  1.1        is 	fmov.l		%fpsr,%d1		# save status
   10443  1.1        is 	fmov.l		&0x0,%fpcr		# clear FPCR
   10444  1.1        is 
   10445  1.1        is 	or.l		%d1,USER_FPSR(%a6)	# save INEX2,N
   10446  1.1        is 
   10447  1.1        is fsglmul_normal_exit:
   10448  1.1        is 	fmovm.x		&0x80,FP_SCR0(%a6)	# store out result
   10449  1.1        is 	mov.l		%d2,-(%sp)		# save d2
   10450  1.1        is 	mov.w		FP_SCR0_EX(%a6),%d1	# load {sgn,exp}
   10451  1.1        is 	mov.l		%d1,%d2			# make a copy
   10452  1.1        is 	andi.l		&0x7fff,%d1		# strip sign
   10453  1.1        is 	andi.w		&0x8000,%d2		# keep old sign
   10454  1.1        is 	sub.l		%d0,%d1			# add scale factor
   10455  1.1        is 	or.w		%d2,%d1			# concat old sign,new exp
   10456  1.1        is 	mov.w		%d1,FP_SCR0_EX(%a6)	# insert new exponent
   10457  1.1        is 	mov.l		(%sp)+,%d2		# restore d2
   10458  1.1        is 	fmovm.x		FP_SCR0(%a6),&0x80	# return result in fp0
   10459  1.1        is 	rts
   10460  1.1        is 
   10461  1.1        is fsglmul_ovfl:
   10462  1.1        is 	fmovm.x		FP_SCR1(%a6),&0x80	# load dst op
   10463  1.1        is 
   10464  1.1        is 	fmov.l		L_SCR3(%a6),%fpcr	# set FPCR
   10465  1.1        is 	fmov.l		&0x0,%fpsr		# clear FPSR
   10466  1.1        is 
   10467  1.1        is 	fsglmul.x	FP_SCR0(%a6),%fp0	# execute sgl multiply
   10468  1.1        is 
   10469  1.1        is 	fmov.l		%fpsr,%d1		# save status
   10470  1.1        is 	fmov.l		&0x0,%fpcr		# clear FPCR
   10471  1.1        is 
   10472  1.1        is 	or.l		%d1,USER_FPSR(%a6)	# save INEX2,N
   10473  1.1        is 
   10474  1.1        is fsglmul_ovfl_tst:
   10475  1.1        is 
   10476  1.1        is # save setting this until now because this is where fsglmul_may_ovfl may jump in
   10477  1.1        is 	or.l		&ovfl_inx_mask, USER_FPSR(%a6) # set ovfl/aovfl/ainex
   10478  1.1        is 
   10479  1.1        is 	mov.b		FPCR_ENABLE(%a6),%d1
   10480  1.1        is 	andi.b		&0x13,%d1		# is OVFL or INEX enabled?
   10481  1.1        is 	bne.b		fsglmul_ovfl_ena	# yes
   10482  1.1        is 
   10483  1.1        is fsglmul_ovfl_dis:
   10484  1.1        is 	btst		&neg_bit,FPSR_CC(%a6)	# is result negative?
   10485  1.1        is 	sne		%d1			# set sign param accordingly
   10486  1.1        is 	mov.l		L_SCR3(%a6),%d0		# pass prec:rnd
   10487  1.1        is 	andi.b		&0x30,%d0		# force prec = ext
   10488  1.1        is 	bsr.l		ovf_res			# calculate default result
   10489  1.1        is 	or.b		%d0,FPSR_CC(%a6)	# set INF,N if applicable
   10490  1.1        is 	fmovm.x		(%a0),&0x80		# return default result in fp0
   10491  1.1        is 	rts
   10492  1.1        is 
   10493  1.1        is fsglmul_ovfl_ena:
   10494  1.1        is 	fmovm.x		&0x80,FP_SCR0(%a6)	# move result to stack
   10495  1.1        is 
   10496  1.1        is 	mov.l		%d2,-(%sp)		# save d2
   10497  1.1        is 	mov.w		FP_SCR0_EX(%a6),%d1	# fetch {sgn,exp}
   10498  1.1        is 	mov.l		%d1,%d2			# make a copy
   10499  1.1        is 	andi.l		&0x7fff,%d1		# strip sign
   10500  1.1        is 	sub.l		%d0,%d1			# add scale factor
   10501  1.1        is 	subi.l		&0x6000,%d1		# subtract bias
   10502  1.1        is 	andi.w		&0x7fff,%d1
   10503  1.1        is 	andi.w		&0x8000,%d2		# keep old sign
   10504  1.1        is 	or.w		%d2,%d1			# concat old sign,new exp
   10505  1.1        is 	mov.w		%d1,FP_SCR0_EX(%a6)	# insert new exponent
   10506  1.1        is 	mov.l		(%sp)+,%d2		# restore d2
   10507  1.1        is 	fmovm.x		FP_SCR0(%a6),&0x40	# return EXOP in fp1
   10508  1.1        is 	bra.b		fsglmul_ovfl_dis
   10509  1.1        is 
   10510  1.1        is fsglmul_may_ovfl:
   10511  1.1        is 	fmovm.x		FP_SCR1(%a6),&0x80	# load dst op
   10512  1.1        is 
   10513  1.1        is 	fmov.l		L_SCR3(%a6),%fpcr	# set FPCR
   10514  1.1        is 	fmov.l		&0x0,%fpsr		# clear FPSR
   10515  1.1        is 
   10516  1.1        is 	fsglmul.x	FP_SCR0(%a6),%fp0	# execute sgl multiply
   10517  1.1        is 
   10518  1.1        is 	fmov.l		%fpsr,%d1		# save status
   10519  1.1        is 	fmov.l		&0x0,%fpcr		# clear FPCR
   10520  1.1        is 
   10521  1.1        is 	or.l		%d1,USER_FPSR(%a6)	# save INEX2,N
   10522  1.1        is 
   10523  1.1        is 	fabs.x		%fp0,%fp1		# make a copy of result
   10524  1.1        is 	fcmp.b		%fp1,&0x2		# is |result| >= 2.b?
   10525  1.1        is 	fbge.w		fsglmul_ovfl_tst	# yes; overflow has occurred
   10526  1.1        is 
   10527  1.1        is # no, it didn't overflow; we have correct result
   10528  1.1        is 	bra.w		fsglmul_normal_exit
   10529  1.1        is 
   10530  1.1        is fsglmul_unfl:
   10531  1.1        is 	bset		&unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
   10532  1.1        is 
   10533  1.1        is 	fmovm.x		FP_SCR1(%a6),&0x80	# load dst op
   10534  1.1        is 
   10535  1.1        is 	fmov.l		&rz_mode*0x10,%fpcr	# set FPCR
   10536  1.1        is 	fmov.l		&0x0,%fpsr		# clear FPSR
   10537  1.1        is 
   10538  1.1        is 	fsglmul.x	FP_SCR0(%a6),%fp0	# execute sgl multiply
   10539  1.1        is 
   10540  1.1        is 	fmov.l		%fpsr,%d1		# save status
   10541  1.1        is 	fmov.l		&0x0,%fpcr		# clear FPCR
   10542  1.1        is 
   10543  1.1        is 	or.l		%d1,USER_FPSR(%a6)	# save INEX2,N
   10544  1.1        is 
   10545  1.1        is 	mov.b		FPCR_ENABLE(%a6),%d1
   10546  1.1        is 	andi.b		&0x0b,%d1		# is UNFL or INEX enabled?
   10547  1.1        is 	bne.b		fsglmul_unfl_ena	# yes
   10548  1.1        is 
   10549  1.1        is fsglmul_unfl_dis:
   10550  1.1        is 	fmovm.x		&0x80,FP_SCR0(%a6)	# store out result
   10551  1.1        is 
   10552  1.1        is 	lea		FP_SCR0(%a6),%a0	# pass: result addr
   10553  1.1        is 	mov.l		L_SCR3(%a6),%d1		# pass: rnd prec,mode
   10554  1.1        is 	bsr.l		unf_res4		# calculate default result
   10555  1.1        is 	or.b		%d0,FPSR_CC(%a6)	# 'Z' bit may have been set
   10556  1.1        is 	fmovm.x		FP_SCR0(%a6),&0x80	# return default result in fp0
   10557  1.1        is 	rts
   10558  1.1        is 
   10559  1.1        is #
   10560  1.1        is # UNFL is enabled.
   10561  1.1        is #
   10562  1.1        is fsglmul_unfl_ena:
   10563  1.1        is 	fmovm.x		FP_SCR1(%a6),&0x40	# load dst op
   10564  1.1        is 
   10565  1.1        is 	fmov.l		L_SCR3(%a6),%fpcr	# set FPCR
   10566  1.1        is 	fmov.l		&0x0,%fpsr		# clear FPSR
   10567  1.1        is 
   10568  1.1        is 	fsglmul.x	FP_SCR0(%a6),%fp1	# execute sgl multiply
   10569  1.1        is 
   10570  1.1        is 	fmov.l		&0x0,%fpcr		# clear FPCR
   10571  1.1        is 
   10572  1.1        is 	fmovm.x		&0x40,FP_SCR0(%a6)	# save result to stack
   10573  1.1        is 	mov.l		%d2,-(%sp)		# save d2
   10574  1.1        is 	mov.w		FP_SCR0_EX(%a6),%d1	# fetch {sgn,exp}
   10575  1.1        is 	mov.l		%d1,%d2			# make a copy
   10576  1.1        is 	andi.l		&0x7fff,%d1		# strip sign
   10577  1.1        is 	andi.w		&0x8000,%d2		# keep old sign
   10578  1.1        is 	sub.l		%d0,%d1			# add scale factor
   10579  1.1        is 	addi.l		&0x6000,%d1		# add bias
   10580  1.1        is 	andi.w		&0x7fff,%d1
   10581  1.1        is 	or.w		%d2,%d1			# concat old sign,new exp
   10582  1.1        is 	mov.w		%d1,FP_SCR0_EX(%a6)	# insert new exponent
   10583  1.1        is 	mov.l		(%sp)+,%d2		# restore d2
   10584  1.1        is 	fmovm.x		FP_SCR0(%a6),&0x40	# return EXOP in fp1
   10585  1.1        is 	bra.w		fsglmul_unfl_dis
   10586  1.1        is 
   10587  1.1        is fsglmul_may_unfl:
   10588  1.1        is 	fmovm.x		FP_SCR1(%a6),&0x80	# load dst op
   10589  1.1        is 
   10590  1.1        is 	fmov.l		L_SCR3(%a6),%fpcr	# set FPCR
   10591  1.1        is 	fmov.l		&0x0,%fpsr		# clear FPSR
   10592  1.1        is 
   10593  1.1        is 	fsglmul.x	FP_SCR0(%a6),%fp0	# execute sgl multiply
   10594  1.1        is 
   10595  1.1        is 	fmov.l		%fpsr,%d1		# save status
   10596  1.1        is 	fmov.l		&0x0,%fpcr		# clear FPCR
   10597  1.1        is 
   10598  1.1        is 	or.l		%d1,USER_FPSR(%a6)	# save INEX2,N
   10599  1.1        is 
   10600  1.1        is 	fabs.x		%fp0,%fp1		# make a copy of result
   10601  1.1        is 	fcmp.b		%fp1,&0x2		# is |result| > 2.b?
   10602  1.1        is 	fbgt.w		fsglmul_normal_exit	# no; no underflow occurred
   10603  1.1        is 	fblt.w		fsglmul_unfl		# yes; underflow occurred
   10604  1.1        is 
   10605  1.1        is #
   10606  1.1        is # we still don't know if underflow occurred. result is ~ equal to 2. but,
   10607  1.1        is # we don't know if the result was an underflow that rounded up to a 2 or
   10608  1.1        is # a normalized number that rounded down to a 2. so, redo the entire operation
   10609  1.1        is # using RZ as the rounding mode to see what the pre-rounded result is.
   10610  1.1        is # this case should be relatively rare.
   10611  1.1        is #
   10612  1.1        is 	fmovm.x		FP_SCR1(%a6),&0x40	# load dst op into fp1
   10613  1.1        is 
   10614  1.1        is 	mov.l		L_SCR3(%a6),%d1
   10615  1.1        is 	andi.b		&0xc0,%d1		# keep rnd prec
   10616  1.1        is 	ori.b		&rz_mode*0x10,%d1	# insert RZ
   10617  1.1        is 
   10618  1.1        is 	fmov.l		%d1,%fpcr		# set FPCR
   10619  1.1        is 	fmov.l		&0x0,%fpsr		# clear FPSR
   10620  1.1        is 
   10621  1.1        is 	fsglmul.x	FP_SCR0(%a6),%fp1	# execute sgl multiply
   10622  1.1        is 
   10623  1.1        is 	fmov.l		&0x0,%fpcr		# clear FPCR
   10624  1.1        is 	fabs.x		%fp1			# make absolute value
   10625  1.1        is 	fcmp.b		%fp1,&0x2		# is |result| < 2.b?
   10626  1.1        is 	fbge.w		fsglmul_normal_exit	# no; no underflow occurred
   10627  1.1        is 	bra.w		fsglmul_unfl		# yes, underflow occurred
   10628  1.1        is 
   10629  1.1        is ##############################################################################
   10630  1.1        is 
   10631  1.1        is #
   10632  1.1        is # Single Precision Multiply: inputs are not both normalized; what are they?
   10633  1.1        is #
   10634  1.1        is fsglmul_not_norm:
   10635  1.1        is 	mov.w		(tbl_fsglmul_op.b,%pc,%d1.w*2),%d1
   10636  1.1        is 	jmp		(tbl_fsglmul_op.b,%pc,%d1.w*1)
   10637  1.1        is 
   10638  1.1        is 	swbeg		&48
   10639  1.1        is tbl_fsglmul_op:
   10640  1.1        is 	short		fsglmul_norm		- tbl_fsglmul_op # NORM x NORM
   10641  1.1        is 	short		fsglmul_zero		- tbl_fsglmul_op # NORM x ZERO
   10642  1.1        is 	short		fsglmul_inf_src		- tbl_fsglmul_op # NORM x INF
   10643  1.1        is 	short		fsglmul_res_qnan	- tbl_fsglmul_op # NORM x QNAN
   10644  1.1        is 	short		fsglmul_norm		- tbl_fsglmul_op # NORM x DENORM
   10645  1.1        is 	short		fsglmul_res_snan	- tbl_fsglmul_op # NORM x SNAN
   10646  1.1        is 	short		tbl_fsglmul_op		- tbl_fsglmul_op #
   10647  1.1        is 	short		tbl_fsglmul_op		- tbl_fsglmul_op #
   10648  1.1        is 
   10649  1.1        is 	short		fsglmul_zero		- tbl_fsglmul_op # ZERO x NORM
   10650  1.1        is 	short		fsglmul_zero		- tbl_fsglmul_op # ZERO x ZERO
   10651  1.1        is 	short		fsglmul_res_operr	- tbl_fsglmul_op # ZERO x INF
   10652  1.1        is 	short		fsglmul_res_qnan	- tbl_fsglmul_op # ZERO x QNAN
   10653  1.1        is 	short		fsglmul_zero		- tbl_fsglmul_op # ZERO x DENORM
   10654  1.1        is 	short		fsglmul_res_snan	- tbl_fsglmul_op # ZERO x SNAN
   10655  1.1        is 	short		tbl_fsglmul_op		- tbl_fsglmul_op #
   10656  1.1        is 	short		tbl_fsglmul_op		- tbl_fsglmul_op #
   10657  1.1        is 
   10658  1.1        is 	short		fsglmul_inf_dst		- tbl_fsglmul_op # INF x NORM
   10659  1.1        is 	short		fsglmul_res_operr	- tbl_fsglmul_op # INF x ZERO
   10660  1.1        is 	short		fsglmul_inf_dst		- tbl_fsglmul_op # INF x INF
   10661  1.1        is 	short		fsglmul_res_qnan	- tbl_fsglmul_op # INF x QNAN
   10662  1.1        is 	short		fsglmul_inf_dst		- tbl_fsglmul_op # INF x DENORM
   10663  1.1        is 	short		fsglmul_res_snan	- tbl_fsglmul_op # INF x SNAN
   10664  1.1        is 	short		tbl_fsglmul_op		- tbl_fsglmul_op #
   10665  1.1        is 	short		tbl_fsglmul_op		- tbl_fsglmul_op #
   10666  1.1        is 
   10667  1.1        is 	short		fsglmul_res_qnan	- tbl_fsglmul_op # QNAN x NORM
   10668  1.1        is 	short		fsglmul_res_qnan	- tbl_fsglmul_op # QNAN x ZERO
   10669  1.1        is 	short		fsglmul_res_qnan	- tbl_fsglmul_op # QNAN x INF
   10670  1.1        is 	short		fsglmul_res_qnan	- tbl_fsglmul_op # QNAN x QNAN
   10671  1.1        is 	short		fsglmul_res_qnan	- tbl_fsglmul_op # QNAN x DENORM
   10672  1.1        is 	short		fsglmul_res_snan	- tbl_fsglmul_op # QNAN x SNAN
   10673  1.1        is 	short		tbl_fsglmul_op		- tbl_fsglmul_op #
   10674  1.1        is 	short		tbl_fsglmul_op		- tbl_fsglmul_op #
   10675  1.1        is 
   10676  1.1        is 	short		fsglmul_norm		- tbl_fsglmul_op # NORM x NORM
   10677  1.1        is 	short		fsglmul_zero		- tbl_fsglmul_op # NORM x ZERO
   10678  1.1        is 	short		fsglmul_inf_src		- tbl_fsglmul_op # NORM x INF
   10679  1.1        is 	short		fsglmul_res_qnan	- tbl_fsglmul_op # NORM x QNAN
   10680  1.1        is 	short		fsglmul_norm		- tbl_fsglmul_op # NORM x DENORM
   10681  1.1        is 	short		fsglmul_res_snan	- tbl_fsglmul_op # NORM x SNAN
   10682  1.1        is 	short		tbl_fsglmul_op		- tbl_fsglmul_op #
   10683  1.1        is 	short		tbl_fsglmul_op		- tbl_fsglmul_op #
   10684  1.1        is 
   10685  1.1        is 	short		fsglmul_res_snan	- tbl_fsglmul_op # SNAN x NORM
   10686  1.1        is 	short		fsglmul_res_snan	- tbl_fsglmul_op # SNAN x ZERO
   10687  1.1        is 	short		fsglmul_res_snan	- tbl_fsglmul_op # SNAN x INF
   10688  1.1        is 	short		fsglmul_res_snan	- tbl_fsglmul_op # SNAN x QNAN
   10689  1.1        is 	short		fsglmul_res_snan	- tbl_fsglmul_op # SNAN x DENORM
   10690  1.1        is 	short		fsglmul_res_snan	- tbl_fsglmul_op # SNAN x SNAN
   10691  1.1        is 	short		tbl_fsglmul_op		- tbl_fsglmul_op #
   10692  1.1        is 	short		tbl_fsglmul_op		- tbl_fsglmul_op #
   10693  1.1        is 
   10694  1.1        is fsglmul_res_operr:
   10695  1.1        is 	bra.l		res_operr
   10696  1.1        is fsglmul_res_snan:
   10697  1.1        is 	bra.l		res_snan
   10698  1.1        is fsglmul_res_qnan:
   10699  1.1        is 	bra.l		res_qnan
   10700  1.1        is fsglmul_zero:
   10701  1.1        is 	bra.l		fmul_zero
   10702  1.1        is fsglmul_inf_src:
   10703  1.1        is 	bra.l		fmul_inf_src
   10704  1.1        is fsglmul_inf_dst:
   10705  1.1        is 	bra.l		fmul_inf_dst
   10706  1.1        is 
   10707  1.1        is #########################################################################
   10708  1.1        is # XDEF ****************************************************************	#
   10709  1.1        is # 	fsgldiv(): emulates the fsgldiv instruction			#
   10710  1.1        is #									#
   10711  1.1        is # XREF ****************************************************************	#
   10712  1.1        is #	scale_to_zero_src() - scale src exponent to zero		#
   10713  1.1        is #	scale_to_zero_dst() - scale dst exponent to zero		#
   10714  1.1        is #	unf_res4() - return default underflow result for sglop		#
   10715  1.1        is #	ovf_res() - return default overflow result			#
   10716  1.1        is # 	res_qnan() - return QNAN result					#
   10717  1.1        is # 	res_snan() - return SNAN result					#
   10718  1.1        is #									#
   10719  1.1        is # INPUT ***************************************************************	#
   10720  1.1        is #	a0 = pointer to extended precision source operand		#
   10721  1.1        is #	a1 = pointer to extended precision destination operand		#
   10722  1.1        is #	d0  rnd prec,mode						#
   10723  1.1        is #									#
   10724  1.1        is # OUTPUT **************************************************************	#
   10725  1.1        is #	fp0 = result							#
   10726  1.1        is #	fp1 = EXOP (if exception occurred)				#
   10727  1.1        is #									#
   10728  1.1        is # ALGORITHM ***********************************************************	#
   10729  1.1        is #	Handle NANs, infinities, and zeroes as special cases. Divide	#
   10730  1.1        is # norms/denorms into ext/sgl/dbl precision.				#
   10731  1.1        is #	For norms/denorms, scale the exponents such that a divide	#
   10732  1.1        is # instruction won't cause an exception. Use the regular fsgldiv to	#
   10733  1.1        is # compute a result. Check if the regular operands would have taken	#
   10734  1.1        is # an exception. If so, return the default overflow/underflow result	#
   10735  1.1        is # and return the EXOP if exceptions are enabled. Else, scale the 	#
   10736  1.1        is # result operand to the proper exponent.				#
   10737  1.1        is #									#
   10738  1.1        is #########################################################################
   10739  1.1        is 
   10740  1.1        is 	global		fsgldiv
   10741  1.1        is fsgldiv:
   10742  1.1        is 	mov.l		%d0,L_SCR3(%a6)		# store rnd info
   10743  1.1        is 
   10744  1.1        is 	clr.w		%d1
   10745  1.1        is 	mov.b		DTAG(%a6),%d1
   10746  1.1        is 	lsl.b		&0x3,%d1
   10747  1.1        is 	or.b		STAG(%a6),%d1		# combine src tags
   10748  1.1        is 
   10749  1.1        is 	bne.w		fsgldiv_not_norm	# optimize on non-norm input
   10750  1.1        is 
   10751  1.1        is #
   10752  1.1        is # DIVIDE: NORMs and DENORMs ONLY!
   10753  1.1        is #
   10754  1.1        is fsgldiv_norm:
   10755  1.1        is 	mov.w		DST_EX(%a1),FP_SCR1_EX(%a6)
   10756  1.1        is 	mov.l		DST_HI(%a1),FP_SCR1_HI(%a6)
   10757  1.1        is 	mov.l		DST_LO(%a1),FP_SCR1_LO(%a6)
   10758  1.1        is 
   10759  1.1        is 	mov.w		SRC_EX(%a0),FP_SCR0_EX(%a6)
   10760  1.1        is 	mov.l		SRC_HI(%a0),FP_SCR0_HI(%a6)
   10761  1.1        is 	mov.l		SRC_LO(%a0),FP_SCR0_LO(%a6)
   10762  1.1        is 
   10763  1.1        is 	bsr.l		scale_to_zero_src	# calculate scale factor 1
   10764  1.1        is 	mov.l		%d0,-(%sp)		# save scale factor 1
   10765  1.1        is 
   10766  1.1        is 	bsr.l		scale_to_zero_dst	# calculate scale factor 2
   10767  1.1        is 
   10768  1.1        is 	neg.l		(%sp)			# S.F. = scale1 - scale2
   10769  1.1        is 	add.l		%d0,(%sp)
   10770  1.1        is 
   10771  1.1        is 	mov.w		2+L_SCR3(%a6),%d1	# fetch precision,mode
   10772  1.1        is 	lsr.b		&0x6,%d1
   10773  1.1        is 	mov.l		(%sp)+,%d0
   10774  1.1        is 	cmpi.l		%d0,&0x3fff-0x7ffe
   10775  1.1        is 	ble.w		fsgldiv_may_ovfl
   10776  1.1        is 
   10777  1.1        is 	cmpi.l		%d0,&0x3fff-0x0000 	# will result underflow?
   10778  1.1        is 	beq.w		fsgldiv_may_unfl	# maybe
   10779  1.1        is 	bgt.w		fsgldiv_unfl		# yes; go handle underflow
   10780  1.1        is 
   10781  1.1        is fsgldiv_normal:
   10782  1.1        is 	fmovm.x		FP_SCR1(%a6),&0x80	# load dst op
   10783  1.1        is 
   10784  1.1        is 	fmov.l		L_SCR3(%a6),%fpcr	# save FPCR
   10785  1.1        is 	fmov.l		&0x0,%fpsr		# clear FPSR
   10786  1.1        is 
   10787  1.1        is 	fsgldiv.x	FP_SCR0(%a6),%fp0	# perform sgl divide
   10788  1.1        is 
   10789  1.1        is 	fmov.l		%fpsr,%d1		# save FPSR
   10790  1.1        is 	fmov.l		&0x0,%fpcr		# clear FPCR
   10791  1.1        is 
   10792  1.1        is 	or.l		%d1,USER_FPSR(%a6)	# save INEX2,N
   10793  1.1        is 
   10794  1.1        is fsgldiv_normal_exit:
   10795  1.1        is 	fmovm.x		&0x80,FP_SCR0(%a6)	# store result on stack
   10796  1.1        is 	mov.l		%d2,-(%sp)		# save d2
   10797  1.1        is 	mov.w		FP_SCR0_EX(%a6),%d1	# load {sgn,exp}
   10798  1.1        is 	mov.l		%d1,%d2			# make a copy
   10799  1.1        is 	andi.l		&0x7fff,%d1		# strip sign
   10800  1.1        is 	andi.w		&0x8000,%d2		# keep old sign
   10801  1.1        is 	sub.l		%d0,%d1			# add scale factor
   10802  1.1        is 	or.w		%d2,%d1			# concat old sign,new exp
   10803  1.1        is 	mov.w		%d1,FP_SCR0_EX(%a6)	# insert new exponent
   10804  1.1        is 	mov.l		(%sp)+,%d2		# restore d2
   10805  1.1        is 	fmovm.x		FP_SCR0(%a6),&0x80	# return result in fp0
   10806  1.1        is 	rts
   10807  1.1        is 
   10808  1.1        is fsgldiv_may_ovfl:
   10809  1.1        is 	fmovm.x		FP_SCR1(%a6),&0x80	# load dst op
   10810  1.1        is 
   10811  1.1        is 	fmov.l		L_SCR3(%a6),%fpcr	# set FPCR
   10812  1.1        is 	fmov.l		&0x0,%fpsr		# set FPSR
   10813  1.1        is 
   10814  1.1        is 	fsgldiv.x	FP_SCR0(%a6),%fp0	# execute divide
   10815  1.1        is 
   10816  1.1        is 	fmov.l		%fpsr,%d1
   10817  1.1        is 	fmov.l		&0x0,%fpcr
   10818  1.1        is 
   10819  1.1        is 	or.l		%d1,USER_FPSR(%a6)	# save INEX,N
   10820  1.1        is 
   10821  1.1        is 	fmovm.x		&0x01,-(%sp)		# save result to stack
   10822  1.1        is 	mov.w		(%sp),%d1		# fetch new exponent
   10823  1.1        is 	add.l		&0xc,%sp		# clear result
   10824  1.1        is 	andi.l		&0x7fff,%d1		# strip sign
   10825  1.1        is 	sub.l		%d0,%d1			# add scale factor
   10826  1.1        is 	cmp.l		%d1,&0x7fff		# did divide overflow?
   10827  1.1        is 	blt.b		fsgldiv_normal_exit
   10828  1.1        is 
   10829  1.1        is fsgldiv_ovfl_tst:
   10830  1.1        is 	or.w		&ovfl_inx_mask,2+USER_FPSR(%a6) # set ovfl/aovfl/ainex
   10831  1.1        is 
   10832  1.1        is 	mov.b		FPCR_ENABLE(%a6),%d1
   10833  1.1        is 	andi.b		&0x13,%d1		# is OVFL or INEX enabled?
   10834  1.1        is 	bne.b		fsgldiv_ovfl_ena	# yes
   10835  1.1        is 
   10836  1.1        is fsgldiv_ovfl_dis:
   10837  1.1        is 	btst		&neg_bit,FPSR_CC(%a6) 	# is result negative
   10838  1.1        is 	sne		%d1			# set sign param accordingly
   10839  1.1        is 	mov.l		L_SCR3(%a6),%d0		# pass prec:rnd
   10840  1.1        is 	andi.b		&0x30,%d0		# kill precision
   10841  1.1        is 	bsr.l		ovf_res			# calculate default result
   10842  1.1        is 	or.b		%d0,FPSR_CC(%a6)	# set INF if applicable
   10843  1.1        is 	fmovm.x		(%a0),&0x80		# return default result in fp0
   10844  1.1        is 	rts
   10845  1.1        is 
   10846  1.1        is fsgldiv_ovfl_ena:
   10847  1.1        is 	fmovm.x		&0x80,FP_SCR0(%a6)	# move result to stack
   10848  1.1        is 
   10849  1.1        is 	mov.l		%d2,-(%sp)		# save d2
   10850  1.1        is 	mov.w		FP_SCR0_EX(%a6),%d1	# fetch {sgn,exp}
   10851  1.1        is 	mov.l		%d1,%d2			# make a copy
   10852  1.1        is 	andi.l		&0x7fff,%d1		# strip sign
   10853  1.1        is 	andi.w		&0x8000,%d2		# keep old sign
   10854  1.1        is 	sub.l		%d0,%d1			# add scale factor
   10855  1.1        is 	subi.l		&0x6000,%d1		# subtract new bias
   10856  1.1        is 	andi.w		&0x7fff,%d1		# clear ms bit
   10857  1.1        is 	or.w		%d2,%d1			# concat old sign,new exp
   10858  1.1        is 	mov.w		%d1,FP_SCR0_EX(%a6)	# insert new exponent
   10859  1.1        is 	mov.l		(%sp)+,%d2		# restore d2
   10860  1.1        is 	fmovm.x		FP_SCR0(%a6),&0x40	# return EXOP in fp1
   10861  1.1        is 	bra.b		fsgldiv_ovfl_dis
   10862  1.1        is 
   10863  1.1        is fsgldiv_unfl:
   10864  1.1        is 	bset		&unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
   10865  1.1        is 
   10866  1.1        is 	fmovm.x		FP_SCR1(%a6),&0x80	# load dst op
   10867  1.1        is 
   10868  1.1        is 	fmov.l		&rz_mode*0x10,%fpcr	# set FPCR
   10869  1.1        is 	fmov.l		&0x0,%fpsr		# clear FPSR
   10870  1.1        is 
   10871  1.1        is 	fsgldiv.x	FP_SCR0(%a6),%fp0	# execute sgl divide
   10872  1.1        is 
   10873  1.1        is 	fmov.l		%fpsr,%d1		# save status
   10874  1.1        is 	fmov.l		&0x0,%fpcr		# clear FPCR
   10875  1.1        is 
   10876  1.1        is 	or.l		%d1,USER_FPSR(%a6)	# save INEX2,N
   10877  1.1        is 
   10878  1.1        is 	mov.b		FPCR_ENABLE(%a6),%d1
   10879  1.1        is 	andi.b		&0x0b,%d1		# is UNFL or INEX enabled?
   10880  1.1        is 	bne.b		fsgldiv_unfl_ena	# yes
   10881  1.1        is 
   10882  1.1        is fsgldiv_unfl_dis:
   10883  1.1        is 	fmovm.x		&0x80,FP_SCR0(%a6)	# store out result
   10884  1.1        is 
   10885  1.1        is 	lea		FP_SCR0(%a6),%a0	# pass: result addr
   10886  1.1        is 	mov.l		L_SCR3(%a6),%d1		# pass: rnd prec,mode
   10887  1.1        is 	bsr.l		unf_res4		# calculate default result
   10888  1.1        is 	or.b		%d0,FPSR_CC(%a6)	# 'Z' bit may have been set
   10889  1.1        is 	fmovm.x		FP_SCR0(%a6),&0x80	# return default result in fp0
   10890  1.1        is 	rts
   10891  1.1        is 
   10892  1.1        is #
   10893  1.1        is # UNFL is enabled.
   10894  1.1        is #
   10895  1.1        is fsgldiv_unfl_ena:
   10896  1.1        is 	fmovm.x		FP_SCR1(%a6),&0x40	# load dst op
   10897  1.1        is 
   10898  1.1        is 	fmov.l		L_SCR3(%a6),%fpcr	# set FPCR
   10899  1.1        is 	fmov.l		&0x0,%fpsr		# clear FPSR
   10900  1.1        is 
   10901  1.1        is 	fsgldiv.x	FP_SCR0(%a6),%fp1	# execute sgl divide
   10902  1.1        is 
   10903  1.1        is 	fmov.l		&0x0,%fpcr		# clear FPCR
   10904  1.1        is 
   10905  1.1        is 	fmovm.x		&0x40,FP_SCR0(%a6)	# save result to stack
   10906  1.1        is 	mov.l		%d2,-(%sp)		# save d2
   10907  1.1        is 	mov.w		FP_SCR0_EX(%a6),%d1	# fetch {sgn,exp}
   10908  1.1        is 	mov.l		%d1,%d2			# make a copy
   10909  1.1        is 	andi.l		&0x7fff,%d1		# strip sign
   10910  1.1        is 	andi.w		&0x8000,%d2		# keep old sign
   10911  1.1        is 	sub.l		%d0,%d1			# add scale factor
   10912  1.1        is 	addi.l		&0x6000,%d1		# add bias
   10913  1.1        is 	andi.w		&0x7fff,%d1		# clear top bit
   10914  1.1        is 	or.w		%d2,%d1			# concat old sign, new exp
   10915  1.1        is 	mov.w		%d1,FP_SCR0_EX(%a6)	# insert new exponent
   10916  1.1        is 	mov.l		(%sp)+,%d2		# restore d2
   10917  1.1        is 	fmovm.x		FP_SCR0(%a6),&0x40	# return EXOP in fp1
   10918  1.1        is 	bra.b		fsgldiv_unfl_dis
   10919  1.1        is 
   10920  1.1        is #
   10921  1.1        is # the divide operation MAY underflow:
   10922  1.1        is #
   10923  1.1        is fsgldiv_may_unfl:
   10924  1.1        is 	fmovm.x		FP_SCR1(%a6),&0x80	# load dst op
   10925  1.1        is 
   10926  1.1        is 	fmov.l		L_SCR3(%a6),%fpcr	# set FPCR
   10927  1.1        is 	fmov.l		&0x0,%fpsr		# clear FPSR
   10928  1.1        is 
   10929  1.1        is 	fsgldiv.x	FP_SCR0(%a6),%fp0	# execute sgl divide
   10930  1.1        is 
   10931  1.1        is 	fmov.l		%fpsr,%d1		# save status
   10932  1.1        is 	fmov.l		&0x0,%fpcr		# clear FPCR
   10933  1.1        is 
   10934  1.1        is 	or.l		%d1,USER_FPSR(%a6)	# save INEX2,N
   10935  1.1        is 
   10936  1.1        is 	fabs.x		%fp0,%fp1		# make a copy of result
   10937  1.1        is 	fcmp.b		%fp1,&0x1		# is |result| > 1.b?
   10938  1.1        is 	fbgt.w		fsgldiv_normal_exit	# no; no underflow occurred
   10939  1.1        is 	fblt.w		fsgldiv_unfl		# yes; underflow occurred
   10940  1.1        is 
   10941  1.1        is #
   10942  1.1        is # we still don't know if underflow occurred. result is ~ equal to 1. but,
   10943  1.1        is # we don't know if the result was an underflow that rounded up to a 1
   10944  1.1        is # or a normalized number that rounded down to a 1. so, redo the entire
   10945  1.1        is # operation using RZ as the rounding mode to see what the pre-rounded
   10946  1.1        is # result is. this case should be relatively rare.
   10947  1.1        is #
   10948  1.1        is 	fmovm.x		FP_SCR1(%a6),&0x40	# load dst op into %fp1
   10949  1.1        is 
   10950  1.1        is 	clr.l		%d1			# clear scratch register
   10951  1.1        is 	ori.b		&rz_mode*0x10,%d1	# force RZ rnd mode
   10952  1.1        is 
   10953  1.1        is 	fmov.l		%d1,%fpcr		# set FPCR
   10954  1.1        is 	fmov.l		&0x0,%fpsr		# clear FPSR
   10955  1.1        is 
   10956  1.1        is 	fsgldiv.x	FP_SCR0(%a6),%fp1	# execute sgl divide
   10957  1.1        is 
   10958  1.1        is 	fmov.l		&0x0,%fpcr		# clear FPCR
   10959  1.1        is 	fabs.x		%fp1			# make absolute value
   10960  1.1        is 	fcmp.b		%fp1,&0x1		# is |result| < 1.b?
   10961  1.1        is 	fbge.w		fsgldiv_normal_exit	# no; no underflow occurred
   10962  1.1        is 	bra.w		fsgldiv_unfl		# yes; underflow occurred
   10963  1.1        is 
   10964  1.1        is ############################################################################
   10965  1.1        is 
   10966  1.1        is #
   10967  1.1        is # Divide: inputs are not both normalized; what are they?
   10968  1.1        is #
   10969  1.1        is fsgldiv_not_norm:
   10970  1.1        is 	mov.w		(tbl_fsgldiv_op.b,%pc,%d1.w*2),%d1
   10971  1.1        is 	jmp		(tbl_fsgldiv_op.b,%pc,%d1.w*1)
   10972  1.1        is 
   10973  1.1        is 	swbeg		&48
   10974  1.1        is tbl_fsgldiv_op:
   10975  1.1        is 	short		fsgldiv_norm		- tbl_fsgldiv_op # NORM / NORM
   10976  1.1        is 	short		fsgldiv_inf_load	- tbl_fsgldiv_op # NORM / ZERO
   10977  1.1        is 	short		fsgldiv_zero_load	- tbl_fsgldiv_op # NORM / INF
   10978  1.1        is 	short		fsgldiv_res_qnan	- tbl_fsgldiv_op # NORM / QNAN
   10979  1.1        is 	short		fsgldiv_norm		- tbl_fsgldiv_op # NORM / DENORM
   10980  1.1        is 	short		fsgldiv_res_snan	- tbl_fsgldiv_op # NORM / SNAN
   10981  1.1        is 	short		tbl_fsgldiv_op		- tbl_fsgldiv_op #
   10982  1.1        is 	short		tbl_fsgldiv_op		- tbl_fsgldiv_op #
   10983  1.1        is 
   10984  1.1        is 	short		fsgldiv_zero_load	- tbl_fsgldiv_op # ZERO / NORM
   10985  1.1        is 	short		fsgldiv_res_operr	- tbl_fsgldiv_op # ZERO / ZERO
   10986  1.1        is 	short		fsgldiv_zero_load	- tbl_fsgldiv_op # ZERO / INF
   10987  1.1        is 	short		fsgldiv_res_qnan	- tbl_fsgldiv_op # ZERO / QNAN
   10988  1.1        is 	short		fsgldiv_zero_load	- tbl_fsgldiv_op # ZERO / DENORM
   10989  1.1        is 	short		fsgldiv_res_snan	- tbl_fsgldiv_op # ZERO / SNAN
   10990  1.1        is 	short		tbl_fsgldiv_op		- tbl_fsgldiv_op #
   10991  1.1        is 	short		tbl_fsgldiv_op		- tbl_fsgldiv_op #
   10992  1.1        is 
   10993  1.1        is 	short		fsgldiv_inf_dst		- tbl_fsgldiv_op # INF / NORM
   10994  1.1        is 	short		fsgldiv_inf_dst		- tbl_fsgldiv_op # INF / ZERO
   10995  1.1        is 	short		fsgldiv_res_operr	- tbl_fsgldiv_op # INF / INF
   10996  1.1        is 	short		fsgldiv_res_qnan	- tbl_fsgldiv_op # INF / QNAN
   10997  1.1        is 	short		fsgldiv_inf_dst		- tbl_fsgldiv_op # INF / DENORM
   10998  1.1        is 	short		fsgldiv_res_snan	- tbl_fsgldiv_op # INF / SNAN
   10999  1.1        is 	short		tbl_fsgldiv_op		- tbl_fsgldiv_op #
   11000  1.1        is 	short		tbl_fsgldiv_op		- tbl_fsgldiv_op #
   11001  1.1        is 
   11002  1.1        is 	short		fsgldiv_res_qnan	- tbl_fsgldiv_op # QNAN / NORM
   11003  1.1        is 	short		fsgldiv_res_qnan	- tbl_fsgldiv_op # QNAN / ZERO
   11004  1.1        is 	short		fsgldiv_res_qnan	- tbl_fsgldiv_op # QNAN / INF
   11005  1.1        is 	short		fsgldiv_res_qnan	- tbl_fsgldiv_op # QNAN / QNAN
   11006  1.1        is 	short		fsgldiv_res_qnan	- tbl_fsgldiv_op # QNAN / DENORM
   11007  1.1        is 	short		fsgldiv_res_snan	- tbl_fsgldiv_op # QNAN / SNAN
   11008  1.1        is 	short		tbl_fsgldiv_op		- tbl_fsgldiv_op #
   11009  1.1        is 	short		tbl_fsgldiv_op		- tbl_fsgldiv_op #
   11010  1.1        is 
   11011  1.1        is 	short		fsgldiv_norm		- tbl_fsgldiv_op # DENORM / NORM
   11012  1.1        is 	short		fsgldiv_inf_load	- tbl_fsgldiv_op # DENORM / ZERO
   11013  1.1        is 	short		fsgldiv_zero_load	- tbl_fsgldiv_op # DENORM / INF
   11014  1.1        is 	short		fsgldiv_res_qnan	- tbl_fsgldiv_op # DENORM / QNAN
   11015  1.1        is 	short		fsgldiv_norm		- tbl_fsgldiv_op # DENORM / DENORM
   11016  1.1        is 	short		fsgldiv_res_snan	- tbl_fsgldiv_op # DENORM / SNAN
   11017  1.1        is 	short		tbl_fsgldiv_op		- tbl_fsgldiv_op #
   11018  1.1        is 	short		tbl_fsgldiv_op		- tbl_fsgldiv_op #
   11019  1.1        is 
   11020  1.1        is 	short		fsgldiv_res_snan	- tbl_fsgldiv_op # SNAN / NORM
   11021  1.1        is 	short		fsgldiv_res_snan	- tbl_fsgldiv_op # SNAN / ZERO
   11022  1.1        is 	short		fsgldiv_res_snan	- tbl_fsgldiv_op # SNAN / INF
   11023  1.1        is 	short		fsgldiv_res_snan	- tbl_fsgldiv_op # SNAN / QNAN
   11024  1.1        is 	short		fsgldiv_res_snan	- tbl_fsgldiv_op # SNAN / DENORM
   11025  1.1        is 	short		fsgldiv_res_snan	- tbl_fsgldiv_op # SNAN / SNAN
   11026  1.1        is 	short		tbl_fsgldiv_op		- tbl_fsgldiv_op #
   11027  1.1        is 	short		tbl_fsgldiv_op		- tbl_fsgldiv_op #
   11028  1.1        is 
   11029  1.1        is fsgldiv_res_qnan:
   11030  1.1        is 	bra.l		res_qnan
   11031  1.1        is fsgldiv_res_snan:
   11032  1.1        is 	bra.l		res_snan
   11033  1.1        is fsgldiv_res_operr:
   11034  1.1        is 	bra.l		res_operr
   11035  1.1        is fsgldiv_inf_load:
   11036  1.1        is 	bra.l		fdiv_inf_load
   11037  1.1        is fsgldiv_zero_load:
   11038  1.1        is 	bra.l		fdiv_zero_load
   11039  1.1        is fsgldiv_inf_dst:
   11040  1.1        is 	bra.l		fdiv_inf_dst
   11041  1.1        is 
   11042  1.1        is #########################################################################
   11043  1.1        is # XDEF ****************************************************************	#
   11044  1.1        is #	fadd(): emulates the fadd instruction				#
   11045  1.1        is #	fsadd(): emulates the fadd instruction				#
   11046  1.1        is #	fdadd(): emulates the fdadd instruction				#
   11047  1.1        is #									#
   11048  1.1        is # XREF ****************************************************************	#
   11049  1.1        is # 	addsub_scaler2() - scale the operands so they won't take exc	#
   11050  1.1        is #	ovf_res() - return default overflow result			#
   11051  1.1        is #	unf_res() - return default underflow result			#
   11052  1.1        is #	res_qnan() - set QNAN result					#
   11053  1.1        is # 	res_snan() - set SNAN result					#
   11054  1.1        is #	res_operr() - set OPERR result					#
   11055  1.1        is #	scale_to_zero_src() - set src operand exponent equal to zero	#
   11056  1.1        is #	scale_to_zero_dst() - set dst operand exponent equal to zero	#
   11057  1.1        is #									#
   11058  1.1        is # INPUT ***************************************************************	#
   11059  1.1        is #	a0 = pointer to extended precision source operand		#
   11060  1.1        is # 	a1 = pointer to extended precision destination operand		#
   11061  1.1        is #									#
   11062  1.1        is # OUTPUT **************************************************************	#
   11063  1.1        is #	fp0 = result							#
   11064  1.1        is #	fp1 = EXOP (if exception occurred)				#
   11065  1.1        is #									#
   11066  1.1        is # ALGORITHM ***********************************************************	#
   11067  1.1        is # 	Handle NANs, infinities, and zeroes as special cases. Divide	#
   11068  1.1        is # norms into extended, single, and double precision.			#
   11069  1.1        is #	Do addition after scaling exponents such that exception won't	#
   11070  1.1        is # occur. Then, check result exponent to see if exception would have	#
   11071  1.1        is # occurred. If so, return default result and maybe EXOP. Else, insert	#
   11072  1.1        is # the correct result exponent and return. Set FPSR bits as appropriate.	#
   11073  1.1        is #									#
   11074  1.1        is #########################################################################
   11075  1.1        is 
   11076  1.1        is 	global		fsadd
   11077  1.1        is fsadd:
   11078  1.1        is 	andi.b		&0x30,%d0		# clear rnd prec
   11079  1.1        is 	ori.b		&s_mode*0x10,%d0	# insert sgl prec
   11080  1.1        is 	bra.b		fadd
   11081  1.1        is 
   11082  1.1        is 	global		fdadd
   11083  1.1        is fdadd:
   11084  1.1        is 	andi.b		&0x30,%d0		# clear rnd prec
   11085  1.1        is 	ori.b		&d_mode*0x10,%d0	# insert dbl prec
   11086  1.1        is 
   11087  1.1        is 	global		fadd
   11088  1.1        is fadd:
   11089  1.1        is 	mov.l		%d0,L_SCR3(%a6)		# store rnd info
   11090  1.1        is 
   11091  1.1        is 	clr.w		%d1
   11092  1.1        is 	mov.b		DTAG(%a6),%d1
   11093  1.1        is 	lsl.b		&0x3,%d1
   11094  1.1        is 	or.b		STAG(%a6),%d1		# combine src tags
   11095  1.1        is 
   11096  1.1        is 	bne.w		fadd_not_norm		# optimize on non-norm input
   11097  1.1        is 
   11098  1.1        is #
   11099  1.1        is # ADD: norms and denorms
   11100  1.1        is #
   11101  1.1        is fadd_norm:
   11102  1.1        is 	bsr.l		addsub_scaler2		# scale exponents
   11103  1.1        is 
   11104  1.1        is fadd_zero_entry:
   11105  1.1        is 	fmovm.x		FP_SCR1(%a6),&0x80	# load dst op
   11106  1.1        is 
   11107  1.1        is 	fmov.l		&0x0,%fpsr		# clear FPSR
   11108  1.1        is 	fmov.l		L_SCR3(%a6),%fpcr	# set FPCR
   11109  1.1        is 
   11110  1.1        is 	fadd.x		FP_SCR0(%a6),%fp0	# execute add
   11111  1.1        is 
   11112  1.1        is 	fmov.l		&0x0,%fpcr		# clear FPCR
   11113  1.1        is 	fmov.l		%fpsr,%d1		# fetch INEX2,N,Z
   11114  1.1        is 
   11115  1.1        is 	or.l		%d1,USER_FPSR(%a6)	# save exc and ccode bits
   11116  1.1        is 
   11117  1.1        is 	fbeq.w		fadd_zero_exit		# if result is zero, end now
   11118  1.1        is 
   11119  1.1        is 	mov.l		%d2,-(%sp)		# save d2
   11120  1.1        is 
   11121  1.1        is 	fmovm.x		&0x01,-(%sp)		# save result to stack
   11122  1.1        is 
   11123  1.1        is 	mov.w		2+L_SCR3(%a6),%d1
   11124  1.1        is 	lsr.b		&0x6,%d1
   11125  1.1        is 
   11126  1.1        is 	mov.w		(%sp),%d2		# fetch new sign, exp
   11127  1.1        is 	andi.l		&0x7fff,%d2		# strip sign
   11128  1.1        is 	sub.l		%d0,%d2			# add scale factor
   11129  1.1        is 
   11130  1.1        is 	cmp.l		%d2,(tbl_fadd_ovfl.b,%pc,%d1.w*4) # is it an overflow?
   11131  1.1        is 	bge.b		fadd_ovfl		# yes
   11132  1.1        is 
   11133  1.1        is 	cmp.l		%d2,(tbl_fadd_unfl.b,%pc,%d1.w*4) # is it an underflow?
   11134  1.1        is 	blt.w		fadd_unfl		# yes
   11135  1.1        is 	beq.w		fadd_may_unfl		# maybe; go find out
   11136  1.1        is 
   11137  1.1        is fadd_normal:
   11138  1.1        is 	mov.w		(%sp),%d1
   11139  1.1        is 	andi.w		&0x8000,%d1		# keep sign
   11140  1.1        is 	or.w		%d2,%d1			# concat sign,new exp
   11141  1.1        is 	mov.w		%d1,(%sp)		# insert new exponent
   11142  1.1        is 
   11143  1.1        is 	fmovm.x		(%sp)+,&0x80		# return result in fp0
   11144  1.1        is 
   11145  1.1        is 	mov.l		(%sp)+,%d2		# restore d2
   11146  1.1        is 	rts
   11147  1.1        is 
   11148  1.1        is fadd_zero_exit:
   11149  1.1        is #	fmov.s		&0x00000000,%fp0	# return zero in fp0
   11150  1.1        is 	rts
   11151  1.1        is 
   11152  1.1        is tbl_fadd_ovfl:
   11153  1.1        is 	long		0x7fff			# ext ovfl
   11154  1.1        is 	long		0x407f			# sgl ovfl
   11155  1.1        is 	long		0x43ff			# dbl ovfl
   11156  1.1        is 
   11157  1.1        is tbl_fadd_unfl:
   11158  1.1        is 	long	        0x0000			# ext unfl
   11159  1.1        is 	long		0x3f81			# sgl unfl
   11160  1.1        is 	long		0x3c01			# dbl unfl
   11161  1.1        is 
   11162  1.1        is fadd_ovfl:
   11163  1.1        is 	or.l		&ovfl_inx_mask,USER_FPSR(%a6) # set ovfl/aovfl/ainex
   11164  1.1        is 
   11165  1.1        is 	mov.b		FPCR_ENABLE(%a6),%d1
   11166  1.1        is 	andi.b		&0x13,%d1		# is OVFL or INEX enabled?
   11167  1.1        is 	bne.b		fadd_ovfl_ena		# yes
   11168  1.1        is 
   11169  1.1        is 	add.l		&0xc,%sp
   11170  1.1        is fadd_ovfl_dis:
   11171  1.1        is 	btst		&neg_bit,FPSR_CC(%a6)	# is result negative?
   11172  1.1        is 	sne		%d1			# set sign param accordingly
   11173  1.1        is 	mov.l		L_SCR3(%a6),%d0		# pass prec:rnd
   11174  1.1        is 	bsr.l		ovf_res			# calculate default result
   11175  1.1        is 	or.b		%d0,FPSR_CC(%a6)	# set INF,N if applicable
   11176  1.1        is 	fmovm.x		(%a0),&0x80		# return default result in fp0
   11177  1.1        is 	mov.l		(%sp)+,%d2		# restore d2
   11178  1.1        is 	rts
   11179  1.1        is 
   11180  1.1        is fadd_ovfl_ena:
   11181  1.1        is 	mov.b		L_SCR3(%a6),%d1
   11182  1.1        is 	andi.b		&0xc0,%d1		# is precision extended?
   11183  1.1        is 	bne.b		fadd_ovfl_ena_sd	# no; prec = sgl or dbl
   11184  1.1        is 
   11185  1.1        is fadd_ovfl_ena_cont:
   11186  1.1        is 	mov.w		(%sp),%d1
   11187  1.1        is 	andi.w		&0x8000,%d1		# keep sign
   11188  1.1        is 	subi.l		&0x6000,%d2		# add extra bias
   11189  1.1        is 	andi.w		&0x7fff,%d2
   11190  1.1        is 	or.w		%d2,%d1			# concat sign,new exp
   11191  1.1        is 	mov.w		%d1,(%sp)		# insert new exponent
   11192  1.1        is 
   11193  1.1        is 	fmovm.x		(%sp)+,&0x40		# return EXOP in fp1
   11194  1.1        is 	bra.b		fadd_ovfl_dis
   11195  1.1        is 
   11196  1.1        is fadd_ovfl_ena_sd:
   11197  1.1        is 	fmovm.x		FP_SCR1(%a6),&0x80	# load dst op
   11198  1.1        is 
   11199  1.1        is 	mov.l		L_SCR3(%a6),%d1
   11200  1.1        is 	andi.b		&0x30,%d1		# keep rnd mode
   11201  1.1        is 	fmov.l		%d1,%fpcr		# set FPCR
   11202  1.1        is 
   11203  1.1        is 	fadd.x		FP_SCR0(%a6),%fp0	# execute add
   11204  1.1        is 
   11205  1.1        is 	fmov.l		&0x0,%fpcr		# clear FPCR
   11206  1.1        is 
   11207  1.1        is 	add.l		&0xc,%sp
   11208  1.1        is 	fmovm.x		&0x01,-(%sp)
   11209  1.1        is 	bra.b		fadd_ovfl_ena_cont
   11210  1.1        is 
   11211  1.1        is fadd_unfl:
   11212  1.1        is 	bset		&unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
   11213  1.1        is 
   11214  1.1        is 	add.l		&0xc,%sp
   11215  1.1        is 
   11216  1.1        is 	fmovm.x		FP_SCR1(%a6),&0x80	# load dst op
   11217  1.1        is 
   11218  1.1        is 	fmov.l		&rz_mode*0x10,%fpcr	# set FPCR
   11219  1.1        is 	fmov.l		&0x0,%fpsr		# clear FPSR
   11220  1.1        is 
   11221  1.1        is 	fadd.x		FP_SCR0(%a6),%fp0	# execute add
   11222  1.1        is 
   11223  1.1        is 	fmov.l		&0x0,%fpcr		# clear FPCR
   11224  1.1        is 	fmov.l		%fpsr,%d1		# save status
   11225  1.1        is 
   11226  1.1        is 	or.l		%d1,USER_FPSR(%a6)	# save INEX,N
   11227  1.1        is 
   11228  1.1        is 	mov.b		FPCR_ENABLE(%a6),%d1
   11229  1.1        is 	andi.b		&0x0b,%d1		# is UNFL or INEX enabled?
   11230  1.1        is 	bne.b		fadd_unfl_ena		# yes
   11231  1.1        is 
   11232  1.1        is fadd_unfl_dis:
   11233  1.1        is 	fmovm.x		&0x80,FP_SCR0(%a6)	# store out result
   11234  1.1        is 
   11235  1.1        is 	lea		FP_SCR0(%a6),%a0	# pass: result addr
   11236  1.1        is 	mov.l		L_SCR3(%a6),%d1		# pass: rnd prec,mode
   11237  1.1        is 	bsr.l		unf_res			# calculate default result
   11238  1.1        is 	or.b		%d0,FPSR_CC(%a6)	# 'Z' bit may have been set
   11239  1.1        is 	fmovm.x		FP_SCR0(%a6),&0x80	# return default result in fp0
   11240  1.1        is 	mov.l		(%sp)+,%d2		# restore d2
   11241  1.1        is 	rts
   11242  1.1        is 
   11243  1.1        is fadd_unfl_ena:
   11244  1.1        is 	fmovm.x		FP_SCR1(%a6),&0x40	# load dst op
   11245  1.1        is 
   11246  1.1        is 	mov.l		L_SCR3(%a6),%d1
   11247  1.1        is 	andi.b		&0xc0,%d1		# is precision extended?
   11248  1.1        is 	bne.b		fadd_unfl_ena_sd	# no; sgl or dbl
   11249  1.1        is 
   11250  1.1        is 	fmov.l		L_SCR3(%a6),%fpcr	# set FPCR
   11251  1.1        is 
   11252  1.1        is fadd_unfl_ena_cont:
   11253  1.1        is 	fmov.l		&0x0,%fpsr		# clear FPSR
   11254  1.1        is 
   11255  1.1        is 	fadd.x		FP_SCR0(%a6),%fp1	# execute multiply
   11256  1.1        is 
   11257  1.1        is 	fmov.l		&0x0,%fpcr		# clear FPCR
   11258  1.1        is 
   11259  1.1        is 	fmovm.x		&0x40,FP_SCR0(%a6)	# save result to stack
   11260  1.1        is 	mov.w		FP_SCR0_EX(%a6),%d1	# fetch {sgn,exp}
   11261  1.1        is 	mov.l		%d1,%d2			# make a copy
   11262  1.1        is 	andi.l		&0x7fff,%d1		# strip sign
   11263  1.1        is 	andi.w		&0x8000,%d2		# keep old sign
   11264  1.1        is 	sub.l		%d0,%d1			# add scale factor
   11265  1.1        is 	addi.l		&0x6000,%d1		# add new bias
   11266  1.1        is 	andi.w		&0x7fff,%d1		# clear top bit
   11267  1.1        is 	or.w		%d2,%d1			# concat sign,new exp
   11268  1.1        is 	mov.w		%d1,FP_SCR0_EX(%a6)	# insert new exponent
   11269  1.1        is 	fmovm.x		FP_SCR0(%a6),&0x40	# return EXOP in fp1
   11270  1.1        is 	bra.w		fadd_unfl_dis
   11271  1.1        is 
   11272  1.1        is fadd_unfl_ena_sd:
   11273  1.1        is 	mov.l		L_SCR3(%a6),%d1
   11274  1.1        is 	andi.b		&0x30,%d1		# use only rnd mode
   11275  1.1        is 	fmov.l		%d1,%fpcr		# set FPCR
   11276  1.1        is 
   11277  1.1        is 	bra.b		fadd_unfl_ena_cont
   11278  1.1        is 
   11279  1.1        is #
   11280  1.1        is # result is equal to the smallest normalized number in the selected precision
   11281  1.1        is # if the precision is extended, this result could not have come from an
   11282  1.1        is # underflow that rounded up.
   11283  1.1        is #
   11284  1.1        is fadd_may_unfl:
   11285  1.1        is 	mov.l		L_SCR3(%a6),%d1
   11286  1.1        is 	andi.b		&0xc0,%d1
   11287  1.1        is 	beq.w		fadd_normal		# yes; no underflow occurred
   11288  1.1        is 
   11289  1.1        is 	mov.l		0x4(%sp),%d1		# extract hi(man)
   11290  1.1        is 	cmpi.l		%d1,&0x80000000		# is hi(man) = 0x80000000?
   11291  1.1        is 	bne.w		fadd_normal		# no; no underflow occurred
   11292  1.1        is 
   11293  1.1        is 	tst.l		0x8(%sp)		# is lo(man) = 0x0?
   11294  1.1        is 	bne.w		fadd_normal		# no; no underflow occurred
   11295  1.1        is 
   11296  1.1        is 	btst		&inex2_bit,FPSR_EXCEPT(%a6) # is INEX2 set?
   11297  1.1        is 	beq.w		fadd_normal		# no; no underflow occurred
   11298  1.1        is 
   11299  1.1        is #
   11300  1.1        is # ok, so now the result has a exponent equal to the smallest normalized
   11301  1.1        is # exponent for the selected precision. also, the mantissa is equal to
   11302  1.1        is # 0x8000000000000000 and this mantissa is the result of rounding non-zero
   11303  1.1        is # g,r,s.
   11304  1.1        is # now, we must determine whether the pre-rounded result was an underflow
   11305  1.1        is # rounded "up" or a normalized number rounded "down".
   11306  1.1        is # so, we do this be re-executing the add using RZ as the rounding mode and
   11307  1.1        is # seeing if the new result is smaller or equal to the current result.
   11308  1.1        is #
   11309  1.1        is 	fmovm.x		FP_SCR1(%a6),&0x40	# load dst op into fp1
   11310  1.1        is 
   11311  1.1        is 	mov.l		L_SCR3(%a6),%d1
   11312  1.1        is 	andi.b		&0xc0,%d1		# keep rnd prec
   11313  1.1        is 	ori.b		&rz_mode*0x10,%d1	# insert rnd mode
   11314  1.1        is 	fmov.l		%d1,%fpcr		# set FPCR
   11315  1.1        is 	fmov.l		&0x0,%fpsr		# clear FPSR
   11316  1.1        is 
   11317  1.1        is 	fadd.x		FP_SCR0(%a6),%fp1	# execute add
   11318  1.1        is 
   11319  1.1        is 	fmov.l		&0x0,%fpcr		# clear FPCR
   11320  1.1        is 
   11321  1.1        is 	fabs.x		%fp0			# compare absolute values
   11322  1.1        is 	fabs.x		%fp1
   11323  1.1        is 	fcmp.x		%fp0,%fp1		# is first result > second?
   11324  1.1        is 
   11325  1.1        is 	fbgt.w		fadd_unfl		# yes; it's an underflow
   11326  1.1        is 	bra.w		fadd_normal		# no; it's not an underflow
   11327  1.1        is 
   11328  1.1        is ##########################################################################
   11329  1.1        is 
   11330  1.1        is #
   11331  1.1        is # Add: inputs are not both normalized; what are they?
   11332  1.1        is #
   11333  1.1        is fadd_not_norm:
   11334  1.1        is 	mov.w		(tbl_fadd_op.b,%pc,%d1.w*2),%d1
   11335  1.1        is 	jmp		(tbl_fadd_op.b,%pc,%d1.w*1)
   11336  1.1        is 
   11337  1.1        is 	swbeg		&48
   11338  1.1        is tbl_fadd_op:
   11339  1.1        is 	short		fadd_norm	- tbl_fadd_op # NORM + NORM
   11340  1.1        is 	short		fadd_zero_src	- tbl_fadd_op # NORM + ZERO
   11341  1.1        is 	short		fadd_inf_src	- tbl_fadd_op # NORM + INF
   11342  1.1        is 	short		fadd_res_qnan	- tbl_fadd_op # NORM + QNAN
   11343  1.1        is 	short		fadd_norm	- tbl_fadd_op # NORM + DENORM
   11344  1.1        is 	short		fadd_res_snan	- tbl_fadd_op # NORM + SNAN
   11345  1.1        is 	short		tbl_fadd_op	- tbl_fadd_op #
   11346  1.1        is 	short		tbl_fadd_op	- tbl_fadd_op #
   11347  1.1        is 
   11348  1.1        is 	short		fadd_zero_dst	- tbl_fadd_op # ZERO + NORM
   11349  1.1        is 	short		fadd_zero_2	- tbl_fadd_op # ZERO + ZERO
   11350  1.1        is 	short		fadd_inf_src	- tbl_fadd_op # ZERO + INF
   11351  1.1        is 	short		fadd_res_qnan	- tbl_fadd_op # NORM + QNAN
   11352  1.1        is 	short		fadd_zero_dst	- tbl_fadd_op # ZERO + DENORM
   11353  1.1        is 	short		fadd_res_snan	- tbl_fadd_op # NORM + SNAN
   11354  1.1        is 	short		tbl_fadd_op	- tbl_fadd_op #
   11355  1.1        is 	short		tbl_fadd_op	- tbl_fadd_op #
   11356  1.1        is 
   11357  1.1        is 	short		fadd_inf_dst	- tbl_fadd_op # INF + NORM
   11358  1.1        is 	short		fadd_inf_dst	- tbl_fadd_op # INF + ZERO
   11359  1.1        is 	short		fadd_inf_2	- tbl_fadd_op # INF + INF
   11360  1.1        is 	short		fadd_res_qnan	- tbl_fadd_op # NORM + QNAN
   11361  1.1        is 	short		fadd_inf_dst	- tbl_fadd_op # INF + DENORM
   11362  1.1        is 	short		fadd_res_snan	- tbl_fadd_op # NORM + SNAN
   11363  1.1        is 	short		tbl_fadd_op	- tbl_fadd_op #
   11364  1.1        is 	short		tbl_fadd_op	- tbl_fadd_op #
   11365  1.1        is 
   11366  1.1        is 	short		fadd_res_qnan	- tbl_fadd_op # QNAN + NORM
   11367  1.1        is 	short		fadd_res_qnan	- tbl_fadd_op # QNAN + ZERO
   11368  1.1        is 	short		fadd_res_qnan	- tbl_fadd_op # QNAN + INF
   11369  1.1        is 	short		fadd_res_qnan	- tbl_fadd_op # QNAN + QNAN
   11370  1.1        is 	short		fadd_res_qnan	- tbl_fadd_op # QNAN + DENORM
   11371  1.1        is 	short		fadd_res_snan	- tbl_fadd_op # QNAN + SNAN
   11372  1.1        is 	short		tbl_fadd_op	- tbl_fadd_op #
   11373  1.1        is 	short		tbl_fadd_op	- tbl_fadd_op #
   11374  1.1        is 
   11375  1.1        is 	short		fadd_norm	- tbl_fadd_op # DENORM + NORM
   11376  1.1        is 	short		fadd_zero_src	- tbl_fadd_op # DENORM + ZERO
   11377  1.1        is 	short		fadd_inf_src	- tbl_fadd_op # DENORM + INF
   11378  1.1        is 	short		fadd_res_qnan	- tbl_fadd_op # NORM + QNAN
   11379  1.1        is 	short		fadd_norm	- tbl_fadd_op # DENORM + DENORM
   11380  1.1        is 	short		fadd_res_snan	- tbl_fadd_op # NORM + SNAN
   11381  1.1        is 	short		tbl_fadd_op	- tbl_fadd_op #
   11382  1.1        is 	short		tbl_fadd_op	- tbl_fadd_op #
   11383  1.1        is 
   11384  1.1        is 	short		fadd_res_snan	- tbl_fadd_op # SNAN + NORM
   11385  1.1        is 	short		fadd_res_snan	- tbl_fadd_op # SNAN + ZERO
   11386  1.1        is 	short		fadd_res_snan	- tbl_fadd_op # SNAN + INF
   11387  1.1        is 	short		fadd_res_snan	- tbl_fadd_op # SNAN + QNAN
   11388  1.1        is 	short		fadd_res_snan	- tbl_fadd_op # SNAN + DENORM
   11389  1.1        is 	short		fadd_res_snan	- tbl_fadd_op # SNAN + SNAN
   11390  1.1        is 	short		tbl_fadd_op	- tbl_fadd_op #
   11391  1.1        is 	short		tbl_fadd_op	- tbl_fadd_op #
   11392  1.1        is 
   11393  1.1        is fadd_res_qnan:
   11394  1.1        is 	bra.l		res_qnan
   11395  1.1        is fadd_res_snan:
   11396  1.1        is 	bra.l		res_snan
   11397  1.1        is 
   11398  1.1        is #
   11399  1.1        is # both operands are ZEROes
   11400  1.1        is #
   11401  1.1        is fadd_zero_2:
   11402  1.1        is 	mov.b		SRC_EX(%a0),%d0		# are the signs opposite
   11403  1.1        is 	mov.b		DST_EX(%a1),%d1
   11404  1.1        is 	eor.b		%d0,%d1
   11405  1.1        is 	bmi.w		fadd_zero_2_chk_rm	# weed out (-ZERO)+(+ZERO)
   11406  1.1        is 
   11407  1.1        is # the signs are the same. so determine whether they are positive or negative
   11408  1.1        is # and return the appropriately signed zero.
   11409  1.1        is 	tst.b		%d0			# are ZEROes positive or negative?
   11410  1.1        is 	bmi.b		fadd_zero_rm		# negative
   11411  1.1        is 	fmov.s		&0x00000000,%fp0	# return +ZERO
   11412  1.1        is 	mov.b		&z_bmask,FPSR_CC(%a6)	# set Z
   11413  1.1        is 	rts
   11414  1.1        is 
   11415  1.1        is #
   11416  1.1        is # the ZEROes have opposite signs:
   11417  1.1        is # - therefore, we return +ZERO if the rounding modes are RN,RZ, or RP.
   11418  1.1        is # - -ZERO is returned in the case of RM.
   11419  1.1        is #
   11420  1.1        is fadd_zero_2_chk_rm:
   11421  1.1        is 	mov.b		3+L_SCR3(%a6),%d1
   11422  1.1        is 	andi.b		&0x30,%d1		# extract rnd mode
   11423  1.1        is 	cmpi.b		%d1,&rm_mode*0x10	# is rnd mode == RM?
   11424  1.1        is 	beq.b		fadd_zero_rm		# yes
   11425  1.1        is 	fmov.s		&0x00000000,%fp0	# return +ZERO
   11426  1.1        is 	mov.b		&z_bmask,FPSR_CC(%a6)	# set Z
   11427  1.1        is 	rts
   11428  1.1        is 
   11429  1.1        is fadd_zero_rm:
   11430  1.1        is 	fmov.s		&0x80000000,%fp0	# return -ZERO
   11431  1.1        is 	mov.b		&neg_bmask+z_bmask,FPSR_CC(%a6) # set NEG/Z
   11432  1.1        is 	rts
   11433  1.1        is 
   11434  1.1        is #
   11435  1.1        is # one operand is a ZERO and the other is a DENORM or NORM. scale
   11436  1.1        is # the DENORM or NORM and jump to the regular fadd routine.
   11437  1.1        is #
   11438  1.1        is fadd_zero_dst:
   11439  1.1        is 	mov.w		SRC_EX(%a0),FP_SCR0_EX(%a6)
   11440  1.1        is 	mov.l		SRC_HI(%a0),FP_SCR0_HI(%a6)
   11441  1.1        is 	mov.l		SRC_LO(%a0),FP_SCR0_LO(%a6)
   11442  1.1        is 	bsr.l		scale_to_zero_src	# scale the operand
   11443  1.1        is 	clr.w		FP_SCR1_EX(%a6)
   11444  1.1        is 	clr.l		FP_SCR1_HI(%a6)
   11445  1.1        is 	clr.l		FP_SCR1_LO(%a6)
   11446  1.1        is 	bra.w		fadd_zero_entry		# go execute fadd
   11447  1.1        is 
   11448  1.1        is fadd_zero_src:
   11449  1.1        is 	mov.w		DST_EX(%a1),FP_SCR1_EX(%a6)
   11450  1.1        is 	mov.l		DST_HI(%a1),FP_SCR1_HI(%a6)
   11451  1.1        is 	mov.l		DST_LO(%a1),FP_SCR1_LO(%a6)
   11452  1.1        is 	bsr.l		scale_to_zero_dst	# scale the operand
   11453  1.1        is 	clr.w		FP_SCR0_EX(%a6)
   11454  1.1        is 	clr.l		FP_SCR0_HI(%a6)
   11455  1.1        is 	clr.l		FP_SCR0_LO(%a6)
   11456  1.1        is 	bra.w		fadd_zero_entry		# go execute fadd
   11457  1.1        is 
   11458  1.1        is #
   11459  1.1        is # both operands are INFs. an OPERR will result if the INFs have
   11460  1.1        is # different signs. else, an INF of the same sign is returned
   11461  1.1        is #
   11462  1.1        is fadd_inf_2:
   11463  1.1        is 	mov.b		SRC_EX(%a0),%d0		# exclusive or the signs
   11464  1.1        is 	mov.b		DST_EX(%a1),%d1
   11465  1.1        is 	eor.b		%d1,%d0
   11466  1.1        is 	bmi.l		res_operr		# weed out (-INF)+(+INF)
   11467  1.1        is 
   11468  1.1        is # ok, so it's not an OPERR. but, we do have to remember to return the
   11469  1.1        is # src INF since that's where the 881/882 gets the j-bit from...
   11470  1.1        is 
   11471  1.1        is #
   11472  1.1        is # operands are INF and one of {ZERO, INF, DENORM, NORM}
   11473  1.1        is #
   11474  1.1        is fadd_inf_src:
   11475  1.1        is 	fmovm.x		SRC(%a0),&0x80		# return src INF
   11476  1.1        is 	tst.b		SRC_EX(%a0)		# is INF positive?
   11477  1.1        is 	bpl.b		fadd_inf_done		# yes; we're done
   11478  1.1        is 	mov.b		&neg_bmask+inf_bmask,FPSR_CC(%a6) # set INF/NEG
   11479  1.1        is 	rts
   11480  1.1        is 
   11481  1.1        is #
   11482  1.1        is # operands are INF and one of {ZERO, INF, DENORM, NORM}
   11483  1.1        is #
   11484  1.1        is fadd_inf_dst:
   11485  1.1        is 	fmovm.x		DST(%a1),&0x80		# return dst INF
   11486  1.1        is 	tst.b		DST_EX(%a1)		# is INF positive?
   11487  1.1        is 	bpl.b		fadd_inf_done		# yes; we're done
   11488  1.1        is 	mov.b		&neg_bmask+inf_bmask,FPSR_CC(%a6) # set INF/NEG
   11489  1.1        is 	rts
   11490  1.1        is 
   11491  1.1        is fadd_inf_done:
   11492  1.1        is 	mov.b		&inf_bmask,FPSR_CC(%a6) # set INF
   11493  1.1        is 	rts
   11494  1.1        is 
   11495  1.1        is #########################################################################
   11496  1.1        is # XDEF ****************************************************************	#
   11497  1.1        is #	fsub(): emulates the fsub instruction				#
   11498  1.1        is #	fssub(): emulates the fssub instruction				#
   11499  1.1        is #	fdsub(): emulates the fdsub instruction				#
   11500  1.1        is #									#
   11501  1.1        is # XREF ****************************************************************	#
   11502  1.1        is # 	addsub_scaler2() - scale the operands so they won't take exc	#
   11503  1.1        is #	ovf_res() - return default overflow result			#
   11504  1.1        is #	unf_res() - return default underflow result			#
   11505  1.1        is #	res_qnan() - set QNAN result					#
   11506  1.1        is # 	res_snan() - set SNAN result					#
   11507  1.1        is #	res_operr() - set OPERR result					#
   11508  1.1        is #	scale_to_zero_src() - set src operand exponent equal to zero	#
   11509  1.1        is #	scale_to_zero_dst() - set dst operand exponent equal to zero	#
   11510  1.1        is #									#
   11511  1.1        is # INPUT ***************************************************************	#
   11512  1.1        is #	a0 = pointer to extended precision source operand		#
   11513  1.1        is # 	a1 = pointer to extended precision destination operand		#
   11514  1.1        is #									#
   11515  1.1        is # OUTPUT **************************************************************	#
   11516  1.1        is #	fp0 = result							#
   11517  1.1        is #	fp1 = EXOP (if exception occurred)				#
   11518  1.1        is #									#
   11519  1.1        is # ALGORITHM ***********************************************************	#
   11520  1.1        is # 	Handle NANs, infinities, and zeroes as special cases. Divide	#
   11521  1.1        is # norms into extended, single, and double precision.			#
   11522  1.1        is #	Do subtraction after scaling exponents such that exception won't#
   11523  1.1        is # occur. Then, check result exponent to see if exception would have	#
   11524  1.1        is # occurred. If so, return default result and maybe EXOP. Else, insert	#
   11525  1.1        is # the correct result exponent and return. Set FPSR bits as appropriate.	#
   11526  1.1        is #									#
   11527  1.1        is #########################################################################
   11528  1.1        is 
   11529  1.1        is 	global		fssub
   11530  1.1        is fssub:
   11531  1.1        is 	andi.b		&0x30,%d0		# clear rnd prec
   11532  1.1        is 	ori.b		&s_mode*0x10,%d0	# insert sgl prec
   11533  1.1        is 	bra.b		fsub
   11534  1.1        is 
   11535  1.1        is 	global		fdsub
   11536  1.1        is fdsub:
   11537  1.1        is 	andi.b		&0x30,%d0		# clear rnd prec
   11538  1.1        is 	ori.b		&d_mode*0x10,%d0	# insert dbl prec
   11539  1.1        is 
   11540  1.1        is 	global		fsub
   11541  1.1        is fsub:
   11542  1.1        is 	mov.l		%d0,L_SCR3(%a6)		# store rnd info
   11543  1.1        is 
   11544  1.1        is 	clr.w		%d1
   11545  1.1        is 	mov.b		DTAG(%a6),%d1
   11546  1.1        is 	lsl.b		&0x3,%d1
   11547  1.1        is 	or.b		STAG(%a6),%d1		# combine src tags
   11548  1.1        is 
   11549  1.1        is 	bne.w		fsub_not_norm		# optimize on non-norm input
   11550  1.1        is 
   11551  1.1        is #
   11552  1.1        is # SUB: norms and denorms
   11553  1.1        is #
   11554  1.1        is fsub_norm:
   11555  1.1        is 	bsr.l		addsub_scaler2		# scale exponents
   11556  1.1        is 
   11557  1.1        is fsub_zero_entry:
   11558  1.1        is 	fmovm.x		FP_SCR1(%a6),&0x80	# load dst op
   11559  1.1        is 
   11560  1.1        is 	fmov.l		&0x0,%fpsr		# clear FPSR
   11561  1.1        is 	fmov.l		L_SCR3(%a6),%fpcr	# set FPCR
   11562  1.1        is 
   11563  1.1        is 	fsub.x		FP_SCR0(%a6),%fp0	# execute subtract
   11564  1.1        is 
   11565  1.1        is 	fmov.l		&0x0,%fpcr		# clear FPCR
   11566  1.1        is 	fmov.l		%fpsr,%d1		# fetch INEX2, N, Z
   11567  1.1        is 
   11568  1.1        is 	or.l		%d1,USER_FPSR(%a6)	# save exc and ccode bits
   11569  1.1        is 
   11570  1.1        is 	fbeq.w		fsub_zero_exit		# if result zero, end now
   11571  1.1        is 
   11572  1.1        is 	mov.l		%d2,-(%sp)		# save d2
   11573  1.1        is 
   11574  1.1        is 	fmovm.x		&0x01,-(%sp)		# save result to stack
   11575  1.1        is 
   11576  1.1        is 	mov.w		2+L_SCR3(%a6),%d1
   11577  1.1        is 	lsr.b		&0x6,%d1
   11578  1.1        is 
   11579  1.1        is 	mov.w		(%sp),%d2		# fetch new exponent
   11580  1.1        is 	andi.l		&0x7fff,%d2		# strip sign
   11581  1.1        is 	sub.l		%d0,%d2			# add scale factor
   11582  1.1        is 
   11583  1.1        is 	cmp.l		%d2,(tbl_fsub_ovfl.b,%pc,%d1.w*4) # is it an overflow?
   11584  1.1        is 	bge.b		fsub_ovfl		# yes
   11585  1.1        is 
   11586  1.1        is 	cmp.l		%d2,(tbl_fsub_unfl.b,%pc,%d1.w*4) # is it an underflow?
   11587  1.1        is 	blt.w		fsub_unfl		# yes
   11588  1.1        is 	beq.w		fsub_may_unfl		# maybe; go find out
   11589  1.1        is 
   11590  1.1        is fsub_normal:
   11591  1.1        is 	mov.w		(%sp),%d1
   11592  1.1        is 	andi.w		&0x8000,%d1		# keep sign
   11593  1.1        is 	or.w		%d2,%d1			# insert new exponent
   11594  1.1        is 	mov.w		%d1,(%sp)		# insert new exponent
   11595  1.1        is 
   11596  1.1        is 	fmovm.x		(%sp)+,&0x80		# return result in fp0
   11597  1.1        is 
   11598  1.1        is 	mov.l		(%sp)+,%d2		# restore d2
   11599  1.1        is 	rts
   11600  1.1        is 
   11601  1.1        is fsub_zero_exit:
   11602  1.1        is #	fmov.s		&0x00000000,%fp0	# return zero in fp0
   11603  1.1        is 	rts
   11604  1.1        is 
   11605  1.1        is tbl_fsub_ovfl:
   11606  1.1        is 	long		0x7fff			# ext ovfl
   11607  1.1        is 	long		0x407f			# sgl ovfl
   11608  1.1        is 	long		0x43ff			# dbl ovfl
   11609  1.1        is 
   11610  1.1        is tbl_fsub_unfl:
   11611  1.1        is 	long	        0x0000			# ext unfl
   11612  1.1        is 	long		0x3f81			# sgl unfl
   11613  1.1        is 	long		0x3c01			# dbl unfl
   11614  1.1        is 
   11615  1.1        is fsub_ovfl:
   11616  1.1        is 	or.l		&ovfl_inx_mask,USER_FPSR(%a6) # set ovfl/aovfl/ainex
   11617  1.1        is 
   11618  1.1        is 	mov.b		FPCR_ENABLE(%a6),%d1
   11619  1.1        is 	andi.b		&0x13,%d1		# is OVFL or INEX enabled?
   11620  1.1        is 	bne.b		fsub_ovfl_ena		# yes
   11621  1.1        is 
   11622  1.1        is 	add.l		&0xc,%sp
   11623  1.1        is fsub_ovfl_dis:
   11624  1.1        is 	btst		&neg_bit,FPSR_CC(%a6)	# is result negative?
   11625  1.1        is 	sne		%d1			# set sign param accordingly
   11626  1.1        is 	mov.l		L_SCR3(%a6),%d0		# pass prec:rnd
   11627  1.1        is 	bsr.l		ovf_res			# calculate default result
   11628  1.1        is 	or.b		%d0,FPSR_CC(%a6)	# set INF,N if applicable
   11629  1.1        is 	fmovm.x		(%a0),&0x80		# return default result in fp0
   11630  1.1        is 	mov.l		(%sp)+,%d2		# restore d2
   11631  1.1        is 	rts
   11632  1.1        is 
   11633  1.1        is fsub_ovfl_ena:
   11634  1.1        is 	mov.b		L_SCR3(%a6),%d1
   11635  1.1        is 	andi.b		&0xc0,%d1		# is precision extended?
   11636  1.1        is 	bne.b		fsub_ovfl_ena_sd	# no
   11637  1.1        is 
   11638  1.1        is fsub_ovfl_ena_cont:
   11639  1.1        is 	mov.w		(%sp),%d1		# fetch {sgn,exp}
   11640  1.1        is 	andi.w		&0x8000,%d1		# keep sign
   11641  1.1        is 	subi.l		&0x6000,%d2		# subtract new bias
   11642  1.1        is 	andi.w		&0x7fff,%d2		# clear top bit
   11643  1.1        is 	or.w		%d2,%d1			# concat sign,exp
   11644  1.1        is 	mov.w		%d1,(%sp)		# insert new exponent
   11645  1.1        is 
   11646  1.1        is 	fmovm.x		(%sp)+,&0x40		# return EXOP in fp1
   11647  1.1        is 	bra.b		fsub_ovfl_dis
   11648  1.1        is 
   11649  1.1        is fsub_ovfl_ena_sd:
   11650  1.1        is 	fmovm.x		FP_SCR1(%a6),&0x80	# load dst op
   11651  1.1        is 
   11652  1.1        is 	mov.l		L_SCR3(%a6),%d1
   11653  1.1        is 	andi.b		&0x30,%d1		# clear rnd prec
   11654  1.1        is 	fmov.l		%d1,%fpcr		# set FPCR
   11655  1.1        is 
   11656  1.1        is 	fsub.x		FP_SCR0(%a6),%fp0	# execute subtract
   11657  1.1        is 
   11658  1.1        is 	fmov.l		&0x0,%fpcr		# clear FPCR
   11659  1.1        is 
   11660  1.1        is 	add.l		&0xc,%sp
   11661  1.1        is 	fmovm.x		&0x01,-(%sp)
   11662  1.1        is 	bra.b		fsub_ovfl_ena_cont
   11663  1.1        is 
   11664  1.1        is fsub_unfl:
   11665  1.1        is 	bset		&unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
   11666  1.1        is 
   11667  1.1        is 	add.l		&0xc,%sp
   11668  1.1        is 
   11669  1.1        is 	fmovm.x		FP_SCR1(%a6),&0x80	# load dst op
   11670  1.1        is 
   11671  1.1        is 	fmov.l		&rz_mode*0x10,%fpcr	# set FPCR
   11672  1.1        is 	fmov.l		&0x0,%fpsr		# clear FPSR
   11673  1.1        is 
   11674  1.1        is 	fsub.x		FP_SCR0(%a6),%fp0	# execute subtract
   11675  1.1        is 
   11676  1.1        is 	fmov.l		&0x0,%fpcr		# clear FPCR
   11677  1.1        is 	fmov.l		%fpsr,%d1		# save status
   11678  1.1        is 
   11679  1.1        is 	or.l		%d1,USER_FPSR(%a6)
   11680  1.1        is 
   11681  1.1        is 	mov.b		FPCR_ENABLE(%a6),%d1
   11682  1.1        is 	andi.b		&0x0b,%d1		# is UNFL or INEX enabled?
   11683  1.1        is 	bne.b		fsub_unfl_ena		# yes
   11684  1.1        is 
   11685  1.1        is fsub_unfl_dis:
   11686  1.1        is 	fmovm.x		&0x80,FP_SCR0(%a6)	# store out result
   11687  1.1        is 
   11688  1.1        is 	lea		FP_SCR0(%a6),%a0	# pass: result addr
   11689  1.1        is 	mov.l		L_SCR3(%a6),%d1		# pass: rnd prec,mode
   11690  1.1        is 	bsr.l		unf_res			# calculate default result
   11691  1.1        is 	or.b		%d0,FPSR_CC(%a6)	# 'Z' may have been set
   11692  1.1        is 	fmovm.x		FP_SCR0(%a6),&0x80	# return default result in fp0
   11693  1.1        is 	mov.l		(%sp)+,%d2		# restore d2
   11694  1.1        is 	rts
   11695  1.1        is 
   11696  1.1        is fsub_unfl_ena:
   11697  1.1        is 	fmovm.x		FP_SCR1(%a6),&0x40
   11698  1.1        is 
   11699  1.1        is 	mov.l		L_SCR3(%a6),%d1
   11700  1.1        is 	andi.b		&0xc0,%d1		# is precision extended?
   11701  1.1        is 	bne.b		fsub_unfl_ena_sd	# no
   11702  1.1        is 
   11703  1.1        is 	fmov.l		L_SCR3(%a6),%fpcr	# set FPCR
   11704  1.1        is 
   11705  1.1        is fsub_unfl_ena_cont:
   11706  1.1        is 	fmov.l		&0x0,%fpsr		# clear FPSR
   11707  1.1        is 
   11708  1.1        is 	fsub.x		FP_SCR0(%a6),%fp1	# execute subtract
   11709  1.1        is 
   11710  1.1        is 	fmov.l		&0x0,%fpcr		# clear FPCR
   11711  1.1        is 
   11712  1.1        is 	fmovm.x		&0x40,FP_SCR0(%a6)	# store result to stack
   11713  1.1        is 	mov.w		FP_SCR0_EX(%a6),%d1	# fetch {sgn,exp}
   11714  1.1        is 	mov.l		%d1,%d2			# make a copy
   11715  1.1        is 	andi.l		&0x7fff,%d1		# strip sign
   11716  1.1        is 	andi.w		&0x8000,%d2		# keep old sign
   11717  1.1        is 	sub.l		%d0,%d1			# add scale factor
   11718  1.1        is 	addi.l		&0x6000,%d1		# subtract new bias
   11719  1.1        is 	andi.w		&0x7fff,%d1		# clear top bit
   11720  1.1        is 	or.w		%d2,%d1			# concat sgn,exp
   11721  1.1        is 	mov.w		%d1,FP_SCR0_EX(%a6)	# insert new exponent
   11722  1.1        is 	fmovm.x		FP_SCR0(%a6),&0x40	# return EXOP in fp1
   11723  1.1        is 	bra.w		fsub_unfl_dis
   11724  1.1        is 
   11725  1.1        is fsub_unfl_ena_sd:
   11726  1.1        is 	mov.l		L_SCR3(%a6),%d1
   11727  1.1        is 	andi.b		&0x30,%d1		# clear rnd prec
   11728  1.1        is 	fmov.l		%d1,%fpcr		# set FPCR
   11729  1.1        is 
   11730  1.1        is 	bra.b		fsub_unfl_ena_cont
   11731  1.1        is 
   11732  1.1        is #
   11733  1.1        is # result is equal to the smallest normalized number in the selected precision
   11734  1.1        is # if the precision is extended, this result could not have come from an
   11735  1.1        is # underflow that rounded up.
   11736  1.1        is #
   11737  1.1        is fsub_may_unfl:
   11738  1.1        is 	mov.l		L_SCR3(%a6),%d1
   11739  1.1        is 	andi.b		&0xc0,%d1		# fetch rnd prec
   11740  1.1        is 	beq.w		fsub_normal		# yes; no underflow occurred
   11741  1.1        is 
   11742  1.1        is 	mov.l		0x4(%sp),%d1
   11743  1.1        is 	cmpi.l		%d1,&0x80000000		# is hi(man) = 0x80000000?
   11744  1.1        is 	bne.w		fsub_normal		# no; no underflow occurred
   11745  1.1        is 
   11746  1.1        is 	tst.l		0x8(%sp)		# is lo(man) = 0x0?
   11747  1.1        is 	bne.w		fsub_normal		# no; no underflow occurred
   11748  1.1        is 
   11749  1.1        is 	btst		&inex2_bit,FPSR_EXCEPT(%a6) # is INEX2 set?
   11750  1.1        is 	beq.w		fsub_normal		# no; no underflow occurred
   11751  1.1        is 
   11752  1.1        is #
   11753  1.1        is # ok, so now the result has a exponent equal to the smallest normalized
   11754  1.1        is # exponent for the selected precision. also, the mantissa is equal to
   11755  1.1        is # 0x8000000000000000 and this mantissa is the result of rounding non-zero
   11756  1.1        is # g,r,s.
   11757  1.1        is # now, we must determine whether the pre-rounded result was an underflow
   11758  1.1        is # rounded "up" or a normalized number rounded "down".
   11759  1.1        is # so, we do this be re-executing the add using RZ as the rounding mode and
   11760  1.1        is # seeing if the new result is smaller or equal to the current result.
   11761  1.1        is #
   11762  1.1        is 	fmovm.x		FP_SCR1(%a6),&0x40	# load dst op into fp1
   11763  1.1        is 
   11764  1.1        is 	mov.l		L_SCR3(%a6),%d1
   11765  1.1        is 	andi.b		&0xc0,%d1		# keep rnd prec
   11766  1.1        is 	ori.b		&rz_mode*0x10,%d1	# insert rnd mode
   11767  1.1        is 	fmov.l		%d1,%fpcr		# set FPCR
   11768  1.1        is 	fmov.l		&0x0,%fpsr		# clear FPSR
   11769  1.1        is 
   11770  1.1        is 	fsub.x		FP_SCR0(%a6),%fp1	# execute subtract
   11771  1.1        is 
   11772  1.1        is 	fmov.l		&0x0,%fpcr		# clear FPCR
   11773  1.1        is 
   11774  1.1        is 	fabs.x		%fp0			# compare absolute values
   11775  1.1        is 	fabs.x		%fp1
   11776  1.1        is 	fcmp.x		%fp0,%fp1		# is first result > second?
   11777  1.1        is 
   11778  1.1        is 	fbgt.w		fsub_unfl		# yes; it's an underflow
   11779  1.1        is 	bra.w		fsub_normal		# no; it's not an underflow
   11780  1.1        is 
   11781  1.1        is ##########################################################################
   11782  1.1        is 
   11783  1.1        is #
   11784  1.1        is # Sub: inputs are not both normalized; what are they?
   11785  1.1        is #
   11786  1.1        is fsub_not_norm:
   11787  1.1        is 	mov.w		(tbl_fsub_op.b,%pc,%d1.w*2),%d1
   11788  1.1        is 	jmp		(tbl_fsub_op.b,%pc,%d1.w*1)
   11789  1.1        is 
   11790  1.1        is 	swbeg		&48
   11791  1.1        is tbl_fsub_op:
   11792  1.1        is 	short		fsub_norm	- tbl_fsub_op # NORM - NORM
   11793  1.1        is 	short		fsub_zero_src	- tbl_fsub_op # NORM - ZERO
   11794  1.1        is 	short		fsub_inf_src	- tbl_fsub_op # NORM - INF
   11795  1.1        is 	short		fsub_res_qnan	- tbl_fsub_op # NORM - QNAN
   11796  1.1        is 	short		fsub_norm	- tbl_fsub_op # NORM - DENORM
   11797  1.1        is 	short		fsub_res_snan	- tbl_fsub_op # NORM - SNAN
   11798  1.1        is 	short		tbl_fsub_op	- tbl_fsub_op #
   11799  1.1        is 	short		tbl_fsub_op	- tbl_fsub_op #
   11800  1.1        is 
   11801  1.1        is 	short		fsub_zero_dst	- tbl_fsub_op # ZERO - NORM
   11802  1.1        is 	short		fsub_zero_2	- tbl_fsub_op # ZERO - ZERO
   11803  1.1        is 	short		fsub_inf_src	- tbl_fsub_op # ZERO - INF
   11804  1.1        is 	short		fsub_res_qnan	- tbl_fsub_op # NORM - QNAN
   11805  1.1        is 	short		fsub_zero_dst	- tbl_fsub_op # ZERO - DENORM
   11806  1.1        is 	short		fsub_res_snan	- tbl_fsub_op # NORM - SNAN
   11807  1.1        is 	short		tbl_fsub_op	- tbl_fsub_op #
   11808  1.1        is 	short		tbl_fsub_op	- tbl_fsub_op #
   11809  1.1        is 
   11810  1.1        is 	short		fsub_inf_dst	- tbl_fsub_op # INF - NORM
   11811  1.1        is 	short		fsub_inf_dst	- tbl_fsub_op # INF - ZERO
   11812  1.1        is 	short		fsub_inf_2	- tbl_fsub_op # INF - INF
   11813  1.1        is 	short		fsub_res_qnan	- tbl_fsub_op # NORM - QNAN
   11814  1.1        is 	short		fsub_inf_dst	- tbl_fsub_op # INF - DENORM
   11815  1.1        is 	short		fsub_res_snan	- tbl_fsub_op # NORM - SNAN
   11816  1.1        is 	short		tbl_fsub_op	- tbl_fsub_op #
   11817  1.1        is 	short		tbl_fsub_op	- tbl_fsub_op #
   11818  1.1        is 
   11819  1.1        is 	short		fsub_res_qnan	- tbl_fsub_op # QNAN - NORM
   11820  1.1        is 	short		fsub_res_qnan	- tbl_fsub_op # QNAN - ZERO
   11821  1.1        is 	short		fsub_res_qnan	- tbl_fsub_op # QNAN - INF
   11822  1.1        is 	short		fsub_res_qnan	- tbl_fsub_op # QNAN - QNAN
   11823  1.1        is 	short		fsub_res_qnan	- tbl_fsub_op # QNAN - DENORM
   11824  1.1        is 	short		fsub_res_snan	- tbl_fsub_op # QNAN - SNAN
   11825  1.1        is 	short		tbl_fsub_op	- tbl_fsub_op #
   11826  1.1        is 	short		tbl_fsub_op	- tbl_fsub_op #
   11827  1.1        is 
   11828  1.1        is 	short		fsub_norm	- tbl_fsub_op # DENORM - NORM
   11829  1.1        is 	short		fsub_zero_src	- tbl_fsub_op # DENORM - ZERO
   11830  1.1        is 	short		fsub_inf_src	- tbl_fsub_op # DENORM - INF
   11831  1.1        is 	short		fsub_res_qnan	- tbl_fsub_op # NORM - QNAN
   11832  1.1        is 	short		fsub_norm	- tbl_fsub_op # DENORM - DENORM
   11833  1.1        is 	short		fsub_res_snan	- tbl_fsub_op # NORM - SNAN
   11834  1.1        is 	short		tbl_fsub_op	- tbl_fsub_op #
   11835  1.1        is 	short		tbl_fsub_op	- tbl_fsub_op #
   11836  1.1        is 
   11837  1.1        is 	short		fsub_res_snan	- tbl_fsub_op # SNAN - NORM
   11838  1.1        is 	short		fsub_res_snan	- tbl_fsub_op # SNAN - ZERO
   11839  1.1        is 	short		fsub_res_snan	- tbl_fsub_op # SNAN - INF
   11840  1.1        is 	short		fsub_res_snan	- tbl_fsub_op # SNAN - QNAN
   11841  1.1        is 	short		fsub_res_snan	- tbl_fsub_op # SNAN - DENORM
   11842  1.1        is 	short		fsub_res_snan	- tbl_fsub_op # SNAN - SNAN
   11843  1.1        is 	short		tbl_fsub_op	- tbl_fsub_op #
   11844  1.1        is 	short		tbl_fsub_op	- tbl_fsub_op #
   11845  1.1        is 
   11846  1.1        is fsub_res_qnan:
   11847  1.1        is 	bra.l		res_qnan
   11848  1.1        is fsub_res_snan:
   11849  1.1        is 	bra.l		res_snan
   11850  1.1        is 
   11851  1.1        is #
   11852  1.1        is # both operands are ZEROes
   11853  1.1        is #
   11854  1.1        is fsub_zero_2:
   11855  1.1        is 	mov.b		SRC_EX(%a0),%d0
   11856  1.1        is 	mov.b		DST_EX(%a1),%d1
   11857  1.1        is 	eor.b		%d1,%d0
   11858  1.1        is 	bpl.b		fsub_zero_2_chk_rm
   11859  1.1        is 
   11860  1.1        is # the signs are opposite, so, return a ZERO w/ the sign of the dst ZERO
   11861  1.1        is 	tst.b		%d0			# is dst negative?
   11862  1.1        is 	bmi.b		fsub_zero_2_rm		# yes
   11863  1.1        is 	fmov.s		&0x00000000,%fp0	# no; return +ZERO
   11864  1.1        is 	mov.b		&z_bmask,FPSR_CC(%a6)	# set Z
   11865  1.1        is 	rts
   11866  1.1        is 
   11867  1.1        is #
   11868  1.1        is # the ZEROes have the same signs:
   11869  1.1        is # - therefore, we return +ZERO if the rounding mode is RN,RZ, or RP
   11870  1.1        is # - -ZERO is returned in the case of RM.
   11871  1.1        is #
   11872  1.1        is fsub_zero_2_chk_rm:
   11873  1.1        is 	mov.b		3+L_SCR3(%a6),%d1
   11874  1.1        is 	andi.b		&0x30,%d1		# extract rnd mode
   11875  1.1        is 	cmpi.b		%d1,&rm_mode*0x10	# is rnd mode = RM?
   11876  1.1        is 	beq.b		fsub_zero_2_rm		# yes
   11877  1.1        is 	fmov.s		&0x00000000,%fp0	# no; return +ZERO
   11878  1.1        is 	mov.b		&z_bmask,FPSR_CC(%a6)	# set Z
   11879  1.1        is 	rts
   11880  1.1        is 
   11881  1.1        is fsub_zero_2_rm:
   11882  1.1        is 	fmov.s		&0x80000000,%fp0	# return -ZERO
   11883  1.1        is 	mov.b		&z_bmask+neg_bmask,FPSR_CC(%a6)	# set Z/NEG
   11884  1.1        is 	rts
   11885  1.1        is 
   11886  1.1        is #
   11887  1.1        is # one operand is a ZERO and the other is a DENORM or a NORM.
   11888  1.1        is # scale the DENORM or NORM and jump to the regular fsub routine.
   11889  1.1        is #
   11890  1.1        is fsub_zero_dst:
   11891  1.1        is 	mov.w		SRC_EX(%a0),FP_SCR0_EX(%a6)
   11892  1.1        is 	mov.l		SRC_HI(%a0),FP_SCR0_HI(%a6)
   11893  1.1        is 	mov.l		SRC_LO(%a0),FP_SCR0_LO(%a6)
   11894  1.1        is 	bsr.l		scale_to_zero_src	# scale the operand
   11895  1.1        is 	clr.w		FP_SCR1_EX(%a6)
   11896  1.1        is 	clr.l		FP_SCR1_HI(%a6)
   11897  1.1        is 	clr.l		FP_SCR1_LO(%a6)
   11898  1.1        is 	bra.w		fsub_zero_entry		# go execute fsub
   11899  1.1        is 
   11900  1.1        is fsub_zero_src:
   11901  1.1        is 	mov.w		DST_EX(%a1),FP_SCR1_EX(%a6)
   11902  1.1        is 	mov.l		DST_HI(%a1),FP_SCR1_HI(%a6)
   11903  1.1        is 	mov.l		DST_LO(%a1),FP_SCR1_LO(%a6)
   11904  1.1        is 	bsr.l		scale_to_zero_dst	# scale the operand
   11905  1.1        is 	clr.w		FP_SCR0_EX(%a6)
   11906  1.1        is 	clr.l		FP_SCR0_HI(%a6)
   11907  1.1        is 	clr.l		FP_SCR0_LO(%a6)
   11908  1.1        is 	bra.w		fsub_zero_entry		# go execute fsub
   11909  1.1        is 
   11910  1.1        is #
   11911  1.1        is # both operands are INFs. an OPERR will result if the INFs have the
   11912  1.1        is # same signs. else,
   11913  1.1        is #
   11914  1.1        is fsub_inf_2:
   11915  1.1        is 	mov.b		SRC_EX(%a0),%d0		# exclusive or the signs
   11916  1.1        is 	mov.b		DST_EX(%a1),%d1
   11917  1.1        is 	eor.b		%d1,%d0
   11918  1.1        is 	bpl.l		res_operr		# weed out (-INF)+(+INF)
   11919  1.1        is 
   11920  1.1        is # ok, so it's not an OPERR. but we do have to remember to return
   11921  1.1        is # the src INF since that's where the 881/882 gets the j-bit.
   11922  1.1        is 
   11923  1.1        is fsub_inf_src:
   11924  1.1        is 	fmovm.x		SRC(%a0),&0x80		# return src INF
   11925  1.1        is 	fneg.x		%fp0			# invert sign
   11926  1.1        is 	fbge.w		fsub_inf_done		# sign is now positive
   11927  1.1        is 	mov.b		&neg_bmask+inf_bmask,FPSR_CC(%a6) # set INF/NEG
   11928  1.1        is 	rts
   11929  1.1        is 
   11930  1.1        is fsub_inf_dst:
   11931  1.1        is 	fmovm.x		DST(%a1),&0x80		# return dst INF
   11932  1.1        is 	tst.b		DST_EX(%a1)		# is INF negative?
   11933  1.1        is 	bpl.b		fsub_inf_done		# no
   11934  1.1        is 	mov.b		&neg_bmask+inf_bmask,FPSR_CC(%a6) # set INF/NEG
   11935  1.1        is 	rts
   11936  1.1        is 
   11937  1.1        is fsub_inf_done:
   11938  1.1        is 	mov.b		&inf_bmask,FPSR_CC(%a6)	# set INF
   11939  1.1        is 	rts
   11940  1.1        is 
   11941  1.1        is #########################################################################
   11942  1.1        is # XDEF ****************************************************************	#
   11943  1.1        is # 	fsqrt(): emulates the fsqrt instruction				#
   11944  1.1        is #	fssqrt(): emulates the fssqrt instruction			#
   11945  1.1        is #	fdsqrt(): emulates the fdsqrt instruction			#
   11946  1.1        is #									#
   11947  1.1        is # XREF ****************************************************************	#
   11948  1.1        is #	scale_sqrt() - scale the source operand				#
   11949  1.1        is #	unf_res() - return default underflow result			#
   11950  1.1        is #	ovf_res() - return default overflow result			#
   11951  1.1        is # 	res_qnan_1op() - return QNAN result				#
   11952  1.1        is # 	res_snan_1op() - return SNAN result				#
   11953  1.1        is #									#
   11954  1.1        is # INPUT ***************************************************************	#
   11955  1.1        is #	a0 = pointer to extended precision source operand		#
   11956  1.1        is #	d0  rnd prec,mode						#
   11957  1.1        is #									#
   11958  1.1        is # OUTPUT **************************************************************	#
   11959  1.1        is #	fp0 = result							#
   11960  1.1        is #	fp1 = EXOP (if exception occurred)				#
   11961  1.1        is #									#
   11962  1.1        is # ALGORITHM ***********************************************************	#
   11963  1.1        is #	Handle NANs, infinities, and zeroes as special cases. Divide	#
   11964  1.1        is # norms/denorms into ext/sgl/dbl precision.				#
   11965  1.1        is #	For norms/denorms, scale the exponents such that a sqrt		#
   11966  1.1        is # instruction won't cause an exception. Use the regular fsqrt to	#
   11967  1.1        is # compute a result. Check if the regular operands would have taken	#
   11968  1.1        is # an exception. If so, return the default overflow/underflow result	#
   11969  1.1        is # and return the EXOP if exceptions are enabled. Else, scale the 	#
   11970  1.1        is # result operand to the proper exponent.				#
   11971  1.1        is #									#
   11972  1.1        is #########################################################################
   11973  1.1        is 
   11974  1.1        is 	global		fssqrt
   11975  1.1        is fssqrt:
   11976  1.1        is 	andi.b		&0x30,%d0		# clear rnd prec
   11977  1.1        is 	ori.b		&s_mode*0x10,%d0	# insert sgl precision
   11978  1.1        is 	bra.b		fsqrt
   11979  1.1        is 
   11980  1.1        is 	global		fdsqrt
   11981  1.1        is fdsqrt:
   11982  1.1        is 	andi.b		&0x30,%d0		# clear rnd prec
   11983  1.1        is 	ori.b		&d_mode*0x10,%d0	# insert dbl precision
   11984  1.1        is 
   11985  1.1        is 	global		fsqrt
   11986  1.1        is fsqrt:
   11987  1.1        is 	mov.l		%d0,L_SCR3(%a6)		# store rnd info
   11988  1.1        is 	clr.w		%d1
   11989  1.1        is 	mov.b		STAG(%a6),%d1
   11990  1.1        is 	bne.w		fsqrt_not_norm		# optimize on non-norm input
   11991  1.1        is 
   11992  1.1        is #
   11993  1.1        is # SQUARE ROOT: norms and denorms ONLY!
   11994  1.1        is #
   11995  1.1        is fsqrt_norm:
   11996  1.1        is 	tst.b		SRC_EX(%a0)		# is operand negative?
   11997  1.1        is 	bmi.l		res_operr		# yes
   11998  1.1        is 
   11999  1.1        is 	andi.b		&0xc0,%d0		# is precision extended?
   12000  1.1        is 	bne.b		fsqrt_not_ext		# no; go handle sgl or dbl
   12001  1.1        is 
   12002  1.1        is 	fmov.l		L_SCR3(%a6),%fpcr	# set FPCR
   12003  1.1        is 	fmov.l		&0x0,%fpsr		# clear FPSR
   12004  1.1        is 
   12005  1.1        is 	fsqrt.x		(%a0),%fp0		# execute square root
   12006  1.1        is 
   12007  1.1        is 	fmov.l		%fpsr,%d1
   12008  1.1        is 	or.l		%d1,USER_FPSR(%a6)	# set N,INEX
   12009  1.1        is 
   12010  1.1        is 	rts
   12011  1.1        is 
   12012  1.1        is fsqrt_denorm:
   12013  1.1        is 	tst.b		SRC_EX(%a0)		# is operand negative?
   12014  1.1        is 	bmi.l		res_operr		# yes
   12015  1.1        is 
   12016  1.1        is 	andi.b		&0xc0,%d0		# is precision extended?
   12017  1.1        is 	bne.b		fsqrt_not_ext		# no; go handle sgl or dbl
   12018  1.1        is 
   12019  1.1        is 	mov.w		SRC_EX(%a0),FP_SCR0_EX(%a6)
   12020  1.1        is 	mov.l		SRC_HI(%a0),FP_SCR0_HI(%a6)
   12021  1.1        is 	mov.l		SRC_LO(%a0),FP_SCR0_LO(%a6)
   12022  1.1        is 
   12023  1.1        is 	bsr.l		scale_sqrt		# calculate scale factor
   12024  1.1        is 
   12025  1.1        is 	bra.w		fsqrt_sd_normal
   12026  1.1        is 
   12027  1.1        is #
   12028  1.1        is # operand is either single or double
   12029  1.1        is #
   12030  1.1        is fsqrt_not_ext:
   12031  1.1        is 	cmpi.b		%d0,&s_mode*0x10	# separate sgl/dbl prec
   12032  1.1        is 	bne.w		fsqrt_dbl
   12033  1.1        is 
   12034  1.1        is #
   12035  1.1        is # operand is to be rounded to single precision
   12036  1.1        is #
   12037  1.1        is fsqrt_sgl:
   12038  1.1        is 	mov.w		SRC_EX(%a0),FP_SCR0_EX(%a6)
   12039  1.1        is 	mov.l		SRC_HI(%a0),FP_SCR0_HI(%a6)
   12040  1.1        is 	mov.l		SRC_LO(%a0),FP_SCR0_LO(%a6)
   12041  1.1        is 
   12042  1.1        is 	bsr.l		scale_sqrt		# calculate scale factor
   12043  1.1        is 
   12044  1.1        is 	cmpi.l		%d0,&0x3fff-0x3f81	# will move in underflow?
   12045  1.1        is 	beq.w		fsqrt_sd_may_unfl
   12046  1.1        is 	bgt.w		fsqrt_sd_unfl		# yes; go handle underflow
   12047  1.1        is 	cmpi.l		%d0,&0x3fff-0x407f	# will move in overflow?
   12048  1.1        is 	beq.w		fsqrt_sd_may_ovfl	# maybe; go check
   12049  1.1        is 	blt.w		fsqrt_sd_ovfl		# yes; go handle overflow
   12050  1.1        is 
   12051  1.1        is #
   12052  1.1        is # operand will NOT overflow or underflow when moved in to the fp reg file
   12053  1.1        is #
   12054  1.1        is fsqrt_sd_normal:
   12055  1.1        is 	fmov.l		&0x0,%fpsr		# clear FPSR
   12056  1.1        is 	fmov.l		L_SCR3(%a6),%fpcr	# set FPCR
   12057  1.1        is 
   12058  1.1        is 	fsqrt.x		FP_SCR0(%a6),%fp0	# perform absolute
   12059  1.1        is 
   12060  1.1        is 	fmov.l		%fpsr,%d1		# save FPSR
   12061  1.1        is 	fmov.l		&0x0,%fpcr		# clear FPCR
   12062  1.1        is 
   12063  1.1        is 	or.l		%d1,USER_FPSR(%a6)	# save INEX2,N
   12064  1.1        is 
   12065  1.1        is fsqrt_sd_normal_exit:
   12066  1.1        is 	mov.l		%d2,-(%sp)		# save d2
   12067  1.1        is 	fmovm.x		&0x80,FP_SCR0(%a6)	# store out result
   12068  1.1        is 	mov.w		FP_SCR0_EX(%a6),%d1	# load sgn,exp
   12069  1.1        is 	mov.l		%d1,%d2			# make a copy
   12070  1.1        is 	andi.l		&0x7fff,%d1		# strip sign
   12071  1.1        is 	sub.l		%d0,%d1			# add scale factor
   12072  1.1        is 	andi.w		&0x8000,%d2		# keep old sign
   12073  1.1        is 	or.w		%d1,%d2			# concat old sign,new exp
   12074  1.1        is 	mov.w		%d2,FP_SCR0_EX(%a6)	# insert new exponent
   12075  1.1        is 	mov.l		(%sp)+,%d2		# restore d2
   12076  1.1        is 	fmovm.x		FP_SCR0(%a6),&0x80	# return result in fp0
   12077  1.1        is 	rts
   12078  1.1        is 
   12079  1.1        is #
   12080  1.1        is # operand is to be rounded to double precision
   12081  1.1        is #
   12082  1.1        is fsqrt_dbl:
   12083  1.1        is 	mov.w		SRC_EX(%a0),FP_SCR0_EX(%a6)
   12084  1.1        is 	mov.l		SRC_HI(%a0),FP_SCR0_HI(%a6)
   12085  1.1        is 	mov.l		SRC_LO(%a0),FP_SCR0_LO(%a6)
   12086  1.1        is 
   12087  1.1        is 	bsr.l		scale_sqrt		# calculate scale factor
   12088  1.1        is 
   12089  1.1        is 	cmpi.l		%d0,&0x3fff-0x3c01	# will move in underflow?
   12090  1.1        is 	beq.w		fsqrt_sd_may_unfl
   12091  1.1        is 	bgt.b		fsqrt_sd_unfl		# yes; go handle underflow
   12092  1.1        is 	cmpi.l		%d0,&0x3fff-0x43ff	# will move in overflow?
   12093  1.1        is 	beq.w		fsqrt_sd_may_ovfl	# maybe; go check
   12094  1.1        is 	blt.w		fsqrt_sd_ovfl		# yes; go handle overflow
   12095  1.1        is 	bra.w		fsqrt_sd_normal		# no; ho handle normalized op
   12096  1.1        is 
   12097  1.1        is # we're on the line here and the distinguising characteristic is whether
   12098  1.1        is # the exponent is 3fff or 3ffe. if it's 3ffe, then it's a safe number
   12099  1.1        is # elsewise fall through to underflow.
   12100  1.1        is fsqrt_sd_may_unfl:
   12101  1.1        is 	btst		&0x0,1+FP_SCR0_EX(%a6)	# is exponent 0x3fff?
   12102  1.1        is 	bne.w		fsqrt_sd_normal		# yes, so no underflow
   12103  1.1        is 
   12104  1.1        is #
   12105  1.1        is # operand WILL underflow when moved in to the fp register file
   12106  1.1        is #
   12107  1.1        is fsqrt_sd_unfl:
   12108  1.1        is 	bset		&unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
   12109  1.1        is 
   12110  1.1        is 	fmov.l		&rz_mode*0x10,%fpcr	# set FPCR
   12111  1.1        is 	fmov.l		&0x0,%fpsr		# clear FPSR
   12112  1.1        is 
   12113  1.1        is 	fsqrt.x 	FP_SCR0(%a6),%fp0	# execute square root
   12114  1.1        is 
   12115  1.1        is 	fmov.l		%fpsr,%d1		# save status
   12116  1.1        is 	fmov.l		&0x0,%fpcr		# clear FPCR
   12117  1.1        is 
   12118  1.1        is 	or.l		%d1,USER_FPSR(%a6)	# save INEX2,N
   12119  1.1        is 
   12120  1.1        is # if underflow or inexact is enabled, go calculate EXOP first.
   12121  1.1        is 	mov.b		FPCR_ENABLE(%a6),%d1
   12122  1.1        is 	andi.b		&0x0b,%d1		# is UNFL or INEX enabled?
   12123  1.1        is 	bne.b		fsqrt_sd_unfl_ena	# yes
   12124  1.1        is 
   12125  1.1        is fsqrt_sd_unfl_dis:
   12126  1.1        is 	fmovm.x		&0x80,FP_SCR0(%a6)	# store out result
   12127  1.1        is 
   12128  1.1        is 	lea		FP_SCR0(%a6),%a0	# pass: result addr
   12129  1.1        is 	mov.l		L_SCR3(%a6),%d1		# pass: rnd prec,mode
   12130  1.1        is 	bsr.l		unf_res			# calculate default result
   12131  1.1        is 	or.b		%d0,FPSR_CC(%a6)	# set possible 'Z' ccode
   12132  1.1        is 	fmovm.x		FP_SCR0(%a6),&0x80	# return default result in fp0
   12133  1.1        is 	rts
   12134  1.1        is 
   12135  1.1        is #
   12136  1.1        is # operand will underflow AND underflow is enabled.
   12137  1.1        is # therefore, we must return the result rounded to extended precision.
   12138  1.1        is #
   12139  1.1        is fsqrt_sd_unfl_ena:
   12140  1.1        is 	mov.l		FP_SCR0_HI(%a6),FP_SCR1_HI(%a6)
   12141  1.1        is 	mov.l		FP_SCR0_LO(%a6),FP_SCR1_LO(%a6)
   12142  1.1        is 	mov.w		FP_SCR0_EX(%a6),%d1	# load current exponent
   12143  1.1        is 
   12144  1.1        is 	mov.l		%d2,-(%sp)		# save d2
   12145  1.1        is 	mov.l		%d1,%d2			# make a copy
   12146  1.1        is 	andi.l		&0x7fff,%d1		# strip sign
   12147  1.1        is 	andi.w		&0x8000,%d2		# keep old sign
   12148  1.1        is 	sub.l		%d0,%d1			# subtract scale factor
   12149  1.1        is 	addi.l		&0x6000,%d1		# add new bias
   12150  1.1        is 	andi.w		&0x7fff,%d1
   12151  1.1        is 	or.w		%d2,%d1			# concat new sign,new exp
   12152  1.1        is 	mov.w		%d1,FP_SCR1_EX(%a6)	# insert new exp
   12153  1.1        is 	fmovm.x		FP_SCR1(%a6),&0x40	# return EXOP in fp1
   12154  1.1        is 	mov.l		(%sp)+,%d2		# restore d2
   12155  1.1        is 	bra.b		fsqrt_sd_unfl_dis
   12156  1.1        is 
   12157  1.1        is #
   12158  1.1        is # operand WILL overflow.
   12159  1.1        is #
   12160  1.1        is fsqrt_sd_ovfl:
   12161  1.1        is 	fmov.l		&0x0,%fpsr		# clear FPSR
   12162  1.1        is 	fmov.l		L_SCR3(%a6),%fpcr	# set FPCR
   12163  1.1        is 
   12164  1.1        is 	fsqrt.x		FP_SCR0(%a6),%fp0	# perform square root
   12165  1.1        is 
   12166  1.1        is 	fmov.l		&0x0,%fpcr		# clear FPCR
   12167  1.1        is 	fmov.l		%fpsr,%d1		# save FPSR
   12168  1.1        is 
   12169  1.1        is 	or.l		%d1,USER_FPSR(%a6)	# save INEX2,N
   12170  1.1        is 
   12171  1.1        is fsqrt_sd_ovfl_tst:
   12172  1.1        is 	or.l		&ovfl_inx_mask,USER_FPSR(%a6) # set ovfl/aovfl/ainex
   12173  1.1        is 
   12174  1.1        is 	mov.b		FPCR_ENABLE(%a6),%d1
   12175  1.1        is 	andi.b		&0x13,%d1		# is OVFL or INEX enabled?
   12176  1.1        is 	bne.b		fsqrt_sd_ovfl_ena	# yes
   12177  1.1        is 
   12178  1.1        is #
   12179  1.1        is # OVFL is not enabled; therefore, we must create the default result by
   12180  1.1        is # calling ovf_res().
   12181  1.1        is #
   12182  1.1        is fsqrt_sd_ovfl_dis:
   12183  1.1        is 	btst		&neg_bit,FPSR_CC(%a6)	# is result negative?
   12184  1.1        is 	sne		%d1			# set sign param accordingly
   12185  1.1        is 	mov.l		L_SCR3(%a6),%d0		# pass: prec,mode
   12186  1.1        is 	bsr.l		ovf_res			# calculate default result
   12187  1.1        is 	or.b		%d0,FPSR_CC(%a6)	# set INF,N if applicable
   12188  1.1        is 	fmovm.x		(%a0),&0x80		# return default result in fp0
   12189  1.1        is 	rts
   12190  1.1        is 
   12191  1.1        is #
   12192  1.1        is # OVFL is enabled.
   12193  1.1        is # the INEX2 bit has already been updated by the round to the correct precision.
   12194  1.1        is # now, round to extended(and don't alter the FPSR).
   12195  1.1        is #
   12196  1.1        is fsqrt_sd_ovfl_ena:
   12197  1.1        is 	mov.l		%d2,-(%sp)		# save d2
   12198  1.1        is 	mov.w		FP_SCR0_EX(%a6),%d1	# fetch {sgn,exp}
   12199  1.1        is 	mov.l		%d1,%d2			# make a copy
   12200  1.1        is 	andi.l		&0x7fff,%d1		# strip sign
   12201  1.1        is 	andi.w		&0x8000,%d2		# keep old sign
   12202  1.1        is 	sub.l		%d0,%d1			# add scale factor
   12203  1.1        is 	subi.l		&0x6000,%d1		# subtract bias
   12204  1.1        is 	andi.w		&0x7fff,%d1
   12205  1.1        is 	or.w		%d2,%d1			# concat sign,exp
   12206  1.1        is 	mov.w		%d1,FP_SCR0_EX(%a6)	# insert new exponent
   12207  1.1        is 	fmovm.x		FP_SCR0(%a6),&0x40	# return EXOP in fp1
   12208  1.1        is 	mov.l		(%sp)+,%d2		# restore d2
   12209  1.1        is 	bra.b		fsqrt_sd_ovfl_dis
   12210  1.1        is 
   12211  1.1        is #
   12212  1.1        is # the move in MAY underflow. so...
   12213  1.1        is #
   12214  1.1        is fsqrt_sd_may_ovfl:
   12215  1.1        is 	btst		&0x0,1+FP_SCR0_EX(%a6)	# is exponent 0x3fff?
   12216  1.1        is 	bne.w		fsqrt_sd_ovfl		# yes, so overflow
   12217  1.1        is 
   12218  1.1        is 	fmov.l		&0x0,%fpsr		# clear FPSR
   12219  1.1        is 	fmov.l		L_SCR3(%a6),%fpcr	# set FPCR
   12220  1.1        is 
   12221  1.1        is 	fsqrt.x		FP_SCR0(%a6),%fp0	# perform absolute
   12222  1.1        is 
   12223  1.1        is 	fmov.l		%fpsr,%d1		# save status
   12224  1.1        is 	fmov.l		&0x0,%fpcr		# clear FPCR
   12225  1.1        is 
   12226  1.1        is 	or.l		%d1,USER_FPSR(%a6)	# save INEX2,N
   12227  1.1        is 
   12228  1.1        is 	fmov.x		%fp0,%fp1		# make a copy of result
   12229  1.1        is 	fcmp.b		%fp1,&0x1		# is |result| >= 1.b?
   12230  1.1        is 	fbge.w		fsqrt_sd_ovfl_tst	# yes; overflow has occurred
   12231  1.1        is 
   12232  1.1        is # no, it didn't overflow; we have correct result
   12233  1.1        is 	bra.w		fsqrt_sd_normal_exit
   12234  1.1        is 
   12235  1.1        is ##########################################################################
   12236  1.1        is 
   12237  1.1        is #
   12238  1.1        is # input is not normalized; what is it?
   12239  1.1        is #
   12240  1.1        is fsqrt_not_norm:
   12241  1.1        is 	cmpi.b		%d1,&DENORM		# weed out DENORM
   12242  1.1        is 	beq.w		fsqrt_denorm
   12243  1.1        is 	cmpi.b		%d1,&ZERO		# weed out ZERO
   12244  1.1        is 	beq.b		fsqrt_zero
   12245  1.1        is 	cmpi.b		%d1,&INF		# weed out INF
   12246  1.1        is 	beq.b		fsqrt_inf
   12247  1.1        is 	cmpi.b		%d1,&SNAN		# weed out SNAN
   12248  1.1        is 	beq.l		res_snan_1op
   12249  1.1        is 	bra.l		res_qnan_1op
   12250  1.1        is 
   12251  1.1        is #
   12252  1.1        is # 	fsqrt(+0) = +0
   12253  1.1        is # 	fsqrt(-0) = -0
   12254  1.1        is #	fsqrt(+INF) = +INF
   12255  1.1        is # 	fsqrt(-INF) = OPERR
   12256  1.1        is #
   12257  1.1        is fsqrt_zero:
   12258  1.1        is 	tst.b		SRC_EX(%a0)		# is ZERO positive or negative?
   12259  1.1        is 	bmi.b		fsqrt_zero_m		# negative
   12260  1.1        is fsqrt_zero_p:
   12261  1.1        is 	fmov.s		&0x00000000,%fp0	# return +ZERO
   12262  1.1        is 	mov.b		&z_bmask,FPSR_CC(%a6)	# set 'Z' ccode bit
   12263  1.1        is 	rts
   12264  1.1        is fsqrt_zero_m:
   12265  1.1        is 	fmov.s		&0x80000000,%fp0	# return -ZERO
   12266  1.1        is 	mov.b		&z_bmask+neg_bmask,FPSR_CC(%a6)	# set 'Z','N' ccode bits
   12267  1.1        is 	rts
   12268  1.1        is 
   12269  1.1        is fsqrt_inf:
   12270  1.1        is 	tst.b		SRC_EX(%a0)		# is INF positive or negative?
   12271  1.1        is 	bmi.l		res_operr		# negative
   12272  1.1        is fsqrt_inf_p:
   12273  1.1        is 	fmovm.x		SRC(%a0),&0x80		# return +INF in fp0
   12274  1.1        is 	mov.b		&inf_bmask,FPSR_CC(%a6)	# set 'I' ccode bit
   12275  1.1        is 	rts
   12276  1.1        is 
   12277  1.1        is #########################################################################
   12278  1.1        is # XDEF ****************************************************************	#
   12279  1.1        is #	fetch_dreg(): fetch register according to index in d1		#
   12280  1.1        is #									#
   12281  1.1        is # XREF ****************************************************************	#
   12282  1.1        is #	None								#
   12283  1.1        is #									#
   12284  1.1        is # INPUT ***************************************************************	#
   12285  1.1        is #	d1 = index of register to fetch from				#
   12286  1.1        is # 									#
   12287  1.1        is # OUTPUT **************************************************************	#
   12288  1.1        is #	d0 = value of register fetched					#
   12289  1.1        is #									#
   12290  1.1        is # ALGORITHM ***********************************************************	#
   12291  1.1        is #	According to the index value in d1 which can range from zero 	#
   12292  1.1        is # to fifteen, load the corresponding register file value (where 	#
   12293  1.1        is # address register indexes start at 8). D0/D1/A0/A1/A6/A7 are on the	#
   12294  1.1        is # stack. The rest should still be in their original places.		#
   12295  1.1        is #									#
   12296  1.1        is #########################################################################
   12297  1.1        is 
   12298  1.1        is # this routine leaves d1 intact for subsequent store_dreg calls.
   12299  1.1        is 	global		fetch_dreg
   12300  1.1        is fetch_dreg:
   12301  1.1        is 	mov.w		(tbl_fdreg.b,%pc,%d1.w*2),%d0
   12302  1.1        is 	jmp		(tbl_fdreg.b,%pc,%d0.w*1)
   12303  1.1        is 
   12304  1.1        is tbl_fdreg:
   12305  1.1        is 	short		fdreg0 - tbl_fdreg
   12306  1.1        is 	short		fdreg1 - tbl_fdreg
   12307  1.1        is 	short		fdreg2 - tbl_fdreg
   12308  1.1        is 	short		fdreg3 - tbl_fdreg
   12309  1.1        is 	short		fdreg4 - tbl_fdreg
   12310  1.1        is 	short		fdreg5 - tbl_fdreg
   12311  1.1        is 	short		fdreg6 - tbl_fdreg
   12312  1.1        is 	short		fdreg7 - tbl_fdreg
   12313  1.1        is 	short		fdreg8 - tbl_fdreg
   12314  1.1        is 	short		fdreg9 - tbl_fdreg
   12315  1.1        is 	short		fdrega - tbl_fdreg
   12316  1.1        is 	short		fdregb - tbl_fdreg
   12317  1.1        is 	short		fdregc - tbl_fdreg
   12318  1.1        is 	short		fdregd - tbl_fdreg
   12319  1.1        is 	short		fdrege - tbl_fdreg
   12320  1.1        is 	short		fdregf - tbl_fdreg
   12321  1.1        is 
   12322  1.1        is fdreg0:
   12323  1.1        is 	mov.l		EXC_DREGS+0x0(%a6),%d0
   12324  1.1        is 	rts
   12325  1.1        is fdreg1:
   12326  1.1        is 	mov.l		EXC_DREGS+0x4(%a6),%d0
   12327  1.1        is 	rts
   12328  1.1        is fdreg2:
   12329  1.1        is 	mov.l		%d2,%d0
   12330  1.1        is 	rts
   12331  1.1        is fdreg3:
   12332  1.1        is 	mov.l		%d3,%d0
   12333  1.1        is 	rts
   12334  1.1        is fdreg4:
   12335  1.1        is 	mov.l		%d4,%d0
   12336  1.1        is 	rts
   12337  1.1        is fdreg5:
   12338  1.1        is 	mov.l		%d5,%d0
   12339  1.1        is 	rts
   12340  1.1        is fdreg6:
   12341  1.1        is 	mov.l		%d6,%d0
   12342  1.1        is 	rts
   12343  1.1        is fdreg7:
   12344  1.1        is 	mov.l		%d7,%d0
   12345  1.1        is 	rts
   12346  1.1        is fdreg8:
   12347  1.1        is 	mov.l		EXC_DREGS+0x8(%a6),%d0
   12348  1.1        is 	rts
   12349  1.1        is fdreg9:
   12350  1.1        is 	mov.l		EXC_DREGS+0xc(%a6),%d0
   12351  1.1        is 	rts
   12352  1.1        is fdrega:
   12353  1.1        is 	mov.l		%a2,%d0
   12354  1.1        is 	rts
   12355  1.1        is fdregb:
   12356  1.1        is 	mov.l		%a3,%d0
   12357  1.1        is 	rts
   12358  1.1        is fdregc:
   12359  1.1        is 	mov.l		%a4,%d0
   12360  1.1        is 	rts
   12361  1.1        is fdregd:
   12362  1.1        is 	mov.l		%a5,%d0
   12363  1.1        is 	rts
   12364  1.1        is fdrege:
   12365  1.1        is 	mov.l		(%a6),%d0
   12366  1.1        is 	rts
   12367  1.1        is fdregf:
   12368  1.1        is 	mov.l		EXC_A7(%a6),%d0
   12369  1.1        is 	rts
   12370  1.1        is 
   12371  1.1        is #########################################################################
   12372  1.1        is # XDEF ****************************************************************	#
   12373  1.1        is #	store_dreg_l(): store longword to data register specified by d1	#
   12374  1.1        is #									#
   12375  1.1        is # XREF ****************************************************************	#
   12376  1.1        is #	None								#
   12377  1.1        is #									#
   12378  1.1        is # INPUT ***************************************************************	#
   12379  1.1        is #	d0 = longowrd value to store					#
   12380  1.1        is #	d1 = index of register to fetch from				#
   12381  1.1        is # 									#
   12382  1.1        is # OUTPUT **************************************************************	#
   12383  1.1        is #	(data register is updated)					#
   12384  1.1        is #									#
   12385  1.1        is # ALGORITHM ***********************************************************	#
   12386  1.1        is #	According to the index value in d1, store the longword value	#
   12387  1.1        is # in d0 to the corresponding data register. D0/D1 are on the stack	#
   12388  1.1        is # while the rest are in their initial places.				#
   12389  1.1        is #									#
   12390  1.1        is #########################################################################
   12391  1.1        is 
   12392  1.1        is 	global		store_dreg_l
   12393  1.1        is store_dreg_l:
   12394  1.1        is 	mov.w		(tbl_sdregl.b,%pc,%d1.w*2),%d1
   12395  1.1        is 	jmp		(tbl_sdregl.b,%pc,%d1.w*1)
   12396  1.1        is 
   12397  1.1        is tbl_sdregl:
   12398  1.1        is 	short		sdregl0 - tbl_sdregl
   12399  1.1        is 	short		sdregl1 - tbl_sdregl
   12400  1.1        is 	short		sdregl2 - tbl_sdregl
   12401  1.1        is 	short		sdregl3 - tbl_sdregl
   12402  1.1        is 	short		sdregl4 - tbl_sdregl
   12403  1.1        is 	short		sdregl5 - tbl_sdregl
   12404  1.1        is 	short		sdregl6 - tbl_sdregl
   12405  1.1        is 	short		sdregl7 - tbl_sdregl
   12406  1.1        is 
   12407  1.1        is sdregl0:
   12408  1.1        is 	mov.l		%d0,EXC_DREGS+0x0(%a6)
   12409  1.1        is 	rts
   12410  1.1        is sdregl1:
   12411  1.1        is 	mov.l		%d0,EXC_DREGS+0x4(%a6)
   12412  1.1        is 	rts
   12413  1.1        is sdregl2:
   12414  1.1        is 	mov.l		%d0,%d2
   12415  1.1        is 	rts
   12416  1.1        is sdregl3:
   12417  1.1        is 	mov.l		%d0,%d3
   12418  1.1        is 	rts
   12419  1.1        is sdregl4:
   12420  1.1        is 	mov.l		%d0,%d4
   12421  1.1        is 	rts
   12422  1.1        is sdregl5:
   12423  1.1        is 	mov.l		%d0,%d5
   12424  1.1        is 	rts
   12425  1.1        is sdregl6:
   12426  1.1        is 	mov.l		%d0,%d6
   12427  1.1        is 	rts
   12428  1.1        is sdregl7:
   12429  1.1        is 	mov.l		%d0,%d7
   12430  1.1        is 	rts
   12431  1.1        is 
   12432  1.1        is #########################################################################
   12433  1.1        is # XDEF ****************************************************************	#
   12434  1.1        is #	store_dreg_w(): store word to data register specified by d1	#
   12435  1.1        is #									#
   12436  1.1        is # XREF ****************************************************************	#
   12437  1.1        is #	None								#
   12438  1.1        is #									#
   12439  1.1        is # INPUT ***************************************************************	#
   12440  1.1        is #	d0 = word value to store					#
   12441  1.1        is #	d1 = index of register to fetch from				#
   12442  1.1        is # 									#
   12443  1.1        is # OUTPUT **************************************************************	#
   12444  1.1        is #	(data register is updated)					#
   12445  1.1        is #									#
   12446  1.1        is # ALGORITHM ***********************************************************	#
   12447  1.1        is #	According to the index value in d1, store the word value	#
   12448  1.1        is # in d0 to the corresponding data register. D0/D1 are on the stack	#
   12449  1.1        is # while the rest are in their initial places.				#
   12450  1.1        is #									#
   12451  1.1        is #########################################################################
   12452  1.1        is 
   12453  1.1        is 	global		store_dreg_w
   12454  1.1        is store_dreg_w:
   12455  1.1        is 	mov.w		(tbl_sdregw.b,%pc,%d1.w*2),%d1
   12456  1.1        is 	jmp		(tbl_sdregw.b,%pc,%d1.w*1)
   12457  1.1        is 
   12458  1.1        is tbl_sdregw:
   12459  1.1        is 	short		sdregw0 - tbl_sdregw
   12460  1.1        is 	short		sdregw1 - tbl_sdregw
   12461  1.1        is 	short		sdregw2 - tbl_sdregw
   12462  1.1        is 	short		sdregw3 - tbl_sdregw
   12463  1.1        is 	short		sdregw4 - tbl_sdregw
   12464  1.1        is 	short		sdregw5 - tbl_sdregw
   12465  1.1        is 	short		sdregw6 - tbl_sdregw
   12466  1.1        is 	short		sdregw7 - tbl_sdregw
   12467  1.1        is 
   12468  1.1        is sdregw0:
   12469  1.1        is 	mov.w		%d0,2+EXC_DREGS+0x0(%a6)
   12470  1.1        is 	rts
   12471  1.1        is sdregw1:
   12472  1.1        is 	mov.w		%d0,2+EXC_DREGS+0x4(%a6)
   12473  1.1        is 	rts
   12474  1.1        is sdregw2:
   12475  1.1        is 	mov.w		%d0,%d2
   12476  1.1        is 	rts
   12477  1.1        is sdregw3:
   12478  1.1        is 	mov.w		%d0,%d3
   12479  1.1        is 	rts
   12480  1.1        is sdregw4:
   12481  1.1        is 	mov.w		%d0,%d4
   12482  1.1        is 	rts
   12483  1.1        is sdregw5:
   12484  1.1        is 	mov.w		%d0,%d5
   12485  1.1        is 	rts
   12486  1.1        is sdregw6:
   12487  1.1        is 	mov.w		%d0,%d6
   12488  1.1        is 	rts
   12489  1.1        is sdregw7:
   12490  1.1        is 	mov.w		%d0,%d7
   12491  1.1        is 	rts
   12492  1.1        is 
   12493  1.1        is #########################################################################
   12494  1.1        is # XDEF ****************************************************************	#
   12495  1.1        is #	store_dreg_b(): store byte to data register specified by d1	#
   12496  1.1        is #									#
   12497  1.1        is # XREF ****************************************************************	#
   12498  1.1        is #	None								#
   12499  1.1        is #									#
   12500  1.1        is # INPUT ***************************************************************	#
   12501  1.1        is #	d0 = byte value to store					#
   12502  1.1        is #	d1 = index of register to fetch from				#
   12503  1.1        is # 									#
   12504  1.1        is # OUTPUT **************************************************************	#
   12505  1.1        is #	(data register is updated)					#
   12506  1.1        is #									#
   12507  1.1        is # ALGORITHM ***********************************************************	#
   12508  1.1        is #	According to the index value in d1, store the byte value	#
   12509  1.1        is # in d0 to the corresponding data register. D0/D1 are on the stack	#
   12510  1.1        is # while the rest are in their initial places.				#
   12511  1.1        is #									#
   12512  1.1        is #########################################################################
   12513  1.1        is 
   12514  1.1        is 	global		store_dreg_b
   12515  1.1        is store_dreg_b:
   12516  1.1        is 	mov.w		(tbl_sdregb.b,%pc,%d1.w*2),%d1
   12517  1.1        is 	jmp		(tbl_sdregb.b,%pc,%d1.w*1)
   12518  1.1        is 
   12519  1.1        is tbl_sdregb:
   12520  1.1        is 	short		sdregb0 - tbl_sdregb
   12521  1.1        is 	short		sdregb1 - tbl_sdregb
   12522  1.1        is 	short		sdregb2 - tbl_sdregb
   12523  1.1        is 	short		sdregb3 - tbl_sdregb
   12524  1.1        is 	short		sdregb4 - tbl_sdregb
   12525  1.1        is 	short		sdregb5 - tbl_sdregb
   12526  1.1        is 	short		sdregb6 - tbl_sdregb
   12527  1.1        is 	short		sdregb7 - tbl_sdregb
   12528  1.1        is 
   12529  1.1        is sdregb0:
   12530  1.1        is 	mov.b		%d0,3+EXC_DREGS+0x0(%a6)
   12531  1.1        is 	rts
   12532  1.1        is sdregb1:
   12533  1.1        is 	mov.b		%d0,3+EXC_DREGS+0x4(%a6)
   12534  1.1        is 	rts
   12535  1.1        is sdregb2:
   12536  1.1        is 	mov.b		%d0,%d2
   12537  1.1        is 	rts
   12538  1.1        is sdregb3:
   12539  1.1        is 	mov.b		%d0,%d3
   12540  1.1        is 	rts
   12541  1.1        is sdregb4:
   12542  1.1        is 	mov.b		%d0,%d4
   12543  1.1        is 	rts
   12544  1.1        is sdregb5:
   12545  1.1        is 	mov.b		%d0,%d5
   12546  1.1        is 	rts
   12547  1.1        is sdregb6:
   12548  1.1        is 	mov.b		%d0,%d6
   12549  1.1        is 	rts
   12550  1.1        is sdregb7:
   12551  1.1        is 	mov.b		%d0,%d7
   12552  1.1        is 	rts
   12553  1.1        is 
   12554  1.1        is #########################################################################
   12555  1.1        is # XDEF ****************************************************************	#
   12556  1.1        is #	inc_areg(): increment an address register by the value in d0	#
   12557  1.1        is #									#
   12558  1.1        is # XREF ****************************************************************	#
   12559  1.1        is #	None								#
   12560  1.1        is #									#
   12561  1.1        is # INPUT ***************************************************************	#
   12562  1.1        is #	d0 = amount to increment by					#
   12563  1.1        is #	d1 = index of address register to increment			#
   12564  1.1        is # 									#
   12565  1.1        is # OUTPUT **************************************************************	#
   12566  1.1        is #	(address register is updated)					#
   12567  1.1        is #									#
   12568  1.1        is # ALGORITHM ***********************************************************	#
   12569  1.1        is # 	Typically used for an instruction w/ a post-increment <ea>, 	#
   12570  1.1        is # this routine adds the increment value in d0 to the address register	#
   12571  1.1        is # specified by d1. A0/A1/A6/A7 reside on the stack. The rest reside	#
   12572  1.1        is # in their original places.						#
   12573  1.1        is # 	For a7, if the increment amount is one, then we have to 	#
   12574  1.1        is # increment by two. For any a7 update, set the mia7_flag so that if	#
   12575  1.1        is # an access error exception occurs later in emulation, this address	#
   12576  1.1        is # register update can be undone.					#
   12577  1.1        is #									#
   12578  1.1        is #########################################################################
   12579  1.1        is 
   12580  1.1        is 	global		inc_areg
   12581  1.1        is inc_areg:
   12582  1.1        is 	mov.w		(tbl_iareg.b,%pc,%d1.w*2),%d1
   12583  1.1        is 	jmp		(tbl_iareg.b,%pc,%d1.w*1)
   12584  1.1        is 
   12585  1.1        is tbl_iareg:
   12586  1.1        is 	short		iareg0 - tbl_iareg
   12587  1.1        is 	short		iareg1 - tbl_iareg
   12588  1.1        is 	short		iareg2 - tbl_iareg
   12589  1.1        is 	short		iareg3 - tbl_iareg
   12590  1.1        is 	short		iareg4 - tbl_iareg
   12591  1.1        is 	short		iareg5 - tbl_iareg
   12592  1.1        is 	short		iareg6 - tbl_iareg
   12593  1.1        is 	short		iareg7 - tbl_iareg
   12594  1.1        is 
   12595  1.1        is iareg0:	add.l		%d0,EXC_DREGS+0x8(%a6)
   12596  1.1        is 	rts
   12597  1.1        is iareg1:	add.l		%d0,EXC_DREGS+0xc(%a6)
   12598  1.1        is 	rts
   12599  1.1        is iareg2:	add.l		%d0,%a2
   12600  1.1        is 	rts
   12601  1.1        is iareg3:	add.l		%d0,%a3
   12602  1.1        is 	rts
   12603  1.1        is iareg4:	add.l		%d0,%a4
   12604  1.1        is 	rts
   12605  1.1        is iareg5:	add.l		%d0,%a5
   12606  1.1        is 	rts
   12607  1.1        is iareg6:	add.l		%d0,(%a6)
   12608  1.1        is 	rts
   12609  1.1        is iareg7:	mov.b		&mia7_flg,SPCOND_FLG(%a6)
   12610  1.1        is 	cmpi.b		%d0,&0x1
   12611  1.1        is 	beq.b		iareg7b
   12612  1.1        is 	add.l		%d0,EXC_A7(%a6)
   12613  1.1        is 	rts
   12614  1.1        is iareg7b:
   12615  1.1        is 	addq.l		&0x2,EXC_A7(%a6)
   12616  1.1        is 	rts
   12617  1.1        is 
   12618  1.1        is #########################################################################
   12619  1.1        is # XDEF ****************************************************************	#
   12620  1.1        is #	dec_areg(): decrement an address register by the value in d0	#
   12621  1.1        is #									#
   12622  1.1        is # XREF ****************************************************************	#
   12623  1.1        is #	None								#
   12624  1.1        is #									#
   12625  1.1        is # INPUT ***************************************************************	#
   12626  1.1        is #	d0 = amount to decrement by					#
   12627  1.1        is #	d1 = index of address register to decrement			#
   12628  1.1        is # 									#
   12629  1.1        is # OUTPUT **************************************************************	#
   12630  1.1        is #	(address register is updated)					#
   12631  1.1        is #									#
   12632  1.1        is # ALGORITHM ***********************************************************	#
   12633  1.1        is # 	Typically used for an instruction w/ a pre-decrement <ea>, 	#
   12634  1.1        is # this routine adds the decrement value in d0 to the address register	#
   12635  1.1        is # specified by d1. A0/A1/A6/A7 reside on the stack. The rest reside	#
   12636  1.1        is # in their original places.						#
   12637  1.1        is # 	For a7, if the decrement amount is one, then we have to 	#
   12638  1.1        is # decrement by two. For any a7 update, set the mda7_flag so that if	#
   12639  1.1        is # an access error exception occurs later in emulation, this address	#
   12640  1.1        is # register update can be undone.					#
   12641  1.1        is #									#
   12642  1.1        is #########################################################################
   12643  1.1        is 
   12644  1.1        is 	global		dec_areg
   12645  1.1        is dec_areg:
   12646  1.1        is 	mov.w		(tbl_dareg.b,%pc,%d1.w*2),%d1
   12647  1.1        is 	jmp		(tbl_dareg.b,%pc,%d1.w*1)
   12648  1.1        is 
   12649  1.1        is tbl_dareg:
   12650  1.1        is 	short		dareg0 - tbl_dareg
   12651  1.1        is 	short		dareg1 - tbl_dareg
   12652  1.1        is 	short		dareg2 - tbl_dareg
   12653  1.1        is 	short		dareg3 - tbl_dareg
   12654  1.1        is 	short		dareg4 - tbl_dareg
   12655  1.1        is 	short		dareg5 - tbl_dareg
   12656  1.1        is 	short		dareg6 - tbl_dareg
   12657  1.1        is 	short		dareg7 - tbl_dareg
   12658  1.1        is 
   12659  1.1        is dareg0:	sub.l		%d0,EXC_DREGS+0x8(%a6)
   12660  1.1        is 	rts
   12661  1.1        is dareg1:	sub.l		%d0,EXC_DREGS+0xc(%a6)
   12662  1.1        is 	rts
   12663  1.1        is dareg2:	sub.l		%d0,%a2
   12664  1.1        is 	rts
   12665  1.1        is dareg3:	sub.l		%d0,%a3
   12666  1.1        is 	rts
   12667  1.1        is dareg4:	sub.l		%d0,%a4
   12668  1.1        is 	rts
   12669  1.1        is dareg5:	sub.l		%d0,%a5
   12670  1.1        is 	rts
   12671  1.1        is dareg6:	sub.l		%d0,(%a6)
   12672  1.1        is 	rts
   12673  1.1        is dareg7:	mov.b		&mda7_flg,SPCOND_FLG(%a6)
   12674  1.1        is 	cmpi.b		%d0,&0x1
   12675  1.1        is 	beq.b		dareg7b
   12676  1.1        is 	sub.l		%d0,EXC_A7(%a6)
   12677  1.1        is 	rts
   12678  1.1        is dareg7b:
   12679  1.1        is 	subq.l		&0x2,EXC_A7(%a6)
   12680  1.1        is 	rts
   12681  1.1        is 
   12682  1.1        is ##############################################################################
   12683  1.1        is 
   12684  1.1        is #########################################################################
   12685  1.1        is # XDEF ****************************************************************	#
   12686  1.1        is #	load_fpn1(): load FP register value into FP_SRC(a6).		#
   12687  1.1        is #									#
   12688  1.1        is # XREF ****************************************************************	#
   12689  1.1        is #	None								#
   12690  1.1        is #									#
   12691  1.1        is # INPUT ***************************************************************	#
   12692  1.1        is #	d0 = index of FP register to load				#
   12693  1.1        is # 									#
   12694  1.1        is # OUTPUT **************************************************************	#
   12695  1.1        is #	FP_SRC(a6) = value loaded from FP register file			#
   12696  1.1        is #									#
   12697  1.1        is # ALGORITHM ***********************************************************	#
   12698  1.1        is #	Using the index in d0, load FP_SRC(a6) with a number from the 	#
   12699  1.1        is # FP register file.							#
   12700  1.1        is #									#
   12701  1.1        is #########################################################################
   12702  1.1        is 
   12703  1.1        is 	global 		load_fpn1
   12704  1.1        is load_fpn1:
   12705  1.1        is 	mov.w		(tbl_load_fpn1.b,%pc,%d0.w*2), %d0
   12706  1.1        is 	jmp		(tbl_load_fpn1.b,%pc,%d0.w*1)
   12707  1.1        is 
   12708  1.1        is tbl_load_fpn1:
   12709  1.1        is 	short		load_fpn1_0 - tbl_load_fpn1
   12710  1.1        is 	short		load_fpn1_1 - tbl_load_fpn1
   12711  1.1        is 	short		load_fpn1_2 - tbl_load_fpn1
   12712  1.1        is 	short		load_fpn1_3 - tbl_load_fpn1
   12713  1.1        is 	short		load_fpn1_4 - tbl_load_fpn1
   12714  1.1        is 	short		load_fpn1_5 - tbl_load_fpn1
   12715  1.1        is 	short		load_fpn1_6 - tbl_load_fpn1
   12716  1.1        is 	short		load_fpn1_7 - tbl_load_fpn1
   12717  1.1        is 
   12718  1.1        is load_fpn1_0:
   12719  1.1        is 	mov.l		0+EXC_FP0(%a6), 0+FP_SRC(%a6)
   12720  1.1        is 	mov.l		4+EXC_FP0(%a6), 4+FP_SRC(%a6)
   12721  1.1        is 	mov.l		8+EXC_FP0(%a6), 8+FP_SRC(%a6)
   12722  1.1        is 	lea		FP_SRC(%a6), %a0
   12723  1.1        is 	rts
   12724  1.1        is load_fpn1_1:
   12725  1.1        is 	mov.l		0+EXC_FP1(%a6), 0+FP_SRC(%a6)
   12726  1.1        is 	mov.l		4+EXC_FP1(%a6), 4+FP_SRC(%a6)
   12727  1.1        is 	mov.l		8+EXC_FP1(%a6), 8+FP_SRC(%a6)
   12728  1.1        is 	lea		FP_SRC(%a6), %a0
   12729  1.1        is 	rts
   12730  1.1        is load_fpn1_2:
   12731  1.1        is 	fmovm.x		&0x20, FP_SRC(%a6)
   12732  1.1        is 	lea		FP_SRC(%a6), %a0
   12733  1.1        is 	rts
   12734  1.1        is load_fpn1_3:
   12735  1.1        is 	fmovm.x		&0x10, FP_SRC(%a6)
   12736  1.1        is 	lea		FP_SRC(%a6), %a0
   12737  1.1        is 	rts
   12738  1.1        is load_fpn1_4:
   12739  1.1        is 	fmovm.x		&0x08, FP_SRC(%a6)
   12740  1.1        is 	lea		FP_SRC(%a6), %a0
   12741  1.1        is 	rts
   12742  1.1        is load_fpn1_5:
   12743  1.1        is 	fmovm.x		&0x04, FP_SRC(%a6)
   12744  1.1        is 	lea		FP_SRC(%a6), %a0
   12745  1.1        is 	rts
   12746  1.1        is load_fpn1_6:
   12747  1.1        is 	fmovm.x		&0x02, FP_SRC(%a6)
   12748  1.1        is 	lea		FP_SRC(%a6), %a0
   12749  1.1        is 	rts
   12750  1.1        is load_fpn1_7:
   12751  1.1        is 	fmovm.x		&0x01, FP_SRC(%a6)
   12752  1.1        is 	lea		FP_SRC(%a6), %a0
   12753  1.1        is 	rts
   12754  1.1        is 
   12755  1.1        is #############################################################################
   12756  1.1        is 
   12757  1.1        is #########################################################################
   12758  1.1        is # XDEF ****************************************************************	#
   12759  1.1        is #	load_fpn2(): load FP register value into FP_DST(a6).		#
   12760  1.1        is #									#
   12761  1.1        is # XREF ****************************************************************	#
   12762  1.1        is #	None								#
   12763  1.1        is #									#
   12764  1.1        is # INPUT ***************************************************************	#
   12765  1.1        is #	d0 = index of FP register to load				#
   12766  1.1        is # 									#
   12767  1.1        is # OUTPUT **************************************************************	#
   12768  1.1        is #	FP_DST(a6) = value loaded from FP register file			#
   12769  1.1        is #									#
   12770  1.1        is # ALGORITHM ***********************************************************	#
   12771  1.1        is #	Using the index in d0, load FP_DST(a6) with a number from the 	#
   12772  1.1        is # FP register file.							#
   12773  1.1        is #									#
   12774  1.1        is #########################################################################
   12775  1.1        is 
   12776  1.1        is 	global		load_fpn2
   12777  1.1        is load_fpn2:
   12778  1.1        is 	mov.w		(tbl_load_fpn2.b,%pc,%d0.w*2), %d0
   12779  1.1        is 	jmp		(tbl_load_fpn2.b,%pc,%d0.w*1)
   12780  1.1        is 
   12781  1.1        is tbl_load_fpn2:
   12782  1.1        is 	short		load_fpn2_0 - tbl_load_fpn2
   12783  1.1        is 	short		load_fpn2_1 - tbl_load_fpn2
   12784  1.1        is 	short		load_fpn2_2 - tbl_load_fpn2
   12785  1.1        is 	short		load_fpn2_3 - tbl_load_fpn2
   12786  1.1        is 	short		load_fpn2_4 - tbl_load_fpn2
   12787  1.1        is 	short		load_fpn2_5 - tbl_load_fpn2
   12788  1.1        is 	short		load_fpn2_6 - tbl_load_fpn2
   12789  1.1        is 	short		load_fpn2_7 - tbl_load_fpn2
   12790  1.1        is 
   12791  1.1        is load_fpn2_0:
   12792  1.1        is 	mov.l		0+EXC_FP0(%a6), 0+FP_DST(%a6)
   12793  1.1        is 	mov.l		4+EXC_FP0(%a6), 4+FP_DST(%a6)
   12794  1.1        is 	mov.l		8+EXC_FP0(%a6), 8+FP_DST(%a6)
   12795  1.1        is 	lea		FP_DST(%a6), %a0
   12796  1.1        is 	rts
   12797  1.1        is load_fpn2_1:
   12798  1.1        is 	mov.l		0+EXC_FP1(%a6), 0+FP_DST(%a6)
   12799  1.1        is 	mov.l		4+EXC_FP1(%a6), 4+FP_DST(%a6)
   12800  1.1        is 	mov.l		8+EXC_FP1(%a6), 8+FP_DST(%a6)
   12801  1.1        is 	lea		FP_DST(%a6), %a0
   12802  1.1        is 	rts
   12803  1.1        is load_fpn2_2:
   12804  1.1        is 	fmovm.x		&0x20, FP_DST(%a6)
   12805  1.1        is 	lea		FP_DST(%a6), %a0
   12806  1.1        is 	rts
   12807  1.1        is load_fpn2_3:
   12808  1.1        is 	fmovm.x		&0x10, FP_DST(%a6)
   12809  1.1        is 	lea		FP_DST(%a6), %a0
   12810  1.1        is 	rts
   12811  1.1        is load_fpn2_4:
   12812  1.1        is 	fmovm.x		&0x08, FP_DST(%a6)
   12813  1.1        is 	lea		FP_DST(%a6), %a0
   12814  1.1        is 	rts
   12815  1.1        is load_fpn2_5:
   12816  1.1        is 	fmovm.x		&0x04, FP_DST(%a6)
   12817  1.1        is 	lea		FP_DST(%a6), %a0
   12818  1.1        is 	rts
   12819  1.1        is load_fpn2_6:
   12820  1.1        is 	fmovm.x		&0x02, FP_DST(%a6)
   12821  1.1        is 	lea		FP_DST(%a6), %a0
   12822  1.1        is 	rts
   12823  1.1        is load_fpn2_7:
   12824  1.1        is 	fmovm.x		&0x01, FP_DST(%a6)
   12825  1.1        is 	lea		FP_DST(%a6), %a0
   12826  1.1        is 	rts
   12827  1.1        is 
   12828  1.1        is #############################################################################
   12829  1.1        is 
   12830  1.1        is #########################################################################
   12831  1.1        is # XDEF ****************************************************************	#
   12832  1.1        is # 	store_fpreg(): store an fp value to the fpreg designated d0.	#
   12833  1.1        is #									#
   12834  1.1        is # XREF ****************************************************************	#
   12835  1.1        is #	None								#
   12836  1.1        is #									#
   12837  1.1        is # INPUT ***************************************************************	#
   12838  1.1        is #	fp0 = extended precision value to store				#
   12839  1.1        is #	d0  = index of floating-point register				#
   12840  1.1        is # 									#
   12841  1.1        is # OUTPUT **************************************************************	#
   12842  1.1        is #	None								#
   12843  1.1        is #									#
   12844  1.1        is # ALGORITHM ***********************************************************	#
   12845  1.1        is #	Store the value in fp0 to the FP register designated by the	#
   12846  1.1        is # value in d0. The FP number can be DENORM or SNAN so we have to be	#
   12847  1.1        is # careful that we don't take an exception here.				#
   12848  1.1        is #									#
   12849  1.1        is #########################################################################
   12850  1.1        is 
   12851  1.1        is 	global		store_fpreg
   12852  1.1        is store_fpreg:
   12853  1.1        is 	mov.w		(tbl_store_fpreg.b,%pc,%d0.w*2), %d0
   12854  1.1        is 	jmp		(tbl_store_fpreg.b,%pc,%d0.w*1)
   12855  1.1        is 
   12856  1.1        is tbl_store_fpreg:
   12857  1.1        is 	short		store_fpreg_0 - tbl_store_fpreg
   12858  1.1        is 	short		store_fpreg_1 - tbl_store_fpreg
   12859  1.1        is 	short		store_fpreg_2 - tbl_store_fpreg
   12860  1.1        is 	short		store_fpreg_3 - tbl_store_fpreg
   12861  1.1        is 	short		store_fpreg_4 - tbl_store_fpreg
   12862  1.1        is 	short		store_fpreg_5 - tbl_store_fpreg
   12863  1.1        is 	short		store_fpreg_6 - tbl_store_fpreg
   12864  1.1        is 	short		store_fpreg_7 - tbl_store_fpreg
   12865  1.1        is 
   12866  1.1        is store_fpreg_0:
   12867  1.1        is 	fmovm.x		&0x80, EXC_FP0(%a6)
   12868  1.1        is 	rts
   12869  1.1        is store_fpreg_1:
   12870  1.1        is 	fmovm.x		&0x80, EXC_FP1(%a6)
   12871  1.1        is 	rts
   12872  1.1        is store_fpreg_2:
   12873  1.1        is 	fmovm.x 	&0x01, -(%sp)
   12874  1.1        is 	fmovm.x		(%sp)+, &0x20
   12875  1.1        is 	rts
   12876  1.1        is store_fpreg_3:
   12877  1.1        is 	fmovm.x 	&0x01, -(%sp)
   12878  1.1        is 	fmovm.x		(%sp)+, &0x10
   12879  1.1        is 	rts
   12880  1.1        is store_fpreg_4:
   12881  1.1        is 	fmovm.x 	&0x01, -(%sp)
   12882  1.1        is 	fmovm.x		(%sp)+, &0x08
   12883  1.1        is 	rts
   12884  1.1        is store_fpreg_5:
   12885  1.1        is 	fmovm.x 	&0x01, -(%sp)
   12886  1.1        is 	fmovm.x		(%sp)+, &0x04
   12887  1.1        is 	rts
   12888  1.1        is store_fpreg_6:
   12889  1.1        is 	fmovm.x 	&0x01, -(%sp)
   12890  1.1        is 	fmovm.x		(%sp)+, &0x02
   12891  1.1        is 	rts
   12892  1.1        is store_fpreg_7:
   12893  1.1        is 	fmovm.x 	&0x01, -(%sp)
   12894  1.1        is 	fmovm.x		(%sp)+, &0x01
   12895  1.1        is 	rts
   12896  1.1        is 
   12897  1.1        is #########################################################################
   12898  1.1        is # XDEF ****************************************************************	#
   12899  1.1        is #	get_packed(): fetch a packed operand from memory and then	#
   12900  1.1        is #		      convert it to a floating-point binary number.	#
   12901  1.1        is #									#
   12902  1.1        is # XREF ****************************************************************	#
   12903  1.1        is #	_dcalc_ea() - calculate the correct <ea>			#
   12904  1.1        is #	_mem_read() - fetch the packed operand from memory		#
   12905  1.1        is #	facc_in_x() - the fetch failed so jump to special exit code	#
   12906  1.1        is #	decbin()    - convert packed to binary extended precision	#
   12907  1.1        is #									#
   12908  1.1        is # INPUT ***************************************************************	#
   12909  1.1        is #	None								#
   12910  1.1        is # 									#
   12911  1.1        is # OUTPUT **************************************************************	#
   12912  1.1        is #	If no failure on _mem_read():					#
   12913  1.1        is # 	FP_SRC(a6) = packed operand now as a binary FP number		#
   12914  1.1        is #									#
   12915  1.1        is # ALGORITHM ***********************************************************	#
   12916  1.1        is #	Get the correct <ea> whihc is the value on the exception stack 	#
   12917  1.1        is # frame w/ maybe a correction factor if the <ea> is -(an) or (an)+.	#
   12918  1.1        is # Then, fetch the operand from memory. If the fetch fails, exit		#
   12919  1.1        is # through facc_in_x().							#
   12920  1.1        is #	If the packed operand is a ZERO,NAN, or INF, convert it to	#
   12921  1.1        is # its binary representation here. Else, call decbin() which will 	#
   12922  1.1        is # convert the packed value to an extended precision binary value.	#
   12923  1.1        is #									#
   12924  1.1        is #########################################################################
   12925  1.1        is 
   12926  1.1        is # the stacked <ea> for packed is correct except for -(An).
   12927  1.1        is # the base reg must be updated for both -(An) and (An)+.
   12928  1.1        is 	global		get_packed
   12929  1.1        is get_packed:
   12930  1.1        is 	mov.l		&0xc,%d0		# packed is 12 bytes
   12931  1.1        is 	bsr.l		_dcalc_ea		# fetch <ea>; correct An
   12932  1.1        is 
   12933  1.1        is 	lea		FP_SRC(%a6),%a1		# pass: ptr to super dst
   12934  1.1        is 	mov.l		&0xc,%d0		# pass: 12 bytes
   12935  1.1        is 	bsr.l		_dmem_read		# read packed operand
   12936  1.1        is 
   12937  1.1        is 	tst.l		%d1			# did dfetch fail?
   12938  1.1        is 	bne.l		facc_in_x		# yes
   12939  1.1        is 
   12940  1.1        is # The packed operand is an INF or a NAN if the exponent field is all ones.
   12941  1.1        is 	bfextu		FP_SRC(%a6){&1:&15},%d0	# get exp
   12942  1.1        is 	cmpi.w		%d0,&0x7fff		# INF or NAN?
   12943  1.1        is 	bne.b		gp_try_zero		# no
   12944  1.1        is 	rts					# operand is an INF or NAN
   12945  1.1        is 
   12946  1.1        is # The packed operand is a zero if the mantissa is all zero, else it's
   12947  1.1        is # a normal packed op.
   12948  1.1        is gp_try_zero:
   12949  1.1        is 	mov.b		3+FP_SRC(%a6),%d0	# get byte 4
   12950  1.1        is 	andi.b		&0x0f,%d0		# clear all but last nybble
   12951  1.1        is 	bne.b		gp_not_spec		# not a zero
   12952  1.1        is 	tst.l		FP_SRC_HI(%a6)		# is lw 2 zero?
   12953  1.1        is 	bne.b		gp_not_spec		# not a zero
   12954  1.1        is 	tst.l		FP_SRC_LO(%a6)		# is lw 3 zero?
   12955  1.1        is 	bne.b		gp_not_spec		# not a zero
   12956  1.1        is 	rts					# operand is a ZERO
   12957  1.1        is gp_not_spec:
   12958  1.1        is 	lea		FP_SRC(%a6),%a0		# pass: ptr to packed op
   12959  1.1        is 	bsr.l		decbin			# convert to extended
   12960  1.1        is 	fmovm.x		&0x80,FP_SRC(%a6)	# make this the srcop
   12961  1.1        is 	rts
   12962  1.1        is 
   12963  1.1        is #########################################################################
   12964  1.1        is # decbin(): Converts normalized packed bcd value pointed to by register	#
   12965  1.1        is #	    a0 to extended-precision value in fp0.			#
   12966  1.1        is #									#
   12967  1.1        is # INPUT ***************************************************************	#
   12968  1.1        is #	a0 = pointer to normalized packed bcd value			#
   12969  1.1        is #									#
   12970  1.1        is # OUTPUT **************************************************************	#
   12971  1.1        is #	fp0 = exact fp representation of the packed bcd value.		#
   12972  1.1        is #									#
   12973  1.1        is # ALGORITHM ***********************************************************	#
   12974  1.1        is #	Expected is a normal bcd (i.e. non-exceptional; all inf, zero,	#
   12975  1.1        is #	and NaN operands are dispatched without entering this routine)	#
   12976  1.1        is #	value in 68881/882 format at location (a0).			#
   12977  1.1        is #									#
   12978  1.1        is #	A1. Convert the bcd exponent to binary by successive adds and 	#
   12979  1.1        is #	muls. Set the sign according to SE. Subtract 16 to compensate	#
   12980  1.1        is #	for the mantissa which is to be interpreted as 17 integer	#
   12981  1.1        is #	digits, rather than 1 integer and 16 fraction digits.		#
   12982  1.1        is #	Note: this operation can never overflow.			#
   12983  1.1        is #									#
   12984  1.1        is #	A2. Convert the bcd mantissa to binary by successive		#
   12985  1.1        is #	adds and muls in FP0. Set the sign according to SM.		#
   12986  1.1        is #	The mantissa digits will be converted with the decimal point	#
   12987  1.1        is #	assumed following the least-significant digit.			#
   12988  1.1        is #	Note: this operation can never overflow.			#
   12989  1.1        is #									#
   12990  1.1        is #	A3. Count the number of leading/trailing zeros in the		#
   12991  1.1        is #	bcd string.  If SE is positive, count the leading zeros;	#
   12992  1.1        is #	if negative, count the trailing zeros.  Set the adjusted	#
   12993  1.1        is #	exponent equal to the exponent from A1 and the zero count	#
   12994  1.1        is #	added if SM = 1 and subtracted if SM = 0.  Scale the		#
   12995  1.1        is #	mantissa the equivalent of forcing in the bcd value:		#
   12996  1.1        is #									#
   12997  1.1        is #	SM = 0	a non-zero digit in the integer position		#
   12998  1.1        is #	SM = 1	a non-zero digit in Mant0, lsd of the fraction		#
   12999  1.1        is #									#
   13000  1.1        is #	this will insure that any value, regardless of its		#
   13001  1.1        is #	representation (ex. 0.1E2, 1E1, 10E0, 100E-1), is converted	#
   13002  1.1        is #	consistently.							#
   13003  1.1        is #									#
   13004  1.1        is #	A4. Calculate the factor 10^exp in FP1 using a table of		#
   13005  1.1        is #	10^(2^n) values.  To reduce the error in forming factors	#
   13006  1.1        is #	greater than 10^27, a directed rounding scheme is used with	#
   13007  1.1        is #	tables rounded to RN, RM, and RP, according to the table	#
   13008  1.1        is #	in the comments of the pwrten section.				#
   13009  1.1        is #									#
   13010  1.1        is #	A5. Form the final binary number by scaling the mantissa by	#
   13011  1.1        is #	the exponent factor.  This is done by multiplying the		#
   13012  1.1        is #	mantissa in FP0 by the factor in FP1 if the adjusted		#
   13013  1.1        is #	exponent sign is positive, and dividing FP0 by FP1 if		#
   13014  1.1        is #	it is negative.							#
   13015  1.1        is #									#
   13016  1.1        is #	Clean up and return. Check if the final mul or div was inexact.	#
   13017  1.1        is #	If so, set INEX1 in USER_FPSR.					#
   13018  1.1        is #									#
   13019  1.1        is #########################################################################
   13020  1.1        is 
   13021  1.1        is #
   13022  1.1        is #	PTENRN, PTENRM, and PTENRP are arrays of powers of 10 rounded
   13023  1.1        is #	to nearest, minus, and plus, respectively.  The tables include
   13024  1.1        is #	10**{1,2,4,8,16,32,64,128,256,512,1024,2048,4096}.  No rounding
   13025  1.1        is #	is required until the power is greater than 27, however, all
   13026  1.1        is #	tables include the first 5 for ease of indexing.
   13027  1.1        is #
   13028  1.1        is RTABLE:
   13029  1.1        is 	byte		0,0,0,0
   13030  1.1        is 	byte		2,3,2,3
   13031  1.1        is 	byte		2,3,3,2
   13032  1.1        is 	byte		3,2,2,3
   13033  1.1        is 
   13034  1.1        is 	set		FNIBS,7
   13035  1.1        is 	set		FSTRT,0
   13036  1.1        is 
   13037  1.1        is 	set		ESTRT,4
   13038  1.1        is 	set		EDIGITS,2
   13039  1.1        is 
   13040  1.1        is 	global		decbin
   13041  1.1        is decbin:
   13042  1.1        is 	mov.l		0x0(%a0),FP_SCR0_EX(%a6) # make a copy of input
   13043  1.1        is 	mov.l		0x4(%a0),FP_SCR0_HI(%a6) # so we don't alter it
   13044  1.1        is 	mov.l		0x8(%a0),FP_SCR0_LO(%a6)
   13045  1.1        is 
   13046  1.1        is 	lea		FP_SCR0(%a6),%a0
   13047  1.1        is 
   13048  1.1        is 	movm.l		&0x3c00,-(%sp)		# save d2-d5
   13049  1.1        is 	fmovm.x		&0x1,-(%sp)		# save fp1
   13050  1.1        is #
   13051  1.1        is # Calculate exponent:
   13052  1.1        is #  1. Copy bcd value in memory for use as a working copy.
   13053  1.1        is #  2. Calculate absolute value of exponent in d1 by mul and add.
   13054  1.1        is #  3. Correct for exponent sign.
   13055  1.1        is #  4. Subtract 16 to compensate for interpreting the mant as all integer digits.
   13056  1.1        is #     (i.e., all digits assumed left of the decimal point.)
   13057  1.1        is #
   13058  1.1        is # Register usage:
   13059  1.1        is #
   13060  1.1        is #  calc_e:
   13061  1.1        is #	(*)  d0: temp digit storage
   13062  1.1        is #	(*)  d1: accumulator for binary exponent
   13063  1.1        is #	(*)  d2: digit count
   13064  1.1        is #	(*)  d3: offset pointer
   13065  1.1        is #	( )  d4: first word of bcd
   13066  1.1        is #	( )  a0: pointer to working bcd value
   13067  1.1        is #	( )  a6: pointer to original bcd value
   13068  1.1        is #	(*)  FP_SCR1: working copy of original bcd value
   13069  1.1        is #	(*)  L_SCR1: copy of original exponent word
   13070  1.1        is #
   13071  1.1        is calc_e:
   13072  1.1        is 	mov.l		&EDIGITS,%d2		# # of nibbles (digits) in fraction part
   13073  1.1        is 	mov.l		&ESTRT,%d3		# counter to pick up digits
   13074  1.1        is 	mov.l		(%a0),%d4		# get first word of bcd
   13075  1.1        is 	clr.l		%d1			# zero d1 for accumulator
   13076  1.1        is e_gd:
   13077  1.1        is 	mulu.l		&0xa,%d1		# mul partial product by one digit place
   13078  1.1        is 	bfextu		%d4{%d3:&4},%d0		# get the digit and zero extend into d0
   13079  1.1        is 	add.l		%d0,%d1			# d1 = d1 + d0
   13080  1.1        is 	addq.b		&4,%d3			# advance d3 to the next digit
   13081  1.1        is 	dbf.w		%d2,e_gd		# if we have used all 3 digits, exit loop
   13082  1.1        is 	btst		&30,%d4			# get SE
   13083  1.1        is 	beq.b		e_pos			# don't negate if pos
   13084  1.1        is 	neg.l		%d1			# negate before subtracting
   13085  1.1        is e_pos:
   13086  1.1        is 	sub.l		&16,%d1			# sub to compensate for shift of mant
   13087  1.1        is 	bge.b		e_save			# if still pos, do not neg
   13088  1.1        is 	neg.l		%d1			# now negative, make pos and set SE
   13089  1.1        is 	or.l		&0x40000000,%d4		# set SE in d4,
   13090  1.1        is 	or.l		&0x40000000,(%a0)	# and in working bcd
   13091  1.1        is e_save:
   13092  1.1        is 	mov.l		%d1,-(%sp)		# save exp on stack
   13093  1.1        is #
   13094  1.1        is #
   13095  1.1        is # Calculate mantissa:
   13096  1.1        is #  1. Calculate absolute value of mantissa in fp0 by mul and add.
   13097  1.1        is #  2. Correct for mantissa sign.
   13098  1.1        is #     (i.e., all digits assumed left of the decimal point.)
   13099  1.1        is #
   13100  1.1        is # Register usage:
   13101  1.1        is #
   13102  1.1        is #  calc_m:
   13103  1.1        is #	(*)  d0: temp digit storage
   13104  1.1        is #	(*)  d1: lword counter
   13105  1.1        is #	(*)  d2: digit count
   13106  1.1        is #	(*)  d3: offset pointer
   13107  1.1        is #	( )  d4: words 2 and 3 of bcd
   13108  1.1        is #	( )  a0: pointer to working bcd value
   13109  1.1        is #	( )  a6: pointer to original bcd value
   13110  1.1        is #	(*) fp0: mantissa accumulator
   13111  1.1        is #	( )  FP_SCR1: working copy of original bcd value
   13112  1.1        is #	( )  L_SCR1: copy of original exponent word
   13113  1.1        is #
   13114  1.1        is calc_m:
   13115  1.1        is 	mov.l		&1,%d1			# word counter, init to 1
   13116  1.1        is 	fmov.s		&0x00000000,%fp0	# accumulator
   13117  1.1        is #
   13118  1.1        is #
   13119  1.1        is #  Since the packed number has a long word between the first & second parts,
   13120  1.1        is #  get the integer digit then skip down & get the rest of the
   13121  1.1        is #  mantissa.  We will unroll the loop once.
   13122  1.1        is #
   13123  1.1        is 	bfextu		(%a0){&28:&4},%d0	# integer part is ls digit in long word
   13124  1.1        is 	fadd.b		%d0,%fp0		# add digit to sum in fp0
   13125  1.1        is #
   13126  1.1        is #
   13127  1.1        is #  Get the rest of the mantissa.
   13128  1.1        is #
   13129  1.1        is loadlw:
   13130  1.1        is 	mov.l		(%a0,%d1.L*4),%d4	# load mantissa lonqword into d4
   13131  1.1        is 	mov.l		&FSTRT,%d3		# counter to pick up digits
   13132  1.1        is 	mov.l		&FNIBS,%d2		# reset number of digits per a0 ptr
   13133  1.1        is md2b:
   13134  1.1        is 	fmul.s		&0x41200000,%fp0	# fp0 = fp0 * 10
   13135  1.1        is 	bfextu		%d4{%d3:&4},%d0		# get the digit and zero extend
   13136  1.1        is 	fadd.b		%d0,%fp0		# fp0 = fp0 + digit
   13137  1.1        is #
   13138  1.1        is #
   13139  1.1        is #  If all the digits (8) in that long word have been converted (d2=0),
   13140  1.1        is #  then inc d1 (=2) to point to the next long word and reset d3 to 0
   13141  1.1        is #  to initialize the digit offset, and set d2 to 7 for the digit count;
   13142  1.1        is #  else continue with this long word.
   13143  1.1        is #
   13144  1.1        is 	addq.b		&4,%d3			# advance d3 to the next digit
   13145  1.1        is 	dbf.w		%d2,md2b		# check for last digit in this lw
   13146  1.1        is nextlw:
   13147  1.1        is 	addq.l		&1,%d1			# inc lw pointer in mantissa
   13148  1.1        is 	cmp.l		%d1,&2			# test for last lw
   13149  1.1        is 	ble.b		loadlw			# if not, get last one
   13150  1.1        is #
   13151  1.1        is #  Check the sign of the mant and make the value in fp0 the same sign.
   13152  1.1        is #
   13153  1.1        is m_sign:
   13154  1.1        is 	btst		&31,(%a0)		# test sign of the mantissa
   13155  1.1        is 	beq.b		ap_st_z			# if clear, go to append/strip zeros
   13156  1.1        is 	fneg.x		%fp0			# if set, negate fp0
   13157  1.1        is #
   13158  1.1        is # Append/strip zeros:
   13159  1.1        is #
   13160  1.1        is #  For adjusted exponents which have an absolute value greater than 27*,
   13161  1.1        is #  this routine calculates the amount needed to normalize the mantissa
   13162  1.1        is #  for the adjusted exponent.  That number is subtracted from the exp
   13163  1.1        is #  if the exp was positive, and added if it was negative.  The purpose
   13164  1.1        is #  of this is to reduce the value of the exponent and the possibility
   13165  1.1        is #  of error in calculation of pwrten.
   13166  1.1        is #
   13167  1.1        is #  1. Branch on the sign of the adjusted exponent.
   13168  1.1        is #  2p.(positive exp)
   13169  1.1        is #   2. Check M16 and the digits in lwords 2 and 3 in decending order.
   13170  1.1        is #   3. Add one for each zero encountered until a non-zero digit.
   13171  1.1        is #   4. Subtract the count from the exp.
   13172  1.1        is #   5. Check if the exp has crossed zero in #3 above; make the exp abs
   13173  1.1        is #	   and set SE.
   13174  1.1        is #	6. Multiply the mantissa by 10**count.
   13175  1.1        is #  2n.(negative exp)
   13176  1.1        is #   2. Check the digits in lwords 3 and 2 in decending order.
   13177  1.1        is #   3. Add one for each zero encountered until a non-zero digit.
   13178  1.1        is #   4. Add the count to the exp.
   13179  1.1        is #   5. Check if the exp has crossed zero in #3 above; clear SE.
   13180  1.1        is #   6. Divide the mantissa by 10**count.
   13181  1.1        is #
   13182  1.1        is #  *Why 27?  If the adjusted exponent is within -28 < expA < 28, than
   13183  1.1        is #   any adjustment due to append/strip zeros will drive the resultane
   13184  1.1        is #   exponent towards zero.  Since all pwrten constants with a power
   13185  1.1        is #   of 27 or less are exact, there is no need to use this routine to
   13186  1.1        is #   attempt to lessen the resultant exponent.
   13187  1.1        is #
   13188  1.1        is # Register usage:
   13189  1.1        is #
   13190  1.1        is #  ap_st_z:
   13191  1.1        is #	(*)  d0: temp digit storage
   13192  1.1        is #	(*)  d1: zero count
   13193  1.1        is #	(*)  d2: digit count
   13194  1.1        is #	(*)  d3: offset pointer
   13195  1.1        is #	( )  d4: first word of bcd
   13196  1.1        is #	(*)  d5: lword counter
   13197  1.1        is #	( )  a0: pointer to working bcd value
   13198  1.1        is #	( )  FP_SCR1: working copy of original bcd value
   13199  1.1        is #	( )  L_SCR1: copy of original exponent word
   13200  1.1        is #
   13201  1.1        is #
   13202  1.1        is # First check the absolute value of the exponent to see if this
   13203  1.1        is # routine is necessary.  If so, then check the sign of the exponent
   13204  1.1        is # and do append (+) or strip (-) zeros accordingly.
   13205  1.1        is # This section handles a positive adjusted exponent.
   13206  1.1        is #
   13207  1.1        is ap_st_z:
   13208  1.1        is 	mov.l		(%sp),%d1		# load expA for range test
   13209  1.1        is 	cmp.l		%d1,&27			# test is with 27
   13210  1.1        is 	ble.w		pwrten			# if abs(expA) <28, skip ap/st zeros
   13211  1.1        is 	btst		&30,(%a0)		# check sign of exp
   13212  1.1        is 	bne.b		ap_st_n			# if neg, go to neg side
   13213  1.1        is 	clr.l		%d1			# zero count reg
   13214  1.1        is 	mov.l		(%a0),%d4		# load lword 1 to d4
   13215  1.1        is 	bfextu		%d4{&28:&4},%d0		# get M16 in d0
   13216  1.1        is 	bne.b		ap_p_fx			# if M16 is non-zero, go fix exp
   13217  1.1        is 	addq.l		&1,%d1			# inc zero count
   13218  1.1        is 	mov.l		&1,%d5			# init lword counter
   13219  1.1        is 	mov.l		(%a0,%d5.L*4),%d4	# get lword 2 to d4
   13220  1.1        is 	bne.b		ap_p_cl			# if lw 2 is zero, skip it
   13221  1.1        is 	addq.l		&8,%d1			# and inc count by 8
   13222  1.1        is 	addq.l		&1,%d5			# inc lword counter
   13223  1.1        is 	mov.l		(%a0,%d5.L*4),%d4	# get lword 3 to d4
   13224  1.1        is ap_p_cl:
   13225  1.1        is 	clr.l		%d3			# init offset reg
   13226  1.1        is 	mov.l		&7,%d2			# init digit counter
   13227  1.1        is ap_p_gd:
   13228  1.1        is 	bfextu		%d4{%d3:&4},%d0		# get digit
   13229  1.1        is 	bne.b		ap_p_fx			# if non-zero, go to fix exp
   13230  1.1        is 	addq.l		&4,%d3			# point to next digit
   13231  1.1        is 	addq.l		&1,%d1			# inc digit counter
   13232  1.1        is 	dbf.w		%d2,ap_p_gd		# get next digit
   13233  1.1        is ap_p_fx:
   13234  1.1        is 	mov.l		%d1,%d0			# copy counter to d2
   13235  1.1        is 	mov.l		(%sp),%d1		# get adjusted exp from memory
   13236  1.1        is 	sub.l		%d0,%d1			# subtract count from exp
   13237  1.1        is 	bge.b		ap_p_fm			# if still pos, go to pwrten
   13238  1.1        is 	neg.l		%d1			# now its neg; get abs
   13239  1.1        is 	mov.l		(%a0),%d4		# load lword 1 to d4
   13240  1.1        is 	or.l		&0x40000000,%d4		# and set SE in d4
   13241  1.1        is 	or.l		&0x40000000,(%a0)	# and in memory
   13242  1.1        is #
   13243  1.1        is # Calculate the mantissa multiplier to compensate for the striping of
   13244  1.1        is # zeros from the mantissa.
   13245  1.1        is #
   13246  1.1        is ap_p_fm:
   13247  1.1        is 	lea.l		PTENRN(%pc),%a1		# get address of power-of-ten table
   13248  1.1        is 	clr.l		%d3			# init table index
   13249  1.1        is 	fmov.s		&0x3f800000,%fp1	# init fp1 to 1
   13250  1.1        is 	mov.l		&3,%d2			# init d2 to count bits in counter
   13251  1.1        is ap_p_el:
   13252  1.1        is 	asr.l		&1,%d0			# shift lsb into carry
   13253  1.1        is 	bcc.b		ap_p_en			# if 1, mul fp1 by pwrten factor
   13254  1.1        is 	fmul.x		(%a1,%d3),%fp1		# mul by 10**(d3_bit_no)
   13255  1.1        is ap_p_en:
   13256  1.1        is 	add.l		&12,%d3			# inc d3 to next rtable entry
   13257  1.1        is 	tst.l		%d0			# check if d0 is zero
   13258  1.1        is 	bne.b		ap_p_el			# if not, get next bit
   13259  1.1        is 	fmul.x		%fp1,%fp0		# mul mantissa by 10**(no_bits_shifted)
   13260  1.1        is 	bra.b		pwrten			# go calc pwrten
   13261  1.1        is #
   13262  1.1        is # This section handles a negative adjusted exponent.
   13263  1.1        is #
   13264  1.1        is ap_st_n:
   13265  1.1        is 	clr.l		%d1			# clr counter
   13266  1.1        is 	mov.l		&2,%d5			# set up d5 to point to lword 3
   13267  1.1        is 	mov.l		(%a0,%d5.L*4),%d4	# get lword 3
   13268  1.1        is 	bne.b		ap_n_cl			# if not zero, check digits
   13269  1.1        is 	sub.l		&1,%d5			# dec d5 to point to lword 2
   13270  1.1        is 	addq.l		&8,%d1			# inc counter by 8
   13271  1.1        is 	mov.l		(%a0,%d5.L*4),%d4	# get lword 2
   13272  1.1        is ap_n_cl:
   13273  1.1        is 	mov.l		&28,%d3			# point to last digit
   13274  1.1        is 	mov.l		&7,%d2			# init digit counter
   13275  1.1        is ap_n_gd:
   13276  1.1        is 	bfextu		%d4{%d3:&4},%d0		# get digit
   13277  1.1        is 	bne.b		ap_n_fx			# if non-zero, go to exp fix
   13278  1.1        is 	subq.l		&4,%d3			# point to previous digit
   13279  1.1        is 	addq.l		&1,%d1			# inc digit counter
   13280  1.1        is 	dbf.w		%d2,ap_n_gd		# get next digit
   13281  1.1        is ap_n_fx:
   13282  1.1        is 	mov.l		%d1,%d0			# copy counter to d0
   13283  1.1        is 	mov.l		(%sp),%d1		# get adjusted exp from memory
   13284  1.1        is 	sub.l		%d0,%d1			# subtract count from exp
   13285  1.1        is 	bgt.b		ap_n_fm			# if still pos, go fix mantissa
   13286  1.1        is 	neg.l		%d1			# take abs of exp and clr SE
   13287  1.1        is 	mov.l		(%a0),%d4		# load lword 1 to d4
   13288  1.1        is 	and.l		&0xbfffffff,%d4		# and clr SE in d4
   13289  1.1        is 	and.l		&0xbfffffff,(%a0)	# and in memory
   13290  1.1        is #
   13291  1.1        is # Calculate the mantissa multiplier to compensate for the appending of
   13292  1.1        is # zeros to the mantissa.
   13293  1.1        is #
   13294  1.1        is ap_n_fm:
   13295  1.1        is 	lea.l		PTENRN(%pc),%a1		# get address of power-of-ten table
   13296  1.1        is 	clr.l		%d3			# init table index
   13297  1.1        is 	fmov.s		&0x3f800000,%fp1	# init fp1 to 1
   13298  1.1        is 	mov.l		&3,%d2			# init d2 to count bits in counter
   13299  1.1        is ap_n_el:
   13300  1.1        is 	asr.l		&1,%d0			# shift lsb into carry
   13301  1.1        is 	bcc.b		ap_n_en			# if 1, mul fp1 by pwrten factor
   13302  1.1        is 	fmul.x		(%a1,%d3),%fp1		# mul by 10**(d3_bit_no)
   13303  1.1        is ap_n_en:
   13304  1.1        is 	add.l		&12,%d3			# inc d3 to next rtable entry
   13305  1.1        is 	tst.l		%d0			# check if d0 is zero
   13306  1.1        is 	bne.b		ap_n_el			# if not, get next bit
   13307  1.1        is 	fdiv.x		%fp1,%fp0		# div mantissa by 10**(no_bits_shifted)
   13308  1.1        is #
   13309  1.1        is #
   13310  1.1        is # Calculate power-of-ten factor from adjusted and shifted exponent.
   13311  1.1        is #
   13312  1.1        is # Register usage:
   13313  1.1        is #
   13314  1.1        is #  pwrten:
   13315  1.1        is #	(*)  d0: temp
   13316  1.1        is #	( )  d1: exponent
   13317  1.1        is #	(*)  d2: {FPCR[6:5],SM,SE} as index in RTABLE; temp
   13318  1.1        is #	(*)  d3: FPCR work copy
   13319  1.1        is #	( )  d4: first word of bcd
   13320  1.1        is #	(*)  a1: RTABLE pointer
   13321  1.1        is #  calc_p:
   13322  1.1        is #	(*)  d0: temp
   13323  1.1        is #	( )  d1: exponent
   13324  1.1        is #	(*)  d3: PWRTxx table index
   13325  1.1        is #	( )  a0: pointer to working copy of bcd
   13326  1.1        is #	(*)  a1: PWRTxx pointer
   13327  1.1        is #	(*) fp1: power-of-ten accumulator
   13328  1.1        is #
   13329  1.1        is # Pwrten calculates the exponent factor in the selected rounding mode
   13330  1.1        is # according to the following table:
   13331  1.1        is #
   13332  1.1        is #	Sign of Mant  Sign of Exp  Rounding Mode  PWRTEN Rounding Mode
   13333  1.1        is #
   13334  1.1        is #	ANY	  ANY	RN	RN
   13335  1.1        is #
   13336  1.1        is #	 +	   +	RP	RP
   13337  1.1        is #	 -	   +	RP	RM
   13338  1.1        is #	 +	   -	RP	RM
   13339  1.1        is #	 -	   -	RP	RP
   13340  1.1        is #
   13341  1.1        is #	 +	   +	RM	RM
   13342  1.1        is #	 -	   +	RM	RP
   13343  1.1        is #	 +	   -	RM	RP
   13344  1.1        is #	 -	   -	RM	RM
   13345  1.1        is #
   13346  1.1        is #	 +	   +	RZ	RM
   13347  1.1        is #	 -	   +	RZ	RM
   13348  1.1        is #	 +	   -	RZ	RP
   13349  1.1        is #	 -	   -	RZ	RP
   13350  1.1        is #
   13351  1.1        is #
   13352  1.1        is pwrten:
   13353  1.1        is 	mov.l		USER_FPCR(%a6),%d3	# get user's FPCR
   13354  1.1        is 	bfextu		%d3{&26:&2},%d2		# isolate rounding mode bits
   13355  1.1        is 	mov.l		(%a0),%d4		# reload 1st bcd word to d4
   13356  1.1        is 	asl.l		&2,%d2			# format d2 to be
   13357  1.1        is 	bfextu		%d4{&0:&2},%d0		# {FPCR[6],FPCR[5],SM,SE}
   13358  1.1        is 	add.l		%d0,%d2			# in d2 as index into RTABLE
   13359  1.1        is 	lea.l		RTABLE(%pc),%a1		# load rtable base
   13360  1.1        is 	mov.b		(%a1,%d2),%d0		# load new rounding bits from table
   13361  1.1        is 	clr.l		%d3			# clear d3 to force no exc and extended
   13362  1.1        is 	bfins		%d0,%d3{&26:&2}		# stuff new rounding bits in FPCR
   13363  1.1        is 	fmov.l		%d3,%fpcr		# write new FPCR
   13364  1.1        is 	asr.l		&1,%d0			# write correct PTENxx table
   13365  1.1        is 	bcc.b		not_rp			# to a1
   13366  1.1        is 	lea.l		PTENRP(%pc),%a1		# it is RP
   13367  1.1        is 	bra.b		calc_p			# go to init section
   13368  1.1        is not_rp:
   13369  1.1        is 	asr.l		&1,%d0			# keep checking
   13370  1.1        is 	bcc.b		not_rm
   13371  1.1        is 	lea.l		PTENRM(%pc),%a1		# it is RM
   13372  1.1        is 	bra.b		calc_p			# go to init section
   13373  1.1        is not_rm:
   13374  1.1        is 	lea.l		PTENRN(%pc),%a1		# it is RN
   13375  1.1        is calc_p:
   13376  1.1        is 	mov.l		%d1,%d0			# copy exp to d0;use d0
   13377  1.1        is 	bpl.b		no_neg			# if exp is negative,
   13378  1.1        is 	neg.l		%d0			# invert it
   13379  1.1        is 	or.l		&0x40000000,(%a0)	# and set SE bit
   13380  1.1        is no_neg:
   13381  1.1        is 	clr.l		%d3			# table index
   13382  1.1        is 	fmov.s		&0x3f800000,%fp1	# init fp1 to 1
   13383  1.1        is e_loop:
   13384  1.1        is 	asr.l		&1,%d0			# shift next bit into carry
   13385  1.1        is 	bcc.b		e_next			# if zero, skip the mul
   13386  1.1        is 	fmul.x		(%a1,%d3),%fp1		# mul by 10**(d3_bit_no)
   13387  1.1        is e_next:
   13388  1.1        is 	add.l		&12,%d3			# inc d3 to next rtable entry
   13389  1.1        is 	tst.l		%d0			# check if d0 is zero
   13390  1.1        is 	bne.b		e_loop			# not zero, continue shifting
   13391  1.1        is #
   13392  1.1        is #
   13393  1.1        is #  Check the sign of the adjusted exp and make the value in fp0 the
   13394  1.1        is #  same sign. If the exp was pos then multiply fp1*fp0;
   13395  1.1        is #  else divide fp0/fp1.
   13396  1.1        is #
   13397  1.1        is # Register Usage:
   13398  1.1        is #  norm:
   13399  1.1        is #	( )  a0: pointer to working bcd value
   13400  1.1        is #	(*) fp0: mantissa accumulator
   13401  1.1        is #	( ) fp1: scaling factor - 10**(abs(exp))
   13402  1.1        is #
   13403  1.1        is pnorm:
   13404  1.1        is 	btst		&30,(%a0)		# test the sign of the exponent
   13405  1.1        is 	beq.b		mul			# if clear, go to multiply
   13406  1.1        is div:
   13407  1.1        is 	fdiv.x		%fp1,%fp0		# exp is negative, so divide mant by exp
   13408  1.1        is 	bra.b		end_dec
   13409  1.1        is mul:
   13410  1.1        is 	fmul.x		%fp1,%fp0		# exp is positive, so multiply by exp
   13411  1.1        is #
   13412  1.1        is #
   13413  1.1        is # Clean up and return with result in fp0.
   13414  1.1        is #
   13415  1.1        is # If the final mul/div in decbin incurred an inex exception,
   13416  1.1        is # it will be inex2, but will be reported as inex1 by get_op.
   13417  1.1        is #
   13418  1.1        is end_dec:
   13419  1.1        is 	fmov.l		%fpsr,%d0		# get status register
   13420  1.1        is 	bclr		&inex2_bit+8,%d0	# test for inex2 and clear it
   13421  1.1        is 	beq.b		no_exc			# skip this if no exc
   13422  1.1        is 	ori.w		&inx1a_mask,2+USER_FPSR(%a6) # set INEX1/AINEX
   13423  1.1        is no_exc:
   13424  1.1        is 	add.l		&0x4,%sp		# clear 1 lw param
   13425  1.1        is 	fmovm.x		(%sp)+,&0x40		# restore fp1
   13426  1.1        is 	movm.l		(%sp)+,&0x3c		# restore d2-d5
   13427  1.1        is 	fmov.l		&0x0,%fpcr
   13428  1.1        is 	fmov.l		&0x0,%fpsr
   13429  1.1        is 	rts
   13430  1.1        is 
   13431  1.1        is #########################################################################
   13432  1.1        is # bindec(): Converts an input in extended precision format to bcd format#
   13433  1.1        is #									#
   13434  1.1        is # INPUT ***************************************************************	#
   13435  1.1        is #	a0 = pointer to the input extended precision value in memory.	#
   13436  1.1        is #	     the input may be either normalized, unnormalized, or 	#
   13437  1.1        is #	     denormalized.						#
   13438  1.1        is #	d0 = contains the k-factor sign-extended to 32-bits. 		#
   13439  1.1        is #									#
   13440  1.1        is # OUTPUT **************************************************************	#
   13441  1.1        is #	FP_SCR0(a6) = bcd format result on the stack.			#
   13442  1.1        is #									#
   13443  1.1        is # ALGORITHM ***********************************************************	#
   13444  1.1        is #									#
   13445  1.1        is #	A1.	Set RM and size ext;  Set SIGMA = sign of input.  	#
   13446  1.1        is #		The k-factor is saved for use in d7. Clear the		#
   13447  1.1        is #		BINDEC_FLG for separating normalized/denormalized	#
   13448  1.1        is #		input.  If input is unnormalized or denormalized,	#
   13449  1.1        is #		normalize it.						#
   13450  1.1        is #									#
   13451  1.1        is #	A2.	Set X = abs(input).					#
   13452  1.1        is #									#
   13453  1.1        is #	A3.	Compute ILOG.						#
   13454  1.1        is #		ILOG is the log base 10 of the input value.  It is	#
   13455  1.1        is #		approximated by adding e + 0.f when the original 	#
   13456  1.1        is #		value is viewed as 2^^e * 1.f in extended precision.  	#
   13457  1.1        is #		This value is stored in d6.				#
   13458  1.1        is #									#
   13459  1.1        is #	A4.	Clr INEX bit.						#
   13460  1.1        is #		The operation in A3 above may have set INEX2.  		#
   13461  1.1        is #									#
   13462  1.1        is #	A5.	Set ICTR = 0;						#
   13463  1.1        is #		ICTR is a flag used in A13.  It must be set before the 	#
   13464  1.1        is #		loop entry A6.						#
   13465  1.1        is #									#
   13466  1.1        is #	A6.	Calculate LEN.						#
   13467  1.1        is #		LEN is the number of digits to be displayed.  The	#
   13468  1.1        is #		k-factor can dictate either the total number of digits,	#
   13469  1.1        is #		if it is a positive number, or the number of digits	#
   13470  1.1        is #		after the decimal point which are to be included as	#
   13471  1.1        is #		significant.  See the 68882 manual for examples.	#
   13472  1.1        is #		If LEN is computed to be greater than 17, set OPERR in	#
   13473  1.1        is #		USER_FPSR.  LEN is stored in d4.			#
   13474  1.1        is #									#
   13475  1.1        is #	A7.	Calculate SCALE.					#
   13476  1.1        is #		SCALE is equal to 10^ISCALE, where ISCALE is the number	#
   13477  1.1        is #		of decimal places needed to insure LEN integer digits	#
   13478  1.1        is #		in the output before conversion to bcd. LAMBDA is the	#
   13479  1.1        is #		sign of ISCALE, used in A9. Fp1 contains		#
   13480  1.1        is #		10^^(abs(ISCALE)) using a rounding mode which is a	#
   13481  1.1        is #		function of the original rounding mode and the signs	#
   13482  1.1        is #		of ISCALE and X.  A table is given in the code.		#
   13483  1.1        is #									#
   13484  1.1        is #	A8.	Clr INEX; Force RZ.					#
   13485  1.1        is #		The operation in A3 above may have set INEX2.  		#
   13486  1.1        is #		RZ mode is forced for the scaling operation to insure	#
   13487  1.1        is #		only one rounding error.  The grs bits are collected in #
   13488  1.1        is #		the INEX flag for use in A10.				#
   13489  1.1        is #									#
   13490  1.1        is #	A9.	Scale X -> Y.						#
   13491  1.1        is #		The mantissa is scaled to the desired number of		#
   13492  1.1        is #		significant digits.  The excess digits are collected	#
   13493  1.1        is #		in INEX2.						#
   13494  1.1        is #									#
   13495  1.1        is #	A10.	Or in INEX.						#
   13496  1.2       wiz #		If INEX is set, round error occurred.  This is		#
   13497  1.1        is #		compensated for by 'or-ing' in the INEX2 flag to	#
   13498  1.1        is #		the lsb of Y.						#
   13499  1.1        is #									#
   13500  1.1        is #	A11.	Restore original FPCR; set size ext.			#
   13501  1.1        is #		Perform FINT operation in the user's rounding mode.	#
   13502  1.1        is #		Keep the size to extended.				#
   13503  1.1        is #									#
   13504  1.1        is #	A12.	Calculate YINT = FINT(Y) according to user's rounding	#
   13505  1.1        is #		mode.  The FPSP routine sintd0 is used.  The output	#
   13506  1.1        is #		is in fp0.						#
   13507  1.1        is #									#
   13508  1.1        is #	A13.	Check for LEN digits.					#
   13509  1.1        is #		If the int operation results in more than LEN digits,	#
   13510  1.1        is #		or less than LEN -1 digits, adjust ILOG and repeat from	#
   13511  1.1        is #		A6.  This test occurs only on the first pass.  If the	#
   13512  1.1        is #		result is exactly 10^LEN, decrement ILOG and divide	#
   13513  1.1        is #		the mantissa by 10.					#
   13514  1.1        is #									#
   13515  1.1        is #	A14.	Convert the mantissa to bcd.				#
   13516  1.1        is #		The binstr routine is used to convert the LEN digit 	#
   13517  1.1        is #		mantissa to bcd in memory.  The input to binstr is	#
   13518  1.1        is #		to be a fraction; i.e. (mantissa)/10^LEN and adjusted	#
   13519  1.1        is #		such that the decimal point is to the left of bit 63.	#
   13520  1.1        is #		The bcd digits are stored in the correct position in 	#
   13521  1.1        is #		the final string area in memory.			#
   13522  1.1        is #									#
   13523  1.1        is #	A15.	Convert the exponent to bcd.				#
   13524  1.1        is #		As in A14 above, the exp is converted to bcd and the	#
   13525  1.1        is #		digits are stored in the final string.			#
   13526  1.1        is #		Test the length of the final exponent string.  If the	#
   13527  1.1        is #		length is 4, set operr.					#
   13528  1.1        is #									#
   13529  1.1        is #	A16.	Write sign bits to final string.			#
   13530  1.1        is #									#
   13531  1.1        is #########################################################################
   13532  1.1        is 
   13533  1.1        is set	BINDEC_FLG,	EXC_TEMP	# DENORM flag
   13534  1.1        is 
   13535  1.1        is # Constants in extended precision
   13536  1.1        is PLOG2:
   13537  1.1        is 	long		0x3FFD0000,0x9A209A84,0xFBCFF798,0x00000000
   13538  1.1        is PLOG2UP1:
   13539  1.1        is 	long		0x3FFD0000,0x9A209A84,0xFBCFF799,0x00000000
   13540  1.1        is 
   13541  1.1        is # Constants in single precision
   13542  1.1        is FONE:
   13543  1.1        is 	long		0x3F800000,0x00000000,0x00000000,0x00000000
   13544  1.1        is FTWO:
   13545  1.1        is 	long		0x40000000,0x00000000,0x00000000,0x00000000
   13546  1.1        is FTEN:
   13547  1.1        is 	long		0x41200000,0x00000000,0x00000000,0x00000000
   13548  1.1        is F4933:
   13549  1.1        is 	long		0x459A2800,0x00000000,0x00000000,0x00000000
   13550  1.1        is 
   13551  1.1        is RBDTBL:
   13552  1.1        is 	byte		0,0,0,0
   13553  1.1        is 	byte		3,3,2,2
   13554  1.1        is 	byte		3,2,2,3
   13555  1.1        is 	byte		2,3,3,2
   13556  1.1        is 
   13557  1.1        is #	Implementation Notes:
   13558  1.1        is #
   13559  1.1        is #	The registers are used as follows:
   13560  1.1        is #
   13561  1.1        is #		d0: scratch; LEN input to binstr
   13562  1.1        is #		d1: scratch
   13563  1.1        is #		d2: upper 32-bits of mantissa for binstr
   13564  1.1        is #		d3: scratch;lower 32-bits of mantissa for binstr
   13565  1.1        is #		d4: LEN
   13566  1.1        is #      		d5: LAMBDA/ICTR
   13567  1.1        is #		d6: ILOG
   13568  1.1        is #		d7: k-factor
   13569  1.1        is #		a0: ptr for original operand/final result
   13570  1.1        is #		a1: scratch pointer
   13571  1.1        is #		a2: pointer to FP_X; abs(original value) in ext
   13572  1.1        is #		fp0: scratch
   13573  1.1        is #		fp1: scratch
   13574  1.1        is #		fp2: scratch
   13575  1.1        is #		F_SCR1:
   13576  1.1        is #		F_SCR2:
   13577  1.1        is #		L_SCR1:
   13578  1.1        is #		L_SCR2:
   13579  1.1        is 
   13580  1.1        is 	global		bindec
   13581  1.1        is bindec:
   13582  1.1        is 	movm.l		&0x3f20,-(%sp)	#  {%d2-%d7/%a2}
   13583  1.1        is 	fmovm.x		&0x7,-(%sp)	#  {%fp0-%fp2}
   13584  1.1        is 
   13585  1.1        is # A1. Set RM and size ext. Set SIGMA = sign input;
   13586  1.1        is #     The k-factor is saved for use in d7.  Clear BINDEC_FLG for
   13587  1.1        is #     separating  normalized/denormalized input.  If the input
   13588  1.1        is #     is a denormalized number, set the BINDEC_FLG memory word
   13589  1.1        is #     to signal denorm.  If the input is unnormalized, normalize
   13590  1.1        is #     the input and test for denormalized result.
   13591  1.1        is #
   13592  1.1        is 	fmov.l		&rm_mode*0x10,%fpcr	# set RM and ext
   13593  1.1        is 	mov.l		(%a0),L_SCR2(%a6)	# save exponent for sign check
   13594  1.1        is 	mov.l		%d0,%d7		# move k-factor to d7
   13595  1.1        is 
   13596  1.1        is 	clr.b		BINDEC_FLG(%a6)	# clr norm/denorm flag
   13597  1.1        is 	cmpi.b		STAG(%a6),&DENORM # is input a DENORM?
   13598  1.1        is 	bne.w		A2_str		# no; input is a NORM
   13599  1.1        is 
   13600  1.1        is #
   13601  1.1        is # Normalize the denorm
   13602  1.1        is #
   13603  1.1        is un_de_norm:
   13604  1.1        is 	mov.w		(%a0),%d0
   13605  1.1        is 	and.w		&0x7fff,%d0	# strip sign of normalized exp
   13606  1.1        is 	mov.l		4(%a0),%d1
   13607  1.1        is 	mov.l		8(%a0),%d2
   13608  1.1        is norm_loop:
   13609  1.1        is 	sub.w		&1,%d0
   13610  1.1        is 	lsl.l		&1,%d2
   13611  1.1        is 	roxl.l		&1,%d1
   13612  1.1        is 	tst.l		%d1
   13613  1.1        is 	bge.b		norm_loop
   13614  1.1        is #
   13615  1.1        is # Test if the normalized input is denormalized
   13616  1.1        is #
   13617  1.1        is 	tst.w		%d0
   13618  1.1        is 	bgt.b		pos_exp		# if greater than zero, it is a norm
   13619  1.1        is 	st		BINDEC_FLG(%a6)	# set flag for denorm
   13620  1.1        is pos_exp:
   13621  1.1        is 	and.w		&0x7fff,%d0	# strip sign of normalized exp
   13622  1.1        is 	mov.w		%d0,(%a0)
   13623  1.1        is 	mov.l		%d1,4(%a0)
   13624  1.1        is 	mov.l		%d2,8(%a0)
   13625  1.1        is 
   13626  1.1        is # A2. Set X = abs(input).
   13627  1.1        is #
   13628  1.1        is A2_str:
   13629  1.1        is 	mov.l		(%a0),FP_SCR1(%a6)	# move input to work space
   13630  1.1        is 	mov.l		4(%a0),FP_SCR1+4(%a6)	# move input to work space
   13631  1.1        is 	mov.l		8(%a0),FP_SCR1+8(%a6)	# move input to work space
   13632  1.1        is 	and.l		&0x7fffffff,FP_SCR1(%a6)	# create abs(X)
   13633  1.1        is 
   13634  1.1        is # A3. Compute ILOG.
   13635  1.1        is #     ILOG is the log base 10 of the input value.  It is approx-
   13636  1.1        is #     imated by adding e + 0.f when the original value is viewed
   13637  1.1        is #     as 2^^e * 1.f in extended precision.  This value is stored
   13638  1.1        is #     in d6.
   13639  1.1        is #
   13640  1.1        is # Register usage:
   13641  1.1        is #	Input/Output
   13642  1.1        is #	d0: k-factor/exponent
   13643  1.1        is #	d2: x/x
   13644  1.1        is #	d3: x/x
   13645  1.1        is #	d4: x/x
   13646  1.1        is #	d5: x/x
   13647  1.1        is #	d6: x/ILOG
   13648  1.1        is #	d7: k-factor/Unchanged
   13649  1.1        is #	a0: ptr for original operand/final result
   13650  1.1        is #	a1: x/x
   13651  1.1        is #	a2: x/x
   13652  1.1        is #	fp0: x/float(ILOG)
   13653  1.1        is #	fp1: x/x
   13654  1.1        is #	fp2: x/x
   13655  1.1        is #	F_SCR1:x/x
   13656  1.1        is #	F_SCR2:Abs(X)/Abs(X) with $3fff exponent
   13657  1.1        is #	L_SCR1:x/x
   13658  1.1        is #	L_SCR2:first word of X packed/Unchanged
   13659  1.1        is 
   13660  1.1        is 	tst.b		BINDEC_FLG(%a6)	# check for denorm
   13661  1.1        is 	beq.b		A3_cont		# if clr, continue with norm
   13662  1.1        is 	mov.l		&-4933,%d6	# force ILOG = -4933
   13663  1.1        is 	bra.b		A4_str
   13664  1.1        is A3_cont:
   13665  1.1        is 	mov.w		FP_SCR1(%a6),%d0	# move exp to d0
   13666  1.1        is 	mov.w		&0x3fff,FP_SCR1(%a6)	# replace exponent with 0x3fff
   13667  1.1        is 	fmov.x		FP_SCR1(%a6),%fp0	# now fp0 has 1.f
   13668  1.1        is 	sub.w		&0x3fff,%d0	# strip off bias
   13669  1.1        is 	fadd.w		%d0,%fp0	# add in exp
   13670  1.1        is 	fsub.s		FONE(%pc),%fp0	# subtract off 1.0
   13671  1.1        is 	fbge.w		pos_res		# if pos, branch
   13672  1.1        is 	fmul.x		PLOG2UP1(%pc),%fp0	# if neg, mul by LOG2UP1
   13673  1.1        is 	fmov.l		%fp0,%d6	# put ILOG in d6 as a lword
   13674  1.1        is 	bra.b		A4_str		# go move out ILOG
   13675  1.1        is pos_res:
   13676  1.1        is 	fmul.x		PLOG2(%pc),%fp0	# if pos, mul by LOG2
   13677  1.1        is 	fmov.l		%fp0,%d6	# put ILOG in d6 as a lword
   13678  1.1        is 
   13679  1.1        is 
   13680  1.1        is # A4. Clr INEX bit.
   13681  1.1        is #     The operation in A3 above may have set INEX2.
   13682  1.1        is 
   13683  1.1        is A4_str:
   13684  1.1        is 	fmov.l		&0,%fpsr	# zero all of fpsr - nothing needed
   13685  1.1        is 
   13686  1.1        is 
   13687  1.1        is # A5. Set ICTR = 0;
   13688  1.1        is #     ICTR is a flag used in A13.  It must be set before the
   13689  1.1        is #     loop entry A6. The lower word of d5 is used for ICTR.
   13690  1.1        is 
   13691  1.1        is 	clr.w		%d5		# clear ICTR
   13692  1.1        is 
   13693  1.1        is # A6. Calculate LEN.
   13694  1.1        is #     LEN is the number of digits to be displayed.  The k-factor
   13695  1.1        is #     can dictate either the total number of digits, if it is
   13696  1.1        is #     a positive number, or the number of digits after the
   13697  1.1        is #     original decimal point which are to be included as
   13698  1.1        is #     significant.  See the 68882 manual for examples.
   13699  1.1        is #     If LEN is computed to be greater than 17, set OPERR in
   13700  1.1        is #     USER_FPSR.  LEN is stored in d4.
   13701  1.1        is #
   13702  1.1        is # Register usage:
   13703  1.1        is #	Input/Output
   13704  1.1        is #	d0: exponent/Unchanged
   13705  1.1        is #	d2: x/x/scratch
   13706  1.1        is #	d3: x/x
   13707  1.1        is #	d4: exc picture/LEN
   13708  1.1        is #	d5: ICTR/Unchanged
   13709  1.1        is #	d6: ILOG/Unchanged
   13710  1.1        is #	d7: k-factor/Unchanged
   13711  1.1        is #	a0: ptr for original operand/final result
   13712  1.1        is #	a1: x/x
   13713  1.1        is #	a2: x/x
   13714  1.1        is #	fp0: float(ILOG)/Unchanged
   13715  1.1        is #	fp1: x/x
   13716  1.1        is #	fp2: x/x
   13717  1.1        is #	F_SCR1:x/x
   13718  1.1        is #	F_SCR2:Abs(X) with $3fff exponent/Unchanged
   13719  1.1        is #	L_SCR1:x/x
   13720  1.1        is #	L_SCR2:first word of X packed/Unchanged
   13721  1.1        is 
   13722  1.1        is A6_str:
   13723  1.1        is 	tst.l		%d7		# branch on sign of k
   13724  1.1        is 	ble.b		k_neg		# if k <= 0, LEN = ILOG + 1 - k
   13725  1.1        is 	mov.l		%d7,%d4		# if k > 0, LEN = k
   13726  1.1        is 	bra.b		len_ck		# skip to LEN check
   13727  1.1        is k_neg:
   13728  1.1        is 	mov.l		%d6,%d4		# first load ILOG to d4
   13729  1.1        is 	sub.l		%d7,%d4		# subtract off k
   13730  1.1        is 	addq.l		&1,%d4		# add in the 1
   13731  1.1        is len_ck:
   13732  1.1        is 	tst.l		%d4		# LEN check: branch on sign of LEN
   13733  1.1        is 	ble.b		LEN_ng		# if neg, set LEN = 1
   13734  1.1        is 	cmp.l		%d4,&17		# test if LEN > 17
   13735  1.1        is 	ble.b		A7_str		# if not, forget it
   13736  1.1        is 	mov.l		&17,%d4		# set max LEN = 17
   13737  1.1        is 	tst.l		%d7		# if negative, never set OPERR
   13738  1.1        is 	ble.b		A7_str		# if positive, continue
   13739  1.1        is 	or.l		&opaop_mask,USER_FPSR(%a6)	# set OPERR & AIOP in USER_FPSR
   13740  1.1        is 	bra.b		A7_str		# finished here
   13741  1.1        is LEN_ng:
   13742  1.1        is 	mov.l		&1,%d4		# min LEN is 1
   13743  1.1        is 
   13744  1.1        is 
   13745  1.1        is # A7. Calculate SCALE.
   13746  1.1        is #     SCALE is equal to 10^ISCALE, where ISCALE is the number
   13747  1.1        is #     of decimal places needed to insure LEN integer digits
   13748  1.1        is #     in the output before conversion to bcd. LAMBDA is the sign
   13749  1.1        is #     of ISCALE, used in A9.  Fp1 contains 10^^(abs(ISCALE)) using
   13750  1.1        is #     the rounding mode as given in the following table (see
   13751  1.1        is #     Coonen, p. 7.23 as ref.; however, the SCALE variable is
   13752  1.1        is #     of opposite sign in bindec.sa from Coonen).
   13753  1.1        is #
   13754  1.1        is #	Initial					USE
   13755  1.1        is #	FPCR[6:5]	LAMBDA	SIGN(X)		FPCR[6:5]
   13756  1.1        is #	----------------------------------------------
   13757  1.1        is #	 RN	00	   0	   0		00/0	RN
   13758  1.1        is #	 RN	00	   0	   1		00/0	RN
   13759  1.1        is #	 RN	00	   1	   0		00/0	RN
   13760  1.1        is #	 RN	00	   1	   1		00/0	RN
   13761  1.1        is #	 RZ	01	   0	   0		11/3	RP
   13762  1.1        is #	 RZ	01	   0	   1		11/3	RP
   13763  1.1        is #	 RZ	01	   1	   0		10/2	RM
   13764  1.1        is #	 RZ	01	   1	   1		10/2	RM
   13765  1.1        is #	 RM	10	   0	   0		11/3	RP
   13766  1.1        is #	 RM	10	   0	   1		10/2	RM
   13767  1.1        is #	 RM	10	   1	   0		10/2	RM
   13768  1.1        is #	 RM	10	   1	   1		11/3	RP
   13769  1.1        is #	 RP	11	   0	   0		10/2	RM
   13770  1.1        is #	 RP	11	   0	   1		11/3	RP
   13771  1.1        is #	 RP	11	   1	   0		11/3	RP
   13772  1.1        is #	 RP	11	   1	   1		10/2	RM
   13773  1.1        is #
   13774  1.1        is # Register usage:
   13775  1.1        is #	Input/Output
   13776  1.1        is #	d0: exponent/scratch - final is 0
   13777  1.1        is #	d2: x/0 or 24 for A9
   13778  1.1        is #	d3: x/scratch - offset ptr into PTENRM array
   13779  1.1        is #	d4: LEN/Unchanged
   13780  1.1        is #	d5: 0/ICTR:LAMBDA
   13781  1.1        is #	d6: ILOG/ILOG or k if ((k<=0)&(ILOG<k))
   13782  1.1        is #	d7: k-factor/Unchanged
   13783  1.1        is #	a0: ptr for original operand/final result
   13784  1.1        is #	a1: x/ptr to PTENRM array
   13785  1.1        is #	a2: x/x
   13786  1.1        is #	fp0: float(ILOG)/Unchanged
   13787  1.1        is #	fp1: x/10^ISCALE
   13788  1.1        is #	fp2: x/x
   13789  1.1        is #	F_SCR1:x/x
   13790  1.1        is #	F_SCR2:Abs(X) with $3fff exponent/Unchanged
   13791  1.1        is #	L_SCR1:x/x
   13792  1.1        is #	L_SCR2:first word of X packed/Unchanged
   13793  1.1        is 
   13794  1.1        is A7_str:
   13795  1.1        is 	tst.l		%d7		# test sign of k
   13796  1.1        is 	bgt.b		k_pos		# if pos and > 0, skip this
   13797  1.1        is 	cmp.l		%d7,%d6		# test k - ILOG
   13798  1.1        is 	blt.b		k_pos		# if ILOG >= k, skip this
   13799  1.1        is 	mov.l		%d7,%d6		# if ((k<0) & (ILOG < k)) ILOG = k
   13800  1.1        is k_pos:
   13801  1.1        is 	mov.l		%d6,%d0		# calc ILOG + 1 - LEN in d0
   13802  1.1        is 	addq.l		&1,%d0		# add the 1
   13803  1.1        is 	sub.l		%d4,%d0		# sub off LEN
   13804  1.1        is 	swap		%d5		# use upper word of d5 for LAMBDA
   13805  1.1        is 	clr.w		%d5		# set it zero initially
   13806  1.1        is 	clr.w		%d2		# set up d2 for very small case
   13807  1.1        is 	tst.l		%d0		# test sign of ISCALE
   13808  1.1        is 	bge.b		iscale		# if pos, skip next inst
   13809  1.1        is 	addq.w		&1,%d5		# if neg, set LAMBDA true
   13810  1.1        is 	cmp.l		%d0,&0xffffecd4	# test iscale <= -4908
   13811  1.1        is 	bgt.b		no_inf		# if false, skip rest
   13812  1.1        is 	add.l		&24,%d0		# add in 24 to iscale
   13813  1.1        is 	mov.l		&24,%d2		# put 24 in d2 for A9
   13814  1.1        is no_inf:
   13815  1.1        is 	neg.l		%d0		# and take abs of ISCALE
   13816  1.1        is iscale:
   13817  1.1        is 	fmov.s		FONE(%pc),%fp1	# init fp1 to 1
   13818  1.1        is 	bfextu		USER_FPCR(%a6){&26:&2},%d1	# get initial rmode bits
   13819  1.1        is 	lsl.w		&1,%d1		# put them in bits 2:1
   13820  1.1        is 	add.w		%d5,%d1		# add in LAMBDA
   13821  1.1        is 	lsl.w		&1,%d1		# put them in bits 3:1
   13822  1.1        is 	tst.l		L_SCR2(%a6)	# test sign of original x
   13823  1.1        is 	bge.b		x_pos		# if pos, don't set bit 0
   13824  1.1        is 	addq.l		&1,%d1		# if neg, set bit 0
   13825  1.1        is x_pos:
   13826  1.1        is 	lea.l		RBDTBL(%pc),%a2	# load rbdtbl base
   13827  1.1        is 	mov.b		(%a2,%d1),%d3	# load d3 with new rmode
   13828  1.1        is 	lsl.l		&4,%d3		# put bits in proper position
   13829  1.1        is 	fmov.l		%d3,%fpcr	# load bits into fpu
   13830  1.1        is 	lsr.l		&4,%d3		# put bits in proper position
   13831  1.1        is 	tst.b		%d3		# decode new rmode for pten table
   13832  1.1        is 	bne.b		not_rn		# if zero, it is RN
   13833  1.1        is 	lea.l		PTENRN(%pc),%a1	# load a1 with RN table base
   13834  1.1        is 	bra.b		rmode		# exit decode
   13835  1.1        is not_rn:
   13836  1.1        is 	lsr.b		&1,%d3		# get lsb in carry
   13837  1.1        is 	bcc.b		not_rp2		# if carry clear, it is RM
   13838  1.1        is 	lea.l		PTENRP(%pc),%a1	# load a1 with RP table base
   13839  1.1        is 	bra.b		rmode		# exit decode
   13840  1.1        is not_rp2:
   13841  1.1        is 	lea.l		PTENRM(%pc),%a1	# load a1 with RM table base
   13842  1.1        is rmode:
   13843  1.1        is 	clr.l		%d3		# clr table index
   13844  1.1        is e_loop2:
   13845  1.1        is 	lsr.l		&1,%d0		# shift next bit into carry
   13846  1.1        is 	bcc.b		e_next2		# if zero, skip the mul
   13847  1.1        is 	fmul.x		(%a1,%d3),%fp1	# mul by 10**(d3_bit_no)
   13848  1.1        is e_next2:
   13849  1.1        is 	add.l		&12,%d3		# inc d3 to next pwrten table entry
   13850  1.1        is 	tst.l		%d0		# test if ISCALE is zero
   13851  1.1        is 	bne.b		e_loop2		# if not, loop
   13852  1.1        is 
   13853  1.1        is # A8. Clr INEX; Force RZ.
   13854  1.1        is #     The operation in A3 above may have set INEX2.
   13855  1.1        is #     RZ mode is forced for the scaling operation to insure
   13856  1.1        is #     only one rounding error.  The grs bits are collected in
   13857  1.1        is #     the INEX flag for use in A10.
   13858  1.1        is #
   13859  1.1        is # Register usage:
   13860  1.1        is #	Input/Output
   13861  1.1        is 
   13862  1.1        is 	fmov.l		&0,%fpsr	# clr INEX
   13863  1.1        is 	fmov.l		&rz_mode*0x10,%fpcr	# set RZ rounding mode
   13864  1.1        is 
   13865  1.1        is # A9. Scale X -> Y.
   13866  1.1        is #     The mantissa is scaled to the desired number of significant
   13867  1.1        is #     digits.  The excess digits are collected in INEX2. If mul,
   13868  1.1        is #     Check d2 for excess 10 exponential value.  If not zero,
   13869  1.1        is #     the iscale value would have caused the pwrten calculation
   13870  1.1        is #     to overflow.  Only a negative iscale can cause this, so
   13871  1.1        is #     multiply by 10^(d2), which is now only allowed to be 24,
   13872  1.1        is #     with a multiply by 10^8 and 10^16, which is exact since
   13873  1.1        is #     10^24 is exact.  If the input was denormalized, we must
   13874  1.1        is #     create a busy stack frame with the mul command and the
   13875  1.1        is #     two operands, and allow the fpu to complete the multiply.
   13876  1.1        is #
   13877  1.1        is # Register usage:
   13878  1.1        is #	Input/Output
   13879  1.1        is #	d0: FPCR with RZ mode/Unchanged
   13880  1.1        is #	d2: 0 or 24/unchanged
   13881  1.1        is #	d3: x/x
   13882  1.1        is #	d4: LEN/Unchanged
   13883  1.1        is #	d5: ICTR:LAMBDA
   13884  1.1        is #	d6: ILOG/Unchanged
   13885  1.1        is #	d7: k-factor/Unchanged
   13886  1.1        is #	a0: ptr for original operand/final result
   13887  1.1        is #	a1: ptr to PTENRM array/Unchanged
   13888  1.1        is #	a2: x/x
   13889  1.1        is #	fp0: float(ILOG)/X adjusted for SCALE (Y)
   13890  1.1        is #	fp1: 10^ISCALE/Unchanged
   13891  1.1        is #	fp2: x/x
   13892  1.1        is #	F_SCR1:x/x
   13893  1.1        is #	F_SCR2:Abs(X) with $3fff exponent/Unchanged
   13894  1.1        is #	L_SCR1:x/x
   13895  1.1        is #	L_SCR2:first word of X packed/Unchanged
   13896  1.1        is 
   13897  1.1        is A9_str:
   13898  1.1        is 	fmov.x		(%a0),%fp0	# load X from memory
   13899  1.1        is 	fabs.x		%fp0		# use abs(X)
   13900  1.1        is 	tst.w		%d5		# LAMBDA is in lower word of d5
   13901  1.1        is 	bne.b		sc_mul		# if neg (LAMBDA = 1), scale by mul
   13902  1.1        is 	fdiv.x		%fp1,%fp0	# calculate X / SCALE -> Y to fp0
   13903  1.1        is 	bra.w		A10_st		# branch to A10
   13904  1.1        is 
   13905  1.1        is sc_mul:
   13906  1.1        is 	tst.b		BINDEC_FLG(%a6)	# check for denorm
   13907  1.1        is 	beq.w		A9_norm		# if norm, continue with mul
   13908  1.1        is 
   13909  1.1        is # for DENORM, we must calculate:
   13910  1.1        is #	fp0 = input_op * 10^ISCALE * 10^24
   13911  1.1        is # since the input operand is a DENORM, we can't multiply it directly.
   13912  1.1        is # so, we do the multiplication of the exponents and mantissas separately.
   13913  1.1        is # in this way, we avoid underflow on intermediate stages of the
   13914  1.1        is # multiplication and guarantee a result without exception.
   13915  1.1        is 	fmovm.x		&0x2,-(%sp)	# save 10^ISCALE to stack
   13916  1.1        is 
   13917  1.1        is 	mov.w		(%sp),%d3	# grab exponent
   13918  1.1        is 	andi.w		&0x7fff,%d3	# clear sign
   13919  1.1        is 	ori.w		&0x8000,(%a0)	# make DENORM exp negative
   13920  1.1        is 	add.w		(%a0),%d3	# add DENORM exp to 10^ISCALE exp
   13921  1.1        is 	subi.w		&0x3fff,%d3	# subtract BIAS
   13922  1.1        is 	add.w		36(%a1),%d3
   13923  1.1        is 	subi.w		&0x3fff,%d3	# subtract BIAS
   13924  1.1        is 	add.w		48(%a1),%d3
   13925  1.1        is 	subi.w		&0x3fff,%d3	# subtract BIAS
   13926  1.1        is 
   13927  1.1        is 	bmi.w		sc_mul_err	# is result is DENORM, punt!!!
   13928  1.1        is 
   13929  1.1        is 	andi.w		&0x8000,(%sp)	# keep sign
   13930  1.1        is 	or.w		%d3,(%sp)	# insert new exponent
   13931  1.1        is 	andi.w		&0x7fff,(%a0)	# clear sign bit on DENORM again
   13932  1.1        is 	mov.l		0x8(%a0),-(%sp) # put input op mantissa on stk
   13933  1.1        is 	mov.l		0x4(%a0),-(%sp)
   13934  1.1        is 	mov.l		&0x3fff0000,-(%sp) # force exp to zero
   13935  1.1        is 	fmovm.x		(%sp)+,&0x80	# load normalized DENORM into fp0
   13936  1.1        is 	fmul.x		(%sp)+,%fp0
   13937  1.1        is 
   13938  1.1        is #	fmul.x	36(%a1),%fp0	# multiply fp0 by 10^8
   13939  1.1        is #	fmul.x	48(%a1),%fp0	# multiply fp0 by 10^16
   13940  1.1        is 	mov.l		36+8(%a1),-(%sp) # get 10^8 mantissa
   13941  1.1        is 	mov.l		36+4(%a1),-(%sp)
   13942  1.1        is 	mov.l		&0x3fff0000,-(%sp) # force exp to zero
   13943  1.1        is 	mov.l		48+8(%a1),-(%sp) # get 10^16 mantissa
   13944  1.1        is 	mov.l		48+4(%a1),-(%sp)
   13945  1.1        is 	mov.l		&0x3fff0000,-(%sp)# force exp to zero
   13946  1.1        is 	fmul.x		(%sp)+,%fp0	# multiply fp0 by 10^8
   13947  1.1        is 	fmul.x		(%sp)+,%fp0	# multiply fp0 by 10^16
   13948  1.1        is 	bra.b		A10_st
   13949  1.1        is 
   13950  1.1        is sc_mul_err:
   13951  1.1        is 	bra.b		sc_mul_err
   13952  1.1        is 
   13953  1.1        is A9_norm:
   13954  1.1        is 	tst.w		%d2		# test for small exp case
   13955  1.1        is 	beq.b		A9_con		# if zero, continue as normal
   13956  1.1        is 	fmul.x		36(%a1),%fp0	# multiply fp0 by 10^8
   13957  1.1        is 	fmul.x		48(%a1),%fp0	# multiply fp0 by 10^16
   13958  1.1        is A9_con:
   13959  1.1        is 	fmul.x		%fp1,%fp0	# calculate X * SCALE -> Y to fp0
   13960  1.1        is 
   13961  1.1        is # A10. Or in INEX.
   13962  1.2       wiz #      If INEX is set, round error occurred.  This is compensated
   13963  1.1        is #      for by 'or-ing' in the INEX2 flag to the lsb of Y.
   13964  1.1        is #
   13965  1.1        is # Register usage:
   13966  1.1        is #	Input/Output
   13967  1.1        is #	d0: FPCR with RZ mode/FPSR with INEX2 isolated
   13968  1.1        is #	d2: x/x
   13969  1.1        is #	d3: x/x
   13970  1.1        is #	d4: LEN/Unchanged
   13971  1.1        is #	d5: ICTR:LAMBDA
   13972  1.1        is #	d6: ILOG/Unchanged
   13973  1.1        is #	d7: k-factor/Unchanged
   13974  1.1        is #	a0: ptr for original operand/final result
   13975  1.1        is #	a1: ptr to PTENxx array/Unchanged
   13976  1.1        is #	a2: x/ptr to FP_SCR1(a6)
   13977  1.1        is #	fp0: Y/Y with lsb adjusted
   13978  1.1        is #	fp1: 10^ISCALE/Unchanged
   13979  1.1        is #	fp2: x/x
   13980  1.1        is 
   13981  1.1        is A10_st:
   13982  1.1        is 	fmov.l		%fpsr,%d0	# get FPSR
   13983  1.1        is 	fmov.x		%fp0,FP_SCR1(%a6)	# move Y to memory
   13984  1.1        is 	lea.l		FP_SCR1(%a6),%a2	# load a2 with ptr to FP_SCR1
   13985  1.1        is 	btst		&9,%d0		# check if INEX2 set
   13986  1.1        is 	beq.b		A11_st		# if clear, skip rest
   13987  1.1        is 	or.l		&1,8(%a2)	# or in 1 to lsb of mantissa
   13988  1.1        is 	fmov.x		FP_SCR1(%a6),%fp0	# write adjusted Y back to fpu
   13989  1.1        is 
   13990  1.1        is 
   13991  1.1        is # A11. Restore original FPCR; set size ext.
   13992  1.1        is #      Perform FINT operation in the user's rounding mode.  Keep
   13993  1.1        is #      the size to extended.  The sintdo entry point in the sint
   13994  1.1        is #      routine expects the FPCR value to be in USER_FPCR for
   13995  1.1        is #      mode and precision.  The original FPCR is saved in L_SCR1.
   13996  1.1        is 
   13997  1.1        is A11_st:
   13998  1.1        is 	mov.l		USER_FPCR(%a6),L_SCR1(%a6)	# save it for later
   13999  1.1        is 	and.l		&0x00000030,USER_FPCR(%a6)	# set size to ext,
   14000  1.1        is #					;block exceptions
   14001  1.1        is 
   14002  1.1        is 
   14003  1.1        is # A12. Calculate YINT = FINT(Y) according to user's rounding mode.
   14004  1.1        is #      The FPSP routine sintd0 is used.  The output is in fp0.
   14005  1.1        is #
   14006  1.1        is # Register usage:
   14007  1.1        is #	Input/Output
   14008  1.1        is #	d0: FPSR with AINEX cleared/FPCR with size set to ext
   14009  1.1        is #	d2: x/x/scratch
   14010  1.1        is #	d3: x/x
   14011  1.1        is #	d4: LEN/Unchanged
   14012  1.1        is #	d5: ICTR:LAMBDA/Unchanged
   14013  1.1        is #	d6: ILOG/Unchanged
   14014  1.1        is #	d7: k-factor/Unchanged
   14015  1.1        is #	a0: ptr for original operand/src ptr for sintdo
   14016  1.1        is #	a1: ptr to PTENxx array/Unchanged
   14017  1.1        is #	a2: ptr to FP_SCR1(a6)/Unchanged
   14018  1.1        is #	a6: temp pointer to FP_SCR1(a6) - orig value saved and restored
   14019  1.1        is #	fp0: Y/YINT
   14020  1.1        is #	fp1: 10^ISCALE/Unchanged
   14021  1.1        is #	fp2: x/x
   14022  1.1        is #	F_SCR1:x/x
   14023  1.1        is #	F_SCR2:Y adjusted for inex/Y with original exponent
   14024  1.1        is #	L_SCR1:x/original USER_FPCR
   14025  1.1        is #	L_SCR2:first word of X packed/Unchanged
   14026  1.1        is 
   14027  1.1        is A12_st:
   14028  1.1        is 	movm.l	&0xc0c0,-(%sp)	# save regs used by sintd0	 {%d0-%d1/%a0-%a1}
   14029  1.1        is 	mov.l	L_SCR1(%a6),-(%sp)
   14030  1.1        is 	mov.l	L_SCR2(%a6),-(%sp)
   14031  1.1        is 
   14032  1.1        is 	lea.l		FP_SCR1(%a6),%a0	# a0 is ptr to FP_SCR1(a6)
   14033  1.1        is 	fmov.x		%fp0,(%a0)	# move Y to memory at FP_SCR1(a6)
   14034  1.1        is 	tst.l		L_SCR2(%a6)	# test sign of original operand
   14035  1.1        is 	bge.b		do_fint12		# if pos, use Y
   14036  1.1        is 	or.l		&0x80000000,(%a0)	# if neg, use -Y
   14037  1.1        is do_fint12:
   14038  1.1        is 	mov.l	USER_FPSR(%a6),-(%sp)
   14039  1.1        is #	bsr	sintdo		# sint routine returns int in fp0
   14040  1.1        is 
   14041  1.1        is 	fmov.l	USER_FPCR(%a6),%fpcr
   14042  1.1        is 	fmov.l	&0x0,%fpsr			# clear the AEXC bits!!!
   14043  1.1        is ##	mov.l		USER_FPCR(%a6),%d0	# ext prec/keep rnd mode
   14044  1.1        is ##	andi.l		&0x00000030,%d0
   14045  1.1        is ##	fmov.l		%d0,%fpcr
   14046  1.1        is 	fint.x		FP_SCR1(%a6),%fp0	# do fint()
   14047  1.1        is 	fmov.l	%fpsr,%d0
   14048  1.1        is 	or.w	%d0,FPSR_EXCEPT(%a6)
   14049  1.1        is ##	fmov.l		&0x0,%fpcr
   14050  1.1        is ##	fmov.l		%fpsr,%d0		# don't keep ccodes
   14051  1.1        is ##	or.w		%d0,FPSR_EXCEPT(%a6)
   14052  1.1        is 
   14053  1.1        is 	mov.b	(%sp),USER_FPSR(%a6)
   14054  1.1        is 	add.l	&4,%sp
   14055  1.1        is 
   14056  1.1        is 	mov.l	(%sp)+,L_SCR2(%a6)
   14057  1.1        is 	mov.l	(%sp)+,L_SCR1(%a6)
   14058  1.1        is 	movm.l	(%sp)+,&0x303	# restore regs used by sint	 {%d0-%d1/%a0-%a1}
   14059  1.1        is 
   14060  1.1        is 	mov.l	L_SCR2(%a6),FP_SCR1(%a6)	# restore original exponent
   14061  1.1        is 	mov.l	L_SCR1(%a6),USER_FPCR(%a6)	# restore user's FPCR
   14062  1.1        is 
   14063  1.1        is # A13. Check for LEN digits.
   14064  1.1        is #      If the int operation results in more than LEN digits,
   14065  1.1        is #      or less than LEN -1 digits, adjust ILOG and repeat from
   14066  1.1        is #      A6.  This test occurs only on the first pass.  If the
   14067  1.1        is #      result is exactly 10^LEN, decrement ILOG and divide
   14068  1.1        is #      the mantissa by 10.  The calculation of 10^LEN cannot
   14069  1.1        is #      be inexact, since all powers of ten upto 10^27 are exact
   14070  1.1        is #      in extended precision, so the use of a previous power-of-ten
   14071  1.1        is #      table will introduce no error.
   14072  1.1        is #
   14073  1.1        is #
   14074  1.1        is # Register usage:
   14075  1.1        is #	Input/Output
   14076  1.1        is #	d0: FPCR with size set to ext/scratch final = 0
   14077  1.1        is #	d2: x/x
   14078  1.1        is #	d3: x/scratch final = x
   14079  1.1        is #	d4: LEN/LEN adjusted
   14080  1.1        is #	d5: ICTR:LAMBDA/LAMBDA:ICTR
   14081  1.1        is #	d6: ILOG/ILOG adjusted
   14082  1.1        is #	d7: k-factor/Unchanged
   14083  1.1        is #	a0: pointer into memory for packed bcd string formation
   14084  1.1        is #	a1: ptr to PTENxx array/Unchanged
   14085  1.1        is #	a2: ptr to FP_SCR1(a6)/Unchanged
   14086  1.1        is #	fp0: int portion of Y/abs(YINT) adjusted
   14087  1.1        is #	fp1: 10^ISCALE/Unchanged
   14088  1.1        is #	fp2: x/10^LEN
   14089  1.1        is #	F_SCR1:x/x
   14090  1.1        is #	F_SCR2:Y with original exponent/Unchanged
   14091  1.1        is #	L_SCR1:original USER_FPCR/Unchanged
   14092  1.1        is #	L_SCR2:first word of X packed/Unchanged
   14093  1.1        is 
   14094  1.1        is A13_st:
   14095  1.1        is 	swap		%d5		# put ICTR in lower word of d5
   14096  1.1        is 	tst.w		%d5		# check if ICTR = 0
   14097  1.1        is 	bne		not_zr		# if non-zero, go to second test
   14098  1.1        is #
   14099  1.1        is # Compute 10^(LEN-1)
   14100  1.1        is #
   14101  1.1        is 	fmov.s		FONE(%pc),%fp2	# init fp2 to 1.0
   14102  1.1        is 	mov.l		%d4,%d0		# put LEN in d0
   14103  1.1        is 	subq.l		&1,%d0		# d0 = LEN -1
   14104  1.1        is 	clr.l		%d3		# clr table index
   14105  1.1        is l_loop:
   14106  1.1        is 	lsr.l		&1,%d0		# shift next bit into carry
   14107  1.1        is 	bcc.b		l_next		# if zero, skip the mul
   14108  1.1        is 	fmul.x		(%a1,%d3),%fp2	# mul by 10**(d3_bit_no)
   14109  1.1        is l_next:
   14110  1.1        is 	add.l		&12,%d3		# inc d3 to next pwrten table entry
   14111  1.1        is 	tst.l		%d0		# test if LEN is zero
   14112  1.1        is 	bne.b		l_loop		# if not, loop
   14113  1.1        is #
   14114  1.1        is # 10^LEN-1 is computed for this test and A14.  If the input was
   14115  1.1        is # denormalized, check only the case in which YINT > 10^LEN.
   14116  1.1        is #
   14117  1.1        is 	tst.b		BINDEC_FLG(%a6)	# check if input was norm
   14118  1.1        is 	beq.b		A13_con		# if norm, continue with checking
   14119  1.1        is 	fabs.x		%fp0		# take abs of YINT
   14120  1.1        is 	bra		test_2
   14121  1.1        is #
   14122  1.1        is # Compare abs(YINT) to 10^(LEN-1) and 10^LEN
   14123  1.1        is #
   14124  1.1        is A13_con:
   14125  1.1        is 	fabs.x		%fp0		# take abs of YINT
   14126  1.1        is 	fcmp.x		%fp0,%fp2	# compare abs(YINT) with 10^(LEN-1)
   14127  1.1        is 	fbge.w		test_2		# if greater, do next test
   14128  1.1        is 	subq.l		&1,%d6		# subtract 1 from ILOG
   14129  1.1        is 	mov.w		&1,%d5		# set ICTR
   14130  1.1        is 	fmov.l		&rm_mode*0x10,%fpcr	# set rmode to RM
   14131  1.1        is 	fmul.s		FTEN(%pc),%fp2	# compute 10^LEN
   14132  1.1        is 	bra.w		A6_str		# return to A6 and recompute YINT
   14133  1.1        is test_2:
   14134  1.1        is 	fmul.s		FTEN(%pc),%fp2	# compute 10^LEN
   14135  1.1        is 	fcmp.x		%fp0,%fp2	# compare abs(YINT) with 10^LEN
   14136  1.1        is 	fblt.w		A14_st		# if less, all is ok, go to A14
   14137  1.1        is 	fbgt.w		fix_ex		# if greater, fix and redo
   14138  1.1        is 	fdiv.s		FTEN(%pc),%fp0	# if equal, divide by 10
   14139  1.1        is 	addq.l		&1,%d6		# and inc ILOG
   14140  1.1        is 	bra.b		A14_st		# and continue elsewhere
   14141  1.1        is fix_ex:
   14142  1.1        is 	addq.l		&1,%d6		# increment ILOG by 1
   14143  1.1        is 	mov.w		&1,%d5		# set ICTR
   14144  1.1        is 	fmov.l		&rm_mode*0x10,%fpcr	# set rmode to RM
   14145  1.1        is 	bra.w		A6_str		# return to A6 and recompute YINT
   14146  1.1        is #
   14147  1.1        is # Since ICTR <> 0, we have already been through one adjustment,
   14148  1.1        is # and shouldn't have another; this is to check if abs(YINT) = 10^LEN
   14149  1.1        is # 10^LEN is again computed using whatever table is in a1 since the
   14150  1.1        is # value calculated cannot be inexact.
   14151  1.1        is #
   14152  1.1        is not_zr:
   14153  1.1        is 	fmov.s		FONE(%pc),%fp2	# init fp2 to 1.0
   14154  1.1        is 	mov.l		%d4,%d0		# put LEN in d0
   14155  1.1        is 	clr.l		%d3		# clr table index
   14156  1.1        is z_loop:
   14157  1.1        is 	lsr.l		&1,%d0		# shift next bit into carry
   14158  1.1        is 	bcc.b		z_next		# if zero, skip the mul
   14159  1.1        is 	fmul.x		(%a1,%d3),%fp2	# mul by 10**(d3_bit_no)
   14160  1.1        is z_next:
   14161  1.1        is 	add.l		&12,%d3		# inc d3 to next pwrten table entry
   14162  1.1        is 	tst.l		%d0		# test if LEN is zero
   14163  1.1        is 	bne.b		z_loop		# if not, loop
   14164  1.1        is 	fabs.x		%fp0		# get abs(YINT)
   14165  1.1        is 	fcmp.x		%fp0,%fp2	# check if abs(YINT) = 10^LEN
   14166  1.1        is 	fbneq.w		A14_st		# if not, skip this
   14167  1.1        is 	fdiv.s		FTEN(%pc),%fp0	# divide abs(YINT) by 10
   14168  1.1        is 	addq.l		&1,%d6		# and inc ILOG by 1
   14169  1.1        is 	addq.l		&1,%d4		# and inc LEN
   14170  1.1        is 	fmul.s		FTEN(%pc),%fp2	# if LEN++, the get 10^^LEN
   14171  1.1        is 
   14172  1.1        is # A14. Convert the mantissa to bcd.
   14173  1.1        is #      The binstr routine is used to convert the LEN digit
   14174  1.1        is #      mantissa to bcd in memory.  The input to binstr is
   14175  1.1        is #      to be a fraction; i.e. (mantissa)/10^LEN and adjusted
   14176  1.1        is #      such that the decimal point is to the left of bit 63.
   14177  1.1        is #      The bcd digits are stored in the correct position in
   14178  1.1        is #      the final string area in memory.
   14179  1.1        is #
   14180  1.1        is #
   14181  1.1        is # Register usage:
   14182  1.1        is #	Input/Output
   14183  1.1        is #	d0: x/LEN call to binstr - final is 0
   14184  1.1        is #	d1: x/0
   14185  1.1        is #	d2: x/ms 32-bits of mant of abs(YINT)
   14186  1.1        is #	d3: x/ls 32-bits of mant of abs(YINT)
   14187  1.1        is #	d4: LEN/Unchanged
   14188  1.1        is #	d5: ICTR:LAMBDA/LAMBDA:ICTR
   14189  1.1        is #	d6: ILOG
   14190  1.1        is #	d7: k-factor/Unchanged
   14191  1.1        is #	a0: pointer into memory for packed bcd string formation
   14192  1.1        is #	    /ptr to first mantissa byte in result string
   14193  1.1        is #	a1: ptr to PTENxx array/Unchanged
   14194  1.1        is #	a2: ptr to FP_SCR1(a6)/Unchanged
   14195  1.1        is #	fp0: int portion of Y/abs(YINT) adjusted
   14196  1.1        is #	fp1: 10^ISCALE/Unchanged
   14197  1.1        is #	fp2: 10^LEN/Unchanged
   14198  1.1        is #	F_SCR1:x/Work area for final result
   14199  1.1        is #	F_SCR2:Y with original exponent/Unchanged
   14200  1.1        is #	L_SCR1:original USER_FPCR/Unchanged
   14201  1.1        is #	L_SCR2:first word of X packed/Unchanged
   14202  1.1        is 
   14203  1.1        is A14_st:
   14204  1.1        is 	fmov.l		&rz_mode*0x10,%fpcr	# force rz for conversion
   14205  1.1        is 	fdiv.x		%fp2,%fp0	# divide abs(YINT) by 10^LEN
   14206  1.1        is 	lea.l		FP_SCR0(%a6),%a0
   14207  1.1        is 	fmov.x		%fp0,(%a0)	# move abs(YINT)/10^LEN to memory
   14208  1.1        is 	mov.l		4(%a0),%d2	# move 2nd word of FP_RES to d2
   14209  1.1        is 	mov.l		8(%a0),%d3	# move 3rd word of FP_RES to d3
   14210  1.1        is 	clr.l		4(%a0)		# zero word 2 of FP_RES
   14211  1.1        is 	clr.l		8(%a0)		# zero word 3 of FP_RES
   14212  1.1        is 	mov.l		(%a0),%d0	# move exponent to d0
   14213  1.1        is 	swap		%d0		# put exponent in lower word
   14214  1.1        is 	beq.b		no_sft		# if zero, don't shift
   14215  1.1        is 	sub.l		&0x3ffd,%d0	# sub bias less 2 to make fract
   14216  1.1        is 	tst.l		%d0		# check if > 1
   14217  1.1        is 	bgt.b		no_sft		# if so, don't shift
   14218  1.1        is 	neg.l		%d0		# make exp positive
   14219  1.1        is m_loop:
   14220  1.1        is 	lsr.l		&1,%d2		# shift d2:d3 right, add 0s
   14221  1.1        is 	roxr.l		&1,%d3		# the number of places
   14222  1.1        is 	dbf.w		%d0,m_loop	# given in d0
   14223  1.1        is no_sft:
   14224  1.1        is 	tst.l		%d2		# check for mantissa of zero
   14225  1.1        is 	bne.b		no_zr		# if not, go on
   14226  1.1        is 	tst.l		%d3		# continue zero check
   14227  1.1        is 	beq.b		zer_m		# if zero, go directly to binstr
   14228  1.1        is no_zr:
   14229  1.1        is 	clr.l		%d1		# put zero in d1 for addx
   14230  1.1        is 	add.l		&0x00000080,%d3	# inc at bit 7
   14231  1.1        is 	addx.l		%d1,%d2		# continue inc
   14232  1.1        is 	and.l		&0xffffff80,%d3	# strip off lsb not used by 882
   14233  1.1        is zer_m:
   14234  1.1        is 	mov.l		%d4,%d0		# put LEN in d0 for binstr call
   14235  1.1        is 	addq.l		&3,%a0		# a0 points to M16 byte in result
   14236  1.1        is 	bsr		binstr		# call binstr to convert mant
   14237  1.1        is 
   14238  1.1        is 
   14239  1.1        is # A15. Convert the exponent to bcd.
   14240  1.1        is #      As in A14 above, the exp is converted to bcd and the
   14241  1.1        is #      digits are stored in the final string.
   14242  1.1        is #
   14243  1.1        is #      Digits are stored in L_SCR1(a6) on return from BINDEC as:
   14244  1.1        is #
   14245  1.1        is #  	 32               16 15                0
   14246  1.1        is #	-----------------------------------------
   14247  1.1        is #  	|  0 | e3 | e2 | e1 | e4 |  X |  X |  X |
   14248  1.1        is #	-----------------------------------------
   14249  1.1        is #
   14250  1.1        is # And are moved into their proper places in FP_SCR0.  If digit e4
   14251  1.1        is # is non-zero, OPERR is signaled.  In all cases, all 4 digits are
   14252  1.1        is # written as specified in the 881/882 manual for packed decimal.
   14253  1.1        is #
   14254  1.1        is # Register usage:
   14255  1.1        is #	Input/Output
   14256  1.1        is #	d0: x/LEN call to binstr - final is 0
   14257  1.1        is #	d1: x/scratch (0);shift count for final exponent packing
   14258  1.1        is #	d2: x/ms 32-bits of exp fraction/scratch
   14259  1.1        is #	d3: x/ls 32-bits of exp fraction
   14260  1.1        is #	d4: LEN/Unchanged
   14261  1.1        is #	d5: ICTR:LAMBDA/LAMBDA:ICTR
   14262  1.1        is #	d6: ILOG
   14263  1.1        is #	d7: k-factor/Unchanged
   14264  1.1        is #	a0: ptr to result string/ptr to L_SCR1(a6)
   14265  1.1        is #	a1: ptr to PTENxx array/Unchanged
   14266  1.1        is #	a2: ptr to FP_SCR1(a6)/Unchanged
   14267  1.1        is #	fp0: abs(YINT) adjusted/float(ILOG)
   14268  1.1        is #	fp1: 10^ISCALE/Unchanged
   14269  1.1        is #	fp2: 10^LEN/Unchanged
   14270  1.1        is #	F_SCR1:Work area for final result/BCD result
   14271  1.1        is #	F_SCR2:Y with original exponent/ILOG/10^4
   14272  1.1        is #	L_SCR1:original USER_FPCR/Exponent digits on return from binstr
   14273  1.1        is #	L_SCR2:first word of X packed/Unchanged
   14274  1.1        is 
   14275  1.1        is A15_st:
   14276  1.1        is 	tst.b		BINDEC_FLG(%a6)	# check for denorm
   14277  1.1        is 	beq.b		not_denorm
   14278  1.1        is 	ftest.x		%fp0		# test for zero
   14279  1.1        is 	fbeq.w		den_zero	# if zero, use k-factor or 4933
   14280  1.1        is 	fmov.l		%d6,%fp0	# float ILOG
   14281  1.1        is 	fabs.x		%fp0		# get abs of ILOG
   14282  1.1        is 	bra.b		convrt
   14283  1.1        is den_zero:
   14284  1.1        is 	tst.l		%d7		# check sign of the k-factor
   14285  1.1        is 	blt.b		use_ilog	# if negative, use ILOG
   14286  1.1        is 	fmov.s		F4933(%pc),%fp0	# force exponent to 4933
   14287  1.1        is 	bra.b		convrt		# do it
   14288  1.1        is use_ilog:
   14289  1.1        is 	fmov.l		%d6,%fp0	# float ILOG
   14290  1.1        is 	fabs.x		%fp0		# get abs of ILOG
   14291  1.1        is 	bra.b		convrt
   14292  1.1        is not_denorm:
   14293  1.1        is 	ftest.x		%fp0		# test for zero
   14294  1.1        is 	fbneq.w		not_zero	# if zero, force exponent
   14295  1.1        is 	fmov.s		FONE(%pc),%fp0	# force exponent to 1
   14296  1.1        is 	bra.b		convrt		# do it
   14297  1.1        is not_zero:
   14298  1.1        is 	fmov.l		%d6,%fp0	# float ILOG
   14299  1.1        is 	fabs.x		%fp0		# get abs of ILOG
   14300  1.1        is convrt:
   14301  1.1        is 	fdiv.x		24(%a1),%fp0	# compute ILOG/10^4
   14302  1.1        is 	fmov.x		%fp0,FP_SCR1(%a6)	# store fp0 in memory
   14303  1.1        is 	mov.l		4(%a2),%d2	# move word 2 to d2
   14304  1.1        is 	mov.l		8(%a2),%d3	# move word 3 to d3
   14305  1.1        is 	mov.w		(%a2),%d0	# move exp to d0
   14306  1.1        is 	beq.b		x_loop_fin	# if zero, skip the shift
   14307  1.1        is 	sub.w		&0x3ffd,%d0	# subtract off bias
   14308  1.1        is 	neg.w		%d0		# make exp positive
   14309  1.1        is x_loop:
   14310  1.1        is 	lsr.l		&1,%d2		# shift d2:d3 right
   14311  1.1        is 	roxr.l		&1,%d3		# the number of places
   14312  1.1        is 	dbf.w		%d0,x_loop	# given in d0
   14313  1.1        is x_loop_fin:
   14314  1.1        is 	clr.l		%d1		# put zero in d1 for addx
   14315  1.1        is 	add.l		&0x00000080,%d3	# inc at bit 6
   14316  1.1        is 	addx.l		%d1,%d2		# continue inc
   14317  1.1        is 	and.l		&0xffffff80,%d3	# strip off lsb not used by 882
   14318  1.1        is 	mov.l		&4,%d0		# put 4 in d0 for binstr call
   14319  1.1        is 	lea.l		L_SCR1(%a6),%a0	# a0 is ptr to L_SCR1 for exp digits
   14320  1.1        is 	bsr		binstr		# call binstr to convert exp
   14321  1.1        is 	mov.l		L_SCR1(%a6),%d0	# load L_SCR1 lword to d0
   14322  1.1        is 	mov.l		&12,%d1		# use d1 for shift count
   14323  1.1        is 	lsr.l		%d1,%d0		# shift d0 right by 12
   14324  1.1        is 	bfins		%d0,FP_SCR0(%a6){&4:&12}	# put e3:e2:e1 in FP_SCR0
   14325  1.1        is 	lsr.l		%d1,%d0		# shift d0 right by 12
   14326  1.1        is 	bfins		%d0,FP_SCR0(%a6){&16:&4}	# put e4 in FP_SCR0
   14327  1.1        is 	tst.b		%d0		# check if e4 is zero
   14328  1.1        is 	beq.b		A16_st		# if zero, skip rest
   14329  1.1        is 	or.l		&opaop_mask,USER_FPSR(%a6)	# set OPERR & AIOP in USER_FPSR
   14330  1.1        is 
   14331  1.1        is 
   14332  1.1        is # A16. Write sign bits to final string.
   14333  1.1        is #	   Sigma is bit 31 of initial value; RHO is bit 31 of d6 (ILOG).
   14334  1.1        is #
   14335  1.1        is # Register usage:
   14336  1.1        is #	Input/Output
   14337  1.1        is #	d0: x/scratch - final is x
   14338  1.1        is #	d2: x/x
   14339  1.1        is #	d3: x/x
   14340  1.1        is #	d4: LEN/Unchanged
   14341  1.1        is #	d5: ICTR:LAMBDA/LAMBDA:ICTR
   14342  1.1        is #	d6: ILOG/ILOG adjusted
   14343  1.1        is #	d7: k-factor/Unchanged
   14344  1.1        is #	a0: ptr to L_SCR1(a6)/Unchanged
   14345  1.1        is #	a1: ptr to PTENxx array/Unchanged
   14346  1.1        is #	a2: ptr to FP_SCR1(a6)/Unchanged
   14347  1.1        is #	fp0: float(ILOG)/Unchanged
   14348  1.1        is #	fp1: 10^ISCALE/Unchanged
   14349  1.1        is #	fp2: 10^LEN/Unchanged
   14350  1.1        is #	F_SCR1:BCD result with correct signs
   14351  1.1        is #	F_SCR2:ILOG/10^4
   14352  1.1        is #	L_SCR1:Exponent digits on return from binstr
   14353  1.1        is #	L_SCR2:first word of X packed/Unchanged
   14354  1.1        is 
   14355  1.1        is A16_st:
   14356  1.1        is 	clr.l		%d0		# clr d0 for collection of signs
   14357  1.1        is 	and.b		&0x0f,FP_SCR0(%a6)	# clear first nibble of FP_SCR0
   14358  1.1        is 	tst.l		L_SCR2(%a6)	# check sign of original mantissa
   14359  1.1        is 	bge.b		mant_p		# if pos, don't set SM
   14360  1.1        is 	mov.l		&2,%d0		# move 2 in to d0 for SM
   14361  1.1        is mant_p:
   14362  1.1        is 	tst.l		%d6		# check sign of ILOG
   14363  1.1        is 	bge.b		wr_sgn		# if pos, don't set SE
   14364  1.1        is 	addq.l		&1,%d0		# set bit 0 in d0 for SE
   14365  1.1        is wr_sgn:
   14366  1.1        is 	bfins		%d0,FP_SCR0(%a6){&0:&2}	# insert SM and SE into FP_SCR0
   14367  1.1        is 
   14368  1.1        is # Clean up and restore all registers used.
   14369  1.1        is 
   14370  1.1        is 	fmov.l		&0,%fpsr	# clear possible inex2/ainex bits
   14371  1.1        is 	fmovm.x		(%sp)+,&0xe0	#  {%fp0-%fp2}
   14372  1.1        is 	movm.l		(%sp)+,&0x4fc	#  {%d2-%d7/%a2}
   14373  1.1        is 	rts
   14374  1.1        is 
   14375  1.1        is 	global		PTENRN
   14376  1.1        is PTENRN:
   14377  1.1        is 	long		0x40020000,0xA0000000,0x00000000	# 10 ^ 1
   14378  1.1        is 	long		0x40050000,0xC8000000,0x00000000	# 10 ^ 2
   14379  1.1        is 	long		0x400C0000,0x9C400000,0x00000000	# 10 ^ 4
   14380  1.1        is 	long		0x40190000,0xBEBC2000,0x00000000	# 10 ^ 8
   14381  1.1        is 	long		0x40340000,0x8E1BC9BF,0x04000000	# 10 ^ 16
   14382  1.1        is 	long		0x40690000,0x9DC5ADA8,0x2B70B59E	# 10 ^ 32
   14383  1.1        is 	long		0x40D30000,0xC2781F49,0xFFCFA6D5	# 10 ^ 64
   14384  1.1        is 	long		0x41A80000,0x93BA47C9,0x80E98CE0	# 10 ^ 128
   14385  1.1        is 	long		0x43510000,0xAA7EEBFB,0x9DF9DE8E	# 10 ^ 256
   14386  1.1        is 	long		0x46A30000,0xE319A0AE,0xA60E91C7	# 10 ^ 512
   14387  1.1        is 	long		0x4D480000,0xC9767586,0x81750C17	# 10 ^ 1024
   14388  1.1        is 	long		0x5A920000,0x9E8B3B5D,0xC53D5DE5	# 10 ^ 2048
   14389  1.1        is 	long		0x75250000,0xC4605202,0x8A20979B	# 10 ^ 4096
   14390  1.1        is 
   14391  1.1        is 	global		PTENRP
   14392  1.1        is PTENRP:
   14393  1.1        is 	long		0x40020000,0xA0000000,0x00000000	# 10 ^ 1
   14394  1.1        is 	long		0x40050000,0xC8000000,0x00000000	# 10 ^ 2
   14395  1.1        is 	long		0x400C0000,0x9C400000,0x00000000	# 10 ^ 4
   14396  1.1        is 	long		0x40190000,0xBEBC2000,0x00000000	# 10 ^ 8
   14397  1.1        is 	long		0x40340000,0x8E1BC9BF,0x04000000	# 10 ^ 16
   14398  1.1        is 	long		0x40690000,0x9DC5ADA8,0x2B70B59E	# 10 ^ 32
   14399  1.1        is 	long		0x40D30000,0xC2781F49,0xFFCFA6D6	# 10 ^ 64
   14400  1.1        is 	long		0x41A80000,0x93BA47C9,0x80E98CE0	# 10 ^ 128
   14401  1.1        is 	long		0x43510000,0xAA7EEBFB,0x9DF9DE8E	# 10 ^ 256
   14402  1.1        is 	long		0x46A30000,0xE319A0AE,0xA60E91C7	# 10 ^ 512
   14403  1.1        is 	long		0x4D480000,0xC9767586,0x81750C18	# 10 ^ 1024
   14404  1.1        is 	long		0x5A920000,0x9E8B3B5D,0xC53D5DE5	# 10 ^ 2048
   14405  1.1        is 	long		0x75250000,0xC4605202,0x8A20979B	# 10 ^ 4096
   14406  1.1        is 
   14407  1.1        is 	global		PTENRM
   14408  1.1        is PTENRM:
   14409  1.1        is 	long		0x40020000,0xA0000000,0x00000000	# 10 ^ 1
   14410  1.1        is 	long		0x40050000,0xC8000000,0x00000000	# 10 ^ 2
   14411  1.1        is 	long		0x400C0000,0x9C400000,0x00000000	# 10 ^ 4
   14412  1.1        is 	long		0x40190000,0xBEBC2000,0x00000000	# 10 ^ 8
   14413  1.1        is 	long		0x40340000,0x8E1BC9BF,0x04000000	# 10 ^ 16
   14414  1.1        is 	long		0x40690000,0x9DC5ADA8,0x2B70B59D	# 10 ^ 32
   14415  1.1        is 	long		0x40D30000,0xC2781F49,0xFFCFA6D5	# 10 ^ 64
   14416  1.1        is 	long		0x41A80000,0x93BA47C9,0x80E98CDF	# 10 ^ 128
   14417  1.1        is 	long		0x43510000,0xAA7EEBFB,0x9DF9DE8D	# 10 ^ 256
   14418  1.1        is 	long		0x46A30000,0xE319A0AE,0xA60E91C6	# 10 ^ 512
   14419  1.1        is 	long		0x4D480000,0xC9767586,0x81750C17	# 10 ^ 1024
   14420  1.1        is 	long		0x5A920000,0x9E8B3B5D,0xC53D5DE4	# 10 ^ 2048
   14421  1.1        is 	long		0x75250000,0xC4605202,0x8A20979A	# 10 ^ 4096
   14422  1.1        is 
   14423  1.1        is #########################################################################
   14424  1.1        is # binstr(): Converts a 64-bit binary integer to bcd.			#
   14425  1.1        is #									#
   14426  1.1        is # INPUT *************************************************************** #
   14427  1.1        is #	d2:d3 = 64-bit binary integer					#
   14428  1.1        is #	d0    = desired length (LEN)					#
   14429  1.1        is #	a0    = pointer to start in memory for bcd characters		#
   14430  1.1        is #          	(This pointer must point to byte 4 of the first		#
   14431  1.1        is #          	 lword of the packed decimal memory string.)		#
   14432  1.1        is #									#
   14433  1.1        is # OUTPUT ************************************************************** #
   14434  1.1        is #	a0 = pointer to LEN bcd digits representing the 64-bit integer.	#
   14435  1.1        is #									#
   14436  1.1        is # ALGORITHM ***********************************************************	#
   14437  1.1        is #	The 64-bit binary is assumed to have a decimal point before	#
   14438  1.1        is #	bit 63.  The fraction is multiplied by 10 using a mul by 2	#
   14439  1.1        is #	shift and a mul by 8 shift.  The bits shifted out of the	#
   14440  1.1        is #	msb form a decimal digit.  This process is iterated until	#
   14441  1.1        is #	LEN digits are formed.						#
   14442  1.1        is #									#
   14443  1.1        is # A1. Init d7 to 1.  D7 is the byte digit counter, and if 1, the	#
   14444  1.1        is #     digit formed will be assumed the least significant.  This is	#
   14445  1.1        is #     to force the first byte formed to have a 0 in the upper 4 bits.	#
   14446  1.1        is #									#
   14447  1.1        is # A2. Beginning of the loop:						#
   14448  1.1        is #     Copy the fraction in d2:d3 to d4:d5.				#
   14449  1.1        is #									#
   14450  1.1        is # A3. Multiply the fraction in d2:d3 by 8 using bit-field		#
   14451  1.1        is #     extracts and shifts.  The three msbs from d2 will go into d1.	#
   14452  1.1        is #									#
   14453  1.1        is # A4. Multiply the fraction in d4:d5 by 2 using shifts.  The msb	#
   14454  1.1        is #     will be collected by the carry.					#
   14455  1.1        is #									#
   14456  1.1        is # A5. Add using the carry the 64-bit quantities in d2:d3 and d4:d5	#
   14457  1.1        is #     into d2:d3.  D1 will contain the bcd digit formed.		#
   14458  1.1        is #									#
   14459  1.1        is # A6. Test d7.  If zero, the digit formed is the ms digit.  If non-	#
   14460  1.1        is #     zero, it is the ls digit.  Put the digit in its place in the	#
   14461  1.1        is #     upper word of d0.  If it is the ls digit, write the word		#
   14462  1.1        is #     from d0 to memory.						#
   14463  1.1        is #									#
   14464  1.1        is # A7. Decrement d6 (LEN counter) and repeat the loop until zero.	#
   14465  1.1        is #									#
   14466  1.1        is #########################################################################
   14467  1.1        is 
   14468  1.1        is #	Implementation Notes:
   14469  1.1        is #
   14470  1.1        is #	The registers are used as follows:
   14471  1.1        is #
   14472  1.1        is #		d0: LEN counter
   14473  1.1        is #		d1: temp used to form the digit
   14474  1.1        is #		d2: upper 32-bits of fraction for mul by 8
   14475  1.1        is #		d3: lower 32-bits of fraction for mul by 8
   14476  1.1        is #		d4: upper 32-bits of fraction for mul by 2
   14477  1.1        is #		d5: lower 32-bits of fraction for mul by 2
   14478  1.1        is #		d6: temp for bit-field extracts
   14479  1.1        is #		d7: byte digit formation word;digit count {0,1}
   14480  1.1        is #		a0: pointer into memory for packed bcd string formation
   14481  1.1        is #
   14482  1.1        is 
   14483  1.1        is 	global		binstr
   14484  1.1        is binstr:
   14485  1.1        is 	movm.l		&0xff00,-(%sp)	#  {%d0-%d7}
   14486  1.1        is 
   14487  1.1        is #
   14488  1.1        is # A1: Init d7
   14489  1.1        is #
   14490  1.1        is 	mov.l		&1,%d7		# init d7 for second digit
   14491  1.1        is 	subq.l		&1,%d0		# for dbf d0 would have LEN+1 passes
   14492  1.1        is #
   14493  1.1        is # A2. Copy d2:d3 to d4:d5.  Start loop.
   14494  1.1        is #
   14495  1.1        is loop:
   14496  1.1        is 	mov.l		%d2,%d4		# copy the fraction before muls
   14497  1.1        is 	mov.l		%d3,%d5		# to d4:d5
   14498  1.1        is #
   14499  1.1        is # A3. Multiply d2:d3 by 8; extract msbs into d1.
   14500  1.1        is #
   14501  1.1        is 	bfextu		%d2{&0:&3},%d1	# copy 3 msbs of d2 into d1
   14502  1.1        is 	asl.l		&3,%d2		# shift d2 left by 3 places
   14503  1.1        is 	bfextu		%d3{&0:&3},%d6	# copy 3 msbs of d3 into d6
   14504  1.1        is 	asl.l		&3,%d3		# shift d3 left by 3 places
   14505  1.1        is 	or.l		%d6,%d2		# or in msbs from d3 into d2
   14506  1.1        is #
   14507  1.1        is # A4. Multiply d4:d5 by 2; add carry out to d1.
   14508  1.1        is #
   14509  1.1        is 	asl.l		&1,%d5		# mul d5 by 2
   14510  1.1        is 	roxl.l		&1,%d4		# mul d4 by 2
   14511  1.1        is 	swap		%d6		# put 0 in d6 lower word
   14512  1.1        is 	addx.w		%d6,%d1		# add in extend from mul by 2
   14513  1.1        is #
   14514  1.1        is # A5. Add mul by 8 to mul by 2.  D1 contains the digit formed.
   14515  1.1        is #
   14516  1.1        is 	add.l		%d5,%d3		# add lower 32 bits
   14517  1.1        is 	nop				# ERRATA FIX #13 (Rev. 1.2 6/6/90)
   14518  1.1        is 	addx.l		%d4,%d2		# add with extend upper 32 bits
   14519  1.1        is 	nop				# ERRATA FIX #13 (Rev. 1.2 6/6/90)
   14520  1.1        is 	addx.w		%d6,%d1		# add in extend from add to d1
   14521  1.1        is 	swap		%d6		# with d6 = 0; put 0 in upper word
   14522  1.1        is #
   14523  1.1        is # A6. Test d7 and branch.
   14524  1.1        is #
   14525  1.1        is 	tst.w		%d7		# if zero, store digit & to loop
   14526  1.1        is 	beq.b		first_d		# if non-zero, form byte & write
   14527  1.1        is sec_d:
   14528  1.1        is 	swap		%d7		# bring first digit to word d7b
   14529  1.1        is 	asl.w		&4,%d7		# first digit in upper 4 bits d7b
   14530  1.1        is 	add.w		%d1,%d7		# add in ls digit to d7b
   14531  1.1        is 	mov.b		%d7,(%a0)+	# store d7b byte in memory
   14532  1.1        is 	swap		%d7		# put LEN counter in word d7a
   14533  1.1        is 	clr.w		%d7		# set d7a to signal no digits done
   14534  1.1        is 	dbf.w		%d0,loop	# do loop some more!
   14535  1.1        is 	bra.b		end_bstr	# finished, so exit
   14536  1.1        is first_d:
   14537  1.1        is 	swap		%d7		# put digit word in d7b
   14538  1.1        is 	mov.w		%d1,%d7		# put new digit in d7b
   14539  1.1        is 	swap		%d7		# put LEN counter in word d7a
   14540  1.1        is 	addq.w		&1,%d7		# set d7a to signal first digit done
   14541  1.1        is 	dbf.w		%d0,loop	# do loop some more!
   14542  1.1        is 	swap		%d7		# put last digit in string
   14543  1.1        is 	lsl.w		&4,%d7		# move it to upper 4 bits
   14544  1.1        is 	mov.b		%d7,(%a0)+	# store it in memory string
   14545  1.1        is #
   14546  1.1        is # Clean up and return with result in fp0.
   14547  1.1        is #
   14548  1.1        is end_bstr:
   14549  1.1        is 	movm.l		(%sp)+,&0xff	#  {%d0-%d7}
   14550  1.1        is 	rts
   14551  1.1        is 
   14552  1.1        is #########################################################################
   14553  1.1        is # XDEF ****************************************************************	#
   14554  1.1        is #	facc_in_b(): dmem_read_byte failed				#
   14555  1.1        is #	facc_in_w(): dmem_read_word failed				#
   14556  1.1        is #	facc_in_l(): dmem_read_long failed				#
   14557  1.1        is #	facc_in_d(): dmem_read of dbl prec failed			#
   14558  1.1        is #	facc_in_x(): dmem_read of ext prec failed			#
   14559  1.1        is #									#
   14560  1.1        is #	facc_out_b(): dmem_write_byte failed				#
   14561  1.1        is #	facc_out_w(): dmem_write_word failed				#
   14562  1.1        is #	facc_out_l(): dmem_write_long failed				#
   14563  1.1        is #	facc_out_d(): dmem_write of dbl prec failed			#
   14564  1.1        is #	facc_out_x(): dmem_write of ext prec failed			#
   14565  1.1        is #									#
   14566  1.1        is # XREF ****************************************************************	#
   14567  1.1        is #	_real_access() - exit through access error handler		#
   14568  1.1        is #									#
   14569  1.1        is # INPUT ***************************************************************	#
   14570  1.1        is #	None								#
   14571  1.1        is # 									#
   14572  1.1        is # OUTPUT **************************************************************	#
   14573  1.1        is #	None								#
   14574  1.1        is #									#
   14575  1.1        is # ALGORITHM ***********************************************************	#
   14576  1.1        is # 	Flow jumps here when an FP data fetch call gets an error 	#
   14577  1.1        is # result. This means the operating system wants an access error frame	#
   14578  1.1        is # made out of the current exception stack frame. 			#
   14579  1.1        is #	So, we first call restore() which makes sure that any updated	#
   14580  1.1        is # -(an)+ register gets returned to its pre-exception value and then	#
   14581  1.1        is # we change the stack to an acess error stack frame.			#
   14582  1.1        is #									#
   14583  1.1        is #########################################################################
   14584  1.1        is 
   14585  1.1        is facc_in_b:
   14586  1.1        is 	movq.l		&0x1,%d0			# one byte
   14587  1.1        is 	bsr.w		restore				# fix An
   14588  1.1        is 
   14589  1.1        is 	mov.w		&0x0121,EXC_VOFF(%a6)		# set FSLW
   14590  1.1        is 	bra.w		facc_finish
   14591  1.1        is 
   14592  1.1        is facc_in_w:
   14593  1.1        is 	movq.l		&0x2,%d0			# two bytes
   14594  1.1        is 	bsr.w		restore				# fix An
   14595  1.1        is 
   14596  1.1        is 	mov.w		&0x0141,EXC_VOFF(%a6)		# set FSLW
   14597  1.1        is 	bra.b		facc_finish
   14598  1.1        is 
   14599  1.1        is facc_in_l:
   14600  1.1        is 	movq.l		&0x4,%d0			# four bytes
   14601  1.1        is 	bsr.w		restore				# fix An
   14602  1.1        is 
   14603  1.1        is 	mov.w		&0x0101,EXC_VOFF(%a6)		# set FSLW
   14604  1.1        is 	bra.b		facc_finish
   14605  1.1        is 
   14606  1.1        is facc_in_d:
   14607  1.1        is 	movq.l		&0x8,%d0			# eight bytes
   14608  1.1        is 	bsr.w		restore				# fix An
   14609  1.1        is 
   14610  1.1        is 	mov.w		&0x0161,EXC_VOFF(%a6)		# set FSLW
   14611  1.1        is 	bra.b		facc_finish
   14612  1.1        is 
   14613  1.1        is facc_in_x:
   14614  1.1        is 	movq.l		&0xc,%d0			# twelve bytes
   14615  1.1        is 	bsr.w		restore				# fix An
   14616  1.1        is 
   14617  1.1        is 	mov.w		&0x0161,EXC_VOFF(%a6)		# set FSLW
   14618  1.1        is 	bra.b		facc_finish
   14619  1.1        is 
   14620  1.1        is ################################################################
   14621  1.1        is 
   14622  1.1        is facc_out_b:
   14623  1.1        is 	movq.l		&0x1,%d0			# one byte
   14624  1.1        is 	bsr.w		restore				# restore An
   14625  1.1        is 
   14626  1.1        is 	mov.w		&0x00a1,EXC_VOFF(%a6)		# set FSLW
   14627  1.1        is 	bra.b		facc_finish
   14628  1.1        is 
   14629  1.1        is facc_out_w:
   14630  1.1        is 	movq.l		&0x2,%d0			# two bytes
   14631  1.1        is 	bsr.w		restore				# restore An
   14632  1.1        is 
   14633  1.1        is 	mov.w		&0x00c1,EXC_VOFF(%a6)		# set FSLW
   14634  1.1        is 	bra.b		facc_finish
   14635  1.1        is 
   14636  1.1        is facc_out_l:
   14637  1.1        is 	movq.l		&0x4,%d0			# four bytes
   14638  1.1        is 	bsr.w		restore				# restore An
   14639  1.1        is 
   14640  1.1        is 	mov.w		&0x0081,EXC_VOFF(%a6)		# set FSLW
   14641  1.1        is 	bra.b		facc_finish
   14642  1.1        is 
   14643  1.1        is facc_out_d:
   14644  1.1        is 	movq.l		&0x8,%d0			# eight bytes
   14645  1.1        is 	bsr.w		restore				# restore An
   14646  1.1        is 
   14647  1.1        is 	mov.w		&0x00e1,EXC_VOFF(%a6)		# set FSLW
   14648  1.1        is 	bra.b		facc_finish
   14649  1.1        is 
   14650  1.1        is facc_out_x:
   14651  1.1        is 	mov.l		&0xc,%d0			# twelve bytes
   14652  1.1        is 	bsr.w		restore				# restore An
   14653  1.1        is 
   14654  1.1        is 	mov.w		&0x00e1,EXC_VOFF(%a6)		# set FSLW
   14655  1.1        is 
   14656  1.1        is # here's where we actually create the access error frame from the
   14657  1.1        is # current exception stack frame.
   14658  1.1        is facc_finish:
   14659  1.1        is 	mov.l		USER_FPIAR(%a6),EXC_PC(%a6) # store current PC
   14660  1.1        is 
   14661  1.1        is 	fmovm.x		EXC_FPREGS(%a6),&0xc0	# restore fp0-fp1
   14662  1.1        is 	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
   14663  1.1        is 	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
   14664  1.1        is 
   14665  1.1        is 	unlk		%a6
   14666  1.1        is 
   14667  1.1        is 	mov.l		(%sp),-(%sp)		# store SR, hi(PC)
   14668  1.1        is 	mov.l		0x8(%sp),0x4(%sp)	# store lo(PC)
   14669  1.1        is 	mov.l		0xc(%sp),0x8(%sp)	# store EA
   14670  1.1        is 	mov.l		&0x00000001,0xc(%sp)	# store FSLW
   14671  1.1        is 	mov.w		0x6(%sp),0xc(%sp)	# fix FSLW (size)
   14672  1.1        is 	mov.w		&0x4008,0x6(%sp)	# store voff
   14673  1.1        is 
   14674  1.1        is 	btst		&0x5,(%sp)		# supervisor or user mode?
   14675  1.1        is 	beq.b		facc_out2		# user
   14676  1.1        is 	bset		&0x2,0xd(%sp)		# set supervisor TM bit
   14677  1.1        is 
   14678  1.1        is facc_out2:
   14679  1.1        is 	bra.l		_real_access
   14680  1.1        is 
   14681  1.1        is ##################################################################
   14682  1.1        is 
   14683  1.1        is # if the effective addressing mode was predecrement or postincrement,
   14684  1.1        is # the emulation has already changed its value to the correct post-
   14685  1.1        is # instruction value. but since we're exiting to the access error
   14686  1.1        is # handler, then AN must be returned to its pre-instruction value.
   14687  1.1        is # we do that here.
   14688  1.1        is restore:
   14689  1.1        is 	mov.b		EXC_OPWORD+0x1(%a6),%d1
   14690  1.1        is 	andi.b		&0x38,%d1		# extract opmode
   14691  1.1        is 	cmpi.b		%d1,&0x18		# postinc?
   14692  1.1        is 	beq.w		rest_inc
   14693  1.1        is 	cmpi.b		%d1,&0x20		# predec?
   14694  1.1        is 	beq.w		rest_dec
   14695  1.1        is 	rts
   14696  1.1        is 
   14697  1.1        is rest_inc:
   14698  1.1        is 	mov.b		EXC_OPWORD+0x1(%a6),%d1
   14699  1.1        is 	andi.w		&0x0007,%d1		# fetch An
   14700  1.1        is 
   14701  1.1        is 	mov.w		(tbl_rest_inc.b,%pc,%d1.w*2),%d1
   14702  1.1        is 	jmp		(tbl_rest_inc.b,%pc,%d1.w*1)
   14703  1.1        is 
   14704  1.1        is tbl_rest_inc:
   14705  1.1        is 	short		ri_a0 - tbl_rest_inc
   14706  1.1        is 	short		ri_a1 - tbl_rest_inc
   14707  1.1        is 	short		ri_a2 - tbl_rest_inc
   14708  1.1        is 	short		ri_a3 - tbl_rest_inc
   14709  1.1        is 	short		ri_a4 - tbl_rest_inc
   14710  1.1        is 	short		ri_a5 - tbl_rest_inc
   14711  1.1        is 	short		ri_a6 - tbl_rest_inc
   14712  1.1        is 	short		ri_a7 - tbl_rest_inc
   14713  1.1        is 
   14714  1.1        is ri_a0:
   14715  1.1        is 	sub.l		%d0,EXC_DREGS+0x8(%a6)	# fix stacked a0
   14716  1.1        is 	rts
   14717  1.1        is ri_a1:
   14718  1.1        is 	sub.l		%d0,EXC_DREGS+0xc(%a6)	# fix stacked a1
   14719  1.1        is 	rts
   14720  1.1        is ri_a2:
   14721  1.1        is 	sub.l		%d0,%a2			# fix a2
   14722  1.1        is 	rts
   14723  1.1        is ri_a3:
   14724  1.1        is 	sub.l		%d0,%a3			# fix a3
   14725  1.1        is 	rts
   14726  1.1        is ri_a4:
   14727  1.1        is 	sub.l		%d0,%a4			# fix a4
   14728  1.1        is 	rts
   14729  1.1        is ri_a5:
   14730  1.1        is 	sub.l		%d0,%a5			# fix a5
   14731  1.1        is 	rts
   14732  1.1        is ri_a6:
   14733  1.1        is 	sub.l		%d0,(%a6)		# fix stacked a6
   14734  1.1        is 	rts
   14735  1.1        is # if it's a fmove out instruction, we don't have to fix a7
   14736  1.1        is # because we hadn't changed it yet. if it's an opclass two
   14737  1.1        is # instruction (data moved in) and the exception was in supervisor
   14738  1.1        is # mode, then also also wasn't updated. if it was user mode, then
   14739  1.1        is # restore the correct a7 which is in the USP currently.
   14740  1.1        is ri_a7:
   14741  1.1        is 	cmpi.b		EXC_VOFF(%a6),&0x30	# move in or out?
   14742  1.1        is 	bne.b		ri_a7_done		# out
   14743  1.1        is 
   14744  1.1        is 	btst		&0x5,EXC_SR(%a6)	# user or supervisor?
   14745  1.1        is 	bne.b		ri_a7_done		# supervisor
   14746  1.1        is 	movc		%usp,%a0		# restore USP
   14747  1.1        is 	sub.l		%d0,%a0
   14748  1.1        is 	movc		%a0,%usp
   14749  1.1        is ri_a7_done:
   14750  1.1        is 	rts
   14751  1.1        is 
   14752  1.1        is # need to invert adjustment value if the <ea> was predec
   14753  1.1        is rest_dec:
   14754  1.1        is 	neg.l		%d0
   14755  1.1        is 	bra.b		rest_inc
   14756