2 * strcmp - compare two strings
4 * Copyright (c) 2012-2022, Arm Limited.
5 * SPDX-License-Identifier: MIT
15 #include <machine/asm.h>
19 #define REP8_01 0x0101010101010101
20 #define REP8_7f 0x7f7f7f7f7f7f7f7f
40 /* On big-endian early bytes are at MSB and on little-endian LSB.
41 LS_FW means shifting towards early bytes. */
48 /* NUL detection works on the principle that (X - 1) & (~X) & 0x80
49 (=> (X - 1) & ~(X | 0x7f)) is non-zero iff a byte is zero, and
50 can be done in parallel across the entire word.
51 Since carry propagation makes 0x1 bytes before a NUL byte appear
52 NUL too in big-endian, byte-reverse the data before the NUL check. */
61 cbnz tmp, L(mutual_align)
66 ldr data2, [src1, off2]
71 sub has_nul, tmp, zeroones
74 sub has_nul, data1, zeroones
75 orr tmp, data1, REP8_7f
77 bics has_nul, has_nul, tmp /* Non-zero if NUL terminator. */
78 ccmp data1, data2, 0, eq
83 eor diff, data1, data2
84 orr syndrome, diff, has_nul
87 rev syndrome, syndrome
92 /* The most-significant-non-zero bit of the syndrome marks either the
93 first bit that is different, or the top bit of the first zero byte.
94 Shifting left now will bring the critical information into the
96 lsl data1, data1, shift
97 lsl data2, data2, shift
98 /* But we need to zero-extend (char is unsigned) the value and then
99 perform a signed 32-bit subtraction. */
101 sub result, data1, data2, lsr 56
107 /* Sources are mutually aligned, but are not currently at an
108 alignment boundary. Round down the addresses and then mask off
109 the bytes that precede the start point. */
111 ldr data2, [src1, off2]
113 neg shift, src2, lsl 3 /* Bits to alignment -64. */
115 LS_FW tmp, tmp, shift
116 orr data1, data1, tmp
117 orr data2, data2, tmp
121 /* Align SRC1 to 8 bytes and then compare 8 bytes at a time, always
122 checking to make sure that we don't access beyond the end of SRC2. */
123 cbz tmp, L(src1_aligned)
125 ldrb data1w, [src1], 1
126 ldrb data2w, [src2], 1
128 ccmp data1w, data2w, 0, ne /* NZCV = 0b0000. */
131 b.ne L(do_misaligned)
134 neg shift, src2, lsl 3
140 lsr tmp, zeroones, shift
141 orr data3, data3, tmp
142 sub has_nul, data3, zeroones
143 orr tmp, data3, REP8_7f
144 bics has_nul, has_nul, tmp
152 ldr data3, [src1, off1]
153 ldr data2, [src1, off2]
157 sub has_nul, data3, zeroones
158 orr tmp, data3, REP8_7f
160 bics has_nul, has_nul, tmp
161 ccmp data1, data2, 0, eq
162 b.eq L(loop_unaligned)
164 lsl tmp, has_nul, shift
168 eor diff, data1, data2
169 orr syndrome, diff, tmp
170 cbnz syndrome, L(end)
174 lsr data2, data3, shift
175 lsr has_nul, has_nul, shift
180 eor diff, data1, data2
181 orr syndrome, diff, has_nul
185 sub result, data1, data2