]>
Commit | Line | Data |
---|---|---|
0a51f0ac | 1 | /* Optimized, inlined string functions. S/390 version. |
bfff8b1b | 2 | Copyright (C) 2000-2017 Free Software Foundation, Inc. |
0a51f0ac UD |
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 | |
41bdb6e2 AJ |
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. | |
0a51f0ac UD |
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 | |
41bdb6e2 AJ |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
14 | Lesser General Public License for more details. | |
0a51f0ac | 15 | |
41bdb6e2 | 16 | You should have received a copy of the GNU Lesser General Public |
59ba27a6 PE |
17 | License along with the GNU C Library; if not, see |
18 | <http://www.gnu.org/licenses/>. */ | |
0a51f0ac UD |
19 | |
20 | #ifndef _STRING_H | |
21 | # error "Never use <bits/string.h> directly; include <string.h> instead." | |
22 | #endif | |
23 | ||
16396c41 L |
24 | /* Use the unaligned string inline ABI. */ |
25 | #define _STRING_INLINE_unaligned 1 | |
0a51f0ac UD |
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 | |
de1c3ebb | 33 | # ifndef __extern_inline |
0a51f0ac UD |
34 | # define __STRING_INLINE inline |
35 | # else | |
b037a293 | 36 | # define __STRING_INLINE __extern_inline |
0a51f0ac UD |
37 | # endif |
38 | #endif | |
39 | ||
40 | #define _HAVE_STRING_ARCH_strlen 1 | |
41 | #ifndef _FORCE_INLINES | |
37143323 UD |
42 | #define strlen(str) __strlen_g ((str)) |
43 | ||
a784e502 | 44 | __STRING_INLINE size_t __strlen_g (const char *) __asm__ ("strlen"); |
a78814a9 | 45 | |
0a51f0ac | 46 | __STRING_INLINE size_t |
a784e502 | 47 | __strlen_g (const char *__str) |
0a51f0ac UD |
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" | |
a784e502 | 56 | : "+&a" (__ptr), "+&a" (__tmp) : |
1bc97733 | 57 | : "cc", "memory", "0" ); |
0a51f0ac UD |
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 | |
37143323 UD |
65 | #define strcpy(dest, src) __strcpy_g ((dest), (src)) |
66 | ||
31cf3942 | 67 | __STRING_INLINE char *__strcpy_g (char *, const char *) __asm__ ("strcpy"); |
a78814a9 | 68 | |
0a51f0ac | 69 | __STRING_INLINE char * |
a784e502 | 70 | __strcpy_g (char *__dest, const char *__src) |
0a51f0ac UD |
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 | |
37143323 UD |
85 | #define strncpy(dest, src, n) __strncpy_g ((dest), (src), (n)) |
86 | ||
a784e502 | 87 | __STRING_INLINE char *__strncpy_g (char *, const char *, size_t) |
a78814a9 UD |
88 | __asm__ ("strncpy"); |
89 | ||
0a51f0ac | 90 | __STRING_INLINE char * |
a784e502 | 91 | __strncpy_g (char *__dest, const char *__src, size_t __n) |
0a51f0ac UD |
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" | |
a784e502 UD |
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" | |
0a51f0ac | 105 | #if defined(__s390x__) |
a784e502 | 106 | " brctg %1,0b\n" |
0a51f0ac | 107 | #else |
a784e502 | 108 | " brct %1,0b\n" |
0a51f0ac | 109 | #endif |
a784e502 UD |
110 | " j 4f\n" |
111 | "2: la %0,1(%0)\n" | |
112 | " stc 0,0(%2,%0)\n" | |
0a51f0ac | 113 | #if defined(__s390x__) |
a784e502 | 114 | "3: brctg %1,2b\n" |
0a51f0ac | 115 | #else |
a784e502 | 116 | "3: brct %1,2b\n" |
0a51f0ac | 117 | #endif |
a784e502 UD |
118 | "4:" |
119 | : "+&a" (__ptr), "+&a" (__n) : "a" (__diff) | |
120 | : "cc", "memory", "0" ); | |
0a51f0ac UD |
121 | } |
122 | return __ret; | |
123 | } | |
124 | #endif | |
125 | ||
126 | /* Append SRC onto DEST. */ | |
127 | #define _HAVE_STRING_ARCH_strcat 1 | |
128 | #ifndef _FORCE_INLINES | |
37143323 UD |
129 | #define strcat(dest, src) __strcat_g ((dest), (src)) |
130 | ||
a784e502 | 131 | __STRING_INLINE char *__strcat_g (char *, const char *) __asm__ ("strcat"); |
a78814a9 | 132 | |
0a51f0ac | 133 | __STRING_INLINE char * |
a784e502 | 134 | __strcat_g (char *__dest, const char *__src) |
0a51f0ac UD |
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) : | |
1bc97733 | 153 | : "cc", "memory", "0" ); |
0a51f0ac UD |
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 | |
37143323 UD |
161 | #define strncat(dest, src, n) __strncat_g ((dest), (src), (n)) |
162 | ||
a784e502 | 163 | __STRING_INLINE char *__strncat_g (char *, const char *, size_t) |
a78814a9 UD |
164 | __asm__ ("strncat"); |
165 | ||
0a51f0ac | 166 | __STRING_INLINE char * |
a784e502 | 167 | __strncat_g (char *__dest, const char *__src, size_t __n) |
0a51f0ac UD |
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) : | |
1bc97733 | 181 | : "cc", "memory", "0" ); |
0a51f0ac UD |
182 | |
183 | __diff = (size_t) (__ptr - __src); | |
184 | __tmp = (char *) __src; | |
185 | __asm__ __volatile__ (" j 1f\n" | |
a784e502 UD |
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" | |
0a51f0ac | 190 | #if defined(__s390x__) |
a784e502 | 191 | " brctg %1,0b\n" |
0a51f0ac | 192 | #else |
a784e502 | 193 | " brct %1,0b\n" |
0a51f0ac UD |
194 | #endif |
195 | " slr 0,0\n" | |
a784e502 | 196 | " stc 0,1(%2,%0)\n" |
0a51f0ac | 197 | "2:" |
a784e502 UD |
198 | : "+&a" (__tmp), "+&a" (__n) : "a" (__diff) |
199 | : "cc", "memory", "0" ); | |
0a51f0ac UD |
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 * | |
a784e502 | 210 | memchr (const void *__str, int __c, size_t __n) |
0a51f0ac UD |
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" | |
a784e502 UD |
220 | " brc 13,1f\n" |
221 | " la %0,0\n" | |
222 | "1:" | |
0a51f0ac | 223 | : "+&a" (__ptr), "+&a" (__tmp) : "d" (__c) |
1bc97733 | 224 | : "cc", "memory", "0" ); |
0a51f0ac UD |
225 | return __ptr; |
226 | } | |
227 | #endif | |
228 | ||
63724a6d SL |
229 | /* Compare S1 and S2. */ |
230 | #define _HAVE_STRING_ARCH_strcmp 1 | |
0a51f0ac UD |
231 | #ifndef _FORCE_INLINES |
232 | __STRING_INLINE int | |
a784e502 | 233 | strcmp (const char *__s1, const char *__s2) |
0a51f0ac UD |
234 | { |
235 | char *__p1, *__p2; | |
236 | int __ret; | |
237 | ||
238 | __p1 = (char *) __s1; | |
239 | __p2 = (char *) __s2; | |
240 | __asm__ __volatile__ (" slr 0,0\n" | |
a784e502 | 241 | "0: clst %1,%2\n" |
0a51f0ac UD |
242 | " jo 0b\n" |
243 | " ipm %0\n" | |
244 | " srl %0,28" | |
a784e502 | 245 | : "=d" (__ret), "+&a" (__p1), "+&a" (__p2) : |
1bc97733 | 246 | : "cc", "memory", "0" ); |
0a51f0ac UD |
247 | __ret = (__ret == 0) ? 0 : (__ret == 1) ? -1 : 1; |
248 | return __ret; | |
249 | } | |
250 | #endif | |
251 | ||
252 | #endif /* Use string inlines && GNU CC. */ |