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