glibc/sysdeps/aarch64/tst-vpcs-mod.S

142 lines
3.6 KiB
ArmAsm

/* Record the register state before and after a variant PCS call.
Copyright (C) 2020-2023 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
The GNU C Library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library. If not, see
<https://www.gnu.org/licenses/>. */
.variant_pcs vpcs_call
.global vpcs_call
.type vpcs_call, %function
vpcs_call:
.cfi_startproc
hint 34 /* bti c. */
/* Save register state to *x0. */
stp x0, x1, [x0]
stp x2, x3, [x0, 16]
stp x4, x5, [x0, 32]
stp x6, x7, [x0, 48]
stp x8, x9, [x0, 64]
stp x10, x11, [x0, 80]
stp x12, x13, [x0, 96]
stp x14, x15, [x0, 112]
stp x16, x17, [x0, 128]
stp x18, x19, [x0, 144]
stp x20, x21, [x0, 160]
stp x22, x23, [x0, 176]
stp x24, x25, [x0, 192]
stp x26, x27, [x0, 208]
stp x28, x29, [x0, 224]
mov x1, sp
stp x30, x1, [x0, 240]
stp q0, q1, [x0, 256]
stp q2, q3, [x0, 288]
stp q4, q5, [x0, 320]
stp q6, q7, [x0, 352]
stp q8, q9, [x0, 384]
stp q10, q11, [x0, 416]
stp q12, q13, [x0, 448]
stp q14, q15, [x0, 480]
stp q16, q17, [x0, 512]
stp q18, q19, [x0, 544]
stp q20, q21, [x0, 576]
stp q22, q23, [x0, 608]
stp q24, q25, [x0, 640]
stp q26, q27, [x0, 672]
stp q28, q29, [x0, 704]
stp q30, q31, [x0, 736]
ret
.cfi_endproc
.size vpcs_call, .-vpcs_call
.global vpcs_call_regs
.type vpcs_call_regs, %function
vpcs_call_regs:
.cfi_startproc
hint 34 /* bti c. */
stp x29, x30, [sp, -160]!
mov x29, sp
/* Save callee-saved registers. */
stp x19, x20, [sp, 16]
stp x21, x22, [sp, 32]
stp x23, x24, [sp, 48]
stp x25, x26, [sp, 64]
stp x27, x28, [sp, 80]
stp d8, d9, [sp, 96]
stp d10, d11, [sp, 112]
stp d12, d13, [sp, 128]
stp d14, d15, [sp, 144]
/* Initialize most registers from *x1, and save x0, x1, x29, x30,
and sp (== x29), so *x1 contains the register state. */
stp x0, x1, [x1]
str x29, [x1, 232]
ldp x2, x3, [x1, 16]
ldp x4, x5, [x1, 32]
ldp x6, x7, [x1, 48]
ldp x8, x9, [x1, 64]
ldp x10, x11, [x1, 80]
ldp x12, x13, [x1, 96]
ldp x14, x15, [x1, 112]
ldp x16, x17, [x1, 128]
ldp x18, x19, [x1, 144]
ldp x20, x21, [x1, 160]
ldp x22, x23, [x1, 176]
ldp x24, x25, [x1, 192]
ldp x26, x27, [x1, 208]
ldr x28, [x1, 224]
/* Skip x29, x30, sp. */
ldp q0, q1, [x1, 256]
ldp q2, q3, [x1, 288]
ldp q4, q5, [x1, 320]
ldp q6, q7, [x1, 352]
ldp q8, q9, [x1, 384]
ldp q10, q11, [x1, 416]
ldp q12, q13, [x1, 448]
ldp q14, q15, [x1, 480]
ldp q16, q17, [x1, 512]
ldp q18, q19, [x1, 544]
ldp q20, q21, [x1, 576]
ldp q22, q23, [x1, 608]
ldp q24, q25, [x1, 640]
ldp q26, q27, [x1, 672]
ldp q28, q29, [x1, 704]
ldp q30, q31, [x1, 736]
/* Emulate a BL using B, but save x30 before the branch. */
adr x30, .L_return_addr
stp x30, x29, [x1, 240]
b vpcs_call
.L_return_addr:
/* Restore callee-saved registers. */
ldp x19, x20, [sp, 16]
ldp x21, x22, [sp, 32]
ldp x23, x24, [sp, 48]
ldp x25, x26, [sp, 64]
ldp x27, x28, [sp, 80]
ldp d8, d9, [sp, 96]
ldp d10, d11, [sp, 112]
ldp d12, d13, [sp, 128]
ldp d14, d15, [sp, 144]
ldp x29, x30, [sp], 160
ret
.cfi_endproc
.size vpcs_call_regs, .-vpcs_call_regs