Browse Source

Chris Zankel writes:
The following patches add support for the Xtensa processor architecture
to uClibc. They are based on a recent SVN checkout (12/05/2007).

The first patch (attached to this post) adds Xtensa support to various
shared configuration and make files. The following patches then include
the Xtensa specific files and directories.

I welcome any feedback and would appreciate it if you could include the
patches into the mainline tree. I am certainly committed to maintain the port.

Bob Wilson was kind enough to review the patches.

Some notes about the architecture: Xtensa is a configurable and
extensible processor architecture developed by Tensilica. For more
information, please visit: www.linux-xtensa.org.

Mike Frysinger 17 years ago
parent
commit
124ec18872
62 changed files with 5055 additions and 2 deletions
  1. 2 1
      Rules.mak
  2. 7 0
      extra/Configs/Config.in
  3. 12 0
      extra/Configs/Config.xtensa
  4. 58 0
      include/elf.h
  5. 1 1
      ldso/include/dl-string.h
  6. 61 0
      ldso/ldso/xtensa/dl-debug.h
  7. 106 0
      ldso/ldso/xtensa/dl-startup.h
  8. 7 0
      ldso/ldso/xtensa/dl-syscalls.h
  9. 132 0
      ldso/ldso/xtensa/dl-sysdep.h
  10. 285 0
      ldso/ldso/xtensa/elfinterp.c
  11. 61 0
      ldso/ldso/xtensa/resolve.S
  12. 13 0
      libc/string/xtensa/Makefile
  13. 297 0
      libc/string/xtensa/memcpy.S
  14. 165 0
      libc/string/xtensa/memset.S
  15. 313 0
      libc/string/xtensa/strcmp.S
  16. 150 0
      libc/string/xtensa/strcpy.S
  17. 104 0
      libc/string/xtensa/strlen.S
  18. 241 0
      libc/string/xtensa/strncpy.S
  19. 13 0
      libc/sysdeps/linux/xtensa/Makefile
  20. 14 0
      libc/sysdeps/linux/xtensa/Makefile.arch
  21. 126 0
      libc/sysdeps/linux/xtensa/__longjmp.S
  22. 18 0
      libc/sysdeps/linux/xtensa/__syscall_error.c
  23. 10 0
      libc/sysdeps/linux/xtensa/bits/endian.h
  24. 196 0
      libc/sysdeps/linux/xtensa/bits/fcntl.h
  25. 54 0
      libc/sysdeps/linux/xtensa/bits/ipc.h
  26. 57 0
      libc/sysdeps/linux/xtensa/bits/kernel_stat.h
  27. 48 0
      libc/sysdeps/linux/xtensa/bits/kernel_types.h
  28. 43 0
      libc/sysdeps/linux/xtensa/bits/mathdef.h
  29. 104 0
      libc/sysdeps/linux/xtensa/bits/mman.h
  30. 88 0
      libc/sysdeps/linux/xtensa/bits/msq.h
  31. 46 0
      libc/sysdeps/linux/xtensa/bits/setjmp.h
  32. 115 0
      libc/sysdeps/linux/xtensa/bits/shm.h
  33. 33 0
      libc/sysdeps/linux/xtensa/bits/sigcontextinfo.h
  34. 28 0
      libc/sysdeps/linux/xtensa/bits/stackinfo.h
  35. 153 0
      libc/sysdeps/linux/xtensa/bits/stat.h
  36. 140 0
      libc/sysdeps/linux/xtensa/bits/syscalls.h
  37. 44 0
      libc/sysdeps/linux/xtensa/bits/uClibc_arch_features.h
  38. 31 0
      libc/sysdeps/linux/xtensa/bits/uClibc_page.h
  39. 19 0
      libc/sysdeps/linux/xtensa/bits/wordsize.h
  40. 53 0
      libc/sysdeps/linux/xtensa/bits/xtensa-config.h
  41. 43 0
      libc/sysdeps/linux/xtensa/brk.c
  42. 1 0
      libc/sysdeps/linux/xtensa/bsd-_setjmp.S
  43. 1 0
      libc/sysdeps/linux/xtensa/bsd-setjmp.S
  44. 103 0
      libc/sysdeps/linux/xtensa/clone.S
  45. 119 0
      libc/sysdeps/linux/xtensa/crt1.S
  46. 16 0
      libc/sysdeps/linux/xtensa/crti.S
  47. 8 0
      libc/sysdeps/linux/xtensa/crtn.S
  48. 25 0
      libc/sysdeps/linux/xtensa/fork.c
  49. 57 0
      libc/sysdeps/linux/xtensa/mmap.S
  50. 29 0
      libc/sysdeps/linux/xtensa/posix_fadvise.c
  51. 39 0
      libc/sysdeps/linux/xtensa/posix_fadvise64.c
  52. 193 0
      libc/sysdeps/linux/xtensa/pread_write.c
  53. 131 0
      libc/sysdeps/linux/xtensa/setjmp.S
  54. 121 0
      libc/sysdeps/linux/xtensa/sys/procfs.h
  55. 156 0
      libc/sysdeps/linux/xtensa/sys/ptrace.h
  56. 49 0
      libc/sysdeps/linux/xtensa/sys/ucontext.h
  57. 42 0
      libc/sysdeps/linux/xtensa/syscall.S
  58. 160 0
      libc/sysdeps/linux/xtensa/sysdep.h
  59. 170 0
      libc/sysdeps/linux/xtensa/vfork.S
  60. 95 0
      libc/sysdeps/linux/xtensa/windowspill.S
  61. 48 0
      libpthread/linuxthreads.old/sysdeps/xtensa/pt-machine.h
  62. 1 0
      test/Rules.mak

+ 2 - 1
Rules.mak

@@ -50,7 +50,8 @@ BUILD_CFLAGS = -O2 -Wall
 export ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun.*/sparc/ -e s/sparc.*/sparc/ \
 				  -e s/arm.*/arm/ -e s/sa110/arm/ -e s/sh.*/sh/ \
 				  -e s/s390x/s390/ -e s/parisc.*/hppa/ \
-				  -e s/ppc.*/powerpc/ -e s/mips.*/mips/ )
+				  -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \
+				  -e s/xtensa.*/xtensa/ )
 
 
 #---------------------------------------------------------

+ 7 - 0
extra/Configs/Config.in

@@ -82,6 +82,9 @@ config TARGET_vax
 config TARGET_x86_64
 	bool "x86_64"
 
+config TARGET_xtensa
+	bool "xtensa"
+
 endchoice
 
 
@@ -183,6 +186,10 @@ if TARGET_x86_64
 source "extra/Configs/Config.x86_64"
 endif
 
+if TARGET_xtensa
+source "extra/Configs/Config.xtensa"
+endif
+
 config TARGET_SUBARCH
 	string
 	default "e500" if CONFIG_E500

+ 12 - 0
extra/Configs/Config.xtensa

@@ -0,0 +1,12 @@
+#
+# For a description of the syntax of this configuration file,
+# see extra/config/kconfig-language.txt
+#
+
+config TARGET_ARCH
+	string
+	default "xtensa"
+
+config ARCH_CFLAGS
+	string
+

+ 58 - 0
include/elf.h

@@ -2977,6 +2977,64 @@ typedef Elf32_Addr Elf32_Conflict;
 /* Keep this the last entry.  */
 #define R_NIOS2_NUM				22
 
+/* Xtensa-specific declarations */
+
+/* Xtensa values for the Dyn d_tag field.  */
+#define DT_XTENSA_GOT_LOC_OFF	(DT_LOPROC + 0)
+#define DT_XTENSA_GOT_LOC_SZ	(DT_LOPROC + 1)
+#define DT_XTENSA_NUM		2
+
+/* Xtensa relocations.  */
+#define R_XTENSA_NONE		0
+#define R_XTENSA_32		1
+#define R_XTENSA_RTLD		2
+#define R_XTENSA_GLOB_DAT	3
+#define R_XTENSA_JMP_SLOT	4
+#define R_XTENSA_RELATIVE	5
+#define R_XTENSA_PLT		6
+#define R_XTENSA_OP0		8
+#define R_XTENSA_OP1		9
+#define R_XTENSA_OP2		10
+#define R_XTENSA_ASM_EXPAND	11
+#define R_XTENSA_ASM_SIMPLIFY	12
+#define R_XTENSA_GNU_VTINHERIT	15
+#define R_XTENSA_GNU_VTENTRY	16
+#define R_XTENSA_DIFF8		17
+#define R_XTENSA_DIFF16		18
+#define R_XTENSA_DIFF32		19
+#define R_XTENSA_SLOT0_OP	20
+#define R_XTENSA_SLOT1_OP	21
+#define R_XTENSA_SLOT2_OP	22
+#define R_XTENSA_SLOT3_OP	23
+#define R_XTENSA_SLOT4_OP	24
+#define R_XTENSA_SLOT5_OP	25
+#define R_XTENSA_SLOT6_OP	26
+#define R_XTENSA_SLOT7_OP	27
+#define R_XTENSA_SLOT8_OP	28
+#define R_XTENSA_SLOT9_OP	29
+#define R_XTENSA_SLOT10_OP	30
+#define R_XTENSA_SLOT11_OP	31
+#define R_XTENSA_SLOT12_OP	32
+#define R_XTENSA_SLOT13_OP	33
+#define R_XTENSA_SLOT14_OP	34
+#define R_XTENSA_SLOT0_ALT	35
+#define R_XTENSA_SLOT1_ALT	36
+#define R_XTENSA_SLOT2_ALT	37
+#define R_XTENSA_SLOT3_ALT	38
+#define R_XTENSA_SLOT4_ALT	39
+#define R_XTENSA_SLOT5_ALT	40
+#define R_XTENSA_SLOT6_ALT	41
+#define R_XTENSA_SLOT7_ALT	42
+#define R_XTENSA_SLOT8_ALT	43
+#define R_XTENSA_SLOT9_ALT	44
+#define R_XTENSA_SLOT10_ALT	45
+#define R_XTENSA_SLOT11_ALT	46
+#define R_XTENSA_SLOT12_ALT	47
+#define R_XTENSA_SLOT13_ALT	48
+#define R_XTENSA_SLOT14_ALT	49
+/* Keep this the last entry.  */
+#define R_XTENSA_NUM		50
+
 __END_DECLS
 
 #endif	/* elf.h */

+ 1 - 1
ldso/include/dl-string.h

@@ -286,7 +286,7 @@ static __always_inline char * _dl_simple_ltoahex(char * local, unsigned long i)
  * This requires that load_addr must already be defined... */
 #if defined(mc68000)  || defined(__arm__) || defined(__thumb__) || \
     defined(__mips__) || defined(__sh__)  || defined(__powerpc__) || \
-    defined(__avr32__)
+    defined(__avr32__) || defined(__xtensa__)
 # define CONSTANT_STRING_GOT_FIXUP(X) \
 	if ((X) < (const char *) load_addr) (X) += load_addr
 # define NO_EARLY_SEND_STDERR

+ 61 - 0
ldso/ldso/xtensa/dl-debug.h

@@ -0,0 +1,61 @@
+/* vi: set sw=4 ts=4: */
+/* Xtensa ELF shared library loader suppport
+ *
+ * Copyright (C) 2007 Tensilica Inc.
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+static const char *_dl_reltypes_tab[] =
+{
+	"R_XTENSA_NONE",
+	"R_XTENSA_32",
+	"R_XTENSA_RTLD",
+	"R_XTENSA_GLOB_DAT",
+	"R_XTENSA_JMP_SLOT",
+	"R_XTENSA_RELATIVE",
+	"R_XTENSA_PLT",
+	"R_XTENSA_UNUSED7",
+	"R_XTENSA_OP0",
+	"R_XTENSA_OP1",
+	"R_XTENSA_OP2",
+	"R_XTENSA_ASM_EXPAND",
+	"R_XTENSA_ASM_SIMPLIFY",
+	"R_XTENSA_UNUSED13",
+	"R_XTENSA_UNUSED14",
+	"R_XTENSA_GNU_VTINHERIT",
+	"R_XTENSA_GNU_VTENTRY",
+	"R_XTENSA_DIFF8",
+	"R_XTENSA_DIFF16",
+	"R_XTENSA_DIFF32",
+	"R_XTENSA_SLOT0_OP",
+	"R_XTENSA_SLOT1_OP",
+	"R_XTENSA_SLOT2_OP",
+	"R_XTENSA_SLOT3_OP",
+	"R_XTENSA_SLOT4_OP",
+	"R_XTENSA_SLOT5_OP",
+	"R_XTENSA_SLOT6_OP",
+	"R_XTENSA_SLOT7_OP",
+	"R_XTENSA_SLOT8_OP",
+	"R_XTENSA_SLOT9_OP",
+	"R_XTENSA_SLOT10_OP",
+	"R_XTENSA_SLOT11_OP",
+	"R_XTENSA_SLOT12_OP",
+	"R_XTENSA_SLOT13_OP",
+	"R_XTENSA_SLOT14_OP",
+	"R_XTENSA_SLOT0_ALT",
+	"R_XTENSA_SLOT1_ALT",
+	"R_XTENSA_SLOT2_ALT",
+	"R_XTENSA_SLOT3_ALT",
+	"R_XTENSA_SLOT4_ALT",
+	"R_XTENSA_SLOT5_ALT",
+	"R_XTENSA_SLOT6_ALT",
+	"R_XTENSA_SLOT7_ALT",
+	"R_XTENSA_SLOT8_ALT",
+	"R_XTENSA_SLOT9_ALT",
+	"R_XTENSA_SLOT10_ALT",
+	"R_XTENSA_SLOT11_ALT",
+	"R_XTENSA_SLOT12_ALT",
+	"R_XTENSA_SLOT13_ALT",
+	"R_XTENSA_SLOT14_ALT"
+};

+ 106 - 0
ldso/ldso/xtensa/dl-startup.h

@@ -0,0 +1,106 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Xtensa ELF code used by dl-startup.c.
+ *
+ * Copyright (C) 2007 Tensilica Inc.
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ * Parts taken from glibc/sysdeps/xtensa/dl-machine.h. 
+ */
+
+__asm__ (
+    "	.text\n"
+    "	.align  4\n"
+    "	.global _start\n"
+    "	.type   _start, @function\n"
+    "_start:\n"
+    "	# Compute load offset in a2: the GOT has not yet been relocated\n"
+    "	# but the entries for local symbols contain the relative offsets\n"
+    "	# and we can explicitly add the load offset in this code.\n"
+    "	_call0  0f\n"
+    "	.align  4\n"
+    "0:	movi    a3, _start+3\n"
+    "	sub     a2, a0, a3\n"
+    "	# Make sure a0 is cleared to mark the top of stack.\n"
+    "	movi    a0, 0\n"
+    "	# user_entry_point = _dl_start(pointer to argument block)\n"
+    "	movi    a4, _dl_start\n"
+    "	mov     a6, sp\n"
+    "	add     a4, a4, a2\n"
+    "	callx4  a4\n"
+    "	# Save user_entry_point so we can jump to it.\n"
+    "	mov     a3, a6\n"
+    "	l32i    a7, sp, 0   # load argc\n"
+    "	# Load _dl_skip_args into a4.\n"
+    "	movi    a4, _dl_skip_args\n"
+    "	l32i    a4, a4, 0\n"
+    "	bnez    a4, .Lfixup_stack\n"
+    ".Lfixup_stack_ret:\n"
+    "	# Pass finalizer (_dl_fini) in a2 to the user entry point.\n"
+    "	movi    a2, _dl_fini\n"
+    "	# Jump to user's entry point (_start).\n"
+    "	jx      a3\n"
+    ".Lfixup_stack:\n"
+    "	# argc -= _dl_skip_args (with argc @ sp+0)\n"
+    "	sub     a7, a7, a4\n"
+    "	s32i    a7, sp, 0\n"
+    "	# Shift everything by _dl_skip_args.\n"
+    "	addi    a5, sp, 4   # a5 = destination ptr = argv\n"
+    "	add     a4, a5, a4  # a4 = source ptr = argv + _dl_skip_args\n"
+    "	# Shift argv.\n"
+    "1:	l32i    a6, a4, 0\n"
+    "	addi    a4, a4, 4\n"
+    "	s32i    a6, a5, 0\n"
+    "	addi    a5, a5, 4\n"
+    "	bnez    a6, 1b\n"
+    "	# Shift envp.\n"
+    "2:	l32i    a6, a4, 0\n"
+    "	addi    a4, a4, 4\n"
+    "	s32i    a6, a5, 0\n"
+    "	addi    a5, a5, 4\n"
+    "	bnez    a6, 2b\n"
+    "	# Shift auxiliary table.\n"
+    "3:	l32i    a6, a4, 0\n"
+    "	l32i    a8, a4, 4\n"
+    "	addi    a4, a4, 8\n"
+    "	s32i    a6, a5, 0\n"
+    "	s32i    a8, a5, 4\n"
+    "	addi    a5, a5, 8\n"
+    "	bnez    a6, 3b\n"
+    "	j      .Lfixup_stack_ret");
+
+/* Get a pointer to the argv value.  */
+#define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long *) ARGS) + 1)
+
+/* Function calls are not safe until the GOT relocations have been done.  */
+#define NO_FUNCS_BEFORE_BOOTSTRAP
+
+#define PERFORM_BOOTSTRAP_GOT(tpnt) \
+do { \
+	xtensa_got_location *got_loc; \
+	unsigned long l_addr = tpnt->loadaddr; \
+	Elf32_Word relative_count; \
+	unsigned long rel_addr; \
+	int x; \
+\
+	got_loc = (xtensa_got_location *) \
+		(tpnt->dynamic_info[DT_XTENSA (GOT_LOC_OFF)] + l_addr); \
+\
+	for (x = 0; x < tpnt->dynamic_info[DT_XTENSA (GOT_LOC_SZ)]; x++) { \
+		Elf32_Addr got_start, got_end; \
+		got_start = got_loc[x].offset & ~(PAGE_SIZE - 1); \
+		got_end = ((got_loc[x].offset + got_loc[x].length + PAGE_SIZE - 1) \
+				   & ~(PAGE_SIZE - 1)); \
+		_dl_mprotect ((void *)(got_start + l_addr), got_end - got_start, \
+					  PROT_READ | PROT_WRITE | PROT_EXEC); \
+	} \
+\
+	/* The following is a stripped down version of the code following \
+	   the invocation of PERFORM_BOOTSTRAP_GOT in dl-startup.c.	 That \
+	   code is skipped when PERFORM_BOOTSTRAP_GOT is defined, so it has \
+	   to be done here instead.	 */ \
+	relative_count = tpnt->dynamic_info[DT_RELCONT_IDX]; \
+	rel_addr = tpnt->dynamic_info[DT_RELOC_TABLE_ADDR]; \
+	if (rel_addr) \
+	  elf_machine_relative(load_addr, rel_addr, relative_count); \
+} while (0)

