137c9f0a6Schristos/* 237c9f0a6Schristos * Written by J.T. Conklin <jtc@acorntoolworks.com> 337c9f0a6Schristos * Public domain. 437c9f0a6Schristos */ 537c9f0a6Schristos 637c9f0a6Schristos#include <machine/asm.h> 737c9f0a6Schristos 837c9f0a6Schristos#if defined(LIBC_SCCS) 9*2c56941eSjakllsch RCSID("$NetBSD: strchr.S,v 1.3 2014/03/22 19:38:46 jakllsch Exp $") 1037c9f0a6Schristos#endif 1137c9f0a6Schristos 1237c9f0a6SchristosENTRY(strchr) 1337c9f0a6Schristos pushl %esi 1437c9f0a6Schristos pushl %ebx 1537c9f0a6Schristos movl 12(%esp),%eax 1637c9f0a6Schristos movzbl 16(%esp),%ecx 1737c9f0a6Schristos 1837c9f0a6Schristos /* 1937c9f0a6Schristos * Align to word boundary. 2037c9f0a6Schristos * Consider unrolling loop? 2137c9f0a6Schristos */ 2237c9f0a6Schristos.Lalign: 2337c9f0a6Schristos testb $3,%al 2437c9f0a6Schristos je .Lword_aligned 2537c9f0a6Schristos movb (%eax),%bl 2637c9f0a6Schristos cmpb %cl,%bl 2737c9f0a6Schristos je .Ldone 2837c9f0a6Schristos testb %bl,%bl 2937c9f0a6Schristos je .Lzero 3037c9f0a6Schristos incl %eax 3137c9f0a6Schristos jmp .Lalign 3237c9f0a6Schristos 3337c9f0a6Schristos.Lword_aligned: 3437c9f0a6Schristos /* copy char to all bytes in word */ 3537c9f0a6Schristos movb %cl,%ch 3637c9f0a6Schristos movl %ecx,%edx 3737c9f0a6Schristos sall $16,%ecx 3837c9f0a6Schristos orl %edx,%ecx 3937c9f0a6Schristos 4037c9f0a6Schristos /* Check whether any byte in the word is equal to ch or 0. */ 4137c9f0a6Schristos _ALIGN_TEXT 4237c9f0a6Schristos.Lloop: 4337c9f0a6Schristos movl (%eax),%ebx 4437c9f0a6Schristos addl $4,%eax 4537c9f0a6Schristos movl %ebx,%esi 4637c9f0a6Schristos leal -0x01010101(%ebx),%edx 4737c9f0a6Schristos xorl %ecx,%esi 4837c9f0a6Schristos subl $0x01010101,%esi 4937c9f0a6Schristos orl %esi,%edx 5037c9f0a6Schristos testl $0x80808080,%edx 5137c9f0a6Schristos je .Lloop 5237c9f0a6Schristos 5337c9f0a6Schristos /* 5437c9f0a6Schristos * In rare cases, the above loop may exit prematurely. We must 5537c9f0a6Schristos * return to the loop if none of the bytes in the word match 5637c9f0a6Schristos * ch or are equal to 0. 5737c9f0a6Schristos */ 5837c9f0a6Schristos 5937c9f0a6Schristos /* 6037c9f0a6Schristos * Alignment here avoids a stall on the Athlon, even though 6137c9f0a6Schristos * it's not a branch target. 6237c9f0a6Schristos */ 6337c9f0a6Schristos 6437c9f0a6Schristos _ALIGN_TEXT 6537c9f0a6Schristos cmpb %cl,%bl /* 1st byte == ch? */ 6637c9f0a6Schristos jne 1f 6737c9f0a6Schristos subl $4,%eax 6837c9f0a6Schristos jmp .Ldone 6937c9f0a6Schristos1: testb %bl,%bl /* 1st byte == 0? */ 7037c9f0a6Schristos je .Lzero 7137c9f0a6Schristos 7237c9f0a6Schristos cmpb %cl,%bh /* 2nd byte == ch? */ 7337c9f0a6Schristos jne 1f 7437c9f0a6Schristos subl $3,%eax 7537c9f0a6Schristos jmp .Ldone 7637c9f0a6Schristos1: testb %bh,%bh /* 2nd byte == 0? */ 7737c9f0a6Schristos je .Lzero 7837c9f0a6Schristos 7937c9f0a6Schristos shrl $16,%ebx 8037c9f0a6Schristos cmpb %cl,%bl /* 3rd byte == ch? */ 8137c9f0a6Schristos jne 1f 8237c9f0a6Schristos subl $2,%eax 8337c9f0a6Schristos jmp .Ldone 8437c9f0a6Schristos1: testb %bl,%bl /* 3rd byte == 0? */ 8537c9f0a6Schristos je .Lzero 8637c9f0a6Schristos 8737c9f0a6Schristos cmpb %cl,%bh /* 4th byte == ch? */ 8837c9f0a6Schristos jne 1f 8937c9f0a6Schristos decl %eax 9037c9f0a6Schristos jmp .Ldone 9137c9f0a6Schristos1: testb %bh,%bh /* 4th byte == 0? */ 9237c9f0a6Schristos jne .Lloop 9337c9f0a6Schristos 9437c9f0a6Schristos.Lzero: 9537c9f0a6Schristos /* If a ch wasn't found, return 0. */ 9637c9f0a6Schristos xorl %eax,%eax 9737c9f0a6Schristos 9837c9f0a6Schristos.Ldone: 9937c9f0a6Schristos popl %ebx 10037c9f0a6Schristos popl %esi 10137c9f0a6Schristos ret 102*2c56941eSjakllschEND(strchr) 10353a0f227Sdsl 10453a0f227SdslSTRONG_ALIAS(index,strchr) 105