1/* memcpy optimized with AVX512 for KNL hardware.
2 Copyright (C) 2016 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <http://www.gnu.org/licenses/>. */
18
19#include <sysdep.h>
20
21#if defined HAVE_AVX512_ASM_SUPPORT && IS_IN (libc) \
22 && (defined SHARED \
23 || defined USE_AS_MEMMOVE \
24 || !defined USE_MULTIARCH)
25
26#include "asm-syntax.h"
27#ifndef MEMCPY
28# define MEMCPY __memcpy_avx512_no_vzeroupper
29# define MEMCPY_CHK __memcpy_chk_avx512_no_vzeroupper
30#endif
31
32 .section .text,"ax",@progbits
33#if !defined USE_AS_BCOPY
34ENTRY (MEMCPY_CHK)
35 cmpq %rdx, %rcx
36 jb HIDDEN_JUMPTARGET (__chk_fail)
37END (MEMCPY_CHK)
38#endif
39
40ENTRY (MEMCPY)
41 mov %rdi, %rax
42#ifdef USE_AS_MEMPCPY
43 add %rdx, %rax
44#endif
45 lea (%rsi, %rdx), %rcx
46 lea (%rdi, %rdx), %r9
47 cmp $512, %rdx
48 ja L(512bytesormore)
49
50L(check):
51 cmp $16, %rdx
52 jbe L(less_16bytes)
53 cmp $256, %rdx
54 jb L(less_256bytes)
55 vmovups (%rsi), %zmm0
56 vmovups 0x40(%rsi), %zmm1
57 vmovups 0x80(%rsi), %zmm2
58 vmovups 0xC0(%rsi), %zmm3
59 vmovups -0x100(%rcx), %zmm4
60 vmovups -0xC0(%rcx), %zmm5
61 vmovups -0x80(%rcx), %zmm6
62 vmovups -0x40(%rcx), %zmm7
63 vmovups %zmm0, (%rdi)
64 vmovups %zmm1, 0x40(%rdi)
65 vmovups %zmm2, 0x80(%rdi)
66 vmovups %zmm3, 0xC0(%rdi)
67 vmovups %zmm4, -0x100(%r9)
68 vmovups %zmm5, -0xC0(%r9)
69 vmovups %zmm6, -0x80(%r9)
70 vmovups %zmm7, -0x40(%r9)
71 ret
72
73L(less_256bytes):
74 cmp $128, %dl
75 jb L(less_128bytes)
76 vmovups (%rsi), %zmm0
77 vmovups 0x40(%rsi), %zmm1
78 vmovups -0x80(%rcx), %zmm2
79 vmovups -0x40(%rcx), %zmm3
80 vmovups %zmm0, (%rdi)
81 vmovups %zmm1, 0x40(%rdi)
82 vmovups %zmm2, -0x80(%r9)
83 vmovups %zmm3, -0x40(%r9)
84 ret
85
86L(less_128bytes):
87 cmp $64, %dl
88 jb L(less_64bytes)
89 vmovdqu (%rsi), %ymm0
90 vmovdqu 0x20(%rsi), %ymm1
91 vmovdqu -0x40(%rcx), %ymm2
92 vmovdqu -0x20(%rcx), %ymm3
93 vmovdqu %ymm0, (%rdi)
94 vmovdqu %ymm1, 0x20(%rdi)
95 vmovdqu %ymm2, -0x40(%r9)
96 vmovdqu %ymm3, -0x20(%r9)
97 ret
98
99L(less_64bytes):
100 cmp $32, %dl
101 jb L(less_32bytes)
102 vmovdqu (%rsi), %ymm0
103 vmovdqu -0x20(%rcx), %ymm1
104 vmovdqu %ymm0, (%rdi)
105 vmovdqu %ymm1, -0x20(%r9)
106 ret
107
108L(less_32bytes):
109 vmovdqu (%rsi), %xmm0
110 vmovdqu -0x10(%rcx), %xmm1
111 vmovdqu %xmm0, (%rdi)
112 vmovdqu %xmm1, -0x10(%r9)
113 ret
114
115L(less_16bytes):
116 cmp $8, %dl
117 jb L(less_8bytes)
118 movq (%rsi), %rsi
119 movq -0x8(%rcx), %rcx
120 movq %rsi, (%rdi)
121 movq %rcx, -0x8(%r9)
122 ret
123
124L(less_8bytes):
125 cmp $4, %dl
126 jb L(less_4bytes)
127 mov (%rsi), %esi
128 mov -0x4(%rcx), %ecx
129 mov %esi, (%rdi)
130 mov %ecx, -0x4(%r9)
131 ret
132
133L(less_4bytes):
134 cmp $2, %dl
135 jb L(less_2bytes)
136 mov (%rsi), %si
137 mov -0x2(%rcx), %cx
138 mov %si, (%rdi)
139 mov %cx, -0x2(%r9)
140 ret
141
142L(less_2bytes):
143 cmp $1, %dl
144 jb L(less_1bytes)
145 mov (%rsi), %cl
146 mov %cl, (%rdi)
147L(less_1bytes):
148 ret
149
150L(512bytesormore):
151#ifdef SHARED_CACHE_SIZE_HALF
152 mov $SHARED_CACHE_SIZE_HALF, %r8
153#else
154 mov __x86_shared_cache_size_half(%rip), %r8
155#endif
156 cmp %r8, %rdx
157 jae L(preloop_large)
158 cmp $1024, %rdx
159 ja L(1024bytesormore)
160 prefetcht1 (%rsi)
161 prefetcht1 0x40(%rsi)
162 prefetcht1 0x80(%rsi)
163 prefetcht1 0xC0(%rsi)
164 prefetcht1 0x100(%rsi)
165 prefetcht1 0x140(%rsi)
166 prefetcht1 0x180(%rsi)
167 prefetcht1 0x1C0(%rsi)
168 prefetcht1 -0x200(%rcx)
169 prefetcht1 -0x1C0(%rcx)
170 prefetcht1 -0x180(%rcx)
171 prefetcht1 -0x140(%rcx)
172 prefetcht1 -0x100(%rcx)
173 prefetcht1 -0xC0(%rcx)
174 prefetcht1 -0x80(%rcx)
175 prefetcht1 -0x40(%rcx)
176 vmovups (%rsi), %zmm0
177 vmovups 0x40(%rsi), %zmm1
178 vmovups 0x80(%rsi), %zmm2
179 vmovups 0xC0(%rsi), %zmm3
180 vmovups 0x100(%rsi), %zmm4
181 vmovups 0x140(%rsi), %zmm5
182 vmovups 0x180(%rsi), %zmm6
183 vmovups 0x1C0(%rsi), %zmm7
184 vmovups -0x200(%rcx), %zmm8
185 vmovups -0x1C0(%rcx), %zmm9
186 vmovups -0x180(%rcx), %zmm10
187 vmovups -0x140(%rcx), %zmm11
188 vmovups -0x100(%rcx), %zmm12
189 vmovups -0xC0(%rcx), %zmm13
190 vmovups -0x80(%rcx), %zmm14
191 vmovups -0x40(%rcx), %zmm15
192 vmovups %zmm0, (%rdi)
193 vmovups %zmm1, 0x40(%rdi)
194 vmovups %zmm2, 0x80(%rdi)
195 vmovups %zmm3, 0xC0(%rdi)
196 vmovups %zmm4, 0x100(%rdi)
197 vmovups %zmm5, 0x140(%rdi)
198 vmovups %zmm6, 0x180(%rdi)
199 vmovups %zmm7, 0x1C0(%rdi)
200 vmovups %zmm8, -0x200(%r9)
201 vmovups %zmm9, -0x1C0(%r9)
202 vmovups %zmm10, -0x180(%r9)
203 vmovups %zmm11, -0x140(%r9)
204 vmovups %zmm12, -0x100(%r9)
205 vmovups %zmm13, -0xC0(%r9)
206 vmovups %zmm14, -0x80(%r9)
207 vmovups %zmm15, -0x40(%r9)
208 ret
209
210L(1024bytesormore):
211 cmp %rsi, %rdi
212 ja L(1024bytesormore_bkw)
213 sub $512, %r9
214 vmovups -0x200(%rcx), %zmm8
215 vmovups -0x1C0(%rcx), %zmm9
216 vmovups -0x180(%rcx), %zmm10
217 vmovups -0x140(%rcx), %zmm11
218 vmovups -0x100(%rcx), %zmm12
219 vmovups -0xC0(%rcx), %zmm13
220 vmovups -0x80(%rcx), %zmm14
221 vmovups -0x40(%rcx), %zmm15
222 prefetcht1 (%rsi)
223 prefetcht1 0x40(%rsi)
224 prefetcht1 0x80(%rsi)
225 prefetcht1 0xC0(%rsi)
226 prefetcht1 0x100(%rsi)
227 prefetcht1 0x140(%rsi)
228 prefetcht1 0x180(%rsi)
229 prefetcht1 0x1C0(%rsi)
230
231/* Loop with unaligned memory access. */
232L(gobble_512bytes_loop):
233 vmovups (%rsi), %zmm0
234 vmovups 0x40(%rsi), %zmm1
235 vmovups 0x80(%rsi), %zmm2
236 vmovups 0xC0(%rsi), %zmm3
237 vmovups 0x100(%rsi), %zmm4
238 vmovups 0x140(%rsi), %zmm5
239 vmovups 0x180(%rsi), %zmm6
240 vmovups 0x1C0(%rsi), %zmm7
241 add $512, %rsi
242 prefetcht1 (%rsi)
243 prefetcht1 0x40(%rsi)
244 prefetcht1 0x80(%rsi)
245 prefetcht1 0xC0(%rsi)
246 prefetcht1 0x100(%rsi)
247 prefetcht1 0x140(%rsi)
248 prefetcht1 0x180(%rsi)
249 prefetcht1 0x1C0(%rsi)
250 vmovups %zmm0, (%rdi)
251 vmovups %zmm1, 0x40(%rdi)
252 vmovups %zmm2, 0x80(%rdi)
253 vmovups %zmm3, 0xC0(%rdi)
254 vmovups %zmm4, 0x100(%rdi)
255 vmovups %zmm5, 0x140(%rdi)
256 vmovups %zmm6, 0x180(%rdi)
257 vmovups %zmm7, 0x1C0(%rdi)
258 add $512, %rdi
259 cmp %r9, %rdi
260 jb L(gobble_512bytes_loop)
261 vmovups %zmm8, (%r9)
262 vmovups %zmm9, 0x40(%r9)
263 vmovups %zmm10, 0x80(%r9)
264 vmovups %zmm11, 0xC0(%r9)
265 vmovups %zmm12, 0x100(%r9)
266 vmovups %zmm13, 0x140(%r9)
267 vmovups %zmm14, 0x180(%r9)
268 vmovups %zmm15, 0x1C0(%r9)
269 ret
270
271L(1024bytesormore_bkw):
272 add $512, %rdi
273 vmovups 0x1C0(%rsi), %zmm8
274 vmovups 0x180(%rsi), %zmm9
275 vmovups 0x140(%rsi), %zmm10
276 vmovups 0x100(%rsi), %zmm11
277 vmovups 0xC0(%rsi), %zmm12
278 vmovups 0x80(%rsi), %zmm13
279 vmovups 0x40(%rsi), %zmm14
280 vmovups (%rsi), %zmm15
281 prefetcht1 -0x40(%rcx)
282 prefetcht1 -0x80(%rcx)
283 prefetcht1 -0xC0(%rcx)
284 prefetcht1 -0x100(%rcx)
285 prefetcht1 -0x140(%rcx)
286 prefetcht1 -0x180(%rcx)
287 prefetcht1 -0x1C0(%rcx)
288 prefetcht1 -0x200(%rcx)
289
290/* Backward loop with unaligned memory access. */
291L(gobble_512bytes_loop_bkw):
292 vmovups -0x40(%rcx), %zmm0
293 vmovups -0x80(%rcx), %zmm1
294 vmovups -0xC0(%rcx), %zmm2
295 vmovups -0x100(%rcx), %zmm3
296 vmovups -0x140(%rcx), %zmm4
297 vmovups -0x180(%rcx), %zmm5
298 vmovups -0x1C0(%rcx), %zmm6
299 vmovups -0x200(%rcx), %zmm7
300 sub $512, %rcx
301 prefetcht1 -0x40(%rcx)
302 prefetcht1 -0x80(%rcx)
303 prefetcht1 -0xC0(%rcx)
304 prefetcht1 -0x100(%rcx)
305 prefetcht1 -0x140(%rcx)
306 prefetcht1 -0x180(%rcx)
307 prefetcht1 -0x1C0(%rcx)
308 prefetcht1 -0x200(%rcx)
309 vmovups %zmm0, -0x40(%r9)
310 vmovups %zmm1, -0x80(%r9)
311 vmovups %zmm2, -0xC0(%r9)
312 vmovups %zmm3, -0x100(%r9)
313 vmovups %zmm4, -0x140(%r9)
314 vmovups %zmm5, -0x180(%r9)
315 vmovups %zmm6, -0x1C0(%r9)
316 vmovups %zmm7, -0x200(%r9)
317 sub $512, %r9
318 cmp %rdi, %r9
319 ja L(gobble_512bytes_loop_bkw)
320 vmovups %zmm8, -0x40(%rdi)
321 vmovups %zmm9, -0x80(%rdi)
322 vmovups %zmm10, -0xC0(%rdi)
323 vmovups %zmm11, -0x100(%rdi)
324 vmovups %zmm12, -0x140(%rdi)
325 vmovups %zmm13, -0x180(%rdi)
326 vmovups %zmm14, -0x1C0(%rdi)
327 vmovups %zmm15, -0x200(%rdi)
328 ret
329
330L(preloop_large):
331 cmp %rsi, %rdi
332 ja L(preloop_large_bkw)
333 vmovups (%rsi), %zmm4
334 vmovups 0x40(%rsi), %zmm5
335
336/* Align destination for access with non-temporal stores in the loop. */
337 mov %rdi, %r8
338 and $-0x80, %rdi
339 add $0x80, %rdi
340 sub %rdi, %r8
341 sub %r8, %rsi
342 add %r8, %rdx
343L(gobble_256bytes_nt_loop):
344 prefetcht1 0x200(%rsi)
345 prefetcht1 0x240(%rsi)
346 prefetcht1 0x280(%rsi)
347 prefetcht1 0x2C0(%rsi)
348 prefetcht1 0x300(%rsi)
349 prefetcht1 0x340(%rsi)
350 prefetcht1 0x380(%rsi)
351 prefetcht1 0x3C0(%rsi)
352 vmovdqu64 (%rsi), %zmm0
353 vmovdqu64 0x40(%rsi), %zmm1
354 vmovdqu64 0x80(%rsi), %zmm2
355 vmovdqu64 0xC0(%rsi), %zmm3
356 vmovntdq %zmm0, (%rdi)
357 vmovntdq %zmm1, 0x40(%rdi)
358 vmovntdq %zmm2, 0x80(%rdi)
359 vmovntdq %zmm3, 0xC0(%rdi)
360 sub $256, %rdx
361 add $256, %rsi
362 add $256, %rdi
363 cmp $256, %rdx
364 ja L(gobble_256bytes_nt_loop)
365 sfence
366 vmovups %zmm4, (%rax)
367 vmovups %zmm5, 0x40(%rax)
368 jmp L(check)
369
370L(preloop_large_bkw):
371 vmovups -0x80(%rcx), %zmm4
372 vmovups -0x40(%rcx), %zmm5
373
374/* Align end of destination for access with non-temporal stores. */
375 mov %r9, %r8
376 and $-0x80, %r9
377 sub %r9, %r8
378 sub %r8, %rcx
379 sub %r8, %rdx
380 add %r9, %r8
381L(gobble_256bytes_nt_loop_bkw):
382 prefetcht1 -0x400(%rcx)
383 prefetcht1 -0x3C0(%rcx)
384 prefetcht1 -0x380(%rcx)
385 prefetcht1 -0x340(%rcx)
386 prefetcht1 -0x300(%rcx)
387 prefetcht1 -0x2C0(%rcx)
388 prefetcht1 -0x280(%rcx)
389 prefetcht1 -0x240(%rcx)
390 vmovdqu64 -0x100(%rcx), %zmm0
391 vmovdqu64 -0xC0(%rcx), %zmm1
392 vmovdqu64 -0x80(%rcx), %zmm2
393 vmovdqu64 -0x40(%rcx), %zmm3
394 vmovntdq %zmm0, -0x100(%r9)
395 vmovntdq %zmm1, -0xC0(%r9)
396 vmovntdq %zmm2, -0x80(%r9)
397 vmovntdq %zmm3, -0x40(%r9)
398 sub $256, %rdx
399 sub $256, %rcx
400 sub $256, %r9
401 cmp $256, %rdx
402 ja L(gobble_256bytes_nt_loop_bkw)
403 sfence
404 vmovups %zmm4, -0x80(%r8)
405 vmovups %zmm5, -0x40(%r8)
406 jmp L(check)
407END (MEMCPY)
408#endif
409