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