memset.S 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  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. move a2, zero /* No remaining longs */
  182. PTR_ADDIU t0, 1
  183. STORE_BYTE(0)
  184. STORE_BYTE(1)
  185. #if LONGSIZE == 4
  186. EX(sb, a1, 2(a0), .Lbyte_fixup\@)
  187. #else
  188. STORE_BYTE(2)
  189. STORE_BYTE(3)
  190. STORE_BYTE(4)
  191. STORE_BYTE(5)
  192. EX(sb, a1, 6(a0), .Lbyte_fixup\@)
  193. #endif
  194. 0:
  195. #endif
  196. 1: jr ra
  197. move a2, zero
  198. .Lsmall_memset\@:
  199. beqz a2, 2f
  200. PTR_ADDU t1, a0, a2
  201. 1: PTR_ADDIU a0, 1 /* fill bytewise */
  202. R10KCBARRIER(0(ra))
  203. bne t1, a0, 1b
  204. EX(sb, a1, -1(a0), .Lsmall_fixup\@)
  205. 2: jr ra /* done */
  206. move a2, zero
  207. .if __memset == 1
  208. END(memset)
  209. .set __memset, 0
  210. .hidden __memset
  211. .endif
  212. #ifdef CONFIG_CPU_MIPSR6
  213. .Lbyte_fixup\@:
  214. /*
  215. * unset_bytes = (#bytes - (#unaligned bytes)) - (-#unaligned bytes remaining + 1) + 1
  216. * a2 = a2 - t0 + 1
  217. */
  218. PTR_SUBU a2, t0
  219. jr ra
  220. PTR_ADDIU a2, 1
  221. #endif /* CONFIG_CPU_MIPSR6 */
  222. .Lfirst_fixup\@:
  223. /* unset_bytes already in a2 */
  224. jr ra
  225. nop
  226. .Lfwd_fixup\@:
  227. /*
  228. * unset_bytes = partial_start_addr + #bytes - fault_addr
  229. * a2 = t1 + (a2 & 3f) - $28->task->BUADDR
  230. */
  231. PTR_L t0, TI_TASK($28)
  232. andi a2, 0x3f
  233. LONG_L t0, THREAD_BUADDR(t0)
  234. LONG_ADDU a2, t1
  235. jr ra
  236. LONG_SUBU a2, t0
  237. .Lpartial_fixup\@:
  238. /*
  239. * unset_bytes = partial_end_addr + #bytes - fault_addr
  240. * a2 = a0 + (a2 & STORMASK) - $28->task->BUADDR
  241. */
  242. PTR_L t0, TI_TASK($28)
  243. andi a2, STORMASK
  244. LONG_L t0, THREAD_BUADDR(t0)
  245. LONG_ADDU a2, a0
  246. jr ra
  247. LONG_SUBU a2, t0
  248. .Llast_fixup\@:
  249. /* unset_bytes already in a2 */
  250. jr ra
  251. nop
  252. .Lsmall_fixup\@:
  253. /*
  254. * unset_bytes = end_addr - current_addr + 1
  255. * a2 = t1 - a0 + 1
  256. */
  257. .set reorder
  258. PTR_SUBU a2, t1, a0
  259. PTR_ADDIU a2, 1
  260. jr ra
  261. .set noreorder
  262. .endm
  263. /*
  264. * memset(void *s, int c, size_t n)
  265. *
  266. * a0: start of area to clear
  267. * a1: char to fill with
  268. * a2: size of area to clear
  269. */
  270. LEAF(memset)
  271. EXPORT_SYMBOL(memset)
  272. beqz a1, 1f
  273. move v0, a0 /* result */
  274. andi a1, 0xff /* spread fillword */
  275. LONG_SLL t1, a1, 8
  276. or a1, t1
  277. LONG_SLL t1, a1, 16
  278. #if LONGSIZE == 8
  279. or a1, t1
  280. LONG_SLL t1, a1, 32
  281. #endif
  282. or a1, t1
  283. 1:
  284. #ifndef CONFIG_EVA
  285. FEXPORT(__bzero)
  286. EXPORT_SYMBOL(__bzero)
  287. #else
  288. FEXPORT(__bzero_kernel)
  289. EXPORT_SYMBOL(__bzero_kernel)
  290. #endif
  291. __BUILD_BZERO LEGACY_MODE
  292. #ifdef CONFIG_EVA
  293. LEAF(__bzero)
  294. EXPORT_SYMBOL(__bzero)
  295. __BUILD_BZERO EVA_MODE
  296. END(__bzero)
  297. #endif