2 * arm exception handlers
7 * exception vectors, copied by trapinit() to somewhere useful
9 TEXT vectors(SB), 1, $-4
10 MOVW 0x18(R15), R15 /* reset */
11 MOVW 0x18(R15), R15 /* undefined instr. */
12 MOVW 0x18(R15), R15 /* SWI & SMC */
13 MOVW 0x18(R15), R15 /* prefetch abort */
14 MOVW 0x18(R15), R15 /* data abort */
15 MOVW 0x18(R15), R15 /* reserved */
16 MOVW 0x18(R15), R15 /* IRQ */
17 MOVW 0x18(R15), R15 /* FIQ */
19 TEXT vtable(SB), 1, $-4
20 WORD $_vsvc(SB) /* reset, in svc mode already */
21 WORD $_vund(SB) /* undefined, switch to svc mode */
22 WORD $_vsvc(SB) /* swi, in svc mode already */
23 WORD $_vpabt(SB) /* prefetch abort, switch to svc mode */
24 WORD $_vdabt(SB) /* data abort, switch to svc mode */
25 WORD $_vsvc(SB) /* reserved */
26 WORD $_virq(SB) /* IRQ, switch to svc mode */
27 WORD $_vfiq(SB) /* FIQ, switch to svc mode */
29 TEXT _vsvc(SB), 1, $-4 /* SWI */
30 MOVW.W R14, -4(R13) /* ureg->pc = interrupted PC */
31 MOVW SPSR, R14 /* ureg->psr = SPSR */
32 MOVW.W R14, -4(R13) /* ... */
33 MOVW $PsrMsvc, R14 /* ureg->type = PsrMsvc */
34 MOVW.W R14, -4(R13) /* ... */
36 /* avoid the ambiguity described in notes/movm.w. */
37 MOVM.DB.S [R0-R14], (R13) /* save user level registers */
38 SUB $(15*4), R13 /* r13 now points to ureg */
40 MOVW $setR12(SB), R12 /* Make sure we've got the kernel's SB loaded */
42 // MOVW $(KSEG0+16*KiB-MACHSIZE), R10 /* m */
43 MOVW $(MACHADDR), R10 /* m */
44 MOVW 8(R10), R9 /* up */
46 MOVW R13, R0 /* first arg is pointer to ureg */
47 SUB $8, R13 /* space for argument+link */
51 ADD $(8+4*15), R13 /* make r13 point to ureg->type */
52 MOVW 8(R13), R14 /* restore link */
53 MOVW 4(R13), R0 /* restore SPSR */
54 MOVW R0, SPSR /* ... */
55 MOVM.DB.S (R13), [R0-R14] /* restore registers */
56 ADD $8, R13 /* pop past ureg->{type+psr} */
57 RFE /* MOVM.IA.S.W (R13), [R15] */
59 TEXT _vund(SB), 1, $-4 /* undefined */
60 MOVM.IA [R0-R4], (R13) /* free some working space */
64 TEXT _vpabt(SB), 1, $-4 /* prefetch abort */
65 MOVM.IA [R0-R4], (R13) /* free some working space */
66 MOVW $PsrMabt, R0 /* r0 = type */
69 TEXT _vdabt(SB), 1, $-4 /* data abort */
70 MOVM.IA [R0-R4], (R13) /* free some working space */
71 MOVW $(PsrMabt+1), R0 /* r0 = type */
74 TEXT _virq(SB), 1, $-4 /* IRQ */
75 MOVM.IA [R0-R4], (R13) /* free some working space */
76 MOVW $PsrMirq, R0 /* r0 = type */
80 * come here with type in R0 and R13 pointing above saved [r0-r4].
81 * we'll switch to SVC mode and then call trap.
84 MOVW SPSR, R1 /* save SPSR for ureg */
85 MOVW R14, R2 /* save interrupted pc for ureg */
86 MOVW R13, R3 /* save pointer to where the original [R0-R4] are */
89 * switch processor to svc mode. this switches the banked registers
90 * (r13 [sp] and r14 [link]) to those of svc mode.
94 ORR $(PsrDirq|PsrMsvc), R14
95 MOVW R14, CPSR /* switch! */
97 AND.S $0xf, R1, R4 /* interrupted code kernel or user? */
100 /* here for trap from SVC mode */
101 MOVM.DB.W [R0-R2], (R13) /* set ureg->{type, psr, pc}; r13 points to ureg->type */
102 MOVM.IA (R3), [R0-R4] /* restore [R0-R4] from previous mode's stack */
105 * avoid the ambiguity described in notes/movm.w.
106 * In order to get a predictable value in R13 after the stores,
107 * separate the store-multiple from the stack-pointer adjustment.
108 * We'll assume that the old value of R13 should be stored on the stack.
110 /* save kernel level registers, at end r13 points to ureg */
111 MOVM.DB [R0-R14], (R13)
112 SUB $(15*4), R13 /* SP now points to saved R0 */
114 MOVW $setR12(SB), R12 /* Make sure we've got the kernel's SB loaded */
116 MOVW R13, R0 /* first arg is pointer to ureg */
117 SUB $(4*2), R13 /* space for argument+link (for debugger) */
118 MOVW $0xdeaddead, R11 /* marker */
122 ADD $(4*2+4*15), R13 /* make r13 point to ureg->type */
123 MOVW 8(R13), R14 /* restore link */
124 MOVW 4(R13), R0 /* restore SPSR */
125 MOVW R0, SPSR /* ... */
127 MOVM.DB (R13), [R0-R14] /* restore registers */
129 ADD $(4*2), R13 /* pop past ureg->{type+psr} to pc */
130 RFE /* MOVM.IA.S.W (R13), [R15] */
132 /* here for trap from USER mode */
134 MOVM.DB.W [R0-R2], (R13) /* set ureg->{type, psr, pc}; r13 points to ureg->type */
135 MOVM.IA (R3), [R0-R4] /* restore [R0-R4] from previous mode's stack */
137 /* avoid the ambiguity described in notes/movm.w. */
138 MOVM.DB.S [R0-R14], (R13) /* save kernel level registers */
139 SUB $(15*4), R13 /* r13 now points to ureg */
141 MOVW $setR12(SB), R12 /* Make sure we've got the kernel's SB loaded */
143 // MOVW $(KSEG0+16*KiB-MACHSIZE), R10 /* m */
144 MOVW $(MACHADDR), R10 /* m */
145 MOVW 8(R10), R9 /* up */
147 MOVW R13, R0 /* first arg is pointer to ureg */
148 SUB $(4*2), R13 /* space for argument+link (for debugger) */
152 ADD $(4*2+4*15), R13 /* make r13 point to ureg->type */
153 MOVW 8(R13), R14 /* restore link */
154 MOVW 4(R13), R0 /* restore SPSR */
155 MOVW R0, SPSR /* ... */
156 MOVM.DB.S (R13), [R0-R14] /* restore registers */
157 ADD $(4*2), R13 /* pop past ureg->{type+psr} */
158 RFE /* MOVM.IA.S.W (R13), [R15] */
160 TEXT _vfiq(SB), 1, $-4 /* FIQ */
161 MOVW $PsrMfiq, R8 /* trap type */
162 MOVW SPSR, R9 /* interrupted psr */
163 MOVW R14, R10 /* interrupted pc */
164 MOVM.DB.W [R8-R10], (R13) /* save in ureg */
165 MOVM.DB.W.S [R0-R14], (R13) /* save interrupted regs */
166 MOVW $setR12(SB), R12 /* Make sure we've got the kernel's SB loaded */
167 MOVW $(MACHADDR), R10 /* m */
168 MOVW 8(R10), R9 /* up */
169 MOVW R13, R0 /* first arg is pointer to ureg */
170 SUB $(4*2), R13 /* space for argument+link (for debugger) */
174 ADD $(8+4*15), R13 /* make r13 point to ureg->type */
175 MOVW 8(R13), R14 /* restore link */
176 MOVW 4(R13), R0 /* restore SPSR */
177 MOVW R0, SPSR /* ... */
178 MOVM.DB.S (R13), [R0-R14] /* restore registers */
179 ADD $8, R13 /* pop past ureg->{type+psr} */
180 RFE /* MOVM.IA.S.W (R13), [R15] */
183 * set the stack value for the mode passed in R0
185 TEXT setr13(SB), 1, $-4
191 MOVW R3, CPSR /* switch to new mode */
193 MOVW R13, R0 /* return old sp */
194 MOVW R1, R13 /* install new one */
196 MOVW R2, CPSR /* switch back to old mode */