xref: /openbsd-src/sys/lib/libkern/arch/powerpc/memmove.S (revision 15572fcf8c6bfa0588565cd23f393a5a1499ea57)
1*15572fcfSgkoehler/* $OpenBSD: memmove.S,v 1.6 2020/11/28 19:49:30 gkoehler Exp $ */
27706a561Smiod/* $NetBSD: memmove.S,v 1.3 2011/01/15 07:31:12 matt Exp $ */
37706a561Smiod
47706a561Smiod/* stropt/memmove.S, pl_string_common, pl_linux 10/11/04 11:45:37
57706a561Smiod * ==========================================================================
67706a561Smiod * Optimized memmove implementation for IBM PowerPC 405/440.
77706a561Smiod *
87706a561Smiod *	Copyright (c) 2003, IBM Corporation
97706a561Smiod *	All rights reserved.
107706a561Smiod *
117706a561Smiod *	Redistribution and use in source and binary forms, with or
127706a561Smiod *	without modification, are permitted provided that the following
137706a561Smiod *	conditions are met:
147706a561Smiod *
157706a561Smiod *	* Redistributions of source code must retain the above
167706a561Smiod *	copyright notice, this list of conditions and the following
177706a561Smiod *	disclaimer.
187706a561Smiod *	* Redistributions in binary form must reproduce the above
197706a561Smiod *	copyright notice, this list of conditions and the following
207706a561Smiod *	disclaimer in the documentation and/or other materials
217706a561Smiod *	provided with the distribution.
227706a561Smiod *	* Neither the name of IBM nor the names of its contributors
237706a561Smiod *	may be used to endorse or promote products derived from this
247706a561Smiod *	software without specific prior written permission.
257706a561Smiod *
267706a561Smiod *	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
277706a561Smiod *	CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
287706a561Smiod *	INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
297706a561Smiod *	MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
307706a561Smiod *	DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
317706a561Smiod *	BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
327706a561Smiod *	OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
337706a561Smiod *	PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
347706a561Smiod *	PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
357706a561Smiod *	OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
367706a561Smiod *	(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
377706a561Smiod *	USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
387706a561Smiod *
397706a561Smiod * ==========================================================================
407706a561Smiod */
417706a561Smiod
427706a561Smiod#include <machine/asm.h>
437706a561Smiod
447706a561Smiod        .text
457706a561Smiod
467706a561Smiod/* void *memcpy(void *to, const void *from, size_t len) */
477706a561SmiodENTRY(memcpy)
48*15572fcfSgkoehler	RETGUARD_SETUP(memmove, %r11, %r12)
497706a561Smiod	mr	%r8, %r3		/* Save dst (return value)	*/
507706a561Smiod	b	fwd
517706a561Smiod
527706a561Smiod/* void bcopy(void *, void *, size_t) */
537706a561SmiodENTRY(bcopy)
547706a561Smiod	mr	%r6, %r3		/* swap src/dst */
557706a561Smiod	mr	%r3, %r4
567706a561Smiod	mr	%r4, %r6
577706a561Smiod
587706a561Smiod/* void *memmove(void *, const void *, size_t) */
597706a561SmiodENTRY(memmove)
60*15572fcfSgkoehler	RETGUARD_SETUP(memmove, %r11, %r12)
617706a561Smiod	mr	%r8, %r3		/* Save dst (return value)	*/
627706a561Smiod
637706a561Smiod	cmpw	%r4, %r8		/* Branch to reverse if 	*/
647706a561Smiod	blt	reverse			/* src < dest. Don't want to	*/
657706a561Smiod					/* overwrite end of src with	*/
667706a561Smiod					/* start of dest 		*/
677706a561Smiod
687706a561Smiodfwd:
697706a561Smiod	addi	%r4, %r4, -4		/* Back up src and dst pointers */
707706a561Smiod	addi	%r8, %r8, -4		/* due to auto-update of 'load' */
717706a561Smiod
727706a561Smiod	srwi.	%r9,%r5,2		/* How many words in total cnt	*/
737706a561Smiod	beq-	last1			/* Handle byte by byte if < 4	*/
747706a561Smiod					/* bytes total 			*/
757706a561Smiod	mtctr	%r9			/* Count of words for loop	*/
767706a561Smiod	lwzu	%r7, 4(%r4)		/* Preload first word		*/
777706a561Smiod
787706a561Smiod	b	g1
797706a561Smiod
807706a561Smiodg0:					/* Main loop			*/
817706a561Smiod
827706a561Smiod	lwzu	%r7, 4(%r4)		/* Load a new word		*/
837706a561Smiod	stwu	%r6, 4(%r8)		/* Store previous word		*/
847706a561Smiod
857706a561Smiodg1:
867706a561Smiod
877706a561Smiod	bdz-	last			/* Dec cnt, and branch if just	*/
887706a561Smiod					/* one word to store		*/
897706a561Smiod	lwzu	%r6, 4(%r4)		/* Load another word		*/
907706a561Smiod	stwu	%r7, 4(%r8)		/* Store previous word		*/
917706a561Smiod	bdnz+	g0			/* Dec cnt, and loop again if	*/
927706a561Smiod					/* more words			*/
937706a561Smiod	mr	%r7, %r6		/* If word count -> 0, then...	*/
947706a561Smiod
957706a561Smiodlast:
967706a561Smiod
977706a561Smiod	stwu	%r7, 4(%r8)		/* ... store last word		*/
987706a561Smiod
997706a561Smiodlast1:					/* Byte-by-byte copy		*/
1007706a561Smiod
1017706a561Smiod	clrlwi.	%r5,%r5,30		/* If count -> 0, then ...	*/
1029df9de38Sgkoehler	beq	done			/* we're done			*/
1037706a561Smiod
1047706a561Smiod	mtctr	%r5			/* else load count for loop	*/
1057706a561Smiod
1067706a561Smiod	lbzu	%r6, 4(%r4)		/* 1st byte: update addr by 4	*/
1077706a561Smiod	stbu	%r6, 4(%r8)		/* since we pre-adjusted by 4	*/
1089df9de38Sgkoehler	bdz-	done			/* in anticipation of main loop */
1097706a561Smiod
1107706a561Smiodlast2:
1117706a561Smiod
1127706a561Smiod	lbzu	%r6, 1(%r4)		/* But handle the rest by	*/
1137706a561Smiod	stbu	%r6, 1(%r8)		/* updating addr by 1		*/
1147706a561Smiod	bdnz+	last2
1159df9de38Sgkoehler	b	done
1167706a561Smiod
1177706a561Smiod	/* We're here since src < dest. Don't want to overwrite end of	*/
1187706a561Smiod	/* src with start of dest					*/
1197706a561Smiod
1207706a561Smiodreverse:
1217706a561Smiod
1227706a561Smiod	add	%r4, %r4, %r5		/* Work from end to beginning	*/
1237706a561Smiod	add	%r8, %r8, %r5 		/* so add count to string ptrs	*/
1247706a561Smiod	srwi.	%r9,%r5,2		/* Words in total count		*/
1257706a561Smiod	beq-	rlast1			/* Handle byte by byte if < 4	*/
1267706a561Smiod					/* bytes total 			*/
1277706a561Smiod
1287706a561Smiod	mtctr	%r9			/* Count of words for loop 	*/
1297706a561Smiod
1307706a561Smiod	lwzu	%r7, -4(%r4)		/* Preload first word		*/
1317706a561Smiod	b	rg1
1327706a561Smiod
1337706a561Smiodrg0:					/* Main loop			*/
1347706a561Smiod
1357706a561Smiod	lwzu	%r7, -4(%r4)		/* Load a new word		*/
1367706a561Smiod	stwu	%r6, -4(%r8)		/* Store previous word		*/
1377706a561Smiod
1387706a561Smiodrg1:
1397706a561Smiod
1407706a561Smiod	bdz-	rlast			/* Dec cnt, and branch if just	*/
1417706a561Smiod					/* one word to store		*/
1427706a561Smiod
1437706a561Smiod	lwzu	%r6, -4(%r4)		/* Load another word		*/
1447706a561Smiod	stwu	%r7, -4(%r8)		/* Store previous word		*/
1457706a561Smiod
1467706a561Smiod	bdnz+	rg0			/* Dec cnt, and loop again if	*/
1477706a561Smiod					/* more words			*/
1487706a561Smiod
1497706a561Smiod	mr	%r7, %r6		/* If word count -> 0, then...	*/
1507706a561Smiod
1517706a561Smiodrlast:
1527706a561Smiod
1537706a561Smiod	stwu	%r7, -4(%r8)		/* ... store last word		*/
1547706a561Smiod
1557706a561Smiodrlast1:					/* Byte-by-byte copy		*/
1567706a561Smiod
1577706a561Smiod	clrlwi.	%r5,%r5,30		/* If count -> 0, then...	*/
1589df9de38Sgkoehler	beq	done			/* ... we're done 		*/
1597706a561Smiod
1607706a561Smiod	mtctr	%r5			/* else load count for loop 	*/
1617706a561Smiod
1627706a561Smiodrlast2:
1637706a561Smiod
1647706a561Smiod	lbzu	%r6, -1(%r4)		/* Handle the rest, byte by 	*/
1657706a561Smiod	stbu	%r6, -1(%r8)		/* byte				*/
1667706a561Smiod
1677706a561Smiod	bdnz+	rlast2		 	/* Dec ctr, and branch if more	*/
1687706a561Smiod					/* bytes left			*/
1699df9de38Sgkoehlerdone:
170*15572fcfSgkoehler	RETGUARD_CHECK(memmove, %r11, %r12)
1717706a561Smiod	blr
172