ifpsp060/src/fpsp.S [18148:18545]:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#########################################################################
# XDEF ****************************************************************	#
#	fmovm_dynamic(): emulate "fmovm" dynamic instruction		#
#									#
# XREF ****************************************************************	#
#	fetch_dreg() - fetch data register				#
#	{i,d,}mem_read() - fetch data from memory			#
#	_mem_write() - write data to memory				#
#	iea_iacc() - instruction memory access error occurred		#
#	iea_dacc() - data memory access error occurred			#
#	restore() - restore An index regs if access error occurred	#
#									#
# INPUT ***************************************************************	#
#	None								#
#									#
# OUTPUT **************************************************************	#
#	If instr is "fmovm Dn,-(A7)" from supervisor mode,		#
#		d0 = size of dump					#
#		d1 = Dn							#
#	Else if instruction access error,				#
#		d0 = FSLW						#
#	Else if data access error,					#
#		d0 = FSLW						#
#		a0 = address of fault					#
#	Else								#
#		none.							#
#									#
# ALGORITHM ***********************************************************	#
#	The effective address must be calculated since this is entered	#
# from an "Unimplemented Effective Address" exception handler. So, we	#
# have our own fcalc_ea() routine here. If an access error is flagged	#
# by a _{i,d,}mem_read() call, we must exit through the special		#
# handler.								#
#	The data register is determined and its value loaded to get the	#
# string of FP registers affected. This value is used as an index into	#
# a lookup table such that we can determine the number of bytes		#
# involved.								#
#	If the instruction is "fmovm.x <ea>,Dn", a _mem_read() is used	#
# to read in all FP values. Again, _mem_read() may fail and require a	#
# special exit.								#
#	If the instruction is "fmovm.x DN,<ea>", a _mem_write() is used	#
# to write all FP values. _mem_write() may also fail.			#
#	If the instruction is "fmovm.x DN,-(a7)" from supervisor mode,	#
# then we return the size of the dump and the string to the caller	#
# so that the move can occur outside of this routine. This special	#
# case is required so that moves to the system stack are handled	#
# correctly.								#
#									#
# DYNAMIC:								#
#	fmovm.x	dn, <ea>						#
#	fmovm.x	<ea>, dn						#
#									#
#	      <WORD 1>		      <WORD2>				#
#	1111 0010 00 |<ea>|	11@& 1000 0$$$ 0000			#
#									#
#	& = (0): predecrement addressing mode				#
#	    (1): postincrement or control addressing mode		#
#	@ = (0): move listed regs from memory to the FPU		#
#	    (1): move listed regs from the FPU to memory		#
#	$$$    : index of data register holding reg select mask		#
#									#
# NOTES:								#
#	If the data register holds a zero, then the			#
#	instruction is a nop.						#
#									#
#########################################################################

	global		fmovm_dynamic
fmovm_dynamic:

# extract the data register in which the bit string resides...
	mov.b		1+EXC_EXTWORD(%a6),%d1	# fetch extword
	andi.w		&0x70,%d1		# extract reg bits
	lsr.b		&0x4,%d1		# shift into lo bits

# fetch the bit string into d0...
	bsr.l		fetch_dreg		# fetch reg string

	andi.l		&0x000000ff,%d0		# keep only lo byte

	mov.l		%d0,-(%sp)		# save strg
	mov.b		(tbl_fmovm_size.w,%pc,%d0),%d0
	mov.l		%d0,-(%sp)		# save size
	bsr.l		fmovm_calc_ea		# calculate <ea>
	mov.l		(%sp)+,%d0		# restore size
	mov.l		(%sp)+,%d1		# restore strg

# if the bit string is a zero, then the operation is a no-op
# but, make sure that we've calculated ea and advanced the opword pointer
	beq.w		fmovm_data_done

# separate move ins from move outs...
	btst		&0x5,EXC_EXTWORD(%a6)	# is it a move in or out?
	beq.w		fmovm_data_in		# it's a move out

#############
# MOVE OUT: #
#############
fmovm_data_out:
	btst		&0x4,EXC_EXTWORD(%a6)	# control or predecrement?
	bne.w		fmovm_out_ctrl		# control

