x_store.sa revision 1.2
11.1Smycroft*	MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
21.1Smycroft*	M68000 Hi-Performance Microprocessor Division
31.1Smycroft*	M68040 Software Package 
41.1Smycroft*
51.1Smycroft*	M68040 Software Package Copyright (c) 1993, 1994 Motorola Inc.
61.1Smycroft*	All rights reserved.
71.1Smycroft*
81.1Smycroft*	THE SOFTWARE is provided on an "AS IS" basis and without warranty.
91.1Smycroft*	To the maximum extent permitted by applicable law,
101.1Smycroft*	MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
111.1Smycroft*	INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A
121.1Smycroft*	PARTICULAR PURPOSE and any warranty against infringement with
131.1Smycroft*	regard to the SOFTWARE (INCLUDING ANY MODIFIED VERSIONS THEREOF)
141.1Smycroft*	and any accompanying written materials. 
151.1Smycroft*
161.1Smycroft*	To the maximum extent permitted by applicable law,
171.1Smycroft*	IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
181.1Smycroft*	(INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS
191.1Smycroft*	PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR
201.1Smycroft*	OTHER PECUNIARY LOSS) ARISING OF THE USE OR INABILITY TO USE THE
211.1Smycroft*	SOFTWARE.  Motorola assumes no responsibility for the maintenance
221.1Smycroft*	and support of the SOFTWARE.  
231.1Smycroft*
241.1Smycroft*	You are hereby granted a copyright license to use, modify, and
251.1Smycroft*	distribute the SOFTWARE so long as this entire notice is retained
261.1Smycroft*	without alteration in any modified and/or redistributed versions,
271.1Smycroft*	and that such modified versions are clearly identified as such.
281.1Smycroft*	No licenses are granted by implication, estoppel or otherwise
291.1Smycroft*	under any patents or trademarks of Motorola, Inc.
301.1Smycroft
311.1Smycroft*
321.1Smycroft*	x_store.sa 3.2 1/24/91
331.1Smycroft*
341.1Smycroft*	store --- store operand to memory or register
351.1Smycroft*
361.1Smycroft*	Used by underflow and overflow handlers.
371.1Smycroft*
381.1Smycroft*	a6 = points to fp value to be stored.
391.1Smycroft*
401.1Smycroft
411.1SmycroftX_STORE	IDNT    2,1 Motorola 040 Floating Point Software Package
421.1Smycroft
431.1Smycroft	section	8
441.1Smycroft
451.1Smycroftfpreg_mask:
461.1Smycroft	dc.b	$80,$40,$20,$10,$08,$04,$02,$01
471.1Smycroft
481.1Smycroft	include	fpsp.h
491.1Smycroft
501.1Smycroft	xref	mem_write
511.1Smycroft	xref	get_fline
521.1Smycroft	xref	g_opcls
531.1Smycroft	xref	g_dfmtou
541.1Smycroft	xref	reg_dest
551.1Smycroft
561.1Smycroft	xdef	dest_ext
571.1Smycroft	xdef	dest_dbl
581.1Smycroft	xdef	dest_sgl
591.1Smycroft
601.1Smycroft	xdef	store
611.1Smycroftstore:
621.1Smycroft	btst.b	#E3,E_BYTE(a6)
631.1Smycroft	beq.b	E1_sto
641.1SmycroftE3_sto:
651.1Smycroft	move.l	CMDREG3B(a6),d0
661.1Smycroft	bfextu	d0{6:3},d0		;isolate dest. reg from cmdreg3b
671.1Smycroftsto_fp:
681.1Smycroft	lea	fpreg_mask,a1
691.1Smycroft	move.b	(a1,d0.w),d0		;convert reg# to dynamic register mask
701.1Smycroft	tst.b	LOCAL_SGN(a0)
711.1Smycroft	beq.b	is_pos
721.1Smycroft	bset.b	#sign_bit,LOCAL_EX(a0)
731.1Smycroftis_pos:
741.1Smycroft	fmovem.x (a0),d0		;move to correct register
751.1Smycroft*
761.1Smycroft*	if fp0-fp3 is being modified, we must put a copy
771.1Smycroft*	in the USER_FPn variable on the stack because all exception
781.1Smycroft*	handlers restore fp0-fp3 from there.
791.1Smycroft*
801.1Smycroft	cmp.b	#$80,d0		
811.1Smycroft	bne.b	not_fp0
821.1Smycroft	fmovem.x fp0,USER_FP0(a6)
831.1Smycroft	rts
841.1Smycroftnot_fp0:
851.1Smycroft	cmp.b	#$40,d0
861.1Smycroft	bne.b	not_fp1
871.1Smycroft	fmovem.x fp1,USER_FP1(a6)
881.1Smycroft	rts
891.1Smycroftnot_fp1:
901.1Smycroft	cmp.b	#$20,d0
911.1Smycroft	bne.b	not_fp2
921.1Smycroft	fmovem.x fp2,USER_FP2(a6)
931.1Smycroft	rts
941.1Smycroftnot_fp2:
951.1Smycroft	cmp.b	#$10,d0
961.1Smycroft	bne.b	not_fp3
971.1Smycroft	fmovem.x fp3,USER_FP3(a6)
981.1Smycroft	rts
991.1Smycroftnot_fp3:
1001.1Smycroft	rts
1011.1Smycroft
1021.1SmycroftE1_sto:
1031.1Smycroft	bsr.l	g_opcls		;returns opclass in d0
1041.1Smycroft	cmpi.b	#3,d0
1051.1Smycroft	beq	opc011		;branch if opclass 3
1061.1Smycroft	move.l	CMDREG1B(a6),d0
1071.1Smycroft	bfextu	d0{6:3},d0	;extract destination register
1081.1Smycroft	bra.b	sto_fp
1091.1Smycroft
1101.1Smycroftopc011:
1111.1Smycroft	bsr.l	g_dfmtou	;returns dest format in d0
1121.1Smycroft*				;ext=00, sgl=01, dbl=10
1131.1Smycroft	move.l	a0,a1		;save source addr in a1
1141.1Smycroft	move.l	EXC_EA(a6),a0	;get the address
1151.2Smycroft	tst.l	d0		;if dest format is extended
1161.1Smycroft	beq.w	dest_ext	;then branch
1171.1Smycroft	cmpi.l	#1,d0		;if dest format is single
1181.1Smycroft	beq.b	dest_sgl	;then branch
1191.1Smycroft*
1201.1Smycroft*	fall through to dest_dbl
1211.1Smycroft*
1221.1Smycroft
1231.1Smycroft*
1241.1Smycroft*	dest_dbl --- write double precision value to user space
1251.1Smycroft*
1261.1Smycroft*Input
1271.1Smycroft*	a0 -> destination address
1281.1Smycroft*	a1 -> source in extended precision
1291.1Smycroft*Output
1301.1Smycroft*	a0 -> destroyed
1311.1Smycroft*	a1 -> destroyed
1321.1Smycroft*	d0 -> 0
1331.1Smycroft*
1341.1Smycroft*Changes extended precision to double precision.
1351.1Smycroft* Note: no attempt is made to round the extended value to double.
1361.1Smycroft*	dbl_sign = ext_sign
1371.1Smycroft*	dbl_exp = ext_exp - $3fff(ext bias) + $7ff(dbl bias)
1381.1Smycroft*	get rid of ext integer bit
1391.1Smycroft*	dbl_mant = ext_mant{62:12}
1401.1Smycroft*
1411.1Smycroft*	    	---------------   ---------------    ---------------
1421.1Smycroft*  extended ->  |s|    exp    |   |1| ms mant   |    | ls mant     |
1431.1Smycroft*	    	---------------   ---------------    ---------------
1441.1Smycroft*	   	 95	    64    63 62	      32      31     11	  0
1451.1Smycroft*				     |			     |
1461.1Smycroft*				     |			     |
1471.1Smycroft*				     |			     |
1481.1Smycroft*		 	             v   		     v
1491.1Smycroft*	    		      ---------------   ---------------
1501.1Smycroft*  double   ->  	      |s|exp| mant  |   |  mant       |
1511.1Smycroft*	    		      ---------------   ---------------
1521.1Smycroft*	   	 	      63     51   32   31	       0
1531.1Smycroft*
1541.1Smycroftdest_dbl:
1551.1Smycroft	clr.l	d0		;clear d0
1561.1Smycroft	move.w	LOCAL_EX(a1),d0	;get exponent
1571.1Smycroft	sub.w	#$3fff,d0	;subtract extended precision bias
1581.1Smycroft	cmp.w	#$4000,d0	;check if inf
1591.1Smycroft	beq.b	inf		;if so, special case
1601.1Smycroft	add.w	#$3ff,d0	;add double precision bias
1611.1Smycroft	swap	d0		;d0 now in upper word
1621.1Smycroft	lsl.l	#4,d0		;d0 now in proper place for dbl prec exp
1631.1Smycroft	tst.b	LOCAL_SGN(a1)	
1641.1Smycroft	beq.b	get_mant	;if postive, go process mantissa
1651.1Smycroft	bset.l	#31,d0		;if negative, put in sign information
1661.1Smycroft*				; before continuing
1671.1Smycroft	bra.b	get_mant	;go process mantissa
1681.1Smycroftinf:
1691.1Smycroft	move.l	#$7ff00000,d0	;load dbl inf exponent
1701.1Smycroft	clr.l	LOCAL_HI(a1)	;clear msb
1711.1Smycroft	tst.b	LOCAL_SGN(a1)
1721.1Smycroft	beq.b	dbl_inf		;if positive, go ahead and write it
1731.1Smycroft	bset.l	#31,d0		;if negative put in sign information
1741.1Smycroftdbl_inf:
1751.1Smycroft	move.l	d0,LOCAL_EX(a1)	;put the new exp back on the stack
1761.1Smycroft	bra.b	dbl_wrt
1771.1Smycroftget_mant:
1781.1Smycroft	move.l	LOCAL_HI(a1),d1	;get ms mantissa
1791.1Smycroft	bfextu	d1{1:20},d1	;get upper 20 bits of ms
1801.1Smycroft	or.l	d1,d0		;put these bits in ms word of double
1811.1Smycroft	move.l	d0,LOCAL_EX(a1)	;put the new exp back on the stack
1821.1Smycroft	move.l	LOCAL_HI(a1),d1	;get ms mantissa
1831.1Smycroft	move.l	#21,d0		;load shift count
1841.1Smycroft	lsl.l	d0,d1		;put lower 11 bits in upper bits
1851.1Smycroft	move.l	d1,LOCAL_HI(a1)	;build lower lword in memory
1861.1Smycroft	move.l	LOCAL_LO(a1),d1	;get ls mantissa
1871.1Smycroft	bfextu	d1{0:21},d0	;get ls 21 bits of double
1881.1Smycroft	or.l	d0,LOCAL_HI(a1)	;put them in double result
1891.1Smycroftdbl_wrt:
1901.1Smycroft	move.l	#$8,d0		;byte count for double precision number
1911.1Smycroft	exg	a0,a1		;a0=supervisor source, a1=user dest
1921.1Smycroft	bsr.l	mem_write	;move the number to the user's memory
1931.1Smycroft	rts
1941.1Smycroft*
1951.1Smycroft*	dest_sgl --- write single precision value to user space
1961.1Smycroft*
1971.1Smycroft*Input
1981.1Smycroft*	a0 -> destination address
1991.1Smycroft*	a1 -> source in extended precision
2001.1Smycroft*
2011.1Smycroft*Output
2021.1Smycroft*	a0 -> destroyed
2031.1Smycroft*	a1 -> destroyed
2041.1Smycroft*	d0 -> 0
2051.1Smycroft*
2061.1Smycroft*Changes extended precision to single precision.
2071.1Smycroft*	sgl_sign = ext_sign
2081.1Smycroft*	sgl_exp = ext_exp - $3fff(ext bias) + $7f(sgl bias)
2091.1Smycroft*	get rid of ext integer bit
2101.1Smycroft*	sgl_mant = ext_mant{62:12}
2111.1Smycroft*
2121.1Smycroft*	    	---------------   ---------------    ---------------
2131.1Smycroft*  extended ->  |s|    exp    |   |1| ms mant   |    | ls mant     |
2141.1Smycroft*	    	---------------   ---------------    ---------------
2151.1Smycroft*	   	 95	    64    63 62	   40 32      31     12	  0
2161.1Smycroft*				     |	   |
2171.1Smycroft*				     |	   |
2181.1Smycroft*				     |	   |
2191.1Smycroft*		 	             v     v
2201.1Smycroft*	    		      ---------------
2211.1Smycroft*  single   ->  	      |s|exp| mant  |
2221.1Smycroft*	    		      ---------------
2231.1Smycroft*	   	 	      31     22     0
2241.1Smycroft*
2251.1Smycroftdest_sgl:
2261.1Smycroft	clr.l	d0
2271.1Smycroft	move.w	LOCAL_EX(a1),d0	;get exponent
2281.1Smycroft	sub.w	#$3fff,d0	;subtract extended precision bias
2291.1Smycroft	cmp.w	#$4000,d0	;check if inf
2301.1Smycroft	beq.b	sinf		;if so, special case
2311.1Smycroft	add.w	#$7f,d0		;add single precision bias
2321.1Smycroft	swap	d0		;put exp in upper word of d0
2331.1Smycroft	lsl.l	#7,d0		;shift it into single exp bits
2341.1Smycroft	tst.b	LOCAL_SGN(a1)	
2351.1Smycroft	beq.b	get_sman	;if positive, continue
2361.1Smycroft	bset.l	#31,d0		;if negative, put in sign first
2371.1Smycroft	bra.b	get_sman	;get mantissa
2381.1Smycroftsinf:
2391.1Smycroft	move.l	#$7f800000,d0	;load single inf exp to d0
2401.1Smycroft	tst.b	LOCAL_SGN(a1)
2411.1Smycroft	beq.b	sgl_wrt		;if positive, continue
2421.1Smycroft	bset.l	#31,d0		;if negative, put in sign info
2431.1Smycroft	bra.b	sgl_wrt
2441.1Smycroft
2451.1Smycroftget_sman:
2461.1Smycroft	move.l	LOCAL_HI(a1),d1	;get ms mantissa
2471.1Smycroft	bfextu	d1{1:23},d1	;get upper 23 bits of ms
2481.1Smycroft	or.l	d1,d0		;put these bits in ms word of single
2491.1Smycroft
2501.1Smycroftsgl_wrt:
2511.1Smycroft	move.l	d0,L_SCR1(a6)	;put the new exp back on the stack
2521.1Smycroft	move.l	#$4,d0		;byte count for single precision number
2531.1Smycroft	tst.l	a0		;users destination address
2541.1Smycroft	beq.b	sgl_Dn		;destination is a data register
2551.1Smycroft	exg	a0,a1		;a0=supervisor source, a1=user dest
2561.1Smycroft	lea.l	L_SCR1(a6),a0	;point a0 to data
2571.1Smycroft	bsr.l	mem_write	;move the number to the user's memory
2581.1Smycroft	rts
2591.1Smycroftsgl_Dn:
2601.1Smycroft	bsr.l	get_fline	;returns fline word in d0
2611.1Smycroft	and.w	#$7,d0		;isolate register number
2621.1Smycroft	move.l	d0,d1		;d1 has size:reg formatted for reg_dest
2631.1Smycroft	or.l	#$10,d1		;reg_dest wants size added to reg#
2641.1Smycroft	bra.l	reg_dest	;size is X, rts in reg_dest will
2651.1Smycroft*				;return to caller of dest_sgl
2661.1Smycroft	
2671.1Smycroftdest_ext:
2681.1Smycroft	tst.b	LOCAL_SGN(a1)	;put back sign into exponent word
2691.1Smycroft	beq.b	dstx_cont
2701.1Smycroft	bset.b	#sign_bit,LOCAL_EX(a1)
2711.1Smycroftdstx_cont:
2721.1Smycroft	clr.b	LOCAL_SGN(a1)	;clear out the sign byte
2731.1Smycroft
2741.1Smycroft	move.l	#$0c,d0		;byte count for extended number
2751.1Smycroft	exg	a0,a1		;a0=supervisor source, a1=user dest
2761.1Smycroft	bsr.l	mem_write	;move the number to the user's memory
2771.1Smycroft	rts
2781.1Smycroft
2791.1Smycroft	end
280