memcpy.S 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. /*
  2. * Copyright (C) 2013 Regents of the University of California
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License
  6. * as published by the Free Software Foundation, version 2.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. */
  13. #include <linux/linkage.h>
  14. #include <asm/asm.h>
  15. /* void *memcpy(void *, const void *, size_t) */
  16. ENTRY(memcpy)
  17. move t6, a0 /* Preserve return value */
  18. /* Defer to byte-oriented copy for small sizes */
  19. sltiu a3, a2, 128
  20. bnez a3, 4f
  21. /* Use word-oriented copy only if low-order bits match */
  22. andi a3, t6, SZREG-1
  23. andi a4, a1, SZREG-1
  24. bne a3, a4, 4f
  25. beqz a3, 2f /* Skip if already aligned */
  26. /*
  27. * Round to nearest double word-aligned address
  28. * greater than or equal to start address
  29. */
  30. andi a3, a1, ~(SZREG-1)
  31. addi a3, a3, SZREG
  32. /* Handle initial misalignment */
  33. sub a4, a3, a1
  34. 1:
  35. lb a5, 0(a1)
  36. addi a1, a1, 1
  37. sb a5, 0(t6)
  38. addi t6, t6, 1
  39. bltu a1, a3, 1b
  40. sub a2, a2, a4 /* Update count */
  41. 2:
  42. andi a4, a2, ~((16*SZREG)-1)
  43. beqz a4, 4f
  44. add a3, a1, a4
  45. 3:
  46. REG_L a4, 0(a1)
  47. REG_L a5, SZREG(a1)
  48. REG_L a6, 2*SZREG(a1)
  49. REG_L a7, 3*SZREG(a1)
  50. REG_L t0, 4*SZREG(a1)
  51. REG_L t1, 5*SZREG(a1)
  52. REG_L t2, 6*SZREG(a1)
  53. REG_L t3, 7*SZREG(a1)
  54. REG_L t4, 8*SZREG(a1)
  55. REG_L t5, 9*SZREG(a1)
  56. REG_S a4, 0(t6)
  57. REG_S a5, SZREG(t6)
  58. REG_S a6, 2*SZREG(t6)
  59. REG_S a7, 3*SZREG(t6)
  60. REG_S t0, 4*SZREG(t6)
  61. REG_S t1, 5*SZREG(t6)
  62. REG_S t2, 6*SZREG(t6)
  63. REG_S t3, 7*SZREG(t6)
  64. REG_S t4, 8*SZREG(t6)
  65. REG_S t5, 9*SZREG(t6)
  66. REG_L a4, 10*SZREG(a1)
  67. REG_L a5, 11*SZREG(a1)
  68. REG_L a6, 12*SZREG(a1)
  69. REG_L a7, 13*SZREG(a1)
  70. REG_L t0, 14*SZREG(a1)
  71. REG_L t1, 15*SZREG(a1)
  72. addi a1, a1, 16*SZREG
  73. REG_S a4, 10*SZREG(t6)
  74. REG_S a5, 11*SZREG(t6)
  75. REG_S a6, 12*SZREG(t6)
  76. REG_S a7, 13*SZREG(t6)
  77. REG_S t0, 14*SZREG(t6)
  78. REG_S t1, 15*SZREG(t6)
  79. addi t6, t6, 16*SZREG
  80. bltu a1, a3, 3b
  81. andi a2, a2, (16*SZREG)-1 /* Update count */
  82. 4:
  83. /* Handle trailing misalignment */
  84. beqz a2, 6f
  85. add a3, a1, a2
  86. /* Use word-oriented copy if co-aligned to word boundary */
  87. or a5, a1, t6
  88. or a5, a5, a3
  89. andi a5, a5, 3
  90. bnez a5, 5f
  91. 7:
  92. lw a4, 0(a1)
  93. addi a1, a1, 4
  94. sw a4, 0(t6)
  95. addi t6, t6, 4
  96. bltu a1, a3, 7b
  97. ret
  98. 5:
  99. lb a4, 0(a1)
  100. addi a1, a1, 1
  101. sb a4, 0(t6)
  102. addi t6, t6, 1
  103. bltu a1, a3, 5b
  104. 6:
  105. ret
  106. END(memcpy)