1|
2|	x_store.sa 3.2 1/24/91
3|
4|	store --- store operand to memory or register
5|
6|	Used by underflow and overflow handlers.
7|
8|	a6 = points to fp value to be stored.
9|
10
11|		Copyright (C) Motorola, Inc. 1990
12|			All Rights Reserved
13|
14|	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
15|	The copyright notice above does not evidence any
16|	actual or intended publication of such source code.
17
18X_STORE:	|idnt    2,1 | Motorola 040 Floating Point Software Package
19
20	|section	8
21
22fpreg_mask:
23	.byte	0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01
24
25	.include "fpsp.h"
26
27	|xref	mem_write
28	|xref	get_fline
29	|xref	g_opcls
30	|xref	g_dfmtou
31	|xref	reg_dest
32
33	.global	dest_ext
34	.global	dest_dbl
35	.global	dest_sgl
36
37	.global	store
38store:
39	btstb	#E3,E_BYTE(%a6)
40	beqs	E1_sto
41E3_sto:
42	movel	CMDREG3B(%a6),%d0
43	bfextu	%d0{#6:#3},%d0		|isolate dest. reg from cmdreg3b
44sto_fp:
45	lea	fpreg_mask,%a1
46	moveb	(%a1,%d0.w),%d0		|convert reg# to dynamic register mask
47	tstb	LOCAL_SGN(%a0)
48	beqs	is_pos
49	bsetb	#sign_bit,LOCAL_EX(%a0)
50is_pos:
51	fmovemx (%a0),%d0		|move to correct register
52|
53|	if fp0-fp3 is being modified, we must put a copy
54|	in the USER_FPn variable on the stack because all exception
55|	handlers restore fp0-fp3 from there.
56|
57	cmpb	#0x80,%d0
58	bnes	not_fp0
59	fmovemx %fp0-%fp0,USER_FP0(%a6)
60	rts
61not_fp0:
62	cmpb	#0x40,%d0
63	bnes	not_fp1
64	fmovemx %fp1-%fp1,USER_FP1(%a6)
65	rts
66not_fp1:
67	cmpb	#0x20,%d0
68	bnes	not_fp2
69	fmovemx %fp2-%fp2,USER_FP2(%a6)
70	rts
71not_fp2:
72	cmpb	#0x10,%d0
73	bnes	not_fp3
74	fmovemx %fp3-%fp3,USER_FP3(%a6)
75	rts
76not_fp3:
77	rts
78
79E1_sto:
80	bsrl	g_opcls		|returns opclass in d0
81	cmpib	#3,%d0
82	beq	opc011		|branch if opclass 3
83	movel	CMDREG1B(%a6),%d0
84	bfextu	%d0{#6:#3},%d0	|extract destination register
85	bras	sto_fp
86
87opc011:
88	bsrl	g_dfmtou	|returns dest format in d0
89|				;ext=00, sgl=01, dbl=10
90	movel	%a0,%a1		|save source addr in a1
91	movel	EXC_EA(%a6),%a0	|get the address
92	cmpil	#0,%d0		|if dest format is extended
93	beq	dest_ext	|then branch
94	cmpil	#1,%d0		|if dest format is single
95	beq	dest_sgl	|then branch
96|
97|	fall through to dest_dbl
98|
99
100|
101|	dest_dbl --- write double precision value to user space
102|
103|Input
104|	a0 -> destination address
105|	a1 -> source in extended precision
106|Output
107|	a0 -> destroyed
108|	a1 -> destroyed
109|	d0 -> 0
110|
111|Changes extended precision to double precision.
112| Note: no attempt is made to round the extended value to double.
113|	dbl_sign = ext_sign
114|	dbl_exp = ext_exp - $3fff(ext bias) + $7ff(dbl bias)
115|	get rid of ext integer bit
116|	dbl_mant = ext_mant{62:12}
117|
118|	    	---------------   ---------------    ---------------
119|  extended ->  |s|    exp    |   |1| ms mant   |    | ls mant     |
120|	    	---------------   ---------------    ---------------
121|	   	 95	    64    63 62	      32      31     11	  0
122|				     |			     |
123|				     |			     |
124|				     |			     |
125|		 	             v   		     v
126|	    		      ---------------   ---------------
127|  double   ->  	      |s|exp| mant  |   |  mant       |
128|	    		      ---------------   ---------------
129|	   	 	      63     51   32   31	       0
130|
131dest_dbl:
132	clrl	%d0		|clear d0
133	movew	LOCAL_EX(%a1),%d0	|get exponent
134	subw	#0x3fff,%d0	|subtract extended precision bias
135	cmpw	#0x4000,%d0	|check if inf
136	beqs	inf		|if so, special case
137	addw	#0x3ff,%d0	|add double precision bias
138	swap	%d0		|d0 now in upper word
139	lsll	#4,%d0		|d0 now in proper place for dbl prec exp
140	tstb	LOCAL_SGN(%a1)
141	beqs	get_mant	|if positive, go process mantissa
142	bsetl	#31,%d0		|if negative, put in sign information
143|				; before continuing
144	bras	get_mant	|go process mantissa
145inf:
146	movel	#0x7ff00000,%d0	|load dbl inf exponent
147	clrl	LOCAL_HI(%a1)	|clear msb
148	tstb	LOCAL_SGN(%a1)
149	beqs	dbl_inf		|if positive, go ahead and write it
150	bsetl	#31,%d0		|if negative put in sign information
151dbl_inf:
152	movel	%d0,LOCAL_EX(%a1)	|put the new exp back on the stack
153	bras	dbl_wrt
154get_mant:
155	movel	LOCAL_HI(%a1),%d1	|get ms mantissa
156	bfextu	%d1{#1:#20},%d1	|get upper 20 bits of ms
157	orl	%d1,%d0		|put these bits in ms word of double
158	movel	%d0,LOCAL_EX(%a1)	|put the new exp back on the stack
159	movel	LOCAL_HI(%a1),%d1	|get ms mantissa
160	movel	#21,%d0		|load shift count
161	lsll	%d0,%d1		|put lower 11 bits in upper bits
162	movel	%d1,LOCAL_HI(%a1)	|build lower lword in memory
163	movel	LOCAL_LO(%a1),%d1	|get ls mantissa
164	bfextu	%d1{#0:#21},%d0	|get ls 21 bits of double
165	orl	%d0,LOCAL_HI(%a1)	|put them in double result
166dbl_wrt:
167	movel	#0x8,%d0		|byte count for double precision number
168	exg	%a0,%a1		|a0=supervisor source, a1=user dest
169	bsrl	mem_write	|move the number to the user's memory
170	rts
171|
172|	dest_sgl --- write single precision value to user space
173|
174|Input
175|	a0 -> destination address
176|	a1 -> source in extended precision
177|
178|Output
179|	a0 -> destroyed
180|	a1 -> destroyed
181|	d0 -> 0
182|
183|Changes extended precision to single precision.
184|	sgl_sign = ext_sign
185|	sgl_exp = ext_exp - $3fff(ext bias) + $7f(sgl bias)
186|	get rid of ext integer bit
187|	sgl_mant = ext_mant{62:12}
188|
189|	    	---------------   ---------------    ---------------
190|  extended ->  |s|    exp    |   |1| ms mant   |    | ls mant     |
191|	    	---------------   ---------------    ---------------
192|	   	 95	    64    63 62	   40 32      31     12	  0
193|				     |	   |
194|				     |	   |
195|				     |	   |
196|		 	             v     v
197|	    		      ---------------
198|  single   ->  	      |s|exp| mant  |
199|	    		      ---------------
200|	   	 	      31     22     0
201|
202dest_sgl:
203	clrl	%d0
204	movew	LOCAL_EX(%a1),%d0	|get exponent
205	subw	#0x3fff,%d0	|subtract extended precision bias
206	cmpw	#0x4000,%d0	|check if inf
207	beqs	sinf		|if so, special case
208	addw	#0x7f,%d0		|add single precision bias
209	swap	%d0		|put exp in upper word of d0
210	lsll	#7,%d0		|shift it into single exp bits
211	tstb	LOCAL_SGN(%a1)
212	beqs	get_sman	|if positive, continue
213	bsetl	#31,%d0		|if negative, put in sign first
214	bras	get_sman	|get mantissa
215sinf:
216	movel	#0x7f800000,%d0	|load single inf exp to d0
217	tstb	LOCAL_SGN(%a1)
218	beqs	sgl_wrt		|if positive, continue
219	bsetl	#31,%d0		|if negative, put in sign info
220	bras	sgl_wrt
221
222get_sman:
223	movel	LOCAL_HI(%a1),%d1	|get ms mantissa
224	bfextu	%d1{#1:#23},%d1	|get upper 23 bits of ms
225	orl	%d1,%d0		|put these bits in ms word of single
226
227sgl_wrt:
228	movel	%d0,L_SCR1(%a6)	|put the new exp back on the stack
229	movel	#0x4,%d0		|byte count for single precision number
230	tstl	%a0		|users destination address
231	beqs	sgl_Dn		|destination is a data register
232	exg	%a0,%a1		|a0=supervisor source, a1=user dest
233	leal	L_SCR1(%a6),%a0	|point a0 to data
234	bsrl	mem_write	|move the number to the user's memory
235	rts
236sgl_Dn:
237	bsrl	get_fline	|returns fline word in d0
238	andw	#0x7,%d0		|isolate register number
239	movel	%d0,%d1		|d1 has size:reg formatted for reg_dest
240	orl	#0x10,%d1		|reg_dest wants size added to reg#
241	bral	reg_dest	|size is X, rts in reg_dest will
242|				;return to caller of dest_sgl
243
244dest_ext:
245	tstb	LOCAL_SGN(%a1)	|put back sign into exponent word
246	beqs	dstx_cont
247	bsetb	#sign_bit,LOCAL_EX(%a1)
248dstx_cont:
249	clrb	LOCAL_SGN(%a1)	|clear out the sign byte
250
251	movel	#0x0c,%d0		|byte count for extended number
252	exg	%a0,%a1		|a0=supervisor source, a1=user dest
253	bsrl	mem_write	|move the number to the user's memory
254	rts
255
256	|end
257