source: rtems/c/src/lib/libcpu/m68k/m68040/fpsp/x_unfl.s @ 010e7582

4.104.114.84.95
Last change on this file since 010e7582 was f9b93da, checked in by Joel Sherrill <joel.sherrill@…>, on 04/16/97 at 17:33:04

Added the MC68040 Floating Point Support Package. This was ported
to RTEMS by Eric Norum. It is freely distributable and was acquired
from the Motorola WWW site. More info is in the FPSP README.

  • Property mode set to 100644
File size: 7.0 KB
Line 
1//
2//      x_unfl.sa 3.4 7/1/91
3//
4//      fpsp_unfl --- FPSP handler for underflow exception
5//
6// Trap disabled results
7//      For 881/2 compatibility, sw must denormalize the intermediate
8// result, then store the result.  Denormalization is accomplished
9// by taking the intermediate result (which is always normalized) and
10// shifting the mantissa right while incrementing the exponent until
11// it is equal to the denormalized exponent for the destination
12// format.  After denormalization, the result is rounded to the
13// destination format.
14//             
15// Trap enabled results
16//      All trap disabled code applies. In addition the exceptional
17// operand needs to made available to the user with a bias of $6000
18// added to the exponent.
19//
20
21//              Copyright (C) Motorola, Inc. 1990
22//                      All Rights Reserved
23//
24//      THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
25//      The copyright notice above does not evidence any 
26//      actual or intended publication of such source code.
27
28X_UNFL: //idnt    2,1 | Motorola 040 Floating Point Software Package
29
30        |section        8
31
32        .include "fpsp.defs"
33
34        |xref   denorm
35        |xref   round
36        |xref   store
37        |xref   g_rndpr
38        |xref   g_opcls
39        |xref   g_dfmtou
40        |xref   real_unfl
41        |xref   real_inex
42        |xref   fpsp_done
43        |xref   b1238_fix
44
45        .global fpsp_unfl
46fpsp_unfl:
47        link            %a6,#-LOCAL_SIZE
48        fsave           -(%a7)
49        moveml          %d0-%d1/%a0-%a1,USER_DA(%a6)
50        fmovemx %fp0-%fp3,USER_FP0(%a6)
51        fmoveml %fpcr/%fpsr/%fpiar,USER_FPCR(%a6)
52
53//
54        bsrl            unf_res //denormalize, round & store interm op
55//
56// If underflow exceptions are not enabled, check for inexact
57// exception
58//
59        btstb           #unfl_bit,FPCR_ENABLE(%a6)
60        beqs            ck_inex
61
62        btstb           #E3,E_BYTE(%a6)
63        beqs            no_e3_1
64//
65// Clear dirty bit on dest resister in the frame before branching
66// to b1238_fix.
67//
68        bfextu          CMDREG3B(%a6){#6:#3},%d0        //get dest reg no
69        bclrb           %d0,FPR_DIRTY_BITS(%a6) //clr dest dirty bit
70        bsrl            b1238_fix               //test for bug1238 case
71        movel           USER_FPSR(%a6),FPSR_SHADOW(%a6)
72        orl             #sx_mask,E_BYTE(%a6)
73no_e3_1:
74        moveml          USER_DA(%a6),%d0-%d1/%a0-%a1
75        fmovemx USER_FP0(%a6),%fp0-%fp3
76        fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
77        frestore        (%a7)+
78        unlk            %a6
79        bral            real_unfl
80//
81// It is possible to have either inex2 or inex1 exceptions with the
82// unfl.  If the inex enable bit is set in the FPCR, and either
83// inex2 or inex1 occurred, we must clean up and branch to the
84// real inex handler.
85//
86ck_inex:
87        moveb           FPCR_ENABLE(%a6),%d0
88        andb            FPSR_EXCEPT(%a6),%d0
89        andib           #0x3,%d0
90        beqs            unfl_done
91
92//
93// Inexact enabled and reported, and we must take an inexact exception
94//     
95take_inex:
96        btstb           #E3,E_BYTE(%a6)
97        beqs            no_e3_2
98//
99// Clear dirty bit on dest resister in the frame before branching
100// to b1238_fix.
101//
102        bfextu          CMDREG3B(%a6){#6:#3},%d0        //get dest reg no
103        bclrb           %d0,FPR_DIRTY_BITS(%a6) //clr dest dirty bit
104        bsrl            b1238_fix               //test for bug1238 case
105        movel           USER_FPSR(%a6),FPSR_SHADOW(%a6)
106        orl             #sx_mask,E_BYTE(%a6)
107no_e3_2:
108        moveb           #INEX_VEC,EXC_VEC+1(%a6)
109        moveml         USER_DA(%a6),%d0-%d1/%a0-%a1
110        fmovemx        USER_FP0(%a6),%fp0-%fp3
111        fmoveml        USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
112        frestore        (%a7)+
113        unlk            %a6
114        bral            real_inex
115
116unfl_done:
117        bclrb           #E3,E_BYTE(%a6)
118        beqs            e1_set          //if set then branch
119//
120// Clear dirty bit on dest resister in the frame before branching
121// to b1238_fix.
122//
123        bfextu          CMDREG3B(%a6){#6:#3},%d0                //get dest reg no
124        bclrb           %d0,FPR_DIRTY_BITS(%a6) //clr dest dirty bit
125        bsrl            b1238_fix               //test for bug1238 case
126        movel           USER_FPSR(%a6),FPSR_SHADOW(%a6)
127        orl             #sx_mask,E_BYTE(%a6)
128        moveml          USER_DA(%a6),%d0-%d1/%a0-%a1
129        fmovemx USER_FP0(%a6),%fp0-%fp3
130        fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
131        frestore        (%a7)+
132        unlk            %a6
133        bral            fpsp_done
134e1_set:
135        moveml          USER_DA(%a6),%d0-%d1/%a0-%a1
136        fmovemx USER_FP0(%a6),%fp0-%fp3
137        fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
138        unlk            %a6
139        bral            fpsp_done
140//
141//      unf_res --- underflow result calculation
142//
143unf_res:
144        bsrl            g_rndpr         //returns RND_PREC in d0 0=ext,
145//                                      ;1=sgl, 2=dbl
146//                                      ;we need the RND_PREC in the
147//                                      ;upper word for round
148        movew           #0,-(%a7)       
149        movew           %d0,-(%a7)      //copy RND_PREC to stack
150//
151//
152// If the exception bit set is E3, the exceptional operand from the
153// fpu is in WBTEMP; else it is in FPTEMP.
154//
155        btstb           #E3,E_BYTE(%a6)
156        beqs            unf_E1
157unf_E3:
158        lea             WBTEMP(%a6),%a0 //a0 now points to operand
159//
160// Test for fsgldiv and fsglmul.  If the inst was one of these, then
161// force the precision to extended for the denorm routine.  Use
162// the user's precision for the round routine.
163//
164        movew           CMDREG3B(%a6),%d1       //check for fsgldiv or fsglmul
165        andiw           #0x7f,%d1
166        cmpiw           #0x30,%d1               //check for sgldiv
167        beqs            unf_sgl
168        cmpiw           #0x33,%d1               //check for sglmul
169        bnes            unf_cont        //if not, use fpcr prec in round
170unf_sgl:
171        clrl            %d0
172        movew           #0x1,(%a7)      //override g_rndpr precision
173//                                      ;force single
174        bras            unf_cont
175unf_E1:
176        lea             FPTEMP(%a6),%a0 //a0 now points to operand
177unf_cont:
178        bclrb           #sign_bit,LOCAL_EX(%a0) //clear sign bit
179        sne             LOCAL_SGN(%a0)          //store sign
180
181        bsrl            denorm          //returns denorm, a0 points to it
182//
183// WARNING:
184//                              ;d0 has guard,round sticky bit
185//                              ;make sure that it is not corrupted
186//                              ;before it reaches the round subroutine
187//                              ;also ensure that a0 isn't corrupted
188
189//
190// Set up d1 for round subroutine d1 contains the PREC/MODE
191// information respectively on upper/lower register halves.
192//
193        bfextu          FPCR_MODE(%a6){#2:#2},%d1       //get mode from FPCR
194//                                              ;mode in lower d1
195        addl            (%a7)+,%d1              //merge PREC/MODE
196//
197// WARNING: a0 and d0 are assumed to be intact between the denorm and
198// round subroutines. All code between these two subroutines
199// must not corrupt a0 and d0.
200//
201//
202// Perform Round       
203//      Input:          a0 points to input operand
204//                      d0{31:29} has guard, round, sticky
205//                      d1{01:00} has rounding mode
206//                      d1{17:16} has rounding precision
207//      Output:         a0 points to rounded operand
208//
209
210        bsrl            round           //returns rounded denorm at (a0)
211//
212// Differentiate between store to memory vs. store to register
213//
214unf_store:
215        bsrl            g_opcls         //returns opclass in d0{2:0}
216        cmpib           #0x3,%d0
217        bnes            not_opc011
218//
219// At this point, a store to memory is pending
220//
221opc011:
222        bsrl            g_dfmtou
223        tstb            %d0
224        beqs            ext_opc011      //If extended, do not subtract
225//                              ;If destination format is sgl/dbl,
226        tstb            LOCAL_HI(%a0)   //If rounded result is normal,don't
227//                                      ;subtract
228        bmis            ext_opc011
229        subqw           #1,LOCAL_EX(%a0)        //account for denorm bias vs.
230//                              ;normalized bias
231//                              ;          normalized   denormalized
232//                              ;single       $7f           $7e
233//                              ;double       $3ff          $3fe
234//
235ext_opc011:
236        bsrl            store           //stores to memory
237        bras            unf_done        //finish up
238
239//
240// At this point, a store to a float register is pending
241//
242not_opc011:
243        bsrl            store   //stores to float register
244//                              ;a0 is not corrupted on a store to a
245//                              ;float register.
246//
247// Set the condition codes according to result
248//
249        tstl            LOCAL_HI(%a0)   //check upper mantissa
250        bnes            ck_sgn
251        tstl            LOCAL_LO(%a0)   //check lower mantissa
252        bnes            ck_sgn
253        bsetb           #z_bit,FPSR_CC(%a6) //set condition codes if zero
254ck_sgn:
255        btstb           #sign_bit,LOCAL_EX(%a0) //check the sign bit
256        beqs            unf_done
257        bsetb           #neg_bit,FPSR_CC(%a6)
258
259//
260// Finish. 
261//
262unf_done:
263        btstb           #inex2_bit,FPSR_EXCEPT(%a6)
264        beqs            no_aunfl
265        bsetb           #aunfl_bit,FPSR_AEXCEPT(%a6)
266no_aunfl:
267        rts
268
269        |end
Note: See TracBrowser for help on using the repository browser.