1/* AArch64 support code for fibers and multithreading. 2 Copyright (C) 2019 Free Software Foundation, Inc. 3 4This file is part of GCC. 5 6GCC is free software; you can redistribute it and/or modify it under 7the terms of the GNU General Public License as published by the Free 8Software Foundation; either version 3, or (at your option) any later 9version. 10 11GCC is distributed in the hope that it will be useful, but WITHOUT ANY 12WARRANTY; without even the implied warranty of MERCHANTABILITY or 13FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14for more details. 15 16Under Section 7 of GPL version 3, you are granted additional 17permissions described in the GCC Runtime Library Exception, version 183.1, as published by the Free Software Foundation. 19 20You should have received a copy of the GNU General Public License and 21a copy of the GCC Runtime Library Exception along with this program; 22see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23<http://www.gnu.org/licenses/>. */ 24 25#include "../common/threadasm.S" 26 27/** 28 * preserve/restore AAPCS64 registers 29 * x19-x28 5.1.1 64-bit callee saved 30 * x29 fp, or possibly callee saved reg - depends on platform choice 5.2.3) 31 * x30 lr 32 * d8-d15 5.1.2 says callee only must save bottom 64-bits (the "d" regs) 33 * 34 * saved regs on stack will look like: 35 * 19: x19 36 * 18: x20 37 * ... 38 * 10: x28 39 * 9: x29 (fp) <-- oldp / *newp save stack top 40 * 8: x30 (lr) 41 * 7: d8 42 * ... 43 * 0: d15 <-- sp 44 */ 45 .text 46 .global CSYM(fiber_switchContext) 47 .type CSYM(fiber_switchContext), %function 48 .align 4 49CSYM(fiber_switchContext): 50 .cfi_startproc 51 stp d15, d14, [sp, #-20*8]! 52 stp d13, d12, [sp, #2*8] 53 stp d11, d10, [sp, #4*8] 54 stp d9, d8, [sp, #6*8] 55 stp x30, x29, [sp, #8*8] // lr, fp 56 stp x28, x27, [sp, #10*8] 57 stp x26, x25, [sp, #12*8] 58 stp x24, x23, [sp, #14*8] 59 stp x22, x21, [sp, #16*8] 60 stp x20, x19, [sp, #18*8] 61 62 // oldp is set above saved lr (x30) to hide it and float regs 63 // from GC 64 add x19, sp, #9*8 65 str x19, [x0] // *oldp tstack 66 sub sp, x1, #9*8 // switch to newp sp 67 68 ldp x20, x19, [sp, #18*8] 69 ldp x22, x21, [sp, #16*8] 70 ldp x24, x23, [sp, #14*8] 71 ldp x26, x25, [sp, #12*8] 72 ldp x28, x27, [sp, #10*8] 73 ldp x30, x29, [sp, #8*8] // lr, fp 74 ldp d9, d8, [sp, #6*8] 75 ldp d11, d10, [sp, #4*8] 76 ldp d13, d12, [sp, #2*8] 77 ldp d15, d14, [sp], #20*8 78 ret 79 .cfi_endproc 80 .size CSYM(fiber_switchContext),.-CSYM(fiber_switchContext) 81 82/** 83 * When generating any kind of backtrace (gdb, exception handling) for 84 * a function called in a Fiber, we need to tell the unwinder to stop 85 * at our Fiber main entry point, i.e. we need to mark the bottom of 86 * the call stack. This can be done by clearing the link register lr 87 * prior to calling fiber_entryPoint (i.e. in fiber_switchContext) or 88 * using a .cfi_undefined directive for the link register in the 89 * Fiber entry point. cfi_undefined seems to yield better results in gdb. 90 * Unfortunately we can't place it into fiber_entryPoint using inline 91 * asm, so we use this trampoline instead. 92 */ 93 .text 94 .global CSYM(fiber_trampoline) 95 .p2align 2 96 .type CSYM(fiber_trampoline), %function 97CSYM(fiber_trampoline): 98 .cfi_startproc 99 .cfi_undefined x30 100 // fiber_entryPoint never returns 101 bl CSYM(fiber_entryPoint) 102 .cfi_endproc 103 .size CSYM(fiber_trampoline),.-CSYM(fiber_trampoline) 104