mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-30 00:31:08 +00:00
c6bfe5c4d7
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.
110 lines
3.1 KiB
ArmAsm
110 lines
3.1 KiB
ArmAsm
/* 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)
|