OSDN Git Service

Chris Zankel writes:
authorMike Frysinger <vapier@gentoo.org>
Sat, 5 Jan 2008 10:05:27 +0000 (10:05 -0000)
committerMike Frysinger <vapier@gentoo.org>
Sat, 5 Jan 2008 10:05:27 +0000 (10:05 -0000)
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.

62 files changed:
Rules.mak
extra/Configs/Config.in
extra/Configs/Config.xtensa [new file with mode: 0644]
include/elf.h
ldso/include/dl-string.h
ldso/ldso/xtensa/dl-debug.h [new file with mode: 0644]
ldso/ldso/xtensa/dl-startup.h [new file with mode: 0644]
ldso/ldso/xtensa/dl-syscalls.h [new file with mode: 0644]
ldso/ldso/xtensa/dl-sysdep.h [new file with mode: 0644]
ldso/ldso/xtensa/elfinterp.c [new file with mode: 0644]
ldso/ldso/xtensa/resolve.S [new file with mode: 0644]
libc/string/xtensa/Makefile [new file with mode: 0644]
libc/string/xtensa/memcpy.S [new file with mode: 0644]
libc/string/xtensa/memset.S [new file with mode: 0644]
libc/string/xtensa/strcmp.S [new file with mode: 0644]
libc/string/xtensa/strcpy.S [new file with mode: 0644]
libc/string/xtensa/strlen.S [new file with mode: 0644]
libc/string/xtensa/strncpy.S [new file with mode: 0644]
libc/sysdeps/linux/xtensa/Makefile [new file with mode: 0644]
libc/sysdeps/linux/xtensa/Makefile.arch [new file with mode: 0644]
libc/sysdeps/linux/xtensa/__longjmp.S [new file with mode: 0644]
libc/sysdeps/linux/xtensa/__syscall_error.c [new file with mode: 0644]
libc/sysdeps/linux/xtensa/bits/endian.h [new file with mode: 0644]
libc/sysdeps/linux/xtensa/bits/fcntl.h [new file with mode: 0644]
libc/sysdeps/linux/xtensa/bits/ipc.h [new file with mode: 0644]
libc/sysdeps/linux/xtensa/bits/kernel_stat.h [new file with mode: 0644]
libc/sysdeps/linux/xtensa/bits/kernel_types.h [new file with mode: 0644]
libc/sysdeps/linux/xtensa/bits/mathdef.h [new file with mode: 0644]
libc/sysdeps/linux/xtensa/bits/mman.h [new file with mode: 0644]
libc/sysdeps/linux/xtensa/bits/msq.h [new file with mode: 0644]
libc/sysdeps/linux/xtensa/bits/setjmp.h [new file with mode: 0644]
libc/sysdeps/linux/xtensa/bits/shm.h [new file with mode: 0644]
libc/sysdeps/linux/xtensa/bits/sigcontextinfo.h [new file with mode: 0644]
libc/sysdeps/linux/xtensa/bits/stackinfo.h [new file with mode: 0644]
libc/sysdeps/linux/xtensa/bits/stat.h [new file with mode: 0644]
libc/sysdeps/linux/xtensa/bits/syscalls.h [new file with mode: 0644]
libc/sysdeps/linux/xtensa/bits/uClibc_arch_features.h [new file with mode: 0644]
libc/sysdeps/linux/xtensa/bits/uClibc_page.h [new file with mode: 0644]
libc/sysdeps/linux/xtensa/bits/wordsize.h [new file with mode: 0644]
libc/sysdeps/linux/xtensa/bits/xtensa-config.h [new file with mode: 0644]
libc/sysdeps/linux/xtensa/brk.c [new file with mode: 0644]
libc/sysdeps/linux/xtensa/bsd-_setjmp.S [new file with mode: 0644]
libc/sysdeps/linux/xtensa/bsd-setjmp.S [new file with mode: 0644]
libc/sysdeps/linux/xtensa/clone.S [new file with mode: 0644]
libc/sysdeps/linux/xtensa/crt1.S [new file with mode: 0644]
libc/sysdeps/linux/xtensa/crti.S [new file with mode: 0644]
libc/sysdeps/linux/xtensa/crtn.S [new file with mode: 0644]
libc/sysdeps/linux/xtensa/fork.c [new file with mode: 0644]
libc/sysdeps/linux/xtensa/mmap.S [new file with mode: 0644]
libc/sysdeps/linux/xtensa/posix_fadvise.c [new file with mode: 0644]
libc/sysdeps/linux/xtensa/posix_fadvise64.c [new file with mode: 0644]
libc/sysdeps/linux/xtensa/pread_write.c [new file with mode: 0644]
libc/sysdeps/linux/xtensa/setjmp.S [new file with mode: 0644]
libc/sysdeps/linux/xtensa/sys/procfs.h [new file with mode: 0644]
libc/sysdeps/linux/xtensa/sys/ptrace.h [new file with mode: 0644]
libc/sysdeps/linux/xtensa/sys/ucontext.h [new file with mode: 0644]
libc/sysdeps/linux/xtensa/syscall.S [new file with mode: 0644]
libc/sysdeps/linux/xtensa/sysdep.h [new file with mode: 0644]
libc/sysdeps/linux/xtensa/vfork.S [new file with mode: 0644]
libc/sysdeps/linux/xtensa/windowspill.S [new file with mode: 0644]
libpthread/linuxthreads.old/sysdeps/xtensa/pt-machine.h [new file with mode: 0644]
test/Rules.mak

