Implement getcontext, makecontext, setcontext and swapcontext.

Signed-off-by: Max Filippov <jcmvb...@gmail.com>
---
Changes v1->v2:
- drop wrong comment from __start_context

 extra/Configs/Config.xtensa                 |   3 +-
 libc/sysdeps/linux/xtensa/Makefile.arch     |   3 +
 libc/sysdeps/linux/xtensa/__start_context.S | 100 +++++++++++
 libc/sysdeps/linux/xtensa/getcontext.S      |  99 +++++++++++
 libc/sysdeps/linux/xtensa/makecontext.c     | 179 ++++++++++++++++++++
 libc/sysdeps/linux/xtensa/setcontext.S      | 116 +++++++++++++
 libc/sysdeps/linux/xtensa/swapcontext.S     | 173 +++++++++++++++++++
 libc/sysdeps/linux/xtensa/sysdep.h          |   7 +-
 libc/sysdeps/linux/xtensa/ucontext_i.sym    |  15 ++
 9 files changed, 692 insertions(+), 3 deletions(-)
 create mode 100644 libc/sysdeps/linux/xtensa/__start_context.S
 create mode 100644 libc/sysdeps/linux/xtensa/getcontext.S
 create mode 100644 libc/sysdeps/linux/xtensa/makecontext.c
 create mode 100644 libc/sysdeps/linux/xtensa/setcontext.S
 create mode 100644 libc/sysdeps/linux/xtensa/swapcontext.S
 create mode 100644 libc/sysdeps/linux/xtensa/ucontext_i.sym

diff --git a/extra/Configs/Config.xtensa b/extra/Configs/Config.xtensa
index 3ee8817ba1a2..7316c542d896 100644
--- a/extra/Configs/Config.xtensa
+++ b/extra/Configs/Config.xtensa
@@ -10,5 +10,6 @@ config TARGET_ARCH
 config FORCE_OPTIONS_FOR_ARCH
        bool
        default y
-       select ARCH_HAS_DEPRECATED_SYSCALLS
        select ARCH_ANY_ENDIAN
+       select ARCH_HAS_DEPRECATED_SYSCALLS
+       select ARCH_HAS_UCONTEXT
diff --git a/libc/sysdeps/linux/xtensa/Makefile.arch 
b/libc/sysdeps/linux/xtensa/Makefile.arch
index 23cd08ee5687..f3a93caaafb1 100644
--- a/libc/sysdeps/linux/xtensa/Makefile.arch
+++ b/libc/sysdeps/linux/xtensa/Makefile.arch
@@ -10,3 +10,6 @@ SSRC-y := bsd-_setjmp.S bsd-setjmp.S setjmp.S clone.S \
          sigrestorer.S syscall.S mmap.S windowspill.S __longjmp.S vfork.S
 
 CSRC-$(if $(UCLIBC_HAS_THREADS_NATIVE),,y) += fork.c
