S390: Optimize strcmp and wcscmp.
[glibc.git] / sysdeps / s390 / bits / string.h
blobb48d51100a30c0ebdd6d3aa375b4492c06d09e37
1 /* Optimized, inlined string functions. S/390 version.
2 Copyright (C) 2000-2015 Free Software Foundation, Inc.
3 Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com).
4 This file is part of the GNU C Library.
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.
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.
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/>. */
20 #ifndef _STRING_H
21 # error "Never use <bits/string.h> directly; include <string.h> instead."
22 #endif
24 /* The s390 processors can access unaligned multi-byte variables. */
25 #define _STRING_ARCH_unaligned 1
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
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
40 #define _HAVE_STRING_ARCH_strlen 1
41 #ifndef _FORCE_INLINES
42 #define strlen(str) __strlen_g ((str))
44 __STRING_INLINE size_t __strlen_g (const char *) __asm__ ("strlen");
46 __STRING_INLINE size_t
47 __strlen_g (const char *__str)
49 char *__ptr, *__tmp;
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);
60 #endif
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))
67 __STRING_INLINE char *__strcpy_g (char *, const char *) __asm ("strcpy");
69 __STRING_INLINE char *
70 __strcpy_g (char *__dest, const char *__src)
72 char *tmp = __dest;
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;
81 #endif
83 #define _HAVE_STRING_ARCH_strncpy 1
84 #ifndef _FORCE_INLINES
85 #define strncpy(dest, src, n) __strncpy_g ((dest), (src), (n))
87 __STRING_INLINE char *__strncpy_g (char *, const char *, size_t)
88 __asm__ ("strncpy");
90 __STRING_INLINE char *
91 __strncpy_g (char *__dest, const char *__src, size_t __n)
93 char *__ret = __dest;
94 char *__ptr;
95 size_t __diff;
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" );
122 return __ret;
124 #endif
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))
131 __STRING_INLINE char *__strcat_g (char *, const char *) __asm__ ("strcat");
133 __STRING_INLINE char *
134 __strcat_g (char *__dest, const char *__src)
136 char *__ret = __dest;
137 char *__ptr, *__tmp;
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" );
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;
156 #endif
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))
163 __STRING_INLINE char *__strncat_g (char *, const char *, size_t)
164 __asm__ ("strncat");
166 __STRING_INLINE char *
167 __strncat_g (char *__dest, const char *__src, size_t __n)
169 char *__ret = __dest;
170 char *__ptr, *__tmp;
171 size_t __diff;
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" );
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" );
202 return __ret;
204 #endif
206 /* Search N bytes of S for C. */
207 #define _HAVE_STRING_ARCH_memchr 1
208 #ifndef _FORCE_INLINES
209 __STRING_INLINE void *
210 memchr (const void *__str, int __c, size_t __n)
212 char *__ptr, *__tmp;
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;
227 #endif
229 /* Compare S1 and S2. */
230 #define _HAVE_STRING_ARCH_strcmp 1
231 #ifndef _FORCE_INLINES
232 __STRING_INLINE int
233 strcmp (const char *__s1, const char *__s2)
235 char *__p1, *__p2;
236 int __ret;
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;
250 #endif
252 #endif /* Use string inlines && GNU CC. */