config: fix build with external compiler by passing the sysroot where needed
[AROS.git] / arch / m68k-all / kernel / m68k_exception.c
blob3dbdc288f629537c0eaf2f2b17869a9d38e4865c
1 /*
2 copyright © 1995-2010, the aros development team. all rights reserved.
3 $id$
5 desc: m68k-amiga bootstrap to exec.
6 lang: english
7 */
9 #define DEBUG 0
10 #include <aros/kernel.h>
11 #include <aros/debug.h>
12 #include <aros/asmcall.h>
14 #include <exec/resident.h>
15 #include <exec/execbase.h>
16 #include <exec/memory.h>
18 #include "exec_intern.h"
20 #include "m68k_exception.h"
22 /* Here's how it's all laid out on the Amiga
23 * M68K Exception
24 * 0 Reset: Initial SP
25 * 1 Reset: Initial PC (NOTE: Really is AbsExecBase!)
26 * 2 Bus Error
27 * 3 Address Error
28 * 4 Illegal Instruction
29 * 5 Divide by Zero
30 * 6 CHK Instruction
31 * 7 TRAPV Instruction
32 * 8 Privileged Instruction
33 * 9 Trace
34 * 10 Line 1010 Emulator
35 * 11 Line 1111 Emulator
36 * 12 -
37 * 13 -
38 * 14 Format Error
39 * 15 Uninitilaized Interrupt Vector
40 * 16 -
41 * ..
42 * 23 -
43 * 24 Spurious Interrupt
44 * 25 Level 1 Interrupt
45 * Paula 0: Serial TX
46 * Paula 1: Disk DMA done
47 * Paula 2: Software Int
48 * 26 Level 2 Interrupt
49 * Paula 3: CIA
50 * 27 Level 3 Interrupt
51 * Paula 4: Copper
52 * Paula 5: Vert Blank
53 * Paula 6: Blitter
54 * 28 Level 4 Interrupt
55 * Paula 7: Audio 0
56 * Paula 8: Audio 1
57 * Paula 9: Audio 2
58 * Paula 10: Audio 3
59 * 29 Level 5 Interrupt
60 * Paula 11: Serial RX
61 * Paula 12: Disk Sync
62 * 30 Level 6 Interrupt
63 * Paula 13: External
64 * Paula 14: Copper (special)
65 * 31 Level 7 Interrupt
66 * Paula 15: NMI
67 * 32 TRAP #0
68 * ..
69 * 47 TRAP #15
70 * 48 -
71 * ..
72 * 63 AbsExecBase (copy)
73 * 64 User 1
74 * ..
75 * 255 User 191
78 extern ULONG M68KFaultTable_00[];
79 asm (
80 " .text\n"
81 " .align 4\n"
82 " .globl M68KFaultTable_00\n"
83 "M68KFaultTable_00:\n"
84 ".Lfault_0: bsr.w .Lfault\n" // Placeholder
85 ".Lfault_1: bsr.w .Lfault\n" // Placeholder
86 ".Lfault_2: bsr.w .Lfault\n" // Bus Error
87 ".Lfault_3: bsr.w .Lfault\n" // Address Error
88 ".Lfault_4: bsr.w .Lfault\n" // Illegal instruction
89 ".Lfault_5: bsr.w .Lfault\n" // Zero divide
90 ".Lfault_6: bsr.w .Lfault\n" // CHK
91 ".Lfault_7: bsr.w .Lfault\n" // TRAPV
92 ".Lfault_8: bsr.w .Lfault\n" // Privilege violation
93 ".Lfault_9: bsr.w .Lfault\n" // Trace
94 ".Lfault_10: bsr.w .Lfault\n" // Line A
95 ".Lfault_11: bsr.w .Lfault\n" // Line F
96 ".Lfault_12: bsr.w .Lfault\n" // Placeholder
97 ".Lfault_13: bsr.w .Lfault\n" // Placeholder
98 ".Lfault_14: bsr.w .Lfault\n" // Placeholder
99 ".Lfault_15: bsr.w .Lfault\n" // Placeholder
100 ".Lfault_16: bsr.w .Lfault\n" // Placeholder
101 ".Lfault_17: bsr.w .Lfault\n" // Placeholder
102 ".Lfault_18: bsr.w .Lfault\n" // Placeholder
103 ".Lfault_19: bsr.w .Lfault\n" // Placeholder
104 ".Lfault_20: bsr.w .Lfault\n" // Placeholder
105 ".Lfault_21: bsr.w .Lfault\n" // Placeholder
106 ".Lfault_22: bsr.w .Lfault\n" // Placeholder
107 ".Lfault_23: bsr.w .Lfault\n" // Placeholder
108 ".Lfault: subi.l #(M68KFaultTable_00 + 1*4 - 0*4),%sp@\n"
109 " jmp M68KExceptionHelper\n"
112 extern ULONG M68KLevelTable_00[];
113 asm (
114 " .text\n"
115 " .align 4\n"
116 " .globl M68KLevelTable_00\n"
117 "M68KLevelTable_00:\n"
118 ".Llevel_0: bsr.w .Llevel\n" // Spurious Interrupt
119 ".Llevel_1: bsr.w .Llevel\n" // Level 1 Interrupt
120 ".Llevel_2: bsr.w .Llevel\n" // Level 2 Interrupt
121 ".Llevel_3: bsr.w .Llevel\n" // Level 3 Interrupt
122 ".Llevel_4: bsr.w .Llevel\n" // Level 4 Interrupt
123 ".Llevel_5: bsr.w .Llevel\n" // Level 5 Interrupt
124 ".Llevel_6: bsr.w .Llevel\n" // Level 6 Interrupt
125 ".Llevel_7: bsr.w .Llevel\n" // Level 7 Interrupt
126 ".Llevel: subi.l #(M68KLevelTable_00 + 1*4 - 24*4),%sp@\n"
127 " jmp M68KExceptionHelper\n"
130 extern ULONG M68KTrapTable_00[];
131 asm (
132 " .text\n"
133 " .align 4\n"
134 " .globl M68KTrapTable_00\n"
135 "M68KTrapTable_00:\n"
136 ".Ltrap_0: bsr.w .Ltrap\n" // TRAP #0
137 ".Ltrap_1: bsr.w .Ltrap\n" // TRAP #1
138 ".Ltrap_2: bsr.w .Ltrap\n" // ...
139 ".Ltrap_3: bsr.w .Ltrap\n" // ...
140 ".Ltrap_4: bsr.w .Ltrap\n" // ...
141 ".Ltrap_5: bsr.w .Ltrap\n" // ...
142 ".Ltrap_6: bsr.w .Ltrap\n" // ...
143 ".Ltrap_7: bsr.w .Ltrap\n" // ...
144 ".Ltrap_8: bsr.w .Ltrap\n" // ...
145 ".Ltrap_9: bsr.w .Ltrap\n" // ...
146 ".Ltrap_10: bsr.w .Ltrap\n" // ...
147 ".Ltrap_11: bsr.w .Ltrap\n" // ...
148 ".Ltrap_12: bsr.w .Ltrap\n" // ...
149 ".Ltrap_13: bsr.w .Ltrap\n" // ...
150 ".Ltrap_14: bsr.w .Ltrap\n" // ...
151 ".Ltrap_15: bsr.w .Ltrap\n" // TRAP #15
152 ".Ltrap: subi.l #(M68KTrapTable_00 + 1*4 - 32*4),%sp@\n"
153 " jmp M68KExceptionHelper\n"
156 /* 68000 Exceptions */
157 static void M68KExceptionInit_00(struct ExecBase *SysBase)
159 APTR *exception = (APTR *)0;
160 int i;
162 /* Faults */
163 for (i = 2; i < 24; i++)
164 exception[i] = &M68KFaultTable_00[i];
166 /* Level interrupts */
167 for (i = 0; i < 7; i++)
168 exception[i + 24] = &M68KLevelTable_00[i];
170 /* NMI (exception[31]) is left unset, for debuggers */
172 /* Traps */
173 for (i = 0; i < 16; i++)
174 exception[i + 32] = &M68KTrapTable_00[i];
177 /* 68010 Traps */
179 /* For the 68010+, the lower 12 bits of the UWORD
180 * at %sp@(6) contains the vector number.
181 * Convenience!
183 extern void M68KTrapHelper_10(void);
184 asm (
185 " .text\n"
186 " .align 4\n"
187 " .globl M68KTrapHelper_10\n"
188 "M68KTrapHelper_10:\n"
189 " move.w %sp@(6),%sp@-\n" // Copy the vector
190 " andi.w #0x0fff,%sp@\n" // Clear the upper bits
191 " clr.w %sp@-\n" // extend vector to long
192 " jmp M68KExceptionHelper\n"
195 static void M68KExceptionInit_10(struct ExecBase *SysBase)
197 APTR *exception = (APTR *)0;
198 int i;
200 /* We can use the same code for all M68010+ traps */
201 for (i = 2; i < 64; i++) {
202 /* Don't touch the NMI exception (for debuggers) */
203 if (i == 31)
204 continue;
205 exception[i] = M68KTrapHelper_10;
209 /******************** Exceptions *****************/
211 /* The stack frame here:
212 * Return PC ULONG@(6)
213 * Return SR UWORD@(4)
214 * Exception Vector ULONG@(0)
215 * SP ->
217 * When we call M68KExceptionAction:
218 * Return PC (4)
219 * Return SR (2)
220 * TrapArg (4)
221 * TrapCode (4)
222 * D0-D1/A0-A1 (4 * 4) <= NO TOUCHING!
223 * Pointer to trapcode/arg (4)
224 * Exception Vector (4)
226 * When we come back:
227 * Restore D0-D1/A0-A1
228 * Either execute the trap, or just return.
229 * RTE
231 extern void M68KExceptionHelper(void);
232 asm (
233 " .text\n"
234 " .globl M68KExceptionHelper\n"
235 "M68KExceptionHelper:\n"
236 " clr.l %sp@-\n" // Save space for tc
237 " movem.l %d0-%d1/%a0-%a1,%sp@-\n"// Save regs
238 " lea.l %sp@(4*(4)),%a0\n" // Get location of tc/ta
239 " move.l %sp@(4*(4+1)),%d0\n" // Get exception vector
240 " jsr M68KExceptionAction\n" // Call action routine
241 " movem.l %sp@+,%d0-%d1/%a0-%a1\n"// Restore regs
242 " tst.l %sp@\n" // NULL trapcode? Just return
243 " beq.s 1f\n"
244 " rts\n" // Execute tc_TrapCode
245 "1:\n"
246 " addq.l #4,%sp\n"
247 "0:\n"
248 " addq.l #4,%sp\n" // Drop TrapCode parameter
249 " rte\n" // And return
252 /* Default handler */
253 extern void Exec_MagicResetCode(void);
254 extern struct ExecBase *AbsExecBase;
256 struct M68KTrapCode {
257 APTR trapcode;
258 ULONG traparg;
261 AROS_UFH2(VOID, M68KExceptionAction,
262 AROS_UFHA(ULONG, vector, D0),
263 AROS_UFHA(struct M68KTrapCode *, tc, A0))
265 AROS_USERFUNC_INIT
267 ULONG Id;
268 VOID (*Handler)(ULONG id);
270 if (vector & 1) {
271 /* vector is really a pointer to a M68KException table entry */
272 struct M68KException *Exception;
274 Exception = (APTR)(vector & ~1);
276 Id = Exception->Id;
277 Handler = Exception->Handler;
278 } else {
279 Id = vector >> 2;
280 Handler = NULL;
283 #if DEBUG
284 if (SysBase == NULL || KernelBase == NULL) {
285 volatile LONG *LastAlert = (volatile LONG *)(64 * sizeof(LONG));
286 /* SysBase has been corrupted! Mark the alert,
287 * and reboot.
289 LastAlert[0] = (LONG)(AT_DeadEnd | AN_LibChkSum);
290 /* LastAlert[1] was already set by
291 * Exec/Dispatch
293 LastAlert[1] = 0; /* No SysBase? No Task. */
294 LastAlert[2] = 0;
295 LastAlert[3] = 0;
297 /* Set LastAlert marker */
298 *(volatile ULONG *)0 = 0x48454c50; /* 'HELP' */
299 Exec_MagicResetCode();
300 return;
302 #endif
304 tc->traparg = Id;
305 if (!Handler) {
306 Handler = FindTask(NULL)->tc_TrapCode;
307 if (!Handler) {
308 Handler = SysBase->TaskTrapCode;
311 tc->trapcode = Handler;
313 AROS_USERFUNC_EXIT
316 /* We assume that the caller has already set up
317 * the exceptions to a 'reasonable' default. These
318 * are only the overrides for AROS.
320 void M68KExceptionInit(const struct M68KException *Table, struct ExecBase *SysBase)
322 IPTR *exception = (IPTR *)0; /* Exception base is at 0 */
323 UWORD *jmptab;
324 int i;
325 int size;
327 /* Initialize the Well Known Traps */
328 if (SysBase->AttnFlags & AFF_68010) {
329 M68KExceptionInit_10(SysBase);
330 } else {
331 M68KExceptionInit_00(SysBase);
334 if ((ULONG)Table & 1) {
335 /* Exception Table must be UWORD aligned! */
336 return;
339 for (size = 0; Table[size].Id > 0; size++);
341 /* A little explanation. jmptab will be
342 * constructed as follows:
343 * move.l (i << 1) | 1, %sp@+
344 * 0x2f3c ((i << 1) | 1) >> 16) ((i << 1) | 1) & 0xffff)
345 * jmp %pc@(((size - 1) - i) * (5 * sizeof(UWORD)) + 2)
346 * 0x4efa (((size - 1) - i) * (5 * sizeof(UWORD)) + 2)
347 * ...
348 * ...
349 * jmp M68KExceptionHelper
350 * 0x4ef9 (M68KExceptionHelper >> 16) (M68KExceptionHelper & 0xffff)
352 * NOTICE: jmptab will never be freed! */
353 jmptab = AllocMem(size * (5 * sizeof(UWORD)) + 3 * sizeof(UWORD), 0);
355 for (i = 0; i < size; i++, jmptab += 5) {
356 /* This little trick is why we want
357 * the Table UWORD aligned.
359 * See the rest of this in M68KExceptionHelper
361 ULONG vecid = (ULONG)(&Table[i]) | 1;
363 jmptab[0] = 0x2f3c; // movel #...,%sp@-
364 jmptab[1] = ((IPTR)(vecid) >> 16) & 0xffff;
365 jmptab[2] = ((IPTR)(vecid) >> 0) & 0xffff;
366 jmptab[3] = 0x4efa; // jmp %pc@...
367 jmptab[4] = ((size - 1) - i) * (5 * sizeof(UWORD)) + 2;
368 exception[Table[i].Id] = (IPTR)(&jmptab[0]);
370 jmptab[0] = 0x4ef9; // jmp ....
371 jmptab[1] = ((IPTR)(M68KExceptionHelper) >> 16) & 0xffff;
372 jmptab[2] = ((IPTR)(M68KExceptionHelper) >> 0) & 0xffff;
374 /* We're all set up now! */