1/* setjmp for PowerPC64.
2 Copyright (C) 1995-2024 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
18
19#include <sysdep.h>
20#include <pointer_guard.h>
21#include <stap-probe.h>
22#define _ASM
23#ifdef __NO_VMX__
24#include <novmxsetjmp.h>
25#else
26#include <jmpbuf-offsets.h>
27#endif
28
29#ifndef __NO_VMX__
30 .section ".toc","aw"
31.LC__dl_hwcap:
32# ifdef SHARED
33# if IS_IN (rtld)
34 /* Inside ld.so we use the local alias to avoid runtime GOT
35 relocations. */
36 .tc _rtld_local_ro[TC],_rtld_local_ro
37# else
38 .tc _rtld_global_ro[TC],_rtld_global_ro
39# endif
40# else
41 .tc _dl_hwcap[TC],_dl_hwcap
42# endif
43 .section ".text"
44#endif
45
46 .machine "altivec"
47ENTRY (setjmp_symbol)
48 CALL_MCOUNT 1
49 li r4,1 /* Set second argument to 1. */
50 b JUMPTARGET (GLUE(__sigsetjmp_symbol,_ent))
51END (setjmp_symbol)
52
53#if defined SHARED && !IS_IN (rtld) && !defined __NO_VMX__
54/* When called from within libc we need a special version of _setjmp
55 that saves r2 since the call won't go via a plt call stub. See
56 bugz #269. __GI__setjmp is used in csu/libc-start.c when
57 HAVE_CLEANUP_JMP_BUF is defined. */
58ENTRY (__GI__setjmp)
59 std r2,FRAME_TOC_SAVE(r1) /* Save the callers TOC in the save area. */
60 CALL_MCOUNT 1
61 li r4,0 /* Set second argument to 0. */
62 b JUMPTARGET (GLUE(__sigsetjmp_symbol,_ent))
63END (__GI__setjmp)
64#endif
65
66ENTRY (_setjmp_symbol)
67 CALL_MCOUNT 1
68 li r4,0 /* Set second argument to 0. */
69 b JUMPTARGET (GLUE(__sigsetjmp_symbol,_ent))
70END (_setjmp_symbol)
71libc_hidden_def (_setjmp_symbol)
72
73ENTRY (__sigsetjmp_symbol)
74 CALL_MCOUNT 2
75JUMPTARGET(GLUE(__sigsetjmp_symbol,_ent)):
76#ifdef PTR_MANGLE
77 mr r5, r1
78 PTR_MANGLE (r5, r6)
79 std r5,(JB_GPR1*8)(3)
80#else
81 std r1,(JB_GPR1*8)(3)
82#endif
83 mflr r0
84#if defined SHARED && !IS_IN (rtld)
85 ld r5,FRAME_TOC_SAVE(r1) /* Retrieve the callers TOC. */
86 std r5,(JB_GPR2*8)(3)
87#else
88 std r2,(JB_GPR2*8)(3)
89#endif
90 /* setjmp probe expects longjmp first argument (8@3), second argument
91 (-4@4), and target address (8@0), respectively. */
92 LIBC_PROBE (setjmp, 3, 8@3, -4@4, 8@0)
93 std r14,((JB_GPRS+0)*8)(3)
94 stfd fp14,((JB_FPRS+0)*8)(3)
95#ifdef PTR_MANGLE
96 PTR_MANGLE2 (r0, r6)
97#endif
98 std r0,(JB_LR*8)(3)
99 std r15,((JB_GPRS+1)*8)(3)
100 stfd fp15,((JB_FPRS+1)*8)(3)
101 mfcr r0
102 std r16,((JB_GPRS+2)*8)(3)
103 stfd fp16,((JB_FPRS+2)*8)(3)
104 stw r0,((JB_CR*8)+4)(3) /* 32-bit CR. */
105 std r17,((JB_GPRS+3)*8)(3)
106 stfd fp17,((JB_FPRS+3)*8)(3)
107 std r18,((JB_GPRS+4)*8)(3)
108 stfd fp18,((JB_FPRS+4)*8)(3)
109 std r19,((JB_GPRS+5)*8)(3)
110 stfd fp19,((JB_FPRS+5)*8)(3)
111 std r20,((JB_GPRS+6)*8)(3)
112 stfd fp20,((JB_FPRS+6)*8)(3)
113 std r21,((JB_GPRS+7)*8)(3)
114 stfd fp21,((JB_FPRS+7)*8)(3)
115 std r22,((JB_GPRS+8)*8)(3)
116 stfd fp22,((JB_FPRS+8)*8)(3)
117 std r23,((JB_GPRS+9)*8)(3)
118 stfd fp23,((JB_FPRS+9)*8)(3)
119 std r24,((JB_GPRS+10)*8)(3)
120 stfd fp24,((JB_FPRS+10)*8)(3)
121 std r25,((JB_GPRS+11)*8)(3)
122 stfd fp25,((JB_FPRS+11)*8)(3)
123 std r26,((JB_GPRS+12)*8)(3)
124 stfd fp26,((JB_FPRS+12)*8)(3)
125 std r27,((JB_GPRS+13)*8)(3)
126 stfd fp27,((JB_FPRS+13)*8)(3)
127 std r28,((JB_GPRS+14)*8)(3)
128 stfd fp28,((JB_FPRS+14)*8)(3)
129 std r29,((JB_GPRS+15)*8)(3)
130 stfd fp29,((JB_FPRS+15)*8)(3)
131 std r30,((JB_GPRS+16)*8)(3)
132 stfd fp30,((JB_FPRS+16)*8)(3)
133 std r31,((JB_GPRS+17)*8)(3)
134 stfd fp31,((JB_FPRS+17)*8)(3)
135#ifndef __NO_VMX__
136 addis r6,r2,.LC__dl_hwcap@toc@ha
137 ld r6,.LC__dl_hwcap@toc@l(r6)
138# ifdef SHARED
139 /* Load _rtld-global._dl_hwcap. */
140 ld r6,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET(r6)
141# else
142 /* Load extern _dl_hwcap. */
143 ld r6,0(r6)
144# endif
145 andis. r6,r6,(PPC_FEATURE_HAS_ALTIVEC >> 16)
146 beq L(no_vmx)
147 la r5,((JB_VRS)*8)(3)
148 andi. r6,r5,0xf
149 mfspr r0,VRSAVE
150 stw r0,((JB_VRSAVE)*8)(3) /* 32-bit VRSAVE. */
151 addi r6,r5,16
152 beq+ L(aligned_save_vmx)
153
154 lvsr v0,0,r5
155 lvsl v1,0,r5
156 addi r6,r5,-16
157
158# define save_misaligned_vmx(savevr,prevvr,shiftvr,tmpvr,savegpr,addgpr) \
159 addi addgpr,addgpr,32; \
160 vperm tmpvr,prevvr,savevr,shiftvr; \
161 stvx tmpvr,0,savegpr
162
163 /*
164 * We have to be careful not to corrupt the data below v20 and
165 * above v31. To keep things simple we just rotate both ends in
166 * the opposite direction to our main permute so we can use
167 * the common macro.
168 */
169
170 /* load and rotate data below v20 */
171 lvx v2,0,r5
172 vperm v2,v2,v2,v1
173 save_misaligned_vmx(v20,v2,v0,v3,r5,r6)
174 save_misaligned_vmx(v21,v20,v0,v3,r6,r5)
175 save_misaligned_vmx(v22,v21,v0,v3,r5,r6)
176 save_misaligned_vmx(v23,v22,v0,v3,r6,r5)
177 save_misaligned_vmx(v24,v23,v0,v3,r5,r6)
178 save_misaligned_vmx(v25,v24,v0,v3,r6,r5)
179 save_misaligned_vmx(v26,v25,v0,v3,r5,r6)
180 save_misaligned_vmx(v27,v26,v0,v3,r6,r5)
181 save_misaligned_vmx(v28,v27,v0,v3,r5,r6)
182 save_misaligned_vmx(v29,v28,v0,v3,r6,r5)
183 save_misaligned_vmx(v30,v29,v0,v3,r5,r6)
184 save_misaligned_vmx(v31,v30,v0,v3,r6,r5)
185 /* load and rotate data above v31 */
186 lvx v2,0,r6
187 vperm v2,v2,v2,v1
188 save_misaligned_vmx(v2,v31,v0,v3,r5,r6)
189
190 b L(no_vmx)
191
192L(aligned_save_vmx):
193 stvx 20,0,r5
194 addi r5,r5,32
195 stvx 21,0,r6
196 addi r6,r6,32
197 stvx 22,0,r5
198 addi r5,r5,32
199 stvx 23,0,r6
200 addi r6,r6,32
201 stvx 24,0,r5
202 addi r5,r5,32
203 stvx 25,0,r6
204 addi r6,r6,32
205 stvx 26,0,r5
206 addi r5,r5,32
207 stvx 27,0,r6
208 addi r6,r6,32
209 stvx 28,0,r5
210 addi r5,r5,32
211 stvx 29,0,r6
212 addi r6,r6,32
213 stvx 30,0,r5
214 stvx 31,0,r6
215L(no_vmx):
216#else
217 li r6,0
218#endif
219#if IS_IN (rtld)
220 li r3,0
221 blr
222#elif defined SHARED
223 b JUMPTARGET (NOTOC (__sigjmp_save_symbol))
224#else
225 mflr r0
226 std r0,FRAME_LR_SAVE(r1)
227 stdu r1,-FRAME_MIN_SIZE(r1)
228 cfi_adjust_cfa_offset(FRAME_MIN_SIZE)
229 cfi_offset(lr,FRAME_LR_SAVE)
230 bl JUMPTARGET (__sigjmp_save_symbol)
231 nop
232 ld r0,FRAME_MIN_SIZE+FRAME_LR_SAVE(r1)
233 addi r1,r1,FRAME_MIN_SIZE
234 mtlr r0
235 blr
236#endif
237END (__sigsetjmp_symbol)
238
239#if defined SHARED && !IS_IN (rtld) && !defined __NO_VMX__
240/* When called from within libc we need a special version of __sigsetjmp
241 that saves r2 since the call won't go via a plt call stub. See
242 bugz #269. */
243ENTRY (__GI___sigsetjmp)
244 std r2,FRAME_TOC_SAVE(r1) /* Save the callers TOC in the save area. */
245 CALL_MCOUNT 1
246 b JUMPTARGET (GLUE(__sigsetjmp_symbol,_ent))
247END (__GI___sigsetjmp)
248#endif
249

source code of glibc/sysdeps/powerpc/powerpc64/setjmp-common.S