1/* Set a block of memory to some byte value.  31/64 bit S/390 version.
2   Copyright (C) 2001-2021 Free Software Foundation, Inc.
3   This file is part of the GNU C Library.
4
5   The GNU C Library is free software; you can redistribute it and/or
6   modify it under the terms of the GNU Lesser General Public
7   License as published by the Free Software Foundation; either
8   version 2.1 of the License, or (at your option) any later version.
9
10   The GNU C Library is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13   Lesser General Public License for more details.
14
15   You should have received a copy of the GNU Lesser General Public
16   License along with the GNU C Library; if not, see
17   <https://www.gnu.org/licenses/>.  */
18
19
20#include <sysdep.h>
21#include "asm-syntax.h"
22#include <ifunc-memset.h>
23
24/* INPUT PARAMETERS - MEMSET
25     %r2 = address of memory area
26     %r3 = byte to fill memory with
27     %r4 = number of bytes to fill.
28
29   INPUT PARAMETERS - BZERO
30     %r2 = address of memory area
31     %r3 = number of bytes to fill.  */
32
33       .text
34
35#if HAVE_MEMSET_Z900_G5
36# if defined __s390x__
37#  define LTGR	ltgr
38#  define CGHI	cghi
39#  define LGR	lgr
40#  define AGHI	aghi
41#  define BRCTG	brctg
42# else
43#  define LTGR	ltr
44#  define CGHI	chi
45#  define LGR	lr
46#  define AGHI	ahi
47#  define BRCTG	brct
48# endif /* ! defined __s390x__  */
49
50ENTRY(BZERO_Z900_G5)
51	LGR	%r4,%r3
52	xr	%r3,%r3
53	j	.L_Z900_G5_start
54END(BZERO_Z900_G5)
55
56ENTRY(MEMSET_Z900_G5)
57.L_Z900_G5_start:
58#if defined __s390x__
59	.machine "z900"
60#else
61	.machine "g5"
62#endif /* ! defined __s390x__  */
63	LTGR    %r4,%r4
64	je      .L_Z900_G5_4
65	stc     %r3,0(%r2)
66	CGHI    %r4,1
67	LGR     %r1,%r2
68	je      .L_Z900_G5_4
69	AGHI    %r4,-2
70#if defined __s390x__
71	larl    %r5,.L_Z900_G5_18
72	srlg    %r3,%r4,8
73# define Z900_G5_EX_D 0
74#else
75	basr    %r5,0
76.L_Z900_G5_19:
77# define Z900_G5_EX_D .L_Z900_G5_18-.L_Z900_G5_19
78	lr      %r3,%r4
79	srl     %r3,8
80#endif /* ! defined __s390x__  */
81	LTGR    %r3,%r3
82	jne     .L_Z900_G5_14
83.L_Z900_G5_3:
84	ex      %r4,Z900_G5_EX_D(%r5)
85.L_Z900_G5_4:
86	br      %r14
87.L_Z900_G5_14:
88	mvc     1(256,%r1),0(%r1)
89	la      %r1,256(%r1)
90	BRCTG   %r3,.L_Z900_G5_14
91	j       .L_Z900_G5_3
92.L_Z900_G5_18:
93	mvc     1(1,%r1),0(%r1)
94END(MEMSET_Z900_G5)
95# undef LTGR
96# undef CGHI
97# undef LGR
98# undef AGHI
99# undef BRCTG
100#endif /*  HAVE_MEMSET_Z900_G5  */
101
102#if HAVE_MEMSET_Z10
103ENTRY(BZERO_Z10)
104	.machine "z10"
105	.machinemode "zarch_nohighgprs"
106	lgr	%r4,%r3
107	xr	%r3,%r3
108	j	.L_Z10_start
109END(BZERO_Z10)
110
111ENTRY(MEMSET_Z10)
112.L_Z10_start:
113	.machine "z10"
114	.machinemode "zarch_nohighgprs"
115# if !defined __s390x__
116	llgfr	%r4,%r4
117# endif /* !defined __s390x__  */
118	cgije   %r4,0,.L_Z10_4
119	stc     %r3,0(%r2)
120	lgr     %r1,%r2
121	cgije   %r4,1,.L_Z10_4
122	aghi    %r4,-2
123	srlg    %r5,%r4,8
124	cgijlh  %r5,0,.L_Z10_15
125.L_Z10_3:
126	exrl    %r4,.L_Z10_18
127.L_Z10_4:
128	br      %r14
129.L_Z10_15:
130	cgfi	%r5,163840          # Switch to mvcle for >40MB
131	jh	__memset_mvcle
132.L_Z10_14:
133	pfd     2,1024(%r1)
134	mvc     1(256,%r1),0(%r1)
135	la      %r1,256(%r1)
136	brctg   %r5,.L_Z10_14
137	j       .L_Z10_3
138.L_Z10_18:
139	mvc     1(1,%r1),0(%r1)
140END(MEMSET_Z10)
141#endif /* HAVE_MEMSET_Z10  */
142
143#if HAVE_MEMSET_Z196
144ENTRY(BZERO_Z196)
145	.machine "z196"
146	.machinemode "zarch_nohighgprs"
147	lgr	%r4,%r3
148	xr	%r3,%r3
149	j	.L_Z196_start
150END(BZERO_Z196)
151
152ENTRY(MEMSET_Z196)
153.L_Z196_start:
154	.machine "z196"
155	.machinemode "zarch_nohighgprs"
156# if !defined __s390x__
157	llgfr	%r4,%r4
158# endif /* !defined __s390x__  */
159	clgfi	%r4,1
160	jl	.L_Z196_4	    # n == 0
161	stc     %r3,0(%r2)
162	je      .L_Z196_4	    # n == 1
163	aghi	%r4,-2
164	lgr     %r1,%r2
165	risbg	%r5,%r4,8,128+63,56 # r5 = n / 256
166	jne     .L_Z196_1	    # Jump away if r5 != 0
167.L_Z196_3:
168	exrl    %r4,.L_Z196_17
169.L_Z196_4:
170	br      %r14
171.L_Z196_1:
172	cgfi	%r5,1048576
173	jh	__memset_mvcle	    # Switch to mvcle for >256MB
174.L_Z196_2:
175	pfd     2,1024(%r1)
176	mvc     1(255,%r1),0(%r1)
177	aghi    %r5,-1
178	la      %r1,256(%r1)
179	stc     %r3,0(%r1)
180	jne     .L_Z196_2
181	j       .L_Z196_3
182.L_Z196_17:
183	mvc     1(1,%r1),0(%r1)
184END(MEMSET_Z196)
185#endif /* HAVE_MEMSET_Z196  */
186
187#if HAVE_MEMSET_MVCLE
188ENTRY(__memset_mvcle)
189	aghi	%r4,2               # take back the change done by the caller
190	lgr	%r0,%r2		    # save source address
191	lgr	%r1,%r3		    # move pad byte to R1
192	lgr	%r3,%r4             # move length to r3
193	sgr	%r4,%r4		    # no source for MVCLE, only a pad byte
194	sgr	%r5,%r5
195.L0:	mvcle	%r2,%r4,0(%r1)	    # thats it, MVCLE is your friend
196	jo	.L0
197	lgr	%r2,%r0		    # return value is source address
198.L1:
199	br	%r14
200END(__memset_mvcle)
201#endif /* HAVE_MEMSET_MVCLE  */
202
203#if ! HAVE_MEMSET_IFUNC
204/* If we don't use ifunc, define an alias for memset here.
205   Otherwise see sysdeps/s390/memset.c.  */
206strong_alias (MEMSET_DEFAULT, memset)
207/* Same for bzero.  If ifunc is used, see
208   sysdeps/s390/bzero.c.  */
209strong_alias (BZERO_DEFAULT, __bzero)
210weak_alias (__bzero, bzero)
211#endif
212
213#if defined SHARED && IS_IN (libc)
214/* Defines the internal symbol.
215   Compare to libc_hidden_builtin_def (memset) in string/memset.c.  */
216strong_alias (MEMSET_DEFAULT, __GI_memset)
217#endif
218