xref: /openbmc/linux/arch/m68k/ifpsp060/src/isp.S (revision a976c2951d8f376112361830aa7762beff83a205)
11da177e4SLinus Torvalds~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
21da177e4SLinus TorvaldsMOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
31da177e4SLinus TorvaldsM68000 Hi-Performance Microprocessor Division
41da177e4SLinus TorvaldsM68060 Software Package
51da177e4SLinus TorvaldsProduction Release P1.00 -- October 10, 1994
61da177e4SLinus Torvalds
796de0e25SJan EngelhardtM68060 Software Package Copyright © 1993, 1994 Motorola Inc.  All rights reserved.
81da177e4SLinus Torvalds
91da177e4SLinus TorvaldsTHE SOFTWARE is provided on an "AS IS" basis and without warranty.
101da177e4SLinus TorvaldsTo the maximum extent permitted by applicable law,
111da177e4SLinus TorvaldsMOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
121da177e4SLinus TorvaldsINCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
131da177e4SLinus Torvaldsand any warranty against infringement with regard to the SOFTWARE
141da177e4SLinus Torvalds(INCLUDING ANY MODIFIED VERSIONS THEREOF) and any accompanying written materials.
151da177e4SLinus Torvalds
161da177e4SLinus TorvaldsTo the maximum extent permitted by applicable law,
171da177e4SLinus TorvaldsIN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
181da177e4SLinus Torvalds(INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS,
191da177e4SLinus TorvaldsBUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS)
201da177e4SLinus TorvaldsARISING OF THE USE OR INABILITY TO USE THE SOFTWARE.
211da177e4SLinus TorvaldsMotorola assumes no responsibility for the maintenance and support of the SOFTWARE.
221da177e4SLinus Torvalds
231da177e4SLinus TorvaldsYou are hereby granted a copyright license to use, modify, and distribute the SOFTWARE
241da177e4SLinus Torvaldsso long as this entire notice is retained without alteration in any modified and/or
251da177e4SLinus Torvaldsredistributed versions, and that such modified versions are clearly identified as such.
261da177e4SLinus TorvaldsNo licenses are granted by implication, estoppel or otherwise under any patents
271da177e4SLinus Torvaldsor trademarks of Motorola, Inc.
281da177e4SLinus Torvalds~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
291da177e4SLinus Torvalds# ireal.s:
301da177e4SLinus Torvalds#	This file is appended to the top of the 060ISP package
311da177e4SLinus Torvalds# and contains the entry points into the package. The user, in
321da177e4SLinus Torvalds# effect, branches to one of the branch table entries located
331da177e4SLinus Torvalds# after _060ISP_TABLE.
341da177e4SLinus Torvalds#	Also, subroutine stubs exist in this file (_isp_done for
351da177e4SLinus Torvalds# example) that are referenced by the ISP package itself in order
361da177e4SLinus Torvalds# to call a given routine. The stub routine actually performs the
371da177e4SLinus Torvalds# callout. The ISP code does a "bsr" to the stub routine. This
381da177e4SLinus Torvalds# extra layer of hierarchy adds a slight performance penalty but
391da177e4SLinus Torvalds# it makes the ISP code easier to read and more mainatinable.
401da177e4SLinus Torvalds#
411da177e4SLinus Torvalds
421da177e4SLinus Torvaldsset	_off_chk,	0x00
431da177e4SLinus Torvaldsset	_off_divbyzero,	0x04
441da177e4SLinus Torvaldsset	_off_trace,	0x08
451da177e4SLinus Torvaldsset	_off_access,	0x0c
461da177e4SLinus Torvaldsset	_off_done,	0x10
471da177e4SLinus Torvalds
481da177e4SLinus Torvaldsset	_off_cas,	0x14
491da177e4SLinus Torvaldsset	_off_cas2,	0x18
501da177e4SLinus Torvaldsset	_off_lock,	0x1c
511da177e4SLinus Torvaldsset	_off_unlock,	0x20
521da177e4SLinus Torvalds
531da177e4SLinus Torvaldsset	_off_imr,	0x40
541da177e4SLinus Torvaldsset	_off_dmr,	0x44
551da177e4SLinus Torvaldsset	_off_dmw,	0x48
561da177e4SLinus Torvaldsset	_off_irw,	0x4c
571da177e4SLinus Torvaldsset	_off_irl,	0x50
581da177e4SLinus Torvaldsset	_off_drb,	0x54
591da177e4SLinus Torvaldsset	_off_drw,	0x58
601da177e4SLinus Torvaldsset	_off_drl,	0x5c
611da177e4SLinus Torvaldsset	_off_dwb,	0x60
621da177e4SLinus Torvaldsset	_off_dww,	0x64
631da177e4SLinus Torvaldsset	_off_dwl,	0x68
641da177e4SLinus Torvalds
651da177e4SLinus Torvalds_060ISP_TABLE:
661da177e4SLinus Torvalds
671da177e4SLinus Torvalds# Here's the table of ENTRY POINTS for those linking the package.
681da177e4SLinus Torvalds	bra.l		_isp_unimp
691da177e4SLinus Torvalds	short		0x0000
701da177e4SLinus Torvalds
711da177e4SLinus Torvalds	bra.l		_isp_cas
721da177e4SLinus Torvalds	short		0x0000
731da177e4SLinus Torvalds
741da177e4SLinus Torvalds	bra.l		_isp_cas2
751da177e4SLinus Torvalds	short		0x0000
761da177e4SLinus Torvalds
771da177e4SLinus Torvalds	bra.l		_isp_cas_finish
781da177e4SLinus Torvalds	short		0x0000
791da177e4SLinus Torvalds
801da177e4SLinus Torvalds	bra.l		_isp_cas2_finish
811da177e4SLinus Torvalds	short		0x0000
821da177e4SLinus Torvalds
831da177e4SLinus Torvalds	bra.l		_isp_cas_inrange
841da177e4SLinus Torvalds	short		0x0000
851da177e4SLinus Torvalds
861da177e4SLinus Torvalds	bra.l		_isp_cas_terminate
871da177e4SLinus Torvalds	short		0x0000
881da177e4SLinus Torvalds
891da177e4SLinus Torvalds	bra.l		_isp_cas_restart
901da177e4SLinus Torvalds	short		0x0000
911da177e4SLinus Torvalds
921da177e4SLinus Torvalds	space		64
931da177e4SLinus Torvalds
941da177e4SLinus Torvalds#############################################################
951da177e4SLinus Torvalds
961da177e4SLinus Torvalds	global		_real_chk
971da177e4SLinus Torvalds_real_chk:
981da177e4SLinus Torvalds	mov.l		%d0,-(%sp)
991da177e4SLinus Torvalds	mov.l		(_060ISP_TABLE-0x80+_off_chk,%pc),%d0
1001da177e4SLinus Torvalds	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
1011da177e4SLinus Torvalds	mov.l		0x4(%sp),%d0
1021da177e4SLinus Torvalds	rtd		&0x4
1031da177e4SLinus Torvalds
1041da177e4SLinus Torvalds	global		_real_divbyzero
1051da177e4SLinus Torvalds_real_divbyzero:
1061da177e4SLinus Torvalds	mov.l		%d0,-(%sp)
1071da177e4SLinus Torvalds	mov.l		(_060ISP_TABLE-0x80+_off_divbyzero,%pc),%d0
1081da177e4SLinus Torvalds	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
1091da177e4SLinus Torvalds	mov.l		0x4(%sp),%d0
1101da177e4SLinus Torvalds	rtd		&0x4
1111da177e4SLinus Torvalds
1121da177e4SLinus Torvalds	global		_real_trace
1131da177e4SLinus Torvalds_real_trace:
1141da177e4SLinus Torvalds	mov.l		%d0,-(%sp)
1151da177e4SLinus Torvalds	mov.l		(_060ISP_TABLE-0x80+_off_trace,%pc),%d0
1161da177e4SLinus Torvalds	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
1171da177e4SLinus Torvalds	mov.l		0x4(%sp),%d0
1181da177e4SLinus Torvalds	rtd		&0x4
1191da177e4SLinus Torvalds
1201da177e4SLinus Torvalds	global		_real_access
1211da177e4SLinus Torvalds_real_access:
1221da177e4SLinus Torvalds	mov.l		%d0,-(%sp)
1231da177e4SLinus Torvalds	mov.l		(_060ISP_TABLE-0x80+_off_access,%pc),%d0
1241da177e4SLinus Torvalds	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
1251da177e4SLinus Torvalds	mov.l		0x4(%sp),%d0
1261da177e4SLinus Torvalds	rtd		&0x4
1271da177e4SLinus Torvalds
1281da177e4SLinus Torvalds	global		_isp_done
1291da177e4SLinus Torvalds_isp_done:
1301da177e4SLinus Torvalds	mov.l		%d0,-(%sp)
1311da177e4SLinus Torvalds	mov.l		(_060ISP_TABLE-0x80+_off_done,%pc),%d0
1321da177e4SLinus Torvalds	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
1331da177e4SLinus Torvalds	mov.l		0x4(%sp),%d0
1341da177e4SLinus Torvalds	rtd		&0x4
1351da177e4SLinus Torvalds
1361da177e4SLinus Torvalds#######################################
1371da177e4SLinus Torvalds
1381da177e4SLinus Torvalds	global		_real_cas
1391da177e4SLinus Torvalds_real_cas:
1401da177e4SLinus Torvalds	mov.l		%d0,-(%sp)
1411da177e4SLinus Torvalds	mov.l		(_060ISP_TABLE-0x80+_off_cas,%pc),%d0
1421da177e4SLinus Torvalds	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
1431da177e4SLinus Torvalds	mov.l		0x4(%sp),%d0
1441da177e4SLinus Torvalds	rtd		&0x4
1451da177e4SLinus Torvalds
1461da177e4SLinus Torvalds	global		_real_cas2
1471da177e4SLinus Torvalds_real_cas2:
1481da177e4SLinus Torvalds	mov.l		%d0,-(%sp)
1491da177e4SLinus Torvalds	mov.l		(_060ISP_TABLE-0x80+_off_cas2,%pc),%d0
1501da177e4SLinus Torvalds	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
1511da177e4SLinus Torvalds	mov.l		0x4(%sp),%d0
1521da177e4SLinus Torvalds	rtd		&0x4
1531da177e4SLinus Torvalds
1541da177e4SLinus Torvalds	global		_real_lock_page
1551da177e4SLinus Torvalds_real_lock_page:
1561da177e4SLinus Torvalds	mov.l		%d0,-(%sp)
1571da177e4SLinus Torvalds	mov.l		(_060ISP_TABLE-0x80+_off_lock,%pc),%d0
1581da177e4SLinus Torvalds	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
1591da177e4SLinus Torvalds	mov.l		0x4(%sp),%d0
1601da177e4SLinus Torvalds	rtd		&0x4
1611da177e4SLinus Torvalds
1621da177e4SLinus Torvalds	global		_real_unlock_page
1631da177e4SLinus Torvalds_real_unlock_page:
1641da177e4SLinus Torvalds	mov.l		%d0,-(%sp)
1651da177e4SLinus Torvalds	mov.l		(_060ISP_TABLE-0x80+_off_unlock,%pc),%d0
1661da177e4SLinus Torvalds	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
1671da177e4SLinus Torvalds	mov.l		0x4(%sp),%d0
1681da177e4SLinus Torvalds	rtd		&0x4
1691da177e4SLinus Torvalds
1701da177e4SLinus Torvalds#######################################
1711da177e4SLinus Torvalds
1721da177e4SLinus Torvalds	global		_imem_read
1731da177e4SLinus Torvalds_imem_read:
1741da177e4SLinus Torvalds	mov.l		%d0,-(%sp)
1751da177e4SLinus Torvalds	mov.l		(_060ISP_TABLE-0x80+_off_imr,%pc),%d0
1761da177e4SLinus Torvalds	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
1771da177e4SLinus Torvalds	mov.l		0x4(%sp),%d0
1781da177e4SLinus Torvalds	rtd		&0x4
1791da177e4SLinus Torvalds
1801da177e4SLinus Torvalds	global		_dmem_read
1811da177e4SLinus Torvalds_dmem_read:
1821da177e4SLinus Torvalds	mov.l		%d0,-(%sp)
1831da177e4SLinus Torvalds	mov.l		(_060ISP_TABLE-0x80+_off_dmr,%pc),%d0
1841da177e4SLinus Torvalds	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
1851da177e4SLinus Torvalds	mov.l		0x4(%sp),%d0
1861da177e4SLinus Torvalds	rtd		&0x4
1871da177e4SLinus Torvalds
1881da177e4SLinus Torvalds	global		_dmem_write
1891da177e4SLinus Torvalds_dmem_write:
1901da177e4SLinus Torvalds	mov.l		%d0,-(%sp)
1911da177e4SLinus Torvalds	mov.l		(_060ISP_TABLE-0x80+_off_dmw,%pc),%d0
1921da177e4SLinus Torvalds	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
1931da177e4SLinus Torvalds	mov.l		0x4(%sp),%d0
1941da177e4SLinus Torvalds	rtd		&0x4
1951da177e4SLinus Torvalds
1961da177e4SLinus Torvalds	global		_imem_read_word
1971da177e4SLinus Torvalds_imem_read_word:
1981da177e4SLinus Torvalds	mov.l		%d0,-(%sp)
1991da177e4SLinus Torvalds	mov.l		(_060ISP_TABLE-0x80+_off_irw,%pc),%d0
2001da177e4SLinus Torvalds	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
2011da177e4SLinus Torvalds	mov.l		0x4(%sp),%d0
2021da177e4SLinus Torvalds	rtd		&0x4
2031da177e4SLinus Torvalds
2041da177e4SLinus Torvalds	global		_imem_read_long
2051da177e4SLinus Torvalds_imem_read_long:
2061da177e4SLinus Torvalds	mov.l		%d0,-(%sp)
2071da177e4SLinus Torvalds	mov.l		(_060ISP_TABLE-0x80+_off_irl,%pc),%d0
2081da177e4SLinus Torvalds	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
2091da177e4SLinus Torvalds	mov.l		0x4(%sp),%d0
2101da177e4SLinus Torvalds	rtd		&0x4
2111da177e4SLinus Torvalds
2121da177e4SLinus Torvalds	global		_dmem_read_byte
2131da177e4SLinus Torvalds_dmem_read_byte:
2141da177e4SLinus Torvalds	mov.l		%d0,-(%sp)
2151da177e4SLinus Torvalds	mov.l		(_060ISP_TABLE-0x80+_off_drb,%pc),%d0
2161da177e4SLinus Torvalds	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
2171da177e4SLinus Torvalds	mov.l		0x4(%sp),%d0
2181da177e4SLinus Torvalds	rtd		&0x4
2191da177e4SLinus Torvalds
2201da177e4SLinus Torvalds	global		_dmem_read_word
2211da177e4SLinus Torvalds_dmem_read_word:
2221da177e4SLinus Torvalds	mov.l		%d0,-(%sp)
2231da177e4SLinus Torvalds	mov.l		(_060ISP_TABLE-0x80+_off_drw,%pc),%d0
2241da177e4SLinus Torvalds	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
2251da177e4SLinus Torvalds	mov.l		0x4(%sp),%d0
2261da177e4SLinus Torvalds	rtd		&0x4
2271da177e4SLinus Torvalds
2281da177e4SLinus Torvalds	global		_dmem_read_long
2291da177e4SLinus Torvalds_dmem_read_long:
2301da177e4SLinus Torvalds	mov.l		%d0,-(%sp)
2311da177e4SLinus Torvalds	mov.l		(_060ISP_TABLE-0x80+_off_drl,%pc),%d0
2321da177e4SLinus Torvalds	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
2331da177e4SLinus Torvalds	mov.l		0x4(%sp),%d0
2341da177e4SLinus Torvalds	rtd		&0x4
2351da177e4SLinus Torvalds
2361da177e4SLinus Torvalds	global		_dmem_write_byte
2371da177e4SLinus Torvalds_dmem_write_byte:
2381da177e4SLinus Torvalds	mov.l		%d0,-(%sp)
2391da177e4SLinus Torvalds	mov.l		(_060ISP_TABLE-0x80+_off_dwb,%pc),%d0
2401da177e4SLinus Torvalds	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
2411da177e4SLinus Torvalds	mov.l		0x4(%sp),%d0
2421da177e4SLinus Torvalds	rtd		&0x4
2431da177e4SLinus Torvalds
2441da177e4SLinus Torvalds	global		_dmem_write_word
2451da177e4SLinus Torvalds_dmem_write_word:
2461da177e4SLinus Torvalds	mov.l		%d0,-(%sp)
2471da177e4SLinus Torvalds	mov.l		(_060ISP_TABLE-0x80+_off_dww,%pc),%d0
2481da177e4SLinus Torvalds	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
2491da177e4SLinus Torvalds	mov.l		0x4(%sp),%d0
2501da177e4SLinus Torvalds	rtd		&0x4
2511da177e4SLinus Torvalds
2521da177e4SLinus Torvalds	global		_dmem_write_long
2531da177e4SLinus Torvalds_dmem_write_long:
2541da177e4SLinus Torvalds	mov.l		%d0,-(%sp)
2551da177e4SLinus Torvalds	mov.l		(_060ISP_TABLE-0x80+_off_dwl,%pc),%d0
2561da177e4SLinus Torvalds	pea.l		(_060ISP_TABLE-0x80,%pc,%d0)
2571da177e4SLinus Torvalds	mov.l		0x4(%sp),%d0
2581da177e4SLinus Torvalds	rtd		&0x4
2591da177e4SLinus Torvalds
2601da177e4SLinus Torvalds#
2611da177e4SLinus Torvalds# This file contains a set of define statements for constants
2621da177e4SLinus Torvalds# in oreder to promote readability within the core code itself.
2631da177e4SLinus Torvalds#
2641da177e4SLinus Torvalds
2651da177e4SLinus Torvaldsset LOCAL_SIZE,		96			# stack frame size(bytes)
2661da177e4SLinus Torvaldsset LV,			-LOCAL_SIZE		# stack offset
2671da177e4SLinus Torvalds
2681da177e4SLinus Torvaldsset EXC_ISR,		0x4			# stack status register
2691da177e4SLinus Torvaldsset EXC_IPC,		0x6			# stack pc
2701da177e4SLinus Torvaldsset EXC_IVOFF,		0xa			# stacked vector offset
2711da177e4SLinus Torvalds
2721da177e4SLinus Torvaldsset EXC_AREGS,		LV+64			# offset of all address regs
2731da177e4SLinus Torvaldsset EXC_DREGS,		LV+32			# offset of all data regs
2741da177e4SLinus Torvalds
2751da177e4SLinus Torvaldsset EXC_A7,		EXC_AREGS+(7*4)		# offset of a7
2761da177e4SLinus Torvaldsset EXC_A6,		EXC_AREGS+(6*4)		# offset of a6
2771da177e4SLinus Torvaldsset EXC_A5,		EXC_AREGS+(5*4)		# offset of a5
2781da177e4SLinus Torvaldsset EXC_A4,		EXC_AREGS+(4*4)		# offset of a4
2791da177e4SLinus Torvaldsset EXC_A3,		EXC_AREGS+(3*4)		# offset of a3
2801da177e4SLinus Torvaldsset EXC_A2,		EXC_AREGS+(2*4)		# offset of a2
2811da177e4SLinus Torvaldsset EXC_A1,		EXC_AREGS+(1*4)		# offset of a1
2821da177e4SLinus Torvaldsset EXC_A0,		EXC_AREGS+(0*4)		# offset of a0
2831da177e4SLinus Torvaldsset EXC_D7,		EXC_DREGS+(7*4)		# offset of d7
2841da177e4SLinus Torvaldsset EXC_D6,		EXC_DREGS+(6*4)		# offset of d6
2851da177e4SLinus Torvaldsset EXC_D5,		EXC_DREGS+(5*4)		# offset of d5
2861da177e4SLinus Torvaldsset EXC_D4,		EXC_DREGS+(4*4)		# offset of d4
2871da177e4SLinus Torvaldsset EXC_D3,		EXC_DREGS+(3*4)		# offset of d3
2881da177e4SLinus Torvaldsset EXC_D2,		EXC_DREGS+(2*4)		# offset of d2
2891da177e4SLinus Torvaldsset EXC_D1,		EXC_DREGS+(1*4)		# offset of d1
2901da177e4SLinus Torvaldsset EXC_D0,		EXC_DREGS+(0*4)		# offset of d0
2911da177e4SLinus Torvalds
2921da177e4SLinus Torvaldsset EXC_TEMP,		LV+16			# offset of temp stack space
2931da177e4SLinus Torvalds
2941da177e4SLinus Torvaldsset EXC_SAVVAL,		LV+12			# offset of old areg value
2951da177e4SLinus Torvaldsset EXC_SAVREG,		LV+11			# offset of old areg index
2961da177e4SLinus Torvalds
2971da177e4SLinus Torvaldsset SPCOND_FLG,		LV+10			# offset of spc condition flg
2981da177e4SLinus Torvalds
2991da177e4SLinus Torvaldsset EXC_CC,		LV+8			# offset of cc register
3001da177e4SLinus Torvaldsset EXC_EXTWPTR,	LV+4			# offset of current PC
3011da177e4SLinus Torvaldsset EXC_EXTWORD,	LV+2			# offset of current ext opword
3021da177e4SLinus Torvaldsset EXC_OPWORD,		LV+0			# offset of current opword
3031da177e4SLinus Torvalds
3041da177e4SLinus Torvalds###########################
3051da177e4SLinus Torvalds# SPecial CONDition FLaGs #
3061da177e4SLinus Torvalds###########################
3071da177e4SLinus Torvaldsset mia7_flg,		0x04			# (a7)+ flag
3081da177e4SLinus Torvaldsset mda7_flg,		0x08			# -(a7) flag
3091da177e4SLinus Torvaldsset ichk_flg,		0x10			# chk exception flag
3101da177e4SLinus Torvaldsset idbyz_flg,		0x20			# divbyzero flag
3111da177e4SLinus Torvaldsset restore_flg,	0x40			# restore -(an)+ flag
3121da177e4SLinus Torvaldsset immed_flg,		0x80			# immediate data flag
3131da177e4SLinus Torvalds
3141da177e4SLinus Torvaldsset mia7_bit,		0x2			# (a7)+ bit
3151da177e4SLinus Torvaldsset mda7_bit,		0x3			# -(a7) bit
3161da177e4SLinus Torvaldsset ichk_bit,		0x4			# chk exception bit
3171da177e4SLinus Torvaldsset idbyz_bit,		0x5			# divbyzero bit
3181da177e4SLinus Torvaldsset restore_bit,	0x6			# restore -(a7)+ bit
3191da177e4SLinus Torvaldsset immed_bit,		0x7			# immediate data bit
3201da177e4SLinus Torvalds
3211da177e4SLinus Torvalds#########
3221da177e4SLinus Torvalds# Misc. #
3231da177e4SLinus Torvalds#########
3241da177e4SLinus Torvaldsset BYTE,		1			# len(byte) == 1 byte
3251da177e4SLinus Torvaldsset WORD,		2			# len(word) == 2 bytes
3261da177e4SLinus Torvaldsset LONG,		4			# len(longword) == 4 bytes
3271da177e4SLinus Torvalds
3281da177e4SLinus Torvalds#########################################################################
3291da177e4SLinus Torvalds# XDEF ****************************************************************	#
3301da177e4SLinus Torvalds#	_isp_unimp(): 060ISP entry point for Unimplemented Instruction	#
3311da177e4SLinus Torvalds#									#
3321da177e4SLinus Torvalds#	This handler should be the first code executed upon taking the	#
3331da177e4SLinus Torvalds#	"Unimplemented Integer Instruction" exception in an operating	#
3341da177e4SLinus Torvalds#	system.								#
3351da177e4SLinus Torvalds#									#
3361da177e4SLinus Torvalds# XREF ****************************************************************	#
3371da177e4SLinus Torvalds#	_imem_read_{word,long}() - read instruction word/longword	#
3381da177e4SLinus Torvalds#	_mul64() - emulate 64-bit multiply				#
3391da177e4SLinus Torvalds#	_div64() - emulate 64-bit divide				#
3401da177e4SLinus Torvalds#	_moveperipheral() - emulate "movep"				#
3411da177e4SLinus Torvalds#	_compandset() - emulate misaligned "cas"			#
3421da177e4SLinus Torvalds#	_compandset2() - emulate "cas2"					#
3431da177e4SLinus Torvalds#	_chk2_cmp2() - emulate "cmp2" and "chk2"			#
3441da177e4SLinus Torvalds#	_isp_done() - "callout" for normal final exit			#
3451da177e4SLinus Torvalds#	_real_trace() - "callout" for Trace exception			#
3461da177e4SLinus Torvalds#	_real_chk() - "callout" for Chk exception			#
3471da177e4SLinus Torvalds#	_real_divbyzero() - "callout" for DZ exception			#
3481da177e4SLinus Torvalds#	_real_access() - "callout" for access error exception		#
3491da177e4SLinus Torvalds#									#
3501da177e4SLinus Torvalds# INPUT ***************************************************************	#
3511da177e4SLinus Torvalds#	- The system stack contains the Unimp Int Instr stack frame	#
3521da177e4SLinus Torvalds#									#
3531da177e4SLinus Torvalds# OUTPUT **************************************************************	#
3541da177e4SLinus Torvalds#	If Trace exception:						#
3551da177e4SLinus Torvalds#	- The system stack changed to contain Trace exc stack frame	#
3561da177e4SLinus Torvalds#	If Chk exception:						#
3571da177e4SLinus Torvalds#	- The system stack changed to contain Chk exc stack frame	#
3581da177e4SLinus Torvalds#	If DZ exception:						#
3591da177e4SLinus Torvalds#	- The system stack changed to contain DZ exc stack frame	#
3601da177e4SLinus Torvalds#	If access error exception:					#
3611da177e4SLinus Torvalds#	- The system stack changed to contain access err exc stk frame	#
3621da177e4SLinus Torvalds#	Else:								#
3631da177e4SLinus Torvalds#	- Results saved as appropriate					#
3641da177e4SLinus Torvalds#									#
3651da177e4SLinus Torvalds# ALGORITHM ***********************************************************	#
3661da177e4SLinus Torvalds#	This handler fetches the first instruction longword from	#
3671da177e4SLinus Torvalds# memory and decodes it to determine which of the unimplemented		#
3681da177e4SLinus Torvalds# integer instructions caused this exception. This handler then calls	#
3691da177e4SLinus Torvalds# one of _mul64(), _div64(), _moveperipheral(), _compandset(),		#
3701da177e4SLinus Torvalds# _compandset2(), or _chk2_cmp2() as appropriate.			#
3711da177e4SLinus Torvalds#	Some of these instructions, by their nature, may produce other	#
3721da177e4SLinus Torvalds# types of exceptions. "div" can produce a divide-by-zero exception,	#
3731da177e4SLinus Torvalds# and "chk2" can cause a "Chk" exception. In both cases, the current	#
3741da177e4SLinus Torvalds# exception stack frame must be converted to an exception stack frame	#
3751da177e4SLinus Torvalds# of the correct exception type and an exit must be made through	#
3761da177e4SLinus Torvalds# _real_divbyzero() or _real_chk() as appropriate. In addition, all	#
3771da177e4SLinus Torvalds# instructions may be executing while Trace is enabled. If so, then	#
3781da177e4SLinus Torvalds# a Trace exception stack frame must be created and an exit made	#
3791da177e4SLinus Torvalds# through _real_trace().						#
3801da177e4SLinus Torvalds#	Meanwhile, if any read or write to memory using the		#
3811da177e4SLinus Torvalds# _mem_{read,write}() "callout"s returns a failing value, then an	#
3821da177e4SLinus Torvalds# access error frame must be created and an exit made through		#
3831da177e4SLinus Torvalds# _real_access().							#
3841da177e4SLinus Torvalds#	If none of these occur, then a normal exit is made through	#
3851da177e4SLinus Torvalds# _isp_done().								#
3861da177e4SLinus Torvalds#									#
3871da177e4SLinus Torvalds#	This handler, upon entry, saves almost all user-visible		#
3881da177e4SLinus Torvalds# address and data registers to the stack. Although this may seem to	#
3891da177e4SLinus Torvalds# cause excess memory traffic, it was found that due to having to	#
3901da177e4SLinus Torvalds# access these register files for things like data retrieval and <ea>	#
3911da177e4SLinus Torvalds# calculations, it was more efficient to have them on the stack where	#
3921da177e4SLinus Torvalds# they could be accessed by indexing rather than to make subroutine	#
3931da177e4SLinus Torvalds# calls to retrieve a register of a particular index.			#
3941da177e4SLinus Torvalds#									#
3951da177e4SLinus Torvalds#########################################################################
3961da177e4SLinus Torvalds
3971da177e4SLinus Torvalds	global		_isp_unimp
3981da177e4SLinus Torvalds_isp_unimp:
3991da177e4SLinus Torvalds	link.w		%a6,&-LOCAL_SIZE	# create room for stack frame
4001da177e4SLinus Torvalds
4011da177e4SLinus Torvalds	movm.l		&0x3fff,EXC_DREGS(%a6)	# store d0-d7/a0-a5
4021da177e4SLinus Torvalds	mov.l		(%a6),EXC_A6(%a6)	# store a6
4031da177e4SLinus Torvalds
4041da177e4SLinus Torvalds	btst		&0x5,EXC_ISR(%a6)	# from s or u mode?
4051da177e4SLinus Torvalds	bne.b		uieh_s			# supervisor mode
4061da177e4SLinus Torvaldsuieh_u:
4071da177e4SLinus Torvalds	mov.l		%usp,%a0		# fetch user stack pointer
4081da177e4SLinus Torvalds	mov.l		%a0,EXC_A7(%a6)		# store a7
4091da177e4SLinus Torvalds	bra.b		uieh_cont
4101da177e4SLinus Torvaldsuieh_s:
4111da177e4SLinus Torvalds	lea		0xc(%a6),%a0
4121da177e4SLinus Torvalds	mov.l		%a0,EXC_A7(%a6)		# store corrected sp
4131da177e4SLinus Torvalds
4141da177e4SLinus Torvalds###############################################################################
4151da177e4SLinus Torvalds
4161da177e4SLinus Torvaldsuieh_cont:
4171da177e4SLinus Torvalds	clr.b		SPCOND_FLG(%a6)		# clear "special case" flag
4181da177e4SLinus Torvalds
4191da177e4SLinus Torvalds	mov.w		EXC_ISR(%a6),EXC_CC(%a6) # store cc copy on stack
4201da177e4SLinus Torvalds	mov.l		EXC_IPC(%a6),EXC_EXTWPTR(%a6) # store extwptr on stack
4211da177e4SLinus Torvalds
4221da177e4SLinus Torvalds#
4231da177e4SLinus Torvalds# fetch the opword and first extension word pointed to by the stacked pc
4241da177e4SLinus Torvalds# and store them to the stack for now
4251da177e4SLinus Torvalds#
4261da177e4SLinus Torvalds	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
4271da177e4SLinus Torvalds	addq.l		&0x4,EXC_EXTWPTR(%a6)	# incr instruction ptr
4281da177e4SLinus Torvalds	bsr.l		_imem_read_long		# fetch opword & extword
4291da177e4SLinus Torvalds	mov.l		%d0,EXC_OPWORD(%a6)	# store extword on stack
4301da177e4SLinus Torvalds
4311da177e4SLinus Torvalds
4321da177e4SLinus Torvalds#########################################################################
4331da177e4SLinus Torvalds# muls.l	0100 1100 00 |<ea>|	0*** 1100 0000 0***		#
4341da177e4SLinus Torvalds# mulu.l	0100 1100 00 |<ea>|	0*** 0100 0000 0***		#
4351da177e4SLinus Torvalds#									#
4361da177e4SLinus Torvalds# divs.l	0100 1100 01 |<ea>|	0*** 1100 0000 0***		#
4371da177e4SLinus Torvalds# divu.l	0100 1100 01 |<ea>|	0*** 0100 0000 0***		#
4381da177e4SLinus Torvalds#									#
4391da177e4SLinus Torvalds# movep.w m2r	0000 ***1 00 001***	| <displacement>  |		#
4401da177e4SLinus Torvalds# movep.l m2r	0000 ***1 01 001***	| <displacement>  |		#
4411da177e4SLinus Torvalds# movep.w r2m	0000 ***1 10 001***	| <displacement>  |		#
4421da177e4SLinus Torvalds# movep.l r2m	0000 ***1 11 001***	| <displacement>  |		#
4431da177e4SLinus Torvalds#									#
4441da177e4SLinus Torvalds# cas.w		0000 1100 11 |<ea>|	0000 000* **00 0***		#
4451da177e4SLinus Torvalds# cas.l		0000 1110 11 |<ea>|	0000 000* **00 0***		#
4461da177e4SLinus Torvalds#									#
4471da177e4SLinus Torvalds# cas2.w	0000 1100 11 111100	**** 000* **00 0***		#
4481da177e4SLinus Torvalds#					**** 000* **00 0***		#
4491da177e4SLinus Torvalds# cas2.l	0000 1110 11 111100	**** 000* **00 0***		#
4501da177e4SLinus Torvalds#					**** 000* **00 0***		#
4511da177e4SLinus Torvalds#									#
4521da177e4SLinus Torvalds# chk2.b	0000 0000 11 |<ea>|	**** 1000 0000 0000		#
4531da177e4SLinus Torvalds# chk2.w	0000 0010 11 |<ea>|	**** 1000 0000 0000		#
4541da177e4SLinus Torvalds# chk2.l	0000 0100 11 |<ea>|	**** 1000 0000 0000		#
4551da177e4SLinus Torvalds#									#
4561da177e4SLinus Torvalds# cmp2.b	0000 0000 11 |<ea>|	**** 0000 0000 0000		#
4571da177e4SLinus Torvalds# cmp2.w	0000 0010 11 |<ea>|	**** 0000 0000 0000		#
4581da177e4SLinus Torvalds# cmp2.l	0000 0100 11 |<ea>|	**** 0000 0000 0000		#
4591da177e4SLinus Torvalds#########################################################################
4601da177e4SLinus Torvalds
4611da177e4SLinus Torvalds#
4621da177e4SLinus Torvalds# using bit 14 of the operation word, separate into 2 groups:
4631da177e4SLinus Torvalds# (group1) mul64, div64
4641da177e4SLinus Torvalds# (group2) movep, chk2, cmp2, cas2, cas
4651da177e4SLinus Torvalds#
4661da177e4SLinus Torvalds	btst		&0x1e,%d0		# group1 or group2
4671da177e4SLinus Torvalds	beq.b		uieh_group2		# go handle group2
4681da177e4SLinus Torvalds
4691da177e4SLinus Torvalds#
4701da177e4SLinus Torvalds# now, w/ group1, make mul64's decode the fastest since it will
4711da177e4SLinus Torvalds# most likely be used the most.
4721da177e4SLinus Torvalds#
4731da177e4SLinus Torvaldsuieh_group1:
4741da177e4SLinus Torvalds	btst		&0x16,%d0		# test for div64
4751da177e4SLinus Torvalds	bne.b		uieh_div64		# go handle div64
4761da177e4SLinus Torvalds
4771da177e4SLinus Torvaldsuieh_mul64:
4781da177e4SLinus Torvalds# mul64() may use ()+ addressing and may, therefore, alter a7
4791da177e4SLinus Torvalds
4801da177e4SLinus Torvalds	bsr.l		_mul64			# _mul64()
4811da177e4SLinus Torvalds
4821da177e4SLinus Torvalds	btst		&0x5,EXC_ISR(%a6)	# supervisor mode?
4831da177e4SLinus Torvalds	beq.w		uieh_done
4841da177e4SLinus Torvalds	btst		&mia7_bit,SPCOND_FLG(%a6) # was a7 changed?
4851da177e4SLinus Torvalds	beq.w		uieh_done		# no
4861da177e4SLinus Torvalds	btst		&0x7,EXC_ISR(%a6)	# is trace enabled?
4871da177e4SLinus Torvalds	bne.w		uieh_trace_a7		# yes
4881da177e4SLinus Torvalds	bra.w		uieh_a7			# no
4891da177e4SLinus Torvalds
4901da177e4SLinus Torvaldsuieh_div64:
4911da177e4SLinus Torvalds# div64() may use ()+ addressing and may, therefore, alter a7.
4921da177e4SLinus Torvalds# div64() may take a divide by zero exception.
4931da177e4SLinus Torvalds
4941da177e4SLinus Torvalds	bsr.l		_div64			# _div64()
4951da177e4SLinus Torvalds
4961da177e4SLinus Torvalds# here, we sort out all of the special cases that may have happened.
4971da177e4SLinus Torvalds	btst		&mia7_bit,SPCOND_FLG(%a6) # was a7 changed?
4981da177e4SLinus Torvalds	bne.b		uieh_div64_a7		# yes
4991da177e4SLinus Torvaldsuieh_div64_dbyz:
5001da177e4SLinus Torvalds	btst		&idbyz_bit,SPCOND_FLG(%a6) # did divide-by-zero occur?
5011da177e4SLinus Torvalds	bne.w		uieh_divbyzero		# yes
5021da177e4SLinus Torvalds	bra.w		uieh_done		# no
5031da177e4SLinus Torvaldsuieh_div64_a7:
5041da177e4SLinus Torvalds	btst		&0x5,EXC_ISR(%a6)	# supervisor mode?
5051da177e4SLinus Torvalds	beq.b		uieh_div64_dbyz		# no
5061da177e4SLinus Torvalds# here, a7 has been incremented by 4 bytes in supervisor mode. we still
5071da177e4SLinus Torvalds# may have the following 3 cases:
5081da177e4SLinus Torvalds#	(i)	(a7)+
5091da177e4SLinus Torvalds#	(ii)	(a7)+; trace
5101da177e4SLinus Torvalds#	(iii)	(a7)+; divide-by-zero
5111da177e4SLinus Torvalds#
5121da177e4SLinus Torvalds	btst		&idbyz_bit,SPCOND_FLG(%a6) # did divide-by-zero occur?
5131da177e4SLinus Torvalds	bne.w		uieh_divbyzero_a7	# yes
5141da177e4SLinus Torvalds	tst.b		EXC_ISR(%a6)		# no; is trace enabled?
5151da177e4SLinus Torvalds	bmi.w		uieh_trace_a7		# yes
5161da177e4SLinus Torvalds	bra.w		uieh_a7			# no
5171da177e4SLinus Torvalds
5181da177e4SLinus Torvalds#
5191da177e4SLinus Torvalds# now, w/ group2, make movep's decode the fastest since it will
5201da177e4SLinus Torvalds# most likely be used the most.
5211da177e4SLinus Torvalds#
5221da177e4SLinus Torvaldsuieh_group2:
5231da177e4SLinus Torvalds	btst		&0x18,%d0		# test for not movep
5241da177e4SLinus Torvalds	beq.b		uieh_not_movep
5251da177e4SLinus Torvalds
5261da177e4SLinus Torvalds
5271da177e4SLinus Torvalds	bsr.l		_moveperipheral		# _movep()
5281da177e4SLinus Torvalds	bra.w		uieh_done
5291da177e4SLinus Torvalds
5301da177e4SLinus Torvaldsuieh_not_movep:
5311da177e4SLinus Torvalds	btst		&0x1b,%d0		# test for chk2,cmp2
5321da177e4SLinus Torvalds	beq.b		uieh_chk2cmp2		# go handle chk2,cmp2
5331da177e4SLinus Torvalds
5341da177e4SLinus Torvalds	swap		%d0			# put opword in lo word
5351da177e4SLinus Torvalds	cmpi.b		%d0,&0xfc		# test for cas2
5361da177e4SLinus Torvalds	beq.b		uieh_cas2		# go handle cas2
5371da177e4SLinus Torvalds
5381da177e4SLinus Torvaldsuieh_cas:
5391da177e4SLinus Torvalds
5401da177e4SLinus Torvalds	bsr.l		_compandset		# _cas()
5411da177e4SLinus Torvalds
5421da177e4SLinus Torvalds# the cases of "cas Dc,Du,(a7)+" and "cas Dc,Du,-(a7)" used from supervisor
5431da177e4SLinus Torvalds# mode are simply not considered valid and therefore are not handled.
5441da177e4SLinus Torvalds
5451da177e4SLinus Torvalds	bra.w		uieh_done
5461da177e4SLinus Torvalds
5471da177e4SLinus Torvaldsuieh_cas2:
5481da177e4SLinus Torvalds
5491da177e4SLinus Torvalds	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
5501da177e4SLinus Torvalds	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
5511da177e4SLinus Torvalds	bsr.l		_imem_read_word		# read extension word
5521da177e4SLinus Torvalds
5531da177e4SLinus Torvalds	tst.l		%d1			# ifetch error?
5541da177e4SLinus Torvalds	bne.w		isp_iacc		# yes
5551da177e4SLinus Torvalds
5561da177e4SLinus Torvalds	bsr.l		_compandset2		# _cas2()
5571da177e4SLinus Torvalds	bra.w		uieh_done
5581da177e4SLinus Torvalds
5591da177e4SLinus Torvaldsuieh_chk2cmp2:
5601da177e4SLinus Torvalds# chk2 may take a chk exception
5611da177e4SLinus Torvalds
5621da177e4SLinus Torvalds	bsr.l		_chk2_cmp2		# _chk2_cmp2()
5631da177e4SLinus Torvalds
5641da177e4SLinus Torvalds# here we check to see if a chk trap should be taken
5651da177e4SLinus Torvalds	cmpi.b		SPCOND_FLG(%a6),&ichk_flg
5661da177e4SLinus Torvalds	bne.w		uieh_done
5671da177e4SLinus Torvalds	bra.b		uieh_chk_trap
5681da177e4SLinus Torvalds
5691da177e4SLinus Torvalds###########################################################################
5701da177e4SLinus Torvalds
5711da177e4SLinus Torvalds#
5721da177e4SLinus Torvalds# the required emulation has been completed. now, clean up the necessary stack
5731da177e4SLinus Torvalds# info and prepare for rte
5741da177e4SLinus Torvalds#
5751da177e4SLinus Torvaldsuieh_done:
5761da177e4SLinus Torvalds	mov.b		EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes
5771da177e4SLinus Torvalds
5781da177e4SLinus Torvalds# if exception occurred in user mode, then we have to restore a7 in case it
5791da177e4SLinus Torvalds# changed. we don't have to update a7  for supervisor mose because that case
5801da177e4SLinus Torvalds# doesn't flow through here
5811da177e4SLinus Torvalds	btst		&0x5,EXC_ISR(%a6)	# user or supervisor?
5821da177e4SLinus Torvalds	bne.b		uieh_finish		# supervisor
5831da177e4SLinus Torvalds
5841da177e4SLinus Torvalds	mov.l		EXC_A7(%a6),%a0		# fetch user stack pointer
5851da177e4SLinus Torvalds	mov.l		%a0,%usp		# restore it
5861da177e4SLinus Torvalds
5871da177e4SLinus Torvaldsuieh_finish:
5881da177e4SLinus Torvalds	movm.l		EXC_DREGS(%a6),&0x3fff	# restore d0-d7/a0-a5
5891da177e4SLinus Torvalds
5901da177e4SLinus Torvalds	btst		&0x7,EXC_ISR(%a6)	# is trace mode on?
5911da177e4SLinus Torvalds	bne.b		uieh_trace		# yes;go handle trace mode
5921da177e4SLinus Torvalds
5931da177e4SLinus Torvalds	mov.l		EXC_EXTWPTR(%a6),EXC_IPC(%a6) # new pc on stack frame
5941da177e4SLinus Torvalds	mov.l		EXC_A6(%a6),(%a6)	# prepare new a6 for unlink
5951da177e4SLinus Torvalds	unlk		%a6			# unlink stack frame
5961da177e4SLinus Torvalds	bra.l		_isp_done
5971da177e4SLinus Torvalds
5981da177e4SLinus Torvalds#
5991da177e4SLinus Torvalds# The instruction that was just emulated was also being traced. The trace
6001da177e4SLinus Torvalds# trap for this instruction will be lost unless we jump to the trace handler.
6011da177e4SLinus Torvalds# So, here we create a Trace Exception format number two exception stack
6021da177e4SLinus Torvalds# frame from the Unimplemented Integer Intruction Exception stack frame
6031da177e4SLinus Torvalds# format number zero and jump to the user supplied hook "_real_trace()".
6041da177e4SLinus Torvalds#
6051da177e4SLinus Torvalds#		   UIEH FRAME		   TRACE FRAME
6061da177e4SLinus Torvalds#		*****************	*****************
6071da177e4SLinus Torvalds#		* 0x0 *  0x0f4	*	*    Current	*
6081da177e4SLinus Torvalds#		*****************	*      PC	*
6091da177e4SLinus Torvalds#		*    Current	*	*****************
6101da177e4SLinus Torvalds#		*      PC	*	* 0x2 *  0x024	*
6111da177e4SLinus Torvalds#		*****************	*****************
6121da177e4SLinus Torvalds#		*      SR	*	*     Next	*
6131da177e4SLinus Torvalds#		*****************	*      PC	*
6141da177e4SLinus Torvalds#	      ->*     Old	*	*****************
6151da177e4SLinus Torvalds#  from link -->*      A6	*	*      SR	*
6161da177e4SLinus Torvalds#	        *****************	*****************
6171da177e4SLinus Torvalds#	       /*      A7	*	*      New	* <-- for final unlink
6181da177e4SLinus Torvalds#	      / *		*	*      A6	*
6191da177e4SLinus Torvalds# link frame <  *****************	*****************
6201da177e4SLinus Torvalds#	      \ ~		~	~		~
6211da177e4SLinus Torvalds#	       \*****************	*****************
6221da177e4SLinus Torvalds#
6231da177e4SLinus Torvaldsuieh_trace:
6241da177e4SLinus Torvalds	mov.l		EXC_A6(%a6),-0x4(%a6)
6251da177e4SLinus Torvalds	mov.w		EXC_ISR(%a6),0x0(%a6)
6261da177e4SLinus Torvalds	mov.l		EXC_IPC(%a6),0x8(%a6)
6271da177e4SLinus Torvalds	mov.l		EXC_EXTWPTR(%a6),0x2(%a6)
6281da177e4SLinus Torvalds	mov.w		&0x2024,0x6(%a6)
6291da177e4SLinus Torvalds	sub.l		&0x4,%a6
6301da177e4SLinus Torvalds	unlk		%a6
6311da177e4SLinus Torvalds	bra.l		_real_trace
6321da177e4SLinus Torvalds
6331da177e4SLinus Torvalds#
6341da177e4SLinus Torvalds#	   UIEH FRAME		    CHK FRAME
6351da177e4SLinus Torvalds#	*****************	*****************
6361da177e4SLinus Torvalds#	* 0x0 *  0x0f4	*	*    Current	*
6371da177e4SLinus Torvalds#	*****************	*      PC	*
6381da177e4SLinus Torvalds#	*    Current	*	*****************
6391da177e4SLinus Torvalds#	*      PC	*	* 0x2 *  0x018	*
6401da177e4SLinus Torvalds#	*****************	*****************
6411da177e4SLinus Torvalds#	*      SR	*	*     Next	*
6421da177e4SLinus Torvalds#	*****************	*      PC	*
6431da177e4SLinus Torvalds#	    (4 words)		*****************
6441da177e4SLinus Torvalds#				*      SR	*
6451da177e4SLinus Torvalds#				*****************
6461da177e4SLinus Torvalds#				    (6 words)
6471da177e4SLinus Torvalds#
6481da177e4SLinus Torvalds# the chk2 instruction should take a chk trap. so, here we must create a
6491da177e4SLinus Torvalds# chk stack frame from an unimplemented integer instruction exception frame
6501da177e4SLinus Torvalds# and jump to the user supplied entry point "_real_chk()".
6511da177e4SLinus Torvalds#
6521da177e4SLinus Torvaldsuieh_chk_trap:
6531da177e4SLinus Torvalds	mov.b		EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes
6541da177e4SLinus Torvalds	movm.l		EXC_DREGS(%a6),&0x3fff	# restore d0-d7/a0-a5
6551da177e4SLinus Torvalds
6561da177e4SLinus Torvalds	mov.w		EXC_ISR(%a6),(%a6)	# put new SR on stack
6571da177e4SLinus Torvalds	mov.l		EXC_IPC(%a6),0x8(%a6)	# put "Current PC" on stack
6581da177e4SLinus Torvalds	mov.l		EXC_EXTWPTR(%a6),0x2(%a6) # put "Next PC" on stack
6591da177e4SLinus Torvalds	mov.w		&0x2018,0x6(%a6)	# put Vector Offset on stack
6601da177e4SLinus Torvalds
6611da177e4SLinus Torvalds	mov.l		EXC_A6(%a6),%a6		# restore a6
6621da177e4SLinus Torvalds	add.l		&LOCAL_SIZE,%sp		# clear stack frame
6631da177e4SLinus Torvalds
6641da177e4SLinus Torvalds	bra.l		_real_chk
6651da177e4SLinus Torvalds
6661da177e4SLinus Torvalds#
6671da177e4SLinus Torvalds#	   UIEH FRAME		 DIVBYZERO FRAME
6681da177e4SLinus Torvalds#	*****************	*****************
6691da177e4SLinus Torvalds#	* 0x0 *  0x0f4	*	*    Current	*
6701da177e4SLinus Torvalds#	*****************	*      PC	*
6711da177e4SLinus Torvalds#	*    Current	*	*****************
6721da177e4SLinus Torvalds#	*      PC	*	* 0x2 *  0x014	*
6731da177e4SLinus Torvalds#	*****************	*****************
6741da177e4SLinus Torvalds#	*      SR	*	*     Next	*
6751da177e4SLinus Torvalds#	*****************	*      PC	*
6761da177e4SLinus Torvalds#	    (4 words)		*****************
6771da177e4SLinus Torvalds#				*      SR	*
6781da177e4SLinus Torvalds#				*****************
6791da177e4SLinus Torvalds#				    (6 words)
6801da177e4SLinus Torvalds#
6811da177e4SLinus Torvalds# the divide instruction should take an integer divide by zero trap. so, here
6821da177e4SLinus Torvalds# we must create a divbyzero stack frame from an unimplemented integer
6831da177e4SLinus Torvalds# instruction exception frame and jump to the user supplied entry point
6841da177e4SLinus Torvalds# "_real_divbyzero()".
6851da177e4SLinus Torvalds#
6861da177e4SLinus Torvaldsuieh_divbyzero:
6871da177e4SLinus Torvalds	mov.b		EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes
6881da177e4SLinus Torvalds	movm.l		EXC_DREGS(%a6),&0x3fff	# restore d0-d7/a0-a5
6891da177e4SLinus Torvalds
6901da177e4SLinus Torvalds	mov.w		EXC_ISR(%a6),(%a6)	# put new SR on stack
6911da177e4SLinus Torvalds	mov.l		EXC_IPC(%a6),0x8(%a6)	# put "Current PC" on stack
6921da177e4SLinus Torvalds	mov.l		EXC_EXTWPTR(%a6),0x2(%a6) # put "Next PC" on stack
6931da177e4SLinus Torvalds	mov.w		&0x2014,0x6(%a6)	# put Vector Offset on stack
6941da177e4SLinus Torvalds
6951da177e4SLinus Torvalds	mov.l		EXC_A6(%a6),%a6		# restore a6
6961da177e4SLinus Torvalds	add.l		&LOCAL_SIZE,%sp		# clear stack frame
6971da177e4SLinus Torvalds
6981da177e4SLinus Torvalds	bra.l		_real_divbyzero
6991da177e4SLinus Torvalds
7001da177e4SLinus Torvalds#
7011da177e4SLinus Torvalds#				 DIVBYZERO FRAME
7021da177e4SLinus Torvalds#				*****************
7031da177e4SLinus Torvalds#				*    Current	*
7041da177e4SLinus Torvalds#	   UIEH FRAME		*      PC	*
7051da177e4SLinus Torvalds#	*****************	*****************
7061da177e4SLinus Torvalds#	* 0x0 *  0x0f4	*	* 0x2 * 0x014	*
7071da177e4SLinus Torvalds#	*****************	*****************
7081da177e4SLinus Torvalds#	*    Current	*	*     Next	*
7091da177e4SLinus Torvalds#	*      PC	*	*      PC	*
7101da177e4SLinus Torvalds#	*****************	*****************
7111da177e4SLinus Torvalds#	*      SR	*	*      SR	*
7121da177e4SLinus Torvalds#	*****************	*****************
7131da177e4SLinus Torvalds#	    (4 words)		    (6 words)
7141da177e4SLinus Torvalds#
7151da177e4SLinus Torvalds# the divide instruction should take an integer divide by zero trap. so, here
7161da177e4SLinus Torvalds# we must create a divbyzero stack frame from an unimplemented integer
7171da177e4SLinus Torvalds# instruction exception frame and jump to the user supplied entry point
7181da177e4SLinus Torvalds# "_real_divbyzero()".
7191da177e4SLinus Torvalds#
7201da177e4SLinus Torvalds# However, we must also deal with the fact that (a7)+ was used from supervisor
7211da177e4SLinus Torvalds# mode, thereby shifting the stack frame up 4 bytes.
7221da177e4SLinus Torvalds#
7231da177e4SLinus Torvaldsuieh_divbyzero_a7:
7241da177e4SLinus Torvalds	mov.b		EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes
7251da177e4SLinus Torvalds	movm.l		EXC_DREGS(%a6),&0x3fff	# restore d0-d7/a0-a5
7261da177e4SLinus Torvalds
7271da177e4SLinus Torvalds	mov.l		EXC_IPC(%a6),0xc(%a6)	# put "Current PC" on stack
7281da177e4SLinus Torvalds	mov.w		&0x2014,0xa(%a6)	# put Vector Offset on stack
7291da177e4SLinus Torvalds	mov.l		EXC_EXTWPTR(%a6),0x6(%a6) # put "Next PC" on stack
7301da177e4SLinus Torvalds
7311da177e4SLinus Torvalds	mov.l		EXC_A6(%a6),%a6		# restore a6
7321da177e4SLinus Torvalds	add.l		&4+LOCAL_SIZE,%sp	# clear stack frame
7331da177e4SLinus Torvalds
7341da177e4SLinus Torvalds	bra.l		_real_divbyzero
7351da177e4SLinus Torvalds
7361da177e4SLinus Torvalds#
7371da177e4SLinus Torvalds#				   TRACE FRAME
7381da177e4SLinus Torvalds#				*****************
7391da177e4SLinus Torvalds#				*    Current	*
7401da177e4SLinus Torvalds#	   UIEH FRAME		*      PC	*
7411da177e4SLinus Torvalds#	*****************	*****************
7421da177e4SLinus Torvalds#	* 0x0 *  0x0f4	*	* 0x2 * 0x024	*
7431da177e4SLinus Torvalds#	*****************	*****************
7441da177e4SLinus Torvalds#	*    Current	*	*     Next	*
7451da177e4SLinus Torvalds#	*      PC	*	*      PC	*
7461da177e4SLinus Torvalds#	*****************	*****************
7471da177e4SLinus Torvalds#	*      SR	*	*      SR	*
7481da177e4SLinus Torvalds#	*****************	*****************
7491da177e4SLinus Torvalds#	    (4 words)		    (6 words)
7501da177e4SLinus Torvalds#
7511da177e4SLinus Torvalds#
7521da177e4SLinus Torvalds# The instruction that was just emulated was also being traced. The trace
7531da177e4SLinus Torvalds# trap for this instruction will be lost unless we jump to the trace handler.
7541da177e4SLinus Torvalds# So, here we create a Trace Exception format number two exception stack
7551da177e4SLinus Torvalds# frame from the Unimplemented Integer Intruction Exception stack frame
7561da177e4SLinus Torvalds# format number zero and jump to the user supplied hook "_real_trace()".
7571da177e4SLinus Torvalds#
7581da177e4SLinus Torvalds# However, we must also deal with the fact that (a7)+ was used from supervisor
7591da177e4SLinus Torvalds# mode, thereby shifting the stack frame up 4 bytes.
7601da177e4SLinus Torvalds#
7611da177e4SLinus Torvaldsuieh_trace_a7:
7621da177e4SLinus Torvalds	mov.b		EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes
7631da177e4SLinus Torvalds	movm.l		EXC_DREGS(%a6),&0x3fff	# restore d0-d7/a0-a5
7641da177e4SLinus Torvalds
7651da177e4SLinus Torvalds	mov.l		EXC_IPC(%a6),0xc(%a6)	# put "Current PC" on stack
7661da177e4SLinus Torvalds	mov.w		&0x2024,0xa(%a6)	# put Vector Offset on stack
7671da177e4SLinus Torvalds	mov.l		EXC_EXTWPTR(%a6),0x6(%a6) # put "Next PC" on stack
7681da177e4SLinus Torvalds
7691da177e4SLinus Torvalds	mov.l		EXC_A6(%a6),%a6		# restore a6
7701da177e4SLinus Torvalds	add.l		&4+LOCAL_SIZE,%sp	# clear stack frame
7711da177e4SLinus Torvalds
7721da177e4SLinus Torvalds	bra.l		_real_trace
7731da177e4SLinus Torvalds
7741da177e4SLinus Torvalds#
7751da177e4SLinus Torvalds#				   UIEH FRAME
7761da177e4SLinus Torvalds#				*****************
7771da177e4SLinus Torvalds#				* 0x0 * 0x0f4	*
7781da177e4SLinus Torvalds#	   UIEH FRAME		*****************
7791da177e4SLinus Torvalds#	*****************	*     Next	*
7801da177e4SLinus Torvalds#	* 0x0 *  0x0f4	*	*      PC	*
7811da177e4SLinus Torvalds#	*****************	*****************
7821da177e4SLinus Torvalds#	*    Current	*	*      SR	*
7831da177e4SLinus Torvalds#	*      PC	*	*****************
7841da177e4SLinus Torvalds#	*****************	    (4 words)
7851da177e4SLinus Torvalds#	*      SR	*
7861da177e4SLinus Torvalds#	*****************
7871da177e4SLinus Torvalds#	    (4 words)
7881da177e4SLinus Torvaldsuieh_a7:
7891da177e4SLinus Torvalds	mov.b		EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes
7901da177e4SLinus Torvalds	movm.l		EXC_DREGS(%a6),&0x3fff	# restore d0-d7/a0-a5
7911da177e4SLinus Torvalds
7921da177e4SLinus Torvalds	mov.w		&0x00f4,0xe(%a6)	# put Vector Offset on stack
7931da177e4SLinus Torvalds	mov.l		EXC_EXTWPTR(%a6),0xa(%a6) # put "Next PC" on stack
7941da177e4SLinus Torvalds	mov.w		EXC_ISR(%a6),0x8(%a6)	# put SR on stack
7951da177e4SLinus Torvalds
7961da177e4SLinus Torvalds	mov.l		EXC_A6(%a6),%a6		# restore a6
7971da177e4SLinus Torvalds	add.l		&8+LOCAL_SIZE,%sp	# clear stack frame
7981da177e4SLinus Torvalds	bra.l		_isp_done
7991da177e4SLinus Torvalds
8001da177e4SLinus Torvalds##########
8011da177e4SLinus Torvalds
8021da177e4SLinus Torvalds# this is the exit point if a data read or write fails.
8031da177e4SLinus Torvalds# a0 = failing address
8041da177e4SLinus Torvalds# d0 = fslw
8051da177e4SLinus Torvaldsisp_dacc:
8061da177e4SLinus Torvalds	mov.l		%a0,(%a6)		# save address
8071da177e4SLinus Torvalds	mov.l		%d0,-0x4(%a6)		# save partial fslw
8081da177e4SLinus Torvalds
8091da177e4SLinus Torvalds	lea		-64(%a6),%sp
8101da177e4SLinus Torvalds	movm.l		(%sp)+,&0x7fff		# restore d0-d7/a0-a6
8111da177e4SLinus Torvalds
8121da177e4SLinus Torvalds	mov.l		0xc(%sp),-(%sp)		# move voff,hi(pc)
8131da177e4SLinus Torvalds	mov.l		0x4(%sp),0x10(%sp)	# store fslw
8141da177e4SLinus Torvalds	mov.l		0xc(%sp),0x4(%sp)	# store sr,lo(pc)
8151da177e4SLinus Torvalds	mov.l		0x8(%sp),0xc(%sp)	# store address
8161da177e4SLinus Torvalds	mov.l		(%sp)+,0x4(%sp)		# store voff,hi(pc)
8171da177e4SLinus Torvalds	mov.w		&0x4008,0x6(%sp)	# store new voff
8181da177e4SLinus Torvalds
8191da177e4SLinus Torvalds	bra.b		isp_acc_exit
8201da177e4SLinus Torvalds
8211da177e4SLinus Torvalds# this is the exit point if an instruction word read fails.
8221da177e4SLinus Torvalds# FSLW:
8231da177e4SLinus Torvalds#	misaligned = true
8241da177e4SLinus Torvalds#	read = true
8251da177e4SLinus Torvalds#	size = word
8261da177e4SLinus Torvalds#	instruction = true
8271da177e4SLinus Torvalds#	software emulation error = true
8281da177e4SLinus Torvaldsisp_iacc:
8291da177e4SLinus Torvalds	movm.l		EXC_DREGS(%a6),&0x3fff	# restore d0-d7/a0-a5
8301da177e4SLinus Torvalds	unlk		%a6			# unlink frame
8311da177e4SLinus Torvalds	sub.w		&0x8,%sp		# make room for acc frame
8321da177e4SLinus Torvalds	mov.l		0x8(%sp),(%sp)		# store sr,lo(pc)
8331da177e4SLinus Torvalds	mov.w		0xc(%sp),0x4(%sp)	# store hi(pc)
8341da177e4SLinus Torvalds	mov.w		&0x4008,0x6(%sp)	# store new voff
8351da177e4SLinus Torvalds	mov.l		0x2(%sp),0x8(%sp)	# store address (=pc)
8361da177e4SLinus Torvalds	mov.l		&0x09428001,0xc(%sp)	# store fslw
8371da177e4SLinus Torvalds
8381da177e4SLinus Torvaldsisp_acc_exit:
8391da177e4SLinus Torvalds	btst		&0x5,(%sp)		# user or supervisor?
8401da177e4SLinus Torvalds	beq.b		isp_acc_exit2		# user
8411da177e4SLinus Torvalds	bset		&0x2,0xd(%sp)		# set supervisor TM bit
8421da177e4SLinus Torvaldsisp_acc_exit2:
8431da177e4SLinus Torvalds	bra.l		_real_access
8441da177e4SLinus Torvalds
8451da177e4SLinus Torvalds# if the addressing mode was (an)+ or -(an), the address register must
8461da177e4SLinus Torvalds# be restored to its pre-exception value before entering _real_access.
8471da177e4SLinus Torvaldsisp_restore:
8481da177e4SLinus Torvalds	cmpi.b		SPCOND_FLG(%a6),&restore_flg # do we need a restore?
8491da177e4SLinus Torvalds	bne.b		isp_restore_done	# no
8501da177e4SLinus Torvalds	clr.l		%d0
8511da177e4SLinus Torvalds	mov.b		EXC_SAVREG(%a6),%d0	# regno to restore
8521da177e4SLinus Torvalds	mov.l		EXC_SAVVAL(%a6),(EXC_AREGS,%a6,%d0.l*4) # restore value
8531da177e4SLinus Torvaldsisp_restore_done:
8541da177e4SLinus Torvalds	rts
8551da177e4SLinus Torvalds
8561da177e4SLinus Torvalds#########################################################################
8571da177e4SLinus Torvalds# XDEF ****************************************************************	#
8581da177e4SLinus Torvalds#	_calc_ea(): routine to calculate effective address		#
8591da177e4SLinus Torvalds#									#
8601da177e4SLinus Torvalds# XREF ****************************************************************	#
8611da177e4SLinus Torvalds#	_imem_read_word() - read instruction word			#
8621da177e4SLinus Torvalds#	_imem_read_long() - read instruction longword			#
8631da177e4SLinus Torvalds#	_dmem_read_long() - read data longword (for memory indirect)	#
8641da177e4SLinus Torvalds#	isp_iacc() - handle instruction access error exception		#
8651da177e4SLinus Torvalds#	isp_dacc() - handle data access error exception			#
8661da177e4SLinus Torvalds#									#
8671da177e4SLinus Torvalds# INPUT ***************************************************************	#
8681da177e4SLinus Torvalds#	d0 = number of bytes related to effective address (w,l)		#
8691da177e4SLinus Torvalds#									#
8701da177e4SLinus Torvalds# OUTPUT **************************************************************	#
8711da177e4SLinus Torvalds#	If exiting through isp_dacc...					#
8721da177e4SLinus Torvalds#		a0 = failing address					#
8731da177e4SLinus Torvalds#		d0 = FSLW						#
8741da177e4SLinus Torvalds#	elsif exiting though isp_iacc...				#
8751da177e4SLinus Torvalds#		none							#
8761da177e4SLinus Torvalds#	else								#
8771da177e4SLinus Torvalds#		a0 = effective address					#
8781da177e4SLinus Torvalds#									#
8791da177e4SLinus Torvalds# ALGORITHM ***********************************************************	#
8801da177e4SLinus Torvalds#	The effective address type is decoded from the opword residing	#
8811da177e4SLinus Torvalds# on the stack. A jump table is used to vector to a routine for the	#
8821da177e4SLinus Torvalds# appropriate mode. Since none of the emulated integer instructions	#
8831da177e4SLinus Torvalds# uses byte-sized operands, only handle word and long operations.	#
8841da177e4SLinus Torvalds#									#
8851da177e4SLinus Torvalds#	Dn,An	- shouldn't enter here					#
8861da177e4SLinus Torvalds#	(An)	- fetch An value from stack				#
8871da177e4SLinus Torvalds#	-(An)	- fetch An value from stack; return decr value;		#
8881da177e4SLinus Torvalds#		  place decr value on stack; store old value in case of	#
8891da177e4SLinus Torvalds#		  future access error; if -(a7), set mda7_flg in	#
8901da177e4SLinus Torvalds#		  SPCOND_FLG						#
8911da177e4SLinus Torvalds#	(An)+	- fetch An value from stack; return value;		#
8921da177e4SLinus Torvalds#		  place incr value on stack; store old value in case of	#
8931da177e4SLinus Torvalds#		  future access error; if (a7)+, set mia7_flg in	#
8941da177e4SLinus Torvalds#		  SPCOND_FLG						#
8951da177e4SLinus Torvalds#	(d16,An) - fetch An value from stack; read d16 using		#
8961da177e4SLinus Torvalds#		  _imem_read_word(); fetch may fail -> branch to	#
8971da177e4SLinus Torvalds#		  isp_iacc()						#
8981da177e4SLinus Torvalds#	(xxx).w,(xxx).l - use _imem_read_{word,long}() to fetch		#
8991da177e4SLinus Torvalds#		  address; fetch may fail				#
9001da177e4SLinus Torvalds#	#<data> - return address of immediate value; set immed_flg	#
9011da177e4SLinus Torvalds#		  in SPCOND_FLG						#
9021da177e4SLinus Torvalds#	(d16,PC) - fetch stacked PC value; read d16 using		#
9031da177e4SLinus Torvalds#		  _imem_read_word(); fetch may fail -> branch to	#
9041da177e4SLinus Torvalds#		  isp_iacc()						#
9051da177e4SLinus Torvalds#	everything else - read needed displacements as appropriate w/	#
9061da177e4SLinus Torvalds#		  _imem_read_{word,long}(); read may fail; if memory	#
9071da177e4SLinus Torvalds#		  indirect, read indirect address using			#
9081da177e4SLinus Torvalds#		  _dmem_read_long() which may also fail			#
9091da177e4SLinus Torvalds#									#
9101da177e4SLinus Torvalds#########################################################################
9111da177e4SLinus Torvalds
9121da177e4SLinus Torvalds	global		_calc_ea
9131da177e4SLinus Torvalds_calc_ea:
9141da177e4SLinus Torvalds	mov.l		%d0,%a0			# move # bytes to a0
9151da177e4SLinus Torvalds
9161da177e4SLinus Torvalds# MODE and REG are taken from the EXC_OPWORD.
9171da177e4SLinus Torvalds	mov.w		EXC_OPWORD(%a6),%d0	# fetch opcode word
9181da177e4SLinus Torvalds	mov.w		%d0,%d1			# make a copy
9191da177e4SLinus Torvalds
9201da177e4SLinus Torvalds	andi.w		&0x3f,%d0		# extract mode field
9211da177e4SLinus Torvalds	andi.l		&0x7,%d1		# extract reg  field
9221da177e4SLinus Torvalds
9231da177e4SLinus Torvalds# jump to the corresponding function for each {MODE,REG} pair.
9241da177e4SLinus Torvalds	mov.w		(tbl_ea_mode.b,%pc,%d0.w*2), %d0 # fetch jmp distance
9251da177e4SLinus Torvalds	jmp		(tbl_ea_mode.b,%pc,%d0.w*1) # jmp to correct ea mode
9261da177e4SLinus Torvalds
9271da177e4SLinus Torvalds	swbeg		&64
9281da177e4SLinus Torvaldstbl_ea_mode:
9291da177e4SLinus Torvalds	short		tbl_ea_mode	-	tbl_ea_mode
9301da177e4SLinus Torvalds	short		tbl_ea_mode	-	tbl_ea_mode
9311da177e4SLinus Torvalds	short		tbl_ea_mode	-	tbl_ea_mode
9321da177e4SLinus Torvalds	short		tbl_ea_mode	-	tbl_ea_mode
9331da177e4SLinus Torvalds	short		tbl_ea_mode	-	tbl_ea_mode
9341da177e4SLinus Torvalds	short		tbl_ea_mode	-	tbl_ea_mode
9351da177e4SLinus Torvalds	short		tbl_ea_mode	-	tbl_ea_mode
9361da177e4SLinus Torvalds	short		tbl_ea_mode	-	tbl_ea_mode
9371da177e4SLinus Torvalds
9381da177e4SLinus Torvalds	short		tbl_ea_mode	-	tbl_ea_mode
9391da177e4SLinus Torvalds	short		tbl_ea_mode	-	tbl_ea_mode
9401da177e4SLinus Torvalds	short		tbl_ea_mode	-	tbl_ea_mode
9411da177e4SLinus Torvalds	short		tbl_ea_mode	-	tbl_ea_mode
9421da177e4SLinus Torvalds	short		tbl_ea_mode	-	tbl_ea_mode
9431da177e4SLinus Torvalds	short		tbl_ea_mode	-	tbl_ea_mode
9441da177e4SLinus Torvalds	short		tbl_ea_mode	-	tbl_ea_mode
9451da177e4SLinus Torvalds	short		tbl_ea_mode	-	tbl_ea_mode
9461da177e4SLinus Torvalds
9471da177e4SLinus Torvalds	short		addr_ind_a0	-	tbl_ea_mode
9481da177e4SLinus Torvalds	short		addr_ind_a1	-	tbl_ea_mode
9491da177e4SLinus Torvalds	short		addr_ind_a2	-	tbl_ea_mode
9501da177e4SLinus Torvalds	short		addr_ind_a3	-	tbl_ea_mode
9511da177e4SLinus Torvalds	short		addr_ind_a4	-	tbl_ea_mode
9521da177e4SLinus Torvalds	short		addr_ind_a5	-	tbl_ea_mode
9531da177e4SLinus Torvalds	short		addr_ind_a6	-	tbl_ea_mode
9541da177e4SLinus Torvalds	short		addr_ind_a7	-	tbl_ea_mode
9551da177e4SLinus Torvalds
9561da177e4SLinus Torvalds	short		addr_ind_p_a0	-	tbl_ea_mode
9571da177e4SLinus Torvalds	short		addr_ind_p_a1	-	tbl_ea_mode
9581da177e4SLinus Torvalds	short		addr_ind_p_a2	-	tbl_ea_mode
9591da177e4SLinus Torvalds	short		addr_ind_p_a3	-	tbl_ea_mode
9601da177e4SLinus Torvalds	short		addr_ind_p_a4	-	tbl_ea_mode
9611da177e4SLinus Torvalds	short		addr_ind_p_a5	-	tbl_ea_mode
9621da177e4SLinus Torvalds	short		addr_ind_p_a6	-	tbl_ea_mode
9631da177e4SLinus Torvalds	short		addr_ind_p_a7	-	tbl_ea_mode
9641da177e4SLinus Torvalds
9651da177e4SLinus Torvalds	short		addr_ind_m_a0		-	tbl_ea_mode
9661da177e4SLinus Torvalds	short		addr_ind_m_a1		-	tbl_ea_mode
9671da177e4SLinus Torvalds	short		addr_ind_m_a2		-	tbl_ea_mode
9681da177e4SLinus Torvalds	short		addr_ind_m_a3		-	tbl_ea_mode
9691da177e4SLinus Torvalds	short		addr_ind_m_a4		-	tbl_ea_mode
9701da177e4SLinus Torvalds	short		addr_ind_m_a5		-	tbl_ea_mode
9711da177e4SLinus Torvalds	short		addr_ind_m_a6		-	tbl_ea_mode
9721da177e4SLinus Torvalds	short		addr_ind_m_a7		-	tbl_ea_mode
9731da177e4SLinus Torvalds
9741da177e4SLinus Torvalds	short		addr_ind_disp_a0	-	tbl_ea_mode
9751da177e4SLinus Torvalds	short		addr_ind_disp_a1	-	tbl_ea_mode
9761da177e4SLinus Torvalds	short		addr_ind_disp_a2	-	tbl_ea_mode
9771da177e4SLinus Torvalds	short		addr_ind_disp_a3	-	tbl_ea_mode
9781da177e4SLinus Torvalds	short		addr_ind_disp_a4	-	tbl_ea_mode
9791da177e4SLinus Torvalds	short		addr_ind_disp_a5	-	tbl_ea_mode
9801da177e4SLinus Torvalds	short		addr_ind_disp_a6	-	tbl_ea_mode
9811da177e4SLinus Torvalds	short		addr_ind_disp_a7	-	tbl_ea_mode
9821da177e4SLinus Torvalds
9831da177e4SLinus Torvalds	short		_addr_ind_ext		-	tbl_ea_mode
9841da177e4SLinus Torvalds	short		_addr_ind_ext		-	tbl_ea_mode
9851da177e4SLinus Torvalds	short		_addr_ind_ext		-	tbl_ea_mode
9861da177e4SLinus Torvalds	short		_addr_ind_ext		-	tbl_ea_mode
9871da177e4SLinus Torvalds	short		_addr_ind_ext		-	tbl_ea_mode
9881da177e4SLinus Torvalds	short		_addr_ind_ext		-	tbl_ea_mode
9891da177e4SLinus Torvalds	short		_addr_ind_ext		-	tbl_ea_mode
9901da177e4SLinus Torvalds	short		_addr_ind_ext		-	tbl_ea_mode
9911da177e4SLinus Torvalds
9921da177e4SLinus Torvalds	short		abs_short		-	tbl_ea_mode
9931da177e4SLinus Torvalds	short		abs_long		-	tbl_ea_mode
9941da177e4SLinus Torvalds	short		pc_ind			-	tbl_ea_mode
9951da177e4SLinus Torvalds	short		pc_ind_ext		-	tbl_ea_mode
9961da177e4SLinus Torvalds	short		immediate		-	tbl_ea_mode
9971da177e4SLinus Torvalds	short		tbl_ea_mode		-	tbl_ea_mode
9981da177e4SLinus Torvalds	short		tbl_ea_mode		-	tbl_ea_mode
9991da177e4SLinus Torvalds	short		tbl_ea_mode		-	tbl_ea_mode
10001da177e4SLinus Torvalds
10011da177e4SLinus Torvalds###################################
10021da177e4SLinus Torvalds# Address register indirect: (An) #
10031da177e4SLinus Torvalds###################################
10041da177e4SLinus Torvaldsaddr_ind_a0:
10051da177e4SLinus Torvalds	mov.l		EXC_A0(%a6),%a0		# Get current a0
10061da177e4SLinus Torvalds	rts
10071da177e4SLinus Torvalds
10081da177e4SLinus Torvaldsaddr_ind_a1:
10091da177e4SLinus Torvalds	mov.l		EXC_A1(%a6),%a0		# Get current a1
10101da177e4SLinus Torvalds	rts
10111da177e4SLinus Torvalds
10121da177e4SLinus Torvaldsaddr_ind_a2:
10131da177e4SLinus Torvalds	mov.l		EXC_A2(%a6),%a0		# Get current a2
10141da177e4SLinus Torvalds	rts
10151da177e4SLinus Torvalds
10161da177e4SLinus Torvaldsaddr_ind_a3:
10171da177e4SLinus Torvalds	mov.l		EXC_A3(%a6),%a0		# Get current a3
10181da177e4SLinus Torvalds	rts
10191da177e4SLinus Torvalds
10201da177e4SLinus Torvaldsaddr_ind_a4:
10211da177e4SLinus Torvalds	mov.l		EXC_A4(%a6),%a0		# Get current a4
10221da177e4SLinus Torvalds	rts
10231da177e4SLinus Torvalds
10241da177e4SLinus Torvaldsaddr_ind_a5:
10251da177e4SLinus Torvalds	mov.l		EXC_A5(%a6),%a0		# Get current a5
10261da177e4SLinus Torvalds	rts
10271da177e4SLinus Torvalds
10281da177e4SLinus Torvaldsaddr_ind_a6:
10291da177e4SLinus Torvalds	mov.l		EXC_A6(%a6),%a0		# Get current a6
10301da177e4SLinus Torvalds	rts
10311da177e4SLinus Torvalds
10321da177e4SLinus Torvaldsaddr_ind_a7:
10331da177e4SLinus Torvalds	mov.l		EXC_A7(%a6),%a0		# Get current a7
10341da177e4SLinus Torvalds	rts
10351da177e4SLinus Torvalds
10361da177e4SLinus Torvalds#####################################################
10371da177e4SLinus Torvalds# Address register indirect w/ postincrement: (An)+ #
10381da177e4SLinus Torvalds#####################################################
10391da177e4SLinus Torvaldsaddr_ind_p_a0:
10401da177e4SLinus Torvalds	mov.l		%a0,%d0			# copy no. bytes
10411da177e4SLinus Torvalds	mov.l		EXC_A0(%a6),%a0		# load current value
10421da177e4SLinus Torvalds	add.l		%a0,%d0			# increment
10431da177e4SLinus Torvalds	mov.l		%d0,EXC_A0(%a6)		# save incremented value
10441da177e4SLinus Torvalds
10451da177e4SLinus Torvalds	mov.l		%a0,EXC_SAVVAL(%a6)	# save in case of access error
10461da177e4SLinus Torvalds	mov.b		&0x0,EXC_SAVREG(%a6)	# save regno, too
10471da177e4SLinus Torvalds	mov.b		&restore_flg,SPCOND_FLG(%a6) # set flag
10481da177e4SLinus Torvalds	rts
10491da177e4SLinus Torvalds
10501da177e4SLinus Torvaldsaddr_ind_p_a1:
10511da177e4SLinus Torvalds	mov.l		%a0,%d0			# copy no. bytes
10521da177e4SLinus Torvalds	mov.l		EXC_A1(%a6),%a0		# load current value
10531da177e4SLinus Torvalds	add.l		%a0,%d0			# increment
10541da177e4SLinus Torvalds	mov.l		%d0,EXC_A1(%a6)		# save incremented value
10551da177e4SLinus Torvalds
10561da177e4SLinus Torvalds	mov.l		%a0,EXC_SAVVAL(%a6)	# save in case of access error
10571da177e4SLinus Torvalds	mov.b		&0x1,EXC_SAVREG(%a6)	# save regno, too
10581da177e4SLinus Torvalds	mov.b		&restore_flg,SPCOND_FLG(%a6) # set flag
10591da177e4SLinus Torvalds	rts
10601da177e4SLinus Torvalds
10611da177e4SLinus Torvaldsaddr_ind_p_a2:
10621da177e4SLinus Torvalds	mov.l		%a0,%d0			# copy no. bytes
10631da177e4SLinus Torvalds	mov.l		EXC_A2(%a6),%a0		# load current value
10641da177e4SLinus Torvalds	add.l		%a0,%d0			# increment
10651da177e4SLinus Torvalds	mov.l		%d0,EXC_A2(%a6)		# save incremented value
10661da177e4SLinus Torvalds
10671da177e4SLinus Torvalds	mov.l		%a0,EXC_SAVVAL(%a6)	# save in case of access error
10681da177e4SLinus Torvalds	mov.b		&0x2,EXC_SAVREG(%a6)	# save regno, too
10691da177e4SLinus Torvalds	mov.b		&restore_flg,SPCOND_FLG(%a6) # set flag
10701da177e4SLinus Torvalds	rts
10711da177e4SLinus Torvalds
10721da177e4SLinus Torvaldsaddr_ind_p_a3:
10731da177e4SLinus Torvalds	mov.l		%a0,%d0			# copy no. bytes
10741da177e4SLinus Torvalds	mov.l		EXC_A3(%a6),%a0		# load current value
10751da177e4SLinus Torvalds	add.l		%a0,%d0			# increment
10761da177e4SLinus Torvalds	mov.l		%d0,EXC_A3(%a6)		# save incremented value
10771da177e4SLinus Torvalds
10781da177e4SLinus Torvalds	mov.l		%a0,EXC_SAVVAL(%a6)	# save in case of access error
10791da177e4SLinus Torvalds	mov.b		&0x3,EXC_SAVREG(%a6)	# save regno, too
10801da177e4SLinus Torvalds	mov.b		&restore_flg,SPCOND_FLG(%a6) # set flag
10811da177e4SLinus Torvalds	rts
10821da177e4SLinus Torvalds
10831da177e4SLinus Torvaldsaddr_ind_p_a4:
10841da177e4SLinus Torvalds	mov.l		%a0,%d0			# copy no. bytes
10851da177e4SLinus Torvalds	mov.l		EXC_A4(%a6),%a0		# load current value
10861da177e4SLinus Torvalds	add.l		%a0,%d0			# increment
10871da177e4SLinus Torvalds	mov.l		%d0,EXC_A4(%a6)		# save incremented value
10881da177e4SLinus Torvalds
10891da177e4SLinus Torvalds	mov.l		%a0,EXC_SAVVAL(%a6)	# save in case of access error
10901da177e4SLinus Torvalds	mov.b		&0x4,EXC_SAVREG(%a6)	# save regno, too
10911da177e4SLinus Torvalds	mov.b		&restore_flg,SPCOND_FLG(%a6) # set flag
10921da177e4SLinus Torvalds	rts
10931da177e4SLinus Torvalds
10941da177e4SLinus Torvaldsaddr_ind_p_a5:
10951da177e4SLinus Torvalds	mov.l		%a0,%d0			# copy no. bytes
10961da177e4SLinus Torvalds	mov.l		EXC_A5(%a6),%a0		# load current value
10971da177e4SLinus Torvalds	add.l		%a0,%d0			# increment
10981da177e4SLinus Torvalds	mov.l		%d0,EXC_A5(%a6)		# save incremented value
10991da177e4SLinus Torvalds
11001da177e4SLinus Torvalds	mov.l		%a0,EXC_SAVVAL(%a6)	# save in case of access error
11011da177e4SLinus Torvalds	mov.b		&0x5,EXC_SAVREG(%a6)	# save regno, too
11021da177e4SLinus Torvalds	mov.b		&restore_flg,SPCOND_FLG(%a6) # set flag
11031da177e4SLinus Torvalds	rts
11041da177e4SLinus Torvalds
11051da177e4SLinus Torvaldsaddr_ind_p_a6:
11061da177e4SLinus Torvalds	mov.l		%a0,%d0			# copy no. bytes
11071da177e4SLinus Torvalds	mov.l		EXC_A6(%a6),%a0		# load current value
11081da177e4SLinus Torvalds	add.l		%a0,%d0			# increment
11091da177e4SLinus Torvalds	mov.l		%d0,EXC_A6(%a6)		# save incremented value
11101da177e4SLinus Torvalds
11111da177e4SLinus Torvalds	mov.l		%a0,EXC_SAVVAL(%a6)	# save in case of access error
11121da177e4SLinus Torvalds	mov.b		&0x6,EXC_SAVREG(%a6)	# save regno, too
11131da177e4SLinus Torvalds	mov.b		&restore_flg,SPCOND_FLG(%a6) # set flag
11141da177e4SLinus Torvalds	rts
11151da177e4SLinus Torvalds
11161da177e4SLinus Torvaldsaddr_ind_p_a7:
11171da177e4SLinus Torvalds	mov.b		&mia7_flg,SPCOND_FLG(%a6) # set "special case" flag
11181da177e4SLinus Torvalds
11191da177e4SLinus Torvalds	mov.l		%a0,%d0			# copy no. bytes
11201da177e4SLinus Torvalds	mov.l		EXC_A7(%a6),%a0		# load current value
11211da177e4SLinus Torvalds	add.l		%a0,%d0			# increment
11221da177e4SLinus Torvalds	mov.l		%d0,EXC_A7(%a6)		# save incremented value
11231da177e4SLinus Torvalds	rts
11241da177e4SLinus Torvalds
11251da177e4SLinus Torvalds####################################################
11261da177e4SLinus Torvalds# Address register indirect w/ predecrement: -(An) #
11271da177e4SLinus Torvalds####################################################
11281da177e4SLinus Torvaldsaddr_ind_m_a0:
11291da177e4SLinus Torvalds	mov.l		EXC_A0(%a6),%d0		# Get current a0
11301da177e4SLinus Torvalds	mov.l		%d0,EXC_SAVVAL(%a6)	# save in case of access error
11311da177e4SLinus Torvalds	sub.l		%a0,%d0			# Decrement
11321da177e4SLinus Torvalds	mov.l		%d0,EXC_A0(%a6)		# Save decr value
11331da177e4SLinus Torvalds	mov.l		%d0,%a0
11341da177e4SLinus Torvalds
11351da177e4SLinus Torvalds	mov.b		&0x0,EXC_SAVREG(%a6)	# save regno, too
11361da177e4SLinus Torvalds	mov.b		&restore_flg,SPCOND_FLG(%a6) # set flag
11371da177e4SLinus Torvalds	rts
11381da177e4SLinus Torvalds
11391da177e4SLinus Torvaldsaddr_ind_m_a1:
11401da177e4SLinus Torvalds	mov.l		EXC_A1(%a6),%d0		# Get current a1
11411da177e4SLinus Torvalds	mov.l		%d0,EXC_SAVVAL(%a6)	# save in case of access error
11421da177e4SLinus Torvalds	sub.l		%a0,%d0			# Decrement
11431da177e4SLinus Torvalds	mov.l		%d0,EXC_A1(%a6)		# Save decr value
11441da177e4SLinus Torvalds	mov.l		%d0,%a0
11451da177e4SLinus Torvalds
11461da177e4SLinus Torvalds	mov.b		&0x1,EXC_SAVREG(%a6)	# save regno, too
11471da177e4SLinus Torvalds	mov.b		&restore_flg,SPCOND_FLG(%a6) # set flag
11481da177e4SLinus Torvalds	rts
11491da177e4SLinus Torvalds
11501da177e4SLinus Torvaldsaddr_ind_m_a2:
11511da177e4SLinus Torvalds	mov.l		EXC_A2(%a6),%d0		# Get current a2
11521da177e4SLinus Torvalds	mov.l		%d0,EXC_SAVVAL(%a6)	# save in case of access error
11531da177e4SLinus Torvalds	sub.l		%a0,%d0			# Decrement
11541da177e4SLinus Torvalds	mov.l		%d0,EXC_A2(%a6)		# Save decr value
11551da177e4SLinus Torvalds	mov.l		%d0,%a0
11561da177e4SLinus Torvalds
11571da177e4SLinus Torvalds	mov.b		&0x2,EXC_SAVREG(%a6)	# save regno, too
11581da177e4SLinus Torvalds	mov.b		&restore_flg,SPCOND_FLG(%a6) # set flag
11591da177e4SLinus Torvalds	rts
11601da177e4SLinus Torvalds
11611da177e4SLinus Torvaldsaddr_ind_m_a3:
11621da177e4SLinus Torvalds	mov.l		EXC_A3(%a6),%d0		# Get current a3
11631da177e4SLinus Torvalds	mov.l		%d0,EXC_SAVVAL(%a6)	# save in case of access error
11641da177e4SLinus Torvalds	sub.l		%a0,%d0			# Decrement
11651da177e4SLinus Torvalds	mov.l		%d0,EXC_A3(%a6)		# Save decr value
11661da177e4SLinus Torvalds	mov.l		%d0,%a0
11671da177e4SLinus Torvalds
11681da177e4SLinus Torvalds	mov.b		&0x3,EXC_SAVREG(%a6)	# save regno, too
11691da177e4SLinus Torvalds	mov.b		&restore_flg,SPCOND_FLG(%a6) # set flag
11701da177e4SLinus Torvalds	rts
11711da177e4SLinus Torvalds
11721da177e4SLinus Torvaldsaddr_ind_m_a4:
11731da177e4SLinus Torvalds	mov.l		EXC_A4(%a6),%d0		# Get current a4
11741da177e4SLinus Torvalds	mov.l		%d0,EXC_SAVVAL(%a6)	# save in case of access error
11751da177e4SLinus Torvalds	sub.l		%a0,%d0			# Decrement
11761da177e4SLinus Torvalds	mov.l		%d0,EXC_A4(%a6)		# Save decr value
11771da177e4SLinus Torvalds	mov.l		%d0,%a0
11781da177e4SLinus Torvalds
11791da177e4SLinus Torvalds	mov.b		&0x4,EXC_SAVREG(%a6)	# save regno, too
11801da177e4SLinus Torvalds	mov.b		&restore_flg,SPCOND_FLG(%a6) # set flag
11811da177e4SLinus Torvalds	rts
11821da177e4SLinus Torvalds
11831da177e4SLinus Torvaldsaddr_ind_m_a5:
11841da177e4SLinus Torvalds	mov.l		EXC_A5(%a6),%d0		# Get current a5
11851da177e4SLinus Torvalds	mov.l		%d0,EXC_SAVVAL(%a6)	# save in case of access error
11861da177e4SLinus Torvalds	sub.l		%a0,%d0			# Decrement
11871da177e4SLinus Torvalds	mov.l		%d0,EXC_A5(%a6)		# Save decr value
11881da177e4SLinus Torvalds	mov.l		%d0,%a0
11891da177e4SLinus Torvalds
11901da177e4SLinus Torvalds	mov.b		&0x5,EXC_SAVREG(%a6)	# save regno, too
11911da177e4SLinus Torvalds	mov.b		&restore_flg,SPCOND_FLG(%a6) # set flag
11921da177e4SLinus Torvalds	rts
11931da177e4SLinus Torvalds
11941da177e4SLinus Torvaldsaddr_ind_m_a6:
11951da177e4SLinus Torvalds	mov.l		EXC_A6(%a6),%d0		# Get current a6
11961da177e4SLinus Torvalds	mov.l		%d0,EXC_SAVVAL(%a6)	# save in case of access error
11971da177e4SLinus Torvalds	sub.l		%a0,%d0			# Decrement
11981da177e4SLinus Torvalds	mov.l		%d0,EXC_A6(%a6)		# Save decr value
11991da177e4SLinus Torvalds	mov.l		%d0,%a0
12001da177e4SLinus Torvalds
12011da177e4SLinus Torvalds	mov.b		&0x6,EXC_SAVREG(%a6)	# save regno, too
12021da177e4SLinus Torvalds	mov.b		&restore_flg,SPCOND_FLG(%a6) # set flag
12031da177e4SLinus Torvalds	rts
12041da177e4SLinus Torvalds
12051da177e4SLinus Torvaldsaddr_ind_m_a7:
12061da177e4SLinus Torvalds	mov.b		&mda7_flg,SPCOND_FLG(%a6) # set "special case" flag
12071da177e4SLinus Torvalds
12081da177e4SLinus Torvalds	mov.l		EXC_A7(%a6),%d0		# Get current a7
12091da177e4SLinus Torvalds	sub.l		%a0,%d0			# Decrement
12101da177e4SLinus Torvalds	mov.l		%d0,EXC_A7(%a6)		# Save decr value
12111da177e4SLinus Torvalds	mov.l		%d0,%a0
12121da177e4SLinus Torvalds	rts
12131da177e4SLinus Torvalds
12141da177e4SLinus Torvalds########################################################
12151da177e4SLinus Torvalds# Address register indirect w/ displacement: (d16, An) #
12161da177e4SLinus Torvalds########################################################
12171da177e4SLinus Torvaldsaddr_ind_disp_a0:
12181da177e4SLinus Torvalds	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
12191da177e4SLinus Torvalds	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
12201da177e4SLinus Torvalds	bsr.l		_imem_read_word
12211da177e4SLinus Torvalds
12221da177e4SLinus Torvalds	tst.l		%d1			# ifetch error?
12231da177e4SLinus Torvalds	bne.l		isp_iacc		# yes
12241da177e4SLinus Torvalds
12251da177e4SLinus Torvalds	mov.w		%d0,%a0			# sign extend displacement
12261da177e4SLinus Torvalds	add.l		EXC_A0(%a6),%a0		# a0 + d16
12271da177e4SLinus Torvalds	rts
12281da177e4SLinus Torvalds
12291da177e4SLinus Torvaldsaddr_ind_disp_a1:
12301da177e4SLinus Torvalds	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
12311da177e4SLinus Torvalds	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
12321da177e4SLinus Torvalds	bsr.l		_imem_read_word
12331da177e4SLinus Torvalds
12341da177e4SLinus Torvalds	tst.l		%d1			# ifetch error?
12351da177e4SLinus Torvalds	bne.l		isp_iacc		# yes
12361da177e4SLinus Torvalds
12371da177e4SLinus Torvalds	mov.w		%d0,%a0			# sign extend displacement
12381da177e4SLinus Torvalds	add.l		EXC_A1(%a6),%a0		# a1 + d16
12391da177e4SLinus Torvalds	rts
12401da177e4SLinus Torvalds
12411da177e4SLinus Torvaldsaddr_ind_disp_a2:
12421da177e4SLinus Torvalds	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
12431da177e4SLinus Torvalds	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
12441da177e4SLinus Torvalds	bsr.l		_imem_read_word
12451da177e4SLinus Torvalds
12461da177e4SLinus Torvalds	tst.l		%d1			# ifetch error?
12471da177e4SLinus Torvalds	bne.l		isp_iacc		# yes
12481da177e4SLinus Torvalds
12491da177e4SLinus Torvalds	mov.w		%d0,%a0			# sign extend displacement
12501da177e4SLinus Torvalds	add.l		EXC_A2(%a6),%a0		# a2 + d16
12511da177e4SLinus Torvalds	rts
12521da177e4SLinus Torvalds
12531da177e4SLinus Torvaldsaddr_ind_disp_a3:
12541da177e4SLinus Torvalds	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
12551da177e4SLinus Torvalds	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
12561da177e4SLinus Torvalds	bsr.l		_imem_read_word
12571da177e4SLinus Torvalds
12581da177e4SLinus Torvalds	tst.l		%d1			# ifetch error?
12591da177e4SLinus Torvalds	bne.l		isp_iacc		# yes
12601da177e4SLinus Torvalds
12611da177e4SLinus Torvalds	mov.w		%d0,%a0			# sign extend displacement
12621da177e4SLinus Torvalds	add.l		EXC_A3(%a6),%a0		# a3 + d16
12631da177e4SLinus Torvalds	rts
12641da177e4SLinus Torvalds
12651da177e4SLinus Torvaldsaddr_ind_disp_a4:
12661da177e4SLinus Torvalds	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
12671da177e4SLinus Torvalds	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
12681da177e4SLinus Torvalds	bsr.l		_imem_read_word
12691da177e4SLinus Torvalds
12701da177e4SLinus Torvalds	tst.l		%d1			# ifetch error?
12711da177e4SLinus Torvalds	bne.l		isp_iacc		# yes
12721da177e4SLinus Torvalds
12731da177e4SLinus Torvalds	mov.w		%d0,%a0			# sign extend displacement
12741da177e4SLinus Torvalds	add.l		EXC_A4(%a6),%a0		# a4 + d16
12751da177e4SLinus Torvalds	rts
12761da177e4SLinus Torvalds
12771da177e4SLinus Torvaldsaddr_ind_disp_a5:
12781da177e4SLinus Torvalds	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
12791da177e4SLinus Torvalds	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
12801da177e4SLinus Torvalds	bsr.l		_imem_read_word
12811da177e4SLinus Torvalds
12821da177e4SLinus Torvalds	tst.l		%d1			# ifetch error?
12831da177e4SLinus Torvalds	bne.l		isp_iacc		# yes
12841da177e4SLinus Torvalds
12851da177e4SLinus Torvalds	mov.w		%d0,%a0			# sign extend displacement
12861da177e4SLinus Torvalds	add.l		EXC_A5(%a6),%a0		# a5 + d16
12871da177e4SLinus Torvalds	rts
12881da177e4SLinus Torvalds
12891da177e4SLinus Torvaldsaddr_ind_disp_a6:
12901da177e4SLinus Torvalds	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
12911da177e4SLinus Torvalds	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
12921da177e4SLinus Torvalds	bsr.l		_imem_read_word
12931da177e4SLinus Torvalds
12941da177e4SLinus Torvalds	tst.l		%d1			# ifetch error?
12951da177e4SLinus Torvalds	bne.l		isp_iacc		# yes
12961da177e4SLinus Torvalds
12971da177e4SLinus Torvalds	mov.w		%d0,%a0			# sign extend displacement
12981da177e4SLinus Torvalds	add.l		EXC_A6(%a6),%a0		# a6 + d16
12991da177e4SLinus Torvalds	rts
13001da177e4SLinus Torvalds
13011da177e4SLinus Torvaldsaddr_ind_disp_a7:
13021da177e4SLinus Torvalds	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
13031da177e4SLinus Torvalds	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
13041da177e4SLinus Torvalds	bsr.l		_imem_read_word
13051da177e4SLinus Torvalds
13061da177e4SLinus Torvalds	tst.l		%d1			# ifetch error?
13071da177e4SLinus Torvalds	bne.l		isp_iacc		# yes
13081da177e4SLinus Torvalds
13091da177e4SLinus Torvalds	mov.w		%d0,%a0			# sign extend displacement
13101da177e4SLinus Torvalds	add.l		EXC_A7(%a6),%a0		# a7 + d16
13111da177e4SLinus Torvalds	rts
13121da177e4SLinus Torvalds
13131da177e4SLinus Torvalds########################################################################
13141da177e4SLinus Torvalds# Address register indirect w/ index(8-bit displacement): (dn, An, Xn) #
13151da177e4SLinus Torvalds#    "       "         "    w/   "  (base displacement): (bd, An, Xn)  #
13161da177e4SLinus Torvalds# Memory indirect postindexed: ([bd, An], Xn, od)		       #
13171da177e4SLinus Torvalds# Memory indirect preindexed: ([bd, An, Xn], od)		       #
13181da177e4SLinus Torvalds########################################################################
13191da177e4SLinus Torvalds_addr_ind_ext:
13201da177e4SLinus Torvalds	mov.l		%d1,-(%sp)
13211da177e4SLinus Torvalds
13221da177e4SLinus Torvalds	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
13231da177e4SLinus Torvalds	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
13241da177e4SLinus Torvalds	bsr.l		_imem_read_word		# fetch extword in d0
13251da177e4SLinus Torvalds
13261da177e4SLinus Torvalds	tst.l		%d1			# ifetch error?
13271da177e4SLinus Torvalds	bne.l		isp_iacc		# yes
13281da177e4SLinus Torvalds
13291da177e4SLinus Torvalds	mov.l		(%sp)+,%d1
13301da177e4SLinus Torvalds
13311da177e4SLinus Torvalds	mov.l		(EXC_AREGS,%a6,%d1.w*4),%a0 # put base in a0
13321da177e4SLinus Torvalds
13331da177e4SLinus Torvalds	btst		&0x8,%d0
13341da177e4SLinus Torvalds	beq.b		addr_ind_index_8bit	# for ext word or not?
13351da177e4SLinus Torvalds
13361da177e4SLinus Torvalds	movm.l		&0x3c00,-(%sp)		# save d2-d5
13371da177e4SLinus Torvalds
13381da177e4SLinus Torvalds	mov.l		%d0,%d5			# put extword in d5
13391da177e4SLinus Torvalds	mov.l		%a0,%d3			# put base in d3
13401da177e4SLinus Torvalds
13411da177e4SLinus Torvalds	bra.l		calc_mem_ind		# calc memory indirect
13421da177e4SLinus Torvalds
13431da177e4SLinus Torvaldsaddr_ind_index_8bit:
13441da177e4SLinus Torvalds	mov.l		%d2,-(%sp)		# save old d2
13451da177e4SLinus Torvalds
13461da177e4SLinus Torvalds	mov.l		%d0,%d1
13471da177e4SLinus Torvalds	rol.w		&0x4,%d1
13481da177e4SLinus Torvalds	andi.w		&0xf,%d1		# extract index regno
13491da177e4SLinus Torvalds
13501da177e4SLinus Torvalds	mov.l		(EXC_DREGS,%a6,%d1.w*4),%d1 # fetch index reg value
13511da177e4SLinus Torvalds
13521da177e4SLinus Torvalds	btst		&0xb,%d0		# is it word or long?
13531da177e4SLinus Torvalds	bne.b		aii8_long
13541da177e4SLinus Torvalds	ext.l		%d1			# sign extend word index
13551da177e4SLinus Torvaldsaii8_long:
13561da177e4SLinus Torvalds	mov.l		%d0,%d2
13571da177e4SLinus Torvalds	rol.w		&0x7,%d2
13581da177e4SLinus Torvalds	andi.l		&0x3,%d2		# extract scale value
13591da177e4SLinus Torvalds
13601da177e4SLinus Torvalds	lsl.l		%d2,%d1			# shift index by scale
13611da177e4SLinus Torvalds
13621da177e4SLinus Torvalds	extb.l		%d0			# sign extend displacement
13631da177e4SLinus Torvalds	add.l		%d1,%d0			# index + disp
13641da177e4SLinus Torvalds	add.l		%d0,%a0			# An + (index + disp)
13651da177e4SLinus Torvalds
13661da177e4SLinus Torvalds	mov.l		(%sp)+,%d2		# restore old d2
13671da177e4SLinus Torvalds	rts
13681da177e4SLinus Torvalds
13691da177e4SLinus Torvalds######################
13701da177e4SLinus Torvalds# Immediate: #<data> #
13711da177e4SLinus Torvalds#########################################################################
13721da177e4SLinus Torvalds# word, long: <ea> of the data is the current extension word		#
13731da177e4SLinus Torvalds#	pointer value. new extension word pointer is simply the old	#
13741da177e4SLinus Torvalds#	plus the number of bytes in the data type(2 or 4).		#
13751da177e4SLinus Torvalds#########################################################################
13761da177e4SLinus Torvaldsimmediate:
13771da177e4SLinus Torvalds	mov.b		&immed_flg,SPCOND_FLG(%a6) # set immediate flag
13781da177e4SLinus Torvalds
13791da177e4SLinus Torvalds	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch extension word ptr
13801da177e4SLinus Torvalds	rts
13811da177e4SLinus Torvalds
13821da177e4SLinus Torvalds###########################
13831da177e4SLinus Torvalds# Absolute short: (XXX).W #
13841da177e4SLinus Torvalds###########################
13851da177e4SLinus Torvaldsabs_short:
13861da177e4SLinus Torvalds	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
13871da177e4SLinus Torvalds	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
13881da177e4SLinus Torvalds	bsr.l		_imem_read_word		# fetch short address
13891da177e4SLinus Torvalds
13901da177e4SLinus Torvalds	tst.l		%d1			# ifetch error?
13911da177e4SLinus Torvalds	bne.l		isp_iacc		# yes
13921da177e4SLinus Torvalds
13931da177e4SLinus Torvalds	mov.w		%d0,%a0			# return <ea> in a0
13941da177e4SLinus Torvalds	rts
13951da177e4SLinus Torvalds
13961da177e4SLinus Torvalds##########################
13971da177e4SLinus Torvalds# Absolute long: (XXX).L #
13981da177e4SLinus Torvalds##########################
13991da177e4SLinus Torvaldsabs_long:
14001da177e4SLinus Torvalds	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
14011da177e4SLinus Torvalds	addq.l		&0x4,EXC_EXTWPTR(%a6)	# incr instruction ptr
14021da177e4SLinus Torvalds	bsr.l		_imem_read_long		# fetch long address
14031da177e4SLinus Torvalds
14041da177e4SLinus Torvalds	tst.l		%d1			# ifetch error?
14051da177e4SLinus Torvalds	bne.l		isp_iacc		# yes
14061da177e4SLinus Torvalds
14071da177e4SLinus Torvalds	mov.l		%d0,%a0			# return <ea> in a0
14081da177e4SLinus Torvalds	rts
14091da177e4SLinus Torvalds
14101da177e4SLinus Torvalds#######################################################
14111da177e4SLinus Torvalds# Program counter indirect w/ displacement: (d16, PC) #
14121da177e4SLinus Torvalds#######################################################
14131da177e4SLinus Torvaldspc_ind:
14141da177e4SLinus Torvalds	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
14151da177e4SLinus Torvalds	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
14161da177e4SLinus Torvalds	bsr.l		_imem_read_word		# fetch word displacement
14171da177e4SLinus Torvalds
14181da177e4SLinus Torvalds	tst.l		%d1			# ifetch error?
14191da177e4SLinus Torvalds	bne.l		isp_iacc		# yes
14201da177e4SLinus Torvalds
14211da177e4SLinus Torvalds	mov.w		%d0,%a0			# sign extend displacement
14221da177e4SLinus Torvalds
14231da177e4SLinus Torvalds	add.l		EXC_EXTWPTR(%a6),%a0	# pc + d16
14241da177e4SLinus Torvalds
14251da177e4SLinus Torvalds# _imem_read_word() increased the extwptr by 2. need to adjust here.
14261da177e4SLinus Torvalds	subq.l		&0x2,%a0		# adjust <ea>
14271da177e4SLinus Torvalds
14281da177e4SLinus Torvalds	rts
14291da177e4SLinus Torvalds
14301da177e4SLinus Torvalds##########################################################
14311da177e4SLinus Torvalds# PC indirect w/ index(8-bit displacement): (d8, PC, An) #
14321da177e4SLinus Torvalds# "     "     w/   "  (base displacement): (bd, PC, An)  #
14331da177e4SLinus Torvalds# PC memory indirect postindexed: ([bd, PC], Xn, od)     #
14341da177e4SLinus Torvalds# PC memory indirect preindexed: ([bd, PC, Xn], od)      #
14351da177e4SLinus Torvalds##########################################################
14361da177e4SLinus Torvaldspc_ind_ext:
14371da177e4SLinus Torvalds	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
14381da177e4SLinus Torvalds	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
14391da177e4SLinus Torvalds	bsr.l		_imem_read_word		# fetch ext word
14401da177e4SLinus Torvalds
14411da177e4SLinus Torvalds	tst.l		%d1			# ifetch error?
14421da177e4SLinus Torvalds	bne.l		isp_iacc		# yes
14431da177e4SLinus Torvalds
14441da177e4SLinus Torvalds	mov.l		EXC_EXTWPTR(%a6),%a0	# put base in a0
14451da177e4SLinus Torvalds	subq.l		&0x2,%a0		# adjust base
14461da177e4SLinus Torvalds
14471da177e4SLinus Torvalds	btst		&0x8,%d0		# is disp only 8 bits?
14481da177e4SLinus Torvalds	beq.b		pc_ind_index_8bit	# yes
14491da177e4SLinus Torvalds
14501da177e4SLinus Torvalds# the indexed addressing mode uses a base displacement of size
14511da177e4SLinus Torvalds# word or long
14521da177e4SLinus Torvalds	movm.l		&0x3c00,-(%sp)		# save d2-d5
14531da177e4SLinus Torvalds
14541da177e4SLinus Torvalds	mov.l		%d0,%d5			# put extword in d5
14551da177e4SLinus Torvalds	mov.l		%a0,%d3			# put base in d3
14561da177e4SLinus Torvalds
14571da177e4SLinus Torvalds	bra.l		calc_mem_ind		# calc memory indirect
14581da177e4SLinus Torvalds
14591da177e4SLinus Torvaldspc_ind_index_8bit:
14601da177e4SLinus Torvalds	mov.l		%d2,-(%sp)		# create a temp register
14611da177e4SLinus Torvalds
14621da177e4SLinus Torvalds	mov.l		%d0,%d1			# make extword copy
14631da177e4SLinus Torvalds	rol.w		&0x4,%d1		# rotate reg num into place
14641da177e4SLinus Torvalds	andi.w		&0xf,%d1		# extract register number
14651da177e4SLinus Torvalds
14661da177e4SLinus Torvalds	mov.l		(EXC_DREGS,%a6,%d1.w*4),%d1 # fetch index reg value
14671da177e4SLinus Torvalds
14681da177e4SLinus Torvalds	btst		&0xb,%d0		# is index word or long?
14691da177e4SLinus Torvalds	bne.b		pii8_long		# long
14701da177e4SLinus Torvalds	ext.l		%d1			# sign extend word index
14711da177e4SLinus Torvaldspii8_long:
14721da177e4SLinus Torvalds	mov.l		%d0,%d2			# make extword copy
14731da177e4SLinus Torvalds	rol.w		&0x7,%d2		# rotate scale value into place
14741da177e4SLinus Torvalds	andi.l		&0x3,%d2		# extract scale value
14751da177e4SLinus Torvalds
14761da177e4SLinus Torvalds	lsl.l		%d2,%d1			# shift index by scale
14771da177e4SLinus Torvalds
14781da177e4SLinus Torvalds	extb.l		%d0			# sign extend displacement
14791da177e4SLinus Torvalds	add.l		%d1,%d0			# index + disp
14801da177e4SLinus Torvalds	add.l		%d0,%a0			# An + (index + disp)
14811da177e4SLinus Torvalds
14821da177e4SLinus Torvalds	mov.l		(%sp)+,%d2		# restore temp register
14831da177e4SLinus Torvalds
14841da177e4SLinus Torvalds	rts
14851da177e4SLinus Torvalds
14861da177e4SLinus Torvalds# a5 = exc_extwptr	(global to uaeh)
14871da177e4SLinus Torvalds# a4 = exc_opword	(global to uaeh)
14881da177e4SLinus Torvalds# a3 = exc_dregs	(global to uaeh)
14891da177e4SLinus Torvalds
14901da177e4SLinus Torvalds# d2 = index		(internal "     "    )
14911da177e4SLinus Torvalds# d3 = base		(internal "     "    )
14921da177e4SLinus Torvalds# d4 = od		(internal "     "    )
14931da177e4SLinus Torvalds# d5 = extword		(internal "     "    )
14941da177e4SLinus Torvaldscalc_mem_ind:
14951da177e4SLinus Torvalds	btst		&0x6,%d5		# is the index suppressed?
14961da177e4SLinus Torvalds	beq.b		calc_index
14971da177e4SLinus Torvalds	clr.l		%d2			# yes, so index = 0
14981da177e4SLinus Torvalds	bra.b		base_supp_ck
14991da177e4SLinus Torvaldscalc_index:
15001da177e4SLinus Torvalds	bfextu		%d5{&16:&4},%d2
15011da177e4SLinus Torvalds	mov.l		(EXC_DREGS,%a6,%d2.w*4),%d2
15021da177e4SLinus Torvalds	btst		&0xb,%d5		# is index word or long?
15031da177e4SLinus Torvalds	bne.b		no_ext
15041da177e4SLinus Torvalds	ext.l		%d2
15051da177e4SLinus Torvaldsno_ext:
15061da177e4SLinus Torvalds	bfextu		%d5{&21:&2},%d0
15071da177e4SLinus Torvalds	lsl.l		%d0,%d2
15081da177e4SLinus Torvaldsbase_supp_ck:
15091da177e4SLinus Torvalds	btst		&0x7,%d5		# is the bd suppressed?
15101da177e4SLinus Torvalds	beq.b		no_base_sup
15111da177e4SLinus Torvalds	clr.l		%d3
15121da177e4SLinus Torvaldsno_base_sup:
15131da177e4SLinus Torvalds	bfextu		%d5{&26:&2},%d0	# get bd size
15141da177e4SLinus Torvalds#	beq.l		_error			# if (size == 0) it's reserved
15151da177e4SLinus Torvalds	cmpi.b		%d0,&2
15161da177e4SLinus Torvalds	blt.b		no_bd
15171da177e4SLinus Torvalds	beq.b		get_word_bd
15181da177e4SLinus Torvalds
15191da177e4SLinus Torvalds	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
15201da177e4SLinus Torvalds	addq.l		&0x4,EXC_EXTWPTR(%a6)	# incr instruction ptr
15211da177e4SLinus Torvalds	bsr.l		_imem_read_long
15221da177e4SLinus Torvalds
15231da177e4SLinus Torvalds	tst.l		%d1			# ifetch error?
15241da177e4SLinus Torvalds	bne.l		isp_iacc		# yes
15251da177e4SLinus Torvalds
15261da177e4SLinus Torvalds	bra.b		chk_ind
15271da177e4SLinus Torvaldsget_word_bd:
15281da177e4SLinus Torvalds	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
15291da177e4SLinus Torvalds	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
15301da177e4SLinus Torvalds	bsr.l		_imem_read_word
15311da177e4SLinus Torvalds
15321da177e4SLinus Torvalds	tst.l		%d1			# ifetch error?
15331da177e4SLinus Torvalds	bne.l		isp_iacc		# yes
15341da177e4SLinus Torvalds
15351da177e4SLinus Torvalds	ext.l		%d0			# sign extend bd
15361da177e4SLinus Torvalds
15371da177e4SLinus Torvaldschk_ind:
15381da177e4SLinus Torvalds	add.l		%d0,%d3			# base += bd
15391da177e4SLinus Torvaldsno_bd:
15401da177e4SLinus Torvalds	bfextu		%d5{&30:&2},%d0		# is od suppressed?
15411da177e4SLinus Torvalds	beq.w		aii_bd
15421da177e4SLinus Torvalds	cmpi.b		%d0,&0x2
15431da177e4SLinus Torvalds	blt.b		null_od
15441da177e4SLinus Torvalds	beq.b		word_od
15451da177e4SLinus Torvalds
15461da177e4SLinus Torvalds	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
15471da177e4SLinus Torvalds	addq.l		&0x4,EXC_EXTWPTR(%a6)	# incr instruction ptr
15481da177e4SLinus Torvalds	bsr.l		_imem_read_long
15491da177e4SLinus Torvalds
15501da177e4SLinus Torvalds	tst.l		%d1			# ifetch error?
15511da177e4SLinus Torvalds	bne.l		isp_iacc		# yes
15521da177e4SLinus Torvalds
15531da177e4SLinus Torvalds	bra.b		add_them
15541da177e4SLinus Torvalds
15551da177e4SLinus Torvaldsword_od:
15561da177e4SLinus Torvalds	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
15571da177e4SLinus Torvalds	addq.l		&0x2,EXC_EXTWPTR(%a6)	# incr instruction ptr
15581da177e4SLinus Torvalds	bsr.l		_imem_read_word
15591da177e4SLinus Torvalds
15601da177e4SLinus Torvalds	tst.l		%d1			# ifetch error?
15611da177e4SLinus Torvalds	bne.l		isp_iacc		# yes
15621da177e4SLinus Torvalds
15631da177e4SLinus Torvalds	ext.l		%d0			# sign extend od
15641da177e4SLinus Torvalds	bra.b		add_them
15651da177e4SLinus Torvalds
15661da177e4SLinus Torvaldsnull_od:
15671da177e4SLinus Torvalds	clr.l		%d0
15681da177e4SLinus Torvaldsadd_them:
15691da177e4SLinus Torvalds	mov.l		%d0,%d4
15701da177e4SLinus Torvalds	btst		&0x2,%d5		# pre or post indexing?
15711da177e4SLinus Torvalds	beq.b		pre_indexed
15721da177e4SLinus Torvalds
15731da177e4SLinus Torvalds	mov.l		%d3,%a0
15741da177e4SLinus Torvalds	bsr.l		_dmem_read_long
15751da177e4SLinus Torvalds
15761da177e4SLinus Torvalds	tst.l		%d1			# dfetch error?
15771da177e4SLinus Torvalds	bne.b		calc_ea_err		# yes
15781da177e4SLinus Torvalds
15791da177e4SLinus Torvalds	add.l		%d2,%d0			# <ea> += index
15801da177e4SLinus Torvalds	add.l		%d4,%d0			# <ea> += od
15811da177e4SLinus Torvalds	bra.b		done_ea
15821da177e4SLinus Torvalds
15831da177e4SLinus Torvaldspre_indexed:
15841da177e4SLinus Torvalds	add.l		%d2,%d3			# preindexing
15851da177e4SLinus Torvalds	mov.l		%d3,%a0
15861da177e4SLinus Torvalds	bsr.l		_dmem_read_long
15871da177e4SLinus Torvalds
15881da177e4SLinus Torvalds	tst.l		%d1			# ifetch error?
15891da177e4SLinus Torvalds	bne.b		calc_ea_err		# yes
15901da177e4SLinus Torvalds
15911da177e4SLinus Torvalds	add.l		%d4,%d0			# ea += od
15921da177e4SLinus Torvalds	bra.b		done_ea
15931da177e4SLinus Torvalds
15941da177e4SLinus Torvaldsaii_bd:
15951da177e4SLinus Torvalds	add.l		%d2,%d3			# ea = (base + bd) + index
15961da177e4SLinus Torvalds	mov.l		%d3,%d0
15971da177e4SLinus Torvaldsdone_ea:
15981da177e4SLinus Torvalds	mov.l		%d0,%a0
15991da177e4SLinus Torvalds
16001da177e4SLinus Torvalds	movm.l		(%sp)+,&0x003c		# restore d2-d5
16011da177e4SLinus Torvalds	rts
16021da177e4SLinus Torvalds
16031da177e4SLinus Torvalds# if dmem_read_long() returns a fail message in d1, the package
16041da177e4SLinus Torvalds# must create an access error frame. here, we pass a skeleton fslw
16051da177e4SLinus Torvalds# and the failing address to the routine that creates the new frame.
16061da177e4SLinus Torvalds# FSLW:
16071da177e4SLinus Torvalds#	read = true
16081da177e4SLinus Torvalds#	size = longword
16091da177e4SLinus Torvalds#	TM = data
16101da177e4SLinus Torvalds#	software emulation error = true
16111da177e4SLinus Torvaldscalc_ea_err:
16121da177e4SLinus Torvalds	mov.l		%d3,%a0			# pass failing address
16131da177e4SLinus Torvalds	mov.l		&0x01010001,%d0		# pass fslw
16141da177e4SLinus Torvalds	bra.l		isp_dacc
16151da177e4SLinus Torvalds
16161da177e4SLinus Torvalds#########################################################################
16171da177e4SLinus Torvalds# XDEF **************************************************************** #
16181da177e4SLinus Torvalds#	_moveperipheral(): routine to emulate movep instruction		#
16191da177e4SLinus Torvalds#									#
16201da177e4SLinus Torvalds# XREF **************************************************************** #
16211da177e4SLinus Torvalds#	_dmem_read_byte() - read byte from memory			#
16221da177e4SLinus Torvalds#	_dmem_write_byte() - write byte to memory			#
16231da177e4SLinus Torvalds#	isp_dacc() - handle data access error exception			#
16241da177e4SLinus Torvalds#									#
16251da177e4SLinus Torvalds# INPUT *************************************************************** #
16261da177e4SLinus Torvalds#	none								#
16271da177e4SLinus Torvalds#									#
16281da177e4SLinus Torvalds# OUTPUT ************************************************************** #
16291da177e4SLinus Torvalds#	If exiting through isp_dacc...					#
16301da177e4SLinus Torvalds#		a0 = failing address					#
16311da177e4SLinus Torvalds#		d0 = FSLW						#
16321da177e4SLinus Torvalds#	else								#
16331da177e4SLinus Torvalds#		none							#
16341da177e4SLinus Torvalds#									#
16351da177e4SLinus Torvalds# ALGORITHM ***********************************************************	#
16361da177e4SLinus Torvalds#	Decode the movep instruction words stored at EXC_OPWORD and	#
16371da177e4SLinus Torvalds# either read or write the required bytes from/to memory. Use the	#
16381da177e4SLinus Torvalds# _dmem_{read,write}_byte() routines. If one of the memory routines	#
16391da177e4SLinus Torvalds# returns a failing value, we must pass the failing address and	a FSLW	#
16401da177e4SLinus Torvalds# to the _isp_dacc() routine.						#
16411da177e4SLinus Torvalds#	Since this instruction is used to access peripherals, make sure	#
16421da177e4SLinus Torvalds# to only access the required bytes.					#
16431da177e4SLinus Torvalds#									#
16441da177e4SLinus Torvalds#########################################################################
16451da177e4SLinus Torvalds
16461da177e4SLinus Torvalds###########################
16471da177e4SLinus Torvalds# movep.(w,l)	Dx,(d,Ay) #
16481da177e4SLinus Torvalds# movep.(w,l)	(d,Ay),Dx #
16491da177e4SLinus Torvalds###########################
16501da177e4SLinus Torvalds	global		_moveperipheral
16511da177e4SLinus Torvalds_moveperipheral:
16521da177e4SLinus Torvalds	mov.w		EXC_OPWORD(%a6),%d1	# fetch the opcode word
16531da177e4SLinus Torvalds
16541da177e4SLinus Torvalds	mov.b		%d1,%d0
16551da177e4SLinus Torvalds	and.w		&0x7,%d0		# extract Ay from opcode word
16561da177e4SLinus Torvalds
16571da177e4SLinus Torvalds	mov.l		(EXC_AREGS,%a6,%d0.w*4),%a0 # fetch ay
16581da177e4SLinus Torvalds
16591da177e4SLinus Torvalds	add.w		EXC_EXTWORD(%a6),%a0	# add: an + sgn_ext(disp)
16601da177e4SLinus Torvalds
16611da177e4SLinus Torvalds	btst		&0x7,%d1		# (reg 2 mem) or (mem 2 reg)
16621da177e4SLinus Torvalds	beq.w		mem2reg
16631da177e4SLinus Torvalds
16641da177e4SLinus Torvalds# reg2mem: fetch dx, then write it to memory
16651da177e4SLinus Torvaldsreg2mem:
16661da177e4SLinus Torvalds	mov.w		%d1,%d0
16671da177e4SLinus Torvalds	rol.w		&0x7,%d0
16681da177e4SLinus Torvalds	and.w		&0x7,%d0		# extract Dx from opcode word
16691da177e4SLinus Torvalds
16701da177e4SLinus Torvalds	mov.l		(EXC_DREGS,%a6,%d0.w*4), %d0 # fetch dx
16711da177e4SLinus Torvalds
16721da177e4SLinus Torvalds	btst		&0x6,%d1		# word or long operation?
16731da177e4SLinus Torvalds	beq.b		r2mwtrans
16741da177e4SLinus Torvalds
16751da177e4SLinus Torvalds# a0 = dst addr
16761da177e4SLinus Torvalds# d0 = Dx
16771da177e4SLinus Torvaldsr2mltrans:
16781da177e4SLinus Torvalds	mov.l		%d0,%d2			# store data
16791da177e4SLinus Torvalds	mov.l		%a0,%a2			# store addr
16801da177e4SLinus Torvalds	rol.l		&0x8,%d2
16811da177e4SLinus Torvalds	mov.l		%d2,%d0
16821da177e4SLinus Torvalds
16831da177e4SLinus Torvalds	bsr.l		_dmem_write_byte	# os  : write hi
16841da177e4SLinus Torvalds
16851da177e4SLinus Torvalds	tst.l		%d1			# dfetch error?
16861da177e4SLinus Torvalds	bne.w		movp_write_err		# yes
16871da177e4SLinus Torvalds
16881da177e4SLinus Torvalds	add.w		&0x2,%a2		# incr addr
16891da177e4SLinus Torvalds	mov.l		%a2,%a0
16901da177e4SLinus Torvalds	rol.l		&0x8,%d2
16911da177e4SLinus Torvalds	mov.l		%d2,%d0
16921da177e4SLinus Torvalds
16931da177e4SLinus Torvalds	bsr.l		_dmem_write_byte	# os  : write lo
16941da177e4SLinus Torvalds
16951da177e4SLinus Torvalds	tst.l		%d1			# dfetch error?
16961da177e4SLinus Torvalds	bne.w		movp_write_err		# yes
16971da177e4SLinus Torvalds
16981da177e4SLinus Torvalds	add.w		&0x2,%a2		# incr addr
16991da177e4SLinus Torvalds	mov.l		%a2,%a0
17001da177e4SLinus Torvalds	rol.l		&0x8,%d2
17011da177e4SLinus Torvalds	mov.l		%d2,%d0
17021da177e4SLinus Torvalds
17031da177e4SLinus Torvalds	bsr.l		_dmem_write_byte	# os  : write lo
17041da177e4SLinus Torvalds
17051da177e4SLinus Torvalds	tst.l		%d1			# dfetch error?
17061da177e4SLinus Torvalds	bne.w		movp_write_err		# yes
17071da177e4SLinus Torvalds
17081da177e4SLinus Torvalds	add.w		&0x2,%a2		# incr addr
17091da177e4SLinus Torvalds	mov.l		%a2,%a0
17101da177e4SLinus Torvalds	rol.l		&0x8,%d2
17111da177e4SLinus Torvalds	mov.l		%d2,%d0
17121da177e4SLinus Torvalds
17131da177e4SLinus Torvalds	bsr.l		_dmem_write_byte	# os  : write lo
17141da177e4SLinus Torvalds
17151da177e4SLinus Torvalds	tst.l		%d1			# dfetch error?
17161da177e4SLinus Torvalds	bne.w		movp_write_err		# yes
17171da177e4SLinus Torvalds
17181da177e4SLinus Torvalds	rts
17191da177e4SLinus Torvalds
17201da177e4SLinus Torvalds# a0 = dst addr
17211da177e4SLinus Torvalds# d0 = Dx
17221da177e4SLinus Torvaldsr2mwtrans:
17231da177e4SLinus Torvalds	mov.l		%d0,%d2			# store data
17241da177e4SLinus Torvalds	mov.l		%a0,%a2			# store addr
17251da177e4SLinus Torvalds	lsr.w		&0x8,%d0
17261da177e4SLinus Torvalds
17271da177e4SLinus Torvalds	bsr.l		_dmem_write_byte	# os  : write hi
17281da177e4SLinus Torvalds
17291da177e4SLinus Torvalds	tst.l		%d1			# dfetch error?
17301da177e4SLinus Torvalds	bne.w		movp_write_err		# yes
17311da177e4SLinus Torvalds
17321da177e4SLinus Torvalds	add.w		&0x2,%a2
17331da177e4SLinus Torvalds	mov.l		%a2,%a0
17341da177e4SLinus Torvalds	mov.l		%d2,%d0
17351da177e4SLinus Torvalds
17361da177e4SLinus Torvalds	bsr.l		_dmem_write_byte	# os  : write lo
17371da177e4SLinus Torvalds
17381da177e4SLinus Torvalds	tst.l		%d1			# dfetch error?
17391da177e4SLinus Torvalds	bne.w		movp_write_err		# yes
17401da177e4SLinus Torvalds
17411da177e4SLinus Torvalds	rts
17421da177e4SLinus Torvalds
17431da177e4SLinus Torvalds# mem2reg: read bytes from memory.
17441da177e4SLinus Torvalds# determines the dest register, and then writes the bytes into it.
17451da177e4SLinus Torvaldsmem2reg:
17461da177e4SLinus Torvalds	btst		&0x6,%d1		# word or long operation?
17471da177e4SLinus Torvalds	beq.b		m2rwtrans
17481da177e4SLinus Torvalds
17491da177e4SLinus Torvalds# a0 = dst addr
17501da177e4SLinus Torvaldsm2rltrans:
17511da177e4SLinus Torvalds	mov.l		%a0,%a2			# store addr
17521da177e4SLinus Torvalds
17531da177e4SLinus Torvalds	bsr.l		_dmem_read_byte		# read first byte
17541da177e4SLinus Torvalds
17551da177e4SLinus Torvalds	tst.l		%d1			# dfetch error?
17561da177e4SLinus Torvalds	bne.w		movp_read_err		# yes
17571da177e4SLinus Torvalds
17581da177e4SLinus Torvalds	mov.l		%d0,%d2
17591da177e4SLinus Torvalds
17601da177e4SLinus Torvalds	add.w		&0x2,%a2		# incr addr by 2 bytes
17611da177e4SLinus Torvalds	mov.l		%a2,%a0
17621da177e4SLinus Torvalds
17631da177e4SLinus Torvalds	bsr.l		_dmem_read_byte		# read second byte
17641da177e4SLinus Torvalds
17651da177e4SLinus Torvalds	tst.l		%d1			# dfetch error?
17661da177e4SLinus Torvalds	bne.w		movp_read_err		# yes
17671da177e4SLinus Torvalds
17681da177e4SLinus Torvalds	lsl.w		&0x8,%d2
17691da177e4SLinus Torvalds	mov.b		%d0,%d2			# append bytes
17701da177e4SLinus Torvalds
17711da177e4SLinus Torvalds	add.w		&0x2,%a2		# incr addr by 2 bytes
17721da177e4SLinus Torvalds	mov.l		%a2,%a0
17731da177e4SLinus Torvalds
17741da177e4SLinus Torvalds	bsr.l		_dmem_read_byte		# read second byte
17751da177e4SLinus Torvalds
17761da177e4SLinus Torvalds	tst.l		%d1			# dfetch error?
17771da177e4SLinus Torvalds	bne.w		movp_read_err		# yes
17781da177e4SLinus Torvalds
17791da177e4SLinus Torvalds	lsl.l		&0x8,%d2
17801da177e4SLinus Torvalds	mov.b		%d0,%d2			# append bytes
17811da177e4SLinus Torvalds
17821da177e4SLinus Torvalds	add.w		&0x2,%a2		# incr addr by 2 bytes
17831da177e4SLinus Torvalds	mov.l		%a2,%a0
17841da177e4SLinus Torvalds
17851da177e4SLinus Torvalds	bsr.l		_dmem_read_byte		# read second byte
17861da177e4SLinus Torvalds
17871da177e4SLinus Torvalds	tst.l		%d1			# dfetch error?
17881da177e4SLinus Torvalds	bne.w		movp_read_err		# yes
17891da177e4SLinus Torvalds
17901da177e4SLinus Torvalds	lsl.l		&0x8,%d2
17911da177e4SLinus Torvalds	mov.b		%d0,%d2			# append bytes
17921da177e4SLinus Torvalds
17931da177e4SLinus Torvalds	mov.b		EXC_OPWORD(%a6),%d1
17941da177e4SLinus Torvalds	lsr.b		&0x1,%d1
17951da177e4SLinus Torvalds	and.w		&0x7,%d1		# extract Dx from opcode word
17961da177e4SLinus Torvalds
17971da177e4SLinus Torvalds	mov.l		%d2,(EXC_DREGS,%a6,%d1.w*4) # store dx
17981da177e4SLinus Torvalds
17991da177e4SLinus Torvalds	rts
18001da177e4SLinus Torvalds
18011da177e4SLinus Torvalds# a0 = dst addr
18021da177e4SLinus Torvaldsm2rwtrans:
18031da177e4SLinus Torvalds	mov.l		%a0,%a2			# store addr
18041da177e4SLinus Torvalds
18051da177e4SLinus Torvalds	bsr.l		_dmem_read_byte		# read first byte
18061da177e4SLinus Torvalds
18071da177e4SLinus Torvalds	tst.l		%d1			# dfetch error?
18081da177e4SLinus Torvalds	bne.w		movp_read_err		# yes
18091da177e4SLinus Torvalds
18101da177e4SLinus Torvalds	mov.l		%d0,%d2
18111da177e4SLinus Torvalds
18121da177e4SLinus Torvalds	add.w		&0x2,%a2		# incr addr by 2 bytes
18131da177e4SLinus Torvalds	mov.l		%a2,%a0
18141da177e4SLinus Torvalds
18151da177e4SLinus Torvalds	bsr.l		_dmem_read_byte		# read second byte
18161da177e4SLinus Torvalds
18171da177e4SLinus Torvalds	tst.l		%d1			# dfetch error?
18181da177e4SLinus Torvalds	bne.w		movp_read_err		# yes
18191da177e4SLinus Torvalds
18201da177e4SLinus Torvalds	lsl.w		&0x8,%d2
18211da177e4SLinus Torvalds	mov.b		%d0,%d2			# append bytes
18221da177e4SLinus Torvalds
18231da177e4SLinus Torvalds	mov.b		EXC_OPWORD(%a6),%d1
18241da177e4SLinus Torvalds	lsr.b		&0x1,%d1
18251da177e4SLinus Torvalds	and.w		&0x7,%d1		# extract Dx from opcode word
18261da177e4SLinus Torvalds
18271da177e4SLinus Torvalds	mov.w		%d2,(EXC_DREGS+2,%a6,%d1.w*4) # store dx
18281da177e4SLinus Torvalds
18291da177e4SLinus Torvalds	rts
18301da177e4SLinus Torvalds
18311da177e4SLinus Torvalds# if dmem_{read,write}_byte() returns a fail message in d1, the package
18321da177e4SLinus Torvalds# must create an access error frame. here, we pass a skeleton fslw
18331da177e4SLinus Torvalds# and the failing address to the routine that creates the new frame.
18341da177e4SLinus Torvalds# FSLW:
18351da177e4SLinus Torvalds#	write = true
18361da177e4SLinus Torvalds#	size = byte
18371da177e4SLinus Torvalds#	TM = data
18381da177e4SLinus Torvalds#	software emulation error = true
18391da177e4SLinus Torvaldsmovp_write_err:
18401da177e4SLinus Torvalds	mov.l		%a2,%a0			# pass failing address
18411da177e4SLinus Torvalds	mov.l		&0x00a10001,%d0		# pass fslw
18421da177e4SLinus Torvalds	bra.l		isp_dacc
18431da177e4SLinus Torvalds
18441da177e4SLinus Torvalds# FSLW:
18451da177e4SLinus Torvalds#	read = true
18461da177e4SLinus Torvalds#	size = byte
18471da177e4SLinus Torvalds#	TM = data
18481da177e4SLinus Torvalds#	software emulation error = true
18491da177e4SLinus Torvaldsmovp_read_err:
18501da177e4SLinus Torvalds	mov.l		%a2,%a0			# pass failing address
18511da177e4SLinus Torvalds	mov.l		&0x01210001,%d0		# pass fslw
18521da177e4SLinus Torvalds	bra.l		isp_dacc
18531da177e4SLinus Torvalds
18541da177e4SLinus Torvalds#########################################################################
18551da177e4SLinus Torvalds# XDEF ****************************************************************	#
18561da177e4SLinus Torvalds#	_chk2_cmp2(): routine to emulate chk2/cmp2 instructions		#
18571da177e4SLinus Torvalds#									#
18581da177e4SLinus Torvalds# XREF ****************************************************************	#
18591da177e4SLinus Torvalds#	_calc_ea(): calculate effective address				#
18601da177e4SLinus Torvalds#	_dmem_read_long(): read operands				#
18611da177e4SLinus Torvalds#	_dmem_read_word(): read operands				#
18621da177e4SLinus Torvalds#	isp_dacc(): handle data access error exception			#
18631da177e4SLinus Torvalds#									#
18641da177e4SLinus Torvalds# INPUT ***************************************************************	#
18651da177e4SLinus Torvalds#	none								#
18661da177e4SLinus Torvalds#									#
18671da177e4SLinus Torvalds# OUTPUT **************************************************************	#
18681da177e4SLinus Torvalds#	If exiting through isp_dacc...					#
18691da177e4SLinus Torvalds#		a0 = failing address					#
18701da177e4SLinus Torvalds#		d0 = FSLW						#
18711da177e4SLinus Torvalds#	else								#
18721da177e4SLinus Torvalds#		none							#
18731da177e4SLinus Torvalds#									#
18741da177e4SLinus Torvalds# ALGORITHM ***********************************************************	#
18751da177e4SLinus Torvalds#	First, calculate the effective address, then fetch the byte,	#
18761da177e4SLinus Torvalds# word, or longword sized operands. Then, in the interest of		#
18771da177e4SLinus Torvalds# simplicity, all operands are converted to longword size whether the	#
18781da177e4SLinus Torvalds# operation is byte, word, or long. The bounds are sign extended	#
1879*ad61dd30SStephen Boyd# accordingly. If Rn is a data register, Rn is also sign extended. If	#
18801da177e4SLinus Torvalds# Rn is an address register, it need not be sign extended since the	#
18811da177e4SLinus Torvalds# full register is always used.						#
18821da177e4SLinus Torvalds#	The comparisons are made and the condition codes calculated.	#
18831da177e4SLinus Torvalds# If the instruction is chk2 and the Rn value is out-of-bounds, set	#
18841da177e4SLinus Torvalds# the ichk_flg in SPCOND_FLG.						#
18851da177e4SLinus Torvalds#	If the memory fetch returns a failing value, pass the failing	#
18861da177e4SLinus Torvalds# address and FSLW to the isp_dacc() routine.				#
18871da177e4SLinus Torvalds#									#
18881da177e4SLinus Torvalds#########################################################################
18891da177e4SLinus Torvalds
18901da177e4SLinus Torvalds	global		_chk2_cmp2
18911da177e4SLinus Torvalds_chk2_cmp2:
18921da177e4SLinus Torvalds
18931da177e4SLinus Torvalds# passing size parameter doesn't matter since chk2 & cmp2 can't do
18941da177e4SLinus Torvalds# either predecrement, postincrement, or immediate.
18951da177e4SLinus Torvalds	bsr.l		_calc_ea		# calculate <ea>
18961da177e4SLinus Torvalds
18971da177e4SLinus Torvalds	mov.b		EXC_EXTWORD(%a6), %d0	# fetch hi extension word
18981da177e4SLinus Torvalds	rol.b		&0x4, %d0		# rotate reg bits into lo
18991da177e4SLinus Torvalds	and.w		&0xf, %d0		# extract reg bits
19001da177e4SLinus Torvalds
19011da177e4SLinus Torvalds	mov.l		(EXC_DREGS,%a6,%d0.w*4), %d2 # get regval
19021da177e4SLinus Torvalds
19031da177e4SLinus Torvalds	cmpi.b		EXC_OPWORD(%a6), &0x2	# what size is operation?
19041da177e4SLinus Torvalds	blt.b		chk2_cmp2_byte		# size == byte
19051da177e4SLinus Torvalds	beq.b		chk2_cmp2_word		# size == word
19061da177e4SLinus Torvalds
19071da177e4SLinus Torvalds# the bounds are longword size. call routine to read the lower
19081da177e4SLinus Torvalds# bound into d0 and the higher bound into d1.
19091da177e4SLinus Torvaldschk2_cmp2_long:
19101da177e4SLinus Torvalds	mov.l		%a0,%a2			# save copy of <ea>
19111da177e4SLinus Torvalds	bsr.l		_dmem_read_long		# fetch long lower bound
19121da177e4SLinus Torvalds
19131da177e4SLinus Torvalds	tst.l		%d1			# dfetch error?
19141da177e4SLinus Torvalds	bne.w		chk2_cmp2_err_l		# yes
19151da177e4SLinus Torvalds
19161da177e4SLinus Torvalds	mov.l		%d0,%d3			# save long lower bound
19171da177e4SLinus Torvalds	addq.l		&0x4,%a2
19181da177e4SLinus Torvalds	mov.l		%a2,%a0			# pass <ea> of long upper bound
19191da177e4SLinus Torvalds	bsr.l		_dmem_read_long		# fetch long upper bound
19201da177e4SLinus Torvalds
19211da177e4SLinus Torvalds	tst.l		%d1			# dfetch error?
19221da177e4SLinus Torvalds	bne.w		chk2_cmp2_err_l		# yes
19231da177e4SLinus Torvalds
19241da177e4SLinus Torvalds	mov.l		%d0,%d1			# long upper bound in d1
19251da177e4SLinus Torvalds	mov.l		%d3,%d0			# long lower bound in d0
19261da177e4SLinus Torvalds	bra.w		chk2_cmp2_compare	# go do the compare emulation
19271da177e4SLinus Torvalds
19281da177e4SLinus Torvalds# the bounds are word size. fetch them in one subroutine call by
19291da177e4SLinus Torvalds# reading a longword. sign extend both. if it's a data operation,
19301da177e4SLinus Torvalds# sign extend Rn to long, also.
19311da177e4SLinus Torvaldschk2_cmp2_word:
19321da177e4SLinus Torvalds	mov.l		%a0,%a2
19331da177e4SLinus Torvalds	bsr.l		_dmem_read_long		# fetch 2 word bounds
19341da177e4SLinus Torvalds
19351da177e4SLinus Torvalds	tst.l		%d1			# dfetch error?
19361da177e4SLinus Torvalds	bne.w		chk2_cmp2_err_l		# yes
19371da177e4SLinus Torvalds
19381da177e4SLinus Torvalds	mov.w		%d0, %d1		# place hi in %d1
19391da177e4SLinus Torvalds	swap		%d0			# place lo in %d0
19401da177e4SLinus Torvalds
19411da177e4SLinus Torvalds	ext.l		%d0			# sign extend lo bnd
19421da177e4SLinus Torvalds	ext.l		%d1			# sign extend hi bnd
19431da177e4SLinus Torvalds
19441da177e4SLinus Torvalds	btst		&0x7, EXC_EXTWORD(%a6)	# address compare?
19451da177e4SLinus Torvalds	bne.w		chk2_cmp2_compare	# yes; don't sign extend
19461da177e4SLinus Torvalds
19471da177e4SLinus Torvalds# operation is a data register compare.
19481da177e4SLinus Torvalds# sign extend word to long so we can do simple longword compares.
19491da177e4SLinus Torvalds	ext.l		%d2			# sign extend data word
19501da177e4SLinus Torvalds	bra.w		chk2_cmp2_compare	# go emulate compare
19511da177e4SLinus Torvalds
19521da177e4SLinus Torvalds# the bounds are byte size. fetch them in one subroutine call by
19531da177e4SLinus Torvalds# reading a word. sign extend both. if it's a data operation,
19541da177e4SLinus Torvalds# sign extend Rn to long, also.
19551da177e4SLinus Torvaldschk2_cmp2_byte:
19561da177e4SLinus Torvalds	mov.l		%a0,%a2
19571da177e4SLinus Torvalds	bsr.l		_dmem_read_word		# fetch 2 byte bounds
19581da177e4SLinus Torvalds
19591da177e4SLinus Torvalds	tst.l		%d1			# dfetch error?
19601da177e4SLinus Torvalds	bne.w		chk2_cmp2_err_w		# yes
19611da177e4SLinus Torvalds
19621da177e4SLinus Torvalds	mov.b		%d0, %d1		# place hi in %d1
19631da177e4SLinus Torvalds	lsr.w		&0x8, %d0		# place lo in %d0
19641da177e4SLinus Torvalds
19651da177e4SLinus Torvalds	extb.l		%d0			# sign extend lo bnd
19661da177e4SLinus Torvalds	extb.l		%d1			# sign extend hi bnd
19671da177e4SLinus Torvalds
19681da177e4SLinus Torvalds	btst		&0x7, EXC_EXTWORD(%a6)	# address compare?
19691da177e4SLinus Torvalds	bne.b		chk2_cmp2_compare	# yes; don't sign extend
19701da177e4SLinus Torvalds
19711da177e4SLinus Torvalds# operation is a data register compare.
19721da177e4SLinus Torvalds# sign extend byte to long so we can do simple longword compares.
19731da177e4SLinus Torvalds	extb.l		%d2			# sign extend data byte
19741da177e4SLinus Torvalds
19751da177e4SLinus Torvalds#
19761da177e4SLinus Torvalds# To set the ccodes correctly:
19771da177e4SLinus Torvalds#	(1) save 'Z' bit from (Rn - lo)
19781da177e4SLinus Torvalds#	(2) save 'Z' and 'N' bits from ((hi - lo) - (Rn - hi))
19791da177e4SLinus Torvalds#	(3) keep 'X', 'N', and 'V' from before instruction
19801da177e4SLinus Torvalds#	(4) combine ccodes
19811da177e4SLinus Torvalds#
19821da177e4SLinus Torvaldschk2_cmp2_compare:
19831da177e4SLinus Torvalds	sub.l		%d0, %d2		# (Rn - lo)
19841da177e4SLinus Torvalds	mov.w		%cc, %d3		# fetch resulting ccodes
19851da177e4SLinus Torvalds	andi.b		&0x4, %d3		# keep 'Z' bit
19861da177e4SLinus Torvalds	sub.l		%d0, %d1		# (hi - lo)
19871da177e4SLinus Torvalds	cmp.l		%d1,%d2			# ((hi - lo) - (Rn - hi))
19881da177e4SLinus Torvalds
19891da177e4SLinus Torvalds	mov.w		%cc, %d4		# fetch resulting ccodes
19901da177e4SLinus Torvalds	or.b		%d4, %d3		# combine w/ earlier ccodes
19911da177e4SLinus Torvalds	andi.b		&0x5, %d3		# keep 'Z' and 'N'
19921da177e4SLinus Torvalds
19931da177e4SLinus Torvalds	mov.w		EXC_CC(%a6), %d4	# fetch old ccodes
19941da177e4SLinus Torvalds	andi.b		&0x1a, %d4		# keep 'X','N','V' bits
19951da177e4SLinus Torvalds	or.b		%d3, %d4		# insert new ccodes
19961da177e4SLinus Torvalds	mov.w		%d4, EXC_CC(%a6)	# save new ccodes
19971da177e4SLinus Torvalds
19981da177e4SLinus Torvalds	btst		&0x3, EXC_EXTWORD(%a6)	# separate chk2,cmp2
19991da177e4SLinus Torvalds	bne.b		chk2_finish		# it's a chk2
20001da177e4SLinus Torvalds
20011da177e4SLinus Torvalds	rts
20021da177e4SLinus Torvalds
20031da177e4SLinus Torvalds# this code handles the only difference between chk2 and cmp2. chk2 would
20041da177e4SLinus Torvalds# have trapped out if the value was out of bounds. we check this by seeing
20051da177e4SLinus Torvalds# if the 'N' bit was set by the operation.
20061da177e4SLinus Torvaldschk2_finish:
20071da177e4SLinus Torvalds	btst		&0x0, %d4		# is 'N' bit set?
20081da177e4SLinus Torvalds	bne.b		chk2_trap		# yes;chk2 should trap
20091da177e4SLinus Torvalds	rts
20101da177e4SLinus Torvaldschk2_trap:
20111da177e4SLinus Torvalds	mov.b		&ichk_flg,SPCOND_FLG(%a6) # set "special case" flag
20121da177e4SLinus Torvalds	rts
20131da177e4SLinus Torvalds
20141da177e4SLinus Torvalds# if dmem_read_{long,word}() returns a fail message in d1, the package
20151da177e4SLinus Torvalds# must create an access error frame. here, we pass a skeleton fslw
20161da177e4SLinus Torvalds# and the failing address to the routine that creates the new frame.
20171da177e4SLinus Torvalds# FSLW:
20181da177e4SLinus Torvalds#	read = true
20191da177e4SLinus Torvalds#	size = longword
20201da177e4SLinus Torvalds#	TM = data
20211da177e4SLinus Torvalds#	software emulation error = true
20221da177e4SLinus Torvaldschk2_cmp2_err_l:
20231da177e4SLinus Torvalds	mov.l		%a2,%a0			# pass failing address
20241da177e4SLinus Torvalds	mov.l		&0x01010001,%d0		# pass fslw
20251da177e4SLinus Torvalds	bra.l		isp_dacc
20261da177e4SLinus Torvalds
20271da177e4SLinus Torvalds# FSLW:
20281da177e4SLinus Torvalds#	read = true
20291da177e4SLinus Torvalds#	size = word
20301da177e4SLinus Torvalds#	TM = data
20311da177e4SLinus Torvalds#	software emulation error = true
20321da177e4SLinus Torvaldschk2_cmp2_err_w:
20331da177e4SLinus Torvalds	mov.l		%a2,%a0			# pass failing address
20341da177e4SLinus Torvalds	mov.l		&0x01410001,%d0		# pass fslw
20351da177e4SLinus Torvalds	bra.l		isp_dacc
20361da177e4SLinus Torvalds
20371da177e4SLinus Torvalds#########################################################################
20381da177e4SLinus Torvalds# XDEF ****************************************************************	#
20391da177e4SLinus Torvalds#	_div64(): routine to emulate div{u,s}.l <ea>,Dr:Dq		#
20401da177e4SLinus Torvalds#							64/32->32r:32q	#
20411da177e4SLinus Torvalds#									#
20421da177e4SLinus Torvalds# XREF ****************************************************************	#
20431da177e4SLinus Torvalds#	_calc_ea() - calculate effective address			#
20441da177e4SLinus Torvalds#	isp_iacc() - handle instruction access error exception		#
20451da177e4SLinus Torvalds#	isp_dacc() - handle data access error exception			#
20461da177e4SLinus Torvalds#	isp_restore() - restore An on access error w/ -() or ()+	#
20471da177e4SLinus Torvalds#									#
20481da177e4SLinus Torvalds# INPUT ***************************************************************	#
20491da177e4SLinus Torvalds#	none								#
20501da177e4SLinus Torvalds#									#
20511da177e4SLinus Torvalds# OUTPUT **************************************************************	#
20521da177e4SLinus Torvalds#	If exiting through isp_dacc...					#
20531da177e4SLinus Torvalds#		a0 = failing address					#
20541da177e4SLinus Torvalds#		d0 = FSLW						#
20551da177e4SLinus Torvalds#	else								#
20561da177e4SLinus Torvalds#		none							#
20571da177e4SLinus Torvalds#									#
20581da177e4SLinus Torvalds# ALGORITHM ***********************************************************	#
20591da177e4SLinus Torvalds#	First, decode the operand location. If it's in Dn, fetch from	#
20601da177e4SLinus Torvalds# the stack. If it's in memory, use _calc_ea() to calculate the		#
20611da177e4SLinus Torvalds# effective address. Use _dmem_read_long() to fetch at that address.	#
20621da177e4SLinus Torvalds# Unless the operand is immediate data. Then use _imem_read_long().	#
20631da177e4SLinus Torvalds# Send failures to isp_dacc() or isp_iacc() as appropriate.		#
20641da177e4SLinus Torvalds#	If the operands are signed, make them unsigned and save	the	#
20651da177e4SLinus Torvalds# sign info for later. Separate out special cases like divide-by-zero	#
20661da177e4SLinus Torvalds# or 32-bit divides if possible. Else, use a special math algorithm	#
20671da177e4SLinus Torvalds# to calculate the result.						#
20681da177e4SLinus Torvalds#	Restore sign info if signed instruction. Set the condition	#
20691da177e4SLinus Torvalds# codes. Set idbyz_flg in SPCOND_FLG if divisor was zero. Store the	#
20701da177e4SLinus Torvalds# quotient and remainder in the appropriate data registers on the stack.#
20711da177e4SLinus Torvalds#									#
20721da177e4SLinus Torvalds#########################################################################
20731da177e4SLinus Torvalds
20741da177e4SLinus Torvaldsset	NDIVISOR,	EXC_TEMP+0x0
20751da177e4SLinus Torvaldsset	NDIVIDEND,	EXC_TEMP+0x1
20761da177e4SLinus Torvaldsset	NDRSAVE,	EXC_TEMP+0x2
20771da177e4SLinus Torvaldsset	NDQSAVE,	EXC_TEMP+0x4
20781da177e4SLinus Torvaldsset	DDSECOND,	EXC_TEMP+0x6
20791da177e4SLinus Torvaldsset	DDQUOTIENT,	EXC_TEMP+0x8
20801da177e4SLinus Torvaldsset	DDNORMAL,	EXC_TEMP+0xc
20811da177e4SLinus Torvalds
20821da177e4SLinus Torvalds	global		_div64
20831da177e4SLinus Torvalds#############
20841da177e4SLinus Torvalds# div(u,s)l #
20851da177e4SLinus Torvalds#############
20861da177e4SLinus Torvalds_div64:
20871da177e4SLinus Torvalds	mov.b		EXC_OPWORD+1(%a6), %d0
20881da177e4SLinus Torvalds	andi.b		&0x38, %d0		# extract src mode
20891da177e4SLinus Torvalds
20901da177e4SLinus Torvalds	bne.w		dcontrolmodel_s		# %dn dest or control mode?
20911da177e4SLinus Torvalds
20921da177e4SLinus Torvalds	mov.b		EXC_OPWORD+1(%a6), %d0	# extract Dn from opcode
20931da177e4SLinus Torvalds	andi.w		&0x7, %d0
20941da177e4SLinus Torvalds	mov.l		(EXC_DREGS,%a6,%d0.w*4), %d7 # fetch divisor from register
20951da177e4SLinus Torvalds
20961da177e4SLinus Torvaldsdgotsrcl:
20971da177e4SLinus Torvalds	beq.w		div64eq0		# divisor is = 0!!!
20981da177e4SLinus Torvalds
20991da177e4SLinus Torvalds	mov.b		EXC_EXTWORD+1(%a6), %d0	# extract Dr from extword
21001da177e4SLinus Torvalds	mov.b		EXC_EXTWORD(%a6), %d1	# extract Dq from extword
21011da177e4SLinus Torvalds	and.w		&0x7, %d0
21021da177e4SLinus Torvalds	lsr.b		&0x4, %d1
21031da177e4SLinus Torvalds	and.w		&0x7, %d1
21041da177e4SLinus Torvalds	mov.w		%d0, NDRSAVE(%a6)	# save Dr for later
21051da177e4SLinus Torvalds	mov.w		%d1, NDQSAVE(%a6)	# save Dq for later
21061da177e4SLinus Torvalds
21071da177e4SLinus Torvalds# fetch %dr and %dq directly off stack since all regs are saved there
21081da177e4SLinus Torvalds	mov.l		(EXC_DREGS,%a6,%d0.w*4), %d5 # get dividend hi
21091da177e4SLinus Torvalds	mov.l		(EXC_DREGS,%a6,%d1.w*4), %d6 # get dividend lo
21101da177e4SLinus Torvalds
21111da177e4SLinus Torvalds# separate signed and unsigned divide
21121da177e4SLinus Torvalds	btst		&0x3, EXC_EXTWORD(%a6)	# signed or unsigned?
21131da177e4SLinus Torvalds	beq.b		dspecialcases		# use positive divide
21141da177e4SLinus Torvalds
21151da177e4SLinus Torvalds# save the sign of the divisor
21161da177e4SLinus Torvalds# make divisor unsigned if it's negative
21171da177e4SLinus Torvalds	tst.l		%d7			# chk sign of divisor
21181da177e4SLinus Torvalds	slt		NDIVISOR(%a6)		# save sign of divisor
21191da177e4SLinus Torvalds	bpl.b		dsgndividend
21201da177e4SLinus Torvalds	neg.l		%d7			# complement negative divisor
21211da177e4SLinus Torvalds
21221da177e4SLinus Torvalds# save the sign of the dividend
21231da177e4SLinus Torvalds# make dividend unsigned if it's negative
21241da177e4SLinus Torvaldsdsgndividend:
21251da177e4SLinus Torvalds	tst.l		%d5			# chk sign of hi(dividend)
21261da177e4SLinus Torvalds	slt		NDIVIDEND(%a6)		# save sign of dividend
21271da177e4SLinus Torvalds	bpl.b		dspecialcases
21281da177e4SLinus Torvalds
21291da177e4SLinus Torvalds	mov.w		&0x0, %cc		# clear 'X' cc bit
21301da177e4SLinus Torvalds	negx.l		%d6			# complement signed dividend
21311da177e4SLinus Torvalds	negx.l		%d5
21321da177e4SLinus Torvalds
21331da177e4SLinus Torvalds# extract some special cases:
21341da177e4SLinus Torvalds#	- is (dividend == 0) ?
21351da177e4SLinus Torvalds#	- is (hi(dividend) == 0 && (divisor <= lo(dividend))) ? (32-bit div)
21361da177e4SLinus Torvaldsdspecialcases:
21371da177e4SLinus Torvalds	tst.l		%d5			# is (hi(dividend) == 0)
21381da177e4SLinus Torvalds	bne.b		dnormaldivide		# no, so try it the long way
21391da177e4SLinus Torvalds
21401da177e4SLinus Torvalds	tst.l		%d6			# is (lo(dividend) == 0), too
21411da177e4SLinus Torvalds	beq.w		ddone			# yes, so (dividend == 0)
21421da177e4SLinus Torvalds
21431da177e4SLinus Torvalds	cmp.l		%d7,%d6			# is (divisor <= lo(dividend))
21441da177e4SLinus Torvalds	bls.b		d32bitdivide		# yes, so use 32 bit divide
21451da177e4SLinus Torvalds
21461da177e4SLinus Torvalds	exg		%d5,%d6			# q = 0, r = dividend
21471da177e4SLinus Torvalds	bra.w		divfinish		# can't divide, we're done.
21481da177e4SLinus Torvalds
21491da177e4SLinus Torvaldsd32bitdivide:
21501da177e4SLinus Torvalds	tdivu.l		%d7, %d5:%d6		# it's only a 32/32 bit div!
21511da177e4SLinus Torvalds
21521da177e4SLinus Torvalds	bra.b		divfinish
21531da177e4SLinus Torvalds
21541da177e4SLinus Torvaldsdnormaldivide:
21551da177e4SLinus Torvalds# last special case:
21561da177e4SLinus Torvalds#	- is hi(dividend) >= divisor ? if yes, then overflow
21571da177e4SLinus Torvalds	cmp.l		%d7,%d5
21581da177e4SLinus Torvalds	bls.b		ddovf			# answer won't fit in 32 bits
21591da177e4SLinus Torvalds
21601da177e4SLinus Torvalds# perform the divide algorithm:
21611da177e4SLinus Torvalds	bsr.l		dclassical		# do int divide
21621da177e4SLinus Torvalds
21631da177e4SLinus Torvalds# separate into signed and unsigned finishes.
21641da177e4SLinus Torvaldsdivfinish:
21651da177e4SLinus Torvalds	btst		&0x3, EXC_EXTWORD(%a6)	# do divs, divu separately
21661da177e4SLinus Torvalds	beq.b		ddone			# divu has no processing!!!
21671da177e4SLinus Torvalds
21681da177e4SLinus Torvalds# it was a divs.l, so ccode setting is a little more complicated...
21691da177e4SLinus Torvalds	tst.b		NDIVIDEND(%a6)		# remainder has same sign
21701da177e4SLinus Torvalds	beq.b		dcc			# as dividend.
21711da177e4SLinus Torvalds	neg.l		%d5			# sgn(rem) = sgn(dividend)
21721da177e4SLinus Torvaldsdcc:
21731da177e4SLinus Torvalds	mov.b		NDIVISOR(%a6), %d0
21741da177e4SLinus Torvalds	eor.b		%d0, NDIVIDEND(%a6)	# chk if quotient is negative
21751da177e4SLinus Torvalds	beq.b		dqpos			# branch to quot positive
21761da177e4SLinus Torvalds
21771da177e4SLinus Torvalds# 0x80000000 is the largest number representable as a 32-bit negative
21781da177e4SLinus Torvalds# number. the negative of 0x80000000 is 0x80000000.
21791da177e4SLinus Torvalds	cmpi.l		%d6, &0x80000000	# will (-quot) fit in 32 bits?
21801da177e4SLinus Torvalds	bhi.b		ddovf
21811da177e4SLinus Torvalds
21821da177e4SLinus Torvalds	neg.l		%d6			# make (-quot) 2's comp
21831da177e4SLinus Torvalds
21841da177e4SLinus Torvalds	bra.b		ddone
21851da177e4SLinus Torvalds
21861da177e4SLinus Torvaldsdqpos:
21871da177e4SLinus Torvalds	btst		&0x1f, %d6		# will (+quot) fit in 32 bits?
21881da177e4SLinus Torvalds	bne.b		ddovf
21891da177e4SLinus Torvalds
21901da177e4SLinus Torvaldsddone:
21911da177e4SLinus Torvalds# at this point, result is normal so ccodes are set based on result.
21921da177e4SLinus Torvalds	mov.w		EXC_CC(%a6), %cc
21931da177e4SLinus Torvalds	tst.l		%d6			# set %ccode bits
21941da177e4SLinus Torvalds	mov.w		%cc, EXC_CC(%a6)
21951da177e4SLinus Torvalds
21961da177e4SLinus Torvalds	mov.w		NDRSAVE(%a6), %d0	# get Dr off stack
21971da177e4SLinus Torvalds	mov.w		NDQSAVE(%a6), %d1	# get Dq off stack
21981da177e4SLinus Torvalds
21991da177e4SLinus Torvalds# if the register numbers are the same, only the quotient gets saved.
22001da177e4SLinus Torvalds# so, if we always save the quotient second, we save ourselves a cmp&beq
22011da177e4SLinus Torvalds	mov.l		%d5, (EXC_DREGS,%a6,%d0.w*4) # save remainder
22021da177e4SLinus Torvalds	mov.l		%d6, (EXC_DREGS,%a6,%d1.w*4) # save quotient
22031da177e4SLinus Torvalds
22041da177e4SLinus Torvalds	rts
22051da177e4SLinus Torvalds
22061da177e4SLinus Torvaldsddovf:
22071da177e4SLinus Torvalds	bset		&0x1, EXC_CC+1(%a6)	# 'V' set on overflow
22081da177e4SLinus Torvalds	bclr		&0x0, EXC_CC+1(%a6)	# 'C' cleared on overflow
22091da177e4SLinus Torvalds
22101da177e4SLinus Torvalds	rts
22111da177e4SLinus Torvalds
22121da177e4SLinus Torvaldsdiv64eq0:
22131da177e4SLinus Torvalds	andi.b		&0x1e, EXC_CC+1(%a6)	# clear 'C' bit on divbyzero
22141da177e4SLinus Torvalds	ori.b		&idbyz_flg,SPCOND_FLG(%a6) # set "special case" flag
22151da177e4SLinus Torvalds	rts
22161da177e4SLinus Torvalds
22171da177e4SLinus Torvalds###########################################################################
22181da177e4SLinus Torvalds#########################################################################
22191da177e4SLinus Torvalds# This routine uses the 'classical' Algorithm D from Donald Knuth's	#
22201da177e4SLinus Torvalds# Art of Computer Programming, vol II, Seminumerical Algorithms.	#
22211da177e4SLinus Torvalds# For this implementation b=2**16, and the target is U1U2U3U4/V1V2,	#
22221da177e4SLinus Torvalds# where U,V are words of the quadword dividend and longword divisor,	#
22231da177e4SLinus Torvalds# and U1, V1 are the most significant words.				#
22241da177e4SLinus Torvalds#									#
22251da177e4SLinus Torvalds# The most sig. longword of the 64 bit dividend must be in %d5, least	#
22261da177e4SLinus Torvalds# in %d6. The divisor must be in the variable ddivisor, and the		#
22271da177e4SLinus Torvalds# signed/unsigned flag ddusign must be set (0=unsigned,1=signed).	#
22281da177e4SLinus Torvalds# The quotient is returned in %d6, remainder in %d5, unless the		#
22291da177e4SLinus Torvalds# v (overflow) bit is set in the saved %ccr. If overflow, the dividend	#
22301da177e4SLinus Torvalds# is unchanged.								#
22311da177e4SLinus Torvalds#########################################################################
22321da177e4SLinus Torvaldsdclassical:
22331da177e4SLinus Torvalds# if the divisor msw is 0, use simpler algorithm then the full blown
22341da177e4SLinus Torvalds# one at ddknuth:
22351da177e4SLinus Torvalds
22361da177e4SLinus Torvalds	cmpi.l		%d7, &0xffff
22371da177e4SLinus Torvalds	bhi.b		ddknuth			# go use D. Knuth algorithm
22381da177e4SLinus Torvalds
22391da177e4SLinus Torvalds# Since the divisor is only a word (and larger than the mslw of the dividend),
22401da177e4SLinus Torvalds# a simpler algorithm may be used :
22411da177e4SLinus Torvalds# In the general case, four quotient words would be created by
22421da177e4SLinus Torvalds# dividing the divisor word into each dividend word. In this case,
22431da177e4SLinus Torvalds# the first two quotient words must be zero, or overflow would occur.
22441da177e4SLinus Torvalds# Since we already checked this case above, we can treat the most significant
22451da177e4SLinus Torvalds# longword of the dividend as (0) remainder (see Knuth) and merely complete
22461da177e4SLinus Torvalds# the last two divisions to get a quotient longword and word remainder:
22471da177e4SLinus Torvalds
22481da177e4SLinus Torvalds	clr.l		%d1
22491da177e4SLinus Torvalds	swap		%d5			# same as r*b if previous step rqd
22501da177e4SLinus Torvalds	swap		%d6			# get u3 to lsw position
22511da177e4SLinus Torvalds	mov.w		%d6, %d5		# rb + u3
22521da177e4SLinus Torvalds
22531da177e4SLinus Torvalds	divu.w		%d7, %d5
22541da177e4SLinus Torvalds
22551da177e4SLinus Torvalds	mov.w		%d5, %d1		# first quotient word
22561da177e4SLinus Torvalds	swap		%d6			# get u4
22571da177e4SLinus Torvalds	mov.w		%d6, %d5		# rb + u4
22581da177e4SLinus Torvalds
22591da177e4SLinus Torvalds	divu.w		%d7, %d5
22601da177e4SLinus Torvalds
22611da177e4SLinus Torvalds	swap		%d1
22621da177e4SLinus Torvalds	mov.w		%d5, %d1		# 2nd quotient 'digit'
22631da177e4SLinus Torvalds	clr.w		%d5
22641da177e4SLinus Torvalds	swap		%d5			# now remainder
22651da177e4SLinus Torvalds	mov.l		%d1, %d6		# and quotient
22661da177e4SLinus Torvalds
22671da177e4SLinus Torvalds	rts
22681da177e4SLinus Torvalds
22691da177e4SLinus Torvaldsddknuth:
22701da177e4SLinus Torvalds# In this algorithm, the divisor is treated as a 2 digit (word) number
22711da177e4SLinus Torvalds# which is divided into a 3 digit (word) dividend to get one quotient
22721da177e4SLinus Torvalds# digit (word). After subtraction, the dividend is shifted and the
22731da177e4SLinus Torvalds# process repeated. Before beginning, the divisor and quotient are
22741da177e4SLinus Torvalds# 'normalized' so that the process of estimating the quotient digit
22751da177e4SLinus Torvalds# will yield verifiably correct results..
22761da177e4SLinus Torvalds
22771da177e4SLinus Torvalds	clr.l		DDNORMAL(%a6)		# count of shifts for normalization
22781da177e4SLinus Torvalds	clr.b		DDSECOND(%a6)		# clear flag for quotient digits
22791da177e4SLinus Torvalds	clr.l		%d1			# %d1 will hold trial quotient
22801da177e4SLinus Torvaldsddnchk:
22811da177e4SLinus Torvalds	btst		&31, %d7		# must we normalize? first word of
22821da177e4SLinus Torvalds	bne.b		ddnormalized		# divisor (V1) must be >= 65536/2
22831da177e4SLinus Torvalds	addq.l		&0x1, DDNORMAL(%a6)	# count normalization shifts
22841da177e4SLinus Torvalds	lsl.l		&0x1, %d7		# shift the divisor
22851da177e4SLinus Torvalds	lsl.l		&0x1, %d6		# shift u4,u3 with overflow to u2
22861da177e4SLinus Torvalds	roxl.l		&0x1, %d5		# shift u1,u2
22871da177e4SLinus Torvalds	bra.w		ddnchk
22881da177e4SLinus Torvaldsddnormalized:
22891da177e4SLinus Torvalds
22901da177e4SLinus Torvalds# Now calculate an estimate of the quotient words (msw first, then lsw).
22911da177e4SLinus Torvalds# The comments use subscripts for the first quotient digit determination.
22921da177e4SLinus Torvalds	mov.l		%d7, %d3		# divisor
22931da177e4SLinus Torvalds	mov.l		%d5, %d2		# dividend mslw
22941da177e4SLinus Torvalds	swap		%d2
22951da177e4SLinus Torvalds	swap		%d3
22961da177e4SLinus Torvalds	cmp.w		%d2, %d3		# V1 = U1 ?
22971da177e4SLinus Torvalds	bne.b		ddqcalc1
22981da177e4SLinus Torvalds	mov.w		&0xffff, %d1		# use max trial quotient word
22991da177e4SLinus Torvalds	bra.b		ddadj0
23001da177e4SLinus Torvaldsddqcalc1:
23011da177e4SLinus Torvalds	mov.l		%d5, %d1
23021da177e4SLinus Torvalds
23031da177e4SLinus Torvalds	divu.w		%d3, %d1		# use quotient of mslw/msw
23041da177e4SLinus Torvalds
23051da177e4SLinus Torvalds	andi.l		&0x0000ffff, %d1	# zero any remainder
23061da177e4SLinus Torvaldsddadj0:
23071da177e4SLinus Torvalds
23081da177e4SLinus Torvalds# now test the trial quotient and adjust. This step plus the
23091da177e4SLinus Torvalds# normalization assures (according to Knuth) that the trial
23101da177e4SLinus Torvalds# quotient will be at worst 1 too large.
23111da177e4SLinus Torvalds	mov.l		%d6, -(%sp)
23121da177e4SLinus Torvalds	clr.w		%d6			# word u3 left
23131da177e4SLinus Torvalds	swap		%d6			# in lsw position
23141da177e4SLinus Torvaldsddadj1: mov.l		%d7, %d3
23151da177e4SLinus Torvalds	mov.l		%d1, %d2
23161da177e4SLinus Torvalds	mulu.w		%d7, %d2		# V2q
23171da177e4SLinus Torvalds	swap		%d3
23181da177e4SLinus Torvalds	mulu.w		%d1, %d3		# V1q
23191da177e4SLinus Torvalds	mov.l		%d5, %d4		# U1U2
23201da177e4SLinus Torvalds	sub.l		%d3, %d4		# U1U2 - V1q
23211da177e4SLinus Torvalds
23221da177e4SLinus Torvalds	swap		%d4
23231da177e4SLinus Torvalds
23241da177e4SLinus Torvalds	mov.w		%d4,%d0
23251da177e4SLinus Torvalds	mov.w		%d6,%d4			# insert lower word (U3)
23261da177e4SLinus Torvalds
23271da177e4SLinus Torvalds	tst.w		%d0			# is upper word set?
23281da177e4SLinus Torvalds	bne.w		ddadjd1
23291da177e4SLinus Torvalds
23301da177e4SLinus Torvalds#	add.l		%d6, %d4		# (U1U2 - V1q) + U3
23311da177e4SLinus Torvalds
23321da177e4SLinus Torvalds	cmp.l		%d2, %d4
23331da177e4SLinus Torvalds	bls.b		ddadjd1			# is V2q > (U1U2-V1q) + U3 ?
23341da177e4SLinus Torvalds	subq.l		&0x1, %d1		# yes, decrement and recheck
23351da177e4SLinus Torvalds	bra.b		ddadj1
23361da177e4SLinus Torvaldsddadjd1:
23371da177e4SLinus Torvalds# now test the word by multiplying it by the divisor (V1V2) and comparing
23381da177e4SLinus Torvalds# the 3 digit (word) result with the current dividend words
23391da177e4SLinus Torvalds	mov.l		%d5, -(%sp)		# save %d5 (%d6 already saved)
23401da177e4SLinus Torvalds	mov.l		%d1, %d6
23411da177e4SLinus Torvalds	swap		%d6			# shift answer to ms 3 words
23421da177e4SLinus Torvalds	mov.l		%d7, %d5
23431da177e4SLinus Torvalds	bsr.l		dmm2
23441da177e4SLinus Torvalds	mov.l		%d5, %d2		# now %d2,%d3 are trial*divisor
23451da177e4SLinus Torvalds	mov.l		%d6, %d3
23461da177e4SLinus Torvalds	mov.l		(%sp)+, %d5		# restore dividend
23471da177e4SLinus Torvalds	mov.l		(%sp)+, %d6
23481da177e4SLinus Torvalds	sub.l		%d3, %d6
23491da177e4SLinus Torvalds	subx.l		%d2, %d5		# subtract double precision
23501da177e4SLinus Torvalds	bcc		dd2nd			# no carry, do next quotient digit
23511da177e4SLinus Torvalds	subq.l		&0x1, %d1		# q is one too large
23521da177e4SLinus Torvalds# need to add back divisor longword to current ms 3 digits of dividend
23531da177e4SLinus Torvalds# - according to Knuth, this is done only 2 out of 65536 times for random
23541da177e4SLinus Torvalds# divisor, dividend selection.
23551da177e4SLinus Torvalds	clr.l		%d2
23561da177e4SLinus Torvalds	mov.l		%d7, %d3
23571da177e4SLinus Torvalds	swap		%d3
23581da177e4SLinus Torvalds	clr.w		%d3			# %d3 now ls word of divisor
23591da177e4SLinus Torvalds	add.l		%d3, %d6		# aligned with 3rd word of dividend
23601da177e4SLinus Torvalds	addx.l		%d2, %d5
23611da177e4SLinus Torvalds	mov.l		%d7, %d3
23621da177e4SLinus Torvalds	clr.w		%d3			# %d3 now ms word of divisor
23631da177e4SLinus Torvalds	swap		%d3			# aligned with 2nd word of dividend
23641da177e4SLinus Torvalds	add.l		%d3, %d5
23651da177e4SLinus Torvaldsdd2nd:
23661da177e4SLinus Torvalds	tst.b		DDSECOND(%a6)		# both q words done?
23671da177e4SLinus Torvalds	bne.b		ddremain
23681da177e4SLinus Torvalds# first quotient digit now correct. store digit and shift the
23691da177e4SLinus Torvalds# (subtracted) dividend
23701da177e4SLinus Torvalds	mov.w		%d1, DDQUOTIENT(%a6)
23711da177e4SLinus Torvalds	clr.l		%d1
23721da177e4SLinus Torvalds	swap		%d5
23731da177e4SLinus Torvalds	swap		%d6
23741da177e4SLinus Torvalds	mov.w		%d6, %d5
23751da177e4SLinus Torvalds	clr.w		%d6
23761da177e4SLinus Torvalds	st		DDSECOND(%a6)		# second digit
23771da177e4SLinus Torvalds	bra.w		ddnormalized
23781da177e4SLinus Torvaldsddremain:
23791da177e4SLinus Torvalds# add 2nd word to quotient, get the remainder.
23801da177e4SLinus Torvalds	mov.w		%d1, DDQUOTIENT+2(%a6)
23811da177e4SLinus Torvalds# shift down one word/digit to renormalize remainder.
23821da177e4SLinus Torvalds	mov.w		%d5, %d6
23831da177e4SLinus Torvalds	swap		%d6
23841da177e4SLinus Torvalds	swap		%d5
23851da177e4SLinus Torvalds	mov.l		DDNORMAL(%a6), %d7	# get norm shift count
23861da177e4SLinus Torvalds	beq.b		ddrn
23871da177e4SLinus Torvalds	subq.l		&0x1, %d7		# set for loop count
23881da177e4SLinus Torvaldsddnlp:
23891da177e4SLinus Torvalds	lsr.l		&0x1, %d5		# shift into %d6
23901da177e4SLinus Torvalds	roxr.l		&0x1, %d6
23911da177e4SLinus Torvalds	dbf		%d7, ddnlp
23921da177e4SLinus Torvaldsddrn:
23931da177e4SLinus Torvalds	mov.l		%d6, %d5		# remainder
23941da177e4SLinus Torvalds	mov.l		DDQUOTIENT(%a6), %d6	# quotient
23951da177e4SLinus Torvalds
23961da177e4SLinus Torvalds	rts
23971da177e4SLinus Torvaldsdmm2:
23981da177e4SLinus Torvalds# factors for the 32X32->64 multiplication are in %d5 and %d6.
23991da177e4SLinus Torvalds# returns 64 bit result in %d5 (hi) %d6(lo).
24001da177e4SLinus Torvalds# destroys %d2,%d3,%d4.
24011da177e4SLinus Torvalds
24021da177e4SLinus Torvalds# multiply hi,lo words of each factor to get 4 intermediate products
24031da177e4SLinus Torvalds	mov.l		%d6, %d2
24041da177e4SLinus Torvalds	mov.l		%d6, %d3
24051da177e4SLinus Torvalds	mov.l		%d5, %d4
24061da177e4SLinus Torvalds	swap		%d3
24071da177e4SLinus Torvalds	swap		%d4
24081da177e4SLinus Torvalds	mulu.w		%d5, %d6		# %d6 <- lsw*lsw
24091da177e4SLinus Torvalds	mulu.w		%d3, %d5		# %d5 <- msw-dest*lsw-source
24101da177e4SLinus Torvalds	mulu.w		%d4, %d2		# %d2 <- msw-source*lsw-dest
24111da177e4SLinus Torvalds	mulu.w		%d4, %d3		# %d3 <- msw*msw
24121da177e4SLinus Torvalds# now use swap and addx to consolidate to two longwords
24131da177e4SLinus Torvalds	clr.l		%d4
24141da177e4SLinus Torvalds	swap		%d6
24151da177e4SLinus Torvalds	add.w		%d5, %d6		# add msw of l*l to lsw of m*l product
24161da177e4SLinus Torvalds	addx.w		%d4, %d3		# add any carry to m*m product
24171da177e4SLinus Torvalds	add.w		%d2, %d6		# add in lsw of other m*l product
24181da177e4SLinus Torvalds	addx.w		%d4, %d3		# add any carry to m*m product
24191da177e4SLinus Torvalds	swap		%d6			# %d6 is low 32 bits of final product
24201da177e4SLinus Torvalds	clr.w		%d5
24211da177e4SLinus Torvalds	clr.w		%d2			# lsw of two mixed products used,
24221da177e4SLinus Torvalds	swap		%d5			# now use msws of longwords
24231da177e4SLinus Torvalds	swap		%d2
24241da177e4SLinus Torvalds	add.l		%d2, %d5
24251da177e4SLinus Torvalds	add.l		%d3, %d5		# %d5 now ms 32 bits of final product
24261da177e4SLinus Torvalds	rts
24271da177e4SLinus Torvalds
24281da177e4SLinus Torvalds##########
24291da177e4SLinus Torvaldsdcontrolmodel_s:
24301da177e4SLinus Torvalds	movq.l		&LONG,%d0
24311da177e4SLinus Torvalds	bsr.l		_calc_ea		# calc <ea>
24321da177e4SLinus Torvalds
24331da177e4SLinus Torvalds	cmpi.b		SPCOND_FLG(%a6),&immed_flg # immediate addressing mode?
24341da177e4SLinus Torvalds	beq.b		dimmed			# yes
24351da177e4SLinus Torvalds
24361da177e4SLinus Torvalds	mov.l		%a0,%a2
24371da177e4SLinus Torvalds	bsr.l		_dmem_read_long		# fetch divisor from <ea>
24381da177e4SLinus Torvalds
24391da177e4SLinus Torvalds	tst.l		%d1			# dfetch error?
24401da177e4SLinus Torvalds	bne.b		div64_err		# yes
24411da177e4SLinus Torvalds
24421da177e4SLinus Torvalds	mov.l		%d0, %d7
24431da177e4SLinus Torvalds	bra.w		dgotsrcl
24441da177e4SLinus Torvalds
24451da177e4SLinus Torvalds# we have to split out immediate data here because it must be read using
24461da177e4SLinus Torvalds# imem_read() instead of dmem_read(). this becomes especially important
24471da177e4SLinus Torvalds# if the fetch runs into some deadly fault.
24481da177e4SLinus Torvaldsdimmed:
24491da177e4SLinus Torvalds	addq.l		&0x4,EXC_EXTWPTR(%a6)
24501da177e4SLinus Torvalds	bsr.l		_imem_read_long		# read immediate value
24511da177e4SLinus Torvalds
24521da177e4SLinus Torvalds	tst.l		%d1			# ifetch error?
24531da177e4SLinus Torvalds	bne.l		isp_iacc		# yes
24541da177e4SLinus Torvalds
24551da177e4SLinus Torvalds	mov.l		%d0,%d7
24561da177e4SLinus Torvalds	bra.w		dgotsrcl
24571da177e4SLinus Torvalds
24581da177e4SLinus Torvalds##########
24591da177e4SLinus Torvalds
24601da177e4SLinus Torvalds# if dmem_read_long() returns a fail message in d1, the package
24611da177e4SLinus Torvalds# must create an access error frame. here, we pass a skeleton fslw
24621da177e4SLinus Torvalds# and the failing address to the routine that creates the new frame.
24631da177e4SLinus Torvalds# also, we call isp_restore in case the effective addressing mode was
24641da177e4SLinus Torvalds# (an)+ or -(an) in which case the previous "an" value must be restored.
24651da177e4SLinus Torvalds# FSLW:
24661da177e4SLinus Torvalds#	read = true
24671da177e4SLinus Torvalds#	size = longword
24681da177e4SLinus Torvalds#	TM = data
24691da177e4SLinus Torvalds#	software emulation error = true
24701da177e4SLinus Torvaldsdiv64_err:
24711da177e4SLinus Torvalds	bsr.l		isp_restore		# restore addr reg
24721da177e4SLinus Torvalds	mov.l		%a2,%a0			# pass failing address
24731da177e4SLinus Torvalds	mov.l		&0x01010001,%d0		# pass fslw
24741da177e4SLinus Torvalds	bra.l		isp_dacc
24751da177e4SLinus Torvalds
24761da177e4SLinus Torvalds#########################################################################
24771da177e4SLinus Torvalds# XDEF ****************************************************************	#
24781da177e4SLinus Torvalds#	_mul64(): routine to emulate mul{u,s}.l <ea>,Dh:Dl 32x32->64	#
24791da177e4SLinus Torvalds#									#
24801da177e4SLinus Torvalds# XREF ****************************************************************	#
24811da177e4SLinus Torvalds#	_calc_ea() - calculate effective address			#
24821da177e4SLinus Torvalds#	isp_iacc() - handle instruction access error exception		#
24831da177e4SLinus Torvalds#	isp_dacc() - handle data access error exception			#
24841da177e4SLinus Torvalds#	isp_restore() - restore An on access error w/ -() or ()+	#
24851da177e4SLinus Torvalds#									#
24861da177e4SLinus Torvalds# INPUT ***************************************************************	#
24871da177e4SLinus Torvalds#	none								#
24881da177e4SLinus Torvalds#									#
24891da177e4SLinus Torvalds# OUTPUT **************************************************************	#
24901da177e4SLinus Torvalds#	If exiting through isp_dacc...					#
24911da177e4SLinus Torvalds#		a0 = failing address					#
24921da177e4SLinus Torvalds#		d0 = FSLW						#
24931da177e4SLinus Torvalds#	else								#
24941da177e4SLinus Torvalds#		none							#
24951da177e4SLinus Torvalds#									#
24961da177e4SLinus Torvalds# ALGORITHM ***********************************************************	#
24971da177e4SLinus Torvalds#	First, decode the operand location. If it's in Dn, fetch from	#
24981da177e4SLinus Torvalds# the stack. If it's in memory, use _calc_ea() to calculate the		#
24991da177e4SLinus Torvalds# effective address. Use _dmem_read_long() to fetch at that address.	#
25001da177e4SLinus Torvalds# Unless the operand is immediate data. Then use _imem_read_long().	#
25011da177e4SLinus Torvalds# Send failures to isp_dacc() or isp_iacc() as appropriate.		#
25021da177e4SLinus Torvalds#	If the operands are signed, make them unsigned and save the	#
25031da177e4SLinus Torvalds# sign info for later. Perform the multiplication using 16x16->32	#
25041da177e4SLinus Torvalds# unsigned multiplies and "add" instructions. Store the high and low	#
25051da177e4SLinus Torvalds# portions of the result in the appropriate data registers on the	#
25061da177e4SLinus Torvalds# stack. Calculate the condition codes, also.				#
25071da177e4SLinus Torvalds#									#
25081da177e4SLinus Torvalds#########################################################################
25091da177e4SLinus Torvalds
25101da177e4SLinus Torvalds#############
25111da177e4SLinus Torvalds# mul(u,s)l #
25121da177e4SLinus Torvalds#############
25131da177e4SLinus Torvalds	global		_mul64
25141da177e4SLinus Torvalds_mul64:
25151da177e4SLinus Torvalds	mov.b		EXC_OPWORD+1(%a6), %d0	# extract src {mode,reg}
25161da177e4SLinus Torvalds	cmpi.b		%d0, &0x7		# is src mode Dn or other?
25171da177e4SLinus Torvalds	bgt.w		mul64_memop		# src is in memory
25181da177e4SLinus Torvalds
25191da177e4SLinus Torvalds# multiplier operand in the data register file.
25201da177e4SLinus Torvalds# must extract the register number and fetch the operand from the stack.
25211da177e4SLinus Torvaldsmul64_regop:
25221da177e4SLinus Torvalds	andi.w		&0x7, %d0		# extract Dn
25231da177e4SLinus Torvalds	mov.l		(EXC_DREGS,%a6,%d0.w*4), %d3 # fetch multiplier
25241da177e4SLinus Torvalds
25251da177e4SLinus Torvalds# multiplier is in %d3. now, extract Dl and Dh fields and fetch the
25261da177e4SLinus Torvalds# multiplicand from the data register specified by Dl.
25271da177e4SLinus Torvaldsmul64_multiplicand:
25281da177e4SLinus Torvalds	mov.w		EXC_EXTWORD(%a6), %d2	# fetch ext word
25291da177e4SLinus Torvalds	clr.w		%d1			# clear Dh reg
25301da177e4SLinus Torvalds	mov.b		%d2, %d1		# grab Dh
25311da177e4SLinus Torvalds	rol.w		&0x4, %d2		# align Dl byte
25321da177e4SLinus Torvalds	andi.w		&0x7, %d2		# extract Dl
25331da177e4SLinus Torvalds
25341da177e4SLinus Torvalds	mov.l		(EXC_DREGS,%a6,%d2.w*4), %d4 # get multiplicand
25351da177e4SLinus Torvalds
25361da177e4SLinus Torvalds# check for the case of "zero" result early
25371da177e4SLinus Torvalds	tst.l		%d4			# test multiplicand
25381da177e4SLinus Torvalds	beq.w		mul64_zero		# handle zero separately
25391da177e4SLinus Torvalds	tst.l		%d3			# test multiplier
25401da177e4SLinus Torvalds	beq.w		mul64_zero		# handle zero separately
25411da177e4SLinus Torvalds
25421da177e4SLinus Torvalds# multiplier is in %d3 and multiplicand is in %d4.
25431da177e4SLinus Torvalds# if the operation is to be signed, then the operands are converted
25441da177e4SLinus Torvalds# to unsigned and the result sign is saved for the end.
25451da177e4SLinus Torvalds	clr.b		EXC_TEMP(%a6)		# clear temp space
25461da177e4SLinus Torvalds	btst		&0x3, EXC_EXTWORD(%a6)	# signed or unsigned?
25471da177e4SLinus Torvalds	beq.b		mul64_alg		# unsigned; skip sgn calc
25481da177e4SLinus Torvalds
25491da177e4SLinus Torvalds	tst.l		%d3			# is multiplier negative?
25501da177e4SLinus Torvalds	bge.b		mul64_chk_md_sgn	# no
25511da177e4SLinus Torvalds	neg.l		%d3			# make multiplier positive
25521da177e4SLinus Torvalds	ori.b		&0x1, EXC_TEMP(%a6)	# save multiplier sgn
25531da177e4SLinus Torvalds
25541da177e4SLinus Torvalds# the result sign is the exclusive or of the operand sign bits.
25551da177e4SLinus Torvaldsmul64_chk_md_sgn:
25561da177e4SLinus Torvalds	tst.l		%d4			# is multiplicand negative?
25571da177e4SLinus Torvalds	bge.b		mul64_alg		# no
25581da177e4SLinus Torvalds	neg.l		%d4			# make multiplicand positive
25591da177e4SLinus Torvalds	eori.b		&0x1, EXC_TEMP(%a6)	# calculate correct sign
25601da177e4SLinus Torvalds
25611da177e4SLinus Torvalds#########################################################################
25621da177e4SLinus Torvalds#	63			   32				0	#
25631da177e4SLinus Torvalds#	----------------------------					#
25641da177e4SLinus Torvalds#	| hi(mplier) * hi(mplicand)|					#
25651da177e4SLinus Torvalds#	----------------------------					#
25661da177e4SLinus Torvalds#		     -----------------------------			#
25671da177e4SLinus Torvalds#		     | hi(mplier) * lo(mplicand) |			#
25681da177e4SLinus Torvalds#		     -----------------------------			#
25691da177e4SLinus Torvalds#		     -----------------------------			#
25701da177e4SLinus Torvalds#		     | lo(mplier) * hi(mplicand) |			#
25711da177e4SLinus Torvalds#		     -----------------------------			#
25721da177e4SLinus Torvalds#	  |			   -----------------------------	#
25731da177e4SLinus Torvalds#	--|--			   | lo(mplier) * lo(mplicand) |	#
25741da177e4SLinus Torvalds#	  |			   -----------------------------	#
25751da177e4SLinus Torvalds#	========================================================	#
25761da177e4SLinus Torvalds#	--------------------------------------------------------	#
25771da177e4SLinus Torvalds#	|	hi(result)	   |	    lo(result)         |	#
25781da177e4SLinus Torvalds#	--------------------------------------------------------	#
25791da177e4SLinus Torvalds#########################################################################
25801da177e4SLinus Torvaldsmul64_alg:
25811da177e4SLinus Torvalds# load temp registers with operands
25821da177e4SLinus Torvalds	mov.l		%d3, %d5		# mr in %d5
25831da177e4SLinus Torvalds	mov.l		%d3, %d6		# mr in %d6
25841da177e4SLinus Torvalds	mov.l		%d4, %d7		# md in %d7
25851da177e4SLinus Torvalds	swap		%d6			# hi(mr) in lo %d6
25861da177e4SLinus Torvalds	swap		%d7			# hi(md) in lo %d7
25871da177e4SLinus Torvalds
25881da177e4SLinus Torvalds# complete necessary multiplies:
25891da177e4SLinus Torvalds	mulu.w		%d4, %d3		# [1] lo(mr) * lo(md)
25901da177e4SLinus Torvalds	mulu.w		%d6, %d4		# [2] hi(mr) * lo(md)
25911da177e4SLinus Torvalds	mulu.w		%d7, %d5		# [3] lo(mr) * hi(md)
25921da177e4SLinus Torvalds	mulu.w		%d7, %d6		# [4] hi(mr) * hi(md)
25931da177e4SLinus Torvalds
25941da177e4SLinus Torvalds# add lo portions of [2],[3] to hi portion of [1].
25951da177e4SLinus Torvalds# add carries produced from these adds to [4].
25961da177e4SLinus Torvalds# lo([1]) is the final lo 16 bits of the result.
25971da177e4SLinus Torvalds	clr.l		%d7			# load %d7 w/ zero value
25981da177e4SLinus Torvalds	swap		%d3			# hi([1]) <==> lo([1])
25991da177e4SLinus Torvalds	add.w		%d4, %d3		# hi([1]) + lo([2])
26001da177e4SLinus Torvalds	addx.l		%d7, %d6		#    [4]  + carry
26011da177e4SLinus Torvalds	add.w		%d5, %d3		# hi([1]) + lo([3])
26021da177e4SLinus Torvalds	addx.l		%d7, %d6		#    [4]  + carry
26031da177e4SLinus Torvalds	swap		%d3			# lo([1]) <==> hi([1])
26041da177e4SLinus Torvalds
26051da177e4SLinus Torvalds# lo portions of [2],[3] have been added in to final result.
26061da177e4SLinus Torvalds# now, clear lo, put hi in lo reg, and add to [4]
26071da177e4SLinus Torvalds	clr.w		%d4			# clear lo([2])
26081da177e4SLinus Torvalds	clr.w		%d5			# clear hi([3])
26091da177e4SLinus Torvalds	swap		%d4			# hi([2]) in lo %d4
26101da177e4SLinus Torvalds	swap		%d5			# hi([3]) in lo %d5
26111da177e4SLinus Torvalds	add.l		%d5, %d4		#    [4]  + hi([2])
26121da177e4SLinus Torvalds	add.l		%d6, %d4		#    [4]  + hi([3])
26131da177e4SLinus Torvalds
26141da177e4SLinus Torvalds# unsigned result is now in {%d4,%d3}
26151da177e4SLinus Torvalds	tst.b		EXC_TEMP(%a6)		# should result be signed?
26161da177e4SLinus Torvalds	beq.b		mul64_done		# no
26171da177e4SLinus Torvalds
26181da177e4SLinus Torvalds# result should be a signed negative number.
26191da177e4SLinus Torvalds# compute 2's complement of the unsigned number:
26201da177e4SLinus Torvalds#   -negate all bits and add 1
26211da177e4SLinus Torvaldsmul64_neg:
26221da177e4SLinus Torvalds	not.l		%d3			# negate lo(result) bits
26231da177e4SLinus Torvalds	not.l		%d4			# negate hi(result) bits
26241da177e4SLinus Torvalds	addq.l		&1, %d3			# add 1 to lo(result)
26251da177e4SLinus Torvalds	addx.l		%d7, %d4		# add carry to hi(result)
26261da177e4SLinus Torvalds
26271da177e4SLinus Torvalds# the result is saved to the register file.
26281da177e4SLinus Torvalds# for '040 compatibility, if Dl == Dh then only the hi(result) is
26291da177e4SLinus Torvalds# saved. so, saving hi after lo accomplishes this without need to
26301da177e4SLinus Torvalds# check Dl,Dh equality.
26311da177e4SLinus Torvaldsmul64_done:
26321da177e4SLinus Torvalds	mov.l		%d3, (EXC_DREGS,%a6,%d2.w*4) # save lo(result)
26331da177e4SLinus Torvalds	mov.w		&0x0, %cc
26341da177e4SLinus Torvalds	mov.l		%d4, (EXC_DREGS,%a6,%d1.w*4) # save hi(result)
26351da177e4SLinus Torvalds
26361da177e4SLinus Torvalds# now, grab the condition codes. only one that can be set is 'N'.
26371da177e4SLinus Torvalds# 'N' CAN be set if the operation is unsigned if bit 63 is set.
26381da177e4SLinus Torvalds	mov.w		%cc, %d7		# fetch %ccr to see if 'N' set
26391da177e4SLinus Torvalds	andi.b		&0x8, %d7		# extract 'N' bit
26401da177e4SLinus Torvalds
26411da177e4SLinus Torvaldsmul64_ccode_set:
26421da177e4SLinus Torvalds	mov.b		EXC_CC+1(%a6), %d6	# fetch previous %ccr
26431da177e4SLinus Torvalds	andi.b		&0x10, %d6		# all but 'X' bit changes
26441da177e4SLinus Torvalds
26451da177e4SLinus Torvalds	or.b		%d7, %d6		# group 'X' and 'N'
26461da177e4SLinus Torvalds	mov.b		%d6, EXC_CC+1(%a6)	# save new %ccr
26471da177e4SLinus Torvalds
26481da177e4SLinus Torvalds	rts
26491da177e4SLinus Torvalds
26501da177e4SLinus Torvalds# one or both of the operands is zero so the result is also zero.
26511da177e4SLinus Torvalds# save the zero result to the register file and set the 'Z' ccode bit.
26521da177e4SLinus Torvaldsmul64_zero:
26531da177e4SLinus Torvalds	clr.l		(EXC_DREGS,%a6,%d2.w*4) # save lo(result)
26541da177e4SLinus Torvalds	clr.l		(EXC_DREGS,%a6,%d1.w*4) # save hi(result)
26551da177e4SLinus Torvalds
26561da177e4SLinus Torvalds	movq.l		&0x4, %d7		# set 'Z' ccode bit
26571da177e4SLinus Torvalds	bra.b		mul64_ccode_set		# finish ccode set
26581da177e4SLinus Torvalds
26591da177e4SLinus Torvalds##########
26601da177e4SLinus Torvalds
26611da177e4SLinus Torvalds# multiplier operand is in memory at the effective address.
26621da177e4SLinus Torvalds# must calculate the <ea> and go fetch the 32-bit operand.
26631da177e4SLinus Torvaldsmul64_memop:
26641da177e4SLinus Torvalds	movq.l		&LONG, %d0		# pass # of bytes
26651da177e4SLinus Torvalds	bsr.l		_calc_ea		# calculate <ea>
26661da177e4SLinus Torvalds
26671da177e4SLinus Torvalds	cmpi.b		SPCOND_FLG(%a6),&immed_flg # immediate addressing mode?
26681da177e4SLinus Torvalds	beq.b		mul64_immed		# yes
26691da177e4SLinus Torvalds
26701da177e4SLinus Torvalds	mov.l		%a0,%a2
26711da177e4SLinus Torvalds	bsr.l		_dmem_read_long		# fetch src from addr (%a0)
26721da177e4SLinus Torvalds
26731da177e4SLinus Torvalds	tst.l		%d1			# dfetch error?
26741da177e4SLinus Torvalds	bne.w		mul64_err		# yes
26751da177e4SLinus Torvalds
26761da177e4SLinus Torvalds	mov.l		%d0, %d3		# store multiplier in %d3
26771da177e4SLinus Torvalds
26781da177e4SLinus Torvalds	bra.w		mul64_multiplicand
26791da177e4SLinus Torvalds
26801da177e4SLinus Torvalds# we have to split out immediate data here because it must be read using
26811da177e4SLinus Torvalds# imem_read() instead of dmem_read(). this becomes especially important
26821da177e4SLinus Torvalds# if the fetch runs into some deadly fault.
26831da177e4SLinus Torvaldsmul64_immed:
26841da177e4SLinus Torvalds	addq.l		&0x4,EXC_EXTWPTR(%a6)
26851da177e4SLinus Torvalds	bsr.l		_imem_read_long		# read immediate value
26861da177e4SLinus Torvalds
26871da177e4SLinus Torvalds	tst.l		%d1			# ifetch error?
26881da177e4SLinus Torvalds	bne.l		isp_iacc		# yes
26891da177e4SLinus Torvalds
26901da177e4SLinus Torvalds	mov.l		%d0,%d3
26911da177e4SLinus Torvalds	bra.w		mul64_multiplicand
26921da177e4SLinus Torvalds
26931da177e4SLinus Torvalds##########
26941da177e4SLinus Torvalds
26951da177e4SLinus Torvalds# if dmem_read_long() returns a fail message in d1, the package
26961da177e4SLinus Torvalds# must create an access error frame. here, we pass a skeleton fslw
26971da177e4SLinus Torvalds# and the failing address to the routine that creates the new frame.
26981da177e4SLinus Torvalds# also, we call isp_restore in case the effective addressing mode was
26991da177e4SLinus Torvalds# (an)+ or -(an) in which case the previous "an" value must be restored.
27001da177e4SLinus Torvalds# FSLW:
27011da177e4SLinus Torvalds#	read = true
27021da177e4SLinus Torvalds#	size = longword
27031da177e4SLinus Torvalds#	TM = data
27041da177e4SLinus Torvalds#	software emulation error = true
27051da177e4SLinus Torvaldsmul64_err:
27061da177e4SLinus Torvalds	bsr.l		isp_restore		# restore addr reg
27071da177e4SLinus Torvalds	mov.l		%a2,%a0			# pass failing address
27081da177e4SLinus Torvalds	mov.l		&0x01010001,%d0		# pass fslw
27091da177e4SLinus Torvalds	bra.l		isp_dacc
27101da177e4SLinus Torvalds
27111da177e4SLinus Torvalds#########################################################################
27121da177e4SLinus Torvalds# XDEF ****************************************************************	#
27131da177e4SLinus Torvalds#	_compandset2(): routine to emulate cas2()			#
27141da177e4SLinus Torvalds#			(internal to package)				#
27151da177e4SLinus Torvalds#									#
27161da177e4SLinus Torvalds#	_isp_cas2_finish(): store ccodes, store compare regs		#
27171da177e4SLinus Torvalds#			    (external to package)			#
27181da177e4SLinus Torvalds#									#
27191da177e4SLinus Torvalds# XREF ****************************************************************	#
27201da177e4SLinus Torvalds#	_real_lock_page() - "callout" to lock op's page from page-outs	#
27211da177e4SLinus Torvalds#	_cas_terminate2() - access error exit				#
27221da177e4SLinus Torvalds#	_real_cas2() - "callout" to core cas2 emulation code		#
27231da177e4SLinus Torvalds#	_real_unlock_page() - "callout" to unlock page			#
27241da177e4SLinus Torvalds#									#
27251da177e4SLinus Torvalds# INPUT ***************************************************************	#
27261da177e4SLinus Torvalds# _compandset2():							#
27271da177e4SLinus Torvalds#	d0 = instruction extension word					#
27281da177e4SLinus Torvalds#									#
27291da177e4SLinus Torvalds# _isp_cas2_finish():							#
27301da177e4SLinus Torvalds#	see cas2 core emulation code					#
27311da177e4SLinus Torvalds#									#
27321da177e4SLinus Torvalds# OUTPUT **************************************************************	#
27331da177e4SLinus Torvalds# _compandset2():							#
27341da177e4SLinus Torvalds#	see cas2 core emulation code					#
27351da177e4SLinus Torvalds#									#
27361da177e4SLinus Torvalds# _isp_cas_finish():							#
27371da177e4SLinus Torvalds#	None (register file or memroy changed as appropriate)		#
27381da177e4SLinus Torvalds#									#
27391da177e4SLinus Torvalds# ALGORITHM ***********************************************************	#
27401da177e4SLinus Torvalds# compandset2():							#
27411da177e4SLinus Torvalds#	Decode the instruction and fetch the appropriate Update and	#
27421da177e4SLinus Torvalds# Compare operands. Then call the "callout" _real_lock_page() for each	#
27431da177e4SLinus Torvalds# memory operand address so that the operating system can keep these	#
27441da177e4SLinus Torvalds# pages from being paged out. If either _real_lock_page() fails, exit	#
27451da177e4SLinus Torvalds# through _cas_terminate2(). Don't forget to unlock the 1st locked page	#
27461da177e4SLinus Torvalds# using _real_unlock_paged() if the 2nd lock-page fails.		#
27471da177e4SLinus Torvalds# Finally, branch to the core cas2 emulation code by calling the	#
27481da177e4SLinus Torvalds# "callout" _real_cas2().						#
27491da177e4SLinus Torvalds#									#
27501da177e4SLinus Torvalds# _isp_cas2_finish():							#
27511da177e4SLinus Torvalds#	Re-perform the comparison so we can determine the condition	#
27521da177e4SLinus Torvalds# codes which were too much trouble to keep around during the locked	#
27531da177e4SLinus Torvalds# emulation. Then unlock each operands page by calling the "callout"	#
27541da177e4SLinus Torvalds# _real_unlock_page().							#
27551da177e4SLinus Torvalds#									#
27561da177e4SLinus Torvalds#########################################################################
27571da177e4SLinus Torvalds
27581da177e4SLinus Torvaldsset ADDR1,	EXC_TEMP+0xc
27591da177e4SLinus Torvaldsset ADDR2,	EXC_TEMP+0x0
27601da177e4SLinus Torvaldsset DC2,	EXC_TEMP+0xa
27611da177e4SLinus Torvaldsset DC1,	EXC_TEMP+0x8
27621da177e4SLinus Torvalds
27631da177e4SLinus Torvalds	global		_compandset2
27641da177e4SLinus Torvalds_compandset2:
27651da177e4SLinus Torvalds	mov.l		%d0,EXC_TEMP+0x4(%a6)		# store for possible restart
27661da177e4SLinus Torvalds	mov.l		%d0,%d1			# extension word in d0
27671da177e4SLinus Torvalds
27681da177e4SLinus Torvalds	rol.w		&0x4,%d0
27691da177e4SLinus Torvalds	andi.w		&0xf,%d0		# extract Rn2
27701da177e4SLinus Torvalds	mov.l		(EXC_DREGS,%a6,%d0.w*4),%a1 # fetch ADDR2
27711da177e4SLinus Torvalds	mov.l		%a1,ADDR2(%a6)
27721da177e4SLinus Torvalds
27731da177e4SLinus Torvalds	mov.l		%d1,%d0
27741da177e4SLinus Torvalds
27751da177e4SLinus Torvalds	lsr.w		&0x6,%d1
27761da177e4SLinus Torvalds	andi.w		&0x7,%d1		# extract Du2
27771da177e4SLinus Torvalds	mov.l		(EXC_DREGS,%a6,%d1.w*4),%d5 # fetch Update2 Op
27781da177e4SLinus Torvalds
27791da177e4SLinus Torvalds	andi.w		&0x7,%d0		# extract Dc2
27801da177e4SLinus Torvalds	mov.l		(EXC_DREGS,%a6,%d0.w*4),%d3 # fetch Compare2 Op
27811da177e4SLinus Torvalds	mov.w		%d0,DC2(%a6)
27821da177e4SLinus Torvalds
27831da177e4SLinus Torvalds	mov.w		EXC_EXTWORD(%a6),%d0
27841da177e4SLinus Torvalds	mov.l		%d0,%d1
27851da177e4SLinus Torvalds
27861da177e4SLinus Torvalds	rol.w		&0x4,%d0
27871da177e4SLinus Torvalds	andi.w		&0xf,%d0		# extract Rn1
27881da177e4SLinus Torvalds	mov.l		(EXC_DREGS,%a6,%d0.w*4),%a0 # fetch ADDR1
27891da177e4SLinus Torvalds	mov.l		%a0,ADDR1(%a6)
27901da177e4SLinus Torvalds
27911da177e4SLinus Torvalds	mov.l		%d1,%d0
27921da177e4SLinus Torvalds
27931da177e4SLinus Torvalds	lsr.w		&0x6,%d1
27941da177e4SLinus Torvalds	andi.w		&0x7,%d1		# extract Du1
27951da177e4SLinus Torvalds	mov.l		(EXC_DREGS,%a6,%d1.w*4),%d4 # fetch Update1 Op
27961da177e4SLinus Torvalds
27971da177e4SLinus Torvalds	andi.w		&0x7,%d0		# extract Dc1
27981da177e4SLinus Torvalds	mov.l		(EXC_DREGS,%a6,%d0.w*4),%d2 # fetch Compare1 Op
27991da177e4SLinus Torvalds	mov.w		%d0,DC1(%a6)
28001da177e4SLinus Torvalds
28011da177e4SLinus Torvalds	btst		&0x1,EXC_OPWORD(%a6)	# word or long?
28021da177e4SLinus Torvalds	sne		%d7
28031da177e4SLinus Torvalds
28041da177e4SLinus Torvalds	btst		&0x5,EXC_ISR(%a6)	# user or supervisor?
28051da177e4SLinus Torvalds	sne		%d6
28061da177e4SLinus Torvalds
28071da177e4SLinus Torvalds	mov.l		%a0,%a2
28081da177e4SLinus Torvalds	mov.l		%a1,%a3
28091da177e4SLinus Torvalds
28101da177e4SLinus Torvalds	mov.l		%d7,%d1			# pass size
28111da177e4SLinus Torvalds	mov.l		%d6,%d0			# pass mode
28121da177e4SLinus Torvalds	bsr.l		_real_lock_page		# lock page
28131da177e4SLinus Torvalds	mov.l		%a2,%a0
28141da177e4SLinus Torvalds	tst.l		%d0			# error?
28151da177e4SLinus Torvalds	bne.l		_cas_terminate2		# yes
28161da177e4SLinus Torvalds
28171da177e4SLinus Torvalds	mov.l		%d7,%d1			# pass size
28181da177e4SLinus Torvalds	mov.l		%d6,%d0			# pass mode
28191da177e4SLinus Torvalds	mov.l		%a3,%a0			# pass addr
28201da177e4SLinus Torvalds	bsr.l		_real_lock_page		# lock page
28211da177e4SLinus Torvalds	mov.l		%a3,%a0
28221da177e4SLinus Torvalds	tst.l		%d0			# error?
28231da177e4SLinus Torvalds	bne.b		cas_preterm		# yes
28241da177e4SLinus Torvalds
28251da177e4SLinus Torvalds	mov.l		%a2,%a0
28261da177e4SLinus Torvalds	mov.l		%a3,%a1
28271da177e4SLinus Torvalds
28281da177e4SLinus Torvalds	bra.l		_real_cas2
28291da177e4SLinus Torvalds
28301da177e4SLinus Torvalds# if the 2nd lock attempt fails, then we must still unlock the
28311da177e4SLinus Torvalds# first page(s).
28321da177e4SLinus Torvaldscas_preterm:
28331da177e4SLinus Torvalds	mov.l		%d0,-(%sp)		# save FSLW
28341da177e4SLinus Torvalds	mov.l		%d7,%d1			# pass size
28351da177e4SLinus Torvalds	mov.l		%d6,%d0			# pass mode
28361da177e4SLinus Torvalds	mov.l		%a2,%a0			# pass ADDR1
28371da177e4SLinus Torvalds	bsr.l		_real_unlock_page	# unlock first page(s)
28381da177e4SLinus Torvalds	mov.l		(%sp)+,%d0		# restore FSLW
28391da177e4SLinus Torvalds	mov.l		%a3,%a0			# pass failing addr
28401da177e4SLinus Torvalds	bra.l		_cas_terminate2
28411da177e4SLinus Torvalds
28421da177e4SLinus Torvalds#############################################################
28431da177e4SLinus Torvalds
28441da177e4SLinus Torvalds	global		_isp_cas2_finish
28451da177e4SLinus Torvalds_isp_cas2_finish:
28461da177e4SLinus Torvalds	btst		&0x1,EXC_OPWORD(%a6)
28471da177e4SLinus Torvalds	bne.b		cas2_finish_l
28481da177e4SLinus Torvalds
28491da177e4SLinus Torvalds	mov.w		EXC_CC(%a6),%cc		# load old ccodes
28501da177e4SLinus Torvalds	cmp.w		%d0,%d2
28511da177e4SLinus Torvalds	bne.b		cas2_finish_w_save
28521da177e4SLinus Torvalds	cmp.w		%d1,%d3
28531da177e4SLinus Torvaldscas2_finish_w_save:
28541da177e4SLinus Torvalds	mov.w		%cc,EXC_CC(%a6)		# save new ccodes
28551da177e4SLinus Torvalds
28561da177e4SLinus Torvalds	tst.b		%d4			# update compare reg?
28571da177e4SLinus Torvalds	bne.b		cas2_finish_w_done	# no
28581da177e4SLinus Torvalds
28591da177e4SLinus Torvalds	mov.w		DC2(%a6),%d3		# fetch Dc2
28601da177e4SLinus Torvalds	mov.w		%d1,(2+EXC_DREGS,%a6,%d3.w*4) # store new Compare2 Op
28611da177e4SLinus Torvalds
28621da177e4SLinus Torvalds	mov.w		DC1(%a6),%d2		# fetch Dc1
28631da177e4SLinus Torvalds	mov.w		%d0,(2+EXC_DREGS,%a6,%d2.w*4) # store new Compare1 Op
28641da177e4SLinus Torvalds
28651da177e4SLinus Torvaldscas2_finish_w_done:
28661da177e4SLinus Torvalds	btst		&0x5,EXC_ISR(%a6)
28671da177e4SLinus Torvalds	sne		%d2
28681da177e4SLinus Torvalds	mov.l		%d2,%d0			# pass mode
28691da177e4SLinus Torvalds	sf		%d1			# pass size
28701da177e4SLinus Torvalds	mov.l		ADDR1(%a6),%a0		# pass ADDR1
28711da177e4SLinus Torvalds	bsr.l		_real_unlock_page	# unlock page
28721da177e4SLinus Torvalds
28731da177e4SLinus Torvalds	mov.l		%d2,%d0			# pass mode
28741da177e4SLinus Torvalds	sf		%d1			# pass size
28751da177e4SLinus Torvalds	mov.l		ADDR2(%a6),%a0		# pass ADDR2
28761da177e4SLinus Torvalds	bsr.l		_real_unlock_page	# unlock page
28771da177e4SLinus Torvalds	rts
28781da177e4SLinus Torvalds
28791da177e4SLinus Torvaldscas2_finish_l:
28801da177e4SLinus Torvalds	mov.w		EXC_CC(%a6),%cc		# load old ccodes
28811da177e4SLinus Torvalds	cmp.l		%d0,%d2
28821da177e4SLinus Torvalds	bne.b		cas2_finish_l_save
28831da177e4SLinus Torvalds	cmp.l		%d1,%d3
28841da177e4SLinus Torvaldscas2_finish_l_save:
28851da177e4SLinus Torvalds	mov.w		%cc,EXC_CC(%a6)		# save new ccodes
28861da177e4SLinus Torvalds
28871da177e4SLinus Torvalds	tst.b		%d4			# update compare reg?
28881da177e4SLinus Torvalds	bne.b		cas2_finish_l_done	# no
28891da177e4SLinus Torvalds
28901da177e4SLinus Torvalds	mov.w		DC2(%a6),%d3		# fetch Dc2
28911da177e4SLinus Torvalds	mov.l		%d1,(EXC_DREGS,%a6,%d3.w*4) # store new Compare2 Op
28921da177e4SLinus Torvalds
28931da177e4SLinus Torvalds	mov.w		DC1(%a6),%d2		# fetch Dc1
28941da177e4SLinus Torvalds	mov.l		%d0,(EXC_DREGS,%a6,%d2.w*4) # store new Compare1 Op
28951da177e4SLinus Torvalds
28961da177e4SLinus Torvaldscas2_finish_l_done:
28971da177e4SLinus Torvalds	btst		&0x5,EXC_ISR(%a6)
28981da177e4SLinus Torvalds	sne		%d2
28991da177e4SLinus Torvalds	mov.l		%d2,%d0			# pass mode
29001da177e4SLinus Torvalds	st		%d1			# pass size
29011da177e4SLinus Torvalds	mov.l		ADDR1(%a6),%a0		# pass ADDR1
29021da177e4SLinus Torvalds	bsr.l		_real_unlock_page	# unlock page
29031da177e4SLinus Torvalds
29041da177e4SLinus Torvalds	mov.l		%d2,%d0			# pass mode
29051da177e4SLinus Torvalds	st		%d1			# pass size
29061da177e4SLinus Torvalds	mov.l		ADDR2(%a6),%a0		# pass ADDR2
29071da177e4SLinus Torvalds	bsr.l		_real_unlock_page	# unlock page
29081da177e4SLinus Torvalds	rts
29091da177e4SLinus Torvalds
29101da177e4SLinus Torvalds########
29111da177e4SLinus Torvalds	global		cr_cas2
29121da177e4SLinus Torvaldscr_cas2:
29131da177e4SLinus Torvalds	mov.l		EXC_TEMP+0x4(%a6),%d0
29141da177e4SLinus Torvalds	bra.w		_compandset2
29151da177e4SLinus Torvalds
29161da177e4SLinus Torvalds#########################################################################
29171da177e4SLinus Torvalds# XDEF ****************************************************************	#
29181da177e4SLinus Torvalds#	_compandset(): routine to emulate cas w/ misaligned <ea>	#
29191da177e4SLinus Torvalds#		       (internal to package)				#
29201da177e4SLinus Torvalds#	_isp_cas_finish(): routine called when cas emulation completes	#
29211da177e4SLinus Torvalds#			   (external and internal to package)		#
29221da177e4SLinus Torvalds#	_isp_cas_restart(): restart cas emulation after a fault		#
29231da177e4SLinus Torvalds#			    (external to package)			#
29241da177e4SLinus Torvalds#	_isp_cas_terminate(): create access error stack frame on fault	#
29251da177e4SLinus Torvalds#			      (external and internal to package)	#
29261da177e4SLinus Torvalds#	_isp_cas_inrange(): checks whether instr addess is within range	#
29271da177e4SLinus Torvalds#			    of core cas/cas2emulation code		#
29281da177e4SLinus Torvalds#			    (external to package)			#
29291da177e4SLinus Torvalds#									#
29301da177e4SLinus Torvalds# XREF ****************************************************************	#
29311da177e4SLinus Torvalds#	_calc_ea(): calculate effective address				#
29321da177e4SLinus Torvalds#									#
29331da177e4SLinus Torvalds# INPUT ***************************************************************	#
29341da177e4SLinus Torvalds# compandset():								#
29351da177e4SLinus Torvalds#	none								#
29361da177e4SLinus Torvalds# _isp_cas_restart():							#
29371da177e4SLinus Torvalds#	d6 = previous sfc/dfc						#
29381da177e4SLinus Torvalds# _isp_cas_finish():							#
29391da177e4SLinus Torvalds# _isp_cas_terminate():							#
29401da177e4SLinus Torvalds#	a0 = failing address						#
29411da177e4SLinus Torvalds#	d0 = FSLW							#
29421da177e4SLinus Torvalds#	d6 = previous sfc/dfc						#
29431da177e4SLinus Torvalds# _isp_cas_inrange():							#
29441da177e4SLinus Torvalds#	a0 = instruction address to be checked				#
29451da177e4SLinus Torvalds#									#
29461da177e4SLinus Torvalds# OUTPUT **************************************************************	#
29471da177e4SLinus Torvalds# compandset():								#
29481da177e4SLinus Torvalds#		none							#
29491da177e4SLinus Torvalds# _isp_cas_restart():							#
29501da177e4SLinus Torvalds#	a0 = effective address						#
29511da177e4SLinus Torvalds#	d7 = word or longword flag					#
29521da177e4SLinus Torvalds# _isp_cas_finish():							#
29531da177e4SLinus Torvalds#	a0 = effective address						#
29541da177e4SLinus Torvalds# _isp_cas_terminate():							#
29551da177e4SLinus Torvalds#	initial register set before emulation exception			#
29561da177e4SLinus Torvalds# _isp_cas_inrange():							#
29571da177e4SLinus Torvalds#	d0 = 0 => in range; -1 => out of range				#
29581da177e4SLinus Torvalds#									#
29591da177e4SLinus Torvalds# ALGORITHM ***********************************************************	#
29601da177e4SLinus Torvalds#									#
29611da177e4SLinus Torvalds# compandset():								#
29621da177e4SLinus Torvalds#	First, calculate the effective address. Then, decode the	#
29631da177e4SLinus Torvalds# instruction word and fetch the "compare" (DC) and "update" (Du)	#
29641da177e4SLinus Torvalds# operands.								#
29651da177e4SLinus Torvalds#	Next, call the external routine _real_lock_page() so that the	#
29661da177e4SLinus Torvalds# operating system can keep this page from being paged out while we're	#
29671da177e4SLinus Torvalds# in this routine. If this call fails, jump to _cas_terminate2().	#
29681da177e4SLinus Torvalds#	The routine then branches to _real_cas(). This external routine	#
29691da177e4SLinus Torvalds# that actually emulates cas can be supplied by the external os or	#
29701da177e4SLinus Torvalds# made to point directly back into the 060ISP which has a routine for	#
29711da177e4SLinus Torvalds# this purpose.								#
29721da177e4SLinus Torvalds#									#
29731da177e4SLinus Torvalds# _isp_cas_finish():							#
29741da177e4SLinus Torvalds#	Either way, after emulation, the package is re-entered at	#
29751da177e4SLinus Torvalds# _isp_cas_finish(). This routine re-compares the operands in order to	#
29761da177e4SLinus Torvalds# set the condition codes. Finally, these routines will call		#
29771da177e4SLinus Torvalds# _real_unlock_page() in order to unlock the pages that were previously	#
29781da177e4SLinus Torvalds# locked.								#
29791da177e4SLinus Torvalds#									#
29801da177e4SLinus Torvalds# _isp_cas_restart():							#
29811da177e4SLinus Torvalds#	This routine can be entered from an access error handler where	#
29821da177e4SLinus Torvalds# the emulation sequence should be re-started from the beginning.	#
29831da177e4SLinus Torvalds#									#
29841da177e4SLinus Torvalds# _isp_cas_terminate():							#
29851da177e4SLinus Torvalds#	This routine can be entered from an access error handler where	#
29861da177e4SLinus Torvalds# an emulation operand access failed and the operating system would	#
29871da177e4SLinus Torvalds# like an access error stack frame created instead of the current	#
29881da177e4SLinus Torvalds# unimplemented integer instruction frame.				#
29891da177e4SLinus Torvalds#	Also, the package enters here if a call to _real_lock_page()	#
29901da177e4SLinus Torvalds# fails.								#
29911da177e4SLinus Torvalds#									#
29921da177e4SLinus Torvalds# _isp_cas_inrange():							#
29931da177e4SLinus Torvalds#	Checks to see whether the instruction address passed to it in	#
29941da177e4SLinus Torvalds# a0 is within the software package cas/cas2 emulation routines. This	#
29951da177e4SLinus Torvalds# can be helpful for an operating system to determine whether an access	#
29961da177e4SLinus Torvalds# error during emulation was due to a cas/cas2 emulation access.	#
29971da177e4SLinus Torvalds#									#
29981da177e4SLinus Torvalds#########################################################################
29991da177e4SLinus Torvalds
30001da177e4SLinus Torvaldsset DC,		EXC_TEMP+0x8
30011da177e4SLinus Torvaldsset ADDR,	EXC_TEMP+0x4
30021da177e4SLinus Torvalds
30031da177e4SLinus Torvalds	global		_compandset
30041da177e4SLinus Torvalds_compandset:
30051da177e4SLinus Torvalds	btst		&0x1,EXC_OPWORD(%a6)	# word or long operation?
30061da177e4SLinus Torvalds	bne.b		compandsetl		# long
30071da177e4SLinus Torvalds
30081da177e4SLinus Torvaldscompandsetw:
30091da177e4SLinus Torvalds	movq.l		&0x2,%d0		# size = 2 bytes
30101da177e4SLinus Torvalds	bsr.l		_calc_ea		# a0 = calculated <ea>
30111da177e4SLinus Torvalds	mov.l		%a0,ADDR(%a6)		# save <ea> for possible restart
30121da177e4SLinus Torvalds	sf		%d7			# clear d7 for word size
30131da177e4SLinus Torvalds	bra.b		compandsetfetch
30141da177e4SLinus Torvalds
30151da177e4SLinus Torvaldscompandsetl:
30161da177e4SLinus Torvalds	movq.l		&0x4,%d0		# size = 4 bytes
30171da177e4SLinus Torvalds	bsr.l		_calc_ea		# a0 = calculated <ea>
30181da177e4SLinus Torvalds	mov.l		%a0,ADDR(%a6)		# save <ea> for possible restart
30191da177e4SLinus Torvalds	st		%d7			# set d7 for longword size
30201da177e4SLinus Torvalds
30211da177e4SLinus Torvaldscompandsetfetch:
30221da177e4SLinus Torvalds	mov.w		EXC_EXTWORD(%a6),%d0	# fetch cas extension word
30231da177e4SLinus Torvalds	mov.l		%d0,%d1			# make a copy
30241da177e4SLinus Torvalds
30251da177e4SLinus Torvalds	lsr.w		&0x6,%d0
30261da177e4SLinus Torvalds	andi.w		&0x7,%d0		# extract Du
30271da177e4SLinus Torvalds	mov.l		(EXC_DREGS,%a6,%d0.w*4),%d2 # get update operand
30281da177e4SLinus Torvalds
30291da177e4SLinus Torvalds	andi.w		&0x7,%d1		# extract Dc
30301da177e4SLinus Torvalds	mov.l		(EXC_DREGS,%a6,%d1.w*4),%d4 # get compare operand
30311da177e4SLinus Torvalds	mov.w		%d1,DC(%a6)		# save Dc
30321da177e4SLinus Torvalds
30331da177e4SLinus Torvalds	btst		&0x5,EXC_ISR(%a6)	# which mode for exception?
30341da177e4SLinus Torvalds	sne		%d6			# set on supervisor mode
30351da177e4SLinus Torvalds
30361da177e4SLinus Torvalds	mov.l		%a0,%a2			# save temporarily
30371da177e4SLinus Torvalds	mov.l		%d7,%d1			# pass size
30381da177e4SLinus Torvalds	mov.l		%d6,%d0			# pass mode
30391da177e4SLinus Torvalds	bsr.l		_real_lock_page		# lock page
30401da177e4SLinus Torvalds	tst.l		%d0			# did error occur?
30411da177e4SLinus Torvalds	bne.w		_cas_terminate2		# yes, clean up the mess
30421da177e4SLinus Torvalds	mov.l		%a2,%a0			# pass addr in a0
30431da177e4SLinus Torvalds
30441da177e4SLinus Torvalds	bra.l		_real_cas
30451da177e4SLinus Torvalds
30461da177e4SLinus Torvalds########
30471da177e4SLinus Torvalds	global		_isp_cas_finish
30481da177e4SLinus Torvalds_isp_cas_finish:
30491da177e4SLinus Torvalds	btst		&0x1,EXC_OPWORD(%a6)
30501da177e4SLinus Torvalds	bne.b		cas_finish_l
30511da177e4SLinus Torvalds
30521da177e4SLinus Torvalds# just do the compare again since it's faster than saving the ccodes
30531da177e4SLinus Torvalds# from the locked routine...
30541da177e4SLinus Torvaldscas_finish_w:
30551da177e4SLinus Torvalds	mov.w		EXC_CC(%a6),%cc		# restore cc
30561da177e4SLinus Torvalds	cmp.w		%d0,%d4			# do word compare
30571da177e4SLinus Torvalds	mov.w		%cc,EXC_CC(%a6)		# save cc
30581da177e4SLinus Torvalds
30591da177e4SLinus Torvalds	tst.b		%d1			# update compare reg?
30601da177e4SLinus Torvalds	bne.b		cas_finish_w_done	# no
30611da177e4SLinus Torvalds
30621da177e4SLinus Torvalds	mov.w		DC(%a6),%d3
30631da177e4SLinus Torvalds	mov.w		%d0,(EXC_DREGS+2,%a6,%d3.w*4) # Dc = destination
30641da177e4SLinus Torvalds
30651da177e4SLinus Torvaldscas_finish_w_done:
30661da177e4SLinus Torvalds	mov.l		ADDR(%a6),%a0		# pass addr
30671da177e4SLinus Torvalds	sf		%d1			# pass size
30681da177e4SLinus Torvalds	btst		&0x5,EXC_ISR(%a6)
30691da177e4SLinus Torvalds	sne		%d0			# pass mode
30701da177e4SLinus Torvalds	bsr.l		_real_unlock_page	# unlock page
30711da177e4SLinus Torvalds	rts
30721da177e4SLinus Torvalds
30731da177e4SLinus Torvalds# just do the compare again since it's faster than saving the ccodes
30741da177e4SLinus Torvalds# from the locked routine...
30751da177e4SLinus Torvaldscas_finish_l:
30761da177e4SLinus Torvalds	mov.w		EXC_CC(%a6),%cc		# restore cc
30771da177e4SLinus Torvalds	cmp.l		%d0,%d4			# do longword compare
30781da177e4SLinus Torvalds	mov.w		%cc,EXC_CC(%a6)		# save cc
30791da177e4SLinus Torvalds
30801da177e4SLinus Torvalds	tst.b		%d1			# update compare reg?
30811da177e4SLinus Torvalds	bne.b		cas_finish_l_done	# no
30821da177e4SLinus Torvalds
30831da177e4SLinus Torvalds	mov.w		DC(%a6),%d3
30841da177e4SLinus Torvalds	mov.l		%d0,(EXC_DREGS,%a6,%d3.w*4) # Dc = destination
30851da177e4SLinus Torvalds
30861da177e4SLinus Torvaldscas_finish_l_done:
30871da177e4SLinus Torvalds	mov.l		ADDR(%a6),%a0		# pass addr
30881da177e4SLinus Torvalds	st		%d1			# pass size
30891da177e4SLinus Torvalds	btst		&0x5,EXC_ISR(%a6)
30901da177e4SLinus Torvalds	sne		%d0			# pass mode
30911da177e4SLinus Torvalds	bsr.l		_real_unlock_page	# unlock page
30921da177e4SLinus Torvalds	rts
30931da177e4SLinus Torvalds
30941da177e4SLinus Torvalds########
30951da177e4SLinus Torvalds
30961da177e4SLinus Torvalds	global		_isp_cas_restart
30971da177e4SLinus Torvalds_isp_cas_restart:
30981da177e4SLinus Torvalds	mov.l		%d6,%sfc		# restore previous sfc
30991da177e4SLinus Torvalds	mov.l		%d6,%dfc		# restore previous dfc
31001da177e4SLinus Torvalds
31011da177e4SLinus Torvalds	cmpi.b		EXC_OPWORD+1(%a6),&0xfc	# cas or cas2?
31021da177e4SLinus Torvalds	beq.l		cr_cas2			# cas2
31031da177e4SLinus Torvaldscr_cas:
31041da177e4SLinus Torvalds	mov.l		ADDR(%a6),%a0		# load <ea>
31051da177e4SLinus Torvalds	btst		&0x1,EXC_OPWORD(%a6)	# word or long operation?
31061da177e4SLinus Torvalds	sne		%d7			# set d7 accordingly
31071da177e4SLinus Torvalds	bra.w		compandsetfetch
31081da177e4SLinus Torvalds
31091da177e4SLinus Torvalds########
31101da177e4SLinus Torvalds
31111da177e4SLinus Torvalds# At this stage, it would be nice if d0 held the FSLW.
31121da177e4SLinus Torvalds	global		_isp_cas_terminate
31131da177e4SLinus Torvalds_isp_cas_terminate:
31141da177e4SLinus Torvalds	mov.l		%d6,%sfc		# restore previous sfc
31151da177e4SLinus Torvalds	mov.l		%d6,%dfc		# restore previous dfc
31161da177e4SLinus Torvalds
31171da177e4SLinus Torvalds	global		_cas_terminate2
31181da177e4SLinus Torvalds_cas_terminate2:
31191da177e4SLinus Torvalds	mov.l		%a0,%a2			# copy failing addr to a2
31201da177e4SLinus Torvalds
31211da177e4SLinus Torvalds	mov.l		%d0,-(%sp)
31221da177e4SLinus Torvalds	bsr.l		isp_restore		# restore An (if ()+ or -())
31231da177e4SLinus Torvalds	mov.l		(%sp)+,%d0
31241da177e4SLinus Torvalds
31251da177e4SLinus Torvalds	addq.l		&0x4,%sp		# remove sub return addr
31261da177e4SLinus Torvalds	subq.l		&0x8,%sp		# make room for bigger stack
31271da177e4SLinus Torvalds	subq.l		&0x8,%a6		# shift frame ptr down, too
31281da177e4SLinus Torvalds	mov.l		&26,%d1			# want to move 51 longwords
31291da177e4SLinus Torvalds	lea		0x8(%sp),%a0		# get address of old stack
31301da177e4SLinus Torvalds	lea		0x0(%sp),%a1		# get address of new stack
31311da177e4SLinus Torvaldscas_term_cont:
31321da177e4SLinus Torvalds	mov.l		(%a0)+,(%a1)+		# move a longword
31331da177e4SLinus Torvalds	dbra.w		%d1,cas_term_cont	# keep going
31341da177e4SLinus Torvalds
31351da177e4SLinus Torvalds	mov.w		&0x4008,EXC_IVOFF(%a6)	# put new stk fmt, voff
31361da177e4SLinus Torvalds	mov.l		%a2,EXC_IVOFF+0x2(%a6)	# put faulting addr on stack
31371da177e4SLinus Torvalds	mov.l		%d0,EXC_IVOFF+0x6(%a6)	# put FSLW on stack
31381da177e4SLinus Torvalds	movm.l		EXC_DREGS(%a6),&0x3fff	# restore user regs
31391da177e4SLinus Torvalds	unlk		%a6			# unlink stack frame
31401da177e4SLinus Torvalds	bra.l		_real_access
31411da177e4SLinus Torvalds
31421da177e4SLinus Torvalds########
31431da177e4SLinus Torvalds
31441da177e4SLinus Torvalds	global		_isp_cas_inrange
31451da177e4SLinus Torvalds_isp_cas_inrange:
31461da177e4SLinus Torvalds	clr.l		%d0			# clear return result
31471da177e4SLinus Torvalds	lea		_CASHI(%pc),%a1		# load end of CAS core code
31481da177e4SLinus Torvalds	cmp.l		%a1,%a0			# is PC in range?
31491da177e4SLinus Torvalds	blt.b		cin_no			# no
31501da177e4SLinus Torvalds	lea		_CASLO(%pc),%a1		# load begin of CAS core code
31511da177e4SLinus Torvalds	cmp.l		%a0,%a1			# is PC in range?
31521da177e4SLinus Torvalds	blt.b		cin_no			# no
31531da177e4SLinus Torvalds	rts					# yes; return d0 = 0
31541da177e4SLinus Torvaldscin_no:
31551da177e4SLinus Torvalds	mov.l		&-0x1,%d0		# out of range; return d0 = -1
31561da177e4SLinus Torvalds	rts
31571da177e4SLinus Torvalds
31581da177e4SLinus Torvalds#################################################################
31591da177e4SLinus Torvalds#################################################################
31601da177e4SLinus Torvalds#################################################################
31611da177e4SLinus Torvalds# This is the start of the cas and cas2 "core" emulation code.	#
31621da177e4SLinus Torvalds# This is the section that may need to be replaced by the host	#
31631da177e4SLinus Torvalds# OS if it is too operating system-specific.			#
31641da177e4SLinus Torvalds# Please refer to the package documentation to see how to	#
31651da177e4SLinus Torvalds# "replace" this section, if necessary.				#
31661da177e4SLinus Torvalds#################################################################
31671da177e4SLinus Torvalds#################################################################
31681da177e4SLinus Torvalds#################################################################
31691da177e4SLinus Torvalds
31701da177e4SLinus Torvalds#       ######      ##      ######     ####
31711da177e4SLinus Torvalds#       #	   #  #     #         #    #
31721da177e4SLinus Torvalds#	#	  ######    ######        #
31731da177e4SLinus Torvalds#	#	  #    #         #      #
31741da177e4SLinus Torvalds#       ######    #    #    ######    ######
31751da177e4SLinus Torvalds
31761da177e4SLinus Torvalds#########################################################################
31771da177e4SLinus Torvalds# XDEF ****************************************************************	#
31781da177e4SLinus Torvalds#	_isp_cas2(): "core" emulation code for the cas2 instruction	#
31791da177e4SLinus Torvalds#									#
31801da177e4SLinus Torvalds# XREF ****************************************************************	#
31811da177e4SLinus Torvalds#	_isp_cas2_finish() - only exit point for this emulation code;	#
31821da177e4SLinus Torvalds#			     do clean-up; calculate ccodes; store	#
31831da177e4SLinus Torvalds#			     Compare Ops if appropriate.		#
31841da177e4SLinus Torvalds#									#
31851da177e4SLinus Torvalds# INPUT ***************************************************************	#
31861da177e4SLinus Torvalds#	*see chart below*						#
31871da177e4SLinus Torvalds#									#
31881da177e4SLinus Torvalds# OUTPUT **************************************************************	#
31891da177e4SLinus Torvalds#	*see chart below*						#
31901da177e4SLinus Torvalds#									#
31911da177e4SLinus Torvalds# ALGORITHM ***********************************************************	#
31921da177e4SLinus Torvalds#	(1) Make several copies of the effective address.		#
31931da177e4SLinus Torvalds#	(2) Save current SR; Then mask off all maskable interrupts.	#
31941da177e4SLinus Torvalds#	(3) Save current SFC/DFC (ASSUMED TO BE EQUAL!!!); Then set	#
31951da177e4SLinus Torvalds#	    according to whether exception occurred in user or		#
31961da177e4SLinus Torvalds#	    supervisor mode.						#
31971da177e4SLinus Torvalds#	(4) Use "plpaw" instruction to pre-load ATC with effective	#
31981da177e4SLinus Torvalds#	    address pages(s). THIS SHOULD NOT FAULT!!! The relevant	#
31991da177e4SLinus Torvalds#	    page(s) should have already been made resident prior to	#
32001da177e4SLinus Torvalds#	    entering this routine.					#
32011da177e4SLinus Torvalds#	(5) Push the operand lines from the cache w/ "cpushl".		#
32021da177e4SLinus Torvalds#	    In the 68040, this was done within the locked region. In	#
32031da177e4SLinus Torvalds#	    the 68060, it is done outside of the locked region.		#
32041da177e4SLinus Torvalds#	(6) Use "plpar" instruction to do a re-load of ATC entries for	#
32051da177e4SLinus Torvalds#	    ADDR1 since ADDR2 entries may have pushed ADDR1 out of the	#
32061da177e4SLinus Torvalds#	    ATC.							#
32071da177e4SLinus Torvalds#	(7) Pre-fetch the core emulation instructions by executing	#
32081da177e4SLinus Torvalds#	    one branch within each physical line (16 bytes) of the code	#
32091da177e4SLinus Torvalds#	    before actually executing the code.				#
32101da177e4SLinus Torvalds#	(8) Load the BUSCR w/ the bus lock value.			#
32111da177e4SLinus Torvalds#	(9) Fetch the source operands using "moves".			#
32121da177e4SLinus Torvalds#	(10)Do the compares. If both equal, go to step (13).		#
32131da177e4SLinus Torvalds#	(11)Unequal. No update occurs. But, we do write the DST1 op	#
32141da177e4SLinus Torvalds#	    back to itself (as w/ the '040) so we can gracefully unlock	#
32151da177e4SLinus Torvalds#	    the bus (and assert LOCKE*) using BUSCR and the final move.	#
32161da177e4SLinus Torvalds#	(12)Exit.							#
32171da177e4SLinus Torvalds#	(13)Write update operand to the DST locations. Use BUSCR to	#
32181da177e4SLinus Torvalds#	    assert LOCKE* for the final write operation.		#
32191da177e4SLinus Torvalds#	(14)Exit.							#
32201da177e4SLinus Torvalds#									#
32211da177e4SLinus Torvalds#	The algorithm is actually implemented slightly differently	#
32221da177e4SLinus Torvalds# depending on the size of the operation and the misalignment of the	#
32231da177e4SLinus Torvalds# operands. A misaligned operand must be written in aligned chunks or	#
32241da177e4SLinus Torvalds# else the BUSCR register control gets confused.			#
32251da177e4SLinus Torvalds#									#
32261da177e4SLinus Torvalds#########################################################################
32271da177e4SLinus Torvalds
32281da177e4SLinus Torvalds#################################################################
32291da177e4SLinus Torvalds# THIS IS THE STATE OF THE INTEGER REGISTER FILE UPON		#
32301da177e4SLinus Torvalds# ENTERING _isp_cas2().						#
32311da177e4SLinus Torvalds#								#
32321da177e4SLinus Torvalds# D0 = xxxxxxxx							#
32331da177e4SLinus Torvalds# D1 = xxxxxxxx							#
32341da177e4SLinus Torvalds# D2 = cmp operand 1						#
32351da177e4SLinus Torvalds# D3 = cmp operand 2						#
32361da177e4SLinus Torvalds# D4 = update oper 1						#
32371da177e4SLinus Torvalds# D5 = update oper 2						#
32381da177e4SLinus Torvalds# D6 = 'xxxxxxff if supervisor mode; 'xxxxxx00 if user mode	#
32391da177e4SLinus Torvalds# D7 = 'xxxxxxff if longword operation; 'xxxxxx00 if word	#
32401da177e4SLinus Torvalds# A0 = ADDR1							#
32411da177e4SLinus Torvalds# A1 = ADDR2							#
32421da177e4SLinus Torvalds# A2 = xxxxxxxx							#
32431da177e4SLinus Torvalds# A3 = xxxxxxxx							#
32441da177e4SLinus Torvalds# A4 = xxxxxxxx							#
32451da177e4SLinus Torvalds# A5 = xxxxxxxx							#
32461da177e4SLinus Torvalds# A6 = frame pointer						#
32471da177e4SLinus Torvalds# A7 = stack pointer						#
32481da177e4SLinus Torvalds#################################################################
32491da177e4SLinus Torvalds
32501da177e4SLinus Torvalds#	align		0x1000
32511da177e4SLinus Torvalds# beginning label used by _isp_cas_inrange()
32521da177e4SLinus Torvalds	global		_CASLO
32531da177e4SLinus Torvalds_CASLO:
32541da177e4SLinus Torvalds
32551da177e4SLinus Torvalds	global		_isp_cas2
32561da177e4SLinus Torvalds_isp_cas2:
32571da177e4SLinus Torvalds	tst.b		%d6			# user or supervisor mode?
32581da177e4SLinus Torvalds	bne.b		cas2_supervisor		# supervisor
32591da177e4SLinus Torvaldscas2_user:
32601da177e4SLinus Torvalds	movq.l		&0x1,%d0		# load user data fc
32611da177e4SLinus Torvalds	bra.b		cas2_cont
32621da177e4SLinus Torvaldscas2_supervisor:
32631da177e4SLinus Torvalds	movq.l		&0x5,%d0		# load supervisor data fc
32641da177e4SLinus Torvaldscas2_cont:
32651da177e4SLinus Torvalds	tst.b		%d7			# word or longword?
32661da177e4SLinus Torvalds	beq.w		cas2w			# word
32671da177e4SLinus Torvalds
32681da177e4SLinus Torvalds####
32691da177e4SLinus Torvaldscas2l:
32701da177e4SLinus Torvalds	mov.l		%a0,%a2			# copy ADDR1
32711da177e4SLinus Torvalds	mov.l		%a1,%a3			# copy ADDR2
32721da177e4SLinus Torvalds	mov.l		%a0,%a4			# copy ADDR1
32731da177e4SLinus Torvalds	mov.l		%a1,%a5			# copy ADDR2
32741da177e4SLinus Torvalds
32751da177e4SLinus Torvalds	addq.l		&0x3,%a4		# ADDR1+3
32761da177e4SLinus Torvalds	addq.l		&0x3,%a5		# ADDR2+3
32771da177e4SLinus Torvalds	mov.l		%a2,%d1			# ADDR1
32781da177e4SLinus Torvalds
32791da177e4SLinus Torvalds# mask interrupts levels 0-6. save old mask value.
32801da177e4SLinus Torvalds	mov.w		%sr,%d7			# save current SR
32811da177e4SLinus Torvalds	ori.w		&0x0700,%sr		# inhibit interrupts
32821da177e4SLinus Torvalds
32831da177e4SLinus Torvalds# load the SFC and DFC with the appropriate mode.
32841da177e4SLinus Torvalds	movc		%sfc,%d6		# save old SFC/DFC
32851da177e4SLinus Torvalds	movc		%d0,%sfc		# store new SFC
32861da177e4SLinus Torvalds	movc		%d0,%dfc		# store new DFC
32871da177e4SLinus Torvalds
32881da177e4SLinus Torvalds# pre-load the operand ATC. no page faults should occur here because
32891da177e4SLinus Torvalds# _real_lock_page() should have taken care of this.
32901da177e4SLinus Torvalds	plpaw		(%a2)			# load atc for ADDR1
32911da177e4SLinus Torvalds	plpaw		(%a4)			# load atc for ADDR1+3
32921da177e4SLinus Torvalds	plpaw		(%a3)			# load atc for ADDR2
32931da177e4SLinus Torvalds	plpaw		(%a5)			# load atc for ADDR2+3
32941da177e4SLinus Torvalds
32951da177e4SLinus Torvalds# push the operand lines from the cache if they exist.
32961da177e4SLinus Torvalds	cpushl		%dc,(%a2)		# push line for ADDR1
32971da177e4SLinus Torvalds	cpushl		%dc,(%a4)		# push line for ADDR1+3
32981da177e4SLinus Torvalds	cpushl		%dc,(%a3)		# push line for ADDR2
32991da177e4SLinus Torvalds	cpushl		%dc,(%a5)		# push line for ADDR2+2
33001da177e4SLinus Torvalds
33011da177e4SLinus Torvalds	mov.l		%d1,%a2			# ADDR1
33021da177e4SLinus Torvalds	addq.l		&0x3,%d1
33031da177e4SLinus Torvalds	mov.l		%d1,%a4			# ADDR1+3
33041da177e4SLinus Torvalds# if ADDR1 was ATC resident before the above "plpaw" and was executed
33051da177e4SLinus Torvalds# and it was the next entry scheduled for replacement and ADDR2
33061da177e4SLinus Torvalds# shares the same set, then the "plpaw" for ADDR2 can push the ADDR1
33071da177e4SLinus Torvalds# entries from the ATC. so, we do a second set of "plpa"s.
33081da177e4SLinus Torvalds	plpar		(%a2)			# load atc for ADDR1
33091da177e4SLinus Torvalds	plpar		(%a4)			# load atc for ADDR1+3
33101da177e4SLinus Torvalds
33111da177e4SLinus Torvalds# load the BUSCR values.
33121da177e4SLinus Torvalds	mov.l		&0x80000000,%a2		# assert LOCK* buscr value
33131da177e4SLinus Torvalds	mov.l		&0xa0000000,%a3		# assert LOCKE* buscr value
33141da177e4SLinus Torvalds	mov.l		&0x00000000,%a4		# buscr unlock value
33151da177e4SLinus Torvalds
33161da177e4SLinus Torvalds# there are three possible mis-aligned cases for longword cas. they
33171da177e4SLinus Torvalds# are separated because the final write which asserts LOCKE* must
33181da177e4SLinus Torvalds# be aligned.
33191da177e4SLinus Torvalds	mov.l		%a0,%d0			# is ADDR1 misaligned?
33201da177e4SLinus Torvalds	andi.b		&0x3,%d0
33211da177e4SLinus Torvalds	beq.b		CAS2L_ENTER		# no
33221da177e4SLinus Torvalds	cmpi.b		%d0,&0x2
33231da177e4SLinus Torvalds	beq.w		CAS2L2_ENTER		# yes; word misaligned
33241da177e4SLinus Torvalds	bra.w		CAS2L3_ENTER		# yes; byte misaligned
33251da177e4SLinus Torvalds
33261da177e4SLinus Torvalds#
33271da177e4SLinus Torvalds# D0 = dst operand 1 <-
33281da177e4SLinus Torvalds# D1 = dst operand 2 <-
33291da177e4SLinus Torvalds# D2 = cmp operand 1
33301da177e4SLinus Torvalds# D3 = cmp operand 2
33311da177e4SLinus Torvalds# D4 = update oper 1
33321da177e4SLinus Torvalds# D5 = update oper 2
33331da177e4SLinus Torvalds# D6 = old SFC/DFC
33341da177e4SLinus Torvalds# D7 = old SR
33351da177e4SLinus Torvalds# A0 = ADDR1
33361da177e4SLinus Torvalds# A1 = ADDR2
33371da177e4SLinus Torvalds# A2 = bus LOCK*  value
33381da177e4SLinus Torvalds# A3 = bus LOCKE* value
33391da177e4SLinus Torvalds# A4 = bus unlock value
33401da177e4SLinus Torvalds# A5 = xxxxxxxx
33411da177e4SLinus Torvalds#
33421da177e4SLinus Torvalds	align		0x10
33431da177e4SLinus TorvaldsCAS2L_START:
33441da177e4SLinus Torvalds	movc		%a2,%buscr		# assert LOCK*
33451da177e4SLinus Torvalds	movs.l		(%a1),%d1		# fetch Dest2[31:0]
33461da177e4SLinus Torvalds	movs.l		(%a0),%d0		# fetch Dest1[31:0]
33471da177e4SLinus Torvalds	bra.b		CAS2L_CONT
33481da177e4SLinus TorvaldsCAS2L_ENTER:
33491da177e4SLinus Torvalds	bra.b		~+16
33501da177e4SLinus Torvalds
33511da177e4SLinus TorvaldsCAS2L_CONT:
33521da177e4SLinus Torvalds	cmp.l		%d0,%d2			# Dest1 - Compare1
33531da177e4SLinus Torvalds	bne.b		CAS2L_NOUPDATE
33541da177e4SLinus Torvalds	cmp.l		%d1,%d3			# Dest2 - Compare2
33551da177e4SLinus Torvalds	bne.b		CAS2L_NOUPDATE
33561da177e4SLinus Torvalds	movs.l		%d5,(%a1)		# Update2[31:0] -> DEST2
33571da177e4SLinus Torvalds	bra.b		CAS2L_UPDATE
33581da177e4SLinus Torvalds	bra.b		~+16
33591da177e4SLinus Torvalds
33601da177e4SLinus TorvaldsCAS2L_UPDATE:
33611da177e4SLinus Torvalds	movc		%a3,%buscr		# assert LOCKE*
33621da177e4SLinus Torvalds	movs.l		%d4,(%a0)		# Update1[31:0] -> DEST1
33631da177e4SLinus Torvalds	movc		%a4,%buscr		# unlock the bus
33641da177e4SLinus Torvalds	bra.b		cas2l_update_done
33651da177e4SLinus Torvalds	bra.b		~+16
33661da177e4SLinus Torvalds
33671da177e4SLinus TorvaldsCAS2L_NOUPDATE:
33681da177e4SLinus Torvalds	movc		%a3,%buscr		# assert LOCKE*
33691da177e4SLinus Torvalds	movs.l		%d0,(%a0)		# Dest1[31:0] -> DEST1
33701da177e4SLinus Torvalds	movc		%a4,%buscr		# unlock the bus
33711da177e4SLinus Torvalds	bra.b		cas2l_noupdate_done
33721da177e4SLinus Torvalds	bra.b		~+16
33731da177e4SLinus Torvalds
33741da177e4SLinus TorvaldsCAS2L_FILLER:
33751da177e4SLinus Torvalds	nop
33761da177e4SLinus Torvalds	nop
33771da177e4SLinus Torvalds	nop
33781da177e4SLinus Torvalds	nop
33791da177e4SLinus Torvalds	nop
33801da177e4SLinus Torvalds	nop
33811da177e4SLinus Torvalds	nop
33821da177e4SLinus Torvalds	bra.b		CAS2L_START
33831da177e4SLinus Torvalds
33841da177e4SLinus Torvalds####
33851da177e4SLinus Torvalds
33861da177e4SLinus Torvalds#################################################################
33871da177e4SLinus Torvalds# THIS MUST BE THE STATE OF THE INTEGER REGISTER FILE UPON	#
33881da177e4SLinus Torvalds# ENTERING _isp_cas2().						#
33891da177e4SLinus Torvalds#								#
33901da177e4SLinus Torvalds# D0 = destination[31:0] operand 1				#
33911da177e4SLinus Torvalds# D1 = destination[31:0] operand 2				#
33921da177e4SLinus Torvalds# D2 = cmp[31:0] operand 1					#
33931da177e4SLinus Torvalds# D3 = cmp[31:0] operand 2					#
33941da177e4SLinus Torvalds# D4 = 'xxxxxx11 -> no reg update; 'xxxxxx00 -> update required	#
33951da177e4SLinus Torvalds# D5 = xxxxxxxx							#
33961da177e4SLinus Torvalds# D6 = xxxxxxxx							#
33971da177e4SLinus Torvalds# D7 = xxxxxxxx							#
33981da177e4SLinus Torvalds# A0 = xxxxxxxx							#
33991da177e4SLinus Torvalds# A1 = xxxxxxxx							#
34001da177e4SLinus Torvalds# A2 = xxxxxxxx							#
34011da177e4SLinus Torvalds# A3 = xxxxxxxx							#
34021da177e4SLinus Torvalds# A4 = xxxxxxxx							#
34031da177e4SLinus Torvalds# A5 = xxxxxxxx							#
34041da177e4SLinus Torvalds# A6 = frame pointer						#
34051da177e4SLinus Torvalds# A7 = stack pointer						#
34061da177e4SLinus Torvalds#################################################################
34071da177e4SLinus Torvalds
34081da177e4SLinus Torvaldscas2l_noupdate_done:
34091da177e4SLinus Torvalds
34101da177e4SLinus Torvalds# restore previous SFC/DFC value.
34111da177e4SLinus Torvalds	movc		%d6,%sfc		# restore old SFC
34121da177e4SLinus Torvalds	movc		%d6,%dfc		# restore old DFC
34131da177e4SLinus Torvalds
34141da177e4SLinus Torvalds# restore previous interrupt mask level.
34151da177e4SLinus Torvalds	mov.w		%d7,%sr			# restore old SR
34161da177e4SLinus Torvalds
34171da177e4SLinus Torvalds	sf		%d4			# indicate no update was done
34181da177e4SLinus Torvalds	bra.l		_isp_cas2_finish
34191da177e4SLinus Torvalds
34201da177e4SLinus Torvaldscas2l_update_done:
34211da177e4SLinus Torvalds
34221da177e4SLinus Torvalds# restore previous SFC/DFC value.
34231da177e4SLinus Torvalds	movc		%d6,%sfc		# restore old SFC
34241da177e4SLinus Torvalds	movc		%d6,%dfc		# restore old DFC
34251da177e4SLinus Torvalds
34261da177e4SLinus Torvalds# restore previous interrupt mask level.
34271da177e4SLinus Torvalds	mov.w		%d7,%sr			# restore old SR
34281da177e4SLinus Torvalds
34291da177e4SLinus Torvalds	st		%d4			# indicate update was done
34301da177e4SLinus Torvalds	bra.l		_isp_cas2_finish
34311da177e4SLinus Torvalds####
34321da177e4SLinus Torvalds
34331da177e4SLinus Torvalds	align		0x10
34341da177e4SLinus TorvaldsCAS2L2_START:
34351da177e4SLinus Torvalds	movc		%a2,%buscr		# assert LOCK*
34361da177e4SLinus Torvalds	movs.l		(%a1),%d1		# fetch Dest2[31:0]
34371da177e4SLinus Torvalds	movs.l		(%a0),%d0		# fetch Dest1[31:0]
34381da177e4SLinus Torvalds	bra.b		CAS2L2_CONT
34391da177e4SLinus TorvaldsCAS2L2_ENTER:
34401da177e4SLinus Torvalds	bra.b		~+16
34411da177e4SLinus Torvalds
34421da177e4SLinus TorvaldsCAS2L2_CONT:
34431da177e4SLinus Torvalds	cmp.l		%d0,%d2			# Dest1 - Compare1
34441da177e4SLinus Torvalds	bne.b		CAS2L2_NOUPDATE
34451da177e4SLinus Torvalds	cmp.l		%d1,%d3			# Dest2 - Compare2
34461da177e4SLinus Torvalds	bne.b		CAS2L2_NOUPDATE
34471da177e4SLinus Torvalds	movs.l		%d5,(%a1)		# Update2[31:0] -> Dest2
34481da177e4SLinus Torvalds	bra.b		CAS2L2_UPDATE
34491da177e4SLinus Torvalds	bra.b		~+16
34501da177e4SLinus Torvalds
34511da177e4SLinus TorvaldsCAS2L2_UPDATE:
34521da177e4SLinus Torvalds	swap		%d4			# get Update1[31:16]
34531da177e4SLinus Torvalds	movs.w		%d4,(%a0)+		# Update1[31:16] -> DEST1
34541da177e4SLinus Torvalds	movc		%a3,%buscr		# assert LOCKE*
34551da177e4SLinus Torvalds	swap		%d4			# get Update1[15:0]
34561da177e4SLinus Torvalds	bra.b		CAS2L2_UPDATE2
34571da177e4SLinus Torvalds	bra.b		~+16
34581da177e4SLinus Torvalds
34591da177e4SLinus TorvaldsCAS2L2_UPDATE2:
34601da177e4SLinus Torvalds	movs.w		%d4,(%a0)		# Update1[15:0] -> DEST1+0x2
34611da177e4SLinus Torvalds	movc		%a4,%buscr		# unlock the bus
34621da177e4SLinus Torvalds	bra.w		cas2l_update_done
34631da177e4SLinus Torvalds	nop
34641da177e4SLinus Torvalds	bra.b		~+16
34651da177e4SLinus Torvalds
34661da177e4SLinus TorvaldsCAS2L2_NOUPDATE:
34671da177e4SLinus Torvalds	swap		%d0			# get Dest1[31:16]
34681da177e4SLinus Torvalds	movs.w		%d0,(%a0)+		# Dest1[31:16] -> DEST1
34691da177e4SLinus Torvalds	movc		%a3,%buscr		# assert LOCKE*
34701da177e4SLinus Torvalds	swap		%d0			# get Dest1[15:0]
34711da177e4SLinus Torvalds	bra.b		CAS2L2_NOUPDATE2
34721da177e4SLinus Torvalds	bra.b		~+16
34731da177e4SLinus Torvalds
34741da177e4SLinus TorvaldsCAS2L2_NOUPDATE2:
34751da177e4SLinus Torvalds	movs.w		%d0,(%a0)		# Dest1[15:0] -> DEST1+0x2
34761da177e4SLinus Torvalds	movc		%a4,%buscr		# unlock the bus
34771da177e4SLinus Torvalds	bra.w		cas2l_noupdate_done
34781da177e4SLinus Torvalds	nop
34791da177e4SLinus Torvalds	bra.b		~+16
34801da177e4SLinus Torvalds
34811da177e4SLinus TorvaldsCAS2L2_FILLER:
34821da177e4SLinus Torvalds	nop
34831da177e4SLinus Torvalds	nop
34841da177e4SLinus Torvalds	nop
34851da177e4SLinus Torvalds	nop
34861da177e4SLinus Torvalds	nop
34871da177e4SLinus Torvalds	nop
34881da177e4SLinus Torvalds	nop
34891da177e4SLinus Torvalds	bra.b		CAS2L2_START
34901da177e4SLinus Torvalds
34911da177e4SLinus Torvalds#################################
34921da177e4SLinus Torvalds
34931da177e4SLinus Torvalds	align		0x10
34941da177e4SLinus TorvaldsCAS2L3_START:
34951da177e4SLinus Torvalds	movc		%a2,%buscr		# assert LOCK*
34961da177e4SLinus Torvalds	movs.l		(%a1),%d1		# fetch Dest2[31:0]
34971da177e4SLinus Torvalds	movs.l		(%a0),%d0		# fetch Dest1[31:0]
34981da177e4SLinus Torvalds	bra.b		CAS2L3_CONT
34991da177e4SLinus TorvaldsCAS2L3_ENTER:
35001da177e4SLinus Torvalds	bra.b		~+16
35011da177e4SLinus Torvalds
35021da177e4SLinus TorvaldsCAS2L3_CONT:
35031da177e4SLinus Torvalds	cmp.l		%d0,%d2			# Dest1 - Compare1
35041da177e4SLinus Torvalds	bne.b		CAS2L3_NOUPDATE
35051da177e4SLinus Torvalds	cmp.l		%d1,%d3			# Dest2 - Compare2
35061da177e4SLinus Torvalds	bne.b		CAS2L3_NOUPDATE
35071da177e4SLinus Torvalds	movs.l		%d5,(%a1)		# Update2[31:0] -> DEST2
35081da177e4SLinus Torvalds	bra.b		CAS2L3_UPDATE
35091da177e4SLinus Torvalds	bra.b		~+16
35101da177e4SLinus Torvalds
35111da177e4SLinus TorvaldsCAS2L3_UPDATE:
35121da177e4SLinus Torvalds	rol.l		&0x8,%d4		# get Update1[31:24]
35131da177e4SLinus Torvalds	movs.b		%d4,(%a0)+		# Update1[31:24] -> DEST1
35141da177e4SLinus Torvalds	swap		%d4			# get Update1[23:8]
35151da177e4SLinus Torvalds	movs.w		%d4,(%a0)+		# Update1[23:8] -> DEST1+0x1
35161da177e4SLinus Torvalds	bra.b		CAS2L3_UPDATE2
35171da177e4SLinus Torvalds	bra.b		~+16
35181da177e4SLinus Torvalds
35191da177e4SLinus TorvaldsCAS2L3_UPDATE2:
35201da177e4SLinus Torvalds	rol.l		&0x8,%d4		# get Update1[7:0]
35211da177e4SLinus Torvalds	movc		%a3,%buscr		# assert LOCKE*
35221da177e4SLinus Torvalds	movs.b		%d4,(%a0)		# Update1[7:0] -> DEST1+0x3
35231da177e4SLinus Torvalds	bra.b		CAS2L3_UPDATE3
35241da177e4SLinus Torvalds	nop
35251da177e4SLinus Torvalds	bra.b		~+16
35261da177e4SLinus Torvalds
35271da177e4SLinus TorvaldsCAS2L3_UPDATE3:
35281da177e4SLinus Torvalds	movc		%a4,%buscr		# unlock the bus
35291da177e4SLinus Torvalds	bra.w		cas2l_update_done
35301da177e4SLinus Torvalds	nop
35311da177e4SLinus Torvalds	nop
35321da177e4SLinus Torvalds	nop
35331da177e4SLinus Torvalds	bra.b		~+16
35341da177e4SLinus Torvalds
35351da177e4SLinus TorvaldsCAS2L3_NOUPDATE:
35361da177e4SLinus Torvalds	rol.l		&0x8,%d0		# get Dest1[31:24]
35371da177e4SLinus Torvalds	movs.b		%d0,(%a0)+		# Dest1[31:24] -> DEST1
35381da177e4SLinus Torvalds	swap		%d0			# get Dest1[23:8]
35391da177e4SLinus Torvalds	movs.w		%d0,(%a0)+		# Dest1[23:8] -> DEST1+0x1
35401da177e4SLinus Torvalds	bra.b		CAS2L3_NOUPDATE2
35411da177e4SLinus Torvalds	bra.b		~+16
35421da177e4SLinus Torvalds
35431da177e4SLinus TorvaldsCAS2L3_NOUPDATE2:
35441da177e4SLinus Torvalds	rol.l		&0x8,%d0		# get Dest1[7:0]
35451da177e4SLinus Torvalds	movc		%a3,%buscr		# assert LOCKE*
35461da177e4SLinus Torvalds	movs.b		%d0,(%a0)		# Update1[7:0] -> DEST1+0x3
35471da177e4SLinus Torvalds	bra.b		CAS2L3_NOUPDATE3
35481da177e4SLinus Torvalds	nop
35491da177e4SLinus Torvalds	bra.b		~+16
35501da177e4SLinus Torvalds
35511da177e4SLinus TorvaldsCAS2L3_NOUPDATE3:
35521da177e4SLinus Torvalds	movc		%a4,%buscr		# unlock the bus
35531da177e4SLinus Torvalds	bra.w		cas2l_noupdate_done
35541da177e4SLinus Torvalds	nop
35551da177e4SLinus Torvalds	nop
35561da177e4SLinus Torvalds	nop
35571da177e4SLinus Torvalds	bra.b		~+14
35581da177e4SLinus Torvalds
35591da177e4SLinus TorvaldsCAS2L3_FILLER:
35601da177e4SLinus Torvalds	nop
35611da177e4SLinus Torvalds	nop
35621da177e4SLinus Torvalds	nop
35631da177e4SLinus Torvalds	nop
35641da177e4SLinus Torvalds	nop
35651da177e4SLinus Torvalds	nop
35661da177e4SLinus Torvalds	bra.w		CAS2L3_START
35671da177e4SLinus Torvalds
35681da177e4SLinus Torvalds#############################################################
35691da177e4SLinus Torvalds#############################################################
35701da177e4SLinus Torvalds
35711da177e4SLinus Torvaldscas2w:
35721da177e4SLinus Torvalds	mov.l		%a0,%a2			# copy ADDR1
35731da177e4SLinus Torvalds	mov.l		%a1,%a3			# copy ADDR2
35741da177e4SLinus Torvalds	mov.l		%a0,%a4			# copy ADDR1
35751da177e4SLinus Torvalds	mov.l		%a1,%a5			# copy ADDR2
35761da177e4SLinus Torvalds
35771da177e4SLinus Torvalds	addq.l		&0x1,%a4		# ADDR1+1
35781da177e4SLinus Torvalds	addq.l		&0x1,%a5		# ADDR2+1
35791da177e4SLinus Torvalds	mov.l		%a2,%d1			# ADDR1
35801da177e4SLinus Torvalds
35811da177e4SLinus Torvalds# mask interrupt levels 0-6. save old mask value.
35821da177e4SLinus Torvalds	mov.w		%sr,%d7			# save current SR
35831da177e4SLinus Torvalds	ori.w		&0x0700,%sr		# inhibit interrupts
35841da177e4SLinus Torvalds
35851da177e4SLinus Torvalds# load the SFC and DFC with the appropriate mode.
35861da177e4SLinus Torvalds	movc		%sfc,%d6		# save old SFC/DFC
35871da177e4SLinus Torvalds	movc		%d0,%sfc		# store new SFC
35881da177e4SLinus Torvalds	movc		%d0,%dfc		# store new DFC
35891da177e4SLinus Torvalds
35901da177e4SLinus Torvalds# pre-load the operand ATC. no page faults should occur because
35911da177e4SLinus Torvalds# _real_lock_page() should have taken care of this.
35921da177e4SLinus Torvalds	plpaw		(%a2)			# load atc for ADDR1
35931da177e4SLinus Torvalds	plpaw		(%a4)			# load atc for ADDR1+1
35941da177e4SLinus Torvalds	plpaw		(%a3)			# load atc for ADDR2
35951da177e4SLinus Torvalds	plpaw		(%a5)			# load atc for ADDR2+1
35961da177e4SLinus Torvalds
35971da177e4SLinus Torvalds# push the operand cache lines from the cache if they exist.
35981da177e4SLinus Torvalds	cpushl		%dc,(%a2)		# push line for ADDR1
35991da177e4SLinus Torvalds	cpushl		%dc,(%a4)		# push line for ADDR1+1
36001da177e4SLinus Torvalds	cpushl		%dc,(%a3)		# push line for ADDR2
36011da177e4SLinus Torvalds	cpushl		%dc,(%a5)		# push line for ADDR2+1
36021da177e4SLinus Torvalds
36031da177e4SLinus Torvalds	mov.l		%d1,%a2			# ADDR1
36041da177e4SLinus Torvalds	addq.l		&0x3,%d1
36051da177e4SLinus Torvalds	mov.l		%d1,%a4			# ADDR1+3
36061da177e4SLinus Torvalds# if ADDR1 was ATC resident before the above "plpaw" and was executed
36071da177e4SLinus Torvalds# and it was the next entry scheduled for replacement and ADDR2
36081da177e4SLinus Torvalds# shares the same set, then the "plpaw" for ADDR2 can push the ADDR1
36091da177e4SLinus Torvalds# entries from the ATC. so, we do a second set of "plpa"s.
36101da177e4SLinus Torvalds	plpar		(%a2)			# load atc for ADDR1
36111da177e4SLinus Torvalds	plpar		(%a4)			# load atc for ADDR1+3
36121da177e4SLinus Torvalds
36131da177e4SLinus Torvalds# load the BUSCR values.
36141da177e4SLinus Torvalds	mov.l		&0x80000000,%a2		# assert LOCK* buscr value
36151da177e4SLinus Torvalds	mov.l		&0xa0000000,%a3		# assert LOCKE* buscr value
36161da177e4SLinus Torvalds	mov.l		&0x00000000,%a4		# buscr unlock value
36171da177e4SLinus Torvalds
36181da177e4SLinus Torvalds# there are two possible mis-aligned cases for word cas. they
36191da177e4SLinus Torvalds# are separated because the final write which asserts LOCKE* must
36201da177e4SLinus Torvalds# be aligned.
36211da177e4SLinus Torvalds	mov.l		%a0,%d0			# is ADDR1 misaligned?
36221da177e4SLinus Torvalds	btst		&0x0,%d0
36231da177e4SLinus Torvalds	bne.w		CAS2W2_ENTER		# yes
36241da177e4SLinus Torvalds	bra.b		CAS2W_ENTER		# no
36251da177e4SLinus Torvalds
36261da177e4SLinus Torvalds#
36271da177e4SLinus Torvalds# D0 = dst operand 1 <-
36281da177e4SLinus Torvalds# D1 = dst operand 2 <-
36291da177e4SLinus Torvalds# D2 = cmp operand 1
36301da177e4SLinus Torvalds# D3 = cmp operand 2
36311da177e4SLinus Torvalds# D4 = update oper 1
36321da177e4SLinus Torvalds# D5 = update oper 2
36331da177e4SLinus Torvalds# D6 = old SFC/DFC
36341da177e4SLinus Torvalds# D7 = old SR
36351da177e4SLinus Torvalds# A0 = ADDR1
36361da177e4SLinus Torvalds# A1 = ADDR2
36371da177e4SLinus Torvalds# A2 = bus LOCK*  value
36381da177e4SLinus Torvalds# A3 = bus LOCKE* value
36391da177e4SLinus Torvalds# A4 = bus unlock value
36401da177e4SLinus Torvalds# A5 = xxxxxxxx
36411da177e4SLinus Torvalds#
36421da177e4SLinus Torvalds	align		0x10
36431da177e4SLinus TorvaldsCAS2W_START:
36441da177e4SLinus Torvalds	movc		%a2,%buscr		# assert LOCK*
36451da177e4SLinus Torvalds	movs.w		(%a1),%d1		# fetch Dest2[15:0]
36461da177e4SLinus Torvalds	movs.w		(%a0),%d0		# fetch Dest1[15:0]
36471da177e4SLinus Torvalds	bra.b		CAS2W_CONT2
36481da177e4SLinus TorvaldsCAS2W_ENTER:
36491da177e4SLinus Torvalds	bra.b		~+16
36501da177e4SLinus Torvalds
36511da177e4SLinus TorvaldsCAS2W_CONT2:
36521da177e4SLinus Torvalds	cmp.w		%d0,%d2			# Dest1 - Compare1
36531da177e4SLinus Torvalds	bne.b		CAS2W_NOUPDATE
36541da177e4SLinus Torvalds	cmp.w		%d1,%d3			# Dest2 - Compare2
36551da177e4SLinus Torvalds	bne.b		CAS2W_NOUPDATE
36561da177e4SLinus Torvalds	movs.w		%d5,(%a1)		# Update2[15:0] -> DEST2
36571da177e4SLinus Torvalds	bra.b		CAS2W_UPDATE
36581da177e4SLinus Torvalds	bra.b		~+16
36591da177e4SLinus Torvalds
36601da177e4SLinus TorvaldsCAS2W_UPDATE:
36611da177e4SLinus Torvalds	movc		%a3,%buscr		# assert LOCKE*
36621da177e4SLinus Torvalds	movs.w		%d4,(%a0)		# Update1[15:0] -> DEST1
36631da177e4SLinus Torvalds	movc		%a4,%buscr		# unlock the bus
36641da177e4SLinus Torvalds	bra.b		cas2w_update_done
36651da177e4SLinus Torvalds	bra.b		~+16
36661da177e4SLinus Torvalds
36671da177e4SLinus TorvaldsCAS2W_NOUPDATE:
36681da177e4SLinus Torvalds	movc		%a3,%buscr		# assert LOCKE*
36691da177e4SLinus Torvalds	movs.w		%d0,(%a0)		# Dest1[15:0] -> DEST1
36701da177e4SLinus Torvalds	movc		%a4,%buscr		# unlock the bus
36711da177e4SLinus Torvalds	bra.b		cas2w_noupdate_done
36721da177e4SLinus Torvalds	bra.b		~+16
36731da177e4SLinus Torvalds
36741da177e4SLinus TorvaldsCAS2W_FILLER:
36751da177e4SLinus Torvalds	nop
36761da177e4SLinus Torvalds	nop
36771da177e4SLinus Torvalds	nop
36781da177e4SLinus Torvalds	nop
36791da177e4SLinus Torvalds	nop
36801da177e4SLinus Torvalds	nop
36811da177e4SLinus Torvalds	nop
36821da177e4SLinus Torvalds	bra.b		CAS2W_START
36831da177e4SLinus Torvalds
36841da177e4SLinus Torvalds####
36851da177e4SLinus Torvalds
36861da177e4SLinus Torvalds#################################################################
36871da177e4SLinus Torvalds# THIS MUST BE THE STATE OF THE INTEGER REGISTER FILE UPON	#
36881da177e4SLinus Torvalds# ENTERING _isp_cas2().						#
36891da177e4SLinus Torvalds#								#
36901da177e4SLinus Torvalds# D0 = destination[15:0] operand 1				#
36911da177e4SLinus Torvalds# D1 = destination[15:0] operand 2				#
36921da177e4SLinus Torvalds# D2 = cmp[15:0] operand 1					#
36931da177e4SLinus Torvalds# D3 = cmp[15:0] operand 2					#
36941da177e4SLinus Torvalds# D4 = 'xxxxxx11 -> no reg update; 'xxxxxx00 -> update required	#
36951da177e4SLinus Torvalds# D5 = xxxxxxxx							#
36961da177e4SLinus Torvalds# D6 = xxxxxxxx							#
36971da177e4SLinus Torvalds# D7 = xxxxxxxx							#
36981da177e4SLinus Torvalds# A0 = xxxxxxxx							#
36991da177e4SLinus Torvalds# A1 = xxxxxxxx							#
37001da177e4SLinus Torvalds# A2 = xxxxxxxx							#
37011da177e4SLinus Torvalds# A3 = xxxxxxxx							#
37021da177e4SLinus Torvalds# A4 = xxxxxxxx							#
37031da177e4SLinus Torvalds# A5 = xxxxxxxx							#
37041da177e4SLinus Torvalds# A6 = frame pointer						#
37051da177e4SLinus Torvalds# A7 = stack pointer						#
37061da177e4SLinus Torvalds#################################################################
37071da177e4SLinus Torvalds
37081da177e4SLinus Torvaldscas2w_noupdate_done:
37091da177e4SLinus Torvalds
37101da177e4SLinus Torvalds# restore previous SFC/DFC value.
37111da177e4SLinus Torvalds	movc		%d6,%sfc		# restore old SFC
37121da177e4SLinus Torvalds	movc		%d6,%dfc		# restore old DFC
37131da177e4SLinus Torvalds
37141da177e4SLinus Torvalds# restore previous interrupt mask level.
37151da177e4SLinus Torvalds	mov.w		%d7,%sr			# restore old SR
37161da177e4SLinus Torvalds
37171da177e4SLinus Torvalds	sf		%d4			# indicate no update was done
37181da177e4SLinus Torvalds	bra.l		_isp_cas2_finish
37191da177e4SLinus Torvalds
37201da177e4SLinus Torvaldscas2w_update_done:
37211da177e4SLinus Torvalds
37221da177e4SLinus Torvalds# restore previous SFC/DFC value.
37231da177e4SLinus Torvalds	movc		%d6,%sfc		# restore old SFC
37241da177e4SLinus Torvalds	movc		%d6,%dfc		# restore old DFC
37251da177e4SLinus Torvalds
37261da177e4SLinus Torvalds# restore previous interrupt mask level.
37271da177e4SLinus Torvalds	mov.w		%d7,%sr			# restore old SR
37281da177e4SLinus Torvalds
37291da177e4SLinus Torvalds	st		%d4			# indicate update was done
37301da177e4SLinus Torvalds	bra.l		_isp_cas2_finish
37311da177e4SLinus Torvalds####
37321da177e4SLinus Torvalds
37331da177e4SLinus Torvalds	align		0x10
37341da177e4SLinus TorvaldsCAS2W2_START:
37351da177e4SLinus Torvalds	movc		%a2,%buscr		# assert LOCK*
37361da177e4SLinus Torvalds	movs.w		(%a1),%d1		# fetch Dest2[15:0]
37371da177e4SLinus Torvalds	movs.w		(%a0),%d0		# fetch Dest1[15:0]
37381da177e4SLinus Torvalds	bra.b		CAS2W2_CONT2
37391da177e4SLinus TorvaldsCAS2W2_ENTER:
37401da177e4SLinus Torvalds	bra.b		~+16
37411da177e4SLinus Torvalds
37421da177e4SLinus TorvaldsCAS2W2_CONT2:
37431da177e4SLinus Torvalds	cmp.w		%d0,%d2			# Dest1 - Compare1
37441da177e4SLinus Torvalds	bne.b		CAS2W2_NOUPDATE
37451da177e4SLinus Torvalds	cmp.w		%d1,%d3			# Dest2 - Compare2
37461da177e4SLinus Torvalds	bne.b		CAS2W2_NOUPDATE
37471da177e4SLinus Torvalds	movs.w		%d5,(%a1)		# Update2[15:0] -> DEST2
37481da177e4SLinus Torvalds	bra.b		CAS2W2_UPDATE
37491da177e4SLinus Torvalds	bra.b		~+16
37501da177e4SLinus Torvalds
37511da177e4SLinus TorvaldsCAS2W2_UPDATE:
37521da177e4SLinus Torvalds	ror.l		&0x8,%d4		# get Update1[15:8]
37531da177e4SLinus Torvalds	movs.b		%d4,(%a0)+		# Update1[15:8] -> DEST1
37541da177e4SLinus Torvalds	movc		%a3,%buscr		# assert LOCKE*
37551da177e4SLinus Torvalds	rol.l		&0x8,%d4		# get Update1[7:0]
37561da177e4SLinus Torvalds	bra.b		CAS2W2_UPDATE2
37571da177e4SLinus Torvalds	bra.b		~+16
37581da177e4SLinus Torvalds
37591da177e4SLinus TorvaldsCAS2W2_UPDATE2:
37601da177e4SLinus Torvalds	movs.b		%d4,(%a0)		# Update1[7:0] -> DEST1+0x1
37611da177e4SLinus Torvalds	movc		%a4,%buscr		# unlock the bus
37621da177e4SLinus Torvalds	bra.w		cas2w_update_done
37631da177e4SLinus Torvalds	nop
37641da177e4SLinus Torvalds	bra.b		~+16
37651da177e4SLinus Torvalds
37661da177e4SLinus TorvaldsCAS2W2_NOUPDATE:
37671da177e4SLinus Torvalds	ror.l		&0x8,%d0		# get Dest1[15:8]
37681da177e4SLinus Torvalds	movs.b		%d0,(%a0)+		# Dest1[15:8] -> DEST1
37691da177e4SLinus Torvalds	movc		%a3,%buscr		# assert LOCKE*
37701da177e4SLinus Torvalds	rol.l		&0x8,%d0		# get Dest1[7:0]
37711da177e4SLinus Torvalds	bra.b		CAS2W2_NOUPDATE2
37721da177e4SLinus Torvalds	bra.b		~+16
37731da177e4SLinus Torvalds
37741da177e4SLinus TorvaldsCAS2W2_NOUPDATE2:
37751da177e4SLinus Torvalds	movs.b		%d0,(%a0)		# Dest1[7:0] -> DEST1+0x1
37761da177e4SLinus Torvalds	movc		%a4,%buscr		# unlock the bus
37771da177e4SLinus Torvalds	bra.w		cas2w_noupdate_done
37781da177e4SLinus Torvalds	nop
37791da177e4SLinus Torvalds	bra.b		~+16
37801da177e4SLinus Torvalds
37811da177e4SLinus TorvaldsCAS2W2_FILLER:
37821da177e4SLinus Torvalds	nop
37831da177e4SLinus Torvalds	nop
37841da177e4SLinus Torvalds	nop
37851da177e4SLinus Torvalds	nop
37861da177e4SLinus Torvalds	nop
37871da177e4SLinus Torvalds	nop
37881da177e4SLinus Torvalds	nop
37891da177e4SLinus Torvalds	bra.b		CAS2W2_START
37901da177e4SLinus Torvalds
37911da177e4SLinus Torvalds#       ######      ##      ######
37921da177e4SLinus Torvalds#       #	   #  #     #
37931da177e4SLinus Torvalds#	#	  ######    ######
37941da177e4SLinus Torvalds#	#	  #    #         #
37951da177e4SLinus Torvalds#       ######    #    #    ######
37961da177e4SLinus Torvalds
37971da177e4SLinus Torvalds#########################################################################
37981da177e4SLinus Torvalds# XDEF ****************************************************************	#
37991da177e4SLinus Torvalds#	_isp_cas(): "core" emulation code for the cas instruction	#
38001da177e4SLinus Torvalds#									#
38011da177e4SLinus Torvalds# XREF ****************************************************************	#
38021da177e4SLinus Torvalds#	_isp_cas_finish() - only exit point for this emulation code;	#
38031da177e4SLinus Torvalds#			    do clean-up					#
38041da177e4SLinus Torvalds#									#
38051da177e4SLinus Torvalds# INPUT ***************************************************************	#
38061da177e4SLinus Torvalds#	*see entry chart below*						#
38071da177e4SLinus Torvalds#									#
38081da177e4SLinus Torvalds# OUTPUT **************************************************************	#
38091da177e4SLinus Torvalds#	*see exit chart below*						#
38101da177e4SLinus Torvalds#									#
38111da177e4SLinus Torvalds# ALGORITHM ***********************************************************	#
38121da177e4SLinus Torvalds#	(1) Make several copies of the effective address.		#
38131da177e4SLinus Torvalds#	(2) Save current SR; Then mask off all maskable interrupts.	#
38141da177e4SLinus Torvalds#	(3) Save current DFC/SFC (ASSUMED TO BE EQUAL!!!); Then set	#
38151da177e4SLinus Torvalds#	    SFC/DFC according to whether exception occurred in user or	#
38161da177e4SLinus Torvalds#	    supervisor mode.						#
38174e0385ddSMasahiro Yamada#	(4) Use "plpaw" instruction to pre-load ATC with effective	#
38181da177e4SLinus Torvalds#	    address page(s). THIS SHOULD NOT FAULT!!! The relevant	#
38191da177e4SLinus Torvalds#	    page(s) should have been made resident prior to entering	#
38201da177e4SLinus Torvalds#	    this routine.						#
38211da177e4SLinus Torvalds#	(5) Push the operand lines from the cache w/ "cpushl".		#
38221da177e4SLinus Torvalds#	    In the 68040, this was done within the locked region. In	#
38231da177e4SLinus Torvalds#	    the 68060, it is done outside of the locked region.		#
38241da177e4SLinus Torvalds#	(6) Pre-fetch the core emulation instructions by executing one	#
38251da177e4SLinus Torvalds#	    branch within each physical line (16 bytes) of the code	#
38261da177e4SLinus Torvalds#	    before actually executing the code.				#
38271da177e4SLinus Torvalds#	(7) Load the BUSCR with the bus lock value.			#
38281da177e4SLinus Torvalds#	(8) Fetch the source operand.					#
38291da177e4SLinus Torvalds#	(9) Do the compare. If equal, go to step (12).			#
38301da177e4SLinus Torvalds#	(10)Unequal. No update occurs. But, we do write the DST op back	#
38311da177e4SLinus Torvalds#	    to itself (as w/ the '040) so we can gracefully unlock	#
38321da177e4SLinus Torvalds#	    the bus (and assert LOCKE*) using BUSCR and the final move.	#
38331da177e4SLinus Torvalds#	(11)Exit.							#
38341da177e4SLinus Torvalds#	(12)Write update operand to the DST location. Use BUSCR to	#
38351da177e4SLinus Torvalds#	    assert LOCKE* for the final write operation.		#
38361da177e4SLinus Torvalds#	(13)Exit.							#
38371da177e4SLinus Torvalds#									#
38381da177e4SLinus Torvalds#	The algorithm is actually implemented slightly differently	#
38391da177e4SLinus Torvalds# depending on the size of the operation and the misalignment of the	#
38401da177e4SLinus Torvalds# operand. A misaligned operand must be written in aligned chunks or	#
38411da177e4SLinus Torvalds# else the BUSCR register control gets confused.			#
38421da177e4SLinus Torvalds#									#
38431da177e4SLinus Torvalds#########################################################################
38441da177e4SLinus Torvalds
38451da177e4SLinus Torvalds#########################################################
38461da177e4SLinus Torvalds# THIS IS THE STATE OF THE INTEGER REGISTER FILE UPON	#
38471da177e4SLinus Torvalds# ENTERING _isp_cas().					#
38481da177e4SLinus Torvalds#							#
38491da177e4SLinus Torvalds# D0 = xxxxxxxx						#
38501da177e4SLinus Torvalds# D1 = xxxxxxxx						#
38511da177e4SLinus Torvalds# D2 = update operand					#
38521da177e4SLinus Torvalds# D3 = xxxxxxxx						#
38531da177e4SLinus Torvalds# D4 = compare operand					#
38541da177e4SLinus Torvalds# D5 = xxxxxxxx						#
38551da177e4SLinus Torvalds# D6 = supervisor ('xxxxxxff) or user mode ('xxxxxx00)	#
38561da177e4SLinus Torvalds# D7 = longword ('xxxxxxff) or word size ('xxxxxx00)	#
38571da177e4SLinus Torvalds# A0 = ADDR						#
38581da177e4SLinus Torvalds# A1 = xxxxxxxx						#
38591da177e4SLinus Torvalds# A2 = xxxxxxxx						#
38601da177e4SLinus Torvalds# A3 = xxxxxxxx						#
38611da177e4SLinus Torvalds# A4 = xxxxxxxx						#
38621da177e4SLinus Torvalds# A5 = xxxxxxxx						#
38631da177e4SLinus Torvalds# A6 = frame pointer					#
38641da177e4SLinus Torvalds# A7 = stack pointer					#
38651da177e4SLinus Torvalds#########################################################
38661da177e4SLinus Torvalds
38671da177e4SLinus Torvalds	global		_isp_cas
38681da177e4SLinus Torvalds_isp_cas:
38691da177e4SLinus Torvalds	tst.b		%d6			# user or supervisor mode?
38701da177e4SLinus Torvalds	bne.b		cas_super		# supervisor
38711da177e4SLinus Torvaldscas_user:
38721da177e4SLinus Torvalds	movq.l		&0x1,%d0		# load user data fc
38731da177e4SLinus Torvalds	bra.b		cas_cont
38741da177e4SLinus Torvaldscas_super:
38751da177e4SLinus Torvalds	movq.l		&0x5,%d0		# load supervisor data fc
38761da177e4SLinus Torvalds
38771da177e4SLinus Torvaldscas_cont:
38781da177e4SLinus Torvalds	tst.b		%d7			# word or longword?
38791da177e4SLinus Torvalds	bne.w		casl			# longword
38801da177e4SLinus Torvalds
38811da177e4SLinus Torvalds####
38821da177e4SLinus Torvaldscasw:
38831da177e4SLinus Torvalds	mov.l		%a0,%a1			# make copy for plpaw1
38841da177e4SLinus Torvalds	mov.l		%a0,%a2			# make copy for plpaw2
38851da177e4SLinus Torvalds	addq.l		&0x1,%a2		# plpaw2 points to end of word
38861da177e4SLinus Torvalds
38871da177e4SLinus Torvalds	mov.l		%d2,%d3			# d3 = update[7:0]
38881da177e4SLinus Torvalds	lsr.w		&0x8,%d2		# d2 = update[15:8]
38891da177e4SLinus Torvalds
38901da177e4SLinus Torvalds# mask interrupt levels 0-6. save old mask value.
38911da177e4SLinus Torvalds	mov.w		%sr,%d7			# save current SR
38921da177e4SLinus Torvalds	ori.w		&0x0700,%sr		# inhibit interrupts
38931da177e4SLinus Torvalds
38941da177e4SLinus Torvalds# load the SFC and DFC with the appropriate mode.
38951da177e4SLinus Torvalds	movc		%sfc,%d6		# save old SFC/DFC
38961da177e4SLinus Torvalds	movc		%d0,%sfc		# load new sfc
38971da177e4SLinus Torvalds	movc		%d0,%dfc		# load new dfc
38981da177e4SLinus Torvalds
38991da177e4SLinus Torvalds# pre-load the operand ATC. no page faults should occur here because
39001da177e4SLinus Torvalds# _real_lock_page() should have taken care of this.
39011da177e4SLinus Torvalds	plpaw		(%a1)			# load atc for ADDR
39021da177e4SLinus Torvalds	plpaw		(%a2)			# load atc for ADDR+1
39031da177e4SLinus Torvalds
39041da177e4SLinus Torvalds# push the operand lines from the cache if they exist.
39051da177e4SLinus Torvalds	cpushl		%dc,(%a1)		# push dirty data
39061da177e4SLinus Torvalds	cpushl		%dc,(%a2)		# push dirty data
39071da177e4SLinus Torvalds
39081da177e4SLinus Torvalds# load the BUSCR values.
39091da177e4SLinus Torvalds	mov.l		&0x80000000,%a1		# assert LOCK* buscr value
39101da177e4SLinus Torvalds	mov.l		&0xa0000000,%a2		# assert LOCKE* buscr value
39111da177e4SLinus Torvalds	mov.l		&0x00000000,%a3		# buscr unlock value
39121da177e4SLinus Torvalds
39131da177e4SLinus Torvalds# pre-load the instruction cache for the following algorithm.
39141da177e4SLinus Torvalds# this will minimize the number of cycles that LOCK* will be asserted.
39151da177e4SLinus Torvalds	bra.b		CASW_ENTER		# start pre-loading icache
39161da177e4SLinus Torvalds
39171da177e4SLinus Torvalds#
39181da177e4SLinus Torvalds# D0 = dst operand <-
39191da177e4SLinus Torvalds# D1 = update[15:8] operand
39201da177e4SLinus Torvalds# D2 = update[7:0]  operand
39211da177e4SLinus Torvalds# D3 = xxxxxxxx
39221da177e4SLinus Torvalds# D4 = compare[15:0] operand
39231da177e4SLinus Torvalds# D5 = xxxxxxxx
39241da177e4SLinus Torvalds# D6 = old SFC/DFC
39251da177e4SLinus Torvalds# D7 = old SR
39261da177e4SLinus Torvalds# A0 = ADDR
39271da177e4SLinus Torvalds# A1 = bus LOCK*  value
39281da177e4SLinus Torvalds# A2 = bus LOCKE* value
39291da177e4SLinus Torvalds# A3 = bus unlock value
39301da177e4SLinus Torvalds# A4 = xxxxxxxx
39311da177e4SLinus Torvalds# A5 = xxxxxxxx
39321da177e4SLinus Torvalds#
39331da177e4SLinus Torvalds	align		0x10
39341da177e4SLinus TorvaldsCASW_START:
39351da177e4SLinus Torvalds	movc		%a1,%buscr		# assert LOCK*
39361da177e4SLinus Torvalds	movs.w		(%a0),%d0		# fetch Dest[15:0]
39371da177e4SLinus Torvalds	cmp.w		%d0,%d4			# Dest - Compare
39381da177e4SLinus Torvalds	bne.b		CASW_NOUPDATE
39391da177e4SLinus Torvalds	bra.b		CASW_UPDATE
39401da177e4SLinus TorvaldsCASW_ENTER:
39411da177e4SLinus Torvalds	bra.b		~+16
39421da177e4SLinus Torvalds
39431da177e4SLinus TorvaldsCASW_UPDATE:
39441da177e4SLinus Torvalds	movs.b		%d2,(%a0)+		# Update[15:8] -> DEST
39451da177e4SLinus Torvalds	movc		%a2,%buscr		# assert LOCKE*
39461da177e4SLinus Torvalds	movs.b		%d3,(%a0)		# Update[7:0] -> DEST+0x1
39471da177e4SLinus Torvalds	bra.b		CASW_UPDATE2
39481da177e4SLinus Torvalds	bra.b		~+16
39491da177e4SLinus Torvalds
39501da177e4SLinus TorvaldsCASW_UPDATE2:
39511da177e4SLinus Torvalds	movc		%a3,%buscr		# unlock the bus
39521da177e4SLinus Torvalds	bra.b		casw_update_done
39531da177e4SLinus Torvalds	nop
39541da177e4SLinus Torvalds	nop
39551da177e4SLinus Torvalds	nop
39561da177e4SLinus Torvalds	nop
39571da177e4SLinus Torvalds	bra.b		~+16
39581da177e4SLinus Torvalds
39591da177e4SLinus TorvaldsCASW_NOUPDATE:
39601da177e4SLinus Torvalds	ror.l		&0x8,%d0		# get Dest[15:8]
39611da177e4SLinus Torvalds	movs.b		%d0,(%a0)+		# Dest[15:8] -> DEST
39621da177e4SLinus Torvalds	movc		%a2,%buscr		# assert LOCKE*
39631da177e4SLinus Torvalds	rol.l		&0x8,%d0		# get Dest[7:0]
39641da177e4SLinus Torvalds	bra.b		CASW_NOUPDATE2
39651da177e4SLinus Torvalds	bra.b		~+16
39661da177e4SLinus Torvalds
39671da177e4SLinus TorvaldsCASW_NOUPDATE2:
39681da177e4SLinus Torvalds	movs.b		%d0,(%a0)		# Dest[7:0] -> DEST+0x1
39691da177e4SLinus Torvalds	movc		%a3,%buscr		# unlock the bus
39701da177e4SLinus Torvalds	bra.b		casw_noupdate_done
39711da177e4SLinus Torvalds	nop
39721da177e4SLinus Torvalds	nop
39731da177e4SLinus Torvalds	bra.b		~+16
39741da177e4SLinus Torvalds
39751da177e4SLinus TorvaldsCASW_FILLER:
39761da177e4SLinus Torvalds	nop
39771da177e4SLinus Torvalds	nop
39781da177e4SLinus Torvalds	nop
39791da177e4SLinus Torvalds	nop
39801da177e4SLinus Torvalds	nop
39811da177e4SLinus Torvalds	nop
39821da177e4SLinus Torvalds	nop
39831da177e4SLinus Torvalds	bra.b		CASW_START
39841da177e4SLinus Torvalds
39851da177e4SLinus Torvalds#################################################################
39861da177e4SLinus Torvalds# THIS MUST BE THE STATE OF THE INTEGER REGISTER FILE UPON	#
39871da177e4SLinus Torvalds# CALLING _isp_cas_finish().					#
39881da177e4SLinus Torvalds#								#
39891da177e4SLinus Torvalds# D0 = destination[15:0] operand				#
39901da177e4SLinus Torvalds# D1 = 'xxxxxx11 -> no reg update; 'xxxxxx00 -> update required	#
39911da177e4SLinus Torvalds# D2 = xxxxxxxx							#
39921da177e4SLinus Torvalds# D3 = xxxxxxxx							#
39931da177e4SLinus Torvalds# D4 = compare[15:0] operand					#
39941da177e4SLinus Torvalds# D5 = xxxxxxxx							#
39951da177e4SLinus Torvalds# D6 = xxxxxxxx							#
39961da177e4SLinus Torvalds# D7 = xxxxxxxx							#
39971da177e4SLinus Torvalds# A0 = xxxxxxxx							#
39981da177e4SLinus Torvalds# A1 = xxxxxxxx							#
39991da177e4SLinus Torvalds# A2 = xxxxxxxx							#
40001da177e4SLinus Torvalds# A3 = xxxxxxxx							#
40011da177e4SLinus Torvalds# A4 = xxxxxxxx							#
40021da177e4SLinus Torvalds# A5 = xxxxxxxx							#
40031da177e4SLinus Torvalds# A6 = frame pointer						#
40041da177e4SLinus Torvalds# A7 = stack pointer						#
40051da177e4SLinus Torvalds#################################################################
40061da177e4SLinus Torvalds
40071da177e4SLinus Torvaldscasw_noupdate_done:
40081da177e4SLinus Torvalds
40091da177e4SLinus Torvalds# restore previous SFC/DFC value.
40101da177e4SLinus Torvalds	movc		%d6,%sfc		# restore old SFC
40111da177e4SLinus Torvalds	movc		%d6,%dfc		# restore old DFC
40121da177e4SLinus Torvalds
40131da177e4SLinus Torvalds# restore previous interrupt mask level.
40141da177e4SLinus Torvalds	mov.w		%d7,%sr			# restore old SR
40151da177e4SLinus Torvalds
40161da177e4SLinus Torvalds	sf		%d1			# indicate no update was done
40171da177e4SLinus Torvalds	bra.l		_isp_cas_finish
40181da177e4SLinus Torvalds
40191da177e4SLinus Torvaldscasw_update_done:
40201da177e4SLinus Torvalds
40211da177e4SLinus Torvalds# restore previous SFC/DFC value.
40221da177e4SLinus Torvalds	movc		%d6,%sfc		# restore old SFC
40231da177e4SLinus Torvalds	movc		%d6,%dfc		# restore old DFC
40241da177e4SLinus Torvalds
40251da177e4SLinus Torvalds# restore previous interrupt mask level.
40261da177e4SLinus Torvalds	mov.w		%d7,%sr			# restore old SR
40271da177e4SLinus Torvalds
40281da177e4SLinus Torvalds	st		%d1			# indicate update was done
40291da177e4SLinus Torvalds	bra.l		_isp_cas_finish
40301da177e4SLinus Torvalds
40311da177e4SLinus Torvalds################
40321da177e4SLinus Torvalds
40331da177e4SLinus Torvalds# there are two possible mis-aligned cases for longword cas. they
40341da177e4SLinus Torvalds# are separated because the final write which asserts LOCKE* must
40351da177e4SLinus Torvalds# be an aligned write.
40361da177e4SLinus Torvaldscasl:
40371da177e4SLinus Torvalds	mov.l		%a0,%a1			# make copy for plpaw1
40381da177e4SLinus Torvalds	mov.l		%a0,%a2			# make copy for plpaw2
40391da177e4SLinus Torvalds	addq.l		&0x3,%a2		# plpaw2 points to end of longword
40401da177e4SLinus Torvalds
40411da177e4SLinus Torvalds	mov.l		%a0,%d1			# byte or word misaligned?
40421da177e4SLinus Torvalds	btst		&0x0,%d1
40431da177e4SLinus Torvalds	bne.w		casl2			# byte misaligned
40441da177e4SLinus Torvalds
40451da177e4SLinus Torvalds	mov.l		%d2,%d3			# d3 = update[15:0]
40461da177e4SLinus Torvalds	swap		%d2			# d2 = update[31:16]
40471da177e4SLinus Torvalds
40481da177e4SLinus Torvalds# mask interrupts levels 0-6. save old mask value.
40491da177e4SLinus Torvalds	mov.w		%sr,%d7			# save current SR
40501da177e4SLinus Torvalds	ori.w		&0x0700,%sr		# inhibit interrupts
40511da177e4SLinus Torvalds
40521da177e4SLinus Torvalds# load the SFC and DFC with the appropriate mode.
40531da177e4SLinus Torvalds	movc		%sfc,%d6		# save old SFC/DFC
40541da177e4SLinus Torvalds	movc		%d0,%sfc		# load new sfc
40551da177e4SLinus Torvalds	movc		%d0,%dfc		# load new dfc
40561da177e4SLinus Torvalds
40571da177e4SLinus Torvalds# pre-load the operand ATC. no page faults should occur here because
40581da177e4SLinus Torvalds# _real_lock_page() should have taken care of this.
40591da177e4SLinus Torvalds	plpaw		(%a1)			# load atc for ADDR
40601da177e4SLinus Torvalds	plpaw		(%a2)			# load atc for ADDR+3
40611da177e4SLinus Torvalds
40621da177e4SLinus Torvalds# push the operand lines from the cache if they exist.
40631da177e4SLinus Torvalds	cpushl		%dc,(%a1)		# push dirty data
40641da177e4SLinus Torvalds	cpushl		%dc,(%a2)		# push dirty data
40651da177e4SLinus Torvalds
40661da177e4SLinus Torvalds# load the BUSCR values.
40671da177e4SLinus Torvalds	mov.l		&0x80000000,%a1		# assert LOCK* buscr value
40681da177e4SLinus Torvalds	mov.l		&0xa0000000,%a2		# assert LOCKE* buscr value
40691da177e4SLinus Torvalds	mov.l		&0x00000000,%a3		# buscr unlock value
40701da177e4SLinus Torvalds
40711da177e4SLinus Torvalds	bra.b		CASL_ENTER		# start pre-loading icache
40721da177e4SLinus Torvalds
40731da177e4SLinus Torvalds#
40741da177e4SLinus Torvalds# D0 = dst operand <-
40751da177e4SLinus Torvalds# D1 = xxxxxxxx
40761da177e4SLinus Torvalds# D2 = update[31:16] operand
40771da177e4SLinus Torvalds# D3 = update[15:0]  operand
40781da177e4SLinus Torvalds# D4 = compare[31:0] operand
40791da177e4SLinus Torvalds# D5 = xxxxxxxx
40801da177e4SLinus Torvalds# D6 = old SFC/DFC
40811da177e4SLinus Torvalds# D7 = old SR
40821da177e4SLinus Torvalds# A0 = ADDR
40831da177e4SLinus Torvalds# A1 = bus LOCK*  value
40841da177e4SLinus Torvalds# A2 = bus LOCKE* value
40851da177e4SLinus Torvalds# A3 = bus unlock value
40861da177e4SLinus Torvalds# A4 = xxxxxxxx
40871da177e4SLinus Torvalds# A5 = xxxxxxxx
40881da177e4SLinus Torvalds#
40891da177e4SLinus Torvalds	align		0x10
40901da177e4SLinus TorvaldsCASL_START:
40911da177e4SLinus Torvalds	movc		%a1,%buscr		# assert LOCK*
40921da177e4SLinus Torvalds	movs.l		(%a0),%d0		# fetch Dest[31:0]
40931da177e4SLinus Torvalds	cmp.l		%d0,%d4			# Dest - Compare
40941da177e4SLinus Torvalds	bne.b		CASL_NOUPDATE
40951da177e4SLinus Torvalds	bra.b		CASL_UPDATE
40961da177e4SLinus TorvaldsCASL_ENTER:
40971da177e4SLinus Torvalds	bra.b		~+16
40981da177e4SLinus Torvalds
40991da177e4SLinus TorvaldsCASL_UPDATE:
41001da177e4SLinus Torvalds	movs.w		%d2,(%a0)+		# Update[31:16] -> DEST
41011da177e4SLinus Torvalds	movc		%a2,%buscr		# assert LOCKE*
41021da177e4SLinus Torvalds	movs.w		%d3,(%a0)		# Update[15:0] -> DEST+0x2
41031da177e4SLinus Torvalds	bra.b		CASL_UPDATE2
41041da177e4SLinus Torvalds	bra.b		~+16
41051da177e4SLinus Torvalds
41061da177e4SLinus TorvaldsCASL_UPDATE2:
41071da177e4SLinus Torvalds	movc		%a3,%buscr		# unlock the bus
41081da177e4SLinus Torvalds	bra.b		casl_update_done
41091da177e4SLinus Torvalds	nop
41101da177e4SLinus Torvalds	nop
41111da177e4SLinus Torvalds	nop
41121da177e4SLinus Torvalds	nop
41131da177e4SLinus Torvalds	bra.b		~+16
41141da177e4SLinus Torvalds
41151da177e4SLinus TorvaldsCASL_NOUPDATE:
41161da177e4SLinus Torvalds	swap		%d0			# get Dest[31:16]
41171da177e4SLinus Torvalds	movs.w		%d0,(%a0)+		# Dest[31:16] -> DEST
41181da177e4SLinus Torvalds	swap		%d0			# get Dest[15:0]
41191da177e4SLinus Torvalds	movc		%a2,%buscr		# assert LOCKE*
41201da177e4SLinus Torvalds	bra.b		CASL_NOUPDATE2
41211da177e4SLinus Torvalds	bra.b		~+16
41221da177e4SLinus Torvalds
41231da177e4SLinus TorvaldsCASL_NOUPDATE2:
41241da177e4SLinus Torvalds	movs.w		%d0,(%a0)		# Dest[15:0] -> DEST+0x2
41251da177e4SLinus Torvalds	movc		%a3,%buscr		# unlock the bus
41261da177e4SLinus Torvalds	bra.b		casl_noupdate_done
41271da177e4SLinus Torvalds	nop
41281da177e4SLinus Torvalds	nop
41291da177e4SLinus Torvalds	bra.b		~+16
41301da177e4SLinus Torvalds
41311da177e4SLinus TorvaldsCASL_FILLER:
41321da177e4SLinus Torvalds	nop
41331da177e4SLinus Torvalds	nop
41341da177e4SLinus Torvalds	nop
41351da177e4SLinus Torvalds	nop
41361da177e4SLinus Torvalds	nop
41371da177e4SLinus Torvalds	nop
41381da177e4SLinus Torvalds	nop
41391da177e4SLinus Torvalds	bra.b		CASL_START
41401da177e4SLinus Torvalds
41411da177e4SLinus Torvalds#################################################################
41421da177e4SLinus Torvalds# THIS MUST BE THE STATE OF THE INTEGER REGISTER FILE UPON	#
41431da177e4SLinus Torvalds# CALLING _isp_cas_finish().					#
41441da177e4SLinus Torvalds#								#
41451da177e4SLinus Torvalds# D0 = destination[31:0] operand				#
41461da177e4SLinus Torvalds# D1 = 'xxxxxx11 -> no reg update; 'xxxxxx00 -> update required	#
41471da177e4SLinus Torvalds# D2 = xxxxxxxx							#
41481da177e4SLinus Torvalds# D3 = xxxxxxxx							#
41491da177e4SLinus Torvalds# D4 = compare[31:0] operand					#
41501da177e4SLinus Torvalds# D5 = xxxxxxxx							#
41511da177e4SLinus Torvalds# D6 = xxxxxxxx							#
41521da177e4SLinus Torvalds# D7 = xxxxxxxx							#
41531da177e4SLinus Torvalds# A0 = xxxxxxxx							#
41541da177e4SLinus Torvalds# A1 = xxxxxxxx							#
41551da177e4SLinus Torvalds# A2 = xxxxxxxx							#
41561da177e4SLinus Torvalds# A3 = xxxxxxxx							#
41571da177e4SLinus Torvalds# A4 = xxxxxxxx							#
41581da177e4SLinus Torvalds# A5 = xxxxxxxx							#
41591da177e4SLinus Torvalds# A6 = frame pointer						#
41601da177e4SLinus Torvalds# A7 = stack pointer						#
41611da177e4SLinus Torvalds#################################################################
41621da177e4SLinus Torvalds
41631da177e4SLinus Torvaldscasl_noupdate_done:
41641da177e4SLinus Torvalds
41651da177e4SLinus Torvalds# restore previous SFC/DFC value.
41661da177e4SLinus Torvalds	movc		%d6,%sfc		# restore old SFC
41671da177e4SLinus Torvalds	movc		%d6,%dfc		# restore old DFC
41681da177e4SLinus Torvalds
41691da177e4SLinus Torvalds# restore previous interrupt mask level.
41701da177e4SLinus Torvalds	mov.w		%d7,%sr			# restore old SR
41711da177e4SLinus Torvalds
41721da177e4SLinus Torvalds	sf		%d1			# indicate no update was done
41731da177e4SLinus Torvalds	bra.l		_isp_cas_finish
41741da177e4SLinus Torvalds
41751da177e4SLinus Torvaldscasl_update_done:
41761da177e4SLinus Torvalds
41771da177e4SLinus Torvalds# restore previous SFC/DFC value.
41781da177e4SLinus Torvalds	movc		%d6,%sfc		# restore old SFC
41791da177e4SLinus Torvalds	movc		%d6,%dfc		# restore old DFC
41801da177e4SLinus Torvalds
41811da177e4SLinus Torvalds# restore previous interrupts mask level.
41821da177e4SLinus Torvalds	mov.w		%d7,%sr			# restore old SR
41831da177e4SLinus Torvalds
41841da177e4SLinus Torvalds	st		%d1			# indicate update was done
41851da177e4SLinus Torvalds	bra.l		_isp_cas_finish
41861da177e4SLinus Torvalds
41871da177e4SLinus Torvalds#######################################
41881da177e4SLinus Torvaldscasl2:
41891da177e4SLinus Torvalds	mov.l		%d2,%d5			# d5 = Update[7:0]
41901da177e4SLinus Torvalds	lsr.l		&0x8,%d2
41911da177e4SLinus Torvalds	mov.l		%d2,%d3			# d3 = Update[23:8]
41921da177e4SLinus Torvalds	swap		%d2			# d2 = Update[31:24]
41931da177e4SLinus Torvalds
41941da177e4SLinus Torvalds# mask interrupts levels 0-6. save old mask value.
41951da177e4SLinus Torvalds	mov.w		%sr,%d7			# save current SR
41961da177e4SLinus Torvalds	ori.w		&0x0700,%sr		# inhibit interrupts
41971da177e4SLinus Torvalds
41981da177e4SLinus Torvalds# load the SFC and DFC with the appropriate mode.
41991da177e4SLinus Torvalds	movc		%sfc,%d6		# save old SFC/DFC
42001da177e4SLinus Torvalds	movc		%d0,%sfc		# load new sfc
42011da177e4SLinus Torvalds	movc		%d0,%dfc		# load new dfc
42021da177e4SLinus Torvalds
42031da177e4SLinus Torvalds# pre-load the operand ATC. no page faults should occur here because
42041da177e4SLinus Torvalds# _real_lock_page() should have taken care of this already.
42051da177e4SLinus Torvalds	plpaw		(%a1)			# load atc for ADDR
42061da177e4SLinus Torvalds	plpaw		(%a2)			# load atc for ADDR+3
42071da177e4SLinus Torvalds
42081da177e4SLinus Torvalds# puch the operand lines from the cache if they exist.
42091da177e4SLinus Torvalds	cpushl		%dc,(%a1)		# push dirty data
42101da177e4SLinus Torvalds	cpushl		%dc,(%a2)		# push dirty data
42111da177e4SLinus Torvalds
42121da177e4SLinus Torvalds# load the BUSCR values.
42131da177e4SLinus Torvalds	mov.l		&0x80000000,%a1		# assert LOCK* buscr value
42141da177e4SLinus Torvalds	mov.l		&0xa0000000,%a2		# assert LOCKE* buscr value
42151da177e4SLinus Torvalds	mov.l		&0x00000000,%a3		# buscr unlock value
42161da177e4SLinus Torvalds
42171da177e4SLinus Torvalds# pre-load the instruction cache for the following algorithm.
42181da177e4SLinus Torvalds# this will minimize the number of cycles that LOCK* will be asserted.
42191da177e4SLinus Torvalds	bra.b		CASL2_ENTER		# start pre-loading icache
42201da177e4SLinus Torvalds
42211da177e4SLinus Torvalds#
42221da177e4SLinus Torvalds# D0 = dst operand <-
42231da177e4SLinus Torvalds# D1 = xxxxxxxx
42241da177e4SLinus Torvalds# D2 = update[31:24] operand
42251da177e4SLinus Torvalds# D3 = update[23:8]  operand
42261da177e4SLinus Torvalds# D4 = compare[31:0] operand
42271da177e4SLinus Torvalds# D5 = update[7:0]  operand
42281da177e4SLinus Torvalds# D6 = old SFC/DFC
42291da177e4SLinus Torvalds# D7 = old SR
42301da177e4SLinus Torvalds# A0 = ADDR
42311da177e4SLinus Torvalds# A1 = bus LOCK*  value
42321da177e4SLinus Torvalds# A2 = bus LOCKE* value
42331da177e4SLinus Torvalds# A3 = bus unlock value
42341da177e4SLinus Torvalds# A4 = xxxxxxxx
42351da177e4SLinus Torvalds# A5 = xxxxxxxx
42361da177e4SLinus Torvalds#
42371da177e4SLinus Torvalds	align		0x10
42381da177e4SLinus TorvaldsCASL2_START:
42391da177e4SLinus Torvalds	movc		%a1,%buscr		# assert LOCK*
42401da177e4SLinus Torvalds	movs.l		(%a0),%d0		# fetch Dest[31:0]
42411da177e4SLinus Torvalds	cmp.l		%d0,%d4			# Dest - Compare
42421da177e4SLinus Torvalds	bne.b		CASL2_NOUPDATE
42431da177e4SLinus Torvalds	bra.b		CASL2_UPDATE
42441da177e4SLinus TorvaldsCASL2_ENTER:
42451da177e4SLinus Torvalds	bra.b		~+16
42461da177e4SLinus Torvalds
42471da177e4SLinus TorvaldsCASL2_UPDATE:
42481da177e4SLinus Torvalds	movs.b		%d2,(%a0)+		# Update[31:24] -> DEST
42491da177e4SLinus Torvalds	movs.w		%d3,(%a0)+		# Update[23:8] -> DEST+0x1
42501da177e4SLinus Torvalds	movc		%a2,%buscr		# assert LOCKE*
42511da177e4SLinus Torvalds	bra.b		CASL2_UPDATE2
42521da177e4SLinus Torvalds	bra.b		~+16
42531da177e4SLinus Torvalds
42541da177e4SLinus TorvaldsCASL2_UPDATE2:
42551da177e4SLinus Torvalds	movs.b		%d5,(%a0)		# Update[7:0] -> DEST+0x3
42561da177e4SLinus Torvalds	movc		%a3,%buscr		# unlock the bus
42571da177e4SLinus Torvalds	bra.w		casl_update_done
42581da177e4SLinus Torvalds	nop
42591da177e4SLinus Torvalds	bra.b		~+16
42601da177e4SLinus Torvalds
42611da177e4SLinus TorvaldsCASL2_NOUPDATE:
42621da177e4SLinus Torvalds	rol.l		&0x8,%d0		# get Dest[31:24]
42631da177e4SLinus Torvalds	movs.b		%d0,(%a0)+		# Dest[31:24] -> DEST
42641da177e4SLinus Torvalds	swap		%d0			# get Dest[23:8]
42651da177e4SLinus Torvalds	movs.w		%d0,(%a0)+		# Dest[23:8] -> DEST+0x1
42661da177e4SLinus Torvalds	bra.b		CASL2_NOUPDATE2
42671da177e4SLinus Torvalds	bra.b		~+16
42681da177e4SLinus Torvalds
42691da177e4SLinus TorvaldsCASL2_NOUPDATE2:
42701da177e4SLinus Torvalds	rol.l		&0x8,%d0		# get Dest[7:0]
42711da177e4SLinus Torvalds	movc		%a2,%buscr		# assert LOCKE*
42721da177e4SLinus Torvalds	movs.b		%d0,(%a0)		# Dest[7:0] -> DEST+0x3
42731da177e4SLinus Torvalds	bra.b		CASL2_NOUPDATE3
42741da177e4SLinus Torvalds	nop
42751da177e4SLinus Torvalds	bra.b		~+16
42761da177e4SLinus Torvalds
42771da177e4SLinus TorvaldsCASL2_NOUPDATE3:
42781da177e4SLinus Torvalds	movc		%a3,%buscr		# unlock the bus
42791da177e4SLinus Torvalds	bra.w		casl_noupdate_done
42801da177e4SLinus Torvalds	nop
42811da177e4SLinus Torvalds	nop
42821da177e4SLinus Torvalds	nop
42831da177e4SLinus Torvalds	bra.b		~+16
42841da177e4SLinus Torvalds
42851da177e4SLinus TorvaldsCASL2_FILLER:
42861da177e4SLinus Torvalds	nop
42871da177e4SLinus Torvalds	nop
42881da177e4SLinus Torvalds	nop
42891da177e4SLinus Torvalds	nop
42901da177e4SLinus Torvalds	nop
42911da177e4SLinus Torvalds	nop
42921da177e4SLinus Torvalds	nop
42931da177e4SLinus Torvalds	bra.b		CASL2_START
42941da177e4SLinus Torvalds
42951da177e4SLinus Torvalds####
42961da177e4SLinus Torvalds####
42971da177e4SLinus Torvalds# end label used by _isp_cas_inrange()
42981da177e4SLinus Torvalds	global		_CASHI
42991da177e4SLinus Torvalds_CASHI:
4300