memset.S 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  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 <variant/core.h>
  14. /*
  15. * void *memset(void *dst, int c, size_t length)
  16. *
  17. * The algorithm is as follows:
  18. * Create a word with c in all byte positions
  19. * If the destination is aligned,
  20. * do 16B chucks with a loop, and then finish up with
  21. * 8B, 4B, 2B, and 1B stores conditional on the length.
  22. * If destination is unaligned, align it by conditionally
  23. * setting 1B and 2B and then go to aligned case.
  24. * This code tries to use fall-through branches for the common
  25. * case of an aligned destination (except for the branches to
  26. * the alignment labels).
  27. */
  28. /* Load or store instructions that may cause exceptions use the EX macro. */
  29. #define EX(insn,reg1,reg2,offset,handler) \
  30. 9: insn reg1, reg2, offset; \
  31. .section __ex_table, "a"; \
  32. .word 9b, handler; \
  33. .previous
  34. .text
  35. .align 4
  36. .global memset
  37. .type memset,@function
  38. memset:
  39. entry sp, 16 # minimal stack frame
  40. # a2/ dst, a3/ c, a4/ length
  41. extui a3, a3, 0, 8 # mask to just 8 bits
  42. slli a7, a3, 8 # duplicate character in all bytes of word
  43. or a3, a3, a7 # ...
  44. slli a7, a3, 16 # ...
  45. or a3, a3, a7 # ...
  46. mov a5, a2 # copy dst so that a2 is return value
  47. movi a6, 3 # for alignment tests
  48. bany a2, a6, .Ldstunaligned # if dst is unaligned
  49. .L0: # return here from .Ldstunaligned when dst is aligned
  50. srli a7, a4, 4 # number of loop iterations with 16B
  51. # per iteration
  52. bnez a4, .Laligned
  53. retw
  54. /*
  55. * Destination is word-aligned.
  56. */
  57. # set 16 bytes per iteration for word-aligned dst
  58. .align 4 # 1 mod 4 alignment for LOOPNEZ
  59. .byte 0 # (0 mod 4 alignment for LBEG)
  60. .Laligned:
  61. #if XCHAL_HAVE_LOOPS
  62. loopnez a7, .Loop1done
  63. #else /* !XCHAL_HAVE_LOOPS */
  64. beqz a7, .Loop1done
  65. slli a6, a7, 4
  66. add a6, a6, a5 # a6 = end of last 16B chunk
  67. #endif /* !XCHAL_HAVE_LOOPS */
  68. .Loop1:
  69. EX(s32i, a3, a5, 0, memset_fixup)
  70. EX(s32i, a3, a5, 4, memset_fixup)
  71. EX(s32i, a3, a5, 8, memset_fixup)
  72. EX(s32i, a3, a5, 12, memset_fixup)
  73. addi a5, a5, 16
  74. #if !XCHAL_HAVE_LOOPS
  75. blt a5, a6, .Loop1
  76. #endif /* !XCHAL_HAVE_LOOPS */
  77. .Loop1done:
  78. bbci.l a4, 3, .L2
  79. # set 8 bytes
  80. EX(s32i, a3, a5, 0, memset_fixup)
  81. EX(s32i, a3, a5, 4, memset_fixup)
  82. addi a5, a5, 8
  83. .L2:
  84. bbci.l a4, 2, .L3
  85. # set 4 bytes
  86. EX(s32i, a3, a5, 0, memset_fixup)
  87. addi a5, a5, 4
  88. .L3:
  89. bbci.l a4, 1, .L4
  90. # set 2 bytes
  91. EX(s16i, a3, a5, 0, memset_fixup)
  92. addi a5, a5, 2
  93. .L4:
  94. bbci.l a4, 0, .L5
  95. # set 1 byte
  96. EX(s8i, a3, a5, 0, memset_fixup)
  97. .L5:
  98. .Lret1:
  99. retw
  100. /*
  101. * Destination is unaligned
  102. */
  103. .Ldstunaligned:
  104. bltui a4, 8, .Lbyteset # do short copies byte by byte
  105. bbci.l a5, 0, .L20 # branch if dst alignment half-aligned
  106. # dst is only byte aligned
  107. # set 1 byte
  108. EX(s8i, a3, a5, 0, memset_fixup)
  109. addi a5, a5, 1
  110. addi a4, a4, -1
  111. # now retest if dst aligned
  112. bbci.l a5, 1, .L0 # if now aligned, return to main algorithm
  113. .L20:
  114. # dst half-aligned
  115. # set 2 bytes
  116. EX(s16i, a3, a5, 0, memset_fixup)
  117. addi a5, a5, 2
  118. addi a4, a4, -2
  119. j .L0 # dst is now aligned, return to main algorithm
  120. /*
  121. * Byte by byte set
  122. */
  123. .align 4
  124. .byte 0 # 1 mod 4 alignment for LOOPNEZ
  125. # (0 mod 4 alignment for LBEG)
  126. .Lbyteset:
  127. #if XCHAL_HAVE_LOOPS
  128. loopnez a4, .Lbytesetdone
  129. #else /* !XCHAL_HAVE_LOOPS */
  130. beqz a4, .Lbytesetdone
  131. add a6, a5, a4 # a6 = ending address
  132. #endif /* !XCHAL_HAVE_LOOPS */
  133. .Lbyteloop:
  134. EX(s8i, a3, a5, 0, memset_fixup)
  135. addi a5, a5, 1
  136. #if !XCHAL_HAVE_LOOPS
  137. blt a5, a6, .Lbyteloop
  138. #endif /* !XCHAL_HAVE_LOOPS */
  139. .Lbytesetdone:
  140. retw
  141. .section .fixup, "ax"
  142. .align 4
  143. /* We return zero if a failure occurred. */
  144. memset_fixup:
  145. movi a2, 0
  146. retw