netbsd.sa revision 1.6 1 * $NetBSD: netbsd.sa,v 1.6 2024/09/20 19:38:53 andvar Exp $
2
3 * MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
4 * M68000 Hi-Performance Microprocessor Division
5 * M68040 Software Package
6 *
7 * M68040 Software Package Copyright (c) 1993, 1994 Motorola Inc.
8 * All rights reserved.
9 *
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.
17 *
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.
25 *
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.
32
33 *
34 * skeleton.sa 3.2 4/26/91
35 *
36 * This file contains code that is system dependent and will
37 * need to be modified to install the FPSP.
38 *
39 * Each entry point for exception 'xxxx' begins with a 'jmp fpsp_xxxx'.
40 * Put any target system specific handling that must be done immediately
41 * before the jump instruction. If there no handling necessary, then
42 * the 'fpsp_xxxx' handler entry point should be placed in the exception
43 * table so that the 'jmp' can be eliminated. If the FPSP determines that the
44 * exception is one that must be reported then there will be a
45 * return from the package by a 'jmp real_xxxx'. At that point
46 * the machine state will be identical to the state before
47 * the FPSP was entered. In particular, whatever condition
48 * that caused the exception will still be pending when the FPSP
49 * package returns. Thus, there will be system specific code
50 * to handle the exception.
51 *
52 * If the exception was completely handled by the package, then
53 * the return will be via a 'jmp fpsp_done'. Unless there is
54 * OS specific work to be done (such as handling a context switch or
55 * interrupt) the user program can be resumed via 'rte'.
56 *
57 * In the following skeleton code, some typical 'real_xxxx' handling
58 * code is shown. This code may need to be moved to an appropriate
59 * place in the target system, or rewritten.
60 *
61
62 SKELETON IDNT 2,1 Motorola 040 Floating Point Software Package
63
64 section 15
65 *
66 * The following counters are used for standalone testing
67 *
68
69 section 8
70
71 include fpsp.h
72
73 *
74 * XXX Note, this is NOT valid Motorola syntax, but what else can we do?
75 *
76 #include <machine/asm.h>
77
78 xref b1238_fix
79 xref _C_LABEL(mmutype)
80
81 *
82 * Divide by Zero exception
83 *
84 * All dz exceptions are 'real', hence no fpsp_dz entry point.
85 *
86 xdef dz
87 xdef real_dz
88 dz:
89 cmp.l #-2,_C_LABEL(mmutype)
90 bne.l _C_LABEL(fpfault)
91 real_dz:
92 link a6,#-LOCAL_SIZE
93 fsave -(sp)
94 bclr.b #E1,E_BYTE(a6)
95 frestore (sp)+
96 unlk a6
97 jmp _C_LABEL(fpfault)
98
99 *
100 * Inexact exception
101 *
102 * All inexact exceptions are real, but the 'real' handler
103 * will probably want to clear the pending exception.
104 * The provided code will clear the E3 exception (if pending),
105 * otherwise clear the E1 exception. The frestore is not really
106 * necessary for E1 exceptions.
107 *
108 * Code following the 'inex' label is to handle bug #1232. In this
109 * bug, if an E1 snan, ovfl, or unfl occurred, and the process was
110 * swapped out before taking the exception, the exception taken on
111 * return was inex, rather than the correct exception. The snan, ovfl,
112 * and unfl exception to be taken must not have been enabled. The
113 * fix is to check for E1, and the existence of one of snan, ovfl,
114 * or unfl bits set in the fpsr. If any of these are set, branch
115 * to the appropriate handler for the exception in the fpsr. Note
116 * that this fix is only for d43b parts, and is skipped if the
117 * version number is not $40.
118 *
119 *
120 xdef real_inex
121 xdef inex
122 inex:
123 cmp.l #-2,_C_LABEL(mmutype)
124 bne.l _C_LABEL(fpfault)
125 link a6,#-LOCAL_SIZE
126 fsave -(sp)
127 cmpi.b #VER_40,(sp) ;test version number
128 bne.b not_fmt40
129 fmove.l fpsr,-(sp)
130 btst.b #E1,E_BYTE(a6) ;test for E1 set
131 beq.b not_b1232
132 btst.b #snan_bit,2(sp) ;test for snan
133 beq inex_ckofl
134 addq.l #4,sp
135 frestore (sp)+
136 unlk a6
137 bra snan
138 inex_ckofl:
139 btst.b #ovfl_bit,2(sp) ;test for ovfl
140 beq inex_ckufl
141 addq.l #4,sp
142 frestore (sp)+
143 unlk a6
144 bra ovfl
145 inex_ckufl:
146 btst.b #unfl_bit,2(sp) ;test for unfl
147 beq not_b1232
148 addq.l #4,sp
149 frestore (sp)+
150 unlk a6
151 bra unfl
152
153 *
154 * We do not have the bug 1232 case. Clean up the stack and call
155 * real_inex.
156 *
157 not_b1232:
158 addq.l #4,sp
159 frestore (sp)+
160 unlk a6
161
162 real_inex:
163 link a6,#-LOCAL_SIZE
164 fsave -(sp)
165 not_fmt40:
166 bclr.b #E3,E_BYTE(a6) ;clear and test E3 flag
167 beq.b inex_cke1
168 *
169 * Clear dirty bit on dest register in the frame before branching
170 * to b1238_fix.
171 *
172 movem.l d0/d1,USER_DA(a6)
173 bfextu CMDREG1B(a6){6:3},d0 ;get dest reg no
174 bclr.b d0,FPR_DIRTY_BITS(a6) ;clr dest dirty bit
175 bsr.l b1238_fix ;test for bug1238 case
176 movem.l USER_DA(a6),d0/d1
177 bra.b inex_done
178 inex_cke1:
179 bclr.b #E1,E_BYTE(a6)
180 inex_done:
181 frestore (sp)+
182 unlk a6
183 jmp _C_LABEL(fpfault)
184
185 *
186 * Overflow exception
187 *
188 xref fpsp_ovfl
189 xdef real_ovfl
190 xdef ovfl
191 ovfl:
192 cmp.l #-2,_C_LABEL(mmutype)
193 beq.l fpsp_ovfl
194 jmp _C_LABEL(fpfault)
195 real_ovfl:
196 link a6,#-LOCAL_SIZE
197 fsave -(sp)
198 bclr.b #E3,E_BYTE(a6) ;clear and test E3 flag
199 bne.b ovfl_done
200 bclr.b #E1,E_BYTE(a6)
201 ovfl_done:
202 frestore (sp)+
203 unlk a6
204 jmp _C_LABEL(fpfault)
205
206 *
207 * Underflow exception
208 *
209 xref fpsp_unfl
210 xdef real_unfl
211 xdef unfl
212 unfl:
213 cmp.l #-2,_C_LABEL(mmutype)
214 beq.l fpsp_unfl
215 jmp _C_LABEL(fpfault)
216 real_unfl:
217 link a6,#-LOCAL_SIZE
218 fsave -(sp)
219 bclr.b #E3,E_BYTE(a6) ;clear and test E3 flag
220 bne.b unfl_done
221 bclr.b #E1,E_BYTE(a6)
222 unfl_done:
223 frestore (sp)+
224 unlk a6
225 jmp _C_LABEL(fpfault)
226
227 *
228 * Signalling NAN exception
229 *
230 xref fpsp_snan
231 xdef real_snan
232 xdef snan
233 snan:
234 cmp.l #-2,_C_LABEL(mmutype)
235 beq.l fpsp_snan
236 jmp _C_LABEL(fpfault)
237 real_snan:
238 link a6,#-LOCAL_SIZE
239 fsave -(sp)
240 bclr.b #E1,E_BYTE(a6) ;snan is always an E1 exception
241 frestore (sp)+
242 unlk a6
243 jmp _C_LABEL(fpfault)
244
245 *
246 * Operand Error exception
247 *
248 xref fpsp_operr
249 xdef real_operr
250 xdef operr
251 operr:
252 cmp.l #-2,_C_LABEL(mmutype)
253 beq.l fpsp_operr
254 jmp _C_LABEL(fpfault)
255 real_operr:
256 link a6,#-LOCAL_SIZE
257 fsave -(sp)
258 bclr.b #E1,E_BYTE(a6) ;operr is always an E1 exception
259 frestore (sp)+
260 unlk a6
261 jmp _C_LABEL(fpfault)
262
263 *
264 * BSUN exception
265 *
266 * This sample handler simply clears the nan bit in the FPSR.
267 *
268 xref fpsp_bsun
269 xdef real_bsun
270 xdef bsun
271 bsun:
272 cmp.l #-2,_C_LABEL(mmutype)
273 beq.l fpsp_bsun
274 jmp _C_LABEL(fpfault)
275 real_bsun:
276 link a6,#-LOCAL_SIZE
277 fsave -(sp)
278 bclr.b #E1,E_BYTE(a6) ;bsun is always an E1 exception
279 fmove.l FPSR,-(sp)
280 bclr.b #nan_bit,(sp)
281 fmove.l (sp)+,FPSR
282 frestore (sp)+
283 unlk a6
284 jmp _C_LABEL(fpfault)
285
286 *
287 * F-line exception
288 *
289 * A 'real' F-line exception is one that the FPSP isn't supposed to
290 * handle. E.g. an instruction with a co-processor ID that is not 1.
291 *
292 *
293 xref fpsp_fline
294 xdef real_fline
295 xdef fline
296 fline:
297 cmp.l #-2,_C_LABEL(mmutype)
298 beq.l fpsp_fline
299 jmp _C_LABEL(fpfault)
300 real_fline:
301 jmp _C_LABEL(fpfault)
302
303 *
304 * Unsupported data type exception
305 *
306 xref fpsp_unsupp
307 xdef real_unsupp
308 xdef unsupp
309 unsupp:
310 cmp.l #-2,_C_LABEL(mmutype)
311 beq.l fpsp_unsupp
312 jmp _C_LABEL(fpfault)
313 real_unsupp:
314 link a6,#-LOCAL_SIZE
315 fsave -(sp)
316 bclr.b #E1,E_BYTE(a6) ;unsupp is always an E1 exception
317 frestore (sp)+
318 unlk a6
319 jmp _C_LABEL(fpfault)
320
321 *
322 * Trace exception
323 *
324 xdef real_trace
325 real_trace:
326 rte
327
328 *
329 * fpsp_fmt_error --- exit point for frame format error
330 *
331 * The fpu stack frame does not match the frames existing
332 * or planned at the time of this writing. The fpsp is
333 * unable to handle frame sizes not in the following
334 * version:size pairs:
335 *
336 * {4060, 4160} - busy frame
337 * {4028, 4130} - unimp frame
338 * {4000, 4100} - idle frame
339 *
340 * This entry point simply holds an f-line illegal value.
341 * Replace this with a call to your kernel panic code or
342 * code to handle future revisions of the fpu.
343 *
344 xdef fpsp_fmt_error
345 fpsp_fmt_error:
346 pea 1f
347 jsr _C_LABEL(panic)
348 dc.l $f27f0000 ;f-line illegal
349 1:
350 .asciz "bad floating point stack frame"
351 .even
352
353 *
354 * fpsp_done --- FPSP exit point
355 *
356 * The exception has been handled by the package and we are ready
357 * to return to user mode, but there may be OS specific code
358 * to execute before we do. If there is, do it now.
359 *
360 *
361 xref _ASM_LABEL(rei)
362 xdef fpsp_done
363 fpsp_done:
364 jmp _ASM_LABEL(rei)
365
366 *
367 * mem_write --- write to user or supervisor address space
368 *
369 * Writes to memory while in supervisor mode. copyout accomplishes
370 * this via a 'moves' instruction. copyout is a UNIX SVR3 (and later) function.
371 * If you don't have copyout, use the local copy of the function below.
372 *
373 * a0 - supervisor source address
374 * a1 - user destination address
375 * d0 - number of bytes to write (maximum count is 12)
376 *
377 * The supervisor source address is guaranteed to point into the supervisor
378 * stack. The result is that a UNIX
379 * process is allowed to sleep as a consequence of a page fault during
380 * copyout. The probability of a page fault is exceedingly small because
381 * the 68040 always reads the destination address and thus the page
382 * faults should have already been handled.
383 *
384 * If the EXC_SR shows that the exception was from supervisor space,
385 * then just do a dumb (and slow) memory move. In a UNIX environment
386 * there shouldn't be any supervisor mode floating point exceptions.
387 *
388 xdef mem_write
389 mem_write:
390 btst.b #5,EXC_SR(a6) ;check for supervisor state
391 beq.b user_write
392 super_write:
393 move.b (a0)+,(a1)+
394 subq.l #1,d0
395 bne.b super_write
396 rts
397 user_write:
398 move.l d1,-(sp) ;preserve d1 just in case
399 move.l d0,-(sp)
400 move.l a1,-(sp)
401 move.l a0,-(sp)
402 jsr _C_LABEL(copyout)
403 add.l #12,sp
404 move.l (sp)+,d1
405 rts
406
407 *
408 * mem_read --- read from user or supervisor address space
409 *
410 * Reads from memory while in supervisor mode. copyin accomplishes
411 * this via a 'moves' instruction. copyin is a UNIX SVR3 (and later) function.
412 * If you don't have copyin, use the local copy of the function below.
413 *
414 * The FPSP calls mem_read to read the original F-line instruction in order
415 * to extract the data register number when the 'Dn' addressing mode is
416 * used.
417 *
418 *Input:
419 * a0 - user source address
420 * a1 - supervisor destination address
421 * d0 - number of bytes to read (maximum count is 12)
422 *
423 * Like mem_write, mem_read always reads with a supervisor
424 * destination address on the supervisor stack. Also like mem_write,
425 * the EXC_SR is checked and a simple memory copy is done if reading
426 * from supervisor space is indicated.
427 *
428 xdef mem_read
429 mem_read:
430 btst.b #5,EXC_SR(a6) ;check for supervisor state
431 beq.b user_read
432 super_read:
433 move.b (a0)+,(a1)+
434 subq.l #1,d0
435 bne.b super_read
436 rts
437 user_read:
438 move.l d1,-(sp) ;preserve d1 just in case
439 move.l d0,-(sp)
440 move.l a1,-(sp)
441 move.l a0,-(sp)
442 jsr _C_LABEL(copyin)
443 add.l #12,sp
444 move.l (sp)+,d1
445 rts
446
447 end
448