2 * arm exception handlers
6 #undef B /* B is for 'botch' */
9 * exception vectors, copied by trapinit() to somewhere useful
11 TEXT vectors(SB), 1, $-4
12 MOVW 0x18(R15), R15 /* reset */
13 MOVW 0x18(R15), R15 /* undefined instr. */
14 MOVW 0x18(R15), R15 /* SWI & SMC */
15 MOVW 0x18(R15), R15 /* prefetch abort */
16 MOVW 0x18(R15), R15 /* data abort */
17 MOVW 0x18(R15), R15 /* reserved */
18 MOVW 0x18(R15), R15 /* IRQ */
19 MOVW 0x18(R15), R15 /* FIQ */
21 TEXT vtable(SB), 1, $-4
22 WORD $_vsvc(SB) /* reset, in svc mode already */
23 WORD $_vund(SB) /* undefined, switch to svc mode */
24 WORD $_vsvc(SB) /* swi, in svc mode already */
25 WORD $_vpabt(SB) /* prefetch abort, switch to svc mode */
26 WORD $_vdabt(SB) /* data abort, switch to svc mode */
27 WORD $_vsvc(SB) /* reserved */
28 WORD $_virq(SB) /* IRQ, switch to svc mode */
29 // WORD $_vfiq(SB) /* FIQ, switch to svc mode */
30 WORD $_virq(SB) /* FIQ, switch to svc mode */
32 TEXT _vrst(SB), 1, $-4
35 TEXT _vsvc(SB), 1, $-4 /* SWI */
36 MOVW.W R14, -4(R13) /* ureg->pc = interrupted PC */
37 MOVW SPSR, R14 /* ureg->psr = SPSR */
38 MOVW.W R14, -4(R13) /* ... */
39 MOVW $PsrMsvc, R14 /* ureg->type = PsrMsvc */
40 MOVW.W R14, -4(R13) /* ... */
42 /* avoid the ambiguity described in notes/movm.w. */
43 // MOVM.DB.W.S [R0-R14], (R13) /* save user level registers, at end r13 points to ureg */
44 MOVM.DB.S [R0-R14], (R13) /* save user level registers */
45 SUB $(15*4), R13 /* r13 now points to ureg */
47 MOVW $setR12(SB), R12 /* Make sure we've got the kernel's SB loaded */
49 // MOVW $(KSEG0+16*KiB-MACHSIZE), R10 /* m */
50 MOVW $(L1-MACHSIZE), R10 /* m */
51 MOVW 8(R10), R9 /* up */
53 MOVW R13, R0 /* first arg is pointer to ureg */
54 SUB $8, R13 /* space for argument+link */
58 ADD $(8+4*15), R13 /* make r13 point to ureg->type */
59 MOVW 8(R13), R14 /* restore link */
60 MOVW 4(R13), R0 /* restore SPSR */
61 MOVW R0, SPSR /* ... */
62 MOVM.DB.S (R13), [R0-R14] /* restore registers */
63 ADD $8, R13 /* pop past ureg->{type+psr} */
64 RFE /* MOVM.IA.S.W (R13), [R15] */
66 TEXT _vund(SB), 1, $-4 /* undefined */
67 MOVM.IA [R0-R4], (R13) /* free some working space */
71 TEXT _vpabt(SB), 1, $-4 /* prefetch abort */
72 MOVM.IA [R0-R4], (R13) /* free some working space */
73 MOVW $PsrMabt, R0 /* r0 = type */
76 TEXT _vdabt(SB), 1, $-4 /* data abort */
77 MOVM.IA [R0-R4], (R13) /* free some working space */
78 MOVW $(PsrMabt+1), R0 /* r0 = type */
81 TEXT _virq(SB), 1, $-4 /* IRQ */
82 MOVM.IA [R0-R4], (R13) /* free some working space */
83 MOVW $PsrMirq, R0 /* r0 = type */
87 * come here with type in R0 and R13 pointing above saved [r0-r4].
88 * we'll switch to SVC mode and then call trap.
91 MOVW SPSR, R1 /* save SPSR for ureg */
92 MOVW R14, R2 /* save interrupted pc for ureg */
93 MOVW R13, R3 /* save pointer to where the original [R0-R4] are */
96 * switch processor to svc mode. this switches the banked registers
97 * (r13 [sp] and r14 [link]) to those of svc mode.
101 ORR $(PsrDirq|PsrDfiq|PsrMsvc), R14
102 MOVW R14, CPSR /* switch! */
104 AND.S $0xf, R1, R4 /* interrupted code kernel or user? */
107 /* here for trap from SVC mode */
108 MOVM.DB.W [R0-R2], (R13) /* set ureg->{type, psr, pc}; r13 points to ureg->type */
109 MOVM.IA (R3), [R0-R4] /* restore [R0-R4] from previous mode's stack */
112 * avoid the ambiguity described in notes/movm.w.
113 * In order to get a predictable value in R13 after the stores,
114 * separate the store-multiple from the stack-pointer adjustment.
115 * We'll assume that the old value of R13 should be stored on the stack.
117 /* save kernel level registers, at end r13 points to ureg */
118 // MOVM.DB.W [R0-R14], (R13)
119 MOVM.DB [R0-R14], (R13)
120 SUB $(15*4), R13 /* SP now points to saved R0 */
122 MOVW $setR12(SB), R12 /* Make sure we've got the kernel's SB loaded */
124 MOVW R13, R0 /* first arg is pointer to ureg */
125 SUB $(4*2), R13 /* space for argument+link (for debugger) */
126 MOVW $0xdeaddead, R11 /* marker */
130 ADD $(4*2+4*15), R13 /* make r13 point to ureg->type */
131 MOVW 8(R13), R14 /* restore link */
132 MOVW 4(R13), R0 /* restore SPSR */
133 MOVW R0, SPSR /* ... */
135 MOVM.DB (R13), [R0-R14] /* restore registers */
137 ADD $(4*2), R13 /* pop past ureg->{type+psr} to pc */
138 RFE /* MOVM.IA.S.W (R13), [R15] */
140 /* here for trap from USER mode */
142 MOVM.DB.W [R0-R2], (R13) /* set ureg->{type, psr, pc}; r13 points to ureg->type */
143 MOVM.IA (R3), [R0-R4] /* restore [R0-R4] from previous mode's stack */
145 /* avoid the ambiguity described in notes/movm.w. */
146 // MOVM.DB.W.S [R0-R14], (R13) /* save kernel level registers, at end r13 points to ureg */
147 MOVM.DB.S [R0-R14], (R13) /* save kernel level registers */
148 SUB $(15*4), R13 /* r13 now points to ureg */
150 MOVW $setR12(SB), R12 /* Make sure we've got the kernel's SB loaded */
152 // MOVW $(KSEG0+16*KiB-MACHSIZE), R10 /* m */
153 MOVW $(L1-MACHSIZE), R10 /* m */
154 MOVW 8(R10), R9 /* up */
156 MOVW R13, R0 /* first arg is pointer to ureg */
157 SUB $(4*2), R13 /* space for argument+link (for debugger) */
161 ADD $(4*2+4*15), R13 /* make r13 point to ureg->type */
162 MOVW 8(R13), R14 /* restore link */
163 MOVW 4(R13), R0 /* restore SPSR */
164 MOVW R0, SPSR /* ... */
165 MOVM.DB.S (R13), [R0-R14] /* restore registers */
166 ADD $(4*2), R13 /* pop past ureg->{type+psr} */
167 RFE /* MOVM.IA.S.W (R13), [R15] */
169 TEXT _vfiq(SB), 1, $-4 /* FIQ */
170 RFE /* FIQ is special, ignore it for now */
173 * set the stack value for the mode passed in R0
175 TEXT setr13(SB), 1, $-4
181 MOVW R3, CPSR /* switch to new mode */
183 MOVW R13, R0 /* return old sp */
184 MOVW R1, R13 /* install new one */
186 MOVW R2, CPSR /* switch back to old mode */