libvisual  0.5.0
lv_mem.c
1 /* Libvisual - The audio visualisation framework.
2  *
3  * Copyright (C) 2012 Libvisual team
4  * 2004-2006 Dennis Smit
5  *
6  * Authors: Dennis Smit <ds@nerds-incorporated.org>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU Lesser General Public License as
10  * published by the Free Software Foundation; either version 2.1
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21  */
22 
23 #include "config.h"
24 #include "lv_mem.h"
25 #include "lv_common.h"
26 #include "lv_cpu.h"
27 #include "lv_bits.h"
28 #include <string.h>
29 #include <stdlib.h>
30 
31 /* Standard C fallbacks */
32 static void *mem_copy_c (void *dest, const void *src, visual_size_t n);
33 static void *mem_set8_c (void *dest, int c, visual_size_t n);
34 static void *mem_set16_c (void *dest, int c, visual_size_t n);
35 static void *mem_set32_c (void *dest, int c, visual_size_t n);
36 static void *mem_copy_pitch_c (void *dest, const void *src, int pitch1, int pitch2, int width, int rows);
37 
38 
39 /* x86 SIMD optimized versions */
40 #if defined(VISUAL_ARCH_X86) || defined(VISUAL_ARCH_X86_64)
41 static void *mem_copy_3dnow (void *dest, const void *src, visual_size_t n);
42 static void *mem_copy_mmx (void *dest, const void *src, visual_size_t n);
43 static void *mem_copy_mmx2 (void *dest, const void *src, visual_size_t n);
44 
45 static void *mem_copy_pitch_mmx (void *dest, const void *src, int pitch1, int pitch2, int width, int rows);
46 static void *mem_copy_pitch_mmx2 (void *dest, const void *src, int pitch1, int pitch2, int width, int rows);
47 static void *mem_copy_pitch_3dnow (void *dest, const void *src, int pitch1, int pitch2, int width, int rows);
48 
49 static void *mem_set8_mmx (void *dest, int c, visual_size_t n);
50 static void *mem_set8_mmx2 (void *dest, int c, visual_size_t n);
51 
52 static void *mem_set16_mmx (void *dest, int c, visual_size_t n);
53 static void *mem_set16_mmx2 (void *dest, int c, visual_size_t n);
54 
55 static void *mem_set32_mmx (void *dest, int c, visual_size_t n);
56 static void *mem_set32_mmx2 (void *dest, int c, visual_size_t n);
57 #endif /* VISUAL_ARCH_X86 || VISUAL_ARCH_X86_64 */
58 
59 
60 /* Optimal performance functions set by visual_mem_initialize(). */
61 VisMemCopyFunc visual_mem_copy = mem_copy_c;
62 VisMemCopyPitchFunc visual_mem_copy_pitch = mem_copy_pitch_c;
63 
64 VisMemSet8Func visual_mem_set = mem_set8_c;
65 VisMemSet16Func visual_mem_set16 = mem_set16_c;
66 VisMemSet32Func visual_mem_set32 = mem_set32_c;
67 
68 
69 void visual_mem_initialize ()
70 {
71  /* Arranged from slow to fast, so the slower version gets overloaded
72  * every time */
73 
74  visual_mem_copy = mem_copy_c;
75  visual_mem_copy_pitch = mem_copy_pitch_c;
76 
77  visual_mem_set = mem_set8_c;
78  visual_mem_set16 = mem_set16_c;
79  visual_mem_set32 = mem_set32_c;
80 
81 #if defined(VISUAL_ARCH_X86) || defined(VISUAL_ARCH_X86_64)
82 
83  if (visual_cpu_has_mmx ()) {
84  visual_mem_copy = mem_copy_mmx;
85  visual_mem_copy_pitch = mem_copy_pitch_mmx;
86 
87  visual_mem_set = mem_set8_mmx;
88  visual_mem_set16 = mem_set16_mmx;
89  visual_mem_set32 = mem_set32_mmx;
90  }
91 
92  /* The k6-II and k6-III don't have mmx2, but of course can use the prefetch
93  * facility that 3dnow provides. */
94  if (visual_cpu_has_3dnow ()) {
95  visual_mem_copy = mem_copy_3dnow;
96  visual_mem_copy_pitch = mem_copy_pitch_3dnow;
97  }
98 
99  if (visual_cpu_has_mmx2 ()) {
100  visual_mem_copy = mem_copy_mmx2;
101  visual_mem_copy_pitch = mem_copy_pitch_mmx2;
102 
103  visual_mem_set = mem_set8_mmx2;
104  visual_mem_set16 = mem_set16_mmx2;
105  visual_mem_set32 = mem_set32_mmx2;
106  }
107 
108 #endif /* VISUAL_ARCH_X86 || VISUAL_ARCH_X86_64 */
109 }
110 
111 void *visual_mem_malloc (visual_size_t nbytes)
112 {
113  void *buf;
114 
115  visual_return_val_if_fail (nbytes > 0, NULL);
116 
117  buf = malloc (nbytes);
118 
119  if (buf == NULL) {
120  visual_log (VISUAL_LOG_ERROR, "Cannot get %" VISUAL_SIZE_T_FORMAT " bytes of memory", nbytes);
121 
122  return NULL;
123  }
124 
125  return buf;
126 }
127 
128 void *visual_mem_malloc0 (visual_size_t nbytes)
129 {
130  void *buf;
131 
132  visual_return_val_if_fail (nbytes > 0, NULL);
133 
134  buf = visual_mem_malloc (nbytes);
135 
136  visual_mem_set (buf, 0, nbytes);
137 
138  return buf;
139 }
140 
141 void *visual_mem_realloc (void *ptr, visual_size_t nbytes)
142 {
143  return realloc (ptr, nbytes);
144 }
145 
146 void visual_mem_free (void *ptr)
147 {
148  free (ptr);
149 }
150 
151 static void *mem_copy_c (void *dest, const void *src, visual_size_t n)
152 {
153  return memcpy(dest, src, n);
154 }
155 
156 /* Memset functions, 1 byte memset */
157 static void *mem_set8_c (void *dest, int c, visual_size_t n)
158 {
159  return memset(dest, c, n);
160 }
161 
162 /* Memset functions, 2 byte memset */
163 static void *mem_set16_c (void *dest, int c, visual_size_t n)
164 {
165  uint32_t *d = dest;
166  uint16_t *dc = dest;
167  uint32_t setflag32 =
168  (c & 0xffff) |
169  ((c << 16) & 0xffff0000);
170  uint16_t setflag16 = c & 0xffff;
171 
172  while (n >= 2) {
173  *d++ = setflag32;
174  n -= 2;
175  }
176 
177  dc = (uint16_t *) d;
178 
179  while (n--)
180  *dc++ = setflag16;
181 
182  return dest;
183 }
184 
185 /* Memset functions, 4 byte memset */
186 static void *mem_set32_c (void *dest, int c, visual_size_t n)
187 {
188  uint32_t *d = dest;
189  uint32_t setflag32 = c;
190 
191  while (n--)
192  *d++ = setflag32;
193 
194  return dest;
195 }
196 
197 
198 /* Memcopy with pitch functions */
199 static void *mem_copy_pitch_c (void *dest, const void *src, int pitch1, int pitch2, int row_bytes, int rows)
200 {
201  uint8_t *d = dest;
202  const uint8_t *s = src;
203  int i;
204 
205  for (i = 0; i < rows; i++) {
206  memcpy(d, s, row_bytes);
207 
208  d += pitch1;
209  s += pitch2;
210  }
211 
212  return dest;
213 }
214 
215 
216 #if defined(VISUAL_ARCH_X86) || defined(VISUAL_ARCH_X86_64)
217 
218 static void *mem_copy_mmx (void *dest, const void *src, visual_size_t n)
219 {
220  uint32_t *d = dest;
221  const uint32_t *s = src;
222  uint8_t *dc = dest;
223  const uint8_t *sc = src;
224 
225  while (n >= 64) {
226  __asm __volatile
227  ("\n\t movq (%0), %%mm0"
228  "\n\t movq 8(%0), %%mm1"
229  "\n\t movq 16(%0), %%mm2"
230  "\n\t movq 24(%0), %%mm3"
231  "\n\t movq 32(%0), %%mm4"
232  "\n\t movq 40(%0), %%mm5"
233  "\n\t movq 48(%0), %%mm6"
234  "\n\t movq 56(%0), %%mm7"
235  "\n\t movq %%mm0, (%1)"
236  "\n\t movq %%mm1, 8(%1)"
237  "\n\t movq %%mm2, 16(%1)"
238  "\n\t movq %%mm3, 24(%1)"
239  "\n\t movq %%mm4, 32(%1)"
240  "\n\t movq %%mm5, 40(%1)"
241  "\n\t movq %%mm6, 48(%1)"
242  "\n\t movq %%mm7, 56(%1)"
243  :: "r" (s), "r" (d) : "memory");
244 
245  d += 16;
246  s += 16;
247 
248  n -= 64;
249  }
250 
251  __asm __volatile
252  ("\n\t emms");
253 
254  while (n >= 4) {
255  *d++ = *s++;
256  n -= 4;
257  }
258 
259  dc = (uint8_t *) d;
260  sc = (const uint8_t *) s;
261 
262  while (n--)
263  *dc++ = *sc++;
264 
265  return dest;
266 }
267 
268 static void *mem_copy_mmx2 (void *dest, const void *src, visual_size_t n)
269 {
270  uint32_t *d = dest;
271  const uint32_t *s = src;
272  uint8_t *dc = dest;
273  const uint8_t *sc = src;
274 
275  while (n >= 64) {
276  __asm __volatile
277  ("\n\t prefetchnta 256(%0)"
278  "\n\t prefetchnta 320(%0)"
279  "\n\t movq (%0), %%mm0"
280  "\n\t movq 8(%0), %%mm1"
281  "\n\t movq 16(%0), %%mm2"
282  "\n\t movq 24(%0), %%mm3"
283  "\n\t movq 32(%0), %%mm4"
284  "\n\t movq 40(%0), %%mm5"
285  "\n\t movq 48(%0), %%mm6"
286  "\n\t movq 56(%0), %%mm7"
287  "\n\t movntq %%mm0, (%1)"
288  "\n\t movntq %%mm1, 8(%1)"
289  "\n\t movntq %%mm2, 16(%1)"
290  "\n\t movntq %%mm3, 24(%1)"
291  "\n\t movntq %%mm4, 32(%1)"
292  "\n\t movntq %%mm5, 40(%1)"
293  "\n\t movntq %%mm6, 48(%1)"
294  "\n\t movntq %%mm7, 56(%1)"
295  :: "r" (s), "r" (d) : "memory");
296 
297  d += 16;
298  s += 16;
299 
300  n -= 64;
301  }
302 
303  __asm __volatile
304  ("\n\t emms");
305 
306  while (n >= 4) {
307  *d++ = *s++;
308  n -= 4;
309  }
310 
311  dc = (uint8_t *) d;
312  sc = (const uint8_t *) s;
313 
314  while (n--)
315  *dc++ = *sc++;
316 
317  return dest;
318 }
319 
320 static void *mem_copy_3dnow (void *dest, const void *src, visual_size_t n)
321 {
322  uint32_t *d = dest;
323  const uint32_t *s = src;
324  uint8_t *dc = dest;
325  const uint8_t *sc = src;
326 
327  while (n >= 64) {
328  __asm __volatile
329  ("\n\t prefetch 256(%0)"
330  "\n\t prefetch 320(%0)"
331  "\n\t movq (%0), %%mm0"
332  "\n\t movq 8(%0), %%mm1"
333  "\n\t movq 16(%0), %%mm2"
334  "\n\t movq 24(%0), %%mm3"
335  "\n\t movq 32(%0), %%mm4"
336  "\n\t movq 40(%0), %%mm5"
337  "\n\t movq 48(%0), %%mm6"
338  "\n\t movq 56(%0), %%mm7"
339  "\n\t movq %%mm0, (%1)"
340  "\n\t movq %%mm1, 8(%1)"
341  "\n\t movq %%mm2, 16(%1)"
342  "\n\t movq %%mm3, 24(%1)"
343  "\n\t movq %%mm4, 32(%1)"
344  "\n\t movq %%mm5, 40(%1)"
345  "\n\t movq %%mm6, 48(%1)"
346  "\n\t movq %%mm7, 56(%1)"
347  :: "r" (s), "r" (d) : "memory");
348 
349  d += 16;
350  s += 16;
351 
352  n -= 64;
353  }
354 
355  __asm __volatile
356  ("\n\t emms");
357 
358  while (n >= 4) {
359  *d++ = *s++;
360  n -= 4;
361  }
362 
363  dc = (uint8_t *) d;
364  sc = (const uint8_t *) s;
365 
366  while (n--)
367  *dc++ = *sc++;
368 
369  return dest;
370 }
371 
372 
373 static void *mem_copy_pitch_mmx (void *dest, const void *src, int pitch1, int pitch2, int width, int rows)
374 {
375  uint32_t *d = dest;
376  const uint32_t *s = src;
377  int i;
378 
379  for (i = 0; i < rows; i++) {
380  uint32_t *inner_d;
381  const uint32_t *inner_s;
382  uint8_t *inner_dc = (uint8_t*) d;
383  const uint8_t *inner_sc = (const uint8_t*) s;
384  int n = width;
385 
386  while (!VISUAL_ALIGNED(inner_dc, 4) && n > 4) {
387  *inner_dc++ = *inner_sc++;
388  n--;
389  }
390 
391  inner_d = (uint32_t*) inner_dc;
392  inner_s = (const uint32_t*) inner_sc;
393 
394 #if defined(VISUAL_ARCH_X86) || defined(VISUAL_ARCH_X86_64)
395  while (n >= 64) {
396  __asm __volatile
397  ("\n\t movq (%0), %%mm0"
398  "\n\t movq 8(%0), %%mm1"
399  "\n\t movq 16(%0), %%mm2"
400  "\n\t movq 24(%0), %%mm3"
401  "\n\t movq 32(%0), %%mm4"
402  "\n\t movq 40(%0), %%mm5"
403  "\n\t movq 48(%0), %%mm6"
404  "\n\t movq 56(%0), %%mm7"
405  "\n\t movq %%mm0, (%1)"
406  "\n\t movq %%mm1, 8(%1)"
407  "\n\t movq %%mm2, 16(%1)"
408  "\n\t movq %%mm3, 24(%1)"
409  "\n\t movq %%mm4, 32(%1)"
410  "\n\t movq %%mm5, 40(%1)"
411  "\n\t movq %%mm6, 48(%1)"
412  "\n\t movq %%mm7, 56(%1)"
413  :: "r" (inner_s), "r" (inner_d) : "memory");
414 
415  inner_d += 16;
416  inner_s += 16;
417 
418  n -= 64;
419  }
420 
421  __asm __volatile
422  ("\n\t emms");
423 #endif /* VISUAL_ARCH_X86 */
424 
425  while (n >= 4) {
426  *inner_d++ = *inner_s++;
427  n -= 4;
428  }
429 
430  inner_dc = (uint8_t*) inner_d;
431  inner_sc = (const uint8_t*) inner_s;
432 
433  while (n--)
434  *inner_dc++ = *inner_sc++;
435 
436  d = (uint32_t*)((uint8_t*) d + pitch1);
437  s = (const uint32_t*)((const uint8_t*) s + pitch2);
438  }
439 
440  return dest;
441 }
442 
443 static void *mem_copy_pitch_mmx2 (void *dest, const void *src, int pitch1, int pitch2, int width, int rows)
444 {
445  uint32_t *d = dest;
446  const uint32_t *s = src;
447  int i;
448 
449  for (i = 0; i < rows; i++) {
450  uint32_t *inner_d;
451  const uint32_t *inner_s;
452  uint8_t *inner_dc = (uint8_t*) d;
453  const uint8_t *inner_sc = (const uint8_t*) s;
454  int n = width;
455 
456  while (!VISUAL_ALIGNED(inner_dc, 4) && n > 4) {
457  *inner_dc++ = *inner_sc++;
458  n--;
459  }
460 
461  inner_d = (uint32_t*) inner_dc;
462  inner_s = (const uint32_t*) inner_sc;
463 
464 #if defined(VISUAL_ARCH_X86) || defined(VISUAL_ARCH_X86_64)
465  while (n >= 64) {
466  __asm __volatile
467  ("\n\t prefetchnta 256(%0)"
468  "\n\t prefetchnta 320(%0)"
469  "\n\t movq (%0), %%mm0"
470  "\n\t movq 8(%0), %%mm1"
471  "\n\t movq 16(%0), %%mm2"
472  "\n\t movq 24(%0), %%mm3"
473  "\n\t movq 32(%0), %%mm4"
474  "\n\t movq 40(%0), %%mm5"
475  "\n\t movq 48(%0), %%mm6"
476  "\n\t movq 56(%0), %%mm7"
477  "\n\t movntq %%mm0, (%1)"
478  "\n\t movntq %%mm1, 8(%1)"
479  "\n\t movntq %%mm2, 16(%1)"
480  "\n\t movntq %%mm3, 24(%1)"
481  "\n\t movntq %%mm4, 32(%1)"
482  "\n\t movntq %%mm5, 40(%1)"
483  "\n\t movntq %%mm6, 48(%1)"
484  "\n\t movntq %%mm7, 56(%1)"
485  :: "r" (inner_s), "r" (inner_d) : "memory");
486 
487  inner_d += 16;
488  inner_s += 16;
489 
490  n -= 64;
491  }
492 
493  __asm __volatile
494  ("\n\t emms");
495 #endif /* VISUAL_ARCH_X86 */
496 
497  while (n >= 4) {
498  *inner_d++ = *inner_s++;
499  n -= 4;
500  }
501 
502  inner_dc = (uint8_t*) inner_d;
503  inner_sc = (const uint8_t*) inner_s;
504 
505  while (n--)
506  *inner_dc++ = *inner_sc++;
507 
508  d = (uint32_t*)((uint8_t*) d + pitch1);
509  s = (const uint32_t*)((const uint8_t*) s + pitch2);
510  }
511 
512  return dest;
513 }
514 
515 static void *mem_copy_pitch_3dnow (void *dest, const void *src, int pitch1, int pitch2, int width, int rows)
516 {
517  uint32_t *d = dest;
518  const uint32_t *s = src;
519  int i;
520 
521  for (i = 0; i < rows; i++) {
522  uint32_t *inner_d;
523  const uint32_t *inner_s;
524  uint8_t *inner_dc = (uint8_t*) d;
525  const uint8_t *inner_sc = (const uint8_t*) s;
526  int n = width;
527 
528  while (!VISUAL_ALIGNED(inner_dc, 4) && n > 4) {
529  *inner_dc++ = *inner_sc++;
530  n--;
531  }
532 
533  inner_d = (uint32_t*) inner_dc;
534  inner_s = (const uint32_t*) inner_sc;
535 
536 #if defined(VISUAL_ARCH_X86) || defined(VISUAL_ARCH_X86_64)
537  while (n >= 64) {
538  __asm __volatile
539  ("\n\t prefetch 256(%0)"
540  "\n\t prefetch 320(%0)"
541  "\n\t movq (%0), %%mm0"
542  "\n\t movq 8(%0), %%mm1"
543  "\n\t movq 16(%0), %%mm2"
544  "\n\t movq 24(%0), %%mm3"
545  "\n\t movq 32(%0), %%mm4"
546  "\n\t movq 40(%0), %%mm5"
547  "\n\t movq 48(%0), %%mm6"
548  "\n\t movq 56(%0), %%mm7"
549  "\n\t movq %%mm0, (%1)"
550  "\n\t movq %%mm1, 8(%1)"
551  "\n\t movq %%mm2, 16(%1)"
552  "\n\t movq %%mm3, 24(%1)"
553  "\n\t movq %%mm4, 32(%1)"
554  "\n\t movq %%mm5, 40(%1)"
555  "\n\t movq %%mm6, 48(%1)"
556  "\n\t movq %%mm7, 56(%1)"
557  :: "r" (inner_s), "r" (inner_d) : "memory");
558 
559  inner_d += 16;
560  inner_s += 16;
561 
562  n -= 64;
563  }
564 
565  __asm __volatile
566  ("\n\t emms");
567 #endif /* VISUAL_ARCH_X86 */
568 
569  while (n >= 4) {
570  *inner_d++ = *inner_s++;
571  n -= 4;
572  }
573 
574  inner_dc = (uint8_t*) inner_d;
575  inner_sc = (const uint8_t*) inner_s;
576 
577  while (n--)
578  *inner_dc++ = *inner_sc++;
579 
580  d = (uint32_t*)((uint8_t*) d + pitch1);
581  s = (const uint32_t*)((const uint8_t*) s + pitch2);
582  }
583 
584  return dest;
585 }
586 
587 static void *mem_set8_mmx (void *dest, int c, visual_size_t n)
588 {
589  uint32_t *d = dest;
590  uint8_t *dc = dest;
591  uint32_t setflag32 =
592  (c & 0xff) |
593  ((c << 8) & 0xff00) |
594  ((c << 16) & 0xff0000) |
595  ((c << 24) & 0xff000000);
596  uint8_t setflag8 = c & 0xff;
597 
598  __asm __volatile
599  ("\n\t movd (%0), %%mm0"
600  "\n\t movd (%0), %%mm1"
601  "\n\t psllq $32, %%mm1"
602  "\n\t por %%mm1, %%mm0"
603  "\n\t movq %%mm0, %%mm2"
604  "\n\t movq %%mm0, %%mm1"
605  "\n\t movq %%mm2, %%mm3"
606  "\n\t movq %%mm1, %%mm4"
607  "\n\t movq %%mm0, %%mm5"
608  "\n\t movq %%mm2, %%mm6"
609  "\n\t movq %%mm1, %%mm7"
610  :: "r" (&setflag32) : "memory");
611 
612  while (n >= 64) {
613  __asm __volatile
614  ("\n\t movq %%mm0, (%0)"
615  "\n\t movq %%mm1, 8(%0)"
616  "\n\t movq %%mm2, 16(%0)"
617  "\n\t movq %%mm3, 24(%0)"
618  "\n\t movq %%mm4, 32(%0)"
619  "\n\t movq %%mm5, 40(%0)"
620  "\n\t movq %%mm6, 48(%0)"
621  "\n\t movq %%mm7, 56(%0)"
622  :: "r" (d) : "memory");
623 
624  d += 16;
625 
626  n -= 64;
627  }
628 
629  __asm __volatile
630  ("\n\t emms");
631 
632  while (n >= 4) {
633  *d++ = setflag32;
634  n -= 4;
635  }
636 
637  dc = (uint8_t *) d;
638 
639  while (n--)
640  *dc++ = setflag8;
641 
642  return dest;
643 }
644 
645 static void *mem_set8_mmx2 (void *dest, int c, visual_size_t n)
646 {
647  uint32_t *d = dest;
648  uint8_t *dc = dest;
649  uint32_t setflag32 =
650  (c & 0xff) |
651  ((c << 8) & 0xff00) |
652  ((c << 16) & 0xff0000) |
653  ((c << 24) & 0xff000000);
654  uint8_t setflag8 = c & 0xff;
655 
656  __asm __volatile
657  ("\n\t movd (%0), %%mm0"
658  "\n\t movd (%0), %%mm1"
659  "\n\t psllq $32, %%mm1"
660  "\n\t por %%mm1, %%mm0"
661  "\n\t movq %%mm0, %%mm2"
662  "\n\t movq %%mm0, %%mm1"
663  "\n\t movq %%mm2, %%mm3"
664  "\n\t movq %%mm1, %%mm4"
665  "\n\t movq %%mm0, %%mm5"
666  "\n\t movq %%mm2, %%mm6"
667  "\n\t movq %%mm1, %%mm7"
668  :: "r" (&setflag32) : "memory");
669 
670  while (n >= 64) {
671  __asm __volatile
672  ("\n\t movntq %%mm0, (%0)"
673  "\n\t movntq %%mm1, 8(%0)"
674  "\n\t movntq %%mm2, 16(%0)"
675  "\n\t movntq %%mm3, 24(%0)"
676  "\n\t movntq %%mm4, 32(%0)"
677  "\n\t movntq %%mm5, 40(%0)"
678  "\n\t movntq %%mm6, 48(%0)"
679  "\n\t movntq %%mm7, 56(%0)"
680  :: "r" (d) : "memory");
681 
682  d += 16;
683 
684  n -= 64;
685  }
686 
687  __asm __volatile
688  ("\n\t emms");
689 
690  while (n >= 4) {
691  *d++ = setflag32;
692  n -= 4;
693  }
694 
695  dc = (uint8_t *) d;
696 
697  while (n--)
698  *dc++ = setflag8;
699 
700  return dest;
701 }
702 
703 static void *mem_set16_mmx (void *dest, int c, visual_size_t n)
704 {
705  uint32_t *d = dest;
706  uint16_t *dc = dest;
707  uint32_t setflag32 =
708  (c & 0xffff) |
709  ((c << 16) & 0xffff0000);
710  uint16_t setflag16 = c & 0xffff;
711 
712  __asm __volatile
713  ("\n\t movd (%0), %%mm0"
714  "\n\t movd (%0), %%mm1"
715  "\n\t psllq $32, %%mm1"
716  "\n\t por %%mm1, %%mm0"
717  "\n\t movq %%mm0, %%mm2"
718  "\n\t movq %%mm0, %%mm1"
719  "\n\t movq %%mm2, %%mm3"
720  "\n\t movq %%mm1, %%mm4"
721  "\n\t movq %%mm0, %%mm5"
722  "\n\t movq %%mm2, %%mm6"
723  "\n\t movq %%mm1, %%mm7"
724  :: "r" (&setflag32) : "memory");
725 
726  while (n >= 64) {
727  __asm __volatile
728  ("\n\t movq %%mm0, (%0)"
729  "\n\t movq %%mm1, 8(%0)"
730  "\n\t movq %%mm2, 16(%0)"
731  "\n\t movq %%mm3, 24(%0)"
732  "\n\t movq %%mm4, 32(%0)"
733  "\n\t movq %%mm5, 40(%0)"
734  "\n\t movq %%mm6, 48(%0)"
735  "\n\t movq %%mm7, 56(%0)"
736  :: "r" (d) : "memory");
737 
738  d += 16;
739 
740  n -= 32;
741  }
742 
743  __asm __volatile
744  ("\n\t emms");
745 
746  while (n >= 2) {
747  *d++ = setflag32;
748  n -= 2;
749  }
750 
751  dc = (uint16_t *) d;
752 
753  while (n--)
754  *dc++ = setflag16;
755 
756  return dest;
757 }
758 
759 static void *mem_set16_mmx2 (void *dest, int c, visual_size_t n)
760 {
761  uint32_t *d = dest;
762  uint16_t *dc = dest;
763  uint32_t setflag32 =
764  (c & 0xffff) |
765  ((c << 16) & 0xffff0000);
766  uint16_t setflag16 = c & 0xffff;
767 
768  __asm __volatile
769  ("\n\t movd (%0), %%mm0"
770  "\n\t movd (%0), %%mm1"
771  "\n\t psllq $32, %%mm1"
772  "\n\t por %%mm1, %%mm0"
773  "\n\t movq %%mm0, %%mm2"
774  "\n\t movq %%mm0, %%mm1"
775  "\n\t movq %%mm2, %%mm3"
776  "\n\t movq %%mm1, %%mm4"
777  "\n\t movq %%mm0, %%mm5"
778  "\n\t movq %%mm2, %%mm6"
779  "\n\t movq %%mm1, %%mm7"
780  :: "r" (&setflag32) : "memory");
781 
782  while (n >= 32) {
783  __asm __volatile
784  ("\n\t movntq %%mm0, (%0)"
785  "\n\t movntq %%mm1, 8(%0)"
786  "\n\t movntq %%mm2, 16(%0)"
787  "\n\t movntq %%mm3, 24(%0)"
788  "\n\t movntq %%mm4, 32(%0)"
789  "\n\t movntq %%mm5, 40(%0)"
790  "\n\t movntq %%mm6, 48(%0)"
791  "\n\t movntq %%mm7, 56(%0)"
792  :: "r" (d) : "memory");
793 
794  d += 16;
795 
796  n -= 32;
797  }
798 
799  __asm __volatile
800  ("\n\t emms");
801 
802  while (n >= 2) {
803  *d++ = setflag32;
804  n -= 2;
805  }
806 
807  dc = (uint16_t *) d;
808 
809  while (n--)
810  *dc++ = setflag16;
811 
812  return dest;
813 }
814 
815 static void *mem_set32_mmx (void *dest, int c, visual_size_t n)
816 {
817  uint32_t *d = dest;
818  uint32_t setflag32 = c;
819 
820  __asm __volatile
821  ("\n\t movd (%0), %%mm0"
822  "\n\t movd (%0), %%mm1"
823  "\n\t psllq $32, %%mm1"
824  "\n\t por %%mm1, %%mm0"
825  "\n\t movq %%mm0, %%mm2"
826  "\n\t movq %%mm0, %%mm1"
827  "\n\t movq %%mm2, %%mm3"
828  "\n\t movq %%mm1, %%mm4"
829  "\n\t movq %%mm0, %%mm5"
830  "\n\t movq %%mm2, %%mm6"
831  "\n\t movq %%mm1, %%mm7"
832  :: "r" (&setflag32) : "memory");
833 
834  while (n >= 64) {
835  __asm __volatile
836  ("\n\t movq %%mm0, (%0)"
837  "\n\t movq %%mm1, 8(%0)"
838  "\n\t movq %%mm2, 16(%0)"
839  "\n\t movq %%mm3, 24(%0)"
840  "\n\t movq %%mm4, 32(%0)"
841  "\n\t movq %%mm5, 40(%0)"
842  "\n\t movq %%mm6, 48(%0)"
843  "\n\t movq %%mm7, 56(%0)"
844  :: "r" (d) : "memory");
845 
846  d += 16;
847 
848  n -= 16;
849  }
850 
851  __asm __volatile
852  ("\n\t emms");
853 
854  while (n--)
855  *d++ = setflag32;
856 
857  return dest;
858 }
859 
860 static void *mem_set32_mmx2 (void *dest, int c, visual_size_t n)
861 {
862  uint32_t *d = dest;
863  uint32_t setflag32 = c;
864 
865  __asm __volatile
866  ("\n\t movd (%0), %%mm0"
867  "\n\t movd (%0), %%mm1"
868  "\n\t psllq $32, %%mm1"
869  "\n\t por %%mm1, %%mm0"
870  "\n\t movq %%mm0, %%mm2"
871  "\n\t movq %%mm0, %%mm1"
872  "\n\t movq %%mm2, %%mm3"
873  "\n\t movq %%mm1, %%mm4"
874  "\n\t movq %%mm0, %%mm5"
875  "\n\t movq %%mm2, %%mm6"
876  "\n\t movq %%mm1, %%mm7"
877  :: "r" (&setflag32) : "memory");
878 
879  while (n >= 64) {
880  __asm __volatile
881  ("\n\t movntq %%mm0, (%0)"
882  "\n\t movntq %%mm1, 8(%0)"
883  "\n\t movntq %%mm2, 16(%0)"
884  "\n\t movntq %%mm3, 24(%0)"
885  "\n\t movntq %%mm4, 32(%0)"
886  "\n\t movntq %%mm5, 40(%0)"
887  "\n\t movntq %%mm6, 48(%0)"
888  "\n\t movntq %%mm7, 56(%0)"
889  :: "r" (d) : "memory");
890 
891  d += 16;
892 
893  n -= 16;
894  }
895 
896  __asm __volatile
897  ("\n\t emms");
898 
899  while (n--)
900  *d++ = setflag32;
901 
902  return dest;
903 }
904 
905 #endif /* VISUAL_ARCH_X86 || VISUAL_ARCH_X86_64 */