xref: /netbsd/sys/arch/m68k/fpsp/x_store.sa (revision bf9ec67e)
1*	$NetBSD: x_store.sa,v 1.4 2001/12/09 01:43:13 briggs Exp $
2
3*	MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
4*	M68000 Hi-Performance Microprocessor Division
5*	M68040 Software Package
6*
7*	M68040 Software Package Copyright (c) 1993, 1994 Motorola Inc.
8*	All rights reserved.
9*
10*	THE SOFTWARE is provided on an "AS IS" basis and without warranty.
11*	To the maximum extent permitted by applicable law,
12*	MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
13*	INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A
14*	PARTICULAR PURPOSE and any warranty against infringement with
15*	regard to the SOFTWARE (INCLUDING ANY MODIFIED VERSIONS THEREOF)
16*	and any accompanying written materials.
17*
18*	To the maximum extent permitted by applicable law,
19*	IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
20*	(INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS
21*	PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR
22*	OTHER PECUNIARY LOSS) ARISING OF THE USE OR INABILITY TO USE THE
23*	SOFTWARE.  Motorola assumes no responsibility for the maintenance
24*	and support of the SOFTWARE.
25*
26*	You are hereby granted a copyright license to use, modify, and
27*	distribute the SOFTWARE so long as this entire notice is retained
28*	without alteration in any modified and/or redistributed versions,
29*	and that such modified versions are clearly identified as such.
30*	No licenses are granted by implication, estoppel or otherwise
31*	under any patents or trademarks of Motorola, Inc.
32
33*
34*	x_store.sa 3.2 1/24/91
35*
36*	store --- store operand to memory or register
37*
38*	Used by underflow and overflow handlers.
39*
40*	a6 = points to fp value to be stored.
41*
42
43X_STORE	IDNT    2,1 Motorola 040 Floating Point Software Package
44
45	section	8
46
47fpreg_mask:
48	dc.b	$80,$40,$20,$10,$08,$04,$02,$01
49
50	include	fpsp.h
51
52	xref	mem_write
53	xref	get_fline
54	xref	g_opcls
55	xref	g_dfmtou
56	xref	reg_dest
57
58	xdef	dest_ext
59	xdef	dest_dbl
60	xdef	dest_sgl
61
62	xdef	store
63store:
64	btst.b	#E3,E_BYTE(a6)
65	beq.b	E1_sto
66E3_sto:
67	move.l	CMDREG3B(a6),d0
68	bfextu	d0{6:3},d0		;isolate dest. reg from cmdreg3b
69sto_fp:
70	lea	fpreg_mask,a1
71	move.b	(a1,d0.w),d0		;convert reg# to dynamic register mask
72	tst.b	LOCAL_SGN(a0)
73	beq.b	is_pos
74	bset.b	#sign_bit,LOCAL_EX(a0)
75is_pos:
76	fmovem.x (a0),d0		;move to correct register
77*
78*	if fp0-fp3 is being modified, we must put a copy
79*	in the USER_FPn variable on the stack because all exception
80*	handlers restore fp0-fp3 from there.
81*
82	cmp.b	#$80,d0
83	bne.b	not_fp0
84	fmovem.x fp0,USER_FP0(a6)
85	rts
86not_fp0:
87	cmp.b	#$40,d0
88	bne.b	not_fp1
89	fmovem.x fp1,USER_FP1(a6)
90	rts
91not_fp1:
92	cmp.b	#$20,d0
93	bne.b	not_fp2
94	fmovem.x fp2,USER_FP2(a6)
95	rts
96not_fp2:
97	cmp.b	#$10,d0
98	bne.b	not_fp3
99	fmovem.x fp3,USER_FP3(a6)
100	rts
101not_fp3:
102	rts
103
104E1_sto:
105	bsr.l	g_opcls		;returns opclass in d0
106	cmpi.b	#3,d0
107	beq	opc011		;branch if opclass 3
108	move.l	CMDREG1B(a6),d0
109	bfextu	d0{6:3},d0	;extract destination register
110	bra.b	sto_fp
111
112opc011:
113	bsr.l	g_dfmtou	;returns dest format in d0
114*				;ext=00, sgl=01, dbl=10
115	move.l	a0,a1		;save source addr in a1
116	move.l	EXC_EA(a6),a0	;get the address
117	tst.l	d0		;if dest format is extended
118	beq.w	dest_ext	;then branch
119	cmpi.l	#1,d0		;if dest format is single
120	beq.b	short_dest_sgl	;then branch
121*
122*	fall through to dest_dbl
123*
124
125*
126*	dest_dbl --- write double precision value to user space
127*
128*Input
129*	a0 -> destination address
130*	a1 -> source in extended precision
131*Output
132*	a0 -> destroyed
133*	a1 -> destroyed
134*	d0 -> 0
135*
136*Changes extended precision to double precision.
137* Note: no attempt is made to round the extended value to double.
138*	dbl_sign = ext_sign
139*	dbl_exp = ext_exp - $3fff(ext bias) + $7ff(dbl bias)
140*	get rid of ext integer bit
141*	dbl_mant = ext_mant{62:12}
142*
143*	    	---------------   ---------------    ---------------
144*  extended ->  |s|    exp    |   |1| ms mant   |    | ls mant     |
145*	    	---------------   ---------------    ---------------
146*	   	 95	    64    63 62	      32      31     11	  0
147*				     |			     |
148*				     |			     |
149*				     |			     |
150*		 	             v   		     v
151*	    		      ---------------   ---------------
152*  double   ->  	      |s|exp| mant  |   |  mant       |
153*	    		      ---------------   ---------------
154*	   	 	      63     51   32   31	       0
155*
156dest_dbl:
157	clr.l	d0		;clear d0
158	move.w	LOCAL_EX(a1),d0	;get exponent
159	sub.w	#$3fff,d0	;subtract extended precision bias
160	cmp.w	#$4000,d0	;check if inf
161	beq.b	inf		;if so, special case
162	add.w	#$3ff,d0	;add double precision bias
163	swap	d0		;d0 now in upper word
164	lsl.l	#4,d0		;d0 now in proper place for dbl prec exp
165	tst.b	LOCAL_SGN(a1)
166	beq.b	get_mant	;if postive, go process mantissa
167	bset.l	#31,d0		;if negative, put in sign information
168*				; before continuing
169	bra.b	get_mant	;go process mantissa
170inf:
171	move.l	#$7ff00000,d0	;load dbl inf exponent
172	clr.l	LOCAL_HI(a1)	;clear msb
173	tst.b	LOCAL_SGN(a1)
174	beq.b	dbl_inf		;if positive, go ahead and write it
175	bset.l	#31,d0		;if negative put in sign information
176dbl_inf:
177	move.l	d0,LOCAL_EX(a1)	;put the new exp back on the stack
178	bra.b	dbl_wrt
179get_mant:
180	move.l	LOCAL_HI(a1),d1	;get ms mantissa
181	bfextu	d1{1:20},d1	;get upper 20 bits of ms
182	or.l	d1,d0		;put these bits in ms word of double
183	move.l	d0,LOCAL_EX(a1)	;put the new exp back on the stack
184	move.l	LOCAL_HI(a1),d1	;get ms mantissa
185	move.l	#21,d0		;load shift count
186	lsl.l	d0,d1		;put lower 11 bits in upper bits
187	move.l	d1,LOCAL_HI(a1)	;build lower lword in memory
188	move.l	LOCAL_LO(a1),d1	;get ls mantissa
189	bfextu	d1{0:21},d0	;get ls 21 bits of double
190	or.l	d0,LOCAL_HI(a1)	;put them in double result
191dbl_wrt:
192	move.l	#$8,d0		;byte count for double precision number
193	exg	a0,a1		;a0=supervisor source, a1=user dest
194	bsr.l	mem_write	;move the number to the user's memory
195	rts
196*
197*	dest_sgl --- write single precision value to user space
198*
199*Input
200*	a0 -> destination address
201*	a1 -> source in extended precision
202*
203*Output
204*	a0 -> destroyed
205*	a1 -> destroyed
206*	d0 -> 0
207*
208*Changes extended precision to single precision.
209*	sgl_sign = ext_sign
210*	sgl_exp = ext_exp - $3fff(ext bias) + $7f(sgl bias)
211*	get rid of ext integer bit
212*	sgl_mant = ext_mant{62:12}
213*
214*	    	---------------   ---------------    ---------------
215*  extended ->  |s|    exp    |   |1| ms mant   |    | ls mant     |
216*	    	---------------   ---------------    ---------------
217*	   	 95	    64    63 62	   40 32      31     12	  0
218*				     |	   |
219*				     |	   |
220*				     |	   |
221*		 	             v     v
222*	    		      ---------------
223*  single   ->  	      |s|exp| mant  |
224*	    		      ---------------
225*	   	 	      31     22     0
226*
227dest_sgl:
228short_dest_sgl:
229	clr.l	d0
230	move.w	LOCAL_EX(a1),d0	;get exponent
231	sub.w	#$3fff,d0	;subtract extended precision bias
232	cmp.w	#$4000,d0	;check if inf
233	beq.b	sinf		;if so, special case
234	add.w	#$7f,d0		;add single precision bias
235	swap	d0		;put exp in upper word of d0
236	lsl.l	#7,d0		;shift it into single exp bits
237	tst.b	LOCAL_SGN(a1)
238	beq.b	get_sman	;if positive, continue
239	bset.l	#31,d0		;if negative, put in sign first
240	bra.b	get_sman	;get mantissa
241sinf:
242	move.l	#$7f800000,d0	;load single inf exp to d0
243	tst.b	LOCAL_SGN(a1)
244	beq.b	sgl_wrt		;if positive, continue
245	bset.l	#31,d0		;if negative, put in sign info
246	bra.b	sgl_wrt
247
248get_sman:
249	move.l	LOCAL_HI(a1),d1	;get ms mantissa
250	bfextu	d1{1:23},d1	;get upper 23 bits of ms
251	or.l	d1,d0		;put these bits in ms word of single
252
253sgl_wrt:
254	move.l	d0,L_SCR1(a6)	;put the new exp back on the stack
255	move.l	#$4,d0		;byte count for single precision number
256	tst.l	a0		;users destination address
257	beq.b	sgl_Dn		;destination is a data register
258	exg	a0,a1		;a0=supervisor source, a1=user dest
259	lea.l	L_SCR1(a6),a0	;point a0 to data
260	bsr.l	mem_write	;move the number to the user's memory
261	rts
262sgl_Dn:
263	bsr.l	get_fline	;returns fline word in d0
264	and.w	#$7,d0		;isolate register number
265	move.l	d0,d1		;d1 has size:reg formatted for reg_dest
266	or.l	#$10,d1		;reg_dest wants size added to reg#
267	bra.l	reg_dest	;size is X, rts in reg_dest will
268*				;return to caller of dest_sgl
269
270dest_ext:
271	tst.b	LOCAL_SGN(a1)	;put back sign into exponent word
272	beq.b	dstx_cont
273	bset.b	#sign_bit,LOCAL_EX(a1)
274dstx_cont:
275	clr.b	LOCAL_SGN(a1)	;clear out the sign byte
276
277	move.l	#$0c,d0		;byte count for extended number
278	exg	a0,a1		;a0=supervisor source, a1=user dest
279	bsr.l	mem_write	;move the number to the user's memory
280	rts
281
282	end
283