Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  *    Optimized string functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  *  S390 version
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  *    Copyright IBM Corp. 2004
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #define IN_ARCH_STRING_C 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17)  * Helper functions to find the end of a string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) static inline char *__strend(const char *s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) 	register unsigned long r0 asm("0") = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) 	asm volatile ("0: srst  %0,%1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 		      "   jo    0b"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 		      : "+d" (r0), "+a" (s) :  : "cc", "memory");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 	return (char *) r0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) static inline char *__strnend(const char *s, size_t n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 	register unsigned long r0 asm("0") = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 	const char *p = s + n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 	asm volatile ("0: srst  %0,%1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 		      "   jo    0b"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 		      : "+d" (p), "+a" (s) : "d" (r0) : "cc", "memory");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 	return (char *) p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41)  * strlen - Find the length of a string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42)  * @s: The string to be sized
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44)  * returns the length of @s
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) #ifdef __HAVE_ARCH_STRLEN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) size_t strlen(const char *s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	return __strend(s) - s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) EXPORT_SYMBOL(strlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55)  * strnlen - Find the length of a length-limited string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56)  * @s: The string to be sized
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57)  * @n: The maximum number of bytes to search
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59)  * returns the minimum of the length of @s and @n
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) #ifdef __HAVE_ARCH_STRNLEN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) size_t strnlen(const char *s, size_t n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 	return __strnend(s, n) - s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) EXPORT_SYMBOL(strnlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70)  * strcpy - Copy a %NUL terminated string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71)  * @dest: Where to copy the string to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72)  * @src: Where to copy the string from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74)  * returns a pointer to @dest
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) #ifdef __HAVE_ARCH_STRCPY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) char *strcpy(char *dest, const char *src)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 	register int r0 asm("0") = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 	char *ret = dest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 	asm volatile ("0: mvst  %0,%1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 		      "   jo    0b"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 		      : "+&a" (dest), "+&a" (src) : "d" (r0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 		      : "cc", "memory" );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) EXPORT_SYMBOL(strcpy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92)  * strlcpy - Copy a %NUL terminated string into a sized buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93)  * @dest: Where to copy the string to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94)  * @src: Where to copy the string from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95)  * @size: size of destination buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97)  * Compatible with *BSD: the result is always a valid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98)  * NUL-terminated string that fits in the buffer (unless,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99)  * of course, the buffer size is zero). It does not pad
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)  * out the result like strncpy() does.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) #ifdef __HAVE_ARCH_STRLCPY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) size_t strlcpy(char *dest, const char *src, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	size_t ret = __strend(src) - src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	if (size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 		size_t len = (ret >= size) ? size-1 : ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 		dest[len] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 		memcpy(dest, src, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) EXPORT_SYMBOL(strlcpy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)  * strncpy - Copy a length-limited, %NUL-terminated string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)  * @dest: Where to copy the string to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)  * @src: Where to copy the string from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)  * @n: The maximum number of bytes to copy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)  * The result is not %NUL-terminated if the source exceeds
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)  * @n bytes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) #ifdef __HAVE_ARCH_STRNCPY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) char *strncpy(char *dest, const char *src, size_t n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	size_t len = __strnend(src, n) - src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	memset(dest + len, 0, n - len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 	memcpy(dest, src, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	return dest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) EXPORT_SYMBOL(strncpy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)  * strcat - Append one %NUL-terminated string to another
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)  * @dest: The string to be appended to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)  * @src: The string to append to it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)  * returns a pointer to @dest
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) #ifdef __HAVE_ARCH_STRCAT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) char *strcat(char *dest, const char *src)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	register int r0 asm("0") = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	unsigned long dummy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 	char *ret = dest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 	asm volatile ("0: srst  %0,%1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 		      "   jo    0b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 		      "1: mvst  %0,%2\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 		      "   jo    1b"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 		      : "=&a" (dummy), "+a" (dest), "+a" (src)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 		      : "d" (r0), "0" (0UL) : "cc", "memory" );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) EXPORT_SYMBOL(strcat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)  * strlcat - Append a length-limited, %NUL-terminated string to another
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)  * @dest: The string to be appended to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)  * @src: The string to append to it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)  * @n: The size of the destination buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) #ifdef __HAVE_ARCH_STRLCAT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) size_t strlcat(char *dest, const char *src, size_t n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 	size_t dsize = __strend(dest) - dest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	size_t len = __strend(src) - src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 	size_t res = dsize + len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 	if (dsize < n) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 		dest += dsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 		n -= dsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 		if (len >= n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 			len = n - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 		dest[len] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 		memcpy(dest, src, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 	return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) EXPORT_SYMBOL(strlcat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)  * strncat - Append a length-limited, %NUL-terminated string to another
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)  * @dest: The string to be appended to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)  * @src: The string to append to it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)  * @n: The maximum numbers of bytes to copy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)  * returns a pointer to @dest
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)  * Note that in contrast to strncpy, strncat ensures the result is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)  * terminated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) #ifdef __HAVE_ARCH_STRNCAT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) char *strncat(char *dest, const char *src, size_t n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 	size_t len = __strnend(src, n) - src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 	char *p = __strend(dest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 	p[len] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 	memcpy(p, src, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 	return dest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) EXPORT_SYMBOL(strncat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)  * strcmp - Compare two strings
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)  * @s1: One string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)  * @s2: Another string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)  * returns   0 if @s1 and @s2 are equal,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)  *	   < 0 if @s1 is less than @s2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)  *	   > 0 if @s1 is greater than @s2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) #ifdef __HAVE_ARCH_STRCMP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) int strcmp(const char *s1, const char *s2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 	register int r0 asm("0") = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 	int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 	asm volatile ("0: clst %2,%3\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 		      "   jo   0b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 		      "   je   1f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 		      "   ic   %0,0(%2)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 		      "   ic   %1,0(%3)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 		      "   sr   %0,%1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 		      "1:"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 		      : "+d" (ret), "+d" (r0), "+a" (s1), "+a" (s2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 		      : : "cc", "memory");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) EXPORT_SYMBOL(strcmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)  * strrchr - Find the last occurrence of a character in a string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)  * @s: The string to be searched
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)  * @c: The character to search for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) #ifdef __HAVE_ARCH_STRRCHR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) char *strrchr(const char *s, int c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 	ssize_t len = __strend(s) - s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 		if (s[len] == (char)c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 			return (char *)s + len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 	} while (--len >= 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 	return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) EXPORT_SYMBOL(strrchr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) static inline int clcle(const char *s1, unsigned long l1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 			const char *s2, unsigned long l2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 	register unsigned long r2 asm("2") = (unsigned long) s1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 	register unsigned long r3 asm("3") = (unsigned long) l1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 	register unsigned long r4 asm("4") = (unsigned long) s2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 	register unsigned long r5 asm("5") = (unsigned long) l2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 	int cc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 	asm volatile ("0: clcle %1,%3,0\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 		      "   jo    0b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 		      "   ipm   %0\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 		      "   srl   %0,28"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 		      : "=&d" (cc), "+a" (r2), "+a" (r3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 			"+a" (r4), "+a" (r5) : : "cc", "memory");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 	return cc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)  * strstr - Find the first substring in a %NUL terminated string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)  * @s1: The string to be searched
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)  * @s2: The string to search for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) #ifdef __HAVE_ARCH_STRSTR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) char *strstr(const char *s1, const char *s2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 	int l1, l2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 	l2 = __strend(s2) - s2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 	if (!l2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 		return (char *) s1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 	l1 = __strend(s1) - s1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 	while (l1-- >= l2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 		int cc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 		cc = clcle(s1, l2, s2, l2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 		if (!cc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 			return (char *) s1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 		s1++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 	return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) EXPORT_SYMBOL(strstr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)  * memchr - Find a character in an area of memory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)  * @s: The memory area
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)  * @c: The byte to search for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)  * @n: The size of the area.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)  * returns the address of the first occurrence of @c, or %NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)  * if @c is not found
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) #ifdef __HAVE_ARCH_MEMCHR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) void *memchr(const void *s, int c, size_t n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 	register int r0 asm("0") = (char) c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 	const void *ret = s + n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 	asm volatile ("0: srst  %0,%1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 		      "   jo    0b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 		      "   jl	1f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 		      "   la    %0,0\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 		      "1:"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 		      : "+a" (ret), "+&a" (s) : "d" (r0) : "cc", "memory");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 	return (void *) ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) EXPORT_SYMBOL(memchr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)  * memcmp - Compare two areas of memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)  * @s1: One area of memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)  * @s2: Another area of memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)  * @n: The size of the area.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) #ifdef __HAVE_ARCH_MEMCMP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) int memcmp(const void *s1, const void *s2, size_t n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 	ret = clcle(s1, n, s2, n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 		ret = ret == 1 ? -1 : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) EXPORT_SYMBOL(memcmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)  * memscan - Find a character in an area of memory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)  * @s: The memory area
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)  * @c: The byte to search for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)  * @n: The size of the area.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)  * returns the address of the first occurrence of @c, or 1 byte past
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)  * the area if @c is not found
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) #ifdef __HAVE_ARCH_MEMSCAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) void *memscan(void *s, int c, size_t n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 	register int r0 asm("0") = (char) c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 	const void *ret = s + n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 	asm volatile ("0: srst  %0,%1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 		      "   jo    0b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 		      : "+a" (ret), "+&a" (s) : "d" (r0) : "cc", "memory");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 	return (void *) ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) EXPORT_SYMBOL(memscan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) #endif