xref: /minix3/common/lib/libc/arch/powerpc/string/memmove.S (revision b6cbf7203b080219de306404f8022a65b7884f33)
1*b6cbf720SGianluca Guida/* $NetBSD: memmove.S,v 1.3 2011/01/15 07:31:12 matt Exp $ */
2*b6cbf720SGianluca Guida
3*b6cbf720SGianluca Guida/* stropt/memmove.S, pl_string_common, pl_linux 10/11/04 11:45:37
4*b6cbf720SGianluca Guida * ==========================================================================
5*b6cbf720SGianluca Guida * Optimized memmove implementation for IBM PowerPC 405/440.
6*b6cbf720SGianluca Guida *
7*b6cbf720SGianluca Guida *	Copyright (c) 2003, IBM Corporation
8*b6cbf720SGianluca Guida *	All rights reserved.
9*b6cbf720SGianluca Guida *
10*b6cbf720SGianluca Guida *	Redistribution and use in source and binary forms, with or
11*b6cbf720SGianluca Guida *	without modification, are permitted provided that the following
12*b6cbf720SGianluca Guida *	conditions are met:
13*b6cbf720SGianluca Guida *
14*b6cbf720SGianluca Guida *	* Redistributions of source code must retain the above
15*b6cbf720SGianluca Guida *	copyright notice, this list of conditions and the following
16*b6cbf720SGianluca Guida *	disclaimer.
17*b6cbf720SGianluca Guida *	* Redistributions in binary form must reproduce the above
18*b6cbf720SGianluca Guida *	copyright notice, this list of conditions and the following
19*b6cbf720SGianluca Guida *	disclaimer in the documentation and/or other materials
20*b6cbf720SGianluca Guida *	provided with the distribution.
21*b6cbf720SGianluca Guida *	* Neither the name of IBM nor the names of its contributors
22*b6cbf720SGianluca Guida *	may be used to endorse or promote products derived from this
23*b6cbf720SGianluca Guida *	software without specific prior written permission.
24*b6cbf720SGianluca Guida *
25*b6cbf720SGianluca Guida *	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
26*b6cbf720SGianluca Guida *	CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
27*b6cbf720SGianluca Guida *	INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
28*b6cbf720SGianluca Guida *	MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
29*b6cbf720SGianluca Guida *	DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
30*b6cbf720SGianluca Guida *	BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
31*b6cbf720SGianluca Guida *	OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32*b6cbf720SGianluca Guida *	PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33*b6cbf720SGianluca Guida *	PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
34*b6cbf720SGianluca Guida *	OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35*b6cbf720SGianluca Guida *	(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
36*b6cbf720SGianluca Guida *	USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37*b6cbf720SGianluca Guida *
38*b6cbf720SGianluca Guida * ==========================================================================
39*b6cbf720SGianluca Guida *
40*b6cbf720SGianluca Guida * Function: Move memory area (handles overlapping regions)
41*b6cbf720SGianluca Guida *
42*b6cbf720SGianluca Guida *		void *memmove(void * dest, const void * src, int n)
43*b6cbf720SGianluca Guida *
44*b6cbf720SGianluca Guida * Input:	r3 - destination address
45*b6cbf720SGianluca Guida *	 r4 - source address
46*b6cbf720SGianluca Guida *	 r5 - byte count
47*b6cbf720SGianluca Guida * Output: r3 - destination address
48*b6cbf720SGianluca Guida *
49*b6cbf720SGianluca Guida * ==========================================================================
50*b6cbf720SGianluca Guida */
51*b6cbf720SGianluca Guida
52*b6cbf720SGianluca Guida#include <machine/asm.h>
53*b6cbf720SGianluca Guida
54*b6cbf720SGianluca Guida        .text
55*b6cbf720SGianluca Guida        .align 4
56*b6cbf720SGianluca Guida#ifdef _BCOPY
57*b6cbf720SGianluca Guida/* bcopy = memcpy/memmove with arguments reversed. */
58*b6cbf720SGianluca Guida/* LINTSTUB: Func: void bcopy(void *, void *, size_t) */
59*b6cbf720SGianluca GuidaENTRY(bcopy)
60*b6cbf720SGianluca Guida	mr	%r6, %r3		/* swap src/dst */
61*b6cbf720SGianluca Guida	mr	%r3, %r4
62*b6cbf720SGianluca Guida	mr	%r4, %r6
63*b6cbf720SGianluca Guida#else
64*b6cbf720SGianluca Guida/* LINTSTUB: Func: void *memmove(void *, const void *, size_t) */
65*b6cbf720SGianluca GuidaENTRY(memmove)
66*b6cbf720SGianluca Guida#endif
67*b6cbf720SGianluca Guida
68*b6cbf720SGianluca Guida	mr	%r8, %r3		/* Save dst (return value)	*/
69*b6cbf720SGianluca Guida
70*b6cbf720SGianluca Guida	cmpw	%r4, %r8		/* Branch to reverse if 	*/
71*b6cbf720SGianluca Guida	blt	reverse			/* src < dest. Don't want to	*/
72*b6cbf720SGianluca Guida					/* overwrite end of src with	*/
73*b6cbf720SGianluca Guida					/* start of dest 		*/
74*b6cbf720SGianluca Guida
75*b6cbf720SGianluca Guida	addi	%r4, %r4, -4		/* Back up src and dst pointers */
76*b6cbf720SGianluca Guida	addi	%r8, %r8, -4		/* due to auto-update of 'load' */
77*b6cbf720SGianluca Guida
78*b6cbf720SGianluca Guida	srwi.	%r9,%r5,2			/* How many words in total cnt	*/
79*b6cbf720SGianluca Guida	beq-	last1			/* Handle byte by byte if < 4	*/
80*b6cbf720SGianluca Guida					/* bytes total 			*/
81*b6cbf720SGianluca Guida	mtctr	%r9			/* Count of words for loop		*/
82*b6cbf720SGianluca Guida	lwzu	%r7, 4(%r4)		/* Preload first word		*/
83*b6cbf720SGianluca Guida
84*b6cbf720SGianluca Guida	b	g1
85*b6cbf720SGianluca Guida
86*b6cbf720SGianluca Guidag0:					/* Main loop			*/
87*b6cbf720SGianluca Guida
88*b6cbf720SGianluca Guida	lwzu	%r7, 4(%r4)		/* Load a new word		*/
89*b6cbf720SGianluca Guida	stwu	%r6, 4(%r8)		/* Store previous word		*/
90*b6cbf720SGianluca Guida
91*b6cbf720SGianluca Guidag1:
92*b6cbf720SGianluca Guida
93*b6cbf720SGianluca Guida	bdz-	last			/* Dec cnt, and branch if just	*/
94*b6cbf720SGianluca Guida					/* one word to store		*/
95*b6cbf720SGianluca Guida	lwzu	%r6, 4(%r4)		/* Load another word		*/
96*b6cbf720SGianluca Guida	stwu	%r7, 4(%r8)		/* Store previous word		*/
97*b6cbf720SGianluca Guida	bdnz+	g0			/* Dec cnt, and loop again if	*/
98*b6cbf720SGianluca Guida					/* more words			*/
99*b6cbf720SGianluca Guida	mr	%r7, %r6			/* If word count -> 0, then...	*/
100*b6cbf720SGianluca Guida
101*b6cbf720SGianluca Guidalast:
102*b6cbf720SGianluca Guida
103*b6cbf720SGianluca Guida	stwu	%r7, 4(%r8)		/* ... store last word		*/
104*b6cbf720SGianluca Guida
105*b6cbf720SGianluca Guidalast1:					/* Byte-by-byte copy		*/
106*b6cbf720SGianluca Guida
107*b6cbf720SGianluca Guida	clrlwi.	%r5,%r5,30		/* If count -> 0, then ...	*/
108*b6cbf720SGianluca Guida	beqlr				/* we're done			*/
109*b6cbf720SGianluca Guida
110*b6cbf720SGianluca Guida	mtctr	%r5			/* else load count for loop	*/
111*b6cbf720SGianluca Guida
112*b6cbf720SGianluca Guida	lbzu	%r6, 4(%r4)		/* 1st byte: update addr by 4	*/
113*b6cbf720SGianluca Guida	stbu	%r6, 4(%r8)		/* since we pre-adjusted by 4	*/
114*b6cbf720SGianluca Guida	bdzlr-				/* in anticipation of main loop */
115*b6cbf720SGianluca Guida
116*b6cbf720SGianluca Guidalast2:
117*b6cbf720SGianluca Guida
118*b6cbf720SGianluca Guida	lbzu	%r6, 1(%r4)		/* But handle the rest by		*/
119*b6cbf720SGianluca Guida	stbu	%r6, 1(%r8)		/* updating addr by 1		*/
120*b6cbf720SGianluca Guida	bdnz+	last2
121*b6cbf720SGianluca Guida
122*b6cbf720SGianluca Guida	blr
123*b6cbf720SGianluca Guida
124*b6cbf720SGianluca Guida	/* We're here since src < dest. Don't want to overwrite end of	*/
125*b6cbf720SGianluca Guida	/* src with start of dest						*/
126*b6cbf720SGianluca Guida
127*b6cbf720SGianluca Guidareverse:
128*b6cbf720SGianluca Guida
129*b6cbf720SGianluca Guida	add	%r4, %r4, %r5		/* Work from end to beginning	*/
130*b6cbf720SGianluca Guida	add	%r8, %r8, %r5 		/* so add count to string ptrs	*/
131*b6cbf720SGianluca Guida	srwi.	%r9,%r5,2			/* Words in total count		*/
132*b6cbf720SGianluca Guida	beq-	rlast1			/* Handle byte by byte if < 4	*/
133*b6cbf720SGianluca Guida					/* bytes total 			*/
134*b6cbf720SGianluca Guida
135*b6cbf720SGianluca Guida	mtctr	%r9			/* Count of words for loop 	*/
136*b6cbf720SGianluca Guida
137*b6cbf720SGianluca Guida	lwzu	%r7, -4(%r4)		/* Preload first word		*/
138*b6cbf720SGianluca Guida	b	rg1
139*b6cbf720SGianluca Guida
140*b6cbf720SGianluca Guidarg0:					/* Main loop			*/
141*b6cbf720SGianluca Guida
142*b6cbf720SGianluca Guida	lwzu	%r7, -4(%r4)		/* Load a new word		*/
143*b6cbf720SGianluca Guida	stwu	%r6, -4(%r8)		/* Store previous word		*/
144*b6cbf720SGianluca Guida
145*b6cbf720SGianluca Guidarg1:
146*b6cbf720SGianluca Guida
147*b6cbf720SGianluca Guida	bdz-	rlast			/* Dec cnt, and branch if just	*/
148*b6cbf720SGianluca Guida					/* one word to store		*/
149*b6cbf720SGianluca Guida
150*b6cbf720SGianluca Guida	lwzu	%r6, -4(%r4)		/* Load another word		*/
151*b6cbf720SGianluca Guida	stwu	%r7, -4(%r8)		/* Store previous word		*/
152*b6cbf720SGianluca Guida
153*b6cbf720SGianluca Guida	bdnz+	rg0			/* Dec cnt, and loop again if	*/
154*b6cbf720SGianluca Guida					/* more words			*/
155*b6cbf720SGianluca Guida
156*b6cbf720SGianluca Guida	mr	%r7, %r6			/* If word count -> 0, then...	*/
157*b6cbf720SGianluca Guida
158*b6cbf720SGianluca Guidarlast:
159*b6cbf720SGianluca Guida
160*b6cbf720SGianluca Guida	stwu	%r7, -4(%r8)		/* ... store last word		*/
161*b6cbf720SGianluca Guida
162*b6cbf720SGianluca Guidarlast1:					/* Byte-by-byte copy		*/
163*b6cbf720SGianluca Guida
164*b6cbf720SGianluca Guida	clrlwi.	%r5,%r5,30		/* If count -> 0, then...	*/
165*b6cbf720SGianluca Guida	beqlr				/* ... we're done 		*/
166*b6cbf720SGianluca Guida
167*b6cbf720SGianluca Guida	mtctr	%r5			/* else load count for loop 	*/
168*b6cbf720SGianluca Guida
169*b6cbf720SGianluca Guidarlast2:
170*b6cbf720SGianluca Guida
171*b6cbf720SGianluca Guida	lbzu	%r6, -1(%r4)		/* Handle the rest, byte by 	*/
172*b6cbf720SGianluca Guida	stbu	%r6, -1(%r8)		/* byte				*/
173*b6cbf720SGianluca Guida
174*b6cbf720SGianluca Guida	bdnz+	rlast2		 	/* Dec ctr, and branch if more	*/
175*b6cbf720SGianluca Guida					/* bytes left			*/
176*b6cbf720SGianluca Guida	blr
177*b6cbf720SGianluca Guida
178*b6cbf720SGianluca Guida#ifdef _BCOPY
179*b6cbf720SGianluca GuidaEND(bcopy)
180*b6cbf720SGianluca Guida#else
181*b6cbf720SGianluca GuidaEND(memmove)
182*b6cbf720SGianluca Guida#endif
183