aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/lib/mem.S
blob: 7422a706f31048aab96945dea2b24ebae6deffee (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/*
 * String handling functions.
 *
 * Copyright IBM Corp. 2012
 */

#include <linux/linkage.h>
#include <asm/export.h>

/*
 * void *memmove(void *dest, const void *src, size_t n)
 */
ENTRY(memmove)
	ltgr	%r4,%r4
	lgr	%r1,%r2
	bzr	%r14
	clgr	%r2,%r3
	jnh	.Lmemmove_forward
	la	%r5,0(%r4,%r3)
	clgr	%r2,%r5
	jl	.Lmemmove_reverse
.Lmemmove_forward:
	aghi	%r4,-1
	srlg	%r0,%r4,8
	ltgr	%r0,%r0
	jz	.Lmemmove_rest
.Lmemmove_loop:
	mvc	0(256,%r1),0(%r3)
	la	%r1,256(%r1)
	la	%r3,256(%r3)
	brctg	%r0,.Lmemmove_loop
.Lmemmove_rest:
	larl	%r5,.Lmemmove_mvc
	ex	%r4,0(%r5)
	br	%r14
.Lmemmove_reverse:
	aghi	%r4,-1
.Lmemmove_reverse_loop:
	ic	%r0,0(%r4,%r3)
	stc	%r0,0(%r4,%r1)
	brctg	%r4,.Lmemmove_reverse_loop
	ic	%r0,0(%r4,%r3)
	stc	%r0,0(%r4,%r1)
	br	%r14
.Lmemmove_mvc:
	mvc	0(1,%r1),0(%r3)
EXPORT_SYMBOL(memmove)

/*
 * memset implementation
 *
 * This code corresponds to the C construct below. We do distinguish
 * between clearing (c == 0) and setting a memory array (c != 0) simply
 * because nearly all memset invocations in the kernel clear memory and
 * the xc instruction is preferred in such cases.
 *
 * void *memset(void *s, int c, size_t n)
 * {
 *	if (likely(c == 0))
 *		return __builtin_memset(s, 0, n);
 *	return __builtin_memset(s, c, n);
 * }
 */
ENTRY(memset)
	ltgr	%r4,%r4
	bzr	%r14
	ltgr	%r3,%r3
	jnz	.Lmemset_fill
	aghi	%r4,-1
	srlg	%r3,%r4,8
	ltgr	%r3,%r3
	lgr	%r1,%r2
	jz	.Lmemset_clear_rest
.Lmemset_clear_loop:
	xc	0(256,%r1),0(%r1)
	la	%r1,256(%r1)
	brctg	%r3,.Lmemset_clear_loop
.Lmemset_clear_rest:
	larl	%r3,.Lmemset_xc
	ex	%r4,0(%r3)
	br	%r14
.Lmemset_fill:
	stc	%r3,0(%r2)
	cghi	%r4,1
	lgr	%r1,%r2
	ber	%r14
	aghi	%r4,-2
	srlg	%r3,%r4,8
	ltgr	%r3,%r3
	jz	.Lmemset_fill_rest
.Lmemset_fill_loop:
	mvc	1(256,%r1),0(%r1)
	la	%r1,256(%r1)
	brctg	%r3,.Lmemset_fill_loop
.Lmemset_fill_rest:
	larl	%r3,.Lmemset_mvc
	ex	%r4,0(%r3)
	br	%r14
.Lmemset_xc:
	xc	0(1,%r1),0(%r1)
.Lmemset_mvc:
	mvc	1(1,%r1),0(%r1)
EXPORT_SYMBOL(memset)

/*
 * memcpy implementation
 *
 * void *memcpy(void *dest, const void *src, size_t n)
 */
ENTRY(memcpy)
	ltgr	%r4,%r4
	bzr	%r14
	aghi	%r4,-1
	srlg	%r5,%r4,8
	ltgr	%r5,%r5
	lgr	%r1,%r2
	jnz	.Lmemcpy_loop
.Lmemcpy_rest:
	larl	%r5,.Lmemcpy_mvc
	ex	%r4,0(%r5)
	br	%r14
.Lmemcpy_loop:
	mvc	0(256,%r1),0(%r3)
	la	%r1,256(%r1)
	la	%r3,256(%r3)
	brctg	%r5,.Lmemcpy_loop
	j	.Lmemcpy_rest
.Lmemcpy_mvc:
	mvc	0(1,%r1),0(%r3)
EXPORT_SYMBOL(memcpy)