2.9
[glibc/nacl-glibc.git] / sysdeps / s390 / bits / string.h
blob49103b9438a8b34dc7541e54dfded7a1cb1ba302
1 /* Optimized, inlined string functions. S/390 version.
2 Copyright (C) 2000, 2001, 2007 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, write to the Free
18 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 USA. */
21 #ifndef _STRING_H
22 # error "Never use <bits/string.h> directly; include <string.h> instead."
23 #endif
25 /* The s390 processors can access unaligned multi-byte variables. */
26 #define _STRING_ARCH_unaligned 1
28 /* We only provide optimizations if the user selects them and if
29 GNU CC is used. */
30 #if !defined __NO_STRING_INLINES && defined __USE_STRING_INLINES \
31 && defined __GNUC__ && __GNUC__ >= 2
33 #ifndef __STRING_INLINE
34 # ifndef __extern_inline
35 # define __STRING_INLINE inline
36 # else
37 # define __STRING_INLINE __extern_inline
38 # endif
39 #endif
41 #define _HAVE_STRING_ARCH_strlen 1
42 #ifndef _FORCE_INLINES
43 #define strlen(str) __strlen_g ((str))
45 __STRING_INLINE size_t __strlen_g (__const char *) __asm__ ("strlen");
47 __STRING_INLINE size_t
48 __strlen_g (__const char *__str)
50 char *__ptr, *__tmp;
52 __ptr = (char *) 0;
53 __tmp = (char *) __str;
54 __asm__ __volatile__ (" la 0,0\n"
55 "0: srst %0,%1\n"
56 " jo 0b\n"
57 : "+&a" (__ptr), "+&a" (__tmp) :
58 : "cc", "memory", "0" );
59 return (size_t) (__ptr - __str);
61 #endif
63 /* Copy SRC to DEST. */
64 #define _HAVE_STRING_ARCH_strcpy 1
65 #ifndef _FORCE_INLINES
66 #define strcpy(dest, src) __strcpy_g ((dest), (src))
68 __STRING_INLINE char *__strcpy_g (char *, __const char *) __asm ("strcpy");
70 __STRING_INLINE char *
71 __strcpy_g (char *__dest, __const char *__src)
73 char *tmp = __dest;
75 __asm__ __volatile__ (" la 0,0\n"
76 "0: mvst %0,%1\n"
77 " jo 0b"
78 : "+&a" (__dest), "+&a" (__src) :
79 : "cc", "memory", "0" );
80 return tmp;
82 #endif
84 #define _HAVE_STRING_ARCH_strncpy 1
85 #ifndef _FORCE_INLINES
86 #define strncpy(dest, src, n) __strncpy_g ((dest), (src), (n))
88 __STRING_INLINE char *__strncpy_g (char *, __const char *, size_t)
89 __asm__ ("strncpy");
91 __STRING_INLINE char *
92 __strncpy_g (char *__dest, __const char *__src, size_t __n)
94 char *__ret = __dest;
95 char *__ptr;
96 size_t __diff;
98 if (__n > 0) {
99 __diff = (size_t) (__dest - __src);
100 __ptr = (char *) __src;
101 __asm__ __volatile__ (" j 1f\n"
102 "0: la %0,1(%0)\n"
103 "1: icm 0,1,0(%0)\n"
104 " stc 0,0(%2,%0)\n"
105 " jz 3f\n"
106 #if defined(__s390x__)
107 " brctg %1,0b\n"
108 #else
109 " brct %1,0b\n"
110 #endif
111 " j 4f\n"
112 "2: la %0,1(%0)\n"
113 " stc 0,0(%2,%0)\n"
114 #if defined(__s390x__)
115 "3: brctg %1,2b\n"
116 #else
117 "3: brct %1,2b\n"
118 #endif
119 "4:"
120 : "+&a" (__ptr), "+&a" (__n) : "a" (__diff)
121 : "cc", "memory", "0" );
123 return __ret;
125 #endif
127 /* Append SRC onto DEST. */
128 #define _HAVE_STRING_ARCH_strcat 1
129 #ifndef _FORCE_INLINES
130 #define strcat(dest, src) __strcat_g ((dest), (src))
132 __STRING_INLINE char *__strcat_g (char *, __const char *) __asm__ ("strcat");
134 __STRING_INLINE char *
135 __strcat_g (char *__dest, __const char *__src)
137 char *__ret = __dest;
138 char *__ptr, *__tmp;
140 /* Move __ptr to the end of __dest. */
141 __ptr = (char *) 0;
142 __tmp = __dest;
143 __asm__ __volatile__ (" la 0,0\n"
144 "0: srst %0,%1\n"
145 " jo 0b\n"
146 : "+&a" (__ptr), "+&a" (__tmp) :
147 : "cc", "0" );
149 /* Now do the copy. */
150 __asm__ __volatile__ (" la 0,0\n"
151 "0: mvst %0,%1\n"
152 " jo 0b"
153 : "+&a" (__ptr), "+&a" (__src) :
154 : "cc", "memory", "0" );
155 return __ret;
157 #endif
159 /* Append no more than N characters from SRC onto DEST. */
160 #define _HAVE_STRING_ARCH_strncat 1
161 #ifndef _FORCE_INLINES
162 #define strncat(dest, src, n) __strncat_g ((dest), (src), (n))
164 __STRING_INLINE char *__strncat_g (char *, __const char *, size_t)
165 __asm__ ("strncat");
167 __STRING_INLINE char *
168 __strncat_g (char *__dest, __const char *__src, size_t __n)
170 char *__ret = __dest;
171 char *__ptr, *__tmp;
172 size_t __diff;
174 if (__n > 0) {
175 /* Move __ptr to the end of __dest. */
176 __ptr = (char *) 0;
177 __tmp = __dest;
178 __asm__ __volatile__ (" la 0,0\n"
179 "0: srst %0,%1\n"
180 " jo 0b\n"
181 : "+&a" (__ptr), "+&a" (__tmp) :
182 : "cc", "memory", "0" );
184 __diff = (size_t) (__ptr - __src);
185 __tmp = (char *) __src;
186 __asm__ __volatile__ (" j 1f\n"
187 "0: la %0,1(%0)\n"
188 "1: icm 0,1,0(%0)\n"
189 " stc 0,0(%2,%0)\n"
190 " jz 2f\n"
191 #if defined(__s390x__)
192 " brctg %1,0b\n"
193 #else
194 " brct %1,0b\n"
195 #endif
196 " slr 0,0\n"
197 " stc 0,1(%2,%0)\n"
198 "2:"
199 : "+&a" (__tmp), "+&a" (__n) : "a" (__diff)
200 : "cc", "memory", "0" );
203 return __ret;
205 #endif
207 /* Search N bytes of S for C. */
208 #define _HAVE_STRING_ARCH_memchr 1
209 #ifndef _FORCE_INLINES
210 __STRING_INLINE void *
211 memchr (__const void *__str, int __c, size_t __n)
213 char *__ptr, *__tmp;
215 __tmp = (char *) __str;
216 __ptr = (char *) __tmp + __n;
217 __asm__ __volatile__ (" lhi 0,0xff\n"
218 " nr 0,%2\n"
219 "0: srst %0,%1\n"
220 " jo 0b\n"
221 " brc 13,1f\n"
222 " la %0,0\n"
223 "1:"
224 : "+&a" (__ptr), "+&a" (__tmp) : "d" (__c)
225 : "cc", "memory", "0" );
226 return __ptr;
228 #endif
230 /* Search N bytes of S for C. */
231 #define _HAVE_STRING_ARCH_memchr 1
232 #ifndef _FORCE_INLINES
233 __STRING_INLINE int
234 strcmp (__const char *__s1, __const char *__s2)
236 char *__p1, *__p2;
237 int __ret;
239 __p1 = (char *) __s1;
240 __p2 = (char *) __s2;
241 __asm__ __volatile__ (" slr 0,0\n"
242 "0: clst %1,%2\n"
243 " jo 0b\n"
244 " ipm %0\n"
245 " srl %0,28"
246 : "=d" (__ret), "+&a" (__p1), "+&a" (__p2) :
247 : "cc", "memory", "0" );
248 __ret = (__ret == 0) ? 0 : (__ret == 1) ? -1 : 1;
249 return __ret;
251 #endif
253 #endif /* Use string inlines && GNU CC. */