[libc] Add startup code for ARM v7-A, ARM v7-R variants (#153576)
These variants require a different exception table that requires a bit of initialisation. This allows us to enable testing for these variants downstream.
This commit is contained in:
parent
21b607adbe
commit
6b16a276ef
@ -15,6 +15,8 @@
|
||||
#include "startup/baremetal/fini.h"
|
||||
#include "startup/baremetal/init.h"
|
||||
|
||||
#include <arm_acle.h> // For __arm_wsr
|
||||
|
||||
extern "C" {
|
||||
int main(int argc, char **argv);
|
||||
void _start();
|
||||
@ -33,6 +35,7 @@ extern uintptr_t __bss_size[];
|
||||
} // extern "C"
|
||||
|
||||
namespace {
|
||||
#if __ARM_ARCH_PROFILE == 'M'
|
||||
// Based on
|
||||
// https://developer.arm.com/documentation/107565/0101/Use-case-examples/Generic-Information/What-is-inside-a-program-image-/Vector-table
|
||||
void NMI_Handler() {}
|
||||
@ -55,8 +58,8 @@ const HandlerType vector_table[] = {
|
||||
reinterpret_cast<HandlerType>(&__stack), // SP
|
||||
_start, // Reset
|
||||
NMI_Handler, // NMI Handler
|
||||
HardFault_Handler, // Hard Fault Handlerß
|
||||
MemManage_Handler, // MPU Fault Han`dler
|
||||
HardFault_Handler, // Hard Fault Handler
|
||||
MemManage_Handler, // MPU Fault Handler
|
||||
BusFault_Handler, // Bus Fault Handler
|
||||
UsageFault_Handler, // Usage Fault Handler
|
||||
0, // Reserved
|
||||
@ -70,12 +73,64 @@ const HandlerType vector_table[] = {
|
||||
SysTick_Handler, // SysTick Handler
|
||||
// Unused
|
||||
};
|
||||
#else
|
||||
// Based on
|
||||
// https://developer.arm.com/documentation/den0013/0400/Boot-Code/Booting-a-bare-metal-system
|
||||
void Reset_Handler() { LIBC_NAMESPACE::exit(1); }
|
||||
void Undefined_Handler() { LIBC_NAMESPACE::exit(1); }
|
||||
void SWI_Handler() { LIBC_NAMESPACE::exit(1); }
|
||||
void PrefetchAbort_Handler() { LIBC_NAMESPACE::exit(1); }
|
||||
void DataAbort_Handler() { LIBC_NAMESPACE::exit(1); }
|
||||
void IRQ_Handler() { LIBC_NAMESPACE::exit(1); }
|
||||
void FIQ_Handler() { LIBC_NAMESPACE::exit(1); }
|
||||
|
||||
// The AArch32 exception vector table has 8 entries, each of which is 4
|
||||
// bytes long, and contains code. The whole table must be 32-byte aligned.
|
||||
// The table may also be relocated, so we make it position-independent by
|
||||
// having a table of handler addresses and loading the address to pc.
|
||||
[[gnu::section(".vectors"), gnu::aligned(32), gnu::used, gnu::naked,
|
||||
gnu::target("arm")]]
|
||||
void vector_table() {
|
||||
asm("LDR pc, [pc, #24]");
|
||||
asm("LDR pc, [pc, #24]");
|
||||
asm("LDR pc, [pc, #24]");
|
||||
asm("LDR pc, [pc, #24]");
|
||||
asm("LDR pc, [pc, #24]");
|
||||
asm("LDR pc, [pc, #24]");
|
||||
asm("LDR pc, [pc, #24]");
|
||||
asm("LDR pc, [pc, #24]");
|
||||
asm(".word %c0" : : "X"(Reset_Handler));
|
||||
asm(".word %c0" : : "X"(Undefined_Handler));
|
||||
asm(".word %c0" : : "X"(SWI_Handler));
|
||||
asm(".word %c0" : : "X"(PrefetchAbort_Handler));
|
||||
asm(".word %c0" : : "X"(DataAbort_Handler));
|
||||
asm(".word %c0" : : "X"(0));
|
||||
asm(".word %c0" : : "X"(IRQ_Handler));
|
||||
asm(".word %c0" : : "X"(FIQ_Handler));
|
||||
}
|
||||
#endif
|
||||
} // namespace
|
||||
|
||||
namespace LIBC_NAMESPACE_DECL {
|
||||
[[noreturn]] void do_start() {
|
||||
// FIXME: set up the QEMU test environment
|
||||
|
||||
#if __ARM_ARCH_PROFILE == 'A' || __ARM_ARCH_PROFILE == 'R'
|
||||
// Set up registers to be used in exception handling
|
||||
// Copy the current sp value to each of the banked copies of sp.
|
||||
__arm_wsr("CPSR_c", 0x11); // FIQ
|
||||
asm volatile("mov sp, %0" : : "r"(__builtin_frame_address(0)));
|
||||
__arm_wsr("CPSR_c", 0x12); // IRQ
|
||||
asm volatile("mov sp, %0" : : "r"(__builtin_frame_address(0)));
|
||||
__arm_wsr("CPSR_c", 0x17); // ABT
|
||||
asm volatile("mov sp, %0" : : "r"(__builtin_frame_address(0)));
|
||||
__arm_wsr("CPSR_c", 0x1B); // UND
|
||||
asm volatile("mov sp, %0" : : "r"(__builtin_frame_address(0)));
|
||||
__arm_wsr("CPSR_c", 0x1F); // SYS
|
||||
asm volatile("mov sp, %0" : : "r"(__builtin_frame_address(0)));
|
||||
__arm_wsr("CPSR_c", 0x13); // SVC
|
||||
#endif
|
||||
|
||||
// Perform the equivalent of scatterloading
|
||||
LIBC_NAMESPACE::memcpy(__data_start, __data_source,
|
||||
reinterpret_cast<uintptr_t>(__data_size));
|
||||
@ -89,7 +144,13 @@ namespace LIBC_NAMESPACE_DECL {
|
||||
}
|
||||
} // namespace LIBC_NAMESPACE_DECL
|
||||
|
||||
extern "C" void _start() {
|
||||
extern "C" {
|
||||
#ifdef __ARM_ARCH_ISA_ARM
|
||||
// If ARM state is supported, it must be used (instead of Thumb)
|
||||
[[gnu::naked, gnu::target("arm")]]
|
||||
#endif
|
||||
void _start() {
|
||||
asm volatile("mov sp, %0" : : "r"(&__stack));
|
||||
asm volatile("bl %0" : : "X"(LIBC_NAMESPACE::do_start));
|
||||
}
|
||||
} // extern "C"
|
||||
|
Loading…
x
Reference in New Issue
Block a user