usr/src/lib/libc/sparc/gen/strncpy.s
author Mark J. Nelson <Mark.J.Nelson@Sun.COM>
Wed, 06 Aug 2008 16:29:39 -0600
changeset 7298 b69e27387f74
parent 6812 febeba71273d
permissions -rw-r--r--
6733918 Teamware has retired, please welcome your new manager, Mercurial 4758439 some files use "current date" sccs keywords 6560843 asm sources should not rely on .file "%M%" for naming STT_FILE symbols 6560958 Solaris:: perl modules should not use SCCS keywords in version information 6729074 webrev doesn't deal well with remote ssh hg parents
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     1
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     2
 * CDDL HEADER START
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     3
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     4
 * The contents of this file are subject to the terms of the
6812
febeba71273d PSARC 2008/309 expunge synonyms.h
raf
parents: 0
diff changeset
     5
 * Common Development and Distribution License (the "License").
febeba71273d PSARC 2008/309 expunge synonyms.h
raf
parents: 0
diff changeset
     6
 * You may not use this file except in compliance with the License.
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     7
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     8
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     9
 * or http://www.opensolaris.org/os/licensing.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    10
 * See the License for the specific language governing permissions
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    11
 * and limitations under the License.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    12
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    13
 * When distributing Covered Code, include this CDDL HEADER in each
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    14
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    15
 * If applicable, add the following below this CDDL HEADER, with the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    16
 * fields enclosed by brackets "[]" replaced with your own identifying
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    17
 * information: Portions Copyright [yyyy] [name of copyright owner]
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    18
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    19
 * CDDL HEADER END
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    20
 */
