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