memset.S 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. /*
  2. * This file is subject to the terms and conditions of the GNU General Public
  3. * License. See the file "COPYING" in the main directory of this archive
  4. * for more details.
  5. *
  6. * Copyright (C) 1998, 1999, 2000 by Ralf Baechle
  7. * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
  8. * Copyright (C) 2007 by Maciej W. Rozycki
  9. * Copyright (C) 2011, 2012 MIPS Technologies, Inc.
  10. */
  11. #include <asm/asm.h>
  12. #include <asm/asm-offsets.h>
  13. #include <asm/regdef.h>
  14. #if LONGSIZE == 4
  15. #define LONG_S_L swl
  16. #define LONG_S_R swr
  17. #else
  18. #define LONG_S_L sdl
  19. #define LONG_S_R sdr
  20. #endif
  21. #ifdef CONFIG_CPU_MICROMIPS
  22. #define STORSIZE (LONGSIZE * 2)
  23. #define STORMASK (STORSIZE - 1)
  24. #define FILL64RG t8
  25. #define FILLPTRG t7
  26. #undef LONG_S
  27. #define LONG_S LONG_SP
  28. #else
  29. #define STORSIZE LONGSIZE
  30. #define STORMASK LONGMASK
  31. #define FILL64RG a1
  32. #define FILLPTRG t0
  33. #endif
  34. #define EX(insn,reg,addr,handler) \
  35. 9: insn reg, addr; \
  36. .section __ex_table,"a"; \
  37. PTR 9b, handler; \
  38. .previous
  39. .macro f_fill64 dst, offset, val, fixup
  40. EX(LONG_S, \val, (\offset + 0 * STORSIZE)(\dst), \fixup)
  41. EX(LONG_S, \val, (\offset + 1 * STORSIZE)(\dst), \fixup)
  42. EX(LONG_S, \val, (\offset + 2 * STORSIZE)(\dst), \fixup)
  43. EX(LONG_S, \val, (\offset + 3 * STORSIZE)(\dst), \fixup)
  44. #if ((defined(CONFIG_CPU_MICROMIPS) && (LONGSIZE == 4)) || !defined(CONFIG_CPU_MICROMIPS))
  45. EX(LONG_S, \val, (\offset + 4 * STORSIZE)(\dst), \fixup)
  46. EX(LONG_S, \val, (\offset + 5 * STORSIZE)(\dst), \fixup)
  47. EX(LONG_S, \val, (\offset + 6 * STORSIZE)(\dst), \fixup)
  48. EX(LONG_S, \val, (\offset + 7 * STORSIZE)(\dst), \fixup)
  49. #endif
  50. #if (!defined(CONFIG_CPU_MICROMIPS) && (LONGSIZE == 4))
  51. EX(LONG_S, \val, (\offset + 8 * STORSIZE)(\dst), \fixup)
  52. EX(LONG_S, \val, (\offset + 9 * STORSIZE)(\dst), \fixup)
  53. EX(LONG_S, \val, (\offset + 10 * STORSIZE)(\dst), \fixup)
  54. EX(LONG_S, \val, (\offset + 11 * STORSIZE)(\dst), \fixup)
  55. EX(LONG_S, \val, (\offset + 12 * STORSIZE)(\dst), \fixup)
  56. EX(LONG_S, \val, (\offset + 13 * STORSIZE)(\dst), \fixup)
  57. EX(LONG_S, \val, (\offset + 14 * STORSIZE)(\dst), \fixup)
  58. EX(LONG_S, \val, (\offset + 15 * STORSIZE)(\dst), \fixup)
  59. #endif
  60. .endm
  61. /*
  62. * memset(void *s, int c, size_t n)
  63. *
  64. * a0: start of area to clear
  65. * a1: char to fill with
  66. * a2: size of area to clear
  67. */
  68. .set noreorder
  69. .align 5
  70. LEAF(memset)
  71. beqz a1, 1f
  72. move v0, a0 /* result */
  73. andi a1, 0xff /* spread fillword */
  74. LONG_SLL t1, a1, 8
  75. or a1, t1
  76. LONG_SLL t1, a1, 16
  77. #if LONGSIZE == 8
  78. or a1, t1
  79. LONG_SLL t1, a1, 32
  80. #endif
  81. or a1, t1
  82. 1:
  83. FEXPORT(__bzero)
  84. sltiu t0, a2, STORSIZE /* very small region? */
  85. bnez t0, .Lsmall_memset
  86. andi t0, a0, STORMASK /* aligned? */
  87. #ifdef CONFIG_CPU_MICROMIPS
  88. move t8, a1 /* used by 'swp' instruction */
  89. move t9, a1
  90. #endif
  91. #ifndef CONFIG_CPU_DADDI_WORKAROUNDS
  92. beqz t0, 1f
  93. PTR_SUBU t0, STORSIZE /* alignment in bytes */
  94. #else
  95. .set noat
  96. li AT, STORSIZE
  97. beqz t0, 1f
  98. PTR_SUBU t0, AT /* alignment in bytes */
  99. .set at
  100. #endif
  101. R10KCBARRIER(0(ra))
  102. #ifdef __MIPSEB__
  103. EX(LONG_S_L, a1, (a0), .Lfirst_fixup) /* make word/dword aligned */
  104. #endif
  105. #ifdef __MIPSEL__
  106. EX(LONG_S_R, a1, (a0), .Lfirst_fixup) /* make word/dword aligned */
  107. #endif
  108. PTR_SUBU a0, t0 /* long align ptr */
  109. PTR_ADDU a2, t0 /* correct size */
  110. 1: ori t1, a2, 0x3f /* # of full blocks */
  111. xori t1, 0x3f
  112. beqz t1, .Lmemset_partial /* no block to fill */
  113. andi t0, a2, 0x40-STORSIZE
  114. PTR_ADDU t1, a0 /* end address */
  115. .set reorder
  116. 1: PTR_ADDIU a0, 64
  117. R10KCBARRIER(0(ra))
  118. f_fill64 a0, -64, FILL64RG, .Lfwd_fixup
  119. bne t1, a0, 1b
  120. .set noreorder
  121. .Lmemset_partial:
  122. R10KCBARRIER(0(ra))
  123. PTR_LA t1, 2f /* where to start */
  124. #ifdef CONFIG_CPU_MICROMIPS
  125. LONG_SRL t7, t0, 1
  126. #endif
  127. #if LONGSIZE == 4
  128. PTR_SUBU t1, FILLPTRG
  129. #else
  130. .set noat
  131. LONG_SRL AT, FILLPTRG, 1
  132. PTR_SUBU t1, AT
  133. .set at
  134. #endif
  135. jr t1
  136. PTR_ADDU a0, t0 /* dest ptr */
  137. .set push
  138. .set noreorder
  139. .set nomacro
  140. f_fill64 a0, -64, FILL64RG, .Lpartial_fixup /* ... but first do longs ... */
  141. 2: .set pop
  142. andi a2, STORMASK /* At most one long to go */
  143. beqz a2, 1f
  144. PTR_ADDU a0, a2 /* What's left */
  145. R10KCBARRIER(0(ra))
  146. #ifdef __MIPSEB__
  147. EX(LONG_S_R, a1, -1(a0), .Llast_fixup)
  148. #endif
  149. #ifdef __MIPSEL__
  150. EX(LONG_S_L, a1, -1(a0), .Llast_fixup)
  151. #endif
  152. 1: jr ra
  153. move a2, zero
  154. .Lsmall_memset:
  155. beqz a2, 2f
  156. PTR_ADDU t1, a0, a2
  157. 1: PTR_ADDIU a0, 1 /* fill bytewise */
  158. R10KCBARRIER(0(ra))
  159. bne t1, a0, 1b
  160. sb a1, -1(a0)
  161. 2: jr ra /* done */
  162. move a2, zero
  163. END(memset)
  164. .Lfirst_fixup:
  165. jr ra
  166. nop
  167. .Lfwd_fixup:
  168. PTR_L t0, TI_TASK($28)
  169. andi a2, 0x3f
  170. LONG_L t0, THREAD_BUADDR(t0)
  171. LONG_ADDU a2, t1
  172. jr ra
  173. LONG_SUBU a2, t0
  174. .Lpartial_fixup:
  175. PTR_L t0, TI_TASK($28)
  176. andi a2, STORMASK
  177. LONG_L t0, THREAD_BUADDR(t0)
  178. LONG_ADDU a2, t1
  179. jr ra
  180. LONG_SUBU a2, t0
  181. .Llast_fixup:
  182. jr ra
  183. andi v1, a2, STORMASK