xref: /titanic_44/usr/src/lib/libc/capabilities/sun4u/common/memcpy.s (revision 665923daaf9b7b5ee8ba9b9f1937776cf0f499db)
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22/*
23 * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26	.file	"memcpy.s"
27
28/*
29 * memcpy(s1, s2, len)
30 *
31 * Copy s2 to s1, always copy n bytes.
32 * Note: this does not work for overlapped copies, bcopy() does
33 *
34 * Fast assembler language version of the following C-program for memcpy
35 * which represents the `standard' for the C-library.
36 *
37 *	void *
38 *	memcpy(void *s, const void *s0, size_t n)
39 *	{
40 *		if (n != 0) {
41 *	   	    char *s1 = s;
42 *		    const char *s2 = s0;
43 *		    do {
44 *			*s1++ = *s2++;
45 *		    } while (--n != 0);
46 *		}
47 *		return ( s );
48 *	}
49 */
50
51#include <sys/asm_linkage.h>
52#include <sys/sun4asi.h>
53#include <sys/trap.h>
54
55	ANSI_PRAGMA_WEAK(memmove,function)
56	ANSI_PRAGMA_WEAK(memcpy,function)
57
58	ENTRY(memmove)
59	cmp	%o1, %o0	! if from address is >= to use forward copy
60	bgeu	%ncc, forcpy	! else use backward if ...
61	sub	%o0, %o1, %o4	! get difference of two addresses
62	cmp	%o2, %o4	! compare size and difference of addresses
63	bleu	%ncc, forcpy	! if size is bigger, do overlapped copy
64	nop
65
66        !
67        ! an overlapped copy that must be done "backwards"
68        !
69.ovbc:
70	mov	%o0, %o5		! save des address for return val
71	add     %o1, %o2, %o1           ! get to end of source space
72        add     %o0, %o2, %o0           ! get to end of destination space
73
74.chksize:
75	cmp	%o2, 8
76	bgeu,pn	%ncc, .dbalign
77	nop
78
79
80.byte:
811:	deccc	%o2			! decrement count
82	blu,pn	%ncc, exit		! loop until done
83	dec	%o0			! decrement to address
84	dec	%o1			! decrement from address
85        ldub	[%o1], %o3		! read a byte
86        ba	1b			! loop until done
87	stb	%o3, [%o0]		! write byte
88
89.dbalign:
90	andcc	%o0, 7, %o3
91	bz	%ncc, .dbbck
92	nop
93	dec	%o1
94	dec	%o0
95	dec	%o2
96	ldub	[%o1], %o3
97	ba	.chksize
98	stb	%o3, [%o0]
99
100.dbbck:
101
102        rd      %fprs, %o3              ! o3 = fprs
103
104
105        ! if fprs.fef == 0, set it. Checking it, reqires 2 instructions.
106        ! So set it anyway, without checking.
107        wr      %g0, 0x4, %fprs         ! fprs.fef = 1
108
109        alignaddr	%o1, %g0, %g1		! align src
110        ldd	[%g1], %d0		! get first 8 byte block
111	sub	%g1, 8, %g1
112	andn	%o2, 7, %o4
113	sub	%o1, %o4, %o1
114
1152:
116	sub	%o0, 8, %o0		! since we are at the end
117					! when we first enter the loop
118        ldd	[%g1], %d2
119        faligndata %d2, %d0, %d8	! extract 8 bytes out
120        std	%d8, [%o0]		! store it
121
122	sub	%g1, 8, %g1
123        sub	%o2, 8, %o2		! 8 less bytes to copy
124	cmp	%o2, 8			! or do we have < 8 bytes
125        bgeu,pt	%ncc, 2b
126	fmovd	%d2, %d0
127
128        and     %o3, 0x4, %o3           ! fprs.du = fprs.dl = 0
129        ba      .byte
130        wr      %o3, %g0, %fprs         ! fprs = o3 - restore fprs
131
132	SET_SIZE(memmove)
133
134
135	ENTRY(memcpy)
136	ENTRY(__align_cpy_1)
137forcpy:
138	mov	%o0, %o5		! save des address for return val
139
140	cmp	%o2, 32			! for small counts copy bytes
141	bgu,a	%ncc, .alignsrc
142	andcc   %o1, 7, %o3             ! is src aligned on a 8 byte bound
143
144.bytecp:
145	! Do byte copy
146	tst	%o2
147	bleu,a,pn %ncc, exit
148	nop
149
1501:	ldub	[%o1], %o4
151	inc 	%o1
152	inc	%o0
153	deccc	%o2
154	bgu	%ncc, 1b
155	stb	%o4, [%o0 - 1]
156
157exit:
158	retl
159	mov	%o5, %o0
160
161.alignsrc:
162        bz      %ncc, .bigcpy		! src already double aligned
163	sub     %o3, 8, %o3
164        neg     %o3                     ! bytes till src double aligned
165
166        sub     %o2, %o3, %o2           ! update o2 with new count
167
168	! Copy %o3 bytes till double aligned
169
1702:      ldub    [%o1], %o4
171        inc     %o1
172        inc     %o0
173        deccc   %o3
174        bgu	%ncc, 2b
175        stb     %o4, [%o0 - 1]
176
177	! Now Source (%o1) is double word aligned
178
179.bigcpy: 				! >= 17 bytes to copy
180	andcc	%o0, 7, %o3		! is dst aligned on a 8 byte bound
181        bz      %ncc, .blkchk		! already double aligned
182	sub     %o3, 8, %o3
183        neg     %o3                     ! bytes till double aligned
184
185        sub     %o2, %o3, %o2           ! update o2 with new count
186
187	! Copy %o3 bytes till double aligned
188
1893:      ldub    [%o1], %o4
190        inc     %o1
191        inc     %o0
192        deccc   %o3
193        bgu	%ncc, 3b
194        stb     %o4, [%o0 - 1]
195
196	! Now Destination (%o0) is double word aligned
197.blkchk:
198	cmp     %o2, 384		! if cnt < 256 + 128 -  no Block ld/st
199	bgeu,a	%ncc, blkcpy		!    do double word copy
200	subcc	%o0, %o1, %o4		! %o4 = dest - src
201
202	! double word copy - using ldd and faligndata. Copies upto
203	! 8 byte multiple count and does byte copy for the residual.
204.dwcpy:
205	rd	%fprs, %o3		! o3 = fprs
206
207	! if fprs.fef == 0, set it. Checking it, reqires 2 instructions.
208	! So set it anyway, without checking.
209	wr	%g0, 0x4, %fprs 	! fprs.fef = 1
210	andn    %o2, 7, %o4     	! o4 has 8 byte aligned cnt
211	sub	%o4, 8, %o4
212        alignaddr %o1, %g0, %g1
213        ldd     [%g1], %d0
214        add     %g1, 8, %g1
2154:
216        ldd     [%g1], %d2
217        add     %g1, 8, %g1
218        sub     %o2, 8, %o2
219        subcc   %o4, 8, %o4
220        faligndata %d0, %d2, %d8
221        std     %d8, [%o0]
222        add     %o1, 8, %o1
223        bz,pn   %ncc, .residcp
224        add     %o0, 8, %o0
225        ldd     [%g1], %d0
226        add     %g1, 8, %g1
227        sub     %o2, 8, %o2
228        subcc   %o4, 8, %o4
229        faligndata %d2, %d0, %d8
230        std     %d8, [%o0]
231        add     %o1, 8, %o1
232        bgu,pn	%ncc, 4b
233        add     %o0, 8, %o0
234
235.residcp:				! Do byte copy
236	tst	%o2
237	bz,a,pn %ncc, dwexit
238	nop
239
2405:	ldub	[%o1], %o4
241	inc 	%o1
242	inc	%o0
243	deccc	%o2
244	bgu	%ncc, 5b
245	stb	%o4, [%o0 - 1]
246
247dwexit:
248        and     %o3, 0x4, %o3           ! fprs.du = fprs.dl = 0
249        wr      %o3, %g0, %fprs         ! fprs = o3 - restore fprs
250	retl
251	mov	%o5, %o0
252
253blkcpy:
254	! subcc	%o0, %o1, %o4		! in delay slot of branch
255	bneg,a,pn %ncc, 1f		! %o4 = abs(%o4)
256	neg	%o4
2571:
258	/*
259	 * Compare against 256 since we should be checking block addresses
260	 * and (dest & ~63) - (src & ~63) can be 3 blocks even if
261	 * src = dest + (64 * 3) + 63.
262	 */
263	cmp	%o4, 256		! if smaller than 3 blocks skip
264	blu,pn	%ncc, .dwcpy		! and do it the slower way
265	andcc	%o0, 63, %o3
266
267	save    %sp, -SA(MINFRAME), %sp
268        rd      %fprs, %l3              ! l3 = fprs
269
270        ! if fprs.fef == 0, set it. Checking it, reqires 2 instructions.
271        ! So set it anyway, without checking.
272        wr      %g0, 0x4, %fprs         ! fprs.fef = 1
273
274        bz,pn   %ncc, blalign           ! now block aligned
275        sub     %i3, 64, %i3
276        neg     %i3                     ! bytes till block aligned
277	sub	%i2, %i3, %i2		! update %i2 with new count
278
279	! Copy %i3 bytes till dst is block (64 byte) aligned. use
280	! double word copies.
281
282        alignaddr %i1, %g0, %g1
283        ldd     [%g1], %d0
284        add     %g1, 8, %g1
2856:
286        ldd     [%g1], %d2
287        add     %g1, 8, %g1
288        subcc   %i3, 8, %i3
289        faligndata %d0, %d2, %d8
290        std     %d8, [%i0]
291        add     %i1, 8, %i1
292        bz,pn   %ncc, blalign
293        add     %i0, 8, %i0
294        ldd     [%g1], %d0
295        add     %g1, 8, %g1
296        subcc   %i3, 8, %i3
297        faligndata %d2, %d0, %d8
298        std     %d8, [%i0]
299        add     %i1, 8, %i1
300        bgu,pn	%ncc, 6b
301        add     %i0, 8, %i0
302
303blalign:
304	membar  #StoreLoad
305	! %i2 = total length
306	! %i3 = blocks  (length - 64) / 64
307	! %i4 = doubles remaining  (length - blocks)
308	sub	%i2, 64, %i3
309	andn	%i3, 63, %i3
310	sub	%i2, %i3, %i4
311	andn	%i4, 7, %i4
312	sub	%i4, 16, %i4
313	sub	%i2, %i4, %i2
314	sub	%i2, %i3, %i2
315
316	andn	%i1, 0x3F, %l7		! blk aligned address
317	alignaddr %i1, %g0, %g0		! gen %gsr
318
319	srl	%i1, 3, %l5		! bits 3,4,5 are now least sig in  %l5
320	andcc  	%l5, 7, %l6		! mask everything except bits 1,2 3
321	add	%i1, %i4, %i1
322	add	%i1, %i3, %i1
323
324	be,a	%ncc, 1f	! branch taken if src is 64-byte aligned
325	ldda	[%l7]ASI_BLK_P, %d0
326
327	call	.+8		! get the address of this instruction in %o7
328	sll	%l6, 2, %l4
329	add	%o7, %l4, %o7
330	jmp	%o7 + 16	! jump to the starting ldd instruction
331	nop
332	ldd	[%l7+8], %d2
333	ldd	[%l7+16], %d4
334	ldd	[%l7+24], %d6
335	ldd	[%l7+32], %d8
336	ldd	[%l7+40], %d10
337	ldd	[%l7+48], %d12
338	ldd	[%l7+56], %d14
3391:
340	add	%l7, 64, %l7
341	ldda	[%l7]ASI_BLK_P, %d16
342	add	%l7, 64, %l7
343	ldda	[%l7]ASI_BLK_P, %d32
344	add	%l7, 64, %l7
345	sub	%i3, 128, %i3
346
347
348        ! switch statement to get us to the right 8 byte blk within a
349        ! 64 byte block
350
351	cmp	 %l6, 4
352	bgeu,a	 hlf
353	cmp	 %l6, 6
354	cmp	 %l6, 2
355	bgeu,a	 sqtr
356	nop
357	cmp	 %l6, 1
358	be,a	 seg1
359	nop
360	ba	 seg0
361	nop
362sqtr:
363	be,a	 seg2
364	nop
365	ba,a	 seg3
366	nop
367
368hlf:
369	bgeu,a	 fqtr
370	nop
371	cmp	 %l6, 5
372	be,a	 seg5
373	nop
374	ba	 seg4
375	nop
376fqtr:
377	be,a	 seg6
378	nop
379	ba	 seg7
380	nop
381
382#define	FALIGN_D0			\
383	faligndata %d0, %d2, %d48	;\
384	faligndata %d2, %d4, %d50	;\
385	faligndata %d4, %d6, %d52	;\
386	faligndata %d6, %d8, %d54	;\
387	faligndata %d8, %d10, %d56	;\
388	faligndata %d10, %d12, %d58	;\
389	faligndata %d12, %d14, %d60	;\
390	faligndata %d14, %d16, %d62
391
392#define	FALIGN_D16			\
393	faligndata %d16, %d18, %d48	;\
394	faligndata %d18, %d20, %d50	;\
395	faligndata %d20, %d22, %d52	;\
396	faligndata %d22, %d24, %d54	;\
397	faligndata %d24, %d26, %d56	;\
398	faligndata %d26, %d28, %d58	;\
399	faligndata %d28, %d30, %d60	;\
400	faligndata %d30, %d32, %d62
401
402#define	FALIGN_D32			\
403	faligndata %d32, %d34, %d48	;\
404	faligndata %d34, %d36, %d50	;\
405	faligndata %d36, %d38, %d52	;\
406	faligndata %d38, %d40, %d54	;\
407	faligndata %d40, %d42, %d56	;\
408	faligndata %d42, %d44, %d58	;\
409	faligndata %d44, %d46, %d60	;\
410	faligndata %d46, %d0, %d62
411
412seg0:
413	! 1st chunk - %d0 low, %d16 high, %d32 pre, %d48 dst
414	FALIGN_D0
415	ldda	[%l7]ASI_BLK_P, %d0
416	stda	%d48, [%i0]ASI_BLK_P
417	add	%l7, 64, %l7
418	subcc	%i3, 64, %i3
419	bz,pn	%ncc, 0f
420	add	%i0, 64, %i0
421	! 2nd chunk -  %d0 pre, %d16 low, %d32 high, %d48 dst
422	FALIGN_D16
423	ldda	[%l7]ASI_BLK_P, %d16
424	stda	%d48, [%i0]ASI_BLK_P
425	add	%l7, 64, %l7
426	subcc	%i3, 64, %i3
427	bz,pn	%ncc, 1f
428	add	%i0, 64, %i0
429	! 3rd chunk -  %d0 high, %d16 pre, %d32 low, %d48 dst
430	FALIGN_D32
431	ldda	[%l7]ASI_BLK_P, %d32
432	stda	%d48, [%i0]ASI_BLK_P
433	add	%l7, 64, %l7
434	subcc	%i3, 64, %i3
435	bz,pn	%ncc, 2f
436	add	%i0, 64, %i0
437	ba,a,pt	%ncc, seg0
438
4390:
440	FALIGN_D16
441	stda	%d48, [%i0]ASI_BLK_P
442	add	%i0, 64, %i0
443	membar	#Sync
444	FALIGN_D32
445	stda	%d48, [%i0]ASI_BLK_P
446	ba,pt	%ncc, blkd0
447	add	%i0, 64, %i0
448
4491:
450	FALIGN_D32
451	stda	%d48, [%i0]ASI_BLK_P
452	add	%i0, 64, %i0
453	membar	#Sync
454	FALIGN_D0
455	stda	%d48, [%i0]ASI_BLK_P
456	ba,pt	%ncc, blkd16
457	add	%i0, 64, %i0
458
4592:
460	FALIGN_D0
461	stda	%d48, [%i0]ASI_BLK_P
462	add	%i0, 64, %i0
463	membar	#Sync
464	FALIGN_D16
465	stda	%d48, [%i0]ASI_BLK_P
466	ba,pt	%ncc, blkd32
467	add	%i0, 64, %i0
468
469
470#define	FALIGN_D2			\
471	faligndata %d2, %d4, %d48	;\
472	faligndata %d4, %d6, %d50	;\
473	faligndata %d6, %d8, %d52	;\
474	faligndata %d8, %d10, %d54	;\
475	faligndata %d10, %d12, %d56	;\
476	faligndata %d12, %d14, %d58	;\
477	faligndata %d14, %d16, %d60	;\
478	faligndata %d16, %d18, %d62
479
480#define	FALIGN_D18			\
481	faligndata %d18, %d20, %d48	;\
482	faligndata %d20, %d22, %d50	;\
483	faligndata %d22, %d24, %d52	;\
484	faligndata %d24, %d26, %d54	;\
485	faligndata %d26, %d28, %d56	;\
486	faligndata %d28, %d30, %d58	;\
487	faligndata %d30, %d32, %d60	;\
488	faligndata %d32, %d34, %d62
489
490#define	FALIGN_D34			\
491	faligndata %d34, %d36, %d48	;\
492	faligndata %d36, %d38, %d50	;\
493	faligndata %d38, %d40, %d52	;\
494	faligndata %d40, %d42, %d54	;\
495	faligndata %d42, %d44, %d56	;\
496	faligndata %d44, %d46, %d58	;\
497	faligndata %d46, %d0, %d60	;\
498	faligndata %d0, %d2, %d62
499
500seg1:
501	! 1st chunk - %d0 low, %d16 high, %d32 pre, %d48 dst
502	FALIGN_D2
503	ldda	[%l7]ASI_BLK_P, %d0
504	stda	%d48, [%i0]ASI_BLK_P
505	add	%l7, 64, %l7
506	subcc	%i3, 64, %i3
507	bz,pn	%ncc, 0f
508	add	%i0, 64, %i0
509	! 2nd chunk -  %d0 pre, %d16 low, %d32 high, %d48 dst
510	FALIGN_D18
511	ldda	[%l7]ASI_BLK_P, %d16
512	stda	%d48, [%i0]ASI_BLK_P
513	add	%l7, 64, %l7
514	subcc	%i3, 64, %i3
515	bz,pn	%ncc, 1f
516	add	%i0, 64, %i0
517	! 3rd chunk -  %d0 high, %d16 pre, %d32 low, %d48 dst
518	FALIGN_D34
519	ldda	[%l7]ASI_BLK_P, %d32
520	stda	%d48, [%i0]ASI_BLK_P
521	add	%l7, 64, %l7
522	subcc	%i3, 64, %i3
523	bz,pn	%ncc, 2f
524	add	%i0, 64, %i0
525	ba,a,pt	%ncc, seg1
5260:
527	FALIGN_D18
528	stda	%d48, [%i0]ASI_BLK_P
529	add	%i0, 64, %i0
530	membar	#Sync
531	FALIGN_D34
532	stda	%d48, [%i0]ASI_BLK_P
533	ba,pt	%ncc, blkd2
534	add	%i0, 64, %i0
535
5361:
537	FALIGN_D34
538	stda	%d48, [%i0]ASI_BLK_P
539	add	%i0, 64, %i0
540	membar	#Sync
541	FALIGN_D2
542	stda	%d48, [%i0]ASI_BLK_P
543	ba,pt	%ncc, blkd18
544	add	%i0, 64, %i0
545
5462:
547	FALIGN_D2
548	stda	%d48, [%i0]ASI_BLK_P
549	add	%i0, 64, %i0
550	membar	#Sync
551	FALIGN_D18
552	stda	%d48, [%i0]ASI_BLK_P
553	ba,pt	%ncc, blkd34
554	add	%i0, 64, %i0
555
556#define	FALIGN_D4			\
557	faligndata %d4, %d6, %d48	;\
558	faligndata %d6, %d8, %d50	;\
559	faligndata %d8, %d10, %d52	;\
560	faligndata %d10, %d12, %d54	;\
561	faligndata %d12, %d14, %d56	;\
562	faligndata %d14, %d16, %d58	;\
563	faligndata %d16, %d18, %d60	;\
564	faligndata %d18, %d20, %d62
565
566#define	FALIGN_D20			\
567	faligndata %d20, %d22, %d48	;\
568	faligndata %d22, %d24, %d50	;\
569	faligndata %d24, %d26, %d52	;\
570	faligndata %d26, %d28, %d54	;\
571	faligndata %d28, %d30, %d56	;\
572	faligndata %d30, %d32, %d58	;\
573	faligndata %d32, %d34, %d60	;\
574	faligndata %d34, %d36, %d62
575
576#define	FALIGN_D36			\
577	faligndata %d36, %d38, %d48	;\
578	faligndata %d38, %d40, %d50	;\
579	faligndata %d40, %d42, %d52	;\
580	faligndata %d42, %d44, %d54	;\
581	faligndata %d44, %d46, %d56	;\
582	faligndata %d46, %d0, %d58	;\
583	faligndata %d0, %d2, %d60	;\
584	faligndata %d2, %d4, %d62
585
586seg2:
587	! 1st chunk - %d0 low, %d16 high, %d32 pre, %d48 dst
588	FALIGN_D4
589	ldda	[%l7]ASI_BLK_P, %d0
590	stda	%d48, [%i0]ASI_BLK_P
591	add	%l7, 64, %l7
592	subcc	%i3, 64, %i3
593	bz,pn	%ncc, 0f
594	add	%i0, 64, %i0
595	! 2nd chunk -  %d0 pre, %d16 low, %d32 high, %d48 dst
596	FALIGN_D20
597	ldda	[%l7]ASI_BLK_P, %d16
598	stda	%d48, [%i0]ASI_BLK_P
599	add	%l7, 64, %l7
600	subcc	%i3, 64, %i3
601	bz,pn	%ncc, 1f
602	add	%i0, 64, %i0
603	! 3rd chunk -  %d0 high, %d16 pre, %d32 low, %d48 dst
604	FALIGN_D36
605	ldda	[%l7]ASI_BLK_P, %d32
606	stda	%d48, [%i0]ASI_BLK_P
607	add	%l7, 64, %l7
608	subcc	%i3, 64, %i3
609	bz,pn	%ncc, 2f
610	add	%i0, 64, %i0
611	ba,a,pt	%ncc, seg2
612
6130:
614	FALIGN_D20
615	stda	%d48, [%i0]ASI_BLK_P
616	add	%i0, 64, %i0
617	membar	#Sync
618	FALIGN_D36
619	stda	%d48, [%i0]ASI_BLK_P
620	ba,pt	%ncc, blkd4
621	add	%i0, 64, %i0
622
6231:
624	FALIGN_D36
625	stda	%d48, [%i0]ASI_BLK_P
626	add	%i0, 64, %i0
627	membar	#Sync
628	FALIGN_D4
629	stda	%d48, [%i0]ASI_BLK_P
630	ba,pt	%ncc, blkd20
631	add	%i0, 64, %i0
632
6332:
634	FALIGN_D4
635	stda	%d48, [%i0]ASI_BLK_P
636	add	%i0, 64, %i0
637	membar	#Sync
638	FALIGN_D20
639	stda	%d48, [%i0]ASI_BLK_P
640	ba,pt	%ncc, blkd36
641	add	%i0, 64, %i0
642
643
644#define	FALIGN_D6			\
645	faligndata %d6, %d8, %d48	;\
646	faligndata %d8, %d10, %d50	;\
647	faligndata %d10, %d12, %d52	;\
648	faligndata %d12, %d14, %d54	;\
649	faligndata %d14, %d16, %d56	;\
650	faligndata %d16, %d18, %d58	;\
651	faligndata %d18, %d20, %d60	;\
652	faligndata %d20, %d22, %d62
653
654#define	FALIGN_D22			\
655	faligndata %d22, %d24, %d48	;\
656	faligndata %d24, %d26, %d50	;\
657	faligndata %d26, %d28, %d52	;\
658	faligndata %d28, %d30, %d54	;\
659	faligndata %d30, %d32, %d56	;\
660	faligndata %d32, %d34, %d58	;\
661	faligndata %d34, %d36, %d60	;\
662	faligndata %d36, %d38, %d62
663
664#define	FALIGN_D38			\
665	faligndata %d38, %d40, %d48	;\
666	faligndata %d40, %d42, %d50	;\
667	faligndata %d42, %d44, %d52	;\
668	faligndata %d44, %d46, %d54	;\
669	faligndata %d46, %d0, %d56	;\
670	faligndata %d0, %d2, %d58	;\
671	faligndata %d2, %d4, %d60	;\
672	faligndata %d4, %d6, %d62
673
674seg3:
675	! 1st chunk - %d0 low, %d16 high, %d32 pre, %d48 dst
676	FALIGN_D6
677	ldda	[%l7]ASI_BLK_P, %d0
678	stda	%d48, [%i0]ASI_BLK_P
679	add	%l7, 64, %l7
680	subcc	%i3, 64, %i3
681	bz,pn	%ncc, 0f
682	add	%i0, 64, %i0
683	! 2nd chunk -  %d0 pre, %d16 low, %d32 high, %d48 dst
684	FALIGN_D22
685	ldda	[%l7]ASI_BLK_P, %d16
686	stda	%d48, [%i0]ASI_BLK_P
687	add	%l7, 64, %l7
688	subcc	%i3, 64, %i3
689	bz,pn	%ncc, 1f
690	add	%i0, 64, %i0
691	! 3rd chunk -  %d0 high, %d16 pre, %d32 low, %d48 dst
692	FALIGN_D38
693	ldda	[%l7]ASI_BLK_P, %d32
694	stda	%d48, [%i0]ASI_BLK_P
695	add	%l7, 64, %l7
696	subcc	%i3, 64, %i3
697	bz,pn	%ncc, 2f
698	add	%i0, 64, %i0
699	ba,a,pt	%ncc, seg3
700
7010:
702	FALIGN_D22
703	stda	%d48, [%i0]ASI_BLK_P
704	add	%i0, 64, %i0
705	membar	#Sync
706	FALIGN_D38
707	stda	%d48, [%i0]ASI_BLK_P
708	ba,pt	%ncc, blkd6
709	add	%i0, 64, %i0
710
7111:
712	FALIGN_D38
713	stda	%d48, [%i0]ASI_BLK_P
714	add	%i0, 64, %i0
715	membar	#Sync
716	FALIGN_D6
717	stda	%d48, [%i0]ASI_BLK_P
718	ba,pt	%ncc, blkd22
719	add	%i0, 64, %i0
720
7212:
722	FALIGN_D6
723	stda	%d48, [%i0]ASI_BLK_P
724	add	%i0, 64, %i0
725	membar	#Sync
726	FALIGN_D22
727	stda	%d48, [%i0]ASI_BLK_P
728	ba,pt	%ncc, blkd38
729	add	%i0, 64, %i0
730
731
732#define	FALIGN_D8			\
733	faligndata %d8, %d10, %d48	;\
734	faligndata %d10, %d12, %d50	;\
735	faligndata %d12, %d14, %d52	;\
736	faligndata %d14, %d16, %d54	;\
737	faligndata %d16, %d18, %d56	;\
738	faligndata %d18, %d20, %d58	;\
739	faligndata %d20, %d22, %d60	;\
740	faligndata %d22, %d24, %d62
741
742#define	FALIGN_D24			\
743	faligndata %d24, %d26, %d48	;\
744	faligndata %d26, %d28, %d50	;\
745	faligndata %d28, %d30, %d52	;\
746	faligndata %d30, %d32, %d54	;\
747	faligndata %d32, %d34, %d56	;\
748	faligndata %d34, %d36, %d58	;\
749	faligndata %d36, %d38, %d60	;\
750	faligndata %d38, %d40, %d62
751
752#define	FALIGN_D40			\
753	faligndata %d40, %d42, %d48	;\
754	faligndata %d42, %d44, %d50	;\
755	faligndata %d44, %d46, %d52	;\
756	faligndata %d46, %d0, %d54	;\
757	faligndata %d0, %d2, %d56	;\
758	faligndata %d2, %d4, %d58	;\
759	faligndata %d4, %d6, %d60	;\
760	faligndata %d6, %d8, %d62
761
762seg4:
763	! 1st chunk - %d0 low, %d16 high, %d32 pre, %d48 dst
764	FALIGN_D8
765	ldda	[%l7]ASI_BLK_P, %d0
766	stda	%d48, [%i0]ASI_BLK_P
767	add	%l7, 64, %l7
768	subcc	%i3, 64, %i3
769	bz,pn	%ncc, 0f
770	add	%i0, 64, %i0
771	! 2nd chunk -  %d0 pre, %d16 low, %d32 high, %d48 dst
772	FALIGN_D24
773	ldda	[%l7]ASI_BLK_P, %d16
774	stda	%d48, [%i0]ASI_BLK_P
775	add	%l7, 64, %l7
776	subcc	%i3, 64, %i3
777	bz,pn	%ncc, 1f
778	add	%i0, 64, %i0
779	! 3rd chunk -  %d0 high, %d16 pre, %d32 low, %d48 dst
780	FALIGN_D40
781	ldda	[%l7]ASI_BLK_P, %d32
782	stda	%d48, [%i0]ASI_BLK_P
783	add	%l7, 64, %l7
784	subcc	%i3, 64, %i3
785	bz,pn	%ncc, 2f
786	add	%i0, 64, %i0
787	ba,a,pt	%ncc, seg4
788
7890:
790	FALIGN_D24
791	stda	%d48, [%i0]ASI_BLK_P
792	add	%i0, 64, %i0
793	membar	#Sync
794	FALIGN_D40
795	stda	%d48, [%i0]ASI_BLK_P
796	ba,pt	%ncc, blkd8
797	add	%i0, 64, %i0
798
7991:
800	FALIGN_D40
801	stda	%d48, [%i0]ASI_BLK_P
802	add	%i0, 64, %i0
803	membar	#Sync
804	FALIGN_D8
805	stda	%d48, [%i0]ASI_BLK_P
806	ba,pt	%ncc, blkd24
807	add	%i0, 64, %i0
808
8092:
810	FALIGN_D8
811	stda	%d48, [%i0]ASI_BLK_P
812	add	%i0, 64, %i0
813	membar	#Sync
814	FALIGN_D24
815	stda	%d48, [%i0]ASI_BLK_P
816	ba,pt	%ncc, blkd40
817	add	%i0, 64, %i0
818
819
820#define	FALIGN_D10			\
821	faligndata %d10, %d12, %d48	;\
822	faligndata %d12, %d14, %d50	;\
823	faligndata %d14, %d16, %d52	;\
824	faligndata %d16, %d18, %d54	;\
825	faligndata %d18, %d20, %d56	;\
826	faligndata %d20, %d22, %d58	;\
827	faligndata %d22, %d24, %d60	;\
828	faligndata %d24, %d26, %d62
829
830#define	FALIGN_D26			\
831	faligndata %d26, %d28, %d48	;\
832	faligndata %d28, %d30, %d50	;\
833	faligndata %d30, %d32, %d52	;\
834	faligndata %d32, %d34, %d54	;\
835	faligndata %d34, %d36, %d56	;\
836	faligndata %d36, %d38, %d58	;\
837	faligndata %d38, %d40, %d60	;\
838	faligndata %d40, %d42, %d62
839
840#define	FALIGN_D42			\
841	faligndata %d42, %d44, %d48	;\
842	faligndata %d44, %d46, %d50	;\
843	faligndata %d46, %d0, %d52	;\
844	faligndata %d0, %d2, %d54	;\
845	faligndata %d2, %d4, %d56	;\
846	faligndata %d4, %d6, %d58	;\
847	faligndata %d6, %d8, %d60	;\
848	faligndata %d8, %d10, %d62
849
850seg5:
851	! 1st chunk - %d0 low, %d16 high, %d32 pre, %d48 dst
852	FALIGN_D10
853	ldda	[%l7]ASI_BLK_P, %d0
854	stda	%d48, [%i0]ASI_BLK_P
855	add	%l7, 64, %l7
856	subcc	%i3, 64, %i3
857	bz,pn	%ncc, 0f
858	add	%i0, 64, %i0
859	! 2nd chunk -  %d0 pre, %d16 low, %d32 high, %d48 dst
860	FALIGN_D26
861	ldda	[%l7]ASI_BLK_P, %d16
862	stda	%d48, [%i0]ASI_BLK_P
863	add	%l7, 64, %l7
864	subcc	%i3, 64, %i3
865	bz,pn	%ncc, 1f
866	add	%i0, 64, %i0
867	! 3rd chunk -  %d0 high, %d16 pre, %d32 low, %d48 dst
868	FALIGN_D42
869	ldda	[%l7]ASI_BLK_P, %d32
870	stda	%d48, [%i0]ASI_BLK_P
871	add	%l7, 64, %l7
872	subcc	%i3, 64, %i3
873	bz,pn	%ncc, 2f
874	add	%i0, 64, %i0
875	ba,a,pt	%ncc, seg5
876
8770:
878	FALIGN_D26
879	stda	%d48, [%i0]ASI_BLK_P
880	add	%i0, 64, %i0
881	membar	#Sync
882	FALIGN_D42
883	stda	%d48, [%i0]ASI_BLK_P
884	ba,pt	%ncc, blkd10
885	add	%i0, 64, %i0
886
8871:
888	FALIGN_D42
889	stda	%d48, [%i0]ASI_BLK_P
890	add	%i0, 64, %i0
891	membar	#Sync
892	FALIGN_D10
893	stda	%d48, [%i0]ASI_BLK_P
894	ba,pt	%ncc, blkd26
895	add	%i0, 64, %i0
896
8972:
898	FALIGN_D10
899	stda	%d48, [%i0]ASI_BLK_P
900	add	%i0, 64, %i0
901	membar	#Sync
902	FALIGN_D26
903	stda	%d48, [%i0]ASI_BLK_P
904	ba,pt	%ncc, blkd42
905	add	%i0, 64, %i0
906
907
908#define	FALIGN_D12			\
909	faligndata %d12, %d14, %d48	;\
910	faligndata %d14, %d16, %d50	;\
911	faligndata %d16, %d18, %d52	;\
912	faligndata %d18, %d20, %d54	;\
913	faligndata %d20, %d22, %d56	;\
914	faligndata %d22, %d24, %d58	;\
915	faligndata %d24, %d26, %d60	;\
916	faligndata %d26, %d28, %d62
917
918#define	FALIGN_D28			\
919	faligndata %d28, %d30, %d48	;\
920	faligndata %d30, %d32, %d50	;\
921	faligndata %d32, %d34, %d52	;\
922	faligndata %d34, %d36, %d54	;\
923	faligndata %d36, %d38, %d56	;\
924	faligndata %d38, %d40, %d58	;\
925	faligndata %d40, %d42, %d60	;\
926	faligndata %d42, %d44, %d62
927
928#define	FALIGN_D44			\
929	faligndata %d44, %d46, %d48	;\
930	faligndata %d46, %d0, %d50	;\
931	faligndata %d0, %d2, %d52	;\
932	faligndata %d2, %d4, %d54	;\
933	faligndata %d4, %d6, %d56	;\
934	faligndata %d6, %d8, %d58	;\
935	faligndata %d8, %d10, %d60	;\
936	faligndata %d10, %d12, %d62
937
938seg6:
939	! 1st chunk - %d0 low, %d16 high, %d32 pre, %d48 dst
940	FALIGN_D12
941	ldda	[%l7]ASI_BLK_P, %d0
942	stda	%d48, [%i0]ASI_BLK_P
943	add	%l7, 64, %l7
944	subcc	%i3, 64, %i3
945	bz,pn	%ncc, 0f
946	add	%i0, 64, %i0
947	! 2nd chunk -  %d0 pre, %d16 low, %d32 high, %d48 dst
948	FALIGN_D28
949	ldda	[%l7]ASI_BLK_P, %d16
950	stda	%d48, [%i0]ASI_BLK_P
951	add	%l7, 64, %l7
952	subcc	%i3, 64, %i3
953	bz,pn	%ncc, 1f
954	add	%i0, 64, %i0
955	! 3rd chunk -  %d0 high, %d16 pre, %d32 low, %d48 dst
956	FALIGN_D44
957	ldda	[%l7]ASI_BLK_P, %d32
958	stda	%d48, [%i0]ASI_BLK_P
959	add	%l7, 64, %l7
960	subcc	%i3, 64, %i3
961	bz,pn	%ncc, 2f
962	add	%i0, 64, %i0
963	ba,a,pt	%ncc, seg6
964
9650:
966	FALIGN_D28
967	stda	%d48, [%i0]ASI_BLK_P
968	add	%i0, 64, %i0
969	membar	#Sync
970	FALIGN_D44
971	stda	%d48, [%i0]ASI_BLK_P
972	ba,pt	%ncc, blkd12
973	add	%i0, 64, %i0
974
9751:
976	FALIGN_D44
977	stda	%d48, [%i0]ASI_BLK_P
978	add	%i0, 64, %i0
979	membar	#Sync
980	FALIGN_D12
981	stda	%d48, [%i0]ASI_BLK_P
982	ba,pt	%ncc, blkd28
983	add	%i0, 64, %i0
984
9852:
986	FALIGN_D12
987	stda	%d48, [%i0]ASI_BLK_P
988	add	%i0, 64, %i0
989	membar	#Sync
990	FALIGN_D28
991	stda	%d48, [%i0]ASI_BLK_P
992	ba,pt	%ncc, blkd44
993	add	%i0, 64, %i0
994
995
996#define	FALIGN_D14			\
997	faligndata %d14, %d16, %d48	;\
998	faligndata %d16, %d18, %d50	;\
999	faligndata %d18, %d20, %d52	;\
1000	faligndata %d20, %d22, %d54	;\
1001	faligndata %d22, %d24, %d56	;\
1002	faligndata %d24, %d26, %d58	;\
1003	faligndata %d26, %d28, %d60	;\
1004	faligndata %d28, %d30, %d62
1005
1006#define	FALIGN_D30			\
1007	faligndata %d30, %d32, %d48	;\
1008	faligndata %d32, %d34, %d50	;\
1009	faligndata %d34, %d36, %d52	;\
1010	faligndata %d36, %d38, %d54	;\
1011	faligndata %d38, %d40, %d56	;\
1012	faligndata %d40, %d42, %d58	;\
1013	faligndata %d42, %d44, %d60	;\
1014	faligndata %d44, %d46, %d62
1015
1016#define	FALIGN_D46			\
1017	faligndata %d46, %d0, %d48	;\
1018	faligndata %d0, %d2, %d50	;\
1019	faligndata %d2, %d4, %d52	;\
1020	faligndata %d4, %d6, %d54	;\
1021	faligndata %d6, %d8, %d56	;\
1022	faligndata %d8, %d10, %d58	;\
1023	faligndata %d10, %d12, %d60	;\
1024	faligndata %d12, %d14, %d62
1025
1026seg7:
1027	! 1st chunk - %d0 low, %d16 high, %d32 pre, %d48 dst
1028	FALIGN_D14
1029	ldda	[%l7]ASI_BLK_P, %d0
1030	stda	%d48, [%i0]ASI_BLK_P
1031	add	%l7, 64, %l7
1032	subcc	%i3, 64, %i3
1033	bz,pn	%ncc, 0f
1034	add	%i0, 64, %i0
1035	! 2nd chunk -  %d0 pre, %d16 low, %d32 high, %d48 dst
1036	FALIGN_D30
1037	ldda	[%l7]ASI_BLK_P, %d16
1038	stda	%d48, [%i0]ASI_BLK_P
1039	add	%l7, 64, %l7
1040	subcc	%i3, 64, %i3
1041	bz,pn	%ncc, 1f
1042	add	%i0, 64, %i0
1043	! 3rd chunk -  %d0 high, %d16 pre, %d32 low, %d48 dst
1044	FALIGN_D46
1045	ldda	[%l7]ASI_BLK_P, %d32
1046	stda	%d48, [%i0]ASI_BLK_P
1047	add	%l7, 64, %l7
1048	subcc	%i3, 64, %i3
1049	bz,pn	%ncc, 2f
1050	add	%i0, 64, %i0
1051	ba,a,pt	%ncc, seg7
1052
10530:
1054	FALIGN_D30
1055	stda	%d48, [%i0]ASI_BLK_P
1056	add	%i0, 64, %i0
1057	membar	#Sync
1058	FALIGN_D46
1059	stda	%d48, [%i0]ASI_BLK_P
1060	ba,pt	%ncc, blkd14
1061	add	%i0, 64, %i0
1062
10631:
1064	FALIGN_D46
1065	stda	%d48, [%i0]ASI_BLK_P
1066	add	%i0, 64, %i0
1067	membar	#Sync
1068	FALIGN_D14
1069	stda	%d48, [%i0]ASI_BLK_P
1070	ba,pt	%ncc, blkd30
1071	add	%i0, 64, %i0
1072
10732:
1074	FALIGN_D14
1075	stda	%d48, [%i0]ASI_BLK_P
1076	add	%i0, 64, %i0
1077	membar	#Sync
1078	FALIGN_D30
1079	stda	%d48, [%i0]ASI_BLK_P
1080	ba,pt	%ncc, blkd46
1081	add	%i0, 64, %i0
1082
1083
1084	!
1085	! dribble out the last partial block
1086	!
1087blkd0:
1088	subcc	%i4, 8, %i4
1089	blu,pn	%ncc, blkdone
1090	faligndata %d0, %d2, %d48
1091	std	%d48, [%i0]
1092	add	%i0, 8, %i0
1093blkd2:
1094	subcc	%i4, 8, %i4
1095	blu,pn	%ncc, blkdone
1096	faligndata %d2, %d4, %d48
1097	std	%d48, [%i0]
1098	add	%i0, 8, %i0
1099blkd4:
1100	subcc	%i4, 8, %i4
1101	blu,pn	%ncc, blkdone
1102	faligndata %d4, %d6, %d48
1103	std	%d48, [%i0]
1104	add	%i0, 8, %i0
1105blkd6:
1106	subcc	%i4, 8, %i4
1107	blu,pn	%ncc, blkdone
1108	faligndata %d6, %d8, %d48
1109	std	%d48, [%i0]
1110	add	%i0, 8, %i0
1111blkd8:
1112	subcc	%i4, 8, %i4
1113	blu,pn	%ncc, blkdone
1114	faligndata %d8, %d10, %d48
1115	std	%d48, [%i0]
1116	add	%i0, 8, %i0
1117blkd10:
1118	subcc	%i4, 8, %i4
1119	blu,pn	%ncc, blkdone
1120	faligndata %d10, %d12, %d48
1121	std	%d48, [%i0]
1122	add	%i0, 8, %i0
1123blkd12:
1124	subcc	%i4, 8, %i4
1125	blu,pn	%ncc, blkdone
1126	faligndata %d12, %d14, %d48
1127	std	%d48, [%i0]
1128	add	%i0, 8, %i0
1129blkd14:
1130	subcc	%i4, 8, %i4
1131	blu,pn	%ncc, blkdone
1132	fsrc1	%d14, %d0
1133	ba,a,pt	%ncc, blkleft
1134
1135blkd16:
1136	subcc	%i4, 8, %i4
1137	blu,pn	%ncc, blkdone
1138	faligndata %d16, %d18, %d48
1139	std	%d48, [%i0]
1140	add	%i0, 8, %i0
1141blkd18:
1142	subcc	%i4, 8, %i4
1143	blu,pn	%ncc, blkdone
1144	faligndata %d18, %d20, %d48
1145	std	%d48, [%i0]
1146	add	%i0, 8, %i0
1147blkd20:
1148	subcc	%i4, 8, %i4
1149	blu,pn	%ncc, blkdone
1150	faligndata %d20, %d22, %d48
1151	std	%d48, [%i0]
1152	add	%i0, 8, %i0
1153blkd22:
1154	subcc	%i4, 8, %i4
1155	blu,pn	%ncc, blkdone
1156	faligndata %d22, %d24, %d48
1157	std	%d48, [%i0]
1158	add	%i0, 8, %i0
1159blkd24:
1160	subcc	%i4, 8, %i4
1161	blu,pn	%ncc, blkdone
1162	faligndata %d24, %d26, %d48
1163	std	%d48, [%i0]
1164	add	%i0, 8, %i0
1165blkd26:
1166	subcc	%i4, 8, %i4
1167	blu,pn	%ncc, blkdone
1168	faligndata %d26, %d28, %d48
1169	std	%d48, [%i0]
1170	add	%i0, 8, %i0
1171blkd28:
1172	subcc	%i4, 8, %i4
1173	blu,pn	%ncc, blkdone
1174	faligndata %d28, %d30, %d48
1175	std	%d48, [%i0]
1176	add	%i0, 8, %i0
1177blkd30:
1178	subcc	%i4, 8, %i4
1179	blu,pn	%ncc, blkdone
1180	fsrc1	%d30, %d0
1181	ba,a,pt	%ncc, blkleft
1182blkd32:
1183	subcc	%i4, 8, %i4
1184	blu,pn	%ncc, blkdone
1185	faligndata %d32, %d34, %d48
1186	std	%d48, [%i0]
1187	add	%i0, 8, %i0
1188blkd34:
1189	subcc	%i4, 8, %i4
1190	blu,pn	%ncc, blkdone
1191	faligndata %d34, %d36, %d48
1192	std	%d48, [%i0]
1193	add	%i0, 8, %i0
1194blkd36:
1195	subcc	%i4, 8, %i4
1196	blu,pn	%ncc, blkdone
1197	faligndata %d36, %d38, %d48
1198	std	%d48, [%i0]
1199	add	%i0, 8, %i0
1200blkd38:
1201	subcc	%i4, 8, %i4
1202	blu,pn	%ncc, blkdone
1203	faligndata %d38, %d40, %d48
1204	std	%d48, [%i0]
1205	add	%i0, 8, %i0
1206blkd40:
1207	subcc	%i4, 8, %i4
1208	blu,pn	%ncc, blkdone
1209	faligndata %d40, %d42, %d48
1210	std	%d48, [%i0]
1211	add	%i0, 8, %i0
1212blkd42:
1213	subcc	%i4, 8, %i4
1214	blu,pn	%ncc, blkdone
1215	faligndata %d42, %d44, %d48
1216	std	%d48, [%i0]
1217	add	%i0, 8, %i0
1218blkd44:
1219	subcc	%i4, 8, %i4
1220	blu,pn	%ncc, blkdone
1221	faligndata %d44, %d46, %d48
1222	std	%d48, [%i0]
1223	add	%i0, 8, %i0
1224blkd46:
1225	subcc	%i4, 8, %i4
1226	blu,pn	%ncc, blkdone
1227	fsrc1	%d46, %d0
1228
1229blkleft:
1230	ldd	[%l7], %d2
1231	add	%l7, 8, %l7
1232	subcc	%i4, 8, %i4
1233	faligndata %d0, %d2, %d8
1234	std	%d8, [%i0]
1235	blu,pn	%ncc, blkdone
1236	add	%i0, 8, %i0
1237	ldd	[%l7], %d0
1238	add	%l7, 8, %l7
1239	subcc	%i4, 8, %i4
1240	faligndata %d2, %d0, %d8
1241	std	%d8, [%i0]
1242	bgeu,pt	%ncc, blkleft
1243	add	%i0, 8, %i0
1244
1245blkdone:
1246	tst	%i2
1247	bz,pt 	%ncc, blkexit
1248	and	%l3, 0x4, %l3		! fprs.du = fprs.dl = 0
1249
12507:      ldub    [%i1], %i4
1251        inc     %i1
1252        inc     %i0
1253        deccc   %i2
1254        bgu  	%ncc, 7b
1255        stb     %i4, [%i0 - 1]
1256
1257blkexit:
1258        and     %l3, 0x4, %l3           ! fprs.du = fprs.dl = 0
1259	wr      %l3, %g0, %fprs         ! fprs = l3 - restore fprs.fef
1260	membar  #StoreLoad|#StoreStore
1261	ret
1262	restore %i5, %g0, %o0
1263
1264	SET_SIZE(memcpy)
1265	SET_SIZE(__align_cpy_1)
1266