Browse Source

add support for xtensa architecture, tested with qemu. thanks to Max Filippov for help

Waldemar Brodkorb 10 years ago
parent
commit
47e4109811

+ 5 - 1
mk/vars.mk

@@ -134,7 +134,11 @@ endif
 
 ifeq ($(ADK_LINUX_MICROBLAZE),y)
 TARGET_CFLAGS+=		-mxl-barrel-shift
-TARGET_CXX_FLAGS+=	-mxl-barrel-shift
+TARGET_CXXFLAGS+=	-mxl-barrel-shift
+endif
+ifeq ($(ADK_LINUX_XTENSA),y)
+TARGET_CFLAGS+=		-mlongcalls -mtext-section-literals
+TARGET_CXXFLAGS+=	-mlongcalls -mtext-section-literals
 endif
 
 ifneq ($(ADK_DEBUG),)

+ 1 - 1
package/boost/Makefile

@@ -14,7 +14,7 @@ PKG_URL:=		http://www.boost.org/
 PKG_SITES:=		${MASTER_SITE_SOURCEFORGE:=boost/}
 PKG_OPTS:=		dev
 
-PKG_ARCH_DEPENDS:=	!m68k
+PKG_ARCH_DEPENDS:=	!m68k !xtensa
 
 DISTFILES:=		boost_1_55_0.tar.gz
 WRKDIST=		${WRKDIR}/${PKG_NAME}_1_55_0

+ 2 - 1
package/mkimage/Makefile

@@ -22,7 +22,8 @@ $(eval $(call HOST_template,MKIMAGE,mkimage,$(PKG_VERSION)-${PKG_RELEASE}))
 HOST_STYLE:=		manual
 
 host-build:
-	$(CC_FOR_BUILD) $(CFLAGS_FOR_BUILD) -o ${WRKBUILD}/mkimage ${WRKBUILD}/mkimage.c ${WRKBUILD}/crc32.c
+	$(CC_FOR_BUILD) $(CFLAGS_FOR_BUILD) -o ${WRKBUILD}/mkimage \
+		${WRKBUILD}/mkimage.c ${WRKBUILD}/crc32.c
 
 mkimage-hostinstall:
 	${INSTALL_DIR} ${STAGING_HOST_DIR}/usr/bin

+ 1 - 0
package/mkimage/src/image.h

@@ -77,6 +77,7 @@
 #define IH_CPU_NIOS2		15	/* Nios-II	*/
 #define IH_CPU_BLACKFIN		16	/* Blackfin	*/
 #define IH_CPU_AVR32		17	/* AVR32	*/
+#define IH_CPU_XTENSA		18	/* XTENSA	*/
 
 /*
  * Image Types

+ 1 - 0
package/mkimage/src/mkimage.c

@@ -98,6 +98,7 @@ table_entry_t arch_name[] = {
     {	IH_CPU_SPARC64,		"sparc64",	"SPARC 64 Bit",	},
     {	IH_CPU_BLACKFIN,	"blackfin",	"Blackfin",	},
     {	IH_CPU_AVR32,		"avr32",	"AVR32",	},
+    {	IH_CPU_XTENSA,		"xtensa",	"XTENSA",	},
     {	-1,			"",		"",		},
 };
 

+ 3 - 0
package/openssl/Makefile

@@ -46,6 +46,9 @@ endif
 ifeq ($(ADK_LINUX_MICROBLAZE),y)
 TARGET_CFLAGS:=		$(subst g3,g,$(TARGET_CFLAGS))
 endif
+ifeq ($(ADK_LINUX_XTENSA),y)
+TARGET_CFLAGS:=		$(subst g3,g,$(TARGET_CFLAGS))
+endif
 
 ifeq ($(ADK_LINUX_X86_64),y)
 CONFIG:=		linux-embedded-x86_64

+ 1 - 0
target/arch.lst

@@ -11,3 +11,4 @@ sparc64
 sh
 x86
 x86_64
+xtensa

+ 1 - 1
target/config/Config.in.cpu

@@ -130,4 +130,4 @@ config ADK_TARGET_CPU_ARCH
 	default "sh4eb" if ADK_LINUX_SH && ADK_big
 	default "ppc" if ADK_CPU_PPC
 	default "ppc64" if ADK_CPU_PPC64
-
+	default "xtensa" if ADK_LINUX_XTENSA

+ 1 - 0
target/config/Config.in.kernel

@@ -47,6 +47,7 @@ config ADK_TARGET_KERNEL_MINICONFIG
 	default "qemu-sparc64" if ADK_TARGET_SYSTEM_QEMU_SPARC64
 	default "qemu-x86" if ADK_TARGET_SYSTEM_QEMU_X86
 	default "qemu-x86_64" if ADK_TARGET_SYSTEM_QEMU_X86_64
+	default "qemu-xtensa" if ADK_TARGET_SYSTEM_QEMU_XTENSA
 	default "aranym-m68k" if ADK_TARGET_SYSTEM_ARANYM_M68K
 	default "vbox-x86" if ADK_TARGET_SYSTEM_VBOX_X86
 	default "ibm-x40" if ADK_TARGET_SYSTEM_IBM_X40

+ 1 - 0
target/config/Config.in.libc.choice

@@ -9,6 +9,7 @@ config ADK_TARGET_LIB_GLIBC
 	prompt "GNU C library"
 	boolean
 	select ADK_glibc
+	depends on !ADK_LINUX_XTENSA
 	help
 	 http://www.gnu.org/libc
 

+ 1 - 1
target/config/Config.in.qemuopts

@@ -29,7 +29,7 @@ endchoice
 
 choice
 prompt "Qemu Emulation with storage device"
-depends on ADK_TARGET_QEMU
+depends on ADK_TARGET_QEMU && !ADK_TARGET_SYSTEM_QEMU_XTENSA
 default ADK_TARGET_QEMU_WITH_BLOCK if ADK_TARGET_ROOTFS_ARCHIVE
 default ADK_TARGET_QEMU_WITH_BLOCK if ADK_TARGET_ROOTFS_SQUASHFS
 default ADK_TARGET_QEMU_WITH_BLOCK if ADK_TARGET_ROOTFS_JFFS2

+ 4 - 2
target/config/Config.in.target

@@ -58,6 +58,7 @@ config ADK_TARGET_CMDLINE
 	default "console=ttySC1" if ADK_TARGET_SYSTEM_QEMU_SH
 	default "console=ttyS0,115200" if ADK_TARGET_SYSTEM_QEMU_SPARC64
 	default "console=ttyS0,115200" if ADK_TARGET_SYSTEM_QEMU_X86 || ADK_TARGET_SYSTEM_QEMU_X86_64
+	default "console=ttyS0,38400" if ADK_TARGET_SYSTEM_QEMU_XTENSA
 	default ""
 
 choice
@@ -76,9 +77,9 @@ config ADK_TARGET_ROOTFS_INITRAMFS
 		ADK_LINUX_PPC || \
 		ADK_LINUX_SPARC || \
 		ADK_LINUX_X86 || \
-		ADK_LINUX_X86_64 || \
-		ADK_LINUX_NATIVE
+		ADK_LINUX_X86_64
 	depends on !ADK_TARGET_VBOX
+	depends on !ADK_TARGET_SYSTEM_QEMU_XTENSA
 	depends on !ADK_TARGET_SYSTEM_RASPBERRY_PI
 	depends on !ADK_TARGET_SYSTEM_MIKROTIK_RB532
 	select ADK_KERNEL_BLK_DEV_INITRD
@@ -183,6 +184,7 @@ config ADK_TARGET_ROOTFS_ISO
 config ADK_TARGET_ROOTFS_INITRAMFSARCHIVE
 	boolean "Archive usable for initramfs creation"
 	depends on !ADK_TARGET_SYSTEM_MIKROTIK_RB532
+	depends on !ADK_TARGET_SYSTEM_QEMU_XTENSA
 	help
 	  Use this option if your planning to create a initramfs,
 	  useful for adk-test-framework.

+ 9 - 0
target/xtensa/Config.in

@@ -0,0 +1,9 @@
+choice
+depends on ADK_LINUX_XTENSA && !ADK_CHOOSE_TARGET_ARCH
+prompt "Target system"
+
+config ADK_CHOOSE_TARGET_SYSTEM_XTENSA
+        boolean "Choose target system"
+
+source "target/xtensa/Config.in.systems"
+endchoice

+ 69 - 0
target/xtensa/Makefile

@@ -0,0 +1,69 @@
+# This file is part of the OpenADK project. OpenADK is copyrighted
+# material, please see the LICENCE file in the top-level directory.
+
+include $(TOPDIR)/rules.mk
+include $(TOPDIR)/mk/kernel.mk
+include $(TOPDIR)/mk/modules.mk
+include $(TOPDIR)/mk/kernel-build.mk
+include $(TOPDIR)/mk/image.mk
+
+KERNEL:=$(LINUX_DIR)/arch/xtensa/boot/Image.elf
+
+QEMU_ARGS:=-M lx60 -cpu dc232b -monitor null
+QEMU_ARGS+=${ADK_QEMU_ARGS}
+
+# target helper text
+ifeq ($(ADK_TARGET_FS),archive)
+targethelp:
+	@echo "The RootFS tarball is: $(FW_DIR)/$(ROOTFSTARBALL)"
+ifeq ($(ADK_TARGET_QEMU),y)
+	@echo 'The kernel file is: $(FW_DIR)/${TARGET_KERNEL}'
+	@echo "Use following command to create a QEMU Image:"
+	@echo "./scripts/create.sh qemu-${ADK_TARGET_CPU_ARCH}.img $(FW_DIR)/$(ROOTFSTARBALL)"
+	@echo "Start qemu with following options:"
+	@echo 'qemu-system-${ADK_TARGET_CPU_ARCH} ${QEMU_ARGS} -kernel $(FW_DIR)/$(TARGET_KERNEL) qemu-${ADK_TARGET_CPU_ARCH}.img'
+endif
+endif
+ifeq ($(ADK_TARGET_FS),initramfs)
+targethelp:
+	@echo 'The kernel file is: $(FW_DIR)/${TARGET_KERNEL}'
+	@echo 'The initramfs image is: ${FW_DIR}/${INITRAMFS}'
+ifeq ($(ADK_TARGET_QEMU),y)
+	@echo "Start qemu with following command line:"
+	@echo 'qemu-system-${ADK_TARGET_CPU_ARCH} ${QEMU_ARGS} -kernel $(FW_DIR)/$(TARGET_KERNEL) -initrd ${FW_DIR}/${INITRAMFS}'
+endif
+endif
+ifeq ($(ADK_TARGET_FS),initramfsarchive)
+targethelp:
+	@echo 'The kernel file is: $(FW_DIR)/${TARGET_KERNEL}'
+	@echo "The RootFS tarball is: $(FW_DIR)/$(ROOTFSUSERTARBALL)"
+endif
+ifeq ($(ADK_TARGET_FS),initramfspiggyback)
+targethelp:
+	@echo 'The kernel+initramfs file is: $(FW_DIR)/${TARGET_KERNEL}'
+ifeq ($(ADK_TARGET_QEMU),y)
+	@echo "Start qemu with following command line:"
+	@echo 'qemu-system-${ADK_TARGET_CPU_ARCH} ${QEMU_ARGS} -kernel $(FW_DIR)/$(TARGET_KERNEL)'
+endif
+endif
+
+# image creation and kernel install
+kernel-strip:
+	$(TARGET_CROSS)objcopy $(OSTRIP) -S $(KERNEL) $(BUILD_DIR)/$(TARGET_KERNEL)
+
+kernel-install: kernel-strip
+	@cp $(BUILD_DIR)/$(TARGET_KERNEL) $(FW_DIR)/${TARGET_KERNEL}
+
+# filesystem specific targets
+ifeq ($(ADK_TARGET_FS),archive)
+imageinstall: $(FW_DIR)/$(ROOTFSTARBALL) targethelp
+endif
+ifeq ($(ADK_TARGET_FS),initramfs)
+imageinstall: kernel-install $(FW_DIR)/$(INITRAMFS) targethelp
+endif
+ifeq ($(ADK_TARGET_FS),initramfsarchive)
+imageinstall: kernel-install $(FW_DIR)/$(ROOTFSUSERTARBALL) targethelp
+endif
+ifeq ($(ADK_TARGET_FS),initramfspiggyback)
+imageinstall: createinitramfs targethelp
+endif

+ 8 - 0
target/xtensa/kernel/qemu-xtensa

@@ -0,0 +1,8 @@
+CONFIG_XTENSA=y
+CONFIG_XTENSA_VARIANT_DC232B=y
+CONFIG_XTENSA_UNALIGNED_USER=y
+CONFIG_MATH_EMULATION=y
+CONFIG_XTENSA_PLATFORM_XTFPGA=y
+CONFIG_SERIAL_CONSOLE=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y

BIN
target/xtensa/overlay/xtensa_dc232b.tar


+ 10 - 0
target/xtensa/systems/qemu-xtensa

@@ -0,0 +1,10 @@
+config ADK_TARGET_SYSTEM_QEMU_XTENSA
+	bool "Qemu Emulator"
+	select ADK_xtensa
+	select ADK_qemu_xtensa
+	select ADK_TARGET_QEMU
+	select ADK_TARGET_KERNEL_ZIMAGE
+	select ADK_HOST_NEED_MKIMAGE
+	help
+	 Support for Qemu Emulator XTENSA architecture.
+

+ 9 - 0
target/xtensa/systems/toolchain-xtensa

@@ -0,0 +1,9 @@
+config ADK_TARGET_SYSTEM_TOOLCHAIN_XTENSA
+	bool "Toolchain only"
+	select ADK_xtensa
+	select ADK_toolchain_xtensa
+	select ADK_TARGET_TOOLCHAIN
+	select ADK_TARGET_PACKAGE_TXZ
+	help
+	  XTENSA toolchain.
+

+ 4 - 0
target/xtensa/target.mk

@@ -0,0 +1,4 @@
+include $(TOPDIR)/mk/kernel-ver.mk
+ARCH:=			xtensa
+CPU_ARCH:=		$(ADK_TARGET_CPU_ARCH)
+TARGET_CFLAGS_ARCH:=    $(ADK_TARGET_CFLAGS)

+ 243 - 0
target/xtensa/uclibc.config

@@ -0,0 +1,243 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# uClibc 0.9.34-git C Library Configuration
+#
+# TARGET_alpha is not set
+# TARGET_arc is not set
+# TARGET_arm is not set
+# TARGET_avr32 is not set
+# TARGET_bfin is not set
+# TARGET_c6x is not set
+# TARGET_cris is not set
+# TARGET_e1 is not set
+# TARGET_frv is not set
+# TARGET_h8300 is not set
+# TARGET_hppa is not set
+# TARGET_i386 is not set
+# TARGET_i960 is not set
+# TARGET_ia64 is not set
+# TARGET_m68k is not set
+# TARGET_metag is not set
+# TARGET_microblaze is not set
+# TARGET_mips is not set
+# TARGET_nios is not set
+# TARGET_nios2 is not set
+# TARGET_powerpc is not set
+# TARGET_sh is not set
+# TARGET_sh64 is not set
+# TARGET_sparc is not set
+# TARGET_v850 is not set
+# TARGET_vax is not set
+# TARGET_x86_64 is not set
+TARGET_xtensa=y
+
+#
+# Target Architecture Features and Options
+#
+TARGET_ARCH="xtensa"
+FORCE_OPTIONS_FOR_ARCH=y
+TARGET_SUBARCH=""
+
+#
+# Using ELF file format
+#
+ARCH_HAS_DEPRECATED_SYSCALLS=y
+ARCH_HAS_MMU=y
+ARCH_USE_MMU=y
+UCLIBC_HAS_FLOATS=y
+UCLIBC_HAS_FPU=y
+DO_C99_MATH=y
+# DO_XSI_MATH is not set
+UCLIBC_HAS_FENV=yes
+KERNEL_HEADERS=""
+HAVE_DOT_CONFIG=y
+
+#
+# General Library Settings
+#
+DOPIC=y
+HAVE_SHARED=y
+# FORCE_SHAREABLE_TEXT_SEGMENTS is not set
+LDSO_LDD_SUPPORT=y
+LDSO_CACHE_SUPPORT=y
+# LDSO_PRELOAD_ENV_SUPPORT is not set
+# LDSO_PRELOAD_FILE_SUPPORT is not set
+LDSO_BASE_FILENAME="ld.so"
+# LDSO_STANDALONE_SUPPORT is not set
+# LDSO_PRELINK_SUPPORT is not set
+# UCLIBC_STATIC_LDCONFIG is not set
+LDSO_RUNPATH=y
+LDSO_SAFE_RUNPATH=y
+LDSO_SEARCH_INTERP_PATH=y
+LDSO_LD_LIBRARY_PATH=y
+LDSO_NO_CLEANUP=y
+UCLIBC_CTOR_DTOR=y
+# LDSO_GNU_HASH_SUPPORT is not set
+# HAS_NO_THREADS is not set
+# LINUXTHREADS_OLD is not set
+# LINUXTHREADS_NEW is not set
+UCLIBC_HAS_THREADS_NATIVE=yes
+UCLIBC_HAS_THREADS=y
+# PTHREADS_DEBUG_SUPPORT is not set
+UCLIBC_HAS_SYSLOG=y
+UCLIBC_HAS_LFS=y
+# MALLOC is not set
+# MALLOC_SIMPLE is not set
+MALLOC_STANDARD=y
+MALLOC_GLIBC_COMPAT=y
+UCLIBC_HAS_OBSTACK=y
+UCLIBC_DYNAMIC_ATEXIT=y
+COMPAT_ATEXIT=y
+# UCLIBC_SUSV2_LEGACY is not set
+UCLIBC_SUSV3_LEGACY=y
+# UCLIBC_SUSV3_LEGACY_MACROS is not set
+UCLIBC_SUSV4_LEGACY=y
+# UCLIBC_STRICT_HEADERS is not set
+# UCLIBC_HAS_STUBS is not set
+UCLIBC_HAS_SHADOW=y
+UCLIBC_HAS_PROGRAM_INVOCATION_NAME=y
+UCLIBC_HAS___PROGNAME=y
+UCLIBC_HAS_PTY=y
+ASSUME_DEVPTS=y
+UNIX98PTY_ONLY=y
+UCLIBC_HAS_GETPT=y
+UCLIBC_HAS_LIBUTIL=y
+UCLIBC_HAS_TM_EXTENSIONS=y
+UCLIBC_HAS_TZ_CACHING=y
+UCLIBC_HAS_TZ_FILE=y
+UCLIBC_HAS_TZ_FILE_READ_MANY=y
+UCLIBC_TZ_FILE_PATH="/etc/TZ"
+UCLIBC_FALLBACK_TO_ETC_LOCALTIME=y
+
+#
+# Advanced Library Settings
+#
+UCLIBC_PWD_BUFFER_SIZE=256
+UCLIBC_GRP_BUFFER_SIZE=256
+
+#
+# Support various families of functions
+#
+UCLIBC_LINUX_MODULE_26=y
+# UCLIBC_LINUX_MODULE_24 is not set
+UCLIBC_LINUX_SPECIFIC=y
+UCLIBC_HAS_GNU_ERROR=y
+UCLIBC_BSD_SPECIFIC=y
+UCLIBC_HAS_BSD_ERR=y
+# UCLIBC_HAS_OBSOLETE_BSD_SIGNAL is not set
+# UCLIBC_HAS_OBSOLETE_SYSV_SIGNAL is not set
+# UCLIBC_NTP_LEGACY is not set
+# UCLIBC_SV4_DEPRECATED is not set
+UCLIBC_HAS_REALTIME=y
+UCLIBC_HAS_ADVANCED_REALTIME=y
+UCLIBC_HAS_EPOLL=y
+# UCLIBC_HAS_XATTR is not set
+# UCLIBC_HAS_PROFILING is not set
+UCLIBC_HAS_CRYPT_IMPL=y
+# UCLIBC_HAS_SHA256_CRYPT_IMPL is not set
+# UCLIBC_HAS_SHA512_CRYPT_IMPL is not set
+UCLIBC_HAS_CRYPT=y
+UCLIBC_HAS_NETWORK_SUPPORT=y
+UCLIBC_HAS_SOCKET=y
+UCLIBC_HAS_IPV4=y
+UCLIBC_HAS_IPV6=y
+UCLIBC_HAS_RPC=y
+UCLIBC_HAS_FULL_RPC=y
+UCLIBC_HAS_REENTRANT_RPC=y
+UCLIBC_USE_NETLINK=y
+UCLIBC_SUPPORT_AI_ADDRCONFIG=y
+UCLIBC_HAS_BSD_RES_CLOSE=y
+UCLIBC_HAS_COMPAT_RES_STATE=y
+# UCLIBC_HAS_EXTRA_COMPAT_RES_STATE is not set
+UCLIBC_HAS_RESOLVER_SUPPORT=y
+UCLIBC_HAS_LIBRESOLV_STUB=y
+UCLIBC_HAS_LIBNSL_STUB=y
+
+#
+# String and Stdio Support
+#
+UCLIBC_HAS_STRING_GENERIC_OPT=y
+UCLIBC_HAS_STRING_ARCH_OPT=y
+UCLIBC_HAS_CTYPE_TABLES=y
+UCLIBC_HAS_CTYPE_SIGNED=y
+# UCLIBC_HAS_CTYPE_UNSAFE is not set
+UCLIBC_HAS_CTYPE_CHECKED=y
+# UCLIBC_HAS_CTYPE_ENFORCED is not set
+UCLIBC_HAS_WCHAR=y
+# UCLIBC_HAS_LOCALE is not set
+UCLIBC_HAS_HEXADECIMAL_FLOATS=y
+UCLIBC_HAS_GLIBC_CUSTOM_PRINTF=y
+UCLIBC_PRINTF_SCANF_POSITIONAL_ARGS=9
+# UCLIBC_HAS_STDIO_BUFSIZ_256 is not set
+# UCLIBC_HAS_STDIO_BUFSIZ_512 is not set
+# UCLIBC_HAS_STDIO_BUFSIZ_1024 is not set
+# UCLIBC_HAS_STDIO_BUFSIZ_2048 is not set
+UCLIBC_HAS_STDIO_BUFSIZ_4096=y
+# UCLIBC_HAS_STDIO_BUFSIZ_8192 is not set
+UCLIBC_HAS_STDIO_BUILTIN_BUFFER_NONE=y
+# UCLIBC_HAS_STDIO_BUILTIN_BUFFER_4 is not set
+# UCLIBC_HAS_STDIO_BUILTIN_BUFFER_8 is not set
+# UCLIBC_HAS_STDIO_SHUTDOWN_ON_ABORT is not set
+UCLIBC_HAS_STDIO_GETC_MACRO=y
+UCLIBC_HAS_STDIO_PUTC_MACRO=y
+UCLIBC_HAS_STDIO_AUTO_RW_TRANSITION=y
+# UCLIBC_HAS_FOPEN_LARGEFILE_MODE is not set
+UCLIBC_HAS_FOPEN_EXCLUSIVE_MODE=y
+# UCLIBC_HAS_FOPEN_CLOSEEXEC_MODE is not set
+UCLIBC_HAS_GLIBC_CUSTOM_STREAMS=y
+UCLIBC_HAS_PRINTF_M_SPEC=y
+UCLIBC_HAS_ERRNO_MESSAGES=y
+# UCLIBC_HAS_SYS_ERRLIST is not set
+UCLIBC_HAS_SIGNUM_MESSAGES=y
+# UCLIBC_HAS_SYS_SIGLIST is not set
+UCLIBC_HAS_GNU_GETOPT=y
+UCLIBC_HAS_GNU_GETSUBOPT=y
+
+#
+# Big and Tall
+#
+UCLIBC_HAS_REGEX=y
+# UCLIBC_HAS_REGEX_OLD is not set
+UCLIBC_HAS_FNMATCH=y
+# UCLIBC_HAS_FNMATCH_OLD is not set
+UCLIBC_HAS_WORDEXP=y
+UCLIBC_HAS_NFTW=y
+UCLIBC_HAS_FTW=y
+UCLIBC_HAS_FTS=y
+UCLIBC_HAS_GLOB=y
+UCLIBC_HAS_GNU_GLOB=y
+UCLIBC_HAS_UTMPX=y
+
+#
+# Library Installation Options
+#
+RUNTIME_PREFIX="/"
+DEVEL_PREFIX="/usr/"
+MULTILIB_DIR="lib"
+HARDWIRED_ABSPATH=y
+
+#
+# Security options
+#
+UCLIBC_HAS_ARC4RANDOM=y
+# ARC4RANDOM_USES_NODEV is not set
+# UCLIBC_HAS_SSP is not set
+UCLIBC_BUILD_RELRO=y
+UCLIBC_BUILD_NOW=y
+UCLIBC_BUILD_NOEXECSTACK=y
+
+#
+# Development/debugging options
+#
+CROSS_COMPILER_PREFIX=""
+UCLIBC_EXTRA_CFLAGS=""
+DODEBUG=y
+# DOASSERTS is not set
+# SUPPORT_LD_DEBUG is not set
+# SUPPORT_LD_DEBUG_EARLY is not set
+# UCLIBC_MALLOC_DEBUGGING is not set
+# UCLIBC_HAS_BACKTRACE is not set
+WARNINGS="-Wall"
+EXTRA_WARNINGS=y
+# DOMULTI is not set
+# UCLIBC_MJN3_ONLY is not set

+ 4 - 0
toolchain/binutils/Makefile

@@ -40,6 +40,10 @@ endif
 
 $(WRKBUILD)/.headers:
 $(WRKBUILD)/.configured:
+ifeq ($(ADK_LINUX_XTENSA),y)
+	tar xf $(TOPDIR)/target/xtensa/overlay/xtensa_dc232b.tar \
+		--strip-components=1 -C $(WRKSRC) binutils
+endif
 	(cd $(WRKBUILD); \
 		$(WRKBUILD)/configure \
 		--prefix=$(TOOLCHAIN_DIR)/usr \

+ 9 - 2
toolchain/gcc/Makefile

@@ -10,6 +10,10 @@ ifeq ($(ADK_TARGET_LIB_MUSL),y)
 TARGET_CXXFLAGS:=	$(filter-out -fstack-protector-all,$(TARGET_CXXFLAGS))
 endif
 
+ifneq ($(ADK_LINUX_XTENSA),y)
+GCC_FINAL_CONFOPTS+=	--enable-cxx-flags='$(TARGET_CXXFLAGS)'
+endif
+
 GCC_CONFOPTS:=		--prefix=$(TOOLCHAIN_DIR)/usr \
 			--with-bugurl="http://www.openadk.org/" \
 			--build=$(GNU_HOST_NAME) \
@@ -131,6 +135,10 @@ GCC_BUILD_DIR_INITIAL:=	$(WRKBUILD)-initial
 GCC_BUILD_DIR_FINAL:=	$(WRKBUILD)-final
 
 $(GCC_BUILD_DIR_MINIMAL)/.configured:
+ifeq ($(ADK_LINUX_XTENSA),y)
+	tar xf $(TOPDIR)/target/xtensa/overlay/xtensa_dc232b.tar \
+		--strip-components=1 -C $(WRKSRC) gcc
+endif
 	mkdir -p $(GCC_BUILD_DIR_MINIMAL)
 	# these symlinks are very important, do not remove
 	rm -rf $(TOOLCHAIN_DIR)/usr/$(GNU_TARGET_NAME)/sys-include
@@ -198,8 +206,7 @@ $(GCC_BUILD_DIR_FINAL)/.configured:
 			--enable-languages=$(LANGUAGES) \
 			--with-build-sysroot='$${prefix}/${STAGING_HOST2TARGET}' \
 			--with-sysroot='$${prefix}/${STAGING_HOST2TARGET}' \
-			--enable-shared='libstdc++' \
-			--enable-cxx-flags='$(TARGET_CXXFLAGS)'
+			--enable-shared='libstdc++'
 	touch $@
 
 $(WRKBUILD)/.compiled: $(GCC_BUILD_DIR_FINAL)/.configured

+ 23 - 12
toolchain/gcc/patches/4.8.3/musl-stubs.patch

@@ -1,6 +1,6 @@
-diff -Nur gcc-4.8.2.orig/gcc/config/m68k/linux.h gcc-4.8.2/gcc/config/m68k/linux.h
---- gcc-4.8.2.orig/gcc/config/m68k/linux.h	2013-01-10 21:38:27.000000000 +0100
-+++ gcc-4.8.2/gcc/config/m68k/linux.h	2014-02-24 10:19:00.214399704 +0100
+diff -Nur gcc-4.8.3.orig/gcc/config/m68k/linux.h gcc-4.8.3/gcc/config/m68k/linux.h
+--- gcc-4.8.3.orig/gcc/config/m68k/linux.h	2013-01-10 21:38:27.000000000 +0100
++++ gcc-4.8.3/gcc/config/m68k/linux.h	2014-06-01 08:57:42.139913658 +0200
 @@ -72,6 +72,7 @@
     done.  */
  
