xref: /minix/common/lib/libc/arch/i386/string/strchr.S (revision 84d9c625)
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: strchr.S,v 1.2 2009/07/17 19:37:57 dsl Exp $")
10#endif
11
12ENTRY(strchr)
13	pushl	%esi
14	pushl	%ebx
15	movl	12(%esp),%eax
16	movzbl	16(%esp),%ecx
17
18	/*
19	 * Align to word boundary.
20	 * Consider unrolling loop?
21	 */
22.Lalign:
23	testb	$3,%al
24	je	.Lword_aligned
25	movb	(%eax),%bl
26	cmpb	%cl,%bl
27	je	.Ldone
28	testb	%bl,%bl
29	je	.Lzero
30	incl	%eax
31	jmp	.Lalign
32
33.Lword_aligned:
34	/* copy char to all bytes in word */
35	movb	%cl,%ch
36	movl	%ecx,%edx
37	sall	$16,%ecx
38	orl	%edx,%ecx
39
40	/* Check whether any byte in the word is equal to ch or 0. */
41	_ALIGN_TEXT
42.Lloop:
43	movl	(%eax),%ebx
44	addl	$4,%eax
45	movl	%ebx,%esi
46	leal	-0x01010101(%ebx),%edx
47	xorl	%ecx,%esi
48	subl	$0x01010101,%esi
49	orl	%esi,%edx
50	testl	$0x80808080,%edx
51	je	.Lloop
52
53	/*
54	 * In rare cases, the above loop may exit prematurely. We must
55	 * return to the loop if none of the bytes in the word match
56	 * ch or are equal to 0.
57	 */
58
59	/*
60	 * Alignment here avoids a stall on the Athlon, even though
61	 * it's not a branch target.
62	 */
63
64	_ALIGN_TEXT
65	cmpb	%cl,%bl		/* 1st byte == ch? */
66	jne	1f
67	subl	$4,%eax
68	jmp	.Ldone
691:	testb	%bl,%bl		/* 1st byte == 0? */
70	je	.Lzero
71
72	cmpb	%cl,%bh		/* 2nd byte == ch? */
73	jne	1f
74	subl	$3,%eax
75	jmp	.Ldone
761:	testb	%bh,%bh		/* 2nd byte == 0? */
77	je	.Lzero
78
79	shrl	$16,%ebx
80	cmpb	%cl,%bl		/* 3rd byte == ch? */
81	jne	1f
82	subl	$2,%eax
83	jmp	.Ldone
841:	testb	%bl,%bl		/* 3rd byte == 0? */
85	je	.Lzero
86
87	cmpb	%cl,%bh		/* 4th byte == ch? */
88	jne	1f
89	decl	%eax
90	jmp	.Ldone
911:	testb	%bh,%bh		/* 4th byte == 0? */
92	jne	.Lloop
93
94.Lzero:
95	/* If a ch wasn't found, return 0. */
96	xorl	%eax,%eax
97
98.Ldone:
99	popl	%ebx
100	popl	%esi
101	ret
102
103STRONG_ALIAS(index,strchr)
104