xref: /titanic_41/usr/src/lib/libc/sparc/gen/memmove.s (revision a2bb96e7d59f447f59bc306e53b7d00e38594667)
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 (c) 1987-1995, by Sun Microsystems, Inc.
24 * All rights reserved.
25 */
26
27.ident	"%Z%%M%	%I%	%E% SMI"
28
29	.file	"%M%"
30
31#include <sys/asm_linkage.h>
32
33	ANSI_PRAGMA_WEAK(memmove,function)
34
35#include "synonyms.h"
36
37/*
38 * memmove(s1, s2, len)
39 * Copy s2 to s1, always copy n bytes.
40 * For overlapped copies it does the right thing.
41 */
42	ENTRY(memmove)
43	save	%sp, -SA(MINFRAME), %sp		! not a leaf routine any more
44	mov	%i0, %l6	! Save pointer to destination
45	cmp	%i1, %i0	! if from address is >= to use forward copy
46	bgeu,a	2f		! else use backward if ...
47	cmp	%i2, 17		! delay slot, for small counts copy bytes
48
49	sub	%i0, %i1, %i4	! get difference of two addresses
50	cmp	%i2, %i4	! compare size and difference of addresses
51	bgu	ovbc		! if size is bigger, have do overlapped copy
52	cmp	%i2, 17		! delay slot, for small counts copy bytes
53	!
54	! normal, copy forwards
55	!
562:	ble	dbytecp
57	andcc	%i1, 3, %i5		! is src word aligned
58	bz	aldst
59	cmp	%i5, 2			! is src half-word aligned
60	be	s2algn
61	cmp	%i5, 3			! src is byte aligned
62s1algn:	ldub	[%i1], %i3		! move 1 or 3 bytes to align it
63	inc	1, %i1
64	stb	%i3, [%i0]		! move a byte to align src
65	inc	1, %i0
66	bne	s2algn
67	dec	%i2
68	b	ald			! now go align dest
69	andcc	%i0, 3, %i5
70
71s2algn:	lduh	[%i1], %i3		! know src is 2 byte alinged
72	inc	2, %i1
73	srl	%i3, 8, %i4
74	stb	%i4, [%i0]		! have to do bytes,
75	stb	%i3, [%i0 + 1]		! don't know dst alingment
76	inc	2, %i0
77	dec	2, %i2
78
79aldst:	andcc	%i0, 3, %i5		! align the destination address
80ald:	bz	w4cp
81	cmp	%i5, 2
82	bz	w2cp
83	cmp	%i5, 3
84w3cp:	ld	[%i1], %i4
85	inc	4, %i1
86	srl	%i4, 24, %i5
87	stb	%i5, [%i0]
88	bne	w1cp
89	inc	%i0
90	dec	1, %i2
91	andn	%i2, 3, %i3		! i3 is aligned word count
92	dec	4, %i3			! avoid reading beyond tail of src
93	sub	%i1, %i0, %i1		! i1 gets the difference
94
951:	sll	%i4, 8, %g1		! save residual bytes
96	ld	[%i1+%i0], %i4
97	deccc	4, %i3
98	srl	%i4, 24, %i5		! merge with residual
99	or	%i5, %g1, %g1
100	st	%g1, [%i0]
101	bnz	1b
102	inc	4, %i0
103	sub	%i1, 3, %i1		! used one byte of last word read
104	and	%i2, 3, %i2
105	b	7f
106	inc	4, %i2
107
108w1cp:	srl	%i4, 8, %i5
109	sth	%i5, [%i0]
110	inc	2, %i0
111	dec	3, %i2
112	andn	%i2, 3, %i3
113	dec	4, %i3			! avoid reading beyond tail of src
114	sub	%i1, %i0, %i1		! i1 gets the difference
115
1162:	sll	%i4, 24, %g1		! save residual bytes
117	ld	[%i1+%i0], %i4
118	deccc	4, %i3
119	srl	%i4, 8, %i5		! merge with residual
120	or	%i5, %g1, %g1
121	st	%g1, [%i0]
122	bnz	2b
123	inc	4, %i0
124	sub	%i1, 1, %i1		! used three bytes of last word read
125	and	%i2, 3, %i2
126	b	7f
127	inc	4, %i2
128
129w2cp:	ld	[%i1], %i4
130	inc	4, %i1
131	srl	%i4, 16, %i5
132	sth	%i5, [%i0]
133	inc	2, %i0
134	dec	2, %i2
135	andn	%i2, 3, %i3		! i3 is aligned word count
136	dec	4, %i3			! avoid reading beyond tail of src
137	sub	%i1, %i0, %i1		! i1 gets the difference
138
1393:	sll	%i4, 16, %g1		! save residual bytes
140	ld	[%i1+%i0], %i4
141	deccc	4, %i3
142	srl	%i4, 16, %i5		! merge with residual
143	or	%i5, %g1, %g1
144	st	%g1, [%i0]
145	bnz	3b
146	inc	4, %i0
147	sub	%i1, 2, %i1		! used two bytes of last word read
148	and	%i2, 3, %i2
149	b	7f
150	inc	4, %i2
151
152w4cp:	andn	%i2, 3, %i3		! i3 is aligned word count
153	sub	%i1, %i0, %i1		! i1 gets the difference
154
1551:	ld	[%i1+%i0], %i4		! read from address
156	deccc	4, %i3			! decrement count
157	st	%i4, [%i0]		! write at destination address
158	bg	1b
159	inc	4, %i0			! increment to address
160	b	7f
161	and	%i2, 3, %i2		! number of leftover bytes, if any
162
163	!
164	! differenced byte copy, works with any alignment
165	!
166dbytecp:
167	b	7f
168	sub	%i1, %i0, %i1		! i1 gets the difference
169
1704:	stb	%i4, [%i0]		! write to address
171	inc	%i0			! inc to address
1727:	deccc	%i2			! decrement count
173	bge,a	4b			! loop till done
174	ldub	[%i1+%i0], %i4		! read from address
175	ret
176	restore %l6, %g0, %o0		! return pointer to destination
177
178	!
179	! an overlapped copy that must be done "backwards"
180	!
181ovbc:	add	%i1, %i2, %i1		! get to end of source space
182	add	%i0, %i2, %i0		! get to end of destination space
183	sub	%i1, %i0, %i1		! i1 gets the difference
184
1855:	dec	%i0			! decrement to address
186	ldub	[%i1+%i0], %i3		! read a byte
187	deccc	%i2			! decrement count
188	bg	5b			! loop until done
189	stb	%i3, [%i0]		! write byte
190	ret
191	restore %l6, %g0, %o0		! return pointer to destination
192
193	SET_SIZE(memmove)
194