/* AArch64 support code for fibers and multithreading. Copyright (C) 2019-2022 Free Software Foundation, Inc. This file is part of GCC. GCC is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GCC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Under Section 7 of GPL version 3, you are granted additional permissions described in the GCC Runtime Library Exception, version 3.1, as published by the Free Software Foundation. You should have received a copy of the GNU General Public License and a copy of the GCC Runtime Library Exception along with this program; see the files COPYING3 and COPYING.RUNTIME respectively. If not, see . */ #include "../common/threadasm.S" /** * preserve/restore AAPCS64 registers * x19-x28 5.1.1 64-bit callee saved * x29 fp, or possibly callee saved reg - depends on platform choice 5.2.3) * x30 lr * d8-d15 5.1.2 says callee only must save bottom 64-bits (the "d" regs) * * saved regs on stack will look like: * 19: x19 * 18: x20 * ... * 10: x28 * 9: x29 (fp) <-- oldp / *newp save stack top * 8: x30 (lr) * 7: d8 * ... * 0: d15 <-- sp */ .text .global CSYM(fiber_switchContext) .type CSYM(fiber_switchContext), %function .align 4 CSYM(fiber_switchContext): .cfi_startproc stp d15, d14, [sp, #-20*8]! stp d13, d12, [sp, #2*8] stp d11, d10, [sp, #4*8] stp d9, d8, [sp, #6*8] stp x30, x29, [sp, #8*8] // lr, fp stp x28, x27, [sp, #10*8] stp x26, x25, [sp, #12*8] stp x24, x23, [sp, #14*8] stp x22, x21, [sp, #16*8] stp x20, x19, [sp, #18*8] // oldp is set above saved lr (x30) to hide it and float regs // from GC add x19, sp, #9*8 str x19, [x0] // *oldp tstack sub sp, x1, #9*8 // switch to newp sp ldp x20, x19, [sp, #18*8] ldp x22, x21, [sp, #16*8] ldp x24, x23, [sp, #14*8] ldp x26, x25, [sp, #12*8] ldp x28, x27, [sp, #10*8] ldp x30, x29, [sp, #8*8] // lr, fp ldp d9, d8, [sp, #6*8] ldp d11, d10, [sp, #4*8] ldp d13, d12, [sp, #2*8] ldp d15, d14, [sp], #20*8 ret .cfi_endproc .size CSYM(fiber_switchContext),.-CSYM(fiber_switchContext) /** * When generating any kind of backtrace (gdb, exception handling) for * a function called in a Fiber, we need to tell the unwinder to stop * at our Fiber main entry point, i.e. we need to mark the bottom of * the call stack. This can be done by clearing the link register lr * prior to calling fiber_entryPoint (i.e. in fiber_switchContext) or * using a .cfi_undefined directive for the link register in the * Fiber entry point. cfi_undefined seems to yield better results in gdb. * Unfortunately we can't place it into fiber_entryPoint using inline * asm, so we use this trampoline instead. */ .text .global CSYM(fiber_trampoline) .p2align 2 .type CSYM(fiber_trampoline), %function CSYM(fiber_trampoline): .cfi_startproc .cfi_undefined x30 // fiber_entryPoint never returns bl CSYM(fiber_entryPoint) .cfi_endproc .size CSYM(fiber_trampoline),.-CSYM(fiber_trampoline)