1/* Modify saved context.
2 Copyright (C) 2009-2022 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 <sys/asm.h>
21#include <sys/fpregdef.h>
22#include <sys/regdef.h>
23
24#include "ucontext_i.h"
25
26/* int makecontext (ucontext_t *ucp, (void *func) (), int argc, ...) */
27
28 .text
29 .set nomips16
30LOCALSZ = 0
31ARGSZ = 0
32MASK = 0x00000000
33#ifdef __PIC__
34LOCALSZ = 1 /* save gp */
35#endif
36#if _MIPS_SIM != _ABIO32
37ARGSZ = 5 /* save a3-a7 */
38# ifdef __PIC__
39MASK = 0x10000000
40# endif
41#endif
42FRAMESZ = (((ARGSZ + LOCALSZ) * SZREG) + ALSZ) & ALMASK
43GPOFF = FRAMESZ - ((ARGSZ + 1) * SZREG)
44#if _MIPS_SIM != _ABIO32
45A3OFF = FRAMESZ - (5 * SZREG) /* callee-allocated */
46A4OFF = FRAMESZ - (4 * SZREG)
47A5OFF = FRAMESZ - (3 * SZREG)
48A6OFF = FRAMESZ - (2 * SZREG)
49A7OFF = FRAMESZ - (1 * SZREG)
50NARGREGS = 8
51#else
52A3OFF = FRAMESZ + (3 * SZREG) /* caller-allocated */
53NARGREGS = 4
54#endif
55MCONTEXT_GREGSZ = 8
56#if _MIPS_SIM == _ABIO32 && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
57MCONTEXT_GREGOFF = 4
58#else
59MCONTEXT_GREGOFF = 0
60#endif
61
62NESTED (__makecontext, FRAMESZ, ra)
63 .mask MASK, -(ARGSZ * SZREG)
64 .fmask 0x00000000, 0
65
6698:
67#ifdef __PIC__
68 SETUP_GP
69#endif
70
71 PTR_ADDIU sp, -FRAMESZ
72 cfi_adjust_cfa_offset (FRAMESZ)
73
74#ifdef __PIC__
75 SETUP_GP64_STACK (GPOFF, __makecontext)
76 SAVE_GP (GPOFF)
77#endif
78
79#ifdef PROF
80 .set noat
81 move AT, ra
82 jal _mcount
83 .set at
84#endif
85
86 /* Store args to be passed. */
87 REG_S a3, A3OFF(sp)
88#if _MIPS_SIM != _ABIO32
89 REG_S a4, A4OFF(sp)
90 REG_S a5, A5OFF(sp)
91 REG_S a6, A6OFF(sp)
92 REG_S a7, A7OFF(sp)
93#endif
94
95 /* Set up the stack. */
96 PTR_L t0, STACK_SP(a0)
97 PTR_L t2, STACK_SIZE(a0)
98 PTR_ADDIU t1, sp, A3OFF
99 PTR_ADDU t0, t2
100 and t0, ALMASK
101 blez a2, 2f /* no arguments */
102
103 /* Store register arguments. */
104 PTR_ADDIU t2, a0, MCONTEXT_GREGS + 4 * MCONTEXT_GREGSZ + MCONTEXT_GREGOFF
105 move t3, zero
1060:
107 addiu t3, 1
108 REG_L v1, (t1)
109 PTR_ADDIU t1, SZREG
110 REG_S v1, (t2)
111 PTR_ADDIU t2, MCONTEXT_GREGSZ
112 bgeu t3, a2, 2f /* all done */
113 bltu t3, NARGREGS, 0b /* next */
114
115 /* Make room for stack arguments. */
116 PTR_SUBU t2, a2, t3
117 PTR_SLL t2, 3
118 PTR_SUBU t0, t2
119 and t0, ALMASK
120
121 /* Store stack arguments. */
122 move t2, t0
1231:
124 addiu t3, 1
125 REG_L v1, (t1)
126 PTR_ADDIU t1, SZREG
127 REG_S v1, (t2)
128 PTR_ADDIU t2, SZREG
129 bltu t3, a2, 1b /* next */
130
1312:
132#if _MIPS_SIM == _ABIO32
133 /* Make room for a0-a3 storage. */
134 PTR_ADDIU t0, -(NARGSAVE * SZREG)
135#endif
136 PTR_L v1, UCONTEXT_LINK(a0)
137#ifdef __PIC__
138 PTR_ADDIU t9, 99f - 98b
139#else
140 PTR_LA t9, 99f
141#endif
142 /* sp */
143 REG_S t0, (MCONTEXT_GREGOFF + 29 * MCONTEXT_GREGSZ + MCONTEXT_GREGS)(a0)
144 /* s0 */
145 REG_S v1, (MCONTEXT_GREGOFF + 16 * MCONTEXT_GREGSZ + MCONTEXT_GREGS)(a0)
146#ifdef __PIC__
147 /* s1 */
148 REG_S gp, (MCONTEXT_GREGOFF + 17 * MCONTEXT_GREGSZ + MCONTEXT_GREGS)(a0)
149#endif
150 /* ra */
151 REG_S t9, (MCONTEXT_GREGOFF + 31 * MCONTEXT_GREGSZ + MCONTEXT_GREGS)(a0)
152 REG_S a1, (MCONTEXT_GREGOFF + MCONTEXT_PC)(a0)
153
154#ifdef __PIC__
155 RESTORE_GP64_STACK
156 PTR_ADDIU sp, FRAMESZ
157 cfi_adjust_cfa_offset (-FRAMESZ)
158#endif
159 jr ra
160
161 /* We need to terminate the FDE to stop unwinding if backtrace was
162 called within a context created by makecontext. */
163 cfi_endproc
164 nop
165
16699:
167#ifdef __PIC__
168 move gp, s1
169#endif
170 move a0, zero
171 beqz s0, 0f
172
173 /* setcontext (ucp) */
174 move a0, s0
175#ifdef __PIC__
176 PTR_LA t9, JUMPTARGET (__setcontext)
177 jalr t9
178# if _MIPS_SIM == _ABIO32
179 move gp, s1
180# endif
181#else
182 jal JUMPTARGET (__setcontext)
183#endif
184 move a0, v0
185
1860:
187 /* exit (a0) */
188#ifdef __PIC__
189 PTR_LA t9, HIDDEN_JUMPTARGET (exit)
190 jalr t9
191#else
192 jal HIDDEN_JUMPTARGET (exit)
193#endif
194
195 /* You don't exist, you won't feel anything. */
1961:
197 lb zero, (zero)
198 b 1b
199
200 cfi_startproc
201PSEUDO_END (__makecontext)
202
203weak_alias (__makecontext, makecontext)
204

source code of glibc/sysdeps/unix/sysv/linux/mips/makecontext.S