memcpy.c 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. /*
  2. * Copyright (C) 2002 Mark Debbage (Mark.Debbage@superh.com)
  3. *
  4. * May be copied or modified under the terms of the GNU General Public
  5. * License. See linux/COPYING for more information.
  6. *
  7. */
  8. #include <linux/config.h>
  9. #include <linux/types.h>
  10. #include <asm/string.h>
  11. // This is a simplistic optimization of memcpy to increase the
  12. // granularity of access beyond one byte using aligned
  13. // loads and stores. This is not an optimal implementation
  14. // for SH-5 (especially with regard to prefetching and the cache),
  15. // and a better version should be provided later ...
  16. void *memcpy(void *dest, const void *src, size_t count)
  17. {
  18. char *d = (char *) dest, *s = (char *) src;
  19. if (count >= 32) {
  20. int i = 8 - (((unsigned long) d) & 0x7);
  21. if (i != 8)
  22. while (i-- && count--) {
  23. *d++ = *s++;
  24. }
  25. if (((((unsigned long) d) & 0x7) == 0) &&
  26. ((((unsigned long) s) & 0x7) == 0)) {
  27. while (count >= 32) {
  28. unsigned long long t1, t2, t3, t4;
  29. t1 = *(unsigned long long *) (s);
  30. t2 = *(unsigned long long *) (s + 8);
  31. t3 = *(unsigned long long *) (s + 16);
  32. t4 = *(unsigned long long *) (s + 24);
  33. *(unsigned long long *) (d) = t1;
  34. *(unsigned long long *) (d + 8) = t2;
  35. *(unsigned long long *) (d + 16) = t3;
  36. *(unsigned long long *) (d + 24) = t4;
  37. d += 32;
  38. s += 32;
  39. count -= 32;
  40. }
  41. while (count >= 8) {
  42. *(unsigned long long *) d =
  43. *(unsigned long long *) s;
  44. d += 8;
  45. s += 8;
  46. count -= 8;
  47. }
  48. }
  49. if (((((unsigned long) d) & 0x3) == 0) &&
  50. ((((unsigned long) s) & 0x3) == 0)) {
  51. while (count >= 4) {
  52. *(unsigned long *) d = *(unsigned long *) s;
  53. d += 4;
  54. s += 4;
  55. count -= 4;
  56. }
  57. }
  58. if (((((unsigned long) d) & 0x1) == 0) &&
  59. ((((unsigned long) s) & 0x1) == 0)) {
  60. while (count >= 2) {
  61. *(unsigned short *) d = *(unsigned short *) s;
  62. d += 2;
  63. s += 2;
  64. count -= 2;
  65. }
  66. }
  67. }
  68. while (count--) {
  69. *d++ = *s++;
  70. }
  71. return d;
  72. }