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