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/ strncpy(s1, s2, n) 33/ 34/ Copies s2 to s1, truncating or null-padding to always copy n bytes 35/ Returns s1 36/ 37/ Fast assembly language version of the following C-program strncpy 38/ which represents the `standard' for the C-library. 39/ 40/ char * 41/ strncpy(char *s1, const char *s2, size_t n) 42/ { 43/ char *os1 = s1; 44/ 45/ n++; 46/ while ((--n != 0) && ((*s1++ = *s2++) != '\0')) 47/ ; 48/ if (n != 0) 49/ while (--n != 0) 50/ *s1++ = '\0'; 51/ return (os1); 52/ } 53/ 54/ In this assembly language version, the following expression is used 55/ to check if a 32-bit word data contains a null byte or not: 56/ (((A & 0x7f7f7f7f) + 0x7f7f7f7f) | A) & 0x80808080 57/ If the above expression geneates a value other than 0x80808080, 58/ that means the 32-bit word data contains a null byte. 59/ 60 61/ Assume relatively long strings and small numbers of nulls at end. 62 63#include "SYS.h" 64 65 ENTRY(strncpy) 66 pushl %edi / save register variables 67 pushl %esi 68 69 movl 16(%esp), %eax / %eax = source string address 70 movl 12(%esp), %edi / %edi = destination string address 71 movl 20(%esp), %esi / %esi = number of bytes 72 73 testl $3, %eax / if %eax not word aligned 74 jnz .L1 / goto .L1 75.L8: 76 cmpl $4, %esi / if number of bytes < 4 77 jb .L4 / goto .L4 78 .align 4 79.L2: 80 movl (%eax), %edx / move 1 word from (%eax) to %edx 81 movl $0x7f7f7f7f, %ecx 82 andl %edx, %ecx / %ecx = %edx & 0x7f7f7f7f 83 addl $4, %eax / next word 84 addl $0x7f7f7f7f, %ecx / %ecx += 0x7f7f7f7f 85 orl %edx, %ecx / %ecx |= %edx 86 andl $0x80808080, %ecx / %ecx &= 0x80808080 87 cmpl $0x80808080, %ecx / if null byte in this word 88 jne .L3 / goto .L3 89 movl %edx, (%edi) / copy this word to (%edi) 90 subl $4, %esi / decrement number of bytes by 4 91 addl $4, %edi / next word 92 cmpl $4, %esi / if number of bytes >= 4 93 jae .L2 / goto .L2 94 jmp .L4 / goto .L4 95.L3: 96 subl $4, %eax / post-incremented 97 .align 4 98.L4: 99 / (number of bytes < 4) or (a null byte found in the word) 100 cmpl $0, %esi / if number of bytes == 0 101 je .L7 / goto .L7 (finished) 102 movb (%eax), %dl / %dl = a byte in (%eax) 103 decl %esi / decrement number of bytes by 1 104 movb %dl, (%edi) / copy %dl to (%edi) 105 incl %eax / next byte 106 incl %edi / next byte 107 cmpb $0, %dl / compare %dl with a null byte 108 je .L5 / if %dl is a null, goto .L5 109 jmp .L4 / goto .L4 110 .align 4 111.L1: 112 / %eax not aligned 113 cmpl $0, %esi / if number of bytes == 0 114 je .L7 / goto .L7 (finished) 115 movb (%eax), %dl / %dl = a byte in (%eax) 116 decl %esi / decrement number of bytes by 1 117 movb %dl, (%edi) / copy %dl to (%edi) 118 incl %edi / next byte 119 incl %eax / next byte 120 cmpb $0, %dl / compare %dl with a null byte 121 je .L5 / if %dl is a null, goto .L5 122 testl $3, %eax / if %eax word aligned 123 jz .L8 / goto .L8 124 jmp .L1 / goto .L1 (not word aligned) 125 .align 4 126.L5: 127 movl %esi, %ecx / %ecx = length to copy null bytes 128 xorl %eax, %eax / clear %eax 129 shrl $2, %ecx / %ecx = words to copy null bytes 130 rep ; sstol / rep;sstol is optimal 131 andl $3, %esi / %esi = leftover bytes 132.L6: 133 cmpl $0, %esi / if number of bytes == 0 134 jz .L7 / goto .L7 (finished) 135 movb $0, (%edi) / move a null byte to (%edi) 136 decl %esi / decrement number of bytes by 1 137 incl %edi / next byte 138 jmp .L6 / goto .L6 139 .align 4 140.L7: 141 movl 12(%esp), %eax / return the destination address 142 popl %esi / restore register variables 143 popl %edi 144 ret 145 SET_SIZE(strncpy) 146