]> git.saurik.com Git - apple/libc.git/blame - arm/string/strncmp.s
Libc-825.24.tar.gz
[apple/libc.git] / arm / string / strncmp.s
CommitLineData
ad3c9f2a
A
1/*
2 * Copyright (c) 2010, 2011 Apple, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
11 * file.
12 *
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24.text
25.syntax unified
26.code 32
27.globl _strncmp
28// int strncmp(const char *s1, const char *s2, size_t n);
29//
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.
33
34#define ESTABLISH_FRAME \
35 push {r4-r7,lr} ;\
36 add r7, sp, #12 ;\
37 push {r8,r10}
38#define CLEAR_FRAME \
39 pop {r8,r10} ;\
40 pop {r4-r7,lr}
41
42.align 3
43.long 0, 0x01010101
44_strncmp:
45// If n < 16, jump straight to the byte-by-byte comparison loop.
46 cmp r2, #16
47 blo L_byteCompareLoop
48// Load a character from each string and advance the pointers. If the loaded
49// characters are unequal or NUL, return their difference.
500: ldrb r3, [r0],#1
51 ldrb ip, [r1],#1
52 sub r2, #1
53 cmp r3, #1
54 cmphs r3, ip
55 bne L_earlyReturn
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.
59 tst r0, #3
60 bne 0b
61
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.
64 ESTABLISH_FRAME
65 ldr lr, (_strncmp-4)
66
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:
70//
71// aligned s2 to be loaded on next iteration
72// | "true" s2 |
73// v v v
74// +---+---+---+---+ +---+---+---+---+
75// | 0 | 1 | 2 | 3 | | 4 | 5 | 6 | 7 |
76// +---+---+---+---+ +---+---+---+---+
77// ^-----------------^
78// to be compared on next iteration
79 and r10, r1, #3
80 bic r1, r1, #3
81 mov r10, r10, lsl #3
82 rsb r6, r10,#32
83
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
87
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.
92 ldr r8, [r1],#4
93 orr r8, r8, lr, lsr r6
94 sub r3, r8, lr
95 bic r3, r3, r8
96 tst r3, lr, lsl #7
97 mov r5, r8, lsr r10
98 bne L_unwindLoopPreload
99
100.align 3
101L_wordCompareLoop:
102// If n < 4, abort the word compare loop before we load any more data.
103 subs r2, r2, #4
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.
110 ldr r8, [r1],#4
111#if defined _ARM_ARCH_6
112 uqsub8 r3, lr, r8
113 tst r3, r3
114 ldr ip, [r0],#4
115#else
116 sub r3, r8, lr
117 bic r3, r3, r8
118 ldr ip, [r0],#4
119 tst r3, lr, lsl #7
120#endif
121 orr r4, r5, r8, lsl r6
122 cmpeq ip, r4
123 mov r5, r8, lsr r10
124 beq L_wordCompareLoop
125
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.
128 sub r0, r0, #4
129 sub r1, r1, #4
130L_nIsLessThanFour:
131 add r2, r2, #4
132L_unwindLoopPreload:
133 sub r1, r1, r6, lsr #3
134 add r2, r2, r6, lsr #3
135 CLEAR_FRAME
136
137L_byteCompareLoop:
138// If n-- == 0, we have exhausted the allowed number of comparisons, and need
139// to return zero without additional loads.
140 subs r2, r2, #1
141 movlo r0, #0
142 bxlo lr
143// Load a character from each string and advance the pointers. If the loaded
144// characters are unequal or NUL, return their difference.
145 ldrb r3, [r0],#1
146 ldrb ip, [r1],#1
147 cmp r3, #1
148 cmpcs r3, ip
149 beq L_byteCompareLoop
150
151L_earlyReturn:
152// Return the difference between the last two characters loaded.
153 sub r0, r3, ip
154 bx lr