1/* 2 * CDDL HEADER START 3 * 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. 7 * 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. 12 * 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] 18 * 19 * CDDL HEADER END 20 */ 21/* 22 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 .file "strcat.s" 27 28/ 29/ strcat(s1, s2) 30/ 31/ Concatenates s2 on the end of s1. s1's space must be large enough. 32/ Returns s1. 33/ 34/ Fast assembly language version of the following C-program strcat 35/ which represents the `standard' for the C-library. 36/ 37/ char * 38/ strcat(char *s1, const char *s2) 39/ { 40/ char *os1 = s1; 41/ 42/ while (*s1++) 43/ ; 44/ --s1; 45/ while (*s1++ = *s2++) 46/ ; 47/ return (os1); 48/ } 49/ 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. 55/ 56 57#include "SYS.h" 58 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 121 ret 122 SET_SIZE(strcat) 123