Blame sysdeps/powerpc/powerpc64/setjmp-common.S

Packit 6c4009
/* setjmp for PowerPC64.
Packit 6c4009
   Copyright (C) 1995-2018 Free Software Foundation, Inc.
Packit 6c4009
   This file is part of the GNU C Library.
Packit 6c4009
Packit 6c4009
   The GNU C Library is free software; you can redistribute it and/or
Packit 6c4009
   modify it under the terms of the GNU Lesser General Public
Packit 6c4009
   License as published by the Free Software Foundation; either
Packit 6c4009
   version 2.1 of the License, or (at your option) any later version.
Packit 6c4009
Packit 6c4009
   The GNU C Library is distributed in the hope that it will be useful,
Packit 6c4009
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6c4009
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6c4009
   Lesser General Public License for more details.
Packit 6c4009
Packit 6c4009
   You should have received a copy of the GNU Lesser General Public
Packit 6c4009
   License along with the GNU C Library; if not, see
Packit 6c4009
   <http://www.gnu.org/licenses/>.  */
Packit 6c4009
Packit 6c4009
#include <sysdep.h>
Packit 6c4009
#include <stap-probe.h>
Packit 6c4009
#define _ASM
Packit 6c4009
#ifdef __NO_VMX__
Packit 6c4009
#include <novmxsetjmp.h>
Packit 6c4009
#else
Packit 6c4009
#include <jmpbuf-offsets.h>
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
#ifndef __NO_VMX__
Packit 6c4009
	.section	".toc","aw"
Packit 6c4009
.LC__dl_hwcap:
Packit 6c4009
# ifdef SHARED
Packit 6c4009
#  if IS_IN (rtld)
Packit 6c4009
	/* Inside ld.so we use the local alias to avoid runtime GOT
Packit 6c4009
	   relocations.  */
Packit 6c4009
	.tc _rtld_local_ro[TC],_rtld_local_ro
Packit 6c4009
#  else
Packit 6c4009
	.tc _rtld_global_ro[TC],_rtld_global_ro
Packit 6c4009
#  endif
Packit 6c4009
# else
Packit 6c4009
	.tc _dl_hwcap[TC],_dl_hwcap
Packit 6c4009
# endif
Packit 6c4009
	.section ".text"
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
	.machine	"altivec"
Packit 6c4009
ENTRY (setjmp_symbol)
Packit 6c4009
	CALL_MCOUNT 1
Packit 6c4009
	li r4,1			/* Set second argument to 1.  */
Packit 6c4009
	b JUMPTARGET (GLUE(__sigsetjmp_symbol,_ent))
Packit 6c4009
END (setjmp_symbol)
Packit 6c4009
Packit 6c4009
#if defined SHARED && !IS_IN (rtld) && !defined __NO_VMX__
Packit 6c4009
/* When called from within libc we need a special version of _setjmp
Packit 6c4009
   that saves r2 since the call won't go via a plt call stub.  See
Packit 6c4009
   bugz #269.  __GI__setjmp is used in csu/libc-start.c when
Packit 6c4009
   HAVE_CLEANUP_JMP_BUF is defined.  */
Packit 6c4009
ENTRY (__GI__setjmp)
Packit 6c4009
	std r2,FRAME_TOC_SAVE(r1)		/* Save the callers TOC in the save area.  */
Packit 6c4009
	CALL_MCOUNT 1
Packit 6c4009
	li r4,0			/* Set second argument to 0.  */
Packit 6c4009
	b JUMPTARGET (GLUE(__sigsetjmp_symbol,_ent))
Packit 6c4009
END (__GI__setjmp)
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
ENTRY (_setjmp_symbol)
Packit 6c4009
	CALL_MCOUNT 1
Packit 6c4009
	li r4,0			/* Set second argument to 0.  */
Packit 6c4009
	b JUMPTARGET (GLUE(__sigsetjmp_symbol,_ent))