+ 7 - 0
ldso/ldso/xtensa/dl-syscalls.h

@@ -0,0 +1,7 @@
+/* We can't use the real errno in ldso, since it has not yet
+ * been dynamicly linked in yet. */
+#include "sys/syscall.h"
+extern int _dl_errno;
+#undef __set_errno
+#define __set_errno(X) {(_dl_errno) = (X);}
+

+ 132 - 0
ldso/ldso/xtensa/dl-sysdep.h

@@ -0,0 +1,132 @@
+/* Machine-dependent ELF dynamic relocation.
+   Parts copied from glibc/sysdeps/xtensa/dl-machine.h
+   Copyright (C) 2001, 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.  */
+
+/* Define this if the system uses RELOCA.  */
+#define ELF_USES_RELOCA
+#include <elf.h>
+#include <link.h>
+
+/* Translate a processor specific dynamic tag to the index
+   in l_info array.  */
+#define DT_XTENSA(x) (DT_XTENSA_##x - DT_LOPROC + DT_NUM + OS_NUM)
+
+typedef struct xtensa_got_location_struct {
+  Elf32_Off offset;
+  Elf32_Word length;
+} xtensa_got_location;
+
+/* Initialization sequence for the GOT.  */
+#define INIT_GOT(GOT_BASE, MODULE) \
+  do {									      \
+    xtensa_got_location *got_loc;					      \
+    Elf32_Addr l_addr = MODULE->loadaddr;				      \
+    int x;								      \
+									      \
+    got_loc = (xtensa_got_location *)					      \
+      (MODULE->dynamic_info[DT_XTENSA (GOT_LOC_OFF)] + l_addr);		      \
+									      \
+    for (x = 0; x < MODULE->dynamic_info[DT_XTENSA (GOT_LOC_SZ)]; x++)	      \
+      {									      \
+	Elf32_Addr got_start, got_end;					      \
+	got_start = got_loc[x].offset & ~(PAGE_SIZE - 1);		      \
+	got_end = ((got_loc[x].offset + got_loc[x].length + PAGE_SIZE - 1)    \
+		   & ~(PAGE_SIZE - 1));					      \
+	_dl_mprotect ((void *)(got_start + l_addr) , got_end - got_start,     \
+		      PROT_READ | PROT_WRITE | PROT_EXEC);		      \
+      }									      \
+									      \
+    /* Fill in first GOT entry according to the ABI.  */		      \
+    GOT_BASE[0] = (unsigned long) _dl_linux_resolve;			      \
+  } while (0)
+
+/* Parse dynamic info */
+#define ARCH_NUM 2
+#define ARCH_DYNAMIC_INFO(dpnt, dynamic, debug_addr) \
+  do {									\
+    if (dpnt->d_tag == DT_XTENSA_GOT_LOC_OFF)				\
+      dynamic[DT_XTENSA (GOT_LOC_OFF)] = dpnt->d_un.d_ptr;		\
+    else if (dpnt->d_tag == DT_XTENSA_GOT_LOC_SZ)			\
+      dynamic[DT_XTENSA (GOT_LOC_SZ)] = dpnt->d_un.d_val;		\
+  } while (0)
+
+/* Here we define the magic numbers that this dynamic loader should accept. */
+#define MAGIC1 EM_XTENSA
+#undef	MAGIC2
+
+/* Used for error messages. */
+#define ELF_TARGET "Xtensa"
+
+struct elf_resolve;
+extern unsigned long _dl_linux_resolver (struct elf_resolve *, int);
+
+/* 4096 bytes alignment */
+#define PAGE_ALIGN 0xfffff000
+#define ADDR_ALIGN 0xfff
+#define OFFS_ALIGN 0x7ffff000
+
+/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry, so
+   undefined references should not be allowed to define the value.  */
+#define elf_machine_type_class(type) \
+  (((type) == R_XTENSA_JMP_SLOT) * ELF_RTYPE_CLASS_PLT)
+
+/* Return the link-time address of _DYNAMIC.  */
+static inline Elf32_Addr
+elf_machine_dynamic (void)
+{
+  /* This function is only used while bootstrapping the runtime linker.
+     The "_DYNAMIC" symbol is always local so its GOT entry will initially
+     contain the link-time address.  */
+  return (Elf32_Addr) &_DYNAMIC;
+}
+
+/* Return the run-time load address of the shared object.  */
+static inline Elf32_Addr
+elf_machine_load_address (void)
+{
+  Elf32_Addr addr, tmp;
+
+  /* At this point, the runtime linker is being bootstrapped and the GOT
+     entry used for ".Lhere" will contain the link address.  The CALL0 will
+     produce the dynamic address of ".Lhere" + 3.  Thus, the end result is
+     equal to "dynamic_address(.Lhere) - link_address(.Lhere)".  */
+  __asm__ ("\
+	movi	%0, .Lhere\n\
+	mov	%1, a0\n\
+.Lhere:	_call0	0f\n\
+	.align	4\n\
+0:	sub	%0, a0, %0\n\
+	mov	a0, %1"
+	   : "=a" (addr), "=a" (tmp));
+
+  return addr - 3;
+}
+
+static inline void
+elf_machine_relative (Elf32_Addr load_off, const Elf32_Addr rel_addr,
+		      Elf32_Word relative_count)
+{
+  Elf32_Rela *rpnt = (Elf32_Rela *) rel_addr;
+  while (relative_count--)
+    {
+      Elf32_Addr *const reloc_addr = (Elf32_Addr *) (load_off + rpnt->r_offset);
+      *reloc_addr += load_off + rpnt->r_addend;
+      rpnt++;
+    }
+}

+ 285 - 0
ldso/ldso/xtensa/elfinterp.c

