blob: 39e0b7fe7c7a100c7f4e2a3c13f815951815e854 [file] [log] [blame]
xf.libfc6e712025-02-07 01:54:34 -08001/* Optimized, inlined string functions. S/390 version.
2 Copyright (C) 2000-2016 Free Software Foundation, Inc.
3 Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com).
4 This file is part of the GNU C Library.
5
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
10
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, see
18 <http://www.gnu.org/licenses/>. */
19
20#ifndef _STRING_H
21# error "Never use <bits/string.h> directly; include <string.h> instead."
22#endif
23
24/* Use the unaligned string inline ABI. */
25#define _STRING_INLINE_unaligned 1
26
27/* We only provide optimizations if the user selects them and if
28 GNU CC is used. */
29#if !defined __NO_STRING_INLINES && defined __USE_STRING_INLINES \
30 && defined __GNUC__ && __GNUC__ >= 2
31
32#ifndef __STRING_INLINE
33# ifndef __extern_inline
34# define __STRING_INLINE inline
35# else
36# define __STRING_INLINE __extern_inline
37# endif
38#endif
39
40#define _HAVE_STRING_ARCH_strlen 1
41#ifndef _FORCE_INLINES
42#define strlen(str) __strlen_g ((str))
43
44__STRING_INLINE size_t __strlen_g (const char *) __asm__ ("strlen");
45
46__STRING_INLINE size_t
47__strlen_g (const char *__str)
48{
49 char *__ptr, *__tmp;
50
51 __ptr = (char *) 0;
52 __tmp = (char *) __str;
53 __asm__ __volatile__ (" la 0,0\n"
54 "0: srst %0,%1\n"
55 " jo 0b\n"
56 : "+&a" (__ptr), "+&a" (__tmp) :
57 : "cc", "memory", "0" );
58 return (size_t) (__ptr - __str);
59}
60#endif
61
62/* Copy SRC to DEST. */
63#define _HAVE_STRING_ARCH_strcpy 1
64#ifndef _FORCE_INLINES
65#define strcpy(dest, src) __strcpy_g ((dest), (src))
66
67__STRING_INLINE char *__strcpy_g (char *, const char *) __asm__ ("strcpy");
68
69__STRING_INLINE char *
70__strcpy_g (char *__dest, const char *__src)
71{
72 char *tmp = __dest;
73
74 __asm__ __volatile__ (" la 0,0\n"
75 "0: mvst %0,%1\n"
76 " jo 0b"
77 : "+&a" (__dest), "+&a" (__src) :
78 : "cc", "memory", "0" );
79 return tmp;
80}
81#endif
82
83#define _HAVE_STRING_ARCH_strncpy 1
84#ifndef _FORCE_INLINES
85#define strncpy(dest, src, n) __strncpy_g ((dest), (src), (n))
86
87__STRING_INLINE char *__strncpy_g (char *, const char *, size_t)
88 __asm__ ("strncpy");
89
90__STRING_INLINE char *
91__strncpy_g (char *__dest, const char *__src, size_t __n)
92{
93 char *__ret = __dest;
94 char *__ptr;
95 size_t __diff;
96
97 if (__n > 0) {
98 __diff = (size_t) (__dest - __src);
99 __ptr = (char *) __src;
100 __asm__ __volatile__ (" j 1f\n"
101 "0: la %0,1(%0)\n"
102 "1: icm 0,1,0(%0)\n"
103 " stc 0,0(%2,%0)\n"
104 " jz 3f\n"
105#if defined(__s390x__)
106 " brctg %1,0b\n"
107#else
108 " brct %1,0b\n"
109#endif
110 " j 4f\n"
111 "2: la %0,1(%0)\n"
112 " stc 0,0(%2,%0)\n"
113#if defined(__s390x__)
114 "3: brctg %1,2b\n"
115#else
116 "3: brct %1,2b\n"
117#endif
118 "4:"
119 : "+&a" (__ptr), "+&a" (__n) : "a" (__diff)
120 : "cc", "memory", "0" );
121 }
122 return __ret;
123}
124#endif
125
126/* Append SRC onto DEST. */
127#define _HAVE_STRING_ARCH_strcat 1
128#ifndef _FORCE_INLINES
129#define strcat(dest, src) __strcat_g ((dest), (src))
130
131__STRING_INLINE char *__strcat_g (char *, const char *) __asm__ ("strcat");
132
133__STRING_INLINE char *
134__strcat_g (char *__dest, const char *__src)
135{
136 char *__ret = __dest;
137 char *__ptr, *__tmp;
138
139 /* Move __ptr to the end of __dest. */
140 __ptr = (char *) 0;
141 __tmp = __dest;
142 __asm__ __volatile__ (" la 0,0\n"
143 "0: srst %0,%1\n"
144 " jo 0b\n"
145 : "+&a" (__ptr), "+&a" (__tmp) :
146 : "cc", "0" );
147
148 /* Now do the copy. */
149 __asm__ __volatile__ (" la 0,0\n"
150 "0: mvst %0,%1\n"
151 " jo 0b"
152 : "+&a" (__ptr), "+&a" (__src) :
153 : "cc", "memory", "0" );
154 return __ret;
155}
156#endif
157
158/* Append no more than N characters from SRC onto DEST. */
159#define _HAVE_STRING_ARCH_strncat 1
160#ifndef _FORCE_INLINES
161#define strncat(dest, src, n) __strncat_g ((dest), (src), (n))
162
163__STRING_INLINE char *__strncat_g (char *, const char *, size_t)
164 __asm__ ("strncat");
165
166__STRING_INLINE char *
167__strncat_g (char *__dest, const char *__src, size_t __n)
168{
169 char *__ret = __dest;
170 char *__ptr, *__tmp;
171 size_t __diff;
172
173 if (__n > 0) {
174 /* Move __ptr to the end of __dest. */
175 __ptr = (char *) 0;
176 __tmp = __dest;
177 __asm__ __volatile__ (" la 0,0\n"
178 "0: srst %0,%1\n"
179 " jo 0b\n"
180 : "+&a" (__ptr), "+&a" (__tmp) :
181 : "cc", "memory", "0" );
182
183 __diff = (size_t) (__ptr - __src);
184 __tmp = (char *) __src;
185 __asm__ __volatile__ (" j 1f\n"
186 "0: la %0,1(%0)\n"
187 "1: icm 0,1,0(%0)\n"
188 " stc 0,0(%2,%0)\n"
189 " jz 2f\n"
190#if defined(__s390x__)
191 " brctg %1,0b\n"
192#else
193 " brct %1,0b\n"
194#endif
195 " slr 0,0\n"
196 " stc 0,1(%2,%0)\n"
197 "2:"
198 : "+&a" (__tmp), "+&a" (__n) : "a" (__diff)
199 : "cc", "memory", "0" );
200
201 }
202 return __ret;
203}
204#endif
205
206/* Search N bytes of S for C. */
207#define _HAVE_STRING_ARCH_memchr 1
208#ifndef _FORCE_INLINES
209__STRING_INLINE void *
210memchr (const void *__str, int __c, size_t __n)
211{
212 char *__ptr, *__tmp;
213
214 __tmp = (char *) __str;
215 __ptr = (char *) __tmp + __n;
216 __asm__ __volatile__ (" lhi 0,0xff\n"
217 " nr 0,%2\n"
218 "0: srst %0,%1\n"
219 " jo 0b\n"
220 " brc 13,1f\n"
221 " la %0,0\n"
222 "1:"
223 : "+&a" (__ptr), "+&a" (__tmp) : "d" (__c)
224 : "cc", "memory", "0" );
225 return __ptr;
226}
227#endif
228
229/* Compare S1 and S2. */
230#define _HAVE_STRING_ARCH_strcmp 1
231#ifndef _FORCE_INLINES
232__STRING_INLINE int
233strcmp (const char *__s1, const char *__s2)
234{
235 char *__p1, *__p2;
236 int __ret;
237
238 __p1 = (char *) __s1;
239 __p2 = (char *) __s2;
240 __asm__ __volatile__ (" slr 0,0\n"
241 "0: clst %1,%2\n"
242 " jo 0b\n"
243 " ipm %0\n"
244 " srl %0,28"
245 : "=d" (__ret), "+&a" (__p1), "+&a" (__p2) :
246 : "cc", "memory", "0" );
247 __ret = (__ret == 0) ? 0 : (__ret == 1) ? -1 : 1;
248 return __ret;
249}
250#endif
251
252#endif /* Use string inlines && GNU CC. */