18c2ecf20Sopenharmony_ci|
28c2ecf20Sopenharmony_ci|	x_store.sa 3.2 1/24/91
38c2ecf20Sopenharmony_ci|
48c2ecf20Sopenharmony_ci|	store --- store operand to memory or register
58c2ecf20Sopenharmony_ci|
68c2ecf20Sopenharmony_ci|	Used by underflow and overflow handlers.
78c2ecf20Sopenharmony_ci|
88c2ecf20Sopenharmony_ci|	a6 = points to fp value to be stored.
98c2ecf20Sopenharmony_ci|
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci|		Copyright (C) Motorola, Inc. 1990
128c2ecf20Sopenharmony_ci|			All Rights Reserved
138c2ecf20Sopenharmony_ci|
148c2ecf20Sopenharmony_ci|       For details on the license for this file, please see the
158c2ecf20Sopenharmony_ci|       file, README, in this same directory.
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ciX_STORE:	|idnt    2,1 | Motorola 040 Floating Point Software Package
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci	|section	8
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_cifpreg_mask:
228c2ecf20Sopenharmony_ci	.byte	0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_ci#include "fpsp.h"
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci	|xref	mem_write
278c2ecf20Sopenharmony_ci	|xref	get_fline
288c2ecf20Sopenharmony_ci	|xref	g_opcls
298c2ecf20Sopenharmony_ci	|xref	g_dfmtou
308c2ecf20Sopenharmony_ci	|xref	reg_dest
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci	.global	dest_ext
338c2ecf20Sopenharmony_ci	.global	dest_dbl
348c2ecf20Sopenharmony_ci	.global	dest_sgl
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci	.global	store
378c2ecf20Sopenharmony_cistore:
388c2ecf20Sopenharmony_ci	btstb	#E3,E_BYTE(%a6)
398c2ecf20Sopenharmony_ci	beqs	E1_sto
408c2ecf20Sopenharmony_ciE3_sto:
418c2ecf20Sopenharmony_ci	movel	CMDREG3B(%a6),%d0
428c2ecf20Sopenharmony_ci	bfextu	%d0{#6:#3},%d0		|isolate dest. reg from cmdreg3b
438c2ecf20Sopenharmony_cisto_fp:
448c2ecf20Sopenharmony_ci	lea	fpreg_mask,%a1
458c2ecf20Sopenharmony_ci	moveb	(%a1,%d0.w),%d0		|convert reg# to dynamic register mask
468c2ecf20Sopenharmony_ci	tstb	LOCAL_SGN(%a0)
478c2ecf20Sopenharmony_ci	beqs	is_pos
488c2ecf20Sopenharmony_ci	bsetb	#sign_bit,LOCAL_EX(%a0)
498c2ecf20Sopenharmony_ciis_pos:
508c2ecf20Sopenharmony_ci	fmovemx (%a0),%d0		|move to correct register
518c2ecf20Sopenharmony_ci|
528c2ecf20Sopenharmony_ci|	if fp0-fp3 is being modified, we must put a copy
538c2ecf20Sopenharmony_ci|	in the USER_FPn variable on the stack because all exception
548c2ecf20Sopenharmony_ci|	handlers restore fp0-fp3 from there.
558c2ecf20Sopenharmony_ci|
568c2ecf20Sopenharmony_ci	cmpb	#0x80,%d0
578c2ecf20Sopenharmony_ci	bnes	not_fp0
588c2ecf20Sopenharmony_ci	fmovemx %fp0-%fp0,USER_FP0(%a6)
598c2ecf20Sopenharmony_ci	rts
608c2ecf20Sopenharmony_cinot_fp0:
618c2ecf20Sopenharmony_ci	cmpb	#0x40,%d0
628c2ecf20Sopenharmony_ci	bnes	not_fp1
638c2ecf20Sopenharmony_ci	fmovemx %fp1-%fp1,USER_FP1(%a6)
648c2ecf20Sopenharmony_ci	rts
658c2ecf20Sopenharmony_cinot_fp1:
668c2ecf20Sopenharmony_ci	cmpb	#0x20,%d0
678c2ecf20Sopenharmony_ci	bnes	not_fp2
688c2ecf20Sopenharmony_ci	fmovemx %fp2-%fp2,USER_FP2(%a6)
698c2ecf20Sopenharmony_ci	rts
708c2ecf20Sopenharmony_cinot_fp2:
718c2ecf20Sopenharmony_ci	cmpb	#0x10,%d0
728c2ecf20Sopenharmony_ci	bnes	not_fp3
738c2ecf20Sopenharmony_ci	fmovemx %fp3-%fp3,USER_FP3(%a6)
748c2ecf20Sopenharmony_ci	rts
758c2ecf20Sopenharmony_cinot_fp3:
768c2ecf20Sopenharmony_ci	rts
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ciE1_sto:
798c2ecf20Sopenharmony_ci	bsrl	g_opcls		|returns opclass in d0
808c2ecf20Sopenharmony_ci	cmpib	#3,%d0
818c2ecf20Sopenharmony_ci	beq	opc011		|branch if opclass 3
828c2ecf20Sopenharmony_ci	movel	CMDREG1B(%a6),%d0
838c2ecf20Sopenharmony_ci	bfextu	%d0{#6:#3},%d0	|extract destination register
848c2ecf20Sopenharmony_ci	bras	sto_fp
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ciopc011:
878c2ecf20Sopenharmony_ci	bsrl	g_dfmtou	|returns dest format in d0
888c2ecf20Sopenharmony_ci|				;ext=00, sgl=01, dbl=10
898c2ecf20Sopenharmony_ci	movel	%a0,%a1		|save source addr in a1
908c2ecf20Sopenharmony_ci	movel	EXC_EA(%a6),%a0	|get the address
918c2ecf20Sopenharmony_ci	cmpil	#0,%d0		|if dest format is extended
928c2ecf20Sopenharmony_ci	beq	dest_ext	|then branch
938c2ecf20Sopenharmony_ci	cmpil	#1,%d0		|if dest format is single
948c2ecf20Sopenharmony_ci	beq	dest_sgl	|then branch
958c2ecf20Sopenharmony_ci|
968c2ecf20Sopenharmony_ci|	fall through to dest_dbl
978c2ecf20Sopenharmony_ci|
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_ci|
1008c2ecf20Sopenharmony_ci|	dest_dbl --- write double precision value to user space
1018c2ecf20Sopenharmony_ci|
1028c2ecf20Sopenharmony_ci|Input
1038c2ecf20Sopenharmony_ci|	a0 -> destination address
1048c2ecf20Sopenharmony_ci|	a1 -> source in extended precision
1058c2ecf20Sopenharmony_ci|Output
1068c2ecf20Sopenharmony_ci|	a0 -> destroyed
1078c2ecf20Sopenharmony_ci|	a1 -> destroyed
1088c2ecf20Sopenharmony_ci|	d0 -> 0
1098c2ecf20Sopenharmony_ci|
1108c2ecf20Sopenharmony_ci|Changes extended precision to double precision.
1118c2ecf20Sopenharmony_ci| Note: no attempt is made to round the extended value to double.
1128c2ecf20Sopenharmony_ci|	dbl_sign = ext_sign
1138c2ecf20Sopenharmony_ci|	dbl_exp = ext_exp - $3fff(ext bias) + $7ff(dbl bias)
1148c2ecf20Sopenharmony_ci|	get rid of ext integer bit
1158c2ecf20Sopenharmony_ci|	dbl_mant = ext_mant{62:12}
1168c2ecf20Sopenharmony_ci|
1178c2ecf20Sopenharmony_ci|		---------------   ---------------    ---------------
1188c2ecf20Sopenharmony_ci|  extended ->  |s|    exp    |   |1| ms mant   |    | ls mant     |
1198c2ecf20Sopenharmony_ci|		---------------   ---------------    ---------------
1208c2ecf20Sopenharmony_ci|		 95	    64    63 62	      32      31     11	  0
1218c2ecf20Sopenharmony_ci|				     |			     |
1228c2ecf20Sopenharmony_ci|				     |			     |
1238c2ecf20Sopenharmony_ci|				     |			     |
1248c2ecf20Sopenharmony_ci|			             v			     v
1258c2ecf20Sopenharmony_ci|			      ---------------   ---------------
1268c2ecf20Sopenharmony_ci|  double   ->		      |s|exp| mant  |   |  mant       |
1278c2ecf20Sopenharmony_ci|			      ---------------   ---------------
1288c2ecf20Sopenharmony_ci|			      63     51   32   31	       0
1298c2ecf20Sopenharmony_ci|
1308c2ecf20Sopenharmony_cidest_dbl:
1318c2ecf20Sopenharmony_ci	clrl	%d0		|clear d0
1328c2ecf20Sopenharmony_ci	movew	LOCAL_EX(%a1),%d0	|get exponent
1338c2ecf20Sopenharmony_ci	subw	#0x3fff,%d0	|subtract extended precision bias
1348c2ecf20Sopenharmony_ci	cmpw	#0x4000,%d0	|check if inf
1358c2ecf20Sopenharmony_ci	beqs	inf		|if so, special case
1368c2ecf20Sopenharmony_ci	addw	#0x3ff,%d0	|add double precision bias
1378c2ecf20Sopenharmony_ci	swap	%d0		|d0 now in upper word
1388c2ecf20Sopenharmony_ci	lsll	#4,%d0		|d0 now in proper place for dbl prec exp
1398c2ecf20Sopenharmony_ci	tstb	LOCAL_SGN(%a1)
1408c2ecf20Sopenharmony_ci	beqs	get_mant	|if positive, go process mantissa
1418c2ecf20Sopenharmony_ci	bsetl	#31,%d0		|if negative, put in sign information
1428c2ecf20Sopenharmony_ci|				; before continuing
1438c2ecf20Sopenharmony_ci	bras	get_mant	|go process mantissa
1448c2ecf20Sopenharmony_ciinf:
1458c2ecf20Sopenharmony_ci	movel	#0x7ff00000,%d0	|load dbl inf exponent
1468c2ecf20Sopenharmony_ci	clrl	LOCAL_HI(%a1)	|clear msb
1478c2ecf20Sopenharmony_ci	tstb	LOCAL_SGN(%a1)
1488c2ecf20Sopenharmony_ci	beqs	dbl_inf		|if positive, go ahead and write it
1498c2ecf20Sopenharmony_ci	bsetl	#31,%d0		|if negative put in sign information
1508c2ecf20Sopenharmony_cidbl_inf:
1518c2ecf20Sopenharmony_ci	movel	%d0,LOCAL_EX(%a1)	|put the new exp back on the stack
1528c2ecf20Sopenharmony_ci	bras	dbl_wrt
1538c2ecf20Sopenharmony_ciget_mant:
1548c2ecf20Sopenharmony_ci	movel	LOCAL_HI(%a1),%d1	|get ms mantissa
1558c2ecf20Sopenharmony_ci	bfextu	%d1{#1:#20},%d1	|get upper 20 bits of ms
1568c2ecf20Sopenharmony_ci	orl	%d1,%d0		|put these bits in ms word of double
1578c2ecf20Sopenharmony_ci	movel	%d0,LOCAL_EX(%a1)	|put the new exp back on the stack
1588c2ecf20Sopenharmony_ci	movel	LOCAL_HI(%a1),%d1	|get ms mantissa
1598c2ecf20Sopenharmony_ci	movel	#21,%d0		|load shift count
1608c2ecf20Sopenharmony_ci	lsll	%d0,%d1		|put lower 11 bits in upper bits
1618c2ecf20Sopenharmony_ci	movel	%d1,LOCAL_HI(%a1)	|build lower lword in memory
1628c2ecf20Sopenharmony_ci	movel	LOCAL_LO(%a1),%d1	|get ls mantissa
1638c2ecf20Sopenharmony_ci	bfextu	%d1{#0:#21},%d0	|get ls 21 bits of double
1648c2ecf20Sopenharmony_ci	orl	%d0,LOCAL_HI(%a1)	|put them in double result
1658c2ecf20Sopenharmony_cidbl_wrt:
1668c2ecf20Sopenharmony_ci	movel	#0x8,%d0		|byte count for double precision number
1678c2ecf20Sopenharmony_ci	exg	%a0,%a1		|a0=supervisor source, a1=user dest
1688c2ecf20Sopenharmony_ci	bsrl	mem_write	|move the number to the user's memory
1698c2ecf20Sopenharmony_ci	rts
1708c2ecf20Sopenharmony_ci|
1718c2ecf20Sopenharmony_ci|	dest_sgl --- write single precision value to user space
1728c2ecf20Sopenharmony_ci|
1738c2ecf20Sopenharmony_ci|Input
1748c2ecf20Sopenharmony_ci|	a0 -> destination address
1758c2ecf20Sopenharmony_ci|	a1 -> source in extended precision
1768c2ecf20Sopenharmony_ci|
1778c2ecf20Sopenharmony_ci|Output
1788c2ecf20Sopenharmony_ci|	a0 -> destroyed
1798c2ecf20Sopenharmony_ci|	a1 -> destroyed
1808c2ecf20Sopenharmony_ci|	d0 -> 0
1818c2ecf20Sopenharmony_ci|
1828c2ecf20Sopenharmony_ci|Changes extended precision to single precision.
1838c2ecf20Sopenharmony_ci|	sgl_sign = ext_sign
1848c2ecf20Sopenharmony_ci|	sgl_exp = ext_exp - $3fff(ext bias) + $7f(sgl bias)
1858c2ecf20Sopenharmony_ci|	get rid of ext integer bit
1868c2ecf20Sopenharmony_ci|	sgl_mant = ext_mant{62:12}
1878c2ecf20Sopenharmony_ci|
1888c2ecf20Sopenharmony_ci|		---------------   ---------------    ---------------
1898c2ecf20Sopenharmony_ci|  extended ->  |s|    exp    |   |1| ms mant   |    | ls mant     |
1908c2ecf20Sopenharmony_ci|		---------------   ---------------    ---------------
1918c2ecf20Sopenharmony_ci|		 95	    64    63 62	   40 32      31     12	  0
1928c2ecf20Sopenharmony_ci|				     |	   |
1938c2ecf20Sopenharmony_ci|				     |	   |
1948c2ecf20Sopenharmony_ci|				     |	   |
1958c2ecf20Sopenharmony_ci|			             v     v
1968c2ecf20Sopenharmony_ci|			      ---------------
1978c2ecf20Sopenharmony_ci|  single   ->		      |s|exp| mant  |
1988c2ecf20Sopenharmony_ci|			      ---------------
1998c2ecf20Sopenharmony_ci|			      31     22     0
2008c2ecf20Sopenharmony_ci|
2018c2ecf20Sopenharmony_cidest_sgl:
2028c2ecf20Sopenharmony_ci	clrl	%d0
2038c2ecf20Sopenharmony_ci	movew	LOCAL_EX(%a1),%d0	|get exponent
2048c2ecf20Sopenharmony_ci	subw	#0x3fff,%d0	|subtract extended precision bias
2058c2ecf20Sopenharmony_ci	cmpw	#0x4000,%d0	|check if inf
2068c2ecf20Sopenharmony_ci	beqs	sinf		|if so, special case
2078c2ecf20Sopenharmony_ci	addw	#0x7f,%d0		|add single precision bias
2088c2ecf20Sopenharmony_ci	swap	%d0		|put exp in upper word of d0
2098c2ecf20Sopenharmony_ci	lsll	#7,%d0		|shift it into single exp bits
2108c2ecf20Sopenharmony_ci	tstb	LOCAL_SGN(%a1)
2118c2ecf20Sopenharmony_ci	beqs	get_sman	|if positive, continue
2128c2ecf20Sopenharmony_ci	bsetl	#31,%d0		|if negative, put in sign first
2138c2ecf20Sopenharmony_ci	bras	get_sman	|get mantissa
2148c2ecf20Sopenharmony_cisinf:
2158c2ecf20Sopenharmony_ci	movel	#0x7f800000,%d0	|load single inf exp to d0
2168c2ecf20Sopenharmony_ci	tstb	LOCAL_SGN(%a1)
2178c2ecf20Sopenharmony_ci	beqs	sgl_wrt		|if positive, continue
2188c2ecf20Sopenharmony_ci	bsetl	#31,%d0		|if negative, put in sign info
2198c2ecf20Sopenharmony_ci	bras	sgl_wrt
2208c2ecf20Sopenharmony_ci
2218c2ecf20Sopenharmony_ciget_sman:
2228c2ecf20Sopenharmony_ci	movel	LOCAL_HI(%a1),%d1	|get ms mantissa
2238c2ecf20Sopenharmony_ci	bfextu	%d1{#1:#23},%d1	|get upper 23 bits of ms
2248c2ecf20Sopenharmony_ci	orl	%d1,%d0		|put these bits in ms word of single
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_cisgl_wrt:
2278c2ecf20Sopenharmony_ci	movel	%d0,L_SCR1(%a6)	|put the new exp back on the stack
2288c2ecf20Sopenharmony_ci	movel	#0x4,%d0		|byte count for single precision number
2298c2ecf20Sopenharmony_ci	tstl	%a0		|users destination address
2308c2ecf20Sopenharmony_ci	beqs	sgl_Dn		|destination is a data register
2318c2ecf20Sopenharmony_ci	exg	%a0,%a1		|a0=supervisor source, a1=user dest
2328c2ecf20Sopenharmony_ci	leal	L_SCR1(%a6),%a0	|point a0 to data
2338c2ecf20Sopenharmony_ci	bsrl	mem_write	|move the number to the user's memory
2348c2ecf20Sopenharmony_ci	rts
2358c2ecf20Sopenharmony_cisgl_Dn:
2368c2ecf20Sopenharmony_ci	bsrl	get_fline	|returns fline word in d0
2378c2ecf20Sopenharmony_ci	andw	#0x7,%d0		|isolate register number
2388c2ecf20Sopenharmony_ci	movel	%d0,%d1		|d1 has size:reg formatted for reg_dest
2398c2ecf20Sopenharmony_ci	orl	#0x10,%d1		|reg_dest wants size added to reg#
2408c2ecf20Sopenharmony_ci	bral	reg_dest	|size is X, rts in reg_dest will
2418c2ecf20Sopenharmony_ci|				;return to caller of dest_sgl
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_cidest_ext:
2448c2ecf20Sopenharmony_ci	tstb	LOCAL_SGN(%a1)	|put back sign into exponent word
2458c2ecf20Sopenharmony_ci	beqs	dstx_cont
2468c2ecf20Sopenharmony_ci	bsetb	#sign_bit,LOCAL_EX(%a1)
2478c2ecf20Sopenharmony_cidstx_cont:
2488c2ecf20Sopenharmony_ci	clrb	LOCAL_SGN(%a1)	|clear out the sign byte
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_ci	movel	#0x0c,%d0		|byte count for extended number
2518c2ecf20Sopenharmony_ci	exg	%a0,%a1		|a0=supervisor source, a1=user dest
2528c2ecf20Sopenharmony_ci	bsrl	mem_write	|move the number to the user's memory
2538c2ecf20Sopenharmony_ci	rts
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_ci	|end
256