@@ -0,0 +1,285 @@
+/* vi: set sw=4 ts=4: */
+/* Xtensa ELF shared library loader suppport
+ *
+ * Copyright (C) 2007 Tensilica Inc.
+ * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald,
+ *                              David Engel, Hongjiu Lu and Mitch D'Souza
+ * Copyright (C) 2001-2004 Erik Andersen
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. The name of the above contributors may not be
+ *    used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "ldso.h"
+
+unsigned long
+_dl_linux_resolver (struct elf_resolve *tpnt, int reloc_entry)
+{
+	int reloc_type;
+	ELF_RELOC *this_reloc;
+	char *strtab;
+	Elf32_Sym *symtab;
+	int symtab_index;
+	char *rel_addr;
+	char *new_addr;
+	char **got_addr;
+	char *symname;
+
+	rel_addr = (char *) tpnt->dynamic_info[DT_JMPREL];
+	this_reloc = (ELF_RELOC *) (rel_addr + reloc_entry);
+	reloc_type = ELF32_R_TYPE (this_reloc->r_info);
+	symtab_index = ELF32_R_SYM (this_reloc->r_info);
+
+	symtab = (Elf32_Sym *) tpnt->dynamic_info[DT_SYMTAB];
+	strtab = (char *) tpnt->dynamic_info[DT_STRTAB];
+	symname = strtab + symtab[symtab_index].st_name;
+
+	if (unlikely (reloc_type != R_XTENSA_JMP_SLOT)) {
+		_dl_dprintf (2, "%s: Incorrect relocation type in jump relocations\n",
+					 _dl_progname);
+		_dl_exit (1);
+	}
+
+	/* Address of the literal to fix up.  */
+	got_addr = (char **) (this_reloc->r_offset + tpnt->loadaddr);
+
+	/* Get the address of the GOT entry.  */
+	new_addr = _dl_find_hash (symname, tpnt->symbol_scope, tpnt,
+							  ELF_RTYPE_CLASS_PLT);
+	if (unlikely (!new_addr)) {
+		_dl_dprintf (2, "%s: can't resolve symbol '%s'\n",
+					 _dl_progname, symname);
+		_dl_exit (1);
+	}
+
+#if defined (__SUPPORT_LD_DEBUG__)
+	if (_dl_debug_bindings) {
+		_dl_dprintf (_dl_debug_file, "\nresolve function: %s", symname);
+		if (_dl_debug_detail)
+			_dl_dprintf (_dl_debug_file, "\n\tpatched %x ==> %x @ %x\n",
+						 *got_addr, new_addr, got_addr);
+	}
+	if (!_dl_debug_nofixups)
+		*got_addr = new_addr;
+#else
+	*got_addr = new_addr;
+#endif
+
+	return (unsigned long) new_addr;
+}
+
+
+static int
+_dl_parse (struct elf_resolve *tpnt, struct dyn_elf *scope,
+		   unsigned long rel_addr, unsigned long rel_size,
+		   int (*reloc_fnc) (struct elf_resolve *tpnt, struct dyn_elf *scope,
+							 ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab))
+{
+	unsigned int i;
+	char *strtab;
+	Elf32_Sym *symtab;
+	ELF_RELOC *rpnt;
+	int symtab_index;
+
+	/* Parse the relocation information.  */
+	rpnt = (ELF_RELOC *) rel_addr;
+	rel_size /= sizeof (ELF_RELOC);
+
+	symtab = (Elf32_Sym *) tpnt->dynamic_info[DT_SYMTAB];
+	strtab = (char *) tpnt->dynamic_info[DT_STRTAB];
+
+	for (i = 0; i < rel_size; i++, rpnt++) {
+		int res;
+
+		symtab_index = ELF32_R_SYM (rpnt->r_info);
+
+		debug_sym (symtab, strtab, symtab_index);
+		debug_reloc (symtab, strtab, rpnt);
+
+		res = reloc_fnc (tpnt, scope, rpnt, symtab, strtab);
+
+		if (res == 0)
+			continue;
+
+		_dl_dprintf (2, "\n%s: ", _dl_progname);
+
+		if (symtab_index)
+			_dl_dprintf (2, "symbol '%s': ",
+						 strtab + symtab[symtab_index].st_name);
+
+		if (unlikely (res < 0)) {
+			int reloc_type = ELF32_R_TYPE (rpnt->r_info);
+#if defined (__SUPPORT_LD_DEBUG__)
+			_dl_dprintf (2, "can't handle reloc type %s\n",
+						 _dl_reltypes (reloc_type));
+#else
+			_dl_dprintf (2, "can't handle reloc type %x\n", reloc_type);
+#endif
+			_dl_exit (-res);
+		}
+		if (unlikely (res > 0)) {
+			_dl_dprintf (2, "can't resolve symbol\n");
+			return res;
+		}
+	}
+
+	return 0;
+}
+
+
+static int
+_dl_do_reloc (struct elf_resolve *tpnt, struct dyn_elf *scope,
+			  ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
+{
+	int reloc_type;
+	int symtab_index;
+	char *symname;
+	Elf32_Sym *sym;
+	Elf32_Addr *reloc_addr;
+	Elf32_Addr symbol_addr;
+#if defined (__SUPPORT_LD_DEBUG__)
+	Elf32_Addr old_val;
+#endif
+
+	reloc_addr = (Elf32_Addr *) (tpnt->loadaddr + rpnt->r_offset);
+	reloc_type = ELF32_R_TYPE (rpnt->r_info);
+	symtab_index = ELF32_R_SYM (rpnt->r_info);
+	sym = &symtab[symtab_index];
+	symbol_addr = 0;
+	symname = strtab + sym->st_name;
+
+	if (symtab_index) {
+		symbol_addr = (Elf32_Addr)
+			_dl_find_hash (symname, scope, tpnt,
+						   elf_machine_type_class (reloc_type));
+
+		/*
+		 * We want to allow undefined references to weak symbols - this might
+		 * have been intentional.  We should not be linking local symbols
+		 * here, so all bases should be covered.
+		 */
+		if (unlikely (!symbol_addr &&
+					  ELF32_ST_BIND (sym->st_info) != STB_WEAK)) {
+			_dl_dprintf (2, "%s: can't resolve symbol '%s'\n",
+						 _dl_progname, symname);
+			_dl_exit (1);
+		}
+	}
+
+#if defined (__SUPPORT_LD_DEBUG__)
+	old_val = *reloc_addr;
+#endif
+
+	switch (reloc_type) {
+	case R_XTENSA_NONE:
+		break;
+
+	case R_XTENSA_GLOB_DAT:
+	case R_XTENSA_JMP_SLOT:
+		*reloc_addr = symbol_addr + rpnt->r_addend;
+		break;
+
+	case R_XTENSA_RTLD:
+		if (rpnt->r_addend == 1) {
+			/* Grab the function pointer stashed at the beginning of the
+			   GOT by the GOT_INIT function.  */
+			*reloc_addr = *(Elf32_Addr *) tpnt->dynamic_info[DT_PLTGOT];
+		} else if (rpnt->r_addend == 2) {
+			/* Store the link map for the object.  */
+			*reloc_addr = (Elf32_Addr) tpnt;
+		} else {
+			_dl_exit (1);
+		}
+		break;
+
+	case R_XTENSA_RELATIVE:
+		*reloc_addr += tpnt->loadaddr + rpnt->r_addend;
+		break;
+
+	default:
+		return -1; /* Calls _dl_exit(1).  */
+	}
+#if defined (__SUPPORT_LD_DEBUG__)
+	if (_dl_debug_reloc && _dl_debug_detail)
+		_dl_dprintf (_dl_debug_file, "\tpatched: %x ==> %x @ %x",
+					 old_val, *reloc_addr, reloc_addr);
+#endif
+
+	return 0;
+}
+
+
+static int
+_dl_do_lazy_reloc (struct elf_resolve *tpnt, struct dyn_elf *scope,
+				   ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
+{
+	int reloc_type;
+	Elf32_Addr *reloc_addr;
+#if defined (__SUPPORT_LD_DEBUG__)
+	Elf32_Addr old_val;
+#endif
+
+	reloc_addr = (Elf32_Addr *) (tpnt->loadaddr + rpnt->r_offset);
+	reloc_type = ELF32_R_TYPE (rpnt->r_info);
+
+#if defined (__SUPPORT_LD_DEBUG__)
+	old_val = *reloc_addr;
+#endif
+
+	switch (reloc_type) {
+	case R_XTENSA_JMP_SLOT:
+		/* Perform a RELATIVE reloc on the GOT entry that transfers
+		   to the stub function.  */
+		*reloc_addr += tpnt->loadaddr;
+		break;
+	case R_XTENSA_NONE:
+		break;
+	default:
+		_dl_exit (1);
+	}
+
+#if defined (__SUPPORT_LD_DEBUG__)
+	if (_dl_debug_reloc && _dl_debug_detail)
+		_dl_dprintf (_dl_debug_file, "\tpatched: %x ==> %x @ %x",
+					 old_val, *reloc_addr, reloc_addr);
+#endif
+	return 0;
+
+}
+
+void
+_dl_parse_lazy_relocation_information (struct dyn_elf *rpnt,
+									   unsigned long rel_addr,
+									   unsigned long rel_size)
+{
+	(void) _dl_parse (rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc);
+}
+
+int
+_dl_parse_relocation_information (struct dyn_elf *rpnt,
+								  unsigned long rel_addr,
+								  unsigned long rel_size)
+{
+	return _dl_parse (rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size,
+					  _dl_do_reloc);
+}

+ 61 - 0
ldso/ldso/xtensa/resolve.S

@@ -0,0 +1,61 @@
+/* Xtensa dynamic resolver.
+   Parts copied from glibc/sysdeps/xtensa/dl-trampoline.S
+   Copyright (C) 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.  */
+
+#define MIN_FRAME_SIZE 32
+
+#ifdef __XTENSA_EB__
+#define XTENSA_IMM12_FLD_OFFSET 8
+#else /* __XTENSA_EL__ */
+#define XTENSA_IMM12_FLD_OFFSET 12
+#endif /* __XTENSA_EL__ */
+
+	.text
+	.align	4
+	.global	_dl_linux_resolve
+	.type	_dl_linux_resolve, @function
+_dl_linux_resolve:
+	/* Fix up the high 2 bits of the return address.  */
+	mov	a14, a0		// save a0 temporarily
+	_call0	0f
+	.align	4
+0:	extui	a13, a0, 30, 2
+	slli	a13, a13, 30
+	mov	a0, a14		// restore a0
+	slli	a12, a0, 2
+	srli	a12, a12, 2
+	or	a12, a12, a13
+
+	/* Call the fixup function.  */
+	movi	a8, _dl_linux_resolver
+	callx8	a8
+
+	/* Extract the target's frame size from the ENTRY instruction.  */
+	l32i	a11, a10, 0
+	extui	a11, a11, XTENSA_IMM12_FLD_OFFSET, 12
+	slli	a11, a11, 3
+
+	addi	a11, a11, -MIN_FRAME_SIZE
+	sub	a11, sp, a11
+	movsp	sp, a11
+
+	/* Jump to the next instruction past the ENTRY.  */
+	addi	a10, a10, 3
+	jx	a10
+	.size	_dl_linux_resolve, . - _dl_linux_resolve

+ 13 - 0
libc/string/xtensa/Makefile

@@ -0,0 +1,13 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2005 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+top_srcdir:=../../../
+top_builddir:=../../../
+all: objs
+include $(top_builddir)Rules.mak
+include ../Makefile.in
+include $(top_srcdir)Makerules

+ 297 - 0
libc/string/xtensa/memcpy.S

@@ -0,0 +1,297 @@
+/* Optimized memcpy for Xtensa.
+   Copyright (C) 2001, 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.  */
+
+#include "../../sysdeps/linux/xtensa/sysdep.h"
+#include <bits/xtensa-config.h>
+
+	.macro	src_b	r, w0, w1
+#ifdef __XTENSA_EB__
+	src	\r, \w0, \w1
+#else
+	src	\r, \w1, \w0
+#endif
+	.endm
+
+	.macro	ssa8	r
+#ifdef __XTENSA_EB__
+	ssa8b	\r
+#else
+	ssa8l	\r
+#endif
+	.endm
+
+/* If the Xtensa Unaligned Load Exception option is not used, this
+   code can run a few cycles faster by relying on the low address bits
+   being ignored.  However, if the code is then run with an Xtensa ISS
+   client that checks for unaligned accesses, it will produce a lot of
+   warning messages.  Set this flag to disable the use of unaligned
+   accesses and keep the ISS happy.  */
+
+#define UNALIGNED_ADDRESSES_CHECKED 1
+
+/* Do not use .literal_position in the ENTRY macro.  */
+#undef LITERAL_POSITION
+#define LITERAL_POSITION
+
+
+/* void *memcpy (void *dst, const void *src, size_t len)
+
+   The algorithm is as follows:
+
+   If the destination is unaligned, align it by conditionally
+   copying 1- and/or 2-byte pieces.
+
+   If the source is aligned, copy 16 bytes with a loop, and then finish up
+   with 8, 4, 2, and 1-byte copies conditional on the length.
+
+   Else (if source is unaligned), do the same, but use SRC to align the
+   source data.
+
+   This code tries to use fall-through branches for the common
+   case of aligned source and destination and multiple of 4 (or 8) length.  */
+
+
+/* Byte by byte copy.  */
+
+	.text
+	.align	4
+	.literal_position
+__memcpy_aux:
+
+	/* Skip a byte to get 1 mod 4 alignment for LOOPNEZ
+	   (0 mod 4 alignment for LBEG).  */
+	.byte	0
+
+.Lbytecopy:
+#if XCHAL_HAVE_LOOPS
+	loopnez	a4, 2f
+#else
+	beqz	a4, 2f
+	add	a7, a3, a4	// a7 = end address for source
+#endif
+1:	l8ui	a6, a3, 0
+	addi	a3, a3, 1
+	s8i	a6, a5, 0
+	addi	a5, a5, 1
+#if !XCHAL_HAVE_LOOPS
+	blt	a3, a7, 1b
+#endif
+2:	retw
+
+
+/* Destination is unaligned.  */
+
+	.align	4
+.Ldst1mod2: // dst is only byte aligned
+
+	/* Do short copies byte-by-byte.  */
+	_bltui	a4, 7, .Lbytecopy
+
+	/* Copy 1 byte.  */
+	l8ui	a6, a3, 0
+	addi	a3, a3, 1
+	addi	a4, a4, -1
+	s8i	a6, a5, 0
+	addi	a5, a5, 1
+
+	/* Return to main algorithm if dst is now aligned.  */
+	_bbci.l	a5, 1, .Ldstaligned
+
+.Ldst2mod4: // dst has 16-bit alignment
+
+	/* Do short copies byte-by-byte.  */
+	_bltui	a4, 6, .Lbytecopy
+
+	/* Copy 2 bytes.  */
+	l8ui	a6, a3, 0
+	l8ui	a7, a3, 1
+	addi	a3, a3, 2
+	addi	a4, a4, -2
+	s8i	a6, a5, 0
+	s8i	a7, a5, 1
+	addi	a5, a5, 2
+
+	/* dst is now aligned; return to main algorithm.  */
+	j	.Ldstaligned
+
+
+ENTRY (memcpy)
+	/* a2 = dst, a3 = src, a4 = len */
+
+	mov	a5, a2		// copy dst so that a2 is return value
+	_bbsi.l	a2, 0, .Ldst1mod2
+	_bbsi.l	a2, 1, .Ldst2mod4
+.Ldstaligned:
+
+	/* Get number of loop iterations with 16B per iteration.  */
+	srli	a7, a4, 4
+
+	/* Check if source is aligned.  */
+	movi	a8, 3
+	_bany	a3, a8, .Lsrcunaligned
+
+	/* Destination and source are word-aligned, use word copy.  */
+#if XCHAL_HAVE_LOOPS
+	loopnez	a7, 2f
+#else
+	beqz	a7, 2f
+	slli	a8, a7, 4
+	add	a8, a8, a3	// a8 = end of last 16B source chunk
+#endif
+1:	l32i	a6, a3, 0
+	l32i	a7, a3, 4
+	s32i	a6, a5, 0
+	l32i	a6, a3, 8
+	s32i	a7, a5, 4
+	l32i	a7, a3, 12
+	s32i	a6, a5, 8
+	addi	a3, a3, 16
+	s32i	a7, a5, 12
+	addi	a5, a5, 16
+#if !XCHAL_HAVE_LOOPS
+	blt	a3, a8, 1b
+#endif
+
+	/* Copy any leftover pieces smaller than 16B.  */
+2:	bbci.l	a4, 3, 3f
+
+	/* Copy 8 bytes.  */
+	l32i	a6, a3, 0
+	l32i	a7, a3, 4
+	addi	a3, a3, 8
+	s32i	a6, a5, 0
+	s32i	a7, a5, 4
+	addi	a5, a5, 8
+
+3:	bbsi.l	a4, 2, 4f
+	bbsi.l	a4, 1, 5f
+	bbsi.l	a4, 0, 6f
+	retw
+
+	/* Copy 4 bytes.  */
+4:	l32i	a6, a3, 0
+	addi	a3, a3, 4
+	s32i	a6, a5, 0
+	addi	a5, a5, 4
+	bbsi.l	a4, 1, 5f
+	bbsi.l	a4, 0, 6f
+	retw
+
+	/* Copy 2 bytes.  */
+5:	l16ui	a6, a3, 0
+	addi	a3, a3, 2
+	s16i	a6, a5, 0
+	addi	a5, a5, 2
+	bbsi.l	a4, 0, 6f
+	retw
+
+	/* Copy 1 byte.  */
+6:	l8ui	a6, a3, 0
+	s8i	a6, a5, 0
+
+.Ldone:
+	retw
+
+
+/* Destination is aligned; source is unaligned.  */
+
+	.align	4
+.Lsrcunaligned:
+	/* Avoid loading anything for zero-length copies.  */
+	_beqz	a4, .Ldone
+
+	/* Copy 16 bytes per iteration for word-aligned dst and
+	   unaligned src.  */
+	ssa8	a3		// set shift amount from byte offset
+#if UNALIGNED_ADDRESSES_CHECKED
+	and	a11, a3, a8	// save unalignment offset for below
+	sub	a3, a3, a11	// align a3
+#endif
+	l32i	a6, a3, 0	// load first word
+#if XCHAL_HAVE_LOOPS
+	loopnez	a7, 2f
+#else
+	beqz	a7, 2f
+	slli	a10, a7, 4
+	add	a10, a10, a3	// a10 = end of last 16B source chunk
+#endif
+1:	l32i	a7, a3, 4
+	l32i	a8, a3, 8
+	src_b	a6, a6, a7
+	s32i	a6, a5, 0
+	l32i	a9, a3, 12
+	src_b	a7, a7, a8
+	s32i	a7, a5, 4
+	l32i	a6, a3, 16
+	src_b	a8, a8, a9
+	s32i	a8, a5, 8
+	addi	a3, a3, 16
+	src_b	a9, a9, a6
+	s32i	a9, a5, 12
+	addi	a5, a5, 16
+#if !XCHAL_HAVE_LOOPS
+	blt	a3, a10, 1b
+#endif
+
+2:	bbci.l	a4, 3, 3f
+
+	/* Copy 8 bytes.  */
+	l32i	a7, a3, 4
+	l32i	a8, a3, 8
+	src_b	a6, a6, a7
+	s32i	a6, a5, 0
+	addi	a3, a3, 8
+	src_b	a7, a7, a8
+	s32i	a7, a5, 4
+	addi	a5, a5, 8
+	mov	a6, a8
+
+3:	bbci.l	a4, 2, 4f
+
+	/* Copy 4 bytes.  */
+	l32i	a7, a3, 4
+	addi	a3, a3, 4
+	src_b	a6, a6, a7
+	s32i	a6, a5, 0
+	addi	a5, a5, 4
+	mov	a6, a7
+4:
+#if UNALIGNED_ADDRESSES_CHECKED
+	add	a3, a3, a11	// readjust a3 with correct misalignment
+#endif
+	bbsi.l	a4, 1, 5f
+	bbsi.l	a4, 0, 6f
+	retw
+
+	/* Copy 2 bytes.  */
+5:	l8ui	a6, a3, 0
+	l8ui	a7, a3, 1
+	addi	a3, a3, 2
+	s8i	a6, a5, 0
+	s8i	a7, a5, 1
+	addi	a5, a5, 2
+	bbsi.l	a4, 0, 6f
+	retw
+
+	/* Copy 1 byte.  */
+6:	l8ui	a6, a3, 0
+	s8i	a6, a5, 0
+	retw
+
+libc_hidden_def (memcpy)

+ 165 - 0
libc/string/xtensa/memset.S

@@ -0,0 +1,165 @@
+/* Optimized memset for Xtensa.
+   Copyright (C) 2001, 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.  */
+
+#include "../../sysdeps/linux/xtensa/sysdep.h"
+#include <bits/xtensa-config.h>
+
+/* Do not use .literal_position in the ENTRY macro.  */
+#undef LITERAL_POSITION
+#define LITERAL_POSITION
+
+/* void *memset (void *dst, int c, size_t length)
+
+   The algorithm is as follows:
+
+   Create a word with c in all byte positions.
+	
+   If the destination is aligned, set 16B chunks with a loop, and then
+   finish up with 8B, 4B, 2B, and 1B stores conditional on the length.
+
+   If the destination is unaligned, align it by conditionally
+   setting 1B and/or 2B and then go to aligned case.
+
+   This code tries to use fall-through branches for the common
+   case of an aligned destination (except for the branches to
+   the alignment labels).  */
+
+
+/* Byte-by-byte set.  */
+
+	.text
+	.align	4
+	.literal_position
+__memset_aux:
+
+	/* Skip a byte to get 1 mod 4 alignment for LOOPNEZ
+	   (0 mod 4 alignment for LBEG).  */
+	.byte	0
+
+.Lbyteset:
+#if XCHAL_HAVE_LOOPS
+	loopnez	a4, 2f
+#else
+	beqz	a4, 2f
+	add	a6, a5, a4	// a6 = ending address
+#endif
+1:	s8i	a3, a5, 0
+	addi	a5, a5, 1
+#if !XCHAL_HAVE_LOOPS
+	blt	a5, a6, 1b
+#endif
+2:	retw
+
+
+/* Destination is unaligned.  */
+
+	.align	4
+
+.Ldst1mod2: // dst is only byte aligned
+
+	/* Do short sizes byte-by-byte.  */
+	bltui	a4, 8, .Lbyteset
+
+	/* Set 1 byte.  */
+	s8i	a3, a5, 0
+	addi	a5, a5, 1
+	addi	a4, a4, -1
+
+	/* Now retest if dst is aligned.  */
+	_bbci.l	a5, 1, .Ldstaligned
+
+.Ldst2mod4: // dst has 16-bit alignment
+
+	/* Do short sizes byte-by-byte.  */
+	bltui	a4, 8, .Lbyteset
+
+	/* Set 2 bytes.  */
+	s16i	a3, a5, 0
+	addi	a5, a5, 2
+	addi	a4, a4, -2
+
+	/* dst is now aligned; return to main algorithm */
+	j	.Ldstaligned
+
+
+ENTRY (memset)
+	/* a2 = dst, a3 = c, a4 = length */
+
+	/* Duplicate character into all bytes of word.  */
+	extui	a3, a3, 0, 8
+	slli	a7, a3, 8
+	or	a3, a3, a7
+	slli	a7, a3, 16
+	or	a3, a3, a7
+
+	mov	a5, a2		// copy dst so that a2 is return value
+
+	/* Check if dst is unaligned.  */
+	_bbsi.l	a2, 0, .Ldst1mod2
+	_bbsi.l	a2, 1, .Ldst2mod4
+.Ldstaligned:
+
+	/* Get number of loop iterations with 16B per iteration.  */
+	srli	a7, a4, 4
+
+	/* Destination is word-aligned.  */
+#if XCHAL_HAVE_LOOPS
+	loopnez	a7, 2f
+#else
+	beqz	a7, 2f
+	slli	a6, a7, 4
+	add	a6, a6, a5	// a6 = end of last 16B chunk
+#endif
+	/* Set 16 bytes per iteration.  */
+1:	s32i	a3, a5, 0
+	s32i	a3, a5, 4
+	s32i	a3, a5, 8
+	s32i	a3, a5, 12
+	addi	a5, a5, 16
+#if !XCHAL_HAVE_LOOPS
+	blt	a5, a6, 1b
+#endif
+
+	/* Set any leftover pieces smaller than 16B.  */
+2:	bbci.l	a4, 3, 3f
+
+	/* Set 8 bytes.  */
+	s32i	a3, a5, 0
+	s32i	a3, a5, 4
+	addi	a5, a5, 8
+
+3:	bbci.l	a4, 2, 4f
+
+	/* Set 4 bytes.  */
+	s32i	a3, a5, 0
+	addi	a5, a5, 4
+
+4:	bbci.l	a4, 1, 5f
+
+	/* Set 2 bytes.  */
+	s16i	a3, a5, 0
+	addi	a5, a5, 2
+
+5:	bbci.l	a4, 0, 6f
+
+	/* Set 1 byte.  */
+	s8i	a3, a5, 0
+6:	retw
+
+libc_hidden_def (memset)

+ 313 - 0
libc/string/xtensa/strcmp.S

@@ -0,0 +1,313 @@
+/* Optimized strcmp for Xtensa.
+   Copyright (C) 2001, 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.  */
+
+#include "../../sysdeps/linux/xtensa/sysdep.h"
+#include <bits/xtensa-config.h>
+
+#ifdef __XTENSA_EB__
+#define	MASK0 0xff000000
+#define	MASK1 0x00ff0000
+#define	MASK2 0x0000ff00
+#define	MASK3 0x000000ff
+#else
+#define	MASK0 0x000000ff
+#define	MASK1 0x0000ff00
+#define	MASK2 0x00ff0000
+#define	MASK3 0xff000000
+#endif
+
+#define MASK4 0x40404040
+
+	.literal .Lmask0, MASK0
+	.literal .Lmask1, MASK1
+	.literal .Lmask2, MASK2
+	.literal .Lmask3, MASK3
+	.literal .Lmask4, MASK4
+
+	.text
+ENTRY (strcmp)
+	/* a2 = s1, a3 = s2 */
+
+	l8ui	a8, a2, 0	// byte 0 from s1
+	l8ui	a9, a3, 0	// byte 0 from s2
+	movi	a10, 3		// mask
+	bne	a8, a9, .Lretdiff
+
+	or	a11, a2, a3
+	bnone	a11, a10, .Laligned
+
+	xor	a11, a2, a3	// compare low two bits of s1 and s2
+	bany	a11, a10, .Lunaligned	// if they have different alignment
+
+	/* s1/s2 are not word-aligned.  */
+	addi	a2, a2, 1	// advance s1
+	beqz	a8, .Leq	// bytes equal, if zero, strings are equal
+	addi	a3, a3, 1	// advance s2
+	bnone	a2, a10, .Laligned // if s1/s2 now aligned
+	l8ui	a8, a2, 0	// byte 1 from s1
+	l8ui	a9, a3, 0	// byte 1 from s2
+	addi	a2, a2, 1	// advance s1
+	bne	a8, a9, .Lretdiff // if different, return difference
+	beqz	a8, .Leq	// bytes equal, if zero, strings are equal
+	addi	a3, a3, 1	// advance s2
+	bnone	a2, a10, .Laligned // if s1/s2 now aligned
+	l8ui	a8, a2, 0	// byte 2 from s1
+	l8ui	a9, a3, 0	// byte 2 from s2
+	addi	a2, a2, 1	// advance s1
+	bne	a8, a9, .Lretdiff // if different, return difference
+	beqz	a8, .Leq	// bytes equal, if zero, strings are equal
+	addi	a3, a3, 1	// advance s2
+	j	.Laligned
+
+/* s1 and s2 have different alignment.
+
+   If the zero-overhead loop option is available, use an (almost)
+   infinite zero-overhead loop with conditional exits so we only pay
+   for taken branches when exiting the loop.
+
+   Note: It is important for this unaligned case to come before the
+   code for aligned strings, because otherwise some of the branches
+   above cannot reach and have to be transformed to branches around
+   jumps.  The unaligned code is smaller and the branches can reach
+   over it.  */
+
+	.align	4
+	/* (2 mod 4) alignment for loop instruction */
+.Lunaligned:
+#if XCHAL_HAVE_LOOPS
+	_movi.n	a8, 0		// set up for the maximum loop count
+	loop	a8, .Lretdiff	// loop forever (almost anyway)
+#endif
+.Lnextbyte:
+	l8ui	a8, a2, 0
+	l8ui	a9, a3, 0
+	addi	a2, a2, 1
+	bne	a8, a9, .Lretdiff
+	addi	a3, a3, 1
+#if XCHAL_HAVE_LOOPS
+	beqz	a8, .Lretdiff
+#else
+	bnez	a8, .Lnextbyte
+#endif
+.Lretdiff:
+	sub	a2, a8, a9
+	retw
+
+/* s1 is word-aligned; s2 is word-aligned.
+
+   If the zero-overhead loop option is available, use an (almost)
+   infinite zero-overhead loop with conditional exits so we only pay
+   for taken branches when exiting the loop.  */
+
+/* New algorithm, relying on the fact that all normal ASCII is between
+   32 and 127.
+
+   Rather than check all bytes for zero:
+   Take one word (4 bytes).  Call it w1.
+   Shift w1 left by one into w1'.
+   Or w1 and w1'.  For all normal ASCII bit 6 will be 1; for zero it won't.
+   Check that all 4 bit 6's (one for each byte) are one:
+   If they are, we are definitely not done.
+   If they are not, we are probably done, but need to check for zero.  */
+
+	.align	4
+#if XCHAL_HAVE_LOOPS
+.Laligned:
+	.begin	no-transform
+	l32r	a4, .Lmask0	// mask for byte 0
+	l32r	a7, .Lmask4
+	/* Loop forever.  (a4 is more than than the maximum number
+	   of iterations) */
+	loop	a4, .Laligned_done
+
+	/* First unrolled loop body.  */
+	l32i	a8, a2, 0	// get word from s1
+	l32i	a9, a3, 0	// get word from s2
+	slli	a5, a8, 1
+	bne	a8, a9, .Lwne2
+	or	a9, a8, a5
+	bnall	a9, a7, .Lprobeq
+
+	/* Second unrolled loop body.  */
+	l32i	a8, a2, 4	// get word from s1+4
+	l32i	a9, a3, 4	// get word from s2+4
+	slli	a5, a8, 1
+	bne	a8, a9, .Lwne2
+	or	a9, a8, a5
+	bnall	a9, a7, .Lprobeq2
+
+	addi	a2, a2, 8	// advance s1 pointer
+	addi	a3, a3, 8	// advance s2 pointer
+.Laligned_done:
+	or	a1, a1, a1	// nop
+
+.Lprobeq2:
+	/* Adjust pointers to account for the loop unrolling.  */
+	addi	a2, a2, 4
+	addi	a3, a3, 4
+
+#else /* !XCHAL_HAVE_LOOPS */
+
+.Laligned:
+	movi	a4, MASK0	// mask for byte 0
+	movi	a7, MASK4
+	j	.Lfirstword
+.Lnextword:
+	addi	a2, a2, 4	// advance s1 pointer
+	addi	a3, a3, 4	// advance s2 pointer
+.Lfirstword:
+	l32i	a8, a2, 0	// get word from s1
+	l32i	a9, a3, 0	// get word from s2
+	slli	a5, a8, 1
+	bne	a8, a9, .Lwne2
+	or	a9, a8, a5
+	ball	a9, a7, .Lnextword
+#endif /* !XCHAL_HAVE_LOOPS */
+
+	/* align (0 mod 4) */
+.Lprobeq:
+	/* Words are probably equal, but check for sure.
+	   If not, loop over the rest of string using normal algorithm.  */
+
+	bnone	a8, a4, .Leq	// if byte 0 is zero
+	l32r	a5, .Lmask1	// mask for byte 1
+	l32r	a6, .Lmask2	// mask for byte 2
+	bnone	a8, a5, .Leq	// if byte 1 is zero
+	l32r	a7, .Lmask3	// mask for byte 3
+	bnone	a8, a6, .Leq	// if byte 2 is zero
+	bnone	a8, a7, .Leq	// if byte 3 is zero
+	addi.n	a2, a2, 4	// advance s1 pointer
+	addi.n	a3, a3, 4	// advance s2 pointer
+#if XCHAL_HAVE_LOOPS
+
+	/* align (1 mod 4) */
+	loop	a4, .Leq	// loop forever (a4 is bigger than max iters)
+	.end	no-transform
+
+	l32i	a8, a2, 0	// get word from s1
+	l32i	a9, a3, 0	// get word from s2
+	addi	a2, a2, 4	// advance s1 pointer
+	bne	a8, a9, .Lwne
+	bnone	a8, a4, .Leq	// if byte 0 is zero
+	bnone	a8, a5, .Leq	// if byte 1 is zero
+	bnone	a8, a6, .Leq	// if byte 2 is zero
+	bnone	a8, a7, .Leq	// if byte 3 is zero
+	addi	a3, a3, 4	// advance s2 pointer
+
+#else /* !XCHAL_HAVE_LOOPS */
+
+	j	.Lfirstword2
+.Lnextword2:
+	addi	a3, a3, 4	// advance s2 pointer
+.Lfirstword2:
+	l32i	a8, a2, 0	// get word from s1
+	l32i	a9, a3, 0	// get word from s2
+	addi	a2, a2, 4	// advance s1 pointer
+	bne	a8, a9, .Lwne
+	bnone	a8, a4, .Leq	// if byte 0 is zero
+	bnone	a8, a5, .Leq	// if byte 1 is zero
+	bnone	a8, a6, .Leq	// if byte 2 is zero
+	bany	a8, a7, .Lnextword2	// if byte 3 is zero
+#endif /* !XCHAL_HAVE_LOOPS */
+
+	/* Words are equal; some byte is zero.  */
+.Leq:	movi	a2, 0		// return equal
+	retw
+
+.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
+	   comparison.  */
+#ifdef __XTENSA_EB__
+	or	a10, a8, a5
+	bnall	a10, a7, .Lsomezero
+	bgeu	a8, a9, .Lposreturn
+	movi	a2, -1
+	retw
+.Lposreturn:
+	movi	a2, 1
+	retw
+.Lsomezero:	// There is probably some zero byte.
+#endif /* __XTENSA_EB__ */
+.Lwne:	/* Words are not equal.  */
+	xor	a2, a8, a9	// get word with nonzero in byte that differs
+	bany	a2, a4, .Ldiff0	// if byte 0 differs
+	movi	a5, MASK1	// mask for byte 1
+	bnone	a8, a4, .Leq	// if byte 0 is zero
+	bany	a2, a5, .Ldiff1	// if byte 1 differs
+	movi	a6, MASK2	// mask for byte 2
+	bnone	a8, a5, .Leq	// if byte 1 is zero
+	bany	a2, a6, .Ldiff2	// if byte 2 differs
+	bnone	a8, a6, .Leq	// if byte 2 is zero
+#ifdef __XTENSA_EB__
+.Ldiff3:
+.Ldiff2:
+.Ldiff1:
+	/* Byte 0 is equal (at least) and there is a difference before a zero
+	   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
+
+.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
+
+#else /* !__XTENSA_EB__ */
+	/* Little-endian is a little more difficult because can't subtract
+	   whole words.  */
+.Ldiff3:
+	/* Bytes 0-2 are equal; byte 3 is different.
+	   For little-endian need to have a sign bit for the difference.  */
+	extui	a10, a8, 24, 8
+	extui	a11, a9, 24, 8
+	sub	a2, a10, a11
+	retw
+
+.Ldiff0:
+	/* Byte 0 is different.  */
+	extui	a10, a8, 0, 8
+	extui	a11, a9, 0, 8
+	sub	a2, a10, a11
+	retw
+
+.Ldiff1:
+	/* Byte 0 is equal; byte 1 is different.  */
+	extui	a10, a8, 8, 8
+	extui	a11, a9, 8, 8
+	sub	a2, a10, a11
+	retw
+
+.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
+
+#endif /* !__XTENSA_EB */
+
+libc_hidden_def (strcmp)
+
+#ifndef __UCLIBC_HAS_LOCALE__
+strong_alias (strcmp, strcoll)
+libc_hidden_def (strcoll)
+#endif

+ 150 - 0
libc/string/xtensa/strcpy.S

@@ -0,0 +1,150 @@
+/* Optimized strcpy for Xtensa.
+   Copyright (C) 2001, 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.  */
+
+#include "../../sysdeps/linux/xtensa/sysdep.h"
+#include <bits/xtensa-config.h>
+
+#ifdef __XTENSA_EB__
+#define	MASK0 0xff000000
+#define	MASK1 0x00ff0000
+#define	MASK2 0x0000ff00
+#define	MASK3 0x000000ff
+#else
+#define	MASK0 0x000000ff
+#define	MASK1 0x0000ff00
+#define	MASK2 0x00ff0000
+#define	MASK3 0xff000000
+#endif
+
+	.text
+ENTRY (strcpy)
+	/* a2 = dst, a3 = src */
+
+	mov	a10, a2		// leave dst in return value register
+	movi	a4, MASK0
+	movi	a5, MASK1
+	movi	a6, MASK2
+	movi	a7, MASK3
+	bbsi.l	a3, 0, .Lsrc1mod2
+	bbsi.l	a3, 1, .Lsrc2mod4
+.Lsrcaligned:
+
+	/* Check if the destination is aligned.  */
+	movi	a8, 3
+	bnone	a10, a8, .Laligned
+
+	j	.Ldstunaligned
+
+.Lsrc1mod2: // src address is odd
+	l8ui	a8, a3, 0	// get byte 0
+	addi	a3, a3, 1	// advance src pointer
+	s8i	a8, a10, 0	// store byte 0
+	beqz	a8, 1f		// if byte 0 is zero
+	addi	a10, a10, 1	// advance dst pointer
+	bbci.l	a3, 1, .Lsrcaligned // if src is now word-aligned
+
+.Lsrc2mod4: // src address is 2 mod 4
+	l8ui	a8, a3, 0	// get byte 0
+	/* 1-cycle interlock */
+	s8i	a8, a10, 0	// store byte 0
+	beqz	a8, 1f		// if byte 0 is zero
+	l8ui	a8, a3, 1	// get byte 0
+	addi	a3, a3, 2	// advance src pointer
+	s8i	a8, a10, 1	// store byte 0
+	addi	a10, a10, 2	// advance dst pointer
+	bnez	a8, .Lsrcaligned
+1:	retw
+
+
+/* dst is word-aligned; src is word-aligned.  */
+
+	.align	4
+#if XCHAL_HAVE_LOOPS
+	/* (2 mod 4) alignment for loop instruction */
+.Laligned:
+	_movi.n	a8, 0		// set up for the maximum loop count
+	loop	a8, .Lz3	// loop forever (almost anyway)
+	l32i	a8, a3, 0	// get word from src
+	addi	a3, a3, 4	// advance src pointer
+	bnone	a8, a4, .Lz0	// if byte 0 is zero
+	bnone	a8, a5, .Lz1	// if byte 1 is zero
+	bnone	a8, a6, .Lz2	// if byte 2 is zero
+	s32i	a8, a10, 0	// store word to dst
+	bnone	a8, a7, .Lz3	// if byte 3 is zero
+	addi	a10, a10, 4	// advance dst pointer
+
+#else /* !XCHAL_HAVE_LOOPS */
+
+1:	addi	a10, a10, 4	// advance dst pointer
+.Laligned:
+	l32i	a8, a3, 0	// get word from src
+	addi	a3, a3, 4	// advance src pointer
+	bnone	a8, a4, .Lz0	// if byte 0 is zero
+	bnone	a8, a5, .Lz1	// if byte 1 is zero
+	bnone	a8, a6, .Lz2	// if byte 2 is zero
+	s32i	a8, a10, 0	// store word to dst
+	bany	a8, a7, 1b	// if byte 3 is zero
+#endif /* !XCHAL_HAVE_LOOPS */
+
+.Lz3:	/* Byte 3 is zero.  */
+	retw
+
+.Lz0:	/* Byte 0 is zero.  */
+#ifdef __XTENSA_EB__
+	movi	a8, 0
+#endif
+	s8i	a8, a10, 0
+	retw
+
+.Lz1:	/* Byte 1 is zero.  */
+#ifdef __XTENSA_EB__
+        extui   a8, a8, 16, 16
+#endif
+	s16i	a8, a10, 0
+	retw
+
+.Lz2:	/* Byte 2 is zero.  */
+#ifdef __XTENSA_EB__
+        extui   a8, a8, 16, 16
+#endif
+	s16i	a8, a10, 0
+	movi	a8, 0
+	s8i	a8, a10, 2
+	retw
+
+	.align	4
+	/* (2 mod 4) alignment for loop instruction */
+.Ldstunaligned:
+
+#if XCHAL_HAVE_LOOPS
+	_movi.n	a8, 0		// set up for the maximum loop count
+	loop	a8, 2f		// loop forever (almost anyway)
+#endif
+1:	l8ui	a8, a3, 0
+	addi	a3, a3, 1
+	s8i	a8, a10, 0
+	addi	a10, a10, 1
+#if XCHAL_HAVE_LOOPS
+	beqz	a8, 2f
+#else
+	bnez	a8, 1b
+#endif
+2:	retw
+
+libc_hidden_def (strcpy)

+ 104 - 0
libc/string/xtensa/strlen.S

@@ -0,0 +1,104 @@
+/* Optimized strlen for Xtensa.
+   Copyright (C) 2001, 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.  */
+
+#include "../../sysdeps/linux/xtensa/sysdep.h"
+#include <bits/xtensa-config.h>
+
+#ifdef __XTENSA_EB__
+#define	MASK0 0xff000000
+#define	MASK1 0x00ff0000
+#define	MASK2 0x0000ff00
+#define	MASK3 0x000000ff
+#else
+#define	MASK0 0x000000ff
+#define	MASK1 0x0000ff00
+#define	MASK2 0x00ff0000
+#define	MASK3 0xff000000
+#endif
+
+	.text
+ENTRY (strlen)
+	/* a2 = s */
+
+	addi	a3, a2, -4	// because we overincrement at the end
+	movi	a4, MASK0
+	movi	a5, MASK1
+	movi	a6, MASK2
+	movi	a7, MASK3
+	bbsi.l	a2, 0, .L1mod2
+	bbsi.l	a2, 1, .L2mod4
+	j	.Laligned
+
+.L1mod2: // address is odd
+	l8ui	a8, a3, 4	// get byte 0
+	addi	a3, a3, 1	// advance string pointer
+	beqz	a8, .Lz3	// if byte 0 is zero
+	bbci.l	a3, 1, .Laligned // if string pointer is now word-aligned
+
+.L2mod4: // address is 2 mod 4
+	addi	a3, a3, 2	// advance ptr for aligned access
+	l32i	a8, a3, 0	// get word with first two bytes of string
+	bnone	a8, a6, .Lz2	// if byte 2 (of word, not string) is zero
+	bany	a8, a7, .Laligned // if byte 3 (of word, not string) is nonzero
+
+	/* Byte 3 is zero.  */
+	addi	a3, a3, 3	// point to zero byte
+	sub	a2, a3, a2	// subtract to get length
+	retw
+
+
+/* String is word-aligned.  */
+
+	.align	4
+	/* (2 mod 4) alignment for loop instruction */
+.Laligned:
+#if XCHAL_HAVE_LOOPS
+	_movi.n	a8, 0		// set up for the maximum loop count
+	loop	a8, .Lz3	// loop forever (almost anyway)
+#endif
+1:	l32i	a8, a3, 4	// get next word of string
+	addi	a3, a3, 4	// advance string pointer
+	bnone	a8, a4, .Lz0	// if byte 0 is zero
+	bnone	a8, a5, .Lz1	// if byte 1 is zero
+	bnone	a8, a6, .Lz2	// if byte 2 is zero
+#if XCHAL_HAVE_LOOPS
+	bnone	a8, a7, .Lz3	// if byte 3 is zero
+#else
+	bany	a8, a7, 1b	// repeat if byte 3 is non-zero
+#endif
+
+.Lz3:	/* Byte 3 is zero.  */
+	addi	a3, a3, 3	// point to zero byte
+	/* Fall through....  */
+
+.Lz0:	/* Byte 0 is zero.  */
+	sub	a2, a3, a2	// subtract to get length
+	retw
+
+.Lz1:	/* Byte 1 is zero.  */
+	addi	a3, a3, 1	// point to zero byte
+	sub	a2, a3, a2	// subtract to get length
+	retw
+
+.Lz2:	/* Byte 2 is zero.  */
+	addi	a3, a3, 2	// point to zero byte
+	sub	a2, a3, a2	// subtract to get length
+	retw
+
+libc_hidden_def (strlen)

+ 241 - 0
libc/string/xtensa/strncpy.S

@@ -0,0 +1,241 @@
+/* Optimized strcpy for Xtensa.
+   Copyright (C) 2001, 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.  */
+
+#include "../../sysdeps/linux/xtensa/sysdep.h"
+#include <bits/xtensa-config.h>
+
+#ifdef __XTENSA_EB__
+#define	MASK0 0xff000000
+#define	MASK1 0x00ff0000
+#define	MASK2 0x0000ff00
+#define	MASK3 0x000000ff
+#else
+#define	MASK0 0x000000ff
+#define	MASK1 0x0000ff00
+#define	MASK2 0x00ff0000
+#define	MASK3 0xff000000
+#endif
+
+/* Do not use .literal_position in the ENTRY macro.  */
+#undef LITERAL_POSITION
+#define LITERAL_POSITION
+
+	.text
+	.align	4
+	.literal_position
+__strncpy_aux:
+
+.Lsrc1mod2: // src address is odd
+	l8ui	a8, a3, 0	// get byte 0
+	addi	a3, a3, 1	// advance src pointer
+	s8i	a8, a10, 0	// store byte 0
+	addi	a4, a4, -1	// decrement n
+	beqz    a4, .Lret       // if n is zero
+	addi	a10, a10, 1	// advance dst pointer
+	beqz	a8, .Lfill	// if byte 0 is zero
+	bbci.l	a3, 1, .Lsrcaligned // if src is now word-aligned
+
+.Lsrc2mod4: // src address is 2 mod 4
+	l8ui	a8, a3, 0	// get byte 0
+	addi	a4, a4, -1	// decrement n
+	s8i	a8, a10, 0	// store byte 0
+	beqz    a4, .Lret       // if n is zero
+	addi	a10, a10, 1	// advance dst pointer
+	beqz	a8, .Lfill	// if byte 0 is zero
+	l8ui	a8, a3, 1	// get byte 0
+	addi	a3, a3, 2	// advance src pointer
+	s8i	a8, a10, 0	// store byte 0
+	addi	a4, a4, -1	// decrement n
+	beqz    a4, .Lret       // if n is zero
+	addi	a10, a10, 1	// advance dst pointer
+	bnez	a8, .Lsrcaligned
+	j	.Lfill
+
+.Lret:
+	retw
+
+
+ENTRY (strncpy)
+	/* a2 = dst, a3 = src */
+
+	mov	a10, a2		// leave dst in return value register
+	beqz    a4, .Lret       // if n is zero
+
+	movi	a11, MASK0
+	movi	a5, MASK1
+	movi	a6, MASK2
+	movi	a7, MASK3
+	bbsi.l	a3, 0, .Lsrc1mod2
+	bbsi.l	a3, 1, .Lsrc2mod4
+.Lsrcaligned:
+
+	/* Check if the destination is aligned.  */
+	movi	a8, 3
+	bnone	a10, a8, .Laligned
+
+	j	.Ldstunaligned
+
+
+/* Fill the dst with zeros -- n is at least 1.  */
+
+.Lfill:
+	movi	a9, 0
+	bbsi.l	a10, 0, .Lfill1mod2
+	bbsi.l	a10, 1, .Lfill2mod4
+.Lfillaligned:
+	blti	a4, 4, .Lfillcleanup
+
+	/* Loop filling complete words with zero.  */
+#if XCHAL_HAVE_LOOPS
+
+	srai	a8, a4, 2
+	loop	a8, 1f
+	s32i	a9, a10, 0
+	addi	a10, a10, 4
+
+1:	slli	a8, a8, 2
+	sub	a4, a4, a8
+
+#else /* !XCHAL_HAVE_LOOPS */
+
+1:	s32i	a9, a10, 0
+	addi	a10, a10, 4
+	addi	a4, a4, -4
+	bgei    a4, 4, 1b
+
+#endif /* !XCHAL_HAVE_LOOPS */
+
+	beqz	a4, 2f
+
+.Lfillcleanup:
+	/* Fill leftover (1 to 3) bytes with zero.  */
+	s8i	a9, a10, 0	// store byte 0
+	addi	a4, a4, -1	// decrement n
+	addi	a10, a10, 1
+	bnez    a4, .Lfillcleanup 
+
+2:	retw
+	
+.Lfill1mod2: // dst address is odd
+	s8i	a9, a10, 0	// store byte 0
+	addi	a4, a4, -1	// decrement n
+	beqz    a4, 2b		// if n is zero
+	addi    a10, a10, 1	// advance dst pointer
+	bbci.l	a10, 1, .Lfillaligned // if dst is now word-aligned
+
+.Lfill2mod4: // dst address is 2 mod 4
+	s8i	a9, a10, 0	// store byte 0
+	addi	a4, a4, -1	// decrement n
+	beqz    a4, 2b		// if n is zero
+	s8i	a9, a10, 1	// store byte 1
+	addi	a4, a4, -1	// decrement n
+	beqz    a4, 2b		// if n is zero
+	addi    a10, a10, 2	// advance dst pointer
+	j	.Lfillaligned
+
+
+/* dst is word-aligned; src is word-aligned; n is at least 1.  */
+
+	.align	4
+	/* (2 mod 4) alignment for loop instruction */
+.Laligned:
+#if XCHAL_HAVE_LOOPS
+	_movi.n	a8, 0		// set up for the maximum loop count
+	loop	a8, 1f		// loop forever (almost anyway)
+	blti	a4, 5, .Ldstunaligned // n is near limit; do one at a time
+	l32i	a8, a3, 0	// get word from src
+	addi	a3, a3, 4	// advance src pointer
+	bnone	a8, a11, .Lz0	// if byte 0 is zero
+	bnone	a8, a5, .Lz1	// if byte 1 is zero
+	bnone	a8, a6, .Lz2	// if byte 2 is zero
+	s32i	a8, a10, 0	// store word to dst
+	addi	a4, a4, -4	// decrement n
+	addi	a10, a10, 4	// advance dst pointer
+	bnone	a8, a7, .Lfill	// if byte 3 is zero
+1:	
+
+#else /* !XCHAL_HAVE_LOOPS */
+
+1:	blti	a4, 5, .Ldstunaligned // n is near limit; do one at a time
+	l32i	a8, a3, 0	// get word from src
+	addi	a3, a3, 4	// advance src pointer
+	bnone	a8, a11, .Lz0	// if byte 0 is zero
+	bnone	a8, a5, .Lz1	// if byte 1 is zero
+	bnone	a8, a6, .Lz2	// if byte 2 is zero
+	s32i	a8, a10, 0	// store word to dst
+	addi	a4, a4, -4	// decrement n
+	addi	a10, a10, 4	// advance dst pointer
+	bany	a8, a7, 1b	// no zeroes
+#endif /* !XCHAL_HAVE_LOOPS */
+
+	j	.Lfill
+
+.Lz0:	/* Byte 0 is zero.  */
+#ifdef __XTENSA_EB__
+	movi	a8, 0
+#endif
+	s8i	a8, a10, 0
+	addi	a4, a4, -1	// decrement n
+	addi	a10, a10, 1	// advance dst pointer
+	j	.Lfill
+
+.Lz1:	/* Byte 1 is zero.  */
+#ifdef __XTENSA_EB__
+        extui   a8, a8, 16, 16
+#endif
+	s16i	a8, a10, 0
+	addi	a4, a4, -2	// decrement n
+	addi	a10, a10, 2	// advance dst pointer
+	j	.Lfill
+
+.Lz2:	/* Byte 2 is zero.  */
+#ifdef __XTENSA_EB__
+        extui   a8, a8, 16, 16
+#endif
+	s16i	a8, a10, 0
+	movi	a8, 0
+	s8i	a8, a10, 2
+	addi	a4, a4, -3	// decrement n
+	addi	a10, a10, 3	// advance dst pointer
+	j	.Lfill
+
+	.align	4
+	/* (2 mod 4) alignment for loop instruction */
+.Ldstunaligned:
+
+#if XCHAL_HAVE_LOOPS
+	_movi.n	a8, 0		// set up for the maximum loop count
+	loop	a8, 2f		// loop forever (almost anyway)
+#endif
+1:	l8ui	a8, a3, 0
+	addi	a3, a3, 1
+	s8i	a8, a10, 0
+	addi	a4, a4, -1
+	beqz	a4, 3f
+	addi	a10, a10, 1
+#if XCHAL_HAVE_LOOPS
+	beqz	a8, 2f
+#else
+	bnez	a8, 1b
+#endif
+2:	j	.Lfill
+
+3:	retw
+
+libc_hidden_def (strncpy)

+ 13 - 0
libc/sysdeps/linux/xtensa/Makefile

@@ -0,0 +1,13 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2005 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+top_srcdir=../../../../
+top_builddir=../../../../
+all: objs
+include $(top_builddir)Rules.mak
+include Makefile.arch
+include $(top_srcdir)Makerules

+ 14 - 0
libc/sysdeps/linux/xtensa/Makefile.arch

@@ -0,0 +1,14 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2007 Tensilica Inc.
+#
+# 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 \
+     	__syscall_error.c
+
+SSRC := bsd-_setjmp.S bsd-setjmp.S setjmp.S clone.S \
+	syscall.S mmap.S windowspill.S __longjmp.S vfork.S
+
+include $(top_srcdir)libc/sysdeps/linux/Makefile.commonarch

+ 126 - 0
libc/sysdeps/linux/xtensa/__longjmp.S

@@ -0,0 +1,126 @@
+/* longjmp for Xtensa Processors.
+
+   Copyright (C) 2001, 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.  */
+
+/* This implementation relies heavily on the Xtensa register window
+   mechanism.  Setjmp flushes all the windows except its own to the
+   stack and then copies registers from the save areas on the stack
+   into the jmp_buf structure, along with the return address of the call
+   to setjmp.  Longjmp invalidates all the windows except its own, and
+   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.  */
+
+
+#include "sysdep.h"
+
+
+ENTRY (__longjmp)
+
+	/* Invalidate all but the current window.  Reading and writing
+	   special registers WINDOWBASE and WINDOWSTART are
+	   privileged operations, so user processes must call the
+	   slower __window_spill() to do the job.  */
+
+	movi	a4, __window_spill
+	callx4	a4
+
+	/* Return to the return address of the setjmp, using the
+	   window size bits from the setjmp call so that the caller
+	   will be able to find the return value that we put in a2.  */
+
+	l32i	a0, a2, 64
+
+	/* Copy the first 4 saved registers from jmp_buf into the save area
+	   at the current sp so that the values will be restored to registers
+	   when longjmp returns. */
+
+	addi	a7, a1, -16
+	l32i	a4, a2, 0
+	l32i	a5, a2, 4
+	s32i	a4, a7, 0
+	s32i	a5, a7, 4
+	l32i	a4, a2, 8
+	l32i	a5, a2, 12
+	s32i	a4, a7, 8
+	s32i	a5, a7, 12
+
+	/* Copy the remaining 0-8 saved registers.  */
+	extui	a7, a0, 30, 2
+	blti	a7, 2, .Lendlj
+	l32i	a8, a2, 52
+	slli	a4, a7, 4
+	sub	a6, a8, a4
+	addi	a5, a2, 16
+	addi	a8, a8, -16		// a8 = end of register overflow area
+.Lljloop:
+	l32i	a7, a5, 0
+	l32i	a4, a5, 4
+	s32i	a7, a6, 0
+	s32i	a4, a6, 4
+	l32i	a7, a5, 8
+	l32i	a4, a5, 12
+	s32i	a7, a6, 8
+	s32i	a4, a6, 12
+	addi	a5, a5, 16
+	addi	a6, a6, 16
+	blt	a6, a8, .Lljloop
+.Lendlj:
+
+	/* The 4 words saved from the register save area at the target's
+	   sp are copied back to the target procedure's save area.  The
+	   only point of this is to prevent a catastrophic failure in
+	   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	a4, a2, 48
+	l32i	a5, a2, 52
+	s32i	a4, a7, 0
+	s32i	a5, a7, 4
+	l32i	a4, a2, 56
+	l32i	a5, a2, 60
+	s32i	a4, a7, 8
+	s32i	a5, a7, 12
+
+	/* Return v ? v : 1.  */
+	movi	a2, 1
+	movnez	a2, a3, a3
+
+	retw
+END (__longjmp)
+
+libc_hidden_def (__longjmp)

+ 18 - 0
libc/sysdeps/linux/xtensa/__syscall_error.c

@@ -0,0 +1,18 @@
+/* Wrapper for setting errno.
+ *
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#include <errno.h>
+#include <features.h>
+
+/* This routine is jumped to by all the syscall handlers, to stash
+ * an error number into errno.  */
+int __syscall_error(int err_no) attribute_hidden;
+int __syscall_error(int err_no)
+{
+	__set_errno(-err_no);
+	return -1;
+}

+ 10 - 0
libc/sysdeps/linux/xtensa/bits/endian.h

@@ -0,0 +1,10 @@
+#ifndef _ENDIAN_H
+# error "Never use <bits/endian.h> directly; include <endian.h> instead."
+#endif
+
+/* Xtensa can be either big or little endian.  */
+#ifdef __XTENSA_EB__
+# define __BYTE_ORDER __BIG_ENDIAN
+#else
+# define __BYTE_ORDER __LITTLE_ENDIAN
+#endif

+ 196 - 0
libc/sysdeps/linux/xtensa/bits/fcntl.h

@@ -0,0 +1,196 @@
+/* O_*, F_*, FD_* bit values for Linux.
+   Copyright (C) 1995, 1996, 1997, 1998, 2000, 2004, 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	_FCNTL_H
+# error "Never use <bits/fcntl.h> directly; include <fcntl.h> instead."
+#endif
+
+#include <sys/types.h>
+#ifdef __USE_GNU
+# include <bits/uio.h>
+#endif
+
+
+/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
+   located on an ext2 file system */
+#define O_ACCMODE	   0003
+#define O_RDONLY	     00
+#define O_WRONLY	     01
+#define O_RDWR		     02
+#define O_CREAT		   0100	/* not fcntl */
+#define O_EXCL		   0200	/* not fcntl */
+#define O_NOCTTY	   0400	/* not fcntl */
+#define O_TRUNC		  01000	/* not fcntl */
+#define O_APPEND	  02000
+#define O_NONBLOCK	  04000
+#define O_NDELAY	O_NONBLOCK
+#define O_SYNC		 010000
+#define O_FSYNC		 O_SYNC
+#define O_ASYNC		 020000
+
+#ifdef __USE_GNU
+# define O_DIRECT	 040000	/* Direct disk access.	*/
+# define O_DIRECTORY	0200000	/* Must be a directory.	 */
+# define O_NOFOLLOW	0400000	/* Do not follow links.	 */
+# define O_NOATIME     01000000 /* Do not set atime.  */
+#endif
+
+/* For now Linux has synchronisity options for data and read operations.
+   We define the symbols here but let them do the same as O_SYNC since
+   this is a superset.	*/
+#if defined __USE_POSIX199309 || defined __USE_UNIX98
+# define O_DSYNC	O_SYNC	/* Synchronize data.  */
+# define O_RSYNC	O_SYNC	/* Synchronize read operations.	 */
+#endif
+
+#ifdef __USE_LARGEFILE64
+# define O_LARGEFILE	0100000
+#endif
+
+/* Values for the second argument to `fcntl'.  */
+#define F_DUPFD		0	/* Duplicate file descriptor.  */
+#define F_GETFD		1	/* Get file descriptor flags.  */
+#define F_SETFD		2	/* Set file descriptor flags.  */
+#define F_GETFL		3	/* Get file status flags.  */
+#define F_SETFL		4	/* Set file status flags.  */
+#ifndef __USE_FILE_OFFSET64
+# define F_GETLK	5	/* Get record locking info.  */
+# define F_SETLK	6	/* Set record locking info (non-blocking).  */
+# define F_SETLKW	7	/* Set record locking info (blocking).	*/
+#else
+# define F_GETLK	F_GETLK64  /* Get record locking info.	*/
+# define F_SETLK	F_SETLK64  /* Set record locking info (non-blocking).*/
+# define F_SETLKW	F_SETLKW64 /* Set record locking info (blocking).  */
+#endif
+#define F_GETLK64	12	/* Get record locking info.  */
+#define F_SETLK64	13	/* Set record locking info (non-blocking).  */
+#define F_SETLKW64	14	/* Set record locking info (blocking).	*/
+
+#if defined __USE_BSD || defined __USE_UNIX98
+# define F_SETOWN	8	/* Get owner of socket (receiver of SIGIO).  */
+# define F_GETOWN	9	/* Set owner of socket (receiver of SIGIO).  */
+#endif
+
+#ifdef __USE_GNU
+# define F_SETSIG	10	/* Set number of signal to be sent.  */
+# define F_GETSIG	11	/* Get number of signal to be sent.  */
+#endif
+
+#ifdef __USE_GNU
+# define F_SETLEASE	1024	/* Set a lease.	 */
+# define F_GETLEASE	1025	/* Enquire what lease is active.  */
+# define F_NOTIFY	1026	/* Request notfications on a directory.	 */
+#endif
+
+/* For F_[GET|SET]FD.  */
+#define FD_CLOEXEC	1	/* actually anything with low bit set goes */
+
+/* For posix fcntl() and `l_type' field of a `struct flock' for lockf().  */
+#define F_RDLCK		0	/* Read lock.  */
+#define F_WRLCK		1	/* Write lock.	*/
+#define F_UNLCK		2	/* Remove lock.	 */
+
+/* For old implementation of bsd flock().  */
+#define F_EXLCK		4	/* or 3 */
+#define F_SHLCK		8	/* or 4 */
+
+#ifdef __USE_BSD
+/* Operations for bsd flock(), also used by the kernel implementation.	*/
+# define LOCK_SH	1	/* shared lock */
+# define LOCK_EX	2	/* exclusive lock */
+# define LOCK_NB	4	/* or'd with one of the above to prevent
+				   blocking */
+# define LOCK_UN	8	/* remove lock */
+#endif
+
+#ifdef __USE_GNU
+# define LOCK_MAND	32	/* This is a mandatory flock:	*/
+# define LOCK_READ	64	/* ... which allows concurrent read operations.	 */
+# define LOCK_WRITE	128	/* ... which allows concurrent write operations.  */
+# define LOCK_RW	192	/* ... Which allows concurrent read & write operations.	 */
+#endif
+
+#ifdef __USE_GNU
+/* Types of directory notifications that may be requested with F_NOTIFY.  */
+# define DN_ACCESS	0x00000001	/* File accessed.  */
+# define DN_MODIFY	0x00000002	/* File modified.  */
+# define DN_CREATE	0x00000004	/* File created.  */
+# define DN_DELETE	0x00000008	/* File removed.  */
+# define DN_RENAME	0x00000010	/* File renamed.  */
+# define DN_ATTRIB	0x00000020	/* File changed attibutes.  */
+# define DN_MULTISHOT	0x80000000	/* Don't remove notifier.  */
+#endif
+
+struct flock
+  {
+    short int l_type;	/* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK.	*/
+    short int l_whence;	/* Where `l_start' is relative to (like `lseek').  */
+#ifndef __USE_FILE_OFFSET64
+    __off_t l_start;	/* Offset where the lock begins.  */
+    __off_t l_len;	/* Size of the locked area; zero means until EOF.  */
+#else
+    __off64_t l_start;	/* Offset where the lock begins.  */
+    __off64_t l_len;	/* Size of the locked area; zero means until EOF.  */
+#endif
+    __pid_t l_pid;	/* Process holding the lock.  */
+  };
+
+#ifdef __USE_LARGEFILE64
+struct flock64
+  {
+    short int l_type;	/* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK.	*/
+    short int l_whence;	/* Where `l_start' is relative to (like `lseek').  */
+    __off64_t l_start;	/* Offset where the lock begins.  */
+    __off64_t l_len;	/* Size of the locked area; zero means until EOF.  */
+    __pid_t l_pid;	/* Process holding the lock.  */
+  };
+#endif
+
+/* Define some more compatibility macros to be backward compatible with
+   BSD systems which did not managed to hide these kernel macros.  */
+#ifdef	__USE_BSD
+# define FAPPEND	O_APPEND
+# define FFSYNC		O_FSYNC
+# define FASYNC		O_ASYNC
+# define FNONBLOCK	O_NONBLOCK
+# define FNDELAY	O_NDELAY
+#endif /* Use BSD.  */
+
+/* Advise to `posix_fadvise'.  */
+#ifdef __USE_XOPEN2K
+# define POSIX_FADV_NORMAL	0 /* No further special treatment.  */
+# define POSIX_FADV_RANDOM	1 /* Expect random page references.  */
+# define POSIX_FADV_SEQUENTIAL	2 /* Expect sequential page references.	 */
+# define POSIX_FADV_WILLNEED	3 /* Will need these pages.  */
+# define POSIX_FADV_DONTNEED	4 /* Don't need these pages.  */
+# define POSIX_FADV_NOREUSE	5 /* Data will be accessed once.  */
+#endif
+
+__BEGIN_DECLS
+
+#ifdef __USE_GNU
+
+/* Provide kernel hint to read ahead.  */
+extern ssize_t readahead (int __fd, __off64_t __offset, size_t __count)
+    __THROW;
+
+#endif
+
+__END_DECLS

+ 54 - 0
libc/sysdeps/linux/xtensa/bits/ipc.h

@@ -0,0 +1,54 @@
+/* Copyright (C) 1995-1999, 2000, 2005, 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_IPC_H
+# error "Never use <bits/ipc.h> directly; include <sys/ipc.h> instead."
+#endif
+
+#include <bits/types.h>
+
+/* Mode bits for `msgget', `semget', and `shmget'.  */
+#define IPC_CREAT	01000		/* Create key if key does not exist. */
+#define IPC_EXCL	02000		/* Fail if key exists.  */
+#define IPC_NOWAIT	04000		/* Return error on wait.  */
+
+/* Control commands for `msgctl', `semctl', and `shmctl'.  */
+#define IPC_RMID	0		/* Remove identifier.  */
+#define IPC_SET		1		/* Set `ipc_perm' options.  */
+#define IPC_STAT	2		/* Get `ipc_perm' options.  */
+#ifdef __USE_GNU
+# define IPC_INFO	3		/* See ipcs.  */
+#endif
+
+/* Special key values.  */
+#define IPC_PRIVATE	((__key_t) 0)	/* Private key.  */
+
+
+/* Data structure used to pass permission information to IPC operations.  */
+struct ipc_perm
+  {
+    __key_t __key;			/* Key.  */
+    __uid_t uid;			/* Owner's user ID.  */
+    __gid_t gid;			/* Owner's group ID.  */
+    __uid_t cuid;			/* Creator's user ID.  */
+    __gid_t cgid;			/* Creator's group ID.  */
+    unsigned int mode;			/* Read/write permission.  */
+    unsigned int __seq;			/* Sequence number.  */
+    unsigned long int __unused1;
+    unsigned long int __unused2;
+  };

+ 57 - 0
libc/sysdeps/linux/xtensa/bits/kernel_stat.h

@@ -0,0 +1,57 @@
+#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;
+	unsigned int	st_mode;
+	unsigned int	st_nlink;
+	unsigned int	st_uid;
+	unsigned int	st_gid;
+	unsigned long	st_rdev;
+	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;
+	unsigned long	__unused4;
+	unsigned long	__unused5;
+};
+
+struct kernel_stat64 {
+	unsigned long long st_dev;	/* Device */
+	unsigned long long st_ino;	/* File serial number */
+	unsigned int  st_mode;		/* File mode. */
+	unsigned int  st_nlink;		/* Link count. */
+	unsigned int  st_uid;		/* User ID of the file's owner. */
+	unsigned int  st_gid;		/* Group ID of the file's group. */
+	unsigned long long st_rdev;	/* Device number, if device. */
+	long long st_size;		/* Size of file, in bytes. */
+	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;
+	unsigned long __unused4;
+	unsigned long __unused5;
+};
+
+#endif	/* _BITS_STAT_STRUCT_H */

+ 48 - 0
libc/sysdeps/linux/xtensa/bits/kernel_types.h

@@ -0,0 +1,48 @@
+/* Note that we use the exact same include guard #define names
+ * as asm/posix_types.h.  This will avoid gratuitous conflicts 
+ * with the posix_types.h kernel header, and will ensure that 
+ * our private content, and not the kernel header, will win.
+ *  -Erik
+ */
+#ifndef _XTENSA_POSIX_TYPES_H
+#define _XTENSA_POSIX_TYPES_H
+
+typedef unsigned long	__kernel_ino_t;
+typedef unsigned int	__kernel_mode_t;
+typedef unsigned long	__kernel_nlink_t;
+typedef long		__kernel_off_t;
+typedef int		__kernel_pid_t;
+typedef unsigned short	__kernel_ipc_pid_t;
+typedef unsigned int	__kernel_uid_t;
+typedef unsigned int	__kernel_gid_t;
+typedef unsigned int	__kernel_size_t;
+typedef int		__kernel_ssize_t;
+typedef long		__kernel_ptrdiff_t;
+typedef long		__kernel_time_t;
+typedef long		__kernel_suseconds_t;
+typedef long		__kernel_clock_t;
+typedef int		__kernel_timer_t;
+typedef int		__kernel_clockid_t;
+typedef int		__kernel_daddr_t;
+typedef char *		__kernel_caddr_t;
+typedef unsigned short	__kernel_uid16_t;
+typedef unsigned short	__kernel_gid16_t;
+typedef unsigned int	__kernel_uid32_t;
+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 long	__kernel_loff_t;
+
+/* Beginning in 2.6 kernels, which is the first version that includes the
+   Xtensa port, __kernel_dev_t is defined in "linux/types.h" and is no longer
+   architecture-specific.  It is defined here in uClibc for consistency with
+   other uClibc ports and for lack of a better place.  */
+typedef unsigned int	__kernel_dev_t;
+
+typedef struct {
+	int	val[2];
+} __kernel_fsid_t;
+
+#endif /* _XTENSA_POSIX_TYPES_H */

+ 43 - 0
libc/sysdeps/linux/xtensa/bits/mathdef.h

@@ -0,0 +1,43 @@
+/* Copyright (C) 2000, 2001, 2004, 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.  */
+
+#if !defined _MATH_H && !defined _COMPLEX_H
+# error "Never use <bits/mathdef.h> directly; include <math.h> instead"
+#endif
+
+#if defined __USE_ISOC99 && defined _MATH_H && !defined _MATH_H_MATHDEF
+# define _MATH_H_MATHDEF	1
+
+/* Xtensa has `float' and `double' operations.  */
+typedef float float_t;		/* `float' expressions are evaluated as
+				   `float'.  */
+typedef double double_t;	/* `double' expressions are evaluated as
+				   `double'.  */
+
+/* The values returned by `ilogb' for 0 and NaN respectively.  */
+# define FP_ILOGB0	(-2147483647)
+# define FP_ILOGBNAN	2147483647
+
+#endif	/* ISO C99 */
+
+#ifndef __NO_LONG_DOUBLE_MATH
+/* Signal that we do not really have a `long double'.  The disables the
+   declaration of all the `long double' function variants.  */
+# define __NO_LONG_DOUBLE_MATH	1
+#endif

+ 104 - 0
libc/sysdeps/linux/xtensa/bits/mman.h

@@ -0,0 +1,104 @@
+/* Definitions for POSIX memory map interface.  Linux/Xtensa version.
+   Copyright (C) 1997, 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_MMAN_H
+# error "Never use <bits/mman.h> directly; include <sys/mman.h> instead."
+#endif
+
+/* The following definitions basically come from the kernel headers.
+   But the kernel header is not namespace clean.  */
+
+
+/* Protections are chosen from these bits, OR'd together.  The
+   implementation does not necessarily support PROT_EXEC or PROT_WRITE
+   without PROT_READ.  The only guarantees are that no writing will be
+   allowed without PROT_WRITE and no access will be allowed for PROT_NONE. */
+
+#define PROT_READ	0x1		/* Page can be read.  */
+#define PROT_WRITE	0x2		/* Page can be written.  */
+#define PROT_EXEC	0x4		/* Page can be executed.  */
+#define PROT_NONE	0x0		/* Page can not be accessed.  */
+#define PROT_GROWSDOWN	0x01000000	/* Extend change to start of
+					   growsdown vma (mprotect only).  */
+#define PROT_GROWSUP	0x02000000	/* Extend change to start of
+					   growsup vma (mprotect only).  */
+
+/* Sharing types (must choose one and only one of these).  */
+#define MAP_SHARED	0x01		/* Share changes.  */
+#define MAP_PRIVATE	0x02		/* Changes are private.  */
+#ifdef __USE_MISC
+# define MAP_TYPE	0x0f		/* Mask for type of mapping.  */
+#endif
+
+/* Other flags.  */
+#define MAP_FIXED	0x10		/* Interpret addr exactly.  */
+#ifdef __USE_MISC
+# define MAP_FILE	0
+# define MAP_ANONYMOUS	0x800		/* Don't use a file.  */
+# define MAP_ANON	MAP_ANONYMOUS
+# define MAP_RENAME	MAP_ANONYMOUS
+#endif
+
+/* These are Linux-specific.  */
+#ifdef __USE_MISC
+# define MAP_GROWSDOWN	0x1000		/* Stack-like segment.  */
+# define MAP_DENYWRITE	0x2000		/* ETXTBSY */
+# define MAP_EXECUTABLE	0x4000		/* Mark it as an executable.  */
+# define MAP_LOCKED	0x8000		/* Lock the mapping.  */
+# 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.  */
+#endif
+
+/* Flags to `msync'.  */
+#define MS_ASYNC	1		/* Sync memory asynchronously.  */
+#define MS_SYNC		4		/* Synchronous memory sync.  */
+#define MS_INVALIDATE	2		/* Invalidate the caches.  */
+
+/* Flags for `mlockall'.  */
+#define MCL_CURRENT	1		/* Lock all currently mapped pages.  */
+#define MCL_FUTURE	2		/* Lock all additions to address
+					   space.  */
+
+/* Flags for `mremap'.  */
+#ifdef __USE_GNU
+# define MREMAP_MAYMOVE	1
+# define MREMAP_FIXED	2
+#endif
+
+/* Advice to `madvise'.  */
+#ifdef __USE_BSD
+# define MADV_NORMAL	 0	/* No further special treatment.  */
+# define MADV_RANDOM	 1	/* Expect random page references.  */
+# define MADV_SEQUENTIAL 2	/* Expect sequential page references.  */
+# define MADV_WILLNEED	 3	/* Will need these pages.  */
+# define MADV_DONTNEED	 4	/* Don't need these pages.  */
+# define MADV_REMOVE	 9	/* Remove these pages and resources.  */
+# define MADV_DONTFORK	 10	/* Do not inherit across fork.  */
+# define MADV_DOFORK	 11	/* Do inherit across fork.  */
+#endif
+
+/* The POSIX people had to invent similar names for the same things.  */
+#ifdef __USE_XOPEN2K
+# define POSIX_MADV_NORMAL	0 /* No further special treatment.  */
+# define POSIX_MADV_RANDOM	1 /* Expect random page references.  */
+# define POSIX_MADV_SEQUENTIAL	2 /* Expect sequential page references.  */
+# define POSIX_MADV_WILLNEED	3 /* Will need these pages.  */
+# define POSIX_MADV_DONTNEED	4 /* Don't need these pages.  */
+#endif

+ 88 - 0
libc/sysdeps/linux/xtensa/bits/msq.h

@@ -0,0 +1,88 @@
+/* Copyright (C) 1995-1997, 2000, 2004, 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_MSG_H
+# error "Never use <bits/msq.h> directly; include <sys/msg.h> instead."
+#endif
+
+#include <bits/types.h>
+
+/* Define options for message queue functions.  */
+#define MSG_NOERROR	010000	/* no error if message is too big */
+#ifdef __USE_GNU
+# define MSG_EXCEPT	020000	/* recv any msg except of specified type */
+#endif
+
+/* Types used in the structure definition.  */
+typedef unsigned long int msgqnum_t;
+typedef unsigned long int msglen_t;
+
+
+/* Structure of record for one message inside the kernel.
+   The type `struct msg' is opaque.  */
+struct msqid_ds
+{
+  struct ipc_perm msg_perm;	/* structure describing operation permission */
+#if defined (__XTENSA_EB__)
+  unsigned long int __unused1;
+  __time_t msg_stime;		/* time of last msgsnd command */
+  unsigned long int __unused2;
+  __time_t msg_rtime;		/* time of last msgrcv command */
+  unsigned long int __unused3;
+  __time_t msg_ctime;		/* time of last change */
+#elif defined (__XTENSA_EL__)
+  __time_t msg_stime;		/* time of last msgsnd command */
+  unsigned long int __unused1;
+  __time_t msg_rtime;		/* time of last msgrcv command */
+  unsigned long int __unused2;
+  __time_t msg_ctime;		/* time of last change */
+  unsigned long int __unused3;
+#else
+# error endian order not defined
+#endif
+  unsigned long int __msg_cbytes; /* current number of bytes on queue */
+  msgqnum_t msg_qnum;		/* number of messages currently on queue */
+  msglen_t msg_qbytes;		/* max number of bytes allowed on queue */
+  __pid_t msg_lspid;		/* pid of last msgsnd() */
+  __pid_t msg_lrpid;		/* pid of last msgrcv() */
+  unsigned long int __unused4;
+  unsigned long int __unused5;
+};
+
+#ifdef __USE_MISC
+
+# define msg_cbytes	__msg_cbytes
+
+/* ipcs ctl commands */
+# define MSG_STAT 11
+# define MSG_INFO 12
+
+/* buffer for msgctl calls IPC_INFO, MSG_INFO */
+struct msginfo
+  {
+    int msgpool;
+    int msgmap;
+    int msgmax;
+    int msgmnb;
+    int msgmni;
+    int msgssz;
+    int msgtql;
+    unsigned short int msgseg;
+  };
+
+#endif /* __USE_MISC */

+ 46 - 0
libc/sysdeps/linux/xtensa/bits/setjmp.h

@@ -0,0 +1,46 @@
+/* Copyright (C) 1997, 1998, 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.  */
+
+/* Define the machine-dependent type `jmp_buf'.  Xtensa version.  */
+#ifndef _BITS_SETJMP_H
+#define _BITS_SETJMP_H	1
+
+#if !defined _SETJMP_H && !defined _PTHREAD_H
+# error "Never include <bits/setjmp.h> directly; use <setjmp.h> instead."
+#endif
+
+/* 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
+
+/* 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])
+
+#endif	/* bits/setjmp.h */

+ 115 - 0
libc/sysdeps/linux/xtensa/bits/shm.h

@@ -0,0 +1,115 @@
+/* Copyright (C) 1995, 1996, 1997, 2000, 2002, 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_SHM_H
+# error "Never include <bits/shm.h> directly; use <sys/shm.h> instead."
+#endif
+
+#include <bits/types.h>
+
+/* Permission flag for shmget.  */
+#define SHM_R		0400		/* or S_IRUGO from <linux/stat.h> */
+#define SHM_W		0200		/* or S_IWUGO from <linux/stat.h> */
+
+/* Flags for `shmat'.  */
+#define SHM_RDONLY	010000		/* attach read-only else read-write */
+#define SHM_RND		020000		/* round attach address to SHMLBA */
+#define SHM_REMAP	040000		/* take-over region on attach */
+
+/* Commands for `shmctl'.  */
+#define SHM_LOCK	11		/* lock segment (root only) */
+#define SHM_UNLOCK	12		/* unlock segment (root only) */
+
+__BEGIN_DECLS
+
+/* Segment low boundary address multiple.  */
+#define SHMLBA		(__getpagesize ())
+extern int __getpagesize (void) __THROW __attribute__ ((__const__));
+
+
+/* Type to count number of attaches.  */
+typedef unsigned long int shmatt_t;
+
+/* Data structure describing a set of semaphores.  */
+struct shmid_ds
+  {
+    struct ipc_perm shm_perm;		/* operation permission struct */
+    size_t shm_segsz;			/* size of segment in bytes */
+#if defined (__XTENSA_EL__)
+    __time_t shm_atime;			/* time of last shmat() */
+    unsigned long int __unused1;
+    __time_t shm_dtime;			/* time of last shmdt() */
+    unsigned long int __unused2;
+    __time_t shm_ctime;			/* time of last change by shmctl() */
+    unsigned long int __unused3;
+#elif defined (__XTENSA_EB__)
+    unsigned long int __unused1;
+    __time_t shm_atime;			/* time of last shmat() */
+    unsigned long int __unused2;
+    __time_t shm_dtime;			/* time of last shmdt() */
+    unsigned long int __unused3;
+    __time_t shm_ctime;			/* time of last change by shmctl() */
+#else
+# error endian order not defined
+#endif
+    __pid_t shm_cpid;			/* pid of creator */
+    __pid_t shm_lpid;			/* pid of last shmop */
+    shmatt_t shm_nattch;		/* number of current attaches */
+    unsigned long int __unused4;
+    unsigned long int __unused5;
+  };
+
+#ifdef __USE_MISC
+
+/* ipcs ctl commands */
+# define SHM_STAT 	13
+# define SHM_INFO 	14
+
+/* shm_mode upper byte flags */
+# define SHM_DEST	01000	/* segment will be destroyed on last detach */
+# define SHM_LOCKED	02000   /* segment will not be swapped */
+# define SHM_HUGETLB	04000	/* segment is mapped via hugetlb */
+# define SHM_NORESERVE	010000	/* don't check for reservations */
+
+struct	shminfo
+  {
+    unsigned long int shmmax;
+    unsigned long int shmmin;
+    unsigned long int shmmni;
+    unsigned long int shmseg;
+    unsigned long int shmall;
+    unsigned long int __unused1;
+    unsigned long int __unused2;
+    unsigned long int __unused3;
+    unsigned long int __unused4;
+  };
+
+struct shm_info
+  {
+    int used_ids;
+    unsigned long int shm_tot;	/* total allocated shm */
+    unsigned long int shm_rss;	/* total resident shm */
+    unsigned long int shm_swp;	/* total swapped shm */
+    unsigned long int swap_attempts;
+    unsigned long int swap_successes;
+  };
+
+#endif /* __USE_MISC */
+
+__END_DECLS

+ 33 - 0
libc/sysdeps/linux/xtensa/bits/sigcontextinfo.h

@@ -0,0 +1,33 @@
+/* Copyright (C) 2003, 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.  */
+
+/* Also see register-dump.h, where we spill live registers to the
+   stack so that we can trace the stack backward.  */
+
+#define SIGCONTEXT unsigned long _info, ucontext_t *
+#define SIGCONTEXT_EXTRA_ARGS _info,
+
+/* ANDing with 0x3fffffff clears the window-size bits.
+   Assumes TASK_SIZE = 0x40000000.  */
+
+#define GET_PC(ctx)	((void *) (ctx->uc_mcontext.sc_pc & 0x3fffffff))
+#define GET_FRAME(ctx)	((void *) ctx->uc_mcontext.sc_a[1])
+#define GET_STACK(ctx)	((void *) ctx->uc_mcontext.sc_a[1])
+#define CALL_SIGHANDLER(handler, signo, ctx) \
+  (handler)((signo), SIGCONTEXT_EXTRA_ARGS (ctx))
+

+ 28 - 0
libc/sysdeps/linux/xtensa/bits/stackinfo.h

@@ -0,0 +1,28 @@
+/* Copyright (C) 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.  */
+
+/* This file contains a bit of information about the stack allocation
+   of the processor.  */
+
+#ifndef _STACKINFO_H
+#define _STACKINFO_H	1
+
+/* On Xtensa the stack grows down.  */
+#define _STACK_GROWS_DOWN	1
+
+#endif	/* stackinfo.h */

+ 153 - 0
libc/sysdeps/linux/xtensa/bits/stat.h

@@ -0,0 +1,153 @@
+/* Copyright (C) 1992, 1995-2005, 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_STAT_H
+# error "Never include <bits/stat.h> directly; use <sys/stat.h> instead."
+#endif
+
+/* Versions of the `struct stat' data structure.  */
+#define _STAT_VER_KERNEL	0
+#define _STAT_VER_LINUX		1
+#define _STAT_VER		_STAT_VER_LINUX
+
+/* Versions of the `xmknod' interface.  */
+#define _MKNOD_VER_LINUX	0
+
+
+struct stat
+  {
+    __dev_t st_dev;			/* Device.  */
+#ifndef __USE_FILE_OFFSET64
+    __ino_t st_ino;			/* File serial number.	*/
+#else
+    __ino64_t st_ino;			/* File serial number.	*/
+#endif
+    __mode_t st_mode;			/* File mode.  */
+    __nlink_t st_nlink;			/* Link count.  */
+    __uid_t st_uid;			/* User ID of the file's owner.	*/
+    __gid_t st_gid;			/* Group ID of the file's group.*/
+    __dev_t st_rdev;			/* Device number, if device.  */
+#ifndef __USE_FILE_OFFSET64
+    __off_t st_size;			/* Size of file, in bytes.  */
+#else
+    __off64_t st_size;			/* Size of file, in bytes.  */
+#endif
+    __blksize_t st_blksize;		/* Optimal block size for I/O.  */
+
+#ifndef __USE_FILE_OFFSET64
+    __blkcnt_t st_blocks;		/* Number 512-byte blocks allocated. */
+#else
+    unsigned long __pad2;
+    __blkcnt64_t st_blocks;		/* Number 512-byte blocks allocated. */
+#endif
+#if 0 /*def __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
+       identifier 'timespec' to appear in the <sys/stat.h> header.
+       Therefore we have to handle the use of this header in strictly
+       standard-compliant sources special.  */
+    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.  */
+# define st_atime st_atim.tv_sec	/* Backward compatibility.  */
+# define st_mtime st_mtim.tv_sec
+# define st_ctime st_ctim.tv_sec
+#else
+    __time_t st_atime;			/* Time of last access.  */
+    unsigned long int st_atimensec;	/* Nscecs of last access.  */
+    __time_t st_mtime;			/* Time of last modification.  */
+    unsigned long int st_mtimensec;	/* Nsecs of last modification.  */
+    __time_t st_ctime;			/* Time of last status change.  */
+    unsigned long int st_ctimensec;	/* Nsecs of last status change.  */
+#endif
+    unsigned long int __unused4;
+    unsigned long int __unused5;
+  };
+
+#ifdef __USE_LARGEFILE64
+struct stat64
+  {
+    __dev_t st_dev;			/* Device.  */
+    __ino64_t st_ino;			/* File serial number.  */
+    __mode_t st_mode;			/* File mode.  */
+    __nlink_t st_nlink;			/* Link count.  */
+    __uid_t st_uid;			/* User ID of the file's owner.	*/
+    __gid_t st_gid;			/* Group ID of the file's group.*/
+    __dev_t st_rdev;			/* Device number, if device.  */
+    __off64_t st_size;			/* Size of file, in bytes.  */
+    __blksize_t st_blksize;		/* Optimal block size for I/O.  */
+
+    unsigned long __pad2;
+    __blkcnt64_t st_blocks;		/* Number 512-byte blocks allocated. */
+#if 0 /*def __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
+       identifier 'timespec' to appear in the <sys/stat.h> header.
+       Therefore we have to handle the use of this header in strictly
+       standard-compliant sources special.  */
+    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.  */
+#else
+    __time_t st_atime;			/* Time of last access.  */
+    unsigned long int st_atimensec;	/* Nscecs of last access.  */
+    __time_t st_mtime;			/* Time of last modification.  */
+    unsigned long int st_mtimensec;	/* Nsecs of last modification.  */
+    __time_t st_ctime;			/* Time of last status change.  */
+    unsigned long int st_ctimensec;	/* Nsecs of last status change.  */
+#endif
+    unsigned long __unused4;
+    unsigned long __unused5;
+  };
+#endif
+
+/* Tell code we have these members.  */
+#define	_STATBUF_ST_BLKSIZE
+#define _STATBUF_ST_RDEV
+/* Nanosecond resolution time values are supported.  */
+#define _STATBUF_ST_NSEC
+
+/* Encoding of the file mode.  */
+
+#define	__S_IFMT	0170000	/* These bits determine file type.  */
+
+/* File types.  */
+#define	__S_IFDIR	0040000	/* Directory.  */
+#define	__S_IFCHR	0020000	/* Character device.  */
+#define	__S_IFBLK	0060000	/* Block device.  */
+#define	__S_IFREG	0100000	/* Regular file.  */
+#define	__S_IFIFO	0010000	/* FIFO.  */
+#define	__S_IFLNK	0120000	/* Symbolic link.  */
+#define	__S_IFSOCK	0140000	/* Socket.  */
+
+/* POSIX.1b objects.  Note that these macros always evaluate to zero.  But
+   they do it by enforcing the correct use of the macros.  */
+#define __S_TYPEISMQ(buf)  ((buf)->st_mode - (buf)->st_mode)
+#define __S_TYPEISSEM(buf) ((buf)->st_mode - (buf)->st_mode)
+#define __S_TYPEISSHM(buf) ((buf)->st_mode - (buf)->st_mode)
+
+/* Protection bits.  */
+
+#define	__S_ISUID	04000	/* Set user ID on execution.  */
+#define	__S_ISGID	02000	/* Set group ID on execution.  */
+#define	__S_ISVTX	01000	/* Save swapped text after use (sticky).  */
+#define	__S_IREAD	0400	/* Read by owner.  */
+#define	__S_IWRITE	0200	/* Write by owner.  */
+#define	__S_IEXEC	0100	/* Execute by owner.  */

+ 140 - 0
libc/sysdeps/linux/xtensa/bits/syscalls.h

@@ -0,0 +1,140 @@
+#ifndef _BITS_SYSCALLS_H
+#define _BITS_SYSCALLS_H
+#ifndef _SYSCALL_H
+# error "Never use <bits/syscalls.h> directly; include <sys/syscall.h> instead."
+#endif
+
+/*
+   Some of the sneaky macros in the code were taken from 
+   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:
+
+   return addr	stack ptr	arg0, arg1, arg2, arg3, arg4, arg5
+   -----------	---------	----------------------------------
+   a0		a1		a2,   a3,   a4,   a5,   a6,   a7
+
+   (Of course a function with say 3 arguments does not have entries for
+   arguments 4, 5, and 6.)
+
+   Linux takes system-call arguments in registers.  The ABI and Xtensa
+   software conventions require the system-call number in a2.  We move any
+   argument that was in a2 to a7, and a7 to a8 if we have all 6 arguments.
+   Note that for improved efficiency, we do NOT shift all parameters down
+   one register to maintain the original order.
+
+   syscall number		arg0, arg1, arg2, arg3, arg4, arg5
+   --------------		----------------------------------
+   a2				a6,   a3,   a4,   a5,   a8,   a9
+
+   Upon return, a2 and a3 are clobbered; all other registers are preserved.  */
+
+#undef  DO_CALL
+#define DO_CALL(syscall_name, nargs)					      \
+	DO_ARGS_##nargs							      \
+	movi	a2, SYS_ify (syscall_name);				      \
+	syscall
+
+#define DO_ARGS_0
+#define DO_ARGS_1	mov a6, a2;
+#define DO_ARGS_2	mov a6, a2;
+#define DO_ARGS_3	mov a6, a2;
+#define DO_ARGS_4	mov a6, a2;
+#define DO_ARGS_5	mov a8, a6; mov a6, a2;
+#define DO_ARGS_6	mov a9, a7; mov a8, a6; mov a6, a2;
+
+#else /* not __ASSEMBLER__ */
+
+#include <errno.h>
+
+#define STR(s) #s
+#define LD_ARG(n,ar)	register int _a##n asm (STR(a##n)) = (int) (ar)
+
+#define LD_ARGS_0()
+#define LD_ARGS_1(a0)			LD_ARG(6,a0)
+#define LD_ARGS_2(a0,a1)		LD_ARGS_1(a0); LD_ARG(3,a1)
+#define LD_ARGS_3(a0,a1,a2)		LD_ARGS_2(a0,a1); LD_ARG(4,a2)
+#define LD_ARGS_4(a0,a1,a2,a3)		LD_ARGS_3(a0,a1,a2); LD_ARG(5,a3)
+#define LD_ARGS_5(a0,a1,a2,a3,a4)	LD_ARGS_4(a0,a1,a2,a3); LD_ARG(8,a4)
+#define LD_ARGS_6(a0,a1,a2,a3,a4,a5)	LD_ARGS_5(a0,a1,a2,a3,a4); LD_ARG(9,a5)
+
+#define ASM_ARGS_0			"r"(_a2)
+#define ASM_ARGS_1			ASM_ARGS_0, "r"(_a6)
+#define ASM_ARGS_2			ASM_ARGS_1, "r"(_a3)
+#define ASM_ARGS_3			ASM_ARGS_2, "r"(_a4)
+#define ASM_ARGS_4			ASM_ARGS_3, "r"(_a5)
+#define ASM_ARGS_5			ASM_ARGS_4, "r"(_a8)
+#define ASM_ARGS_6			ASM_ARGS_5, "r"(_a9)
+
+/* 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...)			      \
+  ({ 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));    \
+}
+
+#endif /* not __ASSEMBLER__ */
+#endif /* _BITS_SYSCALLS_H */

+ 44 - 0
libc/sysdeps/linux/xtensa/bits/uClibc_arch_features.h

@@ -0,0 +1,44 @@
+/*
+ * Track misc arch-specific features that aren't config options
+ */
+
+#ifndef _BITS_UCLIBC_ARCH_FEATURES_H
+#define _BITS_UCLIBC_ARCH_FEATURES_H
+
+/* instruction used when calling abort() to kill yourself */
+#define __UCLIBC_ABORT_INSTRUCTION__ "ill"
+
+/* can your target use syscall6() for mmap ? */
+#define __UCLIBC_MMAP_HAS_6_ARGS__
+
+/* does your target use syscall4() for truncate64 ? (32bit arches only) */
+#undef __UCLIBC_TRUNCATE64_HAS_4_ARGS__
+
+/* does your target have a broken create_module() ? */
+#undef __UCLIBC_BROKEN_CREATE_MODULE__
+
+/* does your target have to worry about older [gs]etrlimit() ? */
+#undef __UCLIBC_HANDLE_OLDER_RLIMIT__
+
+/* does your target prefix all symbols with an _ ? */
+#define __UCLIBC_NO_UNDERSCORES__
+
+/* 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 IEEE signed zero floats */
+#define __UCLIBC_HAVE_SIGNED_ZERO__
+
+#endif /* _BITS_UCLIBC_ARCH_FEATURES_H */

+ 31 - 0
libc/sysdeps/linux/xtensa/bits/uClibc_page.h

@@ -0,0 +1,31 @@
+/*  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 */

+ 19 - 0
libc/sysdeps/linux/xtensa/bits/wordsize.h

@@ -0,0 +1,19 @@
+/* Copyright (C) 1999 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., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#define __WORDSIZE	32

+ 53 - 0
libc/sysdeps/linux/xtensa/bits/xtensa-config.h

@@ -0,0 +1,53 @@
+/* Xtensa configuration settings.
+   Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007
+   Free Software Foundation, Inc.
+   Contributed by Bob Wilson (bwilson@tensilica.com) at Tensilica.
+
+   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 XTENSA_CONFIG_H
+#define XTENSA_CONFIG_H
+
+/* The macros defined here match those with the same names in the Xtensa
+   compile-time HAL (Hardware Abstraction Layer).  Please refer to the
+   Xtensa System Software Reference Manual for documentation of these
+   macros.  */
+
+/* The following macros reflect the default expectations for Xtensa
+   processor configurations that can run glibc.  If you want to try
+   building glibc for an Xtensa configuration that is missing these
+   options, you will at least need to change the values of these
+   macros.  */
+
+#undef XCHAL_HAVE_NSA
+#define XCHAL_HAVE_NSA			1
+
+#undef XCHAL_HAVE_LOOPS
+#define XCHAL_HAVE_LOOPS		1
+
+/* Assume the maximum number of AR registers.  This currently only affects
+   the __window_spill function, and it is always safe to flush extra.  */
+
+#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 */

+ 43 - 0
libc/sysdeps/linux/xtensa/brk.c

@@ -0,0 +1,43 @@
+/* brk system call for Linux/Xtensa.
+   Copyright (C) 1996, 1997, 2005, 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.  */
+
+#include <errno.h>
+#include <unistd.h>
+#include <sys/syscall.h>
+
+/* This must be initialized data because commons can't have aliases.  */
+void *__curbrk attribute_hidden = 0;
+
+libc_hidden_proto(brk)
+int
+brk (void *addr)
+{
+  void *newbrk;
+
+  __curbrk = newbrk = (void *) INLINE_SYSCALL (brk, 1, addr);
+
+  if (newbrk < addr)
+    {
+      __set_errno (ENOMEM);
+      return -1;
+    }
+
+  return 0;
+}
+libc_hidden_def(brk)

+ 1 - 0
libc/sysdeps/linux/xtensa/bsd-_setjmp.S

@@ -0,0 +1 @@
+/* _setjmp is in setjmp.S  */

+ 1 - 0
libc/sysdeps/linux/xtensa/bsd-setjmp.S

@@ -0,0 +1 @@
+/* setjmp is in setjmp.S  */

+ 103 - 0
libc/sysdeps/linux/xtensa/clone.S

@@ -0,0 +1,103 @@
+/* Copyright (C) 2001, 2005, 2007 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.
+
+   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.  */
+
+/* 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.  */
+
+#include "sysdep.h"
+#include <sys/syscall.h>
+#define _ERRNO_H	1
+#include <bits/errno.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) */
+
+        .text
+ENTRY (__clone)
+
+	/* Sanity check arguments.  */
+	beqz	a2, .Leinval	/* no NULL function pointers */
+	beqz	a3, .Leinval	/* no NULL stack pointers */
+
+	/* 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.  */
+
+	mov	a9, a5			/* save function argument */
+	mov	a5, a7
+	mov	a7, a2			/* save function pointer */
+	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) */
+	syscall
+	bltz	a2, SYSCALL_ERROR_LABEL
+	beqz	a2, .Lthread_start
+
+	/* Fall through for parent.  */
+.Lpseudo_end:
+	retw
+
+.Leinval:
+	movi	a2, -EINVAL
+	j	SYSCALL_ERROR_LABEL
+
+.Lthread_start:
+	/* Start child thread.  */
+	movi	a0, 0			/* terminate the stack frame */
+
+#ifdef RESET_PID
+	/* Check and see if we need to reset the PID.  */
+	bbsi.l	a6, 16, 1f		/* CLONE_THREAD = 0x00010000 */
+	movi	a2, -1
+	bbsi.l	a6, 8, 2f		/* 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 */
+
+	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.  */
+	movi	a2, JUMPTARGET(_exit)
+	callx4	a2
+
+PSEUDO_END (__clone)
+
+weak_alias (__clone, clone)

