aboutsummaryrefslogtreecommitdiff
path: root/libc/startup/baremetal/arm/start.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libc/startup/baremetal/arm/start.cpp')
-rw-r--r--libc/startup/baremetal/arm/start.cpp92
1 files changed, 92 insertions, 0 deletions
diff --git a/libc/startup/baremetal/arm/start.cpp b/libc/startup/baremetal/arm/start.cpp
new file mode 100644
index 0000000..123efc4
--- /dev/null
+++ b/libc/startup/baremetal/arm/start.cpp
@@ -0,0 +1,92 @@
+//===-- Implementation of crt for arm -------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/__support/macros/config.h"
+#include "src/stdlib/atexit.h"
+#include "src/stdlib/exit.h"
+#include "src/string/memcpy.h"
+#include "src/string/memset.h"
+#include "startup/baremetal/fini.h"
+#include "startup/baremetal/init.h"
+
+#include <stdint.h>
+
+extern "C" {
+int main(int argc, char **argv);
+void _start();
+
+// Semihosting library initialisation if applicable. Required for printf, etc.
+[[gnu::weak]] void _platform_init() {}
+
+// These symbols are provided by the linker. The exact names are not defined by
+// a standard.
+extern uintptr_t __stack;
+extern uintptr_t __data_source[];
+extern uintptr_t __data_start[];
+extern uintptr_t __data_size[];
+extern uintptr_t __bss_start[];
+extern uintptr_t __bss_size[];
+
+// 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() {}
+void HardFault_Handler() { LIBC_NAMESPACE::exit(1); }
+void MemManage_Handler() { LIBC_NAMESPACE::exit(1); }
+void BusFault_Handler() { LIBC_NAMESPACE::exit(1); }
+void UsageFault_Handler() { LIBC_NAMESPACE::exit(1); }
+void SVC_Handler() {}
+void DebugMon_Handler() {}
+void PendSV_Handler() {}
+void SysTick_Handler() {}
+
+// Architecturally the bottom 7 bits of VTOR are zero, meaning the vector table
+// has to be 128-byte aligned, however an implementation can require more bits
+// to be zero and Cortex-M23 can require up to 10, so 1024-byte align the vector
+// table.
+using HandlerType = void (*)(void);
+const HandlerType vector_table[]
+ __attribute__((section(".vectors"), aligned(1024), used)) = {
+ (HandlerType)&__stack, // SP
+ _start, // Reset
+ NMI_Handler, // NMI Handler
+ HardFault_Handler, // Hard Fault Handlerß
+ MemManage_Handler, // MPU Fault Han`dler
+ BusFault_Handler, // Bus Fault Handler
+ UsageFault_Handler, // Usage Fault Handler
+ 0, // Reserved
+ 0, // Reserved
+ 0, // Reserved
+ 0, // Reserved
+ SVC_Handler, // SVC Handler
+ DebugMon_Handler, // Debug Monitor Handler
+ 0, // Reserved
+ PendSV_Handler, // PendSV Handler
+ SysTick_Handler, // SysTick Handler
+ // Unused
+};
+} // extern "C"
+
+namespace LIBC_NAMESPACE_DECL {
+[[noreturn]] void do_start() {
+ // FIXME: set up the QEMU test environment
+
+ // Perform the equivalent of scatterloading
+ LIBC_NAMESPACE::memcpy(__data_start, __data_source, (uintptr_t)__data_size);
+ LIBC_NAMESPACE::memset(__bss_start, '\0', (uintptr_t)__bss_size);
+ __libc_init_array();
+
+ _platform_init();
+ LIBC_NAMESPACE::atexit(&__libc_fini_array);
+ LIBC_NAMESPACE::exit(main(0, 0));
+}
+} // namespace LIBC_NAMESPACE_DECL
+
+extern "C" void _start() {
+ asm volatile("mov sp, %0" : : "r"(&__stack));
+ asm volatile("bl %0" : : "X"(LIBC_NAMESPACE::do_start));
+}