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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22/* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 .ident "%Z%%M% %I% %E% SMI" 28 29 .file "%M%" 30 31/ 32/ strncat(s1, s2, n) 33/ 34/ Concatenates s2 on the end of s1. s1's space must be large enough. 35/ At most n characters are moved. 36/ Returns s1. 37/ 38/ Fast assembly language version of the following C-program strncat 39/ which represents the `standard' for the C-library. 40/ 41/ char * 42/ strncat(char *s1, const char *s2, size_t n) 43/ { 44/ char *os1 = s1; 45/ 46/ n++; 47/ while (*s1++) 48/ ; 49/ --s1; 50/ while (*s1++ = *s2++) 51/ if (--n == 0) { 52/ s1[-1] = '\0'; 53/ break; 54/ } 55/ return (os1); 56/ } 57/ 58/ In this assembly language version, the following expression is used 59/ to check if a 32-bit word data contains a null byte or not: 60/ (((A & 0x7f7f7f7f) + 0x7f7f7f7f) | A) & 0x80808080 61/ If the above expression geneates a value other than 0x80808080, 62/ that means the 32-bit word data contains a null byte. 63/ 64 65#include "SYS.h" 66 67 ENTRY(strncat) 68 pushl %edi / save register variables 69 pushl %esi 70 movl 12(%esp), %edi / %edi = destination string address 71 testl $3, %edi / if %edi not word aligned 72 jnz .L1 / goto .L1 73 .align 4 74.L2: 75 movl (%edi), %edx / move 1 word from (%edi) to %edx 76 movl $0x7f7f7f7f, %ecx 77 andl %edx, %ecx / %ecx = %edx & 0x7f7f7f7f 78 addl $4, %edi / next word 79 addl $0x7f7f7f7f, %ecx / %ecx += 0x7f7f7f7f 80 orl %edx, %ecx / %ecx |= %edx 81 andl $0x80808080, %ecx / %ecx &= 0x80808080 82 cmpl $0x80808080, %ecx / if no null byte in this word 83 je .L2 / goto .L2 84 subl $4, %edi / post-incremented 85.L1: 86 cmpb $0, (%edi) / if a byte in (%edi) is null 87 je .L3 / goto .L3 88 incl %edi / next byte 89 testl $3, %edi / if %edi not word aligned 90 jnz .L1 / goto .L1 91 jmp .L2 / goto .L2 (%edi word aligned) 92 .align 4 93.L3: 94 / %edi points to a null byte in destination string 95 movl 16(%esp), %eax / %eax = source string address 96 movl 20(%esp), %esi / %esi = number of bytes 97 98 testl $3, %eax / if %eax not word aligned 99 jnz .L4 / goto .L4 100 cmpl $4, %esi / if number of bytes < 4 101 jb .L7 / goto .L7 102 .align 4 103.L5: 104 movl (%eax), %edx / move 1 word from (%eax) to %edx 105 movl $0x7f7f7f7f, %ecx 106 andl %edx, %ecx / %ecx = %edx & 0x7f7f7f7f 107 addl $4, %eax / next word 108 addl $0x7f7f7f7f, %ecx / %ecx += 0x7f7f7f7f 109 orl %edx, %ecx / %ecx |= %edx 110 andl $0x80808080, %ecx / %ecx &= 0x80808080 111 cmpl $0x80808080, %ecx / if null byte in this word 112 jne .L6 / goto .L6 113 movl %edx, (%edi) / copy this word to (%edi) 114 subl $4, %esi / decrement number of bytes by 4 115 addl $4, %edi / next word 116 cmpl $4, %esi / if number of bytes >= 4 117 jae .L5 / goto .L5 118 jmp .L7 / goto .L7 119.L6: 120 subl $4, %eax / post-incremented 121 .align 4 122.L7: 123 / number of bytes < 4 or a null byte found in the word 124 cmpl $0, %esi / if number of bytes == 0 125 jz .L8 / goto .L8 (finished) 126 movb (%eax), %dl / %dl = a byte in (%eax) 127 decl %esi / decrement number of bytes by 1 128 movb %dl, (%edi) / copy %dl to (%edi) 129 incl %eax / next byte 130 incl %edi / next byte 131 cmpb $0, %dl / compare %dl with a null byte 132 je .L9 / if %dl is a null, goto .L9 133 jmp .L7 / goto .L7 134 .align 4 135 136.L4: 137 / %eax not aligned 138 cmpl $0, %esi / if number of bytes == 0 139 jz .L8 / goto .L8 (finished) 140 movb (%eax), %dl / %dl = a byte in (%eax) 141 decl %esi / decrement number of bytes by 1 142 movb %dl, (%edi) / copy %dl to (%edi) 143 incl %edi / next byte 144 incl %eax / next byte 145 cmpb $0, %dl / compare %dl with a null byte 146 je .L9 / if %dl is a null, goto .L9 147 jmp .L4 / goto .L4 148 .align 4 149.L8: 150 movb $0, (%edi) / null termination 151.L9: 152 movl 12(%esp), %eax / return the destination address 153 popl %esi / restore register variables 154 popl %edi 155 ret 156 SET_SIZE(strncat) 157