############################
fmovm_out_predec:
# for predecrement mode, the bit string is the opposite of both control
# operations and postincrement mode. (bit7 = FP7 ... bit0 = FP0)
# here, we convert it to be just like the others...
	mov.b		(tbl_fmovm_convert.w,%pc,%d1.w*1),%d1

	btst		&0x5,EXC_SR(%a6)	# user or supervisor mode?
	beq.b		fmovm_out_ctrl		# user

fmovm_out_predec_s:
	cmpi.b		SPCOND_FLG(%a6),&mda7_flg # is <ea> mode -(a7)?
	bne.b		fmovm_out_ctrl

# the operation was unfortunately an: fmovm.x dn,-(sp)
# called from supervisor mode.
# we're also passing "size" and "strg" back to the calling routine
	rts

############################
fmovm_out_ctrl:
	mov.l		%a0,%a1			# move <ea> to a1

	sub.l		%d0,%sp			# subtract size of dump
	lea		(%sp),%a0

	tst.b		%d1			# should FP0 be moved?
	bpl.b		fmovm_out_ctrl_fp1	# no

	mov.l		0x0+EXC_FP0(%a6),(%a0)+	# yes
	mov.l		0x4+EXC_FP0(%a6),(%a0)+
	mov.l		0x8+EXC_FP0(%a6),(%a0)+

fmovm_out_ctrl_fp1:
	lsl.b		&0x1,%d1		# should FP1 be moved?
	bpl.b		fmovm_out_ctrl_fp2	# no

	mov.l		0x0+EXC_FP1(%a6),(%a0)+	# yes
	mov.l		0x4+EXC_FP1(%a6),(%a0)+
	mov.l		0x8+EXC_FP1(%a6),(%a0)+

fmovm_out_ctrl_fp2:
	lsl.b		&0x1,%d1		# should FP2 be moved?
	bpl.b		fmovm_out_ctrl_fp3	# no

	fmovm.x		&0x20,(%a0)		# yes
	add.l		&0xc,%a0

fmovm_out_ctrl_fp3:
	lsl.b		&0x1,%d1		# should FP3 be moved?
	bpl.b		fmovm_out_ctrl_fp4	# no

	fmovm.x		&0x10,(%a0)		# yes
	add.l		&0xc,%a0

fmovm_out_ctrl_fp4:
	lsl.b		&0x1,%d1		# should FP4 be moved?
	bpl.b		fmovm_out_ctrl_fp5	# no

	fmovm.x		&0x08,(%a0)		# yes
	add.l		&0xc,%a0

fmovm_out_ctrl_fp5:
	lsl.b		&0x1,%d1		# should FP5 be moved?
	bpl.b		fmovm_out_ctrl_fp6	# no

	fmovm.x		&0x04,(%a0)		# yes
	add.l		&0xc,%a0

fmovm_out_ctrl_fp6:
	lsl.b		&0x1,%d1		# should FP6 be moved?
	bpl.b		fmovm_out_ctrl_fp7	# no

	fmovm.x		&0x02,(%a0)		# yes
	add.l		&0xc,%a0

fmovm_out_ctrl_fp7:
	lsl.b		&0x1,%d1		# should FP7 be moved?
	bpl.b		fmovm_out_ctrl_done	# no

	fmovm.x		&0x01,(%a0)		# yes
	add.l		&0xc,%a0

fmovm_out_ctrl_done:
	mov.l		%a1,L_SCR1(%a6)

	lea		(%sp),%a0		# pass: supervisor src
	mov.l		%d0,-(%sp)		# save size
	bsr.l		_dmem_write		# copy data to user mem

	mov.l		(%sp)+,%d0
	add.l		%d0,%sp			# clear fpreg data from stack

	tst.l		%d1			# did dstore err?
	bne.w		fmovm_out_err		# yes

	rts

############
# MOVE IN: #
############
fmovm_data_in:
	mov.l		%a0,L_SCR1(%a6)

	sub.l		%d0,%sp			# make room for fpregs
	lea		(%sp),%a1

	mov.l		%d1,-(%sp)		# save bit string for later
	mov.l		%d0,-(%sp)		# save # of bytes

	bsr.l		_dmem_read		# copy data from user mem

	mov.l		(%sp)+,%d0		# retrieve # of bytes

	tst.l		%d1			# did dfetch fail?
	bne.w		fmovm_in_err		# yes

	mov.l		(%sp)+,%d1		# load bit string

	lea		(%sp),%a0		# addr of stack

	tst.b		%d1			# should FP0 be moved?
	bpl.b		fmovm_data_in_fp1	# no

	mov.l		(%a0)+,0x0+EXC_FP0(%a6)	# yes
	mov.l		(%a0)+,0x4+EXC_FP0(%a6)
	mov.l		(%a0)+,0x8+EXC_FP0(%a6)

