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