usr/src/lib/libc/i386/gen/strcat.s
author Mark J. Nelson <Mark.J.Nelson@Sun.COM>
Wed, 06 Aug 2008 16:29:39 -0600
changeset 7298 b69e27387f74
parent 0 68f95e015346
permissions -rw-r--r--
6733918 Teamware has retired, please welcome your new manager, Mercurial 4758439 some files use "current date" sccs keywords 6560843 asm sources should not rely on .file "%M%" for naming STT_FILE symbols 6560958 Solaris:: perl modules should not use SCCS keywords in version information 6729074 webrev doesn't deal well with remote ssh hg parents
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     1
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     2
 * CDDL HEADER START
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     3
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     4
 * The contents of this file are subject to the terms of the
7298
b69e27387f74 6733918 Teamware has retired, please welcome your new manager, Mercurial
Mark J. Nelson <Mark.J.Nelson@Sun.COM>
parents: 0
diff changeset
     5
 * Common Development and Distribution License (the "License").
b69e27387f74 6733918 Teamware has retired, please welcome your new manager, Mercurial
Mark J. Nelson <Mark.J.Nelson@Sun.COM>
parents: 0
diff changeset
     6
 * You may not use this file except in compliance with the License.
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     7
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     8
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     9
 * or http://www.opensolaris.org/os/licensing.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    10
 * See the License for the specific language governing permissions
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    11
 * and limitations under the License.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    12
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    13
 * When distributing Covered Code, include this CDDL HEADER in each
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    14
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    15
 * If applicable, add the following below this CDDL HEADER, with the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    16
 * fields enclosed by brackets "[]" replaced with your own identifying
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    17
 * information: Portions Copyright [yyyy] [name of copyright owner]
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    18
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    19
 * CDDL HEADER END
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    20
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    21
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    22
 * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    23
 * Use is subject to license terms.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    24
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    25
7298
b69e27387f74 6733918 Teamware has retired, please welcome your new manager, Mercurial
Mark J. Nelson <Mark.J.Nelson@Sun.COM>
parents: 0
diff changeset
    26
	.file	"strcat.s"
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    27
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    28
/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    29
/ strcat(s1, s2)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    30
/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    31
/ Concatenates s2 on the end of s1.  s1's space must be large enough.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    32
/ Returns s1.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    33
/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    34
/ Fast assembly language version of the following C-program strcat
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    35
/ which represents the `standard' for the C-library.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    36
/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    37
/	char *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    38
/	strcat(char *s1, const char *s2)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    39
/	{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    40
/		char	*os1 = s1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    41
/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    42
/		while (*s1++)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    43
/			;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    44
/		--s1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    45
/		while (*s1++ = *s2++)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    46
/			;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    47
/		return (os1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    48
/	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    49
/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    50
/ In this assembly language version, the following expression is used
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    51
/ to check if a 32-bit word data contains a null byte or not:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    52
/	(((A & 0x7f7f7f7f) + 0x7f7f7f7f) | A) & 0x80808080
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    53
/ If the above expression geneates a value other than 0x80808080,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    54
/ that means the 32-bit word data contains a null byte.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    55
/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    56
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    57
#include "SYS.h"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    58
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    59
	ENTRY(strcat)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    60
	pushl	%edi			/ save register variable
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    61
	/ find a null byte in destination string 
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    62
	movl	8(%esp), %edi		/ %edi = destination string address
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    63
	testl	$3, %edi		/ if %edi not word aligned
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    64
	jnz	.L1			/ goto .L1
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    65
	.align	4
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    66
.L2:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    67
	movl	(%edi), %edx		/ move 1 word from (%edi) to %edx
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    68
	movl	$0x7f7f7f7f, %ecx
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    69
	andl	%edx, %ecx		/ %ecx = %edx & 0x7f7f7f7f
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    70
	addl	$4, %edi		/ next word
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    71
	addl	$0x7f7f7f7f, %ecx	/ %ecx += 0x7f7f7f7f
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    72
	orl	%edx, %ecx		/ %ecx |= %edx
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    73
	andl	$0x80808080, %ecx	/ %ecx &= 0x80808080
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    74
	cmpl	$0x80808080, %ecx	/ if no null byte in this word
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    75
	je	.L2			/ goto .L2
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    76
	subl	$4, %edi		/ post-incremented
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    77
.L1:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    78
	cmpb	$0, (%edi)		/ if a byte in (%edi) is null
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    79
	je	.L3			/ goto .L3
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    80
	incl	%edi			/ next byte
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    81
	testl	$3, %edi		/ if %edi not word aligned
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    82
	jnz	.L1			/ goto .L1
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    83
	jmp	.L2			/ goto .L2 (%edi word aligned)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    84
	.align	4
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    85
.L3:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    86
	/ %edi points to a null byte in destination string
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    87
	movl	12(%esp), %eax		/ %eax = source string address
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    88
	testl	$3, %eax		/ if %eax not word aligned
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    89
	jnz	.L4			/ goto .L4
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    90
	.align	4
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    91
.L5:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    92
	movl	(%eax), %edx		/ move 1 word from (%eax) to %edx
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    93
	movl	$0x7f7f7f7f, %ecx
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    94
	andl	%edx, %ecx		/ %ecx = %edx & 0x7f7f7f7f
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    95
	addl	$4, %eax		/ next word
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    96
	addl	$0x7f7f7f7f, %ecx	/ %ecx += 0x7f7f7f7f	
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    97
	orl	%edx, %ecx		/ %ecx |= %edx
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    98
	andl	$0x80808080, %ecx	/ %ecx &= 0x80808080
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    99
	cmpl	$0x80808080, %ecx	/ if null byte in this word
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   100
	jne	.L7			/ goto .L7
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   101
	movl	%edx, (%edi)		/ copy this word to (%edi)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   102
	addl	$4, %edi		/ next word
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   103
	jmp	.L5			/ goto .L5
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   104
.L7:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   105
	subl	$4, %eax		/ post-incremented
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   106
	.align	4
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   107
.L4:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   108
	movb	(%eax), %dl		/ %dl = a byte in (%eax)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   109
	cmpb	$0, %dl			/ compare %dl with a null byte
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   110
	movb	%dl, (%edi)		/ copy %dl to (%edi)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   111
	je	.L6			/ if %dl is a null, goto .L6
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   112
	incl	%eax			/ next byte
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   113
	incl	%edi			/ next byte
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   114
	testl	$3, %eax		/ if %eax not word aligned
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   115
	jnz	.L4			/ goto .L4
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   116
	jmp	.L5			/ goto .L5 (%eax word aligned)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   117
	.align	4
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   118
.L6:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   119
	movl	8(%esp), %eax		/ return the destination address
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   120
	popl	%edi			/ restore register variable
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   121
	ret
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   122
	SET_SIZE(strcat)