xref: /openbsd-src/lib/libc/arch/amd64/string/strrchr.S (revision 631951aab24dc7dce7719dfa2487185ea5ef120f)
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