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