xref: /linux/arch/sparc/lib/memcpy.S (revision 367b8112fe2ea5c39a7bb4d263dcdd9b612fae18)
1/* memcpy.S: Sparc optimized memcpy and memmove code
2 * Hand optimized from GNU libc's memcpy and memmove
3 * Copyright (C) 1991,1996 Free Software Foundation
4 * Copyright (C) 1995 Linus Torvalds (Linus.Torvalds@helsinki.fi)
5 * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
6 * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be)
7 * Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
8 */
9
10#ifdef __KERNEL__
11
12#define FUNC(x) 											\
13	.globl	x;		\
14	.type	x,@function;	\
15	.align	4;											\
16x:
17
18#undef FASTER_REVERSE
19#undef FASTER_NONALIGNED
20#define FASTER_ALIGNED
21
22/* In kernel these functions don't return a value.
23 * One should use macros in asm/string.h for that purpose.
24 * We return 0, so that bugs are more apparent.
25 */
26#define SETUP_RETL
27#define RETL_INSN	clr	%o0
28
29#else
30
31/* libc */
32
33#include "DEFS.h"
34
35#define FASTER_REVERSE
36#define FASTER_NONALIGNED
37#define FASTER_ALIGNED
38
39#define SETUP_RETL	mov	%o0, %g6
40#define RETL_INSN	mov	%g6, %o0
41
42#endif
43
44/* Both these macros have to start with exactly the same insn */
45#define MOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7) \
46	ldd	[%src + (offset) + 0x00], %t0; \
47	ldd	[%src + (offset) + 0x08], %t2; \
48	ldd	[%src + (offset) + 0x10], %t4; \
49	ldd	[%src + (offset) + 0x18], %t6; \
50	st	%t0, [%dst + (offset) + 0x00]; \
51	st	%t1, [%dst + (offset) + 0x04]; \
52	st	%t2, [%dst + (offset) + 0x08]; \
53	st	%t3, [%dst + (offset) + 0x0c]; \
54	st	%t4, [%dst + (offset) + 0x10]; \
55	st	%t5, [%dst + (offset) + 0x14]; \
56	st	%t6, [%dst + (offset) + 0x18]; \
57	st	%t7, [%dst + (offset) + 0x1c];
58
59#define MOVE_BIGALIGNCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7) \
60	ldd	[%src + (offset) + 0x00], %t0; \
61	ldd	[%src + (offset) + 0x08], %t2; \
62	ldd	[%src + (offset) + 0x10], %t4; \
63	ldd	[%src + (offset) + 0x18], %t6; \
64	std	%t0, [%dst + (offset) + 0x00]; \
65	std	%t2, [%dst + (offset) + 0x08]; \
66	std	%t4, [%dst + (offset) + 0x10]; \
67	std	%t6, [%dst + (offset) + 0x18];
68
69#define MOVE_LASTCHUNK(src, dst, offset, t0, t1, t2, t3) \
70	ldd	[%src - (offset) - 0x10], %t0; \
71	ldd	[%src - (offset) - 0x08], %t2; \
72	st	%t0, [%dst - (offset) - 0x10]; \
73	st	%t1, [%dst - (offset) - 0x0c]; \
74	st	%t2, [%dst - (offset) - 0x08]; \
75	st	%t3, [%dst - (offset) - 0x04];
76
77#define MOVE_LASTALIGNCHUNK(src, dst, offset, t0, t1, t2, t3) \
78	ldd	[%src - (offset) - 0x10], %t0; \
79	ldd	[%src - (offset) - 0x08], %t2; \
80	std	%t0, [%dst - (offset) - 0x10]; \
81	std	%t2, [%dst - (offset) - 0x08];
82
83#define MOVE_SHORTCHUNK(src, dst, offset, t0, t1) \
84	ldub	[%src - (offset) - 0x02], %t0; \
85	ldub	[%src - (offset) - 0x01], %t1; \
86	stb	%t0, [%dst - (offset) - 0x02]; \
87	stb	%t1, [%dst - (offset) - 0x01];
88
89/* Both these macros have to start with exactly the same insn */
90#define RMOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7) \
91	ldd	[%src - (offset) - 0x20], %t0; \
92	ldd	[%src - (offset) - 0x18], %t2; \
93	ldd	[%src - (offset) - 0x10], %t4; \
94	ldd	[%src - (offset) - 0x08], %t6; \
95	st	%t0, [%dst - (offset) - 0x20]; \
96	st	%t1, [%dst - (offset) - 0x1c]; \
97	st	%t2, [%dst - (offset) - 0x18]; \
98	st	%t3, [%dst - (offset) - 0x14]; \
99	st	%t4, [%dst - (offset) - 0x10]; \
100	st	%t5, [%dst - (offset) - 0x0c]; \
101	st	%t6, [%dst - (offset) - 0x08]; \
102	st	%t7, [%dst - (offset) - 0x04];
103
104#define RMOVE_BIGALIGNCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7) \
105	ldd	[%src - (offset) - 0x20], %t0; \
106	ldd	[%src - (offset) - 0x18], %t2; \
107	ldd	[%src - (offset) - 0x10], %t4; \
108	ldd	[%src - (offset) - 0x08], %t6; \
109	std	%t0, [%dst - (offset) - 0x20]; \
110	std	%t2, [%dst - (offset) - 0x18]; \
111	std	%t4, [%dst - (offset) - 0x10]; \
112	std	%t6, [%dst - (offset) - 0x08];
113
114#define RMOVE_LASTCHUNK(src, dst, offset, t0, t1, t2, t3) \
115	ldd	[%src + (offset) + 0x00], %t0; \
116	ldd	[%src + (offset) + 0x08], %t2; \
117	st	%t0, [%dst + (offset) + 0x00]; \
118	st	%t1, [%dst + (offset) + 0x04]; \
119	st	%t2, [%dst + (offset) + 0x08]; \
120	st	%t3, [%dst + (offset) + 0x0c];
121
122#define RMOVE_SHORTCHUNK(src, dst, offset, t0, t1) \
123	ldub	[%src + (offset) + 0x00], %t0; \
124	ldub	[%src + (offset) + 0x01], %t1; \
125	stb	%t0, [%dst + (offset) + 0x00]; \
126	stb	%t1, [%dst + (offset) + 0x01];
127
128#define SMOVE_CHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, prev, shil, shir, offset2) \
129	ldd	[%src + (offset) + 0x00], %t0; \
130	ldd	[%src + (offset) + 0x08], %t2; \
131	srl	%t0, shir, %t5; \
132	srl	%t1, shir, %t6; \
133	sll	%t0, shil, %t0; \
134	or	%t5, %prev, %t5; \
135	sll	%t1, shil, %prev; \
136	or	%t6, %t0, %t0; \
137	srl	%t2, shir, %t1; \
138	srl	%t3, shir, %t6; \
139	sll	%t2, shil, %t2; \
140	or	%t1, %prev, %t1; \
141	std	%t4, [%dst + (offset) + (offset2) - 0x04]; \
142	std	%t0, [%dst + (offset) + (offset2) + 0x04]; \
143	sll	%t3, shil, %prev; \
144	or	%t6, %t2, %t4;
145
146#define SMOVE_ALIGNCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, prev, shil, shir, offset2) \
147	ldd	[%src + (offset) + 0x00], %t0; \
148	ldd	[%src + (offset) + 0x08], %t2; \
149	srl	%t0, shir, %t4;	\
150	srl	%t1, shir, %t5;	\
151	sll	%t0, shil, %t6;	\
152	or	%t4, %prev, %t0; \
153	sll	%t1, shil, %prev; \
154	or	%t5, %t6, %t1; \
155	srl	%t2, shir, %t4;	\
156	srl	%t3, shir, %t5;	\
157	sll	%t2, shil, %t6; \
158	or	%t4, %prev, %t2; \
159	sll	%t3, shil, %prev; \
160	or	%t5, %t6, %t3; \
161	std	%t0, [%dst + (offset) + (offset2) + 0x00]; \
162	std	%t2, [%dst + (offset) + (offset2) + 0x08];
163
164	.text
165	.align	4
166
167#ifdef FASTER_REVERSE
168
16970:	/* rdword_align */
170
171	andcc		%o1, 1, %g0
172	be		4f
173	 andcc		%o1, 2, %g0
174
175	ldub		[%o1 - 1], %g2
176	sub		%o1, 1, %o1
177	stb		%g2, [%o0 - 1]
178	sub		%o2, 1, %o2
179	be		3f
180	 sub		%o0, 1, %o0
1814:
182	lduh		[%o1 - 2], %g2
183	sub		%o1, 2, %o1
184	sth		%g2, [%o0 - 2]
185	sub		%o2, 2, %o2
186	b		3f
187	 sub		%o0, 2, %o0
188
189#endif /* FASTER_REVERSE */
190
1910:
192	retl
193	 nop		! Only bcopy returns here and it retuns void...
194
195#ifdef __KERNEL__
196FUNC(amemmove)
197FUNC(__memmove)
198#endif
199FUNC(memmove)
200	cmp		%o0, %o1
201	SETUP_RETL
202	bleu		9f
203	 sub		%o0, %o1, %o4
204
205	add		%o1, %o2, %o3
206	cmp		%o3, %o0
207	bleu		0f
208	 andcc		%o4, 3, %o5
209
210#ifndef FASTER_REVERSE
211
212	add		%o1, %o2, %o1
213	add		%o0, %o2, %o0
214	sub		%o1, 1, %o1
215	sub		%o0, 1, %o0
216
2171:	/* reverse_bytes */
218
219	ldub		[%o1], %o4
220	subcc		%o2, 1, %o2
221	stb		%o4, [%o0]
222	sub		%o1, 1, %o1
223	bne		1b
224	 sub		%o0, 1, %o0
225
226	retl
227	 RETL_INSN
228
229#else /* FASTER_REVERSE */
230
231	add		%o1, %o2, %o1
232	add		%o0, %o2, %o0
233	bne		77f
234	 cmp		%o2, 15
235	bleu		91f
236	 andcc		%o1, 3, %g0
237	bne		70b
2383:
239	 andcc		%o1, 4, %g0
240
241	be		2f
242	 mov		%o2, %g1
243
244	ld		[%o1 - 4], %o4
245	sub		%g1, 4, %g1
246	st		%o4, [%o0 - 4]
247	sub		%o1, 4, %o1
248	sub		%o0, 4, %o0
2492:
250	andcc		%g1, 0xffffff80, %g7
251	be		3f
252	 andcc		%o0, 4, %g0
253
254	be		74f + 4
2555:
256	RMOVE_BIGCHUNK(o1, o0, 0x00, o2, o3, o4, o5, g2, g3, g4, g5)
257	RMOVE_BIGCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5)
258	RMOVE_BIGCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5)
259	RMOVE_BIGCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5)
260	subcc		%g7, 128, %g7
261	sub		%o1, 128, %o1
262	bne		5b
263	 sub		%o0, 128, %o0
2643:
265	andcc		%g1, 0x70, %g7
266	be		72f
267	 andcc		%g1, 8, %g0
268
269	sethi		%hi(72f), %o5
270	srl		%g7, 1, %o4
271	add		%g7, %o4, %o4
272	sub		%o1, %g7, %o1
273	sub		%o5, %o4, %o5
274	jmpl		%o5 + %lo(72f), %g0
275	 sub		%o0, %g7, %o0
276
27771:	/* rmemcpy_table */
278	RMOVE_LASTCHUNK(o1, o0, 0x60, g2, g3, g4, g5)
279	RMOVE_LASTCHUNK(o1, o0, 0x50, g2, g3, g4, g5)
280	RMOVE_LASTCHUNK(o1, o0, 0x40, g2, g3, g4, g5)
281	RMOVE_LASTCHUNK(o1, o0, 0x30, g2, g3, g4, g5)
282	RMOVE_LASTCHUNK(o1, o0, 0x20, g2, g3, g4, g5)
283	RMOVE_LASTCHUNK(o1, o0, 0x10, g2, g3, g4, g5)
284	RMOVE_LASTCHUNK(o1, o0, 0x00, g2, g3, g4, g5)
285
28672:	/* rmemcpy_table_end */
287
288	be		73f
289	 andcc		%g1, 4, %g0
290
291	ldd		[%o1 - 0x08], %g2
292	sub		%o0, 8, %o0
293	sub		%o1, 8, %o1
294	st		%g2, [%o0]
295	st		%g3, [%o0 + 0x04]
296
29773:	/* rmemcpy_last7 */
298
299	be		1f
300	 andcc		%g1, 2, %g0
301
302	ld		[%o1 - 4], %g2
303	sub		%o1, 4, %o1
304	st		%g2, [%o0 - 4]
305	sub		%o0, 4, %o0
3061:
307	be		1f
308	 andcc		%g1, 1, %g0
309
310	lduh		[%o1 - 2], %g2
311	sub		%o1, 2, %o1
312	sth		%g2, [%o0 - 2]
313	sub		%o0, 2, %o0
3141:
315	be		1f
316	 nop
317
318	ldub		[%o1 - 1], %g2
319	stb		%g2, [%o0 - 1]
3201:
321	retl
322 	 RETL_INSN
323
32474:	/* rldd_std */
325	RMOVE_BIGALIGNCHUNK(o1, o0, 0x00, o2, o3, o4, o5, g2, g3, g4, g5)
326	RMOVE_BIGALIGNCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5)
327	RMOVE_BIGALIGNCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5)
328	RMOVE_BIGALIGNCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5)
329	subcc		%g7, 128, %g7
330	sub		%o1, 128, %o1
331	bne		74b
332	 sub		%o0, 128, %o0
333
334	andcc		%g1, 0x70, %g7
335	be		72b
336	 andcc		%g1, 8, %g0
337
338	sethi		%hi(72b), %o5
339	srl		%g7, 1, %o4
340	add		%g7, %o4, %o4
341	sub		%o1, %g7, %o1
342	sub		%o5, %o4, %o5
343	jmpl		%o5 + %lo(72b), %g0
344	 sub		%o0, %g7, %o0
345
34675:	/* rshort_end */
347
348	and		%o2, 0xe, %o3
3492:
350	sethi		%hi(76f), %o5
351	sll		%o3, 3, %o4
352	sub		%o0, %o3, %o0
353	sub		%o5, %o4, %o5
354	sub		%o1, %o3, %o1
355	jmpl		%o5 + %lo(76f), %g0
356	 andcc		%o2, 1, %g0
357
358	RMOVE_SHORTCHUNK(o1, o0, 0x0c, g2, g3)
359	RMOVE_SHORTCHUNK(o1, o0, 0x0a, g2, g3)
360	RMOVE_SHORTCHUNK(o1, o0, 0x08, g2, g3)
361	RMOVE_SHORTCHUNK(o1, o0, 0x06, g2, g3)
362	RMOVE_SHORTCHUNK(o1, o0, 0x04, g2, g3)
363	RMOVE_SHORTCHUNK(o1, o0, 0x02, g2, g3)
364	RMOVE_SHORTCHUNK(o1, o0, 0x00, g2, g3)
365
36676:	/* rshort_table_end */
367
368	be		1f
369	 nop
370	ldub		[%o1 - 1], %g2
371	stb		%g2, [%o0 - 1]
3721:
373	retl
374 	 RETL_INSN
375
37691:	/* rshort_aligned_end */
377
378	bne		75b
379	 andcc		%o2, 8, %g0
380
381	be		1f
382	 andcc		%o2, 4, %g0
383
384	ld		[%o1 - 0x08], %g2
385	ld		[%o1 - 0x04], %g3
386	sub		%o1, 8, %o1
387	st		%g2, [%o0 - 0x08]
388	st		%g3, [%o0 - 0x04]
389	sub		%o0, 8, %o0
3901:
391	b		73b
392	 mov		%o2, %g1
393
39477:	/* rnon_aligned */
395	cmp		%o2, 15
396	bleu		75b
397	 andcc		%o0, 3, %g0
398	be		64f
399	 andcc		%o0, 1, %g0
400	be		63f
401	 andcc		%o0, 2, %g0
402	ldub		[%o1 - 1], %g5
403	sub		%o1, 1, %o1
404	stb		%g5, [%o0 - 1]
405	sub		%o0, 1, %o0
406	be		64f
407	 sub		%o2, 1, %o2
40863:
409	ldub		[%o1 - 1], %g5
410	sub		%o1, 2, %o1
411	stb		%g5, [%o0 - 1]
412	sub		%o0, 2, %o0
413	ldub		[%o1], %g5
414	sub		%o2, 2, %o2
415	stb		%g5, [%o0]
41664:
417	and		%o1, 3, %g2
418	and		%o1, -4, %o1
419	and		%o2, 0xc, %g3
420	add		%o1, 4, %o1
421	cmp		%g3, 4
422	sll		%g2, 3, %g4
423	mov		32, %g2
424	be		4f
425	 sub		%g2, %g4, %g7
426
427	blu		3f
428	 cmp		%g3, 8
429
430	be		2f
431	 srl		%o2, 2, %g3
432
433	ld		[%o1 - 4], %o3
434	add		%o0, -8, %o0
435	ld		[%o1 - 8], %o4
436	add		%o1, -16, %o1
437	b		7f
438	 add		%g3, 1, %g3
4392:
440	ld		[%o1 - 4], %o4
441	add		%o0, -4, %o0
442	ld		[%o1 - 8], %g1
443	add		%o1, -12, %o1
444	b		8f
445	 add		%g3, 2, %g3
4463:
447	ld		[%o1 - 4], %o5
448	add		%o0, -12, %o0
449	ld		[%o1 - 8], %o3
450	add		%o1, -20, %o1
451	b		6f
452	 srl		%o2, 2, %g3
4534:
454	ld		[%o1 - 4], %g1
455	srl		%o2, 2, %g3
456	ld		[%o1 - 8], %o5
457	add		%o1, -24, %o1
458	add		%o0, -16, %o0
459	add		%g3, -1, %g3
460
461	ld		[%o1 + 12], %o3
4625:
463	sll		%o5, %g4, %g2
464	srl		%g1, %g7, %g5
465	or		%g2, %g5, %g2
466	st		%g2, [%o0 + 12]
4676:
468	ld		[%o1 + 8], %o4
469	sll		%o3, %g4, %g2
470	srl		%o5, %g7, %g5
471	or		%g2, %g5, %g2
472	st		%g2, [%o0 + 8]
4737:
474	ld		[%o1 + 4], %g1
475	sll		%o4, %g4, %g2
476	srl		%o3, %g7, %g5
477	or		%g2, %g5, %g2
478	st		%g2, [%o0 + 4]
4798:
480	ld		[%o1], %o5
481	sll		%g1, %g4, %g2
482	srl		%o4, %g7, %g5
483	addcc		%g3, -4, %g3
484	or		%g2, %g5, %g2
485	add		%o1, -16, %o1
486	st		%g2, [%o0]
487	add		%o0, -16, %o0
488	bne,a		5b
489	 ld		[%o1 + 12], %o3
490	sll		%o5, %g4, %g2
491	srl		%g1, %g7, %g5
492	srl		%g4, 3, %g3
493	or		%g2, %g5, %g2
494	add		%o1, %g3, %o1
495	andcc		%o2, 2, %g0
496	st		%g2, [%o0 + 12]
497	be		1f
498	 andcc		%o2, 1, %g0
499
500	ldub		[%o1 + 15], %g5
501	add		%o1, -2, %o1
502	stb		%g5, [%o0 + 11]
503	add		%o0, -2, %o0
504	ldub		[%o1 + 16], %g5
505	stb		%g5, [%o0 + 12]
5061:
507	be		1f
508	 nop
509	ldub		[%o1 + 15], %g5
510	stb		%g5, [%o0 + 11]
5111:
512	retl
513	 RETL_INSN
514
515#endif /* FASTER_REVERSE */
516
517/* NOTE: This code is executed just for the cases,
518         where %src (=%o1) & 3 is != 0.
519	 We need to align it to 4. So, for (%src & 3)
520	 1 we need to do ldub,lduh
521	 2 lduh
522	 3 just ldub
523         so even if it looks weird, the branches
524         are correct here. -jj
525 */
52678:	/* dword_align */
527
528	andcc		%o1, 1, %g0
529	be		4f
530	 andcc		%o1, 2, %g0
531
532	ldub		[%o1], %g2
533	add		%o1, 1, %o1
534	stb		%g2, [%o0]
535	sub		%o2, 1, %o2
536	bne		3f
537	 add		%o0, 1, %o0
5384:
539	lduh		[%o1], %g2
540	add		%o1, 2, %o1
541	sth		%g2, [%o0]
542	sub		%o2, 2, %o2
543	b		3f
544	 add		%o0, 2, %o0
545
546#ifdef __KERNEL__
547FUNC(__memcpy)
548#endif
549FUNC(memcpy)	/* %o0=dst %o1=src %o2=len */
550
551	sub		%o0, %o1, %o4
552	SETUP_RETL
5539:
554	andcc		%o4, 3, %o5
5550:
556	bne		86f
557	 cmp		%o2, 15
558
559	bleu		90f
560	 andcc		%o1, 3, %g0
561
562	bne		78b
5633:
564	 andcc		%o1, 4, %g0
565
566	be		2f
567	 mov		%o2, %g1
568
569	ld		[%o1], %o4
570	sub		%g1, 4, %g1
571	st		%o4, [%o0]
572	add		%o1, 4, %o1
573	add		%o0, 4, %o0
5742:
575	andcc		%g1, 0xffffff80, %g7
576	be		3f
577	 andcc		%o0, 4, %g0
578
579	be		82f + 4
5805:
581	MOVE_BIGCHUNK(o1, o0, 0x00, o2, o3, o4, o5, g2, g3, g4, g5)
582	MOVE_BIGCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5)
583	MOVE_BIGCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5)
584	MOVE_BIGCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5)
585	subcc		%g7, 128, %g7
586	add		%o1, 128, %o1
587	bne		5b
588	 add		%o0, 128, %o0
5893:
590	andcc		%g1, 0x70, %g7
591	be		80f
592	 andcc		%g1, 8, %g0
593
594	sethi		%hi(80f), %o5
595	srl		%g7, 1, %o4
596	add		%g7, %o4, %o4
597	add		%o1, %g7, %o1
598	sub		%o5, %o4, %o5
599	jmpl		%o5 + %lo(80f), %g0
600	 add		%o0, %g7, %o0
601
60279:	/* memcpy_table */
603
604	MOVE_LASTCHUNK(o1, o0, 0x60, g2, g3, g4, g5)
605	MOVE_LASTCHUNK(o1, o0, 0x50, g2, g3, g4, g5)
606	MOVE_LASTCHUNK(o1, o0, 0x40, g2, g3, g4, g5)
607	MOVE_LASTCHUNK(o1, o0, 0x30, g2, g3, g4, g5)
608	MOVE_LASTCHUNK(o1, o0, 0x20, g2, g3, g4, g5)
609	MOVE_LASTCHUNK(o1, o0, 0x10, g2, g3, g4, g5)
610	MOVE_LASTCHUNK(o1, o0, 0x00, g2, g3, g4, g5)
611
61280:	/* memcpy_table_end */
613	be		81f
614	 andcc		%g1, 4, %g0
615
616	ldd		[%o1], %g2
617	add		%o0, 8, %o0
618	st		%g2, [%o0 - 0x08]
619	add		%o1, 8, %o1
620	st		%g3, [%o0 - 0x04]
621
62281:	/* memcpy_last7 */
623
624	be		1f
625	 andcc		%g1, 2, %g0
626
627	ld		[%o1], %g2
628	add		%o1, 4, %o1
629	st		%g2, [%o0]
630	add		%o0, 4, %o0
6311:
632	be		1f
633	 andcc		%g1, 1, %g0
634
635	lduh		[%o1], %g2
636	add		%o1, 2, %o1
637	sth		%g2, [%o0]
638	add		%o0, 2, %o0
6391:
640	be		1f
641	 nop
642
643	ldub		[%o1], %g2
644	stb		%g2, [%o0]
6451:
646	retl
647 	 RETL_INSN
648
64982:	/* ldd_std */
650	MOVE_BIGALIGNCHUNK(o1, o0, 0x00, o2, o3, o4, o5, g2, g3, g4, g5)
651	MOVE_BIGALIGNCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5)
652	MOVE_BIGALIGNCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5)
653	MOVE_BIGALIGNCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5)
654	subcc		%g7, 128, %g7
655	add		%o1, 128, %o1
656	bne		82b
657	 add		%o0, 128, %o0
658
659#ifndef FASTER_ALIGNED
660
661	andcc		%g1, 0x70, %g7
662	be		80b
663	 andcc		%g1, 8, %g0
664
665	sethi		%hi(80b), %o5
666	srl		%g7, 1, %o4
667	add		%g7, %o4, %o4
668	add		%o1, %g7, %o1
669	sub		%o5, %o4, %o5
670	jmpl		%o5 + %lo(80b), %g0
671	 add		%o0, %g7, %o0
672
673#else /* FASTER_ALIGNED */
674
675	andcc		%g1, 0x70, %g7
676	be		84f
677	 andcc		%g1, 8, %g0
678
679	sethi		%hi(84f), %o5
680	add		%o1, %g7, %o1
681	sub		%o5, %g7, %o5
682	jmpl		%o5 + %lo(84f), %g0
683	 add		%o0, %g7, %o0
684
68583:	/* amemcpy_table */
686
687	MOVE_LASTALIGNCHUNK(o1, o0, 0x60, g2, g3, g4, g5)
688	MOVE_LASTALIGNCHUNK(o1, o0, 0x50, g2, g3, g4, g5)
689	MOVE_LASTALIGNCHUNK(o1, o0, 0x40, g2, g3, g4, g5)
690	MOVE_LASTALIGNCHUNK(o1, o0, 0x30, g2, g3, g4, g5)
691	MOVE_LASTALIGNCHUNK(o1, o0, 0x20, g2, g3, g4, g5)
692	MOVE_LASTALIGNCHUNK(o1, o0, 0x10, g2, g3, g4, g5)
693	MOVE_LASTALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5)
694
69584:	/* amemcpy_table_end */
696	be		85f
697	 andcc		%g1, 4, %g0
698
699	ldd		[%o1], %g2
700	add		%o0, 8, %o0
701	std		%g2, [%o0 - 0x08]
702	add		%o1, 8, %o1
70385:	/* amemcpy_last7 */
704	be		1f
705	 andcc		%g1, 2, %g0
706
707	ld		[%o1], %g2
708	add		%o1, 4, %o1
709	st		%g2, [%o0]
710	add		%o0, 4, %o0
7111:
712	be		1f
713	 andcc		%g1, 1, %g0
714
715	lduh		[%o1], %g2
716	add		%o1, 2, %o1
717	sth		%g2, [%o0]
718	add		%o0, 2, %o0
7191:
720	be		1f
721	 nop
722
723	ldub		[%o1], %g2
724	stb		%g2, [%o0]
7251:
726	retl
727 	 RETL_INSN
728
729#endif /* FASTER_ALIGNED */
730
73186:	/* non_aligned */
732	cmp		%o2, 6
733	bleu		88f
734
735#ifdef FASTER_NONALIGNED
736
737	 cmp		%o2, 256
738	bcc		87f
739
740#endif /* FASTER_NONALIGNED */
741
742	 andcc		%o0, 3, %g0
743	be		61f
744	 andcc		%o0, 1, %g0
745	be		60f
746	 andcc		%o0, 2, %g0
747
748	ldub		[%o1], %g5
749	add		%o1, 1, %o1
750	stb		%g5, [%o0]
751	sub		%o2, 1, %o2
752	bne		61f
753	 add		%o0, 1, %o0
75460:
755	ldub		[%o1], %g3
756	add		%o1, 2, %o1
757	stb		%g3, [%o0]
758	sub		%o2, 2, %o2
759	ldub		[%o1 - 1], %g3
760	add		%o0, 2, %o0
761	stb		%g3, [%o0 - 1]
76261:
763	and		%o1, 3, %g2
764	and		%o2, 0xc, %g3
765	and		%o1, -4, %o1
766	cmp		%g3, 4
767	sll		%g2, 3, %g4
768	mov		32, %g2
769	be		4f
770	 sub		%g2, %g4, %g7
771
772	blu		3f
773	 cmp		%g3, 0x8
774
775	be		2f
776	 srl		%o2, 2, %g3
777
778	ld		[%o1], %o3
779	add		%o0, -8, %o0
780	ld		[%o1 + 4], %o4
781	b		8f
782	 add		%g3, 1, %g3
7832:
784	ld		[%o1], %o4
785	add		%o0, -12, %o0
786	ld		[%o1 + 4], %o5
787	add		%g3, 2, %g3
788	b		9f
789	 add		%o1, -4, %o1
7903:
791	ld		[%o1], %g1
792	add		%o0, -4, %o0
793	ld		[%o1 + 4], %o3
794	srl		%o2, 2, %g3
795	b		7f
796	 add		%o1, 4, %o1
7974:
798	ld		[%o1], %o5
799	cmp		%o2, 7
800	ld		[%o1 + 4], %g1
801	srl		%o2, 2, %g3
802	bleu		10f
803	 add		%o1, 8, %o1
804
805	ld		[%o1], %o3
806	add		%g3, -1, %g3
8075:
808	sll		%o5, %g4, %g2
809	srl		%g1, %g7, %g5
810	or		%g2, %g5, %g2
811	st		%g2, [%o0]
8127:
813	ld		[%o1 + 4], %o4
814	sll		%g1, %g4, %g2
815	srl		%o3, %g7, %g5
816	or		%g2, %g5, %g2
817	st		%g2, [%o0 + 4]
8188:
819	ld		[%o1 + 8], %o5
820	sll		%o3, %g4, %g2
821	srl		%o4, %g7, %g5
822	or		%g2, %g5, %g2
823	st		%g2, [%o0 + 8]
8249:
825	ld		[%o1 + 12], %g1
826	sll		%o4, %g4, %g2
827	srl		%o5, %g7, %g5
828	addcc		%g3, -4, %g3
829	or		%g2, %g5, %g2
830	add		%o1, 16, %o1
831	st		%g2, [%o0 + 12]
832	add		%o0, 16, %o0
833	bne,a		5b
834	 ld		[%o1], %o3
83510:
836	sll		%o5, %g4, %g2
837	srl		%g1, %g7, %g5
838	srl		%g7, 3, %g3
839	or		%g2, %g5, %g2
840	sub		%o1, %g3, %o1
841	andcc		%o2, 2, %g0
842	st		%g2, [%o0]
843	be		1f
844	 andcc		%o2, 1, %g0
845
846	ldub		[%o1], %g2
847	add		%o1, 2, %o1
848	stb		%g2, [%o0 + 4]
849	add		%o0, 2, %o0
850	ldub		[%o1 - 1], %g2
851	stb		%g2, [%o0 + 3]
8521:
853	be		1f
854	 nop
855	ldub		[%o1], %g2
856	stb		%g2, [%o0 + 4]
8571:
858	retl
859	 RETL_INSN
860
861#ifdef FASTER_NONALIGNED
862
86387:	/* faster_nonaligned */
864
865	andcc		%o1, 3, %g0
866	be		3f
867	 andcc		%o1, 1, %g0
868
869	be		4f
870	 andcc		%o1, 2, %g0
871
872	ldub		[%o1], %g2
873	add		%o1, 1, %o1
874	stb		%g2, [%o0]
875	sub		%o2, 1, %o2
876	bne		3f
877	 add		%o0, 1, %o0
8784:
879	lduh		[%o1], %g2
880	add		%o1, 2, %o1
881	srl		%g2, 8, %g3
882	sub		%o2, 2, %o2
883	stb		%g3, [%o0]
884	add		%o0, 2, %o0
885	stb		%g2, [%o0 - 1]
8863:
887	 andcc		%o1, 4, %g0
888
889	bne		2f
890	 cmp		%o5, 1
891
892	ld		[%o1], %o4
893	srl		%o4, 24, %g2
894	stb		%g2, [%o0]
895	srl		%o4, 16, %g3
896	stb		%g3, [%o0 + 1]
897	srl		%o4, 8, %g2
898	stb		%g2, [%o0 + 2]
899	sub		%o2, 4, %o2
900	stb		%o4, [%o0 + 3]
901	add		%o1, 4, %o1
902	add		%o0, 4, %o0
9032:
904	be		33f
905	 cmp		%o5, 2
906	be		32f
907	 sub		%o2, 4, %o2
90831:
909	ld		[%o1], %g2
910	add		%o1, 4, %o1
911	srl		%g2, 24, %g3
912	and		%o0, 7, %g5
913	stb		%g3, [%o0]
914	cmp		%g5, 7
915	sll		%g2, 8, %g1
916	add		%o0, 4, %o0
917	be		41f
918	 and		%o2, 0xffffffc0, %o3
919	ld		[%o0 - 7], %o4
9204:
921	SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
922	SMOVE_CHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
923	SMOVE_CHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
924	SMOVE_CHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
925	subcc		%o3, 64, %o3
926	add		%o1, 64, %o1
927	bne		4b
928	 add		%o0, 64, %o0
929
930	andcc		%o2, 0x30, %o3
931	be,a		1f
932	 srl		%g1, 16, %g2
9334:
934	SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
935	subcc		%o3, 16, %o3
936	add		%o1, 16, %o1
937	bne		4b
938	 add		%o0, 16, %o0
939
940	srl		%g1, 16, %g2
9411:
942	st		%o4, [%o0 - 7]
943	sth		%g2, [%o0 - 3]
944	srl		%g1, 8, %g4
945	b		88f
946	 stb		%g4, [%o0 - 1]
94732:
948	ld		[%o1], %g2
949	add		%o1, 4, %o1
950	srl		%g2, 16, %g3
951	and		%o0, 7, %g5
952	sth		%g3, [%o0]
953	cmp		%g5, 6
954	sll		%g2, 16, %g1
955	add		%o0, 4, %o0
956	be		42f
957	 and		%o2, 0xffffffc0, %o3
958	ld		[%o0 - 6], %o4
9594:
960	SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
961	SMOVE_CHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
962	SMOVE_CHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
963	SMOVE_CHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
964	subcc		%o3, 64, %o3
965	add		%o1, 64, %o1
966	bne		4b
967	 add		%o0, 64, %o0
968
969	andcc		%o2, 0x30, %o3
970	be,a		1f
971	 srl		%g1, 16, %g2
9724:
973	SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
974	subcc		%o3, 16, %o3
975	add		%o1, 16, %o1
976	bne		4b
977	 add		%o0, 16, %o0
978
979	srl		%g1, 16, %g2
9801:
981	st		%o4, [%o0 - 6]
982	b		88f
983	 sth		%g2, [%o0 - 2]
98433:
985	ld		[%o1], %g2
986	sub		%o2, 4, %o2
987	srl		%g2, 24, %g3
988	and		%o0, 7, %g5
989	stb		%g3, [%o0]
990	cmp		%g5, 5
991	srl		%g2, 8, %g4
992	sll		%g2, 24, %g1
993	sth		%g4, [%o0 + 1]
994	add		%o1, 4, %o1
995	be		43f
996	 and		%o2, 0xffffffc0, %o3
997
998	ld		[%o0 - 1], %o4
999	add		%o0, 4, %o0
10004:
1001	SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, -1)
1002	SMOVE_CHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, -1)
1003	SMOVE_CHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, -1)
1004	SMOVE_CHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, -1)
1005	subcc		%o3, 64, %o3
1006	add		%o1, 64, %o1
1007	bne		4b
1008	 add		%o0, 64, %o0
1009
1010	andcc		%o2, 0x30, %o3
1011	be,a		1f
1012	 srl		%g1, 24, %g2
10134:
1014	SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, -1)
1015	subcc		%o3, 16, %o3
1016	add		%o1, 16, %o1
1017	bne		4b
1018	 add		%o0, 16, %o0
1019
1020	srl		%g1, 24, %g2
10211:
1022	st		%o4, [%o0 - 5]
1023	b		88f
1024	 stb		%g2, [%o0 - 1]
102541:
1026	SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
1027	SMOVE_ALIGNCHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
1028	SMOVE_ALIGNCHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
1029	SMOVE_ALIGNCHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
1030	subcc		%o3, 64, %o3
1031	add		%o1, 64, %o1
1032	bne		41b
1033	 add		%o0, 64, %o0
1034
1035	andcc		%o2, 0x30, %o3
1036	be,a		1f
1037	 srl		%g1, 16, %g2
10384:
1039	SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
1040	subcc		%o3, 16, %o3
1041	add		%o1, 16, %o1
1042	bne		4b
1043	 add		%o0, 16, %o0
1044
1045	srl		%g1, 16, %g2
10461:
1047	sth		%g2, [%o0 - 3]
1048	srl		%g1, 8, %g4
1049	b		88f
1050	 stb		%g4, [%o0 - 1]
105143:
1052	SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, 3)
1053	SMOVE_ALIGNCHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, 3)
1054	SMOVE_ALIGNCHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, 3)
1055	SMOVE_ALIGNCHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, 3)
1056	subcc		%o3, 64, %o3
1057	add		%o1, 64, %o1
1058	bne		43b
1059	 add		%o0, 64, %o0
1060
1061	andcc		%o2, 0x30, %o3
1062	be,a		1f
1063	 srl		%g1, 24, %g2
10644:
1065	SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, 3)
1066	subcc		%o3, 16, %o3
1067	add		%o1, 16, %o1
1068	bne		4b
1069	 add		%o0, 16, %o0
1070
1071	srl		%g1, 24, %g2
10721:
1073	stb		%g2, [%o0 + 3]
1074	b		88f
1075	 add		%o0, 4, %o0
107642:
1077	SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
1078	SMOVE_ALIGNCHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
1079	SMOVE_ALIGNCHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
1080	SMOVE_ALIGNCHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
1081	subcc		%o3, 64, %o3
1082	add		%o1, 64, %o1
1083	bne		42b
1084	 add		%o0, 64, %o0
1085
1086	andcc		%o2, 0x30, %o3
1087	be,a		1f
1088	 srl		%g1, 16, %g2
10894:
1090	SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
1091	subcc		%o3, 16, %o3
1092	add		%o1, 16, %o1
1093	bne		4b
1094	 add		%o0, 16, %o0
1095
1096	srl		%g1, 16, %g2
10971:
1098	sth		%g2, [%o0 - 2]
1099
1100	/* Fall through */
1101
1102#endif /* FASTER_NONALIGNED */
1103
110488:	/* short_end */
1105
1106	and		%o2, 0xe, %o3
110720:
1108	sethi		%hi(89f), %o5
1109	sll		%o3, 3, %o4
1110	add		%o0, %o3, %o0
1111	sub		%o5, %o4, %o5
1112	add		%o1, %o3, %o1
1113	jmpl		%o5 + %lo(89f), %g0
1114	 andcc		%o2, 1, %g0
1115
1116	MOVE_SHORTCHUNK(o1, o0, 0x0c, g2, g3)
1117	MOVE_SHORTCHUNK(o1, o0, 0x0a, g2, g3)
1118	MOVE_SHORTCHUNK(o1, o0, 0x08, g2, g3)
1119	MOVE_SHORTCHUNK(o1, o0, 0x06, g2, g3)
1120	MOVE_SHORTCHUNK(o1, o0, 0x04, g2, g3)
1121	MOVE_SHORTCHUNK(o1, o0, 0x02, g2, g3)
1122	MOVE_SHORTCHUNK(o1, o0, 0x00, g2, g3)
1123
112489:	/* short_table_end */
1125
1126	be		1f
1127	 nop
1128
1129	ldub		[%o1], %g2
1130	stb		%g2, [%o0]
11311:
1132	retl
1133 	 RETL_INSN
1134
113590:	/* short_aligned_end */
1136	bne		88b
1137	 andcc		%o2, 8, %g0
1138
1139	be		1f
1140	 andcc		%o2, 4, %g0
1141
1142	ld		[%o1 + 0x00], %g2
1143	ld		[%o1 + 0x04], %g3
1144	add		%o1, 8, %o1
1145	st		%g2, [%o0 + 0x00]
1146	st		%g3, [%o0 + 0x04]
1147	add		%o0, 8, %o0
11481:
1149	b		81b
1150	 mov		%o2, %g1
1151