-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtrap_asm.S
More file actions
162 lines (136 loc) · 5.68 KB
/
Copy pathtrap_asm.S
File metadata and controls
162 lines (136 loc) · 5.68 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
//low-level trap handler glue code
#include "arm.h"
.text
.code 32
.global trap_swi
.global trap_irq
.global trap_reset
.global trap_und
.global trap_iabort
.global trap_dabort
.global trap_na
.global trap_fiq
.global trapret
# handle SWI, we allow nested SWI
trap_swi:
# build trapframe on the stack
STMFD sp!, {r0-r12, r14} // save context
MRS r2, spsr // copy spsr to r2
STMFD r13!, {r2} // save r2(spsr) to the stack
STMFD r13!, {r14} // save r14 again to have one uniform trapframe
STMFD r13, {sp, lr}^ // save user mode sp and lr
SUB r13, r13, #8
# call traps (trapframe *fp)
MOV r0, r13 // copy r13_svc to r0
BL swi_handler // branch to the isr_swi
# restore states
trapret:
LDMFD r13, {sp, lr}^ // restore user mode sp and lr
ADD r13, r13, #8
LDMFD r13!, {r14} // restore r14
LDMFD r13!, {r2} // restore spsr
MSR spsr_cxsf, r2
LDMFD r13!,{r0-r12, pc}^ // restore context and return
# handle IRQ, we allow nested IRQs
trap_irq:
# save a few registers to the irq stack to provide scratch regs.
# r14 (lr_irq) contains the instruction (pc) to return to, need to
# save it on the stack as r14 is banked
SUB r14, r14, #4 // r14 (lr) contains the interrupted PC
STMFD r13!, {r0-r2, r14} //
MRS r1, spsr // save spsr_irq
MOV r0, r13 // save stack stop (r13_irq)
ADD r13, r13, #16 // reset the IRQ stack
# switch to the SVC mode
MRS r2, cpsr
BIC r2, r2, #MODE_MASK
ORR r2, r2, #SVC_MODE
MSR cpsr_cxsf, r2
# now, in SVC mode, sp, lr, pc (r13, r14, r15) are all banked
# build the trap frame
LDR r2, [r0, #12] // read the r14_irq, then save it
STMFD r13!, {r2}
STMFD r13!, {r3-r12} // r4-r12 are preserved (non-banked)
LDMFD r0, {r3-r5} // copy r0-r2 over from irq stack
STMFD r13!, {r3-r5}
STMFD r13!, {r1} // save spsr
STMFD r13!, {lr} // save r14_svc
STMFD r13, {sp, lr}^ // save user mode sp and lr
SUB r13, r13, #8
# get the parameters, then call the handler
MOV r0, r13 // points to
BL irq_handler
# restore the previous status
B trapret
# handle reset/undefine instruction/abort/not-assigned/fiq
# these handler does not allow nested handling
trap_reset:
MOV r14, #0 // lr: not defined on reset
STMFD r13!, {r0-r12, r14}
MRS r2, spsr // copy spsr to r2
STMFD r13!, {r2} // save r2(spsr) to the stack
STMFD r13!, {r14} // save r14 again (it is not really correct)
STMFD r13, {sp, lr}^ // save user mode sp and lr
SUB r13, r13, #8
# call traps (trapframe *fp)
MOV r0, r13 // copy r13_svc to r0
BL reset_handler
B .
trap_und:
STMFD r13!, {r0-r12, r14} // lr: instruction after the undefined
MRS r2, spsr // copy spsr to r2
STMFD r13!, {r2} // save r2(spsr) to the stack
STMFD r13!, {r14} // save r14 again (it is not really correct)
STMFD r13, {sp, lr}^ // save user mode sp and lr
SUB r13, r13, #8
# call traps (trapframe *fp)
MOV r0, r13 // save trapframe as the first parameter
BL und_handler
B .
trap_iabort:
SUB r14, r14, #4 // lr: instruction causing the abort
STMFD r13!, {r0-r12, r14}
MRS r2, spsr // copy spsr to r2
STMFD r13!, {r2} // save r2(spsr) to the stack
STMFD r13!, {r14} // save r14 again (it is not really correct)
STMFD r13, {sp, lr}^ // save user mode sp and lr
SUB r13, r13, #8
# call traps (trapframe *fp)
MOV r0, r13 // save trapframe as the first parameter
BL iabort_handler
B .
trap_dabort:
SUB r14, r14, #8 // lr: instruction causing the abort
STMFD r13!, {r0-r12, r14}
MRS r2, spsr // copy spsr to r2
STMFD r13!, {r2} // save r2(spsr) to the stack
STMFD r13!, {r14} // save r14 again (it is not really correct)
STMFD r13, {sp, lr}^ // save user mode sp and lr
SUB r13, r13, #8
# call traps (trapframe *fp)
MOV r0, r13 // save trapframe as the first parameter
BL dabort_handler
B trapret
trap_na:
STMFD r13!, {r0-r12, r14} // should never happen, hardware error
MRS r2, spsr // copy spsr to r2
STMFD r13!, {r2} // save r2(spsr) to the stack
STMFD r13!, {r14} // save r14 again (it is not really correct)
STMFD r13, {sp, lr}^ // save user mode sp and lr
SUB r13, r13, #8
# call traps (trapframe *fp)
MOV r0, r13 // save trapframe as the first parameter
BL na_handler
B .
trap_fiq:
SUB r14, r14, #4 // lr: return address after the fiq handler
STMFD r13!, {r0-r12, r14}
MRS r2, spsr // copy spsr to r2
STMFD r13!, {r2} // save r2(spsr) to the stack
STMFD r13!, {r14} // save r14 again (it is not really correct)
STMFD r13, {sp, lr}^ // save user mode sp and lr
SUB r13, r13, #8
# call traps (trapframe *fp)
MOV r0, r13 // save trapframe as the first parameter
BL fiq_handler
B .