11dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
21dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
31dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * All rights reserved.
41dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
51dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Redistribution and use in source and binary forms, with or without
61dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * modification, are permitted provided that the following conditions
71dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * are met:
81dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *  * Redistributions of source code must retain the above copyright
91dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *    notice, this list of conditions and the following disclaimer.
101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *  * Redistributions in binary form must reproduce the above copyright
111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *    notice, this list of conditions and the following disclaimer in
121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *    the documentation and/or other materials provided with the
131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *    distribution.
141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * SUCH DAMAGE.
271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <machine/cpu-features.h>
30851e68a2402fa414544e66650e09dfdaac813e51Elliott Hughes#include <private/bionic_asm.h>
311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
323ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding
333ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding#ifdef HAVE_32_BYTE_CACHE_LINE
343ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding#define CACHE_LINE_SIZE     32
353ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding#else
363ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding#define CACHE_LINE_SIZE     64
373ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding#endif
383ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding
391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
403ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding * Optimized memcmp() for Cortex-A9.
411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
43420878c6908cf9c2862888477ec3f424a06cf172Kenny RootENTRY(memcmp)
443ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding        pld         [r0, #(CACHE_LINE_SIZE * 0)]
453ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding        pld         [r0, #(CACHE_LINE_SIZE * 1)]
461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        /* take of the case where length is 0 or the buffers are the same */
481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        cmp         r0, r1
491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        moveq       r0, #0
501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        bxeq        lr
511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
523ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding        pld         [r1, #(CACHE_LINE_SIZE * 0)]
533ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding        pld         [r1, #(CACHE_LINE_SIZE * 1)]
543ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding
553ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding        /* make sure we have at least 8+4 bytes, this simplify things below
563ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding         * and avoid some overhead for small blocks
573ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding         */
583ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding        cmp        r2, #(8+4)
593ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding        bmi        10f
603ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding/*
613ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding * Neon optimization
623ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding * Comparing 32 bytes at a time
633ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding */
643ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding#if defined(__ARM_NEON__) && defined(NEON_UNALIGNED_ACCESS)
653ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding        subs        r2, r2, #32
663ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding        blo         3f
673ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding
683ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding        /* preload all the cache lines we need. */
693ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding        pld         [r0, #(CACHE_LINE_SIZE * 2)]
703ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding        pld         [r1, #(CACHE_LINE_SIZE * 2)]
713ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding
723ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding1:      /* The main loop compares 32 bytes at a time */
733ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding        vld1.8      {d0 - d3}, [r0]!
743ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding        pld         [r0, #(CACHE_LINE_SIZE * 2)]
753ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding        vld1.8      {d4 - d7}, [r1]!
763ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding        pld         [r1, #(CACHE_LINE_SIZE * 2)]
773ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding
783ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding        /* Start subtracting the values and merge results */
793ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding        vsub.i8     q0, q2
803ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding        vsub.i8     q1, q3
813ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding        vorr        q2, q0, q1
823ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding        vorr        d4, d5
833ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding        vmov        r3, ip, d4
843ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding        /* Check if there are any differences among the 32 bytes */
853ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding        orrs        r3, ip
863ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding        bne         2f
873ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding        subs        r2, r2, #32
883ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding        bhs         1b
893ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding        b           3f
903ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding2:
913ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding        /* Check if the difference was in the first or last 16 bytes */
923ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding        sub         r0, #32
933ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding        vorr        d0, d1
943ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding        sub         r1, #32
953ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding        vmov        r3, ip, d0
963ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding        orrs        r3, ip
973ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding        /* if the first 16 bytes are equal, we only have to rewind 16 bytes */
983ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding        ittt        eq
993ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding        subeq       r2, #16
1003ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding        addeq       r0, #16
1013ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding        addeq       r1, #16
1023ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding
1033ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding3:      /* fix-up the remaining count */
1043ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding        add         r2, r2, #32
1053ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding
1063ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding        cmp        r2, #(8+4)
1073ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding        bmi        10f
1083ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding#endif
1093ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding
1101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        /* save registers */
1111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        stmfd       sp!, {r4, lr}
112ed45970ac5a182e512669cfa5c15b9f4fa783ad7Christopher Ferris        .cfi_def_cfa_offset 8
113ed45970ac5a182e512669cfa5c15b9f4fa783ad7Christopher Ferris        .cfi_rel_offset r4, 0
114ed45970ac5a182e512669cfa5c15b9f4fa783ad7Christopher Ferris        .cfi_rel_offset lr, 4
1151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        /* since r0 hold the result, move the first source
1171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project         * pointer somewhere else
1181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project         */
1191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project         mov        r4, r0
1206719500dbd9330d7539d2db3dcf3e8ad1858c7aaElliott Hughes
1211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        /* align first pointer to word boundary
1221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project         * offset = -src & 3
1231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project         */
1241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        rsb         r3, r4, #0
1251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        ands        r3, r3, #3
1261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        beq         0f
1271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        /* align first pointer  */
1291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        sub         r2, r2, r3
1301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project1:      ldrb        r0, [r4], #1
1311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        ldrb        ip, [r1], #1
1321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        subs        r0, r0, ip
1331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        bne         9f
1341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        subs        r3, r3, #1
1351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        bne         1b
1361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project0:      /* here the first pointer is aligned, and we have at least 4 bytes
1391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project         * to process.
1401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project         */
1411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        /* see if the pointers are congruent */
1431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        eor         r0, r4, r1
1441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        ands        r0, r0, #3
1451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        bne         5f
1461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        /* congruent case, 32 bytes per iteration
1481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project         * We need to make sure there are at least 32+4 bytes left
1491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project         * because we effectively read ahead one word, and we could
1501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project         * read past the buffer (and segfault) if we're not careful.
1511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project         */
1521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        ldr         ip, [r1]
1541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        subs        r2, r2, #(32 + 4)
1551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        bmi         1f
1566719500dbd9330d7539d2db3dcf3e8ad1858c7aaElliott Hughes
1573ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding0:      pld         [r4, #(CACHE_LINE_SIZE * 2)]
1583ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding        pld         [r1, #(CACHE_LINE_SIZE * 2)]
1591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        ldr         r0, [r4], #4
1601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        ldr         lr, [r1, #4]!
1611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        eors        r0, r0, ip
1621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        ldreq       r0, [r4], #4
1631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        ldreq       ip, [r1, #4]!
1641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        eoreqs      r0, r0, lr
1651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        ldreq       r0, [r4], #4
1661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        ldreq       lr, [r1, #4]!
1671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        eoreqs      r0, r0, ip
1681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        ldreq       r0, [r4], #4
1691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        ldreq       ip, [r1, #4]!
1701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        eoreqs      r0, r0, lr
1711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        ldreq       r0, [r4], #4
1721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        ldreq       lr, [r1, #4]!
1731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        eoreqs      r0, r0, ip
1741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        ldreq       r0, [r4], #4
1751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        ldreq       ip, [r1, #4]!
1761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        eoreqs      r0, r0, lr
1771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        ldreq       r0, [r4], #4
1781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        ldreq       lr, [r1, #4]!
1791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        eoreqs      r0, r0, ip
1801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        ldreq       r0, [r4], #4
1811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        ldreq       ip, [r1, #4]!
1821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        eoreqs      r0, r0, lr
1836719500dbd9330d7539d2db3dcf3e8ad1858c7aaElliott Hughes        bne         2f
1841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        subs        r2, r2, #32
1851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        bhs         0b
1861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        /* do we have at least 4 bytes left? */
1881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project1:      adds        r2, r2, #(32 - 4 + 4)
1891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        bmi         4f
1906719500dbd9330d7539d2db3dcf3e8ad1858c7aaElliott Hughes
1911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        /* finish off 4 bytes at a time */
1921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project3:      ldr         r0, [r4], #4
1931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        ldr         ip, [r1], #4
1941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        eors        r0, r0, ip
1951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        bne         2f
1961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        subs        r2, r2, #4
1971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        bhs         3b
1981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        /* are we done? */
2001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project4:      adds        r2, r2, #4
2011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        moveq       r0, #0
2021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        beq         9f
2031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        /* finish off the remaining bytes */
2051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        b           8f
2061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project2:      /* the last 4 bytes are different, restart them */
2081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        sub         r4, r4, #4
2091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        sub         r1, r1, #4
2101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        mov         r2, #4
2111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        /* process the last few bytes */
2131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project8:      ldrb        r0, [r4], #1
2141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        ldrb        ip, [r1], #1
2151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        // stall
2161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        subs        r0, r0, ip
2171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        bne         9f
2181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        subs        r2, r2, #1
2191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        bne         8b
2201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project9:      /* restore registers and return */
2221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        ldmfd       sp!, {r4, lr}
2231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        bx          lr
2241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2253ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding10:     /* process less than 12 bytes */
2263ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding        cmp         r2, #0
2273ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding        moveq       r0, #0
2283ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding        bxeq        lr
2293ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding        mov         r3, r0
2303ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding11:
2313ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding        ldrb        r0, [r3], #1
2323ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding        ldrb        ip, [r1], #1
2333ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding        subs        r0, ip
2343ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding        bxne        lr
2353ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding        subs        r2, r2, #1
2363ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding        bne         11b
2373ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding        bx          lr
2381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project5:      /*************** non-congruent case ***************/
2406719500dbd9330d7539d2db3dcf3e8ad1858c7aaElliott Hughes        and         r0, r1, #3
2411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        cmp         r0, #2
2421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        bne         4f
2431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        /* here, offset is 2 (16-bits aligned, special cased) */
2456719500dbd9330d7539d2db3dcf3e8ad1858c7aaElliott Hughes
2461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        /* make sure we have at least 16 bytes to process */
2471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        subs        r2, r2, #16
2481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        addmi       r2, r2, #16
2491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        bmi         8b
2501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        /* align the unaligned pointer */
2521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        bic         r1, r1, #3
2531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        ldr         lr, [r1], #4
2541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2553ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding6:      pld         [r1, #(CACHE_LINE_SIZE * 2)]
2563ebd31c0a1d343c3fd7845d7b1149e841ad83c6aHenrik Smiding        pld         [r4, #(CACHE_LINE_SIZE * 2)]
2571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        mov         ip, lr, lsr #16
2581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        ldr         lr, [r1], #4
2591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        ldr         r0, [r4], #4
2601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        orr         ip, ip, lr, lsl #16
2611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        eors        r0, r0, ip
2621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        moveq       ip, lr, lsr #16
2631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        ldreq       lr, [r1], #4
2641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        ldreq       r0, [r4], #4
2651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        orreq       ip, ip, lr, lsl #16
2661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        eoreqs      r0, r0, ip
2671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        moveq       ip, lr, lsr #16
2681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        ldreq       lr, [r1], #4
2691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        ldreq       r0, [r4], #4
2701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        orreq       ip, ip, lr, lsl #16
2711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        eoreqs      r0, r0, ip
2721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        moveq       ip, lr, lsr #16
2731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        ldreq       lr, [r1], #4
2741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        ldreq       r0, [r4], #4
2751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        orreq       ip, ip, lr, lsl #16
2761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        eoreqs      r0, r0, ip
2771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        bne         7f
2781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        subs        r2, r2, #16
2791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        bhs         6b
2801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        sub         r1, r1, #2
2811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        /* are we done? */
2821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        adds        r2, r2, #16
2831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        moveq       r0, #0
2841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        beq         9b
2851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        /* finish off the remaining bytes */
2861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        b           8b
2871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project7:      /* fix up the 2 pointers and fallthrough... */
2891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        sub         r1, r1, #(4+2)
2901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        sub         r4, r4, #4
2911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        mov         r2, #4
2921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        b           8b
2931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project4:      /*************** offset is 1 or 3 (less optimized) ***************/
2961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		stmfd		sp!, {r5, r6, r7}
2981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        // r5 = rhs
3001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        // r6 = lhs
3011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        // r7 = scratch
3021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
3031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        mov         r5, r0, lsl #3		/* r5 = right shift */
3041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        rsb         r6, r5, #32         /* r6 = left shift */
3051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
3061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        /* align the unaligned pointer */
3071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        bic         r1, r1, #3
3081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        ldr         r7, [r1], #4
3091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        sub         r2, r2, #8
3101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
3111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project6:      mov         ip, r7, lsr r5
3121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        ldr         r7, [r1], #4
3131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        ldr         r0, [r4], #4
3141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        orr         ip, ip, r7, lsl r6
3151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        eors        r0, r0, ip
3161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        moveq       ip, r7, lsr r5
3171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        ldreq       r7, [r1], #4
3181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        ldreq       r0, [r4], #4
3191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        orreq       ip, ip, r7, lsl r6
3201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        eoreqs      r0, r0, ip
3211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        bne         7f
3221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        subs        r2, r2, #8
3231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        bhs         6b
3241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
3251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        sub         r1, r1, r6, lsr #3
3261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		ldmfd       sp!, {r5, r6, r7}
3271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
3281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        /* are we done? */
3291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        adds        r2, r2, #8
3301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        moveq       r0, #0
3311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        beq         9b
3321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
3331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        /* finish off the remaining bytes */
3341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        b           8b
3351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
3361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project7:      /* fix up the 2 pointers and fallthrough... */
3371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        sub         r1, r1, #4
3381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        sub         r1, r1, r6, lsr #3
3391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        sub         r4, r4, #4
3401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        mov         r2, #4
3411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		ldmfd		sp!, {r5, r6, r7}
3421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        b           8b
3436719500dbd9330d7539d2db3dcf3e8ad1858c7aaElliott HughesEND(memcmp)
344