+ 119 - 0
libc/sysdeps/linux/xtensa/crt1.S

@@ -0,0 +1,119 @@
+/* Startup code compliant to the ELF Xtensa ABI.
+   Copyright (C) 2001, 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.
+
+   In addition to the permissions in the GNU Lesser General Public
+   License, the Free Software Foundation gives you unlimited
+   permission to link the compiled version of this file with other
+   programs, and to distribute those programs without any restriction
+   coming from the use of this file. (The GNU Lesser General Public
+   License restrictions do apply in other respects; for example, they
+   cover modification of the file, and distribution when not linked
+   into another program.)
+
+   Note that people who make modified versions of this file are not
+   obligated to grant this special exception for their modified
+   versions; it is their choice whether to do so. The GNU Lesser
+   General Public License gives permission to release a modified
+   version without this exception; this exception also makes it
+   possible to release a modified version which carries forward this
+   exception.
+
+   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.  */
+
+#include <features.h>
+
+#ifndef __UCLIBC_CTOR_DTOR__
+        .weak _init
+        .weak _fini
+#endif
+
+/* This is the canonical entry point, usually the first thing in the text
+   segment.  When the entry point runs, most register values are unspecified,
+   except for:
+
+	a2	Contains a function pointer to be registered with `atexit'.
+		This is how the dynamic linker arranges to have DT_FINI
+		functions called for shared libraries that have been loaded
+		before this code runs.
+
+	a1	The stack (i.e., a1+16) contains the arguments and environment:
+		a1+0			argc
+		a1+4			argv[0]
+		...
+		a1+(4*argc)		NULL
+		a1+(4*(argc+1))		envp[0]
+		...
+					NULL
+
+  Setup parameters accordingly (for a call4).  See function prototype
+  from sysdeps/generic/libc-start.c
+
+	a6 = *main
+	a7 = argc
+	a8 = ubp_av
+	a9 = *init
+	a10 = *fini
+	a11 = *rtld_fini
+	[sp+0] = stack_end
+ */
+
+	.text
+	.align	4
+	.literal_position
+	.global	_start
+	.type	_start, @function
+_start:
+	/* Clear a0 to obviously mark the outermost frame.  */
+	movi	a0, 0
+
+	/* Load up the user's main function.  */
+	movi	a6, 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	a7, a1, 0	/* Load the argument count.  */
+	addi	a8, a1, 4	/* Compute the argv pointer.  */
+
+	/* Push address of our own entry points to .fini and .init.  */
+	movi	a9, _init
+	movi	a10, _fini
+
+	/* Setup the shared library termination function.  */
+	mov	a11, a2
+
+	/* 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	a4, __uClibc_main
+	callx4	a4
+
+	/* Crash if somehow `exit' does return.  */
+	ill
+
+	/* Define a symbol for the first piece of initialized data.  */
+	.data
+	.align	4
+	.global	__data_start
+__data_start:
+	.long	0
+	.weak	data_start
+	data_start = __data_start

