1/*	$OpenBSD: memcpy.S,v 1.6 2015/08/31 02:53:56 guenther Exp $	*/
2/*	$NetBSD: bcopy.S,v 1.3 1996/10/17 03:08:11 cgd Exp $	*/
3
4/*
5 * Copyright (c) 1995 Carnegie-Mellon University.
6 * All rights reserved.
7 *
8 * Author: Trevor Blackwell.  Support for use as memcpy() and memmove()
9 *	   added by Chris Demetriou.
10 *
11 * Permission to use, copy, modify and distribute this software and
12 * its documentation is hereby granted, provided that both the copyright
13 * notice and this permission notice appear in all copies of the
14 * software, derivative works or modified versions, and any portions
15 * thereof, and that both notices appear in supporting documentation.
16 *
17 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
18 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
19 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
20 *
21 * Carnegie Mellon requests users of this software to return to
22 *
23 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
24 *  School of Computer Science
25 *  Carnegie Mellon University
26 *  Pittsburgh PA 15213-3890
27 *
28 * any improvements or extensions that they make and grant Carnegie the
29 * rights to redistribute these changes.
30 */
31
32#include "SYS.h"
33
34#define	SRCREG		a1
35#define	DSTREG		a0
36#define	SIZEREG		a2
37
38/*
39 * Copy bytes.
40 *
41 * char *memcpy(void *to, const void *from, size_t len);
42 *
43 * No matter how invoked, the source and destination registers
44 * for calculation.  There's no point in copying them to "working"
45 * registers, since the code uses their values "in place," and
46 * copying them would be slower.
47 */
48
49LEAF(memcpy,3)
50	/* set up return value, while we still can */
51	mov	DSTREG,v0
52
53	/* Check for zero length */
54	beq	SIZEREG,bcopy_done
55
56	/* a3 = end address */
57	addq	SRCREG,SIZEREG,a3
58
59	/* Get the first word */
60	ldq_u	t2,0(SRCREG)
61
62	/* Do they have the same alignment? */
63	xor	SRCREG,DSTREG,t0
64	and	t0,7,t0
65	and	DSTREG,7,t1
66	bne	t0,bcopy_different_alignment
67
68	/* src & dst have same alignment */
69	beq	t1,bcopy_all_aligned
70
71	ldq_u	t3,0(DSTREG)
72	addq	SIZEREG,t1,SIZEREG
73	mskqh	t2,SRCREG,t2
74	mskql	t3,SRCREG,t3
75	or	t2,t3,t2
76
77	/* Dst is 8-byte aligned */
78
79bcopy_all_aligned:
80	/* If less than 8 bytes,skip loop */
81	subq	SIZEREG,1,t0
82	and	SIZEREG,7,SIZEREG
83	bic	t0,7,t0
84	beq	t0,bcopy_samealign_lp_end
85
86bcopy_samealign_lp:
87	stq_u	t2,0(DSTREG)
88	addq	DSTREG,8,DSTREG
89	ldq_u	t2,8(SRCREG)
90	subq	t0,8,t0
91	addq	SRCREG,8,SRCREG
92	bne	t0,bcopy_samealign_lp
93
94bcopy_samealign_lp_end:
95	/* If we're done, exit */
96	bne	SIZEREG,bcopy_small_left
97	stq_u	t2,0(DSTREG)
98	RET
99
100bcopy_small_left:
101	mskql	t2,SIZEREG,t4
102	ldq_u	t3,0(DSTREG)
103	mskqh	t3,SIZEREG,t3
104	or	t4,t3,t4
105	stq_u	t4,0(DSTREG)
106	RET
107
108bcopy_different_alignment:
109	/*
110	 * this is the fun part
111	 */
112	addq	SRCREG,SIZEREG,a3
113	cmpule	SIZEREG,8,t0
114	bne	t0,bcopy_da_finish
115
116	beq	t1,bcopy_da_noentry
117
118	/* Do the initial partial word */
119	subq	zero,DSTREG,t0
120	and	t0,7,t0
121	ldq_u	t3,7(SRCREG)
122	extql	t2,SRCREG,t2
123	extqh	t3,SRCREG,t3
124	or	t2,t3,t5
125	insql	t5,DSTREG,t5
126	ldq_u	t6,0(DSTREG)
127	mskql	t6,DSTREG,t6
128	or	t5,t6,t5
129	stq_u	t5,0(DSTREG)
130	addq	SRCREG,t0,SRCREG
131	addq	DSTREG,t0,DSTREG
132	subq	SIZEREG,t0,SIZEREG
133	ldq_u	t2,0(SRCREG)
134
135bcopy_da_noentry:
136	subq	SIZEREG,1,t0
137	bic	t0,7,t0
138	and	SIZEREG,7,SIZEREG
139	beq	t0,bcopy_da_finish2
140
141bcopy_da_lp:
142	ldq_u	t3,7(SRCREG)
143	addq	SRCREG,8,SRCREG
144	extql	t2,SRCREG,t4
145	extqh	t3,SRCREG,t5
146	subq	t0,8,t0
147	or	t4,t5,t5
148	stq	t5,0(DSTREG)
149	addq	DSTREG,8,DSTREG
150	beq	t0,bcopy_da_finish1
151	ldq_u	t2,7(SRCREG)
152	addq	SRCREG,8,SRCREG
153	extql	t3,SRCREG,t4
154	extqh	t2,SRCREG,t5
155	subq	t0,8,t0
156	or	t4,t5,t5
157	stq	t5,0(DSTREG)
158	addq	DSTREG,8,DSTREG
159	bne	t0,bcopy_da_lp
160
161bcopy_da_finish2:
162	/* Do the last new word */
163	mov	t2,t3
164
165bcopy_da_finish1:
166	/* Do the last partial word */
167	ldq_u	t2,-1(a3)
168	extql	t3,SRCREG,t3
169	extqh	t2,SRCREG,t2
170	or	t2,t3,t2
171	br	zero,bcopy_samealign_lp_end
172
173bcopy_da_finish:
174	/* Do the last word in the next source word */
175	ldq_u	t3,-1(a3)
176	extql	t2,SRCREG,t2
177	extqh	t3,SRCREG,t3
178	or	t2,t3,t2
179	insqh	t2,DSTREG,t3
180	insql	t2,DSTREG,t2
181	lda	t4,-1(zero)
182	mskql	t4,SIZEREG,t5
183	cmovne	t5,t5,t4
184	insqh	t4,DSTREG,t5
185	insql	t4,DSTREG,t4
186	addq	DSTREG,SIZEREG,a4
187	ldq_u	t6,0(DSTREG)
188	ldq_u	t7,-1(a4)
189	bic	t6,t4,t6
190	bic	t7,t5,t7
191	and	t2,t4,t2
192	and	t3,t5,t3
193	or	t2,t6,t2
194	or	t3,t7,t3
195	stq_u	t3,-1(a4)
196	stq_u	t2,0(DSTREG)
197bcopy_done:
198	RET
199
200	END_STRONG(memcpy)
201