summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--newlib/ChangeLog4
-rw-r--r--newlib/libc/machine/arm/strcmp.c21
2 files changed, 24 insertions, 1 deletions
diff --git a/newlib/ChangeLog b/newlib/ChangeLog
index 0731a75d4..846d79875 100644
--- a/newlib/ChangeLog
+++ b/newlib/ChangeLog
@@ -1,3 +1,7 @@
+2009-03-23 Richard Earnshaw <rearnsha@arm.com>
+
+ * libc/machine/arm/strcmp.c (strcmp): Treat char as unsigned.
+
2009-03-23 Corinna Vinschen <corinna@vinschen.de>
* libc/locale/locale.c (loadlocale): Fix typo in language and
diff --git a/newlib/libc/machine/arm/strcmp.c b/newlib/libc/machine/arm/strcmp.c
index 6b3347598..d34bae094 100644
--- a/newlib/libc/machine/arm/strcmp.c
+++ b/newlib/libc/machine/arm/strcmp.c
@@ -112,7 +112,26 @@ __attribute__((naked)) strcmp (const char* s1, const char* s2)
"it eq\n\t"
SHFT2LSB"eq r3, r3, #8\n\t"
"beq 2b\n\t"
- "sub r0, r0, r3, "SHFT2MSB" #24\n\t"
+ /* On a big-endian machine, r0 contains the desired byte in bits
+ 0-7; on a little-endian machine they are in bits 24-31. In
+ both cases the other bits in r0 are all zero. For r3 the
+ interesting byte is at the other end of the word, but the
+ other bits are not necessarily zero. We need a signed result
+ representing the differnece in the unsigned bytes, so for the
+ little-endian case we can't just shift the interesting bits
+ up. */
+#ifdef __ARMEB__
+ "sub r0, r0, r3, lsr #24\n\t"
+#else
+ "and r3, r3, #255\n\t"
+#ifdef __thumb2__
+ /* No RSB instruction in Thumb2 */
+ "lsr r0, r0, #24\n\t"
+ "sub r0, r0, r3\n\t"
+#else
+ "rsb r0, r3, r0, lsr #24\n\t"
+#endif
+#endif
#ifndef __thumb2__
"ldr r4, [sp], #4\n\t"
#endif