+ 16 - 0
libc/sysdeps/linux/xtensa/crti.S

@@ -0,0 +1,16 @@
+/* glibc's sysdeps/xtensa/elf/initfini.c used for reference [PROLOG] */
+
+	.section .init
+	.align	4
+	.global	_init
+	.type	_init, @function
+_init:
+	entry	sp, 48
+
+
+	.section .fini
+	.align	4
+	.global	_fini
+	.type	_fini, @function
+_fini:
+	entry	sp, 48

+ 8 - 0
libc/sysdeps/linux/xtensa/crtn.S

@@ -0,0 +1,8 @@
+/* glibc's sysdeps/xtensa/elf/initfini.c used for reference [EPILOG] */
+
+	.section .init
+	retw
+
+
+	.section .fini
+	retw

+ 25 - 0
libc/sysdeps/linux/xtensa/fork.c

@@ -0,0 +1,25 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * fork() for Xtensa uClibc
+ *
+ * Copyright (C) 2007 Tensilica Inc.
+ *
+ * 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'.  */
+
+extern __typeof(fork) __libc_fork;
+
+libc_hidden_proto (fork)
+pid_t __libc_fork (void)
+{
+  return (pid_t) INLINE_SYSCALL (clone, 2, SIGCHLD, 0);
+}
+weak_alias (__libc_fork, fork)
+libc_hidden_weak (fork)

