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]

[ARM] Fixes for arm str* routines


Another couple of bugs have been found in the string routines that I
posted recently.  The first, fixed by Mark Mitchell, concerns the
thumb-2 compilation of strlen (strings shorter than 4 bytes could
sometimes be reported as being longer than 4 bytes).

The second is a case of an unfortunate (l)user.  Anyone unfortunate
enough to have a string that contained 0x80 would find that the routines
treated that as an end-of-string marker, leading to short strings.

Fixed thusly:

2009-03-09  Mark Mitchell  <mark@codesourcery.com>

        * libc/machine/arm/strlen.c (strlen): Fix defect in Thumb-2 mode.

2009-03-12  Richard Earnshaw  <rearnsha@arm.com>

	* libc/machine/arm/strlen.c (strlen): Correctly detect
	end-of-string.
	* libc/machine/arm/strcpy.c (strcpy): Likewise.
	* libc/machine/arm/strcmp.c (strcmp, strcmp_unaligned): Likewise.


diff --git a/newlib/libc/machine/arm/strcmp.c b/newlib/libc/machine/arm/strcmp.c
index f7d39aa..6b33475 100644
--- a/newlib/libc/machine/arm/strcmp.c
+++ b/newlib/libc/machine/arm/strcmp.c
@@ -97,7 +97,7 @@ __attribute__((naked)) strcmp (const char* s1, const char* s2)
       "cmp	ip, r3\n\t"
       "itttt	eq\n\t"
       /* check for any zero bytes in first word */
-      "eoreq	r2, r2, ip\n\t"
+      "biceq	r2, r2, ip\n\t"
       "tsteq	r2, "magic2(r4)"\n\t"
       "ldreq	ip, [r0], #4\n\t"
       "ldreq	r3, [r1], #4\n\t"
@@ -171,9 +171,9 @@ strcmp_unaligned(const char* s1, const char* s2)
 	  w2 RSHIFT= shift;						\
 	  break;							\
 	}								\
-      if (__builtin_expect(((w1 - b1) ^ w1) & (b1 << 7), 0))		\
+      if (__builtin_expect(((w1 - b1) & ~w1) & (b1 << 7), 0))		\
 	{								\
-	  if ((((w1 - b1) ^ w1) & (b1 << 7)) & mask)			\
+	  if ((((w1 - b1) & ~w1) & (b1 << 7)) & mask)			\
 	    w2 RSHIFT= shift;						\
 	  else								\
 	    {								\
@@ -284,7 +284,7 @@ strcmp_unaligned(const char* s1, const char* s2)
       "bic	t1, w1, #"MSB"\n\t"
       "cmp	t1, w2, "SHFT2LSB" #8\n\t"
       "sub	r3, w1, b1\n\t"
-      "eor	r3, r3, w1\n\t"
+      "bic	r3, r3, w1\n\t"
       "bne	4f\n\t"
       "ands	r3, r3, b1, lsl #7\n\t"
       "it	eq\n\t"
@@ -320,7 +320,7 @@ strcmp_unaligned(const char* s1, const char* s2)
       SHFT2MSB"	t1, w1, #16\n\t"
       "sub	r3, w1, b1\n\t"
       SHFT2LSB"	t1, t1, #16\n\t"
-      "eor	r3, r3, w1\n\t"
+      "bic	r3, r3, w1\n\t"
       "cmp	t1, w2, "SHFT2LSB" #16\n\t"
       "bne	4f\n\t"
       "ands	r3, r3, b1, lsl #7\n\t"
@@ -356,7 +356,7 @@ strcmp_unaligned(const char* s1, const char* s2)
       "and	t1, w1, #"LSB"\n\t"
       "cmp	t1, w2, "SHFT2LSB" #24\n\t"
       "sub	r3, w1, b1\n\t"
-      "eor	r3, r3, w1\n\t"
+      "bic	r3, r3, w1\n\t"
       "bne	4f\n\t"
       "ands	r3, r3, b1, lsl #7\n\t"
       "it	eq\n\t"
diff --git a/newlib/libc/machine/arm/strcpy.c b/newlib/libc/machine/arm/strcpy.c
index a655a11..b2e3f51 100644
--- a/newlib/libc/machine/arm/strcpy.c
+++ b/newlib/libc/machine/arm/strcpy.c
@@ -64,7 +64,7 @@ strcpy (char* dst, const char* src)
        "ldr	r3, [r1], #4\n\t"
        "beq	2f\n\t"
        "sub	r2, r3, "magic1(r5)"\n\t"
-       "eors	r2, r2, r3\n\t"
+       "bics	r2, r2, r3\n\t"
        "tst	r2, "magic2(r5)"\n\t"
        "itt	eq\n\t"
        "streq	r3, [ip], #4\n\t"
@@ -78,12 +78,12 @@ strcpy (char* dst, const char* src)
        "optpld	r1, #8\n\t"
        "ldr	r4, [r1], #4\n\t"
        "sub	r2, r3, "magic1(r5)"\n\t"
-       "eors	r2, r2, r3\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"
-       "eors	r2, r2, r4\n\t"
+       "bics	r2, r2, r4\n\t"
        "tst	r2, "magic2(r5)"\n\t"
        "itt	eq\n\t"
        "ldreq	r3, [r1], #4\n\t"
diff --git a/newlib/libc/machine/arm/strlen.c b/newlib/libc/machine/arm/strlen.c
index 6442c77..f31f721 100644
--- a/newlib/libc/machine/arm/strlen.c
+++ b/newlib/libc/machine/arm/strlen.c
@@ -79,16 +79,17 @@ strlen (const char* str)
        "add	ip, len, #4\n\t"
        "mov	ip, ip, asl #3\n\t"
        "mvn	r2, #0\n\t"
-       "it	ne\n\t"
        /* ... are masked out */
 #ifdef __thumb__
+       "itt	ne\n\t"
 # ifdef __ARMEB__
        "lslne	r2, ip\n\t"
 # else
        "lsrne	r2, ip\n\t"
 # endif
-       "orr	data, data, r2\n\t"
+       "orrne	data, data, r2\n\t"
 #else
+       "it	ne\n\t"
 # ifdef __ARMEB__
        "orrne	data, data, r2, lsl ip\n\t"
 # else
@@ -104,13 +105,15 @@ strlen (const char* str)
 #endif
        "orr	ip, ip, ip, lsl #16\n"
 
-	/* This is the main loop.  We subtract one from each byte in the
-	   word: the sign bit changes iff the byte was zero.  */
+	/* This is the main loop.  We subtract one from each byte in
+	   the word: the sign bit changes iff the byte was zero or
+	   0x80 -- we eliminate the latter case by anding the result
+	   with the 1-s complement of the data.  */
        "1:\n\t"
        /* test (data - 0x01010101)  */
        "sub	r2, data, ip\n\t"
-       /* ... ^ data */
-       "eor	r2, r2, data\n\t"
+       /* ... & ~data */
+       "bic	r2, r2, data\n\t"
        /* ... & 0x80808080 == 0? */
        "ands	r2, r2, ip, lsl #7\n\t"
 #ifdef _ISA_ARM_7
@@ -124,8 +127,8 @@ strlen (const char* str)
        /*  test (data - 0x01010101)  */
        "ittt	eq\n\t"
        "subeq	r2, data, ip\n\t"
-       /* ... ^ data */
-       "eoreq	r2, r2, data\n\t"
+       /* ... & ~data */
+       "biceq	r2, r2, data\n\t"
        /* ... & 0x80808080 == 0? */
        "andeqs	r2, r2, ip, lsl #7\n\t"
 #endif

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