index c14a907..99d7efa 100644 (file)
--- a/Rules.mak
+++ b/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/ )
 
 
 #---------------------------------------------------------
index ec4cb4b..37dc0ba 100644 (file)
@@ -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
diff --git a/extra/Configs/Config.xtensa b/extra/Configs/Config.xtensa
new file mode 100644 (file)
index 0000000..7513247
--- /dev/null
@@ -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
+
index 5ce5c69..4c6d090 100644 (file)
@@ -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 */
index bf993b2..746bd91 100644 (file)
@@ -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
diff --git a/ldso/ldso/xtensa/dl-debug.h b/ldso/ldso/xtensa/dl-debug.h
new file mode 100644 (file)
index 0000000..327defc
--- /dev/null
@@ -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"
+};
diff --git a/ldso/ldso/xtensa/dl-startup.h b/ldso/ldso/xtensa/dl-startup.h
new file mode 100644 (file)
index 0000000..2fd0128
--- /dev/null
@@ -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)
diff --git a/ldso/ldso/xtensa/dl-syscalls.h b/ldso/ldso/xtensa/dl-syscalls.h
new file mode 100644 (file)
index 0000000..4b42a57
--- /dev/null
@@ -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);}
+
diff --git a/ldso/ldso/xtensa/dl-sysdep.h b/ldso/ldso/xtensa/dl-sysdep.h
new file mode 100644 (file)
index 0000000..afbbf3b
--- /dev/null
@@ -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++;
+    }
+}
diff --git a/ldso/ldso/xtensa/elfinterp.c b/ldso/ldso/xtensa/elfinterp.c
new file mode 100644 (file)
index 0000000..a459431
--- /dev/null
@@ -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);
+}
diff --git a/ldso/ldso/xtensa/resolve.S b/ldso/ldso/xtensa/resolve.S
new file mode 100644 (file)
index 0000000..fb29839
--- /dev/null
@@ -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
diff --git a/libc/string/xtensa/Makefile b/libc/string/xtensa/Makefile
new file mode 100644 (file)
index 0000000..0a95346
--- /dev/null
@@ -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
diff --git a/libc/string/xtensa/memcpy.S b/libc/string/xtensa/memcpy.S
new file mode 100644 (file)
index 0000000..19f3a68
--- /dev/null
@@ -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)
diff --git a/libc/string/xtensa/memset.S b/libc/string/xtensa/memset.S
new file mode 100644 (file)
index 0000000..c092882
--- /dev/null
@@ -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)
diff --git a/libc/string/xtensa/strcmp.S b/libc/string/xtensa/strcmp.S
new file mode 100644 (file)
index 0000000..90c418d
--- /dev/null
@@ -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
diff --git a/libc/string/xtensa/strcpy.S b/libc/string/xtensa/strcpy.S
new file mode 100644 (file)
index 0000000..1080703
--- /dev/null
@@ -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)
diff --git a/libc/string/xtensa/strlen.S b/libc/string/xtensa/strlen.S
new file mode 100644 (file)
index 0000000..dd72c16
--- /dev/null
@@ -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)
diff --git a/libc/string/xtensa/strncpy.S b/libc/string/xtensa/strncpy.S
new file mode 100644 (file)
index 0000000..7ba2ef7
--- /dev/null
@@ -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)
diff --git a/libc/sysdeps/linux/xtensa/Makefile b/libc/sysdeps/linux/xtensa/Makefile
new file mode 100644 (file)
index 0000000..633c91f
--- /dev/null
@@ -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
diff --git a/libc/sysdeps/linux/xtensa/Makefile.arch b/libc/sysdeps/linux/xtensa/Makefile.arch
new file mode 100644 (file)
index 0000000..74510c9
--- /dev/null
@@ -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
diff --git a/libc/sysdeps/linux/xtensa/__longjmp.S b/libc/sysdeps/linux/xtensa/__longjmp.S
new file mode 100644 (file)
index 0000000..0fa9390
--- /dev/null
@@ -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)
diff --git a/libc/sysdeps/linux/xtensa/__syscall_error.c b/libc/sysdeps/linux/xtensa/__syscall_error.c
new file mode 100644 (file)
index 0000000..2b642e8
--- /dev/null
@@ -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;
+}
diff --git a/libc/sysdeps/linux/xtensa/bits/endian.h b/libc/sysdeps/linux/xtensa/bits/endian.h
new file mode 100644 (file)
index 0000000..38b3af3
--- /dev/null
@@ -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
diff --git a/libc/sysdeps/linux/xtensa/bits/fcntl.h b/libc/sysdeps/linux/xtensa/bits/fcntl.h
new file mode 100644 (file)
index 0000000..2c4e2f0
--- /dev/null
@@ -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
diff --git a/libc/sysdeps/linux/xtensa/bits/ipc.h b/libc/sysdeps/linux/xtensa/bits/ipc.h
new file mode 100644 (file)
index 0000000..481bdcc
--- /dev/null
@@ -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;
+  };
diff --git a/libc/sysdeps/linux/xtensa/bits/kernel_stat.h b/libc/sysdeps/linux/xtensa/bits/kernel_stat.h
new file mode 100644 (file)
index 0000000..6afb3a6
--- /dev/null
@@ -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 */
diff --git a/libc/sysdeps/linux/xtensa/bits/kernel_types.h b/libc/sysdeps/linux/xtensa/bits/kernel_types.h
new file mode 100644 (file)
index 0000000..f392ba7
--- /dev/null
@@ -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 */
diff --git a/libc/sysdeps/linux/xtensa/bits/mathdef.h b/libc/sysdeps/linux/xtensa/bits/mathdef.h
new file mode 100644 (file)
index 0000000..0177fa9
--- /dev/null
@@ -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
diff --git a/libc/sysdeps/linux/xtensa/bits/mman.h b/libc/sysdeps/linux/xtensa/bits/mman.h
new file mode 100644 (file)
index 0000000..d3beae6
--- /dev/null
@@ -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
diff --git a/libc/sysdeps/linux/xtensa/bits/msq.h b/libc/sysdeps/linux/xtensa/bits/msq.h
new file mode 100644 (file)
index 0000000..2eca21e
--- /dev/null
@@ -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 */
diff --git a/libc/sysdeps/linux/xtensa/bits/setjmp.h b/libc/sysdeps/linux/xtensa/bits/setjmp.h
new file mode 100644 (file)
index 0000000..1bc4896
--- /dev/null
@@ -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 */
diff --git a/libc/sysdeps/linux/xtensa/bits/shm.h b/libc/sysdeps/linux/xtensa/bits/shm.h
new file mode 100644 (file)
index 0000000..de41d0d
--- /dev/null
@@ -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
diff --git a/libc/sysdeps/linux/xtensa/bits/sigcontextinfo.h b/libc/sysdeps/linux/xtensa/bits/sigcontextinfo.h
new file mode 100644 (file)
index 0000000..8f3301c
--- /dev/null
@@ -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))
+
diff --git a/libc/sysdeps/linux/xtensa/bits/stackinfo.h b/libc/sysdeps/linux/xtensa/bits/stackinfo.h
new file mode 100644 (file)
index 0000000..50ddf25
--- /dev/null
@@ -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 */
diff --git a/libc/sysdeps/linux/xtensa/bits/stat.h b/libc/sysdeps/linux/xtensa/bits/stat.h
new file mode 100644 (file)
index 0000000..c6debc8
--- /dev/null
@@ -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.  */
diff --git a/libc/sysdeps/linux/xtensa/bits/syscalls.h b/libc/sysdeps/linux/xtensa/bits/syscalls.h
new file mode 100644 (file)
index 0000000..76bcf40
--- /dev/null
@@ -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 */
diff --git a/libc/sysdeps/linux/xtensa/bits/uClibc_arch_features.h b/libc/sysdeps/linux/xtensa/bits/uClibc_arch_features.h
new file mode 100644 (file)
index 0000000..7abd0ce
--- /dev/null
@@ -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 */
diff --git a/libc/sysdeps/linux/xtensa/bits/uClibc_page.h b/libc/sysdeps/linux/xtensa/bits/uClibc_page.h
new file mode 100644 (file)
index 0000000..74a9f60
--- /dev/null
@@ -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 */
diff --git a/libc/sysdeps/linux/xtensa/bits/wordsize.h b/libc/sysdeps/linux/xtensa/bits/wordsize.h
new file mode 100644 (file)
index 0000000..ba643b6
--- /dev/null
@@ -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
diff --git a/libc/sysdeps/linux/xtensa/bits/xtensa-config.h b/libc/sysdeps/linux/xtensa/bits/xtensa-config.h
new file mode 100644 (file)
index 0000000..34cf28c
--- /dev/null
@@ -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 */
diff --git a/libc/sysdeps/linux/xtensa/brk.c b/libc/sysdeps/linux/xtensa/brk.c
new file mode 100644 (file)
index 0000000..51f610b
--- /dev/null
@@ -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)
diff --git a/libc/sysdeps/linux/xtensa/bsd-_setjmp.S b/libc/sysdeps/linux/xtensa/bsd-_setjmp.S
new file mode 100644 (file)
index 0000000..4e6a2da
--- /dev/null
@@ -0,0 +1 @@
+/* _setjmp is in setjmp.S  */
diff --git a/libc/sysdeps/linux/xtensa/bsd-setjmp.S b/libc/sysdeps/linux/xtensa/bsd-setjmp.S
new file mode 100644 (file)
index 0000000..1da848d
--- /dev/null
@@ -0,0 +1 @@
+/* setjmp is in setjmp.S  */
diff --git a/libc/sysdeps/linux/xtensa/clone.S b/libc/sysdeps/linux/xtensa/clone.S
new file mode 100644 (file)
index 0000000..31921ea
--- /dev/null
@@ -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)
diff --git a/libc/sysdeps/linux/xtensa/crt1.S b/libc/sysdeps/linux/xtensa/crt1.S
new file mode 100644 (file)
index 0000000..63fbadc
--- /dev/null
@@ -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
diff --git a/libc/sysdeps/linux/xtensa/crti.S b/libc/sysdeps/linux/xtensa/crti.S
new file mode 100644 (file)
index 0000000..a01c02c
--- /dev/null
@@ -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
diff --git a/libc/sysdeps/linux/xtensa/crtn.S b/libc/sysdeps/linux/xtensa/crtn.S
new file mode 100644 (file)
index 0000000..ab1a489
--- /dev/null
@@ -0,0 +1,8 @@
+/* glibc's sysdeps/xtensa/elf/initfini.c used for reference [EPILOG] */
+
+       .section .init
+       retw
+
+
+       .section .fini
+       retw
diff --git a/libc/sysdeps/linux/xtensa/fork.c b/libc/sysdeps/linux/xtensa/fork.c
new file mode 100644 (file)
index 0000000..0348441
--- /dev/null
@@ -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)
diff --git a/libc/sysdeps/linux/xtensa/mmap.S b/libc/sysdeps/linux/xtensa/mmap.S
new file mode 100644 (file)
index 0000000..c991e7d
--- /dev/null
@@ -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)
diff --git a/libc/sysdeps/linux/xtensa/posix_fadvise.c b/libc/sysdeps/linux/xtensa/posix_fadvise.c
new file mode 100644 (file)
index 0000000..0fe13a1
--- /dev/null
@@ -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
+}
diff --git a/libc/sysdeps/linux/xtensa/posix_fadvise64.c b/libc/sysdeps/linux/xtensa/posix_fadvise64.c
new file mode 100644 (file)
index 0000000..1fdeeba
--- /dev/null
@@ -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__ */
diff --git a/libc/sysdeps/linux/xtensa/pread_write.c b/libc/sysdeps/linux/xtensa/pread_write.c
new file mode 100644 (file)
index 0000000..9e88132
--- /dev/null
@@ -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 */
diff --git a/libc/sysdeps/linux/xtensa/setjmp.S b/libc/sysdeps/linux/xtensa/setjmp.S
new file mode 100644 (file)
index 0000000..5e81460
--- /dev/null
@@ -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)
diff --git a/libc/sysdeps/linux/xtensa/sys/procfs.h b/libc/sysdeps/linux/xtensa/sys/procfs.h
new file mode 100644 (file)
index 0000000..785c400
--- /dev/null
@@ -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 */
diff --git a/libc/sysdeps/linux/xtensa/sys/ptrace.h b/libc/sysdeps/linux/xtensa/sys/ptrace.h
new file mode 100644 (file)
index 0000000..7aad929
--- /dev/null
@@ -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 */
diff --git a/libc/sysdeps/linux/xtensa/sys/ucontext.h b/libc/sysdeps/linux/xtensa/sys/ucontext.h
new file mode 100644 (file)
index 0000000..4c37201
--- /dev/null
@@ -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 */
diff --git a/libc/sysdeps/linux/xtensa/syscall.S b/libc/sysdeps/linux/xtensa/syscall.S
new file mode 100644 (file)
index 0000000..955e889
--- /dev/null
@@ -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)
diff --git a/libc/sysdeps/linux/xtensa/sysdep.h b/libc/sysdeps/linux/xtensa/sysdep.h
new file mode 100644 (file)
index 0000000..5708a81
--- /dev/null
@@ -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__ */
diff --git a/libc/sysdeps/linux/xtensa/vfork.S b/libc/sysdeps/linux/xtensa/vfork.S
new file mode 100644 (file)
index 0000000..830a0cd
--- /dev/null
@@ -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)
diff --git a/libc/sysdeps/linux/xtensa/windowspill.S b/libc/sysdeps/linux/xtensa/windowspill.S
new file mode 100644 (file)
index 0000000..950c27b
--- /dev/null
@@ -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
diff --git a/libpthread/linuxthreads.old/sysdeps/xtensa/pt-machine.h b/libpthread/linuxthreads.old/sysdeps/xtensa/pt-machine.h
new file mode 100644 (file)
index 0000000..d5ab9f0
--- /dev/null
@@ -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 */
index ce63977..f6d9fcd 100644 (file)
@@ -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