1/* longjmp for PowerPC64.
2   Copyright (C) 1995-2021 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#define _SETJMP_H
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 (__longjmp)
48	CALL_MCOUNT 2
49#ifndef __NO_VMX__
50	ld    r5,.LC__dl_hwcap@toc(r2)
51# ifdef SHARED
52	/* Load _rtld-global._dl_hwcap.  */
53	ld    r5,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET(r5)
54# else
55	ld    r5,0(r5) /* Load extern _dl_hwcap.  */
56# endif
57	andis.  r5,r5,(PPC_FEATURE_HAS_ALTIVEC >> 16)
58	beq	L(no_vmx)
59	la	r5,((JB_VRS)*8)(3)
60	andi.	r6,r5,0xf
61	lwz	r0,((JB_VRSAVE)*8)(3)	/* 32-bit VRSAVE.  */
62	mtspr	VRSAVE,r0
63	beq+	L(aligned_restore_vmx)
64	addi    r6,r5,16
65	lvsl	v0,0,r5
66	lvx	v1,0,r5
67	addi    r5,r5,32
68	lvx	v21,0,r6
69	vperm   v20,v1,v21,v0
70# define load_misaligned_vmx_lo_loaded(loadvr,lovr,shiftvr,loadgpr,addgpr) \
71	addi    addgpr,addgpr,32; \
72	lvx	lovr,0,loadgpr; \
73	vperm   loadvr,loadvr,lovr,shiftvr;
74	load_misaligned_vmx_lo_loaded(v21,v22,v0,r5,r6)
75	load_misaligned_vmx_lo_loaded(v22,v23,v0,r6,r5)
76	load_misaligned_vmx_lo_loaded(v23,v24,v0,r5,r6)
77	load_misaligned_vmx_lo_loaded(v24,v25,v0,r6,r5)
78	load_misaligned_vmx_lo_loaded(v25,v26,v0,r5,r6)
79	load_misaligned_vmx_lo_loaded(v26,v27,v0,r6,r5)
80	load_misaligned_vmx_lo_loaded(v27,v28,v0,r5,r6)
81	load_misaligned_vmx_lo_loaded(v28,v29,v0,r6,r5)
82	load_misaligned_vmx_lo_loaded(v29,v30,v0,r5,r6)
83	load_misaligned_vmx_lo_loaded(v30,v31,v0,r6,r5)
84	lvx	v1,0,r5
85	vperm   v31,v31,v1,v0
86	b       L(no_vmx)
87L(aligned_restore_vmx):
88	addi	r6,r5,16
89	lvx	v20,0,r5
90	addi	r5,r5,32
91	lvx	v21,0,r6
92	addi	r6,r6,32
93	lvx	v22,0,r5
94	addi	r5,r5,32
95	lvx	v23,0,r6
96	addi	r6,r6,32
97	lvx	v24,0,r5
98	addi	r5,r5,32
99	lvx	v25,0,r6
100	addi	r6,r6,32
101	lvx	v26,0,r5
102	addi	r5,r5,32
103	lvx	v27,0,r6
104	addi	r6,r6,32
105	lvx	v28,0,r5
106	addi	r5,r5,32
107	lvx	v29,0,r6
108	addi	r6,r6,32
109	lvx	v30,0,r5
110	lvx	v31,0,r6
111L(no_vmx):
112#endif
113#if defined PTR_DEMANGLE || defined CHECK_SP
114	ld r22,(JB_GPR1*8)(r3)
115#else
116	ld r1,(JB_GPR1*8)(r3)
117#endif
118#ifdef PTR_DEMANGLE
119# ifdef CHECK_SP
120	PTR_DEMANGLE3 (r22, r22, r25)
121# else
122	PTR_DEMANGLE3 (r1, r22, r25)
123# endif
124#endif
125#ifdef CHECK_SP
126	CHECK_SP (r22)
127	mr r1,r22
128#endif
129	ld r2,(JB_GPR2*8)(r3)
130	ld r0,(JB_LR*8)(r3)
131	ld r14,((JB_GPRS+0)*8)(r3)
132	lfd fp14,((JB_FPRS+0)*8)(r3)
133	ld r15,((JB_GPRS+1)*8)(r3)
134	lfd fp15,((JB_FPRS+1)*8)(r3)
135	ld r16,((JB_GPRS+2)*8)(r3)
136	lfd fp16,((JB_FPRS+2)*8)(r3)
137	ld r17,((JB_GPRS+3)*8)(r3)
138	lfd fp17,((JB_FPRS+3)*8)(r3)
139	ld r18,((JB_GPRS+4)*8)(r3)
140	lfd fp18,((JB_FPRS+4)*8)(r3)
141	ld r19,((JB_GPRS+5)*8)(r3)
142	lfd fp19,((JB_FPRS+5)*8)(r3)
143	ld r20,((JB_GPRS+6)*8)(r3)
144	lfd fp20,((JB_FPRS+6)*8)(r3)
145#ifdef PTR_DEMANGLE
146	PTR_DEMANGLE2 (r0, r25)
147#endif
148     /* longjmp/longjmp_target probe expects longjmp first argument (8@3),
149	second argument (-4@4), and target address (8@0), respectively.  */
150	LIBC_PROBE (longjmp, 3, 8@3, -4@4, 8@0)
151	mtlr r0
152	std r2,FRAME_TOC_SAVE(r1)	/* Restore the TOC save area.  */
153	ld r21,((JB_GPRS+7)*8)(r3)
154	lfd fp21,((JB_FPRS+7)*8)(r3)
155	ld r22,((JB_GPRS+8)*8)(r3)
156	lfd fp22,((JB_FPRS+8)*8)(r3)
157	lwz r5,((JB_CR*8)+4)(r3)	/* 32-bit CR.  */
158	ld r23,((JB_GPRS+9)*8)(r3)
159	lfd fp23,((JB_FPRS+9)*8)(r3)
160	ld r24,((JB_GPRS+10)*8)(r3)
161	lfd fp24,((JB_FPRS+10)*8)(r3)
162	ld r25,((JB_GPRS+11)*8)(r3)
163	lfd fp25,((JB_FPRS+11)*8)(r3)
164	mtcrf 0xFF,r5
165	ld r26,((JB_GPRS+12)*8)(r3)
166	lfd fp26,((JB_FPRS+12)*8)(r3)
167	ld r27,((JB_GPRS+13)*8)(r3)
168	lfd fp27,((JB_FPRS+13)*8)(r3)
169	ld r28,((JB_GPRS+14)*8)(r3)
170	lfd fp28,((JB_FPRS+14)*8)(r3)
171	ld r29,((JB_GPRS+15)*8)(r3)
172	lfd fp29,((JB_FPRS+15)*8)(r3)
173	ld r30,((JB_GPRS+16)*8)(r3)
174	lfd fp30,((JB_FPRS+16)*8)(r3)
175	ld r31,((JB_GPRS+17)*8)(r3)
176	lfd fp31,((JB_FPRS+17)*8)(r3)
177	LIBC_PROBE (longjmp_target, 3, 8@3, -4@4, 8@0)
178	mr r3,r4
179	blr
180END (__longjmp)
181