source: rtems/bsps/m68k/shared/fpsp/scale.S @ d584269

5
Last change on this file since d584269 was 3cf2bf63, checked in by Sebastian Huber <sebastian.huber@…>, on 03/26/18 at 10:17:06

bsps/m68k: Move fpsp support to bsps

This patch is a part of the BSP source reorganization.

Update #3285.

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