1/* 2 * Written by J.T. Conklin <jtc@acorntoolworks.com> 3 * Public domain. 4 */ 5 6#include <machine/asm.h> 7 8#if defined(LIBC_SCCS) 9 RCSID("$NetBSD: strchr.S,v 1.2 2009/07/17 19:37:57 dsl Exp $") 10#endif 11 12ENTRY(strchr) 13 pushl %esi 14 pushl %ebx 15 movl 12(%esp),%eax 16 movzbl 16(%esp),%ecx 17 18 /* 19 * Align to word boundary. 20 * Consider unrolling loop? 21 */ 22.Lalign: 23 testb $3,%al 24 je .Lword_aligned 25 movb (%eax),%bl 26 cmpb %cl,%bl 27 je .Ldone 28 testb %bl,%bl 29 je .Lzero 30 incl %eax 31 jmp .Lalign 32 33.Lword_aligned: 34 /* copy char to all bytes in word */ 35 movb %cl,%ch 36 movl %ecx,%edx 37 sall $16,%ecx 38 orl %edx,%ecx 39 40 /* Check whether any byte in the word is equal to ch or 0. */ 41 _ALIGN_TEXT 42.Lloop: 43 movl (%eax),%ebx 44 addl $4,%eax 45 movl %ebx,%esi 46 leal -0x01010101(%ebx),%edx 47 xorl %ecx,%esi 48 subl $0x01010101,%esi 49 orl %esi,%edx 50 testl $0x80808080,%edx 51 je .Lloop 52 53 /* 54 * In rare cases, the above loop may exit prematurely. We must 55 * return to the loop if none of the bytes in the word match 56 * ch or are equal to 0. 57 */ 58 59 /* 60 * Alignment here avoids a stall on the Athlon, even though 61 * it's not a branch target. 62 */ 63 64 _ALIGN_TEXT 65 cmpb %cl,%bl /* 1st byte == ch? */ 66 jne 1f 67 subl $4,%eax 68 jmp .Ldone 691: testb %bl,%bl /* 1st byte == 0? */ 70 je .Lzero 71 72 cmpb %cl,%bh /* 2nd byte == ch? */ 73 jne 1f 74 subl $3,%eax 75 jmp .Ldone 761: testb %bh,%bh /* 2nd byte == 0? */ 77 je .Lzero 78 79 shrl $16,%ebx 80 cmpb %cl,%bl /* 3rd byte == ch? */ 81 jne 1f 82 subl $2,%eax 83 jmp .Ldone 841: testb %bl,%bl /* 3rd byte == 0? */ 85 je .Lzero 86 87 cmpb %cl,%bh /* 4th byte == ch? */ 88 jne 1f 89 decl %eax 90 jmp .Ldone 911: testb %bh,%bh /* 4th byte == 0? */ 92 jne .Lloop 93 94.Lzero: 95 /* If a ch wasn't found, return 0. */ 96 xorl %eax,%eax 97 98.Ldone: 99 popl %ebx 100 popl %esi 101 ret 102 103STRONG_ALIAS(index,strchr) 104