6812
febeba71273d PSARC 2008/309 expunge synonyms.h
raf
parents: 0
diff changeset
    21
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    22
/*
6812
febeba71273d PSARC 2008/309 expunge synonyms.h
raf
parents: 0
diff changeset
    23
 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    24
 * Use is subject to license terms.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    25
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    26
7298
b69e27387f74 6733918 Teamware has retired, please welcome your new manager, Mercurial
Mark J. Nelson <Mark.J.Nelson@Sun.COM>
parents: 6812
diff changeset
    27
	.file	"strncpy.s"
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    28
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    29
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    30
 * strncpy(s1, s2)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    31
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    32
 * Copy string s2 to s1, truncating or null-padding to always copy n bytes
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    33
 * return s1.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    34
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    35
 * Fast assembler language version of the following C-program for strncpy
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    36
 * which represents the `standard' for the C-library.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    37
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    38
 *	char *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    39
 *	strncpy(char *s1, const char *s2, size_t n)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    40
 *	{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    41
 *		char *os1 = s1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    42
 *	
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    43
 *		n++;				
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    44
 *		while ((--n != 0) &&  ((*s1++ = *s2++) != '\0'))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    45
 *			;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    46
 *		if (n != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    47
 *			while (--n != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    48
 *				*s1++ = '\0';
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    49
 *		return (os1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    50
 *	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    51
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    52
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    53
#include <sys/asm_linkage.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    54
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    55
	! strncpy works similarly to strcpy, except that n bytes of s2
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    56
	! are copied to s1. If a null character is reached in s2 yet more
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    57
	! bytes remain to be copied, strncpy will copy null bytes into
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    58
	! the destination string.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    59
	!
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    60
	! This implementation works by first aligning the src ptr and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    61
	! performing small copies until it is aligned.  Then, the string
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    62
	! is copied based upon destination alignment.  (byte, half-word,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    63
	! word, etc.)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    64
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    65
	ENTRY(strncpy)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    66
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    67
	.align 32
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    68
	subcc	%g0, %o2, %o4		! n = -n
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    69
	bz	.doneshort		! if n == 0, done
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    70
	cmp	%o2, 7			! n < 7 ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    71
	add	%o1, %o2, %o3		! src = src + n
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    72
	blu	.shortcpy		! n < 7, use byte-wise copy 
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    73
	add	%o0, %o2, %o2		! dst = dst + n
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    74
	andcc	%o1, 3, %o5		! src word aligned ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    75
	bz	.wordaligned		! yup
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    76
	save	%sp, -0x40, %sp		! create new register window
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    77
	sub	%i5, 4, %i5		! bytes until src aligned
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    78
	nop				! align loop on 16-byte boundary
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    79
	nop				! align loop on 16-byte boundary
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    80
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    81
.alignsrc:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    82
	ldub	[%i3 + %i4], %i1	! src[]
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    83
	stb	%i1, [%i2 + %i4]	! dst[] = src[]
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    84
	inccc	%i4			! src++, dst++, n--
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    85
	bz	.done			! n == 0, done
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    86
	tst     %i1			! end of src reached (null byte) ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    87
	bz,a	.bytepad		! yes, at least one byte to pad here
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    88
	add 	%i2, %i4, %l0		! need single dest pointer for fill
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    89
	inccc	%i5			! src aligned now?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    90
	bnz	.alignsrc		! no, copy another byte
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    91
	.empty
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    92
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    93
.wordaligned:	
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    94
	add	%i2, %i4, %l0		! dst
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    95
	sethi	%hi(0x01010101), %l1	! Alan Mycroft's magic1
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    96
	sub	%i2, 4, %i2		! adjust for dest pre-incr in cpy loops
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    97
	or	%l1, %lo(0x01010101),%l1!  finish loading magic1
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    98
	andcc	%l0, 3, %g1		! destination word aligned ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    99
	bnz	.dstnotaligned		! nope
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   100
	sll	%l1, 7, %i5		! create Alan Mycroft's magic2
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   101
	
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   102
.storeword:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   103
	lduw	[%i3 + %i4], %i1	! src dword
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   104
	addcc	%i4, 4, %i4		! n += 4, src += 4, dst += 4
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   105
	bcs	.lastword		! if counter wraps, last word
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   106
	andn	%i5, %i1, %g1		! ~dword & 0x80808080
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   107
	sub	%i1, %l1, %l0		! dword - 0x01010101
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   108
	andcc	%l0, %g1, %g0		! ((dword - 0x01010101) & ~dword & 0x80808080)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   109
	bz,a	.storeword		! no zero byte if magic expression == 0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   110
	stw	%i1, [%i2 + %i4]	! store word to dst (address pre-incremented)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   111
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   112
	! n has not expired, but src is at the end. we need to push out the 
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   113
	! remaining src bytes and then start padding with null bytes
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   114
	
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   115
.zerobyte:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   116
	add	%i2, %i4, %l0		! pointer to dest string
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   117
	srl	%i1, 24, %g1		! first byte
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   118
	stb	%g1, [%l0]		! store it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   119
	sub	%g1, 1, %g1		! byte == 0 ? -1 : byte - 1
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   120
	sra	%g1, 31, %g1		! byte == 0 ? -1 : 0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   121
	andn	%i1, %g1, %i1		! if byte == 0, start padding with null bytes
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   122
	srl	%i1, 16, %g1		! second byte
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   123
	stb	%g1, [%l0 + 1]		! store it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   124
	and	%g1, 0xff, %g1		! isolate byte
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   125
	sub	%g1, 1, %g1		! byte == 0 ? -1 : byte - 1
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   126
	sra	%g1, 31, %g1		! byte == 0 ? -1 : 0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   127
	andn	%i1, %g1, %i1		! if byte == 0, start padding with null bytes
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   128
	srl	%i1, 8, %g1		! third byte
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   129
	stb	%g1, [%l0 + 2]		! store it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   130
	and	%g1, 0xff, %g1		! isolate byte
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   131
	sub	%g1, 1, %g1		! byte == 0 ? -1 : byte - 1
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   132
	sra	%g1, 31, %g1		! byte == 0 ? -1 : 0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   133
	andn	%i1, %g1, %i1		! if byte == 0, start padding with null bytes
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   134
	stb	%i1, [%l0 + 3]		! store fourth byte
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   135
	addcc	%i4, 8, %g0		! number of pad bytes < 8 ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   136
	bcs	.bytepad		! yes, do simple byte wise fill
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   137
	add	%l0, 4, %l0		! dst += 4
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   138
	andcc	%l0, 3, %l1		! dst offset relative to word boundary
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   139
	bz	.fillaligned		! dst already word aligned
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   140
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   141
	! here there is a least one more byte to zero out: otherwise we would 
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   142
	! have exited through label .lastword
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   143
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   144
	sub	%l1, 4, %l1		! bytes to align dst to word boundary
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   145
.makealigned:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   146
	stb	%g0, [%l0]		! dst[] = 0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   147
	addcc	%i4, 1, %i4		! n--
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   148
	bz	.done			! n == 0, we are done
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   149
	addcc	%l1, 1, %l1		! any more byte needed to align
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   150
	bnz	.makealigned		! yup, pad another byte
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   151
	add	%l0, 1, %l0		! dst++
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   152
	nop				! pad to align copy loop below
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   153
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   154
	! here we know that there at least another 4 bytes to pad, since
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   155
	! we don't get here unless there were >= 8 bytes to pad to begin
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   156
	! with, and we have padded at most 3 bytes suring dst aligning
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   157
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   158
.fillaligned:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   159
	add	%i4, 3, %i2		! round up to next word boundary
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   160
	and	%i2, -4, %l1		! pointer to next word boundary
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   161
	and	%i2, 4, %i2		! word count odd ? 4 : 0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   162
	stw	%g0, [%l0]		! store first word
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   163
	addcc	%l1, %i2, %l1		! dword count == 1 ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   164
	add	%i4, %i2, %i4		! if word count odd, n -= 4
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   165
	bz	.bytepad		! if word count == 1, pad bytes left
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   166
	add	%l0, %i2, %l0		! bump dst if word count odd
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   167
		
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   168
.fillword:	
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   169
	addcc	%l1, 8, %l1		! count -= 8
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   170
	stw	%g0, [%l0]		! dst[n] = 0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   171
	stw	%g0, [%l0 + 4]		! dst[n+4] = 0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   172
	add	%l0, 8, %l0		! dst += 8
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   173
	bcc	.fillword		! fill words until count == 0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   174
	addcc	%i4, 8, %i4		! n -= 8
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   175
	bz	.done			! if n == 0, we are done
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   176
	.empty
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   177
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   178
.bytepad:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   179
	and	%i4, 1, %i2		! byte count odd ? 1 : 0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   180
	stb	%g0, [%l0]		! store first byte
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   181
	addcc	%i4, %i2, %i4		! byte count == 1 ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   182
	bz	.done			! yup, we are done
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   183
	add	%l0, %i2, %l0		! bump pointer if odd		
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   184
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   185
.fillbyte:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   186
	addcc	%i4, 2, %i4		! n -= 2
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   187
	stb	%g0, [%l0]		! dst[n] = 0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   188
	stb	%g0, [%l0 + 1]		! dst[n+1] = 0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   189
	bnz	.fillbyte		! fill until n == 0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   190
	add	%l0, 2, %l0		! dst += 2
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   191
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   192
.done:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   193
	ret				! done
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   194
	restore	%i0, %g0, %o0		! restore reg window, return dst
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   195
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   196
	! this is the last word. It may contain null bytes. store bytes 
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   197
	! until n == 0. if null byte encountered, continue
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   198
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   199
.lastword:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   200
	sub	%i4, 4, %i4		! undo counter pre-increment
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   201
	add	%i2, 4, %i2		! adjust dst for counter un-bumping
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   202
	
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   203
	srl	%i1, 24, %g1		! first byte
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   204
	stb	%g1, [%i2 + %i4]	! store it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   205
	inccc	%i4			! n--
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   206
	bz	.done			! if n == 0, we're done
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   207
	sub	%g1, 1, %g1		! byte == 0 ? -1 : byte - 1
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   208
	sra	%g1, 31, %g1		! byte == 0 ? -1 : 0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   209
	andn	%i1, %g1, %i1		! if byte == 0, start padding with null
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   210
	srl	%i1, 16, %g1		! second byte
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   211
	stb	%g1, [%i2 + %i4]	! store it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   212
	inccc	%i4			! n--
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   213
	bz	.done			! if n == 0, we're done
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   214
	and	%g1, 0xff, %g1		! isolate byte
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   215
	sub	%g1, 1, %g1		! byte == 0 ? -1 : byte - 1
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   216
	sra	%g1, 31, %g1		! byte == 0 ? -1 : 0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   217
	andn	%i1, %g1, %i1		! if byte == 0, start padding with null
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   218
	srl	%i1, 8, %g1		! third byte
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   219
	stb	%g1, [%i2 + %i4]	! store it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   220
	inccc	%i4			! n--
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   221
	bz	.done			! if n == 0, we're done
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   222
	and	%g1, 0xff, %g1		! isolate byte
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   223
	sub	%g1, 1, %g1		! byte == 0 ? -1 : byte - 1
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   224
	sra	%g1, 31, %g1		! byte == 0 ? -1 : 0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   225
	andn	%i1, %g1, %i1		! if byte == 0, start padding with null
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   226
	ba	.done			! here n must be zero, we are done
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   227
	stb	%i1, [%i2 + %i4]	! store fourth byte
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   228
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   229
.dstnotaligned:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   230
	cmp	%g1, 2			! dst half word aligned?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   231
	be	.storehalfword2		! yup, store half word at a time
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   232
	.empty
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   233
.storebyte:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   234
	lduw	[%i3 + %i4], %i1	! x = src[]
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   235
	addcc	%i4, 4, %i4		! src += 4, dst += 4, n -= 4
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   236
	bcs	.lastword		! if counter wraps, last word
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   237
	andn	%i5, %i1, %g1		! ~x & 0x80808080
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   238
	sub	%i1, %l1, %l0		! x - 0x01010101
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   239
	andcc	%l0, %g1, %g0		! ((x - 0x01010101) & ~x & 0x80808080)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   240
	bnz	.zerobyte		! end of src found, may need to pad
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   241
	add	%i2, %i4, %l0		! dst (in pointer form)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   242
	srl	%i1, 24, %g1		! %g1<7:0> = 1st byte; half-word aligned now 
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   243
	stb	%g1, [%l0]		! store first byte
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   244
	srl	%i1, 8, %g1		! %g1<15:0> = bytes 2, 3
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   245
	sth	%g1, [%l0 + 1]		! store bytes 2, 3
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   246
	ba	.storebyte		! next word
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   247
	stb	%i1, [%l0 + 3]		! store fourth byte
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   248
	nop
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   249
	nop
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   250
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   251
.storehalfword:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   252
	lduw	[%i3 + %i4], %i1	! x = src[]
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   253
.storehalfword2:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   254
	addcc	%i4, 4, %i4		! src += 4, dst += 4, n -= 4
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   255
	bcs	.lastword		! if counter wraps, last word
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   256
	andn	%i5, %i1, %g1		! ~x & 0x80808080
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   257
	sub	%i1, %l1, %l0		! x - 0x01010101
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   258
	andcc	%l0, %g1, %g0		! ((x -0x01010101) & ~x & 0x8080808080)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   259
	bnz	.zerobyte		! x has zero byte, handle end cases
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   260
	add	%i2, %i4, %l0		! dst (in pointer form)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   261
	srl	%i1, 16, %g1		! %g1<15:0> = bytes 1, 2
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   262
	sth	%g1, [%l0]		! store bytes 1, 2
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   263
	ba	.storehalfword		! next dword
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   264
	sth	%i1, [%l0 + 2]		! store bytes 3, 4
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   265
	
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   266
.shortcpy:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   267
	ldub	[%o3 + %o4], %o5	! src[]
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   268
	stb	%o5, [%o2 + %o4]	! dst[] = src[]
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   269
	inccc	%o4			! src++, dst++, n--
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   270
	bz	.doneshort		! if n == 0, done
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   271
	tst	%o5			! src[] == 0 ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   272
	bnz,a	.shortcpy		! nope, next byte
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   273
	nop				! empty delay slot
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   274
	
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   275
.padbyte:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   276
	stb	%g0, [%o2 + %o4]	! dst[] = 0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   277
.padbyte2:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   278
	addcc	%o4, 1, %o4		! dst++, n--
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   279
	bnz,a	.padbyte2		! if n != 0, next byte
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   280
	stb	%g0, [%o2 + %o4]	! dst[] = 0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   281
	nop				! align label below to 16-byte boundary
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   282
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   283
.doneshort:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   284
	retl				! return from leaf
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   285
	nop				! empty delay slot
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   286
	SET_SIZE(strncpy)