1/* Compare two memory blocks for differences in the first COUNT bytes. 2 Copyright (C) 2004-2022 Free Software Foundation, Inc. 3 This file is part of the GNU C Library. 4 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. 9 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. 14 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/>. */ 18 19#include <sysdep.h> 20#include "asm-syntax.h" 21 22#define PARMS 4+4 /* Preserve EBX. */ 23#define BLK1 PARMS 24#define BLK2 BLK1+4 25#define LEN BLK2+4 26#define ENTRANCE pushl %ebx; cfi_adjust_cfa_offset (4); \ 27 cfi_rel_offset (ebx, 0) 28#define RETURN popl %ebx; cfi_adjust_cfa_offset (-4); \ 29 cfi_restore (ebx); ret 30 31/* Load an entry in a jump table into EBX. TABLE is a jump table 32 with relative offsets. INDEX is a register contains the index 33 into the jump table. */ 34#define LOAD_JUMP_TABLE_ENTRY(TABLE, INDEX) \ 35 /* We first load PC into EBX. */ \ 36 SETUP_PIC_REG(bx); \ 37 /* Get the address of the jump table. */ \ 38 addl $(TABLE - .), %ebx; \ 39 /* Get the entry and convert the relative offset to the \ 40 absolute address. */ \ 41 addl (%ebx,INDEX,4), %ebx 42 43 .text 44 ALIGN (4) 45ENTRY (memcmp) 46 ENTRANCE 47 48 movl BLK1(%esp), %eax 49 movl BLK2(%esp), %edx 50 movl LEN(%esp), %ecx 51 52 cmpl $1, %ecx 53 jne L(not_1) 54 movzbl (%eax), %ecx /* LEN == 1 */ 55 cmpb (%edx), %cl 56 jne L(neq) 57L(bye): 58 xorl %eax, %eax 59 RETURN 60 61 cfi_adjust_cfa_offset (4) 62 cfi_rel_offset (ebx, 0) 63L(neq): 64 sbbl %eax, %eax 65 sbbl $-1, %eax 66 RETURN 67 68 cfi_adjust_cfa_offset (4) 69 cfi_rel_offset (ebx, 0) 70L(not_1): 71 jl L(bye) /* LEN == 0 */ 72 73 pushl %esi 74 cfi_adjust_cfa_offset (4) 75 movl %eax, %esi 76 cfi_rel_offset (esi, 0) 77 cmpl $32, %ecx; 78 jge L(32bytesormore) /* LEN => 32 */ 79 80 LOAD_JUMP_TABLE_ENTRY (L(table_32bytes), %ecx) 81 addl %ecx, %edx 82 addl %ecx, %esi 83 _CET_NOTRACK jmp *%ebx 84 85 ALIGN (4) 86L(28bytes): 87 movl -28(%esi), %eax 88 movl -28(%edx), %ecx 89 cmpl %ecx, %eax 90 jne L(find_diff) 91L(24bytes): 92 movl -24(%esi), %eax 93 movl -24(%edx), %ecx 94 cmpl %ecx, %eax 95 jne L(find_diff) 96L(20bytes): 97 movl -20(%esi), %eax 98 movl -20(%edx), %ecx 99 cmpl %ecx, %eax 100 jne L(find_diff) 101L(16bytes): 102 movl -16(%esi), %eax 103 movl -16(%edx), %ecx 104 cmpl %ecx, %eax 105 jne L(find_diff) 106L(12bytes): 107 movl -12(%esi), %eax 108 movl -12(%edx), %ecx 109 cmpl %ecx, %eax 110 jne L(find_diff) 111L(8bytes): 112 movl -8(%esi), %eax 113 movl -8(%edx), %ecx 114 cmpl %ecx, %eax 115 jne L(find_diff) 116L(4bytes): 117 movl -4(%esi), %eax 118 movl -4(%edx), %ecx 119 cmpl %ecx, %eax 120 jne L(find_diff) 121L(0bytes): 122 popl %esi 123 cfi_adjust_cfa_offset (-4) 124 cfi_restore (esi) 125 xorl %eax, %eax 126 RETURN 127 128 cfi_adjust_cfa_offset (8) 129 cfi_rel_offset (esi, 0) 130 cfi_rel_offset (ebx, 4) 131L(29bytes): 132 movl -29(%esi), %eax 133 movl -29(%edx), %ecx 134 cmpl %ecx, %eax 135 jne L(find_diff) 136L(25bytes): 137 movl -25(%esi), %eax 138 movl -25(%edx), %ecx 139 cmpl %ecx, %eax 140 jne L(find_diff) 141L(21bytes): 142 movl -21(%esi), %eax 143 movl -21(%edx), %ecx 144 cmpl %ecx, %eax 145 jne L(find_diff) 146L(17bytes): 147 movl -17(%esi), %eax 148 movl -17(%edx), %ecx 149 cmpl %ecx, %eax 150 jne L(find_diff) 151L(13bytes): 152 movl -13(%esi), %eax 153 movl -13(%edx), %ecx 154 cmpl %ecx, %eax 155 jne L(find_diff) 156L(9bytes): 157 movl -9(%esi), %eax 158 movl -9(%edx), %ecx 159 cmpl %ecx, %eax 160 jne L(find_diff) 161L(5bytes): 162 movl -5(%esi), %eax 163 movl -5(%edx), %ecx 164 cmpl %ecx, %eax 165 jne L(find_diff) 166L(1bytes): 167 movzbl -1(%esi), %eax 168 cmpb -1(%edx), %al 169 jne L(set) 170 popl %esi 171 cfi_adjust_cfa_offset (-4) 172 cfi_restore (esi) 173 xorl %eax, %eax 174 RETURN 175 176 cfi_adjust_cfa_offset (8) 177 cfi_rel_offset (esi, 0) 178 cfi_rel_offset (ebx, 4) 179L(30bytes): 180 movl -30(%esi), %eax 181 movl -30(%edx), %ecx 182 cmpl %ecx, %eax 183 jne L(find_diff) 184L(26bytes): 185 movl -26(%esi), %eax 186 movl -26(%edx), %ecx 187 cmpl %ecx, %eax 188 jne L(find_diff) 189L(22bytes): 190 movl -22(%esi), %eax 191 movl -22(%edx), %ecx 192 cmpl %ecx, %eax 193 jne L(find_diff) 194L(18bytes): 195 movl -18(%esi), %eax 196 movl -18(%edx), %ecx 197 cmpl %ecx, %eax 198 jne L(find_diff) 199L(14bytes): 200 movl -14(%esi), %eax 201 movl -14(%edx), %ecx 202 cmpl %ecx, %eax 203 jne L(find_diff) 204L(10bytes): 205 movl -10(%esi), %eax 206 movl -10(%edx), %ecx 207 cmpl %ecx, %eax 208 jne L(find_diff) 209L(6bytes): 210 movl -6(%esi), %eax 211 movl -6(%edx), %ecx 212 cmpl %ecx, %eax 213 jne L(find_diff) 214L(2bytes): 215 movzwl -2(%esi), %eax 216 movzwl -2(%edx), %ecx 217 cmpb %cl, %al 218 jne L(set) 219 cmpl %ecx, %eax 220 jne L(set) 221 popl %esi 222 cfi_adjust_cfa_offset (-4) 223 cfi_restore (esi) 224 xorl %eax, %eax 225 RETURN 226 227 cfi_adjust_cfa_offset (8) 228 cfi_rel_offset (esi, 0) 229 cfi_rel_offset (ebx, 4) 230L(31bytes): 231 movl -31(%esi), %eax 232 movl -31(%edx), %ecx 233 cmpl %ecx, %eax 234 jne L(find_diff) 235L(27bytes): 236 movl -27(%esi), %eax 237 movl -27(%edx), %ecx 238 cmpl %ecx, %eax 239 jne L(find_diff) 240L(23bytes): 241 movl -23(%esi), %eax 242 movl -23(%edx), %ecx 243 cmpl %ecx, %eax 244 jne L(find_diff) 245L(19bytes): 246 movl -19(%esi), %eax 247 movl -19(%edx), %ecx 248 cmpl %ecx, %eax 249 jne L(find_diff) 250L(15bytes): 251 movl -15(%esi), %eax 252 movl -15(%edx), %ecx 253 cmpl %ecx, %eax 254 jne L(find_diff) 255L(11bytes): 256 movl -11(%esi), %eax 257 movl -11(%edx), %ecx 258 cmpl %ecx, %eax 259 jne L(find_diff) 260L(7bytes): 261 movl -7(%esi), %eax 262 movl -7(%edx), %ecx 263 cmpl %ecx, %eax 264 jne L(find_diff) 265L(3bytes): 266 movzwl -3(%esi), %eax 267 movzwl -3(%edx), %ecx 268 cmpb %cl, %al 269 jne L(set) 270 cmpl %ecx, %eax 271 jne L(set) 272 movzbl -1(%esi), %eax 273 cmpb -1(%edx), %al 274 jne L(set) 275 popl %esi 276 cfi_adjust_cfa_offset (-4) 277 cfi_restore (esi) 278 xorl %eax, %eax 279 RETURN 280 281 cfi_adjust_cfa_offset (8) 282 cfi_rel_offset (esi, 0) 283 cfi_rel_offset (ebx, 4) 284 ALIGN (4) 285/* ECX >= 32. */ 286L(32bytesormore): 287 subl $32, %ecx 288 289 movl (%esi), %eax 290 cmpl (%edx), %eax 291 jne L(load_ecx) 292 293 movl 4(%esi), %eax 294 cmpl 4(%edx), %eax 295 jne L(load_ecx_4) 296 297 movl 8(%esi), %eax 298 cmpl 8(%edx), %eax 299 jne L(load_ecx_8) 300 301 movl 12(%esi), %eax 302 cmpl 12(%edx), %eax 303 jne L(load_ecx_12) 304 305 movl 16(%esi), %eax 306 cmpl 16(%edx), %eax 307 jne L(load_ecx_16) 308 309 movl 20(%esi), %eax 310 cmpl 20(%edx), %eax 311 jne L(load_ecx_20) 312 313 movl 24(%esi), %eax 314 cmpl 24(%edx), %eax 315 jne L(load_ecx_24) 316 317 movl 28(%esi), %eax 318 cmpl 28(%edx), %eax 319 jne L(load_ecx_28) 320 321 addl $32, %esi 322 addl $32, %edx 323 cmpl $32, %ecx 324 jge L(32bytesormore) 325 326 LOAD_JUMP_TABLE_ENTRY (L(table_32bytes), %ecx) 327 addl %ecx, %edx 328 addl %ecx, %esi 329 _CET_NOTRACK jmp *%ebx 330 331L(load_ecx_28): 332 addl $0x4, %edx 333L(load_ecx_24): 334 addl $0x4, %edx 335L(load_ecx_20): 336 addl $0x4, %edx 337L(load_ecx_16): 338 addl $0x4, %edx 339L(load_ecx_12): 340 addl $0x4, %edx 341L(load_ecx_8): 342 addl $0x4, %edx 343L(load_ecx_4): 344 addl $0x4, %edx 345L(load_ecx): 346 movl (%edx), %ecx 347 348L(find_diff): 349 cmpb %cl, %al 350 jne L(set) 351 cmpb %ch, %ah 352 jne L(set) 353 shrl $16,%eax 354 shrl $16,%ecx 355 cmpb %cl, %al 356 jne L(set) 357 /* We get there only if we already know there is a 358 difference. */ 359 cmpl %ecx, %eax 360L(set): 361 sbbl %eax, %eax 362 sbbl $-1, %eax 363 popl %esi 364 cfi_adjust_cfa_offset (-4) 365 cfi_restore (esi) 366 RETURN 367END (memcmp) 368 369 .section .rodata 370 ALIGN (2) 371L(table_32bytes) : 372 .long L(0bytes) - L(table_32bytes) 373 .long L(1bytes) - L(table_32bytes) 374 .long L(2bytes) - L(table_32bytes) 375 .long L(3bytes) - L(table_32bytes) 376 .long L(4bytes) - L(table_32bytes) 377 .long L(5bytes) - L(table_32bytes) 378 .long L(6bytes) - L(table_32bytes) 379 .long L(7bytes) - L(table_32bytes) 380 .long L(8bytes) - L(table_32bytes) 381 .long L(9bytes) - L(table_32bytes) 382 .long L(10bytes) - L(table_32bytes) 383 .long L(11bytes) - L(table_32bytes) 384 .long L(12bytes) - L(table_32bytes) 385 .long L(13bytes) - L(table_32bytes) 386 .long L(14bytes) - L(table_32bytes) 387 .long L(15bytes) - L(table_32bytes) 388 .long L(16bytes) - L(table_32bytes) 389 .long L(17bytes) - L(table_32bytes) 390 .long L(18bytes) - L(table_32bytes) 391 .long L(19bytes) - L(table_32bytes) 392 .long L(20bytes) - L(table_32bytes) 393 .long L(21bytes) - L(table_32bytes) 394 .long L(22bytes) - L(table_32bytes) 395 .long L(23bytes) - L(table_32bytes) 396 .long L(24bytes) - L(table_32bytes) 397 .long L(25bytes) - L(table_32bytes) 398 .long L(26bytes) - L(table_32bytes) 399 .long L(27bytes) - L(table_32bytes) 400 .long L(28bytes) - L(table_32bytes) 401 .long L(29bytes) - L(table_32bytes) 402 .long L(30bytes) - L(table_32bytes) 403 .long L(31bytes) - L(table_32bytes) 404 405 406#undef bcmp 407weak_alias (memcmp, bcmp) 408#undef __memcmpeq 409strong_alias (memcmp, __memcmpeq) 410libc_hidden_builtin_def (memcmp) 411libc_hidden_def (__memcmpeq) 412