blob: 232df75b68566bc5faa30ecb5bf930ecb52ae551 [file] [log] [blame]
Christopher Ferris31dea252013-03-08 16:50:31 -08001/*
2 * Copyright (c) 2013 ARM Ltd
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. The name of the company may not be used to endorse or promote
14 * products derived from this software without specific prior written
15 * permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
22 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <machine/cpu-features.h>
30#include <machine/asm.h>
31
32#ifdef __ARMEB__
33#define S2LOMEM lsl
34#define S2LOMEMEQ lsleq
35#define S2HIMEM lsr
36#define MSB 0x000000ff
37#define LSB 0xff000000
38#define BYTE0_OFFSET 24
39#define BYTE1_OFFSET 16
40#define BYTE2_OFFSET 8
41#define BYTE3_OFFSET 0
42#else /* not __ARMEB__ */
43#define S2LOMEM lsr
44#define S2LOMEMEQ lsreq
45#define S2HIMEM lsl
46#define BYTE0_OFFSET 0
47#define BYTE1_OFFSET 8
48#define BYTE2_OFFSET 16
49#define BYTE3_OFFSET 24
50#define MSB 0xff000000
51#define LSB 0x000000ff
52#endif /* not __ARMEB__ */
53
54.syntax unified
55
56#if defined (__thumb__)
57 .thumb
58 .thumb_func
59#endif
60
61ENTRY(strcmp)
62 /* Use LDRD whenever possible. */
63
64/* The main thing to look out for when comparing large blocks is that
65 the loads do not cross a page boundary when loading past the index
66 of the byte with the first difference or the first string-terminator.
67
68 For example, if the strings are identical and the string-terminator
69 is at index k, byte by byte comparison will not load beyond address
70 s1+k and s2+k; word by word comparison may load up to 3 bytes beyond
71 k; double word - up to 7 bytes. If the load of these bytes crosses
72 a page boundary, it might cause a memory fault (if the page is not mapped)
73 that would not have happened in byte by byte comparison.
74
75 If an address is (double) word aligned, then a load of a (double) word
76 from that address will not cross a page boundary.
77 Therefore, the algorithm below considers word and double-word alignment
78 of strings separately. */
79
80/* High-level description of the algorithm.
81
82 * The fast path: if both strings are double-word aligned,
83 use LDRD to load two words from each string in every loop iteration.
84 * If the strings have the same offset from a word boundary,
85 use LDRB to load and compare byte by byte until
86 the first string is aligned to a word boundary (at most 3 bytes).
87 This is optimized for quick return on short unaligned strings.
88 * If the strings have the same offset from a double-word boundary,
89 use LDRD to load two words from each string in every loop iteration, as in the fast path.
90 * If the strings do not have the same offset from a double-word boundary,
91 load a word from the second string before the loop to initialize the queue.
92 Use LDRD to load two words from every string in every loop iteration.
93 Inside the loop, load the second word from the second string only after comparing
94 the first word, using the queued value, to guarantee safety across page boundaries.
95 * If the strings do not have the same offset from a word boundary,
96 use LDR and a shift queue. Order of loads and comparisons matters,
97 similarly to the previous case.
98
99 * Use UADD8 and SEL to compare words, and use REV and CLZ to compute the return value.
100 * The only difference between ARM and Thumb modes is the use of CBZ instruction.
101 * The only difference between big and little endian is the use of REV in little endian
102 to compute the return value, instead of MOV.
103*/
104
105 .macro m_cbz reg label
106#ifdef __thumb2__
107 cbz \reg, \label
108#else /* not defined __thumb2__ */
109 cmp \reg, #0
110 beq \label
111#endif /* not defined __thumb2__ */
112 .endm /* m_cbz */
113
114 .macro m_cbnz reg label
115#ifdef __thumb2__
116 cbnz \reg, \label
117#else /* not defined __thumb2__ */
118 cmp \reg, #0
119 bne \label
120#endif /* not defined __thumb2__ */
121 .endm /* m_cbnz */
122
123 .macro init
124 /* Macro to save temporary registers and prepare magic values. */
125 subs sp, sp, #16
Christopher Ferrisbd7fe1d2013-08-20 11:20:48 -0700126 .cfi_def_cfa_offset 16
Christopher Ferris31dea252013-03-08 16:50:31 -0800127 strd r4, r5, [sp, #8]
Christopher Ferrisbd7fe1d2013-08-20 11:20:48 -0700128 .cfi_rel_offset r4, 0
129 .cfi_rel_offset r5, 4
Christopher Ferris31dea252013-03-08 16:50:31 -0800130 strd r6, r7, [sp]
Christopher Ferrisbd7fe1d2013-08-20 11:20:48 -0700131 .cfi_rel_offset r6, 8
132 .cfi_rel_offset r7, 12
Christopher Ferris31dea252013-03-08 16:50:31 -0800133 mvn r6, #0 /* all F */
134 mov r7, #0 /* all 0 */
135 .endm /* init */
136
137 .macro magic_compare_and_branch w1 w2 label
138 /* Macro to compare registers w1 and w2 and conditionally branch to label. */
139 cmp \w1, \w2 /* Are w1 and w2 the same? */
140 magic_find_zero_bytes \w1
141 it eq
142 cmpeq ip, #0 /* Is there a zero byte in w1? */
143 bne \label
144 .endm /* magic_compare_and_branch */
145
146 .macro magic_find_zero_bytes w1
147 /* Macro to find all-zero bytes in w1, result is in ip. */
148#if (defined (__ARM_FEATURE_DSP))
149 uadd8 ip, \w1, r6
150 sel ip, r7, r6
151#else /* not defined (__ARM_FEATURE_DSP) */
152 /* __ARM_FEATURE_DSP is not defined for some Cortex-M processors.
153 Coincidently, these processors only have Thumb-2 mode, where we can use the
154 the (large) magic constant available directly as an immediate in instructions.
155 Note that we cannot use the magic constant in ARM mode, where we need
156 to create the constant in a register. */
157 sub ip, \w1, #0x01010101
158 bic ip, ip, \w1
159 and ip, ip, #0x80808080
160#endif /* not defined (__ARM_FEATURE_DSP) */
161 .endm /* magic_find_zero_bytes */
162
163 .macro setup_return w1 w2
164#ifdef __ARMEB__
165 mov r1, \w1
166 mov r2, \w2
167#else /* not __ARMEB__ */
168 rev r1, \w1
169 rev r2, \w2
170#endif /* not __ARMEB__ */
171 .endm /* setup_return */
172
Christopher Ferrisbd7fe1d2013-08-20 11:20:48 -0700173 .cfi_startproc
Christopher Ferris31dea252013-03-08 16:50:31 -0800174 pld [r0, #0]
175 pld [r1, #0]
176
177 /* Are both strings double-word aligned? */
178 orr ip, r0, r1
179 tst ip, #7
Christopher Ferrisa57c9c02013-08-21 09:41:12 -0700180 bne .L_do_align
Christopher Ferris31dea252013-03-08 16:50:31 -0800181
182 /* Fast path. */
Christopher Ferrisa57c9c02013-08-21 09:41:12 -0700183 .save {r4-r7}
Christopher Ferris31dea252013-03-08 16:50:31 -0800184 init
185
Christopher Ferrisa57c9c02013-08-21 09:41:12 -0700186.L_doubleword_aligned:
Christopher Ferris31dea252013-03-08 16:50:31 -0800187
188 /* Get here when the strings to compare are double-word aligned. */
189 /* Compare two words in every iteration. */
190 .p2align 2
1912:
192 pld [r0, #16]
193 pld [r1, #16]
194
195 /* Load the next double-word from each string. */
196 ldrd r2, r3, [r0], #8
197 ldrd r4, r5, [r1], #8
198
Christopher Ferrisa57c9c02013-08-21 09:41:12 -0700199 magic_compare_and_branch w1=r2, w2=r4, label=.L_return_24
200 magic_compare_and_branch w1=r3, w2=r5, label=.L_return_35
Christopher Ferris31dea252013-03-08 16:50:31 -0800201 b 2b
202
Christopher Ferrisa57c9c02013-08-21 09:41:12 -0700203.L_do_align:
Christopher Ferris31dea252013-03-08 16:50:31 -0800204 /* Is the first string word-aligned? */
205 ands ip, r0, #3
Christopher Ferrisa57c9c02013-08-21 09:41:12 -0700206 beq .L_word_aligned_r0
Christopher Ferris31dea252013-03-08 16:50:31 -0800207
208 /* Fast compare byte by byte until the first string is word-aligned. */
209 /* The offset of r0 from a word boundary is in ip. Thus, the number of bytes
210 to read until the next word boundary is 4-ip. */
211 bic r0, r0, #3
212 ldr r2, [r0], #4
213 lsls ip, ip, #31
Christopher Ferrisa57c9c02013-08-21 09:41:12 -0700214 beq .L_byte2
215 bcs .L_byte3
Christopher Ferris31dea252013-03-08 16:50:31 -0800216
Christopher Ferrisa57c9c02013-08-21 09:41:12 -0700217.L_byte1:
Christopher Ferris31dea252013-03-08 16:50:31 -0800218 ldrb ip, [r1], #1
219 uxtb r3, r2, ror #BYTE1_OFFSET
220 subs ip, r3, ip
Christopher Ferrisa57c9c02013-08-21 09:41:12 -0700221 bne .L_fast_return
222 m_cbz reg=r3, label=.L_fast_return
Christopher Ferris31dea252013-03-08 16:50:31 -0800223
Christopher Ferrisa57c9c02013-08-21 09:41:12 -0700224.L_byte2:
Christopher Ferris31dea252013-03-08 16:50:31 -0800225 ldrb ip, [r1], #1
226 uxtb r3, r2, ror #BYTE2_OFFSET
227 subs ip, r3, ip
Christopher Ferrisa57c9c02013-08-21 09:41:12 -0700228 bne .L_fast_return
229 m_cbz reg=r3, label=.L_fast_return
Christopher Ferris31dea252013-03-08 16:50:31 -0800230
Christopher Ferrisa57c9c02013-08-21 09:41:12 -0700231.L_byte3:
Christopher Ferris31dea252013-03-08 16:50:31 -0800232 ldrb ip, [r1], #1
233 uxtb r3, r2, ror #BYTE3_OFFSET
234 subs ip, r3, ip
Christopher Ferrisa57c9c02013-08-21 09:41:12 -0700235 bne .L_fast_return
236 m_cbnz reg=r3, label=.L_word_aligned_r0
Christopher Ferris31dea252013-03-08 16:50:31 -0800237
Christopher Ferrisa57c9c02013-08-21 09:41:12 -0700238.L_fast_return:
Christopher Ferris31dea252013-03-08 16:50:31 -0800239 mov r0, ip
240 bx lr
241
Christopher Ferrisa57c9c02013-08-21 09:41:12 -0700242.L_word_aligned_r0:
Christopher Ferris31dea252013-03-08 16:50:31 -0800243 init
244 /* The first string is word-aligned. */
245 /* Is the second string word-aligned? */
246 ands ip, r1, #3
Christopher Ferrisa57c9c02013-08-21 09:41:12 -0700247 bne .L_strcmp_unaligned
Christopher Ferris31dea252013-03-08 16:50:31 -0800248
Christopher Ferrisa57c9c02013-08-21 09:41:12 -0700249.L_word_aligned:
Christopher Ferris31dea252013-03-08 16:50:31 -0800250 /* The strings are word-aligned. */
251 /* Is the first string double-word aligned? */
252 tst r0, #4
Christopher Ferrisa57c9c02013-08-21 09:41:12 -0700253 beq .L_doubleword_aligned_r0
Christopher Ferris31dea252013-03-08 16:50:31 -0800254
255 /* If r0 is not double-word aligned yet, align it by loading
256 and comparing the next word from each string. */
257 ldr r2, [r0], #4
258 ldr r4, [r1], #4
Christopher Ferrisa57c9c02013-08-21 09:41:12 -0700259 magic_compare_and_branch w1=r2 w2=r4 label=.L_return_24
Christopher Ferris31dea252013-03-08 16:50:31 -0800260
Christopher Ferrisa57c9c02013-08-21 09:41:12 -0700261.L_doubleword_aligned_r0:
Christopher Ferris31dea252013-03-08 16:50:31 -0800262 /* Get here when r0 is double-word aligned. */
263 /* Is r1 doubleword_aligned? */
264 tst r1, #4
Christopher Ferrisa57c9c02013-08-21 09:41:12 -0700265 beq .L_doubleword_aligned
Christopher Ferris31dea252013-03-08 16:50:31 -0800266
267 /* Get here when the strings to compare are word-aligned,
268 r0 is double-word aligned, but r1 is not double-word aligned. */
269
270 /* Initialize the queue. */
271 ldr r5, [r1], #4
272
273 /* Compare two words in every iteration. */
274 .p2align 2
2753:
276 pld [r0, #16]
277 pld [r1, #16]
278
279 /* Load the next double-word from each string and compare. */
280 ldrd r2, r3, [r0], #8
Christopher Ferrisa57c9c02013-08-21 09:41:12 -0700281 magic_compare_and_branch w1=r2 w2=r5 label=.L_return_25
Christopher Ferris31dea252013-03-08 16:50:31 -0800282 ldrd r4, r5, [r1], #8
Christopher Ferrisa57c9c02013-08-21 09:41:12 -0700283 magic_compare_and_branch w1=r3 w2=r4 label=.L_return_34
Christopher Ferris31dea252013-03-08 16:50:31 -0800284 b 3b
285
286 .macro miscmp_word offsetlo offsethi
287 /* Macro to compare misaligned strings. */
288 /* r0, r1 are word-aligned, and at least one of the strings
289 is not double-word aligned. */
290 /* Compare one word in every loop iteration. */
291 /* OFFSETLO is the original bit-offset of r1 from a word-boundary,
292 OFFSETHI is 32 - OFFSETLO (i.e., offset from the next word). */
293
294 /* Initialize the shift queue. */
295 ldr r5, [r1], #4
296
297 /* Compare one word from each string in every loop iteration. */
298 .p2align 2
2997:
300 ldr r3, [r0], #4
301 S2LOMEM r5, r5, #\offsetlo
302 magic_find_zero_bytes w1=r3
303 cmp r7, ip, S2HIMEM #\offsetlo
304 and r2, r3, r6, S2LOMEM #\offsetlo
305 it eq
306 cmpeq r2, r5
Christopher Ferrisa57c9c02013-08-21 09:41:12 -0700307 bne .L_return_25
Christopher Ferris31dea252013-03-08 16:50:31 -0800308 ldr r5, [r1], #4
309 cmp ip, #0
310 eor r3, r2, r3
311 S2HIMEM r2, r5, #\offsethi
312 it eq
313 cmpeq r3, r2
Christopher Ferrisa57c9c02013-08-21 09:41:12 -0700314 bne .L_return_32
Christopher Ferris31dea252013-03-08 16:50:31 -0800315 b 7b
316 .endm /* miscmp_word */
317
Christopher Ferrisa57c9c02013-08-21 09:41:12 -0700318.L_return_32:
Christopher Ferris31dea252013-03-08 16:50:31 -0800319 setup_return w1=r3, w2=r2
Christopher Ferrisa57c9c02013-08-21 09:41:12 -0700320 b .L_do_return
321.L_return_34:
Christopher Ferris31dea252013-03-08 16:50:31 -0800322 setup_return w1=r3, w2=r4
Christopher Ferrisa57c9c02013-08-21 09:41:12 -0700323 b .L_do_return
324.L_return_25:
Christopher Ferris31dea252013-03-08 16:50:31 -0800325 setup_return w1=r2, w2=r5
Christopher Ferrisa57c9c02013-08-21 09:41:12 -0700326 b .L_do_return
327.L_return_35:
Christopher Ferris31dea252013-03-08 16:50:31 -0800328 setup_return w1=r3, w2=r5
Christopher Ferrisa57c9c02013-08-21 09:41:12 -0700329 b .L_do_return
330.L_return_24:
Christopher Ferris31dea252013-03-08 16:50:31 -0800331 setup_return w1=r2, w2=r4
332
Christopher Ferrisa57c9c02013-08-21 09:41:12 -0700333.L_do_return:
Christopher Ferris31dea252013-03-08 16:50:31 -0800334
335#ifdef __ARMEB__
336 mov r0, ip
337#else /* not __ARMEB__ */
338 rev r0, ip
339#endif /* not __ARMEB__ */
340
341 /* Restore temporaries early, before computing the return value. */
342 ldrd r6, r7, [sp]
343 ldrd r4, r5, [sp, #8]
344 adds sp, sp, #16
Christopher Ferrisbd7fe1d2013-08-20 11:20:48 -0700345 .cfi_def_cfa_offset 0
346 .cfi_restore r4
347 .cfi_restore r5
348 .cfi_restore r6
349 .cfi_restore r7
Christopher Ferris31dea252013-03-08 16:50:31 -0800350
351 /* There is a zero or a different byte between r1 and r2. */
352 /* r0 contains a mask of all-zero bytes in r1. */
353 /* Using r0 and not ip here because cbz requires low register. */
Christopher Ferrisa57c9c02013-08-21 09:41:12 -0700354 m_cbz reg=r0, label=.L_compute_return_value
Christopher Ferris31dea252013-03-08 16:50:31 -0800355 clz r0, r0
356 /* r0 contains the number of bits on the left of the first all-zero byte in r1. */
357 rsb r0, r0, #24
358 /* Here, r0 contains the number of bits on the right of the first all-zero byte in r1. */
359 lsr r1, r1, r0
360 lsr r2, r2, r0
361
Christopher Ferrisa57c9c02013-08-21 09:41:12 -0700362.L_compute_return_value:
Christopher Ferris31dea252013-03-08 16:50:31 -0800363 movs r0, #1
364 cmp r1, r2
365 /* The return value is computed as follows.
366 If r1>r2 then (C==1 and Z==0) and LS doesn't hold and r0 is #1 at return.
367 If r1<r2 then (C==0 and Z==0) and we execute SBC with carry_in=0,
368 which means r0:=r0-r0-1 and r0 is #-1 at return.
369 If r1=r2 then (C==1 and Z==1) and we execute SBC with carry_in=1,
370 which means r0:=r0-r0 and r0 is #0 at return.
371 (C==0 and Z==1) cannot happen because the carry bit is "not borrow". */
372 it ls
373 sbcls r0, r0, r0
374 bx lr
375
376 /* The code from the previous version of strcmp.S handles all of the
377 * cases where the first string and seconds string cannot both be
378 * aligned to a word boundary faster than the new algorithm. See
379 * bionic/libc/arch-arm/cortex-a15/bionic/strcmp.S for the unedited
380 * version of the code.
381 */
Christopher Ferrisa57c9c02013-08-21 09:41:12 -0700382.L_strcmp_unaligned:
Christopher Ferris31dea252013-03-08 16:50:31 -0800383 wp1 .req r0
384 wp2 .req r1
385 b1 .req r2
386 w1 .req r4
387 w2 .req r5
388 t1 .req ip
389 @ r3 is scratch
390
3912:
392 mov b1, #1
393 orr b1, b1, b1, lsl #8
394 orr b1, b1, b1, lsl #16
395
396 and t1, wp2, #3
397 bic wp2, wp2, #3
398 ldr w1, [wp1], #4
399 ldr w2, [wp2], #4
400 cmp t1, #2
401 beq 2f
402 bhi 3f
403
404 /* Critical inner Loop: Block with 3 bytes initial overlap */
405 .p2align 2
4061:
407 bic t1, w1, #MSB
408 cmp t1, w2, S2LOMEM #8
409 sub r3, w1, b1
410 bic r3, r3, w1
411 bne 4f
412 ands r3, r3, b1, lsl #7
413 it eq
414 ldreq w2, [wp2], #4
415 bne 5f
416 eor t1, t1, w1
417 cmp t1, w2, S2HIMEM #24
418 bne 6f
419 ldr w1, [wp1], #4
420 b 1b
4214:
422 S2LOMEM w2, w2, #8
423 b 8f
424
4255:
426#ifdef __ARMEB__
427 /* The syndrome value may contain false ones if the string ends
428 * with the bytes 0x01 0x00
429 */
430 tst w1, #0xff000000
431 itt ne
432 tstne w1, #0x00ff0000
433 tstne w1, #0x0000ff00
434 beq 7f
435#else
436 bics r3, r3, #0xff000000
437 bne 7f
438#endif
439 ldrb w2, [wp2]
440 S2LOMEM t1, w1, #24
441#ifdef __ARMEB__
442 lsl w2, w2, #24
443#endif
444 b 8f
445
4466:
447 S2LOMEM t1, w1, #24
448 and w2, w2, #LSB
449 b 8f
450
451 /* Critical inner Loop: Block with 2 bytes initial overlap */
452 .p2align 2
4532:
454 S2HIMEM t1, w1, #16
455 sub r3, w1, b1
456 S2LOMEM t1, t1, #16
457 bic r3, r3, w1
458 cmp t1, w2, S2LOMEM #16
459 bne 4f
460 ands r3, r3, b1, lsl #7
461 it eq
462 ldreq w2, [wp2], #4
463 bne 5f
464 eor t1, t1, w1
465 cmp t1, w2, S2HIMEM #16
466 bne 6f
467 ldr w1, [wp1], #4
468 b 2b
469
4705:
471#ifdef __ARMEB__
472 /* The syndrome value may contain false ones if the string ends
473 * with the bytes 0x01 0x00
474 */
475 tst w1, #0xff000000
476 it ne
477 tstne w1, #0x00ff0000
478 beq 7f
479#else
480 lsls r3, r3, #16
481 bne 7f
482#endif
483 ldrh w2, [wp2]
484 S2LOMEM t1, w1, #16
485#ifdef __ARMEB__
486 lsl w2, w2, #16
487#endif
488 b 8f
489
4906:
491 S2HIMEM w2, w2, #16
492 S2LOMEM t1, w1, #16
4934:
494 S2LOMEM w2, w2, #16
495 b 8f
496
497 /* Critical inner Loop: Block with 1 byte initial overlap */
498 .p2align 2
4993:
500 and t1, w1, #LSB
501 cmp t1, w2, S2LOMEM #24
502 sub r3, w1, b1
503 bic r3, r3, w1
504 bne 4f
505 ands r3, r3, b1, lsl #7
506 it eq
507 ldreq w2, [wp2], #4
508 bne 5f
509 eor t1, t1, w1
510 cmp t1, w2, S2HIMEM #8
511 bne 6f
512 ldr w1, [wp1], #4
513 b 3b
5144:
515 S2LOMEM w2, w2, #24
516 b 8f
5175:
518 /* The syndrome value may contain false ones if the string ends
519 * with the bytes 0x01 0x00
520 */
521 tst w1, #LSB
522 beq 7f
523 ldr w2, [wp2], #4
5246:
525 S2LOMEM t1, w1, #8
526 bic w2, w2, #MSB
527 b 8f
5287:
529 mov r0, #0
530
531 /* Restore registers and stack. */
532 ldrd r6, r7, [sp]
533 ldrd r4, r5, [sp, #8]
534 adds sp, sp, #16
Christopher Ferrisbd7fe1d2013-08-20 11:20:48 -0700535 .cfi_def_cfa_offset 0
536 .cfi_restore r4
537 .cfi_restore r5
538 .cfi_restore r6
539 .cfi_restore r7
Christopher Ferris31dea252013-03-08 16:50:31 -0800540
541 bx lr
542
5438:
544 and r2, t1, #LSB
545 and r0, w2, #LSB
546 cmp r0, #1
547 it cs
548 cmpcs r0, r2
549 itt eq
550 S2LOMEMEQ t1, t1, #8
551 S2LOMEMEQ w2, w2, #8
552 beq 8b
553 sub r0, r2, r0
554
555 /* Restore registers and stack. */
556 ldrd r6, r7, [sp]
557 ldrd r4, r5, [sp, #8]
558 adds sp, sp, #16
559
560 bx lr
Christopher Ferrisbd7fe1d2013-08-20 11:20:48 -0700561 .cfi_endproc
Christopher Ferris31dea252013-03-08 16:50:31 -0800562END(strcmp)