summaryrefslogtreecommitdiff
path: root/ports/sysdeps/arm
diff options
context:
space:
mode:
Diffstat (limited to 'ports/sysdeps/arm')
-rw-r--r--ports/sysdeps/arm/Implies3
-rw-r--r--ports/sysdeps/arm/Makefile35
-rw-r--r--ports/sysdeps/arm/Versions20
-rw-r--r--ports/sysdeps/arm/__longjmp.S111
-rw-r--r--ports/sysdeps/arm/abi-note.S9
-rw-r--r--ports/sysdeps/arm/aeabi_assert.c26
-rw-r--r--ports/sysdeps/arm/aeabi_atexit.c27
-rw-r--r--ports/sysdeps/arm/aeabi_errno_addr.c24
-rw-r--r--ports/sysdeps/arm/aeabi_lcsts.c98
-rw-r--r--ports/sysdeps/arm/aeabi_localeconv.c24
-rw-r--r--ports/sysdeps/arm/aeabi_math.c41
-rw-r--r--ports/sysdeps/arm/aeabi_mb_cur_max.c27
-rw-r--r--ports/sysdeps/arm/aeabi_memclr.c30
-rw-r--r--ports/sysdeps/arm/aeabi_memcpy.c31
-rw-r--r--ports/sysdeps/arm/aeabi_memmove.c31
-rw-r--r--ports/sysdeps/arm/aeabi_memset.c30
-rw-r--r--ports/sysdeps/arm/aeabi_sighandlers.S53
-rw-r--r--ports/sysdeps/arm/aeabi_unwind_cpp_pr1.c51
-rw-r--r--ports/sysdeps/arm/arm-mcount.S108
-rw-r--r--ports/sysdeps/arm/armv6t2/memchr.S163
-rw-r--r--ports/sysdeps/arm/armv7/Implies2
-rw-r--r--ports/sysdeps/arm/backtrace.c125
-rw-r--r--ports/sysdeps/arm/bits/endian.h10
-rw-r--r--ports/sysdeps/arm/bits/fenv.h73
-rw-r--r--ports/sysdeps/arm/bits/link.h65
-rw-r--r--ports/sysdeps/arm/bits/linkmap.h5
-rw-r--r--ports/sysdeps/arm/bits/mathdef.h56
-rw-r--r--ports/sysdeps/arm/bits/setjmp.h37
-rw-r--r--ports/sysdeps/arm/bsd-_setjmp.S29
-rw-r--r--ports/sysdeps/arm/bsd-setjmp.S28
-rwxr-xr-xports/sysdeps/arm/configure335
-rw-r--r--ports/sysdeps/arm/configure.in68
-rw-r--r--ports/sysdeps/arm/crti.S93
-rw-r--r--ports/sysdeps/arm/crtn.S55
-rw-r--r--ports/sysdeps/arm/dl-irel.h51
-rw-r--r--ports/sysdeps/arm/dl-lookupcfg.h27
-rw-r--r--ports/sysdeps/arm/dl-machine.h694
-rw-r--r--ports/sysdeps/arm/dl-sysdep.h23
-rw-r--r--ports/sysdeps/arm/dl-tls.h31
-rw-r--r--ports/sysdeps/arm/dl-tlsdesc.S218
-rw-r--r--ports/sysdeps/arm/dl-tlsdesc.h68
-rw-r--r--ports/sysdeps/arm/dl-trampoline.S217
-rw-r--r--ports/sysdeps/arm/fclrexcpt.c60
-rw-r--r--ports/sysdeps/arm/fedisblxcpt.c50
-rw-r--r--ports/sysdeps/arm/feenablxcpt.c50
-rw-r--r--ports/sysdeps/arm/fegetenv.c51
-rw-r--r--ports/sysdeps/arm/fegetexcept.c42
-rw-r--r--ports/sysdeps/arm/fegetround.c42
-rw-r--r--ports/sysdeps/arm/feholdexcpt.c53
-rw-r--r--ports/sysdeps/arm/fesetenv.c56
-rw-r--r--ports/sysdeps/arm/fesetround.c56
-rw-r--r--ports/sysdeps/arm/feupdateenv.c59
-rw-r--r--ports/sysdeps/arm/fgetexcptflg.c53
-rw-r--r--ports/sysdeps/arm/find_exidx.c79
-rw-r--r--ports/sysdeps/arm/fpu_control.h63
-rw-r--r--ports/sysdeps/arm/fraiseexcpt.c109
-rw-r--r--ports/sysdeps/arm/frame.h27
-rw-r--r--ports/sysdeps/arm/framestate.c1
-rw-r--r--ports/sysdeps/arm/fsetexcptflg.c59
-rw-r--r--ports/sysdeps/arm/ftestexcept.c43
-rw-r--r--ports/sysdeps/arm/gccframe.h21
-rw-r--r--ports/sysdeps/arm/gmp-mparam.h36
-rw-r--r--ports/sysdeps/arm/jmpbuf-offsets.h19
-rw-r--r--ports/sysdeps/arm/jmpbuf-unwind.h35
-rw-r--r--ports/sysdeps/arm/ldsodefs.h40
-rw-r--r--ports/sysdeps/arm/libc-tls.c32
-rw-r--r--ports/sysdeps/arm/libm-test-ulps1845
-rw-r--r--ports/sysdeps/arm/machine-gmon.h33
-rw-r--r--ports/sysdeps/arm/memcpy.S263
-rw-r--r--ports/sysdeps/arm/memmove.S279
-rw-r--r--ports/sysdeps/arm/memset.S64
-rw-r--r--ports/sysdeps/arm/memusage.h20
-rw-r--r--ports/sysdeps/arm/nptl/Makefile20
-rw-r--r--ports/sysdeps/arm/nptl/pthread_spin_lock.c29
-rw-r--r--ports/sysdeps/arm/nptl/pthread_spin_trylock.c26
-rw-r--r--ports/sysdeps/arm/nptl/pthreaddef.h46
-rw-r--r--ports/sysdeps/arm/nptl/tcb-offsets.sym11
-rw-r--r--ports/sysdeps/arm/nptl/tls.h151
-rw-r--r--ports/sysdeps/arm/preconfigure50
-rw-r--r--ports/sysdeps/arm/rtld-global-offsets.sym7
-rw-r--r--ports/sysdeps/arm/setfpucw.c46
-rw-r--r--ports/sysdeps/arm/setjmp.S98
-rw-r--r--ports/sysdeps/arm/shlib-versions9
-rw-r--r--ports/sysdeps/arm/stackinfo.h33
-rw-r--r--ports/sysdeps/arm/start.S148
-rw-r--r--ports/sysdeps/arm/strlen.S72
-rw-r--r--ports/sysdeps/arm/sys/ucontext.h94
-rw-r--r--ports/sysdeps/arm/sysdep.h120
-rw-r--r--ports/sysdeps/arm/tls-macros.h78
-rw-r--r--ports/sysdeps/arm/tlsdesc.c160
-rw-r--r--ports/sysdeps/arm/tlsdesc.sym15
-rw-r--r--ports/sysdeps/arm/tst-audit.h25
-rw-r--r--ports/sysdeps/arm/unwind-dw2-fde-glibc.c79
-rw-r--r--ports/sysdeps/arm/unwind-pe.c1
94 files changed, 8210 insertions, 0 deletions
diff --git a/ports/sysdeps/arm/Implies b/ports/sysdeps/arm/Implies
new file mode 100644
index 0000000000..780c4e2467
--- /dev/null
+++ b/ports/sysdeps/arm/Implies
@@ -0,0 +1,3 @@
+wordsize-32
+ieee754/flt-32
+ieee754/dbl-64
diff --git a/ports/sysdeps/arm/Makefile b/ports/sysdeps/arm/Makefile
new file mode 100644
index 0000000000..5fd5136328
--- /dev/null
+++ b/ports/sysdeps/arm/Makefile
@@ -0,0 +1,35 @@
+ifeq ($(subdir),elf)
+sysdep-dl-routines += tlsdesc dl-tlsdesc
+sysdep_routines += aeabi_unwind_cpp_pr1 find_exidx tlsdesc dl-tlsdesc
+sysdep-rtld-routines += aeabi_unwind_cpp_pr1 tlsdesc dl-tlsdesc
+shared-only-routines += aeabi_unwind_cpp_pr1
+endif
+
+ifeq ($(subdir),csu)
+# get offset to rtld_global._dl_hwcap
+gen-as-const-headers += rtld-global-offsets.sym tlsdesc.sym
+aeabi_constants = aeabi_lcsts aeabi_sighandlers aeabi_math
+aeabi_routines = aeabi_assert aeabi_localeconv aeabi_errno_addr \
+ aeabi_mb_cur_max aeabi_atexit aeabi_memclr aeabi_memcpy \
+ aeabi_memmove aeabi_memset
+
+sysdep_routines += $(aeabi_constants) $(aeabi_routines)
+static-only-routines += $(aeabi_constants)
+endif
+
+# to pull in __aeabi_read_tp, needed for tls
+ifeq ($(subdir),malloc)
+$(objpfx)libmemusage.so: $(common-objpfx)libc_nonshared.a
+endif
+
+ifeq ($(subdir),gmon)
+sysdep_routines += arm-mcount
+endif
+
+ifeq ($(subdir),debug)
+CFLAGS-backtrace.c += -funwind-tables
+endif
+
+ifeq ($(subdir),math)
+$(objpfx)libm.so: $(elfobjdir)/ld.so
+endif
diff --git a/ports/sysdeps/arm/Versions b/ports/sysdeps/arm/Versions
new file mode 100644
index 0000000000..5f2af29c38
--- /dev/null
+++ b/ports/sysdeps/arm/Versions
@@ -0,0 +1,20 @@
+libc {
+ GLIBC_2.4 {
+ # ARM EABI compatibility routines
+ __aeabi_assert;
+ __aeabi_atexit;
+ __aeabi_errno_addr;
+ __aeabi_localeconv;
+ __aeabi_MB_CUR_MAX;
+ __aeabi_memclr; __aeabi_memclr4; __aeabi_memclr8;
+ __aeabi_memcpy; __aeabi_memcpy4; __aeabi_memcpy8;
+ __aeabi_memmove; __aeabi_memmove4; __aeabi_memmove8;
+ __aeabi_memset; __aeabi_memset4; __aeabi_memset8;
+
+ # Helper routines
+ __gnu_Unwind_Find_exidx;
+ }
+ GLIBC_2.8 {
+ __gnu_mcount_nc;
+ }
+}
diff --git a/ports/sysdeps/arm/__longjmp.S b/ports/sysdeps/arm/__longjmp.S
new file mode 100644
index 0000000000..cc802c15bd
--- /dev/null
+++ b/ports/sysdeps/arm/__longjmp.S
@@ -0,0 +1,111 @@
+/* longjmp for ARM.
+ Copyright (C) 1997, 1998, 2005, 2006, 2009, 2010
+ Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#define _SETJMP_H
+#define _ASM
+#include <bits/setjmp.h>
+#include <rtld-global-offsets.h>
+
+/* __longjmp(jmpbuf, val) */
+
+ENTRY (__longjmp)
+ mov ip, r0
+ movs r0, r1 /* get the return value in place */
+ moveq r0, #1 /* can't let setjmp() return zero! */
+
+#ifdef CHECK_SP
+ ldr r4, [ip, #32] /* jmpbuf's sp */
+ cfi_undefined (r4)
+ CHECK_SP (r4)
+#endif
+ LOADREGS(ia, ip!, {v1-v6, sl, fp, sp, lr})
+ cfi_restore (v1)
+ cfi_restore (v2)
+ cfi_restore (v3)
+ cfi_restore (v4)
+ cfi_restore (v5)
+ cfi_restore (v6)
+ cfi_restore (sl)
+ cfi_restore (fp)
+ cfi_restore (sp)
+ cfi_restore (lr)
+
+#ifdef IS_IN_rtld
+ ldr a2, 1f
+ ldr a3, Lrtld_local_ro
+0: add a2, pc, a2
+ add a2, a2, a3
+ ldr a2, [a2, #RTLD_GLOBAL_RO_DL_HWCAP_OFFSET]
+#else
+#ifdef PIC
+ ldr a2, 1f
+ ldr a3, Lrtld_global_ro
+0: add a2, pc, a2
+ ldr a2, [a2, a3]
+ ldr a2, [a2, #RTLD_GLOBAL_RO_DL_HWCAP_OFFSET]
+#else
+ ldr a2, Lhwcap
+ ldr a2, [a2, #0]
+#endif
+#endif
+
+ tst a2, #HWCAP_ARM_VFP
+ beq Lno_vfp
+
+ /* Restore the VFP registers. */
+ /* Following instruction is vldmia ip!, {d8-d15}. */
+ ldc p11, cr8, [r12], #64
+ /* Restore the floating-point status register. */
+ ldr a3, [ip], #4
+ /* Following instruction is fmxr fpscr, a3. */
+ mcr p10, 7, a3, cr1, cr0, 0
+Lno_vfp:
+
+ tst a2, #HWCAP_ARM_IWMMXT
+ beq Lno_iwmmxt
+
+ /* Restore the call-preserved iWMMXt registers. */
+ /* Following instructions are wldrd wr10, [ip], #8 (etc.) */
+ ldcl p1, cr10, [r12], #8
+ ldcl p1, cr11, [r12], #8
+ ldcl p1, cr12, [r12], #8
+ ldcl p1, cr13, [r12], #8
+ ldcl p1, cr14, [r12], #8
+ ldcl p1, cr15, [r12], #8
+Lno_iwmmxt:
+
+ DO_RET(lr)
+
+#ifdef IS_IN_rtld
+1: .long _GLOBAL_OFFSET_TABLE_ - 0b - 8
+Lrtld_local_ro:
+ .long C_SYMBOL_NAME(_rtld_local_ro)(GOTOFF)
+#else
+#ifdef PIC
+1: .long _GLOBAL_OFFSET_TABLE_ - 0b - 8
+Lrtld_global_ro:
+ .long C_SYMBOL_NAME(_rtld_global_ro)(GOT)
+#else
+Lhwcap:
+ .long C_SYMBOL_NAME(_dl_hwcap)
+#endif
+#endif
+
+END (__longjmp)
diff --git a/ports/sysdeps/arm/abi-note.S b/ports/sysdeps/arm/abi-note.S
new file mode 100644
index 0000000000..1060c3d280
--- /dev/null
+++ b/ports/sysdeps/arm/abi-note.S
@@ -0,0 +1,9 @@
+/* Tag_ABI_align8_preserved: This code preserves 8-byte
+ alignment in any callee. */
+ .eabi_attribute 25, 1
+/* Tag_ABI_align8_needed: This code may require 8-byte alignment from
+ the caller. */
+ .eabi_attribute 24, 1
+
+#include <csu/abi-note.S>
+
diff --git a/ports/sysdeps/arm/aeabi_assert.c b/ports/sysdeps/arm/aeabi_assert.c
new file mode 100644
index 0000000000..c8fb188913
--- /dev/null
+++ b/ports/sysdeps/arm/aeabi_assert.c
@@ -0,0 +1,26 @@
+/* Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <assert.h>
+#include <stdlib.h>
+
+void
+__aeabi_assert (const char *assertion, const char *file,
+ unsigned int line)
+{
+ __assert_fail (assertion, file, line, NULL);
+}
diff --git a/ports/sysdeps/arm/aeabi_atexit.c b/ports/sysdeps/arm/aeabi_atexit.c
new file mode 100644
index 0000000000..5427fae961
--- /dev/null
+++ b/ports/sysdeps/arm/aeabi_atexit.c
@@ -0,0 +1,27 @@
+/* Copyright (C) 2005 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <stdlib.h>
+
+/* Register a function to be called by exit or when a shared library
+ is unloaded. This routine is like __cxa_atexit, but uses the
+ calling sequence required by the ARM EABI. */
+int
+__aeabi_atexit (void *arg, void (*func) (void *), void *d)
+{
+ return __cxa_atexit (func, arg, d);
+}
diff --git a/ports/sysdeps/arm/aeabi_errno_addr.c b/ports/sysdeps/arm/aeabi_errno_addr.c
new file mode 100644
index 0000000000..b9ee3a5fdd
--- /dev/null
+++ b/ports/sysdeps/arm/aeabi_errno_addr.c
@@ -0,0 +1,24 @@
+/* Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+
+volatile int *
+__aeabi_errno_addr (void)
+{
+ return &errno;
+}
diff --git a/ports/sysdeps/arm/aeabi_lcsts.c b/ports/sysdeps/arm/aeabi_lcsts.c
new file mode 100644
index 0000000000..c53800d6c6
--- /dev/null
+++ b/ports/sysdeps/arm/aeabi_lcsts.c
@@ -0,0 +1,98 @@
+/* Link-time constants for ARM EABI.
+ Copyright (C) 2005 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ 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/>. */
+
+/* The ARM EABI requires that we provide ISO compile-time constants as
+ link-time constants. Some portable applications may reference these. */
+
+#include <errno.h>
+#include <limits.h>
+#include <locale.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <stdio.h>
+#include <time.h>
+
+#define eabi_constant2(X,Y) const int __aeabi_##X attribute_hidden = Y
+#define eabi_constant(X) const int __aeabi_##X attribute_hidden = X
+
+eabi_constant (EDOM);
+eabi_constant (ERANGE);
+eabi_constant (EILSEQ);
+
+eabi_constant (MB_LEN_MAX);
+
+eabi_constant (LC_COLLATE);
+eabi_constant (LC_CTYPE);
+eabi_constant (LC_MONETARY);
+eabi_constant (LC_NUMERIC);
+eabi_constant (LC_TIME);
+eabi_constant (LC_ALL);
+
+/* The value of __aeabi_JMP_BUF_SIZE is the number of doublewords in a
+ jmp_buf. */
+eabi_constant2 (JMP_BUF_SIZE, sizeof (jmp_buf) / 8);
+
+eabi_constant (SIGABRT);
+eabi_constant (SIGFPE);
+eabi_constant (SIGILL);
+eabi_constant (SIGINT);
+eabi_constant (SIGSEGV);
+eabi_constant (SIGTERM);
+
+eabi_constant2 (IOFBF, _IOFBF);
+eabi_constant2 (IOLBF, _IOLBF);
+eabi_constant2 (IONBF, _IONBF);
+eabi_constant (BUFSIZ);
+eabi_constant (FOPEN_MAX);
+eabi_constant (TMP_MAX);
+eabi_constant (FILENAME_MAX);
+eabi_constant (L_tmpnam);
+
+FILE *__aeabi_stdin attribute_hidden;
+FILE *__aeabi_stdout attribute_hidden;
+FILE *__aeabi_stderr attribute_hidden;
+
+static void __attribute__ ((used))
+setup_aeabi_stdio (void)
+{
+ __aeabi_stdin = stdin;
+ __aeabi_stdout = stdout;
+ __aeabi_stderr = stderr;
+}
+
+static void (*fp) (void) __attribute__ ((used, section (".preinit_array")))
+ = setup_aeabi_stdio;
+
+eabi_constant (CLOCKS_PER_SEC);
diff --git a/ports/sysdeps/arm/aeabi_localeconv.c b/ports/sysdeps/arm/aeabi_localeconv.c
new file mode 100644
index 0000000000..233dc62049
--- /dev/null
+++ b/ports/sysdeps/arm/aeabi_localeconv.c
@@ -0,0 +1,24 @@
+/* Copyright (C) 2004, 2005, 2008 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <locale.h>
+
+struct lconv *
+__aeabi_localeconv (void)
+{
+ return __localeconv ();
+}
diff --git a/ports/sysdeps/arm/aeabi_math.c b/ports/sysdeps/arm/aeabi_math.c
new file mode 100644
index 0000000000..d7bcd56714
--- /dev/null
+++ b/ports/sysdeps/arm/aeabi_math.c
@@ -0,0 +1,41 @@
+/* Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ 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/>. */
+
+#include <math.h>
+
+const double __aeabi_HUGE_VAL attribute_hidden = HUGE_VAL;
+const long double __aeabi_HUGE_VALL attribute_hidden = HUGE_VALL;
+const float __aeabi_HUGE_VALF attribute_hidden = HUGE_VALF;
+const float __aeabi_INFINITY attribute_hidden = INFINITY;
+const float __aeabi_NAN attribute_hidden = NAN;
diff --git a/ports/sysdeps/arm/aeabi_mb_cur_max.c b/ports/sysdeps/arm/aeabi_mb_cur_max.c
new file mode 100644
index 0000000000..3c03a9ae3a
--- /dev/null
+++ b/ports/sysdeps/arm/aeabi_mb_cur_max.c
@@ -0,0 +1,27 @@
+/* Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <langinfo.h>
+#include <locale.h>
+#include <stdlib.h>
+#include <locale/localeinfo.h>
+
+int
+__aeabi_MB_CUR_MAX (void)
+{
+ return MB_CUR_MAX;
+}
diff --git a/ports/sysdeps/arm/aeabi_memclr.c b/ports/sysdeps/arm/aeabi_memclr.c
new file mode 100644
index 0000000000..e2974520e5
--- /dev/null
+++ b/ports/sysdeps/arm/aeabi_memclr.c
@@ -0,0 +1,30 @@
+/* Copyright (C) 2005 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <string.h>
+
+/* Clear memory. Can't alias to bzero because it's not defined in the
+ same translation unit. */
+void
+__aeabi_memclr (void *dest, size_t n)
+{
+ __bzero (dest, n);
+}
+
+/* Versions of the above which may assume memory alignment. */
+strong_alias (__aeabi_memclr, __aeabi_memclr4)
+strong_alias (__aeabi_memclr, __aeabi_memclr8)
diff --git a/ports/sysdeps/arm/aeabi_memcpy.c b/ports/sysdeps/arm/aeabi_memcpy.c
new file mode 100644
index 0000000000..403a7ef525
--- /dev/null
+++ b/ports/sysdeps/arm/aeabi_memcpy.c
@@ -0,0 +1,31 @@
+/* Copyright (C) 2005 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <string.h>
+
+/* Copy memory like memcpy, but no return value required. Can't alias
+ to memcpy because it's not defined in the same translation
+ unit. */
+void
+__aeabi_memcpy (void *dest, const void *src, size_t n)
+{
+ memcpy (dest, src, n);
+}
+
+/* Versions of the above which may assume memory alignment. */
+strong_alias (__aeabi_memcpy, __aeabi_memcpy4)
+strong_alias (__aeabi_memcpy, __aeabi_memcpy8)
diff --git a/ports/sysdeps/arm/aeabi_memmove.c b/ports/sysdeps/arm/aeabi_memmove.c
new file mode 100644
index 0000000000..e824946a79
--- /dev/null
+++ b/ports/sysdeps/arm/aeabi_memmove.c
@@ -0,0 +1,31 @@
+/* Copyright (C) 2005 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <string.h>
+
+/* Copy memory like memmove, but no return value required. Can't
+ alias to memmove because it's not defined in the same translation
+ unit. */
+void
+__aeabi_memmove (void *dest, const void *src, size_t n)
+{
+ memmove (dest, src, n);
+}
+
+/* Versions of the above which may assume memory alignment. */
+strong_alias (__aeabi_memmove, __aeabi_memmove4)
+strong_alias (__aeabi_memmove, __aeabi_memmove8)
diff --git a/ports/sysdeps/arm/aeabi_memset.c b/ports/sysdeps/arm/aeabi_memset.c
new file mode 100644
index 0000000000..b7775f9196
--- /dev/null
+++ b/ports/sysdeps/arm/aeabi_memset.c
@@ -0,0 +1,30 @@
+/* Copyright (C) 2005 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <string.h>
+
+/* Set memory like memset, but different argument order and no return
+ value required. */
+void
+__aeabi_memset (void *dest, size_t n, int c)
+{
+ memset (dest, c, n);
+}
+
+/* Versions of the above which may assume memory alignment. */
+strong_alias (__aeabi_memset, __aeabi_memset4)
+strong_alias (__aeabi_memset, __aeabi_memset8)
diff --git a/ports/sysdeps/arm/aeabi_sighandlers.S b/ports/sysdeps/arm/aeabi_sighandlers.S
new file mode 100644
index 0000000000..082039e9cd
--- /dev/null
+++ b/ports/sysdeps/arm/aeabi_sighandlers.S
@@ -0,0 +1,53 @@
+/* Link-time constants for ARM EABI - signal handlers.
+ Copyright (C) 2005 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ 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/>. */
+
+/* The ARM EABI defines these as "functions". */
+
+#include <sysdep.h>
+
+ .global __aeabi_SIG_DFL
+ .hidden __aeabi_SIG_DFL
+ .type __aeabi_SIG_DFL, %function
+ .set __aeabi_SIG_DFL, 0
+
+ .global __aeabi_SIG_IGN
+ .hidden __aeabi_SIG_IGN
+ .type __aeabi_SIG_IGN, %function
+ .set __aeabi_SIG_IGN, 1
+
+ .global __aeabi_SIG_ERR
+ .hidden __aeabi_SIG_ERR
+ .type __aeabi_SIG_ERR, %function
+ .set __aeabi_SIG_ERR, -1
diff --git a/ports/sysdeps/arm/aeabi_unwind_cpp_pr1.c b/ports/sysdeps/arm/aeabi_unwind_cpp_pr1.c
new file mode 100644
index 0000000000..5dbbd9b0a1
--- /dev/null
+++ b/ports/sysdeps/arm/aeabi_unwind_cpp_pr1.c
@@ -0,0 +1,51 @@
+/* Copyright (C) 2005 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+/* Because some objects in ld.so and libc.so are built with
+ -fexceptions, we end up with references to this personality
+ routine. However, these libraries are not linked against
+ libgcc_eh.a, so we need a dummy definition. This routine will
+ never actually be called. */
+
+#include <stdlib.h>
+
+attribute_hidden
+void
+__aeabi_unwind_cpp_pr0 (void)
+{
+#ifndef IS_IN_rtld
+ abort ();
+#endif
+}
+
+attribute_hidden
+void
+__aeabi_unwind_cpp_pr1 (void)
+{
+#ifndef IS_IN_rtld
+ abort ();
+#endif
+}
+
+attribute_hidden
+void
+__aeabi_unwind_cpp_pr2 (void)
+{
+#ifndef IS_IN_rtld
+ abort ();
+#endif
+}
diff --git a/ports/sysdeps/arm/arm-mcount.S b/ports/sysdeps/arm/arm-mcount.S
new file mode 100644
index 0000000000..5ee66bea02
--- /dev/null
+++ b/ports/sysdeps/arm/arm-mcount.S
@@ -0,0 +1,108 @@
+/* Implementation of profiling support. ARM EABI version.
+ Copyright (C) 2008, 2009, 2010 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/>. */
+
+/* Don't call mcount when calling mcount... */
+#undef PROF
+
+#include <sysdep.h>
+
+
+#ifdef __thumb2__
+ .thumb
+ .syntax unified
+#endif
+
+
+/* Use an assembly stub with a special ABI. The calling lr has been
+ pushed to the stack (which will be misaligned). We should preserve
+ all registers except ip and pop a word off the stack.
+
+ NOTE: This assumes mcount_internal does not clobber any non-core
+ (coprocessor) registers. Currently this is true, but may require
+ additional attention in the future.
+
+ The calling sequence looks something like:
+func:
+ push {lr}
+ bl __gnu_mount_nc
+ <function body>
+*/
+
+ENTRY(__gnu_mcount_nc)
+ push {r0, r1, r2, r3, lr}
+ cfi_adjust_cfa_offset (20)
+ cfi_rel_offset (r0, 0)
+ cfi_rel_offset (r1, 4)
+ cfi_rel_offset (r2, 8)
+ cfi_rel_offset (r3, 12)
+ cfi_rel_offset (lr, 16)
+ bic r1, lr, #1
+ ldr r0, [sp, #20]
+ bl __mcount_internal
+ pop {r0, r1, r2, r3, ip, lr}
+ cfi_adjust_cfa_offset (-24)
+ cfi_restore (r0)
+ cfi_restore (r1)
+ cfi_restore (r2)
+ cfi_restore (r3)
+ cfi_register (lr, ip)
+ bx ip
+END(__gnu_mcount_nc)
+
+
+/* Provide old mcount for backwards compatibility. This requires
+ code be compiled with APCS frame pointers. */
+
+ENTRY(_mcount)
+ stmdb sp!, {r0, r1, r2, r3, fp, lr}
+ cfi_adjust_cfa_offset (24)
+ cfi_rel_offset (r0, 0)
+ cfi_rel_offset (r1, 4)
+ cfi_rel_offset (r2, 8)
+ cfi_rel_offset (r3, 12)
+ cfi_rel_offset (fp, 16)
+ cfi_rel_offset (lr, 20)
+#ifdef __thumb2__
+ movs r0, fp
+ ittt ne
+ ldrne r0, [r0, #-4]
+#else
+ movs fp, fp
+ ldrne r0, [fp, #-4]
+#endif
+ movnes r1, lr
+ blne __mcount_internal
+#ifdef __thumb2__
+ ldmia sp!, {r0, r1, r2, r3, fp, pc}
+#else
+ ldmia sp!, {r0, r1, r2, r3, fp, lr}
+ cfi_adjust_cfa_offset (-24)
+ cfi_restore (r0)
+ cfi_restore (r1)
+ cfi_restore (r2)
+ cfi_restore (r3)
+ cfi_restore (fp)
+ cfi_restore (lr)
+ bx lr
+#endif
+END(_mcount)
+
+/* The canonical name for the function is `_mcount' in both C and asm,
+ but some old asm code might assume it's `mcount'. */
+#undef mcount
+weak_alias (_mcount, mcount)
diff --git a/ports/sysdeps/arm/armv6t2/memchr.S b/ports/sysdeps/arm/armv6t2/memchr.S
new file mode 100644
index 0000000000..69ea320e89
--- /dev/null
+++ b/ports/sysdeps/arm/armv6t2/memchr.S
@@ -0,0 +1,163 @@
+/* Copyright (C) 2011 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Code contributed by Dave Gilbert <david.gilbert@linaro.org>
+
+ 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>
+
+@ This memchr routine is optimised on a Cortex-A9 and should work on all ARMv7
+@ and ARMv6T2 processors. It has a fast path for short sizes, and has an
+@ optimised path for large data sets; the worst case is finding the match early
+@ in a large data set.
+@ Note: The use of cbz/cbnz means it's Thumb only
+
+@ 2011-07-15 david.gilbert@linaro.org
+@ Copy from Cortex strings release 21 and change license
+@ http://bazaar.launchpad.net/~linaro-toolchain-dev/cortex-strings/trunk/view/head:/src/linaro-a9/memchr.S
+@ Change function declarations/entry/exit
+@ 2011-12-01 david.gilbert@linaro.org
+@ Add some fixes from comments received (including use of ldrd instead ldm)
+@ 2011-12-07 david.gilbert@linaro.org
+@ Removed cbz from align loop - can't be taken
+
+@ this lets us check a flag in a 00/ff byte easily in either endianness
+#ifdef __ARMEB__
+#define CHARTSTMASK(c) 1<<(31-(c*8))
+#else
+#define CHARTSTMASK(c) 1<<(c*8)
+#endif
+ .syntax unified
+
+ .text
+ .thumb
+
+@ ---------------------------------------------------------------------------
+ .thumb_func
+ .global memchr
+ .type memchr,%function
+ENTRY(memchr)
+ @ r0 = start of memory to scan
+ @ r1 = character to look for
+ @ r2 = length
+ @ returns r0 = pointer to character or NULL if not found
+ and r1,r1,#0xff @ Don't think we can trust the caller to actually pass a char
+
+ cmp r2,#16 @ If it's short don't bother with anything clever
+ blt 20f
+
+ tst r0, #7 @ If it's already aligned skip the next bit
+ beq 10f
+
+ @ Work up to an aligned point
+5:
+ ldrb r3, [r0],#1
+ subs r2, r2, #1
+ cmp r3, r1
+ beq 50f @ If it matches exit found
+ tst r0, #7
+ bne 5b @ If not aligned yet then do next byte
+
+10:
+ @ At this point, we are aligned, we know we have at least 8 bytes to work with
+ push {r4,r5,r6,r7}
+ cfi_adjust_cfa_offset (16)
+ cfi_rel_offset (r4, 0)
+ cfi_rel_offset (r5, 4)
+ cfi_rel_offset (r6, 8)
+ cfi_rel_offset (r7, 12)
+
+ cfi_remember_state
+
+ orr r1, r1, r1, lsl #8 @ expand the match word across to all bytes
+ orr r1, r1, r1, lsl #16
+ bic r4, r2, #7 @ Number of double words to work with * 8
+ mvns r7, #0 @ all F's
+ movs r3, #0
+
+15:
+ ldrd r5,r6, [r0],#8
+ subs r4, r4, #8
+ eor r5,r5, r1 @ Get it so that r5,r6 have 00's where the bytes match the target
+ eor r6,r6, r1
+ uadd8 r5, r5, r7 @ Parallel add 0xff - sets the GE bits for anything that wasn't 0
+ sel r5, r3, r7 @ bytes are 00 for none-00 bytes, or ff for 00 bytes - NOTE INVERSION
+ uadd8 r6, r6, r7 @ Parallel add 0xff - sets the GE bits for anything that wasn't 0
+ sel r6, r5, r7 @ chained....bytes are 00 for none-00 bytes, or ff for 00 bytes - NOTE INVERSION
+ cbnz r6, 60f
+ bne 15b @ (Flags from the subs above) If not run out of bytes then go around again
+
+ pop {r4,r5,r6,r7}
+ cfi_adjust_cfa_offset (-16)
+ cfi_restore (r4)
+ cfi_restore (r5)
+ cfi_restore (r6)
+ cfi_restore (r7)
+
+ and r1,r1,#0xff @ Get r1 back to a single character from the expansion above
+ and r2,r2,#7 @ Leave the count remaining as the number after the double words have been done
+
+20:
+ cbz r2, 40f @ 0 length or hit the end already then not found
+
+21: @ Post aligned section, or just a short call
+ ldrb r3,[r0],#1
+ subs r2,r2,#1
+ eor r3,r3,r1 @ r3 = 0 if match - doesn't break flags from sub
+ cbz r3, 50f
+ bne 21b @ on r2 flags
+
+40:
+ movs r0,#0 @ not found
+ DO_RET(lr)
+
+50:
+ subs r0,r0,#1 @ found
+ DO_RET(lr)
+
+60: @ We're here because the fast path found a hit - now we have to track down exactly which word it was
+ @ r0 points to the start of the double word after the one that was tested
+ @ r5 has the 00/ff pattern for the first word, r6 has the chained value
+ cfi_restore_state
+ cmp r5, #0
+ itte eq
+ moveq r5, r6 @ the end is in the 2nd word
+ subeq r0,r0,#3 @ Points to 2nd byte of 2nd word
+ subne r0,r0,#7 @ or 2nd byte of 1st word
+
+ @ r0 currently points to the 2nd byte of the word containing the hit
+ tst r5, # CHARTSTMASK(0) @ 1st character
+ bne 61f
+ adds r0,r0,#1
+ tst r5, # CHARTSTMASK(1) @ 2nd character
+ ittt eq
+ addeq r0,r0,#1
+ tsteq r5, # (3<<15) @ 2nd & 3rd character
+ @ If not the 3rd must be the last one
+ addeq r0,r0,#1
+
+61:
+ pop {r4,r5,r6,r7}
+ cfi_adjust_cfa_offset (-16)
+ cfi_restore (r4)
+ cfi_restore (r5)
+ cfi_restore (r6)
+ cfi_restore (r7)
+
+ subs r0,r0,#1
+ DO_RET(lr)
+
+END(memchr)
+libc_hidden_builtin_def (memchr)
diff --git a/ports/sysdeps/arm/armv7/Implies b/ports/sysdeps/arm/armv7/Implies
new file mode 100644
index 0000000000..c6cd0eb877
--- /dev/null
+++ b/ports/sysdeps/arm/armv7/Implies
@@ -0,0 +1,2 @@
+# We can do everything that 6T2 can
+arm/armv6t2
diff --git a/ports/sysdeps/arm/backtrace.c b/ports/sysdeps/arm/backtrace.c
new file mode 100644
index 0000000000..3d839e628c
--- /dev/null
+++ b/ports/sysdeps/arm/backtrace.c
@@ -0,0 +1,125 @@
+/* Return backtrace of current program state.
+ Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Kazu Hirata <kazu@codesourcery.com>, 2008.
+
+ 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 <bits/libc-lock.h>
+#include <dlfcn.h>
+#include <execinfo.h>
+#include <stdlib.h>
+#include <unwind.h>
+
+struct trace_arg
+{
+ void **array;
+ int cnt, size;
+};
+
+#ifdef SHARED
+static _Unwind_Reason_Code (*unwind_backtrace) (_Unwind_Trace_Fn, void *);
+static _Unwind_VRS_Result (*unwind_vrs_get) (_Unwind_Context *,
+ _Unwind_VRS_RegClass,
+ _uw,
+ _Unwind_VRS_DataRepresentation,
+ void *);
+
+static void *libgcc_handle;
+
+static void
+init (void)
+{
+ libgcc_handle = __libc_dlopen ("libgcc_s.so.1");
+
+ if (libgcc_handle == NULL)
+ return;
+
+ unwind_backtrace = __libc_dlsym (libgcc_handle, "_Unwind_Backtrace");
+ unwind_vrs_get = __libc_dlsym (libgcc_handle, "_Unwind_VRS_Get");
+ if (unwind_vrs_get == NULL)
+ unwind_backtrace = NULL;
+}
+
+/* This function is identical to "_Unwind_GetGR", except that it uses
+ "unwind_vrs_get" instead of "_Unwind_VRS_Get". */
+static inline _Unwind_Word
+unwind_getgr (_Unwind_Context *context, int regno)
+{
+ _uw val;
+ unwind_vrs_get (context, _UVRSC_CORE, regno, _UVRSD_UINT32, &val);
+ return val;
+}
+
+/* This macro is identical to the _Unwind_GetIP macro, except that it
+ uses "unwind_getgr" instead of "_Unwind_GetGR". */
+# define unwind_getip(context) \
+ (unwind_getgr (context, 15) & ~(_Unwind_Word)1)
+#else
+# define unwind_backtrace _Unwind_Backtrace
+# define unwind_getip _Unwind_GetIP
+#endif
+
+static _Unwind_Reason_Code
+backtrace_helper (struct _Unwind_Context *ctx, void *a)
+{
+ struct trace_arg *arg = a;
+
+ /* We are first called with address in the __backtrace function.
+ Skip it. */
+ if (arg->cnt != -1)
+ arg->array[arg->cnt] = (void *) unwind_getip (ctx);
+ if (++arg->cnt == arg->size)
+ return _URC_END_OF_STACK;
+ return _URC_NO_REASON;
+}
+
+int
+__backtrace (array, size)
+ void **array;
+ int size;
+{
+ struct trace_arg arg = { .array = array, .size = size, .cnt = -1 };
+#ifdef SHARED
+ __libc_once_define (static, once);
+
+ __libc_once (once, init);
+ if (unwind_backtrace == NULL)
+ return 0;
+#endif
+
+ if (size >= 1)
+ unwind_backtrace (backtrace_helper, &arg);
+
+ if (arg.cnt > 1 && arg.array[arg.cnt - 1] == NULL)
+ --arg.cnt;
+ return arg.cnt != -1 ? arg.cnt : 0;
+}
+weak_alias (__backtrace, backtrace)
+libc_hidden_def (__backtrace)
+
+
+#ifdef SHARED
+/* Free all resources if necessary. */
+libc_freeres_fn (free_mem)
+{
+ unwind_backtrace = NULL;
+ if (libgcc_handle != NULL)
+ {
+ __libc_dlclose (libgcc_handle);
+ libgcc_handle = NULL;
+ }
+}
+#endif
diff --git a/ports/sysdeps/arm/bits/endian.h b/ports/sysdeps/arm/bits/endian.h
new file mode 100644
index 0000000000..f49f6ab1c9
--- /dev/null
+++ b/ports/sysdeps/arm/bits/endian.h
@@ -0,0 +1,10 @@
+#ifndef _ENDIAN_H
+# error "Never use <bits/endian.h> directly; include <endian.h> instead."
+#endif
+
+/* ARM can be either big or little endian. */
+#ifdef __ARMEB__
+#define __BYTE_ORDER __BIG_ENDIAN
+#else
+#define __BYTE_ORDER __LITTLE_ENDIAN
+#endif
diff --git a/ports/sysdeps/arm/bits/fenv.h b/ports/sysdeps/arm/bits/fenv.h
new file mode 100644
index 0000000000..006ccf5288
--- /dev/null
+++ b/ports/sysdeps/arm/bits/fenv.h
@@ -0,0 +1,73 @@
+/* Copyright (C) 2004, 2005, 2012 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _FENV_H
+# error "Never use <bits/fenv.h> directly; include <fenv.h> instead."
+#endif
+
+/* Define bits representing exceptions in the FPU status word. */
+enum
+ {
+ FE_INVALID = 1,
+#define FE_INVALID FE_INVALID
+ FE_DIVBYZERO = 2,
+#define FE_DIVBYZERO FE_DIVBYZERO
+ FE_OVERFLOW = 4,
+#define FE_OVERFLOW FE_OVERFLOW
+ FE_UNDERFLOW = 8,
+#define FE_UNDERFLOW FE_UNDERFLOW
+ FE_INEXACT = 16,
+#define FE_INEXACT FE_INEXACT
+ };
+
+/* Amount to shift by to convert an exception to a mask bit. */
+#define FE_EXCEPT_SHIFT 8
+
+/* All supported exceptions. */
+#define FE_ALL_EXCEPT \
+ (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT)
+
+/* VFP supports all of the four defined rounding modes. */
+enum
+ {
+ FE_TONEAREST = 0,
+#define FE_TONEAREST FE_TONEAREST
+ FE_UPWARD = 0x400000,
+#define FE_UPWARD FE_UPWARD
+ FE_DOWNWARD = 0x800000,
+#define FE_DOWNWARD FE_DOWNWARD
+ FE_TOWARDZERO = 0xc00000
+#define FE_TOWARDZERO FE_TOWARDZERO
+ };
+
+/* Type representing exception flags. */
+typedef unsigned int fexcept_t;
+
+/* Type representing floating-point environment. */
+typedef struct
+ {
+ unsigned int __cw;
+ }
+fenv_t;
+
+/* If the default argument is used we use this value. */
+#define FE_DFL_ENV ((fenv_t *) -1l)
+
+#ifdef __USE_GNU
+/* Floating-point environment where none of the exceptions are masked. */
+# define FE_NOMASK_ENV ((const fenv_t *) -2)
+#endif
diff --git a/ports/sysdeps/arm/bits/link.h b/ports/sysdeps/arm/bits/link.h
new file mode 100644
index 0000000000..37b94c509f
--- /dev/null
+++ b/ports/sysdeps/arm/bits/link.h
@@ -0,0 +1,65 @@
+/* Copyright (C) 2005, 2009 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _LINK_H
+# error "Never include <bits/link.h> directly; use <link.h> instead."
+#endif
+
+
+/* Registers for entry into PLT on ARM. */
+typedef struct La_arm_regs
+{
+ uint32_t lr_reg[4];
+ uint32_t lr_sp;
+ uint32_t lr_lr;
+ /* Coprocessor registers used for argument passing. The data
+ stored here depends on the coprocessors available in the
+ system which are used for function calls in the current ABI.
+ VFP uses eight 64-bit registers, and iWMMXt uses ten. */
+ uint32_t lr_coproc[42];
+} La_arm_regs;
+
+/* Return values for calls from PLT on ARM. */
+typedef struct La_arm_retval
+{
+ /* Up to four integer registers can be used for a return value in
+ some ABIs (APCS complex long double). */
+ uint32_t lrv_reg[4];
+
+ /* Any coprocessor registers which might be used to return values
+ in the current ABI. */
+ uint32_t lrv_coproc[12];
+} La_arm_retval;
+
+
+__BEGIN_DECLS
+
+extern Elf32_Addr la_arm_gnu_pltenter (Elf32_Sym *__sym, unsigned int __ndx,
+ uintptr_t *__refcook,
+ uintptr_t *__defcook,
+ La_arm_regs *__regs,
+ unsigned int *__flags,
+ const char *__symname,
+ long int *__framesizep);
+extern unsigned int la_arm_gnu_pltexit (Elf32_Sym *__sym, unsigned int __ndx,
+ uintptr_t *__refcook,
+ uintptr_t *__defcook,
+ const La_arm_regs *__inregs,
+ La_arm_retval *__outregs,
+ const char *__symname);
+
+__END_DECLS
diff --git a/ports/sysdeps/arm/bits/linkmap.h b/ports/sysdeps/arm/bits/linkmap.h
new file mode 100644
index 0000000000..7c2b4a6da8
--- /dev/null
+++ b/ports/sysdeps/arm/bits/linkmap.h
@@ -0,0 +1,5 @@
+struct link_map_machine
+ {
+ Elf32_Addr plt; /* Address of .plt */
+ void *tlsdesc_table; /* Address of TLS descriptor hash table. */
+ };
diff --git a/ports/sysdeps/arm/bits/mathdef.h b/ports/sysdeps/arm/bits/mathdef.h
new file mode 100644
index 0000000000..37e9226745
--- /dev/null
+++ b/ports/sysdeps/arm/bits/mathdef.h
@@ -0,0 +1,56 @@
+/* Copyright (C) 1999, 2000, 2004, 2006, 2007, 2010
+ Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#if !defined _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
+
+/* GCC does not promote `float' values to `double'. */
+typedef float float_t; /* `float' expressions are evaluated as
+ `float'. */
+typedef double double_t; /* `double' expressions are evaluated as
+ `double'. */
+
+/* The values returned by `ilogb' for 0 and NaN respectively. */
+# define FP_ILOGB0 (-2147483647)
+# define FP_ILOGBNAN (2147483647)
+
+/* 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 */
+
+#ifndef __NO_LONG_DOUBLE_MATH
+/* Signal that we do not really have a `long double'. This disables the
+ declaration of all the `long double' function variants. */
+# define __NO_LONG_DOUBLE_MATH 1
+#endif
diff --git a/ports/sysdeps/arm/bits/setjmp.h b/ports/sysdeps/arm/bits/setjmp.h
new file mode 100644
index 0000000000..bdc41ce86e
--- /dev/null
+++ b/ports/sysdeps/arm/bits/setjmp.h
@@ -0,0 +1,37 @@
+/* Copyright (C) 2004, 2005, 2006, 2009 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 the machine-dependent type `jmp_buf'. ARM EABI 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
+/* The exact set of registers saved may depend on the particular core
+ in use, as some coprocessor registers may need to be saved. The C
+ Library ABI requires that the buffer be 8-byte aligned, and
+ recommends that the buffer contain 64 words. The first 28 words
+ are occupied by v1-v6, sl, fp, sp, pc, d8-d15, and fpscr. (Note
+ that d8-15 require 17 words, due to the use of fstmx.) */
+typedef int __jmp_buf[64] __attribute__((__aligned__ (8)));
+#endif
+
+#endif
diff --git a/ports/sysdeps/arm/bsd-_setjmp.S b/ports/sysdeps/arm/bsd-_setjmp.S
new file mode 100644
index 0000000000..d27ef94425
--- /dev/null
+++ b/ports/sysdeps/arm/bsd-_setjmp.S
@@ -0,0 +1,29 @@
+/* BSD `_setjmp' entry point to `sigsetjmp (..., 0)'. ARM version.
+ Copyright (C) 1997, 1998, 2002, 2008 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/>. */
+
+/* This just does a tail-call to `__sigsetjmp (ARG, 1)'.
+ We cannot do it in C because it must be a tail-call, so frame-unwinding
+ in setjmp doesn't clobber the state restored by longjmp. */
+
+#include <sysdep.h>
+
+ENTRY (_setjmp)
+ mov r1, #0
+ b PLTJMP(HIDDEN_JUMPTARGET(__sigsetjmp))
+END (_setjmp)
+libc_hidden_def (_setjmp)
diff --git a/ports/sysdeps/arm/bsd-setjmp.S b/ports/sysdeps/arm/bsd-setjmp.S
new file mode 100644
index 0000000000..bc2097e79a
--- /dev/null
+++ b/ports/sysdeps/arm/bsd-setjmp.S
@@ -0,0 +1,28 @@
+/* BSD `setjmp' entry point to `sigsetjmp (..., 1)'. ARM version.
+ Copyright (C) 1997, 1998, 2008 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/>. */
+
+/* This just does a tail-call to `__sigsetjmp (ARG, 1)'.
+ We cannot do it in C because it must be a tail-call, so frame-unwinding
+ in setjmp doesn't clobber the state restored by longjmp. */
+
+#include <sysdep.h>
+
+ENTRY (setjmp)
+ mov r1, #1
+ b PLTJMP(HIDDEN_JUMPTARGET(__sigsetjmp))
+END (setjmp)
diff --git a/ports/sysdeps/arm/configure b/ports/sysdeps/arm/configure
new file mode 100755
index 0000000000..665151fead
--- /dev/null
+++ b/ports/sysdeps/arm/configure
@@ -0,0 +1,335 @@
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+
+ as_lineno_1=$LINENO as_lineno_1a=$LINENO
+ as_lineno_2=$LINENO as_lineno_2a=$LINENO
+ eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+ test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
+ # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
+ sed '
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
+ N
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+ t loop
+ s/-\n.*//
+ ' >$as_me.lineno &&
+ chmod +x "$as_me.lineno" ||
+ { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
+ # Exit status is that of the last command.
+ exit
+}
+
+# This file is generated from configure.in by Autoconf. DO NOT EDIT!
+ # Local configure fragment for sysdeps/arm.
+
+# Check for support of thread-local storage handling in assembler and
+# linker.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ARM TLS support" >&5
+$as_echo_n "checking for ARM TLS support... " >&6; }
+if ${libc_cv_arm_tls+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat > conftest.s <<\EOF
+ .section ".tdata", "awT", %progbits
+ .globl foo
+foo: .long 1
+ .section ".tbss", "awT", %nobits
+ .globl bar
+bar: .skip 4
+ .text
+.word foo(tpoff)
+.word foo(tlsgd)
+EOF
+if { ac_try='${CC-cc} -c $CFLAGS conftest.s 1>&5'
+ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }; then
+ libc_cv_arm_tls=yes
+else
+ libc_cv_arm_tls=no
+fi
+rm -f conftest*
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_arm_tls" >&5
+$as_echo "$libc_cv_arm_tls" >&6; }
+if test $libc_cv_arm_tls = no; then
+ as_fn_error $? "the assembler must support TLS" "$LINENO" 5
+fi
+
+#AC_DEFINE(PI_STATIC_AND_HIDDEN)
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the CFI directive .cfi_sections is supported" >&5
+$as_echo_n "checking whether the CFI directive .cfi_sections is supported... " >&6; }
+if ${libc_cv_asm_cfi_directive_sections+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat > conftest.s <<EOF
+ .text
+ .cfi_sections .debug_frame, .eh_frame
+ .cfi_startproc
+ .cfi_endproc
+EOF
+ if { ac_try='${CC-cc} $ASFLAGS -c conftest.s 1>&5'
+ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }; then
+ libc_cv_asm_cfi_directive_sections=yes
+ else
+ libc_cv_asm_cfi_directive_sections=no
+ fi
+ rm -f conftest*
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_asm_cfi_directive_sections" >&5
+$as_echo "$libc_cv_asm_cfi_directive_sections" >&6; }
+if test $libc_cv_asm_cfi_directive_sections != yes; then
+ as_fn_error $? "need .cfi_sections in this configuration" "$LINENO" 5
+fi
+
+# We check to see if the compiler and flags are
+# selecting the hard-float ABI and if they are then
+# we set libc_cv_arm_pcs_vfp to yes which causes
+# HAVE_ARM_PCS_VFP to be defined in config.h and
+# in include/libc-symbols.h and thus available to
+# shlib-versions to select the appropriate name for
+# the dynamic linker via %ifdef.
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
+$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
+if ${ac_cv_path_GREP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -z "$GREP"; then
+ ac_path_GREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in grep ggrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+ { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue
+# Check for GNU ac_path_GREP and select it if it is found.
+ # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+ ac_count=0
+ $as_echo_n 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ $as_echo 'GREP' >> "conftest.nl"
+ "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_GREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_GREP="$ac_path_GREP"
+ ac_path_GREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_GREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_GREP"; then
+ as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_GREP=$GREP
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
+$as_echo "$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
+$as_echo_n "checking for egrep... " >&6; }
+if ${ac_cv_path_EGREP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+ then ac_cv_path_EGREP="$GREP -E"
+ else
+ if test -z "$EGREP"; then
+ ac_path_EGREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in egrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+ { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue
+# Check for GNU ac_path_EGREP and select it if it is found.
+ # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+ ac_count=0
+ $as_echo_n 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ $as_echo 'EGREP' >> "conftest.nl"
+ "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_EGREP="$ac_path_EGREP"
+ ac_path_EGREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_EGREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_EGREP"; then
+ as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_EGREP=$EGREP
+fi
+
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
+$as_echo "$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler is using the ARM hard-float ABI" >&5
+$as_echo_n "checking whether the compiler is using the ARM hard-float ABI... " >&6; }
+if ${libc_cv_arm_pcs_vfp+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifdef __ARM_PCS_VFP
+ yes
+ #endif
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "yes" >/dev/null 2>&1; then :
+ libc_cv_arm_pcs_vfp=yes
+else
+ libc_cv_arm_pcs_vfp=no
+fi
+rm -f conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_arm_pcs_vfp" >&5
+$as_echo "$libc_cv_arm_pcs_vfp" >&6; }
+if test $libc_cv_arm_pcs_vfp = yes; then
+ $as_echo "#define HAVE_ARM_PCS_VFP 1" >>confdefs.h
+
+fi
diff --git a/ports/sysdeps/arm/configure.in b/ports/sysdeps/arm/configure.in
new file mode 100644
index 0000000000..64cef5f94e
--- /dev/null
+++ b/ports/sysdeps/arm/configure.in
@@ -0,0 +1,68 @@
+GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory.
+# Local configure fragment for sysdeps/arm.
+
+# Check for support of thread-local storage handling in assembler and
+# linker.
+AC_CACHE_CHECK(for ARM TLS support, libc_cv_arm_tls, [dnl
+cat > conftest.s <<\EOF
+ .section ".tdata", "awT", %progbits
+ .globl foo
+foo: .long 1
+ .section ".tbss", "awT", %nobits
+ .globl bar
+bar: .skip 4
+ .text
+.word foo(tpoff)
+.word foo(tlsgd)
+EOF
+dnl
+if AC_TRY_COMMAND(${CC-cc} -c $CFLAGS conftest.s 1>&AS_MESSAGE_LOG_FD); then
+ libc_cv_arm_tls=yes
+else
+ libc_cv_arm_tls=no
+fi
+rm -f conftest*])
+if test $libc_cv_arm_tls = no; then
+ AC_MSG_ERROR([the assembler must support TLS])
+fi
+
+dnl It is always possible to access static and hidden symbols in an
+dnl position independent way.
+dnl NOTE: This feature was added by the GCC TLS patches. We should test for
+dnl it. Until we do, don't define it.
+#AC_DEFINE(PI_STATIC_AND_HIDDEN)
+
+AC_CACHE_CHECK([whether the CFI directive .cfi_sections is supported],
+ [libc_cv_asm_cfi_directive_sections],
+ [cat > conftest.s <<EOF
+ .text
+ .cfi_sections .debug_frame, .eh_frame
+ .cfi_startproc
+ .cfi_endproc
+EOF
+ if AC_TRY_COMMAND(${CC-cc} $ASFLAGS -c conftest.s 1>&AS_MESSAGE_LOG_FD); then
+ libc_cv_asm_cfi_directive_sections=yes
+ else
+ libc_cv_asm_cfi_directive_sections=no
+ fi
+ rm -f conftest*])
+if test $libc_cv_asm_cfi_directive_sections != yes; then
+ AC_MSG_ERROR([need .cfi_sections in this configuration])
+fi
+
+# We check to see if the compiler and flags are
+# selecting the hard-float ABI and if they are then
+# we set libc_cv_arm_pcs_vfp to yes which causes
+# HAVE_ARM_PCS_VFP to be defined in config.h and
+# in include/libc-symbols.h and thus available to
+# shlib-versions to select the appropriate name for
+# the dynamic linker via %ifdef.
+AC_CACHE_CHECK([whether the compiler is using the ARM hard-float ABI],
+ [libc_cv_arm_pcs_vfp],
+ [AC_EGREP_CPP(yes,[#ifdef __ARM_PCS_VFP
+ yes
+ #endif
+ ], libc_cv_arm_pcs_vfp=yes, libc_cv_arm_pcs_vfp=no)])
+if test $libc_cv_arm_pcs_vfp = yes; then
+ AC_DEFINE(HAVE_ARM_PCS_VFP)
+fi
diff --git a/ports/sysdeps/arm/crti.S b/ports/sysdeps/arm/crti.S
new file mode 100644
index 0000000000..a203d6a22c
--- /dev/null
+++ b/ports/sysdeps/arm/crti.S
@@ -0,0 +1,93 @@
+/* Special .init and .fini section support for ARM.
+ Copyright (C) 1995-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
+
+#if PREINIT_FUNCTION_WEAK
+ .p2align 2
+ .type call_weak_fn, %function
+call_weak_fn:
+ ldr r3, .LGOT
+ ldr r2, .LGOT+4
+.LPIC:
+ add r3, pc, r3
+ ldr r2, [r3, r2]
+ cmp r2, #0
+ bxeq lr
+ b PREINIT_FUNCTION
+ .p2align 2
+.LGOT:
+ .word _GLOBAL_OFFSET_TABLE_-(.LPIC+8)
+ .word PREINIT_FUNCTION(GOT)
+#endif
+
+ .section .init,"ax",%progbits
+ .p2align 2
+ .globl _init
+ .type _init, %function
+_init:
+ stmfd sp!, {r3, lr}
+#if PREINIT_FUNCTION_WEAK
+ bl call_weak_fn
+#else
+ bl PREINIT_FUNCTION
+#endif
+
+ .section .fini,"ax",%progbits
+ .p2align 2
+ .globl _fini
+ .type _fini, %function
+_fini:
+ stmfd sp!, {r3, lr}
diff --git a/ports/sysdeps/arm/crtn.S b/ports/sysdeps/arm/crtn.S
new file mode 100644
index 0000000000..28e3153108
--- /dev/null
+++ b/ports/sysdeps/arm/crtn.S
@@ -0,0 +1,55 @@
+/* Special .init and .fini section support for ARM.
+ Copyright (C) 1995-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/>. */
+
+#include <sysdep.h>
+
+/* crtn.S puts function epilogues in the .init and .fini sections
+ corresponding to the prologues in crti.S. */
+
+ .section .init,"ax",%progbits
+#ifdef __ARM_ARCH_4T__
+ ldmfd sp!, {r3, lr}
+ bx lr
+#else
+ ldmfd sp!, {r3, pc}
+#endif
+
+ .section .fini,"ax",%progbits
+#ifdef __ARM_ARCH_4T__
+ ldmfd sp!, {r3, lr}
+ bx lr
+#else
+ ldmfd sp!, {r3, pc}
+#endif
diff --git a/ports/sysdeps/arm/dl-irel.h b/ports/sysdeps/arm/dl-irel.h
new file mode 100644
index 0000000000..5b1964e90e
--- /dev/null
+++ b/ports/sysdeps/arm/dl-irel.h
@@ -0,0 +1,51 @@
+/* Machine-dependent ELF indirect relocation inline functions.
+ ARM version.
+ Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _DL_IREL_H
+#define _DL_IREL_H
+
+#include <stdio.h>
+#include <unistd.h>
+
+#define ELF_MACHINE_IREL 1
+
+static inline Elf32_Addr
+__attribute ((always_inline))
+elf_ifunc_invoke (Elf32_Addr addr)
+{
+ return ((Elf32_Addr (*) (unsigned long int)) (addr)) (GLRO(dl_hwcap));
+}
+
+static inline void
+__attribute ((always_inline))
+elf_irel (const Elf32_Rel *reloc)
+{
+ Elf32_Addr *const reloc_addr = (void *) reloc->r_offset;
+ const unsigned long int r_type = ELF32_R_TYPE (reloc->r_info);
+
+ if (__builtin_expect (r_type == R_ARM_IRELATIVE, 1))
+ {
+ Elf32_Addr value = elf_ifunc_invoke (*reloc_addr);
+ *reloc_addr = value;
+ }
+ else
+ __libc_fatal ("unexpected reloc type in static binary");
+}
+
+#endif /* dl-irel.h */
diff --git a/ports/sysdeps/arm/dl-lookupcfg.h b/ports/sysdeps/arm/dl-lookupcfg.h
new file mode 100644
index 0000000000..bf3acd07c1
--- /dev/null
+++ b/ports/sysdeps/arm/dl-lookupcfg.h
@@ -0,0 +1,27 @@
+/* Configuration of lookup functions.
+ Copyright (C) 2006, 2010 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 DL_UNMAP_IS_SPECIAL
+
+#include_next <dl-lookupcfg.h>
+
+struct link_map;
+
+extern void internal_function _dl_unmap (struct link_map *map);
+
+#define DL_UNMAP(map) _dl_unmap (map)
diff --git a/ports/sysdeps/arm/dl-machine.h b/ports/sysdeps/arm/dl-machine.h
new file mode 100644
index 0000000000..8d905e8ad9
--- /dev/null
+++ b/ports/sysdeps/arm/dl-machine.h
@@ -0,0 +1,694 @@
+/* Machine-dependent ELF dynamic relocation inline functions. ARM version.
+ Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,
+ 2006, 2009, 2010, 2011 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef dl_machine_h
+#define dl_machine_h
+
+#define ELF_MACHINE_NAME "ARM"
+
+#include <sys/param.h>
+#include <tls.h>
+#include <dl-tlsdesc.h>
+#include <dl-irel.h>
+
+#define CLEAR_CACHE(BEG,END) \
+ INTERNAL_SYSCALL_ARM (cacheflush, , 3, (BEG), (END), 0)
+
+/* Return nonzero iff ELF header is compatible with the running host. */
+static inline int __attribute__ ((unused))
+elf_machine_matches_host (const Elf32_Ehdr *ehdr)
+{
+ return ehdr->e_machine == EM_ARM;
+}
+
+
+/* Return the link-time address of _DYNAMIC. Conveniently, this is the
+ first element of the GOT. We used to use the PIC register to do this
+ without a constant pool reference, but GCC 4.2 will use a pseudo-register
+ for the PIC base, so it may not be in r10. */
+static inline Elf32_Addr __attribute__ ((unused))
+elf_machine_dynamic (void)
+{
+ Elf32_Addr dynamic;
+#ifdef __thumb2__
+ long tmp;
+ asm ("ldr\t%0, 1f\n\t"
+ "adr\t%1, 1f\n\t"
+ "ldr\t%0, [%0, %1]\n\t"
+ "b 2f\n"
+ ".align 2\n"
+ "1: .word _GLOBAL_OFFSET_TABLE_ - 1b\n"
+ "2:" : "=r" (dynamic), "=r"(tmp));
+#else
+ asm ("ldr %0, 2f\n"
+ "1: ldr %0, [pc, %0]\n"
+ "b 3f\n"
+ "2: .word _GLOBAL_OFFSET_TABLE_ - (1b+8)\n"
+ "3:" : "=r" (dynamic));
+#endif
+ return dynamic;
+}
+
+
+/* Return the run-time load address of the shared object. */
+static inline Elf32_Addr __attribute__ ((unused))
+elf_machine_load_address (void)
+{
+ extern void __dl_start asm ("_dl_start");
+ Elf32_Addr got_addr = (Elf32_Addr) &__dl_start;
+ Elf32_Addr pcrel_addr;
+#ifdef __thumb__
+ /* Clear the low bit of the funciton address. */
+ got_addr &= ~(Elf32_Addr) 1;
+#endif
+ asm ("adr %0, _dl_start" : "=r" (pcrel_addr));
+ return pcrel_addr - got_addr;
+}
+
+
+/* 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)
+{
+ Elf32_Addr *got;
+ extern void _dl_runtime_resolve (Elf32_Word);
+ extern void _dl_runtime_profile (Elf32_Word);
+
+ if (l->l_info[DT_JMPREL] && lazy)
+ {
+ /* patb: this is different than i386 */
+ /* The GOT entries for functions in the PLT have not yet been filled
+ in. Their initial contents will arrange when called to push an
+ index into the .got section, load ip with &_GLOBAL_OFFSET_TABLE_[3],
+ and then jump to _GLOBAL_OFFSET_TABLE[2]. */
+ got = (Elf32_Addr *) D_PTR (l, l_info[DT_PLTGOT]);
+ /* If a library is prelinked but we have to relocate anyway,
+ we have to be able to undo the prelinking of .got.plt.
+ The prelinker saved us here address of .plt. */
+ if (got[1])
+ l->l_mach.plt = got[1] + l->l_addr;
+ got[1] = (Elf32_Addr) l; /* Identify this shared object. */
+
+ /* The got[2] 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 GOT so that all future calls also
+ end in this function. */
+ if (profile)
+ {
+ got[2] = (Elf32_Addr) &_dl_runtime_profile;
+
+ if (GLRO(dl_profile) != NULL
+ && _dl_name_match_p (GLRO(dl_profile), l))
+ /* 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 GOT entry indicated by
+ the offset on the stack, and then jump to the resolved address. */
+ got[2] = (Elf32_Addr) &_dl_runtime_resolve;
+ }
+
+ if (l->l_info[ADDRIDX (DT_TLSDESC_GOT)] && lazy)
+ *(Elf32_Addr*)(D_PTR (l, l_info[ADDRIDX (DT_TLSDESC_GOT)]) + l->l_addr)
+ = (Elf32_Addr) &_dl_tlsdesc_lazy_resolver;
+
+ return lazy;
+}
+
+#if defined(__USE_BX__)
+#define BX(x) "bx\t" #x
+#else
+#define BX(x) "mov\tpc, " #x
+#endif
+
+/* Mask identifying addresses reserved for the user program,
+ where the dynamic linker should not map anything. */
+#define ELF_MACHINE_USER_ADDRESS_MASK 0xf8000000UL
+
+/* 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 ("\
+.text\n\
+.globl _start\n\
+.type _start, %function\n\
+.globl _dl_start_user\n\
+.type _dl_start_user, %function\n\
+_start:\n\
+ @ we are PIC code, so get global offset table\n\
+ ldr sl, .L_GET_GOT\n\
+ @ See if we were run as a command with the executable file\n\
+ @ name as an extra leading argument.\n\
+ ldr r4, .L_SKIP_ARGS\n\
+ @ at start time, all the args are on the stack\n\
+ mov r0, sp\n\
+ bl _dl_start\n\
+ @ returns user entry point in r0\n\
+_dl_start_user:\n\
+ adr r6, .L_GET_GOT\n\
+ add sl, sl, r6\n\
+ ldr r4, [sl, r4]\n\
+ @ save the entry point in another register\n\
+ mov r6, r0\n\
+ @ get the original arg count\n\
+ ldr r1, [sp]\n\
+ @ get the argv address\n\
+ add r2, sp, #4\n\
+ @ Fix up the stack if necessary.\n\
+ cmp r4, #0\n\
+ bne .L_fixup_stack\n\
+.L_done_fixup:\n\
+ @ compute envp\n\
+ add r3, r2, r1, lsl #2\n\
+ add r3, r3, #4\n\
+ @ now we call _dl_init\n\
+ ldr r0, .L_LOADED\n\
+ ldr r0, [sl, r0]\n\
+ @ call _dl_init\n\
+ bl _dl_init_internal(PLT)\n\
+ @ load the finalizer function\n\
+ ldr r0, .L_FINI_PROC\n\
+ add r0, sl, r0\n\
+ @ jump to the user_s entry point\n\
+ " BX(r6) "\n\
+\n\
+ @ iWMMXt and EABI targets require the stack to be eight byte\n\
+ @ aligned - shuffle arguments etc.\n\
+.L_fixup_stack:\n\
+ @ subtract _dl_skip_args from original arg count\n\
+ sub r1, r1, r4\n\
+ @ store the new argc in the new stack location\n\
+ str r1, [sp]\n\
+ @ find the first unskipped argument\n\
+ mov r3, r2\n\
+ add r4, r2, r4, lsl #2\n\
+ @ shuffle argv down\n\
+1: ldr r5, [r4], #4\n\
+ str r5, [r3], #4\n\
+ cmp r5, #0\n\
+ bne 1b\n\
+ @ shuffle envp down\n\
+1: ldr r5, [r4], #4\n\
+ str r5, [r3], #4\n\
+ cmp r5, #0\n\
+ bne 1b\n\
+ @ shuffle auxv down\n\
+1: ldmia r4!, {r0, r5}\n\
+ stmia r3!, {r0, r5}\n\
+ cmp r0, #0\n\
+ bne 1b\n\
+ @ Update _dl_argv\n\
+ ldr r3, .L_ARGV\n\
+ str r2, [sl, r3]\n\
+ b .L_done_fixup\n\
+\n\
+.L_GET_GOT:\n\
+ .word _GLOBAL_OFFSET_TABLE_ - .L_GET_GOT\n\
+.L_SKIP_ARGS:\n\
+ .word _dl_skip_args(GOTOFF)\n\
+.L_FINI_PROC:\n\
+ .word _dl_fini(GOTOFF)\n\
+.L_ARGV:\n\
+ .word _dl_argv(GOTOFF)\n\
+.L_LOADED:\n\
+ .word _rtld_local(GOTOFF)\n\
+.previous\n\
+");
+
+/* 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. */
+#ifndef RTLD_BOOTSTRAP
+# define elf_machine_type_class(type) \
+ ((((type) == R_ARM_JUMP_SLOT || (type) == R_ARM_TLS_DTPMOD32 \
+ || (type) == R_ARM_TLS_DTPOFF32 || (type) == R_ARM_TLS_TPOFF32 \
+ || (type) == R_ARM_TLS_DESC) \
+ * ELF_RTYPE_CLASS_PLT) \
+ | (((type) == R_ARM_COPY) * ELF_RTYPE_CLASS_COPY))
+#else
+#define elf_machine_type_class(type) \
+ ((((type) == R_ARM_JUMP_SLOT) * ELF_RTYPE_CLASS_PLT) \
+ | (((type) == R_ARM_COPY) * ELF_RTYPE_CLASS_COPY))
+#endif
+
+/* A reloc type used for ld.so cmdline arg lookups to reject PLT entries. */
+#define ELF_MACHINE_JMP_SLOT R_ARM_JUMP_SLOT
+
+/* ARM never uses Elf32_Rela relocations for the dynamic linker.
+ Prelinked libraries may use Elf32_Rela though. */
+#define ELF_MACHINE_PLT_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 Elf32_Addr
+elf_machine_fixup_plt (struct link_map *map, lookup_t t,
+ const Elf32_Rel *reloc,
+ Elf32_Addr *reloc_addr, Elf32_Addr value)
+{
+ return *reloc_addr = value;
+}
+
+/* Return the final value of a plt relocation. */
+static inline Elf32_Addr
+elf_machine_plt_value (struct link_map *map, const Elf32_Rel *reloc,
+ Elf32_Addr value)
+{
+ return value;
+}
+
+#endif /* !dl_machine_h */
+
+
+/* ARM never uses Elf32_Rela relocations for the dynamic linker.
+ Prelinked libraries may use Elf32_Rela though. */
+#define ELF_MACHINE_NO_RELA defined RTLD_BOOTSTRAP
+
+/* Names of the architecture-specific auditing callback functions. */
+#define ARCH_LA_PLTENTER arm_gnu_pltenter
+#define ARCH_LA_PLTEXIT arm_gnu_pltexit
+
+#ifdef RESOLVE_MAP
+
+/* Deal with an out-of-range PC24 reloc. */
+auto Elf32_Addr
+fix_bad_pc24 (Elf32_Addr *const reloc_addr, Elf32_Addr value)
+{
+ static void *fix_page;
+ static unsigned int fix_offset;
+ static size_t pagesize;
+ Elf32_Word *fix_address;
+
+ if (! fix_page)
+ {
+ if (! pagesize)
+ pagesize = getpagesize ();
+ fix_page = mmap (NULL, pagesize, PROT_READ | PROT_WRITE | PROT_EXEC,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ if (! fix_page)
+ assert (! "could not map page for fixup");
+ fix_offset = 0;
+ }
+
+ fix_address = (Elf32_Word *)(fix_page + fix_offset);
+ fix_address[0] = 0xe51ff004; /* ldr pc, [pc, #-4] */
+ fix_address[1] = value;
+
+ fix_offset += 8;
+ if (fix_offset >= pagesize)
+ fix_page = NULL;
+
+ return (Elf32_Addr)fix_address;
+}
+
+/* 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_rel (struct link_map *map, const Elf32_Rel *reloc,
+ const Elf32_Sym *sym, const struct r_found_version *version,
+ void *const reloc_addr_arg, int skip_ifunc)
+{
+ Elf32_Addr *const reloc_addr = reloc_addr_arg;
+ const unsigned int r_type = ELF32_R_TYPE (reloc->r_info);
+
+#if !defined RTLD_BOOTSTRAP || !defined HAVE_Z_COMBRELOC
+ if (__builtin_expect (r_type == R_ARM_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 (_dl_rtld_map);
+# endif
+ if (map != &GL(dl_rtld_map)) /* Already done in rtld itself. */
+# endif
+ *reloc_addr += map->l_addr;
+ }
+# ifndef RTLD_BOOTSTRAP
+ else if (__builtin_expect (r_type == R_ARM_NONE, 0))
+ return;
+# endif
+ else
+#endif
+ {
+ const Elf32_Sym *const refsym = sym;
+ struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
+ Elf32_Addr value = sym_map == NULL ? 0 : 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 = elf_ifunc_invoke (value);
+
+ switch (r_type)
+ {
+ case R_ARM_COPY:
+ if (sym == NULL)
+ /* This can happen in trace mode if an object could not be
+ found. */
+ break;
+ if (sym->st_size > refsym->st_size
+ || (GLRO(dl_verbose) && sym->st_size < refsym->st_size))
+ {
+ const char *strtab;
+
+ strtab = (const void *) 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));
+ break;
+ case R_ARM_GLOB_DAT:
+ case R_ARM_JUMP_SLOT:
+# ifdef RTLD_BOOTSTRAP
+ /* Fix weak undefined references. */
+ if (sym != NULL && sym->st_value == 0)
+ *reloc_addr = 0;
+ else
+# endif
+ *reloc_addr = value;
+ break;
+ case R_ARM_ABS32:
+ {
+# ifndef RTLD_BOOTSTRAP
+ /* 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 (_dl_rtld_map);
+# endif
+ if (map == &GL(dl_rtld_map))
+ /* Undo the relocation done here during bootstrapping.
+ Now we will relocate it anew, possibly using a
+ binding found in the user program or a loaded library
+ rather than the dynamic linker's built-in definitions
+ used while loading those libraries. */
+ value -= map->l_addr + refsym->st_value;
+# endif
+ *reloc_addr += value;
+ break;
+ }
+ case R_ARM_TLS_DESC:
+ {
+ struct tlsdesc volatile *td =
+ (struct tlsdesc volatile *)reloc_addr;
+
+# ifndef RTLD_BOOTSTRAP
+ if (! sym)
+ td->entry = _dl_tlsdesc_undefweak;
+ else
+# endif
+ {
+ value = sym->st_value + td->argument.value;
+
+# ifndef RTLD_BOOTSTRAP
+# ifndef SHARED
+ CHECK_STATIC_TLS (map, sym_map);
+# else
+ if (!TRY_STATIC_TLS (map, sym_map))
+ {
+ td->argument.pointer
+ = _dl_make_tlsdesc_dynamic (sym_map, value);
+ td->entry = _dl_tlsdesc_dynamic;
+ }
+ else
+# endif
+# endif
+ {
+ td->argument.value = value + sym_map->l_tls_offset;
+ td->entry = _dl_tlsdesc_return;
+ }
+ }
+ }
+ break;
+ case R_ARM_PC24:
+ {
+ Elf32_Sword addend;
+ Elf32_Addr newvalue, topbits;
+
+ addend = *reloc_addr & 0x00ffffff;
+ if (addend & 0x00800000) addend |= 0xff000000;
+
+ newvalue = value - (Elf32_Addr)reloc_addr + (addend << 2);
+ topbits = newvalue & 0xfe000000;
+ if (topbits != 0xfe000000 && topbits != 0x00000000)
+ {
+ newvalue = fix_bad_pc24(reloc_addr, value)
+ - (Elf32_Addr)reloc_addr + (addend << 2);
+ topbits = newvalue & 0xfe000000;
+ if (topbits != 0xfe000000 && topbits != 0x00000000)
+ {
+ _dl_signal_error (0, map->l_name, NULL,
+ "R_ARM_PC24 relocation out of range");
+ }
+ }
+ newvalue >>= 2;
+ value = (*reloc_addr & 0xff000000) | (newvalue & 0x00ffffff);
+ *reloc_addr = value;
+ }
+ break;
+#if !defined RTLD_BOOTSTRAP
+ case R_ARM_TLS_DTPMOD32:
+ /* Get the information from the link map returned by the
+ resolv function. */
+ if (sym_map != NULL)
+ *reloc_addr = sym_map->l_tls_modid;
+ break;
+
+ case R_ARM_TLS_DTPOFF32:
+ if (sym != NULL)
+ *reloc_addr += sym->st_value;
+ break;
+
+ case R_ARM_TLS_TPOFF32:
+ if (sym != NULL)
+ {
+ CHECK_STATIC_TLS (map, sym_map);
+ *reloc_addr += sym->st_value + sym_map->l_tls_offset;
+ }
+ break;
+ case R_ARM_IRELATIVE:
+ value = map->l_addr + *reloc_addr;
+ value = ((Elf32_Addr (*) (void)) value) ();
+ *reloc_addr = value;
+ break;
+#endif
+ default:
+ _dl_reloc_bad_type (map, r_type, 0);
+ break;
+ }
+ }
+}
+
+# ifndef RTLD_BOOTSTRAP
+auto inline void
+__attribute__ ((always_inline))
+elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
+ const Elf32_Sym *sym, const struct r_found_version *version,
+ void *const reloc_addr_arg, int skip_ifunc)
+{
+ Elf32_Addr *const reloc_addr = reloc_addr_arg;
+ const unsigned int r_type = ELF32_R_TYPE (reloc->r_info);
+
+ if (__builtin_expect (r_type == R_ARM_RELATIVE, 0))
+ *reloc_addr = map->l_addr + reloc->r_addend;
+ else if (__builtin_expect (r_type == R_ARM_NONE, 0))
+ return;
+ else
+ {
+# ifndef RESOLVE_CONFLICT_FIND_MAP
+ const Elf32_Sym *const refsym = sym;
+# endif
+ struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
+ Elf32_Addr value = sym_map == NULL ? 0 : 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 = elf_ifunc_invoke (value);
+
+ switch (r_type)
+ {
+# ifndef RESOLVE_CONFLICT_FIND_MAP
+ /* Not needed for dl-conflict.c. */
+ case R_ARM_COPY:
+ if (sym == NULL)
+ /* This can happen in trace mode if an object could not be
+ found. */
+ break;
+ if (sym->st_size > refsym->st_size
+ || (GLRO(dl_verbose) && sym->st_size < refsym->st_size))
+ {
+ const char *strtab;
+
+ strtab = (const void *) 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));
+ break;
+# endif /* !RESOLVE_CONFLICT_FIND_MAP */
+ case R_ARM_GLOB_DAT:
+ case R_ARM_JUMP_SLOT:
+ case R_ARM_ABS32:
+ *reloc_addr = value + reloc->r_addend;
+ break;
+ case R_ARM_PC24:
+ {
+ Elf32_Addr newvalue, topbits;
+
+ newvalue = value + reloc->r_addend - (Elf32_Addr)reloc_addr;
+ topbits = newvalue & 0xfe000000;
+ if (topbits != 0xfe000000 && topbits != 0x00000000)
+ {
+ newvalue = fix_bad_pc24(reloc_addr, value)
+ - (Elf32_Addr)reloc_addr + (reloc->r_addend << 2);
+ topbits = newvalue & 0xfe000000;
+ if (topbits != 0xfe000000 && topbits != 0x00000000)
+ {
+ _dl_signal_error (0, map->l_name, NULL,
+ "R_ARM_PC24 relocation out of range");
+ }
+ }
+ newvalue >>= 2;
+ value = (*reloc_addr & 0xff000000) | (newvalue & 0x00ffffff);
+ *reloc_addr = value;
+ }
+ break;
+#if !defined RTLD_BOOTSTRAP
+ case R_ARM_TLS_DTPMOD32:
+ /* Get the information from the link map returned by the
+ resolv function. */
+ if (sym_map != NULL)
+ *reloc_addr = sym_map->l_tls_modid;
+ break;
+
+ case R_ARM_TLS_DTPOFF32:
+ *reloc_addr = (sym == NULL ? 0 : sym->st_value) + reloc->r_addend;
+ break;
+
+ case R_ARM_TLS_TPOFF32:
+ if (sym != NULL)
+ {
+ CHECK_STATIC_TLS (map, sym_map);
+ *reloc_addr = (sym->st_value + sym_map->l_tls_offset
+ + reloc->r_addend);
+ }
+ break;
+ case R_ARM_IRELATIVE:
+ value = map->l_addr + *reloc_addr;
+ value = ((Elf32_Addr (*) (void)) value) ();
+ *reloc_addr = value;
+ break;
+#endif
+ default:
+ _dl_reloc_bad_type (map, r_type, 0);
+ break;
+ }
+ }
+}
+# endif
+
+auto inline void
+__attribute__ ((always_inline))
+elf_machine_rel_relative (Elf32_Addr l_addr, const Elf32_Rel *reloc,
+ void *const reloc_addr_arg)
+{
+ Elf32_Addr *const reloc_addr = reloc_addr_arg;
+ *reloc_addr += l_addr;
+}
+
+# ifndef RTLD_BOOTSTRAP
+auto inline void
+__attribute__ ((always_inline))
+elf_machine_rela_relative (Elf32_Addr l_addr, const Elf32_Rela *reloc,
+ void *const reloc_addr_arg)
+{
+ Elf32_Addr *const reloc_addr = reloc_addr_arg;
+ *reloc_addr = l_addr + reloc->r_addend;
+}
+# endif
+
+auto inline void
+__attribute__ ((always_inline))
+elf_machine_lazy_rel (struct link_map *map,
+ Elf32_Addr l_addr, const Elf32_Rel *reloc,
+ int skip_ifunc)
+{
+ Elf32_Addr *const reloc_addr = (void *) (l_addr + reloc->r_offset);
+ const unsigned int r_type = ELF32_R_TYPE (reloc->r_info);
+ /* Check for unexpected PLT reloc type. */
+ if (__builtin_expect (r_type == R_ARM_JUMP_SLOT, 1))
+ {
+ if (__builtin_expect (map->l_mach.plt, 0) == 0)
+ *reloc_addr += l_addr;
+ else
+ *reloc_addr = map->l_mach.plt;
+ }
+ else if (__builtin_expect (r_type == R_ARM_TLS_DESC, 1))
+ {
+ struct tlsdesc volatile *td =
+ (struct tlsdesc volatile *)reloc_addr;
+
+ /* The linker must have given us the parameter we need in the
+ first GOT entry, and left the second one empty. We fill the
+ last with the resolver address */
+ assert (td->entry == 0);
+ td->entry = (void*)(D_PTR (map, l_info[ADDRIDX (DT_TLSDESC_PLT)])
+ + map->l_addr);
+ }
+ else
+ _dl_reloc_bad_type (map, r_type, 1);
+}
+
+#endif /* RESOLVE_MAP */
diff --git a/ports/sysdeps/arm/dl-sysdep.h b/ports/sysdeps/arm/dl-sysdep.h
new file mode 100644
index 0000000000..91c754b12c
--- /dev/null
+++ b/ports/sysdeps/arm/dl-sysdep.h
@@ -0,0 +1,23 @@
+/* System-specific settings for dynamic linker code. Alpha version.
+ Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include_next <dl-sysdep.h>
+
+/* _dl_argv cannot be attribute_relro, because _dl_start_user
+ might write into it after _dl_start returns. */
+#define DL_ARGV_NOT_RELRO 1
diff --git a/ports/sysdeps/arm/dl-tls.h b/ports/sysdeps/arm/dl-tls.h
new file mode 100644
index 0000000000..ada45f78c8
--- /dev/null
+++ b/ports/sysdeps/arm/dl-tls.h
@@ -0,0 +1,31 @@
+/* Thread-local storage handling in the ELF dynamic linker. ARM version.
+ Copyright (C) 2005, 2011 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/>. */
+
+
+/* Type used for the representation of TLS information in the GOT. */
+typedef struct dl_tls_index
+{
+ unsigned long int ti_module;
+ unsigned long int ti_offset;
+} tls_index;
+
+
+extern void *__tls_get_addr (tls_index *ti);
+
+/* Value used for dtv entries for which the allocation is delayed. */
+#define TLS_DTV_UNALLOCATED ((void *) -1l)
diff --git a/ports/sysdeps/arm/dl-tlsdesc.S b/ports/sysdeps/arm/dl-tlsdesc.S
new file mode 100644
index 0000000000..f21555281f
--- /dev/null
+++ b/ports/sysdeps/arm/dl-tlsdesc.S
@@ -0,0 +1,218 @@
+/* Thread-local storage handling in the ELF dynamic linker. ARM version.
+ Copyright (C) 2006, 2010, 2011 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <tls.h>
+#include "tlsdesc.h"
+
+#ifdef __USE_BX__
+ #define BX(x) bx x
+#else
+ #define BX(x) mov pc, x
+#endif
+
+ .text
+ @ emit debug information with cfi
+ @ use arm-specific pseudos for unwinding itself
+ .cfi_sections .debug_frame
+ .hidden _dl_tlsdesc_return
+ .global _dl_tlsdesc_return
+ .type _dl_tlsdesc_return,#function
+ cfi_startproc
+ .fnstart
+ .align 2
+_dl_tlsdesc_return:
+ ldr r0, [r0]
+ BX (lr)
+ .fnend
+ cfi_endproc
+ .size _dl_tlsdesc_return, .-_dl_tlsdesc_return
+
+ .hidden _dl_tlsdesc_undefweak
+ .global _dl_tlsdesc_undefweak
+ .type _dl_tlsdesc_undefweak,#function
+ cfi_startproc
+ .fnstart
+ .align 2
+_dl_tlsdesc_undefweak:
+ @ Are we allowed a misaligned stack pointer calling read_tp?
+ .save {lr}
+ stmdb sp!, {lr}
+ cfi_adjust_cfa_offset (4)
+ cfi_rel_offset (lr,0)
+ bl __aeabi_read_tp
+ rsb r0, r0, #0
+ ldmia sp!, {lr}
+ cfi_adjust_cfa_offset (-4)
+ cfi_restore (lr)
+ BX (lr)
+
+ cfi_endproc
+ .fnend
+ .size _dl_tlsdesc_undefweak, .-_dl_tlsdesc_undefweak
+
+#ifdef SHARED
+ .hidden _dl_tlsdesc_dynamic
+ .global _dl_tlsdesc_dynamic
+ .type _dl_tlsdesc_dynamic,#function
+
+
+/*
+ The assembly code that follows is a rendition of the following
+ C code, hand-optimized a little bit.
+
+ptrdiff_t
+_dl_tlsdesc_dynamic(struct tlsdesc *tdp)
+{
+ struct tlsdesc_dynamic_arg *td = tdp->argument.pointer;
+ dtv_t *dtv = (dtv_t *)THREAD_DTV();
+ if (__builtin_expect (td->gen_count <= dtv[0].counter
+ && dtv[td->tlsinfo.ti_module].pointer.val
+ != TLS_DTV_UNALLOCATED,
+ 1))
+ return dtv[td->tlsinfo.ti_module].pointer.val +
+ td->tlsinfo.ti_offset - __builtin_thread_pointer();
+
+ return __tls_get_addr (&td->tlsinfo) - __builtin_thread_pointer();
+}
+
+*/
+ cfi_startproc
+ .fnstart
+ .align 2
+_dl_tlsdesc_dynamic:
+ /* Our calling convention is to clobber r0, r1 and the processor
+ flags. All others that are modified must be saved */
+ .save {r2,r3,r4,lr}
+ stmdb sp!, {r2,r3,r4,lr}
+ cfi_adjust_cfa_offset (16)
+ cfi_rel_offset (r2,0)
+ cfi_rel_offset (r3,4)
+ cfi_rel_offset (r4,8)
+ cfi_rel_offset (lr,12)
+ ldr r1, [r0] /* td */
+ bl __aeabi_read_tp
+ mov r4, r0 /* r4 = tp */
+ ldr r0, [r0]
+ ldr r2, [r1, #8] /* gen_count */
+ ldr r3, [r0]
+ cmp r2, r3
+ bhi 1f
+ ldr r3, [r1]
+ ldr r2, [r0, r3, lsl #3]
+ cmn r2, #1
+ ldrne r3, [r1, #4]
+ addne r3, r2, r3
+ rsbne r0, r4, r3
+ bne 2f
+1: mov r0, r1
+ bl __tls_get_addr
+ rsb r0, r4, r0
+2: ldmia sp!, {r2,r3,r4, lr}
+ cfi_adjust_cfa_offset (-16)
+ cfi_restore (lr)
+ cfi_restore (r4)
+ cfi_restore (r3)
+ cfi_restore (r2)
+ BX (lr)
+ .fnend
+ cfi_endproc
+ .size _dl_tlsdesc_dynamic, .-_dl_tlsdesc_dynamic
+#endif /* SHARED */
+
+/* lazy resolved for tls descriptors. */
+ .hidden _dl_tlsdesc_lazy_resolver
+ .global _dl_tlsdesc_lazy_resolver
+ .type _dl_tlsdesc_lazy_resolver,#function
+ cfi_startproc
+ .fnstart
+ .align 2
+_dl_tlsdesc_lazy_resolver:
+ /* r0 points at the tlsdesc,
+ r1 points at the GOT
+ r2 was pushed by the trampoline and used as a temp,
+ we need to pop it here.
+ We push the remaining call-clobbered registers here, and also
+ R1 -- to keep the stack correctly aligned. */
+ /* Tell the unwinder that r2 has already been pushed. */
+ .save {r2}
+ cfi_adjust_cfa_offset (4)
+ cfi_rel_offset (r2, 0)
+ .save {r0,r1,r3,ip,lr}
+ stmdb sp!, {r0, r1, r3, ip, lr}
+ cfi_adjust_cfa_offset (20)
+ cfi_rel_offset (r0, 0)
+ cfi_rel_offset (r1, 4)
+ cfi_rel_offset (r3, 8)
+ cfi_rel_offset (ip, 12)
+ cfi_rel_offset (lr, 16)
+ bl _dl_tlsdesc_lazy_resolver_fixup
+ ldmia sp!, {r0, r1, r3, ip, lr}
+ cfi_adjust_cfa_offset (-20)
+ cfi_restore (lr)
+ cfi_restore (ip)
+ cfi_restore (r3)
+ cfi_restore (r1)
+ cfi_restore (r0)
+ ldmia sp!, {r2}
+ cfi_adjust_cfa_offset (-4)
+ cfi_restore (r2)
+ ldr r1, [r0, #4]
+ BX (r1)
+ .fnend
+ cfi_endproc
+ .size _dl_tlsdesc_lazy_resolver, .-_dl_tlsdesc_lazy_resolver
+
+/* Holder for lazy tls descriptors being resolve in another thread.
+ Same ABI as the lazy resolver itself. */
+ .hidden _dl_tlsdesc_resolve_hold
+ .global _dl_tlsdesc_resolve_hold
+ .type _dl_tlsdesc_resolve_hold,#function
+ cfi_startproc
+ .fnstart
+ .align 2
+_dl_tlsdesc_resolve_hold:
+ /* Tell the unwinder that r2 has already been pushed. */
+ .save {r2}
+ cfi_adjust_cfa_offset (4)
+ cfi_rel_offset (r2, 0)
+ .save {r0,r1,r3,ip,lr}
+ stmdb sp!, {r0, r1, r3, ip, lr}
+ cfi_adjust_cfa_offset (20)
+ cfi_rel_offset (r0, 0)
+ cfi_rel_offset (r1, 4)
+ cfi_rel_offset (r3, 8)
+ cfi_rel_offset (ip, 12)
+ cfi_rel_offset (lr, 16)
+ adr r2, _dl_tlsdesc_resolve_hold
+ bl _dl_tlsdesc_resolve_hold_fixup
+ ldmia sp!, {r0, r1, r3, ip, lr}
+ cfi_adjust_cfa_offset (-20)
+ cfi_restore (lr)
+ cfi_restore (ip)
+ cfi_restore (r3)
+ cfi_restore (r1)
+ cfi_restore (r0)
+ ldmia sp!, {r2}
+ cfi_adjust_cfa_offset (-4)
+ cfi_restore (r2)
+ ldr r1, [r0, #4]
+ BX (r1)
+ .fnend
+ cfi_endproc
+ .size _dl_tlsdesc_resolve_hold, .-_dl_tlsdesc_resolve_hold
diff --git a/ports/sysdeps/arm/dl-tlsdesc.h b/ports/sysdeps/arm/dl-tlsdesc.h
new file mode 100644
index 0000000000..2b1131c55a
--- /dev/null
+++ b/ports/sysdeps/arm/dl-tlsdesc.h
@@ -0,0 +1,68 @@
+/* Thread-local storage descriptor handling in the ELF dynamic linker.
+ ARM version.
+ Copyright (C) 2005, 2010 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; witout even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _ARM_DL_TLSDESC_H
+# define _ARM_DL_TLSDESC_H 1
+
+/* Use this to access DT_TLSDESC_PLT and DT_TLSDESC_GOT. */
+#ifndef ADDRIDX
+# define ADDRIDX(tag) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM \
+ + DT_EXTRANUM + DT_VALNUM + DT_ADDRTAGIDX (tag))
+#endif
+
+/* Type used to represent a TLS descriptor in the GOT. */
+struct tlsdesc
+{
+ union
+ {
+ void *pointer;
+ long value;
+ } argument;
+ ptrdiff_t (*entry)(struct tlsdesc *);
+};
+
+
+typedef struct dl_tls_index
+{
+ unsigned long int ti_module;
+ unsigned long int ti_offset;
+} tls_index;
+
+/* Type used as the argument in a TLS descriptor for a symbol that
+ needs dynamic TLS offsets. */
+struct tlsdesc_dynamic_arg
+{
+ tls_index tlsinfo;
+ size_t gen_count;
+};
+
+extern ptrdiff_t attribute_hidden
+ _dl_tlsdesc_return(struct tlsdesc *),
+ _dl_tlsdesc_undefweak(struct tlsdesc *),
+ _dl_tlsdesc_resolve_hold(struct tlsdesc *),
+ _dl_tlsdesc_lazy_resolver(struct tlsdesc *);
+
+# ifdef SHARED
+extern void *_dl_make_tlsdesc_dynamic (struct link_map *map, size_t ti_offset);
+
+extern ptrdiff_t attribute_hidden
+ _dl_tlsdesc_dynamic(struct tlsdesc *);
+# endif
+
+#endif
diff --git a/ports/sysdeps/arm/dl-trampoline.S b/ports/sysdeps/arm/dl-trampoline.S
new file mode 100644
index 0000000000..370bda3467
--- /dev/null
+++ b/ports/sysdeps/arm/dl-trampoline.S
@@ -0,0 +1,217 @@
+/* PLT trampolines. ARM version.
+ Copyright (C) 2005, 2010 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <libc-symbols.h>
+
+#if defined(__USE_BX__)
+#define BX(x) bx x
+#else
+#define BX(x) mov pc, x
+#endif
+
+ .text
+ .globl _dl_runtime_resolve
+ .type _dl_runtime_resolve, #function
+ .cfi_sections .debug_frame
+ cfi_startproc
+ .align 2
+_dl_runtime_resolve:
+ cfi_adjust_cfa_offset (4)
+ cfi_rel_offset (lr, 0)
+
+ @ we get called with
+ @ stack[0] contains the return address from this call
+ @ ip contains &GOT[n+3] (pointer to function)
+ @ lr points to &GOT[2]
+
+ @ Save arguments. We save r4 to realign the stack.
+ stmdb sp!,{r0-r4}
+ cfi_adjust_cfa_offset (20)
+ cfi_rel_offset (r0, 0)
+ cfi_rel_offset (r1, 4)
+ cfi_rel_offset (r2, 8)
+ cfi_rel_offset (r3, 12)
+
+ @ get pointer to linker struct
+ ldr r0, [lr, #-4]
+
+ @ prepare to call _dl_fixup()
+ @ change &GOT[n+3] into 8*n NOTE: reloc are 8 bytes each
+ sub r1, ip, lr
+ sub r1, r1, #4
+ add r1, r1, r1
+
+ @ call fixup routine
+ bl _dl_fixup
+
+ @ save the return
+ mov ip, r0
+
+ @ get arguments and return address back. We restore r4
+ @ only to realign the stack.
+ ldmia sp!, {r0-r4,lr}
+ cfi_adjust_cfa_offset (-24)
+
+ @ jump to the newly found address
+ BX(ip)
+
+ cfi_endproc
+ .size _dl_runtime_resolve, .-_dl_runtime_resolve
+
+#ifndef PROF
+ .globl _dl_runtime_profile
+ .type _dl_runtime_profile, #function
+ .cfi_sections .debug_frame
+ cfi_startproc
+ .align 2
+_dl_runtime_profile:
+ cfi_adjust_cfa_offset (4)
+ cfi_rel_offset (lr, 0)
+
+ @ we get called with
+ @ stack[0] contains the return address from this call
+ @ ip contains &GOT[n+3] (pointer to function)
+ @ lr points to &GOT[2]
+
+ @ Stack layout:
+ @ 212 - saved lr
+ @ 208 - framesize returned from pltenter
+ @ 16 - La_arm_regs
+ @ 8 - Saved two arguments to _dl_profile_fixup
+ @ 4 - Saved result of _dl_profile_fixup
+ @ 0 - outgoing argument to _dl_profile_fixup
+ @ For now, we only save the general purpose registers.
+
+ sub sp, sp, #196
+ cfi_adjust_cfa_offset (196)
+ stmia sp, {r0-r3}
+ cfi_rel_offset (r0, 0)
+ cfi_rel_offset (r1, 4)
+ cfi_rel_offset (r2, 8)
+ cfi_rel_offset (r3, 12)
+
+ sub sp, sp, #16
+ cfi_adjust_cfa_offset (16)
+
+ @ Save sp and lr.
+ add r0, sp, #216
+ str r0, [sp, #32]
+ ldr r2, [sp, #212]
+ str r2, [sp, #36]
+
+ @ get pointer to linker struct
+ ldr r0, [lr, #-4]
+
+ @ prepare to call _dl_profile_fixup()
+ @ change &GOT[n+3] into 8*n NOTE: reloc are 8 bytes each
+ sub r1, ip, lr
+ sub r1, r1, #4
+ add r1, r1, r1
+
+ @ Save these two arguments for pltexit.
+ add r3, sp, #8
+ stmia r3!, {r0,r1}
+
+ @ Set up extra args for _dl_profile_fixup.
+ @ r2 and r3 are already loaded.
+ add ip, sp, #208
+ str ip, [sp, #0]
+
+ @ call profiling fixup routine
+ bl _dl_profile_fixup
+
+ @ The address to call is now in r0.
+
+ @ Check whether we're wrapping this function.
+ ldr ip, [sp, #208]
+ cmp ip, #0
+ bge 1f
+ cfi_remember_state
+
+ @ save the return
+ mov ip, r0
+
+ @ get arguments and return address back
+ add sp, sp, #16
+ cfi_adjust_cfa_offset (-16)
+ ldmia sp, {r0-r3,sp,lr}
+ cfi_adjust_cfa_offset (-200)
+
+ @ jump to the newly found address
+ BX(ip)
+
+ cfi_restore_state
+1:
+ @ The new frame size is in ip.
+
+ @ New stack layout:
+ @ 268 - saved r7
+ @ 264 - saved result of _dl_profile_fixup
+ @ 72 - La_arm_regs
+ @ 64 - Saved two arguments to _dl_profile_fixup
+ @ 0 - La_arm_retval
+ @ For now, we only save the general purpose registers.
+
+ @ Build the new frame.
+ str r7, [sp, #212]
+ cfi_rel_offset (r7, 212)
+ sub r7, sp, #56
+ cfi_def_cfa_register (r7)
+ cfi_adjust_cfa_offset (56)
+ sub sp, sp, ip
+ bic sp, sp, #7
+
+ @ Save the _dl_profile_fixup result around the call to memcpy.
+ str r0, [r7, #264]
+
+ @ Copy the stack arguments.
+ mov r0, sp
+ add r1, r7, #272
+ mov r2, ip
+ bl memcpy
+
+ @ Call the function.
+ add ip, r7, #72
+ ldmia ip, {r0-r3}
+ ldr ip, [r7, #264]
+ mov lr, pc
+ BX(ip)
+ stmia r7, {r0-r3}
+
+ @ Call pltexit.
+ add ip, r7, #64
+ ldmia ip, {r0,r1}
+ add r2, r7, #72
+ add r3, r7, #0
+ bl _dl_call_pltexit
+
+ @ Return to caller.
+ ldmia r7, {r0-r3}
+ mov sp, r7
+ cfi_def_cfa_register (sp)
+ ldr r7, [sp, #268]
+ ldr lr, [sp, #92]
+ add sp, sp, #272
+ cfi_adjust_cfa_offset (-272)
+ BX(lr)
+
+ cfi_endproc
+ .size _dl_runtime_profile, .-_dl_runtime_profile
+#endif
+ .previous
diff --git a/ports/sysdeps/arm/fclrexcpt.c b/ports/sysdeps/arm/fclrexcpt.c
new file mode 100644
index 0000000000..ddedc3573c
--- /dev/null
+++ b/ports/sysdeps/arm/fclrexcpt.c
@@ -0,0 +1,60 @@
+/* Clear given exceptions in current floating-point environment.
+ Copyright (C) 1997,98,99,2000,01,05,11 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+#include <unistd.h>
+#include <ldsodefs.h>
+#include <dl-procinfo.h>
+#include <sysdep.h>
+
+int
+__feclearexcept (int excepts)
+{
+ if (GLRO (dl_hwcap) & HWCAP_ARM_VFP)
+ {
+ unsigned long int temp;
+
+ /* Mask out unsupported bits/exceptions. */
+ excepts &= FE_ALL_EXCEPT;
+
+ /* Get the current floating point status. */
+ _FPU_GETCW (temp);
+
+ /* Clear the relevant bits. */
+ temp = (temp & ~FE_ALL_EXCEPT) | (temp & FE_ALL_EXCEPT & ~excepts);
+
+ /* Put the new data in effect. */
+ _FPU_SETCW (temp);
+
+ /* Success. */
+ return 0;
+ }
+
+ /* Unsupported, so fail unless nothing needs to be done. */
+ return (excepts != 0);
+}
+
+#include <shlib-compat.h>
+#if SHLIB_COMPAT (libm, GLIBC_2_1, GLIBC_2_2)
+strong_alias (__feclearexcept, __old_feclearexcept)
+compat_symbol (libm, __old_feclearexcept, feclearexcept, GLIBC_2_1);
+#endif
+
+versioned_symbol (libm, __feclearexcept, feclearexcept, GLIBC_2_2);
diff --git a/ports/sysdeps/arm/fedisblxcpt.c b/ports/sysdeps/arm/fedisblxcpt.c
new file mode 100644
index 0000000000..c9c62a48ef
--- /dev/null
+++ b/ports/sysdeps/arm/fedisblxcpt.c
@@ -0,0 +1,50 @@
+/* Disable floating-point exceptions.
+ Copyright (C) 2001, 2005 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Philip Blundell <philb@gnu.org>, 2001.
+
+ 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 <fpu_control.h>
+
+#include <unistd.h>
+#include <ldsodefs.h>
+#include <dl-procinfo.h>
+#include <sysdep.h>
+
+int
+fedisableexcept (int excepts)
+{
+ if (GLRO (dl_hwcap) & HWCAP_ARM_VFP)
+ {
+ unsigned long int new_exc, old_exc;
+
+ _FPU_GETCW(new_exc);
+
+ old_exc = (new_exc >> FE_EXCEPT_SHIFT) & FE_ALL_EXCEPT;
+
+ excepts &= FE_ALL_EXCEPT;
+
+ new_exc &= ~(excepts << FE_EXCEPT_SHIFT);
+
+ _FPU_SETCW(new_exc);
+
+ return old_exc;
+ }
+
+ /* Unsupported, so return -1 for failure. */
+ return -1;
+}
diff --git a/ports/sysdeps/arm/feenablxcpt.c b/ports/sysdeps/arm/feenablxcpt.c
new file mode 100644
index 0000000000..3b2b934f57
--- /dev/null
+++ b/ports/sysdeps/arm/feenablxcpt.c
@@ -0,0 +1,50 @@
+/* Enable floating-point exceptions.
+ Copyright (C) 2001, 2005 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Philip Blundell <philb@gnu.org>, 2001.
+
+ 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 <fpu_control.h>
+
+#include <unistd.h>
+#include <ldsodefs.h>
+#include <dl-procinfo.h>
+#include <sysdep.h>
+
+int
+feenableexcept (int excepts)
+{
+ if (GLRO (dl_hwcap) & HWCAP_ARM_VFP)
+ {
+ unsigned long int new_exc, old_exc;
+
+ _FPU_GETCW(new_exc);
+
+ old_exc = (new_exc >> FE_EXCEPT_SHIFT) & FE_ALL_EXCEPT;
+
+ excepts &= FE_ALL_EXCEPT;
+
+ new_exc |= (excepts << FE_EXCEPT_SHIFT);
+
+ _FPU_SETCW(new_exc);
+
+ return old_exc;
+ }
+
+ /* Unsupported, so return -1 for failure. */
+ return -1;
+}
diff --git a/ports/sysdeps/arm/fegetenv.c b/ports/sysdeps/arm/fegetenv.c
new file mode 100644
index 0000000000..c638635df4
--- /dev/null
+++ b/ports/sysdeps/arm/fegetenv.c
@@ -0,0 +1,51 @@
+/* Store current floating-point environment.
+ Copyright (C) 1997,98,99,2000,01,05,10 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+#include <unistd.h>
+#include <ldsodefs.h>
+#include <dl-procinfo.h>
+#include <sysdep.h>
+
+int
+__fegetenv (fenv_t *envp)
+{
+ if (GLRO (dl_hwcap) & HWCAP_ARM_VFP)
+ {
+ unsigned long int temp;
+ _FPU_GETCW (temp);
+ envp->__cw = temp;
+
+ /* Success. */
+ return 0;
+ }
+
+ /* Unsupported, so fail. */
+ return 1;
+}
+
+#include <shlib-compat.h>
+#if SHLIB_COMPAT (libm, GLIBC_2_1, GLIBC_2_2)
+strong_alias (__fegetenv, __old_fegetenv)
+compat_symbol (libm, __old_fegetenv, fegetenv, GLIBC_2_1);
+#endif
+
+libm_hidden_ver (__fegetenv, fegetenv)
+versioned_symbol (libm, __fegetenv, fegetenv, GLIBC_2_2);
diff --git a/ports/sysdeps/arm/fegetexcept.c b/ports/sysdeps/arm/fegetexcept.c
new file mode 100644
index 0000000000..929d6c5cfa
--- /dev/null
+++ b/ports/sysdeps/arm/fegetexcept.c
@@ -0,0 +1,42 @@
+/* Get floating-point exceptions.
+ Copyright (C) 2001, 2005 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Philip Blundell <philb@gnu.org>, 2001
+
+ 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 <fpu_control.h>
+
+#include <unistd.h>
+#include <ldsodefs.h>
+#include <dl-procinfo.h>
+#include <sysdep.h>
+
+int
+fegetexcept (void)
+{
+ if (GLRO (dl_hwcap) & HWCAP_ARM_VFP)
+ {
+ unsigned long temp;
+
+ _FPU_GETCW (temp);
+
+ return (temp >> FE_EXCEPT_SHIFT) & FE_ALL_EXCEPT;
+ }
+
+ /* Unsupported. Return all exceptions disabled. */
+ return 0;
+}
diff --git a/ports/sysdeps/arm/fegetround.c b/ports/sysdeps/arm/fegetround.c
new file mode 100644
index 0000000000..df1049706b
--- /dev/null
+++ b/ports/sysdeps/arm/fegetround.c
@@ -0,0 +1,42 @@
+/* Return current rounding direction.
+ Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+#include <unistd.h>
+#include <ldsodefs.h>
+#include <dl-procinfo.h>
+#include <sysdep.h>
+
+int
+fegetround (void)
+{
+ if (GLRO (dl_hwcap) & HWCAP_ARM_VFP)
+ {
+ unsigned int temp;
+
+ /* Get the current environment. */
+ _FPU_GETCW (temp);
+
+ return temp & FE_TOWARDZERO;
+ }
+
+ /* The current soft-float implementation only handles TONEAREST. */
+ return FE_TONEAREST;
+}
diff --git a/ports/sysdeps/arm/feholdexcpt.c b/ports/sysdeps/arm/feholdexcpt.c
new file mode 100644
index 0000000000..4aed48bb39
--- /dev/null
+++ b/ports/sysdeps/arm/feholdexcpt.c
@@ -0,0 +1,53 @@
+/* Store current floating-point environment and clear exceptions.
+ Copyright (C) 1997, 1998, 1999, 2005 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+#include <unistd.h>
+#include <ldsodefs.h>
+#include <dl-procinfo.h>
+#include <sysdep.h>
+
+int
+feholdexcept (fenv_t *envp)
+{
+ if (GLRO (dl_hwcap) & HWCAP_ARM_VFP)
+ {
+ unsigned long int temp;
+
+ /* Store the environment. */
+ _FPU_GETCW(temp);
+ envp->__cw = temp;
+
+ /* Now set all exceptions to non-stop. */
+ temp &= ~(FE_ALL_EXCEPT << FE_EXCEPT_SHIFT);
+
+ /* And clear all exception flags. */
+ temp &= ~FE_ALL_EXCEPT;
+
+ _FPU_SETCW(temp);
+
+ return 0;
+ }
+
+ /* Unsupported, so fail. */
+ return 1;
+}
+
+libm_hidden_def (feholdexcept)
diff --git a/ports/sysdeps/arm/fesetenv.c b/ports/sysdeps/arm/fesetenv.c
new file mode 100644
index 0000000000..61370325e2
--- /dev/null
+++ b/ports/sysdeps/arm/fesetenv.c
@@ -0,0 +1,56 @@
+/* Install given floating-point environment.
+ Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+#include <unistd.h>
+#include <ldsodefs.h>
+#include <dl-procinfo.h>
+#include <sysdep.h>
+
+int
+__fesetenv (const fenv_t *envp)
+{
+ if (GLRO (dl_hwcap) & HWCAP_ARM_VFP)
+ {
+ unsigned int temp;
+
+ _FPU_GETCW (temp);
+ temp &= _FPU_RESERVED;
+
+ if (envp == FE_DFL_ENV)
+ temp |= _FPU_DEFAULT;
+ else if (envp == FE_NOMASK_ENV)
+ temp |= _FPU_IEEE;
+ else
+ temp |= envp->__cw & ~_FPU_RESERVED;
+
+ _FPU_SETCW (temp);
+
+ /* Success. */
+ return 0;
+ }
+
+ /* Unsupported, so fail. */
+ return 1;
+}
+
+#include <shlib-compat.h>
+libm_hidden_ver (__fesetenv, fesetenv)
+versioned_symbol (libm, __fesetenv, fesetenv, GLIBC_2_2);
diff --git a/ports/sysdeps/arm/fesetround.c b/ports/sysdeps/arm/fesetround.c
new file mode 100644
index 0000000000..997bd98f5a
--- /dev/null
+++ b/ports/sysdeps/arm/fesetround.c
@@ -0,0 +1,56 @@
+/* Set current rounding direction.
+ Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+#include <unistd.h>
+#include <ldsodefs.h>
+#include <dl-procinfo.h>
+#include <sysdep.h>
+
+int
+fesetround (int round)
+{
+ if (GLRO (dl_hwcap) & HWCAP_ARM_VFP)
+ {
+ fpu_control_t temp;
+
+ switch (round)
+ {
+ case FE_TONEAREST:
+ case FE_UPWARD:
+ case FE_DOWNWARD:
+ case FE_TOWARDZERO:
+ _FPU_GETCW (temp);
+ temp = (temp & ~FE_TOWARDZERO) | round;
+ _FPU_SETCW (temp);
+ return 0;
+ default:
+ return 1;
+ }
+ }
+ else if (round == FE_TONEAREST)
+ /* This is the only supported rounding mode for soft-fp. */
+ return 0;
+
+ /* Unsupported, so fail. */
+ return 1;
+}
+
+libm_hidden_def (fesetround)
diff --git a/ports/sysdeps/arm/feupdateenv.c b/ports/sysdeps/arm/feupdateenv.c
new file mode 100644
index 0000000000..98f265432c
--- /dev/null
+++ b/ports/sysdeps/arm/feupdateenv.c
@@ -0,0 +1,59 @@
+/* Install given floating-point environment and raise exceptions.
+ Copyright (C) 1997, 1999, 2000, 2008, 2010 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+ 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 <fpu_control.h>
+
+#include <unistd.h>
+#include <ldsodefs.h>
+#include <dl-procinfo.h>
+#include <sysdep.h>
+
+int
+__feupdateenv (const fenv_t *envp)
+{
+ if (GLRO (dl_hwcap) & HWCAP_ARM_VFP)
+ {
+ unsigned int temp;
+
+ /* Get the current exception state. */
+ _FPU_GETCW (temp);
+
+ /* Install new environment. */
+ fesetenv (envp);
+
+ /* Raise the saved exceptions. */
+ feraiseexcept (temp & FE_ALL_EXCEPT);
+
+ /* Success. */
+ return 0;
+ }
+
+ /* Unsupported, so fail. */
+ return 1;
+}
+
+#include <shlib-compat.h>
+#if SHLIB_COMPAT (libm, GLIBC_2_1, GLIBC_2_2)
+strong_alias (__feupdateenv, __old_feupdateenv)
+compat_symbol (libm, __old_feupdateenv, feupdateenv, GLIBC_2_1);
+#endif
+
+libm_hidden_ver (__feupdateenv, feupdateenv)
+versioned_symbol (libm, __feupdateenv, feupdateenv, GLIBC_2_2);
diff --git a/ports/sysdeps/arm/fgetexcptflg.c b/ports/sysdeps/arm/fgetexcptflg.c
new file mode 100644
index 0000000000..41661a2e29
--- /dev/null
+++ b/ports/sysdeps/arm/fgetexcptflg.c
@@ -0,0 +1,53 @@
+/* Store current representation for exceptions.
+ Copyright (C) 1997, 1999, 2000, 2008 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+ 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 <fpu_control.h>
+
+#include <unistd.h>
+#include <ldsodefs.h>
+#include <dl-procinfo.h>
+#include <sysdep.h>
+
+int
+__fegetexceptflag (fexcept_t *flagp, int excepts)
+{
+ if (GLRO (dl_hwcap) & HWCAP_ARM_VFP)
+ {
+ unsigned long temp;
+
+ /* Get the current exceptions. */
+ _FPU_GETCW (temp);
+
+ *flagp = temp & excepts & FE_ALL_EXCEPT;
+
+ /* Success. */
+ return 0;
+ }
+
+ /* Unsupported, so fail. */
+ return 1;
+}
+
+#include <shlib-compat.h>
+#if SHLIB_COMPAT (libm, GLIBC_2_1, GLIBC_2_2)
+strong_alias (__fegetexceptflag, __old_fegetexceptflag)
+compat_symbol (libm, __old_fegetexceptflag, fegetexceptflag, GLIBC_2_1);
+#endif
+versioned_symbol (libm, __fegetexceptflag, fegetexceptflag, GLIBC_2_2);
diff --git a/ports/sysdeps/arm/find_exidx.c b/ports/sysdeps/arm/find_exidx.c
new file mode 100644
index 0000000000..12ade46d87
--- /dev/null
+++ b/ports/sysdeps/arm/find_exidx.c
@@ -0,0 +1,79 @@
+/* Copyright (C) 2005, 2008 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <link.h>
+#include <unwind.h>
+
+struct unw_eh_callback_data
+{
+ _Unwind_Ptr pc;
+ _Unwind_Ptr exidx_start;
+ int exidx_len;
+};
+
+
+/* Callback to determins if the PC lies within an object, and remember the
+ location of the exception index table if it does. */
+
+static int
+find_exidx_callback (struct dl_phdr_info * info, size_t size, void * ptr)
+{
+ struct unw_eh_callback_data * data;
+ const ElfW(Phdr) *phdr;
+ int i;
+ int match;
+ _Unwind_Ptr load_base;
+
+ data = (struct unw_eh_callback_data *) ptr;
+ load_base = info->dlpi_addr;
+ phdr = info->dlpi_phdr;
+
+ match = 0;
+ for (i = info->dlpi_phnum; i > 0; i--, phdr++)
+ {
+ if (phdr->p_type == PT_LOAD)
+ {
+ _Unwind_Ptr vaddr = phdr->p_vaddr + load_base;
+ if (data->pc >= vaddr && data->pc < vaddr + phdr->p_memsz)
+ match = 1;
+ }
+ else if (phdr->p_type == PT_ARM_EXIDX)
+ {
+ data->exidx_start = (_Unwind_Ptr) (phdr->p_vaddr + load_base);
+ data->exidx_len = phdr->p_memsz;
+ }
+ }
+
+ return match;
+}
+
+
+/* Find the exception index table containing PC. */
+
+_Unwind_Ptr
+__gnu_Unwind_Find_exidx (_Unwind_Ptr pc, int * pcount)
+{
+ struct unw_eh_callback_data data;
+
+ data.pc = pc;
+ data.exidx_start = 0;
+ if (__dl_iterate_phdr (find_exidx_callback, &data) <= 0)
+ return 0;
+
+ *pcount = data.exidx_len / 8;
+ return data.exidx_start;
+}
diff --git a/ports/sysdeps/arm/fpu_control.h b/ports/sysdeps/arm/fpu_control.h
new file mode 100644
index 0000000000..635bc7d4ee
--- /dev/null
+++ b/ports/sysdeps/arm/fpu_control.h
@@ -0,0 +1,63 @@
+/* FPU control word definitions. ARM VFP version.
+ Copyright (C) 2004, 2005, 2009 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _FPU_CONTROL_H
+#define _FPU_CONTROL_H
+
+#if !defined(_LIBC) && defined(__SOFTFP__)
+
+#define _FPU_RESERVED 0xffffffff
+#define _FPU_DEFAULT 0x00000000
+typedef unsigned int fpu_control_t;
+#define _FPU_GETCW(cw) 0
+#define _FPU_SETCW(cw) do { } while (0)
+extern fpu_control_t __fpu_control;
+
+#else
+
+/* masking of interrupts */
+#define _FPU_MASK_IM 0x00000100 /* invalid operation */
+#define _FPU_MASK_ZM 0x00000200 /* divide by zero */
+#define _FPU_MASK_OM 0x00000400 /* overflow */
+#define _FPU_MASK_UM 0x00000800 /* underflow */
+#define _FPU_MASK_PM 0x00001000 /* inexact */
+
+/* Some bits in the FPSCR are not yet defined. They must be preserved when
+ modifying the contents. */
+#define _FPU_RESERVED 0x0e08e0e0
+#define _FPU_DEFAULT 0x00000000
+/* Default + exceptions enabled. */
+#define _FPU_IEEE (_FPU_DEFAULT | 0x00001f00)
+
+/* Type of the control word. */
+typedef unsigned int fpu_control_t;
+
+/* Macros for accessing the hardware control word. */
+/* This is fmrx %0, fpscr. */
+#define _FPU_GETCW(cw) \
+ __asm__ __volatile__ ("mrc p10, 7, %0, cr1, cr0, 0" : "=r" (cw))
+/* This is fmxr fpscr, %0. */
+#define _FPU_SETCW(cw) \
+ __asm__ __volatile__ ("mcr p10, 7, %0, cr1, cr0, 0" : : "r" (cw))
+
+/* Default control word set at startup. */
+extern fpu_control_t __fpu_control;
+
+#endif /* __SOFTFP__ */
+
+#endif /* _FPU_CONTROL_H */
diff --git a/ports/sysdeps/arm/fraiseexcpt.c b/ports/sysdeps/arm/fraiseexcpt.c
new file mode 100644
index 0000000000..0a4368839f
--- /dev/null
+++ b/ports/sysdeps/arm/fraiseexcpt.c
@@ -0,0 +1,109 @@
+/* Raise given exceptions.
+ Copyright (C) 2004, 2005, 2011 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <fpu_control.h>
+#include <fenv.h>
+#include <float.h>
+
+#include <unistd.h>
+#include <ldsodefs.h>
+#include <dl-procinfo.h>
+#include <sysdep.h>
+
+int
+feraiseexcept (int excepts)
+{
+ if (GLRO (dl_hwcap) & HWCAP_ARM_VFP)
+ {
+ int fpscr;
+ const float fp_zero = 0.0, fp_one = 1.0, fp_max = FLT_MAX,
+ fp_min = FLT_MIN, fp_1e32 = 1.0e32f, fp_two = 2.0,
+ fp_three = 3.0;
+
+ /* Raise exceptions represented by EXPECTS. But we must raise only
+ one signal at a time. It is important that if the overflow/underflow
+ exception and the inexact exception are given at the same time,
+ the overflow/underflow exception follows the inexact exception. After
+ each exception we read from the fpscr, to force the exception to be
+ raised immediately. */
+
+ /* There are additional complications because this file may be compiled
+ without VFP support enabled, and we also can't assume that the
+ assembler has VFP instructions enabled. To get around this we use the
+ generic coprocessor mnemonics and avoid asking GCC to put float values
+ in VFP registers. */
+
+ /* First: invalid exception. */
+ if (FE_INVALID & excepts)
+ __asm__ __volatile__ (
+ "ldc p10, cr0, %1\n\t" /* flds s0, %1 */
+ "cdp p10, 8, cr0, cr0, cr0, 0\n\t" /* fdivs s0, s0, s0 */
+ "mrc p10, 7, %0, cr1, cr0, 0" : "=r" (fpscr) /* fmrx %0, fpscr */
+ : "m" (fp_zero)
+ : "s0");
+
+ /* Next: division by zero. */
+ if (FE_DIVBYZERO & excepts)
+ __asm__ __volatile__ (
+ "ldc p10, cr0, %1\n\t" /* flds s0, %1 */
+ "ldcl p10, cr0, %2\n\t" /* flds s1, %2 */
+ "cdp p10, 8, cr0, cr0, cr0, 1\n\t" /* fdivs s0, s0, s1 */
+ "mrc p10, 7, %0, cr1, cr0, 0" : "=r" (fpscr) /* fmrx %0, fpscr */
+ : "m" (fp_one), "m" (fp_zero)
+ : "s0", "s1");
+
+ /* Next: overflow. */
+ if (FE_OVERFLOW & excepts)
+ /* There's no way to raise overflow without also raising inexact. */
+ __asm__ __volatile__ (
+ "ldc p10, cr0, %1\n\t" /* flds s0, %1 */
+ "ldcl p10, cr0, %2\n\t" /* flds s1, %2 */
+ "cdp p10, 3, cr0, cr0, cr0, 1\n\t" /* fadds s0, s0, s1 */
+ "mrc p10, 7, %0, cr1, cr0, 0" : "=r" (fpscr) /* fmrx %0, fpscr */
+ : "m" (fp_max), "m" (fp_1e32)
+ : "s0", "s1");
+
+ /* Next: underflow. */
+ if (FE_UNDERFLOW & excepts)
+ __asm__ __volatile__ (
+ "ldc p10, cr0, %1\n\t" /* flds s0, %1 */
+ "ldcl p10, cr0, %2\n\t" /* flds s1, %2 */
+ "cdp p10, 8, cr0, cr0, cr0, 1\n\t" /* fdivs s0, s0, s1 */
+ "mrc p10, 7, %0, cr1, cr0, 0" : "=r" (fpscr) /* fmrx %0, fpscr */
+ : "m" (fp_min), "m" (fp_three)
+ : "s0", "s1");
+
+ /* Last: inexact. */
+ if (FE_INEXACT & excepts)
+ __asm__ __volatile__ (
+ "ldc p10, cr0, %1\n\t" /* flds s0, %1 */
+ "ldcl p10, cr0, %2\n\t" /* flds s1, %2 */
+ "cdp p10, 8, cr0, cr0, cr0, 1\n\t" /* fdivs s0, s0, s1 */
+ "mrc p10, 7, %0, cr1, cr0, 0" : "=r" (fpscr) /* fmrx %0, fpscr */
+ : "m" (fp_two), "m" (fp_three)
+ : "s0", "s1");
+
+ /* Success. */
+ return 0;
+ }
+
+ /* Unsupported, so fail unless nothing needs to be done. */
+ return (excepts != 0);
+}
+
+libm_hidden_def (feraiseexcept)
diff --git a/ports/sysdeps/arm/frame.h b/ports/sysdeps/arm/frame.h
new file mode 100644
index 0000000000..a98729b688
--- /dev/null
+++ b/ports/sysdeps/arm/frame.h
@@ -0,0 +1,27 @@
+/* Definition of stack frame structure. ARM/APCS version.
+ Copyright (C) 2000, 2002 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.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 is the APCS stack backtrace structure. */
+struct layout
+{
+ struct layout *__unbounded next;
+ void *__unbounded sp;
+ void *__unbounded return_address;
+};
+
+#define FIRST_FRAME_POINTER ADVANCE_STACK_FRAME (__builtin_frame_address (0))
diff --git a/ports/sysdeps/arm/framestate.c b/ports/sysdeps/arm/framestate.c
new file mode 100644
index 0000000000..710cecca97
--- /dev/null
+++ b/ports/sysdeps/arm/framestate.c
@@ -0,0 +1 @@
+/* Empty */
diff --git a/ports/sysdeps/arm/fsetexcptflg.c b/ports/sysdeps/arm/fsetexcptflg.c
new file mode 100644
index 0000000000..bee51a96a2
--- /dev/null
+++ b/ports/sysdeps/arm/fsetexcptflg.c
@@ -0,0 +1,59 @@
+/* Set floating-point environment exception handling.
+ Copyright (C) 1997,98,99,2000,01,05,08,11 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <fenv.h>
+#include <math.h>
+#include <fpu_control.h>
+
+#include <unistd.h>
+#include <ldsodefs.h>
+#include <dl-procinfo.h>
+#include <sysdep.h>
+
+int
+__fesetexceptflag (const fexcept_t *flagp, int excepts)
+{
+ if (GLRO (dl_hwcap) & HWCAP_ARM_VFP)
+ {
+ fexcept_t temp;
+
+ /* Get the current environment. */
+ _FPU_GETCW (temp);
+
+ /* Set the desired exception mask. */
+ temp &= ~(excepts & FE_ALL_EXCEPT);
+ temp |= (*flagp & excepts & FE_ALL_EXCEPT);
+
+ /* Save state back to the FPU. */
+ _FPU_SETCW (temp);
+
+ /* Success. */
+ return 0;
+ }
+
+ /* Unsupported, so fail unless nothing needs to be done. */
+ return (excepts != 0);
+}
+
+#include <shlib-compat.h>
+#if SHLIB_COMPAT (libm, GLIBC_2_1, GLIBC_2_2)
+strong_alias (__fesetexceptflag, __old_fesetexceptflag)
+compat_symbol (libm, __old_fesetexceptflag, fesetexceptflag, GLIBC_2_1);
+#endif
+
+versioned_symbol (libm, __fesetexceptflag, fesetexceptflag, GLIBC_2_2);
diff --git a/ports/sysdeps/arm/ftestexcept.c b/ports/sysdeps/arm/ftestexcept.c
new file mode 100644
index 0000000000..06817d2fe0
--- /dev/null
+++ b/ports/sysdeps/arm/ftestexcept.c
@@ -0,0 +1,43 @@
+/* Test exception in current environment.
+ Copyright (C) 1997, 1998, 2005, 2010 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+#include <unistd.h>
+#include <ldsodefs.h>
+#include <dl-procinfo.h>
+#include <sysdep.h>
+
+int
+fetestexcept (int excepts)
+{
+ if (GLRO (dl_hwcap) & HWCAP_ARM_VFP)
+ {
+ fexcept_t temp;
+
+ /* Get current exceptions. */
+ _FPU_GETCW(temp);
+
+ return temp & excepts & FE_ALL_EXCEPT;
+ }
+
+ /* Unsupported, return 0. */
+ return 0;
+}
+libm_hidden_def (fetestexcept)
diff --git a/ports/sysdeps/arm/gccframe.h b/ports/sysdeps/arm/gccframe.h
new file mode 100644
index 0000000000..166d8fb59b
--- /dev/null
+++ b/ports/sysdeps/arm/gccframe.h
@@ -0,0 +1,21 @@
+/* Definition of object in frame unwind info. arm version.
+ Copyright (C) 2001 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 FIRST_PSEUDO_REGISTER 27
+
+#include <sysdeps/generic/gccframe.h>
diff --git a/ports/sysdeps/arm/gmp-mparam.h b/ports/sysdeps/arm/gmp-mparam.h
new file mode 100644
index 0000000000..b391b68f06
--- /dev/null
+++ b/ports/sysdeps/arm/gmp-mparam.h
@@ -0,0 +1,36 @@
+/* gmp-mparam.h -- Compiler/machine parameter header file.
+
+Copyright (C) 1991, 1993, 1994, 1995, 2005 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP 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 MP 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 MP Library. If not, see <http://www.gnu.org/licenses/>. */
+
+#define BITS_PER_MP_LIMB 32
+#define BYTES_PER_MP_LIMB 4
+#define BITS_PER_LONGINT 32
+#define BITS_PER_INT 32
+#define BITS_PER_SHORTINT 16
+#define BITS_PER_CHAR 8
+
+#if defined(__ARMEB__)
+# define IEEE_DOUBLE_MIXED_ENDIAN 0
+# define IEEE_DOUBLE_BIG_ENDIAN 1
+#elif defined(__VFP_FP__)
+# define IEEE_DOUBLE_MIXED_ENDIAN 0
+# define IEEE_DOUBLE_BIG_ENDIAN 0
+#else
+# define IEEE_DOUBLE_BIG_ENDIAN 0
+# define IEEE_DOUBLE_MIXED_ENDIAN 1
+#endif
diff --git a/ports/sysdeps/arm/jmpbuf-offsets.h b/ports/sysdeps/arm/jmpbuf-offsets.h
new file mode 100644
index 0000000000..642a9657d5
--- /dev/null
+++ b/ports/sysdeps/arm/jmpbuf-offsets.h
@@ -0,0 +1,19 @@
+/* Private macros for accessing __jmp_buf contents. ARM EABI version.
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#define __JMP_BUF_SP 8
diff --git a/ports/sysdeps/arm/jmpbuf-unwind.h b/ports/sysdeps/arm/jmpbuf-unwind.h
new file mode 100644
index 0000000000..d3a58d03a2
--- /dev/null
+++ b/ports/sysdeps/arm/jmpbuf-unwind.h
@@ -0,0 +1,35 @@
+/* Copyright (C) 2005,2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <setjmp.h>
+#include <jmpbuf-offsets.h>
+#include <stdint.h>
+#include <unwind.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[__JMP_BUF_SP]))
+
+#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \
+ _JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), _adj)
+
+#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \
+ ((uintptr_t) (_address) - (_adj) < (uintptr_t) (_jmpbuf)[__JMP_BUF_SP] - (_adj))
+
+/* We use the normal longjmp for unwinding. */
+#define __libc_unwind_longjmp(buf, val) __libc_longjmp (buf, val)
diff --git a/ports/sysdeps/arm/ldsodefs.h b/ports/sysdeps/arm/ldsodefs.h
new file mode 100644
index 0000000000..aa323d3ecd
--- /dev/null
+++ b/ports/sysdeps/arm/ldsodefs.h
@@ -0,0 +1,40 @@
+/* Run-time dynamic linker data structures for loaded ELF shared objects.
+ Copyright (C) 2005 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _ARM_LDSODEFS_H
+#define _ARM_LDSODEFS_H 1
+
+#include <elf.h>
+
+struct La_arm_regs;
+struct La_arm_retval;
+
+#define ARCH_PLTENTER_MEMBERS \
+ Elf32_Addr (*arm_gnu_pltenter) (Elf32_Sym *, unsigned int, uintptr_t *, \
+ uintptr_t *, struct La_arm_regs *, \
+ unsigned int *, const char *, \
+ long int *)
+
+#define ARCH_PLTEXIT_MEMBERS \
+ Elf32_Addr (*arm_gnu_pltexit) (Elf32_Sym *, unsigned int, uintptr_t *, \
+ uintptr_t *, struct La_arm_regs *, \
+ struct La_arm_retval *, const char *)
+
+#include_next <ldsodefs.h>
+
+#endif
diff --git a/ports/sysdeps/arm/libc-tls.c b/ports/sysdeps/arm/libc-tls.c
new file mode 100644
index 0000000000..747de1c995
--- /dev/null
+++ b/ports/sysdeps/arm/libc-tls.c
@@ -0,0 +1,32 @@
+/* Thread-local storage handling in the ELF dynamic linker. ARM version.
+ Copyright (C) 2005, 2011 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <csu/libc-tls.c>
+#include <dl-tls.h>
+
+/* On ARM, linker optimizations are not required, so __tls_get_addr
+ can be called even in statically linked binaries. In this case module
+ must be always 1 and PT_TLS segment exist in the binary, otherwise it
+ would not link. */
+
+void *
+__tls_get_addr (tls_index *ti)
+{
+ dtv_t *dtv = THREAD_DTV ();
+ return (char *) dtv[1].pointer.val + ti->ti_offset;
+}
diff --git a/ports/sysdeps/arm/libm-test-ulps b/ports/sysdeps/arm/libm-test-ulps
new file mode 100644
index 0000000000..51356dddb6
--- /dev/null
+++ b/ports/sysdeps/arm/libm-test-ulps
@@ -0,0 +1,1845 @@
+# Begin of automatic generation
+
+# acos_downward
+Test "acos_downward (-0) == pi/2":
+float: 1
+ifloat: 1
+Test "acos_downward (-0.5) == M_PI_6l*4.0":
+double: 1
+idouble: 1
+Test "acos_downward (-1) == pi":
+float: 1
+ifloat: 1
+Test "acos_downward (0) == pi/2":
+float: 1
+ifloat: 1
+Test "acos_downward (0.5) == M_PI_6l*2.0":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+# acos_towardzero
+Test "acos_towardzero (-0) == pi/2":
+float: 1
+ifloat: 1
+Test "acos_towardzero (-0.5) == M_PI_6l*4.0":
+double: 1
+idouble: 1
+Test "acos_towardzero (-1) == pi":
+float: 1
+ifloat: 1
+Test "acos_towardzero (0) == pi/2":
+float: 1
+ifloat: 1
+Test "acos_towardzero (0.5) == M_PI_6l*2.0":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+# asin_downward
+Test "asin_downward (-0.5) == -pi/6":
+double: 1
+idouble: 1
+Test "asin_downward (0.5) == pi/6":
+double: 1
+idouble: 1
+Test "asin_downward (1.0) == pi/2":
+float: 1
+ifloat: 1
+
+# asin_towardzero
+Test "asin_towardzero (-0.5) == -pi/6":
+double: 1
+idouble: 1
+Test "asin_towardzero (-1.0) == -pi/2":
+float: 1
+ifloat: 1
+Test "asin_towardzero (0.5) == pi/6":
+double: 1
+idouble: 1
+Test "asin_towardzero (1.0) == pi/2":
+float: 1
+ifloat: 1
+
+# asin_upward
+Test "asin_upward (-1.0) == -pi/2":
+float: 1
+ifloat: 1
+
+# 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
+
+# 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 (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 "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_downward
+Test "cos_downward (1) == 0.5403023058681397174009366074429766037323":
+float: 1
+ifloat: 1
+Test "cos_downward (2) == -0.4161468365471423869975682295007621897660":
+float: 1
+ifloat: 1
+Test "cos_downward (3) == -0.9899924966004454572715727947312613023937":
+float: 1
+ifloat: 1
+Test "cos_downward (4) == -0.6536436208636119146391681830977503814241":
+float: 1
+ifloat: 1
+Test "cos_downward (5) == 0.2836621854632262644666391715135573083344":
+float: 1
+ifloat: 1
+Test "cos_downward (7) == 0.7539022543433046381411975217191820122183":
+float: 1
+ifloat: 1
+Test "cos_downward (8) == -0.1455000338086135258688413818311946826093":
+float: 1
+ifloat: 1
+
+# cos_tonearest
+Test "cos_tonearest (7) == 0.7539022543433046381411975217191820122183":
+float: 1
+ifloat: 1
+
+# cos_towardzero
+Test "cos_towardzero (2) == -0.4161468365471423869975682295007621897660":
+float: 1
+ifloat: 1
+Test "cos_towardzero (3) == -0.9899924966004454572715727947312613023937":
+float: 1
+ifloat: 1
+Test "cos_towardzero (5) == 0.2836621854632262644666391715135573083344":
+float: 1
+ifloat: 1
+Test "cos_towardzero (7) == 0.7539022543433046381411975217191820122183":
+float: 1
+ifloat: 1
+Test "cos_towardzero (8) == -0.1455000338086135258688413818311946826093":
+float: 1
+ifloat: 1
+
+# cos_upward
+Test "cos_upward (10) == -0.8390715290764524522588639478240648345199":
+float: 1
+ifloat: 1
+Test "cos_upward (6) == 0.9601702866503660205456522979229244054519":
+float: 1
+ifloat: 1
+Test "cos_upward (7) == 0.7539022543433046381411975217191820122183":
+float: 1
+ifloat: 1
+Test "cos_upward (9) == -0.9111302618846769883682947111811653112463":
+float: 2
+ifloat: 2
+
+# cosh_downward
+Test "cosh_downward (22) == 1792456423.065795780980053377632656584997":
+float: 1
+ifloat: 1
+Test "cosh_downward (23) == 4872401723.124451300068625740569997090344":
+float: 1
+ifloat: 1
+Test "cosh_downward (24) == 13244561064.92173614708845674912733665919":
+float: 1
+ifloat: 1
+
+# cosh_towardzero
+Test "cosh_towardzero (22) == 1792456423.065795780980053377632656584997":
+float: 1
+ifloat: 1
+Test "cosh_towardzero (23) == 4872401723.124451300068625740569997090344":
+float: 1
+ifloat: 1
+Test "cosh_towardzero (24) == 13244561064.92173614708845674912733665919":
+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
+
+# 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 (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
+
+# exp_downward
+Test "exp_downward (2) == e^2":
+float: 1
+ifloat: 1
+Test "exp_downward (3) == e^3":
+float: 1
+ifloat: 1
+
+# exp_towardzero
+Test "exp_towardzero (2) == e^2":
+float: 1
+ifloat: 1
+Test "exp_towardzero (3) == e^3":
+float: 1
+ifloat: 1
+
+# exp_upward
+Test "exp_upward (1) == e":
+float: 1
+ifloat: 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
+
+# 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
+
+# pow_downward
+Test "pow_downward (1.5, 1.03125) == 1.519127098714743184071644334163037684948":
+float: 1
+ifloat: 1
+
+# pow_towardzero
+Test "pow_towardzero (1.5, 1.03125) == 1.519127098714743184071644334163037684948":
+float: 1
+ifloat: 1
+
+# pow_upward
+Test "pow_upward (1.0625, 1.125) == 1.070582293028761362162622578677070098674":
+float: 1
+ifloat: 1
+
+# sin_downward
+Test "sin_downward (10) == -0.5440211108893698134047476618513772816836":
+float: 1
+ifloat: 1
+Test "sin_downward (3) == 0.1411200080598672221007448028081102798469":
+float: 1
+ifloat: 1
+Test "sin_downward (5) == -0.9589242746631384688931544061559939733525":
+float: 1
+ifloat: 1
+Test "sin_downward (6) == -0.2794154981989258728115554466118947596280":
+float: 1
+ifloat: 1
+
+# sin_tonearest
+Test "sin_tonearest (1) == 0.8414709848078965066525023216302989996226":
+float: 1
+ifloat: 1
+
+# sin_towardzero
+Test "sin_towardzero (1) == 0.8414709848078965066525023216302989996226":
+float: 1
+ifloat: 1
+Test "sin_towardzero (10) == -0.5440211108893698134047476618513772816836":
+float: 1
+ifloat: 1
+Test "sin_towardzero (4) == -0.7568024953079282513726390945118290941359":
+float: 1
+ifloat: 1
+Test "sin_towardzero (5) == -0.9589242746631384688931544061559939733525":
+float: 1
+ifloat: 1
+Test "sin_towardzero (9) == 0.4121184852417565697562725663524351793439":
+float: 1
+ifloat: 1
+
+# sin_upward
+Test "sin_upward (1) == 0.8414709848078965066525023216302989996226":
+float: 1
+ifloat: 1
+Test "sin_upward (2) == 0.9092974268256816953960198659117448427023":
+float: 2
+ifloat: 2
+Test "sin_upward (4) == -0.7568024953079282513726390945118290941359":
+float: 1
+ifloat: 1
+Test "sin_upward (9) == 0.4121184852417565697562725663524351793439":
+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
+
+# sinh_downward
+Test "sinh_downward (22) == 1792456423.065795780701106568345764104225":
+float: 1
+ifloat: 1
+Test "sinh_downward (23) == 4872401723.124451299966006944252978187305":
+float: 1
+ifloat: 1
+Test "sinh_downward (24) == 13244561064.92173614705070540368454568168":
+float: 1
+ifloat: 1
+
+# sinh_towardzero
+Test "sinh_towardzero (22) == 1792456423.065795780701106568345764104225":
+float: 1
+ifloat: 1
+Test "sinh_towardzero (23) == 4872401723.124451299966006944252978187305":
+float: 1
+ifloat: 1
+Test "sinh_towardzero (24) == 13244561064.92173614705070540368454568168":
+float: 1
+ifloat: 1
+
+# tan_downward
+Test "tan_downward (1) == 1.5574077246549022305069748074583601730873":
+float: 1
+ifloat: 1
+Test "tan_downward (10) == 0.6483608274590866712591249330098086768169":
+float: 1
+ifloat: 1
+Test "tan_downward (2) == -2.1850398632615189916433061023136825434320":
+float: 1
+ifloat: 1
+Test "tan_downward (6) == -0.2910061913847491570536995888681755428312":
+float: 1
+ifloat: 1
+Test "tan_downward (8) == -6.7997114552203786999252627596086333648814":
+float: 1
+ifloat: 1
+Test "tan_downward (9) == -0.4523156594418098405903708757987855343087":
+float: 1
+ifloat: 1
+
+# tan_towardzero
+Test "tan_towardzero (10) == 0.6483608274590866712591249330098086768169":
+float: 1
+ifloat: 1
+Test "tan_towardzero (3) == -0.1425465430742778052956354105339134932261":
+float: 1
+ifloat: 1
+Test "tan_towardzero (4) == 1.1578212823495775831373424182673239231198":
+float: 1
+ifloat: 1
+Test "tan_towardzero (5) == -3.3805150062465856369827058794473439087096":
+float: 1
+ifloat: 1
+Test "tan_towardzero (9) == -0.4523156594418098405903708757987855343087":
+float: 1
+ifloat: 1
+
+# tan_upward
+Test "tan_upward (1) == 1.5574077246549022305069748074583601730873":
+float: 1
+ifloat: 1
+Test "tan_upward (10) == 0.6483608274590866712591249330098086768169":
+float: 1
+ifloat: 1
+Test "tan_upward (3) == -0.1425465430742778052956354105339134932261":
+float: 1
+ifloat: 1
+Test "tan_upward (5) == -3.3805150062465856369827058794473439087096":
+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: "acos_downward":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: "acos_towardzero":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: "asin_downward":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: "asin_towardzero":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: "asin_upward":
+float: 1
+ifloat: 1
+
+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_downward":
+float: 1
+ifloat: 1
+
+Function: "cos_tonearest":
+float: 1
+ifloat: 1
+
+Function: "cos_towardzero":
+float: 1
+ifloat: 1
+
+Function: "cos_upward":
+float: 2
+ifloat: 2
+
+Function: "cosh_downward":
+float: 1
+ifloat: 1
+
+Function: "cosh_towardzero":
+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: "exp_downward":
+float: 1
+ifloat: 1
+
+Function: "exp_towardzero":
+float: 1
+ifloat: 1
+
+Function: "exp_upward":
+float: 1
+ifloat: 1
+
+Function: "expm1":
+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: "pow_downward":
+float: 1
+ifloat: 1
+
+Function: "pow_towardzero":
+float: 1
+ifloat: 1
+
+Function: "pow_upward":
+float: 1
+ifloat: 1
+
+Function: "sin_downward":
+float: 1
+ifloat: 1
+
+Function: "sin_tonearest":
+float: 1
+ifloat: 1
+
+Function: "sin_towardzero":
+float: 1
+ifloat: 1
+
+Function: "sin_upward":
+float: 2
+ifloat: 2
+
+Function: "sincos":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: "sinh_downward":
+float: 1
+ifloat: 1
+
+Function: "sinh_towardzero":
+float: 1
+ifloat: 1
+
+Function: "tan":
+double: 1
+idouble: 1
+
+Function: "tan_downward":
+float: 1
+ifloat: 1
+
+Function: "tan_towardzero":
+float: 1
+ifloat: 1
+
+Function: "tan_upward":
+float: 1
+ifloat: 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/arm/machine-gmon.h b/ports/sysdeps/arm/machine-gmon.h
new file mode 100644
index 0000000000..671d6b176b
--- /dev/null
+++ b/ports/sysdeps/arm/machine-gmon.h
@@ -0,0 +1,33 @@
+/* Machine-dependent definitions for profiling support. ARM EABI version.
+ Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+
+/* GCC for the ARM cannot compile __builtin_return_address(N) for N != 0,
+ so we must use an assembly stub. */
+
+/* We must not pollute the global namespace. */
+#define mcount_internal __mcount_internal
+
+extern void mcount_internal (u_long frompc, u_long selfpc) internal_function;
+#define _MCOUNT_DECL(frompc, selfpc) \
+ void internal_function mcount_internal (u_long frompc, u_long selfpc)
+
+
+/* Define MCOUNT as empty since we have the implementation in another file. */
+#define MCOUNT
diff --git a/ports/sysdeps/arm/memcpy.S b/ports/sysdeps/arm/memcpy.S
new file mode 100644
index 0000000000..08f7f76ecf
--- /dev/null
+++ b/ports/sysdeps/arm/memcpy.S
@@ -0,0 +1,263 @@
+/* Copyright (C) 2006, 2009 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ Contributed by MontaVista Software, Inc. (written by Nicolas Pitre)
+
+ 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>
+
+/*
+ * Data preload for architectures that support it (ARM V5TE and above)
+ */
+#if (!defined (__ARM_ARCH_2__) && !defined (__ARM_ARCH_3__) \
+ && !defined (__ARM_ARCH_3M__) && !defined (__ARM_ARCH_4__) \
+ && !defined (__ARM_ARCH_4T__) && !defined (__ARM_ARCH_5__) \
+ && !defined (__ARM_ARCH_5T__))
+#define PLD(code...) code
+#else
+#define PLD(code...)
+#endif
+
+/*
+ * This can be used to enable code to cacheline align the source pointer.
+ * Experiments on tested architectures (StrongARM and XScale) didn't show
+ * this a worthwhile thing to do. That might be different in the future.
+ */
+//#define CALGN(code...) code
+#define CALGN(code...)
+
+/*
+ * Endian independent macros for shifting bytes within registers.
+ */
+#ifndef __ARMEB__
+#define pull lsr
+#define push lsl
+#else
+#define pull lsl
+#define push lsr
+#endif
+
+ .text
+
+/* Prototype: void *memcpy(void *dest, const void *src, size_t n); */
+
+ENTRY(memcpy)
+
+ stmfd sp!, {r0, r4, lr}
+ cfi_adjust_cfa_offset (12)
+ cfi_rel_offset (r4, 4)
+ cfi_rel_offset (lr, 8)
+
+ cfi_remember_state
+
+ subs r2, r2, #4
+ blt 8f
+ ands ip, r0, #3
+ PLD( pld [r1, #0] )
+ bne 9f
+ ands ip, r1, #3
+ bne 10f
+
+1: subs r2, r2, #(28)
+ stmfd sp!, {r5 - r8}
+ cfi_adjust_cfa_offset (16)
+ cfi_rel_offset (r5, 0)
+ cfi_rel_offset (r6, 4)
+ cfi_rel_offset (r7, 8)
+ cfi_rel_offset (r8, 12)
+ blt 5f
+
+ CALGN( ands ip, r1, #31 )
+ CALGN( rsb r3, ip, #32 )
+ CALGN( sbcnes r4, r3, r2 ) @ C is always set here
+ CALGN( bcs 2f )
+ CALGN( adr r4, 6f )
+ CALGN( subs r2, r2, r3 ) @ C gets set
+ CALGN( add pc, r4, ip )
+
+ PLD( pld [r1, #0] )
+2: PLD( subs r2, r2, #96 )
+ PLD( pld [r1, #28] )
+ PLD( blt 4f )
+ PLD( pld [r1, #60] )
+ PLD( pld [r1, #92] )
+
+3: PLD( pld [r1, #124] )
+4: ldmia r1!, {r3, r4, r5, r6, r7, r8, ip, lr}
+ subs r2, r2, #32
+ stmia r0!, {r3, r4, r5, r6, r7, r8, ip, lr}
+ bge 3b
+ PLD( cmn r2, #96 )
+ PLD( bge 4b )
+
+5: ands ip, r2, #28
+ rsb ip, ip, #32
+ addne pc, pc, ip @ C is always clear here
+ b 7f
+6: nop
+ ldr r3, [r1], #4
+ ldr r4, [r1], #4
+ ldr r5, [r1], #4
+ ldr r6, [r1], #4
+ ldr r7, [r1], #4
+ ldr r8, [r1], #4
+ ldr lr, [r1], #4
+
+ add pc, pc, ip
+ nop
+ nop
+ str r3, [r0], #4
+ str r4, [r0], #4
+ str r5, [r0], #4
+ str r6, [r0], #4
+ str r7, [r0], #4
+ str r8, [r0], #4
+ str lr, [r0], #4
+
+ CALGN( bcs 2b )
+
+7: ldmfd sp!, {r5 - r8}
+ cfi_adjust_cfa_offset (-16)
+ cfi_restore (r5)
+ cfi_restore (r6)
+ cfi_restore (r7)
+ cfi_restore (r8)
+
+8: movs r2, r2, lsl #31
+ ldrneb r3, [r1], #1
+ ldrcsb r4, [r1], #1
+ ldrcsb ip, [r1]
+ strneb r3, [r0], #1
+ strcsb r4, [r0], #1
+ strcsb ip, [r0]
+
+#if defined (__ARM_ARCH_4T__) && defined(__THUMB_INTERWORK__)
+ ldmfd sp!, {r0, r4, lr}
+ cfi_adjust_cfa_offset (-12)
+ cfi_restore (r4)
+ cfi_restore (lr)
+ bx lr
+#else
+ ldmfd sp!, {r0, r4, pc}
+#endif
+
+ cfi_restore_state
+
+9: rsb ip, ip, #4
+ cmp ip, #2
+ ldrgtb r3, [r1], #1
+ ldrgeb r4, [r1], #1
+ ldrb lr, [r1], #1
+ strgtb r3, [r0], #1
+ strgeb r4, [r0], #1
+ subs r2, r2, ip
+ strb lr, [r0], #1
+ blt 8b
+ ands ip, r1, #3
+ beq 1b
+
+10: bic r1, r1, #3
+ cmp ip, #2
+ ldr lr, [r1], #4
+ beq 17f
+ bgt 18f
+
+
+ .macro forward_copy_shift pull push
+
+ subs r2, r2, #28
+ blt 14f
+
+ CALGN( ands ip, r1, #31 )
+ CALGN( rsb ip, ip, #32 )
+ CALGN( sbcnes r4, ip, r2 ) @ C is always set here
+ CALGN( subcc r2, r2, ip )
+ CALGN( bcc 15f )
+
+11: stmfd sp!, {r5 - r9}
+ cfi_adjust_cfa_offset (20)
+ cfi_rel_offset (r5, 0)
+ cfi_rel_offset (r6, 4)
+ cfi_rel_offset (r7, 8)
+ cfi_rel_offset (r8, 12)
+ cfi_rel_offset (r9, 16)
+
+ PLD( pld [r1, #0] )
+ PLD( subs r2, r2, #96 )
+ PLD( pld [r1, #28] )
+ PLD( blt 13f )
+ PLD( pld [r1, #60] )
+ PLD( pld [r1, #92] )
+
+12: PLD( pld [r1, #124] )
+13: ldmia r1!, {r4, r5, r6, r7}
+ mov r3, lr, pull #\pull
+ subs r2, r2, #32
+ ldmia r1!, {r8, r9, ip, lr}
+ orr r3, r3, r4, push #\push
+ mov r4, r4, pull #\pull
+ orr r4, r4, r5, push #\push
+ mov r5, r5, pull #\pull
+ orr r5, r5, r6, push #\push
+ mov r6, r6, pull #\pull
+ orr r6, r6, r7, push #\push
+ mov r7, r7, pull #\pull
+ orr r7, r7, r8, push #\push
+ mov r8, r8, pull #\pull
+ orr r8, r8, r9, push #\push
+ mov r9, r9, pull #\pull
+ orr r9, r9, ip, push #\push
+ mov ip, ip, pull #\pull
+ orr ip, ip, lr, push #\push
+ stmia r0!, {r3, r4, r5, r6, r7, r8, r9, ip}
+ bge 12b
+ PLD( cmn r2, #96 )
+ PLD( bge 13b )
+
+ ldmfd sp!, {r5 - r9}
+ cfi_adjust_cfa_offset (-20)
+ cfi_restore (r5)
+ cfi_restore (r6)
+ cfi_restore (r7)
+ cfi_restore (r8)
+ cfi_restore (r9)
+
+14: ands ip, r2, #28
+ beq 16f
+
+15: mov r3, lr, pull #\pull
+ ldr lr, [r1], #4
+ subs ip, ip, #4
+ orr r3, r3, lr, push #\push
+ str r3, [r0], #4
+ bgt 15b
+ CALGN( cmp r2, #0 )
+ CALGN( bge 11b )
+
+16: sub r1, r1, #(\push / 8)
+ b 8b
+
+ .endm
+
+
+ forward_copy_shift pull=8 push=24
+
+17: forward_copy_shift pull=16 push=16
+
+18: forward_copy_shift pull=24 push=8
+
+END(memcpy)
+libc_hidden_builtin_def (memcpy)
diff --git a/ports/sysdeps/arm/memmove.S b/ports/sysdeps/arm/memmove.S
new file mode 100644
index 0000000000..4ec6567064
--- /dev/null
+++ b/ports/sysdeps/arm/memmove.S
@@ -0,0 +1,279 @@
+/* Copyright (C) 2006, 2008, 2009 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ Contributed by MontaVista Software, Inc. (written by Nicolas Pitre)
+
+ 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>
+
+/*
+ * Data preload for architectures that support it (ARM V5TE and above)
+ */
+#if (!defined (__ARM_ARCH_2__) && !defined (__ARM_ARCH_3__) \
+ && !defined (__ARM_ARCH_3M__) && !defined (__ARM_ARCH_4__) \
+ && !defined (__ARM_ARCH_4T__) && !defined (__ARM_ARCH_5__) \
+ && !defined (__ARM_ARCH_5T__))
+#define PLD(code...) code
+#else
+#define PLD(code...)
+#endif
+
+/*
+ * This can be used to enable code to cacheline align the source pointer.
+ * Experiments on tested architectures (StrongARM and XScale) didn't show
+ * this a worthwhile thing to do. That might be different in the future.
+ */
+//#define CALGN(code...) code
+#define CALGN(code...)
+
+/*
+ * Endian independent macros for shifting bytes within registers.
+ */
+#ifndef __ARMEB__
+#define pull lsr
+#define push lsl
+#else
+#define pull lsl
+#define push lsr
+#endif
+
+ .text
+
+/*
+ * Prototype: void *memmove(void *dest, const void *src, size_t n);
+ *
+ * Note:
+ *
+ * If the memory regions don't overlap, we simply branch to memcpy which is
+ * normally a bit faster. Otherwise the copy is done going downwards.
+ */
+
+ENTRY(memmove)
+
+ subs ip, r0, r1
+ cmphi r2, ip
+#ifdef NOT_IN_libc
+ bls memcpy
+#else
+ bls HIDDEN_JUMPTARGET(memcpy)
+#endif
+
+ stmfd sp!, {r0, r4, lr}
+ cfi_adjust_cfa_offset (12)
+ cfi_rel_offset (r4, 4)
+ cfi_rel_offset (lr, 8)
+
+ cfi_remember_state
+
+ add r1, r1, r2
+ add r0, r0, r2
+ subs r2, r2, #4
+ blt 8f
+ ands ip, r0, #3
+ PLD( pld [r1, #-4] )
+ bne 9f
+ ands ip, r1, #3
+ bne 10f
+
+1: subs r2, r2, #(28)
+ stmfd sp!, {r5 - r8}
+ cfi_adjust_cfa_offset (16)
+ cfi_rel_offset (r5, 0)
+ cfi_rel_offset (r6, 4)
+ cfi_rel_offset (r7, 8)
+ cfi_rel_offset (r8, 12)
+ blt 5f
+
+ CALGN( ands ip, r1, #31 )
+ CALGN( sbcnes r4, ip, r2 ) @ C is always set here
+ CALGN( bcs 2f )
+ CALGN( adr r4, 6f )
+ CALGN( subs r2, r2, ip ) @ C is set here
+ CALGN( add pc, r4, ip )
+
+ PLD( pld [r1, #-4] )
+2: PLD( subs r2, r2, #96 )
+ PLD( pld [r1, #-32] )
+ PLD( blt 4f )
+ PLD( pld [r1, #-64] )
+ PLD( pld [r1, #-96] )
+
+3: PLD( pld [r1, #-128] )
+4: ldmdb r1!, {r3, r4, r5, r6, r7, r8, ip, lr}
+ subs r2, r2, #32
+ stmdb r0!, {r3, r4, r5, r6, r7, r8, ip, lr}
+ bge 3b
+ PLD( cmn r2, #96 )
+ PLD( bge 4b )
+
+5: ands ip, r2, #28
+ rsb ip, ip, #32
+ addne pc, pc, ip @ C is always clear here
+ b 7f
+6: nop
+ ldr r3, [r1, #-4]!
+ ldr r4, [r1, #-4]!
+ ldr r5, [r1, #-4]!
+ ldr r6, [r1, #-4]!
+ ldr r7, [r1, #-4]!
+ ldr r8, [r1, #-4]!
+ ldr lr, [r1, #-4]!
+
+ add pc, pc, ip
+ nop
+ nop
+ str r3, [r0, #-4]!
+ str r4, [r0, #-4]!
+ str r5, [r0, #-4]!
+ str r6, [r0, #-4]!
+ str r7, [r0, #-4]!
+ str r8, [r0, #-4]!
+ str lr, [r0, #-4]!
+
+ CALGN( bcs 2b )
+
+7: ldmfd sp!, {r5 - r8}
+ cfi_adjust_cfa_offset (-16)
+ cfi_restore (r5)
+ cfi_restore (r6)
+ cfi_restore (r7)
+ cfi_restore (r8)
+
+8: movs r2, r2, lsl #31
+ ldrneb r3, [r1, #-1]!
+ ldrcsb r4, [r1, #-1]!
+ ldrcsb ip, [r1, #-1]
+ strneb r3, [r0, #-1]!
+ strcsb r4, [r0, #-1]!
+ strcsb ip, [r0, #-1]
+
+#if defined (__ARM_ARCH_4T__) && defined (__THUMB_INTERWORK__)
+ ldmfd sp!, {r0, r4, lr}
+ cfi_adjust_cfa_offset (-12)
+ cfi_restore (r4)
+ cfi_restore (lr)
+ bx lr
+#else
+ ldmfd sp!, {r0, r4, pc}
+#endif
+
+ cfi_restore_state
+
+9: cmp ip, #2
+ ldrgtb r3, [r1, #-1]!
+ ldrgeb r4, [r1, #-1]!
+ ldrb lr, [r1, #-1]!
+ strgtb r3, [r0, #-1]!
+ strgeb r4, [r0, #-1]!
+ subs r2, r2, ip
+ strb lr, [r0, #-1]!
+ blt 8b
+ ands ip, r1, #3
+ beq 1b
+
+10: bic r1, r1, #3
+ cmp ip, #2
+ ldr r3, [r1, #0]
+ beq 17f
+ blt 18f
+
+
+ .macro backward_copy_shift push pull
+
+ subs r2, r2, #28
+ blt 14f
+
+ CALGN( ands ip, r1, #31 )
+ CALGN( rsb ip, ip, #32 )
+ CALGN( sbcnes r4, ip, r2 ) @ C is always set here
+ CALGN( subcc r2, r2, ip )
+ CALGN( bcc 15f )
+
+11: stmfd sp!, {r5 - r9}
+ cfi_adjust_cfa_offset (20)
+ cfi_rel_offset (r5, 0)
+ cfi_rel_offset (r6, 4)
+ cfi_rel_offset (r7, 8)
+ cfi_rel_offset (r8, 12)
+ cfi_rel_offset (r9, 16)
+
+ PLD( pld [r1, #-4] )
+ PLD( subs r2, r2, #96 )
+ PLD( pld [r1, #-32] )
+ PLD( blt 13f )
+ PLD( pld [r1, #-64] )
+ PLD( pld [r1, #-96] )
+
+12: PLD( pld [r1, #-128] )
+13: ldmdb r1!, {r7, r8, r9, ip}
+ mov lr, r3, push #\push
+ subs r2, r2, #32
+ ldmdb r1!, {r3, r4, r5, r6}
+ orr lr, lr, ip, pull #\pull
+ mov ip, ip, push #\push
+ orr ip, ip, r9, pull #\pull
+ mov r9, r9, push #\push
+ orr r9, r9, r8, pull #\pull
+ mov r8, r8, push #\push
+ orr r8, r8, r7, pull #\pull
+ mov r7, r7, push #\push
+ orr r7, r7, r6, pull #\pull
+ mov r6, r6, push #\push
+ orr r6, r6, r5, pull #\pull
+ mov r5, r5, push #\push
+ orr r5, r5, r4, pull #\pull
+ mov r4, r4, push #\push
+ orr r4, r4, r3, pull #\pull
+ stmdb r0!, {r4 - r9, ip, lr}
+ bge 12b
+ PLD( cmn r2, #96 )
+ PLD( bge 13b )
+
+ ldmfd sp!, {r5 - r9}
+ cfi_adjust_cfa_offset (-20)
+ cfi_restore (r5)
+ cfi_restore (r6)
+ cfi_restore (r7)
+ cfi_restore (r8)
+ cfi_restore (r9)
+
+14: ands ip, r2, #28
+ beq 16f
+
+15: mov lr, r3, push #\push
+ ldr r3, [r1, #-4]!
+ subs ip, ip, #4
+ orr lr, lr, r3, pull #\pull
+ str lr, [r0, #-4]!
+ bgt 15b
+ CALGN( cmp r2, #0 )
+ CALGN( bge 11b )
+
+16: add r1, r1, #(\pull / 8)
+ b 8b
+
+ .endm
+
+
+ backward_copy_shift push=8 pull=24
+
+17: backward_copy_shift push=16 pull=16
+
+18: backward_copy_shift push=24 pull=8
+
+
+END(memmove)
+libc_hidden_builtin_def (memmove)
diff --git a/ports/sysdeps/arm/memset.S b/ports/sysdeps/arm/memset.S
new file mode 100644
index 0000000000..a29031c266
--- /dev/null
+++ b/ports/sysdeps/arm/memset.S
@@ -0,0 +1,64 @@
+/* Copyright (C) 1998, 2003 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Philip Blundell <philb@gnu.org>
+
+ 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>
+
+/* void *memset (dstpp, c, len) */
+
+ENTRY(memset)
+ mov r3, r0
+ cmp r2, #8
+ bcc 2f @ less than 8 bytes to move
+
+1:
+ tst r3, #3 @ aligned yet?
+ strneb r1, [r3], #1
+ subne r2, r2, #1
+ bne 1b
+
+ and r1, r1, #255 @ clear any sign bits
+ orr r1, r1, r1, lsl $8
+ orr r1, r1, r1, lsl $16
+ mov ip, r1
+
+1:
+ subs r2, r2, #8
+ stmcsia r3!, {r1, ip} @ store up to 32 bytes per loop iteration
+ subcss r2, r2, #8
+ stmcsia r3!, {r1, ip}
+ subcss r2, r2, #8
+ stmcsia r3!, {r1, ip}
+ subcss r2, r2, #8
+ stmcsia r3!, {r1, ip}
+ bcs 1b
+
+ and r2, r2, #7
+2:
+ subs r2, r2, #1 @ store up to 4 bytes per loop iteration
+ strcsb r1, [r3], #1
+ subcss r2, r2, #1
+ strcsb r1, [r3], #1
+ subcss r2, r2, #1
+ strcsb r1, [r3], #1
+ subcss r2, r2, #1
+ strcsb r1, [r3], #1
+ bcs 2b
+
+ DO_RET(lr)
+END(memset)
+libc_hidden_builtin_def (memset)
diff --git a/ports/sysdeps/arm/memusage.h b/ports/sysdeps/arm/memusage.h
new file mode 100644
index 0000000000..08a25425b9
--- /dev/null
+++ b/ports/sysdeps/arm/memusage.h
@@ -0,0 +1,20 @@
+/* Copyright (C) 2000 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 GETSP() ({ register uintptr_t stack_ptr asm ("sp"); stack_ptr; })
+
+#include <sysdeps/generic/memusage.h>
diff --git a/ports/sysdeps/arm/nptl/Makefile b/ports/sysdeps/arm/nptl/Makefile
new file mode 100644
index 0000000000..e2497397cb
--- /dev/null
+++ b/ports/sysdeps/arm/nptl/Makefile
@@ -0,0 +1,20 @@
+# Copyright (C) 2005 Free Software Foundation, Inc.
+# This file is part of the GNU C Library.
+#
+# The GNU C Library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# The GNU C Library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with the GNU C Library. If not, see
+# <http://www.gnu.org/licenses/>.
+
+ifeq ($(subdir),csu)
+gen-as-const-headers += tcb-offsets.sym
+endif
diff --git a/ports/sysdeps/arm/nptl/pthread_spin_lock.c b/ports/sysdeps/arm/nptl/pthread_spin_lock.c
new file mode 100644
index 0000000000..3a23bd31a5
--- /dev/null
+++ b/ports/sysdeps/arm/nptl/pthread_spin_lock.c
@@ -0,0 +1,29 @@
+/* Copyright (C) 2008 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <atomic.h>
+#include "pthreadP.h"
+
+int
+pthread_spin_lock (pthread_spinlock_t *lock)
+{
+ while (atomic_compare_and_exchange_val_acq (lock, 1, 0) != 0)
+ while (*lock != 0)
+ ;
+
+ return 0;
+}
diff --git a/ports/sysdeps/arm/nptl/pthread_spin_trylock.c b/ports/sysdeps/arm/nptl/pthread_spin_trylock.c
new file mode 100644
index 0000000000..7d3118071e
--- /dev/null
+++ b/ports/sysdeps/arm/nptl/pthread_spin_trylock.c
@@ -0,0 +1,26 @@
+/* Copyright (C) 2008 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <atomic.h>
+#include "pthreadP.h"
+
+int
+pthread_spin_trylock (pthread_spinlock_t *lock)
+{
+ return atomic_compare_and_exchange_val_acq (lock, 1, 0) ? EBUSY : 0;
+}
diff --git a/ports/sysdeps/arm/nptl/pthreaddef.h b/ports/sysdeps/arm/nptl/pthreaddef.h
new file mode 100644
index 0000000000..5385b24167
--- /dev/null
+++ b/ports/sysdeps/arm/nptl/pthreaddef.h
@@ -0,0 +1,46 @@
+/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+/* Default stack size. */
+#define ARCH_STACK_DEFAULT_SIZE (2 * 1024 * 1024)
+
+/* Required stack pointer alignment at beginning. SSE requires 16
+ bytes. */
+#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.
+
+ __builtin_frame_address (0) returns the value of the hard frame
+ pointer, which will point at the location of the saved PC on the
+ stack. Below this in memory is the remainder of the linkage info,
+ occupying 12 bytes. Therefore in order to address from
+ CURRENT_STACK_FRAME using "struct layout", we need to have the macro
+ return the hard FP minus 12. Of course, this makes no sense
+ without the obsolete APCS stack layout... */
+#define CURRENT_STACK_FRAME (__builtin_frame_address (0) - 12)
+
+
+/* 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/arm/nptl/tcb-offsets.sym b/ports/sysdeps/arm/nptl/tcb-offsets.sym
new file mode 100644
index 0000000000..92cc441d3d
--- /dev/null
+++ b/ports/sysdeps/arm/nptl/tcb-offsets.sym
@@ -0,0 +1,11 @@
+#include <sysdep.h>
+#include <tls.h>
+
+--
+
+-- Derive offsets relative to the thread register.
+#define thread_offsetof(mem) (long)(offsetof(struct pthread, mem) - sizeof(struct pthread))
+
+MULTIPLE_THREADS_OFFSET thread_offsetof (header.multiple_threads)
+PID_OFFSET thread_offsetof (pid)
+TID_OFFSET thread_offsetof (tid)
diff --git a/ports/sysdeps/arm/nptl/tls.h b/ports/sysdeps/arm/nptl/tls.h
new file mode 100644
index 0000000000..52f695e58b
--- /dev/null
+++ b/ports/sysdeps/arm/nptl/tls.h
@@ -0,0 +1,151 @@
+/* Definition for thread-local data handling. NPTL/ARM version.
+ Copyright (C) 2005, 2007, 2011 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _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
+
+/* Get the thread descriptor definition. */
+# include <nptl/descr.h>
+
+typedef struct
+{
+ dtv_t *dtv;
+ void *private;
+} tcbhead_t;
+
+/* This is the size of the initial TCB. */
+# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t)
+
+/* Alignment requirements for the initial TCB. */
+# define TLS_INIT_TCB_ALIGN 16
+
+/* This is the size of the TCB. */
+# define TLS_TCB_SIZE sizeof (tcbhead_t)
+
+/* This is the size we need before TCB. */
+# define TLS_PRE_TCB_SIZE sizeof (struct pthread)
+
+/* Alignment requirements for the TCB. */
+# define TLS_TCB_ALIGN 16
+
+/* Install the dtv pointer. The pointer passed is to the element with
+ index -1 which contain the length. */
+# define INSTALL_DTV(tcbp, dtvp) \
+ (((tcbhead_t *) (tcbp))->dtv = (dtvp) + 1)
+
+/* Install new dtv for current thread. */
+# define INSTALL_NEW_DTV(dtv) \
+ (THREAD_DTV() = (dtv))
+
+/* Return dtv of given thread descriptor. */
+# define GET_DTV(tcbp) \
+ (((tcbhead_t *) (tcbp))->dtv)
+
+/* Code to initially initialize the thread pointer. This might need
+ special attention since 'errno' is not yet available and if the
+ operation can cause a failure 'errno' must not be touched. */
+# define TLS_INIT_TP(tcbp, secondcall) \
+ ({ INTERNAL_SYSCALL_DECL (err); \
+ long result_var; \
+ result_var = INTERNAL_SYSCALL_ARM (set_tls, err, 1, (tcbp)); \
+ INTERNAL_SYSCALL_ERROR_P (result_var, err) \
+ ? "unknown error" : NULL; })
+
+/* Return the address of the dtv for the current thread. */
+# define THREAD_DTV() \
+ (((tcbhead_t *) __builtin_thread_pointer ())->dtv)
+
+/* Return the thread descriptor for the current thread. */
+# define THREAD_SELF \
+ ((struct pthread *)__builtin_thread_pointer () - 1)
+
+/* Magic for libthread_db to know how to do THREAD_SELF. */
+# define DB_THREAD_SELF \
+ CONST_THREAD_AREA (32, sizeof (struct pthread))
+
+/* Access to data in the thread descriptor is easy. */
+#define THREAD_GETMEM(descr, member) \
+ descr->member
+#define THREAD_GETMEM_NC(descr, member, idx) \
+ descr->member[idx]
+#define THREAD_SETMEM(descr, member, value) \
+ descr->member = (value)
+#define THREAD_SETMEM_NC(descr, member, idx, value) \
+ descr->member[idx] = (value)
+
+/* Initializing the thread pointer will generate a SIGILL if the syscall
+ is not available. */
+#define TLS_INIT_TP_EXPENSIVE 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/arm/preconfigure b/ports/sysdeps/arm/preconfigure
new file mode 100644
index 0000000000..d98c167a95
--- /dev/null
+++ b/ports/sysdeps/arm/preconfigure
@@ -0,0 +1,50 @@
+case "$machine" in
+arm*)
+ base_machine=arm
+ case $config_os in
+ linux-gnueabi*)
+ # Lets ask the compiler which ARM family we've got
+ # Unfortunately it doesn't define any flags for implementations
+ # that you might pass to -mcpu or -mtune
+ # Note if you add patterns here you must ensure that
+ # an appropriate directory exists in sysdeps/arm
+ archcppflag=`echo "" |
+ $CC $CFLAGS $CPPFLAGS -E -dM - |
+ grep __ARM_ARCH |
+ sed -e 's/^#define //' -e 's/ .*//'`
+
+ case x$archcppflag in
+ x__ARM_ARCH_[89]*__)
+ machine=armv7
+ echo "Found compiler is configured for something newer than v7 - using v7"
+ ;;
+
+ x__ARM_ARCH_7A__)
+ machine=armv7
+ echo "Found compiler is configured for $machine"
+ ;;
+
+ x__ARM_ARCH_6T2__)
+ machine=armv6t2
+ echo "Found compiler is configured for $machine"
+ ;;
+
+ *)
+ machine=arm
+ echo 2>&1 "arm/preconfigure: Did not find ARM architecture type; using default"
+ ;;
+ esac
+
+ machine=arm/$machine
+ if [ "${CFLAGS+set}" != "set" ]; then
+ CFLAGS="-g -O2"
+ fi
+ CFLAGS="$CFLAGS -fno-unwind-tables"
+ ;;
+ *)
+ echo "Old ABI no longer supported" 2>&1
+ exit 1
+ ;;
+ esac
+ ;;
+esac
diff --git a/ports/sysdeps/arm/rtld-global-offsets.sym b/ports/sysdeps/arm/rtld-global-offsets.sym
new file mode 100644
index 0000000000..ff4e97f2a6
--- /dev/null
+++ b/ports/sysdeps/arm/rtld-global-offsets.sym
@@ -0,0 +1,7 @@
+#define SHARED 1
+
+#include <ldsodefs.h>
+
+#define rtld_global_ro_offsetof(mem) offsetof (struct rtld_global_ro, mem)
+
+RTLD_GLOBAL_RO_DL_HWCAP_OFFSET rtld_global_ro_offsetof (_dl_hwcap)
diff --git a/ports/sysdeps/arm/setfpucw.c b/ports/sysdeps/arm/setfpucw.c
new file mode 100644
index 0000000000..d0cea32b9d
--- /dev/null
+++ b/ports/sysdeps/arm/setfpucw.c
@@ -0,0 +1,46 @@
+/* Set the FPU control word.
+ Copyright (C) 1996, 1997, 1999, 2005 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <math.h>
+#include <fpu_control.h>
+
+#include <unistd.h>
+#include <ldsodefs.h>
+#include <dl-procinfo.h>
+#include <sysdep.h>
+
+void
+__setfpucw (fpu_control_t set)
+{
+ if (GLRO (dl_hwcap) & HWCAP_ARM_VFP)
+ {
+ fpu_control_t cw;
+
+ /* Fetch the current control word. */
+ _FPU_GETCW (cw);
+
+ /* Preserve the reserved bits, and set the rest as the user
+ specified (or the default, if the user gave zero). */
+ cw &= _FPU_RESERVED;
+ cw |= set & ~_FPU_RESERVED;
+
+ _FPU_SETCW (cw);
+ }
+
+ /* Do nothing if a VFP unit isn't present. */
+}
diff --git a/ports/sysdeps/arm/setjmp.S b/ports/sysdeps/arm/setjmp.S
new file mode 100644
index 0000000000..5e3f39cc75
--- /dev/null
+++ b/ports/sysdeps/arm/setjmp.S
@@ -0,0 +1,98 @@
+/* setjmp for ARM.
+ Copyright (C) 1997, 1998, 2005, 2006, 2008 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#define _SETJMP_H
+#define _ASM
+#include <bits/setjmp.h>
+#include <rtld-global-offsets.h>
+
+ENTRY (__sigsetjmp)
+ mov ip, r0
+
+ /* Save registers */
+ stmia ip!, {v1-v6, sl, fp, sp, lr}
+
+ /* Check if we have a VFP unit. */
+#ifdef IS_IN_rtld
+ ldr a3, 1f
+ ldr a4, Lrtld_local_ro
+0: add a3, pc, a3
+ add a3, a3, a4
+ ldr a3, [a3, #RTLD_GLOBAL_RO_DL_HWCAP_OFFSET]
+#else
+#ifdef PIC
+ ldr a3, 1f
+ ldr a4, Lrtld_global_ro
+0: add a3, pc, a3
+ ldr a3, [a3, a4]
+ ldr a3, [a3, #RTLD_GLOBAL_RO_DL_HWCAP_OFFSET]
+#else
+ ldr a3, Lhwcap
+ ldr a3, [a3, #0]
+#endif
+#endif
+
+ tst a3, #HWCAP_ARM_VFP
+ beq Lno_vfp
+
+ /* Store the VFP registers.
+ Don't use VFP instructions directly because this code
+ is used in non-VFP multilibs. */
+ /* Following instruction is vstmia ip!, {d8-d15}. */
+ stc p11, cr8, [ip], #64
+ /* Store the floating-point status register. */
+ /* Following instruction is vmrs a4, fpscr. */
+ mrc p10, 7, a4, cr1, cr0, 0
+ str a4, [ip], #4
+Lno_vfp:
+
+ tst a3, #HWCAP_ARM_IWMMXT
+ beq Lno_iwmmxt
+
+ /* Save the call-preserved iWMMXt registers. */
+ /* Following instructions are wstrd wr10, [ip], #8 (etc.) */
+ stcl p1, cr10, [r12], #8
+ stcl p1, cr11, [r12], #8
+ stcl p1, cr12, [r12], #8
+ stcl p1, cr13, [r12], #8
+ stcl p1, cr14, [r12], #8
+ stcl p1, cr15, [r12], #8
+Lno_iwmmxt:
+
+ /* Make a tail call to __sigjmp_save; it takes the same args. */
+ B PLTJMP(C_SYMBOL_NAME(__sigjmp_save))
+
+#ifdef IS_IN_rtld
+1: .long _GLOBAL_OFFSET_TABLE_ - 0b - 8
+Lrtld_local_ro:
+ .long C_SYMBOL_NAME(_rtld_local_ro)(GOTOFF)
+#else
+#ifdef PIC
+1: .long _GLOBAL_OFFSET_TABLE_ - 0b - 8
+Lrtld_global_ro:
+ .long C_SYMBOL_NAME(_rtld_global_ro)(GOT)
+#else
+Lhwcap:
+ .long C_SYMBOL_NAME(_dl_hwcap)
+#endif
+#endif
+
+END (__sigsetjmp)
+
+hidden_def (__sigsetjmp)
diff --git a/ports/sysdeps/arm/shlib-versions b/ports/sysdeps/arm/shlib-versions
new file mode 100644
index 0000000000..1ac597abbb
--- /dev/null
+++ b/ports/sysdeps/arm/shlib-versions
@@ -0,0 +1,9 @@
+arm.*-.*-linux-gnueabi.* DEFAULT GLIBC_2.4
+
+%ifdef HAVE_ARM_PCS_VFP
+# The EABI-derived hard-float ABI uses a new dynamic linker.
+arm.*-.*-linux-gnueabi.* ld=ld-linux-armhf.so.3
+%else
+# The EABI-derived soft-float ABI continues to use ld-linux.so.3.
+arm.*-.*-linux-gnueabi.* ld=ld-linux.so.3
+%endif
diff --git a/ports/sysdeps/arm/stackinfo.h b/ports/sysdeps/arm/stackinfo.h
new file mode 100644
index 0000000000..ea706bb2cb
--- /dev/null
+++ b/ports/sysdeps/arm/stackinfo.h
@@ -0,0 +1,33 @@
+/* Copyright (C) 2001, 2010 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/>. */
+
+/* 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 Arm the stack grows down. */
+#define _STACK_GROWS_DOWN 1
+
+/* Default to an executable stack. PF_X can be overridden if PT_GNU_STACK is
+ * present, but it is presumed absent. */
+#define DEFAULT_STACK_PERMS (PF_R|PF_W|PF_X)
+
+#endif /* stackinfo.h */
diff --git a/ports/sysdeps/arm/start.S b/ports/sysdeps/arm/start.S
new file mode 100644
index 0000000000..245d7aa571
--- /dev/null
+++ b/ports/sysdeps/arm/start.S
@@ -0,0 +1,148 @@
+/* Startup code for ARM & ELF
+ Copyright (C) 1995-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/>. */
+
+/* This is the canonical entry point, usually the first thing in the text
+ segment.
+
+ Note that the code in the .init section has already been run.
+ This includes _init and _libc_init
+
+
+ At this entry point, most registers' values are unspecified, except:
+
+ a1 Contains a function pointer to be registered with `atexit'.
+ This is how the dynamic linker arranges to have DT_FINI
+ functions called for shared libraries that have been loaded
+ before this code runs.
+
+ sp The stack contains the arguments and environment:
+ 0(sp) argc
+ 4(sp) argv[0]
+ ...
+ (4*argc)(sp) NULL
+ (4*(argc+1))(sp) envp[0]
+ ...
+ NULL
+*/
+
+/* Tag_ABI_align8_preserved: This code preserves 8-byte
+ alignment in any callee. */
+ .eabi_attribute 25, 1
+/* Tag_ABI_align8_needed: This code may require 8-byte alignment from
+ the caller. */
+ .eabi_attribute 24, 1
+
+#if defined(__thumb2__)
+ .thumb
+ .syntax unified
+#endif
+
+ .text
+ .globl _start
+ .type _start,#function
+_start:
+ /* Protect against unhandled exceptions. */
+ .fnstart
+ /* Clear the frame pointer and link register since this is the outermost frame. */
+ mov fp, #0
+ mov lr, #0
+
+ /* Pop argc off the stack and save a pointer to argv */
+ ldr a2, [sp], #4
+ mov a3, sp
+
+ /* Push stack limit */
+ str a3, [sp, #-4]!
+
+ /* Push rtld_fini */
+ str a1, [sp, #-4]!
+
+#ifdef SHARED
+ ldr sl, .L_GOT
+ adr a4, .L_GOT
+ add sl, sl, a4
+
+ ldr ip, .L_GOT+4 /* __libc_csu_fini */
+ ldr ip, [sl, ip]
+
+ str ip, [sp, #-4]! /* Push __libc_csu_fini */
+
+ ldr a4, .L_GOT+8 /* __libc_csu_init */
+ ldr a4, [sl, a4]
+
+ ldr a1, .L_GOT+12 /* main */
+ ldr a1, [sl, a1]
+
+ /* __libc_start_main (main, argc, argv, init, fini, rtld_fini, stack_end) */
+ /* Let the libc call main and exit with its return code. */
+ bl __libc_start_main(PLT)
+#else
+ /* Fetch address of __libc_csu_fini */
+ ldr ip, =__libc_csu_fini
+
+ /* Push __libc_csu_fini */
+ str ip, [sp, #-4]!
+
+ /* Set up the other arguments in registers */
+ ldr a1, =main
+ ldr a4, =__libc_csu_init
+
+ /* __libc_start_main (main, argc, argv, init, fini, rtld_fini, stack_end) */
+ /* Let the libc call main and exit with its return code. */
+ bl __libc_start_main
+#endif
+
+ /* should never get here....*/
+ bl abort
+
+#ifdef SHARED
+ .align 2
+.L_GOT:
+ .word _GLOBAL_OFFSET_TABLE_ - .L_GOT
+ .word __libc_csu_fini(GOT)
+ .word __libc_csu_init(GOT)
+ .word main(GOT)
+#endif
+
+ .cantunwind
+ .fnend
+
+/* Define a symbol for the first piece of initialized data. */
+ .data
+ .globl __data_start
+__data_start:
+ .long 0
+ .weak data_start
+ data_start = __data_start
diff --git a/ports/sysdeps/arm/strlen.S b/ports/sysdeps/arm/strlen.S
new file mode 100644
index 0000000000..0f18647ef4
--- /dev/null
+++ b/ports/sysdeps/arm/strlen.S
@@ -0,0 +1,72 @@
+/* Copyright (C) 1998, 2003 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Code contributed by Matthew Wilcox <willy@odie.barnet.ac.uk>
+
+ 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>
+
+/* size_t strlen(const char *S)
+ * entry: r0 -> string
+ * exit: r0 = len
+ */
+
+ENTRY(strlen)
+ bic r1, r0, $3 @ addr of word containing first byte
+ ldr r2, [r1], $4 @ get the first word
+ ands r3, r0, $3 @ how many bytes are duff?
+ rsb r0, r3, $0 @ get - that number into counter.
+ beq Laligned @ skip into main check routine if no
+ @ more
+#ifdef __ARMEB__
+ orr r2, r2, $0xff000000 @ set this byte to non-zero
+ subs r3, r3, $1 @ any more to do?
+ orrgt r2, r2, $0x00ff0000 @ if so, set this byte
+ subs r3, r3, $1 @ more?
+ orrgt r2, r2, $0x0000ff00 @ then set.
+#else
+ orr r2, r2, $0x000000ff @ set this byte to non-zero
+ subs r3, r3, $1 @ any more to do?
+ orrgt r2, r2, $0x0000ff00 @ if so, set this byte
+ subs r3, r3, $1 @ more?
+ orrgt r2, r2, $0x00ff0000 @ then set.
+#endif
+Laligned: @ here, we have a word in r2. Does it
+ tst r2, $0x000000ff @ contain any zeroes?
+ tstne r2, $0x0000ff00 @
+ tstne r2, $0x00ff0000 @
+ tstne r2, $0xff000000 @
+ addne r0, r0, $4 @ if not, the string is 4 bytes longer
+ ldrne r2, [r1], $4 @ and we continue to the next word
+ bne Laligned @
+Llastword: @ drop through to here once we find a
+#ifdef __ARMEB__
+ tst r2, $0xff000000 @ word that has a zero byte in it
+ addne r0, r0, $1 @
+ tstne r2, $0x00ff0000 @ and add up to 3 bytes on to it
+ addne r0, r0, $1 @
+ tstne r2, $0x0000ff00 @ (if first three all non-zero, 4th
+ addne r0, r0, $1 @ must be zero)
+#else
+ tst r2, $0x000000ff @ word that has a zero byte in it
+ addne r0, r0, $1 @
+ tstne r2, $0x0000ff00 @ and add up to 3 bytes on to it
+ addne r0, r0, $1 @
+ tstne r2, $0x00ff0000 @ (if first three all non-zero, 4th
+ addne r0, r0, $1 @ must be zero)
+#endif
+ DO_RET(lr)
+END(strlen)
+libc_hidden_builtin_def (strlen)
diff --git a/ports/sysdeps/arm/sys/ucontext.h b/ports/sysdeps/arm/sys/ucontext.h
new file mode 100644
index 0000000000..e1d7c074dd
--- /dev/null
+++ b/ports/sysdeps/arm/sys/ucontext.h
@@ -0,0 +1,94 @@
+/* Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+/* System V/ARM ABI compliant context switching support. */
+
+#ifndef _SYS_UCONTEXT_H
+#define _SYS_UCONTEXT_H 1
+
+#include <features.h>
+#include <signal.h>
+
+typedef int greg_t;
+
+/* Number of general registers. */
+#define NGREG 16
+
+/* Container for all general registers. */
+typedef greg_t gregset_t[NGREG];
+
+/* Number of each register is the `gregset_t' array. */
+enum
+{
+ R0 = 0,
+#define R0 R0
+ R1 = 1,
+#define R1 R1
+ R2 = 2,
+#define R2 R2
+ R3 = 3,
+#define R3 R3
+ R4 = 4,
+#define R4 R4
+ R5 = 5,
+#define R5 R5
+ R6 = 6,
+#define R6 R6
+ R7 = 7,
+#define R7 R7
+ R8 = 8,
+#define R8 R8
+ R9 = 9,
+#define R9 R9
+ R10 = 10,
+#define R10 R10
+ R11 = 11,
+#define R11 R11
+ R12 = 12,
+#define R12 R12
+ R13 = 13,
+#define R13 R13
+ R14 = 14,
+#define R14 R14
+ R15 = 15,
+#define R15 R15
+};
+
+/* Structure to describe FPU registers. */
+typedef struct fpregset
+ {
+ } fpregset_t;
+
+/* Context to describe whole processor state. */
+typedef struct
+ {
+ gregset_t gregs;
+ fpregset_t fpregs;
+ } mcontext_t;
+
+/* Userlevel context. */
+typedef struct ucontext
+ {
+ unsigned long int uc_flags;
+ struct ucontext *uc_link;
+ __sigset_t uc_sigmask;
+ stack_t uc_stack;
+ mcontext_t uc_mcontext;
+ long int uc_filler[5];
+ } ucontext_t;
+
+#endif /* sys/ucontext.h */
diff --git a/ports/sysdeps/arm/sysdep.h b/ports/sysdeps/arm/sysdep.h
new file mode 100644
index 0000000000..7800456f64
--- /dev/null
+++ b/ports/sysdeps/arm/sysdep.h
@@ -0,0 +1,120 @@
+/* Assembler macros for ARM.
+ Copyright (C) 1997, 1998, 2003, 2009, 2010, 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/>. */
+
+#include <sysdeps/generic/sysdep.h>
+#include <features.h>
+
+#if (!defined (__ARM_ARCH_2__) && !defined (__ARM_ARCH_3__) \
+ && !defined (__ARM_ARCH_3M__) && !defined (__ARM_ARCH_4__))
+# define __USE_BX__
+#endif
+
+#ifdef __ASSEMBLER__
+
+/* Syntactic details of assembler. */
+
+#define ALIGNARG(log2) log2
+/* For ELF we need the `.type' directive to make shared libs work right. */
+#define ASM_TYPE_DIRECTIVE(name,typearg) .type name,%##typearg;
+#define ASM_SIZE_DIRECTIVE(name) .size name,.-name
+
+#define PLTJMP(_x) _x##(PLT)
+
+/* APCS-32 doesn't preserve the condition codes across function call. */
+#ifdef __APCS_32__
+#define LOADREGS(cond, base, reglist...)\
+ ldm##cond base,reglist
+#ifdef __USE_BX__
+#define RETINSTR(cond, reg) \
+ bx##cond reg
+#define DO_RET(_reg) \
+ bx _reg
+#else
+#define RETINSTR(cond, reg) \
+ mov##cond pc, reg
+#define DO_RET(_reg) \
+ mov pc, _reg
+#endif
+#else /* APCS-26 */
+#define LOADREGS(cond, base, reglist...)\
+ ldm##cond base,reglist^
+#define RETINSTR(cond, reg) \
+ mov##cond##s pc, reg
+#define DO_RET(_reg) \
+ movs pc, _reg
+#endif
+
+/* 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 ALIGNARG(4); \
+ C_LABEL(name) \
+ .cfi_sections .debug_frame; \
+ cfi_startproc; \
+ CALL_MCOUNT
+
+#undef END
+#define END(name) \
+ cfi_endproc; \
+ ASM_SIZE_DIRECTIVE(name)
+
+/* If compiled for profiling, call `mcount' at the start of each function. */
+#ifdef PROF
+/* Call __gnu_mcount_nc if GCC >= 4.4. */
+#if __GNUC_PREREQ(4,4)
+#define CALL_MCOUNT \
+ str lr,[sp, #-4]!; \
+ cfi_adjust_cfa_offset (4); \
+ cfi_rel_offset (lr, 0); \
+ bl PLTJMP(mcount); \
+ cfi_adjust_cfa_offset (-4); \
+ cfi_restore (lr)
+#else /* else call _mcount */
+#define CALL_MCOUNT \
+ str lr,[sp, #-4]!; \
+ cfi_adjust_cfa_offset (4); \
+ cfi_rel_offset (lr, 0); \
+ bl PLTJMP(mcount); \
+ ldr lr, [sp], #4; \
+ cfi_adjust_cfa_offset (-4); \
+ cfi_restore (lr)
+#endif
+#else
+#define CALL_MCOUNT /* Do nothing. */
+#endif
+
+/* 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
+#if __GNUC_PREREQ(4,4)
+#define mcount __gnu_mcount_nc
+#else
+#define mcount _mcount
+#endif
+
+/* Tag_ABI_align8_preserved: This code preserves 8-byte
+ alignment in any callee. */
+ .eabi_attribute 25, 1
+/* Tag_ABI_align8_needed: This code may require 8-byte alignment from
+ the caller. */
+ .eabi_attribute 24, 1
+
+#endif /* __ASSEMBLER__ */
diff --git a/ports/sysdeps/arm/tls-macros.h b/ports/sysdeps/arm/tls-macros.h
new file mode 100644
index 0000000000..e41d3bc5aa
--- /dev/null
+++ b/ports/sysdeps/arm/tls-macros.h
@@ -0,0 +1,78 @@
+#ifdef __thumb2__
+#define ARM_PC_OFFSET "4"
+#else
+#define ARM_PC_OFFSET "8"
+#endif
+
+#define TLS_LE(x) \
+ ({ int *__result; \
+ void *tp = __builtin_thread_pointer (); \
+ asm ("ldr %0, 1f; " \
+ "add %0, %1, %0; " \
+ "b 2f; " \
+ ".align 2; " \
+ "1: .word " #x "(tpoff); " \
+ "2: " \
+ : "=&r" (__result) : "r" (tp)); \
+ __result; })
+
+#ifdef __thumb2__
+#define TLS_IE(x) \
+ ({ int *__result; \
+ void *tp = __builtin_thread_pointer (); \
+ asm ("ldr %0, 1f; " \
+ "3: add %0, pc, %0;" \
+ "ldr %0, [%0];" \
+ "add %0, %1, %0; " \
+ "b 2f; " \
+ ".align 2; " \
+ "1: .word " #x "(gottpoff) + (. - 3b - 4); " \
+ "2: " \
+ : "=&r" (__result) : "r" (tp)); \
+ __result; })
+#else
+#define TLS_IE(x) \
+ ({ int *__result; \
+ void *tp = __builtin_thread_pointer (); \
+ asm ("ldr %0, 1f; " \
+ "3: ldr %0, [pc, %0];" \
+ "add %0, %1, %0; " \
+ "b 2f; " \
+ ".align 2; " \
+ "1: .word " #x "(gottpoff) + (. - 3b - 8); " \
+ "2: " \
+ : "=&r" (__result) : "r" (tp)); \
+ __result; })
+#endif
+
+#define TLS_LD(x) \
+ ({ char *__result; \
+ int __offset; \
+ extern void *__tls_get_addr (void *); \
+ asm ("ldr %0, 2f; " \
+ "1: add %0, pc, %0; " \
+ "b 3f; " \
+ ".align 2; " \
+ "2: .word " #x "(tlsldm) + (. - 1b - "ARM_PC_OFFSET"); " \
+ "3: " \
+ : "=r" (__result)); \
+ __result = (char *)__tls_get_addr (__result); \
+ asm ("ldr %0, 1f; " \
+ "b 2f; " \
+ ".align 2; " \
+ "1: .word " #x "(tlsldo); " \
+ "2: " \
+ : "=r" (__offset)); \
+ (int *) (__result + __offset); })
+
+#define TLS_GD(x) \
+ ({ int *__result; \
+ extern void *__tls_get_addr (void *); \
+ asm ("ldr %0, 2f; " \
+ "1: add %0, pc, %0; " \
+ "b 3f; " \
+ ".align 2; " \
+ "2: .word " #x "(tlsgd) + (. - 1b - "ARM_PC_OFFSET"); " \
+ "3: " \
+ : "=r" (__result)); \
+ (int *)__tls_get_addr (__result); })
diff --git a/ports/sysdeps/arm/tlsdesc.c b/ports/sysdeps/arm/tlsdesc.c
new file mode 100644
index 0000000000..c5e69a8755
--- /dev/null
+++ b/ports/sysdeps/arm/tlsdesc.c
@@ -0,0 +1,160 @@
+/* Manage TLS descriptors. ARM version.
+ Copyright (C) 2005, 2010, 2011 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <link.h>
+#include <ldsodefs.h>
+#include <elf/dynamic-link.h>
+#include <tls.h>
+#include <dl-tlsdesc.h>
+#include <tlsdeschtab.h>
+
+/* This function is used to lazily resolve TLS_DESC REL relocations
+ Besides the TLS descriptor itself, we get the module's got address
+ as the second parameter. */
+
+void
+attribute_hidden
+_dl_tlsdesc_lazy_resolver_fixup (struct tlsdesc volatile *td,
+ Elf32_Addr *got)
+{
+ struct link_map *l = (struct link_map *)got[1];
+ lookup_t result;
+ unsigned long value;
+
+ if (_dl_tlsdesc_resolve_early_return_p
+ (td, (void*)(D_PTR (l, l_info[ADDRIDX (DT_TLSDESC_PLT)]) + l->l_addr)))
+ return;
+
+ if (td->argument.value & 0x80000000)
+ {
+ /* A global symbol, this is the symbol index. */
+ /* The code below was borrowed from _dl_fixup(). */
+ const Elf_Symndx symndx = td->argument.value ^ 0x80000000;
+ const ElfW(Sym) *const symtab
+ = (const void *) D_PTR (l, l_info[DT_SYMTAB]);
+ const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]);
+ const ElfW(Sym) *sym = &symtab[symndx];
+
+ /* Look up the target symbol. If the normal lookup rules are not
+ used don't look in the global scope. */
+ if (ELFW(ST_BIND) (sym->st_info) != STB_LOCAL
+ && __builtin_expect (ELFW(ST_VISIBILITY) (sym->st_other), 0) == 0)
+ {
+ const struct r_found_version *version = NULL;
+
+ if (l->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
+ {
+ const ElfW(Half) *vernum =
+ (const void *) D_PTR (l, l_info[VERSYMIDX (DT_VERSYM)]);
+ ElfW(Half) ndx = vernum[symndx] & 0x7fff;
+ version = &l->l_versions[ndx];
+ if (version->hash == 0)
+ version = NULL;
+ }
+
+ result = _dl_lookup_symbol_x
+ (strtab + sym->st_name, l, &sym,
+ l->l_scope, version, ELF_RTYPE_CLASS_PLT,
+ DL_LOOKUP_ADD_DEPENDENCY, NULL);
+ if (sym)
+ value = sym->st_value;
+ else
+ {
+ td->entry = _dl_tlsdesc_undefweak;
+ goto done;
+ }
+ }
+ else
+ {
+ /* We already found the symbol. The module (and therefore its load
+ address) is also known. */
+ result = l;
+ value = sym->st_value;
+ }
+ }
+ else
+ {
+ /* A local symbol, this is the offset within our tls section.
+ */
+ value = td->argument.value;
+ result = l;
+ }
+
+#ifndef SHARED
+ CHECK_STATIC_TLS (l, result);
+#else
+ if (!TRY_STATIC_TLS (l, result))
+ {
+ td->argument.pointer = _dl_make_tlsdesc_dynamic (result, value);
+ td->entry = _dl_tlsdesc_dynamic;
+ }
+ else
+#endif
+ {
+ td->argument.value = value + result->l_tls_offset;
+ td->entry = _dl_tlsdesc_return;
+ }
+
+ done:
+ _dl_tlsdesc_wake_up_held_fixups ();
+}
+
+/* This function is used to avoid busy waiting for other threads to
+ complete the lazy relocation. Once another thread wins the race to
+ relocate a TLS descriptor, it sets the descriptor up such that this
+ function is called to wait until the resolver releases the
+ lock. */
+
+void
+attribute_hidden
+_dl_tlsdesc_resolve_hold_fixup (struct tlsdesc volatile *td,
+ void *caller)
+{
+ /* Maybe we're lucky and can return early. */
+ if (caller != td->entry)
+ return;
+
+ /* Locking here will stop execution until the running resolver runs
+ _dl_tlsdesc_wake_up_held_fixups(), releasing the lock.
+
+ FIXME: We'd be better off waiting on a condition variable, such
+ that we didn't have to hold the lock throughout the relocation
+ processing. */
+ __rtld_lock_lock_recursive (GL(dl_load_lock));
+ __rtld_lock_unlock_recursive (GL(dl_load_lock));
+}
+
+/* Unmap the dynamic object, but also release its TLS descriptor table
+ if there is one. */
+
+void
+internal_function
+_dl_unmap (struct link_map *map)
+{
+ __munmap ((void *) (map)->l_map_start,
+ (map)->l_map_end - (map)->l_map_start);
+
+#if SHARED
+ /* _dl_unmap is only called for dlopen()ed libraries, for which
+ calling free() is safe, or before we've completed the initial
+ relocation, in which case calling free() is probably pointless,
+ but still safe. */
+ if (map->l_mach.tlsdesc_table)
+ htab_delete (map->l_mach.tlsdesc_table);
+#endif
+}
diff --git a/ports/sysdeps/arm/tlsdesc.sym b/ports/sysdeps/arm/tlsdesc.sym
new file mode 100644
index 0000000000..3f3a13e2c4
--- /dev/null
+++ b/ports/sysdeps/arm/tlsdesc.sym
@@ -0,0 +1,15 @@
+#include <stddef.h>
+#include <sysdep.h>
+#include <tls.h>
+#include <link.h>
+#include <dl-tlsdesc.h>
+
+--
+
+-- Abuse tls.h macros to derive offsets relative to the thread register.
+
+TLSDESC_ARG offsetof(struct tlsdesc, argument.pointer)
+
+TLSDESC_GEN_COUNT offsetof(struct tlsdesc_dynamic_arg, gen_count)
+TLSDESC_MODID offsetof(struct tlsdesc_dynamic_arg, tlsinfo.ti_module)
+TLSDESC_MODOFF offsetof(struct tlsdesc_dynamic_arg, tlsinfo.ti_offset)
diff --git a/ports/sysdeps/arm/tst-audit.h b/ports/sysdeps/arm/tst-audit.h
new file mode 100644
index 0000000000..0a755a2ebd
--- /dev/null
+++ b/ports/sysdeps/arm/tst-audit.h
@@ -0,0 +1,25 @@
+/* Definitions for testing PLT entry/exit auditing. ARM version.
+
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#define pltenter la_arm_gnu_pltenter
+#define pltexit la_arm_gnu_pltexit
+#define La_regs La_arm_regs
+#define La_retval La_arm_retval
+#define int_retval lrv_reg[0]
diff --git a/ports/sysdeps/arm/unwind-dw2-fde-glibc.c b/ports/sysdeps/arm/unwind-dw2-fde-glibc.c
new file mode 100644
index 0000000000..a94189b7e8
--- /dev/null
+++ b/ports/sysdeps/arm/unwind-dw2-fde-glibc.c
@@ -0,0 +1,79 @@
+/* Dummy exception handling and frame unwind runtime interface routines.
+ Copyright (C) 2004 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/>. */
+
+/* ARM uses setjmp-longjmp exceptions. However, previous versions of
+ GNU libc exported some DWARF-2 exception handling support routines.
+ They are not necessary, but older (or broken) configurations of GCC
+ will do so. Even though all references to these are weak, because
+ they refer to versioned symbols, they must be provided. */
+
+#include <stdlib.h>
+#include <unwind.h>
+#include <unwind-dw2-fde.h>
+
+/* These may be called from startup code, but don't need to do
+ anything. */
+
+void __register_frame_info_bases (void *a1, struct object *a2,
+ void *a3, void *a4)
+{
+}
+
+void __register_frame_info (void *a1, struct object *a2)
+{
+}
+
+void __register_frame (void *a1)
+{
+}
+
+void __register_frame_info_table_bases (void *a1, struct object *a2,
+ void *a3, void *a4)
+{
+}
+
+void __register_frame_info_table (void *a1, struct object *a2)
+{
+}
+
+void __register_frame_table (void *a1)
+{
+}
+
+void *__deregister_frame_info (void *a1)
+{
+ return NULL;
+}
+
+void *__deregister_frame_info_bases (void *a1)
+{
+ return NULL;
+}
+
+void __deregister_frame (void *a1)
+{
+}
+
+/* This should not be called. */
+
+fde *
+_Unwind_Find_FDE (void *a1, struct dwarf_eh_bases *a2)
+{
+ abort ();
+}
diff --git a/ports/sysdeps/arm/unwind-pe.c b/ports/sysdeps/arm/unwind-pe.c
new file mode 100644
index 0000000000..710cecca97
--- /dev/null
+++ b/ports/sysdeps/arm/unwind-pe.c
@@ -0,0 +1 @@
+/* Empty */