⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 isp.s

📁 linux内核源码
💻 S
📖 第 1 页 / 共 5 页
字号:
	bsr.l		_dmem_read_byte		# read second byte	tst.l		%d1			# dfetch error?	bne.w		movp_read_err		# yes	lsl.l		&0x8,%d2	mov.b		%d0,%d2			# append bytes	add.w		&0x2,%a2		# incr addr by 2 bytes	mov.l		%a2,%a0	bsr.l		_dmem_read_byte		# read second byte	tst.l		%d1			# dfetch error?	bne.w		movp_read_err		# yes	lsl.l		&0x8,%d2	mov.b		%d0,%d2			# append bytes	mov.b		EXC_OPWORD(%a6),%d1	lsr.b		&0x1,%d1	and.w		&0x7,%d1		# extract Dx from opcode word	mov.l		%d2,(EXC_DREGS,%a6,%d1.w*4) # store dx	rts# a0 = dst addrm2rwtrans:	mov.l		%a0,%a2			# store addr	bsr.l		_dmem_read_byte		# read first byte	tst.l		%d1			# dfetch error?	bne.w		movp_read_err		# yes	mov.l		%d0,%d2	add.w		&0x2,%a2		# incr addr by 2 bytes	mov.l		%a2,%a0	bsr.l		_dmem_read_byte		# read second byte	tst.l		%d1			# dfetch error?	bne.w		movp_read_err		# yes	lsl.w		&0x8,%d2	mov.b		%d0,%d2			# append bytes	mov.b		EXC_OPWORD(%a6),%d1	lsr.b		&0x1,%d1	and.w		&0x7,%d1		# extract Dx from opcode word	mov.w		%d2,(EXC_DREGS+2,%a6,%d1.w*4) # store dx	rts# if dmem_{read,write}_byte() returns a fail message in d1, the package# must create an access error frame. here, we pass a skeleton fslw# and the failing address to the routine that creates the new frame.# FSLW:#	write = true#	size = byte#	TM = data#	software emulation error = truemovp_write_err:	mov.l		%a2,%a0			# pass failing address	mov.l		&0x00a10001,%d0		# pass fslw	bra.l		isp_dacc# FSLW:#	read = true#	size = byte#	TM = data#	software emulation error = truemovp_read_err:	mov.l		%a2,%a0			# pass failing address	mov.l		&0x01210001,%d0		# pass fslw	bra.l		isp_dacc########################################################################## XDEF ****************************************************************	##	_chk2_cmp2(): routine to emulate chk2/cmp2 instructions		##									## XREF ****************************************************************	##	_calc_ea(): calculate effective address				##	_dmem_read_long(): read operands				##	_dmem_read_word(): read operands				##	isp_dacc(): handle data access error exception			##									## INPUT ***************************************************************	##	none								##									## OUTPUT **************************************************************	##	If exiting through isp_dacc...					##		a0 = failing address					##		d0 = FSLW						##	else								##		none							##									## ALGORITHM ***********************************************************	##	First, calculate the effective address, then fetch the byte,	## word, or longword sized operands. Then, in the interest of		## simplicity, all operands are converted to longword size whether the	## operation is byte, word, or long. The bounds are sign extended	## accordingly. If Rn is a data regsiter, Rn is also sign extended. If	## Rn is an address register, it need not be sign extended since the	## full register is always used.						##	The comparisons are made and the condition codes calculated.	## If the instruction is chk2 and the Rn value is out-of-bounds, set	## the ichk_flg in SPCOND_FLG.						##	If the memory fetch returns a failing value, pass the failing	## address and FSLW to the isp_dacc() routine.				##									##########################################################################	global		_chk2_cmp2_chk2_cmp2:# passing size parameter doesn't matter since chk2 & cmp2 can't do# either predecrement, postincrement, or immediate.	bsr.l		_calc_ea		# calculate <ea>	mov.b		EXC_EXTWORD(%a6), %d0	# fetch hi extension word	rol.b		&0x4, %d0		# rotate reg bits into lo	and.w		&0xf, %d0		# extract reg bits	mov.l		(EXC_DREGS,%a6,%d0.w*4), %d2 # get regval	cmpi.b		EXC_OPWORD(%a6), &0x2	# what size is operation?	blt.b		chk2_cmp2_byte		# size == byte	beq.b		chk2_cmp2_word		# size == word# the bounds are longword size. call routine to read the lower# bound into d0 and the higher bound into d1.chk2_cmp2_long:	mov.l		%a0,%a2			# save copy of <ea>	bsr.l		_dmem_read_long		# fetch long lower bound	tst.l		%d1			# dfetch error?	bne.w		chk2_cmp2_err_l		# yes	mov.l		%d0,%d3			# save long lower bound	addq.l		&0x4,%a2	mov.l		%a2,%a0			# pass <ea> of long upper bound	bsr.l		_dmem_read_long		# fetch long upper bound	tst.l		%d1			# dfetch error?	bne.w		chk2_cmp2_err_l		# yes	mov.l		%d0,%d1			# long upper bound in d1	mov.l		%d3,%d0			# long lower bound in d0	bra.w		chk2_cmp2_compare	# go do the compare emulation# the bounds are word size. fetch them in one subroutine call by# reading a longword. sign extend both. if it's a data operation,# sign extend Rn to long, also.chk2_cmp2_word:	mov.l		%a0,%a2	bsr.l		_dmem_read_long		# fetch 2 word bounds	tst.l		%d1			# dfetch error?	bne.w		chk2_cmp2_err_l		# yes	mov.w		%d0, %d1		# place hi in %d1	swap		%d0			# place lo in %d0	ext.l		%d0			# sign extend lo bnd	ext.l		%d1			# sign extend hi bnd	btst		&0x7, EXC_EXTWORD(%a6)	# address compare?	bne.w		chk2_cmp2_compare	# yes; don't sign extend# operation is a data register compare.# sign extend word to long so we can do simple longword compares.	ext.l		%d2			# sign extend data word	bra.w		chk2_cmp2_compare	# go emulate compare# the bounds are byte size. fetch them in one subroutine call by# reading a word. sign extend both. if it's a data operation,# sign extend Rn to long, also.chk2_cmp2_byte:	mov.l		%a0,%a2	bsr.l		_dmem_read_word		# fetch 2 byte bounds	tst.l		%d1			# dfetch error?	bne.w		chk2_cmp2_err_w		# yes	mov.b		%d0, %d1		# place hi in %d1	lsr.w		&0x8, %d0		# place lo in %d0	extb.l		%d0			# sign extend lo bnd	extb.l		%d1			# sign extend hi bnd	btst		&0x7, EXC_EXTWORD(%a6)	# address compare?	bne.b		chk2_cmp2_compare	# yes; don't sign extend# operation is a data register compare.# sign extend byte to long so we can do simple longword compares.	extb.l		%d2			# sign extend data byte## To set the ccodes correctly:#	(1) save 'Z' bit from (Rn - lo)#	(2) save 'Z' and 'N' bits from ((hi - lo) - (Rn - hi))#	(3) keep 'X', 'N', and 'V' from before instruction#	(4) combine ccodes#chk2_cmp2_compare:	sub.l		%d0, %d2		# (Rn - lo)	mov.w		%cc, %d3		# fetch resulting ccodes	andi.b		&0x4, %d3		# keep 'Z' bit	sub.l		%d0, %d1		# (hi - lo)	cmp.l		%d1,%d2			# ((hi - lo) - (Rn - hi))	mov.w		%cc, %d4		# fetch resulting ccodes	or.b		%d4, %d3		# combine w/ earlier ccodes	andi.b		&0x5, %d3		# keep 'Z' and 'N'	mov.w		EXC_CC(%a6), %d4	# fetch old ccodes	andi.b		&0x1a, %d4		# keep 'X','N','V' bits	or.b		%d3, %d4		# insert new ccodes	mov.w		%d4, EXC_CC(%a6)	# save new ccodes	btst		&0x3, EXC_EXTWORD(%a6)	# separate chk2,cmp2	bne.b		chk2_finish		# it's a chk2	rts# this code handles the only difference between chk2 and cmp2. chk2 would# have trapped out if the value was out of bounds. we check this by seeing# if the 'N' bit was set by the operation.chk2_finish:	btst		&0x0, %d4		# is 'N' bit set?	bne.b		chk2_trap		# yes;chk2 should trap	rtschk2_trap:	mov.b		&ichk_flg,SPCOND_FLG(%a6) # set "special case" flag	rts# if dmem_read_{long,word}() returns a fail message in d1, the package# must create an access error frame. here, we pass a skeleton fslw# and the failing address to the routine that creates the new frame.# FSLW:#	read = true#	size = longword#	TM = data#	software emulation error = truechk2_cmp2_err_l:	mov.l		%a2,%a0			# pass failing address	mov.l		&0x01010001,%d0		# pass fslw	bra.l		isp_dacc# FSLW:#	read = true#	size = word#	TM = data#	software emulation error = truechk2_cmp2_err_w:	mov.l		%a2,%a0			# pass failing address	mov.l		&0x01410001,%d0		# pass fslw	bra.l		isp_dacc########################################################################## XDEF ****************************************************************	##	_div64(): routine to emulate div{u,s}.l <ea>,Dr:Dq		##							64/32->32r:32q	##									## XREF ****************************************************************	##	_calc_ea() - calculate effective address			##	isp_iacc() - handle instruction access error exception		##	isp_dacc() - handle data access error exception			##	isp_restore() - restore An on access error w/ -() or ()+	##									## INPUT ***************************************************************	##	none								##									## OUTPUT **************************************************************	##	If exiting through isp_dacc...					##		a0 = failing address					##		d0 = FSLW						##	else								##		none							##									## ALGORITHM ***********************************************************	##	First, decode the operand location. If it's in Dn, fetch from	## the stack. If it's in memory, use _calc_ea() to calculate the		## effective address. Use _dmem_read_long() to fetch at that address.	## Unless the operand is immediate data. Then use _imem_read_long().	## Send failures to isp_dacc() or isp_iacc() as appropriate.		##	If the operands are signed, make them unsigned and save	the	## sign info for later. Separate out special cases like divide-by-zero	## or 32-bit divides if possible. Else, use a special math algorithm	## to calculate the result.						##	Restore sign info if signed instruction. Set the condition	## codes. Set idbyz_flg in SPCOND_FLG if divisor was zero. Store the	## quotient and remainder in the appropriate data registers on the stack.##									##########################################################################set	NDIVISOR,	EXC_TEMP+0x0set	NDIVIDEND,	EXC_TEMP+0x1set	NDRSAVE,	EXC_TEMP+0x2set	NDQSAVE,	EXC_TEMP+0x4set	DDSECOND,	EXC_TEMP+0x6set	DDQUOTIENT,	EXC_TEMP+0x8set	DDNORMAL,	EXC_TEMP+0xc	global		_div64############## div(u,s)l ##############_div64:	mov.b		EXC_OPWORD+1(%a6), %d0	andi.b		&0x38, %d0		# extract src mode	bne.w		dcontrolmodel_s		# %dn dest or control mode?	mov.b		EXC_OPWORD+1(%a6), %d0	# extract Dn from opcode	andi.w		&0x7, %d0	mov.l		(EXC_DREGS,%a6,%d0.w*4), %d7 # fetch divisor from registerdgotsrcl:	beq.w		div64eq0		# divisor is = 0!!!	mov.b		EXC_EXTWORD+1(%a6), %d0	# extract Dr from extword	mov.b		EXC_EXTWORD(%a6), %d1	# extract Dq from extword	and.w		&0x7, %d0	lsr.b		&0x4, %d1	and.w		&0x7, %d1	mov.w		%d0, NDRSAVE(%a6)	# save Dr for later	mov.w		%d1, NDQSAVE(%a6)	# save Dq for later# fetch %dr and %dq directly off stack since all regs are saved there	mov.l		(EXC_DREGS,%a6,%d0.w*4), %d5 # get dividend hi	mov.l		(EXC_DREGS,%a6,%d1.w*4), %d6 # get dividend lo# separate signed and unsigned divide	btst		&0x3, EXC_EXTWORD(%a6)	# signed or unsigned?	beq.b		dspecialcases		# use positive divide# save the sign of the divisor# make divisor unsigned if it's negative	tst.l		%d7			# chk sign of divisor	slt		NDIVISOR(%a6)		# save sign of divisor	bpl.b		dsgndividend	neg.l		%d7			# complement negative divisor# save the sign of the dividend# make dividend unsigned if it's negativedsgndividend:	tst.l		%d5			# chk sign of hi(dividend)	slt		NDIVIDEND(%a6)		# save sign of dividend	bpl.b		dspecialcases	mov.w		&0x0, %cc		# clear 'X' cc bit	negx.l		%d6			# complement signed dividend	negx.l		%d5# extract some special cases:#	- is (dividend == 0) ?#	- is (hi(dividend) == 0 && (divisor <= lo(dividend))) ? (32-bit div)dspecialcases:	tst.l		%d5			# is (hi(dividend) == 0)	bne.b		dnormaldivide		# no, so try it the long way	tst.l		%d6			# is (lo(dividend) == 0), too	beq.w		ddone			# yes, so (dividend == 0)	cmp.l		%d7,%d6			# is (divisor <= lo(dividend))	bls.b		d32bitdivide		# yes, so use 32 bit divide	exg		%d5,%d6			# q = 0, r = dividend	bra.w		divfinish		# can't divide, we're done.d32bitdivide:	tdivu.l		%d7, %d5:%d6		# it's only a 32/32 bit div!	bra.b		divfinishdnormaldivide:# last special case:#	- is hi(dividend) >= divisor ? if yes, then overflow	cmp.l		%d7,%d5	bls.b		ddovf			# answer won't fit in 32 bits# perform the divide algorithm:	bsr.l		dclassical		# do int divide# separate into signed and unsigned finishes.divfinish:	btst		&0x3, EXC_EXTWORD(%a6)	# do divs, divu separately	beq.b		ddone			# divu has no processing!!!# it was a divs.l, so ccode setting is a little more complicated...	tst.b		NDIVIDEND(%a6)		# remainder has same sign	beq.b		dcc			# as dividend.	neg.l		%d5			# sgn(rem) = sgn(dividend)dcc:	mov.b		NDIVISOR(%a6), %d0	eor.b		%d0, NDIVIDEND(%a6)	# chk if quotient is negative	beq.b		dqpos			# branch to quot positive# 0x80000000 is the largest number representable as a 32-bit negative# number. the negative of 0x80000000 is 0x80000000.	cmpi.l		%d6, &0x80000000	# will (-quot) fit in 32 bits?	bhi.b		ddovf	neg.l		%d6			# make (-quot) 2's comp	bra.b		ddonedqpos:	btst		&0x1f, %d6		# will (+quot) fit in 32 bits?	bne.b		ddovfddone:# at this point, result is normal so ccodes are set based on result.	mov.w		EXC_CC(%a6), %cc	tst.l		%d6			# set %ccode bits	mov.w		%cc, EXC_CC(%a6)	mov.w		NDRSAVE(%a6), %d0	# get Dr off stack	mov.w		NDQSAVE(%a6), %d1	# get Dq off stack# if the register numbers are the same, only the quotient gets saved.# so, if we always save the quotient second, we save ourselves a cmp&beq	mov.l		%d5, (EXC_DREGS,%a6,%d0.w*4) # save remainder	mov.l		%d6, (EXC_DREGS,%a6,%d1.w*4) # save quotient	rtsddovf:	bset		&0x1, EXC_CC+1(%a6)	# 'V' set on overflow	bclr		&0x0, EXC_CC+1(%a6)	# 'C' cleared on overflow	rtsdiv64eq0:	

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -