xref: /titanic_44/usr/src/lib/libc/sparc/gen/memmove.s (revision 9a70fc3be3b1e966bf78825cdb8d509963a6f0a1)
17c478bd9Sstevel@tonic-gate/*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
57257d1b4Sraf * Common Development and Distribution License (the "License").
67257d1b4Sraf * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217257d1b4Sraf
227c478bd9Sstevel@tonic-gate/*
237257d1b4Sraf * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
247257d1b4Sraf * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate */
267c478bd9Sstevel@tonic-gate
27*9a70fc3bSMark J. Nelson	.file	"memmove.s"
287c478bd9Sstevel@tonic-gate
297c478bd9Sstevel@tonic-gate#include <sys/asm_linkage.h>
307c478bd9Sstevel@tonic-gate
317c478bd9Sstevel@tonic-gate	ANSI_PRAGMA_WEAK(memmove,function)
327c478bd9Sstevel@tonic-gate
337c478bd9Sstevel@tonic-gate/*
347c478bd9Sstevel@tonic-gate * memmove(s1, s2, len)
357c478bd9Sstevel@tonic-gate * Copy s2 to s1, always copy n bytes.
367c478bd9Sstevel@tonic-gate * For overlapped copies it does the right thing.
377c478bd9Sstevel@tonic-gate */
387c478bd9Sstevel@tonic-gate	ENTRY(memmove)
397c478bd9Sstevel@tonic-gate	save	%sp, -SA(MINFRAME), %sp		! not a leaf routine any more
407c478bd9Sstevel@tonic-gate	mov	%i0, %l6	! Save pointer to destination
417c478bd9Sstevel@tonic-gate	cmp	%i1, %i0	! if from address is >= to use forward copy
427c478bd9Sstevel@tonic-gate	bgeu,a	2f		! else use backward if ...
437c478bd9Sstevel@tonic-gate	cmp	%i2, 17		! delay slot, for small counts copy bytes
447c478bd9Sstevel@tonic-gate
457c478bd9Sstevel@tonic-gate	sub	%i0, %i1, %i4	! get difference of two addresses
467c478bd9Sstevel@tonic-gate	cmp	%i2, %i4	! compare size and difference of addresses
477c478bd9Sstevel@tonic-gate	bgu	ovbc		! if size is bigger, have do overlapped copy
487c478bd9Sstevel@tonic-gate	cmp	%i2, 17		! delay slot, for small counts copy bytes
497c478bd9Sstevel@tonic-gate	!
507c478bd9Sstevel@tonic-gate	! normal, copy forwards
517c478bd9Sstevel@tonic-gate	!
527c478bd9Sstevel@tonic-gate2:	ble	dbytecp
537c478bd9Sstevel@tonic-gate	andcc	%i1, 3, %i5		! is src word aligned
547c478bd9Sstevel@tonic-gate	bz	aldst
557c478bd9Sstevel@tonic-gate	cmp	%i5, 2			! is src half-word aligned
567c478bd9Sstevel@tonic-gate	be	s2algn
577c478bd9Sstevel@tonic-gate	cmp	%i5, 3			! src is byte aligned
587c478bd9Sstevel@tonic-gates1algn:	ldub	[%i1], %i3		! move 1 or 3 bytes to align it
597c478bd9Sstevel@tonic-gate	inc	1, %i1
607c478bd9Sstevel@tonic-gate	stb	%i3, [%i0]		! move a byte to align src
617c478bd9Sstevel@tonic-gate	inc	1, %i0
627c478bd9Sstevel@tonic-gate	bne	s2algn
637c478bd9Sstevel@tonic-gate	dec	%i2
647c478bd9Sstevel@tonic-gate	b	ald			! now go align dest
657c478bd9Sstevel@tonic-gate	andcc	%i0, 3, %i5
667c478bd9Sstevel@tonic-gate
677c478bd9Sstevel@tonic-gates2algn:	lduh	[%i1], %i3		! know src is 2 byte alinged
687c478bd9Sstevel@tonic-gate	inc	2, %i1
697c478bd9Sstevel@tonic-gate	srl	%i3, 8, %i4
707c478bd9Sstevel@tonic-gate	stb	%i4, [%i0]		! have to do bytes,
717c478bd9Sstevel@tonic-gate	stb	%i3, [%i0 + 1]		! don't know dst alingment
727c478bd9Sstevel@tonic-gate	inc	2, %i0
737c478bd9Sstevel@tonic-gate	dec	2, %i2
747c478bd9Sstevel@tonic-gate
757c478bd9Sstevel@tonic-gatealdst:	andcc	%i0, 3, %i5		! align the destination address
767c478bd9Sstevel@tonic-gateald:	bz	w4cp
777c478bd9Sstevel@tonic-gate	cmp	%i5, 2
787c478bd9Sstevel@tonic-gate	bz	w2cp
797c478bd9Sstevel@tonic-gate	cmp	%i5, 3
807c478bd9Sstevel@tonic-gatew3cp:	ld	[%i1], %i4
817c478bd9Sstevel@tonic-gate	inc	4, %i1
827c478bd9Sstevel@tonic-gate	srl	%i4, 24, %i5
837c478bd9Sstevel@tonic-gate	stb	%i5, [%i0]
847c478bd9Sstevel@tonic-gate	bne	w1cp
857c478bd9Sstevel@tonic-gate	inc	%i0
867c478bd9Sstevel@tonic-gate	dec	1, %i2
877c478bd9Sstevel@tonic-gate	andn	%i2, 3, %i3		! i3 is aligned word count
887c478bd9Sstevel@tonic-gate	dec	4, %i3			! avoid reading beyond tail of src
897c478bd9Sstevel@tonic-gate	sub	%i1, %i0, %i1		! i1 gets the difference
907c478bd9Sstevel@tonic-gate
917c478bd9Sstevel@tonic-gate1:	sll	%i4, 8, %g1		! save residual bytes
927c478bd9Sstevel@tonic-gate	ld	[%i1+%i0], %i4
937c478bd9Sstevel@tonic-gate	deccc	4, %i3
947c478bd9Sstevel@tonic-gate	srl	%i4, 24, %i5		! merge with residual
957c478bd9Sstevel@tonic-gate	or	%i5, %g1, %g1
967c478bd9Sstevel@tonic-gate	st	%g1, [%i0]
977c478bd9Sstevel@tonic-gate	bnz	1b
987c478bd9Sstevel@tonic-gate	inc	4, %i0
997c478bd9Sstevel@tonic-gate	sub	%i1, 3, %i1		! used one byte of last word read
1007c478bd9Sstevel@tonic-gate	and	%i2, 3, %i2
1017c478bd9Sstevel@tonic-gate	b	7f
1027c478bd9Sstevel@tonic-gate	inc	4, %i2
1037c478bd9Sstevel@tonic-gate
1047c478bd9Sstevel@tonic-gatew1cp:	srl	%i4, 8, %i5
1057c478bd9Sstevel@tonic-gate	sth	%i5, [%i0]
1067c478bd9Sstevel@tonic-gate	inc	2, %i0
1077c478bd9Sstevel@tonic-gate	dec	3, %i2
1087c478bd9Sstevel@tonic-gate	andn	%i2, 3, %i3
1097c478bd9Sstevel@tonic-gate	dec	4, %i3			! avoid reading beyond tail of src
1107c478bd9Sstevel@tonic-gate	sub	%i1, %i0, %i1		! i1 gets the difference
1117c478bd9Sstevel@tonic-gate
1127c478bd9Sstevel@tonic-gate2:	sll	%i4, 24, %g1		! save residual bytes
1137c478bd9Sstevel@tonic-gate	ld	[%i1+%i0], %i4
1147c478bd9Sstevel@tonic-gate	deccc	4, %i3
1157c478bd9Sstevel@tonic-gate	srl	%i4, 8, %i5		! merge with residual
1167c478bd9Sstevel@tonic-gate	or	%i5, %g1, %g1
1177c478bd9Sstevel@tonic-gate	st	%g1, [%i0]
1187c478bd9Sstevel@tonic-gate	bnz	2b
1197c478bd9Sstevel@tonic-gate	inc	4, %i0
1207c478bd9Sstevel@tonic-gate	sub	%i1, 1, %i1		! used three bytes of last word read
1217c478bd9Sstevel@tonic-gate	and	%i2, 3, %i2
1227c478bd9Sstevel@tonic-gate	b	7f
1237c478bd9Sstevel@tonic-gate	inc	4, %i2
1247c478bd9Sstevel@tonic-gate
1257c478bd9Sstevel@tonic-gatew2cp:	ld	[%i1], %i4
1267c478bd9Sstevel@tonic-gate	inc	4, %i1
1277c478bd9Sstevel@tonic-gate	srl	%i4, 16, %i5
1287c478bd9Sstevel@tonic-gate	sth	%i5, [%i0]
1297c478bd9Sstevel@tonic-gate	inc	2, %i0
1307c478bd9Sstevel@tonic-gate	dec	2, %i2
1317c478bd9Sstevel@tonic-gate	andn	%i2, 3, %i3		! i3 is aligned word count
1327c478bd9Sstevel@tonic-gate	dec	4, %i3			! avoid reading beyond tail of src
1337c478bd9Sstevel@tonic-gate	sub	%i1, %i0, %i1		! i1 gets the difference
1347c478bd9Sstevel@tonic-gate
1357c478bd9Sstevel@tonic-gate3:	sll	%i4, 16, %g1		! save residual bytes
1367c478bd9Sstevel@tonic-gate	ld	[%i1+%i0], %i4
1377c478bd9Sstevel@tonic-gate	deccc	4, %i3
1387c478bd9Sstevel@tonic-gate	srl	%i4, 16, %i5		! merge with residual
1397c478bd9Sstevel@tonic-gate	or	%i5, %g1, %g1
1407c478bd9Sstevel@tonic-gate	st	%g1, [%i0]
1417c478bd9Sstevel@tonic-gate	bnz	3b
1427c478bd9Sstevel@tonic-gate	inc	4, %i0
1437c478bd9Sstevel@tonic-gate	sub	%i1, 2, %i1		! used two bytes of last word read
1447c478bd9Sstevel@tonic-gate	and	%i2, 3, %i2
1457c478bd9Sstevel@tonic-gate	b	7f
1467c478bd9Sstevel@tonic-gate	inc	4, %i2
1477c478bd9Sstevel@tonic-gate
1487c478bd9Sstevel@tonic-gatew4cp:	andn	%i2, 3, %i3		! i3 is aligned word count
1497c478bd9Sstevel@tonic-gate	sub	%i1, %i0, %i1		! i1 gets the difference
1507c478bd9Sstevel@tonic-gate
1517c478bd9Sstevel@tonic-gate1:	ld	[%i1+%i0], %i4		! read from address
1527c478bd9Sstevel@tonic-gate	deccc	4, %i3			! decrement count
1537c478bd9Sstevel@tonic-gate	st	%i4, [%i0]		! write at destination address
1547c478bd9Sstevel@tonic-gate	bg	1b
1557c478bd9Sstevel@tonic-gate	inc	4, %i0			! increment to address
1567c478bd9Sstevel@tonic-gate	b	7f
1577c478bd9Sstevel@tonic-gate	and	%i2, 3, %i2		! number of leftover bytes, if any
1587c478bd9Sstevel@tonic-gate
1597c478bd9Sstevel@tonic-gate	!
1607c478bd9Sstevel@tonic-gate	! differenced byte copy, works with any alignment
1617c478bd9Sstevel@tonic-gate	!
1627c478bd9Sstevel@tonic-gatedbytecp:
1637c478bd9Sstevel@tonic-gate	b	7f
1647c478bd9Sstevel@tonic-gate	sub	%i1, %i0, %i1		! i1 gets the difference
1657c478bd9Sstevel@tonic-gate
1667c478bd9Sstevel@tonic-gate4:	stb	%i4, [%i0]		! write to address
1677c478bd9Sstevel@tonic-gate	inc	%i0			! inc to address
1687c478bd9Sstevel@tonic-gate7:	deccc	%i2			! decrement count
1697c478bd9Sstevel@tonic-gate	bge,a	4b			! loop till done
1707c478bd9Sstevel@tonic-gate	ldub	[%i1+%i0], %i4		! read from address
1717c478bd9Sstevel@tonic-gate	ret
1727c478bd9Sstevel@tonic-gate	restore %l6, %g0, %o0		! return pointer to destination
1737c478bd9Sstevel@tonic-gate
1747c478bd9Sstevel@tonic-gate	!
1757c478bd9Sstevel@tonic-gate	! an overlapped copy that must be done "backwards"
1767c478bd9Sstevel@tonic-gate	!
1777c478bd9Sstevel@tonic-gateovbc:	add	%i1, %i2, %i1		! get to end of source space
1787c478bd9Sstevel@tonic-gate	add	%i0, %i2, %i0		! get to end of destination space
1797c478bd9Sstevel@tonic-gate	sub	%i1, %i0, %i1		! i1 gets the difference
1807c478bd9Sstevel@tonic-gate
1817c478bd9Sstevel@tonic-gate5:	dec	%i0			! decrement to address
1827c478bd9Sstevel@tonic-gate	ldub	[%i1+%i0], %i3		! read a byte
1837c478bd9Sstevel@tonic-gate	deccc	%i2			! decrement count
1847c478bd9Sstevel@tonic-gate	bg	5b			! loop until done
1857c478bd9Sstevel@tonic-gate	stb	%i3, [%i0]		! write byte
1867c478bd9Sstevel@tonic-gate	ret
1877c478bd9Sstevel@tonic-gate	restore %l6, %g0, %o0		! return pointer to destination
1887c478bd9Sstevel@tonic-gate
1897c478bd9Sstevel@tonic-gate	SET_SIZE(memmove)
190