]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/bcm/lexception.s
merge
[plan9front.git] / sys / src / 9 / bcm / lexception.s
1 /*
2  * arm exception handlers
3  */
4 #include "arm.s"
5
6 /*
7  *  exception vectors, copied by trapinit() to somewhere useful
8  */
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 */
18
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 */
28
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)            /* ... */
35
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 */
39
40         MOVW    $setR12(SB), R12        /* Make sure we've got the kernel's SB loaded */
41
42 //      MOVW    $(KSEG0+16*KiB-MACHSIZE), R10   /* m */
43         MOVW    $(MACHADDR), R10        /* m */
44         MOVW    8(R10), R9              /* up */
45
46         MOVW    R13, R0                 /* first arg is pointer to ureg */
47         SUB     $8, R13                 /* space for argument+link */
48
49         BL      syscall(SB)
50
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] */
58
59 TEXT _vund(SB), 1, $-4                  /* undefined */
60         MOVM.IA [R0-R4], (R13)          /* free some working space */
61         MOVW    $PsrMund, R0
62         B       _vswitch
63
64 TEXT _vpabt(SB), 1, $-4                 /* prefetch abort */
65         MOVM.IA [R0-R4], (R13)          /* free some working space */
66         MOVW    $PsrMabt, R0            /* r0 = type */
67         B       _vswitch
68
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 */
72         B       _vswitch
73
74 TEXT _virq(SB), 1, $-4                  /* IRQ */
75         MOVM.IA [R0-R4], (R13)          /* free some working space */
76         MOVW    $PsrMirq, R0            /* r0 = type */
77         B       _vswitch
78
79         /*
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.
82          */
83 _vswitch:
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 */
87
88         /*
89          * switch processor to svc mode.  this switches the banked registers
90          * (r13 [sp] and r14 [link]) to those of svc mode.
91          */
92         MOVW    CPSR, R14
93         BIC     $PsrMask, R14
94         ORR     $(PsrDirq|PsrMsvc), R14
95         MOVW    R14, CPSR               /* switch! */
96
97         AND.S   $0xf, R1, R4            /* interrupted code kernel or user? */
98         BEQ     _userexcep
99
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 */
103
104         /*
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.
109          */
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 */
113
114         MOVW    $setR12(SB), R12        /* Make sure we've got the kernel's SB loaded */
115
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 */
119
120         BL      trap(SB)
121
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                /* ... */
126
127         MOVM.DB (R13), [R0-R14]         /* restore registers */
128
129         ADD     $(4*2), R13             /* pop past ureg->{type+psr} to pc */
130         RFE                             /* MOVM.IA.S.W (R13), [R15] */
131
132         /* here for trap from USER mode */
133 _userexcep:
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 */
136
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 */
140
141         MOVW    $setR12(SB), R12        /* Make sure we've got the kernel's SB loaded */
142
143 //      MOVW    $(KSEG0+16*KiB-MACHSIZE), R10   /* m */
144         MOVW    $(MACHADDR), R10        /* m */
145         MOVW    8(R10), R9              /* up */
146
147         MOVW    R13, R0                 /* first arg is pointer to ureg */
148         SUB     $(4*2), R13             /* space for argument+link (for debugger) */
149
150         BL      trap(SB)
151
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] */
159
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) */
171
172         BL      fiq(SB)
173
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] */
181
182 /*
183  *  set the stack value for the mode passed in R0
184  */
185 TEXT setr13(SB), 1, $-4
186         MOVW    4(FP), R1
187
188         MOVW    CPSR, R2
189         BIC     $PsrMask, R2, R3
190         ORR     R0, R3
191         MOVW    R3, CPSR                /* switch to new mode */
192
193         MOVW    R13, R0                 /* return old sp */
194         MOVW    R1, R13                 /* install new one */
195
196         MOVW    R2, CPSR                /* switch back to old mode */
197         RET