1 /* Copyright (C) 2012-2024 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library. If not, see
17 <https://www.gnu.org/licenses/>. */
27 #define REP8_01 0x0101010101010101
28 #define REP8_7f 0x7f7f7f7f7f7f7f7f
30 /* Parameters and result. */
35 /* Internal variables. */
50 /* On big-endian early bytes are at MSB and on little-endian LSB.
51 LS_FW means shifting towards early bytes. */
58 /* NUL detection works on the principle that (X - 1) & (~X) & 0x80
59 (=> (X - 1) & ~(X | 0x7f)) is non-zero iff a byte is zero, and
60 can be done in parallel across the entire word.
61 Since carry propagation makes 0x1 bytes before a NUL byte appear
62 NUL too in big-endian, byte-reverse the data before the NUL check. */
72 cbnz tmp, L(mutual_align)
77 ldr data2, [src1, off2]
82 sub has_nul, tmp, zeroones
85 sub has_nul, data1, zeroones
86 orr tmp, data1, REP8_7f
88 bics has_nul, has_nul, tmp /* Non-zero if NUL terminator. */
89 ccmp data1, data2, 0, eq
94 eor diff, data1, data2
95 orr syndrome, diff, has_nul
98 rev syndrome, syndrome
103 /* The most-significant-non-zero bit of the syndrome marks either the
104 first bit that is different, or the top bit of the first zero byte.
105 Shifting left now will bring the critical information into the
107 lsl data1, data1, shift
108 lsl data2, data2, shift
109 /* But we need to zero-extend (char is unsigned) the value and then
110 perform a signed 32-bit subtraction. */
112 sub result, data1, data2, lsr 56
118 /* Sources are mutually aligned, but are not currently at an
119 alignment boundary. Round down the addresses and then mask off
120 the bytes that precede the start point. */
122 ldr data2, [src1, off2]
124 neg shift, src2, lsl 3 /* Bits to alignment -64. */
126 LS_FW tmp, tmp, shift
127 orr data1, data1, tmp
128 orr data2, data2, tmp
132 /* Align SRC1 to 8 bytes and then compare 8 bytes at a time, always
133 checking to make sure that we don't access beyond the end of SRC2. */
134 cbz tmp, L(src1_aligned)
136 ldrb data1w, [src1], 1
137 ldrb data2w, [src2], 1
139 ccmp data1w, data2w, 0, ne /* NZCV = 0b0000. */
142 b.ne L(do_misaligned)
145 neg shift, src2, lsl 3
151 lsr tmp, zeroones, shift
152 orr data3, data3, tmp
153 sub has_nul, data3, zeroones
154 orr tmp, data3, REP8_7f
155 bics has_nul, has_nul, tmp
163 ldr data3, [src1, off1]
164 ldr data2, [src1, off2]
168 sub has_nul, data3, zeroones
169 orr tmp, data3, REP8_7f
171 bics has_nul, has_nul, tmp
172 ccmp data1, data2, 0, eq
173 b.eq L(loop_unaligned)
175 lsl tmp, has_nul, shift
179 eor diff, data1, data2
180 orr syndrome, diff, tmp
181 cbnz syndrome, L(end)
185 lsr data2, data3, shift
186 lsr has_nul, has_nul, shift
191 eor diff, data1, data2
192 orr syndrome, diff, has_nul
196 sub result, data1, data2
200 libc_hidden_builtin_def (strcmp)