xref: /onnv-gate/usr/src/lib/libc/sparc/gen/memmove.s (revision 7298:b69e27387f74)
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.
246812Sraf * Use is subject to license terms.
250Sstevel@tonic-gate */
260Sstevel@tonic-gate
27*7298SMark.J.Nelson@Sun.COM	.file	"memmove.s"
280Sstevel@tonic-gate
290Sstevel@tonic-gate#include <sys/asm_linkage.h>
300Sstevel@tonic-gate
310Sstevel@tonic-gate	ANSI_PRAGMA_WEAK(memmove,function)
320Sstevel@tonic-gate
330Sstevel@tonic-gate/*
340Sstevel@tonic-gate * memmove(s1, s2, len)
350Sstevel@tonic-gate * Copy s2 to s1, always copy n bytes.
360Sstevel@tonic-gate * For overlapped copies it does the right thing.
370Sstevel@tonic-gate */
380Sstevel@tonic-gate	ENTRY(memmove)
390Sstevel@tonic-gate	save	%sp, -SA(MINFRAME), %sp		! not a leaf routine any more
400Sstevel@tonic-gate	mov	%i0, %l6	! Save pointer to destination
410Sstevel@tonic-gate	cmp	%i1, %i0	! if from address is >= to use forward copy
420Sstevel@tonic-gate	bgeu,a	2f		! else use backward if ...
430Sstevel@tonic-gate	cmp	%i2, 17		! delay slot, for small counts copy bytes
440Sstevel@tonic-gate
450Sstevel@tonic-gate	sub	%i0, %i1, %i4	! get difference of two addresses
460Sstevel@tonic-gate	cmp	%i2, %i4	! compare size and difference of addresses
470Sstevel@tonic-gate	bgu	ovbc		! if size is bigger, have do overlapped copy
480Sstevel@tonic-gate	cmp	%i2, 17		! delay slot, for small counts copy bytes
490Sstevel@tonic-gate	!
500Sstevel@tonic-gate	! normal, copy forwards
510Sstevel@tonic-gate	!
520Sstevel@tonic-gate2:	ble	dbytecp
530Sstevel@tonic-gate	andcc	%i1, 3, %i5		! is src word aligned
540Sstevel@tonic-gate	bz	aldst
550Sstevel@tonic-gate	cmp	%i5, 2			! is src half-word aligned
560Sstevel@tonic-gate	be	s2algn
570Sstevel@tonic-gate	cmp	%i5, 3			! src is byte aligned
580Sstevel@tonic-gates1algn:	ldub	[%i1], %i3		! move 1 or 3 bytes to align it
590Sstevel@tonic-gate	inc	1, %i1
600Sstevel@tonic-gate	stb	%i3, [%i0]		! move a byte to align src
610Sstevel@tonic-gate	inc	1, %i0
620Sstevel@tonic-gate	bne	s2algn
630Sstevel@tonic-gate	dec	%i2
640Sstevel@tonic-gate	b	ald			! now go align dest
650Sstevel@tonic-gate	andcc	%i0, 3, %i5
660Sstevel@tonic-gate
670Sstevel@tonic-gates2algn:	lduh	[%i1], %i3		! know src is 2 byte alinged
680Sstevel@tonic-gate	inc	2, %i1
690Sstevel@tonic-gate	srl	%i3, 8, %i4
700Sstevel@tonic-gate	stb	%i4, [%i0]		! have to do bytes,
710Sstevel@tonic-gate	stb	%i3, [%i0 + 1]		! don't know dst alingment
720Sstevel@tonic-gate	inc	2, %i0
730Sstevel@tonic-gate	dec	2, %i2
740Sstevel@tonic-gate
750Sstevel@tonic-gatealdst:	andcc	%i0, 3, %i5		! align the destination address
760Sstevel@tonic-gateald:	bz	w4cp
770Sstevel@tonic-gate	cmp	%i5, 2
780Sstevel@tonic-gate	bz	w2cp
790Sstevel@tonic-gate	cmp	%i5, 3
800Sstevel@tonic-gatew3cp:	ld	[%i1], %i4
810Sstevel@tonic-gate	inc	4, %i1
820Sstevel@tonic-gate	srl	%i4, 24, %i5
830Sstevel@tonic-gate	stb	%i5, [%i0]
840Sstevel@tonic-gate	bne	w1cp
850Sstevel@tonic-gate	inc	%i0
860Sstevel@tonic-gate	dec	1, %i2
870Sstevel@tonic-gate	andn	%i2, 3, %i3		! i3 is aligned word count
880Sstevel@tonic-gate	dec	4, %i3			! avoid reading beyond tail of src
890Sstevel@tonic-gate	sub	%i1, %i0, %i1		! i1 gets the difference
900Sstevel@tonic-gate
910Sstevel@tonic-gate1:	sll	%i4, 8, %g1		! save residual bytes
920Sstevel@tonic-gate	ld	[%i1+%i0], %i4
930Sstevel@tonic-gate	deccc	4, %i3
940Sstevel@tonic-gate	srl	%i4, 24, %i5		! merge with residual
950Sstevel@tonic-gate	or	%i5, %g1, %g1
960Sstevel@tonic-gate	st	%g1, [%i0]
970Sstevel@tonic-gate	bnz	1b
980Sstevel@tonic-gate	inc	4, %i0
990Sstevel@tonic-gate	sub	%i1, 3, %i1		! used one byte of last word read
1000Sstevel@tonic-gate	and	%i2, 3, %i2
1010Sstevel@tonic-gate	b	7f
1020Sstevel@tonic-gate	inc	4, %i2
1030Sstevel@tonic-gate
1040Sstevel@tonic-gatew1cp:	srl	%i4, 8, %i5
1050Sstevel@tonic-gate	sth	%i5, [%i0]
1060Sstevel@tonic-gate	inc	2, %i0
1070Sstevel@tonic-gate	dec	3, %i2
1080Sstevel@tonic-gate	andn	%i2, 3, %i3
1090Sstevel@tonic-gate	dec	4, %i3			! avoid reading beyond tail of src
1100Sstevel@tonic-gate	sub	%i1, %i0, %i1		! i1 gets the difference
1110Sstevel@tonic-gate
1120Sstevel@tonic-gate2:	sll	%i4, 24, %g1		! save residual bytes
1130Sstevel@tonic-gate	ld	[%i1+%i0], %i4
1140Sstevel@tonic-gate	deccc	4, %i3
1150Sstevel@tonic-gate	srl	%i4, 8, %i5		! merge with residual
1160Sstevel@tonic-gate	or	%i5, %g1, %g1
1170Sstevel@tonic-gate	st	%g1, [%i0]
1180Sstevel@tonic-gate	bnz	2b
1190Sstevel@tonic-gate	inc	4, %i0
1200Sstevel@tonic-gate	sub	%i1, 1, %i1		! used three bytes of last word read
1210Sstevel@tonic-gate	and	%i2, 3, %i2
1220Sstevel@tonic-gate	b	7f
1230Sstevel@tonic-gate	inc	4, %i2
1240Sstevel@tonic-gate
1250Sstevel@tonic-gatew2cp:	ld	[%i1], %i4
1260Sstevel@tonic-gate	inc	4, %i1
1270Sstevel@tonic-gate	srl	%i4, 16, %i5
1280Sstevel@tonic-gate	sth	%i5, [%i0]
1290Sstevel@tonic-gate	inc	2, %i0
1300Sstevel@tonic-gate	dec	2, %i2
1310Sstevel@tonic-gate	andn	%i2, 3, %i3		! i3 is aligned word count
1320Sstevel@tonic-gate	dec	4, %i3			! avoid reading beyond tail of src
1330Sstevel@tonic-gate	sub	%i1, %i0, %i1		! i1 gets the difference
1340Sstevel@tonic-gate
1350Sstevel@tonic-gate3:	sll	%i4, 16, %g1		! save residual bytes
1360Sstevel@tonic-gate	ld	[%i1+%i0], %i4
1370Sstevel@tonic-gate	deccc	4, %i3
1380Sstevel@tonic-gate	srl	%i4, 16, %i5		! merge with residual
1390Sstevel@tonic-gate	or	%i5, %g1, %g1
1400Sstevel@tonic-gate	st	%g1, [%i0]
1410Sstevel@tonic-gate	bnz	3b
1420Sstevel@tonic-gate	inc	4, %i0
1430Sstevel@tonic-gate	sub	%i1, 2, %i1		! used two bytes of last word read
1440Sstevel@tonic-gate	and	%i2, 3, %i2
1450Sstevel@tonic-gate	b	7f
1460Sstevel@tonic-gate	inc	4, %i2
1470Sstevel@tonic-gate
1480Sstevel@tonic-gatew4cp:	andn	%i2, 3, %i3		! i3 is aligned word count
1490Sstevel@tonic-gate	sub	%i1, %i0, %i1		! i1 gets the difference
1500Sstevel@tonic-gate
1510Sstevel@tonic-gate1:	ld	[%i1+%i0], %i4		! read from address
1520Sstevel@tonic-gate	deccc	4, %i3			! decrement count
1530Sstevel@tonic-gate	st	%i4, [%i0]		! write at destination address
1540Sstevel@tonic-gate	bg	1b
1550Sstevel@tonic-gate	inc	4, %i0			! increment to address
1560Sstevel@tonic-gate	b	7f
1570Sstevel@tonic-gate	and	%i2, 3, %i2		! number of leftover bytes, if any
1580Sstevel@tonic-gate
1590Sstevel@tonic-gate	!
1600Sstevel@tonic-gate	! differenced byte copy, works with any alignment
1610Sstevel@tonic-gate	!
1620Sstevel@tonic-gatedbytecp:
1630Sstevel@tonic-gate	b	7f
1640Sstevel@tonic-gate	sub	%i1, %i0, %i1		! i1 gets the difference
1650Sstevel@tonic-gate
1660Sstevel@tonic-gate4:	stb	%i4, [%i0]		! write to address
1670Sstevel@tonic-gate	inc	%i0			! inc to address
1680Sstevel@tonic-gate7:	deccc	%i2			! decrement count
1690Sstevel@tonic-gate	bge,a	4b			! loop till done
1700Sstevel@tonic-gate	ldub	[%i1+%i0], %i4		! read from address
1710Sstevel@tonic-gate	ret
1720Sstevel@tonic-gate	restore %l6, %g0, %o0		! return pointer to destination
1730Sstevel@tonic-gate
1740Sstevel@tonic-gate	!
1750Sstevel@tonic-gate	! an overlapped copy that must be done "backwards"
1760Sstevel@tonic-gate	!
1770Sstevel@tonic-gateovbc:	add	%i1, %i2, %i1		! get to end of source space
1780Sstevel@tonic-gate	add	%i0, %i2, %i0		! get to end of destination space
1790Sstevel@tonic-gate	sub	%i1, %i0, %i1		! i1 gets the difference
1800Sstevel@tonic-gate
1810Sstevel@tonic-gate5:	dec	%i0			! decrement to address
1820Sstevel@tonic-gate	ldub	[%i1+%i0], %i3		! read a byte
1830Sstevel@tonic-gate	deccc	%i2			! decrement count
1840Sstevel@tonic-gate	bg	5b			! loop until done
1850Sstevel@tonic-gate	stb	%i3, [%i0]		! write byte
1860Sstevel@tonic-gate	ret
1870Sstevel@tonic-gate	restore %l6, %g0, %o0		! return pointer to destination
1880Sstevel@tonic-gate
1890Sstevel@tonic-gate	SET_SIZE(memmove)
190