xref: /minix3/common/lib/libc/arch/sh3/string/memcpy.S (revision b6cbf7203b080219de306404f8022a65b7884f33)
1*b6cbf720SGianluca Guida/*	$NetBSD: memcpy.S,v 1.2 2006/04/22 23:53:47 uwe Exp $	*/
2*b6cbf720SGianluca Guida
3*b6cbf720SGianluca Guida/*
4*b6cbf720SGianluca Guida * Copyright (c) 2000 SHIMIZU Ryo <ryo@misakimix.org>
5*b6cbf720SGianluca Guida * All rights reserved.
6*b6cbf720SGianluca Guida *
7*b6cbf720SGianluca Guida * Redistribution and use in source and binary forms, with or without
8*b6cbf720SGianluca Guida * modification, are permitted provided that the following conditions
9*b6cbf720SGianluca Guida * are met:
10*b6cbf720SGianluca Guida * 1. Redistributions of source code must retain the above copyright
11*b6cbf720SGianluca Guida *    notice, this list of conditions and the following disclaimer.
12*b6cbf720SGianluca Guida * 2. Redistributions in binary form must reproduce the above copyright
13*b6cbf720SGianluca Guida *    notice, this list of conditions and the following disclaimer in the
14*b6cbf720SGianluca Guida *    documentation and/or other materials provided with the distribution.
15*b6cbf720SGianluca Guida * 3. The name of the author may not be used to endorse or promote products
16*b6cbf720SGianluca Guida *    derived from this software without specific prior written permission.
17*b6cbf720SGianluca Guida *
18*b6cbf720SGianluca Guida * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19*b6cbf720SGianluca Guida * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20*b6cbf720SGianluca Guida * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21*b6cbf720SGianluca Guida * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22*b6cbf720SGianluca Guida * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23*b6cbf720SGianluca Guida * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24*b6cbf720SGianluca Guida * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25*b6cbf720SGianluca Guida * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26*b6cbf720SGianluca Guida * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27*b6cbf720SGianluca Guida * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*b6cbf720SGianluca Guida */
29*b6cbf720SGianluca Guida
30*b6cbf720SGianluca Guida#include <machine/asm.h>
31*b6cbf720SGianluca Guida
32*b6cbf720SGianluca Guida#if defined(LIBC_SCCS) && !defined(lint)
33*b6cbf720SGianluca Guida	RCSID("$NetBSD: memcpy.S,v 1.2 2006/04/22 23:53:47 uwe Exp $")
34*b6cbf720SGianluca Guida#endif
35*b6cbf720SGianluca Guida
36*b6cbf720SGianluca Guida#if !defined(MEMCOPY) && !defined(MEMMOVE) && !defined(BCOPY)
37*b6cbf720SGianluca Guida#define MEMCOPY
38*b6cbf720SGianluca Guida#endif
39*b6cbf720SGianluca Guida
40*b6cbf720SGianluca Guida#if defined(MEMCOPY) || defined(MEMMOVE)
41*b6cbf720SGianluca Guida#define	REG_DST0	r3
42*b6cbf720SGianluca Guida#define	REG_SRC		r5
43*b6cbf720SGianluca Guida#define	REG_DST		r4
44*b6cbf720SGianluca Guida#else
45*b6cbf720SGianluca Guida#define	REG_SRC		r4
46*b6cbf720SGianluca Guida#define	REG_DST		r5
47*b6cbf720SGianluca Guida#endif
48*b6cbf720SGianluca Guida
49*b6cbf720SGianluca Guida#define	REG_LEN		r6
50*b6cbf720SGianluca Guida
51*b6cbf720SGianluca Guida#if defined(MEMCOPY)
52*b6cbf720SGianluca GuidaENTRY(memcpy)
53*b6cbf720SGianluca Guida#elif defined(MEMMOVE)
54*b6cbf720SGianluca GuidaENTRY(memmove)
55*b6cbf720SGianluca Guida#elif defined(BCOPY)
56*b6cbf720SGianluca GuidaENTRY(bcopy)
57*b6cbf720SGianluca Guida#endif
58*b6cbf720SGianluca Guida#ifdef REG_DST0
59*b6cbf720SGianluca Guida	mov	REG_DST,REG_DST0
60*b6cbf720SGianluca Guida#endif
61*b6cbf720SGianluca Guida	cmp/eq	REG_DST,REG_SRC	/* if ( src == dst ) return; */
62*b6cbf720SGianluca Guida	bt/s	bcopy_return
63*b6cbf720SGianluca Guida	cmp/hi	REG_DST,REG_SRC
64*b6cbf720SGianluca Guida	bf/s	bcopy_overlap
65*b6cbf720SGianluca Guida
66*b6cbf720SGianluca Guida	mov	REG_SRC,r0
67*b6cbf720SGianluca Guida	xor	REG_DST,r0
68*b6cbf720SGianluca Guida	and	#3,r0
69*b6cbf720SGianluca Guida	mov	r0,r1
70*b6cbf720SGianluca Guida	tst	r0,r0		/* (src ^ dst) & 3         */
71*b6cbf720SGianluca Guida	bf/s	word_align
72*b6cbf720SGianluca Guida
73*b6cbf720SGianluca Guidalongword_align:
74*b6cbf720SGianluca Guida	tst	REG_LEN,REG_LEN	/* if ( len==0 ) return;   */
75*b6cbf720SGianluca Guida	bt/s	bcopy_return
76*b6cbf720SGianluca Guida
77*b6cbf720SGianluca Guida
78*b6cbf720SGianluca Guida	mov	REG_SRC,r0
79*b6cbf720SGianluca Guida	tst	#1,r0		/* if ( src & 1 )          */
80*b6cbf720SGianluca Guida	bt	1f
81*b6cbf720SGianluca Guida	mov.b	@REG_SRC+,r0	/*    *dst++ = *src++;     */
82*b6cbf720SGianluca Guida	add	#-1,REG_LEN
83*b6cbf720SGianluca Guida	mov.b	r0,@REG_DST
84*b6cbf720SGianluca Guida	add	#1,REG_DST
85*b6cbf720SGianluca Guida1:
86*b6cbf720SGianluca Guida
87*b6cbf720SGianluca Guida
88*b6cbf720SGianluca Guida	mov	#1,r0
89*b6cbf720SGianluca Guida	cmp/hi	r0,REG_LEN	/* if ( (len > 1) &&       */
90*b6cbf720SGianluca Guida	bf/s	1f
91*b6cbf720SGianluca Guida	mov	REG_SRC,r0
92*b6cbf720SGianluca Guida	tst	#2,r0		/*      (src & 2) {        */
93*b6cbf720SGianluca Guida	bt	1f
94*b6cbf720SGianluca Guida	mov.w	@REG_SRC+,r0	/*        *((unsigned short*)dst)++ = *((unsigned short*)src)++; */
95*b6cbf720SGianluca Guida	add	#-2,REG_LEN	/*        len -= 2;                                              */
96*b6cbf720SGianluca Guida	mov.w	r0,@REG_DST
97*b6cbf720SGianluca Guida	add	#2,REG_DST	/* }                       */
98*b6cbf720SGianluca Guida1:
99*b6cbf720SGianluca Guida
100*b6cbf720SGianluca Guida
101*b6cbf720SGianluca Guida	mov	#3,r1
102*b6cbf720SGianluca Guida	cmp/hi	r1,REG_LEN	/* while ( len > 3 ) {     */
103*b6cbf720SGianluca Guida	bf/s	no_align_delay
104*b6cbf720SGianluca Guida	tst	REG_LEN,REG_LEN
105*b6cbf720SGianluca Guida2:
106*b6cbf720SGianluca Guida	mov.l	@REG_SRC+,r0	/*   *((unsigned long*)dst)++ = *((unsigned long*)src)++;        */
107*b6cbf720SGianluca Guida	add	#-4,REG_LEN	/*   len -= 4;                                                   */
108*b6cbf720SGianluca Guida	mov.l	r0,@REG_DST
109*b6cbf720SGianluca Guida	cmp/hi	r1,REG_LEN
110*b6cbf720SGianluca Guida	bt/s	2b
111*b6cbf720SGianluca Guida	add	#4,REG_DST	/* }                       */
112*b6cbf720SGianluca Guida
113*b6cbf720SGianluca Guida	bra	no_align_delay
114*b6cbf720SGianluca Guida	tst	REG_LEN,REG_LEN
115*b6cbf720SGianluca Guida
116*b6cbf720SGianluca Guida
117*b6cbf720SGianluca Guidaword_align:
118*b6cbf720SGianluca Guida	mov	r1,r0
119*b6cbf720SGianluca Guida	tst	#1,r0
120*b6cbf720SGianluca Guida	bf/s	no_align_delay
121*b6cbf720SGianluca Guida	tst	REG_LEN,REG_LEN	/* if ( len == 0 ) return; */
122*b6cbf720SGianluca Guida	bt	bcopy_return
123*b6cbf720SGianluca Guida
124*b6cbf720SGianluca Guida
125*b6cbf720SGianluca Guida	mov	REG_SRC,r0	/* if ( src & 1 )          */
126*b6cbf720SGianluca Guida	tst	#1,r0
127*b6cbf720SGianluca Guida	bt	1f
128*b6cbf720SGianluca Guida	mov.b	@REG_SRC+,r0	/*    *dst++ = *src++;     */
129*b6cbf720SGianluca Guida	add	#-1,REG_LEN
130*b6cbf720SGianluca Guida	mov.b	r0,@REG_DST
131*b6cbf720SGianluca Guida	add	#1,REG_DST
132*b6cbf720SGianluca Guida1:
133*b6cbf720SGianluca Guida
134*b6cbf720SGianluca Guida
135*b6cbf720SGianluca Guida	mov	#1,r1
136*b6cbf720SGianluca Guida	cmp/hi	r1,REG_LEN	/* while ( len > 1 ) {     */
137*b6cbf720SGianluca Guida	bf/s	no_align_delay
138*b6cbf720SGianluca Guida	tst	REG_LEN,REG_LEN
139*b6cbf720SGianluca Guida2:
140*b6cbf720SGianluca Guida	mov.w	@REG_SRC+,r0	/*   *((unsigned short*)dst)++ = *((unsigned short*)src)++;      */
141*b6cbf720SGianluca Guida	add	#-2,REG_LEN	/*   len -= 2;                                                   */
142*b6cbf720SGianluca Guida	mov.w	r0,@REG_DST
143*b6cbf720SGianluca Guida	cmp/hi	r1,REG_LEN
144*b6cbf720SGianluca Guida	bt/s	2b
145*b6cbf720SGianluca Guida	add	#2,REG_DST	/* }                       */
146*b6cbf720SGianluca Guida
147*b6cbf720SGianluca Guida
148*b6cbf720SGianluca Guidano_align:
149*b6cbf720SGianluca Guida	tst	REG_LEN,REG_LEN	/* while ( len!= ) {       */
150*b6cbf720SGianluca Guidano_align_delay:
151*b6cbf720SGianluca Guida	bt	bcopy_return
152*b6cbf720SGianluca Guida1:
153*b6cbf720SGianluca Guida	mov.b	@REG_SRC+,r0	/*    *dst++ = *src++;     */
154*b6cbf720SGianluca Guida	add	#-1,REG_LEN	/*    len--;               */
155*b6cbf720SGianluca Guida	mov.b	r0,@REG_DST
156*b6cbf720SGianluca Guida	tst	REG_LEN,REG_LEN
157*b6cbf720SGianluca Guida	bf/s	1b
158*b6cbf720SGianluca Guida	add	#1,REG_DST	/* }                       */
159*b6cbf720SGianluca Guidabcopy_return:
160*b6cbf720SGianluca Guida	rts
161*b6cbf720SGianluca Guida#ifdef REG_DST0
162*b6cbf720SGianluca Guida	mov	REG_DST0,r0
163*b6cbf720SGianluca Guida#else
164*b6cbf720SGianluca Guida	nop
165*b6cbf720SGianluca Guida#endif
166*b6cbf720SGianluca Guida
167*b6cbf720SGianluca Guida
168*b6cbf720SGianluca Guidabcopy_overlap:
169*b6cbf720SGianluca Guida	add	REG_LEN,REG_SRC
170*b6cbf720SGianluca Guida	add	REG_LEN,REG_DST
171*b6cbf720SGianluca Guida
172*b6cbf720SGianluca Guida	mov	REG_SRC,r0
173*b6cbf720SGianluca Guida	xor	REG_DST,r0
174*b6cbf720SGianluca Guida	and	#3,r0
175*b6cbf720SGianluca Guida	mov	r0,r1
176*b6cbf720SGianluca Guida	tst	r0,r0		/* (src ^ dst) & 3         */
177*b6cbf720SGianluca Guida	bf/s	ov_word_align
178*b6cbf720SGianluca Guida
179*b6cbf720SGianluca Guidaov_longword_align:
180*b6cbf720SGianluca Guida	tst	REG_LEN,REG_LEN	/* if ( len==0 ) return;   */
181*b6cbf720SGianluca Guida	bt/s	bcopy_return
182*b6cbf720SGianluca Guida
183*b6cbf720SGianluca Guida
184*b6cbf720SGianluca Guida	mov	REG_SRC,r0
185*b6cbf720SGianluca Guida	tst	#1,r0		/* if ( src & 1 )          */
186*b6cbf720SGianluca Guida	bt	1f
187*b6cbf720SGianluca Guida	add	#-1,REG_SRC	/*    *--dst = *--src;     */
188*b6cbf720SGianluca Guida	mov.b	@REG_SRC,r0
189*b6cbf720SGianluca Guida	mov.b	r0,@-REG_DST
190*b6cbf720SGianluca Guida	add	#-1,REG_LEN
191*b6cbf720SGianluca Guida1:
192*b6cbf720SGianluca Guida
193*b6cbf720SGianluca Guida
194*b6cbf720SGianluca Guida	mov	#1,r0
195*b6cbf720SGianluca Guida	cmp/hi	r0,REG_LEN	/* if ( (len > 1) &&       */
196*b6cbf720SGianluca Guida	bf/s	1f
197*b6cbf720SGianluca Guida	mov	REG_SRC,r0
198*b6cbf720SGianluca Guida	tst	#2,r0		/*      (src & 2) {        */
199*b6cbf720SGianluca Guida	bt	1f
200*b6cbf720SGianluca Guida	add	#-2,REG_SRC	/*        *--((unsigned short*)dst) = *--((unsigned short*)src); */
201*b6cbf720SGianluca Guida	mov.w	@REG_SRC,r0
202*b6cbf720SGianluca Guida	add	#-2,REG_LEN	/*        len -= 2;                                              */
203*b6cbf720SGianluca Guida	mov.w	r0,@-REG_DST	/* }                       */
204*b6cbf720SGianluca Guida1:
205*b6cbf720SGianluca Guida
206*b6cbf720SGianluca Guida
207*b6cbf720SGianluca Guida	mov	#3,r1
208*b6cbf720SGianluca Guida	cmp/hi	r1,REG_LEN	/* while ( len > 3 ) {     */
209*b6cbf720SGianluca Guida	bf/s	ov_no_align_delay
210*b6cbf720SGianluca Guida	tst	REG_LEN,REG_LEN
211*b6cbf720SGianluca Guida2:
212*b6cbf720SGianluca Guida	add	#-4,REG_SRC
213*b6cbf720SGianluca Guida	mov.l	@REG_SRC,r0	/*   *((unsigned long*)dst)++ = *((unsigned long*)src)++;        */
214*b6cbf720SGianluca Guida	add	#-4,REG_LEN	/*   len -= 4;                                                   */
215*b6cbf720SGianluca Guida	cmp/hi	r1,REG_LEN
216*b6cbf720SGianluca Guida	bt/s	2b
217*b6cbf720SGianluca Guida	mov.l	r0,@-REG_DST	/* }                       */
218*b6cbf720SGianluca Guida
219*b6cbf720SGianluca Guida	bra	ov_no_align_delay
220*b6cbf720SGianluca Guida	tst	REG_LEN,REG_LEN
221*b6cbf720SGianluca Guida
222*b6cbf720SGianluca Guida
223*b6cbf720SGianluca Guidaov_word_align:
224*b6cbf720SGianluca Guida	mov	r1,r0
225*b6cbf720SGianluca Guida	tst	#1,r0
226*b6cbf720SGianluca Guida	bf/s	ov_no_align_delay
227*b6cbf720SGianluca Guida	tst	REG_LEN,REG_LEN	/* if ( len == 0 ) return; */
228*b6cbf720SGianluca Guida	bt	bcopy_return
229*b6cbf720SGianluca Guida
230*b6cbf720SGianluca Guida
231*b6cbf720SGianluca Guida	mov	REG_SRC,r0	/* if ( src & 1 )          */
232*b6cbf720SGianluca Guida	tst	#1,r0
233*b6cbf720SGianluca Guida	bt	1f
234*b6cbf720SGianluca Guida	add	#-1,REG_SRC
235*b6cbf720SGianluca Guida	mov.b	@REG_SRC,r0	/*    *--dst = *--src;     */
236*b6cbf720SGianluca Guida	add	#-1,REG_LEN
237*b6cbf720SGianluca Guida	mov.b	r0,@-REG_DST
238*b6cbf720SGianluca Guida1:
239*b6cbf720SGianluca Guida
240*b6cbf720SGianluca Guida
241*b6cbf720SGianluca Guida	mov	#1,r1
242*b6cbf720SGianluca Guida	cmp/hi	r1,REG_LEN	/* while ( len > 1 ) {     */
243*b6cbf720SGianluca Guida	bf/s	ov_no_align_delay
244*b6cbf720SGianluca Guida	tst	REG_LEN,REG_LEN
245*b6cbf720SGianluca Guida2:
246*b6cbf720SGianluca Guida	add	#-2,REG_SRC
247*b6cbf720SGianluca Guida	mov.w	@REG_SRC,r0	/*   *--((unsigned short*)dst) = *--((unsigned short*)src);      */
248*b6cbf720SGianluca Guida	add	#-2,REG_LEN	/*   len -= 2;                                                   */
249*b6cbf720SGianluca Guida	cmp/hi	r1,REG_LEN
250*b6cbf720SGianluca Guida	bt/s	2b
251*b6cbf720SGianluca Guida	mov.w	r0,@-REG_DST	/* }                       */
252*b6cbf720SGianluca Guida
253*b6cbf720SGianluca Guida
254*b6cbf720SGianluca Guidaov_no_align:
255*b6cbf720SGianluca Guida	tst	REG_LEN,REG_LEN	/* while ( len!= ) {       */
256*b6cbf720SGianluca Guidaov_no_align_delay:
257*b6cbf720SGianluca Guida	bt	9f
258*b6cbf720SGianluca Guida1:
259*b6cbf720SGianluca Guida	add	#-1,REG_SRC
260*b6cbf720SGianluca Guida	mov.b	@REG_SRC,r0	/*    *--dst = *--src;     */
261*b6cbf720SGianluca Guida	add	#-1,REG_LEN	/*    len--;               */
262*b6cbf720SGianluca Guida	tst	REG_LEN,REG_LEN
263*b6cbf720SGianluca Guida	bf/s	1b
264*b6cbf720SGianluca Guida	mov.b	r0,@-REG_DST	/* }                       */
265*b6cbf720SGianluca Guida9:
266*b6cbf720SGianluca Guida	rts
267*b6cbf720SGianluca Guida#ifdef REG_DST0
268*b6cbf720SGianluca Guida	mov	REG_DST0,r0
269*b6cbf720SGianluca Guida#else
270*b6cbf720SGianluca Guida	nop
271*b6cbf720SGianluca Guida#endif
272