import less(1)
[unleashed/tickless.git] / usr / src / lib / libc / i386 / gen / strcat.s
blob7a37a9d219b47d9749f9a4d3cd65827c98fee2a4
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
22 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 .file "strcat.s"
29 / strcat(s1, s2)
31 / Concatenates s2 on the end of s1. s1's space must be large enough.
32 / Returns s1.
34 / Fast assembly language version of the following C-program strcat
35 / which represents the `standard' for the C-library.
37 / char *
38 / strcat(char *s1, const char *s2)
39 / {
40 / char *os1 = s1;
42 / while (*s1++)
43 / ;
44 / --s1;
45 / while (*s1++ = *s2++)
46 / ;
47 / return (os1);
48 / }
50 / In this assembly language version, the following expression is used
51 / to check if a 32-bit word data contains a null byte or not:
52 / (((A & 0x7f7f7f7f) + 0x7f7f7f7f) | A) & 0x80808080
53 / If the above expression geneates a value other than 0x80808080,
54 / that means the 32-bit word data contains a null byte.
57 #include "SYS.h"
59 ENTRY(strcat)
60 pushl %edi / save register variable
61 / find a null byte in destination string
62 movl 8(%esp), %edi / %edi = destination string address
63 testl $3, %edi / if %edi not word aligned
64 jnz .L1 / goto .L1
65 .align 4
66 .L2:
67 movl (%edi), %edx / move 1 word from (%edi) to %edx
68 movl $0x7f7f7f7f, %ecx
69 andl %edx, %ecx / %ecx = %edx & 0x7f7f7f7f
70 addl $4, %edi / next word
71 addl $0x7f7f7f7f, %ecx / %ecx += 0x7f7f7f7f
72 orl %edx, %ecx / %ecx |= %edx
73 andl $0x80808080, %ecx / %ecx &= 0x80808080
74 cmpl $0x80808080, %ecx / if no null byte in this word
75 je .L2 / goto .L2
76 subl $4, %edi / post-incremented
77 .L1:
78 cmpb $0, (%edi) / if a byte in (%edi) is null
79 je .L3 / goto .L3
80 incl %edi / next byte
81 testl $3, %edi / if %edi not word aligned
82 jnz .L1 / goto .L1
83 jmp .L2 / goto .L2 (%edi word aligned)
84 .align 4
85 .L3:
86 / %edi points to a null byte in destination string
87 movl 12(%esp), %eax / %eax = source string address
88 testl $3, %eax / if %eax not word aligned
89 jnz .L4 / goto .L4
90 .align 4
91 .L5:
92 movl (%eax), %edx / move 1 word from (%eax) to %edx
93 movl $0x7f7f7f7f, %ecx
94 andl %edx, %ecx / %ecx = %edx & 0x7f7f7f7f
95 addl $4, %eax / next word
96 addl $0x7f7f7f7f, %ecx / %ecx += 0x7f7f7f7f
97 orl %edx, %ecx / %ecx |= %edx
98 andl $0x80808080, %ecx / %ecx &= 0x80808080
99 cmpl $0x80808080, %ecx / if null byte in this word
100 jne .L7 / goto .L7
101 movl %edx, (%edi) / copy this word to (%edi)
102 addl $4, %edi / next word
103 jmp .L5 / goto .L5
104 .L7:
105 subl $4, %eax / post-incremented
106 .align 4
107 .L4:
108 movb (%eax), %dl / %dl = a byte in (%eax)
109 cmpb $0, %dl / compare %dl with a null byte
110 movb %dl, (%edi) / copy %dl to (%edi)
111 je .L6 / if %dl is a null, goto .L6
112 incl %eax / next byte
113 incl %edi / next byte
114 testl $3, %eax / if %eax not word aligned
115 jnz .L4 / goto .L4
116 jmp .L5 / goto .L5 (%eax word aligned)
117 .align 4
118 .L6:
119 movl 8(%esp), %eax / return the destination address
120 popl %edi / restore register variable
122 SET_SIZE(strcat)