[libc-commits] [libc] 6b16a27 - [libc] Add startup code for ARM v7-A, ARM v7-R variants (#153576)
via libc-commits
libc-commits at lists.llvm.org
Fri Aug 15 02:17:53 PDT 2025
Author: William Huynh
Date: 2025-08-15T09:17:50Z
New Revision: 6b16a276ef8fe6b68330ecb57f7c1ee985880967
URL: https://github.com/llvm/llvm-project/commit/6b16a276ef8fe6b68330ecb57f7c1ee985880967
DIFF: https://github.com/llvm/llvm-project/commit/6b16a276ef8fe6b68330ecb57f7c1ee985880967.diff
LOG: [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.
Added:
Modified:
libc/startup/baremetal/arm/start.cpp
Removed:
################################################################################
diff --git a/libc/startup/baremetal/arm/start.cpp b/libc/startup/baremetal/arm/start.cpp
index 493445e2922b0..c089a14f5f782 100644
--- a/libc/startup/baremetal/arm/start.cpp
+++ b/libc/startup/baremetal/arm/start.cpp
@@ -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"
More information about the libc-commits
mailing list