fmovm_data_in_fp1:
	lsl.b		&0x1,%d1		# should FP1 be moved?
	bpl.b		fmovm_data_in_fp2	# no

	mov.l		(%a0)+,0x0+EXC_FP1(%a6)	# yes
	mov.l		(%a0)+,0x4+EXC_FP1(%a6)
	mov.l		(%a0)+,0x8+EXC_FP1(%a6)

fmovm_data_in_fp2:
	lsl.b		&0x1,%d1		# should FP2 be moved?
	bpl.b		fmovm_data_in_fp3	# no

	fmovm.x		(%a0)+,&0x20		# yes

fmovm_data_in_fp3:
	lsl.b		&0x1,%d1		# should FP3 be moved?
	bpl.b		fmovm_data_in_fp4	# no

	fmovm.x		(%a0)+,&0x10		# yes

fmovm_data_in_fp4:
	lsl.b		&0x1,%d1		# should FP4 be moved?
	bpl.b		fmovm_data_in_fp5	# no

	fmovm.x		(%a0)+,&0x08		# yes

fmovm_data_in_fp5:
	lsl.b		&0x1,%d1		# should FP5 be moved?
	bpl.b		fmovm_data_in_fp6	# no

	fmovm.x		(%a0)+,&0x04		# yes

fmovm_data_in_fp6:
	lsl.b		&0x1,%d1		# should FP6 be moved?
	bpl.b		fmovm_data_in_fp7	# no

	fmovm.x		(%a0)+,&0x02		# yes

fmovm_data_in_fp7:
	lsl.b		&0x1,%d1		# should FP7 be moved?
	bpl.b		fmovm_data_in_done	# no

	fmovm.x		(%a0)+,&0x01		# yes

fmovm_data_in_done:
	add.l		%d0,%sp			# remove fpregs from stack
	rts

#####################################

fmovm_data_done:
	rts

##############################################################################

#
# table indexed by the operation's bit string that gives the number
# of bytes that will be moved.
#
# number of bytes = (# of 1's in bit string) * 12(bytes/fpreg)
#
tbl_fmovm_size:
	byte	0x00,0x0c,0x0c,0x18,0x0c,0x18,0x18,0x24
	byte	0x0c,0x18,0x18,0x24,0x18,0x24,0x24,0x30
	byte	0x0c,0x18,0x18,0x24,0x18,0x24,0x24,0x30
	byte	0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
	byte	0x0c,0x18,0x18,0x24,0x18,0x24,0x24,0x30
	byte	0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
	byte	0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
	byte	0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
	byte	0x0c,0x18,0x18,0x24,0x18,0x24,0x24,0x30
	byte	0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
	byte	0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
	byte	0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
	byte	0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
	byte	0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
	byte	0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
	byte	0x30,0x3c,0x3c,0x48,0x3c,0x48,0x48,0x54
	byte	0x0c,0x18,0x18,0x24,0x18,0x24,0x24,0x30
	byte	0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
	byte	0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
	byte	0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
	byte	0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
	byte	0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
	byte	0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
	byte	0x30,0x3c,0x3c,0x48,0x3c,0x48,0x48,0x54
	byte	0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
	byte	0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
	byte	0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
	byte	0x30,0x3c,0x3c,0x48,0x3c,0x48,0x48,0x54
	byte	0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
	byte	0x30,0x3c,0x3c,0x48,0x3c,0x48,0x48,0x54
	byte	0x30,0x3c,0x3c,0x48,0x3c,0x48,0x48,0x54
	byte	0x3c,0x48,0x48,0x54,0x48,0x54,0x54,0x60