+ 57 - 0
libc/sysdeps/linux/xtensa/mmap.S

@@ -0,0 +1,57 @@
+/* Copyright (C) 2005, 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.  */
+
+#include "sysdep.h"
+#include <sys/syscall.h>
+
+#define PAGE_SHIFT 12
+
+/* __ptr_t __mmap (a2 = __ptr_t addr,
+		   a3 = size_t len,
+		   a4 = int prot,
+		   a5 = int flags,
+		   a6 = int fd,
+		   a7 = off_t offset) */
+
+ENTRY (__mmap)
+
+	/* We only support mmap2 in the kernel, so shift offset by
+	   page - size.  */
+	mov	a8, a6
+	mov	a6, a2
+	movi	a2, SYS_ify (mmap2)
+	srli	a9, a7, PAGE_SHIFT
+
+	/* syscall (a2 = NR_mmap2,
+		    a6 = arg0,
+		    a3 = arg1,
+		    a4 = arg2,
+		    a5 = arg3,
+		    a8 = arg4,
+		    a9 = arg5) */
+
+	syscall
+	bltz	a2, SYSCALL_ERROR_LABEL
+
+.Lpseudo_end:
+	retw
+
+PSEUDO_END (__mmap)
+
+weak_alias (__mmap, mmap)
+libc_hidden_weak (mmap)

