2 copyright © 1995-2010, the aros development team. all rights reserved.
5 desc: m68k-amiga bootstrap to exec.
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
25 * 1 Reset: Initial PC (NOTE: Really is AbsExecBase!)
28 * 4 Illegal Instruction
32 * 8 Privileged Instruction
34 * 10 Line 1010 Emulator
35 * 11 Line 1111 Emulator
39 * 15 Uninitilaized Interrupt Vector
43 * 24 Spurious Interrupt
44 * 25 Level 1 Interrupt
46 * Paula 1: Disk DMA done
47 * Paula 2: Software Int
48 * 26 Level 2 Interrupt
50 * 27 Level 3 Interrupt
54 * 28 Level 4 Interrupt
59 * 29 Level 5 Interrupt
62 * 30 Level 6 Interrupt
64 * Paula 14: Copper (special)
65 * 31 Level 7 Interrupt
72 * 63 AbsExecBase (copy)
78 extern ULONG M68KFaultTable_00
[];
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
[];
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
[];
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;
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 */
173 for (i
= 0; i
< 16; i
++)
174 exception
[i
+ 32] = &M68KTrapTable_00
[i
];
179 /* For the 68010+, the lower 12 bits of the UWORD
180 * at %sp@(6) contains the vector number.
183 extern void M68KTrapHelper_10(void);
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;
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) */
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)
217 * When we call M68KExceptionAction:
222 * D0-D1/A0-A1 (4 * 4) <= NO TOUCHING!
223 * Pointer to trapcode/arg (4)
224 * Exception Vector (4)
227 * Restore D0-D1/A0-A1
228 * Either execute the trap, or just return.
231 extern void M68KExceptionHelper(void);
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
244 " rts\n" // Execute tc_TrapCode
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
{
261 AROS_UFH2(VOID
, M68KExceptionAction
,
262 AROS_UFHA(ULONG
, vector
, D0
),
263 AROS_UFHA(struct M68KTrapCode
*, tc
, A0
))
268 VOID (*Handler
)(ULONG id
);
271 /* vector is really a pointer to a M68KException table entry */
272 struct M68KException
*Exception
;
274 Exception
= (APTR
)(vector
& ~1);
277 Handler
= Exception
->Handler
;
284 if (SysBase
== NULL
|| KernelBase
== NULL
) {
285 volatile LONG
*LastAlert
= (volatile LONG
*)(64 * sizeof(LONG
));
286 /* SysBase has been corrupted! Mark the alert,
289 LastAlert
[0] = (LONG
)(AT_DeadEnd
| AN_LibChkSum
);
290 /* LastAlert[1] was already set by
293 LastAlert
[1] = 0; /* No SysBase? No Task. */
297 /* Set LastAlert marker */
298 *(volatile ULONG
*)0 = 0x48454c50; /* 'HELP' */
299 Exec_MagicResetCode();
306 Handler
= FindTask(NULL
)->tc_TrapCode
;
308 Handler
= SysBase
->TaskTrapCode
;
311 tc
->trapcode
= Handler
;
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 */
327 /* Initialize the Well Known Traps */
328 if (SysBase
->AttnFlags
& AFF_68010
) {
329 M68KExceptionInit_10(SysBase
);
331 M68KExceptionInit_00(SysBase
);
334 if ((ULONG
)Table
& 1) {
335 /* Exception Table must be UWORD aligned! */
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)
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! */