]> sourceware.org Git - newlib-cygwin.git/commitdiff
2013-01-10 Marcus Shawcroft <marcus.shawcroft@linaro.org>
authorMarcus Shawcroft <marcus.shawcroft@arm.com>
Thu, 10 Jan 2013 13:00:40 +0000 (13:00 +0000)
committerMarcus Shawcroft <marcus.shawcroft@arm.com>
Thu, 10 Jan 2013 13:00:40 +0000 (13:00 +0000)
        * libc/machine/aarch64/Makefile.am (lib_a_SOURCES): Add
        strnlen-stub.c and strnlen.S
        * libc/machine/aarch64/Makefile.in: Regenerated.
        * libc/machine/aarch64/strnlen-stub.c: New file.
        * libc/machine/aarch64/strnlen.S: New file.

newlib/ChangeLog
newlib/libc/machine/aarch64/Makefile.am
newlib/libc/machine/aarch64/Makefile.in
newlib/libc/machine/aarch64/strnlen-stub.c [new file with mode: 0644]
newlib/libc/machine/aarch64/strnlen.S [new file with mode: 0644]

index ecff125ffe3321b079f90fc094167be8fe674d8d..610edbc5a0f886fdaa335786eceef6f6a901c31e 100644 (file)
@@ -1,3 +1,11 @@
+2013-01-10  Marcus Shawcroft  <marcus.shawcroft@linaro.org>
+
+        * libc/machine/aarch64/Makefile.am (lib_a_SOURCES): Add
+       strnlen-stub.c and strnlen.S
+       * libc/machine/aarch64/Makefile.in: Regenerated.
+       * libc/machine/aarch64/strnlen-stub.c: New file.
+       * libc/machine/aarch64/strnlen.S: New file.
+
 2013-01-10  Marcus Shawcroft  <marcus.shawcroft@linaro.org>
 
        * libc/machine/aarch64/Makefile.am (lib_a_SOURCES):
index d454975d746a4b2fbedb36b89e4da00bf022f8da..21aeed1cd9a3fc32b5d4536e302b830319230907 100644 (file)
@@ -22,6 +22,8 @@ lib_a_SOURCES += strlen-stub.c
 lib_a_SOURCES += strlen.S
 lib_a_SOURCES += strncmp-stub.c
 lib_a_SOURCES += strncmp.S
+lib_a_SOURCES += strnlen-stub.c
+lib_a_SOURCES += strnlen.S
 
 lib_a_CCASFLAGS=$(AM_CCASFLAGS)
 lib_a_CFLAGS=$(AM_CFLAGS)
index 78a312d34dd5939e24f647db867c3ea3115f949c..b5a9724e8ea3e763e1d5ab8644cb967a9fcd1c5e 100644 (file)
@@ -75,7 +75,8 @@ am_lib_a_OBJECTS = lib_a-memcpy-stub.$(OBJEXT) lib_a-memcpy.$(OBJEXT) \
        lib_a-setjmp.$(OBJEXT) lib_a-strcmp-stub.$(OBJEXT) \
        lib_a-strcmp.$(OBJEXT) lib_a-strlen-stub.$(OBJEXT) \
        lib_a-strlen.$(OBJEXT) lib_a-strncmp-stub.$(OBJEXT) \
-       lib_a-strncmp.$(OBJEXT)
+       lib_a-strncmp.$(OBJEXT) lib_a-strnlen-stub.$(OBJEXT) \
+       lib_a-strnlen.$(OBJEXT)
 lib_a_OBJECTS = $(am_lib_a_OBJECTS)
 DEFAULT_INCLUDES = -I.@am__isrc@
 depcomp =
@@ -203,7 +204,8 @@ AM_CCASFLAGS = $(INCLUDES)
 noinst_LIBRARIES = lib.a
 lib_a_SOURCES = memcpy-stub.c memcpy.S memmove-stub.c memmove.S \
        memset-stub.c memset.S setjmp.S strcmp-stub.c strcmp.S \
-       strlen-stub.c strlen.S strncmp-stub.c strncmp.S
+       strlen-stub.c strlen.S strncmp-stub.c strncmp.S strnlen-stub.c \
+       strnlen.S
 lib_a_CCASFLAGS = $(AM_CCASFLAGS)
 lib_a_CFLAGS = $(AM_CFLAGS)
 ACLOCAL_AMFLAGS = -I ../../.. -I ../../../..
