1 /* Create new context for ARC.
2    Copyright (C) 2020-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 <sys/ucontext.h>
23 
24 void
__makecontext(ucontext_t * ucp,void (* func)(void),int argc,...)25 __makecontext (ucontext_t *ucp, void (*func) (void), int argc, ...)
26 {
27   extern void __startcontext (void) attribute_hidden;
28   unsigned long int sp, *r;
29   va_list vl;
30   int i, reg_args, stack_args;
31 
32   sp = ((unsigned long int) ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size) & ~7;
33 
34   ucp->uc_mcontext.__sp = sp;
35   ucp->uc_mcontext.__fp = 0;
36 
37   /* __startcontext is sort of trampoline to invoke @func
38      From setcontext pov, the resume address is __startcontext,
39      set it up in BLINK place holder.  */
40 
41   ucp->uc_mcontext.__blink = (unsigned long int) &__startcontext;
42 
43   /* __startcontext passed 2 types of args
44        - args to @func setup in canonical r0-r7
45        - @func and next function in r14,r15.   */
46 
47   ucp->uc_mcontext.__r14 = (unsigned long int) func;
48   ucp->uc_mcontext.__r15 = (unsigned long int) ucp->uc_link;
49 
50   r = &ucp->uc_mcontext.__r0;
51 
52   va_start (vl, argc);
53 
54   reg_args = argc > 8 ? 8 : argc;
55   for (i = 0; i < reg_args; i++)
56     *r-- = va_arg (vl, unsigned long int);
57 
58   stack_args = argc - reg_args;
59 
60   if (__glibc_unlikely (stack_args > 0))
61     {
62       sp -= stack_args * sizeof (unsigned long int);
63       ucp->uc_mcontext.__sp = sp;
64       r = (unsigned long int *) sp;
65 
66       for (i = 0; i < stack_args; i++)
67         *r++ = va_arg (vl, unsigned long int);
68     }
69 
70   va_end (vl);
71 }
72 
73 weak_alias (__makecontext, makecontext)
74