106708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes/*	$OpenBSD: strcat.S,v 1.8 2005/08/07 11:30:38 espie Exp $ */
206708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes/*
306708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes * Written by J.T. Conklin <jtc@netbsd.org>.
406708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes * Public domain.
506708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes */
606708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes
7851e68a2402fa414544e66650e09dfdaac813e51Elliott Hughes#include <private/bionic_asm.h>
806708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes
906708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes#if defined(APIWARN)
1006708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes#APP
1106708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes	.section .gnu.warning.strcat
1206708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes	.ascii "warning: strcat() is almost always misused, please use strlcat()"
1306708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes#NO_APP
1406708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes#endif
1506708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes
1606708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes/*
1706708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes * NOTE: I've unrolled the loop eight times: large enough to make a
1806708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes * significant difference, and small enough not to totally trash the
1906708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes * cache.
2006708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes */
2106708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes
2206708df6fb1cced3840d5db9c82ef13f29516e7fElliott HughesENTRY(strcat)
2306708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes	pushl	%edi			/* save edi */
2406708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes	movl	8(%esp),%edi		/* dst address */
2506708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes	movl	12(%esp),%edx		/* src address */
2606708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes	pushl	%edi			/* push destination address */
2706708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes
2806708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes	cld				/* set search forward */
2906708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes	xorl	%eax,%eax		/* set search for null terminator */
3006708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes	movl	$-1,%ecx		/* set search for lots of characters */
3106708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes	repne				/* search! */
3206708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes	scasb
3306708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes
3406708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes	leal	-1(%edi),%ecx		/* correct dst address */
3506708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes
3606708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes	.align 2,0x90
3706708df6fb1cced3840d5db9c82ef13f29516e7fElliott HughesL1:	movb	(%edx),%al		/* unroll loop, but not too much */
3806708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes	movb	%al,(%ecx)
3906708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes	testb	%al,%al
4006708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes	jz	L2
4106708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes	movb	1(%edx),%al
4206708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes	movb	%al,1(%ecx)
4306708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes	testb	%al,%al
4406708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes	jz	L2
4506708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes	movb	2(%edx),%al
4606708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes	movb	%al,2(%ecx)
4706708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes	testb	%al,%al
4806708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes	jz	L2
4906708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes	movb	3(%edx),%al
5006708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes	movb	%al,3(%ecx)
5106708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes	testb	%al,%al
5206708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes	jz	L2
5306708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes	movb	4(%edx),%al
5406708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes	movb	%al,4(%ecx)
5506708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes	testb	%al,%al
5606708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes	jz	L2
5706708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes	movb	5(%edx),%al
5806708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes	movb	%al,5(%ecx)
5906708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes	testb	%al,%al
6006708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes	jz	L2
6106708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes	movb	6(%edx),%al
6206708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes	movb	%al,6(%ecx)
6306708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes	testb	%al,%al
6406708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes	jz	L2
6506708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes	movb	7(%edx),%al
6606708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes	movb	%al,7(%ecx)
6706708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes	addl	$8,%edx
6806708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes	addl	$8,%ecx
6906708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes	testb	%al,%al
7006708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes	jnz	L1
7106708df6fb1cced3840d5db9c82ef13f29516e7fElliott HughesL2:	popl	%eax			/* pop destination address */
7206708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes	popl	%edi			/* restore edi */
7306708df6fb1cced3840d5db9c82ef13f29516e7fElliott Hughes	ret
7406708df6fb1cced3840d5db9c82ef13f29516e7fElliott HughesEND(strcat)
75