Packit 6c4009
END (_setjmp_symbol)
Packit 6c4009
libc_hidden_def (_setjmp_symbol)
Packit 6c4009
Packit 6c4009
ENTRY (__sigsetjmp_symbol)
Packit 6c4009
	CALL_MCOUNT 2
Packit 6c4009
JUMPTARGET(GLUE(__sigsetjmp_symbol,_ent)):
Packit 6c4009
#ifdef PTR_MANGLE
Packit 6c4009
	mr   r5, r1
Packit 6c4009
	PTR_MANGLE (r5, r6)
Packit 6c4009
	std  r5,(JB_GPR1*8)(3)
Packit 6c4009
#else
Packit 6c4009
	std  r1,(JB_GPR1*8)(3)
Packit 6c4009
#endif
Packit 6c4009
	mflr r0
Packit 6c4009
#if defined SHARED && !IS_IN (rtld)
Packit 6c4009
	ld   r5,FRAME_TOC_SAVE(r1)	/* Retrieve the callers TOC.  */
Packit 6c4009
	std  r5,(JB_GPR2*8)(3)
Packit 6c4009
#else
Packit 6c4009
	std  r2,(JB_GPR2*8)(3)
Packit 6c4009
#endif
Packit 6c4009
	/* setjmp probe expects longjmp first argument (8@3), second argument
Packit 6c4009
	   (-4@4), and target address (8@0), respectively.  */
Packit 6c4009
	LIBC_PROBE (setjmp, 3, 8@3, -4@4, 8@0)
Packit 6c4009
	std  r14,((JB_GPRS+0)*8)(3)
Packit 6c4009
	stfd fp14,((JB_FPRS+0)*8)(3)
Packit 6c4009
#ifdef PTR_MANGLE
Packit 6c4009
	PTR_MANGLE2 (r0, r6)
Packit 6c4009
#endif
Packit 6c4009
	std  r0,(JB_LR*8)(3)
Packit 6c4009
	std  r15,((JB_GPRS+1)*8)(3)
Packit 6c4009
	stfd fp15,((JB_FPRS+1)*8)(3)
Packit 6c4009
	mfcr r0
Packit 6c4009
	std  r16,((JB_GPRS+2)*8)(3)
Packit 6c4009
	stfd fp16,((JB_FPRS+2)*8)(3)
Packit 6c4009
	stw  r0,((JB_CR*8)+4)(3)	/* 32-bit CR.  */
Packit 6c4009
	std  r17,((JB_GPRS+3)*8)(3)
Packit 6c4009
	stfd fp17,((JB_FPRS+3)*8)(3)
Packit 6c4009
	std  r18,((JB_GPRS+4)*8)(3)
Packit 6c4009
	stfd fp18,((JB_FPRS+4)*8)(3)
Packit 6c4009
	std  r19,((JB_GPRS+5)*8)(3)
Packit 6c4009
	stfd fp19,((JB_FPRS+5)*8)(3)
Packit 6c4009
	std  r20,((JB_GPRS+6)*8)(3)
Packit 6c4009
	stfd fp20,((JB_FPRS+6)*8)(3)
Packit 6c4009
	std  r21,((JB_GPRS+7)*8)(3)
Packit 6c4009
	stfd fp21,((JB_FPRS+7)*8)(3)
Packit 6c4009
	std  r22,((JB_GPRS+8)*8)(3)
Packit 6c4009
	stfd fp22,((JB_FPRS+8)*8)(3)
Packit 6c4009
	std  r23,((JB_GPRS+9)*8)(3)
Packit 6c4009
	stfd fp23,((JB_FPRS+9)*8)(3)
Packit 6c4009
	std  r24,((JB_GPRS+10)*8)(3)
Packit 6c4009
	stfd fp24,((JB_FPRS+10)*8)(3)
Packit 6c4009
	std  r25,((JB_GPRS+11)*8)(3)
Packit 6c4009
	stfd fp25,((JB_FPRS+11)*8)(3)
Packit 6c4009
	std  r26,((JB_GPRS+12)*8)(3)
Packit 6c4009
	stfd fp26,((JB_FPRS+12)*8)(3)
