104 lines
3.5 KiB
ArmAsm
104 lines
3.5 KiB
ArmAsm
/* 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
|
|
<http://www.gnu.org/licenses/>. */
|
|
|
|
#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)
|