@@ -9,9 +9,9 @@ diff -Nur gcc-4.8.2.orig/gcc/config/m68k/linux.h gcc-4.8.2/gcc/config/m68k/linux
  
  #undef LINK_SPEC
  #define LINK_SPEC "-m m68kelf %{shared} \
-diff -Nur gcc-4.8.2.orig/gcc/config/mips/linux64.h gcc-4.8.2/gcc/config/mips/linux64.h
---- gcc-4.8.2.orig/gcc/config/mips/linux64.h	2013-01-10 21:38:27.000000000 +0100
-+++ gcc-4.8.2/gcc/config/mips/linux64.h	2014-02-24 10:19:47.238583895 +0100
+diff -Nur gcc-4.8.3.orig/gcc/config/mips/linux64.h gcc-4.8.3/gcc/config/mips/linux64.h
+--- gcc-4.8.3.orig/gcc/config/mips/linux64.h	2013-01-10 21:38:27.000000000 +0100
++++ gcc-4.8.3/gcc/config/mips/linux64.h	2014-06-01 08:57:42.139913658 +0200
 @@ -27,6 +27,9 @@
  #define GLIBC_DYNAMIC_LINKERN32 "/lib32/ld.so.1"
  #define UCLIBC_DYNAMIC_LINKERN32 "/lib32/ld-uClibc.so.0"
@@ -23,9 +23,9 @@ diff -Nur gcc-4.8.2.orig/gcc/config/mips/linux64.h gcc-4.8.2/gcc/config/mips/lin
    CHOOSE_DYNAMIC_LINKER (GLIBC_DYNAMIC_LINKERN32, UCLIBC_DYNAMIC_LINKERN32, \
 -			 BIONIC_DYNAMIC_LINKERN32)
 +			 BIONIC_DYNAMIC_LINKERN32, MUSL_DYNAMIC_LINKERN32)
-diff -Nur gcc-4.8.2.orig/gcc/config/sparc/linux64.h gcc-4.8.2/gcc/config/sparc/linux64.h
---- gcc-4.8.2.orig/gcc/config/sparc/linux64.h	2013-01-10 21:38:27.000000000 +0100
-+++ gcc-4.8.2/gcc/config/sparc/linux64.h	2014-02-24 10:20:49.414827006 +0100
+diff -Nur gcc-4.8.3.orig/gcc/config/sparc/linux64.h gcc-4.8.3/gcc/config/sparc/linux64.h
+--- gcc-4.8.3.orig/gcc/config/sparc/linux64.h	2013-01-10 21:38:27.000000000 +0100
++++ gcc-4.8.3/gcc/config/sparc/linux64.h	2014-06-01 08:57:42.139913658 +0200
 @@ -94,6 +94,9 @@
  
  #define GLIBC_DYNAMIC_LINKER32 "/lib/ld-linux.so.2"
@@ -36,9 +36,9 @@ diff -Nur gcc-4.8.2.orig/gcc/config/sparc/linux64.h gcc-4.8.2/gcc/config/sparc/l
  
  #ifdef SPARC_BI_ARCH
  
-diff -Nur gcc-4.8.2.orig/gcc/config/sparc/linux.h gcc-4.8.2/gcc/config/sparc/linux.h
---- gcc-4.8.2.orig/gcc/config/sparc/linux.h	2013-01-10 21:38:27.000000000 +0100
-+++ gcc-4.8.2/gcc/config/sparc/linux.h	2014-02-24 10:21:14.342924339 +0100
+diff -Nur gcc-4.8.3.orig/gcc/config/sparc/linux.h gcc-4.8.3/gcc/config/sparc/linux.h
+--- gcc-4.8.3.orig/gcc/config/sparc/linux.h	2013-01-10 21:38:27.000000000 +0100
++++ gcc-4.8.3/gcc/config/sparc/linux.h	2014-06-01 08:57:42.139913658 +0200
 @@ -84,6 +84,7 @@
     done.  */
  
@@ -47,3 +47,14 @@ diff -Nur gcc-4.8.2.orig/gcc/config/sparc/linux.h gcc-4.8.2/gcc/config/sparc/lin
  
  #undef  LINK_SPEC
  #define LINK_SPEC "-m elf32_sparc %{shared:-shared} \
+diff -Nur gcc-4.8.3.orig/gcc/config/xtensa/linux.h gcc-4.8.3/gcc/config/xtensa/linux.h
+--- gcc-4.8.3.orig/gcc/config/xtensa/linux.h	2013-01-10 21:38:27.000000000 +0100
++++ gcc-4.8.3/gcc/config/xtensa/linux.h	2014-06-01 08:58:39.740070402 +0200
+@@ -45,6 +45,7 @@
+   %{mno-longcalls:--no-longcalls}"
+ 
+ #define GLIBC_DYNAMIC_LINKER "/lib/ld.so.1"
++#define MUSL_DYNAMIC_LINKER "/lib/ld-musl-xtensa.so.1"
+ 
+ #undef LINK_SPEC
+ #define LINK_SPEC \

+ 1 - 0
toolchain/uclibc/Makefile

@@ -9,6 +9,7 @@ include Makefile.inc
 include ${TOPDIR}/mk/buildhlp.mk
 
 TARGET_CFLAGS:=$(filter-out -flto,$(TARGET_CFLAGS))
+TARGET_CFLAGS:=$(filter-out -mtext-section-literals,$(TARGET_CFLAGS))
 
 ifeq (${ADK_MAKE_PARALLEL},y)
 UCLIBC_MAKEOPTS+=	-j${ADK_MAKE_JOBS}

+ 209 - 32
toolchain/uclibc/patches/uclibc-git-20140602.patch → toolchain/uclibc/patches/uclibc-git-20140613.patch

@@ -33284,8 +33284,16 @@ diff -Nur uClibc-0.9.33.2/ldso/ldso/arm/aeabi_read_tp.S uClibc-git/ldso/ldso/arm
  
 diff -Nur uClibc-0.9.33.2/ldso/ldso/arm/dl-startup.h uClibc-git/ldso/ldso/arm/dl-startup.h
 --- uClibc-0.9.33.2/ldso/ldso/arm/dl-startup.h	2012-05-15 09:20:09.000000000 +0200
