1/* Create new context.
2   Copyright (C) 2005-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 <abort-instr.h>
21
22#include "ucontext_i.h"
23
24/* void __makecontext (ucontext_t *ucp, void (*func)(), int argc, ...);
25  __makecontext sets up a stack and registers for context to run a given
26  function.  The registers are set up like this:
27    r4-r7: parameters 1 to 4
28    r8	 : uc_link from ucontext structure
29    pc	 : (*func) pointer
30    pr	 : address of exitcode
31    r15	 : stack pointer for func.  */
32
33	.text
34	.align	5
35ENTRY(__makecontext)
36	mov	#4, r3
37	mov.l	@(oSS_SP,r4), r1	/* r1 <- ucb->stack_base */
38	mov.l	@(oSS_SIZE,r4), r2	/* r2 <- ucb->stack_size */
39	add	r1, r2			/* r2 <- stack_top */
40	cmp/gt	r3, r6			/* argc > 4? */
41	bf/s	1f
42	 shlr2	r2			/* r2 <- stack_top / 4 */
43	sub	r6, r2
44	add	r3, r2
451:
46	shll2	r2		/* r2 <- stack_top - ((argc > 4) ? 4 * (argc - 4) : 0 */
47	mov	#oR15, r0
48	mov.l	@(oLINK,r4), r1
49	mov.l	r2, @(r0,r4)	/* ucp->r15 <- r2 */
50	mov.l	r1, @(oR8,r4)	/* ucp->r8 <- ucp->uc_link */
51	mov	#oPC, r0
52	mov.l	r5, @(r0,r4)	/* ucp->PC <- func */
53
54	cmp/pl	r6		/* argc > 0? */
55	bf/s	.L1
56	 dt	r6
57	mov.l	r7, @(oR4,r4)	/* ucp->r4 <- argv[0] */
58	cmp/pl	r6		/* argc > 1? */
59	bf/s	.L1
60	 dt	r6
61	mov.l	@(0,r15), r1
62	mov.l	r1, @(oR5,r4)	/* ucp->r5 <- argv[1] */
63	cmp/pl	r6		/* argc > 2? */
64	bf/s	.L1
65	 dt	r6
66	mov.l	@(4,r15), r1
67	mov.l	r1, @(oR6,r4)	/* ucp->r6 <- argv[2] */
68	cmp/pl	r6		/* argc > 3? */
69	bf/s	.L1
70	 dt	r6
71	mov.l	@(8,r15), r1
72	mov.l	r1, @(oR7,r4)	/* ucp->r7 <- argv[3] */
73	mov	#12,r0
74.L0:				/* Save remaining argv[] on the stack.  */
75	cmp/pl	r6
76	bf/s	.L1
77	 dt	r6
78	mov.l	@(r0,r15), r1
79	mov.l	r1, @r2
80	add	#4, r0
81	bra	.L0
82	 add	#4, r2
83.L1:
84#ifdef PIC
85	mova	.Lexitcode, r0
86#else
87	mov.l	.L2, r0
88#endif
89	add	#oPR, r4
90	rts
91	 mov.l	r0, @r4		/* ucp->pr <- exitcode */
92#ifndef PIC
93	.align	2
94.L2:
95	.long	.Lexitcode
96#endif
97	cfi_endproc
98
99	.align	5
100	cfi_startproc
101.Lexitcode:
102#ifdef PIC
103	mov.l	r12, @-r15
104	cfi_adjust_cfa_offset (4)
105	cfi_rel_offset (r12, 0)
106	mova	.Lgot, r0
107	mov.l	.Lgot, r12
108	add	r0, r12
109#endif
110	tst	r8, r8		/* ucb->uc_link == NULL? */
111	bt/s	2f
112	 mov	r8, r4		/* r4 <- ucb->uc_link */
113	mov.l	.Lsetcontext, r1
114	sts.l	pr, @-r15
115	cfi_adjust_cfa_offset (4)
116	cfi_rel_offset (pr, 0)
117#ifdef PIC
118	bsrf	r1
119.LPCS0:
120	 nop
121#else
122	jsr	@r1
123	 nop
124#endif
125        /* Restore to keep CFI/CFA balanced.  */
126	lds.l	@r15+, pr
127	cfi_adjust_cfa_offset (-4)
128	cfi_restore (pr)
129	/* If this returns (which can happen if the syscall fails) we'll exit
130	   the program with the return error value (-1).  */
131	mov	r0, r4
132
1332:
134	mov.l	.Lexit, r1
135#ifdef PIC
136	add	r12, r1
137#endif
138	jsr	@r1
139	 nop
140	/* The 'exit' call should never return.  In case it does cause the
141	   process to terminate.  */
142	ABORT_INSTRUCTION_ASM
143
144	.align	2
145#ifdef PIC
146.Lgot:
147	.long	_GLOBAL_OFFSET_TABLE_
148.Lsetcontext:
149	.long	__setcontext@PLT-(.LPCS0+2-(.))
150.Lexit:
151	.long	HIDDEN_JUMPTARGET(exit)@GOTOFF
152#else
153.Lsetcontext:
154	.long	__setcontext
155.Lexit:
156	.long	HIDDEN_JUMPTARGET(exit)
157#endif
158PSEUDO_END(__makecontext)
159
160weak_alias (__makecontext, makecontext)
161