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