[libc-commits] [libc] [libc] Add startup code for ARM v7-A, ARM v7-R variants (PR #153576)

via libc-commits libc-commits at lists.llvm.org
Thu Aug 14 06:40:03 PDT 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-libc

Author: William Huynh (saturn691)

<details>
<summary>Changes</summary>

These variants require a different exception table that requires a bit of initialisation.

This allows us to enable testing for these variants downstream.

---
Full diff: https://github.com/llvm/llvm-project/pull/153576.diff


1 Files Affected:

- (modified) libc/startup/baremetal/arm/start.cpp (+64-3) 


``````````diff
diff --git a/libc/startup/baremetal/arm/start.cpp b/libc/startup/baremetal/arm/start.cpp
index 493445e2922b0..a926206c73a6f 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>
+
 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"

``````````

</details>


https://github.com/llvm/llvm-project/pull/153576


More information about the libc-commits mailing list