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