@@ -308,6 +310,12 @@ lib_a-strncmp.o: strncmp.S
 lib_a-strncmp.obj: strncmp.S
        $(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CCASFLAGS) $(CCASFLAGS) -c -o lib_a-strncmp.obj `if test -f 'strncmp.S'; then $(CYGPATH_W) 'strncmp.S'; else $(CYGPATH_W) '$(srcdir)/strncmp.S'; fi`
 
+lib_a-strnlen.o: strnlen.S
+       $(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CCASFLAGS) $(CCASFLAGS) -c -o lib_a-strnlen.o `test -f 'strnlen.S' || echo '$(srcdir)/'`strnlen.S
+
+lib_a-strnlen.obj: strnlen.S
+       $(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CCASFLAGS) $(CCASFLAGS) -c -o lib_a-strnlen.obj `if test -f 'strnlen.S'; then $(CYGPATH_W) 'strnlen.S'; else $(CYGPATH_W) '$(srcdir)/strnlen.S'; fi`
+
 .c.o:
        $(COMPILE) -c $<
 
@@ -350,6 +358,12 @@ lib_a-strncmp-stub.o: strncmp-stub.c
 lib_a-strncmp-stub.obj: strncmp-stub.c
        $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-strncmp-stub.obj `if test -f 'strncmp-stub.c'; then $(CYGPATH_W) 'strncmp-stub.c'; else $(CYGPATH_W) '$(srcdir)/strncmp-stub.c'; fi`
 
