1 /* Create new context.  OpenRISC version.
2    Copyright (C) 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 <stdarg.h>
21 #include <stdint.h>
22 #include <ucontext.h>
23 
24 /* makecontext sets up a stack and the registers for the
25    user context.  The stack looks like this:
26 
27 		+-----------------------+
28 		| padding as required   |
29 		+-----------------------+
30     sp ->       | parameters 7 to n     |
31 		+-----------------------+
32 
33    The registers are set up like this:
34      r3-r8  : parameters 1 to 6
35      r14    : uc_link
36      r1     : stack pointer
37      r2     : frame pointer, set to NULL
38 */
39 void
__makecontext(ucontext_t * ucp,void (* func)(void),int argc,...)40 __makecontext (ucontext_t *ucp, void (*func) (void), int argc, ...)
41 {
42   extern void __startcontext (void);
43   unsigned long int *sp;
44   va_list ap;
45   int i;
46 
47   sp = (unsigned long int *)
48     ((uintptr_t) ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size);
49 
50   /* Allocate stack arguments.  */
51   sp -= argc < 6 ? 0 : argc - 6;
52 
53   /* Keep the stack aligned.  */
54   sp = (unsigned long int *) (((uintptr_t) sp) & -4L);
55 
56   /* Keep uc_link in r14.  */
57   ucp->uc_mcontext.__gprs[14] = (uintptr_t) ucp->uc_link;
58   /* Return address points to function __startcontext.  */
59   ucp->uc_mcontext.__gprs[9] = (uintptr_t) &__startcontext;
60   /* Frame pointer is null.  */
61   ucp->uc_mcontext.__gprs[2] = (uintptr_t) 0;
62   /* Restart in user-space starting at 'func'.  */
63   ucp->uc_mcontext.__gprs[11] = (uintptr_t) func;
64   /* Set stack pointer.  */
65   ucp->uc_mcontext.__gprs[1] = (uintptr_t) sp;
66 
67   va_start (ap, argc);
68   for (i = 0; i < argc; ++i)
69     if (i < 6)
70       ucp->uc_mcontext.__gprs[i + 3] = va_arg (ap, unsigned long int);
71     else
72       sp[i - 6] = va_arg (ap, unsigned long int);
73 
74   va_end (ap);
75 }
76 
77 weak_alias (__makecontext, makecontext)
78