-+++ uClibc-git/ldso/ldso/arm/dl-startup.h	2014-06-02 17:40:33.926711497 +0200
-@@ -14,6 +14,7 @@
++++ uClibc-git/ldso/ldso/arm/dl-startup.h	2014-06-13 18:29:20.810293291 +0200
+@@ -7,13 +7,14 @@
+  */
+ 
+ #include <features.h>
+-#include <bits/arm_asm.h>
++#include <bits/arm_bx.h>
+ 
+ #if !defined(__thumb__)
+ __asm__(
      "	.text\n"
      "	.globl	_start\n"
      "	.type	_start,%function\n"
@@ -33325,8 +33333,16 @@ diff -Nur uClibc-0.9.33.2/ldso/ldso/arm/elfinterp.c uClibc-git/ldso/ldso/arm/elf
  		{
 diff -Nur uClibc-0.9.33.2/ldso/ldso/arm/resolve.S uClibc-git/ldso/ldso/arm/resolve.S
 --- uClibc-0.9.33.2/ldso/ldso/arm/resolve.S	2012-05-15 09:20:09.000000000 +0200
-+++ uClibc-git/ldso/ldso/arm/resolve.S	2014-06-02 17:40:33.926711497 +0200
-@@ -101,7 +101,7 @@
++++ uClibc-git/ldso/ldso/arm/resolve.S	2014-06-13 18:29:20.834293397 +0200
+@@ -92,6 +92,7 @@
+ 
+ #include <sys/syscall.h>
+ #include <bits/arm_asm.h>
++#include <bits/arm_bx.h>
+ 
+ #include <features.h>
+ 
+@@ -101,7 +102,7 @@
  
   .text
   .align 4      @ 16 byte boundary and there are 32 bytes below (arm case)
@@ -47267,10 +47283,32 @@ diff -Nur uClibc-0.9.33.2/libc/string/arc/strlen.S uClibc-git/libc/string/arc/st
 +	sub_s.ne r1,r1,r1
 +END(strlen)
 +libc_hidden_def(strlen)
+diff -Nur uClibc-0.9.33.2/libc/string/arm/memcmp.S uClibc-git/libc/string/arm/memcmp.S
+--- uClibc-0.9.33.2/libc/string/arm/memcmp.S	2012-05-15 09:20:09.000000000 +0200
++++ uClibc-git/libc/string/arm/memcmp.S	2014-06-13 18:29:20.834293397 +0200
+@@ -31,6 +31,7 @@
+ 
+ #include <features.h>
+ #include <bits/arm_asm.h>
++#include <bits/arm_bx.h>
+ 
+ .text
+ .global memcmp
+diff -Nur uClibc-0.9.33.2/libc/string/arm/_memcpy.S uClibc-git/libc/string/arm/_memcpy.S
+--- uClibc-0.9.33.2/libc/string/arm/_memcpy.S	2012-05-15 09:20:09.000000000 +0200
++++ uClibc-git/libc/string/arm/_memcpy.S	2014-06-13 18:29:20.834293397 +0200
+@@ -40,6 +40,7 @@
+ #include <features.h>
+ #include <endian.h>
+ #include <bits/arm_asm.h>
++#include <bits/arm_bx.h>
+ 
+ #if !defined(THUMB1_ONLY)
+ /*
 diff -Nur uClibc-0.9.33.2/libc/string/arm/memset.S uClibc-git/libc/string/arm/memset.S
 --- uClibc-0.9.33.2/libc/string/arm/memset.S	2012-05-15 09:20:09.000000000 +0200
-+++ uClibc-git/libc/string/arm/memset.S	2014-06-02 17:40:34.182712914 +0200
-@@ -13,9 +13,8 @@
++++ uClibc-git/libc/string/arm/memset.S	2014-06-13 18:29:20.834293397 +0200
+@@ -13,13 +13,13 @@
     Lesser General Public License for more details.
  
     You should have received a copy of the GNU Lesser General Public
@@ -47282,10 +47320,26 @@ diff -Nur uClibc-0.9.33.2/libc/string/arm/memset.S uClibc-git/libc/string/arm/me
  
  #include <features.h>
  #include <sys/syscall.h>
+ #include <bits/arm_asm.h>
++#include <bits/arm_bx.h>
+ 
+ .text
+ .global memset
+diff -Nur uClibc-0.9.33.2/libc/string/arm/strcmp.S uClibc-git/libc/string/arm/strcmp.S
+--- uClibc-0.9.33.2/libc/string/arm/strcmp.S	2012-05-15 09:20:09.000000000 +0200
++++ uClibc-git/libc/string/arm/strcmp.S	2014-06-13 18:29:20.838293415 +0200
+@@ -31,6 +31,7 @@
+ 
+ #include <features.h>
+ #include <bits/arm_asm.h>
++#include <bits/arm_bx.h>
+ 
+ .text
+ .global strcmp
 diff -Nur uClibc-0.9.33.2/libc/string/arm/strlen.S uClibc-git/libc/string/arm/strlen.S
 --- uClibc-0.9.33.2/libc/string/arm/strlen.S	2012-05-15 09:20:09.000000000 +0200
-+++ uClibc-git/libc/string/arm/strlen.S	2014-06-02 17:40:34.182712914 +0200
-@@ -13,9 +13,8 @@
++++ uClibc-git/libc/string/arm/strlen.S	2014-06-13 18:29:20.838293415 +0200
+@@ -13,14 +13,14 @@
     Lesser General Public License for more details.
  
     You should have received a copy of the GNU Lesser General Public
@@ -47297,6 +47351,12 @@ diff -Nur uClibc-0.9.33.2/libc/string/arm/strlen.S uClibc-git/libc/string/arm/st
  
  #include <features.h>
  #include <endian.h>
+ #include <sys/syscall.h>
+ #include <bits/arm_asm.h>
++#include <bits/arm_bx.h>
+ 
+ /* size_t strlen(const char *S)
+  * entry: r0 -> string
 diff -Nur uClibc-0.9.33.2/libc/string/avr32/Makefile uClibc-git/libc/string/avr32/Makefile
 --- uClibc-0.9.33.2/libc/string/avr32/Makefile	2012-05-15 09:20:09.000000000 +0200
 +++ uClibc-git/libc/string/avr32/Makefile	2014-06-02 17:40:34.182712914 +0200
@@ -53640,7 +53700,7 @@ diff -Nur uClibc-0.9.33.2/libc/sysdeps/linux/arm/aeabi_unwind_cpp_pr1.c uClibc-g
     -fexceptions, we end up with references to this personality
 diff -Nur uClibc-0.9.33.2/libc/sysdeps/linux/arm/bits/arm_asm.h uClibc-git/libc/sysdeps/linux/arm/bits/arm_asm.h
 --- uClibc-0.9.33.2/libc/sysdeps/linux/arm/bits/arm_asm.h	2012-05-15 09:20:09.000000000 +0200
-+++ uClibc-git/libc/sysdeps/linux/arm/bits/arm_asm.h	2014-06-02 17:40:34.282713468 +0200
++++ uClibc-git/libc/sysdeps/linux/arm/bits/arm_asm.h	2014-06-13 18:29:20.838293415 +0200
 @@ -3,8 +3,10 @@
  #define _ARM_ASM_H
  
@@ -53652,6 +53712,57 @@ diff -Nur uClibc-0.9.33.2/libc/sysdeps/linux/arm/bits/arm_asm.h uClibc-git/libc/
  #define IT(t, cond) i##t cond
  #else
  /* XXX: This can be removed if/when we require an assembler that supports
+@@ -24,12 +26,4 @@
+ #define THUMB1_ONLY 1
+ #endif
+ 
+-#if defined(__USE_BX__)
+-# if (   defined (__ARM_ARCH_2__)  || defined (__ARM_ARCH_3__) \
+-      || defined (__ARM_ARCH_3M__) || defined (__ARM_ARCH_4__) \
+-     )
+-#  error Use of BX was requested, but is not available on the target processor.
+-# endif /* ARCH level */
+-#endif /* __USE_BX__ */
+-
+ #endif /* _ARM_ASM_H */
+diff -Nur uClibc-0.9.33.2/libc/sysdeps/linux/arm/bits/arm_bx.h uClibc-git/libc/sysdeps/linux/arm/bits/arm_bx.h
+--- uClibc-0.9.33.2/libc/sysdeps/linux/arm/bits/arm_bx.h	1970-01-01 01:00:00.000000000 +0100
++++ uClibc-git/libc/sysdeps/linux/arm/bits/arm_bx.h	2014-06-13 18:29:20.838293415 +0200
+@@ -0,0 +1,34 @@
++/* Copyright (C) 2013 Yann E. MORIN <yann.morin.1998@free.fr>
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with the GNU C Library; if not, see
++ * <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef _ARM_BX_H
++#define _ARM_BX_H
++
++/* We need features.h first */
++#if !defined _FEATURES_H
++#error Please include features.h first
++#endif /* features.h not yet included */
++
++#if defined(__USE_BX__)
++# if (   defined (__ARM_ARCH_2__)  || defined (__ARM_ARCH_3__) \
++      || defined (__ARM_ARCH_3M__) || defined (__ARM_ARCH_4__) \
++     )
++#  error Use of BX was requested, but is not available on the target processor.
++# endif /* ARCH level */
++#endif /* __USE_BX__ */
++
++#endif /* _ARM_BX_H */
 diff -Nur uClibc-0.9.33.2/libc/sysdeps/linux/arm/bits/armsigctx.h uClibc-git/libc/sysdeps/linux/arm/bits/armsigctx.h
 --- uClibc-0.9.33.2/libc/sysdeps/linux/arm/bits/armsigctx.h	2012-05-15 09:20:09.000000000 +0200
 +++ uClibc-git/libc/sysdeps/linux/arm/bits/armsigctx.h	2014-06-02 17:40:34.282713468 +0200
@@ -53947,7 +54058,7 @@ diff -Nur uClibc-0.9.33.2/libc/sysdeps/linux/arm/bsd-_setjmp.S uClibc-git/libc/s
  
 diff -Nur uClibc-0.9.33.2/libc/sysdeps/linux/arm/clone.S uClibc-git/libc/sysdeps/linux/arm/clone.S
 --- uClibc-0.9.33.2/libc/sysdeps/linux/arm/clone.S	2012-05-15 09:20:09.000000000 +0200
-+++ uClibc-git/libc/sysdeps/linux/arm/clone.S	2014-06-02 17:40:34.306713601 +0200
++++ uClibc-git/libc/sysdeps/linux/arm/clone.S	2014-06-13 18:29:20.838293415 +0200
 @@ -13,9 +13,8 @@
     Lesser General Public License for more details.
  
@@ -53960,11 +54071,20 @@ diff -Nur uClibc-0.9.33.2/libc/sysdeps/linux/arm/clone.S uClibc-git/libc/sysdeps
  
  /* clone() is even more special than fork() as it mucks with stacks
     and invokes a function in the right context after its all over.  */
-@@ -111,8 +110,8 @@
+@@ -25,6 +24,7 @@
+ #include <bits/errno.h>
+ #include <sys/syscall.h>
+ #include <bits/arm_asm.h>
++#include <bits/arm_bx.h>
+ 
+ #if defined(__NR_clone)
+ /* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg); */
+@@ -111,8 +111,9 @@
  	ldr	r4, [sp, #12]
  	DO_CALL (clone)
  	movs	a1, a1
 -	blt	__error
++	IT(t, ne)
  	ldmnefd	sp!, {r4}
 +	blt	__error
  	IT(t, ne)
@@ -54191,8 +54311,8 @@ diff -Nur uClibc-0.9.33.2/libc/sysdeps/linux/arm/jmpbuf-unwind.h uClibc-git/libc
 +#endif
 diff -Nur uClibc-0.9.33.2/libc/sysdeps/linux/arm/__longjmp.S uClibc-git/libc/sysdeps/linux/arm/__longjmp.S
 --- uClibc-0.9.33.2/libc/sysdeps/linux/arm/__longjmp.S	2012-05-15 09:20:09.000000000 +0200
-+++ uClibc-git/libc/sysdeps/linux/arm/__longjmp.S	2014-06-02 17:40:34.266713379 +0200
-@@ -13,16 +13,11 @@
++++ uClibc-git/libc/sysdeps/linux/arm/__longjmp.S	2014-06-13 18:29:20.838293415 +0200
+@@ -13,16 +13,12 @@
     Lesser General Public License for more details.
  
     You should have received a copy of the GNU Lesser General Public
@@ -54208,6 +54328,7 @@ diff -Nur uClibc-0.9.33.2/libc/sysdeps/linux/arm/__longjmp.S uClibc-git/libc/sys
 -#define _ASM
 -#include <bits/setjmp.h>
 -
++#include <bits/arm_bx.h>
  
  .global __longjmp
  .type __longjmp,%function
@@ -54362,8 +54483,8 @@ diff -Nur uClibc-0.9.33.2/libc/sysdeps/linux/arm/Makefile.arch uClibc-git/libc/s
 +	)
 diff -Nur uClibc-0.9.33.2/libc/sysdeps/linux/arm/mmap64.S uClibc-git/libc/sysdeps/linux/arm/mmap64.S
 --- uClibc-0.9.33.2/libc/sysdeps/linux/arm/mmap64.S	2012-05-15 09:20:09.000000000 +0200
-+++ uClibc-git/libc/sysdeps/linux/arm/mmap64.S	2014-06-02 17:40:34.306713601 +0200
-@@ -12,17 +12,16 @@
++++ uClibc-git/libc/sysdeps/linux/arm/mmap64.S	2014-06-13 18:29:20.838293415 +0200
+@@ -12,17 +12,17 @@
     Lesser General Public License for more details.
  
     You should have received a copy of the GNU Lesser General Public
@@ -54379,6 +54500,7 @@ diff -Nur uClibc-0.9.33.2/libc/sysdeps/linux/arm/mmap64.S uClibc-git/libc/sysdep
  #include <bits/errno.h>
  #include <sys/syscall.h>
  #include <bits/arm_asm.h>
++#include <bits/arm_bx.h>
  
 -#if defined __UCLIBC_HAS_LFS__ && defined __NR_mmap2
 +#ifdef __NR_mmap2
@@ -54873,8 +54995,8 @@ diff -Nur uClibc-0.9.33.2/libc/sysdeps/linux/arm/sys/user.h uClibc-git/libc/sysd
  #define _SYS_USER_H	1
 diff -Nur uClibc-0.9.33.2/libc/sysdeps/linux/arm/syscall-eabi.S uClibc-git/libc/sysdeps/linux/arm/syscall-eabi.S
 --- uClibc-0.9.33.2/libc/sysdeps/linux/arm/syscall-eabi.S	2012-05-15 09:20:09.000000000 +0200
-+++ uClibc-git/libc/sysdeps/linux/arm/syscall-eabi.S	2014-06-02 17:40:34.310713623 +0200
-@@ -12,9 +12,8 @@
++++ uClibc-git/libc/sysdeps/linux/arm/syscall-eabi.S	2014-06-13 18:29:20.838293415 +0200
+@@ -12,12 +12,12 @@
     Lesser General Public License for more details.
  
     You should have received a copy of the GNU Lesser General Public
@@ -54886,10 +55008,14 @@ diff -Nur uClibc-0.9.33.2/libc/sysdeps/linux/arm/syscall-eabi.S uClibc-git/libc/
  
  #include <sys/syscall.h>
  #include <bits/arm_asm.h>
++#include <bits/arm_bx.h>
+ 
+ /* In the EABI syscall interface, we don't need a special syscall to
+    implement syscall().  It won't work reliably with 64-bit arguments
 diff -Nur uClibc-0.9.33.2/libc/sysdeps/linux/arm/sysdep.h uClibc-git/libc/sysdeps/linux/arm/sysdep.h
 --- uClibc-0.9.33.2/libc/sysdeps/linux/arm/sysdep.h	2012-05-15 09:20:09.000000000 +0200
-+++ uClibc-git/libc/sysdeps/linux/arm/sysdep.h	2014-06-02 17:40:34.310713623 +0200
-@@ -13,9 +13,8 @@
++++ uClibc-git/libc/sysdeps/linux/arm/sysdep.h	2014-06-13 18:29:20.838293415 +0200
+@@ -13,15 +13,14 @@
     Lesser General Public License for more details.
  
     You should have received a copy of the GNU Lesser General Public
@@ -54901,6 +55027,13 @@ diff -Nur uClibc-0.9.33.2/libc/sysdeps/linux/arm/sysdep.h uClibc-git/libc/sysdep
  
  #ifndef _LINUX_ARM_SYSDEP_H
  #define _LINUX_ARM_SYSDEP_H 1
+ 
+ #include <common/sysdep.h>
+-#include <bits/arm_asm.h>
++#include <bits/arm_bx.h>
+ 
+ #include <sys/syscall.h>
+ /* For Linux we can use the system call table in the header file
 @@ -157,6 +156,7 @@
  #define	PSEUDO_END_ERRVAL(name) \
    END (name)
@@ -54969,8 +55102,16 @@ diff -Nur uClibc-0.9.33.2/libc/sysdeps/linux/arm/unwind.h uClibc-git/libc/sysdep
     ABI defined objects, and GNU support routines.  */
 diff -Nur uClibc-0.9.33.2/libc/sysdeps/linux/arm/vfork.S uClibc-git/libc/sysdeps/linux/arm/vfork.S
 --- uClibc-0.9.33.2/libc/sysdeps/linux/arm/vfork.S	2012-05-15 09:20:09.000000000 +0200
-+++ uClibc-git/libc/sysdeps/linux/arm/vfork.S	2014-06-02 17:40:34.310713623 +0200
-@@ -104,5 +104,5 @@
++++ uClibc-git/libc/sysdeps/linux/arm/vfork.S	2014-06-13 18:29:20.838293415 +0200
+@@ -7,6 +7,7 @@
+ 
+ #include <features.h>
+ #include <bits/arm_asm.h>
++#include <bits/arm_bx.h>
+ 
+ #define _ERRNO_H
+ #include <bits/errno.h>
+@@ -104,5 +105,5 @@
  .size __vfork,.-__vfork
  
  weak_alias(__vfork,vfork)
@@ -83209,7 +83350,7 @@ diff -Nur uClibc-0.9.33.2/libc/sysdeps/linux/x86_64/setjmp.S uClibc-git/libc/sys
  .type   __sigsetjmp,%function
 diff -Nur uClibc-0.9.33.2/libc/sysdeps/linux/x86_64/sigaction.c uClibc-git/libc/sysdeps/linux/x86_64/sigaction.c
 --- uClibc-0.9.33.2/libc/sysdeps/linux/x86_64/sigaction.c	2012-05-15 09:20:09.000000000 +0200
-+++ uClibc-git/libc/sysdeps/linux/x86_64/sigaction.c	2014-06-02 17:40:34.686715704 +0200
++++ uClibc-git/libc/sysdeps/linux/x86_64/sigaction.c	2014-06-13 18:29:20.838293415 +0200
 @@ -13,9 +13,8 @@
     Lesser General Public License for more details.
  
@@ -83232,6 +83373,27 @@ diff -Nur uClibc-0.9.33.2/libc/sysdeps/linux/x86_64/sigaction.c uClibc-git/libc/
  #ifdef __NR_rt_sigaction
  
  /* Using the hidden attribute here does not change the code but it
+@@ -115,11 +111,19 @@
+    signal handlers work right.  Important are both the names
+    (__restore_rt) and the exact instruction sequence.
+    If you ever feel the need to make any changes, please notify the
+-   appropriate GDB maintainer.  */
++   appropriate GDB maintainer.
++
++   The unwind information starts a byte before __restore_rt, so that
++   it is found when unwinding, to get an address the unwinder assumes
++   will be in the middle of a call instruction.  See the Linux kernel
++   (the i386 vsyscall, in particular) for an explanation of the complex
++   unwind information used here in order to get the traditional CFA.
++ */
+ 
+ #define RESTORE(name, syscall) RESTORE2(name, syscall)
+ #define RESTORE2(name, syscall) \
+ __asm__ (						\
++	"nop\n"						\
+ 	".text\n"					\
+ 	"__" #name ":\n"				\
+ 	"	movq	$" #syscall ", %rax\n"		\
 diff -Nur uClibc-0.9.33.2/libc/sysdeps/linux/x86_64/__start_context.S uClibc-git/libc/sysdeps/linux/x86_64/__start_context.S
 --- uClibc-0.9.33.2/libc/sysdeps/linux/x86_64/__start_context.S	1970-01-01 01:00:00.000000000 +0100
 +++ uClibc-git/libc/sysdeps/linux/x86_64/__start_context.S	2014-06-02 17:40:34.682715682 +0200
@@ -101011,7 +101173,7 @@ diff -Nur uClibc-0.9.33.2/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthr
  #include <lowlevellock.h>
 diff -Nur uClibc-0.9.33.2/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S uClibc-git/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S
 --- uClibc-0.9.33.2/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S	2012-05-15 09:20:09.000000000 +0200
-+++ uClibc-git/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S	2014-06-02 17:40:35.098717984 +0200
++++ uClibc-git/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S	2014-06-13 18:29:20.838293415 +0200
 @@ -13,9 +13,8 @@
     Lesser General Public License for more details.
  
@@ -101024,6 +101186,14 @@ diff -Nur uClibc-0.9.33.2/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthr
  
  #include <sysdep.h>
  #include <lowlevellock.h>
+@@ -23,6 +22,7 @@
+ #include <pthread-errnos.h>
+ #include <pthread-pi-defines.h>
+ #include <bits/kernel-features.h>
++#include <tcb-offsets.h>
+ 
+ 
+ 	.text
 diff -Nur uClibc-0.9.33.2/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S uClibc-git/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S
 --- uClibc-0.9.33.2/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S	2012-05-15 09:20:09.000000000 +0200
 +++ uClibc-git/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S	2014-06-02 17:40:35.098717984 +0200
@@ -107277,7 +107447,7 @@ diff -Nur uClibc-0.9.33.2/Makefile.help uClibc-git/Makefile.help
  	@echo '  PREFIX=		- Prepended prefix'
 diff -Nur uClibc-0.9.33.2/Makefile.in uClibc-git/Makefile.in
 --- uClibc-0.9.33.2/Makefile.in	2012-05-15 09:20:09.000000000 +0200
-+++ uClibc-git/Makefile.in	2014-06-02 17:40:33.670710081 +0200
++++ uClibc-git/Makefile.in	2014-06-13 18:29:20.642292552 +0200
 @@ -8,18 +8,8 @@
  #--------------------------------------------------------------
  # You shouldn't need to mess with anything beyond this point...
@@ -107439,7 +107609,7 @@ diff -Nur uClibc-0.9.33.2/Makefile.in uClibc-git/Makefile.in
  	DEVEL_PREFIX=/usr/ \
  	HOSTCC="$(HOSTCC)" \
  	install
-@@ -210,16 +225,27 @@
+@@ -210,21 +225,34 @@
  # a "y" here means the feature is enabled and so we should *not* rm it.
  # if the option expands to nothing though, we can punt the headers.
  HEADERS_RM- := \
@@ -107467,7 +107637,14 @@ diff -Nur uClibc-0.9.33.2/Makefile.in uClibc-git/Makefile.in
  	bits/uClibc_uintmaxtostr.h \
  	bits/uClibc_uwchar.h \
  	bits/uClibc_va_copy.h \
-@@ -259,18 +285,23 @@
+ 	bits/sigcontextinfo.h \
+ 	bits/stackinfo.h \
++	atomic.h \
++	bits/atomic.h \
+ 	tls.h \
+ 	rpc/des_crypt.h \
+ 	rpc/key_prot.h \
+@@ -259,18 +287,23 @@
  HEADERS_RM-$(UCLIBC_HAS_REGEX)               += regex.h regexp.h
  HEADERS_RM-$(UCLIBC_HAS_RPC)                 += rpc
  HEADERS_RM-$(UCLIBC_HAS_SHADOW)              += shadow.h
@@ -107493,7 +107670,7 @@ diff -Nur uClibc-0.9.33.2/Makefile.in uClibc-git/Makefile.in
  	bits/inotify.h \
  	sys/inotify.h \
  	sys/kdaemon.h \
-@@ -288,11 +319,13 @@
+@@ -288,11 +321,13 @@
  	sys/sysinfo.h \
  	bits/timerfd.h \
  	sys/timerfd.h \
@@ -107507,7 +107684,7 @@ diff -Nur uClibc-0.9.33.2/Makefile.in uClibc-git/Makefile.in
  
  ifneq ($(findstring install,$(MAKECMDGOALS)),)
  $(addprefix $(PREFIX)$(DEVEL_PREFIX),include $(MULTILIB_DIR)):
-@@ -303,7 +336,9 @@
+@@ -303,7 +338,9 @@
  	$(do_mkdir)
  endif
  endif
@@ -107518,7 +107695,7 @@ diff -Nur uClibc-0.9.33.2/Makefile.in uClibc-git/Makefile.in
  	@$(call disp_install,"include -> $(PREFIX)$(DEVEL_PREFIX)include")
  	$(Q)top_builddir=$(top_builddir) \
  	$(top_srcdir)extra/scripts/install_headers.sh \
-@@ -346,12 +381,7 @@
+@@ -346,12 +383,7 @@
  else
  	-$(INSTALL) -m 755 $(top_builddir)lib/libc.so $(PREFIX)$(DEVEL_PREFIX)$(MULTILIB_DIR)/
  endif
@@ -107532,7 +107709,7 @@ diff -Nur uClibc-0.9.33.2/Makefile.in uClibc-git/Makefile.in
  ifeq ($(UCLIBC_HAS_THREADS),y)
  ifneq ($(LINUXTHREADS_OLD),y)
  ifeq ($(HARDWIRED_ABSPATH),y)
-@@ -422,49 +452,55 @@
+@@ -422,49 +454,55 @@
  install_hostutils: hostutils
  	$(Q)$(MAKE) CROSS_COMPILE="$(CROSS_COMPILE)" CC="$(CC)" HOSTCC="$(HOSTCC)" DOTHOST=.host -C utils utils_install
  
@@ -107611,7 +107788,7 @@ diff -Nur uClibc-0.9.33.2/Makefile.in uClibc-git/Makefile.in
  
  menuconfig-clean-y:
  	$(Q)$(MAKE) -C extra/config CLEAN_extra/config
-@@ -484,11 +520,11 @@
+@@ -484,11 +522,11 @@
  	$(Q)$(RM) $(top_builddir)extra/scripts/unifdef
  	$(Q)$(RM) -r $(LOCAL_INSTALL_PATH)
  
@@ -107626,7 +107803,7 @@ diff -Nur uClibc-0.9.33.2/Makefile.in uClibc-git/Makefile.in
  
  dist release:
  	$(RM) ../uClibc-$(VERSION).tar
-@@ -499,7 +535,9 @@
+@@ -499,7 +537,9 @@
  	du -b ../uClibc-$(VERSION).tar.{bz2,xz}
  
  test check: test_compile

+ 3515 - 0
toolchain/uclibc/patches/xxx-xtensa-nptl.patch

@@ -0,0 +1,3515 @@
+diff -Nur uClibc-git/include/elf.h uClibc-xtensa/include/elf.h
+--- uClibc-git/include/elf.h	2014-06-02 17:40:33.826710944 +0200
++++ uClibc-xtensa/include/elf.h	2014-06-03 16:03:19.065886532 +0200
+@@ -3072,8 +3071,11 @@
+ #define R_XTENSA_SLOT12_ALT	47
+ #define R_XTENSA_SLOT13_ALT	48
+ #define R_XTENSA_SLOT14_ALT	49
++#define R_XTENSA_TLSDESC_FN	50
++#define R_XTENSA_TLSDESC_ARG	51
++#define R_XTENSA_TLS_TPOFF	53
+ /* Keep this the last entry.  */
+-#define R_XTENSA_NUM		50
++#define R_XTENSA_NUM		54
+ 
+ /* C6X specific relocs */
+ #define R_C6000_NONE		0
+diff -Nur uClibc-git/include/link.h uClibc-xtensa/include/link.h
+--- uClibc-git/include/link.h	2014-06-02 17:40:33.846711055 +0200
++++ uClibc-xtensa/include/link.h	2014-06-03 15:28:27.185347373 +0200
+@@ -132,6 +132,8 @@
+     size_t l_tls_modid;
+     /* Nonzero if _dl_init_static_tls should be called for this module */
+     unsigned int l_need_tls_init:1;
++    /* Address of TLS descriptor hash table.  */
++    void *l_tlsdesc_table;
+ #endif
+ #endif
+   };
+diff -Nur uClibc-git/ldso/include/dl-hash.h uClibc-xtensa/ldso/include/dl-hash.h
+--- uClibc-git/ldso/include/dl-hash.h	2014-06-02 17:40:33.902711365 +0200
++++ uClibc-xtensa/ldso/include/dl-hash.h	2014-06-03 15:29:09.505536959 +0200
+@@ -70,6 +70,8 @@
+   size_t l_tls_modid;
+   /* Nonzero if _dl_init_static_tls should be called for this module */
+   unsigned int l_need_tls_init:1;
++  /* Address of TLS descriptor hash table.  */
++  void *l_tlsdesc_table;
+ #endif
+ 
+   ElfW(Addr) mapaddr;
+diff -Nur uClibc-git/ldso/include/inline-hashtab.h uClibc-xtensa/ldso/include/inline-hashtab.h
+--- uClibc-git/ldso/include/inline-hashtab.h	1970-01-01 01:00:00.000000000 +0100
++++ uClibc-xtensa/ldso/include/inline-hashtab.h	2014-06-03 11:57:42.031052092 +0200
+@@ -0,0 +1,265 @@
++/*
++ * The hashcode handling code below is heavily inspired in libiberty's
++ * hashtab code, but with most adaptation points and support for
++ * deleting elements removed.
++ *
++ * Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
++ * Contributed by Vladimir Makarov (vmakarov@cygnus.com).
++ */
++
++#ifndef INLINE_HASHTAB_H
++# define INLINE_HASHTAB_H 1
++
++static __always_inline unsigned long
++higher_prime_number(unsigned long n)
++{
++	/* These are primes that are near, but slightly smaller than, a power of two. */
++	static const unsigned long primes[] = {
++		7,
++		13,
++		31,
++		61,
++		127,
++		251,
++		509,
++		1021,
++		2039,
++		4093,
++		8191,
++		16381,
++		32749,
++		65521,
++		131071,
++		262139,
++		524287,
++		1048573,
++		2097143,
++		4194301,
++		8388593,
++		16777213,
++		33554393,
++		67108859,
++		134217689,
++		268435399,
++		536870909,
++		1073741789,
++		/* 4294967291 */
++		((unsigned long) 2147483647) + ((unsigned long) 2147483644),
++	};
++	const unsigned long *low = &primes[0];
++	const unsigned long *high = &primes[ARRAY_SIZE(primes)];
++
++	while (low != high) {
++		const unsigned long *mid = low + (high - low) / 2;
++		if (n > *mid)
++			low = mid + 1;
++		else
++			high = mid;
++	}
++
++#if 0
++	/* If we've run out of primes, abort.  */
++	if (n > *low) {
++		fprintf(stderr, "Cannot find prime bigger than %lu\n", n);
++		abort();
++	}
++#endif
++
++	return *low;
++}
++
++struct funcdesc_ht
++{
++	/* Table itself */
++	void **entries;
++
++	/* Current size (in entries) of the hash table */
++	size_t size;
++
++	/* Current number of elements */
++	size_t n_elements;
++};
++
++static __always_inline struct funcdesc_ht *
++htab_create(void)
++{
++	struct funcdesc_ht *ht = _dl_malloc(sizeof(*ht));
++	size_t ent_size;
++
++	if (!ht)
++		return NULL;
++	ht->size = 3;
++	ent_size = sizeof(void *) * ht->size;
++	ht->entries = _dl_malloc(ent_size);
++	if (!ht->entries)
++		return NULL;
++
++	ht->n_elements = 0;
++	_dl_memset(ht->entries, 0, ent_size);
++
++	return ht;
++}
++
++/*
++ * This is only called from _dl_loadaddr_unmap, so it's safe to call
++ * _dl_free().  See the discussion below.
++ */
++static __always_inline void
++htab_delete(struct funcdesc_ht *htab)
++{
++	size_t i;
++
++	for (i = htab->size - 1; i >= 0; i--)
++		if (htab->entries[i])
++			_dl_free(htab->entries[i]);
++
++	_dl_free(htab->entries);
++	_dl_free(htab);
++}
++
++/*
++ * Similar to htab_find_slot, but without several unwanted side effects:
++ *  - Does not call htab->eq_f when it finds an existing entry.
++ *  - Does not change the count of elements/searches/collisions in the
++ *    hash table.
++ * This function also assumes there are no deleted entries in the table.
++ * HASH is the hash value for the element to be inserted.
++ */
++static __always_inline void **
++find_empty_slot_for_expand(struct funcdesc_ht *htab, int hash)
++{
++	size_t size = htab->size;
++	unsigned int index = hash % size;
++	void **slot = htab->entries + index;
++	int hash2;
++
++	if (!*slot)
++		return slot;
++
++	hash2 = 1 + hash % (size - 2);
++	for (;;) {
++		index += hash2;
++		if (index >= size)
++			index -= size;
++
++		slot = htab->entries + index;
++		if (!*slot)
++			return slot;
++	}
++}
++
++/*
++ * The following function changes size of memory allocated for the
++ * entries and repeatedly inserts the table elements.  The occupancy
++ * of the table after the call will be about 50%.  Naturally the hash
++ * table must already exist.  Remember also that the place of the
++ * table entries is changed.  If memory allocation failures are allowed,
++ * this function will return zero, indicating that the table could not be
++ * expanded.  If all goes well, it will return a non-zero value.
++ */
++static __always_inline int
++htab_expand(struct funcdesc_ht *htab, int (*hash_fn) (void *))
++{
++	void **oentries;
++	void **olimit;
++	void **p;
++	void **nentries;
++	size_t nsize;
++
++	oentries = htab->entries;
++	olimit = oentries + htab->size;
++
++	/*
++	 * Resize only when table after removal of unused elements is either
++	 * too full or too empty.
++	 */
++	if (htab->n_elements * 2 > htab->size)
++		nsize = higher_prime_number(htab->n_elements * 2);
++	else
++		nsize = htab->size;
++
++	nentries = _dl_malloc(sizeof(*nentries) * nsize);
++	_dl_memset(nentries, 0, sizeof(*nentries) * nsize);
++	if (nentries == NULL)
++		return 0;
++	htab->entries = nentries;
++	htab->size = nsize;
++
++	p = oentries;
++	do {
++		if (*p)
++			*find_empty_slot_for_expand(htab, hash_fn(*p)) = *p;
++		p++;
++	} while (p < olimit);
++
++#if 0
++	/*
++	 * We can't tell whether this was allocated by the _dl_malloc()
++	 * built into ld.so or malloc() in the main executable or libc,
++	 * and calling free() for something that wasn't malloc()ed could
++	 * do Very Bad Things (TM).  Take the conservative approach
++	 * here, potentially wasting as much memory as actually used by
++	 * the hash table, even if multiple growths occur.  That's not
++	 * so bad as to require some overengineered solution that would
++	 * enable us to keep track of how it was allocated.
++	 */
++	_dl_free(oentries);
++#endif
++	return 1;
++}
++
++/*
++ * This function searches for a hash table slot containing an entry
++ * equal to the given element.  To delete an entry, call this with
++ * INSERT = 0, then call htab_clear_slot on the slot returned (possibly
++ * after doing some checks).  To insert an entry, call this with
++ * INSERT = 1, then write the value you want into the returned slot.
++ * When inserting an entry, NULL may be returned if memory allocation
++ * fails.
++ */
++static __always_inline void **
++htab_find_slot(struct funcdesc_ht *htab, void *ptr, int insert,
++	       int (*hash_fn)(void *), int (*eq_fn)(void *, void *))
++{
++	unsigned int index;
++	int hash, hash2;
++	size_t size;
++	void **entry;
++
++	if (htab->size * 3 <= htab->n_elements * 4 &&
++	    htab_expand(htab, hash_fn) == 0)
++		return NULL;
++
++	hash = hash_fn(ptr);
++
++	size = htab->size;
++	index = hash % size;
++
++	entry = &htab->entries[index];
++	if (!*entry)
++		goto empty_entry;
++	else if (eq_fn(*entry, ptr))
++		return entry;
++
++	hash2 = 1 + hash % (size - 2);
++	for (;;) {
++		index += hash2;
++		if (index >= size)
++			index -= size;
++
++		entry = &htab->entries[index];
++		if (!*entry)
++			goto empty_entry;
++		else if (eq_fn(*entry, ptr))
++			return entry;
++	}
++
++ empty_entry:
++	if (!insert)
++		return NULL;
++
++	htab->n_elements++;
++	return entry;
++}
++
++#endif
+diff -Nur uClibc-git/ldso/include/ldsodefs.h uClibc-xtensa/ldso/include/ldsodefs.h
+--- uClibc-git/ldso/include/ldsodefs.h	2014-06-02 17:40:33.922711475 +0200
++++ uClibc-xtensa/ldso/include/ldsodefs.h	2014-06-03 16:10:51.175659505 +0200
+@@ -62,13 +62,18 @@
+ 
+ extern void _dl_allocate_static_tls (struct link_map *map)
+      internal_function attribute_hidden;
++extern int _dl_try_allocate_static_tls (struct link_map* map)
++     internal_function attribute_hidden;
+ 
+ /* Taken from glibc/elf/dl-reloc.c */
+ #define CHECK_STATIC_TLS(sym_map)											\
+ 	do {																	\
+-		if (unlikely((sym_map)->l_tls_offset == NO_TLS_OFFSET))	\
++		if (__builtin_expect ((sym_map)->l_tls_offset == NO_TLS_OFFSET, 0))	\
+ 			_dl_allocate_static_tls (sym_map);								\
+ 	} while (0)
++#define TRY_STATIC_TLS(sym_map)												\
++	(__builtin_expect ((sym_map)->l_tls_offset != NO_TLS_OFFSET, 1)			\
++		 || _dl_try_allocate_static_tls (sym_map) == 0)
+ 
+ /* These are internal entry points to the two halves of _dl_allocate_tls,
+    only used within rtld.c itself at startup time.  */
+diff -Nur uClibc-git/ldso/include/tlsdeschtab.h uClibc-xtensa/ldso/include/tlsdeschtab.h
+--- uClibc-git/ldso/include/tlsdeschtab.h	1970-01-01 01:00:00.000000000 +0100
++++ uClibc-xtensa/ldso/include/tlsdeschtab.h	2014-06-03 14:58:29.681335708 +0200
+@@ -0,0 +1,119 @@
++/* Hash table for TLS descriptors.
++   Copyright (C) 2005-2013 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++   Contributed by Alexandre Oliva  <aoliva@redhat.com>
++
++   uClibc port by Baruch Siach <baruch@tkos.co.il>
++
++   The GNU C Library is free software; you can redistribute it and/or
++   modify it under the terms of the GNU Lesser General Public
++   License as published by the Free Software Foundation; either
++   version 2.1 of the License, or (at your option) any later version.
++
++   The GNU C Library is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++   Lesser General Public License for more details.
++
++   You should have received a copy of the GNU Lesser General Public
++   License along with the GNU C Library; if not, see
++   <http://www.gnu.org/licenses/>.  */
++
++#ifndef TLSDESCHTAB_H
++# define TLSDESCHTAB_H 1
++
++# ifdef SHARED
++
++#  include <inline-hashtab.h>
++
++inline static int
++hash_tlsdesc (void *p)
++{
++  struct tlsdesc_dynamic_arg *td = p;
++
++  /* We know all entries are for the same module, so ti_offset is the
++     only distinguishing entry.  */
++  return td->tlsinfo.ti_offset;
++}
++
++inline static int
++eq_tlsdesc (void *p, void *q)
++{
++  struct tlsdesc_dynamic_arg *tdp = p, *tdq = q;
++
++  return tdp->tlsinfo.ti_offset == tdq->tlsinfo.ti_offset;
++}
++
++inline static int
++map_generation (struct link_map *map)
++{
++  size_t idx = map->l_tls_modid;
++  struct dtv_slotinfo_list *listp = GL(dl_tls_dtv_slotinfo_list);
++
++  /* Find the place in the dtv slotinfo list.  */
++  do
++    {
++      /* Does it fit in the array of this list element?  */
++      if (idx < listp->len)
++	{
++	  /* We should never get here for a module in static TLS, so
++	     we can assume that, if the generation count is zero, we
++	     still haven't determined the generation count for this
++	     module.  */
++	  if (listp->slotinfo[idx].gen)
++	    return listp->slotinfo[idx].gen;
++	  else
++	    break;
++	}
++      idx -= listp->len;
++      listp = listp->next;
++    }
++  while (listp != NULL);
++
++  /* If we get to this point, the module still hasn't been assigned an
++     entry in the dtv slotinfo data structures, and it will when we're
++     done with relocations.  At that point, the module will get a
++     generation number that is one past the current generation, so
++     return exactly that.  */
++  return GL(dl_tls_generation) + 1;
++}
++
++void *
++internal_function
++_dl_make_tlsdesc_dynamic (struct link_map *map, size_t ti_offset)
++{
++  struct funcdesc_ht *ht;
++  void **entry;
++  struct tlsdesc_dynamic_arg *td, test;
++
++  ht = map->l_tlsdesc_table;
++  if (! ht)
++    {
++      ht = htab_create ();
++      if (! ht)
++	  return 0;
++      map->l_tlsdesc_table = ht;
++    }
++
++  test.tlsinfo.ti_module = map->l_tls_modid;
++  test.tlsinfo.ti_offset = ti_offset;
++  entry = htab_find_slot (ht, &test, 1, hash_tlsdesc, eq_tlsdesc);
++  if (*entry)
++    {
++      td = *entry;
++      return td;
++    }
++
++  *entry = td = _dl_malloc (sizeof (struct tlsdesc_dynamic_arg));
++  /* This may be higher than the map's generation, but it doesn't
++     matter much.  Worst case, we'll have one extra DTV update per
++     thread.  */
++  td->gen_count = map_generation (map);
++  td->tlsinfo = test.tlsinfo;
++
++  return td;
++}
++
++# endif /* SHARED */
++
++#endif
+diff -Nur uClibc-git/ldso/ldso/dl-tls.c uClibc-xtensa/ldso/ldso/dl-tls.c
+--- uClibc-git/ldso/ldso/dl-tls.c	2014-06-02 17:40:33.946711608 +0200
++++ uClibc-xtensa/ldso/ldso/dl-tls.c	2014-06-03 16:10:28.547570023 +0200
+@@ -100,20 +100,16 @@
+  * the static TLS area already allocated for each running thread.  If this
+  * object's TLS segment is too big to fit, we fail.  If it fits,
+  * we set MAP->l_tls_offset and return.
+- * This function intentionally does not return any value but signals error
+- * directly, as static TLS should be rare and code handling it should
+- * not be inlined as much as possible.
+  */
+-void
+-internal_function __attribute_noinline__
+-_dl_allocate_static_tls (struct link_map *map)
++int
++internal_function
++_dl_try_allocate_static_tls (struct link_map* map)
+ {
+ 	/* If the alignment requirements are too high fail.  */
+ 	if (map->l_tls_align > _dl_tls_static_align)
+ 	{
+ fail:
+-		_dl_dprintf(2, "cannot allocate memory in static TLS block");
+-		_dl_exit(30);
++		return -1;
+ 	}
+ 
+ # ifdef TLS_TCB_AT_TP
+@@ -169,6 +165,23 @@
+ 	}
+ 	else
+ 		map->l_need_tls_init = 1;
++
++	return 0;
++}
++
++/*
++ * This function intentionally does not return any value but signals error
++ * directly, as static TLS should be rare and code handling it should
++ * not be inlined as much as possible.
++ */
++void
++internal_function __attribute_noinline__
++_dl_allocate_static_tls (struct link_map *map)
++{
++	if (_dl_try_allocate_static_tls (map)) {
++		_dl_dprintf(2, "cannot allocate memory in static TLS block");
++		_dl_exit(30);
++	}
+ }
+ 
+ #ifdef SHARED
+diff -Nur uClibc-git/ldso/ldso/fdpic/dl-inlines.h uClibc-xtensa/ldso/ldso/fdpic/dl-inlines.h
+--- uClibc-git/ldso/ldso/fdpic/dl-inlines.h	2014-06-02 17:40:33.950711630 +0200
++++ uClibc-xtensa/ldso/ldso/fdpic/dl-inlines.h	2014-06-03 11:57:43.263058897 +0200
+@@ -5,6 +5,8 @@
+  * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+  */
+ 
++#include <inline-hashtab.h>
++
+ /* Initialize a DL_LOADADDR_TYPE given a got pointer and a complete load map. */
+ static __always_inline void
+ __dl_init_loadaddr_map(struct elf32_fdpic_loadaddr *loadaddr, Elf32_Addr dl_boot_got_pointer,
+@@ -143,269 +145,18 @@
+ 	return 0;
+ }
+ 
+-/*
+- * The hashcode handling code below is heavily inspired in libiberty's
+- * hashtab code, but with most adaptation points and support for
+- * deleting elements removed.
+- *
+- * Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+- * Contributed by Vladimir Makarov (vmakarov@cygnus.com).
+- */
+-static __always_inline unsigned long
+-higher_prime_number(unsigned long n)
+-{
+-	/* These are primes that are near, but slightly smaller than, a power of two. */
+-	static const unsigned long primes[] = {
+-		7,
+-		13,
+-		31,
+-		61,
+-		127,
+-		251,
+-		509,
+-		1021,
+-		2039,
+-		4093,
+-		8191,
+-		16381,
+-		32749,
+-		65521,
+-		131071,
+-		262139,
+-		524287,
+-		1048573,
+-		2097143,
+-		4194301,
+-		8388593,
+-		16777213,
+-		33554393,
+-		67108859,
+-		134217689,
+-		268435399,
+-		536870909,
+-		1073741789,
+-		/* 4294967291 */
+-		((unsigned long) 2147483647) + ((unsigned long) 2147483644),
+-	};
+-	const unsigned long *low = &primes[0];
+-	const unsigned long *high = &primes[ARRAY_SIZE(primes)];
+-
+-	while (low != high) {
+-		const unsigned long *mid = low + (high - low) / 2;
+-		if (n > *mid)
+-			low = mid + 1;
+-		else
+-			high = mid;
+-	}
+-
+-#if 0
+-	/* If we've run out of primes, abort.  */
+-	if (n > *low) {
+-		fprintf(stderr, "Cannot find prime bigger than %lu\n", n);
+-		abort();
+-	}
+-#endif
+-
+-	return *low;
+-}
+-
+-struct funcdesc_ht
+-{
+-	/* Table itself */
+-	struct funcdesc_value **entries;
+-
+-	/* Current size (in entries) of the hash table */
+-	size_t size;
+-
+-	/* Current number of elements */
+-	size_t n_elements;
+-};
+-
+-static __always_inline int
+-hash_pointer(const void *p)
++static int
++hash_pointer(void *p)
+ {
+ 	return (int) ((long)p >> 3);
+ }
+ 
+-static __always_inline struct funcdesc_ht *
+-htab_create(void)
+-{
+-	struct funcdesc_ht *ht = _dl_malloc(sizeof(*ht));
+-	size_t ent_size;
+-
+-	if (!ht)
+-		return NULL;
+-	ht->size = 3;
+-	ent_size = sizeof(struct funcdesc_ht_value *) * ht->size;
+-	ht->entries = _dl_malloc(ent_size);
+-	if (!ht->entries)
+-		return NULL;
+-
+-	ht->n_elements = 0;
+-	_dl_memset(ht->entries, 0, ent_size);
+-
+-	return ht;
+-}
+-
+-/*
+- * This is only called from _dl_loadaddr_unmap, so it's safe to call
+- * _dl_free().  See the discussion below.
+- */
+-static __always_inline void
+-htab_delete(struct funcdesc_ht *htab)
+-{
+-	size_t i;
+-
+-	for (i = htab->size - 1; i >= 0; i--)
+-		if (htab->entries[i])
+-			_dl_free(htab->entries[i]);
+-
+-	_dl_free(htab->entries);
+-	_dl_free(htab);
+-}
+-
+-/*
+- * Similar to htab_find_slot, but without several unwanted side effects:
+- *  - Does not call htab->eq_f when it finds an existing entry.
+- *  - Does not change the count of elements/searches/collisions in the
+- *    hash table.
+- * This function also assumes there are no deleted entries in the table.
+- * HASH is the hash value for the element to be inserted.
+- */
+-static __always_inline struct funcdesc_value **
+-find_empty_slot_for_expand(struct funcdesc_ht *htab, int hash)
++static int
++eq_pointer(void *p, void *q)
+ {
+-	size_t size = htab->size;
+-	unsigned int index = hash % size;
+-	struct funcdesc_value **slot = htab->entries + index;
+-	int hash2;
+-
+-	if (!*slot)
+-		return slot;
+-
+-	hash2 = 1 + hash % (size - 2);
+-	for (;;) {
+-		index += hash2;
+-		if (index >= size)
+-			index -= size;
+-
+-		slot = htab->entries + index;
+-		if (!*slot)
+-			return slot;
+-	}
+-}
+-
+-/*
+- * The following function changes size of memory allocated for the
+- * entries and repeatedly inserts the table elements.  The occupancy
+- * of the table after the call will be about 50%.  Naturally the hash
+- * table must already exist.  Remember also that the place of the
+- * table entries is changed.  If memory allocation failures are allowed,
+- * this function will return zero, indicating that the table could not be
+- * expanded.  If all goes well, it will return a non-zero value.
+- */
+-static __always_inline int
+-htab_expand(struct funcdesc_ht *htab)
+-{
+-	struct funcdesc_value **oentries;
+-	struct funcdesc_value **olimit;
+-	struct funcdesc_value **p;
+-	struct funcdesc_value **nentries;
+-	size_t nsize;
+-
+-	oentries = htab->entries;
+-	olimit = oentries + htab->size;
+-
+-	/*
+-	 * Resize only when table after removal of unused elements is either
+-	 * too full or too empty.
+-	 */
+-	if (htab->n_elements * 2 > htab->size)
+-		nsize = higher_prime_number(htab->n_elements * 2);
+-	else
+-		nsize = htab->size;
+-
+-	nentries = _dl_malloc(sizeof(*nentries) * nsize);
+-	_dl_memset(nentries, 0, sizeof(*nentries) * nsize);
+-	if (nentries == NULL)
+-		return 0;
+-	htab->entries = nentries;
+-	htab->size = nsize;
+-
+-	p = oentries;
+-	do {
+-		if (*p)
+-			*find_empty_slot_for_expand(htab, hash_pointer((*p)->entry_point)) = *p;
+-		p++;
+-	} while (p < olimit);
+-
+-#if 0
+-	/*
+-	 * We can't tell whether this was allocated by the _dl_malloc()
+-	 * built into ld.so or malloc() in the main executable or libc,
+-	 * and calling free() for something that wasn't malloc()ed could
+-	 * do Very Bad Things (TM).  Take the conservative approach
+-	 * here, potentially wasting as much memory as actually used by
+-	 * the hash table, even if multiple growths occur.  That's not
+-	 * so bad as to require some overengineered solution that would
+-	 * enable us to keep track of how it was allocated.
+-	 */
+-	_dl_free(oentries);
+-#endif
+-	return 1;
+-}
+-
+-/*
+- * This function searches for a hash table slot containing an entry
+- * equal to the given element.  To delete an entry, call this with
+- * INSERT = 0, then call htab_clear_slot on the slot returned (possibly
+- * after doing some checks).  To insert an entry, call this with
+- * INSERT = 1, then write the value you want into the returned slot.
+- * When inserting an entry, NULL may be returned if memory allocation
+- * fails.
+- */
+-static __always_inline struct funcdesc_value **
+-htab_find_slot(struct funcdesc_ht *htab, void *ptr, int insert)
+-{
+-	unsigned int index;
+-	int hash, hash2;
+-	size_t size;
+-	struct funcdesc_value **entry;
+-
+-	if (htab->size * 3 <= htab->n_elements * 4 &&
+-	    htab_expand(htab) == 0)
+-		return NULL;
+-
+-	hash = hash_pointer(ptr);
+-
+-	size = htab->size;
+-	index = hash % size;
+-
+-	entry = &htab->entries[index];
+-	if (!*entry)
+-		goto empty_entry;
+-	else if ((*entry)->entry_point == ptr)
+-		return entry;
+-
+-	hash2 = 1 + hash % (size - 2);
+-	for (;;) {
+-		index += hash2;
+-		if (index >= size)
+-			index -= size;
+-
+-		entry = &htab->entries[index];
+-		if (!*entry)
+-			goto empty_entry;
+-		else if ((*entry)->entry_point == ptr)
+-			return entry;
+-	}
+-
+- empty_entry:
+-	if (!insert)
+-		return NULL;
++	struct funcdesc_value *entry = p;
+ 
+-	htab->n_elements++;
+-	return entry;
++	return entry->entry_point == q;
+ }
+ 
+ void *
+@@ -424,7 +175,7 @@
+ 		tpnt->funcdesc_ht = ht;
+ 	}
+ 
+-	entry = htab_find_slot(ht, entry_point, 1);
++	entry = htab_find_slot(ht, entry_point, 1, hash_pointer, eq_pointer);
+ 	if (*entry) {
+ 		_dl_assert((*entry)->entry_point == entry_point);
+ 		return _dl_stabilize_funcdesc(*entry);
+@@ -459,7 +210,8 @@
+ 		if (fd->got_value != rpnt->loadaddr.got_value)
+ 			continue;
+ 
+-		address = htab_find_slot(rpnt->funcdesc_ht, (void *)fd->entry_point, 0);
++		address = htab_find_slot(rpnt->funcdesc_ht, (void *)fd->entry_point, 0,
++				hash_pointer, eq_pointer);
+ 
+ 		if (address && *(struct funcdesc_value *const*)address == fd) {
+ 			address = (*(struct funcdesc_value *const*)address)->entry_point;
+diff -Nur uClibc-git/ldso/ldso/xtensa/dl-debug.h uClibc-xtensa/ldso/ldso/xtensa/dl-debug.h
+--- uClibc-git/ldso/ldso/xtensa/dl-debug.h	2014-06-02 17:40:33.958711675 +0200
++++ uClibc-xtensa/ldso/ldso/xtensa/dl-debug.h	2014-06-03 12:22:20.032058866 +0200
+@@ -8,54 +8,31 @@
+ 
+ static const char * const _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"
++	 [0] "R_XTENSA_NONE",			"R_XTENSA_32",
++	 [2] "R_XTENSA_RTLD",			"R_XTENSA_GLOB_DAT",
++	 [4] "R_XTENSA_JMP_SLOT",		"R_XTENSA_RELATIVE",
++	 [6] "R_XTENSA_PLT",			"R_XTENSA_UNUSED7",
++	 [8] "R_XTENSA_OP0",			"R_XTENSA_OP1",
++	[10] "R_XTENSA_OP2",			"R_XTENSA_ASM_EXPAND",
++	[12] "R_XTENSA_ASM_SIMPLIFY",	"R_XTENSA_UNUSED13",
++	[14] "R_XTENSA_UNUSED14",		"R_XTENSA_GNU_VTINHERIT",
++	[16] "R_XTENSA_GNU_VTENTRY",	"R_XTENSA_DIFF8",
++	[18] "R_XTENSA_DIFF16",			"R_XTENSA_DIFF32",
++	[20] "R_XTENSA_SLOT0_OP",		"R_XTENSA_SLOT1_OP",
++	[22] "R_XTENSA_SLOT2_OP",		"R_XTENSA_SLOT3_OP",
++	[24] "R_XTENSA_SLOT4_OP",		"R_XTENSA_SLOT5_OP",
++	[26] "R_XTENSA_SLOT6_OP",		"R_XTENSA_SLOT7_OP",
++	[28] "R_XTENSA_SLOT8_OP",		"R_XTENSA_SLOT9_OP",
++	[30] "R_XTENSA_SLOT10_OP",		"R_XTENSA_SLOT11_OP",
++	[32] "R_XTENSA_SLOT12_OP",		"R_XTENSA_SLOT13_OP",
++	[34] "R_XTENSA_SLOT14_OP",		"R_XTENSA_SLOT0_ALT",
++	[36] "R_XTENSA_SLOT1_ALT",		"R_XTENSA_SLOT2_ALT",
++	[38] "R_XTENSA_SLOT3_ALT",		"R_XTENSA_SLOT4_ALT",
++	[40] "R_XTENSA_SLOT5_ALT",		"R_XTENSA_SLOT6_ALT",
++	[42] "R_XTENSA_SLOT7_ALT",		"R_XTENSA_SLOT8_ALT",
++	[44] "R_XTENSA_SLOT9_ALT",		"R_XTENSA_SLOT10_ALT",
++	[46] "R_XTENSA_SLOT11_ALT",		"R_XTENSA_SLOT12_ALT",
++	[48] "R_XTENSA_SLOT13_ALT",		"R_XTENSA_SLOT14_ALT",
++	[50] "R_XTENSA_TLSDESC_FN",		"R_XTENSA_TLSDESC_ARG",
++	[52] "R_XTENSA_TLS_TPOFF"
+ };
+diff -Nur uClibc-git/ldso/ldso/xtensa/dl-startup.h uClibc-xtensa/ldso/ldso/xtensa/dl-startup.h
+--- uClibc-git/ldso/ldso/xtensa/dl-startup.h	2014-06-02 17:40:33.958711675 +0200
++++ uClibc-xtensa/ldso/ldso/xtensa/dl-startup.h	2014-06-03 12:22:20.112059404 +0200
+@@ -11,7 +11,6 @@
+ __asm__ (
+     "	.text\n"
+     "	.align  4\n"
+-    "	.literal_position\n"
+     "	.global _start\n"
+     "	.type   _start, @function\n"
+     "	.hidden _start\n"
+diff -Nur uClibc-git/ldso/ldso/xtensa/dl-sysdep.h uClibc-xtensa/ldso/ldso/xtensa/dl-sysdep.h
+--- uClibc-git/ldso/ldso/xtensa/dl-sysdep.h	2014-06-02 17:40:33.958711675 +0200
++++ uClibc-xtensa/ldso/ldso/xtensa/dl-sysdep.h	2014-06-03 12:22:20.340060933 +0200
+@@ -78,10 +78,13 @@
+ struct elf_resolve;
+ extern unsigned long _dl_linux_resolver (struct elf_resolve *, int);
+ 
+-/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry, so
+-   undefined references should not be allowed to define the value.  */
++/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry or
++   TLS variable, 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)
++  (((type) == R_XTENSA_JMP_SLOT || (type) == R_XTENSA_TLS_TPOFF \
++   || (type) == R_XTENSA_TLSDESC_FN || (type) == R_XTENSA_TLSDESC_ARG) \
++   * ELF_RTYPE_CLASS_PLT)
+ 
+ /* Return the link-time address of _DYNAMIC.  */
+ static __always_inline Elf32_Addr
+diff -Nur uClibc-git/ldso/ldso/xtensa/dl-tlsdesc.S uClibc-xtensa/ldso/ldso/xtensa/dl-tlsdesc.S
+--- uClibc-git/ldso/ldso/xtensa/dl-tlsdesc.S	1970-01-01 01:00:00.000000000 +0100
++++ uClibc-xtensa/ldso/ldso/xtensa/dl-tlsdesc.S	2014-06-03 12:22:20.340060933 +0200
+@@ -0,0 +1,96 @@
++/* Thread-local storage handling in the ELF dynamic linker.  Xtensa version.
++   Copyright (C) 2012-2013 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++
++   The GNU C Library is free software; you can redistribute it and/or
++   modify it under the terms of the GNU Lesser General Public
++   License as published by the Free Software Foundation; either
++   version 2.1 of the License, or (at your option) any later version.
++
++   The GNU C Library is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++   Lesser General Public License for more details.
++
++   You should have received a copy of the GNU Lesser General Public
++   License along with the GNU C Library.  If not, see
++   <http://www.gnu.org/licenses/>.  */
++
++#include <sysdep.h>
++#include <tls.h>
++#include "tlsdesc.h"
++
++
++	.text
++	.align 4
++	.hidden _dl_tlsdesc_return
++	.global	_dl_tlsdesc_return
++	.type	_dl_tlsdesc_return, @function
++_dl_tlsdesc_return:
++	entry	a1, 16
++	rur.threadptr	a3
++	add		a2, a2, a3
++	retw
++	.size	_dl_tlsdesc_return, .-_dl_tlsdesc_return
++
++#ifdef SHARED
++
++
++	/* This function is used for symbols that need dynamic TLS.
++
++	   The argument passed to this function points to the TLS descriptor.
++
++	   The assembly code that follows is a rendition of the following
++	   C code, hand-optimized a little bit.
++
++	   ptrdiff_t
++	   _dl_tlsdesc_dynamic(struct tlsdesc_dynamic_arg *td)
++	   {
++	     dtv_t *dtv = (dtv_t *)THREAD_DTV();
++	     if (td->gen_count <= dtv[0].counter
++	         && dtv[td->tlsinfo.ti_module].pointer.val
++	            != TLS_DTV_UNALLOCATED)
++	       return dtv[td->tlsinfo.ti_module].pointer.val
++	              + td->tlsinfo.ti_offset - __builtin_thread_pointer();
++	     return __tls_get_addr (&td->tlsinfo) - __builtin_thread_pointer();
++	   }
++	 */
++
++	.align 4
++	.hidden _dl_tlsdesc_dynamic
++	.global	_dl_tlsdesc_dynamic
++	.type	_dl_tlsdesc_dynamic, @function
++_dl_tlsdesc_dynamic:
++	entry	a1, 32
++
++	/* dtv_t *dtv = (dtv_t *)THREAD_DTV(); */
++	rur.threadptr	a3
++	l32i	a4, a3, 0
++
++	/* if (td->gen_count <= dtv[0].counter */
++	l32i	a6, a2, TLSDESC_GEN_COUNT
++	l32i	a7, a4, 0
++	blt	a7, a6, .Lslow
++
++	/* && dtv[td->tlsinfo.ti_module].pointer.val != TLS_DTV_UNALLOCATED) */
++	l32i	a6, a2, TLSDESC_MODID
++	addx8	a6, a3, a6
++	l32i	a6, a6, 0
++	beqi	a6, -1, .Lslow
++
++	/* return dtv[td->tlsinfo.ti_module].pointer.val
++	     + td->tlsinfo.ti_offset - __builtin_thread_pointer(); */
++	l32i	a6, a2, TLSDESC_MODOFF
++	sub	a2, a6, a3
++	retw
++
++	/* return __tls_get_addr (&td->tlsinfo) - __builtin_thread_pointer(); */
++.Lslow:
++	mov	a10, a2
++	movi	a8, __tls_get_addr
++	callx8	a8
++	sub	a2, a10, a3
++	retw
++	.size	_dl_tlsdesc_dynamic, .-_dl_tlsdesc_dynamic
++
++#endif /* SHARED */
+diff -Nur uClibc-git/ldso/ldso/xtensa/elfinterp.c uClibc-xtensa/ldso/ldso/xtensa/elfinterp.c
+--- uClibc-git/ldso/ldso/xtensa/elfinterp.c	2014-06-02 17:40:33.958711675 +0200
++++ uClibc-xtensa/ldso/ldso/xtensa/elfinterp.c	2014-06-03 12:22:20.340060933 +0200
+@@ -31,6 +31,8 @@
+  */
+ 
+ #include "ldso.h"
++#include "dl-tls.h"
++#include "tlsdeschtab.h"
+ 
+ unsigned long
+ _dl_linux_resolver (struct elf_resolve *tpnt, int reloc_entry)
+@@ -146,6 +148,9 @@
+ 	int reloc_type;
+ 	int symtab_index;
+ 	char *symname;
++#if defined USE_TLS && USE_TLS
++	struct elf_resolve *tls_tpnt = NULL;
++#endif
+ 	struct symbol_ref sym_ref;
+ 	ElfW(Addr) *reloc_addr;
+ 	ElfW(Addr) symbol_addr;
+@@ -172,15 +177,22 @@
+ 		 * here, so all bases should be covered.
+ 		 */
+ 		if (unlikely (!symbol_addr &&
++					  ELF_ST_TYPE (sym_ref.sym->st_info) != STT_TLS &&
+ 					  ELF_ST_BIND (sym_ref.sym->st_info) != STB_WEAK)) {
+-			_dl_dprintf (2, "%s: can't resolve symbol '%s'\n",
+-						 _dl_progname, symname);
+-			_dl_exit (1);
++			return 1;
+ 		}
+ 		if (_dl_trace_prelink) {
+ 			_dl_debug_lookup (symname, tpnt, &symtab[symtab_index],
+ 						&sym_ref, elf_machine_type_class(reloc_type));
+ 		}
++#if defined USE_TLS && USE_TLS
++		tls_tpnt = sym_ref.tpnt;
++#endif
++	} else {
++		symbol_addr =symtab[symtab_index].st_value;
++#if defined USE_TLS && USE_TLS
++		tls_tpnt = tpnt;
++#endif
+ 	}
+ 
+ #if defined (__SUPPORT_LD_DEBUG__)
+@@ -198,8 +210,8 @@
+ 
+ 	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.  */
++			/* Grab the function pointer stashed at the beginning
++			   of the GOT by the GOT_INIT function.  */
+ 			*reloc_addr = *(ElfW(Addr) *) tpnt->dynamic_info[DT_PLTGOT];
+ 		} else if (rpnt->r_addend == 2) {
+ 			/* Store the link map for the object.  */
+@@ -213,6 +225,35 @@
+ 		*reloc_addr += tpnt->loadaddr + rpnt->r_addend;
+ 		break;
+ 
++#if defined USE_TLS && USE_TLS
++	case R_XTENSA_TLS_TPOFF:
++		CHECK_STATIC_TLS((struct link_map *) tls_tpnt);
++		*reloc_addr = symbol_addr + tls_tpnt->l_tls_offset + rpnt->r_addend;
++		break;
++	case R_XTENSA_TLSDESC_FN:
++#ifndef SHARED
++		CHECK_STATIC_TLS((struct link_map *) tls_tpnt);
++#else
++		if (!TRY_STATIC_TLS ((struct link_map *) tls_tpnt))
++			*reloc_addr = (ElfW(Addr)) _dl_tlsdesc_dynamic;
++		else
++#endif
++			*reloc_addr = (ElfW(Addr)) _dl_tlsdesc_return;
++		break;
++	case R_XTENSA_TLSDESC_ARG:
++#ifndef SHARED
++		CHECK_STATIC_TLS((struct link_map *) tls_tpnt);
++#else
++		if (!TRY_STATIC_TLS ((struct link_map *) tls_tpnt))
++			*reloc_addr = (ElfW(Addr))
++				_dl_make_tlsdesc_dynamic((struct link_map *) tls_tpnt,
++										 symbol_addr + *reloc_addr);
++		else
++#endif
++			*reloc_addr += symbol_addr + tls_tpnt->l_tls_offset;
++		break;
++#endif
++
+ 	default:
+ 		return -1; /* Calls _dl_exit(1).  */
+ 	}
+diff -Nur uClibc-git/ldso/ldso/xtensa/resolve.S uClibc-xtensa/ldso/ldso/xtensa/resolve.S
+--- uClibc-git/ldso/ldso/xtensa/resolve.S	2014-06-02 17:40:33.958711675 +0200
++++ uClibc-xtensa/ldso/ldso/xtensa/resolve.S	2014-06-03 12:22:20.344060961 +0200
+@@ -27,7 +27,6 @@
+ 
+ 	.text
+ 	.align	4
+-	.literal_position
+ 	.global	_dl_linux_resolve
+ 	.type	_dl_linux_resolve, @function
+ _dl_linux_resolve:
+diff -Nur uClibc-git/libc/sysdeps/linux/xtensa/clone.S uClibc-xtensa/libc/sysdeps/linux/xtensa/clone.S
+--- uClibc-git/libc/sysdeps/linux/xtensa/clone.S	2014-06-02 17:40:34.722715903 +0200
++++ uClibc-xtensa/libc/sysdeps/linux/xtensa/clone.S	2014-06-03 12:04:16.669187814 +0200
+@@ -1,34 +1,38 @@
+-/* Copyright (C) 2001, 2005, 2007 Free Software Foundation, Inc.
++/* Copyright (C) 2001, 2005 Free Software Foundation, Inc.
+ 
+    The GNU C Library is free software; you can redistribute it and/or
+-   modify it under the terms of the GNU Lesser General Public
+-   License as published by the Free Software Foundation; either
+-   version 2.1 of the License, or (at your option) any later version.
++   modify it under the terms of the GNU Library General Public License as
++   published by the Free Software Foundation; either version 2 of the
++   License, or (at your option) any later version.
+ 
+    The GNU C Library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+-   Lesser General Public License for more details.
++   Library General Public License for more details.
+ 
+-   You should have received a copy of the GNU Lesser General Public
+-   License along with the GNU C Library; if not, see
+-   <http://www.gnu.org/licenses/>.  */
++   You should have received a copy of the GNU Library General Public
++   License along with the GNU C Library; see the file COPYING.LIB.  If not,
++   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
++   Boston, MA 02111-1307, USA.  */
+ 
+ /* clone is even more special than fork as it mucks with stacks
+-   and invokes a function in the right context after it's all over.  */
++   and invokes a function in the right context after its all over.  */
+ 
+-#include "sysdep.h"
+-#include <sys/syscall.h>
++#include <features.h>
++#include <sysdep.h>
+ #define _ERRNO_H	1
+ #include <bits/errno.h>
+-
+-/* 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) */
++#ifdef RESET_PID
++#include <tls.h>
++#endif
++#define __ASSEMBLY__
++#include <linux/sched.h>
++
++/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg,
++                    a2                    a3               a4        a5
++             pid_t *ptid, struct user_desc *tls, pid_t *ctid)
++                   a6               a7              16(sp)
++*/
+ 
+         .text
+ ENTRY (__clone)
+@@ -39,7 +43,7 @@
+ 
+ 	/* a2 and a3 are candidates for destruction by system-call return
+ 	   parameters.  We don't need the stack pointer after the system
+-	   call.  We trust that the kernel will preserve a7, a9, and a6.  */
++	   call.  We trust that the kernel will preserve a6, a7 and a9. */
+ 
+ 	mov	a9, a5			/* save function argument */
+ 	mov	a5, a7
+@@ -48,19 +52,18 @@
+ 	mov	a6, a4
+ 	mov	a4, a8
+ 	l32i	a8, a1, 16		/* child_tid */
+-	movi	a2, SYS_ify (clone)
++	movi	a2, SYS_ify(clone)
++
++	/* syscall(NR_clone,clone_flags, usp, parent_tid, child_tls, child_tid)
++                     a2         a6        a3        a4        a5         a8
++         */
+ 
+-	/* 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.  */
++	/* fall through for parent */
++
+ .Lpseudo_end:
+ 	retw
+ 
+@@ -69,32 +72,38 @@
+ 	j	SYSCALL_ERROR_LABEL
+ 
+ .Lthread_start:
+-	/* Start child thread.  */
+-	movi	a0, 0			/* terminate the stack frame */
++
++#if CLONE_THREAD != 0x00010000 || CLONE_VM != 0x00000100
++# error invalid values for CLONE_THREAD or CLONE_VM
++#endif
+ 
+ #ifdef RESET_PID
+-	/* Check and see if we need to reset the PID.  */
+-	bbsi.l	a6, 16, 1f		/* CLONE_THREAD = 0x00010000 */
++	bbsi.l	a6, 16, .Lskip_restore_pid	/* CLONE_THREAD = 0x00010000 */
+ 	movi	a2, -1
+-	bbsi.l	a6, 8, 2f		/* CLONE_VM = 0x00000100 */
+-	movi	a2, SYS_ify (getpid)
++	bbsi	a6, 8, .Lgotpid			/* CLONE_VM     = 0x00000100 */
++	movi	a2, SYS_ify(getpid)
+ 	syscall
+-2:	rur	a3, THREADPTR
+-	movi	a4, PID_OFFSET
+-	add	a4, a4, a3
+-	s32i	a2, a4, 0
+-	movi	a4, TID_OFFSET
+-	add	a4, a4, a3
+-	s32i	a2, a3, 0
+-1:
+-#endif /* RESET_PID */
++.Lgotpid:
++	rur	a3, threadptr
++	movi	a0, TLS_PRE_TCB_SIZE
++	sub	a3, a3, a0
++	s32i	a2, a3, PID
++	s32i	a2, a3, TID
++.Lskip_restore_pid:
++#endif
+ 
++	/* start child thread */
++	movi	a0, 0			/* terminate the stack frame */
+ 	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)
++	   function in a6 is seen as inputs to _exit. */
++#ifdef	PIC
++	movi	a2, _exit@PLT
++#else
++	movi	a2, _exit
++#endif
+ 	callx4	a2
+ 
+ PSEUDO_END (__clone)
+diff -Nur uClibc-git/libc/sysdeps/linux/xtensa/fork.c uClibc-xtensa/libc/sysdeps/linux/xtensa/fork.c
+--- uClibc-git/libc/sysdeps/linux/xtensa/fork.c	2014-06-02 17:40:34.726715926 +0200
++++ uClibc-xtensa/libc/sysdeps/linux/xtensa/fork.c	2014-06-03 12:04:16.669187814 +0200
+@@ -20,6 +20,10 @@
+ {
+ 	return (pid_t) INLINE_SYSCALL(clone, 2, SIGCHLD, 0);
+ }
+-lt_strong_alias(fork)
+-lt_libc_hidden(fork)
++# ifdef __UCLIBC_HAS_THREADS__
++strong_alias(fork,__libc_fork)
++libc_hidden_weak(fork)
++# else
++libc_hidden_def(fork)
++# endif
+ #endif
+diff -Nur uClibc-git/libc/sysdeps/linux/xtensa/jmpbuf-unwind.h uClibc-xtensa/libc/sysdeps/linux/xtensa/jmpbuf-unwind.h
+--- uClibc-git/libc/sysdeps/linux/xtensa/jmpbuf-unwind.h	2014-06-02 17:40:34.726715926 +0200
++++ uClibc-xtensa/libc/sysdeps/linux/xtensa/jmpbuf-unwind.h	2014-06-03 12:04:16.669187814 +0200
+@@ -1,25 +1,23 @@
+-/* 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, see
+-   <http://www.gnu.org/licenses/>.  */
+-
+-/* Test if longjmp to JMPBUF would unwind the frame containing a local
+-   variable at ADDRESS.  */
+-
++/*
++ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
++ *
++ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
++ */
+ #include <setjmp.h>
+ #include <jmpbuf-offsets.h>
+ 
++/* Test if longjmp to JMPBUF would unwind the frame
++   containing a local variable at ADDRESS.  */
+ #define _JMPBUF_UNWINDS(jmpbuf, address) \
+   ((void *) (address) < (void *) (jmpbuf)[JB_SP])
++
++#ifdef __UCLIBC_HAS_THREADS_NATIVE__
++#include <stdint.h>
++#include <unwind.h>
++
++#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \
++  _JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), _adj)
++
++#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \
++  ((uintptr_t) (_address) - (_adj) < (uintptr_t) (_jmpbuf)[JB_SP] - (_adj))
++#endif
+diff -Nur uClibc-git/libc/sysdeps/linux/xtensa/Makefile.arch uClibc-xtensa/libc/sysdeps/linux/xtensa/Makefile.arch
+--- uClibc-git/libc/sysdeps/linux/xtensa/Makefile.arch	2014-06-02 17:40:34.686715704 +0200
++++ uClibc-xtensa/libc/sysdeps/linux/xtensa/Makefile.arch	2014-06-03 12:04:16.669187814 +0200
+@@ -5,7 +5,10 @@
+ # Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ #
+ 
+-CSRC-y := brk.c fork.c sigaction.c __syscall_error.c
++CSRC-y := brk.c sigaction.c __syscall_error.c
+ 
+ SSRC-y := bsd-_setjmp.S bsd-setjmp.S setjmp.S clone.S \
+ 	sigrestorer.S syscall.S mmap.S windowspill.S __longjmp.S vfork.S
++
++CSRC-$(if $(UCLIBC_HAS_THREADS_NATIVE),,y) += fork.c
++SSRC-$(if $(UCLIBC_HAS_THREADS_NATIVE),,y) += clone.S
+diff -Nur uClibc-git/libc/sysdeps/linux/xtensa/sys/ptrace.h uClibc-xtensa/libc/sysdeps/linux/xtensa/sys/ptrace.h
+--- uClibc-git/libc/sysdeps/linux/xtensa/sys/ptrace.h	1970-01-01 01:00:00.000000000 +0100
++++ uClibc-xtensa/libc/sysdeps/linux/xtensa/sys/ptrace.h	2014-06-03 11:58:41.563379928 +0200
+@@ -0,0 +1,155 @@
++/* `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, see
++   <http://www.gnu.org/licenses/>.  */
++
++#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 -Nur uClibc-git/libc/sysdeps/linux/xtensa/sysdep.h uClibc-xtensa/libc/sysdeps/linux/xtensa/sysdep.h
+--- uClibc-git/libc/sysdeps/linux/xtensa/sysdep.h	2014-06-02 17:40:34.726715926 +0200
++++ uClibc-xtensa/libc/sysdeps/linux/xtensa/sysdep.h	2014-06-03 15:24:57.308410770 +0200
+@@ -16,6 +16,10 @@
+    License along with the GNU C Library; if not, see
+    <http://www.gnu.org/licenses/>.  */
+ 
++#ifndef _LINUX_XTENSA_SYSDEP_H
++#define _LINUX_XTENSA_SYSDEP_H 1
++
++#include <common/sysdep.h>
+ #include <sys/syscall.h>
+ 
+ #ifdef __ASSEMBLER__
+@@ -24,12 +28,6 @@
+ #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);			\
+@@ -52,6 +50,15 @@
+ #undef END
+ #define END(name) ASM_SIZE_DIRECTIVE(name)
+ 
++/* Local label name for asm code. */
++#ifndef L
++# ifdef HAVE_ELF
++#  define L(name)       .L##name
++# else
++#  define L(name)       name
++# endif
++#endif
++
+ /* Define a macro for this directive so it can be removed in a few places.  */
+ #define LITERAL_POSITION .literal_position
+ 
+@@ -123,19 +130,7 @@
+ #define	PSEUDO_END_ERRVAL(name)						      \
+   END (name)
+ 
+-#undef ret_ERRVAL
+-#define ret_ERRVAL retw
+-
+-#if defined 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 defined _LIBC_REENTRANT
+ # if defined USE___THREAD
+ #  ifndef NOT_IN_libc
+ #   define SYSCALL_ERROR_ERRNO __libc_errno
+@@ -170,3 +165,9 @@
+ #endif /* _LIBC_REENTRANT */
+ 
+ #endif	/* __ASSEMBLER__ */
++
++/* Pointer mangling is not yet supported for Xtensa.  */
++#define PTR_MANGLE(var) (void) (var)
++#define PTR_DEMANGLE(var) (void) (var)
++
++#endif	/* _LINUX_XTENSA_SYSDEP_H */
+diff -Nur uClibc-git/libc/sysdeps/linux/xtensa/vfork.S uClibc-xtensa/libc/sysdeps/linux/xtensa/vfork.S
+--- uClibc-git/libc/sysdeps/linux/xtensa/vfork.S	2014-06-02 17:40:34.726715926 +0200
++++ uClibc-xtensa/libc/sysdeps/linux/xtensa/vfork.S	2014-06-03 12:04:16.669187814 +0200
+@@ -1,4 +1,4 @@
+-/* Copyright (C) 2005, 2007 Free Software Foundation, Inc.
++/* Copyright (C) 2005-2013 Free Software Foundation, Inc.
+    This file is part of the GNU C Library.
+ 
+    The GNU C Library is free software; you can redistribute it and/or
+@@ -19,72 +19,67 @@
+ #include <sys/syscall.h>
+ #define _SIGNAL_H
+ #include <bits/signum.h>
++#define __ASSEMBLY__
++#include <linux/sched.h>
+ 
+ 
+-/* Clone the calling process, but without copying the whole address space.
++/*
++   Clone the calling process, but without copying the whole address space.
+    The calling process is suspended until the new process exits or is
+    replaced by a call to `execve'.  Return -1 for errors, 0 to the new process,
+    and the process ID of the new process to the old process.
+ 
+    Note that it is important that we don't create a new stack frame for the
+-   caller.  */
++   caller.
+ 
+-
+-/* The following are defined in linux/sched.h, which unfortunately
+-   is not safe for inclusion in an assembly file.  */
+-#define CLONE_VM        0x00000100     /* set if VM shared between processes */
+-#define CLONE_VFORK     0x00004000     /* set if the parent wants the child to
+-					  wake it up on mm_release */
++*/
+ 
+ #ifndef SAVE_PID
+-#define SAVE_PID
++#define SAVE_PID(a,b,c,d)
+ #endif
+-
+ #ifndef RESTORE_PID
+-#define RESTORE_PID
++#define RESTORE_PID(a,b,c)
++#endif
++#ifndef RESTORE_PID12
++#define RESTORE_PID12(a,b,c)
+ #endif
+ 
++/*
++   pid_t vfork(void);
++   Implemented as __clone_syscall(CLONE_VFORK | CLONE_VM | SIGCHLD, 0)
++ */
+ 
+-/* pid_t vfork(void);
+-   Implemented as __clone_syscall(CLONE_VFORK | CLONE_VM | SIGCHLD, 0) */
+ 
+ HIDDEN_ENTRY (__vfork)
++        .literal .Ljumptable, 0, .L4, .L8, .L12
+ 
+-	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
+-
++	mov	a3, a0			# move return address out of the way
++	movi	a0, .Ljumptable
++	extui	a2, a3, 30, 2		# call-size: call4/8/12 = 1/2/3
++	addx4	a0, a2, a0		# find return address in jumptable
+ 	slli	a2, a2, 30
+-	xor	a3, a0, a2		/* remove call-size from return addr */
+-	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
++	l32i	a0, a0, 0
++
++	xor	a3, a3, a2		# remove call-size from return address
++	or	a0, a0, a2		# create temporary return address
++	retw
+ 
+ 	/* a7: return address */
++
+ .L4:	mov	a12, a2
+ 	mov	a13, a3
+ 
+-	SAVE_PID
++	SAVE_PID(a5,a15,a2,a3)
+ 
+-	/* Use syscall 'clone'.  Set new stack pointer to the same address.  */
+-	movi	a2, SYS_ify (clone)
++	/* use syscall 'clone' and set new stack pointer to the same address */
++
++	movi	a2, SYS_ify(clone)
+ 	movi	a3, 0
+ 	movi	a6, CLONE_VM | CLONE_VFORK | SIGCHLD
++
+         syscall
+ 
+-	RESTORE_PID
++	RESTORE_PID(a5,a15,a2)
+ 
+ 	movi	a5, -4096
+ 
+@@ -94,22 +89,24 @@
+ 
+ 	bgeu	a6, a5, 1f
+ 	jx	a7
+-1:	call4	.Lerr			/* returns to original caller */
+ 
++1:	call4	.Lerr
+ 
+ 	/* a11: return address */
++
+ .L8:	mov	a12, a2
+ 	mov	a13, a3
+ 	mov	a14, a6
+ 
+-	SAVE_PID
++	SAVE_PID(a9,a15,a2,a3)
+ 
+-	movi	a2, SYS_ify (clone)
++	movi	a2, SYS_ify(clone)
+ 	movi	a3, 0
+ 	movi	a6, CLONE_VM | CLONE_VFORK | SIGCHLD
++
+ 	syscall
+ 
+-	RESTORE_PID
++	RESTORE_PID(a9,a15,a2)
+ 
+ 	movi	a9, -4096
+ 
+@@ -120,22 +117,25 @@
+ 
+ 	bgeu	a10, a9, 1f
+ 	jx	a11
+-1:	call8	.Lerr			/* returns to original caller */
++
++1:	call8	.Lerr
+ 
+ 
+ 	/* a15: return address */
++
+ .L12:	mov	a12, a2
+ 	mov	a13, a3
+ 	mov	a14, a6
+ 
+-	SAVE_PID
++	SAVE_PID (a2,a3,a2,a6)
+ 
+-	movi	a2, SYS_ify (clone)
++	movi	a2, SYS_ify(clone)
+ 	movi	a3, 0
+ 	movi	a6, CLONE_VM | CLONE_VFORK | SIGCHLD
++
+ 	syscall
+ 
+-	RESTORE_PID
++	RESTORE_PID12(a3,a6,a15)
+ 
+ 	mov	a3, a13
+ 	movi	a13, -4096
+@@ -147,18 +147,18 @@
+ 
+ 	bgeu	a14, a13, 1f
+ 	jx	a15
+-1:	call12	.Lerr			/* returns to original caller */
+ 
++1:	call12	.Lerr
+ 
+ 	.align 4
++
+ .Lerr:	entry	a1, 16
+ 
+-	/* Restore the return address.  */
+-	extui	a4, a0, 30, 2		/* get the call-size bits */
++	/* Restore return address */
++
++	extui	a4, a0, 30, 2
+ 	slli	a4, a4, 30
+-	slli	a3, a3, 2		/* clear high bits of target address */
+-	srli	a3, a3, 2
+-	or	a0, a3, a4		/* combine them */
++	or	a0, a3, a4
+ 
+ 	PSEUDO_END (__vfork)
+ .Lpseudo_end:
+diff -Nur uClibc-git/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.c uClibc-xtensa/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.c
+--- uClibc-git/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.c	2014-06-02 17:40:35.102718006 +0200
++++ uClibc-xtensa/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.c	2014-06-03 12:35:45.097932730 +0200
+@@ -22,8 +22,6 @@
+ #include <lowlevellock.h>
+ #include <sys/time.h>
+ #include <tls.h>
+-#include <tcb-offsets.h>
+-
+ 
+ void
+ __lll_lock_wait_private (int *futex)
+diff -Nur uClibc-git/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/bits/pthreadtypes.h uClibc-xtensa/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/bits/pthreadtypes.h
+--- uClibc-git/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/bits/pthreadtypes.h	1970-01-01 01:00:00.000000000 +0100
++++ uClibc-xtensa/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/bits/pthreadtypes.h	2014-06-03 12:04:16.669187814 +0200
+@@ -0,0 +1,184 @@
++/* Copyright (C) 2002-2012 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++
++   The GNU C Library is free software; you can redistribute it and/or
++   modify it under the terms of the GNU Lesser General Public
++   License as published by the Free Software Foundation; either
++   version 2.1 of the License, or (at your option) any later version.
++
++   The GNU C Library is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++   Lesser General Public License for more details.
++
++   You should have received a copy of the GNU Lesser General Public
++   License along with the GNU C Library.  If not, see
++   <http://www.gnu.org/licenses/>.  */
++
++#ifndef _BITS_PTHREADTYPES_H
++#define _BITS_PTHREADTYPES_H	1
++
++#include <endian.h>
++
++#define __SIZEOF_PTHREAD_ATTR_T 36
++#define __SIZEOF_PTHREAD_MUTEX_T 24
++#define __SIZEOF_PTHREAD_MUTEXATTR_T 4
++#define __SIZEOF_PTHREAD_COND_T 48
++#define __SIZEOF_PTHREAD_COND_COMPAT_T 12
++#define __SIZEOF_PTHREAD_CONDATTR_T 4
++#define __SIZEOF_PTHREAD_RWLOCK_T 32
++#define __SIZEOF_PTHREAD_RWLOCKATTR_T 8
++#define __SIZEOF_PTHREAD_BARRIER_T 20
++#define __SIZEOF_PTHREAD_BARRIERATTR_T 4
++
++
++/* Thread identifiers.  The structure of the attribute type is not
++   exposed on purpose.  */
++typedef unsigned long int pthread_t;
++
++
++union pthread_attr_t
++{
++  char __size[__SIZEOF_PTHREAD_ATTR_T];
++  long int __align;
++};
++#ifndef __have_pthread_attr_t
++typedef union pthread_attr_t pthread_attr_t;
++# define __have_pthread_attr_t	1
++#endif
++
++
++typedef struct __pthread_internal_slist
++{
++  struct __pthread_internal_slist *__next;
++} __pthread_slist_t;
++
++
++/* Data structures for mutex handling.  The structure of the attribute
++   type is not exposed on purpose.  */
++typedef union
++{
++  struct __pthread_mutex_s
++  {
++    int __lock;
++    unsigned int __count;
++    int __owner;
++    /* KIND must stay at this position in the structure to maintain
++       binary compatibility.  */
++    int __kind;
++    unsigned int __nusers;
++    __extension__ union
++    {
++      int __spins;
++      __pthread_slist_t __list;
++    };
++  } __data;
++  char __size[__SIZEOF_PTHREAD_MUTEX_T];
++  long int __align;
++} pthread_mutex_t;
++
++typedef union
++{
++  char __size[__SIZEOF_PTHREAD_MUTEXATTR_T];
++  long int __align;
++} pthread_mutexattr_t;
++
++
++/* Data structure for conditional variable handling.  The structure of
++   the attribute type is not exposed on purpose.  */
++typedef union
++{
++  struct
++  {
++    int __lock;
++    unsigned int __futex;
++    __extension__ unsigned long long int __total_seq;
++    __extension__ unsigned long long int __wakeup_seq;
++    __extension__ unsigned long long int __woken_seq;
++    void *__mutex;
++    unsigned int __nwaiters;
++    unsigned int __broadcast_seq;
++  } __data;
++  char __size[__SIZEOF_PTHREAD_COND_T];
++  __extension__ long long int __align;
++} pthread_cond_t;
++
++typedef union
++{
++  char __size[__SIZEOF_PTHREAD_CONDATTR_T];
++  long int __align;
++} pthread_condattr_t;
++
++
++/* Keys for thread-specific data */
++typedef unsigned int pthread_key_t;
++
++
++/* Once-only execution */
++typedef int pthread_once_t;
++
++
++#if defined __USE_UNIX98 || defined __USE_XOPEN2K
++/* Data structure for read-write lock variable handling.  The
++   structure of the attribute type is not exposed on purpose.  */
++typedef union
++{
++  struct
++  {
++    int __lock;
++    unsigned int __nr_readers;
++    unsigned int __readers_wakeup;
++    unsigned int __writer_wakeup;
++    unsigned int __nr_readers_queued;
++    unsigned int __nr_writers_queued;
++#if __BYTE_ORDER == __BIG_ENDIAN
++    unsigned char __pad1;
++    unsigned char __pad2;
++    unsigned char __shared;
++    /* FLAGS must stay at this position in the structure to maintain
++       binary compatibility.  */
++    unsigned char __flags;
++#else
++    /* FLAGS must stay at this position in the structure to maintain
++       binary compatibility.  */
++    unsigned char __flags;
++    unsigned char __shared;
++    unsigned char __pad1;
++    unsigned char __pad2;
++#endif
++    int __writer;
++  } __data;
++  char __size[__SIZEOF_PTHREAD_RWLOCK_T];
++  long int __align;
++} pthread_rwlock_t;
++
++typedef union
++{
++  char __size[__SIZEOF_PTHREAD_RWLOCKATTR_T];
++  long int __align;
++} pthread_rwlockattr_t;
++#endif
++
++
++#ifdef __USE_XOPEN2K
++/* POSIX spinlock data type.  */
++typedef volatile int pthread_spinlock_t;
++
++
++/* POSIX barriers data type.  The structure of the type is
++   deliberately not exposed.  */
++typedef union
++{
++  char __size[__SIZEOF_PTHREAD_BARRIER_T];
++  long int __align;
++} pthread_barrier_t;
++
++typedef union
++{
++  char __size[__SIZEOF_PTHREAD_BARRIERATTR_T];
++  int __align;
++} pthread_barrierattr_t;
++#endif
++
++
++#endif	/* bits/pthreadtypes.h */
+diff -Nur uClibc-git/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/bits/semaphore.h uClibc-xtensa/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/bits/semaphore.h
+--- uClibc-git/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/bits/semaphore.h	1970-01-01 01:00:00.000000000 +0100
++++ uClibc-xtensa/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/bits/semaphore.h	2014-06-03 12:04:16.669187814 +0200
+@@ -0,0 +1,35 @@
++/* Copyright (C) 2012 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++
++   The GNU C Library is free software; you can redistribute it and/or
++   modify it under the terms of the GNU Lesser General Public
++   License as published by the Free Software Foundation; either
++   version 2.1 of the License, or (at your option) any later version.
++
++   The GNU C Library is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++   Lesser General Public License for more details.
++
++   You should have received a copy of the GNU Lesser General Public
++   License along with the GNU C Library; if not, write to the Free
++   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
++   02111-1307 USA.  */
++
++#ifndef _SEMAPHORE_H
++# error "Never use <bits/semaphore.h> directly; include <semaphore.h> instead."
++#endif
++
++
++#define __SIZEOF_SEM_T	16
++
++
++/* Value returned if `sem_open' failed.  */
++#define SEM_FAILED      ((sem_t *) 0)
++
++
++typedef union
++{
++  char __size[__SIZEOF_SEM_T];
++  long int __align;
++} sem_t;
+diff -Nur uClibc-git/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/clone.S uClibc-xtensa/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/clone.S
+--- uClibc-git/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/clone.S	1970-01-01 01:00:00.000000000 +0100
++++ uClibc-xtensa/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/clone.S	2014-06-03 12:04:16.669187814 +0200
+@@ -0,0 +1,3 @@
++#define RESET_PID
++#include <tcb-offsets.h>
++#include <libc/sysdeps/linux/xtensa/clone.S>
+diff -Nur uClibc-git/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/createthread.c uClibc-xtensa/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/createthread.c
+--- uClibc-git/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/createthread.c	1970-01-01 01:00:00.000000000 +0100
++++ uClibc-xtensa/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/createthread.c	2014-06-03 12:04:16.669187814 +0200
+@@ -0,0 +1,24 @@
++/* Copyright (C) 2012 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++
++   The GNU C Library is free software; you can redistribute it and/or
++   modify it under the terms of the GNU Lesser General Public
++   License as published by the Free Software Foundation; either
++   version 2.1 of the License, or (at your option) any later version.
++
++   The GNU C Library is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++   Lesser General Public License for more details.
++
++   You should have received a copy of the GNU Lesser General Public
++   License along with the GNU C Library; if not, write to the Free
++   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
++   02111-1307 USA.  */
++
++/* Value passed to 'clone' for initialization of the thread register.  */
++#define TLS_VALUE (pd + 1)
++
++
++/* Get the real implementation.  */
++#include <sysdeps/pthread/createthread.c>
+diff -Nur uClibc-git/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/fork.c uClibc-xtensa/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/fork.c
+--- uClibc-git/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/fork.c	1970-01-01 01:00:00.000000000 +0100
++++ uClibc-xtensa/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/fork.c	2014-06-03 12:04:16.669187814 +0200
+@@ -0,0 +1,29 @@
++/* Copyright (C) 2013 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++
++   The GNU C Library is free software; you can redistribute it and/or
++   modify it under the terms of the GNU Lesser General Public
++   License as published by the Free Software Foundation; either
++   version 2.1 of the License, or (at your option) any later version.
++
++   The GNU C Library is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++   Lesser General Public License for more details.
++
++   You should have received a copy of the GNU Lesser General Public
++   License along with the GNU C Library; if not, see
++   <http://www.gnu.org/licenses/>.  */
++
++#include <sched.h>
++#include <signal.h>
++#include <sysdep.h>
++#include <tls.h>
++
++
++#define ARCH_FORK() \
++  INLINE_SYSCALL (clone, 5,						      \
++		  CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD, 0,     \
++		  NULL, NULL, &THREAD_SELF->tid)
++
++#include "../fork.c"
+diff -Nur uClibc-git/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/lowlevellock.c uClibc-xtensa/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/lowlevellock.c
+--- uClibc-git/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/lowlevellock.c	1970-01-01 01:00:00.000000000 +0100
++++ uClibc-xtensa/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/lowlevellock.c	2014-06-03 12:04:16.669187814 +0200
+@@ -0,0 +1,132 @@
++/* low level locking for pthread library.  Generic futex-using version.
++   Copyright (C) 2003-2013 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++
++   The GNU C Library is free software; you can redistribute it and/or
++   modify it under the terms of the GNU Lesser General Public
++   License as published by the Free Software Foundation; either
++   version 2.1 of the License, or (at your option) any later version.
++
++   The GNU C Library is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
++   Lesser General Public License for more details.
++
++   You should have received a copy of the GNU Lesser General Public
++   License along with the GNU C Library.  If not, see
++   <http://www.gnu.org/licenses/>.  */
++
++#include <errno.h>
++#include <sysdep.h>
++#include <lowlevellock.h>
++#include <sys/time.h>
++
++void
++__lll_lock_wait_private (int *futex)
++{
++  do
++    {
++      int oldval = atomic_compare_and_exchange_val_acq (futex, 2, 1);
++      if (oldval != 0)
++	lll_futex_wait (futex, 2, LLL_PRIVATE);
++    }
++  while (atomic_compare_and_exchange_bool_acq (futex, 2, 0) != 0);
++}
++
++
++/* These functions don't get included in libc.so  */
++#ifdef IS_IN_libpthread
++void
++__lll_lock_wait (int *futex, int private)
++{
++  do
++    {
++      int oldval = atomic_compare_and_exchange_val_acq (futex, 2, 1);
++      if (oldval != 0)
++	lll_futex_wait (futex, 2, private);
++    }
++  while (atomic_compare_and_exchange_bool_acq (futex, 2, 0) != 0);
++}
++
++
++int
++__lll_timedlock_wait (int *futex, const struct timespec *abstime, int private)
++{
++  struct timespec rt;
++
++  /* Reject invalid timeouts.  */
++  if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
++    return EINVAL;
++
++  /* Upgrade the lock.  */
++  if (atomic_exchange_acq (futex, 2) == 0)
++    return 0;
++
++  do
++    {
++      struct timeval tv;
++
++      /* Get the current time.  */
++      (void) __gettimeofday (&tv, NULL);
++
++      /* Compute relative timeout.  */
++      rt.tv_sec = abstime->tv_sec - tv.tv_sec;
++      rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000;
++      if (rt.tv_nsec < 0)
++	{
++	  rt.tv_nsec += 1000000000;
++	  --rt.tv_sec;
++	}
++
++      /* Already timed out?  */
++      if (rt.tv_sec < 0)
++	return ETIMEDOUT;
++
++      // XYZ: Lost the lock to check whether it was private.
++      lll_futex_timed_wait (futex, 2, &rt, private);
++    }
++  while (atomic_compare_and_exchange_bool_acq (futex, 2, 0) != 0);
++
++  return 0;
++}
++
++
++int
++__lll_timedwait_tid (int *tidp, const struct timespec *abstime)
++{
++  int tid;
++
++  if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
++    return EINVAL;
++
++  /* Repeat until thread terminated.  */
++  while ((tid = *tidp) != 0)
++    {
++      struct timeval tv;
++      struct timespec rt;
++
++      /* Get the current time.  */
++      (void) __gettimeofday (&tv, NULL);
++
++      /* Compute relative timeout.  */
++      rt.tv_sec = abstime->tv_sec - tv.tv_sec;
++      rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000;
++      if (rt.tv_nsec < 0)
++	{
++	  rt.tv_nsec += 1000000000;
++	  --rt.tv_sec;
++	}
++
++      /* Already timed out?  */
++      if (rt.tv_sec < 0)
++	return ETIMEDOUT;
++
++      /* Wait until thread terminates.  */
++      // XYZ: Lost the lock to check whether it was private.
++      if (lll_futex_timed_wait (tidp, tid, &rt, LLL_SHARED) == -ETIMEDOUT)
++	return ETIMEDOUT;
++    }
++
++  return 0;
++}
++#endif
+diff -Nur uClibc-git/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/lowlevellock.h uClibc-xtensa/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/lowlevellock.h
+--- uClibc-git/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/lowlevellock.h	1970-01-01 01:00:00.000000000 +0100
++++ uClibc-xtensa/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/lowlevellock.h	2014-06-03 12:04:16.669187814 +0200
+@@ -0,0 +1,293 @@
++/* Copyright (C) 2005-2013 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++
++   The GNU C Library is free software; you can redistribute it and/or
++   modify it under the terms of the GNU Lesser General Public
++   License as published by the Free Software Foundation; either
++   version 2.1 of the License, or (at your option) any later version.
++
++   The GNU C Library is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
++   Lesser General Public License for more details.
++
++   You should have received a copy of the GNU Lesser General Public
++   License along with the GNU C Library.  If not, see
++   <http://www.gnu.org/licenses/>.  */
++
++#ifndef _LOWLEVELLOCK_H
++#define _LOWLEVELLOCK_H	1
++
++#include <time.h>
++#include <sys/param.h>
++#include <bits/pthreadtypes.h>
++#include <atomic.h>
++#include <sysdep.h>
++#include <bits/kernel-features.h>
++
++#define FUTEX_WAIT		0
++#define FUTEX_WAKE		1
++#define FUTEX_REQUEUE		3
++#define FUTEX_CMP_REQUEUE	4
++#define FUTEX_WAKE_OP		5
++#define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE	((4 << 24) | 1)
++#define FUTEX_LOCK_PI		6
++#define FUTEX_UNLOCK_PI		7
++#define FUTEX_TRYLOCK_PI	8
++#define FUTEX_WAIT_BITSET	9
++#define FUTEX_WAKE_BITSET	10
++#define FUTEX_PRIVATE_FLAG	128
++#define FUTEX_CLOCK_REALTIME	256
++
++#define FUTEX_BITSET_MATCH_ANY	0xffffffff
++
++/* Values for 'private' parameter of locking macros.  Yes, the
++   definition seems to be backwards.  But it is not.  The bit will be
++   reversed before passing to the system call.  */
++#define LLL_PRIVATE	0
++#define LLL_SHARED	FUTEX_PRIVATE_FLAG
++
++
++#if !defined NOT_IN_libc || defined IS_IN_rtld
++/* In libc.so or ld.so all futexes are private.  */
++# ifdef __ASSUME_PRIVATE_FUTEX
++#  define __lll_private_flag(fl, private) \
++  ((fl) | FUTEX_PRIVATE_FLAG)
++# else
++#  define __lll_private_flag(fl, private) \
++  ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex))
++# endif
++#else
++# ifdef __ASSUME_PRIVATE_FUTEX
++#  define __lll_private_flag(fl, private) \
++  (((fl) | FUTEX_PRIVATE_FLAG) ^ (private))
++# else
++#  define __lll_private_flag(fl, private) \
++  (__builtin_constant_p (private)					      \
++   ? ((private) == 0							      \
++      ? ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex))	      \
++      : (fl))								      \
++   : ((fl) | (((private) ^ FUTEX_PRIVATE_FLAG)				      \
++	      & THREAD_GETMEM (THREAD_SELF, header.private_futex))))
++# endif
++#endif
++
++
++#define lll_futex_wait(futexp, val, private) \
++  lll_futex_timed_wait(futexp, val, NULL, private)
++
++#define lll_futex_timed_wait(futexp, val, timespec, private) \
++  ({									      \
++    INTERNAL_SYSCALL_DECL (__err);					      \
++    long int __ret;							      \
++    __ret = INTERNAL_SYSCALL (futex, __err, 4, (futexp),		      \
++			      __lll_private_flag (FUTEX_WAIT, private),	      \
++			      (val), (timespec));			      \
++    __ret;								      \
++  })
++
++#define lll_futex_timed_wait_bitset(futexp, val, timespec, clockbit, private) \
++  ({									\
++    INTERNAL_SYSCALL_DECL (__err);					\
++    long int __ret;							\
++    int __op = FUTEX_WAIT_BITSET | clockbit;				\
++    __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp),		\
++			      __lll_private_flag (__op, private),	\
++			      (val), (timespec), NULL /* Unused.  */,	\
++			      FUTEX_BITSET_MATCH_ANY);			\
++    __ret;								\
++  })
++
++#define lll_futex_wake(futexp, nr, private) \
++  ({									      \
++    INTERNAL_SYSCALL_DECL (__err);					      \
++    long int __ret;							      \
++    __ret = INTERNAL_SYSCALL (futex, __err, 4, (futexp),		      \
++			      __lll_private_flag (FUTEX_WAKE, private),	      \
++			      (nr), 0);					      \
++    __ret;								      \
++  })
++
++#define lll_robust_dead(futexv, private) \
++  do									      \
++    {									      \
++      int *__futexp = &(futexv);					      \
++      atomic_or (__futexp, FUTEX_OWNER_DIED);				      \
++      lll_futex_wake (__futexp, 1, private);				      \
++    }									      \
++  while (0)
++
++/* Returns non-zero if error happened, zero if success.  */
++#define lll_futex_requeue(futexp, nr_wake, nr_move, mutex, val, private) \
++  ({									      \
++    INTERNAL_SYSCALL_DECL (__err);					      \
++    long int __ret;							      \
++    __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp),		      \
++			      __lll_private_flag (FUTEX_CMP_REQUEUE, private),\
++			      (nr_wake), (nr_move), (mutex), (val));	      \
++    INTERNAL_SYSCALL_ERROR_P (__ret, __err);				      \
++  })
++
++
++/* Returns non-zero if error happened, zero if success.  */
++#define lll_futex_wake_unlock(futexp, nr_wake, nr_wake2, futexp2, private) \
++  ({									      \
++    INTERNAL_SYSCALL_DECL (__err);					      \
++    long int __ret;							      \
++    __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp),		      \
++			      __lll_private_flag (FUTEX_WAKE_OP, private),    \
++			      (nr_wake), (nr_wake2), (futexp2),		      \
++			      FUTEX_OP_CLEAR_WAKE_IF_GT_ONE);		      \
++    INTERNAL_SYSCALL_ERROR_P (__ret, __err);				      \
++  })
++
++
++#define lll_trylock(lock)	\
++  atomic_compare_and_exchange_val_acq(&(lock), 1, 0)
++
++#define lll_cond_trylock(lock)	\
++  atomic_compare_and_exchange_val_acq(&(lock), 2, 0)
++
++#define __lll_robust_trylock(futex, id) \
++  (atomic_compare_and_exchange_val_acq (futex, id, 0) != 0)
++#define lll_robust_trylock(lock, id) \
++  __lll_robust_trylock (&(lock), id)
++
++extern void __lll_lock_wait_private (int *futex) attribute_hidden;
++extern void __lll_lock_wait (int *futex, int private) attribute_hidden;
++extern int __lll_robust_lock_wait (int *futex, int private) attribute_hidden;
++
++#define __lll_lock(futex, private)					      \
++  ((void) ({								      \
++    int *__futex = (futex);						      \
++    if (__builtin_expect (atomic_compare_and_exchange_val_acq (__futex,       \
++								1, 0), 0))    \
++      {									      \
++	if (__builtin_constant_p (private) && (private) == LLL_PRIVATE)	      \
++	  __lll_lock_wait_private (__futex);				      \
++	else								      \
++	  __lll_lock_wait (__futex, private);				      \
++      }									      \
++  }))
++#define lll_lock(futex, private) __lll_lock (&(futex), private)
++
++
++#define __lll_robust_lock(futex, id, private)				      \
++  ({									      \
++    int *__futex = (futex);						      \
++    int __val = 0;							      \
++									      \
++    if (__builtin_expect (atomic_compare_and_exchange_bool_acq (__futex, id,  \
++								0), 0))	      \
++      __val = __lll_robust_lock_wait (__futex, private);		      \
++    __val;								      \
++  })
++#define lll_robust_lock(futex, id, private) \
++  __lll_robust_lock (&(futex), id, private)
++
++
++#define __lll_cond_lock(futex, private)					      \
++  ((void) ({								      \
++    int *__futex = (futex);						      \
++    if (__builtin_expect (atomic_exchange_acq (__futex, 2), 0))		      \
++      __lll_lock_wait (__futex, private);				      \
++  }))
++#define lll_cond_lock(futex, private) __lll_cond_lock (&(futex), private)
++
++
++#define lll_robust_cond_lock(futex, id, private) \
++  __lll_robust_lock (&(futex), (id) | FUTEX_WAITERS, private)
++
++
++extern int __lll_timedlock_wait (int *futex, const struct timespec *,
++				 int private) attribute_hidden;
++extern int __lll_robust_timedlock_wait (int *futex, const struct timespec *,
++					int private) attribute_hidden;
++
++#define __lll_timedlock(futex, abstime, private)			      \
++  ({									      \
++     int *__futex = (futex);						      \
++     int __val = 0;							      \
++									      \
++     if (__builtin_expect (atomic_exchange_acq (__futex, 1), 0))	      \
++       __val = __lll_timedlock_wait (__futex, abstime, private);	      \
++     __val;								      \
++  })
++#define lll_timedlock(futex, abstime, private) \
++  __lll_timedlock (&(futex), abstime, private)
++
++
++#define __lll_robust_timedlock(futex, abstime, id, private)		      \
++  ({									      \
++    int *__futex = (futex);						      \
++    int __val = 0;							      \
++									      \
++    if (__builtin_expect (atomic_compare_and_exchange_bool_acq (__futex, id,  \
++								0), 0))	      \
++      __val = __lll_robust_timedlock_wait (__futex, abstime, private);	      \
++    __val;								      \
++  })
++#define lll_robust_timedlock(futex, abstime, id, private) \
++  __lll_robust_timedlock (&(futex), abstime, id, private)
++
++
++#define __lll_unlock(futex, private) \
++  (void)							\
++    ({ int *__futex = (futex);					\
++       int __oldval = atomic_exchange_rel (__futex, 0);		\
++       if (__builtin_expect (__oldval > 1, 0))			\
++	 lll_futex_wake (__futex, 1, private);			\
++    })
++#define lll_unlock(futex, private) __lll_unlock(&(futex), private)
++
++
++#define __lll_robust_unlock(futex, private) \
++  (void)							\
++    ({ int *__futex = (futex);					\
++       int __oldval = atomic_exchange_rel (__futex, 0);		\
++       if (__builtin_expect (__oldval & FUTEX_WAITERS, 0))	\
++	 lll_futex_wake (__futex, 1, private);			\
++    })
++#define lll_robust_unlock(futex, private) \
++  __lll_robust_unlock(&(futex), private)
++
++
++#define lll_islocked(futex) \
++  (futex != 0)
++
++
++/* Our internal lock implementation is identical to the binary-compatible
++   mutex implementation. */
++
++/* Initializers for lock.  */
++#define LLL_LOCK_INITIALIZER		(0)
++#define LLL_LOCK_INITIALIZER_LOCKED	(1)
++
++/* The states of a lock are:
++    0  -  untaken
++    1  -  taken by one user
++   >1  -  taken by more users */
++
++/* The kernel notifies a process which uses CLONE_CHILD_CLEARTID via futex
++   wakeup when the clone terminates.  The memory location contains the
++   thread ID while the clone is running and is reset to zero
++   afterwards.	*/
++#define lll_wait_tid(tid) \
++  do {					\
++    __typeof (tid) __tid;		\
++    while ((__tid = (tid)) != 0)	\
++      lll_futex_wait (&(tid), __tid, LLL_SHARED);\
++  } while (0)
++
++extern int __lll_timedwait_tid (int *, const struct timespec *)
++     attribute_hidden;
++
++#define lll_timedwait_tid(tid, abstime) \
++  ({							\
++    int __res = 0;					\
++    if ((tid) != 0)					\
++      __res = __lll_timedwait_tid (&(tid), (abstime));	\
++    __res;						\
++  })
++
++#endif	/* lowlevellock.h */
+diff -Nur uClibc-git/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/Makefile.arch uClibc-xtensa/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/Makefile.arch
+--- uClibc-git/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/Makefile.arch	1970-01-01 01:00:00.000000000 +0100
++++ uClibc-xtensa/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/Makefile.arch	2014-06-03 12:04:16.669187814 +0200
+@@ -0,0 +1,17 @@
++# Makefile for uClibc NPTL
++#
++# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
++#
++
++libc_linux_arch_CSRC = fork.c
++libc_linux_arch_SSRC = clone.S vfork.S
++libpthread_linux_arch_CSRC = pthread_once.c
++libpthread_linux_arch_SSRC = pt-vfork.S
++
++CFLAGS-OMIT-fork.c = -DNOT_IN_libc -DIS_IN_libpthread
++ASFLAGS-pt-vfork.S = -DNOT_IN_libc -DIS_IN_libpthread -D_LIBC_REENTRANT
++
++ASFLAGS-clone.S = -D_LIBC_REENTRANT
++ASFLAGS-vfork.S = -D_LIBC_REENTRANT
++ASFLAGS-syscall.S = -D_LIBC_REENTRANT
++ASFLAGS-mmap.S = -D_LIBC_REENTRANT
+diff -Nur uClibc-git/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/pthread_once.c uClibc-xtensa/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/pthread_once.c
+--- uClibc-git/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/pthread_once.c	1970-01-01 01:00:00.000000000 +0100
++++ uClibc-xtensa/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/pthread_once.c	2014-06-03 12:04:16.669187814 +0200
+@@ -0,0 +1,89 @@
++/* Copyright (C) 2004-2013 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++
++   The GNU C Library is free software; you can redistribute it and/or
++   modify it under the terms of the GNU Lesser General Public
++   License as published by the Free Software Foundation; either
++   version 2.1 of the License, or (at your option) any later version.
++
++   The GNU C Library is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
++   Lesser General Public License for more details.
++
++   You should have received a copy of the GNU Lesser General Public
++   License along with the GNU C Library.  If not, see
++   <http://www.gnu.org/licenses/>.  */
++
++#include "pthreadP.h"
++#include <lowlevellock.h>
++
++unsigned long int __fork_generation attribute_hidden;
++
++static void
++clear_once_control (void *arg)
++{
++  pthread_once_t *once_control = (pthread_once_t *) arg;
++
++  *once_control = 0;
++  lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE);
++}
++
++int
++__pthread_once (pthread_once_t *once_control, void (*init_routine) (void))
++{
++  for (;;)
++    {
++      int oldval;
++      int newval;
++
++      /* Pseudo code:
++	 newval = __fork_generation | 1;
++	 oldval = *once_control;
++	 if ((oldval & 2) == 0)
++	   *once_control = newval;
++	 Do this atomically.
++      */
++      do
++	{
++	  newval = __fork_generation | 1;
++	  oldval = *once_control;
++	  if (oldval & 2)
++	    break;
++	} while (atomic_compare_and_exchange_val_acq (once_control, newval, oldval) != oldval);
++
++      /* Check if the initializer has already been done.  */
++      if ((oldval & 2) != 0)
++	return 0;
++
++      /* Check if another thread already runs the initializer.	*/
++      if ((oldval & 1) == 0)
++	break;
++
++      /* Check whether the initializer execution was interrupted by a fork.  */
++      if (oldval != newval)
++	break;
++
++      /* Same generation, some other thread was faster. Wait.  */
++      lll_futex_wait (once_control, oldval, LLL_PRIVATE);
++    }
++
++  /* This thread is the first here.  Do the initialization.
++     Register a cleanup handler so that in case the thread gets
++     interrupted the initialization can be restarted.  */
++  pthread_cleanup_push (clear_once_control, once_control);
++
++  init_routine ();
++
++  pthread_cleanup_pop (0);
++
++  /* Say that the initialisation is done.  */
++  *once_control = __fork_generation | 2;
++
++  /* Wake up all other threads.  */
++  lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE);
++
++  return 0;
++}
++weak_alias (__pthread_once, pthread_once)
++strong_alias (__pthread_once, __pthread_once_internal)
+diff -Nur uClibc-git/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/pt-initfini.c uClibc-xtensa/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/pt-initfini.c
+--- uClibc-git/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/pt-initfini.c	1970-01-01 01:00:00.000000000 +0100
++++ uClibc-xtensa/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/pt-initfini.c	2014-06-03 12:04:16.669187814 +0200
+@@ -0,0 +1,134 @@
++/* Special .init and .fini section support.  Linuxthread version.
++   Copyright (C) 1995,1996,1997,2000,2001,2002 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 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 Library 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.)
++
++   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; see the file COPYING.LIB.  If not,
++   see <http://www.gnu.org/licenses/>.  */
++
++/* This file is compiled into assembly code which is then munged by a sed
++   script into two files: crti.s and crtn.s.
++
++   * crti.s puts a function prologue at the beginning of the
++   .init and .fini sections and defines global symbols for
++   those addresses, so they can be called as functions.
++
++   * crtn.s puts the corresponding function epilogues
++   in the .init and .fini sections. */
++
++#include <stdlib.h>
++
++/* We use embedded asm for .section unconditionally, as this makes it
++   easier to insert the necessary directives into crtn.S. */
++#define SECTION(x) __asm__ (".section " x )
++
++/* Embed an #include to pull in the alignment and .end directives. */
++__asm__ ("\n#include \"defs.h\"");
++__asm__ ("\n#if defined __i686 && defined __ASSEMBLER__");
++__asm__ ("\n#undef __i686");
++__asm__ ("\n#define __i686 __i686");
++__asm__ ("\n#endif");
++
++/* The initial common code ends here. */
++__asm__ ("\n/*@HEADER_ENDS*/");
++
++/* To determine whether we need .end and .align: */
++__asm__ ("\n/*@TESTS_BEGIN*/");
++extern void dummy (void (*foo) (void));
++void
++dummy (void (*foo) (void))
++{
++  if (foo)
++    (*foo) ();
++}
++__asm__ ("\n/*@TESTS_END*/");
++
++/* The beginning of _init:  */
++__asm__ ("\n/*@_init_PROLOG_BEGINS*/");
++
++static void
++call_initialize_minimal (void)
++{
++  extern void __pthread_initialize_minimal_internal (void)
++    __attribute ((visibility ("hidden")));
++
++  __pthread_initialize_minimal_internal ();
++}
++
++SECTION (".init");
++extern void __attribute__ ((section (".init"))) _init (void);
++void
++_init (void)
++{
++  /* The very first thing we must do is to set up the registers.  */
++  call_initialize_minimal ();
++
++  __asm__ ("ALIGN");
++  __asm__("END_INIT");
++  /* Now the epilog. */
++  __asm__ ("\n/*@_init_PROLOG_ENDS*/");
++  __asm__ ("\n/*@_init_EPILOG_BEGINS*/");
++  SECTION(".init");
++}
++__asm__ ("END_INIT");
++
++/* End of the _init epilog, beginning of the _fini prolog. */
++__asm__ ("\n/*@_init_EPILOG_ENDS*/");
++__asm__ ("\n/*@_fini_PROLOG_BEGINS*/");
++
++SECTION (".fini");
++extern void __attribute__ ((section (".fini"))) _fini (void);
++void
++_fini (void)
++{
++
++  /* End of the _fini prolog. */
++  __asm__ ("ALIGN");
++  __asm__ ("END_FINI");
++  __asm__ ("\n/*@_fini_PROLOG_ENDS*/");
++
++  /* Xtensa: It doesn't really matter whether GCC thinks this is a leaf
++     function or not, and the scripts that are supposed to remove the
++     call don't catch the literal, resulting in an undefined symbol
++     reference.  */
++#if 0
++  {
++    /* Let GCC know that _fini is not a leaf function by having a dummy
++       function call here.  We arrange for this call to be omitted from
++       either crt file.  */
++    extern void i_am_not_a_leaf (void);
++    i_am_not_a_leaf ();
++  }
++#endif
++
++  /* Beginning of the _fini epilog. */
++  __asm__ ("\n/*@_fini_EPILOG_BEGINS*/");
++  SECTION (".fini");
++}
++__asm__ ("END_FINI");
++
++/* End of the _fini epilog.  Any further generated assembly (e.g. .ident)
++   is shared between both crt files. */
++__asm__ ("\n/*@_fini_EPILOG_ENDS*/");
++__asm__ ("\n/*@TRAILER_BEGINS*/");
++
++/* End of file. */
+diff -Nur uClibc-git/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/pt-vfork.S uClibc-xtensa/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/pt-vfork.S
+--- uClibc-git/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/pt-vfork.S	1970-01-01 01:00:00.000000000 +0100
++++ uClibc-xtensa/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/pt-vfork.S	2014-06-03 12:04:16.669187814 +0200
+@@ -0,0 +1,48 @@
++/* Copyright (C) 2013 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++
++   The GNU C Library is free software; you can redistribute it and/or
++   modify it under the terms of the GNU Lesser General Public
++   License as published by the Free Software Foundation; either
++   version 2.1 of the License, or (at your option) any later version.
++
++   The GNU C Library is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++   Lesser General Public License for more details.
++
++   You should have received a copy of the GNU Lesser General Public
++   License along with the GNU C Library.  If not, see
++   <http://www.gnu.org/licenses/>.  */
++
++#include <tls.h>
++
++/*
++  Save the PID value (save the negated value)
++  Registers ar, as are available; pid, tp are preserved across
++ */
++#define SAVE_PID(pid, tp, ar, as)					\
++	rur	tp, threadptr;						\
++	movi	ar, TLS_PRE_TCB_SIZE;					\
++	sub	tp, tp, ar;						\
++	l32i	pid, tp, PID;						\
++	neg	ar, pid;						\
++	s32i	pid, tp, PID;						\
++
++/*
++  Restore the PID value if we are back in the parent.
++ */
++#define RESTORE_PID(pid, tp, res)					\
++	beqz	res, 1f;						\
++	s32i	pid, tp, PID;						\
++1:
++
++#define RESTORE_PID12(ar, as, at)					\
++	rur	as, threadptr;						\
++	movi	ar, TLS_PRE_TCB_SIZE;					\
++	sub	as, as, ar;						\
++	l32i	ar, as, PID;						\
++	neg	ar, ar;							\
++	s32i	ar, as, PID;
++
++#include <libc/sysdeps/linux/xtensa/vfork.S>
+diff -Nur uClibc-git/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/sysdep-cancel.h uClibc-xtensa/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/sysdep-cancel.h
+--- uClibc-git/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/sysdep-cancel.h	1970-01-01 01:00:00.000000000 +0100
++++ uClibc-xtensa/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/sysdep-cancel.h	2014-06-03 12:04:16.669187814 +0200
+@@ -0,0 +1,108 @@
++/* Copyright (C) 2003 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.  */
++
++#include <sysdep.h>
++#include <tls.h>
++/* #include <pt-machine.h> */
++#ifndef __ASSEMBLER__
++# include <pthreadP.h>
++#endif
++
++#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt
++// FIXME: ENTRY includes an entry instruction, here we'd want entry sp, 48!
++# undef PSEUDO
++# define PSEUDO(name, syscall_name, args)				      \
++  .text;								      \
++  ENTRY (name)								      \
++    SINGLE_THREAD_P(a15);						      \
++    bnez     a15, .Lpseudo_cancel; 					      \
++    DO_CALL (syscall_name, args);					      \
++    bgez     a2, .Lpseudo_done; 					      \
++    movi     a4, -4095;							      \
++    blt      a2, a4, .Lpseudo_done; 					      \
++    j        SYSCALL_ERROR_LABEL;					      \
++  .Lpseudo_done: 							      \
++    retw;								      \
++  .Lpseudo_cancel: 							      \
++    /* The syscall args are in a2...a7; no need to save */		      \
++    CENABLE;								      \
++    /* The return value is in a10 and preserved across the syscall */	      \
++    DO_CALL (syscall_name, args);					      \
++    CDISABLE;								      \
++    bgez     a2, .Lpseudo_end;                                                \
++    movi     a4, -4095;							      \
++    blt      a2, a4, .Lpseudo_end;                                            \
++    j        SYSCALL_ERROR_LABEL;					      \
++  .Lpseudo_end:
++
++
++# ifdef IS_IN_libpthread
++#  define CENABLE_FUNC	__pthread_enable_asynccancel
++#  define CDISABLE_FUNC	__pthread_disable_asynccancel
++#  define __local_multiple_threads __pthread_multiple_threads
++# elif !defined NOT_IN_libc
++#  define CENABLE_FUNC	__libc_enable_asynccancel
++#  define CDISABLE_FUNC	__libc_disable_asynccancel
++#  define __local_multiple_threads __libc_multiple_threads
++# elif defined IS_IN_librt
++#  define CENABLE_FUNC	__librt_enable_asynccancel
++#  define CDISABLE_FUNC	__librt_disable_asynccancel
++# else
++#  error Unsupported library
++# endif
++
++# define CENABLE	movi    a8, CENABLE_FUNC;		\
++			callx8  a8
++# define CDISABLE	movi    a8, CDISABLE_FUNC;		\
++			callx8  a8
++
++# if defined IS_IN_libpthread || !defined NOT_IN_libc
++#  ifndef __ASSEMBLER__
++extern int __local_multiple_threads attribute_hidden;
++#   define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1)
++#  else
++#   define SINGLE_THREAD_P(reg) movi reg, __local_multiple_threads; \
++			        l32i reg, reg, 0;
++#  endif
++
++# else
++#  ifndef __ASSEMBLER__
++#   define SINGLE_THREAD_P \
++	__builtin_expect (THREAD_GETMEM (THREAD_SELF, \
++			  header.multiple_threads) == 0, 1)
++#  else
++#   define SINGLE_THREAD_P(reg) \
++	rur reg, threadptr; \
++	l32i reg, reg, MULTIPLE_THREADS_OFFSET;
++#  endif
++# endif
++
++#else
++
++/* This code should never be used but we define it anyhow.  */
++# define SINGLE_THREAD_P (1)
++# define NO_CANCELLATION 1
++
++#endif
++
++
++#ifndef __ASSEMBLER__
++# define RTLD_SINGLE_THREAD_P \
++  __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
++				   header.multiple_threads) == 0, 1)
++#endif
+diff -Nur uClibc-git/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/vfork.S uClibc-xtensa/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/vfork.S
+--- uClibc-git/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/vfork.S	1970-01-01 01:00:00.000000000 +0100
++++ uClibc-xtensa/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/vfork.S	2014-06-03 12:04:16.669187814 +0200
+@@ -0,0 +1,59 @@
++/* Copyright (C) 2013 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++
++   The GNU C Library is free software; you can redistribute it and/or
++   modify it under the terms of the GNU Lesser General Public
++   License as published by the Free Software Foundation; either
++   version 2.1 of the License, or (at your option) any later version.
++
++   The GNU C Library is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++   Lesser General Public License for more details.
++
++   You should have received a copy of the GNU Lesser General Public
++   License along with the GNU C Library.  If not, see
++   <http://www.gnu.org/licenses/>.  */
++
++#include <tls.h>
++
++/*
++  Save the PID value, save 0x80000000 if PID was 0.
++  Registers a2 and a3 are available; ar should return the PID and as threadptr
++ */
++
++#define SAVE_PID(pid,tp,ar,as)						\
++	rur	tp, threadptr;						\
++	movi	ar, TLS_PRE_TCB_SIZE;					\
++	sub	tp, tp, ar;						\
++	l32i	pid, tp, PID;						\
++	neg	ar, pid;						\
++	movi	as, 0x80000000;						\
++	moveqz	ar, as, ar;						\
++	s32i	ar, tp, PID;						\
++
++/*
++  Restore the PID value, restore to 0 if saved value was 0x80000000
++  Return value from the syscall is in a2.
++ */
++#define RESTORE_PID(pid,tp,res)						\
++	beqz	res, 1f;						\
++	s32i	pid, tp, PID;						\
++1:
++
++/*
++  Special version for call12, where we don't have enough registers
++  available to preserve the original PID.
++ */
++#define RESTORE_PID12(ar, as, at)					\
++	rur	as, threadptr;						\
++	movi	ar, TLS_PRE_TCB_SIZE;					\
++	sub	as, as, ar;						\
++	l32i	ar, as, PID;						\
++	movi	at, 0x80000000;						\
++	sub	at, at, ar;						\
++	neg	ar, ar;							\
++	moveqz	ar, at, at;						\
++	s32i	ar, as, PID;
++
++#include <libc/sysdeps/linux/xtensa/vfork.S>
+diff -Nur uClibc-git/libpthread/nptl/sysdeps/xtensa/dl-tls.h uClibc-xtensa/libpthread/nptl/sysdeps/xtensa/dl-tls.h
+--- uClibc-git/libpthread/nptl/sysdeps/xtensa/dl-tls.h	1970-01-01 01:00:00.000000000 +0100
++++ uClibc-xtensa/libpthread/nptl/sysdeps/xtensa/dl-tls.h	2014-06-03 12:04:16.669187814 +0200
+@@ -0,0 +1,58 @@
++/* Thread-local storage handling in the ELF dynamic linker.  Xtensa version.
++   Copyright (C) 2013 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++
++   The GNU C Library is free software; you can redistribute it and/or
++   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.  */
++
++#ifndef _XTENSA_DL_TLS_H
++#define _XTENSA_DL_TLS_H 1
++
++/* Type used for the representation of TLS information in the GOT.  */
++typedef struct
++{
++  unsigned long int ti_module;
++  unsigned long int ti_offset;
++} tls_index;
++
++extern void *__tls_get_addr (tls_index *ti);
++
++/* Type used to represent a TLS descriptor.  */
++struct tlsdesc
++{
++  union
++    {
++      void *pointer;
++      long value;
++    } argument;
++  ptrdiff_t (*entry)(struct tlsdesc *);
++};
++
++/* Type used as the argument in a TLS descriptor for a symbol that
++   needs dynamic TLS offsets.  */
++struct tlsdesc_dynamic_arg
++{
++  tls_index tlsinfo;
++  size_t gen_count;
++};
++
++extern ptrdiff_t attribute_hidden
++  _dl_tlsdesc_return(struct tlsdesc_dynamic_arg *);
++
++extern void *_dl_make_tlsdesc_dynamic (struct link_map *map, size_t ti_offset);
++extern ptrdiff_t attribute_hidden
++  _dl_tlsdesc_dynamic(struct tlsdesc_dynamic_arg *);
++
++#endif
+diff -Nur uClibc-git/libpthread/nptl/sysdeps/xtensa/jmpbuf-unwind.h uClibc-xtensa/libpthread/nptl/sysdeps/xtensa/jmpbuf-unwind.h
+--- uClibc-git/libpthread/nptl/sysdeps/xtensa/jmpbuf-unwind.h	1970-01-01 01:00:00.000000000 +0100
++++ uClibc-xtensa/libpthread/nptl/sysdeps/xtensa/jmpbuf-unwind.h	2014-06-03 12:04:16.669187814 +0200
+@@ -0,0 +1,32 @@
++/* Copyright (C) 2005,2006 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++
++   The GNU C Library is free software; you can redistribute it and/or
++   modify it under the terms of the GNU Lesser General Public
++   License as published by the Free Software Foundation; either
++   version 2.1 of the License, or (at your option) any later version.
++
++   The GNU C Library is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++   Lesser General Public License for more details.
++
++   You should have received a copy of the GNU Lesser General Public
++   License along with the GNU C Library; if not, see
++   <http://www.gnu.org/licenses/>.  */
++
++#include <setjmp.h>
++#include <stdint.h>
++#include <unwind.h>
++
++/* Test if longjmp to JMPBUF would unwind the frame
++   containing a local variable at ADDRESS.  */
++#undef _JMPBUF_UNWINDS
++#define _JMPBUF_UNWINDS(jmpbuf, address, demangle) \
++  ((void *) (address) < (void *) demangle (jmpbuf[JB_SP]))
++
++#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \
++  _JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), _adj)
++
++#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \
++  ((uintptr_t) (_address) - (_adj) < (uintptr_t) (_jmpbuf)[JB_SP] - (_adj))
+diff -Nur uClibc-git/libpthread/nptl/sysdeps/xtensa/libc-tls.c uClibc-xtensa/libpthread/nptl/sysdeps/xtensa/libc-tls.c
+--- uClibc-git/libpthread/nptl/sysdeps/xtensa/libc-tls.c	1970-01-01 01:00:00.000000000 +0100
++++ uClibc-xtensa/libpthread/nptl/sysdeps/xtensa/libc-tls.c	2014-06-03 12:04:16.669187814 +0200
+@@ -0,0 +1,36 @@
++/* Thread-local storage handling in the ELF dynamic linker.  Xtensa version.
++   Copyright (C) 2005 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++
++   The GNU C Library is free software; you can redistribute it and/or
++   modify it under the terms of the GNU Lesser General Public
++   License as published by the Free Software Foundation; either
++   version 2.1 of the License, or (at your option) any later version.
++
++   The GNU C Library is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++   Lesser General Public License for more details.
++
++   You should have received a copy of the GNU Lesser General Public
++   License along with the GNU C Library; if not, see
++   <http://www.gnu.org/licenses/>.  */
++
++#include <sysdeps/generic/libc-tls.c>
++#include <dl-tls.h>
++
++#if defined(USE_TLS) && USE_TLS
++
++/* On Xtensa, linker optimizations are not required, so __tls_get_addr
++   can be called even in statically linked binaries.  In this case module
++   must be always 1 and PT_TLS segment exist in the binary, otherwise it
++   would not link.  */
++
++void *
++__tls_get_addr (tls_index *ti)
++{
++  dtv_t *dtv = THREAD_DTV ();
++  return (char *) dtv[1].pointer.val + ti->ti_offset;
++}
++
++#endif
+diff -Nur uClibc-git/libpthread/nptl/sysdeps/xtensa/Makefile.arch uClibc-xtensa/libpthread/nptl/sysdeps/xtensa/Makefile.arch
+--- uClibc-git/libpthread/nptl/sysdeps/xtensa/Makefile.arch	1970-01-01 01:00:00.000000000 +0100
++++ uClibc-xtensa/libpthread/nptl/sysdeps/xtensa/Makefile.arch	2014-06-03 12:04:16.669187814 +0200
+@@ -0,0 +1,40 @@
++# Copyright (C) 2012 Free Software Foundation, Inc.
++# This file is part of the GNU C Library.
++#
++# The GNU C Library is free software; you can redistribute it and/or
++# modify it under the terms of the GNU Lesser General Public
++# License as published by the Free Software Foundation; either
++# version 2.1 of the License, or (at your option) any later version.
++#
++# The GNU C Library is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++# Lesser General Public License for more details.
++#
++# You should have received a copy of the GNU Lesser General Public
++# License along with the GNU C Library; if not, write to the Free
++# Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
++# 02111-1307 USA.
++
++CFLAGS-pt-raise.c = -DNOT_IN_libc -DIS_IN_libpthread
++
++ASFLAGS-dl-tlsdesc.S = -DNOT_IN_libc=1
++ASFLAGS-pthread_spin_lock.S = -DNOT_IN_libc -DIS_IN_libpthread
++ASFLAGS-pthread_spin_trylock.S = -DNOT_IN_libc -DIS_IN_libpthread
++ASFLAGS-nptl-sysdep.S = -DNOT_IN_libc -DIS_IN_libpthread	\
++                        -D_LIBC_REENTRANT			\
++                        -I$(top_srcdir)libc/sysdeps/linux/xtensa
++
++libc_arch_a_CSRC = libc-tls.c
++librt_arch_a_SSRC = dl-tlsdesc.S
++
++CFLAGS-gen_tlsdesc.c = -S
++$(libpthread_arch_OUT)/gen_tlsdesc.c: $(libpthread_arch_DIR)/tlsdesc.sym | $(libpthread_arch_OUT)
++	$(do_awk) $(top_srcdir)extra/scripts/gen-as-const.awk $< > $@
++$(libpthread_arch_OUT)/gen_tlsdesc.s: $(libpthread_arch_OUT)/gen_tlsdesc.c | headers
++	$(compile.c)
++libpthread-generated-y += $(libpthread_arch_OUT)/gen_tlsdesc.s
++$(libpthread_arch_OUT)/tlsdesc.h: $(libpthread_arch_OUT)/gen_tlsdesc.s
++	$(do_sed) $(PTHREAD_GENERATE_MANGLE) $< > $@
++	@if test ! -s $@ ; then rm -f $@ ; false ; fi
++pregen-headers-$(UCLIBC_HAS_THREADS_NATIVE) += $(libpthread_arch_OUT)/tlsdesc.h
+diff -Nur uClibc-git/libpthread/nptl/sysdeps/xtensa/pthreaddef.h uClibc-xtensa/libpthread/nptl/sysdeps/xtensa/pthreaddef.h
+--- uClibc-git/libpthread/nptl/sysdeps/xtensa/pthreaddef.h	1970-01-01 01:00:00.000000000 +0100
++++ uClibc-xtensa/libpthread/nptl/sysdeps/xtensa/pthreaddef.h	2014-06-03 12:04:16.669187814 +0200
+@@ -0,0 +1,39 @@
++/* Copyright (C) 2002, 2003, 2005 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.  */
++
++/* Default stack size.  */
++#define ARCH_STACK_DEFAULT_SIZE	(2 * 1024 * 1024)
++
++/* Required stack pointer alignment at beginning.  */
++#define STACK_ALIGN		16
++
++/* Minimal stack size after allocating thread descriptor and guard size.  */
++#define MINIMAL_REST_STACK	2048
++
++/* Alignment requirement for TCB.  */
++#define TCB_ALIGNMENT		16
++
++
++/* Location of current stack frame.  */
++#define CURRENT_STACK_FRAME	__builtin_frame_address (0)
++
++
++/* XXX Until we have a better place keep the definitions here.  */
++
++#define __exit_thread_inline(val) \
++  INLINE_SYSCALL (exit, 1, (val))
+diff -Nur uClibc-git/libpthread/nptl/sysdeps/xtensa/pthread_spin_lock.S uClibc-xtensa/libpthread/nptl/sysdeps/xtensa/pthread_spin_lock.S
+--- uClibc-git/libpthread/nptl/sysdeps/xtensa/pthread_spin_lock.S	1970-01-01 01:00:00.000000000 +0100
++++ uClibc-xtensa/libpthread/nptl/sysdeps/xtensa/pthread_spin_lock.S	2014-06-03 12:04:16.669187814 +0200
+@@ -0,0 +1,37 @@
++/* Copyright (C) 2012 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++
++   The GNU C Library is free software; you can redistribute it and/or
++   modify it under the terms of the GNU Lesser General Public
++   License as published by the Free Software Foundation; either
++   version 2.1 of the License, or (at your option) any later version.
++
++   The GNU C Library is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++   Lesser General Public License for more details.
++
++   You should have received a copy of the GNU Lesser General Public
++   License along with the GNU C Library; if not, write to the Free
++   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
++   02111-1307 USA.  */
++
++	.text
++	.align 4
++
++	.globl pthread_spin_lock
++pthread_spin_lock:
++
++	entry	a1, 16
++
++	movi	a3, 0
++	wsr 	a3, scompare1
++	movi	a3, 1
++1:	s32c1i	a3, a2, 0
++	bnez	a3, 1b
++	movi	a2, 0
++
++	retw
++
++	.type pthread_spin_lock, @function
++	.size pthread_spin_lock, .-pthread_spin_lock
+diff -Nur uClibc-git/libpthread/nptl/sysdeps/xtensa/pthread_spin_trylock.S uClibc-xtensa/libpthread/nptl/sysdeps/xtensa/pthread_spin_trylock.S
+--- uClibc-git/libpthread/nptl/sysdeps/xtensa/pthread_spin_trylock.S	1970-01-01 01:00:00.000000000 +0100
++++ uClibc-xtensa/libpthread/nptl/sysdeps/xtensa/pthread_spin_trylock.S	2014-06-03 12:04:16.669187814 +0200
+@@ -0,0 +1,40 @@
++/* Copyright (C) 2005 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 _ERRNO_H 1
++#include <bits/errno.h>
++
++	.text
++	.align 4
++
++	.globl pthread_spin_trylock
++pthread_spin_trylock:
++
++	entry	a1, 16
++
++	movi	a3, 0
++	wsr 	a3, scompare1
++	movi	a3, 1
++	s32c1i	a3, a2, 0
++	movi	a2, EBUSY
++	moveqz	a2, a3, a3
++
++	retw
++
++	.type pthread_spin_trylock, @function
++	.size pthread_spin_trylock, .-pthread_spin_trylock
+diff -Nur uClibc-git/libpthread/nptl/sysdeps/xtensa/tcb-offsets.sym uClibc-xtensa/libpthread/nptl/sysdeps/xtensa/tcb-offsets.sym
+--- uClibc-git/libpthread/nptl/sysdeps/xtensa/tcb-offsets.sym	1970-01-01 01:00:00.000000000 +0100
++++ uClibc-xtensa/libpthread/nptl/sysdeps/xtensa/tcb-offsets.sym	2014-06-03 12:04:16.669187814 +0200
+@@ -0,0 +1,7 @@
++#include <sysdep.h>
++#include <tls.h>
++
++TLS_PRE_TCB_SIZE	sizeof (struct pthread)
++MULTIPLE_THREADS_OFFSET	offsetof (struct pthread, header.multiple_threads)
++PID			offsetof (struct pthread, pid)
++TID			offsetof (struct pthread, tid)
+diff -Nur uClibc-git/libpthread/nptl/sysdeps/xtensa/tlsdesc.sym uClibc-xtensa/libpthread/nptl/sysdeps/xtensa/tlsdesc.sym
+--- uClibc-git/libpthread/nptl/sysdeps/xtensa/tlsdesc.sym	1970-01-01 01:00:00.000000000 +0100
++++ uClibc-xtensa/libpthread/nptl/sysdeps/xtensa/tlsdesc.sym	2014-06-03 12:04:16.669187814 +0200
+@@ -0,0 +1,10 @@
++#include <stddef.h>
++#include <sysdep.h>
++#include <tls.h>
++#include <link.h>
++#include <dl-tls.h>
++
++TLSDESC_ARG		offsetof(struct tlsdesc, argument)
++TLSDESC_GEN_COUNT	offsetof(struct tlsdesc_dynamic_arg, gen_count)
++TLSDESC_MODID		offsetof(struct tlsdesc_dynamic_arg, tlsinfo.ti_module)
++TLSDESC_MODOFF		offsetof(struct tlsdesc_dynamic_arg, tlsinfo.ti_offset)
+diff -Nur uClibc-git/libpthread/nptl/sysdeps/xtensa/tls.h uClibc-xtensa/libpthread/nptl/sysdeps/xtensa/tls.h
+--- uClibc-git/libpthread/nptl/sysdeps/xtensa/tls.h	1970-01-01 01:00:00.000000000 +0100
++++ uClibc-xtensa/libpthread/nptl/sysdeps/xtensa/tls.h	2014-06-03 12:04:16.669187814 +0200
+@@ -0,0 +1,159 @@
++/* Definition for thread-local data handling.  NPTL/Xtensa version.
++   Copyright (C) 2012 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++
++   The GNU C Library is free software; you can redistribute it and/or
++   modify it under the terms of the GNU Lesser General Public
++   License as published by the Free Software Foundation; either
++   version 2.1 of the License, or (at your option) any later version.
++
++   The GNU C Library is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++   Lesser General Public License for more details.
++
++   You should have received a copy of the GNU Lesser General Public
++   License along with the GNU C Library; if not, write to the Free
++   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
++   02111-1307 USA.  */
++
++#ifndef _TLS_H
++#define _TLS_H
++
++#ifndef __ASSEMBLER__
++
++# include <stdbool.h>
++# include <stddef.h>
++# include <stdint.h>
++
++/* Type for the dtv.  */
++typedef union dtv
++{
++  size_t counter;
++  struct
++  {
++    void *val;
++    bool is_static;
++  } pointer;
++} dtv_t;
++
++
++#else /* __ASSEMBLER__ */
++# include <tcb-offsets.h>
++#endif /* __ASSEMBLER__ */
++
++/* We require TLS support in the tools.  */
++#define HAVE_TLS_SUPPORT                1
++#define HAVE_TLS_MODEL_ATTRIBUTE        1
++#define HAVE___THREAD                   1
++
++/* Signal that TLS support is available.  */
++#define USE_TLS	1
++
++#ifndef __ASSEMBLER__
++
++/* Get system call information.  */
++# include <sysdep.h>
++
++/* The TLS blocks start right after the TCB.  */
++# define TLS_DTV_AT_TP	1
++
++/* Get the thread descriptor definition.  */
++# include <../../descr.h>
++
++typedef struct
++{
++  dtv_t *dtv;
++  void *private;
++} tcbhead_t;
++
++/* This is the size of the initial TCB.  */
++# define TLS_INIT_TCB_SIZE	sizeof (tcbhead_t)
++
++/* Alignment requirements for the initial TCB.  */
++# define TLS_INIT_TCB_ALIGN	16
++
++/* This is the size of the TCB.  */
++# define TLS_TCB_SIZE		sizeof (tcbhead_t)
++
++/* This is the size we need before TCB.  */
++# define TLS_PRE_TCB_SIZE	sizeof (struct pthread)
++
++/* Alignment requirements for the TCB.  */
++# define TLS_TCB_ALIGN		16
++
++
++/* Install the dtv pointer.  The pointer passed is to the element with
++   index -1 which contain the length.  */
++# define INSTALL_DTV(tcbp, dtvp) \
++  (((tcbhead_t *) (tcbp))->dtv = (dtvp) + 1)
++
++/* Install new dtv for current thread.  */
++# define INSTALL_NEW_DTV(dtv)						\
++  ({ tcbhead_t *__tcbp;							\
++     __asm__ __volatile__ ("rur %0, threadptr" : "=r" (__tcbp));	\
++     __tcbp->dtv = (dtv); })						\
++
++/* Return dtv of given thread descriptor.  */
++# define GET_DTV(tcbp) \
++  (((tcbhead_t *) (tcbp))->dtv)
++
++/* Code to initially initialize the thread pointer.  This might need
++   special attention since 'errno' is not yet available and if the
++   operation can cause a failure 'errno' must not be touched.  */
++# define TLS_INIT_TP(tcbp, secondcall)					\
++  ({ __asm__ __volatile__ ("wur %0, threadptr" : : "r" (tcbp)); 0; })
++
++/* Return the address of the dtv for the current thread.  */
++# define THREAD_DTV()							\
++  ({ tcbhead_t *__tcbp;							\
++      __asm__ __volatile__ ("rur %0, threadptr" : "=r" (__tcbp));	\
++      __tcbp->dtv; })
++
++/* Return the thread descriptor for the current thread.  */
++# define THREAD_SELF							\
++ ({ struct pthread *__self;						\
++    __asm__ ("rur %0, threadptr" : "=r" (__self));			\
++    __self - 1; })
++
++/* Magic for libthread_db to know how to do THREAD_SELF.  */
++# define DB_THREAD_SELF \
++  CONST_THREAD_AREA (32, sizeof (struct pthread))
++
++/* Access to data in the thread descriptor is easy.  */
++#define THREAD_GETMEM(descr, member) \
++  descr->member
++#define THREAD_GETMEM_NC(descr, member, idx) \
++  descr->member[idx]
++#define THREAD_SETMEM(descr, member, value) \
++  descr->member = (value)
++#define THREAD_SETMEM_NC(descr, member, idx, value) \
++  descr->member[idx] = (value)
++
++/* Get and set the global scope generation counter in struct pthread.  */
++#define THREAD_GSCOPE_FLAG_UNUSED 0
++#define THREAD_GSCOPE_FLAG_USED   1
++#define THREAD_GSCOPE_FLAG_WAIT   2
++#define THREAD_GSCOPE_RESET_FLAG() \
++  do									     \
++    { int __res								     \
++	= atomic_exchange_rel (&THREAD_SELF->header.gscope_flag,	     \
++			       THREAD_GSCOPE_FLAG_UNUSED);		     \
++      if (__res == THREAD_GSCOPE_FLAG_WAIT)				     \
++	lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1, LLL_PRIVATE);   \
++    }									     \
++  while (0)
++#define THREAD_GSCOPE_SET_FLAG() \
++  do									     \
++    {									     \
++      THREAD_SELF->header.gscope_flag = THREAD_GSCOPE_FLAG_USED;	     \
++      atomic_write_barrier ();						     \
++    }									     \
++  while (0)
++
++#define THREAD_GSCOPE_WAIT() \
++  GL(dl_wait_lookup_done) ()
++
++#endif /* __ASSEMBLER__ */
++
++#endif	/* tls.h */