xref: /minix3/common/lib/libc/arch/x86_64/string/strrchr.S (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
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