18c2ecf20Sopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
28c2ecf20Sopenharmony_ciMOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
38c2ecf20Sopenharmony_ciM68000 Hi-Performance Microprocessor Division
48c2ecf20Sopenharmony_ciM68060 Software Package
58c2ecf20Sopenharmony_ciProduction Release P1.00 -- October 10, 1994
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ciM68060 Software Package Copyright © 1993, 1994 Motorola Inc.  All rights reserved.
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ciTHE SOFTWARE is provided on an "AS IS" basis and without warranty.
108c2ecf20Sopenharmony_ciTo the maximum extent permitted by applicable law,
118c2ecf20Sopenharmony_ciMOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
128c2ecf20Sopenharmony_ciINCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
138c2ecf20Sopenharmony_ciand any warranty against infringement with regard to the SOFTWARE
148c2ecf20Sopenharmony_ci(INCLUDING ANY MODIFIED VERSIONS THEREOF) and any accompanying written materials.
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ciTo the maximum extent permitted by applicable law,
178c2ecf20Sopenharmony_ciIN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
188c2ecf20Sopenharmony_ci(INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS,
198c2ecf20Sopenharmony_ciBUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS)
208c2ecf20Sopenharmony_ciARISING OF THE USE OR INABILITY TO USE THE SOFTWARE.
218c2ecf20Sopenharmony_ciMotorola assumes no responsibility for the maintenance and support of the SOFTWARE.
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ciYou are hereby granted a copyright license to use, modify, and distribute the SOFTWARE
248c2ecf20Sopenharmony_ciso long as this entire notice is retained without alteration in any modified and/or
258c2ecf20Sopenharmony_ciredistributed versions, and that such modified versions are clearly identified as such.
268c2ecf20Sopenharmony_ciNo licenses are granted by implication, estoppel or otherwise under any patents
278c2ecf20Sopenharmony_cior trademarks of Motorola, Inc.
288c2ecf20Sopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
298c2ecf20Sopenharmony_ci# ireal.s:
308c2ecf20Sopenharmony_ci#	This file is appended to the top of the 060ISP package
318c2ecf20Sopenharmony_ci# and contains the entry points into the package. The user, in
328c2ecf20Sopenharmony_ci# effect, branches to one of the branch table entries located
338c2ecf20Sopenharmony_ci# after _060ISP_TABLE.
348c2ecf20Sopenharmony_ci#	Also, subroutine stubs exist in this file (_isp_done for
358c2ecf20Sopenharmony_ci# example) that are referenced by the ISP package itself in order
368c2ecf20Sopenharmony_ci# to call a given routine. The stub routine actually performs the
378c2ecf20Sopenharmony_ci# callout. The ISP code does a "bsr" to the stub routine. This
388c2ecf20Sopenharmony_ci# extra layer of hierarchy adds a slight performance penalty but
398c2ecf20Sopenharmony_ci# it makes the ISP code easier to read and more mainatinable.
408c2ecf20Sopenharmony_ci#
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ciset	_off_chk,	0x00
438c2ecf20Sopenharmony_ciset	_off_divbyzero,	0x04
448c2ecf20Sopenharmony_ciset	_off_trace,	0x08
458c2ecf20Sopenharmony_ciset	_off_access,	0x0c
468c2ecf20Sopenharmony_ciset	_off_done,	0x10
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ciset	_off_cas,	0x14
498c2ecf20Sopenharmony_ciset	_off_cas2,	0x18
508c2ecf20Sopenharmony_ciset	_off_lock,	0x1c
518c2ecf20Sopenharmony_ciset	_off_unlock,	0x20
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ciset	_off_imr,	0x40
548c2ecf20Sopenharmony_ciset	_off_dmr,	0x44
558c2ecf20Sopenharmony_ciset	_off_dmw,	0x48
568c2ecf20Sopenharmony_ciset	_off_irw,	0x4c
578c2ecf20Sopenharmony_ciset	_off_irl,	0x50
588c2ecf20Sopenharmony_ciset	_off_drb,	0x54
598c2ecf20Sopenharmony_ciset	_off_drw,	0x58
608c2ecf20Sopenharmony_ciset	_off_drl,	0x5c
618c2ecf20Sopenharmony_ciset	_off_dwb,	0x60
628c2ecf20Sopenharmony_ciset	_off_dww,	0x64
638c2ecf20Sopenharmony_ciset	_off_dwl,	0x68
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_ci_060ISP_TABLE:
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci# Here's the table of ENTRY POINTS for those linking the package.
688c2ecf20Sopenharmony_ci	bra.l		_isp_unimp
698c2ecf20Sopenharmony_ci	short		0x0000
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ci	bra.l		_isp_cas
728c2ecf20Sopenharmony_ci	short		0x0000
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci	bra.l		_isp_cas2
758c2ecf20Sopenharmony_ci	short		0x0000
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci	bra.l		_isp_cas_finish
788c2ecf20Sopenharmony_ci	short		0x0000
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ci	bra.l		_isp_cas2_finish
818c2ecf20Sopenharmony_ci	short		0x0000
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci	bra.l		_isp_cas_inrange
848c2ecf20Sopenharmony_ci	short		0x0000
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ci	bra.l		_isp_cas_terminate
878c2ecf20Sopenharmony_ci	short		0x0000
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ci	bra.l		_isp_cas_restart
908c2ecf20Sopenharmony_ci	short		0x0000
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_ci	space		64
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci#############################################################
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_ci	global		_real_chk
978c2ecf20Sopenharmony_ci_real_chk:
988c2ecf20Sopenharmony_ci	mov.l		%d0,-(%sp)
998c2ecf20Sopenharmony_ci	mov.l		(_060ISP_TABLE-0x80+_off_chk,%pc),%d0
1008c2ecf20Sopenharmony_ci	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
1018c2ecf20Sopenharmony_ci	mov.l		0x4(%sp),%d0
1028c2ecf20Sopenharmony_ci	rtd		&0x4
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_ci	global		_real_divbyzero
1058c2ecf20Sopenharmony_ci_real_divbyzero:
1068c2ecf20Sopenharmony_ci	mov.l		%d0,-(%sp)
1078c2ecf20Sopenharmony_ci	mov.l		(_060ISP_TABLE-0x80+_off_divbyzero,%pc),%d0
1088c2ecf20Sopenharmony_ci	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
1098c2ecf20Sopenharmony_ci	mov.l		0x4(%sp),%d0
1108c2ecf20Sopenharmony_ci	rtd		&0x4
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_ci	global		_real_trace
1138c2ecf20Sopenharmony_ci_real_trace:
1148c2ecf20Sopenharmony_ci	mov.l		%d0,-(%sp)
1158c2ecf20Sopenharmony_ci	mov.l		(_060ISP_TABLE-0x80+_off_trace,%pc),%d0
1168c2ecf20Sopenharmony_ci	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
1178c2ecf20Sopenharmony_ci	mov.l		0x4(%sp),%d0
1188c2ecf20Sopenharmony_ci	rtd		&0x4
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_ci	global		_real_access
1218c2ecf20Sopenharmony_ci_real_access:
1228c2ecf20Sopenharmony_ci	mov.l		%d0,-(%sp)
1238c2ecf20Sopenharmony_ci	mov.l		(_060ISP_TABLE-0x80+_off_access,%pc),%d0
1248c2ecf20Sopenharmony_ci	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
1258c2ecf20Sopenharmony_ci	mov.l		0x4(%sp),%d0
1268c2ecf20Sopenharmony_ci	rtd		&0x4
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_ci	global		_isp_done
1298c2ecf20Sopenharmony_ci_isp_done:
1308c2ecf20Sopenharmony_ci	mov.l		%d0,-(%sp)
1318c2ecf20Sopenharmony_ci	mov.l		(_060ISP_TABLE-0x80+_off_done,%pc),%d0
1328c2ecf20Sopenharmony_ci	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
1338c2ecf20Sopenharmony_ci	mov.l		0x4(%sp),%d0
1348c2ecf20Sopenharmony_ci	rtd		&0x4
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_ci#######################################
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_ci	global		_real_cas
1398c2ecf20Sopenharmony_ci_real_cas:
1408c2ecf20Sopenharmony_ci	mov.l		%d0,-(%sp)
1418c2ecf20Sopenharmony_ci	mov.l		(_060ISP_TABLE-0x80+_off_cas,%pc),%d0
1428c2ecf20Sopenharmony_ci	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
1438c2ecf20Sopenharmony_ci	mov.l		0x4(%sp),%d0
1448c2ecf20Sopenharmony_ci	rtd		&0x4
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_ci	global		_real_cas2
1478c2ecf20Sopenharmony_ci_real_cas2:
1488c2ecf20Sopenharmony_ci	mov.l		%d0,-(%sp)
1498c2ecf20Sopenharmony_ci	mov.l		(_060ISP_TABLE-0x80+_off_cas2,%pc),%d0
1508c2ecf20Sopenharmony_ci	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
1518c2ecf20Sopenharmony_ci	mov.l		0x4(%sp),%d0
1528c2ecf20Sopenharmony_ci	rtd		&0x4
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_ci	global		_real_lock_page
1558c2ecf20Sopenharmony_ci_real_lock_page:
1568c2ecf20Sopenharmony_ci	mov.l		%d0,-(%sp)
1578c2ecf20Sopenharmony_ci	mov.l		(_060ISP_TABLE-0x80+_off_lock,%pc),%d0
1588c2ecf20Sopenharmony_ci	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
1598c2ecf20Sopenharmony_ci	mov.l		0x4(%sp),%d0
1608c2ecf20Sopenharmony_ci	rtd		&0x4
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ci	global		_real_unlock_page
1638c2ecf20Sopenharmony_ci_real_unlock_page:
1648c2ecf20Sopenharmony_ci	mov.l		%d0,-(%sp)
1658c2ecf20Sopenharmony_ci	mov.l		(_060ISP_TABLE-0x80+_off_unlock,%pc),%d0
1668c2ecf20Sopenharmony_ci	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
1678c2ecf20Sopenharmony_ci	mov.l		0x4(%sp),%d0
1688c2ecf20Sopenharmony_ci	rtd		&0x4
1698c2ecf20Sopenharmony_ci
1708c2ecf20Sopenharmony_ci#######################################
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_ci	global		_imem_read
1738c2ecf20Sopenharmony_ci_imem_read:
1748c2ecf20Sopenharmony_ci	mov.l		%d0,-(%sp)
1758c2ecf20Sopenharmony_ci	mov.l		(_060ISP_TABLE-0x80+_off_imr,%pc),%d0
1768c2ecf20Sopenharmony_ci	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
1778c2ecf20Sopenharmony_ci	mov.l		0x4(%sp),%d0
1788c2ecf20Sopenharmony_ci	rtd		&0x4
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_ci	global		_dmem_read
1818c2ecf20Sopenharmony_ci_dmem_read:
1828c2ecf20Sopenharmony_ci	mov.l		%d0,-(%sp)
1838c2ecf20Sopenharmony_ci	mov.l		(_060ISP_TABLE-0x80+_off_dmr,%pc),%d0
1848c2ecf20Sopenharmony_ci	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
1858c2ecf20Sopenharmony_ci	mov.l		0x4(%sp),%d0
1868c2ecf20Sopenharmony_ci	rtd		&0x4
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_ci	global		_dmem_write
1898c2ecf20Sopenharmony_ci_dmem_write:
1908c2ecf20Sopenharmony_ci	mov.l		%d0,-(%sp)
1918c2ecf20Sopenharmony_ci	mov.l		(_060ISP_TABLE-0x80+_off_dmw,%pc),%d0
1928c2ecf20Sopenharmony_ci	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
1938c2ecf20Sopenharmony_ci	mov.l		0x4(%sp),%d0
1948c2ecf20Sopenharmony_ci	rtd		&0x4
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_ci	global		_imem_read_word
1978c2ecf20Sopenharmony_ci_imem_read_word:
1988c2ecf20Sopenharmony_ci	mov.l		%d0,-(%sp)
1998c2ecf20Sopenharmony_ci	mov.l		(_060ISP_TABLE-0x80+_off_irw,%pc),%d0
2008c2ecf20Sopenharmony_ci	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
2018c2ecf20Sopenharmony_ci	mov.l		0x4(%sp),%d0
2028c2ecf20Sopenharmony_ci	rtd		&0x4
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_ci	global		_imem_read_long
2058c2ecf20Sopenharmony_ci_imem_read_long:
2068c2ecf20Sopenharmony_ci	mov.l		%d0,-(%sp)
2078c2ecf20Sopenharmony_ci	mov.l		(_060ISP_TABLE-0x80+_off_irl,%pc),%d0
2088c2ecf20Sopenharmony_ci	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
2098c2ecf20Sopenharmony_ci	mov.l		0x4(%sp),%d0
2108c2ecf20Sopenharmony_ci	rtd		&0x4
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_ci	global		_dmem_read_byte
2138c2ecf20Sopenharmony_ci_dmem_read_byte:
2148c2ecf20Sopenharmony_ci	mov.l		%d0,-(%sp)
2158c2ecf20Sopenharmony_ci	mov.l		(_060ISP_TABLE-0x80+_off_drb,%pc),%d0
2168c2ecf20Sopenharmony_ci	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
2178c2ecf20Sopenharmony_ci	mov.l		0x4(%sp),%d0
2188c2ecf20Sopenharmony_ci	rtd		&0x4
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_ci	global		_dmem_read_word
2218c2ecf20Sopenharmony_ci_dmem_read_word:
2228c2ecf20Sopenharmony_ci	mov.l		%d0,-(%sp)
2238c2ecf20Sopenharmony_ci	mov.l		(_060ISP_TABLE-0x80+_off_drw,%pc),%d0
2248c2ecf20Sopenharmony_ci	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
2258c2ecf20Sopenharmony_ci	mov.l		0x4(%sp),%d0
2268c2ecf20Sopenharmony_ci	rtd		&0x4
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_ci	global		_dmem_read_long
2298c2ecf20Sopenharmony_ci_dmem_read_long:
2308c2ecf20Sopenharmony_ci	mov.l		%d0,-(%sp)
2318c2ecf20Sopenharmony_ci	mov.l		(_060ISP_TABLE-0x80+_off_drl,%pc),%d0
2328c2ecf20Sopenharmony_ci	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
2338c2ecf20Sopenharmony_ci	mov.l		0x4(%sp),%d0
2348c2ecf20Sopenharmony_ci	rtd		&0x4
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_ci	global		_dmem_write_byte
2378c2ecf20Sopenharmony_ci_dmem_write_byte:
2388c2ecf20Sopenharmony_ci	mov.l		%d0,-(%sp)
2398c2ecf20Sopenharmony_ci	mov.l		(_060ISP_TABLE-0x80+_off_dwb,%pc),%d0
2408c2ecf20Sopenharmony_ci	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
2418c2ecf20Sopenharmony_ci	mov.l		0x4(%sp),%d0
2428c2ecf20Sopenharmony_ci	rtd		&0x4
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_ci	global		_dmem_write_word
2458c2ecf20Sopenharmony_ci_dmem_write_word:
2468c2ecf20Sopenharmony_ci	mov.l		%d0,-(%sp)
2478c2ecf20Sopenharmony_ci	mov.l		(_060ISP_TABLE-0x80+_off_dww,%pc),%d0
2488c2ecf20Sopenharmony_ci	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
2498c2ecf20Sopenharmony_ci	mov.l		0x4(%sp),%d0
2508c2ecf20Sopenharmony_ci	rtd		&0x4
2518c2ecf20Sopenharmony_ci
2528c2ecf20Sopenharmony_ci	global		_dmem_write_long
2538c2ecf20Sopenharmony_ci_dmem_write_long:
2548c2ecf20Sopenharmony_ci	mov.l		%d0,-(%sp)
2558c2ecf20Sopenharmony_ci	mov.l		(_060ISP_TABLE-0x80+_off_dwl,%pc),%d0
2568c2ecf20Sopenharmony_ci	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
2578c2ecf20Sopenharmony_ci	mov.l		0x4(%sp),%d0
2588c2ecf20Sopenharmony_ci	rtd		&0x4
2598c2ecf20Sopenharmony_ci
2608c2ecf20Sopenharmony_ci#
2618c2ecf20Sopenharmony_ci# This file contains a set of define statements for constants
2628c2ecf20Sopenharmony_ci# in oreder to promote readability within the core code itself.
2638c2ecf20Sopenharmony_ci#
2648c2ecf20Sopenharmony_ci
2658c2ecf20Sopenharmony_ciset LOCAL_SIZE,		96			# stack frame size(bytes)
2668c2ecf20Sopenharmony_ciset LV,			-LOCAL_SIZE		# stack offset
2678c2ecf20Sopenharmony_ci
2688c2ecf20Sopenharmony_ciset EXC_ISR,		0x4			# stack status register
2698c2ecf20Sopenharmony_ciset EXC_IPC,		0x6			# stack pc
2708c2ecf20Sopenharmony_ciset EXC_IVOFF,		0xa			# stacked vector offset
2718c2ecf20Sopenharmony_ci
2728c2ecf20Sopenharmony_ciset EXC_AREGS,		LV+64			# offset of all address regs
2738c2ecf20Sopenharmony_ciset EXC_DREGS,		LV+32			# offset of all data regs
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_ciset EXC_A7,		EXC_AREGS+(7*4)		# offset of a7
2768c2ecf20Sopenharmony_ciset EXC_A6,		EXC_AREGS+(6*4)		# offset of a6
2778c2ecf20Sopenharmony_ciset EXC_A5,		EXC_AREGS+(5*4)		# offset of a5
2788c2ecf20Sopenharmony_ciset EXC_A4,		EXC_AREGS+(4*4)		# offset of a4
2798c2ecf20Sopenharmony_ciset EXC_A3,		EXC_AREGS+(3*4)		# offset of a3
2808c2ecf20Sopenharmony_ciset EXC_A2,		EXC_AREGS+(2*4)		# offset of a2
2818c2ecf20Sopenharmony_ciset EXC_A1,		EXC_AREGS+(1*4)		# offset of a1
2828c2ecf20Sopenharmony_ciset EXC_A0,		EXC_AREGS+(0*4)		# offset of a0
2838c2ecf20Sopenharmony_ciset EXC_D7,		EXC_DREGS+(7*4)		# offset of d7
2848c2ecf20Sopenharmony_ciset EXC_D6,		EXC_DREGS+(6*4)		# offset of d6
2858c2ecf20Sopenharmony_ciset EXC_D5,		EXC_DREGS+(5*4)		# offset of d5
2868c2ecf20Sopenharmony_ciset EXC_D4,		EXC_DREGS+(4*4)		# offset of d4
2878c2ecf20Sopenharmony_ciset EXC_D3,		EXC_DREGS+(3*4)		# offset of d3
2888c2ecf20Sopenharmony_ciset EXC_D2,		EXC_DREGS+(2*4)		# offset of d2
2898c2ecf20Sopenharmony_ciset EXC_D1,		EXC_DREGS+(1*4)		# offset of d1
2908c2ecf20Sopenharmony_ciset EXC_D0,		EXC_DREGS+(0*4)		# offset of d0
2918c2ecf20Sopenharmony_ci
2928c2ecf20Sopenharmony_ciset EXC_TEMP,		LV+16			# offset of temp stack space
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_ciset EXC_SAVVAL,		LV+12			# offset of old areg value
2958c2ecf20Sopenharmony_ciset EXC_SAVREG,		LV+11			# offset of old areg index
2968c2ecf20Sopenharmony_ci
2978c2ecf20Sopenharmony_ciset SPCOND_FLG,		LV+10			# offset of spc condition flg
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_ciset EXC_CC,		LV+8			# offset of cc register
3008c2ecf20Sopenharmony_ciset EXC_EXTWPTR,	LV+4			# offset of current PC
3018c2ecf20Sopenharmony_ciset EXC_EXTWORD,	LV+2			# offset of current ext opword
3028c2ecf20Sopenharmony_ciset EXC_OPWORD,		LV+0			# offset of current opword
3038c2ecf20Sopenharmony_ci
3048c2ecf20Sopenharmony_ci###########################
3058c2ecf20Sopenharmony_ci# SPecial CONDition FLaGs #
3068c2ecf20Sopenharmony_ci###########################
3078c2ecf20Sopenharmony_ciset mia7_flg,		0x04			# (a7)+ flag
3088c2ecf20Sopenharmony_ciset mda7_flg,		0x08			# -(a7) flag
3098c2ecf20Sopenharmony_ciset ichk_flg,		0x10			# chk exception flag
3108c2ecf20Sopenharmony_ciset idbyz_flg,		0x20			# divbyzero flag
3118c2ecf20Sopenharmony_ciset restore_flg,	0x40			# restore -(an)+ flag
3128c2ecf20Sopenharmony_ciset immed_flg,		0x80			# immediate data flag
3138c2ecf20Sopenharmony_ci
3148c2ecf20Sopenharmony_ciset mia7_bit,		0x2			# (a7)+ bit
3158c2ecf20Sopenharmony_ciset mda7_bit,		0x3			# -(a7) bit
3168c2ecf20Sopenharmony_ciset ichk_bit,		0x4			# chk exception bit
3178c2ecf20Sopenharmony_ciset idbyz_bit,		0x5			# divbyzero bit
3188c2ecf20Sopenharmony_ciset restore_bit,	0x6			# restore -(a7)+ bit
3198c2ecf20Sopenharmony_ciset immed_bit,		0x7			# immediate data bit
3208c2ecf20Sopenharmony_ci
3218c2ecf20Sopenharmony_ci#########
3228c2ecf20Sopenharmony_ci# Misc. #
3238c2ecf20Sopenharmony_ci#########
3248c2ecf20Sopenharmony_ciset BYTE,		1			# len(byte) == 1 byte
3258c2ecf20Sopenharmony_ciset WORD,		2			# len(word) == 2 bytes
3268c2ecf20Sopenharmony_ciset LONG,		4			# len(longword) == 4 bytes
3278c2ecf20Sopenharmony_ci
3288c2ecf20Sopenharmony_ci#########################################################################
3298c2ecf20Sopenharmony_ci# XDEF ****************************************************************	#
3308c2ecf20Sopenharmony_ci#	_isp_unimp(): 060ISP entry point for Unimplemented Instruction	#
3318c2ecf20Sopenharmony_ci#									#
3328c2ecf20Sopenharmony_ci#	This handler should be the first code executed upon taking the	#
3338c2ecf20Sopenharmony_ci#	"Unimplemented Integer Instruction" exception in an operating	#
3348c2ecf20Sopenharmony_ci#	system.								#
3358c2ecf20Sopenharmony_ci#									#
3368c2ecf20Sopenharmony_ci# XREF ****************************************************************	#
3378c2ecf20Sopenharmony_ci#	_imem_read_{word,long}() - read instruction word/longword	#
3388c2ecf20Sopenharmony_ci#	_mul64() - emulate 64-bit multiply				#
3398c2ecf20Sopenharmony_ci#	_div64() - emulate 64-bit divide				#
3408c2ecf20Sopenharmony_ci#	_moveperipheral() - emulate "movep"				#
3418c2ecf20Sopenharmony_ci#	_compandset() - emulate misaligned "cas"			#
3428c2ecf20Sopenharmony_ci#	_compandset2() - emulate "cas2"					#
3438c2ecf20Sopenharmony_ci#	_chk2_cmp2() - emulate "cmp2" and "chk2"			#
3448c2ecf20Sopenharmony_ci#	_isp_done() - "callout" for normal final exit			#
3458c2ecf20Sopenharmony_ci#	_real_trace() - "callout" for Trace exception			#
3468c2ecf20Sopenharmony_ci#	_real_chk() - "callout" for Chk exception			#
3478c2ecf20Sopenharmony_ci#	_real_divbyzero() - "callout" for DZ exception			#
3488c2ecf20Sopenharmony_ci#	_real_access() - "callout" for access error exception		#
3498c2ecf20Sopenharmony_ci#									#
3508c2ecf20Sopenharmony_ci# INPUT ***************************************************************	#
3518c2ecf20Sopenharmony_ci#	- The system stack contains the Unimp Int Instr stack frame	#
3528c2ecf20Sopenharmony_ci#									#
3538c2ecf20Sopenharmony_ci# OUTPUT **************************************************************	#
3548c2ecf20Sopenharmony_ci#	If Trace exception:						#
3558c2ecf20Sopenharmony_ci#	- The system stack changed to contain Trace exc stack frame	#
3568c2ecf20Sopenharmony_ci#	If Chk exception:						#
3578c2ecf20Sopenharmony_ci#	- The system stack changed to contain Chk exc stack frame	#
3588c2ecf20Sopenharmony_ci#	If DZ exception:						#
3598c2ecf20Sopenharmony_ci#	- The system stack changed to contain DZ exc stack frame	#
3608c2ecf20Sopenharmony_ci#	If access error exception:					#
3618c2ecf20Sopenharmony_ci#	- The system stack changed to contain access err exc stk frame	#
3628c2ecf20Sopenharmony_ci#	Else:								#
3638c2ecf20Sopenharmony_ci#	- Results saved as appropriate					#
3648c2ecf20Sopenharmony_ci#									#
3658c2ecf20Sopenharmony_ci# ALGORITHM ***********************************************************	#
3668c2ecf20Sopenharmony_ci#	This handler fetches the first instruction longword from	#
3678c2ecf20Sopenharmony_ci# memory and decodes it to determine which of the unimplemented		#
3688c2ecf20Sopenharmony_ci# integer instructions caused this exception. This handler then calls	#
3698c2ecf20Sopenharmony_ci# one of _mul64(), _div64(), _moveperipheral(), _compandset(),		#
3708c2ecf20Sopenharmony_ci# _compandset2(), or _chk2_cmp2() as appropriate.			#
3718c2ecf20Sopenharmony_ci#	Some of these instructions, by their nature, may produce other	#
3728c2ecf20Sopenharmony_ci# types of exceptions. "div" can produce a divide-by-zero exception,	#
3738c2ecf20Sopenharmony_ci# and "chk2" can cause a "Chk" exception. In both cases, the current	#
3748c2ecf20Sopenharmony_ci# exception stack frame must be converted to an exception stack frame	#
3758c2ecf20Sopenharmony_ci# of the correct exception type and an exit must be made through	#
3768c2ecf20Sopenharmony_ci# _real_divbyzero() or _real_chk() as appropriate. In addition, all	#
3778c2ecf20Sopenharmony_ci# instructions may be executing while Trace is enabled. If so, then	#
3788c2ecf20Sopenharmony_ci# a Trace exception stack frame must be created and an exit made	#
3798c2ecf20Sopenharmony_ci# through _real_trace().						#
3808c2ecf20Sopenharmony_ci#	Meanwhile, if any read or write to memory using the		#
3818c2ecf20Sopenharmony_ci# _mem_{read,write}() "callout"s returns a failing value, then an	#
3828c2ecf20Sopenharmony_ci# access error frame must be created and an exit made through		#
3838c2ecf20Sopenharmony_ci# _real_access().							#
3848c2ecf20Sopenharmony_ci#	If none of these occur, then a normal exit is made through	#
3858c2ecf20Sopenharmony_ci# _isp_done().								#
3868c2ecf20Sopenharmony_ci#									#
3878c2ecf20Sopenharmony_ci#	This handler, upon entry, saves almost all user-visible		#
3888c2ecf20Sopenharmony_ci# address and data registers to the stack. Although this may seem to	#
3898c2ecf20Sopenharmony_ci# cause excess memory traffic, it was found that due to having to	#
3908c2ecf20Sopenharmony_ci# access these register files for things like data retrieval and <ea>	#
3918c2ecf20Sopenharmony_ci# calculations, it was more efficient to have them on the stack where	#
3928c2ecf20Sopenharmony_ci# they could be accessed by indexing rather than to make subroutine	#
3938c2ecf20Sopenharmony_ci# calls to retrieve a register of a particular index.			#
3948c2ecf20Sopenharmony_ci#									#
3958c2ecf20Sopenharmony_ci#########################################################################
3968c2ecf20Sopenharmony_ci
3978c2ecf20Sopenharmony_ci	global		_isp_unimp
3988c2ecf20Sopenharmony_ci_isp_unimp:
3998c2ecf20Sopenharmony_ci	link.w		%a6,&-LOCAL_SIZE	# create room for stack frame
4008c2ecf20Sopenharmony_ci
4018c2ecf20Sopenharmony_ci	movm.l		&0x3fff,EXC_DREGS(%a6)	# store d0-d7/a0-a5
4028c2ecf20Sopenharmony_ci	mov.l		(%a6),EXC_A6(%a6)	# store a6
4038c2ecf20Sopenharmony_ci
4048c2ecf20Sopenharmony_ci	btst		&0x5,EXC_ISR(%a6)	# from s or u mode?
4058c2ecf20Sopenharmony_ci	bne.b		uieh_s			# supervisor mode
4068c2ecf20Sopenharmony_ciuieh_u:
4078c2ecf20Sopenharmony_ci	mov.l		%usp,%a0		# fetch user stack pointer
4088c2ecf20Sopenharmony_ci	mov.l		%a0,EXC_A7(%a6)		# store a7
4098c2ecf20Sopenharmony_ci	bra.b		uieh_cont
4108c2ecf20Sopenharmony_ciuieh_s:
4118c2ecf20Sopenharmony_ci	lea		0xc(%a6),%a0
4128c2ecf20Sopenharmony_ci	mov.l		%a0,EXC_A7(%a6)		# store corrected sp
4138c2ecf20Sopenharmony_ci
4148c2ecf20Sopenharmony_ci###############################################################################
4158c2ecf20Sopenharmony_ci
4168c2ecf20Sopenharmony_ciuieh_cont:
4178c2ecf20Sopenharmony_ci	clr.b		SPCOND_FLG(%a6)		# clear "special case" flag
4188c2ecf20Sopenharmony_ci
4198c2ecf20Sopenharmony_ci	mov.w		EXC_ISR(%a6),EXC_CC(%a6) # store cc copy on stack
4208c2ecf20Sopenharmony_ci	mov.l		EXC_IPC(%a6),EXC_EXTWPTR(%a6) # store extwptr on stack
4218c2ecf20Sopenharmony_ci
4228c2ecf20Sopenharmony_ci#
4238c2ecf20Sopenharmony_ci# fetch the opword and first extension word pointed to by the stacked pc
4248c2ecf20Sopenharmony_ci# and store them to the stack for now
4258c2ecf20Sopenharmony_ci#
4268c2ecf20Sopenharmony_ci	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
4278c2ecf20Sopenharmony_ci	addq.l		&0x4,EXC_EXTWPTR(%a6)	# incr instruction ptr
4288c2ecf20Sopenharmony_ci	bsr.l		_imem_read_long		# fetch opword & extword
4298c2ecf20Sopenharmony_ci	mov.l		%d0,EXC_OPWORD(%a6)	# store extword on stack
4308c2ecf20Sopenharmony_ci
4318c2ecf20Sopenharmony_ci
4328c2ecf20Sopenharmony_ci#########################################################################
4338c2ecf20Sopenharmony_ci# muls.l	0100 1100 00 |<ea>|	0*** 1100 0000 0***		#
4348c2ecf20Sopenharmony_ci# mulu.l	0100 1100 00 |<ea>|	0*** 0100 0000 0***		#
4358c2ecf20Sopenharmony_ci#									#
4368c2ecf20Sopenharmony_ci# divs.l	0100 1100 01 |<ea>|	0*** 1100 0000 0***		#
4378c2ecf20Sopenharmony_ci# divu.l	0100 1100 01 |<ea>|	0*** 0100 0000 0***		#
4388c2ecf20Sopenharmony_ci#									#
4398c2ecf20Sopenharmony_ci# movep.w m2r	0000 ***1 00 001***	| <displacement>  |		#
4408c2ecf20Sopenharmony_ci# movep.l m2r	0000 ***1 01 001***	| <displacement>  |		#
4418c2ecf20Sopenharmony_ci# movep.w r2m	0000 ***1 10 001***	| <displacement>  |		#
4428c2ecf20Sopenharmony_ci# movep.l r2m	0000 ***1 11 001***	| <displacement>  |		#
4438c2ecf20Sopenharmony_ci#									#
4448c2ecf20Sopenharmony_ci# cas.w		0000 1100 11 |<ea>|	0000 000* **00 0***		#
4458c2ecf20Sopenharmony_ci# cas.l		0000 1110 11 |<ea>|	0000 000* **00 0***		#
4468c2ecf20Sopenharmony_ci#									#
4478c2ecf20Sopenharmony_ci# cas2.w	0000 1100 11 111100	**** 000* **00 0***		#
4488c2ecf20Sopenharmony_ci#					**** 000* **00 0***		#
4498c2ecf20Sopenharmony_ci# cas2.l	0000 1110 11 111100	**** 000* **00 0***		#
4508c2ecf20Sopenharmony_ci#					**** 000* **00 0***		#
4518c2ecf20Sopenharmony_ci#									#
4528c2ecf20Sopenharmony_ci# chk2.b	0000 0000 11 |<ea>|	**** 1000 0000 0000		#
4538c2ecf20Sopenharmony_ci# chk2.w	0000 0010 11 |<ea>|	**** 1000 0000 0000		#
4548c2ecf20Sopenharmony_ci# chk2.l	0000 0100 11 |<ea>|	**** 1000 0000 0000		#
4558c2ecf20Sopenharmony_ci#									#
4568c2ecf20Sopenharmony_ci# cmp2.b	0000 0000 11 |<ea>|	**** 0000 0000 0000		#
4578c2ecf20Sopenharmony_ci# cmp2.w	0000 0010 11 |<ea>|	**** 0000 0000 0000		#
4588c2ecf20Sopenharmony_ci# cmp2.l	0000 0100 11 |<ea>|	**** 0000 0000 0000		#
4598c2ecf20Sopenharmony_ci#########################################################################
4608c2ecf20Sopenharmony_ci
4618c2ecf20Sopenharmony_ci#
4628c2ecf20Sopenharmony_ci# using bit 14 of the operation word, separate into 2 groups:
4638c2ecf20Sopenharmony_ci# (group1) mul64, div64
4648c2ecf20Sopenharmony_ci# (group2) movep, chk2, cmp2, cas2, cas
4658c2ecf20Sopenharmony_ci#
4668c2ecf20Sopenharmony_ci	btst		&0x1e,%d0		# group1 or group2
4678c2ecf20Sopenharmony_ci	beq.b		uieh_group2		# go handle group2
4688c2ecf20Sopenharmony_ci
4698c2ecf20Sopenharmony_ci#
4708c2ecf20Sopenharmony_ci# now, w/ group1, make mul64's decode the fastest since it will
4718c2ecf20Sopenharmony_ci# most likely be used the most.
4728c2ecf20Sopenharmony_ci#
4738c2ecf20Sopenharmony_ciuieh_group1:
4748c2ecf20Sopenharmony_ci	btst		&0x16,%d0		# test for div64
4758c2ecf20Sopenharmony_ci	bne.b		uieh_div64		# go handle div64
4768c2ecf20Sopenharmony_ci
4778c2ecf20Sopenharmony_ciuieh_mul64:
4788c2ecf20Sopenharmony_ci# mul64() may use ()+ addressing and may, therefore, alter a7
4798c2ecf20Sopenharmony_ci
4808c2ecf20Sopenharmony_ci	bsr.l		_mul64			# _mul64()
4818c2ecf20Sopenharmony_ci
4828c2ecf20Sopenharmony_ci	btst		&0x5,EXC_ISR(%a6)	# supervisor mode?
4838c2ecf20Sopenharmony_ci	beq.w		uieh_done
4848c2ecf20Sopenharmony_ci	btst		&mia7_bit,SPCOND_FLG(%a6) # was a7 changed?
4858c2ecf20Sopenharmony_ci	beq.w		uieh_done		# no
4868c2ecf20Sopenharmony_ci	btst		&0x7,EXC_ISR(%a6)	# is trace enabled?
4878c2ecf20Sopenharmony_ci	bne.w		uieh_trace_a7		# yes
4888c2ecf20Sopenharmony_ci	bra.w		uieh_a7			# no
4898c2ecf20Sopenharmony_ci
4908c2ecf20Sopenharmony_ciuieh_div64:
4918c2ecf20Sopenharmony_ci# div64() may use ()+ addressing and may, therefore, alter a7.
4928c2ecf20Sopenharmony_ci# div64() may take a divide by zero exception.
4938c2ecf20Sopenharmony_ci
4948c2ecf20Sopenharmony_ci	bsr.l		_div64			# _div64()
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_ci# here, we sort out all of the special cases that may have happened.
4978c2ecf20Sopenharmony_ci	btst		&mia7_bit,SPCOND_FLG(%a6) # was a7 changed?
4988c2ecf20Sopenharmony_ci	bne.b		uieh_div64_a7		# yes
4998c2ecf20Sopenharmony_ciuieh_div64_dbyz:
5008c2ecf20Sopenharmony_ci	btst		&idbyz_bit,SPCOND_FLG(%a6) # did divide-by-zero occur?
5018c2ecf20Sopenharmony_ci	bne.w		uieh_divbyzero		# yes
5028c2ecf20Sopenharmony_ci	bra.w		uieh_done		# no
5038c2ecf20Sopenharmony_ciuieh_div64_a7:
5048c2ecf20Sopenharmony_ci	btst		&0x5,EXC_ISR(%a6)	# supervisor mode?
5058c2ecf20Sopenharmony_ci	beq.b		uieh_div64_dbyz		# no
5068c2ecf20Sopenharmony_ci# here, a7 has been incremented by 4 bytes in supervisor mode. we still
5078c2ecf20Sopenharmony_ci# may have the following 3 cases:
5088c2ecf20Sopenharmony_ci#	(i)	(a7)+
5098c2ecf20Sopenharmony_ci#	(ii)	(a7)+; trace
5108c2ecf20Sopenharmony_ci#	(iii)	(a7)+; divide-by-zero
5118c2ecf20Sopenharmony_ci#
5128c2ecf20Sopenharmony_ci	btst		&idbyz_bit,SPCOND_FLG(%a6) # did divide-by-zero occur?
5138c2ecf20Sopenharmony_ci	bne.w		uieh_divbyzero_a7	# yes
5148c2ecf20Sopenharmony_ci	tst.b		EXC_ISR(%a6)		# no; is trace enabled?
5158c2ecf20Sopenharmony_ci	bmi.w		uieh_trace_a7		# yes
5168c2ecf20Sopenharmony_ci	bra.w		uieh_a7			# no
5178c2ecf20Sopenharmony_ci
5188c2ecf20Sopenharmony_ci#
5198c2ecf20Sopenharmony_ci# now, w/ group2, make movep's decode the fastest since it will
5208c2ecf20Sopenharmony_ci# most likely be used the most.
5218c2ecf20Sopenharmony_ci#
5228c2ecf20Sopenharmony_ciuieh_group2:
5238c2ecf20Sopenharmony_ci	btst		&0x18,%d0		# test for not movep
5248c2ecf20Sopenharmony_ci	beq.b		uieh_not_movep
5258c2ecf20Sopenharmony_ci
5268c2ecf20Sopenharmony_ci
5278c2ecf20Sopenharmony_ci	bsr.l		_moveperipheral		# _movep()
5288c2ecf20Sopenharmony_ci	bra.w		uieh_done
5298c2ecf20Sopenharmony_ci
5308c2ecf20Sopenharmony_ciuieh_not_movep:
5318c2ecf20Sopenharmony_ci	btst		&0x1b,%d0		# test for chk2,cmp2
5328c2ecf20Sopenharmony_ci	beq.b		uieh_chk2cmp2		# go handle chk2,cmp2
5338c2ecf20Sopenharmony_ci
5348c2ecf20Sopenharmony_ci	swap		%d0			# put opword in lo word
5358c2ecf20Sopenharmony_ci	cmpi.b		%d0,&0xfc		# test for cas2
5368c2ecf20Sopenharmony_ci	beq.b		uieh_cas2		# go handle cas2
5378c2ecf20Sopenharmony_ci
5388c2ecf20Sopenharmony_ciuieh_cas:
5398c2ecf20Sopenharmony_ci
5408c2ecf20Sopenharmony_ci	bsr.l		_compandset		# _cas()
5418c2ecf20Sopenharmony_ci
5428c2ecf20Sopenharmony_ci# the cases of "cas Dc,Du,(a7)+" and "cas Dc,Du,-(a7)" used from supervisor
5438c2ecf20Sopenharmony_ci# mode are simply not considered valid and therefore are not handled.
5448c2ecf20Sopenharmony_ci
5458c2ecf20Sopenharmony_ci	bra.w		uieh_done
5468c2ecf20Sopenharmony_ci
5478c2ecf20Sopenharmony_ciuieh_cas2:
5488c2ecf20Sopenharmony_ci
5498c2ecf20Sopenharmony_ci	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
5508c2ecf20Sopenharmony_ci	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
5518c2ecf20Sopenharmony_ci	bsr.l		_imem_read_word		# read extension word
5528c2ecf20Sopenharmony_ci
5538c2ecf20Sopenharmony_ci	tst.l		%d1			# ifetch error?
5548c2ecf20Sopenharmony_ci	bne.w		isp_iacc		# yes
5558c2ecf20Sopenharmony_ci
5568c2ecf20Sopenharmony_ci	bsr.l		_compandset2		# _cas2()
5578c2ecf20Sopenharmony_ci	bra.w		uieh_done
5588c2ecf20Sopenharmony_ci
5598c2ecf20Sopenharmony_ciuieh_chk2cmp2:
5608c2ecf20Sopenharmony_ci# chk2 may take a chk exception
5618c2ecf20Sopenharmony_ci
5628c2ecf20Sopenharmony_ci	bsr.l		_chk2_cmp2		# _chk2_cmp2()
5638c2ecf20Sopenharmony_ci
5648c2ecf20Sopenharmony_ci# here we check to see if a chk trap should be taken
5658c2ecf20Sopenharmony_ci	cmpi.b		SPCOND_FLG(%a6),&ichk_flg
5668c2ecf20Sopenharmony_ci	bne.w		uieh_done
5678c2ecf20Sopenharmony_ci	bra.b		uieh_chk_trap
5688c2ecf20Sopenharmony_ci
5698c2ecf20Sopenharmony_ci###########################################################################
5708c2ecf20Sopenharmony_ci
5718c2ecf20Sopenharmony_ci#
5728c2ecf20Sopenharmony_ci# the required emulation has been completed. now, clean up the necessary stack
5738c2ecf20Sopenharmony_ci# info and prepare for rte
5748c2ecf20Sopenharmony_ci#
5758c2ecf20Sopenharmony_ciuieh_done:
5768c2ecf20Sopenharmony_ci	mov.b		EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes
5778c2ecf20Sopenharmony_ci
5788c2ecf20Sopenharmony_ci# if exception occurred in user mode, then we have to restore a7 in case it
5798c2ecf20Sopenharmony_ci# changed. we don't have to update a7  for supervisor mose because that case
5808c2ecf20Sopenharmony_ci# doesn't flow through here
5818c2ecf20Sopenharmony_ci	btst		&0x5,EXC_ISR(%a6)	# user or supervisor?
5828c2ecf20Sopenharmony_ci	bne.b		uieh_finish		# supervisor
5838c2ecf20Sopenharmony_ci
5848c2ecf20Sopenharmony_ci	mov.l		EXC_A7(%a6),%a0		# fetch user stack pointer
5858c2ecf20Sopenharmony_ci	mov.l		%a0,%usp		# restore it
5868c2ecf20Sopenharmony_ci
5878c2ecf20Sopenharmony_ciuieh_finish:
5888c2ecf20Sopenharmony_ci	movm.l		EXC_DREGS(%a6),&0x3fff	# restore d0-d7/a0-a5
5898c2ecf20Sopenharmony_ci
5908c2ecf20Sopenharmony_ci	btst		&0x7,EXC_ISR(%a6)	# is trace mode on?
5918c2ecf20Sopenharmony_ci	bne.b		uieh_trace		# yes;go handle trace mode
5928c2ecf20Sopenharmony_ci
5938c2ecf20Sopenharmony_ci	mov.l		EXC_EXTWPTR(%a6),EXC_IPC(%a6) # new pc on stack frame
5948c2ecf20Sopenharmony_ci	mov.l		EXC_A6(%a6),(%a6)	# prepare new a6 for unlink
5958c2ecf20Sopenharmony_ci	unlk		%a6			# unlink stack frame
5968c2ecf20Sopenharmony_ci	bra.l		_isp_done
5978c2ecf20Sopenharmony_ci
5988c2ecf20Sopenharmony_ci#
5998c2ecf20Sopenharmony_ci# The instruction that was just emulated was also being traced. The trace
6008c2ecf20Sopenharmony_ci# trap for this instruction will be lost unless we jump to the trace handler.
6018c2ecf20Sopenharmony_ci# So, here we create a Trace Exception format number two exception stack
6028c2ecf20Sopenharmony_ci# frame from the Unimplemented Integer Intruction Exception stack frame
6038c2ecf20Sopenharmony_ci# format number zero and jump to the user supplied hook "_real_trace()".
6048c2ecf20Sopenharmony_ci#
6058c2ecf20Sopenharmony_ci#		   UIEH FRAME		   TRACE FRAME
6068c2ecf20Sopenharmony_ci#		*****************	*****************
6078c2ecf20Sopenharmony_ci#		* 0x0 *  0x0f4	*	*    Current	*
6088c2ecf20Sopenharmony_ci#		*****************	*      PC	*
6098c2ecf20Sopenharmony_ci#		*    Current	*	*****************
6108c2ecf20Sopenharmony_ci#		*      PC	*	* 0x2 *  0x024	*
6118c2ecf20Sopenharmony_ci#		*****************	*****************
6128c2ecf20Sopenharmony_ci#		*      SR	*	*     Next	*
6138c2ecf20Sopenharmony_ci#		*****************	*      PC	*
6148c2ecf20Sopenharmony_ci#	      ->*     Old	*	*****************
6158c2ecf20Sopenharmony_ci#  from link -->*      A6	*	*      SR	*
6168c2ecf20Sopenharmony_ci#	        *****************	*****************
6178c2ecf20Sopenharmony_ci#	       /*      A7	*	*      New	* <-- for final unlink
6188c2ecf20Sopenharmony_ci#	      / *		*	*      A6	*
6198c2ecf20Sopenharmony_ci# link frame <  *****************	*****************
6208c2ecf20Sopenharmony_ci#	      \ ~		~	~		~
6218c2ecf20Sopenharmony_ci#	       \*****************	*****************
6228c2ecf20Sopenharmony_ci#
6238c2ecf20Sopenharmony_ciuieh_trace:
6248c2ecf20Sopenharmony_ci	mov.l		EXC_A6(%a6),-0x4(%a6)
6258c2ecf20Sopenharmony_ci	mov.w		EXC_ISR(%a6),0x0(%a6)
6268c2ecf20Sopenharmony_ci	mov.l		EXC_IPC(%a6),0x8(%a6)
6278c2ecf20Sopenharmony_ci	mov.l		EXC_EXTWPTR(%a6),0x2(%a6)
6288c2ecf20Sopenharmony_ci	mov.w		&0x2024,0x6(%a6)
6298c2ecf20Sopenharmony_ci	sub.l		&0x4,%a6
6308c2ecf20Sopenharmony_ci	unlk		%a6
6318c2ecf20Sopenharmony_ci	bra.l		_real_trace
6328c2ecf20Sopenharmony_ci
6338c2ecf20Sopenharmony_ci#
6348c2ecf20Sopenharmony_ci#	   UIEH FRAME		    CHK FRAME
6358c2ecf20Sopenharmony_ci#	*****************	*****************
6368c2ecf20Sopenharmony_ci#	* 0x0 *  0x0f4	*	*    Current	*
6378c2ecf20Sopenharmony_ci#	*****************	*      PC	*
6388c2ecf20Sopenharmony_ci#	*    Current	*	*****************
6398c2ecf20Sopenharmony_ci#	*      PC	*	* 0x2 *  0x018	*
6408c2ecf20Sopenharmony_ci#	*****************	*****************
6418c2ecf20Sopenharmony_ci#	*      SR	*	*     Next	*
6428c2ecf20Sopenharmony_ci#	*****************	*      PC	*
6438c2ecf20Sopenharmony_ci#	    (4 words)		*****************
6448c2ecf20Sopenharmony_ci#				*      SR	*
6458c2ecf20Sopenharmony_ci#				*****************
6468c2ecf20Sopenharmony_ci#				    (6 words)
6478c2ecf20Sopenharmony_ci#
6488c2ecf20Sopenharmony_ci# the chk2 instruction should take a chk trap. so, here we must create a
6498c2ecf20Sopenharmony_ci# chk stack frame from an unimplemented integer instruction exception frame
6508c2ecf20Sopenharmony_ci# and jump to the user supplied entry point "_real_chk()".
6518c2ecf20Sopenharmony_ci#
6528c2ecf20Sopenharmony_ciuieh_chk_trap:
6538c2ecf20Sopenharmony_ci	mov.b		EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes
6548c2ecf20Sopenharmony_ci	movm.l		EXC_DREGS(%a6),&0x3fff	# restore d0-d7/a0-a5
6558c2ecf20Sopenharmony_ci
6568c2ecf20Sopenharmony_ci	mov.w		EXC_ISR(%a6),(%a6)	# put new SR on stack
6578c2ecf20Sopenharmony_ci	mov.l		EXC_IPC(%a6),0x8(%a6)	# put "Current PC" on stack
6588c2ecf20Sopenharmony_ci	mov.l		EXC_EXTWPTR(%a6),0x2(%a6) # put "Next PC" on stack
6598c2ecf20Sopenharmony_ci	mov.w		&0x2018,0x6(%a6)	# put Vector Offset on stack
6608c2ecf20Sopenharmony_ci
6618c2ecf20Sopenharmony_ci	mov.l		EXC_A6(%a6),%a6		# restore a6
6628c2ecf20Sopenharmony_ci	add.l		&LOCAL_SIZE,%sp		# clear stack frame
6638c2ecf20Sopenharmony_ci
6648c2ecf20Sopenharmony_ci	bra.l		_real_chk
6658c2ecf20Sopenharmony_ci
6668c2ecf20Sopenharmony_ci#
6678c2ecf20Sopenharmony_ci#	   UIEH FRAME		 DIVBYZERO FRAME
6688c2ecf20Sopenharmony_ci#	*****************	*****************
6698c2ecf20Sopenharmony_ci#	* 0x0 *  0x0f4	*	*    Current	*
6708c2ecf20Sopenharmony_ci#	*****************	*      PC	*
6718c2ecf20Sopenharmony_ci#	*    Current	*	*****************
6728c2ecf20Sopenharmony_ci#	*      PC	*	* 0x2 *  0x014	*
6738c2ecf20Sopenharmony_ci#	*****************	*****************
6748c2ecf20Sopenharmony_ci#	*      SR	*	*     Next	*
6758c2ecf20Sopenharmony_ci#	*****************	*      PC	*
6768c2ecf20Sopenharmony_ci#	    (4 words)		*****************
6778c2ecf20Sopenharmony_ci#				*      SR	*
6788c2ecf20Sopenharmony_ci#				*****************
6798c2ecf20Sopenharmony_ci#				    (6 words)
6808c2ecf20Sopenharmony_ci#
6818c2ecf20Sopenharmony_ci# the divide instruction should take an integer divide by zero trap. so, here
6828c2ecf20Sopenharmony_ci# we must create a divbyzero stack frame from an unimplemented integer
6838c2ecf20Sopenharmony_ci# instruction exception frame and jump to the user supplied entry point
6848c2ecf20Sopenharmony_ci# "_real_divbyzero()".
6858c2ecf20Sopenharmony_ci#
6868c2ecf20Sopenharmony_ciuieh_divbyzero:
6878c2ecf20Sopenharmony_ci	mov.b		EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes
6888c2ecf20Sopenharmony_ci	movm.l		EXC_DREGS(%a6),&0x3fff	# restore d0-d7/a0-a5
6898c2ecf20Sopenharmony_ci
6908c2ecf20Sopenharmony_ci	mov.w		EXC_ISR(%a6),(%a6)	# put new SR on stack
6918c2ecf20Sopenharmony_ci	mov.l		EXC_IPC(%a6),0x8(%a6)	# put "Current PC" on stack
6928c2ecf20Sopenharmony_ci	mov.l		EXC_EXTWPTR(%a6),0x2(%a6) # put "Next PC" on stack
6938c2ecf20Sopenharmony_ci	mov.w		&0x2014,0x6(%a6)	# put Vector Offset on stack
6948c2ecf20Sopenharmony_ci
6958c2ecf20Sopenharmony_ci	mov.l		EXC_A6(%a6),%a6		# restore a6
6968c2ecf20Sopenharmony_ci	add.l		&LOCAL_SIZE,%sp		# clear stack frame
6978c2ecf20Sopenharmony_ci
6988c2ecf20Sopenharmony_ci	bra.l		_real_divbyzero
6998c2ecf20Sopenharmony_ci
7008c2ecf20Sopenharmony_ci#
7018c2ecf20Sopenharmony_ci#				 DIVBYZERO FRAME
7028c2ecf20Sopenharmony_ci#				*****************
7038c2ecf20Sopenharmony_ci#				*    Current	*
7048c2ecf20Sopenharmony_ci#	   UIEH FRAME		*      PC	*
7058c2ecf20Sopenharmony_ci#	*****************	*****************
7068c2ecf20Sopenharmony_ci#	* 0x0 *  0x0f4	*	* 0x2 * 0x014	*
7078c2ecf20Sopenharmony_ci#	*****************	*****************
7088c2ecf20Sopenharmony_ci#	*    Current	*	*     Next	*
7098c2ecf20Sopenharmony_ci#	*      PC	*	*      PC	*
7108c2ecf20Sopenharmony_ci#	*****************	*****************
7118c2ecf20Sopenharmony_ci#	*      SR	*	*      SR	*
7128c2ecf20Sopenharmony_ci#	*****************	*****************
7138c2ecf20Sopenharmony_ci#	    (4 words)		    (6 words)
7148c2ecf20Sopenharmony_ci#
7158c2ecf20Sopenharmony_ci# the divide instruction should take an integer divide by zero trap. so, here
7168c2ecf20Sopenharmony_ci# we must create a divbyzero stack frame from an unimplemented integer
7178c2ecf20Sopenharmony_ci# instruction exception frame and jump to the user supplied entry point
7188c2ecf20Sopenharmony_ci# "_real_divbyzero()".
7198c2ecf20Sopenharmony_ci#
7208c2ecf20Sopenharmony_ci# However, we must also deal with the fact that (a7)+ was used from supervisor
7218c2ecf20Sopenharmony_ci# mode, thereby shifting the stack frame up 4 bytes.
7228c2ecf20Sopenharmony_ci#
7238c2ecf20Sopenharmony_ciuieh_divbyzero_a7:
7248c2ecf20Sopenharmony_ci	mov.b		EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes
7258c2ecf20Sopenharmony_ci	movm.l		EXC_DREGS(%a6),&0x3fff	# restore d0-d7/a0-a5
7268c2ecf20Sopenharmony_ci
7278c2ecf20Sopenharmony_ci	mov.l		EXC_IPC(%a6),0xc(%a6)	# put "Current PC" on stack
7288c2ecf20Sopenharmony_ci	mov.w		&0x2014,0xa(%a6)	# put Vector Offset on stack
7298c2ecf20Sopenharmony_ci	mov.l		EXC_EXTWPTR(%a6),0x6(%a6) # put "Next PC" on stack
7308c2ecf20Sopenharmony_ci
7318c2ecf20Sopenharmony_ci	mov.l		EXC_A6(%a6),%a6		# restore a6
7328c2ecf20Sopenharmony_ci	add.l		&4+LOCAL_SIZE,%sp	# clear stack frame
7338c2ecf20Sopenharmony_ci
7348c2ecf20Sopenharmony_ci	bra.l		_real_divbyzero
7358c2ecf20Sopenharmony_ci
7368c2ecf20Sopenharmony_ci#
7378c2ecf20Sopenharmony_ci#				   TRACE FRAME
7388c2ecf20Sopenharmony_ci#				*****************
7398c2ecf20Sopenharmony_ci#				*    Current	*
7408c2ecf20Sopenharmony_ci#	   UIEH FRAME		*      PC	*
7418c2ecf20Sopenharmony_ci#	*****************	*****************
7428c2ecf20Sopenharmony_ci#	* 0x0 *  0x0f4	*	* 0x2 * 0x024	*
7438c2ecf20Sopenharmony_ci#	*****************	*****************
7448c2ecf20Sopenharmony_ci#	*    Current	*	*     Next	*
7458c2ecf20Sopenharmony_ci#	*      PC	*	*      PC	*
7468c2ecf20Sopenharmony_ci#	*****************	*****************
7478c2ecf20Sopenharmony_ci#	*      SR	*	*      SR	*
7488c2ecf20Sopenharmony_ci#	*****************	*****************
7498c2ecf20Sopenharmony_ci#	    (4 words)		    (6 words)
7508c2ecf20Sopenharmony_ci#
7518c2ecf20Sopenharmony_ci#
7528c2ecf20Sopenharmony_ci# The instruction that was just emulated was also being traced. The trace
7538c2ecf20Sopenharmony_ci# trap for this instruction will be lost unless we jump to the trace handler.
7548c2ecf20Sopenharmony_ci# So, here we create a Trace Exception format number two exception stack
7558c2ecf20Sopenharmony_ci# frame from the Unimplemented Integer Intruction Exception stack frame
7568c2ecf20Sopenharmony_ci# format number zero and jump to the user supplied hook "_real_trace()".
7578c2ecf20Sopenharmony_ci#
7588c2ecf20Sopenharmony_ci# However, we must also deal with the fact that (a7)+ was used from supervisor
7598c2ecf20Sopenharmony_ci# mode, thereby shifting the stack frame up 4 bytes.
7608c2ecf20Sopenharmony_ci#
7618c2ecf20Sopenharmony_ciuieh_trace_a7:
7628c2ecf20Sopenharmony_ci	mov.b		EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes
7638c2ecf20Sopenharmony_ci	movm.l		EXC_DREGS(%a6),&0x3fff	# restore d0-d7/a0-a5
7648c2ecf20Sopenharmony_ci
7658c2ecf20Sopenharmony_ci	mov.l		EXC_IPC(%a6),0xc(%a6)	# put "Current PC" on stack
7668c2ecf20Sopenharmony_ci	mov.w		&0x2024,0xa(%a6)	# put Vector Offset on stack
7678c2ecf20Sopenharmony_ci	mov.l		EXC_EXTWPTR(%a6),0x6(%a6) # put "Next PC" on stack
7688c2ecf20Sopenharmony_ci
7698c2ecf20Sopenharmony_ci	mov.l		EXC_A6(%a6),%a6		# restore a6
7708c2ecf20Sopenharmony_ci	add.l		&4+LOCAL_SIZE,%sp	# clear stack frame
7718c2ecf20Sopenharmony_ci
7728c2ecf20Sopenharmony_ci	bra.l		_real_trace
7738c2ecf20Sopenharmony_ci
7748c2ecf20Sopenharmony_ci#
7758c2ecf20Sopenharmony_ci#				   UIEH FRAME
7768c2ecf20Sopenharmony_ci#				*****************
7778c2ecf20Sopenharmony_ci#				* 0x0 * 0x0f4	*
7788c2ecf20Sopenharmony_ci#	   UIEH FRAME		*****************
7798c2ecf20Sopenharmony_ci#	*****************	*     Next	*
7808c2ecf20Sopenharmony_ci#	* 0x0 *  0x0f4	*	*      PC	*
7818c2ecf20Sopenharmony_ci#	*****************	*****************
7828c2ecf20Sopenharmony_ci#	*    Current	*	*      SR	*
7838c2ecf20Sopenharmony_ci#	*      PC	*	*****************
7848c2ecf20Sopenharmony_ci#	*****************	    (4 words)
7858c2ecf20Sopenharmony_ci#	*      SR	*
7868c2ecf20Sopenharmony_ci#	*****************
7878c2ecf20Sopenharmony_ci#	    (4 words)
7888c2ecf20Sopenharmony_ciuieh_a7:
7898c2ecf20Sopenharmony_ci	mov.b		EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes
7908c2ecf20Sopenharmony_ci	movm.l		EXC_DREGS(%a6),&0x3fff	# restore d0-d7/a0-a5
7918c2ecf20Sopenharmony_ci
7928c2ecf20Sopenharmony_ci	mov.w		&0x00f4,0xe(%a6)	# put Vector Offset on stack
7938c2ecf20Sopenharmony_ci	mov.l		EXC_EXTWPTR(%a6),0xa(%a6) # put "Next PC" on stack
7948c2ecf20Sopenharmony_ci	mov.w		EXC_ISR(%a6),0x8(%a6)	# put SR on stack
7958c2ecf20Sopenharmony_ci
7968c2ecf20Sopenharmony_ci	mov.l		EXC_A6(%a6),%a6		# restore a6
7978c2ecf20Sopenharmony_ci	add.l		&8+LOCAL_SIZE,%sp	# clear stack frame
7988c2ecf20Sopenharmony_ci	bra.l		_isp_done
7998c2ecf20Sopenharmony_ci
8008c2ecf20Sopenharmony_ci##########
8018c2ecf20Sopenharmony_ci
8028c2ecf20Sopenharmony_ci# this is the exit point if a data read or write fails.
8038c2ecf20Sopenharmony_ci# a0 = failing address
8048c2ecf20Sopenharmony_ci# d0 = fslw
8058c2ecf20Sopenharmony_ciisp_dacc:
8068c2ecf20Sopenharmony_ci	mov.l		%a0,(%a6)		# save address
8078c2ecf20Sopenharmony_ci	mov.l		%d0,-0x4(%a6)		# save partial fslw
8088c2ecf20Sopenharmony_ci
8098c2ecf20Sopenharmony_ci	lea		-64(%a6),%sp
8108c2ecf20Sopenharmony_ci	movm.l		(%sp)+,&0x7fff		# restore d0-d7/a0-a6
8118c2ecf20Sopenharmony_ci
8128c2ecf20Sopenharmony_ci	mov.l		0xc(%sp),-(%sp)		# move voff,hi(pc)
8138c2ecf20Sopenharmony_ci	mov.l		0x4(%sp),0x10(%sp)	# store fslw
8148c2ecf20Sopenharmony_ci	mov.l		0xc(%sp),0x4(%sp)	# store sr,lo(pc)
8158c2ecf20Sopenharmony_ci	mov.l		0x8(%sp),0xc(%sp)	# store address
8168c2ecf20Sopenharmony_ci	mov.l		(%sp)+,0x4(%sp)		# store voff,hi(pc)
8178c2ecf20Sopenharmony_ci	mov.w		&0x4008,0x6(%sp)	# store new voff
8188c2ecf20Sopenharmony_ci
8198c2ecf20Sopenharmony_ci	bra.b		isp_acc_exit
8208c2ecf20Sopenharmony_ci
8218c2ecf20Sopenharmony_ci# this is the exit point if an instruction word read fails.
8228c2ecf20Sopenharmony_ci# FSLW:
8238c2ecf20Sopenharmony_ci#	misaligned = true
8248c2ecf20Sopenharmony_ci#	read = true
8258c2ecf20Sopenharmony_ci#	size = word
8268c2ecf20Sopenharmony_ci#	instruction = true
8278c2ecf20Sopenharmony_ci#	software emulation error = true
8288c2ecf20Sopenharmony_ciisp_iacc:
8298c2ecf20Sopenharmony_ci	movm.l		EXC_DREGS(%a6),&0x3fff	# restore d0-d7/a0-a5
8308c2ecf20Sopenharmony_ci	unlk		%a6			# unlink frame
8318c2ecf20Sopenharmony_ci	sub.w		&0x8,%sp		# make room for acc frame
8328c2ecf20Sopenharmony_ci	mov.l		0x8(%sp),(%sp)		# store sr,lo(pc)
8338c2ecf20Sopenharmony_ci	mov.w		0xc(%sp),0x4(%sp)	# store hi(pc)
8348c2ecf20Sopenharmony_ci	mov.w		&0x4008,0x6(%sp)	# store new voff
8358c2ecf20Sopenharmony_ci	mov.l		0x2(%sp),0x8(%sp)	# store address (=pc)
8368c2ecf20Sopenharmony_ci	mov.l		&0x09428001,0xc(%sp)	# store fslw
8378c2ecf20Sopenharmony_ci
8388c2ecf20Sopenharmony_ciisp_acc_exit:
8398c2ecf20Sopenharmony_ci	btst		&0x5,(%sp)		# user or supervisor?
8408c2ecf20Sopenharmony_ci	beq.b		isp_acc_exit2		# user
8418c2ecf20Sopenharmony_ci	bset		&0x2,0xd(%sp)		# set supervisor TM bit
8428c2ecf20Sopenharmony_ciisp_acc_exit2:
8438c2ecf20Sopenharmony_ci	bra.l		_real_access
8448c2ecf20Sopenharmony_ci
8458c2ecf20Sopenharmony_ci# if the addressing mode was (an)+ or -(an), the address register must
8468c2ecf20Sopenharmony_ci# be restored to its pre-exception value before entering _real_access.
8478c2ecf20Sopenharmony_ciisp_restore:
8488c2ecf20Sopenharmony_ci	cmpi.b		SPCOND_FLG(%a6),&restore_flg # do we need a restore?
8498c2ecf20Sopenharmony_ci	bne.b		isp_restore_done	# no
8508c2ecf20Sopenharmony_ci	clr.l		%d0
8518c2ecf20Sopenharmony_ci	mov.b		EXC_SAVREG(%a6),%d0	# regno to restore
8528c2ecf20Sopenharmony_ci	mov.l		EXC_SAVVAL(%a6),(EXC_AREGS,%a6,%d0.l*4) # restore value
8538c2ecf20Sopenharmony_ciisp_restore_done:
8548c2ecf20Sopenharmony_ci	rts
8558c2ecf20Sopenharmony_ci
8568c2ecf20Sopenharmony_ci#########################################################################
8578c2ecf20Sopenharmony_ci# XDEF ****************************************************************	#
8588c2ecf20Sopenharmony_ci#	_calc_ea(): routine to calculate effective address		#
8598c2ecf20Sopenharmony_ci#									#
8608c2ecf20Sopenharmony_ci# XREF ****************************************************************	#
8618c2ecf20Sopenharmony_ci#	_imem_read_word() - read instruction word			#
8628c2ecf20Sopenharmony_ci#	_imem_read_long() - read instruction longword			#
8638c2ecf20Sopenharmony_ci#	_dmem_read_long() - read data longword (for memory indirect)	#
8648c2ecf20Sopenharmony_ci#	isp_iacc() - handle instruction access error exception		#
8658c2ecf20Sopenharmony_ci#	isp_dacc() - handle data access error exception			#
8668c2ecf20Sopenharmony_ci#									#
8678c2ecf20Sopenharmony_ci# INPUT ***************************************************************	#
8688c2ecf20Sopenharmony_ci#	d0 = number of bytes related to effective address (w,l)		#
8698c2ecf20Sopenharmony_ci#									#
8708c2ecf20Sopenharmony_ci# OUTPUT **************************************************************	#
8718c2ecf20Sopenharmony_ci#	If exiting through isp_dacc...					#
8728c2ecf20Sopenharmony_ci#		a0 = failing address					#
8738c2ecf20Sopenharmony_ci#		d0 = FSLW						#
8748c2ecf20Sopenharmony_ci#	elsif exiting though isp_iacc...				#
8758c2ecf20Sopenharmony_ci#		none							#
8768c2ecf20Sopenharmony_ci#	else								#
8778c2ecf20Sopenharmony_ci#		a0 = effective address					#
8788c2ecf20Sopenharmony_ci#									#
8798c2ecf20Sopenharmony_ci# ALGORITHM ***********************************************************	#
8808c2ecf20Sopenharmony_ci#	The effective address type is decoded from the opword residing	#
8818c2ecf20Sopenharmony_ci# on the stack. A jump table is used to vector to a routine for the	#
8828c2ecf20Sopenharmony_ci# appropriate mode. Since none of the emulated integer instructions	#
8838c2ecf20Sopenharmony_ci# uses byte-sized operands, only handle word and long operations.	#
8848c2ecf20Sopenharmony_ci#									#
8858c2ecf20Sopenharmony_ci#	Dn,An	- shouldn't enter here					#
8868c2ecf20Sopenharmony_ci#	(An)	- fetch An value from stack				#
8878c2ecf20Sopenharmony_ci#	-(An)	- fetch An value from stack; return decr value;		#
8888c2ecf20Sopenharmony_ci#		  place decr value on stack; store old value in case of	#
8898c2ecf20Sopenharmony_ci#		  future access error; if -(a7), set mda7_flg in	#
8908c2ecf20Sopenharmony_ci#		  SPCOND_FLG						#
8918c2ecf20Sopenharmony_ci#	(An)+	- fetch An value from stack; return value;		#
8928c2ecf20Sopenharmony_ci#		  place incr value on stack; store old value in case of	#
8938c2ecf20Sopenharmony_ci#		  future access error; if (a7)+, set mia7_flg in	#
8948c2ecf20Sopenharmony_ci#		  SPCOND_FLG						#
8958c2ecf20Sopenharmony_ci#	(d16,An) - fetch An value from stack; read d16 using		#
8968c2ecf20Sopenharmony_ci#		  _imem_read_word(); fetch may fail -> branch to	#
8978c2ecf20Sopenharmony_ci#		  isp_iacc()						#
8988c2ecf20Sopenharmony_ci#	(xxx).w,(xxx).l - use _imem_read_{word,long}() to fetch		#
8998c2ecf20Sopenharmony_ci#		  address; fetch may fail				#
9008c2ecf20Sopenharmony_ci#	#<data> - return address of immediate value; set immed_flg	#
9018c2ecf20Sopenharmony_ci#		  in SPCOND_FLG						#
9028c2ecf20Sopenharmony_ci#	(d16,PC) - fetch stacked PC value; read d16 using		#
9038c2ecf20Sopenharmony_ci#		  _imem_read_word(); fetch may fail -> branch to	#
9048c2ecf20Sopenharmony_ci#		  isp_iacc()						#
9058c2ecf20Sopenharmony_ci#	everything else - read needed displacements as appropriate w/	#
9068c2ecf20Sopenharmony_ci#		  _imem_read_{word,long}(); read may fail; if memory	#
9078c2ecf20Sopenharmony_ci#		  indirect, read indirect address using			#
9088c2ecf20Sopenharmony_ci#		  _dmem_read_long() which may also fail			#
9098c2ecf20Sopenharmony_ci#									#
9108c2ecf20Sopenharmony_ci#########################################################################
9118c2ecf20Sopenharmony_ci
9128c2ecf20Sopenharmony_ci	global		_calc_ea
9138c2ecf20Sopenharmony_ci_calc_ea:
9148c2ecf20Sopenharmony_ci	mov.l		%d0,%a0			# move # bytes to a0
9158c2ecf20Sopenharmony_ci
9168c2ecf20Sopenharmony_ci# MODE and REG are taken from the EXC_OPWORD.
9178c2ecf20Sopenharmony_ci	mov.w		EXC_OPWORD(%a6),%d0	# fetch opcode word
9188c2ecf20Sopenharmony_ci	mov.w		%d0,%d1			# make a copy
9198c2ecf20Sopenharmony_ci
9208c2ecf20Sopenharmony_ci	andi.w		&0x3f,%d0		# extract mode field
9218c2ecf20Sopenharmony_ci	andi.l		&0x7,%d1		# extract reg  field
9228c2ecf20Sopenharmony_ci
9238c2ecf20Sopenharmony_ci# jump to the corresponding function for each {MODE,REG} pair.
9248c2ecf20Sopenharmony_ci	mov.w		(tbl_ea_mode.b,%pc,%d0.w*2), %d0 # fetch jmp distance
9258c2ecf20Sopenharmony_ci	jmp		(tbl_ea_mode.b,%pc,%d0.w*1) # jmp to correct ea mode
9268c2ecf20Sopenharmony_ci
9278c2ecf20Sopenharmony_ci	swbeg		&64
9288c2ecf20Sopenharmony_citbl_ea_mode:
9298c2ecf20Sopenharmony_ci	short		tbl_ea_mode	-	tbl_ea_mode
9308c2ecf20Sopenharmony_ci	short		tbl_ea_mode	-	tbl_ea_mode
9318c2ecf20Sopenharmony_ci	short		tbl_ea_mode	-	tbl_ea_mode
9328c2ecf20Sopenharmony_ci	short		tbl_ea_mode	-	tbl_ea_mode
9338c2ecf20Sopenharmony_ci	short		tbl_ea_mode	-	tbl_ea_mode
9348c2ecf20Sopenharmony_ci	short		tbl_ea_mode	-	tbl_ea_mode
9358c2ecf20Sopenharmony_ci	short		tbl_ea_mode	-	tbl_ea_mode
9368c2ecf20Sopenharmony_ci	short		tbl_ea_mode	-	tbl_ea_mode
9378c2ecf20Sopenharmony_ci
9388c2ecf20Sopenharmony_ci	short		tbl_ea_mode	-	tbl_ea_mode
9398c2ecf20Sopenharmony_ci	short		tbl_ea_mode	-	tbl_ea_mode
9408c2ecf20Sopenharmony_ci	short		tbl_ea_mode	-	tbl_ea_mode
9418c2ecf20Sopenharmony_ci	short		tbl_ea_mode	-	tbl_ea_mode
9428c2ecf20Sopenharmony_ci	short		tbl_ea_mode	-	tbl_ea_mode
9438c2ecf20Sopenharmony_ci	short		tbl_ea_mode	-	tbl_ea_mode
9448c2ecf20Sopenharmony_ci	short		tbl_ea_mode	-	tbl_ea_mode
9458c2ecf20Sopenharmony_ci	short		tbl_ea_mode	-	tbl_ea_mode
9468c2ecf20Sopenharmony_ci
9478c2ecf20Sopenharmony_ci	short		addr_ind_a0	-	tbl_ea_mode
9488c2ecf20Sopenharmony_ci	short		addr_ind_a1	-	tbl_ea_mode
9498c2ecf20Sopenharmony_ci	short		addr_ind_a2	-	tbl_ea_mode
9508c2ecf20Sopenharmony_ci	short		addr_ind_a3	-	tbl_ea_mode
9518c2ecf20Sopenharmony_ci	short		addr_ind_a4	-	tbl_ea_mode
9528c2ecf20Sopenharmony_ci	short		addr_ind_a5	-	tbl_ea_mode
9538c2ecf20Sopenharmony_ci	short		addr_ind_a6	-	tbl_ea_mode
9548c2ecf20Sopenharmony_ci	short		addr_ind_a7	-	tbl_ea_mode
9558c2ecf20Sopenharmony_ci
9568c2ecf20Sopenharmony_ci	short		addr_ind_p_a0	-	tbl_ea_mode
9578c2ecf20Sopenharmony_ci	short		addr_ind_p_a1	-	tbl_ea_mode
9588c2ecf20Sopenharmony_ci	short		addr_ind_p_a2	-	tbl_ea_mode
9598c2ecf20Sopenharmony_ci	short		addr_ind_p_a3	-	tbl_ea_mode
9608c2ecf20Sopenharmony_ci	short		addr_ind_p_a4	-	tbl_ea_mode
9618c2ecf20Sopenharmony_ci	short		addr_ind_p_a5	-	tbl_ea_mode
9628c2ecf20Sopenharmony_ci	short		addr_ind_p_a6	-	tbl_ea_mode
9638c2ecf20Sopenharmony_ci	short		addr_ind_p_a7	-	tbl_ea_mode
9648c2ecf20Sopenharmony_ci
9658c2ecf20Sopenharmony_ci	short		addr_ind_m_a0		-	tbl_ea_mode
9668c2ecf20Sopenharmony_ci	short		addr_ind_m_a1		-	tbl_ea_mode
9678c2ecf20Sopenharmony_ci	short		addr_ind_m_a2		-	tbl_ea_mode
9688c2ecf20Sopenharmony_ci	short		addr_ind_m_a3		-	tbl_ea_mode
9698c2ecf20Sopenharmony_ci	short		addr_ind_m_a4		-	tbl_ea_mode
9708c2ecf20Sopenharmony_ci	short		addr_ind_m_a5		-	tbl_ea_mode
9718c2ecf20Sopenharmony_ci	short		addr_ind_m_a6		-	tbl_ea_mode
9728c2ecf20Sopenharmony_ci	short		addr_ind_m_a7		-	tbl_ea_mode
9738c2ecf20Sopenharmony_ci
9748c2ecf20Sopenharmony_ci	short		addr_ind_disp_a0	-	tbl_ea_mode
9758c2ecf20Sopenharmony_ci	short		addr_ind_disp_a1	-	tbl_ea_mode
9768c2ecf20Sopenharmony_ci	short		addr_ind_disp_a2	-	tbl_ea_mode
9778c2ecf20Sopenharmony_ci	short		addr_ind_disp_a3	-	tbl_ea_mode
9788c2ecf20Sopenharmony_ci	short		addr_ind_disp_a4	-	tbl_ea_mode
9798c2ecf20Sopenharmony_ci	short		addr_ind_disp_a5	-	tbl_ea_mode
9808c2ecf20Sopenharmony_ci	short		addr_ind_disp_a6	-	tbl_ea_mode
9818c2ecf20Sopenharmony_ci	short		addr_ind_disp_a7	-	tbl_ea_mode
9828c2ecf20Sopenharmony_ci
9838c2ecf20Sopenharmony_ci	short		_addr_ind_ext		-	tbl_ea_mode
9848c2ecf20Sopenharmony_ci	short		_addr_ind_ext		-	tbl_ea_mode
9858c2ecf20Sopenharmony_ci	short		_addr_ind_ext		-	tbl_ea_mode
9868c2ecf20Sopenharmony_ci	short		_addr_ind_ext		-	tbl_ea_mode
9878c2ecf20Sopenharmony_ci	short		_addr_ind_ext		-	tbl_ea_mode
9888c2ecf20Sopenharmony_ci	short		_addr_ind_ext		-	tbl_ea_mode
9898c2ecf20Sopenharmony_ci	short		_addr_ind_ext		-	tbl_ea_mode
9908c2ecf20Sopenharmony_ci	short		_addr_ind_ext		-	tbl_ea_mode
9918c2ecf20Sopenharmony_ci
9928c2ecf20Sopenharmony_ci	short		abs_short		-	tbl_ea_mode
9938c2ecf20Sopenharmony_ci	short		abs_long		-	tbl_ea_mode
9948c2ecf20Sopenharmony_ci	short		pc_ind			-	tbl_ea_mode
9958c2ecf20Sopenharmony_ci	short		pc_ind_ext		-	tbl_ea_mode
9968c2ecf20Sopenharmony_ci	short		immediate		-	tbl_ea_mode
9978c2ecf20Sopenharmony_ci	short		tbl_ea_mode		-	tbl_ea_mode
9988c2ecf20Sopenharmony_ci	short		tbl_ea_mode		-	tbl_ea_mode
9998c2ecf20Sopenharmony_ci	short		tbl_ea_mode		-	tbl_ea_mode
10008c2ecf20Sopenharmony_ci
10018c2ecf20Sopenharmony_ci###################################
10028c2ecf20Sopenharmony_ci# Address register indirect: (An) #
10038c2ecf20Sopenharmony_ci###################################
10048c2ecf20Sopenharmony_ciaddr_ind_a0:
10058c2ecf20Sopenharmony_ci	mov.l		EXC_A0(%a6),%a0		# Get current a0
10068c2ecf20Sopenharmony_ci	rts
10078c2ecf20Sopenharmony_ci
10088c2ecf20Sopenharmony_ciaddr_ind_a1:
10098c2ecf20Sopenharmony_ci	mov.l		EXC_A1(%a6),%a0		# Get current a1
10108c2ecf20Sopenharmony_ci	rts
10118c2ecf20Sopenharmony_ci
10128c2ecf20Sopenharmony_ciaddr_ind_a2:
10138c2ecf20Sopenharmony_ci	mov.l		EXC_A2(%a6),%a0		# Get current a2
10148c2ecf20Sopenharmony_ci	rts
10158c2ecf20Sopenharmony_ci
10168c2ecf20Sopenharmony_ciaddr_ind_a3:
10178c2ecf20Sopenharmony_ci	mov.l		EXC_A3(%a6),%a0		# Get current a3
10188c2ecf20Sopenharmony_ci	rts
10198c2ecf20Sopenharmony_ci
10208c2ecf20Sopenharmony_ciaddr_ind_a4:
10218c2ecf20Sopenharmony_ci	mov.l		EXC_A4(%a6),%a0		# Get current a4
10228c2ecf20Sopenharmony_ci	rts
10238c2ecf20Sopenharmony_ci
10248c2ecf20Sopenharmony_ciaddr_ind_a5:
10258c2ecf20Sopenharmony_ci	mov.l		EXC_A5(%a6),%a0		# Get current a5
10268c2ecf20Sopenharmony_ci	rts
10278c2ecf20Sopenharmony_ci
10288c2ecf20Sopenharmony_ciaddr_ind_a6:
10298c2ecf20Sopenharmony_ci	mov.l		EXC_A6(%a6),%a0		# Get current a6
10308c2ecf20Sopenharmony_ci	rts
10318c2ecf20Sopenharmony_ci
10328c2ecf20Sopenharmony_ciaddr_ind_a7:
10338c2ecf20Sopenharmony_ci	mov.l		EXC_A7(%a6),%a0		# Get current a7
10348c2ecf20Sopenharmony_ci	rts
10358c2ecf20Sopenharmony_ci
10368c2ecf20Sopenharmony_ci#####################################################
10378c2ecf20Sopenharmony_ci# Address register indirect w/ postincrement: (An)+ #
10388c2ecf20Sopenharmony_ci#####################################################
10398c2ecf20Sopenharmony_ciaddr_ind_p_a0:
10408c2ecf20Sopenharmony_ci	mov.l		%a0,%d0			# copy no. bytes
10418c2ecf20Sopenharmony_ci	mov.l		EXC_A0(%a6),%a0		# load current value
10428c2ecf20Sopenharmony_ci	add.l		%a0,%d0			# increment
10438c2ecf20Sopenharmony_ci	mov.l		%d0,EXC_A0(%a6)		# save incremented value
10448c2ecf20Sopenharmony_ci
10458c2ecf20Sopenharmony_ci	mov.l		%a0,EXC_SAVVAL(%a6)	# save in case of access error
10468c2ecf20Sopenharmony_ci	mov.b		&0x0,EXC_SAVREG(%a6)	# save regno, too
10478c2ecf20Sopenharmony_ci	mov.b		&restore_flg,SPCOND_FLG(%a6) # set flag
10488c2ecf20Sopenharmony_ci	rts
10498c2ecf20Sopenharmony_ci
10508c2ecf20Sopenharmony_ciaddr_ind_p_a1:
10518c2ecf20Sopenharmony_ci	mov.l		%a0,%d0			# copy no. bytes
10528c2ecf20Sopenharmony_ci	mov.l		EXC_A1(%a6),%a0		# load current value
10538c2ecf20Sopenharmony_ci	add.l		%a0,%d0			# increment
10548c2ecf20Sopenharmony_ci	mov.l		%d0,EXC_A1(%a6)		# save incremented value
10558c2ecf20Sopenharmony_ci
10568c2ecf20Sopenharmony_ci	mov.l		%a0,EXC_SAVVAL(%a6)	# save in case of access error
10578c2ecf20Sopenharmony_ci	mov.b		&0x1,EXC_SAVREG(%a6)	# save regno, too
10588c2ecf20Sopenharmony_ci	mov.b		&restore_flg,SPCOND_FLG(%a6) # set flag
10598c2ecf20Sopenharmony_ci	rts
10608c2ecf20Sopenharmony_ci
10618c2ecf20Sopenharmony_ciaddr_ind_p_a2:
10628c2ecf20Sopenharmony_ci	mov.l		%a0,%d0			# copy no. bytes
10638c2ecf20Sopenharmony_ci	mov.l		EXC_A2(%a6),%a0		# load current value
10648c2ecf20Sopenharmony_ci	add.l		%a0,%d0			# increment
10658c2ecf20Sopenharmony_ci	mov.l		%d0,EXC_A2(%a6)		# save incremented value
10668c2ecf20Sopenharmony_ci
10678c2ecf20Sopenharmony_ci	mov.l		%a0,EXC_SAVVAL(%a6)	# save in case of access error
10688c2ecf20Sopenharmony_ci	mov.b		&0x2,EXC_SAVREG(%a6)	# save regno, too
10698c2ecf20Sopenharmony_ci	mov.b		&restore_flg,SPCOND_FLG(%a6) # set flag
10708c2ecf20Sopenharmony_ci	rts
10718c2ecf20Sopenharmony_ci
10728c2ecf20Sopenharmony_ciaddr_ind_p_a3:
10738c2ecf20Sopenharmony_ci	mov.l		%a0,%d0			# copy no. bytes
10748c2ecf20Sopenharmony_ci	mov.l		EXC_A3(%a6),%a0		# load current value
10758c2ecf20Sopenharmony_ci	add.l		%a0,%d0			# increment
10768c2ecf20Sopenharmony_ci	mov.l		%d0,EXC_A3(%a6)		# save incremented value
10778c2ecf20Sopenharmony_ci
10788c2ecf20Sopenharmony_ci	mov.l		%a0,EXC_SAVVAL(%a6)	# save in case of access error
10798c2ecf20Sopenharmony_ci	mov.b		&0x3,EXC_SAVREG(%a6)	# save regno, too
10808c2ecf20Sopenharmony_ci	mov.b		&restore_flg,SPCOND_FLG(%a6) # set flag
10818c2ecf20Sopenharmony_ci	rts
10828c2ecf20Sopenharmony_ci
10838c2ecf20Sopenharmony_ciaddr_ind_p_a4:
10848c2ecf20Sopenharmony_ci	mov.l		%a0,%d0			# copy no. bytes
10858c2ecf20Sopenharmony_ci	mov.l		EXC_A4(%a6),%a0		# load current value
10868c2ecf20Sopenharmony_ci	add.l		%a0,%d0			# increment
10878c2ecf20Sopenharmony_ci	mov.l		%d0,EXC_A4(%a6)		# save incremented value
10888c2ecf20Sopenharmony_ci
10898c2ecf20Sopenharmony_ci	mov.l		%a0,EXC_SAVVAL(%a6)	# save in case of access error
10908c2ecf20Sopenharmony_ci	mov.b		&0x4,EXC_SAVREG(%a6)	# save regno, too
10918c2ecf20Sopenharmony_ci	mov.b		&restore_flg,SPCOND_FLG(%a6) # set flag
10928c2ecf20Sopenharmony_ci	rts
10938c2ecf20Sopenharmony_ci
10948c2ecf20Sopenharmony_ciaddr_ind_p_a5:
10958c2ecf20Sopenharmony_ci	mov.l		%a0,%d0			# copy no. bytes
10968c2ecf20Sopenharmony_ci	mov.l		EXC_A5(%a6),%a0		# load current value
10978c2ecf20Sopenharmony_ci	add.l		%a0,%d0			# increment
10988c2ecf20Sopenharmony_ci	mov.l		%d0,EXC_A5(%a6)		# save incremented value
10998c2ecf20Sopenharmony_ci
11008c2ecf20Sopenharmony_ci	mov.l		%a0,EXC_SAVVAL(%a6)	# save in case of access error
11018c2ecf20Sopenharmony_ci	mov.b		&0x5,EXC_SAVREG(%a6)	# save regno, too
11028c2ecf20Sopenharmony_ci	mov.b		&restore_flg,SPCOND_FLG(%a6) # set flag
11038c2ecf20Sopenharmony_ci	rts
11048c2ecf20Sopenharmony_ci
11058c2ecf20Sopenharmony_ciaddr_ind_p_a6:
11068c2ecf20Sopenharmony_ci	mov.l		%a0,%d0			# copy no. bytes
11078c2ecf20Sopenharmony_ci	mov.l		EXC_A6(%a6),%a0		# load current value
11088c2ecf20Sopenharmony_ci	add.l		%a0,%d0			# increment
11098c2ecf20Sopenharmony_ci	mov.l		%d0,EXC_A6(%a6)		# save incremented value
11108c2ecf20Sopenharmony_ci
11118c2ecf20Sopenharmony_ci	mov.l		%a0,EXC_SAVVAL(%a6)	# save in case of access error
11128c2ecf20Sopenharmony_ci	mov.b		&0x6,EXC_SAVREG(%a6)	# save regno, too
11138c2ecf20Sopenharmony_ci	mov.b		&restore_flg,SPCOND_FLG(%a6) # set flag
11148c2ecf20Sopenharmony_ci	rts
11158c2ecf20Sopenharmony_ci
11168c2ecf20Sopenharmony_ciaddr_ind_p_a7:
11178c2ecf20Sopenharmony_ci	mov.b		&mia7_flg,SPCOND_FLG(%a6) # set "special case" flag
11188c2ecf20Sopenharmony_ci
11198c2ecf20Sopenharmony_ci	mov.l		%a0,%d0			# copy no. bytes
11208c2ecf20Sopenharmony_ci	mov.l		EXC_A7(%a6),%a0		# load current value
11218c2ecf20Sopenharmony_ci	add.l		%a0,%d0			# increment
11228c2ecf20Sopenharmony_ci	mov.l		%d0,EXC_A7(%a6)		# save incremented value
11238c2ecf20Sopenharmony_ci	rts
11248c2ecf20Sopenharmony_ci
11258c2ecf20Sopenharmony_ci####################################################
11268c2ecf20Sopenharmony_ci# Address register indirect w/ predecrement: -(An) #
11278c2ecf20Sopenharmony_ci####################################################
11288c2ecf20Sopenharmony_ciaddr_ind_m_a0:
11298c2ecf20Sopenharmony_ci	mov.l		EXC_A0(%a6),%d0		# Get current a0
11308c2ecf20Sopenharmony_ci	mov.l		%d0,EXC_SAVVAL(%a6)	# save in case of access error
11318c2ecf20Sopenharmony_ci	sub.l		%a0,%d0			# Decrement
11328c2ecf20Sopenharmony_ci	mov.l		%d0,EXC_A0(%a6)		# Save decr value
11338c2ecf20Sopenharmony_ci	mov.l		%d0,%a0
11348c2ecf20Sopenharmony_ci
11358c2ecf20Sopenharmony_ci	mov.b		&0x0,EXC_SAVREG(%a6)	# save regno, too
11368c2ecf20Sopenharmony_ci	mov.b		&restore_flg,SPCOND_FLG(%a6) # set flag
11378c2ecf20Sopenharmony_ci	rts
11388c2ecf20Sopenharmony_ci
11398c2ecf20Sopenharmony_ciaddr_ind_m_a1:
11408c2ecf20Sopenharmony_ci	mov.l		EXC_A1(%a6),%d0		# Get current a1
11418c2ecf20Sopenharmony_ci	mov.l		%d0,EXC_SAVVAL(%a6)	# save in case of access error
11428c2ecf20Sopenharmony_ci	sub.l		%a0,%d0			# Decrement
11438c2ecf20Sopenharmony_ci	mov.l		%d0,EXC_A1(%a6)		# Save decr value
11448c2ecf20Sopenharmony_ci	mov.l		%d0,%a0
11458c2ecf20Sopenharmony_ci
11468c2ecf20Sopenharmony_ci	mov.b		&0x1,EXC_SAVREG(%a6)	# save regno, too
11478c2ecf20Sopenharmony_ci	mov.b		&restore_flg,SPCOND_FLG(%a6) # set flag
11488c2ecf20Sopenharmony_ci	rts
11498c2ecf20Sopenharmony_ci
11508c2ecf20Sopenharmony_ciaddr_ind_m_a2:
11518c2ecf20Sopenharmony_ci	mov.l		EXC_A2(%a6),%d0		# Get current a2
11528c2ecf20Sopenharmony_ci	mov.l		%d0,EXC_SAVVAL(%a6)	# save in case of access error
11538c2ecf20Sopenharmony_ci	sub.l		%a0,%d0			# Decrement
11548c2ecf20Sopenharmony_ci	mov.l		%d0,EXC_A2(%a6)		# Save decr value
11558c2ecf20Sopenharmony_ci	mov.l		%d0,%a0
11568c2ecf20Sopenharmony_ci
11578c2ecf20Sopenharmony_ci	mov.b		&0x2,EXC_SAVREG(%a6)	# save regno, too
11588c2ecf20Sopenharmony_ci	mov.b		&restore_flg,SPCOND_FLG(%a6) # set flag
11598c2ecf20Sopenharmony_ci	rts
11608c2ecf20Sopenharmony_ci
11618c2ecf20Sopenharmony_ciaddr_ind_m_a3:
11628c2ecf20Sopenharmony_ci	mov.l		EXC_A3(%a6),%d0		# Get current a3
11638c2ecf20Sopenharmony_ci	mov.l		%d0,EXC_SAVVAL(%a6)	# save in case of access error
11648c2ecf20Sopenharmony_ci	sub.l		%a0,%d0			# Decrement
11658c2ecf20Sopenharmony_ci	mov.l		%d0,EXC_A3(%a6)		# Save decr value
11668c2ecf20Sopenharmony_ci	mov.l		%d0,%a0
11678c2ecf20Sopenharmony_ci
11688c2ecf20Sopenharmony_ci	mov.b		&0x3,EXC_SAVREG(%a6)	# save regno, too
11698c2ecf20Sopenharmony_ci	mov.b		&restore_flg,SPCOND_FLG(%a6) # set flag
11708c2ecf20Sopenharmony_ci	rts
11718c2ecf20Sopenharmony_ci
11728c2ecf20Sopenharmony_ciaddr_ind_m_a4:
11738c2ecf20Sopenharmony_ci	mov.l		EXC_A4(%a6),%d0		# Get current a4
11748c2ecf20Sopenharmony_ci	mov.l		%d0,EXC_SAVVAL(%a6)	# save in case of access error
11758c2ecf20Sopenharmony_ci	sub.l		%a0,%d0			# Decrement
11768c2ecf20Sopenharmony_ci	mov.l		%d0,EXC_A4(%a6)		# Save decr value
11778c2ecf20Sopenharmony_ci	mov.l		%d0,%a0
11788c2ecf20Sopenharmony_ci
11798c2ecf20Sopenharmony_ci	mov.b		&0x4,EXC_SAVREG(%a6)	# save regno, too
11808c2ecf20Sopenharmony_ci	mov.b		&restore_flg,SPCOND_FLG(%a6) # set flag
11818c2ecf20Sopenharmony_ci	rts
11828c2ecf20Sopenharmony_ci
11838c2ecf20Sopenharmony_ciaddr_ind_m_a5:
11848c2ecf20Sopenharmony_ci	mov.l		EXC_A5(%a6),%d0		# Get current a5
11858c2ecf20Sopenharmony_ci	mov.l		%d0,EXC_SAVVAL(%a6)	# save in case of access error
11868c2ecf20Sopenharmony_ci	sub.l		%a0,%d0			# Decrement
11878c2ecf20Sopenharmony_ci	mov.l		%d0,EXC_A5(%a6)		# Save decr value
11888c2ecf20Sopenharmony_ci	mov.l		%d0,%a0
11898c2ecf20Sopenharmony_ci
11908c2ecf20Sopenharmony_ci	mov.b		&0x5,EXC_SAVREG(%a6)	# save regno, too
11918c2ecf20Sopenharmony_ci	mov.b		&restore_flg,SPCOND_FLG(%a6) # set flag
11928c2ecf20Sopenharmony_ci	rts
11938c2ecf20Sopenharmony_ci
11948c2ecf20Sopenharmony_ciaddr_ind_m_a6:
11958c2ecf20Sopenharmony_ci	mov.l		EXC_A6(%a6),%d0		# Get current a6
11968c2ecf20Sopenharmony_ci	mov.l		%d0,EXC_SAVVAL(%a6)	# save in case of access error
11978c2ecf20Sopenharmony_ci	sub.l		%a0,%d0			# Decrement
11988c2ecf20Sopenharmony_ci	mov.l		%d0,EXC_A6(%a6)		# Save decr value
11998c2ecf20Sopenharmony_ci	mov.l		%d0,%a0
12008c2ecf20Sopenharmony_ci
12018c2ecf20Sopenharmony_ci	mov.b		&0x6,EXC_SAVREG(%a6)	# save regno, too
12028c2ecf20Sopenharmony_ci	mov.b		&restore_flg,SPCOND_FLG(%a6) # set flag
12038c2ecf20Sopenharmony_ci	rts
12048c2ecf20Sopenharmony_ci
12058c2ecf20Sopenharmony_ciaddr_ind_m_a7:
12068c2ecf20Sopenharmony_ci	mov.b		&mda7_flg,SPCOND_FLG(%a6) # set "special case" flag
12078c2ecf20Sopenharmony_ci
12088c2ecf20Sopenharmony_ci	mov.l		EXC_A7(%a6),%d0		# Get current a7
12098c2ecf20Sopenharmony_ci	sub.l		%a0,%d0			# Decrement
12108c2ecf20Sopenharmony_ci	mov.l		%d0,EXC_A7(%a6)		# Save decr value
12118c2ecf20Sopenharmony_ci	mov.l		%d0,%a0
12128c2ecf20Sopenharmony_ci	rts
12138c2ecf20Sopenharmony_ci
12148c2ecf20Sopenharmony_ci########################################################
12158c2ecf20Sopenharmony_ci# Address register indirect w/ displacement: (d16, An) #
12168c2ecf20Sopenharmony_ci########################################################
12178c2ecf20Sopenharmony_ciaddr_ind_disp_a0:
12188c2ecf20Sopenharmony_ci	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
12198c2ecf20Sopenharmony_ci	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
12208c2ecf20Sopenharmony_ci	bsr.l		_imem_read_word
12218c2ecf20Sopenharmony_ci
12228c2ecf20Sopenharmony_ci	tst.l		%d1			# ifetch error?
12238c2ecf20Sopenharmony_ci	bne.l		isp_iacc		# yes
12248c2ecf20Sopenharmony_ci
12258c2ecf20Sopenharmony_ci	mov.w		%d0,%a0			# sign extend displacement
12268c2ecf20Sopenharmony_ci	add.l		EXC_A0(%a6),%a0		# a0 + d16
12278c2ecf20Sopenharmony_ci	rts
12288c2ecf20Sopenharmony_ci
12298c2ecf20Sopenharmony_ciaddr_ind_disp_a1:
12308c2ecf20Sopenharmony_ci	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
12318c2ecf20Sopenharmony_ci	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
12328c2ecf20Sopenharmony_ci	bsr.l		_imem_read_word
12338c2ecf20Sopenharmony_ci
12348c2ecf20Sopenharmony_ci	tst.l		%d1			# ifetch error?
12358c2ecf20Sopenharmony_ci	bne.l		isp_iacc		# yes
12368c2ecf20Sopenharmony_ci
12378c2ecf20Sopenharmony_ci	mov.w		%d0,%a0			# sign extend displacement
12388c2ecf20Sopenharmony_ci	add.l		EXC_A1(%a6),%a0		# a1 + d16
12398c2ecf20Sopenharmony_ci	rts
12408c2ecf20Sopenharmony_ci
12418c2ecf20Sopenharmony_ciaddr_ind_disp_a2:
12428c2ecf20Sopenharmony_ci	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
12438c2ecf20Sopenharmony_ci	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
12448c2ecf20Sopenharmony_ci	bsr.l		_imem_read_word
12458c2ecf20Sopenharmony_ci
12468c2ecf20Sopenharmony_ci	tst.l		%d1			# ifetch error?
12478c2ecf20Sopenharmony_ci	bne.l		isp_iacc		# yes
12488c2ecf20Sopenharmony_ci
12498c2ecf20Sopenharmony_ci	mov.w		%d0,%a0			# sign extend displacement
12508c2ecf20Sopenharmony_ci	add.l		EXC_A2(%a6),%a0		# a2 + d16
12518c2ecf20Sopenharmony_ci	rts
12528c2ecf20Sopenharmony_ci
12538c2ecf20Sopenharmony_ciaddr_ind_disp_a3:
12548c2ecf20Sopenharmony_ci	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
12558c2ecf20Sopenharmony_ci	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
12568c2ecf20Sopenharmony_ci	bsr.l		_imem_read_word
12578c2ecf20Sopenharmony_ci
12588c2ecf20Sopenharmony_ci	tst.l		%d1			# ifetch error?
12598c2ecf20Sopenharmony_ci	bne.l		isp_iacc		# yes
12608c2ecf20Sopenharmony_ci
12618c2ecf20Sopenharmony_ci	mov.w		%d0,%a0			# sign extend displacement
12628c2ecf20Sopenharmony_ci	add.l		EXC_A3(%a6),%a0		# a3 + d16
12638c2ecf20Sopenharmony_ci	rts
12648c2ecf20Sopenharmony_ci
12658c2ecf20Sopenharmony_ciaddr_ind_disp_a4:
12668c2ecf20Sopenharmony_ci	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
12678c2ecf20Sopenharmony_ci	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
12688c2ecf20Sopenharmony_ci	bsr.l		_imem_read_word
12698c2ecf20Sopenharmony_ci
12708c2ecf20Sopenharmony_ci	tst.l		%d1			# ifetch error?
12718c2ecf20Sopenharmony_ci	bne.l		isp_iacc		# yes
12728c2ecf20Sopenharmony_ci
12738c2ecf20Sopenharmony_ci	mov.w		%d0,%a0			# sign extend displacement
12748c2ecf20Sopenharmony_ci	add.l		EXC_A4(%a6),%a0		# a4 + d16
12758c2ecf20Sopenharmony_ci	rts
12768c2ecf20Sopenharmony_ci
12778c2ecf20Sopenharmony_ciaddr_ind_disp_a5:
12788c2ecf20Sopenharmony_ci	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
12798c2ecf20Sopenharmony_ci	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
12808c2ecf20Sopenharmony_ci	bsr.l		_imem_read_word
12818c2ecf20Sopenharmony_ci
12828c2ecf20Sopenharmony_ci	tst.l		%d1			# ifetch error?
12838c2ecf20Sopenharmony_ci	bne.l		isp_iacc		# yes
12848c2ecf20Sopenharmony_ci
12858c2ecf20Sopenharmony_ci	mov.w		%d0,%a0			# sign extend displacement
12868c2ecf20Sopenharmony_ci	add.l		EXC_A5(%a6),%a0		# a5 + d16
12878c2ecf20Sopenharmony_ci	rts
12888c2ecf20Sopenharmony_ci
12898c2ecf20Sopenharmony_ciaddr_ind_disp_a6:
12908c2ecf20Sopenharmony_ci	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
12918c2ecf20Sopenharmony_ci	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
12928c2ecf20Sopenharmony_ci	bsr.l		_imem_read_word
12938c2ecf20Sopenharmony_ci
12948c2ecf20Sopenharmony_ci	tst.l		%d1			# ifetch error?
12958c2ecf20Sopenharmony_ci	bne.l		isp_iacc		# yes
12968c2ecf20Sopenharmony_ci
12978c2ecf20Sopenharmony_ci	mov.w		%d0,%a0			# sign extend displacement
12988c2ecf20Sopenharmony_ci	add.l		EXC_A6(%a6),%a0		# a6 + d16
12998c2ecf20Sopenharmony_ci	rts
13008c2ecf20Sopenharmony_ci
13018c2ecf20Sopenharmony_ciaddr_ind_disp_a7:
13028c2ecf20Sopenharmony_ci	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
13038c2ecf20Sopenharmony_ci	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
13048c2ecf20Sopenharmony_ci	bsr.l		_imem_read_word
13058c2ecf20Sopenharmony_ci
13068c2ecf20Sopenharmony_ci	tst.l		%d1			# ifetch error?
13078c2ecf20Sopenharmony_ci	bne.l		isp_iacc		# yes
13088c2ecf20Sopenharmony_ci
13098c2ecf20Sopenharmony_ci	mov.w		%d0,%a0			# sign extend displacement
13108c2ecf20Sopenharmony_ci	add.l		EXC_A7(%a6),%a0		# a7 + d16
13118c2ecf20Sopenharmony_ci	rts
13128c2ecf20Sopenharmony_ci
13138c2ecf20Sopenharmony_ci########################################################################
13148c2ecf20Sopenharmony_ci# Address register indirect w/ index(8-bit displacement): (dn, An, Xn) #
13158c2ecf20Sopenharmony_ci#    "       "         "    w/   "  (base displacement): (bd, An, Xn)  #
13168c2ecf20Sopenharmony_ci# Memory indirect postindexed: ([bd, An], Xn, od)		       #
13178c2ecf20Sopenharmony_ci# Memory indirect preindexed: ([bd, An, Xn], od)		       #
13188c2ecf20Sopenharmony_ci########################################################################
13198c2ecf20Sopenharmony_ci_addr_ind_ext:
13208c2ecf20Sopenharmony_ci	mov.l		%d1,-(%sp)
13218c2ecf20Sopenharmony_ci
13228c2ecf20Sopenharmony_ci	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
13238c2ecf20Sopenharmony_ci	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
13248c2ecf20Sopenharmony_ci	bsr.l		_imem_read_word		# fetch extword in d0
13258c2ecf20Sopenharmony_ci
13268c2ecf20Sopenharmony_ci	tst.l		%d1			# ifetch error?
13278c2ecf20Sopenharmony_ci	bne.l		isp_iacc		# yes
13288c2ecf20Sopenharmony_ci
13298c2ecf20Sopenharmony_ci	mov.l		(%sp)+,%d1
13308c2ecf20Sopenharmony_ci
13318c2ecf20Sopenharmony_ci	mov.l		(EXC_AREGS,%a6,%d1.w*4),%a0 # put base in a0
13328c2ecf20Sopenharmony_ci
13338c2ecf20Sopenharmony_ci	btst		&0x8,%d0
13348c2ecf20Sopenharmony_ci	beq.b		addr_ind_index_8bit	# for ext word or not?
13358c2ecf20Sopenharmony_ci
13368c2ecf20Sopenharmony_ci	movm.l		&0x3c00,-(%sp)		# save d2-d5
13378c2ecf20Sopenharmony_ci
13388c2ecf20Sopenharmony_ci	mov.l		%d0,%d5			# put extword in d5
13398c2ecf20Sopenharmony_ci	mov.l		%a0,%d3			# put base in d3
13408c2ecf20Sopenharmony_ci
13418c2ecf20Sopenharmony_ci	bra.l		calc_mem_ind		# calc memory indirect
13428c2ecf20Sopenharmony_ci
13438c2ecf20Sopenharmony_ciaddr_ind_index_8bit:
13448c2ecf20Sopenharmony_ci	mov.l		%d2,-(%sp)		# save old d2
13458c2ecf20Sopenharmony_ci
13468c2ecf20Sopenharmony_ci	mov.l		%d0,%d1
13478c2ecf20Sopenharmony_ci	rol.w		&0x4,%d1
13488c2ecf20Sopenharmony_ci	andi.w		&0xf,%d1		# extract index regno
13498c2ecf20Sopenharmony_ci
13508c2ecf20Sopenharmony_ci	mov.l		(EXC_DREGS,%a6,%d1.w*4),%d1 # fetch index reg value
13518c2ecf20Sopenharmony_ci
13528c2ecf20Sopenharmony_ci	btst		&0xb,%d0		# is it word or long?
13538c2ecf20Sopenharmony_ci	bne.b		aii8_long
13548c2ecf20Sopenharmony_ci	ext.l		%d1			# sign extend word index
13558c2ecf20Sopenharmony_ciaii8_long:
13568c2ecf20Sopenharmony_ci	mov.l		%d0,%d2
13578c2ecf20Sopenharmony_ci	rol.w		&0x7,%d2
13588c2ecf20Sopenharmony_ci	andi.l		&0x3,%d2		# extract scale value
13598c2ecf20Sopenharmony_ci
13608c2ecf20Sopenharmony_ci	lsl.l		%d2,%d1			# shift index by scale
13618c2ecf20Sopenharmony_ci
13628c2ecf20Sopenharmony_ci	extb.l		%d0			# sign extend displacement
13638c2ecf20Sopenharmony_ci	add.l		%d1,%d0			# index + disp
13648c2ecf20Sopenharmony_ci	add.l		%d0,%a0			# An + (index + disp)
13658c2ecf20Sopenharmony_ci
13668c2ecf20Sopenharmony_ci	mov.l		(%sp)+,%d2		# restore old d2
13678c2ecf20Sopenharmony_ci	rts
13688c2ecf20Sopenharmony_ci
13698c2ecf20Sopenharmony_ci######################
13708c2ecf20Sopenharmony_ci# Immediate: #<data> #
13718c2ecf20Sopenharmony_ci#########################################################################
13728c2ecf20Sopenharmony_ci# word, long: <ea> of the data is the current extension word		#
13738c2ecf20Sopenharmony_ci#	pointer value. new extension word pointer is simply the old	#
13748c2ecf20Sopenharmony_ci#	plus the number of bytes in the data type(2 or 4).		#
13758c2ecf20Sopenharmony_ci#########################################################################
13768c2ecf20Sopenharmony_ciimmediate:
13778c2ecf20Sopenharmony_ci	mov.b		&immed_flg,SPCOND_FLG(%a6) # set immediate flag
13788c2ecf20Sopenharmony_ci
13798c2ecf20Sopenharmony_ci	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch extension word ptr
13808c2ecf20Sopenharmony_ci	rts
13818c2ecf20Sopenharmony_ci
13828c2ecf20Sopenharmony_ci###########################
13838c2ecf20Sopenharmony_ci# Absolute short: (XXX).W #
13848c2ecf20Sopenharmony_ci###########################
13858c2ecf20Sopenharmony_ciabs_short:
13868c2ecf20Sopenharmony_ci	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
13878c2ecf20Sopenharmony_ci	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
13888c2ecf20Sopenharmony_ci	bsr.l		_imem_read_word		# fetch short address
13898c2ecf20Sopenharmony_ci
13908c2ecf20Sopenharmony_ci	tst.l		%d1			# ifetch error?
13918c2ecf20Sopenharmony_ci	bne.l		isp_iacc		# yes
13928c2ecf20Sopenharmony_ci
13938c2ecf20Sopenharmony_ci	mov.w		%d0,%a0			# return <ea> in a0
13948c2ecf20Sopenharmony_ci	rts
13958c2ecf20Sopenharmony_ci
13968c2ecf20Sopenharmony_ci##########################
13978c2ecf20Sopenharmony_ci# Absolute long: (XXX).L #
13988c2ecf20Sopenharmony_ci##########################
13998c2ecf20Sopenharmony_ciabs_long:
14008c2ecf20Sopenharmony_ci	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
14018c2ecf20Sopenharmony_ci	addq.l		&0x4,EXC_EXTWPTR(%a6)	# incr instruction ptr
14028c2ecf20Sopenharmony_ci	bsr.l		_imem_read_long		# fetch long address
14038c2ecf20Sopenharmony_ci
14048c2ecf20Sopenharmony_ci	tst.l		%d1			# ifetch error?
14058c2ecf20Sopenharmony_ci	bne.l		isp_iacc		# yes
14068c2ecf20Sopenharmony_ci
14078c2ecf20Sopenharmony_ci	mov.l		%d0,%a0			# return <ea> in a0
14088c2ecf20Sopenharmony_ci	rts
14098c2ecf20Sopenharmony_ci
14108c2ecf20Sopenharmony_ci#######################################################
14118c2ecf20Sopenharmony_ci# Program counter indirect w/ displacement: (d16, PC) #
14128c2ecf20Sopenharmony_ci#######################################################
14138c2ecf20Sopenharmony_cipc_ind:
14148c2ecf20Sopenharmony_ci	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
14158c2ecf20Sopenharmony_ci	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
14168c2ecf20Sopenharmony_ci	bsr.l		_imem_read_word		# fetch word displacement
14178c2ecf20Sopenharmony_ci
14188c2ecf20Sopenharmony_ci	tst.l		%d1			# ifetch error?
14198c2ecf20Sopenharmony_ci	bne.l		isp_iacc		# yes
14208c2ecf20Sopenharmony_ci
14218c2ecf20Sopenharmony_ci	mov.w		%d0,%a0			# sign extend displacement
14228c2ecf20Sopenharmony_ci
14238c2ecf20Sopenharmony_ci	add.l		EXC_EXTWPTR(%a6),%a0	# pc + d16
14248c2ecf20Sopenharmony_ci
14258c2ecf20Sopenharmony_ci# _imem_read_word() increased the extwptr by 2. need to adjust here.
14268c2ecf20Sopenharmony_ci	subq.l		&0x2,%a0		# adjust <ea>
14278c2ecf20Sopenharmony_ci
14288c2ecf20Sopenharmony_ci	rts
14298c2ecf20Sopenharmony_ci
14308c2ecf20Sopenharmony_ci##########################################################
14318c2ecf20Sopenharmony_ci# PC indirect w/ index(8-bit displacement): (d8, PC, An) #
14328c2ecf20Sopenharmony_ci# "     "     w/   "  (base displacement): (bd, PC, An)  #
14338c2ecf20Sopenharmony_ci# PC memory indirect postindexed: ([bd, PC], Xn, od)     #
14348c2ecf20Sopenharmony_ci# PC memory indirect preindexed: ([bd, PC, Xn], od)      #
14358c2ecf20Sopenharmony_ci##########################################################
14368c2ecf20Sopenharmony_cipc_ind_ext:
14378c2ecf20Sopenharmony_ci	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
14388c2ecf20Sopenharmony_ci	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
14398c2ecf20Sopenharmony_ci	bsr.l		_imem_read_word		# fetch ext word
14408c2ecf20Sopenharmony_ci
14418c2ecf20Sopenharmony_ci	tst.l		%d1			# ifetch error?
14428c2ecf20Sopenharmony_ci	bne.l		isp_iacc		# yes
14438c2ecf20Sopenharmony_ci
14448c2ecf20Sopenharmony_ci	mov.l		EXC_EXTWPTR(%a6),%a0	# put base in a0
14458c2ecf20Sopenharmony_ci	subq.l		&0x2,%a0		# adjust base
14468c2ecf20Sopenharmony_ci
14478c2ecf20Sopenharmony_ci	btst		&0x8,%d0		# is disp only 8 bits?
14488c2ecf20Sopenharmony_ci	beq.b		pc_ind_index_8bit	# yes
14498c2ecf20Sopenharmony_ci
14508c2ecf20Sopenharmony_ci# the indexed addressing mode uses a base displacement of size
14518c2ecf20Sopenharmony_ci# word or long
14528c2ecf20Sopenharmony_ci	movm.l		&0x3c00,-(%sp)		# save d2-d5
14538c2ecf20Sopenharmony_ci
14548c2ecf20Sopenharmony_ci	mov.l		%d0,%d5			# put extword in d5
14558c2ecf20Sopenharmony_ci	mov.l		%a0,%d3			# put base in d3
14568c2ecf20Sopenharmony_ci
14578c2ecf20Sopenharmony_ci	bra.l		calc_mem_ind		# calc memory indirect
14588c2ecf20Sopenharmony_ci
14598c2ecf20Sopenharmony_cipc_ind_index_8bit:
14608c2ecf20Sopenharmony_ci	mov.l		%d2,-(%sp)		# create a temp register
14618c2ecf20Sopenharmony_ci
14628c2ecf20Sopenharmony_ci	mov.l		%d0,%d1			# make extword copy
14638c2ecf20Sopenharmony_ci	rol.w		&0x4,%d1		# rotate reg num into place
14648c2ecf20Sopenharmony_ci	andi.w		&0xf,%d1		# extract register number
14658c2ecf20Sopenharmony_ci
14668c2ecf20Sopenharmony_ci	mov.l		(EXC_DREGS,%a6,%d1.w*4),%d1 # fetch index reg value
14678c2ecf20Sopenharmony_ci
14688c2ecf20Sopenharmony_ci	btst		&0xb,%d0		# is index word or long?
14698c2ecf20Sopenharmony_ci	bne.b		pii8_long		# long
14708c2ecf20Sopenharmony_ci	ext.l		%d1			# sign extend word index
14718c2ecf20Sopenharmony_cipii8_long:
14728c2ecf20Sopenharmony_ci	mov.l		%d0,%d2			# make extword copy
14738c2ecf20Sopenharmony_ci	rol.w		&0x7,%d2		# rotate scale value into place
14748c2ecf20Sopenharmony_ci	andi.l		&0x3,%d2		# extract scale value
14758c2ecf20Sopenharmony_ci
14768c2ecf20Sopenharmony_ci	lsl.l		%d2,%d1			# shift index by scale
14778c2ecf20Sopenharmony_ci
14788c2ecf20Sopenharmony_ci	extb.l		%d0			# sign extend displacement
14798c2ecf20Sopenharmony_ci	add.l		%d1,%d0			# index + disp
14808c2ecf20Sopenharmony_ci	add.l		%d0,%a0			# An + (index + disp)
14818c2ecf20Sopenharmony_ci
14828c2ecf20Sopenharmony_ci	mov.l		(%sp)+,%d2		# restore temp register
14838c2ecf20Sopenharmony_ci
14848c2ecf20Sopenharmony_ci	rts
14858c2ecf20Sopenharmony_ci
14868c2ecf20Sopenharmony_ci# a5 = exc_extwptr	(global to uaeh)
14878c2ecf20Sopenharmony_ci# a4 = exc_opword	(global to uaeh)
14888c2ecf20Sopenharmony_ci# a3 = exc_dregs	(global to uaeh)
14898c2ecf20Sopenharmony_ci
14908c2ecf20Sopenharmony_ci# d2 = index		(internal "     "    )
14918c2ecf20Sopenharmony_ci# d3 = base		(internal "     "    )
14928c2ecf20Sopenharmony_ci# d4 = od		(internal "     "    )
14938c2ecf20Sopenharmony_ci# d5 = extword		(internal "     "    )
14948c2ecf20Sopenharmony_cicalc_mem_ind:
14958c2ecf20Sopenharmony_ci	btst		&0x6,%d5		# is the index suppressed?
14968c2ecf20Sopenharmony_ci	beq.b		calc_index
14978c2ecf20Sopenharmony_ci	clr.l		%d2			# yes, so index = 0
14988c2ecf20Sopenharmony_ci	bra.b		base_supp_ck
14998c2ecf20Sopenharmony_cicalc_index:
15008c2ecf20Sopenharmony_ci	bfextu		%d5{&16:&4},%d2
15018c2ecf20Sopenharmony_ci	mov.l		(EXC_DREGS,%a6,%d2.w*4),%d2
15028c2ecf20Sopenharmony_ci	btst		&0xb,%d5		# is index word or long?
15038c2ecf20Sopenharmony_ci	bne.b		no_ext
15048c2ecf20Sopenharmony_ci	ext.l		%d2
15058c2ecf20Sopenharmony_cino_ext:
15068c2ecf20Sopenharmony_ci	bfextu		%d5{&21:&2},%d0
15078c2ecf20Sopenharmony_ci	lsl.l		%d0,%d2
15088c2ecf20Sopenharmony_cibase_supp_ck:
15098c2ecf20Sopenharmony_ci	btst		&0x7,%d5		# is the bd suppressed?
15108c2ecf20Sopenharmony_ci	beq.b		no_base_sup
15118c2ecf20Sopenharmony_ci	clr.l		%d3
15128c2ecf20Sopenharmony_cino_base_sup:
15138c2ecf20Sopenharmony_ci	bfextu		%d5{&26:&2},%d0	# get bd size
15148c2ecf20Sopenharmony_ci#	beq.l		_error			# if (size == 0) it's reserved
15158c2ecf20Sopenharmony_ci	cmpi.b		%d0,&2
15168c2ecf20Sopenharmony_ci	blt.b		no_bd
15178c2ecf20Sopenharmony_ci	beq.b		get_word_bd
15188c2ecf20Sopenharmony_ci
15198c2ecf20Sopenharmony_ci	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
15208c2ecf20Sopenharmony_ci	addq.l		&0x4,EXC_EXTWPTR(%a6)	# incr instruction ptr
15218c2ecf20Sopenharmony_ci	bsr.l		_imem_read_long
15228c2ecf20Sopenharmony_ci
15238c2ecf20Sopenharmony_ci	tst.l		%d1			# ifetch error?
15248c2ecf20Sopenharmony_ci	bne.l		isp_iacc		# yes
15258c2ecf20Sopenharmony_ci
15268c2ecf20Sopenharmony_ci	bra.b		chk_ind
15278c2ecf20Sopenharmony_ciget_word_bd:
15288c2ecf20Sopenharmony_ci	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
15298c2ecf20Sopenharmony_ci	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
15308c2ecf20Sopenharmony_ci	bsr.l		_imem_read_word
15318c2ecf20Sopenharmony_ci
15328c2ecf20Sopenharmony_ci	tst.l		%d1			# ifetch error?
15338c2ecf20Sopenharmony_ci	bne.l		isp_iacc		# yes
15348c2ecf20Sopenharmony_ci
15358c2ecf20Sopenharmony_ci	ext.l		%d0			# sign extend bd
15368c2ecf20Sopenharmony_ci
15378c2ecf20Sopenharmony_cichk_ind:
15388c2ecf20Sopenharmony_ci	add.l		%d0,%d3			# base += bd
15398c2ecf20Sopenharmony_cino_bd:
15408c2ecf20Sopenharmony_ci	bfextu		%d5{&30:&2},%d0		# is od suppressed?
15418c2ecf20Sopenharmony_ci	beq.w		aii_bd
15428c2ecf20Sopenharmony_ci	cmpi.b		%d0,&0x2
15438c2ecf20Sopenharmony_ci	blt.b		null_od
15448c2ecf20Sopenharmony_ci	beq.b		word_od
15458c2ecf20Sopenharmony_ci
15468c2ecf20Sopenharmony_ci	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
15478c2ecf20Sopenharmony_ci	addq.l		&0x4,EXC_EXTWPTR(%a6)	# incr instruction ptr
15488c2ecf20Sopenharmony_ci	bsr.l		_imem_read_long
15498c2ecf20Sopenharmony_ci
15508c2ecf20Sopenharmony_ci	tst.l		%d1			# ifetch error?
15518c2ecf20Sopenharmony_ci	bne.l		isp_iacc		# yes
15528c2ecf20Sopenharmony_ci
15538c2ecf20Sopenharmony_ci	bra.b		add_them
15548c2ecf20Sopenharmony_ci
15558c2ecf20Sopenharmony_ciword_od:
15568c2ecf20Sopenharmony_ci	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
15578c2ecf20Sopenharmony_ci	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
15588c2ecf20Sopenharmony_ci	bsr.l		_imem_read_word
15598c2ecf20Sopenharmony_ci
15608c2ecf20Sopenharmony_ci	tst.l		%d1			# ifetch error?
15618c2ecf20Sopenharmony_ci	bne.l		isp_iacc		# yes
15628c2ecf20Sopenharmony_ci
15638c2ecf20Sopenharmony_ci	ext.l		%d0			# sign extend od
15648c2ecf20Sopenharmony_ci	bra.b		add_them
15658c2ecf20Sopenharmony_ci
15668c2ecf20Sopenharmony_cinull_od:
15678c2ecf20Sopenharmony_ci	clr.l		%d0
15688c2ecf20Sopenharmony_ciadd_them:
15698c2ecf20Sopenharmony_ci	mov.l		%d0,%d4
15708c2ecf20Sopenharmony_ci	btst		&0x2,%d5		# pre or post indexing?
15718c2ecf20Sopenharmony_ci	beq.b		pre_indexed
15728c2ecf20Sopenharmony_ci
15738c2ecf20Sopenharmony_ci	mov.l		%d3,%a0
15748c2ecf20Sopenharmony_ci	bsr.l		_dmem_read_long
15758c2ecf20Sopenharmony_ci
15768c2ecf20Sopenharmony_ci	tst.l		%d1			# dfetch error?
15778c2ecf20Sopenharmony_ci	bne.b		calc_ea_err		# yes
15788c2ecf20Sopenharmony_ci
15798c2ecf20Sopenharmony_ci	add.l		%d2,%d0			# <ea> += index
15808c2ecf20Sopenharmony_ci	add.l		%d4,%d0			# <ea> += od
15818c2ecf20Sopenharmony_ci	bra.b		done_ea
15828c2ecf20Sopenharmony_ci
15838c2ecf20Sopenharmony_cipre_indexed:
15848c2ecf20Sopenharmony_ci	add.l		%d2,%d3			# preindexing
15858c2ecf20Sopenharmony_ci	mov.l		%d3,%a0
15868c2ecf20Sopenharmony_ci	bsr.l		_dmem_read_long
15878c2ecf20Sopenharmony_ci
15888c2ecf20Sopenharmony_ci	tst.l		%d1			# ifetch error?
15898c2ecf20Sopenharmony_ci	bne.b		calc_ea_err		# yes
15908c2ecf20Sopenharmony_ci
15918c2ecf20Sopenharmony_ci	add.l		%d4,%d0			# ea += od
15928c2ecf20Sopenharmony_ci	bra.b		done_ea
15938c2ecf20Sopenharmony_ci
15948c2ecf20Sopenharmony_ciaii_bd:
15958c2ecf20Sopenharmony_ci	add.l		%d2,%d3			# ea = (base + bd) + index
15968c2ecf20Sopenharmony_ci	mov.l		%d3,%d0
15978c2ecf20Sopenharmony_cidone_ea:
15988c2ecf20Sopenharmony_ci	mov.l		%d0,%a0
15998c2ecf20Sopenharmony_ci
16008c2ecf20Sopenharmony_ci	movm.l		(%sp)+,&0x003c		# restore d2-d5
16018c2ecf20Sopenharmony_ci	rts
16028c2ecf20Sopenharmony_ci
16038c2ecf20Sopenharmony_ci# if dmem_read_long() returns a fail message in d1, the package
16048c2ecf20Sopenharmony_ci# must create an access error frame. here, we pass a skeleton fslw
16058c2ecf20Sopenharmony_ci# and the failing address to the routine that creates the new frame.
16068c2ecf20Sopenharmony_ci# FSLW:
16078c2ecf20Sopenharmony_ci#	read = true
16088c2ecf20Sopenharmony_ci#	size = longword
16098c2ecf20Sopenharmony_ci#	TM = data
16108c2ecf20Sopenharmony_ci#	software emulation error = true
16118c2ecf20Sopenharmony_cicalc_ea_err:
16128c2ecf20Sopenharmony_ci	mov.l		%d3,%a0			# pass failing address
16138c2ecf20Sopenharmony_ci	mov.l		&0x01010001,%d0		# pass fslw
16148c2ecf20Sopenharmony_ci	bra.l		isp_dacc
16158c2ecf20Sopenharmony_ci
16168c2ecf20Sopenharmony_ci#########################################################################
16178c2ecf20Sopenharmony_ci# XDEF **************************************************************** #
16188c2ecf20Sopenharmony_ci#	_moveperipheral(): routine to emulate movep instruction		#
16198c2ecf20Sopenharmony_ci#									#
16208c2ecf20Sopenharmony_ci# XREF **************************************************************** #
16218c2ecf20Sopenharmony_ci#	_dmem_read_byte() - read byte from memory			#
16228c2ecf20Sopenharmony_ci#	_dmem_write_byte() - write byte to memory			#
16238c2ecf20Sopenharmony_ci#	isp_dacc() - handle data access error exception			#
16248c2ecf20Sopenharmony_ci#									#
16258c2ecf20Sopenharmony_ci# INPUT *************************************************************** #
16268c2ecf20Sopenharmony_ci#	none								#
16278c2ecf20Sopenharmony_ci#									#
16288c2ecf20Sopenharmony_ci# OUTPUT ************************************************************** #
16298c2ecf20Sopenharmony_ci#	If exiting through isp_dacc...					#
16308c2ecf20Sopenharmony_ci#		a0 = failing address					#
16318c2ecf20Sopenharmony_ci#		d0 = FSLW						#
16328c2ecf20Sopenharmony_ci#	else								#
16338c2ecf20Sopenharmony_ci#		none							#
16348c2ecf20Sopenharmony_ci#									#
16358c2ecf20Sopenharmony_ci# ALGORITHM ***********************************************************	#
16368c2ecf20Sopenharmony_ci#	Decode the movep instruction words stored at EXC_OPWORD and	#
16378c2ecf20Sopenharmony_ci# either read or write the required bytes from/to memory. Use the	#
16388c2ecf20Sopenharmony_ci# _dmem_{read,write}_byte() routines. If one of the memory routines	#
16398c2ecf20Sopenharmony_ci# returns a failing value, we must pass the failing address and	a FSLW	#
16408c2ecf20Sopenharmony_ci# to the _isp_dacc() routine.						#
16418c2ecf20Sopenharmony_ci#	Since this instruction is used to access peripherals, make sure	#
16428c2ecf20Sopenharmony_ci# to only access the required bytes.					#
16438c2ecf20Sopenharmony_ci#									#
16448c2ecf20Sopenharmony_ci#########################################################################
16458c2ecf20Sopenharmony_ci
16468c2ecf20Sopenharmony_ci###########################
16478c2ecf20Sopenharmony_ci# movep.(w,l)	Dx,(d,Ay) #
16488c2ecf20Sopenharmony_ci# movep.(w,l)	(d,Ay),Dx #
16498c2ecf20Sopenharmony_ci###########################
16508c2ecf20Sopenharmony_ci	global		_moveperipheral
16518c2ecf20Sopenharmony_ci_moveperipheral:
16528c2ecf20Sopenharmony_ci	mov.w		EXC_OPWORD(%a6),%d1	# fetch the opcode word
16538c2ecf20Sopenharmony_ci
16548c2ecf20Sopenharmony_ci	mov.b		%d1,%d0
16558c2ecf20Sopenharmony_ci	and.w		&0x7,%d0		# extract Ay from opcode word
16568c2ecf20Sopenharmony_ci
16578c2ecf20Sopenharmony_ci	mov.l		(EXC_AREGS,%a6,%d0.w*4),%a0 # fetch ay
16588c2ecf20Sopenharmony_ci
16598c2ecf20Sopenharmony_ci	add.w		EXC_EXTWORD(%a6),%a0	# add: an + sgn_ext(disp)
16608c2ecf20Sopenharmony_ci
16618c2ecf20Sopenharmony_ci	btst		&0x7,%d1		# (reg 2 mem) or (mem 2 reg)
16628c2ecf20Sopenharmony_ci	beq.w		mem2reg
16638c2ecf20Sopenharmony_ci
16648c2ecf20Sopenharmony_ci# reg2mem: fetch dx, then write it to memory
16658c2ecf20Sopenharmony_cireg2mem:
16668c2ecf20Sopenharmony_ci	mov.w		%d1,%d0
16678c2ecf20Sopenharmony_ci	rol.w		&0x7,%d0
16688c2ecf20Sopenharmony_ci	and.w		&0x7,%d0		# extract Dx from opcode word
16698c2ecf20Sopenharmony_ci
16708c2ecf20Sopenharmony_ci	mov.l		(EXC_DREGS,%a6,%d0.w*4), %d0 # fetch dx
16718c2ecf20Sopenharmony_ci
16728c2ecf20Sopenharmony_ci	btst		&0x6,%d1		# word or long operation?
16738c2ecf20Sopenharmony_ci	beq.b		r2mwtrans
16748c2ecf20Sopenharmony_ci
16758c2ecf20Sopenharmony_ci# a0 = dst addr
16768c2ecf20Sopenharmony_ci# d0 = Dx
16778c2ecf20Sopenharmony_cir2mltrans:
16788c2ecf20Sopenharmony_ci	mov.l		%d0,%d2			# store data
16798c2ecf20Sopenharmony_ci	mov.l		%a0,%a2			# store addr
16808c2ecf20Sopenharmony_ci	rol.l		&0x8,%d2
16818c2ecf20Sopenharmony_ci	mov.l		%d2,%d0
16828c2ecf20Sopenharmony_ci
16838c2ecf20Sopenharmony_ci	bsr.l		_dmem_write_byte	# os  : write hi
16848c2ecf20Sopenharmony_ci
16858c2ecf20Sopenharmony_ci	tst.l		%d1			# dfetch error?
16868c2ecf20Sopenharmony_ci	bne.w		movp_write_err		# yes
16878c2ecf20Sopenharmony_ci
16888c2ecf20Sopenharmony_ci	add.w		&0x2,%a2		# incr addr
16898c2ecf20Sopenharmony_ci	mov.l		%a2,%a0
16908c2ecf20Sopenharmony_ci	rol.l		&0x8,%d2
16918c2ecf20Sopenharmony_ci	mov.l		%d2,%d0
16928c2ecf20Sopenharmony_ci
16938c2ecf20Sopenharmony_ci	bsr.l		_dmem_write_byte	# os  : write lo
16948c2ecf20Sopenharmony_ci
16958c2ecf20Sopenharmony_ci	tst.l		%d1			# dfetch error?
16968c2ecf20Sopenharmony_ci	bne.w		movp_write_err		# yes
16978c2ecf20Sopenharmony_ci
16988c2ecf20Sopenharmony_ci	add.w		&0x2,%a2		# incr addr
16998c2ecf20Sopenharmony_ci	mov.l		%a2,%a0
17008c2ecf20Sopenharmony_ci	rol.l		&0x8,%d2
17018c2ecf20Sopenharmony_ci	mov.l		%d2,%d0
17028c2ecf20Sopenharmony_ci
17038c2ecf20Sopenharmony_ci	bsr.l		_dmem_write_byte	# os  : write lo
17048c2ecf20Sopenharmony_ci
17058c2ecf20Sopenharmony_ci	tst.l		%d1			# dfetch error?
17068c2ecf20Sopenharmony_ci	bne.w		movp_write_err		# yes
17078c2ecf20Sopenharmony_ci
17088c2ecf20Sopenharmony_ci	add.w		&0x2,%a2		# incr addr
17098c2ecf20Sopenharmony_ci	mov.l		%a2,%a0
17108c2ecf20Sopenharmony_ci	rol.l		&0x8,%d2
17118c2ecf20Sopenharmony_ci	mov.l		%d2,%d0
17128c2ecf20Sopenharmony_ci
17138c2ecf20Sopenharmony_ci	bsr.l		_dmem_write_byte	# os  : write lo
17148c2ecf20Sopenharmony_ci
17158c2ecf20Sopenharmony_ci	tst.l		%d1			# dfetch error?
17168c2ecf20Sopenharmony_ci	bne.w		movp_write_err		# yes
17178c2ecf20Sopenharmony_ci
17188c2ecf20Sopenharmony_ci	rts
17198c2ecf20Sopenharmony_ci
17208c2ecf20Sopenharmony_ci# a0 = dst addr
17218c2ecf20Sopenharmony_ci# d0 = Dx
17228c2ecf20Sopenharmony_cir2mwtrans:
17238c2ecf20Sopenharmony_ci	mov.l		%d0,%d2			# store data
17248c2ecf20Sopenharmony_ci	mov.l		%a0,%a2			# store addr
17258c2ecf20Sopenharmony_ci	lsr.w		&0x8,%d0
17268c2ecf20Sopenharmony_ci
17278c2ecf20Sopenharmony_ci	bsr.l		_dmem_write_byte	# os  : write hi
17288c2ecf20Sopenharmony_ci
17298c2ecf20Sopenharmony_ci	tst.l		%d1			# dfetch error?
17308c2ecf20Sopenharmony_ci	bne.w		movp_write_err		# yes
17318c2ecf20Sopenharmony_ci
17328c2ecf20Sopenharmony_ci	add.w		&0x2,%a2
17338c2ecf20Sopenharmony_ci	mov.l		%a2,%a0
17348c2ecf20Sopenharmony_ci	mov.l		%d2,%d0
17358c2ecf20Sopenharmony_ci
17368c2ecf20Sopenharmony_ci	bsr.l		_dmem_write_byte	# os  : write lo
17378c2ecf20Sopenharmony_ci
17388c2ecf20Sopenharmony_ci	tst.l		%d1			# dfetch error?
17398c2ecf20Sopenharmony_ci	bne.w		movp_write_err		# yes
17408c2ecf20Sopenharmony_ci
17418c2ecf20Sopenharmony_ci	rts
17428c2ecf20Sopenharmony_ci
17438c2ecf20Sopenharmony_ci# mem2reg: read bytes from memory.
17448c2ecf20Sopenharmony_ci# determines the dest register, and then writes the bytes into it.
17458c2ecf20Sopenharmony_cimem2reg:
17468c2ecf20Sopenharmony_ci	btst		&0x6,%d1		# word or long operation?
17478c2ecf20Sopenharmony_ci	beq.b		m2rwtrans
17488c2ecf20Sopenharmony_ci
17498c2ecf20Sopenharmony_ci# a0 = dst addr
17508c2ecf20Sopenharmony_cim2rltrans:
17518c2ecf20Sopenharmony_ci	mov.l		%a0,%a2			# store addr
17528c2ecf20Sopenharmony_ci
17538c2ecf20Sopenharmony_ci	bsr.l		_dmem_read_byte		# read first byte
17548c2ecf20Sopenharmony_ci
17558c2ecf20Sopenharmony_ci	tst.l		%d1			# dfetch error?
17568c2ecf20Sopenharmony_ci	bne.w		movp_read_err		# yes
17578c2ecf20Sopenharmony_ci
17588c2ecf20Sopenharmony_ci	mov.l		%d0,%d2
17598c2ecf20Sopenharmony_ci
17608c2ecf20Sopenharmony_ci	add.w		&0x2,%a2		# incr addr by 2 bytes
17618c2ecf20Sopenharmony_ci	mov.l		%a2,%a0
17628c2ecf20Sopenharmony_ci
17638c2ecf20Sopenharmony_ci	bsr.l		_dmem_read_byte		# read second byte
17648c2ecf20Sopenharmony_ci
17658c2ecf20Sopenharmony_ci	tst.l		%d1			# dfetch error?
17668c2ecf20Sopenharmony_ci	bne.w		movp_read_err		# yes
17678c2ecf20Sopenharmony_ci
17688c2ecf20Sopenharmony_ci	lsl.w		&0x8,%d2
17698c2ecf20Sopenharmony_ci	mov.b		%d0,%d2			# append bytes
17708c2ecf20Sopenharmony_ci
17718c2ecf20Sopenharmony_ci	add.w		&0x2,%a2		# incr addr by 2 bytes
17728c2ecf20Sopenharmony_ci	mov.l		%a2,%a0
17738c2ecf20Sopenharmony_ci
17748c2ecf20Sopenharmony_ci	bsr.l		_dmem_read_byte		# read second byte
17758c2ecf20Sopenharmony_ci
17768c2ecf20Sopenharmony_ci	tst.l		%d1			# dfetch error?
17778c2ecf20Sopenharmony_ci	bne.w		movp_read_err		# yes
17788c2ecf20Sopenharmony_ci
17798c2ecf20Sopenharmony_ci	lsl.l		&0x8,%d2
17808c2ecf20Sopenharmony_ci	mov.b		%d0,%d2			# append bytes
17818c2ecf20Sopenharmony_ci
17828c2ecf20Sopenharmony_ci	add.w		&0x2,%a2		# incr addr by 2 bytes
17838c2ecf20Sopenharmony_ci	mov.l		%a2,%a0
17848c2ecf20Sopenharmony_ci
17858c2ecf20Sopenharmony_ci	bsr.l		_dmem_read_byte		# read second byte
17868c2ecf20Sopenharmony_ci
17878c2ecf20Sopenharmony_ci	tst.l		%d1			# dfetch error?
17888c2ecf20Sopenharmony_ci	bne.w		movp_read_err		# yes
17898c2ecf20Sopenharmony_ci
17908c2ecf20Sopenharmony_ci	lsl.l		&0x8,%d2
17918c2ecf20Sopenharmony_ci	mov.b		%d0,%d2			# append bytes
17928c2ecf20Sopenharmony_ci
17938c2ecf20Sopenharmony_ci	mov.b		EXC_OPWORD(%a6),%d1
17948c2ecf20Sopenharmony_ci	lsr.b		&0x1,%d1
17958c2ecf20Sopenharmony_ci	and.w		&0x7,%d1		# extract Dx from opcode word
17968c2ecf20Sopenharmony_ci
17978c2ecf20Sopenharmony_ci	mov.l		%d2,(EXC_DREGS,%a6,%d1.w*4) # store dx
17988c2ecf20Sopenharmony_ci
17998c2ecf20Sopenharmony_ci	rts
18008c2ecf20Sopenharmony_ci
18018c2ecf20Sopenharmony_ci# a0 = dst addr
18028c2ecf20Sopenharmony_cim2rwtrans:
18038c2ecf20Sopenharmony_ci	mov.l		%a0,%a2			# store addr
18048c2ecf20Sopenharmony_ci
18058c2ecf20Sopenharmony_ci	bsr.l		_dmem_read_byte		# read first byte
18068c2ecf20Sopenharmony_ci
18078c2ecf20Sopenharmony_ci	tst.l		%d1			# dfetch error?
18088c2ecf20Sopenharmony_ci	bne.w		movp_read_err		# yes
18098c2ecf20Sopenharmony_ci
18108c2ecf20Sopenharmony_ci	mov.l		%d0,%d2
18118c2ecf20Sopenharmony_ci
18128c2ecf20Sopenharmony_ci	add.w		&0x2,%a2		# incr addr by 2 bytes
18138c2ecf20Sopenharmony_ci	mov.l		%a2,%a0
18148c2ecf20Sopenharmony_ci
18158c2ecf20Sopenharmony_ci	bsr.l		_dmem_read_byte		# read second byte
18168c2ecf20Sopenharmony_ci
18178c2ecf20Sopenharmony_ci	tst.l		%d1			# dfetch error?
18188c2ecf20Sopenharmony_ci	bne.w		movp_read_err		# yes
18198c2ecf20Sopenharmony_ci
18208c2ecf20Sopenharmony_ci	lsl.w		&0x8,%d2
18218c2ecf20Sopenharmony_ci	mov.b		%d0,%d2			# append bytes
18228c2ecf20Sopenharmony_ci
18238c2ecf20Sopenharmony_ci	mov.b		EXC_OPWORD(%a6),%d1
18248c2ecf20Sopenharmony_ci	lsr.b		&0x1,%d1
18258c2ecf20Sopenharmony_ci	and.w		&0x7,%d1		# extract Dx from opcode word
18268c2ecf20Sopenharmony_ci
18278c2ecf20Sopenharmony_ci	mov.w		%d2,(EXC_DREGS+2,%a6,%d1.w*4) # store dx
18288c2ecf20Sopenharmony_ci
18298c2ecf20Sopenharmony_ci	rts
18308c2ecf20Sopenharmony_ci
18318c2ecf20Sopenharmony_ci# if dmem_{read,write}_byte() returns a fail message in d1, the package
18328c2ecf20Sopenharmony_ci# must create an access error frame. here, we pass a skeleton fslw
18338c2ecf20Sopenharmony_ci# and the failing address to the routine that creates the new frame.
18348c2ecf20Sopenharmony_ci# FSLW:
18358c2ecf20Sopenharmony_ci#	write = true
18368c2ecf20Sopenharmony_ci#	size = byte
18378c2ecf20Sopenharmony_ci#	TM = data
18388c2ecf20Sopenharmony_ci#	software emulation error = true
18398c2ecf20Sopenharmony_cimovp_write_err:
18408c2ecf20Sopenharmony_ci	mov.l		%a2,%a0			# pass failing address
18418c2ecf20Sopenharmony_ci	mov.l		&0x00a10001,%d0		# pass fslw
18428c2ecf20Sopenharmony_ci	bra.l		isp_dacc
18438c2ecf20Sopenharmony_ci
18448c2ecf20Sopenharmony_ci# FSLW:
18458c2ecf20Sopenharmony_ci#	read = true
18468c2ecf20Sopenharmony_ci#	size = byte
18478c2ecf20Sopenharmony_ci#	TM = data
18488c2ecf20Sopenharmony_ci#	software emulation error = true
18498c2ecf20Sopenharmony_cimovp_read_err:
18508c2ecf20Sopenharmony_ci	mov.l		%a2,%a0			# pass failing address
18518c2ecf20Sopenharmony_ci	mov.l		&0x01210001,%d0		# pass fslw
18528c2ecf20Sopenharmony_ci	bra.l		isp_dacc
18538c2ecf20Sopenharmony_ci
18548c2ecf20Sopenharmony_ci#########################################################################
18558c2ecf20Sopenharmony_ci# XDEF ****************************************************************	#
18568c2ecf20Sopenharmony_ci#	_chk2_cmp2(): routine to emulate chk2/cmp2 instructions		#
18578c2ecf20Sopenharmony_ci#									#
18588c2ecf20Sopenharmony_ci# XREF ****************************************************************	#
18598c2ecf20Sopenharmony_ci#	_calc_ea(): calculate effective address				#
18608c2ecf20Sopenharmony_ci#	_dmem_read_long(): read operands				#
18618c2ecf20Sopenharmony_ci#	_dmem_read_word(): read operands				#
18628c2ecf20Sopenharmony_ci#	isp_dacc(): handle data access error exception			#
18638c2ecf20Sopenharmony_ci#									#
18648c2ecf20Sopenharmony_ci# INPUT ***************************************************************	#
18658c2ecf20Sopenharmony_ci#	none								#
18668c2ecf20Sopenharmony_ci#									#
18678c2ecf20Sopenharmony_ci# OUTPUT **************************************************************	#
18688c2ecf20Sopenharmony_ci#	If exiting through isp_dacc...					#
18698c2ecf20Sopenharmony_ci#		a0 = failing address					#
18708c2ecf20Sopenharmony_ci#		d0 = FSLW						#
18718c2ecf20Sopenharmony_ci#	else								#
18728c2ecf20Sopenharmony_ci#		none							#
18738c2ecf20Sopenharmony_ci#									#
18748c2ecf20Sopenharmony_ci# ALGORITHM ***********************************************************	#
18758c2ecf20Sopenharmony_ci#	First, calculate the effective address, then fetch the byte,	#
18768c2ecf20Sopenharmony_ci# word, or longword sized operands. Then, in the interest of		#
18778c2ecf20Sopenharmony_ci# simplicity, all operands are converted to longword size whether the	#
18788c2ecf20Sopenharmony_ci# operation is byte, word, or long. The bounds are sign extended	#
18798c2ecf20Sopenharmony_ci# accordingly. If Rn is a data register, Rn is also sign extended. If	#
18808c2ecf20Sopenharmony_ci# Rn is an address register, it need not be sign extended since the	#
18818c2ecf20Sopenharmony_ci# full register is always used.						#
18828c2ecf20Sopenharmony_ci#	The comparisons are made and the condition codes calculated.	#
18838c2ecf20Sopenharmony_ci# If the instruction is chk2 and the Rn value is out-of-bounds, set	#
18848c2ecf20Sopenharmony_ci# the ichk_flg in SPCOND_FLG.						#
18858c2ecf20Sopenharmony_ci#	If the memory fetch returns a failing value, pass the failing	#
18868c2ecf20Sopenharmony_ci# address and FSLW to the isp_dacc() routine.				#
18878c2ecf20Sopenharmony_ci#									#
18888c2ecf20Sopenharmony_ci#########################################################################
18898c2ecf20Sopenharmony_ci
18908c2ecf20Sopenharmony_ci	global		_chk2_cmp2
18918c2ecf20Sopenharmony_ci_chk2_cmp2:
18928c2ecf20Sopenharmony_ci
18938c2ecf20Sopenharmony_ci# passing size parameter doesn't matter since chk2 & cmp2 can't do
18948c2ecf20Sopenharmony_ci# either predecrement, postincrement, or immediate.
18958c2ecf20Sopenharmony_ci	bsr.l		_calc_ea		# calculate <ea>
18968c2ecf20Sopenharmony_ci
18978c2ecf20Sopenharmony_ci	mov.b		EXC_EXTWORD(%a6), %d0	# fetch hi extension word
18988c2ecf20Sopenharmony_ci	rol.b		&0x4, %d0		# rotate reg bits into lo
18998c2ecf20Sopenharmony_ci	and.w		&0xf, %d0		# extract reg bits
19008c2ecf20Sopenharmony_ci
19018c2ecf20Sopenharmony_ci	mov.l		(EXC_DREGS,%a6,%d0.w*4), %d2 # get regval
19028c2ecf20Sopenharmony_ci
19038c2ecf20Sopenharmony_ci	cmpi.b		EXC_OPWORD(%a6), &0x2	# what size is operation?
19048c2ecf20Sopenharmony_ci	blt.b		chk2_cmp2_byte		# size == byte
19058c2ecf20Sopenharmony_ci	beq.b		chk2_cmp2_word		# size == word
19068c2ecf20Sopenharmony_ci
19078c2ecf20Sopenharmony_ci# the bounds are longword size. call routine to read the lower
19088c2ecf20Sopenharmony_ci# bound into d0 and the higher bound into d1.
19098c2ecf20Sopenharmony_cichk2_cmp2_long:
19108c2ecf20Sopenharmony_ci	mov.l		%a0,%a2			# save copy of <ea>
19118c2ecf20Sopenharmony_ci	bsr.l		_dmem_read_long		# fetch long lower bound
19128c2ecf20Sopenharmony_ci
19138c2ecf20Sopenharmony_ci	tst.l		%d1			# dfetch error?
19148c2ecf20Sopenharmony_ci	bne.w		chk2_cmp2_err_l		# yes
19158c2ecf20Sopenharmony_ci
19168c2ecf20Sopenharmony_ci	mov.l		%d0,%d3			# save long lower bound
19178c2ecf20Sopenharmony_ci	addq.l		&0x4,%a2
19188c2ecf20Sopenharmony_ci	mov.l		%a2,%a0			# pass <ea> of long upper bound
19198c2ecf20Sopenharmony_ci	bsr.l		_dmem_read_long		# fetch long upper bound
19208c2ecf20Sopenharmony_ci
19218c2ecf20Sopenharmony_ci	tst.l		%d1			# dfetch error?
19228c2ecf20Sopenharmony_ci	bne.w		chk2_cmp2_err_l		# yes
19238c2ecf20Sopenharmony_ci
19248c2ecf20Sopenharmony_ci	mov.l		%d0,%d1			# long upper bound in d1
19258c2ecf20Sopenharmony_ci	mov.l		%d3,%d0			# long lower bound in d0
19268c2ecf20Sopenharmony_ci	bra.w		chk2_cmp2_compare	# go do the compare emulation
19278c2ecf20Sopenharmony_ci
19288c2ecf20Sopenharmony_ci# the bounds are word size. fetch them in one subroutine call by
19298c2ecf20Sopenharmony_ci# reading a longword. sign extend both. if it's a data operation,
19308c2ecf20Sopenharmony_ci# sign extend Rn to long, also.
19318c2ecf20Sopenharmony_cichk2_cmp2_word:
19328c2ecf20Sopenharmony_ci	mov.l		%a0,%a2
19338c2ecf20Sopenharmony_ci	bsr.l		_dmem_read_long		# fetch 2 word bounds
19348c2ecf20Sopenharmony_ci
19358c2ecf20Sopenharmony_ci	tst.l		%d1			# dfetch error?
19368c2ecf20Sopenharmony_ci	bne.w		chk2_cmp2_err_l		# yes
19378c2ecf20Sopenharmony_ci
19388c2ecf20Sopenharmony_ci	mov.w		%d0, %d1		# place hi in %d1
19398c2ecf20Sopenharmony_ci	swap		%d0			# place lo in %d0
19408c2ecf20Sopenharmony_ci
19418c2ecf20Sopenharmony_ci	ext.l		%d0			# sign extend lo bnd
19428c2ecf20Sopenharmony_ci	ext.l		%d1			# sign extend hi bnd
19438c2ecf20Sopenharmony_ci
19448c2ecf20Sopenharmony_ci	btst		&0x7, EXC_EXTWORD(%a6)	# address compare?
19458c2ecf20Sopenharmony_ci	bne.w		chk2_cmp2_compare	# yes; don't sign extend
19468c2ecf20Sopenharmony_ci
19478c2ecf20Sopenharmony_ci# operation is a data register compare.
19488c2ecf20Sopenharmony_ci# sign extend word to long so we can do simple longword compares.
19498c2ecf20Sopenharmony_ci	ext.l		%d2			# sign extend data word
19508c2ecf20Sopenharmony_ci	bra.w		chk2_cmp2_compare	# go emulate compare
19518c2ecf20Sopenharmony_ci
19528c2ecf20Sopenharmony_ci# the bounds are byte size. fetch them in one subroutine call by
19538c2ecf20Sopenharmony_ci# reading a word. sign extend both. if it's a data operation,
19548c2ecf20Sopenharmony_ci# sign extend Rn to long, also.
19558c2ecf20Sopenharmony_cichk2_cmp2_byte:
19568c2ecf20Sopenharmony_ci	mov.l		%a0,%a2
19578c2ecf20Sopenharmony_ci	bsr.l		_dmem_read_word		# fetch 2 byte bounds
19588c2ecf20Sopenharmony_ci
19598c2ecf20Sopenharmony_ci	tst.l		%d1			# dfetch error?
19608c2ecf20Sopenharmony_ci	bne.w		chk2_cmp2_err_w		# yes
19618c2ecf20Sopenharmony_ci
19628c2ecf20Sopenharmony_ci	mov.b		%d0, %d1		# place hi in %d1
19638c2ecf20Sopenharmony_ci	lsr.w		&0x8, %d0		# place lo in %d0
19648c2ecf20Sopenharmony_ci
19658c2ecf20Sopenharmony_ci	extb.l		%d0			# sign extend lo bnd
19668c2ecf20Sopenharmony_ci	extb.l		%d1			# sign extend hi bnd
19678c2ecf20Sopenharmony_ci
19688c2ecf20Sopenharmony_ci	btst		&0x7, EXC_EXTWORD(%a6)	# address compare?
19698c2ecf20Sopenharmony_ci	bne.b		chk2_cmp2_compare	# yes; don't sign extend
19708c2ecf20Sopenharmony_ci
19718c2ecf20Sopenharmony_ci# operation is a data register compare.
19728c2ecf20Sopenharmony_ci# sign extend byte to long so we can do simple longword compares.
19738c2ecf20Sopenharmony_ci	extb.l		%d2			# sign extend data byte
19748c2ecf20Sopenharmony_ci
19758c2ecf20Sopenharmony_ci#
19768c2ecf20Sopenharmony_ci# To set the ccodes correctly:
19778c2ecf20Sopenharmony_ci#	(1) save 'Z' bit from (Rn - lo)
19788c2ecf20Sopenharmony_ci#	(2) save 'Z' and 'N' bits from ((hi - lo) - (Rn - hi))
19798c2ecf20Sopenharmony_ci#	(3) keep 'X', 'N', and 'V' from before instruction
19808c2ecf20Sopenharmony_ci#	(4) combine ccodes
19818c2ecf20Sopenharmony_ci#
19828c2ecf20Sopenharmony_cichk2_cmp2_compare:
19838c2ecf20Sopenharmony_ci	sub.l		%d0, %d2		# (Rn - lo)
19848c2ecf20Sopenharmony_ci	mov.w		%cc, %d3		# fetch resulting ccodes
19858c2ecf20Sopenharmony_ci	andi.b		&0x4, %d3		# keep 'Z' bit
19868c2ecf20Sopenharmony_ci	sub.l		%d0, %d1		# (hi - lo)
19878c2ecf20Sopenharmony_ci	cmp.l		%d1,%d2			# ((hi - lo) - (Rn - hi))
19888c2ecf20Sopenharmony_ci
19898c2ecf20Sopenharmony_ci	mov.w		%cc, %d4		# fetch resulting ccodes
19908c2ecf20Sopenharmony_ci	or.b		%d4, %d3		# combine w/ earlier ccodes
19918c2ecf20Sopenharmony_ci	andi.b		&0x5, %d3		# keep 'Z' and 'N'
19928c2ecf20Sopenharmony_ci
19938c2ecf20Sopenharmony_ci	mov.w		EXC_CC(%a6), %d4	# fetch old ccodes
19948c2ecf20Sopenharmony_ci	andi.b		&0x1a, %d4		# keep 'X','N','V' bits
19958c2ecf20Sopenharmony_ci	or.b		%d3, %d4		# insert new ccodes
19968c2ecf20Sopenharmony_ci	mov.w		%d4, EXC_CC(%a6)	# save new ccodes
19978c2ecf20Sopenharmony_ci
19988c2ecf20Sopenharmony_ci	btst		&0x3, EXC_EXTWORD(%a6)	# separate chk2,cmp2
19998c2ecf20Sopenharmony_ci	bne.b		chk2_finish		# it's a chk2
20008c2ecf20Sopenharmony_ci
20018c2ecf20Sopenharmony_ci	rts
20028c2ecf20Sopenharmony_ci
20038c2ecf20Sopenharmony_ci# this code handles the only difference between chk2 and cmp2. chk2 would
20048c2ecf20Sopenharmony_ci# have trapped out if the value was out of bounds. we check this by seeing
20058c2ecf20Sopenharmony_ci# if the 'N' bit was set by the operation.
20068c2ecf20Sopenharmony_cichk2_finish:
20078c2ecf20Sopenharmony_ci	btst		&0x0, %d4		# is 'N' bit set?
20088c2ecf20Sopenharmony_ci	bne.b		chk2_trap		# yes;chk2 should trap
20098c2ecf20Sopenharmony_ci	rts
20108c2ecf20Sopenharmony_cichk2_trap:
20118c2ecf20Sopenharmony_ci	mov.b		&ichk_flg,SPCOND_FLG(%a6) # set "special case" flag
20128c2ecf20Sopenharmony_ci	rts
20138c2ecf20Sopenharmony_ci
20148c2ecf20Sopenharmony_ci# if dmem_read_{long,word}() returns a fail message in d1, the package
20158c2ecf20Sopenharmony_ci# must create an access error frame. here, we pass a skeleton fslw
20168c2ecf20Sopenharmony_ci# and the failing address to the routine that creates the new frame.
20178c2ecf20Sopenharmony_ci# FSLW:
20188c2ecf20Sopenharmony_ci#	read = true
20198c2ecf20Sopenharmony_ci#	size = longword
20208c2ecf20Sopenharmony_ci#	TM = data
20218c2ecf20Sopenharmony_ci#	software emulation error = true
20228c2ecf20Sopenharmony_cichk2_cmp2_err_l:
20238c2ecf20Sopenharmony_ci	mov.l		%a2,%a0			# pass failing address
20248c2ecf20Sopenharmony_ci	mov.l		&0x01010001,%d0		# pass fslw
20258c2ecf20Sopenharmony_ci	bra.l		isp_dacc
20268c2ecf20Sopenharmony_ci
20278c2ecf20Sopenharmony_ci# FSLW:
20288c2ecf20Sopenharmony_ci#	read = true
20298c2ecf20Sopenharmony_ci#	size = word
20308c2ecf20Sopenharmony_ci#	TM = data
20318c2ecf20Sopenharmony_ci#	software emulation error = true
20328c2ecf20Sopenharmony_cichk2_cmp2_err_w:
20338c2ecf20Sopenharmony_ci	mov.l		%a2,%a0			# pass failing address
20348c2ecf20Sopenharmony_ci	mov.l		&0x01410001,%d0		# pass fslw
20358c2ecf20Sopenharmony_ci	bra.l		isp_dacc
20368c2ecf20Sopenharmony_ci
20378c2ecf20Sopenharmony_ci#########################################################################
20388c2ecf20Sopenharmony_ci# XDEF ****************************************************************	#
20398c2ecf20Sopenharmony_ci#	_div64(): routine to emulate div{u,s}.l <ea>,Dr:Dq		#
20408c2ecf20Sopenharmony_ci#							64/32->32r:32q	#
20418c2ecf20Sopenharmony_ci#									#
20428c2ecf20Sopenharmony_ci# XREF ****************************************************************	#
20438c2ecf20Sopenharmony_ci#	_calc_ea() - calculate effective address			#
20448c2ecf20Sopenharmony_ci#	isp_iacc() - handle instruction access error exception		#
20458c2ecf20Sopenharmony_ci#	isp_dacc() - handle data access error exception			#
20468c2ecf20Sopenharmony_ci#	isp_restore() - restore An on access error w/ -() or ()+	#
20478c2ecf20Sopenharmony_ci#									#
20488c2ecf20Sopenharmony_ci# INPUT ***************************************************************	#
20498c2ecf20Sopenharmony_ci#	none								#
20508c2ecf20Sopenharmony_ci#									#
20518c2ecf20Sopenharmony_ci# OUTPUT **************************************************************	#
20528c2ecf20Sopenharmony_ci#	If exiting through isp_dacc...					#
20538c2ecf20Sopenharmony_ci#		a0 = failing address					#
20548c2ecf20Sopenharmony_ci#		d0 = FSLW						#
20558c2ecf20Sopenharmony_ci#	else								#
20568c2ecf20Sopenharmony_ci#		none							#
20578c2ecf20Sopenharmony_ci#									#
20588c2ecf20Sopenharmony_ci# ALGORITHM ***********************************************************	#
20598c2ecf20Sopenharmony_ci#	First, decode the operand location. If it's in Dn, fetch from	#
20608c2ecf20Sopenharmony_ci# the stack. If it's in memory, use _calc_ea() to calculate the		#
20618c2ecf20Sopenharmony_ci# effective address. Use _dmem_read_long() to fetch at that address.	#
20628c2ecf20Sopenharmony_ci# Unless the operand is immediate data. Then use _imem_read_long().	#
20638c2ecf20Sopenharmony_ci# Send failures to isp_dacc() or isp_iacc() as appropriate.		#
20648c2ecf20Sopenharmony_ci#	If the operands are signed, make them unsigned and save	the	#
20658c2ecf20Sopenharmony_ci# sign info for later. Separate out special cases like divide-by-zero	#
20668c2ecf20Sopenharmony_ci# or 32-bit divides if possible. Else, use a special math algorithm	#
20678c2ecf20Sopenharmony_ci# to calculate the result.						#
20688c2ecf20Sopenharmony_ci#	Restore sign info if signed instruction. Set the condition	#
20698c2ecf20Sopenharmony_ci# codes. Set idbyz_flg in SPCOND_FLG if divisor was zero. Store the	#
20708c2ecf20Sopenharmony_ci# quotient and remainder in the appropriate data registers on the stack.#
20718c2ecf20Sopenharmony_ci#									#
20728c2ecf20Sopenharmony_ci#########################################################################
20738c2ecf20Sopenharmony_ci
20748c2ecf20Sopenharmony_ciset	NDIVISOR,	EXC_TEMP+0x0
20758c2ecf20Sopenharmony_ciset	NDIVIDEND,	EXC_TEMP+0x1
20768c2ecf20Sopenharmony_ciset	NDRSAVE,	EXC_TEMP+0x2
20778c2ecf20Sopenharmony_ciset	NDQSAVE,	EXC_TEMP+0x4
20788c2ecf20Sopenharmony_ciset	DDSECOND,	EXC_TEMP+0x6
20798c2ecf20Sopenharmony_ciset	DDQUOTIENT,	EXC_TEMP+0x8
20808c2ecf20Sopenharmony_ciset	DDNORMAL,	EXC_TEMP+0xc
20818c2ecf20Sopenharmony_ci
20828c2ecf20Sopenharmony_ci	global		_div64
20838c2ecf20Sopenharmony_ci#############
20848c2ecf20Sopenharmony_ci# div(u,s)l #
20858c2ecf20Sopenharmony_ci#############
20868c2ecf20Sopenharmony_ci_div64:
20878c2ecf20Sopenharmony_ci	mov.b		EXC_OPWORD+1(%a6), %d0
20888c2ecf20Sopenharmony_ci	andi.b		&0x38, %d0		# extract src mode
20898c2ecf20Sopenharmony_ci
20908c2ecf20Sopenharmony_ci	bne.w		dcontrolmodel_s		# %dn dest or control mode?
20918c2ecf20Sopenharmony_ci
20928c2ecf20Sopenharmony_ci	mov.b		EXC_OPWORD+1(%a6), %d0	# extract Dn from opcode
20938c2ecf20Sopenharmony_ci	andi.w		&0x7, %d0
20948c2ecf20Sopenharmony_ci	mov.l		(EXC_DREGS,%a6,%d0.w*4), %d7 # fetch divisor from register
20958c2ecf20Sopenharmony_ci
20968c2ecf20Sopenharmony_cidgotsrcl:
20978c2ecf20Sopenharmony_ci	beq.w		div64eq0		# divisor is = 0!!!
20988c2ecf20Sopenharmony_ci
20998c2ecf20Sopenharmony_ci	mov.b		EXC_EXTWORD+1(%a6), %d0	# extract Dr from extword
21008c2ecf20Sopenharmony_ci	mov.b		EXC_EXTWORD(%a6), %d1	# extract Dq from extword
21018c2ecf20Sopenharmony_ci	and.w		&0x7, %d0
21028c2ecf20Sopenharmony_ci	lsr.b		&0x4, %d1
21038c2ecf20Sopenharmony_ci	and.w		&0x7, %d1
21048c2ecf20Sopenharmony_ci	mov.w		%d0, NDRSAVE(%a6)	# save Dr for later
21058c2ecf20Sopenharmony_ci	mov.w		%d1, NDQSAVE(%a6)	# save Dq for later
21068c2ecf20Sopenharmony_ci
21078c2ecf20Sopenharmony_ci# fetch %dr and %dq directly off stack since all regs are saved there
21088c2ecf20Sopenharmony_ci	mov.l		(EXC_DREGS,%a6,%d0.w*4), %d5 # get dividend hi
21098c2ecf20Sopenharmony_ci	mov.l		(EXC_DREGS,%a6,%d1.w*4), %d6 # get dividend lo
21108c2ecf20Sopenharmony_ci
21118c2ecf20Sopenharmony_ci# separate signed and unsigned divide
21128c2ecf20Sopenharmony_ci	btst		&0x3, EXC_EXTWORD(%a6)	# signed or unsigned?
21138c2ecf20Sopenharmony_ci	beq.b		dspecialcases		# use positive divide
21148c2ecf20Sopenharmony_ci
21158c2ecf20Sopenharmony_ci# save the sign of the divisor
21168c2ecf20Sopenharmony_ci# make divisor unsigned if it's negative
21178c2ecf20Sopenharmony_ci	tst.l		%d7			# chk sign of divisor
21188c2ecf20Sopenharmony_ci	slt		NDIVISOR(%a6)		# save sign of divisor
21198c2ecf20Sopenharmony_ci	bpl.b		dsgndividend
21208c2ecf20Sopenharmony_ci	neg.l		%d7			# complement negative divisor
21218c2ecf20Sopenharmony_ci
21228c2ecf20Sopenharmony_ci# save the sign of the dividend
21238c2ecf20Sopenharmony_ci# make dividend unsigned if it's negative
21248c2ecf20Sopenharmony_cidsgndividend:
21258c2ecf20Sopenharmony_ci	tst.l		%d5			# chk sign of hi(dividend)
21268c2ecf20Sopenharmony_ci	slt		NDIVIDEND(%a6)		# save sign of dividend
21278c2ecf20Sopenharmony_ci	bpl.b		dspecialcases
21288c2ecf20Sopenharmony_ci
21298c2ecf20Sopenharmony_ci	mov.w		&0x0, %cc		# clear 'X' cc bit
21308c2ecf20Sopenharmony_ci	negx.l		%d6			# complement signed dividend
21318c2ecf20Sopenharmony_ci	negx.l		%d5
21328c2ecf20Sopenharmony_ci
21338c2ecf20Sopenharmony_ci# extract some special cases:
21348c2ecf20Sopenharmony_ci#	- is (dividend == 0) ?
21358c2ecf20Sopenharmony_ci#	- is (hi(dividend) == 0 && (divisor <= lo(dividend))) ? (32-bit div)
21368c2ecf20Sopenharmony_cidspecialcases:
21378c2ecf20Sopenharmony_ci	tst.l		%d5			# is (hi(dividend) == 0)
21388c2ecf20Sopenharmony_ci	bne.b		dnormaldivide		# no, so try it the long way
21398c2ecf20Sopenharmony_ci
21408c2ecf20Sopenharmony_ci	tst.l		%d6			# is (lo(dividend) == 0), too
21418c2ecf20Sopenharmony_ci	beq.w		ddone			# yes, so (dividend == 0)
21428c2ecf20Sopenharmony_ci
21438c2ecf20Sopenharmony_ci	cmp.l		%d7,%d6			# is (divisor <= lo(dividend))
21448c2ecf20Sopenharmony_ci	bls.b		d32bitdivide		# yes, so use 32 bit divide
21458c2ecf20Sopenharmony_ci
21468c2ecf20Sopenharmony_ci	exg		%d5,%d6			# q = 0, r = dividend
21478c2ecf20Sopenharmony_ci	bra.w		divfinish		# can't divide, we're done.
21488c2ecf20Sopenharmony_ci
21498c2ecf20Sopenharmony_cid32bitdivide:
21508c2ecf20Sopenharmony_ci	tdivu.l		%d7, %d5:%d6		# it's only a 32/32 bit div!
21518c2ecf20Sopenharmony_ci
21528c2ecf20Sopenharmony_ci	bra.b		divfinish
21538c2ecf20Sopenharmony_ci
21548c2ecf20Sopenharmony_cidnormaldivide:
21558c2ecf20Sopenharmony_ci# last special case:
21568c2ecf20Sopenharmony_ci#	- is hi(dividend) >= divisor ? if yes, then overflow
21578c2ecf20Sopenharmony_ci	cmp.l		%d7,%d5
21588c2ecf20Sopenharmony_ci	bls.b		ddovf			# answer won't fit in 32 bits
21598c2ecf20Sopenharmony_ci
21608c2ecf20Sopenharmony_ci# perform the divide algorithm:
21618c2ecf20Sopenharmony_ci	bsr.l		dclassical		# do int divide
21628c2ecf20Sopenharmony_ci
21638c2ecf20Sopenharmony_ci# separate into signed and unsigned finishes.
21648c2ecf20Sopenharmony_cidivfinish:
21658c2ecf20Sopenharmony_ci	btst		&0x3, EXC_EXTWORD(%a6)	# do divs, divu separately
21668c2ecf20Sopenharmony_ci	beq.b		ddone			# divu has no processing!!!
21678c2ecf20Sopenharmony_ci
21688c2ecf20Sopenharmony_ci# it was a divs.l, so ccode setting is a little more complicated...
21698c2ecf20Sopenharmony_ci	tst.b		NDIVIDEND(%a6)		# remainder has same sign
21708c2ecf20Sopenharmony_ci	beq.b		dcc			# as dividend.
21718c2ecf20Sopenharmony_ci	neg.l		%d5			# sgn(rem) = sgn(dividend)
21728c2ecf20Sopenharmony_cidcc:
21738c2ecf20Sopenharmony_ci	mov.b		NDIVISOR(%a6), %d0
21748c2ecf20Sopenharmony_ci	eor.b		%d0, NDIVIDEND(%a6)	# chk if quotient is negative
21758c2ecf20Sopenharmony_ci	beq.b		dqpos			# branch to quot positive
21768c2ecf20Sopenharmony_ci
21778c2ecf20Sopenharmony_ci# 0x80000000 is the largest number representable as a 32-bit negative
21788c2ecf20Sopenharmony_ci# number. the negative of 0x80000000 is 0x80000000.
21798c2ecf20Sopenharmony_ci	cmpi.l		%d6, &0x80000000	# will (-quot) fit in 32 bits?
21808c2ecf20Sopenharmony_ci	bhi.b		ddovf
21818c2ecf20Sopenharmony_ci
21828c2ecf20Sopenharmony_ci	neg.l		%d6			# make (-quot) 2's comp
21838c2ecf20Sopenharmony_ci
21848c2ecf20Sopenharmony_ci	bra.b		ddone
21858c2ecf20Sopenharmony_ci
21868c2ecf20Sopenharmony_cidqpos:
21878c2ecf20Sopenharmony_ci	btst		&0x1f, %d6		# will (+quot) fit in 32 bits?
21888c2ecf20Sopenharmony_ci	bne.b		ddovf
21898c2ecf20Sopenharmony_ci
21908c2ecf20Sopenharmony_ciddone:
21918c2ecf20Sopenharmony_ci# at this point, result is normal so ccodes are set based on result.
21928c2ecf20Sopenharmony_ci	mov.w		EXC_CC(%a6), %cc
21938c2ecf20Sopenharmony_ci	tst.l		%d6			# set %ccode bits
21948c2ecf20Sopenharmony_ci	mov.w		%cc, EXC_CC(%a6)
21958c2ecf20Sopenharmony_ci
21968c2ecf20Sopenharmony_ci	mov.w		NDRSAVE(%a6), %d0	# get Dr off stack
21978c2ecf20Sopenharmony_ci	mov.w		NDQSAVE(%a6), %d1	# get Dq off stack
21988c2ecf20Sopenharmony_ci
21998c2ecf20Sopenharmony_ci# if the register numbers are the same, only the quotient gets saved.
22008c2ecf20Sopenharmony_ci# so, if we always save the quotient second, we save ourselves a cmp&beq
22018c2ecf20Sopenharmony_ci	mov.l		%d5, (EXC_DREGS,%a6,%d0.w*4) # save remainder
22028c2ecf20Sopenharmony_ci	mov.l		%d6, (EXC_DREGS,%a6,%d1.w*4) # save quotient
22038c2ecf20Sopenharmony_ci
22048c2ecf20Sopenharmony_ci	rts
22058c2ecf20Sopenharmony_ci
22068c2ecf20Sopenharmony_ciddovf:
22078c2ecf20Sopenharmony_ci	bset		&0x1, EXC_CC+1(%a6)	# 'V' set on overflow
22088c2ecf20Sopenharmony_ci	bclr		&0x0, EXC_CC+1(%a6)	# 'C' cleared on overflow
22098c2ecf20Sopenharmony_ci
22108c2ecf20Sopenharmony_ci	rts
22118c2ecf20Sopenharmony_ci
22128c2ecf20Sopenharmony_cidiv64eq0:
22138c2ecf20Sopenharmony_ci	andi.b		&0x1e, EXC_CC+1(%a6)	# clear 'C' bit on divbyzero
22148c2ecf20Sopenharmony_ci	ori.b		&idbyz_flg,SPCOND_FLG(%a6) # set "special case" flag
22158c2ecf20Sopenharmony_ci	rts
22168c2ecf20Sopenharmony_ci
22178c2ecf20Sopenharmony_ci###########################################################################
22188c2ecf20Sopenharmony_ci#########################################################################
22198c2ecf20Sopenharmony_ci# This routine uses the 'classical' Algorithm D from Donald Knuth's	#
22208c2ecf20Sopenharmony_ci# Art of Computer Programming, vol II, Seminumerical Algorithms.	#
22218c2ecf20Sopenharmony_ci# For this implementation b=2**16, and the target is U1U2U3U4/V1V2,	#
22228c2ecf20Sopenharmony_ci# where U,V are words of the quadword dividend and longword divisor,	#
22238c2ecf20Sopenharmony_ci# and U1, V1 are the most significant words.				#
22248c2ecf20Sopenharmony_ci#									#
22258c2ecf20Sopenharmony_ci# The most sig. longword of the 64 bit dividend must be in %d5, least	#
22268c2ecf20Sopenharmony_ci# in %d6. The divisor must be in the variable ddivisor, and the		#
22278c2ecf20Sopenharmony_ci# signed/unsigned flag ddusign must be set (0=unsigned,1=signed).	#
22288c2ecf20Sopenharmony_ci# The quotient is returned in %d6, remainder in %d5, unless the		#
22298c2ecf20Sopenharmony_ci# v (overflow) bit is set in the saved %ccr. If overflow, the dividend	#
22308c2ecf20Sopenharmony_ci# is unchanged.								#
22318c2ecf20Sopenharmony_ci#########################################################################
22328c2ecf20Sopenharmony_cidclassical:
22338c2ecf20Sopenharmony_ci# if the divisor msw is 0, use simpler algorithm then the full blown
22348c2ecf20Sopenharmony_ci# one at ddknuth:
22358c2ecf20Sopenharmony_ci
22368c2ecf20Sopenharmony_ci	cmpi.l		%d7, &0xffff
22378c2ecf20Sopenharmony_ci	bhi.b		ddknuth			# go use D. Knuth algorithm
22388c2ecf20Sopenharmony_ci
22398c2ecf20Sopenharmony_ci# Since the divisor is only a word (and larger than the mslw of the dividend),
22408c2ecf20Sopenharmony_ci# a simpler algorithm may be used :
22418c2ecf20Sopenharmony_ci# In the general case, four quotient words would be created by
22428c2ecf20Sopenharmony_ci# dividing the divisor word into each dividend word. In this case,
22438c2ecf20Sopenharmony_ci# the first two quotient words must be zero, or overflow would occur.
22448c2ecf20Sopenharmony_ci# Since we already checked this case above, we can treat the most significant
22458c2ecf20Sopenharmony_ci# longword of the dividend as (0) remainder (see Knuth) and merely complete
22468c2ecf20Sopenharmony_ci# the last two divisions to get a quotient longword and word remainder:
22478c2ecf20Sopenharmony_ci
22488c2ecf20Sopenharmony_ci	clr.l		%d1
22498c2ecf20Sopenharmony_ci	swap		%d5			# same as r*b if previous step rqd
22508c2ecf20Sopenharmony_ci	swap		%d6			# get u3 to lsw position
22518c2ecf20Sopenharmony_ci	mov.w		%d6, %d5		# rb + u3
22528c2ecf20Sopenharmony_ci
22538c2ecf20Sopenharmony_ci	divu.w		%d7, %d5
22548c2ecf20Sopenharmony_ci
22558c2ecf20Sopenharmony_ci	mov.w		%d5, %d1		# first quotient word
22568c2ecf20Sopenharmony_ci	swap		%d6			# get u4
22578c2ecf20Sopenharmony_ci	mov.w		%d6, %d5		# rb + u4
22588c2ecf20Sopenharmony_ci
22598c2ecf20Sopenharmony_ci	divu.w		%d7, %d5
22608c2ecf20Sopenharmony_ci
22618c2ecf20Sopenharmony_ci	swap		%d1
22628c2ecf20Sopenharmony_ci	mov.w		%d5, %d1		# 2nd quotient 'digit'
22638c2ecf20Sopenharmony_ci	clr.w		%d5
22648c2ecf20Sopenharmony_ci	swap		%d5			# now remainder
22658c2ecf20Sopenharmony_ci	mov.l		%d1, %d6		# and quotient
22668c2ecf20Sopenharmony_ci
22678c2ecf20Sopenharmony_ci	rts
22688c2ecf20Sopenharmony_ci
22698c2ecf20Sopenharmony_ciddknuth:
22708c2ecf20Sopenharmony_ci# In this algorithm, the divisor is treated as a 2 digit (word) number
22718c2ecf20Sopenharmony_ci# which is divided into a 3 digit (word) dividend to get one quotient
22728c2ecf20Sopenharmony_ci# digit (word). After subtraction, the dividend is shifted and the
22738c2ecf20Sopenharmony_ci# process repeated. Before beginning, the divisor and quotient are
22748c2ecf20Sopenharmony_ci# 'normalized' so that the process of estimating the quotient digit
22758c2ecf20Sopenharmony_ci# will yield verifiably correct results..
22768c2ecf20Sopenharmony_ci
22778c2ecf20Sopenharmony_ci	clr.l		DDNORMAL(%a6)		# count of shifts for normalization
22788c2ecf20Sopenharmony_ci	clr.b		DDSECOND(%a6)		# clear flag for quotient digits
22798c2ecf20Sopenharmony_ci	clr.l		%d1			# %d1 will hold trial quotient
22808c2ecf20Sopenharmony_ciddnchk:
22818c2ecf20Sopenharmony_ci	btst		&31, %d7		# must we normalize? first word of
22828c2ecf20Sopenharmony_ci	bne.b		ddnormalized		# divisor (V1) must be >= 65536/2
22838c2ecf20Sopenharmony_ci	addq.l		&0x1, DDNORMAL(%a6)	# count normalization shifts
22848c2ecf20Sopenharmony_ci	lsl.l		&0x1, %d7		# shift the divisor
22858c2ecf20Sopenharmony_ci	lsl.l		&0x1, %d6		# shift u4,u3 with overflow to u2
22868c2ecf20Sopenharmony_ci	roxl.l		&0x1, %d5		# shift u1,u2
22878c2ecf20Sopenharmony_ci	bra.w		ddnchk
22888c2ecf20Sopenharmony_ciddnormalized:
22898c2ecf20Sopenharmony_ci
22908c2ecf20Sopenharmony_ci# Now calculate an estimate of the quotient words (msw first, then lsw).
22918c2ecf20Sopenharmony_ci# The comments use subscripts for the first quotient digit determination.
22928c2ecf20Sopenharmony_ci	mov.l		%d7, %d3		# divisor
22938c2ecf20Sopenharmony_ci	mov.l		%d5, %d2		# dividend mslw
22948c2ecf20Sopenharmony_ci	swap		%d2
22958c2ecf20Sopenharmony_ci	swap		%d3
22968c2ecf20Sopenharmony_ci	cmp.w		%d2, %d3		# V1 = U1 ?
22978c2ecf20Sopenharmony_ci	bne.b		ddqcalc1
22988c2ecf20Sopenharmony_ci	mov.w		&0xffff, %d1		# use max trial quotient word
22998c2ecf20Sopenharmony_ci	bra.b		ddadj0
23008c2ecf20Sopenharmony_ciddqcalc1:
23018c2ecf20Sopenharmony_ci	mov.l		%d5, %d1
23028c2ecf20Sopenharmony_ci
23038c2ecf20Sopenharmony_ci	divu.w		%d3, %d1		# use quotient of mslw/msw
23048c2ecf20Sopenharmony_ci
23058c2ecf20Sopenharmony_ci	andi.l		&0x0000ffff, %d1	# zero any remainder
23068c2ecf20Sopenharmony_ciddadj0:
23078c2ecf20Sopenharmony_ci
23088c2ecf20Sopenharmony_ci# now test the trial quotient and adjust. This step plus the
23098c2ecf20Sopenharmony_ci# normalization assures (according to Knuth) that the trial
23108c2ecf20Sopenharmony_ci# quotient will be at worst 1 too large.
23118c2ecf20Sopenharmony_ci	mov.l		%d6, -(%sp)
23128c2ecf20Sopenharmony_ci	clr.w		%d6			# word u3 left
23138c2ecf20Sopenharmony_ci	swap		%d6			# in lsw position
23148c2ecf20Sopenharmony_ciddadj1: mov.l		%d7, %d3
23158c2ecf20Sopenharmony_ci	mov.l		%d1, %d2
23168c2ecf20Sopenharmony_ci	mulu.w		%d7, %d2		# V2q
23178c2ecf20Sopenharmony_ci	swap		%d3
23188c2ecf20Sopenharmony_ci	mulu.w		%d1, %d3		# V1q
23198c2ecf20Sopenharmony_ci	mov.l		%d5, %d4		# U1U2
23208c2ecf20Sopenharmony_ci	sub.l		%d3, %d4		# U1U2 - V1q
23218c2ecf20Sopenharmony_ci
23228c2ecf20Sopenharmony_ci	swap		%d4
23238c2ecf20Sopenharmony_ci
23248c2ecf20Sopenharmony_ci	mov.w		%d4,%d0
23258c2ecf20Sopenharmony_ci	mov.w		%d6,%d4			# insert lower word (U3)
23268c2ecf20Sopenharmony_ci
23278c2ecf20Sopenharmony_ci	tst.w		%d0			# is upper word set?
23288c2ecf20Sopenharmony_ci	bne.w		ddadjd1
23298c2ecf20Sopenharmony_ci
23308c2ecf20Sopenharmony_ci#	add.l		%d6, %d4		# (U1U2 - V1q) + U3
23318c2ecf20Sopenharmony_ci
23328c2ecf20Sopenharmony_ci	cmp.l		%d2, %d4
23338c2ecf20Sopenharmony_ci	bls.b		ddadjd1			# is V2q > (U1U2-V1q) + U3 ?
23348c2ecf20Sopenharmony_ci	subq.l		&0x1, %d1		# yes, decrement and recheck
23358c2ecf20Sopenharmony_ci	bra.b		ddadj1
23368c2ecf20Sopenharmony_ciddadjd1:
23378c2ecf20Sopenharmony_ci# now test the word by multiplying it by the divisor (V1V2) and comparing
23388c2ecf20Sopenharmony_ci# the 3 digit (word) result with the current dividend words
23398c2ecf20Sopenharmony_ci	mov.l		%d5, -(%sp)		# save %d5 (%d6 already saved)
23408c2ecf20Sopenharmony_ci	mov.l		%d1, %d6
23418c2ecf20Sopenharmony_ci	swap		%d6			# shift answer to ms 3 words
23428c2ecf20Sopenharmony_ci	mov.l		%d7, %d5
23438c2ecf20Sopenharmony_ci	bsr.l		dmm2
23448c2ecf20Sopenharmony_ci	mov.l		%d5, %d2		# now %d2,%d3 are trial*divisor
23458c2ecf20Sopenharmony_ci	mov.l		%d6, %d3
23468c2ecf20Sopenharmony_ci	mov.l		(%sp)+, %d5		# restore dividend
23478c2ecf20Sopenharmony_ci	mov.l		(%sp)+, %d6
23488c2ecf20Sopenharmony_ci	sub.l		%d3, %d6
23498c2ecf20Sopenharmony_ci	subx.l		%d2, %d5		# subtract double precision
23508c2ecf20Sopenharmony_ci	bcc		dd2nd			# no carry, do next quotient digit
23518c2ecf20Sopenharmony_ci	subq.l		&0x1, %d1		# q is one too large
23528c2ecf20Sopenharmony_ci# need to add back divisor longword to current ms 3 digits of dividend
23538c2ecf20Sopenharmony_ci# - according to Knuth, this is done only 2 out of 65536 times for random
23548c2ecf20Sopenharmony_ci# divisor, dividend selection.
23558c2ecf20Sopenharmony_ci	clr.l		%d2
23568c2ecf20Sopenharmony_ci	mov.l		%d7, %d3
23578c2ecf20Sopenharmony_ci	swap		%d3
23588c2ecf20Sopenharmony_ci	clr.w		%d3			# %d3 now ls word of divisor
23598c2ecf20Sopenharmony_ci	add.l		%d3, %d6		# aligned with 3rd word of dividend
23608c2ecf20Sopenharmony_ci	addx.l		%d2, %d5
23618c2ecf20Sopenharmony_ci	mov.l		%d7, %d3
23628c2ecf20Sopenharmony_ci	clr.w		%d3			# %d3 now ms word of divisor
23638c2ecf20Sopenharmony_ci	swap		%d3			# aligned with 2nd word of dividend
23648c2ecf20Sopenharmony_ci	add.l		%d3, %d5
23658c2ecf20Sopenharmony_cidd2nd:
23668c2ecf20Sopenharmony_ci	tst.b		DDSECOND(%a6)		# both q words done?
23678c2ecf20Sopenharmony_ci	bne.b		ddremain
23688c2ecf20Sopenharmony_ci# first quotient digit now correct. store digit and shift the
23698c2ecf20Sopenharmony_ci# (subtracted) dividend
23708c2ecf20Sopenharmony_ci	mov.w		%d1, DDQUOTIENT(%a6)
23718c2ecf20Sopenharmony_ci	clr.l		%d1
23728c2ecf20Sopenharmony_ci	swap		%d5
23738c2ecf20Sopenharmony_ci	swap		%d6
23748c2ecf20Sopenharmony_ci	mov.w		%d6, %d5
23758c2ecf20Sopenharmony_ci	clr.w		%d6
23768c2ecf20Sopenharmony_ci	st		DDSECOND(%a6)		# second digit
23778c2ecf20Sopenharmony_ci	bra.w		ddnormalized
23788c2ecf20Sopenharmony_ciddremain:
23798c2ecf20Sopenharmony_ci# add 2nd word to quotient, get the remainder.
23808c2ecf20Sopenharmony_ci	mov.w		%d1, DDQUOTIENT+2(%a6)
23818c2ecf20Sopenharmony_ci# shift down one word/digit to renormalize remainder.
23828c2ecf20Sopenharmony_ci	mov.w		%d5, %d6
23838c2ecf20Sopenharmony_ci	swap		%d6
23848c2ecf20Sopenharmony_ci	swap		%d5
23858c2ecf20Sopenharmony_ci	mov.l		DDNORMAL(%a6), %d7	# get norm shift count
23868c2ecf20Sopenharmony_ci	beq.b		ddrn
23878c2ecf20Sopenharmony_ci	subq.l		&0x1, %d7		# set for loop count
23888c2ecf20Sopenharmony_ciddnlp:
23898c2ecf20Sopenharmony_ci	lsr.l		&0x1, %d5		# shift into %d6
23908c2ecf20Sopenharmony_ci	roxr.l		&0x1, %d6
23918c2ecf20Sopenharmony_ci	dbf		%d7, ddnlp
23928c2ecf20Sopenharmony_ciddrn:
23938c2ecf20Sopenharmony_ci	mov.l		%d6, %d5		# remainder
23948c2ecf20Sopenharmony_ci	mov.l		DDQUOTIENT(%a6), %d6	# quotient
23958c2ecf20Sopenharmony_ci
23968c2ecf20Sopenharmony_ci	rts
23978c2ecf20Sopenharmony_cidmm2:
23988c2ecf20Sopenharmony_ci# factors for the 32X32->64 multiplication are in %d5 and %d6.
23998c2ecf20Sopenharmony_ci# returns 64 bit result in %d5 (hi) %d6(lo).
24008c2ecf20Sopenharmony_ci# destroys %d2,%d3,%d4.
24018c2ecf20Sopenharmony_ci
24028c2ecf20Sopenharmony_ci# multiply hi,lo words of each factor to get 4 intermediate products
24038c2ecf20Sopenharmony_ci	mov.l		%d6, %d2
24048c2ecf20Sopenharmony_ci	mov.l		%d6, %d3
24058c2ecf20Sopenharmony_ci	mov.l		%d5, %d4
24068c2ecf20Sopenharmony_ci	swap		%d3
24078c2ecf20Sopenharmony_ci	swap		%d4
24088c2ecf20Sopenharmony_ci	mulu.w		%d5, %d6		# %d6 <- lsw*lsw
24098c2ecf20Sopenharmony_ci	mulu.w		%d3, %d5		# %d5 <- msw-dest*lsw-source
24108c2ecf20Sopenharmony_ci	mulu.w		%d4, %d2		# %d2 <- msw-source*lsw-dest
24118c2ecf20Sopenharmony_ci	mulu.w		%d4, %d3		# %d3 <- msw*msw
24128c2ecf20Sopenharmony_ci# now use swap and addx to consolidate to two longwords
24138c2ecf20Sopenharmony_ci	clr.l		%d4
24148c2ecf20Sopenharmony_ci	swap		%d6
24158c2ecf20Sopenharmony_ci	add.w		%d5, %d6		# add msw of l*l to lsw of m*l product
24168c2ecf20Sopenharmony_ci	addx.w		%d4, %d3		# add any carry to m*m product
24178c2ecf20Sopenharmony_ci	add.w		%d2, %d6		# add in lsw of other m*l product
24188c2ecf20Sopenharmony_ci	addx.w		%d4, %d3		# add any carry to m*m product
24198c2ecf20Sopenharmony_ci	swap		%d6			# %d6 is low 32 bits of final product
24208c2ecf20Sopenharmony_ci	clr.w		%d5
24218c2ecf20Sopenharmony_ci	clr.w		%d2			# lsw of two mixed products used,
24228c2ecf20Sopenharmony_ci	swap		%d5			# now use msws of longwords
24238c2ecf20Sopenharmony_ci	swap		%d2
24248c2ecf20Sopenharmony_ci	add.l		%d2, %d5
24258c2ecf20Sopenharmony_ci	add.l		%d3, %d5		# %d5 now ms 32 bits of final product
24268c2ecf20Sopenharmony_ci	rts
24278c2ecf20Sopenharmony_ci
24288c2ecf20Sopenharmony_ci##########
24298c2ecf20Sopenharmony_cidcontrolmodel_s:
24308c2ecf20Sopenharmony_ci	movq.l		&LONG,%d0
24318c2ecf20Sopenharmony_ci	bsr.l		_calc_ea		# calc <ea>
24328c2ecf20Sopenharmony_ci
24338c2ecf20Sopenharmony_ci	cmpi.b		SPCOND_FLG(%a6),&immed_flg # immediate addressing mode?
24348c2ecf20Sopenharmony_ci	beq.b		dimmed			# yes
24358c2ecf20Sopenharmony_ci
24368c2ecf20Sopenharmony_ci	mov.l		%a0,%a2
24378c2ecf20Sopenharmony_ci	bsr.l		_dmem_read_long		# fetch divisor from <ea>
24388c2ecf20Sopenharmony_ci
24398c2ecf20Sopenharmony_ci	tst.l		%d1			# dfetch error?
24408c2ecf20Sopenharmony_ci	bne.b		div64_err		# yes
24418c2ecf20Sopenharmony_ci
24428c2ecf20Sopenharmony_ci	mov.l		%d0, %d7
24438c2ecf20Sopenharmony_ci	bra.w		dgotsrcl
24448c2ecf20Sopenharmony_ci
24458c2ecf20Sopenharmony_ci# we have to split out immediate data here because it must be read using
24468c2ecf20Sopenharmony_ci# imem_read() instead of dmem_read(). this becomes especially important
24478c2ecf20Sopenharmony_ci# if the fetch runs into some deadly fault.
24488c2ecf20Sopenharmony_cidimmed:
24498c2ecf20Sopenharmony_ci	addq.l		&0x4,EXC_EXTWPTR(%a6)
24508c2ecf20Sopenharmony_ci	bsr.l		_imem_read_long		# read immediate value
24518c2ecf20Sopenharmony_ci
24528c2ecf20Sopenharmony_ci	tst.l		%d1			# ifetch error?
24538c2ecf20Sopenharmony_ci	bne.l		isp_iacc		# yes
24548c2ecf20Sopenharmony_ci
24558c2ecf20Sopenharmony_ci	mov.l		%d0,%d7
24568c2ecf20Sopenharmony_ci	bra.w		dgotsrcl
24578c2ecf20Sopenharmony_ci
24588c2ecf20Sopenharmony_ci##########
24598c2ecf20Sopenharmony_ci
24608c2ecf20Sopenharmony_ci# if dmem_read_long() returns a fail message in d1, the package
24618c2ecf20Sopenharmony_ci# must create an access error frame. here, we pass a skeleton fslw
24628c2ecf20Sopenharmony_ci# and the failing address to the routine that creates the new frame.
24638c2ecf20Sopenharmony_ci# also, we call isp_restore in case the effective addressing mode was
24648c2ecf20Sopenharmony_ci# (an)+ or -(an) in which case the previous "an" value must be restored.
24658c2ecf20Sopenharmony_ci# FSLW:
24668c2ecf20Sopenharmony_ci#	read = true
24678c2ecf20Sopenharmony_ci#	size = longword
24688c2ecf20Sopenharmony_ci#	TM = data
24698c2ecf20Sopenharmony_ci#	software emulation error = true
24708c2ecf20Sopenharmony_cidiv64_err:
24718c2ecf20Sopenharmony_ci	bsr.l		isp_restore		# restore addr reg
24728c2ecf20Sopenharmony_ci	mov.l		%a2,%a0			# pass failing address
24738c2ecf20Sopenharmony_ci	mov.l		&0x01010001,%d0		# pass fslw
24748c2ecf20Sopenharmony_ci	bra.l		isp_dacc
24758c2ecf20Sopenharmony_ci
24768c2ecf20Sopenharmony_ci#########################################################################
24778c2ecf20Sopenharmony_ci# XDEF ****************************************************************	#
24788c2ecf20Sopenharmony_ci#	_mul64(): routine to emulate mul{u,s}.l <ea>,Dh:Dl 32x32->64	#
24798c2ecf20Sopenharmony_ci#									#
24808c2ecf20Sopenharmony_ci# XREF ****************************************************************	#
24818c2ecf20Sopenharmony_ci#	_calc_ea() - calculate effective address			#
24828c2ecf20Sopenharmony_ci#	isp_iacc() - handle instruction access error exception		#
24838c2ecf20Sopenharmony_ci#	isp_dacc() - handle data access error exception			#
24848c2ecf20Sopenharmony_ci#	isp_restore() - restore An on access error w/ -() or ()+	#
24858c2ecf20Sopenharmony_ci#									#
24868c2ecf20Sopenharmony_ci# INPUT ***************************************************************	#
24878c2ecf20Sopenharmony_ci#	none								#
24888c2ecf20Sopenharmony_ci#									#
24898c2ecf20Sopenharmony_ci# OUTPUT **************************************************************	#
24908c2ecf20Sopenharmony_ci#	If exiting through isp_dacc...					#
24918c2ecf20Sopenharmony_ci#		a0 = failing address					#
24928c2ecf20Sopenharmony_ci#		d0 = FSLW						#
24938c2ecf20Sopenharmony_ci#	else								#
24948c2ecf20Sopenharmony_ci#		none							#
24958c2ecf20Sopenharmony_ci#									#
24968c2ecf20Sopenharmony_ci# ALGORITHM ***********************************************************	#
24978c2ecf20Sopenharmony_ci#	First, decode the operand location. If it's in Dn, fetch from	#
24988c2ecf20Sopenharmony_ci# the stack. If it's in memory, use _calc_ea() to calculate the		#
24998c2ecf20Sopenharmony_ci# effective address. Use _dmem_read_long() to fetch at that address.	#
25008c2ecf20Sopenharmony_ci# Unless the operand is immediate data. Then use _imem_read_long().	#
25018c2ecf20Sopenharmony_ci# Send failures to isp_dacc() or isp_iacc() as appropriate.		#
25028c2ecf20Sopenharmony_ci#	If the operands are signed, make them unsigned and save the	#
25038c2ecf20Sopenharmony_ci# sign info for later. Perform the multiplication using 16x16->32	#
25048c2ecf20Sopenharmony_ci# unsigned multiplies and "add" instructions. Store the high and low	#
25058c2ecf20Sopenharmony_ci# portions of the result in the appropriate data registers on the	#
25068c2ecf20Sopenharmony_ci# stack. Calculate the condition codes, also.				#
25078c2ecf20Sopenharmony_ci#									#
25088c2ecf20Sopenharmony_ci#########################################################################
25098c2ecf20Sopenharmony_ci
25108c2ecf20Sopenharmony_ci#############
25118c2ecf20Sopenharmony_ci# mul(u,s)l #
25128c2ecf20Sopenharmony_ci#############
25138c2ecf20Sopenharmony_ci	global		_mul64
25148c2ecf20Sopenharmony_ci_mul64:
25158c2ecf20Sopenharmony_ci	mov.b		EXC_OPWORD+1(%a6), %d0	# extract src {mode,reg}
25168c2ecf20Sopenharmony_ci	cmpi.b		%d0, &0x7		# is src mode Dn or other?
25178c2ecf20Sopenharmony_ci	bgt.w		mul64_memop		# src is in memory
25188c2ecf20Sopenharmony_ci
25198c2ecf20Sopenharmony_ci# multiplier operand in the data register file.
25208c2ecf20Sopenharmony_ci# must extract the register number and fetch the operand from the stack.
25218c2ecf20Sopenharmony_cimul64_regop:
25228c2ecf20Sopenharmony_ci	andi.w		&0x7, %d0		# extract Dn
25238c2ecf20Sopenharmony_ci	mov.l		(EXC_DREGS,%a6,%d0.w*4), %d3 # fetch multiplier
25248c2ecf20Sopenharmony_ci
25258c2ecf20Sopenharmony_ci# multiplier is in %d3. now, extract Dl and Dh fields and fetch the
25268c2ecf20Sopenharmony_ci# multiplicand from the data register specified by Dl.
25278c2ecf20Sopenharmony_cimul64_multiplicand:
25288c2ecf20Sopenharmony_ci	mov.w		EXC_EXTWORD(%a6), %d2	# fetch ext word
25298c2ecf20Sopenharmony_ci	clr.w		%d1			# clear Dh reg
25308c2ecf20Sopenharmony_ci	mov.b		%d2, %d1		# grab Dh
25318c2ecf20Sopenharmony_ci	rol.w		&0x4, %d2		# align Dl byte
25328c2ecf20Sopenharmony_ci	andi.w		&0x7, %d2		# extract Dl
25338c2ecf20Sopenharmony_ci
25348c2ecf20Sopenharmony_ci	mov.l		(EXC_DREGS,%a6,%d2.w*4), %d4 # get multiplicand
25358c2ecf20Sopenharmony_ci
25368c2ecf20Sopenharmony_ci# check for the case of "zero" result early
25378c2ecf20Sopenharmony_ci	tst.l		%d4			# test multiplicand
25388c2ecf20Sopenharmony_ci	beq.w		mul64_zero		# handle zero separately
25398c2ecf20Sopenharmony_ci	tst.l		%d3			# test multiplier
25408c2ecf20Sopenharmony_ci	beq.w		mul64_zero		# handle zero separately
25418c2ecf20Sopenharmony_ci
25428c2ecf20Sopenharmony_ci# multiplier is in %d3 and multiplicand is in %d4.
25438c2ecf20Sopenharmony_ci# if the operation is to be signed, then the operands are converted
25448c2ecf20Sopenharmony_ci# to unsigned and the result sign is saved for the end.
25458c2ecf20Sopenharmony_ci	clr.b		EXC_TEMP(%a6)		# clear temp space
25468c2ecf20Sopenharmony_ci	btst		&0x3, EXC_EXTWORD(%a6)	# signed or unsigned?
25478c2ecf20Sopenharmony_ci	beq.b		mul64_alg		# unsigned; skip sgn calc
25488c2ecf20Sopenharmony_ci
25498c2ecf20Sopenharmony_ci	tst.l		%d3			# is multiplier negative?
25508c2ecf20Sopenharmony_ci	bge.b		mul64_chk_md_sgn	# no
25518c2ecf20Sopenharmony_ci	neg.l		%d3			# make multiplier positive
25528c2ecf20Sopenharmony_ci	ori.b		&0x1, EXC_TEMP(%a6)	# save multiplier sgn
25538c2ecf20Sopenharmony_ci
25548c2ecf20Sopenharmony_ci# the result sign is the exclusive or of the operand sign bits.
25558c2ecf20Sopenharmony_cimul64_chk_md_sgn:
25568c2ecf20Sopenharmony_ci	tst.l		%d4			# is multiplicand negative?
25578c2ecf20Sopenharmony_ci	bge.b		mul64_alg		# no
25588c2ecf20Sopenharmony_ci	neg.l		%d4			# make multiplicand positive
25598c2ecf20Sopenharmony_ci	eori.b		&0x1, EXC_TEMP(%a6)	# calculate correct sign
25608c2ecf20Sopenharmony_ci
25618c2ecf20Sopenharmony_ci#########################################################################
25628c2ecf20Sopenharmony_ci#	63			   32				0	#
25638c2ecf20Sopenharmony_ci#	----------------------------					#
25648c2ecf20Sopenharmony_ci#	| hi(mplier) * hi(mplicand)|					#
25658c2ecf20Sopenharmony_ci#	----------------------------					#
25668c2ecf20Sopenharmony_ci#		     -----------------------------			#
25678c2ecf20Sopenharmony_ci#		     | hi(mplier) * lo(mplicand) |			#
25688c2ecf20Sopenharmony_ci#		     -----------------------------			#
25698c2ecf20Sopenharmony_ci#		     -----------------------------			#
25708c2ecf20Sopenharmony_ci#		     | lo(mplier) * hi(mplicand) |			#
25718c2ecf20Sopenharmony_ci#		     -----------------------------			#
25728c2ecf20Sopenharmony_ci#	  |			   -----------------------------	#
25738c2ecf20Sopenharmony_ci#	--|--			   | lo(mplier) * lo(mplicand) |	#
25748c2ecf20Sopenharmony_ci#	  |			   -----------------------------	#
25758c2ecf20Sopenharmony_ci#	========================================================	#
25768c2ecf20Sopenharmony_ci#	--------------------------------------------------------	#
25778c2ecf20Sopenharmony_ci#	|	hi(result)	   |	    lo(result)         |	#
25788c2ecf20Sopenharmony_ci#	--------------------------------------------------------	#
25798c2ecf20Sopenharmony_ci#########################################################################
25808c2ecf20Sopenharmony_cimul64_alg:
25818c2ecf20Sopenharmony_ci# load temp registers with operands
25828c2ecf20Sopenharmony_ci	mov.l		%d3, %d5		# mr in %d5
25838c2ecf20Sopenharmony_ci	mov.l		%d3, %d6		# mr in %d6
25848c2ecf20Sopenharmony_ci	mov.l		%d4, %d7		# md in %d7
25858c2ecf20Sopenharmony_ci	swap		%d6			# hi(mr) in lo %d6
25868c2ecf20Sopenharmony_ci	swap		%d7			# hi(md) in lo %d7
25878c2ecf20Sopenharmony_ci
25888c2ecf20Sopenharmony_ci# complete necessary multiplies:
25898c2ecf20Sopenharmony_ci	mulu.w		%d4, %d3		# [1] lo(mr) * lo(md)
25908c2ecf20Sopenharmony_ci	mulu.w		%d6, %d4		# [2] hi(mr) * lo(md)
25918c2ecf20Sopenharmony_ci	mulu.w		%d7, %d5		# [3] lo(mr) * hi(md)
25928c2ecf20Sopenharmony_ci	mulu.w		%d7, %d6		# [4] hi(mr) * hi(md)
25938c2ecf20Sopenharmony_ci
25948c2ecf20Sopenharmony_ci# add lo portions of [2],[3] to hi portion of [1].
25958c2ecf20Sopenharmony_ci# add carries produced from these adds to [4].
25968c2ecf20Sopenharmony_ci# lo([1]) is the final lo 16 bits of the result.
25978c2ecf20Sopenharmony_ci	clr.l		%d7			# load %d7 w/ zero value
25988c2ecf20Sopenharmony_ci	swap		%d3			# hi([1]) <==> lo([1])
25998c2ecf20Sopenharmony_ci	add.w		%d4, %d3		# hi([1]) + lo([2])
26008c2ecf20Sopenharmony_ci	addx.l		%d7, %d6		#    [4]  + carry
26018c2ecf20Sopenharmony_ci	add.w		%d5, %d3		# hi([1]) + lo([3])
26028c2ecf20Sopenharmony_ci	addx.l		%d7, %d6		#    [4]  + carry
26038c2ecf20Sopenharmony_ci	swap		%d3			# lo([1]) <==> hi([1])
26048c2ecf20Sopenharmony_ci
26058c2ecf20Sopenharmony_ci# lo portions of [2],[3] have been added in to final result.
26068c2ecf20Sopenharmony_ci# now, clear lo, put hi in lo reg, and add to [4]
26078c2ecf20Sopenharmony_ci	clr.w		%d4			# clear lo([2])
26088c2ecf20Sopenharmony_ci	clr.w		%d5			# clear hi([3])
26098c2ecf20Sopenharmony_ci	swap		%d4			# hi([2]) in lo %d4
26108c2ecf20Sopenharmony_ci	swap		%d5			# hi([3]) in lo %d5
26118c2ecf20Sopenharmony_ci	add.l		%d5, %d4		#    [4]  + hi([2])
26128c2ecf20Sopenharmony_ci	add.l		%d6, %d4		#    [4]  + hi([3])
26138c2ecf20Sopenharmony_ci
26148c2ecf20Sopenharmony_ci# unsigned result is now in {%d4,%d3}
26158c2ecf20Sopenharmony_ci	tst.b		EXC_TEMP(%a6)		# should result be signed?
26168c2ecf20Sopenharmony_ci	beq.b		mul64_done		# no
26178c2ecf20Sopenharmony_ci
26188c2ecf20Sopenharmony_ci# result should be a signed negative number.
26198c2ecf20Sopenharmony_ci# compute 2's complement of the unsigned number:
26208c2ecf20Sopenharmony_ci#   -negate all bits and add 1
26218c2ecf20Sopenharmony_cimul64_neg:
26228c2ecf20Sopenharmony_ci	not.l		%d3			# negate lo(result) bits
26238c2ecf20Sopenharmony_ci	not.l		%d4			# negate hi(result) bits
26248c2ecf20Sopenharmony_ci	addq.l		&1, %d3			# add 1 to lo(result)
26258c2ecf20Sopenharmony_ci	addx.l		%d7, %d4		# add carry to hi(result)
26268c2ecf20Sopenharmony_ci
26278c2ecf20Sopenharmony_ci# the result is saved to the register file.
26288c2ecf20Sopenharmony_ci# for '040 compatibility, if Dl == Dh then only the hi(result) is
26298c2ecf20Sopenharmony_ci# saved. so, saving hi after lo accomplishes this without need to
26308c2ecf20Sopenharmony_ci# check Dl,Dh equality.
26318c2ecf20Sopenharmony_cimul64_done:
26328c2ecf20Sopenharmony_ci	mov.l		%d3, (EXC_DREGS,%a6,%d2.w*4) # save lo(result)
26338c2ecf20Sopenharmony_ci	mov.w		&0x0, %cc
26348c2ecf20Sopenharmony_ci	mov.l		%d4, (EXC_DREGS,%a6,%d1.w*4) # save hi(result)
26358c2ecf20Sopenharmony_ci
26368c2ecf20Sopenharmony_ci# now, grab the condition codes. only one that can be set is 'N'.
26378c2ecf20Sopenharmony_ci# 'N' CAN be set if the operation is unsigned if bit 63 is set.
26388c2ecf20Sopenharmony_ci	mov.w		%cc, %d7		# fetch %ccr to see if 'N' set
26398c2ecf20Sopenharmony_ci	andi.b		&0x8, %d7		# extract 'N' bit
26408c2ecf20Sopenharmony_ci
26418c2ecf20Sopenharmony_cimul64_ccode_set:
26428c2ecf20Sopenharmony_ci	mov.b		EXC_CC+1(%a6), %d6	# fetch previous %ccr
26438c2ecf20Sopenharmony_ci	andi.b		&0x10, %d6		# all but 'X' bit changes
26448c2ecf20Sopenharmony_ci
26458c2ecf20Sopenharmony_ci	or.b		%d7, %d6		# group 'X' and 'N'
26468c2ecf20Sopenharmony_ci	mov.b		%d6, EXC_CC+1(%a6)	# save new %ccr
26478c2ecf20Sopenharmony_ci
26488c2ecf20Sopenharmony_ci	rts
26498c2ecf20Sopenharmony_ci
26508c2ecf20Sopenharmony_ci# one or both of the operands is zero so the result is also zero.
26518c2ecf20Sopenharmony_ci# save the zero result to the register file and set the 'Z' ccode bit.
26528c2ecf20Sopenharmony_cimul64_zero:
26538c2ecf20Sopenharmony_ci	clr.l		(EXC_DREGS,%a6,%d2.w*4) # save lo(result)
26548c2ecf20Sopenharmony_ci	clr.l		(EXC_DREGS,%a6,%d1.w*4) # save hi(result)
26558c2ecf20Sopenharmony_ci
26568c2ecf20Sopenharmony_ci	movq.l		&0x4, %d7		# set 'Z' ccode bit
26578c2ecf20Sopenharmony_ci	bra.b		mul64_ccode_set		# finish ccode set
26588c2ecf20Sopenharmony_ci
26598c2ecf20Sopenharmony_ci##########
26608c2ecf20Sopenharmony_ci
26618c2ecf20Sopenharmony_ci# multiplier operand is in memory at the effective address.
26628c2ecf20Sopenharmony_ci# must calculate the <ea> and go fetch the 32-bit operand.
26638c2ecf20Sopenharmony_cimul64_memop:
26648c2ecf20Sopenharmony_ci	movq.l		&LONG, %d0		# pass # of bytes
26658c2ecf20Sopenharmony_ci	bsr.l		_calc_ea		# calculate <ea>
26668c2ecf20Sopenharmony_ci
26678c2ecf20Sopenharmony_ci	cmpi.b		SPCOND_FLG(%a6),&immed_flg # immediate addressing mode?
26688c2ecf20Sopenharmony_ci	beq.b		mul64_immed		# yes
26698c2ecf20Sopenharmony_ci
26708c2ecf20Sopenharmony_ci	mov.l		%a0,%a2
26718c2ecf20Sopenharmony_ci	bsr.l		_dmem_read_long		# fetch src from addr (%a0)
26728c2ecf20Sopenharmony_ci
26738c2ecf20Sopenharmony_ci	tst.l		%d1			# dfetch error?
26748c2ecf20Sopenharmony_ci	bne.w		mul64_err		# yes
26758c2ecf20Sopenharmony_ci
26768c2ecf20Sopenharmony_ci	mov.l		%d0, %d3		# store multiplier in %d3
26778c2ecf20Sopenharmony_ci
26788c2ecf20Sopenharmony_ci	bra.w		mul64_multiplicand
26798c2ecf20Sopenharmony_ci
26808c2ecf20Sopenharmony_ci# we have to split out immediate data here because it must be read using
26818c2ecf20Sopenharmony_ci# imem_read() instead of dmem_read(). this becomes especially important
26828c2ecf20Sopenharmony_ci# if the fetch runs into some deadly fault.
26838c2ecf20Sopenharmony_cimul64_immed:
26848c2ecf20Sopenharmony_ci	addq.l		&0x4,EXC_EXTWPTR(%a6)
26858c2ecf20Sopenharmony_ci	bsr.l		_imem_read_long		# read immediate value
26868c2ecf20Sopenharmony_ci
26878c2ecf20Sopenharmony_ci	tst.l		%d1			# ifetch error?
26888c2ecf20Sopenharmony_ci	bne.l		isp_iacc		# yes
26898c2ecf20Sopenharmony_ci
26908c2ecf20Sopenharmony_ci	mov.l		%d0,%d3
26918c2ecf20Sopenharmony_ci	bra.w		mul64_multiplicand
26928c2ecf20Sopenharmony_ci
26938c2ecf20Sopenharmony_ci##########
26948c2ecf20Sopenharmony_ci
26958c2ecf20Sopenharmony_ci# if dmem_read_long() returns a fail message in d1, the package
26968c2ecf20Sopenharmony_ci# must create an access error frame. here, we pass a skeleton fslw
26978c2ecf20Sopenharmony_ci# and the failing address to the routine that creates the new frame.
26988c2ecf20Sopenharmony_ci# also, we call isp_restore in case the effective addressing mode was
26998c2ecf20Sopenharmony_ci# (an)+ or -(an) in which case the previous "an" value must be restored.
27008c2ecf20Sopenharmony_ci# FSLW:
27018c2ecf20Sopenharmony_ci#	read = true
27028c2ecf20Sopenharmony_ci#	size = longword
27038c2ecf20Sopenharmony_ci#	TM = data
27048c2ecf20Sopenharmony_ci#	software emulation error = true
27058c2ecf20Sopenharmony_cimul64_err:
27068c2ecf20Sopenharmony_ci	bsr.l		isp_restore		# restore addr reg
27078c2ecf20Sopenharmony_ci	mov.l		%a2,%a0			# pass failing address
27088c2ecf20Sopenharmony_ci	mov.l		&0x01010001,%d0		# pass fslw
27098c2ecf20Sopenharmony_ci	bra.l		isp_dacc
27108c2ecf20Sopenharmony_ci
27118c2ecf20Sopenharmony_ci#########################################################################
27128c2ecf20Sopenharmony_ci# XDEF ****************************************************************	#
27138c2ecf20Sopenharmony_ci#	_compandset2(): routine to emulate cas2()			#
27148c2ecf20Sopenharmony_ci#			(internal to package)				#
27158c2ecf20Sopenharmony_ci#									#
27168c2ecf20Sopenharmony_ci#	_isp_cas2_finish(): store ccodes, store compare regs		#
27178c2ecf20Sopenharmony_ci#			    (external to package)			#
27188c2ecf20Sopenharmony_ci#									#
27198c2ecf20Sopenharmony_ci# XREF ****************************************************************	#
27208c2ecf20Sopenharmony_ci#	_real_lock_page() - "callout" to lock op's page from page-outs	#
27218c2ecf20Sopenharmony_ci#	_cas_terminate2() - access error exit				#
27228c2ecf20Sopenharmony_ci#	_real_cas2() - "callout" to core cas2 emulation code		#
27238c2ecf20Sopenharmony_ci#	_real_unlock_page() - "callout" to unlock page			#
27248c2ecf20Sopenharmony_ci#									#
27258c2ecf20Sopenharmony_ci# INPUT ***************************************************************	#
27268c2ecf20Sopenharmony_ci# _compandset2():							#
27278c2ecf20Sopenharmony_ci#	d0 = instruction extension word					#
27288c2ecf20Sopenharmony_ci#									#
27298c2ecf20Sopenharmony_ci# _isp_cas2_finish():							#
27308c2ecf20Sopenharmony_ci#	see cas2 core emulation code					#
27318c2ecf20Sopenharmony_ci#									#
27328c2ecf20Sopenharmony_ci# OUTPUT **************************************************************	#
27338c2ecf20Sopenharmony_ci# _compandset2():							#
27348c2ecf20Sopenharmony_ci#	see cas2 core emulation code					#
27358c2ecf20Sopenharmony_ci#									#
27368c2ecf20Sopenharmony_ci# _isp_cas_finish():							#
27378c2ecf20Sopenharmony_ci#	None (register file or memroy changed as appropriate)		#
27388c2ecf20Sopenharmony_ci#									#
27398c2ecf20Sopenharmony_ci# ALGORITHM ***********************************************************	#
27408c2ecf20Sopenharmony_ci# compandset2():							#
27418c2ecf20Sopenharmony_ci#	Decode the instruction and fetch the appropriate Update and	#
27428c2ecf20Sopenharmony_ci# Compare operands. Then call the "callout" _real_lock_page() for each	#
27438c2ecf20Sopenharmony_ci# memory operand address so that the operating system can keep these	#
27448c2ecf20Sopenharmony_ci# pages from being paged out. If either _real_lock_page() fails, exit	#
27458c2ecf20Sopenharmony_ci# through _cas_terminate2(). Don't forget to unlock the 1st locked page	#
27468c2ecf20Sopenharmony_ci# using _real_unlock_paged() if the 2nd lock-page fails.		#
27478c2ecf20Sopenharmony_ci# Finally, branch to the core cas2 emulation code by calling the	#
27488c2ecf20Sopenharmony_ci# "callout" _real_cas2().						#
27498c2ecf20Sopenharmony_ci#									#
27508c2ecf20Sopenharmony_ci# _isp_cas2_finish():							#
27518c2ecf20Sopenharmony_ci#	Re-perform the comparison so we can determine the condition	#
27528c2ecf20Sopenharmony_ci# codes which were too much trouble to keep around during the locked	#
27538c2ecf20Sopenharmony_ci# emulation. Then unlock each operands page by calling the "callout"	#
27548c2ecf20Sopenharmony_ci# _real_unlock_page().							#
27558c2ecf20Sopenharmony_ci#									#
27568c2ecf20Sopenharmony_ci#########################################################################
27578c2ecf20Sopenharmony_ci
27588c2ecf20Sopenharmony_ciset ADDR1,	EXC_TEMP+0xc
27598c2ecf20Sopenharmony_ciset ADDR2,	EXC_TEMP+0x0
27608c2ecf20Sopenharmony_ciset DC2,	EXC_TEMP+0xa
27618c2ecf20Sopenharmony_ciset DC1,	EXC_TEMP+0x8
27628c2ecf20Sopenharmony_ci
27638c2ecf20Sopenharmony_ci	global		_compandset2
27648c2ecf20Sopenharmony_ci_compandset2:
27658c2ecf20Sopenharmony_ci	mov.l		%d0,EXC_TEMP+0x4(%a6)		# store for possible restart
27668c2ecf20Sopenharmony_ci	mov.l		%d0,%d1			# extension word in d0
27678c2ecf20Sopenharmony_ci
27688c2ecf20Sopenharmony_ci	rol.w		&0x4,%d0
27698c2ecf20Sopenharmony_ci	andi.w		&0xf,%d0		# extract Rn2
27708c2ecf20Sopenharmony_ci	mov.l		(EXC_DREGS,%a6,%d0.w*4),%a1 # fetch ADDR2
27718c2ecf20Sopenharmony_ci	mov.l		%a1,ADDR2(%a6)
27728c2ecf20Sopenharmony_ci
27738c2ecf20Sopenharmony_ci	mov.l		%d1,%d0
27748c2ecf20Sopenharmony_ci
27758c2ecf20Sopenharmony_ci	lsr.w		&0x6,%d1
27768c2ecf20Sopenharmony_ci	andi.w		&0x7,%d1		# extract Du2
27778c2ecf20Sopenharmony_ci	mov.l		(EXC_DREGS,%a6,%d1.w*4),%d5 # fetch Update2 Op
27788c2ecf20Sopenharmony_ci
27798c2ecf20Sopenharmony_ci	andi.w		&0x7,%d0		# extract Dc2
27808c2ecf20Sopenharmony_ci	mov.l		(EXC_DREGS,%a6,%d0.w*4),%d3 # fetch Compare2 Op
27818c2ecf20Sopenharmony_ci	mov.w		%d0,DC2(%a6)
27828c2ecf20Sopenharmony_ci
27838c2ecf20Sopenharmony_ci	mov.w		EXC_EXTWORD(%a6),%d0
27848c2ecf20Sopenharmony_ci	mov.l		%d0,%d1
27858c2ecf20Sopenharmony_ci
27868c2ecf20Sopenharmony_ci	rol.w		&0x4,%d0
27878c2ecf20Sopenharmony_ci	andi.w		&0xf,%d0		# extract Rn1
27888c2ecf20Sopenharmony_ci	mov.l		(EXC_DREGS,%a6,%d0.w*4),%a0 # fetch ADDR1
27898c2ecf20Sopenharmony_ci	mov.l		%a0,ADDR1(%a6)
27908c2ecf20Sopenharmony_ci
27918c2ecf20Sopenharmony_ci	mov.l		%d1,%d0
27928c2ecf20Sopenharmony_ci
27938c2ecf20Sopenharmony_ci	lsr.w		&0x6,%d1
27948c2ecf20Sopenharmony_ci	andi.w		&0x7,%d1		# extract Du1
27958c2ecf20Sopenharmony_ci	mov.l		(EXC_DREGS,%a6,%d1.w*4),%d4 # fetch Update1 Op
27968c2ecf20Sopenharmony_ci
27978c2ecf20Sopenharmony_ci	andi.w		&0x7,%d0		# extract Dc1
27988c2ecf20Sopenharmony_ci	mov.l		(EXC_DREGS,%a6,%d0.w*4),%d2 # fetch Compare1 Op
27998c2ecf20Sopenharmony_ci	mov.w		%d0,DC1(%a6)
28008c2ecf20Sopenharmony_ci
28018c2ecf20Sopenharmony_ci	btst		&0x1,EXC_OPWORD(%a6)	# word or long?
28028c2ecf20Sopenharmony_ci	sne		%d7
28038c2ecf20Sopenharmony_ci
28048c2ecf20Sopenharmony_ci	btst		&0x5,EXC_ISR(%a6)	# user or supervisor?
28058c2ecf20Sopenharmony_ci	sne		%d6
28068c2ecf20Sopenharmony_ci
28078c2ecf20Sopenharmony_ci	mov.l		%a0,%a2
28088c2ecf20Sopenharmony_ci	mov.l		%a1,%a3
28098c2ecf20Sopenharmony_ci
28108c2ecf20Sopenharmony_ci	mov.l		%d7,%d1			# pass size
28118c2ecf20Sopenharmony_ci	mov.l		%d6,%d0			# pass mode
28128c2ecf20Sopenharmony_ci	bsr.l		_real_lock_page		# lock page
28138c2ecf20Sopenharmony_ci	mov.l		%a2,%a0
28148c2ecf20Sopenharmony_ci	tst.l		%d0			# error?
28158c2ecf20Sopenharmony_ci	bne.l		_cas_terminate2		# yes
28168c2ecf20Sopenharmony_ci
28178c2ecf20Sopenharmony_ci	mov.l		%d7,%d1			# pass size
28188c2ecf20Sopenharmony_ci	mov.l		%d6,%d0			# pass mode
28198c2ecf20Sopenharmony_ci	mov.l		%a3,%a0			# pass addr
28208c2ecf20Sopenharmony_ci	bsr.l		_real_lock_page		# lock page
28218c2ecf20Sopenharmony_ci	mov.l		%a3,%a0
28228c2ecf20Sopenharmony_ci	tst.l		%d0			# error?
28238c2ecf20Sopenharmony_ci	bne.b		cas_preterm		# yes
28248c2ecf20Sopenharmony_ci
28258c2ecf20Sopenharmony_ci	mov.l		%a2,%a0
28268c2ecf20Sopenharmony_ci	mov.l		%a3,%a1
28278c2ecf20Sopenharmony_ci
28288c2ecf20Sopenharmony_ci	bra.l		_real_cas2
28298c2ecf20Sopenharmony_ci
28308c2ecf20Sopenharmony_ci# if the 2nd lock attempt fails, then we must still unlock the
28318c2ecf20Sopenharmony_ci# first page(s).
28328c2ecf20Sopenharmony_cicas_preterm:
28338c2ecf20Sopenharmony_ci	mov.l		%d0,-(%sp)		# save FSLW
28348c2ecf20Sopenharmony_ci	mov.l		%d7,%d1			# pass size
28358c2ecf20Sopenharmony_ci	mov.l		%d6,%d0			# pass mode
28368c2ecf20Sopenharmony_ci	mov.l		%a2,%a0			# pass ADDR1
28378c2ecf20Sopenharmony_ci	bsr.l		_real_unlock_page	# unlock first page(s)
28388c2ecf20Sopenharmony_ci	mov.l		(%sp)+,%d0		# restore FSLW
28398c2ecf20Sopenharmony_ci	mov.l		%a3,%a0			# pass failing addr
28408c2ecf20Sopenharmony_ci	bra.l		_cas_terminate2
28418c2ecf20Sopenharmony_ci
28428c2ecf20Sopenharmony_ci#############################################################
28438c2ecf20Sopenharmony_ci
28448c2ecf20Sopenharmony_ci	global		_isp_cas2_finish
28458c2ecf20Sopenharmony_ci_isp_cas2_finish:
28468c2ecf20Sopenharmony_ci	btst		&0x1,EXC_OPWORD(%a6)
28478c2ecf20Sopenharmony_ci	bne.b		cas2_finish_l
28488c2ecf20Sopenharmony_ci
28498c2ecf20Sopenharmony_ci	mov.w		EXC_CC(%a6),%cc		# load old ccodes
28508c2ecf20Sopenharmony_ci	cmp.w		%d0,%d2
28518c2ecf20Sopenharmony_ci	bne.b		cas2_finish_w_save
28528c2ecf20Sopenharmony_ci	cmp.w		%d1,%d3
28538c2ecf20Sopenharmony_cicas2_finish_w_save:
28548c2ecf20Sopenharmony_ci	mov.w		%cc,EXC_CC(%a6)		# save new ccodes
28558c2ecf20Sopenharmony_ci
28568c2ecf20Sopenharmony_ci	tst.b		%d4			# update compare reg?
28578c2ecf20Sopenharmony_ci	bne.b		cas2_finish_w_done	# no
28588c2ecf20Sopenharmony_ci
28598c2ecf20Sopenharmony_ci	mov.w		DC2(%a6),%d3		# fetch Dc2
28608c2ecf20Sopenharmony_ci	mov.w		%d1,(2+EXC_DREGS,%a6,%d3.w*4) # store new Compare2 Op
28618c2ecf20Sopenharmony_ci
28628c2ecf20Sopenharmony_ci	mov.w		DC1(%a6),%d2		# fetch Dc1
28638c2ecf20Sopenharmony_ci	mov.w		%d0,(2+EXC_DREGS,%a6,%d2.w*4) # store new Compare1 Op
28648c2ecf20Sopenharmony_ci
28658c2ecf20Sopenharmony_cicas2_finish_w_done:
28668c2ecf20Sopenharmony_ci	btst		&0x5,EXC_ISR(%a6)
28678c2ecf20Sopenharmony_ci	sne		%d2
28688c2ecf20Sopenharmony_ci	mov.l		%d2,%d0			# pass mode
28698c2ecf20Sopenharmony_ci	sf		%d1			# pass size
28708c2ecf20Sopenharmony_ci	mov.l		ADDR1(%a6),%a0		# pass ADDR1
28718c2ecf20Sopenharmony_ci	bsr.l		_real_unlock_page	# unlock page
28728c2ecf20Sopenharmony_ci
28738c2ecf20Sopenharmony_ci	mov.l		%d2,%d0			# pass mode
28748c2ecf20Sopenharmony_ci	sf		%d1			# pass size
28758c2ecf20Sopenharmony_ci	mov.l		ADDR2(%a6),%a0		# pass ADDR2
28768c2ecf20Sopenharmony_ci	bsr.l		_real_unlock_page	# unlock page
28778c2ecf20Sopenharmony_ci	rts
28788c2ecf20Sopenharmony_ci
28798c2ecf20Sopenharmony_cicas2_finish_l:
28808c2ecf20Sopenharmony_ci	mov.w		EXC_CC(%a6),%cc		# load old ccodes
28818c2ecf20Sopenharmony_ci	cmp.l		%d0,%d2
28828c2ecf20Sopenharmony_ci	bne.b		cas2_finish_l_save
28838c2ecf20Sopenharmony_ci	cmp.l		%d1,%d3
28848c2ecf20Sopenharmony_cicas2_finish_l_save:
28858c2ecf20Sopenharmony_ci	mov.w		%cc,EXC_CC(%a6)		# save new ccodes
28868c2ecf20Sopenharmony_ci
28878c2ecf20Sopenharmony_ci	tst.b		%d4			# update compare reg?
28888c2ecf20Sopenharmony_ci	bne.b		cas2_finish_l_done	# no
28898c2ecf20Sopenharmony_ci
28908c2ecf20Sopenharmony_ci	mov.w		DC2(%a6),%d3		# fetch Dc2
28918c2ecf20Sopenharmony_ci	mov.l		%d1,(EXC_DREGS,%a6,%d3.w*4) # store new Compare2 Op
28928c2ecf20Sopenharmony_ci
28938c2ecf20Sopenharmony_ci	mov.w		DC1(%a6),%d2		# fetch Dc1
28948c2ecf20Sopenharmony_ci	mov.l		%d0,(EXC_DREGS,%a6,%d2.w*4) # store new Compare1 Op
28958c2ecf20Sopenharmony_ci
28968c2ecf20Sopenharmony_cicas2_finish_l_done:
28978c2ecf20Sopenharmony_ci	btst		&0x5,EXC_ISR(%a6)
28988c2ecf20Sopenharmony_ci	sne		%d2
28998c2ecf20Sopenharmony_ci	mov.l		%d2,%d0			# pass mode
29008c2ecf20Sopenharmony_ci	st		%d1			# pass size
29018c2ecf20Sopenharmony_ci	mov.l		ADDR1(%a6),%a0		# pass ADDR1
29028c2ecf20Sopenharmony_ci	bsr.l		_real_unlock_page	# unlock page
29038c2ecf20Sopenharmony_ci
29048c2ecf20Sopenharmony_ci	mov.l		%d2,%d0			# pass mode
29058c2ecf20Sopenharmony_ci	st		%d1			# pass size
29068c2ecf20Sopenharmony_ci	mov.l		ADDR2(%a6),%a0		# pass ADDR2
29078c2ecf20Sopenharmony_ci	bsr.l		_real_unlock_page	# unlock page
29088c2ecf20Sopenharmony_ci	rts
29098c2ecf20Sopenharmony_ci
29108c2ecf20Sopenharmony_ci########
29118c2ecf20Sopenharmony_ci	global		cr_cas2
29128c2ecf20Sopenharmony_cicr_cas2:
29138c2ecf20Sopenharmony_ci	mov.l		EXC_TEMP+0x4(%a6),%d0
29148c2ecf20Sopenharmony_ci	bra.w		_compandset2
29158c2ecf20Sopenharmony_ci
29168c2ecf20Sopenharmony_ci#########################################################################
29178c2ecf20Sopenharmony_ci# XDEF ****************************************************************	#
29188c2ecf20Sopenharmony_ci#	_compandset(): routine to emulate cas w/ misaligned <ea>	#
29198c2ecf20Sopenharmony_ci#		       (internal to package)				#
29208c2ecf20Sopenharmony_ci#	_isp_cas_finish(): routine called when cas emulation completes	#
29218c2ecf20Sopenharmony_ci#			   (external and internal to package)		#
29228c2ecf20Sopenharmony_ci#	_isp_cas_restart(): restart cas emulation after a fault		#
29238c2ecf20Sopenharmony_ci#			    (external to package)			#
29248c2ecf20Sopenharmony_ci#	_isp_cas_terminate(): create access error stack frame on fault	#
29258c2ecf20Sopenharmony_ci#			      (external and internal to package)	#
29268c2ecf20Sopenharmony_ci#	_isp_cas_inrange(): checks whether instr addess is within range	#
29278c2ecf20Sopenharmony_ci#			    of core cas/cas2emulation code		#
29288c2ecf20Sopenharmony_ci#			    (external to package)			#
29298c2ecf20Sopenharmony_ci#									#
29308c2ecf20Sopenharmony_ci# XREF ****************************************************************	#
29318c2ecf20Sopenharmony_ci#	_calc_ea(): calculate effective address				#
29328c2ecf20Sopenharmony_ci#									#
29338c2ecf20Sopenharmony_ci# INPUT ***************************************************************	#
29348c2ecf20Sopenharmony_ci# compandset():								#
29358c2ecf20Sopenharmony_ci#	none								#
29368c2ecf20Sopenharmony_ci# _isp_cas_restart():							#
29378c2ecf20Sopenharmony_ci#	d6 = previous sfc/dfc						#
29388c2ecf20Sopenharmony_ci# _isp_cas_finish():							#
29398c2ecf20Sopenharmony_ci# _isp_cas_terminate():							#
29408c2ecf20Sopenharmony_ci#	a0 = failing address						#
29418c2ecf20Sopenharmony_ci#	d0 = FSLW							#
29428c2ecf20Sopenharmony_ci#	d6 = previous sfc/dfc						#
29438c2ecf20Sopenharmony_ci# _isp_cas_inrange():							#
29448c2ecf20Sopenharmony_ci#	a0 = instruction address to be checked				#
29458c2ecf20Sopenharmony_ci#									#
29468c2ecf20Sopenharmony_ci# OUTPUT **************************************************************	#
29478c2ecf20Sopenharmony_ci# compandset():								#
29488c2ecf20Sopenharmony_ci#		none							#
29498c2ecf20Sopenharmony_ci# _isp_cas_restart():							#
29508c2ecf20Sopenharmony_ci#	a0 = effective address						#
29518c2ecf20Sopenharmony_ci#	d7 = word or longword flag					#
29528c2ecf20Sopenharmony_ci# _isp_cas_finish():							#
29538c2ecf20Sopenharmony_ci#	a0 = effective address						#
29548c2ecf20Sopenharmony_ci# _isp_cas_terminate():							#
29558c2ecf20Sopenharmony_ci#	initial register set before emulation exception			#
29568c2ecf20Sopenharmony_ci# _isp_cas_inrange():							#
29578c2ecf20Sopenharmony_ci#	d0 = 0 => in range; -1 => out of range				#
29588c2ecf20Sopenharmony_ci#									#
29598c2ecf20Sopenharmony_ci# ALGORITHM ***********************************************************	#
29608c2ecf20Sopenharmony_ci#									#
29618c2ecf20Sopenharmony_ci# compandset():								#
29628c2ecf20Sopenharmony_ci#	First, calculate the effective address. Then, decode the	#
29638c2ecf20Sopenharmony_ci# instruction word and fetch the "compare" (DC) and "update" (Du)	#
29648c2ecf20Sopenharmony_ci# operands.								#
29658c2ecf20Sopenharmony_ci#	Next, call the external routine _real_lock_page() so that the	#
29668c2ecf20Sopenharmony_ci# operating system can keep this page from being paged out while we're	#
29678c2ecf20Sopenharmony_ci# in this routine. If this call fails, jump to _cas_terminate2().	#
29688c2ecf20Sopenharmony_ci#	The routine then branches to _real_cas(). This external routine	#
29698c2ecf20Sopenharmony_ci# that actually emulates cas can be supplied by the external os or	#
29708c2ecf20Sopenharmony_ci# made to point directly back into the 060ISP which has a routine for	#
29718c2ecf20Sopenharmony_ci# this purpose.								#
29728c2ecf20Sopenharmony_ci#									#
29738c2ecf20Sopenharmony_ci# _isp_cas_finish():							#
29748c2ecf20Sopenharmony_ci#	Either way, after emulation, the package is re-entered at	#
29758c2ecf20Sopenharmony_ci# _isp_cas_finish(). This routine re-compares the operands in order to	#
29768c2ecf20Sopenharmony_ci# set the condition codes. Finally, these routines will call		#
29778c2ecf20Sopenharmony_ci# _real_unlock_page() in order to unlock the pages that were previously	#
29788c2ecf20Sopenharmony_ci# locked.								#
29798c2ecf20Sopenharmony_ci#									#
29808c2ecf20Sopenharmony_ci# _isp_cas_restart():							#
29818c2ecf20Sopenharmony_ci#	This routine can be entered from an access error handler where	#
29828c2ecf20Sopenharmony_ci# the emulation sequence should be re-started from the beginning.	#
29838c2ecf20Sopenharmony_ci#									#
29848c2ecf20Sopenharmony_ci# _isp_cas_terminate():							#
29858c2ecf20Sopenharmony_ci#	This routine can be entered from an access error handler where	#
29868c2ecf20Sopenharmony_ci# an emulation operand access failed and the operating system would	#
29878c2ecf20Sopenharmony_ci# like an access error stack frame created instead of the current	#
29888c2ecf20Sopenharmony_ci# unimplemented integer instruction frame.				#
29898c2ecf20Sopenharmony_ci#	Also, the package enters here if a call to _real_lock_page()	#
29908c2ecf20Sopenharmony_ci# fails.								#
29918c2ecf20Sopenharmony_ci#									#
29928c2ecf20Sopenharmony_ci# _isp_cas_inrange():							#
29938c2ecf20Sopenharmony_ci#	Checks to see whether the instruction address passed to it in	#
29948c2ecf20Sopenharmony_ci# a0 is within the software package cas/cas2 emulation routines. This	#
29958c2ecf20Sopenharmony_ci# can be helpful for an operating system to determine whether an access	#
29968c2ecf20Sopenharmony_ci# error during emulation was due to a cas/cas2 emulation access.	#
29978c2ecf20Sopenharmony_ci#									#
29988c2ecf20Sopenharmony_ci#########################################################################
29998c2ecf20Sopenharmony_ci
30008c2ecf20Sopenharmony_ciset DC,		EXC_TEMP+0x8
30018c2ecf20Sopenharmony_ciset ADDR,	EXC_TEMP+0x4
30028c2ecf20Sopenharmony_ci
30038c2ecf20Sopenharmony_ci	global		_compandset
30048c2ecf20Sopenharmony_ci_compandset:
30058c2ecf20Sopenharmony_ci	btst		&0x1,EXC_OPWORD(%a6)	# word or long operation?
30068c2ecf20Sopenharmony_ci	bne.b		compandsetl		# long
30078c2ecf20Sopenharmony_ci
30088c2ecf20Sopenharmony_cicompandsetw:
30098c2ecf20Sopenharmony_ci	movq.l		&0x2,%d0		# size = 2 bytes
30108c2ecf20Sopenharmony_ci	bsr.l		_calc_ea		# a0 = calculated <ea>
30118c2ecf20Sopenharmony_ci	mov.l		%a0,ADDR(%a6)		# save <ea> for possible restart
30128c2ecf20Sopenharmony_ci	sf		%d7			# clear d7 for word size
30138c2ecf20Sopenharmony_ci	bra.b		compandsetfetch
30148c2ecf20Sopenharmony_ci
30158c2ecf20Sopenharmony_cicompandsetl:
30168c2ecf20Sopenharmony_ci	movq.l		&0x4,%d0		# size = 4 bytes
30178c2ecf20Sopenharmony_ci	bsr.l		_calc_ea		# a0 = calculated <ea>
30188c2ecf20Sopenharmony_ci	mov.l		%a0,ADDR(%a6)		# save <ea> for possible restart
30198c2ecf20Sopenharmony_ci	st		%d7			# set d7 for longword size
30208c2ecf20Sopenharmony_ci
30218c2ecf20Sopenharmony_cicompandsetfetch:
30228c2ecf20Sopenharmony_ci	mov.w		EXC_EXTWORD(%a6),%d0	# fetch cas extension word
30238c2ecf20Sopenharmony_ci	mov.l		%d0,%d1			# make a copy
30248c2ecf20Sopenharmony_ci
30258c2ecf20Sopenharmony_ci	lsr.w		&0x6,%d0
30268c2ecf20Sopenharmony_ci	andi.w		&0x7,%d0		# extract Du
30278c2ecf20Sopenharmony_ci	mov.l		(EXC_DREGS,%a6,%d0.w*4),%d2 # get update operand
30288c2ecf20Sopenharmony_ci
30298c2ecf20Sopenharmony_ci	andi.w		&0x7,%d1		# extract Dc
30308c2ecf20Sopenharmony_ci	mov.l		(EXC_DREGS,%a6,%d1.w*4),%d4 # get compare operand
30318c2ecf20Sopenharmony_ci	mov.w		%d1,DC(%a6)		# save Dc
30328c2ecf20Sopenharmony_ci
30338c2ecf20Sopenharmony_ci	btst		&0x5,EXC_ISR(%a6)	# which mode for exception?
30348c2ecf20Sopenharmony_ci	sne		%d6			# set on supervisor mode
30358c2ecf20Sopenharmony_ci
30368c2ecf20Sopenharmony_ci	mov.l		%a0,%a2			# save temporarily
30378c2ecf20Sopenharmony_ci	mov.l		%d7,%d1			# pass size
30388c2ecf20Sopenharmony_ci	mov.l		%d6,%d0			# pass mode
30398c2ecf20Sopenharmony_ci	bsr.l		_real_lock_page		# lock page
30408c2ecf20Sopenharmony_ci	tst.l		%d0			# did error occur?
30418c2ecf20Sopenharmony_ci	bne.w		_cas_terminate2		# yes, clean up the mess
30428c2ecf20Sopenharmony_ci	mov.l		%a2,%a0			# pass addr in a0
30438c2ecf20Sopenharmony_ci
30448c2ecf20Sopenharmony_ci	bra.l		_real_cas
30458c2ecf20Sopenharmony_ci
30468c2ecf20Sopenharmony_ci########
30478c2ecf20Sopenharmony_ci	global		_isp_cas_finish
30488c2ecf20Sopenharmony_ci_isp_cas_finish:
30498c2ecf20Sopenharmony_ci	btst		&0x1,EXC_OPWORD(%a6)
30508c2ecf20Sopenharmony_ci	bne.b		cas_finish_l
30518c2ecf20Sopenharmony_ci
30528c2ecf20Sopenharmony_ci# just do the compare again since it's faster than saving the ccodes
30538c2ecf20Sopenharmony_ci# from the locked routine...
30548c2ecf20Sopenharmony_cicas_finish_w:
30558c2ecf20Sopenharmony_ci	mov.w		EXC_CC(%a6),%cc		# restore cc
30568c2ecf20Sopenharmony_ci	cmp.w		%d0,%d4			# do word compare
30578c2ecf20Sopenharmony_ci	mov.w		%cc,EXC_CC(%a6)		# save cc
30588c2ecf20Sopenharmony_ci
30598c2ecf20Sopenharmony_ci	tst.b		%d1			# update compare reg?
30608c2ecf20Sopenharmony_ci	bne.b		cas_finish_w_done	# no
30618c2ecf20Sopenharmony_ci
30628c2ecf20Sopenharmony_ci	mov.w		DC(%a6),%d3
30638c2ecf20Sopenharmony_ci	mov.w		%d0,(EXC_DREGS+2,%a6,%d3.w*4) # Dc = destination
30648c2ecf20Sopenharmony_ci
30658c2ecf20Sopenharmony_cicas_finish_w_done:
30668c2ecf20Sopenharmony_ci	mov.l		ADDR(%a6),%a0		# pass addr
30678c2ecf20Sopenharmony_ci	sf		%d1			# pass size
30688c2ecf20Sopenharmony_ci	btst		&0x5,EXC_ISR(%a6)
30698c2ecf20Sopenharmony_ci	sne		%d0			# pass mode
30708c2ecf20Sopenharmony_ci	bsr.l		_real_unlock_page	# unlock page
30718c2ecf20Sopenharmony_ci	rts
30728c2ecf20Sopenharmony_ci
30738c2ecf20Sopenharmony_ci# just do the compare again since it's faster than saving the ccodes
30748c2ecf20Sopenharmony_ci# from the locked routine...
30758c2ecf20Sopenharmony_cicas_finish_l:
30768c2ecf20Sopenharmony_ci	mov.w		EXC_CC(%a6),%cc		# restore cc
30778c2ecf20Sopenharmony_ci	cmp.l		%d0,%d4			# do longword compare
30788c2ecf20Sopenharmony_ci	mov.w		%cc,EXC_CC(%a6)		# save cc
30798c2ecf20Sopenharmony_ci
30808c2ecf20Sopenharmony_ci	tst.b		%d1			# update compare reg?
30818c2ecf20Sopenharmony_ci	bne.b		cas_finish_l_done	# no
30828c2ecf20Sopenharmony_ci
30838c2ecf20Sopenharmony_ci	mov.w		DC(%a6),%d3
30848c2ecf20Sopenharmony_ci	mov.l		%d0,(EXC_DREGS,%a6,%d3.w*4) # Dc = destination
30858c2ecf20Sopenharmony_ci
30868c2ecf20Sopenharmony_cicas_finish_l_done:
30878c2ecf20Sopenharmony_ci	mov.l		ADDR(%a6),%a0		# pass addr
30888c2ecf20Sopenharmony_ci	st		%d1			# pass size
30898c2ecf20Sopenharmony_ci	btst		&0x5,EXC_ISR(%a6)
30908c2ecf20Sopenharmony_ci	sne		%d0			# pass mode
30918c2ecf20Sopenharmony_ci	bsr.l		_real_unlock_page	# unlock page
30928c2ecf20Sopenharmony_ci	rts
30938c2ecf20Sopenharmony_ci
30948c2ecf20Sopenharmony_ci########
30958c2ecf20Sopenharmony_ci
30968c2ecf20Sopenharmony_ci	global		_isp_cas_restart
30978c2ecf20Sopenharmony_ci_isp_cas_restart:
30988c2ecf20Sopenharmony_ci	mov.l		%d6,%sfc		# restore previous sfc
30998c2ecf20Sopenharmony_ci	mov.l		%d6,%dfc		# restore previous dfc
31008c2ecf20Sopenharmony_ci
31018c2ecf20Sopenharmony_ci	cmpi.b		EXC_OPWORD+1(%a6),&0xfc	# cas or cas2?
31028c2ecf20Sopenharmony_ci	beq.l		cr_cas2			# cas2
31038c2ecf20Sopenharmony_cicr_cas:
31048c2ecf20Sopenharmony_ci	mov.l		ADDR(%a6),%a0		# load <ea>
31058c2ecf20Sopenharmony_ci	btst		&0x1,EXC_OPWORD(%a6)	# word or long operation?
31068c2ecf20Sopenharmony_ci	sne		%d7			# set d7 accordingly
31078c2ecf20Sopenharmony_ci	bra.w		compandsetfetch
31088c2ecf20Sopenharmony_ci
31098c2ecf20Sopenharmony_ci########
31108c2ecf20Sopenharmony_ci
31118c2ecf20Sopenharmony_ci# At this stage, it would be nice if d0 held the FSLW.
31128c2ecf20Sopenharmony_ci	global		_isp_cas_terminate
31138c2ecf20Sopenharmony_ci_isp_cas_terminate:
31148c2ecf20Sopenharmony_ci	mov.l		%d6,%sfc		# restore previous sfc
31158c2ecf20Sopenharmony_ci	mov.l		%d6,%dfc		# restore previous dfc
31168c2ecf20Sopenharmony_ci
31178c2ecf20Sopenharmony_ci	global		_cas_terminate2
31188c2ecf20Sopenharmony_ci_cas_terminate2:
31198c2ecf20Sopenharmony_ci	mov.l		%a0,%a2			# copy failing addr to a2
31208c2ecf20Sopenharmony_ci
31218c2ecf20Sopenharmony_ci	mov.l		%d0,-(%sp)
31228c2ecf20Sopenharmony_ci	bsr.l		isp_restore		# restore An (if ()+ or -())
31238c2ecf20Sopenharmony_ci	mov.l		(%sp)+,%d0
31248c2ecf20Sopenharmony_ci
31258c2ecf20Sopenharmony_ci	addq.l		&0x4,%sp		# remove sub return addr
31268c2ecf20Sopenharmony_ci	subq.l		&0x8,%sp		# make room for bigger stack
31278c2ecf20Sopenharmony_ci	subq.l		&0x8,%a6		# shift frame ptr down, too
31288c2ecf20Sopenharmony_ci	mov.l		&26,%d1			# want to move 51 longwords
31298c2ecf20Sopenharmony_ci	lea		0x8(%sp),%a0		# get address of old stack
31308c2ecf20Sopenharmony_ci	lea		0x0(%sp),%a1		# get address of new stack
31318c2ecf20Sopenharmony_cicas_term_cont:
31328c2ecf20Sopenharmony_ci	mov.l		(%a0)+,(%a1)+		# move a longword
31338c2ecf20Sopenharmony_ci	dbra.w		%d1,cas_term_cont	# keep going
31348c2ecf20Sopenharmony_ci
31358c2ecf20Sopenharmony_ci	mov.w		&0x4008,EXC_IVOFF(%a6)	# put new stk fmt, voff
31368c2ecf20Sopenharmony_ci	mov.l		%a2,EXC_IVOFF+0x2(%a6)	# put faulting addr on stack
31378c2ecf20Sopenharmony_ci	mov.l		%d0,EXC_IVOFF+0x6(%a6)	# put FSLW on stack
31388c2ecf20Sopenharmony_ci	movm.l		EXC_DREGS(%a6),&0x3fff	# restore user regs
31398c2ecf20Sopenharmony_ci	unlk		%a6			# unlink stack frame
31408c2ecf20Sopenharmony_ci	bra.l		_real_access
31418c2ecf20Sopenharmony_ci
31428c2ecf20Sopenharmony_ci########
31438c2ecf20Sopenharmony_ci
31448c2ecf20Sopenharmony_ci	global		_isp_cas_inrange
31458c2ecf20Sopenharmony_ci_isp_cas_inrange:
31468c2ecf20Sopenharmony_ci	clr.l		%d0			# clear return result
31478c2ecf20Sopenharmony_ci	lea		_CASHI(%pc),%a1		# load end of CAS core code
31488c2ecf20Sopenharmony_ci	cmp.l		%a1,%a0			# is PC in range?
31498c2ecf20Sopenharmony_ci	blt.b		cin_no			# no
31508c2ecf20Sopenharmony_ci	lea		_CASLO(%pc),%a1		# load begin of CAS core code
31518c2ecf20Sopenharmony_ci	cmp.l		%a0,%a1			# is PC in range?
31528c2ecf20Sopenharmony_ci	blt.b		cin_no			# no
31538c2ecf20Sopenharmony_ci	rts					# yes; return d0 = 0
31548c2ecf20Sopenharmony_cicin_no:
31558c2ecf20Sopenharmony_ci	mov.l		&-0x1,%d0		# out of range; return d0 = -1
31568c2ecf20Sopenharmony_ci	rts
31578c2ecf20Sopenharmony_ci
31588c2ecf20Sopenharmony_ci#################################################################
31598c2ecf20Sopenharmony_ci#################################################################
31608c2ecf20Sopenharmony_ci#################################################################
31618c2ecf20Sopenharmony_ci# This is the start of the cas and cas2 "core" emulation code.	#
31628c2ecf20Sopenharmony_ci# This is the section that may need to be replaced by the host	#
31638c2ecf20Sopenharmony_ci# OS if it is too operating system-specific.			#
31648c2ecf20Sopenharmony_ci# Please refer to the package documentation to see how to	#
31658c2ecf20Sopenharmony_ci# "replace" this section, if necessary.				#
31668c2ecf20Sopenharmony_ci#################################################################
31678c2ecf20Sopenharmony_ci#################################################################
31688c2ecf20Sopenharmony_ci#################################################################
31698c2ecf20Sopenharmony_ci
31708c2ecf20Sopenharmony_ci#       ######      ##      ######     ####
31718c2ecf20Sopenharmony_ci#       #	   #  #     #         #    #
31728c2ecf20Sopenharmony_ci#	#	  ######    ######        #
31738c2ecf20Sopenharmony_ci#	#	  #    #         #      #
31748c2ecf20Sopenharmony_ci#       ######    #    #    ######    ######
31758c2ecf20Sopenharmony_ci
31768c2ecf20Sopenharmony_ci#########################################################################
31778c2ecf20Sopenharmony_ci# XDEF ****************************************************************	#
31788c2ecf20Sopenharmony_ci#	_isp_cas2(): "core" emulation code for the cas2 instruction	#
31798c2ecf20Sopenharmony_ci#									#
31808c2ecf20Sopenharmony_ci# XREF ****************************************************************	#
31818c2ecf20Sopenharmony_ci#	_isp_cas2_finish() - only exit point for this emulation code;	#
31828c2ecf20Sopenharmony_ci#			     do clean-up; calculate ccodes; store	#
31838c2ecf20Sopenharmony_ci#			     Compare Ops if appropriate.		#
31848c2ecf20Sopenharmony_ci#									#
31858c2ecf20Sopenharmony_ci# INPUT ***************************************************************	#
31868c2ecf20Sopenharmony_ci#	*see chart below*						#
31878c2ecf20Sopenharmony_ci#									#
31888c2ecf20Sopenharmony_ci# OUTPUT **************************************************************	#
31898c2ecf20Sopenharmony_ci#	*see chart below*						#
31908c2ecf20Sopenharmony_ci#									#
31918c2ecf20Sopenharmony_ci# ALGORITHM ***********************************************************	#
31928c2ecf20Sopenharmony_ci#	(1) Make several copies of the effective address.		#
31938c2ecf20Sopenharmony_ci#	(2) Save current SR; Then mask off all maskable interrupts.	#
31948c2ecf20Sopenharmony_ci#	(3) Save current SFC/DFC (ASSUMED TO BE EQUAL!!!); Then set	#
31958c2ecf20Sopenharmony_ci#	    according to whether exception occurred in user or		#
31968c2ecf20Sopenharmony_ci#	    supervisor mode.						#
31978c2ecf20Sopenharmony_ci#	(4) Use "plpaw" instruction to pre-load ATC with effective	#
31988c2ecf20Sopenharmony_ci#	    address pages(s). THIS SHOULD NOT FAULT!!! The relevant	#
31998c2ecf20Sopenharmony_ci#	    page(s) should have already been made resident prior to	#
32008c2ecf20Sopenharmony_ci#	    entering this routine.					#
32018c2ecf20Sopenharmony_ci#	(5) Push the operand lines from the cache w/ "cpushl".		#
32028c2ecf20Sopenharmony_ci#	    In the 68040, this was done within the locked region. In	#
32038c2ecf20Sopenharmony_ci#	    the 68060, it is done outside of the locked region.		#
32048c2ecf20Sopenharmony_ci#	(6) Use "plpar" instruction to do a re-load of ATC entries for	#
32058c2ecf20Sopenharmony_ci#	    ADDR1 since ADDR2 entries may have pushed ADDR1 out of the	#
32068c2ecf20Sopenharmony_ci#	    ATC.							#
32078c2ecf20Sopenharmony_ci#	(7) Pre-fetch the core emulation instructions by executing	#
32088c2ecf20Sopenharmony_ci#	    one branch within each physical line (16 bytes) of the code	#
32098c2ecf20Sopenharmony_ci#	    before actually executing the code.				#
32108c2ecf20Sopenharmony_ci#	(8) Load the BUSCR w/ the bus lock value.			#
32118c2ecf20Sopenharmony_ci#	(9) Fetch the source operands using "moves".			#
32128c2ecf20Sopenharmony_ci#	(10)Do the compares. If both equal, go to step (13).		#
32138c2ecf20Sopenharmony_ci#	(11)Unequal. No update occurs. But, we do write the DST1 op	#
32148c2ecf20Sopenharmony_ci#	    back to itself (as w/ the '040) so we can gracefully unlock	#
32158c2ecf20Sopenharmony_ci#	    the bus (and assert LOCKE*) using BUSCR and the final move.	#
32168c2ecf20Sopenharmony_ci#	(12)Exit.							#
32178c2ecf20Sopenharmony_ci#	(13)Write update operand to the DST locations. Use BUSCR to	#
32188c2ecf20Sopenharmony_ci#	    assert LOCKE* for the final write operation.		#
32198c2ecf20Sopenharmony_ci#	(14)Exit.							#
32208c2ecf20Sopenharmony_ci#									#
32218c2ecf20Sopenharmony_ci#	The algorithm is actually implemented slightly differently	#
32228c2ecf20Sopenharmony_ci# depending on the size of the operation and the misalignment of the	#
32238c2ecf20Sopenharmony_ci# operands. A misaligned operand must be written in aligned chunks or	#
32248c2ecf20Sopenharmony_ci# else the BUSCR register control gets confused.			#
32258c2ecf20Sopenharmony_ci#									#
32268c2ecf20Sopenharmony_ci#########################################################################
32278c2ecf20Sopenharmony_ci
32288c2ecf20Sopenharmony_ci#################################################################
32298c2ecf20Sopenharmony_ci# THIS IS THE STATE OF THE INTEGER REGISTER FILE UPON		#
32308c2ecf20Sopenharmony_ci# ENTERING _isp_cas2().						#
32318c2ecf20Sopenharmony_ci#								#
32328c2ecf20Sopenharmony_ci# D0 = xxxxxxxx							#
32338c2ecf20Sopenharmony_ci# D1 = xxxxxxxx							#
32348c2ecf20Sopenharmony_ci# D2 = cmp operand 1						#
32358c2ecf20Sopenharmony_ci# D3 = cmp operand 2						#
32368c2ecf20Sopenharmony_ci# D4 = update oper 1						#
32378c2ecf20Sopenharmony_ci# D5 = update oper 2						#
32388c2ecf20Sopenharmony_ci# D6 = 'xxxxxxff if supervisor mode; 'xxxxxx00 if user mode	#
32398c2ecf20Sopenharmony_ci# D7 = 'xxxxxxff if longword operation; 'xxxxxx00 if word	#
32408c2ecf20Sopenharmony_ci# A0 = ADDR1							#
32418c2ecf20Sopenharmony_ci# A1 = ADDR2							#
32428c2ecf20Sopenharmony_ci# A2 = xxxxxxxx							#
32438c2ecf20Sopenharmony_ci# A3 = xxxxxxxx							#
32448c2ecf20Sopenharmony_ci# A4 = xxxxxxxx							#
32458c2ecf20Sopenharmony_ci# A5 = xxxxxxxx							#
32468c2ecf20Sopenharmony_ci# A6 = frame pointer						#
32478c2ecf20Sopenharmony_ci# A7 = stack pointer						#
32488c2ecf20Sopenharmony_ci#################################################################
32498c2ecf20Sopenharmony_ci
32508c2ecf20Sopenharmony_ci#	align		0x1000
32518c2ecf20Sopenharmony_ci# beginning label used by _isp_cas_inrange()
32528c2ecf20Sopenharmony_ci	global		_CASLO
32538c2ecf20Sopenharmony_ci_CASLO:
32548c2ecf20Sopenharmony_ci
32558c2ecf20Sopenharmony_ci	global		_isp_cas2
32568c2ecf20Sopenharmony_ci_isp_cas2:
32578c2ecf20Sopenharmony_ci	tst.b		%d6			# user or supervisor mode?
32588c2ecf20Sopenharmony_ci	bne.b		cas2_supervisor		# supervisor
32598c2ecf20Sopenharmony_cicas2_user:
32608c2ecf20Sopenharmony_ci	movq.l		&0x1,%d0		# load user data fc
32618c2ecf20Sopenharmony_ci	bra.b		cas2_cont
32628c2ecf20Sopenharmony_cicas2_supervisor:
32638c2ecf20Sopenharmony_ci	movq.l		&0x5,%d0		# load supervisor data fc
32648c2ecf20Sopenharmony_cicas2_cont:
32658c2ecf20Sopenharmony_ci	tst.b		%d7			# word or longword?
32668c2ecf20Sopenharmony_ci	beq.w		cas2w			# word
32678c2ecf20Sopenharmony_ci
32688c2ecf20Sopenharmony_ci####
32698c2ecf20Sopenharmony_cicas2l:
32708c2ecf20Sopenharmony_ci	mov.l		%a0,%a2			# copy ADDR1
32718c2ecf20Sopenharmony_ci	mov.l		%a1,%a3			# copy ADDR2
32728c2ecf20Sopenharmony_ci	mov.l		%a0,%a4			# copy ADDR1
32738c2ecf20Sopenharmony_ci	mov.l		%a1,%a5			# copy ADDR2
32748c2ecf20Sopenharmony_ci
32758c2ecf20Sopenharmony_ci	addq.l		&0x3,%a4		# ADDR1+3
32768c2ecf20Sopenharmony_ci	addq.l		&0x3,%a5		# ADDR2+3
32778c2ecf20Sopenharmony_ci	mov.l		%a2,%d1			# ADDR1
32788c2ecf20Sopenharmony_ci
32798c2ecf20Sopenharmony_ci# mask interrupts levels 0-6. save old mask value.
32808c2ecf20Sopenharmony_ci	mov.w		%sr,%d7			# save current SR
32818c2ecf20Sopenharmony_ci	ori.w		&0x0700,%sr		# inhibit interrupts
32828c2ecf20Sopenharmony_ci
32838c2ecf20Sopenharmony_ci# load the SFC and DFC with the appropriate mode.
32848c2ecf20Sopenharmony_ci	movc		%sfc,%d6		# save old SFC/DFC
32858c2ecf20Sopenharmony_ci	movc		%d0,%sfc		# store new SFC
32868c2ecf20Sopenharmony_ci	movc		%d0,%dfc		# store new DFC
32878c2ecf20Sopenharmony_ci
32888c2ecf20Sopenharmony_ci# pre-load the operand ATC. no page faults should occur here because
32898c2ecf20Sopenharmony_ci# _real_lock_page() should have taken care of this.
32908c2ecf20Sopenharmony_ci	plpaw		(%a2)			# load atc for ADDR1
32918c2ecf20Sopenharmony_ci	plpaw		(%a4)			# load atc for ADDR1+3
32928c2ecf20Sopenharmony_ci	plpaw		(%a3)			# load atc for ADDR2
32938c2ecf20Sopenharmony_ci	plpaw		(%a5)			# load atc for ADDR2+3
32948c2ecf20Sopenharmony_ci
32958c2ecf20Sopenharmony_ci# push the operand lines from the cache if they exist.
32968c2ecf20Sopenharmony_ci	cpushl		%dc,(%a2)		# push line for ADDR1
32978c2ecf20Sopenharmony_ci	cpushl		%dc,(%a4)		# push line for ADDR1+3
32988c2ecf20Sopenharmony_ci	cpushl		%dc,(%a3)		# push line for ADDR2
32998c2ecf20Sopenharmony_ci	cpushl		%dc,(%a5)		# push line for ADDR2+2
33008c2ecf20Sopenharmony_ci
33018c2ecf20Sopenharmony_ci	mov.l		%d1,%a2			# ADDR1
33028c2ecf20Sopenharmony_ci	addq.l		&0x3,%d1
33038c2ecf20Sopenharmony_ci	mov.l		%d1,%a4			# ADDR1+3
33048c2ecf20Sopenharmony_ci# if ADDR1 was ATC resident before the above "plpaw" and was executed
33058c2ecf20Sopenharmony_ci# and it was the next entry scheduled for replacement and ADDR2
33068c2ecf20Sopenharmony_ci# shares the same set, then the "plpaw" for ADDR2 can push the ADDR1
33078c2ecf20Sopenharmony_ci# entries from the ATC. so, we do a second set of "plpa"s.
33088c2ecf20Sopenharmony_ci	plpar		(%a2)			# load atc for ADDR1
33098c2ecf20Sopenharmony_ci	plpar		(%a4)			# load atc for ADDR1+3
33108c2ecf20Sopenharmony_ci
33118c2ecf20Sopenharmony_ci# load the BUSCR values.
33128c2ecf20Sopenharmony_ci	mov.l		&0x80000000,%a2		# assert LOCK* buscr value
33138c2ecf20Sopenharmony_ci	mov.l		&0xa0000000,%a3		# assert LOCKE* buscr value
33148c2ecf20Sopenharmony_ci	mov.l		&0x00000000,%a4		# buscr unlock value
33158c2ecf20Sopenharmony_ci
33168c2ecf20Sopenharmony_ci# there are three possible mis-aligned cases for longword cas. they
33178c2ecf20Sopenharmony_ci# are separated because the final write which asserts LOCKE* must
33188c2ecf20Sopenharmony_ci# be aligned.
33198c2ecf20Sopenharmony_ci	mov.l		%a0,%d0			# is ADDR1 misaligned?
33208c2ecf20Sopenharmony_ci	andi.b		&0x3,%d0
33218c2ecf20Sopenharmony_ci	beq.b		CAS2L_ENTER		# no
33228c2ecf20Sopenharmony_ci	cmpi.b		%d0,&0x2
33238c2ecf20Sopenharmony_ci	beq.w		CAS2L2_ENTER		# yes; word misaligned
33248c2ecf20Sopenharmony_ci	bra.w		CAS2L3_ENTER		# yes; byte misaligned
33258c2ecf20Sopenharmony_ci
33268c2ecf20Sopenharmony_ci#
33278c2ecf20Sopenharmony_ci# D0 = dst operand 1 <-
33288c2ecf20Sopenharmony_ci# D1 = dst operand 2 <-
33298c2ecf20Sopenharmony_ci# D2 = cmp operand 1
33308c2ecf20Sopenharmony_ci# D3 = cmp operand 2
33318c2ecf20Sopenharmony_ci# D4 = update oper 1
33328c2ecf20Sopenharmony_ci# D5 = update oper 2
33338c2ecf20Sopenharmony_ci# D6 = old SFC/DFC
33348c2ecf20Sopenharmony_ci# D7 = old SR
33358c2ecf20Sopenharmony_ci# A0 = ADDR1
33368c2ecf20Sopenharmony_ci# A1 = ADDR2
33378c2ecf20Sopenharmony_ci# A2 = bus LOCK*  value
33388c2ecf20Sopenharmony_ci# A3 = bus LOCKE* value
33398c2ecf20Sopenharmony_ci# A4 = bus unlock value
33408c2ecf20Sopenharmony_ci# A5 = xxxxxxxx
33418c2ecf20Sopenharmony_ci#
33428c2ecf20Sopenharmony_ci	align		0x10
33438c2ecf20Sopenharmony_ciCAS2L_START:
33448c2ecf20Sopenharmony_ci	movc		%a2,%buscr		# assert LOCK*
33458c2ecf20Sopenharmony_ci	movs.l		(%a1),%d1		# fetch Dest2[31:0]
33468c2ecf20Sopenharmony_ci	movs.l		(%a0),%d0		# fetch Dest1[31:0]
33478c2ecf20Sopenharmony_ci	bra.b		CAS2L_CONT
33488c2ecf20Sopenharmony_ciCAS2L_ENTER:
33498c2ecf20Sopenharmony_ci	bra.b		~+16
33508c2ecf20Sopenharmony_ci
33518c2ecf20Sopenharmony_ciCAS2L_CONT:
33528c2ecf20Sopenharmony_ci	cmp.l		%d0,%d2			# Dest1 - Compare1
33538c2ecf20Sopenharmony_ci	bne.b		CAS2L_NOUPDATE
33548c2ecf20Sopenharmony_ci	cmp.l		%d1,%d3			# Dest2 - Compare2
33558c2ecf20Sopenharmony_ci	bne.b		CAS2L_NOUPDATE
33568c2ecf20Sopenharmony_ci	movs.l		%d5,(%a1)		# Update2[31:0] -> DEST2
33578c2ecf20Sopenharmony_ci	bra.b		CAS2L_UPDATE
33588c2ecf20Sopenharmony_ci	bra.b		~+16
33598c2ecf20Sopenharmony_ci
33608c2ecf20Sopenharmony_ciCAS2L_UPDATE:
33618c2ecf20Sopenharmony_ci	movc		%a3,%buscr		# assert LOCKE*
33628c2ecf20Sopenharmony_ci	movs.l		%d4,(%a0)		# Update1[31:0] -> DEST1
33638c2ecf20Sopenharmony_ci	movc		%a4,%buscr		# unlock the bus
33648c2ecf20Sopenharmony_ci	bra.b		cas2l_update_done
33658c2ecf20Sopenharmony_ci	bra.b		~+16
33668c2ecf20Sopenharmony_ci
33678c2ecf20Sopenharmony_ciCAS2L_NOUPDATE:
33688c2ecf20Sopenharmony_ci	movc		%a3,%buscr		# assert LOCKE*
33698c2ecf20Sopenharmony_ci	movs.l		%d0,(%a0)		# Dest1[31:0] -> DEST1
33708c2ecf20Sopenharmony_ci	movc		%a4,%buscr		# unlock the bus
33718c2ecf20Sopenharmony_ci	bra.b		cas2l_noupdate_done
33728c2ecf20Sopenharmony_ci	bra.b		~+16
33738c2ecf20Sopenharmony_ci
33748c2ecf20Sopenharmony_ciCAS2L_FILLER:
33758c2ecf20Sopenharmony_ci	nop
33768c2ecf20Sopenharmony_ci	nop
33778c2ecf20Sopenharmony_ci	nop
33788c2ecf20Sopenharmony_ci	nop
33798c2ecf20Sopenharmony_ci	nop
33808c2ecf20Sopenharmony_ci	nop
33818c2ecf20Sopenharmony_ci	nop
33828c2ecf20Sopenharmony_ci	bra.b		CAS2L_START
33838c2ecf20Sopenharmony_ci
33848c2ecf20Sopenharmony_ci####
33858c2ecf20Sopenharmony_ci
33868c2ecf20Sopenharmony_ci#################################################################
33878c2ecf20Sopenharmony_ci# THIS MUST BE THE STATE OF THE INTEGER REGISTER FILE UPON	#
33888c2ecf20Sopenharmony_ci# ENTERING _isp_cas2().						#
33898c2ecf20Sopenharmony_ci#								#
33908c2ecf20Sopenharmony_ci# D0 = destination[31:0] operand 1				#
33918c2ecf20Sopenharmony_ci# D1 = destination[31:0] operand 2				#
33928c2ecf20Sopenharmony_ci# D2 = cmp[31:0] operand 1					#
33938c2ecf20Sopenharmony_ci# D3 = cmp[31:0] operand 2					#
33948c2ecf20Sopenharmony_ci# D4 = 'xxxxxx11 -> no reg update; 'xxxxxx00 -> update required	#
33958c2ecf20Sopenharmony_ci# D5 = xxxxxxxx							#
33968c2ecf20Sopenharmony_ci# D6 = xxxxxxxx							#
33978c2ecf20Sopenharmony_ci# D7 = xxxxxxxx							#
33988c2ecf20Sopenharmony_ci# A0 = xxxxxxxx							#
33998c2ecf20Sopenharmony_ci# A1 = xxxxxxxx							#
34008c2ecf20Sopenharmony_ci# A2 = xxxxxxxx							#
34018c2ecf20Sopenharmony_ci# A3 = xxxxxxxx							#
34028c2ecf20Sopenharmony_ci# A4 = xxxxxxxx							#
34038c2ecf20Sopenharmony_ci# A5 = xxxxxxxx							#
34048c2ecf20Sopenharmony_ci# A6 = frame pointer						#
34058c2ecf20Sopenharmony_ci# A7 = stack pointer						#
34068c2ecf20Sopenharmony_ci#################################################################
34078c2ecf20Sopenharmony_ci
34088c2ecf20Sopenharmony_cicas2l_noupdate_done:
34098c2ecf20Sopenharmony_ci
34108c2ecf20Sopenharmony_ci# restore previous SFC/DFC value.
34118c2ecf20Sopenharmony_ci	movc		%d6,%sfc		# restore old SFC
34128c2ecf20Sopenharmony_ci	movc		%d6,%dfc		# restore old DFC
34138c2ecf20Sopenharmony_ci
34148c2ecf20Sopenharmony_ci# restore previous interrupt mask level.
34158c2ecf20Sopenharmony_ci	mov.w		%d7,%sr			# restore old SR
34168c2ecf20Sopenharmony_ci
34178c2ecf20Sopenharmony_ci	sf		%d4			# indicate no update was done
34188c2ecf20Sopenharmony_ci	bra.l		_isp_cas2_finish
34198c2ecf20Sopenharmony_ci
34208c2ecf20Sopenharmony_cicas2l_update_done:
34218c2ecf20Sopenharmony_ci
34228c2ecf20Sopenharmony_ci# restore previous SFC/DFC value.
34238c2ecf20Sopenharmony_ci	movc		%d6,%sfc		# restore old SFC
34248c2ecf20Sopenharmony_ci	movc		%d6,%dfc		# restore old DFC
34258c2ecf20Sopenharmony_ci
34268c2ecf20Sopenharmony_ci# restore previous interrupt mask level.
34278c2ecf20Sopenharmony_ci	mov.w		%d7,%sr			# restore old SR
34288c2ecf20Sopenharmony_ci
34298c2ecf20Sopenharmony_ci	st		%d4			# indicate update was done
34308c2ecf20Sopenharmony_ci	bra.l		_isp_cas2_finish
34318c2ecf20Sopenharmony_ci####
34328c2ecf20Sopenharmony_ci
34338c2ecf20Sopenharmony_ci	align		0x10
34348c2ecf20Sopenharmony_ciCAS2L2_START:
34358c2ecf20Sopenharmony_ci	movc		%a2,%buscr		# assert LOCK*
34368c2ecf20Sopenharmony_ci	movs.l		(%a1),%d1		# fetch Dest2[31:0]
34378c2ecf20Sopenharmony_ci	movs.l		(%a0),%d0		# fetch Dest1[31:0]
34388c2ecf20Sopenharmony_ci	bra.b		CAS2L2_CONT
34398c2ecf20Sopenharmony_ciCAS2L2_ENTER:
34408c2ecf20Sopenharmony_ci	bra.b		~+16
34418c2ecf20Sopenharmony_ci
34428c2ecf20Sopenharmony_ciCAS2L2_CONT:
34438c2ecf20Sopenharmony_ci	cmp.l		%d0,%d2			# Dest1 - Compare1
34448c2ecf20Sopenharmony_ci	bne.b		CAS2L2_NOUPDATE
34458c2ecf20Sopenharmony_ci	cmp.l		%d1,%d3			# Dest2 - Compare2
34468c2ecf20Sopenharmony_ci	bne.b		CAS2L2_NOUPDATE
34478c2ecf20Sopenharmony_ci	movs.l		%d5,(%a1)		# Update2[31:0] -> Dest2
34488c2ecf20Sopenharmony_ci	bra.b		CAS2L2_UPDATE
34498c2ecf20Sopenharmony_ci	bra.b		~+16
34508c2ecf20Sopenharmony_ci
34518c2ecf20Sopenharmony_ciCAS2L2_UPDATE:
34528c2ecf20Sopenharmony_ci	swap		%d4			# get Update1[31:16]
34538c2ecf20Sopenharmony_ci	movs.w		%d4,(%a0)+		# Update1[31:16] -> DEST1
34548c2ecf20Sopenharmony_ci	movc		%a3,%buscr		# assert LOCKE*
34558c2ecf20Sopenharmony_ci	swap		%d4			# get Update1[15:0]
34568c2ecf20Sopenharmony_ci	bra.b		CAS2L2_UPDATE2
34578c2ecf20Sopenharmony_ci	bra.b		~+16
34588c2ecf20Sopenharmony_ci
34598c2ecf20Sopenharmony_ciCAS2L2_UPDATE2:
34608c2ecf20Sopenharmony_ci	movs.w		%d4,(%a0)		# Update1[15:0] -> DEST1+0x2
34618c2ecf20Sopenharmony_ci	movc		%a4,%buscr		# unlock the bus
34628c2ecf20Sopenharmony_ci	bra.w		cas2l_update_done
34638c2ecf20Sopenharmony_ci	nop
34648c2ecf20Sopenharmony_ci	bra.b		~+16
34658c2ecf20Sopenharmony_ci
34668c2ecf20Sopenharmony_ciCAS2L2_NOUPDATE:
34678c2ecf20Sopenharmony_ci	swap		%d0			# get Dest1[31:16]
34688c2ecf20Sopenharmony_ci	movs.w		%d0,(%a0)+		# Dest1[31:16] -> DEST1
34698c2ecf20Sopenharmony_ci	movc		%a3,%buscr		# assert LOCKE*
34708c2ecf20Sopenharmony_ci	swap		%d0			# get Dest1[15:0]
34718c2ecf20Sopenharmony_ci	bra.b		CAS2L2_NOUPDATE2
34728c2ecf20Sopenharmony_ci	bra.b		~+16
34738c2ecf20Sopenharmony_ci
34748c2ecf20Sopenharmony_ciCAS2L2_NOUPDATE2:
34758c2ecf20Sopenharmony_ci	movs.w		%d0,(%a0)		# Dest1[15:0] -> DEST1+0x2
34768c2ecf20Sopenharmony_ci	movc		%a4,%buscr		# unlock the bus
34778c2ecf20Sopenharmony_ci	bra.w		cas2l_noupdate_done
34788c2ecf20Sopenharmony_ci	nop
34798c2ecf20Sopenharmony_ci	bra.b		~+16
34808c2ecf20Sopenharmony_ci
34818c2ecf20Sopenharmony_ciCAS2L2_FILLER:
34828c2ecf20Sopenharmony_ci	nop
34838c2ecf20Sopenharmony_ci	nop
34848c2ecf20Sopenharmony_ci	nop
34858c2ecf20Sopenharmony_ci	nop
34868c2ecf20Sopenharmony_ci	nop
34878c2ecf20Sopenharmony_ci	nop
34888c2ecf20Sopenharmony_ci	nop
34898c2ecf20Sopenharmony_ci	bra.b		CAS2L2_START
34908c2ecf20Sopenharmony_ci
34918c2ecf20Sopenharmony_ci#################################
34928c2ecf20Sopenharmony_ci
34938c2ecf20Sopenharmony_ci	align		0x10
34948c2ecf20Sopenharmony_ciCAS2L3_START:
34958c2ecf20Sopenharmony_ci	movc		%a2,%buscr		# assert LOCK*
34968c2ecf20Sopenharmony_ci	movs.l		(%a1),%d1		# fetch Dest2[31:0]
34978c2ecf20Sopenharmony_ci	movs.l		(%a0),%d0		# fetch Dest1[31:0]
34988c2ecf20Sopenharmony_ci	bra.b		CAS2L3_CONT
34998c2ecf20Sopenharmony_ciCAS2L3_ENTER:
35008c2ecf20Sopenharmony_ci	bra.b		~+16
35018c2ecf20Sopenharmony_ci
35028c2ecf20Sopenharmony_ciCAS2L3_CONT:
35038c2ecf20Sopenharmony_ci	cmp.l		%d0,%d2			# Dest1 - Compare1
35048c2ecf20Sopenharmony_ci	bne.b		CAS2L3_NOUPDATE
35058c2ecf20Sopenharmony_ci	cmp.l		%d1,%d3			# Dest2 - Compare2
35068c2ecf20Sopenharmony_ci	bne.b		CAS2L3_NOUPDATE
35078c2ecf20Sopenharmony_ci	movs.l		%d5,(%a1)		# Update2[31:0] -> DEST2
35088c2ecf20Sopenharmony_ci	bra.b		CAS2L3_UPDATE
35098c2ecf20Sopenharmony_ci	bra.b		~+16
35108c2ecf20Sopenharmony_ci
35118c2ecf20Sopenharmony_ciCAS2L3_UPDATE:
35128c2ecf20Sopenharmony_ci	rol.l		&0x8,%d4		# get Update1[31:24]
35138c2ecf20Sopenharmony_ci	movs.b		%d4,(%a0)+		# Update1[31:24] -> DEST1
35148c2ecf20Sopenharmony_ci	swap		%d4			# get Update1[23:8]
35158c2ecf20Sopenharmony_ci	movs.w		%d4,(%a0)+		# Update1[23:8] -> DEST1+0x1
35168c2ecf20Sopenharmony_ci	bra.b		CAS2L3_UPDATE2
35178c2ecf20Sopenharmony_ci	bra.b		~+16
35188c2ecf20Sopenharmony_ci
35198c2ecf20Sopenharmony_ciCAS2L3_UPDATE2:
35208c2ecf20Sopenharmony_ci	rol.l		&0x8,%d4		# get Update1[7:0]
35218c2ecf20Sopenharmony_ci	movc		%a3,%buscr		# assert LOCKE*
35228c2ecf20Sopenharmony_ci	movs.b		%d4,(%a0)		# Update1[7:0] -> DEST1+0x3
35238c2ecf20Sopenharmony_ci	bra.b		CAS2L3_UPDATE3
35248c2ecf20Sopenharmony_ci	nop
35258c2ecf20Sopenharmony_ci	bra.b		~+16
35268c2ecf20Sopenharmony_ci
35278c2ecf20Sopenharmony_ciCAS2L3_UPDATE3:
35288c2ecf20Sopenharmony_ci	movc		%a4,%buscr		# unlock the bus
35298c2ecf20Sopenharmony_ci	bra.w		cas2l_update_done
35308c2ecf20Sopenharmony_ci	nop
35318c2ecf20Sopenharmony_ci	nop
35328c2ecf20Sopenharmony_ci	nop
35338c2ecf20Sopenharmony_ci	bra.b		~+16
35348c2ecf20Sopenharmony_ci
35358c2ecf20Sopenharmony_ciCAS2L3_NOUPDATE:
35368c2ecf20Sopenharmony_ci	rol.l		&0x8,%d0		# get Dest1[31:24]
35378c2ecf20Sopenharmony_ci	movs.b		%d0,(%a0)+		# Dest1[31:24] -> DEST1
35388c2ecf20Sopenharmony_ci	swap		%d0			# get Dest1[23:8]
35398c2ecf20Sopenharmony_ci	movs.w		%d0,(%a0)+		# Dest1[23:8] -> DEST1+0x1
35408c2ecf20Sopenharmony_ci	bra.b		CAS2L3_NOUPDATE2
35418c2ecf20Sopenharmony_ci	bra.b		~+16
35428c2ecf20Sopenharmony_ci
35438c2ecf20Sopenharmony_ciCAS2L3_NOUPDATE2:
35448c2ecf20Sopenharmony_ci	rol.l		&0x8,%d0		# get Dest1[7:0]
35458c2ecf20Sopenharmony_ci	movc		%a3,%buscr		# assert LOCKE*
35468c2ecf20Sopenharmony_ci	movs.b		%d0,(%a0)		# Update1[7:0] -> DEST1+0x3
35478c2ecf20Sopenharmony_ci	bra.b		CAS2L3_NOUPDATE3
35488c2ecf20Sopenharmony_ci	nop
35498c2ecf20Sopenharmony_ci	bra.b		~+16
35508c2ecf20Sopenharmony_ci
35518c2ecf20Sopenharmony_ciCAS2L3_NOUPDATE3:
35528c2ecf20Sopenharmony_ci	movc		%a4,%buscr		# unlock the bus
35538c2ecf20Sopenharmony_ci	bra.w		cas2l_noupdate_done
35548c2ecf20Sopenharmony_ci	nop
35558c2ecf20Sopenharmony_ci	nop
35568c2ecf20Sopenharmony_ci	nop
35578c2ecf20Sopenharmony_ci	bra.b		~+14
35588c2ecf20Sopenharmony_ci
35598c2ecf20Sopenharmony_ciCAS2L3_FILLER:
35608c2ecf20Sopenharmony_ci	nop
35618c2ecf20Sopenharmony_ci	nop
35628c2ecf20Sopenharmony_ci	nop
35638c2ecf20Sopenharmony_ci	nop
35648c2ecf20Sopenharmony_ci	nop
35658c2ecf20Sopenharmony_ci	nop
35668c2ecf20Sopenharmony_ci	bra.w		CAS2L3_START
35678c2ecf20Sopenharmony_ci
35688c2ecf20Sopenharmony_ci#############################################################
35698c2ecf20Sopenharmony_ci#############################################################
35708c2ecf20Sopenharmony_ci
35718c2ecf20Sopenharmony_cicas2w:
35728c2ecf20Sopenharmony_ci	mov.l		%a0,%a2			# copy ADDR1
35738c2ecf20Sopenharmony_ci	mov.l		%a1,%a3			# copy ADDR2
35748c2ecf20Sopenharmony_ci	mov.l		%a0,%a4			# copy ADDR1
35758c2ecf20Sopenharmony_ci	mov.l		%a1,%a5			# copy ADDR2
35768c2ecf20Sopenharmony_ci
35778c2ecf20Sopenharmony_ci	addq.l		&0x1,%a4		# ADDR1+1
35788c2ecf20Sopenharmony_ci	addq.l		&0x1,%a5		# ADDR2+1
35798c2ecf20Sopenharmony_ci	mov.l		%a2,%d1			# ADDR1
35808c2ecf20Sopenharmony_ci
35818c2ecf20Sopenharmony_ci# mask interrupt levels 0-6. save old mask value.
35828c2ecf20Sopenharmony_ci	mov.w		%sr,%d7			# save current SR
35838c2ecf20Sopenharmony_ci	ori.w		&0x0700,%sr		# inhibit interrupts
35848c2ecf20Sopenharmony_ci
35858c2ecf20Sopenharmony_ci# load the SFC and DFC with the appropriate mode.
35868c2ecf20Sopenharmony_ci	movc		%sfc,%d6		# save old SFC/DFC
35878c2ecf20Sopenharmony_ci	movc		%d0,%sfc		# store new SFC
35888c2ecf20Sopenharmony_ci	movc		%d0,%dfc		# store new DFC
35898c2ecf20Sopenharmony_ci
35908c2ecf20Sopenharmony_ci# pre-load the operand ATC. no page faults should occur because
35918c2ecf20Sopenharmony_ci# _real_lock_page() should have taken care of this.
35928c2ecf20Sopenharmony_ci	plpaw		(%a2)			# load atc for ADDR1
35938c2ecf20Sopenharmony_ci	plpaw		(%a4)			# load atc for ADDR1+1
35948c2ecf20Sopenharmony_ci	plpaw		(%a3)			# load atc for ADDR2
35958c2ecf20Sopenharmony_ci	plpaw		(%a5)			# load atc for ADDR2+1
35968c2ecf20Sopenharmony_ci
35978c2ecf20Sopenharmony_ci# push the operand cache lines from the cache if they exist.
35988c2ecf20Sopenharmony_ci	cpushl		%dc,(%a2)		# push line for ADDR1
35998c2ecf20Sopenharmony_ci	cpushl		%dc,(%a4)		# push line for ADDR1+1
36008c2ecf20Sopenharmony_ci	cpushl		%dc,(%a3)		# push line for ADDR2
36018c2ecf20Sopenharmony_ci	cpushl		%dc,(%a5)		# push line for ADDR2+1
36028c2ecf20Sopenharmony_ci
36038c2ecf20Sopenharmony_ci	mov.l		%d1,%a2			# ADDR1
36048c2ecf20Sopenharmony_ci	addq.l		&0x3,%d1
36058c2ecf20Sopenharmony_ci	mov.l		%d1,%a4			# ADDR1+3
36068c2ecf20Sopenharmony_ci# if ADDR1 was ATC resident before the above "plpaw" and was executed
36078c2ecf20Sopenharmony_ci# and it was the next entry scheduled for replacement and ADDR2
36088c2ecf20Sopenharmony_ci# shares the same set, then the "plpaw" for ADDR2 can push the ADDR1
36098c2ecf20Sopenharmony_ci# entries from the ATC. so, we do a second set of "plpa"s.
36108c2ecf20Sopenharmony_ci	plpar		(%a2)			# load atc for ADDR1
36118c2ecf20Sopenharmony_ci	plpar		(%a4)			# load atc for ADDR1+3
36128c2ecf20Sopenharmony_ci
36138c2ecf20Sopenharmony_ci# load the BUSCR values.
36148c2ecf20Sopenharmony_ci	mov.l		&0x80000000,%a2		# assert LOCK* buscr value
36158c2ecf20Sopenharmony_ci	mov.l		&0xa0000000,%a3		# assert LOCKE* buscr value
36168c2ecf20Sopenharmony_ci	mov.l		&0x00000000,%a4		# buscr unlock value
36178c2ecf20Sopenharmony_ci
36188c2ecf20Sopenharmony_ci# there are two possible mis-aligned cases for word cas. they
36198c2ecf20Sopenharmony_ci# are separated because the final write which asserts LOCKE* must
36208c2ecf20Sopenharmony_ci# be aligned.
36218c2ecf20Sopenharmony_ci	mov.l		%a0,%d0			# is ADDR1 misaligned?
36228c2ecf20Sopenharmony_ci	btst		&0x0,%d0
36238c2ecf20Sopenharmony_ci	bne.w		CAS2W2_ENTER		# yes
36248c2ecf20Sopenharmony_ci	bra.b		CAS2W_ENTER		# no
36258c2ecf20Sopenharmony_ci
36268c2ecf20Sopenharmony_ci#
36278c2ecf20Sopenharmony_ci# D0 = dst operand 1 <-
36288c2ecf20Sopenharmony_ci# D1 = dst operand 2 <-
36298c2ecf20Sopenharmony_ci# D2 = cmp operand 1
36308c2ecf20Sopenharmony_ci# D3 = cmp operand 2
36318c2ecf20Sopenharmony_ci# D4 = update oper 1
36328c2ecf20Sopenharmony_ci# D5 = update oper 2
36338c2ecf20Sopenharmony_ci# D6 = old SFC/DFC
36348c2ecf20Sopenharmony_ci# D7 = old SR
36358c2ecf20Sopenharmony_ci# A0 = ADDR1
36368c2ecf20Sopenharmony_ci# A1 = ADDR2
36378c2ecf20Sopenharmony_ci# A2 = bus LOCK*  value
36388c2ecf20Sopenharmony_ci# A3 = bus LOCKE* value
36398c2ecf20Sopenharmony_ci# A4 = bus unlock value
36408c2ecf20Sopenharmony_ci# A5 = xxxxxxxx
36418c2ecf20Sopenharmony_ci#
36428c2ecf20Sopenharmony_ci	align		0x10
36438c2ecf20Sopenharmony_ciCAS2W_START:
36448c2ecf20Sopenharmony_ci	movc		%a2,%buscr		# assert LOCK*
36458c2ecf20Sopenharmony_ci	movs.w		(%a1),%d1		# fetch Dest2[15:0]
36468c2ecf20Sopenharmony_ci	movs.w		(%a0),%d0		# fetch Dest1[15:0]
36478c2ecf20Sopenharmony_ci	bra.b		CAS2W_CONT2
36488c2ecf20Sopenharmony_ciCAS2W_ENTER:
36498c2ecf20Sopenharmony_ci	bra.b		~+16
36508c2ecf20Sopenharmony_ci
36518c2ecf20Sopenharmony_ciCAS2W_CONT2:
36528c2ecf20Sopenharmony_ci	cmp.w		%d0,%d2			# Dest1 - Compare1
36538c2ecf20Sopenharmony_ci	bne.b		CAS2W_NOUPDATE
36548c2ecf20Sopenharmony_ci	cmp.w		%d1,%d3			# Dest2 - Compare2
36558c2ecf20Sopenharmony_ci	bne.b		CAS2W_NOUPDATE
36568c2ecf20Sopenharmony_ci	movs.w		%d5,(%a1)		# Update2[15:0] -> DEST2
36578c2ecf20Sopenharmony_ci	bra.b		CAS2W_UPDATE
36588c2ecf20Sopenharmony_ci	bra.b		~+16
36598c2ecf20Sopenharmony_ci
36608c2ecf20Sopenharmony_ciCAS2W_UPDATE:
36618c2ecf20Sopenharmony_ci	movc		%a3,%buscr		# assert LOCKE*
36628c2ecf20Sopenharmony_ci	movs.w		%d4,(%a0)		# Update1[15:0] -> DEST1
36638c2ecf20Sopenharmony_ci	movc		%a4,%buscr		# unlock the bus
36648c2ecf20Sopenharmony_ci	bra.b		cas2w_update_done
36658c2ecf20Sopenharmony_ci	bra.b		~+16
36668c2ecf20Sopenharmony_ci
36678c2ecf20Sopenharmony_ciCAS2W_NOUPDATE:
36688c2ecf20Sopenharmony_ci	movc		%a3,%buscr		# assert LOCKE*
36698c2ecf20Sopenharmony_ci	movs.w		%d0,(%a0)		# Dest1[15:0] -> DEST1
36708c2ecf20Sopenharmony_ci	movc		%a4,%buscr		# unlock the bus
36718c2ecf20Sopenharmony_ci	bra.b		cas2w_noupdate_done
36728c2ecf20Sopenharmony_ci	bra.b		~+16
36738c2ecf20Sopenharmony_ci
36748c2ecf20Sopenharmony_ciCAS2W_FILLER:
36758c2ecf20Sopenharmony_ci	nop
36768c2ecf20Sopenharmony_ci	nop
36778c2ecf20Sopenharmony_ci	nop
36788c2ecf20Sopenharmony_ci	nop
36798c2ecf20Sopenharmony_ci	nop
36808c2ecf20Sopenharmony_ci	nop
36818c2ecf20Sopenharmony_ci	nop
36828c2ecf20Sopenharmony_ci	bra.b		CAS2W_START
36838c2ecf20Sopenharmony_ci
36848c2ecf20Sopenharmony_ci####
36858c2ecf20Sopenharmony_ci
36868c2ecf20Sopenharmony_ci#################################################################
36878c2ecf20Sopenharmony_ci# THIS MUST BE THE STATE OF THE INTEGER REGISTER FILE UPON	#
36888c2ecf20Sopenharmony_ci# ENTERING _isp_cas2().						#
36898c2ecf20Sopenharmony_ci#								#
36908c2ecf20Sopenharmony_ci# D0 = destination[15:0] operand 1				#
36918c2ecf20Sopenharmony_ci# D1 = destination[15:0] operand 2				#
36928c2ecf20Sopenharmony_ci# D2 = cmp[15:0] operand 1					#
36938c2ecf20Sopenharmony_ci# D3 = cmp[15:0] operand 2					#
36948c2ecf20Sopenharmony_ci# D4 = 'xxxxxx11 -> no reg update; 'xxxxxx00 -> update required	#
36958c2ecf20Sopenharmony_ci# D5 = xxxxxxxx							#
36968c2ecf20Sopenharmony_ci# D6 = xxxxxxxx							#
36978c2ecf20Sopenharmony_ci# D7 = xxxxxxxx							#
36988c2ecf20Sopenharmony_ci# A0 = xxxxxxxx							#
36998c2ecf20Sopenharmony_ci# A1 = xxxxxxxx							#
37008c2ecf20Sopenharmony_ci# A2 = xxxxxxxx							#
37018c2ecf20Sopenharmony_ci# A3 = xxxxxxxx							#
37028c2ecf20Sopenharmony_ci# A4 = xxxxxxxx							#
37038c2ecf20Sopenharmony_ci# A5 = xxxxxxxx							#
37048c2ecf20Sopenharmony_ci# A6 = frame pointer						#
37058c2ecf20Sopenharmony_ci# A7 = stack pointer						#
37068c2ecf20Sopenharmony_ci#################################################################
37078c2ecf20Sopenharmony_ci
37088c2ecf20Sopenharmony_cicas2w_noupdate_done:
37098c2ecf20Sopenharmony_ci
37108c2ecf20Sopenharmony_ci# restore previous SFC/DFC value.
37118c2ecf20Sopenharmony_ci	movc		%d6,%sfc		# restore old SFC
37128c2ecf20Sopenharmony_ci	movc		%d6,%dfc		# restore old DFC
37138c2ecf20Sopenharmony_ci
37148c2ecf20Sopenharmony_ci# restore previous interrupt mask level.
37158c2ecf20Sopenharmony_ci	mov.w		%d7,%sr			# restore old SR
37168c2ecf20Sopenharmony_ci
37178c2ecf20Sopenharmony_ci	sf		%d4			# indicate no update was done
37188c2ecf20Sopenharmony_ci	bra.l		_isp_cas2_finish
37198c2ecf20Sopenharmony_ci
37208c2ecf20Sopenharmony_cicas2w_update_done:
37218c2ecf20Sopenharmony_ci
37228c2ecf20Sopenharmony_ci# restore previous SFC/DFC value.
37238c2ecf20Sopenharmony_ci	movc		%d6,%sfc		# restore old SFC
37248c2ecf20Sopenharmony_ci	movc		%d6,%dfc		# restore old DFC
37258c2ecf20Sopenharmony_ci
37268c2ecf20Sopenharmony_ci# restore previous interrupt mask level.
37278c2ecf20Sopenharmony_ci	mov.w		%d7,%sr			# restore old SR
37288c2ecf20Sopenharmony_ci
37298c2ecf20Sopenharmony_ci	st		%d4			# indicate update was done
37308c2ecf20Sopenharmony_ci	bra.l		_isp_cas2_finish
37318c2ecf20Sopenharmony_ci####
37328c2ecf20Sopenharmony_ci
37338c2ecf20Sopenharmony_ci	align		0x10
37348c2ecf20Sopenharmony_ciCAS2W2_START:
37358c2ecf20Sopenharmony_ci	movc		%a2,%buscr		# assert LOCK*
37368c2ecf20Sopenharmony_ci	movs.w		(%a1),%d1		# fetch Dest2[15:0]
37378c2ecf20Sopenharmony_ci	movs.w		(%a0),%d0		# fetch Dest1[15:0]
37388c2ecf20Sopenharmony_ci	bra.b		CAS2W2_CONT2
37398c2ecf20Sopenharmony_ciCAS2W2_ENTER:
37408c2ecf20Sopenharmony_ci	bra.b		~+16
37418c2ecf20Sopenharmony_ci
37428c2ecf20Sopenharmony_ciCAS2W2_CONT2:
37438c2ecf20Sopenharmony_ci	cmp.w		%d0,%d2			# Dest1 - Compare1
37448c2ecf20Sopenharmony_ci	bne.b		CAS2W2_NOUPDATE
37458c2ecf20Sopenharmony_ci	cmp.w		%d1,%d3			# Dest2 - Compare2
37468c2ecf20Sopenharmony_ci	bne.b		CAS2W2_NOUPDATE
37478c2ecf20Sopenharmony_ci	movs.w		%d5,(%a1)		# Update2[15:0] -> DEST2
37488c2ecf20Sopenharmony_ci	bra.b		CAS2W2_UPDATE
37498c2ecf20Sopenharmony_ci	bra.b		~+16
37508c2ecf20Sopenharmony_ci
37518c2ecf20Sopenharmony_ciCAS2W2_UPDATE:
37528c2ecf20Sopenharmony_ci	ror.l		&0x8,%d4		# get Update1[15:8]
37538c2ecf20Sopenharmony_ci	movs.b		%d4,(%a0)+		# Update1[15:8] -> DEST1
37548c2ecf20Sopenharmony_ci	movc		%a3,%buscr		# assert LOCKE*
37558c2ecf20Sopenharmony_ci	rol.l		&0x8,%d4		# get Update1[7:0]
37568c2ecf20Sopenharmony_ci	bra.b		CAS2W2_UPDATE2
37578c2ecf20Sopenharmony_ci	bra.b		~+16
37588c2ecf20Sopenharmony_ci
37598c2ecf20Sopenharmony_ciCAS2W2_UPDATE2:
37608c2ecf20Sopenharmony_ci	movs.b		%d4,(%a0)		# Update1[7:0] -> DEST1+0x1
37618c2ecf20Sopenharmony_ci	movc		%a4,%buscr		# unlock the bus
37628c2ecf20Sopenharmony_ci	bra.w		cas2w_update_done
37638c2ecf20Sopenharmony_ci	nop
37648c2ecf20Sopenharmony_ci	bra.b		~+16
37658c2ecf20Sopenharmony_ci
37668c2ecf20Sopenharmony_ciCAS2W2_NOUPDATE:
37678c2ecf20Sopenharmony_ci	ror.l		&0x8,%d0		# get Dest1[15:8]
37688c2ecf20Sopenharmony_ci	movs.b		%d0,(%a0)+		# Dest1[15:8] -> DEST1
37698c2ecf20Sopenharmony_ci	movc		%a3,%buscr		# assert LOCKE*
37708c2ecf20Sopenharmony_ci	rol.l		&0x8,%d0		# get Dest1[7:0]
37718c2ecf20Sopenharmony_ci	bra.b		CAS2W2_NOUPDATE2
37728c2ecf20Sopenharmony_ci	bra.b		~+16
37738c2ecf20Sopenharmony_ci
37748c2ecf20Sopenharmony_ciCAS2W2_NOUPDATE2:
37758c2ecf20Sopenharmony_ci	movs.b		%d0,(%a0)		# Dest1[7:0] -> DEST1+0x1
37768c2ecf20Sopenharmony_ci	movc		%a4,%buscr		# unlock the bus
37778c2ecf20Sopenharmony_ci	bra.w		cas2w_noupdate_done
37788c2ecf20Sopenharmony_ci	nop
37798c2ecf20Sopenharmony_ci	bra.b		~+16
37808c2ecf20Sopenharmony_ci
37818c2ecf20Sopenharmony_ciCAS2W2_FILLER:
37828c2ecf20Sopenharmony_ci	nop
37838c2ecf20Sopenharmony_ci	nop
37848c2ecf20Sopenharmony_ci	nop
37858c2ecf20Sopenharmony_ci	nop
37868c2ecf20Sopenharmony_ci	nop
37878c2ecf20Sopenharmony_ci	nop
37888c2ecf20Sopenharmony_ci	nop
37898c2ecf20Sopenharmony_ci	bra.b		CAS2W2_START
37908c2ecf20Sopenharmony_ci
37918c2ecf20Sopenharmony_ci#       ######      ##      ######
37928c2ecf20Sopenharmony_ci#       #	   #  #     #
37938c2ecf20Sopenharmony_ci#	#	  ######    ######
37948c2ecf20Sopenharmony_ci#	#	  #    #         #
37958c2ecf20Sopenharmony_ci#       ######    #    #    ######
37968c2ecf20Sopenharmony_ci
37978c2ecf20Sopenharmony_ci#########################################################################
37988c2ecf20Sopenharmony_ci# XDEF ****************************************************************	#
37998c2ecf20Sopenharmony_ci#	_isp_cas(): "core" emulation code for the cas instruction	#
38008c2ecf20Sopenharmony_ci#									#
38018c2ecf20Sopenharmony_ci# XREF ****************************************************************	#
38028c2ecf20Sopenharmony_ci#	_isp_cas_finish() - only exit point for this emulation code;	#
38038c2ecf20Sopenharmony_ci#			    do clean-up					#
38048c2ecf20Sopenharmony_ci#									#
38058c2ecf20Sopenharmony_ci# INPUT ***************************************************************	#
38068c2ecf20Sopenharmony_ci#	*see entry chart below*						#
38078c2ecf20Sopenharmony_ci#									#
38088c2ecf20Sopenharmony_ci# OUTPUT **************************************************************	#
38098c2ecf20Sopenharmony_ci#	*see exit chart below*						#
38108c2ecf20Sopenharmony_ci#									#
38118c2ecf20Sopenharmony_ci# ALGORITHM ***********************************************************	#
38128c2ecf20Sopenharmony_ci#	(1) Make several copies of the effective address.		#
38138c2ecf20Sopenharmony_ci#	(2) Save current SR; Then mask off all maskable interrupts.	#
38148c2ecf20Sopenharmony_ci#	(3) Save current DFC/SFC (ASSUMED TO BE EQUAL!!!); Then set	#
38158c2ecf20Sopenharmony_ci#	    SFC/DFC according to whether exception occurred in user or	#
38168c2ecf20Sopenharmony_ci#	    supervisor mode.						#
38178c2ecf20Sopenharmony_ci#	(4) Use "plpaw" instruction to pre-load ATC with effective	#
38188c2ecf20Sopenharmony_ci#	    address page(s). THIS SHOULD NOT FAULT!!! The relevant	#
38198c2ecf20Sopenharmony_ci#	    page(s) should have been made resident prior to entering	#
38208c2ecf20Sopenharmony_ci#	    this routine.						#
38218c2ecf20Sopenharmony_ci#	(5) Push the operand lines from the cache w/ "cpushl".		#
38228c2ecf20Sopenharmony_ci#	    In the 68040, this was done within the locked region. In	#
38238c2ecf20Sopenharmony_ci#	    the 68060, it is done outside of the locked region.		#
38248c2ecf20Sopenharmony_ci#	(6) Pre-fetch the core emulation instructions by executing one	#
38258c2ecf20Sopenharmony_ci#	    branch within each physical line (16 bytes) of the code	#
38268c2ecf20Sopenharmony_ci#	    before actually executing the code.				#
38278c2ecf20Sopenharmony_ci#	(7) Load the BUSCR with the bus lock value.			#
38288c2ecf20Sopenharmony_ci#	(8) Fetch the source operand.					#
38298c2ecf20Sopenharmony_ci#	(9) Do the compare. If equal, go to step (12).			#
38308c2ecf20Sopenharmony_ci#	(10)Unequal. No update occurs. But, we do write the DST op back	#
38318c2ecf20Sopenharmony_ci#	    to itself (as w/ the '040) so we can gracefully unlock	#
38328c2ecf20Sopenharmony_ci#	    the bus (and assert LOCKE*) using BUSCR and the final move.	#
38338c2ecf20Sopenharmony_ci#	(11)Exit.							#
38348c2ecf20Sopenharmony_ci#	(12)Write update operand to the DST location. Use BUSCR to	#
38358c2ecf20Sopenharmony_ci#	    assert LOCKE* for the final write operation.		#
38368c2ecf20Sopenharmony_ci#	(13)Exit.							#
38378c2ecf20Sopenharmony_ci#									#
38388c2ecf20Sopenharmony_ci#	The algorithm is actually implemented slightly differently	#
38398c2ecf20Sopenharmony_ci# depending on the size of the operation and the misalignment of the	#
38408c2ecf20Sopenharmony_ci# operand. A misaligned operand must be written in aligned chunks or	#
38418c2ecf20Sopenharmony_ci# else the BUSCR register control gets confused.			#
38428c2ecf20Sopenharmony_ci#									#
38438c2ecf20Sopenharmony_ci#########################################################################
38448c2ecf20Sopenharmony_ci
38458c2ecf20Sopenharmony_ci#########################################################
38468c2ecf20Sopenharmony_ci# THIS IS THE STATE OF THE INTEGER REGISTER FILE UPON	#
38478c2ecf20Sopenharmony_ci# ENTERING _isp_cas().					#
38488c2ecf20Sopenharmony_ci#							#
38498c2ecf20Sopenharmony_ci# D0 = xxxxxxxx						#
38508c2ecf20Sopenharmony_ci# D1 = xxxxxxxx						#
38518c2ecf20Sopenharmony_ci# D2 = update operand					#
38528c2ecf20Sopenharmony_ci# D3 = xxxxxxxx						#
38538c2ecf20Sopenharmony_ci# D4 = compare operand					#
38548c2ecf20Sopenharmony_ci# D5 = xxxxxxxx						#
38558c2ecf20Sopenharmony_ci# D6 = supervisor ('xxxxxxff) or user mode ('xxxxxx00)	#
38568c2ecf20Sopenharmony_ci# D7 = longword ('xxxxxxff) or word size ('xxxxxx00)	#
38578c2ecf20Sopenharmony_ci# A0 = ADDR						#
38588c2ecf20Sopenharmony_ci# A1 = xxxxxxxx						#
38598c2ecf20Sopenharmony_ci# A2 = xxxxxxxx						#
38608c2ecf20Sopenharmony_ci# A3 = xxxxxxxx						#
38618c2ecf20Sopenharmony_ci# A4 = xxxxxxxx						#
38628c2ecf20Sopenharmony_ci# A5 = xxxxxxxx						#
38638c2ecf20Sopenharmony_ci# A6 = frame pointer					#
38648c2ecf20Sopenharmony_ci# A7 = stack pointer					#
38658c2ecf20Sopenharmony_ci#########################################################
38668c2ecf20Sopenharmony_ci
38678c2ecf20Sopenharmony_ci	global		_isp_cas
38688c2ecf20Sopenharmony_ci_isp_cas:
38698c2ecf20Sopenharmony_ci	tst.b		%d6			# user or supervisor mode?
38708c2ecf20Sopenharmony_ci	bne.b		cas_super		# supervisor
38718c2ecf20Sopenharmony_cicas_user:
38728c2ecf20Sopenharmony_ci	movq.l		&0x1,%d0		# load user data fc
38738c2ecf20Sopenharmony_ci	bra.b		cas_cont
38748c2ecf20Sopenharmony_cicas_super:
38758c2ecf20Sopenharmony_ci	movq.l		&0x5,%d0		# load supervisor data fc
38768c2ecf20Sopenharmony_ci
38778c2ecf20Sopenharmony_cicas_cont:
38788c2ecf20Sopenharmony_ci	tst.b		%d7			# word or longword?
38798c2ecf20Sopenharmony_ci	bne.w		casl			# longword
38808c2ecf20Sopenharmony_ci
38818c2ecf20Sopenharmony_ci####
38828c2ecf20Sopenharmony_cicasw:
38838c2ecf20Sopenharmony_ci	mov.l		%a0,%a1			# make copy for plpaw1
38848c2ecf20Sopenharmony_ci	mov.l		%a0,%a2			# make copy for plpaw2
38858c2ecf20Sopenharmony_ci	addq.l		&0x1,%a2		# plpaw2 points to end of word
38868c2ecf20Sopenharmony_ci
38878c2ecf20Sopenharmony_ci	mov.l		%d2,%d3			# d3 = update[7:0]
38888c2ecf20Sopenharmony_ci	lsr.w		&0x8,%d2		# d2 = update[15:8]
38898c2ecf20Sopenharmony_ci
38908c2ecf20Sopenharmony_ci# mask interrupt levels 0-6. save old mask value.
38918c2ecf20Sopenharmony_ci	mov.w		%sr,%d7			# save current SR
38928c2ecf20Sopenharmony_ci	ori.w		&0x0700,%sr		# inhibit interrupts
38938c2ecf20Sopenharmony_ci
38948c2ecf20Sopenharmony_ci# load the SFC and DFC with the appropriate mode.
38958c2ecf20Sopenharmony_ci	movc		%sfc,%d6		# save old SFC/DFC
38968c2ecf20Sopenharmony_ci	movc		%d0,%sfc		# load new sfc
38978c2ecf20Sopenharmony_ci	movc		%d0,%dfc		# load new dfc
38988c2ecf20Sopenharmony_ci
38998c2ecf20Sopenharmony_ci# pre-load the operand ATC. no page faults should occur here because
39008c2ecf20Sopenharmony_ci# _real_lock_page() should have taken care of this.
39018c2ecf20Sopenharmony_ci	plpaw		(%a1)			# load atc for ADDR
39028c2ecf20Sopenharmony_ci	plpaw		(%a2)			# load atc for ADDR+1
39038c2ecf20Sopenharmony_ci
39048c2ecf20Sopenharmony_ci# push the operand lines from the cache if they exist.
39058c2ecf20Sopenharmony_ci	cpushl		%dc,(%a1)		# push dirty data
39068c2ecf20Sopenharmony_ci	cpushl		%dc,(%a2)		# push dirty data
39078c2ecf20Sopenharmony_ci
39088c2ecf20Sopenharmony_ci# load the BUSCR values.
39098c2ecf20Sopenharmony_ci	mov.l		&0x80000000,%a1		# assert LOCK* buscr value
39108c2ecf20Sopenharmony_ci	mov.l		&0xa0000000,%a2		# assert LOCKE* buscr value
39118c2ecf20Sopenharmony_ci	mov.l		&0x00000000,%a3		# buscr unlock value
39128c2ecf20Sopenharmony_ci
39138c2ecf20Sopenharmony_ci# pre-load the instruction cache for the following algorithm.
39148c2ecf20Sopenharmony_ci# this will minimize the number of cycles that LOCK* will be asserted.
39158c2ecf20Sopenharmony_ci	bra.b		CASW_ENTER		# start pre-loading icache
39168c2ecf20Sopenharmony_ci
39178c2ecf20Sopenharmony_ci#
39188c2ecf20Sopenharmony_ci# D0 = dst operand <-
39198c2ecf20Sopenharmony_ci# D1 = update[15:8] operand
39208c2ecf20Sopenharmony_ci# D2 = update[7:0]  operand
39218c2ecf20Sopenharmony_ci# D3 = xxxxxxxx
39228c2ecf20Sopenharmony_ci# D4 = compare[15:0] operand
39238c2ecf20Sopenharmony_ci# D5 = xxxxxxxx
39248c2ecf20Sopenharmony_ci# D6 = old SFC/DFC
39258c2ecf20Sopenharmony_ci# D7 = old SR
39268c2ecf20Sopenharmony_ci# A0 = ADDR
39278c2ecf20Sopenharmony_ci# A1 = bus LOCK*  value
39288c2ecf20Sopenharmony_ci# A2 = bus LOCKE* value
39298c2ecf20Sopenharmony_ci# A3 = bus unlock value
39308c2ecf20Sopenharmony_ci# A4 = xxxxxxxx
39318c2ecf20Sopenharmony_ci# A5 = xxxxxxxx
39328c2ecf20Sopenharmony_ci#
39338c2ecf20Sopenharmony_ci	align		0x10
39348c2ecf20Sopenharmony_ciCASW_START:
39358c2ecf20Sopenharmony_ci	movc		%a1,%buscr		# assert LOCK*
39368c2ecf20Sopenharmony_ci	movs.w		(%a0),%d0		# fetch Dest[15:0]
39378c2ecf20Sopenharmony_ci	cmp.w		%d0,%d4			# Dest - Compare
39388c2ecf20Sopenharmony_ci	bne.b		CASW_NOUPDATE
39398c2ecf20Sopenharmony_ci	bra.b		CASW_UPDATE
39408c2ecf20Sopenharmony_ciCASW_ENTER:
39418c2ecf20Sopenharmony_ci	bra.b		~+16
39428c2ecf20Sopenharmony_ci
39438c2ecf20Sopenharmony_ciCASW_UPDATE:
39448c2ecf20Sopenharmony_ci	movs.b		%d2,(%a0)+		# Update[15:8] -> DEST
39458c2ecf20Sopenharmony_ci	movc		%a2,%buscr		# assert LOCKE*
39468c2ecf20Sopenharmony_ci	movs.b		%d3,(%a0)		# Update[7:0] -> DEST+0x1
39478c2ecf20Sopenharmony_ci	bra.b		CASW_UPDATE2
39488c2ecf20Sopenharmony_ci	bra.b		~+16
39498c2ecf20Sopenharmony_ci
39508c2ecf20Sopenharmony_ciCASW_UPDATE2:
39518c2ecf20Sopenharmony_ci	movc		%a3,%buscr		# unlock the bus
39528c2ecf20Sopenharmony_ci	bra.b		casw_update_done
39538c2ecf20Sopenharmony_ci	nop
39548c2ecf20Sopenharmony_ci	nop
39558c2ecf20Sopenharmony_ci	nop
39568c2ecf20Sopenharmony_ci	nop
39578c2ecf20Sopenharmony_ci	bra.b		~+16
39588c2ecf20Sopenharmony_ci
39598c2ecf20Sopenharmony_ciCASW_NOUPDATE:
39608c2ecf20Sopenharmony_ci	ror.l		&0x8,%d0		# get Dest[15:8]
39618c2ecf20Sopenharmony_ci	movs.b		%d0,(%a0)+		# Dest[15:8] -> DEST
39628c2ecf20Sopenharmony_ci	movc		%a2,%buscr		# assert LOCKE*
39638c2ecf20Sopenharmony_ci	rol.l		&0x8,%d0		# get Dest[7:0]
39648c2ecf20Sopenharmony_ci	bra.b		CASW_NOUPDATE2
39658c2ecf20Sopenharmony_ci	bra.b		~+16
39668c2ecf20Sopenharmony_ci
39678c2ecf20Sopenharmony_ciCASW_NOUPDATE2:
39688c2ecf20Sopenharmony_ci	movs.b		%d0,(%a0)		# Dest[7:0] -> DEST+0x1
39698c2ecf20Sopenharmony_ci	movc		%a3,%buscr		# unlock the bus
39708c2ecf20Sopenharmony_ci	bra.b		casw_noupdate_done
39718c2ecf20Sopenharmony_ci	nop
39728c2ecf20Sopenharmony_ci	nop
39738c2ecf20Sopenharmony_ci	bra.b		~+16
39748c2ecf20Sopenharmony_ci
39758c2ecf20Sopenharmony_ciCASW_FILLER:
39768c2ecf20Sopenharmony_ci	nop
39778c2ecf20Sopenharmony_ci	nop
39788c2ecf20Sopenharmony_ci	nop
39798c2ecf20Sopenharmony_ci	nop
39808c2ecf20Sopenharmony_ci	nop
39818c2ecf20Sopenharmony_ci	nop
39828c2ecf20Sopenharmony_ci	nop
39838c2ecf20Sopenharmony_ci	bra.b		CASW_START
39848c2ecf20Sopenharmony_ci
39858c2ecf20Sopenharmony_ci#################################################################
39868c2ecf20Sopenharmony_ci# THIS MUST BE THE STATE OF THE INTEGER REGISTER FILE UPON	#
39878c2ecf20Sopenharmony_ci# CALLING _isp_cas_finish().					#
39888c2ecf20Sopenharmony_ci#								#
39898c2ecf20Sopenharmony_ci# D0 = destination[15:0] operand				#
39908c2ecf20Sopenharmony_ci# D1 = 'xxxxxx11 -> no reg update; 'xxxxxx00 -> update required	#
39918c2ecf20Sopenharmony_ci# D2 = xxxxxxxx							#
39928c2ecf20Sopenharmony_ci# D3 = xxxxxxxx							#
39938c2ecf20Sopenharmony_ci# D4 = compare[15:0] operand					#
39948c2ecf20Sopenharmony_ci# D5 = xxxxxxxx							#
39958c2ecf20Sopenharmony_ci# D6 = xxxxxxxx							#
39968c2ecf20Sopenharmony_ci# D7 = xxxxxxxx							#
39978c2ecf20Sopenharmony_ci# A0 = xxxxxxxx							#
39988c2ecf20Sopenharmony_ci# A1 = xxxxxxxx							#
39998c2ecf20Sopenharmony_ci# A2 = xxxxxxxx							#
40008c2ecf20Sopenharmony_ci# A3 = xxxxxxxx							#
40018c2ecf20Sopenharmony_ci# A4 = xxxxxxxx							#
40028c2ecf20Sopenharmony_ci# A5 = xxxxxxxx							#
40038c2ecf20Sopenharmony_ci# A6 = frame pointer						#
40048c2ecf20Sopenharmony_ci# A7 = stack pointer						#
40058c2ecf20Sopenharmony_ci#################################################################
40068c2ecf20Sopenharmony_ci
40078c2ecf20Sopenharmony_cicasw_noupdate_done:
40088c2ecf20Sopenharmony_ci
40098c2ecf20Sopenharmony_ci# restore previous SFC/DFC value.
40108c2ecf20Sopenharmony_ci	movc		%d6,%sfc		# restore old SFC
40118c2ecf20Sopenharmony_ci	movc		%d6,%dfc		# restore old DFC
40128c2ecf20Sopenharmony_ci
40138c2ecf20Sopenharmony_ci# restore previous interrupt mask level.
40148c2ecf20Sopenharmony_ci	mov.w		%d7,%sr			# restore old SR
40158c2ecf20Sopenharmony_ci
40168c2ecf20Sopenharmony_ci	sf		%d1			# indicate no update was done
40178c2ecf20Sopenharmony_ci	bra.l		_isp_cas_finish
40188c2ecf20Sopenharmony_ci
40198c2ecf20Sopenharmony_cicasw_update_done:
40208c2ecf20Sopenharmony_ci
40218c2ecf20Sopenharmony_ci# restore previous SFC/DFC value.
40228c2ecf20Sopenharmony_ci	movc		%d6,%sfc		# restore old SFC
40238c2ecf20Sopenharmony_ci	movc		%d6,%dfc		# restore old DFC
40248c2ecf20Sopenharmony_ci
40258c2ecf20Sopenharmony_ci# restore previous interrupt mask level.
40268c2ecf20Sopenharmony_ci	mov.w		%d7,%sr			# restore old SR
40278c2ecf20Sopenharmony_ci
40288c2ecf20Sopenharmony_ci	st		%d1			# indicate update was done
40298c2ecf20Sopenharmony_ci	bra.l		_isp_cas_finish
40308c2ecf20Sopenharmony_ci
40318c2ecf20Sopenharmony_ci################
40328c2ecf20Sopenharmony_ci
40338c2ecf20Sopenharmony_ci# there are two possible mis-aligned cases for longword cas. they
40348c2ecf20Sopenharmony_ci# are separated because the final write which asserts LOCKE* must
40358c2ecf20Sopenharmony_ci# be an aligned write.
40368c2ecf20Sopenharmony_cicasl:
40378c2ecf20Sopenharmony_ci	mov.l		%a0,%a1			# make copy for plpaw1
40388c2ecf20Sopenharmony_ci	mov.l		%a0,%a2			# make copy for plpaw2
40398c2ecf20Sopenharmony_ci	addq.l		&0x3,%a2		# plpaw2 points to end of longword
40408c2ecf20Sopenharmony_ci
40418c2ecf20Sopenharmony_ci	mov.l		%a0,%d1			# byte or word misaligned?
40428c2ecf20Sopenharmony_ci	btst		&0x0,%d1
40438c2ecf20Sopenharmony_ci	bne.w		casl2			# byte misaligned
40448c2ecf20Sopenharmony_ci
40458c2ecf20Sopenharmony_ci	mov.l		%d2,%d3			# d3 = update[15:0]
40468c2ecf20Sopenharmony_ci	swap		%d2			# d2 = update[31:16]
40478c2ecf20Sopenharmony_ci
40488c2ecf20Sopenharmony_ci# mask interrupts levels 0-6. save old mask value.
40498c2ecf20Sopenharmony_ci	mov.w		%sr,%d7			# save current SR
40508c2ecf20Sopenharmony_ci	ori.w		&0x0700,%sr		# inhibit interrupts
40518c2ecf20Sopenharmony_ci
40528c2ecf20Sopenharmony_ci# load the SFC and DFC with the appropriate mode.
40538c2ecf20Sopenharmony_ci	movc		%sfc,%d6		# save old SFC/DFC
40548c2ecf20Sopenharmony_ci	movc		%d0,%sfc		# load new sfc
40558c2ecf20Sopenharmony_ci	movc		%d0,%dfc		# load new dfc
40568c2ecf20Sopenharmony_ci
40578c2ecf20Sopenharmony_ci# pre-load the operand ATC. no page faults should occur here because
40588c2ecf20Sopenharmony_ci# _real_lock_page() should have taken care of this.
40598c2ecf20Sopenharmony_ci	plpaw		(%a1)			# load atc for ADDR
40608c2ecf20Sopenharmony_ci	plpaw		(%a2)			# load atc for ADDR+3
40618c2ecf20Sopenharmony_ci
40628c2ecf20Sopenharmony_ci# push the operand lines from the cache if they exist.
40638c2ecf20Sopenharmony_ci	cpushl		%dc,(%a1)		# push dirty data
40648c2ecf20Sopenharmony_ci	cpushl		%dc,(%a2)		# push dirty data
40658c2ecf20Sopenharmony_ci
40668c2ecf20Sopenharmony_ci# load the BUSCR values.
40678c2ecf20Sopenharmony_ci	mov.l		&0x80000000,%a1		# assert LOCK* buscr value
40688c2ecf20Sopenharmony_ci	mov.l		&0xa0000000,%a2		# assert LOCKE* buscr value
40698c2ecf20Sopenharmony_ci	mov.l		&0x00000000,%a3		# buscr unlock value
40708c2ecf20Sopenharmony_ci
40718c2ecf20Sopenharmony_ci	bra.b		CASL_ENTER		# start pre-loading icache
40728c2ecf20Sopenharmony_ci
40738c2ecf20Sopenharmony_ci#
40748c2ecf20Sopenharmony_ci# D0 = dst operand <-
40758c2ecf20Sopenharmony_ci# D1 = xxxxxxxx
40768c2ecf20Sopenharmony_ci# D2 = update[31:16] operand
40778c2ecf20Sopenharmony_ci# D3 = update[15:0]  operand
40788c2ecf20Sopenharmony_ci# D4 = compare[31:0] operand
40798c2ecf20Sopenharmony_ci# D5 = xxxxxxxx
40808c2ecf20Sopenharmony_ci# D6 = old SFC/DFC
40818c2ecf20Sopenharmony_ci# D7 = old SR
40828c2ecf20Sopenharmony_ci# A0 = ADDR
40838c2ecf20Sopenharmony_ci# A1 = bus LOCK*  value
40848c2ecf20Sopenharmony_ci# A2 = bus LOCKE* value
40858c2ecf20Sopenharmony_ci# A3 = bus unlock value
40868c2ecf20Sopenharmony_ci# A4 = xxxxxxxx
40878c2ecf20Sopenharmony_ci# A5 = xxxxxxxx
40888c2ecf20Sopenharmony_ci#
40898c2ecf20Sopenharmony_ci	align		0x10
40908c2ecf20Sopenharmony_ciCASL_START:
40918c2ecf20Sopenharmony_ci	movc		%a1,%buscr		# assert LOCK*
40928c2ecf20Sopenharmony_ci	movs.l		(%a0),%d0		# fetch Dest[31:0]
40938c2ecf20Sopenharmony_ci	cmp.l		%d0,%d4			# Dest - Compare
40948c2ecf20Sopenharmony_ci	bne.b		CASL_NOUPDATE
40958c2ecf20Sopenharmony_ci	bra.b		CASL_UPDATE
40968c2ecf20Sopenharmony_ciCASL_ENTER:
40978c2ecf20Sopenharmony_ci	bra.b		~+16
40988c2ecf20Sopenharmony_ci
40998c2ecf20Sopenharmony_ciCASL_UPDATE:
41008c2ecf20Sopenharmony_ci	movs.w		%d2,(%a0)+		# Update[31:16] -> DEST
41018c2ecf20Sopenharmony_ci	movc		%a2,%buscr		# assert LOCKE*
41028c2ecf20Sopenharmony_ci	movs.w		%d3,(%a0)		# Update[15:0] -> DEST+0x2
41038c2ecf20Sopenharmony_ci	bra.b		CASL_UPDATE2
41048c2ecf20Sopenharmony_ci	bra.b		~+16
41058c2ecf20Sopenharmony_ci
41068c2ecf20Sopenharmony_ciCASL_UPDATE2:
41078c2ecf20Sopenharmony_ci	movc		%a3,%buscr		# unlock the bus
41088c2ecf20Sopenharmony_ci	bra.b		casl_update_done
41098c2ecf20Sopenharmony_ci	nop
41108c2ecf20Sopenharmony_ci	nop
41118c2ecf20Sopenharmony_ci	nop
41128c2ecf20Sopenharmony_ci	nop
41138c2ecf20Sopenharmony_ci	bra.b		~+16
41148c2ecf20Sopenharmony_ci
41158c2ecf20Sopenharmony_ciCASL_NOUPDATE:
41168c2ecf20Sopenharmony_ci	swap		%d0			# get Dest[31:16]
41178c2ecf20Sopenharmony_ci	movs.w		%d0,(%a0)+		# Dest[31:16] -> DEST
41188c2ecf20Sopenharmony_ci	swap		%d0			# get Dest[15:0]
41198c2ecf20Sopenharmony_ci	movc		%a2,%buscr		# assert LOCKE*
41208c2ecf20Sopenharmony_ci	bra.b		CASL_NOUPDATE2
41218c2ecf20Sopenharmony_ci	bra.b		~+16
41228c2ecf20Sopenharmony_ci
41238c2ecf20Sopenharmony_ciCASL_NOUPDATE2:
41248c2ecf20Sopenharmony_ci	movs.w		%d0,(%a0)		# Dest[15:0] -> DEST+0x2
41258c2ecf20Sopenharmony_ci	movc		%a3,%buscr		# unlock the bus
41268c2ecf20Sopenharmony_ci	bra.b		casl_noupdate_done
41278c2ecf20Sopenharmony_ci	nop
41288c2ecf20Sopenharmony_ci	nop
41298c2ecf20Sopenharmony_ci	bra.b		~+16
41308c2ecf20Sopenharmony_ci
41318c2ecf20Sopenharmony_ciCASL_FILLER:
41328c2ecf20Sopenharmony_ci	nop
41338c2ecf20Sopenharmony_ci	nop
41348c2ecf20Sopenharmony_ci	nop
41358c2ecf20Sopenharmony_ci	nop
41368c2ecf20Sopenharmony_ci	nop
41378c2ecf20Sopenharmony_ci	nop
41388c2ecf20Sopenharmony_ci	nop
41398c2ecf20Sopenharmony_ci	bra.b		CASL_START
41408c2ecf20Sopenharmony_ci
41418c2ecf20Sopenharmony_ci#################################################################
41428c2ecf20Sopenharmony_ci# THIS MUST BE THE STATE OF THE INTEGER REGISTER FILE UPON	#
41438c2ecf20Sopenharmony_ci# CALLING _isp_cas_finish().					#
41448c2ecf20Sopenharmony_ci#								#
41458c2ecf20Sopenharmony_ci# D0 = destination[31:0] operand				#
41468c2ecf20Sopenharmony_ci# D1 = 'xxxxxx11 -> no reg update; 'xxxxxx00 -> update required	#
41478c2ecf20Sopenharmony_ci# D2 = xxxxxxxx							#
41488c2ecf20Sopenharmony_ci# D3 = xxxxxxxx							#
41498c2ecf20Sopenharmony_ci# D4 = compare[31:0] operand					#
41508c2ecf20Sopenharmony_ci# D5 = xxxxxxxx							#
41518c2ecf20Sopenharmony_ci# D6 = xxxxxxxx							#
41528c2ecf20Sopenharmony_ci# D7 = xxxxxxxx							#
41538c2ecf20Sopenharmony_ci# A0 = xxxxxxxx							#
41548c2ecf20Sopenharmony_ci# A1 = xxxxxxxx							#
41558c2ecf20Sopenharmony_ci# A2 = xxxxxxxx							#
41568c2ecf20Sopenharmony_ci# A3 = xxxxxxxx							#
41578c2ecf20Sopenharmony_ci# A4 = xxxxxxxx							#
41588c2ecf20Sopenharmony_ci# A5 = xxxxxxxx							#
41598c2ecf20Sopenharmony_ci# A6 = frame pointer						#
41608c2ecf20Sopenharmony_ci# A7 = stack pointer						#
41618c2ecf20Sopenharmony_ci#################################################################
41628c2ecf20Sopenharmony_ci
41638c2ecf20Sopenharmony_cicasl_noupdate_done:
41648c2ecf20Sopenharmony_ci
41658c2ecf20Sopenharmony_ci# restore previous SFC/DFC value.
41668c2ecf20Sopenharmony_ci	movc		%d6,%sfc		# restore old SFC
41678c2ecf20Sopenharmony_ci	movc		%d6,%dfc		# restore old DFC
41688c2ecf20Sopenharmony_ci
41698c2ecf20Sopenharmony_ci# restore previous interrupt mask level.
41708c2ecf20Sopenharmony_ci	mov.w		%d7,%sr			# restore old SR
41718c2ecf20Sopenharmony_ci
41728c2ecf20Sopenharmony_ci	sf		%d1			# indicate no update was done
41738c2ecf20Sopenharmony_ci	bra.l		_isp_cas_finish
41748c2ecf20Sopenharmony_ci
41758c2ecf20Sopenharmony_cicasl_update_done:
41768c2ecf20Sopenharmony_ci
41778c2ecf20Sopenharmony_ci# restore previous SFC/DFC value.
41788c2ecf20Sopenharmony_ci	movc		%d6,%sfc		# restore old SFC
41798c2ecf20Sopenharmony_ci	movc		%d6,%dfc		# restore old DFC
41808c2ecf20Sopenharmony_ci
41818c2ecf20Sopenharmony_ci# restore previous interrupts mask level.
41828c2ecf20Sopenharmony_ci	mov.w		%d7,%sr			# restore old SR
41838c2ecf20Sopenharmony_ci
41848c2ecf20Sopenharmony_ci	st		%d1			# indicate update was done
41858c2ecf20Sopenharmony_ci	bra.l		_isp_cas_finish
41868c2ecf20Sopenharmony_ci
41878c2ecf20Sopenharmony_ci#######################################
41888c2ecf20Sopenharmony_cicasl2:
41898c2ecf20Sopenharmony_ci	mov.l		%d2,%d5			# d5 = Update[7:0]
41908c2ecf20Sopenharmony_ci	lsr.l		&0x8,%d2
41918c2ecf20Sopenharmony_ci	mov.l		%d2,%d3			# d3 = Update[23:8]
41928c2ecf20Sopenharmony_ci	swap		%d2			# d2 = Update[31:24]
41938c2ecf20Sopenharmony_ci
41948c2ecf20Sopenharmony_ci# mask interrupts levels 0-6. save old mask value.
41958c2ecf20Sopenharmony_ci	mov.w		%sr,%d7			# save current SR
41968c2ecf20Sopenharmony_ci	ori.w		&0x0700,%sr		# inhibit interrupts
41978c2ecf20Sopenharmony_ci
41988c2ecf20Sopenharmony_ci# load the SFC and DFC with the appropriate mode.
41998c2ecf20Sopenharmony_ci	movc		%sfc,%d6		# save old SFC/DFC
42008c2ecf20Sopenharmony_ci	movc		%d0,%sfc		# load new sfc
42018c2ecf20Sopenharmony_ci	movc		%d0,%dfc		# load new dfc
42028c2ecf20Sopenharmony_ci
42038c2ecf20Sopenharmony_ci# pre-load the operand ATC. no page faults should occur here because
42048c2ecf20Sopenharmony_ci# _real_lock_page() should have taken care of this already.
42058c2ecf20Sopenharmony_ci	plpaw		(%a1)			# load atc for ADDR
42068c2ecf20Sopenharmony_ci	plpaw		(%a2)			# load atc for ADDR+3
42078c2ecf20Sopenharmony_ci
42088c2ecf20Sopenharmony_ci# puch the operand lines from the cache if they exist.
42098c2ecf20Sopenharmony_ci	cpushl		%dc,(%a1)		# push dirty data
42108c2ecf20Sopenharmony_ci	cpushl		%dc,(%a2)		# push dirty data
42118c2ecf20Sopenharmony_ci
42128c2ecf20Sopenharmony_ci# load the BUSCR values.
42138c2ecf20Sopenharmony_ci	mov.l		&0x80000000,%a1		# assert LOCK* buscr value
42148c2ecf20Sopenharmony_ci	mov.l		&0xa0000000,%a2		# assert LOCKE* buscr value
42158c2ecf20Sopenharmony_ci	mov.l		&0x00000000,%a3		# buscr unlock value
42168c2ecf20Sopenharmony_ci
42178c2ecf20Sopenharmony_ci# pre-load the instruction cache for the following algorithm.
42188c2ecf20Sopenharmony_ci# this will minimize the number of cycles that LOCK* will be asserted.
42198c2ecf20Sopenharmony_ci	bra.b		CASL2_ENTER		# start pre-loading icache
42208c2ecf20Sopenharmony_ci
42218c2ecf20Sopenharmony_ci#
42228c2ecf20Sopenharmony_ci# D0 = dst operand <-
42238c2ecf20Sopenharmony_ci# D1 = xxxxxxxx
42248c2ecf20Sopenharmony_ci# D2 = update[31:24] operand
42258c2ecf20Sopenharmony_ci# D3 = update[23:8]  operand
42268c2ecf20Sopenharmony_ci# D4 = compare[31:0] operand
42278c2ecf20Sopenharmony_ci# D5 = update[7:0]  operand
42288c2ecf20Sopenharmony_ci# D6 = old SFC/DFC
42298c2ecf20Sopenharmony_ci# D7 = old SR
42308c2ecf20Sopenharmony_ci# A0 = ADDR
42318c2ecf20Sopenharmony_ci# A1 = bus LOCK*  value
42328c2ecf20Sopenharmony_ci# A2 = bus LOCKE* value
42338c2ecf20Sopenharmony_ci# A3 = bus unlock value
42348c2ecf20Sopenharmony_ci# A4 = xxxxxxxx
42358c2ecf20Sopenharmony_ci# A5 = xxxxxxxx
42368c2ecf20Sopenharmony_ci#
42378c2ecf20Sopenharmony_ci	align		0x10
42388c2ecf20Sopenharmony_ciCASL2_START:
42398c2ecf20Sopenharmony_ci	movc		%a1,%buscr		# assert LOCK*
42408c2ecf20Sopenharmony_ci	movs.l		(%a0),%d0		# fetch Dest[31:0]
42418c2ecf20Sopenharmony_ci	cmp.l		%d0,%d4			# Dest - Compare
42428c2ecf20Sopenharmony_ci	bne.b		CASL2_NOUPDATE
42438c2ecf20Sopenharmony_ci	bra.b		CASL2_UPDATE
42448c2ecf20Sopenharmony_ciCASL2_ENTER:
42458c2ecf20Sopenharmony_ci	bra.b		~+16
42468c2ecf20Sopenharmony_ci
42478c2ecf20Sopenharmony_ciCASL2_UPDATE:
42488c2ecf20Sopenharmony_ci	movs.b		%d2,(%a0)+		# Update[31:24] -> DEST
42498c2ecf20Sopenharmony_ci	movs.w		%d3,(%a0)+		# Update[23:8] -> DEST+0x1
42508c2ecf20Sopenharmony_ci	movc		%a2,%buscr		# assert LOCKE*
42518c2ecf20Sopenharmony_ci	bra.b		CASL2_UPDATE2
42528c2ecf20Sopenharmony_ci	bra.b		~+16
42538c2ecf20Sopenharmony_ci
42548c2ecf20Sopenharmony_ciCASL2_UPDATE2:
42558c2ecf20Sopenharmony_ci	movs.b		%d5,(%a0)		# Update[7:0] -> DEST+0x3
42568c2ecf20Sopenharmony_ci	movc		%a3,%buscr		# unlock the bus
42578c2ecf20Sopenharmony_ci	bra.w		casl_update_done
42588c2ecf20Sopenharmony_ci	nop
42598c2ecf20Sopenharmony_ci	bra.b		~+16
42608c2ecf20Sopenharmony_ci
42618c2ecf20Sopenharmony_ciCASL2_NOUPDATE:
42628c2ecf20Sopenharmony_ci	rol.l		&0x8,%d0		# get Dest[31:24]
42638c2ecf20Sopenharmony_ci	movs.b		%d0,(%a0)+		# Dest[31:24] -> DEST
42648c2ecf20Sopenharmony_ci	swap		%d0			# get Dest[23:8]
42658c2ecf20Sopenharmony_ci	movs.w		%d0,(%a0)+		# Dest[23:8] -> DEST+0x1
42668c2ecf20Sopenharmony_ci	bra.b		CASL2_NOUPDATE2
42678c2ecf20Sopenharmony_ci	bra.b		~+16
42688c2ecf20Sopenharmony_ci
42698c2ecf20Sopenharmony_ciCASL2_NOUPDATE2:
42708c2ecf20Sopenharmony_ci	rol.l		&0x8,%d0		# get Dest[7:0]
42718c2ecf20Sopenharmony_ci	movc		%a2,%buscr		# assert LOCKE*
42728c2ecf20Sopenharmony_ci	movs.b		%d0,(%a0)		# Dest[7:0] -> DEST+0x3
42738c2ecf20Sopenharmony_ci	bra.b		CASL2_NOUPDATE3
42748c2ecf20Sopenharmony_ci	nop
42758c2ecf20Sopenharmony_ci	bra.b		~+16
42768c2ecf20Sopenharmony_ci
42778c2ecf20Sopenharmony_ciCASL2_NOUPDATE3:
42788c2ecf20Sopenharmony_ci	movc		%a3,%buscr		# unlock the bus
42798c2ecf20Sopenharmony_ci	bra.w		casl_noupdate_done
42808c2ecf20Sopenharmony_ci	nop
42818c2ecf20Sopenharmony_ci	nop
42828c2ecf20Sopenharmony_ci	nop
42838c2ecf20Sopenharmony_ci	bra.b		~+16
42848c2ecf20Sopenharmony_ci
42858c2ecf20Sopenharmony_ciCASL2_FILLER:
42868c2ecf20Sopenharmony_ci	nop
42878c2ecf20Sopenharmony_ci	nop
42888c2ecf20Sopenharmony_ci	nop
42898c2ecf20Sopenharmony_ci	nop
42908c2ecf20Sopenharmony_ci	nop
42918c2ecf20Sopenharmony_ci	nop
42928c2ecf20Sopenharmony_ci	nop
42938c2ecf20Sopenharmony_ci	bra.b		CASL2_START
42948c2ecf20Sopenharmony_ci
42958c2ecf20Sopenharmony_ci####
42968c2ecf20Sopenharmony_ci####
42978c2ecf20Sopenharmony_ci# end label used by _isp_cas_inrange()
42988c2ecf20Sopenharmony_ci	global		_CASHI
42998c2ecf20Sopenharmony_ci_CASHI:
4300