2 * Copyright (c) 2010, 2011 Apple, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
28 // int strncmp(const char *s1, const char *s2, size_t n);
30 // Returns zero if the two NUL-terminated strings s1 and s2 are equal up to
31 // n characters. Otherwise, returns the difference between the first two
32 // characters that do not match, interpreted as unsigned integers.
34 #define ESTABLISH_FRAME \
45 // If n < 16, jump straight to the byte-by-byte comparison loop.
48 // Load a character from each string and advance the pointers. If the loaded
49 // characters are unequal or NUL, return their difference.
56 // If the address of the next character from s1 does not have word alignment,
57 // continue with the character-by-character comparison. Otherwise, fall
58 // through into the word-by-word comparison path.
62 // We have not encountered a NUL or a mismatch, and s1 has word alignment.
63 // Establish a frame, since we're going to need additional registers anyway.
67 // Word align s2, and place the remainder in r10. Compute the right- and
68 // left-shifts to extract each word that we will compare to the other source
69 // from the aligned words that we load:
71 // aligned s2 to be loaded on next iteration
74 // +---+---+---+---+ +---+---+---+---+
75 // | 0 | 1 | 2 | 3 | | 4 | 5 | 6 | 7 |
76 // +---+---+---+---+ +---+---+---+---+
77 // ^-----------------^
78 // to be compared on next iteration
84 // Subtract the number of bytes of the initial word load from s2 that will
85 // actually be used from n.
86 sub r2, r2, r6, lsr #3
88 // Load the first aligned word of s2. OR 0x01 into any bytes that preceed the
89 // "true s2", to prevent our check for NUL from generating a false positive.
90 // Then check for NUL, and jump to the byte-by-byte comparison loop after
91 // unwinding the pointers if we enounter one.
93 orr r8, r8, lr, lsr r6
98 bne L_unwindLoopPreload
102 // If n < 4, abort the word compare loop before we load any more data.
104 blo L_nIsLessThanFour
105 // Load the next aligned word of s2 and check if it contains any NUL bytes.
106 // Load the next aligned word of s1, and extract the corresponding bytes from
107 // the two words of s2 loaded in this and the previous iteration of the loop.
108 // Compare these two words.
109 // If no NUL or mismatched words have been encountered, continue the loop.
111 #if defined _ARM_ARCH_6
121 orr r4, r5, r8, lsl r6
124 beq L_wordCompareLoop
126 // Either we have encountered a NUL, or we have found a mismatch between s1
127 // and s2. Unwind the pointers and use a byte-by-byte comparison loop.
133 sub r1, r1, r6, lsr #3
134 add r2, r2, r6, lsr #3
138 // If n-- == 0, we have exhausted the allowed number of comparisons, and need
139 // to return zero without additional loads.
143 // Load a character from each string and advance the pointers. If the loaded
144 // characters are unequal or NUL, return their difference.
149 beq L_byteCompareLoop
152 // Return the difference between the last two characters loaded.