Update copyright notices with scripts/update-copyrights
[glibc.git] / ports / sysdeps / unix / sysv / linux / tile / setcontext.S
blob76a797d32c7f3ae84487e1fcbf8fb66507d83ce5
1 /* Copyright (C) 2011-2014 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
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.
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.
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    <http://www.gnu.org/licenses/>.  */
19 #include <sysdep.h>
20 #include <asm/errno.h>
21 #include <arch/spr_def.h>
22 #include <arch/abi.h>
24 #include "ucontext_i.h"
26 /* PL to return to via iret in setcontext */
27 #define RETURN_PL 0
29 /* int setcontext (const ucontext_t *ucp) */
31         .text
32 ENTRY (__setcontext)
33         FEEDBACK_ENTER(__setcontext)
35         /* See if this is a true signal context (flags == 0).
36            If so, restore by invoking rt_sigreturn().  */
37 #if UC_FLAGS_OFFSET != 0
38 # error "Add offset to r0 prior to load."
39 #endif
40         LD_PTR r10, r0
41         {
42          BEQZ r10, .Lsigreturn
43          addi r10, r10, -1  /* Confirm that it has value "1".  */
44         }
45         BNEZ r10, .Lbadcontext
47         /* Save lr and r0 briefly on the stack and set the signal mask:
48            rt_sigprocmask (SIG_SETMASK, &ucp->uc_sigmask, NULL, _NSIG / 8).  */
49         {
50          ST sp, lr
51          ADDI_PTR r11, sp, -(2 * REGSIZE)
52          move r10, sp
53         }
54         ADDI_PTR sp, sp, -(3 * REGSIZE)
55         cfi_def_cfa_offset (3 * REGSIZE)
56         cfi_offset (lr, 0)
57         {
58          ST r11, r10
59          ADDI_PTR r10, sp, (2 * REGSIZE)
60         }
61         {
62          ST r10, r0
63          ADDLI_PTR r1, r0, UC_SIGMASK_OFFSET
64         }
65         cfi_offset (r0, -REGSIZE)
66         {
67          movei r3, _NSIG / 8
68          movei r2, 0
69         }
70         {
71          movei r0, SIG_SETMASK
72          moveli TREG_SYSCALL_NR_NAME, __NR_rt_sigprocmask
73         }
74         swint1
75         ADDI_PTR r11, sp, 2 * REGSIZE  /* Restore uc_context to r11. */
76         {
77          LD r11, r11
78          ADDI_PTR sp, sp, 3 * REGSIZE
79         }
80         cfi_def_cfa_offset (0)
81         LD lr, sp
82         {
83          ADDI_PTR r10, r11, UC_REG(0)
84          BNEZ r1, .Lsyscall_error
85         }
87         /* Restore the argument registers; note they will be random
88            unless makecontext() has been called.  */
89         { LD r0, r10; ADDI_PTR r10, r10, REGSIZE }
90         { LD r1, r10; ADDI_PTR r10, r10, REGSIZE }
91         { LD r2, r10; ADDI_PTR r10, r10, REGSIZE }
92         { LD r3, r10; ADDI_PTR r10, r10, REGSIZE }
93         { LD r4, r10; ADDI_PTR r10, r10, REGSIZE }
94         { LD r5, r10; ADDI_PTR r10, r10, REGSIZE }
95         { LD r6, r10; ADDI_PTR r10, r10, REGSIZE }
96         { LD r7, r10; ADDI_PTR r10, r10, REGSIZE }
97         { LD r8, r10; ADDI_PTR r10, r10, REGSIZE }
98         { LD r9, r10; ADDLI_PTR r10, r10, UC_REG(30) - UC_REG(9) }
100         /* Restore the callee-saved GPRs.  */
101         { LD r30, r10; ADDI_PTR r10, r10, REGSIZE }
102         { LD r31, r10; ADDI_PTR r10, r10, REGSIZE }
103         { LD r32, r10; ADDI_PTR r10, r10, REGSIZE }
104         { LD r33, r10; ADDI_PTR r10, r10, REGSIZE }
105         { LD r34, r10; ADDI_PTR r10, r10, REGSIZE }
106         { LD r35, r10; ADDI_PTR r10, r10, REGSIZE }
107         { LD r36, r10; ADDI_PTR r10, r10, REGSIZE }
108         { LD r37, r10; ADDI_PTR r10, r10, REGSIZE }
109         { LD r38, r10; ADDI_PTR r10, r10, REGSIZE }
110         { LD r39, r10; ADDI_PTR r10, r10, REGSIZE }
111         { LD r40, r10; ADDI_PTR r10, r10, REGSIZE }
112         { LD r41, r10; ADDI_PTR r10, r10, REGSIZE }
113         { LD r42, r10; ADDI_PTR r10, r10, REGSIZE }
114         { LD r43, r10; ADDI_PTR r10, r10, REGSIZE }
115         { LD r44, r10; ADDI_PTR r10, r10, REGSIZE }
116         { LD r45, r10; ADDI_PTR r10, r10, REGSIZE }
117         { LD r46, r10; ADDI_PTR r10, r10, REGSIZE }
118         { LD r47, r10; ADDI_PTR r10, r10, REGSIZE }
119         { LD r48, r10; ADDI_PTR r10, r10, REGSIZE }
120         { LD r49, r10; ADDI_PTR r10, r10, REGSIZE }
121         { LD r50, r10; ADDI_PTR r10, r10, REGSIZE }
122         { LD r51, r10; ADDI_PTR r10, r10, REGSIZE }
123         { LD r52, r10; ADDI_PTR r10, r10, REGSIZE * 2 }
124         /* Skip tp since it must not change for a given thread.  */
125         { LD sp, r10;  ADDI_PTR r10, r10, REGSIZE }
126         { LD lr, r10;  ADDI_PTR r10, r10, REGSIZE }
127         { LD r11, r10; ADDI_PTR r10, r10, REGSIZE }
129         /* Construct an iret context; we set ICS so we can validly load
130            EX_CONTEXT for iret without being interrupted halfway through.  */
131         {
132          LD r12, r10
133          movei r13, 1
134         }
135         {
136          mtspr INTERRUPT_CRITICAL_SECTION, r13
137          shli r12, r12, SPR_EX_CONTEXT_0_1__ICS_SHIFT
138         }
139         {
140          mtspr EX_CONTEXT_0_0, r11
141          ori r12, r12, RETURN_PL
142         }
143         mtspr EX_CONTEXT_0_1, r12
144         iret
145         jrp lr    /* keep the backtracer happy */
147 .Lsigreturn:
148         /* This is a context obtained from a signal handler.
149            Perform a full restore by pushing the context
150            passed onto a simulated signal frame on the stack
151            and call the signal return syscall as if a signal
152            handler exited normally.  */
153         {
154          ADDLI_PTR sp, sp, -(C_ABI_SAVE_AREA_SIZE + SI_MAX_SIZE + UC_SIZE)
155          ADDLI_PTR r1, sp, -UC_SIZE
156         }
157         cfi_def_cfa_offset (C_ABI_SAVE_AREA_SIZE + SI_MAX_SIZE + UC_SIZE)
158         moveli r2, UC_SIZE / REGSIZE
159 0:      {
160          LD r10, r0
161          ADDI_PTR r0, r0, REGSIZE
162         }
163         {
164          ST r1, r10
165          ADDI_PTR r1, r1, REGSIZE
166          addi r2, r2, -1
167         }
168         BNEZ r2, 0b
169         moveli TREG_SYSCALL_NR_NAME, __NR_rt_sigreturn
170         swint1
172         /* Restore the stack and fall through to the error
173            path.  Successful rt_sigreturn never returns to
174            its calling place.  */
175         ADDLI_PTR sp, sp, (C_ABI_SAVE_AREA_SIZE + SI_MAX_SIZE + UC_SIZE)
176         cfi_def_cfa_offset (0)
178 .Lsyscall_error:
179         j SYSCALL_ERROR_NAME
181 .Lbadcontext:
182         {
183          movei r1, EINVAL
184          j SYSCALL_ERROR_NAME
185         }
187 END (__setcontext)
189 .hidden __setcontext
190 weak_alias (__setcontext, setcontext)
192 ENTRY (__startcontext)
193         FEEDBACK_ENTER(__startcontext)
194         BEQZ r30, 1f
195         {
196          move r0, r30
197          jal __setcontext
198         }
199 1:      {
200          movei r0, 0
201          j HIDDEN_JUMPTARGET(exit)
202         }
203 END (__startcontext)
204 .hidden __startcontext