+lib_a-strnlen-stub.o: strnlen-stub.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-strnlen-stub.o `test -f 'strnlen-stub.c' || echo '$(srcdir)/'`strnlen-stub.c
+
+lib_a-strnlen-stub.obj: strnlen-stub.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-strnlen-stub.obj `if test -f 'strnlen-stub.c'; then $(CYGPATH_W) 'strnlen-stub.c'; else $(CYGPATH_W) '$(srcdir)/strnlen-stub.c'; fi`
+
 ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
        list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
        unique=`for i in $$list; do \
diff --git a/newlib/libc/machine/aarch64/strnlen-stub.c b/newlib/libc/machine/aarch64/strnlen-stub.c
new file mode 100644 (file)
index 0000000..8e1903c
--- /dev/null
@@ -0,0 +1,31 @@
+/* Copyright (c) 2013, 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 the Linaro 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. */
+
+#if (defined (__OPTIMIZE_SIZE__) || defined (PREFER_SIZE_OVER_SPEED))
+# include "../../string/strnlen.c"
+#else
+/* See strnlen.S  */
+#endif
diff --git a/newlib/libc/machine/aarch64/strnlen.S b/newlib/libc/machine/aarch64/strnlen.S
new file mode 100644 (file)
index 0000000..893163d
--- /dev/null
@@ -0,0 +1,170 @@
+/* strnlen - calculate the length of a string with limit.
+
+   Copyright (c) 2013, 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 the Linaro 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. */
+
+#if (defined (__OPTIMIZE_SIZE__) || defined (PREFER_SIZE_OVER_SPEED))
+/* See strlen-stub.c  */
+#else
+
+/* Assumptions:
+ *
+ * ARMv8-a, AArch64
+ */
+
+/* Arguments and results.  */
+#define srcin          x0
+#define len            x0
+#define limit          x1
+
+/* Locals and temporaries.  */
+#define src            x2
+#define data1          x3
+#define data2          x4
+#define data2a         x5
+#define has_nul1       x6
+#define has_nul2       x7
+#define tmp1           x8
+#define tmp2           x9
+#define tmp3           x10
+#define tmp4           x11
+#define zeroones       x12
+#define pos            x13
+#define limit_wd       x14
+
+       .macro def_fn f p2align=0
+       .text
+       .p2align \p2align
+       .global \f
+       .type \f, %function
+\f:
+       .endm
+
+#define REP8_01 0x0101010101010101
+#define REP8_7f 0x7f7f7f7f7f7f7f7f
+#define REP8_80 0x8080808080808080
+
+       .text
+       .p2align        6
+.Lstart:
+       /* Pre-pad to ensure critical loop begins an icache line.  */
+       .rep 7
+       nop
+       .endr
+       /* Put this code here to avoid wasting more space with pre-padding.  */
+.Lhit_limit:
+       mov     len, limit
+       ret
+
+def_fn strnlen
+       cbz     limit, .Lhit_limit
+       mov     zeroones, #REP8_01
+       bic     src, srcin, #15
+       ands    tmp1, srcin, #15
+       b.ne    .Lmisaligned
+       add     limit_wd, limit, #15
+       lsr     limit_wd, limit_wd, #4
+       /* NUL detection works on the principle that (X - 1) & (~X) & 0x80
+          (=> (X - 1) & ~(X | 0x7f)) is non-zero iff a byte is zero, and
+          can be done in parallel across the entire word.  */
+       /* The inner loop deals with two Dwords at a time.  This has a
+          slightly higher start-up cost, but we should win quite quickly,
+          especially on cores with a high number of issue slots per
+          cycle, as we get much better parallelism out of the operations.  */
+
+       /* Start of critial section -- keep to one 64Byte cache line.  */
+.Lloop:
+       ldp     data1, data2, [src], #16
+.Lrealigned:
+       sub     tmp1, data1, zeroones
+       orr     tmp2, data1, #REP8_7f
+       sub     tmp3, data2, zeroones
+       orr     tmp4, data2, #REP8_7f
+       bic     has_nul1, tmp1, tmp2
+       bic     has_nul2, tmp3, tmp4
+       subs    limit_wd, limit_wd, #1
+       orr     tmp1, has_nul1, has_nul2
+       ccmp    tmp1, #0, #0, ne        /* NZCV = 0000  */
+       b.eq    .Lloop
+       /* End of critical section -- keep to one 64Byte cache line.  */
+
+       orr     tmp1, has_nul1, has_nul2
+       cbz     tmp1, .Lhit_limit       /* No null in final Qword.  */
+
+       /* We know there's a null in the final Qword.  The easiest thing
+          to do now is work out the length of the string and return
+          MIN (len, limit).  */
+
+       sub     len, src, srcin
+       cbz     has_nul1, .Lnul_in_data2
+#ifdef __AARCH64EB__
+       mov     data2, data1
+#endif
+       sub     len, len, #8
+       mov     has_nul2, has_nul1
+.Lnul_in_data2:
+#ifdef __AARCH64EB__
+       /* For big-endian, carry propagation (if the final byte in the
+          string is 0x01) means we cannot use has_nul directly.  The
+          easiest way to get the correct byte is to byte-swap the data
+          and calculate the syndrome a second time.  */
+       rev     data2, data2
+       sub     tmp1, data2, zeroones
+       orr     tmp2, data2, #REP8_7f
+       bic     has_nul2, tmp1, tmp2
+#endif
+       sub     len, len, #8
+       rev     has_nul2, has_nul2
+       clz     pos, has_nul2
+       add     len, len, pos, lsr #3           /* Bits to bytes.  */
+       cmp     len, limit
+       csel    len, len, limit, ls             /* Return the lower value.  */
+       ret
+
+.Lmisaligned:
+       add     tmp3, limit, tmp1
+       cmp     tmp1, #8
+       neg     tmp1, tmp1
+       ldp     data1, data2, [src], #16
+       add     limit_wd, tmp3, #15
+       lsl     tmp1, tmp1, #3          /* Bytes beyond alignment -> bits.  */
+       mov     tmp2, #~0
+       lsr     limit_wd, limit_wd, #4
+#ifdef __AARCH64EB__
+       /* Big-endian.  Early bytes are at MSB.  */
+       lsl     tmp2, tmp2, tmp1        /* Shift (tmp1 & 63).  */
+#else
+       /* Little-endian.  Early bytes are at LSB.  */
+       lsr     tmp2, tmp2, tmp1        /* Shift (tmp1 & 63).  */
+#endif
+       orr     data1, data1, tmp2
+       orr     data2a, data2, tmp2
+       csinv   data1, data1, xzr, le
+       csel    data2, data2, data2a, le
+       b       .Lrealigned
+       .size   strnlen, . - .Lstart    /* Include pre-padding in size.  */
+
+#endif
This page took 0.052327 seconds and 5 git commands to generate.