mem.S 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. /*
  3. * String handling functions.
  4. *
  5. * Copyright IBM Corp. 2012
  6. */
  7. #include <linux/linkage.h>
  8. #include <asm/export.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. WEAK(memmove)
  15. ENTRY(__memmove)
  16. ltgr %r4,%r4
  17. lgr %r1,%r2
  18. jz .Lmemmove_exit
  19. aghi %r4,-1
  20. clgr %r2,%r3
  21. jnh .Lmemmove_forward
  22. la %r5,1(%r4,%r3)
  23. clgr %r2,%r5
  24. jl .Lmemmove_reverse
  25. .Lmemmove_forward:
  26. srlg %r0,%r4,8
  27. ltgr %r0,%r0
  28. jz .Lmemmove_forward_remainder
  29. .Lmemmove_forward_loop:
  30. mvc 0(256,%r1),0(%r3)
  31. la %r1,256(%r1)
  32. la %r3,256(%r3)
  33. brctg %r0,.Lmemmove_forward_loop
  34. .Lmemmove_forward_remainder:
  35. larl %r5,.Lmemmove_mvc
  36. ex %r4,0(%r5)
  37. .Lmemmove_exit:
  38. BR_EX %r14
  39. .Lmemmove_reverse:
  40. ic %r0,0(%r4,%r3)
  41. stc %r0,0(%r4,%r1)
  42. brctg %r4,.Lmemmove_reverse
  43. ic %r0,0(%r4,%r3)
  44. stc %r0,0(%r4,%r1)
  45. BR_EX %r14
  46. .Lmemmove_mvc:
  47. mvc 0(1,%r1),0(%r3)
  48. ENDPROC(__memmove)
  49. EXPORT_SYMBOL(memmove)
  50. /*
  51. * memset implementation
  52. *
  53. * This code corresponds to the C construct below. We do distinguish
  54. * between clearing (c == 0) and setting a memory array (c != 0) simply
  55. * because nearly all memset invocations in the kernel clear memory and
  56. * the xc instruction is preferred in such cases.
  57. *
  58. * void *memset(void *s, int c, size_t n)
  59. * {
  60. * if (likely(c == 0))
  61. * return __builtin_memset(s, 0, n);
  62. * return __builtin_memset(s, c, n);
  63. * }
  64. */
  65. WEAK(memset)
  66. ENTRY(__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. ENDPROC(__memset)
  111. EXPORT_SYMBOL(memset)
  112. /*
  113. * memcpy implementation
  114. *
  115. * void *memcpy(void *dest, const void *src, size_t n)
  116. */
  117. WEAK(memcpy)
  118. ENTRY(__memcpy)
  119. ltgr %r4,%r4
  120. jz .Lmemcpy_exit
  121. aghi %r4,-1
  122. srlg %r5,%r4,8
  123. ltgr %r5,%r5
  124. lgr %r1,%r2
  125. jnz .Lmemcpy_loop
  126. .Lmemcpy_remainder:
  127. larl %r5,.Lmemcpy_mvc
  128. ex %r4,0(%r5)
  129. .Lmemcpy_exit:
  130. BR_EX %r14
  131. .Lmemcpy_loop:
  132. mvc 0(256,%r1),0(%r3)
  133. la %r1,256(%r1)
  134. la %r3,256(%r3)
  135. brctg %r5,.Lmemcpy_loop
  136. j .Lmemcpy_remainder
  137. .Lmemcpy_mvc:
  138. mvc 0(1,%r1),0(%r3)
  139. ENDPROC(__memcpy)
  140. EXPORT_SYMBOL(memcpy)
  141. /*
  142. * __memset16/32/64
  143. *
  144. * void *__memset16(uint16_t *s, uint16_t v, size_t count)
  145. * void *__memset32(uint32_t *s, uint32_t v, size_t count)
  146. * void *__memset64(uint64_t *s, uint64_t v, size_t count)
  147. */
  148. .macro __MEMSET bits,bytes,insn
  149. ENTRY(__memset\bits)
  150. ltgr %r4,%r4
  151. jz .L__memset_exit\bits
  152. cghi %r4,\bytes
  153. je .L__memset_store\bits
  154. aghi %r4,-(\bytes+1)
  155. srlg %r5,%r4,8
  156. ltgr %r5,%r5
  157. lgr %r1,%r2
  158. jz .L__memset_remainder\bits
  159. .L__memset_loop\bits:
  160. \insn %r3,0(%r1)
  161. mvc \bytes(256-\bytes,%r1),0(%r1)
  162. la %r1,256(%r1)
  163. brctg %r5,.L__memset_loop\bits
  164. .L__memset_remainder\bits:
  165. \insn %r3,0(%r1)
  166. larl %r5,.L__memset_mvc\bits
  167. ex %r4,0(%r5)
  168. BR_EX %r14
  169. .L__memset_store\bits:
  170. \insn %r3,0(%r2)
  171. .L__memset_exit\bits:
  172. BR_EX %r14
  173. .L__memset_mvc\bits:
  174. mvc \bytes(1,%r1),0(%r1)
  175. ENDPROC(__memset\bits)
  176. .endm
  177. __MEMSET 16,2,sth
  178. EXPORT_SYMBOL(__memset16)
  179. __MEMSET 32,4,st
  180. EXPORT_SYMBOL(__memset32)
  181. __MEMSET 64,8,stg
  182. EXPORT_SYMBOL(__memset64)