bionic: Add ARMv7 optimized string handling routines 49/2249/4
authorBernhard Rosenkraenzer <Bernhard.Rosenkranzer@linaro.org>
Mon, 11 Jun 2012 10:33:44 +0000 (12:33 +0200)
committerBernhard Rosenkraenzer <Bernhard.Rosenkranzer@linaro.org>
Mon, 11 Jun 2012 11:42:44 +0000 (13:42 +0200)
Add ARMv7 - and especially Cortex-A9 - optimized string handling
routines based on the versions found in the cortex-strings library.

Change-Id: I497075bea5b82aef8989625bdec512029676fe7f
Signed-off-by: Bernhard Rosenkraenzer <Bernhard.Rosenkranzer@linaro.org>
libc/Android.mk
libc/arch-arm/bionic/armv7/memchr.S [new file with mode: 0644]
libc/arch-arm/bionic/armv7/memcpy.S [new file with mode: 0644]
libc/arch-arm/bionic/armv7/memset.S [new file with mode: 0644]
libc/arch-arm/bionic/armv7/strchr.S [new file with mode: 0644]
libc/arch-arm/bionic/armv7/strcpy.c [new file with mode: 0644]
libc/arch-arm/bionic/armv7/strlen.S [new file with mode: 0644]

index 49c8731..2d6b339 100644 (file)
@@ -178,14 +178,12 @@ libc_common_src_files := \
        stdlib/wchar.c \
        string/index.c \
        string/memccpy.c \
-       string/memchr.c \
        string/memmem.c \
        string/memrchr.c \
        string/memswap.c \
        string/strcasecmp.c \
        string/strcasestr.c \
        string/strcat.c \
-       string/strchr.c \
        string/strcoll.c \
        string/strcspn.c \
        string/strdup.c \
@@ -355,12 +353,8 @@ libc_common_src_files += \
        arch-arm/bionic/tkill.S \
        arch-arm/bionic/memcmp.S \
        arch-arm/bionic/memcmp16.S \
-       arch-arm/bionic/memcpy.S \
-       arch-arm/bionic/memset.S \
        arch-arm/bionic/setjmp.S \
        arch-arm/bionic/sigsetjmp.S \
-       arch-arm/bionic/strlen.c.arm \
-       arch-arm/bionic/strcpy.S \
        arch-arm/bionic/strcmp.S \
        arch-arm/bionic/syscall.S \
        string/memmove.c.arm \
@@ -387,8 +381,31 @@ libc_arch_static_src_files := \
 
 libc_arch_dynamic_src_files := \
        arch-arm/bionic/exidx_dynamic.c
+
+ifeq ($(ARCH_ARM_HAVE_ARMV7A),true)
+libc_common_src_files += \
+       arch-arm/bionic/armv7/memchr.S \
+       arch-arm/bionic/armv7/memcpy.S \
+       arch-arm/bionic/armv7/memset.S \
+       arch-arm/bionic/armv7/strchr.S \
+       arch-arm/bionic/armv7/strcpy.c \
+       arch-arm/bionic/armv7/strlen.S
+else
+libc_common_src_files += \
+       string/memchr.c \
+       arch-arm/bionic/memcpy.S \
+       arch-arm/bionic/memset.S \
+       string/strchr.c \
+       arch-arm/bionic/strcpy.S \
+       arch-arm/bionic/strlen.c.arm
+endif
+
 else # !arm
 
+libc_common_src_files += \
+       string/memchr.c \
+       string/strchr.c
+
 ifeq ($(TARGET_ARCH),x86)
 libc_common_src_files += \
        arch-x86/bionic/__get_sp.S \
