xref: /onnv-gate/usr/src/lib/libc/sparc/gen/memcpy.s (revision 0:68f95e015346)
1*0Sstevel@tonic-gate/*
2*0Sstevel@tonic-gate * CDDL HEADER START
3*0Sstevel@tonic-gate *
4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate * with the License.
8*0Sstevel@tonic-gate *
9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate * and limitations under the License.
13*0Sstevel@tonic-gate *
14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate *
20*0Sstevel@tonic-gate * CDDL HEADER END
21*0Sstevel@tonic-gate */
22*0Sstevel@tonic-gate/*
23*0Sstevel@tonic-gate * Copyright 1987-2003 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate * Use is subject to license terms.
25*0Sstevel@tonic-gate */
26*0Sstevel@tonic-gate
27*0Sstevel@tonic-gate	.ident	"%Z%%M%	%I%	%E% SMI"
28*0Sstevel@tonic-gate
29*0Sstevel@tonic-gate	.file	"%M%"
30*0Sstevel@tonic-gate
31*0Sstevel@tonic-gate/*
32*0Sstevel@tonic-gate * memcpy(s1, s2, len)
33*0Sstevel@tonic-gate *
34*0Sstevel@tonic-gate * Copy s2 to s1, always copy n bytes.
35*0Sstevel@tonic-gate * Note: this does not work for overlapped copies, bcopy() does
36*0Sstevel@tonic-gate *
37*0Sstevel@tonic-gate * Fast assembler language version of the following C-program for memcpy
38*0Sstevel@tonic-gate * which represents the `standard' for the C-library.
39*0Sstevel@tonic-gate *
40*0Sstevel@tonic-gate *	void *
41*0Sstevel@tonic-gate *	memcpy(void *s, const void *s0, size_t n)
42*0Sstevel@tonic-gate *	{
43*0Sstevel@tonic-gate *		if (n != 0) {
44*0Sstevel@tonic-gate *	   	    char *s1 = s;
45*0Sstevel@tonic-gate *		    const char *s2 = s0;
46*0Sstevel@tonic-gate *		    do {
47*0Sstevel@tonic-gate *			*s1++ = *s2++;
48*0Sstevel@tonic-gate *		    } while (--n != 0);
49*0Sstevel@tonic-gate *		}
50*0Sstevel@tonic-gate *		return (s);
51*0Sstevel@tonic-gate *	}
52*0Sstevel@tonic-gate */
53*0Sstevel@tonic-gate
54*0Sstevel@tonic-gate#include <sys/asm_linkage.h>
55*0Sstevel@tonic-gate
56*0Sstevel@tonic-gate	ANSI_PRAGMA_WEAK(memcpy,function)
57*0Sstevel@tonic-gate
58*0Sstevel@tonic-gate#include "synonyms.h"
59*0Sstevel@tonic-gate
60*0Sstevel@tonic-gate	.weak	_private_memcpy
61*0Sstevel@tonic-gate	.type	_private_memcpy, #function
62*0Sstevel@tonic-gate	_private_memcpy = memcpy
63*0Sstevel@tonic-gate
64*0Sstevel@tonic-gate	ENTRY(memcpy)
65*0Sstevel@tonic-gate	st	%o0, [%sp + 68]		! save des address for return val
66*0Sstevel@tonic-gate	cmp	%o2, 17			! for small counts copy bytes
67*0Sstevel@tonic-gate	bleu	.dbytecp
68*0Sstevel@tonic-gate	andcc	%o1, 3, %o5		! is src word aligned
69*0Sstevel@tonic-gate	bz	.aldst
70*0Sstevel@tonic-gate	cmp	%o5, 2			! is src half-word aligned
71*0Sstevel@tonic-gate	be	.s2algn
72*0Sstevel@tonic-gate	cmp	%o5, 3			! src is byte aligned
73*0Sstevel@tonic-gate.s1algn:ldub	[%o1], %o3		! move 1 or 3 bytes to align it
74*0Sstevel@tonic-gate	inc	1, %o1
75*0Sstevel@tonic-gate	stb	%o3, [%o0]		! move a byte to align src
76*0Sstevel@tonic-gate	inc	1, %o0
77*0Sstevel@tonic-gate	bne	.s2algn
78*0Sstevel@tonic-gate	dec	%o2
79*0Sstevel@tonic-gate	b	.ald			! now go align dest
80*0Sstevel@tonic-gate	andcc	%o0, 3, %o5
81*0Sstevel@tonic-gate
82*0Sstevel@tonic-gate.s2algn:lduh	[%o1], %o3		! know src is 2 byte alinged
83*0Sstevel@tonic-gate	inc	2, %o1
84*0Sstevel@tonic-gate	srl	%o3, 8, %o4
85*0Sstevel@tonic-gate	stb	%o4, [%o0]		! have to do bytes,
86*0Sstevel@tonic-gate	stb	%o3, [%o0 + 1]		! don't know dst alingment
87*0Sstevel@tonic-gate	inc	2, %o0
88*0Sstevel@tonic-gate	dec	2, %o2
89*0Sstevel@tonic-gate
90*0Sstevel@tonic-gate.aldst:	andcc	%o0, 3, %o5		! align the destination address
91*0Sstevel@tonic-gate.ald:	bz	.w4cp
92*0Sstevel@tonic-gate	cmp	%o5, 2
93*0Sstevel@tonic-gate	bz	.w2cp
94*0Sstevel@tonic-gate	cmp	%o5, 3
95*0Sstevel@tonic-gate.w3cp:	ld	[%o1], %o4
96*0Sstevel@tonic-gate	inc	4, %o1
97*0Sstevel@tonic-gate	srl	%o4, 24, %o5
98*0Sstevel@tonic-gate	stb	%o5, [%o0]
99*0Sstevel@tonic-gate	bne	.w1cp
100*0Sstevel@tonic-gate	inc	%o0
101*0Sstevel@tonic-gate	dec	1, %o2
102*0Sstevel@tonic-gate	andn	%o2, 3, %o3		! o3 is aligned word count
103*0Sstevel@tonic-gate	dec	4, %o3			! avoid reading beyond tail of src
104*0Sstevel@tonic-gate	sub	%o1, %o0, %o1		! o1 gets the difference
105*0Sstevel@tonic-gate
106*0Sstevel@tonic-gate1:	sll	%o4, 8, %g1		! save residual bytes
107*0Sstevel@tonic-gate	ld	[%o1+%o0], %o4
108*0Sstevel@tonic-gate	deccc	4, %o3
109*0Sstevel@tonic-gate	srl	%o4, 24, %o5		! merge with residual
110*0Sstevel@tonic-gate	or	%o5, %g1, %g1
111*0Sstevel@tonic-gate	st	%g1, [%o0]
112*0Sstevel@tonic-gate	bnz	1b
113*0Sstevel@tonic-gate	inc	4, %o0
114*0Sstevel@tonic-gate	sub	%o1, 3, %o1		! used one byte of last word read
115*0Sstevel@tonic-gate	and	%o2, 3, %o2
116*0Sstevel@tonic-gate	b	7f
117*0Sstevel@tonic-gate	inc	4, %o2
118*0Sstevel@tonic-gate
119*0Sstevel@tonic-gate.w1cp:	srl	%o4, 8, %o5
120*0Sstevel@tonic-gate	sth	%o5, [%o0]
121*0Sstevel@tonic-gate	inc	2, %o0
122*0Sstevel@tonic-gate	dec	3, %o2
123*0Sstevel@tonic-gate	andn	%o2, 3, %o3		! o3 is aligned word count
124*0Sstevel@tonic-gate	dec	4, %o3			! avoid reading beyond tail of src
125*0Sstevel@tonic-gate	sub	%o1, %o0, %o1		! o1 gets the difference
126*0Sstevel@tonic-gate
127*0Sstevel@tonic-gate2:	sll	%o4, 24, %g1		! save residual bytes
128*0Sstevel@tonic-gate	ld	[%o1+%o0], %o4
129*0Sstevel@tonic-gate	deccc	4, %o3
130*0Sstevel@tonic-gate	srl	%o4, 8, %o5		! merge with residual
131*0Sstevel@tonic-gate	or	%o5, %g1, %g1
132*0Sstevel@tonic-gate	st	%g1, [%o0]
133*0Sstevel@tonic-gate	bnz	2b
134*0Sstevel@tonic-gate	inc	4, %o0
135*0Sstevel@tonic-gate	sub	%o1, 1, %o1		! used three bytes of last word read
136*0Sstevel@tonic-gate	and	%o2, 3, %o2
137*0Sstevel@tonic-gate	b	7f
138*0Sstevel@tonic-gate	inc	4, %o2
139*0Sstevel@tonic-gate
140*0Sstevel@tonic-gate.w2cp:	ld	[%o1], %o4
141*0Sstevel@tonic-gate	inc	4, %o1
142*0Sstevel@tonic-gate	srl	%o4, 16, %o5
143*0Sstevel@tonic-gate	sth	%o5, [%o0]
144*0Sstevel@tonic-gate	inc	2, %o0
145*0Sstevel@tonic-gate	dec	2, %o2
146*0Sstevel@tonic-gate	andn	%o2, 3, %o3		! o3 is aligned word count
147*0Sstevel@tonic-gate	dec	4, %o3			! avoid reading beyond tail of src
148*0Sstevel@tonic-gate	sub	%o1, %o0, %o1		! o1 gets the difference
149*0Sstevel@tonic-gate
150*0Sstevel@tonic-gate3:	sll	%o4, 16, %g1		! save residual bytes
151*0Sstevel@tonic-gate	ld	[%o1+%o0], %o4
152*0Sstevel@tonic-gate	deccc	4, %o3
153*0Sstevel@tonic-gate	srl	%o4, 16, %o5		! merge with residual
154*0Sstevel@tonic-gate	or	%o5, %g1, %g1
155*0Sstevel@tonic-gate	st	%g1, [%o0]
156*0Sstevel@tonic-gate	bnz	3b
157*0Sstevel@tonic-gate	inc	4, %o0
158*0Sstevel@tonic-gate	sub	%o1, 2, %o1		! used two bytes of last word read
159*0Sstevel@tonic-gate	and	%o2, 3, %o2
160*0Sstevel@tonic-gate	b	7f
161*0Sstevel@tonic-gate	inc	4, %o2
162*0Sstevel@tonic-gate
163*0Sstevel@tonic-gate.w4cp:	andn	%o2, 3, %o3		! o3 is aligned word count
164*0Sstevel@tonic-gate	sub	%o1, %o0, %o1		! o1 gets the difference
165*0Sstevel@tonic-gate
166*0Sstevel@tonic-gate1:	ld	[%o1+%o0], %o4		! read from address
167*0Sstevel@tonic-gate	deccc	4, %o3			! decrement count
168*0Sstevel@tonic-gate	st	%o4, [%o0]		! write at destination address
169*0Sstevel@tonic-gate	bgu	1b
170*0Sstevel@tonic-gate	inc	4, %o0			! increment to address
171*0Sstevel@tonic-gate	b	7f
172*0Sstevel@tonic-gate	and	%o2, 3, %o2		! number of leftover bytes, if any
173*0Sstevel@tonic-gate
174*0Sstevel@tonic-gate	!
175*0Sstevel@tonic-gate	! differenced byte copy, works with any alignment
176*0Sstevel@tonic-gate	!
177*0Sstevel@tonic-gate.dbytecp:
178*0Sstevel@tonic-gate	b	7f
179*0Sstevel@tonic-gate	sub	%o1, %o0, %o1		! o1 gets the difference
180*0Sstevel@tonic-gate
181*0Sstevel@tonic-gate4:	stb	%o4, [%o0]		! write to address
182*0Sstevel@tonic-gate	inc	%o0			! inc to address
183*0Sstevel@tonic-gate7:	deccc	%o2			! decrement count
184*0Sstevel@tonic-gate	bgeu,a	4b			! loop till done
185*0Sstevel@tonic-gate	ldub	[%o1+%o0], %o4		! read from address
186*0Sstevel@tonic-gate	retl
187*0Sstevel@tonic-gate	ld	[%sp + 68], %o0		! return s1, destination address
188*0Sstevel@tonic-gate
189*0Sstevel@tonic-gate	SET_SIZE(memcpy)
190