#
# table to convert a pre-decrement bit string into a post-increment
# or control bit string.
# ex:	0x00	==>	0x00
#	0x01	==>	0x80
#	0x02	==>	0x40
#		.
#		.
#	0xfd	==>	0xbf
#	0xfe	==>	0x7f
#	0xff	==>	0xff
#
tbl_fmovm_convert:
	byte	0x00,0x80,0x40,0xc0,0x20,0xa0,0x60,0xe0
	byte	0x10,0x90,0x50,0xd0,0x30,0xb0,0x70,0xf0
	byte	0x08,0x88,0x48,0xc8,0x28,0xa8,0x68,0xe8
	byte	0x18,0x98,0x58,0xd8,0x38,0xb8,0x78,0xf8
	byte	0x04,0x84,0x44,0xc4,0x24,0xa4,0x64,0xe4
	byte	0x14,0x94,0x54,0xd4,0x34,0xb4,0x74,0xf4
	byte	0x0c,0x8c,0x4c,0xcc,0x2c,0xac,0x6c,0xec
	byte	0x1c,0x9c,0x5c,0xdc,0x3c,0xbc,0x7c,0xfc
	byte	0x02,0x82,0x42,0xc2,0x22,0xa2,0x62,0xe2
	byte	0x12,0x92,0x52,0xd2,0x32,0xb2,0x72,0xf2
	byte	0x0a,0x8a,0x4a,0xca,0x2a,0xaa,0x6a,0xea
	byte	0x1a,0x9a,0x5a,0xda,0x3a,0xba,0x7a,0xfa
	byte	0x06,0x86,0x46,0xc6,0x26,0xa6,0x66,0xe6
	byte	0x16,0x96,0x56,0xd6,0x36,0xb6,0x76,0xf6
	byte	0x0e,0x8e,0x4e,0xce,0x2e,0xae,0x6e,0xee
	byte	0x1e,0x9e,0x5e,0xde,0x3e,0xbe,0x7e,0xfe
	byte	0x01,0x81,0x41,0xc1,0x21,0xa1,0x61,0xe1
	byte	0x11,0x91,0x51,0xd1,0x31,0xb1,0x71,0xf1
	byte	0x09,0x89,0x49,0xc9,0x29,0xa9,0x69,0xe9
	byte	0x19,0x99,0x59,0xd9,0x39,0xb9,0x79,0xf9
	byte	0x05,0x85,0x45,0xc5,0x25,0xa5,0x65,0xe5
	byte	0x15,0x95,0x55,0xd5,0x35,0xb5,0x75,0xf5
	byte	0x0d,0x8d,0x4d,0xcd,0x2d,0xad,0x6d,0xed
	byte	0x1d,0x9d,0x5d,0xdd,0x3d,0xbd,0x7d,0xfd
	byte	0x03,0x83,0x43,0xc3,0x23,0xa3,0x63,0xe3
	byte	0x13,0x93,0x53,0xd3,0x33,0xb3,0x73,0xf3
	byte	0x0b,0x8b,0x4b,0xcb,0x2b,0xab,0x6b,0xeb
	byte	0x1b,0x9b,0x5b,0xdb,0x3b,0xbb,0x7b,0xfb
	byte	0x07,0x87,0x47,0xc7,0x27,0xa7,0x67,0xe7
	byte	0x17,0x97,0x57,0xd7,0x37,0xb7,0x77,0xf7
	byte	0x0f,0x8f,0x4f,0xcf,0x2f,0xaf,0x6f,0xef
	byte	0x1f,0x9f,0x5f,0xdf,0x3f,0xbf,0x7f,0xff

	global		fmovm_calc_ea
###############################################
# _fmovm_calc_ea: calculate effective address #
###############################################
fmovm_calc_ea:
	mov.l		%d0,%a0			# move # bytes to a0

# currently, MODE and REG are taken from the EXC_OPWORD. this could be
# easily changed if they were inputs passed in registers.
	mov.w		EXC_OPWORD(%a6),%d0	# fetch opcode word
	mov.w		%d0,%d1			# make a copy

	andi.w		&0x3f,%d0		# extract mode field
	andi.l		&0x7,%d1		# extract reg  field

# jump to the corresponding function for each {MODE,REG} pair.
	mov.w		(tbl_fea_mode.b,%pc,%d0.w*2),%d0 # fetch jmp distance
	jmp		(tbl_fea_mode.b,%pc,%d0.w*1) # jmp to correct ea mode

	swbeg		&64
tbl_fea_mode:
	short		tbl_fea_mode	-	tbl_fea_mode
	short		tbl_fea_mode	-	tbl_fea_mode
	short		tbl_fea_mode	-	tbl_fea_mode
	short		tbl_fea_mode	-	tbl_fea_mode
	short		tbl_fea_mode	-	tbl_fea_mode
	short		tbl_fea_mode	-	tbl_fea_mode
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -



ifpsp060/src/pfpsp.S [4197:4594]:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#########################################################################
# XDEF ****************************************************************	#
#	fmovm_dynamic(): emulate "fmovm" dynamic instruction		#
#									#
# XREF ****************************************************************	#
#	fetch_dreg() - fetch data register				#
#	{i,d,}mem_read() - fetch data from memory			#
#	_mem_write() - write data to memory				#
#	iea_iacc() - instruction memory access error occurred		#
#	iea_dacc() - data memory access error occurred			#
#	restore() - restore An index regs if access error occurred	#
#									#
# INPUT ***************************************************************	#
#	None								#
#									#
# OUTPUT **************************************************************	#
#	If instr is "fmovm Dn,-(A7)" from supervisor mode,		#
#		d0 = size of dump					#
#		d1 = Dn							#
#	Else if instruction access error,				#
#		d0 = FSLW						#
#	Else if data access error,					#
#		d0 = FSLW						#
#		a0 = address of fault					#
#	Else								#
#		none.							#
#									#
# ALGORITHM ***********************************************************	#
#	The effective address must be calculated since this is entered	#
# from an "Unimplemented Effective Address" exception handler. So, we	#
# have our own fcalc_ea() routine here. If an access error is flagged	#
# by a _{i,d,}mem_read() call, we must exit through the special		#
# handler.								#
#	The data register is determined and its value loaded to get the	#
# string of FP registers affected. This value is used as an index into	#
# a lookup table such that we can determine the number of bytes		#
# involved.								#
#	If the instruction is "fmovm.x <ea>,Dn", a _mem_read() is used	#
# to read in all FP values. Again, _mem_read() may fail and require a	#
# special exit.								#
#	If the instruction is "fmovm.x DN,<ea>", a _mem_write() is used	#
# to write all FP values. _mem_write() may also fail.			#
#	If the instruction is "fmovm.x DN,-(a7)" from supervisor mode,	#
# then we return the size of the dump and the string to the caller	#
# so that the move can occur outside of this routine. This special	#
# case is required so that moves to the system stack are handled	#
# correctly.								#
#									#
# DYNAMIC:								#
#	fmovm.x	dn, <ea>						#
#	fmovm.x	<ea>, dn						#
#									#
#	      <WORD 1>		      <WORD2>				#
#	1111 0010 00 |<ea>|	11@& 1000 0$$$ 0000			#
#									#
#	& = (0): predecrement addressing mode				#
#	    (1): postincrement or control addressing mode		#
#	@ = (0): move listed regs from memory to the FPU		#
#	    (1): move listed regs from the FPU to memory		#
#	$$$    : index of data register holding reg select mask		#
#									#
# NOTES:								#
#	If the data register holds a zero, then the			#
#	instruction is a nop.						#
#									#
#########################################################################

	global		fmovm_dynamic
fmovm_dynamic:

# extract the data register in which the bit string resides...
	mov.b		1+EXC_EXTWORD(%a6),%d1	# fetch extword
	andi.w		&0x70,%d1		# extract reg bits
	lsr.b		&0x4,%d1		# shift into lo bits

# fetch the bit string into d0...
	bsr.l		fetch_dreg		# fetch reg string

	andi.l		&0x000000ff,%d0		# keep only lo byte

	mov.l		%d0,-(%sp)		# save strg
	mov.b		(tbl_fmovm_size.w,%pc,%d0),%d0
	mov.l		%d0,-(%sp)		# save size
	bsr.l		fmovm_calc_ea		# calculate <ea>
	mov.l		(%sp)+,%d0		# restore size
	mov.l		(%sp)+,%d1		# restore strg

# if the bit string is a zero, then the operation is a no-op
# but, make sure that we've calculated ea and advanced the opword pointer
	beq.w		fmovm_data_done

# separate move ins from move outs...
	btst		&0x5,EXC_EXTWORD(%a6)	# is it a move in or out?
	beq.w		fmovm_data_in		# it's a move out

#############
# MOVE OUT: #
#############
fmovm_data_out:
	btst		&0x4,EXC_EXTWORD(%a6)	# control or predecrement?
	bne.w		fmovm_out_ctrl		# control

