1 | // |
---|
2 | // skeleton.sa 3.2 4/26/91 |
---|
3 | // |
---|
4 | // This file contains code that is system dependent and will |
---|
5 | // need to be modified to install the FPSP. |
---|
6 | // |
---|
7 | // Each entry point for exception 'xxxx' begins with a 'jmp fpsp_xxxx'. |
---|
8 | // Put any target system specific handling that must be done immediately |
---|
9 | // before the jump instruction. If there no handling necessary, then |
---|
10 | // the 'fpsp_xxxx' handler entry point should be placed in the exception |
---|
11 | // table so that the 'jmp' can be eliminated. If the FPSP determines that the |
---|
12 | // exception is one that must be reported then there will be a |
---|
13 | // return from the package by a 'jmp real_xxxx'. At that point |
---|
14 | // the machine state will be identical to the state before |
---|
15 | // the FPSP was entered. In particular, whatever condition |
---|
16 | // that caused the exception will still be pending when the FPSP |
---|
17 | // package returns. Thus, there will be system specific code |
---|
18 | // to handle the exception. |
---|
19 | // |
---|
20 | // If the exception was completely handled by the package, then |
---|
21 | // the return will be via a 'jmp fpsp_done'. Unless there is |
---|
22 | // OS specific work to be done (such as handling a context switch or |
---|
23 | // interrupt) the user program can be resumed via 'rte'. |
---|
24 | // |
---|
25 | // In the following skeleton code, some typical 'real_xxxx' handling |
---|
26 | // code is shown. This code may need to be moved to an appropriate |
---|
27 | // place in the target system, or rewritten. |
---|
28 | // |
---|
29 | |
---|
30 | // Copyright (C) Motorola, Inc. 1990 |
---|
31 | // All Rights Reserved |
---|
32 | // |
---|
33 | // THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA |
---|
34 | // The copyright notice above does not evidence any |
---|
35 | // actual or intended publication of such source code. |
---|
36 | |
---|
37 | // |
---|
38 | // Modified for Linux-1.3.x by Jes Sorensen (jds@kom.auc.dk) |
---|
39 | // |
---|
40 | |
---|
41 | #include <asm.h> |
---|
42 | |
---|
43 | //SKELETON idnt 2,1 | Motorola 040 Floating Point Software Package |
---|
44 | |
---|
45 | .include "fpsp.defs" |
---|
46 | |
---|
47 | // |
---|
48 | // Divide by Zero exception |
---|
49 | // |
---|
50 | // All dz exceptions are 'real', hence no fpsp_dz entry point. |
---|
51 | // |
---|
52 | .global SYM(_fpspEntry_dz) |
---|
53 | SYM(_fpspEntry_dz): |
---|
54 | link %a6,#-LOCAL_SIZE |
---|
55 | fsave -(%sp) |
---|
56 | bclrb #E1,E_BYTE(%a6) |
---|
57 | frestore (%sp)+ |
---|
58 | unlk %a6 |
---|
59 | jmp ([SYM(M68040FPSPUserExceptionHandlers)+3*4],za0) |
---|
60 | |
---|
61 | // |
---|
62 | // Inexact exception |
---|
63 | // |
---|
64 | // All inexact exceptions are real, but the 'real' handler |
---|
65 | // will probably want to clear the pending exception. |
---|
66 | // The provided code will clear the E3 exception (if pending), |
---|
67 | // otherwise clear the E1 exception. The frestore is not really |
---|
68 | // necessary for E1 exceptions. |
---|
69 | // |
---|
70 | // Code following the 'inex' label is to handle bug #1232. In this |
---|
71 | // bug, if an E1 snan, ovfl, or unfl occurred, and the process was |
---|
72 | // swapped out before taking the exception, the exception taken on |
---|
73 | // return was inex, rather than the correct exception. The snan, ovfl, |
---|
74 | // and unfl exception to be taken must not have been enabled. The |
---|
75 | // fix is to check for E1, and the existence of one of snan, ovfl, |
---|
76 | // or unfl bits set in the fpsr. If any of these are set, branch |
---|
77 | // to the appropriate handler for the exception in the fpsr. Note |
---|
78 | // that this fix is only for d43b parts, and is skipped if the |
---|
79 | // version number is not $40. |
---|
80 | // |
---|
81 | // |
---|
82 | .global SYM(_fpspEntry_inex) |
---|
83 | .global real_inex |
---|
84 | SYM(_fpspEntry_inex): |
---|
85 | link %a6,#-LOCAL_SIZE |
---|
86 | fsave -(%sp) |
---|
87 | cmpib #VER_40,(%sp) //test version number |
---|
88 | bnes not_fmt40 |
---|
89 | fmovel %fpsr,-(%sp) |
---|
90 | btstb #E1,E_BYTE(%a6) //test for E1 set |
---|
91 | beqs not_b1232 |
---|
92 | btstb #snan_bit,2(%sp) //test for snan |
---|
93 | beq inex_ckofl |
---|
94 | addl #4,%sp |
---|
95 | frestore (%sp)+ |
---|
96 | unlk %a6 |
---|
97 | bra snan |
---|
98 | inex_ckofl: |
---|
99 | btstb #ovfl_bit,2(%sp) //test for ovfl |
---|
100 | beq inex_ckufl |
---|
101 | addl #4,%sp |
---|
102 | frestore (%sp)+ |
---|
103 | unlk %a6 |
---|
104 | bra SYM(_fpspEntry_ovfl) |
---|
105 | inex_ckufl: |
---|
106 | btstb #unfl_bit,2(%sp) //test for unfl |
---|
107 | beq not_b1232 |
---|
108 | addl #4,%sp |
---|
109 | frestore (%sp)+ |
---|
110 | unlk %a6 |
---|
111 | bra SYM(_fpspEntry_unfl) |
---|
112 | |
---|
113 | // |
---|
114 | // We do not have the bug 1232 case. Clean up the stack and call |
---|
115 | // real_inex. |
---|
116 | // |
---|
117 | not_b1232: |
---|
118 | addl #4,%sp |
---|
119 | frestore (%sp)+ |
---|
120 | unlk %a6 |
---|
121 | |
---|
122 | real_inex: |
---|
123 | link %a6,#-LOCAL_SIZE |
---|
124 | fsave -(%sp) |
---|
125 | not_fmt40: |
---|
126 | bclrb #E3,E_BYTE(%a6) //clear and test E3 flag |
---|
127 | beqs inex_cke1 |
---|
128 | // |
---|
129 | // Clear dirty bit on dest resister in the frame before branching |
---|
130 | // to b1238_fix. |
---|
131 | // |
---|
132 | moveml %d0/%d1,USER_DA(%a6) |
---|
133 | bfextu CMDREG1B(%a6){#6:#3},%d0 //get dest reg no |
---|
134 | bclrb %d0,FPR_DIRTY_BITS(%a6) //clr dest dirty bit |
---|
135 | bsrl b1238_fix //test for bug1238 case |
---|
136 | moveml USER_DA(%a6),%d0/%d1 |
---|
137 | bras inex_done |
---|
138 | inex_cke1: |
---|
139 | bclrb #E1,E_BYTE(%a6) |
---|
140 | inex_done: |
---|
141 | frestore (%sp)+ |
---|
142 | unlk %a6 |
---|
143 | jmp ([SYM(M68040FPSPUserExceptionHandlers)+2*4],za0) |
---|
144 | |
---|
145 | // |
---|
146 | // Overflow exception |
---|
147 | // |
---|
148 | .global SYM(_fpspEntry_ovfl) |
---|
149 | .global real_ovfl |
---|
150 | SYM(_fpspEntry_ovfl): |
---|
151 | jmp fpsp_ovfl |
---|
152 | real_ovfl: |
---|
153 | link %a6,#-LOCAL_SIZE |
---|
154 | fsave -(%sp) |
---|
155 | bclrb #E3,E_BYTE(%a6) //clear and test E3 flag |
---|
156 | bnes ovfl_done |
---|
157 | bclrb #E1,E_BYTE(%a6) |
---|
158 | ovfl_done: |
---|
159 | frestore (%sp)+ |
---|
160 | unlk %a6 |
---|
161 | jmp ([SYM(M68040FPSPUserExceptionHandlers)+6*4],za0) |
---|
162 | |
---|
163 | // |
---|
164 | // Underflow exception |
---|
165 | // |
---|
166 | .global SYM(_fpspEntry_unfl) |
---|
167 | .global real_unfl |
---|
168 | SYM(_fpspEntry_unfl): |
---|
169 | jmp fpsp_unfl |
---|
170 | real_unfl: |
---|
171 | link %a6,#-LOCAL_SIZE |
---|
172 | fsave -(%sp) |
---|
173 | bclrb #E3,E_BYTE(%a6) //clear and test E3 flag |
---|
174 | bnes unfl_done |
---|
175 | bclrb #E1,E_BYTE(%a6) |
---|
176 | unfl_done: |
---|
177 | frestore (%sp)+ |
---|
178 | unlk %a6 |
---|
179 | jmp ([SYM(M68040FPSPUserExceptionHandlers)+4*4],za0) |
---|
180 | |
---|
181 | // |
---|
182 | // Signalling NAN exception |
---|
183 | // |
---|
184 | .global SYM(_fpspEntry_snan) |
---|
185 | .global real_snan |
---|
186 | SYM(_fpspEntry_snan): |
---|
187 | snan: |
---|
188 | jmp fpsp_snan |
---|
189 | real_snan: |
---|
190 | link %a6,#-LOCAL_SIZE |
---|
191 | fsave -(%sp) |
---|
192 | bclrb #E1,E_BYTE(%a6) //snan is always an E1 exception |
---|
193 | frestore (%sp)+ |
---|
194 | unlk %a6 |
---|
195 | jmp ([SYM(M68040FPSPUserExceptionHandlers)+7*4],za0) |
---|
196 | |
---|
197 | // |
---|
198 | // Operand Error exception |
---|
199 | // |
---|
200 | .global SYM(_fpspEntry_operr) |
---|
201 | .global real_operr |
---|
202 | SYM(_fpspEntry_operr): |
---|
203 | jmp fpsp_operr |
---|
204 | real_operr: |
---|
205 | link %a6,#-LOCAL_SIZE |
---|
206 | fsave -(%sp) |
---|
207 | bclrb #E1,E_BYTE(%a6) //operr is always an E1 exception |
---|
208 | frestore (%sp)+ |
---|
209 | unlk %a6 |
---|
210 | jmp ([SYM(M68040FPSPUserExceptionHandlers)+5*4],za0) |
---|
211 | |
---|
212 | // |
---|
213 | // BSUN exception |
---|
214 | // |
---|
215 | // This sample handler simply clears the nan bit in the FPSR. |
---|
216 | // |
---|
217 | .global SYM(_fpspEntry_bsun) |
---|
218 | .global real_bsun |
---|
219 | SYM(_fpspEntry_bsun): |
---|
220 | jmp fpsp_bsun |
---|
221 | real_bsun: |
---|
222 | link %a6,#-LOCAL_SIZE |
---|
223 | fsave -(%sp) |
---|
224 | bclrb #E1,E_BYTE(%a6) //bsun is always an E1 exception |
---|
225 | fmovel %FPSR,-(%sp) |
---|
226 | bclrb #nan_bit,(%sp) |
---|
227 | fmovel (%sp)+,%FPSR |
---|
228 | frestore (%sp)+ |
---|
229 | unlk %a6 |
---|
230 | jmp ([SYM(M68040FPSPUserExceptionHandlers)+1*4],za0) |
---|
231 | |
---|
232 | // |
---|
233 | // F-line exception |
---|
234 | // |
---|
235 | // A 'real' F-line exception is one that the FPSP is not supposed to |
---|
236 | // handle. E.g. an instruction with a co-processor ID that is not 1. |
---|
237 | // |
---|
238 | .global SYM(_fpspEntry_fline) |
---|
239 | .global real_fline |
---|
240 | SYM(_fpspEntry_fline): |
---|
241 | jmp fpsp_fline |
---|
242 | real_fline: |
---|
243 | jmp ([SYM(M68040FPSPUserExceptionHandlers)+0*4],za0) |
---|
244 | |
---|
245 | // |
---|
246 | // Unsupported data type exception |
---|
247 | // |
---|
248 | .global SYM(_fpspEntry_unsupp) |
---|
249 | .global real_unsupp |
---|
250 | SYM(_fpspEntry_unsupp): |
---|
251 | jmp fpsp_unsupp |
---|
252 | real_unsupp: |
---|
253 | link %a6,#-LOCAL_SIZE |
---|
254 | fsave -(%sp) |
---|
255 | bclrb #E1,E_BYTE(%a6) //unsupp is always an E1 exception |
---|
256 | frestore (%sp)+ |
---|
257 | unlk %a6 |
---|
258 | jmp ([SYM(M68040FPSPUserExceptionHandlers)+8*4],za0) |
---|
259 | |
---|
260 | // |
---|
261 | // Trace exception |
---|
262 | // |
---|
263 | .global real_trace |
---|
264 | real_trace: |
---|
265 | trap #10 |
---|
266 | |
---|
267 | // |
---|
268 | // fpsp_fmt_error --- exit point for frame format error |
---|
269 | // |
---|
270 | // The fpu stack frame does not match the frames existing |
---|
271 | // or planned at the time of this writing. The fpsp is |
---|
272 | // unable to handle frame sizes not in the following |
---|
273 | // version:size pairs: |
---|
274 | // |
---|
275 | // {4060, 4160} - busy frame |
---|
276 | // {4028, 4130} - unimp frame |
---|
277 | // {4000, 4100} - idle frame |
---|
278 | // |
---|
279 | .global fpsp_fmt_error |
---|
280 | fpsp_fmt_error: |
---|
281 | trap #11 |
---|
282 | |
---|
283 | // |
---|
284 | // fpsp_done --- FPSP exit point |
---|
285 | // |
---|
286 | // The exception has been handled by the package and we are ready |
---|
287 | // to return to user mode, but there may be OS specific code |
---|
288 | // to execute before we do. If there is, do it now. |
---|
289 | // |
---|
290 | // For now, the RTEMS does not bother looking at the |
---|
291 | // possibility that it is time to reschedule.... |
---|
292 | // |
---|
293 | |
---|
294 | .global fpsp_done |
---|
295 | fpsp_done: |
---|
296 | rte |
---|
297 | |
---|
298 | // |
---|
299 | // mem_write --- write to user or supervisor address space |
---|
300 | // |
---|
301 | // Writes to memory while in supervisor mode. |
---|
302 | // |
---|
303 | // a0 - supervisor source address |
---|
304 | // a1 - user/supervisor destination address |
---|
305 | // d0 - number of bytes to write (maximum count is 12) |
---|
306 | // |
---|
307 | .global mem_write |
---|
308 | mem_write: |
---|
309 | btstb #5,EXC_SR(%a6) //check for supervisor state |
---|
310 | beqs user_write |
---|
311 | super_write: |
---|
312 | moveb (%a0)+,(%a1)+ |
---|
313 | subql #1,%d0 |
---|
314 | bnes super_write |
---|
315 | rts |
---|
316 | user_write: |
---|
317 | movel %d1,-(%sp) //preserve d1 just in case |
---|
318 | movel %d0,-(%sp) |
---|
319 | movel %a1,-(%sp) |
---|
320 | movel %a0,-(%sp) |
---|
321 | jsr copyout |
---|
322 | addw #12,%sp |
---|
323 | movel (%sp)+,%d1 |
---|
324 | rts |
---|
325 | // |
---|
326 | // mem_read --- read from user or supervisor address space |
---|
327 | // |
---|
328 | // Reads from memory while in supervisor mode. |
---|
329 | // |
---|
330 | // The FPSP calls mem_read to read the original F-line instruction in order |
---|
331 | // to extract the data register number when the 'Dn' addressing mode is |
---|
332 | // used. |
---|
333 | // |
---|
334 | //Input: |
---|
335 | // a0 - user/supervisor source address |
---|
336 | // a1 - supervisor destination address |
---|
337 | // d0 - number of bytes to read (maximum count is 12) |
---|
338 | // |
---|
339 | // Like mem_write, mem_read always reads with a supervisor |
---|
340 | // destination address on the supervisor stack. Also like mem_write, |
---|
341 | // the EXC_SR is checked and a simple memory copy is done if reading |
---|
342 | // from supervisor space is indicated. |
---|
343 | // |
---|
344 | .global mem_read |
---|
345 | mem_read: |
---|
346 | btstb #5,EXC_SR(%a6) //check for supervisor state |
---|
347 | beqs user_read |
---|
348 | super_read: |
---|
349 | moveb (%a0)+,(%a1)+ |
---|
350 | subql #1,%d0 |
---|
351 | bnes super_read |
---|
352 | rts |
---|
353 | user_read: |
---|
354 | movel %d1,-(%sp) //preserve d1 just in case |
---|
355 | movel %d0,-(%sp) |
---|
356 | movel %a1,-(%sp) |
---|
357 | movel %a0,-(%sp) |
---|
358 | jsr copyin |
---|
359 | addw #12,%sp |
---|
360 | movel (%sp)+,%d1 |
---|
361 | rts |
---|
362 | |
---|
363 | // |
---|
364 | // Use these routines if your kernel does not have copyout/copyin equivalents. |
---|
365 | // Assumes that D0/D1/A0/A1 are scratch registers. copyout overwrites DFC, |
---|
366 | // and copyin overwrites SFC. |
---|
367 | // |
---|
368 | copyout: |
---|
369 | movel 4(%sp),%a0 // source |
---|
370 | movel 8(%sp),%a1 // destination |
---|
371 | movel 12(%sp),%d0 // count |
---|
372 | subl #1,%d0 // dec count by 1 for dbra |
---|
373 | movel #1,%d1 |
---|
374 | movec %d1,%DFC // set dfc for user data space |
---|
375 | moreout: |
---|
376 | moveb (%a0)+,%d1 // fetch supervisor byte |
---|
377 | movesb %d1,(%a1)+ // write user byte |
---|
378 | dbf %d0,moreout |
---|
379 | rts |
---|
380 | |
---|
381 | copyin: |
---|
382 | movel 4(%sp),%a0 // source |
---|
383 | movel 8(%sp),%a1 // destination |
---|
384 | movel 12(%sp),%d0 // count |
---|
385 | subl #1,%d0 // dec count by 1 for dbra |
---|
386 | movel #1,%d1 |
---|
387 | movec %d1,%SFC // set sfc for user space |
---|
388 | morein: |
---|
389 | movesb (%a0)+,%d1 // fetch user byte |
---|
390 | moveb %d1,(%a1)+ // write supervisor byte |
---|
391 | dbf %d0,morein |
---|
392 | rts |
---|
393 | |
---|
394 | |end |
---|