476b711967ceb39957c4dcd0dbd34da6768d5f8b
[linux-3.10.git] / arch / m68k / fpsp040 / kernel_ex.S
1 |
2 |       kernel_ex.sa 3.3 12/19/90
3 |
4 | This file contains routines to force exception status in the
5 | fpu for exceptional cases detected or reported within the
6 | transcendental functions.  Typically, the t_xx routine will
7 | set the appropriate bits in the USER_FPSR word on the stack.
8 | The bits are tested in gen_except.sa to determine if an exceptional
9 | situation needs to be created on return from the FPSP.
10 |
11
12 |               Copyright (C) Motorola, Inc. 1990
13 |                       All Rights Reserved
14 |
15 |       THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
16 |       The copyright notice above does not evidence any
17 |       actual or intended publication of such source code.
18
19 KERNEL_EX:    |idnt    2,1 | Motorola 040 Floating Point Software Package
20
21         |section    8
22
23 #include "fpsp.h"
24
25 mns_inf:  .long 0xffff0000,0x00000000,0x00000000
26 pls_inf:  .long 0x7fff0000,0x00000000,0x00000000
27 nan:      .long 0x7fff0000,0xffffffff,0xffffffff
28 huge:     .long 0x7ffe0000,0xffffffff,0xffffffff
29
30         |xref     ovf_r_k
31         |xref     unf_sub
32         |xref     nrm_set
33
34         .global   t_dz
35         .global      t_dz2
36         .global      t_operr
37         .global      t_unfl
38         .global      t_ovfl
39         .global      t_ovfl2
40         .global      t_inx2
41         .global   t_frcinx
42         .global   t_extdnrm
43         .global   t_resdnrm
44         .global   dst_nan
45         .global   src_nan
46 |
47 |       DZ exception
48 |
49 |
50 |       if dz trap disabled
51 |               store properly signed inf (use sign of etemp) into fp0
52 |               set FPSR exception status dz bit, condition code
53 |               inf bit, and accrued dz bit
54 |               return
55 |               frestore the frame into the machine (done by unimp_hd)
56 |
57 |       else dz trap enabled
58 |               set exception status bit & accrued bits in FPSR
59 |               set flag to disable sto_res from corrupting fp register
60 |               return
61 |               frestore the frame into the machine (done by unimp_hd)
62 |
63 | t_dz2 is used by monadic functions such as flogn (from do_func).
64 | t_dz is used by monadic functions such as satanh (from the
65 | transcendental function).
66 |
67 t_dz2:
68         bsetb   #neg_bit,FPSR_CC(%a6)   |set neg bit in FPSR
69         fmovel  #0,%FPSR                        |clr status bits (Z set)
70         btstb   #dz_bit,FPCR_ENABLE(%a6)        |test FPCR for dz exc enabled
71         bnes    dz_ena_end
72         bras    m_inf                   |flogx always returns -inf
73 t_dz:
74         fmovel  #0,%FPSR                        |clr status bits (Z set)
75         btstb   #dz_bit,FPCR_ENABLE(%a6)        |test FPCR for dz exc enabled
76         bnes    dz_ena
77 |
78 |       dz disabled
79 |
80         btstb   #sign_bit,ETEMP_EX(%a6) |check sign for neg or pos
81         beqs    p_inf                   |branch if pos sign
82
83 m_inf:
84         fmovemx mns_inf,%fp0-%fp0               |load -inf
85         bsetb   #neg_bit,FPSR_CC(%a6)   |set neg bit in FPSR
86         bras    set_fpsr
87 p_inf:
88         fmovemx pls_inf,%fp0-%fp0               |load +inf
89 set_fpsr:
90         orl     #dzinf_mask,USER_FPSR(%a6) |set I,DZ,ADZ
91         rts
92 |
93 |       dz enabled
94 |
95 dz_ena:
96         btstb   #sign_bit,ETEMP_EX(%a6) |check sign for neg or pos
97         beqs    dz_ena_end
98         bsetb   #neg_bit,FPSR_CC(%a6)   |set neg bit in FPSR
99 dz_ena_end:
100         orl     #dzinf_mask,USER_FPSR(%a6) |set I,DZ,ADZ
101         st      STORE_FLG(%a6)
102         rts
103 |
104 |       OPERR exception
105 |
106 |       if (operr trap disabled)
107 |               set FPSR exception status operr bit, condition code
108 |               nan bit; Store default NAN into fp0
109 |               frestore the frame into the machine (done by unimp_hd)
110 |
111 |       else (operr trap enabled)
112 |               set FPSR exception status operr bit, accrued operr bit
113 |               set flag to disable sto_res from corrupting fp register
114 |               frestore the frame into the machine (done by unimp_hd)
115 |
116 t_operr:
117         orl     #opnan_mask,USER_FPSR(%a6) |set NaN, OPERR, AIOP
118
119         btstb   #operr_bit,FPCR_ENABLE(%a6) |test FPCR for operr enabled
120         bnes    op_ena
121
122         fmovemx nan,%fp0-%fp0           |load default nan
123         rts
124 op_ena:
125         st      STORE_FLG(%a6)          |do not corrupt destination
126         rts
127
128 |
129 |       t_unfl --- UNFL exception
130 |
131 | This entry point is used by all routines requiring unfl, inex2,
132 | aunfl, and ainex to be set on exit.
133 |
134 | On entry, a0 points to the exceptional operand.  The final exceptional
135 | operand is built in FP_SCR1 and only the sign from the original operand
136 | is used.
137 |
138 t_unfl:
139         clrl    FP_SCR1(%a6)            |set exceptional operand to zero
140         clrl    FP_SCR1+4(%a6)
141         clrl    FP_SCR1+8(%a6)
142         tstb    (%a0)                   |extract sign from caller's exop
143         bpls    unfl_signok
144         bset    #sign_bit,FP_SCR1(%a6)
145 unfl_signok:
146         leal    FP_SCR1(%a6),%a0
147         orl     #unfinx_mask,USER_FPSR(%a6)
148 |                                       ;set UNFL, INEX2, AUNFL, AINEX
149 unfl_con:
150         btstb   #unfl_bit,FPCR_ENABLE(%a6)
151         beqs    unfl_dis
152
153 unfl_ena:
154         bfclr   STAG(%a6){#5:#3}                |clear wbtm66,wbtm1,wbtm0
155         bsetb   #wbtemp15_bit,WB_BYTE(%a6) |set wbtemp15
156         bsetb   #sticky_bit,STICKY(%a6) |set sticky bit
157
158         bclrb   #E1,E_BYTE(%a6)
159
160 unfl_dis:
161         bfextu  FPCR_MODE(%a6){#0:#2},%d0       |get round precision
162
163         bclrb   #sign_bit,LOCAL_EX(%a0)
164         sne     LOCAL_SGN(%a0)          |convert to internal ext format
165
166         bsr     unf_sub                 |returns IEEE result at a0
167 |                                       ;and sets FPSR_CC accordingly
168
169         bfclr   LOCAL_SGN(%a0){#0:#8}   |convert back to IEEE ext format
170         beqs    unfl_fin
171
172         bsetb   #sign_bit,LOCAL_EX(%a0)
173         bsetb   #sign_bit,FP_SCR1(%a6)  |set sign bit of exc operand
174
175 unfl_fin:
176         fmovemx (%a0),%fp0-%fp0         |store result in fp0
177         rts
178
179
180 |
181 |       t_ovfl2 --- OVFL exception (without inex2 returned)
182 |
183 | This entry is used by scale to force catastrophic overflow.  The
184 | ovfl, aovfl, and ainex bits are set, but not the inex2 bit.
185 |
186 t_ovfl2:
187         orl     #ovfl_inx_mask,USER_FPSR(%a6)
188         movel   ETEMP(%a6),FP_SCR1(%a6)
189         movel   ETEMP_HI(%a6),FP_SCR1+4(%a6)
190         movel   ETEMP_LO(%a6),FP_SCR1+8(%a6)
191 |
192 | Check for single or double round precision.  If single, check if
193 | the lower 40 bits of ETEMP are zero; if not, set inex2.  If double,
194 | check if the lower 21 bits are zero; if not, set inex2.
195 |
196         moveb   FPCR_MODE(%a6),%d0
197         andib   #0xc0,%d0
198         beq     t_work          |if extended, finish ovfl processing
199         cmpib   #0x40,%d0               |test for single
200         bnes    t_dbl
201 t_sgl:
202         tstb    ETEMP_LO(%a6)
203         bnes    t_setinx2
204         movel   ETEMP_HI(%a6),%d0
205         andil   #0xff,%d0               |look at only lower 8 bits
206         bnes    t_setinx2
207         bra     t_work
208 t_dbl:
209         movel   ETEMP_LO(%a6),%d0
210         andil   #0x7ff,%d0      |look at only lower 11 bits
211         beq     t_work
212 t_setinx2:
213         orl     #inex2_mask,USER_FPSR(%a6)
214         bras    t_work
215 |
216 |       t_ovfl --- OVFL exception
217 |
218 |** Note: the exc operand is returned in ETEMP.
219 |
220 t_ovfl:
221         orl     #ovfinx_mask,USER_FPSR(%a6)
222 t_work:
223         btstb   #ovfl_bit,FPCR_ENABLE(%a6) |test FPCR for ovfl enabled
224         beqs    ovf_dis
225
226 ovf_ena:
227         clrl    FP_SCR1(%a6)            |set exceptional operand
228         clrl    FP_SCR1+4(%a6)
229         clrl    FP_SCR1+8(%a6)
230
231         bfclr   STAG(%a6){#5:#3}                |clear wbtm66,wbtm1,wbtm0
232         bclrb   #wbtemp15_bit,WB_BYTE(%a6) |clear wbtemp15
233         bsetb   #sticky_bit,STICKY(%a6) |set sticky bit
234
235         bclrb   #E1,E_BYTE(%a6)
236 |                                       ;fall through to disabled case
237
238 | For disabled overflow call 'ovf_r_k'.  This routine loads the
239 | correct result based on the rounding precision, destination
240 | format, rounding mode and sign.
241 |
242 ovf_dis:
243         bsr     ovf_r_k                 |returns unsigned ETEMP_EX
244 |                                       ;and sets FPSR_CC accordingly.
245         bfclr   ETEMP_SGN(%a6){#0:#8}   |fix sign
246         beqs    ovf_pos
247         bsetb   #sign_bit,ETEMP_EX(%a6)
248         bsetb   #sign_bit,FP_SCR1(%a6)  |set exceptional operand sign
249 ovf_pos:
250         fmovemx ETEMP(%a6),%fp0-%fp0            |move the result to fp0
251         rts
252
253
254 |
255 |       INEX2 exception
256 |
257 | The inex2 and ainex bits are set.
258 |
259 t_inx2:
260         orl     #inx2a_mask,USER_FPSR(%a6) |set INEX2, AINEX
261         rts
262
263 |
264 |       Force Inex2
265 |
266 | This routine is called by the transcendental routines to force
267 | the inex2 exception bits set in the FPSR.  If the underflow bit
268 | is set, but the underflow trap was not taken, the aunfl bit in
269 | the FPSR must be set.
270 |
271 t_frcinx:
272         orl     #inx2a_mask,USER_FPSR(%a6) |set INEX2, AINEX
273         btstb   #unfl_bit,FPSR_EXCEPT(%a6) |test for unfl bit set
274         beqs    no_uacc1                |if clear, do not set aunfl
275         bsetb   #aunfl_bit,FPSR_AEXCEPT(%a6)
276 no_uacc1:
277         rts
278
279 |
280 |       DST_NAN
281 |
282 | Determine if the destination nan is signalling or non-signalling,
283 | and set the FPSR bits accordingly.  See the MC68040 User's Manual
284 | section 3.2.2.5 NOT-A-NUMBERS.
285 |
286 dst_nan:
287         btstb   #sign_bit,FPTEMP_EX(%a6) |test sign of nan
288         beqs    dst_pos                 |if clr, it was positive
289         bsetb   #neg_bit,FPSR_CC(%a6)   |set N bit
290 dst_pos:
291         btstb   #signan_bit,FPTEMP_HI(%a6) |check if signalling
292         beqs    dst_snan                |branch if signalling
293
294         fmovel  %d1,%fpcr                       |restore user's rmode/prec
295         fmovex FPTEMP(%a6),%fp0         |return the non-signalling nan
296 |
297 | Check the source nan.  If it is signalling, snan will be reported.
298 |
299         moveb   STAG(%a6),%d0
300         andib   #0xe0,%d0
301         cmpib   #0x60,%d0
302         bnes    no_snan
303         btstb   #signan_bit,ETEMP_HI(%a6) |check if signalling
304         bnes    no_snan
305         orl     #snaniop_mask,USER_FPSR(%a6) |set NAN, SNAN, AIOP
306 no_snan:
307         rts
308
309 dst_snan:
310         btstb   #snan_bit,FPCR_ENABLE(%a6) |check if trap enabled
311         beqs    dst_dis                 |branch if disabled
312
313         orb     #nan_tag,DTAG(%a6)      |set up dtag for nan
314         st      STORE_FLG(%a6)          |do not store a result
315         orl     #snaniop_mask,USER_FPSR(%a6) |set NAN, SNAN, AIOP
316         rts
317
318 dst_dis:
319         bsetb   #signan_bit,FPTEMP_HI(%a6) |set SNAN bit in sop
320         fmovel  %d1,%fpcr                       |restore user's rmode/prec
321         fmovex FPTEMP(%a6),%fp0         |load non-sign. nan
322         orl     #snaniop_mask,USER_FPSR(%a6) |set NAN, SNAN, AIOP
323         rts
324
325 |
326 |       SRC_NAN
327 |
328 | Determine if the source nan is signalling or non-signalling,
329 | and set the FPSR bits accordingly.  See the MC68040 User's Manual
330 | section 3.2.2.5 NOT-A-NUMBERS.
331 |
332 src_nan:
333         btstb   #sign_bit,ETEMP_EX(%a6) |test sign of nan
334         beqs    src_pos                 |if clr, it was positive
335         bsetb   #neg_bit,FPSR_CC(%a6)   |set N bit
336 src_pos:
337         btstb   #signan_bit,ETEMP_HI(%a6) |check if signalling
338         beqs    src_snan                |branch if signalling
339         fmovel  %d1,%fpcr                       |restore user's rmode/prec
340         fmovex ETEMP(%a6),%fp0          |return the non-signalling nan
341         rts
342
343 src_snan:
344         btstb   #snan_bit,FPCR_ENABLE(%a6) |check if trap enabled
345         beqs    src_dis                 |branch if disabled
346         bsetb   #signan_bit,ETEMP_HI(%a6) |set SNAN bit in sop
347         orb     #norm_tag,DTAG(%a6)     |set up dtag for norm
348         orb     #nan_tag,STAG(%a6)      |set up stag for nan
349         st      STORE_FLG(%a6)          |do not store a result
350         orl     #snaniop_mask,USER_FPSR(%a6) |set NAN, SNAN, AIOP
351         rts
352
353 src_dis:
354         bsetb   #signan_bit,ETEMP_HI(%a6) |set SNAN bit in sop
355         fmovel  %d1,%fpcr                       |restore user's rmode/prec
356         fmovex ETEMP(%a6),%fp0          |load non-sign. nan
357         orl     #snaniop_mask,USER_FPSR(%a6) |set NAN, SNAN, AIOP
358         rts
359
360 |
361 | For all functions that have a denormalized input and that f(x)=x,
362 | this is the entry point
363 |
364 t_extdnrm:
365         orl     #unfinx_mask,USER_FPSR(%a6)
366 |                                       ;set UNFL, INEX2, AUNFL, AINEX
367         bras    xdnrm_con
368 |
369 | Entry point for scale with extended denorm.  The function does
370 | not set inex2, aunfl, or ainex.
371 |
372 t_resdnrm:
373         orl     #unfl_mask,USER_FPSR(%a6)
374
375 xdnrm_con:
376         btstb   #unfl_bit,FPCR_ENABLE(%a6)
377         beqs    xdnrm_dis
378
379 |
380 | If exceptions are enabled, the additional task of setting up WBTEMP
381 | is needed so that when the underflow exception handler is entered,
382 | the user perceives no difference between what the 040 provides vs.
383 | what the FPSP provides.
384 |
385 xdnrm_ena:
386         movel   %a0,-(%a7)
387
388         movel   LOCAL_EX(%a0),FP_SCR1(%a6)
389         movel   LOCAL_HI(%a0),FP_SCR1+4(%a6)
390         movel   LOCAL_LO(%a0),FP_SCR1+8(%a6)
391
392         lea     FP_SCR1(%a6),%a0
393
394         bclrb   #sign_bit,LOCAL_EX(%a0)
395         sne     LOCAL_SGN(%a0)          |convert to internal ext format
396         tstw    LOCAL_EX(%a0)           |check if input is denorm
397         beqs    xdnrm_dn                |if so, skip nrm_set
398         bsr     nrm_set                 |normalize the result (exponent
399 |                                       ;will be negative
400 xdnrm_dn:
401         bclrb   #sign_bit,LOCAL_EX(%a0) |take off false sign
402         bfclr   LOCAL_SGN(%a0){#0:#8}   |change back to IEEE ext format
403         beqs    xdep
404         bsetb   #sign_bit,LOCAL_EX(%a0)
405 xdep:
406         bfclr   STAG(%a6){#5:#3}                |clear wbtm66,wbtm1,wbtm0
407         bsetb   #wbtemp15_bit,WB_BYTE(%a6) |set wbtemp15
408         bclrb   #sticky_bit,STICKY(%a6) |clear sticky bit
409         bclrb   #E1,E_BYTE(%a6)
410         movel   (%a7)+,%a0
411 xdnrm_dis:
412         bfextu  FPCR_MODE(%a6){#0:#2},%d0       |get round precision
413         bnes    not_ext                 |if not round extended, store
414 |                                       ;IEEE defaults
415 is_ext:
416         btstb   #sign_bit,LOCAL_EX(%a0)
417         beqs    xdnrm_store
418
419         bsetb   #neg_bit,FPSR_CC(%a6)   |set N bit in FPSR_CC
420
421         bras    xdnrm_store
422
423 not_ext:
424         bclrb   #sign_bit,LOCAL_EX(%a0)
425         sne     LOCAL_SGN(%a0)          |convert to internal ext format
426         bsr     unf_sub                 |returns IEEE result pointed by
427 |                                       ;a0; sets FPSR_CC accordingly
428         bfclr   LOCAL_SGN(%a0){#0:#8}   |convert back to IEEE ext format
429         beqs    xdnrm_store
430         bsetb   #sign_bit,LOCAL_EX(%a0)
431 xdnrm_store:
432         fmovemx (%a0),%fp0-%fp0         |store result in fp0
433         rts
434
435 |
436 | This subroutine is used for dyadic operations that use an extended
437 | denorm within the kernel. The approach used is to capture the frame,
438 | fix/restore.
439 |
440         .global t_avoid_unsupp
441 t_avoid_unsupp:
442         link    %a2,#-LOCAL_SIZE                |so that a2 fpsp.h negative
443 |                                       ;offsets may be used
444         fsave   -(%a7)
445         tstb    1(%a7)                  |check if idle, exit if so
446         beq     idle_end
447         btstb   #E1,E_BYTE(%a2)         |check for an E1 exception if
448 |                                       ;enabled, there is an unsupp
449         beq     end_avun                |else, exit
450         btstb   #7,DTAG(%a2)            |check for denorm destination
451         beqs    src_den                 |else, must be a source denorm
452 |
453 | handle destination denorm
454 |
455         lea     FPTEMP(%a2),%a0
456         btstb   #sign_bit,LOCAL_EX(%a0)
457         sne     LOCAL_SGN(%a0)          |convert to internal ext format
458         bclrb   #7,DTAG(%a2)            |set DTAG to norm
459         bsr     nrm_set                 |normalize result, exponent
460 |                                       ;will become negative
461         bclrb   #sign_bit,LOCAL_EX(%a0) |get rid of fake sign
462         bfclr   LOCAL_SGN(%a0){#0:#8}   |convert back to IEEE ext format
463         beqs    ck_src_den              |check if source is also denorm
464         bsetb   #sign_bit,LOCAL_EX(%a0)
465 ck_src_den:
466         btstb   #7,STAG(%a2)
467         beqs    end_avun
468 src_den:
469         lea     ETEMP(%a2),%a0
470         btstb   #sign_bit,LOCAL_EX(%a0)
471         sne     LOCAL_SGN(%a0)          |convert to internal ext format
472         bclrb   #7,STAG(%a2)            |set STAG to norm
473         bsr     nrm_set                 |normalize result, exponent
474 |                                       ;will become negative
475         bclrb   #sign_bit,LOCAL_EX(%a0) |get rid of fake sign
476         bfclr   LOCAL_SGN(%a0){#0:#8}   |convert back to IEEE ext format
477         beqs    den_com
478         bsetb   #sign_bit,LOCAL_EX(%a0)
479 den_com:
480         moveb   #0xfe,CU_SAVEPC(%a2)    |set continue frame
481         clrw    NMNEXC(%a2)             |clear NMNEXC
482         bclrb   #E1,E_BYTE(%a2)
483 |       fmove.l %FPSR,FPSR_SHADOW(%a2)
484 |       bset.b  #SFLAG,E_BYTE(%a2)
485 |       bset.b  #XFLAG,T_BYTE(%a2)
486 end_avun:
487         frestore (%a7)+
488         unlk    %a2
489         rts
490 idle_end:
491         addl    #4,%a7
492         unlk    %a2
493         rts
494         |end