1 * $NetBSD: gen_except.sa,v 1.3 1994/10/26 07:49:07 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.
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
38 * This routine compares the exception enable byte of the
39 * user_fpcr on the stack with the exception status byte
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:
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
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
92 lea.l BUSY_SIZE+LOCAL_SIZE(a7),a1 ;init a1 so fpsp.h
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
105 or.l d1,d0 ;put it in the right place
106 bfextu CMDREG1B(a6){10:3},d1 ;extract bit 3,4,5
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.
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)
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
128 cmpi.b #UNIMP_40_SIZE-4,1(a7) ;test for orig unimp frame
130 lea.l UNIMP_40_SIZE+LOCAL_SIZE(a7),a1
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
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.
146 or.l d0,USER_FPSR(a6)
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.
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.
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
171 move.l USER_FPSR(a6),FPSR_SHADOW(a6) ;set exc bits
172 or.l #sx_mask,E_BYTE(a6)
175 cmp.b #UNIMP_40_SIZE-4,1(a7)
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
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.
201 bset.b #E1,E_BYTE(a6) ;set E1 flag
202 bra.w commonE ;go clean and exit
205 tst.b UFLG_TMP(a6) ;test flag for unsup/unimp state
208 bset.b #E3,E_BYTE(a6) ;set E3 flag
209 bclr.b #E1,E_BYTE(a6) ;clr E1 from unimp
216 bset.b #E3,E_BYTE(a6) ;set E3 flag
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
224 or.l d1,d0 ;put it in the right place
225 bfextu CMDREG1B(a6){10:3},d1 ;extract bit 3,4,5
228 or.l d1,d0 ;put them in the right place
229 move.l d0,CMDREG3B(a6) ;in the busy frame
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
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
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.
251 tst.b UFLG_TMP(a6) ;test flag for unsupp/unimp state
254 tst.b RES_FLG(a6) ;check if frestore is needed
255 bne.w do_clean ;if clear, no frestore needed
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
263 * Unsupported Data Type Handler:
265 * An fmoveout that results in an overflow is reported this way.
267 * An fmoveout that results in an underflow is reported this way.
269 * Unimplemented Instruction Handler:
271 * Only scosh, setox, ssinh, stwotox, and scale can set overflow in
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.
283 tst.b UFLG_TMP(a6) ;test flag for unsupp/unimp state
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
292 * move.w #$fe,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
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
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
318 clr.l -(a7) ;clear and dec a7
320 move.b VER_TMP(a6),(a7)
321 move.b #BUSY_SIZE-4,1(a7) ;write busy fmt word.
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
336 or.l d1,d0 ;put it in the right place
337 bfextu CMDREG1B(a6){10:3},d1 ;extract bit 3,4,5
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.
355 cmpi.b #UNIMP_40_SIZE-4,1(a7)
357 moveq.l #13,d0 ;in orig, need to zero 14 lwords
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
365 move.b (a7),VER_TMP(a6)
368 clr.l -(a7) ;clear and dec a7
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)
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)
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
396 tst.b RES_FLG(a6) ;RES_FLG indicates a "continuation" frame
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.
409 btst.b #7,(a7) ;test T1 in SR
411 btst.b #6,(a7) ;test T0 in SR
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.
427 bftst EXC_VEC-4(sp){0:4}
430 subq.l #4,sp make room
435 fmove.l fpiar,BUSY_SIZE+EXC_EA-4(sp)
440 move.w #TRACE_VEC,EXC_VEC-4(a7)
443 * This is a work-around for hardware bug 1384.
448 cmpi.b #$41,(sp) ; check for correct frame
450 bgt nofix ; if more advanced mask, do nada
453 tst.b 1(sp) ; check to see if idle
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
461 move.l USER_D1(a6),d1 ; restore d1
462 move.l #$40280000,-(sp)
468 tst.b 1(sp) ; check to see if idle
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
476 move.l USER_D1(a6),d1 ; restore d1
477 move.l #$41300000,-(sp)
483 bclr.b #etemp15_bit,-40(a5)