memset.S 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. /*
  2. * arch/xtensa/lib/memset.S
  3. *
  4. * ANSI C standard library function memset
  5. * (Well, almost. .fixup code might return zero.)
  6. *
  7. * This file is subject to the terms and conditions of the GNU General
  8. * Public License. See the file "COPYING" in the main directory of
  9. * this archive for more details.
  10. *
  11. * Copyright (C) 2002 Tensilica Inc.
  12. */
  13. #include <linux/linkage.h>
  14. #include <asm/asmmacro.h>
  15. #include <asm/core.h>
  16. /*
  17. * void *memset(void *dst, int c, size_t length)
  18. *
  19. * The algorithm is as follows:
  20. * Create a word with c in all byte positions
  21. * If the destination is aligned,
  22. * do 16B chucks with a loop, and then finish up with
  23. * 8B, 4B, 2B, and 1B stores conditional on the length.
  24. * If destination is unaligned, align it by conditionally
  25. * setting 1B and 2B and then go to aligned case.
  26. * This code tries to use fall-through branches for the common
  27. * case of an aligned destination (except for the branches to
  28. * the alignment labels).
  29. */
  30. .text
  31. ENTRY(__memset)
  32. WEAK(memset)
  33. abi_entry_default
  34. # a2/ dst, a3/ c, a4/ length
  35. extui a3, a3, 0, 8 # mask to just 8 bits
  36. slli a7, a3, 8 # duplicate character in all bytes of word
  37. or a3, a3, a7 # ...
  38. slli a7, a3, 16 # ...
  39. or a3, a3, a7 # ...
  40. mov a5, a2 # copy dst so that a2 is return value
  41. movi a6, 3 # for alignment tests
  42. bany a2, a6, .Ldstunaligned # if dst is unaligned
  43. .L0: # return here from .Ldstunaligned when dst is aligned
  44. srli a7, a4, 4 # number of loop iterations with 16B
  45. # per iteration
  46. bnez a4, .Laligned
  47. abi_ret_default
  48. /*
  49. * Destination is word-aligned.
  50. */
  51. # set 16 bytes per iteration for word-aligned dst
  52. .align 4 # 1 mod 4 alignment for LOOPNEZ
  53. .byte 0 # (0 mod 4 alignment for LBEG)
  54. .Laligned:
  55. #if XCHAL_HAVE_LOOPS
  56. loopnez a7, .Loop1done
  57. #else /* !XCHAL_HAVE_LOOPS */
  58. beqz a7, .Loop1done
  59. slli a6, a7, 4
  60. add a6, a6, a5 # a6 = end of last 16B chunk
  61. #endif /* !XCHAL_HAVE_LOOPS */
  62. .Loop1:
  63. EX(10f) s32i a3, a5, 0
  64. EX(10f) s32i a3, a5, 4
  65. EX(10f) s32i a3, a5, 8
  66. EX(10f) s32i a3, a5, 12
  67. addi a5, a5, 16
  68. #if !XCHAL_HAVE_LOOPS
  69. blt a5, a6, .Loop1
  70. #endif /* !XCHAL_HAVE_LOOPS */
  71. .Loop1done:
  72. bbci.l a4, 3, .L2
  73. # set 8 bytes
  74. EX(10f) s32i a3, a5, 0
  75. EX(10f) s32i a3, a5, 4
  76. addi a5, a5, 8
  77. .L2:
  78. bbci.l a4, 2, .L3
  79. # set 4 bytes
  80. EX(10f) s32i a3, a5, 0
  81. addi a5, a5, 4
  82. .L3:
  83. bbci.l a4, 1, .L4
  84. # set 2 bytes
  85. EX(10f) s16i a3, a5, 0
  86. addi a5, a5, 2
  87. .L4:
  88. bbci.l a4, 0, .L5
  89. # set 1 byte
  90. EX(10f) s8i a3, a5, 0
  91. .L5:
  92. .Lret1:
  93. abi_ret_default
  94. /*
  95. * Destination is unaligned
  96. */
  97. .Ldstunaligned:
  98. bltui a4, 8, .Lbyteset # do short copies byte by byte
  99. bbci.l a5, 0, .L20 # branch if dst alignment half-aligned
  100. # dst is only byte aligned
  101. # set 1 byte
  102. EX(10f) s8i a3, a5, 0
  103. addi a5, a5, 1
  104. addi a4, a4, -1
  105. # now retest if dst aligned
  106. bbci.l a5, 1, .L0 # if now aligned, return to main algorithm
  107. .L20:
  108. # dst half-aligned
  109. # set 2 bytes
  110. EX(10f) s16i a3, a5, 0
  111. addi a5, a5, 2
  112. addi a4, a4, -2
  113. j .L0 # dst is now aligned, return to main algorithm
  114. /*
  115. * Byte by byte set
  116. */
  117. .align 4
  118. .byte 0 # 1 mod 4 alignment for LOOPNEZ
  119. # (0 mod 4 alignment for LBEG)
  120. .Lbyteset:
  121. #if XCHAL_HAVE_LOOPS
  122. loopnez a4, .Lbytesetdone
  123. #else /* !XCHAL_HAVE_LOOPS */
  124. beqz a4, .Lbytesetdone
  125. add a6, a5, a4 # a6 = ending address
  126. #endif /* !XCHAL_HAVE_LOOPS */
  127. .Lbyteloop:
  128. EX(10f) s8i a3, a5, 0
  129. addi a5, a5, 1
  130. #if !XCHAL_HAVE_LOOPS
  131. blt a5, a6, .Lbyteloop
  132. #endif /* !XCHAL_HAVE_LOOPS */
  133. .Lbytesetdone:
  134. abi_ret_default
  135. ENDPROC(__memset)
  136. .section .fixup, "ax"
  137. .align 4
  138. /* We return zero if a failure occurred. */
  139. 10:
  140. movi a2, 0
  141. abi_ret_default