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