memcpy.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * arch/openrisc/lib/memcpy.c
  4. *
  5. * Optimized memory copy routines for openrisc. These are mostly copied
  6. * from ohter sources but slightly entended based on ideas discuassed in
  7. * #openrisc.
  8. *
  9. * The word unroll implementation is an extension to the arm byte
  10. * unrolled implementation, but using word copies (if things are
  11. * properly aligned)
  12. *
  13. * The great arm loop unroll algorithm can be found at:
  14. * arch/arm/boot/compressed/string.c
  15. */
  16. #include <linux/export.h>
  17. #include <linux/string.h>
  18. #ifdef CONFIG_OR1K_1200
  19. /*
  20. * Do memcpy with word copies and loop unrolling. This gives the
  21. * best performance on the OR1200 and MOR1KX archirectures
  22. */
  23. void *memcpy(void *dest, __const void *src, __kernel_size_t n)
  24. {
  25. int i = 0;
  26. unsigned char *d, *s;
  27. uint32_t *dest_w = (uint32_t *)dest, *src_w = (uint32_t *)src;
  28. /* If both source and dest are word aligned copy words */
  29. if (!((unsigned int)dest_w & 3) && !((unsigned int)src_w & 3)) {
  30. /* Copy 32 bytes per loop */
  31. for (i = n >> 5; i > 0; i--) {
  32. *dest_w++ = *src_w++;
  33. *dest_w++ = *src_w++;
  34. *dest_w++ = *src_w++;
  35. *dest_w++ = *src_w++;
  36. *dest_w++ = *src_w++;
  37. *dest_w++ = *src_w++;
  38. *dest_w++ = *src_w++;
  39. *dest_w++ = *src_w++;
  40. }
  41. if (n & 1 << 4) {
  42. *dest_w++ = *src_w++;
  43. *dest_w++ = *src_w++;
  44. *dest_w++ = *src_w++;
  45. *dest_w++ = *src_w++;
  46. }
  47. if (n & 1 << 3) {
  48. *dest_w++ = *src_w++;
  49. *dest_w++ = *src_w++;
  50. }
  51. if (n & 1 << 2)
  52. *dest_w++ = *src_w++;
  53. d = (unsigned char *)dest_w;
  54. s = (unsigned char *)src_w;
  55. } else {
  56. d = (unsigned char *)dest_w;
  57. s = (unsigned char *)src_w;
  58. for (i = n >> 3; i > 0; i--) {
  59. *d++ = *s++;
  60. *d++ = *s++;
  61. *d++ = *s++;
  62. *d++ = *s++;
  63. *d++ = *s++;
  64. *d++ = *s++;
  65. *d++ = *s++;
  66. *d++ = *s++;
  67. }
  68. if (n & 1 << 2) {
  69. *d++ = *s++;
  70. *d++ = *s++;
  71. *d++ = *s++;
  72. *d++ = *s++;
  73. }
  74. }
  75. if (n & 1 << 1) {
  76. *d++ = *s++;
  77. *d++ = *s++;
  78. }
  79. if (n & 1)
  80. *d++ = *s++;
  81. return dest;
  82. }
  83. #else
  84. /*
  85. * Use word copies but no loop unrolling as we cannot assume there
  86. * will be benefits on the archirecture
  87. */
  88. void *memcpy(void *dest, __const void *src, __kernel_size_t n)
  89. {
  90. unsigned char *d, *s;
  91. uint32_t *dest_w = (uint32_t *)dest, *src_w = (uint32_t *)src;
  92. /* If both source and dest are word aligned copy words */
  93. if (!((unsigned int)dest_w & 3) && !((unsigned int)src_w & 3)) {
  94. for (; n >= 4; n -= 4)
  95. *dest_w++ = *src_w++;
  96. }
  97. d = (unsigned char *)dest_w;
  98. s = (unsigned char *)src_w;
  99. /* For remaining or if not aligned, copy bytes */
  100. for (; n >= 1; n -= 1)
  101. *d++ = *s++;
  102. return dest;
  103. }
  104. #endif
  105. EXPORT_SYMBOL(memcpy);