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:38:46 jakllsch Exp $")
10#endif
11
12ENTRY(strrchr)
13	pushl	%esi
14	pushl	%edi
15	pushl	%ebx
16	movl	16(%esp),%edx
17	movzbl	20(%esp),%ecx
18
19	/* zero return value */
20	xorl	%eax,%eax
21
22	/*
23	 * Align to word boundary.
24	 * Consider unrolling loop?
25	 */
26.Lalign:
27	testb	$3,%dl
28	je	.Lword_aligned
29	movb	(%edx),%bl
30	cmpb	%cl,%bl
31	jne	1f
32	movl	%edx,%eax
331:	testb	%bl,%bl
34	je	.Ldone
35	incl	%edx
36	jmp	.Lalign
37
38.Lword_aligned:
39	/* copy char to all bytes in word */
40	movb	%cl,%ch
41	movl	%ecx,%edi
42	sall	$16,%ecx
43	orl	%edi,%ecx
44
45	/* Check whether any byte in the word is equal to ch or 0.  */
46	_ALIGN_TEXT
47.Lloop:
48	movl	(%edx),%ebx
49	addl	$4,%edx
50	movl	%ebx,%esi
51	leal	-0x01010101(%ebx),%edi
52	xorl	%ecx,%esi
53	subl	$0x01010101,%esi
54	orl	%esi,%edi
55	testl	$0x80808080,%edi
56	je	.Lloop
57
58	/*
59	 * In rare cases, the above loop may exit prematurely. We must
60	 * return to the loop if none of the bytes in the word match
61	 * ch or are equal to 0.
62	 */
63
64	_ALIGN_TEXT
65	cmpb	%cl,%bl		/* 1st byte == ch? */
66	jne	1f
67	leal	-4(%edx),%eax
681:	testb	%bl,%bl		/* 1st byte == 0? */
69	je	.Ldone
70
71	cmpb	%cl,%bh		/* 2nd byte == ch? */
72	jne	1f
73	leal	-3(%edx),%eax
741:	testb	%bh,%bh		/* 2nd byte == 0? */
75	je	.Ldone
76
77	shrl	$16,%ebx
78	cmpb	%cl,%bl		/* 3rd byte == ch? */
79	jne	1f
80	leal	-2(%edx),%eax
811:	testb	%bl,%bl		/* 3rd byte == 0? */
82	je	.Ldone
83
84	cmpb	%cl,%bh		/* 4th byte == ch? */
85	jne	1f
86	leal	-1(%edx),%eax
871:	testb	%bh,%bh		/* 4th byte == 0? */
88	jne	.Lloop
89
90.Ldone:
91	popl	%ebx
92	popl	%edi
93	popl	%esi
94	ret
95END(strrchr)
96
97STRONG_ALIAS(rindex,strrchr)
98