summaryrefslogtreecommitdiff
path: root/libc/sysdeps/linux/xtensa
diff options
context:
space:
mode:
Diffstat (limited to 'libc/sysdeps/linux/xtensa')
-rw-r--r--libc/sysdeps/linux/xtensa/Makefile.arch8
-rw-r--r--libc/sysdeps/linux/xtensa/__longjmp.S28
-rw-r--r--libc/sysdeps/linux/xtensa/bits/atomic.h232
-rw-r--r--libc/sysdeps/linux/xtensa/bits/fcntl.h13
-rw-r--r--libc/sysdeps/linux/xtensa/bits/ipc.h5
-rw-r--r--libc/sysdeps/linux/xtensa/bits/kernel_stat.h24
-rw-r--r--libc/sysdeps/linux/xtensa/bits/kernel_types.h2
-rw-r--r--libc/sysdeps/linux/xtensa/bits/mathdef.h5
-rw-r--r--libc/sysdeps/linux/xtensa/bits/mman.h7
-rw-r--r--libc/sysdeps/linux/xtensa/bits/msq.h5
-rw-r--r--libc/sysdeps/linux/xtensa/bits/setjmp.h23
-rw-r--r--libc/sysdeps/linux/xtensa/bits/shm.h5
-rw-r--r--libc/sysdeps/linux/xtensa/bits/sigcontext.h40
-rw-r--r--libc/sysdeps/linux/xtensa/bits/sigcontextinfo.h5
-rw-r--r--libc/sysdeps/linux/xtensa/bits/stackinfo.h5
-rw-r--r--libc/sysdeps/linux/xtensa/bits/stat.h14
-rw-r--r--libc/sysdeps/linux/xtensa/bits/syscalls.h61
-rw-r--r--libc/sysdeps/linux/xtensa/bits/uClibc_arch_features.h14
-rw-r--r--libc/sysdeps/linux/xtensa/bits/uClibc_page.h31
-rw-r--r--libc/sysdeps/linux/xtensa/bits/wordsize.h5
-rw-r--r--libc/sysdeps/linux/xtensa/bits/xtensa-config.h11
-rw-r--r--libc/sysdeps/linux/xtensa/brk.c6
-rw-r--r--libc/sysdeps/linux/xtensa/clone.S111
-rw-r--r--libc/sysdeps/linux/xtensa/crt1.S35
-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/fork.c24
-rw-r--r--libc/sysdeps/linux/xtensa/jmpbuf-offsets.h20
-rw-r--r--libc/sysdeps/linux/xtensa/jmpbuf-unwind.h23
-rw-r--r--libc/sysdeps/linux/xtensa/mmap.S7
-rw-r--r--libc/sysdeps/linux/xtensa/posix_fadvise.c29
-rw-r--r--libc/sysdeps/linux/xtensa/posix_fadvise64.c39
-rw-r--r--libc/sysdeps/linux/xtensa/pread_write.c193
-rw-r--r--libc/sysdeps/linux/xtensa/setjmp.S174
-rw-r--r--libc/sysdeps/linux/xtensa/sigaction.c53
-rw-r--r--libc/sysdeps/linux/xtensa/sigrestorer.S6
-rw-r--r--libc/sysdeps/linux/xtensa/sys/procfs.h5
-rw-r--r--libc/sysdeps/linux/xtensa/sys/ptrace.h156
-rw-r--r--libc/sysdeps/linux/xtensa/sys/ucontext.h5
-rw-r--r--libc/sysdeps/linux/xtensa/sys/user.h20
-rw-r--r--libc/sysdeps/linux/xtensa/syscall.S9
-rw-r--r--libc/sysdeps/linux/xtensa/sysdep.h99
-rw-r--r--libc/sysdeps/linux/xtensa/vfork.S137
-rw-r--r--libc/sysdeps/linux/xtensa/windowspill.S34
44 files changed, 886 insertions, 874 deletions
diff --git a/libc/sysdeps/linux/xtensa/Makefile.arch b/libc/sysdeps/linux/xtensa/Makefile.arch
index f54886444..b9b6b87d5 100644
--- a/libc/sysdeps/linux/xtensa/Makefile.arch
+++ b/libc/sysdeps/linux/xtensa/Makefile.arch
@@ -5,10 +5,10 @@
# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
#
-CSRC := brk.c fork.c posix_fadvise.c posix_fadvise64.c pread_write.c \
- sigaction.c __syscall_error.c
+CSRC-y := brk.c sigaction.c __syscall_error.c
-SSRC := bsd-_setjmp.S bsd-setjmp.S setjmp.S clone.S \
+SSRC-y := bsd-_setjmp.S bsd-setjmp.S setjmp.S clone.S \
sigrestorer.S syscall.S mmap.S windowspill.S __longjmp.S vfork.S
-include $(top_srcdir)libc/sysdeps/linux/Makefile.commonarch
+CSRC-$(if $(UCLIBC_HAS_THREADS_NATIVE),,y) += fork.c
+SSRC-$(if $(UCLIBC_HAS_THREADS_NATIVE),,y) += clone.S
diff --git a/libc/sysdeps/linux/xtensa/__longjmp.S b/libc/sysdeps/linux/xtensa/__longjmp.S
index 0fa939095..acc0b4ff2 100644
--- a/libc/sysdeps/linux/xtensa/__longjmp.S
+++ b/libc/sysdeps/linux/xtensa/__longjmp.S
@@ -14,9 +14,8 @@
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, write to the Free
- Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
- Boston, MA 02110-1301, USA. */
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
/* This implementation relies heavily on the Xtensa register window
mechanism. Setjmp flushes all the windows except its own to the
@@ -49,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
@@ -84,7 +84,7 @@ ENTRY (__longjmp)
slli a4, a7, 4
sub a6, a8, a4
addi a5, a2, 16
- addi a8, a8, -16 // a8 = end of register overflow area
+ addi a8, a8, -16 /* a8 = end of register overflow area */
.Lljloop:
l32i a7, a5, 0
l32i a4, a5, 4
@@ -105,8 +105,8 @@ ENTRY (__longjmp)
case the contents were moved by an alloca after calling
setjmp. This is a bit paranoid but it doesn't cost much. */
- l32i a7, a2, 4 // load the target stack pointer
- addi a7, a7, -16 // find the destination save area
+ l32i a7, a2, 4 /* load the target stack pointer */
+ addi a7, a7, -16 /* find the destination save area */
l32i a4, a2, 48
l32i a5, a2, 52
s32i a4, a7, 0
@@ -121,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/atomic.h b/libc/sysdeps/linux/xtensa/bits/atomic.h
new file mode 100644
index 000000000..b2be547f0
--- /dev/null
+++ b/libc/sysdeps/linux/xtensa/bits/atomic.h
@@ -0,0 +1,232 @@
+/* Copyright (C) 2012 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/>. */
+
+#ifndef _BITS_ATOMIC_H
+#define _BITS_ATOMIC_H 1
+
+#include <inttypes.h>
+
+typedef int32_t atomic32_t;
+typedef uint32_t uatomic32_t;
+typedef int_fast32_t atomic_fast32_t;
+typedef uint_fast32_t uatomic_fast32_t;
+
+typedef int64_t atomic64_t;
+typedef uint64_t uatomic64_t;
+typedef int_fast64_t atomic_fast64_t;
+typedef uint_fast64_t uatomic_fast64_t;
+
+typedef intptr_t atomicptr_t;
+typedef uintptr_t uatomicptr_t;
+typedef intmax_t atomic_max_t;
+typedef uintmax_t uatomic_max_t;
+
+
+/* Xtensa has only a 32-bit form of a store-conditional instruction. */
+
+#define __arch_compare_and_exchange_bool_8_acq(mem, newval, oldval) \
+ (abort (), 0)
+
+#define __arch_compare_and_exchange_bool_16_acq(mem, newval, oldval) \
+ (abort (), 0)
+
+#define __arch_compare_and_exchange_bool_8_rel(mem, newval, oldval) \
+ (abort (), 0)
+
+#define __arch_compare_and_exchange_bool_16_rel(mem, newval, oldval) \
+ (abort (), 0)
+
+/* Atomically store NEWVAL in *MEM if *MEM is equal to OLDVAL.
+ Return the old *MEM value. */
+
+#define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval) \
+ ({__typeof__(*(mem)) __tmp, __value; \
+ __asm__ __volatile__( \
+ "1: l32i %1, %2, 0 \n" \
+ " bne %1, %4, 2f \n" \
+ " wsr %1, SCOMPARE1 \n" \
+ " mov %0, %1 \n" \
+ " mov %1, %3 \n" \
+ " s32c1i %1, %2, 0 \n" \
+ " bne %0, %1, 1b \n" \
+ "2: \n" \
+ : "=&a" (__value), "=&a" (__tmp) \
+ : "a" (mem), "a" (newval), "a" (oldval) \
+ : "memory" ); \
+ __tmp; \
+ })
+
+/* Atomically store NEWVAL in *MEM if *MEM is equal to OLDVAL.
+ Return zero if *MEM was changed or non-zero if no exchange happened. */
+
+#define __arch_compare_and_exchange_bool_32_acq(mem, newval, oldval) \
+ ({__typeof__(*(mem)) __tmp, __value; \
+ __asm__ __volatile__( \
+ "1: l32i %0, %2, 0 \n" \
+ " sub %1, %4, %0 \n" \
+ " bnez %1, 2f \n" \
+ " wsr %0, SCOMPARE1 \n" \
+ " mov %1, %3 \n" \
+ " s32c1i %1, %2, 0 \n" \
+ " bne %0, %1, 1b \n" \
+ " movi %1, 0 \n" \
+ "2: \n" \
+ : "=&a" (__value), "=&a" (__tmp) \
+ : "a" (mem), "a" (newval), "a" (oldval) \
+ : "memory" ); \
+ __tmp != 0; \
+ })
+
+/* Store NEWVALUE in *MEM and return the old value. */
+
+#define __arch_exchange_32_acq(mem, newval) \
+ ({__typeof__(*(mem)) __tmp, __value; \
+ __asm__ __volatile__( \
+ "1: l32i %0, %2, 0 \n" \
+ " wsr %0, SCOMPARE1 \n" \
+ " mov %1, %3 \n" \
+ " s32c1i %1, %2, 0 \n" \
+ " bne %0, %1, 1b \n" \
+ : "=&a" (__value), "=&a" (__tmp) \
+ : "a" (mem), "a" (newval) \
+ : "memory" ); \
+ __tmp; \
+ })
+
+/* Add VALUE to *MEM and return the old value of *MEM. */
+
+#define __arch_atomic_exchange_and_add_32(mem, value) \
+ ({__typeof__(*(mem)) __tmp, __value; \
+ __asm__ __volatile__( \
+ "1: l32i %0, %2, 0 \n" \
+ " wsr %0, SCOMPARE1 \n" \
+ " add %1, %0, %3 \n" \
+ " s32c1i %1, %2, 0 \n" \
+ " bne %0, %1, 1b \n" \
+ : "=&a" (__value), "=&a" (__tmp) \
+ : "a" (mem), "a" (value) \
+ : "memory" ); \
+ __tmp; \
+ })
+
+/* Subtract VALUE from *MEM and return the old value of *MEM. */
+
+#define __arch_atomic_exchange_and_sub_32(mem, value) \
+ ({__typeof__(*(mem)) __tmp, __value; \
+ __asm__ __volatile__( \
+ "1: l32i %0, %2, 0 \n" \
+ " wsr %0, SCOMPARE1 \n" \
+ " sub %1, %0, %3 \n" \
+ " s32c1i %1, %2, 0 \n" \
+ " bne %0, %1, 1b \n" \
+ : "=&a" (__value), "=&a" (__tmp) \
+ : "a" (mem), "a" (value) \
+ : "memory" ); \
+ __tmp; \
+ })
+
+/* Decrement *MEM if it is > 0, and return the old value. */
+
+#define __arch_atomic_decrement_if_positive_32(mem) \
+ ({__typeof__(*(mem)) __tmp, __value; \
+ __asm__ __volatile__( \
+ "1: l32i %0, %2, 0 \n" \
+ " blti %0, 1, 2f \n" \
+ " wsr %0, SCOMPARE1 \n" \
+ " addi %1, %0, -1 \n" \
+ " s32c1i %1, %2, 0 \n" \
+ " bne %0, %1, 1b \n" \
+ "2: \n" \
+ : "=&a" (__value), "=&a" (__tmp) \
+ : "a" (mem) \
+ : "memory" ); \
+ __value; \
+ })
+
+
+/* These are the preferred public interfaces: */
+
+#define atomic_compare_and_exchange_val_acq(mem, newval, oldval) \
+ ({ \
+ if (sizeof (*mem) != 4) \
+ abort(); \
+ __arch_compare_and_exchange_val_32_acq(mem, newval, oldval); \
+ })
+
+#define atomic_exchange_acq(mem, newval) \
+ ({ \
+ if (sizeof(*(mem)) != 4) \
+ abort(); \
+ __arch_exchange_32_acq(mem, newval); \
+ })
+
+#define atomic_exchange_and_add(mem, newval) \
+ ({ \
+ if (sizeof(*(mem)) != 4) \
+ abort(); \
+ __arch_atomic_exchange_and_add_32(mem, newval); \
+ })
+
+#define atomic_exchange_and_sub(mem, newval) \
+ ({ \
+ if (sizeof(*(mem)) != 4) \
+ abort(); \
+ __arch_atomic_exchange_and_sub_32(mem, newval); \
+ })
+
+#define atomic_decrement_if_positive(mem) \
+ ({ \
+ if (sizeof(*(mem)) != 4) \
+ abort(); \
+ __arch_atomic_decrement_if_positive_32(mem); \
+ })
+
+
+# define __arch_compare_and_exchange_bool_64_acq(mem, newval, oldval) \
+ (abort (), 0)
+
+# define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \
+ (abort (), (__typeof (*mem)) 0)
+
+# define __arch_compare_and_exchange_bool_64_rel(mem, newval, oldval) \
+ (abort (), 0)
+
+# define __arch_compare_and_exchange_val_64_rel(mem, newval, oldval) \
+ (abort (), (__typeof (*mem)) 0)
+
+# define __arch_atomic_exchange_64_acq(mem, value) \
+ ({ abort (); (*mem) = (value); })
+
+# define __arch_atomic_exchange_64_rel(mem, value) \
+ ({ abort (); (*mem) = (value); })
+
+# define __arch_atomic_exchange_and_add_64(mem, value) \
+ ({ abort (); (*mem) = (value); })
+
+# define __arch_atomic_increment_val_64(mem) \
+ ({ abort (); (*mem)++; })
+
+# define __arch_atomic_decrement_val_64(mem) \
+ ({ abort (); (*mem)--; })
+
+# define __arch_atomic_decrement_if_positive_64(mem) \
+ ({ abort (); (*mem)--; })
+
+
+
+#endif /* _BITS_ATOMIC_H */
+
diff --git a/libc/sysdeps/linux/xtensa/bits/fcntl.h b/libc/sysdeps/linux/xtensa/bits/fcntl.h
index 23de96c02..d21c4e03c 100644
--- a/libc/sysdeps/linux/xtensa/bits/fcntl.h
+++ b/libc/sysdeps/linux/xtensa/bits/fcntl.h
@@ -14,9 +14,8 @@
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, write to the Free
- Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
- Boston, MA 02110-1301, USA. */
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
#ifndef _FCNTL_H
# error "Never use <bits/fcntl.h> directly; include <fcntl.h> instead."
@@ -50,6 +49,8 @@
# define O_DIRECTORY 0200000 /* Must be a directory. */
# define O_NOFOLLOW 0400000 /* Do not follow links. */
# define O_NOATIME 01000000 /* Do not set atime. */
+# define O_CLOEXEC 02000000 /* set close_on_exec */
+# define O_PATH 010000000 /* Resolve pathname but do not open file. */
#endif
/* For now Linux has synchronisity options for data and read operations.
@@ -99,6 +100,8 @@
# define F_NOTIFY 1026 /* Request notfications on a directory. */
# define F_DUPFD_CLOEXEC 1030 /* Duplicate file descriptor with
close-on-exit set on new fd. */
+# define F_SETPIPE_SZ 1031 /* Set pipe page size array. */
+# define F_GETPIPE_SZ 1032 /* Get pipe page size array. */
#endif
/* For F_[GET|SET]FD. */
@@ -186,7 +189,7 @@ struct flock64
#endif
-#ifdef __USE_GNU
+#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__
/* Flags for SYNC_FILE_RANGE. */
# define SYNC_FILE_RANGE_WAIT_BEFORE 1 /* Wait upon writeout of all pages
in the range before performing the
@@ -209,7 +212,7 @@ struct flock64
__BEGIN_DECLS
-#ifdef __USE_GNU
+#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__
/* Provide kernel hint to read ahead. */
extern ssize_t readahead (int __fd, __off64_t __offset, size_t __count)
diff --git a/libc/sysdeps/linux/xtensa/bits/ipc.h b/libc/sysdeps/linux/xtensa/bits/ipc.h
index 481bdcc52..2ad5fc0a2 100644
--- a/libc/sysdeps/linux/xtensa/bits/ipc.h
+++ b/libc/sysdeps/linux/xtensa/bits/ipc.h
@@ -12,9 +12,8 @@
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, write to the Free
- Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
- Boston, MA 02110-1301, USA. */
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
#ifndef _SYS_IPC_H
# error "Never use <bits/ipc.h> directly; include <sys/ipc.h> instead."
diff --git a/libc/sysdeps/linux/xtensa/bits/kernel_stat.h b/libc/sysdeps/linux/xtensa/bits/kernel_stat.h
index 26da9281b..5e4f5c4e5 100644
--- a/libc/sysdeps/linux/xtensa/bits/kernel_stat.h
+++ b/libc/sysdeps/linux/xtensa/bits/kernel_stat.h
@@ -1,16 +1,10 @@
#ifndef _BITS_STAT_STRUCT_H
#define _BITS_STAT_STRUCT_H
-#ifndef _LIBC
-#error bits/kernel_stat.h is for internal uClibc use only!
-#endif
-
/* This file provides whatever this particular arch's kernel thinks
* struct kernel_stat should look like... It turns out each arch has a
* different opinion on the subject... */
-#define STAT_HAVE_NSEC 1
-
struct kernel_stat {
unsigned long st_dev;
unsigned long st_ino;
@@ -22,12 +16,9 @@ struct kernel_stat {
long st_size;
unsigned long st_blksize;
unsigned long st_blocks;
- unsigned long st_atime;
- unsigned long st_atime_nsec;
- unsigned long st_mtime;
- unsigned long st_mtime_nsec;
- unsigned long st_ctime;
- unsigned long st_ctime_nsec;
+ struct timespec st_atim;
+ struct timespec st_mtim;
+ struct timespec st_ctim;
unsigned long __unused4;
unsigned long __unused5;
};
@@ -44,12 +35,9 @@ struct kernel_stat64 {
unsigned long st_blksize; /* Optimal block size for I/O. */
unsigned long __unused2;
unsigned long long st_blocks; /* Number 512-byte blocks allocated. */
- unsigned long st_atime; /* Time of last access. */
- unsigned long st_atime_nsec;
- unsigned long st_mtime; /* Time of last modification. */
- unsigned long st_mtime_nsec;
- unsigned long st_ctime; /* Time of last status change. */
- unsigned long st_ctime_nsec;
+ struct timespec st_atim; /* Time of last access. */
+ struct timespec st_mtim; /* Time of last modification. */
+ struct timespec st_ctim; /* Time of last status change. */
unsigned long __unused4;
unsigned long __unused5;
};
diff --git a/libc/sysdeps/linux/xtensa/bits/kernel_types.h b/libc/sysdeps/linux/xtensa/bits/kernel_types.h
index 44f1075f7..ed38f2e18 100644
--- a/libc/sysdeps/linux/xtensa/bits/kernel_types.h
+++ b/libc/sysdeps/linux/xtensa/bits/kernel_types.h
@@ -33,6 +33,8 @@ typedef unsigned int __kernel_gid32_t;
typedef unsigned short __kernel_old_uid_t;
typedef unsigned short __kernel_old_gid_t;
typedef unsigned short __kernel_old_dev_t;
+typedef long __kernel_long_t;
+typedef unsigned long __kernel_ulong_t;
typedef long long __kernel_loff_t;
/* Beginning in 2.6 kernels, which is the first version that includes the
diff --git a/libc/sysdeps/linux/xtensa/bits/mathdef.h b/libc/sysdeps/linux/xtensa/bits/mathdef.h
index 0177fa9fc..1c73cb255 100644
--- a/libc/sysdeps/linux/xtensa/bits/mathdef.h
+++ b/libc/sysdeps/linux/xtensa/bits/mathdef.h
@@ -13,9 +13,8 @@
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, write to the Free
- Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
- Boston, MA 02110-1301, USA. */
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
#if !defined _MATH_H && !defined _COMPLEX_H
# error "Never use <bits/mathdef.h> directly; include <math.h> instead"
diff --git a/libc/sysdeps/linux/xtensa/bits/mman.h b/libc/sysdeps/linux/xtensa/bits/mman.h
index d3beae6aa..a42e92663 100644
--- a/libc/sysdeps/linux/xtensa/bits/mman.h
+++ b/libc/sysdeps/linux/xtensa/bits/mman.h
@@ -13,9 +13,8 @@
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, write to the Free
- Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
- Boston, MA 02110-1301, USA. */
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
#ifndef _SYS_MMAN_H
# error "Never use <bits/mman.h> directly; include <sys/mman.h> instead."
@@ -64,6 +63,8 @@
# define MAP_NORESERVE 0x0400 /* Don't check for reservations. */
# define MAP_POPULATE 0x10000 /* Populate (prefault) pagetables. */
# define MAP_NONBLOCK 0x20000 /* Do not block on IO. */
+# define MAP_UNINITIALIZED 0x4000000 /* For anonymous mmap, memory could
+ be uninitialized. */
#endif
/* Flags to `msync'. */
diff --git a/libc/sysdeps/linux/xtensa/bits/msq.h b/libc/sysdeps/linux/xtensa/bits/msq.h
index 2eca21e6c..e4f3fa317 100644
--- a/libc/sysdeps/linux/xtensa/bits/msq.h
+++ b/libc/sysdeps/linux/xtensa/bits/msq.h
@@ -12,9 +12,8 @@
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, write to the Free
- Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
- Boston, MA 02110-1301, USA. */
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
#ifndef _SYS_MSG_H
# error "Never use <bits/msq.h> directly; include <sys/msg.h> instead."
diff --git a/libc/sysdeps/linux/xtensa/bits/setjmp.h b/libc/sysdeps/linux/xtensa/bits/setjmp.h
index 1bc4896c8..5d3e5509e 100644
--- a/libc/sysdeps/linux/xtensa/bits/setjmp.h
+++ b/libc/sysdeps/linux/xtensa/bits/setjmp.h
@@ -12,9 +12,8 @@
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, write to the Free
- Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
- Boston, MA 02110-1301, USA. */
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
/* Define the machine-dependent type `jmp_buf'. Xtensa version. */
#ifndef _BITS_SETJMP_H
@@ -24,23 +23,21 @@
# 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
subsequent alloca in proc moves $sp), and the return address within
proc. Everything else is saved on the stack in the normal save areas. */
-#ifndef _ASM
typedef int __jmp_buf[17];
-#endif
-
-#define JB_SP 1
-#define JB_PC 16
+#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). */
-/* Test if longjmp to JMPBUF would unwind the frame containing a local
- variable at ADDRESS. */
-
-#define _JMPBUF_UNWINDS(jmpbuf, address) \
- ((void *) (address) < (void *) (jmpbuf)[JB_SP])
+typedef int __jmp_buf[6];
+#else
+#error Unsupported Xtensa ABI
+#endif
#endif /* bits/setjmp.h */
diff --git a/libc/sysdeps/linux/xtensa/bits/shm.h b/libc/sysdeps/linux/xtensa/bits/shm.h
index de41d0d99..d288a1cca 100644
--- a/libc/sysdeps/linux/xtensa/bits/shm.h
+++ b/libc/sysdeps/linux/xtensa/bits/shm.h
@@ -13,9 +13,8 @@
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, write to the Free
- Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
- Boston, MA 02110-1301, USA. */
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
#ifndef _SYS_SHM_H
# error "Never include <bits/shm.h> directly; use <sys/shm.h> instead."
diff --git a/libc/sysdeps/linux/xtensa/bits/sigcontext.h b/libc/sysdeps/linux/xtensa/bits/sigcontext.h
new file mode 100644
index 000000000..c0af295f9
--- /dev/null
+++ b/libc/sysdeps/linux/xtensa/bits/sigcontext.h
@@ -0,0 +1,40 @@
+/* Copyright (C) 2012 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/>. */
+
+#if !defined _SIGNAL_H && !defined _SYS_UCONTEXT_H
+# error "Never use <bits/sigcontext.h> directly; include <signal.h> instead."
+#endif
+
+#ifndef _BITS_SIGCONTEXT_H
+#define _BITS_SIGCONTEXT_H 1
+
+struct sigcontext
+{
+ unsigned long sc_pc;
+ unsigned long sc_ps;
+ unsigned long sc_lbeg;
+ unsigned long sc_lend;
+ unsigned long sc_lcount;
+ unsigned long sc_sar;
+ unsigned long sc_acclo;
+ unsigned long sc_acchi;
+ unsigned long sc_a[16];
+ void *sc_xtregs;
+};
+
+#endif /* _BITS_SIGCONTEXT_H */
+
diff --git a/libc/sysdeps/linux/xtensa/bits/sigcontextinfo.h b/libc/sysdeps/linux/xtensa/bits/sigcontextinfo.h
index 8f3301c9a..39ad5f689 100644
--- a/libc/sysdeps/linux/xtensa/bits/sigcontextinfo.h
+++ b/libc/sysdeps/linux/xtensa/bits/sigcontextinfo.h
@@ -12,9 +12,8 @@
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, write to the Free
- Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
- Boston, MA 02110-1301, USA. */
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
/* Also see register-dump.h, where we spill live registers to the
stack so that we can trace the stack backward. */
diff --git a/libc/sysdeps/linux/xtensa/bits/stackinfo.h b/libc/sysdeps/linux/xtensa/bits/stackinfo.h
index 50ddf2514..6ecdd69ba 100644
--- a/libc/sysdeps/linux/xtensa/bits/stackinfo.h
+++ b/libc/sysdeps/linux/xtensa/bits/stackinfo.h
@@ -12,9 +12,8 @@
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, write to the Free
- Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
- Boston, MA 02110-1301, USA. */
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
/* This file contains a bit of information about the stack allocation
of the processor. */
diff --git a/libc/sysdeps/linux/xtensa/bits/stat.h b/libc/sysdeps/linux/xtensa/bits/stat.h
index c6debc894..c61b188b7 100644
--- a/libc/sysdeps/linux/xtensa/bits/stat.h
+++ b/libc/sysdeps/linux/xtensa/bits/stat.h
@@ -12,9 +12,8 @@
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, write to the Free
- Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
- Boston, MA 02110-1301, USA. */
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
#ifndef _SYS_STAT_H
# error "Never include <bits/stat.h> directly; use <sys/stat.h> instead."
@@ -55,7 +54,7 @@ struct stat
unsigned long __pad2;
__blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */
#endif
-#if 0 /*def __USE_MISC*/
+#ifdef __USE_MISC
/* Nanosecond resolution timestamps are stored in a format
equivalent to 'struct timespec'. This is the type used
whenever possible but the Unix namespace rules do not allow the
@@ -95,7 +94,7 @@ struct stat64
unsigned long __pad2;
__blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */
-#if 0 /*def __USE_MISC*/
+#ifdef __USE_MISC
/* Nanosecond resolution timestamps are stored in a format
equivalent to 'struct timespec'. This is the type used
whenever possible but the Unix namespace rules do not allow the
@@ -151,3 +150,8 @@ struct stat64
#define __S_IREAD 0400 /* Read by owner. */
#define __S_IWRITE 0200 /* Write by owner. */
#define __S_IEXEC 0100 /* Execute by owner. */
+
+#ifdef __USE_ATFILE
+# define UTIME_NOW ((1l << 30) - 1l)
+# define UTIME_OMIT ((1l << 30) - 2l)
+#endif
diff --git a/libc/sysdeps/linux/xtensa/bits/syscalls.h b/libc/sysdeps/linux/xtensa/bits/syscalls.h
index a59a8052a..7e900c590 100644
--- a/libc/sysdeps/linux/xtensa/bits/syscalls.h
+++ b/libc/sysdeps/linux/xtensa/bits/syscalls.h
@@ -9,8 +9,6 @@
glibc .../sysdeps/unix/sysv/linux/xtensa/sysdep.h
*/
-#define SYS_ify(syscall_name) __NR_##syscall_name
-
#ifdef __ASSEMBLER__
/* The register layout upon entering the function is:
@@ -74,67 +72,16 @@
/* Define a macro which expands into the inline wrapper code for a system
call. */
-#undef INLINE_SYSCALL
-#define INLINE_SYSCALL(name, nr, args...) \
- ({ unsigned long resultvar = INTERNAL_SYSCALL (name, , nr, args); \
- if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (resultvar, ), 0)) \
- { \
- __set_errno (INTERNAL_SYSCALL_ERRNO (resultvar, )); \
- resultvar = (unsigned long) -1; \
- } \
- (long) resultvar; })
-
-#undef INTERNAL_SYSCALL_DECL
-#define INTERNAL_SYSCALL_DECL(err) do { } while (0)
-
#define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \
+(__extension__ \
({ LD_ARG(2, name); \
LD_ARGS_##nr(args); \
__asm__ __volatile__ ("syscall\n" \
: "=a" (_a2) \
: ASM_ARGS_##nr \
: "memory"); \
- (long) _a2; })
-
-#undef INTERNAL_SYSCALL
-#define INTERNAL_SYSCALL(name, err, nr, args...) \
- INTERNAL_SYSCALL_NCS (__NR_##name, err, nr, ##args)
-
-#undef INTERNAL_SYSCALL_ERROR_P
-#define INTERNAL_SYSCALL_ERROR_P(val, err) \
- ((unsigned long) (val) >= -4095L)
-
-#undef INTERNAL_SYSCALL_ERRNO
-#define INTERNAL_SYSCALL_ERRNO(val, err) (-(val))
-
-#define _syscall0(args...) SYSCALL_FUNC (0, args)
-#define _syscall1(args...) SYSCALL_FUNC (1, args)
-#define _syscall2(args...) SYSCALL_FUNC (2, args)
-#define _syscall3(args...) SYSCALL_FUNC (3, args)
-#define _syscall4(args...) SYSCALL_FUNC (4, args)
-#define _syscall5(args...) SYSCALL_FUNC (5, args)
-#define _syscall6(args...) SYSCALL_FUNC (6, args)
-
-#define C_DECL_ARGS_0() void
-#define C_DECL_ARGS_1(t, v) t v
-#define C_DECL_ARGS_2(t, v, args...) t v, C_DECL_ARGS_1(args)
-#define C_DECL_ARGS_3(t, v, args...) t v, C_DECL_ARGS_2(args)
-#define C_DECL_ARGS_4(t, v, args...) t v, C_DECL_ARGS_3(args)
-#define C_DECL_ARGS_5(t, v, args...) t v, C_DECL_ARGS_4(args)
-#define C_DECL_ARGS_6(t, v, args...) t v, C_DECL_ARGS_5(args)
-
-#define C_ARGS_0()
-#define C_ARGS_1(t, v) v
-#define C_ARGS_2(t, v, args...) v, C_ARGS_1 (args)
-#define C_ARGS_3(t, v, args...) v, C_ARGS_2 (args)
-#define C_ARGS_4(t, v, args...) v, C_ARGS_3 (args)
-#define C_ARGS_5(t, v, args...) v, C_ARGS_4 (args)
-#define C_ARGS_6(t, v, args...) v, C_ARGS_5 (args)
-
-#define SYSCALL_FUNC(nargs, type, name, args...) \
-type name (C_DECL_ARGS_##nargs (args)) { \
- return (type) INLINE_SYSCALL (name, nargs, C_ARGS_##nargs (args)); \
-}
-
+ (long) _a2; \
+ }) \
+)
#endif /* not __ASSEMBLER__ */
#endif /* _BITS_SYSCALLS_H */
diff --git a/libc/sysdeps/linux/xtensa/bits/uClibc_arch_features.h b/libc/sysdeps/linux/xtensa/bits/uClibc_arch_features.h
index d6a99b4d2..a15744c2f 100644
--- a/libc/sysdeps/linux/xtensa/bits/uClibc_arch_features.h
+++ b/libc/sysdeps/linux/xtensa/bits/uClibc_arch_features.h
@@ -11,8 +11,8 @@
/* can your target use syscall6() for mmap ? */
#define __UCLIBC_MMAP_HAS_6_ARGS__
-/* does your target use syscall4() for truncate64 ? (32bit arches only) */
-#define __UCLIBC_TRUNCATE64_HAS_4_ARGS__
+/* does your target align 64bit values in register pairs ? (32bit arches only) */
+#define __UCLIBC_SYSCALL_ALIGN_64BIT__
/* does your target have a broken create_module() ? */
#undef __UCLIBC_BROKEN_CREATE_MODULE__
@@ -23,19 +23,19 @@
/* does your target have an asm .set ? */
#define __UCLIBC_HAVE_ASM_SET_DIRECTIVE__
-/* define if target doesn't like .global */
-#undef __UCLIBC_ASM_GLOBAL_DIRECTIVE__
-
/* define if target supports .weak */
#define __UCLIBC_HAVE_ASM_WEAK_DIRECTIVE__
/* define if target supports .weakext */
#undef __UCLIBC_HAVE_ASM_WEAKEXT_DIRECTIVE__
-/* needed probably only for ppc64 */
-#undef __UCLIBC_HAVE_ASM_GLOBAL_DOT_NAME__
+/* define if target supports CFI pseudo ops */
+#undef __UCLIBC_HAVE_ASM_CFI_DIRECTIVES__
/* define if target supports IEEE signed zero floats */
#define __UCLIBC_HAVE_SIGNED_ZERO__
+/* only weird assemblers generally need this */
+#undef __UCLIBC_ASM_LINE_SEP__
+
#endif /* _BITS_UCLIBC_ARCH_FEATURES_H */
diff --git a/libc/sysdeps/linux/xtensa/bits/uClibc_page.h b/libc/sysdeps/linux/xtensa/bits/uClibc_page.h
deleted file mode 100644
index 74a9f60ba..000000000
--- a/libc/sysdeps/linux/xtensa/bits/uClibc_page.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/* Copyright (C) 2004 Erik Andersen
- *
- * This 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, write to the Free
- * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- * 02111-1307 USA.
- */
-
-/* Supply an architecture specific value for PAGE_SIZE and friends. */
-
-#ifndef _UCLIBC_PAGE_H
-#define _UCLIBC_PAGE_H
-
-#include <bits/xtensa-config.h>
-
-/* PAGE_SHIFT determines the page size -- in this case 4096 */
-#define PAGE_SHIFT XCHAL_MMU_MIN_PTE_PAGE_SIZE
-#define PAGE_SIZE (1UL << PAGE_SHIFT)
-#define PAGE_MASK (~(PAGE_SIZE-1))
-
-#endif /* _UCLIBC_PAGE_H */
diff --git a/libc/sysdeps/linux/xtensa/bits/wordsize.h b/libc/sysdeps/linux/xtensa/bits/wordsize.h
index ba643b60a..ca82fd7d4 100644
--- a/libc/sysdeps/linux/xtensa/bits/wordsize.h
+++ b/libc/sysdeps/linux/xtensa/bits/wordsize.h
@@ -12,8 +12,7 @@
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, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 USA. */
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
#define __WORDSIZE 32
diff --git a/libc/sysdeps/linux/xtensa/bits/xtensa-config.h b/libc/sysdeps/linux/xtensa/bits/xtensa-config.h
index 34cf28c0a..2e60af936 100644
--- a/libc/sysdeps/linux/xtensa/bits/xtensa-config.h
+++ b/libc/sysdeps/linux/xtensa/bits/xtensa-config.h
@@ -14,9 +14,8 @@
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, write to the Free
- Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
- Boston, MA 02110-1301, USA. */
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
#ifndef XTENSA_CONFIG_H
#define XTENSA_CONFIG_H
@@ -44,10 +43,4 @@
#undef XCHAL_NUM_AREGS
#define XCHAL_NUM_AREGS 64
-/* Set a default page size. This is currently needed when bootstrapping
- the runtime linker. See comments in dl-machine.h where this is used. */
-
-#undef XCHAL_MMU_MIN_PTE_PAGE_SIZE
-#define XCHAL_MMU_MIN_PTE_PAGE_SIZE 12
-
#endif /* !XTENSA_CONFIG_H */
diff --git a/libc/sysdeps/linux/xtensa/brk.c b/libc/sysdeps/linux/xtensa/brk.c
index 51f610b70..512810409 100644
--- a/libc/sysdeps/linux/xtensa/brk.c
+++ b/libc/sysdeps/linux/xtensa/brk.c
@@ -13,9 +13,8 @@
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, write to the Free
- Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
- Boston, MA 02110-1301, USA. */
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
#include <errno.h>
#include <unistd.h>
@@ -24,7 +23,6 @@
/* This must be initialized data because commons can't have aliases. */
void *__curbrk attribute_hidden = 0;
-libc_hidden_proto(brk)
int
brk (void *addr)
{
diff --git a/libc/sysdeps/linux/xtensa/clone.S b/libc/sysdeps/linux/xtensa/clone.S
index 31921ea47..88cd6c1c3 100644
--- a/libc/sysdeps/linux/xtensa/clone.S
+++ b/libc/sysdeps/linux/xtensa/clone.S
@@ -1,35 +1,38 @@
-/* Copyright (C) 2001, 2005, 2007 Free Software Foundation, Inc.
+/* Copyright (C) 2001, 2005 Free Software Foundation, Inc.
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.
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 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.
+ Library 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, write to the Free
- Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
- Boston, MA 02110-1301, USA. */
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
/* clone is even more special than fork as it mucks with stacks
- and invokes a function in the right context after it's all over. */
+ and invokes a function in the right context after its all over. */
-#include "sysdep.h"
-#include <sys/syscall.h>
+#include <features.h>
+#include <sysdep.h>
#define _ERRNO_H 1
#include <bits/errno.h>
+#ifdef RESET_PID
+#include <tls.h>
+#endif
+#define __ASSEMBLY__
+#include <linux/sched.h>
-/* int clone (a2 = int (*fn)(void *arg),
- a3 = void *child_stack,
- a4 = int flags,
- a5 = void *arg,
- a6 = pid_t *ptid,
- a7 = struct user_desc *tls,
- 16(sp) = pid_t *ctid) */
+/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg,
+ a2 a3 a4 a5
+ pid_t *ptid, struct user_desc *tls, pid_t *ctid)
+ a6 a7 16(sp)
+*/
.text
ENTRY (__clone)
@@ -40,7 +43,7 @@ ENTRY (__clone)
/* a2 and a3 are candidates for destruction by system-call return
parameters. We don't need the stack pointer after the system
- call. We trust that the kernel will preserve a7, a9, and a6. */
+ call. We trust that the kernel will preserve a6, a7 and a9. */
mov a9, a5 /* save function argument */
mov a5, a7
@@ -48,55 +51,69 @@ ENTRY (__clone)
mov a8, a6 /* use a8 as a temp */
mov a6, a4
mov a4, a8
- l32i a8, a1, 16 /* child_tid */
- movi a2, SYS_ify (clone)
-
- /* syscall (a2 = NR_clone,
- a6 = clone_flags,
- a3 = usp,
- a4 = parent_tid,
- a5 = child_tls,
- a8 = 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)
+ a2 a6 a3 a4 a5 a8
+ */
+
syscall
bltz a2, SYSCALL_ERROR_LABEL
beqz a2, .Lthread_start
- /* Fall through for parent. */
+ /* fall through for parent */
+
.Lpseudo_end:
- retw
+ abi_ret
.Leinval:
movi a2, -EINVAL
j SYSCALL_ERROR_LABEL
.Lthread_start:
- /* Start child thread. */
- movi a0, 0 /* terminate the stack frame */
+
+#if CLONE_THREAD != 0x00010000 || CLONE_VM != 0x00000100
+# error invalid values for CLONE_THREAD or CLONE_VM
+#endif
#ifdef RESET_PID
- /* Check and see if we need to reset the PID. */
- bbsi.l a6, 16, 1f /* CLONE_THREAD = 0x00010000 */
+ bbsi.l a6, 16, .Lskip_restore_pid /* CLONE_THREAD = 0x00010000 */
movi a2, -1
- bbsi.l a6, 8, 2f /* CLONE_VM = 0x00000100 */
- movi a2, SYS_ify (getpid)
+ bbsi a6, 8, .Lgotpid /* CLONE_VM = 0x00000100 */
+ movi a2, SYS_ify(getpid)
syscall
-2: rur a3, THREADPTR
- movi a4, PID_OFFSET
- add a4, a4, a3
- s32i a2, a4, 0
- movi a4, TID_OFFSET
- add a4, a4, a3
- s32i a2, a3, 0
-1:
-#endif /* RESET_PID */
+.Lgotpid:
+ rur a3, threadptr
+ movi a0, TLS_PRE_TCB_SIZE
+ sub a3, a3, a0
+ s32i a2, a3, PID
+ s32i a2, a3, TID
+.Lskip_restore_pid:
+#endif
+
+ /* 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. */
+ function in a6 is seen as inputs to _exit. */
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
+#error Unsupported Xtensa ABI
+#endif
PSEUDO_END (__clone)
diff --git a/libc/sysdeps/linux/xtensa/crt1.S b/libc/sysdeps/linux/xtensa/crt1.S
index 63fbadc15..efbe264c0 100644
--- a/libc/sysdeps/linux/xtensa/crt1.S
+++ b/libc/sysdeps/linux/xtensa/crt1.S
@@ -30,9 +30,8 @@
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, write to the Free
- Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
- Boston, MA 02110-1301, USA. */
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
#include <features.h>
@@ -77,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
@@ -105,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/fork.c b/libc/sysdeps/linux/xtensa/fork.c
index b06d934fb..4e4f937a0 100644
--- a/libc/sysdeps/linux/xtensa/fork.c
+++ b/libc/sysdeps/linux/xtensa/fork.c
@@ -7,19 +7,23 @@
* Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
*/
-#include <unistd.h>
-#include <sys/syscall.h>
-#define _SIGNAL_H
-#include <bits/signum.h>
/* Xtensa doesn't provide a 'fork' system call, so we use 'clone'. */
+#include <sys/syscall.h>
-extern __typeof(fork) __libc_fork;
+#if defined __NR_clone && defined __ARCH_USE_MMU__
+# include <unistd.h>
+# include <signal.h>
+# include <cancel.h>
-libc_hidden_proto (fork)
-pid_t __libc_fork (void)
+pid_t fork(void)
{
- return (pid_t) INLINE_SYSCALL (clone, 2, SIGCHLD, 0);
+ return (pid_t) INLINE_SYSCALL(clone, 2, SIGCHLD, 0);
}
-weak_alias (__libc_fork, fork)
-libc_hidden_weak (fork)
+# ifdef __UCLIBC_HAS_THREADS__
+strong_alias(fork,__libc_fork)
+libc_hidden_weak(fork)
+# else
+libc_hidden_def(fork)
+# endif
+#endif
diff --git a/libc/sysdeps/linux/xtensa/jmpbuf-offsets.h b/libc/sysdeps/linux/xtensa/jmpbuf-offsets.h
new file mode 100644
index 000000000..4078dff55
--- /dev/null
+++ b/libc/sysdeps/linux/xtensa/jmpbuf-offsets.h
@@ -0,0 +1,20 @@
+/* Private macros for accessing __jmp_buf contents. Xtensa version.
+ Copyright (C) 2006 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/>. */
+
+#define JB_SP 1
+#define JB_PC 16
diff --git a/libc/sysdeps/linux/xtensa/jmpbuf-unwind.h b/libc/sysdeps/linux/xtensa/jmpbuf-unwind.h
new file mode 100644
index 000000000..4516d9398
--- /dev/null
+++ b/libc/sysdeps/linux/xtensa/jmpbuf-unwind.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+#include <setjmp.h>
+#include <jmpbuf-offsets.h>
+
+/* Test if longjmp to JMPBUF would unwind the frame
+ containing a local variable at ADDRESS. */
+#define _JMPBUF_UNWINDS(jmpbuf, address) \
+ ((void *) (address) < (void *) (jmpbuf)[JB_SP])
+
+#ifdef __UCLIBC_HAS_THREADS_NATIVE__
+#include <stdint.h>
+#include <unwind.h>
+
+#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \
+ _JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), _adj)
+
+#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \
+ ((uintptr_t) (_address) - (_adj) < (uintptr_t) (_jmpbuf)[JB_SP] - (_adj))
+#endif
diff --git a/libc/sysdeps/linux/xtensa/mmap.S b/libc/sysdeps/linux/xtensa/mmap.S
index c991e7d27..b4dd7c53b 100644
--- a/libc/sysdeps/linux/xtensa/mmap.S
+++ b/libc/sysdeps/linux/xtensa/mmap.S
@@ -12,9 +12,8 @@
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, write to the Free
- Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
- Boston, MA 02110-1301, USA. */
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
#include "sysdep.h"
#include <sys/syscall.h>
@@ -49,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/posix_fadvise.c b/libc/sysdeps/linux/xtensa/posix_fadvise.c
deleted file mode 100644
index 0fe13a1e9..000000000
--- a/libc/sysdeps/linux/xtensa/posix_fadvise.c
+++ /dev/null
@@ -1,29 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * posix_fadvise() for Xtensa uClibc
- *
- * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
- * Copyright (C) 2007 Tensilica Inc.
- *
- * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
- */
-
-#include <sys/syscall.h>
-#include <fcntl.h>
-
-int posix_fadvise (int fd, off_t offset, off_t len, int advice)
-{
-#ifdef __NR_fadvise64_64
- INTERNAL_SYSCALL_DECL (err);
- int ret = INTERNAL_SYSCALL (fadvise64_64, err, 6, fd, advice,
- __LONG_LONG_PAIR ((long) (offset >> 31),
- (long) offset),
- __LONG_LONG_PAIR ((long) (len >> 31),
- (long) len));
- if (!INTERNAL_SYSCALL_ERROR_P (ret, err))
- return 0;
- return INTERNAL_SYSCALL_ERRNO (ret, err);
-#else
- return ENOSYS;
-#endif
-}
diff --git a/libc/sysdeps/linux/xtensa/posix_fadvise64.c b/libc/sysdeps/linux/xtensa/posix_fadvise64.c
deleted file mode 100644
index 1fdeeba79..000000000
--- a/libc/sysdeps/linux/xtensa/posix_fadvise64.c
+++ /dev/null
@@ -1,39 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * posix_fadvise64() for Xtensa uClibc
- *
- * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
- * Copyright (C) 2007 Tensilica Inc.
- *
- * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
- */
-
-#include <features.h>
-#include <unistd.h>
-#include <errno.h>
-#include <endian.h>
-#include <stdint.h>
-#include <sys/types.h>
-#include <sys/syscall.h>
-#include <fcntl.h>
-
-#ifdef __UCLIBC_HAS_LFS__
-
-int posix_fadvise64 (int fd, __off64_t offset, __off64_t len, int advice)
-{
-#ifdef __NR_fadvise64_64
- INTERNAL_SYSCALL_DECL (err);
- int ret = INTERNAL_SYSCALL (fadvise64_64, err, 6, fd, advice,
- __LONG_LONG_PAIR ((long) (offset >> 32),
- (long) offset),
- __LONG_LONG_PAIR ((long) (len >> 32),
- (long) len));
- if (!INTERNAL_SYSCALL_ERROR_P (ret, err))
- return 0;
- return INTERNAL_SYSCALL_ERRNO (ret, err);
-#else
- return ENOSYS;
-#endif
-}
-
-#endif /* __UCLIBC_HAS_LFS__ */
diff --git a/libc/sysdeps/linux/xtensa/pread_write.c b/libc/sysdeps/linux/xtensa/pread_write.c
deleted file mode 100644
index 40d0f0324..000000000
--- a/libc/sysdeps/linux/xtensa/pread_write.c
+++ /dev/null
@@ -1,193 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
- *
- * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
- */
-/*
- * Based in part on the files
- * ./sysdeps/unix/sysv/linux/pwrite.c,
- * ./sysdeps/unix/sysv/linux/pread.c,
- * sysdeps/posix/pread.c
- * sysdeps/posix/pwrite.c
- * from GNU libc 2.2.5, but reworked considerably...
- */
-
-#include <sys/syscall.h>
-#include <unistd.h>
-#include <stdint.h>
-#include <endian.h>
-
-extern __typeof(pread) __libc_pread;
-extern __typeof(pwrite) __libc_pwrite;
-#ifdef __UCLIBC_HAS_LFS__
-extern __typeof(pread64) __libc_pread64;
-extern __typeof(pwrite64) __libc_pwrite64;
-#endif
-
-#include <bits/kernel_types.h>
-
-#ifdef __NR_pread
-
-# define __NR___syscall_pread __NR_pread
-/* On Xtensa, 64-bit values are aligned in even/odd register pairs. */
-static __inline__ _syscall6(ssize_t, __syscall_pread, int, fd, void *, buf,
- size_t, count, int, pad, off_t, offset_hi, off_t, offset_lo);
-
-ssize_t __libc_pread(int fd, void *buf, size_t count, off_t offset)
-{
- return __syscall_pread(fd, buf, count, 0, __LONG_LONG_PAIR(offset >> 31, offset));
-}
-weak_alias(__libc_pread,pread)
-
-# ifdef __UCLIBC_HAS_LFS__
-ssize_t __libc_pread64(int fd, void *buf, size_t count, off64_t offset)
-{
- uint32_t low = offset & 0xffffffff;
- uint32_t high = offset >> 32;
- return __syscall_pread(fd, buf, count, 0, __LONG_LONG_PAIR(high, low));
-}
-weak_alias(__libc_pread64,pread64)
-# endif /* __UCLIBC_HAS_LFS__ */
-
-#endif /* __NR_pread */
-
-#ifdef __NR_pwrite
-
-# define __NR___syscall_pwrite __NR_pwrite
-/* On Xtensa, 64-bit values are aligned in even/odd register pairs. */
-static __inline__ _syscall6(ssize_t, __syscall_pwrite, int, fd, const void *, buf,
- size_t, count, int, pad, off_t, offset_hi, off_t, offset_lo);
-
-ssize_t __libc_pwrite(int fd, const void *buf, size_t count, off_t offset)
-{
- return __syscall_pwrite(fd, buf, count, 0, __LONG_LONG_PAIR(offset >> 31, offset));
-}
-weak_alias(__libc_pwrite,pwrite)
-
-# ifdef __UCLIBC_HAS_LFS__
-ssize_t __libc_pwrite64(int fd, const void *buf, size_t count, off64_t offset)
-{
- uint32_t low = offset & 0xffffffff;
- uint32_t high = offset >> 32;
- return __syscall_pwrite(fd, buf, count, 0, __LONG_LONG_PAIR(high, low));
-}
-weak_alias(__libc_pwrite64,pwrite64)
-# endif /* __UCLIBC_HAS_LFS__ */
-#endif /* __NR_pwrite */
-
-#if ! defined __NR_pread || ! defined __NR_pwrite
-libc_hidden_proto(read)
-libc_hidden_proto(write)
-libc_hidden_proto(lseek)
-
-static ssize_t __fake_pread_write(int fd, void *buf,
- size_t count, off_t offset, int do_pwrite)
-{
- int save_errno;
- ssize_t result;
- off_t old_offset;
-
- /* Since we must not change the file pointer preserve the
- * value so that we can restore it later. */
- if ((old_offset=lseek(fd, 0, SEEK_CUR)) == (off_t) -1)
- return -1;
-
- /* Set to wanted position. */
- if (lseek(fd, offset, SEEK_SET) == (off_t) -1)
- return -1;
-
- if (do_pwrite == 1) {
- /* Write the data. */
- result = write(fd, buf, count);
- } else {
- /* Read the data. */
- result = read(fd, buf, count);
- }
-
- /* Now we have to restore the position. If this fails we
- * have to return this as an error. */
- save_errno = errno;
- if (lseek(fd, old_offset, SEEK_SET) == (off_t) -1)
- {
- if (result == -1)
- __set_errno(save_errno);
- return -1;
- }
- __set_errno(save_errno);
- return(result);
-}
-
-# ifdef __UCLIBC_HAS_LFS__
-libc_hidden_proto(lseek64)
-
-static ssize_t __fake_pread_write64(int fd, void *buf,
- size_t count, off64_t offset, int do_pwrite)
-{
- int save_errno;
- ssize_t result;
- off64_t old_offset;
-
- /* Since we must not change the file pointer preserve the
- * value so that we can restore it later. */
- if ((old_offset=lseek64(fd, 0, SEEK_CUR)) == (off64_t) -1)
- return -1;
-
- /* Set to wanted position. */
- if (lseek64(fd, offset, SEEK_SET) == (off64_t) -1)
- return -1;
-
- if (do_pwrite == 1) {
- /* Write the data. */
- result = write(fd, buf, count);
- } else {
- /* Read the data. */
- result = read(fd, buf, count);
- }
-
- /* Now we have to restore the position. */
- save_errno = errno;
- if (lseek64(fd, old_offset, SEEK_SET) == (off64_t) -1) {
- if (result == -1)
- __set_errno (save_errno);
- return -1;
- }
- __set_errno (save_errno);
- return result;
-}
-# endif /* __UCLIBC_HAS_LFS__ */
-#endif /* ! defined __NR_pread || ! defined __NR_pwrite */
-
-#ifndef __NR_pread
-ssize_t __libc_pread(int fd, void *buf, size_t count, off_t offset)
-{
- return __fake_pread_write(fd, buf, count, offset, 0);
-}
-weak_alias(__libc_pread,pread)
-
-# ifdef __UCLIBC_HAS_LFS__
-ssize_t __libc_pread64(int fd, void *buf, size_t count, off64_t offset)
-{
- return __fake_pread_write64(fd, buf, count, offset, 0);
-}
-weak_alias(__libc_pread64,pread64)
-# endif /* __UCLIBC_HAS_LFS__ */
-#endif /* ! __NR_pread */
-
-#ifndef __NR_pwrite
-ssize_t __libc_pwrite(int fd, const void *buf, size_t count, off_t offset)
-{
- /* we won't actually be modifying the buffer,
- *just cast it to get rid of warnings */
- return __fake_pread_write(fd, (void*)buf, count, offset, 1);
-}
-weak_alias(__libc_pwrite,pwrite)
-
-# ifdef __UCLIBC_HAS_LFS__
-ssize_t __libc_pwrite64(int fd, const void *buf, size_t count, off64_t offset)
-{
- return __fake_pread_write64(fd, (void*)buf, count, offset, 1);
-}
-weak_alias(__libc_pwrite64,pwrite64)
-# endif /* __UCLIBC_HAS_LFS__ */
-#endif /* ! __NR_pwrite */
diff --git a/libc/sysdeps/linux/xtensa/setjmp.S b/libc/sysdeps/linux/xtensa/setjmp.S
index 5e81460c7..862bf6729 100644
--- a/libc/sysdeps/linux/xtensa/setjmp.S
+++ b/libc/sysdeps/linux/xtensa/setjmp.S
@@ -13,9 +13,8 @@
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, write to the Free
- Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
- Boston, MA 02110-1301, USA. */
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
/* This implementation relies heavily on the Xtensa register window
mechanism. Setjmp flushes all the windows except its own to the
@@ -25,24 +24,52 @@
then sets things up so that it will return to the right place,
using a window underflow to automatically restore the registers.
- Note that it would probably be sufficient to only copy the
- registers from setjmp's caller into jmp_buf. However, we also copy
- the save area located at the stack pointer of setjmp's caller.
- This save area will typically remain intact until the longjmp call.
- The one exception is when there is an intervening alloca in
- setjmp's caller. This is certainly an unusual situation and is
- likely to cause problems in any case (the storage allocated on the
- stack cannot be safely accessed following the longjmp). As bad as
- it is, on most systems this situation would not necessarily lead to
- a catastrophic failure. If we did not preserve the extra save area
- on Xtensa, however, it would. When setjmp's caller returns after a
- longjmp, there will be a window underflow; an invalid return
- address or stack pointer in the save area will almost certainly
- lead to a crash. Keeping a copy of the extra save area in the
- jmp_buf avoids this with only a small additional cost. If setjmp
- and longjmp are ever time-critical, this could be removed. */
+ Note that we also save the area located just below the stack pointer
+ of the caller. This save area could get overwritten by alloca
+ following the call to setjmp. The alloca moves the stack pointer
+ to allocate memory on the stack. This newly allocated memory
+ includes(!) the original save area (alloca copies the save area
+ before it moves that stack pointer).
+
+
+ previous caller SP -> |------------------------------| <-----+
+ | caller-2 registers a0-a3 | | p
+ |------------------------------| | o
+ | caller registers a4-a8/a12 | | i
+ |------------------------------| | n
+ | caller local stack | | t
+ caller SP -> |------------------------------| <-+ | s
+ | caller-1 registers a0-a3 | -:---+
+ callee (setjmp) SP -> |==============================| |
+ | caller registers a0-a3 | --+
+ |------------------------------|
+
+ In case of an alloca, registers a0-a3 of the previous caller (caller-1)
+ are copied (*), and the original location get likely overwritten.
+
+ previous caller SP -> |------------------------------| <-----+
+ | caller-2 registers a0-a3 | | p
+ |------------------------------| | o
+ | caller registers a4-a8/a12 | | i
+ |------------------------------| | n
+ | caller local stack | | t
+ caller SP before alloca-> |------------------------------| | s
+ | alloca area (overwrites old | |
+ | copy of caller-1 registers) | |
+ caller SP after alloca -> |------------------------------| <-+ |
+ | caller-1 registers a0-a3 (*) | -:---+
+ callee (setjmp) SP -> |==============================| |
+ | caller registers a0-a3 | --+
+ |------------------------------|
+
+ So, when longcall returns to the original caller SP, it also needs
+ to restore the save area below the SP.
+
+ */
#include "sysdep.h"
+
+/* NOTE: The ENTRY macro must allocate exactly 16 bytes (entry a1, 16) */
/* int setjmp (a2 = jmp_buf env) */
@@ -57,74 +84,85 @@ ENTRY (setjmp)
j 1f
END (setjmp)
-/* int __sigsetjmp (a2 = jmp_buf env,
- a3 = int savemask) */
+/* int __sigsetjmp (a2 = jmp_buf env, a3 = int savemask) */
ENTRY (__sigsetjmp)
-1:
+1:
+#if defined(__XTENSA_WINDOWED_ABI__)
/* Flush registers. */
movi a4, __window_spill
callx4 a4
- /* Preserve the second argument (savemask) in a15. The selection
- of a15 is arbitrary, except it's otherwise unused. There is no
- risk of triggering a window overflow since we just returned
- from __window_spill(). */
- mov a15, a3
-
- /* Copy the register save area at (sp - 16). */
- addi a5, a1, -16
- l32i a3, a5, 0
- l32i a4, a5, 4
- s32i a3, a2, 0
- s32i a4, a2, 4
- l32i a3, a5, 8
- l32i a4, a5, 12
- s32i a3, a2, 8
- s32i a4, a2, 12
-
- /* Copy 0-8 words from the register overflow area. */
- extui a3, a0, 30, 2
- blti a3, 2, .Lendsj
- l32i a7, a1, 4
- slli a4, a3, 4
- sub a5, a7, a4
- addi a6, a2, 16
- addi a7, a7, -16 // a7 = end of register overflow area
+ /* Copy the caller register a0-a3 at (sp - 16) to jmpbuf. */
+ addi a7, a1, -16
+ l32i a4, a7, 0
+ l32i a5, a7, 4
+ s32i a4, a2, 0
+ s32i a5, a2, 4
+ l32i a4, a7, 8
+ l32i a5, a7, 12
+ s32i a4, a2, 8
+ s32i a5, a2, 12
+
+ /* Copy the caller registers a4-a8/a12 from the overflow area. */
+ /* Note that entry moved the SP by 16B, so SP of caller-1 is at 4(sp) */
+ extui a7, a0, 30, 2
+ blti a7, 2, .Lendsj
+ l32i a8, a1, 4 /* a8: SP of 'caller-1' */
+ slli a4, a7, 4
+ sub a6, a8, a4
+ addi a5, a2, 16
+ addi a8, a8, -16 /* a8: end of register overflow area */
.Lsjloop:
- l32i a3, a5, 0
- l32i a4, a5, 4
- s32i a3, a6, 0
- s32i a4, a6, 4
- l32i a3, a5, 8
- l32i a4, a5, 12
- s32i a3, a6, 8
- s32i a4, a6, 12
- addi a5, a5, 16
+ l32i a7, a6, 0
+ l32i a4, a6, 4
+ s32i a7, a5, 0
+ s32i a4, a5, 4
+ l32i a7, a6, 8
+ l32i a4, a6, 12
+ s32i a7, a5, 8
+ s32i a4, a5, 12
+ addi a5, a6, 16
addi a6, a6, 16
- blt a5, a7, .Lsjloop
+ blt a6, a8, .Lsjloop
.Lendsj:
- /* Copy the register save area at sp. */
- l32i a3, a1, 0
- l32i a4, a1, 4
- s32i a3, a2, 48
- s32i a4, a2, 52
- l32i a3, a1, 8
- l32i a4, a1, 12
- s32i a3, a2, 56
- s32i a4, a2, 60
+ /* Copy previous caller registers (this is assuming 'entry a1,16') */
+ l32i a4, a1, 0
+ l32i a5, a1, 4
+ s32i a4, a2, 48
+ s32i a5, a2, 52
+ l32i a4, a1, 8
+ l32i a5, a1, 12
+ s32i a4, a2, 56
+ s32i a5, a2, 60
/* Save the return address, including the window size bits. */
s32i a0, a2, 64
- /* a2 still addresses jmp_buf. a15 contains savemask. */
+ /* a2 still points to jmp_buf. a3 contains savemask. */
mov a6, a2
- mov a7, a15
+ mov a7, a3
movi a3, __sigjmp_save
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/sigaction.c b/libc/sysdeps/linux/xtensa/sigaction.c
index 790a8f21f..2a20c6859 100644
--- a/libc/sysdeps/linux/xtensa/sigaction.c
+++ b/libc/sysdeps/linux/xtensa/sigaction.c
@@ -15,45 +15,30 @@
#define SA_RESTORER 0x04000000
-extern void __default_sa_restorer (void);
+extern void __default_sa_restorer(void);
-/* Experimentally off - libc_hidden_proto(memcpy) */
-
-int __libc_sigaction (int signum, const struct sigaction *act,
- struct sigaction *oldact)
+int __libc_sigaction(int sig, const struct sigaction *act,
+ struct sigaction *oact)
{
- struct kernel_sigaction kact, koldact;
- int result;
-
- if (act) {
- kact.k_sa_handler = act->sa_handler;
- memcpy(&kact.sa_mask, &act->sa_mask, sizeof (kact.sa_mask));
- kact.sa_flags = act->sa_flags;
-
- if (kact.sa_flags & SA_RESTORER) {
- kact.sa_restorer = act->sa_restorer;
- } else {
- kact.sa_restorer = __default_sa_restorer;
- kact.sa_flags |= SA_RESTORER;
- }
- }
-
- result = __syscall_rt_sigaction(signum, act ? __ptrvalue (&kact) : NULL,
- oldact ? __ptrvalue (&koldact) : NULL,
- _NSIG / 8);
+ struct sigaction kact;
- if (oldact && result >= 0) {
- oldact->sa_handler = koldact.k_sa_handler;
- memcpy(&oldact->sa_mask, &koldact.sa_mask, sizeof(oldact->sa_mask));
- oldact->sa_flags = koldact.sa_flags;
- oldact->sa_restorer = koldact.sa_restorer;
+ if (act && !(act->sa_flags & SA_RESTORER)) {
+ memcpy(&kact, act, sizeof(kact));
+ kact.sa_restorer = __default_sa_restorer;
+ kact.sa_flags |= SA_RESTORER;
+ act = &kact;
}
-
- return result;
+ /* NB: kernel (as of 2.6.25) will return EINVAL
+ * if sizeof(act->sa_mask) does not match kernel's sizeof(sigset_t) */
+ return __syscall_rt_sigaction(sig, act, oact, sizeof(act->sa_mask));
}
#ifndef LIBC_SIGACTION
-libc_hidden_proto (sigaction)
-weak_alias (__libc_sigaction, sigaction)
-libc_hidden_weak (sigaction)
+# ifndef __UCLIBC_HAS_THREADS__
+strong_alias(__libc_sigaction,sigaction)
+libc_hidden_def(sigaction)
+# else
+weak_alias(__libc_sigaction,sigaction)
+libc_hidden_weak(sigaction)
+# endif
#endif
diff --git a/libc/sysdeps/linux/xtensa/sigrestorer.S b/libc/sysdeps/linux/xtensa/sigrestorer.S
index 474a89319..697f54e1d 100644
--- a/libc/sysdeps/linux/xtensa/sigrestorer.S
+++ b/libc/sysdeps/linux/xtensa/sigrestorer.S
@@ -11,6 +11,12 @@
#endif
.text
+ /* This space separates __default_sa_restorer from the previous
+ * function, so that its corresponding FDE is not mistakenly found
+ * by the libgcc stack unwinder. This is important for correct signal
+ * stack unwinding.
+ */
+ .space 1
.align 4
.global __default_sa_restorer
.type __default_sa_restorer, @function
diff --git a/libc/sysdeps/linux/xtensa/sys/procfs.h b/libc/sysdeps/linux/xtensa/sys/procfs.h
index f6f8752bc..484460449 100644
--- a/libc/sysdeps/linux/xtensa/sys/procfs.h
+++ b/libc/sysdeps/linux/xtensa/sys/procfs.h
@@ -12,9 +12,8 @@
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, write to the Free
- Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
- Boston, MA 02110-1301, USA. */
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
#ifndef _SYS_PROCFS_H
#define _SYS_PROCFS_H 1
diff --git a/libc/sysdeps/linux/xtensa/sys/ptrace.h b/libc/sysdeps/linux/xtensa/sys/ptrace.h
deleted file mode 100644
index 7aad929bb..000000000
--- a/libc/sysdeps/linux/xtensa/sys/ptrace.h
+++ /dev/null
@@ -1,156 +0,0 @@
-/* `ptrace' debugger support interface. Linux version.
- Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007
- 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, write to the Free
- Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
- Boston, MA 02110-1301, USA. */
-
-#ifndef _SYS_PTRACE_H
-#define _SYS_PTRACE_H 1
-
-#include <features.h>
-
-/* Kludge away careless namespace pollution from the kernel. */
-
-#undef PTRACE_GETREGS
-#undef PTRACE_SETREGS
-#undef PTRACE_GETFPREGS
-#undef PTRACE_SETFPREGS
-#undef PTRACE_GETFPREGSIZE
-
-
-__BEGIN_DECLS
-
-/* Type of the REQUEST argument to `ptrace.' */
-enum __ptrace_request
-{
- /* Indicate that the process making this request should be traced.
- All signals received by this process can be intercepted by its
- parent, and its parent can use the other `ptrace' requests. */
- PTRACE_TRACEME = 0,
-#define PT_TRACE_ME PTRACE_TRACEME
-
- /* Return the word in the process's text space at address ADDR. */
- PTRACE_PEEKTEXT = 1,
-#define PT_READ_I PTRACE_PEEKTEXT
-
- /* Return the word in the process's data space at address ADDR. */
- PTRACE_PEEKDATA = 2,
-#define PT_READ_D PTRACE_PEEKDATA
-
- /* Return the word in the process's user area at offset ADDR. */
- PTRACE_PEEKUSER = 3,
-#define PT_READ_U PTRACE_PEEKUSER
-
- /* Write the word DATA into the process's text space at address ADDR. */
- PTRACE_POKETEXT = 4,
-#define PT_WRITE_I PTRACE_POKETEXT
-
- /* Write the word DATA into the process's data space at address ADDR. */
- PTRACE_POKEDATA = 5,
-#define PT_WRITE_D PTRACE_POKEDATA
-
- /* Write the word DATA into the process's user area at offset ADDR. */
- PTRACE_POKEUSER = 6,
-#define PT_WRITE_U PTRACE_POKEUSER
-
- /* Continue the process. */
- PTRACE_CONT = 7,
-#define PT_CONTINUE PTRACE_CONT
-
- /* Kill the process. */
- PTRACE_KILL = 8,
-#define PT_KILL PTRACE_KILL
-
- /* Single step the process.
- This is not supported on all machines. */
- PTRACE_SINGLESTEP = 9,
-#define PT_STEP PTRACE_SINGLESTEP
-
- /* Get all general purpose registers used by a processes.
- This is not supported on all machines. */
- PTRACE_GETREGS = 12,
-#define PT_GETREGS PTRACE_GETREGS
-
- /* Set all general purpose registers used by a processes.
- This is not supported on all machines. */
- PTRACE_SETREGS = 13,
-#define PT_SETREGS PTRACE_SETREGS
-
- /* Get all floating point registers used by a processes.
- This is not supported on all machines. */
- PTRACE_GETFPREGS = 14,
-#define PT_GETFPREGS PTRACE_GETFPREGS
-
- /* Set all floating point registers used by a processes.
- This is not supported on all machines. */
- PTRACE_SETFPREGS = 15,
-#define PT_SETFPREGS PTRACE_SETFPREGS
-
- /* Attach to a process that is already running. */
- PTRACE_ATTACH = 16,
-#define PT_ATTACH PTRACE_ATTACH
-
- /* Detach from a process attached to with PTRACE_ATTACH. */
- PTRACE_DETACH = 17,
-#define PT_DETACH PTRACE_DETACH
-
- /* Get size required for the buffer holding the floating point registers.
- This is not supported on all machines. */
- PTRACE_GETFPREGSIZE = 18,
-#define PT_GETFPREGSIZE PTRACE_GETFPREGSIZE
-
- /* Continue and stop at the next (return from) syscall. */
- PTRACE_SYSCALL = 24
-#define PT_SYSCALL PTRACE_SYSCALL
-};
-
-/* Options set using PTRACE_SETOPTIONS. */
-enum __ptrace_setoptions {
- PTRACE_O_TRACESYSGOOD = 0x00000001,
- PTRACE_O_TRACEFORK = 0x00000002,
- PTRACE_O_TRACEVFORK = 0x00000004,
- PTRACE_O_TRACECLONE = 0x00000008,
- PTRACE_O_TRACEEXEC = 0x00000010,
- PTRACE_O_TRACEVFORKDONE = 0x00000020,
- PTRACE_O_TRACEEXIT = 0x00000040,
- PTRACE_O_MASK = 0x0000007f
-};
-
-/* Wait extended result codes for the above trace options. */
-enum __ptrace_eventcodes {
- PTRACE_EVENT_FORK = 1,
- PTRACE_EVENT_VFORK = 2,
- PTRACE_EVENT_CLONE = 3,
- PTRACE_EVENT_EXEC = 4,
- PTRACE_EVENT_VFORK_DONE = 5,
- PTRACE_EVENT_EXIT = 6
-};
-
-/* Perform process tracing functions. REQUEST is one of the values
- above, and determines the action to be taken.
- For all requests except PTRACE_TRACEME, PID specifies the process to be
- traced.
-
- PID and the other arguments described above for the various requests should
- appear (those that are used for the particular request) as:
- pid_t PID, void *ADDR, int DATA, void *ADDR2
- after REQUEST. */
-extern long int ptrace (enum __ptrace_request __request, ...) __THROW;
-
-__END_DECLS
-
-#endif /* _SYS_PTRACE_H */
diff --git a/libc/sysdeps/linux/xtensa/sys/ucontext.h b/libc/sysdeps/linux/xtensa/sys/ucontext.h
index 4c37201ea..da75d988f 100644
--- a/libc/sysdeps/linux/xtensa/sys/ucontext.h
+++ b/libc/sysdeps/linux/xtensa/sys/ucontext.h
@@ -12,9 +12,8 @@
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, write to the Free
- Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
- Boston, MA 02110-1301, USA. */
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
#ifndef _SYS_UCONTEXT_H
#define _SYS_UCONTEXT_H 1
diff --git a/libc/sysdeps/linux/xtensa/sys/user.h b/libc/sysdeps/linux/xtensa/sys/user.h
new file mode 100644
index 000000000..f97f93edb
--- /dev/null
+++ b/libc/sysdeps/linux/xtensa/sys/user.h
@@ -0,0 +1,20 @@
+/*
+ * include/asm-xtensa/user.h
+ *
+ * Xtensa Processor version.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_USER_H
+#define _XTENSA_USER_H
+
+/* This file usually defines a 'struct user' structure. However, it it only
+ * used for a.out file, which are not supported on Xtensa.
+ */
+
+#endif /* _XTENSA_USER_H */
diff --git a/libc/sysdeps/linux/xtensa/syscall.S b/libc/sysdeps/linux/xtensa/syscall.S
index 955e889cf..790a8d018 100644
--- a/libc/sysdeps/linux/xtensa/syscall.S
+++ b/libc/sysdeps/linux/xtensa/syscall.S
@@ -12,9 +12,8 @@
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, write to the Free
- Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
- Boston, MA 02110-1301, USA. */
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
#include "sysdep.h"
@@ -27,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
@@ -38,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 5708a8114..f5a40eb3a 100644
--- a/libc/sysdeps/linux/xtensa/sysdep.h
+++ b/libc/sysdeps/linux/xtensa/sysdep.h
@@ -13,9 +13,14 @@
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, write to the Free
- Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
- Boston, MA 02110-1301, USA. */
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _LINUX_XTENSA_SYSDEP_H
+#define _LINUX_XTENSA_SYSDEP_H 1
+
+#include <common/sysdep.h>
+#include <sys/syscall.h>
#ifdef __ASSEMBLER__
@@ -23,29 +28,53 @@
#define ASM_TYPE_DIRECTIVE(name, typearg) .type name, typearg
#define ASM_SIZE_DIRECTIVE(name) .size name, . - name
-#ifdef __STDC__
-#define C_LABEL(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
-#define C_LABEL(name) name/**/:
+#error Unsupported Xtensa ABI
#endif
+
#define ENTRY(name) \
- ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(name); \
+ .globl 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) \
+ .globl C_SYMBOL_NAME(name); \
+ .hidden C_SYMBOL_NAME(name); \
+ ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name), @function); \
+ .align ALIGNARG(2); \
+ LITERAL_POSITION; \
+ C_LABEL(name) \
+ abi_entry(sp, FRAMESIZE); \
CALL_MCOUNT
#undef END
#define END(name) ASM_SIZE_DIRECTIVE(name)
+/* Local label name for asm code. */
+#ifndef L
+# ifdef HAVE_ELF
+# define L(name) .L##name
+# else
+# define L(name) name
+# endif
+#endif
+
/* Define a macro for this directive so it can be removed in a few places. */
#define LITERAL_POSITION .literal_position
#undef JUMPTARGET
-#ifdef PIC
+#ifdef __PIC__
/* The "@PLT" suffix is currently a no-op for non-shared linking, but
it doesn't hurt to use it conditionally for PIC code in case that
changes someday. */
@@ -54,7 +83,15 @@
#define JUMPTARGET(name) name
#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. */
@@ -98,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
@@ -112,19 +149,11 @@
#define PSEUDO_END_ERRVAL(name) \
END (name)
-#define ret_ERRVAL retw
-
-#if RTLD_PRIVATE_ERRNO
-# define SYSCALL_ERROR_HANDLER \
-0: movi a4, rtld_errno; \
- neg a2, a2; \
- s32i a2, a4, 0; \
- movi a2, -1; \
- j .Lpseudo_end;
+#undef ret_ERRVAL
+#define ret_ERRVAL abi_ret
-#elif defined _LIBC_REENTRANT
-
-# if USE___THREAD
+#if defined _LIBC_REENTRANT
+# if defined USE___THREAD
# ifndef NOT_IN_libc
# define SYSCALL_ERROR_ERRNO __libc_errno
# else
@@ -139,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; \
@@ -147,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 \
@@ -158,3 +207,9 @@
#endif /* _LIBC_REENTRANT */
#endif /* __ASSEMBLER__ */
+
+/* Pointer mangling is not yet supported for Xtensa. */
+#define PTR_MANGLE(var) (void) (var)
+#define PTR_DEMANGLE(var) (void) (var)
+
+#endif /* _LINUX_XTENSA_SYSDEP_H */
diff --git a/libc/sysdeps/linux/xtensa/vfork.S b/libc/sysdeps/linux/xtensa/vfork.S
index 830a0cd4d..8058fb057 100644
--- a/libc/sysdeps/linux/xtensa/vfork.S
+++ b/libc/sysdeps/linux/xtensa/vfork.S
@@ -1,4 +1,4 @@
-/* Copyright (C) 2005, 2007 Free Software Foundation, Inc.
+/* Copyright (C) 2005-2013 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
@@ -12,80 +12,78 @@
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, write to the Free
- Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
- Boston, MA 02110-1301, USA. */
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
#include "sysdep.h"
#include <sys/syscall.h>
#define _SIGNAL_H
#include <bits/signum.h>
+#define __ASSEMBLY__
+#include <linux/sched.h>
-/* Clone the calling process, but without copying the whole address space.
+/*
+ Clone the calling process, but without copying the whole address space.
The calling process is suspended until the new process exits or is
replaced by a call to `execve'. Return -1 for errors, 0 to the new process,
and the process ID of the new process to the old process.
Note that it is important that we don't create a new stack frame for the
- caller. */
+ caller.
-
-/* The following are defined in linux/sched.h, which unfortunately
- is not safe for inclusion in an assembly file. */
-#define CLONE_VM 0x00000100 /* set if VM shared between processes */
-#define CLONE_VFORK 0x00004000 /* set if the parent wants the child to
- wake it up on mm_release */
+*/
#ifndef SAVE_PID
-#define SAVE_PID
+#define SAVE_PID(a,b,c,d)
#endif
-
#ifndef RESTORE_PID
-#define RESTORE_PID
+#define RESTORE_PID(a,b,c)
+#endif
+#ifndef RESTORE_PID12
+#define RESTORE_PID12(a,b,c)
#endif
+/*
+ pid_t vfork(void);
+ Implemented as __clone_syscall(CLONE_VFORK | CLONE_VM | SIGCHLD, 0)
+ */
-/* pid_t vfork(void);
- Implemented as __clone_syscall(CLONE_VFORK | CLONE_VM | SIGCHLD, 0) */
-ENTRY (__vfork)
+HIDDEN_ENTRY (__vfork)
- movi a6, .Ljumptable
- extui a2, a0, 30, 2 // call-size: call4/8/12 = 1/2/3
- addx4 a4, a2, a6 // find return address in jumptable
- l32i a4, a4, 0
- add a4, a4, a6
+#if defined(__XTENSA_WINDOWED_ABI__)
+ .literal .Ljumptable, 0, .L4, .L8, .L12
+ mov a3, a0 # move return address out of the way
+ movi a0, .Ljumptable
+ extui a2, a3, 30, 2 # call-size: call4/8/12 = 1/2/3
+ addx4 a0, a2, a0 # find return address in jumptable
+ l32i a0, a0, 0
+ # exchange top 2 bits of a0 and a3:
+ xor a2, a0, a3
+ extui a2, a2, 30, 2
slli a2, a2, 30
- xor a3, a0, a2 // remove call-size from return address
- extui a5, a4, 30, 2 // get high bits of jump target
- slli a5, a5, 30
- or a3, a3, a5 // stuff them into the return address
- xor a4, a4, a5 // clear high bits of jump target
- or a0, a4, a2 // create temporary return address
- retw // "return" to .L4, .L8, or .L12
-
- .align 4
-.Ljumptable:
- .word 0
- .word .L4 - .Ljumptable
- .word .L8 - .Ljumptable
- .word .L12 - .Ljumptable
+ xor a0, a0, a2
+ xor a3, a3, a2
+ retw
/* a7: return address */
+
.L4: mov a12, a2
mov a13, a3
- SAVE_PID
+ SAVE_PID(a5,a15,a2,a3)
- /* Use syscall 'clone'. Set new stack pointer to the same address. */
- movi a2, SYS_ify (clone)
- movi a3, 0
+ /* use syscall 'clone' and 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
+ RESTORE_PID(a5,a15,a2)
movi a5, -4096
@@ -95,22 +93,24 @@ ENTRY (__vfork)
bgeu a6, a5, 1f
jx a7
-1: call4 .Lerr // returns to original caller
+1: call4 .Lerr
/* a11: return address */
+
.L8: mov a12, a2
mov a13, a3
mov a14, a6
- SAVE_PID
+ SAVE_PID(a9,a15,a2,a3)
- movi a2, SYS_ify (clone)
+ movi a2, SYS_ify(clone)
movi a3, 0
movi a6, CLONE_VM | CLONE_VFORK | SIGCHLD
+
syscall
- RESTORE_PID
+ RESTORE_PID(a9,a15,a2)
movi a9, -4096
@@ -121,22 +121,25 @@ ENTRY (__vfork)
bgeu a10, a9, 1f
jx a11
-1: call8 .Lerr // returns to original caller
+
+1: call8 .Lerr
/* a15: return address */
+
.L12: mov a12, a2
mov a13, a3
mov a14, a6
- SAVE_PID
+ SAVE_PID (a2,a3,a2,a6)
- movi a2, SYS_ify (clone)
+ movi a2, SYS_ify(clone)
movi a3, 0
movi a6, CLONE_VM | CLONE_VFORK | SIGCHLD
+
syscall
- RESTORE_PID
+ RESTORE_PID12(a3,a6,a15)
mov a3, a13
movi a13, -4096
@@ -148,23 +151,43 @@ ENTRY (__vfork)
bgeu a14, a13, 1f
jx a15
-1: call12 .Lerr // returns to original caller
+1: call12 .Lerr
.align 4
+
.Lerr: entry a1, 16
- /* Restore the return address. */
- extui a4, a0, 30, 2 // get the call-size bits
+ /* Restore return address */
+
+ extui a4, a0, 30, 2
slli a4, a4, 30
- slli a3, a3, 2 // clear high bits of target address
- srli a3, a3, 2
- or a0, a3, a4 // combine them
+ or a0, a3, a4
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)
-libc_hidden_def (__vfork)
+ 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 a63771756..013025648 100644
--- a/libc/sysdeps/linux/xtensa/windowspill.S
+++ b/libc/sysdeps/linux/xtensa/windowspill.S
@@ -13,12 +13,12 @@
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, write to the Free
- Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
- Boston, MA 02110-1301, USA. */
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
#include <bits/xtensa-config.h>
+#ifdef __XTENSA_WINDOWED_ABI__
.text
.align 4
.literal_position
@@ -26,8 +26,8 @@
.type __window_spill, @function
__window_spill:
entry a1, 48
- bbci.l a0, 31, .L4 // branch if called with call4
- bbsi.l a0, 30, .L12 // branch if called with call12
+ bbci.l a0, 31, .L4 /* branch if called with call4 */
+ bbsi.l a0, 30, .L12 /* branch if called with call12 */
/* Called with call8: touch register NUM_REGS-12 (4/20/52) */
.L8:
@@ -36,18 +36,18 @@ __window_spill:
retw
.align 4
-1: _entry a1, 48 // touch NUM_REGS-24 (x/8/40)
+1: _entry a1, 48 /* touch NUM_REGS-24 (x/8/40) */
#if XCHAL_NUM_AREGS == 32
mov a8, a0
retw
#else
mov a12, a0
- _entry a1, 48 // touch NUM_REGS-36 (x/x/28)
+ _entry a1, 48 /* touch NUM_REGS-36 (x/x/28) */
mov a12, a0
- _entry a1, 48 // touch NUM_REGS-48 (x/x/16)
+ _entry a1, 48 /* touch NUM_REGS-48 (x/x/16) */
mov a12, a0
- _entry a1, 16 // touch NUM_REGS-60 (x/x/4)
+ _entry a1, 16 /* touch NUM_REGS-60 (x/x/4) */
#endif
#endif
mov a4, a0
@@ -62,14 +62,14 @@ __window_spill:
retw
.align 4
-1: _entry a1, 48 // touch NUM_REGS-20 (x/12/44)
+1: _entry a1, 48 /* touch NUM_REGS-20 (x/12/44) */
mov a12, a0
#if XCHAL_NUM_AREGS > 32
- _entry a1, 48 // touch NUM_REGS-32 (x/x/32)
+ _entry a1, 48 /* touch NUM_REGS-32 (x/x/32) */
mov a12, a0
- _entry a1, 48 // touch NUM_REGS-44 (x/x/20)
+ _entry a1, 48 /* touch NUM_REGS-44 (x/x/20) */
mov a12, a0
- _entry a1, 48 // touch NUM_REGS-56 (x/x/8)
+ _entry a1, 48 /* touch NUM_REGS-56 (x/x/8) */
mov a8, a0
#endif
#endif
@@ -82,15 +82,17 @@ __window_spill:
retw
.align 4
-1: _entry a1, 48 // touch NUM_REGS-28 (x/4/36)
+1: _entry a1, 48 /* touch NUM_REGS-28 (x/4/36) */
#if XCHAL_NUM_AREGS == 32
mov a4, a0
#else
mov a12, a0
- _entry a1, 48 // touch NUM_REGS-40 (x/x/24)
+ _entry a1, 48 /* touch NUM_REGS-40 (x/x/24) */
mov a12, a0
- _entry a1, 48 // touch NUM_REGS-52 (x/x/12)
+ _entry a1, 48 /* touch NUM_REGS-52 (x/x/12) */
mov a12, a0
#endif
#endif
retw
+
+#endif