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 2003 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 * The strlcpy() function copies at most dstsize-1 characters 32 * (dstsize being the size of the string buffer dst) from src 33 * to dst, truncating src if necessary. The result is always 34 * null-terminated. The function returns strlen(src). Buffer 35 * overflow can be checked as follows: 36 * 37 * if (strlcpy(dst, src, dstsize) >= dstsize) 38 * return -1; 39 */ 40 41#include <sys/asm_linkage.h> 42#include "synonyms.h" 43 44 ! strlcpy implementation is similar to that of strcpy, except 45 ! in this case, the maximum size of the detination must be 46 ! tracked since it bounds our maximum copy size. However, 47 ! we must still continue to check for zero since the routine 48 ! is expected to null-terminate any string that is within 49 ! the dest size bound. 50 ! 51 ! this method starts by checking for and arranging source alignment. 52 ! Once this has occurred, we copy based upon destination alignment. 53 ! This is either by word, halfword, or byte. As this occurs, we 54 ! check for a zero-byte. If one is found, we branch to a method 55 ! which checks for the exact location of a zero-byte within a 56 ! larger word/half-word quantity. 57 58 ENTRY(strlcpy) 59 60 .align 32 61 save %sp, -SA(WINDOWSIZE), %sp 62 subcc %g0, %i2, %g4 ! n = -n or n == 0 ? 63 bz,pn %icc, .getstrlen ! if 0 do nothing but strlen(src) 64 add %i1, %i2, %i3 ! i3 = src + n 65 andcc %i1, 3, %i4 ! word aligned? 66 bz,pn %icc, .wordaligned 67 add %i0, %i2, %i2 ! n = dst + n 68 sub %i4, 4, %i4 ! bytes until src aligned 69 70.alignsrc: 71 ldub [%i3 + %g4], %l1 ! l1 = src[] 72 andcc %l1, 0xff, %g0 ! null byte reached? 73 stub %l1, [%i2 + %g4] ! dst[] = src[] 74 bz,a %icc, .done 75 add %i2, %g4, %i2 ! get single dest ptr for strlen 76 addcc %g4, 1, %g4 ! src++ dest++ n-- 77 bz,pn %icc, .forcenullunalign ! n == 0, append null byte 78 addcc %i4, 1, %i4 ! incr, check align 79 bnz,a %icc, .alignsrc 80 nop 81 82.wordaligned: 83 sethi %hi(0x01010101), %i4 84 add %i2, %g4, %l0 ! l0 = dest 85 or %i4, %lo(0x01010101), %i4 86 sub %i2, 4, %i2 ! pre-incr for in cpy loop 87 andcc %l0, 3, %g1 ! word aligned? 88 bnz %icc, .dstnotaligned 89 sll %i4, 7, %i5 ! Mycroft part deux 90 91.storeword: 92 ld [%i3 + %g4], %l1 ! l1 = src[] 93 addcc %g4, 4, %g4 ! n += 4, src += 4, dst +=4 94 bcs,pn %icc, .lastword 95 andn %i5, %l1, %g1 ! ~word & 0x80808080 96 sub %l1, %i4, %l0 ! word - 0x01010101 97 andcc %l0, %g1, %g0 ! doit 98 bz,a,pt %icc, .storeword ! if expr == 0, no zero byte 99 st %l1, [%i2 + %g4] ! dst[] = src[] 100 101.zerobyte: 102 add %i2, %g4, %i2 ! ptr to dest 103 srl %l1, 24, %g1 ! 1st byte 104 andcc %g1, 0xff, %g0 ! test for end 105 bz,pn %icc, .done 106 stb %g1, [%i2] ! store byte 107 add %i2, 1, %i2 ! dst ++ 108 srl %l1, 16, %g1 ! 2nd byte 109 andcc %g1, 0xff, %g0 ! zero byte ? 110 bz,pn %icc, .done 111 stb %g1, [%i2] ! store byte 112 add %i2, 1, %i2 ! dst ++ 113 srl %l1, 8, %g1 ! 3rd byte 114 andcc %g1, 0xff, %g0 ! zero byte ? 115 bz,pn %icc, .done 116 stb %g1, [%i2] ! store byte 117 stb %l1, [%i2 + 1] ! store last byte 118 add %i2, 1, %i2 ! dst ++ 119 120.done: 121 sub %i2, %i0, %i0 ! len = dst - orig dst 122 ret 123 restore %i0, %g0, %o0 124 125.lastword: 126 add %i2, %g4, %i2 127 sub %g4, 4, %g4 ! undo pre-incr 128 add %i3, %g4, %i3 129 130 srl %l1, 24, %g1 ! 1st byte 131 andcc %g1, 0xff, %g0 ! zero byte? 132 bz,pn %icc, .done 133 stb %g1, [%i2] ! store byte 134 inccc %g4 ! n-- 135 bz .forcenull 136 srl %l1, 16, %g1 ! 2nd byte 137 add %i2, 1, %i2 ! dst++ 138 andcc %g1, 0xff, %g0 ! zero? 139 bz,pn %icc, .done 140 stb %g1, [%i2] ! store 141 inccc %g4 142 bz .forcenull 143 srl %l1, 8, %g1 ! 3rd byte 144 add %i2, 1, %i2 ! dst++ 145 andcc %g1, 0xff, %g0 ! zero? 146 bz,pn %icc, .done 147 stb %g1, [%i2] ! store 148 inccc %g4 ! n-- 149 bz .forcenull 150 andcc %l1, 0xff, %g0 ! zero? 151 add %i2, 1, %i2 ! dst++ 152 bz,pn %ncc, .done 153 stb %l1, [%i2] 154 155.forcenull: 156 stb %g0, [%i2] 157 158.searchword: 159 ld [%i3], %l1 160.searchword2: 161 andn %i5, %l1, %g1 ! word & 0x80808080 162 sub %l1, %i4, %l0 ! word - 0x01010101 163 andcc %l0, %g1, %g0 ! do it 164 bz,a,pt %icc, .searchword 165 add %i3, 4, %i3 ! src += 4 166 167 mov 0xff, %i5 168 sll %i5, 24, %i5 ! mask 1st byte = 0xff000000 169.searchbyte: 170 andcc %l1, %i5, %g0 ! cur byte 0? 171 srl %i5, 8, %i5 ! mask next byte 172 bnz,a %icc, .searchbyte ! cur !=0 continue 173 add %i3, 1, %i3 174 175.endfound: 176 sub %i3, %i1, %i0 ! len = src - orig src 177 ret 178 restore %i0, %g0, %o0 179 nop 180 181.dstnotaligned: 182 cmp %g1, 2 ! halfword aligned? 183 be .storehalfword2 184 .empty 185.storebyte: 186 ld [%i3 + %g4], %l1 ! load src word 187 addcc %g4, 4, %g4 ! src +=4 dst +=4 188 bcs,pn %icc, .lastword 189 andn %i5, %l1, %g1 ! ~x & 0x80808080 190 sub %l1, %i4, %l0 ! x - 0x01010101 191 andcc %l0, %g1, %g0 ! get your Mycroft on 192 bnz,pn %icc, .zerobyte ! non-zero, we have zero byte 193 add %i2, %g4, %l0 ! dst in ptr form 194 srl %l1, 24, %g1 ! get 1st byte, then be hw aligned 195 stb %g1, [%l0] 196 srl %l1, 8, %g1 ! 2nd & 3rd bytes 197 sth %g1, [%l0 + 1] 198 ba .storebyte 199 stb %l1, [%l0 + 3] ! store 4th byte 200 201.storehalfword: 202 ld [%i3 + %g4], %l1 ! src word 203.storehalfword2: 204 addcc %g4, 4, %g4 ! src += 4 dst += 4 205 bcs,pn %icc, .lastword 206 andn %i5, %l1, %g1 ! ~x & 0x80808080 207 sub %l1, %i4, %l0 ! x - 0x01010101 208 andcc %l0, %g1, %g0 ! Mycroft again... 209 bnz,pn %icc, .zerobyte ! non-zer, we have zero byte 210 add %i2, %g4, %l0 ! dst in ptr form 211 srl %l1, 16, %g1 ! first two bytes 212 sth %g1, [%l0] 213 ba .storehalfword 214 sth %l1, [%l0 + 2] 215 216.forcenullunalign: 217 add %i2, %g4, %i2 ! single dst ptr 218 stb %g0, [%i2 - 1] ! store terminating null byte 219 220.getstrlen: 221 sethi %hi(0x01010101), %i4 ! Mycroft... 222 or %i4, %lo(0x01010101), %i4 223 sll %i4, 7, %i5 224 225.getstrlenloop: 226 andcc %i3, 3, %g0 ! word aligned? 227 bz,a,pn %icc, .searchword2 ! search word at a time 228 ld [%i3], %l1 ! src word 229 ldub [%i3], %l1 ! src byte 230 andcc %l1, 0xff, %g0 ! end of src? 231 bnz,a %icc, .getstrlenloop 232 add %i3, 1, %i3 ! src ++ 233 sub %i3, %i1, %i0 ! len = src - orig src 234 ret 235 restore %i0, %g0, %o0 236 SET_SIZE(strlcpy) 237