memcpy.S 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. /* SPDX-License-Identifier: GPL-2.0-only */
  2. /*
  3. * Copyright (C) 2013 Regents of the University of California
  4. */
  5. #include <linux/linkage.h>
  6. #include <asm/asm.h>
  7. /* void *memcpy(void *, const void *, size_t) */
  8. SYM_FUNC_START(__memcpy)
  9. move t6, a0 /* Preserve return value */
  10. /* Defer to byte-oriented copy for small sizes */
  11. sltiu a3, a2, 128
  12. bnez a3, 4f
  13. /* Use word-oriented copy only if low-order bits match */
  14. andi a3, t6, SZREG-1
  15. andi a4, a1, SZREG-1
  16. bne a3, a4, 4f
  17. beqz a3, 2f /* Skip if already aligned */
  18. /*
  19. * Round to nearest double word-aligned address
  20. * greater than or equal to start address
  21. */
  22. andi a3, a1, ~(SZREG-1)
  23. addi a3, a3, SZREG
  24. /* Handle initial misalignment */
  25. sub a4, a3, a1
  26. 1:
  27. lb a5, 0(a1)
  28. addi a1, a1, 1
  29. sb a5, 0(t6)
  30. addi t6, t6, 1
  31. bltu a1, a3, 1b
  32. sub a2, a2, a4 /* Update count */
  33. 2:
  34. andi a4, a2, ~((16*SZREG)-1)
  35. beqz a4, 4f
  36. add a3, a1, a4
  37. 3:
  38. REG_L a4, 0(a1)
  39. REG_L a5, SZREG(a1)
  40. REG_L a6, 2*SZREG(a1)
  41. REG_L a7, 3*SZREG(a1)
  42. REG_L t0, 4*SZREG(a1)
  43. REG_L t1, 5*SZREG(a1)
  44. REG_L t2, 6*SZREG(a1)
  45. REG_L t3, 7*SZREG(a1)
  46. REG_L t4, 8*SZREG(a1)
  47. REG_L t5, 9*SZREG(a1)
  48. REG_S a4, 0(t6)
  49. REG_S a5, SZREG(t6)
  50. REG_S a6, 2*SZREG(t6)
  51. REG_S a7, 3*SZREG(t6)
  52. REG_S t0, 4*SZREG(t6)
  53. REG_S t1, 5*SZREG(t6)
  54. REG_S t2, 6*SZREG(t6)
  55. REG_S t3, 7*SZREG(t6)
  56. REG_S t4, 8*SZREG(t6)
  57. REG_S t5, 9*SZREG(t6)
  58. REG_L a4, 10*SZREG(a1)
  59. REG_L a5, 11*SZREG(a1)
  60. REG_L a6, 12*SZREG(a1)
  61. REG_L a7, 13*SZREG(a1)
  62. REG_L t0, 14*SZREG(a1)
  63. REG_L t1, 15*SZREG(a1)
  64. addi a1, a1, 16*SZREG
  65. REG_S a4, 10*SZREG(t6)
  66. REG_S a5, 11*SZREG(t6)
  67. REG_S a6, 12*SZREG(t6)
  68. REG_S a7, 13*SZREG(t6)
  69. REG_S t0, 14*SZREG(t6)
  70. REG_S t1, 15*SZREG(t6)
  71. addi t6, t6, 16*SZREG
  72. bltu a1, a3, 3b
  73. andi a2, a2, (16*SZREG)-1 /* Update count */
  74. 4:
  75. /* Handle trailing misalignment */
  76. beqz a2, 6f
  77. add a3, a1, a2
  78. /* Use word-oriented copy if co-aligned to word boundary */
  79. or a5, a1, t6
  80. or a5, a5, a3
  81. andi a5, a5, 3
  82. bnez a5, 5f
  83. 7:
  84. lw a4, 0(a1)
  85. addi a1, a1, 4
  86. sw a4, 0(t6)
  87. addi t6, t6, 4
  88. bltu a1, a3, 7b
  89. ret
  90. 5:
  91. lb a4, 0(a1)
  92. addi a1, a1, 1
  93. sb a4, 0(t6)
  94. addi t6, t6, 1
  95. bltu a1, a3, 5b
  96. 6:
  97. ret
  98. SYM_FUNC_END(__memcpy)
  99. SYM_FUNC_ALIAS_WEAK(memcpy, __memcpy)
  100. SYM_FUNC_ALIAS(__pi_memcpy, __memcpy)
  101. SYM_FUNC_ALIAS(__pi___memcpy, __memcpy)