+
+CSRC-$(UCLIBC_HAS_CONTEXT_FUNCS) += makecontext.c
+SSRC-$(UCLIBC_HAS_CONTEXT_FUNCS) += setcontext.S getcontext.S swapcontext.S 
__start_context.S
diff --git a/libc/sysdeps/linux/xtensa/__start_context.S 
b/libc/sysdeps/linux/xtensa/__start_context.S
new file mode 100644
index 000000000000..a30d7b6188ad
--- /dev/null
+++ b/libc/sysdeps/linux/xtensa/__start_context.S
@@ -0,0 +1,100 @@
+/* Copyright (C) 2018 - 2022 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <sysdep.h>
+
+#if defined(__XTENSA_CALL0_ABI__)
+/*
+ * There's no entry instruction, makecontext sets up ucontext_t as if
+ * getcontext was called above and is about to return here.
+ * Registers on entry to this function:
+ *   a12: func to call
+ *   a13: ucp->uc_link, next context to activate if func returns
+ *   a14: func argc
+ */
+       .literal_position
+
+ENTRY_PREFIX(__start_context)
+
+       beqz    a14, 1f
+
+       /* load func arguments 0..1 from stack and free that space */
+       l32i    a2, a1, 8
+       l32i    a3, a1, 12
+       addi    a1, a1, 16
+       bltui   a14, 3, 1f
+
+       /* load func arguments 2..5 from stack and free that space */
+       l32i    a4, a1, 0
+       l32i    a5, a1, 4
+       l32i    a6, a1, 8
+       l32i    a7, a1, 12
+       addi    a1, a1, 16
+       /* func arguments 6..argc - 1 are now at the top of the stack */
+1:
+       callx0  a12
+       beqz    a13, 1f
+       mov     a2, a13
+       movi    a4, JUMPTARGET (setcontext)
+       callx0  a4
+1:
+       movi    a4, JUMPTARGET (_exit)
+       movi    a2, 0
+       callx0  a4
+       ill
+END(__start_context)
+#elif defined(__XTENSA_WINDOWED_ABI__)
+/*
+ * There's no entry instruction, makecontext sets up ucontext_t as if
+ * getcontext was called above and is about to return here.
+ * Registers on entry to this function:
+ *   a2: func to call
+ *   a3: ucp->uc_link, next context to activate if func returns
+ *   a4: func argc
+ *   a5..a7: func arguments 0..2
+ */
+       .literal_position
+
+ENTRY_PREFIX(__start_context)
+
+       mov     a10, a5
+       mov     a11, a6
+       mov     a12, a7
+       bltui   a4, 4, 1f
+
+       /* load func arguments 3..5 from stack and free that space */
+       l32i    a13, a1, 4
+       l32i    a14, a1, 8
+       l32i    a15, a1, 12
+       addi    a5, a1, 16
+       movsp   a1, a5
+       /* func arguments 6..argc - 1 are now at the top of the stack */
+1:
+       callx8  a2
+       beqz    a3, 1f
+       mov     a6, a3
+       movi    a4, JUMPTARGET (setcontext)
+       callx4  a4
+1:
+       movi    a4, JUMPTARGET (_exit)
+       movi    a6, 0
+       callx4  a4
+       ill
+END(__start_context)
+#else
+#error Unsupported Xtensa ABI
+#endif
diff --git a/libc/sysdeps/linux/xtensa/getcontext.S 
b/libc/sysdeps/linux/xtensa/getcontext.S
new file mode 100644
index 000000000000..fbb70c3f8720
--- /dev/null
+++ b/libc/sysdeps/linux/xtensa/getcontext.S
@@ -0,0 +1,99 @@
+/* Copyright (C) 2018 - 2022 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <sysdep.h>
+#include "ucontext_i.h"
+
+#if defined(__XTENSA_CALL0_ABI__)
+ENTRY(__getcontext)
+       s32i    a0, a2, MCONTEXT_SC_PC
+       s32i    a1, a2, MCONTEXT_SC_A_0 + 4
+
+       /* save callee-saved registers in the context */
+       s32i    a12, a2, MCONTEXT_SC_A_0 + 48
+       s32i    a13, a2, MCONTEXT_SC_A_0 + 52
+       s32i    a14, a2, MCONTEXT_SC_A_0 + 56
+       s32i    a15, a2, MCONTEXT_SC_A_0 + 60
+
+       movi    a3, 0
+       addi    a4, a2, UCONTEXT_SIGMASK
+       movi    a2, 0
+       movi    a5, JUMPTARGET (sigprocmask)
+       jx      a5
+END(__getcontext)
+#elif defined(__XTENSA_WINDOWED_ABI__)
+ENTRY(__getcontext)
+       movi    a4, __window_spill
+       callx4  a4
+       s32i    a0, a2, MCONTEXT_SC_PC
+
+       /* copy registers a0..a3 from spill area */
+       addi    a3, a1, -16
+       l32i    a4, a3, 0
+       l32i    a5, a3, 4
+       l32i    a6, a3, 8
+       l32i    a7, a3, 12
+       s32i    a4, a2, MCONTEXT_SC_A_0 + 0
+       s32i    a5, a2, MCONTEXT_SC_A_0 + 4
+       s32i    a6, a2, MCONTEXT_SC_A_0 + 8
+       s32i    a7, a2, MCONTEXT_SC_A_0 + 12
+
+       /* if it was call4 then register saving is done */
+       extui   a4, a0, 30, 2
+       bltui   a4, 2, 1f
+
+       /* otherwise load spill overflow area address into a3 */
+       addi    a3, a5, -16
+       l32i    a3, a3, 4
+       addi    a3, a3, -32
+       beqi    a4, 2, 2f
+
+       /* copy registers a8..a11 from spill overflow area */
+       addi    a3, a3, -16
+       l32i    a4, a3, 16
+       l32i    a5, a3, 20
+       l32i    a6, a3, 24
+       l32i    a7, a3, 28
+       s32i    a4, a2, MCONTEXT_SC_A_0 + 32
+       s32i    a5, a2, MCONTEXT_SC_A_0 + 36
+       s32i    a6, a2, MCONTEXT_SC_A_0 + 40
+       s32i    a7, a2, MCONTEXT_SC_A_0 + 44
+
+       /* copy registers a4..a7 from spill overflow area */
+2:
+       l32i    a4, a3, 0
+       l32i    a5, a3, 4
+       l32i    a6, a3, 8
+       l32i    a7, a3, 12
+       s32i    a4, a2, MCONTEXT_SC_A_0 + 16
+       s32i    a5, a2, MCONTEXT_SC_A_0 + 20
+       s32i    a6, a2, MCONTEXT_SC_A_0 + 24
+       s32i    a7, a2, MCONTEXT_SC_A_0 + 28
+1:
+       movi    a6, 0
+       movi    a7, 0
+       addi    a8, a2, UCONTEXT_SIGMASK
+       movi    a4, JUMPTARGET (sigprocmask)
+       callx4  a4
+       mov     a2, a6
+       retw
+END(__getcontext)
+#else
+#error Unsupported Xtensa ABI
+#endif
+
+weak_alias (__getcontext, getcontext)
diff --git a/libc/sysdeps/linux/xtensa/makecontext.c 
b/libc/sysdeps/linux/xtensa/makecontext.c
new file mode 100644
index 000000000000..da26a0130325
--- /dev/null
+++ b/libc/sysdeps/linux/xtensa/makecontext.c
@@ -0,0 +1,179 @@
+/* Copyright (C) 2018 - 2022 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <sysdep.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <string.h>
+#include <ucontext.h>
+
+extern void __start_context (void);
+
+#if defined(__XTENSA_CALL0_ABI__)
+/*
+ * makecontext sets up new stack like this:
+ *
+ *    +------------------ stack top (uc_stack.ss_sp + uc_stack.ss_size)
+ *    | optional alignment
+ *    +------------------ CFA of __start_context, initial sp points here
+ *    | optional padding
+ *    +------------------ Optional arguments 6..argc - 1
+ *    | func arg argc - 1
+ *    | func arg argc - 2
+ *    |  ...
+ *    | func arg 6
+ *    +------------------ Optional arguments 2..5
+ *    | func arg 5
+ * 16 | func arg 4
+ *    | func arg 3
+ *    | func arg 2
+ *    +------------------ Optional arguments 0..1
+ *    | func arg 1
+ * 16 | func arg 0
+ *    | padding
+ *    | padding
+ *    +------------------ CFA of pseudo getcontext
+ *    |
+ *    +------------------ stack bottom (uc_stack.ss_sp)
+ *
+ * When argc is 0 arguments areas are not allocated,
+ * when 1 <= argc < 3 only area for arguments 0..1 is allocated,
+ * when 3 <= argc < 7 areas for arguments 0..1 and 2..5 is allocated,
+ * when argc >= 7 all three arguments areas are allocated.
+ * Arguments 0..5 area is deallocated by the __start_context after
+ * arguments are loaded into registers.
+ * uc_mcontext registers are set as if __start_context made call0
+ * to getcontext, sp points to that pseudo getcontext CFA.
+ * setcontext/swapcontext will arrange for restoring regiters
+ * a1, a12..a15 of __start_context.
+ */
+
+void
+__makecontext (ucontext_t *ucp, void (*func) (void), int argc, ...)
+{
+  unsigned long sp = ((unsigned long) ucp->uc_stack.ss_sp
+    + ucp->uc_stack.ss_size) & -16;
+  int i;
+
+  if (argc > 0)
+    sp -= 4 * (argc + 2);
+  sp &= -16;
+
+  ucp->uc_mcontext.sc_pc = (unsigned long) __start_context;
+  ucp->uc_mcontext.sc_a[1] = sp;
+  ucp->uc_mcontext.sc_a[12] = (unsigned long) func;
+  ucp->uc_mcontext.sc_a[13] = (unsigned long) ucp->uc_link;
+  ucp->uc_mcontext.sc_a[14] = argc;
+
+  if (argc)
+    {
+      va_list ap;
+
+      va_start (ap, argc);
+      for (i = 0; i < argc; ++i)
+       ((int *) sp)[i + 2] = va_arg (ap, int);
+      va_end (ap);
+    }
+}
+#elif defined(__XTENSA_WINDOWED_ABI__)
+/*
+ * makecontext sets up new stack like this:
+ *
+ *    +------------------ stack top (uc_stack.ss_sp + uc_stack.ss_size)
+ *    | optional alignment
+ *    +------------------ CFA of __start_context
+ * 16 | Outermost caller spill area
+ *    +------------------
+ * 16 | __start_context overflow area
+ *    +------------------ initial sp points here
+ *    | optional padding
+ *    +------------------ Optional arguments 6..argc - 1
+ *    | func arg argc - 1
+ *    | func arg argc - 2
+ *    |  ...
+ *    | func arg 6
+ *    +------------------ Optional arguments 3..5
+ *    | func arg 5
+ * 16 | func arg 4
+ *    | func arg 3
+ *    | padding
+ *    +------------------ CFA of pseudo getcontext
+ * 16 | __start_context caller spill area
+ *    +------------------
+ *    |
+ *    +------------------ stack bottom (uc_stack.ss_sp)
+ *
+ * When argc < 4 both arguments areas are not allocated,
+ * when 4 <= argc < 7 only area for arguments 3..5 is allocated,
+ * when argc >= 7 both arguments areas are allocated.
+ * Arguments 3..5 area is deallocated by the __start_context after
+ * arguments are loaded into registers.
+ * uc_mcontext registers are set as if __start_context made call8
+ * to getcontext, sp points to that pseudo getcontext CFA, spill
+ * area under that sp has a1 pointing to the __start_context CFA
+ * at the top of the stack. setcontext/swapcontext will arrange for
+ * restoring regiters a0..a7 of __start_context.
+ */
+
+void
+__makecontext (ucontext_t *ucp, void (*func) (void), int argc, ...)
+{
+  unsigned long sp = ((unsigned long) ucp->uc_stack.ss_sp
+    + ucp->uc_stack.ss_size - 32) & -16;
+  unsigned long spill0[4] =
+    {
+      0, sp + 32, 0, 0,
+    };
+  int i;
+
+  memset ((void *) sp, 0, 32);
+
+  if (argc > 2)
+    sp -= 4 * (argc - 2);
+  sp &= -16;
+
+  ucp->uc_mcontext.sc_pc =
+    ((unsigned long) __start_context & 0x3fffffff) + 0x80000000;
+  ucp->uc_mcontext.sc_a[0] = 0;
+  ucp->uc_mcontext.sc_a[1] = sp;
+  ucp->uc_mcontext.sc_a[2] = (unsigned long) func;
+  ucp->uc_mcontext.sc_a[3] = (unsigned long) ucp->uc_link;
+  ucp->uc_mcontext.sc_a[4] = argc;
+
+  if (argc)
+    {
+      va_list ap;
+
+      va_start (ap, argc);
+      for (i = 0; i < argc; ++i)
+       {
+         if (i < 3)
+           ucp->uc_mcontext.sc_a[5 + i] = va_arg (ap, int);
+         else
+           ((int *) sp)[i - 2] = va_arg (ap, int);
+       }
+      va_end (ap);
+    }
+
+  sp -= 16;
+  memcpy ((void *) sp, spill0, sizeof (spill0));
+}
+#else
+#error Unsupported Xtensa ABI
+#endif
+
+weak_alias (__makecontext, makecontext)
diff --git a/libc/sysdeps/linux/xtensa/setcontext.S 
b/libc/sysdeps/linux/xtensa/setcontext.S
new file mode 100644
index 000000000000..4df7cc049006
--- /dev/null
+++ b/libc/sysdeps/linux/xtensa/setcontext.S
@@ -0,0 +1,116 @@
+/* Copyright (C) 2018 - 2022 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <sysdep.h>
+#include "ucontext_i.h"
+
+#if defined(__XTENSA_CALL0_ABI__)
+ENTRY(__setcontext)
+       addi    sp, sp, -16
+       s32i    a0, sp, 0
+       s32i    a2, sp, 4
+
+       addi    a3, a2, UCONTEXT_SIGMASK
+       movi    a4, 0
+       movi    a2, SIG_SETMASK
+       movi    a5, JUMPTARGET (sigprocmask)
+       callx0  a5
+       bnez    a2, .Lerror
+
+       l32i    a2, sp, 4
+       l32i    a0, a2, MCONTEXT_SC_PC
+       l32i    a1, a2, MCONTEXT_SC_A_0 + 4
+
+       /* load callee-saved registers from the context */
+       l32i    a12, a2, MCONTEXT_SC_A_0 + 48
+       l32i    a13, a2, MCONTEXT_SC_A_0 + 52
+       l32i    a14, a2, MCONTEXT_SC_A_0 + 56
+       l32i    a15, a2, MCONTEXT_SC_A_0 + 60
+       movi    a2, 0
+       ret
+.Lerror:
+       l32i    a0, sp, 0
+       addi    sp, sp, 16
+       ret
+END(__setcontext)
+#elif defined(__XTENSA_WINDOWED_ABI__)
+ENTRY(__setcontext)
+       movi    a6, SIG_SETMASK
+       addi    a7, a2, UCONTEXT_SIGMASK
+       movi    a8, 0
+       movi    a4, JUMPTARGET (sigprocmask)
+       callx4  a4
+       bnez    a6, .Lerror
+       movi    a4, __window_spill
+       callx4  a4
+
+       l32i    a0, a2, MCONTEXT_SC_PC
+
+       /* copy registers a0..a3 to spill area */
+       addi    a3, a1, -16
+       l32i    a4, a2, MCONTEXT_SC_A_0 + 0
+       l32i    a5, a2, MCONTEXT_SC_A_0 + 4
+       l32i    a6, a2, MCONTEXT_SC_A_0 + 8
+       l32i    a7, a2, MCONTEXT_SC_A_0 + 12
+       s32i    a4, a3, 0
+       s32i    a5, a3, 4
+       s32i    a6, a3, 8
+       s32i    a7, a3, 12
+
+       /* if it was call4 then register setup is done */
+       extui   a4, a0, 30, 2
+       bltui   a4, 2, 1f
+
+       /* otherwise load spill overflow area address into a3 */
+       addi    a3, a5, -16
+       l32i    a3, a3, 4
+       addi    a3, a3, -32
+       beqi    a4, 2, 2f
+
+       /* copy registers a8..a11 to spill overflow area */
+       addi    a3, a3, -16
+       l32i    a4, a2, MCONTEXT_SC_A_0 + 32
+       l32i    a5, a2, MCONTEXT_SC_A_0 + 36
+       l32i    a6, a2, MCONTEXT_SC_A_0 + 40
+       l32i    a7, a2, MCONTEXT_SC_A_0 + 44
+       s32i    a4, a3, 16
+       s32i    a5, a3, 20
+       s32i    a6, a3, 24
+       s32i    a7, a3, 28
+
+       /* copy registers a4..a7 to spill overflow area */
+2:
+       l32i    a4, a2, MCONTEXT_SC_A_0 + 16
+       l32i    a5, a2, MCONTEXT_SC_A_0 + 20
+       l32i    a6, a2, MCONTEXT_SC_A_0 + 24
+       l32i    a7, a2, MCONTEXT_SC_A_0 + 28
+       s32i    a4, a3, 0
+       s32i    a5, a3, 4
+       s32i    a6, a3, 8
+       s32i    a7, a3, 12
+1:
+       movi    a2, 0
+       retw
+.Lerror:
+       mov     a2, a6
+       retw
+END(__setcontext)
+#else
+#error Unsupported Xtensa ABI
+#endif
+
+weak_alias (__setcontext, setcontext)
diff --git a/libc/sysdeps/linux/xtensa/swapcontext.S 
b/libc/sysdeps/linux/xtensa/swapcontext.S
new file mode 100644
index 000000000000..a215edc6d54a
--- /dev/null
+++ b/libc/sysdeps/linux/xtensa/swapcontext.S
@@ -0,0 +1,173 @@
+/* Copyright (C) 2018 - 2022 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <sysdep.h>
+#include "ucontext_i.h"
+
+#if defined(__XTENSA_CALL0_ABI__)
+ENTRY(__swapcontext)
+       s32i    a0, a2, MCONTEXT_SC_PC
+       s32i    a1, a2, MCONTEXT_SC_A_0 + 4
+
+       /* save callee-saved registers in the context */
+       s32i    a12, a2, MCONTEXT_SC_A_0 + 48
+       s32i    a13, a2, MCONTEXT_SC_A_0 + 52
+       s32i    a14, a2, MCONTEXT_SC_A_0 + 56
+       s32i    a15, a2, MCONTEXT_SC_A_0 + 60
+
+       mov     a12, a3
+       mov     a13, a2
+
+       addi    a3, a3, UCONTEXT_SIGMASK
+       addi    a4, a2, UCONTEXT_SIGMASK
+       movi    a2, SIG_SETMASK
+       movi    a5, JUMPTARGET (sigprocmask)
+       callx0  a5
+       bnez    a2, .Lerror
+
+       mov     a2, a12
+       l32i    a0, a2, MCONTEXT_SC_PC
+       l32i    a1, a2, MCONTEXT_SC_A_0 + 4
+
+       /* load callee-saved registers from the context */
+       l32i    a12, a2, MCONTEXT_SC_A_0 + 48
+       l32i    a13, a2, MCONTEXT_SC_A_0 + 52
+       l32i    a14, a2, MCONTEXT_SC_A_0 + 56
+       l32i    a15, a2, MCONTEXT_SC_A_0 + 60
+
+       movi    a2, 0
+       ret
+.Lerror:
+       l32i    a0, a13, MCONTEXT_SC_PC
+       l32i    a12, a13, MCONTEXT_SC_A_0 + 48
+       l32i    a13, a13, MCONTEXT_SC_A_0 + 52
+       ret
+END(__swapcontext)
+#elif defined(__XTENSA_WINDOWED_ABI__)
+ENTRY(__swapcontext)
+       movi    a4, __window_spill
+       callx4  a4
+       mov     a9, a3
+       s32i    a0, a2, MCONTEXT_SC_PC
+
+       /* copy registers a0..a3 from spill area */
+       addi    a3, a1, -16
+       l32i    a4, a3, 0
+       l32i    a5, a3, 4
+       l32i    a6, a3, 8
+       l32i    a7, a3, 12
+       s32i    a4, a2, MCONTEXT_SC_A_0 + 0
+       s32i    a5, a2, MCONTEXT_SC_A_0 + 4
+       s32i    a6, a2, MCONTEXT_SC_A_0 + 8
+       s32i    a7, a2, MCONTEXT_SC_A_0 + 12
+
+       /* if it was call4 then register saving is done */
+       extui   a4, a0, 30, 2
+       bltui   a4, 2, 1f
+
+       /* otherwise load spill overflow area address into a3 */
+       addi    a3, a5, -16
+       l32i    a3, a3, 4
+       addi    a3, a3, -32
+       beqi    a4, 2, 2f
+
+       /* copy registers a8..a11 from spill overflow area */
+       addi    a3, a3, -16
+       l32i    a4, a3, 16
+       l32i    a5, a3, 20
+       l32i    a6, a3, 24
+       l32i    a7, a3, 28
+       s32i    a4, a2, MCONTEXT_SC_A_0 + 32
+       s32i    a5, a2, MCONTEXT_SC_A_0 + 36
+       s32i    a6, a2, MCONTEXT_SC_A_0 + 40
+       s32i    a7, a2, MCONTEXT_SC_A_0 + 44
+
+       /* copy registers a4..a7 from spill overflow area */
+2:
+       l32i    a4, a3, 0
+       l32i    a5, a3, 4
+       l32i    a6, a3, 8
+       l32i    a7, a3, 12
+       s32i    a4, a2, MCONTEXT_SC_A_0 + 16
+       s32i    a5, a2, MCONTEXT_SC_A_0 + 20
+       s32i    a6, a2, MCONTEXT_SC_A_0 + 24
+       s32i    a7, a2, MCONTEXT_SC_A_0 + 28
+1:
+       movi    a6, SIG_SETMASK
+       addi    a7, a9, UCONTEXT_SIGMASK
+       addi    a8, a2, UCONTEXT_SIGMASK
+       mov     a2, a9
+       movi    a4, JUMPTARGET (sigprocmask)
+       callx4  a4
+       bnez    a6, .Lerror
+
+       l32i    a0, a2, MCONTEXT_SC_PC
+
+       /* copy registers a0..a3 to spill area */
+       addi    a3, a1, -16
+       l32i    a4, a2, MCONTEXT_SC_A_0 + 0
+       l32i    a5, a2, MCONTEXT_SC_A_0 + 4
+       l32i    a6, a2, MCONTEXT_SC_A_0 + 8
+       l32i    a7, a2, MCONTEXT_SC_A_0 + 12
+       s32i    a4, a3, 0
+       s32i    a5, a3, 4
+       s32i    a6, a3, 8
+       s32i    a7, a3, 12
+
+       /* if it was call4 then register setup is done */
+       extui   a4, a0, 30, 2
+       bltui   a4, 2, 1f
+
+       /* otherwise load spill overflow area address into a3 */
+       addi    a3, a5, -16
+       l32i    a3, a3, 4
+       addi    a3, a3, -32
+       beqi    a4, 2, 2f
+
+       /* copy registers a8..a11 to spill overflow area */
+       addi    a3, a3, -16
+       l32i    a4, a2, MCONTEXT_SC_A_0 + 32
+       l32i    a5, a2, MCONTEXT_SC_A_0 + 36
+       l32i    a6, a2, MCONTEXT_SC_A_0 + 40
+       l32i    a7, a2, MCONTEXT_SC_A_0 + 44
+       s32i    a4, a3, 16
+       s32i    a5, a3, 20
+       s32i    a6, a3, 24
+       s32i    a7, a3, 28
+
+       /* copy registers a4..a7 to spill overflow area */
+2:
+       l32i    a4, a2, MCONTEXT_SC_A_0 + 16
+       l32i    a5, a2, MCONTEXT_SC_A_0 + 20
+       l32i    a6, a2, MCONTEXT_SC_A_0 + 24
+       l32i    a7, a2, MCONTEXT_SC_A_0 + 28
+       s32i    a4, a3, 0
+       s32i    a5, a3, 4
+       s32i    a6, a3, 8
+       s32i    a7, a3, 12
+1:
+       movi    a2, 0
+       retw
+.Lerror:
+       mov     a2, a6
+       retw
+END(__swapcontext)
+#else
+#error Unsupported Xtensa ABI
+#endif
+
+weak_alias (__swapcontext, swapcontext)
diff --git a/libc/sysdeps/linux/xtensa/sysdep.h 
b/libc/sysdeps/linux/xtensa/sysdep.h
index 0671f0783477..80b3f30fcc5d 100644
--- a/libc/sysdeps/linux/xtensa/sysdep.h
+++ b/libc/sysdeps/linux/xtensa/sysdep.h
@@ -39,12 +39,15 @@
 #endif
 
 
