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