/* Save current context and install the given one.
- Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2002-2019 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 USA. */
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
#include <sysdep.h>
#include <rtld-global-offsets.h>
#include <shlib-compat.h>
-#include "kernel-features.h"
#define __ASSEMBLY__
#include <asm/ptrace.h>
#include "ucontext_i.h"
#include <asm/errno.h>
+ .section ".toc","aw"
+.LC__dl_hwcap:
+#ifdef SHARED
+ .tc _rtld_global_ro[TC],_rtld_global_ro
+#else
+ .tc _dl_hwcap[TC],_dl_hwcap
+#endif
+
#if SHLIB_COMPAT (libc, GLIBC_2_3, GLIBC_2_3_4)
+ .section ".text"
ENTRY(__novec_swapcontext)
-#ifdef __ASSUME_NEW_RT_SIGRETURN_SYSCALL
+ CALL_MCOUNT 2
std r0,(SIGCONTEXT_GP_REGS+(PT_R0*8))(r3)
std r1,(SIGCONTEXT_GP_REGS+(PT_R1*8))(r3)
mflr r0
std r31,-8(1)
+ cfi_offset(r31,-8)
std r2,(SIGCONTEXT_GP_REGS+(PT_R2*8))(r3)
std r0,FRAME_LR_SAVE(r1)
+ cfi_offset (lr, FRAME_LR_SAVE)
std r0,(SIGCONTEXT_GP_REGS+(PT_LNK*8))(r3)
std r0,(SIGCONTEXT_GP_REGS+(PT_NIP*8))(r3)
stdu r1,-128(r1)
+ cfi_adjust_cfa_offset (128)
std r4,(SIGCONTEXT_GP_REGS+(PT_R4*8))(r3)
std r5,(SIGCONTEXT_GP_REGS+(PT_R5*8))(r3)
std r6,(SIGCONTEXT_GP_REGS+(PT_R6*8))(r3)
stfd fp26,(SIGCONTEXT_FP_REGS+(PT_R26*8))(r3)
stfd fp27,(SIGCONTEXT_FP_REGS+(PT_R27*8))(r3)
stfd fp28,(SIGCONTEXT_FP_REGS+(PT_R28*8))(r3)
- stfd fp29,(SIGCONTEXT_GP_REGS+(PT_R29*8))(r3)
+ stfd fp29,(SIGCONTEXT_FP_REGS+(PT_R29*8))(r3)
mffs fp0
stfd fp30,(SIGCONTEXT_FP_REGS+(PT_R30*8))(r3)
stfd fp31,(SIGCONTEXT_FP_REGS+(PT_R31*8))(r3)
* of a procedure call (makecontext), so we don't need to restore
* msr and ctr. We don't restore r13 since it will be used as
* the TLS pointer. */
- lwz r0,(SIGCONTEXT_GP_REGS+(PT_MSR*8))(r31)
+ ld r0,(SIGCONTEXT_GP_REGS+(PT_MSR*8))(r31)
cmpdi r0,0
bne L(nv_do_sigret)
+ ld r8,.LC__dl_hwcap@toc(r2)
+# ifdef SHARED
+/* Load _rtld-global._dl_hwcap. */
+ ld r8,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET(r8)
+# else
+ ld r8,0(r8) /* Load extern _dl_hwcap. */
+# endif
+
lfd fp0,(SIGCONTEXT_FP_REGS+(32*8))(r31)
lfd fp31,(SIGCONTEXT_FP_REGS+(PT_R31*8))(r31)
lfd fp30,(SIGCONTEXT_FP_REGS+(PT_R30*8))(r31)
+
+# ifdef _ARCH_PWR6
+ /* Use the extended four-operand version of the mtfsf insn. */
+ .machine push
+ .machine "power6"
+
+ mtfsf 0xff,fp0,1,0
+
+ .machine pop
+# else
+ /* Availability of DFP indicates a 64-bit FPSCR. */
+ andi. r6,r8,PPC_FEATURE_HAS_DFP
+ beq 5f
+
+ .machine push
+ .machine "power6"
+
+ mtfsf 0xff,fp0,1,0
+
+ .machine pop
+
+ b 6f
+ /* Continue to operate on the FPSCR as if it were 32-bits. */
+5:
mtfsf 0xff,fp0
+6:
+#endif /* _ARCH_PWR6 */
+
lfd fp29,(SIGCONTEXT_FP_REGS+(PT_R29*8))(r31)
lfd fp28,(SIGCONTEXT_FP_REGS+(PT_R28*8))(r31)
lfd fp27,(SIGCONTEXT_FP_REGS+(PT_R27*8))(r31)
ld r4,(SIGCONTEXT_GP_REGS+(PT_R4*8))(r31)
ld r0,(SIGCONTEXT_GP_REGS+(PT_CCR*8))(r31)
ld r5,(SIGCONTEXT_GP_REGS+(PT_R5*8))(r31)
- mfcr r0
+ mtcr r0
ld r6,(SIGCONTEXT_GP_REGS+(PT_R6*8))(r31)
ld r7,(SIGCONTEXT_GP_REGS+(PT_R7*8))(r31)
ld r8,(SIGCONTEXT_GP_REGS+(PT_R8*8))(r31)
li r0,SYS_ify(rt_sigreturn)
sc
/* No return. */
-#else
- /* If the kernel is not at least 2.4.21 then generate a ENOSYS stub. */
- mflr r0
- std r0,FRAME_LR_SAVE(r1)
- stdu r1,-128(r1)
- li r3,ENOSYS
- bl JUMPTARGET(__syscall_error)
- nop
- li r3,-1
- ld r0,128+FRAME_LR_SAVE(r1)
- addi r1,r1,128
- mtlr r0
- blr
-#endif
PSEUDO_END(__novec_swapcontext)
#endif
- .section ".toc","aw"
-.LC__dl_hwcap:
-#ifdef SHARED
- .tc _rtld_global_ro[TC],_rtld_global_ro
-#else
- .tc _dl_hwcap[TC],_dl_hwcap
-#endif
.section ".text"
-
+ .machine "altivec"
ENTRY(__swapcontext)
-#ifdef __ASSUME_NEW_RT_SIGRETURN_SYSCALL
+ CALL_MCOUNT 2
std r0,(SIGCONTEXT_GP_REGS+(PT_R0*8))(r3)
std r1,(SIGCONTEXT_GP_REGS+(PT_R1*8))(r3)
mflr r0
std r31,-8(1)
+ cfi_offset(r31,-8)
std r2,(SIGCONTEXT_GP_REGS+(PT_R2*8))(r3)
std r0,FRAME_LR_SAVE(r1)
+ cfi_offset (lr, FRAME_LR_SAVE)
std r0,(SIGCONTEXT_GP_REGS+(PT_LNK*8))(r3)
std r0,(SIGCONTEXT_GP_REGS+(PT_NIP*8))(r3)
stdu r1,-128(r1)
+ cfi_adjust_cfa_offset(128)
std r4,(SIGCONTEXT_GP_REGS+(PT_R4*8))(r3)
std r5,(SIGCONTEXT_GP_REGS+(PT_R5*8))(r3)
std r6,(SIGCONTEXT_GP_REGS+(PT_R6*8))(r3)
stfd fp26,(SIGCONTEXT_FP_REGS+(PT_R26*8))(r3)
stfd fp27,(SIGCONTEXT_FP_REGS+(PT_R27*8))(r3)
stfd fp28,(SIGCONTEXT_FP_REGS+(PT_R28*8))(r3)
- stfd fp29,(SIGCONTEXT_GP_REGS+(PT_R29*8))(r3)
+ stfd fp29,(SIGCONTEXT_FP_REGS+(PT_R29*8))(r3)
mffs fp0
stfd fp30,(SIGCONTEXT_FP_REGS+(PT_R30*8))(r3)
stfd fp31,(SIGCONTEXT_FP_REGS+(PT_R31*8))(r3)
stfd fp0,(SIGCONTEXT_FP_REGS+(32*8))(r3)
ld r8,.LC__dl_hwcap@toc(r2)
- li r10,0
#ifdef SHARED
/* Load _rtld-global._dl_hwcap. */
ld r8,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET(r8)
#else
ld r8,0(r8) /* Load extern _dl_hwcap. */
#endif
- andis. r8,r8,(PPC_FEATURE_HAS_ALTIVEC >> 16)
- beq L(has_no_vec)
-
la r10,(SIGCONTEXT_V_RESERVE+8)(r3)
la r9,(SIGCONTEXT_V_RESERVE+24)(r3)
+
+ andis. r6,r8,(PPC_FEATURE_HAS_ALTIVEC >> 16)
+
clrrdi r10,r10,4
+ beq L(has_no_vec)
+
clrrdi r9,r9,4
+ mr r8,r10 /* Capture *v_regs value in r5. */
stvx v0,0,r10
stvx v1,0,r9
addi r9,r9,32
stvx v18,0,r10
- stvx v11,0,r9
- addi r19,r10,32
+ stvx v19,0,r9
+ addi r10,r10,32
addi r9,r9,32
stvx v20,0,r10
addi r10,r10,32
addi r9,r9,32
- stvx v10,0,r10
- stvx v11,0,r9
- addi r10,r10,32
- addi r9,r9,32
-
mfvscr v0
mfspr r0,VRSAVE
stvx v0,0,r10
- stw r0,0(9)
+ stw r0,0(r9)
L(has_no_vec):
/*
Store either a NULL or a quadword aligned pointer to the Vector register
array into *v_regs.
*/
- std r10,(SIGCONTEXT_V_REGS_PTR)(r3)
+ std r8,(SIGCONTEXT_V_REGS_PTR)(r3)
mr r31,r4
addi r5,r3,UCONTEXT_SIGMASK
* of a procedure call (makecontext), so we don't need to restore
* msr and ctr. We don't restore r13 since it will be used as
* the TLS pointer. */
- lwz r0,(SIGCONTEXT_GP_REGS+(PT_MSR*8))(r31)
+ ld r0,(SIGCONTEXT_GP_REGS+(PT_MSR*8))(r31)
cmpdi r0,0
bne L(do_sigret)
# else
ld r8,0(r8) /* Load extern _dl_hwcap. */
# endif
- andis. r8,r8,(PPC_FEATURE_HAS_ALTIVEC >> 16)
+ andis. r6,r8,(PPC_FEATURE_HAS_ALTIVEC >> 16)
beq L(has_no_vec2)
cmpdi r10,0
addi r9,r9,32
lvx v18,0,r10
- lvx v11,0,r9
- addi r19,r10,32
+ lvx v19,0,r9
+ addi r10,r10,32
addi r9,r9,32
lvx v20,0,r10
lfd fp0,(SIGCONTEXT_FP_REGS+(32*8))(r31)
lfd fp31,(SIGCONTEXT_FP_REGS+(PT_R31*8))(r31)
lfd fp30,(SIGCONTEXT_FP_REGS+(PT_R30*8))(r31)
+
+# ifdef _ARCH_PWR6
+ /* Use the extended four-operand version of the mtfsf insn. */
+ .machine push
+ .machine "power6"
+
+ mtfsf 0xff,fp0,1,0
+
+ .machine pop
+# else
+ /* Availability of DFP indicates a 64-bit FPSCR. */
+ andi. r6,r8,PPC_FEATURE_HAS_DFP
+ beq 7f
+
+ .machine push
+ .machine "power6"
+
+ mtfsf 0xff,fp0,1,0
+
+ .machine pop
+
+ b 8f
+ /* Continue to operate on the FPSCR as if it were 32-bits. */
+7:
mtfsf 0xff,fp0
+8:
+#endif /* _ARCH_PWR6 */
+
lfd fp29,(SIGCONTEXT_FP_REGS+(PT_R29*8))(r31)
lfd fp28,(SIGCONTEXT_FP_REGS+(PT_R28*8))(r31)
lfd fp27,(SIGCONTEXT_FP_REGS+(PT_R27*8))(r31)
ld r4,(SIGCONTEXT_GP_REGS+(PT_R4*8))(r31)
ld r0,(SIGCONTEXT_GP_REGS+(PT_CCR*8))(r31)
ld r5,(SIGCONTEXT_GP_REGS+(PT_R5*8))(r31)
- mfcr r0
ld r6,(SIGCONTEXT_GP_REGS+(PT_R6*8))(r31)
ld r7,(SIGCONTEXT_GP_REGS+(PT_R7*8))(r31)
ld r8,(SIGCONTEXT_GP_REGS+(PT_R8*8))(r31)
ld r9,(SIGCONTEXT_GP_REGS+(PT_R9*8))(r31)
+ mtcr r0
ld r10,(SIGCONTEXT_GP_REGS+(PT_R10*8))(r31)
ld r11,(SIGCONTEXT_GP_REGS+(PT_R11*8))(r31)
ld r12,(SIGCONTEXT_GP_REGS+(PT_R12*8))(r31)
li r0,SYS_ify(rt_sigreturn)
sc
/* No return. */
-#else
- /* If the kernel is not at least 2.4.21 then generate a ENOSYS stub. */
- mflr r0
- std r0,FRAME_LR_SAVE(r1)
- stdu r1,-128(r1)
- li r3,ENOSYS
- bl JUMPTARGET(__syscall_error)
- nop
- li r3,-1
- ld r0,128+FRAME_LR_SAVE(r1)
- addi r1,r1,128
- mtlr r0
- blr
-#endif
PSEUDO_END(__swapcontext)