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*3b06bbb9Sjakllsch RCSID("$NetBSD: strrchr.S,v 1.3 2014/03/22 19:38:46 jakllsch Exp $") 1037c9f0a6Schristos#endif 1137c9f0a6Schristos 1237c9f0a6SchristosENTRY(strrchr) 1337c9f0a6Schristos pushl %esi 1437c9f0a6Schristos pushl %edi 1537c9f0a6Schristos pushl %ebx 1637c9f0a6Schristos movl 16(%esp),%edx 1737c9f0a6Schristos movzbl 20(%esp),%ecx 1837c9f0a6Schristos 1937c9f0a6Schristos /* zero return value */ 2037c9f0a6Schristos xorl %eax,%eax 2137c9f0a6Schristos 2237c9f0a6Schristos /* 2337c9f0a6Schristos * Align to word boundary. 2437c9f0a6Schristos * Consider unrolling loop? 2537c9f0a6Schristos */ 2637c9f0a6Schristos.Lalign: 2737c9f0a6Schristos testb $3,%dl 2837c9f0a6Schristos je .Lword_aligned 2937c9f0a6Schristos movb (%edx),%bl 3037c9f0a6Schristos cmpb %cl,%bl 3137c9f0a6Schristos jne 1f 3237c9f0a6Schristos movl %edx,%eax 3337c9f0a6Schristos1: testb %bl,%bl 3437c9f0a6Schristos je .Ldone 3537c9f0a6Schristos incl %edx 3637c9f0a6Schristos jmp .Lalign 3737c9f0a6Schristos 3837c9f0a6Schristos.Lword_aligned: 3937c9f0a6Schristos /* copy char to all bytes in word */ 4037c9f0a6Schristos movb %cl,%ch 4137c9f0a6Schristos movl %ecx,%edi 4237c9f0a6Schristos sall $16,%ecx 4337c9f0a6Schristos orl %edi,%ecx 4437c9f0a6Schristos 4537c9f0a6Schristos /* Check whether any byte in the word is equal to ch or 0. */ 4637c9f0a6Schristos _ALIGN_TEXT 4737c9f0a6Schristos.Lloop: 4837c9f0a6Schristos movl (%edx),%ebx 4937c9f0a6Schristos addl $4,%edx 5037c9f0a6Schristos movl %ebx,%esi 5137c9f0a6Schristos leal -0x01010101(%ebx),%edi 5237c9f0a6Schristos xorl %ecx,%esi 5337c9f0a6Schristos subl $0x01010101,%esi 5437c9f0a6Schristos orl %esi,%edi 5537c9f0a6Schristos testl $0x80808080,%edi 5637c9f0a6Schristos je .Lloop 5737c9f0a6Schristos 5837c9f0a6Schristos /* 5937c9f0a6Schristos * In rare cases, the above loop may exit prematurely. We must 6037c9f0a6Schristos * return to the loop if none of the bytes in the word match 6137c9f0a6Schristos * ch or are equal to 0. 6237c9f0a6Schristos */ 6337c9f0a6Schristos 6437c9f0a6Schristos _ALIGN_TEXT 6537c9f0a6Schristos cmpb %cl,%bl /* 1st byte == ch? */ 6637c9f0a6Schristos jne 1f 6737c9f0a6Schristos leal -4(%edx),%eax 6837c9f0a6Schristos1: testb %bl,%bl /* 1st byte == 0? */ 6937c9f0a6Schristos je .Ldone 7037c9f0a6Schristos 7137c9f0a6Schristos cmpb %cl,%bh /* 2nd byte == ch? */ 7237c9f0a6Schristos jne 1f 7337c9f0a6Schristos leal -3(%edx),%eax 7437c9f0a6Schristos1: testb %bh,%bh /* 2nd byte == 0? */ 7537c9f0a6Schristos je .Ldone 7637c9f0a6Schristos 7737c9f0a6Schristos shrl $16,%ebx 7837c9f0a6Schristos cmpb %cl,%bl /* 3rd byte == ch? */ 7937c9f0a6Schristos jne 1f 8037c9f0a6Schristos leal -2(%edx),%eax 8137c9f0a6Schristos1: testb %bl,%bl /* 3rd byte == 0? */ 8237c9f0a6Schristos je .Ldone 8337c9f0a6Schristos 8437c9f0a6Schristos cmpb %cl,%bh /* 4th byte == ch? */ 8537c9f0a6Schristos jne 1f 8637c9f0a6Schristos leal -1(%edx),%eax 8737c9f0a6Schristos1: testb %bh,%bh /* 4th byte == 0? */ 8837c9f0a6Schristos jne .Lloop 8937c9f0a6Schristos 9037c9f0a6Schristos.Ldone: 9137c9f0a6Schristos popl %ebx 9237c9f0a6Schristos popl %edi 9337c9f0a6Schristos popl %esi 9437c9f0a6Schristos ret 95*3b06bbb9SjakllschEND(strrchr) 9653a0f227Sdsl 9753a0f227SdslSTRONG_ALIAS(rindex,strrchr) 98