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