/* * Written by J.T. Conklin * Public domain. */ #include #if defined(LIBC_SCCS) RCSID("$NetBSD: strchr.S,v 1.3 2014/03/22 19:38:46 jakllsch Exp $") #endif ENTRY(strchr) pushl %esi pushl %ebx movl 12(%esp),%eax movzbl 16(%esp),%ecx /* * Align to word boundary. * Consider unrolling loop? */ .Lalign: testb $3,%al je .Lword_aligned movb (%eax),%bl cmpb %cl,%bl je .Ldone testb %bl,%bl je .Lzero incl %eax jmp .Lalign .Lword_aligned: /* copy char to all bytes in word */ movb %cl,%ch movl %ecx,%edx sall $16,%ecx orl %edx,%ecx /* Check whether any byte in the word is equal to ch or 0. */ _ALIGN_TEXT .Lloop: movl (%eax),%ebx addl $4,%eax movl %ebx,%esi leal -0x01010101(%ebx),%edx xorl %ecx,%esi subl $0x01010101,%esi orl %esi,%edx testl $0x80808080,%edx je .Lloop /* * In rare cases, the above loop may exit prematurely. We must * return to the loop if none of the bytes in the word match * ch or are equal to 0. */ /* * Alignment here avoids a stall on the Athlon, even though * it's not a branch target. */ _ALIGN_TEXT cmpb %cl,%bl /* 1st byte == ch? */ jne 1f subl $4,%eax jmp .Ldone 1: testb %bl,%bl /* 1st byte == 0? */ je .Lzero cmpb %cl,%bh /* 2nd byte == ch? */ jne 1f subl $3,%eax jmp .Ldone 1: testb %bh,%bh /* 2nd byte == 0? */ je .Lzero shrl $16,%ebx cmpb %cl,%bl /* 3rd byte == ch? */ jne 1f subl $2,%eax jmp .Ldone 1: testb %bl,%bl /* 3rd byte == 0? */ je .Lzero cmpb %cl,%bh /* 4th byte == ch? */ jne 1f decl %eax jmp .Ldone 1: testb %bh,%bh /* 4th byte == 0? */ jne .Lloop .Lzero: /* If a ch wasn't found, return 0. */ xorl %eax,%eax .Ldone: popl %ebx popl %esi ret END(strchr) STRONG_ALIAS(index,strchr)