1/* longjmp for PowerPC.
2   Copyright (C) 1995-2022 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 <stap-probe.h>
21#define _ASM
22#ifdef __NO_VMX__
23# include <novmxsetjmp.h>
24#else
25# include <jmpbuf-offsets.h>
26#endif
27
28	.machine	"altivec"
29ENTRY (__longjmp_symbol)
30#ifndef __NO_VMX__
31# ifdef PIC
32	mflr    r6
33	cfi_register (lr,r6)
34	SETUP_GOT_ACCESS(r5,got_label)
35	addis	r5,r5,_GLOBAL_OFFSET_TABLE_-got_label@ha
36	addi	r5,r5,_GLOBAL_OFFSET_TABLE_-got_label@l
37#  ifdef SHARED
38#   if IS_IN (rtld)
39	/* Inside ld.so we use the local alias to avoid runtime GOT
40	   relocations.  */
41	lwz     r5,_rtld_local_ro@got(r5)
42#   else
43	lwz     r5,_rtld_global_ro@got(r5)
44#   endif
45	mtlr    r6
46	cfi_same_value (lr)
47	lwz     r5,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET+LOWORD(r5)
48#  else
49	lwz     r5,_dl_hwcap@got(r5)
50	mtlr    r6
51	cfi_same_value (lr)
52	lwz     r5,LOWORD(r5)
53#  endif
54# else
55	lis	r5,(_dl_hwcap+LOWORD)@ha
56	lwz     r5,(_dl_hwcap+LOWORD)@l(r5)
57# endif
58	andis.	r5,r5,(PPC_FEATURE_HAS_ALTIVEC >> 16)
59	beq	L(no_vmx)
60	la	r5,((JB_VRS)*4)(3)
61	andi.	r6,r5,0xf
62	lwz	r0,((JB_VRSAVE)*4)(3)
63	mtspr	VRSAVE,r0
64	beq+	L(aligned_restore_vmx)
65	addi    r6,r5,16
66	lvsl	v0,0,r5
67	lvx	v1,0,r5
68	addi    r5,r5,32
69	lvx	v21,0,r6
70	vperm   v20,v1,v21,v0
71# define load_misaligned_vmx_lo_loaded(loadvr,lovr,shiftvr,loadgpr,addgpr) \
72	addi    addgpr,addgpr,32; \
73	lvx	lovr,0,loadgpr; \
74	vperm   loadvr,loadvr,lovr,shiftvr;
75	load_misaligned_vmx_lo_loaded(v21,v22,v0,r5,r6)
76	load_misaligned_vmx_lo_loaded(v22,v23,v0,r6,r5)
77	load_misaligned_vmx_lo_loaded(v23,v24,v0,r5,r6)
78	load_misaligned_vmx_lo_loaded(v24,v25,v0,r6,r5)
79	load_misaligned_vmx_lo_loaded(v25,v26,v0,r5,r6)
80	load_misaligned_vmx_lo_loaded(v26,v27,v0,r6,r5)
81	load_misaligned_vmx_lo_loaded(v27,v28,v0,r5,r6)
82	load_misaligned_vmx_lo_loaded(v28,v29,v0,r6,r5)
83	load_misaligned_vmx_lo_loaded(v29,v30,v0,r5,r6)
84	load_misaligned_vmx_lo_loaded(v30,v31,v0,r6,r5)
85	lvx	v1,0,r5
86	vperm   v31,v31,v1,v0
87	b       L(no_vmx)
88L(aligned_restore_vmx):
89	addi	r6,r5,16
90	lvx	v20,0,r5
91	addi	r5,r5,32
92	lvx	v21,0,r6
93	addi	r6,r6,32
94	lvx	v22,0,r5
95	addi	r5,r5,32
96	lvx	v23,0,r6
97	addi	r6,r6,32
98	lvx	v24,0,r5
99	addi	r5,r5,32
100	lvx	v25,0,r6
101	addi	r6,r6,32
102	lvx	v26,0,r5
103	addi	r5,r5,32
104	lvx	v27,0,r6
105	addi	r6,r6,32
106	lvx	v28,0,r5
107	addi	r5,r5,32
108	lvx	v29,0,r6
109	addi	r6,r6,32
110	lvx	v30,0,r5
111	lvx	v31,0,r6
112L(no_vmx):
113#endif
114#if defined PTR_DEMANGLE || defined CHECK_SP
115	lwz r24,(JB_GPR1*4)(r3)
116# ifdef CHECK_SP
117#  ifdef PTR_DEMANGLE
118	PTR_DEMANGLE3 (r24, r24, r25)
119#  endif
120	CHECK_SP (r24)
121	mr r1,r24
122# endif
123#else
124	lwz r1,(JB_GPR1*4)(r3)
125#endif
126	lwz r0,(JB_LR*4)(r3)
127	lwz r14,((JB_GPRS+0)*4)(r3)
128	lfd fp14,((JB_FPRS+0*2)*4)(r3)
129	lwz r15,((JB_GPRS+1)*4)(r3)
130	lfd fp15,((JB_FPRS+1*2)*4)(r3)
131	lwz r16,((JB_GPRS+2)*4)(r3)
132	lfd fp16,((JB_FPRS+2*2)*4)(r3)
133	lwz r17,((JB_GPRS+3)*4)(r3)
134	lfd fp17,((JB_FPRS+3*2)*4)(r3)
135	lwz r18,((JB_GPRS+4)*4)(r3)
136	lfd fp18,((JB_FPRS+4*2)*4)(r3)
137	lwz r19,((JB_GPRS+5)*4)(r3)
138	lfd fp19,((JB_FPRS+5*2)*4)(r3)
139	lwz r20,((JB_GPRS+6)*4)(r3)
140	lfd fp20,((JB_FPRS+6*2)*4)(r3)
141#ifdef PTR_DEMANGLE
142# ifndef CHECK_SP
143	PTR_DEMANGLE3 (r1, r24, r25)
144# endif
145	PTR_DEMANGLE2 (r0, r25)
146#endif
147	/* longjmp/longjmp_target probe expects longjmp first argument (4@3),
148	   second argument (-4@4), and target address (4@0), respectively.  */
149	LIBC_PROBE (longjmp, 3, 4@3, -4@4, 4@0)
150	mtlr r0
151	lwz r21,((JB_GPRS+7)*4)(r3)
152	lfd fp21,((JB_FPRS+7*2)*4)(r3)
153	lwz r22,((JB_GPRS+8)*4)(r3)
154	lfd fp22,((JB_FPRS+8*2)*4)(r3)
155	lwz r5,(JB_CR*4)(r3)
156	lwz r23,((JB_GPRS+9)*4)(r3)
157	lfd fp23,((JB_FPRS+9*2)*4)(r3)
158	lwz r24,((JB_GPRS+10)*4)(r3)
159	lfd fp24,((JB_FPRS+10*2)*4)(r3)
160	lwz r25,((JB_GPRS+11)*4)(r3)
161	lfd fp25,((JB_FPRS+11*2)*4)(r3)
162	mtcrf 0xFF,r5
163	lwz r26,((JB_GPRS+12)*4)(r3)
164	lfd fp26,((JB_FPRS+12*2)*4)(r3)
165	lwz r27,((JB_GPRS+13)*4)(r3)
166	lfd fp27,((JB_FPRS+13*2)*4)(r3)
167	lwz r28,((JB_GPRS+14)*4)(r3)
168	lfd fp28,((JB_FPRS+14*2)*4)(r3)
169	lwz r29,((JB_GPRS+15)*4)(r3)
170	lfd fp29,((JB_FPRS+15*2)*4)(r3)
171	lwz r30,((JB_GPRS+16)*4)(r3)
172	lfd fp30,((JB_FPRS+16*2)*4)(r3)
173	lwz r31,((JB_GPRS+17)*4)(r3)
174	lfd fp31,((JB_FPRS+17*2)*4)(r3)
175	LIBC_PROBE (longjmp_target, 3, 4@3, -4@4, 4@0)
176	mr r3,r4
177	blr
178END (__longjmp_symbol)
179