memset.S 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  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_WD 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. .align 5
  75. /*
  76. * Macro to generate the __bzero{,_user} symbol
  77. * Arguments:
  78. * mode: LEGACY_MODE or EVA_MODE
  79. */
  80. .macro __BUILD_BZERO mode
  81. /* Initialize __memset if this is the first time we call this macro */
  82. .ifnotdef __memset
  83. .set __memset, 1
  84. .hidden __memset /* Make sure it does not leak */
  85. .endif
  86. sltiu t0, a2, STORSIZE /* very small region? */
  87. .set noreorder
  88. bnez t0, .Lsmall_memset\@
  89. andi t0, a0, STORMASK /* aligned? */
  90. .set reorder
  91. #ifdef CONFIG_CPU_MICROMIPS
  92. move t8, a1 /* used by 'swp' instruction */
  93. move t9, a1
  94. #endif
  95. .set noreorder
  96. #ifndef CONFIG_CPU_DADDI_WORKAROUNDS
  97. beqz t0, 1f
  98. PTR_SUBU t0, STORSIZE /* alignment in bytes */
  99. #else
  100. .set noat
  101. li AT, STORSIZE
  102. beqz t0, 1f
  103. PTR_SUBU t0, AT /* alignment in bytes */
  104. .set at
  105. #endif
  106. .set reorder
  107. #ifndef CONFIG_CPU_NO_LOAD_STORE_LR
  108. R10KCBARRIER(0(ra))
  109. #ifdef __MIPSEB__
  110. EX(LONG_S_L, a1, (a0), .Lfirst_fixup\@) /* make word/dword aligned */
  111. #else
  112. EX(LONG_S_R, a1, (a0), .Lfirst_fixup\@) /* make word/dword aligned */
  113. #endif
  114. PTR_SUBU a0, t0 /* long align ptr */
  115. PTR_ADDU a2, t0 /* correct size */
  116. #else /* CONFIG_CPU_NO_LOAD_STORE_LR */
  117. #define STORE_BYTE(N) \
  118. EX(sb, a1, N(a0), .Lbyte_fixup\@); \
  119. .set noreorder; \
  120. beqz t0, 0f; \
  121. PTR_ADDU t0, 1; \
  122. .set reorder;
  123. PTR_ADDU a2, t0 /* correct size */
  124. PTR_ADDU t0, 1
  125. STORE_BYTE(0)
  126. STORE_BYTE(1)
  127. #if LONGSIZE == 4
  128. EX(sb, a1, 2(a0), .Lbyte_fixup\@)
  129. #else
  130. STORE_BYTE(2)
  131. STORE_BYTE(3)
  132. STORE_BYTE(4)
  133. STORE_BYTE(5)
  134. EX(sb, a1, 6(a0), .Lbyte_fixup\@)
  135. #endif
  136. 0:
  137. ori a0, STORMASK
  138. xori a0, STORMASK
  139. PTR_ADDIU a0, STORSIZE
  140. #endif /* CONFIG_CPU_NO_LOAD_STORE_LR */
  141. 1: ori t1, a2, 0x3f /* # of full blocks */
  142. xori t1, 0x3f
  143. andi t0, a2, 0x40-STORSIZE
  144. beqz t1, .Lmemset_partial\@ /* no block to fill */
  145. PTR_ADDU t1, a0 /* end address */
  146. 1: PTR_ADDIU a0, 64
  147. R10KCBARRIER(0(ra))
  148. f_fill64 a0, -64, FILL64RG, .Lfwd_fixup\@, \mode
  149. bne t1, a0, 1b
  150. .Lmemset_partial\@:
  151. R10KCBARRIER(0(ra))
  152. PTR_LA t1, 2f /* where to start */
  153. #ifdef CONFIG_CPU_MICROMIPS
  154. LONG_SRL t7, t0, 1
  155. #endif
  156. #if LONGSIZE == 4
  157. PTR_SUBU t1, FILLPTRG
  158. #else
  159. .set noat
  160. LONG_SRL AT, FILLPTRG, 1
  161. PTR_SUBU t1, AT
  162. .set at
  163. #endif
  164. PTR_ADDU a0, t0 /* dest ptr */
  165. jr t1
  166. /* ... but first do longs ... */
  167. f_fill64 a0, -64, FILL64RG, .Lpartial_fixup\@, \mode
  168. 2: andi a2, STORMASK /* At most one long to go */
  169. .set noreorder
  170. beqz a2, 1f
  171. #ifndef CONFIG_CPU_NO_LOAD_STORE_LR
  172. PTR_ADDU a0, a2 /* What's left */
  173. .set reorder
  174. R10KCBARRIER(0(ra))
  175. #ifdef __MIPSEB__
  176. EX(LONG_S_R, a1, -1(a0), .Llast_fixup\@)
  177. #else
  178. EX(LONG_S_L, a1, -1(a0), .Llast_fixup\@)
  179. #endif
  180. #else /* CONFIG_CPU_NO_LOAD_STORE_LR */
  181. PTR_SUBU t0, $0, a2
  182. .set reorder
  183. move a2, zero /* No remaining longs */
  184. PTR_ADDIU t0, 1
  185. STORE_BYTE(0)
  186. STORE_BYTE(1)
  187. #if LONGSIZE == 4
  188. EX(sb, a1, 2(a0), .Lbyte_fixup\@)
  189. #else
  190. STORE_BYTE(2)
  191. STORE_BYTE(3)
  192. STORE_BYTE(4)
  193. STORE_BYTE(5)
  194. EX(sb, a1, 6(a0), .Lbyte_fixup\@)
  195. #endif
  196. 0:
  197. #endif /* CONFIG_CPU_NO_LOAD_STORE_LR */
  198. 1: move a2, zero
  199. jr ra
  200. .Lsmall_memset\@:
  201. PTR_ADDU t1, a0, a2
  202. beqz a2, 2f
  203. 1: PTR_ADDIU a0, 1 /* fill bytewise */
  204. R10KCBARRIER(0(ra))
  205. .set noreorder
  206. bne t1, a0, 1b
  207. EX(sb, a1, -1(a0), .Lsmall_fixup\@)
  208. .set reorder
  209. 2: move a2, zero
  210. jr ra /* done */
  211. .if __memset == 1
  212. END(memset)
  213. .set __memset, 0
  214. .hidden __memset
  215. .endif
  216. #ifdef CONFIG_CPU_NO_LOAD_STORE_LR
  217. .Lbyte_fixup\@:
  218. /*
  219. * unset_bytes = (#bytes - (#unaligned bytes)) - (-#unaligned bytes remaining + 1) + 1
  220. * a2 = a2 - t0 + 1
  221. */
  222. PTR_SUBU a2, t0
  223. PTR_ADDIU a2, 1
  224. jr ra
  225. #endif /* CONFIG_CPU_NO_LOAD_STORE_LR */
  226. .Lfirst_fixup\@:
  227. /* unset_bytes already in a2 */
  228. jr ra
  229. .Lfwd_fixup\@:
  230. /*
  231. * unset_bytes = partial_start_addr + #bytes - fault_addr
  232. * a2 = t1 + (a2 & 3f) - $28->task->BUADDR
  233. */
  234. PTR_L t0, TI_TASK($28)
  235. andi a2, 0x3f
  236. LONG_L t0, THREAD_BUADDR(t0)
  237. LONG_ADDU a2, t1
  238. LONG_SUBU a2, t0
  239. jr ra
  240. .Lpartial_fixup\@:
  241. /*
  242. * unset_bytes = partial_end_addr + #bytes - fault_addr
  243. * a2 = a0 + (a2 & STORMASK) - $28->task->BUADDR
  244. */
  245. PTR_L t0, TI_TASK($28)
  246. andi a2, STORMASK
  247. LONG_L t0, THREAD_BUADDR(t0)
  248. LONG_ADDU a2, a0
  249. LONG_SUBU a2, t0
  250. jr ra
  251. .Llast_fixup\@:
  252. /* unset_bytes already in a2 */
  253. jr ra
  254. .Lsmall_fixup\@:
  255. /*
  256. * unset_bytes = end_addr - current_addr + 1
  257. * a2 = t1 - a0 + 1
  258. */
  259. PTR_SUBU a2, t1, a0
  260. PTR_ADDIU a2, 1
  261. jr ra
  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. move v0, a0 /* result */
  273. beqz a1, 1f
  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. #endif
  288. __BUILD_BZERO LEGACY_MODE
  289. #ifdef CONFIG_EVA
  290. LEAF(__bzero)
  291. EXPORT_SYMBOL(__bzero)
  292. __BUILD_BZERO EVA_MODE
  293. END(__bzero)
  294. #endif