brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.4 KiB · db89828 Raw
192 lines · cpp
1//===-- Implementation of crt for arm -------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "hdr/stdint_proxy.h"10#include "src/__support/macros/config.h"11#include "src/stdlib/atexit.h"12#include "src/stdlib/exit.h"13#include "src/string/memcpy.h"14#include "src/string/memset.h"15#include "startup/baremetal/fini.h"16#include "startup/baremetal/init.h"17 18#include <arm_acle.h> // For __arm_wsr19 20extern "C" {21int main(int argc, char **argv);22void _start();23 24// Semihosting library initialisation if applicable. Required for printf, etc.25[[gnu::weak]] void _platform_init() {}26 27// These symbols are provided by the linker. The exact names are not defined by28// a standard.29extern uintptr_t __stack;30extern uintptr_t __data_source[];31extern uintptr_t __data_start[];32extern uintptr_t __data_size[];33extern uintptr_t __bss_start[];34extern uintptr_t __bss_size[];35} // extern "C"36 37namespace {38#if __ARM_ARCH_PROFILE == 'M'39// Based on40// https://developer.arm.com/documentation/107565/0101/Use-case-examples/Generic-Information/What-is-inside-a-program-image-/Vector-table41void NMI_Handler() {}42void HardFault_Handler() { LIBC_NAMESPACE::exit(1); }43void MemManage_Handler() { LIBC_NAMESPACE::exit(1); }44void BusFault_Handler() { LIBC_NAMESPACE::exit(1); }45void UsageFault_Handler() { LIBC_NAMESPACE::exit(1); }46void SVC_Handler() {}47void DebugMon_Handler() {}48void PendSV_Handler() {}49void SysTick_Handler() {}50 51// Architecturally the bottom 7 bits of VTOR are zero, meaning the vector table52// has to be 128-byte aligned, however an implementation can require more bits53// to be zero and Cortex-M23 can require up to 10, so 1024-byte align the vector54// table.55using HandlerType = void (*)(void);56[[gnu::section(".vectors"), gnu::aligned(1024), gnu::used]]57const HandlerType vector_table[] = {58    reinterpret_cast<HandlerType>(&__stack), // SP59    _start,                                  // Reset60    NMI_Handler,                             // NMI Handler61    HardFault_Handler,                       // Hard Fault Handler62    MemManage_Handler,                       // MPU Fault Handler63    BusFault_Handler,                        // Bus Fault Handler64    UsageFault_Handler,                      // Usage Fault Handler65    0,                                       // Reserved66    0,                                       // Reserved67    0,                                       // Reserved68    0,                                       // Reserved69    SVC_Handler,                             // SVC Handler70    DebugMon_Handler,                        // Debug Monitor Handler71    0,                                       // Reserved72    PendSV_Handler,                          // PendSV Handler73    SysTick_Handler,                         // SysTick Handler74                                             // Unused75};76#else77// Based on78// https://developer.arm.com/documentation/den0013/0400/Boot-Code/Booting-a-bare-metal-system79void Reset_Handler() { LIBC_NAMESPACE::exit(1); }80void Undefined_Handler() { LIBC_NAMESPACE::exit(1); }81void SWI_Handler() { LIBC_NAMESPACE::exit(1); }82void PrefetchAbort_Handler() { LIBC_NAMESPACE::exit(1); }83void DataAbort_Handler() { LIBC_NAMESPACE::exit(1); }84void IRQ_Handler() { LIBC_NAMESPACE::exit(1); }85void FIQ_Handler() { LIBC_NAMESPACE::exit(1); }86 87// The AArch32 exception vector table has 8 entries, each of which is 488// 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 by90// 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")]]93void 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#endif112} // namespace113 114namespace LIBC_NAMESPACE_DECL {115[[noreturn]] void do_start() {116  // FIXME: set up the QEMU test environment117 118#if __ARM_ARCH_PROFILE == 'A' || __ARM_ARCH_PROFILE == 'R'119  // Set up registers to be used in exception handling120  // Copy the current sp value to each of the banked copies of sp.121  __arm_wsr("CPSR_c", 0x11); // FIQ122  asm volatile("mov sp, %0" : : "r"(__builtin_frame_address(0)));123  __arm_wsr("CPSR_c", 0x12); // IRQ124  asm volatile("mov sp, %0" : : "r"(__builtin_frame_address(0)));125  __arm_wsr("CPSR_c", 0x17); // ABT126  asm volatile("mov sp, %0" : : "r"(__builtin_frame_address(0)));127  __arm_wsr("CPSR_c", 0x1B); // UND128  asm volatile("mov sp, %0" : : "r"(__builtin_frame_address(0)));129  __arm_wsr("CPSR_c", 0x1F); // SYS130  asm volatile("mov sp, %0" : : "r"(__builtin_frame_address(0)));131  __arm_wsr("CPSR_c", 0x13); // SVC132#endif133 134#if __ARM_ARCH_PROFILE == 'M' &&                                               \135    (defined(__ARM_FP) || defined(__ARM_FEATURE_MVE))136  // Enable FPU and MVE. They can't be enabled independently: the two are137  // governed by the same bits in CPACR.138  // Based on139  // https://developer.arm.com/documentation/dui0646/c/Cortex-M7-Peripherals/Floating-Point-Unit/Enabling-the-FPU140  // Set CPACR cp10 and cp11.141  auto cpacr = reinterpret_cast<volatile uint32_t *const>(0xE000ED88);142  *cpacr |= (0xF << 20);143  __dsb(0xF);144  __isb(0xF);145#if defined(__ARM_FEATURE_MVE)146  // Initialize low-overhead-loop tail predication to its neutral state147  uint32_t fpscr;148  __asm__ __volatile__("vmrs %0, FPSCR" : "=r"(fpscr) : :);149  fpscr |= (0x4 << 16);150  __asm__ __volatile__("vmsr FPSCR, %0" : : "r"(fpscr) :);151#endif152#elif (__ARM_ARCH_PROFILE == 'A' || __ARM_ARCH_PROFILE == 'R') &&              \153    defined(__ARM_FP)154  // Enable FPU.155  // Based on156  // https://developer.arm.com/documentation/dui0472/m/Compiler-Coding-Practices/Enabling-NEON-and-FPU-for-bare-metal157  // Set CPACR cp10 and cp11.158  uint32_t cpacr = __arm_rsr("p15:0:c1:c0:2");159  cpacr |= (0xF << 20);160  __arm_wsr("p15:0:c1:c0:2", cpacr);161  __isb(0xF);162  // Set FPEXC.EN163  uint32_t fpexc;164  __asm__ __volatile__("vmrs %0, FPEXC" : "=r"(fpexc) : :);165  fpexc |= (0x1 << 30);166  __asm__ __volatile__("vmsr FPEXC, %0" : : "r"(fpexc) :);167#endif168 169  // Perform the equivalent of scatterloading170  LIBC_NAMESPACE::memcpy(__data_start, __data_source,171                         reinterpret_cast<uintptr_t>(__data_size));172  LIBC_NAMESPACE::memset(__bss_start, '\0',173                         reinterpret_cast<uintptr_t>(__bss_size));174  __libc_init_array();175 176  _platform_init();177  LIBC_NAMESPACE::atexit(&__libc_fini_array);178  LIBC_NAMESPACE::exit(main(0, 0));179}180} // namespace LIBC_NAMESPACE_DECL181 182extern "C" {183#ifdef __ARM_ARCH_ISA_ARM184// If ARM state is supported, it must be used (instead of Thumb)185[[gnu::naked, gnu::target("arm")]]186#endif187void _start() {188  asm volatile("mov sp, %0" : : "r"(&__stack));189  asm volatile("bl %0" : : "X"(LIBC_NAMESPACE::do_start));190}191} // extern "C"192