xref: /minix3/common/lib/libc/arch/powerpc/string/memcpy.S (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc/* $NetBSD: memcpy.S,v 1.6 2014/03/04 17:05:14 macallan Exp $ */
2b6cbf720SGianluca Guida
3b6cbf720SGianluca Guida/* stropt/memcpy_440.S, pl_string_common, pl_linux 10/11/04 11:45:36
4b6cbf720SGianluca Guida * ==========================================================================
5b6cbf720SGianluca Guida * Optimized memcpy implementation for IBM PowerPC 440.
6b6cbf720SGianluca Guida *
7b6cbf720SGianluca Guida *  Copyright (c) 2003, IBM Corporation
8b6cbf720SGianluca Guida *  All rights reserved.
9b6cbf720SGianluca Guida *
10b6cbf720SGianluca Guida *  Redistribution and use in source and binary forms, with or
11b6cbf720SGianluca Guida *  without modification, are permitted provided that the following
12b6cbf720SGianluca Guida *  conditions are met:
13b6cbf720SGianluca Guida *
14b6cbf720SGianluca Guida *    * Redistributions of source code must retain the above
15b6cbf720SGianluca Guida *      copyright notice, this list of conditions and the following
16b6cbf720SGianluca Guida *      disclaimer.
17b6cbf720SGianluca Guida *    * Redistributions in binary form must reproduce the above
18b6cbf720SGianluca Guida *      copyright notice, this list of conditions and the following
19b6cbf720SGianluca Guida *      disclaimer in the documentation and/or other materials
20b6cbf720SGianluca Guida *      provided with the distribution.
21b6cbf720SGianluca Guida *    * Neither the name of IBM nor the names of its contributors
22b6cbf720SGianluca Guida *      may be used to endorse or promote products derived from this
23b6cbf720SGianluca Guida *      software without specific prior written permission.
24b6cbf720SGianluca Guida *
25b6cbf720SGianluca Guida *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
26b6cbf720SGianluca Guida *  CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
27b6cbf720SGianluca Guida *  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
28b6cbf720SGianluca Guida *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
29b6cbf720SGianluca Guida *  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
30b6cbf720SGianluca Guida *  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
31b6cbf720SGianluca Guida *  OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32b6cbf720SGianluca Guida *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33b6cbf720SGianluca Guida *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
34b6cbf720SGianluca Guida *  OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35b6cbf720SGianluca Guida *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
36b6cbf720SGianluca Guida *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37b6cbf720SGianluca Guida *
38b6cbf720SGianluca Guida * ==========================================================================
39b6cbf720SGianluca Guida *
40b6cbf720SGianluca Guida * Function: Copy n bytes of the source to the destination. Behavior is
41b6cbf720SGianluca Guida *	   undefined for objects that overlap.
42b6cbf720SGianluca Guida *
43b6cbf720SGianluca Guida *
44b6cbf720SGianluca Guida *	   void *memcpy(void * dest, const void * src, int n)
45b6cbf720SGianluca Guida *
46b6cbf720SGianluca Guida * Input:  r3 - destination address
47b6cbf720SGianluca Guida *	 r4 - source address
48b6cbf720SGianluca Guida *	 r5 - byte count
49b6cbf720SGianluca Guida * Output: r3 - destination address
50b6cbf720SGianluca Guida *
51b6cbf720SGianluca Guida * ==========================================================================
52b6cbf720SGianluca Guida */
53b6cbf720SGianluca Guida
54b6cbf720SGianluca Guida#include <machine/asm.h>
55*0a6a1f1dSLionel Sambuc#ifdef _KERNEL_OPT
56*0a6a1f1dSLionel Sambuc#include "opt_ppcarch.h"
57*0a6a1f1dSLionel Sambuc#endif
58b6cbf720SGianluca Guida
59b6cbf720SGianluca Guida	.text
60b6cbf720SGianluca Guida	.align 4
61b6cbf720SGianluca Guida/* LINTSTUB: Func: void *memcpy(void *, const void *, size_t) */
62b6cbf720SGianluca GuidaENTRY(memcpy)
63b6cbf720SGianluca Guida	/*
64b6cbf720SGianluca Guida	 * Check count passed in R5. If zero, return; otherwise continue.
65b6cbf720SGianluca Guida	 */
66b6cbf720SGianluca Guida	cmpwi	%r5,0
67b6cbf720SGianluca Guida	beqlr-
68b6cbf720SGianluca Guida
69*0a6a1f1dSLionel Sambuc#if defined(_KERNEL) && defined(PPC_OEA601)
70*0a6a1f1dSLionel Sambuc	/*
71*0a6a1f1dSLionel Sambuc	* 601 will generate alignment exceptions if operand crosses
72*0a6a1f1dSLionel Sambuc	 * 4k page boundary, so do byte copy when exception handler
73*0a6a1f1dSLionel Sambuc	 * not available.  Maybe want to have a different memcpy for 601
74*0a6a1f1dSLionel Sambuc	 * that checks for page boundaries/word alignment...
75*0a6a1f1dSLionel Sambuc	 */
76*0a6a1f1dSLionel Sambuc	mfspr   %r6, 287		/* mfpvbr %r6 PVR = 287        */
77*0a6a1f1dSLionel Sambuc	srwi    %r6, %r6, 0x10		/* get version field from PVR  */
78*0a6a1f1dSLionel Sambuc	cmpwi   %r6, 0x1		/* 601 CPU = 0x0001            */
79*0a6a1f1dSLionel Sambuc	bne     bnorm			/* skip byte-only unless 601   */
80*0a6a1f1dSLionel Sambuc
81*0a6a1f1dSLionel Sambuc	or	%r6, %r3, %r4		/* see if both source and dest */
82*0a6a1f1dSLionel Sambuc	andi.	%r6, %r6, 3		/* are 32bit aligned           */
83*0a6a1f1dSLionel Sambuc	beq	bnorm			/* skip byte-only if they are  */
84*0a6a1f1dSLionel Sambucbcpy:
85*0a6a1f1dSLionel Sambuc	mtctr   %r5			/* byte copy everything */
86*0a6a1f1dSLionel Sambuc	li      %r6, 0
87*0a6a1f1dSLionel Sambucbloop:
88*0a6a1f1dSLionel Sambuc	lbzx    %r7, %r4, %r6
89*0a6a1f1dSLionel Sambuc	stbx    %r7, %r3, %r6
90*0a6a1f1dSLionel Sambuc	addi    %r6, %r6, 1
91*0a6a1f1dSLionel Sambuc	bdnz    bloop
92*0a6a1f1dSLionel Sambuc	blr
93*0a6a1f1dSLionel Sambuc
94*0a6a1f1dSLionel Sambucbnorm:
95*0a6a1f1dSLionel Sambuc
96*0a6a1f1dSLionel Sambuc#endif
97*0a6a1f1dSLionel Sambuc
98b6cbf720SGianluca Guida	mr	%r8, %r3		/* Copy dst (return value)	*/
99b6cbf720SGianluca Guida
100b6cbf720SGianluca Guida	addi	%r4, %r4, -4		/* Prepare for main loop's auto	*/
101b6cbf720SGianluca Guida	addi	%r8, %r8, -4		/* update		       */
102b6cbf720SGianluca Guida
103b6cbf720SGianluca Guida	srwi.	%r9,%r5,2		/* Word count -> r9 		*/
104b6cbf720SGianluca Guida	beq-	last1			/* Partial copy if <4 bytes	*/
105b6cbf720SGianluca Guida
106b6cbf720SGianluca Guida	mtctr	%r9			/* Word cnt in CTR for loop     */
107b6cbf720SGianluca Guida	lwzu	%r7, 4(%r4)		/* Preload for main loop	*/
108b6cbf720SGianluca Guida
109b6cbf720SGianluca Guida	b	g1
110b6cbf720SGianluca Guida
111b6cbf720SGianluca Guidag0:					/* Main loop			*/
112b6cbf720SGianluca Guida
113b6cbf720SGianluca Guida	lwzu	%r7, 4(%r4)		/* Load a new word		*/
114b6cbf720SGianluca Guida	stwu	%r6, 4(%r8)		/* Store previous word		*/
115b6cbf720SGianluca Guida
116b6cbf720SGianluca Guidag1:
117b6cbf720SGianluca Guida
118b6cbf720SGianluca Guida	bdz-	last			/* Dec ctr and exit loop if no  */
119b6cbf720SGianluca Guida					/* more words		   */
120b6cbf720SGianluca Guida	lwzu	%r6, 4(%r4)		/* Load another word		*/
121b6cbf720SGianluca Guida	stwu	%r7, 4(%r8)		/* Store previous word		*/
122b6cbf720SGianluca Guida	bdnz+	g0			/* Dec ctr and continue loop if */
123b6cbf720SGianluca Guida					/* more words		   */
124b6cbf720SGianluca Guida
125b6cbf720SGianluca Guida	mr	%r7, %r6
126b6cbf720SGianluca Guida
127b6cbf720SGianluca Guidalast:
128b6cbf720SGianluca Guida
129b6cbf720SGianluca Guida	stwu	%r7, 4(%r8)		/* Store last word		*/
130b6cbf720SGianluca Guida
131b6cbf720SGianluca Guidalast1:					/* Byte-by-byte copy		*/
132b6cbf720SGianluca Guida
133b6cbf720SGianluca Guida	clrlwi.	%r5,%r5,30
134b6cbf720SGianluca Guida	beqlr
135b6cbf720SGianluca Guida
136b6cbf720SGianluca Guida	mtctr	%r5
137b6cbf720SGianluca Guida
138b6cbf720SGianluca Guida	lbzu	%r6, 4(%r4)		/* 1st byte: update by word	*/
139b6cbf720SGianluca Guida	stbu	%r6, 4(%r8)
140b6cbf720SGianluca Guida	bdzlr-
141b6cbf720SGianluca Guida
142b6cbf720SGianluca Guidalast2:
143b6cbf720SGianluca Guida
144b6cbf720SGianluca Guida	lbzu	%r6, 1(%r4)		/* Handle the rest		*/
145b6cbf720SGianluca Guida	stbu	%r6, 1(%r8)
146b6cbf720SGianluca Guida	bdnz+	last2
147b6cbf720SGianluca Guida
148b6cbf720SGianluca Guida	blr
149b6cbf720SGianluca GuidaEND(memcpy)
150