|  | /*	$OpenBSD: strcat.S,v 1.8 2005/08/07 11:30:38 espie Exp $ */ | 
|  | /* | 
|  | * Written by J.T. Conklin <jtc@netbsd.org>. | 
|  | * Public domain. | 
|  | */ | 
|  |  | 
|  | #include <private/bionic_asm.h> | 
|  |  | 
|  | #if defined(APIWARN) | 
|  | #APP | 
|  | .section .gnu.warning.strcat | 
|  | .ascii "warning: strcat() is almost always misused, please use strlcat()" | 
|  | #NO_APP | 
|  | #endif | 
|  |  | 
|  | /* | 
|  | * NOTE: I've unrolled the loop eight times: large enough to make a | 
|  | * significant difference, and small enough not to totally trash the | 
|  | * cache. | 
|  | */ | 
|  |  | 
|  | ENTRY(strcat) | 
|  | pushl	%edi			/* save edi */ | 
|  | movl	8(%esp),%edi		/* dst address */ | 
|  | movl	12(%esp),%edx		/* src address */ | 
|  | pushl	%edi			/* push destination address */ | 
|  |  | 
|  | cld				/* set search forward */ | 
|  | xorl	%eax,%eax		/* set search for null terminator */ | 
|  | movl	$-1,%ecx		/* set search for lots of characters */ | 
|  | repne				/* search! */ | 
|  | scasb | 
|  |  | 
|  | leal	-1(%edi),%ecx		/* correct dst address */ | 
|  |  | 
|  | .align 2,0x90 | 
|  | L1:	movb	(%edx),%al		/* unroll loop, but not too much */ | 
|  | movb	%al,(%ecx) | 
|  | testb	%al,%al | 
|  | jz	L2 | 
|  | movb	1(%edx),%al | 
|  | movb	%al,1(%ecx) | 
|  | testb	%al,%al | 
|  | jz	L2 | 
|  | movb	2(%edx),%al | 
|  | movb	%al,2(%ecx) | 
|  | testb	%al,%al | 
|  | jz	L2 | 
|  | movb	3(%edx),%al | 
|  | movb	%al,3(%ecx) | 
|  | testb	%al,%al | 
|  | jz	L2 | 
|  | movb	4(%edx),%al | 
|  | movb	%al,4(%ecx) | 
|  | testb	%al,%al | 
|  | jz	L2 | 
|  | movb	5(%edx),%al | 
|  | movb	%al,5(%ecx) | 
|  | testb	%al,%al | 
|  | jz	L2 | 
|  | movb	6(%edx),%al | 
|  | movb	%al,6(%ecx) | 
|  | testb	%al,%al | 
|  | jz	L2 | 
|  | movb	7(%edx),%al | 
|  | movb	%al,7(%ecx) | 
|  | addl	$8,%edx | 
|  | addl	$8,%ecx | 
|  | testb	%al,%al | 
|  | jnz	L1 | 
|  | L2:	popl	%eax			/* pop destination address */ | 
|  | popl	%edi			/* restore edi */ | 
|  | ret | 
|  | END(strcat) |