xref: /onnv-gate/usr/src/lib/libc/sparcv9/crt/__align_cpy_2.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	"__align_cpy_2.s"
280Sstevel@tonic-gate
290Sstevel@tonic-gate/*
300Sstevel@tonic-gate * __align_cpy_2(s1, s2, len)
310Sstevel@tonic-gate *
320Sstevel@tonic-gate * Copy s2 to s1, always copy n bytes.
330Sstevel@tonic-gate * Note: this does not work for overlapped copies, bcopy() does
340Sstevel@tonic-gate *	 This routine is copied from memcpy.s, with all values doubled.
350Sstevel@tonic-gate *	 No attempt has been made to improve the comments or performance.
360Sstevel@tonic-gate *
370Sstevel@tonic-gate */
380Sstevel@tonic-gate
390Sstevel@tonic-gate#include <sys/asm_linkage.h>
400Sstevel@tonic-gate
410Sstevel@tonic-gate	ENTRY(__align_cpy_2)
420Sstevel@tonic-gate	cmp	%o0, %o1
430Sstevel@tonic-gate	be,pn	%xcc, .done		! Identical addresses--done.
440Sstevel@tonic-gate	mov	%o0, %g5		! save des address for return val
450Sstevel@tonic-gate	cmp	%o2, 18			! for small counts copy bytes
460Sstevel@tonic-gate	ble,pn	%xcc, .dbytecp
470Sstevel@tonic-gate	andcc	%o1, 6, %o5		! is src 8-byte aligned
480Sstevel@tonic-gate	bz,pn	%xcc, .aldst
490Sstevel@tonic-gate	cmp	%o5, 4			! is src 4-byte aligned
500Sstevel@tonic-gate	be,pt	%xcc, .s2algn
510Sstevel@tonic-gate	cmp	%o5, 6			! src is 2-byte aligned
520Sstevel@tonic-gate.s1algn:lduh	[%o1], %o3		! move 2 or 6 bytes to align it
530Sstevel@tonic-gate	inc	2, %o1
540Sstevel@tonic-gate	sth	%o3, [%g5]		! move 2 bytes to align src
550Sstevel@tonic-gate	inc	2, %g5
560Sstevel@tonic-gate	bne,pt	%xcc, .s2algn
570Sstevel@tonic-gate	dec	2, %o2
580Sstevel@tonic-gate	b	.ald			! now go align dest
590Sstevel@tonic-gate	andcc	%g5, 6, %o5
600Sstevel@tonic-gate
610Sstevel@tonic-gate.s2algn:lduw	[%o1], %o3		! know src is 4-byte aligned
620Sstevel@tonic-gate	inc	4, %o1
630Sstevel@tonic-gate	srlx	%o3, 16, %o4
640Sstevel@tonic-gate	sth	%o4, [%g5]		! have to do 2-bytes,
650Sstevel@tonic-gate	sth	%o3, [%g5 + 2]		! don't know dst alignment
660Sstevel@tonic-gate	inc	4, %g5
670Sstevel@tonic-gate	dec	4, %o2
680Sstevel@tonic-gate
690Sstevel@tonic-gate.aldst:	andcc	%g5, 6, %o5		! align the destination address
700Sstevel@tonic-gate.ald:	bz,pn	%xcc, .w4cp
710Sstevel@tonic-gate	cmp	%o5, 4
720Sstevel@tonic-gate	bz,pn	%xcc, .w2cp
730Sstevel@tonic-gate	cmp	%o5, 6
740Sstevel@tonic-gate.w3cp:	ldx	[%o1], %o4
750Sstevel@tonic-gate	inc	8, %o1
760Sstevel@tonic-gate	srlx	%o4, 48, %o5
770Sstevel@tonic-gate	sth	%o5, [%g5]
780Sstevel@tonic-gate	bne,pt	%xcc, .w1cp
790Sstevel@tonic-gate	inc	2, %g5
800Sstevel@tonic-gate	dec	2, %o2
810Sstevel@tonic-gate	andn	%o2, 6, %o3		! o3 is aligned word count
820Sstevel@tonic-gate	sub	%o1, %g5, %o1		! g5 gets the difference
830Sstevel@tonic-gate
840Sstevel@tonic-gate1:	sllx	%o4, 16, %g1		! save residual bytes
850Sstevel@tonic-gate	ldx	[%o1+%g5], %o4
860Sstevel@tonic-gate	deccc	8, %o3
870Sstevel@tonic-gate	srlx	%o4, 48, %o5		! merge with residual
880Sstevel@tonic-gate	or	%o5, %g1, %g1
890Sstevel@tonic-gate	stx	%g1, [%g5]
900Sstevel@tonic-gate	bnz,pt	%xcc, 1b
910Sstevel@tonic-gate	inc	8, %g5
920Sstevel@tonic-gate	sub	%o1, 6, %o1		! used two bytes of last word read
930Sstevel@tonic-gate	b	7f
940Sstevel@tonic-gate	and	%o2, 6, %o2
950Sstevel@tonic-gate
960Sstevel@tonic-gate.w1cp:	srlx	%o4, 16, %o5
970Sstevel@tonic-gate	st	%o5, [%g5]
980Sstevel@tonic-gate	inc	4, %g5
990Sstevel@tonic-gate	dec	6, %o2
1000Sstevel@tonic-gate	andn	%o2, 6, %o3
1010Sstevel@tonic-gate	sub	%o1, %g5, %o1		! g5 gets the difference
1020Sstevel@tonic-gate
1030Sstevel@tonic-gate2:	sllx	%o4, 48, %g1		! save residual bytes
1040Sstevel@tonic-gate	ldx	[%o1+%g5], %o4
1050Sstevel@tonic-gate	deccc	8, %o3
1060Sstevel@tonic-gate	srlx	%o4, 16, %o5		! merge with residual
1070Sstevel@tonic-gate	or	%o5, %g1, %g1
1080Sstevel@tonic-gate	stx	%g1, [%g5]
1090Sstevel@tonic-gate	bnz,pt	%xcc, 2b
1100Sstevel@tonic-gate	inc	8, %g5
1110Sstevel@tonic-gate	sub	%o1, 2, %o1		! used six bytes of last word read
1120Sstevel@tonic-gate	b	7f
1130Sstevel@tonic-gate	and	%o2, 6, %o2
1140Sstevel@tonic-gate
1150Sstevel@tonic-gate.w2cp:	ldx	[%o1], %o4
1160Sstevel@tonic-gate	inc	8, %o1
1170Sstevel@tonic-gate	srlx	%o4, 32, %o5
1180Sstevel@tonic-gate	st	%o5, [%g5]
1190Sstevel@tonic-gate	inc	4, %g5
1200Sstevel@tonic-gate	dec	4, %o2
1210Sstevel@tonic-gate	andn	%o2, 6, %o3		! o3 is aligned word count
1220Sstevel@tonic-gate	sub	%o1, %g5, %o1		! g5 gets the difference
1230Sstevel@tonic-gate
1240Sstevel@tonic-gate3:	sllx	%o4, 32, %g1		! save residual bytes
1250Sstevel@tonic-gate	ldx	[%o1+%g5], %o4
1260Sstevel@tonic-gate	deccc	8, %o3
1270Sstevel@tonic-gate	srlx	%o4, 32, %o5		! merge with residual
1280Sstevel@tonic-gate	or	%o5, %g1, %g1
1290Sstevel@tonic-gate	stx	%g1, [%g5]
1300Sstevel@tonic-gate	bnz,pt	%xcc, 3b
1310Sstevel@tonic-gate	inc	8, %g5
1320Sstevel@tonic-gate	sub	%o1, 4, %o1		! used four bytes of last word read
1330Sstevel@tonic-gate	b	7f
1340Sstevel@tonic-gate	and	%o2, 6, %o2
1350Sstevel@tonic-gate
1360Sstevel@tonic-gate.w4cp:	andn	%o2, 6, %o3		! o3 is aligned word count
1370Sstevel@tonic-gate	sub	%o1, %g5, %o1		! g5 gets the difference
1380Sstevel@tonic-gate
1390Sstevel@tonic-gate1:	ldx	[%o1+%g5], %o4		! read from address
1400Sstevel@tonic-gate	deccc	8, %o3			! decrement count
1410Sstevel@tonic-gate	stx	%o4, [%g5]		! write at destination address
1420Sstevel@tonic-gate	bg,pt	%xcc, 1b
1430Sstevel@tonic-gate	inc	8, %g5			! increment to address
1440Sstevel@tonic-gate	b	7f
1450Sstevel@tonic-gate	and	%o2, 6, %o2		! number of leftover bytes, if any
1460Sstevel@tonic-gate
1470Sstevel@tonic-gate	!
1480Sstevel@tonic-gate	! differenced byte copy, works with any alignment
1490Sstevel@tonic-gate	!
1500Sstevel@tonic-gate.dbytecp:
1510Sstevel@tonic-gate	b	7f
1520Sstevel@tonic-gate	sub	%o1, %g5, %o1		! g5 gets the difference
1530Sstevel@tonic-gate
1540Sstevel@tonic-gate4:	sth	%o4, [%g5]		! write to address
1550Sstevel@tonic-gate	inc	2, %g5			! inc to address
1560Sstevel@tonic-gate7:	deccc	2, %o2			! decrement count
1570Sstevel@tonic-gate	bge,a,pt %xcc,4b		! loop till done
1580Sstevel@tonic-gate	lduh	[%o1+%g5], %o4		! read from address
1590Sstevel@tonic-gate.done:
1600Sstevel@tonic-gate	retl
1610Sstevel@tonic-gate	nop
1620Sstevel@tonic-gate
1630Sstevel@tonic-gate	SET_SIZE(__align_cpy_2)
164