memset.S 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  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/export.h>
  14. #include <asm/regdef.h>
  15. #if LONGSIZE == 4
  16. #define LONG_S_L swl
  17. #define LONG_S_R swr
  18. #else
  19. #define LONG_S_L sdl
  20. #define LONG_S_R sdr
  21. #endif
  22. #ifdef CONFIG_CPU_MICROMIPS
  23. #define STORSIZE (LONGSIZE * 2)
  24. #define STORMASK (STORSIZE - 1)
  25. #define FILL64RG t8
  26. #define FILLPTRG t7
  27. #undef LONG_S
  28. #define LONG_S LONG_SP
  29. #else
  30. #define STORSIZE LONGSIZE
  31. #define STORMASK LONGMASK
  32. #define FILL64RG a1
  33. #define FILLPTRG t0
  34. #endif
  35. #define LEGACY_MODE 1
  36. #define EVA_MODE 2
  37. /*
  38. * No need to protect it with EVA #ifdefery. The generated block of code
  39. * will never be assembled if EVA is not enabled.
  40. */
  41. #define __EVAFY(insn, reg, addr) __BUILD_EVA_INSN(insn##e, reg, addr)
  42. #define ___BUILD_EVA_INSN(insn, reg, addr) __EVAFY(insn, reg, addr)
  43. #define EX(insn,reg,addr,handler) \
  44. .if \mode == LEGACY_MODE; \
  45. 9: insn reg, addr; \
  46. .else; \
  47. 9: ___BUILD_EVA_INSN(insn, reg, addr); \
  48. .endif; \
  49. .section __ex_table,"a"; \
  50. PTR 9b, handler; \
  51. .previous
  52. .macro f_fill64 dst, offset, val, fixup, mode
  53. EX(LONG_S, \val, (\offset + 0 * STORSIZE)(\dst), \fixup)
  54. EX(LONG_S, \val, (\offset + 1 * STORSIZE)(\dst), \fixup)
  55. EX(LONG_S, \val, (\offset + 2 * STORSIZE)(\dst), \fixup)
  56. EX(LONG_S, \val, (\offset + 3 * STORSIZE)(\dst), \fixup)
  57. #if ((defined(CONFIG_CPU_MICROMIPS) && (LONGSIZE == 4)) || !defined(CONFIG_CPU_MICROMIPS))
  58. EX(LONG_S, \val, (\offset + 4 * STORSIZE)(\dst), \fixup)
  59. EX(LONG_S, \val, (\offset + 5 * STORSIZE)(\dst), \fixup)
  60. EX(LONG_S, \val, (\offset + 6 * STORSIZE)(\dst), \fixup)
  61. EX(LONG_S, \val, (\offset + 7 * STORSIZE)(\dst), \fixup)
  62. #endif
  63. #if (!defined(CONFIG_CPU_MICROMIPS) && (LONGSIZE == 4))
  64. EX(LONG_S, \val, (\offset + 8 * STORSIZE)(\dst), \fixup)
  65. EX(LONG_S, \val, (\offset + 9 * STORSIZE)(\dst), \fixup)
  66. EX(LONG_S, \val, (\offset + 10 * STORSIZE)(\dst), \fixup)
  67. EX(LONG_S, \val, (\offset + 11 * STORSIZE)(\dst), \fixup)
  68. EX(LONG_S, \val, (\offset + 12 * STORSIZE)(\dst), \fixup)
  69. EX(LONG_S, \val, (\offset + 13 * STORSIZE)(\dst), \fixup)
  70. EX(LONG_S, \val, (\offset + 14 * STORSIZE)(\dst), \fixup)
  71. EX(LONG_S, \val, (\offset + 15 * STORSIZE)(\dst), \fixup)
  72. #endif
  73. .endm
  74. .set noreorder
  75. .align 5
  76. /*
  77. * Macro to generate the __bzero{,_user} symbol
  78. * Arguments:
  79. * mode: LEGACY_MODE or EVA_MODE
  80. */
  81. .macro __BUILD_BZERO mode
  82. /* Initialize __memset if this is the first time we call this macro */
  83. .ifnotdef __memset
  84. .set __memset, 1
  85. .hidden __memset /* Make sure it does not leak */
  86. .endif
  87. sltiu t0, a2, STORSIZE /* very small region? */
  88. bnez t0, .Lsmall_memset\@
  89. andi t0, a0, STORMASK /* aligned? */
  90. #ifdef CONFIG_CPU_MICROMIPS
  91. move t8, a1 /* used by 'swp' instruction */
  92. move t9, a1
  93. #endif
  94. #ifndef CONFIG_CPU_DADDI_WORKAROUNDS
  95. beqz t0, 1f
  96. PTR_SUBU t0, STORSIZE /* alignment in bytes */
  97. #else
  98. .set noat
  99. li AT, STORSIZE
  100. beqz t0, 1f
  101. PTR_SUBU t0, AT /* alignment in bytes */
  102. .set at
  103. #endif
  104. #ifndef CONFIG_CPU_MIPSR6
  105. R10KCBARRIER(0(ra))
  106. #ifdef __MIPSEB__
  107. EX(LONG_S_L, a1, (a0), .Lfirst_fixup\@) /* make word/dword aligned */
  108. #else
  109. EX(LONG_S_R, a1, (a0), .Lfirst_fixup\@) /* make word/dword aligned */
  110. #endif
  111. PTR_SUBU a0, t0 /* long align ptr */
  112. PTR_ADDU a2, t0 /* correct size */
  113. #else /* CONFIG_CPU_MIPSR6 */
  114. #define STORE_BYTE(N) \
  115. EX(sb, a1, N(a0), .Lbyte_fixup\@); \
  116. beqz t0, 0f; \
  117. PTR_ADDU t0, 1;
  118. PTR_ADDU a2, t0 /* correct size */
  119. PTR_ADDU t0, 1
  120. STORE_BYTE(0)
  121. STORE_BYTE(1)
  122. #if LONGSIZE == 4
  123. EX(sb, a1, 2(a0), .Lbyte_fixup\@)
  124. #else
  125. STORE_BYTE(2)
  126. STORE_BYTE(3)
  127. STORE_BYTE(4)
  128. STORE_BYTE(5)
  129. EX(sb, a1, 6(a0), .Lbyte_fixup\@)
  130. #endif
  131. 0:
  132. ori a0, STORMASK
  133. xori a0, STORMASK
  134. PTR_ADDIU a0, STORSIZE
  135. #endif /* CONFIG_CPU_MIPSR6 */
  136. 1: ori t1, a2, 0x3f /* # of full blocks */
  137. xori t1, 0x3f
  138. beqz t1, .Lmemset_partial\@ /* no block to fill */
  139. andi t0, a2, 0x40-STORSIZE
  140. PTR_ADDU t1, a0 /* end address */
  141. .set reorder
  142. 1: PTR_ADDIU a0, 64
  143. R10KCBARRIER(0(ra))
  144. f_fill64 a0, -64, FILL64RG, .Lfwd_fixup\@, \mode
  145. bne t1, a0, 1b
  146. .set noreorder
  147. .Lmemset_partial\@:
  148. R10KCBARRIER(0(ra))
  149. PTR_LA t1, 2f /* where to start */
  150. #ifdef CONFIG_CPU_MICROMIPS
  151. LONG_SRL t7, t0, 1
  152. #endif
  153. #if LONGSIZE == 4
  154. PTR_SUBU t1, FILLPTRG
  155. #else
  156. .set noat
  157. LONG_SRL AT, FILLPTRG, 1
  158. PTR_SUBU t1, AT
  159. .set at
  160. #endif
  161. jr t1
  162. PTR_ADDU a0, t0 /* dest ptr */
  163. .set push
  164. .set noreorder
  165. .set nomacro
  166. /* ... but first do longs ... */
  167. f_fill64 a0, -64, FILL64RG, .Lpartial_fixup\@, \mode
  168. 2: .set pop
  169. andi a2, STORMASK /* At most one long to go */
  170. beqz a2, 1f
  171. #ifndef CONFIG_CPU_MIPSR6
  172. PTR_ADDU a0, a2 /* What's left */
  173. R10KCBARRIER(0(ra))
  174. #ifdef __MIPSEB__
  175. EX(LONG_S_R, a1, -1(a0), .Llast_fixup\@)
  176. #else
  177. EX(LONG_S_L, a1, -1(a0), .Llast_fixup\@)
  178. #endif
  179. #else
  180. PTR_SUBU t0, $0, a2
  181. PTR_ADDIU t0, 1
  182. STORE_BYTE(0)
  183. STORE_BYTE(1)
  184. #if LONGSIZE == 4
  185. EX(sb, a1, 2(a0), .Lbyte_fixup\@)
  186. #else
  187. STORE_BYTE(2)
  188. STORE_BYTE(3)
  189. STORE_BYTE(4)
  190. STORE_BYTE(5)
  191. EX(sb, a1, 6(a0), .Lbyte_fixup\@)
  192. #endif
  193. 0:
  194. #endif
  195. 1: jr ra
  196. move a2, zero
  197. .Lsmall_memset\@:
  198. beqz a2, 2f
  199. PTR_ADDU t1, a0, a2
  200. 1: PTR_ADDIU a0, 1 /* fill bytewise */
  201. R10KCBARRIER(0(ra))
  202. bne t1, a0, 1b
  203. EX(sb, a1, -1(a0), .Lsmall_fixup\@)
  204. 2: jr ra /* done */
  205. move a2, zero
  206. .if __memset == 1
  207. END(memset)
  208. .set __memset, 0
  209. .hidden __memset
  210. .endif
  211. #ifdef CONFIG_CPU_MIPSR6
  212. .Lbyte_fixup\@:
  213. PTR_SUBU a2, $0, t0
  214. jr ra
  215. PTR_ADDIU a2, 1
  216. #endif /* CONFIG_CPU_MIPSR6 */
  217. .Lfirst_fixup\@:
  218. jr ra
  219. nop
  220. .Lfwd_fixup\@:
  221. PTR_L t0, TI_TASK($28)
  222. andi a2, 0x3f
  223. LONG_L t0, THREAD_BUADDR(t0)
  224. LONG_ADDU a2, t1
  225. jr ra
  226. LONG_SUBU a2, t0
  227. .Lpartial_fixup\@:
  228. PTR_L t0, TI_TASK($28)
  229. andi a2, STORMASK
  230. LONG_L t0, THREAD_BUADDR(t0)
  231. LONG_ADDU a2, a0
  232. jr ra
  233. LONG_SUBU a2, t0
  234. .Llast_fixup\@:
  235. jr ra
  236. nop
  237. .Lsmall_fixup\@:
  238. PTR_SUBU a2, t1, a0
  239. jr ra
  240. PTR_ADDIU a2, 1
  241. .endm
  242. /*
  243. * memset(void *s, int c, size_t n)
  244. *
  245. * a0: start of area to clear
  246. * a1: char to fill with
  247. * a2: size of area to clear
  248. */
  249. LEAF(memset)
  250. EXPORT_SYMBOL(memset)
  251. beqz a1, 1f
  252. move v0, a0 /* result */
  253. andi a1, 0xff /* spread fillword */
  254. LONG_SLL t1, a1, 8
  255. or a1, t1
  256. LONG_SLL t1, a1, 16
  257. #if LONGSIZE == 8
  258. or a1, t1
  259. LONG_SLL t1, a1, 32
  260. #endif
  261. or a1, t1
  262. 1:
  263. #ifndef CONFIG_EVA
  264. FEXPORT(__bzero)
  265. EXPORT_SYMBOL(__bzero)
  266. #else
  267. FEXPORT(__bzero_kernel)
  268. EXPORT_SYMBOL(__bzero_kernel)
  269. #endif
  270. __BUILD_BZERO LEGACY_MODE
  271. #ifdef CONFIG_EVA
  272. LEAF(__bzero)
  273. EXPORT_SYMBOL(__bzero)
  274. __BUILD_BZERO EVA_MODE
  275. END(__bzero)
  276. #endif