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