162306a36Sopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
262306a36Sopenharmony_ciMOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
362306a36Sopenharmony_ciM68000 Hi-Performance Microprocessor Division
462306a36Sopenharmony_ciM68060 Software Package
562306a36Sopenharmony_ciProduction Release P1.00 -- October 10, 1994
662306a36Sopenharmony_ci
762306a36Sopenharmony_ciM68060 Software Package Copyright © 1993, 1994 Motorola Inc.  All rights reserved.
862306a36Sopenharmony_ci
962306a36Sopenharmony_ciTHE SOFTWARE is provided on an "AS IS" basis and without warranty.
1062306a36Sopenharmony_ciTo the maximum extent permitted by applicable law,
1162306a36Sopenharmony_ciMOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
1262306a36Sopenharmony_ciINCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
1362306a36Sopenharmony_ciand any warranty against infringement with regard to the SOFTWARE
1462306a36Sopenharmony_ci(INCLUDING ANY MODIFIED VERSIONS THEREOF) and any accompanying written materials.
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ciTo the maximum extent permitted by applicable law,
1762306a36Sopenharmony_ciIN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
1862306a36Sopenharmony_ci(INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS,
1962306a36Sopenharmony_ciBUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS)
2062306a36Sopenharmony_ciARISING OF THE USE OR INABILITY TO USE THE SOFTWARE.
2162306a36Sopenharmony_ciMotorola assumes no responsibility for the maintenance and support of the SOFTWARE.
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ciYou are hereby granted a copyright license to use, modify, and distribute the SOFTWARE
2462306a36Sopenharmony_ciso long as this entire notice is retained without alteration in any modified and/or
2562306a36Sopenharmony_ciredistributed versions, and that such modified versions are clearly identified as such.
2662306a36Sopenharmony_ciNo licenses are granted by implication, estoppel or otherwise under any patents
2762306a36Sopenharmony_cior trademarks of Motorola, Inc.
2862306a36Sopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2962306a36Sopenharmony_ci# ireal.s:
3062306a36Sopenharmony_ci#	This file is appended to the top of the 060ISP package
3162306a36Sopenharmony_ci# and contains the entry points into the package. The user, in
3262306a36Sopenharmony_ci# effect, branches to one of the branch table entries located
3362306a36Sopenharmony_ci# after _060ISP_TABLE.
3462306a36Sopenharmony_ci#	Also, subroutine stubs exist in this file (_isp_done for
3562306a36Sopenharmony_ci# example) that are referenced by the ISP package itself in order
3662306a36Sopenharmony_ci# to call a given routine. The stub routine actually performs the
3762306a36Sopenharmony_ci# callout. The ISP code does a "bsr" to the stub routine. This
3862306a36Sopenharmony_ci# extra layer of hierarchy adds a slight performance penalty but
3962306a36Sopenharmony_ci# it makes the ISP code easier to read and more mainatinable.
4062306a36Sopenharmony_ci#
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ciset	_off_chk,	0x00
4362306a36Sopenharmony_ciset	_off_divbyzero,	0x04
4462306a36Sopenharmony_ciset	_off_trace,	0x08
4562306a36Sopenharmony_ciset	_off_access,	0x0c
4662306a36Sopenharmony_ciset	_off_done,	0x10
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ciset	_off_cas,	0x14
4962306a36Sopenharmony_ciset	_off_cas2,	0x18
5062306a36Sopenharmony_ciset	_off_lock,	0x1c
5162306a36Sopenharmony_ciset	_off_unlock,	0x20
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ciset	_off_imr,	0x40
5462306a36Sopenharmony_ciset	_off_dmr,	0x44
5562306a36Sopenharmony_ciset	_off_dmw,	0x48
5662306a36Sopenharmony_ciset	_off_irw,	0x4c
5762306a36Sopenharmony_ciset	_off_irl,	0x50
5862306a36Sopenharmony_ciset	_off_drb,	0x54
5962306a36Sopenharmony_ciset	_off_drw,	0x58
6062306a36Sopenharmony_ciset	_off_drl,	0x5c
6162306a36Sopenharmony_ciset	_off_dwb,	0x60
6262306a36Sopenharmony_ciset	_off_dww,	0x64
6362306a36Sopenharmony_ciset	_off_dwl,	0x68
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci_060ISP_TABLE:
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci# Here's the table of ENTRY POINTS for those linking the package.
6862306a36Sopenharmony_ci	bra.l		_isp_unimp
6962306a36Sopenharmony_ci	short		0x0000
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci	bra.l		_isp_cas
7262306a36Sopenharmony_ci	short		0x0000
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci	bra.l		_isp_cas2
7562306a36Sopenharmony_ci	short		0x0000
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci	bra.l		_isp_cas_finish
7862306a36Sopenharmony_ci	short		0x0000
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci	bra.l		_isp_cas2_finish
8162306a36Sopenharmony_ci	short		0x0000
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci	bra.l		_isp_cas_inrange
8462306a36Sopenharmony_ci	short		0x0000
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci	bra.l		_isp_cas_terminate
8762306a36Sopenharmony_ci	short		0x0000
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci	bra.l		_isp_cas_restart
9062306a36Sopenharmony_ci	short		0x0000
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci	space		64
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ci#############################################################
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci	global		_real_chk
9762306a36Sopenharmony_ci_real_chk:
9862306a36Sopenharmony_ci	mov.l		%d0,-(%sp)
9962306a36Sopenharmony_ci	mov.l		(_060ISP_TABLE-0x80+_off_chk,%pc),%d0
10062306a36Sopenharmony_ci	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
10162306a36Sopenharmony_ci	mov.l		0x4(%sp),%d0
10262306a36Sopenharmony_ci	rtd		&0x4
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ci	global		_real_divbyzero
10562306a36Sopenharmony_ci_real_divbyzero:
10662306a36Sopenharmony_ci	mov.l		%d0,-(%sp)
10762306a36Sopenharmony_ci	mov.l		(_060ISP_TABLE-0x80+_off_divbyzero,%pc),%d0
10862306a36Sopenharmony_ci	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
10962306a36Sopenharmony_ci	mov.l		0x4(%sp),%d0
11062306a36Sopenharmony_ci	rtd		&0x4
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci	global		_real_trace
11362306a36Sopenharmony_ci_real_trace:
11462306a36Sopenharmony_ci	mov.l		%d0,-(%sp)
11562306a36Sopenharmony_ci	mov.l		(_060ISP_TABLE-0x80+_off_trace,%pc),%d0
11662306a36Sopenharmony_ci	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
11762306a36Sopenharmony_ci	mov.l		0x4(%sp),%d0
11862306a36Sopenharmony_ci	rtd		&0x4
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci	global		_real_access
12162306a36Sopenharmony_ci_real_access:
12262306a36Sopenharmony_ci	mov.l		%d0,-(%sp)
12362306a36Sopenharmony_ci	mov.l		(_060ISP_TABLE-0x80+_off_access,%pc),%d0
12462306a36Sopenharmony_ci	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
12562306a36Sopenharmony_ci	mov.l		0x4(%sp),%d0
12662306a36Sopenharmony_ci	rtd		&0x4
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_ci	global		_isp_done
12962306a36Sopenharmony_ci_isp_done:
13062306a36Sopenharmony_ci	mov.l		%d0,-(%sp)
13162306a36Sopenharmony_ci	mov.l		(_060ISP_TABLE-0x80+_off_done,%pc),%d0
13262306a36Sopenharmony_ci	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
13362306a36Sopenharmony_ci	mov.l		0x4(%sp),%d0
13462306a36Sopenharmony_ci	rtd		&0x4
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_ci#######################################
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ci	global		_real_cas
13962306a36Sopenharmony_ci_real_cas:
14062306a36Sopenharmony_ci	mov.l		%d0,-(%sp)
14162306a36Sopenharmony_ci	mov.l		(_060ISP_TABLE-0x80+_off_cas,%pc),%d0
14262306a36Sopenharmony_ci	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
14362306a36Sopenharmony_ci	mov.l		0x4(%sp),%d0
14462306a36Sopenharmony_ci	rtd		&0x4
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_ci	global		_real_cas2
14762306a36Sopenharmony_ci_real_cas2:
14862306a36Sopenharmony_ci	mov.l		%d0,-(%sp)
14962306a36Sopenharmony_ci	mov.l		(_060ISP_TABLE-0x80+_off_cas2,%pc),%d0
15062306a36Sopenharmony_ci	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
15162306a36Sopenharmony_ci	mov.l		0x4(%sp),%d0
15262306a36Sopenharmony_ci	rtd		&0x4
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_ci	global		_real_lock_page
15562306a36Sopenharmony_ci_real_lock_page:
15662306a36Sopenharmony_ci	mov.l		%d0,-(%sp)
15762306a36Sopenharmony_ci	mov.l		(_060ISP_TABLE-0x80+_off_lock,%pc),%d0
15862306a36Sopenharmony_ci	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
15962306a36Sopenharmony_ci	mov.l		0x4(%sp),%d0
16062306a36Sopenharmony_ci	rtd		&0x4
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_ci	global		_real_unlock_page
16362306a36Sopenharmony_ci_real_unlock_page:
16462306a36Sopenharmony_ci	mov.l		%d0,-(%sp)
16562306a36Sopenharmony_ci	mov.l		(_060ISP_TABLE-0x80+_off_unlock,%pc),%d0
16662306a36Sopenharmony_ci	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
16762306a36Sopenharmony_ci	mov.l		0x4(%sp),%d0
16862306a36Sopenharmony_ci	rtd		&0x4
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_ci#######################################
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_ci	global		_imem_read
17362306a36Sopenharmony_ci_imem_read:
17462306a36Sopenharmony_ci	mov.l		%d0,-(%sp)
17562306a36Sopenharmony_ci	mov.l		(_060ISP_TABLE-0x80+_off_imr,%pc),%d0
17662306a36Sopenharmony_ci	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
17762306a36Sopenharmony_ci	mov.l		0x4(%sp),%d0
17862306a36Sopenharmony_ci	rtd		&0x4
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_ci	global		_dmem_read
18162306a36Sopenharmony_ci_dmem_read:
18262306a36Sopenharmony_ci	mov.l		%d0,-(%sp)
18362306a36Sopenharmony_ci	mov.l		(_060ISP_TABLE-0x80+_off_dmr,%pc),%d0
18462306a36Sopenharmony_ci	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
18562306a36Sopenharmony_ci	mov.l		0x4(%sp),%d0
18662306a36Sopenharmony_ci	rtd		&0x4
18762306a36Sopenharmony_ci
18862306a36Sopenharmony_ci	global		_dmem_write
18962306a36Sopenharmony_ci_dmem_write:
19062306a36Sopenharmony_ci	mov.l		%d0,-(%sp)
19162306a36Sopenharmony_ci	mov.l		(_060ISP_TABLE-0x80+_off_dmw,%pc),%d0
19262306a36Sopenharmony_ci	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
19362306a36Sopenharmony_ci	mov.l		0x4(%sp),%d0
19462306a36Sopenharmony_ci	rtd		&0x4
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_ci	global		_imem_read_word
19762306a36Sopenharmony_ci_imem_read_word:
19862306a36Sopenharmony_ci	mov.l		%d0,-(%sp)
19962306a36Sopenharmony_ci	mov.l		(_060ISP_TABLE-0x80+_off_irw,%pc),%d0
20062306a36Sopenharmony_ci	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
20162306a36Sopenharmony_ci	mov.l		0x4(%sp),%d0
20262306a36Sopenharmony_ci	rtd		&0x4
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_ci	global		_imem_read_long
20562306a36Sopenharmony_ci_imem_read_long:
20662306a36Sopenharmony_ci	mov.l		%d0,-(%sp)
20762306a36Sopenharmony_ci	mov.l		(_060ISP_TABLE-0x80+_off_irl,%pc),%d0
20862306a36Sopenharmony_ci	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
20962306a36Sopenharmony_ci	mov.l		0x4(%sp),%d0
21062306a36Sopenharmony_ci	rtd		&0x4
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_ci	global		_dmem_read_byte
21362306a36Sopenharmony_ci_dmem_read_byte:
21462306a36Sopenharmony_ci	mov.l		%d0,-(%sp)
21562306a36Sopenharmony_ci	mov.l		(_060ISP_TABLE-0x80+_off_drb,%pc),%d0
21662306a36Sopenharmony_ci	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
21762306a36Sopenharmony_ci	mov.l		0x4(%sp),%d0
21862306a36Sopenharmony_ci	rtd		&0x4
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_ci	global		_dmem_read_word
22162306a36Sopenharmony_ci_dmem_read_word:
22262306a36Sopenharmony_ci	mov.l		%d0,-(%sp)
22362306a36Sopenharmony_ci	mov.l		(_060ISP_TABLE-0x80+_off_drw,%pc),%d0
22462306a36Sopenharmony_ci	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
22562306a36Sopenharmony_ci	mov.l		0x4(%sp),%d0
22662306a36Sopenharmony_ci	rtd		&0x4
22762306a36Sopenharmony_ci
22862306a36Sopenharmony_ci	global		_dmem_read_long
22962306a36Sopenharmony_ci_dmem_read_long:
23062306a36Sopenharmony_ci	mov.l		%d0,-(%sp)
23162306a36Sopenharmony_ci	mov.l		(_060ISP_TABLE-0x80+_off_drl,%pc),%d0
23262306a36Sopenharmony_ci	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
23362306a36Sopenharmony_ci	mov.l		0x4(%sp),%d0
23462306a36Sopenharmony_ci	rtd		&0x4
23562306a36Sopenharmony_ci
23662306a36Sopenharmony_ci	global		_dmem_write_byte
23762306a36Sopenharmony_ci_dmem_write_byte:
23862306a36Sopenharmony_ci	mov.l		%d0,-(%sp)
23962306a36Sopenharmony_ci	mov.l		(_060ISP_TABLE-0x80+_off_dwb,%pc),%d0
24062306a36Sopenharmony_ci	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
24162306a36Sopenharmony_ci	mov.l		0x4(%sp),%d0
24262306a36Sopenharmony_ci	rtd		&0x4
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_ci	global		_dmem_write_word
24562306a36Sopenharmony_ci_dmem_write_word:
24662306a36Sopenharmony_ci	mov.l		%d0,-(%sp)
24762306a36Sopenharmony_ci	mov.l		(_060ISP_TABLE-0x80+_off_dww,%pc),%d0
24862306a36Sopenharmony_ci	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
24962306a36Sopenharmony_ci	mov.l		0x4(%sp),%d0
25062306a36Sopenharmony_ci	rtd		&0x4
25162306a36Sopenharmony_ci
25262306a36Sopenharmony_ci	global		_dmem_write_long
25362306a36Sopenharmony_ci_dmem_write_long:
25462306a36Sopenharmony_ci	mov.l		%d0,-(%sp)
25562306a36Sopenharmony_ci	mov.l		(_060ISP_TABLE-0x80+_off_dwl,%pc),%d0
25662306a36Sopenharmony_ci	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
25762306a36Sopenharmony_ci	mov.l		0x4(%sp),%d0
25862306a36Sopenharmony_ci	rtd		&0x4
25962306a36Sopenharmony_ci
26062306a36Sopenharmony_ci#
26162306a36Sopenharmony_ci# This file contains a set of define statements for constants
26262306a36Sopenharmony_ci# in oreder to promote readability within the core code itself.
26362306a36Sopenharmony_ci#
26462306a36Sopenharmony_ci
26562306a36Sopenharmony_ciset LOCAL_SIZE,		96			# stack frame size(bytes)
26662306a36Sopenharmony_ciset LV,			-LOCAL_SIZE		# stack offset
26762306a36Sopenharmony_ci
26862306a36Sopenharmony_ciset EXC_ISR,		0x4			# stack status register
26962306a36Sopenharmony_ciset EXC_IPC,		0x6			# stack pc
27062306a36Sopenharmony_ciset EXC_IVOFF,		0xa			# stacked vector offset
27162306a36Sopenharmony_ci
27262306a36Sopenharmony_ciset EXC_AREGS,		LV+64			# offset of all address regs
27362306a36Sopenharmony_ciset EXC_DREGS,		LV+32			# offset of all data regs
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_ciset EXC_A7,		EXC_AREGS+(7*4)		# offset of a7
27662306a36Sopenharmony_ciset EXC_A6,		EXC_AREGS+(6*4)		# offset of a6
27762306a36Sopenharmony_ciset EXC_A5,		EXC_AREGS+(5*4)		# offset of a5
27862306a36Sopenharmony_ciset EXC_A4,		EXC_AREGS+(4*4)		# offset of a4
27962306a36Sopenharmony_ciset EXC_A3,		EXC_AREGS+(3*4)		# offset of a3
28062306a36Sopenharmony_ciset EXC_A2,		EXC_AREGS+(2*4)		# offset of a2
28162306a36Sopenharmony_ciset EXC_A1,		EXC_AREGS+(1*4)		# offset of a1
28262306a36Sopenharmony_ciset EXC_A0,		EXC_AREGS+(0*4)		# offset of a0
28362306a36Sopenharmony_ciset EXC_D7,		EXC_DREGS+(7*4)		# offset of d7
28462306a36Sopenharmony_ciset EXC_D6,		EXC_DREGS+(6*4)		# offset of d6
28562306a36Sopenharmony_ciset EXC_D5,		EXC_DREGS+(5*4)		# offset of d5
28662306a36Sopenharmony_ciset EXC_D4,		EXC_DREGS+(4*4)		# offset of d4
28762306a36Sopenharmony_ciset EXC_D3,		EXC_DREGS+(3*4)		# offset of d3
28862306a36Sopenharmony_ciset EXC_D2,		EXC_DREGS+(2*4)		# offset of d2
28962306a36Sopenharmony_ciset EXC_D1,		EXC_DREGS+(1*4)		# offset of d1
29062306a36Sopenharmony_ciset EXC_D0,		EXC_DREGS+(0*4)		# offset of d0
29162306a36Sopenharmony_ci
29262306a36Sopenharmony_ciset EXC_TEMP,		LV+16			# offset of temp stack space
29362306a36Sopenharmony_ci
29462306a36Sopenharmony_ciset EXC_SAVVAL,		LV+12			# offset of old areg value
29562306a36Sopenharmony_ciset EXC_SAVREG,		LV+11			# offset of old areg index
29662306a36Sopenharmony_ci
29762306a36Sopenharmony_ciset SPCOND_FLG,		LV+10			# offset of spc condition flg
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_ciset EXC_CC,		LV+8			# offset of cc register
30062306a36Sopenharmony_ciset EXC_EXTWPTR,	LV+4			# offset of current PC
30162306a36Sopenharmony_ciset EXC_EXTWORD,	LV+2			# offset of current ext opword
30262306a36Sopenharmony_ciset EXC_OPWORD,		LV+0			# offset of current opword
30362306a36Sopenharmony_ci
30462306a36Sopenharmony_ci###########################
30562306a36Sopenharmony_ci# SPecial CONDition FLaGs #
30662306a36Sopenharmony_ci###########################
30762306a36Sopenharmony_ciset mia7_flg,		0x04			# (a7)+ flag
30862306a36Sopenharmony_ciset mda7_flg,		0x08			# -(a7) flag
30962306a36Sopenharmony_ciset ichk_flg,		0x10			# chk exception flag
31062306a36Sopenharmony_ciset idbyz_flg,		0x20			# divbyzero flag
31162306a36Sopenharmony_ciset restore_flg,	0x40			# restore -(an)+ flag
31262306a36Sopenharmony_ciset immed_flg,		0x80			# immediate data flag
31362306a36Sopenharmony_ci
31462306a36Sopenharmony_ciset mia7_bit,		0x2			# (a7)+ bit
31562306a36Sopenharmony_ciset mda7_bit,		0x3			# -(a7) bit
31662306a36Sopenharmony_ciset ichk_bit,		0x4			# chk exception bit
31762306a36Sopenharmony_ciset idbyz_bit,		0x5			# divbyzero bit
31862306a36Sopenharmony_ciset restore_bit,	0x6			# restore -(a7)+ bit
31962306a36Sopenharmony_ciset immed_bit,		0x7			# immediate data bit
32062306a36Sopenharmony_ci
32162306a36Sopenharmony_ci#########
32262306a36Sopenharmony_ci# Misc. #
32362306a36Sopenharmony_ci#########
32462306a36Sopenharmony_ciset BYTE,		1			# len(byte) == 1 byte
32562306a36Sopenharmony_ciset WORD,		2			# len(word) == 2 bytes
32662306a36Sopenharmony_ciset LONG,		4			# len(longword) == 4 bytes
32762306a36Sopenharmony_ci
32862306a36Sopenharmony_ci#########################################################################
32962306a36Sopenharmony_ci# XDEF ****************************************************************	#
33062306a36Sopenharmony_ci#	_isp_unimp(): 060ISP entry point for Unimplemented Instruction	#
33162306a36Sopenharmony_ci#									#
33262306a36Sopenharmony_ci#	This handler should be the first code executed upon taking the	#
33362306a36Sopenharmony_ci#	"Unimplemented Integer Instruction" exception in an operating	#
33462306a36Sopenharmony_ci#	system.								#
33562306a36Sopenharmony_ci#									#
33662306a36Sopenharmony_ci# XREF ****************************************************************	#
33762306a36Sopenharmony_ci#	_imem_read_{word,long}() - read instruction word/longword	#
33862306a36Sopenharmony_ci#	_mul64() - emulate 64-bit multiply				#
33962306a36Sopenharmony_ci#	_div64() - emulate 64-bit divide				#
34062306a36Sopenharmony_ci#	_moveperipheral() - emulate "movep"				#
34162306a36Sopenharmony_ci#	_compandset() - emulate misaligned "cas"			#
34262306a36Sopenharmony_ci#	_compandset2() - emulate "cas2"					#
34362306a36Sopenharmony_ci#	_chk2_cmp2() - emulate "cmp2" and "chk2"			#
34462306a36Sopenharmony_ci#	_isp_done() - "callout" for normal final exit			#
34562306a36Sopenharmony_ci#	_real_trace() - "callout" for Trace exception			#
34662306a36Sopenharmony_ci#	_real_chk() - "callout" for Chk exception			#
34762306a36Sopenharmony_ci#	_real_divbyzero() - "callout" for DZ exception			#
34862306a36Sopenharmony_ci#	_real_access() - "callout" for access error exception		#
34962306a36Sopenharmony_ci#									#
35062306a36Sopenharmony_ci# INPUT ***************************************************************	#
35162306a36Sopenharmony_ci#	- The system stack contains the Unimp Int Instr stack frame	#
35262306a36Sopenharmony_ci#									#
35362306a36Sopenharmony_ci# OUTPUT **************************************************************	#
35462306a36Sopenharmony_ci#	If Trace exception:						#
35562306a36Sopenharmony_ci#	- The system stack changed to contain Trace exc stack frame	#
35662306a36Sopenharmony_ci#	If Chk exception:						#
35762306a36Sopenharmony_ci#	- The system stack changed to contain Chk exc stack frame	#
35862306a36Sopenharmony_ci#	If DZ exception:						#
35962306a36Sopenharmony_ci#	- The system stack changed to contain DZ exc stack frame	#
36062306a36Sopenharmony_ci#	If access error exception:					#
36162306a36Sopenharmony_ci#	- The system stack changed to contain access err exc stk frame	#
36262306a36Sopenharmony_ci#	Else:								#
36362306a36Sopenharmony_ci#	- Results saved as appropriate					#
36462306a36Sopenharmony_ci#									#
36562306a36Sopenharmony_ci# ALGORITHM ***********************************************************	#
36662306a36Sopenharmony_ci#	This handler fetches the first instruction longword from	#
36762306a36Sopenharmony_ci# memory and decodes it to determine which of the unimplemented		#
36862306a36Sopenharmony_ci# integer instructions caused this exception. This handler then calls	#
36962306a36Sopenharmony_ci# one of _mul64(), _div64(), _moveperipheral(), _compandset(),		#
37062306a36Sopenharmony_ci# _compandset2(), or _chk2_cmp2() as appropriate.			#
37162306a36Sopenharmony_ci#	Some of these instructions, by their nature, may produce other	#
37262306a36Sopenharmony_ci# types of exceptions. "div" can produce a divide-by-zero exception,	#
37362306a36Sopenharmony_ci# and "chk2" can cause a "Chk" exception. In both cases, the current	#
37462306a36Sopenharmony_ci# exception stack frame must be converted to an exception stack frame	#
37562306a36Sopenharmony_ci# of the correct exception type and an exit must be made through	#
37662306a36Sopenharmony_ci# _real_divbyzero() or _real_chk() as appropriate. In addition, all	#
37762306a36Sopenharmony_ci# instructions may be executing while Trace is enabled. If so, then	#
37862306a36Sopenharmony_ci# a Trace exception stack frame must be created and an exit made	#
37962306a36Sopenharmony_ci# through _real_trace().						#
38062306a36Sopenharmony_ci#	Meanwhile, if any read or write to memory using the		#
38162306a36Sopenharmony_ci# _mem_{read,write}() "callout"s returns a failing value, then an	#
38262306a36Sopenharmony_ci# access error frame must be created and an exit made through		#
38362306a36Sopenharmony_ci# _real_access().							#
38462306a36Sopenharmony_ci#	If none of these occur, then a normal exit is made through	#
38562306a36Sopenharmony_ci# _isp_done().								#
38662306a36Sopenharmony_ci#									#
38762306a36Sopenharmony_ci#	This handler, upon entry, saves almost all user-visible		#
38862306a36Sopenharmony_ci# address and data registers to the stack. Although this may seem to	#
38962306a36Sopenharmony_ci# cause excess memory traffic, it was found that due to having to	#
39062306a36Sopenharmony_ci# access these register files for things like data retrieval and <ea>	#
39162306a36Sopenharmony_ci# calculations, it was more efficient to have them on the stack where	#
39262306a36Sopenharmony_ci# they could be accessed by indexing rather than to make subroutine	#
39362306a36Sopenharmony_ci# calls to retrieve a register of a particular index.			#
39462306a36Sopenharmony_ci#									#
39562306a36Sopenharmony_ci#########################################################################
39662306a36Sopenharmony_ci
39762306a36Sopenharmony_ci	global		_isp_unimp
39862306a36Sopenharmony_ci_isp_unimp:
39962306a36Sopenharmony_ci	link.w		%a6,&-LOCAL_SIZE	# create room for stack frame
40062306a36Sopenharmony_ci
40162306a36Sopenharmony_ci	movm.l		&0x3fff,EXC_DREGS(%a6)	# store d0-d7/a0-a5
40262306a36Sopenharmony_ci	mov.l		(%a6),EXC_A6(%a6)	# store a6
40362306a36Sopenharmony_ci
40462306a36Sopenharmony_ci	btst		&0x5,EXC_ISR(%a6)	# from s or u mode?
40562306a36Sopenharmony_ci	bne.b		uieh_s			# supervisor mode
40662306a36Sopenharmony_ciuieh_u:
40762306a36Sopenharmony_ci	mov.l		%usp,%a0		# fetch user stack pointer
40862306a36Sopenharmony_ci	mov.l		%a0,EXC_A7(%a6)		# store a7
40962306a36Sopenharmony_ci	bra.b		uieh_cont
41062306a36Sopenharmony_ciuieh_s:
41162306a36Sopenharmony_ci	lea		0xc(%a6),%a0
41262306a36Sopenharmony_ci	mov.l		%a0,EXC_A7(%a6)		# store corrected sp
41362306a36Sopenharmony_ci
41462306a36Sopenharmony_ci###############################################################################
41562306a36Sopenharmony_ci
41662306a36Sopenharmony_ciuieh_cont:
41762306a36Sopenharmony_ci	clr.b		SPCOND_FLG(%a6)		# clear "special case" flag
41862306a36Sopenharmony_ci
41962306a36Sopenharmony_ci	mov.w		EXC_ISR(%a6),EXC_CC(%a6) # store cc copy on stack
42062306a36Sopenharmony_ci	mov.l		EXC_IPC(%a6),EXC_EXTWPTR(%a6) # store extwptr on stack
42162306a36Sopenharmony_ci
42262306a36Sopenharmony_ci#
42362306a36Sopenharmony_ci# fetch the opword and first extension word pointed to by the stacked pc
42462306a36Sopenharmony_ci# and store them to the stack for now
42562306a36Sopenharmony_ci#
42662306a36Sopenharmony_ci	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
42762306a36Sopenharmony_ci	addq.l		&0x4,EXC_EXTWPTR(%a6)	# incr instruction ptr
42862306a36Sopenharmony_ci	bsr.l		_imem_read_long		# fetch opword & extword
42962306a36Sopenharmony_ci	mov.l		%d0,EXC_OPWORD(%a6)	# store extword on stack
43062306a36Sopenharmony_ci
43162306a36Sopenharmony_ci
43262306a36Sopenharmony_ci#########################################################################
43362306a36Sopenharmony_ci# muls.l	0100 1100 00 |<ea>|	0*** 1100 0000 0***		#
43462306a36Sopenharmony_ci# mulu.l	0100 1100 00 |<ea>|	0*** 0100 0000 0***		#
43562306a36Sopenharmony_ci#									#
43662306a36Sopenharmony_ci# divs.l	0100 1100 01 |<ea>|	0*** 1100 0000 0***		#
43762306a36Sopenharmony_ci# divu.l	0100 1100 01 |<ea>|	0*** 0100 0000 0***		#
43862306a36Sopenharmony_ci#									#
43962306a36Sopenharmony_ci# movep.w m2r	0000 ***1 00 001***	| <displacement>  |		#
44062306a36Sopenharmony_ci# movep.l m2r	0000 ***1 01 001***	| <displacement>  |		#
44162306a36Sopenharmony_ci# movep.w r2m	0000 ***1 10 001***	| <displacement>  |		#
44262306a36Sopenharmony_ci# movep.l r2m	0000 ***1 11 001***	| <displacement>  |		#
44362306a36Sopenharmony_ci#									#
44462306a36Sopenharmony_ci# cas.w		0000 1100 11 |<ea>|	0000 000* **00 0***		#
44562306a36Sopenharmony_ci# cas.l		0000 1110 11 |<ea>|	0000 000* **00 0***		#
44662306a36Sopenharmony_ci#									#
44762306a36Sopenharmony_ci# cas2.w	0000 1100 11 111100	**** 000* **00 0***		#
44862306a36Sopenharmony_ci#					**** 000* **00 0***		#
44962306a36Sopenharmony_ci# cas2.l	0000 1110 11 111100	**** 000* **00 0***		#
45062306a36Sopenharmony_ci#					**** 000* **00 0***		#
45162306a36Sopenharmony_ci#									#
45262306a36Sopenharmony_ci# chk2.b	0000 0000 11 |<ea>|	**** 1000 0000 0000		#
45362306a36Sopenharmony_ci# chk2.w	0000 0010 11 |<ea>|	**** 1000 0000 0000		#
45462306a36Sopenharmony_ci# chk2.l	0000 0100 11 |<ea>|	**** 1000 0000 0000		#
45562306a36Sopenharmony_ci#									#
45662306a36Sopenharmony_ci# cmp2.b	0000 0000 11 |<ea>|	**** 0000 0000 0000		#
45762306a36Sopenharmony_ci# cmp2.w	0000 0010 11 |<ea>|	**** 0000 0000 0000		#
45862306a36Sopenharmony_ci# cmp2.l	0000 0100 11 |<ea>|	**** 0000 0000 0000		#
45962306a36Sopenharmony_ci#########################################################################
46062306a36Sopenharmony_ci
46162306a36Sopenharmony_ci#
46262306a36Sopenharmony_ci# using bit 14 of the operation word, separate into 2 groups:
46362306a36Sopenharmony_ci# (group1) mul64, div64
46462306a36Sopenharmony_ci# (group2) movep, chk2, cmp2, cas2, cas
46562306a36Sopenharmony_ci#
46662306a36Sopenharmony_ci	btst		&0x1e,%d0		# group1 or group2
46762306a36Sopenharmony_ci	beq.b		uieh_group2		# go handle group2
46862306a36Sopenharmony_ci
46962306a36Sopenharmony_ci#
47062306a36Sopenharmony_ci# now, w/ group1, make mul64's decode the fastest since it will
47162306a36Sopenharmony_ci# most likely be used the most.
47262306a36Sopenharmony_ci#
47362306a36Sopenharmony_ciuieh_group1:
47462306a36Sopenharmony_ci	btst		&0x16,%d0		# test for div64
47562306a36Sopenharmony_ci	bne.b		uieh_div64		# go handle div64
47662306a36Sopenharmony_ci
47762306a36Sopenharmony_ciuieh_mul64:
47862306a36Sopenharmony_ci# mul64() may use ()+ addressing and may, therefore, alter a7
47962306a36Sopenharmony_ci
48062306a36Sopenharmony_ci	bsr.l		_mul64			# _mul64()
48162306a36Sopenharmony_ci
48262306a36Sopenharmony_ci	btst		&0x5,EXC_ISR(%a6)	# supervisor mode?
48362306a36Sopenharmony_ci	beq.w		uieh_done
48462306a36Sopenharmony_ci	btst		&mia7_bit,SPCOND_FLG(%a6) # was a7 changed?
48562306a36Sopenharmony_ci	beq.w		uieh_done		# no
48662306a36Sopenharmony_ci	btst		&0x7,EXC_ISR(%a6)	# is trace enabled?
48762306a36Sopenharmony_ci	bne.w		uieh_trace_a7		# yes
48862306a36Sopenharmony_ci	bra.w		uieh_a7			# no
48962306a36Sopenharmony_ci
49062306a36Sopenharmony_ciuieh_div64:
49162306a36Sopenharmony_ci# div64() may use ()+ addressing and may, therefore, alter a7.
49262306a36Sopenharmony_ci# div64() may take a divide by zero exception.
49362306a36Sopenharmony_ci
49462306a36Sopenharmony_ci	bsr.l		_div64			# _div64()
49562306a36Sopenharmony_ci
49662306a36Sopenharmony_ci# here, we sort out all of the special cases that may have happened.
49762306a36Sopenharmony_ci	btst		&mia7_bit,SPCOND_FLG(%a6) # was a7 changed?
49862306a36Sopenharmony_ci	bne.b		uieh_div64_a7		# yes
49962306a36Sopenharmony_ciuieh_div64_dbyz:
50062306a36Sopenharmony_ci	btst		&idbyz_bit,SPCOND_FLG(%a6) # did divide-by-zero occur?
50162306a36Sopenharmony_ci	bne.w		uieh_divbyzero		# yes
50262306a36Sopenharmony_ci	bra.w		uieh_done		# no
50362306a36Sopenharmony_ciuieh_div64_a7:
50462306a36Sopenharmony_ci	btst		&0x5,EXC_ISR(%a6)	# supervisor mode?
50562306a36Sopenharmony_ci	beq.b		uieh_div64_dbyz		# no
50662306a36Sopenharmony_ci# here, a7 has been incremented by 4 bytes in supervisor mode. we still
50762306a36Sopenharmony_ci# may have the following 3 cases:
50862306a36Sopenharmony_ci#	(i)	(a7)+
50962306a36Sopenharmony_ci#	(ii)	(a7)+; trace
51062306a36Sopenharmony_ci#	(iii)	(a7)+; divide-by-zero
51162306a36Sopenharmony_ci#
51262306a36Sopenharmony_ci	btst		&idbyz_bit,SPCOND_FLG(%a6) # did divide-by-zero occur?
51362306a36Sopenharmony_ci	bne.w		uieh_divbyzero_a7	# yes
51462306a36Sopenharmony_ci	tst.b		EXC_ISR(%a6)		# no; is trace enabled?
51562306a36Sopenharmony_ci	bmi.w		uieh_trace_a7		# yes
51662306a36Sopenharmony_ci	bra.w		uieh_a7			# no
51762306a36Sopenharmony_ci
51862306a36Sopenharmony_ci#
51962306a36Sopenharmony_ci# now, w/ group2, make movep's decode the fastest since it will
52062306a36Sopenharmony_ci# most likely be used the most.
52162306a36Sopenharmony_ci#
52262306a36Sopenharmony_ciuieh_group2:
52362306a36Sopenharmony_ci	btst		&0x18,%d0		# test for not movep
52462306a36Sopenharmony_ci	beq.b		uieh_not_movep
52562306a36Sopenharmony_ci
52662306a36Sopenharmony_ci
52762306a36Sopenharmony_ci	bsr.l		_moveperipheral		# _movep()
52862306a36Sopenharmony_ci	bra.w		uieh_done
52962306a36Sopenharmony_ci
53062306a36Sopenharmony_ciuieh_not_movep:
53162306a36Sopenharmony_ci	btst		&0x1b,%d0		# test for chk2,cmp2
53262306a36Sopenharmony_ci	beq.b		uieh_chk2cmp2		# go handle chk2,cmp2
53362306a36Sopenharmony_ci
53462306a36Sopenharmony_ci	swap		%d0			# put opword in lo word
53562306a36Sopenharmony_ci	cmpi.b		%d0,&0xfc		# test for cas2
53662306a36Sopenharmony_ci	beq.b		uieh_cas2		# go handle cas2
53762306a36Sopenharmony_ci
53862306a36Sopenharmony_ciuieh_cas:
53962306a36Sopenharmony_ci
54062306a36Sopenharmony_ci	bsr.l		_compandset		# _cas()
54162306a36Sopenharmony_ci
54262306a36Sopenharmony_ci# the cases of "cas Dc,Du,(a7)+" and "cas Dc,Du,-(a7)" used from supervisor
54362306a36Sopenharmony_ci# mode are simply not considered valid and therefore are not handled.
54462306a36Sopenharmony_ci
54562306a36Sopenharmony_ci	bra.w		uieh_done
54662306a36Sopenharmony_ci
54762306a36Sopenharmony_ciuieh_cas2:
54862306a36Sopenharmony_ci
54962306a36Sopenharmony_ci	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
55062306a36Sopenharmony_ci	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
55162306a36Sopenharmony_ci	bsr.l		_imem_read_word		# read extension word
55262306a36Sopenharmony_ci
55362306a36Sopenharmony_ci	tst.l		%d1			# ifetch error?
55462306a36Sopenharmony_ci	bne.w		isp_iacc		# yes
55562306a36Sopenharmony_ci
55662306a36Sopenharmony_ci	bsr.l		_compandset2		# _cas2()
55762306a36Sopenharmony_ci	bra.w		uieh_done
55862306a36Sopenharmony_ci
55962306a36Sopenharmony_ciuieh_chk2cmp2:
56062306a36Sopenharmony_ci# chk2 may take a chk exception
56162306a36Sopenharmony_ci
56262306a36Sopenharmony_ci	bsr.l		_chk2_cmp2		# _chk2_cmp2()
56362306a36Sopenharmony_ci
56462306a36Sopenharmony_ci# here we check to see if a chk trap should be taken
56562306a36Sopenharmony_ci	cmpi.b		SPCOND_FLG(%a6),&ichk_flg
56662306a36Sopenharmony_ci	bne.w		uieh_done
56762306a36Sopenharmony_ci	bra.b		uieh_chk_trap
56862306a36Sopenharmony_ci
56962306a36Sopenharmony_ci###########################################################################
57062306a36Sopenharmony_ci
57162306a36Sopenharmony_ci#
57262306a36Sopenharmony_ci# the required emulation has been completed. now, clean up the necessary stack
57362306a36Sopenharmony_ci# info and prepare for rte
57462306a36Sopenharmony_ci#
57562306a36Sopenharmony_ciuieh_done:
57662306a36Sopenharmony_ci	mov.b		EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes
57762306a36Sopenharmony_ci
57862306a36Sopenharmony_ci# if exception occurred in user mode, then we have to restore a7 in case it
57962306a36Sopenharmony_ci# changed. we don't have to update a7  for supervisor mose because that case
58062306a36Sopenharmony_ci# doesn't flow through here
58162306a36Sopenharmony_ci	btst		&0x5,EXC_ISR(%a6)	# user or supervisor?
58262306a36Sopenharmony_ci	bne.b		uieh_finish		# supervisor
58362306a36Sopenharmony_ci
58462306a36Sopenharmony_ci	mov.l		EXC_A7(%a6),%a0		# fetch user stack pointer
58562306a36Sopenharmony_ci	mov.l		%a0,%usp		# restore it
58662306a36Sopenharmony_ci
58762306a36Sopenharmony_ciuieh_finish:
58862306a36Sopenharmony_ci	movm.l		EXC_DREGS(%a6),&0x3fff	# restore d0-d7/a0-a5
58962306a36Sopenharmony_ci
59062306a36Sopenharmony_ci	btst		&0x7,EXC_ISR(%a6)	# is trace mode on?
59162306a36Sopenharmony_ci	bne.b		uieh_trace		# yes;go handle trace mode
59262306a36Sopenharmony_ci
59362306a36Sopenharmony_ci	mov.l		EXC_EXTWPTR(%a6),EXC_IPC(%a6) # new pc on stack frame
59462306a36Sopenharmony_ci	mov.l		EXC_A6(%a6),(%a6)	# prepare new a6 for unlink
59562306a36Sopenharmony_ci	unlk		%a6			# unlink stack frame
59662306a36Sopenharmony_ci	bra.l		_isp_done
59762306a36Sopenharmony_ci
59862306a36Sopenharmony_ci#
59962306a36Sopenharmony_ci# The instruction that was just emulated was also being traced. The trace
60062306a36Sopenharmony_ci# trap for this instruction will be lost unless we jump to the trace handler.
60162306a36Sopenharmony_ci# So, here we create a Trace Exception format number two exception stack
60262306a36Sopenharmony_ci# frame from the Unimplemented Integer Intruction Exception stack frame
60362306a36Sopenharmony_ci# format number zero and jump to the user supplied hook "_real_trace()".
60462306a36Sopenharmony_ci#
60562306a36Sopenharmony_ci#		   UIEH FRAME		   TRACE FRAME
60662306a36Sopenharmony_ci#		*****************	*****************
60762306a36Sopenharmony_ci#		* 0x0 *  0x0f4	*	*    Current	*
60862306a36Sopenharmony_ci#		*****************	*      PC	*
60962306a36Sopenharmony_ci#		*    Current	*	*****************
61062306a36Sopenharmony_ci#		*      PC	*	* 0x2 *  0x024	*
61162306a36Sopenharmony_ci#		*****************	*****************
61262306a36Sopenharmony_ci#		*      SR	*	*     Next	*
61362306a36Sopenharmony_ci#		*****************	*      PC	*
61462306a36Sopenharmony_ci#	      ->*     Old	*	*****************
61562306a36Sopenharmony_ci#  from link -->*      A6	*	*      SR	*
61662306a36Sopenharmony_ci#	        *****************	*****************
61762306a36Sopenharmony_ci#	       /*      A7	*	*      New	* <-- for final unlink
61862306a36Sopenharmony_ci#	      / *		*	*      A6	*
61962306a36Sopenharmony_ci# link frame <  *****************	*****************
62062306a36Sopenharmony_ci#	      \ ~		~	~		~
62162306a36Sopenharmony_ci#	       \*****************	*****************
62262306a36Sopenharmony_ci#
62362306a36Sopenharmony_ciuieh_trace:
62462306a36Sopenharmony_ci	mov.l		EXC_A6(%a6),-0x4(%a6)
62562306a36Sopenharmony_ci	mov.w		EXC_ISR(%a6),0x0(%a6)
62662306a36Sopenharmony_ci	mov.l		EXC_IPC(%a6),0x8(%a6)
62762306a36Sopenharmony_ci	mov.l		EXC_EXTWPTR(%a6),0x2(%a6)
62862306a36Sopenharmony_ci	mov.w		&0x2024,0x6(%a6)
62962306a36Sopenharmony_ci	sub.l		&0x4,%a6
63062306a36Sopenharmony_ci	unlk		%a6
63162306a36Sopenharmony_ci	bra.l		_real_trace
63262306a36Sopenharmony_ci
63362306a36Sopenharmony_ci#
63462306a36Sopenharmony_ci#	   UIEH FRAME		    CHK FRAME
63562306a36Sopenharmony_ci#	*****************	*****************
63662306a36Sopenharmony_ci#	* 0x0 *  0x0f4	*	*    Current	*
63762306a36Sopenharmony_ci#	*****************	*      PC	*
63862306a36Sopenharmony_ci#	*    Current	*	*****************
63962306a36Sopenharmony_ci#	*      PC	*	* 0x2 *  0x018	*
64062306a36Sopenharmony_ci#	*****************	*****************
64162306a36Sopenharmony_ci#	*      SR	*	*     Next	*
64262306a36Sopenharmony_ci#	*****************	*      PC	*
64362306a36Sopenharmony_ci#	    (4 words)		*****************
64462306a36Sopenharmony_ci#				*      SR	*
64562306a36Sopenharmony_ci#				*****************
64662306a36Sopenharmony_ci#				    (6 words)
64762306a36Sopenharmony_ci#
64862306a36Sopenharmony_ci# the chk2 instruction should take a chk trap. so, here we must create a
64962306a36Sopenharmony_ci# chk stack frame from an unimplemented integer instruction exception frame
65062306a36Sopenharmony_ci# and jump to the user supplied entry point "_real_chk()".
65162306a36Sopenharmony_ci#
65262306a36Sopenharmony_ciuieh_chk_trap:
65362306a36Sopenharmony_ci	mov.b		EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes
65462306a36Sopenharmony_ci	movm.l		EXC_DREGS(%a6),&0x3fff	# restore d0-d7/a0-a5
65562306a36Sopenharmony_ci
65662306a36Sopenharmony_ci	mov.w		EXC_ISR(%a6),(%a6)	# put new SR on stack
65762306a36Sopenharmony_ci	mov.l		EXC_IPC(%a6),0x8(%a6)	# put "Current PC" on stack
65862306a36Sopenharmony_ci	mov.l		EXC_EXTWPTR(%a6),0x2(%a6) # put "Next PC" on stack
65962306a36Sopenharmony_ci	mov.w		&0x2018,0x6(%a6)	# put Vector Offset on stack
66062306a36Sopenharmony_ci
66162306a36Sopenharmony_ci	mov.l		EXC_A6(%a6),%a6		# restore a6
66262306a36Sopenharmony_ci	add.l		&LOCAL_SIZE,%sp		# clear stack frame
66362306a36Sopenharmony_ci
66462306a36Sopenharmony_ci	bra.l		_real_chk
66562306a36Sopenharmony_ci
66662306a36Sopenharmony_ci#
66762306a36Sopenharmony_ci#	   UIEH FRAME		 DIVBYZERO FRAME
66862306a36Sopenharmony_ci#	*****************	*****************
66962306a36Sopenharmony_ci#	* 0x0 *  0x0f4	*	*    Current	*
67062306a36Sopenharmony_ci#	*****************	*      PC	*
67162306a36Sopenharmony_ci#	*    Current	*	*****************
67262306a36Sopenharmony_ci#	*      PC	*	* 0x2 *  0x014	*
67362306a36Sopenharmony_ci#	*****************	*****************
67462306a36Sopenharmony_ci#	*      SR	*	*     Next	*
67562306a36Sopenharmony_ci#	*****************	*      PC	*
67662306a36Sopenharmony_ci#	    (4 words)		*****************
67762306a36Sopenharmony_ci#				*      SR	*
67862306a36Sopenharmony_ci#				*****************
67962306a36Sopenharmony_ci#				    (6 words)
68062306a36Sopenharmony_ci#
68162306a36Sopenharmony_ci# the divide instruction should take an integer divide by zero trap. so, here
68262306a36Sopenharmony_ci# we must create a divbyzero stack frame from an unimplemented integer
68362306a36Sopenharmony_ci# instruction exception frame and jump to the user supplied entry point
68462306a36Sopenharmony_ci# "_real_divbyzero()".
68562306a36Sopenharmony_ci#
68662306a36Sopenharmony_ciuieh_divbyzero:
68762306a36Sopenharmony_ci	mov.b		EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes
68862306a36Sopenharmony_ci	movm.l		EXC_DREGS(%a6),&0x3fff	# restore d0-d7/a0-a5
68962306a36Sopenharmony_ci
69062306a36Sopenharmony_ci	mov.w		EXC_ISR(%a6),(%a6)	# put new SR on stack
69162306a36Sopenharmony_ci	mov.l		EXC_IPC(%a6),0x8(%a6)	# put "Current PC" on stack
69262306a36Sopenharmony_ci	mov.l		EXC_EXTWPTR(%a6),0x2(%a6) # put "Next PC" on stack
69362306a36Sopenharmony_ci	mov.w		&0x2014,0x6(%a6)	# put Vector Offset on stack
69462306a36Sopenharmony_ci
69562306a36Sopenharmony_ci	mov.l		EXC_A6(%a6),%a6		# restore a6
69662306a36Sopenharmony_ci	add.l		&LOCAL_SIZE,%sp		# clear stack frame
69762306a36Sopenharmony_ci
69862306a36Sopenharmony_ci	bra.l		_real_divbyzero
69962306a36Sopenharmony_ci
70062306a36Sopenharmony_ci#
70162306a36Sopenharmony_ci#				 DIVBYZERO FRAME
70262306a36Sopenharmony_ci#				*****************
70362306a36Sopenharmony_ci#				*    Current	*
70462306a36Sopenharmony_ci#	   UIEH FRAME		*      PC	*
70562306a36Sopenharmony_ci#	*****************	*****************
70662306a36Sopenharmony_ci#	* 0x0 *  0x0f4	*	* 0x2 * 0x014	*
70762306a36Sopenharmony_ci#	*****************	*****************
70862306a36Sopenharmony_ci#	*    Current	*	*     Next	*
70962306a36Sopenharmony_ci#	*      PC	*	*      PC	*
71062306a36Sopenharmony_ci#	*****************	*****************
71162306a36Sopenharmony_ci#	*      SR	*	*      SR	*
71262306a36Sopenharmony_ci#	*****************	*****************
71362306a36Sopenharmony_ci#	    (4 words)		    (6 words)
71462306a36Sopenharmony_ci#
71562306a36Sopenharmony_ci# the divide instruction should take an integer divide by zero trap. so, here
71662306a36Sopenharmony_ci# we must create a divbyzero stack frame from an unimplemented integer
71762306a36Sopenharmony_ci# instruction exception frame and jump to the user supplied entry point
71862306a36Sopenharmony_ci# "_real_divbyzero()".
71962306a36Sopenharmony_ci#
72062306a36Sopenharmony_ci# However, we must also deal with the fact that (a7)+ was used from supervisor
72162306a36Sopenharmony_ci# mode, thereby shifting the stack frame up 4 bytes.
72262306a36Sopenharmony_ci#
72362306a36Sopenharmony_ciuieh_divbyzero_a7:
72462306a36Sopenharmony_ci	mov.b		EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes
72562306a36Sopenharmony_ci	movm.l		EXC_DREGS(%a6),&0x3fff	# restore d0-d7/a0-a5
72662306a36Sopenharmony_ci
72762306a36Sopenharmony_ci	mov.l		EXC_IPC(%a6),0xc(%a6)	# put "Current PC" on stack
72862306a36Sopenharmony_ci	mov.w		&0x2014,0xa(%a6)	# put Vector Offset on stack
72962306a36Sopenharmony_ci	mov.l		EXC_EXTWPTR(%a6),0x6(%a6) # put "Next PC" on stack
73062306a36Sopenharmony_ci
73162306a36Sopenharmony_ci	mov.l		EXC_A6(%a6),%a6		# restore a6
73262306a36Sopenharmony_ci	add.l		&4+LOCAL_SIZE,%sp	# clear stack frame
73362306a36Sopenharmony_ci
73462306a36Sopenharmony_ci	bra.l		_real_divbyzero
73562306a36Sopenharmony_ci
73662306a36Sopenharmony_ci#
73762306a36Sopenharmony_ci#				   TRACE FRAME
73862306a36Sopenharmony_ci#				*****************
73962306a36Sopenharmony_ci#				*    Current	*
74062306a36Sopenharmony_ci#	   UIEH FRAME		*      PC	*
74162306a36Sopenharmony_ci#	*****************	*****************
74262306a36Sopenharmony_ci#	* 0x0 *  0x0f4	*	* 0x2 * 0x024	*
74362306a36Sopenharmony_ci#	*****************	*****************
74462306a36Sopenharmony_ci#	*    Current	*	*     Next	*
74562306a36Sopenharmony_ci#	*      PC	*	*      PC	*
74662306a36Sopenharmony_ci#	*****************	*****************
74762306a36Sopenharmony_ci#	*      SR	*	*      SR	*
74862306a36Sopenharmony_ci#	*****************	*****************
74962306a36Sopenharmony_ci#	    (4 words)		    (6 words)
75062306a36Sopenharmony_ci#
75162306a36Sopenharmony_ci#
75262306a36Sopenharmony_ci# The instruction that was just emulated was also being traced. The trace
75362306a36Sopenharmony_ci# trap for this instruction will be lost unless we jump to the trace handler.
75462306a36Sopenharmony_ci# So, here we create a Trace Exception format number two exception stack
75562306a36Sopenharmony_ci# frame from the Unimplemented Integer Intruction Exception stack frame
75662306a36Sopenharmony_ci# format number zero and jump to the user supplied hook "_real_trace()".
75762306a36Sopenharmony_ci#
75862306a36Sopenharmony_ci# However, we must also deal with the fact that (a7)+ was used from supervisor
75962306a36Sopenharmony_ci# mode, thereby shifting the stack frame up 4 bytes.
76062306a36Sopenharmony_ci#
76162306a36Sopenharmony_ciuieh_trace_a7:
76262306a36Sopenharmony_ci	mov.b		EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes
76362306a36Sopenharmony_ci	movm.l		EXC_DREGS(%a6),&0x3fff	# restore d0-d7/a0-a5
76462306a36Sopenharmony_ci
76562306a36Sopenharmony_ci	mov.l		EXC_IPC(%a6),0xc(%a6)	# put "Current PC" on stack
76662306a36Sopenharmony_ci	mov.w		&0x2024,0xa(%a6)	# put Vector Offset on stack
76762306a36Sopenharmony_ci	mov.l		EXC_EXTWPTR(%a6),0x6(%a6) # put "Next PC" on stack
76862306a36Sopenharmony_ci
76962306a36Sopenharmony_ci	mov.l		EXC_A6(%a6),%a6		# restore a6
77062306a36Sopenharmony_ci	add.l		&4+LOCAL_SIZE,%sp	# clear stack frame
77162306a36Sopenharmony_ci
77262306a36Sopenharmony_ci	bra.l		_real_trace
77362306a36Sopenharmony_ci
77462306a36Sopenharmony_ci#
77562306a36Sopenharmony_ci#				   UIEH FRAME
77662306a36Sopenharmony_ci#				*****************
77762306a36Sopenharmony_ci#				* 0x0 * 0x0f4	*
77862306a36Sopenharmony_ci#	   UIEH FRAME		*****************
77962306a36Sopenharmony_ci#	*****************	*     Next	*
78062306a36Sopenharmony_ci#	* 0x0 *  0x0f4	*	*      PC	*
78162306a36Sopenharmony_ci#	*****************	*****************
78262306a36Sopenharmony_ci#	*    Current	*	*      SR	*
78362306a36Sopenharmony_ci#	*      PC	*	*****************
78462306a36Sopenharmony_ci#	*****************	    (4 words)
78562306a36Sopenharmony_ci#	*      SR	*
78662306a36Sopenharmony_ci#	*****************
78762306a36Sopenharmony_ci#	    (4 words)
78862306a36Sopenharmony_ciuieh_a7:
78962306a36Sopenharmony_ci	mov.b		EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes
79062306a36Sopenharmony_ci	movm.l		EXC_DREGS(%a6),&0x3fff	# restore d0-d7/a0-a5
79162306a36Sopenharmony_ci
79262306a36Sopenharmony_ci	mov.w		&0x00f4,0xe(%a6)	# put Vector Offset on stack
79362306a36Sopenharmony_ci	mov.l		EXC_EXTWPTR(%a6),0xa(%a6) # put "Next PC" on stack
79462306a36Sopenharmony_ci	mov.w		EXC_ISR(%a6),0x8(%a6)	# put SR on stack
79562306a36Sopenharmony_ci
79662306a36Sopenharmony_ci	mov.l		EXC_A6(%a6),%a6		# restore a6
79762306a36Sopenharmony_ci	add.l		&8+LOCAL_SIZE,%sp	# clear stack frame
79862306a36Sopenharmony_ci	bra.l		_isp_done
79962306a36Sopenharmony_ci
80062306a36Sopenharmony_ci##########
80162306a36Sopenharmony_ci
80262306a36Sopenharmony_ci# this is the exit point if a data read or write fails.
80362306a36Sopenharmony_ci# a0 = failing address
80462306a36Sopenharmony_ci# d0 = fslw
80562306a36Sopenharmony_ciisp_dacc:
80662306a36Sopenharmony_ci	mov.l		%a0,(%a6)		# save address
80762306a36Sopenharmony_ci	mov.l		%d0,-0x4(%a6)		# save partial fslw
80862306a36Sopenharmony_ci
80962306a36Sopenharmony_ci	lea		-64(%a6),%sp
81062306a36Sopenharmony_ci	movm.l		(%sp)+,&0x7fff		# restore d0-d7/a0-a6
81162306a36Sopenharmony_ci
81262306a36Sopenharmony_ci	mov.l		0xc(%sp),-(%sp)		# move voff,hi(pc)
81362306a36Sopenharmony_ci	mov.l		0x4(%sp),0x10(%sp)	# store fslw
81462306a36Sopenharmony_ci	mov.l		0xc(%sp),0x4(%sp)	# store sr,lo(pc)
81562306a36Sopenharmony_ci	mov.l		0x8(%sp),0xc(%sp)	# store address
81662306a36Sopenharmony_ci	mov.l		(%sp)+,0x4(%sp)		# store voff,hi(pc)
81762306a36Sopenharmony_ci	mov.w		&0x4008,0x6(%sp)	# store new voff
81862306a36Sopenharmony_ci
81962306a36Sopenharmony_ci	bra.b		isp_acc_exit
82062306a36Sopenharmony_ci
82162306a36Sopenharmony_ci# this is the exit point if an instruction word read fails.
82262306a36Sopenharmony_ci# FSLW:
82362306a36Sopenharmony_ci#	misaligned = true
82462306a36Sopenharmony_ci#	read = true
82562306a36Sopenharmony_ci#	size = word
82662306a36Sopenharmony_ci#	instruction = true
82762306a36Sopenharmony_ci#	software emulation error = true
82862306a36Sopenharmony_ciisp_iacc:
82962306a36Sopenharmony_ci	movm.l		EXC_DREGS(%a6),&0x3fff	# restore d0-d7/a0-a5
83062306a36Sopenharmony_ci	unlk		%a6			# unlink frame
83162306a36Sopenharmony_ci	sub.w		&0x8,%sp		# make room for acc frame
83262306a36Sopenharmony_ci	mov.l		0x8(%sp),(%sp)		# store sr,lo(pc)
83362306a36Sopenharmony_ci	mov.w		0xc(%sp),0x4(%sp)	# store hi(pc)
83462306a36Sopenharmony_ci	mov.w		&0x4008,0x6(%sp)	# store new voff
83562306a36Sopenharmony_ci	mov.l		0x2(%sp),0x8(%sp)	# store address (=pc)
83662306a36Sopenharmony_ci	mov.l		&0x09428001,0xc(%sp)	# store fslw
83762306a36Sopenharmony_ci
83862306a36Sopenharmony_ciisp_acc_exit:
83962306a36Sopenharmony_ci	btst		&0x5,(%sp)		# user or supervisor?
84062306a36Sopenharmony_ci	beq.b		isp_acc_exit2		# user
84162306a36Sopenharmony_ci	bset		&0x2,0xd(%sp)		# set supervisor TM bit
84262306a36Sopenharmony_ciisp_acc_exit2:
84362306a36Sopenharmony_ci	bra.l		_real_access
84462306a36Sopenharmony_ci
84562306a36Sopenharmony_ci# if the addressing mode was (an)+ or -(an), the address register must
84662306a36Sopenharmony_ci# be restored to its pre-exception value before entering _real_access.
84762306a36Sopenharmony_ciisp_restore:
84862306a36Sopenharmony_ci	cmpi.b		SPCOND_FLG(%a6),&restore_flg # do we need a restore?
84962306a36Sopenharmony_ci	bne.b		isp_restore_done	# no
85062306a36Sopenharmony_ci	clr.l		%d0
85162306a36Sopenharmony_ci	mov.b		EXC_SAVREG(%a6),%d0	# regno to restore
85262306a36Sopenharmony_ci	mov.l		EXC_SAVVAL(%a6),(EXC_AREGS,%a6,%d0.l*4) # restore value
85362306a36Sopenharmony_ciisp_restore_done:
85462306a36Sopenharmony_ci	rts
85562306a36Sopenharmony_ci
85662306a36Sopenharmony_ci#########################################################################
85762306a36Sopenharmony_ci# XDEF ****************************************************************	#
85862306a36Sopenharmony_ci#	_calc_ea(): routine to calculate effective address		#
85962306a36Sopenharmony_ci#									#
86062306a36Sopenharmony_ci# XREF ****************************************************************	#
86162306a36Sopenharmony_ci#	_imem_read_word() - read instruction word			#
86262306a36Sopenharmony_ci#	_imem_read_long() - read instruction longword			#
86362306a36Sopenharmony_ci#	_dmem_read_long() - read data longword (for memory indirect)	#
86462306a36Sopenharmony_ci#	isp_iacc() - handle instruction access error exception		#
86562306a36Sopenharmony_ci#	isp_dacc() - handle data access error exception			#
86662306a36Sopenharmony_ci#									#
86762306a36Sopenharmony_ci# INPUT ***************************************************************	#
86862306a36Sopenharmony_ci#	d0 = number of bytes related to effective address (w,l)		#
86962306a36Sopenharmony_ci#									#
87062306a36Sopenharmony_ci# OUTPUT **************************************************************	#
87162306a36Sopenharmony_ci#	If exiting through isp_dacc...					#
87262306a36Sopenharmony_ci#		a0 = failing address					#
87362306a36Sopenharmony_ci#		d0 = FSLW						#
87462306a36Sopenharmony_ci#	elsif exiting though isp_iacc...				#
87562306a36Sopenharmony_ci#		none							#
87662306a36Sopenharmony_ci#	else								#
87762306a36Sopenharmony_ci#		a0 = effective address					#
87862306a36Sopenharmony_ci#									#
87962306a36Sopenharmony_ci# ALGORITHM ***********************************************************	#
88062306a36Sopenharmony_ci#	The effective address type is decoded from the opword residing	#
88162306a36Sopenharmony_ci# on the stack. A jump table is used to vector to a routine for the	#
88262306a36Sopenharmony_ci# appropriate mode. Since none of the emulated integer instructions	#
88362306a36Sopenharmony_ci# uses byte-sized operands, only handle word and long operations.	#
88462306a36Sopenharmony_ci#									#
88562306a36Sopenharmony_ci#	Dn,An	- shouldn't enter here					#
88662306a36Sopenharmony_ci#	(An)	- fetch An value from stack				#
88762306a36Sopenharmony_ci#	-(An)	- fetch An value from stack; return decr value;		#
88862306a36Sopenharmony_ci#		  place decr value on stack; store old value in case of	#
88962306a36Sopenharmony_ci#		  future access error; if -(a7), set mda7_flg in	#
89062306a36Sopenharmony_ci#		  SPCOND_FLG						#
89162306a36Sopenharmony_ci#	(An)+	- fetch An value from stack; return value;		#
89262306a36Sopenharmony_ci#		  place incr value on stack; store old value in case of	#
89362306a36Sopenharmony_ci#		  future access error; if (a7)+, set mia7_flg in	#
89462306a36Sopenharmony_ci#		  SPCOND_FLG						#
89562306a36Sopenharmony_ci#	(d16,An) - fetch An value from stack; read d16 using		#
89662306a36Sopenharmony_ci#		  _imem_read_word(); fetch may fail -> branch to	#
89762306a36Sopenharmony_ci#		  isp_iacc()						#
89862306a36Sopenharmony_ci#	(xxx).w,(xxx).l - use _imem_read_{word,long}() to fetch		#
89962306a36Sopenharmony_ci#		  address; fetch may fail				#
90062306a36Sopenharmony_ci#	#<data> - return address of immediate value; set immed_flg	#
90162306a36Sopenharmony_ci#		  in SPCOND_FLG						#
90262306a36Sopenharmony_ci#	(d16,PC) - fetch stacked PC value; read d16 using		#
90362306a36Sopenharmony_ci#		  _imem_read_word(); fetch may fail -> branch to	#
90462306a36Sopenharmony_ci#		  isp_iacc()						#
90562306a36Sopenharmony_ci#	everything else - read needed displacements as appropriate w/	#
90662306a36Sopenharmony_ci#		  _imem_read_{word,long}(); read may fail; if memory	#
90762306a36Sopenharmony_ci#		  indirect, read indirect address using			#
90862306a36Sopenharmony_ci#		  _dmem_read_long() which may also fail			#
90962306a36Sopenharmony_ci#									#
91062306a36Sopenharmony_ci#########################################################################
91162306a36Sopenharmony_ci
91262306a36Sopenharmony_ci	global		_calc_ea
91362306a36Sopenharmony_ci_calc_ea:
91462306a36Sopenharmony_ci	mov.l		%d0,%a0			# move # bytes to a0
91562306a36Sopenharmony_ci
91662306a36Sopenharmony_ci# MODE and REG are taken from the EXC_OPWORD.
91762306a36Sopenharmony_ci	mov.w		EXC_OPWORD(%a6),%d0	# fetch opcode word
91862306a36Sopenharmony_ci	mov.w		%d0,%d1			# make a copy
91962306a36Sopenharmony_ci
92062306a36Sopenharmony_ci	andi.w		&0x3f,%d0		# extract mode field
92162306a36Sopenharmony_ci	andi.l		&0x7,%d1		# extract reg  field
92262306a36Sopenharmony_ci
92362306a36Sopenharmony_ci# jump to the corresponding function for each {MODE,REG} pair.
92462306a36Sopenharmony_ci	mov.w		(tbl_ea_mode.b,%pc,%d0.w*2), %d0 # fetch jmp distance
92562306a36Sopenharmony_ci	jmp		(tbl_ea_mode.b,%pc,%d0.w*1) # jmp to correct ea mode
92662306a36Sopenharmony_ci
92762306a36Sopenharmony_ci	swbeg		&64
92862306a36Sopenharmony_citbl_ea_mode:
92962306a36Sopenharmony_ci	short		tbl_ea_mode	-	tbl_ea_mode
93062306a36Sopenharmony_ci	short		tbl_ea_mode	-	tbl_ea_mode
93162306a36Sopenharmony_ci	short		tbl_ea_mode	-	tbl_ea_mode
93262306a36Sopenharmony_ci	short		tbl_ea_mode	-	tbl_ea_mode
93362306a36Sopenharmony_ci	short		tbl_ea_mode	-	tbl_ea_mode
93462306a36Sopenharmony_ci	short		tbl_ea_mode	-	tbl_ea_mode
93562306a36Sopenharmony_ci	short		tbl_ea_mode	-	tbl_ea_mode
93662306a36Sopenharmony_ci	short		tbl_ea_mode	-	tbl_ea_mode
93762306a36Sopenharmony_ci
93862306a36Sopenharmony_ci	short		tbl_ea_mode	-	tbl_ea_mode
93962306a36Sopenharmony_ci	short		tbl_ea_mode	-	tbl_ea_mode
94062306a36Sopenharmony_ci	short		tbl_ea_mode	-	tbl_ea_mode
94162306a36Sopenharmony_ci	short		tbl_ea_mode	-	tbl_ea_mode
94262306a36Sopenharmony_ci	short		tbl_ea_mode	-	tbl_ea_mode
94362306a36Sopenharmony_ci	short		tbl_ea_mode	-	tbl_ea_mode
94462306a36Sopenharmony_ci	short		tbl_ea_mode	-	tbl_ea_mode
94562306a36Sopenharmony_ci	short		tbl_ea_mode	-	tbl_ea_mode
94662306a36Sopenharmony_ci
94762306a36Sopenharmony_ci	short		addr_ind_a0	-	tbl_ea_mode
94862306a36Sopenharmony_ci	short		addr_ind_a1	-	tbl_ea_mode
94962306a36Sopenharmony_ci	short		addr_ind_a2	-	tbl_ea_mode
95062306a36Sopenharmony_ci	short		addr_ind_a3	-	tbl_ea_mode
95162306a36Sopenharmony_ci	short		addr_ind_a4	-	tbl_ea_mode
95262306a36Sopenharmony_ci	short		addr_ind_a5	-	tbl_ea_mode
95362306a36Sopenharmony_ci	short		addr_ind_a6	-	tbl_ea_mode
95462306a36Sopenharmony_ci	short		addr_ind_a7	-	tbl_ea_mode
95562306a36Sopenharmony_ci
95662306a36Sopenharmony_ci	short		addr_ind_p_a0	-	tbl_ea_mode
95762306a36Sopenharmony_ci	short		addr_ind_p_a1	-	tbl_ea_mode
95862306a36Sopenharmony_ci	short		addr_ind_p_a2	-	tbl_ea_mode
95962306a36Sopenharmony_ci	short		addr_ind_p_a3	-	tbl_ea_mode
96062306a36Sopenharmony_ci	short		addr_ind_p_a4	-	tbl_ea_mode
96162306a36Sopenharmony_ci	short		addr_ind_p_a5	-	tbl_ea_mode
96262306a36Sopenharmony_ci	short		addr_ind_p_a6	-	tbl_ea_mode
96362306a36Sopenharmony_ci	short		addr_ind_p_a7	-	tbl_ea_mode
96462306a36Sopenharmony_ci
96562306a36Sopenharmony_ci	short		addr_ind_m_a0		-	tbl_ea_mode
96662306a36Sopenharmony_ci	short		addr_ind_m_a1		-	tbl_ea_mode
96762306a36Sopenharmony_ci	short		addr_ind_m_a2		-	tbl_ea_mode
96862306a36Sopenharmony_ci	short		addr_ind_m_a3		-	tbl_ea_mode
96962306a36Sopenharmony_ci	short		addr_ind_m_a4		-	tbl_ea_mode
97062306a36Sopenharmony_ci	short		addr_ind_m_a5		-	tbl_ea_mode
97162306a36Sopenharmony_ci	short		addr_ind_m_a6		-	tbl_ea_mode
97262306a36Sopenharmony_ci	short		addr_ind_m_a7		-	tbl_ea_mode
97362306a36Sopenharmony_ci
97462306a36Sopenharmony_ci	short		addr_ind_disp_a0	-	tbl_ea_mode
97562306a36Sopenharmony_ci	short		addr_ind_disp_a1	-	tbl_ea_mode
97662306a36Sopenharmony_ci	short		addr_ind_disp_a2	-	tbl_ea_mode
97762306a36Sopenharmony_ci	short		addr_ind_disp_a3	-	tbl_ea_mode
97862306a36Sopenharmony_ci	short		addr_ind_disp_a4	-	tbl_ea_mode
97962306a36Sopenharmony_ci	short		addr_ind_disp_a5	-	tbl_ea_mode
98062306a36Sopenharmony_ci	short		addr_ind_disp_a6	-	tbl_ea_mode
98162306a36Sopenharmony_ci	short		addr_ind_disp_a7	-	tbl_ea_mode
98262306a36Sopenharmony_ci
98362306a36Sopenharmony_ci	short		_addr_ind_ext		-	tbl_ea_mode
98462306a36Sopenharmony_ci	short		_addr_ind_ext		-	tbl_ea_mode
98562306a36Sopenharmony_ci	short		_addr_ind_ext		-	tbl_ea_mode
98662306a36Sopenharmony_ci	short		_addr_ind_ext		-	tbl_ea_mode
98762306a36Sopenharmony_ci	short		_addr_ind_ext		-	tbl_ea_mode
98862306a36Sopenharmony_ci	short		_addr_ind_ext		-	tbl_ea_mode
98962306a36Sopenharmony_ci	short		_addr_ind_ext		-	tbl_ea_mode
99062306a36Sopenharmony_ci	short		_addr_ind_ext		-	tbl_ea_mode
99162306a36Sopenharmony_ci
99262306a36Sopenharmony_ci	short		abs_short		-	tbl_ea_mode
99362306a36Sopenharmony_ci	short		abs_long		-	tbl_ea_mode
99462306a36Sopenharmony_ci	short		pc_ind			-	tbl_ea_mode
99562306a36Sopenharmony_ci	short		pc_ind_ext		-	tbl_ea_mode
99662306a36Sopenharmony_ci	short		immediate		-	tbl_ea_mode
99762306a36Sopenharmony_ci	short		tbl_ea_mode		-	tbl_ea_mode
99862306a36Sopenharmony_ci	short		tbl_ea_mode		-	tbl_ea_mode
99962306a36Sopenharmony_ci	short		tbl_ea_mode		-	tbl_ea_mode
100062306a36Sopenharmony_ci
100162306a36Sopenharmony_ci###################################
100262306a36Sopenharmony_ci# Address register indirect: (An) #
100362306a36Sopenharmony_ci###################################
100462306a36Sopenharmony_ciaddr_ind_a0:
100562306a36Sopenharmony_ci	mov.l		EXC_A0(%a6),%a0		# Get current a0
100662306a36Sopenharmony_ci	rts
100762306a36Sopenharmony_ci
100862306a36Sopenharmony_ciaddr_ind_a1:
100962306a36Sopenharmony_ci	mov.l		EXC_A1(%a6),%a0		# Get current a1
101062306a36Sopenharmony_ci	rts
101162306a36Sopenharmony_ci
101262306a36Sopenharmony_ciaddr_ind_a2:
101362306a36Sopenharmony_ci	mov.l		EXC_A2(%a6),%a0		# Get current a2
101462306a36Sopenharmony_ci	rts
101562306a36Sopenharmony_ci
101662306a36Sopenharmony_ciaddr_ind_a3:
101762306a36Sopenharmony_ci	mov.l		EXC_A3(%a6),%a0		# Get current a3
101862306a36Sopenharmony_ci	rts
101962306a36Sopenharmony_ci
102062306a36Sopenharmony_ciaddr_ind_a4:
102162306a36Sopenharmony_ci	mov.l		EXC_A4(%a6),%a0		# Get current a4
102262306a36Sopenharmony_ci	rts
102362306a36Sopenharmony_ci
102462306a36Sopenharmony_ciaddr_ind_a5:
102562306a36Sopenharmony_ci	mov.l		EXC_A5(%a6),%a0		# Get current a5
102662306a36Sopenharmony_ci	rts
102762306a36Sopenharmony_ci
102862306a36Sopenharmony_ciaddr_ind_a6:
102962306a36Sopenharmony_ci	mov.l		EXC_A6(%a6),%a0		# Get current a6
103062306a36Sopenharmony_ci	rts
103162306a36Sopenharmony_ci
103262306a36Sopenharmony_ciaddr_ind_a7:
103362306a36Sopenharmony_ci	mov.l		EXC_A7(%a6),%a0		# Get current a7
103462306a36Sopenharmony_ci	rts
103562306a36Sopenharmony_ci
103662306a36Sopenharmony_ci#####################################################
103762306a36Sopenharmony_ci# Address register indirect w/ postincrement: (An)+ #
103862306a36Sopenharmony_ci#####################################################
103962306a36Sopenharmony_ciaddr_ind_p_a0:
104062306a36Sopenharmony_ci	mov.l		%a0,%d0			# copy no. bytes
104162306a36Sopenharmony_ci	mov.l		EXC_A0(%a6),%a0		# load current value
104262306a36Sopenharmony_ci	add.l		%a0,%d0			# increment
104362306a36Sopenharmony_ci	mov.l		%d0,EXC_A0(%a6)		# save incremented value
104462306a36Sopenharmony_ci
104562306a36Sopenharmony_ci	mov.l		%a0,EXC_SAVVAL(%a6)	# save in case of access error
104662306a36Sopenharmony_ci	mov.b		&0x0,EXC_SAVREG(%a6)	# save regno, too
104762306a36Sopenharmony_ci	mov.b		&restore_flg,SPCOND_FLG(%a6) # set flag
104862306a36Sopenharmony_ci	rts
104962306a36Sopenharmony_ci
105062306a36Sopenharmony_ciaddr_ind_p_a1:
105162306a36Sopenharmony_ci	mov.l		%a0,%d0			# copy no. bytes
105262306a36Sopenharmony_ci	mov.l		EXC_A1(%a6),%a0		# load current value
105362306a36Sopenharmony_ci	add.l		%a0,%d0			# increment
105462306a36Sopenharmony_ci	mov.l		%d0,EXC_A1(%a6)		# save incremented value
105562306a36Sopenharmony_ci
105662306a36Sopenharmony_ci	mov.l		%a0,EXC_SAVVAL(%a6)	# save in case of access error
105762306a36Sopenharmony_ci	mov.b		&0x1,EXC_SAVREG(%a6)	# save regno, too
105862306a36Sopenharmony_ci	mov.b		&restore_flg,SPCOND_FLG(%a6) # set flag
105962306a36Sopenharmony_ci	rts
106062306a36Sopenharmony_ci
106162306a36Sopenharmony_ciaddr_ind_p_a2:
106262306a36Sopenharmony_ci	mov.l		%a0,%d0			# copy no. bytes
106362306a36Sopenharmony_ci	mov.l		EXC_A2(%a6),%a0		# load current value
106462306a36Sopenharmony_ci	add.l		%a0,%d0			# increment
106562306a36Sopenharmony_ci	mov.l		%d0,EXC_A2(%a6)		# save incremented value
106662306a36Sopenharmony_ci
106762306a36Sopenharmony_ci	mov.l		%a0,EXC_SAVVAL(%a6)	# save in case of access error
106862306a36Sopenharmony_ci	mov.b		&0x2,EXC_SAVREG(%a6)	# save regno, too
106962306a36Sopenharmony_ci	mov.b		&restore_flg,SPCOND_FLG(%a6) # set flag
107062306a36Sopenharmony_ci	rts
107162306a36Sopenharmony_ci
107262306a36Sopenharmony_ciaddr_ind_p_a3:
107362306a36Sopenharmony_ci	mov.l		%a0,%d0			# copy no. bytes
107462306a36Sopenharmony_ci	mov.l		EXC_A3(%a6),%a0		# load current value
107562306a36Sopenharmony_ci	add.l		%a0,%d0			# increment
107662306a36Sopenharmony_ci	mov.l		%d0,EXC_A3(%a6)		# save incremented value
107762306a36Sopenharmony_ci
107862306a36Sopenharmony_ci	mov.l		%a0,EXC_SAVVAL(%a6)	# save in case of access error
107962306a36Sopenharmony_ci	mov.b		&0x3,EXC_SAVREG(%a6)	# save regno, too
108062306a36Sopenharmony_ci	mov.b		&restore_flg,SPCOND_FLG(%a6) # set flag
108162306a36Sopenharmony_ci	rts
108262306a36Sopenharmony_ci
108362306a36Sopenharmony_ciaddr_ind_p_a4:
108462306a36Sopenharmony_ci	mov.l		%a0,%d0			# copy no. bytes
108562306a36Sopenharmony_ci	mov.l		EXC_A4(%a6),%a0		# load current value
108662306a36Sopenharmony_ci	add.l		%a0,%d0			# increment
108762306a36Sopenharmony_ci	mov.l		%d0,EXC_A4(%a6)		# save incremented value
108862306a36Sopenharmony_ci
108962306a36Sopenharmony_ci	mov.l		%a0,EXC_SAVVAL(%a6)	# save in case of access error
109062306a36Sopenharmony_ci	mov.b		&0x4,EXC_SAVREG(%a6)	# save regno, too
109162306a36Sopenharmony_ci	mov.b		&restore_flg,SPCOND_FLG(%a6) # set flag
109262306a36Sopenharmony_ci	rts
109362306a36Sopenharmony_ci
109462306a36Sopenharmony_ciaddr_ind_p_a5:
109562306a36Sopenharmony_ci	mov.l		%a0,%d0			# copy no. bytes
109662306a36Sopenharmony_ci	mov.l		EXC_A5(%a6),%a0		# load current value
109762306a36Sopenharmony_ci	add.l		%a0,%d0			# increment
109862306a36Sopenharmony_ci	mov.l		%d0,EXC_A5(%a6)		# save incremented value
109962306a36Sopenharmony_ci
110062306a36Sopenharmony_ci	mov.l		%a0,EXC_SAVVAL(%a6)	# save in case of access error
110162306a36Sopenharmony_ci	mov.b		&0x5,EXC_SAVREG(%a6)	# save regno, too
110262306a36Sopenharmony_ci	mov.b		&restore_flg,SPCOND_FLG(%a6) # set flag
110362306a36Sopenharmony_ci	rts
110462306a36Sopenharmony_ci
110562306a36Sopenharmony_ciaddr_ind_p_a6:
110662306a36Sopenharmony_ci	mov.l		%a0,%d0			# copy no. bytes
110762306a36Sopenharmony_ci	mov.l		EXC_A6(%a6),%a0		# load current value
110862306a36Sopenharmony_ci	add.l		%a0,%d0			# increment
110962306a36Sopenharmony_ci	mov.l		%d0,EXC_A6(%a6)		# save incremented value
111062306a36Sopenharmony_ci
111162306a36Sopenharmony_ci	mov.l		%a0,EXC_SAVVAL(%a6)	# save in case of access error
111262306a36Sopenharmony_ci	mov.b		&0x6,EXC_SAVREG(%a6)	# save regno, too
111362306a36Sopenharmony_ci	mov.b		&restore_flg,SPCOND_FLG(%a6) # set flag
111462306a36Sopenharmony_ci	rts
111562306a36Sopenharmony_ci
111662306a36Sopenharmony_ciaddr_ind_p_a7:
111762306a36Sopenharmony_ci	mov.b		&mia7_flg,SPCOND_FLG(%a6) # set "special case" flag
111862306a36Sopenharmony_ci
111962306a36Sopenharmony_ci	mov.l		%a0,%d0			# copy no. bytes
112062306a36Sopenharmony_ci	mov.l		EXC_A7(%a6),%a0		# load current value
112162306a36Sopenharmony_ci	add.l		%a0,%d0			# increment
112262306a36Sopenharmony_ci	mov.l		%d0,EXC_A7(%a6)		# save incremented value
112362306a36Sopenharmony_ci	rts
112462306a36Sopenharmony_ci
112562306a36Sopenharmony_ci####################################################
112662306a36Sopenharmony_ci# Address register indirect w/ predecrement: -(An) #
112762306a36Sopenharmony_ci####################################################
112862306a36Sopenharmony_ciaddr_ind_m_a0:
112962306a36Sopenharmony_ci	mov.l		EXC_A0(%a6),%d0		# Get current a0
113062306a36Sopenharmony_ci	mov.l		%d0,EXC_SAVVAL(%a6)	# save in case of access error
113162306a36Sopenharmony_ci	sub.l		%a0,%d0			# Decrement
113262306a36Sopenharmony_ci	mov.l		%d0,EXC_A0(%a6)		# Save decr value
113362306a36Sopenharmony_ci	mov.l		%d0,%a0
113462306a36Sopenharmony_ci
113562306a36Sopenharmony_ci	mov.b		&0x0,EXC_SAVREG(%a6)	# save regno, too
113662306a36Sopenharmony_ci	mov.b		&restore_flg,SPCOND_FLG(%a6) # set flag
113762306a36Sopenharmony_ci	rts
113862306a36Sopenharmony_ci
113962306a36Sopenharmony_ciaddr_ind_m_a1:
114062306a36Sopenharmony_ci	mov.l		EXC_A1(%a6),%d0		# Get current a1
114162306a36Sopenharmony_ci	mov.l		%d0,EXC_SAVVAL(%a6)	# save in case of access error
114262306a36Sopenharmony_ci	sub.l		%a0,%d0			# Decrement
114362306a36Sopenharmony_ci	mov.l		%d0,EXC_A1(%a6)		# Save decr value
114462306a36Sopenharmony_ci	mov.l		%d0,%a0
114562306a36Sopenharmony_ci
114662306a36Sopenharmony_ci	mov.b		&0x1,EXC_SAVREG(%a6)	# save regno, too
114762306a36Sopenharmony_ci	mov.b		&restore_flg,SPCOND_FLG(%a6) # set flag
114862306a36Sopenharmony_ci	rts
114962306a36Sopenharmony_ci
115062306a36Sopenharmony_ciaddr_ind_m_a2:
115162306a36Sopenharmony_ci	mov.l		EXC_A2(%a6),%d0		# Get current a2
115262306a36Sopenharmony_ci	mov.l		%d0,EXC_SAVVAL(%a6)	# save in case of access error
115362306a36Sopenharmony_ci	sub.l		%a0,%d0			# Decrement
115462306a36Sopenharmony_ci	mov.l		%d0,EXC_A2(%a6)		# Save decr value
115562306a36Sopenharmony_ci	mov.l		%d0,%a0
115662306a36Sopenharmony_ci
115762306a36Sopenharmony_ci	mov.b		&0x2,EXC_SAVREG(%a6)	# save regno, too
115862306a36Sopenharmony_ci	mov.b		&restore_flg,SPCOND_FLG(%a6) # set flag
115962306a36Sopenharmony_ci	rts
116062306a36Sopenharmony_ci
116162306a36Sopenharmony_ciaddr_ind_m_a3:
116262306a36Sopenharmony_ci	mov.l		EXC_A3(%a6),%d0		# Get current a3
116362306a36Sopenharmony_ci	mov.l		%d0,EXC_SAVVAL(%a6)	# save in case of access error
116462306a36Sopenharmony_ci	sub.l		%a0,%d0			# Decrement
116562306a36Sopenharmony_ci	mov.l		%d0,EXC_A3(%a6)		# Save decr value
116662306a36Sopenharmony_ci	mov.l		%d0,%a0
116762306a36Sopenharmony_ci
116862306a36Sopenharmony_ci	mov.b		&0x3,EXC_SAVREG(%a6)	# save regno, too
116962306a36Sopenharmony_ci	mov.b		&restore_flg,SPCOND_FLG(%a6) # set flag
117062306a36Sopenharmony_ci	rts
117162306a36Sopenharmony_ci
117262306a36Sopenharmony_ciaddr_ind_m_a4:
117362306a36Sopenharmony_ci	mov.l		EXC_A4(%a6),%d0		# Get current a4
117462306a36Sopenharmony_ci	mov.l		%d0,EXC_SAVVAL(%a6)	# save in case of access error
117562306a36Sopenharmony_ci	sub.l		%a0,%d0			# Decrement
117662306a36Sopenharmony_ci	mov.l		%d0,EXC_A4(%a6)		# Save decr value
117762306a36Sopenharmony_ci	mov.l		%d0,%a0
117862306a36Sopenharmony_ci
117962306a36Sopenharmony_ci	mov.b		&0x4,EXC_SAVREG(%a6)	# save regno, too
118062306a36Sopenharmony_ci	mov.b		&restore_flg,SPCOND_FLG(%a6) # set flag
118162306a36Sopenharmony_ci	rts
118262306a36Sopenharmony_ci
118362306a36Sopenharmony_ciaddr_ind_m_a5:
118462306a36Sopenharmony_ci	mov.l		EXC_A5(%a6),%d0		# Get current a5
118562306a36Sopenharmony_ci	mov.l		%d0,EXC_SAVVAL(%a6)	# save in case of access error
118662306a36Sopenharmony_ci	sub.l		%a0,%d0			# Decrement
118762306a36Sopenharmony_ci	mov.l		%d0,EXC_A5(%a6)		# Save decr value
118862306a36Sopenharmony_ci	mov.l		%d0,%a0
118962306a36Sopenharmony_ci
119062306a36Sopenharmony_ci	mov.b		&0x5,EXC_SAVREG(%a6)	# save regno, too
119162306a36Sopenharmony_ci	mov.b		&restore_flg,SPCOND_FLG(%a6) # set flag
119262306a36Sopenharmony_ci	rts
119362306a36Sopenharmony_ci
119462306a36Sopenharmony_ciaddr_ind_m_a6:
119562306a36Sopenharmony_ci	mov.l		EXC_A6(%a6),%d0		# Get current a6
119662306a36Sopenharmony_ci	mov.l		%d0,EXC_SAVVAL(%a6)	# save in case of access error
119762306a36Sopenharmony_ci	sub.l		%a0,%d0			# Decrement
119862306a36Sopenharmony_ci	mov.l		%d0,EXC_A6(%a6)		# Save decr value
119962306a36Sopenharmony_ci	mov.l		%d0,%a0
120062306a36Sopenharmony_ci
120162306a36Sopenharmony_ci	mov.b		&0x6,EXC_SAVREG(%a6)	# save regno, too
120262306a36Sopenharmony_ci	mov.b		&restore_flg,SPCOND_FLG(%a6) # set flag
120362306a36Sopenharmony_ci	rts
120462306a36Sopenharmony_ci
120562306a36Sopenharmony_ciaddr_ind_m_a7:
120662306a36Sopenharmony_ci	mov.b		&mda7_flg,SPCOND_FLG(%a6) # set "special case" flag
120762306a36Sopenharmony_ci
120862306a36Sopenharmony_ci	mov.l		EXC_A7(%a6),%d0		# Get current a7
120962306a36Sopenharmony_ci	sub.l		%a0,%d0			# Decrement
121062306a36Sopenharmony_ci	mov.l		%d0,EXC_A7(%a6)		# Save decr value
121162306a36Sopenharmony_ci	mov.l		%d0,%a0
121262306a36Sopenharmony_ci	rts
121362306a36Sopenharmony_ci
121462306a36Sopenharmony_ci########################################################
121562306a36Sopenharmony_ci# Address register indirect w/ displacement: (d16, An) #
121662306a36Sopenharmony_ci########################################################
121762306a36Sopenharmony_ciaddr_ind_disp_a0:
121862306a36Sopenharmony_ci	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
121962306a36Sopenharmony_ci	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
122062306a36Sopenharmony_ci	bsr.l		_imem_read_word
122162306a36Sopenharmony_ci
122262306a36Sopenharmony_ci	tst.l		%d1			# ifetch error?
122362306a36Sopenharmony_ci	bne.l		isp_iacc		# yes
122462306a36Sopenharmony_ci
122562306a36Sopenharmony_ci	mov.w		%d0,%a0			# sign extend displacement
122662306a36Sopenharmony_ci	add.l		EXC_A0(%a6),%a0		# a0 + d16
122762306a36Sopenharmony_ci	rts
122862306a36Sopenharmony_ci
122962306a36Sopenharmony_ciaddr_ind_disp_a1:
123062306a36Sopenharmony_ci	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
123162306a36Sopenharmony_ci	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
123262306a36Sopenharmony_ci	bsr.l		_imem_read_word
123362306a36Sopenharmony_ci
123462306a36Sopenharmony_ci	tst.l		%d1			# ifetch error?
123562306a36Sopenharmony_ci	bne.l		isp_iacc		# yes
123662306a36Sopenharmony_ci
123762306a36Sopenharmony_ci	mov.w		%d0,%a0			# sign extend displacement
123862306a36Sopenharmony_ci	add.l		EXC_A1(%a6),%a0		# a1 + d16
123962306a36Sopenharmony_ci	rts
124062306a36Sopenharmony_ci
124162306a36Sopenharmony_ciaddr_ind_disp_a2:
124262306a36Sopenharmony_ci	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
124362306a36Sopenharmony_ci	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
124462306a36Sopenharmony_ci	bsr.l		_imem_read_word
124562306a36Sopenharmony_ci
124662306a36Sopenharmony_ci	tst.l		%d1			# ifetch error?
124762306a36Sopenharmony_ci	bne.l		isp_iacc		# yes
124862306a36Sopenharmony_ci
124962306a36Sopenharmony_ci	mov.w		%d0,%a0			# sign extend displacement
125062306a36Sopenharmony_ci	add.l		EXC_A2(%a6),%a0		# a2 + d16
125162306a36Sopenharmony_ci	rts
125262306a36Sopenharmony_ci
125362306a36Sopenharmony_ciaddr_ind_disp_a3:
125462306a36Sopenharmony_ci	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
125562306a36Sopenharmony_ci	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
125662306a36Sopenharmony_ci	bsr.l		_imem_read_word
125762306a36Sopenharmony_ci
125862306a36Sopenharmony_ci	tst.l		%d1			# ifetch error?
125962306a36Sopenharmony_ci	bne.l		isp_iacc		# yes
126062306a36Sopenharmony_ci
126162306a36Sopenharmony_ci	mov.w		%d0,%a0			# sign extend displacement
126262306a36Sopenharmony_ci	add.l		EXC_A3(%a6),%a0		# a3 + d16
126362306a36Sopenharmony_ci	rts
126462306a36Sopenharmony_ci
126562306a36Sopenharmony_ciaddr_ind_disp_a4:
126662306a36Sopenharmony_ci	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
126762306a36Sopenharmony_ci	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
126862306a36Sopenharmony_ci	bsr.l		_imem_read_word
126962306a36Sopenharmony_ci
127062306a36Sopenharmony_ci	tst.l		%d1			# ifetch error?
127162306a36Sopenharmony_ci	bne.l		isp_iacc		# yes
127262306a36Sopenharmony_ci
127362306a36Sopenharmony_ci	mov.w		%d0,%a0			# sign extend displacement
127462306a36Sopenharmony_ci	add.l		EXC_A4(%a6),%a0		# a4 + d16
127562306a36Sopenharmony_ci	rts
127662306a36Sopenharmony_ci
127762306a36Sopenharmony_ciaddr_ind_disp_a5:
127862306a36Sopenharmony_ci	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
127962306a36Sopenharmony_ci	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
128062306a36Sopenharmony_ci	bsr.l		_imem_read_word
128162306a36Sopenharmony_ci
128262306a36Sopenharmony_ci	tst.l		%d1			# ifetch error?
128362306a36Sopenharmony_ci	bne.l		isp_iacc		# yes
128462306a36Sopenharmony_ci
128562306a36Sopenharmony_ci	mov.w		%d0,%a0			# sign extend displacement
128662306a36Sopenharmony_ci	add.l		EXC_A5(%a6),%a0		# a5 + d16
128762306a36Sopenharmony_ci	rts
128862306a36Sopenharmony_ci
128962306a36Sopenharmony_ciaddr_ind_disp_a6:
129062306a36Sopenharmony_ci	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
129162306a36Sopenharmony_ci	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
129262306a36Sopenharmony_ci	bsr.l		_imem_read_word
129362306a36Sopenharmony_ci
129462306a36Sopenharmony_ci	tst.l		%d1			# ifetch error?
129562306a36Sopenharmony_ci	bne.l		isp_iacc		# yes
129662306a36Sopenharmony_ci
129762306a36Sopenharmony_ci	mov.w		%d0,%a0			# sign extend displacement
129862306a36Sopenharmony_ci	add.l		EXC_A6(%a6),%a0		# a6 + d16
129962306a36Sopenharmony_ci	rts
130062306a36Sopenharmony_ci
130162306a36Sopenharmony_ciaddr_ind_disp_a7:
130262306a36Sopenharmony_ci	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
130362306a36Sopenharmony_ci	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
130462306a36Sopenharmony_ci	bsr.l		_imem_read_word
130562306a36Sopenharmony_ci
130662306a36Sopenharmony_ci	tst.l		%d1			# ifetch error?
130762306a36Sopenharmony_ci	bne.l		isp_iacc		# yes
130862306a36Sopenharmony_ci
130962306a36Sopenharmony_ci	mov.w		%d0,%a0			# sign extend displacement
131062306a36Sopenharmony_ci	add.l		EXC_A7(%a6),%a0		# a7 + d16
131162306a36Sopenharmony_ci	rts
131262306a36Sopenharmony_ci
131362306a36Sopenharmony_ci########################################################################
131462306a36Sopenharmony_ci# Address register indirect w/ index(8-bit displacement): (dn, An, Xn) #
131562306a36Sopenharmony_ci#    "       "         "    w/   "  (base displacement): (bd, An, Xn)  #
131662306a36Sopenharmony_ci# Memory indirect postindexed: ([bd, An], Xn, od)		       #
131762306a36Sopenharmony_ci# Memory indirect preindexed: ([bd, An, Xn], od)		       #
131862306a36Sopenharmony_ci########################################################################
131962306a36Sopenharmony_ci_addr_ind_ext:
132062306a36Sopenharmony_ci	mov.l		%d1,-(%sp)
132162306a36Sopenharmony_ci
132262306a36Sopenharmony_ci	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
132362306a36Sopenharmony_ci	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
132462306a36Sopenharmony_ci	bsr.l		_imem_read_word		# fetch extword in d0
132562306a36Sopenharmony_ci
132662306a36Sopenharmony_ci	tst.l		%d1			# ifetch error?
132762306a36Sopenharmony_ci	bne.l		isp_iacc		# yes
132862306a36Sopenharmony_ci
132962306a36Sopenharmony_ci	mov.l		(%sp)+,%d1
133062306a36Sopenharmony_ci
133162306a36Sopenharmony_ci	mov.l		(EXC_AREGS,%a6,%d1.w*4),%a0 # put base in a0
133262306a36Sopenharmony_ci
133362306a36Sopenharmony_ci	btst		&0x8,%d0
133462306a36Sopenharmony_ci	beq.b		addr_ind_index_8bit	# for ext word or not?
133562306a36Sopenharmony_ci
133662306a36Sopenharmony_ci	movm.l		&0x3c00,-(%sp)		# save d2-d5
133762306a36Sopenharmony_ci
133862306a36Sopenharmony_ci	mov.l		%d0,%d5			# put extword in d5
133962306a36Sopenharmony_ci	mov.l		%a0,%d3			# put base in d3
134062306a36Sopenharmony_ci
134162306a36Sopenharmony_ci	bra.l		calc_mem_ind		# calc memory indirect
134262306a36Sopenharmony_ci
134362306a36Sopenharmony_ciaddr_ind_index_8bit:
134462306a36Sopenharmony_ci	mov.l		%d2,-(%sp)		# save old d2
134562306a36Sopenharmony_ci
134662306a36Sopenharmony_ci	mov.l		%d0,%d1
134762306a36Sopenharmony_ci	rol.w		&0x4,%d1
134862306a36Sopenharmony_ci	andi.w		&0xf,%d1		# extract index regno
134962306a36Sopenharmony_ci
135062306a36Sopenharmony_ci	mov.l		(EXC_DREGS,%a6,%d1.w*4),%d1 # fetch index reg value
135162306a36Sopenharmony_ci
135262306a36Sopenharmony_ci	btst		&0xb,%d0		# is it word or long?
135362306a36Sopenharmony_ci	bne.b		aii8_long
135462306a36Sopenharmony_ci	ext.l		%d1			# sign extend word index
135562306a36Sopenharmony_ciaii8_long:
135662306a36Sopenharmony_ci	mov.l		%d0,%d2
135762306a36Sopenharmony_ci	rol.w		&0x7,%d2
135862306a36Sopenharmony_ci	andi.l		&0x3,%d2		# extract scale value
135962306a36Sopenharmony_ci
136062306a36Sopenharmony_ci	lsl.l		%d2,%d1			# shift index by scale
136162306a36Sopenharmony_ci
136262306a36Sopenharmony_ci	extb.l		%d0			# sign extend displacement
136362306a36Sopenharmony_ci	add.l		%d1,%d0			# index + disp
136462306a36Sopenharmony_ci	add.l		%d0,%a0			# An + (index + disp)
136562306a36Sopenharmony_ci
136662306a36Sopenharmony_ci	mov.l		(%sp)+,%d2		# restore old d2
136762306a36Sopenharmony_ci	rts
136862306a36Sopenharmony_ci
136962306a36Sopenharmony_ci######################
137062306a36Sopenharmony_ci# Immediate: #<data> #
137162306a36Sopenharmony_ci#########################################################################
137262306a36Sopenharmony_ci# word, long: <ea> of the data is the current extension word		#
137362306a36Sopenharmony_ci#	pointer value. new extension word pointer is simply the old	#
137462306a36Sopenharmony_ci#	plus the number of bytes in the data type(2 or 4).		#
137562306a36Sopenharmony_ci#########################################################################
137662306a36Sopenharmony_ciimmediate:
137762306a36Sopenharmony_ci	mov.b		&immed_flg,SPCOND_FLG(%a6) # set immediate flag
137862306a36Sopenharmony_ci
137962306a36Sopenharmony_ci	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch extension word ptr
138062306a36Sopenharmony_ci	rts
138162306a36Sopenharmony_ci
138262306a36Sopenharmony_ci###########################
138362306a36Sopenharmony_ci# Absolute short: (XXX).W #
138462306a36Sopenharmony_ci###########################
138562306a36Sopenharmony_ciabs_short:
138662306a36Sopenharmony_ci	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
138762306a36Sopenharmony_ci	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
138862306a36Sopenharmony_ci	bsr.l		_imem_read_word		# fetch short address
138962306a36Sopenharmony_ci
139062306a36Sopenharmony_ci	tst.l		%d1			# ifetch error?
139162306a36Sopenharmony_ci	bne.l		isp_iacc		# yes
139262306a36Sopenharmony_ci
139362306a36Sopenharmony_ci	mov.w		%d0,%a0			# return <ea> in a0
139462306a36Sopenharmony_ci	rts
139562306a36Sopenharmony_ci
139662306a36Sopenharmony_ci##########################
139762306a36Sopenharmony_ci# Absolute long: (XXX).L #
139862306a36Sopenharmony_ci##########################
139962306a36Sopenharmony_ciabs_long:
140062306a36Sopenharmony_ci	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
140162306a36Sopenharmony_ci	addq.l		&0x4,EXC_EXTWPTR(%a6)	# incr instruction ptr
140262306a36Sopenharmony_ci	bsr.l		_imem_read_long		# fetch long address
140362306a36Sopenharmony_ci
140462306a36Sopenharmony_ci	tst.l		%d1			# ifetch error?
140562306a36Sopenharmony_ci	bne.l		isp_iacc		# yes
140662306a36Sopenharmony_ci
140762306a36Sopenharmony_ci	mov.l		%d0,%a0			# return <ea> in a0
140862306a36Sopenharmony_ci	rts
140962306a36Sopenharmony_ci
141062306a36Sopenharmony_ci#######################################################
141162306a36Sopenharmony_ci# Program counter indirect w/ displacement: (d16, PC) #
141262306a36Sopenharmony_ci#######################################################
141362306a36Sopenharmony_cipc_ind:
141462306a36Sopenharmony_ci	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
141562306a36Sopenharmony_ci	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
141662306a36Sopenharmony_ci	bsr.l		_imem_read_word		# fetch word displacement
141762306a36Sopenharmony_ci
141862306a36Sopenharmony_ci	tst.l		%d1			# ifetch error?
141962306a36Sopenharmony_ci	bne.l		isp_iacc		# yes
142062306a36Sopenharmony_ci
142162306a36Sopenharmony_ci	mov.w		%d0,%a0			# sign extend displacement
142262306a36Sopenharmony_ci
142362306a36Sopenharmony_ci	add.l		EXC_EXTWPTR(%a6),%a0	# pc + d16
142462306a36Sopenharmony_ci
142562306a36Sopenharmony_ci# _imem_read_word() increased the extwptr by 2. need to adjust here.
142662306a36Sopenharmony_ci	subq.l		&0x2,%a0		# adjust <ea>
142762306a36Sopenharmony_ci
142862306a36Sopenharmony_ci	rts
142962306a36Sopenharmony_ci
143062306a36Sopenharmony_ci##########################################################
143162306a36Sopenharmony_ci# PC indirect w/ index(8-bit displacement): (d8, PC, An) #
143262306a36Sopenharmony_ci# "     "     w/   "  (base displacement): (bd, PC, An)  #
143362306a36Sopenharmony_ci# PC memory indirect postindexed: ([bd, PC], Xn, od)     #
143462306a36Sopenharmony_ci# PC memory indirect preindexed: ([bd, PC, Xn], od)      #
143562306a36Sopenharmony_ci##########################################################
143662306a36Sopenharmony_cipc_ind_ext:
143762306a36Sopenharmony_ci	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
143862306a36Sopenharmony_ci	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
143962306a36Sopenharmony_ci	bsr.l		_imem_read_word		# fetch ext word
144062306a36Sopenharmony_ci
144162306a36Sopenharmony_ci	tst.l		%d1			# ifetch error?
144262306a36Sopenharmony_ci	bne.l		isp_iacc		# yes
144362306a36Sopenharmony_ci
144462306a36Sopenharmony_ci	mov.l		EXC_EXTWPTR(%a6),%a0	# put base in a0
144562306a36Sopenharmony_ci	subq.l		&0x2,%a0		# adjust base
144662306a36Sopenharmony_ci
144762306a36Sopenharmony_ci	btst		&0x8,%d0		# is disp only 8 bits?
144862306a36Sopenharmony_ci	beq.b		pc_ind_index_8bit	# yes
144962306a36Sopenharmony_ci
145062306a36Sopenharmony_ci# the indexed addressing mode uses a base displacement of size
145162306a36Sopenharmony_ci# word or long
145262306a36Sopenharmony_ci	movm.l		&0x3c00,-(%sp)		# save d2-d5
145362306a36Sopenharmony_ci
145462306a36Sopenharmony_ci	mov.l		%d0,%d5			# put extword in d5
145562306a36Sopenharmony_ci	mov.l		%a0,%d3			# put base in d3
145662306a36Sopenharmony_ci
145762306a36Sopenharmony_ci	bra.l		calc_mem_ind		# calc memory indirect
145862306a36Sopenharmony_ci
145962306a36Sopenharmony_cipc_ind_index_8bit:
146062306a36Sopenharmony_ci	mov.l		%d2,-(%sp)		# create a temp register
146162306a36Sopenharmony_ci
146262306a36Sopenharmony_ci	mov.l		%d0,%d1			# make extword copy
146362306a36Sopenharmony_ci	rol.w		&0x4,%d1		# rotate reg num into place
146462306a36Sopenharmony_ci	andi.w		&0xf,%d1		# extract register number
146562306a36Sopenharmony_ci
146662306a36Sopenharmony_ci	mov.l		(EXC_DREGS,%a6,%d1.w*4),%d1 # fetch index reg value
146762306a36Sopenharmony_ci
146862306a36Sopenharmony_ci	btst		&0xb,%d0		# is index word or long?
146962306a36Sopenharmony_ci	bne.b		pii8_long		# long
147062306a36Sopenharmony_ci	ext.l		%d1			# sign extend word index
147162306a36Sopenharmony_cipii8_long:
147262306a36Sopenharmony_ci	mov.l		%d0,%d2			# make extword copy
147362306a36Sopenharmony_ci	rol.w		&0x7,%d2		# rotate scale value into place
147462306a36Sopenharmony_ci	andi.l		&0x3,%d2		# extract scale value
147562306a36Sopenharmony_ci
147662306a36Sopenharmony_ci	lsl.l		%d2,%d1			# shift index by scale
147762306a36Sopenharmony_ci
147862306a36Sopenharmony_ci	extb.l		%d0			# sign extend displacement
147962306a36Sopenharmony_ci	add.l		%d1,%d0			# index + disp
148062306a36Sopenharmony_ci	add.l		%d0,%a0			# An + (index + disp)
148162306a36Sopenharmony_ci
148262306a36Sopenharmony_ci	mov.l		(%sp)+,%d2		# restore temp register
148362306a36Sopenharmony_ci
148462306a36Sopenharmony_ci	rts
148562306a36Sopenharmony_ci
148662306a36Sopenharmony_ci# a5 = exc_extwptr	(global to uaeh)
148762306a36Sopenharmony_ci# a4 = exc_opword	(global to uaeh)
148862306a36Sopenharmony_ci# a3 = exc_dregs	(global to uaeh)
148962306a36Sopenharmony_ci
149062306a36Sopenharmony_ci# d2 = index		(internal "     "    )
149162306a36Sopenharmony_ci# d3 = base		(internal "     "    )
149262306a36Sopenharmony_ci# d4 = od		(internal "     "    )
149362306a36Sopenharmony_ci# d5 = extword		(internal "     "    )
149462306a36Sopenharmony_cicalc_mem_ind:
149562306a36Sopenharmony_ci	btst		&0x6,%d5		# is the index suppressed?
149662306a36Sopenharmony_ci	beq.b		calc_index
149762306a36Sopenharmony_ci	clr.l		%d2			# yes, so index = 0
149862306a36Sopenharmony_ci	bra.b		base_supp_ck
149962306a36Sopenharmony_cicalc_index:
150062306a36Sopenharmony_ci	bfextu		%d5{&16:&4},%d2
150162306a36Sopenharmony_ci	mov.l		(EXC_DREGS,%a6,%d2.w*4),%d2
150262306a36Sopenharmony_ci	btst		&0xb,%d5		# is index word or long?
150362306a36Sopenharmony_ci	bne.b		no_ext
150462306a36Sopenharmony_ci	ext.l		%d2
150562306a36Sopenharmony_cino_ext:
150662306a36Sopenharmony_ci	bfextu		%d5{&21:&2},%d0
150762306a36Sopenharmony_ci	lsl.l		%d0,%d2
150862306a36Sopenharmony_cibase_supp_ck:
150962306a36Sopenharmony_ci	btst		&0x7,%d5		# is the bd suppressed?
151062306a36Sopenharmony_ci	beq.b		no_base_sup
151162306a36Sopenharmony_ci	clr.l		%d3
151262306a36Sopenharmony_cino_base_sup:
151362306a36Sopenharmony_ci	bfextu		%d5{&26:&2},%d0	# get bd size
151462306a36Sopenharmony_ci#	beq.l		_error			# if (size == 0) it's reserved
151562306a36Sopenharmony_ci	cmpi.b		%d0,&2
151662306a36Sopenharmony_ci	blt.b		no_bd
151762306a36Sopenharmony_ci	beq.b		get_word_bd
151862306a36Sopenharmony_ci
151962306a36Sopenharmony_ci	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
152062306a36Sopenharmony_ci	addq.l		&0x4,EXC_EXTWPTR(%a6)	# incr instruction ptr
152162306a36Sopenharmony_ci	bsr.l		_imem_read_long
152262306a36Sopenharmony_ci
152362306a36Sopenharmony_ci	tst.l		%d1			# ifetch error?
152462306a36Sopenharmony_ci	bne.l		isp_iacc		# yes
152562306a36Sopenharmony_ci
152662306a36Sopenharmony_ci	bra.b		chk_ind
152762306a36Sopenharmony_ciget_word_bd:
152862306a36Sopenharmony_ci	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
152962306a36Sopenharmony_ci	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
153062306a36Sopenharmony_ci	bsr.l		_imem_read_word
153162306a36Sopenharmony_ci
153262306a36Sopenharmony_ci	tst.l		%d1			# ifetch error?
153362306a36Sopenharmony_ci	bne.l		isp_iacc		# yes
153462306a36Sopenharmony_ci
153562306a36Sopenharmony_ci	ext.l		%d0			# sign extend bd
153662306a36Sopenharmony_ci
153762306a36Sopenharmony_cichk_ind:
153862306a36Sopenharmony_ci	add.l		%d0,%d3			# base += bd
153962306a36Sopenharmony_cino_bd:
154062306a36Sopenharmony_ci	bfextu		%d5{&30:&2},%d0		# is od suppressed?
154162306a36Sopenharmony_ci	beq.w		aii_bd
154262306a36Sopenharmony_ci	cmpi.b		%d0,&0x2
154362306a36Sopenharmony_ci	blt.b		null_od
154462306a36Sopenharmony_ci	beq.b		word_od
154562306a36Sopenharmony_ci
154662306a36Sopenharmony_ci	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
154762306a36Sopenharmony_ci	addq.l		&0x4,EXC_EXTWPTR(%a6)	# incr instruction ptr
154862306a36Sopenharmony_ci	bsr.l		_imem_read_long
154962306a36Sopenharmony_ci
155062306a36Sopenharmony_ci	tst.l		%d1			# ifetch error?
155162306a36Sopenharmony_ci	bne.l		isp_iacc		# yes
155262306a36Sopenharmony_ci
155362306a36Sopenharmony_ci	bra.b		add_them
155462306a36Sopenharmony_ci
155562306a36Sopenharmony_ciword_od:
155662306a36Sopenharmony_ci	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
155762306a36Sopenharmony_ci	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
155862306a36Sopenharmony_ci	bsr.l		_imem_read_word
155962306a36Sopenharmony_ci
156062306a36Sopenharmony_ci	tst.l		%d1			# ifetch error?
156162306a36Sopenharmony_ci	bne.l		isp_iacc		# yes
156262306a36Sopenharmony_ci
156362306a36Sopenharmony_ci	ext.l		%d0			# sign extend od
156462306a36Sopenharmony_ci	bra.b		add_them
156562306a36Sopenharmony_ci
156662306a36Sopenharmony_cinull_od:
156762306a36Sopenharmony_ci	clr.l		%d0
156862306a36Sopenharmony_ciadd_them:
156962306a36Sopenharmony_ci	mov.l		%d0,%d4
157062306a36Sopenharmony_ci	btst		&0x2,%d5		# pre or post indexing?
157162306a36Sopenharmony_ci	beq.b		pre_indexed
157262306a36Sopenharmony_ci
157362306a36Sopenharmony_ci	mov.l		%d3,%a0
157462306a36Sopenharmony_ci	bsr.l		_dmem_read_long
157562306a36Sopenharmony_ci
157662306a36Sopenharmony_ci	tst.l		%d1			# dfetch error?
157762306a36Sopenharmony_ci	bne.b		calc_ea_err		# yes
157862306a36Sopenharmony_ci
157962306a36Sopenharmony_ci	add.l		%d2,%d0			# <ea> += index
158062306a36Sopenharmony_ci	add.l		%d4,%d0			# <ea> += od
158162306a36Sopenharmony_ci	bra.b		done_ea
158262306a36Sopenharmony_ci
158362306a36Sopenharmony_cipre_indexed:
158462306a36Sopenharmony_ci	add.l		%d2,%d3			# preindexing
158562306a36Sopenharmony_ci	mov.l		%d3,%a0
158662306a36Sopenharmony_ci	bsr.l		_dmem_read_long
158762306a36Sopenharmony_ci
158862306a36Sopenharmony_ci	tst.l		%d1			# ifetch error?
158962306a36Sopenharmony_ci	bne.b		calc_ea_err		# yes
159062306a36Sopenharmony_ci
159162306a36Sopenharmony_ci	add.l		%d4,%d0			# ea += od
159262306a36Sopenharmony_ci	bra.b		done_ea
159362306a36Sopenharmony_ci
159462306a36Sopenharmony_ciaii_bd:
159562306a36Sopenharmony_ci	add.l		%d2,%d3			# ea = (base + bd) + index
159662306a36Sopenharmony_ci	mov.l		%d3,%d0
159762306a36Sopenharmony_cidone_ea:
159862306a36Sopenharmony_ci	mov.l		%d0,%a0
159962306a36Sopenharmony_ci
160062306a36Sopenharmony_ci	movm.l		(%sp)+,&0x003c		# restore d2-d5
160162306a36Sopenharmony_ci	rts
160262306a36Sopenharmony_ci
160362306a36Sopenharmony_ci# if dmem_read_long() returns a fail message in d1, the package
160462306a36Sopenharmony_ci# must create an access error frame. here, we pass a skeleton fslw
160562306a36Sopenharmony_ci# and the failing address to the routine that creates the new frame.
160662306a36Sopenharmony_ci# FSLW:
160762306a36Sopenharmony_ci#	read = true
160862306a36Sopenharmony_ci#	size = longword
160962306a36Sopenharmony_ci#	TM = data
161062306a36Sopenharmony_ci#	software emulation error = true
161162306a36Sopenharmony_cicalc_ea_err:
161262306a36Sopenharmony_ci	mov.l		%d3,%a0			# pass failing address
161362306a36Sopenharmony_ci	mov.l		&0x01010001,%d0		# pass fslw
161462306a36Sopenharmony_ci	bra.l		isp_dacc
161562306a36Sopenharmony_ci
161662306a36Sopenharmony_ci#########################################################################
161762306a36Sopenharmony_ci# XDEF **************************************************************** #
161862306a36Sopenharmony_ci#	_moveperipheral(): routine to emulate movep instruction		#
161962306a36Sopenharmony_ci#									#
162062306a36Sopenharmony_ci# XREF **************************************************************** #
162162306a36Sopenharmony_ci#	_dmem_read_byte() - read byte from memory			#
162262306a36Sopenharmony_ci#	_dmem_write_byte() - write byte to memory			#
162362306a36Sopenharmony_ci#	isp_dacc() - handle data access error exception			#
162462306a36Sopenharmony_ci#									#
162562306a36Sopenharmony_ci# INPUT *************************************************************** #
162662306a36Sopenharmony_ci#	none								#
162762306a36Sopenharmony_ci#									#
162862306a36Sopenharmony_ci# OUTPUT ************************************************************** #
162962306a36Sopenharmony_ci#	If exiting through isp_dacc...					#
163062306a36Sopenharmony_ci#		a0 = failing address					#
163162306a36Sopenharmony_ci#		d0 = FSLW						#
163262306a36Sopenharmony_ci#	else								#
163362306a36Sopenharmony_ci#		none							#
163462306a36Sopenharmony_ci#									#
163562306a36Sopenharmony_ci# ALGORITHM ***********************************************************	#
163662306a36Sopenharmony_ci#	Decode the movep instruction words stored at EXC_OPWORD and	#
163762306a36Sopenharmony_ci# either read or write the required bytes from/to memory. Use the	#
163862306a36Sopenharmony_ci# _dmem_{read,write}_byte() routines. If one of the memory routines	#
163962306a36Sopenharmony_ci# returns a failing value, we must pass the failing address and	a FSLW	#
164062306a36Sopenharmony_ci# to the _isp_dacc() routine.						#
164162306a36Sopenharmony_ci#	Since this instruction is used to access peripherals, make sure	#
164262306a36Sopenharmony_ci# to only access the required bytes.					#
164362306a36Sopenharmony_ci#									#
164462306a36Sopenharmony_ci#########################################################################
164562306a36Sopenharmony_ci
164662306a36Sopenharmony_ci###########################
164762306a36Sopenharmony_ci# movep.(w,l)	Dx,(d,Ay) #
164862306a36Sopenharmony_ci# movep.(w,l)	(d,Ay),Dx #
164962306a36Sopenharmony_ci###########################
165062306a36Sopenharmony_ci	global		_moveperipheral
165162306a36Sopenharmony_ci_moveperipheral:
165262306a36Sopenharmony_ci	mov.w		EXC_OPWORD(%a6),%d1	# fetch the opcode word
165362306a36Sopenharmony_ci
165462306a36Sopenharmony_ci	mov.b		%d1,%d0
165562306a36Sopenharmony_ci	and.w		&0x7,%d0		# extract Ay from opcode word
165662306a36Sopenharmony_ci
165762306a36Sopenharmony_ci	mov.l		(EXC_AREGS,%a6,%d0.w*4),%a0 # fetch ay
165862306a36Sopenharmony_ci
165962306a36Sopenharmony_ci	add.w		EXC_EXTWORD(%a6),%a0	# add: an + sgn_ext(disp)
166062306a36Sopenharmony_ci
166162306a36Sopenharmony_ci	btst		&0x7,%d1		# (reg 2 mem) or (mem 2 reg)
166262306a36Sopenharmony_ci	beq.w		mem2reg
166362306a36Sopenharmony_ci
166462306a36Sopenharmony_ci# reg2mem: fetch dx, then write it to memory
166562306a36Sopenharmony_cireg2mem:
166662306a36Sopenharmony_ci	mov.w		%d1,%d0
166762306a36Sopenharmony_ci	rol.w		&0x7,%d0
166862306a36Sopenharmony_ci	and.w		&0x7,%d0		# extract Dx from opcode word
166962306a36Sopenharmony_ci
167062306a36Sopenharmony_ci	mov.l		(EXC_DREGS,%a6,%d0.w*4), %d0 # fetch dx
167162306a36Sopenharmony_ci
167262306a36Sopenharmony_ci	btst		&0x6,%d1		# word or long operation?
167362306a36Sopenharmony_ci	beq.b		r2mwtrans
167462306a36Sopenharmony_ci
167562306a36Sopenharmony_ci# a0 = dst addr
167662306a36Sopenharmony_ci# d0 = Dx
167762306a36Sopenharmony_cir2mltrans:
167862306a36Sopenharmony_ci	mov.l		%d0,%d2			# store data
167962306a36Sopenharmony_ci	mov.l		%a0,%a2			# store addr
168062306a36Sopenharmony_ci	rol.l		&0x8,%d2
168162306a36Sopenharmony_ci	mov.l		%d2,%d0
168262306a36Sopenharmony_ci
168362306a36Sopenharmony_ci	bsr.l		_dmem_write_byte	# os  : write hi
168462306a36Sopenharmony_ci
168562306a36Sopenharmony_ci	tst.l		%d1			# dfetch error?
168662306a36Sopenharmony_ci	bne.w		movp_write_err		# yes
168762306a36Sopenharmony_ci
168862306a36Sopenharmony_ci	add.w		&0x2,%a2		# incr addr
168962306a36Sopenharmony_ci	mov.l		%a2,%a0
169062306a36Sopenharmony_ci	rol.l		&0x8,%d2
169162306a36Sopenharmony_ci	mov.l		%d2,%d0
169262306a36Sopenharmony_ci
169362306a36Sopenharmony_ci	bsr.l		_dmem_write_byte	# os  : write lo
169462306a36Sopenharmony_ci
169562306a36Sopenharmony_ci	tst.l		%d1			# dfetch error?
169662306a36Sopenharmony_ci	bne.w		movp_write_err		# yes
169762306a36Sopenharmony_ci
169862306a36Sopenharmony_ci	add.w		&0x2,%a2		# incr addr
169962306a36Sopenharmony_ci	mov.l		%a2,%a0
170062306a36Sopenharmony_ci	rol.l		&0x8,%d2
170162306a36Sopenharmony_ci	mov.l		%d2,%d0
170262306a36Sopenharmony_ci
170362306a36Sopenharmony_ci	bsr.l		_dmem_write_byte	# os  : write lo
170462306a36Sopenharmony_ci
170562306a36Sopenharmony_ci	tst.l		%d1			# dfetch error?
170662306a36Sopenharmony_ci	bne.w		movp_write_err		# yes
170762306a36Sopenharmony_ci
170862306a36Sopenharmony_ci	add.w		&0x2,%a2		# incr addr
170962306a36Sopenharmony_ci	mov.l		%a2,%a0
171062306a36Sopenharmony_ci	rol.l		&0x8,%d2
171162306a36Sopenharmony_ci	mov.l		%d2,%d0
171262306a36Sopenharmony_ci
171362306a36Sopenharmony_ci	bsr.l		_dmem_write_byte	# os  : write lo
171462306a36Sopenharmony_ci
171562306a36Sopenharmony_ci	tst.l		%d1			# dfetch error?
171662306a36Sopenharmony_ci	bne.w		movp_write_err		# yes
171762306a36Sopenharmony_ci
171862306a36Sopenharmony_ci	rts
171962306a36Sopenharmony_ci
172062306a36Sopenharmony_ci# a0 = dst addr
172162306a36Sopenharmony_ci# d0 = Dx
172262306a36Sopenharmony_cir2mwtrans:
172362306a36Sopenharmony_ci	mov.l		%d0,%d2			# store data
172462306a36Sopenharmony_ci	mov.l		%a0,%a2			# store addr
172562306a36Sopenharmony_ci	lsr.w		&0x8,%d0
172662306a36Sopenharmony_ci
172762306a36Sopenharmony_ci	bsr.l		_dmem_write_byte	# os  : write hi
172862306a36Sopenharmony_ci
172962306a36Sopenharmony_ci	tst.l		%d1			# dfetch error?
173062306a36Sopenharmony_ci	bne.w		movp_write_err		# yes
173162306a36Sopenharmony_ci
173262306a36Sopenharmony_ci	add.w		&0x2,%a2
173362306a36Sopenharmony_ci	mov.l		%a2,%a0
173462306a36Sopenharmony_ci	mov.l		%d2,%d0
173562306a36Sopenharmony_ci
173662306a36Sopenharmony_ci	bsr.l		_dmem_write_byte	# os  : write lo
173762306a36Sopenharmony_ci
173862306a36Sopenharmony_ci	tst.l		%d1			# dfetch error?
173962306a36Sopenharmony_ci	bne.w		movp_write_err		# yes
174062306a36Sopenharmony_ci
174162306a36Sopenharmony_ci	rts
174262306a36Sopenharmony_ci
174362306a36Sopenharmony_ci# mem2reg: read bytes from memory.
174462306a36Sopenharmony_ci# determines the dest register, and then writes the bytes into it.
174562306a36Sopenharmony_cimem2reg:
174662306a36Sopenharmony_ci	btst		&0x6,%d1		# word or long operation?
174762306a36Sopenharmony_ci	beq.b		m2rwtrans
174862306a36Sopenharmony_ci
174962306a36Sopenharmony_ci# a0 = dst addr
175062306a36Sopenharmony_cim2rltrans:
175162306a36Sopenharmony_ci	mov.l		%a0,%a2			# store addr
175262306a36Sopenharmony_ci
175362306a36Sopenharmony_ci	bsr.l		_dmem_read_byte		# read first byte
175462306a36Sopenharmony_ci
175562306a36Sopenharmony_ci	tst.l		%d1			# dfetch error?
175662306a36Sopenharmony_ci	bne.w		movp_read_err		# yes
175762306a36Sopenharmony_ci
175862306a36Sopenharmony_ci	mov.l		%d0,%d2
175962306a36Sopenharmony_ci
176062306a36Sopenharmony_ci	add.w		&0x2,%a2		# incr addr by 2 bytes
176162306a36Sopenharmony_ci	mov.l		%a2,%a0
176262306a36Sopenharmony_ci
176362306a36Sopenharmony_ci	bsr.l		_dmem_read_byte		# read second byte
176462306a36Sopenharmony_ci
176562306a36Sopenharmony_ci	tst.l		%d1			# dfetch error?
176662306a36Sopenharmony_ci	bne.w		movp_read_err		# yes
176762306a36Sopenharmony_ci
176862306a36Sopenharmony_ci	lsl.w		&0x8,%d2
176962306a36Sopenharmony_ci	mov.b		%d0,%d2			# append bytes
177062306a36Sopenharmony_ci
177162306a36Sopenharmony_ci	add.w		&0x2,%a2		# incr addr by 2 bytes
177262306a36Sopenharmony_ci	mov.l		%a2,%a0
177362306a36Sopenharmony_ci
177462306a36Sopenharmony_ci	bsr.l		_dmem_read_byte		# read second byte
177562306a36Sopenharmony_ci
177662306a36Sopenharmony_ci	tst.l		%d1			# dfetch error?
177762306a36Sopenharmony_ci	bne.w		movp_read_err		# yes
177862306a36Sopenharmony_ci
177962306a36Sopenharmony_ci	lsl.l		&0x8,%d2
178062306a36Sopenharmony_ci	mov.b		%d0,%d2			# append bytes
178162306a36Sopenharmony_ci
178262306a36Sopenharmony_ci	add.w		&0x2,%a2		# incr addr by 2 bytes
178362306a36Sopenharmony_ci	mov.l		%a2,%a0
178462306a36Sopenharmony_ci
178562306a36Sopenharmony_ci	bsr.l		_dmem_read_byte		# read second byte
178662306a36Sopenharmony_ci
178762306a36Sopenharmony_ci	tst.l		%d1			# dfetch error?
178862306a36Sopenharmony_ci	bne.w		movp_read_err		# yes
178962306a36Sopenharmony_ci
179062306a36Sopenharmony_ci	lsl.l		&0x8,%d2
179162306a36Sopenharmony_ci	mov.b		%d0,%d2			# append bytes
179262306a36Sopenharmony_ci
179362306a36Sopenharmony_ci	mov.b		EXC_OPWORD(%a6),%d1
179462306a36Sopenharmony_ci	lsr.b		&0x1,%d1
179562306a36Sopenharmony_ci	and.w		&0x7,%d1		# extract Dx from opcode word
179662306a36Sopenharmony_ci
179762306a36Sopenharmony_ci	mov.l		%d2,(EXC_DREGS,%a6,%d1.w*4) # store dx
179862306a36Sopenharmony_ci
179962306a36Sopenharmony_ci	rts
180062306a36Sopenharmony_ci
180162306a36Sopenharmony_ci# a0 = dst addr
180262306a36Sopenharmony_cim2rwtrans:
180362306a36Sopenharmony_ci	mov.l		%a0,%a2			# store addr
180462306a36Sopenharmony_ci
180562306a36Sopenharmony_ci	bsr.l		_dmem_read_byte		# read first byte
180662306a36Sopenharmony_ci
180762306a36Sopenharmony_ci	tst.l		%d1			# dfetch error?
180862306a36Sopenharmony_ci	bne.w		movp_read_err		# yes
180962306a36Sopenharmony_ci
181062306a36Sopenharmony_ci	mov.l		%d0,%d2
181162306a36Sopenharmony_ci
181262306a36Sopenharmony_ci	add.w		&0x2,%a2		# incr addr by 2 bytes
181362306a36Sopenharmony_ci	mov.l		%a2,%a0
181462306a36Sopenharmony_ci
181562306a36Sopenharmony_ci	bsr.l		_dmem_read_byte		# read second byte
181662306a36Sopenharmony_ci
181762306a36Sopenharmony_ci	tst.l		%d1			# dfetch error?
181862306a36Sopenharmony_ci	bne.w		movp_read_err		# yes
181962306a36Sopenharmony_ci
182062306a36Sopenharmony_ci	lsl.w		&0x8,%d2
182162306a36Sopenharmony_ci	mov.b		%d0,%d2			# append bytes
182262306a36Sopenharmony_ci
182362306a36Sopenharmony_ci	mov.b		EXC_OPWORD(%a6),%d1
182462306a36Sopenharmony_ci	lsr.b		&0x1,%d1
182562306a36Sopenharmony_ci	and.w		&0x7,%d1		# extract Dx from opcode word
182662306a36Sopenharmony_ci
182762306a36Sopenharmony_ci	mov.w		%d2,(EXC_DREGS+2,%a6,%d1.w*4) # store dx
182862306a36Sopenharmony_ci
182962306a36Sopenharmony_ci	rts
183062306a36Sopenharmony_ci
183162306a36Sopenharmony_ci# if dmem_{read,write}_byte() returns a fail message in d1, the package
183262306a36Sopenharmony_ci# must create an access error frame. here, we pass a skeleton fslw
183362306a36Sopenharmony_ci# and the failing address to the routine that creates the new frame.
183462306a36Sopenharmony_ci# FSLW:
183562306a36Sopenharmony_ci#	write = true
183662306a36Sopenharmony_ci#	size = byte
183762306a36Sopenharmony_ci#	TM = data
183862306a36Sopenharmony_ci#	software emulation error = true
183962306a36Sopenharmony_cimovp_write_err:
184062306a36Sopenharmony_ci	mov.l		%a2,%a0			# pass failing address
184162306a36Sopenharmony_ci	mov.l		&0x00a10001,%d0		# pass fslw
184262306a36Sopenharmony_ci	bra.l		isp_dacc
184362306a36Sopenharmony_ci
184462306a36Sopenharmony_ci# FSLW:
184562306a36Sopenharmony_ci#	read = true
184662306a36Sopenharmony_ci#	size = byte
184762306a36Sopenharmony_ci#	TM = data
184862306a36Sopenharmony_ci#	software emulation error = true
184962306a36Sopenharmony_cimovp_read_err:
185062306a36Sopenharmony_ci	mov.l		%a2,%a0			# pass failing address
185162306a36Sopenharmony_ci	mov.l		&0x01210001,%d0		# pass fslw
185262306a36Sopenharmony_ci	bra.l		isp_dacc
185362306a36Sopenharmony_ci
185462306a36Sopenharmony_ci#########################################################################
185562306a36Sopenharmony_ci# XDEF ****************************************************************	#
185662306a36Sopenharmony_ci#	_chk2_cmp2(): routine to emulate chk2/cmp2 instructions		#
185762306a36Sopenharmony_ci#									#
185862306a36Sopenharmony_ci# XREF ****************************************************************	#
185962306a36Sopenharmony_ci#	_calc_ea(): calculate effective address				#
186062306a36Sopenharmony_ci#	_dmem_read_long(): read operands				#
186162306a36Sopenharmony_ci#	_dmem_read_word(): read operands				#
186262306a36Sopenharmony_ci#	isp_dacc(): handle data access error exception			#
186362306a36Sopenharmony_ci#									#
186462306a36Sopenharmony_ci# INPUT ***************************************************************	#
186562306a36Sopenharmony_ci#	none								#
186662306a36Sopenharmony_ci#									#
186762306a36Sopenharmony_ci# OUTPUT **************************************************************	#
186862306a36Sopenharmony_ci#	If exiting through isp_dacc...					#
186962306a36Sopenharmony_ci#		a0 = failing address					#
187062306a36Sopenharmony_ci#		d0 = FSLW						#
187162306a36Sopenharmony_ci#	else								#
187262306a36Sopenharmony_ci#		none							#
187362306a36Sopenharmony_ci#									#
187462306a36Sopenharmony_ci# ALGORITHM ***********************************************************	#
187562306a36Sopenharmony_ci#	First, calculate the effective address, then fetch the byte,	#
187662306a36Sopenharmony_ci# word, or longword sized operands. Then, in the interest of		#
187762306a36Sopenharmony_ci# simplicity, all operands are converted to longword size whether the	#
187862306a36Sopenharmony_ci# operation is byte, word, or long. The bounds are sign extended	#
187962306a36Sopenharmony_ci# accordingly. If Rn is a data register, Rn is also sign extended. If	#
188062306a36Sopenharmony_ci# Rn is an address register, it need not be sign extended since the	#
188162306a36Sopenharmony_ci# full register is always used.						#
188262306a36Sopenharmony_ci#	The comparisons are made and the condition codes calculated.	#
188362306a36Sopenharmony_ci# If the instruction is chk2 and the Rn value is out-of-bounds, set	#
188462306a36Sopenharmony_ci# the ichk_flg in SPCOND_FLG.						#
188562306a36Sopenharmony_ci#	If the memory fetch returns a failing value, pass the failing	#
188662306a36Sopenharmony_ci# address and FSLW to the isp_dacc() routine.				#
188762306a36Sopenharmony_ci#									#
188862306a36Sopenharmony_ci#########################################################################
188962306a36Sopenharmony_ci
189062306a36Sopenharmony_ci	global		_chk2_cmp2
189162306a36Sopenharmony_ci_chk2_cmp2:
189262306a36Sopenharmony_ci
189362306a36Sopenharmony_ci# passing size parameter doesn't matter since chk2 & cmp2 can't do
189462306a36Sopenharmony_ci# either predecrement, postincrement, or immediate.
189562306a36Sopenharmony_ci	bsr.l		_calc_ea		# calculate <ea>
189662306a36Sopenharmony_ci
189762306a36Sopenharmony_ci	mov.b		EXC_EXTWORD(%a6), %d0	# fetch hi extension word
189862306a36Sopenharmony_ci	rol.b		&0x4, %d0		# rotate reg bits into lo
189962306a36Sopenharmony_ci	and.w		&0xf, %d0		# extract reg bits
190062306a36Sopenharmony_ci
190162306a36Sopenharmony_ci	mov.l		(EXC_DREGS,%a6,%d0.w*4), %d2 # get regval
190262306a36Sopenharmony_ci
190362306a36Sopenharmony_ci	cmpi.b		EXC_OPWORD(%a6), &0x2	# what size is operation?
190462306a36Sopenharmony_ci	blt.b		chk2_cmp2_byte		# size == byte
190562306a36Sopenharmony_ci	beq.b		chk2_cmp2_word		# size == word
190662306a36Sopenharmony_ci
190762306a36Sopenharmony_ci# the bounds are longword size. call routine to read the lower
190862306a36Sopenharmony_ci# bound into d0 and the higher bound into d1.
190962306a36Sopenharmony_cichk2_cmp2_long:
191062306a36Sopenharmony_ci	mov.l		%a0,%a2			# save copy of <ea>
191162306a36Sopenharmony_ci	bsr.l		_dmem_read_long		# fetch long lower bound
191262306a36Sopenharmony_ci
191362306a36Sopenharmony_ci	tst.l		%d1			# dfetch error?
191462306a36Sopenharmony_ci	bne.w		chk2_cmp2_err_l		# yes
191562306a36Sopenharmony_ci
191662306a36Sopenharmony_ci	mov.l		%d0,%d3			# save long lower bound
191762306a36Sopenharmony_ci	addq.l		&0x4,%a2
191862306a36Sopenharmony_ci	mov.l		%a2,%a0			# pass <ea> of long upper bound
191962306a36Sopenharmony_ci	bsr.l		_dmem_read_long		# fetch long upper bound
192062306a36Sopenharmony_ci
192162306a36Sopenharmony_ci	tst.l		%d1			# dfetch error?
192262306a36Sopenharmony_ci	bne.w		chk2_cmp2_err_l		# yes
192362306a36Sopenharmony_ci
192462306a36Sopenharmony_ci	mov.l		%d0,%d1			# long upper bound in d1
192562306a36Sopenharmony_ci	mov.l		%d3,%d0			# long lower bound in d0
192662306a36Sopenharmony_ci	bra.w		chk2_cmp2_compare	# go do the compare emulation
192762306a36Sopenharmony_ci
192862306a36Sopenharmony_ci# the bounds are word size. fetch them in one subroutine call by
192962306a36Sopenharmony_ci# reading a longword. sign extend both. if it's a data operation,
193062306a36Sopenharmony_ci# sign extend Rn to long, also.
193162306a36Sopenharmony_cichk2_cmp2_word:
193262306a36Sopenharmony_ci	mov.l		%a0,%a2
193362306a36Sopenharmony_ci	bsr.l		_dmem_read_long		# fetch 2 word bounds
193462306a36Sopenharmony_ci
193562306a36Sopenharmony_ci	tst.l		%d1			# dfetch error?
193662306a36Sopenharmony_ci	bne.w		chk2_cmp2_err_l		# yes
193762306a36Sopenharmony_ci
193862306a36Sopenharmony_ci	mov.w		%d0, %d1		# place hi in %d1
193962306a36Sopenharmony_ci	swap		%d0			# place lo in %d0
194062306a36Sopenharmony_ci
194162306a36Sopenharmony_ci	ext.l		%d0			# sign extend lo bnd
194262306a36Sopenharmony_ci	ext.l		%d1			# sign extend hi bnd
194362306a36Sopenharmony_ci
194462306a36Sopenharmony_ci	btst		&0x7, EXC_EXTWORD(%a6)	# address compare?
194562306a36Sopenharmony_ci	bne.w		chk2_cmp2_compare	# yes; don't sign extend
194662306a36Sopenharmony_ci
194762306a36Sopenharmony_ci# operation is a data register compare.
194862306a36Sopenharmony_ci# sign extend word to long so we can do simple longword compares.
194962306a36Sopenharmony_ci	ext.l		%d2			# sign extend data word
195062306a36Sopenharmony_ci	bra.w		chk2_cmp2_compare	# go emulate compare
195162306a36Sopenharmony_ci
195262306a36Sopenharmony_ci# the bounds are byte size. fetch them in one subroutine call by
195362306a36Sopenharmony_ci# reading a word. sign extend both. if it's a data operation,
195462306a36Sopenharmony_ci# sign extend Rn to long, also.
195562306a36Sopenharmony_cichk2_cmp2_byte:
195662306a36Sopenharmony_ci	mov.l		%a0,%a2
195762306a36Sopenharmony_ci	bsr.l		_dmem_read_word		# fetch 2 byte bounds
195862306a36Sopenharmony_ci
195962306a36Sopenharmony_ci	tst.l		%d1			# dfetch error?
196062306a36Sopenharmony_ci	bne.w		chk2_cmp2_err_w		# yes
196162306a36Sopenharmony_ci
196262306a36Sopenharmony_ci	mov.b		%d0, %d1		# place hi in %d1
196362306a36Sopenharmony_ci	lsr.w		&0x8, %d0		# place lo in %d0
196462306a36Sopenharmony_ci
196562306a36Sopenharmony_ci	extb.l		%d0			# sign extend lo bnd
196662306a36Sopenharmony_ci	extb.l		%d1			# sign extend hi bnd
196762306a36Sopenharmony_ci
196862306a36Sopenharmony_ci	btst		&0x7, EXC_EXTWORD(%a6)	# address compare?
196962306a36Sopenharmony_ci	bne.b		chk2_cmp2_compare	# yes; don't sign extend
197062306a36Sopenharmony_ci
197162306a36Sopenharmony_ci# operation is a data register compare.
197262306a36Sopenharmony_ci# sign extend byte to long so we can do simple longword compares.
197362306a36Sopenharmony_ci	extb.l		%d2			# sign extend data byte
197462306a36Sopenharmony_ci
197562306a36Sopenharmony_ci#
197662306a36Sopenharmony_ci# To set the ccodes correctly:
197762306a36Sopenharmony_ci#	(1) save 'Z' bit from (Rn - lo)
197862306a36Sopenharmony_ci#	(2) save 'Z' and 'N' bits from ((hi - lo) - (Rn - hi))
197962306a36Sopenharmony_ci#	(3) keep 'X', 'N', and 'V' from before instruction
198062306a36Sopenharmony_ci#	(4) combine ccodes
198162306a36Sopenharmony_ci#
198262306a36Sopenharmony_cichk2_cmp2_compare:
198362306a36Sopenharmony_ci	sub.l		%d0, %d2		# (Rn - lo)
198462306a36Sopenharmony_ci	mov.w		%cc, %d3		# fetch resulting ccodes
198562306a36Sopenharmony_ci	andi.b		&0x4, %d3		# keep 'Z' bit
198662306a36Sopenharmony_ci	sub.l		%d0, %d1		# (hi - lo)
198762306a36Sopenharmony_ci	cmp.l		%d1,%d2			# ((hi - lo) - (Rn - hi))
198862306a36Sopenharmony_ci
198962306a36Sopenharmony_ci	mov.w		%cc, %d4		# fetch resulting ccodes
199062306a36Sopenharmony_ci	or.b		%d4, %d3		# combine w/ earlier ccodes
199162306a36Sopenharmony_ci	andi.b		&0x5, %d3		# keep 'Z' and 'N'
199262306a36Sopenharmony_ci
199362306a36Sopenharmony_ci	mov.w		EXC_CC(%a6), %d4	# fetch old ccodes
199462306a36Sopenharmony_ci	andi.b		&0x1a, %d4		# keep 'X','N','V' bits
199562306a36Sopenharmony_ci	or.b		%d3, %d4		# insert new ccodes
199662306a36Sopenharmony_ci	mov.w		%d4, EXC_CC(%a6)	# save new ccodes
199762306a36Sopenharmony_ci
199862306a36Sopenharmony_ci	btst		&0x3, EXC_EXTWORD(%a6)	# separate chk2,cmp2
199962306a36Sopenharmony_ci	bne.b		chk2_finish		# it's a chk2
200062306a36Sopenharmony_ci
200162306a36Sopenharmony_ci	rts
200262306a36Sopenharmony_ci
200362306a36Sopenharmony_ci# this code handles the only difference between chk2 and cmp2. chk2 would
200462306a36Sopenharmony_ci# have trapped out if the value was out of bounds. we check this by seeing
200562306a36Sopenharmony_ci# if the 'N' bit was set by the operation.
200662306a36Sopenharmony_cichk2_finish:
200762306a36Sopenharmony_ci	btst		&0x0, %d4		# is 'N' bit set?
200862306a36Sopenharmony_ci	bne.b		chk2_trap		# yes;chk2 should trap
200962306a36Sopenharmony_ci	rts
201062306a36Sopenharmony_cichk2_trap:
201162306a36Sopenharmony_ci	mov.b		&ichk_flg,SPCOND_FLG(%a6) # set "special case" flag
201262306a36Sopenharmony_ci	rts
201362306a36Sopenharmony_ci
201462306a36Sopenharmony_ci# if dmem_read_{long,word}() returns a fail message in d1, the package
201562306a36Sopenharmony_ci# must create an access error frame. here, we pass a skeleton fslw
201662306a36Sopenharmony_ci# and the failing address to the routine that creates the new frame.
201762306a36Sopenharmony_ci# FSLW:
201862306a36Sopenharmony_ci#	read = true
201962306a36Sopenharmony_ci#	size = longword
202062306a36Sopenharmony_ci#	TM = data
202162306a36Sopenharmony_ci#	software emulation error = true
202262306a36Sopenharmony_cichk2_cmp2_err_l:
202362306a36Sopenharmony_ci	mov.l		%a2,%a0			# pass failing address
202462306a36Sopenharmony_ci	mov.l		&0x01010001,%d0		# pass fslw
202562306a36Sopenharmony_ci	bra.l		isp_dacc
202662306a36Sopenharmony_ci
202762306a36Sopenharmony_ci# FSLW:
202862306a36Sopenharmony_ci#	read = true
202962306a36Sopenharmony_ci#	size = word
203062306a36Sopenharmony_ci#	TM = data
203162306a36Sopenharmony_ci#	software emulation error = true
203262306a36Sopenharmony_cichk2_cmp2_err_w:
203362306a36Sopenharmony_ci	mov.l		%a2,%a0			# pass failing address
203462306a36Sopenharmony_ci	mov.l		&0x01410001,%d0		# pass fslw
203562306a36Sopenharmony_ci	bra.l		isp_dacc
203662306a36Sopenharmony_ci
203762306a36Sopenharmony_ci#########################################################################
203862306a36Sopenharmony_ci# XDEF ****************************************************************	#
203962306a36Sopenharmony_ci#	_div64(): routine to emulate div{u,s}.l <ea>,Dr:Dq		#
204062306a36Sopenharmony_ci#							64/32->32r:32q	#
204162306a36Sopenharmony_ci#									#
204262306a36Sopenharmony_ci# XREF ****************************************************************	#
204362306a36Sopenharmony_ci#	_calc_ea() - calculate effective address			#
204462306a36Sopenharmony_ci#	isp_iacc() - handle instruction access error exception		#
204562306a36Sopenharmony_ci#	isp_dacc() - handle data access error exception			#
204662306a36Sopenharmony_ci#	isp_restore() - restore An on access error w/ -() or ()+	#
204762306a36Sopenharmony_ci#									#
204862306a36Sopenharmony_ci# INPUT ***************************************************************	#
204962306a36Sopenharmony_ci#	none								#
205062306a36Sopenharmony_ci#									#
205162306a36Sopenharmony_ci# OUTPUT **************************************************************	#
205262306a36Sopenharmony_ci#	If exiting through isp_dacc...					#
205362306a36Sopenharmony_ci#		a0 = failing address					#
205462306a36Sopenharmony_ci#		d0 = FSLW						#
205562306a36Sopenharmony_ci#	else								#
205662306a36Sopenharmony_ci#		none							#
205762306a36Sopenharmony_ci#									#
205862306a36Sopenharmony_ci# ALGORITHM ***********************************************************	#
205962306a36Sopenharmony_ci#	First, decode the operand location. If it's in Dn, fetch from	#
206062306a36Sopenharmony_ci# the stack. If it's in memory, use _calc_ea() to calculate the		#
206162306a36Sopenharmony_ci# effective address. Use _dmem_read_long() to fetch at that address.	#
206262306a36Sopenharmony_ci# Unless the operand is immediate data. Then use _imem_read_long().	#
206362306a36Sopenharmony_ci# Send failures to isp_dacc() or isp_iacc() as appropriate.		#
206462306a36Sopenharmony_ci#	If the operands are signed, make them unsigned and save	the	#
206562306a36Sopenharmony_ci# sign info for later. Separate out special cases like divide-by-zero	#
206662306a36Sopenharmony_ci# or 32-bit divides if possible. Else, use a special math algorithm	#
206762306a36Sopenharmony_ci# to calculate the result.						#
206862306a36Sopenharmony_ci#	Restore sign info if signed instruction. Set the condition	#
206962306a36Sopenharmony_ci# codes. Set idbyz_flg in SPCOND_FLG if divisor was zero. Store the	#
207062306a36Sopenharmony_ci# quotient and remainder in the appropriate data registers on the stack.#
207162306a36Sopenharmony_ci#									#
207262306a36Sopenharmony_ci#########################################################################
207362306a36Sopenharmony_ci
207462306a36Sopenharmony_ciset	NDIVISOR,	EXC_TEMP+0x0
207562306a36Sopenharmony_ciset	NDIVIDEND,	EXC_TEMP+0x1
207662306a36Sopenharmony_ciset	NDRSAVE,	EXC_TEMP+0x2
207762306a36Sopenharmony_ciset	NDQSAVE,	EXC_TEMP+0x4
207862306a36Sopenharmony_ciset	DDSECOND,	EXC_TEMP+0x6
207962306a36Sopenharmony_ciset	DDQUOTIENT,	EXC_TEMP+0x8
208062306a36Sopenharmony_ciset	DDNORMAL,	EXC_TEMP+0xc
208162306a36Sopenharmony_ci
208262306a36Sopenharmony_ci	global		_div64
208362306a36Sopenharmony_ci#############
208462306a36Sopenharmony_ci# div(u,s)l #
208562306a36Sopenharmony_ci#############
208662306a36Sopenharmony_ci_div64:
208762306a36Sopenharmony_ci	mov.b		EXC_OPWORD+1(%a6), %d0
208862306a36Sopenharmony_ci	andi.b		&0x38, %d0		# extract src mode
208962306a36Sopenharmony_ci
209062306a36Sopenharmony_ci	bne.w		dcontrolmodel_s		# %dn dest or control mode?
209162306a36Sopenharmony_ci
209262306a36Sopenharmony_ci	mov.b		EXC_OPWORD+1(%a6), %d0	# extract Dn from opcode
209362306a36Sopenharmony_ci	andi.w		&0x7, %d0
209462306a36Sopenharmony_ci	mov.l		(EXC_DREGS,%a6,%d0.w*4), %d7 # fetch divisor from register
209562306a36Sopenharmony_ci
209662306a36Sopenharmony_cidgotsrcl:
209762306a36Sopenharmony_ci	beq.w		div64eq0		# divisor is = 0!!!
209862306a36Sopenharmony_ci
209962306a36Sopenharmony_ci	mov.b		EXC_EXTWORD+1(%a6), %d0	# extract Dr from extword
210062306a36Sopenharmony_ci	mov.b		EXC_EXTWORD(%a6), %d1	# extract Dq from extword
210162306a36Sopenharmony_ci	and.w		&0x7, %d0
210262306a36Sopenharmony_ci	lsr.b		&0x4, %d1
210362306a36Sopenharmony_ci	and.w		&0x7, %d1
210462306a36Sopenharmony_ci	mov.w		%d0, NDRSAVE(%a6)	# save Dr for later
210562306a36Sopenharmony_ci	mov.w		%d1, NDQSAVE(%a6)	# save Dq for later
210662306a36Sopenharmony_ci
210762306a36Sopenharmony_ci# fetch %dr and %dq directly off stack since all regs are saved there
210862306a36Sopenharmony_ci	mov.l		(EXC_DREGS,%a6,%d0.w*4), %d5 # get dividend hi
210962306a36Sopenharmony_ci	mov.l		(EXC_DREGS,%a6,%d1.w*4), %d6 # get dividend lo
211062306a36Sopenharmony_ci
211162306a36Sopenharmony_ci# separate signed and unsigned divide
211262306a36Sopenharmony_ci	btst		&0x3, EXC_EXTWORD(%a6)	# signed or unsigned?
211362306a36Sopenharmony_ci	beq.b		dspecialcases		# use positive divide
211462306a36Sopenharmony_ci
211562306a36Sopenharmony_ci# save the sign of the divisor
211662306a36Sopenharmony_ci# make divisor unsigned if it's negative
211762306a36Sopenharmony_ci	tst.l		%d7			# chk sign of divisor
211862306a36Sopenharmony_ci	slt		NDIVISOR(%a6)		# save sign of divisor
211962306a36Sopenharmony_ci	bpl.b		dsgndividend
212062306a36Sopenharmony_ci	neg.l		%d7			# complement negative divisor
212162306a36Sopenharmony_ci
212262306a36Sopenharmony_ci# save the sign of the dividend
212362306a36Sopenharmony_ci# make dividend unsigned if it's negative
212462306a36Sopenharmony_cidsgndividend:
212562306a36Sopenharmony_ci	tst.l		%d5			# chk sign of hi(dividend)
212662306a36Sopenharmony_ci	slt		NDIVIDEND(%a6)		# save sign of dividend
212762306a36Sopenharmony_ci	bpl.b		dspecialcases
212862306a36Sopenharmony_ci
212962306a36Sopenharmony_ci	mov.w		&0x0, %cc		# clear 'X' cc bit
213062306a36Sopenharmony_ci	negx.l		%d6			# complement signed dividend
213162306a36Sopenharmony_ci	negx.l		%d5
213262306a36Sopenharmony_ci
213362306a36Sopenharmony_ci# extract some special cases:
213462306a36Sopenharmony_ci#	- is (dividend == 0) ?
213562306a36Sopenharmony_ci#	- is (hi(dividend) == 0 && (divisor <= lo(dividend))) ? (32-bit div)
213662306a36Sopenharmony_cidspecialcases:
213762306a36Sopenharmony_ci	tst.l		%d5			# is (hi(dividend) == 0)
213862306a36Sopenharmony_ci	bne.b		dnormaldivide		# no, so try it the long way
213962306a36Sopenharmony_ci
214062306a36Sopenharmony_ci	tst.l		%d6			# is (lo(dividend) == 0), too
214162306a36Sopenharmony_ci	beq.w		ddone			# yes, so (dividend == 0)
214262306a36Sopenharmony_ci
214362306a36Sopenharmony_ci	cmp.l		%d7,%d6			# is (divisor <= lo(dividend))
214462306a36Sopenharmony_ci	bls.b		d32bitdivide		# yes, so use 32 bit divide
214562306a36Sopenharmony_ci
214662306a36Sopenharmony_ci	exg		%d5,%d6			# q = 0, r = dividend
214762306a36Sopenharmony_ci	bra.w		divfinish		# can't divide, we're done.
214862306a36Sopenharmony_ci
214962306a36Sopenharmony_cid32bitdivide:
215062306a36Sopenharmony_ci	tdivu.l		%d7, %d5:%d6		# it's only a 32/32 bit div!
215162306a36Sopenharmony_ci
215262306a36Sopenharmony_ci	bra.b		divfinish
215362306a36Sopenharmony_ci
215462306a36Sopenharmony_cidnormaldivide:
215562306a36Sopenharmony_ci# last special case:
215662306a36Sopenharmony_ci#	- is hi(dividend) >= divisor ? if yes, then overflow
215762306a36Sopenharmony_ci	cmp.l		%d7,%d5
215862306a36Sopenharmony_ci	bls.b		ddovf			# answer won't fit in 32 bits
215962306a36Sopenharmony_ci
216062306a36Sopenharmony_ci# perform the divide algorithm:
216162306a36Sopenharmony_ci	bsr.l		dclassical		# do int divide
216262306a36Sopenharmony_ci
216362306a36Sopenharmony_ci# separate into signed and unsigned finishes.
216462306a36Sopenharmony_cidivfinish:
216562306a36Sopenharmony_ci	btst		&0x3, EXC_EXTWORD(%a6)	# do divs, divu separately
216662306a36Sopenharmony_ci	beq.b		ddone			# divu has no processing!!!
216762306a36Sopenharmony_ci
216862306a36Sopenharmony_ci# it was a divs.l, so ccode setting is a little more complicated...
216962306a36Sopenharmony_ci	tst.b		NDIVIDEND(%a6)		# remainder has same sign
217062306a36Sopenharmony_ci	beq.b		dcc			# as dividend.
217162306a36Sopenharmony_ci	neg.l		%d5			# sgn(rem) = sgn(dividend)
217262306a36Sopenharmony_cidcc:
217362306a36Sopenharmony_ci	mov.b		NDIVISOR(%a6), %d0
217462306a36Sopenharmony_ci	eor.b		%d0, NDIVIDEND(%a6)	# chk if quotient is negative
217562306a36Sopenharmony_ci	beq.b		dqpos			# branch to quot positive
217662306a36Sopenharmony_ci
217762306a36Sopenharmony_ci# 0x80000000 is the largest number representable as a 32-bit negative
217862306a36Sopenharmony_ci# number. the negative of 0x80000000 is 0x80000000.
217962306a36Sopenharmony_ci	cmpi.l		%d6, &0x80000000	# will (-quot) fit in 32 bits?
218062306a36Sopenharmony_ci	bhi.b		ddovf
218162306a36Sopenharmony_ci
218262306a36Sopenharmony_ci	neg.l		%d6			# make (-quot) 2's comp
218362306a36Sopenharmony_ci
218462306a36Sopenharmony_ci	bra.b		ddone
218562306a36Sopenharmony_ci
218662306a36Sopenharmony_cidqpos:
218762306a36Sopenharmony_ci	btst		&0x1f, %d6		# will (+quot) fit in 32 bits?
218862306a36Sopenharmony_ci	bne.b		ddovf
218962306a36Sopenharmony_ci
219062306a36Sopenharmony_ciddone:
219162306a36Sopenharmony_ci# at this point, result is normal so ccodes are set based on result.
219262306a36Sopenharmony_ci	mov.w		EXC_CC(%a6), %cc
219362306a36Sopenharmony_ci	tst.l		%d6			# set %ccode bits
219462306a36Sopenharmony_ci	mov.w		%cc, EXC_CC(%a6)
219562306a36Sopenharmony_ci
219662306a36Sopenharmony_ci	mov.w		NDRSAVE(%a6), %d0	# get Dr off stack
219762306a36Sopenharmony_ci	mov.w		NDQSAVE(%a6), %d1	# get Dq off stack
219862306a36Sopenharmony_ci
219962306a36Sopenharmony_ci# if the register numbers are the same, only the quotient gets saved.
220062306a36Sopenharmony_ci# so, if we always save the quotient second, we save ourselves a cmp&beq
220162306a36Sopenharmony_ci	mov.l		%d5, (EXC_DREGS,%a6,%d0.w*4) # save remainder
220262306a36Sopenharmony_ci	mov.l		%d6, (EXC_DREGS,%a6,%d1.w*4) # save quotient
220362306a36Sopenharmony_ci
220462306a36Sopenharmony_ci	rts
220562306a36Sopenharmony_ci
220662306a36Sopenharmony_ciddovf:
220762306a36Sopenharmony_ci	bset		&0x1, EXC_CC+1(%a6)	# 'V' set on overflow
220862306a36Sopenharmony_ci	bclr		&0x0, EXC_CC+1(%a6)	# 'C' cleared on overflow
220962306a36Sopenharmony_ci
221062306a36Sopenharmony_ci	rts
221162306a36Sopenharmony_ci
221262306a36Sopenharmony_cidiv64eq0:
221362306a36Sopenharmony_ci	andi.b		&0x1e, EXC_CC+1(%a6)	# clear 'C' bit on divbyzero
221462306a36Sopenharmony_ci	ori.b		&idbyz_flg,SPCOND_FLG(%a6) # set "special case" flag
221562306a36Sopenharmony_ci	rts
221662306a36Sopenharmony_ci
221762306a36Sopenharmony_ci###########################################################################
221862306a36Sopenharmony_ci#########################################################################
221962306a36Sopenharmony_ci# This routine uses the 'classical' Algorithm D from Donald Knuth's	#
222062306a36Sopenharmony_ci# Art of Computer Programming, vol II, Seminumerical Algorithms.	#
222162306a36Sopenharmony_ci# For this implementation b=2**16, and the target is U1U2U3U4/V1V2,	#
222262306a36Sopenharmony_ci# where U,V are words of the quadword dividend and longword divisor,	#
222362306a36Sopenharmony_ci# and U1, V1 are the most significant words.				#
222462306a36Sopenharmony_ci#									#
222562306a36Sopenharmony_ci# The most sig. longword of the 64 bit dividend must be in %d5, least	#
222662306a36Sopenharmony_ci# in %d6. The divisor must be in the variable ddivisor, and the		#
222762306a36Sopenharmony_ci# signed/unsigned flag ddusign must be set (0=unsigned,1=signed).	#
222862306a36Sopenharmony_ci# The quotient is returned in %d6, remainder in %d5, unless the		#
222962306a36Sopenharmony_ci# v (overflow) bit is set in the saved %ccr. If overflow, the dividend	#
223062306a36Sopenharmony_ci# is unchanged.								#
223162306a36Sopenharmony_ci#########################################################################
223262306a36Sopenharmony_cidclassical:
223362306a36Sopenharmony_ci# if the divisor msw is 0, use simpler algorithm then the full blown
223462306a36Sopenharmony_ci# one at ddknuth:
223562306a36Sopenharmony_ci
223662306a36Sopenharmony_ci	cmpi.l		%d7, &0xffff
223762306a36Sopenharmony_ci	bhi.b		ddknuth			# go use D. Knuth algorithm
223862306a36Sopenharmony_ci
223962306a36Sopenharmony_ci# Since the divisor is only a word (and larger than the mslw of the dividend),
224062306a36Sopenharmony_ci# a simpler algorithm may be used :
224162306a36Sopenharmony_ci# In the general case, four quotient words would be created by
224262306a36Sopenharmony_ci# dividing the divisor word into each dividend word. In this case,
224362306a36Sopenharmony_ci# the first two quotient words must be zero, or overflow would occur.
224462306a36Sopenharmony_ci# Since we already checked this case above, we can treat the most significant
224562306a36Sopenharmony_ci# longword of the dividend as (0) remainder (see Knuth) and merely complete
224662306a36Sopenharmony_ci# the last two divisions to get a quotient longword and word remainder:
224762306a36Sopenharmony_ci
224862306a36Sopenharmony_ci	clr.l		%d1
224962306a36Sopenharmony_ci	swap		%d5			# same as r*b if previous step rqd
225062306a36Sopenharmony_ci	swap		%d6			# get u3 to lsw position
225162306a36Sopenharmony_ci	mov.w		%d6, %d5		# rb + u3
225262306a36Sopenharmony_ci
225362306a36Sopenharmony_ci	divu.w		%d7, %d5
225462306a36Sopenharmony_ci
225562306a36Sopenharmony_ci	mov.w		%d5, %d1		# first quotient word
225662306a36Sopenharmony_ci	swap		%d6			# get u4
225762306a36Sopenharmony_ci	mov.w		%d6, %d5		# rb + u4
225862306a36Sopenharmony_ci
225962306a36Sopenharmony_ci	divu.w		%d7, %d5
226062306a36Sopenharmony_ci
226162306a36Sopenharmony_ci	swap		%d1
226262306a36Sopenharmony_ci	mov.w		%d5, %d1		# 2nd quotient 'digit'
226362306a36Sopenharmony_ci	clr.w		%d5
226462306a36Sopenharmony_ci	swap		%d5			# now remainder
226562306a36Sopenharmony_ci	mov.l		%d1, %d6		# and quotient
226662306a36Sopenharmony_ci
226762306a36Sopenharmony_ci	rts
226862306a36Sopenharmony_ci
226962306a36Sopenharmony_ciddknuth:
227062306a36Sopenharmony_ci# In this algorithm, the divisor is treated as a 2 digit (word) number
227162306a36Sopenharmony_ci# which is divided into a 3 digit (word) dividend to get one quotient
227262306a36Sopenharmony_ci# digit (word). After subtraction, the dividend is shifted and the
227362306a36Sopenharmony_ci# process repeated. Before beginning, the divisor and quotient are
227462306a36Sopenharmony_ci# 'normalized' so that the process of estimating the quotient digit
227562306a36Sopenharmony_ci# will yield verifiably correct results..
227662306a36Sopenharmony_ci
227762306a36Sopenharmony_ci	clr.l		DDNORMAL(%a6)		# count of shifts for normalization
227862306a36Sopenharmony_ci	clr.b		DDSECOND(%a6)		# clear flag for quotient digits
227962306a36Sopenharmony_ci	clr.l		%d1			# %d1 will hold trial quotient
228062306a36Sopenharmony_ciddnchk:
228162306a36Sopenharmony_ci	btst		&31, %d7		# must we normalize? first word of
228262306a36Sopenharmony_ci	bne.b		ddnormalized		# divisor (V1) must be >= 65536/2
228362306a36Sopenharmony_ci	addq.l		&0x1, DDNORMAL(%a6)	# count normalization shifts
228462306a36Sopenharmony_ci	lsl.l		&0x1, %d7		# shift the divisor
228562306a36Sopenharmony_ci	lsl.l		&0x1, %d6		# shift u4,u3 with overflow to u2
228662306a36Sopenharmony_ci	roxl.l		&0x1, %d5		# shift u1,u2
228762306a36Sopenharmony_ci	bra.w		ddnchk
228862306a36Sopenharmony_ciddnormalized:
228962306a36Sopenharmony_ci
229062306a36Sopenharmony_ci# Now calculate an estimate of the quotient words (msw first, then lsw).
229162306a36Sopenharmony_ci# The comments use subscripts for the first quotient digit determination.
229262306a36Sopenharmony_ci	mov.l		%d7, %d3		# divisor
229362306a36Sopenharmony_ci	mov.l		%d5, %d2		# dividend mslw
229462306a36Sopenharmony_ci	swap		%d2
229562306a36Sopenharmony_ci	swap		%d3
229662306a36Sopenharmony_ci	cmp.w		%d2, %d3		# V1 = U1 ?
229762306a36Sopenharmony_ci	bne.b		ddqcalc1
229862306a36Sopenharmony_ci	mov.w		&0xffff, %d1		# use max trial quotient word
229962306a36Sopenharmony_ci	bra.b		ddadj0
230062306a36Sopenharmony_ciddqcalc1:
230162306a36Sopenharmony_ci	mov.l		%d5, %d1
230262306a36Sopenharmony_ci
230362306a36Sopenharmony_ci	divu.w		%d3, %d1		# use quotient of mslw/msw
230462306a36Sopenharmony_ci
230562306a36Sopenharmony_ci	andi.l		&0x0000ffff, %d1	# zero any remainder
230662306a36Sopenharmony_ciddadj0:
230762306a36Sopenharmony_ci
230862306a36Sopenharmony_ci# now test the trial quotient and adjust. This step plus the
230962306a36Sopenharmony_ci# normalization assures (according to Knuth) that the trial
231062306a36Sopenharmony_ci# quotient will be at worst 1 too large.
231162306a36Sopenharmony_ci	mov.l		%d6, -(%sp)
231262306a36Sopenharmony_ci	clr.w		%d6			# word u3 left
231362306a36Sopenharmony_ci	swap		%d6			# in lsw position
231462306a36Sopenharmony_ciddadj1: mov.l		%d7, %d3
231562306a36Sopenharmony_ci	mov.l		%d1, %d2
231662306a36Sopenharmony_ci	mulu.w		%d7, %d2		# V2q
231762306a36Sopenharmony_ci	swap		%d3
231862306a36Sopenharmony_ci	mulu.w		%d1, %d3		# V1q
231962306a36Sopenharmony_ci	mov.l		%d5, %d4		# U1U2
232062306a36Sopenharmony_ci	sub.l		%d3, %d4		# U1U2 - V1q
232162306a36Sopenharmony_ci
232262306a36Sopenharmony_ci	swap		%d4
232362306a36Sopenharmony_ci
232462306a36Sopenharmony_ci	mov.w		%d4,%d0
232562306a36Sopenharmony_ci	mov.w		%d6,%d4			# insert lower word (U3)
232662306a36Sopenharmony_ci
232762306a36Sopenharmony_ci	tst.w		%d0			# is upper word set?
232862306a36Sopenharmony_ci	bne.w		ddadjd1
232962306a36Sopenharmony_ci
233062306a36Sopenharmony_ci#	add.l		%d6, %d4		# (U1U2 - V1q) + U3
233162306a36Sopenharmony_ci
233262306a36Sopenharmony_ci	cmp.l		%d2, %d4
233362306a36Sopenharmony_ci	bls.b		ddadjd1			# is V2q > (U1U2-V1q) + U3 ?
233462306a36Sopenharmony_ci	subq.l		&0x1, %d1		# yes, decrement and recheck
233562306a36Sopenharmony_ci	bra.b		ddadj1
233662306a36Sopenharmony_ciddadjd1:
233762306a36Sopenharmony_ci# now test the word by multiplying it by the divisor (V1V2) and comparing
233862306a36Sopenharmony_ci# the 3 digit (word) result with the current dividend words
233962306a36Sopenharmony_ci	mov.l		%d5, -(%sp)		# save %d5 (%d6 already saved)
234062306a36Sopenharmony_ci	mov.l		%d1, %d6
234162306a36Sopenharmony_ci	swap		%d6			# shift answer to ms 3 words
234262306a36Sopenharmony_ci	mov.l		%d7, %d5
234362306a36Sopenharmony_ci	bsr.l		dmm2
234462306a36Sopenharmony_ci	mov.l		%d5, %d2		# now %d2,%d3 are trial*divisor
234562306a36Sopenharmony_ci	mov.l		%d6, %d3
234662306a36Sopenharmony_ci	mov.l		(%sp)+, %d5		# restore dividend
234762306a36Sopenharmony_ci	mov.l		(%sp)+, %d6
234862306a36Sopenharmony_ci	sub.l		%d3, %d6
234962306a36Sopenharmony_ci	subx.l		%d2, %d5		# subtract double precision
235062306a36Sopenharmony_ci	bcc		dd2nd			# no carry, do next quotient digit
235162306a36Sopenharmony_ci	subq.l		&0x1, %d1		# q is one too large
235262306a36Sopenharmony_ci# need to add back divisor longword to current ms 3 digits of dividend
235362306a36Sopenharmony_ci# - according to Knuth, this is done only 2 out of 65536 times for random
235462306a36Sopenharmony_ci# divisor, dividend selection.
235562306a36Sopenharmony_ci	clr.l		%d2
235662306a36Sopenharmony_ci	mov.l		%d7, %d3
235762306a36Sopenharmony_ci	swap		%d3
235862306a36Sopenharmony_ci	clr.w		%d3			# %d3 now ls word of divisor
235962306a36Sopenharmony_ci	add.l		%d3, %d6		# aligned with 3rd word of dividend
236062306a36Sopenharmony_ci	addx.l		%d2, %d5
236162306a36Sopenharmony_ci	mov.l		%d7, %d3
236262306a36Sopenharmony_ci	clr.w		%d3			# %d3 now ms word of divisor
236362306a36Sopenharmony_ci	swap		%d3			# aligned with 2nd word of dividend
236462306a36Sopenharmony_ci	add.l		%d3, %d5
236562306a36Sopenharmony_cidd2nd:
236662306a36Sopenharmony_ci	tst.b		DDSECOND(%a6)		# both q words done?
236762306a36Sopenharmony_ci	bne.b		ddremain
236862306a36Sopenharmony_ci# first quotient digit now correct. store digit and shift the
236962306a36Sopenharmony_ci# (subtracted) dividend
237062306a36Sopenharmony_ci	mov.w		%d1, DDQUOTIENT(%a6)
237162306a36Sopenharmony_ci	clr.l		%d1
237262306a36Sopenharmony_ci	swap		%d5
237362306a36Sopenharmony_ci	swap		%d6
237462306a36Sopenharmony_ci	mov.w		%d6, %d5
237562306a36Sopenharmony_ci	clr.w		%d6
237662306a36Sopenharmony_ci	st		DDSECOND(%a6)		# second digit
237762306a36Sopenharmony_ci	bra.w		ddnormalized
237862306a36Sopenharmony_ciddremain:
237962306a36Sopenharmony_ci# add 2nd word to quotient, get the remainder.
238062306a36Sopenharmony_ci	mov.w		%d1, DDQUOTIENT+2(%a6)
238162306a36Sopenharmony_ci# shift down one word/digit to renormalize remainder.
238262306a36Sopenharmony_ci	mov.w		%d5, %d6
238362306a36Sopenharmony_ci	swap		%d6
238462306a36Sopenharmony_ci	swap		%d5
238562306a36Sopenharmony_ci	mov.l		DDNORMAL(%a6), %d7	# get norm shift count
238662306a36Sopenharmony_ci	beq.b		ddrn
238762306a36Sopenharmony_ci	subq.l		&0x1, %d7		# set for loop count
238862306a36Sopenharmony_ciddnlp:
238962306a36Sopenharmony_ci	lsr.l		&0x1, %d5		# shift into %d6
239062306a36Sopenharmony_ci	roxr.l		&0x1, %d6
239162306a36Sopenharmony_ci	dbf		%d7, ddnlp
239262306a36Sopenharmony_ciddrn:
239362306a36Sopenharmony_ci	mov.l		%d6, %d5		# remainder
239462306a36Sopenharmony_ci	mov.l		DDQUOTIENT(%a6), %d6	# quotient
239562306a36Sopenharmony_ci
239662306a36Sopenharmony_ci	rts
239762306a36Sopenharmony_cidmm2:
239862306a36Sopenharmony_ci# factors for the 32X32->64 multiplication are in %d5 and %d6.
239962306a36Sopenharmony_ci# returns 64 bit result in %d5 (hi) %d6(lo).
240062306a36Sopenharmony_ci# destroys %d2,%d3,%d4.
240162306a36Sopenharmony_ci
240262306a36Sopenharmony_ci# multiply hi,lo words of each factor to get 4 intermediate products
240362306a36Sopenharmony_ci	mov.l		%d6, %d2
240462306a36Sopenharmony_ci	mov.l		%d6, %d3
240562306a36Sopenharmony_ci	mov.l		%d5, %d4
240662306a36Sopenharmony_ci	swap		%d3
240762306a36Sopenharmony_ci	swap		%d4
240862306a36Sopenharmony_ci	mulu.w		%d5, %d6		# %d6 <- lsw*lsw
240962306a36Sopenharmony_ci	mulu.w		%d3, %d5		# %d5 <- msw-dest*lsw-source
241062306a36Sopenharmony_ci	mulu.w		%d4, %d2		# %d2 <- msw-source*lsw-dest
241162306a36Sopenharmony_ci	mulu.w		%d4, %d3		# %d3 <- msw*msw
241262306a36Sopenharmony_ci# now use swap and addx to consolidate to two longwords
241362306a36Sopenharmony_ci	clr.l		%d4
241462306a36Sopenharmony_ci	swap		%d6
241562306a36Sopenharmony_ci	add.w		%d5, %d6		# add msw of l*l to lsw of m*l product
241662306a36Sopenharmony_ci	addx.w		%d4, %d3		# add any carry to m*m product
241762306a36Sopenharmony_ci	add.w		%d2, %d6		# add in lsw of other m*l product
241862306a36Sopenharmony_ci	addx.w		%d4, %d3		# add any carry to m*m product
241962306a36Sopenharmony_ci	swap		%d6			# %d6 is low 32 bits of final product
242062306a36Sopenharmony_ci	clr.w		%d5
242162306a36Sopenharmony_ci	clr.w		%d2			# lsw of two mixed products used,
242262306a36Sopenharmony_ci	swap		%d5			# now use msws of longwords
242362306a36Sopenharmony_ci	swap		%d2
242462306a36Sopenharmony_ci	add.l		%d2, %d5
242562306a36Sopenharmony_ci	add.l		%d3, %d5		# %d5 now ms 32 bits of final product
242662306a36Sopenharmony_ci	rts
242762306a36Sopenharmony_ci
242862306a36Sopenharmony_ci##########
242962306a36Sopenharmony_cidcontrolmodel_s:
243062306a36Sopenharmony_ci	movq.l		&LONG,%d0
243162306a36Sopenharmony_ci	bsr.l		_calc_ea		# calc <ea>
243262306a36Sopenharmony_ci
243362306a36Sopenharmony_ci	cmpi.b		SPCOND_FLG(%a6),&immed_flg # immediate addressing mode?
243462306a36Sopenharmony_ci	beq.b		dimmed			# yes
243562306a36Sopenharmony_ci
243662306a36Sopenharmony_ci	mov.l		%a0,%a2
243762306a36Sopenharmony_ci	bsr.l		_dmem_read_long		# fetch divisor from <ea>
243862306a36Sopenharmony_ci
243962306a36Sopenharmony_ci	tst.l		%d1			# dfetch error?
244062306a36Sopenharmony_ci	bne.b		div64_err		# yes
244162306a36Sopenharmony_ci
244262306a36Sopenharmony_ci	mov.l		%d0, %d7
244362306a36Sopenharmony_ci	bra.w		dgotsrcl
244462306a36Sopenharmony_ci
244562306a36Sopenharmony_ci# we have to split out immediate data here because it must be read using
244662306a36Sopenharmony_ci# imem_read() instead of dmem_read(). this becomes especially important
244762306a36Sopenharmony_ci# if the fetch runs into some deadly fault.
244862306a36Sopenharmony_cidimmed:
244962306a36Sopenharmony_ci	addq.l		&0x4,EXC_EXTWPTR(%a6)
245062306a36Sopenharmony_ci	bsr.l		_imem_read_long		# read immediate value
245162306a36Sopenharmony_ci
245262306a36Sopenharmony_ci	tst.l		%d1			# ifetch error?
245362306a36Sopenharmony_ci	bne.l		isp_iacc		# yes
245462306a36Sopenharmony_ci
245562306a36Sopenharmony_ci	mov.l		%d0,%d7
245662306a36Sopenharmony_ci	bra.w		dgotsrcl
245762306a36Sopenharmony_ci
245862306a36Sopenharmony_ci##########
245962306a36Sopenharmony_ci
246062306a36Sopenharmony_ci# if dmem_read_long() returns a fail message in d1, the package
246162306a36Sopenharmony_ci# must create an access error frame. here, we pass a skeleton fslw
246262306a36Sopenharmony_ci# and the failing address to the routine that creates the new frame.
246362306a36Sopenharmony_ci# also, we call isp_restore in case the effective addressing mode was
246462306a36Sopenharmony_ci# (an)+ or -(an) in which case the previous "an" value must be restored.
246562306a36Sopenharmony_ci# FSLW:
246662306a36Sopenharmony_ci#	read = true
246762306a36Sopenharmony_ci#	size = longword
246862306a36Sopenharmony_ci#	TM = data
246962306a36Sopenharmony_ci#	software emulation error = true
247062306a36Sopenharmony_cidiv64_err:
247162306a36Sopenharmony_ci	bsr.l		isp_restore		# restore addr reg
247262306a36Sopenharmony_ci	mov.l		%a2,%a0			# pass failing address
247362306a36Sopenharmony_ci	mov.l		&0x01010001,%d0		# pass fslw
247462306a36Sopenharmony_ci	bra.l		isp_dacc
247562306a36Sopenharmony_ci
247662306a36Sopenharmony_ci#########################################################################
247762306a36Sopenharmony_ci# XDEF ****************************************************************	#
247862306a36Sopenharmony_ci#	_mul64(): routine to emulate mul{u,s}.l <ea>,Dh:Dl 32x32->64	#
247962306a36Sopenharmony_ci#									#
248062306a36Sopenharmony_ci# XREF ****************************************************************	#
248162306a36Sopenharmony_ci#	_calc_ea() - calculate effective address			#
248262306a36Sopenharmony_ci#	isp_iacc() - handle instruction access error exception		#
248362306a36Sopenharmony_ci#	isp_dacc() - handle data access error exception			#
248462306a36Sopenharmony_ci#	isp_restore() - restore An on access error w/ -() or ()+	#
248562306a36Sopenharmony_ci#									#
248662306a36Sopenharmony_ci# INPUT ***************************************************************	#
248762306a36Sopenharmony_ci#	none								#
248862306a36Sopenharmony_ci#									#
248962306a36Sopenharmony_ci# OUTPUT **************************************************************	#
249062306a36Sopenharmony_ci#	If exiting through isp_dacc...					#
249162306a36Sopenharmony_ci#		a0 = failing address					#
249262306a36Sopenharmony_ci#		d0 = FSLW						#
249362306a36Sopenharmony_ci#	else								#
249462306a36Sopenharmony_ci#		none							#
249562306a36Sopenharmony_ci#									#
249662306a36Sopenharmony_ci# ALGORITHM ***********************************************************	#
249762306a36Sopenharmony_ci#	First, decode the operand location. If it's in Dn, fetch from	#
249862306a36Sopenharmony_ci# the stack. If it's in memory, use _calc_ea() to calculate the		#
249962306a36Sopenharmony_ci# effective address. Use _dmem_read_long() to fetch at that address.	#
250062306a36Sopenharmony_ci# Unless the operand is immediate data. Then use _imem_read_long().	#
250162306a36Sopenharmony_ci# Send failures to isp_dacc() or isp_iacc() as appropriate.		#
250262306a36Sopenharmony_ci#	If the operands are signed, make them unsigned and save the	#
250362306a36Sopenharmony_ci# sign info for later. Perform the multiplication using 16x16->32	#
250462306a36Sopenharmony_ci# unsigned multiplies and "add" instructions. Store the high and low	#
250562306a36Sopenharmony_ci# portions of the result in the appropriate data registers on the	#
250662306a36Sopenharmony_ci# stack. Calculate the condition codes, also.				#
250762306a36Sopenharmony_ci#									#
250862306a36Sopenharmony_ci#########################################################################
250962306a36Sopenharmony_ci
251062306a36Sopenharmony_ci#############
251162306a36Sopenharmony_ci# mul(u,s)l #
251262306a36Sopenharmony_ci#############
251362306a36Sopenharmony_ci	global		_mul64
251462306a36Sopenharmony_ci_mul64:
251562306a36Sopenharmony_ci	mov.b		EXC_OPWORD+1(%a6), %d0	# extract src {mode,reg}
251662306a36Sopenharmony_ci	cmpi.b		%d0, &0x7		# is src mode Dn or other?
251762306a36Sopenharmony_ci	bgt.w		mul64_memop		# src is in memory
251862306a36Sopenharmony_ci
251962306a36Sopenharmony_ci# multiplier operand in the data register file.
252062306a36Sopenharmony_ci# must extract the register number and fetch the operand from the stack.
252162306a36Sopenharmony_cimul64_regop:
252262306a36Sopenharmony_ci	andi.w		&0x7, %d0		# extract Dn
252362306a36Sopenharmony_ci	mov.l		(EXC_DREGS,%a6,%d0.w*4), %d3 # fetch multiplier
252462306a36Sopenharmony_ci
252562306a36Sopenharmony_ci# multiplier is in %d3. now, extract Dl and Dh fields and fetch the
252662306a36Sopenharmony_ci# multiplicand from the data register specified by Dl.
252762306a36Sopenharmony_cimul64_multiplicand:
252862306a36Sopenharmony_ci	mov.w		EXC_EXTWORD(%a6), %d2	# fetch ext word
252962306a36Sopenharmony_ci	clr.w		%d1			# clear Dh reg
253062306a36Sopenharmony_ci	mov.b		%d2, %d1		# grab Dh
253162306a36Sopenharmony_ci	rol.w		&0x4, %d2		# align Dl byte
253262306a36Sopenharmony_ci	andi.w		&0x7, %d2		# extract Dl
253362306a36Sopenharmony_ci
253462306a36Sopenharmony_ci	mov.l		(EXC_DREGS,%a6,%d2.w*4), %d4 # get multiplicand
253562306a36Sopenharmony_ci
253662306a36Sopenharmony_ci# check for the case of "zero" result early
253762306a36Sopenharmony_ci	tst.l		%d4			# test multiplicand
253862306a36Sopenharmony_ci	beq.w		mul64_zero		# handle zero separately
253962306a36Sopenharmony_ci	tst.l		%d3			# test multiplier
254062306a36Sopenharmony_ci	beq.w		mul64_zero		# handle zero separately
254162306a36Sopenharmony_ci
254262306a36Sopenharmony_ci# multiplier is in %d3 and multiplicand is in %d4.
254362306a36Sopenharmony_ci# if the operation is to be signed, then the operands are converted
254462306a36Sopenharmony_ci# to unsigned and the result sign is saved for the end.
254562306a36Sopenharmony_ci	clr.b		EXC_TEMP(%a6)		# clear temp space
254662306a36Sopenharmony_ci	btst		&0x3, EXC_EXTWORD(%a6)	# signed or unsigned?
254762306a36Sopenharmony_ci	beq.b		mul64_alg		# unsigned; skip sgn calc
254862306a36Sopenharmony_ci
254962306a36Sopenharmony_ci	tst.l		%d3			# is multiplier negative?
255062306a36Sopenharmony_ci	bge.b		mul64_chk_md_sgn	# no
255162306a36Sopenharmony_ci	neg.l		%d3			# make multiplier positive
255262306a36Sopenharmony_ci	ori.b		&0x1, EXC_TEMP(%a6)	# save multiplier sgn
255362306a36Sopenharmony_ci
255462306a36Sopenharmony_ci# the result sign is the exclusive or of the operand sign bits.
255562306a36Sopenharmony_cimul64_chk_md_sgn:
255662306a36Sopenharmony_ci	tst.l		%d4			# is multiplicand negative?
255762306a36Sopenharmony_ci	bge.b		mul64_alg		# no
255862306a36Sopenharmony_ci	neg.l		%d4			# make multiplicand positive
255962306a36Sopenharmony_ci	eori.b		&0x1, EXC_TEMP(%a6)	# calculate correct sign
256062306a36Sopenharmony_ci
256162306a36Sopenharmony_ci#########################################################################
256262306a36Sopenharmony_ci#	63			   32				0	#
256362306a36Sopenharmony_ci#	----------------------------					#
256462306a36Sopenharmony_ci#	| hi(mplier) * hi(mplicand)|					#
256562306a36Sopenharmony_ci#	----------------------------					#
256662306a36Sopenharmony_ci#		     -----------------------------			#
256762306a36Sopenharmony_ci#		     | hi(mplier) * lo(mplicand) |			#
256862306a36Sopenharmony_ci#		     -----------------------------			#
256962306a36Sopenharmony_ci#		     -----------------------------			#
257062306a36Sopenharmony_ci#		     | lo(mplier) * hi(mplicand) |			#
257162306a36Sopenharmony_ci#		     -----------------------------			#
257262306a36Sopenharmony_ci#	  |			   -----------------------------	#
257362306a36Sopenharmony_ci#	--|--			   | lo(mplier) * lo(mplicand) |	#
257462306a36Sopenharmony_ci#	  |			   -----------------------------	#
257562306a36Sopenharmony_ci#	========================================================	#
257662306a36Sopenharmony_ci#	--------------------------------------------------------	#
257762306a36Sopenharmony_ci#	|	hi(result)	   |	    lo(result)         |	#
257862306a36Sopenharmony_ci#	--------------------------------------------------------	#
257962306a36Sopenharmony_ci#########################################################################
258062306a36Sopenharmony_cimul64_alg:
258162306a36Sopenharmony_ci# load temp registers with operands
258262306a36Sopenharmony_ci	mov.l		%d3, %d5		# mr in %d5
258362306a36Sopenharmony_ci	mov.l		%d3, %d6		# mr in %d6
258462306a36Sopenharmony_ci	mov.l		%d4, %d7		# md in %d7
258562306a36Sopenharmony_ci	swap		%d6			# hi(mr) in lo %d6
258662306a36Sopenharmony_ci	swap		%d7			# hi(md) in lo %d7
258762306a36Sopenharmony_ci
258862306a36Sopenharmony_ci# complete necessary multiplies:
258962306a36Sopenharmony_ci	mulu.w		%d4, %d3		# [1] lo(mr) * lo(md)
259062306a36Sopenharmony_ci	mulu.w		%d6, %d4		# [2] hi(mr) * lo(md)
259162306a36Sopenharmony_ci	mulu.w		%d7, %d5		# [3] lo(mr) * hi(md)
259262306a36Sopenharmony_ci	mulu.w		%d7, %d6		# [4] hi(mr) * hi(md)
259362306a36Sopenharmony_ci
259462306a36Sopenharmony_ci# add lo portions of [2],[3] to hi portion of [1].
259562306a36Sopenharmony_ci# add carries produced from these adds to [4].
259662306a36Sopenharmony_ci# lo([1]) is the final lo 16 bits of the result.
259762306a36Sopenharmony_ci	clr.l		%d7			# load %d7 w/ zero value
259862306a36Sopenharmony_ci	swap		%d3			# hi([1]) <==> lo([1])
259962306a36Sopenharmony_ci	add.w		%d4, %d3		# hi([1]) + lo([2])
260062306a36Sopenharmony_ci	addx.l		%d7, %d6		#    [4]  + carry
260162306a36Sopenharmony_ci	add.w		%d5, %d3		# hi([1]) + lo([3])
260262306a36Sopenharmony_ci	addx.l		%d7, %d6		#    [4]  + carry
260362306a36Sopenharmony_ci	swap		%d3			# lo([1]) <==> hi([1])
260462306a36Sopenharmony_ci
260562306a36Sopenharmony_ci# lo portions of [2],[3] have been added in to final result.
260662306a36Sopenharmony_ci# now, clear lo, put hi in lo reg, and add to [4]
260762306a36Sopenharmony_ci	clr.w		%d4			# clear lo([2])
260862306a36Sopenharmony_ci	clr.w		%d5			# clear hi([3])
260962306a36Sopenharmony_ci	swap		%d4			# hi([2]) in lo %d4
261062306a36Sopenharmony_ci	swap		%d5			# hi([3]) in lo %d5
261162306a36Sopenharmony_ci	add.l		%d5, %d4		#    [4]  + hi([2])
261262306a36Sopenharmony_ci	add.l		%d6, %d4		#    [4]  + hi([3])
261362306a36Sopenharmony_ci
261462306a36Sopenharmony_ci# unsigned result is now in {%d4,%d3}
261562306a36Sopenharmony_ci	tst.b		EXC_TEMP(%a6)		# should result be signed?
261662306a36Sopenharmony_ci	beq.b		mul64_done		# no
261762306a36Sopenharmony_ci
261862306a36Sopenharmony_ci# result should be a signed negative number.
261962306a36Sopenharmony_ci# compute 2's complement of the unsigned number:
262062306a36Sopenharmony_ci#   -negate all bits and add 1
262162306a36Sopenharmony_cimul64_neg:
262262306a36Sopenharmony_ci	not.l		%d3			# negate lo(result) bits
262362306a36Sopenharmony_ci	not.l		%d4			# negate hi(result) bits
262462306a36Sopenharmony_ci	addq.l		&1, %d3			# add 1 to lo(result)
262562306a36Sopenharmony_ci	addx.l		%d7, %d4		# add carry to hi(result)
262662306a36Sopenharmony_ci
262762306a36Sopenharmony_ci# the result is saved to the register file.
262862306a36Sopenharmony_ci# for '040 compatibility, if Dl == Dh then only the hi(result) is
262962306a36Sopenharmony_ci# saved. so, saving hi after lo accomplishes this without need to
263062306a36Sopenharmony_ci# check Dl,Dh equality.
263162306a36Sopenharmony_cimul64_done:
263262306a36Sopenharmony_ci	mov.l		%d3, (EXC_DREGS,%a6,%d2.w*4) # save lo(result)
263362306a36Sopenharmony_ci	mov.w		&0x0, %cc
263462306a36Sopenharmony_ci	mov.l		%d4, (EXC_DREGS,%a6,%d1.w*4) # save hi(result)
263562306a36Sopenharmony_ci
263662306a36Sopenharmony_ci# now, grab the condition codes. only one that can be set is 'N'.
263762306a36Sopenharmony_ci# 'N' CAN be set if the operation is unsigned if bit 63 is set.
263862306a36Sopenharmony_ci	mov.w		%cc, %d7		# fetch %ccr to see if 'N' set
263962306a36Sopenharmony_ci	andi.b		&0x8, %d7		# extract 'N' bit
264062306a36Sopenharmony_ci
264162306a36Sopenharmony_cimul64_ccode_set:
264262306a36Sopenharmony_ci	mov.b		EXC_CC+1(%a6), %d6	# fetch previous %ccr
264362306a36Sopenharmony_ci	andi.b		&0x10, %d6		# all but 'X' bit changes
264462306a36Sopenharmony_ci
264562306a36Sopenharmony_ci	or.b		%d7, %d6		# group 'X' and 'N'
264662306a36Sopenharmony_ci	mov.b		%d6, EXC_CC+1(%a6)	# save new %ccr
264762306a36Sopenharmony_ci
264862306a36Sopenharmony_ci	rts
264962306a36Sopenharmony_ci
265062306a36Sopenharmony_ci# one or both of the operands is zero so the result is also zero.
265162306a36Sopenharmony_ci# save the zero result to the register file and set the 'Z' ccode bit.
265262306a36Sopenharmony_cimul64_zero:
265362306a36Sopenharmony_ci	clr.l		(EXC_DREGS,%a6,%d2.w*4) # save lo(result)
265462306a36Sopenharmony_ci	clr.l		(EXC_DREGS,%a6,%d1.w*4) # save hi(result)
265562306a36Sopenharmony_ci
265662306a36Sopenharmony_ci	movq.l		&0x4, %d7		# set 'Z' ccode bit
265762306a36Sopenharmony_ci	bra.b		mul64_ccode_set		# finish ccode set
265862306a36Sopenharmony_ci
265962306a36Sopenharmony_ci##########
266062306a36Sopenharmony_ci
266162306a36Sopenharmony_ci# multiplier operand is in memory at the effective address.
266262306a36Sopenharmony_ci# must calculate the <ea> and go fetch the 32-bit operand.
266362306a36Sopenharmony_cimul64_memop:
266462306a36Sopenharmony_ci	movq.l		&LONG, %d0		# pass # of bytes
266562306a36Sopenharmony_ci	bsr.l		_calc_ea		# calculate <ea>
266662306a36Sopenharmony_ci
266762306a36Sopenharmony_ci	cmpi.b		SPCOND_FLG(%a6),&immed_flg # immediate addressing mode?
266862306a36Sopenharmony_ci	beq.b		mul64_immed		# yes
266962306a36Sopenharmony_ci
267062306a36Sopenharmony_ci	mov.l		%a0,%a2
267162306a36Sopenharmony_ci	bsr.l		_dmem_read_long		# fetch src from addr (%a0)
267262306a36Sopenharmony_ci
267362306a36Sopenharmony_ci	tst.l		%d1			# dfetch error?
267462306a36Sopenharmony_ci	bne.w		mul64_err		# yes
267562306a36Sopenharmony_ci
267662306a36Sopenharmony_ci	mov.l		%d0, %d3		# store multiplier in %d3
267762306a36Sopenharmony_ci
267862306a36Sopenharmony_ci	bra.w		mul64_multiplicand
267962306a36Sopenharmony_ci
268062306a36Sopenharmony_ci# we have to split out immediate data here because it must be read using
268162306a36Sopenharmony_ci# imem_read() instead of dmem_read(). this becomes especially important
268262306a36Sopenharmony_ci# if the fetch runs into some deadly fault.
268362306a36Sopenharmony_cimul64_immed:
268462306a36Sopenharmony_ci	addq.l		&0x4,EXC_EXTWPTR(%a6)
268562306a36Sopenharmony_ci	bsr.l		_imem_read_long		# read immediate value
268662306a36Sopenharmony_ci
268762306a36Sopenharmony_ci	tst.l		%d1			# ifetch error?
268862306a36Sopenharmony_ci	bne.l		isp_iacc		# yes
268962306a36Sopenharmony_ci
269062306a36Sopenharmony_ci	mov.l		%d0,%d3
269162306a36Sopenharmony_ci	bra.w		mul64_multiplicand
269262306a36Sopenharmony_ci
269362306a36Sopenharmony_ci##########
269462306a36Sopenharmony_ci
269562306a36Sopenharmony_ci# if dmem_read_long() returns a fail message in d1, the package
269662306a36Sopenharmony_ci# must create an access error frame. here, we pass a skeleton fslw
269762306a36Sopenharmony_ci# and the failing address to the routine that creates the new frame.
269862306a36Sopenharmony_ci# also, we call isp_restore in case the effective addressing mode was
269962306a36Sopenharmony_ci# (an)+ or -(an) in which case the previous "an" value must be restored.
270062306a36Sopenharmony_ci# FSLW:
270162306a36Sopenharmony_ci#	read = true
270262306a36Sopenharmony_ci#	size = longword
270362306a36Sopenharmony_ci#	TM = data
270462306a36Sopenharmony_ci#	software emulation error = true
270562306a36Sopenharmony_cimul64_err:
270662306a36Sopenharmony_ci	bsr.l		isp_restore		# restore addr reg
270762306a36Sopenharmony_ci	mov.l		%a2,%a0			# pass failing address
270862306a36Sopenharmony_ci	mov.l		&0x01010001,%d0		# pass fslw
270962306a36Sopenharmony_ci	bra.l		isp_dacc
271062306a36Sopenharmony_ci
271162306a36Sopenharmony_ci#########################################################################
271262306a36Sopenharmony_ci# XDEF ****************************************************************	#
271362306a36Sopenharmony_ci#	_compandset2(): routine to emulate cas2()			#
271462306a36Sopenharmony_ci#			(internal to package)				#
271562306a36Sopenharmony_ci#									#
271662306a36Sopenharmony_ci#	_isp_cas2_finish(): store ccodes, store compare regs		#
271762306a36Sopenharmony_ci#			    (external to package)			#
271862306a36Sopenharmony_ci#									#
271962306a36Sopenharmony_ci# XREF ****************************************************************	#
272062306a36Sopenharmony_ci#	_real_lock_page() - "callout" to lock op's page from page-outs	#
272162306a36Sopenharmony_ci#	_cas_terminate2() - access error exit				#
272262306a36Sopenharmony_ci#	_real_cas2() - "callout" to core cas2 emulation code		#
272362306a36Sopenharmony_ci#	_real_unlock_page() - "callout" to unlock page			#
272462306a36Sopenharmony_ci#									#
272562306a36Sopenharmony_ci# INPUT ***************************************************************	#
272662306a36Sopenharmony_ci# _compandset2():							#
272762306a36Sopenharmony_ci#	d0 = instruction extension word					#
272862306a36Sopenharmony_ci#									#
272962306a36Sopenharmony_ci# _isp_cas2_finish():							#
273062306a36Sopenharmony_ci#	see cas2 core emulation code					#
273162306a36Sopenharmony_ci#									#
273262306a36Sopenharmony_ci# OUTPUT **************************************************************	#
273362306a36Sopenharmony_ci# _compandset2():							#
273462306a36Sopenharmony_ci#	see cas2 core emulation code					#
273562306a36Sopenharmony_ci#									#
273662306a36Sopenharmony_ci# _isp_cas_finish():							#
273762306a36Sopenharmony_ci#	None (register file or memroy changed as appropriate)		#
273862306a36Sopenharmony_ci#									#
273962306a36Sopenharmony_ci# ALGORITHM ***********************************************************	#
274062306a36Sopenharmony_ci# compandset2():							#
274162306a36Sopenharmony_ci#	Decode the instruction and fetch the appropriate Update and	#
274262306a36Sopenharmony_ci# Compare operands. Then call the "callout" _real_lock_page() for each	#
274362306a36Sopenharmony_ci# memory operand address so that the operating system can keep these	#
274462306a36Sopenharmony_ci# pages from being paged out. If either _real_lock_page() fails, exit	#
274562306a36Sopenharmony_ci# through _cas_terminate2(). Don't forget to unlock the 1st locked page	#
274662306a36Sopenharmony_ci# using _real_unlock_paged() if the 2nd lock-page fails.		#
274762306a36Sopenharmony_ci# Finally, branch to the core cas2 emulation code by calling the	#
274862306a36Sopenharmony_ci# "callout" _real_cas2().						#
274962306a36Sopenharmony_ci#									#
275062306a36Sopenharmony_ci# _isp_cas2_finish():							#
275162306a36Sopenharmony_ci#	Re-perform the comparison so we can determine the condition	#
275262306a36Sopenharmony_ci# codes which were too much trouble to keep around during the locked	#
275362306a36Sopenharmony_ci# emulation. Then unlock each operands page by calling the "callout"	#
275462306a36Sopenharmony_ci# _real_unlock_page().							#
275562306a36Sopenharmony_ci#									#
275662306a36Sopenharmony_ci#########################################################################
275762306a36Sopenharmony_ci
275862306a36Sopenharmony_ciset ADDR1,	EXC_TEMP+0xc
275962306a36Sopenharmony_ciset ADDR2,	EXC_TEMP+0x0
276062306a36Sopenharmony_ciset DC2,	EXC_TEMP+0xa
276162306a36Sopenharmony_ciset DC1,	EXC_TEMP+0x8
276262306a36Sopenharmony_ci
276362306a36Sopenharmony_ci	global		_compandset2
276462306a36Sopenharmony_ci_compandset2:
276562306a36Sopenharmony_ci	mov.l		%d0,EXC_TEMP+0x4(%a6)		# store for possible restart
276662306a36Sopenharmony_ci	mov.l		%d0,%d1			# extension word in d0
276762306a36Sopenharmony_ci
276862306a36Sopenharmony_ci	rol.w		&0x4,%d0
276962306a36Sopenharmony_ci	andi.w		&0xf,%d0		# extract Rn2
277062306a36Sopenharmony_ci	mov.l		(EXC_DREGS,%a6,%d0.w*4),%a1 # fetch ADDR2
277162306a36Sopenharmony_ci	mov.l		%a1,ADDR2(%a6)
277262306a36Sopenharmony_ci
277362306a36Sopenharmony_ci	mov.l		%d1,%d0
277462306a36Sopenharmony_ci
277562306a36Sopenharmony_ci	lsr.w		&0x6,%d1
277662306a36Sopenharmony_ci	andi.w		&0x7,%d1		# extract Du2
277762306a36Sopenharmony_ci	mov.l		(EXC_DREGS,%a6,%d1.w*4),%d5 # fetch Update2 Op
277862306a36Sopenharmony_ci
277962306a36Sopenharmony_ci	andi.w		&0x7,%d0		# extract Dc2
278062306a36Sopenharmony_ci	mov.l		(EXC_DREGS,%a6,%d0.w*4),%d3 # fetch Compare2 Op
278162306a36Sopenharmony_ci	mov.w		%d0,DC2(%a6)
278262306a36Sopenharmony_ci
278362306a36Sopenharmony_ci	mov.w		EXC_EXTWORD(%a6),%d0
278462306a36Sopenharmony_ci	mov.l		%d0,%d1
278562306a36Sopenharmony_ci
278662306a36Sopenharmony_ci	rol.w		&0x4,%d0
278762306a36Sopenharmony_ci	andi.w		&0xf,%d0		# extract Rn1
278862306a36Sopenharmony_ci	mov.l		(EXC_DREGS,%a6,%d0.w*4),%a0 # fetch ADDR1
278962306a36Sopenharmony_ci	mov.l		%a0,ADDR1(%a6)
279062306a36Sopenharmony_ci
279162306a36Sopenharmony_ci	mov.l		%d1,%d0
279262306a36Sopenharmony_ci
279362306a36Sopenharmony_ci	lsr.w		&0x6,%d1
279462306a36Sopenharmony_ci	andi.w		&0x7,%d1		# extract Du1
279562306a36Sopenharmony_ci	mov.l		(EXC_DREGS,%a6,%d1.w*4),%d4 # fetch Update1 Op
279662306a36Sopenharmony_ci
279762306a36Sopenharmony_ci	andi.w		&0x7,%d0		# extract Dc1
279862306a36Sopenharmony_ci	mov.l		(EXC_DREGS,%a6,%d0.w*4),%d2 # fetch Compare1 Op
279962306a36Sopenharmony_ci	mov.w		%d0,DC1(%a6)
280062306a36Sopenharmony_ci
280162306a36Sopenharmony_ci	btst		&0x1,EXC_OPWORD(%a6)	# word or long?
280262306a36Sopenharmony_ci	sne		%d7
280362306a36Sopenharmony_ci
280462306a36Sopenharmony_ci	btst		&0x5,EXC_ISR(%a6)	# user or supervisor?
280562306a36Sopenharmony_ci	sne		%d6
280662306a36Sopenharmony_ci
280762306a36Sopenharmony_ci	mov.l		%a0,%a2
280862306a36Sopenharmony_ci	mov.l		%a1,%a3
280962306a36Sopenharmony_ci
281062306a36Sopenharmony_ci	mov.l		%d7,%d1			# pass size
281162306a36Sopenharmony_ci	mov.l		%d6,%d0			# pass mode
281262306a36Sopenharmony_ci	bsr.l		_real_lock_page		# lock page
281362306a36Sopenharmony_ci	mov.l		%a2,%a0
281462306a36Sopenharmony_ci	tst.l		%d0			# error?
281562306a36Sopenharmony_ci	bne.l		_cas_terminate2		# yes
281662306a36Sopenharmony_ci
281762306a36Sopenharmony_ci	mov.l		%d7,%d1			# pass size
281862306a36Sopenharmony_ci	mov.l		%d6,%d0			# pass mode
281962306a36Sopenharmony_ci	mov.l		%a3,%a0			# pass addr
282062306a36Sopenharmony_ci	bsr.l		_real_lock_page		# lock page
282162306a36Sopenharmony_ci	mov.l		%a3,%a0
282262306a36Sopenharmony_ci	tst.l		%d0			# error?
282362306a36Sopenharmony_ci	bne.b		cas_preterm		# yes
282462306a36Sopenharmony_ci
282562306a36Sopenharmony_ci	mov.l		%a2,%a0
282662306a36Sopenharmony_ci	mov.l		%a3,%a1
282762306a36Sopenharmony_ci
282862306a36Sopenharmony_ci	bra.l		_real_cas2
282962306a36Sopenharmony_ci
283062306a36Sopenharmony_ci# if the 2nd lock attempt fails, then we must still unlock the
283162306a36Sopenharmony_ci# first page(s).
283262306a36Sopenharmony_cicas_preterm:
283362306a36Sopenharmony_ci	mov.l		%d0,-(%sp)		# save FSLW
283462306a36Sopenharmony_ci	mov.l		%d7,%d1			# pass size
283562306a36Sopenharmony_ci	mov.l		%d6,%d0			# pass mode
283662306a36Sopenharmony_ci	mov.l		%a2,%a0			# pass ADDR1
283762306a36Sopenharmony_ci	bsr.l		_real_unlock_page	# unlock first page(s)
283862306a36Sopenharmony_ci	mov.l		(%sp)+,%d0		# restore FSLW
283962306a36Sopenharmony_ci	mov.l		%a3,%a0			# pass failing addr
284062306a36Sopenharmony_ci	bra.l		_cas_terminate2
284162306a36Sopenharmony_ci
284262306a36Sopenharmony_ci#############################################################
284362306a36Sopenharmony_ci
284462306a36Sopenharmony_ci	global		_isp_cas2_finish
284562306a36Sopenharmony_ci_isp_cas2_finish:
284662306a36Sopenharmony_ci	btst		&0x1,EXC_OPWORD(%a6)
284762306a36Sopenharmony_ci	bne.b		cas2_finish_l
284862306a36Sopenharmony_ci
284962306a36Sopenharmony_ci	mov.w		EXC_CC(%a6),%cc		# load old ccodes
285062306a36Sopenharmony_ci	cmp.w		%d0,%d2
285162306a36Sopenharmony_ci	bne.b		cas2_finish_w_save
285262306a36Sopenharmony_ci	cmp.w		%d1,%d3
285362306a36Sopenharmony_cicas2_finish_w_save:
285462306a36Sopenharmony_ci	mov.w		%cc,EXC_CC(%a6)		# save new ccodes
285562306a36Sopenharmony_ci
285662306a36Sopenharmony_ci	tst.b		%d4			# update compare reg?
285762306a36Sopenharmony_ci	bne.b		cas2_finish_w_done	# no
285862306a36Sopenharmony_ci
285962306a36Sopenharmony_ci	mov.w		DC2(%a6),%d3		# fetch Dc2
286062306a36Sopenharmony_ci	mov.w		%d1,(2+EXC_DREGS,%a6,%d3.w*4) # store new Compare2 Op
286162306a36Sopenharmony_ci
286262306a36Sopenharmony_ci	mov.w		DC1(%a6),%d2		# fetch Dc1
286362306a36Sopenharmony_ci	mov.w		%d0,(2+EXC_DREGS,%a6,%d2.w*4) # store new Compare1 Op
286462306a36Sopenharmony_ci
286562306a36Sopenharmony_cicas2_finish_w_done:
286662306a36Sopenharmony_ci	btst		&0x5,EXC_ISR(%a6)
286762306a36Sopenharmony_ci	sne		%d2
286862306a36Sopenharmony_ci	mov.l		%d2,%d0			# pass mode
286962306a36Sopenharmony_ci	sf		%d1			# pass size
287062306a36Sopenharmony_ci	mov.l		ADDR1(%a6),%a0		# pass ADDR1
287162306a36Sopenharmony_ci	bsr.l		_real_unlock_page	# unlock page
287262306a36Sopenharmony_ci
287362306a36Sopenharmony_ci	mov.l		%d2,%d0			# pass mode
287462306a36Sopenharmony_ci	sf		%d1			# pass size
287562306a36Sopenharmony_ci	mov.l		ADDR2(%a6),%a0		# pass ADDR2
287662306a36Sopenharmony_ci	bsr.l		_real_unlock_page	# unlock page
287762306a36Sopenharmony_ci	rts
287862306a36Sopenharmony_ci
287962306a36Sopenharmony_cicas2_finish_l:
288062306a36Sopenharmony_ci	mov.w		EXC_CC(%a6),%cc		# load old ccodes
288162306a36Sopenharmony_ci	cmp.l		%d0,%d2
288262306a36Sopenharmony_ci	bne.b		cas2_finish_l_save
288362306a36Sopenharmony_ci	cmp.l		%d1,%d3
288462306a36Sopenharmony_cicas2_finish_l_save:
288562306a36Sopenharmony_ci	mov.w		%cc,EXC_CC(%a6)		# save new ccodes
288662306a36Sopenharmony_ci
288762306a36Sopenharmony_ci	tst.b		%d4			# update compare reg?
288862306a36Sopenharmony_ci	bne.b		cas2_finish_l_done	# no
288962306a36Sopenharmony_ci
289062306a36Sopenharmony_ci	mov.w		DC2(%a6),%d3		# fetch Dc2
289162306a36Sopenharmony_ci	mov.l		%d1,(EXC_DREGS,%a6,%d3.w*4) # store new Compare2 Op
289262306a36Sopenharmony_ci
289362306a36Sopenharmony_ci	mov.w		DC1(%a6),%d2		# fetch Dc1
289462306a36Sopenharmony_ci	mov.l		%d0,(EXC_DREGS,%a6,%d2.w*4) # store new Compare1 Op
289562306a36Sopenharmony_ci
289662306a36Sopenharmony_cicas2_finish_l_done:
289762306a36Sopenharmony_ci	btst		&0x5,EXC_ISR(%a6)
289862306a36Sopenharmony_ci	sne		%d2
289962306a36Sopenharmony_ci	mov.l		%d2,%d0			# pass mode
290062306a36Sopenharmony_ci	st		%d1			# pass size
290162306a36Sopenharmony_ci	mov.l		ADDR1(%a6),%a0		# pass ADDR1
290262306a36Sopenharmony_ci	bsr.l		_real_unlock_page	# unlock page
290362306a36Sopenharmony_ci
290462306a36Sopenharmony_ci	mov.l		%d2,%d0			# pass mode
290562306a36Sopenharmony_ci	st		%d1			# pass size
290662306a36Sopenharmony_ci	mov.l		ADDR2(%a6),%a0		# pass ADDR2
290762306a36Sopenharmony_ci	bsr.l		_real_unlock_page	# unlock page
290862306a36Sopenharmony_ci	rts
290962306a36Sopenharmony_ci
291062306a36Sopenharmony_ci########
291162306a36Sopenharmony_ci	global		cr_cas2
291262306a36Sopenharmony_cicr_cas2:
291362306a36Sopenharmony_ci	mov.l		EXC_TEMP+0x4(%a6),%d0
291462306a36Sopenharmony_ci	bra.w		_compandset2
291562306a36Sopenharmony_ci
291662306a36Sopenharmony_ci#########################################################################
291762306a36Sopenharmony_ci# XDEF ****************************************************************	#
291862306a36Sopenharmony_ci#	_compandset(): routine to emulate cas w/ misaligned <ea>	#
291962306a36Sopenharmony_ci#		       (internal to package)				#
292062306a36Sopenharmony_ci#	_isp_cas_finish(): routine called when cas emulation completes	#
292162306a36Sopenharmony_ci#			   (external and internal to package)		#
292262306a36Sopenharmony_ci#	_isp_cas_restart(): restart cas emulation after a fault		#
292362306a36Sopenharmony_ci#			    (external to package)			#
292462306a36Sopenharmony_ci#	_isp_cas_terminate(): create access error stack frame on fault	#
292562306a36Sopenharmony_ci#			      (external and internal to package)	#
292662306a36Sopenharmony_ci#	_isp_cas_inrange(): checks whether instr addess is within range	#
292762306a36Sopenharmony_ci#			    of core cas/cas2emulation code		#
292862306a36Sopenharmony_ci#			    (external to package)			#
292962306a36Sopenharmony_ci#									#
293062306a36Sopenharmony_ci# XREF ****************************************************************	#
293162306a36Sopenharmony_ci#	_calc_ea(): calculate effective address				#
293262306a36Sopenharmony_ci#									#
293362306a36Sopenharmony_ci# INPUT ***************************************************************	#
293462306a36Sopenharmony_ci# compandset():								#
293562306a36Sopenharmony_ci#	none								#
293662306a36Sopenharmony_ci# _isp_cas_restart():							#
293762306a36Sopenharmony_ci#	d6 = previous sfc/dfc						#
293862306a36Sopenharmony_ci# _isp_cas_finish():							#
293962306a36Sopenharmony_ci# _isp_cas_terminate():							#
294062306a36Sopenharmony_ci#	a0 = failing address						#
294162306a36Sopenharmony_ci#	d0 = FSLW							#
294262306a36Sopenharmony_ci#	d6 = previous sfc/dfc						#
294362306a36Sopenharmony_ci# _isp_cas_inrange():							#
294462306a36Sopenharmony_ci#	a0 = instruction address to be checked				#
294562306a36Sopenharmony_ci#									#
294662306a36Sopenharmony_ci# OUTPUT **************************************************************	#
294762306a36Sopenharmony_ci# compandset():								#
294862306a36Sopenharmony_ci#		none							#
294962306a36Sopenharmony_ci# _isp_cas_restart():							#
295062306a36Sopenharmony_ci#	a0 = effective address						#
295162306a36Sopenharmony_ci#	d7 = word or longword flag					#
295262306a36Sopenharmony_ci# _isp_cas_finish():							#
295362306a36Sopenharmony_ci#	a0 = effective address						#
295462306a36Sopenharmony_ci# _isp_cas_terminate():							#
295562306a36Sopenharmony_ci#	initial register set before emulation exception			#
295662306a36Sopenharmony_ci# _isp_cas_inrange():							#
295762306a36Sopenharmony_ci#	d0 = 0 => in range; -1 => out of range				#
295862306a36Sopenharmony_ci#									#
295962306a36Sopenharmony_ci# ALGORITHM ***********************************************************	#
296062306a36Sopenharmony_ci#									#
296162306a36Sopenharmony_ci# compandset():								#
296262306a36Sopenharmony_ci#	First, calculate the effective address. Then, decode the	#
296362306a36Sopenharmony_ci# instruction word and fetch the "compare" (DC) and "update" (Du)	#
296462306a36Sopenharmony_ci# operands.								#
296562306a36Sopenharmony_ci#	Next, call the external routine _real_lock_page() so that the	#
296662306a36Sopenharmony_ci# operating system can keep this page from being paged out while we're	#
296762306a36Sopenharmony_ci# in this routine. If this call fails, jump to _cas_terminate2().	#
296862306a36Sopenharmony_ci#	The routine then branches to _real_cas(). This external routine	#
296962306a36Sopenharmony_ci# that actually emulates cas can be supplied by the external os or	#
297062306a36Sopenharmony_ci# made to point directly back into the 060ISP which has a routine for	#
297162306a36Sopenharmony_ci# this purpose.								#
297262306a36Sopenharmony_ci#									#
297362306a36Sopenharmony_ci# _isp_cas_finish():							#
297462306a36Sopenharmony_ci#	Either way, after emulation, the package is re-entered at	#
297562306a36Sopenharmony_ci# _isp_cas_finish(). This routine re-compares the operands in order to	#
297662306a36Sopenharmony_ci# set the condition codes. Finally, these routines will call		#
297762306a36Sopenharmony_ci# _real_unlock_page() in order to unlock the pages that were previously	#
297862306a36Sopenharmony_ci# locked.								#
297962306a36Sopenharmony_ci#									#
298062306a36Sopenharmony_ci# _isp_cas_restart():							#
298162306a36Sopenharmony_ci#	This routine can be entered from an access error handler where	#
298262306a36Sopenharmony_ci# the emulation sequence should be re-started from the beginning.	#
298362306a36Sopenharmony_ci#									#
298462306a36Sopenharmony_ci# _isp_cas_terminate():							#
298562306a36Sopenharmony_ci#	This routine can be entered from an access error handler where	#
298662306a36Sopenharmony_ci# an emulation operand access failed and the operating system would	#
298762306a36Sopenharmony_ci# like an access error stack frame created instead of the current	#
298862306a36Sopenharmony_ci# unimplemented integer instruction frame.				#
298962306a36Sopenharmony_ci#	Also, the package enters here if a call to _real_lock_page()	#
299062306a36Sopenharmony_ci# fails.								#
299162306a36Sopenharmony_ci#									#
299262306a36Sopenharmony_ci# _isp_cas_inrange():							#
299362306a36Sopenharmony_ci#	Checks to see whether the instruction address passed to it in	#
299462306a36Sopenharmony_ci# a0 is within the software package cas/cas2 emulation routines. This	#
299562306a36Sopenharmony_ci# can be helpful for an operating system to determine whether an access	#
299662306a36Sopenharmony_ci# error during emulation was due to a cas/cas2 emulation access.	#
299762306a36Sopenharmony_ci#									#
299862306a36Sopenharmony_ci#########################################################################
299962306a36Sopenharmony_ci
300062306a36Sopenharmony_ciset DC,		EXC_TEMP+0x8
300162306a36Sopenharmony_ciset ADDR,	EXC_TEMP+0x4
300262306a36Sopenharmony_ci
300362306a36Sopenharmony_ci	global		_compandset
300462306a36Sopenharmony_ci_compandset:
300562306a36Sopenharmony_ci	btst		&0x1,EXC_OPWORD(%a6)	# word or long operation?
300662306a36Sopenharmony_ci	bne.b		compandsetl		# long
300762306a36Sopenharmony_ci
300862306a36Sopenharmony_cicompandsetw:
300962306a36Sopenharmony_ci	movq.l		&0x2,%d0		# size = 2 bytes
301062306a36Sopenharmony_ci	bsr.l		_calc_ea		# a0 = calculated <ea>
301162306a36Sopenharmony_ci	mov.l		%a0,ADDR(%a6)		# save <ea> for possible restart
301262306a36Sopenharmony_ci	sf		%d7			# clear d7 for word size
301362306a36Sopenharmony_ci	bra.b		compandsetfetch
301462306a36Sopenharmony_ci
301562306a36Sopenharmony_cicompandsetl:
301662306a36Sopenharmony_ci	movq.l		&0x4,%d0		# size = 4 bytes
301762306a36Sopenharmony_ci	bsr.l		_calc_ea		# a0 = calculated <ea>
301862306a36Sopenharmony_ci	mov.l		%a0,ADDR(%a6)		# save <ea> for possible restart
301962306a36Sopenharmony_ci	st		%d7			# set d7 for longword size
302062306a36Sopenharmony_ci
302162306a36Sopenharmony_cicompandsetfetch:
302262306a36Sopenharmony_ci	mov.w		EXC_EXTWORD(%a6),%d0	# fetch cas extension word
302362306a36Sopenharmony_ci	mov.l		%d0,%d1			# make a copy
302462306a36Sopenharmony_ci
302562306a36Sopenharmony_ci	lsr.w		&0x6,%d0
302662306a36Sopenharmony_ci	andi.w		&0x7,%d0		# extract Du
302762306a36Sopenharmony_ci	mov.l		(EXC_DREGS,%a6,%d0.w*4),%d2 # get update operand
302862306a36Sopenharmony_ci
302962306a36Sopenharmony_ci	andi.w		&0x7,%d1		# extract Dc
303062306a36Sopenharmony_ci	mov.l		(EXC_DREGS,%a6,%d1.w*4),%d4 # get compare operand
303162306a36Sopenharmony_ci	mov.w		%d1,DC(%a6)		# save Dc
303262306a36Sopenharmony_ci
303362306a36Sopenharmony_ci	btst		&0x5,EXC_ISR(%a6)	# which mode for exception?
303462306a36Sopenharmony_ci	sne		%d6			# set on supervisor mode
303562306a36Sopenharmony_ci
303662306a36Sopenharmony_ci	mov.l		%a0,%a2			# save temporarily
303762306a36Sopenharmony_ci	mov.l		%d7,%d1			# pass size
303862306a36Sopenharmony_ci	mov.l		%d6,%d0			# pass mode
303962306a36Sopenharmony_ci	bsr.l		_real_lock_page		# lock page
304062306a36Sopenharmony_ci	tst.l		%d0			# did error occur?
304162306a36Sopenharmony_ci	bne.w		_cas_terminate2		# yes, clean up the mess
304262306a36Sopenharmony_ci	mov.l		%a2,%a0			# pass addr in a0
304362306a36Sopenharmony_ci
304462306a36Sopenharmony_ci	bra.l		_real_cas
304562306a36Sopenharmony_ci
304662306a36Sopenharmony_ci########
304762306a36Sopenharmony_ci	global		_isp_cas_finish
304862306a36Sopenharmony_ci_isp_cas_finish:
304962306a36Sopenharmony_ci	btst		&0x1,EXC_OPWORD(%a6)
305062306a36Sopenharmony_ci	bne.b		cas_finish_l
305162306a36Sopenharmony_ci
305262306a36Sopenharmony_ci# just do the compare again since it's faster than saving the ccodes
305362306a36Sopenharmony_ci# from the locked routine...
305462306a36Sopenharmony_cicas_finish_w:
305562306a36Sopenharmony_ci	mov.w		EXC_CC(%a6),%cc		# restore cc
305662306a36Sopenharmony_ci	cmp.w		%d0,%d4			# do word compare
305762306a36Sopenharmony_ci	mov.w		%cc,EXC_CC(%a6)		# save cc
305862306a36Sopenharmony_ci
305962306a36Sopenharmony_ci	tst.b		%d1			# update compare reg?
306062306a36Sopenharmony_ci	bne.b		cas_finish_w_done	# no
306162306a36Sopenharmony_ci
306262306a36Sopenharmony_ci	mov.w		DC(%a6),%d3
306362306a36Sopenharmony_ci	mov.w		%d0,(EXC_DREGS+2,%a6,%d3.w*4) # Dc = destination
306462306a36Sopenharmony_ci
306562306a36Sopenharmony_cicas_finish_w_done:
306662306a36Sopenharmony_ci	mov.l		ADDR(%a6),%a0		# pass addr
306762306a36Sopenharmony_ci	sf		%d1			# pass size
306862306a36Sopenharmony_ci	btst		&0x5,EXC_ISR(%a6)
306962306a36Sopenharmony_ci	sne		%d0			# pass mode
307062306a36Sopenharmony_ci	bsr.l		_real_unlock_page	# unlock page
307162306a36Sopenharmony_ci	rts
307262306a36Sopenharmony_ci
307362306a36Sopenharmony_ci# just do the compare again since it's faster than saving the ccodes
307462306a36Sopenharmony_ci# from the locked routine...
307562306a36Sopenharmony_cicas_finish_l:
307662306a36Sopenharmony_ci	mov.w		EXC_CC(%a6),%cc		# restore cc
307762306a36Sopenharmony_ci	cmp.l		%d0,%d4			# do longword compare
307862306a36Sopenharmony_ci	mov.w		%cc,EXC_CC(%a6)		# save cc
307962306a36Sopenharmony_ci
308062306a36Sopenharmony_ci	tst.b		%d1			# update compare reg?
308162306a36Sopenharmony_ci	bne.b		cas_finish_l_done	# no
308262306a36Sopenharmony_ci
308362306a36Sopenharmony_ci	mov.w		DC(%a6),%d3
308462306a36Sopenharmony_ci	mov.l		%d0,(EXC_DREGS,%a6,%d3.w*4) # Dc = destination
308562306a36Sopenharmony_ci
308662306a36Sopenharmony_cicas_finish_l_done:
308762306a36Sopenharmony_ci	mov.l		ADDR(%a6),%a0		# pass addr
308862306a36Sopenharmony_ci	st		%d1			# pass size
308962306a36Sopenharmony_ci	btst		&0x5,EXC_ISR(%a6)
309062306a36Sopenharmony_ci	sne		%d0			# pass mode
309162306a36Sopenharmony_ci	bsr.l		_real_unlock_page	# unlock page
309262306a36Sopenharmony_ci	rts
309362306a36Sopenharmony_ci
309462306a36Sopenharmony_ci########
309562306a36Sopenharmony_ci
309662306a36Sopenharmony_ci	global		_isp_cas_restart
309762306a36Sopenharmony_ci_isp_cas_restart:
309862306a36Sopenharmony_ci	mov.l		%d6,%sfc		# restore previous sfc
309962306a36Sopenharmony_ci	mov.l		%d6,%dfc		# restore previous dfc
310062306a36Sopenharmony_ci
310162306a36Sopenharmony_ci	cmpi.b		EXC_OPWORD+1(%a6),&0xfc	# cas or cas2?
310262306a36Sopenharmony_ci	beq.l		cr_cas2			# cas2
310362306a36Sopenharmony_cicr_cas:
310462306a36Sopenharmony_ci	mov.l		ADDR(%a6),%a0		# load <ea>
310562306a36Sopenharmony_ci	btst		&0x1,EXC_OPWORD(%a6)	# word or long operation?
310662306a36Sopenharmony_ci	sne		%d7			# set d7 accordingly
310762306a36Sopenharmony_ci	bra.w		compandsetfetch
310862306a36Sopenharmony_ci
310962306a36Sopenharmony_ci########
311062306a36Sopenharmony_ci
311162306a36Sopenharmony_ci# At this stage, it would be nice if d0 held the FSLW.
311262306a36Sopenharmony_ci	global		_isp_cas_terminate
311362306a36Sopenharmony_ci_isp_cas_terminate:
311462306a36Sopenharmony_ci	mov.l		%d6,%sfc		# restore previous sfc
311562306a36Sopenharmony_ci	mov.l		%d6,%dfc		# restore previous dfc
311662306a36Sopenharmony_ci
311762306a36Sopenharmony_ci	global		_cas_terminate2
311862306a36Sopenharmony_ci_cas_terminate2:
311962306a36Sopenharmony_ci	mov.l		%a0,%a2			# copy failing addr to a2
312062306a36Sopenharmony_ci
312162306a36Sopenharmony_ci	mov.l		%d0,-(%sp)
312262306a36Sopenharmony_ci	bsr.l		isp_restore		# restore An (if ()+ or -())
312362306a36Sopenharmony_ci	mov.l		(%sp)+,%d0
312462306a36Sopenharmony_ci
312562306a36Sopenharmony_ci	addq.l		&0x4,%sp		# remove sub return addr
312662306a36Sopenharmony_ci	subq.l		&0x8,%sp		# make room for bigger stack
312762306a36Sopenharmony_ci	subq.l		&0x8,%a6		# shift frame ptr down, too
312862306a36Sopenharmony_ci	mov.l		&26,%d1			# want to move 51 longwords
312962306a36Sopenharmony_ci	lea		0x8(%sp),%a0		# get address of old stack
313062306a36Sopenharmony_ci	lea		0x0(%sp),%a1		# get address of new stack
313162306a36Sopenharmony_cicas_term_cont:
313262306a36Sopenharmony_ci	mov.l		(%a0)+,(%a1)+		# move a longword
313362306a36Sopenharmony_ci	dbra.w		%d1,cas_term_cont	# keep going
313462306a36Sopenharmony_ci
313562306a36Sopenharmony_ci	mov.w		&0x4008,EXC_IVOFF(%a6)	# put new stk fmt, voff
313662306a36Sopenharmony_ci	mov.l		%a2,EXC_IVOFF+0x2(%a6)	# put faulting addr on stack
313762306a36Sopenharmony_ci	mov.l		%d0,EXC_IVOFF+0x6(%a6)	# put FSLW on stack
313862306a36Sopenharmony_ci	movm.l		EXC_DREGS(%a6),&0x3fff	# restore user regs
313962306a36Sopenharmony_ci	unlk		%a6			# unlink stack frame
314062306a36Sopenharmony_ci	bra.l		_real_access
314162306a36Sopenharmony_ci
314262306a36Sopenharmony_ci########
314362306a36Sopenharmony_ci
314462306a36Sopenharmony_ci	global		_isp_cas_inrange
314562306a36Sopenharmony_ci_isp_cas_inrange:
314662306a36Sopenharmony_ci	clr.l		%d0			# clear return result
314762306a36Sopenharmony_ci	lea		_CASHI(%pc),%a1		# load end of CAS core code
314862306a36Sopenharmony_ci	cmp.l		%a1,%a0			# is PC in range?
314962306a36Sopenharmony_ci	blt.b		cin_no			# no
315062306a36Sopenharmony_ci	lea		_CASLO(%pc),%a1		# load begin of CAS core code
315162306a36Sopenharmony_ci	cmp.l		%a0,%a1			# is PC in range?
315262306a36Sopenharmony_ci	blt.b		cin_no			# no
315362306a36Sopenharmony_ci	rts					# yes; return d0 = 0
315462306a36Sopenharmony_cicin_no:
315562306a36Sopenharmony_ci	mov.l		&-0x1,%d0		# out of range; return d0 = -1
315662306a36Sopenharmony_ci	rts
315762306a36Sopenharmony_ci
315862306a36Sopenharmony_ci#################################################################
315962306a36Sopenharmony_ci#################################################################
316062306a36Sopenharmony_ci#################################################################
316162306a36Sopenharmony_ci# This is the start of the cas and cas2 "core" emulation code.	#
316262306a36Sopenharmony_ci# This is the section that may need to be replaced by the host	#
316362306a36Sopenharmony_ci# OS if it is too operating system-specific.			#
316462306a36Sopenharmony_ci# Please refer to the package documentation to see how to	#
316562306a36Sopenharmony_ci# "replace" this section, if necessary.				#
316662306a36Sopenharmony_ci#################################################################
316762306a36Sopenharmony_ci#################################################################
316862306a36Sopenharmony_ci#################################################################
316962306a36Sopenharmony_ci
317062306a36Sopenharmony_ci#       ######      ##      ######     ####
317162306a36Sopenharmony_ci#       #	   #  #     #         #    #
317262306a36Sopenharmony_ci#	#	  ######    ######        #
317362306a36Sopenharmony_ci#	#	  #    #         #      #
317462306a36Sopenharmony_ci#       ######    #    #    ######    ######
317562306a36Sopenharmony_ci
317662306a36Sopenharmony_ci#########################################################################
317762306a36Sopenharmony_ci# XDEF ****************************************************************	#
317862306a36Sopenharmony_ci#	_isp_cas2(): "core" emulation code for the cas2 instruction	#
317962306a36Sopenharmony_ci#									#
318062306a36Sopenharmony_ci# XREF ****************************************************************	#
318162306a36Sopenharmony_ci#	_isp_cas2_finish() - only exit point for this emulation code;	#
318262306a36Sopenharmony_ci#			     do clean-up; calculate ccodes; store	#
318362306a36Sopenharmony_ci#			     Compare Ops if appropriate.		#
318462306a36Sopenharmony_ci#									#
318562306a36Sopenharmony_ci# INPUT ***************************************************************	#
318662306a36Sopenharmony_ci#	*see chart below*						#
318762306a36Sopenharmony_ci#									#
318862306a36Sopenharmony_ci# OUTPUT **************************************************************	#
318962306a36Sopenharmony_ci#	*see chart below*						#
319062306a36Sopenharmony_ci#									#
319162306a36Sopenharmony_ci# ALGORITHM ***********************************************************	#
319262306a36Sopenharmony_ci#	(1) Make several copies of the effective address.		#
319362306a36Sopenharmony_ci#	(2) Save current SR; Then mask off all maskable interrupts.	#
319462306a36Sopenharmony_ci#	(3) Save current SFC/DFC (ASSUMED TO BE EQUAL!!!); Then set	#
319562306a36Sopenharmony_ci#	    according to whether exception occurred in user or		#
319662306a36Sopenharmony_ci#	    supervisor mode.						#
319762306a36Sopenharmony_ci#	(4) Use "plpaw" instruction to pre-load ATC with effective	#
319862306a36Sopenharmony_ci#	    address pages(s). THIS SHOULD NOT FAULT!!! The relevant	#
319962306a36Sopenharmony_ci#	    page(s) should have already been made resident prior to	#
320062306a36Sopenharmony_ci#	    entering this routine.					#
320162306a36Sopenharmony_ci#	(5) Push the operand lines from the cache w/ "cpushl".		#
320262306a36Sopenharmony_ci#	    In the 68040, this was done within the locked region. In	#
320362306a36Sopenharmony_ci#	    the 68060, it is done outside of the locked region.		#
320462306a36Sopenharmony_ci#	(6) Use "plpar" instruction to do a re-load of ATC entries for	#
320562306a36Sopenharmony_ci#	    ADDR1 since ADDR2 entries may have pushed ADDR1 out of the	#
320662306a36Sopenharmony_ci#	    ATC.							#
320762306a36Sopenharmony_ci#	(7) Pre-fetch the core emulation instructions by executing	#
320862306a36Sopenharmony_ci#	    one branch within each physical line (16 bytes) of the code	#
320962306a36Sopenharmony_ci#	    before actually executing the code.				#
321062306a36Sopenharmony_ci#	(8) Load the BUSCR w/ the bus lock value.			#
321162306a36Sopenharmony_ci#	(9) Fetch the source operands using "moves".			#
321262306a36Sopenharmony_ci#	(10)Do the compares. If both equal, go to step (13).		#
321362306a36Sopenharmony_ci#	(11)Unequal. No update occurs. But, we do write the DST1 op	#
321462306a36Sopenharmony_ci#	    back to itself (as w/ the '040) so we can gracefully unlock	#
321562306a36Sopenharmony_ci#	    the bus (and assert LOCKE*) using BUSCR and the final move.	#
321662306a36Sopenharmony_ci#	(12)Exit.							#
321762306a36Sopenharmony_ci#	(13)Write update operand to the DST locations. Use BUSCR to	#
321862306a36Sopenharmony_ci#	    assert LOCKE* for the final write operation.		#
321962306a36Sopenharmony_ci#	(14)Exit.							#
322062306a36Sopenharmony_ci#									#
322162306a36Sopenharmony_ci#	The algorithm is actually implemented slightly differently	#
322262306a36Sopenharmony_ci# depending on the size of the operation and the misalignment of the	#
322362306a36Sopenharmony_ci# operands. A misaligned operand must be written in aligned chunks or	#
322462306a36Sopenharmony_ci# else the BUSCR register control gets confused.			#
322562306a36Sopenharmony_ci#									#
322662306a36Sopenharmony_ci#########################################################################
322762306a36Sopenharmony_ci
322862306a36Sopenharmony_ci#################################################################
322962306a36Sopenharmony_ci# THIS IS THE STATE OF THE INTEGER REGISTER FILE UPON		#
323062306a36Sopenharmony_ci# ENTERING _isp_cas2().						#
323162306a36Sopenharmony_ci#								#
323262306a36Sopenharmony_ci# D0 = xxxxxxxx							#
323362306a36Sopenharmony_ci# D1 = xxxxxxxx							#
323462306a36Sopenharmony_ci# D2 = cmp operand 1						#
323562306a36Sopenharmony_ci# D3 = cmp operand 2						#
323662306a36Sopenharmony_ci# D4 = update oper 1						#
323762306a36Sopenharmony_ci# D5 = update oper 2						#
323862306a36Sopenharmony_ci# D6 = 'xxxxxxff if supervisor mode; 'xxxxxx00 if user mode	#
323962306a36Sopenharmony_ci# D7 = 'xxxxxxff if longword operation; 'xxxxxx00 if word	#
324062306a36Sopenharmony_ci# A0 = ADDR1							#
324162306a36Sopenharmony_ci# A1 = ADDR2							#
324262306a36Sopenharmony_ci# A2 = xxxxxxxx							#
324362306a36Sopenharmony_ci# A3 = xxxxxxxx							#
324462306a36Sopenharmony_ci# A4 = xxxxxxxx							#
324562306a36Sopenharmony_ci# A5 = xxxxxxxx							#
324662306a36Sopenharmony_ci# A6 = frame pointer						#
324762306a36Sopenharmony_ci# A7 = stack pointer						#
324862306a36Sopenharmony_ci#################################################################
324962306a36Sopenharmony_ci
325062306a36Sopenharmony_ci#	align		0x1000
325162306a36Sopenharmony_ci# beginning label used by _isp_cas_inrange()
325262306a36Sopenharmony_ci	global		_CASLO
325362306a36Sopenharmony_ci_CASLO:
325462306a36Sopenharmony_ci
325562306a36Sopenharmony_ci	global		_isp_cas2
325662306a36Sopenharmony_ci_isp_cas2:
325762306a36Sopenharmony_ci	tst.b		%d6			# user or supervisor mode?
325862306a36Sopenharmony_ci	bne.b		cas2_supervisor		# supervisor
325962306a36Sopenharmony_cicas2_user:
326062306a36Sopenharmony_ci	movq.l		&0x1,%d0		# load user data fc
326162306a36Sopenharmony_ci	bra.b		cas2_cont
326262306a36Sopenharmony_cicas2_supervisor:
326362306a36Sopenharmony_ci	movq.l		&0x5,%d0		# load supervisor data fc
326462306a36Sopenharmony_cicas2_cont:
326562306a36Sopenharmony_ci	tst.b		%d7			# word or longword?
326662306a36Sopenharmony_ci	beq.w		cas2w			# word
326762306a36Sopenharmony_ci
326862306a36Sopenharmony_ci####
326962306a36Sopenharmony_cicas2l:
327062306a36Sopenharmony_ci	mov.l		%a0,%a2			# copy ADDR1
327162306a36Sopenharmony_ci	mov.l		%a1,%a3			# copy ADDR2
327262306a36Sopenharmony_ci	mov.l		%a0,%a4			# copy ADDR1
327362306a36Sopenharmony_ci	mov.l		%a1,%a5			# copy ADDR2
327462306a36Sopenharmony_ci
327562306a36Sopenharmony_ci	addq.l		&0x3,%a4		# ADDR1+3
327662306a36Sopenharmony_ci	addq.l		&0x3,%a5		# ADDR2+3
327762306a36Sopenharmony_ci	mov.l		%a2,%d1			# ADDR1
327862306a36Sopenharmony_ci
327962306a36Sopenharmony_ci# mask interrupts levels 0-6. save old mask value.
328062306a36Sopenharmony_ci	mov.w		%sr,%d7			# save current SR
328162306a36Sopenharmony_ci	ori.w		&0x0700,%sr		# inhibit interrupts
328262306a36Sopenharmony_ci
328362306a36Sopenharmony_ci# load the SFC and DFC with the appropriate mode.
328462306a36Sopenharmony_ci	movc		%sfc,%d6		# save old SFC/DFC
328562306a36Sopenharmony_ci	movc		%d0,%sfc		# store new SFC
328662306a36Sopenharmony_ci	movc		%d0,%dfc		# store new DFC
328762306a36Sopenharmony_ci
328862306a36Sopenharmony_ci# pre-load the operand ATC. no page faults should occur here because
328962306a36Sopenharmony_ci# _real_lock_page() should have taken care of this.
329062306a36Sopenharmony_ci	plpaw		(%a2)			# load atc for ADDR1
329162306a36Sopenharmony_ci	plpaw		(%a4)			# load atc for ADDR1+3
329262306a36Sopenharmony_ci	plpaw		(%a3)			# load atc for ADDR2
329362306a36Sopenharmony_ci	plpaw		(%a5)			# load atc for ADDR2+3
329462306a36Sopenharmony_ci
329562306a36Sopenharmony_ci# push the operand lines from the cache if they exist.
329662306a36Sopenharmony_ci	cpushl		%dc,(%a2)		# push line for ADDR1
329762306a36Sopenharmony_ci	cpushl		%dc,(%a4)		# push line for ADDR1+3
329862306a36Sopenharmony_ci	cpushl		%dc,(%a3)		# push line for ADDR2
329962306a36Sopenharmony_ci	cpushl		%dc,(%a5)		# push line for ADDR2+2
330062306a36Sopenharmony_ci
330162306a36Sopenharmony_ci	mov.l		%d1,%a2			# ADDR1
330262306a36Sopenharmony_ci	addq.l		&0x3,%d1
330362306a36Sopenharmony_ci	mov.l		%d1,%a4			# ADDR1+3
330462306a36Sopenharmony_ci# if ADDR1 was ATC resident before the above "plpaw" and was executed
330562306a36Sopenharmony_ci# and it was the next entry scheduled for replacement and ADDR2
330662306a36Sopenharmony_ci# shares the same set, then the "plpaw" for ADDR2 can push the ADDR1
330762306a36Sopenharmony_ci# entries from the ATC. so, we do a second set of "plpa"s.
330862306a36Sopenharmony_ci	plpar		(%a2)			# load atc for ADDR1
330962306a36Sopenharmony_ci	plpar		(%a4)			# load atc for ADDR1+3
331062306a36Sopenharmony_ci
331162306a36Sopenharmony_ci# load the BUSCR values.
331262306a36Sopenharmony_ci	mov.l		&0x80000000,%a2		# assert LOCK* buscr value
331362306a36Sopenharmony_ci	mov.l		&0xa0000000,%a3		# assert LOCKE* buscr value
331462306a36Sopenharmony_ci	mov.l		&0x00000000,%a4		# buscr unlock value
331562306a36Sopenharmony_ci
331662306a36Sopenharmony_ci# there are three possible mis-aligned cases for longword cas. they
331762306a36Sopenharmony_ci# are separated because the final write which asserts LOCKE* must
331862306a36Sopenharmony_ci# be aligned.
331962306a36Sopenharmony_ci	mov.l		%a0,%d0			# is ADDR1 misaligned?
332062306a36Sopenharmony_ci	andi.b		&0x3,%d0
332162306a36Sopenharmony_ci	beq.b		CAS2L_ENTER		# no
332262306a36Sopenharmony_ci	cmpi.b		%d0,&0x2
332362306a36Sopenharmony_ci	beq.w		CAS2L2_ENTER		# yes; word misaligned
332462306a36Sopenharmony_ci	bra.w		CAS2L3_ENTER		# yes; byte misaligned
332562306a36Sopenharmony_ci
332662306a36Sopenharmony_ci#
332762306a36Sopenharmony_ci# D0 = dst operand 1 <-
332862306a36Sopenharmony_ci# D1 = dst operand 2 <-
332962306a36Sopenharmony_ci# D2 = cmp operand 1
333062306a36Sopenharmony_ci# D3 = cmp operand 2
333162306a36Sopenharmony_ci# D4 = update oper 1
333262306a36Sopenharmony_ci# D5 = update oper 2
333362306a36Sopenharmony_ci# D6 = old SFC/DFC
333462306a36Sopenharmony_ci# D7 = old SR
333562306a36Sopenharmony_ci# A0 = ADDR1
333662306a36Sopenharmony_ci# A1 = ADDR2
333762306a36Sopenharmony_ci# A2 = bus LOCK*  value
333862306a36Sopenharmony_ci# A3 = bus LOCKE* value
333962306a36Sopenharmony_ci# A4 = bus unlock value
334062306a36Sopenharmony_ci# A5 = xxxxxxxx
334162306a36Sopenharmony_ci#
334262306a36Sopenharmony_ci	align		0x10
334362306a36Sopenharmony_ciCAS2L_START:
334462306a36Sopenharmony_ci	movc		%a2,%buscr		# assert LOCK*
334562306a36Sopenharmony_ci	movs.l		(%a1),%d1		# fetch Dest2[31:0]
334662306a36Sopenharmony_ci	movs.l		(%a0),%d0		# fetch Dest1[31:0]
334762306a36Sopenharmony_ci	bra.b		CAS2L_CONT
334862306a36Sopenharmony_ciCAS2L_ENTER:
334962306a36Sopenharmony_ci	bra.b		~+16
335062306a36Sopenharmony_ci
335162306a36Sopenharmony_ciCAS2L_CONT:
335262306a36Sopenharmony_ci	cmp.l		%d0,%d2			# Dest1 - Compare1
335362306a36Sopenharmony_ci	bne.b		CAS2L_NOUPDATE
335462306a36Sopenharmony_ci	cmp.l		%d1,%d3			# Dest2 - Compare2
335562306a36Sopenharmony_ci	bne.b		CAS2L_NOUPDATE
335662306a36Sopenharmony_ci	movs.l		%d5,(%a1)		# Update2[31:0] -> DEST2
335762306a36Sopenharmony_ci	bra.b		CAS2L_UPDATE
335862306a36Sopenharmony_ci	bra.b		~+16
335962306a36Sopenharmony_ci
336062306a36Sopenharmony_ciCAS2L_UPDATE:
336162306a36Sopenharmony_ci	movc		%a3,%buscr		# assert LOCKE*
336262306a36Sopenharmony_ci	movs.l		%d4,(%a0)		# Update1[31:0] -> DEST1
336362306a36Sopenharmony_ci	movc		%a4,%buscr		# unlock the bus
336462306a36Sopenharmony_ci	bra.b		cas2l_update_done
336562306a36Sopenharmony_ci	bra.b		~+16
336662306a36Sopenharmony_ci
336762306a36Sopenharmony_ciCAS2L_NOUPDATE:
336862306a36Sopenharmony_ci	movc		%a3,%buscr		# assert LOCKE*
336962306a36Sopenharmony_ci	movs.l		%d0,(%a0)		# Dest1[31:0] -> DEST1
337062306a36Sopenharmony_ci	movc		%a4,%buscr		# unlock the bus
337162306a36Sopenharmony_ci	bra.b		cas2l_noupdate_done
337262306a36Sopenharmony_ci	bra.b		~+16
337362306a36Sopenharmony_ci
337462306a36Sopenharmony_ciCAS2L_FILLER:
337562306a36Sopenharmony_ci	nop
337662306a36Sopenharmony_ci	nop
337762306a36Sopenharmony_ci	nop
337862306a36Sopenharmony_ci	nop
337962306a36Sopenharmony_ci	nop
338062306a36Sopenharmony_ci	nop
338162306a36Sopenharmony_ci	nop
338262306a36Sopenharmony_ci	bra.b		CAS2L_START
338362306a36Sopenharmony_ci
338462306a36Sopenharmony_ci####
338562306a36Sopenharmony_ci
338662306a36Sopenharmony_ci#################################################################
338762306a36Sopenharmony_ci# THIS MUST BE THE STATE OF THE INTEGER REGISTER FILE UPON	#
338862306a36Sopenharmony_ci# ENTERING _isp_cas2().						#
338962306a36Sopenharmony_ci#								#
339062306a36Sopenharmony_ci# D0 = destination[31:0] operand 1				#
339162306a36Sopenharmony_ci# D1 = destination[31:0] operand 2				#
339262306a36Sopenharmony_ci# D2 = cmp[31:0] operand 1					#
339362306a36Sopenharmony_ci# D3 = cmp[31:0] operand 2					#
339462306a36Sopenharmony_ci# D4 = 'xxxxxx11 -> no reg update; 'xxxxxx00 -> update required	#
339562306a36Sopenharmony_ci# D5 = xxxxxxxx							#
339662306a36Sopenharmony_ci# D6 = xxxxxxxx							#
339762306a36Sopenharmony_ci# D7 = xxxxxxxx							#
339862306a36Sopenharmony_ci# A0 = xxxxxxxx							#
339962306a36Sopenharmony_ci# A1 = xxxxxxxx							#
340062306a36Sopenharmony_ci# A2 = xxxxxxxx							#
340162306a36Sopenharmony_ci# A3 = xxxxxxxx							#
340262306a36Sopenharmony_ci# A4 = xxxxxxxx							#
340362306a36Sopenharmony_ci# A5 = xxxxxxxx							#
340462306a36Sopenharmony_ci# A6 = frame pointer						#
340562306a36Sopenharmony_ci# A7 = stack pointer						#
340662306a36Sopenharmony_ci#################################################################
340762306a36Sopenharmony_ci
340862306a36Sopenharmony_cicas2l_noupdate_done:
340962306a36Sopenharmony_ci
341062306a36Sopenharmony_ci# restore previous SFC/DFC value.
341162306a36Sopenharmony_ci	movc		%d6,%sfc		# restore old SFC
341262306a36Sopenharmony_ci	movc		%d6,%dfc		# restore old DFC
341362306a36Sopenharmony_ci
341462306a36Sopenharmony_ci# restore previous interrupt mask level.
341562306a36Sopenharmony_ci	mov.w		%d7,%sr			# restore old SR
341662306a36Sopenharmony_ci
341762306a36Sopenharmony_ci	sf		%d4			# indicate no update was done
341862306a36Sopenharmony_ci	bra.l		_isp_cas2_finish
341962306a36Sopenharmony_ci
342062306a36Sopenharmony_cicas2l_update_done:
342162306a36Sopenharmony_ci
342262306a36Sopenharmony_ci# restore previous SFC/DFC value.
342362306a36Sopenharmony_ci	movc		%d6,%sfc		# restore old SFC
342462306a36Sopenharmony_ci	movc		%d6,%dfc		# restore old DFC
342562306a36Sopenharmony_ci
342662306a36Sopenharmony_ci# restore previous interrupt mask level.
342762306a36Sopenharmony_ci	mov.w		%d7,%sr			# restore old SR
342862306a36Sopenharmony_ci
342962306a36Sopenharmony_ci	st		%d4			# indicate update was done
343062306a36Sopenharmony_ci	bra.l		_isp_cas2_finish
343162306a36Sopenharmony_ci####
343262306a36Sopenharmony_ci
343362306a36Sopenharmony_ci	align		0x10
343462306a36Sopenharmony_ciCAS2L2_START:
343562306a36Sopenharmony_ci	movc		%a2,%buscr		# assert LOCK*
343662306a36Sopenharmony_ci	movs.l		(%a1),%d1		# fetch Dest2[31:0]
343762306a36Sopenharmony_ci	movs.l		(%a0),%d0		# fetch Dest1[31:0]
343862306a36Sopenharmony_ci	bra.b		CAS2L2_CONT
343962306a36Sopenharmony_ciCAS2L2_ENTER:
344062306a36Sopenharmony_ci	bra.b		~+16
344162306a36Sopenharmony_ci
344262306a36Sopenharmony_ciCAS2L2_CONT:
344362306a36Sopenharmony_ci	cmp.l		%d0,%d2			# Dest1 - Compare1
344462306a36Sopenharmony_ci	bne.b		CAS2L2_NOUPDATE
344562306a36Sopenharmony_ci	cmp.l		%d1,%d3			# Dest2 - Compare2
344662306a36Sopenharmony_ci	bne.b		CAS2L2_NOUPDATE
344762306a36Sopenharmony_ci	movs.l		%d5,(%a1)		# Update2[31:0] -> Dest2
344862306a36Sopenharmony_ci	bra.b		CAS2L2_UPDATE
344962306a36Sopenharmony_ci	bra.b		~+16
345062306a36Sopenharmony_ci
345162306a36Sopenharmony_ciCAS2L2_UPDATE:
345262306a36Sopenharmony_ci	swap		%d4			# get Update1[31:16]
345362306a36Sopenharmony_ci	movs.w		%d4,(%a0)+		# Update1[31:16] -> DEST1
345462306a36Sopenharmony_ci	movc		%a3,%buscr		# assert LOCKE*
345562306a36Sopenharmony_ci	swap		%d4			# get Update1[15:0]
345662306a36Sopenharmony_ci	bra.b		CAS2L2_UPDATE2
345762306a36Sopenharmony_ci	bra.b		~+16
345862306a36Sopenharmony_ci
345962306a36Sopenharmony_ciCAS2L2_UPDATE2:
346062306a36Sopenharmony_ci	movs.w		%d4,(%a0)		# Update1[15:0] -> DEST1+0x2
346162306a36Sopenharmony_ci	movc		%a4,%buscr		# unlock the bus
346262306a36Sopenharmony_ci	bra.w		cas2l_update_done
346362306a36Sopenharmony_ci	nop
346462306a36Sopenharmony_ci	bra.b		~+16
346562306a36Sopenharmony_ci
346662306a36Sopenharmony_ciCAS2L2_NOUPDATE:
346762306a36Sopenharmony_ci	swap		%d0			# get Dest1[31:16]
346862306a36Sopenharmony_ci	movs.w		%d0,(%a0)+		# Dest1[31:16] -> DEST1
346962306a36Sopenharmony_ci	movc		%a3,%buscr		# assert LOCKE*
347062306a36Sopenharmony_ci	swap		%d0			# get Dest1[15:0]
347162306a36Sopenharmony_ci	bra.b		CAS2L2_NOUPDATE2
347262306a36Sopenharmony_ci	bra.b		~+16
347362306a36Sopenharmony_ci
347462306a36Sopenharmony_ciCAS2L2_NOUPDATE2:
347562306a36Sopenharmony_ci	movs.w		%d0,(%a0)		# Dest1[15:0] -> DEST1+0x2
347662306a36Sopenharmony_ci	movc		%a4,%buscr		# unlock the bus
347762306a36Sopenharmony_ci	bra.w		cas2l_noupdate_done
347862306a36Sopenharmony_ci	nop
347962306a36Sopenharmony_ci	bra.b		~+16
348062306a36Sopenharmony_ci
348162306a36Sopenharmony_ciCAS2L2_FILLER:
348262306a36Sopenharmony_ci	nop
348362306a36Sopenharmony_ci	nop
348462306a36Sopenharmony_ci	nop
348562306a36Sopenharmony_ci	nop
348662306a36Sopenharmony_ci	nop
348762306a36Sopenharmony_ci	nop
348862306a36Sopenharmony_ci	nop
348962306a36Sopenharmony_ci	bra.b		CAS2L2_START
349062306a36Sopenharmony_ci
349162306a36Sopenharmony_ci#################################
349262306a36Sopenharmony_ci
349362306a36Sopenharmony_ci	align		0x10
349462306a36Sopenharmony_ciCAS2L3_START:
349562306a36Sopenharmony_ci	movc		%a2,%buscr		# assert LOCK*
349662306a36Sopenharmony_ci	movs.l		(%a1),%d1		# fetch Dest2[31:0]
349762306a36Sopenharmony_ci	movs.l		(%a0),%d0		# fetch Dest1[31:0]
349862306a36Sopenharmony_ci	bra.b		CAS2L3_CONT
349962306a36Sopenharmony_ciCAS2L3_ENTER:
350062306a36Sopenharmony_ci	bra.b		~+16
350162306a36Sopenharmony_ci
350262306a36Sopenharmony_ciCAS2L3_CONT:
350362306a36Sopenharmony_ci	cmp.l		%d0,%d2			# Dest1 - Compare1
350462306a36Sopenharmony_ci	bne.b		CAS2L3_NOUPDATE
350562306a36Sopenharmony_ci	cmp.l		%d1,%d3			# Dest2 - Compare2
350662306a36Sopenharmony_ci	bne.b		CAS2L3_NOUPDATE
350762306a36Sopenharmony_ci	movs.l		%d5,(%a1)		# Update2[31:0] -> DEST2
350862306a36Sopenharmony_ci	bra.b		CAS2L3_UPDATE
350962306a36Sopenharmony_ci	bra.b		~+16
351062306a36Sopenharmony_ci
351162306a36Sopenharmony_ciCAS2L3_UPDATE:
351262306a36Sopenharmony_ci	rol.l		&0x8,%d4		# get Update1[31:24]
351362306a36Sopenharmony_ci	movs.b		%d4,(%a0)+		# Update1[31:24] -> DEST1
351462306a36Sopenharmony_ci	swap		%d4			# get Update1[23:8]
351562306a36Sopenharmony_ci	movs.w		%d4,(%a0)+		# Update1[23:8] -> DEST1+0x1
351662306a36Sopenharmony_ci	bra.b		CAS2L3_UPDATE2
351762306a36Sopenharmony_ci	bra.b		~+16
351862306a36Sopenharmony_ci
351962306a36Sopenharmony_ciCAS2L3_UPDATE2:
352062306a36Sopenharmony_ci	rol.l		&0x8,%d4		# get Update1[7:0]
352162306a36Sopenharmony_ci	movc		%a3,%buscr		# assert LOCKE*
352262306a36Sopenharmony_ci	movs.b		%d4,(%a0)		# Update1[7:0] -> DEST1+0x3
352362306a36Sopenharmony_ci	bra.b		CAS2L3_UPDATE3
352462306a36Sopenharmony_ci	nop
352562306a36Sopenharmony_ci	bra.b		~+16
352662306a36Sopenharmony_ci
352762306a36Sopenharmony_ciCAS2L3_UPDATE3:
352862306a36Sopenharmony_ci	movc		%a4,%buscr		# unlock the bus
352962306a36Sopenharmony_ci	bra.w		cas2l_update_done
353062306a36Sopenharmony_ci	nop
353162306a36Sopenharmony_ci	nop
353262306a36Sopenharmony_ci	nop
353362306a36Sopenharmony_ci	bra.b		~+16
353462306a36Sopenharmony_ci
353562306a36Sopenharmony_ciCAS2L3_NOUPDATE:
353662306a36Sopenharmony_ci	rol.l		&0x8,%d0		# get Dest1[31:24]
353762306a36Sopenharmony_ci	movs.b		%d0,(%a0)+		# Dest1[31:24] -> DEST1
353862306a36Sopenharmony_ci	swap		%d0			# get Dest1[23:8]
353962306a36Sopenharmony_ci	movs.w		%d0,(%a0)+		# Dest1[23:8] -> DEST1+0x1
354062306a36Sopenharmony_ci	bra.b		CAS2L3_NOUPDATE2
354162306a36Sopenharmony_ci	bra.b		~+16
354262306a36Sopenharmony_ci
354362306a36Sopenharmony_ciCAS2L3_NOUPDATE2:
354462306a36Sopenharmony_ci	rol.l		&0x8,%d0		# get Dest1[7:0]
354562306a36Sopenharmony_ci	movc		%a3,%buscr		# assert LOCKE*
354662306a36Sopenharmony_ci	movs.b		%d0,(%a0)		# Update1[7:0] -> DEST1+0x3
354762306a36Sopenharmony_ci	bra.b		CAS2L3_NOUPDATE3
354862306a36Sopenharmony_ci	nop
354962306a36Sopenharmony_ci	bra.b		~+16
355062306a36Sopenharmony_ci
355162306a36Sopenharmony_ciCAS2L3_NOUPDATE3:
355262306a36Sopenharmony_ci	movc		%a4,%buscr		# unlock the bus
355362306a36Sopenharmony_ci	bra.w		cas2l_noupdate_done
355462306a36Sopenharmony_ci	nop
355562306a36Sopenharmony_ci	nop
355662306a36Sopenharmony_ci	nop
355762306a36Sopenharmony_ci	bra.b		~+14
355862306a36Sopenharmony_ci
355962306a36Sopenharmony_ciCAS2L3_FILLER:
356062306a36Sopenharmony_ci	nop
356162306a36Sopenharmony_ci	nop
356262306a36Sopenharmony_ci	nop
356362306a36Sopenharmony_ci	nop
356462306a36Sopenharmony_ci	nop
356562306a36Sopenharmony_ci	nop
356662306a36Sopenharmony_ci	bra.w		CAS2L3_START
356762306a36Sopenharmony_ci
356862306a36Sopenharmony_ci#############################################################
356962306a36Sopenharmony_ci#############################################################
357062306a36Sopenharmony_ci
357162306a36Sopenharmony_cicas2w:
357262306a36Sopenharmony_ci	mov.l		%a0,%a2			# copy ADDR1
357362306a36Sopenharmony_ci	mov.l		%a1,%a3			# copy ADDR2
357462306a36Sopenharmony_ci	mov.l		%a0,%a4			# copy ADDR1
357562306a36Sopenharmony_ci	mov.l		%a1,%a5			# copy ADDR2
357662306a36Sopenharmony_ci
357762306a36Sopenharmony_ci	addq.l		&0x1,%a4		# ADDR1+1
357862306a36Sopenharmony_ci	addq.l		&0x1,%a5		# ADDR2+1
357962306a36Sopenharmony_ci	mov.l		%a2,%d1			# ADDR1
358062306a36Sopenharmony_ci
358162306a36Sopenharmony_ci# mask interrupt levels 0-6. save old mask value.
358262306a36Sopenharmony_ci	mov.w		%sr,%d7			# save current SR
358362306a36Sopenharmony_ci	ori.w		&0x0700,%sr		# inhibit interrupts
358462306a36Sopenharmony_ci
358562306a36Sopenharmony_ci# load the SFC and DFC with the appropriate mode.
358662306a36Sopenharmony_ci	movc		%sfc,%d6		# save old SFC/DFC
358762306a36Sopenharmony_ci	movc		%d0,%sfc		# store new SFC
358862306a36Sopenharmony_ci	movc		%d0,%dfc		# store new DFC
358962306a36Sopenharmony_ci
359062306a36Sopenharmony_ci# pre-load the operand ATC. no page faults should occur because
359162306a36Sopenharmony_ci# _real_lock_page() should have taken care of this.
359262306a36Sopenharmony_ci	plpaw		(%a2)			# load atc for ADDR1
359362306a36Sopenharmony_ci	plpaw		(%a4)			# load atc for ADDR1+1
359462306a36Sopenharmony_ci	plpaw		(%a3)			# load atc for ADDR2
359562306a36Sopenharmony_ci	plpaw		(%a5)			# load atc for ADDR2+1
359662306a36Sopenharmony_ci
359762306a36Sopenharmony_ci# push the operand cache lines from the cache if they exist.
359862306a36Sopenharmony_ci	cpushl		%dc,(%a2)		# push line for ADDR1
359962306a36Sopenharmony_ci	cpushl		%dc,(%a4)		# push line for ADDR1+1
360062306a36Sopenharmony_ci	cpushl		%dc,(%a3)		# push line for ADDR2
360162306a36Sopenharmony_ci	cpushl		%dc,(%a5)		# push line for ADDR2+1
360262306a36Sopenharmony_ci
360362306a36Sopenharmony_ci	mov.l		%d1,%a2			# ADDR1
360462306a36Sopenharmony_ci	addq.l		&0x3,%d1
360562306a36Sopenharmony_ci	mov.l		%d1,%a4			# ADDR1+3
360662306a36Sopenharmony_ci# if ADDR1 was ATC resident before the above "plpaw" and was executed
360762306a36Sopenharmony_ci# and it was the next entry scheduled for replacement and ADDR2
360862306a36Sopenharmony_ci# shares the same set, then the "plpaw" for ADDR2 can push the ADDR1
360962306a36Sopenharmony_ci# entries from the ATC. so, we do a second set of "plpa"s.
361062306a36Sopenharmony_ci	plpar		(%a2)			# load atc for ADDR1
361162306a36Sopenharmony_ci	plpar		(%a4)			# load atc for ADDR1+3
361262306a36Sopenharmony_ci
361362306a36Sopenharmony_ci# load the BUSCR values.
361462306a36Sopenharmony_ci	mov.l		&0x80000000,%a2		# assert LOCK* buscr value
361562306a36Sopenharmony_ci	mov.l		&0xa0000000,%a3		# assert LOCKE* buscr value
361662306a36Sopenharmony_ci	mov.l		&0x00000000,%a4		# buscr unlock value
361762306a36Sopenharmony_ci
361862306a36Sopenharmony_ci# there are two possible mis-aligned cases for word cas. they
361962306a36Sopenharmony_ci# are separated because the final write which asserts LOCKE* must
362062306a36Sopenharmony_ci# be aligned.
362162306a36Sopenharmony_ci	mov.l		%a0,%d0			# is ADDR1 misaligned?
362262306a36Sopenharmony_ci	btst		&0x0,%d0
362362306a36Sopenharmony_ci	bne.w		CAS2W2_ENTER		# yes
362462306a36Sopenharmony_ci	bra.b		CAS2W_ENTER		# no
362562306a36Sopenharmony_ci
362662306a36Sopenharmony_ci#
362762306a36Sopenharmony_ci# D0 = dst operand 1 <-
362862306a36Sopenharmony_ci# D1 = dst operand 2 <-
362962306a36Sopenharmony_ci# D2 = cmp operand 1
363062306a36Sopenharmony_ci# D3 = cmp operand 2
363162306a36Sopenharmony_ci# D4 = update oper 1
363262306a36Sopenharmony_ci# D5 = update oper 2
363362306a36Sopenharmony_ci# D6 = old SFC/DFC
363462306a36Sopenharmony_ci# D7 = old SR
363562306a36Sopenharmony_ci# A0 = ADDR1
363662306a36Sopenharmony_ci# A1 = ADDR2
363762306a36Sopenharmony_ci# A2 = bus LOCK*  value
363862306a36Sopenharmony_ci# A3 = bus LOCKE* value
363962306a36Sopenharmony_ci# A4 = bus unlock value
364062306a36Sopenharmony_ci# A5 = xxxxxxxx
364162306a36Sopenharmony_ci#
364262306a36Sopenharmony_ci	align		0x10
364362306a36Sopenharmony_ciCAS2W_START:
364462306a36Sopenharmony_ci	movc		%a2,%buscr		# assert LOCK*
364562306a36Sopenharmony_ci	movs.w		(%a1),%d1		# fetch Dest2[15:0]
364662306a36Sopenharmony_ci	movs.w		(%a0),%d0		# fetch Dest1[15:0]
364762306a36Sopenharmony_ci	bra.b		CAS2W_CONT2
364862306a36Sopenharmony_ciCAS2W_ENTER:
364962306a36Sopenharmony_ci	bra.b		~+16
365062306a36Sopenharmony_ci
365162306a36Sopenharmony_ciCAS2W_CONT2:
365262306a36Sopenharmony_ci	cmp.w		%d0,%d2			# Dest1 - Compare1
365362306a36Sopenharmony_ci	bne.b		CAS2W_NOUPDATE
365462306a36Sopenharmony_ci	cmp.w		%d1,%d3			# Dest2 - Compare2
365562306a36Sopenharmony_ci	bne.b		CAS2W_NOUPDATE
365662306a36Sopenharmony_ci	movs.w		%d5,(%a1)		# Update2[15:0] -> DEST2
365762306a36Sopenharmony_ci	bra.b		CAS2W_UPDATE
365862306a36Sopenharmony_ci	bra.b		~+16
365962306a36Sopenharmony_ci
366062306a36Sopenharmony_ciCAS2W_UPDATE:
366162306a36Sopenharmony_ci	movc		%a3,%buscr		# assert LOCKE*
366262306a36Sopenharmony_ci	movs.w		%d4,(%a0)		# Update1[15:0] -> DEST1
366362306a36Sopenharmony_ci	movc		%a4,%buscr		# unlock the bus
366462306a36Sopenharmony_ci	bra.b		cas2w_update_done
366562306a36Sopenharmony_ci	bra.b		~+16
366662306a36Sopenharmony_ci
366762306a36Sopenharmony_ciCAS2W_NOUPDATE:
366862306a36Sopenharmony_ci	movc		%a3,%buscr		# assert LOCKE*
366962306a36Sopenharmony_ci	movs.w		%d0,(%a0)		# Dest1[15:0] -> DEST1
367062306a36Sopenharmony_ci	movc		%a4,%buscr		# unlock the bus
367162306a36Sopenharmony_ci	bra.b		cas2w_noupdate_done
367262306a36Sopenharmony_ci	bra.b		~+16
367362306a36Sopenharmony_ci
367462306a36Sopenharmony_ciCAS2W_FILLER:
367562306a36Sopenharmony_ci	nop
367662306a36Sopenharmony_ci	nop
367762306a36Sopenharmony_ci	nop
367862306a36Sopenharmony_ci	nop
367962306a36Sopenharmony_ci	nop
368062306a36Sopenharmony_ci	nop
368162306a36Sopenharmony_ci	nop
368262306a36Sopenharmony_ci	bra.b		CAS2W_START
368362306a36Sopenharmony_ci
368462306a36Sopenharmony_ci####
368562306a36Sopenharmony_ci
368662306a36Sopenharmony_ci#################################################################
368762306a36Sopenharmony_ci# THIS MUST BE THE STATE OF THE INTEGER REGISTER FILE UPON	#
368862306a36Sopenharmony_ci# ENTERING _isp_cas2().						#
368962306a36Sopenharmony_ci#								#
369062306a36Sopenharmony_ci# D0 = destination[15:0] operand 1				#
369162306a36Sopenharmony_ci# D1 = destination[15:0] operand 2				#
369262306a36Sopenharmony_ci# D2 = cmp[15:0] operand 1					#
369362306a36Sopenharmony_ci# D3 = cmp[15:0] operand 2					#
369462306a36Sopenharmony_ci# D4 = 'xxxxxx11 -> no reg update; 'xxxxxx00 -> update required	#
369562306a36Sopenharmony_ci# D5 = xxxxxxxx							#
369662306a36Sopenharmony_ci# D6 = xxxxxxxx							#
369762306a36Sopenharmony_ci# D7 = xxxxxxxx							#
369862306a36Sopenharmony_ci# A0 = xxxxxxxx							#
369962306a36Sopenharmony_ci# A1 = xxxxxxxx							#
370062306a36Sopenharmony_ci# A2 = xxxxxxxx							#
370162306a36Sopenharmony_ci# A3 = xxxxxxxx							#
370262306a36Sopenharmony_ci# A4 = xxxxxxxx							#
370362306a36Sopenharmony_ci# A5 = xxxxxxxx							#
370462306a36Sopenharmony_ci# A6 = frame pointer						#
370562306a36Sopenharmony_ci# A7 = stack pointer						#
370662306a36Sopenharmony_ci#################################################################
370762306a36Sopenharmony_ci
370862306a36Sopenharmony_cicas2w_noupdate_done:
370962306a36Sopenharmony_ci
371062306a36Sopenharmony_ci# restore previous SFC/DFC value.
371162306a36Sopenharmony_ci	movc		%d6,%sfc		# restore old SFC
371262306a36Sopenharmony_ci	movc		%d6,%dfc		# restore old DFC
371362306a36Sopenharmony_ci
371462306a36Sopenharmony_ci# restore previous interrupt mask level.
371562306a36Sopenharmony_ci	mov.w		%d7,%sr			# restore old SR
371662306a36Sopenharmony_ci
371762306a36Sopenharmony_ci	sf		%d4			# indicate no update was done
371862306a36Sopenharmony_ci	bra.l		_isp_cas2_finish
371962306a36Sopenharmony_ci
372062306a36Sopenharmony_cicas2w_update_done:
372162306a36Sopenharmony_ci
372262306a36Sopenharmony_ci# restore previous SFC/DFC value.
372362306a36Sopenharmony_ci	movc		%d6,%sfc		# restore old SFC
372462306a36Sopenharmony_ci	movc		%d6,%dfc		# restore old DFC
372562306a36Sopenharmony_ci
372662306a36Sopenharmony_ci# restore previous interrupt mask level.
372762306a36Sopenharmony_ci	mov.w		%d7,%sr			# restore old SR
372862306a36Sopenharmony_ci
372962306a36Sopenharmony_ci	st		%d4			# indicate update was done
373062306a36Sopenharmony_ci	bra.l		_isp_cas2_finish
373162306a36Sopenharmony_ci####
373262306a36Sopenharmony_ci
373362306a36Sopenharmony_ci	align		0x10
373462306a36Sopenharmony_ciCAS2W2_START:
373562306a36Sopenharmony_ci	movc		%a2,%buscr		# assert LOCK*
373662306a36Sopenharmony_ci	movs.w		(%a1),%d1		# fetch Dest2[15:0]
373762306a36Sopenharmony_ci	movs.w		(%a0),%d0		# fetch Dest1[15:0]
373862306a36Sopenharmony_ci	bra.b		CAS2W2_CONT2
373962306a36Sopenharmony_ciCAS2W2_ENTER:
374062306a36Sopenharmony_ci	bra.b		~+16
374162306a36Sopenharmony_ci
374262306a36Sopenharmony_ciCAS2W2_CONT2:
374362306a36Sopenharmony_ci	cmp.w		%d0,%d2			# Dest1 - Compare1
374462306a36Sopenharmony_ci	bne.b		CAS2W2_NOUPDATE
374562306a36Sopenharmony_ci	cmp.w		%d1,%d3			# Dest2 - Compare2
374662306a36Sopenharmony_ci	bne.b		CAS2W2_NOUPDATE
374762306a36Sopenharmony_ci	movs.w		%d5,(%a1)		# Update2[15:0] -> DEST2
374862306a36Sopenharmony_ci	bra.b		CAS2W2_UPDATE
374962306a36Sopenharmony_ci	bra.b		~+16
375062306a36Sopenharmony_ci
375162306a36Sopenharmony_ciCAS2W2_UPDATE:
375262306a36Sopenharmony_ci	ror.l		&0x8,%d4		# get Update1[15:8]
375362306a36Sopenharmony_ci	movs.b		%d4,(%a0)+		# Update1[15:8] -> DEST1
375462306a36Sopenharmony_ci	movc		%a3,%buscr		# assert LOCKE*
375562306a36Sopenharmony_ci	rol.l		&0x8,%d4		# get Update1[7:0]
375662306a36Sopenharmony_ci	bra.b		CAS2W2_UPDATE2
375762306a36Sopenharmony_ci	bra.b		~+16
375862306a36Sopenharmony_ci
375962306a36Sopenharmony_ciCAS2W2_UPDATE2:
376062306a36Sopenharmony_ci	movs.b		%d4,(%a0)		# Update1[7:0] -> DEST1+0x1
376162306a36Sopenharmony_ci	movc		%a4,%buscr		# unlock the bus
376262306a36Sopenharmony_ci	bra.w		cas2w_update_done
376362306a36Sopenharmony_ci	nop
376462306a36Sopenharmony_ci	bra.b		~+16
376562306a36Sopenharmony_ci
376662306a36Sopenharmony_ciCAS2W2_NOUPDATE:
376762306a36Sopenharmony_ci	ror.l		&0x8,%d0		# get Dest1[15:8]
376862306a36Sopenharmony_ci	movs.b		%d0,(%a0)+		# Dest1[15:8] -> DEST1
376962306a36Sopenharmony_ci	movc		%a3,%buscr		# assert LOCKE*
377062306a36Sopenharmony_ci	rol.l		&0x8,%d0		# get Dest1[7:0]
377162306a36Sopenharmony_ci	bra.b		CAS2W2_NOUPDATE2
377262306a36Sopenharmony_ci	bra.b		~+16
377362306a36Sopenharmony_ci
377462306a36Sopenharmony_ciCAS2W2_NOUPDATE2:
377562306a36Sopenharmony_ci	movs.b		%d0,(%a0)		# Dest1[7:0] -> DEST1+0x1
377662306a36Sopenharmony_ci	movc		%a4,%buscr		# unlock the bus
377762306a36Sopenharmony_ci	bra.w		cas2w_noupdate_done
377862306a36Sopenharmony_ci	nop
377962306a36Sopenharmony_ci	bra.b		~+16
378062306a36Sopenharmony_ci
378162306a36Sopenharmony_ciCAS2W2_FILLER:
378262306a36Sopenharmony_ci	nop
378362306a36Sopenharmony_ci	nop
378462306a36Sopenharmony_ci	nop
378562306a36Sopenharmony_ci	nop
378662306a36Sopenharmony_ci	nop
378762306a36Sopenharmony_ci	nop
378862306a36Sopenharmony_ci	nop
378962306a36Sopenharmony_ci	bra.b		CAS2W2_START
379062306a36Sopenharmony_ci
379162306a36Sopenharmony_ci#       ######      ##      ######
379262306a36Sopenharmony_ci#       #	   #  #     #
379362306a36Sopenharmony_ci#	#	  ######    ######
379462306a36Sopenharmony_ci#	#	  #    #         #
379562306a36Sopenharmony_ci#       ######    #    #    ######
379662306a36Sopenharmony_ci
379762306a36Sopenharmony_ci#########################################################################
379862306a36Sopenharmony_ci# XDEF ****************************************************************	#
379962306a36Sopenharmony_ci#	_isp_cas(): "core" emulation code for the cas instruction	#
380062306a36Sopenharmony_ci#									#
380162306a36Sopenharmony_ci# XREF ****************************************************************	#
380262306a36Sopenharmony_ci#	_isp_cas_finish() - only exit point for this emulation code;	#
380362306a36Sopenharmony_ci#			    do clean-up					#
380462306a36Sopenharmony_ci#									#
380562306a36Sopenharmony_ci# INPUT ***************************************************************	#
380662306a36Sopenharmony_ci#	*see entry chart below*						#
380762306a36Sopenharmony_ci#									#
380862306a36Sopenharmony_ci# OUTPUT **************************************************************	#
380962306a36Sopenharmony_ci#	*see exit chart below*						#
381062306a36Sopenharmony_ci#									#
381162306a36Sopenharmony_ci# ALGORITHM ***********************************************************	#
381262306a36Sopenharmony_ci#	(1) Make several copies of the effective address.		#
381362306a36Sopenharmony_ci#	(2) Save current SR; Then mask off all maskable interrupts.	#
381462306a36Sopenharmony_ci#	(3) Save current DFC/SFC (ASSUMED TO BE EQUAL!!!); Then set	#
381562306a36Sopenharmony_ci#	    SFC/DFC according to whether exception occurred in user or	#
381662306a36Sopenharmony_ci#	    supervisor mode.						#
381762306a36Sopenharmony_ci#	(4) Use "plpaw" instruction to pre-load ATC with effective	#
381862306a36Sopenharmony_ci#	    address page(s). THIS SHOULD NOT FAULT!!! The relevant	#
381962306a36Sopenharmony_ci#	    page(s) should have been made resident prior to entering	#
382062306a36Sopenharmony_ci#	    this routine.						#
382162306a36Sopenharmony_ci#	(5) Push the operand lines from the cache w/ "cpushl".		#
382262306a36Sopenharmony_ci#	    In the 68040, this was done within the locked region. In	#
382362306a36Sopenharmony_ci#	    the 68060, it is done outside of the locked region.		#
382462306a36Sopenharmony_ci#	(6) Pre-fetch the core emulation instructions by executing one	#
382562306a36Sopenharmony_ci#	    branch within each physical line (16 bytes) of the code	#
382662306a36Sopenharmony_ci#	    before actually executing the code.				#
382762306a36Sopenharmony_ci#	(7) Load the BUSCR with the bus lock value.			#
382862306a36Sopenharmony_ci#	(8) Fetch the source operand.					#
382962306a36Sopenharmony_ci#	(9) Do the compare. If equal, go to step (12).			#
383062306a36Sopenharmony_ci#	(10)Unequal. No update occurs. But, we do write the DST op back	#
383162306a36Sopenharmony_ci#	    to itself (as w/ the '040) so we can gracefully unlock	#
383262306a36Sopenharmony_ci#	    the bus (and assert LOCKE*) using BUSCR and the final move.	#
383362306a36Sopenharmony_ci#	(11)Exit.							#
383462306a36Sopenharmony_ci#	(12)Write update operand to the DST location. Use BUSCR to	#
383562306a36Sopenharmony_ci#	    assert LOCKE* for the final write operation.		#
383662306a36Sopenharmony_ci#	(13)Exit.							#
383762306a36Sopenharmony_ci#									#
383862306a36Sopenharmony_ci#	The algorithm is actually implemented slightly differently	#
383962306a36Sopenharmony_ci# depending on the size of the operation and the misalignment of the	#
384062306a36Sopenharmony_ci# operand. A misaligned operand must be written in aligned chunks or	#
384162306a36Sopenharmony_ci# else the BUSCR register control gets confused.			#
384262306a36Sopenharmony_ci#									#
384362306a36Sopenharmony_ci#########################################################################
384462306a36Sopenharmony_ci
384562306a36Sopenharmony_ci#########################################################
384662306a36Sopenharmony_ci# THIS IS THE STATE OF THE INTEGER REGISTER FILE UPON	#
384762306a36Sopenharmony_ci# ENTERING _isp_cas().					#
384862306a36Sopenharmony_ci#							#
384962306a36Sopenharmony_ci# D0 = xxxxxxxx						#
385062306a36Sopenharmony_ci# D1 = xxxxxxxx						#
385162306a36Sopenharmony_ci# D2 = update operand					#
385262306a36Sopenharmony_ci# D3 = xxxxxxxx						#
385362306a36Sopenharmony_ci# D4 = compare operand					#
385462306a36Sopenharmony_ci# D5 = xxxxxxxx						#
385562306a36Sopenharmony_ci# D6 = supervisor ('xxxxxxff) or user mode ('xxxxxx00)	#
385662306a36Sopenharmony_ci# D7 = longword ('xxxxxxff) or word size ('xxxxxx00)	#
385762306a36Sopenharmony_ci# A0 = ADDR						#
385862306a36Sopenharmony_ci# A1 = xxxxxxxx						#
385962306a36Sopenharmony_ci# A2 = xxxxxxxx						#
386062306a36Sopenharmony_ci# A3 = xxxxxxxx						#
386162306a36Sopenharmony_ci# A4 = xxxxxxxx						#
386262306a36Sopenharmony_ci# A5 = xxxxxxxx						#
386362306a36Sopenharmony_ci# A6 = frame pointer					#
386462306a36Sopenharmony_ci# A7 = stack pointer					#
386562306a36Sopenharmony_ci#########################################################
386662306a36Sopenharmony_ci
386762306a36Sopenharmony_ci	global		_isp_cas
386862306a36Sopenharmony_ci_isp_cas:
386962306a36Sopenharmony_ci	tst.b		%d6			# user or supervisor mode?
387062306a36Sopenharmony_ci	bne.b		cas_super		# supervisor
387162306a36Sopenharmony_cicas_user:
387262306a36Sopenharmony_ci	movq.l		&0x1,%d0		# load user data fc
387362306a36Sopenharmony_ci	bra.b		cas_cont
387462306a36Sopenharmony_cicas_super:
387562306a36Sopenharmony_ci	movq.l		&0x5,%d0		# load supervisor data fc
387662306a36Sopenharmony_ci
387762306a36Sopenharmony_cicas_cont:
387862306a36Sopenharmony_ci	tst.b		%d7			# word or longword?
387962306a36Sopenharmony_ci	bne.w		casl			# longword
388062306a36Sopenharmony_ci
388162306a36Sopenharmony_ci####
388262306a36Sopenharmony_cicasw:
388362306a36Sopenharmony_ci	mov.l		%a0,%a1			# make copy for plpaw1
388462306a36Sopenharmony_ci	mov.l		%a0,%a2			# make copy for plpaw2
388562306a36Sopenharmony_ci	addq.l		&0x1,%a2		# plpaw2 points to end of word
388662306a36Sopenharmony_ci
388762306a36Sopenharmony_ci	mov.l		%d2,%d3			# d3 = update[7:0]
388862306a36Sopenharmony_ci	lsr.w		&0x8,%d2		# d2 = update[15:8]
388962306a36Sopenharmony_ci
389062306a36Sopenharmony_ci# mask interrupt levels 0-6. save old mask value.
389162306a36Sopenharmony_ci	mov.w		%sr,%d7			# save current SR
389262306a36Sopenharmony_ci	ori.w		&0x0700,%sr		# inhibit interrupts
389362306a36Sopenharmony_ci
389462306a36Sopenharmony_ci# load the SFC and DFC with the appropriate mode.
389562306a36Sopenharmony_ci	movc		%sfc,%d6		# save old SFC/DFC
389662306a36Sopenharmony_ci	movc		%d0,%sfc		# load new sfc
389762306a36Sopenharmony_ci	movc		%d0,%dfc		# load new dfc
389862306a36Sopenharmony_ci
389962306a36Sopenharmony_ci# pre-load the operand ATC. no page faults should occur here because
390062306a36Sopenharmony_ci# _real_lock_page() should have taken care of this.
390162306a36Sopenharmony_ci	plpaw		(%a1)			# load atc for ADDR
390262306a36Sopenharmony_ci	plpaw		(%a2)			# load atc for ADDR+1
390362306a36Sopenharmony_ci
390462306a36Sopenharmony_ci# push the operand lines from the cache if they exist.
390562306a36Sopenharmony_ci	cpushl		%dc,(%a1)		# push dirty data
390662306a36Sopenharmony_ci	cpushl		%dc,(%a2)		# push dirty data
390762306a36Sopenharmony_ci
390862306a36Sopenharmony_ci# load the BUSCR values.
390962306a36Sopenharmony_ci	mov.l		&0x80000000,%a1		# assert LOCK* buscr value
391062306a36Sopenharmony_ci	mov.l		&0xa0000000,%a2		# assert LOCKE* buscr value
391162306a36Sopenharmony_ci	mov.l		&0x00000000,%a3		# buscr unlock value
391262306a36Sopenharmony_ci
391362306a36Sopenharmony_ci# pre-load the instruction cache for the following algorithm.
391462306a36Sopenharmony_ci# this will minimize the number of cycles that LOCK* will be asserted.
391562306a36Sopenharmony_ci	bra.b		CASW_ENTER		# start pre-loading icache
391662306a36Sopenharmony_ci
391762306a36Sopenharmony_ci#
391862306a36Sopenharmony_ci# D0 = dst operand <-
391962306a36Sopenharmony_ci# D1 = update[15:8] operand
392062306a36Sopenharmony_ci# D2 = update[7:0]  operand
392162306a36Sopenharmony_ci# D3 = xxxxxxxx
392262306a36Sopenharmony_ci# D4 = compare[15:0] operand
392362306a36Sopenharmony_ci# D5 = xxxxxxxx
392462306a36Sopenharmony_ci# D6 = old SFC/DFC
392562306a36Sopenharmony_ci# D7 = old SR
392662306a36Sopenharmony_ci# A0 = ADDR
392762306a36Sopenharmony_ci# A1 = bus LOCK*  value
392862306a36Sopenharmony_ci# A2 = bus LOCKE* value
392962306a36Sopenharmony_ci# A3 = bus unlock value
393062306a36Sopenharmony_ci# A4 = xxxxxxxx
393162306a36Sopenharmony_ci# A5 = xxxxxxxx
393262306a36Sopenharmony_ci#
393362306a36Sopenharmony_ci	align		0x10
393462306a36Sopenharmony_ciCASW_START:
393562306a36Sopenharmony_ci	movc		%a1,%buscr		# assert LOCK*
393662306a36Sopenharmony_ci	movs.w		(%a0),%d0		# fetch Dest[15:0]
393762306a36Sopenharmony_ci	cmp.w		%d0,%d4			# Dest - Compare
393862306a36Sopenharmony_ci	bne.b		CASW_NOUPDATE
393962306a36Sopenharmony_ci	bra.b		CASW_UPDATE
394062306a36Sopenharmony_ciCASW_ENTER:
394162306a36Sopenharmony_ci	bra.b		~+16
394262306a36Sopenharmony_ci
394362306a36Sopenharmony_ciCASW_UPDATE:
394462306a36Sopenharmony_ci	movs.b		%d2,(%a0)+		# Update[15:8] -> DEST
394562306a36Sopenharmony_ci	movc		%a2,%buscr		# assert LOCKE*
394662306a36Sopenharmony_ci	movs.b		%d3,(%a0)		# Update[7:0] -> DEST+0x1
394762306a36Sopenharmony_ci	bra.b		CASW_UPDATE2
394862306a36Sopenharmony_ci	bra.b		~+16
394962306a36Sopenharmony_ci
395062306a36Sopenharmony_ciCASW_UPDATE2:
395162306a36Sopenharmony_ci	movc		%a3,%buscr		# unlock the bus
395262306a36Sopenharmony_ci	bra.b		casw_update_done
395362306a36Sopenharmony_ci	nop
395462306a36Sopenharmony_ci	nop
395562306a36Sopenharmony_ci	nop
395662306a36Sopenharmony_ci	nop
395762306a36Sopenharmony_ci	bra.b		~+16
395862306a36Sopenharmony_ci
395962306a36Sopenharmony_ciCASW_NOUPDATE:
396062306a36Sopenharmony_ci	ror.l		&0x8,%d0		# get Dest[15:8]
396162306a36Sopenharmony_ci	movs.b		%d0,(%a0)+		# Dest[15:8] -> DEST
396262306a36Sopenharmony_ci	movc		%a2,%buscr		# assert LOCKE*
396362306a36Sopenharmony_ci	rol.l		&0x8,%d0		# get Dest[7:0]
396462306a36Sopenharmony_ci	bra.b		CASW_NOUPDATE2
396562306a36Sopenharmony_ci	bra.b		~+16
396662306a36Sopenharmony_ci
396762306a36Sopenharmony_ciCASW_NOUPDATE2:
396862306a36Sopenharmony_ci	movs.b		%d0,(%a0)		# Dest[7:0] -> DEST+0x1
396962306a36Sopenharmony_ci	movc		%a3,%buscr		# unlock the bus
397062306a36Sopenharmony_ci	bra.b		casw_noupdate_done
397162306a36Sopenharmony_ci	nop
397262306a36Sopenharmony_ci	nop
397362306a36Sopenharmony_ci	bra.b		~+16
397462306a36Sopenharmony_ci
397562306a36Sopenharmony_ciCASW_FILLER:
397662306a36Sopenharmony_ci	nop
397762306a36Sopenharmony_ci	nop
397862306a36Sopenharmony_ci	nop
397962306a36Sopenharmony_ci	nop
398062306a36Sopenharmony_ci	nop
398162306a36Sopenharmony_ci	nop
398262306a36Sopenharmony_ci	nop
398362306a36Sopenharmony_ci	bra.b		CASW_START
398462306a36Sopenharmony_ci
398562306a36Sopenharmony_ci#################################################################
398662306a36Sopenharmony_ci# THIS MUST BE THE STATE OF THE INTEGER REGISTER FILE UPON	#
398762306a36Sopenharmony_ci# CALLING _isp_cas_finish().					#
398862306a36Sopenharmony_ci#								#
398962306a36Sopenharmony_ci# D0 = destination[15:0] operand				#
399062306a36Sopenharmony_ci# D1 = 'xxxxxx11 -> no reg update; 'xxxxxx00 -> update required	#
399162306a36Sopenharmony_ci# D2 = xxxxxxxx							#
399262306a36Sopenharmony_ci# D3 = xxxxxxxx							#
399362306a36Sopenharmony_ci# D4 = compare[15:0] operand					#
399462306a36Sopenharmony_ci# D5 = xxxxxxxx							#
399562306a36Sopenharmony_ci# D6 = xxxxxxxx							#
399662306a36Sopenharmony_ci# D7 = xxxxxxxx							#
399762306a36Sopenharmony_ci# A0 = xxxxxxxx							#
399862306a36Sopenharmony_ci# A1 = xxxxxxxx							#
399962306a36Sopenharmony_ci# A2 = xxxxxxxx							#
400062306a36Sopenharmony_ci# A3 = xxxxxxxx							#
400162306a36Sopenharmony_ci# A4 = xxxxxxxx							#
400262306a36Sopenharmony_ci# A5 = xxxxxxxx							#
400362306a36Sopenharmony_ci# A6 = frame pointer						#
400462306a36Sopenharmony_ci# A7 = stack pointer						#
400562306a36Sopenharmony_ci#################################################################
400662306a36Sopenharmony_ci
400762306a36Sopenharmony_cicasw_noupdate_done:
400862306a36Sopenharmony_ci
400962306a36Sopenharmony_ci# restore previous SFC/DFC value.
401062306a36Sopenharmony_ci	movc		%d6,%sfc		# restore old SFC
401162306a36Sopenharmony_ci	movc		%d6,%dfc		# restore old DFC
401262306a36Sopenharmony_ci
401362306a36Sopenharmony_ci# restore previous interrupt mask level.
401462306a36Sopenharmony_ci	mov.w		%d7,%sr			# restore old SR
401562306a36Sopenharmony_ci
401662306a36Sopenharmony_ci	sf		%d1			# indicate no update was done
401762306a36Sopenharmony_ci	bra.l		_isp_cas_finish
401862306a36Sopenharmony_ci
401962306a36Sopenharmony_cicasw_update_done:
402062306a36Sopenharmony_ci
402162306a36Sopenharmony_ci# restore previous SFC/DFC value.
402262306a36Sopenharmony_ci	movc		%d6,%sfc		# restore old SFC
402362306a36Sopenharmony_ci	movc		%d6,%dfc		# restore old DFC
402462306a36Sopenharmony_ci
402562306a36Sopenharmony_ci# restore previous interrupt mask level.
402662306a36Sopenharmony_ci	mov.w		%d7,%sr			# restore old SR
402762306a36Sopenharmony_ci
402862306a36Sopenharmony_ci	st		%d1			# indicate update was done
402962306a36Sopenharmony_ci	bra.l		_isp_cas_finish
403062306a36Sopenharmony_ci
403162306a36Sopenharmony_ci################
403262306a36Sopenharmony_ci
403362306a36Sopenharmony_ci# there are two possible mis-aligned cases for longword cas. they
403462306a36Sopenharmony_ci# are separated because the final write which asserts LOCKE* must
403562306a36Sopenharmony_ci# be an aligned write.
403662306a36Sopenharmony_cicasl:
403762306a36Sopenharmony_ci	mov.l		%a0,%a1			# make copy for plpaw1
403862306a36Sopenharmony_ci	mov.l		%a0,%a2			# make copy for plpaw2
403962306a36Sopenharmony_ci	addq.l		&0x3,%a2		# plpaw2 points to end of longword
404062306a36Sopenharmony_ci
404162306a36Sopenharmony_ci	mov.l		%a0,%d1			# byte or word misaligned?
404262306a36Sopenharmony_ci	btst		&0x0,%d1
404362306a36Sopenharmony_ci	bne.w		casl2			# byte misaligned
404462306a36Sopenharmony_ci
404562306a36Sopenharmony_ci	mov.l		%d2,%d3			# d3 = update[15:0]
404662306a36Sopenharmony_ci	swap		%d2			# d2 = update[31:16]
404762306a36Sopenharmony_ci
404862306a36Sopenharmony_ci# mask interrupts levels 0-6. save old mask value.
404962306a36Sopenharmony_ci	mov.w		%sr,%d7			# save current SR
405062306a36Sopenharmony_ci	ori.w		&0x0700,%sr		# inhibit interrupts
405162306a36Sopenharmony_ci
405262306a36Sopenharmony_ci# load the SFC and DFC with the appropriate mode.
405362306a36Sopenharmony_ci	movc		%sfc,%d6		# save old SFC/DFC
405462306a36Sopenharmony_ci	movc		%d0,%sfc		# load new sfc
405562306a36Sopenharmony_ci	movc		%d0,%dfc		# load new dfc
405662306a36Sopenharmony_ci
405762306a36Sopenharmony_ci# pre-load the operand ATC. no page faults should occur here because
405862306a36Sopenharmony_ci# _real_lock_page() should have taken care of this.
405962306a36Sopenharmony_ci	plpaw		(%a1)			# load atc for ADDR
406062306a36Sopenharmony_ci	plpaw		(%a2)			# load atc for ADDR+3
406162306a36Sopenharmony_ci
406262306a36Sopenharmony_ci# push the operand lines from the cache if they exist.
406362306a36Sopenharmony_ci	cpushl		%dc,(%a1)		# push dirty data
406462306a36Sopenharmony_ci	cpushl		%dc,(%a2)		# push dirty data
406562306a36Sopenharmony_ci
406662306a36Sopenharmony_ci# load the BUSCR values.
406762306a36Sopenharmony_ci	mov.l		&0x80000000,%a1		# assert LOCK* buscr value
406862306a36Sopenharmony_ci	mov.l		&0xa0000000,%a2		# assert LOCKE* buscr value
406962306a36Sopenharmony_ci	mov.l		&0x00000000,%a3		# buscr unlock value
407062306a36Sopenharmony_ci
407162306a36Sopenharmony_ci	bra.b		CASL_ENTER		# start pre-loading icache
407262306a36Sopenharmony_ci
407362306a36Sopenharmony_ci#
407462306a36Sopenharmony_ci# D0 = dst operand <-
407562306a36Sopenharmony_ci# D1 = xxxxxxxx
407662306a36Sopenharmony_ci# D2 = update[31:16] operand
407762306a36Sopenharmony_ci# D3 = update[15:0]  operand
407862306a36Sopenharmony_ci# D4 = compare[31:0] operand
407962306a36Sopenharmony_ci# D5 = xxxxxxxx
408062306a36Sopenharmony_ci# D6 = old SFC/DFC
408162306a36Sopenharmony_ci# D7 = old SR
408262306a36Sopenharmony_ci# A0 = ADDR
408362306a36Sopenharmony_ci# A1 = bus LOCK*  value
408462306a36Sopenharmony_ci# A2 = bus LOCKE* value
408562306a36Sopenharmony_ci# A3 = bus unlock value
408662306a36Sopenharmony_ci# A4 = xxxxxxxx
408762306a36Sopenharmony_ci# A5 = xxxxxxxx
408862306a36Sopenharmony_ci#
408962306a36Sopenharmony_ci	align		0x10
409062306a36Sopenharmony_ciCASL_START:
409162306a36Sopenharmony_ci	movc		%a1,%buscr		# assert LOCK*
409262306a36Sopenharmony_ci	movs.l		(%a0),%d0		# fetch Dest[31:0]
409362306a36Sopenharmony_ci	cmp.l		%d0,%d4			# Dest - Compare
409462306a36Sopenharmony_ci	bne.b		CASL_NOUPDATE
409562306a36Sopenharmony_ci	bra.b		CASL_UPDATE
409662306a36Sopenharmony_ciCASL_ENTER:
409762306a36Sopenharmony_ci	bra.b		~+16
409862306a36Sopenharmony_ci
409962306a36Sopenharmony_ciCASL_UPDATE:
410062306a36Sopenharmony_ci	movs.w		%d2,(%a0)+		# Update[31:16] -> DEST
410162306a36Sopenharmony_ci	movc		%a2,%buscr		# assert LOCKE*
410262306a36Sopenharmony_ci	movs.w		%d3,(%a0)		# Update[15:0] -> DEST+0x2
410362306a36Sopenharmony_ci	bra.b		CASL_UPDATE2
410462306a36Sopenharmony_ci	bra.b		~+16
410562306a36Sopenharmony_ci
410662306a36Sopenharmony_ciCASL_UPDATE2:
410762306a36Sopenharmony_ci	movc		%a3,%buscr		# unlock the bus
410862306a36Sopenharmony_ci	bra.b		casl_update_done
410962306a36Sopenharmony_ci	nop
411062306a36Sopenharmony_ci	nop
411162306a36Sopenharmony_ci	nop
411262306a36Sopenharmony_ci	nop
411362306a36Sopenharmony_ci	bra.b		~+16
411462306a36Sopenharmony_ci
411562306a36Sopenharmony_ciCASL_NOUPDATE:
411662306a36Sopenharmony_ci	swap		%d0			# get Dest[31:16]
411762306a36Sopenharmony_ci	movs.w		%d0,(%a0)+		# Dest[31:16] -> DEST
411862306a36Sopenharmony_ci	swap		%d0			# get Dest[15:0]
411962306a36Sopenharmony_ci	movc		%a2,%buscr		# assert LOCKE*
412062306a36Sopenharmony_ci	bra.b		CASL_NOUPDATE2
412162306a36Sopenharmony_ci	bra.b		~+16
412262306a36Sopenharmony_ci
412362306a36Sopenharmony_ciCASL_NOUPDATE2:
412462306a36Sopenharmony_ci	movs.w		%d0,(%a0)		# Dest[15:0] -> DEST+0x2
412562306a36Sopenharmony_ci	movc		%a3,%buscr		# unlock the bus
412662306a36Sopenharmony_ci	bra.b		casl_noupdate_done
412762306a36Sopenharmony_ci	nop
412862306a36Sopenharmony_ci	nop
412962306a36Sopenharmony_ci	bra.b		~+16
413062306a36Sopenharmony_ci
413162306a36Sopenharmony_ciCASL_FILLER:
413262306a36Sopenharmony_ci	nop
413362306a36Sopenharmony_ci	nop
413462306a36Sopenharmony_ci	nop
413562306a36Sopenharmony_ci	nop
413662306a36Sopenharmony_ci	nop
413762306a36Sopenharmony_ci	nop
413862306a36Sopenharmony_ci	nop
413962306a36Sopenharmony_ci	bra.b		CASL_START
414062306a36Sopenharmony_ci
414162306a36Sopenharmony_ci#################################################################
414262306a36Sopenharmony_ci# THIS MUST BE THE STATE OF THE INTEGER REGISTER FILE UPON	#
414362306a36Sopenharmony_ci# CALLING _isp_cas_finish().					#
414462306a36Sopenharmony_ci#								#
414562306a36Sopenharmony_ci# D0 = destination[31:0] operand				#
414662306a36Sopenharmony_ci# D1 = 'xxxxxx11 -> no reg update; 'xxxxxx00 -> update required	#
414762306a36Sopenharmony_ci# D2 = xxxxxxxx							#
414862306a36Sopenharmony_ci# D3 = xxxxxxxx							#
414962306a36Sopenharmony_ci# D4 = compare[31:0] operand					#
415062306a36Sopenharmony_ci# D5 = xxxxxxxx							#
415162306a36Sopenharmony_ci# D6 = xxxxxxxx							#
415262306a36Sopenharmony_ci# D7 = xxxxxxxx							#
415362306a36Sopenharmony_ci# A0 = xxxxxxxx							#
415462306a36Sopenharmony_ci# A1 = xxxxxxxx							#
415562306a36Sopenharmony_ci# A2 = xxxxxxxx							#
415662306a36Sopenharmony_ci# A3 = xxxxxxxx							#
415762306a36Sopenharmony_ci# A4 = xxxxxxxx							#
415862306a36Sopenharmony_ci# A5 = xxxxxxxx							#
415962306a36Sopenharmony_ci# A6 = frame pointer						#
416062306a36Sopenharmony_ci# A7 = stack pointer						#
416162306a36Sopenharmony_ci#################################################################
416262306a36Sopenharmony_ci
416362306a36Sopenharmony_cicasl_noupdate_done:
416462306a36Sopenharmony_ci
416562306a36Sopenharmony_ci# restore previous SFC/DFC value.
416662306a36Sopenharmony_ci	movc		%d6,%sfc		# restore old SFC
416762306a36Sopenharmony_ci	movc		%d6,%dfc		# restore old DFC
416862306a36Sopenharmony_ci
416962306a36Sopenharmony_ci# restore previous interrupt mask level.
417062306a36Sopenharmony_ci	mov.w		%d7,%sr			# restore old SR
417162306a36Sopenharmony_ci
417262306a36Sopenharmony_ci	sf		%d1			# indicate no update was done
417362306a36Sopenharmony_ci	bra.l		_isp_cas_finish
417462306a36Sopenharmony_ci
417562306a36Sopenharmony_cicasl_update_done:
417662306a36Sopenharmony_ci
417762306a36Sopenharmony_ci# restore previous SFC/DFC value.
417862306a36Sopenharmony_ci	movc		%d6,%sfc		# restore old SFC
417962306a36Sopenharmony_ci	movc		%d6,%dfc		# restore old DFC
418062306a36Sopenharmony_ci
418162306a36Sopenharmony_ci# restore previous interrupts mask level.
418262306a36Sopenharmony_ci	mov.w		%d7,%sr			# restore old SR
418362306a36Sopenharmony_ci
418462306a36Sopenharmony_ci	st		%d1			# indicate update was done
418562306a36Sopenharmony_ci	bra.l		_isp_cas_finish
418662306a36Sopenharmony_ci
418762306a36Sopenharmony_ci#######################################
418862306a36Sopenharmony_cicasl2:
418962306a36Sopenharmony_ci	mov.l		%d2,%d5			# d5 = Update[7:0]
419062306a36Sopenharmony_ci	lsr.l		&0x8,%d2
419162306a36Sopenharmony_ci	mov.l		%d2,%d3			# d3 = Update[23:8]
419262306a36Sopenharmony_ci	swap		%d2			# d2 = Update[31:24]
419362306a36Sopenharmony_ci
419462306a36Sopenharmony_ci# mask interrupts levels 0-6. save old mask value.
419562306a36Sopenharmony_ci	mov.w		%sr,%d7			# save current SR
419662306a36Sopenharmony_ci	ori.w		&0x0700,%sr		# inhibit interrupts
419762306a36Sopenharmony_ci
419862306a36Sopenharmony_ci# load the SFC and DFC with the appropriate mode.
419962306a36Sopenharmony_ci	movc		%sfc,%d6		# save old SFC/DFC
420062306a36Sopenharmony_ci	movc		%d0,%sfc		# load new sfc
420162306a36Sopenharmony_ci	movc		%d0,%dfc		# load new dfc
420262306a36Sopenharmony_ci
420362306a36Sopenharmony_ci# pre-load the operand ATC. no page faults should occur here because
420462306a36Sopenharmony_ci# _real_lock_page() should have taken care of this already.
420562306a36Sopenharmony_ci	plpaw		(%a1)			# load atc for ADDR
420662306a36Sopenharmony_ci	plpaw		(%a2)			# load atc for ADDR+3
420762306a36Sopenharmony_ci
420862306a36Sopenharmony_ci# puch the operand lines from the cache if they exist.
420962306a36Sopenharmony_ci	cpushl		%dc,(%a1)		# push dirty data
421062306a36Sopenharmony_ci	cpushl		%dc,(%a2)		# push dirty data
421162306a36Sopenharmony_ci
421262306a36Sopenharmony_ci# load the BUSCR values.
421362306a36Sopenharmony_ci	mov.l		&0x80000000,%a1		# assert LOCK* buscr value
421462306a36Sopenharmony_ci	mov.l		&0xa0000000,%a2		# assert LOCKE* buscr value
421562306a36Sopenharmony_ci	mov.l		&0x00000000,%a3		# buscr unlock value
421662306a36Sopenharmony_ci
421762306a36Sopenharmony_ci# pre-load the instruction cache for the following algorithm.
421862306a36Sopenharmony_ci# this will minimize the number of cycles that LOCK* will be asserted.
421962306a36Sopenharmony_ci	bra.b		CASL2_ENTER		# start pre-loading icache
422062306a36Sopenharmony_ci
422162306a36Sopenharmony_ci#
422262306a36Sopenharmony_ci# D0 = dst operand <-
422362306a36Sopenharmony_ci# D1 = xxxxxxxx
422462306a36Sopenharmony_ci# D2 = update[31:24] operand
422562306a36Sopenharmony_ci# D3 = update[23:8]  operand
422662306a36Sopenharmony_ci# D4 = compare[31:0] operand
422762306a36Sopenharmony_ci# D5 = update[7:0]  operand
422862306a36Sopenharmony_ci# D6 = old SFC/DFC
422962306a36Sopenharmony_ci# D7 = old SR
423062306a36Sopenharmony_ci# A0 = ADDR
423162306a36Sopenharmony_ci# A1 = bus LOCK*  value
423262306a36Sopenharmony_ci# A2 = bus LOCKE* value
423362306a36Sopenharmony_ci# A3 = bus unlock value
423462306a36Sopenharmony_ci# A4 = xxxxxxxx
423562306a36Sopenharmony_ci# A5 = xxxxxxxx
423662306a36Sopenharmony_ci#
423762306a36Sopenharmony_ci	align		0x10
423862306a36Sopenharmony_ciCASL2_START:
423962306a36Sopenharmony_ci	movc		%a1,%buscr		# assert LOCK*
424062306a36Sopenharmony_ci	movs.l		(%a0),%d0		# fetch Dest[31:0]
424162306a36Sopenharmony_ci	cmp.l		%d0,%d4			# Dest - Compare
424262306a36Sopenharmony_ci	bne.b		CASL2_NOUPDATE
424362306a36Sopenharmony_ci	bra.b		CASL2_UPDATE
424462306a36Sopenharmony_ciCASL2_ENTER:
424562306a36Sopenharmony_ci	bra.b		~+16
424662306a36Sopenharmony_ci
424762306a36Sopenharmony_ciCASL2_UPDATE:
424862306a36Sopenharmony_ci	movs.b		%d2,(%a0)+		# Update[31:24] -> DEST
424962306a36Sopenharmony_ci	movs.w		%d3,(%a0)+		# Update[23:8] -> DEST+0x1
425062306a36Sopenharmony_ci	movc		%a2,%buscr		# assert LOCKE*
425162306a36Sopenharmony_ci	bra.b		CASL2_UPDATE2
425262306a36Sopenharmony_ci	bra.b		~+16
425362306a36Sopenharmony_ci
425462306a36Sopenharmony_ciCASL2_UPDATE2:
425562306a36Sopenharmony_ci	movs.b		%d5,(%a0)		# Update[7:0] -> DEST+0x3
425662306a36Sopenharmony_ci	movc		%a3,%buscr		# unlock the bus
425762306a36Sopenharmony_ci	bra.w		casl_update_done
425862306a36Sopenharmony_ci	nop
425962306a36Sopenharmony_ci	bra.b		~+16
426062306a36Sopenharmony_ci
426162306a36Sopenharmony_ciCASL2_NOUPDATE:
426262306a36Sopenharmony_ci	rol.l		&0x8,%d0		# get Dest[31:24]
426362306a36Sopenharmony_ci	movs.b		%d0,(%a0)+		# Dest[31:24] -> DEST
426462306a36Sopenharmony_ci	swap		%d0			# get Dest[23:8]
426562306a36Sopenharmony_ci	movs.w		%d0,(%a0)+		# Dest[23:8] -> DEST+0x1
426662306a36Sopenharmony_ci	bra.b		CASL2_NOUPDATE2
426762306a36Sopenharmony_ci	bra.b		~+16
426862306a36Sopenharmony_ci
426962306a36Sopenharmony_ciCASL2_NOUPDATE2:
427062306a36Sopenharmony_ci	rol.l		&0x8,%d0		# get Dest[7:0]
427162306a36Sopenharmony_ci	movc		%a2,%buscr		# assert LOCKE*
427262306a36Sopenharmony_ci	movs.b		%d0,(%a0)		# Dest[7:0] -> DEST+0x3
427362306a36Sopenharmony_ci	bra.b		CASL2_NOUPDATE3
427462306a36Sopenharmony_ci	nop
427562306a36Sopenharmony_ci	bra.b		~+16
427662306a36Sopenharmony_ci
427762306a36Sopenharmony_ciCASL2_NOUPDATE3:
427862306a36Sopenharmony_ci	movc		%a3,%buscr		# unlock the bus
427962306a36Sopenharmony_ci	bra.w		casl_noupdate_done
428062306a36Sopenharmony_ci	nop
428162306a36Sopenharmony_ci	nop
428262306a36Sopenharmony_ci	nop
428362306a36Sopenharmony_ci	bra.b		~+16
428462306a36Sopenharmony_ci
428562306a36Sopenharmony_ciCASL2_FILLER:
428662306a36Sopenharmony_ci	nop
428762306a36Sopenharmony_ci	nop
428862306a36Sopenharmony_ci	nop
428962306a36Sopenharmony_ci	nop
429062306a36Sopenharmony_ci	nop
429162306a36Sopenharmony_ci	nop
429262306a36Sopenharmony_ci	nop
429362306a36Sopenharmony_ci	bra.b		CASL2_START
429462306a36Sopenharmony_ci
429562306a36Sopenharmony_ci####
429662306a36Sopenharmony_ci####
429762306a36Sopenharmony_ci# end label used by _isp_cas_inrange()
429862306a36Sopenharmony_ci	global		_CASHI
429962306a36Sopenharmony_ci_CASHI:
4300