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