+ 29 - 0
libc/sysdeps/linux/xtensa/posix_fadvise.c

@@ -0,0 +1,29 @@
+/* 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
+}

+ 39 - 0
libc/sysdeps/linux/xtensa/posix_fadvise64.c

@@ -0,0 +1,39 @@
+/* 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__ */

+ 193 - 0
libc/sysdeps/linux/xtensa/pread_write.c

@@ -0,0 +1,193 @@
+/* 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 */

+ 131 - 0
libc/sysdeps/linux/xtensa/setjmp.S

@@ -0,0 +1,131 @@
+/* setjmp for Xtensa Processors.
+   Copyright (C) 2001, 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.  */
+
+/* This implementation relies heavily on the Xtensa register window
+   mechanism.  Setjmp flushes all the windows except its own to the
+   stack and then copies registers from the save areas on the stack
+   into the jmp_buf structure, along with the return address of the call
+   to setjmp.  Longjmp invalidates all the windows except its own, and
+   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.  */
+
+#include "sysdep.h"
+
+/* int setjmp (a2 = jmp_buf env) */
+
+ENTRY (_setjmp)
+	movi	a3, 0
+	j	1f
+END (_setjmp)
+libc_hidden_def (_setjmp)
+
+ENTRY (setjmp)
+	movi	a3, 1
+	j	1f
+END (setjmp)
+
+/* int __sigsetjmp (a2 = jmp_buf env,
+		    a3 = int savemask)  */
+
+ENTRY (__sigsetjmp)
+1:	
+	/* 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
+.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
+	addi	a6, a6, 16
+	blt	a5, a7, .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
+
+	/* Save the return address, including the window size bits.  */
+	s32i	a0, a2, 64
+
+	/* a2 still addresses jmp_buf.  a15 contains savemask.  */
+	mov	a6, a2
+	mov	a7, a15
+	movi	a3, __sigjmp_save
+	callx4	a3
+	mov	a2, a6
+	retw
+END(__sigsetjmp)
+
+weak_extern(_setjmp)
+weak_extern(setjmp)

