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