-#define        ENTRY(name)                                                     
\
+#define        ENTRY_PREFIX(name)                                              
\
   .globl C_SYMBOL_NAME(name);                          \
   ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name), @function);                 \
   .align ALIGNARG(2);                                                  \
   LITERAL_POSITION;                                                    \
-  C_LABEL(name)                                                                
\
+  C_LABEL(name)
+
+#define        ENTRY(name)                                                     
\
+  ENTRY_PREFIX(name)                                                   \
   abi_entry(sp, FRAMESIZE);
 
 #define        HIDDEN_ENTRY(name)                                              
\
diff --git a/libc/sysdeps/linux/xtensa/ucontext_i.sym 
b/libc/sysdeps/linux/xtensa/ucontext_i.sym
new file mode 100644
index 000000000000..4770c36c9e1d
--- /dev/null
+++ b/libc/sysdeps/linux/xtensa/ucontext_i.sym
@@ -0,0 +1,15 @@
+#include <inttypes.h>
+#include <signal.h>
+#include <stddef.h>
+#include <sys/ucontext.h>
+
+SIG_BLOCK
+SIG_SETMASK
+
+-- Offsets of the fields in the ucontext_t structure.
+#define ucontext(member)       offsetof (ucontext_t, member)
+#define mcontext(member)       ucontext (uc_mcontext.member)
+
+UCONTEXT_SIGMASK               ucontext (uc_sigmask)
+MCONTEXT_SC_A_0                        mcontext (sc_a[0])
+MCONTEXT_SC_PC                 mcontext (sc_pc)
-- 
2.30.2

_______________________________________________
devel mailing list -- devel@uclibc-ng.org
To unsubscribe send an email to devel-le...@uclibc-ng.org

Reply via email to