mem.S 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. /*
  3. * String handling functions.
  4. *
  5. * Copyright IBM Corp. 2012
  6. */
  7. #include <linux/export.h>
  8. #include <linux/linkage.h>
  9. #include <asm/nospec-insn.h>
  10. GEN_BR_THUNK %r14
  11. /*
  12. * void *memmove(void *dest, const void *src, size_t n)
  13. */
  14. SYM_FUNC_START(__memmove)
  15. ltgr %r4,%r4
  16. lgr %r1,%r2
  17. jz .Lmemmove_exit
  18. aghi %r4,-1
  19. clgr %r2,%r3
  20. jnh .Lmemmove_forward
  21. la %r5,1(%r4,%r3)
  22. clgr %r2,%r5
  23. jl .Lmemmove_reverse
  24. .Lmemmove_forward:
  25. srlg %r0,%r4,8
  26. ltgr %r0,%r0
  27. jz .Lmemmove_forward_remainder
  28. .Lmemmove_forward_loop:
  29. mvc 0(256,%r1),0(%r3)
  30. la %r1,256(%r1)
  31. la %r3,256(%r3)
  32. brctg %r0,.Lmemmove_forward_loop
  33. .Lmemmove_forward_remainder:
  34. larl %r5,.Lmemmove_mvc
  35. ex %r4,0(%r5)
  36. .Lmemmove_exit:
  37. BR_EX %r14
  38. .Lmemmove_reverse:
  39. ic %r0,0(%r4,%r3)
  40. stc %r0,0(%r4,%r1)
  41. brctg %r4,.Lmemmove_reverse
  42. ic %r0,0(%r4,%r3)
  43. stc %r0,0(%r4,%r1)
  44. BR_EX %r14
  45. .Lmemmove_mvc:
  46. mvc 0(1,%r1),0(%r3)
  47. SYM_FUNC_END(__memmove)
  48. EXPORT_SYMBOL(__memmove)
  49. SYM_FUNC_ALIAS(memmove, __memmove)
  50. EXPORT_SYMBOL(memmove)
  51. /*
  52. * memset implementation
  53. *
  54. * This code corresponds to the C construct below. We do distinguish
  55. * between clearing (c == 0) and setting a memory array (c != 0) simply
  56. * because nearly all memset invocations in the kernel clear memory and
  57. * the xc instruction is preferred in such cases.
  58. *
  59. * void *memset(void *s, int c, size_t n)
  60. * {
  61. * if (likely(c == 0))
  62. * return __builtin_memset(s, 0, n);
  63. * return __builtin_memset(s, c, n);
  64. * }
  65. */
  66. SYM_FUNC_START(__memset)
  67. ltgr %r4,%r4
  68. jz .Lmemset_exit
  69. ltgr %r3,%r3
  70. jnz .Lmemset_fill
  71. aghi %r4,-1
  72. srlg %r3,%r4,8
  73. ltgr %r3,%r3
  74. lgr %r1,%r2
  75. jz .Lmemset_clear_remainder
  76. .Lmemset_clear_loop:
  77. xc 0(256,%r1),0(%r1)
  78. la %r1,256(%r1)
  79. brctg %r3,.Lmemset_clear_loop
  80. .Lmemset_clear_remainder:
  81. larl %r3,.Lmemset_xc
  82. ex %r4,0(%r3)
  83. .Lmemset_exit:
  84. BR_EX %r14
  85. .Lmemset_fill:
  86. cghi %r4,1
  87. lgr %r1,%r2
  88. je .Lmemset_fill_exit
  89. aghi %r4,-2
  90. srlg %r5,%r4,8
  91. ltgr %r5,%r5
  92. jz .Lmemset_fill_remainder
  93. .Lmemset_fill_loop:
  94. stc %r3,0(%r1)
  95. mvc 1(255,%r1),0(%r1)
  96. la %r1,256(%r1)
  97. brctg %r5,.Lmemset_fill_loop
  98. .Lmemset_fill_remainder:
  99. stc %r3,0(%r1)
  100. larl %r5,.Lmemset_mvc
  101. ex %r4,0(%r5)
  102. BR_EX %r14
  103. .Lmemset_fill_exit:
  104. stc %r3,0(%r1)
  105. BR_EX %r14
  106. .Lmemset_xc:
  107. xc 0(1,%r1),0(%r1)
  108. .Lmemset_mvc:
  109. mvc 1(1,%r1),0(%r1)
  110. SYM_FUNC_END(__memset)
  111. EXPORT_SYMBOL(__memset)
  112. SYM_FUNC_ALIAS(memset, __memset)
  113. EXPORT_SYMBOL(memset)
  114. /*
  115. * memcpy implementation
  116. *
  117. * void *memcpy(void *dest, const void *src, size_t n)
  118. */
  119. SYM_FUNC_START(__memcpy)
  120. ltgr %r4,%r4
  121. jz .Lmemcpy_exit
  122. aghi %r4,-1
  123. srlg %r5,%r4,8
  124. ltgr %r5,%r5
  125. lgr %r1,%r2
  126. jnz .Lmemcpy_loop
  127. .Lmemcpy_remainder:
  128. larl %r5,.Lmemcpy_mvc
  129. ex %r4,0(%r5)
  130. .Lmemcpy_exit:
  131. BR_EX %r14
  132. .Lmemcpy_loop:
  133. mvc 0(256,%r1),0(%r3)
  134. la %r1,256(%r1)
  135. la %r3,256(%r3)
  136. brctg %r5,.Lmemcpy_loop
  137. j .Lmemcpy_remainder
  138. .Lmemcpy_mvc:
  139. mvc 0(1,%r1),0(%r3)
  140. SYM_FUNC_END(__memcpy)
  141. EXPORT_SYMBOL(__memcpy)
  142. SYM_FUNC_ALIAS(memcpy, __memcpy)
  143. EXPORT_SYMBOL(memcpy)
  144. /*
  145. * __memset16/32/64
  146. *
  147. * void *__memset16(uint16_t *s, uint16_t v, size_t count)
  148. * void *__memset32(uint32_t *s, uint32_t v, size_t count)
  149. * void *__memset64(uint64_t *s, uint64_t v, size_t count)
  150. */
  151. .macro __MEMSET bits,bytes,insn
  152. SYM_FUNC_START(__memset\bits)
  153. ltgr %r4,%r4
  154. jz .L__memset_exit\bits
  155. cghi %r4,\bytes
  156. je .L__memset_store\bits
  157. aghi %r4,-(\bytes+1)
  158. srlg %r5,%r4,8
  159. ltgr %r5,%r5
  160. lgr %r1,%r2
  161. jz .L__memset_remainder\bits
  162. .L__memset_loop\bits:
  163. \insn %r3,0(%r1)
  164. mvc \bytes(256-\bytes,%r1),0(%r1)
  165. la %r1,256(%r1)
  166. brctg %r5,.L__memset_loop\bits
  167. .L__memset_remainder\bits:
  168. \insn %r3,0(%r1)
  169. larl %r5,.L__memset_mvc\bits
  170. ex %r4,0(%r5)
  171. BR_EX %r14
  172. .L__memset_store\bits:
  173. \insn %r3,0(%r2)
  174. .L__memset_exit\bits:
  175. BR_EX %r14
  176. .L__memset_mvc\bits:
  177. mvc \bytes(1,%r1),0(%r1)
  178. SYM_FUNC_END(__memset\bits)
  179. .endm
  180. __MEMSET 16,2,sth
  181. EXPORT_SYMBOL(__memset16)
  182. __MEMSET 32,4,st
  183. EXPORT_SYMBOL(__memset32)
  184. __MEMSET 64,8,stg
  185. EXPORT_SYMBOL(__memset64)