xref: /netbsd/sys/arch/m68k/fpsp/scale.sa (revision bf9ec67e)
1*	$NetBSD: scale.sa,v 1.3 1994/10/26 07:49:34 cgd 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*	scale.sa 3.3 7/30/91
35*
36*	The entry point sSCALE computes the destination operand
37*	scaled by the source operand.  If the absoulute value of
38*	the source operand is (>= 2^14) an overflow or underflow
39*	is returned.
40*
41*	The entry point sscale is called from do_func to emulate
42*	the fscale unimplemented instruction.
43*
44*	Input: Double-extended destination operand in FPTEMP,
45*		double-extended source operand in ETEMP.
46*
47*	Output: The function returns scale(X,Y) to fp0.
48*
49*	Modifies: fp0.
50*
51*	Algorithm:
52*
53
54SCALE    IDNT    2,1 Motorola 040 Floating Point Software Package
55
56	section	8
57
58	include	fpsp.h
59
60	xref	t_ovfl2
61	xref	t_unfl
62	xref	round
63	xref	t_resdnrm
64
65SRC_BNDS dc.w	$3fff,$400c
66
67*
68* This entry point is used by the unimplemented instruction exception
69* handler.
70*
71*
72*
73*	FSCALE
74*
75	xdef	sscale
76sscale:
77	fmove.l		#0,fpcr		;clr user enabled exc
78	clr.l		d1
79	move.w		FPTEMP(a6),d1	;get dest exponent
80	smi		L_SCR1(a6)	;use L_SCR1 to hold sign
81	andi.l		#$7fff,d1	;strip sign
82	move.w		ETEMP(a6),d0	;check src bounds
83	andi.w		#$7fff,d0	;clr sign bit
84	cmp2.w		SRC_BNDS,d0
85	bcc.b		src_in
86	cmpi.w		#$400c,d0	;test for too large
87	bge.w		src_out
88*
89* The source input is below 1, so we check for denormalized numbers
90* and set unfl.
91*
92src_small:
93	move.b		DTAG(a6),d0
94	andi.b		#$e0,d0
95	tst.b		d0
96	beq.b		no_denorm
97	st		STORE_FLG(a6)	;dest already contains result
98	or.l		#unfl_mask,USER_FPSR(a6) ;set UNFL
99den_done:
100	lea.l		FPTEMP(a6),a0
101	bra		t_resdnrm
102no_denorm:
103	fmove.l		USER_FPCR(a6),FPCR
104	fmove.x		FPTEMP(a6),fp0	;simply return dest
105	rts
106
107
108*
109* Source is within 2^14 range.  To perform the int operation,
110* move it to d0.
111*
112src_in:
113	fmove.x		ETEMP(a6),fp0	;move in src for int
114	fmove.l		#rz_mode,fpcr	;force rz for src conversion
115	fmove.l		fp0,d0		;int src to d0
116	fmove.l		#0,FPSR		;clr status from above
117	tst.w		ETEMP(a6)	;check src sign
118	blt.w		src_neg
119*
120* Source is positive.  Add the src to the dest exponent.
121* The result can be denormalized, if src = 0, or overflow,
122* if the result of the add sets a bit in the upper word.
123*
124src_pos:
125	tst.w		d1		;check for denorm
126	beq.w		dst_dnrm
127	add.l		d0,d1		;add src to dest exp
128	beq.b		denorm		;if zero, result is denorm
129	cmpi.l		#$7fff,d1	;test for overflow
130	bge.b		ovfl
131	tst.b		L_SCR1(a6)
132	beq.b		spos_pos
133	or.w		#$8000,d1
134spos_pos:
135	move.w		d1,FPTEMP(a6)	;result in FPTEMP
136	fmove.l		USER_FPCR(a6),FPCR
137	fmove.x		FPTEMP(a6),fp0	;write result to fp0
138	rts
139ovfl:
140	tst.b		L_SCR1(a6)
141	beq.b		sovl_pos
142	or.w		#$8000,d1
143sovl_pos:
144	move.w		FPTEMP(a6),ETEMP(a6)	;result in ETEMP
145	move.l		FPTEMP_HI(a6),ETEMP_HI(a6)
146	move.l		FPTEMP_LO(a6),ETEMP_LO(a6)
147	bra		t_ovfl2
148
149denorm:
150	tst.b		L_SCR1(a6)
151	beq.b		den_pos
152	or.w		#$8000,d1
153den_pos:
154	tst.l		FPTEMP_HI(a6)	;check j bit
155	blt.b		nden_exit	;if set, not denorm
156	move.w		d1,ETEMP(a6)	;input expected in ETEMP
157	move.l		FPTEMP_HI(a6),ETEMP_HI(a6)
158	move.l		FPTEMP_LO(a6),ETEMP_LO(a6)
159	or.l		#unfl_bit,USER_FPSR(a6)	;set unfl
160	lea.l		ETEMP(a6),a0
161	bra		t_resdnrm
162nden_exit:
163	move.w		d1,FPTEMP(a6)	;result in FPTEMP
164	fmove.l		USER_FPCR(a6),FPCR
165	fmove.x		FPTEMP(a6),fp0	;write result to fp0
166	rts
167
168*
169* Source is negative.  Add the src to the dest exponent.
170* (The result exponent will be reduced).  The result can be
171* denormalized.
172*
173src_neg:
174	add.l		d0,d1		;add src to dest
175	beq.b		denorm		;if zero, result is denorm
176	blt.b		fix_dnrm	;if negative, result is
177*					;needing denormalization
178	tst.b		L_SCR1(a6)
179	beq.b		sneg_pos
180	or.w		#$8000,d1
181sneg_pos:
182	move.w		d1,FPTEMP(a6)	;result in FPTEMP
183	fmove.l		USER_FPCR(a6),FPCR
184	fmove.x		FPTEMP(a6),fp0	;write result to fp0
185	rts
186
187
188*
189* The result exponent is below denorm value.  Test for catastrophic
190* underflow and force zero if true.  If not, try to shift the
191* mantissa right until a zero exponent exists.
192*
193fix_dnrm:
194	cmpi.w		#$ffc0,d1	;lower bound for normalization
195	blt.w		fix_unfl	;if lower, catastrophic unfl
196	move.w		d1,d0		;use d0 for exp
197	move.l		d2,-(a7)	;free d2 for norm
198	move.l		FPTEMP_HI(a6),d1
199	move.l		FPTEMP_LO(a6),d2
200	clr.l		L_SCR2(a6)
201fix_loop:
202	add.w		#1,d0		;drive d0 to 0
203	lsr.l		#1,d1		;while shifting the
204	roxr.l		#1,d2		;mantissa to the right
205	bcc.b		no_carry
206	st		L_SCR2(a6)	;use L_SCR2 to capture inex
207no_carry:
208	tst.w		d0		;it is finished when
209	blt.b		fix_loop	;d0 is zero or the mantissa
210	tst.b		L_SCR2(a6)
211	beq.b		tst_zero
212	or.l		#unfl_inx_mask,USER_FPSR(a6)
213*					;set unfl, aunfl, ainex
214*
215* Test for zero. If zero, simply use fmove to return +/- zero
216* to the fpu.
217*
218tst_zero:
219	clr.w		FPTEMP_EX(a6)
220	tst.b		L_SCR1(a6)	;test for sign
221	beq.b		tst_con
222	or.w		#$8000,FPTEMP_EX(a6) ;set sign bit
223tst_con:
224	move.l		d1,FPTEMP_HI(a6)
225	move.l		d2,FPTEMP_LO(a6)
226	move.l		(a7)+,d2
227	tst.l		d1
228	bne.b		not_zero
229	tst.l		FPTEMP_LO(a6)
230	bne.b		not_zero
231*
232* Result is zero.  Check for rounding mode to set lsb.  If the
233* mode is rp, and the zero is positive, return smallest denorm.
234* If the mode is rm, and the zero is negative, return smallest
235* negative denorm.
236*
237	btst.b		#5,FPCR_MODE(a6) ;test if rm or rp
238	beq.b		no_dir
239	btst.b		#4,FPCR_MODE(a6) ;check which one
240	beq.b		zer_rm
241zer_rp:
242	tst.b		L_SCR1(a6)	;check sign
243	bne.b		no_dir		;if set, neg op, no inc
244	move.l		#1,FPTEMP_LO(a6) ;set lsb
245	bra.b		sm_dnrm
246zer_rm:
247	tst.b		L_SCR1(a6)	;check sign
248	beq.b		no_dir		;if clr, neg op, no inc
249	move.l		#1,FPTEMP_LO(a6) ;set lsb
250	or.l		#neg_mask,USER_FPSR(a6) ;set N
251	bra.b		sm_dnrm
252no_dir:
253	fmove.l		USER_FPCR(a6),FPCR
254	fmove.x		FPTEMP(a6),fp0	;use fmove to set cc's
255	rts
256
257*
258* The rounding mode changed the zero to a smallest denorm. Call
259* t_resdnrm with exceptional operand in ETEMP.
260*
261sm_dnrm:
262	move.l		FPTEMP_EX(a6),ETEMP_EX(a6)
263	move.l		FPTEMP_HI(a6),ETEMP_HI(a6)
264	move.l		FPTEMP_LO(a6),ETEMP_LO(a6)
265	lea.l		ETEMP(a6),a0
266	bra		t_resdnrm
267
268*
269* Result is still denormalized.
270*
271not_zero:
272	or.l		#unfl_mask,USER_FPSR(a6) ;set unfl
273	tst.b		L_SCR1(a6)	;check for sign
274	beq.b		fix_exit
275	or.l		#neg_mask,USER_FPSR(a6) ;set N
276fix_exit:
277	bra.b		sm_dnrm
278
279
280*
281* The result has underflowed to zero. Return zero and set
282* unfl, aunfl, and ainex.
283*
284fix_unfl:
285	or.l		#unfl_inx_mask,USER_FPSR(a6)
286	btst.b		#5,FPCR_MODE(a6) ;test if rm or rp
287	beq.b		no_dir2
288	btst.b		#4,FPCR_MODE(a6) ;check which one
289	beq.b		zer_rm2
290zer_rp2:
291	tst.b		L_SCR1(a6)	;check sign
292	bne.b		no_dir2		;if set, neg op, no inc
293	clr.l		FPTEMP_EX(a6)
294	clr.l		FPTEMP_HI(a6)
295	move.l		#1,FPTEMP_LO(a6) ;set lsb
296	bra.b		sm_dnrm		;return smallest denorm
297zer_rm2:
298	tst.b		L_SCR1(a6)	;check sign
299	beq.b		no_dir2		;if clr, neg op, no inc
300	move.w		#$8000,FPTEMP_EX(a6)
301	clr.l		FPTEMP_HI(a6)
302	move.l		#1,FPTEMP_LO(a6) ;set lsb
303	or.l		#neg_mask,USER_FPSR(a6) ;set N
304	bra.w		sm_dnrm		;return smallest denorm
305
306no_dir2:
307	tst.b		L_SCR1(a6)
308	bge.b		pos_zero
309neg_zero:
310	clr.l		FP_SCR1(a6)	;clear the exceptional operand
311	clr.l		FP_SCR1+4(a6)	;for gen_except.
312	clr.l		FP_SCR1+8(a6)
313	fmove.s		#:80000000,fp0
314	rts
315pos_zero:
316	clr.l		FP_SCR1(a6)	;clear the exceptional operand
317	clr.l		FP_SCR1+4(a6)	;for gen_except.
318	clr.l		FP_SCR1+8(a6)
319	fmove.s		#:00000000,fp0
320	rts
321
322*
323* The destination is a denormalized number.  It must be handled
324* by first shifting the bits in the mantissa until it is normalized,
325* then adding the remainder of the source to the exponent.
326*
327dst_dnrm:
328	movem.l		d2/d3,-(a7)
329	move.w		FPTEMP_EX(a6),d1
330	move.l		FPTEMP_HI(a6),d2
331	move.l		FPTEMP_LO(a6),d3
332dst_loop:
333	tst.l		d2		;test for normalized result
334	blt.b		dst_norm	;exit loop if so
335	tst.l		d0		;otherwise, test shift count
336	beq.b		dst_fin		;if zero, shifting is done
337	subq.l		#1,d0		;dec src
338	add.l		d3,d3
339	addx.l		d2,d2
340	bra.b		dst_loop
341*
342* Destination became normalized.  Simply add the remaining
343* portion of the src to the exponent.
344*
345dst_norm:
346	add.w		d0,d1		;dst is normalized; add src
347	tst.b		L_SCR1(a6)
348	beq.b		dnrm_pos
349	or.w		#$8000,d1
350dnrm_pos:
351	movem.w		d1,FPTEMP_EX(a6)
352	movem.l		d2,FPTEMP_HI(a6)
353	movem.l		d3,FPTEMP_LO(a6)
354	fmove.l		USER_FPCR(a6),FPCR
355	fmove.x		FPTEMP(a6),fp0
356	movem.l		(a7)+,d2/d3
357	rts
358
359*
360* Destination remained denormalized.  Call t_excdnrm with
361* exceptional operand in ETEMP.
362*
363dst_fin:
364	tst.b		L_SCR1(a6)	;check for sign
365	beq.b		dst_exit
366	or.l		#neg_mask,USER_FPSR(a6) ;set N
367	or.w		#$8000,d1
368dst_exit:
369	movem.w		d1,ETEMP_EX(a6)
370	movem.l		d2,ETEMP_HI(a6)
371	movem.l		d3,ETEMP_LO(a6)
372	or.l		#unfl_mask,USER_FPSR(a6) ;set unfl
373	movem.l		(a7)+,d2/d3
374	lea.l		ETEMP(a6),a0
375	bra		t_resdnrm
376
377*
378* Source is outside of 2^14 range.  Test the sign and branch
379* to the appropriate exception handler.
380*
381src_out:
382	tst.b		L_SCR1(a6)
383	beq.b		scro_pos
384	or.w		#$8000,d1
385scro_pos:
386	move.l		FPTEMP_HI(a6),ETEMP_HI(a6)
387	move.l		FPTEMP_LO(a6),ETEMP_LO(a6)
388	tst.w		ETEMP(a6)
389	blt.b		res_neg
390res_pos:
391	move.w		d1,ETEMP(a6)	;result in ETEMP
392	bra		t_ovfl2
393res_neg:
394	move.w		d1,ETEMP(a6)	;result in ETEMP
395	lea.l		ETEMP(a6),a0
396	bra		t_unfl
397	end
398