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