diff --git a/libc/arch-arm/bionic/armv7/memchr.S b/libc/arch-arm/bionic/armv7/memchr.S
new file mode 100644 (file)
index 0000000..02e59b9
--- /dev/null
@@ -0,0 +1,150 @@
+/* Copyright (c) 2010-2011, Linaro Limited
+   All rights reserved.
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+      * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+      * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+
+      * Neither the name of Linaro Limited nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+   HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+   Written by Dave Gilbert <david.gilbert@linaro.org>
+   Adapted to Bionic by Bernhard Rosenkraenzer <Bernhard.Rosenkranzer@linaro.org>
+
+   This memchr routine is optimised on a Cortex-A9 and should work on
+   all ARMv7 processors.   It has a fast past 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. */
+
+#include <machine/asm.h>
+
+@ 2011-02-07 david.gilbert@linaro.org
+@    Extracted from local git a5b438d861
+@ 2011-07-14 david.gilbert@linaro.org
+@    Import endianness fix from local git ea786f1b
+@ 2011-12-07 david.gilbert@linaro.org
+@    Removed unneeded cbz from align loop
+
+       .syntax unified
+       .arch armv7-a
+
+@ 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
+
+@ ---------------------------------------------------------------------------
+       .thumb_func
+       .p2align 4,,15
+ENTRY(memchr)
+       @ r0 = start of memory to scan
+       @ r1 = character to look for
+       @ r2 = length
+       @ returns r0 = pointer to character or NULL if not found
+       and     r1,r1,#0xff     @ Don't think we can trust the caller to actually pass a char
+
+       cmp     r2,#16          @ If it's short don't bother with anything clever
+       blt     20f
+
+       tst     r0, #7          @ If it's already aligned skip the next bit
+       beq     10f
+
+       @ Work up to an aligned point
+5:
+       ldrb    r3, [r0],#1
+       subs    r2, r2, #1
+       cmp     r3, r1
+       beq     50f             @ If it matches exit found
+       tst     r0, #7
+       bne     5b              @ If not aligned yet then do next byte
+
+10:
+       @ At this point, we are aligned, we know we have at least 8 bytes to work with
+       push    {r4,r5,r6,r7}
+       orr     r1, r1, r1, lsl #8      @ expand the match word across to all bytes
+       orr     r1, r1, r1, lsl #16
+       bic     r4, r2, #7      @ Number of double words to work with
+       mvns    r7, #0          @ all F's
+       movs    r3, #0
+
+15:
+       ldmia   r0!,{r5,r6}
+       subs    r4, r4, #8
+       eor     r5,r5, r1       @ Get it so that r5,r6 have 00's where the bytes match the target
+       eor     r6,r6, r1
+       uadd8   r5, r5, r7      @ Parallel add 0xff - sets the GE bits for anything that wasn't 0
+       sel     r5, r3, r7      @ bytes are 00 for none-00 bytes, or ff for 00 bytes - NOTE INVERSION
+       uadd8   r6, r6, r7      @ Parallel add 0xff - sets the GE bits for anything that wasn't 0
+       sel     r6, r5, r7      @ chained....bytes are 00 for none-00 bytes, or ff for 00 bytes - NOTE INVERSION
+       cbnz    r6, 60f
+       bne     15b             @ (Flags from the subs above) If not run out of bytes then go around again
+
+       pop     {r4,r5,r6,r7}
+       and     r1,r1,#0xff     @ Get r1 back to a single character from the expansion above
+       and     r2,r2,#7        @ Leave the count remaining as the number after the double words have been done
+
+20:
+       cbz     r2, 40f         @ 0 length or hit the end already then not found
+
+21:  @ Post aligned section, or just a short call
+       ldrb    r3,[r0],#1
+       subs    r2,r2,#1
+       eor     r3,r3,r1        @ r3 = 0 if match - doesn't break flags from sub
+       cbz     r3, 50f
+       bne     21b             @ on r2 flags
+
+40:
+       movs    r0,#0           @ not found
+       bx      lr
+
+50:
+       subs    r0,r0,#1        @ found
+       bx      lr
+
+60:  @ We're here because the fast path found a hit - now we have to track down exactly which word it was
+       @ r0 points to the start of the double word after the one that was tested
+       @ r5 has the 00/ff pattern for the first word, r6 has the chained value
+       cmp     r5, #0
+       itte    eq
+       moveq   r5, r6          @ the end is in the 2nd word
+       subeq   r0,r0,#3        @ Points to 2nd byte of 2nd word
+       subne   r0,r0,#7        @ or 2nd byte of 1st word
+
+       @ r0 currently points to the 3rd byte of the word containing the hit
+       tst     r5, # CHARTSTMASK(0)    @ 1st character
+       bne     61f
+       adds    r0,r0,#1
+       tst     r5, # CHARTSTMASK(1)    @ 2nd character
+       ittt    eq
+       addeq   r0,r0,#1
+       tsteq   r5, # (3<<15)           @ 2nd & 3rd character
+       @ If not the 3rd must be the last one
+       addeq   r0,r0,#1
+
+61:
+       pop     {r4,r5,r6,r7}
+       subs    r0,r0,#1
+       bx      lr
+END(memchr)
diff --git a/libc/arch-arm/bionic/armv7/memcpy.S b/libc/arch-arm/bionic/armv7/memcpy.S
new file mode 100644 (file)
index 0000000..f906c78
--- /dev/null
@@ -0,0 +1,374 @@
+/* Copyright (c) 2010-2011, Linaro Limited
+   All rights reserved.
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+      * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+      * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+
+      * Neither the name of Linaro Limited nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+   HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+   Written by Dave Gilbert <david.gilbert@linaro.org>
+   Adapted to Bionic by Bernhard Rosenkraenzer <Bernhard.Rosenkranzer@linaro.org>
+
+   This memcpy routine is optimised on a Cortex-A9 and should work on
+   all ARMv7 processors. */
+
+#include <machine/asm.h>
+
+@ 2011-09-01 david.gilbert@linaro.org
+@    Extracted from local git 2f11b436
+
+       .syntax unified
+       .arch armv7-a
+
+@ 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
+       .thumb
+
+#if defined(__ARM_NEON__)
+@ ---------------------------------------------------------------------------
+       .thumb_func
+       .p2align 4,,15
+ENTRY(memcpy)
+       @ r0 = dest
+       @ r1 = source
+       @ r2 = count
+       @ returns dest in r0
+       @ Overlaps of source/dest not allowed according to spec
+       @ Note this routine relies on v7 misaligned loads/stores
+       pld     [r1]
+       mov     r12, r0         @ stash original r0
+       cmp     r2,#32
+       blt     10f             @ take the small copy case separately
+
+       @ test for either source or destination being misaligned
+       @ (We only rely on word align)
+       tst     r0,#3
+       it      eq
+       tsteq   r1,#3
+       bne     30f             @ misaligned case
+
+4:
+       @ at this point we are word (or better) aligned and have at least
+       @ 32 bytes to play with
+
+       @ If it's a huge copy,  try Neon
+       cmp     r2, #128*1024
+       bge     35f             @ Sharing general non-aligned case here, aligned could be faster
+
+       push    {r3,r4,r5,r6,r7,r8,r10,r11}
+5:
+       ldmia   r1!,{r3,r4,r5,r6,r7,r8,r10,r11}
+       sub     r2,r2,#32
+       pld     [r1,#96]
+       cmp     r2,#32
+       stmia   r0!,{r3,r4,r5,r6,r7,r8,r10,r11}
+       bge     5b
+
+       pop     {r3,r4,r5,r6,r7,r8,r10,r11}
+       @ We are now down to less than 32 bytes
+       cbz     r2,15f          @ quick exit for the case where we copied a multiple of 32
+
+10:  @ small copies (not necessarily aligned - note might be slightly more than 32bytes)
+       cmp     r2,#4
+       blt     12f
+11:
+       sub     r2,r2,#4
+       cmp     r2,#4
+       ldr     r3, [r1],#4
+       str     r3, [r0],#4
+       bge     11b
+12:
+       tst     r2,#2
+       itt     ne
+       ldrhne  r3, [r1],#2
+       strhne  r3, [r0],#2
+
+       tst     r2,#1
+       itt     ne
+       ldrbne  r3, [r1],#1
+       strbne  r3, [r0],#1
+
+15:  @ exit
+       mov     r0,r12          @ restore r0
+       bx      lr
+
+       .align 2
+       .p2align 4,,15
+30:  @ non-aligned - at least 32 bytes to play with
+       @ Test for co-misalignment
+       eor     r3, r0, r1
+       tst     r3,#3
+       beq     50f
+
+       @ Use Neon for misaligned
+35:
+       vld1.8  {d0,d1,d2,d3}, [r1]!
+       sub     r2,r2,#32
+       cmp     r2,#32
+       pld     [r1,#96]
+       vst1.8  {d0,d1,d2,d3}, [r0]!
+       bge     35b
+       b       10b             @ TODO: Probably a bad idea to switch to ARM at this point
+
+       .align 2
+       .p2align 4,,15
+50: @ Co-misaligned
+       @ At this point we've got at least 32 bytes
+51:
+       ldrb    r3,[r1],#1
+       sub     r2,r2,#1
+       strb    r3,[r0],#1
+       tst     r0,#7
+       bne     51b
+
+       cmp     r2,#32
+       blt     10b
+       b       4b
+END(memcpy)
+#else /* __ARM_NEON__ */
+
+       .thumb
+
+@ ---------------------------------------------------------------------------
+       .thumb_func
+       .p2align 4,,15
+ENTRY(memcpy)
+       @ r0 = dest
+       @ r1 = source
+       @ r2 = count
+       @ returns dest in r0
+       @ Overlaps of source/dest not allowed according to spec
+       @ Note this routine relies on v7 misaligned loads/stores
+       pld     [r1]
+       mov     r12, r0         @ stash original r0
+       cmp     r2,#32
+       blt     10f             @ take the small copy case separately
+
+       @ test for either source or destination being misaligned
+       @ (We only rely on word align)
+       @ TODO: Test for co-misalignment
+       tst     r0,#3
+       it      eq
+       tsteq   r1,#3
+       bne     30f             @ misaligned case
+
+4:
+       @ at this point we are word (or better) aligned and have at least
+       @ 32 bytes to play with
+       push    {r3,r4,r5,r6,r7,r8,r10,r11}
+5:
+       ldmia   r1!,{r3,r4,r5,r6,r7,r8,r10,r11}
+       pld     [r1,#96]
+       sub     r2,r2,#32
+       cmp     r2,#32
+       stmia   r0!,{r3,r4,r5,r6,r7,r8,r10,r11}
+       bge     5b
+
+       pop     {r3,r4,r5,r6,r7,r8,r10,r11}
+       @ We are now down to less than 32 bytes
+       cbz     r2,15f          @ quick exit for the case where we copied a multiple of 32
+
+10:  @ small copies (not necessarily aligned - note might be slightly more than 32bytes)
+       cmp     r2,#4
+       blt     12f
+11:
+       sub     r2,r2,#4
+       cmp     r2,#4
+       ldr     r3, [r1],#4
+       str     r3, [r0],#4
+       bge     11b
+12:
+       tst     r2,#2
+       itt     ne
+       ldrhne  r3, [r1],#2
+       strhne  r3, [r0],#2
+
+       tst     r2,#1
+       itt     ne
+       ldrbne  r3, [r1],#1
+       strbne  r3, [r0],#1
+
+15:  @ exit
+       mov     r0,r12          @ restore r0
+       bx      lr
+
+30:  @ non-aligned - at least 32 bytes to play with
+       @ On v7 we're allowed to do ldr's and str's from arbitrary alignments
+       @ but not ldrd/strd or ldm/stm
+       @ Note Neon is often a better choice misaligned using vld1
+
+       @ copy a byte at a time until the point where we have an aligned destination
+       @ we know we have enough bytes to go to know we won't run out in this phase
+       tst     r0,#7
+       beq     35f
+
+31:
+       ldrb    r3,[r1],#1
+       sub     r2,r2,#1
+       strb    r3,[r0],#1
+       tst     r0,#7
+       bne     31b
+
+       cmp     r2,#32          @ Lets get back to knowing we have 32 bytes to play with
+       blt     11b
+
+       @ Now the store address is aligned
+35:
+       push    {r3,r4,r5,r6,r7,r8,r10,r11,r12,r14}
+       and     r6,r1,#3        @ how misaligned we are
+       cmp     r6,#2
+       cbz     r6, 100f        @ Go there if we're actually aligned
+       bge     120f            @ And here if it's aligned on 2 or 3 byte
+               @ Note might be worth splitting to bgt and a separate beq
+               @ if the branches are well separated
+
+       @ At this point dest is aligned, source is 1 byte forward
+110:
+       ldr     r3,[r1]         @ Misaligned load - but it gives the first 4 bytes to store
+       sub     r2,r2,#3        @ Number of bytes left in whole words we can load
+       add     r1,r1,#3        @ To aligned load address
+       bic     r3,r3,#0xff000000
+
+112:
+       ldmia   r1!,{r5,r6,r7,r8}
+       sub     r2,r2,#32
+       cmp     r2,#32
+       pld     [r1,#96]
+
+       orr     r3,r3,r5,lsl#24
+       mov     r4,r5,lsr#8
+       mov     r5,r6,lsr#8
+       orr     r4,r4,r6,lsl#24
+       mov     r6,r7,lsr#8
+       ldmia   r1!,{r10,r11,r12,r14}
+       orr     r5,r5,r7,lsl#24
+       mov     r7,r8,lsr#8
+       orr     r6,r6,r8,lsl#24
+       mov     r8,r10,lsr#8
+       orr     r7,r7,r10,lsl#24
+       mov     r10,r11,lsr#8
+       orr     r8,r8,r11,lsl#24
+       orr     r10,r10,r12,lsl#24
+       mov     r11,r12,lsr#8
+       orr     r11,r11,r14,lsl#24
+       stmia   r0!,{r3,r4,r5,r6,r7,r8,r10,r11}
+       mov     r3,r14,lsr#8
+
+       bge     112b
+
+       @ Deal with the stragglers
+       add     r2,r2,#3
+       sub     r1,r1,#3
+       pop     {r3,r4,r5,r6,r7,r8,r10,r11,r12,r14}
+       b       10b
+
+100:  @ Dest and source aligned - must have been originally co-misaligned
+       @ Fallback to main aligned case if still big enough
+       pop     {r3,r4,r5,r6,r7,r8,r10,r11,r12,r14}
+       b       4b              @ Big copies (32 bytes or more)
+
+120:  @ Dest is aligned, source is align+2 or 3
+       bgt     130f            @ Now split off for 3 byte offset
+
+       ldrh    r3,[r1]
+       sub     r2,r2,#2        @ Number of bytes left in whole words we can load
+       add     r1,r1,#2        @ To aligned load address
+
+122:
+       ldmia   r1!,{r5,r6,r7,r8}
+       sub     r2,r2,#32
+       cmp     r2,#32
+       pld     [r1,#96]
+
+       orr     r3,r3,r5,lsl#16
+       mov     r4,r5,lsr#16
+       mov     r5,r6,lsr#16
+       orr     r4,r4,r6,lsl#16
+       mov     r6,r7,lsr#16
+       ldmia   r1!,{r10,r11,r12,r14}
+       orr     r5,r5,r7,lsl#16
+       orr     r6,r6,r8,lsl#16
+       mov     r7,r8,lsr#16
+       orr     r7,r7,r10,lsl#16
+       mov     r8,r10,lsr#16
+       orr     r8,r8,r11,lsl#16
+       mov     r10,r11,lsr#16
+       orr     r10,r10,r12,lsl#16
+       mov     r11,r12,lsr#16
+       orr     r11,r11,r14,lsl#16
+       stmia   r0!,{r3,r4,r5,r6,r7,r8,r10,r11}
+       mov     r3,r14,lsr#16
+
+       bge     122b
+
+       @ Deal with the stragglers
+       add     r2,r2,#2
+       sub     r1,r1,#2
+       pop     {r3,r4,r5,r6,r7,r8,r10,r11,r12,r14}
+       b       10b
+
+130:  @ Dest is aligned, source is align+3
+       ldrb    r3,[r1]
+       sub     r2,r2,#1        @ Number of bytes left in whole words we can load
+       add     r1,r1,#1        @ To aligned load address
+
+132:
+       ldmia   r1!,{r5,r6,r7,r8}
+       sub     r2,r2,#32
+       cmp     r2,#32
+       pld     [r1,#96]
+
+       orr     r3,r3,r5,lsl#8
+       mov     r4,r5,lsr#24
+       mov     r5,r6,lsr#24
+       orr     r4,r4,r6,lsl#8
+       mov     r6,r7,lsr#24
+       ldmia   r1!,{r10,r11,r12,r14}
+       orr     r5,r5,r7,lsl#8
+       mov     r7,r8,lsr#24
+       orr     r6,r6,r8,lsl#8
+       mov     r8,r10,lsr#24
+       orr     r7,r7,r10,lsl#8
+       orr     r8,r8,r11,lsl#8
+       mov     r10,r11,lsr#24
+       orr     r10,r10,r12,lsl#8
+       mov     r11,r12,lsr#24
+       orr     r11,r11,r14,lsl#8
+       stmia   r0!,{r3,r4,r5,r6,r7,r8,r10,r11}
+       mov     r3,r14,lsr#24
+
+       bge     132b
+
+       @ Deal with the stragglers
+       add     r2,r2,#1
+       sub     r1,r1,#1
+       pop     {r3,r4,r5,r6,r7,r8,r10,r11,r12,r14}
+       b       10b
+END(memcpy)
+#endif
diff --git a/libc/arch-arm/bionic/armv7/memset.S b/libc/arch-arm/bionic/armv7/memset.S
new file mode 100644 (file)
index 0000000..0ecaf49
--- /dev/null
@@ -0,0 +1,124 @@
+/* Copyright (c) 2010-2011, Linaro Limited
+   All rights reserved.
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+      * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+      * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+
+      * Neither the name of Linaro Limited nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+   HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+   Written by Dave Gilbert <david.gilbert@linaro.org>
+   Adapted to Bionic by Bernhard Rosenkraenzer <Bernhard.Rosenkranzer@linaro.org>
+
+   This memset routine is optimised on a Cortex-A9 and should work on
+   all ARMv7 processors. */
+
+#include <machine/asm.h>
+
+       .syntax unified
+       .arch armv7-a
+
+ENTRY(bzero)
+       mov     r2, r1
+       mov     r1, #0
+END(bzero)
+
+@ 2011-08-30 david.gilbert@linaro.org
+@    Extracted from local git 2f11b436
+
+@ 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
+       .text
+       .thumb
+
+@ ---------------------------------------------------------------------------
+       .thumb_func
+       .p2align 4,,15
+ENTRY(memset)
+       @ r0 = address
+       @ r1 = character
+       @ r2 = count
+       @ returns original address in r0
+
+       mov     r3, r0          @ Leave r0 alone
+       cbz     r2, 10f         @ Exit if 0 length
+
+       tst     r0, #7
+       beq     2f              @ Already aligned
+
+       @ Ok, so we're misaligned here
+1:
+       strb    r1, [r3], #1
+       subs    r2,r2,#1
+       tst     r3, #7
+       cbz     r2, 10f         @ Exit if we hit the end
+       bne     1b              @ go round again if still misaligned
+
+2:
+       @ OK, so we're aligned
+       push    {r4,r5,r6,r7}
+       bics    r4, r2, #15     @ if less than 16 bytes then need to finish it off
+       beq     5f
+
+3:
+       @ POSIX says that ch is cast to an unsigned char.  A uxtb is one
+       @ byte and takes two cycles, where an AND is four bytes but one
+       @ cycle.
+       and     r1, #0xFF
+       orr     r1, r1, r1, lsl#8       @ Same character into all bytes
+       orr     r1, r1, r1, lsl#16
+       mov     r5,r1
+       mov     r6,r1
+       mov     r7,r1
+
+4:
+       subs    r4,r4,#16
+       stmia   r3!,{r1,r5,r6,r7}
+       bne     4b
+       and     r2,r2,#15
+
+       @ At this point we're still aligned and we have upto align-1 bytes left to right
+       @ we can avoid some of the byte-at-a time now by testing for some big chunks
+       tst     r2,#8
+       itt     ne
+       subne   r2,r2,#8
+       stmiane r3!,{r1,r5}
+
+5:
+       pop     {r4,r5,r6,r7}
+       cbz     r2, 10f
+
+       @ Got to do any last < alignment bytes
+6:
+       subs    r2,r2,#1
+       strb    r1,[r3],#1
+       bne     6b
+
+10:
+       bx      lr              @ goodbye
+END(memset)
diff --git a/libc/arch-arm/bionic/armv7/strchr.S b/libc/arch-arm/bionic/armv7/strchr.S
new file mode 100644 (file)
index 0000000..370aac9
--- /dev/null
@@ -0,0 +1,77 @@
+/* Copyright (c) 2010-2011, Linaro Limited
+   All rights reserved.
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+      * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+      * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+
+      * Neither the name of Linaro Limited nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+   HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+   Written by Dave Gilbert <david.gilbert@linaro.org>
+   Adapted to Bionic by Bernhard Rosenkraenzer <Bernhard.Rosenkranzer@linaro.org>
+
+   A very simple strchr routine, from benchmarks on A9 it's a bit faster than
+   the current version in eglibc (2.12.1-0ubuntu14 package)
+   I don't think doing a word at a time version is worth it since a lot
+    of strchr cases are very short anyway */
+
+#include <machine/asm.h>
+
+@ 2011-02-07 david.gilbert@linaro.org
+@    Extracted from local git a5b438d861
+
+       .syntax unified
+       .arch armv7-a
+
+       .text
+       .thumb
+
+@ ---------------------------------------------------------------------------
+
+       .thumb_func
+       .p2align 4,,15
+ENTRY(strchr)
+       @ r0 = start of string
+       @ r1 = character to match
+       @ returns NULL for no match, or a pointer to the match
+       and     r1,r1, #255
+
+1:
+       ldrb    r2,[r0],#1
+       cmp     r2,r1
+       cbz     r2,10f
+       bne     1b
+
+       @ We're here if it matched
+5:
+       subs    r0,r0,#1
+       bx      lr
+
+10:
+       @ We're here if we ran off the end
+       cmp     r1, #0  @ Corner case - you're allowed to search for the nil and get a pointer to it
+       beq     5b      @ A bit messy, if it's common we should branch at the start to a special loop
+       mov     r0,#0
+       bx      lr
+END(strchr)
diff --git a/libc/arch-arm/bionic/armv7/strcpy.c b/libc/arch-arm/bionic/armv7/strcpy.c
new file mode 100644 (file)
index 0000000..ce74de6
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2008 ARM Ltd
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the company may not be used to endorse or promote
+ *    products derived from this software without specific prior written
+ *    permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <string.h>
+
+#ifdef __thumb2__
+#define magic1(REG) "#0x01010101"
+#define magic2(REG) "#0x80808080"
+#else
+#define magic1(REG) #REG
+#define magic2(REG) #REG ", lsl #7"
+#endif
+
+#pragma GCC diagnostic push
+/* gcc fails to see the fat that the assembly code
+ * takes care of a return value, causing a
+ * "control reaches end of non-void function"
+ * warning (and, of course, error when building
+ * with -Werror).
+ * Let's disable that warning just for this
+ * function, where we know it's bogus. */
+#pragma GCC diagnostic ignored "-Wreturn-type"
+
+char* __attribute__((naked))
+strcpy (char* dst, const char* src)
+{
+  asm (
+#if !(defined(__OPTIMIZE_SIZE__) || defined (PREFER_SIZE_OVER_SPEED) || \
+      (defined (__thumb__) && !defined (__thumb2__)))
+       "pld    [r1, #0]\n\t"
+       "eor    r2, r0, r1\n\t"
+       "mov    ip, r0\n\t"
+       "tst    r2, #3\n\t"
+       "bne    4f\n\t"
+       "tst    r1, #3\n\t"
+       "bne    3f\n"
+  "5:\n\t"
+#ifndef __thumb2__
+       "str    r5, [sp, #-4]!\n\t"
+       "mov    r5, #0x01\n\t"
+       "orr    r5, r5, r5, lsl #8\n\t"
+       "orr    r5, r5, r5, lsl #16\n\t"
+#endif
+
+       "str    r4, [sp, #-4]!\n\t"
+       "tst    r1, #4\n\t"
+       "ldr    r3, [r1], #4\n\t"
+       "beq    2f\n\t"
+       "sub    r2, r3, "magic1(r5)"\n\t"
+       "bics   r2, r2, r3\n\t"
+       "tst    r2, "magic2(r5)"\n\t"
+       "itt    eq\n\t"
+       "streq  r3, [ip], #4\n\t"
+       "ldreq  r3, [r1], #4\n"
+       "bne    1f\n\t"
+       /* Inner loop.  We now know that r1 is 64-bit aligned, so we
+         can safely fetch up to two words.  This allows us to avoid
+         load stalls.  */
+       ".p2align 2\n"
+  "2:\n\t"
+       "pld    [r1, #8]\n\t"
+       "ldr    r4, [r1], #4\n\t"
+       "sub    r2, r3, "magic1(r5)"\n\t"
+       "bics   r2, r2, r3\n\t"
+       "tst    r2, "magic2(r5)"\n\t"
+       "sub    r2, r4, "magic1(r5)"\n\t"
+       "bne    1f\n\t"
+       "str    r3, [ip], #4\n\t"
+       "bics   r2, r2, r4\n\t"
+       "tst    r2, "magic2(r5)"\n\t"
+       "itt    eq\n\t"
+       "ldreq  r3, [r1], #4\n\t"
+       "streq  r4, [ip], #4\n\t"
+       "beq    2b\n\t"
+       "mov    r3, r4\n"
+  "1:\n\t"
+#ifdef __ARMEB__
+       "rors   r3, r3, #24\n\t"
+#endif
+       "strb   r3, [ip], #1\n\t"
+       "tst    r3, #0xff\n\t"
+#ifdef __ARMEL__
+       "ror    r3, r3, #8\n\t"
+#endif
+       "bne    1b\n\t"
+       "ldr    r4, [sp], #4\n\t"
+#ifndef __thumb2__
+       "ldr    r5, [sp], #4\n\t"
+#endif
+       "BX LR\n"
+
+       /* Strings have the same offset from word alignment, but it's
+         not zero.  */
+  "3:\n\t"
+       "tst    r1, #1\n\t"
+       "beq    1f\n\t"
+       "ldrb   r2, [r1], #1\n\t"
+       "strb   r2, [ip], #1\n\t"
+       "cmp    r2, #0\n\t"
+       "it     eq\n"
+       "BXEQ LR\n"
+  "1:\n\t"
+       "tst    r1, #2\n\t"
+       "beq    5b\n\t"
+       "ldrh   r2, [r1], #2\n\t"
+#ifdef __ARMEB__
+       "tst    r2, #0xff00\n\t"
+       "iteet  ne\n\t"
+       "strneh r2, [ip], #2\n\t"
+       "lsreq  r2, r2, #8\n\t"
+       "streqb r2, [ip]\n\t"
+       "tstne  r2, #0xff\n\t"
+#else
+       "tst    r2, #0xff\n\t"
+       "itet   ne\n\t"
+       "strneh r2, [ip], #2\n\t"
+       "streqb r2, [ip]\n\t"
+       "tstne  r2, #0xff00\n\t"
+#endif
+       "bne    5b\n\t"
+       "BX LR\n"
+
+       /* src and dst do not have a common word-alignement.  Fall back to
+         byte copying.  */
+  "4:\n\t"
+       "ldrb   r2, [r1], #1\n\t"
+       "strb   r2, [ip], #1\n\t"
+       "cmp    r2, #0\n\t"
+       "bne    4b\n\t"
+       "BX LR"
+
+#elif !defined (__thumb__) || defined (__thumb2__)
+       "mov    r3, r0\n\t"
+  "1:\n\t"
+       "ldrb   r2, [r1], #1\n\t"
+       "strb   r2, [r3], #1\n\t"
+       "cmp    r2, #0\n\t"
+       "bne    1b\n\t"
+       "BX LR"
+#else
+       "mov    r3, r0\n\t"
+  "1:\n\t"
+       "ldrb   r2, [r1]\n\t"
+       "add    r1, r1, #1\n\t"
+       "strb   r2, [r3]\n\t"
+       "add    r3, r3, #1\n\t"
+       "cmp    r2, #0\n\t"
+       "bne    1b\n\t"
+       "BX LR"
+#endif
+       );
+}
+
+#pragma GCC diagnostic pop
diff --git a/libc/arch-arm/bionic/armv7/strlen.S b/libc/arch-arm/bionic/armv7/strlen.S
new file mode 100644 (file)
index 0000000..5b76826
--- /dev/null
@@ -0,0 +1,113 @@
+/* Copyright (c) 2010-2011, Linaro Limited
+   All rights reserved.
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+      * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+      * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+
+      * Neither the name of Linaro Limited nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+   HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+   Written by Dave Gilbert <david.gilbert@linaro.org>
+   Adapted to Bionic by Bernhard Rosenkraenzer <bernhard.rosenkranzer@linaro.org>
+
+   This strlen routine is optimised on a Cortex-A9 and should work on
+   all ARMv7 processors.   This routine is reasonably fast for short
+   strings, but is probably slower than a simple implementation if all
+   your strings are very short */
+
+@ 2011-02-08 david.gilbert@linaro.org
+@    Extracted from local git 6848613a
+
+
+@ this lets us check a flag in a 00/ff byte easily in either endianness
+
+#include <machine/asm.h>
+
+#ifdef __ARMEB__
+#define CHARTSTMASK(c) 1<<(31-(c*8))
+#else
+#define CHARTSTMASK(c) 1<<(c*8)
+#endif
+
+@-----------------------------------------------------------------------------------------------------------------------------
+       .syntax unified
+       .arch armv7-a
+
+       .thumb_func
+       .p2align 4,,15
+ENTRY(strlen)
+       @ r0 = string
+       @ returns count of bytes in string not including terminator
+       mov     r1, r0
+       push    { r4,r6 }
+       mvns    r6, #0          @ all F
+       movs    r4, #0
+       tst     r0, #7
+       beq     2f
+
+1:
+       ldrb    r2, [r1], #1
+       tst     r1, #7          @ Hit alignment yet?
+       cbz     r2, 10f         @ Exit if we found the 0
+       bne     1b
+
+       @ So we're now aligned
+2:
+       ldmia   r1!,{r2,r3}
+       uadd8   r2, r2, r6      @ Parallel add 0xff - sets the GE bits for anything that wasn't 0
+       sel     r2, r4, r6      @ bytes are 00 for none-00 bytes, or ff for 00 bytes - NOTE INVERSION
+       uadd8   r3, r3, r6      @ Parallel add 0xff - sets the GE bits for anything that wasn't 0
+       sel     r3, r2, r6      @ bytes are 00 for none-00 bytes, or ff for 00 bytes - NOTE INVERSION
+       cmp     r3, #0
+       beq     2b
+
+strlenendtmp:
+       @ One (or more) of the bytes we loaded was 0 - but which one?
+       @ r2 has the mask corresponding to the first loaded word
+       @ r3 has a combined mask of the two words - but if r2 was all-non 0
+       @ then it's just the 2nd words
+       cmp     r2, #0
+       itte    eq
+       moveq   r2, r3          @ the end is in the 2nd word
+       subeq   r1,r1,#3
+       subne   r1,r1,#7
+
+       @ r1 currently points to the 2nd byte of the word containing the 0
+       tst     r2, # CHARTSTMASK(0)    @ 1st character
+       bne     10f
+       adds    r1,r1,#1
+       tst     r2, # CHARTSTMASK(1)    @ 2nd character
+       ittt    eq
+       addeq   r1,r1,#1
+       tsteq   r2, # (3<<15)   @ 2nd & 3rd character
+       @ If not the 3rd must be the last one
+       addeq   r1,r1,#1
+
+10:
+       @ r0 is still at the beginning, r1 is pointing 1 byte after the terminator
+       sub     r0, r1, r0
+       subs    r0, r0, #1
+       pop     { r4, r6 }
+       bx      lr
+END(strlen)