xref: /openbmc/linux/arch/s390/lib/mem.S (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
1b2441318SGreg Kroah-Hartman/* SPDX-License-Identifier: GPL-2.0 */
2304987e3SHeiko Carstens/*
3304987e3SHeiko Carstens * String handling functions.
4304987e3SHeiko Carstens *
5304987e3SHeiko Carstens * Copyright IBM Corp. 2012
6304987e3SHeiko Carstens */
7304987e3SHeiko Carstens
8*b8c723f1SMasahiro Yamada#include <linux/export.h>
9304987e3SHeiko Carstens#include <linux/linkage.h>
1097489e06SMartin Schwidefsky#include <asm/nospec-insn.h>
1197489e06SMartin Schwidefsky
1297489e06SMartin Schwidefsky	GEN_BR_THUNK %r14
13304987e3SHeiko Carstens
14304987e3SHeiko Carstens/*
15b4623d4eSHeiko Carstens * void *memmove(void *dest, const void *src, size_t n)
16b4623d4eSHeiko Carstens */
17e48b6853SHeiko CarstensSYM_FUNC_START(__memmove)
18b4623d4eSHeiko Carstens	ltgr	%r4,%r4
19b4623d4eSHeiko Carstens	lgr	%r1,%r2
205eda25b1SMartin Schwidefsky	jz	.Lmemmove_exit
21551f4134SHeiko Carstens	aghi	%r4,-1
22b4623d4eSHeiko Carstens	clgr	%r2,%r3
23b4623d4eSHeiko Carstens	jnh	.Lmemmove_forward
24551f4134SHeiko Carstens	la	%r5,1(%r4,%r3)
25b4623d4eSHeiko Carstens	clgr	%r2,%r5
26b4623d4eSHeiko Carstens	jl	.Lmemmove_reverse
27b4623d4eSHeiko Carstens.Lmemmove_forward:
28b4623d4eSHeiko Carstens	srlg	%r0,%r4,8
29b4623d4eSHeiko Carstens	ltgr	%r0,%r0
30551f4134SHeiko Carstens	jz	.Lmemmove_forward_remainder
31551f4134SHeiko Carstens.Lmemmove_forward_loop:
32b4623d4eSHeiko Carstens	mvc	0(256,%r1),0(%r3)
33b4623d4eSHeiko Carstens	la	%r1,256(%r1)
34b4623d4eSHeiko Carstens	la	%r3,256(%r3)
35551f4134SHeiko Carstens	brctg	%r0,.Lmemmove_forward_loop
36551f4134SHeiko Carstens.Lmemmove_forward_remainder:
37b4623d4eSHeiko Carstens	larl	%r5,.Lmemmove_mvc
38b4623d4eSHeiko Carstens	ex	%r4,0(%r5)
395eda25b1SMartin Schwidefsky.Lmemmove_exit:
4097489e06SMartin Schwidefsky	BR_EX	%r14
41b4623d4eSHeiko Carstens.Lmemmove_reverse:
42b4623d4eSHeiko Carstens	ic	%r0,0(%r4,%r3)
43b4623d4eSHeiko Carstens	stc	%r0,0(%r4,%r1)
44551f4134SHeiko Carstens	brctg	%r4,.Lmemmove_reverse
45b4623d4eSHeiko Carstens	ic	%r0,0(%r4,%r3)
46b4623d4eSHeiko Carstens	stc	%r0,0(%r4,%r1)
4797489e06SMartin Schwidefsky	BR_EX	%r14
48b4623d4eSHeiko Carstens.Lmemmove_mvc:
49b4623d4eSHeiko Carstens	mvc	0(1,%r1),0(%r3)
50e48b6853SHeiko CarstensSYM_FUNC_END(__memmove)
51e48b6853SHeiko CarstensEXPORT_SYMBOL(__memmove)
52e48b6853SHeiko Carstens
53e48b6853SHeiko CarstensSYM_FUNC_ALIAS(memmove, __memmove)
54b4623d4eSHeiko CarstensEXPORT_SYMBOL(memmove)
55b4623d4eSHeiko Carstens
56b4623d4eSHeiko Carstens/*
57304987e3SHeiko Carstens * memset implementation
58304987e3SHeiko Carstens *
59304987e3SHeiko Carstens * This code corresponds to the C construct below. We do distinguish
60304987e3SHeiko Carstens * between clearing (c == 0) and setting a memory array (c != 0) simply
61304987e3SHeiko Carstens * because nearly all memset invocations in the kernel clear memory and
62304987e3SHeiko Carstens * the xc instruction is preferred in such cases.
63304987e3SHeiko Carstens *
64304987e3SHeiko Carstens * void *memset(void *s, int c, size_t n)
65304987e3SHeiko Carstens * {
66304987e3SHeiko Carstens *	if (likely(c == 0))
67304987e3SHeiko Carstens *		return __builtin_memset(s, 0, n);
68304987e3SHeiko Carstens *	return __builtin_memset(s, c, n);
69304987e3SHeiko Carstens * }
70304987e3SHeiko Carstens */
71e48b6853SHeiko CarstensSYM_FUNC_START(__memset)
72304987e3SHeiko Carstens	ltgr	%r4,%r4
735eda25b1SMartin Schwidefsky	jz	.Lmemset_exit
74304987e3SHeiko Carstens	ltgr	%r3,%r3
75304987e3SHeiko Carstens	jnz	.Lmemset_fill
76304987e3SHeiko Carstens	aghi	%r4,-1
77304987e3SHeiko Carstens	srlg	%r3,%r4,8
78304987e3SHeiko Carstens	ltgr	%r3,%r3
79304987e3SHeiko Carstens	lgr	%r1,%r2
80551f4134SHeiko Carstens	jz	.Lmemset_clear_remainder
81304987e3SHeiko Carstens.Lmemset_clear_loop:
82304987e3SHeiko Carstens	xc	0(256,%r1),0(%r1)
83304987e3SHeiko Carstens	la	%r1,256(%r1)
84304987e3SHeiko Carstens	brctg	%r3,.Lmemset_clear_loop
85551f4134SHeiko Carstens.Lmemset_clear_remainder:
86304987e3SHeiko Carstens	larl	%r3,.Lmemset_xc
87304987e3SHeiko Carstens	ex	%r4,0(%r3)
885eda25b1SMartin Schwidefsky.Lmemset_exit:
8997489e06SMartin Schwidefsky	BR_EX	%r14
90304987e3SHeiko Carstens.Lmemset_fill:
91304987e3SHeiko Carstens	cghi	%r4,1
92304987e3SHeiko Carstens	lgr	%r1,%r2
93993fef95SHeiko Carstens	je	.Lmemset_fill_exit
94304987e3SHeiko Carstens	aghi	%r4,-2
95993fef95SHeiko Carstens	srlg	%r5,%r4,8
96993fef95SHeiko Carstens	ltgr	%r5,%r5
97551f4134SHeiko Carstens	jz	.Lmemset_fill_remainder
98304987e3SHeiko Carstens.Lmemset_fill_loop:
99993fef95SHeiko Carstens	stc	%r3,0(%r1)
100993fef95SHeiko Carstens	mvc	1(255,%r1),0(%r1)
101304987e3SHeiko Carstens	la	%r1,256(%r1)
102993fef95SHeiko Carstens	brctg	%r5,.Lmemset_fill_loop
103551f4134SHeiko Carstens.Lmemset_fill_remainder:
104993fef95SHeiko Carstens	stc	%r3,0(%r1)
105993fef95SHeiko Carstens	larl	%r5,.Lmemset_mvc
106993fef95SHeiko Carstens	ex	%r4,0(%r5)
10797489e06SMartin Schwidefsky	BR_EX	%r14
108993fef95SHeiko Carstens.Lmemset_fill_exit:
109993fef95SHeiko Carstens	stc	%r3,0(%r1)
11097489e06SMartin Schwidefsky	BR_EX	%r14
111304987e3SHeiko Carstens.Lmemset_xc:
112304987e3SHeiko Carstens	xc	0(1,%r1),0(%r1)
113304987e3SHeiko Carstens.Lmemset_mvc:
114304987e3SHeiko Carstens	mvc	1(1,%r1),0(%r1)
115e48b6853SHeiko CarstensSYM_FUNC_END(__memset)
116e48b6853SHeiko CarstensEXPORT_SYMBOL(__memset)
117e48b6853SHeiko Carstens
118e48b6853SHeiko CarstensSYM_FUNC_ALIAS(memset, __memset)
119711f5df7SAl ViroEXPORT_SYMBOL(memset)
120304987e3SHeiko Carstens
121304987e3SHeiko Carstens/*
122304987e3SHeiko Carstens * memcpy implementation
123304987e3SHeiko Carstens *
124304987e3SHeiko Carstens * void *memcpy(void *dest, const void *src, size_t n)
125304987e3SHeiko Carstens */
126e48b6853SHeiko CarstensSYM_FUNC_START(__memcpy)
127304987e3SHeiko Carstens	ltgr	%r4,%r4
1285eda25b1SMartin Schwidefsky	jz	.Lmemcpy_exit
129304987e3SHeiko Carstens	aghi	%r4,-1
130304987e3SHeiko Carstens	srlg	%r5,%r4,8
131304987e3SHeiko Carstens	ltgr	%r5,%r5
132304987e3SHeiko Carstens	lgr	%r1,%r2
133304987e3SHeiko Carstens	jnz	.Lmemcpy_loop
134551f4134SHeiko Carstens.Lmemcpy_remainder:
135304987e3SHeiko Carstens	larl	%r5,.Lmemcpy_mvc
136304987e3SHeiko Carstens	ex	%r4,0(%r5)
1375eda25b1SMartin Schwidefsky.Lmemcpy_exit:
13897489e06SMartin Schwidefsky	BR_EX	%r14
139304987e3SHeiko Carstens.Lmemcpy_loop:
140304987e3SHeiko Carstens	mvc	0(256,%r1),0(%r3)
141304987e3SHeiko Carstens	la	%r1,256(%r1)
142304987e3SHeiko Carstens	la	%r3,256(%r3)
143304987e3SHeiko Carstens	brctg	%r5,.Lmemcpy_loop
144551f4134SHeiko Carstens	j	.Lmemcpy_remainder
145304987e3SHeiko Carstens.Lmemcpy_mvc:
146304987e3SHeiko Carstens	mvc	0(1,%r1),0(%r3)
147e48b6853SHeiko CarstensSYM_FUNC_END(__memcpy)
148e48b6853SHeiko CarstensEXPORT_SYMBOL(__memcpy)
149e48b6853SHeiko Carstens
150e48b6853SHeiko CarstensSYM_FUNC_ALIAS(memcpy, __memcpy)
151711f5df7SAl ViroEXPORT_SYMBOL(memcpy)
1520b77d670SHeiko Carstens
1530b77d670SHeiko Carstens/*
1540b77d670SHeiko Carstens * __memset16/32/64
1550b77d670SHeiko Carstens *
1560b77d670SHeiko Carstens * void *__memset16(uint16_t *s, uint16_t v, size_t count)
1570b77d670SHeiko Carstens * void *__memset32(uint32_t *s, uint32_t v, size_t count)
1580b77d670SHeiko Carstens * void *__memset64(uint64_t *s, uint64_t v, size_t count)
1590b77d670SHeiko Carstens */
1600b77d670SHeiko Carstens.macro __MEMSET bits,bytes,insn
16145769052SHeiko CarstensSYM_FUNC_START(__memset\bits)
1620b77d670SHeiko Carstens	ltgr	%r4,%r4
1635eda25b1SMartin Schwidefsky	jz	.L__memset_exit\bits
1640b77d670SHeiko Carstens	cghi	%r4,\bytes
1655eda25b1SMartin Schwidefsky	je	.L__memset_store\bits
1660b77d670SHeiko Carstens	aghi	%r4,-(\bytes+1)
1670b77d670SHeiko Carstens	srlg	%r5,%r4,8
1680b77d670SHeiko Carstens	ltgr	%r5,%r5
1690b77d670SHeiko Carstens	lgr	%r1,%r2
1700b77d670SHeiko Carstens	jz	.L__memset_remainder\bits
1710b77d670SHeiko Carstens.L__memset_loop\bits:
1720b77d670SHeiko Carstens	\insn	%r3,0(%r1)
1730b77d670SHeiko Carstens	mvc	\bytes(256-\bytes,%r1),0(%r1)
1740b77d670SHeiko Carstens	la	%r1,256(%r1)
1750b77d670SHeiko Carstens	brctg	%r5,.L__memset_loop\bits
1760b77d670SHeiko Carstens.L__memset_remainder\bits:
1770b77d670SHeiko Carstens	\insn	%r3,0(%r1)
1780b77d670SHeiko Carstens	larl	%r5,.L__memset_mvc\bits
1790b77d670SHeiko Carstens	ex	%r4,0(%r5)
18097489e06SMartin Schwidefsky	BR_EX	%r14
1815eda25b1SMartin Schwidefsky.L__memset_store\bits:
1820b77d670SHeiko Carstens	\insn	%r3,0(%r2)
1835eda25b1SMartin Schwidefsky.L__memset_exit\bits:
18497489e06SMartin Schwidefsky	BR_EX	%r14
1850b77d670SHeiko Carstens.L__memset_mvc\bits:
1860b77d670SHeiko Carstens	mvc	\bytes(1,%r1),0(%r1)
18745769052SHeiko CarstensSYM_FUNC_END(__memset\bits)
1880b77d670SHeiko Carstens.endm
1890b77d670SHeiko Carstens
1900b77d670SHeiko Carstens__MEMSET 16,2,sth
1910b77d670SHeiko CarstensEXPORT_SYMBOL(__memset16)
1920b77d670SHeiko Carstens
1930b77d670SHeiko Carstens__MEMSET 32,4,st
1940b77d670SHeiko CarstensEXPORT_SYMBOL(__memset32)
1950b77d670SHeiko Carstens
1960b77d670SHeiko Carstens__MEMSET 64,8,stg
1970b77d670SHeiko CarstensEXPORT_SYMBOL(__memset64)
198