xref: /netbsd/common/lib/libc/arch/i386/string/strrchr.S (revision 3b06bbb9)
137c9f0a6Schristos/*
237c9f0a6Schristos * Written by J.T. Conklin <jtc@acorntoolworks.com>
337c9f0a6Schristos * Public domain.
437c9f0a6Schristos */
537c9f0a6Schristos
637c9f0a6Schristos#include <machine/asm.h>
737c9f0a6Schristos
837c9f0a6Schristos#if defined(LIBC_SCCS)
9*3b06bbb9Sjakllsch	RCSID("$NetBSD: strrchr.S,v 1.3 2014/03/22 19:38:46 jakllsch Exp $")
1037c9f0a6Schristos#endif
1137c9f0a6Schristos
1237c9f0a6SchristosENTRY(strrchr)
1337c9f0a6Schristos	pushl	%esi
1437c9f0a6Schristos	pushl	%edi
1537c9f0a6Schristos	pushl	%ebx
1637c9f0a6Schristos	movl	16(%esp),%edx
1737c9f0a6Schristos	movzbl	20(%esp),%ecx
1837c9f0a6Schristos
1937c9f0a6Schristos	/* zero return value */
2037c9f0a6Schristos	xorl	%eax,%eax
2137c9f0a6Schristos
2237c9f0a6Schristos	/*
2337c9f0a6Schristos	 * Align to word boundary.
2437c9f0a6Schristos	 * Consider unrolling loop?
2537c9f0a6Schristos	 */
2637c9f0a6Schristos.Lalign:
2737c9f0a6Schristos	testb	$3,%dl
2837c9f0a6Schristos	je	.Lword_aligned
2937c9f0a6Schristos	movb	(%edx),%bl
3037c9f0a6Schristos	cmpb	%cl,%bl
3137c9f0a6Schristos	jne	1f
3237c9f0a6Schristos	movl	%edx,%eax
3337c9f0a6Schristos1:	testb	%bl,%bl
3437c9f0a6Schristos	je	.Ldone
3537c9f0a6Schristos	incl	%edx
3637c9f0a6Schristos	jmp	.Lalign
3737c9f0a6Schristos
3837c9f0a6Schristos.Lword_aligned:
3937c9f0a6Schristos	/* copy char to all bytes in word */
4037c9f0a6Schristos	movb	%cl,%ch
4137c9f0a6Schristos	movl	%ecx,%edi
4237c9f0a6Schristos	sall	$16,%ecx
4337c9f0a6Schristos	orl	%edi,%ecx
4437c9f0a6Schristos
4537c9f0a6Schristos	/* Check whether any byte in the word is equal to ch or 0.  */
4637c9f0a6Schristos	_ALIGN_TEXT
4737c9f0a6Schristos.Lloop:
4837c9f0a6Schristos	movl	(%edx),%ebx
4937c9f0a6Schristos	addl	$4,%edx
5037c9f0a6Schristos	movl	%ebx,%esi
5137c9f0a6Schristos	leal	-0x01010101(%ebx),%edi
5237c9f0a6Schristos	xorl	%ecx,%esi
5337c9f0a6Schristos	subl	$0x01010101,%esi
5437c9f0a6Schristos	orl	%esi,%edi
5537c9f0a6Schristos	testl	$0x80808080,%edi
5637c9f0a6Schristos	je	.Lloop
5737c9f0a6Schristos
5837c9f0a6Schristos	/*
5937c9f0a6Schristos	 * In rare cases, the above loop may exit prematurely. We must
6037c9f0a6Schristos	 * return to the loop if none of the bytes in the word match
6137c9f0a6Schristos	 * ch or are equal to 0.
6237c9f0a6Schristos	 */
6337c9f0a6Schristos
6437c9f0a6Schristos	_ALIGN_TEXT
6537c9f0a6Schristos	cmpb	%cl,%bl		/* 1st byte == ch? */
6637c9f0a6Schristos	jne	1f
6737c9f0a6Schristos	leal	-4(%edx),%eax
6837c9f0a6Schristos1:	testb	%bl,%bl		/* 1st byte == 0? */
6937c9f0a6Schristos	je	.Ldone
7037c9f0a6Schristos
7137c9f0a6Schristos	cmpb	%cl,%bh		/* 2nd byte == ch? */
7237c9f0a6Schristos	jne	1f
7337c9f0a6Schristos	leal	-3(%edx),%eax
7437c9f0a6Schristos1:	testb	%bh,%bh		/* 2nd byte == 0? */
7537c9f0a6Schristos	je	.Ldone
7637c9f0a6Schristos
7737c9f0a6Schristos	shrl	$16,%ebx
7837c9f0a6Schristos	cmpb	%cl,%bl		/* 3rd byte == ch? */
7937c9f0a6Schristos	jne	1f
8037c9f0a6Schristos	leal	-2(%edx),%eax
8137c9f0a6Schristos1:	testb	%bl,%bl		/* 3rd byte == 0? */
8237c9f0a6Schristos	je	.Ldone
8337c9f0a6Schristos
8437c9f0a6Schristos	cmpb	%cl,%bh		/* 4th byte == ch? */
8537c9f0a6Schristos	jne	1f
8637c9f0a6Schristos	leal	-1(%edx),%eax
8737c9f0a6Schristos1:	testb	%bh,%bh		/* 4th byte == 0? */
8837c9f0a6Schristos	jne	.Lloop
8937c9f0a6Schristos
9037c9f0a6Schristos.Ldone:
9137c9f0a6Schristos	popl	%ebx
9237c9f0a6Schristos	popl	%edi
9337c9f0a6Schristos	popl	%esi
9437c9f0a6Schristos	ret
95*3b06bbb9SjakllschEND(strrchr)
9653a0f227Sdsl
9753a0f227SdslSTRONG_ALIAS(rindex,strrchr)
98