15
15
#include " startup/baremetal/fini.h"
16
16
#include " startup/baremetal/init.h"
17
17
18
+ #include < arm_acle.h> // For __arm_wsr
19
+
18
20
extern " C" {
19
21
int main (int argc, char **argv);
20
22
void _start ();
@@ -33,6 +35,7 @@ extern uintptr_t __bss_size[];
33
35
} // extern "C"
34
36
35
37
namespace {
38
+ #if __ARM_ARCH_PROFILE == 'M'
36
39
// Based on
37
40
// https://developer.arm.com/documentation/107565/0101/Use-case-examples/Generic-Information/What-is-inside-a-program-image-/Vector-table
38
41
void NMI_Handler () {}
@@ -55,8 +58,8 @@ const HandlerType vector_table[] = {
55
58
reinterpret_cast <HandlerType>(&__stack), // SP
56
59
_start, // Reset
57
60
NMI_Handler, // NMI Handler
58
- HardFault_Handler, // Hard Fault Handlerß
59
- MemManage_Handler, // MPU Fault Han`dler
61
+ HardFault_Handler, // Hard Fault Handler
62
+ MemManage_Handler, // MPU Fault Handler
60
63
BusFault_Handler, // Bus Fault Handler
61
64
UsageFault_Handler, // Usage Fault Handler
62
65
0 , // Reserved
@@ -70,12 +73,64 @@ const HandlerType vector_table[] = {
70
73
SysTick_Handler, // SysTick Handler
71
74
// Unused
72
75
};
76
+ #else
77
+ // Based on
78
+ // https://developer.arm.com/documentation/den0013/0400/Boot-Code/Booting-a-bare-metal-system
79
+ void Reset_Handler () { LIBC_NAMESPACE::exit (1 ); }
80
+ void Undefined_Handler () { LIBC_NAMESPACE::exit (1 ); }
81
+ void SWI_Handler () { LIBC_NAMESPACE::exit (1 ); }
82
+ void PrefetchAbort_Handler () { LIBC_NAMESPACE::exit (1 ); }
83
+ void DataAbort_Handler () { LIBC_NAMESPACE::exit (1 ); }
84
+ void IRQ_Handler () { LIBC_NAMESPACE::exit (1 ); }
85
+ void FIQ_Handler () { LIBC_NAMESPACE::exit (1 ); }
86
+
87
+ // The AArch32 exception vector table has 8 entries, each of which is 4
88
+ // bytes long, and contains code. The whole table must be 32-byte aligned.
89
+ // The table may also be relocated, so we make it position-independent by
90
+ // having a table of handler addresses and loading the address to pc.
91
+ [[gnu::section(" .vectors" ), gnu::aligned(32 ), gnu::used, gnu::naked,
92
+ gnu::target (" arm" )]]
93
+ void vector_table() {
94
+ asm (" LDR pc, [pc, #24]" );
95
+ asm (" LDR pc, [pc, #24]" );
96
+ asm (" LDR pc, [pc, #24]" );
97
+ asm (" LDR pc, [pc, #24]" );
98
+ asm (" LDR pc, [pc, #24]" );
99
+ asm (" LDR pc, [pc, #24]" );
100
+ asm (" LDR pc, [pc, #24]" );
101
+ asm (" LDR pc, [pc, #24]" );
102
+ asm (" .word %c0" : : " X" (Reset_Handler));
103
+ asm (" .word %c0" : : " X" (Undefined_Handler));
104
+ asm (" .word %c0" : : " X" (SWI_Handler));
105
+ asm (" .word %c0" : : " X" (PrefetchAbort_Handler));
106
+ asm (" .word %c0" : : " X" (DataAbort_Handler));
107
+ asm (" .word %c0" : : " X" (0 ));
108
+ asm (" .word %c0" : : " X" (IRQ_Handler));
109
+ asm (" .word %c0" : : " X" (FIQ_Handler));
110
+ }
111
+ #endif
73
112
} // namespace
74
113
75
114
namespace LIBC_NAMESPACE_DECL {
76
115
[[noreturn]] void do_start () {
77
116
// FIXME: set up the QEMU test environment
78
117
118
+ #if __ARM_ARCH_PROFILE == 'A' || __ARM_ARCH_PROFILE == 'R'
119
+ // Set up registers to be used in exception handling
120
+ // Copy the current sp value to each of the banked copies of sp.
121
+ __arm_wsr (" CPSR_c" , 0x11 ); // FIQ
122
+ asm volatile (" mov sp, %0" : : " r" (__builtin_frame_address (0 )));
123
+ __arm_wsr (" CPSR_c" , 0x12 ); // IRQ
124
+ asm volatile (" mov sp, %0" : : " r" (__builtin_frame_address (0 )));
125
+ __arm_wsr (" CPSR_c" , 0x17 ); // ABT
126
+ asm volatile (" mov sp, %0" : : " r" (__builtin_frame_address (0 )));
127
+ __arm_wsr (" CPSR_c" , 0x1B ); // UND
128
+ asm volatile (" mov sp, %0" : : " r" (__builtin_frame_address (0 )));
129
+ __arm_wsr (" CPSR_c" , 0x1F ); // SYS
130
+ asm volatile (" mov sp, %0" : : " r" (__builtin_frame_address (0 )));
131
+ __arm_wsr (" CPSR_c" , 0x13 ); // SVC
132
+ #endif
133
+
79
134
// Perform the equivalent of scatterloading
80
135
LIBC_NAMESPACE::memcpy (__data_start, __data_source,
81
136
reinterpret_cast <uintptr_t >(__data_size));
@@ -89,7 +144,13 @@ namespace LIBC_NAMESPACE_DECL {
89
144
}
90
145
} // namespace LIBC_NAMESPACE_DECL
91
146
92
- extern " C" void _start () {
147
+ extern " C" {
148
+ #ifdef __ARM_ARCH_ISA_ARM
149
+ // If ARM state is supported, it must be used (instead of Thumb)
150
+ [[gnu::naked, gnu::target(" arm" )]]
151
+ #endif
152
+ void _start () {
93
153
asm volatile (" mov sp, %0" : : " r" (&__stack));
94
154
asm volatile (" bl %0" : : " X" (LIBC_NAMESPACE::do_start));
95
155
}
156
+ } // extern "C"
0 commit comments