1/* 2Copyright (c) 2011, Intel Corporation 3All rights reserved. 4 5Redistribution and use in source and binary forms, with or without 6modification, are permitted provided that the following conditions are met: 7 8 * Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 11 * Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 15 * Neither the name of Intel Corporation nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 19THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 23ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 26ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29*/ 30 31#ifndef USE_AS_STRCAT 32 33# ifndef STRLEN 34# define STRLEN strlen_atom 35# endif 36 37# ifndef L 38# define L(label) .L##label 39# endif 40 41# ifndef cfi_startproc 42# define cfi_startproc .cfi_startproc 43# endif 44 45# ifndef cfi_endproc 46# define cfi_endproc .cfi_endproc 47# endif 48 49/* calee safe register only for strnlen is required */ 50 51# ifdef USE_AS_STRNLEN 52# ifndef cfi_rel_offset 53# define cfi_rel_offset(reg, off) .cfi_rel_offset reg, off 54# endif 55 56# ifndef cfi_restore 57# define cfi_restore(reg) .cfi_restore reg 58# endif 59 60# ifndef cfi_adjust_cfa_offset 61# define cfi_adjust_cfa_offset(off) .cfi_adjust_cfa_offset off 62# endif 63# endif 64 65# ifndef ENTRY 66# define ENTRY(name) \ 67 .type name, @function; \ 68 .globl name; \ 69 .p2align 4; \ 70name: \ 71 cfi_startproc 72# endif 73 74# ifndef END 75# define END(name) \ 76 cfi_endproc; \ 77 .size name, .-name 78# endif 79 80# define PARMS 4 81# define STR PARMS 82# define RETURN ret 83 84# ifdef USE_AS_STRNLEN 85# define LEN PARMS + 8 86# define CFI_PUSH(REG) \ 87 cfi_adjust_cfa_offset (4); \ 88 cfi_rel_offset (REG, 0) 89 90# define CFI_POP(REG) \ 91 cfi_adjust_cfa_offset (-4); \ 92 cfi_restore (REG) 93 94# define PUSH(REG) pushl REG; CFI_PUSH (REG) 95# define POP(REG) popl REG; CFI_POP (REG) 96# undef RETURN 97# define RETURN POP (%edi); ret; CFI_PUSH(%edi); 98# endif 99 100 .text 101ENTRY (STRLEN) 102 mov STR(%esp), %edx 103# ifdef USE_AS_STRNLEN 104 PUSH (%edi) 105 movl LEN(%esp), %edi 106 sub $4, %edi 107 jbe L(len_less4_prolog) 108# endif 109#endif 110 xor %eax, %eax 111 cmpb $0, (%edx) 112 jz L(exit_tail0) 113 cmpb $0, 1(%edx) 114 jz L(exit_tail1) 115 cmpb $0, 2(%edx) 116 jz L(exit_tail2) 117 cmpb $0, 3(%edx) 118 jz L(exit_tail3) 119 120#ifdef USE_AS_STRNLEN 121 sub $4, %edi 122 jbe L(len_less8_prolog) 123#endif 124 125 cmpb $0, 4(%edx) 126 jz L(exit_tail4) 127 cmpb $0, 5(%edx) 128 jz L(exit_tail5) 129 cmpb $0, 6(%edx) 130 jz L(exit_tail6) 131 cmpb $0, 7(%edx) 132 jz L(exit_tail7) 133 134#ifdef USE_AS_STRNLEN 135 sub $4, %edi 136 jbe L(len_less12_prolog) 137#endif 138 139 cmpb $0, 8(%edx) 140 jz L(exit_tail8) 141 cmpb $0, 9(%edx) 142 jz L(exit_tail9) 143 cmpb $0, 10(%edx) 144 jz L(exit_tail10) 145 cmpb $0, 11(%edx) 146 jz L(exit_tail11) 147 148#ifdef USE_AS_STRNLEN 149 sub $4, %edi 150 jbe L(len_less16_prolog) 151#endif 152 153 cmpb $0, 12(%edx) 154 jz L(exit_tail12) 155 cmpb $0, 13(%edx) 156 jz L(exit_tail13) 157 cmpb $0, 14(%edx) 158 jz L(exit_tail14) 159 cmpb $0, 15(%edx) 160 jz L(exit_tail15) 161 162 pxor %xmm0, %xmm0 163 lea 16(%edx), %eax 164 mov %eax, %ecx 165 and $-16, %eax 166 167#ifdef USE_AS_STRNLEN 168 and $15, %edx 169 add %edx, %edi 170 sub $64, %edi 171 jbe L(len_less64) 172#endif 173 174 pcmpeqb (%eax), %xmm0 175 pmovmskb %xmm0, %edx 176 pxor %xmm1, %xmm1 177 lea 16(%eax), %eax 178 test %edx, %edx 179 jnz L(exit) 180 181 pcmpeqb (%eax), %xmm1 182 pmovmskb %xmm1, %edx 183 pxor %xmm2, %xmm2 184 lea 16(%eax), %eax 185 test %edx, %edx 186 jnz L(exit) 187 188 pcmpeqb (%eax), %xmm2 189 pmovmskb %xmm2, %edx 190 pxor %xmm3, %xmm3 191 lea 16(%eax), %eax 192 test %edx, %edx 193 jnz L(exit) 194 195 pcmpeqb (%eax), %xmm3 196 pmovmskb %xmm3, %edx 197 lea 16(%eax), %eax 198 test %edx, %edx 199 jnz L(exit) 200 201#ifdef USE_AS_STRNLEN 202 sub $64, %edi 203 jbe L(len_less64) 204#endif 205 206 pcmpeqb (%eax), %xmm0 207 pmovmskb %xmm0, %edx 208 lea 16(%eax), %eax 209 test %edx, %edx 210 jnz L(exit) 211 212 pcmpeqb (%eax), %xmm1 213 pmovmskb %xmm1, %edx 214 lea 16(%eax), %eax 215 test %edx, %edx 216 jnz L(exit) 217 218 pcmpeqb (%eax), %xmm2 219 pmovmskb %xmm2, %edx 220 lea 16(%eax), %eax 221 test %edx, %edx 222 jnz L(exit) 223 224 pcmpeqb (%eax), %xmm3 225 pmovmskb %xmm3, %edx 226 lea 16(%eax), %eax 227 test %edx, %edx 228 jnz L(exit) 229 230#ifdef USE_AS_STRNLEN 231 sub $64, %edi 232 jbe L(len_less64) 233#endif 234 235 pcmpeqb (%eax), %xmm0 236 pmovmskb %xmm0, %edx 237 lea 16(%eax), %eax 238 test %edx, %edx 239 jnz L(exit) 240 241 pcmpeqb (%eax), %xmm1 242 pmovmskb %xmm1, %edx 243 lea 16(%eax), %eax 244 test %edx, %edx 245 jnz L(exit) 246 247 pcmpeqb (%eax), %xmm2 248 pmovmskb %xmm2, %edx 249 lea 16(%eax), %eax 250 test %edx, %edx 251 jnz L(exit) 252 253 pcmpeqb (%eax), %xmm3 254 pmovmskb %xmm3, %edx 255 lea 16(%eax), %eax 256 test %edx, %edx 257 jnz L(exit) 258 259#ifdef USE_AS_STRNLEN 260 sub $64, %edi 261 jbe L(len_less64) 262#endif 263 264 pcmpeqb (%eax), %xmm0 265 pmovmskb %xmm0, %edx 266 lea 16(%eax), %eax 267 test %edx, %edx 268 jnz L(exit) 269 270 pcmpeqb (%eax), %xmm1 271 pmovmskb %xmm1, %edx 272 lea 16(%eax), %eax 273 test %edx, %edx 274 jnz L(exit) 275 276 pcmpeqb (%eax), %xmm2 277 pmovmskb %xmm2, %edx 278 lea 16(%eax), %eax 279 test %edx, %edx 280 jnz L(exit) 281 282 pcmpeqb (%eax), %xmm3 283 pmovmskb %xmm3, %edx 284 lea 16(%eax), %eax 285 test %edx, %edx 286 jnz L(exit) 287 288#ifdef USE_AS_STRNLEN 289 mov %eax, %edx 290 and $63, %edx 291 add %edx, %edi 292#endif 293 294 and $-0x40, %eax 295 296 .p2align 4 297L(aligned_64_loop): 298#ifdef USE_AS_STRNLEN 299 sub $64, %edi 300 jbe L(len_less64) 301#endif 302 movaps (%eax), %xmm0 303 movaps 16(%eax), %xmm1 304 movaps 32(%eax), %xmm2 305 movaps 48(%eax), %xmm6 306 pminub %xmm1, %xmm0 307 pminub %xmm6, %xmm2 308 pminub %xmm0, %xmm2 309 pcmpeqb %xmm3, %xmm2 310 pmovmskb %xmm2, %edx 311 lea 64(%eax), %eax 312 test %edx, %edx 313 jz L(aligned_64_loop) 314 315 pcmpeqb -64(%eax), %xmm3 316 pmovmskb %xmm3, %edx 317 lea 48(%ecx), %ecx 318 test %edx, %edx 319 jnz L(exit) 320 321 pcmpeqb %xmm1, %xmm3 322 pmovmskb %xmm3, %edx 323 lea -16(%ecx), %ecx 324 test %edx, %edx 325 jnz L(exit) 326 327 pcmpeqb -32(%eax), %xmm3 328 pmovmskb %xmm3, %edx 329 lea -16(%ecx), %ecx 330 test %edx, %edx 331 jnz L(exit) 332 333 pcmpeqb %xmm6, %xmm3 334 pmovmskb %xmm3, %edx 335 lea -16(%ecx), %ecx 336L(exit): 337 sub %ecx, %eax 338 test %dl, %dl 339 jz L(exit_high) 340 341 mov %dl, %cl 342 and $15, %cl 343 jz L(exit_8) 344 test $0x01, %dl 345 jnz L(exit_tail0) 346 test $0x02, %dl 347 jnz L(exit_tail1) 348 test $0x04, %dl 349 jnz L(exit_tail2) 350 add $3, %eax 351 RETURN 352 353 .p2align 4 354L(exit_8): 355 test $0x10, %dl 356 jnz L(exit_tail4) 357 test $0x20, %dl 358 jnz L(exit_tail5) 359 test $0x40, %dl 360 jnz L(exit_tail6) 361 add $7, %eax 362 RETURN 363 364 .p2align 4 365L(exit_high): 366 mov %dh, %ch 367 and $15, %ch 368 jz L(exit_high_8) 369 test $0x01, %dh 370 jnz L(exit_tail8) 371 test $0x02, %dh 372 jnz L(exit_tail9) 373 test $0x04, %dh 374 jnz L(exit_tail10) 375 add $11, %eax 376 RETURN 377 378 .p2align 4 379L(exit_high_8): 380 test $0x10, %dh 381 jnz L(exit_tail12) 382 test $0x20, %dh 383 jnz L(exit_tail13) 384 test $0x40, %dh 385 jnz L(exit_tail14) 386 add $15, %eax 387L(exit_tail0): 388 RETURN 389 390#ifdef USE_AS_STRNLEN 391 392 .p2align 4 393L(len_less64): 394 pxor %xmm0, %xmm0 395 add $64, %edi 396 397 pcmpeqb (%eax), %xmm0 398 pmovmskb %xmm0, %edx 399 pxor %xmm1, %xmm1 400 lea 16(%eax), %eax 401 test %edx, %edx 402 jnz L(strnlen_exit) 403 404 sub $16, %edi 405 jbe L(return_start_len) 406 407 pcmpeqb (%eax), %xmm1 408 pmovmskb %xmm1, %edx 409 lea 16(%eax), %eax 410 test %edx, %edx 411 jnz L(strnlen_exit) 412 413 sub $16, %edi 414 jbe L(return_start_len) 415 416 pcmpeqb (%eax), %xmm0 417 pmovmskb %xmm0, %edx 418 lea 16(%eax), %eax 419 test %edx, %edx 420 jnz L(strnlen_exit) 421 422 sub $16, %edi 423 jbe L(return_start_len) 424 425 pcmpeqb (%eax), %xmm1 426 pmovmskb %xmm1, %edx 427 lea 16(%eax), %eax 428 test %edx, %edx 429 jnz L(strnlen_exit) 430 431#ifndef USE_AS_STRLCAT 432 movl LEN(%esp), %eax 433 RETURN 434#else 435 jmp L(return_start_len) 436#endif 437 438 .p2align 4 439L(strnlen_exit): 440 sub %ecx, %eax 441 442 test %dl, %dl 443 jz L(strnlen_exit_high) 444 mov %dl, %cl 445 and $15, %cl 446 jz L(strnlen_exit_8) 447 test $0x01, %dl 448 jnz L(exit_tail0) 449 test $0x02, %dl 450 jnz L(strnlen_exit_tail1) 451 test $0x04, %dl 452 jnz L(strnlen_exit_tail2) 453 sub $4, %edi 454 jb L(return_start_len) 455 lea 3(%eax), %eax 456 RETURN 457 458 .p2align 4 459L(strnlen_exit_8): 460 test $0x10, %dl 461 jnz L(strnlen_exit_tail4) 462 test $0x20, %dl 463 jnz L(strnlen_exit_tail5) 464 test $0x40, %dl 465 jnz L(strnlen_exit_tail6) 466 sub $8, %edi 467 jb L(return_start_len) 468 lea 7(%eax), %eax 469 RETURN 470 471 .p2align 4 472L(strnlen_exit_high): 473 mov %dh, %ch 474 and $15, %ch 475 jz L(strnlen_exit_high_8) 476 test $0x01, %dh 477 jnz L(strnlen_exit_tail8) 478 test $0x02, %dh 479 jnz L(strnlen_exit_tail9) 480 test $0x04, %dh 481 jnz L(strnlen_exit_tail10) 482 sub $12, %edi 483 jb L(return_start_len) 484 lea 11(%eax), %eax 485 RETURN 486 487 .p2align 4 488L(strnlen_exit_high_8): 489 test $0x10, %dh 490 jnz L(strnlen_exit_tail12) 491 test $0x20, %dh 492 jnz L(strnlen_exit_tail13) 493 test $0x40, %dh 494 jnz L(strnlen_exit_tail14) 495 sub $16, %edi 496 jb L(return_start_len) 497 lea 15(%eax), %eax 498 RETURN 499 500 .p2align 4 501L(strnlen_exit_tail1): 502 sub $2, %edi 503 jb L(return_start_len) 504 lea 1(%eax), %eax 505 RETURN 506 507 .p2align 4 508L(strnlen_exit_tail2): 509 sub $3, %edi 510 jb L(return_start_len) 511 lea 2(%eax), %eax 512 RETURN 513 514 .p2align 4 515L(strnlen_exit_tail4): 516 sub $5, %edi 517 jb L(return_start_len) 518 lea 4(%eax), %eax 519 RETURN 520 521 .p2align 4 522L(strnlen_exit_tail5): 523 sub $6, %edi 524 jb L(return_start_len) 525 lea 5(%eax), %eax 526 RETURN 527 528 .p2align 4 529L(strnlen_exit_tail6): 530 sub $7, %edi 531 jb L(return_start_len) 532 lea 6(%eax), %eax 533 RETURN 534 535 .p2align 4 536L(strnlen_exit_tail8): 537 sub $9, %edi 538 jb L(return_start_len) 539 lea 8(%eax), %eax 540 RETURN 541 542 .p2align 4 543L(strnlen_exit_tail9): 544 sub $10, %edi 545 jb L(return_start_len) 546 lea 9(%eax), %eax 547 RETURN 548 549 .p2align 4 550L(strnlen_exit_tail10): 551 sub $11, %edi 552 jb L(return_start_len) 553 lea 10(%eax), %eax 554 RETURN 555 556 .p2align 4 557L(strnlen_exit_tail12): 558 sub $13, %edi 559 jb L(return_start_len) 560 lea 12(%eax), %eax 561 RETURN 562 563 .p2align 4 564L(strnlen_exit_tail13): 565 sub $14, %edi 566 jb L(return_start_len) 567 lea 13(%eax), %eax 568 RETURN 569 570 .p2align 4 571L(strnlen_exit_tail14): 572 sub $15, %edi 573 jb L(return_start_len) 574 lea 14(%eax), %eax 575 RETURN 576 577#ifndef USE_AS_STRLCAT 578 .p2align 4 579L(return_start_len): 580 movl LEN(%esp), %eax 581 RETURN 582#endif 583 584/* for prolog only */ 585 586 .p2align 4 587L(len_less4_prolog): 588 xor %eax, %eax 589 590 add $4, %edi 591 jz L(exit_tail0) 592 593 cmpb $0, (%edx) 594 jz L(exit_tail0) 595 cmp $1, %edi 596 je L(exit_tail1) 597 598 cmpb $0, 1(%edx) 599 jz L(exit_tail1) 600 cmp $2, %edi 601 je L(exit_tail2) 602 603 cmpb $0, 2(%edx) 604 jz L(exit_tail2) 605 cmp $3, %edi 606 je L(exit_tail3) 607 608 cmpb $0, 3(%edx) 609 jz L(exit_tail3) 610 mov %edi, %eax 611 RETURN 612 613 .p2align 4 614L(len_less8_prolog): 615 add $4, %edi 616 617 cmpb $0, 4(%edx) 618 jz L(exit_tail4) 619 cmp $1, %edi 620 je L(exit_tail5) 621 622 cmpb $0, 5(%edx) 623 jz L(exit_tail5) 624 cmp $2, %edi 625 je L(exit_tail6) 626 627 cmpb $0, 6(%edx) 628 jz L(exit_tail6) 629 cmp $3, %edi 630 je L(exit_tail7) 631 632 cmpb $0, 7(%edx) 633 jz L(exit_tail7) 634 mov $8, %eax 635 RETURN 636 637 638 .p2align 4 639L(len_less12_prolog): 640 add $4, %edi 641 642 cmpb $0, 8(%edx) 643 jz L(exit_tail8) 644 cmp $1, %edi 645 je L(exit_tail9) 646 647 cmpb $0, 9(%edx) 648 jz L(exit_tail9) 649 cmp $2, %edi 650 je L(exit_tail10) 651 652 cmpb $0, 10(%edx) 653 jz L(exit_tail10) 654 cmp $3, %edi 655 je L(exit_tail11) 656 657 cmpb $0, 11(%edx) 658 jz L(exit_tail11) 659 mov $12, %eax 660 RETURN 661 662 .p2align 4 663L(len_less16_prolog): 664 add $4, %edi 665 666 cmpb $0, 12(%edx) 667 jz L(exit_tail12) 668 cmp $1, %edi 669 je L(exit_tail13) 670 671 cmpb $0, 13(%edx) 672 jz L(exit_tail13) 673 cmp $2, %edi 674 je L(exit_tail14) 675 676 cmpb $0, 14(%edx) 677 jz L(exit_tail14) 678 cmp $3, %edi 679 je L(exit_tail15) 680 681 cmpb $0, 15(%edx) 682 jz L(exit_tail15) 683 mov $16, %eax 684 RETURN 685#endif 686 687 .p2align 4 688L(exit_tail1): 689 add $1, %eax 690 RETURN 691 692L(exit_tail2): 693 add $2, %eax 694 RETURN 695 696L(exit_tail3): 697 add $3, %eax 698 RETURN 699 700L(exit_tail4): 701 add $4, %eax 702 RETURN 703 704L(exit_tail5): 705 add $5, %eax 706 RETURN 707 708L(exit_tail6): 709 add $6, %eax 710 RETURN 711 712L(exit_tail7): 713 add $7, %eax 714 RETURN 715 716L(exit_tail8): 717 add $8, %eax 718 RETURN 719 720L(exit_tail9): 721 add $9, %eax 722 RETURN 723 724L(exit_tail10): 725 add $10, %eax 726 RETURN 727 728L(exit_tail11): 729 add $11, %eax 730 RETURN 731 732L(exit_tail12): 733 add $12, %eax 734 RETURN 735 736L(exit_tail13): 737 add $13, %eax 738 RETURN 739 740L(exit_tail14): 741 add $14, %eax 742 RETURN 743 744L(exit_tail15): 745 add $15, %eax 746#ifndef USE_AS_STRCAT 747 RETURN 748END (STRLEN) 749#endif 750