diff options
Diffstat (limited to 'arch/s390/lib/string.c')
| -rw-r--r-- | arch/s390/lib/string.c | 229 |
1 files changed, 93 insertions, 136 deletions
diff --git a/arch/s390/lib/string.c b/arch/s390/lib/string.c index a10e11f7a5f7..757f58960198 100644 --- a/arch/s390/lib/string.c +++ b/arch/s390/lib/string.c @@ -8,33 +8,44 @@ */ #define IN_ARCH_STRING_C 1 +#ifndef __NO_FORTIFY +# define __NO_FORTIFY +#endif #include <linux/types.h> #include <linux/string.h> #include <linux/export.h> +#include <asm/asm.h> /* * Helper functions to find the end of a string */ static inline char *__strend(const char *s) { - register unsigned long r0 asm("0") = 0; - - asm volatile ("0: srst %0,%1\n" - " jo 0b" - : "+d" (r0), "+a" (s) : : "cc", "memory"); - return (char *) r0; + unsigned long e = 0; + + asm volatile( + " lghi 0,0\n" + "0: srst %[e],%[s]\n" + " jo 0b" + : [e] "+&a" (e), [s] "+&a" (s) + : + : "cc", "memory", "0"); + return (char *)e; } static inline char *__strnend(const char *s, size_t n) { - register unsigned long r0 asm("0") = 0; const char *p = s + n; - asm volatile ("0: srst %0,%1\n" - " jo 0b" - : "+d" (p), "+a" (s) : "d" (r0) : "cc", "memory"); - return (char *) p; + asm volatile( + " lghi 0,0\n" + "0: srst %[p],%[s]\n" + " jo 0b" + : [p] "+&d" (p), [s] "+&a" (s) + : + : "cc", "memory", "0"); + return (char *)p; } /** @@ -43,11 +54,13 @@ static inline char *__strnend(const char *s, size_t n) * * returns the length of @s */ +#ifdef __HAVE_ARCH_STRLEN size_t strlen(const char *s) { return __strend(s) - s; } EXPORT_SYMBOL(strlen); +#endif /** * strnlen - Find the length of a length-limited string @@ -56,73 +69,13 @@ EXPORT_SYMBOL(strlen); * * returns the minimum of the length of @s and @n */ +#ifdef __HAVE_ARCH_STRNLEN size_t strnlen(const char *s, size_t n) { return __strnend(s, n) - s; } EXPORT_SYMBOL(strnlen); - -/** - * strcpy - Copy a %NUL terminated string - * @dest: Where to copy the string to - * @src: Where to copy the string from - * - * returns a pointer to @dest - */ -char *strcpy(char *dest, const char *src) -{ - register int r0 asm("0") = 0; - char *ret = dest; - - asm volatile ("0: mvst %0,%1\n" - " jo 0b" - : "+&a" (dest), "+&a" (src) : "d" (r0) - : "cc", "memory" ); - return ret; -} -EXPORT_SYMBOL(strcpy); - -/** - * strlcpy - Copy a %NUL terminated string into a sized buffer - * @dest: Where to copy the string to - * @src: Where to copy the string from - * @size: size of destination buffer - * - * Compatible with *BSD: the result is always a valid - * NUL-terminated string that fits in the buffer (unless, - * of course, the buffer size is zero). It does not pad - * out the result like strncpy() does. - */ -size_t strlcpy(char *dest, const char *src, size_t size) -{ - size_t ret = __strend(src) - src; - - if (size) { - size_t len = (ret >= size) ? size-1 : ret; - dest[len] = '\0'; - memcpy(dest, src, len); - } - return ret; -} -EXPORT_SYMBOL(strlcpy); - -/** - * strncpy - Copy a length-limited, %NUL-terminated string - * @dest: Where to copy the string to - * @src: Where to copy the string from - * @n: The maximum number of bytes to copy - * - * The result is not %NUL-terminated if the source exceeds - * @n bytes. - */ -char *strncpy(char *dest, const char *src, size_t n) -{ - size_t len = __strnend(src, n) - src; - memset(dest + len, 0, n - len); - memcpy(dest, src, len); - return dest; -} -EXPORT_SYMBOL(strncpy); +#endif /** * strcat - Append one %NUL-terminated string to another @@ -131,21 +84,25 @@ EXPORT_SYMBOL(strncpy); * * returns a pointer to @dest */ +#ifdef __HAVE_ARCH_STRCAT char *strcat(char *dest, const char *src) { - register int r0 asm("0") = 0; - unsigned long dummy; + unsigned long dummy = 0; char *ret = dest; - asm volatile ("0: srst %0,%1\n" - " jo 0b\n" - "1: mvst %0,%2\n" - " jo 1b" - : "=&a" (dummy), "+a" (dest), "+a" (src) - : "d" (r0), "0" (0UL) : "cc", "memory" ); + asm volatile( + " lghi 0,0\n" + "0: srst %[dummy],%[dest]\n" + " jo 0b\n" + "1: mvst %[dummy],%[src]\n" + " jo 1b" + : [dummy] "+&a" (dummy), [dest] "+&a" (dest), [src] "+&a" (src) + : + : "cc", "memory", "0"); return ret; } EXPORT_SYMBOL(strcat); +#endif /** * strlcat - Append a length-limited, %NUL-terminated string to another @@ -153,6 +110,7 @@ EXPORT_SYMBOL(strcat); * @src: The string to append to it * @n: The size of the destination buffer. */ +#ifdef __HAVE_ARCH_STRLCAT size_t strlcat(char *dest, const char *src, size_t n) { size_t dsize = __strend(dest) - dest; @@ -170,6 +128,7 @@ size_t strlcat(char *dest, const char *src, size_t n) return res; } EXPORT_SYMBOL(strlcat); +#endif /** * strncat - Append a length-limited, %NUL-terminated string to another @@ -178,10 +137,8 @@ EXPORT_SYMBOL(strlcat); * @n: The maximum numbers of bytes to copy * * returns a pointer to @dest - * - * Note that in contrast to strncpy, strncat ensures the result is - * terminated. */ +#ifdef __HAVE_ARCH_STRNCAT char *strncat(char *dest, const char *src, size_t n) { size_t len = __strnend(src, n) - src; @@ -192,6 +149,7 @@ char *strncat(char *dest, const char *src, size_t n) return dest; } EXPORT_SYMBOL(strncat); +#endif /** * strcmp - Compare two strings @@ -202,58 +160,43 @@ EXPORT_SYMBOL(strncat); * < 0 if @s1 is less than @s2 * > 0 if @s1 is greater than @s2 */ +#ifdef __HAVE_ARCH_STRCMP int strcmp(const char *s1, const char *s2) { - register int r0 asm("0") = 0; int ret = 0; - asm volatile ("0: clst %2,%3\n" - " jo 0b\n" - " je 1f\n" - " ic %0,0(%2)\n" - " ic %1,0(%3)\n" - " sr %0,%1\n" - "1:" - : "+d" (ret), "+d" (r0), "+a" (s1), "+a" (s2) - : : "cc", "memory"); + asm volatile( + " lghi 0,0\n" + "0: clst %[s1],%[s2]\n" + " jo 0b\n" + " je 1f\n" + " ic %[ret],0(%[s1])\n" + " ic 0,0(%[s2])\n" + " sr %[ret],0\n" + "1:" + : [ret] "+&d" (ret), [s1] "+&a" (s1), [s2] "+&a" (s2) + : + : "cc", "memory", "0"); return ret; } EXPORT_SYMBOL(strcmp); - -/** - * strrchr - Find the last occurrence of a character in a string - * @s: The string to be searched - * @c: The character to search for - */ -char *strrchr(const char *s, int c) -{ - size_t len = __strend(s) - s; - - if (len) - do { - if (s[len] == (char) c) - return (char *) s + len; - } while (--len > 0); - return NULL; -} -EXPORT_SYMBOL(strrchr); +#endif static inline int clcle(const char *s1, unsigned long l1, const char *s2, unsigned long l2) { - register unsigned long r2 asm("2") = (unsigned long) s1; - register unsigned long r3 asm("3") = (unsigned long) l1; - register unsigned long r4 asm("4") = (unsigned long) s2; - register unsigned long r5 asm("5") = (unsigned long) l2; + union register_pair r1 = { .even = (unsigned long)s1, .odd = l1, }; + union register_pair r3 = { .even = (unsigned long)s2, .odd = l2, }; int cc; - asm volatile ("0: clcle %1,%3,0\n" - " jo 0b\n" - " ipm %0\n" - " srl %0,28" - : "=&d" (cc), "+a" (r2), "+a" (r3), - "+a" (r4), "+a" (r5) : : "cc", "memory"); - return cc; + asm volatile( + "0: clcle %[r1],%[r3],0\n" + " jo 0b\n" + CC_IPM(cc) + : CC_OUT(cc, cc), [r1] "+d" (r1.pair), [r3] "+d" (r3.pair) + : + : CC_CLOBBER_LIST("memory")); + return CC_TRANSFORM(cc); } /** @@ -261,6 +204,7 @@ static inline int clcle(const char *s1, unsigned long l1, * @s1: The string to be searched * @s2: The string to search for */ +#ifdef __HAVE_ARCH_STRSTR char *strstr(const char *s1, const char *s2) { int l1, l2; @@ -280,6 +224,7 @@ char *strstr(const char *s1, const char *s2) return NULL; } EXPORT_SYMBOL(strstr); +#endif /** * memchr - Find a character in an area of memory. @@ -290,27 +235,33 @@ EXPORT_SYMBOL(strstr); * returns the address of the first occurrence of @c, or %NULL * if @c is not found */ +#ifdef __HAVE_ARCH_MEMCHR void *memchr(const void *s, int c, size_t n) { - register int r0 asm("0") = (char) c; const void *ret = s + n; - asm volatile ("0: srst %0,%1\n" - " jo 0b\n" - " jl 1f\n" - " la %0,0\n" - "1:" - : "+a" (ret), "+&a" (s) : "d" (r0) : "cc", "memory"); + asm volatile( + " lgr 0,%[c]\n" + "0: srst %[ret],%[s]\n" + " jo 0b\n" + " jl 1f\n" + " la %[ret],0\n" + "1:" + : [ret] "+&a" (ret), [s] "+&a" (s) + : [c] "d" (c) + : "cc", "memory", "0"); return (void *) ret; } EXPORT_SYMBOL(memchr); +#endif /** * memcmp - Compare two areas of memory * @s1: One area of memory * @s2: Another area of memory - * @count: The size of the area. + * @n: The size of the area. */ +#ifdef __HAVE_ARCH_MEMCMP int memcmp(const void *s1, const void *s2, size_t n) { int ret; @@ -321,6 +272,7 @@ int memcmp(const void *s1, const void *s2, size_t n) return ret; } EXPORT_SYMBOL(memcmp); +#endif /** * memscan - Find a character in an area of memory. @@ -331,14 +283,19 @@ EXPORT_SYMBOL(memcmp); * returns the address of the first occurrence of @c, or 1 byte past * the area if @c is not found */ +#ifdef __HAVE_ARCH_MEMSCAN void *memscan(void *s, int c, size_t n) { - register int r0 asm("0") = (char) c; const void *ret = s + n; - asm volatile ("0: srst %0,%1\n" - " jo 0b\n" - : "+a" (ret), "+&a" (s) : "d" (r0) : "cc", "memory"); - return (void *) ret; + asm volatile( + " lgr 0,%[c]\n" + "0: srst %[ret],%[s]\n" + " jo 0b" + : [ret] "+&a" (ret), [s] "+&a" (s) + : [c] "d" (c) + : "cc", "memory", "0"); + return (void *)ret; } EXPORT_SYMBOL(memscan); +#endif |