Packit 6c4009
	std  r27,((JB_GPRS+13)*8)(3)
Packit 6c4009
	stfd fp27,((JB_FPRS+13)*8)(3)
Packit 6c4009
	std  r28,((JB_GPRS+14)*8)(3)
Packit 6c4009
	stfd fp28,((JB_FPRS+14)*8)(3)
Packit 6c4009
	std  r29,((JB_GPRS+15)*8)(3)
Packit 6c4009
	stfd fp29,((JB_FPRS+15)*8)(3)
Packit 6c4009
	std  r30,((JB_GPRS+16)*8)(3)
Packit 6c4009
	stfd fp30,((JB_FPRS+16)*8)(3)
Packit 6c4009
	std  r31,((JB_GPRS+17)*8)(3)
Packit 6c4009
	stfd fp31,((JB_FPRS+17)*8)(3)
Packit 6c4009
#ifndef __NO_VMX__
Packit 6c4009
	ld    r6,.LC__dl_hwcap@toc(r2)
Packit 6c4009
# ifdef SHARED
Packit 6c4009
	/* Load _rtld-global._dl_hwcap.  */
Packit 6c4009
	ld    r6,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET(r6)
Packit 6c4009
# else
Packit 6c4009
	ld    r6,0(r6) /* Load extern _dl_hwcap.  */
Packit 6c4009
# endif
Packit 6c4009
	andis.  r6,r6,(PPC_FEATURE_HAS_ALTIVEC >> 16)
Packit 6c4009
	beq	L(no_vmx)
Packit 6c4009
	la	r5,((JB_VRS)*8)(3)
Packit 6c4009
	andi.	r6,r5,0xf
Packit 6c4009
	mfspr	r0,VRSAVE
Packit 6c4009
	stw	r0,((JB_VRSAVE)*8)(3)	/* 32-bit VRSAVE.  */
Packit 6c4009
	addi	r6,r5,16
Packit 6c4009
	beq+	L(aligned_save_vmx)
Packit 6c4009
Packit 6c4009
	lvsr	v0,0,r5
Packit 6c4009
	lvsl	v1,0,r5
Packit 6c4009
	addi	r6,r5,-16
Packit 6c4009
Packit 6c4009
# define save_misaligned_vmx(savevr,prevvr,shiftvr,tmpvr,savegpr,addgpr) \
Packit 6c4009
	addi	addgpr,addgpr,32;					 \
Packit 6c4009
	vperm	tmpvr,prevvr,savevr,shiftvr;				 \
Packit 6c4009
	stvx	tmpvr,0,savegpr
Packit 6c4009
Packit 6c4009
	/*
Packit 6c4009
	 * We have to be careful not to corrupt the data below v20 and
Packit 6c4009
	 * above v31. To keep things simple we just rotate both ends in
Packit 6c4009
	 * the opposite direction to our main permute so we can use
Packit 6c4009
	 * the common macro.
Packit 6c4009
	 */
Packit 6c4009
Packit 6c4009
	/* load and rotate data below v20 */
Packit 6c4009
	lvx	v2,0,r5
Packit 6c4009
	vperm	v2,v2,v2,v1
Packit 6c4009
	save_misaligned_vmx(v20,v2,v0,v3,r5,r6)
Packit 6c4009
	save_misaligned_vmx(v21,v20,v0,v3,r6,r5)
Packit 6c4009
	save_misaligned_vmx(v22,v21,v0,v3,r5,r6)
Packit 6c4009
	save_misaligned_vmx(v23,v22,v0,v3,r6,r5)
Packit 6c4009
	save_misaligned_vmx(v24,v23,v0,v3,r5,r6)
Packit 6c4009
	save_misaligned_vmx(v25,v24,v0,v3,r6,r5)
Packit 6c4009
	save_misaligned_vmx(v26,v25,v0,v3,r5,r6)
Packit 6c4009
	save_misaligned_vmx(v27,v26,v0,v3,r6,r5)
Packit 6c4009
	save_misaligned_vmx(v28,v27,v0,v3,r5,r6)
