1 /* memcmp - compare memory
3 Copyright (C) 2013-2015 Free Software Foundation, Inc.
5 This file is part of the GNU C Library.
7 The GNU C Library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
12 The GNU C Library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public
18 License along with the GNU C Library. If not, see
19 <http://www.gnu.org/licenses/>. */
28 /* Parameters and result. */
34 /* Internal variables. */
49 ENTRY_ALIGN (memcmp, 6)
56 add limit_wd, limit, #7
57 lsr limit_wd, limit_wd, #3
58 /* Start of performance-critical section -- one 64B cache line. */
63 subs limit_wd, limit_wd, #1
64 eor diff, data1, data2 /* Non-zero if differences found. */
65 csinv endloop, diff, xzr, ne /* Last Dword or differences. */
66 cbz endloop, L(loop_aligned)
67 /* End of performance-critical section -- one 64B cache line. */
69 /* Not reached the limit, must have found a diff. */
70 cbnz limit_wd, L(not_limit)
72 /* Limit % 8 == 0 => all bytes significant. */
76 lsl limit, limit, #3 /* Bits -> bytes. */
83 bic data1, data1, mask
84 bic data2, data2, mask
94 /* The MS-non-zero bit of DIFF marks either the first bit
95 that is different, or the end of the significant data.
96 Shifting left now will bring the critical information into the
100 lsl data2, data2, pos
101 /* But we need to zero-extend (char is unsigned) the value and then
102 perform a signed 32-bit subtraction. */
103 lsr data1, data1, #56
104 sub result, data1, data2, lsr #56
108 /* Sources are mutually aligned, but are not currently at an
109 alignment boundary. Round down the addresses and then mask off
110 the bytes that precede the start point. */
113 add limit, limit, tmp1 /* Adjust the limit for the extra. */
114 lsl tmp1, tmp1, #3 /* Bytes beyond alignment -> bits. */
115 ldr data1, [src1], #8
116 neg tmp1, tmp1 /* Bits to alignment -64. */
117 ldr data2, [src2], #8
120 /* Big-endian. Early bytes are at MSB. */
121 lsl tmp2, tmp2, tmp1 /* Shift (tmp1 & 63). */
123 /* Little-endian. Early bytes are at LSB. */
124 lsr tmp2, tmp2, tmp1 /* Shift (tmp1 & 63). */
126 add limit_wd, limit, #7
127 orr data1, data1, tmp2
128 orr data2, data2, tmp2
129 lsr limit_wd, limit_wd, #3
140 /* Perhaps we can do better than this. */
141 ldrb data1w, [src1], #1
142 ldrb data2w, [src2], #1
143 subs limit, limit, #1
144 ccmp data1w, data2w, #0, cs /* NZCV = 0b0000. */
146 sub result, data1, data2
150 weak_alias (memcmp, bcmp)
151 libc_hidden_builtin_def (memcmp)