This repository has been archived by the owner on Jan 24, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 85
/
asm.S
113 lines (101 loc) · 3.04 KB
/
asm.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
.cfi_sections .debug_frame
# Notes for function attributes:
# .type and .thumb_func are _both_ required, otherwise the Thumb mode bit
# will not be set and an invalid vector table is generated.
# LLD requires that section flags are set explicitly.
.section .HardFaultTrampoline, "ax"
.global HardFaultTrampoline
.type HardFaultTrampoline,%function
.thumb_func
.cfi_startproc
# HardFault exceptions are bounced through this trampoline which grabs the
# stack pointer at the time of the exception and passes it to the user's
# HardFault handler in r0.
HardFaultTrampoline:
# Depending on the stack mode in EXC_RETURN, fetch stack pointer from
# PSP or MSP.
mov r0, lr
mov r1, #4
tst r0, r1
bne 0f
mrs r0, MSP
b HardFault
0:
mrs r0, PSP
b HardFault
.cfi_endproc
.size HardFaultTrampoline, . - HardFaultTrampoline
.section .Reset, "ax"
.global Reset
.type Reset,%function
.thumb_func
.cfi_startproc
# Main entry point after reset. This jumps to the user __pre_init function,
# which cannot be called from Rust code without invoking UB, then
# initialises RAM. If the target has an FPU, it is enabled. Finally, jumps
# to the user main function.
Reset:
# ARMv6-M does not initialise LR, but many tools expect it to be 0xFFFF_FFFF
# when reaching the first call frame, so we set it at startup.
# ARMv7-M and above initialise LR to 0xFFFF_FFFF at reset.
ldr r4,=0xffffffff
mov lr,r4
# Run user pre-init code, which must be executed immediately after startup,
# before the potentially time-consuming memory initialisation takes place.
# Example use cases include disabling default watchdogs or enabling RAM.
bl __pre_init
# Restore LR after calling __pre_init (r4 is preserved by subroutines).
mov lr,r4
# Initialise .bss memory. `__sbss` and `__ebss` come from the linker script.
ldr r0,=__sbss
ldr r1,=__ebss
mov r2,#0
0:
cmp r1, r0
beq 1f
stm r0!, {r2}
b 0b
1:
# Initialise .data memory. `__sdata`, `__sidata`, and `__edata` come from the
# linker script. Copy from r2 into r0 until r0 reaches r1.
ldr r0,=__sdata
ldr r1,=__edata
ldr r2,=__sidata
2:
cmp r1, r0
beq 3f
# load 1 word from r2 to r3, inc r2
ldm r2!, {r3}
# store 1 word from r3 to r0, inc r0
stm r0!, {r3}
b 2b
3:
#ifdef HAS_FPU
# Conditionally enable the FPU.
# Address of SCB.CPACR.
ldr r0, =0xE000ED88
# Enable access to CP10 and CP11 from both privileged and unprivileged mode.
ldr r1, =(0b1111 << 20)
# RMW.
ldr r2, [r0]
orr r2, r2, r1
str r2, [r0]
# Barrier is required on some processors.
dsb
isb
#endif
4:
# Preserve `lr` and emit debuginfo that lets external tools restore it.
# This fixes unwinding past the `Reset` handler.
# See https://sourceware.org/binutils/docs/as/CFI-directives.html for an
# explanation of the directives.
.cfi_def_cfa sp, 0
push {lr}
.cfi_offset lr, 0
# Jump to user main function. We use bl for the extended range, but the
# user main function may not return.
bl main
# Trap on return.
udf
.cfi_endproc
.size Reset, . - Reset