1 /* Create new context.  C-SKY version.
2    Copyright (C) 2018-2021 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 <stdarg.h>
20 #include <ucontext.h>
21 
22 /* Number of arguments that go in registers.  */
23 #define NREG_ARGS  4
24 
25 /* Take a context previously prepared via getcontext() and set to
26    call func() with the given int only args.  */
27 void
__makecontext(ucontext_t * ucp,void (* func)(void),int argc,...)28 __makecontext (ucontext_t *ucp, void (*func) (void), int argc, ...)
29 {
30   extern void __startcontext (void);
31   unsigned long *funcstack;
32   va_list vl;
33   unsigned long *regptr;
34   unsigned int reg;
35   int misaligned;
36 
37   /* Start at the top of stack.  */
38   funcstack = (unsigned long *) (ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size);
39 
40   /* Ensure the stack stays eight byte aligned.  */
41   misaligned = ((unsigned long) funcstack & 4) != 0;
42 
43   if ((argc > NREG_ARGS) && (argc & 1) != 0)
44     misaligned = !misaligned;
45 
46   if (misaligned)
47     funcstack -= 1;
48 
49   va_start (vl, argc);
50 
51   /* Reserve space for the on-stack arguments.  */
52   if (argc > NREG_ARGS)
53     funcstack -= (argc - NREG_ARGS);
54 
55   ucp->uc_mcontext.__gregs.__usp = (unsigned long) funcstack;
56   ucp->uc_mcontext.__gregs.__pc = (unsigned long) func;
57 
58   /* Exit to startcontext() with the next context in R9.  */
59   ucp->uc_mcontext.__gregs.__regs[5] = (unsigned long) ucp->uc_link;
60   ucp->uc_mcontext.__gregs.__lr = (unsigned long) __startcontext;
61 
62   /* The first four arguments go into registers.  */
63   regptr = &(ucp->uc_mcontext.__gregs.__a0);
64 
65   for (reg = 0; (reg < argc) && (reg < NREG_ARGS); reg++)
66     *regptr++ = va_arg (vl, unsigned long);
67 
68   /* And the remainder on the stack.  */
69   for (; reg < argc; reg++)
70     *funcstack++ = va_arg (vl, unsigned long);
71 
72   va_end (vl);
73 }
74 weak_alias (__makecontext, makecontext)
75