Loading...
arm/string/strcmp.s /dev/null Libc-825.25
--- /dev/null
+++ Libc/Libc-825.25/arm/string/strcmp.s
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2011 Apple, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+.text
+.syntax unified
+.code 32
+.globl _strcmp
+// int strcmp(const char *s1, const char *s2);
+//
+// Returns zero if the two NUL-terminated strings s1 and s2 are equal.
+// Otherwise, returns the difference between the first two
+// characters that do not match, interpreted as unsigned integers.
+
+#define ESTABLISH_FRAME        \
+    push   {r4-r7,lr}         ;\
+    add     r7,     sp, #12   ;\
+    push   {r8}
+#define CLEAR_FRAME            \
+    pop    {r8}               ;\
+    pop    {r4-r7,lr}
+
+.align 3
+.long 0, 0x01010101
+_strcmp:
+//  Load a character from each string and advance the pointers.  If the loaded
+//  characters are unequal or NUL, return their difference.
+0:	ldrb    r2,    [r0],#1
+    ldrb    ip,    [r1],#1
+    cmp     r2,         #1
+    cmphs   r2,         ip
+    bne     L_earlyReturn
+//  If the address of the next character from s1 does not have word alignment,
+//  continue with the character-by-character comparison.  Otherwise, fall
+//  through into the word-by-word comparison path.
+    tst     r0,         #3
+    bne     0b
+
+//  We have not encountered a NUL or a mismatch, and s1 has word alignment.
+//  Establish a frame, since we're going to need additional registers anyway.
+    ESTABLISH_FRAME
+    ldr     lr,    (_strcmp-4)
+
+//  Word align s2, and place the remainder in r8.  Compute the right- and
+//  left-shifts to extract each word that we will compare to the other source
+//  from the aligned words that we load:
+//
+//      aligned s2        to be loaded on next iteration
+//      |   "true" s2     |
+//      v   v             v
+//      +---+---+---+---+ +---+---+---+---+
+//      | 0 | 1 | 2 | 3 | | 4 | 5 | 6 | 7 |
+//      +---+---+---+---+ +---+---+---+---+
+//          ^-----------------^
+//          to be compared on next iteration
+    and     r8,     r1, #3
+    bic     r1,     r1, #3
+    mov     r8,         r8, lsl #3
+    rsb     r5,     r8, #32
+
+//  Load the first aligned word of s2.  OR 0x01 into any bytes that preceed the
+//  "true s2", to prevent our check for NUL from generating a false positive.
+//  Then check for NUL, and jump to the byte-by-byte comparison loop after
+//  unwinding the pointers if we enounter one.
+    ldr     r6,    [r1],#4
+    orr     r6,     r6, lr, lsr r5
+    sub     r2,     r6, lr
+    bic     r2,     r2, r6
+    tst     r2,         lr, lsl #7
+    mov     r4,         r6, lsr r8
+    bne     L_unwindLoopPreload
+
+.align 3
+L_wordCompareLoop:
+    //  Load the next aligned word of s2 and check if it contains any NUL bytes.
+    //  Load the next aligned word of s1, and extract the corresponding bytes from
+    //  the two words of s2 loaded in this and the previous iteration of the loop.
+    //  Compare these two words.
+    //  If no NUL or mismatched words have been encountered, continue the loop.
+    ldr     r6,    [r1],#4
+#if defined _ARM_ARCH_6
+    uqsub8  r2,     lr, r6
+    tst     r2,         r2
+    ldr     ip,    [r0],#4
+#else
+    sub     r2,     r6, lr
+    bic     r2,     r2, r6
+    ldr     ip,    [r0],#4
+    tst     r2,         lr, lsl #7
+#endif
+    orr     r3,     r4, r6, lsl r5
+    cmpeq   ip,         r3
+    mov     r4,         r6, lsr r8
+    beq     L_wordCompareLoop
+
+//  Either we have encountered a NUL, or we have found a mismatch between s1
+//  and s2.  Unwind the pointers and use a byte-by-byte comparison loop.
+    sub     r0,     r0, #4
+    sub     r1,     r1, #4
+L_unwindLoopPreload:
+    sub     r1,     r1, r5, lsr #3
+    CLEAR_FRAME
+
+L_byteCompareLoop:
+//  Load a character from each string and advance the pointers.  If the loaded
+//  characters are unequal or NUL, return their difference.
+    ldrb    r2,    [r0],#1
+    ldrb    ip,    [r1],#1
+    cmp     r2,         #1
+    cmpcs   r2,         ip
+    beq     L_byteCompareLoop
+
+L_earlyReturn:
+//  Return the difference between the last two characters loaded.
+    sub     r0,     r2, ip
+    bx      lr