-
Notifications
You must be signed in to change notification settings - Fork 34
/
Copy pathstart.S
241 lines (210 loc) · 6.59 KB
/
start.S
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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
/* SPDX-License-Identifier: GPL-2.0+ */
#include <linkage.h>
// Macro to save register values onto the stack
.macro save_regs
str lr, [sp, #-4] // Save value of lr register onto the stack
mrs lr, spsr_all // Save value of spsr_all register onto lr register
str lr, [sp, #-8] // Save value of lr register onto the stack
str r1, [sp, #-12] // Save value of r1 register onto the stack
str r0, [sp, #-16] // Save value of r0 register onto the stack
mov r0, sp // Copy value of sp register to r0 register
cps #0x13 // Switch to SVC mode
ldr r1, [r0, #-4] // Load value of r1 register from stack to r1 register
str r1, [sp, #-4]! // Save value of r1 register onto the stack and update stack pointer
ldr r1, [r0, #-8] // Load value of r1 register from stack to r1 register
str r1, [sp, #-(4 * 16)] // Save value of r1 register onto the stack
ldr r1, [r0, #-12] // Load value of r1 register from stack to r1 register
ldr r0, [r0, #-16] // Load value of r0 register from stack to r0 register
stmdb sp, {r0 - r14}^ // Save values of registers r0-r14 onto the stack
sub sp, sp, #(4 * 16) // Update stack pointer
ldr r4, [sp] // Load value of r4 register from stack to r4 register
and r0, r4, #0x1f // Copy the lower 5 bits of r4 register to r0 register
cmp r0, #0x10 // Compare value of r0 register with 0x10
beq 10f // If equal, jump to label 10
cmp r0, #0x13 // Compare value of r0 register with 0x13
beq 11f // If equal, jump to label 11
b . // Jump to current location
11: add r1, sp, #(4 * 17) // Add (4 * 17) to sp register and copy result to r1 register
str r1, [sp, #(4 * 14)] // Save value of r1 register onto the stack
str lr, [sp, #(4 * 15)] // Save value of lr register onto the stack
10: add r1, sp, #(4 * 17) // Add (4 * 17) to sp register and copy result to r1 register
str r1, [sp, #-4]! // Save value of r1 register onto the stack and update stack pointer
mov r0, sp // Copy value of sp register to r0 register
.endm
// Macro to restore register values from the stack
.macro restore_regs
mov r12, sp // Copy value of sp register to r12 register
ldr sp, [r12], #4 // Load value from memory pointed by r12 register to sp register and update r12 register
ldr r1, [r12], #4 // Load value from memory pointed by r12 register to r1 register and update r12 register
msr spsr_cxsf, r1 // Write value of r1 register to spsr_cxsf register
and r0, r1, #0x1f // Copy the lower 5 bits of r1 register to r0 register
cmp r0, #0x10 // Compare value of r0 register with 0x10
beq 20f // If equal, jump to label 20
cmp r0, #0x13 // Compare value of r0 register with 0x13
beq 21f // If equal, jump to label 21
b . // Jump to current location
20: ldr lr, [r12, #(4 * 15)] // Load value from memory pointed by r12 register to lr register
ldmia r12, {r0 - r14}^ // Load values of registers r0-r14 from memory pointed by r12 register and update r12 register
movs pc, lr // Set value of PC register to value of lr register
21: ldm r12, {r0 - r15}^ // Load values of registers r0-r15 from memory pointed by r12 register
mov r0, r0 // Copy value of r0 register to r0 register
.endm
.arm
.globl _start
.text
_start:
b reset
.align 5
_vector:
b reset
ldr pc, _undefined_instruction
ldr pc, _software_interrupt
ldr pc, _prefetch_abort
ldr pc, _data_abort
ldr pc, _not_used
ldr pc, _irq
ldr pc, _fiq
_undefined_instruction:
.word undefined_instruction
_software_interrupt:
.word software_interrupt
_prefetch_abort:
.word prefetch_abort
_data_abort:
.word data_abort
_not_used:
.word not_used
_irq:
.word irq
_fiq:
.word fiq
reset:
/* Enter svc mode cleanly and mask interrupts */
mrs r0, cpsr
bic r0, r0, #ARMV7_MODE_MASK
orr r0, r0, #ARMV7_SVC_MODE
orr r0, r0, #(ARMV7_IRQ_MASK | ARMV7_FIQ_MASK)
bic r0, r0, #(1<<9) @set little-endian
msr cpsr_c, r0
/* Set vector base address register */
ldr r0, =_vector
mcr p15, 0, r0, c12, c0, 0
mrc p15, 0, r0, c1, c0, 0
bic r0, #(1 << 13)
mcr p15, 0, r0, c1, c0, 0
mrc p15, 0, r0, c1, c0, 0
bic r0, r0, #0x00002000 @ clear bits 13 (--V-)
bic r0, r0, #0x00000007 @ clear bits 2:0 (-CAM)
orr r0, r0, #0x00000800 @ set bit 11 (Z---) BTB
bic r0, r0, #0x00001000 @ clear bit 12 (I) I-cache
mcr p15, 0, r0, c1, c0, 0
/* Set stack pointer */
/* Initialize UND stacks */
mrs r0, cpsr
bic r0, r0, #ARMV7_MODE_MASK
orr r1, r0, #ARMV7_UND_MODE
msr cpsr_cxsf, r1
ldr sp, _stack_und_end
/* Initialize ABT stacks */
mrs r0, cpsr
bic r0, r0, #ARMV7_MODE_MASK
orr r1, r0, #ARMV7_ABT_MODE
msr cpsr_cxsf, r1
ldr sp, _stack_abt_end
/* Initialize IRQ stacks */
mrs r0, cpsr
bic r0, r0, #ARMV7_MODE_MASK
orr r1, r0, #ARMV7_IRQ_MODE
msr cpsr_cxsf, r1
ldr sp, _stack_irq_end
/* Initialize FIQ stacks */
mrs r0, cpsr
bic r0, r0, #ARMV7_MODE_MASK
orr r1, r0, #ARMV7_FIQ_MODE
msr cpsr_cxsf, r1
ldr sp, _stack_fiq_end
/* Initialize SVC stacks */
mrs r0, cpsr
bic r0, r0, #ARMV7_MODE_MASK
orr r1, r0, #ARMV7_SVC_MODE
msr cpsr_cxsf, r1
ldr sp, _stack_srv_end
bl clear_bss
/*
* disable interrupts (FIQ and IRQ), also set the cpu to SVC32 mode,
* except if in HYP mode already
*/
mrs r0, cpsr
and r1, r0, #ARMV7_MODE_MASK @ mask mode bits
teq r1, #0x1a @ test for HYP mode
bicne r0, r0, #ARMV7_MODE_MASK @ clear all mode bits
orrne r0, r0, #ARMV7_SVC_MODE @ set SVC mode
orr r0, r0, #0xc0 @ disable FIQ and IRQ
msr cpsr,r0
bl set_timer_count
bl main
clear_bss:
ldr r0, =_sbss
ldr r1, =_ebss
mov r2, #0
clbss_1:
stmia r0!, {r2}
cmp r0, r1
blt clbss_1
mov pc, lr
/*
* Exception handlers
*/
.align 5
undefined_instruction:
sub lr, lr, #4
save_regs
bl arm32_do_undefined_instruction
restore_regs
.align 5
software_interrupt:
sub lr, lr, #4
save_regs
bl arm32_do_software_interrupt
restore_regs
.align 5
prefetch_abort:
sub lr, lr, #4
save_regs
bl arm32_do_prefetch_abort
restore_regs
.align 5
data_abort:
sub lr, lr, #8
save_regs
bl arm32_do_data_abort
restore_regs
.align 5
not_used:
b .
.align 5
irq:
sub lr, lr, #4
save_regs
bl arm32_do_irq
restore_regs
.align 5
fiq:
sub lr, lr, #4
save_regs
bl arm32_do_fiq
restore_regs
/*
* The location of section
*/
.align 4
_stack_und_end:
.long __stack_und_end
_stack_abt_end:
.long __stack_abt_end
_stack_irq_end:
.long __stack_irq_end
_stack_fiq_end:
.long __stack_fiq_end
_stack_srv_end:
.long __stack_srv_end