about summary refs log tree commit diff
path: root/ports/sysdeps/tile
diff options
context:
space:
mode:
authorJoseph Myers <joseph@codesourcery.com>2012-07-01 13:06:41 +0000
committerJoseph Myers <joseph@codesourcery.com>2012-07-01 13:06:41 +0000
commite64ac02c24b43659048622714afdc92fedf561fa (patch)
tree37162878b72d302de351788bec4c9360c9d55f1d /ports/sysdeps/tile
parenta20c2b3c87aebc7d4b090c622d36480263b80042 (diff)
downloadglibc-e64ac02c24b43659048622714afdc92fedf561fa.tar.gz
glibc-e64ac02c24b43659048622714afdc92fedf561fa.tar.xz
glibc-e64ac02c24b43659048622714afdc92fedf561fa.zip
Move all files into ports/ subdirectory in preparation for merge with glibc glibc-2.16-ports-before-merge
Diffstat (limited to 'ports/sysdeps/tile')
-rw-r--r--ports/sysdeps/tile/Implies2
-rw-r--r--ports/sysdeps/tile/Makefile13
-rw-r--r--ports/sysdeps/tile/Versions6
-rw-r--r--ports/sysdeps/tile/__longjmp.S57
-rw-r--r--ports/sysdeps/tile/__tls_get_addr.S150
-rw-r--r--ports/sysdeps/tile/_mcount.S87
-rw-r--r--ports/sysdeps/tile/abort-instr.h2
-rw-r--r--ports/sysdeps/tile/backtrace.c1
-rw-r--r--ports/sysdeps/tile/bits/atomic.h86
-rw-r--r--ports/sysdeps/tile/bits/byteswap.h35
-rw-r--r--ports/sysdeps/tile/bits/endian.h13
-rw-r--r--ports/sysdeps/tile/bits/fenv.h44
-rw-r--r--ports/sysdeps/tile/bits/link.h57
-rw-r--r--ports/sysdeps/tile/bits/mathdef.h48
-rw-r--r--ports/sysdeps/tile/bits/mathinline.h44
-rw-r--r--ports/sysdeps/tile/bits/setjmp.h36
-rw-r--r--ports/sysdeps/tile/bsd-_setjmp.S1
-rw-r--r--ports/sysdeps/tile/bsd-setjmp.S1
-rw-r--r--ports/sysdeps/tile/bzero.S30
-rw-r--r--ports/sysdeps/tile/crti.S111
-rw-r--r--ports/sysdeps/tile/crtn.S55
-rw-r--r--ports/sysdeps/tile/dl-lookupcfg.h27
-rw-r--r--ports/sysdeps/tile/dl-machine.h914
-rw-r--r--ports/sysdeps/tile/dl-runtime.c79
-rw-r--r--ports/sysdeps/tile/dl-start.S114
-rw-r--r--ports/sysdeps/tile/dl-tls.c27
-rw-r--r--ports/sysdeps/tile/dl-tls.h45
-rw-r--r--ports/sysdeps/tile/dl-trampoline.S193
-rw-r--r--ports/sysdeps/tile/fegetenv.c29
-rw-r--r--ports/sysdeps/tile/fegetround.c25
-rw-r--r--ports/sysdeps/tile/feholdexcpt.c27
-rw-r--r--ports/sysdeps/tile/fesetenv.c31
-rw-r--r--ports/sysdeps/tile/fesetround.c26
-rw-r--r--ports/sysdeps/tile/feupdateenv.c27
-rw-r--r--ports/sysdeps/tile/ffs.c44
-rw-r--r--ports/sysdeps/tile/ffsll.c1
-rw-r--r--ports/sysdeps/tile/gccframe.h21
-rw-r--r--ports/sysdeps/tile/jmpbuf-offsets.h62
-rw-r--r--ports/sysdeps/tile/jmpbuf-unwind.h48
-rw-r--r--ports/sysdeps/tile/ldsodefs.h40
-rw-r--r--ports/sysdeps/tile/libm-test-ulps1484
-rw-r--r--ports/sysdeps/tile/machine-gmon.h25
-rw-r--r--ports/sysdeps/tile/math_private.h13
-rw-r--r--ports/sysdeps/tile/nptl/Makefile20
-rw-r--r--ports/sysdeps/tile/nptl/pthread_spin_lock.c56
-rw-r--r--ports/sysdeps/tile/nptl/pthread_spin_trylock.c32
-rw-r--r--ports/sysdeps/tile/nptl/pthreaddef.h41
-rw-r--r--ports/sysdeps/tile/nptl/tcb-offsets.sym17
-rw-r--r--ports/sysdeps/tile/nptl/tls.h194
-rw-r--r--ports/sysdeps/tile/preconfigure17
-rw-r--r--ports/sysdeps/tile/s_fma.c8
-rw-r--r--ports/sysdeps/tile/s_fmaf.c8
-rw-r--r--ports/sysdeps/tile/setjmp.S46
-rw-r--r--ports/sysdeps/tile/shlib-versions2
-rw-r--r--ports/sysdeps/tile/sotruss-lib.c49
-rw-r--r--ports/sysdeps/tile/stackguard-macros.h14
-rw-r--r--ports/sysdeps/tile/stackinfo.h48
-rw-r--r--ports/sysdeps/tile/start.S183
-rw-r--r--ports/sysdeps/tile/sysdep.h111
-rw-r--r--ports/sysdeps/tile/tilegx/bits/atomic.h49
-rw-r--r--ports/sysdeps/tile/tilegx/bits/wordsize.h8
-rw-r--r--ports/sysdeps/tile/tilegx/memchr.c73
-rw-r--r--ports/sysdeps/tile/tilegx/memcpy.c206
-rw-r--r--ports/sysdeps/tile/tilegx/memset.c151
-rw-r--r--ports/sysdeps/tile/tilegx/memusage.h30
-rw-r--r--ports/sysdeps/tile/tilegx/rawmemchr.c45
-rw-r--r--ports/sysdeps/tile/tilegx/strchr.c67
-rw-r--r--ports/sysdeps/tile/tilegx/strchrnul.c64
-rw-r--r--ports/sysdeps/tile/tilegx/string-endian.h45
-rw-r--r--ports/sysdeps/tile/tilegx/strlen.c39
-rw-r--r--ports/sysdeps/tile/tilegx/strrchr.c68
-rw-r--r--ports/sysdeps/tile/tilegx/tilegx32/Implies3
-rw-r--r--ports/sysdeps/tile/tilegx/tilegx64/Implies3
-rw-r--r--ports/sysdeps/tile/tilepro/Implies2
-rw-r--r--ports/sysdeps/tile/tilepro/bits/atomic.h81
-rw-r--r--ports/sysdeps/tile/tilepro/bits/wordsize.h3
-rw-r--r--ports/sysdeps/tile/tilepro/memchr.c72
-rw-r--r--ports/sysdeps/tile/tilepro/memcpy.S397
-rw-r--r--ports/sysdeps/tile/tilepro/memset.c151
-rw-r--r--ports/sysdeps/tile/tilepro/memusage.h29
-rw-r--r--ports/sysdeps/tile/tilepro/rawmemchr.c45
-rw-r--r--ports/sysdeps/tile/tilepro/strchr.c68
-rw-r--r--ports/sysdeps/tile/tilepro/strchrnul.c65
-rw-r--r--ports/sysdeps/tile/tilepro/strlen.c39
-rw-r--r--ports/sysdeps/tile/tilepro/strrchr.c73
-rw-r--r--ports/sysdeps/tile/tls-macros.h84
-rw-r--r--ports/sysdeps/tile/tst-audit.h23
87 files changed, 7010 insertions, 0 deletions
diff --git a/ports/sysdeps/tile/Implies b/ports/sysdeps/tile/Implies
new file mode 100644
index 0000000000..5b29b26128
--- /dev/null
+++ b/ports/sysdeps/tile/Implies
@@ -0,0 +1,2 @@
+ieee754/dbl-64
+ieee754/flt-32
diff --git a/ports/sysdeps/tile/Makefile b/ports/sysdeps/tile/Makefile
new file mode 100644
index 0000000000..3cd4d1e752
--- /dev/null
+++ b/ports/sysdeps/tile/Makefile
@@ -0,0 +1,13 @@
+# We don't support long doubles as a distinct type.  We don't need to set
+# this variable; it's here mostly for documentational purposes.
+
+long-double-fcts = no
+
+ifeq ($(subdir),gmon)
+sysdep_routines += _mcount
+endif
+
+ifeq ($(subdir),elf)
+# Extra shared linker files to link only into dl-allobjs.so.
+sysdep-rtld-routines += dl-start __tls_get_addr
+endif
diff --git a/ports/sysdeps/tile/Versions b/ports/sysdeps/tile/Versions
new file mode 100644
index 0000000000..b275d7ff3b
--- /dev/null
+++ b/ports/sysdeps/tile/Versions
@@ -0,0 +1,6 @@
+libc {
+  GLIBC_2.12 {
+    # name requested by gcc community.
+    __mcount;
+  }
+}
diff --git a/ports/sysdeps/tile/__longjmp.S b/ports/sysdeps/tile/__longjmp.S
new file mode 100644
index 0000000000..2e41a1d627
--- /dev/null
+++ b/ports/sysdeps/tile/__longjmp.S
@@ -0,0 +1,57 @@
+/* Copyright (C) 2011 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+
+   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 <jmpbuf-offsets.h>
+#include <asm-syntax.h>
+#include <arch/spr_def.h>
+
+/* PL to return to via iret in longjmp */
+#define RETURN_PL 0
+
+	.text
+ENTRY (__longjmp)
+	FEEDBACK_ENTER(__longjmp)
+
+#define RESTORE(r) { LD r, r0 ; ADDI_PTR r0, r0, REGSIZE }
+	FOR_EACH_CALLEE_SAVED_REG(RESTORE)
+
+	/* Make longjmp(buf, 0) return "1" instead.
+	   At the same time, construct our iret context; we set ICS so
+	   we can validly load EX_CONTEXT for iret without being
+	   interrupted halfway through.  */
+	{
+	 LD r2, r0   /* retrieve ICS bit from jmp_buf */
+	 movei r3, 1
+	 CMPEQI r0, r1, 0
+	}
+	{
+	 mtspr INTERRUPT_CRITICAL_SECTION, r3
+	 shli r2, r2, SPR_EX_CONTEXT_0_1__ICS_SHIFT
+	}
+	{
+	 mtspr EX_CONTEXT_0_0, lr
+	 ori r2, r2, RETURN_PL
+	}
+	{
+	 or r0, r1, r0
+	 mtspr EX_CONTEXT_0_1, r2
+	}
+	iret
+	jrp lr   /* Keep the backtracer happy. */
+END (__longjmp)
diff --git a/ports/sysdeps/tile/__tls_get_addr.S b/ports/sysdeps/tile/__tls_get_addr.S
new file mode 100644
index 0000000000..74e4fa2c26
--- /dev/null
+++ b/ports/sysdeps/tile/__tls_get_addr.S
@@ -0,0 +1,150 @@
+/* Copyright (C) 2011-2012 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+
+   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 <bits/wordsize.h>
+
+#if __WORDSIZE == 64
+#define LOG_SIZEOF_DTV_T 4
+#else
+#define LOG_SIZEOF_DTV_T 3
+#endif
+
+/* On entry, r0 points to two words, the module and the offset.
+   On return, r0 holds the pointer to the relevant TLS memory.
+   Only registers r25..r29 are clobbered by the call.  */
+
+	.text
+ENTRY (__tls_get_addr)
+	{
+	 lnk r25
+	 ADDI_PTR r27, tp, DTV_OFFSET
+	}
+.Llnk:
+#ifdef __tilegx__
+	{
+	 LD_PTR r27, r27	/* r27 = THREAD_DTV() */
+	 moveli r26, hw1_last(_rtld_local + TLS_GENERATION_OFFSET - .Llnk)
+	}
+	shl16insli r26, r26, hw0(_rtld_local + TLS_GENERATION_OFFSET - .Llnk)
+	{
+	 ADD_PTR r25, r25, r26
+	 LD_PTR r26, r0		/* r26 = ti_module */
+	}
+#else
+	{
+	 LD_PTR r27, r27	/* r27 = THREAD_DTV() */
+	 addli r25, r25, lo16(_rtld_local + TLS_GENERATION_OFFSET - .Llnk)
+	}
+	{
+	 auli r25, r25, ha16(_rtld_local + TLS_GENERATION_OFFSET - .Llnk)
+	 LD_PTR r26, r0		/* r26 = ti_module */
+	}
+#endif
+	LD_PTR r25, r25		/* r25 = DL(dl_tls_generation) */
+	{
+	 LD_PTR r28, r27	/* r28 = THREAD_DTV()->counter */
+	 ADDI_PTR r29, r0, __SIZEOF_POINTER__
+	}
+	{
+	 LD_PTR r29, r29	/* r29 = ti_offset */
+	 CMPEQ r25, r28, r25	/* r25 nonzero if generation OK */
+	 shli r28, r26, LOG_SIZEOF_DTV_T  /* byte index into dtv array */
+	}
+	{
+	 BEQZ r25, .Lslowpath
+	 CMPEQI r25, r26, -1	/* r25 nonzero if ti_module invalid */
+	}
+	{
+	 BNEZ r25, .Lslowpath
+	 ADD_PTR r28, r28, r27	/* pointer into module array */
+	}
+	LD_PTR r26, r28		/* r26 = module TLS pointer */
+	{
+	 ADD_PTR r0, r26, r29
+	 jrp lr
+	}
+
+.Lslowpath:
+	{
+	 ST sp, lr
+	 ADDLI_PTR r29, sp, - (25 * REGSIZE)
+	}
+	cfi_offset (lr, 0)
+	{
+	 ST r29, sp
+	 ADDLI_PTR sp, sp, - (26 * REGSIZE)
+	}
+	cfi_def_cfa_offset (26 * REGSIZE)
+	ADDI_PTR r29, sp, (2 * REGSIZE)
+	{ ST r29, r1;  ADDI_PTR r29, r29, REGSIZE }
+	{ ST r29, r2;  ADDI_PTR r29, r29, REGSIZE }
+	{ ST r29, r3;  ADDI_PTR r29, r29, REGSIZE }
+	{ ST r29, r4;  ADDI_PTR r29, r29, REGSIZE }
+	{ ST r29, r5;  ADDI_PTR r29, r29, REGSIZE }
+	{ ST r29, r6;  ADDI_PTR r29, r29, REGSIZE }
+	{ ST r29, r7;  ADDI_PTR r29, r29, REGSIZE }
+	{ ST r29, r8;  ADDI_PTR r29, r29, REGSIZE }
+	{ ST r29, r9;  ADDI_PTR r29, r29, REGSIZE }
+	{ ST r29, r10; ADDI_PTR r29, r29, REGSIZE }
+	{ ST r29, r11; ADDI_PTR r29, r29, REGSIZE }
+	{ ST r29, r12; ADDI_PTR r29, r29, REGSIZE }
+	{ ST r29, r13; ADDI_PTR r29, r29, REGSIZE }
+	{ ST r29, r14; ADDI_PTR r29, r29, REGSIZE }
+	{ ST r29, r15; ADDI_PTR r29, r29, REGSIZE }
+	{ ST r29, r16; ADDI_PTR r29, r29, REGSIZE }
+	{ ST r29, r17; ADDI_PTR r29, r29, REGSIZE }
+	{ ST r29, r18; ADDI_PTR r29, r29, REGSIZE }
+	{ ST r29, r19; ADDI_PTR r29, r29, REGSIZE }
+	{ ST r29, r20; ADDI_PTR r29, r29, REGSIZE }
+	{ ST r29, r21; ADDI_PTR r29, r29, REGSIZE }
+	{ ST r29, r22; ADDI_PTR r29, r29, REGSIZE }
+	{ ST r29, r23; ADDI_PTR r29, r29, REGSIZE }
+	{ ST r29, r24; ADDI_PTR r29, r29, REGSIZE }
+	.hidden __tls_get_addr_slow
+	jal __tls_get_addr_slow
+	ADDI_PTR r29, sp, (2 * REGSIZE)
+	{ LD r1,  r29; ADDI_PTR r29, r29, REGSIZE }
+	{ LD r2,  r29; ADDI_PTR r29, r29, REGSIZE }
+	{ LD r3,  r29; ADDI_PTR r29, r29, REGSIZE }
+	{ LD r4,  r29; ADDI_PTR r29, r29, REGSIZE }
+	{ LD r5,  r29; ADDI_PTR r29, r29, REGSIZE }
+	{ LD r6,  r29; ADDI_PTR r29, r29, REGSIZE }
+	{ LD r7,  r29; ADDI_PTR r29, r29, REGSIZE }
+	{ LD r8,  r29; ADDI_PTR r29, r29, REGSIZE }
+	{ LD r9,  r29; ADDI_PTR r29, r29, REGSIZE }
+	{ LD r10, r29; ADDI_PTR r29, r29, REGSIZE }
+	{ LD r11, r29; ADDI_PTR r29, r29, REGSIZE }
+	{ LD r12, r29; ADDI_PTR r29, r29, REGSIZE }
+	{ LD r13, r29; ADDI_PTR r29, r29, REGSIZE }
+	{ LD r14, r29; ADDI_PTR r29, r29, REGSIZE }
+	{ LD r15, r29; ADDI_PTR r29, r29, REGSIZE }
+	{ LD r16, r29; ADDI_PTR r29, r29, REGSIZE }
+	{ LD r17, r29; ADDI_PTR r29, r29, REGSIZE }
+	{ LD r18, r29; ADDI_PTR r29, r29, REGSIZE }
+	{ LD r19, r29; ADDI_PTR r29, r29, REGSIZE }
+	{ LD r20, r29; ADDI_PTR r29, r29, REGSIZE }
+	{ LD r21, r29; ADDI_PTR r29, r29, REGSIZE }
+	{ LD r22, r29; ADDI_PTR r29, r29, REGSIZE }
+	{ LD r23, r29; ADDI_PTR r29, r29, REGSIZE }
+	{ LD r24, r29; ADDLI_PTR sp, sp, (26 * REGSIZE) }
+	cfi_def_cfa_offset (0)
+	LD lr, sp
+	jrp lr
+END (__tls_get_addr)
diff --git a/ports/sysdeps/tile/_mcount.S b/ports/sysdeps/tile/_mcount.S
new file mode 100644
index 0000000000..4754639c91
--- /dev/null
+++ b/ports/sysdeps/tile/_mcount.S
@@ -0,0 +1,87 @@
+/* Copyright (C) 2011 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+   Based on work contributed by David Mosberger (davidm@cs.arizona.edu).
+
+   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/>.  */
+
+/* Assembly stub to invoke __mcount_internal().  Compiler-generated
+   code calls mcount after executing a function's prologue, placing
+   the "lr" register in "r10" for the call.  As a result "lr" is the
+   function that invoked mcount, and "r10" is mcount's caller's
+   caller.  However, we have to save all the parameter registers here
+   before invoking _mcount_internal.  Callee-save and temporary
+   registers need no special attention.  We save r10 and restore it to
+   lr on the way out, to properly handle the case of ENTRY() in
+   assembly code, before lr is saved.  We use the name __mcount since
+   the gcc community prefers using the reserved namespace.  */
+
+#include <sysdep.h>
+
+	.text
+ENTRY(__mcount)
+	{
+	 ST sp, lr
+	 ADDI_PTR r29, sp, - (12 * REGSIZE)
+	}
+	cfi_offset (lr, 0)
+	{
+	 ADDI_PTR sp, sp, - (13 * REGSIZE)
+	 ST r29, sp
+	 ADDI_PTR r29, r29, REGSIZE
+	}
+	cfi_def_cfa_offset (13 * REGSIZE)
+	{ ST r29, r0; ADDI_PTR r29, r29, REGSIZE }
+	{ ST r29, r1; ADDI_PTR r29, r29, REGSIZE }
+	{ ST r29, r2; ADDI_PTR r29, r29, REGSIZE }
+	{ ST r29, r3; ADDI_PTR r29, r29, REGSIZE }
+	{ ST r29, r4; ADDI_PTR r29, r29, REGSIZE }
+	{ ST r29, r5; ADDI_PTR r29, r29, REGSIZE }
+	{ ST r29, r6; ADDI_PTR r29, r29, REGSIZE }
+	{ ST r29, r7; ADDI_PTR r29, r29, REGSIZE }
+	{ ST r29, r8; ADDI_PTR r29, r29, REGSIZE }
+	{ ST r29, r9; ADDI_PTR r29, r29, REGSIZE }
+	{ ST r29, r10; ADDI_PTR r29, r29, REGSIZE; move r0, r10 }
+	{
+	 move r1, lr
+	 jal __mcount_internal
+	}
+	{
+	 ADDI_PTR r29, sp, (2 * REGSIZE)
+	}
+	{ LD r0, r29; ADDI_PTR r29, r29, REGSIZE }
+	{ LD r1, r29; ADDI_PTR r29, r29, REGSIZE }
+	{ LD r2, r29; ADDI_PTR r29, r29, REGSIZE }
+	{ LD r3, r29; ADDI_PTR r29, r29, REGSIZE }
+	{ LD r4, r29; ADDI_PTR r29, r29, REGSIZE }
+	{ LD r5, r29; ADDI_PTR r29, r29, REGSIZE }
+	{ LD r6, r29; ADDI_PTR r29, r29, REGSIZE }
+	{ LD r7, r29; ADDI_PTR r29, r29, REGSIZE }
+	{ LD r8, r29; ADDI_PTR r29, r29, REGSIZE }
+	{ LD r9, r29; ADDI_PTR r29, r29, REGSIZE }
+	{ LD r10, r29; ADDI_PTR sp, sp, (13 * REGSIZE) }
+	cfi_def_cfa_offset (0)
+	{
+	 LD lr, sp
+	}
+	{
+	 move lr, r10
+	 jrp lr
+	}
+END(__mcount)
+
+#undef mcount
+weak_alias (__mcount, _mcount)   /* exported in gmon/Versions */
+weak_alias (__mcount, mcount)    /* exported in stdlib/Versions */
diff --git a/ports/sysdeps/tile/abort-instr.h b/ports/sysdeps/tile/abort-instr.h
new file mode 100644
index 0000000000..0f57da5198
--- /dev/null
+++ b/ports/sysdeps/tile/abort-instr.h
@@ -0,0 +1,2 @@
+/* An instruction which should crash any program is `hlt'.  */
+#define ABORT_INSTRUCTION asm ("ill")
diff --git a/ports/sysdeps/tile/backtrace.c b/ports/sysdeps/tile/backtrace.c
new file mode 100644
index 0000000000..27ce597b39
--- /dev/null
+++ b/ports/sysdeps/tile/backtrace.c
@@ -0,0 +1 @@
+#include <sysdeps/x86_64/backtrace.c>
diff --git a/ports/sysdeps/tile/bits/atomic.h b/ports/sysdeps/tile/bits/atomic.h
new file mode 100644
index 0000000000..cb96004fc8
--- /dev/null
+++ b/ports/sysdeps/tile/bits/atomic.h
@@ -0,0 +1,86 @@
+/* Copyright (C) 2011 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+
+   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/>.  */
+
+/* The sub-architecture headers provide definitions for these macros
+   that work for "int" and "long" size values only:
+
+   atomic_compare_and_exchange_val_acq()
+   atomic_exchange_acq()
+   atomic_exchange_and_add()
+   atomic_and_val()
+   atomic_or_val()
+   atomic_decrement_if_positive() [tilegx only]
+
+   Here we provide generic definitions true for all Tilera chips.  */
+
+#include <stdint.h>
+#include <features.h>
+
+typedef int32_t atomic32_t;
+typedef uint32_t uatomic32_t;
+typedef int_fast32_t atomic_fast32_t;
+typedef uint_fast32_t uatomic_fast32_t;
+
+typedef int64_t atomic64_t;
+typedef uint64_t uatomic64_t;
+typedef int_fast64_t atomic_fast64_t;
+typedef uint_fast64_t uatomic_fast64_t;
+
+typedef intptr_t atomicptr_t;
+typedef uintptr_t uatomicptr_t;
+typedef intmax_t atomic_max_t;
+typedef uintmax_t uatomic_max_t;
+
+/* Barrier macro. */
+#define atomic_full_barrier() __sync_synchronize()
+
+/* APIs with "release" semantics. */
+#define atomic_compare_and_exchange_val_rel(mem, n, o)          \
+  ({                                                            \
+    atomic_full_barrier ();                                     \
+    atomic_compare_and_exchange_val_acq ((mem), (n), (o));      \
+  })
+#define atomic_compare_and_exchange_bool_rel(mem, n, o)         \
+  ({                                                            \
+    atomic_full_barrier ();                                     \
+    atomic_compare_and_exchange_bool_acq ((mem), (n), (o));     \
+  })
+#define atomic_exchange_rel(mem, n)                             \
+  ({                                                            \
+    atomic_full_barrier ();                                     \
+    atomic_exchange_acq ((mem), (n));                           \
+  })
+
+/* Various macros that should just be synonyms. */
+#define catomic_exchange_and_add atomic_exchange_and_add
+#define atomic_and(mem, mask) ((void) atomic_and_val ((mem), (mask)))
+#define catomic_and atomic_and
+#define atomic_or(mem, mask) ((void) atomic_or_val ((mem), (mask)))
+#define catomic_or atomic_or
+
+/* atomic_bit_test_set in terms of atomic_or_val. */
+#define atomic_bit_test_set(mem, bit)                                   \
+  ({ __typeof (*(mem)) __att0_mask = ((__typeof (*(mem))) 1 << (bit));  \
+    atomic_or_val ((mem), __att0_mask) & __att0_mask; })
+
+/*
+ * This non-existent symbol is called for unsupporrted sizes,
+ * indicating a bug in the caller.
+ */
+extern int __atomic_error_bad_argument_size(void)
+  __attribute__ ((warning ("bad sizeof atomic argument")));
diff --git a/ports/sysdeps/tile/bits/byteswap.h b/ports/sysdeps/tile/bits/byteswap.h
new file mode 100644
index 0000000000..8e610c6fc8
--- /dev/null
+++ b/ports/sysdeps/tile/bits/byteswap.h
@@ -0,0 +1,35 @@
+/* Copyright (C) 2011 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#if !defined _BYTESWAP_H && !defined _NETINET_IN_H && !defined _ENDIAN_H
+# error "Never use <bits/byteswap.h> directly; include <byteswap.h> instead."
+#endif
+
+#ifndef _BITS_BYTESWAP_H
+#define _BITS_BYTESWAP_H 1
+
+/* gcc __builtin_bswap64() can constant-fold, etc, so always use it. */
+#define __bswap_16(x) ((unsigned short)(__builtin_bswap32(x) >> 16))
+#define __bswap_32(x) ((unsigned int)__builtin_bswap32(x))
+#define __bswap_64(x) ((unsigned long long)__builtin_bswap64(x))
+
+#define __bswap_constant_16(x) __bswap_16(x)
+#define __bswap_constant_32(x) __bswap_32(x)
+#define __bswap_constant_64(x) __bswap_64(x)
+
+#endif /* _BITS_BYTESWAP_H */
diff --git a/ports/sysdeps/tile/bits/endian.h b/ports/sysdeps/tile/bits/endian.h
new file mode 100644
index 0000000000..43d94bb7a7
--- /dev/null
+++ b/ports/sysdeps/tile/bits/endian.h
@@ -0,0 +1,13 @@
+/* Set endianness for tile.  */
+
+#ifndef _ENDIAN_H
+# error "Never use <bits/endian.h> directly; include <endian.h> instead."
+#endif
+
+#if defined __BIG_ENDIAN__
+# define __BYTE_ORDER __BIG_ENDIAN
+#elif defined __LITTLE_ENDIAN__
+# define __BYTE_ORDER __LITTLE_ENDIAN
+#else
+# error "Endianness not declared!!"
+#endif
diff --git a/ports/sysdeps/tile/bits/fenv.h b/ports/sysdeps/tile/bits/fenv.h
new file mode 100644
index 0000000000..7638e8cc50
--- /dev/null
+++ b/ports/sysdeps/tile/bits/fenv.h
@@ -0,0 +1,44 @@
+/* Copyright (C) 2011 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+
+   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 _FENV_H
+# error "Never use <bits/fenv.h> directly; include <fenv.h> instead."
+#endif
+
+/* The TILE-Gx hardware does not provide floating-point exception
+   handling, and TILEPro does not support any floating-point operations.  */
+#define FE_ALL_EXCEPT 0
+
+/* TILE-Gx supports only round-to-nearest.  The software
+   floating-point support also acts this way.  */
+enum
+  {
+    __FE_UNDEFINED = 0,
+
+    FE_TONEAREST = 1,
+#define FE_TONEAREST	FE_TONEAREST
+  };
+
+/* Type representing exception flags (if there were any).  */
+typedef unsigned int fexcept_t;
+
+/* Type representing floating-point environment.  */
+typedef unsigned int fenv_t;
+
+/* If the default argument is used we use this value.  */
+#define FE_DFL_ENV	((const fenv_t *) -1l)
diff --git a/ports/sysdeps/tile/bits/link.h b/ports/sysdeps/tile/bits/link.h
new file mode 100644
index 0000000000..3cc8c1e837
--- /dev/null
+++ b/ports/sysdeps/tile/bits/link.h
@@ -0,0 +1,57 @@
+/* Copyright (C) 2011 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+
+   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	_LINK_H
+# error "Never include <bits/link.h> directly; use <link.h> instead."
+#endif
+
+#define __need_int_reg_t
+#include <arch/abi.h>
+
+
+/* Registers for entry into PLT.  */
+typedef struct La_tile_regs
+{
+  __uint_reg_t lr_reg[10];
+} La_tile_regs;
+
+/* Return values for calls from PLT.  */
+typedef struct La_tile_retval
+{
+  /* Up to ten registers can be used for a return value (e.g. small struct). */
+  __uint_reg_t lrv_reg[10];
+} La_tile_retval;
+
+
+__BEGIN_DECLS
+
+extern ElfW(Addr) la_tile_gnu_pltenter (ElfW(Sym) *__sym, unsigned int __ndx,
+                                        uintptr_t *__refcook,
+                                        uintptr_t *__defcook,
+                                        La_tile_regs *__regs,
+                                        unsigned int *__flags,
+                                        const char *__symname,
+                                        long int *__framesizep);
+extern unsigned int la_tile_gnu_pltexit (ElfW(Sym) *__sym, unsigned int __ndx,
+                                         uintptr_t *__refcook,
+                                         uintptr_t *__defcook,
+                                         const La_tile_regs *__inregs,
+                                         La_tile_retval *__outregs,
+                                         const char *__symname);
+
+__END_DECLS
diff --git a/ports/sysdeps/tile/bits/mathdef.h b/ports/sysdeps/tile/bits/mathdef.h
new file mode 100644
index 0000000000..bf0da5e438
--- /dev/null
+++ b/ports/sysdeps/tile/bits/mathdef.h
@@ -0,0 +1,48 @@
+/* Copyright (C) 2011 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#if !defined _MATH_H && !defined _COMPLEX_H
+# error "Never use <bits/mathdef.h> directly; include <math.h> instead"
+#endif
+
+#if defined __USE_ISOC99 && defined _MATH_H && !defined _MATH_H_MATHDEF
+# define _MATH_H_MATHDEF	1
+
+/* "float" and "double" expressions evaluated as "float" and "double". */
+typedef float float_t;
+typedef double double_t;
+
+/* The values returned by `ilogb' for 0 and NaN respectively.  */
+# define FP_ILOGB0	(-2147483647)
+# define FP_ILOGBNAN	(2147483647)
+
+/* The GCC 4.6 compiler will define __FP_FAST_FMA{,F,L} if the fma{,f,l}
+   builtins are supported.  */
+# if __FP_FAST_FMA
+#  define FP_FAST_FMA 1
+# endif
+
+# if __FP_FAST_FMAF
+#  define FP_FAST_FMAF 1
+# endif
+
+# if __FP_FAST_FMAL
+#  define FP_FAST_FMAL 1
+# endif
+
+#endif /* ISO C99 */
diff --git a/ports/sysdeps/tile/bits/mathinline.h b/ports/sysdeps/tile/bits/mathinline.h
new file mode 100644
index 0000000000..4c021f7757
--- /dev/null
+++ b/ports/sysdeps/tile/bits/mathinline.h
@@ -0,0 +1,44 @@
+/* Copyright (C) 2011 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+
+   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 _MATH_H
+# error "Never use <bits/mathinline.h> directly; include <math.h> instead."
+#endif
+
+#ifndef __extern_always_inline
+# define __MATH_INLINE __inline
+#else
+# define __MATH_INLINE __extern_always_inline
+#endif
+
+
+#if defined __USE_ISOC99 && defined __GNUC__
+
+/* Test for negative number.  Used in the signbit() macro.  */
+__MATH_INLINE int
+__NTH (__signbitf (float __x))
+{
+  return __builtin_signbitf (__x);
+}
+__MATH_INLINE int
+__NTH (__signbit (double __x))
+{
+  return __builtin_signbit (__x);
+}
+
+#endif
diff --git a/ports/sysdeps/tile/bits/setjmp.h b/ports/sysdeps/tile/bits/setjmp.h
new file mode 100644
index 0000000000..513c73474c
--- /dev/null
+++ b/ports/sysdeps/tile/bits/setjmp.h
@@ -0,0 +1,36 @@
+/* Copyright (C) 2011 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* Define the machine-dependent type `jmp_buf'.  TILE version.  */
+#ifndef _BITS_SETJMP_H
+#define _BITS_SETJMP_H	1
+
+#if !defined _SETJMP_H && !defined _PTHREAD_H
+# error "Never include <bits/setjmp.h> directly; use <setjmp.h> instead."
+#endif
+
+#ifndef _ASM
+
+#define __need_int_reg_t
+#include <arch/abi.h>
+
+typedef __uint_reg_t __jmp_buf[32];
+
+#endif
+
+#endif /* bits/setjmp.h */
diff --git a/ports/sysdeps/tile/bsd-_setjmp.S b/ports/sysdeps/tile/bsd-_setjmp.S
new file mode 100644
index 0000000000..4e6a2da560
--- /dev/null
+++ b/ports/sysdeps/tile/bsd-_setjmp.S
@@ -0,0 +1 @@
+/* _setjmp is in setjmp.S  */
diff --git a/ports/sysdeps/tile/bsd-setjmp.S b/ports/sysdeps/tile/bsd-setjmp.S
new file mode 100644
index 0000000000..1da848d2f1
--- /dev/null
+++ b/ports/sysdeps/tile/bsd-setjmp.S
@@ -0,0 +1 @@
+/* setjmp is in setjmp.S  */
diff --git a/ports/sysdeps/tile/bzero.S b/ports/sysdeps/tile/bzero.S
new file mode 100644
index 0000000000..407233e8cc
--- /dev/null
+++ b/ports/sysdeps/tile/bzero.S
@@ -0,0 +1,30 @@
+/* Copyright (C) 2011 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+
+   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>
+
+	.text
+ENTRY(__bzero)
+	FEEDBACK_ENTER(__bzero)
+	{
+	 move r2, r1
+	 move r1, zero
+	}
+	j __memset
+END(__bzero)
+weak_alias (__bzero, bzero)
diff --git a/ports/sysdeps/tile/crti.S b/ports/sysdeps/tile/crti.S
new file mode 100644
index 0000000000..ccb4464bb7
--- /dev/null
+++ b/ports/sysdeps/tile/crti.S
@@ -0,0 +1,111 @@
+/* Special .init and .fini section support for tile.
+   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.
+
+   In addition to the permissions in the GNU Lesser General Public
+   License, the Free Software Foundation gives you unlimited
+   permission to link the compiled version of this file with other
+   programs, and to distribute those programs without any restriction
+   coming from the use of this file. (The GNU Lesser General Public
+   License restrictions do apply in other respects; for example, they
+   cover modification of the file, and distribution when not linked
+   into another program.)
+
+   Note that people who make modified versions of this file are not
+   obligated to grant this special exception for their modified
+   versions; it is their choice whether to do so. The GNU Lesser
+   General Public License gives permission to release a modified
+   version without this exception; this exception also makes it
+   possible to release a modified version which carries forward this
+   exception.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* 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.  The symbols _init and _fini are
+   magic and cause the linker to emit DT_INIT and DT_FINI.  */
+
+#include <libc-symbols.h>
+#include <sysdep.h>
+
+#ifndef PREINIT_FUNCTION
+# define PREINIT_FUNCTION __gmon_start__
+#endif
+
+#ifndef PREINIT_FUNCTION_WEAK
+# define PREINIT_FUNCTION_WEAK 1
+#endif
+
+#if PREINIT_FUNCTION_WEAK
+	weak_extern (PREINIT_FUNCTION)
+#else
+	.hidden PREINIT_FUNCTION
+#endif
+
+	.section .init,"ax",@progbits
+	.align 8
+	.globl _init
+	.type _init, @function
+_init:
+	{
+	 move r29, sp
+	 ADDI_PTR r28, sp, -REGSIZE
+	 ST sp, lr
+	}
+	ADDI_PTR sp, sp, -(2 * REGSIZE)
+	ST r28, r29
+#if PREINIT_FUNCTION_WEAK
+	lnk r2
+0:
+#ifdef __tilegx__
+	{
+	 moveli r1, hw1_last(_GLOBAL_OFFSET_TABLE_ - 0b)
+	 moveli r0, hw1_last_got(PREINIT_FUNCTION)
+	}
+	{
+	 shl16insli r1, r1, hw0(_GLOBAL_OFFSET_TABLE_ - 0b)
+	 shl16insli r0, r0, hw0_got(PREINIT_FUNCTION)
+	}
+#else
+	{
+	 moveli r1, lo16(_GLOBAL_OFFSET_TABLE_ - 0b)
+	 moveli r0, got_lo16(PREINIT_FUNCTION)
+	}
+	{
+	 auli r1, r1, ha16(_GLOBAL_OFFSET_TABLE_ - 0b)
+	 auli r0, r0, got_ha16(PREINIT_FUNCTION)
+	}
+#endif
+	ADD_PTR r0, r0, r1
+	ADD_PTR r0, r0, r2
+	LD_PTR r0, r0
+	BEQZ r0, .Lno_weak_fn
+#endif
+	jal plt(PREINIT_FUNCTION)
+.Lno_weak_fn:
+
+	.section .fini,"ax",@progbits
+	.align 8
+	.globl _fini
+	.type _fini, @function
+_fini:
+	{
+	 move r29, sp
+	 ADDI_PTR r28, sp, -REGSIZE
+	 ST sp, lr
+	}
+	ADDI_PTR sp, sp, -(2 * REGSIZE)
+	ST r28, r29
diff --git a/ports/sysdeps/tile/crtn.S b/ports/sysdeps/tile/crtn.S
new file mode 100644
index 0000000000..06931a119e
--- /dev/null
+++ b/ports/sysdeps/tile/crtn.S
@@ -0,0 +1,55 @@
+/* Special .init and .fini section support for tile.
+   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.
+
+   In addition to the permissions in the GNU Lesser General Public
+   License, the Free Software Foundation gives you unlimited
+   permission to link the compiled version of this file with other
+   programs, and to distribute those programs without any restriction
+   coming from the use of this file. (The GNU Lesser General Public
+   License restrictions do apply in other respects; for example, they
+   cover modification of the file, and distribution when not linked
+   into another program.)
+
+   Note that people who make modified versions of this file are not
+   obligated to grant this special exception for their modified
+   versions; it is their choice whether to do so. The GNU Lesser
+   General Public License gives permission to release a modified
+   version without this exception; this exception also makes it
+   possible to release a modified version which carries forward this
+   exception.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* crtn.S puts function epilogues in the .init and .fini sections
+   corresponding to the prologues in crti.S. */
+
+#include <sysdep.h>
+
+	.section .init,"ax",@progbits
+	ADDI_PTR r29, sp, (2 * REGSIZE)
+	{
+	 ADDI_PTR sp, sp, (2 * REGSIZE)
+	 LD lr, r29
+	}
+	jrp lr
+
+	.section .fini,"ax",@progbits
+	ADDI_PTR r29, sp, (2 * REGSIZE)
+	{
+	 ADDI_PTR sp, sp, (2 * REGSIZE)
+	 LD lr, r29
+	}
+	jrp lr
diff --git a/ports/sysdeps/tile/dl-lookupcfg.h b/ports/sysdeps/tile/dl-lookupcfg.h
new file mode 100644
index 0000000000..a198c8b163
--- /dev/null
+++ b/ports/sysdeps/tile/dl-lookupcfg.h
@@ -0,0 +1,27 @@
+/* Copyright (C) 2011 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#define DL_UNMAP_IS_SPECIAL
+
+#include_next <dl-lookupcfg.h>
+
+struct link_map;
+
+void internal_function _dl_unmap (struct link_map *map);
+
+#define DL_UNMAP(map) _dl_unmap (map)
diff --git a/ports/sysdeps/tile/dl-machine.h b/ports/sysdeps/tile/dl-machine.h
new file mode 100644
index 0000000000..c4413f9e8a
--- /dev/null
+++ b/ports/sysdeps/tile/dl-machine.h
@@ -0,0 +1,914 @@
+/* Copyright (C) 2011-2012 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+   Based on work contributed by by Carl Pederson & Martin Schwidefsky.
+
+   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 dl_machine_h
+#define dl_machine_h
+
+#ifdef __tilegx__
+#define ELF_MACHINE_NAME "tilegx"
+#else
+#define ELF_MACHINE_NAME "tilepro"
+#endif
+
+#include <sys/param.h>
+#include <string.h>
+#include <link.h>
+#include <bits/wordsize.h>
+#include <arch/icache.h>
+#include <arch/opcode.h>
+
+/* Return nonzero iff ELF header is compatible with the running host.  */
+static inline int
+elf_machine_matches_host (const ElfW(Ehdr) *ehdr)
+{
+#if defined __tilegx__
+  if (ehdr->e_machine != EM_TILEGX)
+    return 0;
+# if __WORDSIZE == 32
+  return (ehdr->e_ident[EI_CLASS] == ELFCLASS32);
+# else
+  return (ehdr->e_ident[EI_CLASS] == ELFCLASS64);
+# endif
+#elif defined __tilepro__
+  return ehdr->e_machine == EM_TILEPRO;
+#else
+# error "Unknown tile architecture."
+#endif
+}
+
+
+/* Return the link-time address of _DYNAMIC.  Conveniently, this is the
+   first element of the GOT.  This must be inlined in a function which
+   uses global data.  */
+
+static inline ElfW(Addr)
+elf_machine_dynamic (void)
+{
+  ElfW(Addr) *got;
+
+#ifdef __tilegx__
+  ElfW(Addr) tmp;
+  asm( "	{ lnk %0; moveli %1, hw2_last(_GLOBAL_OFFSET_TABLE_ - 1f) }\n"
+       "1:	shl16insli %1, %1, hw1(_GLOBAL_OFFSET_TABLE_ - 1b)\n"
+       "	shl16insli %1, %1, hw0(_GLOBAL_OFFSET_TABLE_ - 1b)\n"
+       "        add %0, %0, %1"
+       : "=r" (got), "=r" (tmp));
+#else
+  asm( "	lnk %0\n"
+       "1:	addli %0, %0, lo16(_GLOBAL_OFFSET_TABLE_ - 1b)\n"
+       "	auli %0, %0, ha16(_GLOBAL_OFFSET_TABLE_ - 1b)"
+       : "=r" (got));
+#endif
+
+  return *got;
+}
+
+
+/* Return the run-time load address of the shared object.  */
+static inline ElfW(Addr)
+elf_machine_load_address (void)
+{
+  ElfW(Addr) *got;
+  ElfW(Addr) dynamic;
+
+#ifdef __tilegx__
+  ElfW(Addr) tmp;
+  asm( "	lnk %2\n"
+       "1:	{\n"
+       "	 moveli %0, hw2_last(_GLOBAL_OFFSET_TABLE_ - 1b)\n"
+       "	 moveli %1, hw2_last(_DYNAMIC - 1b)\n"
+       "	}\n"
+       "	{\n"
+       "	 shl16insli %0, %0, hw1(_GLOBAL_OFFSET_TABLE_ - 1b)\n"
+       "	 shl16insli %1, %1, hw1(_DYNAMIC - 1b)\n"
+       "	}\n"
+       "	{\n"
+       "	 shl16insli %0, %0, hw0(_GLOBAL_OFFSET_TABLE_ - 1b)\n"
+       "	 shl16insli %1, %1, hw0(_DYNAMIC - 1b)\n"
+       "	}\n"
+       "	{\n"
+       "	 add %0, %0, %2\n"
+       "	 add %1, %1, %2\n"
+       "	}"
+       : "=r" (got), "=r" (dynamic), "=r" (tmp));
+#else
+  asm( "	lnk %0\n"
+       "1:	{\n"
+       "	 addli %0, %0, lo16(_GLOBAL_OFFSET_TABLE_ - 1b)\n"
+       "	 addli %1, %0, lo16(_DYNAMIC - 1b)\n"
+       "	}\n"
+       "	{\n"
+       "	 auli %0, %0, ha16(_GLOBAL_OFFSET_TABLE_ - 1b)\n"
+       "	 auli %1, %1, ha16(_DYNAMIC - 1b)\n"
+       "	}\n"
+       : "=r" (got), "=r" (dynamic));
+#endif
+
+  return dynamic - *got;
+}
+
+/* Flush some range of the instruction cache.  If invoked prior to
+   actually setting dl_pagesize, we conservatively use 4KB, which
+   is the smallest page size we could plausibly be running with.  */
+static inline void
+_dl_flush_icache (const void *addr, unsigned long size)
+{
+  invalidate_icache (addr, size, GLRO(dl_pagesize) ? : 4096);
+}
+
+/* Set up the loaded object described by L so its unrelocated PLT
+   entries will jump to the on-demand fixup code in dl-runtime.c.  */
+
+static inline int __attribute__ ((unused))
+elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
+{
+  ElfW(Addr) *gotplt;
+  extern void _dl_runtime_resolve (ElfW(Word));
+  extern void _dl_runtime_profile (ElfW(Word));
+
+  if (l->l_info[DT_JMPREL] && lazy)
+    {
+      gotplt = (ElfW(Addr) *) D_PTR (l, l_info[DT_PLTGOT]);
+
+      /* The GOT entries for functions in the PLT have not yet been filled
+         in.  Their initial contents will arrange when called to put in
+         registers an offset into the .rel.plt section, and gotplt[0], then
+         jump to gotplt[1].  */
+
+      /* Identify this shared object.  */
+      gotplt[0] = (ElfW(Addr)) l;
+
+      /* The gotplt[1] entry contains the address of a function which gets
+         called to get the address of a so far unresolved function and jump
+         to it.  The profiling extension of the dynamic linker allows to
+         intercept the calls to collect information.  In this case we don't
+         store the address in the GOTPLT so that all future calls also end
+         in this function.  */
+      if (__builtin_expect (profile, 0))
+        {
+          gotplt[1] = (ElfW(Addr)) &_dl_runtime_profile;
+
+          if (GLRO(dl_profile) != NULL
+              && _dl_name_match_p (GLRO(dl_profile), l))
+            /* This is the object we are looking for.  Say that we really
+               want profiling and the timers are started.  */
+            GL(dl_profile_map) = l;
+        }
+      else
+        /* This function will get called to fix up the GOTPLT entry
+           indicated by the offset on the stack, and then jump to the
+           resolved address.  */
+        gotplt[1] = (ElfW(Addr)) &_dl_runtime_resolve;
+    }
+
+  return lazy;
+}
+
+#if __WORDSIZE == 32
+/* Mask identifying addresses reserved for the user program,
+   where the dynamic linker should not map anything.  */
+#define ELF_MACHINE_USER_ADDRESS_MASK   0xf8000000UL
+#endif
+
+/* Initial entry point code for the dynamic linker.
+   The C function `_dl_start' is the real entry point;
+   its return value is the user program's entry point.  */
+
+#define RTLD_START asm (".globl _dl_start");
+
+#ifndef RTLD_START_SPECIAL_INIT
+#define RTLD_START_SPECIAL_INIT /* nothing */
+#endif
+
+/* Wrap a generic Tilera relocation type. */
+#ifdef __tilegx__
+#define R_TILE(x) R_TILEGX_##x
+#define __R_TILE_TLS(x,c) R_TILEGX_TLS_##x##c
+#define _R_TILE_TLS(x,c) __R_TILE_TLS(x,c)
+#define R_TILE_TLS(x) _R_TILE_TLS(x,__ELF_NATIVE_CLASS)
+#else
+#define R_TILE(x) R_TILEPRO_##x
+#define R_TILE_TLS(x) R_TILEPRO_TLS_##x##32
+#endif
+
+/* 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.
+   ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one
+   of the main executable's symbols, as for a COPY reloc.  */
+#define elf_machine_type_class(type) \
+  ((((type) == R_TILE(JMP_SLOT) || (type) == R_TILE_TLS(DTPMOD)		      \
+     || (type) == R_TILE_TLS(DTPOFF) || (type) == R_TILE_TLS(TPOFF))	      \
+    * ELF_RTYPE_CLASS_PLT)						      \
+   | (((type) == R_TILE(COPY)) * ELF_RTYPE_CLASS_COPY))
+
+/* A reloc type used for ld.so cmdline arg lookups to reject PLT entries.  */
+#define ELF_MACHINE_JMP_SLOT R_TILE(JMP_SLOT)
+
+/* TILE never uses Elf32_Rel relocations.  */
+#define ELF_MACHINE_NO_REL 1
+
+/* We define an initialization functions.  This is called very early in
+   _dl_sysdep_start.  */
+#define DL_PLATFORM_INIT dl_platform_init ()
+
+static inline void __attribute__ ((unused))
+dl_platform_init (void)
+{
+  if (GLRO(dl_platform) != NULL && *GLRO(dl_platform) == '\0')
+    /* Avoid an empty string which would disturb us.  */
+    GLRO(dl_platform) = NULL;
+}
+
+static inline ElfW(Addr)
+elf_machine_fixup_plt (struct link_map *map, lookup_t t,
+        	       const ElfW(Rela) *reloc,
+        	       ElfW(Addr) *reloc_addr, ElfW(Addr) value)
+{
+  return *reloc_addr = value;
+}
+
+/* Return the final value of a plt relocation.  */
+static inline ElfW(Addr)
+elf_machine_plt_value (struct link_map *map, const ElfW(Rela) *reloc,
+        	       ElfW(Addr) value)
+{
+  return value;
+}
+
+/* Support notifying the simulator about new objects. */
+void internal_function _dl_arch_map_object (struct link_map *l);
+#define _dl_arch_map_object _dl_arch_map_object
+
+/* Names of the architecture-specific auditing callback functions.  */
+#define ARCH_LA_PLTENTER tile_gnu_pltenter
+#define ARCH_LA_PLTEXIT tile_gnu_pltexit
+
+#endif /* !dl_machine_h */
+
+
+#ifdef RESOLVE_MAP
+
+struct reloc_howto
+{
+  /* Right shift operand by this number of bits. */
+  unsigned char right_shift;
+
+#ifdef __tilegx__
+  /* If nonzero, this is updating a code bundle. */
+  unsigned char is_bundle_update;
+#else
+  /* If nonzero, add 0x8000 to the value. */
+  unsigned char add_0x8000;
+#endif
+
+  /* If nonzero, subtract the containing address from the address. */
+  unsigned char is_pcrel;
+
+  /* Size in bytes, or 0 if this table entry should be ignored. */
+  unsigned char byte_size;
+};
+
+/* Relocation information. Cannot contain create_* function pointers
+   because then the table would not be position-independent. */
+static const struct reloc_howto howto[] =
+{
+#ifdef __tilegx__
+
+# if __WORDSIZE == 32
+  /* The GX -m32 loader only handles 32-bit types, so it will be confused
+     by shifts larger than that.  We convert them to just sign-extend;
+     they usually indicate a program bug or missed optimization, but we
+     have to handle them correctly anyway.  */
+#  define S32 31
+#  define S48 31
+# else
+#  define S32 32
+#  define S48 48
+# endif
+
+  /* R_TILEGX_NONE */                    {   0, 0, 0, 0 },
+  /* R_TILEGX_64 */                      {   0, 0, 0, 8 },
+  /* R_TILEGX_32 */                      {   0, 0, 0, 4 },
+  /* R_TILEGX_16 */                      {   0, 0, 0, 2 },
+  /* R_TILEGX_8 */                       {   0, 0, 0, 1 },
+  /* R_TILEGX_64_PCREL */                {   0, 0, 1, 8 },
+  /* R_TILEGX_32_PCREL */                {   0, 0, 1, 4 },
+  /* R_TILEGX_16_PCREL */                {   0, 0, 1, 2 },
+  /* R_TILEGX_8_PCREL */                 {   0, 0, 1, 1 },
+  /* R_TILEGX_HW0 */                     {   0, 0, 0, 0 },
+  /* R_TILEGX_HW1 */                     {  16, 0, 0, 0 },
+  /* R_TILEGX_HW2 */                     { S32, 0, 0, 0 },
+  /* R_TILEGX_HW3 */                     { S48, 0, 0, 0 },
+  /* R_TILEGX_HW0_LAST */                {   0, 0, 0, 0 },
+  /* R_TILEGX_HW1_LAST */                {  16, 0, 0, 0 },
+  /* R_TILEGX_HW2_LAST */                { S32, 0, 0, 0 },
+  /* R_TILEGX_COPY */                    {   0, 0, 0, 0 },
+  /* R_TILEGX_GLOB_DAT */                {   0, 0, 0, 8 },
+  /* R_TILEGX_JMP_SLOT */                {   0, 0, 0, 0 },
+  /* R_TILEGX_RELATIVE */                {   0, 0, 0, 0 },
+  /* R_TILEGX_BROFF_X1 */                {   3, 1, 1, 8 },
+  /* R_TILEGX_JUMPOFF_X1 */              {   3, 1, 1, 8 },
+  /* R_TILEGX_JUMPOFF_X1_PLT */          {   3, 1, 1, 8 },
+  /* R_TILEGX_IMM8_X0 */                 {   0, 1, 0, 8 },
+  /* R_TILEGX_IMM8_Y0 */                 {   0, 1, 0, 8 },
+  /* R_TILEGX_IMM8_X1 */                 {   0, 1, 0, 8 },
+  /* R_TILEGX_IMM8_Y1 */                 {   0, 1, 0, 8 },
+  /* R_TILEGX_DEST_IMM8_X1 */            {   0, 1, 0, 8 },
+  /* R_TILEGX_MT_IMM14_X1 */             {   0, 1, 0, 8 },
+  /* R_TILEGX_MF_IMM14_X1 */             {   0, 1, 0, 8 },
+  /* R_TILEGX_MMSTART_X0 */              {   0, 1, 0, 8 },
+  /* R_TILEGX_MMEND_X0 */                {   0, 1, 0, 8 },
+  /* R_TILEGX_SHAMT_X0 */                {   0, 1, 0, 8 },
+  /* R_TILEGX_SHAMT_X1 */                {   0, 1, 0, 8 },
+  /* R_TILEGX_SHAMT_Y0 */                {   0, 1, 0, 8 },
+  /* R_TILEGX_SHAMT_Y1 */                {   0, 1, 0, 8 },
+  /* R_TILEGX_IMM16_X0_HW0 */            {   0, 1, 0, 8 },
+  /* R_TILEGX_IMM16_X1_HW0 */            {   0, 1, 0, 8 },
+  /* R_TILEGX_IMM16_X0_HW1 */            {  16, 1, 0, 8 },
+  /* R_TILEGX_IMM16_X1_HW1 */            {  16, 1, 0, 8 },
+  /* R_TILEGX_IMM16_X0_HW2 */            { S32, 1, 0, 8 },
+  /* R_TILEGX_IMM16_X1_HW2 */            { S32, 1, 0, 8 },
+  /* R_TILEGX_IMM16_X0_HW3 */            { S48, 1, 0, 8 },
+  /* R_TILEGX_IMM16_X1_HW3 */            { S48, 1, 0, 8 },
+  /* R_TILEGX_IMM16_X0_HW0_LAST */       {   0, 1, 0, 8 },
+  /* R_TILEGX_IMM16_X1_HW0_LAST */       {   0, 1, 0, 8 },
+  /* R_TILEGX_IMM16_X0_HW1_LAST */       {  16, 1, 0, 8 },
+  /* R_TILEGX_IMM16_X1_HW1_LAST */       {  16, 1, 0, 8 },
+  /* R_TILEGX_IMM16_X0_HW2_LAST */       { S32, 1, 0, 8 },
+  /* R_TILEGX_IMM16_X1_HW2_LAST */       { S32, 1, 0, 8 },
+  /* R_TILEGX_IMM16_X0_HW0_PCREL */      {   0, 1, 1, 8 },
+  /* R_TILEGX_IMM16_X1_HW0_PCREL */      {   0, 1, 1, 8 },
+  /* R_TILEGX_IMM16_X0_HW1_PCREL */      {  16, 1, 1, 8 },
+  /* R_TILEGX_IMM16_X1_HW1_PCREL */      {  16, 1, 1, 8 },
+  /* R_TILEGX_IMM16_X0_HW2_PCREL */      { S32, 1, 1, 8 },
+  /* R_TILEGX_IMM16_X1_HW2_PCREL */      { S32, 1, 1, 8 },
+  /* R_TILEGX_IMM16_X0_HW3_PCREL */      { S48, 1, 1, 8 },
+  /* R_TILEGX_IMM16_X1_HW3_PCREL */      { S48, 1, 1, 8 },
+  /* R_TILEGX_IMM16_X0_HW0_LAST_PCREL */ {   0, 1, 1, 8 },
+  /* R_TILEGX_IMM16_X1_HW0_LAST_PCREL */ {   0, 1, 1, 8 },
+  /* R_TILEGX_IMM16_X0_HW1_LAST_PCREL */ {  16, 1, 1, 8 },
+  /* R_TILEGX_IMM16_X1_HW1_LAST_PCREL */ {  16, 1, 1, 8 },
+  /* R_TILEGX_IMM16_X0_HW2_LAST_PCREL */ { S32, 1, 1, 8 },
+  /* R_TILEGX_IMM16_X1_HW2_LAST_PCREL */ { S32, 1, 1, 8 },
+  /* R_TILEGX_IMM16_X0_HW0_GOT */        {   0, 1, 0, 0 },
+  /* R_TILEGX_IMM16_X1_HW0_GOT */        {   0, 1, 0, 0 },
+  /* R_TILEGX_IMM16_X0_HW1_GOT */        {  16, 1, 0, 0 },
+  /* R_TILEGX_IMM16_X1_HW1_GOT */        {  16, 1, 0, 0 },
+  /* R_TILEGX_IMM16_X0_HW2_GOT */        { S32, 1, 0, 0 },
+  /* R_TILEGX_IMM16_X1_HW2_GOT */        { S32, 1, 0, 0 },
+  /* R_TILEGX_IMM16_X0_HW3_GOT */        { S48, 1, 0, 0 },
+  /* R_TILEGX_IMM16_X1_HW3_GOT */        { S48, 1, 0, 0 },
+  /* R_TILEGX_IMM16_X0_HW0_LAST_GOT */   {   0, 1, 0, 0 },
+  /* R_TILEGX_IMM16_X1_HW0_LAST_GOT */   {   0, 1, 0, 0 },
+  /* R_TILEGX_IMM16_X0_HW1_LAST_GOT */   {  16, 1, 0, 0 },
+  /* R_TILEGX_IMM16_X1_HW1_LAST_GOT */   {  16, 1, 0, 0 },
+  /* R_TILEGX_IMM16_X0_HW2_LAST_GOT */   { S32, 1, 0, 0 },
+  /* R_TILEGX_IMM16_X1_HW2_LAST_GOT */   { S32, 1, 0, 0 },
+  /* R_TILEGX_IMM16_X0_HW0_TLS_GD */     {   0, 1, 0, 8 },
+  /* R_TILEGX_IMM16_X1_HW0_TLS_GD */     {   0, 1, 0, 8 },
+  /* R_TILEGX_IMM16_X0_HW1_TLS_GD */     {  16, 1, 0, 8 },
+  /* R_TILEGX_IMM16_X1_HW1_TLS_GD */     {  16, 1, 0, 8 },
+  /* R_TILEGX_IMM16_X0_HW2_TLS_GD */     { S32, 1, 0, 8 },
+  /* R_TILEGX_IMM16_X1_HW2_TLS_GD */     { S32, 1, 0, 8 },
+  /* R_TILEGX_IMM16_X0_HW3_TLS_GD */     { S48, 1, 0, 8 },
+  /* R_TILEGX_IMM16_X1_HW3_TLS_GD */     { S48, 1, 0, 8 },
+  /* R_TILEGX_IMM16_X0_HW0_LAST_TLS_GD */{   0, 1, 0, 8 },
+  /* R_TILEGX_IMM16_X1_HW0_LAST_TLS_GD */{   0, 1, 0, 8 },
+  /* R_TILEGX_IMM16_X0_HW1_LAST_TLS_GD */{  16, 1, 0, 8 },
+  /* R_TILEGX_IMM16_X1_HW1_LAST_TLS_GD */{  16, 1, 0, 8 },
+  /* R_TILEGX_IMM16_X0_HW2_LAST_TLS_GD */{ S32, 1, 0, 8 },
+  /* R_TILEGX_IMM16_X1_HW2_LAST_TLS_GD */{ S32, 1, 0, 8 },
+  /* R_TILEGX_IMM16_X0_HW0_TLS_IE */     {   0, 1, 0, 8 },
+  /* R_TILEGX_IMM16_X1_HW0_TLS_IE */     {   0, 1, 0, 8 },
+  /* R_TILEGX_IMM16_X0_HW1_TLS_IE */     {  16, 1, 0, 8 },
+  /* R_TILEGX_IMM16_X1_HW1_TLS_IE */     {  16, 1, 0, 8 },
+  /* R_TILEGX_IMM16_X0_HW2_TLS_IE */     { S32, 1, 0, 8 },
+  /* R_TILEGX_IMM16_X1_HW2_TLS_IE */     { S32, 1, 0, 8 },
+  /* R_TILEGX_IMM16_X0_HW3_TLS_IE */     { S48, 1, 0, 8 },
+  /* R_TILEGX_IMM16_X1_HW3_TLS_IE */     { S48, 1, 0, 8 },
+  /* R_TILEGX_IMM16_X0_HW0_LAST_TLS_IE */{   0, 1, 0, 8 },
+  /* R_TILEGX_IMM16_X1_HW0_LAST_TLS_IE */{   0, 1, 0, 8 },
+  /* R_TILEGX_IMM16_X0_HW1_LAST_TLS_IE */{  16, 1, 0, 8 },
+  /* R_TILEGX_IMM16_X1_HW1_LAST_TLS_IE */{  16, 1, 0, 8 },
+  /* R_TILEGX_IMM16_X0_HW2_LAST_TLS_IE */{ S32, 1, 0, 8 },
+  /* R_TILEGX_IMM16_X1_HW2_LAST_TLS_IE */{ S32, 1, 0, 8 },
+  /* R_TILEGX_TLS_DTPMOD64 */            {   0, 0, 0, 0 },
+  /* R_TILEGX_TLS_DTPOFF64 */            {   0, 0, 0, 0 },
+  /* R_TILEGX_TLS_TPOFF64 */             {   0, 0, 0, 0 },
+  /* R_TILEGX_TLS_DTPMOD32 */            {   0, 0, 0, 0 },
+  /* R_TILEGX_TLS_DTPOFF32 */            {   0, 0, 0, 0 },
+  /* R_TILEGX_TLS_TPOFF32 */             {   0, 0, 0, 0 }
+#else
+  /* R_TILEPRO_NONE */                   { 0,  0, 0, 0 },
+  /* R_TILEPRO_32 */                     { 0,  0, 0, 4 },
+  /* R_TILEPRO_16 */                     { 0,  0, 0, 2 },
+  /* R_TILEPRO_8 */                      { 0,  0, 0, 1 },
+  /* R_TILEPRO_32_PCREL */               { 0,  0, 1, 4 },
+  /* R_TILEPRO_16_PCREL */               { 0,  0, 1, 2 },
+  /* R_TILEPRO_8_PCREL */                { 0,  0, 1, 1 },
+  /* R_TILEPRO_LO16 */                   { 0,  0, 0, 2 },
+  /* R_TILEPRO_HI16 */                   { 16, 0, 0, 2 },
+  /* R_TILEPRO_HA16 */                   { 16, 1, 0, 2 },
+  /* R_TILEPRO_COPY */                   { 0,  0, 0, 0 },
+  /* R_TILEPRO_GLOB_DAT */               { 0,  0, 0, 4 },
+  /* R_TILEPRO_JMP_SLOT */               { 0,  0, 0, 0 },
+  /* R_TILEPRO_RELATIVE */               { 0,  0, 0, 0 },
+  /* R_TILEPRO_BROFF_X1 */               { 3,  0, 1, 8 },
+  /* R_TILEPRO_JOFFLONG_X1 */            { 3,  0, 1, 8 },
+  /* R_TILEPRO_JOFFLONG_X1_PLT */        { 3,  0, 1, 8 },
+  /* R_TILEPRO_IMM8_X0 */                { 0,  0, 0, 8 },
+  /* R_TILEPRO_IMM8_Y0 */                { 0,  0, 0, 8 },
+  /* R_TILEPRO_IMM8_X1 */                { 0,  0, 0, 8 },
+  /* R_TILEPRO_IMM8_Y1 */                { 0,  0, 0, 8 },
+  /* R_TILEPRO_MT_IMM15_X1 */            { 0,  0, 0, 8 },
+  /* R_TILEPRO_MF_IMM15_X1 */            { 0,  0, 0, 8 },
+  /* R_TILEPRO_IMM16_X0 */               { 0,  0, 0, 8 },
+  /* R_TILEPRO_IMM16_X1 */               { 0,  0, 0, 8 },
+  /* R_TILEPRO_IMM16_X0_LO */            { 0,  0, 0, 8 },
+  /* R_TILEPRO_IMM16_X1_LO */            { 0,  0, 0, 8 },
+  /* R_TILEPRO_IMM16_X0_HI */            { 16, 0, 0, 8 },
+  /* R_TILEPRO_IMM16_X1_HI */            { 16, 0, 0, 8 },
+  /* R_TILEPRO_IMM16_X0_HA */            { 16, 1, 0, 8 },
+  /* R_TILEPRO_IMM16_X1_HA */            { 16, 1, 0, 8 },
+  /* R_TILEPRO_IMM16_X0_PCREL */         { 0,  0, 1, 8 },
+  /* R_TILEPRO_IMM16_X1_PCREL */         { 0,  0, 1, 8 },
+  /* R_TILEPRO_IMM16_X0_LO_PCREL */      { 0,  0, 1, 8 },
+  /* R_TILEPRO_IMM16_X1_LO_PCREL */      { 0,  0, 1, 8 },
+  /* R_TILEPRO_IMM16_X0_HI_PCREL */      { 16, 0, 1, 8 },
+  /* R_TILEPRO_IMM16_X1_HI_PCREL */      { 16, 0, 1, 8 },
+  /* R_TILEPRO_IMM16_X0_HA_PCREL */      { 16, 1, 1, 8 },
+  /* R_TILEPRO_IMM16_X1_HA_PCREL */      { 16, 1, 1, 8 },
+  /* R_TILEPRO_IMM16_X0_GOT */           { 0,  0, 0, 0 },
+  /* R_TILEPRO_IMM16_X1_GOT */           { 0,  0, 0, 0 },
+  /* R_TILEPRO_IMM16_X0_GOT_LO */        { 0,  0, 0, 0 },
+  /* R_TILEPRO_IMM16_X1_GOT_LO */        { 0,  0, 0, 0 },
+  /* R_TILEPRO_IMM16_X0_GOT_HI */        { 0,  0, 0, 0 },
+  /* R_TILEPRO_IMM16_X1_GOT_HI */        { 0,  0, 0, 0 },
+  /* R_TILEPRO_IMM16_X0_GOT_HA */        { 0,  0, 0, 0 },
+  /* R_TILEPRO_IMM16_X1_GOT_HA */        { 0,  0, 0, 0 },
+  /* R_TILEPRO_MMSTART_X0 */             { 0,  0, 0, 8 },
+  /* R_TILEPRO_MMEND_X0 */               { 0,  0, 0, 8 },
+  /* R_TILEPRO_MMSTART_X1 */             { 0,  0, 0, 8 },
+  /* R_TILEPRO_MMEND_X1 */               { 0,  0, 0, 8 },
+  /* R_TILEPRO_SHAMT_X0 */               { 0,  0, 0, 8 },
+  /* R_TILEPRO_SHAMT_X1 */               { 0,  0, 0, 8 },
+  /* R_TILEPRO_SHAMT_Y0 */               { 0,  0, 0, 8 },
+  /* R_TILEPRO_SHAMT_Y1 */               { 0,  0, 0, 8 },
+  /* R_TILEPRO_SN_BROFF */               { 0,  0, 0, 0 },
+  /* R_TILEPRO_SN_IMM8 */                { 0,  0, 0, 0 },
+  /* R_TILEPRO_SN_UIMM8 */               { 0,  0, 0, 0 },
+  /* R_TILEPRO_SN_BYTE0 */               { 0,  0, 0, 0 },
+  /* R_TILEPRO_SN_BYTE1 */               { 0,  0, 0, 0 },
+  /* R_TILEPRO_SN_BYTE2 */               { 0,  0, 0, 0 },
+  /* R_TILEPRO_SN_BYTE3 */               { 0,  0, 0, 0 },
+  /* R_TILEPRO_SN_SPCREL0 */             { 0,  0, 0, 0 },
+  /* R_TILEPRO_SN_SPCREL1 */             { 0,  0, 0, 0 },
+  /* R_TILEPRO_SN_SPCREL2 */             { 0,  0, 0, 0 },
+  /* R_TILEPRO_SN_SPCREL3 */             { 0,  0, 0, 0 },
+  /* R_TILEPRO_IMM16_X0_TLS_GD */        { 0,  0, 0, 8 },
+  /* R_TILEPRO_IMM16_X1_TLS_GD */        { 0,  0, 0, 8 },
+  /* R_TILEPRO_IMM16_X0_TLS_GD_LO */     { 0,  0, 0, 8 },
+  /* R_TILEPRO_IMM16_X1_TLS_GD_LO */     { 0,  0, 0, 8 },
+  /* R_TILEPRO_IMM16_X0_TLS_GD_HI */     { 16, 0, 0, 8 },
+  /* R_TILEPRO_IMM16_X1_TLS_GD_HI */     { 16, 0, 0, 8 },
+  /* R_TILEPRO_IMM16_X0_TLS_GD_HA */     { 16, 1, 0, 8 },
+  /* R_TILEPRO_IMM16_X1_TLS_GD_HA */     { 16, 1, 0, 8 },
+  /* R_TILEPRO_IMM16_X0_TLS_IE */        { 0,  0, 0, 8 },
+  /* R_TILEPRO_IMM16_X1_TLS_IE */        { 0,  0, 0, 8 },
+  /* R_TILEPRO_IMM16_X0_TLS_IE_LO */     { 0,  0, 0, 8 },
+  /* R_TILEPRO_IMM16_X1_TLS_IE_LO */     { 0,  0, 0, 8 },
+  /* R_TILEPRO_IMM16_X0_TLS_IE_HI */     { 16, 0, 0, 8 },
+  /* R_TILEPRO_IMM16_X1_TLS_IE_HI */     { 16, 0, 0, 8 },
+  /* R_TILEPRO_IMM16_X0_TLS_IE_HA */     { 16, 1, 0, 8 },
+  /* R_TILEPRO_IMM16_X1_TLS_IE_HA */     { 16, 1, 0, 8 },
+  /* R_TILEPRO_TLS_DTPMOD32 */           { 0,  0, 0, 0 },
+  /* R_TILEPRO_TLS_DTPOFF32 */           { 0,  0, 0, 0 },
+  /* R_TILEPRO_TLS_TPOFF32 */            { 0,  0, 0, 0 },
+#endif
+};
+
+#if __ELF_NATIVE_CLASS == 32
+#define ELFW_R_TYPE	ELF32_R_TYPE
+#define ELFW_ST_TYPE	ELF32_ST_TYPE
+#else
+#define ELFW_R_TYPE	ELF64_R_TYPE
+#define ELFW_ST_TYPE	ELF64_ST_TYPE
+#endif
+
+/* Perform the relocation specified by RELOC and SYM (which is fully resolved).
+   MAP is the object containing the reloc.  */
+
+auto inline void __attribute__ ((always_inline))
+elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc,
+        	  const ElfW(Sym) *sym, const struct r_found_version *version,
+        	  void *const reloc_addr_arg, int skip_ifunc)
+{
+  ElfW(Addr) *const reloc_addr = reloc_addr_arg;
+  const unsigned int r_type = ELFW_R_TYPE (reloc->r_info);
+
+#if !defined RTLD_BOOTSTRAP || !defined HAVE_Z_COMBRELOC
+  if (__builtin_expect (r_type == R_TILE(RELATIVE), 0))
+    {
+# if !defined RTLD_BOOTSTRAP && !defined HAVE_Z_COMBRELOC
+      /* This is defined in rtld.c, but nowhere in the static libc.a;
+         make the reference weak so static programs can still link.
+         This declaration cannot be done when compiling rtld.c
+         (i.e. #ifdef RTLD_BOOTSTRAP) because rtld.c contains the
+         common defn for _dl_rtld_map, which is incompatible with a
+         weak decl in the same file.  */
+#  ifndef SHARED
+      weak_extern (GL(dl_rtld_map));
+#  endif
+      if (map != &GL(dl_rtld_map)) /* Already done in rtld itself.  */
+# endif
+        *reloc_addr = map->l_addr + reloc->r_addend;
+      return;
+    }
+#endif
+
+  if (__builtin_expect (r_type == R_TILE(NONE), 0))
+    return;
+
+#if !defined RTLD_BOOTSTRAP && !defined RESOLVE_CONFLICT_FIND_MAP
+  const ElfW(Sym) *const refsym = sym;
+#endif
+  struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
+  ElfW(Addr) value;
+
+  if (sym == NULL)
+    value = 0;
+  else if (ELFW_ST_TYPE (sym->st_info) == STT_SECTION)
+    value = map->l_addr;  /* like a RELATIVE reloc */
+  else
+    value = sym_map->l_addr + sym->st_value;
+
+  if (sym != NULL
+      && __builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC, 0)
+      && __builtin_expect (sym->st_shndx != SHN_UNDEF, 1)
+      && __builtin_expect (!skip_ifunc, 1))
+    value = ((Elf64_Addr (*) (void)) value) ();
+
+  switch (r_type)
+    {
+    case R_TILE(JMP_SLOT):
+      elf_machine_fixup_plt (map, 0, reloc, reloc_addr,
+                             value + reloc->r_addend);
+      return;
+
+#ifndef RESOLVE_CONFLICT_FIND_MAP
+    case R_TILE_TLS(DTPMOD):
+# ifdef RTLD_BOOTSTRAP
+      /* During startup the dynamic linker is always the module
+         with index 1.
+         XXX If this relocation is necessary move before RESOLVE
+         call.  */
+      *reloc_addr = 1;
+# else
+      /* Get the information from the link map returned by the
+         resolv function.  */
+      if (sym_map != NULL)
+        *reloc_addr = sym_map->l_tls_modid;
+# endif
+      return;
+    case R_TILE_TLS(DTPOFF):
+# ifndef RTLD_BOOTSTRAP
+      /* During relocation all TLS symbols are defined and used.
+         Therefore the offset is already correct.  */
+      if (sym != NULL)
+        *reloc_addr = sym->st_value + reloc->r_addend;
+# endif
+      return;
+    case R_TILE_TLS(TPOFF):
+# ifdef RTLD_BOOTSTRAP
+      *reloc_addr = sym->st_value + reloc->r_addend + map->l_tls_offset;
+# else
+      if (sym != NULL)
+        {
+          CHECK_STATIC_TLS (map, sym_map);
+          *reloc_addr = (sym->st_value + reloc->r_addend
+                         + sym_map->l_tls_offset);
+        }
+#endif
+      return;
+#endif /* use TLS */
+
+#if !defined RTLD_BOOTSTRAP && !defined RESOLVE_CONFLICT_FIND_MAP
+      /* Not needed in dl-conflict.c.  */
+    case R_TILE(COPY):
+      if (sym == NULL)
+        /* This can happen in trace mode if an object could not be found.  */
+        return;
+      if (__builtin_expect (sym->st_size > refsym->st_size, 0)
+          || (__builtin_expect (sym->st_size < refsym->st_size, 0)
+              && __builtin_expect (GLRO(dl_verbose), 0)))
+        {
+          const char *strtab;
+
+          strtab = (const char *) D_PTR (map,l_info[DT_STRTAB]);
+          _dl_error_printf ("%s: Symbol `%s' has different size in shared"
+                            " object, consider re-linking\n",
+                            rtld_progname ?: "<program name unknown>",
+                            strtab + refsym->st_name);
+        }
+      memcpy (reloc_addr_arg, (void *) value,
+              MIN (sym->st_size, refsym->st_size));
+      return;
+#endif
+    }
+
+  /* All remaining relocations must be in the lookup table. */
+  const struct reloc_howto *h = &howto[r_type];
+  if ((unsigned int) r_type >= sizeof howto / sizeof howto[0] ||
+      h->byte_size == 0)
+    {
+#if !defined RTLD_BOOTSTRAP || defined _NDEBUG
+      /* We add these checks in the version to relocate ld.so only
+         if we are still debugging.  */
+      _dl_reloc_bad_type (map, r_type, 0);
+#endif
+      return;
+    }
+
+  value += reloc->r_addend;
+
+  /* The lookup table entry knows how to perform this reloc. */
+  if (h->is_pcrel)
+    value -= (ElfW(Addr)) reloc_addr;
+
+#ifndef __tilegx__
+  if (h->add_0x8000)
+    value += 0x8000;
+#endif
+
+  value >>= h->right_shift;
+
+  switch (h->byte_size)
+    {
+    case 1:
+      *(char *) reloc_addr = value;
+      return;
+    case 2:
+      *(short *) reloc_addr = value;
+      return;
+    case 4:
+      *(int *) reloc_addr = value;
+      return;
+#ifdef __tilegx__
+    case 8:
+      if (!h->is_bundle_update)
+        {
+          *(ElfW(Addr) *) reloc_addr = value;
+          return;
+        }
+#endif
+    }
+
+  /* We are updating a bundle, so use the function pointer that
+     swizzles the operand bits into the right location. */
+
+  tile_bundle_bits *p = (tile_bundle_bits *) reloc_addr;
+  tile_bundle_bits bits = *p;
+
+#define MUNGE(func) do {                                            \
+    bits = ((bits & ~create_##func (-1)) | create_##func (value));  \
+    if (get_##func (bits) != value)                                 \
+      _dl_signal_error (0, map->l_name, NULL,                       \
+                        "relocation value too large for " #func);   \
+  } while (0)
+
+#define MUNGE_NOCHECK(func)                                     \
+  bits = ((bits & ~create_##func (-1)) | create_##func (value))
+
+  switch (r_type)
+    {
+#ifdef __tilegx__
+    case R_TILEGX_BROFF_X1:
+      MUNGE (BrOff_X1);
+      break;
+    case R_TILEGX_JUMPOFF_X1:
+    case R_TILEGX_JUMPOFF_X1_PLT:
+      MUNGE (JumpOff_X1);
+      break;
+    case R_TILEGX_IMM8_X0:
+      MUNGE (Imm8_X0);
+      break;
+    case R_TILEGX_IMM8_Y0:
+      MUNGE (Imm8_Y0);
+      break;
+    case R_TILEGX_IMM8_X1:
+      MUNGE (Imm8_X1);
+      break;
+    case R_TILEGX_IMM8_Y1:
+      MUNGE (Imm8_Y1);
+      break;
+    case R_TILEGX_MT_IMM14_X1:
+      MUNGE (MT_Imm14_X1);
+      break;
+    case R_TILEGX_MF_IMM14_X1:
+      MUNGE (MF_Imm14_X1);
+      break;
+    case R_TILEGX_IMM16_X0_HW0:
+    case R_TILEGX_IMM16_X0_HW1:
+    case R_TILEGX_IMM16_X0_HW2:
+    case R_TILEGX_IMM16_X0_HW3:
+    case R_TILEGX_IMM16_X0_HW0_PCREL:
+    case R_TILEGX_IMM16_X0_HW1_PCREL:
+    case R_TILEGX_IMM16_X0_HW2_PCREL:
+    case R_TILEGX_IMM16_X0_HW3_PCREL:
+    case R_TILEGX_IMM16_X0_HW0_TLS_GD:
+    case R_TILEGX_IMM16_X0_HW0_TLS_IE:
+      MUNGE_NOCHECK (Imm16_X0);
+      break;
+    case R_TILEGX_IMM16_X0_HW0_LAST:
+    case R_TILEGX_IMM16_X0_HW1_LAST:
+    case R_TILEGX_IMM16_X0_HW2_LAST:
+    case R_TILEGX_IMM16_X0_HW0_LAST_PCREL:
+    case R_TILEGX_IMM16_X0_HW1_LAST_PCREL:
+    case R_TILEGX_IMM16_X0_HW2_LAST_PCREL:
+    case R_TILEGX_IMM16_X0_HW0_LAST_TLS_GD:
+    case R_TILEGX_IMM16_X0_HW1_LAST_TLS_GD:
+    case R_TILEGX_IMM16_X0_HW0_LAST_TLS_IE:
+    case R_TILEGX_IMM16_X0_HW1_LAST_TLS_IE:
+      MUNGE (Imm16_X0);
+      break;
+    case R_TILEGX_IMM16_X1_HW0:
+    case R_TILEGX_IMM16_X1_HW1:
+    case R_TILEGX_IMM16_X1_HW2:
+    case R_TILEGX_IMM16_X1_HW3:
+    case R_TILEGX_IMM16_X1_HW0_PCREL:
+    case R_TILEGX_IMM16_X1_HW1_PCREL:
+    case R_TILEGX_IMM16_X1_HW2_PCREL:
+    case R_TILEGX_IMM16_X1_HW3_PCREL:
+    case R_TILEGX_IMM16_X1_HW0_TLS_GD:
+    case R_TILEGX_IMM16_X1_HW0_TLS_IE:
+      MUNGE_NOCHECK (Imm16_X1);
+      break;
+    case R_TILEGX_IMM16_X1_HW0_LAST:
+    case R_TILEGX_IMM16_X1_HW1_LAST:
+    case R_TILEGX_IMM16_X1_HW2_LAST:
+    case R_TILEGX_IMM16_X1_HW0_LAST_PCREL:
+    case R_TILEGX_IMM16_X1_HW1_LAST_PCREL:
+    case R_TILEGX_IMM16_X1_HW2_LAST_PCREL:
+    case R_TILEGX_IMM16_X1_HW0_LAST_TLS_GD:
+    case R_TILEGX_IMM16_X1_HW1_LAST_TLS_GD:
+    case R_TILEGX_IMM16_X1_HW0_LAST_TLS_IE:
+    case R_TILEGX_IMM16_X1_HW1_LAST_TLS_IE:
+      MUNGE (Imm16_X1);
+      break;
+    case R_TILEGX_MMSTART_X0:
+      MUNGE (BFStart_X0);
+      break;
+    case R_TILEGX_MMEND_X0:
+      MUNGE (BFEnd_X0);
+      break;
+    case R_TILEGX_SHAMT_X0:
+      MUNGE (ShAmt_X0);
+      break;
+    case R_TILEGX_SHAMT_X1:
+      MUNGE (ShAmt_X1);
+      break;
+    case R_TILEGX_SHAMT_Y0:
+      MUNGE (ShAmt_Y0);
+      break;
+    case R_TILEGX_SHAMT_Y1:
+      MUNGE (ShAmt_Y1);
+      break;
+#else
+    case R_TILEPRO_BROFF_X1:
+      MUNGE (BrOff_X1);
+      break;
+    case R_TILEPRO_JOFFLONG_X1:
+    case R_TILEPRO_JOFFLONG_X1_PLT:
+      MUNGE_NOCHECK (JOffLong_X1);   /* holds full 32-bit value */
+      break;
+    case R_TILEPRO_IMM8_X0:
+      MUNGE (Imm8_X0);
+      break;
+    case R_TILEPRO_IMM8_Y0:
+      MUNGE (Imm8_Y0);
+      break;
+    case R_TILEPRO_IMM8_X1:
+      MUNGE (Imm8_X1);
+      break;
+    case R_TILEPRO_IMM8_Y1:
+      MUNGE (Imm8_Y1);
+      break;
+    case R_TILEPRO_MT_IMM15_X1:
+      MUNGE (MT_Imm15_X1);
+      break;
+    case R_TILEPRO_MF_IMM15_X1:
+      MUNGE (MF_Imm15_X1);
+      break;
+    case R_TILEPRO_IMM16_X0_LO:
+    case R_TILEPRO_IMM16_X0_HI:
+    case R_TILEPRO_IMM16_X0_HA:
+    case R_TILEPRO_IMM16_X0_LO_PCREL:
+    case R_TILEPRO_IMM16_X0_HI_PCREL:
+    case R_TILEPRO_IMM16_X0_HA_PCREL:
+    case R_TILEPRO_IMM16_X0_TLS_GD_LO:
+    case R_TILEPRO_IMM16_X0_TLS_GD_HI:
+    case R_TILEPRO_IMM16_X0_TLS_GD_HA:
+    case R_TILEPRO_IMM16_X0_TLS_IE_LO:
+    case R_TILEPRO_IMM16_X0_TLS_IE_HI:
+    case R_TILEPRO_IMM16_X0_TLS_IE_HA:
+      MUNGE_NOCHECK (Imm16_X0);
+      break;
+    case R_TILEPRO_IMM16_X0:
+    case R_TILEPRO_IMM16_X0_PCREL:
+    case R_TILEPRO_IMM16_X0_TLS_GD:
+    case R_TILEPRO_IMM16_X0_TLS_IE:
+      MUNGE (Imm16_X0);
+      break;
+    case R_TILEPRO_IMM16_X1_LO:
+    case R_TILEPRO_IMM16_X1_HI:
+    case R_TILEPRO_IMM16_X1_HA:
+    case R_TILEPRO_IMM16_X1_LO_PCREL:
+    case R_TILEPRO_IMM16_X1_HI_PCREL:
+    case R_TILEPRO_IMM16_X1_HA_PCREL:
+    case R_TILEPRO_IMM16_X1_TLS_GD_LO:
+    case R_TILEPRO_IMM16_X1_TLS_GD_HI:
+    case R_TILEPRO_IMM16_X1_TLS_GD_HA:
+    case R_TILEPRO_IMM16_X1_TLS_IE_LO:
+    case R_TILEPRO_IMM16_X1_TLS_IE_HI:
+    case R_TILEPRO_IMM16_X1_TLS_IE_HA:
+      MUNGE_NOCHECK (Imm16_X1);
+      break;
+    case R_TILEPRO_IMM16_X1:
+    case R_TILEPRO_IMM16_X1_PCREL:
+    case R_TILEPRO_IMM16_X1_TLS_GD:
+    case R_TILEPRO_IMM16_X1_TLS_IE:
+      MUNGE (Imm16_X1);
+      break;
+    case R_TILEPRO_MMSTART_X0:
+      MUNGE (MMStart_X0);
+      break;
+    case R_TILEPRO_MMEND_X0:
+      MUNGE (MMEnd_X0);
+      break;
+    case R_TILEPRO_MMSTART_X1:
+      MUNGE (MMStart_X1);
+      break;
+    case R_TILEPRO_MMEND_X1:
+      MUNGE (MMEnd_X1);
+      break;
+    case R_TILEPRO_SHAMT_X0:
+      MUNGE (ShAmt_X0);
+      break;
+    case R_TILEPRO_SHAMT_X1:
+      MUNGE (ShAmt_X1);
+      break;
+    case R_TILEPRO_SHAMT_Y0:
+      MUNGE (ShAmt_Y0);
+      break;
+    case R_TILEPRO_SHAMT_Y1:
+      MUNGE (ShAmt_Y1);
+      break;
+#endif
+    }
+#undef MUNGE
+  *p = bits;
+  _dl_flush_icache (p, sizeof (*p));
+}
+
+auto inline void __attribute__ ((always_inline))
+elf_machine_rela_relative (ElfW(Addr) l_addr, const ElfW(Rela) *reloc,
+                           void *const reloc_addr_arg)
+{
+  ElfW(Addr) *const reloc_addr = reloc_addr_arg;
+  *reloc_addr = l_addr + reloc->r_addend;
+}
+
+auto inline void __attribute__ ((always_inline))
+elf_machine_lazy_rel (struct link_map *map,
+                      ElfW(Addr) l_addr, const ElfW(Rela) *reloc,
+                      int skip_ifunc)
+{
+  const unsigned int r_type = ELF32_R_TYPE (reloc->r_info);
+
+  /* Check for unexpected PLT reloc type.  */
+  if (__builtin_expect (r_type == R_TILE(JMP_SLOT), 1))
+    {
+      *(ElfW(Addr) *) (l_addr + reloc->r_offset) += l_addr;
+    }
+  else
+    _dl_reloc_bad_type (map, r_type, 1);
+}
+
+#endif /* RESOLVE_MAP */
diff --git a/ports/sysdeps/tile/dl-runtime.c b/ports/sysdeps/tile/dl-runtime.c
new file mode 100644
index 0000000000..0aa211db17
--- /dev/null
+++ b/ports/sysdeps/tile/dl-runtime.c
@@ -0,0 +1,79 @@
+/* Copyright (C) 2011 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+
+   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/>.  */
+
+/* Like x86_64, we pass the index of the relocation and not its offset.
+   In _dl_profile_fixup and _dl_call_pltexit we also use the index.
+   Therefore it is wasteful to compute the offset in the trampoline
+   just to reverse the operation immediately afterwards.  */
+#define reloc_offset reloc_arg * sizeof (PLTREL)
+#define reloc_index  reloc_arg
+
+#include <elf/dl-runtime.c>
+
+#include <sys/mman.h>
+#include <arch/sim.h>
+
+/* Support notifying the simulator about new objects. */
+void internal_function
+_dl_arch_map_object (struct link_map *l)
+{
+  int shift;
+
+#define DLPUTC(c) __insn_mtspr(SPR_SIM_CONTROL,                         \
+                               (SIM_CONTROL_DLOPEN                      \
+                                | ((c) << _SIM_CONTROL_OPERATOR_BITS)))
+
+  /* Write the library address in hex. */
+  DLPUTC ('0');
+  DLPUTC ('x');
+  for (shift = (int) sizeof (unsigned long) * 8 - 4; shift >= 0; shift -= 4)
+    DLPUTC ("0123456789abcdef"[(l->l_map_start >> shift) & 0xF]);
+  DLPUTC (':');
+
+  /* Write the library path, including the terminating '\0'. */
+  for (size_t i = 0;; i++)
+    {
+      DLPUTC (l->l_name[i]);
+      if (l->l_name[i] == '\0')
+        break;
+    }
+#undef DLPUTC
+}
+
+/* Support notifying the simulator about removed objects prior to munmap(). */
+void internal_function
+_dl_unmap (struct link_map *l)
+{
+  int shift;
+
+#define DLPUTC(c) __insn_mtspr(SPR_SIM_CONTROL,                         \
+                               (SIM_CONTROL_DLCLOSE                     \
+                                | ((c) << _SIM_CONTROL_OPERATOR_BITS)))
+
+  /* Write the library address in hex. */
+  DLPUTC ('0');
+  DLPUTC ('x');
+  for (shift = (int) sizeof (unsigned long) * 8 - 4; shift >= 0; shift -= 4)
+    DLPUTC ("0123456789abcdef"[(l->l_map_start >> shift) & 0xF]);
+  DLPUTC ('\0');
+#undef DLPUTC
+
+  __munmap ((void *) l->l_map_start, l->l_map_end - l->l_map_start);
+}
+
+#define DL_UNMAP(map) _dl_unmap (map)
diff --git a/ports/sysdeps/tile/dl-start.S b/ports/sysdeps/tile/dl-start.S
new file mode 100644
index 0000000000..97cdac3fce
--- /dev/null
+++ b/ports/sysdeps/tile/dl-start.S
@@ -0,0 +1,114 @@
+/* Copyright (C) 2011 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+
+   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>
+
+	/* Get address of "sym" in "reg" assuming r51 holds ".Llink". */
+	.macro pic_addr reg, sym
+#ifdef __tilegx__
+	moveli \reg, hw1_last(\sym - .Llink)
+	shl16insli \reg, \reg, hw0(\sym - .Llink)
+	ADD_PTR \reg, r51, \reg
+#else
+	ADDLI_PTR \reg, r51, lo16(\sym - .Llink)
+	auli \reg, \reg, ha16(\sym - .Llink)
+#endif
+	.endm
+
+	.text
+ENTRY (_start)
+	/* Linux starts us with sp pointing at the conventional Elf layout,
+	   but we need to allow two 'caller' words for our ABI convention.  */
+	{
+	 move r52, sp
+	 andi sp, sp, -8
+	}
+	cfi_def_cfa_register (r52)
+	{
+	 /* Point sp at base of ABI area; point r4 to the caller-sp word. */
+	 ADDI_PTR sp, sp, -(2 * REGSIZE)
+	 ADDI_PTR r4, sp, -REGSIZE
+	}
+	{
+	 /* Save zero for caller sp in our 'caller' save area, and make
+	    sure lr has a zero value, to limit backtraces.  */
+	 move lr, zero
+	 ST r4, zero
+	}
+	{
+	 move r0, r52
+	 jal _dl_start
+	}
+	/* Save returned start of user program address for later. */
+	move r50, r0
+
+	/* See if we were invoked explicitly with the dynamic loader,
+	   in which case we have to adjust the argument vector.  */
+	lnk r51; .Llink:
+	pic_addr r4, _dl_skip_args
+	LD4U r4, r4
+	BEQZT r4, .Lno_skip
+
+	/* Load the argc word at the initial sp and adjust it.
+	   We basically jump "sp" up over the first few argv entries
+	   and write "argc" a little higher up in memory, to be the
+	   base of the new kernel-initialized stack area.  */
+	LD_PTR r0, r52
+	{
+	 sub r0, r0, r4
+	 SHL_PTR_ADD r52, r4, r52
+	}
+	{
+	 ST_PTR r52, r0
+	 SHL_PTR_ADD sp, r4, sp
+	}
+	andi sp, sp, -8
+
+.Lno_skip:
+	/* Call_dl_init (_dl_loaded, argc, argv, envp).  See elf/start.s
+	   for the layout of memory here; r52 is pointing to "+0".  */
+	pic_addr r0, _rtld_local
+	{
+	 LD_PTR r1, r52  /* load argc in r1 */
+	 ADDLI_PTR r2, r52, __SIZEOF_POINTER__  /* point r2 at argv */
+	}
+	{
+	 LD_PTR r0, r0    /* yields _rtld_global._ns_loaded */
+	 addi r3, r1, 1
+	 move lr, zero
+	}
+	{
+	 SHL_PTR_ADD r3, r3, r2  /* point r3 at envp */
+	 jal _dl_init_internal
+	}
+
+	/* Call user program whose address we saved in r50.
+	   We invoke it just like a static binary, but with _dl_fini
+	   in r0 so we can distinguish.  */
+
+	pic_addr r0, _dl_fini
+	move lr, zero
+	{
+	 move sp, r52
+	 jr r50
+	}
+
+	/* Tell backtracer to give up (_start has no caller). */
+	info 2  /* INFO_OP_CANNOT_BACKTRACE */
+
+END (_start)
diff --git a/ports/sysdeps/tile/dl-tls.c b/ports/sysdeps/tile/dl-tls.c
new file mode 100644
index 0000000000..c3267614ce
--- /dev/null
+++ b/ports/sysdeps/tile/dl-tls.c
@@ -0,0 +1,27 @@
+/* Copyright (C) 2011 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+
+   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/>.  */
+
+#ifdef SHARED
+/* We provide a fast-path version of __tls_get_addr to allow for
+   the normal case to be fast, both by coding the function tightly,
+   and more importantly by fixing its register clobber API so the
+   compiler can avoid having to set up frames, etc., unnecessarily.  */
+#define __tls_get_addr __tls_get_addr_slow
+#endif
+
+#include <elf/dl-tls.c>
diff --git a/ports/sysdeps/tile/dl-tls.h b/ports/sysdeps/tile/dl-tls.h
new file mode 100644
index 0000000000..a6195aac6d
--- /dev/null
+++ b/ports/sysdeps/tile/dl-tls.h
@@ -0,0 +1,45 @@
+/* Copyright (C) 2011 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+
+   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/>.  */
+
+
+/* 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;
+
+/* Fast-path function to get a TLS pointer.  */
+extern void *__tls_get_addr (tls_index *ti);
+
+/* The thread pointer points to the first static TLS block.  */
+#define TLS_TP_OFFSET		0
+
+/* Dynamic thread vector pointers at the start of each TLS block.  */
+#define TLS_DTV_OFFSET		0
+
+/* Compute the value for a GOTTPREL reloc.  */
+#define TLS_TPREL_VALUE(sym_map, sym) \
+  ((sym_map)->l_tls_offset + (sym)->st_value - TLS_TP_OFFSET)
+
+/* Compute the value for a DTPREL reloc.  */
+#define TLS_DTPREL_VALUE(sym) \
+  ((sym)->st_value - TLS_DTV_OFFSET)
+
+/* Value used for dtv entries for which the allocation is delayed.  */
+#define TLS_DTV_UNALLOCATED    ((void *) -1l)
diff --git a/ports/sysdeps/tile/dl-trampoline.S b/ports/sysdeps/tile/dl-trampoline.S
new file mode 100644
index 0000000000..3478824957
--- /dev/null
+++ b/ports/sysdeps/tile/dl-trampoline.S
@@ -0,0 +1,193 @@
+/* Copyright (C) 2011 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+
+   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 <arch/abi.h>
+
+/* This function is called via the PLT header, which is called
+   from an individual PLT entry.
+
+   At this point we have several values passed in:
+
+   lr:  return address to original user code
+   r28: the tpnt value to pass to _dl_runtime_resolver
+   r29: the PLT index of the invoked jump table entry.
+
+   We set up a frame entry that looks like this (in int_reg_t units):
+
+   +57: r25 return values from function...
+   +56: r24
+   [...]
+   +33: r1
+   +32: r0
+   +31: PLT index
+   +30: tpnt
+   +29: stackframe
+   +28: caller lr
+   +27: r25 arguments to function...
+   +26: r24
+   [...]
+   +3:  r1
+   +2:  r0
+   +1:  standard ABI slot (sp)
+   +0:  standard ABI slot (callee lr)
+
+   The entries from "stackframe" up are only used in _dl_profile_resolve.
+   We save and restore r0 through r25, rather than the strictly
+   architected r0 through r9, to support unusual calling conventions;
+   for example, __tls_get_addr takes r0 and returns r0, but promises
+   not to clobber r1 through r24 to support its usual fast path.  */
+
+#define FRAME_SP		(1 * REGSIZE)
+#define FRAME_REGS		(2 * REGSIZE)
+#define FRAME_LR		(28 * REGSIZE)  /* Must follow FRAME_REGS */
+#define FRAME_STACKFRAME	(29 * REGSIZE)
+#define FRAME_TPNT		(30 * REGSIZE)
+#define FRAME_INDEX		(31 * REGSIZE)
+#define FRAME_RETVAL		(32 * REGSIZE)
+
+#define FRAME_SIZE_SMALL	(30 * REGSIZE)
+#define FRAME_SIZE_LARGE	(58 * REGSIZE)
+
+#define FOR_EACH_REG(f) \
+	f(r0);  f(r1);  f(r2);  f(r3);  \
+	f(r4);  f(r5);  f(r6);  f(r7);  \
+	f(r8);  f(r9);  f(r10); f(r11); \
+	f(r12); f(r13); f(r14); f(r15); \
+	f(r16); f(r17); f(r18); f(r19); \
+	f(r20); f(r21); f(r22); f(r23); \
+	f(r24); f(r25)
+
+#define SAVE(REG) { ST r27, REG; ADDI_PTR r27, r27, REGSIZE }
+#define RESTORE(REG) { LD REG, r27; ADDI_PTR r27, r27, REGSIZE }
+
+	.macro dl_resolve, name, profile, framesize
+.text
+.global \name
+.hidden \name
+/* Note that cpp expands ENTRY(\name) incorrectly. */
+.type \name,@function
+.align 8
+\name:
+	cfi_startproc
+	{
+	 ST sp, lr
+	 move r26, sp
+	}
+	{
+	 ADDLI_PTR sp, sp, -\framesize
+	 ADDLI_PTR r27, sp, FRAME_SP - \framesize
+	}
+	cfi_def_cfa_offset (\framesize)
+	{
+	 ST r27, r26
+	 ADDI_PTR r27, r27, FRAME_REGS - FRAME_SP
+	}
+	FOR_EACH_REG(SAVE)
+	{
+	 ST r27, lr
+	 ADDLI_PTR r27, sp, FRAME_TPNT
+	}
+	cfi_offset (lr, FRAME_LR - \framesize)
+	.if \profile
+	{
+	 move r0, r28  /* tpnt value */
+	 ST r27, r28
+	 ADDI_PTR r27, r27, FRAME_INDEX - FRAME_TPNT
+	}
+	{
+	 move r1, r29  /* PLT index */
+	 ST r27, r29
+	}
+	{
+	 move r2, lr  /* retaddr */
+	 ADDI_PTR r3, sp, FRAME_REGS  /* La_tile_regs pointer */
+	}
+	{
+	 ADDLI_PTR r4, sp, FRAME_STACKFRAME  /* framesize pointer */
+	 jal _dl_profile_fixup
+	}
+	ADDLI_PTR r28, sp, FRAME_STACKFRAME
+	LD_PTR r28, r28
+	BGTZ r28, 1f
+	.else
+	{
+	 move r0, r28  /* tpnt value 1 */
+	 move r1, r29  /* PLT index 2 */
+	}
+	jal _dl_fixup
+	.endif
+	{
+	 /* Copy aside the return value so we can restore r0 below. */
+	 move r29, r0
+	 /* Set up r27 to let us start restoring registers. */
+	 ADDLI_PTR r27, sp, FRAME_REGS
+	}
+	FOR_EACH_REG(RESTORE)
+	.if \profile
+	ADDLI_PTR r28, sp, FRAME_STACKFRAME
+	LD r28, r28
+	BGTZ r28, 1f
+	.endif
+	{
+	 /* Restore original user return address. */
+	 LD lr, r27
+	 /* Pop off our stack frame. */
+	 ADDLI_PTR sp, sp, \framesize
+	}
+	cfi_def_cfa_offset (0)
+	jr r29  /* Transfer control to freshly loaded code. */
+	jrp lr  /* Keep backtracer happy. */
+
+	.if \profile
+1:	jalr r29   /* Call resolved function. */
+	{
+	 ADDLI_PTR r28, sp, FRAME_TPNT
+	 ADDLI_PTR r27, sp, FRAME_RETVAL
+	}
+	FOR_EACH_REG(SAVE)
+	{
+	 LD r0, r28
+	 ADDI_PTR r28, r28, FRAME_INDEX - FRAME_TPNT
+	}
+        {
+	 LD r1, r28
+	 ADDLI_PTR r2, sp, FRAME_REGS
+	}
+	{
+	 ADDLI_PTR r3, sp, FRAME_RETVAL
+	 jal _dl_call_pltexit
+	}
+	{
+	 ADDLI_PTR lr, sp, FRAME_LR
+	 ADDLI_PTR r27, sp, FRAME_RETVAL
+        }
+	FOR_EACH_REG(RESTORE)
+	{
+	 LD lr, lr
+	 ADDLI_PTR sp, sp, \framesize
+	}
+	jrp lr
+	.endif
+END (\name)
+	.endm
+
+	dl_resolve _dl_runtime_resolve, 0, FRAME_SIZE_SMALL
+#ifndef PROF
+	dl_resolve _dl_runtime_profile, 1, FRAME_SIZE_LARGE
+#endif
diff --git a/ports/sysdeps/tile/fegetenv.c b/ports/sysdeps/tile/fegetenv.c
new file mode 100644
index 0000000000..f9ccc206dd
--- /dev/null
+++ b/ports/sysdeps/tile/fegetenv.c
@@ -0,0 +1,29 @@
+/* Copyright (C) 2011 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+
+   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 <fenv.h>
+#include <shlib-compat.h>
+
+int
+__fegetenv (fenv_t *envp)
+{
+  /* As a no-op, this always succeeds. */
+  return 0;
+}
+libm_hidden_ver (__fegetenv, fegetenv)
+versioned_symbol (libm, __fegetenv, fegetenv, GLIBC_2_2);
diff --git a/ports/sysdeps/tile/fegetround.c b/ports/sysdeps/tile/fegetround.c
new file mode 100644
index 0000000000..fe5b7c7980
--- /dev/null
+++ b/ports/sysdeps/tile/fegetround.c
@@ -0,0 +1,25 @@
+/* Copyright (C) 2011 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+
+   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 <fenv.h>
+
+int
+fegetround (void)
+{
+  return FE_TONEAREST;
+}
diff --git a/ports/sysdeps/tile/feholdexcpt.c b/ports/sysdeps/tile/feholdexcpt.c
new file mode 100644
index 0000000000..125cd2de72
--- /dev/null
+++ b/ports/sysdeps/tile/feholdexcpt.c
@@ -0,0 +1,27 @@
+/* Copyright (C) 2011 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+
+   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 <fenv.h>
+
+/* Tile has no exception flags, so this routine can be a no-op.  */
+int
+feholdexcept (fenv_t *envp)
+{
+  return 0;
+}
+libm_hidden_def (feholdexcept)
diff --git a/ports/sysdeps/tile/fesetenv.c b/ports/sysdeps/tile/fesetenv.c
new file mode 100644
index 0000000000..88b3e9d218
--- /dev/null
+++ b/ports/sysdeps/tile/fesetenv.c
@@ -0,0 +1,31 @@
+/* Copyright (C) 2011 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+
+   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 <fenv.h>
+#include <shlib-compat.h>
+
+/* The only way to get an initialized fenv_t on Tile is with feholdexcept()
+   or via FE_DFL_ENV, either of which restores the environment to its
+   normal state, i.e. FE_DFL_ENV.  */
+int
+__fesetenv (const fenv_t *envp)
+{
+  return 0;
+}
+libm_hidden_ver (__fesetenv, fesetenv)
+versioned_symbol (libm, __fesetenv, fesetenv, GLIBC_2_2);
diff --git a/ports/sysdeps/tile/fesetround.c b/ports/sysdeps/tile/fesetround.c
new file mode 100644
index 0000000000..5ff30e4ded
--- /dev/null
+++ b/ports/sysdeps/tile/fesetround.c
@@ -0,0 +1,26 @@
+/* Copyright (C) 2011 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+
+   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 <fenv.h>
+
+int
+fesetround (int round)
+{
+  return (round == FE_TONEAREST) ? 0 : 1;
+}
+libm_hidden_def (fesetround)
diff --git a/ports/sysdeps/tile/feupdateenv.c b/ports/sysdeps/tile/feupdateenv.c
new file mode 100644
index 0000000000..8a8a0e7f72
--- /dev/null
+++ b/ports/sysdeps/tile/feupdateenv.c
@@ -0,0 +1,27 @@
+/* Copyright (C) 2011 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+
+   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 <fenv.h>
+
+/* Tile has no exception flags, so this routine can be a no-op.  */
+int
+feupdateenv (const fenv_t *envp)
+{
+  return 0;
+}
+libm_hidden_def (feupdateenv)
diff --git a/ports/sysdeps/tile/ffs.c b/ports/sysdeps/tile/ffs.c
new file mode 100644
index 0000000000..f97b7a4ae9
--- /dev/null
+++ b/ports/sysdeps/tile/ffs.c
@@ -0,0 +1,44 @@
+/* Copyright (C) 2011 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+
+   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 <limits.h>
+#define ffsl __something_else
+#include <string.h>
+
+#undef ffs
+int
+__ffs (int x)
+{
+  return __builtin_ffs (x);
+}
+weak_alias (__ffs, ffs)
+libc_hidden_builtin_def (ffs)
+
+#undef ffsll
+int
+ffsll (long long x)
+{
+  return __builtin_ffsll (x);
+}
+
+#undef ffsl
+#if ULONG_MAX == UINT_MAX
+weak_alias (__ffs, ffsl)
+#else
+weak_alias (ffsll, ffsl)
+#endif
diff --git a/ports/sysdeps/tile/ffsll.c b/ports/sysdeps/tile/ffsll.c
new file mode 100644
index 0000000000..180eaa8c23
--- /dev/null
+++ b/ports/sysdeps/tile/ffsll.c
@@ -0,0 +1 @@
+/* This function is defined in ffs.c.  */
diff --git a/ports/sysdeps/tile/gccframe.h b/ports/sysdeps/tile/gccframe.h
new file mode 100644
index 0000000000..68e620017b
--- /dev/null
+++ b/ports/sysdeps/tile/gccframe.h
@@ -0,0 +1,21 @@
+/* Copyright (C) 2011 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#define FIRST_PSEUDO_REGISTER 64
+
+#include <sysdeps/generic/gccframe.h>
diff --git a/ports/sysdeps/tile/jmpbuf-offsets.h b/ports/sysdeps/tile/jmpbuf-offsets.h
new file mode 100644
index 0000000000..26c3e67db2
--- /dev/null
+++ b/ports/sysdeps/tile/jmpbuf-offsets.h
@@ -0,0 +1,62 @@
+/* Copyright (C) 2011 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+
+   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/>.  */
+
+/* We don't use most of these symbols; they are here for documentation. */
+#define JB_R30  0
+#define JB_R31  1
+#define JB_R32  2
+#define JB_R33  3
+#define JB_R34  4
+#define JB_R35  5
+#define JB_R36  6
+#define JB_R37  7
+#define JB_R38  8
+#define JB_R39  9
+#define JB_R40  10
+#define JB_R41  11
+#define JB_R42  12
+#define JB_R43  13
+#define JB_R44  14
+#define JB_R45  15
+#define JB_R46  16
+#define JB_R47  17
+#define JB_R48  18
+#define JB_R49  19
+#define JB_R50  20
+#define JB_R51  21
+#define JB_FP   22  /* r52 */
+#define JB_TP   23  /* r53 */
+#define JB_SP   24  /* r54 */
+#define JB_PC   25  /* normally LR, r55 */
+#define JB_ICS  26  /* interrupt critical section bit */
+
+/* We save space for some extra state to accomodate future changes.  */
+#define JB_LEN  32  /* number of words */
+
+#define JB_SIZE (JB_LEN * REGSIZE)
+
+/* Helper macro used by all the setjmp/longjmp assembly code. */
+#define FOR_EACH_CALLEE_SAVED_REG(f)                              \
+  .no_require_canonical_reg_names;                f(r30); f(r31); \
+  f(r32); f(r33); f(r34); f(r35); f(r36); f(r37); f(r38); f(r39); \
+  f(r40); f(r41); f(r42); f(r43); f(r44); f(r45); f(r46); f(r47); \
+  f(r48); f(r49); f(r50); f(r51); f(r52); f(r53); f(r54); f(r55)
+
+/* Helper for generic ____longjmp_chk(). */
+#define JB_FRAME_ADDRESS(buf) \
+  ((void *) (unsigned long) (buf[JB_SP]))
diff --git a/ports/sysdeps/tile/jmpbuf-unwind.h b/ports/sysdeps/tile/jmpbuf-unwind.h
new file mode 100644
index 0000000000..7e8d608b05
--- /dev/null
+++ b/ports/sysdeps/tile/jmpbuf-unwind.h
@@ -0,0 +1,48 @@
+/* Copyright (C) 2011 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+   Based on work contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
+
+   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 <jmpbuf-offsets.h>
+#include <stdint.h>
+#include <unwind.h>
+#include <sysdep.h>
+
+/* Test if longjmp to JMPBUF would unwind the frame
+   containing a local variable at ADDRESS.  */
+#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)
+
+static inline uintptr_t __attribute__ ((unused))
+_jmpbuf_sp (__jmp_buf regs)
+{
+  uintptr_t sp = regs[JB_SP];
+#ifdef PTR_DEMANGLE
+  PTR_DEMANGLE (sp);
+#endif
+  return sp;
+}
+
+#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \
+  ((uintptr_t) (_address) - (_adj) < _jmpbuf_sp (_jmpbuf) - (_adj))
+
+/* We use the normal longjmp for unwinding.  */
+#define __libc_unwind_longjmp(buf, val) __libc_longjmp (buf, val)
diff --git a/ports/sysdeps/tile/ldsodefs.h b/ports/sysdeps/tile/ldsodefs.h
new file mode 100644
index 0000000000..393252dad4
--- /dev/null
+++ b/ports/sysdeps/tile/ldsodefs.h
@@ -0,0 +1,40 @@
+/* Copyright (C) 2011 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+
+   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 _TILE_LDSODEFS_H
+#define _TILE_LDSODEFS_H 1
+
+#include <elf.h>
+
+struct La_tile_regs;
+struct La_tile_retval;
+
+#define ARCH_PLTENTER_MEMBERS                                           \
+  ElfW(Addr) (*tile_gnu_pltenter) (ElfW(Sym) *, unsigned int, uintptr_t *, \
+                                   uintptr_t *, struct La_tile_regs *,  \
+                                   unsigned int *, const char *,        \
+                                   long int *)
+
+#define ARCH_PLTEXIT_MEMBERS \
+  ElfW(Addr) (*tile_gnu_pltexit) (ElfW(Sym) *, unsigned int, uintptr_t *, \
+                                  uintptr_t *, const struct La_tile_regs *, \
+                                  struct La_tile_retval *, const char *)
+
+#include_next <ldsodefs.h>
+
+#endif
diff --git a/ports/sysdeps/tile/libm-test-ulps b/ports/sysdeps/tile/libm-test-ulps
new file mode 100644
index 0000000000..a42da1773b
--- /dev/null
+++ b/ports/sysdeps/tile/libm-test-ulps
@@ -0,0 +1,1484 @@
+# Begin of automatic generation
+
+# atan2
+Test "atan2 (-0.75, -1.0) == -2.49809154479650885165983415456218025":
+float: 1
+ifloat: 1
+Test "atan2 (0.75, -1.0) == 2.49809154479650885165983415456218025":
+float: 1
+ifloat: 1
+Test "atan2 (1.390625, 0.9296875) == 0.981498387184244311516296577615519772":
+float: 1
+ifloat: 1
+
+# atanh
+Test "atanh (0.75) == 0.972955074527656652552676371721589865":
+float: 1
+ifloat: 1
+
+# cacos
+Test "Imaginary part of: cacos (+0 + 0.5 i) == pi/2 - 0.4812118250596034474977589134243684231352 i":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "Imaginary part of: cacos (+0 + 1.0 i) == pi/2 - 0.8813735870195430252326093249797923090282 i":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "Imaginary part of: cacos (+0 + 1.5 i) == pi/2 - 1.194763217287109304111930828519090523536 i":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "Imaginary part of: cacos (+0 - 0.5 i) == pi/2 + 0.4812118250596034474977589134243684231352 i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: cacos (+0 - 1.0 i) == pi/2 + 0.8813735870195430252326093249797923090282 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: cacos (+0 - 1.5 i) == pi/2 + 1.194763217287109304111930828519090523536 i":
+double: 1
+idouble: 1
+Test "Imaginary part of: cacos (-0 + 0.5 i) == pi/2 - 0.4812118250596034474977589134243684231352 i":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "Imaginary part of: cacos (-0 + 1.0 i) == pi/2 - 0.8813735870195430252326093249797923090282 i":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "Imaginary part of: cacos (-0 + 1.5 i) == pi/2 - 1.194763217287109304111930828519090523536 i":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "Imaginary part of: cacos (-0 - 0.5 i) == pi/2 + 0.4812118250596034474977589134243684231352 i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: cacos (-0 - 1.0 i) == pi/2 + 0.8813735870195430252326093249797923090282 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: cacos (-0 - 1.5 i) == pi/2 + 1.194763217287109304111930828519090523536 i":
+double: 1
+idouble: 1
+Test "Imaginary part of: cacos (-1.5 + +0 i) == pi - 0.9624236501192068949955178268487368462704 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Real part of: cacos (0.5 + +0 i) == 1.047197551196597746154214461093167628066 - 0 i":
+double: 1
+idouble: 1
+Test "Real part of: cacos (0.5 - 0 i) == 1.047197551196597746154214461093167628066 + +0 i":
+double: 1
+idouble: 1
+Test "Imaginary part of: cacos (1.5 + +0 i) == +0 - 0.9624236501192068949955178268487368462704 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+# cacosh
+Test "Real part of: cacosh (+0 + 0.5 i) == 0.4812118250596034474977589134243684231352 + pi/2 i":
+float: 1
+ifloat: 1
+Test "Real part of: cacosh (+0 + 1.0 i) == 0.8813735870195430252326093249797923090282 + pi/2 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Real part of: cacosh (+0 + 1.5 i) == 1.194763217287109304111930828519090523536 + pi/2 i":
+double: 1
+idouble: 1
+Test "Real part of: cacosh (+0 - 0.5 i) == 0.4812118250596034474977589134243684231352 - pi/2 i":
+float: 1
+ifloat: 1
+Test "Real part of: cacosh (+0 - 1.0 i) == 0.8813735870195430252326093249797923090282 - pi/2 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Real part of: cacosh (+0 - 1.5 i) == 1.194763217287109304111930828519090523536 - pi/2 i":
+double: 1
+idouble: 1
+Test "Real part of: cacosh (-0 + 0.5 i) == 0.4812118250596034474977589134243684231352 + pi/2 i":
+float: 1
+ifloat: 1
+Test "Real part of: cacosh (-0 + 1.0 i) == 0.8813735870195430252326093249797923090282 + pi/2 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Real part of: cacosh (-0 + 1.5 i) == 1.194763217287109304111930828519090523536 + pi/2 i":
+double: 1
+idouble: 1
+Test "Real part of: cacosh (-0 - 0.5 i) == 0.4812118250596034474977589134243684231352 - pi/2 i":
+float: 1
+ifloat: 1
+Test "Real part of: cacosh (-0 - 1.0 i) == 0.8813735870195430252326093249797923090282 - pi/2 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Real part of: cacosh (-0 - 1.5 i) == 1.194763217287109304111930828519090523536 - pi/2 i":
+double: 1
+idouble: 1
+Test "Imaginary part of: cacosh (-0.5 + +0 i) == +0 + 2.094395102393195492308428922186335256131 i":
+double: 1
+idouble: 1
+Test "Imaginary part of: cacosh (-0.5 - 0 i) == +0 - 2.094395102393195492308428922186335256131 i":
+double: 1
+idouble: 1
+Test "Real part of: cacosh (-1.5 + +0 i) == 0.9624236501192068949955178268487368462704 + pi i":
+float: 1
+ifloat: 1
+Test "Real part of: cacosh (-1.5 - 0 i) == 0.9624236501192068949955178268487368462704 - pi i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: cacosh (-2 - 3 i) == 1.9833870299165354323470769028940395 - 2.1414491111159960199416055713254211 i":
+float: 1
+ifloat: 1
+Test "Real part of: cacosh (1.5 + +0 i) == 0.9624236501192068949955178268487368462704 + +0 i":
+float: 1
+ifloat: 1
+Test "Real part of: cacosh (1.5 - 0 i) == 0.9624236501192068949955178268487368462704 - 0 i":
+float: 1
+ifloat: 1
+
+# casin
+Test "Imaginary part of: casin (+0 + 0.5 i) == +0 + 0.4812118250596034474977589134243684231352 i":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "Imaginary part of: casin (+0 + 1.0 i) == +0 + 0.8813735870195430252326093249797923090282 i":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "Imaginary part of: casin (+0 + 1.5 i) == +0 + 1.194763217287109304111930828519090523536 i":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "Imaginary part of: casin (+0 - 0.5 i) == +0 - 0.4812118250596034474977589134243684231352 i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: casin (+0 - 1.0 i) == +0 - 0.8813735870195430252326093249797923090282 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: casin (+0 - 1.5 i) == +0 - 1.194763217287109304111930828519090523536 i":
+double: 1
+idouble: 1
+Test "Imaginary part of: casin (-0 + 0.5 i) == -0 + 0.4812118250596034474977589134243684231352 i":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "Imaginary part of: casin (-0 + 1.0 i) == -0 + 0.8813735870195430252326093249797923090282 i":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "Imaginary part of: casin (-0 + 1.5 i) == -0 + 1.194763217287109304111930828519090523536 i":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "Imaginary part of: casin (-0 - 0.5 i) == -0 - 0.4812118250596034474977589134243684231352 i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: casin (-0 - 1.0 i) == -0 - 0.8813735870195430252326093249797923090282 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: casin (-0 - 1.5 i) == -0 - 1.194763217287109304111930828519090523536 i":
+double: 1
+idouble: 1
+Test "Imaginary part of: casin (-1.5 + +0 i) == -pi/2 + 0.9624236501192068949955178268487368462704 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Real part of: casin (0.75 + 1.25 i) == 0.453276177638793913448921196101971749 + 1.13239363160530819522266333696834467 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: casin (1.5 + +0 i) == pi/2 + 0.9624236501192068949955178268487368462704 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+# casinh
+Test "Real part of: casinh (-0 + 1.5 i) == -0.9624236501192068949955178268487368462704 + pi/2 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Real part of: casinh (-0 - 1.5 i) == -0.9624236501192068949955178268487368462704 - pi/2 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Real part of: casinh (-0.5 + +0 i) == -0.4812118250596034474977589134243684231352 + +0 i":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "Real part of: casinh (-0.5 - 0 i) == -0.4812118250596034474977589134243684231352 - 0 i":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "Real part of: casinh (-1.0 + +0 i) == -0.8813735870195430252326093249797923090282 + +0 i":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "Real part of: casinh (-1.0 - 0 i) == -0.8813735870195430252326093249797923090282 - 0 i":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "Real part of: casinh (-1.5 + +0 i) == -1.194763217287109304111930828519090523536 + +0 i":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "Real part of: casinh (-1.5 - 0 i) == -1.194763217287109304111930828519090523536 - 0 i":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "Real part of: casinh (-2 - 3 i) == -1.9686379257930962917886650952454982 - 0.96465850440760279204541105949953237 i":
+double: 5
+float: 1
+idouble: 5
+ifloat: 1
+Test "Imaginary part of: casinh (-2 - 3 i) == -1.9686379257930962917886650952454982 - 0.96465850440760279204541105949953237 i":
+double: 3
+float: 6
+idouble: 3
+ifloat: 6
+Test "Real part of: casinh (0.5 + +0 i) == 0.4812118250596034474977589134243684231352 + +0 i":
+float: 1
+ifloat: 1
+Test "Real part of: casinh (0.5 - 0 i) == 0.4812118250596034474977589134243684231352 - 0 i":
+float: 1
+ifloat: 1
+Test "Real part of: casinh (0.75 + 1.25 i) == 1.03171853444778027336364058631006594 + 0.911738290968487636358489564316731207 i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: casinh (0.75 + 1.25 i) == 1.03171853444778027336364058631006594 + 0.911738290968487636358489564316731207 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Real part of: casinh (1.0 + +0 i) == 0.8813735870195430252326093249797923090282 + +0 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Real part of: casinh (1.0 - 0 i) == 0.8813735870195430252326093249797923090282 - 0 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Real part of: casinh (1.5 + +0 i) == 1.194763217287109304111930828519090523536 + +0 i":
+double: 1
+idouble: 1
+Test "Real part of: casinh (1.5 - 0 i) == 1.194763217287109304111930828519090523536 - 0 i":
+double: 1
+idouble: 1
+
+# catan
+Test "Imaginary part of: catan (-2 - 3 i) == -1.4099210495965755225306193844604208 - 0.22907268296853876629588180294200276 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+# catanh
+Test "Real part of: catanh (-2 - 3 i) == -0.14694666622552975204743278515471595 - 1.3389725222944935611241935759091443 i":
+double: 4
+idouble: 4
+Test "Real part of: catanh (0.75 + 1.25 i) == 0.261492138795671927078652057366532140 + 0.996825126463918666098902241310446708 i":
+double: 1
+idouble: 1
+
+# cbrt
+Test "cbrt (-27.0) == -3.0":
+double: 1
+idouble: 1
+Test "cbrt (0.75) == 0.908560296416069829445605878163630251":
+double: 1
+idouble: 1
+Test "cbrt (0.9921875) == 0.997389022060725270579075195353955217":
+double: 1
+idouble: 1
+
+# ccos
+Test "Imaginary part of: ccos (-0.75 + 710.5 i) == 1.347490911916428129246890157395342279438e308 + 1.255317763348154410745082950806112487736e308 i":
+double: 1
+idouble: 1
+Test "Imaginary part of: ccos (-0.75 + 89.5 i) == 2.708024460708609732016532185663087200560e38 + 2.522786001038096774676288412995370563339e38 i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: ccos (-0.75 - 710.5 i) == 1.347490911916428129246890157395342279438e308 - 1.255317763348154410745082950806112487736e308 i":
+double: 1
+idouble: 1
+Test "Imaginary part of: ccos (-0.75 - 89.5 i) == 2.708024460708609732016532185663087200560e38 - 2.522786001038096774676288412995370563339e38 i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: ccos (-2 - 3 i) == -4.18962569096880723013255501961597373 - 9.10922789375533659797919726277886212 i":
+float: 1
+ifloat: 1
+Test "Real part of: ccos (0.75 + 1.25 i) == 1.38173873063425888530729933139078645 - 1.09193013555397466170919531722024128 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: ccos (0.75 + 1.25 i) == 1.38173873063425888530729933139078645 - 1.09193013555397466170919531722024128 i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: ccos (0.75 + 710.5 i) == 1.347490911916428129246890157395342279438e308 - 1.255317763348154410745082950806112487736e308 i":
+double: 1
+idouble: 1
+Test "Imaginary part of: ccos (0.75 + 89.5 i) == 2.708024460708609732016532185663087200560e38 - 2.522786001038096774676288412995370563339e38 i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: ccos (0.75 - 710.5 i) == 1.347490911916428129246890157395342279438e308 + 1.255317763348154410745082950806112487736e308 i":
+double: 1
+idouble: 1
+Test "Imaginary part of: ccos (0.75 - 89.5 i) == 2.708024460708609732016532185663087200560e38 + 2.522786001038096774676288412995370563339e38 i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: ccos (0x1p-1074 + 1440 i) == inf - 5.981479269486130556466515778180916082415e301 i":
+double: 1
+idouble: 1
+Test "Imaginary part of: ccos (0x1p-1074 + 1440 i) == inf - 5.981479269486130556466515778180916082415e301 i plus overflow exception":
+double: 1
+idouble: 1
+
+# ccosh
+Test "Real part of: ccosh (-2 - 3 i) == -3.72454550491532256547397070325597253 + 0.511822569987384608834463849801875634 i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: ccosh (-2 - 3 i) == -3.72454550491532256547397070325597253 + 0.511822569987384608834463849801875634 i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: ccosh (-710.5 + 0.75 i) == 1.347490911916428129246890157395342279438e308 - 1.255317763348154410745082950806112487736e308 i":
+double: 1
+idouble: 1
+Test "Imaginary part of: ccosh (-710.5 - 0.75 i) == 1.347490911916428129246890157395342279438e308 + 1.255317763348154410745082950806112487736e308 i":
+double: 1
+idouble: 1
+Test "Imaginary part of: ccosh (-89.5 + 0.75 i) == 2.708024460708609732016532185663087200560e38 - 2.522786001038096774676288412995370563339e38 i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: ccosh (-89.5 - 0.75 i) == 2.708024460708609732016532185663087200560e38 + 2.522786001038096774676288412995370563339e38 i":
+float: 1
+ifloat: 1
+Test "Real part of: ccosh (0.75 + 1.25 i) == 0.408242591877968807788852146397499084 + 0.780365930845853240391326216300863152 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: ccosh (0.75 + 1.25 i) == 0.408242591877968807788852146397499084 + 0.780365930845853240391326216300863152 i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: ccosh (1440 + 0x1p-1074 i) == inf + 5.981479269486130556466515778180916082415e301 i":
+double: 1
+idouble: 1
+Test "Imaginary part of: ccosh (1440 + 0x1p-1074 i) == inf + 5.981479269486130556466515778180916082415e301 i plus overflow exception":
+double: 1
+idouble: 1
+Test "Imaginary part of: ccosh (710.5 + 0.75 i) == 1.347490911916428129246890157395342279438e308 + 1.255317763348154410745082950806112487736e308 i":
+double: 1
+idouble: 1
+Test "Imaginary part of: ccosh (710.5 - 0.75 i) == 1.347490911916428129246890157395342279438e308 - 1.255317763348154410745082950806112487736e308 i":
+double: 1
+idouble: 1
+Test "Imaginary part of: ccosh (89.5 + 0.75 i) == 2.708024460708609732016532185663087200560e38 + 2.522786001038096774676288412995370563339e38 i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: ccosh (89.5 - 0.75 i) == 2.708024460708609732016532185663087200560e38 - 2.522786001038096774676288412995370563339e38 i":
+float: 1
+ifloat: 1
+
+# cexp
+Test "Imaginary part of: cexp (-2.0 - 3.0 i) == -0.13398091492954261346140525546115575 - 0.019098516261135196432576240858800925 i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: cexp (-95 + 0.75 i) == 4.039714446238306526889476684000081624047e-42 + 3.763383677300535390271646960780570275931e-42 i":
+double: 1
+idouble: 1
+Test "Real part of: cexp (0.75 + 1.25 i) == 0.667537446429131586942201977015932112 + 2.00900045494094876258347228145863909 i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: cexp (1440 + 0x1p-1074 i) == inf + 1.196295853897226111293303155636183216483e302 i":
+double: 1
+idouble: 1
+Test "Imaginary part of: cexp (1440 + 0x1p-1074 i) == inf + 1.196295853897226111293303155636183216483e302 i plus overflow exception":
+double: 1
+idouble: 1
+Test "Real part of: cexp (50 + 0x1p127 i) == 4.053997150228616856622417636046265337193e21 + 3.232070315463388524466674772633810238819e21 i":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "Imaginary part of: cexp (50 + 0x1p127 i) == 4.053997150228616856622417636046265337193e21 + 3.232070315463388524466674772633810238819e21 i":
+double: 1
+idouble: 1
+Test "Real part of: cexp (500 + 0x1p1023 i) == -1.159886268932754433233243794561351783426e217 + 7.904017694554466595359379965081774849708e216 i":
+double: 1
+idouble: 1
+Test "Real part of: cexp (709.8125 + 0.75 i) == 1.355121963080879535248452862759108365762e308 + 1.262426823598609432507811340856186873507e308 i":
+double: 1
+idouble: 1
+Test "Imaginary part of: cexp (709.8125 + 0.75 i) == 1.355121963080879535248452862759108365762e308 + 1.262426823598609432507811340856186873507e308 i":
+double: 1
+idouble: 1
+Test "Real part of: cexp (88.75 + 0.75 i) == 2.558360358486542817001900410314204322891e38 + 2.383359453227311447654736314679677655100e38 i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: cexp (88.75 + 0.75 i) == 2.558360358486542817001900410314204322891e38 + 2.383359453227311447654736314679677655100e38 i":
+float: 2
+ifloat: 2
+
+# clog
+Test "Real part of: clog (0.75 + 1.25 i) == 0.376885901188190075998919126749298416 + 1.03037682652431246378774332703115153 i":
+float: 1
+ifloat: 1
+Test "Real part of: clog (0x1p-1074 + 0x1p-1074 i) == -744.0934983311012896593986823853525458290 + pi/4 i":
+double: 1
+idouble: 1
+Test "Real part of: clog (0x1p-147 + 0x1p-147 i) == -101.5460619520319878296245057936228672231 + pi/4 i":
+float: 1
+ifloat: 1
+
+# clog10
+Test "Imaginary part of: clog10 (-0 + inf i) == inf + pi/2*log10(e) i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (-0 - inf i) == inf - pi/2*log10(e) i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (-2 - 3 i) == 0.556971676153418384603252578971164214 - 0.937554462986374708541507952140189646 i":
+double: 1
+idouble: 1
+Test "Imaginary part of: clog10 (-3 + inf i) == inf + pi/2*log10(e) i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (-3 - inf i) == inf - pi/2*log10(e) i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (-inf + 0 i) == inf + pi*log10(e) i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (-inf + 1 i) == inf + pi*log10(e) i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (-inf - 0 i) == inf - pi*log10(e) i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (-inf - 1 i) == inf - pi*log10(e) i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (0 + inf i) == inf + pi/2*log10(e) i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (0 - inf i) == inf - pi/2*log10(e) i":
+float: 1
+ifloat: 1
+Test "Real part of: clog10 (0.75 + 1.25 i) == 0.163679467193165171449476605077428975 + 0.447486970040493067069984724340855636 i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (0x1.fffffep+127 + 0x1.fffffep+127 i) == 38.68235441693561449174780668781319348761 + pi/4*log10(e) i":
+float: 1
+ifloat: 1
+Test "Real part of: clog10 (0x1.fffffep+127 + 1.0 i) == 38.53183941910362389414093724045094697423 + 1.276276851248440096917018665609900318458e-39 i":
+float: 1
+ifloat: 1
+Test "Real part of: clog10 (0x1p-1074 + 0x1p-1074 i) == -323.1557003452838130619487034867432642357 + pi/4*log10(e) i":
+double: 1
+idouble: 1
+Test "Imaginary part of: clog10 (0x1p-147 + 0x1p-147 i) == -44.10089436477324509881274807713822842154 + pi/4*log10(e) i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (0x1p-149 + 0x1p-149 i) == -44.70295435610120748924022586658721447508 + pi/4*log10(e) i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (3 + inf i) == inf + pi/2*log10(e) i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (3 - inf i) == inf - pi/2*log10(e) i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (inf + inf i) == inf + pi/4*log10(e) i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (inf - inf i) == inf - pi/4*log10(e) i":
+float: 1
+ifloat: 1
+
+# cos
+Test "cos (M_PI_6l * 2.0) == 0.5":
+double: 1
+idouble: 1
+Test "cos (M_PI_6l * 4.0) == -0.5":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+
+# cos_tonearest
+Test "cos_tonearest (7) == 0.7539022543433046381411975217191820122183":
+float: 1
+ifloat: 1
+
+# cpow
+Test "Real part of: cpow (0.75 + 1.25 i, 0.0 + 1.0 i) == 0.331825439177608832276067945276730566 + 0.131338600281188544930936345230903032 i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: cpow (0.75 + 1.25 i, 0.0 + 1.0 i) == 0.331825439177608832276067945276730566 + 0.131338600281188544930936345230903032 i":
+float: 1
+ifloat: 1
+Test "Real part of: cpow (0.75 + 1.25 i, 0.75 + 1.25 i) == 0.117506293914473555420279832210420483 + 0.346552747708338676483025352060418001 i":
+double: 1
+float: 4
+idouble: 1
+ifloat: 4
+Test "Real part of: cpow (0.75 + 1.25 i, 1.0 + 1.0 i) == 0.0846958290317209430433805274189191353 + 0.513285749182902449043287190519090481 i":
+double: 2
+float: 3
+idouble: 2
+ifloat: 3
+Test "Real part of: cpow (2 + 3 i, 4 + 0 i) == -119.0 - 120.0 i":
+double: 1
+float: 4
+idouble: 1
+ifloat: 4
+Test "Imaginary part of: cpow (2 + 3 i, 4 + 0 i) == -119.0 - 120.0 i":
+float: 2
+ifloat: 2
+Test "Imaginary part of: cpow (e + 0 i, 0 + 2 * M_PIl i) == 1.0 + 0.0 i":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+
+# csin
+Test "Real part of: csin (-0.75 + 710.5 i) == -1.255317763348154410745082950806112487736e308 + 1.347490911916428129246890157395342279438e308 i":
+double: 1
+idouble: 1
+Test "Real part of: csin (-0.75 + 89.5 i) == -2.522786001038096774676288412995370563339e38 + 2.708024460708609732016532185663087200560e38 i":
+float: 1
+ifloat: 1
+Test "Real part of: csin (-0.75 - 710.5 i) == -1.255317763348154410745082950806112487736e308 - 1.347490911916428129246890157395342279438e308 i":
+double: 1
+idouble: 1
+Test "Real part of: csin (-0.75 - 89.5 i) == -2.522786001038096774676288412995370563339e38 - 2.708024460708609732016532185663087200560e38 i":
+float: 1
+ifloat: 1
+Test "Real part of: csin (0.75 + 710.5 i) == 1.255317763348154410745082950806112487736e308 + 1.347490911916428129246890157395342279438e308 i":
+double: 1
+idouble: 1
+Test "Real part of: csin (0.75 + 89.5 i) == 2.522786001038096774676288412995370563339e38 + 2.708024460708609732016532185663087200560e38 i":
+float: 1
+ifloat: 1
+Test "Real part of: csin (0.75 - 710.5 i) == 1.255317763348154410745082950806112487736e308 - 1.347490911916428129246890157395342279438e308 i":
+double: 1
+idouble: 1
+Test "Real part of: csin (0.75 - 89.5 i) == 2.522786001038096774676288412995370563339e38 - 2.708024460708609732016532185663087200560e38 i":
+float: 1
+ifloat: 1
+Test "Real part of: csin (0x1p-1074 + 1440 i) == 5.981479269486130556466515778180916082415e301 + inf i":
+double: 1
+idouble: 1
+Test "Real part of: csin (0x1p-1074 + 1440 i) == 5.981479269486130556466515778180916082415e301 + inf i plus overflow exception":
+double: 1
+idouble: 1
+
+# csinh
+Test "Imaginary part of: csinh (-2 - 3 i) == 3.59056458998577995201256544779481679 - 0.530921086248519805267040090660676560 i":
+double: 1
+idouble: 1
+Test "Imaginary part of: csinh (-710.5 + 0.75 i) == -1.347490911916428129246890157395342279438e308 + 1.255317763348154410745082950806112487736e308 i":
+double: 1
+idouble: 1
+Test "Imaginary part of: csinh (-710.5 - 0.75 i) == -1.347490911916428129246890157395342279438e308 - 1.255317763348154410745082950806112487736e308 i":
+double: 1
+idouble: 1
+Test "Imaginary part of: csinh (-89.5 + 0.75 i) == -2.708024460708609732016532185663087200560e38 + 2.522786001038096774676288412995370563339e38 i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: csinh (-89.5 - 0.75 i) == -2.708024460708609732016532185663087200560e38 - 2.522786001038096774676288412995370563339e38 i":
+float: 1
+ifloat: 1
+Test "Real part of: csinh (0.75 + 1.25 i) == 0.259294854551162779153349830618433028 + 1.22863452409509552219214606515777594 i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: csinh (0.75 + 1.25 i) == 0.259294854551162779153349830618433028 + 1.22863452409509552219214606515777594 i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: csinh (1440 + 0x1p-1074 i) == inf + 5.981479269486130556466515778180916082415e301 i":
+double: 1
+idouble: 1
+Test "Imaginary part of: csinh (1440 + 0x1p-1074 i) == inf + 5.981479269486130556466515778180916082415e301 i plus overflow exception":
+double: 1
+idouble: 1
+Test "Imaginary part of: csinh (710.5 + 0.75 i) == 1.347490911916428129246890157395342279438e308 + 1.255317763348154410745082950806112487736e308 i":
+double: 1
+idouble: 1
+Test "Imaginary part of: csinh (710.5 - 0.75 i) == 1.347490911916428129246890157395342279438e308 - 1.255317763348154410745082950806112487736e308 i":
+double: 1
+idouble: 1
+Test "Imaginary part of: csinh (89.5 + 0.75 i) == 2.708024460708609732016532185663087200560e38 + 2.522786001038096774676288412995370563339e38 i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: csinh (89.5 - 0.75 i) == 2.708024460708609732016532185663087200560e38 - 2.522786001038096774676288412995370563339e38 i":
+float: 1
+ifloat: 1
+
+# csqrt
+Test "Real part of: csqrt (-2 + 3 i) == 0.89597747612983812471573375529004348 + 1.6741492280355400404480393008490519 i":
+float: 1
+ifloat: 1
+Test "Real part of: csqrt (-2 - 3 i) == 0.89597747612983812471573375529004348 - 1.6741492280355400404480393008490519 i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: csqrt (0x1.fffffep+127 + 1.0 i) == 1.844674352395372953599975585936590505260e+19 + 2.710505511993121390769065968615872097053e-20 i":
+float: 1
+ifloat: 1
+Test "Real part of: csqrt (0x1.fffffffffffffp+1023 + 0x1.fffffffffffffp+1023 i) == 1.473094556905565378990473658199034571917e+154 + 6.101757441282702188537080005372547713595e+153 i":
+double: 1
+idouble: 1
+Test "Imaginary part of: csqrt (0x1.fffffffffffffp+1023 + 0x1.fffffffffffffp+1023 i) == 1.473094556905565378990473658199034571917e+154 + 6.101757441282702188537080005372547713595e+153 i":
+double: 1
+idouble: 1
+Test "Imaginary part of: csqrt (0x1.fffffffffffffp+1023 + 0x1p+1023 i) == 1.379778091031440685006200821918878702861e+154 + 3.257214233483129514781233066898042490248e+153 i":
+double: 1
+idouble: 1
+
+# ctan
+Test "Real part of: ctan (-2 - 3 i) == 0.376402564150424829275122113032269084e-2 - 1.00323862735360980144635859782192726 i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: ctan (-2 - 3 i) == 0.376402564150424829275122113032269084e-2 - 1.00323862735360980144635859782192726 i":
+double: 1
+idouble: 1
+Test "Imaginary part of: ctan (0.75 + 1.25 i) == 0.160807785916206426725166058173438663 + 0.975363285031235646193581759755216379 i":
+double: 1
+idouble: 1
+Test "Real part of: ctan (0x1p1023 + 1 i) == -0.2254627924997545057926782581695274244229 + 0.8786063118883068695462540226219865087189 i":
+double: 1
+idouble: 1
+Test "Imaginary part of: ctan (0x1p127 + 1 i) == 0.2446359391192790896381501310437708987204 + 0.9101334047676183761532873794426475906201 i":
+double: 1
+idouble: 1
+Test "Real part of: ctan (0x3.243f6cp-1 + 0 i) == -2.287733242885645987394874673945769518150e7 + 0.0 i":
+float: 1
+ifloat: 1
+
+# ctanh
+Test "Real part of: ctanh (-2 - 3 i) == -0.965385879022133124278480269394560686 + 0.988437503832249372031403430350121098e-2 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: ctanh (-2 - 3 i) == -0.965385879022133124278480269394560686 + 0.988437503832249372031403430350121098e-2 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: ctanh (0 + 0x3.243f6cp-1 i) == 0.0 - 2.287733242885645987394874673945769518150e7 i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: ctanh (0 + pi/4 i) == 0.0 + 1.0 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Real part of: ctanh (0.75 + 1.25 i) == 1.37260757053378320258048606571226857 + 0.385795952609750664177596760720790220 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: ctanh (0.75 + 1.25 i) == 1.37260757053378320258048606571226857 + 0.385795952609750664177596760720790220 i":
+float: 2
+ifloat: 2
+Test "Imaginary part of: ctanh (1 + 0x1p1023 i) == 0.8786063118883068695462540226219865087189 - 0.2254627924997545057926782581695274244229 i":
+double: 1
+idouble: 1
+Test "Real part of: ctanh (1 + 0x1p127 i) == 0.9101334047676183761532873794426475906201 + 0.2446359391192790896381501310437708987204 i":
+double: 1
+idouble: 1
+
+# erf
+Test "erf (1.25) == 0.922900128256458230136523481197281140":
+double: 1
+idouble: 1
+
+# erfc
+Test "erfc (0x1.f7303cp+1) == 2.705500297238986897105236321218861842255e-8":
+double: 1
+idouble: 1
+Test "erfc (0x1.ffa002p+2) == 1.233585992097580296336099501489175967033e-29":
+float: 1
+ifloat: 1
+Test "erfc (2.0) == 0.00467773498104726583793074363274707139":
+double: 1
+idouble: 1
+Test "erfc (4.125) == 0.542340079956506600531223408575531062e-8":
+double: 1
+idouble: 1
+
+# exp10
+Test "exp10 (-1) == 0.1":
+double: 1
+idouble: 1
+Test "exp10 (-305) == 1.0e-305":
+double: 1
+idouble: 1
+Test "exp10 (-36) == 1.0e-36":
+double: 1
+idouble: 1
+Test "exp10 (3) == 1000":
+double: 1
+idouble: 1
+Test "exp10 (36) == 1.0e36":
+double: 1
+idouble: 1
+
+# expm1
+Test "expm1 (0.75) == 1.11700001661267466854536981983709561":
+double: 1
+idouble: 1
+Test "expm1 (1) == M_El - 1.0":
+float: 1
+ifloat: 1
+Test "expm1 (500.0) == 1.4035922178528374107397703328409120821806e+217":
+double: 1
+idouble: 1
+
+# fma
+Test "fma (-0x1.fffffffffffffp-711, 0x1.fffffffffffffp-275, 0x1.fffffe00007ffp-983) == 0x1.7ffffe00007ffp-983":
+double: 1
+idouble: 1
+Test "fma (0x1.0000002p+0, 0x1.ffffffcp-1, -0x1p-300) == 0x1.fffffffffffffp-1":
+double: 1
+idouble: 1
+Test "fma (0x1.153d650bb9f06p-907, 0x1.2d01230d48407p-125, -0x0.b278d5acfc3cp-1022) == -0x0.b22757123bbe9p-1022":
+double: 1
+idouble: 1
+Test "fma (0x1.4000004p-967, 0x1p-106, 0x0.000001p-1022) == 0x0.0000010000003p-1022":
+double: 1
+idouble: 1
+Test "fma (0x1.7ff8p+13, 0x1.000002p+0, 0x1.ffffp-24) == 0x1.7ff802p+13":
+float: 1
+ifloat: 1
+Test "fma (0x1.7fffff8p-968, 0x1p-106, 0x0.000001p-1022) == 0x0.0000010000001p-1022":
+double: 1
+idouble: 1
+
+# hypot
+Test "hypot (-0.7, -12.4) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "hypot (-0.7, 12.4) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "hypot (-12.4, -0.7) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "hypot (-12.4, 0.7) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "hypot (0.7, -12.4) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "hypot (0.7, 12.4) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "hypot (12.4, -0.7) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "hypot (12.4, 0.7) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+
+# j0
+Test "j0 (-4.0) == -3.9714980986384737228659076845169804197562E-1":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "j0 (0.75) == 0.864242275166648623555731103820923211":
+float: 1
+ifloat: 1
+Test "j0 (0x1.d7ce3ap+107) == 2.775523647291230802651040996274861694514e-17":
+float: 2
+ifloat: 2
+Test "j0 (10.0) == -0.245935764451348335197760862485328754":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "j0 (2.0) == 0.223890779141235668051827454649948626":
+float: 2
+ifloat: 2
+Test "j0 (4.0) == -3.9714980986384737228659076845169804197562E-1":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "j0 (8.0) == 0.171650807137553906090869407851972001":
+float: 1
+ifloat: 1
+
+# j1
+Test "j1 (0x1.3ffp+74) == 1.818984347516051243459364437186082741567e-12":
+double: 1
+idouble: 1
+Test "j1 (0x1.ff00000000002p+840) == 1.846591691699331493194965158699937660696e-127":
+double: 1
+idouble: 1
+Test "j1 (10.0) == 0.0434727461688614366697487680258592883":
+float: 2
+ifloat: 2
+Test "j1 (2.0) == 0.576724807756873387202448242269137087":
+double: 1
+idouble: 1
+Test "j1 (8.0) == 0.234636346853914624381276651590454612":
+double: 1
+idouble: 1
+
+# jn
+Test "jn (0, -4.0) == -3.9714980986384737228659076845169804197562E-1":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "jn (0, 0.75) == 0.864242275166648623555731103820923211":
+float: 1
+ifloat: 1
+Test "jn (0, 10.0) == -0.245935764451348335197760862485328754":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "jn (0, 2.0) == 0.223890779141235668051827454649948626":
+float: 2
+ifloat: 2
+Test "jn (0, 4.0) == -3.9714980986384737228659076845169804197562E-1":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "jn (0, 8.0) == 0.171650807137553906090869407851972001":
+float: 1
+ifloat: 1
+Test "jn (1, 10.0) == 0.0434727461688614366697487680258592883":
+float: 2
+ifloat: 2
+Test "jn (1, 2.0) == 0.576724807756873387202448242269137087":
+double: 1
+idouble: 1
+Test "jn (1, 8.0) == 0.234636346853914624381276651590454612":
+double: 1
+idouble: 1
+Test "jn (10, 0.125) == 0.250543369809369890173993791865771547e-18":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "jn (10, 0.75) == 0.149621713117596814698712483621682835e-10":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "jn (10, 10.0) == 0.207486106633358857697278723518753428":
+double: 4
+float: 3
+idouble: 4
+ifloat: 3
+Test "jn (10, 2.0) == 0.251538628271673670963516093751820639e-6":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+Test "jn (2, 0x1.ffff62p+99) == -4.43860668048170034334926693188979974489e-16":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+Test "jn (2, 2.4048255576957729) == 0.43175480701968038399746111312430703":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "jn (3, 0.125) == 0.406503832554912875023029337653442868e-4":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "jn (3, 0.75) == 0.848438342327410884392755236884386804e-2":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "jn (3, 10.0) == 0.0583793793051868123429354784103409563":
+double: 3
+float: 1
+idouble: 3
+ifloat: 1
+Test "jn (3, 2.0) == 0.128943249474402051098793332969239835":
+float: 1
+ifloat: 1
+Test "jn (3, 2.4048255576957729) == 0.19899990535769083404042146764530813":
+double: 3
+idouble: 3
+Test "jn (4, 2.4048255576957729) == 0.647466661641779720084932282551219891E-1":
+double: 1
+idouble: 1
+Test "jn (5, 2.4048255576957729) == 0.163892432048058525099230549946147698E-1":
+double: 3
+float: 1
+idouble: 3
+ifloat: 1
+Test "jn (6, 2.4048255576957729) == 0.34048184720278336646673682895929161E-2":
+double: 4
+float: 3
+idouble: 4
+ifloat: 3
+Test "jn (7, 2.4048255576957729) == 0.60068836573295394221291569249883076E-3":
+double: 3
+float: 5
+idouble: 3
+ifloat: 5
+Test "jn (8, 2.4048255576957729) == 0.92165786705344923232879022467054148E-4":
+double: 3
+float: 2
+idouble: 3
+ifloat: 2
+Test "jn (9, 2.4048255576957729) == 0.12517270977961513005428966643852564E-4":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+
+# lgamma
+Test "lgamma (0.7) == 0.260867246531666514385732417016759578":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "lgamma (1.2) == -0.853740900033158497197028392998854470e-1":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+
+# log10
+Test "log10 (0.75) == -0.124938736608299953132449886193870744":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+Test "log10 (e) == log10(e)":
+float: 1
+ifloat: 1
+
+# log1p
+Test "log1p (-0.25) == -0.287682072451780927439219005993827432":
+float: 1
+ifloat: 1
+
+# pow
+Test "pow (0x0.ffffffp0, -0x1p24) == 2.7182819094701610539628664526874952929416":
+float: 1
+ifloat: 1
+Test "pow (0x0.ffffffp0, 0x1p24) == 0.3678794302077803437135155590023422899744":
+float: 1
+ifloat: 1
+Test "pow (0x1.000002p0, 0x1p24) == 7.3890552180866447284268641248075832310141":
+float: 1
+ifloat: 1
+
+# sin_tonearest
+Test "sin_tonearest (1) == 0.8414709848078965066525023216302989996226":
+float: 1
+ifloat: 1
+
+# sincos
+Test "sincos (M_PI_6l*2.0, &sin_res, &cos_res) puts 0.5 in cos_res":
+double: 1
+idouble: 1
+Test "sincos (M_PI_6l*2.0, &sin_res, &cos_res) puts 0.86602540378443864676372317075293616 in sin_res":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "sincos (pi/6, &sin_res, &cos_res) puts 0.86602540378443864676372317075293616 in cos_res":
+float: 1
+ifloat: 1
+
+# tgamma
+Test "tgamma (-0.5) == -2 sqrt (pi)":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "tgamma (0.5) == sqrt (pi)":
+float: 1
+ifloat: 1
+Test "tgamma (0.7) == 1.29805533264755778568117117915281162":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+# y0
+Test "y0 (0x1.3ffp+74) == 1.818984347516051243459467456433028748678e-12":
+double: 1
+idouble: 1
+Test "y0 (0x1.ff00000000002p+840) == 1.846591691699331493194965158699937660696e-127":
+double: 1
+idouble: 1
+Test "y0 (1.0) == 0.0882569642156769579829267660235151628":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "y0 (1.5) == 0.382448923797758843955068554978089862":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "y0 (10.0) == 0.0556711672835993914244598774101900481":
+float: 1
+ifloat: 1
+Test "y0 (8.0) == 0.223521489387566220527323400498620359":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+# y1
+Test "y1 (0.125) == -5.19993611253477499595928744876579921":
+double: 1
+idouble: 1
+Test "y1 (0x1.27e204p+99) == -8.881610148467797208469612080785210013461e-16":
+double: 1
+idouble: 1
+Test "y1 (1.5) == -0.412308626973911295952829820633445323":
+float: 1
+ifloat: 1
+Test "y1 (10.0) == 0.249015424206953883923283474663222803":
+double: 3
+float: 1
+idouble: 3
+ifloat: 1
+Test "y1 (2.0) == -0.107032431540937546888370772277476637":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "y1 (8.0) == -0.158060461731247494255555266187483550":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+
+# yn
+Test "yn (0, 1.0) == 0.0882569642156769579829267660235151628":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "yn (0, 1.5) == 0.382448923797758843955068554978089862":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "yn (0, 10.0) == 0.0556711672835993914244598774101900481":
+float: 1
+ifloat: 1
+Test "yn (0, 8.0) == 0.223521489387566220527323400498620359":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "yn (1, 0.125) == -5.19993611253477499595928744876579921":
+double: 1
+idouble: 1
+Test "yn (1, 1.5) == -0.412308626973911295952829820633445323":
+float: 1
+ifloat: 1
+Test "yn (1, 10.0) == 0.249015424206953883923283474663222803":
+double: 3
+float: 1
+idouble: 3
+ifloat: 1
+Test "yn (1, 2.0) == -0.107032431540937546888370772277476637":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "yn (1, 8.0) == -0.158060461731247494255555266187483550":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+Test "yn (10, 0.125) == -127057845771019398.252538486899753195":
+double: 1
+idouble: 1
+Test "yn (10, 0.75) == -2133501638.90573424452445412893839236":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "yn (10, 1.0) == -121618014.278689189288130426667971145":
+double: 1
+idouble: 1
+Test "yn (10, 10.0) == -0.359814152183402722051986577343560609":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "yn (10, 2.0) == -129184.542208039282635913145923304214":
+double: 2
+idouble: 2
+Test "yn (3, 0.125) == -2612.69757350066712600220955744091741":
+double: 1
+idouble: 1
+Test "yn (3, 0.75) == -12.9877176234475433186319774484809207":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "yn (3, 10.0) == -0.251362657183837329779204747654240998":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "yn (3, 2.0) == -1.12778377684042778608158395773179238":
+double: 1
+idouble: 1
+
+# Maximal error of functions:
+Function: "atan2":
+float: 1
+ifloat: 1
+
+Function: "atanh":
+float: 1
+ifloat: 1
+
+Function: Real part of "cacos":
+double: 1
+idouble: 1
+
+Function: Imaginary part of "cacos":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+
+Function: Real part of "cacosh":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: Imaginary part of "cacosh":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: Real part of "casin":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: Imaginary part of "casin":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+
+Function: Real part of "casinh":
+double: 5
+float: 1
+idouble: 5
+ifloat: 1
+
+Function: Imaginary part of "casinh":
+double: 3
+float: 6
+idouble: 3
+ifloat: 6
+
+Function: Imaginary part of "catan":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: Real part of "catanh":
+double: 4
+idouble: 4
+
+Function: "cbrt":
+double: 1
+idouble: 1
+
+Function: Real part of "ccos":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: Imaginary part of "ccos":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: Real part of "ccosh":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: Imaginary part of "ccosh":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: Real part of "cexp":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+
+Function: Imaginary part of "cexp":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+
+Function: Real part of "clog":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: Real part of "clog10":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: Imaginary part of "clog10":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: "cos":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+
+Function: "cos_tonearest":
+float: 1
+ifloat: 1
+
+Function: Real part of "cpow":
+double: 2
+float: 4
+idouble: 2
+ifloat: 4
+
+Function: Imaginary part of "cpow":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+
+Function: Real part of "csin":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: Real part of "csinh":
+float: 1
+ifloat: 1
+
+Function: Imaginary part of "csinh":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: Real part of "csqrt":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: Imaginary part of "csqrt":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: Real part of "ctan":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: Imaginary part of "ctan":
+double: 1
+idouble: 1
+
+Function: Real part of "ctanh":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: Imaginary part of "ctanh":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+
+Function: "erf":
+double: 1
+idouble: 1
+
+Function: "erfc":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: "exp10":
+double: 1
+idouble: 1
+
+Function: "expm1":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: "fma":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: "hypot":
+float: 1
+ifloat: 1
+
+Function: "j0":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+
+Function: "j1":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+
+Function: "jn":
+double: 4
+float: 5
+idouble: 4
+ifloat: 5
+
+Function: "lgamma":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+
+Function: "log10":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+
+Function: "log1p":
+float: 1
+ifloat: 1
+
+Function: "pow":
+float: 1
+ifloat: 1
+
+Function: "sin_tonearest":
+float: 1
+ifloat: 1
+
+Function: "sincos":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: "tan":
+double: 1
+idouble: 1
+
+Function: "tgamma":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: "y0":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+
+Function: "y1":
+double: 3
+float: 2
+idouble: 3
+ifloat: 2
+
+Function: "yn":
+double: 3
+float: 2
+idouble: 3
+ifloat: 2
+
+# end of automatic generation
diff --git a/ports/sysdeps/tile/machine-gmon.h b/ports/sysdeps/tile/machine-gmon.h
new file mode 100644
index 0000000000..9abaffbc01
--- /dev/null
+++ b/ports/sysdeps/tile/machine-gmon.h
@@ -0,0 +1,25 @@
+/* Copyright (C) 2011 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#define _MCOUNT_DECL(from, self) \
+ void __mcount_internal (u_long from, u_long self)
+
+/* Call __mcount_internal with our the return PC for our caller, and
+   the return PC our caller will return to.  Empty since we use an
+   assembly stub instead. */
+#define MCOUNT
diff --git a/ports/sysdeps/tile/math_private.h b/ports/sysdeps/tile/math_private.h
new file mode 100644
index 0000000000..858db4a051
--- /dev/null
+++ b/ports/sysdeps/tile/math_private.h
@@ -0,0 +1,13 @@
+#ifndef _MATH_PRIVATE_H
+
+#include_next <math_private.h>
+
+/* We have no exception support, so feraiseexcept() must be a no-op.
+   And since we don't define FE_INVALID, FE_DIVBYZERO, etc., we
+   must ignore the argument of feraiseexcept() as well.  we return
+   "1" to indicate we failed to raise an exception, though none of
+   the callers in glibc actually care.  The extra level of statement
+   expression wrapping avoids "statement with no effect" warnings.  */
+#define feraiseexcept(excepts) ({ 1; })
+
+#endif
diff --git a/ports/sysdeps/tile/nptl/Makefile b/ports/sysdeps/tile/nptl/Makefile
new file mode 100644
index 0000000000..66749284c7
--- /dev/null
+++ b/ports/sysdeps/tile/nptl/Makefile
@@ -0,0 +1,20 @@
+# Copyright (C) 2002, 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, see
+# <http://www.gnu.org/licenses/>.
+
+ifeq ($(subdir),csu)
+gen-as-const-headers += tcb-offsets.sym
+endif
diff --git a/ports/sysdeps/tile/nptl/pthread_spin_lock.c b/ports/sysdeps/tile/nptl/pthread_spin_lock.c
new file mode 100644
index 0000000000..18716f44c9
--- /dev/null
+++ b/ports/sysdeps/tile/nptl/pthread_spin_lock.c
@@ -0,0 +1,56 @@
+/* Copyright (C) 2011 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+
+   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 <arch/spr_def.h>
+#include <atomic.h>
+
+/* Bound point for bounded exponential backoff */
+#define BACKOFF_MAX 2048
+
+/* Initial cycle delay for exponential backoff */
+#define BACKOFF_START 32
+
+#ifdef __tilegx__
+/* Use cmpexch() after the initial fast-path exch to avoid
+   invalidating the cache line of the lock holder.  */
+# define TNS(p) atomic_exchange_acq((p), 1)
+# define CMPTNS(p) atomic_compare_and_exchange_val_acq((p), 1, 0)
+#else
+# define TNS(p) __insn_tns(p)
+# define CMPTNS(p) __insn_tns(p)
+# define SPR_CYCLE SPR_CYCLE_LOW   /* The low 32 bits are sufficient. */
+#endif
+
+int
+pthread_spin_lock (pthread_spinlock_t *lock)
+{
+  if (__builtin_expect (TNS (lock) != 0, 0))
+    {
+      unsigned int backoff = BACKOFF_START;
+      while (CMPTNS (lock) != 0)
+        {
+          unsigned int start = __insn_mfspr (SPR_CYCLE);
+          while (__insn_mfspr (SPR_CYCLE) - start < backoff)
+            ;
+          if (backoff < BACKOFF_MAX)
+            backoff *= 2;
+        }
+    }
+  return 0;
+}
diff --git a/ports/sysdeps/tile/nptl/pthread_spin_trylock.c b/ports/sysdeps/tile/nptl/pthread_spin_trylock.c
new file mode 100644
index 0000000000..fb67f36deb
--- /dev/null
+++ b/ports/sysdeps/tile/nptl/pthread_spin_trylock.c
@@ -0,0 +1,32 @@
+/* Copyright (C) 2011 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+
+   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 <errno.h>
+
+#ifdef __tilegx__
+#define TNS(p) __insn_exch4((p), 1)
+#else
+#define TNS(p) __insn_tns(p)
+#endif
+
+int
+pthread_spin_trylock (pthread_spinlock_t *lock)
+{
+  return (TNS (lock) == 0) ? 0 : EBUSY;
+}
diff --git a/ports/sysdeps/tile/nptl/pthreaddef.h b/ports/sysdeps/tile/nptl/pthreaddef.h
new file mode 100644
index 0000000000..2b54687994
--- /dev/null
+++ b/ports/sysdeps/tile/nptl/pthreaddef.h
@@ -0,0 +1,41 @@
+/* Copyright (C) 2011 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+
+   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 <stdlib.h>
+#include <string.h>
+
+/* 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 --git a/ports/sysdeps/tile/nptl/tcb-offsets.sym b/ports/sysdeps/tile/nptl/tcb-offsets.sym
new file mode 100644
index 0000000000..6740bc976f
--- /dev/null
+++ b/ports/sysdeps/tile/nptl/tcb-offsets.sym
@@ -0,0 +1,17 @@
+#define SHARED  /* needed to get struct rtld_global from <ldsodefs.h> */
+#include <sysdep.h>
+#include <tls.h>
+#include <ldsodefs.h>
+
+--
+
+-- Abuse tls.h macros to derive offsets relative to the thread register.
+#define thread_offsetof(mem)	(long)(offsetof(struct pthread, mem) - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE)
+
+MULTIPLE_THREADS_OFFSET		thread_offsetof (header.multiple_threads)
+PID_OFFSET			thread_offsetof (pid)
+TID_OFFSET			thread_offsetof (tid)
+POINTER_GUARD			(offsetof (tcbhead_t, pointer_guard) - TLS_TCB_OFFSET - sizeof (tcbhead_t))
+FEEDBACK_DATA_OFFSET		(offsetof (tcbhead_t, feedback_data) - TLS_TCB_OFFSET - sizeof (tcbhead_t))
+DTV_OFFSET			(offsetof (tcbhead_t, dtv) - TLS_TCB_OFFSET - sizeof (tcbhead_t))
+TLS_GENERATION_OFFSET		offsetof (struct rtld_global, _dl_tls_generation)
diff --git a/ports/sysdeps/tile/nptl/tls.h b/ports/sysdeps/tile/nptl/tls.h
new file mode 100644
index 0000000000..303a95e000
--- /dev/null
+++ b/ports/sysdeps/tile/nptl/tls.h
@@ -0,0 +1,194 @@
+/* Copyright (C) 2011 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+
+   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 _TLS_H
+#define _TLS_H	1
+
+# include <dl-sysdep.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__ */
+
+
+#ifndef __ASSEMBLER__
+
+/* Get system call information.  */
+# include <sysdep.h>
+
+/* The TP points to the start of the thread blocks.  */
+# define TLS_DTV_AT_TP	1
+
+/* We use the multiple_threads field in the pthread struct */
+#define TLS_MULTIPLE_THREADS_IN_TCB	1
+
+/* Get the thread descriptor definition.  */
+# include <nptl/descr.h>
+
+/* The stack_guard is accessed directly by GCC -fstack-protector code,
+   so it is a part of public ABI.  The dtv and pointer_guard fields
+   are private.  */
+typedef struct
+{
+  void *feedback_data;
+  uintptr_t pointer_guard;
+  uintptr_t stack_guard;
+  dtv_t *dtv;
+} tcbhead_t;
+
+/* This is the size of the initial TCB.  Because our TCB is before the thread
+   pointer, we don't need this.  */
+# define TLS_INIT_TCB_SIZE	0
+
+/* Alignment requirements for the initial TCB.  */
+# define TLS_INIT_TCB_ALIGN	__alignof__ (struct pthread)
+
+/* This is the size of the TCB.  Because our TCB is before the thread
+   pointer, we don't need this.  */
+# define TLS_TCB_SIZE		0
+
+/* Alignment requirements for the TCB.  */
+# define TLS_TCB_ALIGN		__alignof__ (struct pthread)
+
+/* This is the size we need before TCB - actually, it includes the TCB.  */
+# define TLS_PRE_TCB_SIZE \
+  (sizeof (struct pthread)						      \
+   + ((sizeof (tcbhead_t) + TLS_TCB_ALIGN - 1) & ~(TLS_TCB_ALIGN - 1)))
+
+/* Return the thread descriptor (tp) for the current thread.  */
+register void *__thread_pointer asm ("tp");
+
+/* The thread pointer (in hardware register tp) points to the end of
+   the TCB.  The pthread_descr structure is immediately in front of the TCB.  */
+# define TLS_TCB_OFFSET	0
+
+/* 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))[-1].dtv = (dtvp) + 1)
+
+/* Install new dtv for current thread.  */
+# define INSTALL_NEW_DTV(dtv) (THREAD_DTV() = (dtv))
+
+/* Return dtv of given thread descriptor.  */
+# define GET_DTV(tcbp)	(((tcbhead_t *) (tcbp))[-1].dtv)
+
+/* Code to initially initialize the thread pointer (tp).  */
+# define TLS_INIT_TP(tcbp, secondcall) \
+    (__thread_pointer = (char *)(tcbp) + TLS_TCB_OFFSET, NULL)
+
+/* Return the address of the dtv for the current thread.  */
+# define THREAD_DTV() \
+    (((tcbhead_t *) (__thread_pointer - TLS_TCB_OFFSET))[-1].dtv)
+
+/* Return the thread descriptor for the current thread.  */
+# define THREAD_SELF \
+    ((struct pthread *) (__thread_pointer \
+			 - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE))
+
+/* Magic for libthread_db to know how to do THREAD_SELF.  */
+#ifdef __tilegx__
+# define DB_THREAD_SELF \
+  REGISTER (64, 64, REG_TP * 8, - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE)
+#else
+# define DB_THREAD_SELF \
+  REGISTER (32, 32, REG_TP * 4, - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE)
+#endif
+
+/* Read member of the thread descriptor directly.  */
+# define THREAD_GETMEM(descr, member) (descr->member)
+
+/* Same as THREAD_GETMEM, but the member offset can be non-constant.  */
+# define THREAD_GETMEM_NC(descr, member, idx) \
+    (descr->member[idx])
+
+/* Set member of the thread descriptor directly.  */
+# define THREAD_SETMEM(descr, member, value) \
+    (descr->member = (value))
+
+/* Same as THREAD_SETMEM, but the member offset can be non-constant.  */
+# define THREAD_SETMEM_NC(descr, member, idx, value) \
+    (descr->member[idx] = (value))
+
+/* Set the stack guard field in TCB head.  */
+# define THREAD_SET_STACK_GUARD(value) \
+    (((tcbhead_t *) ((char *) __thread_pointer				      \
+		     - TLS_TCB_OFFSET))[-1].stack_guard = (value))
+# define THREAD_COPY_STACK_GUARD(descr) \
+    (((tcbhead_t *) ((char *) (descr)					      \
+		     + TLS_PRE_TCB_SIZE))[-1].stack_guard		      \
+     = ((tcbhead_t *) ((char *) __thread_pointer			      \
+		       - TLS_TCB_OFFSET))[-1].stack_guard)
+
+/* Set the pointer guard field in TCB head.  */
+# define THREAD_GET_POINTER_GUARD() \
+    (((tcbhead_t *) ((char *) __thread_pointer				      \
+		     - TLS_TCB_OFFSET))[-1].pointer_guard)
+# define THREAD_SET_POINTER_GUARD(value) \
+    (THREAD_GET_POINTER_GUARD () = (value))
+# define THREAD_COPY_POINTER_GUARD(descr) \
+    (((tcbhead_t *) ((char *) (descr)					      \
+		     + TLS_PRE_TCB_SIZE))[-1].pointer_guard		      \
+     = THREAD_GET_POINTER_GUARD())
+
+/* l_tls_offset == 0 is perfectly valid on Tile, so we have to use some
+   different value to mean unset l_tls_offset.  */
+# define NO_TLS_OFFSET		-1
+
+/* 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 */
diff --git a/ports/sysdeps/tile/preconfigure b/ports/sysdeps/tile/preconfigure
new file mode 100644
index 0000000000..9dba5b1040
--- /dev/null
+++ b/ports/sysdeps/tile/preconfigure
@@ -0,0 +1,17 @@
+# This is a -*- sh -*-
+case "$machine" in
+    tilepro)
+	base_machine=tile machine=tile/tilepro ;;
+    tilegx)
+	base_machine=tile
+	if $CC $CFLAGS $CPPFLAGS -E -dM -xc /dev/null | grep -q __LP64__; then
+	    machine=tile/tilegx/tilegx64
+	else
+	    machine=tile/tilegx/tilegx32
+	fi ;;
+esac
+case "$machine" in
+    tile*)
+	libc_commonpagesize=0x10000
+	libc_relro_required=yes ;;
+esac
diff --git a/ports/sysdeps/tile/s_fma.c b/ports/sysdeps/tile/s_fma.c
new file mode 100644
index 0000000000..5be586562e
--- /dev/null
+++ b/ports/sysdeps/tile/s_fma.c
@@ -0,0 +1,8 @@
+/* tile does not support the rounding modes required by the ieee754/dbl-64
+   implementation, but it's still better than the generic implementation.  */
+
+#define libc_feholdexcept_setround(e, x) do { (void) (e); } while (0)
+#define libc_feupdateenv_test(e, x) ((void) (e), 0)
+#define libc_fetestexcept(x) 0
+
+#include <sysdeps/ieee754/dbl-64/s_fma.c>
diff --git a/ports/sysdeps/tile/s_fmaf.c b/ports/sysdeps/tile/s_fmaf.c
new file mode 100644
index 0000000000..92d66b2578
--- /dev/null
+++ b/ports/sysdeps/tile/s_fmaf.c
@@ -0,0 +1,8 @@
+/* tile does not support the rounding modes required by the ieee754/dbl-64
+   implementation, but it's still better than the generic implementation.  */
+
+#define libc_feholdexcept_setround(e, x) do { (void) (e); } while (0)
+#define libc_feupdateenv_test(e, x) ((void) (e), 0)
+#define libc_fetestexcept(x) 0
+
+#include <sysdeps/ieee754/dbl-64/s_fmaf.c>
diff --git a/ports/sysdeps/tile/setjmp.S b/ports/sysdeps/tile/setjmp.S
new file mode 100644
index 0000000000..8624ce9da8
--- /dev/null
+++ b/ports/sysdeps/tile/setjmp.S
@@ -0,0 +1,46 @@
+/* Copyright (C) 2011 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+
+   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 <jmpbuf-offsets.h>
+
+	.text
+
+	/* Keep traditional entry points in with sigsetjmp(). */
+ENTRY(setjmp)
+	{ movei r1, 1; j 1f }
+END(setjmp)
+
+ENTRY(_setjmp)
+	{ movei r1, 0; j 1f }
+END(_setjmp)
+libc_hidden_def (_setjmp)
+
+ENTRY(__sigsetjmp)
+	FEEDBACK_ENTER(__sigsetjmp)
+1:
+	move r2, r0
+
+#define SAVE(r) { ST r2, r ; ADDI_PTR r2, r2, REGSIZE }
+	FOR_EACH_CALLEE_SAVED_REG(SAVE)
+
+	mfspr r3, INTERRUPT_CRITICAL_SECTION
+	ST r2, r3
+	j plt(__sigjmp_save)
+	jrp lr   /* Keep the backtracer happy. */
+END(__sigsetjmp)
diff --git a/ports/sysdeps/tile/shlib-versions b/ports/sysdeps/tile/shlib-versions
new file mode 100644
index 0000000000..f50868ff64
--- /dev/null
+++ b/ports/sysdeps/tile/shlib-versions
@@ -0,0 +1,2 @@
+# glibc 2.12 was released to customers; 2.15 was the first community version.
+tile.*-.*-linux-gnu	DEFAULT		GLIBC_2.12 GLIBC_2.15
diff --git a/ports/sysdeps/tile/sotruss-lib.c b/ports/sysdeps/tile/sotruss-lib.c
new file mode 100644
index 0000000000..6ad99f3d1d
--- /dev/null
+++ b/ports/sysdeps/tile/sotruss-lib.c
@@ -0,0 +1,49 @@
+/* Override generic sotruss-lib.c to define actual functions for tile.
+   Copyright (C) 2012 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#define HAVE_ARCH_PLTENTER
+#define HAVE_ARCH_PLTEXIT
+
+#include <elf/sotruss-lib.c>
+
+ElfW(Addr)
+la_tile_gnu_pltenter (ElfW(Sym) *sym __attribute__ ((unused)),
+		      unsigned int ndx __attribute__ ((unused)),
+		      uintptr_t *refcook, uintptr_t *defcook,
+		      La_tile_regs *regs, unsigned int *flags,
+		      const char *symname, long int *framesizep)
+{
+  print_enter (refcook, defcook, symname,
+	       regs->lr_reg[0], regs->lr_reg[1], regs->lr_reg[2],
+	       *flags);
+
+  /* No need to copy anything, we will not need the parameters in any case.  */
+  *framesizep = 0;
+
+  return sym->st_value;
+}
+
+unsigned int
+la_tile_gnu_pltexit (ElfW(Sym) *sym, unsigned int ndx, uintptr_t *refcook,
+		     uintptr_t *defcook, const struct La_tile_regs *inregs,
+		     struct La_tile_retval *outregs, const char *symname)
+{
+  print_exit (refcook, defcook, symname, outregs->lrv_reg[0]);
+
+  return 0;
+}
diff --git a/ports/sysdeps/tile/stackguard-macros.h b/ports/sysdeps/tile/stackguard-macros.h
new file mode 100644
index 0000000000..589ea2b0d8
--- /dev/null
+++ b/ports/sysdeps/tile/stackguard-macros.h
@@ -0,0 +1,14 @@
+#include <bits/wordsize.h>
+
+#ifdef __tilegx__
+# if __WORDSIZE == 64
+#  define STACK_CHK_GUARD \
+  ({ uintptr_t x; asm ("addi %0, tp, -16; ld %0, %0" : "=r" (x)); x; })
+# else
+#  define STACK_CHK_GUARD \
+  ({ uintptr_t x; asm ("addi %0, tp, -8; ld4s %0, %0" : "=r" (x)); x; })
+# endif
+#else
+# define STACK_CHK_GUARD \
+  ({ uintptr_t x; asm ("addi %0, tp, -8; lw %0, %0" : "=r" (x)); x; })
+#endif
diff --git a/ports/sysdeps/tile/stackinfo.h b/ports/sysdeps/tile/stackinfo.h
new file mode 100644
index 0000000000..f2524ee445
--- /dev/null
+++ b/ports/sysdeps/tile/stackinfo.h
@@ -0,0 +1,48 @@
+/* Copyright (C) 2011 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+
+   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/>.  */
+
+/* This file contains a bit of information about the stack allocation
+   of the processor.  */
+
+#ifndef _STACKINFO_H
+#define _STACKINFO_H	1
+
+#include <elf.h>
+
+/* On tile the stack grows down.  */
+#define _STACK_GROWS_DOWN	1
+
+/* Default to a non-executable stack. */
+#define DEFAULT_STACK_PERMS (PF_R|PF_W)
+
+/* Access to the stack pointer.  The macros are used in alloca_account
+   for which they need to act as barriers as well, hence the additional
+   (unnecessary) parameters.  */
+#define stackinfo_get_sp() \
+  ({ void *p__; asm volatile ("move %0, sp" : "=r" (p__)); p__; })
+#if defined __tilegx__ && __WORDSIZE == 32
+#define __stackinfo_sub "subx"
+#else
+#define __stackinfo_sub "sub"
+#endif
+#define stackinfo_sub_sp(ptr)                                  \
+  ({ ptrdiff_t d__;                                             \
+    asm volatile (__stackinfo_sub " %0, %0, sp" : "=r" (d__) : "0" (ptr));  \
+    d__; })
+
+#endif /* stackinfo.h */
diff --git a/ports/sysdeps/tile/start.S b/ports/sysdeps/tile/start.S
new file mode 100644
index 0000000000..999bb535ca
--- /dev/null
+++ b/ports/sysdeps/tile/start.S
@@ -0,0 +1,183 @@
+/* Copyright (C) 2011 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   In addition to the permissions in the GNU Lesser General Public
+   License, the Free Software Foundation gives you unlimited
+   permission to link the compiled version of this file with other
+   programs, and to distribute those programs without any restriction
+   coming from the use of this file. (The GNU Lesser General Public
+   License restrictions do apply in other respects; for example, they
+   cover modification of the file, and distribution when not linked
+   into another program.)
+
+   Note that people who make modified versions of this file are not
+   obligated to grant this special exception for their modified
+   versions; it is their choice whether to do so. The GNU Lesser
+   General Public License gives permission to release a modified
+   version without this exception; this exception also makes it
+   possible to release a modified version which carries forward this
+   exception.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* This is the canonical entry point, usually the first thing in the text
+   segment.  The ELF standard tells us that the stack is set up like this on
+   entry (the left side is the offset from "sp"), in units of
+   __SIZEOF_POINTER__ entries:
+
+		+0		argc
+		+1		argv[0]
+		...
+		+(argc+1)	NULL
+		+(argc+2)	envp[0]
+		...
+				NULL
+		...		ElfInfo
+
+   The ElfInfo is pairs of key/value long words following the envp
+   pointers and terminated by a zero-valued key.
+
+   Although not mandated by the standard, it happens to be the case
+   that we store the actual argv and envp strings immediately after
+   the ElfInfo data on the stack.
+
+   On entry r0 points to the shared library termination function, or 0
+   if there isn't one.
+*/
+
+#include <features.h>
+#include <sysdep.h>
+#include <arch/abi.h>
+
+	.text
+	.global _start
+	.type   _start,@function
+	.align 8
+_start:
+	/* Linux starts us with sp pointing at the conventional Elf layout,
+	   but we need to allow two "caller" words for our ABI convention.  */
+	{
+	 /* Load argc (stored as a "long", equivalent to a pointer type). */
+	 LD_PTR r1, sp
+
+	 /* Save incoming 'sp', which points to the Elf argument block. */
+	 move r52, sp
+	}
+
+	{
+	 /* Allocate stack frame callee space for __libc_start_main. */
+	 ADDI_PTR r12, sp, -(2 * REGSIZE)
+	}
+
+	{
+	 /* Get our PC. */
+	 lnk r13
+
+	 /* sp is not necessarily properly aligned on startup because
+	    of the way ld.so pops off leading argv elements. So align it. */
+	 andi sp, r12, -8
+	}
+.Lmy_pc:
+
+	{
+	 /* Pass the address of the shared library termination function. */
+	 move r5, r0
+
+	 /* Compute location where __libc_start_main's caller is supposed to
+	    store its frame pointer. */
+	 ADDI_PTR r12, sp, REGSIZE
+
+	 /* Zero out callee space for return address. Unnecessary but free.
+	    This is just paranoia to help backtracing not go awry. */
+	 ST sp, zero
+	}
+	{
+	 /* Zero out our frame pointer for __libc_start_main. */
+	 ST r12, zero
+
+	 /* Zero out lr to make __libc_start_main the end of backtrace.  */
+	 move lr, zero
+
+	 /* Compute a pointer to argv. envp will be determined
+	    later in __libc_start_main.  We set up the first argument
+	    (the address of main) below. */
+	 ADDI_PTR r2, r52, __SIZEOF_POINTER__
+	}
+	{
+	 /* Pass the highest stack address to user code. */
+	 ADDI_PTR r6, sp, (2 * REGSIZE)
+
+	 /* Pass address of main() in r0, and of our own entry
+	    points to .fini and .init in r3 and r4.  */
+#ifdef __tilegx__
+	 moveli r0, hw2_last(main - .Lmy_pc)
+	}
+	{
+	 moveli r3, hw2_last(__libc_csu_init - .Lmy_pc)
+	 shl16insli r0, r0, hw1(main - .Lmy_pc)
+	}
+	{
+	 shl16insli r3, r3, hw1(__libc_csu_init - .Lmy_pc)
+	 shl16insli r0, r0, hw0(main - .Lmy_pc)
+	}
+	{
+	 shl16insli r3, r3, hw0(__libc_csu_init - .Lmy_pc)
+	 moveli r4, hw2_last(__libc_csu_fini - .Lmy_pc)
+	}
+	{
+	 ADD_PTR r0, r0, r13
+	 shl16insli r4, r4, hw1(__libc_csu_fini - .Lmy_pc)
+	}
+	{
+	 ADD_PTR r3, r3, r13
+	 shl16insli r4, r4, hw0(__libc_csu_fini - .Lmy_pc)
+	}
+	{
+	 ADD_PTR r4, r4, r13
+#else
+	 addli r0, r13, lo16(main - .Lmy_pc)
+	}
+	{
+	 auli r0, r0, ha16(main - .Lmy_pc)
+	 addli r3, r13, lo16(__libc_csu_init - .Lmy_pc)
+	}
+	{
+	 auli r3, r3, ha16(__libc_csu_init - .Lmy_pc)
+	 addli r4, r13, lo16(__libc_csu_fini - .Lmy_pc)
+	}
+	{
+	 auli r4, r4, ha16(__libc_csu_fini - .Lmy_pc)
+
+#endif
+
+	 /* Call the user's main function, and exit with its value.
+	    But let the libc call main. */
+	 j plt(__libc_start_main)
+	}
+	{
+	 /* Tell backtracer to give up (_start has no caller). */
+	 info INFO_OP_CANNOT_BACKTRACE
+	}
+.size _start, .-_start
+
+/* Define a symbol for the first piece of initialized data.  */
+	.data
+	.global __data_start
+	.align 8
+__data_start:
+	.long 0
+	.weak data_start
+	data_start = __data_start
diff --git a/ports/sysdeps/tile/sysdep.h b/ports/sysdeps/tile/sysdep.h
new file mode 100644
index 0000000000..58432eb032
--- /dev/null
+++ b/ports/sysdeps/tile/sysdep.h
@@ -0,0 +1,111 @@
+/* Copyright (C) 2011 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+
+   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/sysdep.h>
+#include <bits/wordsize.h>
+#include <arch/abi.h>
+
+#if defined __ASSEMBLER__ || defined REQUEST_ASSEMBLER_MACROS
+
+#include <feedback.h>
+
+/* Make use of .type and .size directives.  */
+#define ASM_TYPE_DIRECTIVE(name,typearg) .type name,typearg;
+#define ASM_SIZE_DIRECTIVE(name) .size name,.-name;
+
+/* Define an entry point visible from C.  */
+#define	ENTRY(name)							      \
+  ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(name);				      \
+  ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name),@function)			      \
+  .align 8;								      \
+  C_LABEL(name)								      \
+  cfi_startproc;							      \
+  CALL_MCOUNT
+
+#undef	END
+#define END(name)							      \
+  cfi_endproc;								      \
+  ASM_SIZE_DIRECTIVE(name)
+
+/* Since C identifiers are not normally prefixed with an underscore
+   on this system, the asm identifier `syscall_error' intrudes on the
+   C name space.  Make sure we use an innocuous name.  */
+#define	syscall_error	__syscall_error
+#define mcount		__mcount
+
+/* If compiled for profiling, call `mcount' at the start of each function.
+   The mcount code requires the caller PC in r10.  The `mcount' function
+   sets lr back to the value r10 had on entry when it returns.  */
+#ifdef	PROF
+#define CALL_MCOUNT { move r10, lr; jal mcount }
+#else
+#define CALL_MCOUNT             /* Do nothing.  */
+#endif
+
+/* Local label name for asm code. */
+#define L(name)		.L##name
+
+/* Specify the size in bytes of a machine register.  */
+#ifdef __tilegx__
+#define REGSIZE		8
+#else
+#define REGSIZE		4
+#endif
+
+/* Support a limited form of shared assembly between tile and tilegx.
+   The presumption is that LD/ST are used for manipulating registers.
+   Since opcode parsing is case-insensitive, we don't need to provide
+   definitions for these on tilegx.  */
+#ifndef __tilegx__
+#define LD		lw
+#define LD4U		lw
+#define ST		sw
+#define ST4		sw
+#define BNEZ		bnz
+#define BEQZ		bz
+#define BEQZT		bzt
+#define BGTZ		bgz
+#define CMPEQI		seqi
+#define CMPEQ		seq
+#define CMOVEQZ		mvz
+#define CMOVNEZ		mvnz
+#endif
+
+/* Provide "pointer-oriented" instruction variants.  These differ not
+   just for tile vs tilegx, but also for tilegx -m64 vs -m32.  */
+#if defined __tilegx__ && __WORDSIZE == 32
+#define ADD_PTR		addx
+#define ADDI_PTR	addxi
+#define ADDLI_PTR	addxli
+#define LD_PTR		ld4s
+#define ST_PTR		st4
+#define SHL_PTR_ADD	shl2add
+#else
+#define ADD_PTR		add
+#define ADDI_PTR	addi
+#define ADDLI_PTR	addli
+#define LD_PTR		LD
+#define ST_PTR		ST
+#ifdef __tilegx__
+#define SHL_PTR_ADD	shl3add
+#else
+#define SHL_PTR_ADD	s2a
+#endif
+#endif
+
+#endif /* __ASSEMBLER__ */
diff --git a/ports/sysdeps/tile/tilegx/bits/atomic.h b/ports/sysdeps/tile/tilegx/bits/atomic.h
new file mode 100644
index 0000000000..270955ac00
--- /dev/null
+++ b/ports/sysdeps/tile/tilegx/bits/atomic.h
@@ -0,0 +1,49 @@
+/* Copyright (C) 2011 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _BITS_ATOMIC_H
+#define _BITS_ATOMIC_H	1
+
+#include <arch/spr_def.h>
+
+/* Pick appropriate 8- or 4-byte instruction. */
+#define __atomic_update(mem, v, op)                                     \
+  ((__typeof (*(mem))) (__typeof (*(mem) - *(mem)))                     \
+   ((sizeof (*(mem)) == 8) ?                                            \
+    __insn_##op ((void *) (mem), (int64_t) (__typeof((v) - (v))) (v)) : \
+    (sizeof (*(mem)) == 4) ?                                            \
+    __insn_##op##4 ((void *) (mem), (int32_t) (__typeof ((v) - (v))) (v)) : \
+    __atomic_error_bad_argument_size()))
+
+#define atomic_compare_and_exchange_val_acq(mem, n, o)                  \
+  ({ __insn_mtspr (SPR_CMPEXCH_VALUE, (int64_t) (__typeof ((o) - (o))) (o)); \
+     __atomic_update (mem, n, cmpexch); })
+#define atomic_exchange_acq(mem, newvalue) \
+  __atomic_update (mem, newvalue, exch)
+#define atomic_exchange_and_add(mem, value) \
+  __atomic_update (mem, value, fetchadd)
+#define atomic_and_val(mem, mask) \
+  __atomic_update (mem, mask, fetchand)
+#define atomic_or_val(mem, mask) \
+  __atomic_update (mem, mask, fetchor)
+#define atomic_decrement_if_positive(mem) \
+  __atomic_update (mem, -1, fetchaddgez)
+
+#include <sysdeps/tile/bits/atomic.h>
+
+#endif /* bits/atomic.h */
diff --git a/ports/sysdeps/tile/tilegx/bits/wordsize.h b/ports/sysdeps/tile/tilegx/bits/wordsize.h
new file mode 100644
index 0000000000..5d4e4b4470
--- /dev/null
+++ b/ports/sysdeps/tile/tilegx/bits/wordsize.h
@@ -0,0 +1,8 @@
+/* Determine the wordsize from the preprocessor defines.  */
+
+#ifdef __LP64__
+# define __WORDSIZE	64
+# define __WORDSIZE_TIME64_COMPAT32	1
+#else
+# define __WORDSIZE	32
+#endif
diff --git a/ports/sysdeps/tile/tilegx/memchr.c b/ports/sysdeps/tile/tilegx/memchr.c
new file mode 100644
index 0000000000..32f24ec43e
--- /dev/null
+++ b/ports/sysdeps/tile/tilegx/memchr.c
@@ -0,0 +1,73 @@
+/* Copyright (C) 2011-2012 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+
+   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 <string.h>
+#include <stdint.h>
+#include "string-endian.h"
+
+void *
+__memchr (const void *s, int c, size_t n)
+{
+  const uint64_t *last_word_ptr;
+  const uint64_t *p;
+  const char *last_byte_ptr;
+  uintptr_t s_int;
+  uint64_t goal, before_mask, v, bits;
+  char *ret;
+
+  if (__builtin_expect (n == 0, 0))
+    {
+      /* Don't dereference any memory if the array is empty. */
+      return NULL;
+    }
+
+  /* Get an aligned pointer. */
+  s_int = (uintptr_t) s;
+  p = (const uint64_t *) (s_int & -8);
+
+  /* Create eight copies of the byte for which we are looking. */
+  goal = copy_byte(c);
+
+  /* Read the first word, but munge it so that bytes before the array
+     will not match goal.  */
+  before_mask = MASK (s_int);
+  v = (*p | before_mask) ^ (goal & before_mask);
+
+  /* Compute the address of the last byte. */
+  last_byte_ptr = (const char *) s + n - 1;
+
+  /* Compute the address of the word containing the last byte. */
+  last_word_ptr = (const uint64_t *) ((uintptr_t) last_byte_ptr & -8);
+
+  while ((bits = __insn_v1cmpeq (v, goal)) == 0)
+    {
+      if (__builtin_expect (p == last_word_ptr, 0))
+        {
+          /* We already read the last word in the array, so give up.  */
+          return NULL;
+        }
+      v = *++p;
+    }
+
+  /* We found a match, but it might be in a byte past the end
+     of the array.  */
+  ret = ((char *) p) + (CFZ (bits) >> 3);
+  return (ret <= last_byte_ptr) ? ret : NULL;
+}
+weak_alias (__memchr, memchr)
+libc_hidden_builtin_def (memchr)
diff --git a/ports/sysdeps/tile/tilegx/memcpy.c b/ports/sysdeps/tile/tilegx/memcpy.c
new file mode 100644
index 0000000000..dd6e30dd60
--- /dev/null
+++ b/ports/sysdeps/tile/tilegx/memcpy.c
@@ -0,0 +1,206 @@
+/* Copyright (C) 2011-2012 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+
+   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 <string.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <arch/chip.h>
+
+/* Must be 8 bytes in size. */
+#define word_t uint64_t
+
+/* How many cache lines ahead should we prefetch? */
+#define PREFETCH_LINES_AHEAD 3
+
+void *
+__memcpy (void *__restrict dstv, const void *__restrict srcv, size_t n)
+{
+  char *__restrict dst1 = (char *) dstv;
+  const char *__restrict src1 = (const char *) srcv;
+  const char *__restrict src1_end;
+  const char *__restrict prefetch;
+  word_t *__restrict dst8; /* 8-byte pointer to destination memory. */
+  word_t final; /* Final bytes to write to trailing word, if any */
+  long i;
+
+  if (n < 16)
+    {
+      for (; n; n--)
+        *dst1++ = *src1++;
+      return dstv;
+    }
+
+  /* Locate the end of source memory we will copy.  Don't prefetch
+     past this.  */
+  src1_end = src1 + n - 1;
+
+  /* Prefetch ahead a few cache lines, but not past the end. */
+  prefetch = src1;
+  for (i = 0; i < PREFETCH_LINES_AHEAD; i++)
+    {
+      __insn_prefetch (prefetch);
+      prefetch += CHIP_L2_LINE_SIZE ();
+      prefetch = (prefetch > src1_end) ? prefetch : src1;
+    }
+
+  /* Copy bytes until dst is word-aligned. */
+  for (; (uintptr_t) dst1 & (sizeof (word_t) - 1); n--)
+    *dst1++ = *src1++;
+
+  /* 8-byte pointer to destination memory. */
+  dst8 = (word_t *) dst1;
+
+  if (__builtin_expect ((uintptr_t) src1 & (sizeof (word_t) - 1), 0))
+    {
+      /* Misaligned copy.  Copy 8 bytes at a time, but don't bother
+         with other fanciness.
+         TODO: Consider prefetching and using wh64 as well.  */
+
+      /* Create an aligned src8. */
+      const word_t *__restrict src8 =
+        (const word_t *) ((uintptr_t) src1 & -sizeof (word_t));
+      word_t b;
+
+      word_t a = *src8++;
+      for (; n >= sizeof (word_t); n -= sizeof (word_t))
+        {
+          b = *src8++;
+          a = __insn_dblalign (a, b, src1);
+          *dst8++ = a;
+          a = b;
+        }
+
+      if (n == 0)
+        return dstv;
+
+      b = ((const char *) src8 <= src1_end) ? *src8 : 0;
+
+      /* Final source bytes to write to trailing partial word, if any. */
+      final = __insn_dblalign (a, b, src1);
+    }
+  else
+    {
+      /* Aligned copy. */
+
+      const word_t *__restrict src8 = (const word_t *) src1;
+
+      /* src8 and dst8 are both word-aligned. */
+      if (n >= CHIP_L2_LINE_SIZE ())
+        {
+          /* Copy until 'dst' is cache-line-aligned. */
+          for (; (uintptr_t) dst8 & (CHIP_L2_LINE_SIZE () - 1);
+               n -= sizeof (word_t))
+            *dst8++ = *src8++;
+
+          /* If copying to self, return.  The test is cheap enough
+             that we do it despite the fact that the memcpy() contract
+             doesn't require us to support overlapping dst and src.
+             This is the most common case of overlap, and any close
+             overlap will cause corruption due to the wh64 below.
+             This case is particularly important since the compiler
+             will emit memcpy() calls for aggregate copies even if it
+             can't prove that src != dst.  */
+          if (__builtin_expect (dst8 == src8, 0))
+            return dstv;
+
+          for (; n >= CHIP_L2_LINE_SIZE ();)
+            {
+              __insn_wh64 (dst8);
+
+              /* Prefetch and advance to next line to prefetch, but
+                 don't go past the end.  */
+              __insn_prefetch (prefetch);
+              prefetch += CHIP_L2_LINE_SIZE ();
+              prefetch = (prefetch > src1_end) ? prefetch :
+                (const char *) src8;
+
+              /* Copy an entire cache line.  Manually unrolled to
+                 avoid idiosyncracies of compiler unrolling.  */
+#define COPY_WORD(offset) ({ dst8[offset] = src8[offset]; n -= 8; })
+              COPY_WORD (0);
+              COPY_WORD (1);
+              COPY_WORD (2);
+              COPY_WORD (3);
+              COPY_WORD (4);
+              COPY_WORD (5);
+              COPY_WORD (6);
+              COPY_WORD (7);
+#if CHIP_L2_LINE_SIZE() != 64
+# error "Fix code that assumes particular L2 cache line size."
+#endif
+
+              dst8 += CHIP_L2_LINE_SIZE () / sizeof (word_t);
+              src8 += CHIP_L2_LINE_SIZE () / sizeof (word_t);
+            }
+        }
+
+      for (; n >= sizeof (word_t); n -= sizeof (word_t))
+        *dst8++ = *src8++;
+
+      if (__builtin_expect (n == 0, 1))
+        return dstv;
+
+      final = *src8;
+    }
+
+  /* n != 0 if we get here.  Write out any trailing bytes. */
+  dst1 = (char *) dst8;
+#ifndef __BIG_ENDIAN__
+  if (n & 4)
+    {
+      *(uint32_t *) dst1 = final;
+      dst1 += 4;
+      final >>= 32;
+      n &= 3;
+    }
+  if (n & 2)
+    {
+      *(uint16_t *) dst1 = final;
+      dst1 += 2;
+      final >>= 16;
+      n &= 1;
+    }
+  if (n)
+    *(uint8_t *) dst1 = final;
+#else
+  if (n & 4)
+    {
+      *(uint32_t *) dst1 = final >> 32;
+      dst1 += 4;
+    }
+  else
+    {
+      final >>= 32;
+    }
+  if (n & 2)
+    {
+      *(uint16_t *) dst1 = final >> 16;
+      dst1 += 2;
+    }
+  else
+    {
+      final >>= 16;
+    }
+  if (n & 1)
+    *(uint8_t *) dst1 = final >> 8;
+#endif
+
+  return dstv;
+}
+weak_alias (__memcpy, memcpy)
+libc_hidden_builtin_def (memcpy)
diff --git a/ports/sysdeps/tile/tilegx/memset.c b/ports/sysdeps/tile/tilegx/memset.c
new file mode 100644
index 0000000000..dad3eadc5a
--- /dev/null
+++ b/ports/sysdeps/tile/tilegx/memset.c
@@ -0,0 +1,151 @@
+/* Copyright (C) 2011-2012 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+
+   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 <arch/chip.h>
+#include <string.h>
+#include <stdint.h>
+#include "string-endian.h"
+
+void *
+__memset (void *s, int c, size_t n)
+{
+  uint64_t *out64;
+  int n64, to_align64;
+  uint64_t v64;
+  uint8_t *out8 = s;
+
+  /* Experimentation shows that a trivial tight loop is a win up until
+     around a size of 20, where writing a word at a time starts to win.  */
+#define BYTE_CUTOFF 20
+
+#if BYTE_CUTOFF < 7
+  /* This must be at least at least this big, or some code later
+     on doesn't work.  */
+# error "BYTE_CUTOFF is too small."
+#endif
+
+  if (n < BYTE_CUTOFF)
+    {
+      /* Strangely, this turns out to be the tightest way to write
+         this loop.  */
+      if (n != 0)
+        {
+          do
+            {
+              /* Strangely, combining these into one line performs worse.  */
+              *out8 = c;
+              out8++;
+            }
+          while (--n != 0);
+        }
+
+      return s;
+    }
+
+  /* Align 'out8'. We know n >= 7 so this won't write past the end.  */
+  while (((uintptr_t) out8 & 7) != 0)
+    {
+      *out8++ = c;
+      --n;
+    }
+
+  /* Align 'n'. */
+  while (n & 7)
+    out8[--n] = c;
+
+  out64 = (uint64_t *) out8;
+  n64 = n >> 3;
+
+  /* Tile input byte out to 64 bits. */
+  v64 = copy_byte(c);
+
+  /* This must be at least 8 or the following loop doesn't work. */
+#define CACHE_LINE_SIZE_IN_DOUBLEWORDS (CHIP_L2_LINE_SIZE() / 8)
+
+  /* Determine how many words we need to emit before the 'out32'
+     pointer becomes aligned modulo the cache line size.  */
+  to_align64 = (-((uintptr_t) out64 >> 3)) &
+    (CACHE_LINE_SIZE_IN_DOUBLEWORDS - 1);
+
+  /* Only bother aligning and using wh64 if there is at least
+     one full cache line to process.  This check also prevents
+     overrunning the end of the buffer with alignment words.  */
+  if (to_align64 <= n64 - CACHE_LINE_SIZE_IN_DOUBLEWORDS)
+    {
+      int lines_left;
+
+      /* Align out64 mod the cache line size so we can use wh64. */
+      n64 -= to_align64;
+      for (; to_align64 != 0; to_align64--)
+        {
+          *out64 = v64;
+          out64++;
+        }
+
+      /* Use unsigned divide to turn this into a right shift. */
+      lines_left = (unsigned) n64 / CACHE_LINE_SIZE_IN_DOUBLEWORDS;
+
+      do
+        {
+          /* Only wh64 a few lines at a time, so we don't exceed the
+             maximum number of victim lines.  */
+          int x = ((lines_left < CHIP_MAX_OUTSTANDING_VICTIMS ()) ? lines_left
+                   : CHIP_MAX_OUTSTANDING_VICTIMS ());
+          uint64_t *wh = out64;
+          int i = x;
+          int j;
+
+          lines_left -= x;
+
+          do
+            {
+              __insn_wh64 (wh);
+              wh += CACHE_LINE_SIZE_IN_DOUBLEWORDS;
+            }
+          while (--i);
+
+          for (j = x * (CACHE_LINE_SIZE_IN_DOUBLEWORDS / 4); j != 0; j--)
+            {
+              *out64++ = v64;
+              *out64++ = v64;
+              *out64++ = v64;
+              *out64++ = v64;
+            }
+        }
+      while (lines_left != 0);
+
+      /* We processed all full lines above, so only this many
+         words remain to be processed.  */
+      n64 &= CACHE_LINE_SIZE_IN_DOUBLEWORDS - 1;
+    }
+
+  /* Now handle any leftover values. */
+  if (n64 != 0)
+    {
+      do
+        {
+          *out64 = v64;
+          out64++;
+        }
+      while (--n64 != 0);
+    }
+
+  return s;
+}
+weak_alias (__memset, memset)
+libc_hidden_builtin_def (memset)
diff --git a/ports/sysdeps/tile/tilegx/memusage.h b/ports/sysdeps/tile/tilegx/memusage.h
new file mode 100644
index 0000000000..0ac8ad8644
--- /dev/null
+++ b/ports/sysdeps/tile/tilegx/memusage.h
@@ -0,0 +1,30 @@
+/* Copyright (C) 2011 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+
+   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 <arch/spr_def.h>
+
+#define GETSP() ({ register uintptr_t stack_ptr asm ("sp"); stack_ptr; })
+
+#define GETTIME(low,high)                       \
+  {                                             \
+    uint64_t cycles = __insn_mfspr (SPR_CYCLE); \
+    low = cycles & 0xffffffff;                  \
+    high = cycles >> 32;                        \
+  }
+
+#include <sysdeps/generic/memusage.h>
diff --git a/ports/sysdeps/tile/tilegx/rawmemchr.c b/ports/sysdeps/tile/tilegx/rawmemchr.c
new file mode 100644
index 0000000000..70b5928ebc
--- /dev/null
+++ b/ports/sysdeps/tile/tilegx/rawmemchr.c
@@ -0,0 +1,45 @@
+/* Copyright (C) 2011-2012 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+
+   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 <string.h>
+#include <stdint.h>
+#include "string-endian.h"
+
+void *
+__rawmemchr (const void *s, int c)
+{
+  /* Get an aligned pointer. */
+  const uintptr_t s_int = (uintptr_t) s;
+  const uint64_t *p = (const uint64_t *) (s_int & -8);
+
+  /* Create eight copies of the byte for which we are looking. */
+  const uint64_t goal = copy_byte(c);
+
+  /* Read the first word, but munge it so that bytes before the array
+     will not match goal.  */
+  const uint64_t before_mask = MASK (s_int);
+  uint64_t v = (*p | before_mask) ^ (goal & before_mask);
+
+  uint64_t bits;
+  while ((bits = __insn_v1cmpeq (v, goal)) == 0)
+    v = *++p;
+
+  return ((char *) p) + (CFZ (bits) >> 3);
+}
+libc_hidden_def (__rawmemchr)
+weak_alias (__rawmemchr, rawmemchr)
diff --git a/ports/sysdeps/tile/tilegx/strchr.c b/ports/sysdeps/tile/tilegx/strchr.c
new file mode 100644
index 0000000000..c6a741b37d
--- /dev/null
+++ b/ports/sysdeps/tile/tilegx/strchr.c
@@ -0,0 +1,67 @@
+/* Copyright (C) 2011-2012 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+
+   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 <string.h>
+#include <stdint.h>
+#include "string-endian.h"
+
+#undef strchr
+
+char *
+strchr (const char *s, int c)
+{
+  int z, g;
+
+  /* Get an aligned pointer. */
+  const uintptr_t s_int = (uintptr_t) s;
+  const uint64_t *p = (const uint64_t *) (s_int & -8);
+
+  /* Create eight copies of the byte for which we are looking. */
+  const uint64_t goal = copy_byte(c);
+
+  /* Read the first aligned word, but force bytes before the string to
+     match neither zero nor goal (we make sure the high bit of each byte
+     is 1, and the low 7 bits are all the opposite of the goal byte).  */
+  const uint64_t before_mask = MASK (s_int);
+  uint64_t v = (*p | before_mask) ^ (goal & __insn_v1shrui (before_mask, 1));
+
+  uint64_t zero_matches, goal_matches;
+  while (1)
+    {
+      /* Look for a terminating '\0'. */
+      zero_matches = __insn_v1cmpeqi (v, 0);
+
+      /* Look for the goal byte. */
+      goal_matches = __insn_v1cmpeq (v, goal);
+
+      if (__builtin_expect ((zero_matches | goal_matches) != 0, 0))
+        break;
+
+      v = *++p;
+    }
+
+  z = CFZ (zero_matches);
+  g = CFZ (goal_matches);
+
+  /* If we found c before '\0' we got a match. Note that if c == '\0'
+     then g == z, and we correctly return the address of the '\0'
+     rather than NULL.  */
+  return (g <= z) ? ((char *) p) + (g >> 3) : NULL;
+}
+weak_alias (strchr, index)
+libc_hidden_builtin_def (strchr)
diff --git a/ports/sysdeps/tile/tilegx/strchrnul.c b/ports/sysdeps/tile/tilegx/strchrnul.c
new file mode 100644
index 0000000000..4251598dca
--- /dev/null
+++ b/ports/sysdeps/tile/tilegx/strchrnul.c
@@ -0,0 +1,64 @@
+/* Copyright (C) 2011-2012 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+
+   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 <string.h>
+#include <stdint.h>
+#include "string-endian.h"
+
+char *
+__strchrnul (const char *s, int c)
+{
+  int z, g;
+
+  /* Get an aligned pointer. */
+  const uintptr_t s_int = (uintptr_t) s;
+  const uint64_t *p = (const uint64_t *) (s_int & -8);
+
+  /* Create eight copies of the byte for which we are looking. */
+  const uint64_t goal = copy_byte(c);
+
+  /* Read the first aligned word, but force bytes before the string to
+     match neither zero nor goal (we make sure the high bit of each byte
+     is 1, and the low 7 bits are all the opposite of the goal byte).  */
+  const uint64_t before_mask = MASK (s_int);
+  uint64_t v = (*p | before_mask) ^ (goal & __insn_v1shrui (before_mask, 1));
+
+  uint64_t zero_matches, goal_matches;
+  while (1)
+    {
+      /* Look for a terminating '\0'. */
+      zero_matches = __insn_v1cmpeqi (v, 0);
+
+      /* Look for the goal byte. */
+      goal_matches = __insn_v1cmpeq (v, goal);
+
+      if (__builtin_expect ((zero_matches | goal_matches) != 0, 0))
+        break;
+
+      v = *++p;
+    }
+
+  z = CFZ (zero_matches);
+  g = CFZ (goal_matches);
+
+  /* Return a pointer to the NUL or goal, whichever is first. */
+  if (z < g)
+    g = z;
+  return ((char *) p) + (g >> 3);
+}
+weak_alias (__strchrnul, strchrnul)
diff --git a/ports/sysdeps/tile/tilegx/string-endian.h b/ports/sysdeps/tile/tilegx/string-endian.h
new file mode 100644
index 0000000000..c2e40ecd4f
--- /dev/null
+++ b/ports/sysdeps/tile/tilegx/string-endian.h
@@ -0,0 +1,45 @@
+/* Copyright (C) 2011-2012 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+
+   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/>.  */
+
+/* Provide a mask based on the pointer alignment that
+   sets up non-zero bytes before the beginning of the string.
+   The MASK expression works because shift counts are taken mod 64.
+   Also, specify how to count "first" and "last" bits
+   when the bits have been read as a word.  */
+
+#ifndef __BIG_ENDIAN__
+#define MASK(x) (__insn_shl(1ULL, (x << 3)) - 1)
+#define NULMASK(x) ((2ULL << x) - 1)
+#define CFZ(x) __insn_ctz(x)
+#define REVCZ(x) __insn_clz(x)
+#else
+#define MASK(x) (__insn_shl(-2LL, ((-x << 3) - 1)))
+#define NULMASK(x) (-2LL << (63 - x))
+#define CFZ(x) __insn_clz(x)
+#define REVCZ(x) __insn_ctz(x)
+#endif
+
+/* Create eight copies of the byte in a uint64_t. */
+static inline uint64_t copy_byte(uint8_t byte)
+{
+  uint64_t word = byte;
+  word = __insn_bfins(word, word, 8, 15);
+  word = __insn_bfins(word, word, 16, 31);
+  word = __insn_bfins(word, word, 32, 63);
+  return word;
+}
diff --git a/ports/sysdeps/tile/tilegx/strlen.c b/ports/sysdeps/tile/tilegx/strlen.c
new file mode 100644
index 0000000000..dda9dff1c9
--- /dev/null
+++ b/ports/sysdeps/tile/tilegx/strlen.c
@@ -0,0 +1,39 @@
+/* Copyright (C) 2011 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+
+   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 <string.h>
+#include <stdint.h>
+#include "string-endian.h"
+
+size_t
+strlen (const char *s)
+{
+  /* Get an aligned pointer. */
+  const uintptr_t s_int = (uintptr_t) s;
+  const uint64_t *p = (const uint64_t *) (s_int & -8);
+
+  /* Read and MASK the first word. */
+  uint64_t v = *p | MASK (s_int);
+
+  uint64_t bits;
+  while ((bits = __insn_v1cmpeqi (v, 0)) == 0)
+    v = *++p;
+
+  return ((const char *) p) + (CFZ (bits) >> 3) - s;
+}
+libc_hidden_builtin_def (strlen)
diff --git a/ports/sysdeps/tile/tilegx/strrchr.c b/ports/sysdeps/tile/tilegx/strrchr.c
new file mode 100644
index 0000000000..b6e43a6832
--- /dev/null
+++ b/ports/sysdeps/tile/tilegx/strrchr.c
@@ -0,0 +1,68 @@
+/* Copyright (C) 2011-2012 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+
+   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 <string.h>
+#include <stdint.h>
+#include "string-endian.h"
+
+char *
+strrchr (const char *s, int c)
+{
+  /* Get an aligned pointer. */
+  const uintptr_t s_int = (uintptr_t) s;
+  const uint64_t *p = (const uint64_t *) (s_int & -8);
+
+  /* Create eight copies of the byte for which we are looking. */
+  const uint64_t goal = copy_byte(c);
+
+  /* Read the first aligned word, but force bytes before the string to
+     match neither zero nor goal (we make sure the high bit of each byte
+     is 1, and the low 7 bits are all the opposite of the goal byte).  */
+  const uint64_t before_mask = MASK (s_int);
+  uint64_t v = (*p | before_mask) ^ (goal & __insn_v1shrui (before_mask, 1));
+  const char *found = NULL;
+  uint64_t zero_matches, goal_matches;
+  while (1)
+    {
+      /* Look for a terminating '\0'. */
+      zero_matches = __insn_v1cmpeqi (v, 0);
+
+      /* Look for the goal byte. */
+      goal_matches = __insn_v1cmpeq (v, goal);
+
+      /* If we found the goal, record the last offset. */
+      if (__builtin_expect (goal_matches != 0, 0))
+        {
+          if (__builtin_expect (zero_matches != 0, 0))
+            {
+              /* Clear any goal after the first zero. */
+              int first_nul = CFZ (zero_matches);
+              goal_matches &= NULMASK (first_nul);
+            }
+          if (__builtin_expect (goal_matches != 0, 1))
+            found = ((char *) p) + 7 - (REVCZ (goal_matches) >> 3);
+        }
+
+      if (__builtin_expect (zero_matches != 0, 0))
+        return (char *) found;
+
+      v = *++p;
+    }
+}
+weak_alias (strrchr, rindex)
+libc_hidden_builtin_def (strrchr)
diff --git a/ports/sysdeps/tile/tilegx/tilegx32/Implies b/ports/sysdeps/tile/tilegx/tilegx32/Implies
new file mode 100644
index 0000000000..993b7f4cd1
--- /dev/null
+++ b/ports/sysdeps/tile/tilegx/tilegx32/Implies
@@ -0,0 +1,3 @@
+tile/tilegx
+tile
+wordsize-32
diff --git a/ports/sysdeps/tile/tilegx/tilegx64/Implies b/ports/sysdeps/tile/tilegx/tilegx64/Implies
new file mode 100644
index 0000000000..eb0686e0e6
--- /dev/null
+++ b/ports/sysdeps/tile/tilegx/tilegx64/Implies
@@ -0,0 +1,3 @@
+tile/tilegx
+tile
+wordsize-64
diff --git a/ports/sysdeps/tile/tilepro/Implies b/ports/sysdeps/tile/tilepro/Implies
new file mode 100644
index 0000000000..709e1dc122
--- /dev/null
+++ b/ports/sysdeps/tile/tilepro/Implies
@@ -0,0 +1,2 @@
+tile
+wordsize-32
diff --git a/ports/sysdeps/tile/tilepro/bits/atomic.h b/ports/sysdeps/tile/tilepro/bits/atomic.h
new file mode 100644
index 0000000000..3b9509f530
--- /dev/null
+++ b/ports/sysdeps/tile/tilepro/bits/atomic.h
@@ -0,0 +1,81 @@
+/* Copyright (C) 2011 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _BITS_ATOMIC_H
+#define _BITS_ATOMIC_H	1
+
+#include <asm/unistd.h>
+
+/* 32-bit integer compare-and-exchange. */
+static __inline __attribute__ ((always_inline))
+int __atomic_cmpxchg_32 (volatile int *mem, int newval, int oldval)
+{
+  int result;
+  __asm__ __volatile__ ("swint1"
+                        : "=R00" (result), "=m" (*mem)
+                        : "R10" (__NR_FAST_cmpxchg), "R00" (mem),
+                          "R01" (oldval), "R02" (newval), "m" (*mem)
+                        : "r20", "r21", "r22", "r23", "r24",
+                          "r25", "r26", "r27", "r28", "r29", "memory");
+  return result;
+}
+
+#define atomic_compare_and_exchange_val_acq(mem, n, o)                  \
+  ((__typeof (*(mem)))                                                  \
+   ((sizeof (*(mem)) == 4) ?                                            \
+    __atomic_cmpxchg_32 ((int *) (mem), (int) (n), (int) (o)) :         \
+    __atomic_error_bad_argument_size()))
+
+/* Atomically compute:
+     int old = *ptr;
+     *ptr = (old & mask) + addend;
+     return old;  */
+
+static __inline __attribute__ ((always_inline))
+int __atomic_update_32 (volatile int *mem, int mask, int addend)
+{
+  int result;
+  __asm__ __volatile__ ("swint1"
+                        : "=R00" (result), "=m" (*mem)
+                        : "R10" (__NR_FAST_atomic_update), "R00" (mem),
+                          "R01" (mask), "R02" (addend), "m" (*mem)
+                        : "r20", "r21", "r22", "r23", "r24",
+                          "r25", "r26", "r27", "r28", "r29", "memory");
+  return result;
+}
+
+/* Size-checked verson of __atomic_update_32. */
+#define __atomic_update(mem, mask, addend)                              \
+  ((__typeof (*(mem)))                                                  \
+   ((sizeof (*(mem)) == 4) ?                                            \
+    __atomic_update_32 ((int *) (mem), (int) (mask), (int) (addend)) :  \
+    __atomic_error_bad_argument_size ()))
+
+#define atomic_exchange_acq(mem, newvalue)              \
+  __atomic_update ((mem), 0, (newvalue))
+#define atomic_exchange_and_add(mem, value)             \
+  __atomic_update ((mem), -1, (value))
+#define atomic_and_val(mem, mask)                       \
+  __atomic_update ((mem), (mask), 0)
+#define atomic_or_val(mem, mask)                        \
+  ({ __typeof (mask) __att1_v = (mask);                 \
+    __atomic_update ((mem), ~__att1_v, __att1_v); })
+
+#include <sysdeps/tile/bits/atomic.h>
+
+#endif /* bits/atomic.h */
diff --git a/ports/sysdeps/tile/tilepro/bits/wordsize.h b/ports/sysdeps/tile/tilepro/bits/wordsize.h
new file mode 100644
index 0000000000..da587a2f12
--- /dev/null
+++ b/ports/sysdeps/tile/tilepro/bits/wordsize.h
@@ -0,0 +1,3 @@
+/* Determine the wordsize from the preprocessor defines.  */
+
+#define __WORDSIZE	32
diff --git a/ports/sysdeps/tile/tilepro/memchr.c b/ports/sysdeps/tile/tilepro/memchr.c
new file mode 100644
index 0000000000..abf4bbadf6
--- /dev/null
+++ b/ports/sysdeps/tile/tilepro/memchr.c
@@ -0,0 +1,72 @@
+/* Copyright (C) 2011 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+
+   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 <string.h>
+#include <stdint.h>
+
+void *
+__memchr (const void *s, int c, size_t n)
+{
+  const uint32_t *last_word_ptr;
+  const uint32_t *p;
+  const char *last_byte_ptr;
+  uintptr_t s_int;
+  uint32_t goal, before_mask, v, bits;
+  char *ret;
+
+  if (__builtin_expect (n == 0, 0))
+    {
+      /* Don't dereference any memory if the array is empty. */
+      return NULL;
+    }
+
+  /* Get an aligned pointer. */
+  s_int = (uintptr_t) s;
+  p = (const uint32_t *) (s_int & -4);
+
+  /* Create four copies of the byte for which we are looking. */
+  goal = 0x01010101 * (uint8_t) c;
+
+  /* Read the first word, but munge it so that bytes before the array
+     will not match goal.  Note that this shift count expression works
+     because we know shift counts are taken mod 32.  */
+  before_mask = (1 << (s_int << 3)) - 1;
+  v = (*p | before_mask) ^ (goal & before_mask);
+
+  /* Compute the address of the last byte. */
+  last_byte_ptr = (const char *) s + n - 1;
+
+  /* Compute the address of the word containing the last byte. */
+  last_word_ptr = (const uint32_t *) ((uintptr_t) last_byte_ptr & -4);
+
+  while ((bits = __insn_seqb (v, goal)) == 0)
+    {
+      if (__builtin_expect (p == last_word_ptr, 0))
+        {
+          /* We already read the last word in the array, so give up.  */
+          return NULL;
+        }
+      v = *++p;
+    }
+
+  /* We found a match, but it might be in a byte past the end of the array.  */
+  ret = ((char *) p) + (__insn_ctz (bits) >> 3);
+  return (ret <= last_byte_ptr) ? ret : NULL;
+}
+weak_alias (__memchr, memchr)
+libc_hidden_builtin_def (memchr)
diff --git a/ports/sysdeps/tile/tilepro/memcpy.S b/ports/sysdeps/tile/tilepro/memcpy.S
new file mode 100644
index 0000000000..0a64f005fb
--- /dev/null
+++ b/ports/sysdeps/tile/tilepro/memcpy.S
@@ -0,0 +1,397 @@
+/* Copyright (C) 2011 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+
+   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 <arch/chip.h>
+#include <sysdep.h>
+
+	.text
+ENTRY (__memcpy)
+	FEEDBACK_ENTER(__memcpy)
+
+	/* r0 is the dest, r1 is the source, r2 is the size. */
+
+	/* Save aside original dest so we can return it at the end. */
+	{ sw sp, lr; move r23, r0; or r4, r0, r1 }
+	cfi_offset (lr, 0)
+
+	/* Check for an empty size. */
+	{ bz r2, .Ldone; andi r4, r4, 3 }
+
+	/* Check for an unaligned source or dest. */
+	{ bnz r4, .Lcopy_unaligned_maybe_many; addli r4, r2, -256 }
+
+.Lcheck_aligned_copy_size:
+	/* If we are copying < 256 bytes, branch to simple case. */
+	{ blzt r4, .Lcopy_8_check; slti_u r8, r2, 8 }
+
+	/* Copying >= 256 bytes, so jump to complex prefetching loop. */
+	{ andi r6, r1, 63; j .Lcopy_many }
+
+/* Aligned 4 byte at a time copy loop.  */
+
+.Lcopy_8_loop:
+	/* Copy two words at a time to hide load latency. */
+	{ lw r3, r1; addi r1, r1, 4; slti_u r8, r2, 16 }
+	{ lw r4, r1; addi r1, r1, 4 }
+	{ sw r0, r3; addi r0, r0, 4; addi r2, r2, -4 }
+	{ sw r0, r4; addi r0, r0, 4; addi r2, r2, -4 }
+.Lcopy_8_check:
+	{ bzt r8, .Lcopy_8_loop; slti_u r4, r2, 4 }
+
+	/* Copy odd leftover word, if any. */
+	{ bnzt r4, .Lcheck_odd_stragglers }
+	{ lw r3, r1; addi r1, r1, 4 }
+	{ sw r0, r3; addi r0, r0, 4; addi r2, r2, -4 }
+
+.Lcheck_odd_stragglers:
+	{ bnz r2, .Lcopy_unaligned_few }
+
+.Ldone:
+	{ move r0, r23; jrp lr }
+
+/* Prefetching multiple cache line copy handler (for large transfers).  */
+
+	/* Copy words until r1 is cache-line-aligned. */
+.Lalign_loop:
+	{ lw r3, r1; addi r1, r1, 4 }
+	{ andi r6, r1, 63 }
+	{ sw r0, r3; addi r0, r0, 4; addi r2, r2, -4 }
+.Lcopy_many:
+	{ bnzt r6, .Lalign_loop; addi r9, r0, 63 }
+
+	{ addi r3, r1, 60; andi r9, r9, -64 }
+
+	/* No need to prefetch dst, we'll just do the wh64
+           right before we copy a line.  */
+	{ lw r5, r3; addi r3, r3, 64; movei r4, 1 }
+	/* Intentionally stall for a few cycles to leave L2 cache alone. */
+	{ bnzt zero, .; move r27, lr }
+	{ lw r6, r3; addi r3, r3, 64 }
+	/* Intentionally stall for a few cycles to leave L2 cache alone. */
+	{ bnzt zero, . }
+	{ lw r7, r3; addi r3, r3, 64 }
+	/* Intentionally stall for a few cycles to leave L2 cache alone. */
+	{ bz zero, .Lbig_loop2 }
+
+	/* On entry to this loop:
+	   - r0 points to the start of dst line 0
+	   - r1 points to start of src line 0
+	   - r2 >= (256 - 60), only the first time the loop trips.
+	   - r3 contains r1 + 128 + 60    [pointer to end of source line 2]
+	     This is our prefetch address. When we get near the end
+	     rather than prefetching off the end this is changed to point
+	     to some "safe" recently loaded address.
+	   - r5 contains *(r1 + 60)       [i.e. last word of source line 0]
+	   - r6 contains *(r1 + 64 + 60)  [i.e. last word of source line 1]
+	   - r9 contains ((r0 + 63) & -64)
+	       [start of next dst cache line.]  */
+
+.Lbig_loop:
+	{ jal .Lcopy_line2; add r15, r1, r2 }
+
+.Lbig_loop2:
+	/* Copy line 0, first stalling until r5 is ready. */
+	{ move r12, r5; lw r16, r1 }
+	{ bz r4, .Lcopy_8_check; slti_u r8, r2, 8 }
+	/* Prefetch several lines ahead. */
+	{ lw r5, r3; addi r3, r3, 64 }
+	{ jal .Lcopy_line }
+
+	/* Copy line 1, first stalling until r6 is ready. */
+	{ move r12, r6; lw r16, r1 }
+	{ bz r4, .Lcopy_8_check; slti_u r8, r2, 8 }
+	/* Prefetch several lines ahead. */
+	{ lw r6, r3; addi r3, r3, 64 }
+	{ jal .Lcopy_line }
+
+	/* Copy line 2, first stalling until r7 is ready. */
+	{ move r12, r7; lw r16, r1 }
+	{ bz r4, .Lcopy_8_check; slti_u r8, r2, 8 }
+	/* Prefetch several lines ahead. */
+	{ lw r7, r3; addi r3, r3, 64 }
+	/* Use up a caches-busy cycle by jumping back to the top of the
+	   loop. Might as well get it out of the way now.  */
+	{ j .Lbig_loop }
+
+
+	/* On entry:
+	   - r0 points to the destination line.
+	   - r1 points to the source line.
+	   - r3 is the next prefetch address.
+	   - r9 holds the last address used for wh64.
+	   - r12 = WORD_15
+	   - r16 = WORD_0.
+	   - r17 == r1 + 16.
+	   - r27 holds saved lr to restore.
+	  
+	   On exit:
+	   - r0 is incremented by 64.
+	   - r1 is incremented by 64, unless that would point to a word
+	     beyond the end of the source array, in which case it is redirected
+	     to point to an arbitrary word already in the cache.
+	   - r2 is decremented by 64.
+	   - r3 is unchanged, unless it points to a word beyond the
+	     end of the source array, in which case it is redirected
+	     to point to an arbitrary word already in the cache.
+	     Redirecting is OK since if we are that close to the end
+	     of the array we will not come back to this subroutine
+	     and use the contents of the prefetched address.
+	   - r4 is nonzero iff r2 >= 64.
+	   - r9 is incremented by 64, unless it points beyond the
+	     end of the last full destination cache line, in which
+	     case it is redirected to a "safe address" that can be
+	     clobbered (sp - 64)
+	   - lr contains the value in r27.  */
+
+/* r26 unused */
+
+.Lcopy_line:
+	/* TODO: when r3 goes past the end, we would like to redirect it
+	   to prefetch the last partial cache line (if any) just once, for the
+	   benefit of the final cleanup loop. But we don't want to
+	   prefetch that line more than once, or subsequent prefetches
+	   will go into the RTF. But then .Lbig_loop should unconditionally
+	   branch to top of loop to execute final prefetch, and its
+	   nop should become a conditional branch.  */
+
+	/* We need two non-memory cycles here to cover the resources
+	   used by the loads initiated by the caller.  */
+	{ add r15, r1, r2 }
+.Lcopy_line2:
+	{ slt_u r13, r3, r15; addi r17, r1, 16 }
+
+	/* NOTE: this will stall for one cycle as L1 is busy. */
+
+	/* Fill second L1D line. */
+	{ lw r17, r17; addi r1, r1, 48; mvz r3, r13, r1 } /* r17 = WORD_4 */
+
+	/* Prepare destination line for writing. */
+	{ wh64 r9; addi r9, r9, 64 }
+
+	/* Load seven words that are L1D hits to cover wh64 L2 usage. */
+
+	/* Load the three remaining words from the last L1D line, which
+	   we know has already filled the L1D.  */
+	{ lw r4, r1;  addi r1, r1, 4;   addi r20, r1, 16 }   /* r4 = WORD_12 */
+	{ lw r8, r1;  addi r1, r1, 4;   slt_u r13, r20, r15 }/* r8 = WORD_13 */
+	{ lw r11, r1; addi r1, r1, -52; mvz r20, r13, r1 }  /* r11 = WORD_14 */
+
+	/* Load the three remaining words from the first L1D line, first
+	   stalling until it has filled by "looking at" r16.  */
+	{ lw r13, r1; addi r1, r1, 4; move zero, r16 }   /* r13 = WORD_1 */
+	{ lw r14, r1; addi r1, r1, 4 }                   /* r14 = WORD_2 */
+	{ lw r15, r1; addi r1, r1, 8; addi r10, r0, 60 } /* r15 = WORD_3 */
+
+	/* Load second word from the second L1D line, first
+	   stalling until it has filled by "looking at" r17.  */
+	{ lw r19, r1; addi r1, r1, 4; move zero, r17 }  /* r19 = WORD_5 */
+
+	/* Store last word to the destination line, potentially dirtying it
+	   for the first time, which keeps the L2 busy for two cycles.  */
+	{ sw r10, r12 }                                 /* store(WORD_15) */
+
+	/* Use two L1D hits to cover the sw L2 access above. */
+	{ lw r10, r1; addi r1, r1, 4 }                  /* r10 = WORD_6 */
+	{ lw r12, r1; addi r1, r1, 4 }                  /* r12 = WORD_7 */
+
+	/* Fill third L1D line. */
+	{ lw r18, r1; addi r1, r1, 4 }                  /* r18 = WORD_8 */
+
+	/* Store first L1D line. */
+	{ sw r0, r16; addi r0, r0, 4; add r16, r0, r2 } /* store(WORD_0) */
+	{ sw r0, r13; addi r0, r0, 4; andi r16, r16, -64 } /* store(WORD_1) */
+	{ sw r0, r14; addi r0, r0, 4; slt_u r16, r9, r16 } /* store(WORD_2) */
+	{ sw r0, r15; addi r0, r0, 4; addi r13, sp, -64 } /* store(WORD_3) */
+
+	/* Store second L1D line. */
+	{ sw r0, r17; addi r0, r0, 4; mvz r9, r16, r13 }/* store(WORD_4) */
+	{ sw r0, r19; addi r0, r0, 4 }                  /* store(WORD_5) */
+	{ sw r0, r10; addi r0, r0, 4 }                  /* store(WORD_6) */
+	{ sw r0, r12; addi r0, r0, 4 }                  /* store(WORD_7) */
+
+	{ lw r13, r1; addi r1, r1, 4; move zero, r18 }  /* r13 = WORD_9 */
+	{ lw r14, r1; addi r1, r1, 4 }                  /* r14 = WORD_10 */
+	{ lw r15, r1; move r1, r20   }                  /* r15 = WORD_11 */
+
+	/* Store third L1D line. */
+	{ sw r0, r18; addi r0, r0, 4 }                  /* store(WORD_8) */
+	{ sw r0, r13; addi r0, r0, 4 }                  /* store(WORD_9) */
+	{ sw r0, r14; addi r0, r0, 4 }                  /* store(WORD_10) */
+	{ sw r0, r15; addi r0, r0, 4 }                  /* store(WORD_11) */
+
+	/* Store rest of fourth L1D line. */
+	{ sw r0, r4;  addi r0, r0, 4 }                  /* store(WORD_12) */
+	{
+	sw r0, r8                                       /* store(WORD_13) */
+	addi r0, r0, 4
+	/* Will r2 be > 64 after we subtract 64 below? */
+	shri r4, r2, 7
+	}
+	{
+	sw r0, r11                                      /* store(WORD_14) */
+	addi r0, r0, 8
+	/* Record 64 bytes successfully copied. */
+	addi r2, r2, -64
+	}
+
+	{ jrp lr; move lr, r27 }
+
+	/* Convey to the backtrace library that the stack frame is
+	   size zero, and the real return address is on the stack
+	   rather than in 'lr'.  */
+	{ info 8 }
+
+	.align 64
+.Lcopy_unaligned_maybe_many:
+	/* Skip the setup overhead if we aren't copying many bytes. */
+	{ slti_u r8, r2, 20; sub r4, zero, r0 }
+	{ bnzt r8, .Lcopy_unaligned_few; andi r4, r4, 3 }
+	{ bz r4, .Ldest_is_word_aligned; add r18, r1, r2 }
+
+/* Unaligned 4 byte at a time copy handler.  */
+
+	/* Copy single bytes until r0 == 0 mod 4, so we can store words. */
+.Lalign_dest_loop:
+	{ lb_u r3, r1; addi r1, r1, 1; addi r4, r4, -1 }
+	{ sb r0, r3;   addi r0, r0, 1; addi r2, r2, -1 }
+	{ bnzt r4, .Lalign_dest_loop; andi r3, r1, 3 }
+
+	/* If source and dest are now *both* aligned, do an aligned copy. */
+	{ bz r3, .Lcheck_aligned_copy_size; addli r4, r2, -256 }
+
+.Ldest_is_word_aligned:
+
+	{ andi r8, r0, 63; lwadd_na r6, r1, 4}
+	{ slti_u r9, r2, 64; bz r8, .Ldest_is_L2_line_aligned }
+
+	/* This copies unaligned words until either there are fewer
+	   than 4 bytes left to copy, or until the destination pointer
+	   is cache-aligned, whichever comes first.
+	  
+	   On entry:
+	   - r0 is the next store address.
+	   - r1 points 4 bytes past the load address corresponding to r0.
+	   - r2 >= 4
+	   - r6 is the next aligned word loaded.  */
+.Lcopy_unaligned_src_words:
+	{ lwadd_na r7, r1, 4; slti_u r8, r2, 4 + 4 }
+	/* stall */
+	{ dword_align r6, r7, r1; slti_u r9, r2, 64 + 4 }
+	{ swadd r0, r6, 4; addi r2, r2, -4 }
+	{ bnz r8, .Lcleanup_unaligned_words; andi r8, r0, 63 }
+	{ bnzt r8, .Lcopy_unaligned_src_words; move r6, r7 }
+
+	/* On entry:
+	   - r0 is the next store address.
+	   - r1 points 4 bytes past the load address corresponding to r0.
+	   - r2 >= 4 (# of bytes left to store).
+	   - r6 is the next aligned src word value.
+	   - r9 = (r2 < 64U).
+	   - r18 points one byte past the end of source memory.  */
+.Ldest_is_L2_line_aligned:
+
+	{
+	/* Not a full cache line remains. */
+	bnz r9, .Lcleanup_unaligned_words
+	move r7, r6
+	}
+
+	/* r2 >= 64 */
+
+	/* Kick off two prefetches, but don't go past the end. */
+	{ addi r3, r1, 63 - 4; addi r8, r1, 64 + 63 - 4 }
+	{ prefetch r3; move r3, r8; slt_u r8, r8, r18 }
+	{ mvz r3, r8, r1; addi r8, r3, 64 }
+	{ prefetch r3; move r3, r8; slt_u r8, r8, r18 }
+	{ mvz r3, r8, r1; movei r17, 0 }
+
+.Lcopy_unaligned_line:
+	/* Prefetch another line. */
+	{ prefetch r3; addi r15, r1, 60; addi r3, r3, 64 }
+	/* Fire off a load of the last word we are about to copy. */
+	{ lw_na r15, r15; slt_u r8, r3, r18 }
+
+	{ mvz r3, r8, r1; wh64 r0 }
+
+	/* This loop runs twice.
+	  
+	   On entry:
+	   - r17 is even before the first iteration, and odd before
+	     the second.  It is incremented inside the loop.  Encountering
+	     an even value at the end of the loop makes it stop.  */
+.Lcopy_half_an_unaligned_line:
+	{
+	/* Stall until the last byte is ready. In the steady state this
+	   guarantees all words to load below will be in the L2 cache, which
+	   avoids shunting the loads to the RTF.  */
+	move zero, r15
+	lwadd_na r7, r1, 16
+	}
+	{ lwadd_na r11, r1, 12 }
+	{ lwadd_na r14, r1, -24 }
+	{ lwadd_na r8, r1, 4 }
+	{ lwadd_na r9, r1, 4 }
+	{
+	lwadd_na r10, r1, 8
+	/* r16 = (r2 < 64), after we subtract 32 from r2 below. */
+	slti_u r16, r2, 64 + 32
+	}
+	{ lwadd_na r12, r1, 4; addi r17, r17, 1 }
+	{ lwadd_na r13, r1, 8; dword_align r6, r7, r1 }
+	{ swadd r0, r6,  4; dword_align r7,  r8,  r1 }
+	{ swadd r0, r7,  4; dword_align r8,  r9,  r1 }
+	{ swadd r0, r8,  4; dword_align r9,  r10, r1 }
+	{ swadd r0, r9,  4; dword_align r10, r11, r1 }
+	{ swadd r0, r10, 4; dword_align r11, r12, r1 }
+	{ swadd r0, r11, 4; dword_align r12, r13, r1 }
+	{ swadd r0, r12, 4; dword_align r13, r14, r1 }
+	{ swadd r0, r13, 4; addi r2, r2, -32 }
+	{ move r6, r14; bbst r17, .Lcopy_half_an_unaligned_line }
+
+	{ bzt r16, .Lcopy_unaligned_line; move r7, r6 }
+
+	/* On entry:
+	   - r0 is the next store address.
+	   - r1 points 4 bytes past the load address corresponding to r0.
+	   - r2 >= 0 (# of bytes left to store).
+	   - r7 is the next aligned src word value.  */
+.Lcleanup_unaligned_words:
+	/* Handle any trailing bytes. */
+	{ bz r2, .Lcopy_unaligned_done; slti_u r8, r2, 4 }
+	{ bzt r8, .Lcopy_unaligned_src_words; move r6, r7 }
+
+	/* Move r1 back to the point where it corresponds to r0. */
+	{ addi r1, r1, -4 }
+
+	/* Fall through */
+
+/* 1 byte at a time copy handler.  */
+
+.Lcopy_unaligned_few:
+	{ lb_u r3, r1; addi r1, r1, 1 }
+	{ sb r0, r3;   addi r0, r0, 1; addi r2, r2, -1 }
+	{ bnzt r2, .Lcopy_unaligned_few }
+
+.Lcopy_unaligned_done:
+
+	{ move r0, r23; jrp lr }
+
+END (__memcpy)
+
+weak_alias (__memcpy, memcpy)
+libc_hidden_builtin_def (memcpy)
diff --git a/ports/sysdeps/tile/tilepro/memset.c b/ports/sysdeps/tile/tilepro/memset.c
new file mode 100644
index 0000000000..6fb9ab81ed
--- /dev/null
+++ b/ports/sysdeps/tile/tilepro/memset.c
@@ -0,0 +1,151 @@
+/* Copyright (C) 2011 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+
+   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 <string.h>
+#include <stdint.h>
+#include <arch/chip.h>
+
+void *
+__memset (void *s, int c, size_t n)
+{
+  uint32_t *out32;
+  int n32;
+  uint32_t v16, v32;
+  uint8_t *out8 = s;
+  int to_align32;
+
+  /* Experimentation shows that a trivial tight loop is a win up until
+     around a size of 20, where writing a word at a time starts to win.  */
+#define BYTE_CUTOFF 20
+
+#if BYTE_CUTOFF < 3
+  /* This must be at least at least this big, or some code later
+     on doesn't work.  */
+# error "BYTE_CUTOFF is too small."
+#endif
+
+  if (n < BYTE_CUTOFF)
+    {
+      /* Strangely, this turns out to be the tightest way to write
+         this loop.  */
+      if (n != 0)
+        {
+          do
+            {
+              /* Strangely, combining these into one line performs worse.  */
+              *out8 = c;
+              out8++;
+            }
+          while (--n != 0);
+        }
+
+      return s;
+    }
+
+  /* Align 'out8'. We know n >= 3 so this won't write past the end. */
+  while (((uintptr_t) out8 & 3) != 0)
+    {
+      *out8++ = c;
+      --n;
+    }
+
+  /* Align 'n'. */
+  while (n & 3)
+    out8[--n] = c;
+
+  out32 = (uint32_t *) out8;
+  n32 = n >> 2;
+
+  /* Tile input byte out to 32 bits. */
+  v16 = __insn_intlb (c, c);
+  v32 = __insn_intlh (v16, v16);
+
+  /* This must be at least 8 or the following loop doesn't work. */
+#define CACHE_LINE_SIZE_IN_WORDS (CHIP_L2_LINE_SIZE() / 4)
+
+  /* Determine how many words we need to emit before the 'out32'
+     pointer becomes aligned modulo the cache line size.  */
+  to_align32 = (-((uintptr_t) out32 >> 2)) & (CACHE_LINE_SIZE_IN_WORDS - 1);
+
+  /* Only bother aligning and using wh64 if there is at least one full
+     cache line to process.  This check also prevents overrunning the
+     end of the buffer with alignment words.  */
+  if (to_align32 <= n32 - CACHE_LINE_SIZE_IN_WORDS)
+    {
+      int lines_left;
+
+      /* Align out32 mod the cache line size so we can use wh64. */
+      n32 -= to_align32;
+      for (; to_align32 != 0; to_align32--)
+        {
+          *out32 = v32;
+          out32++;
+        }
+
+      /* Use unsigned divide to turn this into a right shift. */
+      lines_left = (unsigned) n32 / CACHE_LINE_SIZE_IN_WORDS;
+
+      do
+        {
+          /* Only wh64 a few lines at a time, so we don't exceed the
+             maximum number of victim lines.  */
+          int x = ((lines_left < CHIP_MAX_OUTSTANDING_VICTIMS ())? lines_left
+                   : CHIP_MAX_OUTSTANDING_VICTIMS ());
+          uint32_t *wh = out32;
+          int i = x;
+          int j;
+
+          lines_left -= x;
+
+          do
+            {
+              __insn_wh64 (wh);
+              wh += CACHE_LINE_SIZE_IN_WORDS;
+            }
+          while (--i);
+
+          for (j = x * (CACHE_LINE_SIZE_IN_WORDS / 4); j != 0; j--)
+            {
+              *out32++ = v32;
+              *out32++ = v32;
+              *out32++ = v32;
+              *out32++ = v32;
+            }
+        }
+      while (lines_left != 0);
+
+      /* We processed all full lines above, so only this many words
+         remain to be processed.  */
+      n32 &= CACHE_LINE_SIZE_IN_WORDS - 1;
+    }
+
+  /* Now handle any leftover values. */
+  if (n32 != 0)
+    {
+      do
+        {
+          *out32 = v32;
+          out32++;
+        }
+      while (--n32 != 0);
+    }
+
+  return s;
+}
+weak_alias (__memset, memset)
+libc_hidden_builtin_def (memset)
diff --git a/ports/sysdeps/tile/tilepro/memusage.h b/ports/sysdeps/tile/tilepro/memusage.h
new file mode 100644
index 0000000000..ac07c3871e
--- /dev/null
+++ b/ports/sysdeps/tile/tilepro/memusage.h
@@ -0,0 +1,29 @@
+/* Copyright (C) 2011 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+
+   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 <arch/spr_def.h>
+
+#define GETSP() ({ register uintptr_t stack_ptr asm ("sp"); stack_ptr; })
+
+#define GETTIME(low,high)                       \
+  {                                             \
+    low = __insn_mfspr (SPR_CYCLE_LOW);         \
+    high = __insn_mfspr (SPR_CYCLE_HIGH);       \
+  }
+
+#include <sysdeps/generic/memusage.h>
diff --git a/ports/sysdeps/tile/tilepro/rawmemchr.c b/ports/sysdeps/tile/tilepro/rawmemchr.c
new file mode 100644
index 0000000000..d52bc96618
--- /dev/null
+++ b/ports/sysdeps/tile/tilepro/rawmemchr.c
@@ -0,0 +1,45 @@
+/* Copyright (C) 2011 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+
+   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 <string.h>
+#include <stdint.h>
+
+void *
+__rawmemchr (const void *s, int c)
+{
+  /* Get an aligned pointer. */
+  const uintptr_t s_int = (uintptr_t) s;
+  const uint32_t *p = (const uint32_t *) (s_int & -4);
+
+  /* Create four copies of the byte for which we are looking. */
+  const uint32_t goal = 0x01010101 * (uint8_t) c;
+
+  /* Read the first word, but munge it so that bytes before the array
+     will not match goal.  Note that this shift count expression works
+     because we know shift counts are taken mod 32.  */
+  const uint32_t before_mask = (1 << (s_int << 3)) - 1;
+  uint32_t v = (*p | before_mask) ^ (goal & before_mask);
+
+  uint32_t bits;
+  while ((bits = __insn_seqb (v, goal)) == 0)
+    v = *++p;
+
+  return ((char *) p) + (__insn_ctz (bits) >> 3);
+}
+libc_hidden_def (__rawmemchr)
+weak_alias (__rawmemchr, rawmemchr)
diff --git a/ports/sysdeps/tile/tilepro/strchr.c b/ports/sysdeps/tile/tilepro/strchr.c
new file mode 100644
index 0000000000..8615000e50
--- /dev/null
+++ b/ports/sysdeps/tile/tilepro/strchr.c
@@ -0,0 +1,68 @@
+/* Copyright (C) 2011 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+
+   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 <string.h>
+#include <stdint.h>
+
+#undef strchr
+
+char *
+strchr (const char *s, int c)
+{
+  int z, g;
+
+  /* Get an aligned pointer. */
+  const uintptr_t s_int = (uintptr_t) s;
+  const uint32_t *p = (const uint32_t *) (s_int & -4);
+
+  /* Create four copies of the byte for which we are looking. */
+  const uint32_t goal = 0x01010101 * (uint8_t) c;
+
+  /* Read the first aligned word, but force bytes before the string to
+     match neither zero nor goal (we make sure the high bit of each
+     byte is 1, and the low 7 bits are all the opposite of the goal
+     byte).  Note that this shift count expression works because we
+     know shift counts are taken mod 32.  */
+  const uint32_t before_mask = (1 << (s_int << 3)) - 1;
+  uint32_t v = (*p | before_mask) ^ (goal & __insn_shrib (before_mask, 1));
+
+  uint32_t zero_matches, goal_matches;
+  while (1)
+    {
+      /* Look for a terminating '\0'. */
+      zero_matches = __insn_seqb (v, 0);
+
+      /* Look for the goal byte. */
+      goal_matches = __insn_seqb (v, goal);
+
+      if (__builtin_expect ((zero_matches | goal_matches) != 0, 0))
+        break;
+
+      v = *++p;
+    }
+
+  z = __insn_ctz (zero_matches);
+  g = __insn_ctz (goal_matches);
+
+  /* If we found c before '\0' we got a match. Note that if c == '\0'
+     then g == z, and we correctly return the address of the '\0'
+     rather than NULL.  */
+  return (g <= z) ? ((char *) p) + (g >> 3) : NULL;
+}
+weak_alias (strchr, index)
+libc_hidden_builtin_def (strchr)
diff --git a/ports/sysdeps/tile/tilepro/strchrnul.c b/ports/sysdeps/tile/tilepro/strchrnul.c
new file mode 100644
index 0000000000..4f65612a98
--- /dev/null
+++ b/ports/sysdeps/tile/tilepro/strchrnul.c
@@ -0,0 +1,65 @@
+/* Copyright (C) 2011 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+
+   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 <string.h>
+#include <stdint.h>
+
+char *
+__strchrnul (const char *s, int c)
+{
+  int z, g;
+
+  /* Get an aligned pointer. */
+  const uintptr_t s_int = (uintptr_t) s;
+  const uint32_t *p = (const uint32_t *) (s_int & -4);
+
+  /* Create four copies of the byte for which we are looking. */
+  const uint32_t goal = 0x01010101 * (uint8_t) c;
+
+  /* Read the first aligned word, but force bytes before the string to
+     match neither zero nor goal (we make sure the high bit of each
+     byte is 1, and the low 7 bits are all the opposite of the goal
+     byte).  Note that this shift count expression works because we
+     know shift counts are taken mod 32.  */
+  const uint32_t before_mask = (1 << (s_int << 3)) - 1;
+  uint32_t v = (*p | before_mask) ^ (goal & __insn_shrib (before_mask, 1));
+
+  uint32_t zero_matches, goal_matches;
+  while (1)
+    {
+      /* Look for a terminating '\0'. */
+      zero_matches = __insn_seqb (v, 0);
+
+      /* Look for the goal byte. */
+      goal_matches = __insn_seqb (v, goal);
+
+      if (__builtin_expect ((zero_matches | goal_matches) != 0, 0))
+        break;
+
+      v = *++p;
+    }
+
+  z = __insn_ctz (zero_matches);
+  g = __insn_ctz (goal_matches);
+
+  /* Return a pointer to the NUL or goal, whichever is first. */
+  if (z < g)
+    g = z;
+  return ((char *) p) + (g >> 3);
+}
+weak_alias (__strchrnul, strchrnul)
diff --git a/ports/sysdeps/tile/tilepro/strlen.c b/ports/sysdeps/tile/tilepro/strlen.c
new file mode 100644
index 0000000000..8e53b51aea
--- /dev/null
+++ b/ports/sysdeps/tile/tilepro/strlen.c
@@ -0,0 +1,39 @@
+/* Copyright (C) 2011 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+
+   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 <string.h>
+#include <stdint.h>
+
+size_t
+strlen (const char *s)
+{
+  /* Get an aligned pointer. */
+  const uintptr_t s_int = (uintptr_t) s;
+  const uint32_t *p = (const uint32_t *) (s_int & -4);
+
+  /* Read the first word, but force bytes before the string to be nonzero.
+     This expression works because we know shift counts are taken mod 32.  */
+  uint32_t v = *p | ((1 << (s_int << 3)) - 1);
+
+  uint32_t bits;
+  while ((bits = __insn_seqb (v, 0)) == 0)
+    v = *++p;
+
+  return ((const char *) p) + (__insn_ctz (bits) >> 3) - s;
+}
+libc_hidden_builtin_def (strlen)
diff --git a/ports/sysdeps/tile/tilepro/strrchr.c b/ports/sysdeps/tile/tilepro/strrchr.c
new file mode 100644
index 0000000000..a41f9dad92
--- /dev/null
+++ b/ports/sysdeps/tile/tilepro/strrchr.c
@@ -0,0 +1,73 @@
+/* Copyright (C) 2011 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+
+   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 <string.h>
+#include <stdint.h>
+
+char *
+strrchr (const char *s, int c)
+{
+  /* Get an aligned pointer. */
+  const uintptr_t s_int = (uintptr_t) s;
+  const uint32_t *p = (const uint32_t *) (s_int & -4);
+
+  /* Create four copies of the byte for which we are looking. */
+  const uint32_t goal = 0x01010101 * (uint8_t) c;
+
+  /* Read the first aligned word, but force bytes before the string to
+     match neither zero nor goal (we make sure the high bit of each
+     byte is 1, and the low 7 bits are all the opposite of the goal
+     byte).  Note that this shift count expression works because we
+     know shift counts are taken mod 32.  */
+  const uint32_t before_mask = (1 << (s_int << 3)) - 1;
+  uint32_t v = (*p | before_mask) ^ (goal & __insn_shrib (before_mask, 1));
+  const char *found = NULL;
+  uint32_t zero_matches, goal_matches;
+  while (1)
+    {
+      /* Look for a terminating '\0'. */
+      zero_matches = __insn_seqb (v, 0);
+
+      /* Look for the goal byte. */
+      goal_matches = __insn_seqb (v, goal);
+
+      /* If we found the goal, record the last offset. */
+      if (__builtin_expect (goal_matches != 0, 0))
+        {
+          if (__builtin_expect (zero_matches != 0, 0))
+            {
+              /* Clear any goal after the first zero. */
+              int first_nul = __insn_ctz (zero_matches);
+              /* The number of top bits we need to clear is
+                 32 - (first_nul + 8).  */
+              int shift_amt = (24 - first_nul);
+              goal_matches <<= shift_amt;
+              goal_matches >>= shift_amt;
+            }
+          if (__builtin_expect (goal_matches != 0, 1))
+            found = ((char *) p) + 3 - (__insn_clz (goal_matches) >> 3);
+        }
+
+      if (__builtin_expect (zero_matches != 0, 0))
+        return (char *) found;
+
+      v = *++p;
+    }
+}
+weak_alias (strrchr, rindex)
+libc_hidden_builtin_def (strrchr)
diff --git a/ports/sysdeps/tile/tls-macros.h b/ports/sysdeps/tile/tls-macros.h
new file mode 100644
index 0000000000..25e5375a95
--- /dev/null
+++ b/ports/sysdeps/tile/tls-macros.h
@@ -0,0 +1,84 @@
+/* Copyright (C) 2011-2012 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+
+   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/>.  */
+
+#ifdef __tilegx__
+#define TLS_GD_OFFSET(x)                        \
+  "moveli r0, hw1_last_tls_gd(" #x ")\n\t"      \
+  "shl16insli r0, r0, hw0_tls_gd(" #x ")\n\t"   \
+  "addi r0, %1, tls_add(" #x ")\n\t"
+#else
+#define TLS_GD_OFFSET(x)                        \
+  "auli r0, %1, tls_gd_ha16(" #x ")\n\t"        \
+  "addli r0, r0, tls_gd_lo16(" #x ")\n\t"
+#endif
+
+#define TLS_GD(x)                                               \
+  ({                                                            \
+    int *__retval;                                              \
+    extern char _GLOBAL_OFFSET_TABLE_[];                        \
+                                                                \
+    asm (TLS_GD_OFFSET(x)                                       \
+         "jal tls_gd_call(" #x ")\n\t"                          \
+         "addi %0, r0, tls_gd_add(" #x ")" :                    \
+         "=&r" (__retval) : "r" (_GLOBAL_OFFSET_TABLE_) :       \
+         "r0", "r25", "r26", "r27", "r28", "r29");              \
+    __retval; })
+
+/* No special support for LD mode. */
+#define TLS_LD TLS_GD
+
+#ifdef __tilegx__
+#define TLS_IE_OFFSET(x)                        \
+  "moveli %0, hw1_last_tls_ie(" #x ")\n\t"      \
+  "shl16insli %0, %0, hw0_tls_ie(" #x ")\n\t"   \
+  "addi %0, %1, tls_add(" #x ")\n\t"
+#define LD_TLS "ld_tls"
+#else
+#define TLS_IE_OFFSET(x)                        \
+  "auli %0, %1, tls_ie_ha16(" #x ")\n\t"        \
+  "addli %0, %0, tls_ie_lo16(" #x ")\n\t"
+#define LD_TLS "lw_tls"
+#endif
+
+#define TLS_IE(x)                                               \
+  ({                                                            \
+    int *__retval;                                              \
+    extern char _GLOBAL_OFFSET_TABLE_[];                        \
+                                                                \
+    asm (TLS_IE_OFFSET(x)                                       \
+         LD_TLS " %0, %0, tls_ie_load(" #x ")\n\t"              \
+         "add %0, %0, tp" :                                     \
+         "=&r" (__retval) : "r" (_GLOBAL_OFFSET_TABLE_));       \
+    __retval; })
+
+#ifdef __tilegx__
+#define _TLS_LE(x)                              \
+  "moveli %0, hw1_last_tls_le(" #x ")\n\t"      \
+  "shl16insli %0, %0, hw0_tls_le(" #x ")\n\t"   \
+  "add %0, %0, tp"
+#else
+#define _TLS_LE(x)                              \
+  "auli %0, tp, tls_le_ha16(" #x ")\n\t"        \
+  "addli %0, %0, tls_le_lo16(" #x ")\n\t"
+#endif
+
+#define TLS_LE(x)                               \
+  ({                                            \
+    int *__retval;                              \
+    asm (_TLS_LE(x) : "=r" (__retval));         \
+    __retval; })
diff --git a/ports/sysdeps/tile/tst-audit.h b/ports/sysdeps/tile/tst-audit.h
new file mode 100644
index 0000000000..06006a61c7
--- /dev/null
+++ b/ports/sysdeps/tile/tst-audit.h
@@ -0,0 +1,23 @@
+/* Copyright (C) 2011 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#define pltenter la_tile_gnu_pltenter
+#define pltexit la_tile_gnu_pltexit
+#define La_regs La_tile_regs
+#define La_retval La_tile_retval
+#define int_retval lrv_reg[0]