1 * $NetBSD: scale.sa,v 1.3 1994/10/26 07:49:34 cgd Exp $
3 * MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
4 * M68000 Hi-Performance Microprocessor Division
5 * M68040 Software Package
7 * M68040 Software Package Copyright (c) 1993, 1994 Motorola Inc.
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.
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.
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.
34 * scale.sa 3.3 7/30/91
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
41 * The entry point sscale is called from do_func to emulate
42 * the fscale unimplemented instruction.
44 * Input: Double-extended destination operand in FPTEMP,
45 * double-extended source operand in ETEMP.
47 * Output: The function returns scale(X,Y) to fp0.
54 SCALE IDNT 2,1 Motorola 040 Floating Point Software Package
65 SRC_BNDS dc.w $3fff,$400c
68 * This entry point is used by the unimplemented instruction exception
77 fmove.l #0,fpcr ;clr user enabled exc
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
86 cmpi.w #$400c,d0 ;test for too large
89 * The source input is below 1, so we check for denormalized numbers
97 st STORE_FLG(a6) ;dest already contains result
98 or.l #unfl_mask,USER_FPSR(a6) ;set UNFL
103 fmove.l USER_FPCR(a6),FPCR
104 fmove.x FPTEMP(a6),fp0 ;simply return dest
109 * Source is within 2^14 range. To perform the int operation,
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
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.
125 tst.w d1 ;check for denorm
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
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
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)
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
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
169 * Source is negative. Add the src to the dest exponent.
170 * (The result exponent will be reduced). The result can be
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
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
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.
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
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
206 st L_SCR2(a6) ;use L_SCR2 to capture inex
208 tst.w d0 ;it is finished when
209 blt.b fix_loop ;d0 is zero or the mantissa
212 or.l #unfl_inx_mask,USER_FPSR(a6)
213 * ;set unfl, aunfl, ainex
215 * Test for zero. If zero, simply use fmove to return +/- zero
220 tst.b L_SCR1(a6) ;test for sign
222 or.w #$8000,FPTEMP_EX(a6) ;set sign bit
224 move.l d1,FPTEMP_HI(a6)
225 move.l d2,FPTEMP_LO(a6)
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
237 btst.b #5,FPCR_MODE(a6) ;test if rm or rp
239 btst.b #4,FPCR_MODE(a6) ;check which one
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
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
253 fmove.l USER_FPCR(a6),FPCR
254 fmove.x FPTEMP(a6),fp0 ;use fmove to set cc's
258 * The rounding mode changed the zero to a smallest denorm. Call
259 * t_resdnrm with exceptional operand in ETEMP.
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)
269 * Result is still denormalized.
272 or.l #unfl_mask,USER_FPSR(a6) ;set unfl
273 tst.b L_SCR1(a6) ;check for sign
275 or.l #neg_mask,USER_FPSR(a6) ;set N
281 * The result has underflowed to zero. Return zero and set
282 * unfl, aunfl, and ainex.
285 or.l #unfl_inx_mask,USER_FPSR(a6)
286 btst.b #5,FPCR_MODE(a6) ;test if rm or rp
288 btst.b #4,FPCR_MODE(a6) ;check which one
291 tst.b L_SCR1(a6) ;check sign
292 bne.b no_dir2 ;if set, neg op, no inc
295 move.l #1,FPTEMP_LO(a6) ;set lsb
296 bra.b sm_dnrm ;return smallest denorm
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)
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
310 clr.l FP_SCR1(a6) ;clear the exceptional operand
311 clr.l FP_SCR1+4(a6) ;for gen_except.
313 fmove.s #:80000000,fp0
316 clr.l FP_SCR1(a6) ;clear the exceptional operand
317 clr.l FP_SCR1+4(a6) ;for gen_except.
319 fmove.s #:00000000,fp0
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.
329 move.w FPTEMP_EX(a6),d1
330 move.l FPTEMP_HI(a6),d2
331 move.l FPTEMP_LO(a6),d3
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
342 * Destination became normalized. Simply add the remaining
343 * portion of the src to the exponent.
346 add.w d0,d1 ;dst is normalized; add src
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
360 * Destination remained denormalized. Call t_excdnrm with
361 * exceptional operand in ETEMP.
364 tst.b L_SCR1(a6) ;check for sign
366 or.l #neg_mask,USER_FPSR(a6) ;set N
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
378 * Source is outside of 2^14 range. Test the sign and branch
379 * to the appropriate exception handler.
386 move.l FPTEMP_HI(a6),ETEMP_HI(a6)
387 move.l FPTEMP_LO(a6),ETEMP_LO(a6)
391 move.w d1,ETEMP(a6) ;result in ETEMP
394 move.w d1,ETEMP(a6) ;result in ETEMP