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