############################
fmovm_out_predec:
# for predecrement mode, the bit string is the opposite of both control
# operations and postincrement mode. (bit7 = FP7 ... bit0 = FP0)
# here, we convert it to be just like the others...
	mov.b		(tbl_fmovm_convert.w,%pc,%d1.w*1),%d1

	btst		&0x5,EXC_SR(%a6)	# user or supervisor mode?
	beq.b		fmovm_out_ctrl		# user

fmovm_out_predec_s:
	cmpi.b		SPCOND_FLG(%a6),&mda7_flg # is <ea> mode -(a7)?
	bne.b		fmovm_out_ctrl

# the operation was unfortunately an: fmovm.x dn,-(sp)
# called from supervisor mode.
# we're also passing "size" and "strg" back to the calling routine
	rts

############################
fmovm_out_ctrl:
	mov.l		%a0,%a1			# move <ea> to a1

	sub.l		%d0,%sp			# subtract size of dump
	lea		(%sp),%a0

	tst.b		%d1			# should FP0 be moved?
	bpl.b		fmovm_out_ctrl_fp1	# no

	mov.l		0x0+EXC_FP0(%a6),(%a0)+	# yes
	mov.l		0x4+EXC_FP0(%a6),(%a0)+
	mov.l		0x8+EXC_FP0(%a6),(%a0)+

fmovm_out_ctrl_fp1:
	lsl.b		&0x1,%d1		# should FP1 be moved?
	bpl.b		fmovm_out_ctrl_fp2	# no

	mov.l		0x0+EXC_FP1(%a6),(%a0)+	# yes
	mov.l		0x4+EXC_FP1(%a6),(%a0)+
	mov.l		0x8+EXC_FP1(%a6),(%a0)+

fmovm_out_ctrl_fp2:
	lsl.b		&0x1,%d1		# should FP2 be moved?
	bpl.b		fmovm_out_ctrl_fp3	# no

	fmovm.x		&0x20,(%a0)		# yes
	add.l		&0xc,%a0

fmovm_out_ctrl_fp3:
	lsl.b		&0x1,%d1		# should FP3 be moved?
	bpl.b		fmovm_out_ctrl_fp4	# no

	fmovm.x		&0x10,(%a0)		# yes
	add.l		&0xc,%a0

fmovm_out_ctrl_fp4:
	lsl.b		&0x1,%d1		# should FP4 be moved?
	bpl.b		fmovm_out_ctrl_fp5	# no

	fmovm.x		&0x08,(%a0)		# yes
	add.l		&0xc,%a0

fmovm_out_ctrl_fp5:
	lsl.b		&0x1,%d1		# should FP5 be moved?
	bpl.b		fmovm_out_ctrl_fp6	# no

	fmovm.x		&0x04,(%a0)		# yes
	add.l		&0xc,%a0

fmovm_out_ctrl_fp6:
	lsl.b		&0x1,%d1		# should FP6 be moved?
	bpl.b		fmovm_out_ctrl_fp7	# no

	fmovm.x		&0x02,(%a0)		# yes
	add.l		&0xc,%a0

fmovm_out_ctrl_fp7:
	lsl.b		&0x1,%d1		# should FP7 be moved?
	bpl.b		fmovm_out_ctrl_done	# no

	fmovm.x		&0x01,(%a0)		# yes
	add.l		&0xc,%a0

fmovm_out_ctrl_done:
	mov.l		%a1,L_SCR1(%a6)

	lea		(%sp),%a0		# pass: supervisor src
	mov.l		%d0,-(%sp)		# save size
	bsr.l		_dmem_write		# copy data to user mem

	mov.l		(%sp)+,%d0
	add.l		%d0,%sp			# clear fpreg data from stack

	tst.l		%d1			# did dstore err?
	bne.w		fmovm_out_err		# yes

	rts

############
# MOVE IN: #
############
fmovm_data_in:
	mov.l		%a0,L_SCR1(%a6)

	sub.l		%d0,%sp			# make room for fpregs
	lea		(%sp),%a1

	mov.l		%d1,-(%sp)		# save bit string for later
	mov.l		%d0,-(%sp)		# save # of bytes

	bsr.l		_dmem_read		# copy data from user mem

	mov.l		(%sp)+,%d0		# retrieve # of bytes

	tst.l		%d1			# did dfetch fail?
	bne.w		fmovm_in_err		# yes

	mov.l		(%sp)+,%d1		# load bit string

	lea		(%sp),%a0		# addr of stack

	tst.b		%d1			# should FP0 be moved?
	bpl.b		fmovm_data_in_fp1	# no

	mov.l		(%a0)+,0x0+EXC_FP0(%a6)	# yes
	mov.l		(%a0)+,0x4+EXC_FP0(%a6)
	mov.l		(%a0)+,0x8+EXC_FP0(%a6)

