1 /* memcmp - compare memory
3 Copyright (C) 2013-2017 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)
59 add limit_wd, limit, #7
60 lsr limit_wd, limit_wd, #3
61 /* Start of performance-critical section -- one 64B cache line. */
66 subs limit_wd, limit_wd, #1
67 eor diff, data1, data2 /* Non-zero if differences found. */
68 csinv endloop, diff, xzr, ne /* Last Dword or differences. */
69 cbz endloop, L(loop_aligned)
70 /* End of performance-critical section -- one 64B cache line. */
72 /* Not reached the limit, must have found a diff. */
73 cbnz limit_wd, L(not_limit)
75 /* Limit % 8 == 0 => all bytes significant. */
79 lsl limit, limit, #3 /* Bits -> bytes. */
86 bic data1, data1, mask
87 bic data2, data2, mask
97 /* The MS-non-zero bit of DIFF marks either the first bit
98 that is different, or the end of the significant data.
99 Shifting left now will bring the critical information into the
102 lsl data1, data1, pos
103 lsl data2, data2, pos
104 /* But we need to zero-extend (char is unsigned) the value and then
105 perform a signed 32-bit subtraction. */
106 lsr data1, data1, #56
107 sub result, data1, data2, lsr #56
111 /* Sources are mutually aligned, but are not currently at an
112 alignment boundary. Round down the addresses and then mask off
113 the bytes that precede the start point. */
116 add limit, limit, tmp1 /* Adjust the limit for the extra. */
117 lsl tmp1, tmp1, #3 /* Bytes beyond alignment -> bits. */
118 ldr data1, [src1], #8
119 neg tmp1, tmp1 /* Bits to alignment -64. */
120 ldr data2, [src2], #8
123 /* Big-endian. Early bytes are at MSB. */
124 lsl tmp2, tmp2, tmp1 /* Shift (tmp1 & 63). */
126 /* Little-endian. Early bytes are at LSB. */
127 lsr tmp2, tmp2, tmp1 /* Shift (tmp1 & 63). */
129 add limit_wd, limit, #7
130 orr data1, data1, tmp2
131 orr data2, data2, tmp2
132 lsr limit_wd, limit_wd, #3
143 /* Perhaps we can do better than this. */
144 ldrb data1w, [src1], #1
145 ldrb data2w, [src2], #1
146 subs limit, limit, #1
147 ccmp data1w, data2w, #0, cs /* NZCV = 0b0000. */
149 sub result, data1, data2
153 weak_alias (memcmp, bcmp)
154 libc_hidden_builtin_def (memcmp)