1b6cbf720SGianluca Guida/* 2b6cbf720SGianluca Guida * Written by J.T. Conklin <jtc@acorntoolworks.com> 3b6cbf720SGianluca Guida * Public domain. 4b6cbf720SGianluca Guida */ 5b6cbf720SGianluca Guida 6b6cbf720SGianluca Guida#include <machine/asm.h> 7b6cbf720SGianluca Guida 8b6cbf720SGianluca Guida#if defined(LIBC_SCCS) 9*0a6a1f1dSLionel Sambuc RCSID("$NetBSD: strrchr.S,v 1.3 2014/03/22 19:16:34 jakllsch Exp $") 10b6cbf720SGianluca Guida#endif 11b6cbf720SGianluca Guida 12b6cbf720SGianluca GuidaENTRY(strrchr) 13b6cbf720SGianluca Guida movzbq %sil,%rcx 14b6cbf720SGianluca Guida 15b6cbf720SGianluca Guida /* zero return value */ 16b6cbf720SGianluca Guida xorq %rax,%rax 17b6cbf720SGianluca Guida 18b6cbf720SGianluca Guida /* 19b6cbf720SGianluca Guida * Align to word boundary. 20b6cbf720SGianluca Guida * Consider unrolling loop? 21b6cbf720SGianluca Guida */ 22b6cbf720SGianluca Guida.Lalign: 23b6cbf720SGianluca Guida testb $7,%dil 24b6cbf720SGianluca Guida je .Lword_aligned 25b6cbf720SGianluca Guida movb (%rdi),%dl 26b6cbf720SGianluca Guida cmpb %cl,%dl 27b6cbf720SGianluca Guida cmoveq %rdi,%rax 28b6cbf720SGianluca Guida incq %rdi 29b6cbf720SGianluca Guida testb %dl,%dl 30b6cbf720SGianluca Guida jne .Lalign 31b6cbf720SGianluca Guida jmp .Ldone 32b6cbf720SGianluca Guida 33b6cbf720SGianluca Guida.Lword_aligned: 34b6cbf720SGianluca Guida /* copy char to all bytes in word */ 35b6cbf720SGianluca Guida movb %cl,%ch 36b6cbf720SGianluca Guida movq %rcx,%rdx 37b6cbf720SGianluca Guida salq $16,%rcx 38b6cbf720SGianluca Guida orq %rdx,%rcx 39b6cbf720SGianluca Guida movq %rcx,%rdx 40b6cbf720SGianluca Guida salq $32,%rcx 41b6cbf720SGianluca Guida orq %rdx,%rcx 42b6cbf720SGianluca Guida 43b6cbf720SGianluca Guida movabsq $0x0101010101010101,%r8 44b6cbf720SGianluca Guida movabsq $0x8080808080808080,%r9 45b6cbf720SGianluca Guida 46b6cbf720SGianluca Guida /* Check whether any byte in the word is equal to ch or 0. */ 47b6cbf720SGianluca Guida _ALIGN_TEXT 48b6cbf720SGianluca Guida.Lloop: 49b6cbf720SGianluca Guida movq (%rdi),%rdx 50b6cbf720SGianluca Guida addq $8,%rdi 51b6cbf720SGianluca Guida movq %rdx,%rsi 52b6cbf720SGianluca Guida subq %r8,%rdx 53b6cbf720SGianluca Guida xorq %rcx,%rsi 54b6cbf720SGianluca Guida subq %r8,%rsi 55b6cbf720SGianluca Guida orq %rsi,%rdx 56b6cbf720SGianluca Guida testq %r9,%rdx 57b6cbf720SGianluca Guida je .Lloop 58b6cbf720SGianluca Guida 59b6cbf720SGianluca Guida /* 60b6cbf720SGianluca Guida * In rare cases, the above loop may exit prematurely. We must 61b6cbf720SGianluca Guida * return to the loop if none of the bytes in the word match 62b6cbf720SGianluca Guida * ch or are equal to 0. 63b6cbf720SGianluca Guida */ 64b6cbf720SGianluca Guida 65b6cbf720SGianluca Guida movb -8(%rdi),%dl 66b6cbf720SGianluca Guida cmpb %cl,%dl /* 1st byte == ch? */ 67b6cbf720SGianluca Guida jne 1f 68b6cbf720SGianluca Guida leaq -8(%rdi),%rax 69b6cbf720SGianluca Guida1: testb %dl,%dl /* 1st byte == 0? */ 70b6cbf720SGianluca Guida je .Ldone 71b6cbf720SGianluca Guida 72b6cbf720SGianluca Guida movb -7(%rdi),%dl 73b6cbf720SGianluca Guida cmpb %cl,%dl /* 2nd byte == ch? */ 74b6cbf720SGianluca Guida jne 1f 75b6cbf720SGianluca Guida leaq -7(%rdi),%rax 76b6cbf720SGianluca Guida1: testb %dl,%dl /* 2nd byte == 0? */ 77b6cbf720SGianluca Guida je .Ldone 78b6cbf720SGianluca Guida 79b6cbf720SGianluca Guida movb -6(%rdi),%dl 80b6cbf720SGianluca Guida cmpb %cl,%dl /* 3rd byte == ch? */ 81b6cbf720SGianluca Guida jne 1f 82b6cbf720SGianluca Guida leaq -6(%rdi),%rax 83b6cbf720SGianluca Guida1: testb %dl,%dl /* 3rd byte == 0? */ 84b6cbf720SGianluca Guida je .Ldone 85b6cbf720SGianluca Guida 86b6cbf720SGianluca Guida movb -5(%rdi),%dl 87b6cbf720SGianluca Guida cmpb %cl,%dl /* 4th byte == ch? */ 88b6cbf720SGianluca Guida jne 1f 89b6cbf720SGianluca Guida leaq -5(%rdi),%rax 90b6cbf720SGianluca Guida1: testb %dl,%dl /* 4th byte == 0? */ 91b6cbf720SGianluca Guida je .Ldone 92b6cbf720SGianluca Guida 93b6cbf720SGianluca Guida movb -4(%rdi),%dl 94b6cbf720SGianluca Guida cmpb %cl,%dl /* 5th byte == ch? */ 95b6cbf720SGianluca Guida jne 1f 96b6cbf720SGianluca Guida leaq -4(%rdi),%rax 97b6cbf720SGianluca Guida1: testb %dl,%dl /* 5th byte == 0? */ 98b6cbf720SGianluca Guida je .Ldone 99b6cbf720SGianluca Guida 100b6cbf720SGianluca Guida movb -3(%rdi),%dl 101b6cbf720SGianluca Guida cmpb %cl,%dl /* 6th byte == ch? */ 102b6cbf720SGianluca Guida jne 1f 103b6cbf720SGianluca Guida leaq -3(%rdi),%rax 104b6cbf720SGianluca Guida1: testb %dl,%dl /* 6th byte == 0? */ 105b6cbf720SGianluca Guida je .Ldone 106b6cbf720SGianluca Guida 107b6cbf720SGianluca Guida movb -2(%rdi),%dl 108b6cbf720SGianluca Guida cmpb %cl,%dl /* 7th byte == ch? */ 109b6cbf720SGianluca Guida jne 1f 110b6cbf720SGianluca Guida leaq -2(%rdi),%rax 111b6cbf720SGianluca Guida1: testb %dl,%dl /* 7th byte == 0? */ 112b6cbf720SGianluca Guida je .Ldone 113b6cbf720SGianluca Guida 114b6cbf720SGianluca Guida movb -1(%rdi),%dl 115b6cbf720SGianluca Guida cmpb %cl,%dl /* 8th byte == ch? */ 116b6cbf720SGianluca Guida jne 1f 117b6cbf720SGianluca Guida leaq -1(%rdi),%rax 118b6cbf720SGianluca Guida1: testb %dl,%dl /* 8th byte == 0? */ 119b6cbf720SGianluca Guida jne .Lloop 120b6cbf720SGianluca Guida 121b6cbf720SGianluca Guida.Ldone: 122b6cbf720SGianluca Guida ret 123*0a6a1f1dSLionel SambucEND(strrchr) 124b6cbf720SGianluca Guida 125b6cbf720SGianluca GuidaSTRONG_ALIAS(rindex,strrchr) 126