This is the mail archive of the newlib@sourceware.org mailing list for the newlib project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH, ARM] New strcmp for armv6-m


Hi,

This patch ports the strcmp routine (which is BSD license) from Linaro
Cortex-Strings (https://git.linaro.org/toolchain/cortex-strings.git) to
replace the previous version in newlib.

It happens within the armv6-m Thumb1 wrapper. Both of the big-endian and
little-endian versions of the strcmp are replaced.

The main advantage of this patch is that it can improve the performance of
the strcmp for armv6-m. This solution will also increase the code size. So
it will only be used if __OPTIMIZE_SIZE__ is not defined.

Thanks,
Hale Wang

newlib/ChangeLog:

2014-11-26  Hale Wang  <hale.wang@arm.com>

	* libc/machine/arm/strcmp-armv6m.S: New file.
	* libc/machine/arm/strcmp.S: Add new wrapper.
	* libc/machine/arm/Makefile.am: Add dependencies.
	* libc/machine/arm/Makefile.in: Regenerated.

================================================================
diff --git a/newlib/libc/machine/arm/Makefile.am
b/newlib/libc/machine/arm/Makefile.am
index 6affaf9..dc17690 100644
--- a/newlib/libc/machine/arm/Makefile.am
+++ b/newlib/libc/machine/arm/Makefile.am
@@ -10,19 +10,13 @@ noinst_LIBRARIES = lib.a
 
 if HAVE_THUMB1
 if OPT_SIZE
-STRCMP_SRC=strcmp.S
-STRCMP_OBJ=$(lpfx)strcmp.o
 STRLEN_SRC=strlen.c
 STRLEN_OBJ=$(lpfx)strlen.o
 else
-STRCMP_SRC=
-STRCMP_OBJ=
 STRLEN_SRC=
 STRLEN_OBJ=
 endif
 else
-STRCMP_SRC=strcmp.S
-STRCMP_OBJ=$(lpfx)strcmp.o
 STRLEN_SRC=strlen.c
 STRLEN_OBJ=$(lpfx)strlen.o
 endif
@@ -53,21 +47,21 @@ endif !HAVE_ARMV7M
 endif !HAVE_ARMV7A
 endif !OPT_SIZE
 
-lib_a_SOURCES = setjmp.S access.c $(STRCMP_SRC) strcpy.c \
+lib_a_SOURCES = setjmp.S access.c strcmp.S strcpy.c \
 	        $(MEMCPY_SRC) $(MEMCHR_SRC) $(STRLEN_SRC) \
 		strlen-armv7.S aeabi_memcpy.c aeabi_memcpy-armv7a.S
 
 lib_a_CCASFLAGS=$(AM_CCASFLAGS)
 lib_a_CFLAGS = $(AM_CFLAGS)
-lib_a_LIBADD = $(STRCMP_OBJ) $(STRLEN_OBJ) $(MEMCHR_OBJ) $(MEMCPY_OBJ)
-lib_a_DEPENDENCIES = $(STRCMP_OBJ) $(STRLEN_OBJ) $(MEMCHR_OBJ)
$(MEMCPY_OBJ)
+lib_a_LIBADD = $(STRLEN_OBJ) $(MEMCHR_OBJ) $(MEMCPY_OBJ)
+lib_a_DEPENDENCIES = $(STRLEN_OBJ) $(MEMCHR_OBJ) $(MEMCPY_OBJ)
 
 ACLOCAL_AMFLAGS = -I ../../.. -I ../../../..
 CONFIG_STATUS_DEPENDENCIES = $(newlib_basedir)/configure.host
 
 MEMCPY_DEP=memcpy-armv7a.S memcpy-armv7m.S
 STRCMP_DEP=strcmp-arm-tiny.S strcmp-armv4.S strcmp-armv4t.S strcmp-armv6.S
\
-	strcmp-armv7.S strcmp-armv7m.S
+	strcmp-armv6m.S strcmp-armv7.S strcmp-armv7m.S
 
 $(lpfx)memcpy.o: $(MEMCPY_DEP)
 
diff --git a/newlib/libc/machine/arm/Makefile.in
b/newlib/libc/machine/arm/Makefile.in
index 86562d1..db65405 100644
--- a/newlib/libc/machine/arm/Makefile.in
+++ b/newlib/libc/machine/arm/Makefile.in
@@ -68,27 +68,22 @@ CONFIG_CLEAN_VPATH_FILES =
 LIBRARIES = $(noinst_LIBRARIES)
 ARFLAGS = cru
 lib_a_AR = $(AR) $(ARFLAGS)
-@HAVE_THUMB1_FALSE@am__DEPENDENCIES_1 = $(lpfx)strcmp.o
-@HAVE_THUMB1_TRUE@@OPT_SIZE_TRUE@am__DEPENDENCIES_1 = $(lpfx)strcmp.o
-@HAVE_THUMB1_FALSE@am__DEPENDENCIES_2 = $(lpfx)strlen.o
-@HAVE_THUMB1_TRUE@@OPT_SIZE_TRUE@am__DEPENDENCIES_2 = $(lpfx)strlen.o
-@HAVE_ARMV7_TRUE@am__DEPENDENCIES_3 = $(lpfx)memchr.o
-@HAVE_ARMV7A_FALSE@@HAVE_ARMV7M_TRUE@@OPT_SIZE_FALSE@am__DEPENDENCIES_4 =
$(lpfx)memcpy.o
-@HAVE_ARMV7A_TRUE@@OPT_SIZE_FALSE@am__DEPENDENCIES_4 =  \
+@HAVE_THUMB1_FALSE@am__DEPENDENCIES_1 = $(lpfx)strlen.o
+@HAVE_THUMB1_TRUE@@OPT_SIZE_TRUE@am__DEPENDENCIES_1 = $(lpfx)strlen.o
+@HAVE_ARMV7_TRUE@am__DEPENDENCIES_2 = $(lpfx)memchr.o
+@HAVE_ARMV7A_FALSE@@HAVE_ARMV7M_TRUE@@OPT_SIZE_FALSE@am__DEPENDENCIES_3 =
$(lpfx)memcpy.o
+@HAVE_ARMV7A_TRUE@@OPT_SIZE_FALSE@am__DEPENDENCIES_3 =  \
 @HAVE_ARMV7A_TRUE@@OPT_SIZE_FALSE@	$(lpfx)memcpy.o
-@HAVE_THUMB1_FALSE@am__objects_1 = lib_a-strcmp.$(OBJEXT)
-@HAVE_THUMB1_TRUE@@OPT_SIZE_TRUE@am__objects_1 =  \
-@HAVE_THUMB1_TRUE@@OPT_SIZE_TRUE@	lib_a-strcmp.$(OBJEXT)
-@HAVE_ARMV7A_FALSE@@HAVE_ARMV7M_TRUE@@OPT_SIZE_FALSE@am__objects_2 =
lib_a-memcpy.$(OBJEXT)
-@HAVE_ARMV7A_TRUE@@OPT_SIZE_FALSE@am__objects_2 =  \
+@HAVE_ARMV7A_FALSE@@HAVE_ARMV7M_TRUE@@OPT_SIZE_FALSE@am__objects_1 =
lib_a-memcpy.$(OBJEXT)
+@HAVE_ARMV7A_TRUE@@OPT_SIZE_FALSE@am__objects_1 =  \
 @HAVE_ARMV7A_TRUE@@OPT_SIZE_FALSE@	lib_a-memcpy.$(OBJEXT)
-@HAVE_ARMV7_TRUE@am__objects_3 = lib_a-memchr.$(OBJEXT)
-@HAVE_THUMB1_FALSE@am__objects_4 = lib_a-strlen.$(OBJEXT)
-@HAVE_THUMB1_TRUE@@OPT_SIZE_TRUE@am__objects_4 =  \
+@HAVE_ARMV7_TRUE@am__objects_2 = lib_a-memchr.$(OBJEXT)
+@HAVE_THUMB1_FALSE@am__objects_3 = lib_a-strlen.$(OBJEXT)
+@HAVE_THUMB1_TRUE@@OPT_SIZE_TRUE@am__objects_3 =  \
 @HAVE_THUMB1_TRUE@@OPT_SIZE_TRUE@	lib_a-strlen.$(OBJEXT)
 am_lib_a_OBJECTS = lib_a-setjmp.$(OBJEXT) lib_a-access.$(OBJEXT) \
-	$(am__objects_1) lib_a-strcpy.$(OBJEXT) $(am__objects_2) \
-	$(am__objects_3) $(am__objects_4) lib_a-strlen-armv7.$(OBJEXT) \
+	lib_a-strcmp.$(OBJEXT) lib_a-strcpy.$(OBJEXT) $(am__objects_1) \
+	$(am__objects_2) $(am__objects_3) lib_a-strlen-armv7.$(OBJEXT) \
 	lib_a-aeabi_memcpy.$(OBJEXT) \
 	lib_a-aeabi_memcpy-armv7a.$(OBJEXT)
 lib_a_OBJECTS = $(am_lib_a_OBJECTS)
@@ -148,6 +143,7 @@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
 PACKAGE_NAME = @PACKAGE_NAME@
 PACKAGE_STRING = @PACKAGE_STRING@
 PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
 PACKAGE_VERSION = @PACKAGE_VERSION@
 PATH_SEPARATOR = @PATH_SEPARATOR@
 RANLIB = @RANLIB@
@@ -216,12 +212,6 @@ AUTOMAKE_OPTIONS = cygnus
 INCLUDES = $(NEWLIB_CFLAGS) $(CROSS_CFLAGS) $(TARGET_CFLAGS)
 AM_CCASFLAGS = $(INCLUDES)
 noinst_LIBRARIES = lib.a
-@HAVE_THUMB1_FALSE@STRCMP_SRC = strcmp.S
-@HAVE_THUMB1_TRUE@@OPT_SIZE_FALSE@STRCMP_SRC = 
-@HAVE_THUMB1_TRUE@@OPT_SIZE_TRUE@STRCMP_SRC = strcmp.S
-@HAVE_THUMB1_FALSE@STRCMP_OBJ = $(lpfx)strcmp.o
-@HAVE_THUMB1_TRUE@@OPT_SIZE_FALSE@STRCMP_OBJ = 
-@HAVE_THUMB1_TRUE@@OPT_SIZE_TRUE@STRCMP_OBJ = $(lpfx)strcmp.o
 @HAVE_THUMB1_FALSE@STRLEN_SRC = strlen.c
 @HAVE_THUMB1_TRUE@@OPT_SIZE_FALSE@STRLEN_SRC = 
 @HAVE_THUMB1_TRUE@@OPT_SIZE_TRUE@STRLEN_SRC = strlen.c
@@ -240,19 +230,19 @@ noinst_LIBRARIES = lib.a
 @HAVE_ARMV7A_FALSE@@HAVE_ARMV7M_TRUE@@OPT_SIZE_FALSE@MEMCPY_OBJ =
$(lpfx)memcpy.o
 @HAVE_ARMV7A_TRUE@@OPT_SIZE_FALSE@MEMCPY_OBJ = $(lpfx)memcpy.o
 @OPT_SIZE_TRUE@MEMCPY_OBJ = 
-lib_a_SOURCES = setjmp.S access.c $(STRCMP_SRC) strcpy.c \
+lib_a_SOURCES = setjmp.S access.c strcmp.S strcpy.c \
 	        $(MEMCPY_SRC) $(MEMCHR_SRC) $(STRLEN_SRC) \
 		strlen-armv7.S aeabi_memcpy.c aeabi_memcpy-armv7a.S
 
 lib_a_CCASFLAGS = $(AM_CCASFLAGS)
 lib_a_CFLAGS = $(AM_CFLAGS)
-lib_a_LIBADD = $(STRCMP_OBJ) $(STRLEN_OBJ) $(MEMCHR_OBJ) $(MEMCPY_OBJ)
-lib_a_DEPENDENCIES = $(STRCMP_OBJ) $(STRLEN_OBJ) $(MEMCHR_OBJ)
$(MEMCPY_OBJ)
+lib_a_LIBADD = $(STRLEN_OBJ) $(MEMCHR_OBJ) $(MEMCPY_OBJ)
+lib_a_DEPENDENCIES = $(STRLEN_OBJ) $(MEMCHR_OBJ) $(MEMCPY_OBJ)
 ACLOCAL_AMFLAGS = -I ../../.. -I ../../../..
 CONFIG_STATUS_DEPENDENCIES = $(newlib_basedir)/configure.host
 MEMCPY_DEP = memcpy-armv7a.S memcpy-armv7m.S
 STRCMP_DEP = strcmp-arm-tiny.S strcmp-armv4.S strcmp-armv4t.S
strcmp-armv6.S \
-	strcmp-armv7.S strcmp-armv7m.S
+	strcmp-armv6m.S strcmp-armv7.S strcmp-armv7m.S
 
 all: all-am
 
diff --git a/newlib/libc/machine/arm/strcmp-armv6m.S
b/newlib/libc/machine/arm/strcmp-armv6m.S
new file mode 100644
index 0000000..932841d
--- /dev/null
+++ b/newlib/libc/machine/arm/strcmp-armv6m.S
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2014 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.
+ */
+
+/* Implementation of strcmp for ARMv6m.  This version is only used in
+   ARMv6-M when we want an efficient implementation.  Otherwize if the
+   code size is preferred, strcmp-armv4t.S will be used.  */
+
+	.thumb_func
+	.syntax unified
+	.arch	armv6-m
+
+	.macro DoSub n, label
+	subs	r0, r0, r1
+#ifdef __ARM_BIG_ENDIAN
+	lsrs	r1, r4, \n
+#else
+	lsls	r1, r4, \n
+#endif
+	orrs	r1, r0
+	bne	\label
+	.endm
+
+	.macro Byte_Test n, label
+	lsrs	r0, r2, \n
+	lsrs	r1, r3, \n
+	DoSub	\n, \label
+	.endm
+
+	.text
+def_fn	strcmp
+	.cfi_startproc
+	mov	r2, r0
+	push	{r4, r5, r6, lr}
+	orrs	r2, r1
+	lsls	r2, r2, #30
+	bne	6f
+	ldr	r5, =0x01010101
+	lsls	r6, r5, #7
+1:
+	ldmia	r0!, {r2}
+	ldmia	r1!, {r3}
+	subs	r4, r2, r5
+	bics	r4, r2
+	ands	r4, r6
+	beq	3f
+
+#ifdef __ARM_BIG_ENDIAN
+	Byte_Test #24, 4f
+	Byte_Test #16, 4f
+	Byte_Test #8, 4f
+
+	b       7f
+3:
+	cmp     r2, r3
+	beq     1b
+	cmp     r2, r3
+#else
+	uxtb    r0, r2
+	uxtb    r1, r3
+	DoSub   #24, 2f
+
+	uxth    r0, r2
+	uxth    r1, r3
+	DoSub   #16, 2f
+
+	lsls    r0, r2, #8
+	lsls    r1, r3, #8
+	lsrs    r0, r0, #8
+	lsrs    r1, r1, #8
+	DoSub   #8, 2f
+
+	lsrs    r0, r2, #24
+	lsrs    r1, r3, #24
+	subs    r0, r0, r1
+2:
+	pop     {r4, r5, r6, pc}
+
+3:
+	cmp     r2, r3
+	beq     1b
+	rev     r0, r2
+	rev     r1, r3
+	cmp     r0, r1
+#endif
+
+	bls	5f
+	movs	r0, #1
+4:
+	pop	{r4, r5, r6, pc}
+5:
+	movs	r0, #0
+	mvns	r0, r0
+	pop	{r4, r5, r6, pc}
+6:
+	ldrb	r2, [r0, #0]
+	ldrb	r3, [r1, #0]
+	adds	r0, #1
+	adds	r1, #1
+	cmp	r2, #0
+	beq	7f
+	cmp	r2, r3
+	bne	7f
+	ldrb	r2, [r0, #0]
+	ldrb	r3, [r1, #0]
+	adds	r0, #1
+	adds	r1, #1
+	cmp	r2, #0
+	beq	7f
+	cmp	r2, r3
+	beq	6b
+7:
+	subs	r0, r2, r3
+	pop	{r4, r5, r6, pc}
+	.cfi_endproc
+	.size	strcmp, . - strcmp
diff --git a/newlib/libc/machine/arm/strcmp.S
b/newlib/libc/machine/arm/strcmp.S
index fecfdfd..7b4d7fc 100644
--- a/newlib/libc/machine/arm/strcmp.S
+++ b/newlib/libc/machine/arm/strcmp.S
@@ -65,24 +65,13 @@
 
 # if defined (__thumb__) && !defined (__thumb2__)
 /* Thumb1 only variant.  If size is preferred, use strcmp-armv4t.S.
-   If speed is preferred, the strcmp function in ../../string/strcmp.c
+   If speed is preferred, the strcmp function in strcmp-armv6m.S
    will be used.  */
 
 #  if defined (__OPTIMIZE_SIZE__) || defined (PREFER_SIZE_OVER_SPEED)
 #   include "strcmp-armv4t.S"
 #  else
-    /* Leave this field blank.  So the strcmp() is not defined, and this
will
-       automatically pull in the default C definition of strcmp() from
-       ../../string/strcmp.c.  No need to include this file explicitely.
-       The lib_a-strcmp.o will not be generated, so it won't replace the
-       default lib_a-strcmp.o which is generated by ../../string/strcmp.c.
-       See the commands in configure.in and Makefile.am for more details.
-
-       However, if we need to rewrite this function to be more efficient,
-       we can add the corresponding assembly code into this field and
-       change the commands in configure.in and Makefile.am to allow the
-       corresponding lib_a-strcmp.o to be generated.
-    */
+#   include "strcmp-armv6m.S"
 #  endif
 
 # else
================================================================

Attachment: strcmp-4.patch
Description: Binary data


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]