+ 121 - 0
libc/sysdeps/linux/xtensa/sys/procfs.h

@@ -0,0 +1,121 @@
+/* Copyright (C) 1996, 1997, 1999, 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_PROCFS_H
+#define _SYS_PROCFS_H	1
+
+/* This is somewhat modelled after the file of the same name on SVR4
+   systems.  It provides a definition of the core file format for ELF
+   used on Linux.  It doesn't have anything to do with the /proc file
+   system, even though Linux has one.
+
+   Anyway, the whole purpose of this file is for GDB and GDB only.
+   Don't read too much into it.  Don't use it for anything other than
+   GDB unless you know what you are doing.  */
+
+#include <features.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/user.h>
+
+__BEGIN_DECLS
+
+/* Type for a general-purpose register.  */
+typedef unsigned long elf_greg_t;
+
+#define ELF_NGREG 32
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+
+/* Register set for the floating-point registers.  */
+#define ELF_NFPREG 18
+typedef unsigned long elf_fpreg_t;
+typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
+
+/* Signal info.  */
+struct elf_siginfo
+  {
+    int si_signo;			/* Signal number.  */
+    int si_code;			/* Extra code.  */
+    int si_errno;			/* Errno.  */
+  };
+
+/* Definitions to generate Intel SVR4-like core files.  These mostly
+   have the same names as the SVR4 types with "elf_" tacked on the
+   front to prevent clashes with Linux definitions, and the typedef
+   forms have been avoided.  This is mostly like the SVR4 structure,
+   but more Linuxy, with things that Linux does not support and which
+   GDB doesn't really use excluded.  */
+
+struct elf_prstatus
+  {
+    struct elf_siginfo pr_info;		/* Info associated with signal.  */
+    short int pr_cursig;		/* Current signal.  */
+    unsigned long int pr_sigpend;	/* Set of pending signals.  */
+    unsigned long int pr_sighold;	/* Set of held signals.  */
+    __pid_t pr_pid;
+    __pid_t pr_ppid;
+    __pid_t pr_pgrp;
+    __pid_t pr_sid;
+    struct timeval pr_utime;		/* User time.  */
+    struct timeval pr_stime;		/* System time.  */
+    struct timeval pr_cutime;		/* Cumulative user time.  */
+    struct timeval pr_cstime;		/* Cumulative system time.  */
+    elf_gregset_t pr_reg;		/* GP registers.  */
+    int pr_fpvalid;			/* True if math copro being used.  */
+  };
+
+
+#define ELF_PRARGSZ     (80)    /* Number of chars for args.  */
+
+struct elf_prpsinfo
+  {
+    char pr_state;			/* Numeric process state.  */
+    char pr_sname;			/* Char for pr_state.  */
+    char pr_zomb;			/* Zombie.  */
+    char pr_nice;			/* Nice val.  */
+    unsigned long int pr_flag;		/* Flags.  */
+    unsigned short int pr_uid;
+    unsigned short int pr_gid;
+    int pr_pid, pr_ppid, pr_pgrp, pr_sid;
+    /* Lots missing */
+    char pr_fname[16];			/* Filename of executable.  */
+    char pr_psargs[ELF_PRARGSZ];	/* Initial part of arg list.  */
+  };
+
+/* The rest of this file provides the types for emulation of the
+   Solaris <proc_service.h> interfaces that should be implemented by
+   users of libthread_db.  */
+
+/* Addresses.  */
+typedef void *psaddr_t;
+
+/* Register sets.  Linux has different names.  */
+typedef elf_gregset_t prgregset_t;
+typedef elf_fpregset_t prfpregset_t;
+
+/* We don't have any differences between processes and threads,
+   therefore have only one PID type.  */
+typedef __pid_t lwpid_t;
+
+/* Process status and info.  In the end we do provide typedefs for them.  */
+typedef struct elf_prstatus prstatus_t;
+typedef struct elf_prpsinfo prpsinfo_t;
+
+__END_DECLS
+
+#endif	/* sys/procfs.h */

+ 156 - 0
libc/sysdeps/linux/xtensa/sys/ptrace.h

@@ -0,0 +1,156 @@
+/* `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 */

+ 49 - 0
libc/sysdeps/linux/xtensa/sys/ucontext.h

@@ -0,0 +1,49 @@
+/* Copyright (C) 2001, 2006, 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_UCONTEXT_H
+#define _SYS_UCONTEXT_H	1
+
+#include <features.h>
+#include <signal.h>
+
+/* We need the signal context definitions even if they are not used
+   included in <signal.h>.  */
+#include <bits/sigcontext.h>
+
+/* Revise this structure when we add support for coprocessors.  */
+
+/* Structure to describe FPU registers.  */
+typedef struct fpregset
+{
+  int dummy;
+} fpregset_t;
+
+typedef struct sigcontext mcontext_t;
+
+/* Userlevel context.  */
+typedef struct ucontext
+  {
+    unsigned long int uc_flags;
+    struct ucontext *uc_link;
+    stack_t uc_stack;
+    mcontext_t uc_mcontext;
+    __sigset_t uc_sigmask;
+  } ucontext_t;
+
+#endif /* sys/ucontext.h */

+ 42 - 0
libc/sysdeps/linux/xtensa/syscall.S

@@ -0,0 +1,42 @@
+/* Copyright (C) 2005, 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.  */
+
+#include "sysdep.h"
+
+/* The register layout upon entering the function is:
+
+   arguments	syscall number	arg0, arg1, arg2, arg3, arg4, arg5
+   ---------	--------------	----------------------------------
+   function	a2		a3,   a4,   a5,   a6,   a7,   (sp)
+   syscall	a2		a6,   a3,   a4,   a5,   a8,   a9
+ */
+
+ENTRY (syscall)
+	l32i	a9, a1, 16	/* load extra argument from stack */
+	mov	a8, a7
+	mov	a7, a3		/* preserve a3 in a7 */
+	mov	a3, a4
+	mov	a4, a5
+	mov	a5, a6
+	mov	a6, a7
+	syscall
+	movi    a4, -4095
+	bgeu    a2, a4, SYSCALL_ERROR_LABEL
+.Lpseudo_end:
+	retw
+PSEUDO_END (syscall)

+ 160 - 0
libc/sysdeps/linux/xtensa/sysdep.h

@@ -0,0 +1,160 @@
+/* Assembler macros for Xtensa processors.
+   Copyright (C) 2001, 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.  */
+
+#ifdef __ASSEMBLER__
+
+#define ALIGNARG(log2) 1 << log2
+#define ASM_TYPE_DIRECTIVE(name, typearg) .type name, typearg
+#define ASM_SIZE_DIRECTIVE(name) .size name, . - name
+
+#ifdef __STDC__
+#define C_LABEL(name)	name :
+#else
+#define C_LABEL(name)	name/**/:
+#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;							\
+  CALL_MCOUNT
+
+#undef END
+#define END(name) ASM_SIZE_DIRECTIVE(name)
+
+/* Define a macro for this directive so it can be removed in a few places.  */
+#define LITERAL_POSITION .literal_position
+
+#undef JUMPTARGET
+#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.  */
+#define JUMPTARGET(name) name##@PLT
+#else
+#define JUMPTARGET(name) name
+#endif
+
+#define FRAMESIZE 16
+#define CALL_MCOUNT		/* Do nothing.  */
+
+
+/* Linux uses a negative return value to indicate syscall errors,
+   unlike most Unices, which use the condition codes' carry flag.
+
+   Since version 2.1 the return value of a system call might be
+   negative even if the call succeeded.  E.g., the `lseek' system call
+   might return a large offset.  Therefore we must not anymore test
+   for < 0, but test for a real error by making sure the value in a2
+   is a real error number.  Linus said he will make sure the no syscall
+   returns a value in -1 .. -4095 as a valid result so we can safely
+   test with -4095.  */
+
+/* We don't want the label for the error handler to be global when we define
+   it here.  */
+#define SYSCALL_ERROR_LABEL 0f
+
+#undef  PSEUDO
+#define	PSEUDO(name, syscall_name, args)				      \
+  .text;								      \
+  ENTRY (name)								      \
+	DO_CALL	(syscall_name, args);					      \
+	movi	a4, -4095;						      \
+	bgeu	a2, a4, SYSCALL_ERROR_LABEL;				      \
+  .Lpseudo_end:
+
+#undef	PSEUDO_END
+#define	PSEUDO_END(name)						      \
+  SYSCALL_ERROR_HANDLER							      \
+  END (name)
+
+#undef	PSEUDO_NOERRNO
+#define	PSEUDO_NOERRNO(name, syscall_name, args)			      \
+  .text;								      \
+  ENTRY (name)								      \
+	DO_CALL	(syscall_name, args)
+
+#undef	PSEUDO_END_NOERRNO
+#define	PSEUDO_END_NOERRNO(name)					      \
+  END (name)
+
+#undef	ret_NOERRNO
+#define ret_NOERRNO retw
+
+/* The function has to return the error code.  */
+#undef	PSEUDO_ERRVAL
+#define	PSEUDO_ERRVAL(name, syscall_name, args)				      \
+  .text;								      \
+  ENTRY (name)								      \
+	DO_CALL	(syscall_name, args);					      \
+	neg	a2, a2
+
+#undef	PSEUDO_END_ERRVAL
+#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;
+
+#elif defined _LIBC_REENTRANT
+
+# if USE___THREAD
+#  ifndef NOT_IN_libc
+#   define SYSCALL_ERROR_ERRNO __libc_errno
+#  else
+#   define SYSCALL_ERROR_ERRNO errno
+#  endif
+#  define SYSCALL_ERROR_HANDLER						      \
+0:	rur	a4, THREADPTR;						      \
+	movi	a3, SYSCALL_ERROR_ERRNO@TPOFF;				      \
+	neg	a2, a2;							      \
+	add	a4, a4, a3;						      \
+	s32i	a2, a4, 0;						      \
+	movi	a2, -1;							      \
+	j	.Lpseudo_end;
+# else /* !USE___THREAD */
+#  define SYSCALL_ERROR_HANDLER						      \
+0:	neg	a2, a2;							      \
+	mov	a6, a2;							      \
+	movi	a4, __errno_location@PLT;				      \
+	callx4	a4;						              \
+	s32i	a2, a6, 0;						      \
+	movi	a2, -1;							      \
+	j	.Lpseudo_end;
+# endif /* !USE___THREAD */
+#else /* !_LIBC_REENTRANT */
+#define SYSCALL_ERROR_HANDLER						      \
+0:	movi	a4, errno;						      \
+	neg	a2, a2;							      \
+	s32i	a2, a4, 0;						      \
+	movi	a2, -1;							      \
+	j	.Lpseudo_end;
+#endif /* _LIBC_REENTRANT */
+
+#endif	/* __ASSEMBLER__ */

+ 170 - 0
libc/sysdeps/linux/xtensa/vfork.S

@@ -0,0 +1,170 @@
+/* Copyright (C) 2005, 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.  */
+
+#include "sysdep.h"
+#include <sys/syscall.h>
+#define _SIGNAL_H
+#include <bits/signum.h>
+
+
+/* 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.  */
+
+
+/* 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
+#endif
+
+#ifndef RESTORE_PID
+#define RESTORE_PID
+#endif
+
+
+/* pid_t vfork(void);
+   Implemented as __clone_syscall(CLONE_VFORK | CLONE_VM | SIGCHLD, 0) */
+
+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
+
+	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
+
+	/* a7: return address */
+.L4:	mov	a12, a2
+	mov	a13, a3
+
+	SAVE_PID
+
+	/* 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
+
+	movi	a5, -4096
+
+	mov	a6, a2
+	mov	a2, a12
+	mov	a3, a13
+
+	bgeu	a6, a5, 1f
+	jx	a7
+1:	call4	.Lerr			// returns to original caller
+
+
+	/* a11: return address */
+.L8:	mov	a12, a2
+	mov	a13, a3
+	mov	a14, a6
+
+	SAVE_PID
+
+	movi	a2, SYS_ify (clone)
+	movi	a3, 0
+	movi	a6, CLONE_VM | CLONE_VFORK | SIGCHLD
+	syscall
+
+	RESTORE_PID
+
+	movi	a9, -4096
+
+	mov	a10, a2
+	mov	a2, a12
+	mov	a3, a13
+	mov	a6, a14
+
+	bgeu	a10, a9, 1f
+	jx	a11
+1:	call8	.Lerr			// returns to original caller
+
+
+	/* a15: return address */
+.L12:	mov	a12, a2
+	mov	a13, a3
+	mov	a14, a6
+
+	SAVE_PID
+
+	movi	a2, SYS_ify (clone)
+	movi	a3, 0
+	movi	a6, CLONE_VM | CLONE_VFORK | SIGCHLD
+	syscall
+
+	RESTORE_PID
+
+	mov	a3, a13
+	movi	a13, -4096
+
+	mov	a6, a14
+	mov	a14, a2
+
+	mov	a2, a12
+
+	bgeu	a14, a13, 1f
+	jx	a15
+1:	call12	.Lerr			// returns to original caller
+
+
+	.align 4
+.Lerr:	entry	a1, 16
+
+	/* Restore the return address.  */
+	extui	a4, a0, 30, 2		// get the call-size bits
+	slli	a4, a4, 30
+	slli	a3, a3, 2		// clear high bits of target address
+	srli	a3, a3, 2
+	or	a0, a3, a4		// combine them
+
+	PSEUDO_END (__vfork)
+.Lpseudo_end:
+	retw
+
+libc_hidden_def (__vfork)
+
+weak_alias (__vfork, vfork)

+ 95 - 0
libc/sysdeps/linux/xtensa/windowspill.S

@@ -0,0 +1,95 @@
+/* Function to force register windows to the stack.
+   Copyright (C) 2005, 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.  */
+
+#include <bits/xtensa-config.h>
+
+	.text
+	.align  4
+	.literal_position
+	.global __window_spill
+	.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
+
+	/* Called with call8: touch register NUM_REGS-12 (4/20/52) */
+.L8:
+#if XCHAL_NUM_AREGS > 16
+	call12	1f
+	retw
+
+	.align	4
+1:	_entry	a1, 48			// touch NUM_REGS-24 (x/8/40)
+
+#if XCHAL_NUM_AREGS == 32
+	mov	a8, a0
+	retw
+#else
+	_entry	a1, 48			// touch NUM_REGS-36 (x/x/28)
+	mov	a12, a0
+	_entry	a1, 48			// touch NUM_REGS-48 (x/x/16)
+	mov	a12, a0
+	_entry	a1, 16			// touch NUM_REGS-60 (x/x/4)
+#endif
+#endif
+	mov	a4, a0
+	retw
+
+	/* Called with call4: touch register NUM_REGS-8 (8/24/56) */
+.L4:
+#if XCHAL_NUM_AREGS == 16
+	mov	a8, a0
+#else
+	call12	1f
+	retw
+
+	.align	4
+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)
+	mov	a12, a0
+	_entry	a1, 48			// touch NUM_REGS-44 (x/x/20)
+	mov	a12, a0
+	_entry	a1, 48			// touch NUM_REGS-56 (x/x/8)
+	mov	a8, a0
+#endif
+#endif
+	retw
+
+	/* Called with call12: touch register NUM_REGS-16 (x/16/48) */
+.L12:
+#if XCHAL_NUM_AREGS > 16
+	call12	1f
+	retw
+
+	.align	4
+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)
+	mov	a12, a0
+	_entry	a1, 48			// touch NUM_REGS-52 (x/x/12)
+	mov	a12, a0
+#endif
+#endif
+	retw

+ 48 - 0
libpthread/linuxthreads.old/sysdeps/xtensa/pt-machine.h

@@ -0,0 +1,48 @@
+/* Machine-dependent pthreads configuration and inline functions.
+   Xtensa version.
+
+   Copyright (C) 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 _PT_MACHINE_H
+#define _PT_MACHINE_H   1
+
+#include <sys/syscall.h>
+#include <asm/unistd.h>
+
+#ifndef PT_EI
+# define PT_EI extern inline
+#endif
+
+/* Memory barrier.  */
+#define MEMORY_BARRIER() __asm__ ("memw" : : : "memory")
+
+/* Spinlock implementation; required.  */
+PT_EI long int
+testandset (int *spinlock)
+{
+  int unused = 0;
+  return INTERNAL_SYSCALL (xtensa, , 4, SYS_XTENSA_ATOMIC_SET,
+			   spinlock, 1, unused);
+}
+
+/* Get some notion of the current stack.  Need not be exactly the top
+   of the stack, just something somewhere in the current frame.  */
+#define CURRENT_STACK_FRAME __builtin_frame_address (0)
+
+#endif /* _PT_MACHINE_H */

+ 1 - 0
test/Rules.mak

@@ -39,6 +39,7 @@ TARGET_ARCH:=$(shell $(CC) -dumpmachine | sed -e s'/-.*//' \
 	-e 's/sh[234]/sh/' \
 	-e 's/mips.*/mips/' \
 	-e 's/cris.*/cris/' \
+	-e 's/xtensa.*/xtensa/' \
 	)
 endif
 export TARGET_ARCH