10Sstevel@tonic-gate/* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 56812Sraf * Common Development and Distribution License (the "License"). 66812Sraf * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 216812Sraf 220Sstevel@tonic-gate/* 236812Sraf * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 240Sstevel@tonic-gate * Use is subject to license terms. 250Sstevel@tonic-gate */ 260Sstevel@tonic-gate 27*7298SMark.J.Nelson@Sun.COM .file "strncpy.s" 280Sstevel@tonic-gate 290Sstevel@tonic-gate/* 300Sstevel@tonic-gate * strncpy(s1, s2) 310Sstevel@tonic-gate * 320Sstevel@tonic-gate * Copy string s2 to s1, truncating or null-padding to always copy n bytes 330Sstevel@tonic-gate * return s1. 340Sstevel@tonic-gate * 350Sstevel@tonic-gate * Fast assembler language version of the following C-program for strncpy 360Sstevel@tonic-gate * which represents the `standard' for the C-library. 370Sstevel@tonic-gate * 380Sstevel@tonic-gate * char * 390Sstevel@tonic-gate * strncpy(char *s1, const char *s2, size_t n) 400Sstevel@tonic-gate * { 410Sstevel@tonic-gate * char *os1 = s1; 420Sstevel@tonic-gate * 430Sstevel@tonic-gate * n++; 440Sstevel@tonic-gate * while ((--n != 0) && ((*s1++ = *s2++) != '\0')) 450Sstevel@tonic-gate * ; 460Sstevel@tonic-gate * if (n != 0) 470Sstevel@tonic-gate * while (--n != 0) 480Sstevel@tonic-gate * *s1++ = '\0'; 490Sstevel@tonic-gate * return (os1); 500Sstevel@tonic-gate * } 510Sstevel@tonic-gate */ 520Sstevel@tonic-gate 530Sstevel@tonic-gate#include <sys/asm_linkage.h> 540Sstevel@tonic-gate 550Sstevel@tonic-gate ! strncpy works similarly to strcpy, except that n bytes of s2 560Sstevel@tonic-gate ! are copied to s1. If a null character is reached in s2 yet more 570Sstevel@tonic-gate ! bytes remain to be copied, strncpy will copy null bytes into 580Sstevel@tonic-gate ! the destination string. 590Sstevel@tonic-gate ! 600Sstevel@tonic-gate ! This implementation works by first aligning the src ptr and 610Sstevel@tonic-gate ! performing small copies until it is aligned. Then, the string 620Sstevel@tonic-gate ! is copied based upon destination alignment. (byte, half-word, 630Sstevel@tonic-gate ! word, etc.) 640Sstevel@tonic-gate 650Sstevel@tonic-gate ENTRY(strncpy) 660Sstevel@tonic-gate 670Sstevel@tonic-gate .align 32 680Sstevel@tonic-gate nop ! pad to align loop on 16-byte boundary 690Sstevel@tonic-gate subcc %g0, %o2, %g4 ! n = -n, n == 0 ? 700Sstevel@tonic-gate bz,pn %ncc, .done ! n == 0, done 710Sstevel@tonic-gate add %o1, %o2, %o3 ! src = src + n 720Sstevel@tonic-gate andcc %o1, 7, %o4 ! dword aligned ? 730Sstevel@tonic-gate bz,pn %ncc, .dwordaligned ! yup 740Sstevel@tonic-gate add %o0, %o2, %o2 ! dst = dst + n 750Sstevel@tonic-gate sub %o4, 8, %o4 ! bytes until src aligned 760Sstevel@tonic-gate 770Sstevel@tonic-gate.alignsrc: 780Sstevel@tonic-gate ldub [%o3 + %g4], %o1 ! src[] 790Sstevel@tonic-gate stb %o1, [%o2 + %g4] ! dst[] = src[] 800Sstevel@tonic-gate addcc %g4, 1, %g4 ! src++, dst++, n-- 810Sstevel@tonic-gate bz,pn %ncc, .done ! n == 0, done 820Sstevel@tonic-gate tst %o1 ! end of src reached (null byte) ? 830Sstevel@tonic-gate bz,a %ncc, .bytepad ! yes, at least one byte to pad here 840Sstevel@tonic-gate add %o2, %g4, %o3 ! need single dest pointer for fill 850Sstevel@tonic-gate addcc %o4, 1, %o4 ! src aligned now? 860Sstevel@tonic-gate bnz,a %ncc, .alignsrc ! no, copy another byte 870Sstevel@tonic-gate nop ! pad 880Sstevel@tonic-gate nop ! pad 890Sstevel@tonic-gate 900Sstevel@tonic-gate.dwordaligned: 910Sstevel@tonic-gate sethi %hi(0x01010101), %o4 ! Alan Mycroft's magic1 920Sstevel@tonic-gate add %o2, %g4, %g5 ! dst 930Sstevel@tonic-gate or %o4, %lo(0x01010101),%o4! finish loading magic1 940Sstevel@tonic-gate and %g5, 3, %g1 ! dst<1:0> to examine offset 950Sstevel@tonic-gate sllx %o4, 32, %o1 ! spread magic1 960Sstevel@tonic-gate cmp %g1, 1 ! dst offset of 1 or 5 970Sstevel@tonic-gate or %o4, %o1, %o4 ! to all 64 bits 980Sstevel@tonic-gate sub %o2, 8, %o2 ! adjust for dest pre-incr in cpy loops 990Sstevel@tonic-gate be,pn %ncc, .storebyte1241 ! store 1, 2, 4, 1 bytes 1000Sstevel@tonic-gate sllx %o4, 7, %o5 ! Alan Mycroft's magic2 1010Sstevel@tonic-gate cmp %g1, 3 ! dst offset of 3 or 7 1020Sstevel@tonic-gate be,pn %ncc, .storebyte1421 ! store 1, 4, 2, 1 bytes 1030Sstevel@tonic-gate cmp %g1, 2 ! dst halfword aligned ? 1040Sstevel@tonic-gate be,pn %ncc, .storehalfword ! yup, store half-word wise 1050Sstevel@tonic-gate andcc %g5, 7, %g0 ! dst word aligned ? 1060Sstevel@tonic-gate bnz,pn %ncc, .storeword2 ! yup, store word wise 1070Sstevel@tonic-gate nop ! ensure loop is 16-byte aligned 1080Sstevel@tonic-gate 1090Sstevel@tonic-gate.storedword: 1100Sstevel@tonic-gate ldx [%o3 + %g4], %o1 ! src dword 1110Sstevel@tonic-gate addcc %g4, 8, %g4 ! n += 8, src += 8, dst += 8 1120Sstevel@tonic-gate bcs,pn %ncc,.lastword ! if counter wraps, last word 1130Sstevel@tonic-gate andn %o5, %o1, %g1 ! ~dword & 0x8080808080808080 1140Sstevel@tonic-gate sub %o1, %o4, %g5 ! dword - 0x0101010101010101 1150Sstevel@tonic-gate andcc %g5, %g1, %g0 ! ((dword - 0x0101010101010101) & ~dword & 0x8080808080808080) 1160Sstevel@tonic-gate bz,a,pt %ncc, .storedword ! no zero byte if magic expression == 0 1170Sstevel@tonic-gate stx %o1, [%o2 + %g4] ! store word to dst (address pre-incremented) 1180Sstevel@tonic-gate 1190Sstevel@tonic-gate ! n has not expired, but src is at the end. we need to push out the 1200Sstevel@tonic-gate ! remaining src bytes and then start padding with null bytes 1210Sstevel@tonic-gate 1220Sstevel@tonic-gate.zerobyte: 1230Sstevel@tonic-gate add %o2, %g4, %o3 ! pointer to dest string 1240Sstevel@tonic-gate srlx %o1, 56, %g1 ! first byte 1250Sstevel@tonic-gate stb %g1, [%o3] ! store it 1260Sstevel@tonic-gate andcc %g1, 0xff, %g0 ! end of string ? 1270Sstevel@tonic-gate movz %ncc, %g0, %o1 ! if so, start padding with null bytes 1280Sstevel@tonic-gate srlx %o1, 48, %g1 ! second byte 1290Sstevel@tonic-gate stb %g1, [%o3 + 1] ! store it 1300Sstevel@tonic-gate andcc %g1, 0xff, %g0 ! end of string ? 1310Sstevel@tonic-gate movz %ncc, %g0, %o1 ! if so, start padding with null bytes 1320Sstevel@tonic-gate srlx %o1, 40, %g1 ! third byte 1330Sstevel@tonic-gate stb %g1, [%o3 + 2] ! store it 1340Sstevel@tonic-gate andcc %g1, 0xff, %g0 ! end of string ? 1350Sstevel@tonic-gate movz %ncc, %g0, %o1 ! if so, start padding with null bytes 1360Sstevel@tonic-gate srlx %o1, 32, %g1 ! fourth byte 1370Sstevel@tonic-gate stb %g1, [%o3 + 3] ! store it 1380Sstevel@tonic-gate andcc %g1, 0xff, %g0 ! end of string ? 1390Sstevel@tonic-gate movz %ncc, %g0, %o1 ! if so, start padding with null bytes 1400Sstevel@tonic-gate srlx %o1, 24, %g1 ! fifth byte 1410Sstevel@tonic-gate stb %g1, [%o3 + 4] ! store it 1420Sstevel@tonic-gate andcc %g1, 0xff, %g0 ! end of string ? 1430Sstevel@tonic-gate movz %ncc, %g0, %o1 ! if so, start padding with null bytes 1440Sstevel@tonic-gate srlx %o1, 16, %g1 ! sixth byte 1450Sstevel@tonic-gate stb %g1, [%o3 + 5] ! store it 1460Sstevel@tonic-gate andcc %g1, 0xff, %g0 ! end of string ? 1470Sstevel@tonic-gate movz %ncc, %g0, %o1 ! if so, start padding with null bytes 1480Sstevel@tonic-gate srlx %o1, 8, %g1 ! seventh byte 1490Sstevel@tonic-gate stb %g1, [%o3 + 6] ! store it 1500Sstevel@tonic-gate andcc %g1, 0xff, %g0 ! end of string ? 1510Sstevel@tonic-gate movz %ncc, %g0, %o1 ! if so, start padding with null bytes 1520Sstevel@tonic-gate stb %o1, [%o3 + 7] ! store eighth byte 1530Sstevel@tonic-gate addcc %g4, 16, %g0 ! number of pad bytes < 16 ? 1540Sstevel@tonic-gate bcs,pn %ncc, .bytepad ! yes, do simple byte wise fill 1550Sstevel@tonic-gate add %o3, 8, %o3 ! dst += 8 1560Sstevel@tonic-gate andcc %o3, 7, %o4 ! dst offset relative to dword boundary 1570Sstevel@tonic-gate bz,pn %ncc, .fillaligned ! dst already dword aligned 1580Sstevel@tonic-gate 1590Sstevel@tonic-gate ! here there is a least one more byte to zero out: otherwise we would 1600Sstevel@tonic-gate ! have exited through label .lastword 1610Sstevel@tonic-gate 1620Sstevel@tonic-gate sub %o4, 8, %o4 ! bytes to align dst to dword boundary 1630Sstevel@tonic-gate.makealigned: 1640Sstevel@tonic-gate stb %g0, [%o3] ! dst[] = 0 1650Sstevel@tonic-gate addcc %g4, 1, %g4 ! n-- 1660Sstevel@tonic-gate bz,pt %ncc, .done ! n == 0, we are done 1670Sstevel@tonic-gate addcc %o4, 1, %o4 ! any more byte needed to align 1680Sstevel@tonic-gate bnz,pt %ncc, .makealigned ! yup, pad another byte 1690Sstevel@tonic-gate add %o3, 1, %o3 ! dst++ 1700Sstevel@tonic-gate nop ! pad to align copy loop below 1710Sstevel@tonic-gate nop ! pad to align copy loop below 1720Sstevel@tonic-gate 1730Sstevel@tonic-gate ! here we know that there at least another 8 bytes to pad, since 1740Sstevel@tonic-gate ! we don't get here unless there were >= 16 bytes to pad to begin 1750Sstevel@tonic-gate ! with, and we have padded at most 7 bytes suring dst aligning 1760Sstevel@tonic-gate 1770Sstevel@tonic-gate.fillaligned: 1780Sstevel@tonic-gate add %g4, 7, %o2 ! round up to next dword boundary 1790Sstevel@tonic-gate and %o2, -8, %o4 ! pointer to next dword boundary 1800Sstevel@tonic-gate and %o2, 8, %o2 ! dword count odd ? 8 : 0 1810Sstevel@tonic-gate stx %g0, [%o3] ! store first dword 1820Sstevel@tonic-gate addcc %o4, %o2, %o4 ! dword count == 1 ? 1830Sstevel@tonic-gate add %g4, %o2, %g4 ! if dword count odd, n -= 8 1840Sstevel@tonic-gate bz,pt %ncc, .bytepad ! if dword count == 1, pad leftover bytes 1850Sstevel@tonic-gate add %o3, %o2, %o3 ! bump dst if dword count odd 1860Sstevel@tonic-gate 1870Sstevel@tonic-gate.filldword: 1880Sstevel@tonic-gate addcc %o4, 16, %o4 ! count -= 16 1890Sstevel@tonic-gate stx %g0, [%o3] ! dst[n] = 0 1900Sstevel@tonic-gate stx %g0, [%o3 + 8] ! dst[n+8] = 0 1910Sstevel@tonic-gate add %o3, 16, %o3 ! dst += 16 1920Sstevel@tonic-gate bcc,pt %ncc, .filldword ! fill dwords until count == 0 1930Sstevel@tonic-gate addcc %g4, 16, %g4 ! n -= 16 1940Sstevel@tonic-gate bz,pn %ncc, .done ! if n == 0, we are done 1950Sstevel@tonic-gate 1960Sstevel@tonic-gate.bytepad: 1970Sstevel@tonic-gate and %g4, 1, %o2 ! byte count odd ? 1 : 0 1980Sstevel@tonic-gate stb %g0, [%o3] ! store first byte 1990Sstevel@tonic-gate addcc %g4, %o2, %g4 ! byte count == 1 ? 2000Sstevel@tonic-gate bz,pt %ncc, .done ! yup, we are done 2010Sstevel@tonic-gate add %o3, %o2, %o3 ! bump pointer if odd 2020Sstevel@tonic-gate 2030Sstevel@tonic-gate.fillbyte: 2040Sstevel@tonic-gate addcc %g4, 2, %g4 ! n -= 2 2050Sstevel@tonic-gate stb %g0, [%o3] ! dst[n] = 0 2060Sstevel@tonic-gate stb %g0, [%o3 + 1] ! dst[n+1] = 0 2070Sstevel@tonic-gate bnz,pt %ncc, .fillbyte ! fill until n == 0 2080Sstevel@tonic-gate add %o3, 2, %o3 ! dst += 2 2090Sstevel@tonic-gate 2100Sstevel@tonic-gate.done: 2110Sstevel@tonic-gate retl ! done 2120Sstevel@tonic-gate nop ! pad to align loops below 2130Sstevel@tonic-gate nop ! pad to align loops below 2140Sstevel@tonic-gate 2150Sstevel@tonic-gate ! this is the last word. It may contain null bytes. store bytes 2160Sstevel@tonic-gate ! until n == 0. if null byte encountered, continue 2170Sstevel@tonic-gate 2180Sstevel@tonic-gate.lastword: 2190Sstevel@tonic-gate sub %g4, 8, %g4 ! undo counter pre-increment 2200Sstevel@tonic-gate add %o2, 8, %o2 ! adjust dst for counter un-bumping 2210Sstevel@tonic-gate 2220Sstevel@tonic-gate srlx %o1, 56, %g1 ! first byte 2230Sstevel@tonic-gate stb %g1, [%o2 + %g4] ! store it 2240Sstevel@tonic-gate inccc %g4 ! n-- 2250Sstevel@tonic-gate bz .done ! if n == 0, we're done 2260Sstevel@tonic-gate andcc %g1, 0xff, %g0 ! end of src reached ? 2270Sstevel@tonic-gate movz %ncc, %g0, %o1 ! if so, start padding with null bytes 2280Sstevel@tonic-gate srlx %o1, 48, %g1 ! second byte 2290Sstevel@tonic-gate stb %g1, [%o2 + %g4] ! store it 2300Sstevel@tonic-gate inccc %g4 ! n-- 2310Sstevel@tonic-gate bz .done ! if n == 0, we're done 2320Sstevel@tonic-gate andcc %g1, 0xff, %g0 ! end of src reached ? 2330Sstevel@tonic-gate movz %ncc, %g0, %o1 ! if so, start padding with null bytes 2340Sstevel@tonic-gate srlx %o1, 40, %g1 ! third byte 2350Sstevel@tonic-gate stb %g1, [%o2 + %g4] ! store it 2360Sstevel@tonic-gate inccc %g4 ! n-- 2370Sstevel@tonic-gate bz .done ! if n == 0, we're done 2380Sstevel@tonic-gate andcc %g1, 0xff, %g0 ! end of src reached ? 2390Sstevel@tonic-gate movz %ncc, %g0, %o1 ! if so, start padding with null bytes 2400Sstevel@tonic-gate srlx %o1, 32, %g1 ! fourth byte 2410Sstevel@tonic-gate stb %g1, [%o2 + %g4] ! store it 2420Sstevel@tonic-gate inccc %g4 ! n-- 2430Sstevel@tonic-gate bz .done ! if n == 0, we're done 2440Sstevel@tonic-gate andcc %g1, 0xff, %g0 ! end of src reached ? 2450Sstevel@tonic-gate movz %ncc, %g0, %o1 ! if so, start padding with null bytes 2460Sstevel@tonic-gate srlx %o1, 24, %g1 ! fifth byte 2470Sstevel@tonic-gate stb %g1, [%o2 + %g4] ! store it 2480Sstevel@tonic-gate inccc %g4 ! n-- 2490Sstevel@tonic-gate bz .done ! if n == 0, we're done 2500Sstevel@tonic-gate andcc %g1, 0xff, %g0 ! end of src reached ? 2510Sstevel@tonic-gate movz %ncc, %g0, %o1 ! if so, start padding with null bytes 2520Sstevel@tonic-gate srlx %o1, 16, %g1 ! sixth byte 2530Sstevel@tonic-gate stb %g1, [%o2 + %g4] ! store it 2540Sstevel@tonic-gate inccc %g4 ! n-- 2550Sstevel@tonic-gate bz .done ! if n == 0, we're done 2560Sstevel@tonic-gate andcc %g1, 0xff, %g0 ! end of src reached ? 2570Sstevel@tonic-gate movz %ncc, %g0, %o1 ! if so, start padding with null bytes 2580Sstevel@tonic-gate srlx %o1, 8, %g1 ! seventh byte 2590Sstevel@tonic-gate stb %g1, [%o2 + %g4] ! store it 2600Sstevel@tonic-gate inccc %g4 ! n-- 2610Sstevel@tonic-gate bz .done ! if n == 0, we're done 2620Sstevel@tonic-gate andcc %g1, 0xff, %g0 ! end of src reached ? 2630Sstevel@tonic-gate movz %ncc, %g0, %o1 ! if so, start padding with null bytes 2640Sstevel@tonic-gate ba .done ! here n must be zero, we are done 2650Sstevel@tonic-gate stb %o1, [%o2 + %g4] ! store eigth byte 2660Sstevel@tonic-gate nop ! pad to align loops below 2670Sstevel@tonic-gate nop ! pad to align loops below 2680Sstevel@tonic-gate 2690Sstevel@tonic-gate.storebyte1421: 2700Sstevel@tonic-gate ldx [%o3 + %g4], %o1 ! x = src[] 2710Sstevel@tonic-gate addcc %g4, 8, %g4 ! src += 8, dst += 8 2720Sstevel@tonic-gate bcs,pn %ncc,.lastword ! if counter wraps, last word 2730Sstevel@tonic-gate andn %o5, %o1, %g1 ! ~x & 0x8080808080808080 2740Sstevel@tonic-gate sub %o1, %o4, %g5 ! x - 0x0101010101010101 2750Sstevel@tonic-gate andcc %g5, %g1, %g0 ! ((x - 0x0101010101010101) & ~x & 0x8080808080808080) 2760Sstevel@tonic-gate bnz,pn %ncc, .zerobyte ! end of src found, may need to pad 2770Sstevel@tonic-gate add %o2, %g4, %g5 ! dst (in pointer form) 2780Sstevel@tonic-gate srlx %o1, 56, %g1 ! %g1<7:0> = first byte; word aligned now 2790Sstevel@tonic-gate stb %g1, [%g5] ! store first byte 2800Sstevel@tonic-gate srlx %o1, 24, %g1 ! %g1<31:0> = bytes 2, 3, 4, 5 2810Sstevel@tonic-gate stw %g1, [%g5 + 1] ! store bytes 2, 3, 4, 5 2820Sstevel@tonic-gate srlx %o1, 8, %g1 ! %g1<15:0> = bytes 6, 7 2830Sstevel@tonic-gate sth %g1, [%g5 + 5] ! store bytes 6, 7 2840Sstevel@tonic-gate ba .storebyte1421 ! next dword 2850Sstevel@tonic-gate stb %o1, [%g5 + 7] ! store eigth byte 2860Sstevel@tonic-gate 2870Sstevel@tonic-gate.storebyte1241: 2880Sstevel@tonic-gate ldx [%o3 + %g4], %o1 ! x = src[] 2890Sstevel@tonic-gate addcc %g4, 8, %g4 ! src += 8, dst += 8 2900Sstevel@tonic-gate bcs,pn %ncc,.lastword ! if counter wraps, last word 2910Sstevel@tonic-gate andn %o5, %o1, %g1 ! ~x & 0x8080808080808080 2920Sstevel@tonic-gate sub %o1, %o4, %g5 ! x - 0x0101010101010101 2930Sstevel@tonic-gate andcc %g5, %g1, %g0 ! ((x - 0x0101010101010101) & ~x & 0x8080808080808080) 2940Sstevel@tonic-gate bnz,pn %ncc, .zerobyte ! x has zero byte, handle end cases 2950Sstevel@tonic-gate add %o2, %g4, %g5 ! dst (in pointer form) 2960Sstevel@tonic-gate srlx %o1, 56, %g1 ! %g1<7:0> = first byte; half-word aligned now 2970Sstevel@tonic-gate stb %g1, [%g5] ! store first byte 2980Sstevel@tonic-gate srlx %o1, 40, %g1 ! %g1<15:0> = bytes 2, 3 2990Sstevel@tonic-gate sth %g1, [%g5 + 1] ! store bytes 2, 3 3000Sstevel@tonic-gate srlx %o1, 8, %g1 ! %g1<31:0> = bytes 4, 5, 6, 7 3010Sstevel@tonic-gate stw %g1, [%g5 + 3] ! store bytes 4, 5, 6, 7 3020Sstevel@tonic-gate ba .storebyte1241 ! next dword 3030Sstevel@tonic-gate stb %o1, [%g5 + 7] ! store eigth byte 3040Sstevel@tonic-gate 3050Sstevel@tonic-gate.storehalfword: 3060Sstevel@tonic-gate ldx [%o3 + %g4], %o1 ! x = src[] 3070Sstevel@tonic-gate addcc %g4, 8, %g4 ! src += 8, dst += 8 3080Sstevel@tonic-gate bcs,pn %ncc,.lastword ! if counter wraps, last word 3090Sstevel@tonic-gate andn %o5, %o1, %g1 ! ~x & 0x8080808080808080 3100Sstevel@tonic-gate sub %o1, %o4, %g5 ! x - 0x0101010101010101 3110Sstevel@tonic-gate andcc %g5, %g1, %g0 ! ((x - 0x0101010101010101) & ~x & 0x8080808080808080) 3120Sstevel@tonic-gate bnz,pn %ncc, .zerobyte ! x has zero byte, handle end cases 3130Sstevel@tonic-gate add %o2, %g4, %g5 ! dst (in pointer form) 3140Sstevel@tonic-gate srlx %o1, 48, %g1 ! %g1<15:0> = bytes 1, 2; word aligned now 3150Sstevel@tonic-gate sth %g1, [%g5] ! store bytes 1, 2 3160Sstevel@tonic-gate srlx %o1, 16, %g1 ! %g1<31:0> = bytes 3, 4, 5, 6 3170Sstevel@tonic-gate stw %g1, [%g5 + 2] ! store bytes 3, 4, 5, 6 3180Sstevel@tonic-gate ba .storehalfword ! next dword 3190Sstevel@tonic-gate sth %o1, [%g5 + 6] ! store bytes 7, 8 3200Sstevel@tonic-gate nop ! align next loop to 16-byte boundary 3210Sstevel@tonic-gate nop ! align next loop to 16-byte boundary 3220Sstevel@tonic-gate 3230Sstevel@tonic-gate.storeword2: 3240Sstevel@tonic-gate ldx [%o3 + %g4], %o1 ! x = src[] 3250Sstevel@tonic-gate addcc %g4, 8, %g4 ! src += 8, dst += 8 3260Sstevel@tonic-gate bcs,pn %ncc,.lastword ! if counter wraps, last word 3270Sstevel@tonic-gate andn %o5, %o1, %g1 ! ~x & 0x8080808080808080 3280Sstevel@tonic-gate sub %o1, %o4, %g5 ! x - 0x0101010101010101 3290Sstevel@tonic-gate andcc %g5, %g1, %g0 ! ((x - 0x0101010101010101) & ~x & 0x8080808080808080) 3300Sstevel@tonic-gate bnz,pn %ncc, .zerobyte ! x has zero byte, handle end cases 3310Sstevel@tonic-gate add %o2, %g4, %g5 ! dst (in pointer form) 3320Sstevel@tonic-gate srlx %o1, 32, %g1 ! %g1<31:0> = bytes 1, 2, 3, 4 3330Sstevel@tonic-gate stw %g1, [%g5] ! store bytes 1, 2, 3, 4 3340Sstevel@tonic-gate ba .storeword2 ! next dword 3350Sstevel@tonic-gate stw %o1, [%g5 + 4] ! store bytes 5, 6, 7, 8 3360Sstevel@tonic-gate 3370Sstevel@tonic-gate ! do not remove these pads, loop above may slow down otherwise 3380Sstevel@tonic-gate 3390Sstevel@tonic-gate nop ! pad 3400Sstevel@tonic-gate nop ! pad 3410Sstevel@tonic-gate 3420Sstevel@tonic-gate SET_SIZE(strncpy) 343