Home | History | Annotate | Line # | Download | only in dist
      1  1.1      is #
      2  1.5  andvar # $NetBSD: isp.s,v 1.5 2021/08/02 12:56:23 andvar 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 # ireal.s:
     40  1.1      is #	This file is appended to the top of the 060ISP 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 _060ISP_TABLE.
     44  1.1      is #	Also, subroutine stubs exist in this file (_isp_done for
     45  1.1      is # example) that are referenced by the ISP 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 ISP 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.5  andvar # it makes the ISP code easier to read and more maintainable.
     50  1.1      is #
     51  1.1      is 
     52  1.1      is set	_off_chk,	0x00
     53  1.1      is set	_off_divbyzero,	0x04
     54  1.1      is set	_off_trace,	0x08
     55  1.1      is set	_off_access,	0x0c
     56  1.1      is set	_off_done,	0x10
     57  1.1      is 
     58  1.1      is set	_off_cas,	0x14
     59  1.1      is set	_off_cas2,	0x18
     60  1.1      is set	_off_lock,	0x1c
     61  1.1      is set	_off_unlock,	0x20
     62  1.1      is 
     63  1.1      is set	_off_imr,	0x40
     64  1.1      is set	_off_dmr,	0x44
     65  1.1      is set	_off_dmw,	0x48
     66  1.1      is set	_off_irw,	0x4c
     67  1.1      is set	_off_irl,	0x50
     68  1.1      is set	_off_drb,	0x54
     69  1.1      is set	_off_drw,	0x58
     70  1.1      is set	_off_drl,	0x5c
     71  1.1      is set	_off_dwb,	0x60
     72  1.1      is set	_off_dww,	0x64
     73  1.1      is set	_off_dwl,	0x68
     74  1.1      is 
     75  1.1      is _060ISP_TABLE:
     76  1.1      is 
     77  1.1      is # Here's the table of ENTRY POINTS for those linking the package.
     78  1.1      is 	bra.l		_isp_unimp
     79  1.1      is 	short		0x0000
     80  1.1      is 
     81  1.1      is 	bra.l		_isp_cas
     82  1.1      is 	short		0x0000
     83  1.1      is 
     84  1.1      is 	bra.l		_isp_cas2
     85  1.1      is 	short		0x0000
     86  1.1      is 
     87  1.1      is 	bra.l		_isp_cas_finish
     88  1.1      is 	short		0x0000
     89  1.1      is 
     90  1.1      is 	bra.l		_isp_cas2_finish
     91  1.1      is 	short		0x0000
     92  1.1      is 
     93  1.1      is 	bra.l		_isp_cas_inrange
     94  1.1      is 	short		0x0000
     95  1.1      is 
     96  1.1      is 	bra.l		_isp_cas_terminate
     97  1.1      is 	short		0x0000
     98  1.1      is 
     99  1.1      is 	bra.l		_isp_cas_restart
    100  1.1      is 	short		0x0000
    101  1.1      is 
    102  1.1      is 	space		64
    103  1.1      is 
    104  1.1      is #############################################################
    105  1.1      is 
    106  1.1      is 	global		_real_chk
    107  1.1      is _real_chk:
    108  1.1      is 	mov.l		%d0,-(%sp)
    109  1.1      is 	mov.l		(_060ISP_TABLE-0x80+_off_chk,%pc),%d0
    110  1.1      is 	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
    111  1.1      is 	mov.l		0x4(%sp),%d0
    112  1.1      is 	rtd		&0x4
    113  1.1      is 
    114  1.1      is 	global		_real_divbyzero
    115  1.1      is _real_divbyzero:
    116  1.1      is 	mov.l		%d0,-(%sp)
    117  1.1      is 	mov.l		(_060ISP_TABLE-0x80+_off_divbyzero,%pc),%d0
    118  1.1      is 	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
    119  1.1      is 	mov.l		0x4(%sp),%d0
    120  1.1      is 	rtd		&0x4
    121  1.1      is 
    122  1.1      is 	global		_real_trace
    123  1.1      is _real_trace:
    124  1.1      is 	mov.l		%d0,-(%sp)
    125  1.1      is 	mov.l		(_060ISP_TABLE-0x80+_off_trace,%pc),%d0
    126  1.1      is 	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
    127  1.1      is 	mov.l		0x4(%sp),%d0
    128  1.1      is 	rtd		&0x4
    129  1.1      is 
    130  1.1      is 	global		_real_access
    131  1.1      is _real_access:
    132  1.1      is 	mov.l		%d0,-(%sp)
    133  1.1      is 	mov.l		(_060ISP_TABLE-0x80+_off_access,%pc),%d0
    134  1.1      is 	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
    135  1.1      is 	mov.l		0x4(%sp),%d0
    136  1.1      is 	rtd		&0x4
    137  1.1      is 
    138  1.1      is 	global		_isp_done
    139  1.1      is _isp_done:
    140  1.1      is 	mov.l		%d0,-(%sp)
    141  1.1      is 	mov.l		(_060ISP_TABLE-0x80+_off_done,%pc),%d0
    142  1.1      is 	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
    143  1.1      is 	mov.l		0x4(%sp),%d0
    144  1.1      is 	rtd		&0x4
    145  1.1      is 
    146  1.1      is #######################################
    147  1.1      is 
    148  1.1      is 	global		_real_cas
    149  1.1      is _real_cas:
    150  1.1      is 	mov.l		%d0,-(%sp)
    151  1.1      is 	mov.l		(_060ISP_TABLE-0x80+_off_cas,%pc),%d0
    152  1.1      is 	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
    153  1.1      is 	mov.l		0x4(%sp),%d0
    154  1.1      is 	rtd		&0x4
    155  1.1      is 
    156  1.1      is 	global		_real_cas2
    157  1.1      is _real_cas2:
    158  1.1      is 	mov.l		%d0,-(%sp)
    159  1.1      is 	mov.l		(_060ISP_TABLE-0x80+_off_cas2,%pc),%d0
    160  1.1      is 	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
    161  1.1      is 	mov.l		0x4(%sp),%d0
    162  1.1      is 	rtd		&0x4
    163  1.1      is 
    164  1.1      is 	global		_real_lock_page
    165  1.1      is _real_lock_page:
    166  1.1      is 	mov.l		%d0,-(%sp)
    167  1.1      is 	mov.l		(_060ISP_TABLE-0x80+_off_lock,%pc),%d0
    168  1.1      is 	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
    169  1.1      is 	mov.l		0x4(%sp),%d0
    170  1.1      is 	rtd		&0x4
    171  1.1      is 
    172  1.1      is 	global		_real_unlock_page
    173  1.1      is _real_unlock_page:
    174  1.1      is 	mov.l		%d0,-(%sp)
    175  1.1      is 	mov.l		(_060ISP_TABLE-0x80+_off_unlock,%pc),%d0
    176  1.1      is 	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
    177  1.1      is 	mov.l		0x4(%sp),%d0
    178  1.1      is 	rtd		&0x4
    179  1.1      is 
    180  1.1      is #######################################
    181  1.1      is 
    182  1.1      is 	global		_imem_read
    183  1.1      is _imem_read:
    184  1.1      is 	mov.l		%d0,-(%sp)
    185  1.1      is 	mov.l		(_060ISP_TABLE-0x80+_off_imr,%pc),%d0
    186  1.1      is 	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
    187  1.1      is 	mov.l		0x4(%sp),%d0
    188  1.1      is 	rtd		&0x4
    189  1.1      is 
    190  1.1      is 	global		_dmem_read
    191  1.1      is _dmem_read:
    192  1.1      is 	mov.l		%d0,-(%sp)
    193  1.1      is 	mov.l		(_060ISP_TABLE-0x80+_off_dmr,%pc),%d0
    194  1.1      is 	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
    195  1.1      is 	mov.l		0x4(%sp),%d0
    196  1.1      is 	rtd		&0x4
    197  1.1      is 
    198  1.1      is 	global		_dmem_write
    199  1.1      is _dmem_write:
    200  1.1      is 	mov.l		%d0,-(%sp)
    201  1.1      is 	mov.l		(_060ISP_TABLE-0x80+_off_dmw,%pc),%d0
    202  1.1      is 	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
    203  1.1      is 	mov.l		0x4(%sp),%d0
    204  1.1      is 	rtd		&0x4
    205  1.1      is 
    206  1.1      is 	global		_imem_read_word
    207  1.1      is _imem_read_word:
    208  1.1      is 	mov.l		%d0,-(%sp)
    209  1.1      is 	mov.l		(_060ISP_TABLE-0x80+_off_irw,%pc),%d0
    210  1.1      is 	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
    211  1.1      is 	mov.l		0x4(%sp),%d0
    212  1.1      is 	rtd		&0x4
    213  1.1      is 
    214  1.1      is 	global		_imem_read_long
    215  1.1      is _imem_read_long:
    216  1.1      is 	mov.l		%d0,-(%sp)
    217  1.1      is 	mov.l		(_060ISP_TABLE-0x80+_off_irl,%pc),%d0
    218  1.1      is 	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
    219  1.1      is 	mov.l		0x4(%sp),%d0
    220  1.1      is 	rtd		&0x4
    221  1.1      is 
    222  1.1      is 	global		_dmem_read_byte
    223  1.1      is _dmem_read_byte:
    224  1.1      is 	mov.l		%d0,-(%sp)
    225  1.1      is 	mov.l		(_060ISP_TABLE-0x80+_off_drb,%pc),%d0
    226  1.1      is 	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
    227  1.1      is 	mov.l		0x4(%sp),%d0
    228  1.1      is 	rtd		&0x4
    229  1.1      is 
    230  1.1      is 	global		_dmem_read_word
    231  1.1      is _dmem_read_word:
    232  1.1      is 	mov.l		%d0,-(%sp)
    233  1.1      is 	mov.l		(_060ISP_TABLE-0x80+_off_drw,%pc),%d0
    234  1.1      is 	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
    235  1.1      is 	mov.l		0x4(%sp),%d0
    236  1.1      is 	rtd		&0x4
    237  1.1      is 
    238  1.1      is 	global		_dmem_read_long
    239  1.1      is _dmem_read_long:
    240  1.1      is 	mov.l		%d0,-(%sp)
    241  1.1      is 	mov.l		(_060ISP_TABLE-0x80+_off_drl,%pc),%d0
    242  1.1      is 	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
    243  1.1      is 	mov.l		0x4(%sp),%d0
    244  1.1      is 	rtd		&0x4
    245  1.1      is 
    246  1.1      is 	global		_dmem_write_byte
    247  1.1      is _dmem_write_byte:
    248  1.1      is 	mov.l		%d0,-(%sp)
    249  1.1      is 	mov.l		(_060ISP_TABLE-0x80+_off_dwb,%pc),%d0
    250  1.1      is 	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
    251  1.1      is 	mov.l		0x4(%sp),%d0
    252  1.1      is 	rtd		&0x4
    253  1.1      is 
    254  1.1      is 	global		_dmem_write_word
    255  1.1      is _dmem_write_word:
    256  1.1      is 	mov.l		%d0,-(%sp)
    257  1.1      is 	mov.l		(_060ISP_TABLE-0x80+_off_dww,%pc),%d0
    258  1.1      is 	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
    259  1.1      is 	mov.l		0x4(%sp),%d0
    260  1.1      is 	rtd		&0x4
    261  1.1      is 
    262  1.1      is 	global		_dmem_write_long
    263  1.1      is _dmem_write_long:
    264  1.1      is 	mov.l		%d0,-(%sp)
    265  1.1      is 	mov.l		(_060ISP_TABLE-0x80+_off_dwl,%pc),%d0
    266  1.1      is 	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
    267  1.1      is 	mov.l		0x4(%sp),%d0
    268  1.1      is 	rtd		&0x4
    269  1.1      is 
    270  1.1      is #
    271  1.1      is # This file contains a set of define statements for constants
    272  1.5  andvar # in order to promote readability within the core code itself.
    273  1.1      is #
    274  1.1      is 
    275  1.1      is set LOCAL_SIZE,		96			# stack frame size(bytes)
    276  1.1      is set LV,			-LOCAL_SIZE		# stack offset
    277  1.1      is 
    278  1.1      is set EXC_ISR,		0x4			# stack status register
    279  1.1      is set EXC_IPC,		0x6			# stack pc
    280  1.1      is set EXC_IVOFF,		0xa			# stacked vector offset
    281  1.1      is 
    282  1.1      is set EXC_AREGS,		LV+64			# offset of all address regs
    283  1.1      is set EXC_DREGS,		LV+32			# offset of all data regs
    284  1.1      is 
    285  1.1      is set EXC_A7,		EXC_AREGS+(7*4)		# offset of a7
    286  1.1      is set EXC_A6,		EXC_AREGS+(6*4)		# offset of a6
    287  1.1      is set EXC_A5,		EXC_AREGS+(5*4)		# offset of a5
    288  1.1      is set EXC_A4,		EXC_AREGS+(4*4)		# offset of a4
    289  1.1      is set EXC_A3,		EXC_AREGS+(3*4)		# offset of a3
    290  1.1      is set EXC_A2,		EXC_AREGS+(2*4)		# offset of a2
    291  1.1      is set EXC_A1,		EXC_AREGS+(1*4)		# offset of a1
    292  1.1      is set EXC_A0,		EXC_AREGS+(0*4)		# offset of a0
    293  1.1      is set EXC_D7,		EXC_DREGS+(7*4)		# offset of d7
    294  1.1      is set EXC_D6,		EXC_DREGS+(6*4)		# offset of d6
    295  1.1      is set EXC_D5,		EXC_DREGS+(5*4)		# offset of d5
    296  1.1      is set EXC_D4,		EXC_DREGS+(4*4)		# offset of d4
    297  1.1      is set EXC_D3,		EXC_DREGS+(3*4)		# offset of d3
    298  1.1      is set EXC_D2,		EXC_DREGS+(2*4)		# offset of d2
    299  1.1      is set EXC_D1,		EXC_DREGS+(1*4)		# offset of d1
    300  1.1      is set EXC_D0,		EXC_DREGS+(0*4)		# offset of d0
    301  1.1      is 
    302  1.1      is set EXC_TEMP,		LV+16			# offset of temp stack space
    303  1.1      is 
    304  1.1      is set EXC_SAVVAL,		LV+12			# offset of old areg value
    305  1.1      is set EXC_SAVREG,		LV+11			# offset of old areg index
    306  1.1      is 
    307  1.1      is set SPCOND_FLG,		LV+10			# offset of spc condition flg
    308  1.1      is 
    309  1.1      is set EXC_CC,		LV+8			# offset of cc register
    310  1.1      is set EXC_EXTWPTR,	LV+4			# offset of current PC
    311  1.1      is set EXC_EXTWORD,	LV+2			# offset of current ext opword
    312  1.1      is set EXC_OPWORD,		LV+0			# offset of current opword
    313  1.1      is 
    314  1.1      is ###########################
    315  1.1      is # SPecial CONDition FLaGs #
    316  1.1      is ###########################
    317  1.1      is set mia7_flg,		0x04			# (a7)+ flag
    318  1.1      is set mda7_flg,		0x08			# -(a7) flag
    319  1.1      is set ichk_flg,		0x10			# chk exception flag
    320  1.1      is set idbyz_flg,		0x20			# divbyzero flag
    321  1.1      is set restore_flg,	0x40			# restore -(an)+ flag
    322  1.1      is set immed_flg,		0x80			# immediate data flag
    323  1.1      is 
    324  1.1      is set mia7_bit,		0x2			# (a7)+ bit
    325  1.1      is set mda7_bit,		0x3			# -(a7) bit
    326  1.1      is set ichk_bit,		0x4			# chk exception bit
    327  1.1      is set idbyz_bit,		0x5			# divbyzero bit
    328  1.1      is set restore_bit,	0x6			# restore -(a7)+ bit
    329  1.1      is set immed_bit,		0x7			# immediate data bit
    330  1.1      is 
    331  1.1      is #########
    332  1.1      is # Misc. #
    333  1.1      is #########
    334  1.1      is set BYTE,		1			# len(byte) == 1 byte
    335  1.1      is set WORD, 		2			# len(word) == 2 bytes
    336  1.1      is set LONG, 		4			# len(longword) == 4 bytes
    337  1.1      is 
    338  1.1      is #########################################################################
    339  1.1      is # XDEF ****************************************************************	#
    340  1.1      is #	_isp_unimp(): 060ISP entry point for Unimplemented Instruction	#
    341  1.1      is #									#
    342  1.1      is #	This handler should be the first code executed upon taking the 	#
    343  1.1      is # 	"Unimplemented Integer Instruction" exception in an operating	#
    344  1.1      is #	system.								#
    345  1.1      is #									#
    346  1.1      is # XREF ****************************************************************	#
    347  1.1      is #	_imem_read_{word,long}() - read instruction word/longword	#
    348  1.1      is #	_mul64() - emulate 64-bit multiply				#
    349  1.1      is # 	_div64() - emulate 64-bit divide				#
    350  1.1      is #	_moveperipheral() - emulate "movep"				#
    351  1.1      is #	_compandset() - emulate misaligned "cas"			#
    352  1.1      is #	_compandset2() - emulate "cas2"					#
    353  1.1      is #	_chk2_cmp2() - emulate "cmp2" and "chk2"			#
    354  1.1      is #	_isp_done() - "callout" for normal final exit			#
    355  1.1      is #	_real_trace() - "callout" for Trace exception			#
    356  1.1      is #	_real_chk() - "callout" for Chk exception			#
    357  1.1      is #	_real_divbyzero() - "callout" for DZ exception			#
    358  1.1      is #	_real_access() - "callout" for access error exception		#
    359  1.1      is #									#
    360  1.1      is # INPUT ***************************************************************	#
    361  1.1      is #	- The system stack contains the Unimp Int Instr stack frame	#
    362  1.1      is # 									#
    363  1.1      is # OUTPUT **************************************************************	#
    364  1.1      is #	If Trace exception:						#
    365  1.1      is #	- The system stack changed to contain Trace exc stack frame	#
    366  1.1      is #	If Chk exception:						#
    367  1.1      is #	- The system stack changed to contain Chk exc stack frame	#
    368  1.1      is #	If DZ exception:						#
    369  1.1      is #	- The system stack changed to contain DZ exc stack frame	#
    370  1.1      is #	If access error exception:					#
    371  1.1      is #	- The system stack changed to contain access err exc stk frame	#
    372  1.1      is #	Else:								#
    373  1.1      is #	- Results saved as appropriate					#
    374  1.1      is #									#
    375  1.1      is # ALGORITHM ***********************************************************	#
    376  1.1      is #	This handler fetches the first instruction longword from	#
    377  1.1      is # memory and decodes it to determine which of the unimplemented		#
    378  1.1      is # integer instructions caused this exception. This handler then calls	#
    379  1.1      is # one of _mul64(), _div64(), _moveperipheral(), _compandset(), 		#
    380  1.1      is # _compandset2(), or _chk2_cmp2() as appropriate. 			#
    381  1.1      is #	Some of these instructions, by their nature, may produce other	#
    382  1.1      is # types of exceptions. "div" can produce a divide-by-zero exception,	#
    383  1.1      is # and "chk2" can cause a "Chk" exception. In both cases, the current	#
    384  1.1      is # exception stack frame must be converted to an exception stack frame	#
    385  1.1      is # of the correct exception type and an exit must be made through	#
    386  1.1      is # _real_divbyzero() or _real_chk() as appropriate. In addition, all	#
    387  1.1      is # instructions may be executing while Trace is enabled. If so, then	#
    388  1.1      is # a Trace exception stack frame must be created and an exit made 	#
    389  1.1      is # through _real_trace().						#
    390  1.1      is #	Meanwhile, if any read or write to memory using the		#
    391  1.1      is # _mem_{read,write}() "callout"s returns a failing value, then an	#
    392  1.1      is # access error frame must be created and an exit made through		#
    393  1.1      is # _real_access().							#
    394  1.1      is #	If none of these occur, then a normal exit is made through	#
    395  1.1      is # _isp_done().								#
    396  1.1      is #									#
    397  1.1      is #	This handler, upon entry, saves almost all user-visible 	#
    398  1.1      is # address and data registers to the stack. Although this may seem to	#
    399  1.1      is # cause excess memory traffic, it was found that due to having to	#
    400  1.1      is # access these register files for things like data retrieval and <ea>	#
    401  1.1      is # calculations, it was more efficient to have them on the stack where	#
    402  1.1      is # they could be accessed by indexing rather than to make subroutine 	#
    403  1.1      is # calls to retrieve a register of a particular index. 			#
    404  1.1      is #									#
    405  1.1      is #########################################################################
    406  1.1      is 
    407  1.1      is 	global		_isp_unimp
    408  1.1      is _isp_unimp:
    409  1.1      is 	link.w 		%a6,&-LOCAL_SIZE	# create room for stack frame
    410  1.1      is 
    411  1.1      is 	movm.l		&0x3fff,EXC_DREGS(%a6)	# store d0-d7/a0-a5
    412  1.1      is 	mov.l		(%a6),EXC_A6(%a6)	# store a6
    413  1.1      is 
    414  1.1      is 	btst		&0x5,EXC_ISR(%a6)	# from s or u mode?
    415  1.1      is 	bne.b		uieh_s			# supervisor mode
    416  1.1      is uieh_u:
    417  1.1      is 	mov.l		%usp,%a0		# fetch user stack pointer
    418  1.1      is 	mov.l		%a0,EXC_A7(%a6)		# store a7
    419  1.1      is 	bra.b		uieh_cont
    420  1.1      is uieh_s:
    421  1.1      is 	lea		0xc(%a6),%a0
    422  1.1      is 	mov.l		%a0,EXC_A7(%a6)		# store corrected sp
    423  1.1      is 
    424  1.1      is ###############################################################################
    425  1.1      is 
    426  1.1      is uieh_cont:
    427  1.1      is 	clr.b		SPCOND_FLG(%a6)		# clear "special case" flag
    428  1.1      is 
    429  1.1      is 	mov.w		EXC_ISR(%a6),EXC_CC(%a6) # store cc copy on stack
    430  1.1      is 	mov.l		EXC_IPC(%a6),EXC_EXTWPTR(%a6) # store extwptr on stack
    431  1.1      is 
    432  1.1      is #
    433  1.1      is # fetch the opword and first extension word pointed to by the stacked pc
    434  1.1      is # and store them to the stack for now
    435  1.1      is #
    436  1.1      is 	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
    437  1.1      is 	addq.l		&0x4,EXC_EXTWPTR(%a6)	# incr instruction ptr
    438  1.1      is 	bsr.l		_imem_read_long		# fetch opword & extword
    439  1.1      is 	mov.l		%d0,EXC_OPWORD(%a6)	# store extword on stack
    440  1.1      is 
    441  1.1      is 
    442  1.1      is #########################################################################
    443  1.1      is # muls.l	0100 1100 00 |<ea>|	0*** 1100 0000 0*** 		#
    444  1.1      is # mulu.l	0100 1100 00 |<ea>|	0*** 0100 0000 0***		#
    445  1.1      is #									#
    446  1.1      is # divs.l	0100 1100 01 |<ea>|	0*** 1100 0000 0***		#
    447  1.1      is # divu.l	0100 1100 01 |<ea>|	0*** 0100 0000 0***		#
    448  1.1      is #									#
    449  1.1      is # movep.w m2r	0000 ***1 00 001***	| <displacement>  |		#
    450  1.1      is # movep.l m2r	0000 ***1 01 001***	| <displacement>  |		#
    451  1.1      is # movep.w r2m	0000 ***1 10 001***	| <displacement>  |		#
    452  1.1      is # movep.l r2m	0000 ***1 11 001***	| <displacement>  |		#
    453  1.1      is #									#
    454  1.1      is # cas.w		0000 1100 11 |<ea>|	0000 000* **00 0***		#
    455  1.1      is # cas.l		0000 1110 11 |<ea>|	0000 000* **00 0***		#
    456  1.1      is #									#
    457  1.1      is # cas2.w	0000 1100 11 111100	**** 000* **00 0***		#
    458  1.1      is #					**** 000* **00 0***		#
    459  1.1      is # cas2.l	0000 1110 11 111100	**** 000* **00 0***		#
    460  1.1      is #					**** 000* **00 0***		#
    461  1.1      is #									#
    462  1.1      is # chk2.b	0000 0000 11 |<ea>|	**** 1000 0000 0000		#
    463  1.1      is # chk2.w	0000 0010 11 |<ea>|	**** 1000 0000 0000		#
    464  1.1      is # chk2.l	0000 0100 11 |<ea>|	**** 1000 0000 0000		#
    465  1.1      is #									#
    466  1.1      is # cmp2.b	0000 0000 11 |<ea>|	**** 0000 0000 0000		#
    467  1.1      is # cmp2.w	0000 0010 11 |<ea>|	**** 0000 0000 0000		#
    468  1.1      is # cmp2.l	0000 0100 11 |<ea>|	**** 0000 0000 0000		#
    469  1.1      is #########################################################################
    470  1.1      is 
    471  1.1      is #
    472  1.1      is # using bit 14 of the operation word, separate into 2 groups:
    473  1.1      is # (group1) mul64, div64
    474  1.1      is # (group2) movep, chk2, cmp2, cas2, cas
    475  1.1      is #
    476  1.1      is 	btst		&0x1e,%d0		# group1 or group2
    477  1.1      is 	beq.b		uieh_group2		# go handle group2
    478  1.1      is 
    479  1.1      is #
    480  1.1      is # now, w/ group1, make mul64's decode the fastest since it will
    481  1.1      is # most likely be used the most.
    482  1.1      is #
    483  1.1      is uieh_group1:
    484  1.1      is 	btst		&0x16,%d0		# test for div64
    485  1.1      is 	bne.b		uieh_div64		# go handle div64
    486  1.1      is 
    487  1.1      is uieh_mul64:
    488  1.1      is # mul64() may use ()+ addressing and may, therefore, alter a7
    489  1.1      is 
    490  1.1      is 	bsr.l		_mul64			# _mul64()
    491  1.1      is 
    492  1.1      is 	btst		&0x5,EXC_ISR(%a6)	# supervisor mode?
    493  1.1      is 	beq.w		uieh_done
    494  1.1      is 	btst		&mia7_bit,SPCOND_FLG(%a6) # was a7 changed?
    495  1.1      is 	beq.w		uieh_done		# no
    496  1.1      is 	btst		&0x7,EXC_ISR(%a6)	# is trace enabled?
    497  1.1      is 	bne.w		uieh_trace_a7		# yes
    498  1.1      is 	bra.w		uieh_a7			# no
    499  1.1      is 
    500  1.1      is uieh_div64:
    501  1.1      is # div64() may use ()+ addressing and may, therefore, alter a7.
    502  1.1      is # div64() may take a divide by zero exception.
    503  1.1      is 
    504  1.1      is 	bsr.l		_div64			# _div64()
    505  1.1      is 
    506  1.1      is # here, we sort out all of the special cases that may have happened.
    507  1.1      is 	btst		&mia7_bit,SPCOND_FLG(%a6) # was a7 changed?
    508  1.1      is 	bne.b		uieh_div64_a7		# yes
    509  1.1      is uieh_div64_dbyz:
    510  1.1      is 	btst		&idbyz_bit,SPCOND_FLG(%a6) # did divide-by-zero occur?
    511  1.1      is 	bne.w		uieh_divbyzero		# yes
    512  1.1      is 	bra.w		uieh_done		# no
    513  1.1      is uieh_div64_a7:
    514  1.1      is 	btst		&0x5,EXC_ISR(%a6)	# supervisor mode?
    515  1.1      is 	beq.b		uieh_div64_dbyz		# no
    516  1.1      is # here, a7 has been incremented by 4 bytes in supervisor mode. we still
    517  1.1      is # may have the following 3 cases:
    518  1.1      is #	(i)	(a7)+
    519  1.1      is #	(ii)	(a7)+; trace
    520  1.1      is #	(iii)	(a7)+; divide-by-zero
    521  1.1      is #
    522  1.1      is 	btst		&idbyz_bit,SPCOND_FLG(%a6) # did divide-by-zero occur?
    523  1.1      is 	bne.w		uieh_divbyzero_a7	# yes
    524  1.1      is 	tst.b		EXC_ISR(%a6)		# no; is trace enabled?
    525  1.1      is 	bmi.w		uieh_trace_a7		# yes
    526  1.1      is 	bra.w		uieh_a7			# no
    527  1.1      is 
    528  1.1      is #
    529  1.1      is # now, w/ group2, make movep's decode the fastest since it will
    530  1.1      is # most likely be used the most.
    531  1.1      is #
    532  1.1      is uieh_group2:
    533  1.1      is 	btst		&0x18,%d0		# test for not movep
    534  1.1      is 	beq.b		uieh_not_movep
    535  1.1      is 
    536  1.1      is 
    537  1.1      is 	bsr.l		_moveperipheral		# _movep()
    538  1.1      is 	bra.w		uieh_done
    539  1.1      is 
    540  1.1      is uieh_not_movep:
    541  1.1      is 	btst		&0x1b,%d0		# test for chk2,cmp2
    542  1.1      is 	beq.b		uieh_chk2cmp2		# go handle chk2,cmp2
    543  1.1      is 
    544  1.1      is 	swap		%d0			# put opword in lo word
    545  1.1      is 	cmpi.b	 	%d0,&0xfc		# test for cas2
    546  1.1      is 	beq.b		uieh_cas2		# go handle cas2
    547  1.1      is 
    548  1.1      is uieh_cas:
    549  1.1      is 
    550  1.1      is 	bsr.l		_compandset		# _cas()
    551  1.1      is 
    552  1.1      is # the cases of "cas Dc,Du,(a7)+" and "cas Dc,Du,-(a7)" used from supervisor
    553  1.1      is # mode are simply not considered valid and therefore are not handled.
    554  1.1      is 
    555  1.1      is 	bra.w		uieh_done
    556  1.1      is 
    557  1.1      is uieh_cas2:
    558  1.1      is 
    559  1.1      is 	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
    560  1.1      is 	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
    561  1.1      is 	bsr.l		_imem_read_word		# read extension word
    562  1.1      is 
    563  1.1      is 	tst.l		%d1			# ifetch error?
    564  1.1      is 	bne.w		isp_iacc		# yes
    565  1.1      is 
    566  1.1      is 	bsr.l		_compandset2		# _cas2()
    567  1.1      is 	bra.w		uieh_done
    568  1.1      is 
    569  1.1      is uieh_chk2cmp2:
    570  1.1      is # chk2 may take a chk exception
    571  1.1      is 
    572  1.1      is 	bsr.l		_chk2_cmp2		# _chk2_cmp2()
    573  1.1      is 
    574  1.1      is # here we check to see if a chk trap should be taken
    575  1.1      is 	cmpi.b		SPCOND_FLG(%a6),&ichk_flg
    576  1.1      is 	bne.w		uieh_done
    577  1.1      is 	bra.b		uieh_chk_trap
    578  1.1      is 
    579  1.1      is ###########################################################################
    580  1.1      is 
    581  1.1      is #
    582  1.1      is # the required emulation has been completed. now, clean up the necessary stack
    583  1.1      is # info and prepare for rte
    584  1.1      is #
    585  1.1      is uieh_done:
    586  1.1      is 	mov.b		EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes
    587  1.1      is 
    588  1.1      is # if exception occurred in user mode, then we have to restore a7 in case it
    589  1.4  andvar # changed. we don't have to update a7  for supervisor mouse because that case
    590  1.1      is # doesn't flow through here
    591  1.1      is 	btst		&0x5,EXC_ISR(%a6)	# user or supervisor?
    592  1.1      is 	bne.b		uieh_finish		# supervisor
    593  1.1      is 
    594  1.1      is 	mov.l		EXC_A7(%a6),%a0		# fetch user stack pointer
    595  1.1      is 	mov.l		%a0,%usp		# restore it
    596  1.1      is 
    597  1.1      is uieh_finish:
    598  1.1      is 	movm.l		EXC_DREGS(%a6),&0x3fff 	# restore d0-d7/a0-a5
    599  1.1      is 
    600  1.1      is 	btst		&0x7,EXC_ISR(%a6)	# is trace mode on?
    601  1.1      is 	bne.b		uieh_trace		# yes;go handle trace mode
    602  1.1      is 
    603  1.1      is 	mov.l		EXC_EXTWPTR(%a6),EXC_IPC(%a6) # new pc on stack frame
    604  1.1      is 	mov.l		EXC_A6(%a6),(%a6)	# prepare new a6 for unlink
    605  1.1      is 	unlk		%a6			# unlink stack frame
    606  1.1      is 	bra.l		_isp_done
    607  1.1      is 
    608  1.1      is #
    609  1.1      is # The instruction that was just emulated was also being traced. The trace
    610  1.1      is # trap for this instruction will be lost unless we jump to the trace handler.
    611  1.1      is # So, here we create a Trace Exception format number two exception stack
    612  1.4  andvar # frame from the Unimplemented Integer Instruction Exception stack frame
    613  1.1      is # format number zero and jump to the user supplied hook "_real_trace()".
    614  1.1      is #
    615  1.1      is #		   UIEH FRAME		   TRACE FRAME
    616  1.1      is #		*****************	*****************
    617  1.1      is #		* 0x0 *  0x0f4	*	*    Current	*
    618  1.1      is #		*****************	*      PC	*
    619  1.1      is #		*    Current	*	*****************
    620  1.1      is #		*      PC 	*	* 0x2 *  0x024	*
    621  1.1      is #		*****************	*****************
    622  1.1      is #		*      SR	*	*     Next	*
    623  1.1      is #		*****************	*      PC	*
    624  1.1      is #	      ->*     Old   	*	*****************
    625  1.1      is #  from link -->*      A6	*	*      SR	*
    626  1.1      is #	        *****************	*****************
    627  1.1      is #	       /*      A7	*	*      New	* <-- for final unlink
    628  1.1      is #	      / *		*	*      A6	*
    629  1.1      is # link frame <  *****************	*****************
    630  1.1      is #	      \ ~		~	~		~
    631  1.1      is #	       \*****************	*****************
    632  1.1      is #
    633  1.1      is uieh_trace:
    634  1.1      is 	mov.l		EXC_A6(%a6),-0x4(%a6)
    635  1.1      is 	mov.w		EXC_ISR(%a6),0x0(%a6)
    636  1.1      is 	mov.l		EXC_IPC(%a6),0x8(%a6)
    637  1.1      is 	mov.l		EXC_EXTWPTR(%a6),0x2(%a6)
    638  1.1      is 	mov.w		&0x2024,0x6(%a6)
    639  1.1      is 	sub.l		&0x4,%a6
    640  1.1      is 	unlk		%a6
    641  1.1      is 	bra.l		_real_trace
    642  1.1      is 
    643  1.1      is #
    644  1.1      is #	   UIEH FRAME		    CHK FRAME
    645  1.1      is #	*****************	*****************
    646  1.1      is #	* 0x0 *  0x0f4	*	*    Current	*
    647  1.1      is #	*****************	*      PC	*
    648  1.1      is #	*    Current	*	*****************
    649  1.1      is #	*      PC	*	* 0x2 *  0x018	*
    650  1.1      is #	*****************	*****************
    651  1.1      is #	*      SR	*	*     Next	*
    652  1.1      is #	*****************	*      PC	*
    653  1.1      is #	    (4 words)		*****************
    654  1.1      is #				*      SR	*
    655  1.1      is #				*****************
    656  1.1      is #				    (6 words)
    657  1.1      is #
    658  1.1      is # the chk2 instruction should take a chk trap. so, here we must create a
    659  1.1      is # chk stack frame from an unimplemented integer instruction exception frame
    660  1.1      is # and jump to the user supplied entry point "_real_chk()".
    661  1.1      is #
    662  1.1      is uieh_chk_trap:
    663  1.1      is 	mov.b		EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes
    664  1.1      is 	movm.l		EXC_DREGS(%a6),&0x3fff 	# restore d0-d7/a0-a5
    665  1.1      is 
    666  1.1      is 	mov.w		EXC_ISR(%a6),(%a6)	# put new SR on stack
    667  1.1      is 	mov.l		EXC_IPC(%a6),0x8(%a6)	# put "Current PC" on stack
    668  1.1      is 	mov.l		EXC_EXTWPTR(%a6),0x2(%a6) # put "Next PC" on stack
    669  1.1      is 	mov.w		&0x2018,0x6(%a6)	# put Vector Offset on stack
    670  1.1      is 
    671  1.1      is 	mov.l		EXC_A6(%a6),%a6		# restore a6
    672  1.1      is 	add.l		&LOCAL_SIZE,%sp		# clear stack frame
    673  1.1      is 
    674  1.1      is 	bra.l		_real_chk
    675  1.1      is 
    676  1.1      is #
    677  1.1      is #	   UIEH FRAME		 DIVBYZERO FRAME
    678  1.1      is #	*****************	*****************
    679  1.1      is #	* 0x0 *  0x0f4	*	*    Current	*
    680  1.1      is #	*****************	*      PC	*
    681  1.1      is #	*    Current	*	*****************
    682  1.1      is #	*      PC	*	* 0x2 *  0x014	*
    683  1.1      is #	*****************	*****************
    684  1.1      is #	*      SR	*	*     Next	*
    685  1.1      is #	*****************	*      PC	*
    686  1.1      is #	    (4 words)		*****************
    687  1.1      is #				*      SR	*
    688  1.1      is #				*****************
    689  1.1      is #				    (6 words)
    690  1.1      is #
    691  1.1      is # the divide instruction should take an integer divide by zero trap. so, here
    692  1.1      is # we must create a divbyzero stack frame from an unimplemented integer
    693  1.1      is # instruction exception frame and jump to the user supplied entry point
    694  1.1      is # "_real_divbyzero()".
    695  1.1      is #
    696  1.1      is uieh_divbyzero:
    697  1.1      is 	mov.b		EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes
    698  1.1      is 	movm.l		EXC_DREGS(%a6),&0x3fff 	# restore d0-d7/a0-a5
    699  1.1      is 
    700  1.1      is 	mov.w		EXC_ISR(%a6),(%a6)	# put new SR on stack
    701  1.1      is 	mov.l		EXC_IPC(%a6),0x8(%a6)	# put "Current PC" on stack
    702  1.1      is 	mov.l		EXC_EXTWPTR(%a6),0x2(%a6) # put "Next PC" on stack
    703  1.1      is 	mov.w		&0x2014,0x6(%a6)	# put Vector Offset on stack
    704  1.1      is 
    705  1.1      is 	mov.l		EXC_A6(%a6),%a6		# restore a6
    706  1.1      is 	add.l		&LOCAL_SIZE,%sp		# clear stack frame
    707  1.1      is 
    708  1.1      is 	bra.l		_real_divbyzero
    709  1.1      is 
    710  1.1      is #
    711  1.1      is #				 DIVBYZERO FRAME
    712  1.1      is #				*****************
    713  1.1      is #				*    Current	*
    714  1.1      is #	   UIEH FRAME		*      PC	*
    715  1.1      is #	*****************	*****************
    716  1.1      is #	* 0x0 *  0x0f4	*	* 0x2 * 0x014	*
    717  1.1      is #	*****************	*****************
    718  1.1      is #	*    Current	*	*     Next	*
    719  1.1      is #	*      PC	*	*      PC	*
    720  1.1      is #	*****************	*****************
    721  1.1      is #	*      SR	*	*      SR	*
    722  1.1      is #	*****************	*****************
    723  1.1      is #	    (4 words)		    (6 words)
    724  1.1      is #
    725  1.1      is # the divide instruction should take an integer divide by zero trap. so, here
    726  1.1      is # we must create a divbyzero stack frame from an unimplemented integer
    727  1.1      is # instruction exception frame and jump to the user supplied entry point
    728  1.1      is # "_real_divbyzero()".
    729  1.1      is #
    730  1.1      is # However, we must also deal with the fact that (a7)+ was used from supervisor
    731  1.1      is # mode, thereby shifting the stack frame up 4 bytes.
    732  1.1      is #
    733  1.1      is uieh_divbyzero_a7:
    734  1.1      is 	mov.b		EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes
    735  1.1      is 	movm.l		EXC_DREGS(%a6),&0x3fff 	# restore d0-d7/a0-a5
    736  1.1      is 
    737  1.1      is 	mov.l		EXC_IPC(%a6),0xc(%a6)	# put "Current PC" on stack
    738  1.1      is 	mov.w		&0x2014,0xa(%a6)	# put Vector Offset on stack
    739  1.1      is 	mov.l		EXC_EXTWPTR(%a6),0x6(%a6) # put "Next PC" on stack
    740  1.1      is 
    741  1.1      is 	mov.l		EXC_A6(%a6),%a6		# restore a6
    742  1.1      is 	add.l		&4+LOCAL_SIZE,%sp	# clear stack frame
    743  1.1      is 
    744  1.1      is 	bra.l		_real_divbyzero
    745  1.1      is 
    746  1.1      is #
    747  1.1      is #				   TRACE FRAME
    748  1.1      is #				*****************
    749  1.1      is #				*    Current	*
    750  1.1      is #	   UIEH FRAME		*      PC	*
    751  1.1      is #	*****************	*****************
    752  1.1      is #	* 0x0 *  0x0f4	*	* 0x2 * 0x024	*
    753  1.1      is #	*****************	*****************
    754  1.1      is #	*    Current	*	*     Next	*
    755  1.1      is #	*      PC	*	*      PC	*
    756  1.1      is #	*****************	*****************
    757  1.1      is #	*      SR	*	*      SR	*
    758  1.1      is #	*****************	*****************
    759  1.1      is #	    (4 words)		    (6 words)
    760  1.1      is #
    761  1.1      is #
    762  1.1      is # The instruction that was just emulated was also being traced. The trace
    763  1.1      is # trap for this instruction will be lost unless we jump to the trace handler.
    764  1.1      is # So, here we create a Trace Exception format number two exception stack
    765  1.5  andvar # frame from the Unimplemented Integer Instruction Exception stack frame
    766  1.1      is # format number zero and jump to the user supplied hook "_real_trace()".
    767  1.1      is #
    768  1.1      is # However, we must also deal with the fact that (a7)+ was used from supervisor
    769  1.1      is # mode, thereby shifting the stack frame up 4 bytes.
    770  1.1      is #
    771  1.1      is uieh_trace_a7:
    772  1.1      is 	mov.b		EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes
    773  1.1      is 	movm.l		EXC_DREGS(%a6),&0x3fff 	# restore d0-d7/a0-a5
    774  1.1      is 
    775  1.1      is 	mov.l		EXC_IPC(%a6),0xc(%a6)	# put "Current PC" on stack
    776  1.1      is 	mov.w		&0x2024,0xa(%a6)	# put Vector Offset on stack
    777  1.1      is 	mov.l		EXC_EXTWPTR(%a6),0x6(%a6) # put "Next PC" on stack
    778  1.1      is 
    779  1.1      is 	mov.l		EXC_A6(%a6),%a6		# restore a6
    780  1.1      is 	add.l		&4+LOCAL_SIZE,%sp	# clear stack frame
    781  1.1      is 
    782  1.1      is 	bra.l		_real_trace
    783  1.1      is 
    784  1.1      is #
    785  1.1      is #				   UIEH FRAME
    786  1.1      is #				*****************
    787  1.1      is #				* 0x0 * 0x0f4	*
    788  1.1      is #	   UIEH FRAME		*****************
    789  1.1      is #	*****************	*     Next	*
    790  1.1      is #	* 0x0 *  0x0f4	*	*      PC	*
    791  1.1      is #	*****************	*****************
    792  1.1      is #	*    Current	*	*      SR	*
    793  1.1      is #	*      PC	*	*****************
    794  1.1      is #	*****************	    (4 words)
    795  1.1      is #	*      SR	*
    796  1.1      is #	*****************
    797  1.1      is #	    (4 words)
    798  1.1      is uieh_a7:
    799  1.1      is 	mov.b		EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes
    800  1.1      is 	movm.l		EXC_DREGS(%a6),&0x3fff 	# restore d0-d7/a0-a5
    801  1.1      is 
    802  1.1      is 	mov.w		&0x00f4,0xe(%a6)	# put Vector Offset on stack
    803  1.1      is 	mov.l		EXC_EXTWPTR(%a6),0xa(%a6) # put "Next PC" on stack
    804  1.1      is 	mov.w		EXC_ISR(%a6),0x8(%a6)	# put SR on stack
    805  1.1      is 
    806  1.1      is 	mov.l		EXC_A6(%a6),%a6		# restore a6
    807  1.1      is 	add.l		&8+LOCAL_SIZE,%sp	# clear stack frame
    808  1.1      is 	bra.l		_isp_done
    809  1.1      is 
    810  1.1      is ##########
    811  1.1      is 
    812  1.1      is # this is the exit point if a data read or write fails.
    813  1.1      is # a0 = failing address
    814  1.1      is # d0 = fslw
    815  1.1      is isp_dacc:
    816  1.1      is 	mov.l		%a0,(%a6)		# save address
    817  1.1      is 	mov.l		%d0,-0x4(%a6)		# save partial fslw
    818  1.1      is 
    819  1.1      is 	lea		-64(%a6),%sp
    820  1.1      is 	movm.l		(%sp)+,&0x7fff 		# restore d0-d7/a0-a6
    821  1.1      is 
    822  1.1      is 	mov.l		0xc(%sp),-(%sp)		# move voff,hi(pc)
    823  1.1      is 	mov.l		0x4(%sp),0x10(%sp)	# store fslw
    824  1.1      is 	mov.l		0xc(%sp),0x4(%sp)	# store sr,lo(pc)
    825  1.1      is 	mov.l		0x8(%sp),0xc(%sp)	# store address
    826  1.1      is 	mov.l		(%sp)+,0x4(%sp)		# store voff,hi(pc)
    827  1.1      is 	mov.w		&0x4008,0x6(%sp)	# store new voff
    828  1.1      is 
    829  1.1      is 	bra.b		isp_acc_exit
    830  1.1      is 
    831  1.1      is # this is the exit point if an instruction word read fails.
    832  1.1      is # FSLW:
    833  1.1      is #	misaligned = true
    834  1.1      is #	read = true
    835  1.1      is # 	size = word
    836  1.1      is # 	instruction = true
    837  1.1      is # 	software emulation error = true
    838  1.1      is isp_iacc:
    839  1.1      is 	movm.l		EXC_DREGS(%a6),&0x3fff 	# restore d0-d7/a0-a5
    840  1.1      is 	unlk		%a6			# unlink frame
    841  1.1      is 	sub.w		&0x8,%sp		# make room for acc frame
    842  1.1      is 	mov.l		0x8(%sp),(%sp)		# store sr,lo(pc)
    843  1.1      is 	mov.w		0xc(%sp),0x4(%sp)	# store hi(pc)
    844  1.1      is 	mov.w		&0x4008,0x6(%sp)	# store new voff
    845  1.1      is 	mov.l		0x2(%sp),0x8(%sp)	# store address (=pc)
    846  1.1      is 	mov.l		&0x09428001,0xc(%sp)	# store fslw
    847  1.1      is 
    848  1.1      is isp_acc_exit:
    849  1.1      is 	btst		&0x5,(%sp)		# user or supervisor?
    850  1.1      is 	beq.b		isp_acc_exit2		# user
    851  1.1      is 	bset		&0x2,0xd(%sp)		# set supervisor TM bit
    852  1.1      is isp_acc_exit2:
    853  1.1      is 	bra.l		_real_access
    854  1.1      is 
    855  1.1      is # if the addressing mode was (an)+ or -(an), the address register must
    856  1.1      is # be restored to it's pre-exception value before entering _real_access.
    857  1.1      is isp_restore:
    858  1.1      is 	cmpi.b		SPCOND_FLG(%a6),&restore_flg # do we need a restore?
    859  1.1      is 	bne.b		isp_restore_done	# no
    860  1.1      is 	clr.l		%d0
    861  1.1      is 	mov.b		EXC_SAVREG(%a6),%d0	# regno to restore
    862  1.1      is 	mov.l		EXC_SAVVAL(%a6),(EXC_AREGS,%a6,%d0.l*4) # restore value
    863  1.1      is isp_restore_done:
    864  1.1      is 	rts
    865  1.1      is 
    866  1.1      is #########################################################################
    867  1.1      is # XDEF ****************************************************************	#
    868  1.1      is #	_calc_ea(): routine to calculate effective address		#
    869  1.1      is #									#
    870  1.1      is # XREF ****************************************************************	#
    871  1.1      is # 	_imem_read_word() - read instruction word			#
    872  1.1      is # 	_imem_read_long() - read instruction longword			#
    873  1.1      is # 	_dmem_read_long() - read data longword (for memory indirect)	#
    874  1.1      is # 	isp_iacc() - handle instruction access error exception		#
    875  1.1      is #	isp_dacc() - handle data access error exception			#
    876  1.1      is #									#
    877  1.1      is # INPUT ***************************************************************	#
    878  1.1      is # 	d0 = number of bytes related to effective address (w,l)		#
    879  1.1      is #									#
    880  1.1      is # OUTPUT **************************************************************	#
    881  1.1      is #	If exiting through isp_dacc...					#
    882  1.1      is #		a0 = failing address					#
    883  1.1      is #		d0 = FSLW						#
    884  1.1      is #	elsif exiting though isp_iacc...				#
    885  1.1      is #		none							#
    886  1.1      is #	else								#
    887  1.1      is #		a0 = effective address					#
    888  1.1      is #									#
    889  1.1      is # ALGORITHM ***********************************************************	#
    890  1.1      is # 	The effective address type is decoded from the opword residing	#
    891  1.1      is # on the stack. A jump table is used to vector to a routine for the 	#
    892  1.1      is # appropriate mode. Since none of the emulated integer instructions	#
    893  1.1      is # uses byte-sized operands, only handle word and long operations.	#
    894  1.1      is #									#
    895  1.1      is # 	Dn,An	- shouldn't enter here					#
    896  1.1      is #	(An)	- fetch An value from stack				#
    897  1.1      is # 	-(An)	- fetch An value from stack; return decr value;		#
    898  1.1      is #		  place decr value on stack; store old value in case of	#
    899  1.1      is #		  future access error; if -(a7), set mda7_flg in 	#
    900  1.1      is #		  SPCOND_FLG						#
    901  1.1      is #	(An)+	- fetch An value from stack; return value;		#
    902  1.1      is #		  place incr value on stack; store old value in case of	#
    903  1.1      is #		  future access error; if (a7)+, set mia7_flg in	#
    904  1.1      is #		  SPCOND_FLG						#
    905  1.1      is #	(d16,An) - fetch An value from stack; read d16 using 		#
    906  1.1      is #		  _imem_read_word(); fetch may fail -> branch to	#
    907  1.1      is #		  isp_iacc()						#
    908  1.1      is #	(xxx).w,(xxx).l - use _imem_read_{word,long}() to fetch		#
    909  1.1      is #		  address; fetch may fail				#
    910  1.1      is #	#<data> - return address of immediate value; set immed_flg	#
    911  1.1      is #		  in SPCOND_FLG						#
    912  1.1      is #	(d16,PC) - fetch stacked PC value; read d16 using		#
    913  1.1      is #		  _imem_read_word(); fetch may fail -> branch to	#
    914  1.1      is #		  isp_iacc()						#
    915  1.1      is #	everything else - read needed displacements as appropriate w/	#
    916  1.1      is #		  _imem_read_{word,long}(); read may fail; if memory	#
    917  1.1      is # 		  indirect, read indirect address using			#
    918  1.1      is #		  _dmem_read_long() which may also fail			#
    919  1.1      is #									#
    920  1.1      is #########################################################################
    921  1.1      is 
    922  1.1      is 	global		_calc_ea
    923  1.1      is _calc_ea:
    924  1.1      is 	mov.l		%d0,%a0			# move # bytes to a0
    925  1.1      is 
    926  1.1      is # MODE and REG are taken from the EXC_OPWORD.
    927  1.1      is 	mov.w		EXC_OPWORD(%a6),%d0	# fetch opcode word
    928  1.1      is 	mov.w		%d0,%d1			# make a copy
    929  1.1      is 
    930  1.1      is 	andi.w		&0x3f,%d0		# extract mode field
    931  1.1      is 	andi.l		&0x7,%d1		# extract reg  field
    932  1.1      is 
    933  1.1      is # jump to the corresponding function for each {MODE,REG} pair.
    934  1.1      is 	mov.w		(tbl_ea_mode.b,%pc,%d0.w*2), %d0 # fetch jmp distance
    935  1.1      is 	jmp		(tbl_ea_mode.b,%pc,%d0.w*1) # jmp to correct ea mode
    936  1.1      is 
    937  1.1      is 	swbeg		&64
    938  1.1      is tbl_ea_mode:
    939  1.1      is 	short		tbl_ea_mode	-	tbl_ea_mode
    940  1.1      is 	short		tbl_ea_mode	-	tbl_ea_mode
    941  1.1      is 	short		tbl_ea_mode	-	tbl_ea_mode
    942  1.1      is 	short		tbl_ea_mode	-	tbl_ea_mode
    943  1.1      is 	short		tbl_ea_mode	-	tbl_ea_mode
    944  1.1      is 	short		tbl_ea_mode	-	tbl_ea_mode
    945  1.1      is 	short		tbl_ea_mode	-	tbl_ea_mode
    946  1.1      is 	short		tbl_ea_mode	-	tbl_ea_mode
    947  1.1      is 
    948  1.1      is 	short		tbl_ea_mode	-	tbl_ea_mode
    949  1.1      is 	short		tbl_ea_mode	-	tbl_ea_mode
    950  1.1      is 	short		tbl_ea_mode	-	tbl_ea_mode
    951  1.1      is 	short		tbl_ea_mode	-	tbl_ea_mode
    952  1.1      is 	short		tbl_ea_mode	-	tbl_ea_mode
    953  1.1      is 	short		tbl_ea_mode	-	tbl_ea_mode
    954  1.1      is 	short		tbl_ea_mode	-	tbl_ea_mode
    955  1.1      is 	short		tbl_ea_mode	-	tbl_ea_mode
    956  1.1      is 
    957  1.1      is 	short		addr_ind_a0	- 	tbl_ea_mode
    958  1.1      is 	short		addr_ind_a1	- 	tbl_ea_mode
    959  1.1      is 	short		addr_ind_a2	- 	tbl_ea_mode
    960  1.1      is 	short		addr_ind_a3 	- 	tbl_ea_mode
    961  1.1      is 	short		addr_ind_a4 	- 	tbl_ea_mode
    962  1.1      is 	short		addr_ind_a5 	- 	tbl_ea_mode
    963  1.1      is 	short		addr_ind_a6 	- 	tbl_ea_mode
    964  1.1      is 	short		addr_ind_a7 	- 	tbl_ea_mode
    965  1.1      is 
    966  1.1      is 	short		addr_ind_p_a0	- 	tbl_ea_mode
    967  1.1      is 	short		addr_ind_p_a1 	- 	tbl_ea_mode
    968  1.1      is 	short		addr_ind_p_a2 	- 	tbl_ea_mode
    969  1.1      is 	short		addr_ind_p_a3 	- 	tbl_ea_mode
    970  1.1      is 	short		addr_ind_p_a4 	- 	tbl_ea_mode
    971  1.1      is 	short		addr_ind_p_a5 	- 	tbl_ea_mode
    972  1.1      is 	short		addr_ind_p_a6 	- 	tbl_ea_mode
    973  1.1      is 	short		addr_ind_p_a7 	- 	tbl_ea_mode
    974  1.1      is 
    975  1.1      is 	short		addr_ind_m_a0 		- 	tbl_ea_mode
    976  1.1      is 	short		addr_ind_m_a1 		- 	tbl_ea_mode
    977  1.1      is 	short		addr_ind_m_a2 		- 	tbl_ea_mode
    978  1.1      is 	short		addr_ind_m_a3 		- 	tbl_ea_mode
    979  1.1      is 	short		addr_ind_m_a4 		- 	tbl_ea_mode
    980  1.1      is 	short		addr_ind_m_a5 		- 	tbl_ea_mode
    981  1.1      is 	short		addr_ind_m_a6 		- 	tbl_ea_mode
    982  1.1      is 	short		addr_ind_m_a7 		- 	tbl_ea_mode
    983  1.1      is 
    984  1.1      is 	short		addr_ind_disp_a0	- 	tbl_ea_mode
    985  1.1      is 	short		addr_ind_disp_a1 	- 	tbl_ea_mode
    986  1.1      is 	short		addr_ind_disp_a2 	- 	tbl_ea_mode
    987  1.1      is 	short		addr_ind_disp_a3 	- 	tbl_ea_mode
    988  1.1      is 	short		addr_ind_disp_a4 	- 	tbl_ea_mode
    989  1.1      is 	short		addr_ind_disp_a5 	- 	tbl_ea_mode
    990  1.1      is 	short		addr_ind_disp_a6 	- 	tbl_ea_mode
    991  1.1      is 	short		addr_ind_disp_a7	-	tbl_ea_mode
    992  1.1      is 
    993  1.1      is 	short		_addr_ind_ext 		- 	tbl_ea_mode
    994  1.1      is 	short		_addr_ind_ext 		- 	tbl_ea_mode
    995  1.1      is 	short		_addr_ind_ext 		- 	tbl_ea_mode
    996  1.1      is 	short		_addr_ind_ext 		- 	tbl_ea_mode
    997  1.1      is 	short		_addr_ind_ext 		- 	tbl_ea_mode
    998  1.1      is 	short		_addr_ind_ext 		- 	tbl_ea_mode
    999  1.1      is 	short		_addr_ind_ext 		- 	tbl_ea_mode
   1000  1.1      is 	short		_addr_ind_ext 		- 	tbl_ea_mode
   1001  1.1      is 
   1002  1.1      is 	short		abs_short		- 	tbl_ea_mode
   1003  1.1      is 	short		abs_long		- 	tbl_ea_mode
   1004  1.1      is 	short		pc_ind			- 	tbl_ea_mode
   1005  1.1      is 	short		pc_ind_ext		- 	tbl_ea_mode
   1006  1.1      is 	short		immediate		- 	tbl_ea_mode
   1007  1.1      is 	short		tbl_ea_mode		- 	tbl_ea_mode
   1008  1.1      is 	short		tbl_ea_mode		- 	tbl_ea_mode
   1009  1.1      is 	short		tbl_ea_mode		- 	tbl_ea_mode
   1010  1.1      is 
   1011  1.1      is ###################################
   1012  1.1      is # Address register indirect: (An) #
   1013  1.1      is ###################################
   1014  1.1      is addr_ind_a0:
   1015  1.1      is 	mov.l		EXC_A0(%a6),%a0		# Get current a0
   1016  1.1      is 	rts
   1017  1.1      is 
   1018  1.1      is addr_ind_a1:
   1019  1.1      is 	mov.l		EXC_A1(%a6),%a0		# Get current a1
   1020  1.1      is 	rts
   1021  1.1      is 
   1022  1.1      is addr_ind_a2:
   1023  1.1      is 	mov.l		EXC_A2(%a6),%a0		# Get current a2
   1024  1.1      is 	rts
   1025  1.1      is 
   1026  1.1      is addr_ind_a3:
   1027  1.1      is 	mov.l		EXC_A3(%a6),%a0		# Get current a3
   1028  1.1      is 	rts
   1029  1.1      is 
   1030  1.1      is addr_ind_a4:
   1031  1.1      is 	mov.l		EXC_A4(%a6),%a0		# Get current a4
   1032  1.1      is 	rts
   1033  1.1      is 
   1034  1.1      is addr_ind_a5:
   1035  1.1      is 	mov.l		EXC_A5(%a6),%a0		# Get current a5
   1036  1.1      is 	rts
   1037  1.1      is 
   1038  1.1      is addr_ind_a6:
   1039  1.1      is 	mov.l		EXC_A6(%a6),%a0		# Get current a6
   1040  1.1      is 	rts
   1041  1.1      is 
   1042  1.1      is addr_ind_a7:
   1043  1.1      is 	mov.l		EXC_A7(%a6),%a0		# Get current a7
   1044  1.1      is 	rts
   1045  1.1      is 
   1046  1.1      is #####################################################
   1047  1.1      is # Address register indirect w/ postincrement: (An)+ #
   1048  1.1      is #####################################################
   1049  1.1      is addr_ind_p_a0:
   1050  1.1      is 	mov.l		%a0,%d0			# copy no. bytes
   1051  1.1      is 	mov.l		EXC_A0(%a6),%a0		# load current value
   1052  1.1      is 	add.l		%a0,%d0			# increment
   1053  1.1      is 	mov.l		%d0,EXC_A0(%a6)		# save incremented value
   1054  1.1      is 
   1055  1.1      is 	mov.l		%a0,EXC_SAVVAL(%a6)	# save in case of access error
   1056  1.1      is 	mov.b		&0x0,EXC_SAVREG(%a6)	# save regno, too
   1057  1.1      is 	mov.b		&restore_flg,SPCOND_FLG(%a6) # set flag
   1058  1.1      is 	rts
   1059  1.1      is 
   1060  1.1      is addr_ind_p_a1:
   1061  1.1      is 	mov.l		%a0,%d0			# copy no. bytes
   1062  1.1      is 	mov.l		EXC_A1(%a6),%a0		# load current value
   1063  1.1      is 	add.l		%a0,%d0			# increment
   1064  1.1      is 	mov.l		%d0,EXC_A1(%a6)		# save incremented value
   1065  1.1      is 
   1066  1.1      is 	mov.l		%a0,EXC_SAVVAL(%a6)	# save in case of access error
   1067  1.1      is 	mov.b		&0x1,EXC_SAVREG(%a6)	# save regno, too
   1068  1.1      is 	mov.b		&restore_flg,SPCOND_FLG(%a6) # set flag
   1069  1.1      is 	rts
   1070  1.1      is 
   1071  1.1      is addr_ind_p_a2:
   1072  1.1      is 	mov.l		%a0,%d0			# copy no. bytes
   1073  1.1      is 	mov.l		EXC_A2(%a6),%a0		# load current value
   1074  1.1      is 	add.l		%a0,%d0			# increment
   1075  1.1      is 	mov.l		%d0,EXC_A2(%a6)		# save incremented value
   1076  1.1      is 
   1077  1.1      is 	mov.l		%a0,EXC_SAVVAL(%a6)	# save in case of access error
   1078  1.1      is 	mov.b		&0x2,EXC_SAVREG(%a6)	# save regno, too
   1079  1.1      is 	mov.b		&restore_flg,SPCOND_FLG(%a6) # set flag
   1080  1.1      is 	rts
   1081  1.1      is 
   1082  1.1      is addr_ind_p_a3:
   1083  1.1      is 	mov.l		%a0,%d0			# copy no. bytes
   1084  1.1      is 	mov.l		EXC_A3(%a6),%a0		# load current value
   1085  1.1      is 	add.l		%a0,%d0			# increment
   1086  1.1      is 	mov.l		%d0,EXC_A3(%a6)		# save incremented value
   1087  1.1      is 
   1088  1.1      is 	mov.l		%a0,EXC_SAVVAL(%a6)	# save in case of access error
   1089  1.1      is 	mov.b		&0x3,EXC_SAVREG(%a6)	# save regno, too
   1090  1.1      is 	mov.b		&restore_flg,SPCOND_FLG(%a6) # set flag
   1091  1.1      is 	rts
   1092  1.1      is 
   1093  1.1      is addr_ind_p_a4:
   1094  1.1      is 	mov.l		%a0,%d0			# copy no. bytes
   1095  1.1      is 	mov.l		EXC_A4(%a6),%a0		# load current value
   1096  1.1      is 	add.l		%a0,%d0			# increment
   1097  1.1      is 	mov.l		%d0,EXC_A4(%a6)		# save incremented value
   1098  1.1      is 
   1099  1.1      is 	mov.l		%a0,EXC_SAVVAL(%a6)	# save in case of access error
   1100  1.1      is 	mov.b		&0x4,EXC_SAVREG(%a6)	# save regno, too
   1101  1.1      is 	mov.b		&restore_flg,SPCOND_FLG(%a6) # set flag
   1102  1.1      is 	rts
   1103  1.1      is 
   1104  1.1      is addr_ind_p_a5:
   1105  1.1      is 	mov.l		%a0,%d0			# copy no. bytes
   1106  1.1      is 	mov.l		EXC_A5(%a6),%a0		# load current value
   1107  1.1      is 	add.l		%a0,%d0			# increment
   1108  1.1      is 	mov.l		%d0,EXC_A5(%a6)		# save incremented value
   1109  1.1      is 
   1110  1.1      is 	mov.l		%a0,EXC_SAVVAL(%a6)	# save in case of access error
   1111  1.1      is 	mov.b		&0x5,EXC_SAVREG(%a6)	# save regno, too
   1112  1.1      is 	mov.b		&restore_flg,SPCOND_FLG(%a6) # set flag
   1113  1.1      is 	rts
   1114  1.1      is 
   1115  1.1      is addr_ind_p_a6:
   1116  1.1      is 	mov.l		%a0,%d0			# copy no. bytes
   1117  1.1      is 	mov.l		EXC_A6(%a6),%a0		# load current value
   1118  1.1      is 	add.l		%a0,%d0			# increment
   1119  1.1      is 	mov.l		%d0,EXC_A6(%a6)		# save incremented value
   1120  1.1      is 
   1121  1.1      is 	mov.l		%a0,EXC_SAVVAL(%a6)	# save in case of access error
   1122  1.1      is 	mov.b		&0x6,EXC_SAVREG(%a6)	# save regno, too
   1123  1.1      is 	mov.b		&restore_flg,SPCOND_FLG(%a6) # set flag
   1124  1.1      is 	rts
   1125  1.1      is 
   1126  1.1      is addr_ind_p_a7:
   1127  1.1      is 	mov.b		&mia7_flg,SPCOND_FLG(%a6) # set "special case" flag
   1128  1.1      is 
   1129  1.1      is 	mov.l		%a0,%d0			# copy no. bytes
   1130  1.1      is 	mov.l		EXC_A7(%a6),%a0		# load current value
   1131  1.1      is 	add.l		%a0,%d0			# increment
   1132  1.1      is 	mov.l		%d0,EXC_A7(%a6)		# save incremented value
   1133  1.1      is 	rts
   1134  1.1      is 
   1135  1.1      is ####################################################
   1136  1.1      is # Address register indirect w/ predecrement: -(An) #
   1137  1.1      is ####################################################
   1138  1.1      is addr_ind_m_a0:
   1139  1.1      is 	mov.l		EXC_A0(%a6),%d0		# Get current a0
   1140  1.1      is 	mov.l		%d0,EXC_SAVVAL(%a6)	# save in case of access error
   1141  1.1      is 	sub.l		%a0,%d0			# Decrement
   1142  1.1      is 	mov.l		%d0,EXC_A0(%a6)		# Save decr value
   1143  1.1      is 	mov.l		%d0,%a0
   1144  1.1      is 
   1145  1.1      is 	mov.b		&0x0,EXC_SAVREG(%a6)	# save regno, too
   1146  1.1      is 	mov.b		&restore_flg,SPCOND_FLG(%a6) # set flag
   1147  1.1      is 	rts
   1148  1.1      is 
   1149  1.1      is addr_ind_m_a1:
   1150  1.1      is 	mov.l		EXC_A1(%a6),%d0		# Get current a1
   1151  1.1      is 	mov.l		%d0,EXC_SAVVAL(%a6)	# save in case of access error
   1152  1.1      is 	sub.l		%a0,%d0			# Decrement
   1153  1.1      is 	mov.l		%d0,EXC_A1(%a6)		# Save decr value
   1154  1.1      is 	mov.l		%d0,%a0
   1155  1.1      is 
   1156  1.1      is 	mov.b		&0x1,EXC_SAVREG(%a6)	# save regno, too
   1157  1.1      is 	mov.b		&restore_flg,SPCOND_FLG(%a6) # set flag
   1158  1.1      is 	rts
   1159  1.1      is 
   1160  1.1      is addr_ind_m_a2:
   1161  1.1      is 	mov.l		EXC_A2(%a6),%d0		# Get current a2
   1162  1.1      is 	mov.l		%d0,EXC_SAVVAL(%a6)	# save in case of access error
   1163  1.1      is 	sub.l		%a0,%d0			# Decrement
   1164  1.1      is 	mov.l		%d0,EXC_A2(%a6)		# Save decr value
   1165  1.1      is 	mov.l		%d0,%a0
   1166  1.1      is 
   1167  1.1      is 	mov.b		&0x2,EXC_SAVREG(%a6)	# save regno, too
   1168  1.1      is 	mov.b		&restore_flg,SPCOND_FLG(%a6) # set flag
   1169  1.1      is 	rts
   1170  1.1      is 
   1171  1.1      is addr_ind_m_a3:
   1172  1.1      is 	mov.l		EXC_A3(%a6),%d0		# Get current a3
   1173  1.1      is 	mov.l		%d0,EXC_SAVVAL(%a6)	# save in case of access error
   1174  1.1      is 	sub.l		%a0,%d0			# Decrement
   1175  1.1      is 	mov.l		%d0,EXC_A3(%a6)		# Save decr value
   1176  1.1      is 	mov.l		%d0,%a0
   1177  1.1      is 
   1178  1.1      is 	mov.b		&0x3,EXC_SAVREG(%a6)	# save regno, too
   1179  1.1      is 	mov.b		&restore_flg,SPCOND_FLG(%a6) # set flag
   1180  1.1      is 	rts
   1181  1.1      is 
   1182  1.1      is addr_ind_m_a4:
   1183  1.1      is 	mov.l		EXC_A4(%a6),%d0		# Get current a4
   1184  1.1      is 	mov.l		%d0,EXC_SAVVAL(%a6)	# save in case of access error
   1185  1.1      is 	sub.l		%a0,%d0			# Decrement
   1186  1.1      is 	mov.l		%d0,EXC_A4(%a6)		# Save decr value
   1187  1.1      is 	mov.l		%d0,%a0
   1188  1.1      is 
   1189  1.1      is 	mov.b		&0x4,EXC_SAVREG(%a6)	# save regno, too
   1190  1.1      is 	mov.b		&restore_flg,SPCOND_FLG(%a6) # set flag
   1191  1.1      is 	rts
   1192  1.1      is 
   1193  1.1      is addr_ind_m_a5:
   1194  1.1      is 	mov.l		EXC_A5(%a6),%d0		# Get current a5
   1195  1.1      is 	mov.l		%d0,EXC_SAVVAL(%a6)	# save in case of access error
   1196  1.1      is 	sub.l		%a0,%d0			# Decrement
   1197  1.1      is 	mov.l		%d0,EXC_A5(%a6)		# Save decr value
   1198  1.1      is 	mov.l		%d0,%a0
   1199  1.1      is 
   1200  1.1      is 	mov.b		&0x5,EXC_SAVREG(%a6)	# save regno, too
   1201  1.1      is 	mov.b		&restore_flg,SPCOND_FLG(%a6) # set flag
   1202  1.1      is 	rts
   1203  1.1      is 
   1204  1.1      is addr_ind_m_a6:
   1205  1.1      is 	mov.l		EXC_A6(%a6),%d0		# Get current a6
   1206  1.1      is 	mov.l		%d0,EXC_SAVVAL(%a6)	# save in case of access error
   1207  1.1      is 	sub.l		%a0,%d0			# Decrement
   1208  1.1      is 	mov.l		%d0,EXC_A6(%a6)		# Save decr value
   1209  1.1      is 	mov.l		%d0,%a0
   1210  1.1      is 
   1211  1.1      is 	mov.b		&0x6,EXC_SAVREG(%a6)	# save regno, too
   1212  1.1      is 	mov.b		&restore_flg,SPCOND_FLG(%a6) # set flag
   1213  1.1      is 	rts
   1214  1.1      is 
   1215  1.1      is addr_ind_m_a7:
   1216  1.1      is 	mov.b		&mda7_flg,SPCOND_FLG(%a6) # set "special case" flag
   1217  1.1      is 
   1218  1.1      is 	mov.l		EXC_A7(%a6),%d0		# Get current a7
   1219  1.1      is 	sub.l		%a0,%d0			# Decrement
   1220  1.1      is 	mov.l		%d0,EXC_A7(%a6)		# Save decr value
   1221  1.1      is 	mov.l		%d0,%a0
   1222  1.1      is 	rts
   1223  1.1      is 
   1224  1.1      is ########################################################
   1225  1.1      is # Address register indirect w/ displacement: (d16, An) #
   1226  1.1      is ########################################################
   1227  1.1      is addr_ind_disp_a0:
   1228  1.1      is 	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
   1229  1.1      is 	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
   1230  1.1      is 	bsr.l		_imem_read_word
   1231  1.1      is 
   1232  1.1      is 	tst.l		%d1			# ifetch error?
   1233  1.1      is 	bne.l		isp_iacc		# yes
   1234  1.1      is 
   1235  1.1      is 	mov.w		%d0,%a0			# sign extend displacement
   1236  1.1      is 	add.l		EXC_A0(%a6),%a0		# a0 + d16
   1237  1.1      is 	rts
   1238  1.1      is 
   1239  1.1      is addr_ind_disp_a1:
   1240  1.1      is 	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
   1241  1.1      is 	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
   1242  1.1      is 	bsr.l		_imem_read_word
   1243  1.1      is 
   1244  1.1      is 	tst.l		%d1			# ifetch error?
   1245  1.1      is 	bne.l		isp_iacc		# yes
   1246  1.1      is 
   1247  1.1      is 	mov.w		%d0,%a0			# sign extend displacement
   1248  1.1      is 	add.l		EXC_A1(%a6),%a0		# a1 + d16
   1249  1.1      is 	rts
   1250  1.1      is 
   1251  1.1      is addr_ind_disp_a2:
   1252  1.1      is 	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
   1253  1.1      is 	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
   1254  1.1      is 	bsr.l		_imem_read_word
   1255  1.1      is 
   1256  1.1      is 	tst.l		%d1			# ifetch error?
   1257  1.1      is 	bne.l		isp_iacc		# yes
   1258  1.1      is 
   1259  1.1      is 	mov.w		%d0,%a0			# sign extend displacement
   1260  1.1      is 	add.l		EXC_A2(%a6),%a0		# a2 + d16
   1261  1.1      is 	rts
   1262  1.1      is 
   1263  1.1      is addr_ind_disp_a3:
   1264  1.1      is 	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
   1265  1.1      is 	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
   1266  1.1      is 	bsr.l		_imem_read_word
   1267  1.1      is 
   1268  1.1      is 	tst.l		%d1			# ifetch error?
   1269  1.1      is 	bne.l		isp_iacc		# yes
   1270  1.1      is 
   1271  1.1      is 	mov.w		%d0,%a0			# sign extend displacement
   1272  1.1      is 	add.l		EXC_A3(%a6),%a0		# a3 + d16
   1273  1.1      is 	rts
   1274  1.1      is 
   1275  1.1      is addr_ind_disp_a4:
   1276  1.1      is 	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
   1277  1.1      is 	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
   1278  1.1      is 	bsr.l		_imem_read_word
   1279  1.1      is 
   1280  1.1      is 	tst.l		%d1			# ifetch error?
   1281  1.1      is 	bne.l		isp_iacc		# yes
   1282  1.1      is 
   1283  1.1      is 	mov.w		%d0,%a0			# sign extend displacement
   1284  1.1      is 	add.l		EXC_A4(%a6),%a0		# a4 + d16
   1285  1.1      is 	rts
   1286  1.1      is 
   1287  1.1      is addr_ind_disp_a5:
   1288  1.1      is 	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
   1289  1.1      is 	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
   1290  1.1      is 	bsr.l		_imem_read_word
   1291  1.1      is 
   1292  1.1      is 	tst.l		%d1			# ifetch error?
   1293  1.1      is 	bne.l		isp_iacc		# yes
   1294  1.1      is 
   1295  1.1      is 	mov.w		%d0,%a0			# sign extend displacement
   1296  1.1      is 	add.l		EXC_A5(%a6),%a0		# a5 + d16
   1297  1.1      is 	rts
   1298  1.1      is 
   1299  1.1      is addr_ind_disp_a6:
   1300  1.1      is 	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
   1301  1.1      is 	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
   1302  1.1      is 	bsr.l		_imem_read_word
   1303  1.1      is 
   1304  1.1      is 	tst.l		%d1			# ifetch error?
   1305  1.1      is 	bne.l		isp_iacc		# yes
   1306  1.1      is 
   1307  1.1      is 	mov.w		%d0,%a0			# sign extend displacement
   1308  1.1      is 	add.l		EXC_A6(%a6),%a0		# a6 + d16
   1309  1.1      is 	rts
   1310  1.1      is 
   1311  1.1      is addr_ind_disp_a7:
   1312  1.1      is 	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
   1313  1.1      is 	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
   1314  1.1      is 	bsr.l		_imem_read_word
   1315  1.1      is 
   1316  1.1      is 	tst.l		%d1			# ifetch error?
   1317  1.1      is 	bne.l		isp_iacc		# yes
   1318  1.1      is 
   1319  1.1      is 	mov.w		%d0,%a0			# sign extend displacement
   1320  1.1      is 	add.l		EXC_A7(%a6),%a0		# a7 + d16
   1321  1.1      is 	rts
   1322  1.1      is 
   1323  1.1      is ########################################################################
   1324  1.1      is # Address register indirect w/ index(8-bit displacement): (dn, An, Xn) #
   1325  1.1      is #    "       "         "    w/   "  (base displacement): (bd, An, Xn)  #
   1326  1.1      is # Memory indirect postindexed: ([bd, An], Xn, od)		       #
   1327  1.1      is # Memory indirect preindexed: ([bd, An, Xn], od)		       #
   1328  1.1      is ########################################################################
   1329  1.1      is _addr_ind_ext:
   1330  1.1      is 	mov.l		%d1,-(%sp)
   1331  1.1      is 
   1332  1.1      is 	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
   1333  1.1      is 	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
   1334  1.1      is 	bsr.l		_imem_read_word		# fetch extword in d0
   1335  1.1      is 
   1336  1.1      is 	tst.l		%d1			# ifetch error?
   1337  1.1      is 	bne.l		isp_iacc		# yes
   1338  1.1      is 
   1339  1.1      is 	mov.l		(%sp)+,%d1
   1340  1.1      is 
   1341  1.1      is 	mov.l		(EXC_AREGS,%a6,%d1.w*4),%a0 # put base in a0
   1342  1.1      is 
   1343  1.1      is 	btst		&0x8,%d0
   1344  1.1      is 	beq.b		addr_ind_index_8bit	# for ext word or not?
   1345  1.1      is 
   1346  1.1      is 	movm.l		&0x3c00,-(%sp)		# save d2-d5
   1347  1.1      is 
   1348  1.1      is 	mov.l		%d0,%d5			# put extword in d5
   1349  1.1      is 	mov.l		%a0,%d3			# put base in d3
   1350  1.1      is 
   1351  1.1      is 	bra.l		calc_mem_ind		# calc memory indirect
   1352  1.1      is 
   1353  1.1      is addr_ind_index_8bit:
   1354  1.1      is 	mov.l		%d2,-(%sp)		# save old d2
   1355  1.1      is 
   1356  1.1      is 	mov.l		%d0,%d1
   1357  1.1      is 	rol.w		&0x4,%d1
   1358  1.1      is 	andi.w		&0xf,%d1		# extract index regno
   1359  1.1      is 
   1360  1.1      is 	mov.l		(EXC_DREGS,%a6,%d1.w*4),%d1 # fetch index reg value
   1361  1.1      is 
   1362  1.1      is 	btst		&0xb,%d0		# is it word or long?
   1363  1.1      is 	bne.b		aii8_long
   1364  1.1      is 	ext.l		%d1			# sign extend word index
   1365  1.1      is aii8_long:
   1366  1.1      is 	mov.l		%d0,%d2
   1367  1.1      is 	rol.w		&0x7,%d2
   1368  1.1      is 	andi.l		&0x3,%d2		# extract scale value
   1369  1.1      is 
   1370  1.1      is 	lsl.l		%d2,%d1			# shift index by scale
   1371  1.1      is 
   1372  1.1      is 	extb.l		%d0			# sign extend displacement
   1373  1.1      is 	add.l		%d1,%d0			# index + disp
   1374  1.1      is 	add.l		%d0,%a0			# An + (index + disp)
   1375  1.1      is 
   1376  1.1      is 	mov.l		(%sp)+,%d2		# restore old d2
   1377  1.1      is 	rts
   1378  1.1      is 
   1379  1.1      is ######################
   1380  1.1      is # Immediate: #<data> #
   1381  1.1      is #########################################################################
   1382  1.1      is # word, long: <ea> of the data is the current extension word		#
   1383  1.1      is # 	pointer value. new extension word pointer is simply the old	#
   1384  1.1      is # 	plus the number of bytes in the data type(2 or 4).		#
   1385  1.1      is #########################################################################
   1386  1.1      is immediate:
   1387  1.1      is 	mov.b		&immed_flg,SPCOND_FLG(%a6) # set immediate flag
   1388  1.1      is 
   1389  1.1      is 	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch extension word ptr
   1390  1.1      is 	rts
   1391  1.1      is 
   1392  1.1      is ###########################
   1393  1.1      is # Absolute short: (XXX).W #
   1394  1.1      is ###########################
   1395  1.1      is abs_short:
   1396  1.1      is 	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
   1397  1.1      is 	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
   1398  1.1      is 	bsr.l		_imem_read_word		# fetch short address
   1399  1.1      is 
   1400  1.1      is 	tst.l		%d1			# ifetch error?
   1401  1.1      is 	bne.l		isp_iacc		# yes
   1402  1.1      is 
   1403  1.1      is 	mov.w		%d0,%a0			# return <ea> in a0
   1404  1.1      is 	rts
   1405  1.1      is 
   1406  1.1      is ##########################
   1407  1.1      is # Absolute long: (XXX).L #
   1408  1.1      is ##########################
   1409  1.1      is abs_long:
   1410  1.1      is 	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
   1411  1.1      is 	addq.l		&0x4,EXC_EXTWPTR(%a6)	# incr instruction ptr
   1412  1.1      is 	bsr.l		_imem_read_long		# fetch long address
   1413  1.1      is 
   1414  1.1      is 	tst.l		%d1			# ifetch error?
   1415  1.1      is 	bne.l		isp_iacc		# yes
   1416  1.1      is 
   1417  1.1      is 	mov.l		%d0,%a0			# return <ea> in a0
   1418  1.1      is 	rts
   1419  1.1      is 
   1420  1.1      is #######################################################
   1421  1.1      is # Program counter indirect w/ displacement: (d16, PC) #
   1422  1.1      is #######################################################
   1423  1.1      is pc_ind:
   1424  1.1      is 	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
   1425  1.1      is 	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
   1426  1.1      is 	bsr.l		_imem_read_word		# fetch word displacement
   1427  1.1      is 
   1428  1.1      is 	tst.l		%d1			# ifetch error?
   1429  1.1      is 	bne.l		isp_iacc		# yes
   1430  1.1      is 
   1431  1.1      is 	mov.w		%d0,%a0			# sign extend displacement
   1432  1.1      is 
   1433  1.1      is 	add.l		EXC_EXTWPTR(%a6),%a0	# pc + d16
   1434  1.1      is 
   1435  1.1      is # _imem_read_word() increased the extwptr by 2. need to adjust here.
   1436  1.1      is 	subq.l		&0x2,%a0		# adjust <ea>
   1437  1.1      is 
   1438  1.1      is 	rts
   1439  1.1      is 
   1440  1.1      is ##########################################################
   1441  1.1      is # PC indirect w/ index(8-bit displacement): (d8, PC, An) #
   1442  1.1      is # "     "     w/   "  (base displacement): (bd, PC, An)  #
   1443  1.1      is # PC memory indirect postindexed: ([bd, PC], Xn, od)     #
   1444  1.1      is # PC memory indirect preindexed: ([bd, PC, Xn], od)      #
   1445  1.1      is ##########################################################
   1446  1.1      is pc_ind_ext:
   1447  1.1      is 	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
   1448  1.1      is 	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
   1449  1.1      is 	bsr.l		_imem_read_word		# fetch ext word
   1450  1.1      is 
   1451  1.1      is 	tst.l		%d1			# ifetch error?
   1452  1.1      is 	bne.l		isp_iacc		# yes
   1453  1.1      is 
   1454  1.1      is 	mov.l		EXC_EXTWPTR(%a6),%a0	# put base in a0
   1455  1.1      is 	subq.l		&0x2,%a0		# adjust base
   1456  1.1      is 
   1457  1.1      is 	btst		&0x8,%d0		# is disp only 8 bits?
   1458  1.1      is 	beq.b		pc_ind_index_8bit	# yes
   1459  1.1      is 
   1460  1.1      is # the indexed addressing mode uses a base displacement of size
   1461  1.1      is # word or long
   1462  1.1      is 	movm.l		&0x3c00,-(%sp)		# save d2-d5
   1463  1.1      is 
   1464  1.1      is 	mov.l		%d0,%d5			# put extword in d5
   1465  1.1      is 	mov.l		%a0,%d3			# put base in d3
   1466  1.1      is 
   1467  1.1      is 	bra.l		calc_mem_ind		# calc memory indirect
   1468  1.1      is 
   1469  1.1      is pc_ind_index_8bit:
   1470  1.1      is  	mov.l		%d2,-(%sp)		# create a temp register
   1471  1.1      is 
   1472  1.1      is 	mov.l		%d0,%d1			# make extword copy
   1473  1.1      is 	rol.w		&0x4,%d1		# rotate reg num into place
   1474  1.1      is 	andi.w		&0xf,%d1		# extract register number
   1475  1.1      is 
   1476  1.1      is 	mov.l		(EXC_DREGS,%a6,%d1.w*4),%d1 # fetch index reg value
   1477  1.1      is 
   1478  1.1      is 	btst		&0xb,%d0		# is index word or long?
   1479  1.1      is 	bne.b		pii8_long		# long
   1480  1.1      is 	ext.l		%d1			# sign extend word index
   1481  1.1      is pii8_long:
   1482  1.1      is 	mov.l		%d0,%d2			# make extword copy
   1483  1.1      is 	rol.w		&0x7,%d2		# rotate scale value into place
   1484  1.1      is 	andi.l		&0x3,%d2		# extract scale value
   1485  1.1      is 
   1486  1.1      is 	lsl.l		%d2,%d1			# shift index by scale
   1487  1.1      is 
   1488  1.1      is 	extb.l		%d0			# sign extend displacement
   1489  1.1      is 	add.l		%d1,%d0			# index + disp
   1490  1.1      is 	add.l		%d0,%a0			# An + (index + disp)
   1491  1.1      is 
   1492  1.1      is 	mov.l		(%sp)+,%d2		# restore temp register
   1493  1.1      is 
   1494  1.1      is 	rts
   1495  1.1      is 
   1496  1.1      is # a5 = exc_extwptr	(global to uaeh)
   1497  1.1      is # a4 = exc_opword	(global to uaeh)
   1498  1.1      is # a3 = exc_dregs	(global to uaeh)
   1499  1.1      is 
   1500  1.1      is # d2 = index		(internal "     "    )
   1501  1.1      is # d3 = base		(internal "     "    )
   1502  1.1      is # d4 = od		(internal "     "    )
   1503  1.1      is # d5 = extword		(internal "     "    )
   1504  1.1      is calc_mem_ind:
   1505  1.1      is 	btst		&0x6,%d5		# is the index suppressed?
   1506  1.1      is 	beq.b		calc_index
   1507  1.1      is 	clr.l		%d2			# yes, so index = 0
   1508  1.1      is 	bra.b		base_supp_ck
   1509  1.1      is calc_index:
   1510  1.1      is 	bfextu		%d5{&16:&4},%d2
   1511  1.1      is 	mov.l		(EXC_DREGS,%a6,%d2.w*4),%d2
   1512  1.1      is 	btst		&0xb,%d5		# is index word or long?
   1513  1.1      is 	bne.b		no_ext
   1514  1.1      is 	ext.l		%d2
   1515  1.1      is no_ext:
   1516  1.1      is 	bfextu		%d5{&21:&2},%d0
   1517  1.1      is 	lsl.l		%d0,%d2
   1518  1.1      is base_supp_ck:
   1519  1.1      is 	btst		&0x7,%d5		# is the bd suppressed?
   1520  1.1      is 	beq.b		no_base_sup
   1521  1.1      is 	clr.l		%d3
   1522  1.1      is no_base_sup:
   1523  1.1      is 	bfextu		%d5{&26:&2},%d0	# get bd size
   1524  1.1      is #	beq.l		_error			# if (size == 0) it's reserved
   1525  1.1      is 	cmpi.b	 	%d0,&2
   1526  1.1      is 	blt.b		no_bd
   1527  1.1      is 	beq.b		get_word_bd
   1528  1.1      is 
   1529  1.1      is 	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
   1530  1.1      is 	addq.l		&0x4,EXC_EXTWPTR(%a6)	# incr instruction ptr
   1531  1.1      is 	bsr.l		_imem_read_long
   1532  1.1      is 
   1533  1.1      is 	tst.l		%d1			# ifetch error?
   1534  1.1      is 	bne.l		isp_iacc		# yes
   1535  1.1      is 
   1536  1.1      is 	bra.b		chk_ind
   1537  1.1      is get_word_bd:
   1538  1.1      is 	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
   1539  1.1      is 	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
   1540  1.1      is 	bsr.l		_imem_read_word
   1541  1.1      is 
   1542  1.1      is 	tst.l		%d1			# ifetch error?
   1543  1.1      is 	bne.l		isp_iacc		# yes
   1544  1.1      is 
   1545  1.1      is 	ext.l		%d0			# sign extend bd
   1546  1.1      is 
   1547  1.1      is chk_ind:
   1548  1.1      is 	add.l		%d0,%d3			# base += bd
   1549  1.1      is no_bd:
   1550  1.1      is 	bfextu		%d5{&30:&2},%d0		# is od suppressed?
   1551  1.1      is 	beq.w		aii_bd
   1552  1.1      is 	cmpi.b	 	%d0,&0x2
   1553  1.1      is 	blt.b		null_od
   1554  1.1      is 	beq.b		word_od
   1555  1.1      is 
   1556  1.1      is 	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
   1557  1.1      is 	addq.l		&0x4,EXC_EXTWPTR(%a6)	# incr instruction ptr
   1558  1.1      is 	bsr.l		_imem_read_long
   1559  1.1      is 
   1560  1.1      is 	tst.l		%d1			# ifetch error?
   1561  1.1      is 	bne.l		isp_iacc		# yes
   1562  1.1      is 
   1563  1.1      is 	bra.b 		add_them
   1564  1.1      is 
   1565  1.1      is word_od:
   1566  1.1      is 	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
   1567  1.1      is 	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
   1568  1.1      is 	bsr.l		_imem_read_word
   1569  1.1      is 
   1570  1.1      is 	tst.l		%d1			# ifetch error?
   1571  1.1      is 	bne.l		isp_iacc		# yes
   1572  1.1      is 
   1573  1.1      is 	ext.l		%d0			# sign extend od
   1574  1.1      is 	bra.b		add_them
   1575  1.1      is 
   1576  1.1      is null_od:
   1577  1.1      is 	clr.l		%d0
   1578  1.1      is add_them:
   1579  1.1      is 	mov.l		%d0,%d4
   1580  1.1      is 	btst		&0x2,%d5		# pre or post indexing?
   1581  1.1      is 	beq.b		pre_indexed
   1582  1.1      is 
   1583  1.1      is 	mov.l		%d3,%a0
   1584  1.1      is 	bsr.l		_dmem_read_long
   1585  1.1      is 
   1586  1.1      is 	tst.l		%d1			# dfetch error?
   1587  1.1      is 	bne.b		calc_ea_err		# yes
   1588  1.1      is 
   1589  1.1      is 	add.l		%d2,%d0			# <ea> += index
   1590  1.1      is 	add.l		%d4,%d0			# <ea> += od
   1591  1.1      is 	bra.b		done_ea
   1592  1.1      is 
   1593  1.1      is pre_indexed:
   1594  1.1      is 	add.l		%d2,%d3			# preindexing
   1595  1.1      is 	mov.l		%d3,%a0
   1596  1.1      is 	bsr.l		_dmem_read_long
   1597  1.1      is 
   1598  1.1      is 	tst.l		%d1			# ifetch error?
   1599  1.1      is 	bne.b		calc_ea_err		# yes
   1600  1.1      is 
   1601  1.1      is 	add.l		%d4,%d0			# ea += od
   1602  1.1      is 	bra.b		done_ea
   1603  1.1      is 
   1604  1.1      is aii_bd:
   1605  1.1      is 	add.l		%d2,%d3			# ea = (base + bd) + index
   1606  1.1      is 	mov.l		%d3,%d0
   1607  1.1      is done_ea:
   1608  1.1      is 	mov.l		%d0,%a0
   1609  1.1      is 
   1610  1.1      is 	movm.l		(%sp)+,&0x003c		# restore d2-d5
   1611  1.1      is 	rts
   1612  1.1      is 
   1613  1.1      is # if dmem_read_long() returns a fail message in d1, the package
   1614  1.1      is # must create an access error frame. here, we pass a skeleton fslw
   1615  1.1      is # and the failing address to the routine that creates the new frame.
   1616  1.1      is # FSLW:
   1617  1.1      is # 	read = true
   1618  1.1      is # 	size = longword
   1619  1.1      is #	TM = data
   1620  1.1      is # 	software emulation error = true
   1621  1.1      is calc_ea_err:
   1622  1.1      is 	mov.l		%d3,%a0			# pass failing address
   1623  1.1      is 	mov.l		&0x01010001,%d0		# pass fslw
   1624  1.1      is 	bra.l		isp_dacc
   1625  1.1      is 
   1626  1.1      is #########################################################################
   1627  1.1      is # XDEF **************************************************************** #
   1628  1.1      is # 	_moveperipheral(): routine to emulate movep instruction		#
   1629  1.1      is #									#
   1630  1.1      is # XREF **************************************************************** #
   1631  1.1      is #	_dmem_read_byte() - read byte from memory			#
   1632  1.1      is #	_dmem_write_byte() - write byte to memory			#
   1633  1.1      is #	isp_dacc() - handle data access error exception			#
   1634  1.1      is #									#
   1635  1.1      is # INPUT *************************************************************** #
   1636  1.1      is #	none								#
   1637  1.1      is #									#
   1638  1.1      is # OUTPUT ************************************************************** #
   1639  1.1      is #	If exiting through isp_dacc...					#
   1640  1.1      is #		a0 = failing address					#
   1641  1.1      is #		d0 = FSLW						#
   1642  1.1      is #	else								#
   1643  1.1      is #		none							#
   1644  1.1      is #									#
   1645  1.1      is # ALGORITHM ***********************************************************	#
   1646  1.1      is #	Decode the movep instruction words stored at EXC_OPWORD and	#
   1647  1.1      is # either read or write the required bytes from/to memory. Use the	#
   1648  1.1      is # _dmem_{read,write}_byte() routines. If one of the memory routines	#
   1649  1.1      is # returns a failing value, we must pass the failing address and	a FSLW	#
   1650  1.1      is # to the _isp_dacc() routine.						#
   1651  1.1      is #	Since this instruction is used to access peripherals, make sure	#
   1652  1.1      is # to only access the required bytes.					#
   1653  1.1      is #									#
   1654  1.1      is #########################################################################
   1655  1.1      is 
   1656  1.1      is ###########################
   1657  1.1      is # movep.(w,l)	Dx,(d,Ay) #
   1658  1.1      is # movep.(w,l)	(d,Ay),Dx #
   1659  1.1      is ###########################
   1660  1.1      is 	global 		_moveperipheral
   1661  1.1      is _moveperipheral:
   1662  1.1      is 	mov.w		EXC_OPWORD(%a6),%d1	# fetch the opcode word
   1663  1.1      is 
   1664  1.1      is 	mov.b		%d1,%d0
   1665  1.1      is 	and.w		&0x7,%d0		# extract Ay from opcode word
   1666  1.1      is 
   1667  1.1      is 	mov.l		(EXC_AREGS,%a6,%d0.w*4),%a0 # fetch ay
   1668  1.1      is 
   1669  1.1      is 	add.w		EXC_EXTWORD(%a6),%a0	# add: an + sgn_ext(disp)
   1670  1.1      is 
   1671  1.1      is 	btst		&0x7,%d1		# (reg 2 mem) or (mem 2 reg)
   1672  1.1      is 	beq.w		mem2reg
   1673  1.1      is 
   1674  1.1      is # reg2mem: fetch dx, then write it to memory
   1675  1.1      is reg2mem:
   1676  1.1      is 	mov.w		%d1,%d0
   1677  1.1      is 	rol.w		&0x7,%d0
   1678  1.1      is 	and.w		&0x7,%d0		# extract Dx from opcode word
   1679  1.1      is 
   1680  1.1      is 	mov.l		(EXC_DREGS,%a6,%d0.w*4), %d0 # fetch dx
   1681  1.1      is 
   1682  1.1      is 	btst		&0x6,%d1		# word or long operation?
   1683  1.1      is 	beq.b		r2mwtrans
   1684  1.1      is 
   1685  1.1      is # a0 = dst addr
   1686  1.1      is # d0 = Dx
   1687  1.1      is r2mltrans:
   1688  1.1      is 	mov.l		%d0,%d2			# store data
   1689  1.1      is 	mov.l		%a0,%a2			# store addr
   1690  1.1      is 	rol.l		&0x8,%d2
   1691  1.1      is 	mov.l		%d2,%d0
   1692  1.1      is 
   1693  1.1      is 	bsr.l		_dmem_write_byte	# os  : write hi
   1694  1.1      is 
   1695  1.1      is 	tst.l		%d1			# dfetch error?
   1696  1.1      is 	bne.w		movp_write_err		# yes
   1697  1.1      is 
   1698  1.1      is 	add.w		&0x2,%a2		# incr addr
   1699  1.1      is 	mov.l		%a2,%a0
   1700  1.1      is 	rol.l		&0x8,%d2
   1701  1.1      is 	mov.l		%d2,%d0
   1702  1.1      is 
   1703  1.1      is 	bsr.l		_dmem_write_byte	# os  : write lo
   1704  1.1      is 
   1705  1.1      is 	tst.l		%d1			# dfetch error?
   1706  1.1      is 	bne.w		movp_write_err		# yes
   1707  1.1      is 
   1708  1.1      is 	add.w		&0x2,%a2		# incr addr
   1709  1.1      is 	mov.l		%a2,%a0
   1710  1.1      is 	rol.l		&0x8,%d2
   1711  1.1      is 	mov.l		%d2,%d0
   1712  1.1      is 
   1713  1.1      is 	bsr.l		_dmem_write_byte	# os  : write lo
   1714  1.1      is 
   1715  1.1      is 	tst.l		%d1			# dfetch error?
   1716  1.1      is 	bne.w		movp_write_err		# yes
   1717  1.1      is 
   1718  1.1      is 	add.w		&0x2,%a2		# incr addr
   1719  1.1      is 	mov.l		%a2,%a0
   1720  1.1      is 	rol.l		&0x8,%d2
   1721  1.1      is 	mov.l		%d2,%d0
   1722  1.1      is 
   1723  1.1      is 	bsr.l		_dmem_write_byte	# os  : write lo
   1724  1.1      is 
   1725  1.1      is 	tst.l		%d1			# dfetch error?
   1726  1.1      is 	bne.w		movp_write_err		# yes
   1727  1.1      is 
   1728  1.1      is 	rts
   1729  1.1      is 
   1730  1.1      is # a0 = dst addr
   1731  1.1      is # d0 = Dx
   1732  1.1      is r2mwtrans:
   1733  1.1      is 	mov.l		%d0,%d2			# store data
   1734  1.1      is 	mov.l		%a0,%a2			# store addr
   1735  1.1      is 	lsr.w		&0x8,%d0
   1736  1.1      is 
   1737  1.1      is 	bsr.l		_dmem_write_byte	# os  : write hi
   1738  1.1      is 
   1739  1.1      is 	tst.l		%d1			# dfetch error?
   1740  1.1      is 	bne.w		movp_write_err		# yes
   1741  1.1      is 
   1742  1.1      is 	add.w		&0x2,%a2
   1743  1.1      is 	mov.l		%a2,%a0
   1744  1.1      is 	mov.l		%d2,%d0
   1745  1.1      is 
   1746  1.1      is 	bsr.l		_dmem_write_byte	# os  : write lo
   1747  1.1      is 
   1748  1.1      is 	tst.l		%d1			# dfetch error?
   1749  1.1      is 	bne.w		movp_write_err		# yes
   1750  1.1      is 
   1751  1.1      is 	rts
   1752  1.1      is 
   1753  1.1      is # mem2reg: read bytes from memory.
   1754  1.1      is # determines the dest register, and then writes the bytes into it.
   1755  1.1      is mem2reg:
   1756  1.1      is 	btst		&0x6,%d1		# word or long operation?
   1757  1.1      is 	beq.b		m2rwtrans
   1758  1.1      is 
   1759  1.1      is # a0 = dst addr
   1760  1.1      is m2rltrans:
   1761  1.1      is 	mov.l		%a0,%a2			# store addr
   1762  1.1      is 
   1763  1.1      is 	bsr.l		_dmem_read_byte		# read first byte
   1764  1.1      is 
   1765  1.1      is 	tst.l		%d1			# dfetch error?
   1766  1.1      is 	bne.w		movp_read_err		# yes
   1767  1.1      is 
   1768  1.1      is 	mov.l		%d0,%d2
   1769  1.1      is 
   1770  1.1      is 	add.w		&0x2,%a2		# incr addr by 2 bytes
   1771  1.1      is 	mov.l		%a2,%a0
   1772  1.1      is 
   1773  1.1      is 	bsr.l		_dmem_read_byte		# read second byte
   1774  1.1      is 
   1775  1.1      is 	tst.l		%d1			# dfetch error?
   1776  1.1      is 	bne.w		movp_read_err		# yes
   1777  1.1      is 
   1778  1.1      is 	lsl.w		&0x8,%d2
   1779  1.1      is 	mov.b		%d0,%d2			# append bytes
   1780  1.1      is 
   1781  1.1      is 	add.w		&0x2,%a2		# incr addr by 2 bytes
   1782  1.1      is 	mov.l		%a2,%a0
   1783  1.1      is 
   1784  1.1      is 	bsr.l		_dmem_read_byte		# read second byte
   1785  1.1      is 
   1786  1.1      is 	tst.l		%d1			# dfetch error?
   1787  1.1      is 	bne.w		movp_read_err		# yes
   1788  1.1      is 
   1789  1.1      is 	lsl.l		&0x8,%d2
   1790  1.1      is 	mov.b		%d0,%d2			# append bytes
   1791  1.1      is 
   1792  1.1      is 	add.w		&0x2,%a2		# incr addr by 2 bytes
   1793  1.1      is 	mov.l		%a2,%a0
   1794  1.1      is 
   1795  1.1      is 	bsr.l		_dmem_read_byte		# read second byte
   1796  1.1      is 
   1797  1.1      is 	tst.l		%d1			# dfetch error?
   1798  1.1      is 	bne.w		movp_read_err		# yes
   1799  1.1      is 
   1800  1.1      is 	lsl.l		&0x8,%d2
   1801  1.1      is 	mov.b		%d0,%d2			# append bytes
   1802  1.1      is 
   1803  1.1      is 	mov.b		EXC_OPWORD(%a6),%d1
   1804  1.1      is 	lsr.b		&0x1,%d1
   1805  1.1      is 	and.w		&0x7,%d1		# extract Dx from opcode word
   1806  1.1      is 
   1807  1.1      is 	mov.l		%d2,(EXC_DREGS,%a6,%d1.w*4) # store dx
   1808  1.1      is 
   1809  1.1      is 	rts
   1810  1.1      is 
   1811  1.1      is # a0 = dst addr
   1812  1.1      is m2rwtrans:
   1813  1.1      is 	mov.l		%a0,%a2			# store addr
   1814  1.1      is 
   1815  1.1      is 	bsr.l		_dmem_read_byte		# read first byte
   1816  1.1      is 
   1817  1.1      is 	tst.l		%d1			# dfetch error?
   1818  1.1      is 	bne.w		movp_read_err		# yes
   1819  1.1      is 
   1820  1.1      is 	mov.l		%d0,%d2
   1821  1.1      is 
   1822  1.1      is 	add.w		&0x2,%a2		# incr addr by 2 bytes
   1823  1.1      is 	mov.l		%a2,%a0
   1824  1.1      is 
   1825  1.1      is 	bsr.l		_dmem_read_byte		# read second byte
   1826  1.1      is 
   1827  1.1      is 	tst.l		%d1			# dfetch error?
   1828  1.1      is 	bne.w		movp_read_err		# yes
   1829  1.1      is 
   1830  1.1      is 	lsl.w		&0x8,%d2
   1831  1.1      is 	mov.b		%d0,%d2			# append bytes
   1832  1.1      is 
   1833  1.1      is 	mov.b		EXC_OPWORD(%a6),%d1
   1834  1.1      is 	lsr.b		&0x1,%d1
   1835  1.1      is 	and.w		&0x7,%d1		# extract Dx from opcode word
   1836  1.1      is 
   1837  1.1      is 	mov.w		%d2,(EXC_DREGS+2,%a6,%d1.w*4) # store dx
   1838  1.1      is 
   1839  1.1      is 	rts
   1840  1.1      is 
   1841  1.1      is # if dmem_{read,write}_byte() returns a fail message in d1, the package
   1842  1.1      is # must create an access error frame. here, we pass a skeleton fslw
   1843  1.1      is # and the failing address to the routine that creates the new frame.
   1844  1.1      is # FSLW:
   1845  1.1      is # 	write = true
   1846  1.1      is #	size = byte
   1847  1.1      is #	TM = data
   1848  1.1      is #	software emulation error = true
   1849  1.1      is movp_write_err:
   1850  1.1      is 	mov.l		%a2,%a0			# pass failing address
   1851  1.1      is 	mov.l		&0x00a10001,%d0		# pass fslw
   1852  1.1      is 	bra.l		isp_dacc
   1853  1.1      is 
   1854  1.1      is # FSLW:
   1855  1.1      is # 	read = true
   1856  1.1      is #	size = byte
   1857  1.1      is #	TM = data
   1858  1.1      is #	software emulation error = true
   1859  1.1      is movp_read_err:
   1860  1.1      is 	mov.l		%a2,%a0			# pass failing address
   1861  1.1      is 	mov.l		&0x01210001,%d0		# pass fslw
   1862  1.1      is 	bra.l		isp_dacc
   1863  1.1      is 
   1864  1.1      is #########################################################################
   1865  1.1      is # XDEF ****************************************************************	#
   1866  1.1      is # 	_chk2_cmp2(): routine to emulate chk2/cmp2 instructions		#
   1867  1.1      is #									#
   1868  1.1      is # XREF ****************************************************************	#
   1869  1.1      is #	_calc_ea(): calculate effective address				#
   1870  1.1      is #	_dmem_read_long(): read operands				#
   1871  1.1      is # 	_dmem_read_word(): read operands				#
   1872  1.1      is #	isp_dacc(): handle data access error exception			#
   1873  1.1      is #									#
   1874  1.1      is # INPUT ***************************************************************	#
   1875  1.1      is #	none								#
   1876  1.1      is #									#
   1877  1.1      is # OUTPUT **************************************************************	#
   1878  1.1      is #	If exiting through isp_dacc...					#
   1879  1.1      is #		a0 = failing address					#
   1880  1.1      is #		d0 = FSLW						#
   1881  1.1      is #	else								#
   1882  1.1      is # 		none							#
   1883  1.1      is #									#
   1884  1.1      is # ALGORITHM ***********************************************************	#
   1885  1.1      is #	First, calculate the effective address, then fetch the byte,	#
   1886  1.1      is # word, or longword sized operands. Then, in the interest of 		#
   1887  1.1      is # simplicity, all operands are converted to longword size whether the 	#
   1888  1.1      is # operation is byte, word, or long. The bounds are sign extended 	#
   1889  1.3   kamil # accordingly. If Rn is a data register, Rn is also sign extended. If 	#
   1890  1.1      is # Rn is an address register, it need not be sign extended since the 	#
   1891  1.1      is # full register is always used.						#
   1892  1.1      is #	The comparisons are made and the condition codes calculated.	#
   1893  1.1      is # If the instruction is chk2 and the Rn value is out-of-bounds, set	#
   1894  1.1      is # the ichk_flg in SPCOND_FLG.						#
   1895  1.1      is #	If the memory fetch returns a failing value, pass the failing 	#
   1896  1.1      is # address and FSLW to the isp_dacc() routine.				#
   1897  1.1      is #									#
   1898  1.1      is #########################################################################
   1899  1.1      is 
   1900  1.1      is 	global 		_chk2_cmp2
   1901  1.1      is _chk2_cmp2:
   1902  1.1      is 
   1903  1.1      is # passing size parameter doesn't matter since chk2 & cmp2 can't do
   1904  1.1      is # either predecrement, postincrement, or immediate.
   1905  1.1      is 	bsr.l		_calc_ea		# calculate <ea>
   1906  1.1      is 
   1907  1.1      is 	mov.b		EXC_EXTWORD(%a6), %d0	# fetch hi extension word
   1908  1.1      is 	rol.b		&0x4, %d0		# rotate reg bits into lo
   1909  1.1      is 	and.w		&0xf, %d0		# extract reg bits
   1910  1.1      is 
   1911  1.1      is 	mov.l		(EXC_DREGS,%a6,%d0.w*4), %d2 # get regval
   1912  1.1      is 
   1913  1.1      is 	cmpi.b		EXC_OPWORD(%a6), &0x2	# what size is operation?
   1914  1.1      is 	blt.b		chk2_cmp2_byte		# size == byte
   1915  1.1      is 	beq.b		chk2_cmp2_word		# size == word
   1916  1.1      is 
   1917  1.1      is # the bounds are longword size. call routine to read the lower
   1918  1.1      is # bound into d0 and the higher bound into d1.
   1919  1.1      is chk2_cmp2_long:
   1920  1.1      is 	mov.l		%a0,%a2			# save copy of <ea>
   1921  1.1      is 	bsr.l		_dmem_read_long		# fetch long lower bound
   1922  1.1      is 
   1923  1.1      is 	tst.l		%d1			# dfetch error?
   1924  1.1      is 	bne.w		chk2_cmp2_err_l		# yes
   1925  1.1      is 
   1926  1.1      is 	mov.l		%d0,%d3			# save long lower bound
   1927  1.1      is 	addq.l		&0x4,%a2
   1928  1.1      is 	mov.l		%a2,%a0			# pass <ea> of long upper bound
   1929  1.1      is 	bsr.l		_dmem_read_long		# fetch long upper bound
   1930  1.1      is 
   1931  1.1      is 	tst.l		%d1			# dfetch error?
   1932  1.1      is 	bne.w		chk2_cmp2_err_l		# yes
   1933  1.1      is 
   1934  1.1      is 	mov.l		%d0,%d1			# long upper bound in d1
   1935  1.1      is 	mov.l		%d3,%d0			# long lower bound in d0
   1936  1.1      is 	bra.w		chk2_cmp2_compare	# go do the compare emulation
   1937  1.1      is 
   1938  1.1      is # the bounds are word size. fetch them in one subroutine call by
   1939  1.1      is # reading a longword. sign extend both. if it's a data operation,
   1940  1.1      is # sign extend Rn to long, also.
   1941  1.1      is chk2_cmp2_word:
   1942  1.1      is 	mov.l		%a0,%a2
   1943  1.1      is 	bsr.l		_dmem_read_long		# fetch 2 word bounds
   1944  1.1      is 
   1945  1.1      is 	tst.l		%d1			# dfetch error?
   1946  1.1      is 	bne.w		chk2_cmp2_err_l		# yes
   1947  1.1      is 
   1948  1.1      is 	mov.w		%d0, %d1		# place hi in %d1
   1949  1.1      is 	swap		%d0			# place lo in %d0
   1950  1.1      is 
   1951  1.1      is 	ext.l		%d0			# sign extend lo bnd
   1952  1.1      is 	ext.l		%d1			# sign extend hi bnd
   1953  1.1      is 
   1954  1.1      is 	btst		&0x7, EXC_EXTWORD(%a6)	# address compare?
   1955  1.1      is 	bne.w		chk2_cmp2_compare	# yes; don't sign extend
   1956  1.1      is 
   1957  1.1      is # operation is a data register compare.
   1958  1.1      is # sign extend word to long so we can do simple longword compares.
   1959  1.1      is 	ext.l		%d2			# sign extend data word
   1960  1.1      is 	bra.w		chk2_cmp2_compare	# go emulate compare
   1961  1.1      is 
   1962  1.1      is # the bounds are byte size. fetch them in one subroutine call by
   1963  1.1      is # reading a word. sign extend both. if it's a data operation,
   1964  1.1      is # sign extend Rn to long, also.
   1965  1.1      is chk2_cmp2_byte:
   1966  1.1      is 	mov.l		%a0,%a2
   1967  1.1      is 	bsr.l		_dmem_read_word		# fetch 2 byte bounds
   1968  1.1      is 
   1969  1.1      is 	tst.l		%d1			# dfetch error?
   1970  1.1      is 	bne.w		chk2_cmp2_err_w		# yes
   1971  1.1      is 
   1972  1.1      is 	mov.b		%d0, %d1		# place hi in %d1
   1973  1.1      is 	lsr.w		&0x8, %d0		# place lo in %d0
   1974  1.1      is 
   1975  1.1      is 	extb.l		%d0			# sign extend lo bnd
   1976  1.1      is 	extb.l		%d1			# sign extend hi bnd
   1977  1.1      is 
   1978  1.1      is 	btst		&0x7, EXC_EXTWORD(%a6)	# address compare?
   1979  1.1      is 	bne.b		chk2_cmp2_compare	# yes; don't sign extend
   1980  1.1      is 
   1981  1.1      is # operation is a data register compare.
   1982  1.1      is # sign extend byte to long so we can do simple longword compares.
   1983  1.1      is 	extb.l		%d2			# sign extend data byte
   1984  1.1      is 
   1985  1.1      is #
   1986  1.1      is # To set the ccodes correctly:
   1987  1.1      is # 	(1) save 'Z' bit from (Rn - lo)
   1988  1.1      is #	(2) save 'Z' and 'N' bits from ((hi - lo) - (Rn - hi))
   1989  1.1      is #	(3) keep 'X', 'N', and 'V' from before instruction
   1990  1.1      is #	(4) combine ccodes
   1991  1.1      is #
   1992  1.1      is chk2_cmp2_compare:
   1993  1.1      is 	sub.l		%d0, %d2		# (Rn - lo)
   1994  1.1      is 	mov.w		%cc, %d3		# fetch resulting ccodes
   1995  1.1      is 	andi.b		&0x4, %d3		# keep 'Z' bit
   1996  1.1      is 	sub.l		%d0, %d1		# (hi - lo)
   1997  1.1      is 	cmp.l	 	%d1,%d2			# ((hi - lo) - (Rn - hi))
   1998  1.1      is 
   1999  1.1      is 	mov.w		%cc, %d4		# fetch resulting ccodes
   2000  1.1      is 	or.b		%d4, %d3		# combine w/ earlier ccodes
   2001  1.1      is 	andi.b		&0x5, %d3		# keep 'Z' and 'N'
   2002  1.1      is 
   2003  1.1      is 	mov.w		EXC_CC(%a6), %d4	# fetch old ccodes
   2004  1.1      is 	andi.b		&0x1a, %d4		# keep 'X','N','V' bits
   2005  1.1      is 	or.b		%d3, %d4		# insert new ccodes
   2006  1.1      is 	mov.w		%d4, EXC_CC(%a6)	# save new ccodes
   2007  1.1      is 
   2008  1.1      is 	btst		&0x3, EXC_EXTWORD(%a6)	# separate chk2,cmp2
   2009  1.1      is 	bne.b		chk2_finish		# it's a chk2
   2010  1.1      is 
   2011  1.1      is 	rts
   2012  1.1      is 
   2013  1.1      is # this code handles the only difference between chk2 and cmp2. chk2 would
   2014  1.1      is # have trapped out if the value was out of bounds. we check this by seeing
   2015  1.1      is # if the 'N' bit was set by the operation.
   2016  1.1      is chk2_finish:
   2017  1.1      is 	btst		&0x0, %d4		# is 'N' bit set?
   2018  1.1      is 	bne.b		chk2_trap		# yes;chk2 should trap
   2019  1.1      is 	rts
   2020  1.1      is chk2_trap:
   2021  1.1      is 	mov.b		&ichk_flg,SPCOND_FLG(%a6) # set "special case" flag
   2022  1.1      is 	rts
   2023  1.1      is 
   2024  1.1      is # if dmem_read_{long,word}() returns a fail message in d1, the package
   2025  1.1      is # must create an access error frame. here, we pass a skeleton fslw
   2026  1.1      is # and the failing address to the routine that creates the new frame.
   2027  1.1      is # FSLW:
   2028  1.1      is #	read = true
   2029  1.1      is #	size = longword
   2030  1.1      is #	TM = data
   2031  1.1      is # 	software emulation error = true
   2032  1.1      is chk2_cmp2_err_l:
   2033  1.1      is 	mov.l		%a2,%a0			# pass failing address
   2034  1.1      is 	mov.l		&0x01010001,%d0		# pass fslw
   2035  1.1      is 	bra.l		isp_dacc
   2036  1.1      is 
   2037  1.1      is # FSLW:
   2038  1.1      is #	read = true
   2039  1.1      is #	size = word
   2040  1.1      is #	TM = data
   2041  1.1      is # 	software emulation error = true
   2042  1.1      is chk2_cmp2_err_w:
   2043  1.1      is 	mov.l		%a2,%a0			# pass failing address
   2044  1.1      is 	mov.l		&0x01410001,%d0		# pass fslw
   2045  1.1      is 	bra.l		isp_dacc
   2046  1.1      is 
   2047  1.1      is #########################################################################
   2048  1.1      is # XDEF ****************************************************************	#
   2049  1.1      is # 	_div64(): routine to emulate div{u,s}.l <ea>,Dr:Dq		#
   2050  1.1      is #							64/32->32r:32q	#
   2051  1.1      is #									#
   2052  1.1      is # XREF ****************************************************************	#
   2053  1.1      is #	_calc_ea() - calculate effective address			#
   2054  1.1      is # 	isp_iacc() - handle instruction access error exception		#
   2055  1.1      is #	isp_dacc() - handle data access error exception			#
   2056  1.1      is #	isp_restore() - restore An on access error w/ -() or ()+	#
   2057  1.1      is #									#
   2058  1.1      is # INPUT ***************************************************************	#
   2059  1.1      is #	none								#
   2060  1.1      is #									#
   2061  1.1      is # OUTPUT **************************************************************	#
   2062  1.1      is # 	If exiting through isp_dacc...					#
   2063  1.1      is #		a0 = failing address					#
   2064  1.1      is # 		d0 = FSLW						#
   2065  1.1      is #	else								#
   2066  1.1      is #		none							#
   2067  1.1      is #									#
   2068  1.1      is # ALGORITHM ***********************************************************	#
   2069  1.1      is # 	First, decode the operand location. If it's in Dn, fetch from	#
   2070  1.1      is # the stack. If it's in memory, use _calc_ea() to calculate the 	#
   2071  1.1      is # effective address. Use _dmem_read_long() to fetch at that address.	#
   2072  1.1      is # Unless the operand is immediate data. Then use _imem_read_long().	#
   2073  1.1      is # Send failures to isp_dacc() or isp_iacc() as appropriate.		#
   2074  1.1      is #	If the operands are signed, make them unsigned and save	the 	#
   2075  1.1      is # sign info for later. Separate out special cases like divide-by-zero	#
   2076  1.1      is # or 32-bit divides if possible. Else, use a special math algorithm	#
   2077  1.1      is # to calculate the result. 						#
   2078  1.1      is #	Restore sign info if signed instruction. Set the condition 	#
   2079  1.1      is # codes. Set idbyz_flg in SPCOND_FLG if divisor was zero. Store the 	#
   2080  1.1      is # quotient and remainder in the appropriate data registers on the stack.#
   2081  1.1      is #									#
   2082  1.1      is #########################################################################
   2083  1.1      is 
   2084  1.1      is set	NDIVISOR,	EXC_TEMP+0x0
   2085  1.1      is set	NDIVIDEND,	EXC_TEMP+0x1
   2086  1.1      is set	NDRSAVE,	EXC_TEMP+0x2
   2087  1.1      is set	NDQSAVE,	EXC_TEMP+0x4
   2088  1.1      is set	DDSECOND,	EXC_TEMP+0x6
   2089  1.1      is set	DDQUOTIENT,	EXC_TEMP+0x8
   2090  1.1      is set	DDNORMAL,	EXC_TEMP+0xc
   2091  1.1      is 
   2092  1.1      is 	global		_div64
   2093  1.1      is #############
   2094  1.1      is # div(u,s)l #
   2095  1.1      is #############
   2096  1.1      is _div64:
   2097  1.1      is 	mov.b		EXC_OPWORD+1(%a6), %d0
   2098  1.1      is 	andi.b		&0x38, %d0		# extract src mode
   2099  1.1      is 
   2100  1.1      is 	bne.w		dcontrolmodel_s		# %dn dest or control mode?
   2101  1.1      is 
   2102  1.1      is 	mov.b		EXC_OPWORD+1(%a6), %d0	# extract Dn from opcode
   2103  1.1      is 	andi.w		&0x7, %d0
   2104  1.1      is 	mov.l		(EXC_DREGS,%a6,%d0.w*4), %d7 # fetch divisor from register
   2105  1.1      is 
   2106  1.1      is dgotsrcl:
   2107  1.1      is 	beq.w		div64eq0		# divisor is = 0!!!
   2108  1.1      is 
   2109  1.1      is 	mov.b		EXC_EXTWORD+1(%a6), %d0	# extract Dr from extword
   2110  1.1      is 	mov.b		EXC_EXTWORD(%a6), %d1	# extract Dq from extword
   2111  1.1      is 	and.w		&0x7, %d0
   2112  1.1      is 	lsr.b		&0x4, %d1
   2113  1.1      is 	and.w		&0x7, %d1
   2114  1.1      is 	mov.w		%d0, NDRSAVE(%a6)	# save Dr for later
   2115  1.1      is 	mov.w		%d1, NDQSAVE(%a6)	# save Dq for later
   2116  1.1      is 
   2117  1.1      is # fetch %dr and %dq directly off stack since all regs are saved there
   2118  1.1      is 	mov.l		(EXC_DREGS,%a6,%d0.w*4), %d5 # get dividend hi
   2119  1.1      is 	mov.l		(EXC_DREGS,%a6,%d1.w*4), %d6 # get dividend lo
   2120  1.1      is 
   2121  1.1      is # separate signed and unsigned divide
   2122  1.1      is 	btst		&0x3, EXC_EXTWORD(%a6)	# signed or unsigned?
   2123  1.1      is 	beq.b		dspecialcases		# use positive divide
   2124  1.1      is 
   2125  1.1      is # save the sign of the divisor
   2126  1.1      is # make divisor unsigned if it's negative
   2127  1.1      is 	tst.l		%d7			# chk sign of divisor
   2128  1.1      is 	slt		NDIVISOR(%a6)		# save sign of divisor
   2129  1.1      is 	bpl.b		dsgndividend
   2130  1.1      is 	neg.l		%d7			# complement negative divisor
   2131  1.1      is 
   2132  1.1      is # save the sign of the dividend
   2133  1.1      is # make dividend unsigned if it's negative
   2134  1.1      is dsgndividend:
   2135  1.1      is 	tst.l		%d5			# chk sign of hi(dividend)
   2136  1.1      is 	slt		NDIVIDEND(%a6)		# save sign of dividend
   2137  1.1      is 	bpl.b		dspecialcases
   2138  1.1      is 
   2139  1.1      is 	mov.w		&0x0, %cc		# clear 'X' cc bit
   2140  1.1      is 	negx.l		%d6			# complement signed dividend
   2141  1.1      is 	negx.l		%d5
   2142  1.1      is 
   2143  1.1      is # extract some special cases:
   2144  1.1      is # 	- is (dividend == 0) ?
   2145  1.1      is #	- is (hi(dividend) == 0 && (divisor <= lo(dividend))) ? (32-bit div)
   2146  1.1      is dspecialcases:
   2147  1.1      is 	tst.l		%d5			# is (hi(dividend) == 0)
   2148  1.1      is 	bne.b		dnormaldivide		# no, so try it the long way
   2149  1.1      is 
   2150  1.1      is 	tst.l		%d6			# is (lo(dividend) == 0), too
   2151  1.1      is 	beq.w		ddone			# yes, so (dividend == 0)
   2152  1.1      is 
   2153  1.1      is 	cmp.l	 	%d7,%d6			# is (divisor <= lo(dividend))
   2154  1.1      is 	bls.b		d32bitdivide		# yes, so use 32 bit divide
   2155  1.1      is 
   2156  1.1      is 	exg		%d5,%d6			# q = 0, r = dividend
   2157  1.1      is 	bra.w		divfinish		# can't divide, we're done.
   2158  1.1      is 
   2159  1.1      is d32bitdivide:
   2160  1.1      is 	tdivu.l		%d7, %d5:%d6		# it's only a 32/32 bit div!
   2161  1.1      is 
   2162  1.1      is 	bra.b		divfinish
   2163  1.1      is 
   2164  1.1      is dnormaldivide:
   2165  1.1      is # last special case:
   2166  1.1      is # 	- is hi(dividend) >= divisor ? if yes, then overflow
   2167  1.1      is 	cmp.l		%d7,%d5
   2168  1.1      is 	bls.b		ddovf			# answer won't fit in 32 bits
   2169  1.1      is 
   2170  1.1      is # perform the divide algorithm:
   2171  1.1      is 	bsr.l		dclassical		# do int divide
   2172  1.1      is 
   2173  1.1      is # separate into signed and unsigned finishes.
   2174  1.1      is divfinish:
   2175  1.1      is 	btst		&0x3, EXC_EXTWORD(%a6)	# do divs, divu separately
   2176  1.1      is 	beq.b		ddone			# divu has no processing!!!
   2177  1.1      is 
   2178  1.1      is # it was a divs.l, so ccode setting is a little more complicated...
   2179  1.1      is 	tst.b		NDIVIDEND(%a6)		# remainder has same sign
   2180  1.1      is 	beq.b		dcc			# as dividend.
   2181  1.1      is 	neg.l		%d5			# sgn(rem) = sgn(dividend)
   2182  1.1      is dcc:
   2183  1.1      is 	mov.b		NDIVISOR(%a6), %d0
   2184  1.1      is 	eor.b		%d0, NDIVIDEND(%a6)	# chk if quotient is negative
   2185  1.1      is 	beq.b		dqpos			# branch to quot positive
   2186  1.1      is 
   2187  1.1      is # 0x80000000 is the largest number representable as a 32-bit negative
   2188  1.1      is # number. the negative of 0x80000000 is 0x80000000.
   2189  1.1      is 	cmpi.l		%d6, &0x80000000	# will (-quot) fit in 32 bits?
   2190  1.1      is 	bhi.b		ddovf
   2191  1.1      is 
   2192  1.1      is 	neg.l		%d6			# make (-quot) 2's comp
   2193  1.1      is 
   2194  1.1      is 	bra.b		ddone
   2195  1.1      is 
   2196  1.1      is dqpos:
   2197  1.1      is 	btst		&0x1f, %d6		# will (+quot) fit in 32 bits?
   2198  1.1      is 	bne.b		ddovf
   2199  1.1      is 
   2200  1.1      is ddone:
   2201  1.1      is # at this point, result is normal so ccodes are set based on result.
   2202  1.1      is 	mov.w		EXC_CC(%a6), %cc
   2203  1.1      is 	tst.l		%d6			# set %ccode bits
   2204  1.1      is 	mov.w		%cc, EXC_CC(%a6)
   2205  1.1      is 
   2206  1.1      is 	mov.w		NDRSAVE(%a6), %d0	# get Dr off stack
   2207  1.1      is 	mov.w		NDQSAVE(%a6), %d1	# get Dq off stack
   2208  1.1      is 
   2209  1.1      is # if the register numbers are the same, only the quotient gets saved.
   2210  1.1      is # so, if we always save the quotient second, we save ourselves a cmp&beq
   2211  1.1      is 	mov.l		%d5, (EXC_DREGS,%a6,%d0.w*4) # save remainder
   2212  1.1      is 	mov.l		%d6, (EXC_DREGS,%a6,%d1.w*4) # save quotient
   2213  1.1      is 
   2214  1.1      is 	rts
   2215  1.1      is 
   2216  1.1      is ddovf:
   2217  1.1      is 	bset		&0x1, EXC_CC+1(%a6)	# 'V' set on overflow
   2218  1.1      is 	bclr		&0x0, EXC_CC+1(%a6)	# 'C' cleared on overflow
   2219  1.1      is 
   2220  1.1      is 	rts
   2221  1.1      is 
   2222  1.1      is div64eq0:
   2223  1.1      is 	andi.b		&0x1e, EXC_CC+1(%a6)	# clear 'C' bit on divbyzero
   2224  1.1      is 	ori.b		&idbyz_flg,SPCOND_FLG(%a6) # set "special case" flag
   2225  1.1      is 	rts
   2226  1.1      is 
   2227  1.1      is ###########################################################################
   2228  1.1      is #########################################################################
   2229  1.1      is # This routine uses the 'classical' Algorithm D from Donald Knuth's	#
   2230  1.1      is # Art of Computer Programming, vol II, Seminumerical Algorithms.	#
   2231  1.1      is # For this implementation b=2**16, and the target is U1U2U3U4/V1V2,	#
   2232  1.1      is # where U,V are words of the quadword dividend and longword divisor,	#
   2233  1.1      is # and U1, V1 are the most significant words.				#
   2234  1.1      is # 									#
   2235  1.1      is # The most sig. longword of the 64 bit dividend must be in %d5, least 	#
   2236  1.1      is # in %d6. The divisor must be in the variable ddivisor, and the		#
   2237  1.1      is # signed/unsigned flag ddusign must be set (0=unsigned,1=signed).	#
   2238  1.1      is # The quotient is returned in %d6, remainder in %d5, unless the		#
   2239  1.1      is # v (overflow) bit is set in the saved %ccr. If overflow, the dividend	#
   2240  1.1      is # is unchanged.								#
   2241  1.1      is #########################################################################
   2242  1.1      is dclassical:
   2243  1.1      is # if the divisor msw is 0, use simpler algorithm then the full blown
   2244  1.1      is # one at ddknuth:
   2245  1.1      is 
   2246  1.1      is 	cmpi.l		%d7, &0xffff
   2247  1.1      is 	bhi.b		ddknuth			# go use D. Knuth algorithm
   2248  1.1      is 
   2249  1.1      is # Since the divisor is only a word (and larger than the mslw of the dividend),
   2250  1.1      is # a simpler algorithm may be used :
   2251  1.1      is # In the general case, four quotient words would be created by
   2252  1.1      is # dividing the divisor word into each dividend word. In this case,
   2253  1.1      is # the first two quotient words must be zero, or overflow would occur.
   2254  1.1      is # Since we already checked this case above, we can treat the most significant
   2255  1.1      is # longword of the dividend as (0) remainder (see Knuth) and merely complete
   2256  1.1      is # the last two divisions to get a quotient longword and word remainder:
   2257  1.1      is 
   2258  1.1      is 	clr.l		%d1
   2259  1.1      is 	swap		%d5			# same as r*b if previous step rqd
   2260  1.1      is 	swap		%d6			# get u3 to lsw position
   2261  1.1      is 	mov.w		%d6, %d5		# rb + u3
   2262  1.1      is 
   2263  1.1      is 	divu.w		%d7, %d5
   2264  1.1      is 
   2265  1.1      is 	mov.w		%d5, %d1		# first quotient word
   2266  1.1      is 	swap		%d6			# get u4
   2267  1.1      is 	mov.w		%d6, %d5		# rb + u4
   2268  1.1      is 
   2269  1.1      is 	divu.w		%d7, %d5
   2270  1.1      is 
   2271  1.1      is 	swap		%d1
   2272  1.1      is 	mov.w		%d5, %d1		# 2nd quotient 'digit'
   2273  1.1      is 	clr.w		%d5
   2274  1.1      is 	swap		%d5			# now remainder
   2275  1.1      is 	mov.l		%d1, %d6		# and quotient
   2276  1.1      is 
   2277  1.1      is 	rts
   2278  1.1      is 
   2279  1.1      is ddknuth:
   2280  1.1      is # In this algorithm, the divisor is treated as a 2 digit (word) number
   2281  1.1      is # which is divided into a 3 digit (word) dividend to get one quotient
   2282  1.1      is # digit (word). After subtraction, the dividend is shifted and the
   2283  1.1      is # process repeated. Before beginning, the divisor and quotient are
   2284  1.1      is # 'normalized' so that the process of estimating the quotient digit
   2285  1.1      is # will yield verifiably correct results..
   2286  1.1      is 
   2287  1.1      is 	clr.l		DDNORMAL(%a6)		# count of shifts for normalization
   2288  1.1      is 	clr.b		DDSECOND(%a6)		# clear flag for quotient digits
   2289  1.1      is 	clr.l		%d1			# %d1 will hold trial quotient
   2290  1.1      is ddnchk:
   2291  1.1      is 	btst		&31, %d7		# must we normalize? first word of
   2292  1.1      is 	bne.b		ddnormalized		# divisor (V1) must be >= 65536/2
   2293  1.1      is 	addq.l		&0x1, DDNORMAL(%a6)	# count normalization shifts
   2294  1.1      is 	lsl.l		&0x1, %d7		# shift the divisor
   2295  1.1      is 	lsl.l		&0x1, %d6		# shift u4,u3 with overflow to u2
   2296  1.1      is 	roxl.l		&0x1, %d5		# shift u1,u2
   2297  1.1      is 	bra.w		ddnchk
   2298  1.1      is ddnormalized:
   2299  1.1      is 
   2300  1.1      is # Now calculate an estimate of the quotient words (msw first, then lsw).
   2301  1.1      is # The comments use subscripts for the first quotient digit determination.
   2302  1.1      is 	mov.l		%d7, %d3		# divisor
   2303  1.1      is 	mov.l		%d5, %d2		# dividend mslw
   2304  1.1      is 	swap		%d2
   2305  1.1      is 	swap		%d3
   2306  1.1      is 	cmp.w	 	%d2, %d3		# V1 = U1 ?
   2307  1.1      is 	bne.b		ddqcalc1
   2308  1.1      is 	mov.w		&0xffff, %d1		# use max trial quotient word
   2309  1.1      is 	bra.b		ddadj0
   2310  1.1      is ddqcalc1:
   2311  1.1      is 	mov.l		%d5, %d1
   2312  1.1      is 
   2313  1.1      is 	divu.w		%d3, %d1		# use quotient of mslw/msw
   2314  1.1      is 
   2315  1.1      is 	andi.l		&0x0000ffff, %d1	# zero any remainder
   2316  1.1      is ddadj0:
   2317  1.1      is 
   2318  1.1      is # now test the trial quotient and adjust. This step plus the
   2319  1.1      is # normalization assures (according to Knuth) that the trial
   2320  1.1      is # quotient will be at worst 1 too large.
   2321  1.1      is 	mov.l		%d6, -(%sp)
   2322  1.1      is 	clr.w		%d6			# word u3 left
   2323  1.1      is 	swap		%d6			# in lsw position
   2324  1.1      is ddadj1: mov.l		%d7, %d3
   2325  1.1      is 	mov.l		%d1, %d2
   2326  1.1      is 	mulu.w		%d7, %d2		# V2q
   2327  1.1      is 	swap		%d3
   2328  1.1      is 	mulu.w		%d1, %d3		# V1q
   2329  1.1      is 	mov.l		%d5, %d4		# U1U2
   2330  1.1      is 	sub.l		%d3, %d4		# U1U2 - V1q
   2331  1.1      is 
   2332  1.1      is 	swap		%d4
   2333  1.1      is 
   2334  1.1      is 	mov.w		%d4,%d0
   2335  1.1      is 	mov.w		%d6,%d4			# insert lower word (U3)
   2336  1.1      is 
   2337  1.1      is 	tst.w		%d0			# is upper word set?
   2338  1.1      is 	bne.w		ddadjd1
   2339  1.1      is 
   2340  1.1      is #	add.l		%d6, %d4		# (U1U2 - V1q) + U3
   2341  1.1      is 
   2342  1.1      is 	cmp.l	 	%d2, %d4
   2343  1.1      is 	bls.b		ddadjd1			# is V2q > (U1U2-V1q) + U3 ?
   2344  1.1      is 	subq.l		&0x1, %d1		# yes, decrement and recheck
   2345  1.1      is 	bra.b		ddadj1
   2346  1.1      is ddadjd1:
   2347  1.1      is # now test the word by multiplying it by the divisor (V1V2) and comparing
   2348  1.1      is # the 3 digit (word) result with the current dividend words
   2349  1.1      is 	mov.l		%d5, -(%sp)		# save %d5 (%d6 already saved)
   2350  1.1      is 	mov.l		%d1, %d6
   2351  1.1      is 	swap		%d6			# shift answer to ms 3 words
   2352  1.1      is 	mov.l		%d7, %d5
   2353  1.1      is 	bsr.l		dmm2
   2354  1.1      is 	mov.l		%d5, %d2		# now %d2,%d3 are trial*divisor
   2355  1.1      is 	mov.l		%d6, %d3
   2356  1.1      is 	mov.l		(%sp)+, %d5		# restore dividend
   2357  1.1      is 	mov.l		(%sp)+, %d6
   2358  1.1      is 	sub.l		%d3, %d6
   2359  1.1      is 	subx.l		%d2, %d5		# subtract double precision
   2360  1.1      is 	bcc		dd2nd			# no carry, do next quotient digit
   2361  1.1      is 	subq.l		&0x1, %d1		# q is one too large
   2362  1.1      is # need to add back divisor longword to current ms 3 digits of dividend
   2363  1.1      is # - according to Knuth, this is done only 2 out of 65536 times for random
   2364  1.1      is # divisor, dividend selection.
   2365  1.1      is 	clr.l		%d2
   2366  1.1      is 	mov.l		%d7, %d3
   2367  1.1      is 	swap		%d3
   2368  1.1      is 	clr.w		%d3			# %d3 now ls word of divisor
   2369  1.1      is 	add.l		%d3, %d6		# aligned with 3rd word of dividend
   2370  1.1      is 	addx.l		%d2, %d5
   2371  1.1      is 	mov.l		%d7, %d3
   2372  1.1      is 	clr.w		%d3			# %d3 now ms word of divisor
   2373  1.1      is 	swap		%d3			# aligned with 2nd word of dividend
   2374  1.1      is 	add.l		%d3, %d5
   2375  1.1      is dd2nd:
   2376  1.1      is 	tst.b		DDSECOND(%a6)		# both q words done?
   2377  1.1      is 	bne.b		ddremain
   2378  1.1      is # first quotient digit now correct. store digit and shift the
   2379  1.1      is # (subtracted) dividend
   2380  1.1      is 	mov.w		%d1, DDQUOTIENT(%a6)
   2381  1.1      is 	clr.l		%d1
   2382  1.1      is 	swap		%d5
   2383  1.1      is 	swap		%d6
   2384  1.1      is 	mov.w		%d6, %d5
   2385  1.1      is 	clr.w		%d6
   2386  1.1      is 	st		DDSECOND(%a6)		# second digit
   2387  1.1      is 	bra.w		ddnormalized
   2388  1.1      is ddremain:
   2389  1.1      is # add 2nd word to quotient, get the remainder.
   2390  1.1      is 	mov.w 		%d1, DDQUOTIENT+2(%a6)
   2391  1.1      is # shift down one word/digit to renormalize remainder.
   2392  1.1      is 	mov.w		%d5, %d6
   2393  1.1      is 	swap		%d6
   2394  1.1      is 	swap		%d5
   2395  1.1      is 	mov.l		DDNORMAL(%a6), %d7	# get norm shift count
   2396  1.1      is 	beq.b		ddrn
   2397  1.1      is 	subq.l		&0x1, %d7		# set for loop count
   2398  1.1      is ddnlp:
   2399  1.1      is 	lsr.l		&0x1, %d5		# shift into %d6
   2400  1.1      is 	roxr.l		&0x1, %d6
   2401  1.1      is 	dbf		%d7, ddnlp
   2402  1.1      is ddrn:
   2403  1.1      is 	mov.l		%d6, %d5		# remainder
   2404  1.1      is 	mov.l		DDQUOTIENT(%a6), %d6 	# quotient
   2405  1.1      is 
   2406  1.1      is 	rts
   2407  1.1      is dmm2:
   2408  1.1      is # factors for the 32X32->64 multiplication are in %d5 and %d6.
   2409  1.1      is # returns 64 bit result in %d5 (hi) %d6(lo).
   2410  1.1      is # destroys %d2,%d3,%d4.
   2411  1.1      is 
   2412  1.1      is # multiply hi,lo words of each factor to get 4 intermediate products
   2413  1.1      is 	mov.l		%d6, %d2
   2414  1.1      is 	mov.l		%d6, %d3
   2415  1.1      is 	mov.l		%d5, %d4
   2416  1.1      is 	swap		%d3
   2417  1.1      is 	swap		%d4
   2418  1.1      is 	mulu.w		%d5, %d6		# %d6 <- lsw*lsw
   2419  1.1      is 	mulu.w		%d3, %d5		# %d5 <- msw-dest*lsw-source
   2420  1.1      is 	mulu.w		%d4, %d2		# %d2 <- msw-source*lsw-dest
   2421  1.1      is 	mulu.w		%d4, %d3		# %d3 <- msw*msw
   2422  1.1      is # now use swap and addx to consolidate to two longwords
   2423  1.1      is 	clr.l		%d4
   2424  1.1      is 	swap		%d6
   2425  1.1      is 	add.w		%d5, %d6		# add msw of l*l to lsw of m*l product
   2426  1.1      is 	addx.w		%d4, %d3		# add any carry to m*m product
   2427  1.1      is 	add.w		%d2, %d6		# add in lsw of other m*l product
   2428  1.1      is 	addx.w		%d4, %d3		# add any carry to m*m product
   2429  1.1      is 	swap		%d6			# %d6 is low 32 bits of final product
   2430  1.1      is 	clr.w		%d5
   2431  1.1      is 	clr.w		%d2			# lsw of two mixed products used,
   2432  1.1      is 	swap		%d5			# now use msws of longwords
   2433  1.1      is 	swap		%d2
   2434  1.1      is 	add.l		%d2, %d5
   2435  1.1      is 	add.l		%d3, %d5		# %d5 now ms 32 bits of final product
   2436  1.1      is 	rts
   2437  1.1      is 
   2438  1.1      is ##########
   2439  1.1      is dcontrolmodel_s:
   2440  1.1      is 	movq.l		&LONG,%d0
   2441  1.1      is 	bsr.l		_calc_ea		# calc <ea>
   2442  1.1      is 
   2443  1.1      is 	cmpi.b		SPCOND_FLG(%a6),&immed_flg # immediate addressing mode?
   2444  1.1      is 	beq.b		dimmed			# yes
   2445  1.1      is 
   2446  1.1      is 	mov.l		%a0,%a2
   2447  1.1      is 	bsr.l		_dmem_read_long		# fetch divisor from <ea>
   2448  1.1      is 
   2449  1.1      is 	tst.l		%d1			# dfetch error?
   2450  1.1      is 	bne.b		div64_err		# yes
   2451  1.1      is 
   2452  1.1      is 	mov.l		%d0, %d7
   2453  1.1      is 	bra.w		dgotsrcl
   2454  1.1      is 
   2455  1.1      is # we have to split out immediate data here because it must be read using
   2456  1.1      is # imem_read() instead of dmem_read(). this becomes especially important
   2457  1.1      is # if the fetch runs into some deadly fault.
   2458  1.1      is dimmed:
   2459  1.1      is 	addq.l		&0x4,EXC_EXTWPTR(%a6)
   2460  1.1      is 	bsr.l		_imem_read_long		# read immediate value
   2461  1.1      is 
   2462  1.1      is 	tst.l		%d1			# ifetch error?
   2463  1.1      is 	bne.l		isp_iacc		# yes
   2464  1.1      is 
   2465  1.1      is 	mov.l		%d0,%d7
   2466  1.1      is 	bra.w		dgotsrcl
   2467  1.1      is 
   2468  1.1      is ##########
   2469  1.1      is 
   2470  1.1      is # if dmem_read_long() returns a fail message in d1, the package
   2471  1.1      is # must create an access error frame. here, we pass a skeleton fslw
   2472  1.1      is # and the failing address to the routine that creates the new frame.
   2473  1.1      is # also, we call isp_restore in case the effective addressing mode was
   2474  1.1      is # (an)+ or -(an) in which case the previous "an" value must be restored.
   2475  1.1      is # FSLW:
   2476  1.1      is # 	read = true
   2477  1.1      is # 	size = longword
   2478  1.1      is #	TM = data
   2479  1.1      is # 	software emulation error = true
   2480  1.1      is div64_err:
   2481  1.1      is 	bsr.l		isp_restore		# restore addr reg
   2482  1.1      is 	mov.l		%a2,%a0			# pass failing address
   2483  1.1      is 	mov.l		&0x01010001,%d0		# pass fslw
   2484  1.1      is 	bra.l		isp_dacc
   2485  1.1      is 
   2486  1.1      is #########################################################################
   2487  1.1      is # XDEF ****************************************************************	#
   2488  1.1      is #	_mul64(): routine to emulate mul{u,s}.l <ea>,Dh:Dl 32x32->64	#
   2489  1.1      is #									#
   2490  1.1      is # XREF ****************************************************************	#
   2491  1.1      is #	_calc_ea() - calculate effective address			#
   2492  1.1      is #	isp_iacc() - handle instruction access error exception		#
   2493  1.1      is # 	isp_dacc() - handle data access error exception			#
   2494  1.1      is #	isp_restore() - restore An on access error w/ -() or ()+	#
   2495  1.1      is #									#
   2496  1.1      is # INPUT ***************************************************************	#
   2497  1.1      is #	none								#
   2498  1.1      is #									#
   2499  1.1      is # OUTPUT **************************************************************	#
   2500  1.1      is # 	If exiting through isp_dacc...					#
   2501  1.1      is #		a0 = failing address					#
   2502  1.1      is #		d0 = FSLW						#
   2503  1.1      is # 	else								#
   2504  1.1      is #		none							#
   2505  1.1      is #									#
   2506  1.1      is # ALGORITHM ***********************************************************	#
   2507  1.1      is #	First, decode the operand location. If it's in Dn, fetch from	#
   2508  1.1      is # the stack. If it's in memory, use _calc_ea() to calculate the		#
   2509  1.1      is # effective address. Use _dmem_read_long() to fetch at that address.	#
   2510  1.1      is # Unless the operand is immediate data. Then use _imem_read_long().	#
   2511  1.1      is # Send failures to isp_dacc() or isp_iacc() as appropriate.		#
   2512  1.1      is #	If the operands are signed, make them unsigned and save the 	#
   2513  1.1      is # sign info for later. Perform the multiplication using 16x16->32	#
   2514  1.1      is # unsigned multiplies and "add" instructions. Store the high and low 	#
   2515  1.1      is # portions of the result in the appropriate data registers on the	#
   2516  1.1      is # stack. Calculate the condition codes, also.				#
   2517  1.1      is #									#
   2518  1.1      is #########################################################################
   2519  1.1      is 
   2520  1.1      is #############
   2521  1.1      is # mul(u,s)l #
   2522  1.1      is #############
   2523  1.1      is 	global		_mul64
   2524  1.1      is _mul64:
   2525  1.1      is 	mov.b		EXC_OPWORD+1(%a6), %d0	# extract src {mode,reg}
   2526  1.1      is 	cmpi.b		%d0, &0x7		# is src mode Dn or other?
   2527  1.1      is 	bgt.w		mul64_memop		# src is in memory
   2528  1.1      is 
   2529  1.1      is # multiplier operand in the data register file.
   2530  1.1      is # must extract the register number and fetch the operand from the stack.
   2531  1.1      is mul64_regop:
   2532  1.1      is 	andi.w		&0x7, %d0		# extract Dn
   2533  1.1      is 	mov.l		(EXC_DREGS,%a6,%d0.w*4), %d3 # fetch multiplier
   2534  1.1      is 
   2535  1.1      is # multiplier is in %d3. now, extract Dl and Dh fields and fetch the
   2536  1.1      is # multiplicand from the data register specified by Dl.
   2537  1.1      is mul64_multiplicand:
   2538  1.1      is 	mov.w		EXC_EXTWORD(%a6), %d2	# fetch ext word
   2539  1.1      is 	clr.w		%d1			# clear Dh reg
   2540  1.1      is 	mov.b		%d2, %d1		# grab Dh
   2541  1.1      is 	rol.w		&0x4, %d2		# align Dl byte
   2542  1.1      is 	andi.w		&0x7, %d2		# extract Dl
   2543  1.1      is 
   2544  1.1      is 	mov.l		(EXC_DREGS,%a6,%d2.w*4), %d4 # get multiplicand
   2545  1.1      is 
   2546  1.1      is # check for the case of "zero" result early
   2547  1.1      is 	tst.l		%d4			# test multiplicand
   2548  1.1      is 	beq.w		mul64_zero		# handle zero separately
   2549  1.1      is 	tst.l		%d3			# test multiplier
   2550  1.1      is 	beq.w		mul64_zero		# handle zero separately
   2551  1.1      is 
   2552  1.1      is # multiplier is in %d3 and multiplicand is in %d4.
   2553  1.1      is # if the operation is to be signed, then the operands are converted
   2554  1.1      is # to unsigned and the result sign is saved for the end.
   2555  1.1      is 	clr.b		EXC_TEMP(%a6)		# clear temp space
   2556  1.1      is 	btst		&0x3, EXC_EXTWORD(%a6)	# signed or unsigned?
   2557  1.1      is 	beq.b		mul64_alg		# unsigned; skip sgn calc
   2558  1.1      is 
   2559  1.1      is 	tst.l		%d3			# is multiplier negative?
   2560  1.1      is 	bge.b		mul64_chk_md_sgn	# no
   2561  1.1      is 	neg.l		%d3			# make multiplier positive
   2562  1.1      is 	ori.b		&0x1, EXC_TEMP(%a6)	# save multiplier sgn
   2563  1.1      is 
   2564  1.1      is # the result sign is the exclusive or of the operand sign bits.
   2565  1.1      is mul64_chk_md_sgn:
   2566  1.1      is 	tst.l		%d4			# is multiplicand negative?
   2567  1.1      is 	bge.b		mul64_alg		# no
   2568  1.1      is 	neg.l		%d4			# make multiplicand positive
   2569  1.1      is 	eori.b		&0x1, EXC_TEMP(%a6)	# calculate correct sign
   2570  1.1      is 
   2571  1.1      is #########################################################################
   2572  1.1      is #	63			   32				0	#
   2573  1.1      is # 	----------------------------					#
   2574  1.1      is # 	| hi(mplier) * hi(mplicand)|					#
   2575  1.1      is # 	----------------------------					#
   2576  1.1      is #		     -----------------------------			#
   2577  1.1      is #		     | hi(mplier) * lo(mplicand) |			#
   2578  1.1      is #		     -----------------------------			#
   2579  1.1      is #		     -----------------------------			#
   2580  1.1      is #		     | lo(mplier) * hi(mplicand) |			#
   2581  1.1      is #		     -----------------------------			#
   2582  1.1      is #	  |			   -----------------------------	#
   2583  1.1      is #	--|--			   | lo(mplier) * lo(mplicand) |	#
   2584  1.1      is #	  |			   -----------------------------	#
   2585  1.1      is #	========================================================	#
   2586  1.1      is #	--------------------------------------------------------	#
   2587  1.1      is #	|	hi(result)	   |	    lo(result)         |	#
   2588  1.1      is #	--------------------------------------------------------	#
   2589  1.1      is #########################################################################
   2590  1.1      is mul64_alg:
   2591  1.1      is # load temp registers with operands
   2592  1.1      is 	mov.l		%d3, %d5		# mr in %d5
   2593  1.1      is 	mov.l		%d3, %d6		# mr in %d6
   2594  1.1      is 	mov.l		%d4, %d7		# md in %d7
   2595  1.1      is 	swap		%d6			# hi(mr) in lo %d6
   2596  1.1      is 	swap		%d7			# hi(md) in lo %d7
   2597  1.1      is 
   2598  1.1      is # complete necessary multiplies:
   2599  1.1      is 	mulu.w		%d4, %d3		# [1] lo(mr) * lo(md)
   2600  1.1      is 	mulu.w		%d6, %d4		# [2] hi(mr) * lo(md)
   2601  1.1      is 	mulu.w		%d7, %d5		# [3] lo(mr) * hi(md)
   2602  1.1      is 	mulu.w		%d7, %d6		# [4] hi(mr) * hi(md)
   2603  1.1      is 
   2604  1.1      is # add lo portions of [2],[3] to hi portion of [1].
   2605  1.1      is # add carries produced from these adds to [4].
   2606  1.1      is # lo([1]) is the final lo 16 bits of the result.
   2607  1.1      is 	clr.l		%d7			# load %d7 w/ zero value
   2608  1.1      is 	swap		%d3			# hi([1]) <==> lo([1])
   2609  1.1      is 	add.w		%d4, %d3		# hi([1]) + lo([2])
   2610  1.1      is 	addx.l		%d7, %d6		#    [4]  + carry
   2611  1.1      is 	add.w		%d5, %d3		# hi([1]) + lo([3])
   2612  1.1      is 	addx.l		%d7, %d6		#    [4]  + carry
   2613  1.1      is 	swap		%d3			# lo([1]) <==> hi([1])
   2614  1.1      is 
   2615  1.1      is # lo portions of [2],[3] have been added in to final result.
   2616  1.1      is # now, clear lo, put hi in lo reg, and add to [4]
   2617  1.1      is 	clr.w		%d4			# clear lo([2])
   2618  1.1      is 	clr.w		%d5			# clear hi([3])
   2619  1.1      is 	swap		%d4			# hi([2]) in lo %d4
   2620  1.1      is 	swap		%d5			# hi([3]) in lo %d5
   2621  1.1      is 	add.l		%d5, %d4		#    [4]  + hi([2])
   2622  1.1      is 	add.l		%d6, %d4		#    [4]  + hi([3])
   2623  1.1      is 
   2624  1.1      is # unsigned result is now in {%d4,%d3}
   2625  1.1      is 	tst.b		EXC_TEMP(%a6)		# should result be signed?
   2626  1.1      is 	beq.b		mul64_done		# no
   2627  1.1      is 
   2628  1.1      is # result should be a signed negative number.
   2629  1.1      is # compute 2's complement of the unsigned number:
   2630  1.1      is #   -negate all bits and add 1
   2631  1.1      is mul64_neg:
   2632  1.1      is 	not.l		%d3			# negate lo(result) bits
   2633  1.1      is 	not.l		%d4			# negate hi(result) bits
   2634  1.1      is 	addq.l		&1, %d3			# add 1 to lo(result)
   2635  1.1      is 	addx.l		%d7, %d4		# add carry to hi(result)
   2636  1.1      is 
   2637  1.1      is # the result is saved to the register file.
   2638  1.2     wiz # for '040 compatibility, if Dl == Dh then only the hi(result) is
   2639  1.1      is # saved. so, saving hi after lo accomplishes this without need to
   2640  1.1      is # check Dl,Dh equality.
   2641  1.1      is mul64_done:
   2642  1.1      is 	mov.l		%d3, (EXC_DREGS,%a6,%d2.w*4) # save lo(result)
   2643  1.1      is 	mov.w		&0x0, %cc
   2644  1.1      is 	mov.l		%d4, (EXC_DREGS,%a6,%d1.w*4) # save hi(result)
   2645  1.1      is 
   2646  1.1      is # now, grab the condition codes. only one that can be set is 'N'.
   2647  1.1      is # 'N' CAN be set if the operation is unsigned if bit 63 is set.
   2648  1.1      is 	mov.w		%cc, %d7		# fetch %ccr to see if 'N' set
   2649  1.1      is 	andi.b		&0x8, %d7		# extract 'N' bit
   2650  1.1      is 
   2651  1.1      is mul64_ccode_set:
   2652  1.1      is 	mov.b		EXC_CC+1(%a6), %d6 	# fetch previous %ccr
   2653  1.1      is 	andi.b		&0x10, %d6		# all but 'X' bit changes
   2654  1.1      is 
   2655  1.1      is 	or.b		%d7, %d6		# group 'X' and 'N'
   2656  1.1      is 	mov.b		%d6, EXC_CC+1(%a6)	# save new %ccr
   2657  1.1      is 
   2658  1.1      is 	rts
   2659  1.1      is 
   2660  1.1      is # one or both of the operands is zero so the result is also zero.
   2661  1.1      is # save the zero result to the register file and set the 'Z' ccode bit.
   2662  1.1      is mul64_zero:
   2663  1.1      is 	clr.l		(EXC_DREGS,%a6,%d2.w*4) # save lo(result)
   2664  1.1      is 	clr.l		(EXC_DREGS,%a6,%d1.w*4) # save hi(result)
   2665  1.1      is 
   2666  1.1      is 	movq.l		&0x4, %d7		# set 'Z' ccode bit
   2667  1.1      is 	bra.b		mul64_ccode_set		# finish ccode set
   2668  1.1      is 
   2669  1.1      is ##########
   2670  1.1      is 
   2671  1.1      is # multiplier operand is in memory at the effective address.
   2672  1.1      is # must calculate the <ea> and go fetch the 32-bit operand.
   2673  1.1      is mul64_memop:
   2674  1.1      is 	movq.l		&LONG, %d0		# pass # of bytes
   2675  1.1      is 	bsr.l		_calc_ea		# calculate <ea>
   2676  1.1      is 
   2677  1.1      is 	cmpi.b		SPCOND_FLG(%a6),&immed_flg # immediate addressing mode?
   2678  1.1      is 	beq.b		mul64_immed		# yes
   2679  1.1      is 
   2680  1.1      is 	mov.l		%a0,%a2
   2681  1.1      is 	bsr.l		_dmem_read_long		# fetch src from addr (%a0)
   2682  1.1      is 
   2683  1.1      is 	tst.l		%d1			# dfetch error?
   2684  1.1      is 	bne.w		mul64_err		# yes
   2685  1.1      is 
   2686  1.1      is 	mov.l		%d0, %d3		# store multiplier in %d3
   2687  1.1      is 
   2688  1.1      is 	bra.w		mul64_multiplicand
   2689  1.1      is 
   2690  1.1      is # we have to split out immediate data here because it must be read using
   2691  1.1      is # imem_read() instead of dmem_read(). this becomes especially important
   2692  1.1      is # if the fetch runs into some deadly fault.
   2693  1.1      is mul64_immed:
   2694  1.1      is 	addq.l		&0x4,EXC_EXTWPTR(%a6)
   2695  1.1      is 	bsr.l		_imem_read_long		# read immediate value
   2696  1.1      is 
   2697  1.1      is 	tst.l		%d1			# ifetch error?
   2698  1.1      is 	bne.l		isp_iacc		# yes
   2699  1.1      is 
   2700  1.1      is 	mov.l		%d0,%d3
   2701  1.1      is 	bra.w		mul64_multiplicand
   2702  1.1      is 
   2703  1.1      is ##########
   2704  1.1      is 
   2705  1.1      is # if dmem_read_long() returns a fail message in d1, the package
   2706  1.1      is # must create an access error frame. here, we pass a skeleton fslw
   2707  1.1      is # and the failing address to the routine that creates the new frame.
   2708  1.1      is # also, we call isp_restore in case the effective addressing mode was
   2709  1.1      is # (an)+ or -(an) in which case the previous "an" value must be restored.
   2710  1.1      is # FSLW:
   2711  1.1      is # 	read = true
   2712  1.1      is # 	size = longword
   2713  1.1      is #	TM = data
   2714  1.1      is # 	software emulation error = true
   2715  1.1      is mul64_err:
   2716  1.1      is 	bsr.l		isp_restore		# restore addr reg
   2717  1.1      is 	mov.l		%a2,%a0			# pass failing address
   2718  1.1      is 	mov.l		&0x01010001,%d0		# pass fslw
   2719  1.1      is 	bra.l		isp_dacc
   2720  1.1      is 
   2721  1.1      is #########################################################################
   2722  1.1      is # XDEF ****************************************************************	#
   2723  1.1      is #	_compandset2(): routine to emulate cas2()			#
   2724  1.1      is #			(internal to package)				#
   2725  1.1      is #									#
   2726  1.1      is #	_isp_cas2_finish(): store ccodes, store compare regs		#
   2727  1.1      is #			    (external to package)			#
   2728  1.1      is #									#
   2729  1.1      is # XREF ****************************************************************	#
   2730  1.1      is #	_real_lock_page() - "callout" to lock op's page from page-outs	#
   2731  1.1      is #	_cas_terminate2() - access error exit				#
   2732  1.1      is #	_real_cas2() - "callout" to core cas2 emulation code		#
   2733  1.1      is #	_real_unlock_page() - "callout" to unlock page			#
   2734  1.1      is #									#
   2735  1.1      is # INPUT ***************************************************************	#
   2736  1.1      is # _compandset2():							#
   2737  1.1      is #	d0 = instruction extension word					#
   2738  1.1      is #									#
   2739  1.1      is # _isp_cas2_finish():							#
   2740  1.1      is #	see cas2 core emulation code					#
   2741  1.1      is # 									#
   2742  1.1      is # OUTPUT **************************************************************	#
   2743  1.1      is # _compandset2():							#
   2744  1.1      is #	see cas2 core emulation code					#
   2745  1.1      is #									#
   2746  1.1      is # _isp_cas_finish():							#
   2747  1.1      is #	None (register file or memroy changed as appropriate)		#
   2748  1.1      is #									#
   2749  1.1      is # ALGORITHM ***********************************************************	#
   2750  1.1      is # compandset2():							#
   2751  1.1      is #	Decode the instruction and fetch the appropriate Update and	#
   2752  1.1      is # Compare operands. Then call the "callout" _real_lock_page() for each	#
   2753  1.1      is # memory operand address so that the operating system can keep these	#
   2754  1.1      is # pages from being paged out. If either _real_lock_page() fails, exit	#
   2755  1.1      is # through _cas_terminate2(). Don't forget to unlock the 1st locked page	#
   2756  1.1      is # using _real_unlock_paged() if the 2nd lock-page fails.		#
   2757  1.1      is # Finally, branch to the core cas2 emulation code by calling the 	#
   2758  1.1      is # "callout" _real_cas2().						#
   2759  1.1      is #									#
   2760  1.1      is # _isp_cas2_finish():							#
   2761  1.1      is #	Re-perform the comparison so we can determine the condition	#
   2762  1.1      is # codes which were too much trouble to keep around during the locked	#
   2763  1.1      is # emulation. Then unlock each operands page by calling the "callout"	#
   2764  1.1      is # _real_unlock_page().							#
   2765  1.1      is #									#
   2766  1.1      is #########################################################################
   2767  1.1      is 
   2768  1.1      is set ADDR1,	EXC_TEMP+0xc
   2769  1.1      is set ADDR2,	EXC_TEMP+0x0
   2770  1.1      is set DC2,	EXC_TEMP+0xa
   2771  1.1      is set DC1,	EXC_TEMP+0x8
   2772  1.1      is 
   2773  1.1      is 	global		_compandset2
   2774  1.1      is _compandset2:
   2775  1.1      is 	mov.l		%d0,EXC_TEMP+0x4(%a6)		# store for possible restart
   2776  1.1      is 	mov.l		%d0,%d1			# extension word in d0
   2777  1.1      is 
   2778  1.1      is 	rol.w		&0x4,%d0
   2779  1.1      is 	andi.w		&0xf,%d0		# extract Rn2
   2780  1.1      is 	mov.l		(EXC_DREGS,%a6,%d0.w*4),%a1 # fetch ADDR2
   2781  1.1      is 	mov.l		%a1,ADDR2(%a6)
   2782  1.1      is 
   2783  1.1      is 	mov.l		%d1,%d0
   2784  1.1      is 
   2785  1.1      is 	lsr.w		&0x6,%d1
   2786  1.1      is 	andi.w		&0x7,%d1		# extract Du2
   2787  1.1      is 	mov.l		(EXC_DREGS,%a6,%d1.w*4),%d5 # fetch Update2 Op
   2788  1.1      is 
   2789  1.1      is 	andi.w		&0x7,%d0		# extract Dc2
   2790  1.1      is 	mov.l		(EXC_DREGS,%a6,%d0.w*4),%d3 # fetch Compare2 Op
   2791  1.1      is 	mov.w		%d0,DC2(%a6)
   2792  1.1      is 
   2793  1.1      is 	mov.w		EXC_EXTWORD(%a6),%d0
   2794  1.1      is 	mov.l		%d0,%d1
   2795  1.1      is 
   2796  1.1      is 	rol.w		&0x4,%d0
   2797  1.1      is 	andi.w		&0xf,%d0		# extract Rn1
   2798  1.1      is 	mov.l		(EXC_DREGS,%a6,%d0.w*4),%a0 # fetch ADDR1
   2799  1.1      is 	mov.l		%a0,ADDR1(%a6)
   2800  1.1      is 
   2801  1.1      is 	mov.l		%d1,%d0
   2802  1.1      is 
   2803  1.1      is 	lsr.w		&0x6,%d1
   2804  1.1      is 	andi.w		&0x7,%d1		# extract Du1
   2805  1.1      is 	mov.l		(EXC_DREGS,%a6,%d1.w*4),%d4 # fetch Update1 Op
   2806  1.1      is 
   2807  1.1      is 	andi.w		&0x7,%d0		# extract Dc1
   2808  1.1      is 	mov.l		(EXC_DREGS,%a6,%d0.w*4),%d2 # fetch Compare1 Op
   2809  1.1      is 	mov.w		%d0,DC1(%a6)
   2810  1.1      is 
   2811  1.1      is 	btst		&0x1,EXC_OPWORD(%a6)	# word or long?
   2812  1.1      is 	sne		%d7
   2813  1.1      is 
   2814  1.1      is 	btst		&0x5,EXC_ISR(%a6)	# user or supervisor?
   2815  1.1      is 	sne		%d6
   2816  1.1      is 
   2817  1.1      is 	mov.l		%a0,%a2
   2818  1.1      is 	mov.l		%a1,%a3
   2819  1.1      is 
   2820  1.1      is 	mov.l		%d7,%d1			# pass size
   2821  1.1      is 	mov.l		%d6,%d0			# pass mode
   2822  1.1      is 	bsr.l		_real_lock_page		# lock page
   2823  1.1      is 	mov.l		%a2,%a0
   2824  1.1      is 	tst.l		%d0			# error?
   2825  1.1      is 	bne.l		_cas_terminate2		# yes
   2826  1.1      is 
   2827  1.1      is 	mov.l		%d7,%d1			# pass size
   2828  1.1      is 	mov.l		%d6,%d0			# pass mode
   2829  1.1      is 	mov.l		%a3,%a0			# pass addr
   2830  1.1      is 	bsr.l		_real_lock_page		# lock page
   2831  1.1      is 	mov.l		%a3,%a0
   2832  1.1      is 	tst.l		%d0			# error?
   2833  1.1      is 	bne.b		cas_preterm		# yes
   2834  1.1      is 
   2835  1.1      is 	mov.l		%a2,%a0
   2836  1.1      is 	mov.l		%a3,%a1
   2837  1.1      is 
   2838  1.1      is 	bra.l		_real_cas2
   2839  1.1      is 
   2840  1.1      is # if the 2nd lock attempt fails, then we must still unlock the
   2841  1.1      is # first page(s).
   2842  1.1      is cas_preterm:
   2843  1.1      is 	mov.l		%d0,-(%sp)		# save FSLW
   2844  1.1      is 	mov.l		%d7,%d1			# pass size
   2845  1.1      is 	mov.l		%d6,%d0			# pass mode
   2846  1.1      is 	mov.l		%a2,%a0			# pass ADDR1
   2847  1.1      is 	bsr.l		_real_unlock_page	# unlock first page(s)
   2848  1.1      is 	mov.l		(%sp)+,%d0		# restore FSLW
   2849  1.1      is 	mov.l		%a3,%a0			# pass failing addr
   2850  1.1      is 	bra.l		_cas_terminate2
   2851  1.1      is 
   2852  1.1      is #############################################################
   2853  1.1      is 
   2854  1.1      is 	global		_isp_cas2_finish
   2855  1.1      is _isp_cas2_finish:
   2856  1.1      is 	btst		&0x1,EXC_OPWORD(%a6)
   2857  1.1      is 	bne.b		cas2_finish_l
   2858  1.1      is 
   2859  1.1      is 	mov.w		EXC_CC(%a6),%cc		# load old ccodes
   2860  1.1      is 	cmp.w		%d0,%d2
   2861  1.1      is 	bne.b		cas2_finish_w_save
   2862  1.1      is 	cmp.w		%d1,%d3
   2863  1.1      is cas2_finish_w_save:
   2864  1.1      is 	mov.w		%cc,EXC_CC(%a6)		# save new ccodes
   2865  1.1      is 
   2866  1.1      is 	tst.b		%d4			# update compare reg?
   2867  1.1      is 	bne.b		cas2_finish_w_done	# no
   2868  1.1      is 
   2869  1.1      is 	mov.w		DC2(%a6),%d3		# fetch Dc2
   2870  1.1      is 	mov.w		%d1,(2+EXC_DREGS,%a6,%d3.w*4) # store new Compare2 Op
   2871  1.1      is 
   2872  1.1      is 	mov.w		DC1(%a6),%d2		# fetch Dc1
   2873  1.1      is 	mov.w		%d0,(2+EXC_DREGS,%a6,%d2.w*4) # store new Compare1 Op
   2874  1.1      is 
   2875  1.1      is cas2_finish_w_done:
   2876  1.1      is 	btst		&0x5,EXC_ISR(%a6)
   2877  1.1      is 	sne		%d2
   2878  1.1      is 	mov.l		%d2,%d0			# pass mode
   2879  1.1      is 	sf		%d1			# pass size
   2880  1.1      is 	mov.l		ADDR1(%a6),%a0		# pass ADDR1
   2881  1.1      is 	bsr.l		_real_unlock_page	# unlock page
   2882  1.1      is 
   2883  1.1      is 	mov.l		%d2,%d0			# pass mode
   2884  1.1      is 	sf		%d1			# pass size
   2885  1.1      is 	mov.l		ADDR2(%a6),%a0		# pass ADDR2
   2886  1.1      is 	bsr.l		_real_unlock_page	# unlock page
   2887  1.1      is 	rts
   2888  1.1      is 
   2889  1.1      is cas2_finish_l:
   2890  1.1      is 	mov.w		EXC_CC(%a6),%cc		# load old ccodes
   2891  1.1      is 	cmp.l		%d0,%d2
   2892  1.1      is 	bne.b		cas2_finish_l_save
   2893  1.1      is 	cmp.l		%d1,%d3
   2894  1.1      is cas2_finish_l_save:
   2895  1.1      is 	mov.w		%cc,EXC_CC(%a6)		# save new ccodes
   2896  1.1      is 
   2897  1.1      is 	tst.b		%d4			# update compare reg?
   2898  1.1      is 	bne.b		cas2_finish_l_done	# no
   2899  1.1      is 
   2900  1.1      is 	mov.w		DC2(%a6),%d3		# fetch Dc2
   2901  1.1      is 	mov.l		%d1,(EXC_DREGS,%a6,%d3.w*4) # store new Compare2 Op
   2902  1.1      is 
   2903  1.1      is 	mov.w		DC1(%a6),%d2		# fetch Dc1
   2904  1.1      is 	mov.l		%d0,(EXC_DREGS,%a6,%d2.w*4) # store new Compare1 Op
   2905  1.1      is 
   2906  1.1      is cas2_finish_l_done:
   2907  1.1      is 	btst		&0x5,EXC_ISR(%a6)
   2908  1.1      is 	sne		%d2
   2909  1.1      is 	mov.l		%d2,%d0			# pass mode
   2910  1.1      is 	st		%d1			# pass size
   2911  1.1      is 	mov.l		ADDR1(%a6),%a0		# pass ADDR1
   2912  1.1      is 	bsr.l		_real_unlock_page	# unlock page
   2913  1.1      is 
   2914  1.1      is 	mov.l		%d2,%d0			# pass mode
   2915  1.1      is 	st		%d1			# pass size
   2916  1.1      is 	mov.l		ADDR2(%a6),%a0		# pass ADDR2
   2917  1.1      is 	bsr.l		_real_unlock_page	# unlock page
   2918  1.1      is 	rts
   2919  1.1      is 
   2920  1.1      is ########
   2921  1.1      is 	global		cr_cas2
   2922  1.1      is cr_cas2:
   2923  1.1      is 	mov.l		EXC_TEMP+0x4(%a6),%d0
   2924  1.1      is 	bra.w		_compandset2
   2925  1.1      is 
   2926  1.1      is #########################################################################
   2927  1.1      is # XDEF ****************************************************************	#
   2928  1.1      is #	_compandset(): routine to emulate cas w/ misaligned <ea>	#
   2929  1.1      is #		       (internal to package)				#
   2930  1.1      is #	_isp_cas_finish(): routine called when cas emulation completes	#
   2931  1.1      is #			   (external and internal to package)		#
   2932  1.1      is #	_isp_cas_restart(): restart cas emulation after a fault		#
   2933  1.1      is #			    (external to package)			#
   2934  1.1      is #	_isp_cas_terminate(): create access error stack frame on fault	#
   2935  1.1      is #			      (external and internal to package)	#
   2936  1.5  andvar #	_isp_cas_inrange(): checks whether instr address is within	#
   2937  1.5  andvar #			    range of core cas/cas2emulation code	#
   2938  1.1      is #			    (external to package)			#
   2939  1.1      is #									#
   2940  1.1      is # XREF ****************************************************************	#
   2941  1.1      is # 	_calc_ea(): calculate effective address				#
   2942  1.1      is #									#
   2943  1.1      is # INPUT ***************************************************************	#
   2944  1.1      is # compandset():								#
   2945  1.1      is # 	none								#
   2946  1.1      is # _isp_cas_restart():							#
   2947  1.1      is #	d6 = previous sfc/dfc						#
   2948  1.1      is # _isp_cas_finish():							#
   2949  1.1      is # _isp_cas_terminate():							#
   2950  1.1      is #	a0 = failing address						#
   2951  1.1      is #	d0 = FSLW							#
   2952  1.1      is #	d6 = previous sfc/dfc						#
   2953  1.1      is # _isp_cas_inrange():							#
   2954  1.1      is #	a0 = instruction address to be checked				#
   2955  1.1      is #									#
   2956  1.1      is # OUTPUT **************************************************************	#
   2957  1.1      is # compandset():								#
   2958  1.1      is #		none							#
   2959  1.1      is # _isp_cas_restart():							#
   2960  1.1      is #	a0 = effective address						#
   2961  1.1      is #	d7 = word or longword flag					#
   2962  1.1      is # _isp_cas_finish():							#
   2963  1.1      is #	a0 = effective address						#
   2964  1.1      is # _isp_cas_terminate():							#
   2965  1.1      is #	initial register set before emulation exception			#
   2966  1.1      is # _isp_cas_inrange():							#
   2967  1.1      is #	d0 = 0 => in range; -1 => out of range				#
   2968  1.1      is #									#
   2969  1.1      is # ALGORITHM ***********************************************************	#
   2970  1.1      is #									#
   2971  1.1      is # compandset():								#
   2972  1.1      is #	First, calculate the effective address. Then, decode the 	#
   2973  1.1      is # instruction word and fetch the "compare" (DC) and "update" (Du)	#
   2974  1.1      is # operands.								#
   2975  1.1      is # 	Next, call the external routine _real_lock_page() so that the	#
   2976  1.1      is # operating system can keep this page from being paged out while we're	#
   2977  1.1      is # in this routine. If this call fails, jump to _cas_terminate2().	#
   2978  1.1      is #	The routine then branches to _real_cas(). This external routine	#
   2979  1.1      is # that actually emulates cas can be supplied by the external os or	#
   2980  1.1      is # made to point directly back into the 060ISP which has a routine for	#
   2981  1.1      is # this purpose.								#
   2982  1.1      is #									#
   2983  1.1      is # _isp_cas_finish():							#
   2984  1.1      is # 	Either way, after emulation, the package is re-entered at	#
   2985  1.1      is # _isp_cas_finish(). This routine re-compares the operands in order to	#
   2986  1.1      is # set the condition codes. Finally, these routines will call		#
   2987  1.1      is # _real_unlock_page() in order to unlock the pages that were previously	#
   2988  1.1      is # locked.								#
   2989  1.1      is #									#
   2990  1.1      is # _isp_cas_restart():							#
   2991  1.1      is #	This routine can be entered from an access error handler where	#
   2992  1.1      is # the emulation sequence should be re-started from the beginning.	#
   2993  1.1      is #									#
   2994  1.1      is # _isp_cas_terminate():							#
   2995  1.1      is #	This routine can be entered from an access error handler where	#
   2996  1.1      is # an emulation operand access failed and the operating system would	#
   2997  1.1      is # like an access error stack frame created instead of the current 	#
   2998  1.1      is # unimplemented integer instruction frame.				#
   2999  1.1      is # 	Also, the package enters here if a call to _real_lock_page()	#
   3000  1.1      is # fails.								#
   3001  1.1      is #									#
   3002  1.1      is # _isp_cas_inrange():							#
   3003  1.1      is # 	Checks to see whether the instruction address passed to it in	#
   3004  1.1      is # a0 is within the software package cas/cas2 emulation routines. This	#
   3005  1.1      is # can be helpful for an operating system to determine whether an access	#
   3006  1.1      is # error during emulation was due to a cas/cas2 emulation access.	#
   3007  1.1      is #									#
   3008  1.1      is #########################################################################
   3009  1.1      is 
   3010  1.1      is set DC,		EXC_TEMP+0x8
   3011  1.1      is set ADDR,	EXC_TEMP+0x4
   3012  1.1      is 
   3013  1.1      is 	global		_compandset
   3014  1.1      is _compandset:
   3015  1.1      is 	btst		&0x1,EXC_OPWORD(%a6)	# word or long operation?
   3016  1.1      is 	bne.b		compandsetl		# long
   3017  1.1      is 
   3018  1.1      is compandsetw:
   3019  1.1      is 	movq.l		&0x2,%d0		# size = 2 bytes
   3020  1.1      is 	bsr.l		_calc_ea		# a0 = calculated <ea>
   3021  1.1      is 	mov.l		%a0,ADDR(%a6)		# save <ea> for possible restart
   3022  1.1      is 	sf		%d7			# clear d7 for word size
   3023  1.1      is 	bra.b		compandsetfetch
   3024  1.1      is 
   3025  1.1      is compandsetl:
   3026  1.1      is 	movq.l		&0x4,%d0		# size = 4 bytes
   3027  1.1      is 	bsr.l		_calc_ea		# a0 = calculated <ea>
   3028  1.1      is 	mov.l		%a0,ADDR(%a6)		# save <ea> for possible restart
   3029  1.1      is 	st		%d7			# set d7 for longword size
   3030  1.1      is 
   3031  1.1      is compandsetfetch:
   3032  1.1      is 	mov.w		EXC_EXTWORD(%a6),%d0	# fetch cas extension word
   3033  1.1      is 	mov.l		%d0,%d1			# make a copy
   3034  1.1      is 
   3035  1.1      is 	lsr.w		&0x6,%d0
   3036  1.1      is 	andi.w		&0x7,%d0		# extract Du
   3037  1.1      is 	mov.l		(EXC_DREGS,%a6,%d0.w*4),%d2 # get update operand
   3038  1.1      is 
   3039  1.1      is 	andi.w		&0x7,%d1		# extract Dc
   3040  1.1      is 	mov.l		(EXC_DREGS,%a6,%d1.w*4),%d4 # get compare operand
   3041  1.1      is 	mov.w		%d1,DC(%a6)		# save Dc
   3042  1.1      is 
   3043  1.1      is 	btst		&0x5,EXC_ISR(%a6)	# which mode for exception?
   3044  1.1      is 	sne		%d6			# set on supervisor mode
   3045  1.1      is 
   3046  1.1      is 	mov.l		%a0,%a2			# save temporarily
   3047  1.1      is 	mov.l		%d7,%d1			# pass size
   3048  1.1      is 	mov.l		%d6,%d0			# pass mode
   3049  1.1      is 	bsr.l		_real_lock_page		# lock page
   3050  1.1      is 	tst.l		%d0			# did error occur?
   3051  1.1      is 	bne.w		_cas_terminate2		# yes, clean up the mess
   3052  1.1      is 	mov.l		%a2,%a0			# pass addr in a0
   3053  1.1      is 
   3054  1.1      is 	bra.l		_real_cas
   3055  1.1      is 
   3056  1.1      is ########
   3057  1.1      is 	global		_isp_cas_finish
   3058  1.1      is _isp_cas_finish:
   3059  1.1      is 	btst		&0x1,EXC_OPWORD(%a6)
   3060  1.1      is 	bne.b		cas_finish_l
   3061  1.1      is 
   3062  1.1      is # just do the compare again since it's faster than saving the ccodes
   3063  1.1      is # from the locked routine...
   3064  1.1      is cas_finish_w:
   3065  1.1      is 	mov.w		EXC_CC(%a6),%cc		# restore cc
   3066  1.1      is 	cmp.w	 	%d0,%d4			# do word compare
   3067  1.1      is 	mov.w		%cc,EXC_CC(%a6)		# save cc
   3068  1.1      is 
   3069  1.1      is 	tst.b		%d1			# update compare reg?
   3070  1.1      is 	bne.b		cas_finish_w_done	# no
   3071  1.1      is 
   3072  1.1      is 	mov.w		DC(%a6),%d3
   3073  1.1      is 	mov.w		%d0,(EXC_DREGS+2,%a6,%d3.w*4) # Dc = destination
   3074  1.1      is 
   3075  1.1      is cas_finish_w_done:
   3076  1.1      is 	mov.l		ADDR(%a6),%a0		# pass addr
   3077  1.1      is 	sf		%d1			# pass size
   3078  1.1      is 	btst		&0x5,EXC_ISR(%a6)
   3079  1.1      is 	sne		%d0			# pass mode
   3080  1.1      is 	bsr.l		_real_unlock_page	# unlock page
   3081  1.1      is 	rts
   3082  1.1      is 
   3083  1.1      is # just do the compare again since it's faster than saving the ccodes
   3084  1.1      is # from the locked routine...
   3085  1.1      is cas_finish_l:
   3086  1.1      is 	mov.w		EXC_CC(%a6),%cc		# restore cc
   3087  1.1      is 	cmp.l	 	%d0,%d4			# do longword compare
   3088  1.1      is 	mov.w		%cc,EXC_CC(%a6)		# save cc
   3089  1.1      is 
   3090  1.1      is 	tst.b		%d1			# update compare reg?
   3091  1.1      is 	bne.b		cas_finish_l_done	# no
   3092  1.1      is 
   3093  1.1      is 	mov.w		DC(%a6),%d3
   3094  1.1      is 	mov.l		%d0,(EXC_DREGS,%a6,%d3.w*4) # Dc = destination
   3095  1.1      is 
   3096  1.1      is cas_finish_l_done:
   3097  1.1      is 	mov.l		ADDR(%a6),%a0		# pass addr
   3098  1.1      is 	st		%d1			# pass size
   3099  1.1      is 	btst		&0x5,EXC_ISR(%a6)
   3100  1.1      is 	sne		%d0			# pass mode
   3101  1.1      is 	bsr.l		_real_unlock_page	# unlock page
   3102  1.1      is 	rts
   3103  1.1      is 
   3104  1.1      is ########
   3105  1.1      is 
   3106  1.1      is 	global		_isp_cas_restart
   3107  1.1      is _isp_cas_restart:
   3108  1.1      is 	mov.l		%d6,%sfc		# restore previous sfc
   3109  1.1      is 	mov.l		%d6,%dfc		# restore previous dfc
   3110  1.1      is 
   3111  1.1      is 	cmpi.b		EXC_OPWORD+1(%a6),&0xfc	# cas or cas2?
   3112  1.1      is 	beq.l		cr_cas2			# cas2
   3113  1.1      is cr_cas:
   3114  1.1      is 	mov.l		ADDR(%a6),%a0		# load <ea>
   3115  1.1      is 	btst		&0x1,EXC_OPWORD(%a6)	# word or long operation?
   3116  1.1      is 	sne		%d7			# set d7 accordingly
   3117  1.1      is 	bra.w		compandsetfetch
   3118  1.1      is 
   3119  1.1      is ########
   3120  1.1      is 
   3121  1.1      is # At this stage, it would be nice if d0 held the FSLW.
   3122  1.1      is 	global		_isp_cas_terminate
   3123  1.1      is _isp_cas_terminate:
   3124  1.1      is 	mov.l		%d6,%sfc		# restore previous sfc
   3125  1.1      is 	mov.l		%d6,%dfc		# restore previous dfc
   3126  1.1      is 
   3127  1.1      is 	global		_cas_terminate2
   3128  1.1      is _cas_terminate2:
   3129  1.1      is 	mov.l		%a0,%a2			# copy failing addr to a2
   3130  1.1      is 
   3131  1.1      is 	mov.l		%d0,-(%sp)
   3132  1.1      is 	bsr.l		isp_restore		# restore An (if ()+ or -())
   3133  1.1      is 	mov.l		(%sp)+,%d0
   3134  1.1      is 
   3135  1.1      is 	addq.l		&0x4,%sp		# remove sub return addr
   3136  1.1      is 	subq.l		&0x8,%sp		# make room for bigger stack
   3137  1.1      is 	subq.l		&0x8,%a6		# shift frame ptr down, too
   3138  1.1      is 	mov.l		&26,%d1			# want to move 51 longwords
   3139  1.1      is 	lea		0x8(%sp),%a0		# get address of old stack
   3140  1.1      is 	lea		0x0(%sp),%a1		# get address of new stack
   3141  1.1      is cas_term_cont:
   3142  1.1      is 	mov.l		(%a0)+,(%a1)+		# move a longword
   3143  1.1      is 	dbra.w		%d1,cas_term_cont	# keep going
   3144  1.1      is 
   3145  1.1      is 	mov.w		&0x4008,EXC_IVOFF(%a6)	# put new stk fmt, voff
   3146  1.1      is 	mov.l		%a2,EXC_IVOFF+0x2(%a6)	# put faulting addr on stack
   3147  1.1      is 	mov.l		%d0,EXC_IVOFF+0x6(%a6)	# put FSLW on stack
   3148  1.1      is 	movm.l		EXC_DREGS(%a6),&0x3fff	# restore user regs
   3149  1.1      is 	unlk		%a6			# unlink stack frame
   3150  1.1      is 	bra.l		_real_access
   3151  1.1      is 
   3152  1.1      is ########
   3153  1.1      is 
   3154  1.1      is 	global		_isp_cas_inrange
   3155  1.1      is _isp_cas_inrange:
   3156  1.1      is 	clr.l		%d0			# clear return result
   3157  1.1      is 	lea		_CASHI(%pc),%a1		# load end of CAS core code
   3158  1.1      is 	cmp.l		%a1,%a0			# is PC in range?
   3159  1.1      is 	blt.b		cin_no			# no
   3160  1.1      is 	lea		_CASLO(%pc),%a1		# load begin of CAS core code
   3161  1.1      is 	cmp.l		%a0,%a1			# is PC in range?
   3162  1.1      is 	blt.b		cin_no			# no
   3163  1.1      is 	rts					# yes; return d0 = 0
   3164  1.1      is cin_no:
   3165  1.1      is 	mov.l		&-0x1,%d0		# out of range; return d0 = -1
   3166  1.1      is 	rts
   3167  1.1      is 
   3168  1.1      is #################################################################
   3169  1.1      is #################################################################
   3170  1.1      is #################################################################
   3171  1.1      is # This is the start of the cas and cas2 "core" emulation code.	#
   3172  1.1      is # This is the section that may need to be replaced by the host	#
   3173  1.1      is # OS if it is too operating system-specific.			#
   3174  1.1      is # Please refer to the package documentation to see how to	#
   3175  1.1      is # "replace" this section, if necessary.				#
   3176  1.1      is #################################################################
   3177  1.1      is #################################################################
   3178  1.1      is #################################################################
   3179  1.1      is 
   3180  1.1      is #       ######      ##      ######     ####
   3181  1.1      is #       #	   #  #     #         #    #
   3182  1.1      is #	#	  ######    ######        #
   3183  1.1      is #	#	  #    #         #      #
   3184  1.1      is #       ######    #    #    ######    ######
   3185  1.1      is 
   3186  1.1      is #########################################################################
   3187  1.1      is # XDEF ****************************************************************	#
   3188  1.1      is #	_isp_cas2(): "core" emulation code for the cas2 instruction	#
   3189  1.1      is #									#
   3190  1.1      is # XREF ****************************************************************	#
   3191  1.1      is #	_isp_cas2_finish() - only exit point for this emulation code;	#
   3192  1.1      is #			     do clean-up; calculate ccodes; store 	#
   3193  1.1      is #			     Compare Ops if appropriate.		#
   3194  1.1      is #									#
   3195  1.1      is # INPUT ***************************************************************	#
   3196  1.1      is #	*see chart below*						#
   3197  1.1      is # 									#
   3198  1.1      is # OUTPUT **************************************************************	#
   3199  1.1      is #	*see chart below*						#
   3200  1.1      is #									#
   3201  1.1      is # ALGORITHM ***********************************************************	#
   3202  1.1      is #	(1) Make several copies of the effective address.		#
   3203  1.1      is #	(2) Save current SR; Then mask off all maskable interrupts.	#
   3204  1.1      is #	(3) Save current SFC/DFC (ASSUMED TO BE EQUAL!!!); Then set 	#
   3205  1.1      is #	    according to whether exception occurred in user or 		#
   3206  1.1      is #	    supervisor mode.						#
   3207  1.1      is #	(4) Use "plpaw" instruction to pre-load ATC with effective	#
   3208  1.1      is #	    address pages(s). THIS SHOULD NOT FAULT!!! The relevant	#
   3209  1.1      is #	    page(s) should have already been made resident prior to	#
   3210  1.1      is # 	    entering this routine.					#
   3211  1.1      is #	(5) Push the operand lines from the cache w/ "cpushl". 		#
   3212  1.1      is #	    In the 68040, this was done within the locked region. In	#
   3213  1.1      is # 	    the 68060, it is done outside of the locked region.		#
   3214  1.1      is #	(6) Use "plpar" instruction to do a re-load of ATC entries for	#
   3215  1.1      is #	    ADDR1 since ADDR2 entries may have pushed ADDR1 out of the	#
   3216  1.1      is #	    ATC.							#
   3217  1.1      is #	(7) Pre-fetch the core emulation instructions by executing	#
   3218  1.1      is #	    one branch within each physical line (16 bytes) of the code	#
   3219  1.1      is #	    before actually executing the code.				#
   3220  1.1      is #	(8) Load the BUSCR w/ the bus lock value.			#
   3221  1.1      is #	(9) Fetch the source operands using "moves".			#
   3222  1.1      is #	(10)Do the compares. If both equal, go to step (13).		#
   3223  1.1      is #	(11)Unequal. No update occurs. But, we do write the DST1 op	#
   3224  1.1      is #	    back to itself (as w/ the '040) so we can gracefully unlock	#
   3225  1.1      is #	    the bus (and assert LOCKE*) using BUSCR and the final move.	#
   3226  1.1      is #	(12)Exit.							#
   3227  1.1      is #	(13)Write update operand to the DST locations. Use BUSCR to 	#
   3228  1.1      is #	    assert LOCKE* for the final write operation.		#
   3229  1.1      is #	(14)Exit.							#
   3230  1.1      is #									#
   3231  1.1      is # 	The algorithm is actually implemented slightly differently	#
   3232  1.1      is # depending on the size of the operation and the misalignment of the 	#
   3233  1.1      is # operands. A misaligned operand must be written in aligned chunks or	#
   3234  1.1      is # else the BUSCR register control gets confused.			#
   3235  1.1      is #									#
   3236  1.1      is #########################################################################
   3237  1.1      is 
   3238  1.1      is #################################################################
   3239  1.1      is # THIS IS THE STATE OF THE INTEGER REGISTER FILE UPON		#
   3240  1.1      is # ENTERING _isp_cas2().						#
   3241  1.1      is #								#
   3242  1.1      is # D0 = xxxxxxxx							#
   3243  1.1      is # D1 = xxxxxxxx							#
   3244  1.1      is # D2 = cmp operand 1						#
   3245  1.1      is # D3 = cmp operand 2						#
   3246  1.1      is # D4 = update oper 1						#
   3247  1.1      is # D5 = update oper 2						#
   3248  1.1      is # D6 = 'xxxxxxff if supervisor mode; 'xxxxxx00 if user mode	#
   3249  1.1      is # D7 = 'xxxxxxff if longword operation; 'xxxxxx00 if word 	#
   3250  1.1      is # A0 = ADDR1							#
   3251  1.1      is # A1 = ADDR2							#
   3252  1.1      is # A2 = xxxxxxxx							#
   3253  1.1      is # A3 = xxxxxxxx							#
   3254  1.1      is # A4 = xxxxxxxx							#
   3255  1.1      is # A5 = xxxxxxxx							#
   3256  1.1      is # A6 = frame pointer						#
   3257  1.1      is # A7 = stack pointer						#
   3258  1.1      is #################################################################
   3259  1.1      is 
   3260  1.1      is #	align		0x1000
   3261  1.1      is # beginning label used by _isp_cas_inrange()
   3262  1.1      is 	global		_CASLO
   3263  1.1      is _CASLO:
   3264  1.1      is 
   3265  1.1      is 	global		_isp_cas2
   3266  1.1      is _isp_cas2:
   3267  1.1      is 	tst.b		%d6			# user or supervisor mode?
   3268  1.1      is 	bne.b		cas2_supervisor		# supervisor
   3269  1.1      is cas2_user:
   3270  1.1      is 	movq.l		&0x1,%d0		# load user data fc
   3271  1.1      is 	bra.b		cas2_cont
   3272  1.1      is cas2_supervisor:
   3273  1.1      is 	movq.l		&0x5,%d0		# load supervisor data fc
   3274  1.1      is cas2_cont:
   3275  1.1      is 	tst.b		%d7			# word or longword?
   3276  1.1      is 	beq.w		cas2w			# word
   3277  1.1      is 
   3278  1.1      is ####
   3279  1.1      is cas2l:
   3280  1.1      is 	mov.l		%a0,%a2			# copy ADDR1
   3281  1.1      is 	mov.l		%a1,%a3			# copy ADDR2
   3282  1.1      is 	mov.l		%a0,%a4			# copy ADDR1
   3283  1.1      is 	mov.l		%a1,%a5			# copy ADDR2
   3284  1.1      is 
   3285  1.1      is 	addq.l		&0x3,%a4		# ADDR1+3
   3286  1.1      is 	addq.l		&0x3,%a5		# ADDR2+3
   3287  1.1      is 	mov.l		%a2,%d1			# ADDR1
   3288  1.1      is 
   3289  1.1      is # mask interrupts levels 0-6. save old mask value.
   3290  1.1      is 	mov.w		%sr,%d7			# save current SR
   3291  1.1      is 	ori.w		&0x0700,%sr		# inhibit interrupts
   3292  1.1      is 
   3293  1.1      is # load the SFC and DFC with the appropriate mode.
   3294  1.1      is 	movc		%sfc,%d6		# save old SFC/DFC
   3295  1.1      is 	movc		%d0,%sfc		# store new SFC
   3296  1.1      is 	movc		%d0,%dfc		# store new DFC
   3297  1.1      is 
   3298  1.1      is # pre-load the operand ATC. no page faults should occur here because
   3299  1.1      is # _real_lock_page() should have taken care of this.
   3300  1.1      is 	plpaw		(%a2)			# load atc for ADDR1
   3301  1.1      is 	plpaw		(%a4)			# load atc for ADDR1+3
   3302  1.1      is 	plpaw		(%a3)			# load atc for ADDR2
   3303  1.1      is 	plpaw		(%a5)			# load atc for ADDR2+3
   3304  1.1      is 
   3305  1.1      is # push the operand lines from the cache if they exist.
   3306  1.1      is 	cpushl		%dc,(%a2)		# push line for ADDR1
   3307  1.1      is 	cpushl		%dc,(%a4)		# push line for ADDR1+3
   3308  1.1      is 	cpushl		%dc,(%a3)		# push line for ADDR2
   3309  1.1      is 	cpushl		%dc,(%a5)		# push line for ADDR2+2
   3310  1.1      is 
   3311  1.1      is 	mov.l		%d1,%a2			# ADDR1
   3312  1.1      is 	addq.l		&0x3,%d1
   3313  1.1      is 	mov.l		%d1,%a4			# ADDR1+3
   3314  1.1      is # if ADDR1 was ATC resident before the above "plpaw" and was executed
   3315  1.1      is # and it was the next entry scheduled for replacement and ADDR2
   3316  1.1      is # shares the same set, then the "plpaw" for ADDR2 can push the ADDR1
   3317  1.1      is # entries from the ATC. so, we do a second set of "plpa"s.
   3318  1.1      is 	plpar		(%a2)			# load atc for ADDR1
   3319  1.1      is 	plpar		(%a4)			# load atc for ADDR1+3
   3320  1.1      is 
   3321  1.1      is # load the BUSCR values.
   3322  1.1      is 	mov.l		&0x80000000,%a2		# assert LOCK* buscr value
   3323  1.1      is 	mov.l		&0xa0000000,%a3		# assert LOCKE* buscr value
   3324  1.1      is 	mov.l		&0x00000000,%a4		# buscr unlock value
   3325  1.1      is 
   3326  1.1      is # there are three possible mis-aligned cases for longword cas. they
   3327  1.1      is # are separated because the final write which asserts LOCKE* must
   3328  1.1      is # be aligned.
   3329  1.1      is 	mov.l		%a0,%d0			# is ADDR1 misaligned?
   3330  1.1      is 	andi.b		&0x3,%d0
   3331  1.1      is 	beq.b		CAS2L_ENTER		# no
   3332  1.1      is 	cmpi.b		%d0,&0x2
   3333  1.1      is 	beq.w		CAS2L2_ENTER		# yes; word misaligned
   3334  1.1      is 	bra.w		CAS2L3_ENTER		# yes; byte misaligned
   3335  1.1      is 
   3336  1.1      is #
   3337  1.1      is # D0 = dst operand 1 <-
   3338  1.1      is # D1 = dst operand 2 <-
   3339  1.1      is # D2 = cmp operand 1
   3340  1.1      is # D3 = cmp operand 2
   3341  1.1      is # D4 = update oper 1
   3342  1.1      is # D5 = update oper 2
   3343  1.1      is # D6 = old SFC/DFC
   3344  1.1      is # D7 = old SR
   3345  1.1      is # A0 = ADDR1
   3346  1.1      is # A1 = ADDR2
   3347  1.1      is # A2 = bus LOCK*  value
   3348  1.1      is # A3 = bus LOCKE* value
   3349  1.1      is # A4 = bus unlock value
   3350  1.1      is # A5 = xxxxxxxx
   3351  1.1      is #
   3352  1.1      is 	align 		0x10
   3353  1.1      is CAS2L_START:
   3354  1.1      is 	movc		%a2,%buscr		# assert LOCK*
   3355  1.1      is 	movs.l		(%a1),%d1		# fetch Dest2[31:0]
   3356  1.1      is 	movs.l		(%a0),%d0		# fetch Dest1[31:0]
   3357  1.1      is 	bra.b 		CAS2L_CONT
   3358  1.1      is CAS2L_ENTER:
   3359  1.1      is 	bra.b		~+16
   3360  1.1      is 
   3361  1.1      is CAS2L_CONT:
   3362  1.1      is 	cmp.l	 	%d0,%d2			# Dest1 - Compare1
   3363  1.1      is 	bne.b		CAS2L_NOUPDATE
   3364  1.1      is 	cmp.l	 	%d1,%d3			# Dest2 - Compare2
   3365  1.1      is 	bne.b		CAS2L_NOUPDATE
   3366  1.1      is 	movs.l		%d5,(%a1)		# Update2[31:0] -> DEST2
   3367  1.1      is 	bra.b 		CAS2L_UPDATE
   3368  1.1      is 	bra.b		~+16
   3369  1.1      is 
   3370  1.1      is CAS2L_UPDATE:
   3371  1.1      is 	movc		%a3,%buscr		# assert LOCKE*
   3372  1.1      is 	movs.l		%d4,(%a0)		# Update1[31:0] -> DEST1
   3373  1.1      is 	movc		%a4,%buscr		# unlock the bus
   3374  1.1      is 	bra.b		cas2l_update_done
   3375  1.1      is 	bra.b		~+16
   3376  1.1      is 
   3377  1.1      is CAS2L_NOUPDATE:
   3378  1.1      is 	movc		%a3,%buscr		# assert LOCKE*
   3379  1.1      is 	movs.l		%d0,(%a0)		# Dest1[31:0] -> DEST1
   3380  1.1      is 	movc		%a4,%buscr		# unlock the bus
   3381  1.1      is 	bra.b		cas2l_noupdate_done
   3382  1.1      is 	bra.b		~+16
   3383  1.1      is 
   3384  1.1      is CAS2L_FILLER:
   3385  1.1      is 	nop
   3386  1.1      is 	nop
   3387  1.1      is 	nop
   3388  1.1      is 	nop
   3389  1.1      is 	nop
   3390  1.1      is 	nop
   3391  1.1      is 	nop
   3392  1.1      is 	bra.b		CAS2L_START
   3393  1.1      is 
   3394  1.1      is ####
   3395  1.1      is 
   3396  1.1      is #################################################################
   3397  1.1      is # THIS MUST BE THE STATE OF THE INTEGER REGISTER FILE UPON	#
   3398  1.1      is # ENTERING _isp_cas2().						#
   3399  1.1      is #								#
   3400  1.1      is # D0 = destination[31:0] operand 1				#
   3401  1.1      is # D1 = destination[31:0] operand 2				#
   3402  1.1      is # D2 = cmp[31:0] operand 1					#
   3403  1.1      is # D3 = cmp[31:0] operand 2					#
   3404  1.1      is # D4 = 'xxxxxx11 -> no reg update; 'xxxxxx00 -> update required	#
   3405  1.1      is # D5 = xxxxxxxx							#
   3406  1.1      is # D6 = xxxxxxxx							#
   3407  1.1      is # D7 = xxxxxxxx							#
   3408  1.1      is # A0 = xxxxxxxx							#
   3409  1.1      is # A1 = xxxxxxxx							#
   3410  1.1      is # A2 = xxxxxxxx							#
   3411  1.1      is # A3 = xxxxxxxx							#
   3412  1.1      is # A4 = xxxxxxxx							#
   3413  1.1      is # A5 = xxxxxxxx							#
   3414  1.1      is # A6 = frame pointer						#
   3415  1.1      is # A7 = stack pointer						#
   3416  1.1      is #################################################################
   3417  1.1      is 
   3418  1.1      is cas2l_noupdate_done:
   3419  1.1      is 
   3420  1.1      is # restore previous SFC/DFC value.
   3421  1.1      is 	movc		%d6,%sfc		# restore old SFC
   3422  1.1      is 	movc		%d6,%dfc		# restore old DFC
   3423  1.1      is 
   3424  1.1      is # restore previous interrupt mask level.
   3425  1.1      is 	mov.w		%d7,%sr			# restore old SR
   3426  1.1      is 
   3427  1.1      is 	sf		%d4			# indicate no update was done
   3428  1.1      is 	bra.l		_isp_cas2_finish
   3429  1.1      is 
   3430  1.1      is cas2l_update_done:
   3431  1.1      is 
   3432  1.1      is # restore previous SFC/DFC value.
   3433  1.1      is 	movc		%d6,%sfc		# restore old SFC
   3434  1.1      is 	movc		%d6,%dfc		# restore old DFC
   3435  1.1      is 
   3436  1.1      is # restore previous interrupt mask level.
   3437  1.1      is 	mov.w		%d7,%sr			# restore old SR
   3438  1.1      is 
   3439  1.1      is 	st		%d4			# indicate update was done
   3440  1.1      is 	bra.l		_isp_cas2_finish
   3441  1.1      is ####
   3442  1.1      is 
   3443  1.1      is 	align 		0x10
   3444  1.1      is CAS2L2_START:
   3445  1.1      is 	movc		%a2,%buscr		# assert LOCK*
   3446  1.1      is 	movs.l		(%a1),%d1		# fetch Dest2[31:0]
   3447  1.1      is 	movs.l		(%a0),%d0		# fetch Dest1[31:0]
   3448  1.1      is 	bra.b 		CAS2L2_CONT
   3449  1.1      is CAS2L2_ENTER:
   3450  1.1      is 	bra.b		~+16
   3451  1.1      is 
   3452  1.1      is CAS2L2_CONT:
   3453  1.1      is 	cmp.l	 	%d0,%d2			# Dest1 - Compare1
   3454  1.1      is 	bne.b		CAS2L2_NOUPDATE
   3455  1.1      is 	cmp.l	 	%d1,%d3			# Dest2 - Compare2
   3456  1.1      is 	bne.b		CAS2L2_NOUPDATE
   3457  1.1      is 	movs.l		%d5,(%a1)		# Update2[31:0] -> Dest2
   3458  1.1      is 	bra.b 		CAS2L2_UPDATE
   3459  1.1      is 	bra.b		~+16
   3460  1.1      is 
   3461  1.1      is CAS2L2_UPDATE:
   3462  1.1      is 	swap		%d4			# get Update1[31:16]
   3463  1.1      is 	movs.w		%d4,(%a0)+		# Update1[31:16] -> DEST1
   3464  1.1      is 	movc		%a3,%buscr		# assert LOCKE*
   3465  1.1      is 	swap		%d4			# get Update1[15:0]
   3466  1.1      is 	bra.b		CAS2L2_UPDATE2
   3467  1.1      is 	bra.b		~+16
   3468  1.1      is 
   3469  1.1      is CAS2L2_UPDATE2:
   3470  1.1      is 	movs.w		%d4,(%a0)		# Update1[15:0] -> DEST1+0x2
   3471  1.1      is 	movc		%a4,%buscr		# unlock the bus
   3472  1.1      is 	bra.w		cas2l_update_done
   3473  1.1      is 	nop
   3474  1.1      is 	bra.b		~+16
   3475  1.1      is 
   3476  1.1      is CAS2L2_NOUPDATE:
   3477  1.1      is 	swap		%d0			# get Dest1[31:16]
   3478  1.1      is 	movs.w		%d0,(%a0)+		# Dest1[31:16] -> DEST1
   3479  1.1      is 	movc		%a3,%buscr		# assert LOCKE*
   3480  1.1      is 	swap		%d0			# get Dest1[15:0]
   3481  1.1      is 	bra.b		CAS2L2_NOUPDATE2
   3482  1.1      is 	bra.b		~+16
   3483  1.1      is 
   3484  1.1      is CAS2L2_NOUPDATE2:
   3485  1.1      is 	movs.w		%d0,(%a0)		# Dest1[15:0] -> DEST1+0x2
   3486  1.1      is 	movc		%a4,%buscr		# unlock the bus
   3487  1.1      is 	bra.w		cas2l_noupdate_done
   3488  1.1      is 	nop
   3489  1.1      is 	bra.b		~+16
   3490  1.1      is 
   3491  1.1      is CAS2L2_FILLER:
   3492  1.1      is 	nop
   3493  1.1      is 	nop
   3494  1.1      is 	nop
   3495  1.1      is 	nop
   3496  1.1      is 	nop
   3497  1.1      is 	nop
   3498  1.1      is 	nop
   3499  1.1      is 	bra.b		CAS2L2_START
   3500  1.1      is 
   3501  1.1      is #################################
   3502  1.1      is 
   3503  1.1      is 	align 		0x10
   3504  1.1      is CAS2L3_START:
   3505  1.1      is 	movc		%a2,%buscr		# assert LOCK*
   3506  1.1      is 	movs.l		(%a1),%d1		# fetch Dest2[31:0]
   3507  1.1      is 	movs.l		(%a0),%d0		# fetch Dest1[31:0]
   3508  1.1      is 	bra.b 		CAS2L3_CONT
   3509  1.1      is CAS2L3_ENTER:
   3510  1.1      is 	bra.b		~+16
   3511  1.1      is 
   3512  1.1      is CAS2L3_CONT:
   3513  1.1      is 	cmp.l	 	%d0,%d2			# Dest1 - Compare1
   3514  1.1      is 	bne.b		CAS2L3_NOUPDATE
   3515  1.1      is 	cmp.l	 	%d1,%d3			# Dest2 - Compare2
   3516  1.1      is 	bne.b		CAS2L3_NOUPDATE
   3517  1.1      is 	movs.l		%d5,(%a1)		# Update2[31:0] -> DEST2
   3518  1.1      is 	bra.b 		CAS2L3_UPDATE
   3519  1.1      is 	bra.b		~+16
   3520  1.1      is 
   3521  1.1      is CAS2L3_UPDATE:
   3522  1.1      is 	rol.l		&0x8,%d4		# get Update1[31:24]
   3523  1.1      is 	movs.b		%d4,(%a0)+		# Update1[31:24] -> DEST1
   3524  1.1      is 	swap		%d4			# get Update1[23:8]
   3525  1.1      is 	movs.w		%d4,(%a0)+		# Update1[23:8] -> DEST1+0x1
   3526  1.1      is 	bra.b		CAS2L3_UPDATE2
   3527  1.1      is 	bra.b		~+16
   3528  1.1      is 
   3529  1.1      is CAS2L3_UPDATE2:
   3530  1.1      is 	rol.l		&0x8,%d4		# get Update1[7:0]
   3531  1.1      is 	movc		%a3,%buscr		# assert LOCKE*
   3532  1.1      is 	movs.b		%d4,(%a0)		# Update1[7:0] -> DEST1+0x3
   3533  1.1      is 	bra.b		CAS2L3_UPDATE3
   3534  1.1      is 	nop
   3535  1.1      is 	bra.b		~+16
   3536  1.1      is 
   3537  1.1      is CAS2L3_UPDATE3:
   3538  1.1      is 	movc		%a4,%buscr		# unlock the bus
   3539  1.1      is 	bra.w		cas2l_update_done
   3540  1.1      is 	nop
   3541  1.1      is 	nop
   3542  1.1      is 	nop
   3543  1.1      is 	bra.b		~+16
   3544  1.1      is 
   3545  1.1      is CAS2L3_NOUPDATE:
   3546  1.1      is 	rol.l		&0x8,%d0		# get Dest1[31:24]
   3547  1.1      is 	movs.b		%d0,(%a0)+		# Dest1[31:24] -> DEST1
   3548  1.1      is 	swap		%d0			# get Dest1[23:8]
   3549  1.1      is 	movs.w		%d0,(%a0)+		# Dest1[23:8] -> DEST1+0x1
   3550  1.1      is 	bra.b		CAS2L3_NOUPDATE2
   3551  1.1      is 	bra.b		~+16
   3552  1.1      is 
   3553  1.1      is CAS2L3_NOUPDATE2:
   3554  1.1      is 	rol.l		&0x8,%d0		# get Dest1[7:0]
   3555  1.1      is 	movc		%a3,%buscr		# assert LOCKE*
   3556  1.1      is 	movs.b		%d0,(%a0)		# Update1[7:0] -> DEST1+0x3
   3557  1.1      is 	bra.b		CAS2L3_NOUPDATE3
   3558  1.1      is 	nop
   3559  1.1      is 	bra.b		~+16
   3560  1.1      is 
   3561  1.1      is CAS2L3_NOUPDATE3:
   3562  1.1      is 	movc		%a4,%buscr		# unlock the bus
   3563  1.1      is 	bra.w		cas2l_noupdate_done
   3564  1.1      is 	nop
   3565  1.1      is 	nop
   3566  1.1      is 	nop
   3567  1.1      is 	bra.b		~+14
   3568  1.1      is 
   3569  1.1      is CAS2L3_FILLER:
   3570  1.1      is 	nop
   3571  1.1      is 	nop
   3572  1.1      is 	nop
   3573  1.1      is 	nop
   3574  1.1      is 	nop
   3575  1.1      is 	nop
   3576  1.1      is 	bra.w		CAS2L3_START
   3577  1.1      is 
   3578  1.1      is #############################################################
   3579  1.1      is #############################################################
   3580  1.1      is 
   3581  1.1      is cas2w:
   3582  1.1      is 	mov.l		%a0,%a2			# copy ADDR1
   3583  1.1      is 	mov.l		%a1,%a3			# copy ADDR2
   3584  1.1      is 	mov.l		%a0,%a4			# copy ADDR1
   3585  1.1      is 	mov.l		%a1,%a5			# copy ADDR2
   3586  1.1      is 
   3587  1.1      is 	addq.l		&0x1,%a4		# ADDR1+1
   3588  1.1      is 	addq.l		&0x1,%a5		# ADDR2+1
   3589  1.1      is 	mov.l		%a2,%d1			# ADDR1
   3590  1.1      is 
   3591  1.1      is # mask interrupt levels 0-6. save old mask value.
   3592  1.1      is 	mov.w		%sr,%d7			# save current SR
   3593  1.1      is 	ori.w		&0x0700,%sr		# inhibit interrupts
   3594  1.1      is 
   3595  1.1      is # load the SFC and DFC with the appropriate mode.
   3596  1.1      is 	movc		%sfc,%d6		# save old SFC/DFC
   3597  1.1      is 	movc		%d0,%sfc		# store new SFC
   3598  1.1      is 	movc		%d0,%dfc		# store new DFC
   3599  1.1      is 
   3600  1.1      is # pre-load the operand ATC. no page faults should occur because
   3601  1.1      is # _real_lock_page() should have taken care of this.
   3602  1.1      is 	plpaw		(%a2)			# load atc for ADDR1
   3603  1.1      is 	plpaw		(%a4)			# load atc for ADDR1+1
   3604  1.1      is 	plpaw		(%a3)			# load atc for ADDR2
   3605  1.1      is 	plpaw		(%a5)			# load atc for ADDR2+1
   3606  1.1      is 
   3607  1.1      is # push the operand cache lines from the cache if they exist.
   3608  1.1      is 	cpushl		%dc,(%a2)		# push line for ADDR1
   3609  1.1      is 	cpushl		%dc,(%a4)		# push line for ADDR1+1
   3610  1.1      is 	cpushl		%dc,(%a3)		# push line for ADDR2
   3611  1.1      is 	cpushl		%dc,(%a5)		# push line for ADDR2+1
   3612  1.1      is 
   3613  1.1      is 	mov.l		%d1,%a2			# ADDR1
   3614  1.1      is 	addq.l		&0x3,%d1
   3615  1.1      is 	mov.l		%d1,%a4			# ADDR1+3
   3616  1.1      is # if ADDR1 was ATC resident before the above "plpaw" and was executed
   3617  1.1      is # and it was the next entry scheduled for replacement and ADDR2
   3618  1.1      is # shares the same set, then the "plpaw" for ADDR2 can push the ADDR1
   3619  1.1      is # entries from the ATC. so, we do a second set of "plpa"s.
   3620  1.1      is 	plpar		(%a2)			# load atc for ADDR1
   3621  1.1      is 	plpar		(%a4)			# load atc for ADDR1+3
   3622  1.1      is 
   3623  1.1      is # load the BUSCR values.
   3624  1.1      is 	mov.l		&0x80000000,%a2		# assert LOCK* buscr value
   3625  1.1      is 	mov.l		&0xa0000000,%a3		# assert LOCKE* buscr value
   3626  1.1      is 	mov.l		&0x00000000,%a4		# buscr unlock value
   3627  1.1      is 
   3628  1.1      is # there are two possible mis-aligned cases for word cas. they
   3629  1.1      is # are separated because the final write which asserts LOCKE* must
   3630  1.1      is # be aligned.
   3631  1.1      is 	mov.l		%a0,%d0			# is ADDR1 misaligned?
   3632  1.1      is 	btst		&0x0,%d0
   3633  1.1      is 	bne.w		CAS2W2_ENTER		# yes
   3634  1.1      is 	bra.b		CAS2W_ENTER		# no
   3635  1.1      is 
   3636  1.1      is #
   3637  1.1      is # D0 = dst operand 1 <-
   3638  1.1      is # D1 = dst operand 2 <-
   3639  1.1      is # D2 = cmp operand 1
   3640  1.1      is # D3 = cmp operand 2
   3641  1.1      is # D4 = update oper 1
   3642  1.1      is # D5 = update oper 2
   3643  1.1      is # D6 = old SFC/DFC
   3644  1.1      is # D7 = old SR
   3645  1.1      is # A0 = ADDR1
   3646  1.1      is # A1 = ADDR2
   3647  1.1      is # A2 = bus LOCK*  value
   3648  1.1      is # A3 = bus LOCKE* value
   3649  1.1      is # A4 = bus unlock value
   3650  1.1      is # A5 = xxxxxxxx
   3651  1.1      is #
   3652  1.1      is 	align 		0x10
   3653  1.1      is CAS2W_START:
   3654  1.1      is 	movc		%a2,%buscr		# assert LOCK*
   3655  1.1      is 	movs.w		(%a1),%d1		# fetch Dest2[15:0]
   3656  1.1      is 	movs.w		(%a0),%d0		# fetch Dest1[15:0]
   3657  1.1      is 	bra.b 		CAS2W_CONT2
   3658  1.1      is CAS2W_ENTER:
   3659  1.1      is 	bra.b		~+16
   3660  1.1      is 
   3661  1.1      is CAS2W_CONT2:
   3662  1.1      is 	cmp.w	 	%d0,%d2			# Dest1 - Compare1
   3663  1.1      is 	bne.b		CAS2W_NOUPDATE
   3664  1.1      is 	cmp.w	 	%d1,%d3			# Dest2 - Compare2
   3665  1.1      is 	bne.b		CAS2W_NOUPDATE
   3666  1.1      is 	movs.w		%d5,(%a1)		# Update2[15:0] -> DEST2
   3667  1.1      is 	bra.b 		CAS2W_UPDATE
   3668  1.1      is 	bra.b		~+16
   3669  1.1      is 
   3670  1.1      is CAS2W_UPDATE:
   3671  1.1      is 	movc		%a3,%buscr		# assert LOCKE*
   3672  1.1      is 	movs.w		%d4,(%a0)		# Update1[15:0] -> DEST1
   3673  1.1      is 	movc		%a4,%buscr		# unlock the bus
   3674  1.1      is 	bra.b		cas2w_update_done
   3675  1.1      is 	bra.b		~+16
   3676  1.1      is 
   3677  1.1      is CAS2W_NOUPDATE:
   3678  1.1      is 	movc		%a3,%buscr		# assert LOCKE*
   3679  1.1      is 	movs.w		%d0,(%a0)		# Dest1[15:0] -> DEST1
   3680  1.1      is 	movc		%a4,%buscr		# unlock the bus
   3681  1.1      is 	bra.b		cas2w_noupdate_done
   3682  1.1      is 	bra.b		~+16
   3683  1.1      is 
   3684  1.1      is CAS2W_FILLER:
   3685  1.1      is 	nop
   3686  1.1      is 	nop
   3687  1.1      is 	nop
   3688  1.1      is 	nop
   3689  1.1      is 	nop
   3690  1.1      is 	nop
   3691  1.1      is 	nop
   3692  1.1      is 	bra.b		CAS2W_START
   3693  1.1      is 
   3694  1.1      is ####
   3695  1.1      is 
   3696  1.1      is #################################################################
   3697  1.1      is # THIS MUST BE THE STATE OF THE INTEGER REGISTER FILE UPON	#
   3698  1.1      is # ENTERING _isp_cas2().						#
   3699  1.1      is #								#
   3700  1.1      is # D0 = destination[15:0] operand 1				#
   3701  1.1      is # D1 = destination[15:0] operand 2				#
   3702  1.1      is # D2 = cmp[15:0] operand 1					#
   3703  1.1      is # D3 = cmp[15:0] operand 2					#
   3704  1.1      is # D4 = 'xxxxxx11 -> no reg update; 'xxxxxx00 -> update required	#
   3705  1.1      is # D5 = xxxxxxxx							#
   3706  1.1      is # D6 = xxxxxxxx							#
   3707  1.1      is # D7 = xxxxxxxx							#
   3708  1.1      is # A0 = xxxxxxxx							#
   3709  1.1      is # A1 = xxxxxxxx							#
   3710  1.1      is # A2 = xxxxxxxx							#
   3711  1.1      is # A3 = xxxxxxxx							#
   3712  1.1      is # A4 = xxxxxxxx							#
   3713  1.1      is # A5 = xxxxxxxx							#
   3714  1.1      is # A6 = frame pointer						#
   3715  1.1      is # A7 = stack pointer						#
   3716  1.1      is #################################################################
   3717  1.1      is 
   3718  1.1      is cas2w_noupdate_done:
   3719  1.1      is 
   3720  1.1      is # restore previous SFC/DFC value.
   3721  1.1      is 	movc		%d6,%sfc		# restore old SFC
   3722  1.1      is 	movc		%d6,%dfc		# restore old DFC
   3723  1.1      is 
   3724  1.1      is # restore previous interrupt mask level.
   3725  1.1      is 	mov.w		%d7,%sr			# restore old SR
   3726  1.1      is 
   3727  1.1      is 	sf		%d4			# indicate no update was done
   3728  1.1      is 	bra.l		_isp_cas2_finish
   3729  1.1      is 
   3730  1.1      is cas2w_update_done:
   3731  1.1      is 
   3732  1.1      is # restore previous SFC/DFC value.
   3733  1.1      is 	movc		%d6,%sfc		# restore old SFC
   3734  1.1      is 	movc		%d6,%dfc		# restore old DFC
   3735  1.1      is 
   3736  1.1      is # restore previous interrupt mask level.
   3737  1.1      is 	mov.w		%d7,%sr			# restore old SR
   3738  1.1      is 
   3739  1.1      is 	st		%d4			# indicate update was done
   3740  1.1      is 	bra.l		_isp_cas2_finish
   3741  1.1      is ####
   3742  1.1      is 
   3743  1.1      is 	align 		0x10
   3744  1.1      is CAS2W2_START:
   3745  1.1      is 	movc		%a2,%buscr		# assert LOCK*
   3746  1.1      is 	movs.w		(%a1),%d1		# fetch Dest2[15:0]
   3747  1.1      is 	movs.w		(%a0),%d0		# fetch Dest1[15:0]
   3748  1.1      is 	bra.b 		CAS2W2_CONT2
   3749  1.1      is CAS2W2_ENTER:
   3750  1.1      is 	bra.b		~+16
   3751  1.1      is 
   3752  1.1      is CAS2W2_CONT2:
   3753  1.1      is 	cmp.w	 	%d0,%d2			# Dest1 - Compare1
   3754  1.1      is 	bne.b		CAS2W2_NOUPDATE
   3755  1.1      is 	cmp.w	 	%d1,%d3			# Dest2 - Compare2
   3756  1.1      is 	bne.b		CAS2W2_NOUPDATE
   3757  1.1      is 	movs.w		%d5,(%a1)		# Update2[15:0] -> DEST2
   3758  1.1      is 	bra.b 		CAS2W2_UPDATE
   3759  1.1      is 	bra.b		~+16
   3760  1.1      is 
   3761  1.1      is CAS2W2_UPDATE:
   3762  1.1      is 	ror.l		&0x8,%d4		# get Update1[15:8]
   3763  1.1      is 	movs.b		%d4,(%a0)+		# Update1[15:8] -> DEST1
   3764  1.1      is 	movc		%a3,%buscr		# assert LOCKE*
   3765  1.1      is 	rol.l		&0x8,%d4		# get Update1[7:0]
   3766  1.1      is 	bra.b		CAS2W2_UPDATE2
   3767  1.1      is 	bra.b		~+16
   3768  1.1      is 
   3769  1.1      is CAS2W2_UPDATE2:
   3770  1.1      is 	movs.b		%d4,(%a0)		# Update1[7:0] -> DEST1+0x1
   3771  1.1      is 	movc		%a4,%buscr		# unlock the bus
   3772  1.1      is 	bra.w		cas2w_update_done
   3773  1.1      is 	nop
   3774  1.1      is 	bra.b		~+16
   3775  1.1      is 
   3776  1.1      is CAS2W2_NOUPDATE:
   3777  1.1      is 	ror.l		&0x8,%d0		# get Dest1[15:8]
   3778  1.1      is 	movs.b		%d0,(%a0)+		# Dest1[15:8] -> DEST1
   3779  1.1      is 	movc		%a3,%buscr		# assert LOCKE*
   3780  1.1      is 	rol.l		&0x8,%d0		# get Dest1[7:0]
   3781  1.1      is 	bra.b		CAS2W2_NOUPDATE2
   3782  1.1      is 	bra.b		~+16
   3783  1.1      is 
   3784  1.1      is CAS2W2_NOUPDATE2:
   3785  1.1      is 	movs.b		%d0,(%a0)		# Dest1[7:0] -> DEST1+0x1
   3786  1.1      is 	movc		%a4,%buscr		# unlock the bus
   3787  1.1      is 	bra.w		cas2w_noupdate_done
   3788  1.1      is 	nop
   3789  1.1      is 	bra.b		~+16
   3790  1.1      is 
   3791  1.1      is CAS2W2_FILLER:
   3792  1.1      is 	nop
   3793  1.1      is 	nop
   3794  1.1      is 	nop
   3795  1.1      is 	nop
   3796  1.1      is 	nop
   3797  1.1      is 	nop
   3798  1.1      is 	nop
   3799  1.1      is 	bra.b		CAS2W2_START
   3800  1.1      is 
   3801  1.1      is #       ######      ##      ######
   3802  1.1      is #       #	   #  #     #
   3803  1.1      is #	#	  ######    ######
   3804  1.1      is #	#	  #    #         #
   3805  1.1      is #       ######    #    #    ######
   3806  1.1      is 
   3807  1.1      is #########################################################################
   3808  1.1      is # XDEF ****************************************************************	#
   3809  1.1      is # 	_isp_cas(): "core" emulation code for the cas instruction	#
   3810  1.1      is #									#
   3811  1.1      is # XREF ****************************************************************	#
   3812  1.1      is #	_isp_cas_finish() - only exit point for this emulation code;	#
   3813  1.1      is #			    do clean-up					#
   3814  1.1      is #									#
   3815  1.1      is # INPUT ***************************************************************	#
   3816  1.1      is # 	*see entry chart below*						#
   3817  1.1      is #									#
   3818  1.1      is # OUTPUT **************************************************************	#
   3819  1.1      is #	*see exit chart below*						#
   3820  1.1      is #									#
   3821  1.1      is # ALGORITHM ***********************************************************	#
   3822  1.1      is # 	(1) Make several copies of the effective address. 		#
   3823  1.1      is # 	(2) Save current SR; Then mask off all maskable interrupts.	#
   3824  1.1      is #	(3) Save current DFC/SFC (ASSUMED TO BE EQUAL!!!); Then set	#
   3825  1.1      is #	    SFC/DFC according to whether exception occurred in user or	#
   3826  1.1      is #	    supervisor mode.						#
   3827  1.5  andvar #	(4) Use "plpaw" instruction to pre-load ATC with effective	#
   3828  1.1      is #	    address page(s). THIS SHOULD NOT FAULT!!! The relevant	#
   3829  1.1      is # 	    page(s) should have been made resident prior to entering 	#
   3830  1.1      is #	    this routine.						#
   3831  1.1      is #	(5) Push the operand lines from the cache w/ "cpushl".		#
   3832  1.1      is #	    In the 68040, this was done within the locked region. In	#
   3833  1.1      is #	    the 68060, it is done outside of the locked region.		#
   3834  1.1      is #	(6) Pre-fetch the core emulation instructions by executing one	#
   3835  1.1      is #	    branch within each physical line (16 bytes) of the code	#
   3836  1.1      is #	    before actually executing the code.				#
   3837  1.1      is #	(7) Load the BUSCR with the bus lock value.			#
   3838  1.1      is #	(8) Fetch the source operand.					#
   3839  1.1      is #	(9) Do the compare. If equal, go to step (12).			#
   3840  1.1      is #	(10)Unequal. No update occurs. But, we do write the DST op back	#
   3841  1.1      is #	    to itself (as w/ the '040) so we can gracefully unlock	#
   3842  1.1      is #	    the bus (and assert LOCKE*) using BUSCR and the final move.	#
   3843  1.1      is #	(11)Exit.							#
   3844  1.1      is #	(12)Write update operand to the DST location. Use BUSCR to	#
   3845  1.1      is #	    assert LOCKE* for the final write operation.		#
   3846  1.1      is #	(13)Exit.							#
   3847  1.1      is # 									#
   3848  1.5  andvar # 	The algorithm is actually implemented slightly differently	#
   3849  1.1      is # depending on the size of the operation and the misalignment of the	#
   3850  1.1      is # operand. A misaligned operand must be written in aligned chunks or	#
   3851  1.1      is # else the BUSCR register control gets confused.			#
   3852  1.1      is #									#
   3853  1.1      is #########################################################################
   3854  1.1      is 
   3855  1.1      is #########################################################
   3856  1.1      is # THIS IS THE STATE OF THE INTEGER REGISTER FILE UPON	#
   3857  1.1      is # ENTERING _isp_cas().					#
   3858  1.1      is #							#
   3859  1.1      is # D0 = xxxxxxxx						#
   3860  1.1      is # D1 = xxxxxxxx						#
   3861  1.1      is # D2 = update operand					#
   3862  1.1      is # D3 = xxxxxxxx						#
   3863  1.1      is # D4 = compare operand					#
   3864  1.1      is # D5 = xxxxxxxx						#
   3865  1.1      is # D6 = supervisor ('xxxxxxff) or user mode ('xxxxxx00)	#
   3866  1.1      is # D7 = longword ('xxxxxxff) or word size ('xxxxxx00)	#
   3867  1.1      is # A0 = ADDR						#
   3868  1.1      is # A1 = xxxxxxxx						#
   3869  1.1      is # A2 = xxxxxxxx						#
   3870  1.1      is # A3 = xxxxxxxx						#
   3871  1.1      is # A4 = xxxxxxxx						#
   3872  1.1      is # A5 = xxxxxxxx						#
   3873  1.1      is # A6 = frame pointer					#
   3874  1.1      is # A7 = stack pointer					#
   3875  1.1      is #########################################################
   3876  1.1      is 
   3877  1.1      is 	global		_isp_cas
   3878  1.1      is _isp_cas:
   3879  1.1      is 	tst.b		%d6			# user or supervisor mode?
   3880  1.1      is 	bne.b		cas_super		# supervisor
   3881  1.1      is cas_user:
   3882  1.1      is 	movq.l		&0x1,%d0		# load user data fc
   3883  1.1      is 	bra.b		cas_cont
   3884  1.1      is cas_super:
   3885  1.1      is 	movq.l		&0x5,%d0		# load supervisor data fc
   3886  1.1      is 
   3887  1.1      is cas_cont:
   3888  1.1      is 	tst.b		%d7			# word or longword?
   3889  1.1      is 	bne.w		casl			# longword
   3890  1.1      is 
   3891  1.1      is ####
   3892  1.1      is casw:
   3893  1.1      is 	mov.l		%a0,%a1			# make copy for plpaw1
   3894  1.1      is 	mov.l		%a0,%a2			# make copy for plpaw2
   3895  1.1      is 	addq.l		&0x1,%a2		# plpaw2 points to end of word
   3896  1.1      is 
   3897  1.1      is 	mov.l		%d2,%d3			# d3 = update[7:0]
   3898  1.1      is 	lsr.w		&0x8,%d2		# d2 = update[15:8]
   3899  1.1      is 
   3900  1.1      is # mask interrupt levels 0-6. save old mask value.
   3901  1.1      is 	mov.w		%sr,%d7			# save current SR
   3902  1.1      is 	ori.w		&0x0700,%sr		# inhibit interrupts
   3903  1.1      is 
   3904  1.1      is # load the SFC and DFC with the appropriate mode.
   3905  1.1      is 	movc		%sfc,%d6		# save old SFC/DFC
   3906  1.1      is 	movc		%d0,%sfc		# load new sfc
   3907  1.1      is 	movc		%d0,%dfc		# load new dfc
   3908  1.1      is 
   3909  1.1      is # pre-load the operand ATC. no page faults should occur here because
   3910  1.1      is # _real_lock_page() should have taken care of this.
   3911  1.1      is 	plpaw		(%a1)			# load atc for ADDR
   3912  1.1      is 	plpaw		(%a2)			# load atc for ADDR+1
   3913  1.1      is 
   3914  1.1      is # push the operand lines from the cache if they exist.
   3915  1.1      is 	cpushl		%dc,(%a1)		# push dirty data
   3916  1.1      is 	cpushl		%dc,(%a2)		# push dirty data
   3917  1.1      is 
   3918  1.1      is # load the BUSCR values.
   3919  1.1      is 	mov.l		&0x80000000,%a1		# assert LOCK* buscr value
   3920  1.1      is 	mov.l		&0xa0000000,%a2		# assert LOCKE* buscr value
   3921  1.1      is 	mov.l		&0x00000000,%a3		# buscr unlock value
   3922  1.1      is 
   3923  1.1      is # pre-load the instruction cache for the following algorithm.
   3924  1.1      is # this will minimize the number of cycles that LOCK* will be asserted.
   3925  1.1      is 	bra.b		CASW_ENTER		# start pre-loading icache
   3926  1.1      is 
   3927  1.1      is #
   3928  1.1      is # D0 = dst operand <-
   3929  1.1      is # D1 = update[15:8] operand
   3930  1.1      is # D2 = update[7:0]  operand
   3931  1.1      is # D3 = xxxxxxxx
   3932  1.1      is # D4 = compare[15:0] operand
   3933  1.1      is # D5 = xxxxxxxx
   3934  1.1      is # D6 = old SFC/DFC
   3935  1.1      is # D7 = old SR
   3936  1.1      is # A0 = ADDR
   3937  1.1      is # A1 = bus LOCK*  value
   3938  1.1      is # A2 = bus LOCKE* value
   3939  1.1      is # A3 = bus unlock value
   3940  1.1      is # A4 = xxxxxxxx
   3941  1.1      is # A5 = xxxxxxxx
   3942  1.1      is #
   3943  1.1      is 	align		0x10
   3944  1.1      is CASW_START:
   3945  1.1      is 	movc		%a1,%buscr		# assert LOCK*
   3946  1.1      is 	movs.w		(%a0),%d0		# fetch Dest[15:0]
   3947  1.1      is 	cmp.w	 	%d0,%d4			# Dest - Compare
   3948  1.1      is 	bne.b		CASW_NOUPDATE
   3949  1.1      is 	bra.b 		CASW_UPDATE
   3950  1.1      is CASW_ENTER:
   3951  1.1      is 	bra.b		~+16
   3952  1.1      is 
   3953  1.1      is CASW_UPDATE:
   3954  1.1      is 	movs.b		%d2,(%a0)+		# Update[15:8] -> DEST
   3955  1.1      is 	movc		%a2,%buscr		# assert LOCKE*
   3956  1.1      is 	movs.b		%d3,(%a0)		# Update[7:0] -> DEST+0x1
   3957  1.1      is 	bra.b		CASW_UPDATE2
   3958  1.1      is 	bra.b		~+16
   3959  1.1      is 
   3960  1.1      is CASW_UPDATE2:
   3961  1.1      is 	movc		%a3,%buscr		# unlock the bus
   3962  1.1      is 	bra.b		casw_update_done
   3963  1.1      is 	nop
   3964  1.1      is 	nop
   3965  1.1      is 	nop
   3966  1.1      is 	nop
   3967  1.1      is 	bra.b		~+16
   3968  1.1      is 
   3969  1.1      is CASW_NOUPDATE:
   3970  1.1      is 	ror.l		&0x8,%d0		# get Dest[15:8]
   3971  1.1      is 	movs.b		%d0,(%a0)+		# Dest[15:8] -> DEST
   3972  1.1      is 	movc		%a2,%buscr		# assert LOCKE*
   3973  1.1      is 	rol.l		&0x8,%d0		# get Dest[7:0]
   3974  1.1      is 	bra.b 		CASW_NOUPDATE2
   3975  1.1      is 	bra.b		~+16
   3976  1.1      is 
   3977  1.1      is CASW_NOUPDATE2:
   3978  1.1      is 	movs.b		%d0,(%a0)		# Dest[7:0] -> DEST+0x1
   3979  1.1      is 	movc		%a3,%buscr		# unlock the bus
   3980  1.1      is 	bra.b		casw_noupdate_done
   3981  1.1      is 	nop
   3982  1.1      is 	nop
   3983  1.1      is 	bra.b		~+16
   3984  1.1      is 
   3985  1.1      is CASW_FILLER:
   3986  1.1      is 	nop
   3987  1.1      is 	nop
   3988  1.1      is 	nop
   3989  1.1      is 	nop
   3990  1.1      is 	nop
   3991  1.1      is 	nop
   3992  1.1      is 	nop
   3993  1.1      is 	bra.b		CASW_START
   3994  1.1      is 
   3995  1.1      is #################################################################
   3996  1.1      is # THIS MUST BE THE STATE OF THE INTEGER REGISTER FILE UPON	#
   3997  1.1      is # CALLING _isp_cas_finish().					#
   3998  1.1      is #								#
   3999  1.1      is # D0 = destination[15:0] operand				#
   4000  1.1      is # D1 = 'xxxxxx11 -> no reg update; 'xxxxxx00 -> update required	#
   4001  1.1      is # D2 = xxxxxxxx							#
   4002  1.1      is # D3 = xxxxxxxx							#
   4003  1.1      is # D4 = compare[15:0] operand					#
   4004  1.1      is # D5 = xxxxxxxx							#
   4005  1.1      is # D6 = xxxxxxxx							#
   4006  1.1      is # D7 = xxxxxxxx							#
   4007  1.1      is # A0 = xxxxxxxx							#
   4008  1.1      is # A1 = xxxxxxxx							#
   4009  1.1      is # A2 = xxxxxxxx							#
   4010  1.1      is # A3 = xxxxxxxx							#
   4011  1.1      is # A4 = xxxxxxxx							#
   4012  1.1      is # A5 = xxxxxxxx							#
   4013  1.1      is # A6 = frame pointer						#
   4014  1.1      is # A7 = stack pointer						#
   4015  1.1      is #################################################################
   4016  1.1      is 
   4017  1.1      is casw_noupdate_done:
   4018  1.1      is 
   4019  1.1      is # restore previous SFC/DFC value.
   4020  1.1      is 	movc		%d6,%sfc		# restore old SFC
   4021  1.1      is 	movc		%d6,%dfc		# restore old DFC
   4022  1.1      is 
   4023  1.1      is # restore previous interrupt mask level.
   4024  1.1      is 	mov.w		%d7,%sr			# restore old SR
   4025  1.1      is 
   4026  1.1      is 	sf		%d1			# indicate no update was done
   4027  1.1      is 	bra.l		_isp_cas_finish
   4028  1.1      is 
   4029  1.1      is casw_update_done:
   4030  1.1      is 
   4031  1.1      is # restore previous SFC/DFC value.
   4032  1.1      is 	movc		%d6,%sfc		# restore old SFC
   4033  1.1      is 	movc		%d6,%dfc		# restore old DFC
   4034  1.1      is 
   4035  1.1      is # restore previous interrupt mask level.
   4036  1.1      is 	mov.w		%d7,%sr			# restore old SR
   4037  1.1      is 
   4038  1.1      is 	st		%d1			# indicate update was done
   4039  1.1      is 	bra.l		_isp_cas_finish
   4040  1.1      is 
   4041  1.1      is ################
   4042  1.1      is 
   4043  1.5  andvar # there are two possible misaligned cases for longword cas. they
   4044  1.1      is # are separated because the final write which asserts LOCKE* must
   4045  1.1      is # be an aligned write.
   4046  1.1      is casl:
   4047  1.1      is 	mov.l		%a0,%a1			# make copy for plpaw1
   4048  1.1      is 	mov.l		%a0,%a2			# make copy for plpaw2
   4049  1.1      is 	addq.l		&0x3,%a2		# plpaw2 points to end of longword
   4050  1.1      is 
   4051  1.1      is 	mov.l		%a0,%d1			# byte or word misaligned?
   4052  1.1      is 	btst		&0x0,%d1
   4053  1.1      is 	bne.w		casl2			# byte misaligned
   4054  1.1      is 
   4055  1.1      is 	mov.l		%d2,%d3			# d3 = update[15:0]
   4056  1.1      is 	swap		%d2			# d2 = update[31:16]
   4057  1.1      is 
   4058  1.1      is # mask interrupts levels 0-6. save old mask value.
   4059  1.1      is 	mov.w		%sr,%d7			# save current SR
   4060  1.1      is 	ori.w		&0x0700,%sr		# inhibit interrupts
   4061  1.1      is 
   4062  1.1      is # load the SFC and DFC with the appropriate mode.
   4063  1.1      is 	movc		%sfc,%d6		# save old SFC/DFC
   4064  1.1      is 	movc		%d0,%sfc		# load new sfc
   4065  1.1      is 	movc		%d0,%dfc		# load new dfc
   4066  1.1      is 
   4067  1.1      is # pre-load the operand ATC. no page faults should occur here because
   4068  1.1      is # _real_lock_page() should have taken care of this.
   4069  1.1      is 	plpaw		(%a1)			# load atc for ADDR
   4070  1.1      is 	plpaw		(%a2)			# load atc for ADDR+3
   4071  1.1      is 
   4072  1.1      is # push the operand lines from the cache if they exist.
   4073  1.1      is 	cpushl		%dc,(%a1)		# push dirty data
   4074  1.1      is 	cpushl		%dc,(%a2)		# push dirty data
   4075  1.1      is 
   4076  1.1      is # load the BUSCR values.
   4077  1.1      is 	mov.l		&0x80000000,%a1		# assert LOCK* buscr value
   4078  1.1      is 	mov.l		&0xa0000000,%a2		# assert LOCKE* buscr value
   4079  1.1      is 	mov.l		&0x00000000,%a3		# buscr unlock value
   4080  1.1      is 
   4081  1.1      is 	bra.b		CASL_ENTER		# start pre-loading icache
   4082  1.1      is 
   4083  1.1      is #
   4084  1.1      is # D0 = dst operand <-
   4085  1.1      is # D1 = xxxxxxxx
   4086  1.1      is # D2 = update[31:16] operand
   4087  1.1      is # D3 = update[15:0]  operand
   4088  1.1      is # D4 = compare[31:0] operand
   4089  1.1      is # D5 = xxxxxxxx
   4090  1.1      is # D6 = old SFC/DFC
   4091  1.1      is # D7 = old SR
   4092  1.1      is # A0 = ADDR
   4093  1.1      is # A1 = bus LOCK*  value
   4094  1.1      is # A2 = bus LOCKE* value
   4095  1.1      is # A3 = bus unlock value
   4096  1.1      is # A4 = xxxxxxxx
   4097  1.1      is # A5 = xxxxxxxx
   4098  1.1      is #
   4099  1.1      is 	align		0x10
   4100  1.1      is CASL_START:
   4101  1.1      is 	movc		%a1,%buscr		# assert LOCK*
   4102  1.1      is 	movs.l		(%a0),%d0		# fetch Dest[31:0]
   4103  1.1      is 	cmp.l	 	%d0,%d4			# Dest - Compare
   4104  1.1      is 	bne.b		CASL_NOUPDATE
   4105  1.1      is 	bra.b 		CASL_UPDATE
   4106  1.1      is CASL_ENTER:
   4107  1.1      is 	bra.b		~+16
   4108  1.1      is 
   4109  1.1      is CASL_UPDATE:
   4110  1.1      is 	movs.w		%d2,(%a0)+		# Update[31:16] -> DEST
   4111  1.1      is 	movc		%a2,%buscr		# assert LOCKE*
   4112  1.1      is 	movs.w		%d3,(%a0)		# Update[15:0] -> DEST+0x2
   4113  1.1      is 	bra.b		CASL_UPDATE2
   4114  1.1      is 	bra.b		~+16
   4115  1.1      is 
   4116  1.1      is CASL_UPDATE2:
   4117  1.1      is 	movc		%a3,%buscr		# unlock the bus
   4118  1.1      is 	bra.b		casl_update_done
   4119  1.1      is 	nop
   4120  1.1      is 	nop
   4121  1.1      is 	nop
   4122  1.1      is 	nop
   4123  1.1      is 	bra.b		~+16
   4124  1.1      is 
   4125  1.1      is CASL_NOUPDATE:
   4126  1.1      is 	swap		%d0			# get Dest[31:16]
   4127  1.1      is 	movs.w		%d0,(%a0)+		# Dest[31:16] -> DEST
   4128  1.1      is 	swap		%d0			# get Dest[15:0]
   4129  1.1      is 	movc		%a2,%buscr		# assert LOCKE*
   4130  1.1      is 	bra.b 		CASL_NOUPDATE2
   4131  1.1      is 	bra.b		~+16
   4132  1.1      is 
   4133  1.1      is CASL_NOUPDATE2:
   4134  1.1      is 	movs.w		%d0,(%a0)		# Dest[15:0] -> DEST+0x2
   4135  1.1      is 	movc		%a3,%buscr		# unlock the bus
   4136  1.1      is 	bra.b		casl_noupdate_done
   4137  1.1      is 	nop
   4138  1.1      is 	nop
   4139  1.1      is 	bra.b		~+16
   4140  1.1      is 
   4141  1.1      is CASL_FILLER:
   4142  1.1      is 	nop
   4143  1.1      is 	nop
   4144  1.1      is 	nop
   4145  1.1      is 	nop
   4146  1.1      is 	nop
   4147  1.1      is 	nop
   4148  1.1      is 	nop
   4149  1.1      is 	bra.b		CASL_START
   4150  1.1      is 
   4151  1.1      is #################################################################
   4152  1.1      is # THIS MUST BE THE STATE OF THE INTEGER REGISTER FILE UPON	#
   4153  1.1      is # CALLING _isp_cas_finish().					#
   4154  1.1      is #								#
   4155  1.1      is # D0 = destination[31:0] operand				#
   4156  1.1      is # D1 = 'xxxxxx11 -> no reg update; 'xxxxxx00 -> update required	#
   4157  1.1      is # D2 = xxxxxxxx							#
   4158  1.1      is # D3 = xxxxxxxx							#
   4159  1.1      is # D4 = compare[31:0] operand					#
   4160  1.1      is # D5 = xxxxxxxx							#
   4161  1.1      is # D6 = xxxxxxxx							#
   4162  1.1      is # D7 = xxxxxxxx							#
   4163  1.1      is # A0 = xxxxxxxx							#
   4164  1.1      is # A1 = xxxxxxxx							#
   4165  1.1      is # A2 = xxxxxxxx							#
   4166  1.1      is # A3 = xxxxxxxx							#
   4167  1.1      is # A4 = xxxxxxxx							#
   4168  1.1      is # A5 = xxxxxxxx							#
   4169  1.1      is # A6 = frame pointer						#
   4170  1.1      is # A7 = stack pointer						#
   4171  1.1      is #################################################################
   4172  1.1      is 
   4173  1.1      is casl_noupdate_done:
   4174  1.1      is 
   4175  1.1      is # restore previous SFC/DFC value.
   4176  1.1      is 	movc		%d6,%sfc		# restore old SFC
   4177  1.1      is 	movc		%d6,%dfc		# restore old DFC
   4178  1.1      is 
   4179  1.1      is # restore previous interrupt mask level.
   4180  1.1      is 	mov.w		%d7,%sr			# restore old SR
   4181  1.1      is 
   4182  1.1      is 	sf		%d1			# indicate no update was done
   4183  1.1      is 	bra.l		_isp_cas_finish
   4184  1.1      is 
   4185  1.1      is casl_update_done:
   4186  1.1      is 
   4187  1.1      is # restore previous SFC/DFC value.
   4188  1.1      is 	movc		%d6,%sfc		# restore old SFC
   4189  1.1      is 	movc		%d6,%dfc		# restore old DFC
   4190  1.1      is 
   4191  1.1      is # restore previous interrupts mask level.
   4192  1.1      is 	mov.w		%d7,%sr			# restore old SR
   4193  1.1      is 
   4194  1.1      is 	st		%d1			# indicate update was done
   4195  1.1      is 	bra.l		_isp_cas_finish
   4196  1.1      is 
   4197  1.1      is #######################################
   4198  1.1      is casl2:
   4199  1.1      is 	mov.l		%d2,%d5			# d5 = Update[7:0]
   4200  1.1      is 	lsr.l		&0x8,%d2
   4201  1.1      is 	mov.l		%d2,%d3			# d3 = Update[23:8]
   4202  1.1      is 	swap		%d2			# d2 = Update[31:24]
   4203  1.1      is 
   4204  1.1      is # mask interrupts levels 0-6. save old mask value.
   4205  1.1      is 	mov.w		%sr,%d7			# save current SR
   4206  1.1      is 	ori.w		&0x0700,%sr		# inhibit interrupts
   4207  1.1      is 
   4208  1.1      is # load the SFC and DFC with the appropriate mode.
   4209  1.1      is 	movc		%sfc,%d6		# save old SFC/DFC
   4210  1.1      is 	movc		%d0,%sfc		# load new sfc
   4211  1.1      is 	movc		%d0,%dfc		# load new dfc
   4212  1.1      is 
   4213  1.1      is # pre-load the operand ATC. no page faults should occur here because
   4214  1.1      is # _real_lock_page() should have taken care of this already.
   4215  1.1      is 	plpaw		(%a1)			# load atc for ADDR
   4216  1.1      is 	plpaw		(%a2)			# load atc for ADDR+3
   4217  1.1      is 
   4218  1.1      is # puch the operand lines from the cache if they exist.
   4219  1.1      is 	cpushl		%dc,(%a1)		# push dirty data
   4220  1.1      is 	cpushl		%dc,(%a2)		# push dirty data
   4221  1.1      is 
   4222  1.1      is # load the BUSCR values.
   4223  1.1      is 	mov.l		&0x80000000,%a1		# assert LOCK* buscr value
   4224  1.1      is 	mov.l		&0xa0000000,%a2		# assert LOCKE* buscr value
   4225  1.1      is 	mov.l		&0x00000000,%a3		# buscr unlock value
   4226  1.1      is 
   4227  1.1      is # pre-load the instruction cache for the following algorithm.
   4228  1.1      is # this will minimize the number of cycles that LOCK* will be asserted.
   4229  1.1      is 	bra.b		CASL2_ENTER		# start pre-loading icache
   4230  1.1      is 
   4231  1.1      is #
   4232  1.1      is # D0 = dst operand <-
   4233  1.1      is # D1 = xxxxxxxx
   4234  1.1      is # D2 = update[31:24] operand
   4235  1.1      is # D3 = update[23:8]  operand
   4236  1.1      is # D4 = compare[31:0] operand
   4237  1.1      is # D5 = update[7:0]  operand
   4238  1.1      is # D6 = old SFC/DFC
   4239  1.1      is # D7 = old SR
   4240  1.1      is # A0 = ADDR
   4241  1.1      is # A1 = bus LOCK*  value
   4242  1.1      is # A2 = bus LOCKE* value
   4243  1.1      is # A3 = bus unlock value
   4244  1.1      is # A4 = xxxxxxxx
   4245  1.1      is # A5 = xxxxxxxx
   4246  1.1      is #
   4247  1.1      is 	align		0x10
   4248  1.1      is CASL2_START:
   4249  1.1      is 	movc		%a1,%buscr		# assert LOCK*
   4250  1.1      is 	movs.l		(%a0),%d0		# fetch Dest[31:0]
   4251  1.1      is 	cmp.l	 	%d0,%d4			# Dest - Compare
   4252  1.1      is 	bne.b		CASL2_NOUPDATE
   4253  1.1      is 	bra.b 		CASL2_UPDATE
   4254  1.1      is CASL2_ENTER:
   4255  1.1      is 	bra.b		~+16
   4256  1.1      is 
   4257  1.1      is CASL2_UPDATE:
   4258  1.1      is 	movs.b		%d2,(%a0)+		# Update[31:24] -> DEST
   4259  1.1      is 	movs.w		%d3,(%a0)+		# Update[23:8] -> DEST+0x1
   4260  1.1      is 	movc		%a2,%buscr		# assert LOCKE*
   4261  1.1      is 	bra.b		CASL2_UPDATE2
   4262  1.1      is 	bra.b		~+16
   4263  1.1      is 
   4264  1.1      is CASL2_UPDATE2:
   4265  1.1      is 	movs.b		%d5,(%a0)		# Update[7:0] -> DEST+0x3
   4266  1.1      is 	movc		%a3,%buscr		# unlock the bus
   4267  1.1      is 	bra.w		casl_update_done
   4268  1.1      is 	nop
   4269  1.1      is 	bra.b		~+16
   4270  1.1      is 
   4271  1.1      is CASL2_NOUPDATE:
   4272  1.1      is 	rol.l		&0x8,%d0		# get Dest[31:24]
   4273  1.1      is 	movs.b		%d0,(%a0)+		# Dest[31:24] -> DEST
   4274  1.1      is 	swap		%d0			# get Dest[23:8]
   4275  1.1      is 	movs.w		%d0,(%a0)+		# Dest[23:8] -> DEST+0x1
   4276  1.1      is 	bra.b 		CASL2_NOUPDATE2
   4277  1.1      is 	bra.b		~+16
   4278  1.1      is 
   4279  1.1      is CASL2_NOUPDATE2:
   4280  1.1      is 	rol.l		&0x8,%d0		# get Dest[7:0]
   4281  1.1      is 	movc		%a2,%buscr		# assert LOCKE*
   4282  1.1      is 	movs.b		%d0,(%a0)		# Dest[7:0] -> DEST+0x3
   4283  1.1      is 	bra.b 		CASL2_NOUPDATE3
   4284  1.1      is 	nop
   4285  1.1      is 	bra.b		~+16
   4286  1.1      is 
   4287  1.1      is CASL2_NOUPDATE3:
   4288  1.1      is 	movc		%a3,%buscr		# unlock the bus
   4289  1.1      is 	bra.w		casl_noupdate_done
   4290  1.1      is 	nop
   4291  1.1      is 	nop
   4292  1.1      is 	nop
   4293  1.1      is 	bra.b		~+16
   4294  1.1      is 
   4295  1.1      is CASL2_FILLER:
   4296  1.1      is 	nop
   4297  1.1      is 	nop
   4298  1.1      is 	nop
   4299  1.1      is 	nop
   4300  1.1      is 	nop
   4301  1.1      is 	nop
   4302  1.1      is 	nop
   4303  1.1      is 	bra.b		CASL2_START
   4304  1.1      is 
   4305  1.1      is ####
   4306  1.1      is ####
   4307  1.1      is # end label used by _isp_cas_inrange()
   4308  1.1      is 	global		_CASHI
   4309  1.1      is _CASHI:
   4310