1/* Record the register state before and after a variant PCS call.
2 Copyright (C) 2020-2024 Free Software Foundation, Inc.
3
4 This file is part of the GNU C Library.
5
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public License as
8 published by the Free Software Foundation; either version 2.1 of the
9 License, or (at your option) any later version.
10
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library. If not, see
18 <https://www.gnu.org/licenses/>. */
19
20 .variant_pcs vpcs_call
21 .global vpcs_call
22 .type vpcs_call, %function
23vpcs_call:
24 .cfi_startproc
25 hint 34 /* bti c. */
26
27 /* Save register state to *x0. */
28 stp x0, x1, [x0]
29 stp x2, x3, [x0, 16]
30 stp x4, x5, [x0, 32]
31 stp x6, x7, [x0, 48]
32 stp x8, x9, [x0, 64]
33 stp x10, x11, [x0, 80]
34 stp x12, x13, [x0, 96]
35 stp x14, x15, [x0, 112]
36 stp x16, x17, [x0, 128]
37 stp x18, x19, [x0, 144]
38 stp x20, x21, [x0, 160]
39 stp x22, x23, [x0, 176]
40 stp x24, x25, [x0, 192]
41 stp x26, x27, [x0, 208]
42 stp x28, x29, [x0, 224]
43 mov x1, sp
44 stp x30, x1, [x0, 240]
45 stp q0, q1, [x0, 256]
46 stp q2, q3, [x0, 288]
47 stp q4, q5, [x0, 320]
48 stp q6, q7, [x0, 352]
49 stp q8, q9, [x0, 384]
50 stp q10, q11, [x0, 416]
51 stp q12, q13, [x0, 448]
52 stp q14, q15, [x0, 480]
53 stp q16, q17, [x0, 512]
54 stp q18, q19, [x0, 544]
55 stp q20, q21, [x0, 576]
56 stp q22, q23, [x0, 608]
57 stp q24, q25, [x0, 640]
58 stp q26, q27, [x0, 672]
59 stp q28, q29, [x0, 704]
60 stp q30, q31, [x0, 736]
61 ret
62 .cfi_endproc
63 .size vpcs_call, .-vpcs_call
64
65 .global vpcs_call_regs
66 .type vpcs_call_regs, %function
67vpcs_call_regs:
68 .cfi_startproc
69 hint 34 /* bti c. */
70
71 stp x29, x30, [sp, -160]!
72 mov x29, sp
73
74 /* Save callee-saved registers. */
75 stp x19, x20, [sp, 16]
76 stp x21, x22, [sp, 32]
77 stp x23, x24, [sp, 48]
78 stp x25, x26, [sp, 64]
79 stp x27, x28, [sp, 80]
80 stp d8, d9, [sp, 96]
81 stp d10, d11, [sp, 112]
82 stp d12, d13, [sp, 128]
83 stp d14, d15, [sp, 144]
84
85 /* Initialize most registers from *x1, and save x0, x1, x29, x30,
86 and sp (== x29), so *x1 contains the register state. */
87 stp x0, x1, [x1]
88 str x29, [x1, 232]
89 ldp x2, x3, [x1, 16]
90 ldp x4, x5, [x1, 32]
91 ldp x6, x7, [x1, 48]
92 ldp x8, x9, [x1, 64]
93 ldp x10, x11, [x1, 80]
94 ldp x12, x13, [x1, 96]
95 ldp x14, x15, [x1, 112]
96 ldp x16, x17, [x1, 128]
97 ldp x18, x19, [x1, 144]
98 ldp x20, x21, [x1, 160]
99 ldp x22, x23, [x1, 176]
100 ldp x24, x25, [x1, 192]
101 ldp x26, x27, [x1, 208]
102 ldr x28, [x1, 224]
103 /* Skip x29, x30, sp. */
104 ldp q0, q1, [x1, 256]
105 ldp q2, q3, [x1, 288]
106 ldp q4, q5, [x1, 320]
107 ldp q6, q7, [x1, 352]
108 ldp q8, q9, [x1, 384]
109 ldp q10, q11, [x1, 416]
110 ldp q12, q13, [x1, 448]
111 ldp q14, q15, [x1, 480]
112 ldp q16, q17, [x1, 512]
113 ldp q18, q19, [x1, 544]
114 ldp q20, q21, [x1, 576]
115 ldp q22, q23, [x1, 608]
116 ldp q24, q25, [x1, 640]
117 ldp q26, q27, [x1, 672]
118 ldp q28, q29, [x1, 704]
119 ldp q30, q31, [x1, 736]
120
121 /* Emulate a BL using B, but save x30 before the branch. */
122 adr x30, .L_return_addr
123 stp x30, x29, [x1, 240]
124 b vpcs_call
125.L_return_addr:
126
127 /* Restore callee-saved registers. */
128 ldp x19, x20, [sp, 16]
129 ldp x21, x22, [sp, 32]
130 ldp x23, x24, [sp, 48]
131 ldp x25, x26, [sp, 64]
132 ldp x27, x28, [sp, 80]
133 ldp d8, d9, [sp, 96]
134 ldp d10, d11, [sp, 112]
135 ldp d12, d13, [sp, 128]
136 ldp d14, d15, [sp, 144]
137
138 ldp x29, x30, [sp], 160
139 ret
140 .cfi_endproc
141 .size vpcs_call_regs, .-vpcs_call_regs
142

source code of glibc/sysdeps/aarch64/tst-vpcs-mod.S