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