1  /* Create new context for ARC.
       2     Copyright (C) 2020-2023 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
      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)