summaryrefslogtreecommitdiff
path: root/sysdeps/unix/sysv/linux/powerpc/powerpc64/getcontext.S
blob: 0ebf2d87275e527e53e0030c2ebc5d27d29dc0dc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/* Save current context.
   Copyright (C) 2002 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
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.

   The GNU C Library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   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.  */

#include <sysdep.h>
#include "kernel-features.h"

#define __ASSEMBLY__
#include <asm/ptrace.h>
#include <asm/errno.h>
#include "ucontext_i.h"

ENTRY(__getcontext)
#ifdef __ASSUME_NEW_RT_SIGRETURN_SYSCALL
  std  r0,(SIGCONTEXT_GP_REGS+(PT_R0*8))(r3)
  std  r1,(SIGCONTEXT_GP_REGS+(PT_R1*8))(r3)
  mflr  r0
  std  r2,(SIGCONTEXT_GP_REGS+(PT_R2*8))(r3)
  std  r0,FRAME_LR_SAVE(r1)
  std  r0,(SIGCONTEXT_GP_REGS+(PT_LNK*8))(r3)
  std  r0,(SIGCONTEXT_GP_REGS+(PT_NIP*8))(r3)
  stdu  r1,-128(r1)
  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)
  std  r7,(SIGCONTEXT_GP_REGS+(PT_R7*8))(r3)
  std  r8,(SIGCONTEXT_GP_REGS+(PT_R8*8))(r3)
  std  r9,(SIGCONTEXT_GP_REGS+(PT_R9*8))(r3)
  std  r10,(SIGCONTEXT_GP_REGS+(PT_R10*8))(r3)
  std  r11,(SIGCONTEXT_GP_REGS+(PT_R11*8))(r3)
  std  r12,(SIGCONTEXT_GP_REGS+(PT_R12*8))(r3)
  std  r13,(SIGCONTEXT_GP_REGS+(PT_R13*8))(r3)
  std  r14,(SIGCONTEXT_GP_REGS+(PT_R14*8))(r3)
  std  r15,(SIGCONTEXT_GP_REGS+(PT_R15*8))(r3)
  std  r16,(SIGCONTEXT_GP_REGS+(PT_R16*8))(r3)
  std  r17,(SIGCONTEXT_GP_REGS+(PT_R17*8))(r3)
  std  r18,(SIGCONTEXT_GP_REGS+(PT_R18*8))(r3)
  std  r19,(SIGCONTEXT_GP_REGS+(PT_R19*8))(r3)
  std  r20,(SIGCONTEXT_GP_REGS+(PT_R20*8))(r3)
  std  r21,(SIGCONTEXT_GP_REGS+(PT_R21*8))(r3)
  std  r22,(SIGCONTEXT_GP_REGS+(PT_R22*8))(r3)
  std  r23,(SIGCONTEXT_GP_REGS+(PT_R23*8))(r3)
  std  r24,(SIGCONTEXT_GP_REGS+(PT_R24*8))(r3)
  std  r25,(SIGCONTEXT_GP_REGS+(PT_R25*8))(r3)
  std  r26,(SIGCONTEXT_GP_REGS+(PT_R26*8))(r3)
  std  r27,(SIGCONTEXT_GP_REGS+(PT_R27*8))(r3)
  std  r28,(SIGCONTEXT_GP_REGS+(PT_R28*8))(r3)
  std  r29,(SIGCONTEXT_GP_REGS+(PT_R29*8))(r3)
  std  r30,(SIGCONTEXT_GP_REGS+(PT_R30*8))(r3)
  std  r31,(SIGCONTEXT_GP_REGS+(PT_R31*8))(r3)
  mfctr  r0
  std  r0,(SIGCONTEXT_GP_REGS+(PT_CTR*8))(r3)
  mfxer  r0
  std  r0,(SIGCONTEXT_GP_REGS+(PT_XER*8))(r3)
  mfcr  r0
  std  r0,(SIGCONTEXT_GP_REGS+(PT_CCR*8))(r3)
  
  /* Set the return value of swapcontext to "success".  R3 is the only 
     register whose value is not preserved in the saved context.  */
  li   r0,0
  std  r0,(SIGCONTEXT_GP_REGS+(PT_R3*8))(r3)
  
  /* Zero fill fields that can't be set in user state or are unused.  */
  std  r0,(SIGCONTEXT_GP_REGS+(PT_MSR*8))(r3)
  std  r0,(SIGCONTEXT_GP_REGS+(34*8))(r3)
  std  r0,(SIGCONTEXT_GP_REGS+(PT_SOFTE*8))(r3)
  std  r0,(SIGCONTEXT_GP_REGS+(40*8))(r3)
  std  r0,(SIGCONTEXT_GP_REGS+(41*8))(r3)
  std  r0,(SIGCONTEXT_GP_REGS+(42*8))(r3)
  std  r0,(SIGCONTEXT_GP_REGS+(PT_RESULT*8))(r3)
  
  /* Set the PT_REGS pointer to the address of sigcontext's gp_regs 
     field.  Struct pt_regs and elf_gregset_t are the same thing.  
     We kept the regs field for backwards compatibility with
     libraries built before we extended sigcontext.  */
  addi r0,r3,SIGCONTEXT_GP_REGS
  std  r0,SIGCONTEXT_PT_REGS(r3)
  
  stfd  fp0,(SIGCONTEXT_FP_REGS+(PT_R0*8))(r3)
  stfd  fp1,(SIGCONTEXT_FP_REGS+(PT_R1*8))(r3)
  stfd  fp2,(SIGCONTEXT_FP_REGS+(PT_R2*8))(r3)
  stfd  fp3,(SIGCONTEXT_FP_REGS+(PT_R3*8))(r3)
  stfd  fp4,(SIGCONTEXT_FP_REGS+(PT_R4*8))(r3)
  stfd  fp5,(SIGCONTEXT_FP_REGS+(PT_R5*8))(r3)
  stfd  fp6,(SIGCONTEXT_FP_REGS+(PT_R6*8))(r3)
  stfd  fp7,(SIGCONTEXT_FP_REGS+(PT_R7*8))(r3)
  stfd  fp8,(SIGCONTEXT_FP_REGS+(PT_R8*8))(r3)
  stfd  fp9,(SIGCONTEXT_FP_REGS+(PT_R9*8))(r3)
  stfd  fp10,(SIGCONTEXT_FP_REGS+(PT_R10*8))(r3)
  stfd  fp11,(SIGCONTEXT_FP_REGS+(PT_R11*8))(r3)
  stfd  fp12,(SIGCONTEXT_FP_REGS+(PT_R12*8))(r3)
  stfd  fp13,(SIGCONTEXT_FP_REGS+(PT_R13*8))(r3)
  stfd  fp14,(SIGCONTEXT_FP_REGS+(PT_R14*8))(r3)
  stfd  fp15,(SIGCONTEXT_FP_REGS+(PT_R15*8))(r3)
  stfd  fp16,(SIGCONTEXT_FP_REGS+(PT_R16*8))(r3)
  stfd  fp17,(SIGCONTEXT_FP_REGS+(PT_R17*8))(r3)
  stfd  fp18,(SIGCONTEXT_FP_REGS+(PT_R18*8))(r3)
  stfd  fp19,(SIGCONTEXT_FP_REGS+(PT_R19*8))(r3)
  stfd  fp20,(SIGCONTEXT_FP_REGS+(PT_R20*8))(r3)
  stfd  fp21,(SIGCONTEXT_FP_REGS+(PT_R21*8))(r3)
  stfd  fp22,(SIGCONTEXT_FP_REGS+(PT_R22*8))(r3)
  stfd  fp23,(SIGCONTEXT_FP_REGS+(PT_R23*8))(r3)
  stfd  fp24,(SIGCONTEXT_FP_REGS+(PT_R24*8))(r3)
  stfd  fp25,(SIGCONTEXT_FP_REGS+(PT_R25*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)
  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)

  addi  r5,r3,UCONTEXT_SIGMASK
  li  r4,0
  li  r3,SIG_BLOCK
  bl  JUMPTARGET(sigprocmask)
  nop
#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
#endif
  
  ld    r0,128+FRAME_LR_SAVE(r1)  
  addi  r1,r1,128
  mtlr  r0
  blr
PSEUDO_END(__getcontext)

weak_alias(__getcontext, getcontext)