fmovm_data_in_fp1:
	lsl.b		&0x1,%d1		# should FP1 be moved?
	bpl.b		fmovm_data_in_fp2	# no

	mov.l		(%a0)+,0x0+EXC_FP1(%a6)	# yes
	mov.l		(%a0)+,0x4+EXC_FP1(%a6)
	mov.l		(%a0)+,0x8+EXC_FP1(%a6)

fmovm_data_in_fp2:
	lsl.b		&0x1,%d1		# should FP2 be moved?
	bpl.b		fmovm_data_in_fp3	# no

	fmovm.x		(%a0)+,&0x20		# yes

fmovm_data_in_fp3:
	lsl.b		&0x1,%d1		# should FP3 be moved?
	bpl.b		fmovm_data_in_fp4	# no

	fmovm.x		(%a0)+,&0x10		# yes

fmovm_data_in_fp4:
	lsl.b		&0x1,%d1		# should FP4 be moved?
	bpl.b		fmovm_data_in_fp5	# no

	fmovm.x		(%a0)+,&0x08		# yes

fmovm_data_in_fp5:
	lsl.b		&0x1,%d1		# should FP5 be moved?
	bpl.b		fmovm_data_in_fp6	# no

	fmovm.x		(%a0)+,&0x04		# yes

fmovm_data_in_fp6:
	lsl.b		&0x1,%d1		# should FP6 be moved?
	bpl.b		fmovm_data_in_fp7	# no

	fmovm.x		(%a0)+,&0x02		# yes

fmovm_data_in_fp7:
	lsl.b		&0x1,%d1		# should FP7 be moved?
	bpl.b		fmovm_data_in_done	# no

	fmovm.x		(%a0)+,&0x01		# yes

fmovm_data_in_done:
	add.l		%d0,%sp			# remove fpregs from stack
	rts

#####################################

fmovm_data_done:
	rts

##############################################################################

#
# table indexed by the operation's bit string that gives the number
# of bytes that will be moved.
#
# number of bytes = (# of 1's in bit string) * 12(bytes/fpreg)
#
tbl_fmovm_size:
	byte	0x00,0x0c,0x0c,0x18,0x0c,0x18,0x18,0x24
	byte	0x0c,0x18,0x18,0x24,0x18,0x24,0x24,0x30
	byte	0x0c,0x18,0x18,0x24,0x18,0x24,0x24,0x30
	byte	0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
	byte	0x0c,0x18,0x18,0x24,0x18,0x24,0x24,0x30
	byte	0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
	byte	0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
	byte	0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
	byte	0x0c,0x18,0x18,0x24,0x18,0x24,0x24,0x30
	byte	0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
	byte	0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
	byte	0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
	byte	0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
	byte	0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
	byte	0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
	byte	0x30,0x3c,0x3c,0x48,0x3c,0x48,0x48,0x54
	byte	0x0c,0x18,0x18,0x24,0x18,0x24,0x24,0x30
	byte	0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
	byte	0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
	byte	0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
	byte	0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
	byte	0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
	byte	0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
	byte	0x30,0x3c,0x3c,0x48,0x3c,0x48,0x48,0x54
	byte	0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
	byte	0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
	byte	0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
	byte	0x30,0x3c,0x3c,0x48,0x3c,0x48,0x48,0x54
	byte	0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
	byte	0x30,0x3c,0x3c,0x48,0x3c,0x48,0x48,0x54
	byte	0x30,0x3c,0x3c,0x48,0x3c,0x48,0x48,0x54
	byte	0x3c,0x48,0x48,0x54,0x48,0x54,0x54,0x60

