113 lines · cpp
1//===-- Implementation of crt for aarch64 ---------------------------------===//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>19 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// The Arm ARM for the A-profile architecture (D14.1.5) defines the exceptions.39// However, for simplicity, we don't bother logging, and just exit.40void GenericException_Handler() { LIBC_NAMESPACE::exit(1); }41 42// The AArch64 exception vector table has 16 entries, each of which is 12843// bytes long, and contains code. The whole table must be 2048-byte aligned.44// For our purposes, each entry just contains one branch instruction to the45// exception reporting function, since we never want to resume after an46// exception.47[[gnu::section(".vectors"), gnu::aligned(2048), gnu::used, gnu::naked]]48void vector_table() {49#define VECTOR_TABLE_ENTRY \50 asm(".balign 128"); \51 asm("B %0" : : "X"(GenericException_Handler));52 53 VECTOR_TABLE_ENTRY;54 VECTOR_TABLE_ENTRY;55 VECTOR_TABLE_ENTRY;56 VECTOR_TABLE_ENTRY;57 VECTOR_TABLE_ENTRY;58 VECTOR_TABLE_ENTRY;59 VECTOR_TABLE_ENTRY;60 VECTOR_TABLE_ENTRY;61 VECTOR_TABLE_ENTRY;62 VECTOR_TABLE_ENTRY;63 VECTOR_TABLE_ENTRY;64 VECTOR_TABLE_ENTRY;65 VECTOR_TABLE_ENTRY;66 VECTOR_TABLE_ENTRY;67 VECTOR_TABLE_ENTRY;68 VECTOR_TABLE_ENTRY;69}70} // namespace71 72namespace LIBC_NAMESPACE_DECL {73 74[[noreturn]] void do_start() {75 // TODO: This startup code is not extensive, but rather the MVP for QEMU76 // testing.77 // TODO: Setup memory (MMU, page table, caches)78 // TODO: Consider v8-R variants79 80 // Set up exception handling81 __arm_wsr64("VBAR_EL1", reinterpret_cast<uint64_t>(&vector_table));82 83#ifdef __ARM_FP84 // Do not trap FP/SME/SVE instructions85 static constexpr uint64_t CPACR_SHIFT_FPEN = 20;86 static constexpr uint64_t CPACR_SHIFT_SMEN = 24;87 uint64_t cpacr = __arm_rsr64("CPACR_EL1");88 cpacr |= (0x3 << CPACR_SHIFT_FPEN);89 cpacr |= (0x3 << CPACR_SHIFT_SMEN);90 __arm_wsr64("CPACR_EL1", cpacr);91#endif92 93 // Perform the equivalent of scatterloading94 LIBC_NAMESPACE::memcpy(__data_start, __data_source,95 reinterpret_cast<uintptr_t>(__data_size));96 LIBC_NAMESPACE::memset(__bss_start, '\0',97 reinterpret_cast<uintptr_t>(__bss_size));98 __libc_init_array();99 100 _platform_init();101 LIBC_NAMESPACE::atexit(&__libc_fini_array);102 LIBC_NAMESPACE::exit(main(0, 0));103}104} // namespace LIBC_NAMESPACE_DECL105 106extern "C" {107[[gnu::section(".text.init.enter"), gnu::naked]]108void _start() {109 asm volatile("mov sp, %0" : : "r"(&__stack));110 asm volatile("bl %0" : : "X"(LIBC_NAMESPACE::do_start));111}112} // extern "C"113