No empty .Rs/.Re
[netbsd-mini2440.git] / sys / arch / m68k / fpsp / gen_except.sa
blob9d39022d398725e87c20783deb8d16f5aeafea4e
1 *       $NetBSD$
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 *       gen_except.sa 3.7 1/16/92
36 *       gen_except --- FPSP routine to detect reportable exceptions
37 *       
38 *       This routine compares the exception enable byte of the
39 *       user_fpcr on the stack with the exception status byte
40 *       of the user_fpsr. 
42 *       Any routine which may report an exceptions must load
43 *       the stack frame in memory with the exceptional operand(s).
45 *       Priority for exceptions is:
47 *       Highest:        bsun
48 *                       snan
49 *                       operr
50 *                       ovfl
51 *                       unfl
52 *                       dz
53 *                       inex2
54 *       Lowest:         inex1
56 *       Note: The IEEE standard specifies that inex2 is to be
57 *       reported if ovfl occurs and the ovfl enable bit is not
58 *       set but the inex2 enable bit is.  
61 GEN_EXCEPT    IDNT    2,1 Motorola 040 Floating Point Software Package
63         section 8
65         include fpsp.h
67         xref    real_trace
68         xref    fpsp_done
69         xref    fpsp_fmt_error
71 exc_tbl:
72         dc.l    bsun_exc
73         dc.l    commonE1
74         dc.l    commonE1
75         dc.l    ovfl_unfl
76         dc.l    ovfl_unfl
77         dc.l    commonE1
78         dc.l    commonE3
79         dc.l    commonE3
80         dc.l    no_match
82         xdef    gen_except
83 gen_except:
84         cmpi.b  #IDLE_SIZE-4,1(a7)      ;test for idle frame
85         beq.w   do_check                ;go handle idle frame
86         cmpi.b  #UNIMP_40_SIZE-4,1(a7)  ;test for orig unimp frame
87         beq.b   unimp_x                 ;go handle unimp frame
88         cmpi.b  #UNIMP_41_SIZE-4,1(a7)  ;test for rev unimp frame
89         beq.b   unimp_x                 ;go handle unimp frame
90         cmpi.b  #BUSY_SIZE-4,1(a7)      ;if size <> $60, fmt error
91         bne.l   fpsp_fmt_error
92         lea.l   BUSY_SIZE+LOCAL_SIZE(a7),a1 ;init a1 so fpsp.h
93 *                                       ;equates will work
94 * Fix up the new busy frame with entries from the unimp frame
96         move.l  ETEMP_EX(a6),ETEMP_EX(a1) ;copy etemp from unimp
97         move.l  ETEMP_HI(a6),ETEMP_HI(a1) ;frame to busy frame
98         move.l  ETEMP_LO(a6),ETEMP_LO(a1) 
99         move.l  CMDREG1B(a6),CMDREG1B(a1) ;set inst in frame to unimp
100         move.l  CMDREG1B(a6),d0         ;fix cmd1b to make it
101         and.l   #$03c30000,d0           ;work for cmd3b
102         bfextu  CMDREG1B(a6){13:1},d1   ;extract bit 2
103         lsl.l   #5,d1                   
104         swap    d1
105         or.l    d1,d0                   ;put it in the right place
106         bfextu  CMDREG1B(a6){10:3},d1   ;extract bit 3,4,5
107         lsl.l   #2,d1
108         swap    d1
109         or.l    d1,d0                   ;put them in the right place
110         move.l  d0,CMDREG3B(a1)         ;in the busy frame
112 * Or in the FPSR from the emulation with the USER_FPSR on the stack.
114         fmove.l FPSR,d0         
115         or.l    d0,USER_FPSR(a6)
116         move.l  USER_FPSR(a6),FPSR_SHADOW(a1) ;set exc bits
117         or.l    #sx_mask,E_BYTE(a1)
118         bra     do_clean
121 * Frame is an unimp frame possible resulting from an fmove <ea>,fp0
122 * that caused an exception
124 * a1 is modified to point into the new frame allowing fpsp equates
125 * to be valid.
127 unimp_x:
128         cmpi.b  #UNIMP_40_SIZE-4,1(a7)  ;test for orig unimp frame
129         bne.b   test_rev
130         lea.l   UNIMP_40_SIZE+LOCAL_SIZE(a7),a1
131         bra.b   unimp_con
132 test_rev:
133         cmpi.b  #UNIMP_41_SIZE-4,1(a7)  ;test for rev unimp frame
134         bne.l   fpsp_fmt_error          ;if not $28 or $30
135         lea.l   UNIMP_41_SIZE+LOCAL_SIZE(a7),a1
136         
137 unimp_con:
139 * Fix up the new unimp frame with entries from the old unimp frame
141         move.l  CMDREG1B(a6),CMDREG1B(a1) ;set inst in frame to unimp
143 * Or in the FPSR from the emulation with the USER_FPSR on the stack.
145         fmove.l FPSR,d0         
146         or.l    d0,USER_FPSR(a6)
147         bra     do_clean
150 * Frame is idle, so check for exceptions reported through
151 * USER_FPSR and set the unimp frame accordingly.  
152 * A7 must be incremented to the point before the
153 * idle fsave vector to the unimp vector.
155         
156 do_check:
157         add.l   #4,A7                   ;point A7 back to unimp frame
159 * Or in the FPSR from the emulation with the USER_FPSR on the stack.
161         fmove.l FPSR,d0         
162         or.l    d0,USER_FPSR(a6)
164 * On a busy frame, we must clear the nmnexc bits.
166         cmpi.b  #BUSY_SIZE-4,1(a7)      ;check frame type
167         bne.b   check_fr                ;if busy, clr nmnexc
168         clr.w   NMNEXC(a6)              ;clr nmnexc & nmcexc
169         btst.b  #5,CMDREG1B(a6)         ;test for fmove out
170         bne.b   frame_com
171         move.l  USER_FPSR(a6),FPSR_SHADOW(a6) ;set exc bits
172         or.l    #sx_mask,E_BYTE(a6)
173         bra.b   frame_com
174 check_fr:
175         cmp.b   #UNIMP_40_SIZE-4,1(a7)
176         beq.b   frame_com
177         clr.w   NMNEXC(a6)
178 frame_com:
179         move.b  FPCR_ENABLE(a6),d0      ;get fpcr enable byte
180         and.b   FPSR_EXCEPT(a6),d0      ;and in the fpsr exc byte
181         bfffo   d0{24:8},d1             ;test for first set bit
182         lea.l   exc_tbl,a0              ;load jmp table address
183         subi.b  #24,d1                  ;normalize bit offset to 0-8
184         move.l  (a0,d1.w*4),a0          ;load routine address based
185 *                                       ;based on first enabled exc
186         jmp     (a0)                    ;jump to routine
188 * Bsun is not possible in unimp or unsupp
190 bsun_exc:
191         bra     do_clean
193 * The typical work to be done to the unimp frame to report an 
194 * exception is to set the E1/E3 byte and clr the U flag.
195 * commonE1 does this for E1 exceptions, which are snan, 
196 * operr, and dz.  commonE3 does this for E3 exceptions, which 
197 * are inex2 and inex1, and also clears the E1 exception bit
198 * left over from the unimp exception.
200 commonE1:
201         bset.b  #E1,E_BYTE(a6)          ;set E1 flag
202         bra.w   commonE                 ;go clean and exit
204 commonE3:
205         tst.b   UFLG_TMP(a6)            ;test flag for unsup/unimp state
206         bne.b   unsE3
207 uniE3:
208         bset.b  #E3,E_BYTE(a6)          ;set E3 flag
209         bclr.b  #E1,E_BYTE(a6)          ;clr E1 from unimp
210         bra.w   commonE
212 unsE3:
213         tst.b   RES_FLG(a6)
214         bne.b   unsE3_0 
215 unsE3_1:
216         bset.b  #E3,E_BYTE(a6)          ;set E3 flag
217 unsE3_0:
218         bclr.b  #E1,E_BYTE(a6)          ;clr E1 flag
219         move.l  CMDREG1B(a6),d0
220         and.l   #$03c30000,d0           ;work for cmd3b
221         bfextu  CMDREG1B(a6){13:1},d1   ;extract bit 2
222         lsl.l   #5,d1                   
223         swap    d1
224         or.l    d1,d0                   ;put it in the right place
225         bfextu  CMDREG1B(a6){10:3},d1   ;extract bit 3,4,5
226         lsl.l   #2,d1
227         swap    d1
228         or.l    d1,d0                   ;put them in the right place
229         move.l  d0,CMDREG3B(a6)         ;in the busy frame
231 commonE:
232         bclr.b  #UFLAG,T_BYTE(a6)       ;clr U flag from unimp
233         bra.w   do_clean                ;go clean and exit
235 * No bits in the enable byte match existing exceptions.  Check for
236 * the case of the ovfl exc without the ovfl enabled, but with
237 * inex2 enabled.
239 no_match:
240         btst.b  #inex2_bit,FPCR_ENABLE(a6) ;check for ovfl/inex2 case
241         beq.b   no_exc                  ;if clear, exit
242         btst.b  #ovfl_bit,FPSR_EXCEPT(a6) ;now check ovfl
243         beq.b   no_exc                  ;if clear, exit
244         bra.b   ovfl_unfl               ;go to unfl_ovfl to determine if
245 *                                       ;it is an unsupp or unimp exc
246         
247 * No exceptions are to be reported.  If the instruction was 
248 * unimplemented, no FPU restore is necessary.  If it was
249 * unsupported, we must perform the restore.
250 no_exc:
251         tst.b   UFLG_TMP(a6)    ;test flag for unsupp/unimp state
252         beq.b   uni_no_exc
253 uns_no_exc:
254         tst.b   RES_FLG(a6)     ;check if frestore is needed
255         bne.w   do_clean        ;if clear, no frestore needed
256 uni_no_exc:
257         movem.l USER_DA(a6),d0-d1/a0-a1
258         fmovem.x USER_FP0(a6),fp0-fp3
259         fmovem.l USER_FPCR(a6),fpcr/fpsr/fpiar
260         unlk    a6
261         bra     finish_up
263 * Unsupported Data Type Handler:
264 * Ovfl:
265 *   An fmoveout that results in an overflow is reported this way.
266 * Unfl:
267 *   An fmoveout that results in an underflow is reported this way.
269 * Unimplemented Instruction Handler:
270 * Ovfl:
271 *   Only scosh, setox, ssinh, stwotox, and scale can set overflow in 
272 *   this manner.
273 * Unfl:
274 *   Stwotox, setox, and scale can set underflow in this manner.
275 *   Any of the other Library Routines such that f(x)=x in which
276 *   x is an extended denorm can report an underflow exception. 
277 *   It is the responsibility of the exception-causing exception 
278 *   to make sure that WBTEMP is correct.
280 *   The exceptional operand is in FP_SCR1.
282 ovfl_unfl:
283         tst.b   UFLG_TMP(a6)    ;test flag for unsupp/unimp state
284         beq.b   ofuf_con
286 * The caller was from an unsupported data type trap.  Test if the
287 * caller set CU_ONLY.  If so, the exceptional operand is expected in
288 * FPTEMP, rather than WBTEMP.
290         tst.b   CU_ONLY(a6)             ;test if inst is cu-only
291         beq.w   unsE3
292 *       move.w  #$fe,CU_SAVEPC(a6)
293         clr.b   CU_SAVEPC(a6)
294         bset.b  #E1,E_BYTE(a6)          ;set E1 exception flag
295         move.w  ETEMP_EX(a6),FPTEMP_EX(a6)
296         move.l  ETEMP_HI(a6),FPTEMP_HI(a6)
297         move.l  ETEMP_LO(a6),FPTEMP_LO(a6)
298         bset.b  #fptemp15_bit,DTAG(a6)  ;set fpte15
299         bclr.b  #UFLAG,T_BYTE(a6)       ;clr U flag from unimp
300         bra.w   do_clean                ;go clean and exit
302 ofuf_con:
303         move.b  (a7),VER_TMP(a6)        ;save version number
304         cmpi.b  #BUSY_SIZE-4,1(a7)      ;check for busy frame
305         beq.b   busy_fr                 ;if unimp, grow to busy
306         cmpi.b  #VER_40,(a7)            ;test for orig unimp frame
307         bne.b   try_41                  ;if not, test for rev frame
308         moveq.l #13,d0                  ;need to zero 14 lwords
309         bra.b   ofuf_fin
310 try_41:
311         cmpi.b  #VER_41,(a7)            ;test for rev unimp frame
312         bne.l   fpsp_fmt_error          ;if neither, exit with error
313         moveq.l #11,d0                  ;need to zero 12 lwords
315 ofuf_fin:
316         clr.l   (a7)
317 loop1:
318         clr.l   -(a7)                   ;clear and dec a7
319         dbra.w  d0,loop1
320         move.b  VER_TMP(a6),(a7)
321         move.b  #BUSY_SIZE-4,1(a7)              ;write busy fmt word.
322 busy_fr:
323         move.l  FP_SCR1(a6),WBTEMP_EX(a6)       ;write
324         move.l  FP_SCR1+4(a6),WBTEMP_HI(a6)     ;execptional op to
325         move.l  FP_SCR1+8(a6),WBTEMP_LO(a6)     ;wbtemp
326         bset.b  #E3,E_BYTE(a6)                  ;set E3 flag
327         bclr.b  #E1,E_BYTE(a6)                  ;make sure E1 is clear
328         bclr.b  #UFLAG,T_BYTE(a6)               ;clr U flag
329         move.l  USER_FPSR(a6),FPSR_SHADOW(a6)
330         or.l    #sx_mask,E_BYTE(a6)
331         move.l  CMDREG1B(a6),d0         ;fix cmd1b to make it
332         and.l   #$03c30000,d0           ;work for cmd3b
333         bfextu  CMDREG1B(a6){13:1},d1   ;extract bit 2
334         lsl.l   #5,d1                   
335         swap    d1
336         or.l    d1,d0                   ;put it in the right place
337         bfextu  CMDREG1B(a6){10:3},d1   ;extract bit 3,4,5
338         lsl.l   #2,d1
339         swap    d1
340         or.l    d1,d0                   ;put them in the right place
341         move.l  d0,CMDREG3B(a6)         ;in the busy frame
344 * Check if the frame to be restored is busy or unimp.
345 *** NOTE *** Bug fix for errata (0d43b #3)
346 * If the frame is unimp, we must create a busy frame to 
347 * fix the bug with the nmnexc bits in cases in which they
348 * are set by a previous instruction and not cleared by
349 * the save. The frame will be unimp only if the final 
350 * instruction in an emulation routine caused the exception
351 * by doing an fmove <ea>,fp0.  The exception operand, in
352 * internal format, is in fptemp.
354 do_clean:
355         cmpi.b  #UNIMP_40_SIZE-4,1(a7)
356         bne.b   do_con
357         moveq.l #13,d0                  ;in orig, need to zero 14 lwords
358         bra.b   do_build
359 do_con:
360         cmpi.b  #UNIMP_41_SIZE-4,1(a7)
361         bne.b   do_restore              ;frame must be busy
362         moveq.l #11,d0                  ;in rev, need to zero 12 lwords
364 do_build:
365         move.b  (a7),VER_TMP(a6)
366         clr.l   (a7)
367 loop2:
368         clr.l   -(a7)                   ;clear and dec a7
369         dbra.w  d0,loop2
371 * Use a1 as pointer into new frame.  a6 is not correct if an unimp or
372 * busy frame was created as the result of an exception on the final
373 * instruction of an emulation routine.
375 * We need to set the nmcexc bits if the exception is E1. Otherwise,
376 * the exc taken will be inex2.
378         lea.l   BUSY_SIZE+LOCAL_SIZE(a7),a1     ;init a1 for new frame
379         move.b  VER_TMP(a6),(a7)        ;write busy fmt word
380         move.b  #BUSY_SIZE-4,1(a7)
381         move.l  FP_SCR1(a6),WBTEMP_EX(a1)       ;write
382         move.l  FP_SCR1+4(a6),WBTEMP_HI(a1)     ;exceptional op to
383         move.l  FP_SCR1+8(a6),WBTEMP_LO(a1)     ;wbtemp
384 *       btst.b  #E1,E_BYTE(a1)
385 *       beq.b   do_restore
386         bfextu  USER_FPSR(a6){17:4},d0  ;get snan/operr/ovfl/unfl bits
387         bfins   d0,NMCEXC(a1){4:4}      ;and insert them in nmcexc
388         move.l  USER_FPSR(a6),FPSR_SHADOW(a1) ;set exc bits
389         or.l    #sx_mask,E_BYTE(a1)
390         
391 do_restore:
392         movem.l USER_DA(a6),d0-d1/a0-a1
393         fmovem.x USER_FP0(a6),fp0-fp3
394         fmovem.l USER_FPCR(a6),fpcr/fpsr/fpiar
395         frestore (a7)+
396         tst.b   RES_FLG(a6)     ;RES_FLG indicates a "continuation" frame
397         beq     cont
398         bsr     bug1384
399 cont:
400         unlk    a6
402 * If trace mode enabled, then go to trace handler.  This handler 
403 * cannot have any fp instructions.  If there are fp inst's and an 
404 * exception has been restored into the machine then the exception 
405 * will occur upon execution of the fp inst.  This is not desirable 
406 * in the kernel (supervisor mode).  See MC68040 manual Section 9.3.8.
408 finish_up:
409         btst.b  #7,(a7)         ;test T1 in SR
410         bne.b   g_trace
411         btst.b  #6,(a7)         ;test T0 in SR
412         bne.b   g_trace
413         bra.l   fpsp_done
415 * Change integer stack to look like trace stack
416 * The address of the instruction that caused the
417 * exception is already in the integer stack (is
418 * the same as the saved friar)
420 * If the current frame is already a 6-word stack then all
421 * that needs to be done is to change the vector# to TRACE.
422 * If the frame is only a 4-word stack (meaning we got here
423 * on an Unsupported data type exception), then we need to grow
424 * the stack an extra 2 words and get the FPIAR from the FPU.
426 g_trace:
427         bftst   EXC_VEC-4(sp){0:4}
428         bne     g_easy
430         subq.l  #4,sp           make room
431         move.l  4(sp),(sp)
432         move.l  8(sp),4(sp)
433         sub.l   #BUSY_SIZE,sp
434         fsave   (sp)
435         fmove.l fpiar,BUSY_SIZE+EXC_EA-4(sp)
436         frestore (sp)
437         add.l   #BUSY_SIZE,sp
439 g_easy:
440         move.w  #TRACE_VEC,EXC_VEC-4(a7)
441         bra.l   real_trace
443 *  This is a work-around for hardware bug 1384.
445 bug1384:
446         link    a5,#0
447         fsave   -(sp)
448         cmpi.b  #$41,(sp)       ; check for correct frame
449         beq     frame_41
450         bgt     nofix           ; if more advanced mask, do nada
452 frame_40:
453         tst.b   1(sp)           ; check to see if idle
454         bne     notidle
455 idle40:
456         clr.l   (sp)            ; get rid of old fsave frame
457         move.l  d1,USER_D1(a6)  ; save d1
458         move.w  #8,d1           ; place unimp frame instead
459 loop40: clr.l   -(sp)
460         dbra    d1,loop40
461         move.l  USER_D1(a6),d1  ; restore d1
462         move.l  #$40280000,-(sp)
463         frestore (sp)+
464         unlk    a5      
465         rts
467 frame_41:
468         tst.b   1(sp)           ; check to see if idle
469         bne     notidle 
470 idle41:
471         clr.l   (sp)            ; get rid of old fsave frame
472         move.l  d1,USER_D1(a6)  ; save d1
473         move.w  #10,d1          ; place unimp frame instead
474 loop41: clr.l   -(sp)
475         dbra    d1,loop41
476         move.l  USER_D1(a6),d1  ; restore d1
477         move.l  #$41300000,-(sp)
478         frestore (sp)+
479         unlk    a5      
480         rts
482 notidle:
483         bclr.b  #etemp15_bit,-40(a5) 
484         frestore (sp)+
485         unlk    a5      
486         rts
488 nofix:
489         frestore (sp)+
490         unlk    a5      
491         rts
493         end