#
# table to convert a pre-decrement bit string into a post-increment
# or control bit string.
# ex:	0x00	==>	0x00
#	0x01	==>	0x80
#	0x02	==>	0x40
#		.
#		.
#	0xfd	==>	0xbf
#	0xfe	==>	0x7f
#	0xff	==>	0xff
#
tbl_fmovm_convert:
	byte	0x00,0x80,0x40,0xc0,0x20,0xa0,0x60,0xe0
	byte	0x10,0x90,0x50,0xd0,0x30,0xb0,0x70,0xf0
	byte	0x08,0x88,0x48,0xc8,0x28,0xa8,0x68,0xe8
	byte	0x18,0x98,0x58,0xd8,0x38,0xb8,0x78,0xf8
	byte	0x04,0x84,0x44,0xc4,0x24,0xa4,0x64,0xe4
	byte	0x14,0x94,0x54,0xd4,0x34,0xb4,0x74,0xf4
	byte	0x0c,0x8c,0x4c,0xcc,0x2c,0xac,0x6c,0xec
	byte	0x1c,0x9c,0x5c,0xdc,0x3c,0xbc,0x7c,0xfc
	byte	0x02,0x82,0x42,0xc2,0x22,0xa2,0x62,0xe2
	byte	0x12,0x92,0x52,0xd2,0x32,0xb2,0x72,0xf2
	byte	0x0a,0x8a,0x4a,0xca,0x2a,0xaa,0x6a,0xea
	byte	0x1a,0x9a,0x5a,0xda,0x3a,0xba,0x7a,0xfa
	byte	0x06,0x86,0x46,0xc6,0x26,0xa6,0x66,0xe6
	byte	0x16,0x96,0x56,0xd6,0x36,0xb6,0x76,0xf6
	byte	0x0e,0x8e,0x4e,0xce,0x2e,0xae,0x6e,0xee
	byte	0x1e,0x9e,0x5e,0xde,0x3e,0xbe,0x7e,0xfe
	byte	0x01,0x81,0x41,0xc1,0x21,0xa1,0x61,0xe1
	byte	0x11,0x91,0x51,0xd1,0x31,0xb1,0x71,0xf1
	byte	0x09,0x89,0x49,0xc9,0x29,0xa9,0x69,0xe9
	byte	0x19,0x99,0x59,0xd9,0x39,0xb9,0x79,0xf9
	byte	0x05,0x85,0x45,0xc5,0x25,0xa5,0x65,0xe5
	byte	0x15,0x95,0x55,0xd5,0x35,0xb5,0x75,0xf5
	byte	0x0d,0x8d,0x4d,0xcd,0x2d,0xad,0x6d,0xed
	byte	0x1d,0x9d,0x5d,0xdd,0x3d,0xbd,0x7d,0xfd
	byte	0x03,0x83,0x43,0xc3,0x23,0xa3,0x63,0xe3
	byte	0x13,0x93,0x53,0xd3,0x33,0xb3,0x73,0xf3
	byte	0x0b,0x8b,0x4b,0xcb,0x2b,0xab,0x6b,0xeb
	byte	0x1b,0x9b,0x5b,0xdb,0x3b,0xbb,0x7b,0xfb
	byte	0x07,0x87,0x47,0xc7,0x27,0xa7,0x67,0xe7
	byte	0x17,0x97,0x57,0xd7,0x37,0xb7,0x77,0xf7
	byte	0x0f,0x8f,0x4f,0xcf,0x2f,0xaf,0x6f,0xef
	byte	0x1f,0x9f,0x5f,0xdf,0x3f,0xbf,0x7f,0xff

	global		fmovm_calc_ea
###############################################
# _fmovm_calc_ea: calculate effective address #
###############################################
fmovm_calc_ea:
	mov.l		%d0,%a0			# move # bytes to a0

# currently, MODE and REG are taken from the EXC_OPWORD. this could be
# easily changed if they were inputs passed in registers.
	mov.w		EXC_OPWORD(%a6),%d0	# fetch opcode word
	mov.w		%d0,%d1			# make a copy

	andi.w		&0x3f,%d0		# extract mode field
	andi.l		&0x7,%d1		# extract reg  field

# jump to the corresponding function for each {MODE,REG} pair.
	mov.w		(tbl_fea_mode.b,%pc,%d0.w*2),%d0 # fetch jmp distance
	jmp		(tbl_fea_mode.b,%pc,%d0.w*1) # jmp to correct ea mode

	swbeg		&64
tbl_fea_mode:
	short		tbl_fea_mode	-	tbl_fea_mode
	short		tbl_fea_mode	-	tbl_fea_mode
	short		tbl_fea_mode	-	tbl_fea_mode
	short		tbl_fea_mode	-	tbl_fea_mode
	short		tbl_fea_mode	-	tbl_fea_mode
	short		tbl_fea_mode	-	tbl_fea_mode
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -



