scale.sa revision 1.3 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
54 SCALE 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
65 SRC_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
76 sscale:
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 *
92 src_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
99 den_done:
100 lea.l FPTEMP(a6),a0
101 bra t_resdnrm
102 no_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 *
112 src_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 *
124 src_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
134 spos_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
139 ovfl:
140 tst.b L_SCR1(a6)
141 beq.b sovl_pos
142 or.w #$8000,d1
143 sovl_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
149 denorm:
150 tst.b L_SCR1(a6)
151 beq.b den_pos
152 or.w #$8000,d1
153 den_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
162 nden_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 *
173 src_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
181 sneg_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 *
193 fix_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)
201 fix_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
207 no_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 *
218 tst_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
223 tst_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
241 zer_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
246 zer_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
252 no_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 *
261 sm_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 *
271 not_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
276 fix_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 *
284 fix_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
290 zer_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
297 zer_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
306 no_dir2:
307 tst.b L_SCR1(a6)
308 bge.b pos_zero
309 neg_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
315 pos_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 *
327 dst_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
332 dst_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 *
345 dst_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
350 dnrm_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 *
363 dst_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
368 dst_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 *
381 src_out:
382 tst.b L_SCR1(a6)
383 beq.b scro_pos
384 or.w #$8000,d1
385 scro_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
390 res_pos:
391 move.w d1,ETEMP(a6) ;result in ETEMP
392 bra t_ovfl2
393 res_neg:
394 move.w d1,ETEMP(a6) ;result in ETEMP
395 lea.l ETEMP(a6),a0
396 bra t_unfl
397 end
398