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