xref: /openbsd-src/sys/lib/libkern/arch/m88k/copy_subr.S (revision a28daedfc357b214be5c701aa8ba8adb29a7f1c2)
1/*	$OpenBSD: copy_subr.S,v 1.1 2006/11/17 22:32:38 miod Exp $	*/
2/*
3 * Mach Operating System
4 * Copyright (c) 1993-1992 Carnegie Mellon University
5 * Copyright (c) 1991 OMRON Corporation
6 * Copyright (c) 1996 Nivas Madhur
7 * Copyright (c) 1998 Steve Murphree, Jr.
8 * All Rights Reserved.
9 *
10 * Permission to use, copy, modify and distribute this software and its
11 * documentation is hereby granted, provided that both the copyright
12 * notice and this permission notice appear in all copies of the
13 * software, derivative works or modified versions, and any portions
14 * thereof, and that both notices appear in supporting documentation.
15 *
16 * CARNEGIE MELLON AND OMRON ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS IS"
17 * CONDITION.  CARNEGIE MELLON AND OMRON DISCLAIM ANY LIABILITY OF ANY KIND
18 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
19 *
20 * Carnegie Mellon requests users of this software to return to
21 *
22 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
23 *  School of Computer Science
24 *  Carnegie Mellon University
25 *  Pittsburgh PA 15213-3890
26 *
27 * any improvements or extensions that they make and grant Carnegie the
28 * rights to redistribute these changes.
29 */
30
31#include <machine/asm.h>
32
33/*
34 * copy count bytes of data from source to destination
35 * Don Harper (don@omron.co.jp), Omron Corporation.
36 */
37
38#if defined(MEMCPY) || defined(MEMMOVE)
39#define	SRC	r3
40#define	DST	r2
41#define	SAVE	r5
42#else
43#define	SRC	r2
44#define	DST	r3
45#endif
46#define	LEN	r4
47
48#ifdef MEMCPY
49ENTRY(memcpy)
50#endif
51#ifdef MEMMOVE
52ENTRY(memmove)
53#endif
54#ifdef BCOPY
55ENTRY(bcopy)
56#endif
57#ifdef OVBCOPY
58ENTRY(ovbcopy)
59#endif
60
61#if defined(MEMCPY) || defined(MEMMOVE)
62	or	SAVE, DST, r0
63#endif
64
65	bcnd	eq0,LEN,_ASM_LABEL(bcopy_out)	/* nothing to do if == 0 */
66
67/*
68 * check position of source and destination data
69 */
70	cmp 	r9,SRC,DST	/* compare source address to destination */
71	bb1	eq,r9,_ASM_LABEL(bcopy_out)	/* nothing to do if equal */
72#if defined(MEMMOVE) || defined(OVBCOPY)
73	bb1	lo,r9,_ASM_LABEL(bcopy_reverse)	/* reverse copy if src < dest */
74#endif
75
76/*
77 * source address is greater than destination address, or we do
78 * not have to care about overlapping areas: copy forward
79 */
80	cmp 	r9,LEN,16	/* see if we have at least 16 bytes */
81	bb1	lt,r9,_ASM_LABEL(f_byte_copy)	/* copy bytes for small data length */
82/*
83 * determine copy strategy based on alignment of source and destination
84 */
85	mask	r6,SRC,3	/* get 2 low order bits of source address */
86	mask	r7,DST,3	/* get 2 low order bits of destintation addr */
87	mak	r6,r6,0<4>	/* convert source bits to table offset */
88	mak	r7,r7,0<2>	/* convert destination bits to table offset */
89	or.u	r12,r0,hi16(_ASM_LABEL(f_strat))
90	or	r12,r12,lo16(_ASM_LABEL(f_strat))
91	addu	r6,r6,r7	/* compute final table offset for strategy */
92	ld	r12,r12,r6	/* load the strategy routine */
93	jmp	r12		/* branch to strategy routine */
94
95/*
96 * Copy three bytes from src to destination then copy words
97 */
98ASLOCAL(f_3byte_word_copy)
99	ld.bu	r6,SRC,0	/* load byte from source */
100	ld.bu	r7,SRC,1	/* load byte from source */
101	ld.bu	r8,SRC,2	/* load byte from source */
102	st.b	r6,DST,0	/* store byte to destination */
103	st.b	r7,DST,1	/* store byte to destination */
104	st.b	r8,DST,2	/* store byte to destination */
105	addu	SRC,SRC,3	/* increment source pointer */
106	addu	DST,DST,3	/* increment destination pointer */
107	br.n	_ASM_LABEL(f_word_copy)	/* copy full words */
108	 subu	LEN,LEN,3	/* decrement length */
109
110/*
111 * Copy 1 halfword from src to destination then copy words
112 */
113ASLOCAL(f_1half_word_copy)
114	ld.hu	r6,SRC,0	/* load half-word from source */
115	st.h	r6,DST,0	/* store half-word to destination */
116	addu	SRC,SRC,2	/* increment source pointer */
117	addu	DST,DST,2	/* increment destination pointer */
118	br.n	_ASM_LABEL(f_word_copy)	/* copy full words */
119	 subu	LEN,LEN,2	/* decrement remaining length */
120
121/*
122 * Copy 1 byte from src to destination then copy words
123 */
124ASLOCAL(f_1byte_word_copy)
125	ld.bu	r6,SRC,0	/* load 1 byte from source */
126	st.b	r6,DST,0	/* store 1 byte to destination */
127	addu	SRC,SRC,1	/* increment source pointer */
128	addu	DST,DST,1	/* increment destination pointer */
129	subu	LEN,LEN,1	/* decrement remaining length */
130	/* FALLTHROUGH */
131/*
132 * Copy as many full words as possible, 4 words per loop
133 */
134ASLOCAL(f_word_copy)
135	cmp	r10,LEN,16	/* see if we have 16 bytes remaining */
136	bb1	lo,r10,_ASM_LABEL(f_byte_copy)	/* not enough left, copy bytes */
137	ld	r6,SRC,0	/* load first word */
138	ld	r7,SRC,4	/* load second word */
139	ld	r8,SRC,8	/* load third word */
140	ld	r9,SRC,12	/* load fourth word */
141	st	r6,DST,0	/* store first word */
142	st	r7,DST,4	/* store second word */
143	st 	r8,DST,8	/* store third word */
144	st 	r9,DST,12	/* store fourth word */
145	addu	SRC,SRC,16	/* increment source pointer */
146	addu	DST,DST,16	/* increment destination pointer */
147	br.n	_ASM_LABEL(f_word_copy)	/* branch to copy another block */
148	 subu	LEN,LEN,16	/* decrement remaining length */
149
150ASLOCAL(f_1byte_half_copy)
151	ld.bu	r6,SRC,0	/* load 1 byte from source */
152	st.b	r6,DST,0	/* store 1 byte to destination */
153	addu	SRC,SRC,1	/* increment source pointer */
154	addu	DST,DST,1	/* increment destination pointer */
155	subu	LEN,LEN,1	/* decrement remaining length */
156	/* FALLTHROUGH */
157
158ASLOCAL(f_half_copy)
159	cmp	r10,LEN,16	/* see if we have 16 bytes remaining */
160	bb1	lo,r10,_ASM_LABEL(f_byte_copy)	/* not enough left, copy bytes */
161	ld.hu	r6,SRC,0	/* load first half-word */
162	ld.hu	r7,SRC,2	/* load second half-word */
163	ld.hu	r8,SRC,4	/* load third half-word */
164	ld.hu	r9,SRC,6	/* load fourth half-word */
165	ld.hu	r10,SRC,8	/* load fifth half-word */
166	ld.hu	r11,SRC,10	/* load sixth half-word */
167	ld.hu	r12,SRC,12	/* load seventh half-word */
168	ld.hu	r13,SRC,14	/* load eighth half-word */
169	st.h	r6,DST,0	/* store first half-word */
170	st.h	r7,DST,2	/* store second half-word */
171	st.h 	r8,DST,4	/* store third half-word */
172	st.h 	r9,DST,6	/* store fourth half-word */
173	st.h	r10,DST,8	/* store fifth half-word */
174	st.h	r11,DST,10	/* store sixth half-word */
175	st.h 	r12,DST,12	/* store seventh half-word */
176	st.h 	r13,DST,14	/* store eighth half-word */
177	addu	SRC,SRC,16	/* increment source pointer */
178	addu	DST,DST,16	/* increment destination pointer */
179	br.n	_ASM_LABEL(f_half_copy)	/* branch to copy another block */
180	 subu	LEN,LEN,16	/* decrement remaining length */
181
182ASLOCAL(f_byte_copy)
183	bcnd	eq0,LEN,_ASM_LABEL(bcopy_out)	/* branch if nothing left to copy */
184	ld.bu	r6,SRC,0	/* load byte from source */
185	st.b	r6,DST,0	/* store byte in destination */
186	addu	SRC,SRC,1	/* increment source pointer */
187	addu	DST,DST,1	/* increment destination pointer */
188	br.n	_ASM_LABEL(f_byte_copy)	/* branch for next byte */
189	 subu	LEN,LEN,1	/* decrement remaining length */
190
191#if defined(MEMMOVE) || defined(OVBCOPY)
192/*
193 * source address is less than destination address, copy in reverse
194 */
195ASLOCAL(bcopy_reverse)
196/*
197 * start copy pointers at end of data
198 */
199	addu	SRC,SRC,LEN	/* start source at end of data */
200	addu	DST,DST,LEN	/* start destination at end of data */
201/*
202 * check for short data
203 */
204	cmp 	r9,LEN,16	/* see if we have at least 16 bytes */
205	bb1	lt,r9,_ASM_LABEL(r_byte_copy)	/* copy bytes for small data length */
206/*
207 *	determine copy strategy based on alignment of source and destination
208 */
209	mask	r6,SRC,3	/* get 2 low order bits of source address */
210	mask	r7,DST,3	/* get 2 low order bits of destintation addr */
211	mak	r6,r6,0<4>	/* convert source bits to table offset */
212	mak	r7,r7,0<2>	/* convert destination bits to table offset */
213	or.u	r12,r0,hi16(_ASM_LABEL(r_strat))
214	or	r12,r12,lo16(_ASM_LABEL(r_strat))
215	addu	r6,r6,r7	/* compute final table offset for strategy */
216	ld	r12,r12,r6	/* load the strategy routine */
217	jmp	r12		/* branch to strategy routine */
218
219/*
220 * Copy three bytes from src to destination then copy words
221 */
222ASLOCAL(r_3byte_word_copy)
223	subu	SRC,SRC,3	/* decrement source pointer */
224	subu	DST,DST,3	/* decrement destination pointer */
225	ld.bu	r6,SRC,0	/* load byte from source */
226	ld.bu	r7,SRC,1	/* load byte from source */
227	ld.bu	r8,SRC,2	/* load byte from source */
228	st.b	r6,DST,0	/* store byte to destination */
229	st.b	r7,DST,1	/* store byte to destination */
230	st.b	r8,DST,2	/* store byte to destination */
231	br.n	_ASM_LABEL(r_word_copy)	/* copy full words */
232	 subu	LEN,LEN,3	/* decrement length */
233
234/*
235 * Copy 1 halfword from src to destination then copy words
236 */
237ASLOCAL(r_1half_word_copy)
238	subu	SRC,SRC,2	/* decrement source pointer */
239	subu	DST,DST,2	/* decrement destination pointer */
240	ld.hu	r6,SRC,0	/* load half-word from source */
241	st.h	r6,DST,0	/* store half-word to destination */
242	br.n	_ASM_LABEL(r_word_copy)	/* copy full words */
243	 subu	LEN,LEN,2	/* decrement remaining length */
244
245/*
246 * Copy 1 byte from src to destination then copy words
247 */
248ASLOCAL(r_1byte_word_copy)
249	subu	SRC,SRC,1	/* decrement source pointer */
250	subu	DST,DST,1	/* decrement destination pointer */
251	ld.bu	r6,SRC,0	/* load 1 byte from source */
252	st.b	r6,DST,0	/* store 1 byte to destination */
253	subu	LEN,LEN,1	/* decrement remaining length */
254	/* FALLTHROUGH */
255/*
256 * Copy as many full words as possible, 4 words per loop
257 */
258ASLOCAL(r_word_copy)
259	cmp	r10,LEN,16	/* see if we have 16 bytes remaining */
260	bb1	lo,r10,_ASM_LABEL(r_byte_copy)	/* not enough left, copy bytes */
261	subu	SRC,SRC,16	/* decrement source pointer */
262	subu	DST,DST,16	/* decrement destination pointer */
263	ld	r6,SRC,0	/* load first word */
264	ld	r7,SRC,4	/* load second word */
265	ld	r8,SRC,8	/* load third word */
266	ld	r9,SRC,12	/* load fourth word */
267	st	r6,DST,0	/* store first word */
268	st	r7,DST,4	/* store second word */
269	st 	r8,DST,8	/* store third word */
270	st 	r9,DST,12	/* store fourth word */
271	br.n	_ASM_LABEL(r_word_copy)	/* branch to copy another block */
272	 subu	LEN,LEN,16	/* decrement remaining length */
273
274ASLOCAL(r_1byte_half_copy)
275	subu	SRC,SRC,1	/* decrement source pointer */
276	subu	DST,DST,1	/* decrement destination pointer */
277	ld.bu	r6,SRC,0	/* load 1 byte from source */
278	st.b	r6,DST,0	/* store 1 byte to destination */
279	subu	LEN,LEN,1	/* decrement remaining length */
280	/* FALLTHROUGH */
281
282ASLOCAL(r_half_copy)
283	cmp	r10,LEN,16	/* see if we have 16 bytes remaining */
284	bb1	lo,r10,_ASM_LABEL(r_byte_copy)	/* not enough left, copy bytes */
285	subu	SRC,SRC,16	/* decrement source pointer */
286	subu	DST,DST,16	/* decrement destination pointer */
287	ld.hu	r6,SRC,0	/* load first half-word */
288	ld.hu	r7,SRC,2	/* load second half-word */
289	ld.hu	r8,SRC,4	/* load third half-word */
290	ld.hu	r9,SRC,6	/* load fourth half-word */
291	ld.hu	r10,SRC,8	/* load fifth half-word */
292	ld.hu	r11,SRC,10	/* load sixth half-word */
293	ld.hu	r12,SRC,12	/* load seventh half-word */
294	ld.hu	r13,SRC,14	/* load eighth half-word */
295	st.h	r6,DST,0	/* store first half-word */
296	st.h	r7,DST,2	/* store second half-word */
297	st.h 	r8,DST,4	/* store third half-word */
298	st.h 	r9,DST,6	/* store fourth half-word */
299	st.h	r10,DST,8	/* store fifth half-word */
300	st.h	r11,DST,10	/* store sixth half-word */
301	st.h 	r12,DST,12	/* store seventh half-word */
302	st.h 	r13,DST,14	/* store eighth half-word */
303	br.n	_ASM_LABEL(r_half_copy)	/* branch to copy another block */
304	 subu	LEN,LEN,16	/* decrement remaining length */
305
306ASLOCAL(r_byte_copy)
307	bcnd	eq0,LEN,_ASM_LABEL(bcopy_out)	/* branch if nothing left to copy */
308	subu	SRC,SRC,1		/* decrement source pointer */
309	subu	DST,DST,1		/* decrement destination pointer */
310	ld.bu	r6,SRC,0		/* load byte from source */
311	st.b	r6,DST,0		/* store byte in destination */
312	br.n	_ASM_LABEL(r_byte_copy)	/* branch for next byte */
313	 subu	LEN,LEN,1		/* decrement remaining length */
314#endif	/* MEMMOVE || OVBCOPY */
315
316ASLOCAL(bcopy_out)
317#if defined(MEMCPY) || defined(MEMMOVE)
318	jmp.n	r1		/* all done, return to caller */
319	 or	r2, SAVE, r0
320#else
321	jmp	r1		/* all done, return to caller */
322#endif
323
324	data
325	align	4
326ASLOCAL(f_strat)
327	word	_ASM_LABEL(f_word_copy)
328	word	_ASM_LABEL(f_byte_copy)
329	word	_ASM_LABEL(f_half_copy)
330	word	_ASM_LABEL(f_byte_copy)
331	word	_ASM_LABEL(f_byte_copy)
332	word	_ASM_LABEL(f_3byte_word_copy)
333	word	_ASM_LABEL(f_byte_copy)
334	word	_ASM_LABEL(f_1byte_half_copy)
335	word	_ASM_LABEL(f_half_copy)
336	word	_ASM_LABEL(f_byte_copy)
337	word	_ASM_LABEL(f_1half_word_copy)
338	word	_ASM_LABEL(f_byte_copy)
339	word	_ASM_LABEL(f_byte_copy)
340	word	_ASM_LABEL(f_1byte_half_copy)
341	word	_ASM_LABEL(f_byte_copy)
342	word	_ASM_LABEL(f_1byte_word_copy)
343
344#if defined(MEMMOVE) || defined(OVBCOPY)
345ASLOCAL(r_strat)
346	word	_ASM_LABEL(r_word_copy)
347	word	_ASM_LABEL(r_byte_copy)
348	word	_ASM_LABEL(r_half_copy)
349	word	_ASM_LABEL(r_byte_copy)
350	word	_ASM_LABEL(r_byte_copy)
351	word	_ASM_LABEL(r_1byte_word_copy)
352	word	_ASM_LABEL(r_byte_copy)
353	word	_ASM_LABEL(r_1byte_half_copy)
354	word	_ASM_LABEL(r_half_copy)
355	word	_ASM_LABEL(r_byte_copy)
356	word	_ASM_LABEL(r_1half_word_copy)
357	word	_ASM_LABEL(r_byte_copy)
358	word	_ASM_LABEL(r_byte_copy)
359	word	_ASM_LABEL(r_1byte_half_copy)
360	word	_ASM_LABEL(r_byte_copy)
361	word	_ASM_LABEL(r_3byte_word_copy)
362#endif
363