config: fix build with external compiler by passing the sysroot where needed
[AROS.git] / arch / m68k-all / m680x0 / fpsp / scale.sa
blobe94fded546df61e7c93b76b06e9be4ff01d0850d
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.
8 *       All rights reserved.
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
39 *       is returned.
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.
49 *       Modifies: fp0.
51 *       Algorithm:
52 *               
54 SCALE    IDNT    2,1 Motorola 040 Floating Point Software Package
56         section 8
58         include fpsp.h
60         xref    t_ovfl2
61         xref    t_unfl
62         xref    round
63         xref    t_resdnrm
65 SRC_BNDS dc.w   $3fff,$400c
68 * This entry point is used by the unimplemented instruction exception
69 * handler.
73 *       FSCALE
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
89 * The source input is below 1, so we check for denormalized numbers
90 * and set unfl.
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
109 * Source is within 2^14 range.  To perform the int operation,
110 * move it to d0.
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
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.
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
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
169 * Source is negative.  Add the src to the dest exponent.
170 * (The result exponent will be reduced).  The result can be
171 * denormalized.
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
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.
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
215 * Test for zero. If zero, simply use fmove to return +/- zero
216 * to the fpu.
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
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.
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
258 * The rounding mode changed the zero to a smallest denorm. Call 
259 * t_resdnrm with exceptional operand in ETEMP.
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
269 * Result is still denormalized.
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
279         
281 * The result has underflowed to zero. Return zero and set
282 * unfl, aunfl, and ainex.
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
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
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.
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
342 * Destination became normalized.  Simply add the remaining 
343 * portion of the src to the exponent.
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
360 * Destination remained denormalized.  Call t_excdnrm with
361 * exceptional operand in ETEMP.
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
378 * Source is outside of 2^14 range.  Test the sign and branch
379 * to the appropriate exception handler.
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