1// Copyright 2016 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5// +build mips mipsle
6
7#include "textflag.h"
8
9#ifdef GOARCH_mips
10#define MOVWHI  MOVWL
11#define MOVWLO  MOVWR
12#else
13#define MOVWHI  MOVWR
14#define MOVWLO  MOVWL
15#endif
16
17// See memmove Go doc for important implementation constraints.
18
19// func memmove(to, from unsafe.Pointer, n uintptr)
20TEXT runtime·memmove(SB),NOSPLIT,$-0-12
21	MOVW	n+8(FP), R3
22	MOVW	from+4(FP), R2
23	MOVW	to+0(FP), R1
24
25	ADDU	R3, R2, R4	// end pointer for source
26	ADDU	R3, R1, R5	// end pointer for destination
27
28	// if destination is ahead of source, start at the end of the buffer and go backward.
29	SGTU	R1, R2, R6
30	BNE	R6, backward
31
32	// if less than 4 bytes, use byte by byte copying
33	SGTU	$4, R3, R6
34	BNE	R6, f_small_copy
35
36	// align destination to 4 bytes
37	AND	$3, R1, R6
38	BEQ	R6, f_dest_aligned
39	SUBU	R1, R0, R6
40	AND	$3, R6
41	MOVWHI	0(R2), R7
42	SUBU	R6, R3
43	MOVWLO	3(R2), R7
44	ADDU	R6, R2
45	MOVWHI	R7, 0(R1)
46	ADDU	R6, R1
47
48f_dest_aligned:
49	AND	$31, R3, R7
50	AND	$3, R3, R6
51	SUBU	R7, R5, R7	// end pointer for 32-byte chunks
52	SUBU	R6, R5, R6	// end pointer for 4-byte chunks
53
54	// if source is not aligned, use unaligned reads
55	AND	$3, R2, R8
56	BNE	R8, f_large_ua
57
58f_large:
59	BEQ	R1, R7, f_words
60	ADDU	$32, R1
61	MOVW	0(R2), R8
62	MOVW	4(R2), R9
63	MOVW	8(R2), R10
64	MOVW	12(R2), R11
65	MOVW	16(R2), R12
66	MOVW	20(R2), R13
67	MOVW	24(R2), R14
68	MOVW	28(R2), R15
69	ADDU	$32, R2
70	MOVW	R8, -32(R1)
71	MOVW	R9, -28(R1)
72	MOVW	R10, -24(R1)
73	MOVW	R11, -20(R1)
74	MOVW	R12, -16(R1)
75	MOVW	R13, -12(R1)
76	MOVW	R14, -8(R1)
77	MOVW	R15, -4(R1)
78	JMP	f_large
79
80f_words:
81	BEQ	R1, R6, f_tail
82	ADDU	$4, R1
83	MOVW	0(R2), R8
84	ADDU	$4, R2
85	MOVW	R8, -4(R1)
86	JMP	f_words
87
88f_tail:
89	BEQ	R1, R5, ret
90	MOVWLO	-1(R4), R8
91	MOVWLO	R8, -1(R5)
92
93ret:
94	RET
95
96f_large_ua:
97	BEQ	R1, R7, f_words_ua
98	ADDU	$32, R1
99	MOVWHI	0(R2), R8
100	MOVWHI	4(R2), R9
101	MOVWHI	8(R2), R10
102	MOVWHI	12(R2), R11
103	MOVWHI	16(R2), R12
104	MOVWHI	20(R2), R13
105	MOVWHI	24(R2), R14
106	MOVWHI	28(R2), R15
107	MOVWLO	3(R2), R8
108	MOVWLO	7(R2), R9
109	MOVWLO	11(R2), R10
110	MOVWLO	15(R2), R11
111	MOVWLO	19(R2), R12
112	MOVWLO	23(R2), R13
113	MOVWLO	27(R2), R14
114	MOVWLO	31(R2), R15
115	ADDU	$32, R2
116	MOVW	R8, -32(R1)
117	MOVW	R9, -28(R1)
118	MOVW	R10, -24(R1)
119	MOVW	R11, -20(R1)
120	MOVW	R12, -16(R1)
121	MOVW	R13, -12(R1)
122	MOVW	R14, -8(R1)
123	MOVW	R15, -4(R1)
124	JMP	f_large_ua
125
126f_words_ua:
127	BEQ	R1, R6, f_tail_ua
128	MOVWHI	0(R2), R8
129	ADDU	$4, R1
130	MOVWLO	3(R2), R8
131	ADDU	$4, R2
132	MOVW	R8, -4(R1)
133	JMP	f_words_ua
134
135f_tail_ua:
136	BEQ	R1, R5, ret
137	MOVWHI	-4(R4), R8
138	MOVWLO	-1(R4), R8
139	MOVWLO	R8, -1(R5)
140	JMP	ret
141
142f_small_copy:
143	BEQ	R1, R5, ret
144	ADDU	$1, R1
145	MOVB	0(R2), R6
146	ADDU	$1, R2
147	MOVB	R6, -1(R1)
148	JMP	f_small_copy
149
150backward:
151	SGTU	$4, R3, R6
152	BNE	R6, b_small_copy
153
154	AND	$3, R5, R6
155	BEQ	R6, b_dest_aligned
156	MOVWHI	-4(R4), R7
157	SUBU	R6, R3
158	MOVWLO	-1(R4), R7
159	SUBU	R6, R4
160	MOVWLO	R7, -1(R5)
161	SUBU	R6, R5
162
163b_dest_aligned:
164	AND	$31, R3, R7
165	AND	$3, R3, R6
166	ADDU	R7, R1, R7
167	ADDU	R6, R1, R6
168
169	AND	$3, R4, R8
170	BNE	R8, b_large_ua
171
172b_large:
173	BEQ	R5, R7, b_words
174	ADDU	$-32, R5
175	MOVW	-4(R4), R8
176	MOVW	-8(R4), R9
177	MOVW	-12(R4), R10
178	MOVW	-16(R4), R11
179	MOVW	-20(R4), R12
180	MOVW	-24(R4), R13
181	MOVW	-28(R4), R14
182	MOVW	-32(R4), R15
183	ADDU	$-32, R4
184	MOVW	R8, 28(R5)
185	MOVW	R9, 24(R5)
186	MOVW	R10, 20(R5)
187	MOVW	R11, 16(R5)
188	MOVW	R12, 12(R5)
189	MOVW	R13, 8(R5)
190	MOVW	R14, 4(R5)
191	MOVW	R15, 0(R5)
192	JMP	b_large
193
194b_words:
195	BEQ	R5, R6, b_tail
196	ADDU	$-4, R5
197	MOVW	-4(R4), R8
198	ADDU	$-4, R4
199	MOVW	R8, 0(R5)
200	JMP	b_words
201
202b_tail:
203	BEQ	R5, R1, ret
204	MOVWHI	0(R2), R8	// R2 and R1 have the same alignment so we don't need to load a whole word
205	MOVWHI	R8, 0(R1)
206	JMP	ret
207
208b_large_ua:
209	BEQ	R5, R7, b_words_ua
210	ADDU	$-32, R5
211	MOVWHI	-4(R4), R8
212	MOVWHI	-8(R4), R9
213	MOVWHI	-12(R4), R10
214	MOVWHI	-16(R4), R11
215	MOVWHI	-20(R4), R12
216	MOVWHI	-24(R4), R13
217	MOVWHI	-28(R4), R14
218	MOVWHI	-32(R4), R15
219	MOVWLO	-1(R4), R8
220	MOVWLO	-5(R4), R9
221	MOVWLO	-9(R4), R10
222	MOVWLO	-13(R4), R11
223	MOVWLO	-17(R4), R12
224	MOVWLO	-21(R4), R13
225	MOVWLO	-25(R4), R14
226	MOVWLO	-29(R4), R15
227	ADDU	$-32, R4
228	MOVW	R8, 28(R5)
229	MOVW	R9, 24(R5)
230	MOVW	R10, 20(R5)
231	MOVW	R11, 16(R5)
232	MOVW	R12, 12(R5)
233	MOVW	R13, 8(R5)
234	MOVW	R14, 4(R5)
235	MOVW	R15, 0(R5)
236	JMP	b_large_ua
237
238b_words_ua:
239	BEQ	R5, R6, b_tail_ua
240	MOVWHI	-4(R4), R8
241	ADDU	$-4, R5
242	MOVWLO	-1(R4), R8
243	ADDU	$-4, R4
244	MOVW	R8, 0(R5)
245	JMP	b_words_ua
246
247b_tail_ua:
248	BEQ	R5, R1, ret
249	MOVWHI	(R2), R8
250	MOVWLO	3(R2), R8
251	MOVWHI	R8, 0(R1)
252	JMP ret
253
254b_small_copy:
255	BEQ	R5, R1, ret
256	ADDU	$-1, R5
257	MOVB	-1(R4), R6
258	ADDU	$-1, R4
259	MOVB	R6, 0(R5)
260	JMP	b_small_copy
261