1/* Record the register state before and after a variant PCS call.
2   Copyright (C) 2020-2022 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