Packit 6c4009
	save_misaligned_vmx(v29,v28,v0,v3,r6,r5)
Packit 6c4009
	save_misaligned_vmx(v30,v29,v0,v3,r5,r6)
Packit 6c4009
	save_misaligned_vmx(v31,v30,v0,v3,r6,r5)
Packit 6c4009
	/* load and rotate data above v31 */
Packit 6c4009
	lvx	v2,0,r6
Packit 6c4009
	vperm	v2,v2,v2,v1
Packit 6c4009
	save_misaligned_vmx(v2,v31,v0,v3,r5,r6)
Packit 6c4009
Packit 6c4009
	b	L(no_vmx)
Packit 6c4009
Packit 6c4009
L(aligned_save_vmx):
Packit 6c4009
	stvx	20,0,r5
Packit 6c4009
	addi	r5,r5,32
Packit 6c4009
	stvx	21,0,r6
Packit 6c4009
	addi	r6,r6,32
Packit 6c4009
	stvx	22,0,r5
Packit 6c4009
	addi	r5,r5,32
Packit 6c4009
	stvx	23,0,r6
Packit 6c4009
	addi	r6,r6,32
Packit 6c4009
	stvx	24,0,r5
Packit 6c4009
	addi	r5,r5,32
Packit 6c4009
	stvx	25,0,r6
Packit 6c4009
	addi	r6,r6,32
Packit 6c4009
	stvx	26,0,r5
Packit 6c4009
	addi	r5,r5,32
Packit 6c4009
	stvx	27,0,r6
Packit 6c4009
	addi	r6,r6,32
Packit 6c4009
	stvx	28,0,r5
Packit 6c4009
	addi	r5,r5,32
Packit 6c4009
	stvx	29,0,r6
Packit 6c4009
	addi	r6,r6,32
Packit 6c4009
	stvx	30,0,r5
Packit 6c4009
	stvx	31,0,r6
Packit 6c4009
L(no_vmx):
Packit 6c4009
#else
Packit 6c4009
	li	r6,0
Packit 6c4009
#endif
Packit 6c4009
#if IS_IN (rtld)
Packit 6c4009
	li	r3,0
Packit 6c4009
	blr
Packit 6c4009
#elif defined SHARED
Packit 6c4009
	b	JUMPTARGET (__sigjmp_save_symbol)
Packit 6c4009
#else
Packit 6c4009
	mflr	r0
Packit 6c4009
	std	r0,FRAME_LR_SAVE(r1)
Packit 6c4009
	stdu	r1,-FRAME_MIN_SIZE(r1)
Packit 6c4009
	cfi_adjust_cfa_offset(FRAME_MIN_SIZE)
Packit 6c4009
	cfi_offset(lr,FRAME_LR_SAVE)
Packit 6c4009
	bl	JUMPTARGET (__sigjmp_save_symbol)
Packit 6c4009
	nop
Packit 6c4009
	ld	r0,FRAME_MIN_SIZE+FRAME_LR_SAVE(r1)
Packit 6c4009
	addi	r1,r1,FRAME_MIN_SIZE
Packit 6c4009
	mtlr	r0
Packit 6c4009
	blr
Packit 6c4009
#endif
Packit 6c4009
END (__sigsetjmp_symbol)
Packit 6c4009
Packit 6c4009
#if defined SHARED && !IS_IN (rtld) && !defined __NO_VMX__
Packit 6c4009
/* When called from within libc we need a special version of __sigsetjmp
Packit 6c4009
   that saves r2 since the call won't go via a plt call stub.  See
Packit 6c4009
   bugz #269.  */
Packit 6c4009
ENTRY (__GI___sigsetjmp)
Packit 6c4009
	std r2,FRAME_TOC_SAVE(r1) /* Save the callers TOC in the save area.  */
Packit 6c4009
	CALL_MCOUNT 1
Packit 6c4009
	b JUMPTARGET (GLUE(__sigsetjmp_symbol,_ent))
Packit 6c4009
END (__GI___sigsetjmp)
Packit 6c4009
#endif