mirror of
https://sourceware.org/git/glibc.git
synced 2025-09-02 16:01:20 +03:00
Move arm from ports to libc.
I've moved the ARM port from ports to the main sysdeps hierarchy. Beyond the README update, the move of the files was simply git mv ports/sysdeps/arm sysdeps/arm git mv ports/sysdeps/unix/arm sysdeps/unix/arm git mv ports/sysdeps/unix/sysv/linux/arm sysdeps/unix/sysv/linux/arm and in addition to the ChangeLog entries here, I put a note at the top of ports/ChangeLog.arm similar to that at the top of ChangeLog.powerpc. There is deliberately no NEWS change, as I think it makes the most sense to put in a general note above all ports having moved if we can achieve that for 2.20. Tested that disassembly of installed shared libraries for arm is the same before and after this patch, except for data (not instructions) in ld.so (there are assertions in sysdeps/arm/dl-machine.h, and the path by which that file is found, and so by which it appears in the assertion message, changes as a result of the move). * sysdeps/arm: Move directory from ports/sysdeps/arm. * sysdeps/unix/arm: Move directory from ports/sysdeps/unix/arm. * sysdeps/unix/sysv/linux/arm: Move directory from ports/sysdeps/unix/sysv/linux/arm. * README: Update listing for arm-*-linux-gnueabi. ports/ChangeLog.arm: * sysdeps/arm: Move directory to ../sysdeps/arm. * sysdeps/unix/arm: Move directory to ../sysdeps.arm. * sysdeps/unix/sysv/linux/arm: Move directory to ../sysdeps/unix/sysv/linux/arm.
This commit is contained in:
4
sysdeps/arm/Implies
Normal file
4
sysdeps/arm/Implies
Normal file
@@ -0,0 +1,4 @@
|
||||
arm/soft-fp
|
||||
wordsize-32
|
||||
ieee754/flt-32
|
||||
ieee754/dbl-64
|
34
sysdeps/arm/Makefile
Normal file
34
sysdeps/arm/Makefile
Normal file
@@ -0,0 +1,34 @@
|
||||
gnulib-arch = $(elfobjdir)/libgcc-stubs.a
|
||||
static-gnulib-arch = $(elfobjdir)/libgcc-stubs.a
|
||||
|
||||
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
|
||||
|
||||
$(objpfx)libgcc-stubs.a: $(objpfx)aeabi_unwind_cpp_pr1.os
|
||||
$(build-extra-lib)
|
||||
|
||||
lib-noranlib: $(objpfx)libgcc-stubs.a
|
||||
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
|
||||
|
||||
ifeq ($(subdir),gmon)
|
||||
sysdep_routines += arm-mcount
|
||||
endif
|
||||
|
||||
ifeq ($(subdir),debug)
|
||||
CFLAGS-backtrace.c += -funwind-tables
|
||||
endif
|
20
sysdeps/arm/Versions
Normal file
20
sysdeps/arm/Versions
Normal file
@@ -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;
|
||||
}
|
||||
}
|
140
sysdeps/arm/__longjmp.S
Normal file
140
sysdeps/arm/__longjmp.S
Normal file
@@ -0,0 +1,140 @@
|
||||
/* longjmp for ARM.
|
||||
Copyright (C) 1997-2014 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 <bits/setjmp.h>
|
||||
#include <rtld-global-offsets.h>
|
||||
#include <arm-features.h>
|
||||
|
||||
/* __longjmp(jmpbuf, val) */
|
||||
|
||||
ENTRY (__longjmp)
|
||||
mov ip, r0
|
||||
movs r0, r1 /* get the return value in place */
|
||||
it eq
|
||||
moveq r0, #1 /* can't let setjmp() return zero! */
|
||||
|
||||
#ifdef CHECK_SP
|
||||
sfi_breg ip, \
|
||||
ldr r4, [\B, #32] /* jmpbuf's sp */
|
||||
cfi_undefined (r4)
|
||||
#ifdef PTR_DEMANGLE
|
||||
PTR_DEMANGLE (r4, r4, a3, a4)
|
||||
#endif
|
||||
CHECK_SP (r4)
|
||||
#endif
|
||||
sfi_sp sfi_breg ip, \
|
||||
ldmia \B!, JMP_BUF_REGLIST
|
||||
#ifdef PTR_DEMANGLE
|
||||
ldr a4, [ip], #4
|
||||
PTR_DEMANGLE (a4, a4, a3, a2)
|
||||
mov sp, a4
|
||||
ldr a4, [ip], #4
|
||||
PTR_DEMANGLE2 (lr, a4, a3)
|
||||
#else
|
||||
ldr sp, [ip], #4
|
||||
ldr lr, [ip], #4
|
||||
#endif
|
||||
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)
|
||||
|
||||
#if !defined ARM_ASSUME_NO_IWMMXT || defined __SOFTFP__
|
||||
# define NEED_HWCAP 1
|
||||
#endif
|
||||
|
||||
#ifdef NEED_HWCAP
|
||||
# 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
|
||||
#endif
|
||||
|
||||
#ifdef __SOFTFP__
|
||||
tst a2, #HWCAP_ARM_VFP
|
||||
beq .Lno_vfp
|
||||
#endif
|
||||
|
||||
/* Restore the VFP registers. */
|
||||
/* Following instruction is vldmia ip!, {d8-d15}. */
|
||||
sfi_breg r12, \
|
||||
ldc p11, cr8, [\B], #64
|
||||
.Lno_vfp:
|
||||
|
||||
#ifndef ARM_ASSUME_NO_IWMMXT
|
||||
tst a2, #HWCAP_ARM_IWMMXT
|
||||
beq .Lno_iwmmxt
|
||||
|
||||
/* Restore the call-preserved iWMMXt registers. */
|
||||
/* Following instructions are wldrd wr10, [ip], #8 (etc.) */
|
||||
sfi_breg r12, \
|
||||
ldcl p1, cr10, [\B], #8
|
||||
sfi_breg r12, \
|
||||
ldcl p1, cr11, [\B], #8
|
||||
sfi_breg r12, \
|
||||
ldcl p1, cr12, [\B], #8
|
||||
sfi_breg r12, \
|
||||
ldcl p1, cr13, [\B], #8
|
||||
sfi_breg r12, \
|
||||
ldcl p1, cr14, [\B], #8
|
||||
sfi_breg r12, \
|
||||
ldcl p1, cr15, [\B], #8
|
||||
.Lno_iwmmxt:
|
||||
#endif
|
||||
|
||||
DO_RET(lr)
|
||||
|
||||
#ifdef NEED_HWCAP
|
||||
# ifdef IS_IN_rtld
|
||||
1: .long _GLOBAL_OFFSET_TABLE_ - 0b - PC_OFS
|
||||
.Lrtld_local_ro:
|
||||
.long C_SYMBOL_NAME(_rtld_local_ro)(GOTOFF)
|
||||
# else
|
||||
# ifdef PIC
|
||||
1: .long _GLOBAL_OFFSET_TABLE_ - 0b - PC_OFS
|
||||
.Lrtld_global_ro:
|
||||
.long C_SYMBOL_NAME(_rtld_global_ro)(GOT)
|
||||
# else
|
||||
.Lhwcap:
|
||||
.long C_SYMBOL_NAME(_dl_hwcap)
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
END (__longjmp)
|
9
sysdeps/arm/abi-note.S
Normal file
9
sysdeps/arm/abi-note.S
Normal file
@@ -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>
|
||||
|
99
sysdeps/arm/add_n.S
Normal file
99
sysdeps/arm/add_n.S
Normal file
@@ -0,0 +1,99 @@
|
||||
/* mpn_add_n -- add (or subtract) bignums.
|
||||
Copyright (C) 2013-2014 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 <arm-features.h>
|
||||
|
||||
.syntax unified
|
||||
.text
|
||||
|
||||
#ifdef USE_AS_SUB_N
|
||||
# define INITC cmp r0, r0
|
||||
# define OPC sbcs
|
||||
# define RETC sbc r0, r0, r0; neg r0, r0
|
||||
# define FUNC __mpn_sub_n
|
||||
#else
|
||||
# define INITC cmn r0, #0
|
||||
# define OPC adcs
|
||||
# define RETC mov r0, #0; adc r0, r0, r0
|
||||
# define FUNC __mpn_add_n
|
||||
#endif
|
||||
|
||||
/* mp_limb_t mpn_add_n(res_ptr, src1_ptr, src2_ptr, size) */
|
||||
|
||||
ENTRY (FUNC)
|
||||
push { r4, r5, r6, r7, r8, r10, lr }
|
||||
cfi_adjust_cfa_offset (28)
|
||||
cfi_rel_offset (r4, 0)
|
||||
cfi_rel_offset (r5, 4)
|
||||
cfi_rel_offset (r6, 8)
|
||||
cfi_rel_offset (r7, 12)
|
||||
cfi_rel_offset (r8, 16)
|
||||
cfi_rel_offset (r10, 20)
|
||||
cfi_rel_offset (lr, 24)
|
||||
|
||||
INITC /* initialize carry flag */
|
||||
tst r3, #1 /* count & 1 == 1? */
|
||||
add lr, r1, r3, lsl #2 /* compute end src1 */
|
||||
beq 1f
|
||||
|
||||
sfi_breg r1, \
|
||||
ldr r4, [\B], #4 /* do one to make count even */
|
||||
sfi_breg r2, \
|
||||
ldr r5, [\B], #4
|
||||
OPC r4, r4, r5
|
||||
teq r1, lr /* end of count? (preserve carry) */
|
||||
sfi_breg r0, \
|
||||
str r4, [\B], #4
|
||||
beq 9f
|
||||
1:
|
||||
tst r3, #2 /* count & 2 == 2? */
|
||||
beq 2f
|
||||
sfi_breg r1, \
|
||||
ldm \B!, { r4, r5 } /* do two to make count 0 mod 4 */
|
||||
sfi_breg r2, \
|
||||
ldm \B!, { r6, r7 }
|
||||
OPC r4, r4, r6
|
||||
OPC r5, r5, r7
|
||||
teq r1, lr /* end of count? */
|
||||
sfi_breg r0, \
|
||||
stm \B!, { r4, r5 }
|
||||
beq 9f
|
||||
2:
|
||||
sfi_breg r1, \
|
||||
ldm \B!, { r3, r5, r7, r10 } /* do four each loop */
|
||||
sfi_breg r2, \
|
||||
ldm \B!, { r4, r6, r8, ip }
|
||||
OPC r3, r3, r4
|
||||
OPC r5, r5, r6
|
||||
OPC r7, r7, r8
|
||||
OPC r10, r10, ip
|
||||
teq r1, lr
|
||||
sfi_breg r0, \
|
||||
stm \B!, { r3, r5, r7, r10 }
|
||||
bne 2b
|
||||
|
||||
9:
|
||||
RETC /* copy carry out */
|
||||
#ifndef ARM_ALWAYS_BX
|
||||
pop { r4, r5, r6, r7, r8, r10, pc }
|
||||
#else
|
||||
pop { r4, r5, r6, r7, r8, r10, lr }
|
||||
bx lr
|
||||
#endif
|
||||
END (FUNC)
|
73
sysdeps/arm/addmul_1.S
Normal file
73
sysdeps/arm/addmul_1.S
Normal file
@@ -0,0 +1,73 @@
|
||||
/* mpn_addmul_1 -- multiply and accumulate bignums.
|
||||
Copyright (C) 2013-2014 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>
|
||||
|
||||
.syntax unified
|
||||
.text
|
||||
|
||||
@ cycles/limb
|
||||
@ StrongArm ?
|
||||
@ Cortex-A8 ?
|
||||
@ Cortex-A9 ?
|
||||
@ Cortex-A15 4
|
||||
|
||||
/* mp_limb_t mpn_addmul_1(res_ptr, src1_ptr, size, s2_limb) */
|
||||
|
||||
ENTRY (__mpn_addmul_1)
|
||||
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)
|
||||
|
||||
sfi_breg r1, \
|
||||
ldr r6, [\B], #4
|
||||
sfi_breg r0, \
|
||||
ldr r5, [\B]
|
||||
mov r4, #0 /* init carry in */
|
||||
b 1f
|
||||
0:
|
||||
sfi_breg r1, \
|
||||
ldr r6, [\B], #4 /* load next ul */
|
||||
adds r7, r4, r5 /* (out, c) = cl + lpl */
|
||||
sfi_breg r0, \
|
||||
ldr r5, [\B, #4] /* load next rl */
|
||||
adc r4, ip, #0 /* cl = hpl + c */
|
||||
sfi_breg r0, \
|
||||
str r7, [\B], #4
|
||||
1:
|
||||
mov ip, #0 /* zero-extend rl */
|
||||
umlal r5, ip, r6, r3 /* (hpl, lpl) = ul * vl + rl */
|
||||
subs r2, r2, #1
|
||||
bne 0b
|
||||
|
||||
adds r4, r4, r5 /* (out, c) = cl + llpl */
|
||||
sfi_breg r0, \
|
||||
str r4, [\B]
|
||||
adc r0, ip, #0 /* return hpl + c */
|
||||
|
||||
pop { r4, r5, r6, r7 }
|
||||
cfi_adjust_cfa_offset (-16)
|
||||
cfi_restore (r4)
|
||||
cfi_restore (r5)
|
||||
cfi_restore (r6)
|
||||
cfi_restore (r7)
|
||||
DO_RET (lr)
|
||||
END (__mpn_addmul_1)
|
26
sysdeps/arm/aeabi_assert.c
Normal file
26
sysdeps/arm/aeabi_assert.c
Normal file
@@ -0,0 +1,26 @@
|
||||
/* Copyright (C) 2004-2014 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);
|
||||
}
|
27
sysdeps/arm/aeabi_atexit.c
Normal file
27
sysdeps/arm/aeabi_atexit.c
Normal file
@@ -0,0 +1,27 @@
|
||||
/* Copyright (C) 2005-2014 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);
|
||||
}
|
24
sysdeps/arm/aeabi_errno_addr.c
Normal file
24
sysdeps/arm/aeabi_errno_addr.c
Normal file
@@ -0,0 +1,24 @@
|
||||
/* Copyright (C) 2004-2014 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;
|
||||
}
|
98
sysdeps/arm/aeabi_lcsts.c
Normal file
98
sysdeps/arm/aeabi_lcsts.c
Normal file
@@ -0,0 +1,98 @@
|
||||
/* Link-time constants for ARM EABI.
|
||||
Copyright (C) 2005-2014 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);
|
24
sysdeps/arm/aeabi_localeconv.c
Normal file
24
sysdeps/arm/aeabi_localeconv.c
Normal file
@@ -0,0 +1,24 @@
|
||||
/* Copyright (C) 2004-2014 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 ();
|
||||
}
|
41
sysdeps/arm/aeabi_math.c
Normal file
41
sysdeps/arm/aeabi_math.c
Normal file
@@ -0,0 +1,41 @@
|
||||
/* Copyright (C) 2004-2014 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;
|
27
sysdeps/arm/aeabi_mb_cur_max.c
Normal file
27
sysdeps/arm/aeabi_mb_cur_max.c
Normal file
@@ -0,0 +1,27 @@
|
||||
/* Copyright (C) 2004-2014 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;
|
||||
}
|
30
sysdeps/arm/aeabi_memclr.c
Normal file
30
sysdeps/arm/aeabi_memclr.c
Normal file
@@ -0,0 +1,30 @@
|
||||
/* Copyright (C) 2005-2014 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)
|
31
sysdeps/arm/aeabi_memcpy.c
Normal file
31
sysdeps/arm/aeabi_memcpy.c
Normal file
@@ -0,0 +1,31 @@
|
||||
/* Copyright (C) 2005-2014 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)
|
31
sysdeps/arm/aeabi_memmove.c
Normal file
31
sysdeps/arm/aeabi_memmove.c
Normal file
@@ -0,0 +1,31 @@
|
||||
/* Copyright (C) 2005-2014 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)
|
30
sysdeps/arm/aeabi_memset.c
Normal file
30
sysdeps/arm/aeabi_memset.c
Normal file
@@ -0,0 +1,30 @@
|
||||
/* Copyright (C) 2005-2014 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)
|
53
sysdeps/arm/aeabi_sighandlers.S
Normal file
53
sysdeps/arm/aeabi_sighandlers.S
Normal file
@@ -0,0 +1,53 @@
|
||||
/* Link-time constants for ARM EABI - signal handlers.
|
||||
Copyright (C) 2005-2014 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
|
51
sysdeps/arm/aeabi_unwind_cpp_pr1.c
Normal file
51
sysdeps/arm/aeabi_unwind_cpp_pr1.c
Normal file
@@ -0,0 +1,51 @@
|
||||
/* Copyright (C) 2005-2014 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
|
||||
}
|
59
sysdeps/arm/arm-features.h
Normal file
59
sysdeps/arm/arm-features.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/* Macros to test for CPU features on ARM. Generic ARM version.
|
||||
Copyright (C) 2012-2014 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_ARM_FEATURES_H
|
||||
#define _ARM_ARM_FEATURES_H 1
|
||||
|
||||
/* An OS-specific arm-features.h file should define ARM_HAVE_VFP to
|
||||
an appropriate expression for testing at runtime whether the VFP
|
||||
hardware is present. We'll then redefine it to a constant if we
|
||||
know at compile time that we can assume VFP. */
|
||||
|
||||
#ifndef __SOFTFP__
|
||||
/* The compiler is generating VFP instructions, so we're already
|
||||
assuming the hardware exists. */
|
||||
# undef ARM_HAVE_VFP
|
||||
# define ARM_HAVE_VFP 1
|
||||
#endif
|
||||
|
||||
/* An OS-specific arm-features.h file may define ARM_ASSUME_NO_IWMMXT
|
||||
to indicate at compile time that iWMMXt hardware is never present
|
||||
at runtime (or that we never care about its state) and so need not
|
||||
be checked for. */
|
||||
|
||||
/* A more-specific arm-features.h file may define ARM_ALWAYS_BX to indicate
|
||||
that instructions using pc as a destination register must never be used,
|
||||
so a "bx" (or "blx") instruction is always required. */
|
||||
|
||||
/* The log2 of the minimum alignment required for an address that
|
||||
is the target of a computed branch (i.e. a "bx" instruction).
|
||||
A more-specific arm-features.h file may define this to set a more
|
||||
stringent requirement.
|
||||
|
||||
Using this only makes sense for code in ARM mode (where instructions
|
||||
always have a fixed size of four bytes), or for Thumb-mode code that is
|
||||
specifically aligning all the related branch targets to match (since
|
||||
Thumb instructions might be either two or four bytes). */
|
||||
#ifndef ARM_BX_ALIGN_LOG2
|
||||
# define ARM_BX_ALIGN_LOG2 2
|
||||
#endif
|
||||
|
||||
/* An OS-specific arm-features.h file may define ARM_NO_INDEX_REGISTER to
|
||||
indicate that the two-register addressing modes must never be used. */
|
||||
|
||||
#endif /* arm-features.h */
|
129
sysdeps/arm/arm-mcount.S
Normal file
129
sysdeps/arm/arm-mcount.S
Normal file
@@ -0,0 +1,129 @@
|
||||
/* Implementation of profiling support. ARM EABI version.
|
||||
Copyright (C) 2008-2014 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>
|
||||
|
||||
#undef mcount
|
||||
|
||||
#ifdef __thumb2__
|
||||
.thumb
|
||||
#endif
|
||||
.syntax unified
|
||||
|
||||
|
||||
/* 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_mcount_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)
|
||||
|
||||
|
||||
#include <gcc-compat.h>
|
||||
#include <shlib-compat.h>
|
||||
|
||||
/* The new __gnu_mcount_nc entry point was introduced in 4.4, so the
|
||||
static library needs the old one only to support older compilers.
|
||||
Even in a configuration that only cares about newer compilers, the
|
||||
shared library might need it only for strict ABI compatibility. */
|
||||
|
||||
#if GCC_COMPAT (4, 3) || SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_19)
|
||||
|
||||
/* Provide old mcount for backwards compatibility. This requires
|
||||
code be compiled with APCS frame pointers. */
|
||||
|
||||
ENTRY(__mcount_arm_compat)
|
||||
push {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)
|
||||
movs r0, fp
|
||||
ittt ne
|
||||
sfi_breg r0, \
|
||||
ldrne r0, [\B, #-4]
|
||||
movsne r1, lr
|
||||
blne __mcount_internal
|
||||
# if defined (__ARM_ARCH_4T__) && defined (__THUMB_INTERWORK__)
|
||||
pop {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
|
||||
# else
|
||||
pop {r0, r1, r2, r3, fp, pc}
|
||||
# endif
|
||||
END(__mcount_arm_compat)
|
||||
|
||||
#endif
|
||||
|
||||
#if GCC_COMPAT (4, 3)
|
||||
|
||||
strong_alias (__mcount_arm_compat, _mcount)
|
||||
|
||||
/* The canonical name for the function is `_mcount' in both C and asm,
|
||||
but some old asm code might assume it's `mcount'. */
|
||||
weak_alias (_mcount, mcount)
|
||||
|
||||
#elif SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_19)
|
||||
|
||||
compat_symbol (libc, __mcount_arm_compat, _mcount, GLIBC_2_0)
|
||||
|
||||
strong_alias (__mcount_arm_compat, __mcount_arm_compat_1)
|
||||
compat_symbol (libc, __mcount_arm_compat_1, mcount, GLIBC_2_0)
|
||||
|
||||
#endif
|
109
sysdeps/arm/armv6/rawmemchr.S
Normal file
109
sysdeps/arm/armv6/rawmemchr.S
Normal file
@@ -0,0 +1,109 @@
|
||||
/* rawmemchr -- find a byte within an unsized memory block.
|
||||
Copyright (C) 2013-2014 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>
|
||||
|
||||
.syntax unified
|
||||
.text
|
||||
|
||||
ENTRY (__rawmemchr)
|
||||
@ r0 = start of string
|
||||
@ r1 = character to match
|
||||
@ returns a pointer to the match, which must be present.
|
||||
sfi_breg r0, \
|
||||
ldrb r2, [\B] @ load first byte asap
|
||||
|
||||
@ To cater to long strings, we want to search through a few
|
||||
@ characters until we reach an aligned pointer. To cater to
|
||||
@ small strings, we don't want to start doing word operations
|
||||
@ immediately. The compromise is a maximum of 16 bytes less
|
||||
@ whatever is required to end with an aligned pointer.
|
||||
@ r3 = number of characters to search in alignment loop
|
||||
and r3, r0, #7
|
||||
uxtb r1, r1
|
||||
rsb r3, r3, #15 @ 16 - 1 peeled loop iteration
|
||||
cmp r2, r1
|
||||
it eq
|
||||
bxeq lr
|
||||
|
||||
@ Loop until we find ...
|
||||
1: sfi_breg r0, \
|
||||
ldrb r2, [\B, #1]!
|
||||
subs r3, r3, #1 @ ... the alignment point
|
||||
it ne
|
||||
cmpne r2, r1 @ ... or C
|
||||
bne 1b
|
||||
|
||||
@ Disambiguate the exit possibilites above
|
||||
cmp r2, r1 @ Found C
|
||||
it eq
|
||||
bxeq lr
|
||||
add r0, r0, #1
|
||||
|
||||
@ So now we're aligned.
|
||||
sfi_breg r0, \
|
||||
ldrd r2, r3, [\B], #8
|
||||
orr r1, r1, r1, lsl #8 @ Replicate C to all bytes
|
||||
#ifdef ARCH_HAS_T2
|
||||
movw ip, #0x0101
|
||||
sfi_pld r0, #64
|
||||
movt ip, #0x0101
|
||||
#else
|
||||
ldr ip, =0x01010101
|
||||
sfi_pld r0, #64
|
||||
#endif
|
||||
orr r1, r1, r1, lsl #16
|
||||
|
||||
@ Loop searching for C, 8 bytes at a time.
|
||||
@ Subtracting (unsigned saturating) from 1 means result of 1 for
|
||||
@ any byte that was originally zero and 0 otherwise. Therefore
|
||||
@ we consider the lsb of each byte the "found" bit.
|
||||
2: eor r2, r2, r1 @ Convert C bytes to 0
|
||||
eor r3, r3, r1
|
||||
uqsub8 r2, ip, r2 @ Find C
|
||||
uqsub8 r3, ip, r3
|
||||
sfi_pld r0, #128
|
||||
orrs r3, r3, r2 @ Test both words for found
|
||||
it eq
|
||||
sfi_breg r0, \
|
||||
ldrdeq r2, r3, [\B], #8
|
||||
beq 2b
|
||||
|
||||
@ Found something. Disambiguate between first and second words.
|
||||
@ Adjust r0 to point to the word containing the match.
|
||||
@ Adjust r2 to the found bits for the word containing the match.
|
||||
cmp r2, #0
|
||||
sub r0, r0, #4
|
||||
ite eq
|
||||
moveq r2, r3
|
||||
subne r0, r0, #4
|
||||
|
||||
@ Find the bit-offset of the match within the word. Note that the
|
||||
@ bit result from clz will be 7 higher than "true", but we'll
|
||||
@ immediately discard those bits converting to a byte offset.
|
||||
#ifdef __ARMEL__
|
||||
rev r2, r2 @ For LE, count from the little end
|
||||
#endif
|
||||
clz r2, r2
|
||||
add r0, r0, r2, lsr #3 @ Adjust the pointer to the found byte
|
||||
bx lr
|
||||
|
||||
END (__rawmemchr)
|
||||
|
||||
weak_alias (__rawmemchr, rawmemchr)
|
||||
libc_hidden_def (__rawmemchr)
|
1
sysdeps/arm/armv6/stpcpy.S
Normal file
1
sysdeps/arm/armv6/stpcpy.S
Normal file
@@ -0,0 +1 @@
|
||||
/* Defined in strcpy.S. */
|
147
sysdeps/arm/armv6/strchr.S
Normal file
147
sysdeps/arm/armv6/strchr.S
Normal file
@@ -0,0 +1,147 @@
|
||||
/* strchr -- find the first instance of C in a nul-terminated string.
|
||||
Copyright (C) 2013-2014 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>
|
||||
|
||||
.syntax unified
|
||||
.text
|
||||
|
||||
ENTRY (strchr)
|
||||
@ r0 = start of string
|
||||
@ r1 = character to match
|
||||
@ returns NULL for no match, or a pointer to the match
|
||||
sfi_breg r0, \
|
||||
ldrb r2, [\B] @ load the first byte asap
|
||||
uxtb r1, r1
|
||||
|
||||
@ To cater to long strings, we want to search through a few
|
||||
@ characters until we reach an aligned pointer. To cater to
|
||||
@ small strings, we don't want to start doing word operations
|
||||
@ immediately. The compromise is a maximum of 16 bytes less
|
||||
@ whatever is required to end with an aligned pointer.
|
||||
@ r3 = number of characters to search in alignment loop
|
||||
and r3, r0, #7
|
||||
rsb r3, r3, #15 @ 16 - 1 peeled loop iteration
|
||||
cmp r2, r1 @ Found C?
|
||||
it ne
|
||||
cmpne r2, #0 @ Found EOS?
|
||||
beq 99f
|
||||
|
||||
@ Loop until we find ...
|
||||
1: sfi_breg r0, \
|
||||
ldrb r2, [\B, #1]!
|
||||
subs r3, r3, #1 @ ... the aligment point
|
||||
it ne
|
||||
cmpne r2, r1 @ ... or the character
|
||||
it ne
|
||||
cmpne r2, #0 @ ... or EOS
|
||||
bne 1b
|
||||
|
||||
@ Disambiguate the exit possibilites above
|
||||
cmp r2, r1 @ Found the character
|
||||
it ne
|
||||
cmpne r2, #0 @ Found EOS
|
||||
beq 99f
|
||||
add r0, r0, #1
|
||||
|
||||
@ So now we're aligned. Now we actually need a stack frame.
|
||||
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)
|
||||
|
||||
sfi_breg r0, \
|
||||
ldrd r2, r3, [\B], #8
|
||||
orr r1, r1, r1, lsl #8 @ Replicate C to all bytes
|
||||
#ifdef ARCH_HAS_T2
|
||||
movw ip, #0x0101
|
||||
sfi_pld r0, #64
|
||||
movt ip, #0x0101
|
||||
#else
|
||||
ldr ip, =0x01010101
|
||||
sfi_pld r0, #64
|
||||
#endif
|
||||
orr r1, r1, r1, lsl #16
|
||||
|
||||
@ Loop searching for EOS or C, 8 bytes at a time.
|
||||
2:
|
||||
@ Subtracting (unsigned saturating) from 1 means result of 1 for
|
||||
@ any byte that was originally zero and 0 otherwise. Therefore
|
||||
@ we consider the lsb of each byte the "found" bit.
|
||||
uqsub8 r4, ip, r2 @ Find EOS
|
||||
eor r6, r2, r1 @ Convert C bytes to 0
|
||||
uqsub8 r5, ip, r3
|
||||
eor r7, r3, r1
|
||||
uqsub8 r6, ip, r6 @ Find C
|
||||
sfi_pld r0, #128 @ Prefetch 2 lines ahead
|
||||
uqsub8 r7, ip, r7
|
||||
orr r4, r4, r6 @ Combine found for EOS and C
|
||||
orr r5, r5, r7
|
||||
orrs r6, r4, r5 @ Combine the two words
|
||||
it eq
|
||||
sfi_breg r0, \
|
||||
ldrdeq r2, r3, [\B], #8
|
||||
beq 2b
|
||||
|
||||
@ Found something. Disambiguate between first and second words.
|
||||
@ Adjust r0 to point to the word containing the match.
|
||||
@ Adjust r2 to the contents of the word containing the match.
|
||||
@ Adjust r4 to the found bits for the word containing the match.
|
||||
cmp r4, #0
|
||||
sub r0, r0, #4
|
||||
itte eq
|
||||
moveq r4, r5
|
||||
moveq r2, r3
|
||||
subne r0, r0, #4
|
||||
|
||||
@ Find the bit-offset of the match within the word.
|
||||
#if defined(__ARMEL__)
|
||||
@ For LE, swap the found word so clz searches from the little end.
|
||||
rev r4, r4
|
||||
#else
|
||||
@ For BE, byte swap the word to make it easier to extract the byte.
|
||||
rev r2, r2
|
||||
#endif
|
||||
@ We're counting 0x01 (not 0x80), so the bit offset is 7 too high.
|
||||
clz r3, r4
|
||||
sub r3, r3, #7
|
||||
lsr r2, r2, r3 @ Shift down found byte
|
||||
uxtb r1, r1 @ Undo replication of C
|
||||
uxtb r2, r2 @ Extract found byte
|
||||
add r0, r0, r3, lsr #3 @ Adjust the pointer to the found byte
|
||||
|
||||
pop { r4, r5, r6, r7 }
|
||||
cfi_adjust_cfa_offset (-16)
|
||||
cfi_restore (r4)
|
||||
cfi_restore (r5)
|
||||
cfi_restore (r6)
|
||||
cfi_restore (r7)
|
||||
|
||||
@ Disambiguate between EOS and C.
|
||||
99:
|
||||
cmp r2, r1
|
||||
it ne
|
||||
movne r0, #0 @ Found EOS, return NULL
|
||||
bx lr
|
||||
|
||||
END (strchr)
|
||||
|
||||
weak_alias (strchr, index)
|
||||
libc_hidden_builtin_def (strchr)
|
231
sysdeps/arm/armv6/strcpy.S
Normal file
231
sysdeps/arm/armv6/strcpy.S
Normal file
@@ -0,0 +1,231 @@
|
||||
/* strcpy -- copy a nul-terminated string.
|
||||
Copyright (C) 2013-2014 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>
|
||||
|
||||
/* Endian independent macros for shifting bytes within registers. */
|
||||
#ifdef __ARMEB__
|
||||
#define lsh_gt lsr
|
||||
#define lsh_ls lsl
|
||||
#else
|
||||
#define lsh_gt lsl
|
||||
#define lsh_ls lsr
|
||||
#endif
|
||||
|
||||
.syntax unified
|
||||
.text
|
||||
|
||||
ENTRY (__stpcpy)
|
||||
@ Signal stpcpy with NULL in IP.
|
||||
mov ip, #0
|
||||
b 0f
|
||||
END (__stpcpy)
|
||||
|
||||
weak_alias (__stpcpy, stpcpy)
|
||||
libc_hidden_def (__stpcpy)
|
||||
libc_hidden_builtin_def (stpcpy)
|
||||
|
||||
ENTRY (strcpy)
|
||||
@ Signal strcpy with DEST in IP.
|
||||
mov ip, r0
|
||||
0:
|
||||
sfi_pld r0
|
||||
sfi_pld r1
|
||||
|
||||
@ To cater to long strings, we want 8 byte alignment in the source.
|
||||
@ To cater to small strings, we don't want to start that right away.
|
||||
@ Loop up to 16 times, less whatever it takes to reach alignment.
|
||||
and r3, r1, #7
|
||||
rsb r3, r3, #16
|
||||
|
||||
@ Loop until we find ...
|
||||
1: sfi_breg r1, \
|
||||
ldrb r2, [\B], #1
|
||||
subs r3, r3, #1 @ ... the alignment point
|
||||
sfi_breg r0, \
|
||||
strb r2, [\B], #1
|
||||
it ne
|
||||
cmpne r2, #0 @ ... or EOS
|
||||
bne 1b
|
||||
|
||||
@ Disambiguate the exit possibilites above
|
||||
cmp r2, #0 @ Found EOS
|
||||
beq .Lreturn
|
||||
|
||||
@ Load the next two words asap
|
||||
sfi_breg r1, \
|
||||
ldrd r2, r3, [\B], #8
|
||||
sfi_pld r0, #64
|
||||
sfi_pld r1, #64
|
||||
|
||||
@ For longer strings, we actaully need a stack frame.
|
||||
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)
|
||||
|
||||
@ Subtracting (unsigned saturating) from 1 for any byte means result
|
||||
@ of 1 for any byte that was originally zero and 0 otherwise.
|
||||
@ Therefore we consider the lsb of each byte the "found" bit.
|
||||
#ifdef ARCH_HAS_T2
|
||||
movw r7, #0x0101
|
||||
tst r0, #3 @ Test alignment of DEST
|
||||
movt r7, #0x0101
|
||||
#else
|
||||
ldr r7, =0x01010101
|
||||
tst r0, #3
|
||||
#endif
|
||||
bne .Lunaligned
|
||||
|
||||
@ So now source (r1) is aligned to 8, and dest (r0) is aligned to 4.
|
||||
@ Loop, reading 8 bytes at a time, searching for EOS.
|
||||
.balign 16
|
||||
2: uqsub8 r4, r7, r2 @ Find EOS
|
||||
uqsub8 r5, r7, r3
|
||||
sfi_pld r1, #128
|
||||
cmp r4, #0 @ EOS in first word?
|
||||
sfi_pld r0, #128
|
||||
bne 3f
|
||||
sfi_breg r0, \
|
||||
str r2, [\B], #4
|
||||
cmp r5, #0 @ EOS in second word?
|
||||
bne 4f
|
||||
sfi_breg r0, \
|
||||
str r3, [\B], #4
|
||||
sfi_breg r1, \
|
||||
ldrd r2, r3, [\B], #8
|
||||
b 2b
|
||||
|
||||
3: sub r1, r1, #4 @ backup to first word
|
||||
4: sub r1, r1, #4 @ backup to second word
|
||||
|
||||
@ ... then finish up any tail a byte at a time.
|
||||
@ Note that we generally back up and re-read source bytes,
|
||||
@ but we'll not re-write dest bytes.
|
||||
.Lbyte_loop:
|
||||
sfi_breg r1, \
|
||||
ldrb r2, [\B], #1
|
||||
cmp r2, #0
|
||||
sfi_breg r0, \
|
||||
strb r2, [\B], #1
|
||||
bne .Lbyte_loop
|
||||
|
||||
pop { r4, r5, r6, r7 }
|
||||
cfi_remember_state
|
||||
cfi_adjust_cfa_offset (-16)
|
||||
cfi_restore (r4)
|
||||
cfi_restore (r5)
|
||||
cfi_restore (r6)
|
||||
cfi_restore (r7)
|
||||
|
||||
.Lreturn:
|
||||
cmp ip, #0 @ Was this strcpy or stpcpy?
|
||||
ite eq
|
||||
subeq r0, r0, #1 @ stpcpy: undo post-inc from store
|
||||
movne r0, ip @ strcpy: return original dest
|
||||
bx lr
|
||||
|
||||
.Lunaligned:
|
||||
cfi_restore_state
|
||||
@ Here, source is aligned to 8, but the destination is not word
|
||||
@ aligned. Therefore we have to shift the data in order to be
|
||||
@ able to perform aligned word stores.
|
||||
|
||||
@ Find out which misalignment we're dealing with.
|
||||
tst r0, #1
|
||||
beq .Lunaligned2
|
||||
tst r0, #2
|
||||
bne .Lunaligned3
|
||||
@ Fallthru to .Lunaligned1.
|
||||
|
||||
.macro unaligned_copy unalign
|
||||
@ Prologue to unaligned loop. Seed shifted non-zero bytes.
|
||||
uqsub8 r4, r7, r2 @ Find EOS
|
||||
uqsub8 r5, r7, r3
|
||||
mvns r4, r4 @ EOS in first word?
|
||||
it ne
|
||||
subne r1, r1, #8
|
||||
bne .Lbyte_loop
|
||||
#ifdef __ARMEB__
|
||||
rev r2, r2 @ Byte stores below need LE data
|
||||
#endif
|
||||
@ Store a few bytes from the first word.
|
||||
@ At the same time we align r0 and shift out bytes from r2.
|
||||
.rept 4-\unalign
|
||||
sfi_breg r0, \
|
||||
strb r2, [\B], #1
|
||||
lsr r2, r2, #8
|
||||
.endr
|
||||
#ifdef __ARMEB__
|
||||
rev r2, r2 @ Undo previous rev
|
||||
#endif
|
||||
@ Rotated unaligned copy loop. The tail of the prologue is
|
||||
@ shared with the loop itself.
|
||||
.balign 8
|
||||
1: mvns r5, r5 @ EOS in second word?
|
||||
bne 4f
|
||||
@ Combine first and second words
|
||||
orr r2, r2, r3, lsh_gt #(\unalign*8)
|
||||
@ Save leftover bytes from the two words
|
||||
lsh_ls r6, r3, #((4-\unalign)*8)
|
||||
sfi_breg r0, \
|
||||
str r2, [\B], #4
|
||||
@ The "real" start of the unaligned copy loop.
|
||||
sfi_breg r1, \
|
||||
ldrd r2, r3, [\B], #8 @ Load 8 more bytes
|
||||
uqsub8 r4, r7, r2 @ Find EOS
|
||||
sfi_pld r1, #128
|
||||
uqsub8 r5, r7, r3
|
||||
sfi_pld r0, #128
|
||||
mvns r4, r4 @ EOS in first word?
|
||||
bne 3f
|
||||
@ Combine the leftover and the first word
|
||||
orr r6, r6, r2, lsh_gt #(\unalign*8)
|
||||
@ Discard used bytes from the first word.
|
||||
lsh_ls r2, r2, #((4-\unalign)*8)
|
||||
sfi_breg r0, \
|
||||
str r6, [\B], #4
|
||||
b 1b
|
||||
@ Found EOS in one of the words; adjust backward
|
||||
3: sub r1, r1, #4
|
||||
mov r2, r6
|
||||
4: sub r1, r1, #4
|
||||
@ And store the remaining bytes from the leftover
|
||||
#ifdef __ARMEB__
|
||||
rev r2, r2
|
||||
#endif
|
||||
.rept \unalign
|
||||
sfi_breg r0, \
|
||||
strb r2, [\B], #1
|
||||
lsr r2, r2, #8
|
||||
.endr
|
||||
b .Lbyte_loop
|
||||
.endm
|
||||
|
||||
.Lunaligned1:
|
||||
unaligned_copy 1
|
||||
.Lunaligned2:
|
||||
unaligned_copy 2
|
||||
.Lunaligned3:
|
||||
unaligned_copy 3
|
||||
|
||||
END (strcpy)
|
||||
|
||||
libc_hidden_builtin_def (strcpy)
|
103
sysdeps/arm/armv6/strlen.S
Normal file
103
sysdeps/arm/armv6/strlen.S
Normal file
@@ -0,0 +1,103 @@
|
||||
/* strlen -- find the length of a nul-terminated string.
|
||||
Copyright (C) 2013-2014 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>
|
||||
|
||||
.syntax unified
|
||||
.text
|
||||
|
||||
ENTRY (strlen)
|
||||
@ r0 = start of string
|
||||
sfi_breg r0, \
|
||||
ldrb r2, [\B] @ load the first byte asap
|
||||
|
||||
@ To cater to long strings, we want to search through a few
|
||||
@ characters until we reach an aligned pointer. To cater to
|
||||
@ small strings, we don't want to start doing word operations
|
||||
@ immediately. The compromise is a maximum of 16 bytes less
|
||||
@ whatever is required to end with an aligned pointer.
|
||||
@ r3 = number of characters to search in alignment loop
|
||||
and r3, r0, #7
|
||||
mov r1, r0 @ Save the input pointer
|
||||
rsb r3, r3, #15 @ 16 - 1 peeled loop iteration
|
||||
cmp r2, #0
|
||||
beq 99f
|
||||
|
||||
@ Loop until we find ...
|
||||
1: sfi_breg r0, \
|
||||
ldrb r2, [\B, #1]!
|
||||
subs r3, r3, #1 @ ... the aligment point
|
||||
it ne
|
||||
cmpne r2, #0 @ ... or EOS
|
||||
bne 1b
|
||||
|
||||
@ Disambiguate the exit possibilites above
|
||||
cmp r2, #0 @ Found EOS
|
||||
beq 99f
|
||||
add r0, r0, #1
|
||||
|
||||
@ So now we're aligned.
|
||||
sfi_breg r0, \
|
||||
ldrd r2, r3, [\B], #8
|
||||
#ifdef ARCH_HAS_T2
|
||||
movw ip, #0x0101
|
||||
sfi_pld r0, #64
|
||||
movt ip, #0x0101
|
||||
#else
|
||||
ldr ip, =0x01010101
|
||||
sfi_pld r0, #64
|
||||
#endif
|
||||
|
||||
@ Loop searching for EOS, 8 bytes at a time.
|
||||
@ Subtracting (unsigned saturating) from 1 for any byte means that
|
||||
@ we get 1 for any byte that was originally zero and 0 otherwise.
|
||||
@ Therefore we consider the lsb of each byte the "found" bit.
|
||||
.balign 16
|
||||
2: uqsub8 r2, ip, r2 @ Find EOS
|
||||
uqsub8 r3, ip, r3
|
||||
sfi_pld r0, #128 @ Prefetch 2 lines ahead
|
||||
orrs r3, r3, r2 @ Combine the two words
|
||||
it eq
|
||||
sfi_breg r0, \
|
||||
ldrdeq r2, r3, [\B], #8
|
||||
beq 2b
|
||||
|
||||
@ Found something. Disambiguate between first and second words.
|
||||
@ Adjust r0 to point to the word containing the match.
|
||||
@ Adjust r2 to the found bits for the word containing the match.
|
||||
cmp r2, #0
|
||||
sub r0, r0, #4
|
||||
ite eq
|
||||
moveq r2, r3
|
||||
subne r0, r0, #4
|
||||
|
||||
@ Find the bit-offset of the match within the word. Note that the
|
||||
@ bit result from clz will be 7 higher than "true", but we'll
|
||||
@ immediately discard those bits converting to a byte offset.
|
||||
#ifdef __ARMEL__
|
||||
rev r2, r2 @ For LE, count from the little end
|
||||
#endif
|
||||
clz r2, r2
|
||||
add r0, r0, r2, lsr #3 @ Adjust the pointer to the found byte
|
||||
99:
|
||||
sub r0, r0, r1 @ Subtract input to compute length
|
||||
bx lr
|
||||
|
||||
END (strlen)
|
||||
|
||||
libc_hidden_builtin_def (strlen)
|
131
sysdeps/arm/armv6/strrchr.S
Normal file
131
sysdeps/arm/armv6/strrchr.S
Normal file
@@ -0,0 +1,131 @@
|
||||
/* strrchr -- find the last occurence of C in a nul-terminated string
|
||||
Copyright (C) 2013-2014 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>
|
||||
|
||||
.syntax unified
|
||||
.text
|
||||
|
||||
ENTRY (strrchr)
|
||||
@ r0 = start of string
|
||||
@ r1 = character to match
|
||||
@ returns NULL for no match, or a pointer to the match
|
||||
|
||||
mov r3, r0
|
||||
mov r0, #0
|
||||
uxtb r1, r1
|
||||
|
||||
@ Loop a few times until we're aligned.
|
||||
tst r3, #7
|
||||
beq 2f
|
||||
1: sfi_breg r3, \
|
||||
ldrb r2, [\B], #1
|
||||
cmp r2, r1 @ Find the character
|
||||
it eq
|
||||
subeq r0, r3, #1
|
||||
cmp r2, #0 @ Find EOS
|
||||
it eq
|
||||
bxeq lr
|
||||
tst r3, #7 @ Find the aligment point
|
||||
bne 1b
|
||||
|
||||
@ So now we're aligned. Now we actually need a stack frame.
|
||||
2: 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)
|
||||
|
||||
orr r1, r1, r1, lsl #8 @ Replicate C to all bytes
|
||||
#ifdef ARCH_HAS_T2
|
||||
movw ip, #0x0101
|
||||
movt ip, #0x0101
|
||||
#else
|
||||
ldr ip, =0x01010101
|
||||
#endif
|
||||
orr r1, r1, r1, lsl #16
|
||||
mov r2, #0 @ No found bits yet
|
||||
|
||||
@ Loop searching for EOS and C, 8 bytes at a time.
|
||||
@ Any time we find a match in a word, we copy the address of
|
||||
@ the word to r0, and the found bits to r2.
|
||||
3: sfi_breg r3, \
|
||||
ldrd r4, r5, [\B], #8
|
||||
@ Subtracting (unsigned saturating) from 1 means result of 1 for
|
||||
@ any byte that was originally zero and 0 otherwise. Therefore
|
||||
@ we consider the lsb of each byte the "found" bit.
|
||||
uqsub8 r6, ip, r4 @ Find EOS
|
||||
uqsub8 r7, ip, r5
|
||||
eor r4, r4, r1 @ Convert C bytes to 0
|
||||
eor r5, r5, r1
|
||||
uqsub8 r4, ip, r4 @ Find C
|
||||
uqsub8 r5, ip, r5
|
||||
cmp r6, #0 @ Found EOS, first word
|
||||
bne 4f
|
||||
cmp r4, #0 @ Handle C, first word
|
||||
itt ne
|
||||
subne r0, r3, #8
|
||||
movne r2, r4
|
||||
cmp r7, #0 @ Found EOS, second word
|
||||
bne 5f
|
||||
cmp r5, #0 @ Handle C, second word
|
||||
itt ne
|
||||
subne r0, r3, #4
|
||||
movne r2, r5
|
||||
b 3b
|
||||
|
||||
@ Found EOS in second word; fold to first word.
|
||||
5: add r3, r3, #4 @ Dec pointer to 2nd word, with below
|
||||
mov r4, r5 @ Overwrite first word C found
|
||||
mov r6, r7 @ Overwrite first word EOS found
|
||||
|
||||
@ Found EOS. Zap found C after EOS.
|
||||
4: sub r3, r3, #8 @ Decrement pointer to first word
|
||||
#ifdef __ARMEB__
|
||||
@ Byte swap to be congruent with LE, which is easier from here on.
|
||||
rev r6, r6 @ Byte swap found EOS,
|
||||
rev r4, r4 @ ... this found C
|
||||
rev r2, r2 @ ... prev found C
|
||||
#endif
|
||||
sub r7, r6, #1 @ Toggle EOS lsb and below
|
||||
eor r6, r6, r7 @ All bits below and including lsb
|
||||
ands r4, r4, r6 @ Zap C above EOS
|
||||
itt ne
|
||||
movne r2, r4 @ Copy to result, if still non-zero
|
||||
movne r0, r3
|
||||
|
||||
pop { r4, r5, r6, r7 }
|
||||
cfi_adjust_cfa_offset (-16)
|
||||
cfi_restore (r4)
|
||||
cfi_restore (r5)
|
||||
cfi_restore (r6)
|
||||
cfi_restore (r7)
|
||||
|
||||
@ Adjust the result pointer if we found a word containing C.
|
||||
cmp r2, #0
|
||||
clz r2, r2 @ Find the bit offset of the last C
|
||||
itt ne
|
||||
rsbne r2, r2, #32 @ Convert to a count from the right
|
||||
addne r0, r0, r2, lsr #3 @ Convert to byte offset and add.
|
||||
bx lr
|
||||
|
||||
END (strrchr)
|
||||
|
||||
weak_alias (strrchr, rindex)
|
||||
libc_hidden_builtin_def (strrchr)
|
2
sysdeps/arm/armv6t2/Implies
Normal file
2
sysdeps/arm/armv6t2/Implies
Normal file
@@ -0,0 +1,2 @@
|
||||
# We can do everything that 6 can
|
||||
arm/armv6
|
36
sysdeps/arm/armv6t2/ffs.S
Normal file
36
sysdeps/arm/armv6t2/ffs.S
Normal file
@@ -0,0 +1,36 @@
|
||||
/* ffs -- find first set bit in an int, from least significant end.
|
||||
Copyright (C) 2013-2014 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>
|
||||
|
||||
.syntax unified
|
||||
.text
|
||||
|
||||
ENTRY (__ffs)
|
||||
cmp r0, #0
|
||||
rbit r0, r0
|
||||
itt ne
|
||||
clzne r0, r0
|
||||
addne r0, r0, #1
|
||||
bx lr
|
||||
END (__ffs)
|
||||
|
||||
weak_alias (__ffs, ffs)
|
||||
weak_alias (__ffs, ffsl)
|
||||
libc_hidden_def (__ffs)
|
||||
libc_hidden_builtin_def (ffs)
|
50
sysdeps/arm/armv6t2/ffsll.S
Normal file
50
sysdeps/arm/armv6t2/ffsll.S
Normal file
@@ -0,0 +1,50 @@
|
||||
/* ffsll -- find first set bit in a long long, from least significant end.
|
||||
Copyright (C) 2013-2014 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>
|
||||
|
||||
.syntax unified
|
||||
.text
|
||||
|
||||
ENTRY (ffsll)
|
||||
@ If low part is 0, operate on the high part. Ensure that the
|
||||
@ word on which we operate is in r0. Set r2 to the bit offset
|
||||
@ of the word being considered. Set the flags for the word
|
||||
@ being operated on.
|
||||
#ifdef __ARMEL__
|
||||
cmp r0, #0
|
||||
itee ne
|
||||
movne r2, #0
|
||||
moveq r2, #32
|
||||
movseq r0, r1
|
||||
#else
|
||||
cmp r1, #0
|
||||
ittee ne
|
||||
movne r2, #0
|
||||
movne r0, r1
|
||||
moveq r2, #32
|
||||
cmpeq r0, #0
|
||||
#endif
|
||||
@ Perform the ffs on r0.
|
||||
rbit r0, r0
|
||||
ittt ne
|
||||
clzne r0, r0
|
||||
addne r2, r2, #1
|
||||
addne r0, r0, r2
|
||||
bx lr
|
||||
END (ffsll)
|
187
sysdeps/arm/armv6t2/memchr.S
Normal file
187
sysdeps/arm/armv6t2/memchr.S
Normal file
@@ -0,0 +1,187 @@
|
||||
/* Copyright (C) 2011-2014 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
|
||||
#ifdef NO_THUMB
|
||||
.arm
|
||||
#else
|
||||
.thumb
|
||||
.thumb_func
|
||||
#endif
|
||||
.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:
|
||||
sfi_breg r0, \
|
||||
ldrb r3, [\B],#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 r6, r2, #7 @ Number of double words to work with * 8
|
||||
mvns r7, #0 @ all F's
|
||||
movs r3, #0
|
||||
|
||||
15:
|
||||
sfi_breg r0, \
|
||||
ldrd r4,r5, [\B],#8
|
||||
#ifndef NO_THUMB
|
||||
subs r6, r6, #8
|
||||
#endif
|
||||
eor r4,r4, r1 @ Get it so that r4,r5 have 00's where the bytes match the target
|
||||
eor r5,r5, r1
|
||||
uadd8 r4, r4, r7 @ Parallel add 0xff - sets the GE bits for anything that wasn't 0
|
||||
sel r4, r3, r7 @ bytes are 00 for none-00 bytes, or ff for 00 bytes - NOTE INVERSION
|
||||
uadd8 r5, r5, r7 @ Parallel add 0xff - sets the GE bits for anything that wasn't 0
|
||||
sel r5, r4, r7 @ chained....bytes are 00 for none-00 bytes, or ff for 00 bytes - NOTE INVERSION
|
||||
#ifndef NO_THUMB
|
||||
cbnz r5, 60f
|
||||
#else
|
||||
cmp r5, #0
|
||||
bne 60f
|
||||
subs r6, r6, #8
|
||||
#endif
|
||||
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:
|
||||
#ifndef NO_THUMB
|
||||
cbz r2, 40f @ 0 length or hit the end already then not found
|
||||
#else
|
||||
cmp r2, #0
|
||||
beq 40f
|
||||
#endif
|
||||
|
||||
21: @ Post aligned section, or just a short call
|
||||
sfi_breg r0, \
|
||||
ldrb r3,[\B],#1
|
||||
#ifndef NO_THUMB
|
||||
subs r2,r2,#1
|
||||
eor r3,r3,r1 @ r3 = 0 if match - doesn't break flags from sub
|
||||
cbz r3, 50f
|
||||
#else
|
||||
eors r3, r3, r1
|
||||
beq 50f
|
||||
subs r2, r2, #1
|
||||
#endif
|
||||
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
|
||||
@ r4 has the 00/ff pattern for the first word, r5 has the chained value
|
||||
cfi_restore_state
|
||||
cmp r4, #0
|
||||
itte eq
|
||||
moveq r4, r5 @ 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 r4, # CHARTSTMASK(0) @ 1st character
|
||||
bne 61f
|
||||
adds r0,r0,#1
|
||||
tst r4, # CHARTSTMASK(1) @ 2nd character
|
||||
ittt eq
|
||||
addeq r0,r0,#1
|
||||
tsteq r4, # (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)
|
169
sysdeps/arm/armv6t2/strlen.S
Normal file
169
sysdeps/arm/armv6t2/strlen.S
Normal file
@@ -0,0 +1,169 @@
|
||||
/* Copyright (C) 2010-2014 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/>. */
|
||||
|
||||
/*
|
||||
Assumes:
|
||||
ARMv6T2, AArch32
|
||||
|
||||
*/
|
||||
|
||||
#include <arm-features.h> /* This might #define NO_THUMB. */
|
||||
#include <sysdep.h>
|
||||
|
||||
#ifdef __ARMEB__
|
||||
#define S2LO lsl
|
||||
#define S2HI lsr
|
||||
#else
|
||||
#define S2LO lsr
|
||||
#define S2HI lsl
|
||||
#endif
|
||||
|
||||
#ifndef NO_THUMB
|
||||
/* This code is best on Thumb. */
|
||||
.thumb
|
||||
#else
|
||||
/* Using bne.w explicitly is desirable in Thumb mode because it helps
|
||||
align the following label without a nop. In ARM mode there is no
|
||||
such difference. */
|
||||
.macro bne.w label
|
||||
bne \label
|
||||
.endm
|
||||
|
||||
/* This clobbers the condition codes, which the real Thumb cbnz instruction
|
||||
does not do. But it doesn't matter for any of the uses here. */
|
||||
.macro cbnz reg, label
|
||||
cmp \reg, #0
|
||||
bne \label
|
||||
.endm
|
||||
#endif
|
||||
|
||||
/* Parameters and result. */
|
||||
#define srcin r0
|
||||
#define result r0
|
||||
|
||||
/* Internal variables. */
|
||||
#define src r1
|
||||
#define data1a r2
|
||||
#define data1b r3
|
||||
#define const_m1 r12
|
||||
#define const_0 r4
|
||||
#define tmp1 r4 /* Overlaps const_0 */
|
||||
#define tmp2 r5
|
||||
|
||||
.text
|
||||
.p2align 6
|
||||
ENTRY(strlen)
|
||||
sfi_pld srcin, #0
|
||||
strd r4, r5, [sp, #-8]!
|
||||
cfi_adjust_cfa_offset (8)
|
||||
cfi_rel_offset (r4, 0)
|
||||
cfi_rel_offset (r5, 4)
|
||||
cfi_remember_state
|
||||
bic src, srcin, #7
|
||||
mvn const_m1, #0
|
||||
ands tmp1, srcin, #7 /* (8 - bytes) to alignment. */
|
||||
sfi_pld src, #32
|
||||
bne.w .Lmisaligned8
|
||||
mov const_0, #0
|
||||
mov result, #-8
|
||||
.Lloop_aligned:
|
||||
/* Bytes 0-7. */
|
||||
sfi_breg src, \
|
||||
ldrd data1a, data1b, [\B]
|
||||
sfi_pld src, #64
|
||||
add result, result, #8
|
||||
.Lstart_realigned:
|
||||
uadd8 data1a, data1a, const_m1 /* Saturating GE<0:3> set. */
|
||||
sel data1a, const_0, const_m1 /* Select based on GE<0:3>. */
|
||||
uadd8 data1b, data1b, const_m1
|
||||
sel data1b, data1a, const_m1 /* Only used if d1a == 0. */
|
||||
cbnz data1b, .Lnull_found
|
||||
|
||||
/* Bytes 8-15. */
|
||||
sfi_breg src, \
|
||||
ldrd data1a, data1b, [\B, #8]
|
||||
uadd8 data1a, data1a, const_m1 /* Saturating GE<0:3> set. */
|
||||
add result, result, #8
|
||||
sel data1a, const_0, const_m1 /* Select based on GE<0:3>. */
|
||||
uadd8 data1b, data1b, const_m1
|
||||
sel data1b, data1a, const_m1 /* Only used if d1a == 0. */
|
||||
cbnz data1b, .Lnull_found
|
||||
|
||||
/* Bytes 16-23. */
|
||||
sfi_breg src, \
|
||||
ldrd data1a, data1b, [\B, #16]
|
||||
uadd8 data1a, data1a, const_m1 /* Saturating GE<0:3> set. */
|
||||
add result, result, #8
|
||||
sel data1a, const_0, const_m1 /* Select based on GE<0:3>. */
|
||||
uadd8 data1b, data1b, const_m1
|
||||
sel data1b, data1a, const_m1 /* Only used if d1a == 0. */
|
||||
cbnz data1b, .Lnull_found
|
||||
|
||||
/* Bytes 24-31. */
|
||||
sfi_breg src, \
|
||||
ldrd data1a, data1b, [\B, #24]
|
||||
add src, src, #32
|
||||
uadd8 data1a, data1a, const_m1 /* Saturating GE<0:3> set. */
|
||||
add result, result, #8
|
||||
sel data1a, const_0, const_m1 /* Select based on GE<0:3>. */
|
||||
uadd8 data1b, data1b, const_m1
|
||||
sel data1b, data1a, const_m1 /* Only used if d1a == 0. */
|
||||
cmp data1b, #0
|
||||
beq .Lloop_aligned
|
||||
|
||||
.Lnull_found:
|
||||
cmp data1a, #0
|
||||
itt eq
|
||||
addeq result, result, #4
|
||||
moveq data1a, data1b
|
||||
#ifndef __ARMEB__
|
||||
rev data1a, data1a
|
||||
#endif
|
||||
clz data1a, data1a
|
||||
ldrd r4, r5, [sp], #8
|
||||
cfi_adjust_cfa_offset (-8)
|
||||
cfi_restore (r4)
|
||||
cfi_restore (r5)
|
||||
add result, result, data1a, lsr #3 /* Bits -> Bytes. */
|
||||
DO_RET(lr)
|
||||
|
||||
.Lmisaligned8:
|
||||
cfi_restore_state
|
||||
sfi_breg src, \
|
||||
ldrd data1a, data1b, [\B]
|
||||
and tmp2, tmp1, #3
|
||||
rsb result, tmp1, #0
|
||||
lsl tmp2, tmp2, #3 /* Bytes -> bits. */
|
||||
tst tmp1, #4
|
||||
sfi_pld src, #64
|
||||
S2HI tmp2, const_m1, tmp2
|
||||
#ifdef NO_THUMB
|
||||
mvn tmp1, tmp2
|
||||
orr data1a, data1a, tmp1
|
||||
itt ne
|
||||
orrne data1b, data1b, tmp1
|
||||
#else
|
||||
orn data1a, data1a, tmp2
|
||||
itt ne
|
||||
ornne data1b, data1b, tmp2
|
||||
#endif
|
||||
movne data1a, const_m1
|
||||
mov const_0, #0
|
||||
b .Lstart_realigned
|
||||
|
||||
END(strlen)
|
||||
libc_hidden_builtin_def (strlen)
|
2
sysdeps/arm/armv7/Implies
Normal file
2
sysdeps/arm/armv7/Implies
Normal file
@@ -0,0 +1,2 @@
|
||||
# We can do everything that 6T2 can
|
||||
arm/armv6t2
|
72
sysdeps/arm/armv7/configure
vendored
Normal file
72
sysdeps/arm/armv7/configure
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
# This file is generated from configure.ac by Autoconf. DO NOT EDIT!
|
||||
# Local configure fragment for sysdeps/arm/armv7.
|
||||
|
||||
# We need binutils 2.21 to ensure that NEON alignments are assembled correctly.
|
||||
libc_cv_arm_as_version_ok=yes
|
||||
for ac_prog in $AS
|
||||
do
|
||||
# Extract the first word of "$ac_prog", so it can be a program name with args.
|
||||
set dummy $ac_prog; ac_word=$2
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
|
||||
$as_echo_n "checking for $ac_word... " >&6; }
|
||||
if ${ac_cv_prog_AS+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
if test -n "$AS"; then
|
||||
ac_cv_prog_AS="$AS" # Let the user override the test.
|
||||
else
|
||||
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
|
||||
for as_dir in $PATH
|
||||
do
|
||||
IFS=$as_save_IFS
|
||||
test -z "$as_dir" && as_dir=.
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
|
||||
ac_cv_prog_AS="$ac_prog"
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
break 2
|
||||
fi
|
||||
done
|
||||
done
|
||||
IFS=$as_save_IFS
|
||||
|
||||
fi
|
||||
fi
|
||||
AS=$ac_cv_prog_AS
|
||||
if test -n "$AS"; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $AS" >&5
|
||||
$as_echo "$AS" >&6; }
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
fi
|
||||
|
||||
|
||||
test -n "$AS" && break
|
||||
done
|
||||
|
||||
if test -z "$AS"; then
|
||||
ac_verc_fail=yes
|
||||
else
|
||||
# Found it, now check the version.
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking version of $AS" >&5
|
||||
$as_echo_n "checking version of $AS... " >&6; }
|
||||
ac_prog_version=`$AS --version 2>&1 | sed -n 's/^.*GNU assembler.* \([0-9]*\.[0-9.]*\).*$/\1/p'`
|
||||
case $ac_prog_version in
|
||||
'') ac_prog_version="v. ?.??, bad"; ac_verc_fail=yes;;
|
||||
2.1[0-9][0-9]*|2.2[1-9]*|2.[3-9][0-9]*|[3-9].*|[1-9][0-9]*)
|
||||
ac_prog_version="$ac_prog_version, ok"; ac_verc_fail=no;;
|
||||
*) ac_prog_version="$ac_prog_version, bad"; ac_verc_fail=yes;;
|
||||
|
||||
esac
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_prog_version" >&5
|
||||
$as_echo "$ac_prog_version" >&6; }
|
||||
fi
|
||||
if test $ac_verc_fail = yes; then
|
||||
libc_cv_arm_as_version_ok=no
|
||||
fi
|
||||
|
||||
|
||||
if test $libc_cv_arm_as_version_ok != yes; then
|
||||
as_fn_error $? "as version too old, at least 2.21 is required" "$LINENO" 5
|
||||
fi
|
12
sysdeps/arm/armv7/configure.ac
Normal file
12
sysdeps/arm/armv7/configure.ac
Normal file
@@ -0,0 +1,12 @@
|
||||
GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory.
|
||||
# Local configure fragment for sysdeps/arm/armv7.
|
||||
|
||||
# We need binutils 2.21 to ensure that NEON alignments are assembled correctly.
|
||||
libc_cv_arm_as_version_ok=yes
|
||||
AC_CHECK_PROG_VER(AS, $AS, --version,
|
||||
[GNU assembler.* \([0-9]*\.[0-9.]*\)],
|
||||
[2.1[0-9][0-9]*|2.2[1-9]*|2.[3-9][0-9]*|[3-9].*|[1-9][0-9]*], libc_cv_arm_as_version_ok=no)
|
||||
|
||||
if test $libc_cv_arm_as_version_ok != yes; then
|
||||
AC_MSG_ERROR([as version too old, at least 2.21 is required])
|
||||
fi
|
3
sysdeps/arm/armv7/multiarch/Makefile
Normal file
3
sysdeps/arm/armv7/multiarch/Makefile
Normal file
@@ -0,0 +1,3 @@
|
||||
ifeq ($(subdir),string)
|
||||
sysdep_routines += memcpy_neon memcpy_vfp
|
||||
endif
|
2
sysdeps/arm/armv7/multiarch/aeabi_memcpy.c
Normal file
2
sysdeps/arm/armv7/multiarch/aeabi_memcpy.c
Normal file
@@ -0,0 +1,2 @@
|
||||
/* Empty file to override sysdeps/arm version. See memcpy.S for definitions
|
||||
of these functions. */
|
56
sysdeps/arm/armv7/multiarch/ifunc-impl-list.c
Normal file
56
sysdeps/arm/armv7/multiarch/ifunc-impl-list.c
Normal file
@@ -0,0 +1,56 @@
|
||||
/* Enumerate available IFUNC implementations of a function. ARM version.
|
||||
Copyright (C) 2013-2014 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 <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <ldsodefs.h>
|
||||
#include <sysdep.h>
|
||||
#include <ifunc-impl-list.h>
|
||||
|
||||
/* Fill ARRAY of MAX elements with IFUNC implementations for function
|
||||
NAME and return the number of valid entries. */
|
||||
|
||||
size_t
|
||||
__libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
size_t max)
|
||||
{
|
||||
size_t i = 0;
|
||||
|
||||
bool use_neon = true;
|
||||
#ifdef __ARM_NEON__
|
||||
# define __memcpy_neon memcpy
|
||||
#else
|
||||
use_neon = (GLRO(dl_hwcap) & HWCAP_ARM_NEON) != 0;
|
||||
#endif
|
||||
|
||||
#ifndef __ARM_NEON__
|
||||
bool use_vfp = true;
|
||||
# ifdef __SOFTFP__
|
||||
use_vfp = (GLRO(dl_hwcap) & HWCAP_ARM_VFP) != 0;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
IFUNC_IMPL (i, name, memcpy,
|
||||
IFUNC_IMPL_ADD (array, i, memcpy, use_neon, __memcpy_neon)
|
||||
#ifndef __ARM_NEON__
|
||||
IFUNC_IMPL_ADD (array, i, memcpy, use_vfp, __memcpy_vfp)
|
||||
#endif
|
||||
IFUNC_IMPL_ADD (array, i, memcpy, 1, __memcpy_arm));
|
||||
|
||||
return i;
|
||||
}
|
76
sysdeps/arm/armv7/multiarch/memcpy.S
Normal file
76
sysdeps/arm/armv7/multiarch/memcpy.S
Normal file
@@ -0,0 +1,76 @@
|
||||
/* Multiple versions of memcpy
|
||||
All versions must be listed in ifunc-impl-list.c.
|
||||
Copyright (C) 2013-2014 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/>. */
|
||||
|
||||
/* Thumb requires excess IT instructions here. */
|
||||
#define NO_THUMB
|
||||
#include <sysdep.h>
|
||||
#include <rtld-global-offsets.h>
|
||||
|
||||
#ifndef NOT_IN_libc
|
||||
/* Under __ARM_NEON__, memcpy_neon.S defines the name memcpy. */
|
||||
# ifndef __ARM_NEON__
|
||||
.text
|
||||
ENTRY(memcpy)
|
||||
.type memcpy, %gnu_indirect_function
|
||||
# ifdef __SOFTFP__
|
||||
ldr r1, .Lmemcpy_arm
|
||||
tst r0, #HWCAP_ARM_VFP
|
||||
ldrne r1, .Lmemcpy_vfp
|
||||
# else
|
||||
ldr r1, .Lmemcpy_vfp
|
||||
# endif
|
||||
tst r0, #HWCAP_ARM_NEON
|
||||
ldrne r1, .Lmemcpy_neon
|
||||
1:
|
||||
add r0, r1, pc
|
||||
DO_RET(lr)
|
||||
|
||||
# ifdef __SOFTFP__
|
||||
.Lmemcpy_arm:
|
||||
.long C_SYMBOL_NAME(__memcpy_arm) - 1b - PC_OFS
|
||||
# endif
|
||||
.Lmemcpy_neon:
|
||||
.long C_SYMBOL_NAME(__memcpy_neon) - 1b - PC_OFS
|
||||
.Lmemcpy_vfp:
|
||||
.long C_SYMBOL_NAME(__memcpy_vfp) - 1b - PC_OFS
|
||||
|
||||
END(memcpy)
|
||||
|
||||
libc_hidden_builtin_def (memcpy)
|
||||
#endif /* Not __ARM_NEON__. */
|
||||
|
||||
/* These versions of memcpy are defined not to clobber any VFP or NEON
|
||||
registers so they must always call the ARM variant of the memcpy code. */
|
||||
strong_alias (__memcpy_arm, __aeabi_memcpy)
|
||||
strong_alias (__memcpy_arm, __aeabi_memcpy4)
|
||||
strong_alias (__memcpy_arm, __aeabi_memcpy8)
|
||||
libc_hidden_def (__memcpy_arm)
|
||||
|
||||
#undef libc_hidden_builtin_def
|
||||
#define libc_hidden_builtin_def(name)
|
||||
#undef weak_alias
|
||||
#define weak_alias(x, y)
|
||||
#undef libc_hidden_def
|
||||
#define libc_hidden_def(name)
|
||||
|
||||
#define memcpy __memcpy_arm
|
||||
|
||||
#endif
|
||||
|
||||
#include "memcpy_impl.S"
|
917
sysdeps/arm/armv7/multiarch/memcpy_impl.S
Normal file
917
sysdeps/arm/armv7/multiarch/memcpy_impl.S
Normal file
@@ -0,0 +1,917 @@
|
||||
/* NEON/VFP/ARM version of memcpy optimized for Cortex-A15.
|
||||
Copyright (C) 2013-2014 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 memcpy routine is optimised for Cortex-A15 cores and takes advantage
|
||||
of VFP or NEON when built with the appropriate flags.
|
||||
|
||||
Assumptions:
|
||||
|
||||
ARMv6 (ARMv7-a if using Neon)
|
||||
ARM state
|
||||
Unaligned accesses
|
||||
|
||||
*/
|
||||
|
||||
/* Thumb cannot encode negative immediate offsets in memory operations. */
|
||||
#ifndef NO_THUMB
|
||||
#define NO_THUMB
|
||||
#endif
|
||||
#include <sysdep.h>
|
||||
#include <arm-features.h>
|
||||
|
||||
.syntax unified
|
||||
/* This implementation requires ARM state. */
|
||||
.arm
|
||||
|
||||
#ifdef MEMCPY_NEON
|
||||
|
||||
.fpu neon
|
||||
.arch armv7-a
|
||||
# define FRAME_SIZE 4
|
||||
# define USE_VFP
|
||||
# define USE_NEON
|
||||
|
||||
#elif defined (MEMCPY_VFP)
|
||||
|
||||
.arch armv6
|
||||
.fpu vfpv2
|
||||
# define FRAME_SIZE 32
|
||||
# define USE_VFP
|
||||
|
||||
#else
|
||||
.arch armv6
|
||||
# define FRAME_SIZE 32
|
||||
|
||||
#endif
|
||||
|
||||
#define ALIGN(addr, align) addr:align
|
||||
|
||||
#define INSN_SIZE 4
|
||||
|
||||
/* Call parameters. */
|
||||
#define dstin r0
|
||||
#define src r1
|
||||
#define count r2
|
||||
|
||||
/* Locals. */
|
||||
#define tmp1 r3
|
||||
#define dst ip
|
||||
#define tmp2 r8
|
||||
|
||||
/* These two macros both work by repeated invocation of the macro
|
||||
dispatch_step (not defined here). That macro performs one "step",
|
||||
doing one load instruction and one store instruction to copy one
|
||||
"unit". On entry, TMP1 contains the number of bytes to be copied,
|
||||
a multiple of the unit size. The macro clobbers TMP1 in the
|
||||
process of doing a computed jump to the tail containing the
|
||||
appropriate number of steps.
|
||||
|
||||
In dispatch_7_dword, dispatch_step is invoked seven times, with an
|
||||
argument that is 7 for the first and 1 for the last. Units are
|
||||
double-words (8 bytes). TMP1 is at most 56.
|
||||
|
||||
In dispatch_15_word, dispatch_step is invoked fifteen times,
|
||||
with an argument that is 15 for the first and 1 for the last.
|
||||
Units are words (4 bytes). TMP1 is at most 60. */
|
||||
|
||||
#ifndef ARM_ALWAYS_BX
|
||||
# if ARM_BX_ALIGN_LOG2 != 2
|
||||
# error case not handled
|
||||
# endif
|
||||
.macro dispatch_7_dword
|
||||
rsb tmp1, tmp1, #((7 * 8) - PC_OFS + INSN_SIZE)
|
||||
add pc, pc, tmp1
|
||||
dispatch_step 7
|
||||
dispatch_step 6
|
||||
dispatch_step 5
|
||||
dispatch_step 4
|
||||
dispatch_step 3
|
||||
dispatch_step 2
|
||||
dispatch_step 1
|
||||
.purgem dispatch_step
|
||||
.endm
|
||||
|
||||
.macro dispatch_15_word
|
||||
rsb tmp1, tmp1, #((15 * 4) - PC_OFS/2 + INSN_SIZE/2)
|
||||
add pc, pc, tmp1, lsl #1
|
||||
dispatch_step 15
|
||||
dispatch_step 14
|
||||
dispatch_step 13
|
||||
dispatch_step 12
|
||||
dispatch_step 11
|
||||
dispatch_step 10
|
||||
dispatch_step 9
|
||||
dispatch_step 8
|
||||
dispatch_step 7
|
||||
dispatch_step 6
|
||||
dispatch_step 5
|
||||
dispatch_step 4
|
||||
dispatch_step 3
|
||||
dispatch_step 2
|
||||
dispatch_step 1
|
||||
.purgem dispatch_step
|
||||
.endm
|
||||
#else
|
||||
# if ARM_BX_ALIGN_LOG2 < 3
|
||||
# error case not handled
|
||||
# endif
|
||||
.macro dispatch_helper steps, log2_bytes_per_step
|
||||
/* TMP1 gets (max_bytes - bytes_to_copy), where max_bytes is
|
||||
(STEPS << LOG2_BYTES_PER_STEP).
|
||||
So this is (steps_to_skip << LOG2_BYTES_PER_STEP).
|
||||
Then it needs further adjustment to compensate for the
|
||||
distance between the PC value taken below (0f + PC_OFS)
|
||||
and the first step's instructions (1f). */
|
||||
rsb tmp1, tmp1, #((\steps << \log2_bytes_per_step) \
|
||||
+ ((1f - PC_OFS - 0f) \
|
||||
>> (ARM_BX_ALIGN_LOG2 - \log2_bytes_per_step)))
|
||||
/* Shifting down LOG2_BYTES_PER_STEP gives us the number of
|
||||
steps to skip, then shifting up ARM_BX_ALIGN_LOG2 gives us
|
||||
the (byte) distance to add to the PC. */
|
||||
0: add tmp1, pc, tmp1, lsl #(ARM_BX_ALIGN_LOG2 - \log2_bytes_per_step)
|
||||
bx tmp1
|
||||
.p2align ARM_BX_ALIGN_LOG2
|
||||
1:
|
||||
.endm
|
||||
|
||||
.macro dispatch_7_dword
|
||||
dispatch_helper 7, 3
|
||||
.p2align ARM_BX_ALIGN_LOG2
|
||||
dispatch_step 7
|
||||
.p2align ARM_BX_ALIGN_LOG2
|
||||
dispatch_step 6
|
||||
.p2align ARM_BX_ALIGN_LOG2
|
||||
dispatch_step 5
|
||||
.p2align ARM_BX_ALIGN_LOG2
|
||||
dispatch_step 4
|
||||
.p2align ARM_BX_ALIGN_LOG2
|
||||
dispatch_step 3
|
||||
.p2align ARM_BX_ALIGN_LOG2
|
||||
dispatch_step 2
|
||||
.p2align ARM_BX_ALIGN_LOG2
|
||||
dispatch_step 1
|
||||
.p2align ARM_BX_ALIGN_LOG2
|
||||
.purgem dispatch_step
|
||||
.endm
|
||||
|
||||
.macro dispatch_15_word
|
||||
dispatch_helper 15, 2
|
||||
dispatch_step 15
|
||||
.p2align ARM_BX_ALIGN_LOG2
|
||||
dispatch_step 14
|
||||
.p2align ARM_BX_ALIGN_LOG2
|
||||
dispatch_step 13
|
||||
.p2align ARM_BX_ALIGN_LOG2
|
||||
dispatch_step 12
|
||||
.p2align ARM_BX_ALIGN_LOG2
|
||||
dispatch_step 11
|
||||
.p2align ARM_BX_ALIGN_LOG2
|
||||
dispatch_step 10
|
||||
.p2align ARM_BX_ALIGN_LOG2
|
||||
dispatch_step 9
|
||||
.p2align ARM_BX_ALIGN_LOG2
|
||||
dispatch_step 8
|
||||
.p2align ARM_BX_ALIGN_LOG2
|
||||
dispatch_step 7
|
||||
.p2align ARM_BX_ALIGN_LOG2
|
||||
dispatch_step 6
|
||||
.p2align ARM_BX_ALIGN_LOG2
|
||||
dispatch_step 5
|
||||
.p2align ARM_BX_ALIGN_LOG2
|
||||
dispatch_step 4
|
||||
.p2align ARM_BX_ALIGN_LOG2
|
||||
dispatch_step 3
|
||||
.p2align ARM_BX_ALIGN_LOG2
|
||||
dispatch_step 2
|
||||
.p2align ARM_BX_ALIGN_LOG2
|
||||
dispatch_step 1
|
||||
.p2align ARM_BX_ALIGN_LOG2
|
||||
.purgem dispatch_step
|
||||
.endm
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef USE_NEON
|
||||
/* For bulk copies using GP registers. */
|
||||
#define A_l r2 /* Call-clobbered. */
|
||||
#define A_h r3 /* Call-clobbered. */
|
||||
#define B_l r4
|
||||
#define B_h r5
|
||||
#define C_l r6
|
||||
#define C_h r7
|
||||
/* Don't use the pair r8,r9 because in some EABI variants r9 is reserved. */
|
||||
#define D_l r10
|
||||
#define D_h r11
|
||||
#endif
|
||||
|
||||
/* Number of lines ahead to pre-fetch data. If you change this the code
|
||||
below will need adjustment to compensate. */
|
||||
|
||||
#define prefetch_lines 5
|
||||
|
||||
#ifdef USE_VFP
|
||||
.macro cpy_line_vfp vreg, base
|
||||
sfi_breg dst, \
|
||||
vstr \vreg, [\B, #\base]
|
||||
sfi_breg src, \
|
||||
vldr \vreg, [\B, #\base]
|
||||
sfi_breg dst, \
|
||||
vstr d0, [\B, #\base + 8]
|
||||
sfi_breg src, \
|
||||
vldr d0, [\B, #\base + 8]
|
||||
sfi_breg dst, \
|
||||
vstr d1, [\B, #\base + 16]
|
||||
sfi_breg src, \
|
||||
vldr d1, [\B, #\base + 16]
|
||||
sfi_breg dst, \
|
||||
vstr d2, [\B, #\base + 24]
|
||||
sfi_breg src, \
|
||||
vldr d2, [\B, #\base + 24]
|
||||
sfi_breg dst, \
|
||||
vstr \vreg, [\B, #\base + 32]
|
||||
sfi_breg src, \
|
||||
vldr \vreg, [\B, #\base + prefetch_lines * 64 - 32]
|
||||
sfi_breg dst, \
|
||||
vstr d0, [\B, #\base + 40]
|
||||
sfi_breg src, \
|
||||
vldr d0, [\B, #\base + 40]
|
||||
sfi_breg dst, \
|
||||
vstr d1, [\B, #\base + 48]
|
||||
sfi_breg src, \
|
||||
vldr d1, [\B, #\base + 48]
|
||||
sfi_breg dst, \
|
||||
vstr d2, [\B, #\base + 56]
|
||||
sfi_breg src, \
|
||||
vldr d2, [\B, #\base + 56]
|
||||
.endm
|
||||
|
||||
.macro cpy_tail_vfp vreg, base
|
||||
sfi_breg dst, \
|
||||
vstr \vreg, [\B, #\base]
|
||||
sfi_breg src, \
|
||||
vldr \vreg, [\B, #\base]
|
||||
sfi_breg dst, \
|
||||
vstr d0, [\B, #\base + 8]
|
||||
sfi_breg src, \
|
||||
vldr d0, [\B, #\base + 8]
|
||||
sfi_breg dst, \
|
||||
vstr d1, [\B, #\base + 16]
|
||||
sfi_breg src, \
|
||||
vldr d1, [\B, #\base + 16]
|
||||
sfi_breg dst, \
|
||||
vstr d2, [\B, #\base + 24]
|
||||
sfi_breg src, \
|
||||
vldr d2, [\B, #\base + 24]
|
||||
sfi_breg dst, \
|
||||
vstr \vreg, [\B, #\base + 32]
|
||||
sfi_breg dst, \
|
||||
vstr d0, [\B, #\base + 40]
|
||||
sfi_breg src, \
|
||||
vldr d0, [\B, #\base + 40]
|
||||
sfi_breg dst, \
|
||||
vstr d1, [\B, #\base + 48]
|
||||
sfi_breg src, \
|
||||
vldr d1, [\B, #\base + 48]
|
||||
sfi_breg dst, \
|
||||
vstr d2, [\B, #\base + 56]
|
||||
sfi_breg src, \
|
||||
vldr d2, [\B, #\base + 56]
|
||||
.endm
|
||||
#endif
|
||||
|
||||
.p2align 6
|
||||
ENTRY(memcpy)
|
||||
|
||||
mov dst, dstin /* Preserve dstin, we need to return it. */
|
||||
cmp count, #64
|
||||
bge .Lcpy_not_short
|
||||
/* Deal with small copies quickly by dropping straight into the
|
||||
exit block. */
|
||||
|
||||
.Ltail63unaligned:
|
||||
#ifdef USE_NEON
|
||||
/* These need an extra layer of macro just to work around a
|
||||
bug in the assembler's parser when an operand starts with
|
||||
a {...}. http://sourceware.org/bugzilla/show_bug.cgi?id=15647
|
||||
tracks that bug; it was not fixed as of binutils-2.23.2. */
|
||||
.macro neon_load_d0 reg
|
||||
vld1.8 {d0}, [\reg]!
|
||||
.endm
|
||||
.macro neon_store_d0 reg
|
||||
vst1.8 {d0}, [\reg]!
|
||||
.endm
|
||||
|
||||
/* These are used by the NaCl sfi_breg macro. */
|
||||
.macro _sfi_breg_dmask_neon_load_d0 reg
|
||||
_sfi_dmask \reg
|
||||
.endm
|
||||
.macro _sfi_breg_dmask_neon_store_d0 reg
|
||||
_sfi_dmask \reg
|
||||
.endm
|
||||
|
||||
and tmp1, count, #0x38
|
||||
.macro dispatch_step i
|
||||
sfi_breg src, neon_load_d0 \B
|
||||
sfi_breg dst, neon_store_d0 \B
|
||||
.endm
|
||||
dispatch_7_dword
|
||||
|
||||
tst count, #4
|
||||
sfi_breg src, \
|
||||
ldrne tmp1, [\B], #4
|
||||
sfi_breg dst, \
|
||||
strne tmp1, [\B], #4
|
||||
#else
|
||||
/* Copy up to 15 full words of data. May not be aligned. */
|
||||
/* Cannot use VFP for unaligned data. */
|
||||
and tmp1, count, #0x3c
|
||||
add dst, dst, tmp1
|
||||
add src, src, tmp1
|
||||
/* Jump directly into the sequence below at the correct offset. */
|
||||
.macro dispatch_step i
|
||||
sfi_breg src, \
|
||||
ldr tmp1, [\B, #-(\i * 4)]
|
||||
sfi_breg dst, \
|
||||
str tmp1, [\B, #-(\i * 4)]
|
||||
.endm
|
||||
dispatch_15_word
|
||||
#endif
|
||||
|
||||
lsls count, count, #31
|
||||
sfi_breg src, \
|
||||
ldrhcs tmp1, [\B], #2
|
||||
sfi_breg src, \
|
||||
ldrbne src, [\B] /* Src is dead, use as a scratch. */
|
||||
sfi_breg dst, \
|
||||
strhcs tmp1, [\B], #2
|
||||
sfi_breg dst, \
|
||||
strbne src, [\B]
|
||||
bx lr
|
||||
|
||||
.Lcpy_not_short:
|
||||
/* At least 64 bytes to copy, but don't know the alignment yet. */
|
||||
str tmp2, [sp, #-FRAME_SIZE]!
|
||||
cfi_adjust_cfa_offset (FRAME_SIZE)
|
||||
cfi_rel_offset (tmp2, 0)
|
||||
cfi_remember_state
|
||||
and tmp2, src, #7
|
||||
and tmp1, dst, #7
|
||||
cmp tmp1, tmp2
|
||||
bne .Lcpy_notaligned
|
||||
|
||||
#ifdef USE_VFP
|
||||
/* Magic dust alert! Force VFP on Cortex-A9. Experiments show
|
||||
that the FP pipeline is much better at streaming loads and
|
||||
stores. This is outside the critical loop. */
|
||||
vmov.f32 s0, s0
|
||||
#endif
|
||||
|
||||
/* SRC and DST have the same mutual 64-bit alignment, but we may
|
||||
still need to pre-copy some bytes to get to natural alignment.
|
||||
We bring SRC and DST into full 64-bit alignment. */
|
||||
lsls tmp2, dst, #29
|
||||
beq 1f
|
||||
rsbs tmp2, tmp2, #0
|
||||
sub count, count, tmp2, lsr #29
|
||||
sfi_breg src, \
|
||||
ldrmi tmp1, [\B], #4
|
||||
sfi_breg dst, \
|
||||
strmi tmp1, [\B], #4
|
||||
lsls tmp2, tmp2, #2
|
||||
sfi_breg src, \
|
||||
ldrhcs tmp1, [\B], #2
|
||||
sfi_breg src, \
|
||||
ldrbne tmp2, [\B], #1
|
||||
sfi_breg dst, \
|
||||
strhcs tmp1, [\B], #2
|
||||
sfi_breg dst, \
|
||||
strbne tmp2, [\B], #1
|
||||
|
||||
1:
|
||||
subs tmp2, count, #64 /* Use tmp2 for count. */
|
||||
blt .Ltail63aligned
|
||||
|
||||
cmp tmp2, #512
|
||||
bge .Lcpy_body_long
|
||||
|
||||
.Lcpy_body_medium: /* Count in tmp2. */
|
||||
#ifdef USE_VFP
|
||||
1:
|
||||
sfi_breg src, \
|
||||
vldr d0, [\B, #0]
|
||||
subs tmp2, tmp2, #64
|
||||
sfi_breg src, \
|
||||
vldr d1, [\B, #8]
|
||||
sfi_breg dst, \
|
||||
vstr d0, [\B, #0]
|
||||
sfi_breg src, \
|
||||
vldr d0, [\B, #16]
|
||||
sfi_breg dst, \
|
||||
vstr d1, [\B, #8]
|
||||
sfi_breg src, \
|
||||
vldr d1, [\B, #24]
|
||||
sfi_breg dst, \
|
||||
vstr d0, [\B, #16]
|
||||
sfi_breg src, \
|
||||
vldr d0, [\B, #32]
|
||||
sfi_breg dst, \
|
||||
vstr d1, [\B, #24]
|
||||
sfi_breg src, \
|
||||
vldr d1, [\B, #40]
|
||||
sfi_breg dst, \
|
||||
vstr d0, [\B, #32]
|
||||
sfi_breg src, \
|
||||
vldr d0, [\B, #48]
|
||||
sfi_breg dst, \
|
||||
vstr d1, [\B, #40]
|
||||
sfi_breg src, \
|
||||
vldr d1, [\B, #56]
|
||||
sfi_breg dst, \
|
||||
vstr d0, [\B, #48]
|
||||
add src, src, #64
|
||||
sfi_breg dst, \
|
||||
vstr d1, [\B, #56]
|
||||
add dst, dst, #64
|
||||
bge 1b
|
||||
tst tmp2, #0x3f
|
||||
beq .Ldone
|
||||
|
||||
.Ltail63aligned: /* Count in tmp2. */
|
||||
and tmp1, tmp2, #0x38
|
||||
add dst, dst, tmp1
|
||||
add src, src, tmp1
|
||||
.macro dispatch_step i
|
||||
sfi_breg src, \
|
||||
vldr d0, [\B, #-(\i * 8)]
|
||||
sfi_breg dst, \
|
||||
vstr d0, [\B, #-(\i * 8)]
|
||||
.endm
|
||||
dispatch_7_dword
|
||||
#else
|
||||
sub src, src, #8
|
||||
sub dst, dst, #8
|
||||
1:
|
||||
sfi_breg src, \
|
||||
ldrd A_l, A_h, [\B, #8]
|
||||
sfi_breg dst, \
|
||||
strd A_l, A_h, [\B, #8]
|
||||
sfi_breg src, \
|
||||
ldrd A_l, A_h, [\B, #16]
|
||||
sfi_breg dst, \
|
||||
strd A_l, A_h, [\B, #16]
|
||||
sfi_breg src, \
|
||||
ldrd A_l, A_h, [\B, #24]
|
||||
sfi_breg dst, \
|
||||
strd A_l, A_h, [\B, #24]
|
||||
sfi_breg src, \
|
||||
ldrd A_l, A_h, [\B, #32]
|
||||
sfi_breg dst, \
|
||||
strd A_l, A_h, [\B, #32]
|
||||
sfi_breg src, \
|
||||
ldrd A_l, A_h, [\B, #40]
|
||||
sfi_breg dst, \
|
||||
strd A_l, A_h, [\B, #40]
|
||||
sfi_breg src, \
|
||||
ldrd A_l, A_h, [\B, #48]
|
||||
sfi_breg dst, \
|
||||
strd A_l, A_h, [\B, #48]
|
||||
sfi_breg src, \
|
||||
ldrd A_l, A_h, [\B, #56]
|
||||
sfi_breg dst, \
|
||||
strd A_l, A_h, [\B, #56]
|
||||
sfi_breg src, \
|
||||
ldrd A_l, A_h, [\B, #64]!
|
||||
sfi_breg dst, \
|
||||
strd A_l, A_h, [\B, #64]!
|
||||
subs tmp2, tmp2, #64
|
||||
bge 1b
|
||||
tst tmp2, #0x3f
|
||||
bne 1f
|
||||
ldr tmp2,[sp], #FRAME_SIZE
|
||||
cfi_adjust_cfa_offset (-FRAME_SIZE)
|
||||
cfi_restore (tmp2)
|
||||
bx lr
|
||||
|
||||
cfi_restore_state
|
||||
cfi_remember_state
|
||||
1:
|
||||
add src, src, #8
|
||||
add dst, dst, #8
|
||||
|
||||
.Ltail63aligned: /* Count in tmp2. */
|
||||
/* Copy up to 7 d-words of data. Similar to Ltail63unaligned, but
|
||||
we know that the src and dest are 64-bit aligned so we can use
|
||||
LDRD/STRD to improve efficiency. */
|
||||
/* TMP2 is now negative, but we don't care about that. The bottom
|
||||
six bits still tell us how many bytes are left to copy. */
|
||||
|
||||
and tmp1, tmp2, #0x38
|
||||
add dst, dst, tmp1
|
||||
add src, src, tmp1
|
||||
.macro dispatch_step i
|
||||
sfi_breg src, \
|
||||
ldrd A_l, A_h, [\B, #-(\i * 8)]
|
||||
sfi_breg dst, \
|
||||
strd A_l, A_h, [\B, #-(\i * 8)]
|
||||
.endm
|
||||
dispatch_7_dword
|
||||
#endif
|
||||
|
||||
tst tmp2, #4
|
||||
sfi_breg src, \
|
||||
ldrne tmp1, [\B], #4
|
||||
sfi_breg dst, \
|
||||
strne tmp1, [\B], #4
|
||||
lsls tmp2, tmp2, #31 /* Count (tmp2) now dead. */
|
||||
sfi_breg src, \
|
||||
ldrhcs tmp1, [\B], #2
|
||||
sfi_breg src, \
|
||||
ldrbne tmp2, [\B]
|
||||
sfi_breg dst, \
|
||||
strhcs tmp1, [\B], #2
|
||||
sfi_breg dst, \
|
||||
strbne tmp2, [\B]
|
||||
|
||||
.Ldone:
|
||||
ldr tmp2, [sp], #FRAME_SIZE
|
||||
cfi_adjust_cfa_offset (-FRAME_SIZE)
|
||||
cfi_restore (tmp2)
|
||||
bx lr
|
||||
|
||||
cfi_restore_state
|
||||
cfi_remember_state
|
||||
|
||||
.Lcpy_body_long: /* Count in tmp2. */
|
||||
|
||||
/* Long copy. We know that there's at least (prefetch_lines * 64)
|
||||
bytes to go. */
|
||||
#ifdef USE_VFP
|
||||
/* Don't use PLD. Instead, read some data in advance of the current
|
||||
copy position into a register. This should act like a PLD
|
||||
operation but we won't have to repeat the transfer. */
|
||||
|
||||
sfi_breg src, \
|
||||
vldr d3, [\B, #0]
|
||||
sfi_breg src, \
|
||||
vldr d4, [\B, #64]
|
||||
sfi_breg src, \
|
||||
vldr d5, [\B, #128]
|
||||
sfi_breg src, \
|
||||
vldr d6, [\B, #192]
|
||||
sfi_breg src, \
|
||||
vldr d7, [\B, #256]
|
||||
|
||||
sfi_breg src, \
|
||||
vldr d0, [\B, #8]
|
||||
sfi_breg src, \
|
||||
vldr d1, [\B, #16]
|
||||
sfi_breg src, \
|
||||
vldr d2, [\B, #24]
|
||||
add src, src, #32
|
||||
|
||||
subs tmp2, tmp2, #prefetch_lines * 64 * 2
|
||||
blt 2f
|
||||
1:
|
||||
cpy_line_vfp d3, 0
|
||||
cpy_line_vfp d4, 64
|
||||
cpy_line_vfp d5, 128
|
||||
add dst, dst, #3 * 64
|
||||
add src, src, #3 * 64
|
||||
cpy_line_vfp d6, 0
|
||||
cpy_line_vfp d7, 64
|
||||
add dst, dst, #2 * 64
|
||||
add src, src, #2 * 64
|
||||
subs tmp2, tmp2, #prefetch_lines * 64
|
||||
bge 1b
|
||||
|
||||
2:
|
||||
cpy_tail_vfp d3, 0
|
||||
cpy_tail_vfp d4, 64
|
||||
cpy_tail_vfp d5, 128
|
||||
add src, src, #3 * 64
|
||||
add dst, dst, #3 * 64
|
||||
cpy_tail_vfp d6, 0
|
||||
sfi_breg dst, \
|
||||
vstr d7, [\B, #64]
|
||||
sfi_breg src, \
|
||||
vldr d7, [\B, #64]
|
||||
sfi_breg dst, \
|
||||
vstr d0, [\B, #64 + 8]
|
||||
sfi_breg src, \
|
||||
vldr d0, [\B, #64 + 8]
|
||||
sfi_breg dst, \
|
||||
vstr d1, [\B, #64 + 16]
|
||||
sfi_breg src, \
|
||||
vldr d1, [\B, #64 + 16]
|
||||
sfi_breg dst, \
|
||||
vstr d2, [\B, #64 + 24]
|
||||
sfi_breg src, \
|
||||
vldr d2, [\B, #64 + 24]
|
||||
sfi_breg dst, \
|
||||
vstr d7, [\B, #64 + 32]
|
||||
add src, src, #96
|
||||
sfi_breg dst, \
|
||||
vstr d0, [\B, #64 + 40]
|
||||
sfi_breg dst, \
|
||||
vstr d1, [\B, #64 + 48]
|
||||
sfi_breg dst, \
|
||||
vstr d2, [\B, #64 + 56]
|
||||
add dst, dst, #128
|
||||
add tmp2, tmp2, #prefetch_lines * 64
|
||||
b .Lcpy_body_medium
|
||||
#else
|
||||
/* Long copy. Use an SMS style loop to maximize the I/O
|
||||
bandwidth of the core. We don't have enough spare registers
|
||||
to synthesise prefetching, so use PLD operations. */
|
||||
/* Pre-bias src and dst. */
|
||||
sub src, src, #8
|
||||
sub dst, dst, #8
|
||||
sfi_pld src, #8
|
||||
sfi_pld src, #72
|
||||
subs tmp2, tmp2, #64
|
||||
sfi_pld src, #136
|
||||
sfi_breg src, \
|
||||
ldrd A_l, A_h, [\B, #8]
|
||||
strd B_l, B_h, [sp, #8]
|
||||
cfi_rel_offset (B_l, 8)
|
||||
cfi_rel_offset (B_h, 12)
|
||||
sfi_breg src, \
|
||||
ldrd B_l, B_h, [\B, #16]
|
||||
strd C_l, C_h, [sp, #16]
|
||||
cfi_rel_offset (C_l, 16)
|
||||
cfi_rel_offset (C_h, 20)
|
||||
sfi_breg src, \
|
||||
ldrd C_l, C_h, [\B, #24]
|
||||
strd D_l, D_h, [sp, #24]
|
||||
cfi_rel_offset (D_l, 24)
|
||||
cfi_rel_offset (D_h, 28)
|
||||
sfi_pld src, #200
|
||||
sfi_breg src, \
|
||||
ldrd D_l, D_h, [\B, #32]!
|
||||
b 1f
|
||||
.p2align 6
|
||||
2:
|
||||
sfi_pld src, #232
|
||||
sfi_breg dst, \
|
||||
strd A_l, A_h, [\B, #40]
|
||||
sfi_breg src, \
|
||||
ldrd A_l, A_h, [\B, #40]
|
||||
sfi_breg dst, \
|
||||
strd B_l, B_h, [\B, #48]
|
||||
sfi_breg src, \
|
||||
ldrd B_l, B_h, [\B, #48]
|
||||
sfi_breg dst, \
|
||||
strd C_l, C_h, [\B, #56]
|
||||
sfi_breg src, \
|
||||
ldrd C_l, C_h, [\B, #56]
|
||||
sfi_breg dst, \
|
||||
strd D_l, D_h, [\B, #64]!
|
||||
sfi_breg src, \
|
||||
ldrd D_l, D_h, [\B, #64]!
|
||||
subs tmp2, tmp2, #64
|
||||
1:
|
||||
sfi_breg dst, \
|
||||
strd A_l, A_h, [\B, #8]
|
||||
sfi_breg src, \
|
||||
ldrd A_l, A_h, [\B, #8]
|
||||
sfi_breg dst, \
|
||||
strd B_l, B_h, [\B, #16]
|
||||
sfi_breg src, \
|
||||
ldrd B_l, B_h, [\B, #16]
|
||||
sfi_breg dst, \
|
||||
strd C_l, C_h, [\B, #24]
|
||||
sfi_breg src, \
|
||||
ldrd C_l, C_h, [\B, #24]
|
||||
sfi_breg dst, \
|
||||
strd D_l, D_h, [\B, #32]
|
||||
sfi_breg src, \
|
||||
ldrd D_l, D_h, [\B, #32]
|
||||
bcs 2b
|
||||
/* Save the remaining bytes and restore the callee-saved regs. */
|
||||
sfi_breg dst, \
|
||||
strd A_l, A_h, [\B, #40]
|
||||
add src, src, #40
|
||||
sfi_breg dst, \
|
||||
strd B_l, B_h, [\B, #48]
|
||||
ldrd B_l, B_h, [sp, #8]
|
||||
cfi_restore (B_l)
|
||||
cfi_restore (B_h)
|
||||
sfi_breg dst, \
|
||||
strd C_l, C_h, [\B, #56]
|
||||
ldrd C_l, C_h, [sp, #16]
|
||||
cfi_restore (C_l)
|
||||
cfi_restore (C_h)
|
||||
sfi_breg dst, \
|
||||
strd D_l, D_h, [\B, #64]
|
||||
ldrd D_l, D_h, [sp, #24]
|
||||
cfi_restore (D_l)
|
||||
cfi_restore (D_h)
|
||||
add dst, dst, #72
|
||||
tst tmp2, #0x3f
|
||||
bne .Ltail63aligned
|
||||
ldr tmp2, [sp], #FRAME_SIZE
|
||||
cfi_adjust_cfa_offset (-FRAME_SIZE)
|
||||
cfi_restore (tmp2)
|
||||
bx lr
|
||||
#endif
|
||||
|
||||
cfi_restore_state
|
||||
cfi_remember_state
|
||||
|
||||
.Lcpy_notaligned:
|
||||
sfi_pld src
|
||||
sfi_pld src, #64
|
||||
/* There's at least 64 bytes to copy, but there is no mutual
|
||||
alignment. */
|
||||
/* Bring DST to 64-bit alignment. */
|
||||
lsls tmp2, dst, #29
|
||||
sfi_pld src, #(2 * 64)
|
||||
beq 1f
|
||||
rsbs tmp2, tmp2, #0
|
||||
sub count, count, tmp2, lsr #29
|
||||
sfi_breg src, \
|
||||
ldrmi tmp1, [\B], #4
|
||||
sfi_breg dst, \
|
||||
strmi tmp1, [\B], #4
|
||||
lsls tmp2, tmp2, #2
|
||||
sfi_breg src, \
|
||||
ldrbne tmp1, [\B], #1
|
||||
sfi_breg src, \
|
||||
ldrhcs tmp2, [\B], #2
|
||||
sfi_breg dst, \
|
||||
strbne tmp1, [\B], #1
|
||||
sfi_breg dst, \
|
||||
strhcs tmp2, [\B], #2
|
||||
1:
|
||||
sfi_pld src, #(3 * 64)
|
||||
subs count, count, #64
|
||||
ldrmi tmp2, [sp], #FRAME_SIZE
|
||||
bmi .Ltail63unaligned
|
||||
sfi_pld src, #(4 * 64)
|
||||
|
||||
#ifdef USE_NEON
|
||||
/* These need an extra layer of macro just to work around a
|
||||
bug in the assembler's parser when an operand starts with
|
||||
a {...}. */
|
||||
.macro neon_load_multi reglist, basereg
|
||||
vld1.8 {\reglist}, [\basereg]!
|
||||
.endm
|
||||
.macro neon_store_multi reglist, basereg
|
||||
vst1.8 {\reglist}, [ALIGN (\basereg, 64)]!
|
||||
.endm
|
||||
|
||||
/* These are used by the NaCl sfi_breg macro. */
|
||||
.macro _sfi_breg_dmask_neon_load_multi reg
|
||||
_sfi_dmask \reg
|
||||
.endm
|
||||
.macro _sfi_breg_dmask_neon_store_multi reg
|
||||
_sfi_dmask \reg
|
||||
.endm
|
||||
|
||||
sfi_breg src, neon_load_multi d0-d3, \B
|
||||
sfi_breg src, neon_load_multi d4-d7, \B
|
||||
subs count, count, #64
|
||||
bmi 2f
|
||||
1:
|
||||
sfi_pld src, #(4 * 64)
|
||||
sfi_breg dst, neon_store_multi d0-d3, \B
|
||||
sfi_breg src, neon_load_multi d0-d3, \B
|
||||
sfi_breg dst, neon_store_multi d4-d7, \B
|
||||
sfi_breg src, neon_load_multi d4-d7, \B
|
||||
subs count, count, #64
|
||||
bpl 1b
|
||||
2:
|
||||
sfi_breg dst, neon_store_multi d0-d3, \B
|
||||
sfi_breg dst, neon_store_multi d4-d7, \B
|
||||
ands count, count, #0x3f
|
||||
#else
|
||||
/* Use an SMS style loop to maximize the I/O bandwidth. */
|
||||
sub src, src, #4
|
||||
sub dst, dst, #8
|
||||
subs tmp2, count, #64 /* Use tmp2 for count. */
|
||||
sfi_breg src, \
|
||||
ldr A_l, [\B, #4]
|
||||
sfi_breg src, \
|
||||
ldr A_h, [\B, #8]
|
||||
strd B_l, B_h, [sp, #8]
|
||||
cfi_rel_offset (B_l, 8)
|
||||
cfi_rel_offset (B_h, 12)
|
||||
sfi_breg src, \
|
||||
ldr B_l, [\B, #12]
|
||||
sfi_breg src, \
|
||||
ldr B_h, [\B, #16]
|
||||
strd C_l, C_h, [sp, #16]
|
||||
cfi_rel_offset (C_l, 16)
|
||||
cfi_rel_offset (C_h, 20)
|
||||
sfi_breg src, \
|
||||
ldr C_l, [\B, #20]
|
||||
sfi_breg src, \
|
||||
ldr C_h, [\B, #24]
|
||||
strd D_l, D_h, [sp, #24]
|
||||
cfi_rel_offset (D_l, 24)
|
||||
cfi_rel_offset (D_h, 28)
|
||||
sfi_breg src, \
|
||||
ldr D_l, [\B, #28]
|
||||
sfi_breg src, \
|
||||
ldr D_h, [\B, #32]!
|
||||
b 1f
|
||||
.p2align 6
|
||||
2:
|
||||
sfi_pld src, #(5 * 64) - (32 - 4)
|
||||
sfi_breg dst, \
|
||||
strd A_l, A_h, [\B, #40]
|
||||
sfi_breg src, \
|
||||
ldr A_l, [\B, #36]
|
||||
sfi_breg src, \
|
||||
ldr A_h, [\B, #40]
|
||||
sfi_breg dst, \
|
||||
strd B_l, B_h, [\B, #48]
|
||||
sfi_breg src, \
|
||||
ldr B_l, [\B, #44]
|
||||
sfi_breg src, \
|
||||
ldr B_h, [\B, #48]
|
||||
sfi_breg dst, \
|
||||
strd C_l, C_h, [\B, #56]
|
||||
sfi_breg src, \
|
||||
ldr C_l, [\B, #52]
|
||||
sfi_breg src, \
|
||||
ldr C_h, [\B, #56]
|
||||
sfi_breg dst, \
|
||||
strd D_l, D_h, [\B, #64]!
|
||||
sfi_breg src, \
|
||||
ldr D_l, [\B, #60]
|
||||
sfi_breg src, \
|
||||
ldr D_h, [\B, #64]!
|
||||
subs tmp2, tmp2, #64
|
||||
1:
|
||||
sfi_breg dst, \
|
||||
strd A_l, A_h, [\B, #8]
|
||||
sfi_breg src, \
|
||||
ldr A_l, [\B, #4]
|
||||
sfi_breg src, \
|
||||
ldr A_h, [\B, #8]
|
||||
sfi_breg dst, \
|
||||
strd B_l, B_h, [\B, #16]
|
||||
sfi_breg src, \
|
||||
ldr B_l, [\B, #12]
|
||||
sfi_breg src, \
|
||||
ldr B_h, [\B, #16]
|
||||
sfi_breg dst, \
|
||||
strd C_l, C_h, [\B, #24]
|
||||
sfi_breg src, \
|
||||
ldr C_l, [\B, #20]
|
||||
sfi_breg src, \
|
||||
ldr C_h, [\B, #24]
|
||||
sfi_breg dst, \
|
||||
strd D_l, D_h, [\B, #32]
|
||||
sfi_breg src, \
|
||||
ldr D_l, [\B, #28]
|
||||
sfi_breg src, \
|
||||
ldr D_h, [\B, #32]
|
||||
bcs 2b
|
||||
|
||||
/* Save the remaining bytes and restore the callee-saved regs. */
|
||||
sfi_breg dst, \
|
||||
strd A_l, A_h, [\B, #40]
|
||||
add src, src, #36
|
||||
sfi_breg dst, \
|
||||
strd B_l, B_h, [\B, #48]
|
||||
ldrd B_l, B_h, [sp, #8]
|
||||
cfi_restore (B_l)
|
||||
cfi_restore (B_h)
|
||||
sfi_breg dst, \
|
||||
strd C_l, C_h, [\B, #56]
|
||||
ldrd C_l, C_h, [sp, #16]
|
||||
cfi_restore (C_l)
|
||||
cfi_restore (C_h)
|
||||
sfi_breg dst, \
|
||||
strd D_l, D_h, [\B, #64]
|
||||
ldrd D_l, D_h, [sp, #24]
|
||||
cfi_restore (D_l)
|
||||
cfi_restore (D_h)
|
||||
add dst, dst, #72
|
||||
ands count, tmp2, #0x3f
|
||||
#endif
|
||||
ldr tmp2, [sp], #FRAME_SIZE
|
||||
cfi_adjust_cfa_offset (-FRAME_SIZE)
|
||||
cfi_restore (tmp2)
|
||||
bne .Ltail63unaligned
|
||||
bx lr
|
||||
|
||||
END(memcpy)
|
||||
libc_hidden_builtin_def (memcpy)
|
9
sysdeps/arm/armv7/multiarch/memcpy_neon.S
Normal file
9
sysdeps/arm/armv7/multiarch/memcpy_neon.S
Normal file
@@ -0,0 +1,9 @@
|
||||
#ifdef __ARM_NEON__
|
||||
/* Under __ARM_NEON__, this file defines memcpy directly. */
|
||||
libc_hidden_builtin_def (memcpy)
|
||||
#else
|
||||
# define memcpy __memcpy_neon
|
||||
#endif
|
||||
|
||||
#define MEMCPY_NEON
|
||||
#include "memcpy_impl.S"
|
7
sysdeps/arm/armv7/multiarch/memcpy_vfp.S
Normal file
7
sysdeps/arm/armv7/multiarch/memcpy_vfp.S
Normal file
@@ -0,0 +1,7 @@
|
||||
/* Under __ARM_NEON__, memcpy_neon.S defines memcpy directly
|
||||
and the __memcpy_vfp code will never be used. */
|
||||
#ifndef __ARM_NEON__
|
||||
# define MEMCPY_VFP
|
||||
# define memcpy __memcpy_vfp
|
||||
# include "memcpy_impl.S"
|
||||
#endif
|
125
sysdeps/arm/backtrace.c
Normal file
125
sysdeps/arm/backtrace.c
Normal file
@@ -0,0 +1,125 @@
|
||||
/* Return backtrace of current program state.
|
||||
Copyright (C) 2008-2014 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
|
159
sysdeps/arm/bits/atomic.h
Normal file
159
sysdeps/arm/bits/atomic.h
Normal file
@@ -0,0 +1,159 @@
|
||||
/* Atomic operations. Pure ARM version.
|
||||
Copyright (C) 2002-2014 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 <stdint.h>
|
||||
|
||||
typedef int8_t atomic8_t;
|
||||
typedef uint8_t uatomic8_t;
|
||||
typedef int_fast8_t atomic_fast8_t;
|
||||
typedef uint_fast8_t uatomic_fast8_t;
|
||||
|
||||
typedef int32_t atomic32_t;
|
||||
typedef uint32_t uatomic32_t;
|
||||
typedef int_fast32_t atomic_fast32_t;
|
||||
typedef uint_fast32_t uatomic_fast32_t;
|
||||
|
||||
typedef intptr_t atomicptr_t;
|
||||
typedef uintptr_t uatomicptr_t;
|
||||
typedef intmax_t atomic_max_t;
|
||||
typedef uintmax_t uatomic_max_t;
|
||||
|
||||
void __arm_link_error (void);
|
||||
|
||||
#ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4
|
||||
# define atomic_full_barrier() __sync_synchronize ()
|
||||
#else
|
||||
# define atomic_full_barrier() __arm_assisted_full_barrier ()
|
||||
#endif
|
||||
|
||||
/* An OS-specific bits/atomic.h file will define this macro if
|
||||
the OS can provide something. If not, we'll fail to build
|
||||
with a compiler that doesn't supply the operation. */
|
||||
#ifndef __arm_assisted_full_barrier
|
||||
# define __arm_assisted_full_barrier() __arm_link_error()
|
||||
#endif
|
||||
|
||||
/* Use the atomic builtins provided by GCC in case the backend provides
|
||||
a pattern to do this efficiently. */
|
||||
#if __GNUC_PREREQ (4, 7) && defined __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4
|
||||
|
||||
# define atomic_exchange_acq(mem, value) \
|
||||
__atomic_val_bysize (__arch_exchange, int, mem, value, __ATOMIC_ACQUIRE)
|
||||
|
||||
# define atomic_exchange_rel(mem, value) \
|
||||
__atomic_val_bysize (__arch_exchange, int, mem, value, __ATOMIC_RELEASE)
|
||||
|
||||
/* Atomic exchange (without compare). */
|
||||
|
||||
# define __arch_exchange_8_int(mem, newval, model) \
|
||||
(__arm_link_error (), (typeof (*mem)) 0)
|
||||
|
||||
# define __arch_exchange_16_int(mem, newval, model) \
|
||||
(__arm_link_error (), (typeof (*mem)) 0)
|
||||
|
||||
# define __arch_exchange_32_int(mem, newval, model) \
|
||||
__atomic_exchange_n (mem, newval, model)
|
||||
|
||||
# define __arch_exchange_64_int(mem, newval, model) \
|
||||
(__arm_link_error (), (typeof (*mem)) 0)
|
||||
|
||||
/* Compare and exchange with "acquire" semantics, ie barrier after. */
|
||||
|
||||
# define atomic_compare_and_exchange_bool_acq(mem, new, old) \
|
||||
__atomic_bool_bysize (__arch_compare_and_exchange_bool, int, \
|
||||
mem, new, old, __ATOMIC_ACQUIRE)
|
||||
|
||||
# define atomic_compare_and_exchange_val_acq(mem, new, old) \
|
||||
__atomic_val_bysize (__arch_compare_and_exchange_val, int, \
|
||||
mem, new, old, __ATOMIC_ACQUIRE)
|
||||
|
||||
/* Compare and exchange with "release" semantics, ie barrier before. */
|
||||
|
||||
# define atomic_compare_and_exchange_bool_rel(mem, new, old) \
|
||||
__atomic_bool_bysize (__arch_compare_and_exchange_bool, int, \
|
||||
mem, new, old, __ATOMIC_RELEASE)
|
||||
|
||||
# define atomic_compare_and_exchange_val_rel(mem, new, old) \
|
||||
__atomic_val_bysize (__arch_compare_and_exchange_val, int, \
|
||||
mem, new, old, __ATOMIC_RELEASE)
|
||||
|
||||
/* Compare and exchange.
|
||||
For all "bool" routines, we return FALSE if exchange succesful. */
|
||||
|
||||
# define __arch_compare_and_exchange_bool_8_int(mem, newval, oldval, model) \
|
||||
({__arm_link_error (); oldval; })
|
||||
|
||||
# define __arch_compare_and_exchange_bool_16_int(mem, newval, oldval, model) \
|
||||
({__arm_link_error (); oldval; })
|
||||
|
||||
# define __arch_compare_and_exchange_bool_32_int(mem, newval, oldval, model) \
|
||||
({ \
|
||||
typeof (*mem) __oldval = (oldval); \
|
||||
!__atomic_compare_exchange_n (mem, (void *) &__oldval, newval, 0, \
|
||||
model, __ATOMIC_RELAXED); \
|
||||
})
|
||||
|
||||
# define __arch_compare_and_exchange_bool_64_int(mem, newval, oldval, model) \
|
||||
({__arm_link_error (); oldval; })
|
||||
|
||||
# define __arch_compare_and_exchange_val_8_int(mem, newval, oldval, model) \
|
||||
({__arm_link_error (); oldval; })
|
||||
|
||||
# define __arch_compare_and_exchange_val_16_int(mem, newval, oldval, model) \
|
||||
({__arm_link_error (); oldval; })
|
||||
|
||||
# define __arch_compare_and_exchange_val_32_int(mem, newval, oldval, model) \
|
||||
({ \
|
||||
typeof (*mem) __oldval = (oldval); \
|
||||
__atomic_compare_exchange_n (mem, (void *) &__oldval, newval, 0, \
|
||||
model, __ATOMIC_RELAXED); \
|
||||
__oldval; \
|
||||
})
|
||||
|
||||
# define __arch_compare_and_exchange_val_64_int(mem, newval, oldval, model) \
|
||||
({__arm_link_error (); oldval; })
|
||||
|
||||
#elif defined __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4
|
||||
/* Atomic compare and exchange. */
|
||||
# define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval) \
|
||||
__sync_val_compare_and_swap ((mem), (oldval), (newval))
|
||||
#else
|
||||
# define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval) \
|
||||
__arm_assisted_compare_and_exchange_val_32_acq ((mem), (newval), (oldval))
|
||||
#endif
|
||||
|
||||
#if !__GNUC_PREREQ (4, 7) || !defined (__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)
|
||||
/* We don't support atomic operations on any non-word types.
|
||||
So make them link errors. */
|
||||
# define __arch_compare_and_exchange_val_8_acq(mem, newval, oldval) \
|
||||
({ __arm_link_error (); oldval; })
|
||||
|
||||
# define __arch_compare_and_exchange_val_16_acq(mem, newval, oldval) \
|
||||
({ __arm_link_error (); oldval; })
|
||||
|
||||
# define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \
|
||||
({ __arm_link_error (); oldval; })
|
||||
#endif
|
||||
|
||||
/* An OS-specific bits/atomic.h file will define this macro if
|
||||
the OS can provide something. If not, we'll fail to build
|
||||
with a compiler that doesn't supply the operation. */
|
||||
#ifndef __arm_assisted_compare_and_exchange_val_32_acq
|
||||
# define __arm_assisted_compare_and_exchange_val_32_acq(mem, newval, oldval) \
|
||||
({ __arm_link_error (); oldval; })
|
||||
#endif
|
10
sysdeps/arm/bits/endian.h
Normal file
10
sysdeps/arm/bits/endian.h
Normal file
@@ -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
|
82
sysdeps/arm/bits/fenv.h
Normal file
82
sysdeps/arm/bits/fenv.h
Normal file
@@ -0,0 +1,82 @@
|
||||
/* Copyright (C) 2004-2014 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 =
|
||||
#define FE_INVALID 1
|
||||
FE_INVALID,
|
||||
FE_DIVBYZERO =
|
||||
#define FE_DIVBYZERO 2
|
||||
FE_DIVBYZERO,
|
||||
FE_OVERFLOW =
|
||||
#define FE_OVERFLOW 4
|
||||
FE_OVERFLOW,
|
||||
FE_UNDERFLOW =
|
||||
#define FE_UNDERFLOW 8
|
||||
FE_UNDERFLOW,
|
||||
FE_INEXACT =
|
||||
#define FE_INEXACT 16
|
||||
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 =
|
||||
#define FE_TONEAREST 0
|
||||
FE_TONEAREST,
|
||||
FE_UPWARD =
|
||||
#define FE_UPWARD 0x400000
|
||||
FE_UPWARD,
|
||||
FE_DOWNWARD =
|
||||
#define FE_DOWNWARD 0x800000
|
||||
FE_DOWNWARD,
|
||||
FE_TOWARDZERO =
|
||||
#define FE_TOWARDZERO 0xc00000
|
||||
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 ((const 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
|
65
sysdeps/arm/bits/link.h
Normal file
65
sysdeps/arm/bits/link.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/* Copyright (C) 2005-2014 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
|
5
sysdeps/arm/bits/linkmap.h
Normal file
5
sysdeps/arm/bits/linkmap.h
Normal file
@@ -0,0 +1,5 @@
|
||||
struct link_map_machine
|
||||
{
|
||||
Elf32_Addr plt; /* Address of .plt */
|
||||
void *tlsdesc_table; /* Address of TLS descriptor hash table. */
|
||||
};
|
55
sysdeps/arm/bits/mathdef.h
Normal file
55
sysdeps/arm/bits/mathdef.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/* Copyright (C) 1999-2014 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
|
37
sysdeps/arm/bits/setjmp.h
Normal file
37
sysdeps/arm/bits/setjmp.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/* Copyright (C) 2004-2014 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 __ASSEMBLER__
|
||||
/* 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 27 words
|
||||
are occupied by v1-v6, sl, fp, sp, pc, and d8-d15. (Note that
|
||||
d8-15 require 17 words, due to the use of fstmx.) */
|
||||
typedef int __jmp_buf[64] __attribute__((__aligned__ (8)));
|
||||
#endif
|
||||
|
||||
#endif
|
29
sysdeps/arm/bsd-_setjmp.S
Normal file
29
sysdeps/arm/bsd-_setjmp.S
Normal file
@@ -0,0 +1,29 @@
|
||||
/* BSD `_setjmp' entry point to `sigsetjmp (..., 0)'. ARM version.
|
||||
Copyright (C) 1997-2014 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)
|
28
sysdeps/arm/bsd-setjmp.S
Normal file
28
sysdeps/arm/bsd-setjmp.S
Normal file
@@ -0,0 +1,28 @@
|
||||
/* BSD `setjmp' entry point to `sigsetjmp (..., 1)'. ARM version.
|
||||
Copyright (C) 1997-2014 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)
|
205
sysdeps/arm/configure
vendored
Normal file
205
sysdeps/arm/configure
vendored
Normal file
@@ -0,0 +1,205 @@
|
||||
# This file is generated from configure.ac by Autoconf. DO NOT EDIT!
|
||||
# Local configure fragment for sysdeps/arm.
|
||||
|
||||
#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
|
||||
|
||||
config_vars="$config_vars
|
||||
default-abi = hard"
|
||||
else
|
||||
config_vars="$config_vars
|
||||
default-abi = soft"
|
||||
fi
|
46
sysdeps/arm/configure.ac
Normal file
46
sysdeps/arm/configure.ac
Normal file
@@ -0,0 +1,46 @@
|
||||
GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory.
|
||||
# Local configure fragment for sysdeps/arm.
|
||||
|
||||
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)
|
||||
LIBC_CONFIG_VAR([default-abi], [hard])
|
||||
else
|
||||
LIBC_CONFIG_VAR([default-abi], [soft])
|
||||
fi
|
95
sysdeps/arm/crti.S
Normal file
95
sysdeps/arm/crti.S
Normal file
@@ -0,0 +1,95 @@
|
||||
/* Special .init and .fini section support for ARM.
|
||||
Copyright (C) 1995-2014 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. */
|
||||
|
||||
/* Always build .init and .fini sections in ARM mode. */
|
||||
#define NO_THUMB
|
||||
#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:
|
||||
push {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:
|
||||
push {r3, lr}
|
57
sysdeps/arm/crtn.S
Normal file
57
sysdeps/arm/crtn.S
Normal file
@@ -0,0 +1,57 @@
|
||||
/* Special .init and .fini section support for ARM.
|
||||
Copyright (C) 1995-2014 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/>. */
|
||||
|
||||
/* Always build .init and .fini sections in ARM mode. */
|
||||
#define NO_THUMB
|
||||
#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__
|
||||
pop {r3, lr}
|
||||
bx lr
|
||||
#else
|
||||
pop {r3, pc}
|
||||
#endif
|
||||
|
||||
.section .fini,"ax",%progbits
|
||||
#ifdef __ARM_ARCH_4T__
|
||||
pop {r3, lr}
|
||||
bx lr
|
||||
#else
|
||||
pop {r3, pc}
|
||||
#endif
|
52
sysdeps/arm/dl-irel.h
Normal file
52
sysdeps/arm/dl-irel.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/* Machine-dependent ELF indirect relocation inline functions.
|
||||
ARM version.
|
||||
Copyright (C) 2009-2014 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>
|
||||
#include <ldsodefs.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 */
|
27
sysdeps/arm/dl-lookupcfg.h
Normal file
27
sysdeps/arm/dl-lookupcfg.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/* Configuration of lookup functions.
|
||||
Copyright (C) 2006-2014 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)
|
662
sysdeps/arm/dl-machine.h
Normal file
662
sysdeps/arm/dl-machine.h
Normal file
@@ -0,0 +1,662 @@
|
||||
/* Machine-dependent ELF dynamic relocation inline functions. ARM version.
|
||||
Copyright (C) 1995-2014 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>
|
||||
|
||||
#ifndef CLEAR_CACHE
|
||||
# error CLEAR_CACHE definition required to handle TEXTREL
|
||||
#endif
|
||||
|
||||
/* 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. */
|
||||
static inline Elf32_Addr __attribute__ ((unused))
|
||||
elf_machine_dynamic (void)
|
||||
{
|
||||
/* Declaring this hidden ensures that a PC-relative reference is used. */
|
||||
extern const Elf32_Addr _GLOBAL_OFFSET_TABLE_[] attribute_hidden;
|
||||
return _GLOBAL_OFFSET_TABLE_[0];
|
||||
}
|
||||
|
||||
|
||||
/* Return the run-time load address of the shared object. */
|
||||
static inline Elf32_Addr __attribute__ ((unused))
|
||||
elf_machine_load_address (void)
|
||||
{
|
||||
extern Elf32_Addr internal_function __dl_start (void *) 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(ARCH_HAS_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
|
||||
/* Handle a PC24 reloc, including the out-of-range case. */
|
||||
auto void
|
||||
relocate_pc24 (struct link_map *map, Elf32_Addr value,
|
||||
Elf32_Addr *const reloc_addr, Elf32_Sword addend)
|
||||
{
|
||||
Elf32_Addr new_value;
|
||||
|
||||
/* Set NEW_VALUE based on V, and return true iff it overflows 24 bits. */
|
||||
inline bool set_new_value (Elf32_Addr v)
|
||||
{
|
||||
new_value = v + addend - (Elf32_Addr) reloc_addr;
|
||||
Elf32_Addr topbits = new_value & 0xfe000000;
|
||||
return topbits != 0xfe000000 && topbits != 0x00000000;
|
||||
}
|
||||
|
||||
if (set_new_value (value))
|
||||
{
|
||||
/* The PC-relative address doesn't fit in 24 bits! */
|
||||
|
||||
static void *fix_page;
|
||||
static size_t fix_offset;
|
||||
if (fix_page == NULL)
|
||||
{
|
||||
void *new_page = __mmap (NULL, GLRO(dl_pagesize),
|
||||
PROT_READ | PROT_WRITE | PROT_EXEC,
|
||||
MAP_PRIVATE | MAP_ANON, -1, 0);
|
||||
if (new_page == MAP_FAILED)
|
||||
_dl_signal_error (0, map->l_name, NULL,
|
||||
"could not map page for fixup");
|
||||
fix_page = new_page;
|
||||
assert (fix_offset == 0);
|
||||
}
|
||||
|
||||
Elf32_Word *fix_address = fix_page + fix_offset;
|
||||
fix_address[0] = 0xe51ff004; /* ldr pc, [pc, #-4] */
|
||||
fix_address[1] = value;
|
||||
|
||||
fix_offset += sizeof fix_address[0] * 2;
|
||||
if (fix_offset >= GLRO(dl_pagesize))
|
||||
{
|
||||
fix_page = NULL;
|
||||
fix_offset = 0;
|
||||
}
|
||||
|
||||
if (set_new_value ((Elf32_Addr) fix_address))
|
||||
_dl_signal_error (0, map->l_name, NULL,
|
||||
"R_ARM_PC24 relocation out of range");
|
||||
}
|
||||
|
||||
*reloc_addr = (*reloc_addr & 0xff000000) | ((new_value >> 2) & 0x00ffffff);
|
||||
}
|
||||
|
||||
/* 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, 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:
|
||||
{
|
||||
struct unaligned
|
||||
{
|
||||
Elf32_Addr x;
|
||||
} __attribute__ ((packed, may_alias));
|
||||
# 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
|
||||
/* Support relocations on mis-aligned offsets. */
|
||||
((struct unaligned *) reloc_addr)->x += 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:
|
||||
relocate_pc24 (map, value, reloc_addr,
|
||||
/* Sign-extend the 24-bit addend in the
|
||||
instruction (which counts instructions), and
|
||||
then shift it up two so as to count bytes. */
|
||||
(((Elf32_Sword) *reloc_addr << 8) >> 8) << 2);
|
||||
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 (*) (int)) value) (GLRO(dl_hwcap));
|
||||
*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, 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:
|
||||
relocate_pc24 (map, value, reloc_addr, reloc->r_addend);
|
||||
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 (*) (int)) value) (GLRO(dl_hwcap));
|
||||
*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 */
|
23
sysdeps/arm/dl-sysdep.h
Normal file
23
sysdeps/arm/dl-sysdep.h
Normal file
@@ -0,0 +1,23 @@
|
||||
/* System-specific settings for dynamic linker code. Alpha version.
|
||||
Copyright (C) 2002-2014 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
|
31
sysdeps/arm/dl-tls.h
Normal file
31
sysdeps/arm/dl-tls.h
Normal file
@@ -0,0 +1,31 @@
|
||||
/* Thread-local storage handling in the ELF dynamic linker. ARM version.
|
||||
Copyright (C) 2005-2014 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)
|
226
sysdeps/arm/dl-tlsdesc.S
Normal file
226
sysdeps/arm/dl-tlsdesc.S
Normal file
@@ -0,0 +1,226 @@
|
||||
/* Thread-local storage handling in the ELF dynamic linker. ARM version.
|
||||
Copyright (C) 2006-2014 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 <arm-features.h>
|
||||
#include <tls.h>
|
||||
#include "tlsdesc.h"
|
||||
|
||||
.text
|
||||
@ emit debug information with cfi
|
||||
@ use arm-specific pseudos for unwinding itself
|
||||
CFI_SECTIONS
|
||||
.hidden _dl_tlsdesc_return
|
||||
.global _dl_tlsdesc_return
|
||||
.type _dl_tlsdesc_return,#function
|
||||
cfi_startproc
|
||||
eabi_fnstart
|
||||
.align 2
|
||||
_dl_tlsdesc_return:
|
||||
sfi_breg r0, \
|
||||
ldr r0, [\B]
|
||||
BX (lr)
|
||||
eabi_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
|
||||
eabi_fnstart
|
||||
.align 2
|
||||
_dl_tlsdesc_undefweak:
|
||||
GET_TLS (r1)
|
||||
rsb r0, r0, #0
|
||||
BX (lr)
|
||||
cfi_endproc
|
||||
eabi_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
|
||||
eabi_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 */
|
||||
eabi_save ({r2,r3,r4,lr})
|
||||
push {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)
|
||||
sfi_breg r0, \
|
||||
ldr r1, [\B] /* td */
|
||||
GET_TLS (lr)
|
||||
mov r4, r0 /* r4 = tp */
|
||||
sfi_breg r0, \
|
||||
ldr r0, [\B]
|
||||
sfi_breg r1, \
|
||||
ldr r2, [\B, #8] /* gen_count */
|
||||
sfi_breg r0, \
|
||||
ldr r3, [\B]
|
||||
cmp r2, r3
|
||||
bhi 1f
|
||||
sfi_breg r1, \
|
||||
ldr r3, [\B]
|
||||
#ifndef ARM_NO_INDEX_REGISTER
|
||||
ldr r2, [r0, r3, lsl #3]
|
||||
#else
|
||||
add lr, r0, r3, lsl #3
|
||||
sfi_breg lr, \
|
||||
ldr r2, [\B]
|
||||
#endif
|
||||
cmn r2, #1
|
||||
ittt ne
|
||||
sfi_breg r1, \
|
||||
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:
|
||||
#if ((defined (__ARM_ARCH_4T__) && defined (__THUMB_INTERWORK__)) \
|
||||
|| defined (ARM_ALWAYS_BX))
|
||||
pop {r2,r3,r4, lr}
|
||||
cfi_adjust_cfa_offset (-16)
|
||||
cfi_restore (lr)
|
||||
cfi_restore (r4)
|
||||
cfi_restore (r3)
|
||||
cfi_restore (r2)
|
||||
bx lr
|
||||
#else
|
||||
pop {r2,r3,r4, pc}
|
||||
#endif
|
||||
eabi_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
|
||||
eabi_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. */
|
||||
eabi_save ({r2})
|
||||
cfi_adjust_cfa_offset (4)
|
||||
cfi_rel_offset (r2, 0)
|
||||
eabi_save ({r0,r1,r3,ip,lr})
|
||||
push {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
|
||||
pop {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)
|
||||
pop {r2}
|
||||
cfi_adjust_cfa_offset (-4)
|
||||
cfi_restore (r2)
|
||||
sfi_breg r0, \
|
||||
ldr r1, [\B, #4]
|
||||
BX (r1)
|
||||
eabi_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
|
||||
eabi_fnstart
|
||||
.align 2
|
||||
_dl_tlsdesc_resolve_hold:
|
||||
/* Tell the unwinder that r2 has already been pushed. */
|
||||
eabi_save ({r2})
|
||||
cfi_adjust_cfa_offset (4)
|
||||
cfi_rel_offset (r2, 0)
|
||||
eabi_save ({r0,r1,r3,ip,lr})
|
||||
push {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
|
||||
pop {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)
|
||||
pop {r2}
|
||||
cfi_adjust_cfa_offset (-4)
|
||||
cfi_restore (r2)
|
||||
sfi_breg r0, \
|
||||
ldr r1, [\B, #4]
|
||||
BX (r1)
|
||||
eabi_fnend
|
||||
cfi_endproc
|
||||
.size _dl_tlsdesc_resolve_hold, .-_dl_tlsdesc_resolve_hold
|
62
sysdeps/arm/dl-tlsdesc.h
Normal file
62
sysdeps/arm/dl-tlsdesc.h
Normal file
@@ -0,0 +1,62 @@
|
||||
/* Thread-local storage descriptor handling in the ELF dynamic linker.
|
||||
ARM version.
|
||||
Copyright (C) 2005-2014 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
|
||||
|
||||
/* 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
|
212
sysdeps/arm/dl-trampoline.S
Normal file
212
sysdeps/arm/dl-trampoline.S
Normal file
@@ -0,0 +1,212 @@
|
||||
/* PLT trampolines. ARM version.
|
||||
Copyright (C) 2005-2014 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/>. */
|
||||
|
||||
/* ??? Needs more rearrangement for the LDM to handle thumb mode. */
|
||||
#define NO_THUMB
|
||||
#include <sysdep.h>
|
||||
#include <libc-symbols.h>
|
||||
|
||||
.text
|
||||
.globl _dl_runtime_resolve
|
||||
.type _dl_runtime_resolve, #function
|
||||
CFI_SECTIONS
|
||||
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.
|
||||
push {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.
|
||||
pop {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
|
||||
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]
|
||||
BLX(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
|
58
sysdeps/arm/fclrexcpt.c
Normal file
58
sysdeps/arm/fclrexcpt.c
Normal file
@@ -0,0 +1,58 @@
|
||||
/* Clear given exceptions in current floating-point environment.
|
||||
Copyright (C) 1997-2014 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 <arm-features.h>
|
||||
|
||||
|
||||
int
|
||||
__feclearexcept (int excepts)
|
||||
{
|
||||
if (ARM_HAVE_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
|
||||
|
||||
libm_hidden_ver (__feclearexcept, feclearexcept)
|
||||
versioned_symbol (libm, __feclearexcept, feclearexcept, GLIBC_2_2);
|
47
sysdeps/arm/fedisblxcpt.c
Normal file
47
sysdeps/arm/fedisblxcpt.c
Normal file
@@ -0,0 +1,47 @@
|
||||
/* Disable floating-point exceptions.
|
||||
Copyright (C) 2001-2014 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 <arm-features.h>
|
||||
|
||||
|
||||
int
|
||||
fedisableexcept (int excepts)
|
||||
{
|
||||
if (ARM_HAVE_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;
|
||||
}
|
59
sysdeps/arm/feenablxcpt.c
Normal file
59
sysdeps/arm/feenablxcpt.c
Normal file
@@ -0,0 +1,59 @@
|
||||
/* Enable floating-point exceptions.
|
||||
Copyright (C) 2001-2014 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 <arm-features.h>
|
||||
|
||||
|
||||
int
|
||||
feenableexcept (int excepts)
|
||||
{
|
||||
if (ARM_HAVE_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);
|
||||
|
||||
if (excepts != 0)
|
||||
{
|
||||
/* VFPv3 and VFPv4 do not support trapping exceptions, so
|
||||
test whether the relevant bits were set and fail if
|
||||
not. */
|
||||
unsigned int temp;
|
||||
_FPU_GETCW (temp);
|
||||
if ((temp & (excepts << FE_EXCEPT_SHIFT))
|
||||
!= (excepts << FE_EXCEPT_SHIFT))
|
||||
return -1;
|
||||
}
|
||||
|
||||
return old_exc;
|
||||
}
|
||||
|
||||
/* Unsupported, so return -1 for failure. */
|
||||
return -1;
|
||||
}
|
48
sysdeps/arm/fegetenv.c
Normal file
48
sysdeps/arm/fegetenv.c
Normal file
@@ -0,0 +1,48 @@
|
||||
/* Store current floating-point environment.
|
||||
Copyright (C) 1997-2014 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 <arm-features.h>
|
||||
|
||||
|
||||
int
|
||||
__fegetenv (fenv_t *envp)
|
||||
{
|
||||
if (ARM_HAVE_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);
|
39
sysdeps/arm/fegetexcept.c
Normal file
39
sysdeps/arm/fegetexcept.c
Normal file
@@ -0,0 +1,39 @@
|
||||
/* Get floating-point exceptions.
|
||||
Copyright (C) 2001-2014 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 <arm-features.h>
|
||||
|
||||
|
||||
int
|
||||
fegetexcept (void)
|
||||
{
|
||||
if (ARM_HAVE_VFP)
|
||||
{
|
||||
unsigned long temp;
|
||||
|
||||
_FPU_GETCW (temp);
|
||||
|
||||
return (temp >> FE_EXCEPT_SHIFT) & FE_ALL_EXCEPT;
|
||||
}
|
||||
|
||||
/* Unsupported. Return all exceptions disabled. */
|
||||
return 0;
|
||||
}
|
40
sysdeps/arm/fegetround.c
Normal file
40
sysdeps/arm/fegetround.c
Normal file
@@ -0,0 +1,40 @@
|
||||
/* Return current rounding direction.
|
||||
Copyright (C) 2004-2014 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 <arm-features.h>
|
||||
|
||||
|
||||
int
|
||||
fegetround (void)
|
||||
{
|
||||
if (ARM_HAVE_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;
|
||||
}
|
||||
libm_hidden_def (fegetround)
|
50
sysdeps/arm/feholdexcpt.c
Normal file
50
sysdeps/arm/feholdexcpt.c
Normal file
@@ -0,0 +1,50 @@
|
||||
/* Store current floating-point environment and clear exceptions.
|
||||
Copyright (C) 1997-2014 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 <arm-features.h>
|
||||
|
||||
|
||||
int
|
||||
feholdexcept (fenv_t *envp)
|
||||
{
|
||||
if (ARM_HAVE_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)
|
63
sysdeps/arm/fesetenv.c
Normal file
63
sysdeps/arm/fesetenv.c
Normal file
@@ -0,0 +1,63 @@
|
||||
/* Install given floating-point environment.
|
||||
Copyright (C) 2004-2014 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 <arm-features.h>
|
||||
|
||||
|
||||
int
|
||||
__fesetenv (const fenv_t *envp)
|
||||
{
|
||||
if (ARM_HAVE_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);
|
||||
|
||||
if (envp == FE_NOMASK_ENV)
|
||||
{
|
||||
/* VFPv3 and VFPv4 do not support trapping exceptions, so
|
||||
test whether the relevant bits were set and fail if
|
||||
not. */
|
||||
_FPU_GETCW (temp);
|
||||
if ((temp & _FPU_IEEE) != _FPU_IEEE)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* 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);
|
53
sysdeps/arm/fesetround.c
Normal file
53
sysdeps/arm/fesetround.c
Normal file
@@ -0,0 +1,53 @@
|
||||
/* Set current rounding direction.
|
||||
Copyright (C) 2004-2014 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 <arm-features.h>
|
||||
|
||||
|
||||
int
|
||||
fesetround (int round)
|
||||
{
|
||||
if (ARM_HAVE_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)
|
56
sysdeps/arm/feupdateenv.c
Normal file
56
sysdeps/arm/feupdateenv.c
Normal file
@@ -0,0 +1,56 @@
|
||||
/* Install given floating-point environment and raise exceptions.
|
||||
Copyright (C) 1997-2014 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 <arm-features.h>
|
||||
|
||||
|
||||
int
|
||||
__feupdateenv (const fenv_t *envp)
|
||||
{
|
||||
if (ARM_HAVE_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);
|
50
sysdeps/arm/fgetexcptflg.c
Normal file
50
sysdeps/arm/fgetexcptflg.c
Normal file
@@ -0,0 +1,50 @@
|
||||
/* Store current representation for exceptions.
|
||||
Copyright (C) 1997-2014 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 <arm-features.h>
|
||||
|
||||
|
||||
int
|
||||
__fegetexceptflag (fexcept_t *flagp, int excepts)
|
||||
{
|
||||
if (ARM_HAVE_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);
|
79
sysdeps/arm/find_exidx.c
Normal file
79
sysdeps/arm/find_exidx.c
Normal file
@@ -0,0 +1,79 @@
|
||||
/* Copyright (C) 2005-2014 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;
|
||||
}
|
63
sysdeps/arm/fpu_control.h
Normal file
63
sysdeps/arm/fpu_control.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/* FPU control word definitions. ARM VFP version.
|
||||
Copyright (C) 2004-2014 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(_LIBC_TEST)) && defined(__SOFTFP__)
|
||||
|
||||
#define _FPU_RESERVED 0xffffffff
|
||||
#define _FPU_DEFAULT 0x00000000
|
||||
typedef unsigned int fpu_control_t;
|
||||
#define _FPU_GETCW(cw) (cw) = 0
|
||||
#define _FPU_SETCW(cw) (void) (cw)
|
||||
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 0x00086060
|
||||
#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 */
|
106
sysdeps/arm/fraiseexcpt.c
Normal file
106
sysdeps/arm/fraiseexcpt.c
Normal file
@@ -0,0 +1,106 @@
|
||||
/* Raise given exceptions.
|
||||
Copyright (C) 2004-2014 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 <arm-features.h>
|
||||
|
||||
|
||||
int
|
||||
feraiseexcept (int excepts)
|
||||
{
|
||||
if (ARM_HAVE_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)
|
27
sysdeps/arm/frame.h
Normal file
27
sysdeps/arm/frame.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/* Definition of stack frame structure. ARM/APCS version.
|
||||
Copyright (C) 2000-2014 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 *next;
|
||||
void *sp;
|
||||
void *return_address;
|
||||
};
|
||||
|
||||
#define FIRST_FRAME_POINTER ADVANCE_STACK_FRAME (__builtin_frame_address (0))
|
1
sysdeps/arm/framestate.c
Normal file
1
sysdeps/arm/framestate.c
Normal file
@@ -0,0 +1 @@
|
||||
/* Empty */
|
56
sysdeps/arm/fsetexcptflg.c
Normal file
56
sysdeps/arm/fsetexcptflg.c
Normal file
@@ -0,0 +1,56 @@
|
||||
/* Set floating-point environment exception handling.
|
||||
Copyright (C) 1997-2014 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 <arm-features.h>
|
||||
|
||||
|
||||
int
|
||||
__fesetexceptflag (const fexcept_t *flagp, int excepts)
|
||||
{
|
||||
if (ARM_HAVE_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);
|
40
sysdeps/arm/ftestexcept.c
Normal file
40
sysdeps/arm/ftestexcept.c
Normal file
@@ -0,0 +1,40 @@
|
||||
/* Test exception in current environment.
|
||||
Copyright (C) 1997-2014 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 <arm-features.h>
|
||||
|
||||
|
||||
int
|
||||
fetestexcept (int excepts)
|
||||
{
|
||||
if (ARM_HAVE_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)
|
35
sysdeps/arm/gcc-compat.h
Normal file
35
sysdeps/arm/gcc-compat.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/* Macros for checking required GCC compatibility. ARM version.
|
||||
Copyright (C) 2014 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_GCC_COMPAT_H
|
||||
#define _ARM_GCC_COMPAT_H 1
|
||||
|
||||
#ifndef GCC_COMPAT_VERSION
|
||||
# ifdef __ARM_PCS_VFP
|
||||
/* The hard-float ABI was first supported in 4.5. */
|
||||
# define GCC_COMPAT_VERSION GCC_VERSION (4, 5)
|
||||
# else
|
||||
/* The EABI configurations (the only ones we handle) were first supported
|
||||
in 4.1. */
|
||||
# define GCC_COMPAT_VERSION GCC_VERSION (4, 1)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include_next <gcc-compat.h>
|
||||
|
||||
#endif
|
21
sysdeps/arm/gccframe.h
Normal file
21
sysdeps/arm/gccframe.h
Normal file
@@ -0,0 +1,21 @@
|
||||
/* Definition of object in frame unwind info. arm version.
|
||||
Copyright (C) 2001-2014 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>
|
42
sysdeps/arm/get-rounding-mode.h
Normal file
42
sysdeps/arm/get-rounding-mode.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/* Determine floating-point rounding mode within libc. ARM version.
|
||||
Copyright (C) 2012-2014 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_GET_ROUNDING_MODE_H
|
||||
#define _ARM_GET_ROUNDING_MODE_H 1
|
||||
|
||||
#include <arm-features.h>
|
||||
#include <fenv.h>
|
||||
#include <fpu_control.h>
|
||||
|
||||
/* Return the floating-point rounding mode. */
|
||||
|
||||
static inline int
|
||||
get_rounding_mode (void)
|
||||
{
|
||||
if (ARM_HAVE_VFP)
|
||||
{
|
||||
fpu_control_t fc;
|
||||
|
||||
_FPU_GETCW (fc);
|
||||
return fc & FE_TOWARDZERO;
|
||||
}
|
||||
else
|
||||
return FE_TONEAREST;
|
||||
}
|
||||
|
||||
#endif /* get-rounding-mode.h */
|
36
sysdeps/arm/gmp-mparam.h
Normal file
36
sysdeps/arm/gmp-mparam.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/* gmp-mparam.h -- Compiler/machine parameter header file.
|
||||
|
||||
Copyright (C) 1991-2014 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
|
36
sysdeps/arm/include/bits/setjmp.h
Normal file
36
sysdeps/arm/include/bits/setjmp.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/* Private jmp_buf-related definitions. ARM EABI version.
|
||||
Copyright (C) 2013-2014 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 _INCLUDE_BITS_SETJMP_H
|
||||
#define _INCLUDE_BITS_SETJMP_H 1
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
/* Get the public declarations. */
|
||||
# include <sysdeps/arm/bits/setjmp.h>
|
||||
#endif
|
||||
|
||||
#ifndef _ISOMAC
|
||||
/* Register list for a ldm/stm instruction to load/store
|
||||
the general registers from a __jmp_buf. */
|
||||
# define JMP_BUF_REGLIST {v1-v6, sl, fp}
|
||||
|
||||
/* Index of __jmp_buf where the sp register resides. */
|
||||
# define __JMP_BUF_SP 8
|
||||
#endif
|
||||
|
||||
#endif /* include/bits/setjmp.h */
|
45
sysdeps/arm/jmpbuf-unwind.h
Normal file
45
sysdeps/arm/jmpbuf-unwind.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/* Copyright (C) 2005-2014 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library. If not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <setjmp.h>
|
||||
#include <stdint.h>
|
||||
#include <sysdep.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)
|
||||
|
||||
static inline uintptr_t __attribute__ ((unused))
|
||||
_jmpbuf_sp (__jmp_buf regs)
|
||||
{
|
||||
uintptr_t sp = regs[__JMP_BUF_SP];
|
||||
#ifdef PTR_DEMANGLE
|
||||
PTR_DEMANGLE (sp);
|
||||
#endif
|
||||
return sp;
|
||||
}
|
||||
|
||||
#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \
|
||||
((uintptr_t) (_address) - (_adj) < _jmpbuf_sp (_jmpbuf) - (_adj))
|
||||
|
||||
/* We use the normal longjmp for unwinding. */
|
||||
#define __libc_unwind_longjmp(buf, val) __libc_longjmp (buf, val)
|
40
sysdeps/arm/ldsodefs.h
Normal file
40
sysdeps/arm/ldsodefs.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/* Run-time dynamic linker data structures for loaded ELF shared objects.
|
||||
Copyright (C) 2005-2014 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 *, const struct La_arm_regs *, \
|
||||
struct La_arm_retval *, const char *)
|
||||
|
||||
#include_next <ldsodefs.h>
|
||||
|
||||
#endif
|
32
sysdeps/arm/libc-tls.c
Normal file
32
sysdeps/arm/libc-tls.c
Normal file
@@ -0,0 +1,32 @@
|
||||
/* Thread-local storage handling in the ELF dynamic linker. ARM version.
|
||||
Copyright (C) 2005-2014 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;
|
||||
}
|
8028
sysdeps/arm/libm-test-ulps
Normal file
8028
sysdeps/arm/libm-test-ulps
Normal file
File diff suppressed because it is too large
Load Diff
33
sysdeps/arm/machine-gmon.h
Normal file
33
sysdeps/arm/machine-gmon.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/* Machine-dependent definitions for profiling support. ARM EABI version.
|
||||
Copyright (C) 2008-2014 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
|
32
sysdeps/arm/math-tests.h
Normal file
32
sysdeps/arm/math-tests.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/* Configuration for math tests. ARM version.
|
||||
Copyright (C) 2013-2014 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/>. */
|
||||
|
||||
/* On systems with VFP support, but where glibc is built for
|
||||
soft-float, the libgcc functions used in libc and libm do not
|
||||
support rounding modes, although fesetround succeeds, and do not
|
||||
support exceptions. */
|
||||
#ifdef __SOFTFP__
|
||||
# define ROUNDING_TESTS_float(MODE) ((MODE) == FE_TONEAREST)
|
||||
# define ROUNDING_TESTS_double(MODE) ((MODE) == FE_TONEAREST)
|
||||
# define ROUNDING_TESTS_long_double(MODE) ((MODE) == FE_TONEAREST)
|
||||
# define EXCEPTION_TESTS_float 0
|
||||
# define EXCEPTION_TESTS_double 0
|
||||
# define EXCEPTION_TESTS_long_double 0
|
||||
#endif
|
||||
|
||||
#include_next <math-tests.h>
|
344
sysdeps/arm/memcpy.S
Normal file
344
sysdeps/arm/memcpy.S
Normal file
@@ -0,0 +1,344 @@
|
||||
/* Copyright (C) 2006-2014 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/>. */
|
||||
|
||||
/* Thumb requires excessive IT insns here. */
|
||||
#define NO_THUMB
|
||||
#include <sysdep.h>
|
||||
#include <arm-features.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
|
||||
.syntax unified
|
||||
|
||||
/* Prototype: void *memcpy(void *dest, const void *src, size_t n); */
|
||||
|
||||
ENTRY(memcpy)
|
||||
|
||||
push {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( sfi_pld r1, #0 )
|
||||
bne 9f
|
||||
ands ip, r1, #3
|
||||
bne 10f
|
||||
|
||||
1: subs r2, r2, #(28)
|
||||
push {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( sbcsne r4, r3, r2 ) @ C is always set here
|
||||
CALGN( bcs 2f )
|
||||
CALGN( adr r4, 6f )
|
||||
CALGN( subs r2, r2, r3 ) @ C gets set
|
||||
#ifndef ARM_ALWAYS_BX
|
||||
CALGN( add pc, r4, ip, lsl #(ARM_BX_ALIGN_LOG2 - 2))
|
||||
#else
|
||||
CALGN( add r4, r4, ip, lsl #(ARM_BX_ALIGN_LOG2 - 2))
|
||||
CALGN( bx r4 )
|
||||
#endif
|
||||
|
||||
PLD( sfi_pld r1, #0 )
|
||||
2: PLD( subs r2, r2, #96 )
|
||||
PLD( sfi_pld r1, #28 )
|
||||
PLD( blt 4f )
|
||||
PLD( sfi_pld r1, #60 )
|
||||
PLD( sfi_pld r1, #92 )
|
||||
|
||||
3: PLD( sfi_pld r1, #124 )
|
||||
4: sfi_breg r1, \
|
||||
ldmia \B!, {r3, r4, r5, r6, r7, r8, ip, lr}
|
||||
subs r2, r2, #32
|
||||
sfi_breg r0, \
|
||||
stmia \B!, {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
|
||||
#ifndef ARM_ALWAYS_BX
|
||||
/* C is always clear here. */
|
||||
addne pc, pc, ip, lsl #(ARM_BX_ALIGN_LOG2 - 2)
|
||||
b 7f
|
||||
#else
|
||||
beq 7f
|
||||
push {r10}
|
||||
cfi_adjust_cfa_offset (4)
|
||||
cfi_rel_offset (r10, 0)
|
||||
add r10, pc, ip, lsl #(ARM_BX_ALIGN_LOG2 - 2)
|
||||
bx r10
|
||||
#endif
|
||||
.p2align ARM_BX_ALIGN_LOG2
|
||||
6: nop
|
||||
.p2align ARM_BX_ALIGN_LOG2
|
||||
sfi_breg r1, \
|
||||
ldr r3, [\B], #4
|
||||
.p2align ARM_BX_ALIGN_LOG2
|
||||
sfi_breg r1, \
|
||||
ldr r4, [\B], #4
|
||||
.p2align ARM_BX_ALIGN_LOG2
|
||||
sfi_breg r1, \
|
||||
ldr r5, [\B], #4
|
||||
.p2align ARM_BX_ALIGN_LOG2
|
||||
sfi_breg r1, \
|
||||
ldr r6, [\B], #4
|
||||
.p2align ARM_BX_ALIGN_LOG2
|
||||
sfi_breg r1, \
|
||||
ldr r7, [\B], #4
|
||||
.p2align ARM_BX_ALIGN_LOG2
|
||||
sfi_breg r1, \
|
||||
ldr r8, [\B], #4
|
||||
.p2align ARM_BX_ALIGN_LOG2
|
||||
sfi_breg r1, \
|
||||
ldr lr, [\B], #4
|
||||
|
||||
#ifndef ARM_ALWAYS_BX
|
||||
add pc, pc, ip, lsl #(ARM_BX_ALIGN_LOG2 - 2)
|
||||
nop
|
||||
#else
|
||||
add r10, pc, ip, lsl #(ARM_BX_ALIGN_LOG2 - 2)
|
||||
bx r10
|
||||
#endif
|
||||
.p2align ARM_BX_ALIGN_LOG2
|
||||
nop
|
||||
.p2align ARM_BX_ALIGN_LOG2
|
||||
sfi_breg r0, \
|
||||
str r3, [\B], #4
|
||||
.p2align ARM_BX_ALIGN_LOG2
|
||||
sfi_breg r0, \
|
||||
str r4, [\B], #4
|
||||
.p2align ARM_BX_ALIGN_LOG2
|
||||
sfi_breg r0, \
|
||||
str r5, [\B], #4
|
||||
.p2align ARM_BX_ALIGN_LOG2
|
||||
sfi_breg r0, \
|
||||
str r6, [\B], #4
|
||||
.p2align ARM_BX_ALIGN_LOG2
|
||||
sfi_breg r0, \
|
||||
str r7, [\B], #4
|
||||
.p2align ARM_BX_ALIGN_LOG2
|
||||
sfi_breg r0, \
|
||||
str r8, [\B], #4
|
||||
.p2align ARM_BX_ALIGN_LOG2
|
||||
sfi_breg r0, \
|
||||
str lr, [\B], #4
|
||||
|
||||
#ifdef ARM_ALWAYS_BX
|
||||
pop {r10}
|
||||
cfi_adjust_cfa_offset (-4)
|
||||
cfi_restore (r10)
|
||||
#endif
|
||||
|
||||
CALGN( bcs 2b )
|
||||
|
||||
7: pop {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
|
||||
sfi_breg r1, \
|
||||
ldrbne r3, [\B], #1
|
||||
sfi_breg r1, \
|
||||
ldrbcs r4, [\B], #1
|
||||
sfi_breg r1, \
|
||||
ldrbcs ip, [\B]
|
||||
sfi_breg r0, \
|
||||
strbne r3, [\B], #1
|
||||
sfi_breg r0, \
|
||||
strbcs r4, [\B], #1
|
||||
sfi_breg r0, \
|
||||
strbcs ip, [\B]
|
||||
|
||||
#if ((defined (__ARM_ARCH_4T__) && defined(__THUMB_INTERWORK__)) \
|
||||
|| defined (ARM_ALWAYS_BX))
|
||||
pop {r0, r4, lr}
|
||||
cfi_adjust_cfa_offset (-12)
|
||||
cfi_restore (r4)
|
||||
cfi_restore (lr)
|
||||
bx lr
|
||||
#else
|
||||
pop {r0, r4, pc}
|
||||
#endif
|
||||
|
||||
cfi_restore_state
|
||||
|
||||
9: rsb ip, ip, #4
|
||||
cmp ip, #2
|
||||
sfi_breg r1, \
|
||||
ldrbgt r3, [\B], #1
|
||||
sfi_breg r1, \
|
||||
ldrbge r4, [\B], #1
|
||||
sfi_breg r1, \
|
||||
ldrb lr, [\B], #1
|
||||
sfi_breg r0, \
|
||||
strbgt r3, [\B], #1
|
||||
sfi_breg r0, \
|
||||
strbge r4, [\B], #1
|
||||
subs r2, r2, ip
|
||||
sfi_breg r0, \
|
||||
strb lr, [\B], #1
|
||||
blt 8b
|
||||
ands ip, r1, #3
|
||||
beq 1b
|
||||
|
||||
10: bic r1, r1, #3
|
||||
cmp ip, #2
|
||||
sfi_breg r1, \
|
||||
ldr lr, [\B], #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( sbcsne r4, ip, r2 ) @ C is always set here
|
||||
CALGN( subcc r2, r2, ip )
|
||||
CALGN( bcc 15f )
|
||||
|
||||
11: push {r5 - r8, r10}
|
||||
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 (r10, 16)
|
||||
|
||||
PLD( sfi_pld r1, #0 )
|
||||
PLD( subs r2, r2, #96 )
|
||||
PLD( sfi_pld r1, #28 )
|
||||
PLD( blt 13f )
|
||||
PLD( sfi_pld r1, #60 )
|
||||
PLD( sfi_pld r1, #92 )
|
||||
|
||||
12: PLD( sfi_pld r1, #124 )
|
||||
13: sfi_breg r1, \
|
||||
ldmia \B!, {r4, r5, r6, r7}
|
||||
mov r3, lr, PULL #\pull
|
||||
subs r2, r2, #32
|
||||
sfi_breg r1, \
|
||||
ldmia \B!, {r8, r10, 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, r10, PUSH #\push
|
||||
mov r10, r10, PULL #\pull
|
||||
orr r10, r10, ip, PUSH #\push
|
||||
mov ip, ip, PULL #\pull
|
||||
orr ip, ip, lr, PUSH #\push
|
||||
sfi_breg r0, \
|
||||
stmia \B!, {r3, r4, r5, r6, r7, r8, r10, ip}
|
||||
bge 12b
|
||||
PLD( cmn r2, #96 )
|
||||
PLD( bge 13b )
|
||||
|
||||
pop {r5 - r8, r10}
|
||||
cfi_adjust_cfa_offset (-20)
|
||||
cfi_restore (r5)
|
||||
cfi_restore (r6)
|
||||
cfi_restore (r7)
|
||||
cfi_restore (r8)
|
||||
cfi_restore (r10)
|
||||
|
||||
14: ands ip, r2, #28
|
||||
beq 16f
|
||||
|
||||
15: mov r3, lr, PULL #\pull
|
||||
sfi_breg r1, \
|
||||
ldr lr, [\B], #4
|
||||
subs ip, ip, #4
|
||||
orr r3, r3, lr, PUSH #\push
|
||||
sfi_breg r0, \
|
||||
str r3, [\B], #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)
|
360
sysdeps/arm/memmove.S
Normal file
360
sysdeps/arm/memmove.S
Normal file
@@ -0,0 +1,360 @@
|
||||
/* Copyright (C) 2006-2014 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/>. */
|
||||
|
||||
/* Thumb requires excessive IT insns here. */
|
||||
#define NO_THUMB
|
||||
#include <sysdep.h>
|
||||
#include <arm-features.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
|
||||
.syntax unified
|
||||
|
||||
/*
|
||||
* 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
|
||||
|
||||
push {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( sfi_pld r1, #-4 )
|
||||
bne 9f
|
||||
ands ip, r1, #3
|
||||
bne 10f
|
||||
|
||||
1: subs r2, r2, #(28)
|
||||
push {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( sbcsne r4, ip, r2 ) @ C is always set here
|
||||
CALGN( bcs 2f )
|
||||
CALGN( adr r4, 6f )
|
||||
CALGN( subs r2, r2, ip ) @ C is set here
|
||||
#ifndef ARM_ALWAYS_BX
|
||||
CALGN( add pc, r4, ip, lsl #(ARM_BX_ALIGN_LOG2 - 2))
|
||||
#else
|
||||
CALGN( add r4, r4, ip, lsl #(ARM_BX_ALIGN_LOG2 - 2))
|
||||
CALGN( bx r4 )
|
||||
#endif
|
||||
|
||||
PLD( sfi_pld r1, #-4 )
|
||||
2: PLD( subs r2, r2, #96 )
|
||||
PLD( sfi_pld r1, #-32 )
|
||||
PLD( blt 4f )
|
||||
PLD( sfi_pld r1, #-64 )
|
||||
PLD( sfi_pld r1, #-96 )
|
||||
|
||||
3: PLD( sfi_pld r1, #-128 )
|
||||
4: sfi_breg r1, \
|
||||
ldmdb \B!, {r3, r4, r5, r6, r7, r8, ip, lr}
|
||||
subs r2, r2, #32
|
||||
sfi_breg r0, \
|
||||
stmdb \B!, {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
|
||||
#ifndef ARM_ALWAYS_BX
|
||||
/* C is always clear here. */
|
||||
addne pc, pc, ip, lsl #(ARM_BX_ALIGN_LOG2 - 2)
|
||||
b 7f
|
||||
#else
|
||||
beq 7f
|
||||
push {r10}
|
||||
cfi_adjust_cfa_offset (4)
|
||||
cfi_rel_offset (r10, 0)
|
||||
add r10, pc, ip, lsl #(ARM_BX_ALIGN_LOG2 - 2)
|
||||
bx r10
|
||||
#endif
|
||||
.p2align ARM_BX_ALIGN_LOG2
|
||||
6: nop
|
||||
.p2align ARM_BX_ALIGN_LOG2
|
||||
sfi_breg r1, \
|
||||
ldr r3, [\B, #-4]!
|
||||
.p2align ARM_BX_ALIGN_LOG2
|
||||
sfi_breg r1, \
|
||||
ldr r4, [\B, #-4]!
|
||||
.p2align ARM_BX_ALIGN_LOG2
|
||||
sfi_breg r1, \
|
||||
ldr r5, [\B, #-4]!
|
||||
.p2align ARM_BX_ALIGN_LOG2
|
||||
sfi_breg r1, \
|
||||
ldr r6, [\B, #-4]!
|
||||
.p2align ARM_BX_ALIGN_LOG2
|
||||
sfi_breg r1, \
|
||||
ldr r7, [\B, #-4]!
|
||||
.p2align ARM_BX_ALIGN_LOG2
|
||||
sfi_breg r1, \
|
||||
ldr r8, [\B, #-4]!
|
||||
.p2align ARM_BX_ALIGN_LOG2
|
||||
sfi_breg r1, \
|
||||
ldr lr, [\B, #-4]!
|
||||
|
||||
#ifndef ARM_ALWAYS_BX
|
||||
add pc, pc, ip, lsl #(ARM_BX_ALIGN_LOG2 - 2)
|
||||
nop
|
||||
#else
|
||||
add r10, pc, ip, lsl #(ARM_BX_ALIGN_LOG2 - 2)
|
||||
bx r10
|
||||
#endif
|
||||
.p2align ARM_BX_ALIGN_LOG2
|
||||
nop
|
||||
.p2align ARM_BX_ALIGN_LOG2
|
||||
sfi_breg r0, \
|
||||
str r3, [\B, #-4]!
|
||||
.p2align ARM_BX_ALIGN_LOG2
|
||||
sfi_breg r0, \
|
||||
str r4, [\B, #-4]!
|
||||
.p2align ARM_BX_ALIGN_LOG2
|
||||
sfi_breg r0, \
|
||||
str r5, [\B, #-4]!
|
||||
.p2align ARM_BX_ALIGN_LOG2
|
||||
sfi_breg r0, \
|
||||
str r6, [\B, #-4]!
|
||||
.p2align ARM_BX_ALIGN_LOG2
|
||||
sfi_breg r0, \
|
||||
str r7, [\B, #-4]!
|
||||
.p2align ARM_BX_ALIGN_LOG2
|
||||
sfi_breg r0, \
|
||||
str r8, [\B, #-4]!
|
||||
.p2align ARM_BX_ALIGN_LOG2
|
||||
sfi_breg r0, \
|
||||
str lr, [\B, #-4]!
|
||||
|
||||
#ifdef ARM_ALWAYS_BX
|
||||
pop {r10}
|
||||
cfi_adjust_cfa_offset (-4)
|
||||
cfi_restore (r10)
|
||||
#endif
|
||||
|
||||
CALGN( bcs 2b )
|
||||
|
||||
7: pop {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
|
||||
sfi_breg r1, \
|
||||
ldrbne r3, [\B, #-1]!
|
||||
sfi_breg r1, \
|
||||
ldrbcs r4, [\B, #-1]!
|
||||
sfi_breg r1, \
|
||||
ldrbcs ip, [\B, #-1]
|
||||
sfi_breg r0, \
|
||||
strbne r3, [\B, #-1]!
|
||||
sfi_breg r0, \
|
||||
strbcs r4, [\B, #-1]!
|
||||
sfi_breg r0, \
|
||||
strbcs ip, [\B, #-1]
|
||||
|
||||
#if ((defined (__ARM_ARCH_4T__) && defined (__THUMB_INTERWORK__)) \
|
||||
|| defined (ARM_ALWAYS_BX))
|
||||
pop {r0, r4, lr}
|
||||
cfi_adjust_cfa_offset (-12)
|
||||
cfi_restore (r4)
|
||||
cfi_restore (lr)
|
||||
bx lr
|
||||
#else
|
||||
pop {r0, r4, pc}
|
||||
#endif
|
||||
|
||||
cfi_restore_state
|
||||
|
||||
9: cmp ip, #2
|
||||
sfi_breg r1, \
|
||||
ldrbgt r3, [\B, #-1]!
|
||||
sfi_breg r1, \
|
||||
ldrbge r4, [\B, #-1]!
|
||||
sfi_breg r1, \
|
||||
ldrb lr, [\B, #-1]!
|
||||
sfi_breg r0, \
|
||||
strbgt r3, [\B, #-1]!
|
||||
sfi_breg r0, \
|
||||
strbge r4, [\B, #-1]!
|
||||
subs r2, r2, ip
|
||||
sfi_breg r0, \
|
||||
strb lr, [\B, #-1]!
|
||||
blt 8b
|
||||
ands ip, r1, #3
|
||||
beq 1b
|
||||
|
||||
10: bic r1, r1, #3
|
||||
cmp ip, #2
|
||||
sfi_breg r1, \
|
||||
ldr r3, [\B, #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( sbcsne r4, ip, r2 ) @ C is always set here
|
||||
CALGN( subcc r2, r2, ip )
|
||||
CALGN( bcc 15f )
|
||||
|
||||
11: push {r5 - r8, r10}
|
||||
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 (r10, 16)
|
||||
|
||||
PLD( sfi_pld r1, #-4 )
|
||||
PLD( subs r2, r2, #96 )
|
||||
PLD( sfi_pld r1, #-32 )
|
||||
PLD( blt 13f )
|
||||
PLD( sfi_pld r1, #-64 )
|
||||
PLD( sfi_pld r1, #-96 )
|
||||
|
||||
12: PLD( sfi_pld r1, #-128 )
|
||||
13: sfi_breg r1, \
|
||||
ldmdb \B!, {r7, r8, r10, ip}
|
||||
mov lr, r3, PUSH #\push
|
||||
subs r2, r2, #32
|
||||
sfi_breg r1, \
|
||||
ldmdb \B!, {r3, r4, r5, r6}
|
||||
orr lr, lr, ip, PULL #\pull
|
||||
mov ip, ip, PUSH #\push
|
||||
orr ip, ip, r10, PULL #\pull
|
||||
mov r10, r10, PUSH #\push
|
||||
orr r10, r10, 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
|
||||
sfi_breg r0, \
|
||||
stmdb \B!, {r4 - r8, r10, ip, lr}
|
||||
bge 12b
|
||||
PLD( cmn r2, #96 )
|
||||
PLD( bge 13b )
|
||||
|
||||
pop {r5 - r8, r10}
|
||||
cfi_adjust_cfa_offset (-20)
|
||||
cfi_restore (r5)
|
||||
cfi_restore (r6)
|
||||
cfi_restore (r7)
|
||||
cfi_restore (r8)
|
||||
cfi_restore (r10)
|
||||
|
||||
14: ands ip, r2, #28
|
||||
beq 16f
|
||||
|
||||
15: mov lr, r3, PUSH #\push
|
||||
sfi_breg r1, \
|
||||
ldr r3, [\B, #-4]!
|
||||
subs ip, ip, #4
|
||||
orr lr, lr, r3, PULL #\pull
|
||||
sfi_breg r0, \
|
||||
str lr, [\B, #-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)
|
78
sysdeps/arm/memset.S
Normal file
78
sysdeps/arm/memset.S
Normal file
@@ -0,0 +1,78 @@
|
||||
/* Copyright (C) 1998-2014 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/>. */
|
||||
|
||||
/* Thumb requires excessive IT insns here. */
|
||||
#define NO_THUMB
|
||||
#include <sysdep.h>
|
||||
|
||||
.text
|
||||
.syntax unified
|
||||
|
||||
/* 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?
|
||||
sfi_breg r3, \
|
||||
strbne r1, [\B], #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
|
||||
sfi_breg r3, \
|
||||
stmiacs \B!, {r1, ip} @ store up to 32 bytes per loop iteration
|
||||
subscs r2, r2, #8
|
||||
sfi_breg r3, \
|
||||
stmiacs \B!, {r1, ip}
|
||||
subscs r2, r2, #8
|
||||
sfi_breg r3, \
|
||||
stmiacs \B!, {r1, ip}
|
||||
subscs r2, r2, #8
|
||||
sfi_breg r3, \
|
||||
stmiacs \B!, {r1, ip}
|
||||
bcs 1b
|
||||
|
||||
and r2, r2, #7
|
||||
2:
|
||||
subs r2, r2, #1 @ store up to 4 bytes per loop iteration
|
||||
sfi_breg r3, \
|
||||
strbcs r1, [\B], #1
|
||||
subscs r2, r2, #1
|
||||
sfi_breg r3, \
|
||||
strbcs r1, [\B], #1
|
||||
subscs r2, r2, #1
|
||||
sfi_breg r3, \
|
||||
strbcs r1, [\B], #1
|
||||
subscs r2, r2, #1
|
||||
sfi_breg r3, \
|
||||
strbcs r1, [\B], #1
|
||||
bcs 2b
|
||||
|
||||
DO_RET(lr)
|
||||
END(memset)
|
||||
libc_hidden_builtin_def (memset)
|
20
sysdeps/arm/memusage.h
Normal file
20
sysdeps/arm/memusage.h
Normal file
@@ -0,0 +1,20 @@
|
||||
/* Copyright (C) 2000-2014 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>
|
20
sysdeps/arm/nptl/Makefile
Normal file
20
sysdeps/arm/nptl/Makefile
Normal file
@@ -0,0 +1,20 @@
|
||||
# Copyright (C) 2005-2014 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
|
23
sysdeps/arm/nptl/pthread_spin_lock.c
Normal file
23
sysdeps/arm/nptl/pthread_spin_lock.c
Normal file
@@ -0,0 +1,23 @@
|
||||
/* Copyright (C) 2008-2014 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 SPIN_LOCK_READS_BETWEEN_CMPXCHG 1000
|
||||
|
||||
/* We can't use the normal "#include <nptl/pthread_spin_lock.c>" because
|
||||
it will resolve to this very file. Using "sysdeps/.." as reference to the
|
||||
top level directory does the job. */
|
||||
#include <sysdeps/../nptl/pthread_spin_lock.c>
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user