summaryrefslogtreecommitdiff
path: root/libc
diff options
context:
space:
mode:
Diffstat (limited to 'libc')
-rw-r--r--libc/string/xtensa/memcpy.S16
-rw-r--r--libc/string/xtensa/memset.S4
-rw-r--r--libc/string/xtensa/strcmp.S20
-rw-r--r--libc/string/xtensa/strcpy.S12
-rw-r--r--libc/string/xtensa/strlen.S8
-rw-r--r--libc/string/xtensa/strncpy.S6
-rw-r--r--libc/sysdeps/linux/xtensa/__longjmp.S17
-rw-r--r--libc/sysdeps/linux/xtensa/bits/setjmp.h9
-rw-r--r--libc/sysdeps/linux/xtensa/clone.S21
-rw-r--r--libc/sysdeps/linux/xtensa/crt1.S30
-rw-r--r--libc/sysdeps/linux/xtensa/crti.S15
-rw-r--r--libc/sysdeps/linux/xtensa/crtn.S17
-rw-r--r--libc/sysdeps/linux/xtensa/mmap.S2
-rw-r--r--libc/sysdeps/linux/xtensa/setjmp.S17
-rw-r--r--libc/sysdeps/linux/xtensa/syscall.S4
-rw-r--r--libc/sysdeps/linux/xtensa/sysdep.h45
-rw-r--r--libc/sysdeps/linux/xtensa/vfork.S23
-rw-r--r--libc/sysdeps/linux/xtensa/windowspill.S3
18 files changed, 221 insertions, 48 deletions
diff --git a/libc/string/xtensa/memcpy.S b/libc/string/xtensa/memcpy.S
index 2b23b4113..244205611 100644
--- a/libc/string/xtensa/memcpy.S
+++ b/libc/string/xtensa/memcpy.S
@@ -91,7 +91,7 @@ __memcpy_aux:
#if !XCHAL_HAVE_LOOPS
blt a3, a7, 1b
#endif
-2: retw
+2: abi_ret
/* Destination is unaligned. */
@@ -181,7 +181,7 @@ ENTRY (memcpy)
3: bbsi.l a4, 2, 4f
bbsi.l a4, 1, 5f
bbsi.l a4, 0, 6f
- retw
+ abi_ret
/* Copy 4 bytes. */
4: l32i a6, a3, 0
@@ -190,7 +190,7 @@ ENTRY (memcpy)
addi a5, a5, 4
bbsi.l a4, 1, 5f
bbsi.l a4, 0, 6f
- retw
+ abi_ret
/* Copy 2 bytes. */
5: l16ui a6, a3, 0
@@ -198,14 +198,14 @@ ENTRY (memcpy)
s16i a6, a5, 0
addi a5, a5, 2
bbsi.l a4, 0, 6f
- retw
+ abi_ret
/* Copy 1 byte. */
6: l8ui a6, a3, 0
s8i a6, a5, 0
.Ldone:
- retw
+ abi_ret
/* Destination is aligned; source is unaligned. */
@@ -276,7 +276,7 @@ ENTRY (memcpy)
#endif
bbsi.l a4, 1, 5f
bbsi.l a4, 0, 6f
- retw
+ abi_ret
/* Copy 2 bytes. */
5: l8ui a6, a3, 0
@@ -286,11 +286,11 @@ ENTRY (memcpy)
s8i a7, a5, 1
addi a5, a5, 2
bbsi.l a4, 0, 6f
- retw
+ abi_ret
/* Copy 1 byte. */
6: l8ui a6, a3, 0
s8i a6, a5, 0
- retw
+ abi_ret
libc_hidden_def (memcpy)
diff --git a/libc/string/xtensa/memset.S b/libc/string/xtensa/memset.S
index 435d6dea0..20bf14c75 100644
--- a/libc/string/xtensa/memset.S
+++ b/libc/string/xtensa/memset.S
@@ -63,7 +63,7 @@ __memset_aux:
#if !XCHAL_HAVE_LOOPS
blt a5, a6, 1b
#endif
-2: retw
+2: abi_ret
/* Destination is unaligned. */
@@ -159,6 +159,6 @@ ENTRY (memset)
/* Set 1 byte. */
s8i a3, a5, 0
-6: retw
+6: abi_ret
libc_hidden_def (memset)
diff --git a/libc/string/xtensa/strcmp.S b/libc/string/xtensa/strcmp.S
index 8ed1ed009..2dce590db 100644
--- a/libc/string/xtensa/strcmp.S
+++ b/libc/string/xtensa/strcmp.S
@@ -108,7 +108,7 @@ ENTRY (strcmp)
#endif
.Lretdiff:
sub a2, a8, a9
- retw
+ abi_ret
/* s1 is word-aligned; s2 is word-aligned.
@@ -229,7 +229,7 @@ ENTRY (strcmp)
/* Words are equal; some byte is zero. */
.Leq: movi a2, 0 /* return equal */
- retw
+ abi_ret
.Lwne2: /* Words are not equal. On big-endian processors, if none of the
bytes are zero, the return value can be determined by a simple
@@ -239,10 +239,10 @@ ENTRY (strcmp)
bnall a10, a7, .Lsomezero
bgeu a8, a9, .Lposreturn
movi a2, -1
- retw
+ abi_ret
.Lposreturn:
movi a2, 1
- retw
+ abi_ret
.Lsomezero: /* There is probably some zero byte. */
#endif /* __XTENSA_EB__ */
.Lwne: /* Words are not equal. */
@@ -263,14 +263,14 @@ ENTRY (strcmp)
byte. Just subtract words to get the return value.
The high order equal bytes cancel, leaving room for the sign. */
sub a2, a8, a9
- retw
+ abi_ret
.Ldiff0:
/* Need to make room for the sign, so can't subtract whole words. */
extui a10, a8, 24, 8
extui a11, a9, 24, 8
sub a2, a10, a11
- retw
+ abi_ret
#else /* !__XTENSA_EB__ */
/* Little-endian is a little more difficult because can't subtract
@@ -281,28 +281,28 @@ ENTRY (strcmp)
extui a10, a8, 24, 8
extui a11, a9, 24, 8
sub a2, a10, a11
- retw
+ abi_ret
.Ldiff0:
/* Byte 0 is different. */
extui a10, a8, 0, 8
extui a11, a9, 0, 8
sub a2, a10, a11
- retw
+ abi_ret
.Ldiff1:
/* Byte 0 is equal; byte 1 is different. */
extui a10, a8, 8, 8
extui a11, a9, 8, 8
sub a2, a10, a11
- retw
+ abi_ret
.Ldiff2:
/* Bytes 0-1 are equal; byte 2 is different. */
extui a10, a8, 16, 8
extui a11, a9, 16, 8
sub a2, a10, a11
- retw
+ abi_ret
#endif /* !__XTENSA_EB */
diff --git a/libc/string/xtensa/strcpy.S b/libc/string/xtensa/strcpy.S
index f9f586896..9f42b34e6 100644
--- a/libc/string/xtensa/strcpy.S
+++ b/libc/string/xtensa/strcpy.S
@@ -68,7 +68,7 @@ ENTRY (strcpy)
s8i a8, a10, 1 /* store byte 0 */
addi a10, a10, 2 /* advance dst pointer */
bnez a8, .Lsrcaligned
-1: retw
+1: abi_ret
/* dst is word-aligned; src is word-aligned. */
@@ -102,21 +102,21 @@ ENTRY (strcpy)
#endif /* !XCHAL_HAVE_LOOPS */
.Lz3: /* Byte 3 is zero. */
- retw
+ abi_ret
.Lz0: /* Byte 0 is zero. */
#ifdef __XTENSA_EB__
movi a8, 0
#endif
s8i a8, a10, 0
- retw
+ abi_ret
.Lz1: /* Byte 1 is zero. */
#ifdef __XTENSA_EB__
extui a8, a8, 16, 16
#endif
s16i a8, a10, 0
- retw
+ abi_ret
.Lz2: /* Byte 2 is zero. */
#ifdef __XTENSA_EB__
@@ -125,7 +125,7 @@ ENTRY (strcpy)
s16i a8, a10, 0
movi a8, 0
s8i a8, a10, 2
- retw
+ abi_ret
.align 4
/* (2 mod 4) alignment for loop instruction */
@@ -144,6 +144,6 @@ ENTRY (strcpy)
#else
bnez a8, 1b
#endif
-2: retw
+2: abi_ret
libc_hidden_def (strcpy)
diff --git a/libc/string/xtensa/strlen.S b/libc/string/xtensa/strlen.S
index 86fe11390..e1c98c8f0 100644
--- a/libc/string/xtensa/strlen.S
+++ b/libc/string/xtensa/strlen.S
@@ -59,7 +59,7 @@ ENTRY (strlen)
/* Byte 3 is zero. */
addi a3, a3, 3 /* point to zero byte */
sub a2, a3, a2 /* subtract to get length */
- retw
+ abi_ret
/* String is word-aligned. */
@@ -88,16 +88,16 @@ ENTRY (strlen)
.Lz0: /* Byte 0 is zero. */
sub a2, a3, a2 /* subtract to get length */
- retw
+ abi_ret
.Lz1: /* Byte 1 is zero. */
addi a3, a3, 1 /* point to zero byte */
sub a2, a3, a2 /* subtract to get length */
- retw
+ abi_ret
.Lz2: /* Byte 2 is zero. */
addi a3, a3, 2 /* point to zero byte */
sub a2, a3, a2 /* subtract to get length */
- retw
+ abi_ret
libc_hidden_def (strlen)
diff --git a/libc/string/xtensa/strncpy.S b/libc/string/xtensa/strncpy.S
index 115d44cf8..aa8db5da1 100644
--- a/libc/string/xtensa/strncpy.S
+++ b/libc/string/xtensa/strncpy.S
@@ -67,7 +67,7 @@ __strncpy_aux:
j .Lfill
.Lret:
- retw
+ abi_ret
ENTRY (strncpy)
@@ -129,7 +129,7 @@ ENTRY (strncpy)
addi a10, a10, 1
bnez a4, .Lfillcleanup
-2: retw
+2: abi_ret
.Lfill1mod2: /* dst address is odd */
s8i a9, a10, 0 /* store byte 0 */
@@ -235,6 +235,6 @@ ENTRY (strncpy)
#endif
2: j .Lfill
-3: retw
+3: abi_ret
libc_hidden_def (strncpy)
diff --git a/libc/sysdeps/linux/xtensa/__longjmp.S b/libc/sysdeps/linux/xtensa/__longjmp.S
index 4d55906db..acc0b4ff2 100644
--- a/libc/sysdeps/linux/xtensa/__longjmp.S
+++ b/libc/sysdeps/linux/xtensa/__longjmp.S
@@ -48,6 +48,7 @@
ENTRY (__longjmp)
+#if defined(__XTENSA_WINDOWED_ABI__)
/* Invalidate all but the current window. Reading and writing
special registers WINDOWBASE and WINDOWSTART are
privileged operations, so user processes must call the
@@ -120,6 +121,22 @@ ENTRY (__longjmp)
movnez a2, a3, a3
retw
+#elif defined(__XTENSA_CALL0_ABI__)
+ l32i a0, a2, 0
+ l32i a1, a2, 4
+ l32i a12, a2, 8
+ l32i a13, a2, 12
+ l32i a14, a2, 16
+ l32i a15, a2, 20
+
+ /* Return v ? v : 1. */
+ movi a2, 1
+ movnez a2, a3, a3
+
+ ret
+#else
+#error Unsupported Xtensa ABI
+#endif
END (__longjmp)
libc_hidden_def (__longjmp)
diff --git a/libc/sysdeps/linux/xtensa/bits/setjmp.h b/libc/sysdeps/linux/xtensa/bits/setjmp.h
index 183fa3e64..5d3e5509e 100644
--- a/libc/sysdeps/linux/xtensa/bits/setjmp.h
+++ b/libc/sysdeps/linux/xtensa/bits/setjmp.h
@@ -23,6 +23,7 @@
# error "Never include <bits/setjmp.h> directly; use <setjmp.h> instead."
#endif
+#if defined(__XTENSA_WINDOWED_ABI__)
/* The jmp_buf structure for Xtensa holds the following (where "proc"
is the procedure that calls setjmp): 4-12 registers from the window
of proc, the 4 words from the save area at proc's $sp (in case a
@@ -30,5 +31,13 @@
proc. Everything else is saved on the stack in the normal save areas. */
typedef int __jmp_buf[17];
+#elif defined(__XTENSA_CALL0_ABI__)
+/* The jmp_buf structure for Xtensa Call0 ABI holds the return address,
+ the stack pointer and callee-saved registers (a12 - a15). */
+
+typedef int __jmp_buf[6];
+#else
+#error Unsupported Xtensa ABI
+#endif
#endif /* bits/setjmp.h */
diff --git a/libc/sysdeps/linux/xtensa/clone.S b/libc/sysdeps/linux/xtensa/clone.S
index 34d68a875..88cd6c1c3 100644
--- a/libc/sysdeps/linux/xtensa/clone.S
+++ b/libc/sysdeps/linux/xtensa/clone.S
@@ -51,7 +51,7 @@ ENTRY (__clone)
mov a8, a6 /* use a8 as a temp */
mov a6, a4
mov a4, a8
- l32i a8, a1, 16 /* child_tid */
+ l32i a8, a1, FRAMESIZE /* child_tid */
movi a2, SYS_ify(clone)
/* syscall(NR_clone,clone_flags, usp, parent_tid, child_tls, child_tid)
@@ -65,7 +65,7 @@ ENTRY (__clone)
/* fall through for parent */
.Lpseudo_end:
- retw
+ abi_ret
.Leinval:
movi a2, -EINVAL
@@ -94,17 +94,26 @@ ENTRY (__clone)
/* start child thread */
movi a0, 0 /* terminate the stack frame */
+
+#if defined(__XTENSA_WINDOWED_ABI__)
mov a6, a9 /* load up the 'arg' parameter */
callx4 a7 /* call the user's function */
/* Call _exit. Note that any return parameter from the user's
function in a6 is seen as inputs to _exit. */
-#ifdef PIC
- movi a2, _exit@PLT
+ movi a2, JUMPTARGET(_exit)
+ callx4 a2
+#elif defined(__XTENSA_CALL0_ABI__)
+ mov a2, a9 /* load up the 'arg' parameter */
+ callx0 a7 /* call the user's function */
+
+ /* Call _exit. Note that any return parameter from the user's
+ function in a2 is seen as inputs to _exit. */
+ movi a0, JUMPTARGET(_exit)
+ callx0 a0
#else
- movi a2, _exit
+#error Unsupported Xtensa ABI
#endif
- callx4 a2
PSEUDO_END (__clone)
diff --git a/libc/sysdeps/linux/xtensa/crt1.S b/libc/sysdeps/linux/xtensa/crt1.S
index 025ebd070..efbe264c0 100644
--- a/libc/sysdeps/linux/xtensa/crt1.S
+++ b/libc/sysdeps/linux/xtensa/crt1.S
@@ -76,6 +76,7 @@
.global _start
.type _start, @function
_start:
+#if defined(__XTENSA_WINDOWED_ABI__)
/* Clear a0 to obviously mark the outermost frame. */
movi a0, 0
@@ -104,6 +105,35 @@ _start:
But let the libc call main. */
movi a4, __uClibc_main
callx4 a4
+#elif defined(__XTENSA_CALL0_ABI__)
+ /* Setup the shared library termination function. */
+ mov a7, a2
+
+ /* Load up the user's main function. */
+ movi a2, main
+
+ /* Extract the arguments as encoded on the stack and set up
+ the arguments for `main': argc, argv. envp will be determined
+ later in __uClibc_main. */
+ l32i a3, a1, 0 /* Load the argument count. */
+ addi a4, a1, 4 /* Compute the argv pointer. */
+
+ /* Push address of our own entry points to .fini and .init. */
+ movi a5, _init
+ movi a6, _fini
+
+ /* Provide the highest stack address to the user code (for stacks
+ which grow downwards). Note that we destroy the stack version
+ of argc here. */
+ s32i a1, a1, 0
+
+ /* Call the user's main function, and exit with its value.
+ But let the libc call main. */
+ movi a0, __uClibc_main
+ callx0 a0
+#else
+#error Unsupported Xtensa ABI
+#endif
/* Crash if somehow `exit' does return. */
ill
diff --git a/libc/sysdeps/linux/xtensa/crti.S b/libc/sysdeps/linux/xtensa/crti.S
index a01c02c9f..ba804eb45 100644
--- a/libc/sysdeps/linux/xtensa/crti.S
+++ b/libc/sysdeps/linux/xtensa/crti.S
@@ -5,12 +5,25 @@
.global _init
.type _init, @function
_init:
+#if defined(__XTENSA_WINDOWED_ABI__)
entry sp, 48
-
+#elif defined(__XTENSA_CALL0_ABI__)
+ addi sp, sp, -16
+ s32i a0, sp, 0
+#else
+#error Unsupported Xtensa ABI
+#endif
.section .fini
.align 4
.global _fini
.type _fini, @function
_fini:
+#if defined(__XTENSA_WINDOWED_ABI__)
entry sp, 48
+#elif defined(__XTENSA_CALL0_ABI__)
+ addi sp, sp, -16
+ s32i a0, sp, 0
+#else
+#error Unsupported Xtensa ABI
+#endif
diff --git a/libc/sysdeps/linux/xtensa/crtn.S b/libc/sysdeps/linux/xtensa/crtn.S
index ab1a489c5..a3598da1a 100644
--- a/libc/sysdeps/linux/xtensa/crtn.S
+++ b/libc/sysdeps/linux/xtensa/crtn.S
@@ -1,8 +1,23 @@
/* glibc's sysdeps/xtensa/elf/initfini.c used for reference [EPILOG] */
.section .init
+#if defined(__XTENSA_WINDOWED_ABI__)
retw
-
+#elif defined(__XTENSA_CALL0_ABI__)
+ l32i a0, sp, 0
+ addi sp, sp, 16
+ ret
+#else
+#error Unsupported Xtensa ABI
+#endif
.section .fini
+#if defined(__XTENSA_WINDOWED_ABI__)
retw
+#elif defined(__XTENSA_CALL0_ABI__)
+ l32i a0, sp, 0
+ addi sp, sp, 16
+ ret
+#else
+#error Unsupported Xtensa ABI
+#endif
diff --git a/libc/sysdeps/linux/xtensa/mmap.S b/libc/sysdeps/linux/xtensa/mmap.S
index c05036aae..b4dd7c53b 100644
--- a/libc/sysdeps/linux/xtensa/mmap.S
+++ b/libc/sysdeps/linux/xtensa/mmap.S
@@ -48,7 +48,7 @@ ENTRY (__mmap)
bltz a2, SYSCALL_ERROR_LABEL
.Lpseudo_end:
- retw
+ abi_ret
PSEUDO_END (__mmap)
diff --git a/libc/sysdeps/linux/xtensa/setjmp.S b/libc/sysdeps/linux/xtensa/setjmp.S
index bf4691294..862bf6729 100644
--- a/libc/sysdeps/linux/xtensa/setjmp.S
+++ b/libc/sysdeps/linux/xtensa/setjmp.S
@@ -88,6 +88,7 @@ END (setjmp)
ENTRY (__sigsetjmp)
1:
+#if defined(__XTENSA_WINDOWED_ABI__)
/* Flush registers. */
movi a4, __window_spill
callx4 a4
@@ -146,6 +147,22 @@ ENTRY (__sigsetjmp)
callx4 a3
mov a2, a6
retw
+#elif defined(__XTENSA_CALL0_ABI__)
+ s32i a0, a2, 0
+ s32i a1, a2, 4
+ s32i a12, a2, 8
+ s32i a13, a2, 12
+ s32i a14, a2, 16
+ s32i a15, a2, 20
+ mov a12, a2
+ movi a0, __sigjmp_save
+ callx0 a0
+ l32i a0, a12, 0
+ l32i a12, a12, 8
+ ret
+#else
+#error Unsupported Xtensa ABI
+#endif
END(__sigsetjmp)
weak_extern(_setjmp)
diff --git a/libc/sysdeps/linux/xtensa/syscall.S b/libc/sysdeps/linux/xtensa/syscall.S
index 0e1a5d0be..790a8d018 100644
--- a/libc/sysdeps/linux/xtensa/syscall.S
+++ b/libc/sysdeps/linux/xtensa/syscall.S
@@ -26,7 +26,7 @@
*/
ENTRY (syscall)
- l32i a9, a1, 16 /* load extra argument from stack */
+ l32i a9, a1, FRAMESIZE/* load extra argument from stack */
mov a8, a7
mov a7, a3 /* preserve a3 in a7 */
mov a3, a4
@@ -37,5 +37,5 @@ ENTRY (syscall)
movi a4, -4095
bgeu a2, a4, SYSCALL_ERROR_LABEL
.Lpseudo_end:
- retw
+ abi_ret
PSEUDO_END (syscall)
diff --git a/libc/sysdeps/linux/xtensa/sysdep.h b/libc/sysdeps/linux/xtensa/sysdep.h
index 4873a413d..ce2b0a0d6 100644
--- a/libc/sysdeps/linux/xtensa/sysdep.h
+++ b/libc/sysdeps/linux/xtensa/sysdep.h
@@ -28,13 +28,24 @@
#define ASM_TYPE_DIRECTIVE(name, typearg) .type name, typearg
#define ASM_SIZE_DIRECTIVE(name) .size name, . - name
+#if defined(__XTENSA_WINDOWED_ABI__)
+#define abi_entry(reg, frame_size) entry reg, frame_size
+#define abi_ret retw
+#elif defined(__XTENSA_CALL0_ABI__)
+#define abi_entry(reg, frame_size)
+#define abi_ret ret
+#else
+#error Unsupported Xtensa ABI
+#endif
+
+
#define ENTRY(name) \
ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(name); \
ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name), @function); \
.align ALIGNARG(2); \
LITERAL_POSITION; \
C_LABEL(name) \
- entry sp, FRAMESIZE; \
+ abi_entry(sp, FRAMESIZE); \
CALL_MCOUNT
#define HIDDEN_ENTRY(name) \
@@ -44,7 +55,7 @@
.align ALIGNARG(2); \
LITERAL_POSITION; \
C_LABEL(name) \
- entry sp, FRAMESIZE; \
+ abi_entry(sp, FRAMESIZE); \
CALL_MCOUNT
#undef END
@@ -73,7 +84,13 @@
#endif
#ifndef FRAMESIZE
+#if defined(__XTENSA_WINDOWED_ABI__)
#define FRAMESIZE 16
+#elif defined(__XTENSA_CALL0_ABI__)
+#define FRAMESIZE 0
+#else
+#error Unsupported Xtensa ABI
+#endif
#endif
#define CALL_MCOUNT /* Do nothing. */
@@ -118,7 +135,7 @@
END (name)
#undef ret_NOERRNO
-#define ret_NOERRNO retw
+#define ret_NOERRNO abi_ret
/* The function has to return the error code. */
#undef PSEUDO_ERRVAL
@@ -133,7 +150,7 @@
END (name)
#undef ret_ERRVAL
-#define ret_ERRVAL retw
+#define ret_ERRVAL abi_ret
#if defined _LIBC_REENTRANT
# if defined USE___THREAD
@@ -151,6 +168,8 @@
movi a2, -1; \
j .Lpseudo_end;
# else /* !USE___THREAD */
+
+#if defined(__XTENSA_WINDOWED_ABI__)
# define SYSCALL_ERROR_HANDLER \
0: neg a2, a2; \
mov a6, a2; \
@@ -159,6 +178,24 @@
s32i a2, a6, 0; \
movi a2, -1; \
j .Lpseudo_end;
+#elif defined(__XTENSA_CALL0_ABI__)
+# define SYSCALL_ERROR_HANDLER \
+0: neg a2, a2; \
+ addi a1, a1, -16; \
+ s32i a0, a1, 0; \
+ s32i a2, a1, 4; \
+ movi a0, __errno_location@PLT; \
+ callx0 a0; \
+ l32i a0, a1, 0; \
+ l32i a3, a1, 4; \
+ addi a1, a1, 16; \
+ s32i a3, a2, 0; \
+ movi a2, -1; \
+ j .Lpseudo_end;
+#else
+#error Unsupported Xtensa ABI
+#endif
+
# endif /* !USE___THREAD */
#else /* !_LIBC_REENTRANT */
#define SYSCALL_ERROR_HANDLER \
diff --git a/libc/sysdeps/linux/xtensa/vfork.S b/libc/sysdeps/linux/xtensa/vfork.S
index 6aced0a50..b8db5c1a1 100644
--- a/libc/sysdeps/linux/xtensa/vfork.S
+++ b/libc/sysdeps/linux/xtensa/vfork.S
@@ -51,6 +51,8 @@
HIDDEN_ENTRY (__vfork)
+
+#if defined(__XTENSA_WINDOWED_ABI__)
.literal .Ljumptable, 0, .L4, .L8, .L12
mov a3, a0 # move return address out of the way
@@ -163,6 +165,27 @@ HIDDEN_ENTRY (__vfork)
PSEUDO_END (__vfork)
.Lpseudo_end:
retw
+#elif defined(__XTENSA_CALL0_ABI__)
+ SAVE_PID(a5, a8, a3, a4)
+
+ /* Use syscall 'clone'. Set new stack pointer to the same address. */
+ movi a2, SYS_ify (clone)
+ movi a3, 0
+ movi a6, CLONE_VM | CLONE_VFORK | SIGCHLD
+ syscall
+
+ RESTORE_PID(a5, a8, a2)
+
+ movi a3, -4096
+ bgeu a2, a3, 1f
+ ret
+1:
+ PSEUDO_END (__vfork)
+.Lpseudo_end:
+ ret
+#else
+#error Unsupported Xtensa ABI
+#endif
weak_alias (__vfork, vfork)
libc_hidden_def(vfork)
diff --git a/libc/sysdeps/linux/xtensa/windowspill.S b/libc/sysdeps/linux/xtensa/windowspill.S
index 4167b2877..013025648 100644
--- a/libc/sysdeps/linux/xtensa/windowspill.S
+++ b/libc/sysdeps/linux/xtensa/windowspill.S
@@ -18,6 +18,7 @@
#include <bits/xtensa-config.h>
+#ifdef __XTENSA_WINDOWED_ABI__
.text
.align 4
.literal_position
@@ -93,3 +94,5 @@ __window_spill:
#endif
#endif
retw
+
+#endif