| // Copyright 2023 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <lib/arch/asm.h> |
| |
| // This defines the entry point in assembly, such that it calls: |
| // extern "C" uintptr_t StartLd(StartupStack& stack); |
| // And then jumps to the user entry point in the return value, with |
| // the original stack intact. |
| // (See posix-startup.cc for definition.) |
| |
| .function _start, global |
| |
| // This can assume the sp is already aligned to 16 by the kernel. |
| |
| #if defined(__aarch64__) |
| |
| mov x0, sp |
| bl StartLd |
| // The executable's entry point checks x0 for a pointer to pass to atexit. |
| mov x16, x0 |
| mov x0, xzr |
| br x16 |
| |
| #elif defined(__riscv) |
| |
| mv a0, sp |
| call StartLd |
| // The executable's entry point checks a5 for a pointer to pass to atexit. |
| mv a5, zero |
| jr a0 |
| |
| #elif defined(__x86_64__) |
| |
| // The ld-startup-tests.cc code puts its return address here. |
| // Save it in a call-saved register. |
| mov -8(%rsp), %rbx |
| |
| mov %rsp, %rdi |
| call StartLd |
| // The executable's entry point checks %rdx for a pointer to pass to atexit. |
| xor %rdx, %rdx |
| // Restore the saved incoming return address so a special test executable |
| // can know the protocol to recover it from below the stack. |
| mov %rbx, -8(%rsp) |
| jmp *%rax |
| |
| #else |
| #error "unsupported machine" |
| #endif |
| |
| .end_function |