18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 28c2ecf20Sopenharmony_ci#ifndef _ASM_X86_STRING_32_H 38c2ecf20Sopenharmony_ci#define _ASM_X86_STRING_32_H 48c2ecf20Sopenharmony_ci 58c2ecf20Sopenharmony_ci#ifdef __KERNEL__ 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci/* Let gcc decide whether to inline or use the out of line functions */ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#define __HAVE_ARCH_STRCPY 108c2ecf20Sopenharmony_ciextern char *strcpy(char *dest, const char *src); 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#define __HAVE_ARCH_STRNCPY 138c2ecf20Sopenharmony_ciextern char *strncpy(char *dest, const char *src, size_t count); 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#define __HAVE_ARCH_STRCAT 168c2ecf20Sopenharmony_ciextern char *strcat(char *dest, const char *src); 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci#define __HAVE_ARCH_STRNCAT 198c2ecf20Sopenharmony_ciextern char *strncat(char *dest, const char *src, size_t count); 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci#define __HAVE_ARCH_STRCMP 228c2ecf20Sopenharmony_ciextern int strcmp(const char *cs, const char *ct); 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci#define __HAVE_ARCH_STRNCMP 258c2ecf20Sopenharmony_ciextern int strncmp(const char *cs, const char *ct, size_t count); 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci#define __HAVE_ARCH_STRCHR 288c2ecf20Sopenharmony_ciextern char *strchr(const char *s, int c); 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci#define __HAVE_ARCH_STRLEN 318c2ecf20Sopenharmony_ciextern size_t strlen(const char *s); 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_cistatic __always_inline void *__memcpy(void *to, const void *from, size_t n) 348c2ecf20Sopenharmony_ci{ 358c2ecf20Sopenharmony_ci int d0, d1, d2; 368c2ecf20Sopenharmony_ci asm volatile("rep ; movsl\n\t" 378c2ecf20Sopenharmony_ci "movl %4,%%ecx\n\t" 388c2ecf20Sopenharmony_ci "andl $3,%%ecx\n\t" 398c2ecf20Sopenharmony_ci "jz 1f\n\t" 408c2ecf20Sopenharmony_ci "rep ; movsb\n\t" 418c2ecf20Sopenharmony_ci "1:" 428c2ecf20Sopenharmony_ci : "=&c" (d0), "=&D" (d1), "=&S" (d2) 438c2ecf20Sopenharmony_ci : "0" (n / 4), "g" (n), "1" ((long)to), "2" ((long)from) 448c2ecf20Sopenharmony_ci : "memory"); 458c2ecf20Sopenharmony_ci return to; 468c2ecf20Sopenharmony_ci} 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci/* 498c2ecf20Sopenharmony_ci * This looks ugly, but the compiler can optimize it totally, 508c2ecf20Sopenharmony_ci * as the count is constant. 518c2ecf20Sopenharmony_ci */ 528c2ecf20Sopenharmony_cistatic __always_inline void *__constant_memcpy(void *to, const void *from, 538c2ecf20Sopenharmony_ci size_t n) 548c2ecf20Sopenharmony_ci{ 558c2ecf20Sopenharmony_ci long esi, edi; 568c2ecf20Sopenharmony_ci if (!n) 578c2ecf20Sopenharmony_ci return to; 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci switch (n) { 608c2ecf20Sopenharmony_ci case 1: 618c2ecf20Sopenharmony_ci *(char *)to = *(char *)from; 628c2ecf20Sopenharmony_ci return to; 638c2ecf20Sopenharmony_ci case 2: 648c2ecf20Sopenharmony_ci *(short *)to = *(short *)from; 658c2ecf20Sopenharmony_ci return to; 668c2ecf20Sopenharmony_ci case 4: 678c2ecf20Sopenharmony_ci *(int *)to = *(int *)from; 688c2ecf20Sopenharmony_ci return to; 698c2ecf20Sopenharmony_ci case 3: 708c2ecf20Sopenharmony_ci *(short *)to = *(short *)from; 718c2ecf20Sopenharmony_ci *((char *)to + 2) = *((char *)from + 2); 728c2ecf20Sopenharmony_ci return to; 738c2ecf20Sopenharmony_ci case 5: 748c2ecf20Sopenharmony_ci *(int *)to = *(int *)from; 758c2ecf20Sopenharmony_ci *((char *)to + 4) = *((char *)from + 4); 768c2ecf20Sopenharmony_ci return to; 778c2ecf20Sopenharmony_ci case 6: 788c2ecf20Sopenharmony_ci *(int *)to = *(int *)from; 798c2ecf20Sopenharmony_ci *((short *)to + 2) = *((short *)from + 2); 808c2ecf20Sopenharmony_ci return to; 818c2ecf20Sopenharmony_ci case 8: 828c2ecf20Sopenharmony_ci *(int *)to = *(int *)from; 838c2ecf20Sopenharmony_ci *((int *)to + 1) = *((int *)from + 1); 848c2ecf20Sopenharmony_ci return to; 858c2ecf20Sopenharmony_ci } 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci esi = (long)from; 888c2ecf20Sopenharmony_ci edi = (long)to; 898c2ecf20Sopenharmony_ci if (n >= 5 * 4) { 908c2ecf20Sopenharmony_ci /* large block: use rep prefix */ 918c2ecf20Sopenharmony_ci int ecx; 928c2ecf20Sopenharmony_ci asm volatile("rep ; movsl" 938c2ecf20Sopenharmony_ci : "=&c" (ecx), "=&D" (edi), "=&S" (esi) 948c2ecf20Sopenharmony_ci : "0" (n / 4), "1" (edi), "2" (esi) 958c2ecf20Sopenharmony_ci : "memory" 968c2ecf20Sopenharmony_ci ); 978c2ecf20Sopenharmony_ci } else { 988c2ecf20Sopenharmony_ci /* small block: don't clobber ecx + smaller code */ 998c2ecf20Sopenharmony_ci if (n >= 4 * 4) 1008c2ecf20Sopenharmony_ci asm volatile("movsl" 1018c2ecf20Sopenharmony_ci : "=&D"(edi), "=&S"(esi) 1028c2ecf20Sopenharmony_ci : "0"(edi), "1"(esi) 1038c2ecf20Sopenharmony_ci : "memory"); 1048c2ecf20Sopenharmony_ci if (n >= 3 * 4) 1058c2ecf20Sopenharmony_ci asm volatile("movsl" 1068c2ecf20Sopenharmony_ci : "=&D"(edi), "=&S"(esi) 1078c2ecf20Sopenharmony_ci : "0"(edi), "1"(esi) 1088c2ecf20Sopenharmony_ci : "memory"); 1098c2ecf20Sopenharmony_ci if (n >= 2 * 4) 1108c2ecf20Sopenharmony_ci asm volatile("movsl" 1118c2ecf20Sopenharmony_ci : "=&D"(edi), "=&S"(esi) 1128c2ecf20Sopenharmony_ci : "0"(edi), "1"(esi) 1138c2ecf20Sopenharmony_ci : "memory"); 1148c2ecf20Sopenharmony_ci if (n >= 1 * 4) 1158c2ecf20Sopenharmony_ci asm volatile("movsl" 1168c2ecf20Sopenharmony_ci : "=&D"(edi), "=&S"(esi) 1178c2ecf20Sopenharmony_ci : "0"(edi), "1"(esi) 1188c2ecf20Sopenharmony_ci : "memory"); 1198c2ecf20Sopenharmony_ci } 1208c2ecf20Sopenharmony_ci switch (n % 4) { 1218c2ecf20Sopenharmony_ci /* tail */ 1228c2ecf20Sopenharmony_ci case 0: 1238c2ecf20Sopenharmony_ci return to; 1248c2ecf20Sopenharmony_ci case 1: 1258c2ecf20Sopenharmony_ci asm volatile("movsb" 1268c2ecf20Sopenharmony_ci : "=&D"(edi), "=&S"(esi) 1278c2ecf20Sopenharmony_ci : "0"(edi), "1"(esi) 1288c2ecf20Sopenharmony_ci : "memory"); 1298c2ecf20Sopenharmony_ci return to; 1308c2ecf20Sopenharmony_ci case 2: 1318c2ecf20Sopenharmony_ci asm volatile("movsw" 1328c2ecf20Sopenharmony_ci : "=&D"(edi), "=&S"(esi) 1338c2ecf20Sopenharmony_ci : "0"(edi), "1"(esi) 1348c2ecf20Sopenharmony_ci : "memory"); 1358c2ecf20Sopenharmony_ci return to; 1368c2ecf20Sopenharmony_ci default: 1378c2ecf20Sopenharmony_ci asm volatile("movsw\n\tmovsb" 1388c2ecf20Sopenharmony_ci : "=&D"(edi), "=&S"(esi) 1398c2ecf20Sopenharmony_ci : "0"(edi), "1"(esi) 1408c2ecf20Sopenharmony_ci : "memory"); 1418c2ecf20Sopenharmony_ci return to; 1428c2ecf20Sopenharmony_ci } 1438c2ecf20Sopenharmony_ci} 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci#define __HAVE_ARCH_MEMCPY 1468c2ecf20Sopenharmony_ciextern void *memcpy(void *, const void *, size_t); 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci#ifndef CONFIG_FORTIFY_SOURCE 1498c2ecf20Sopenharmony_ci#ifdef CONFIG_X86_USE_3DNOW 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci#include <asm/mmx.h> 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci/* 1548c2ecf20Sopenharmony_ci * This CPU favours 3DNow strongly (eg AMD Athlon) 1558c2ecf20Sopenharmony_ci */ 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_cistatic inline void *__constant_memcpy3d(void *to, const void *from, size_t len) 1588c2ecf20Sopenharmony_ci{ 1598c2ecf20Sopenharmony_ci if (len < 512) 1608c2ecf20Sopenharmony_ci return __constant_memcpy(to, from, len); 1618c2ecf20Sopenharmony_ci return _mmx_memcpy(to, from, len); 1628c2ecf20Sopenharmony_ci} 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_cistatic inline void *__memcpy3d(void *to, const void *from, size_t len) 1658c2ecf20Sopenharmony_ci{ 1668c2ecf20Sopenharmony_ci if (len < 512) 1678c2ecf20Sopenharmony_ci return __memcpy(to, from, len); 1688c2ecf20Sopenharmony_ci return _mmx_memcpy(to, from, len); 1698c2ecf20Sopenharmony_ci} 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci#define memcpy(t, f, n) \ 1728c2ecf20Sopenharmony_ci (__builtin_constant_p((n)) \ 1738c2ecf20Sopenharmony_ci ? __constant_memcpy3d((t), (f), (n)) \ 1748c2ecf20Sopenharmony_ci : __memcpy3d((t), (f), (n))) 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci#else 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci/* 1798c2ecf20Sopenharmony_ci * No 3D Now! 1808c2ecf20Sopenharmony_ci */ 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_ci#define memcpy(t, f, n) __builtin_memcpy(t, f, n) 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci#endif 1858c2ecf20Sopenharmony_ci#endif /* !CONFIG_FORTIFY_SOURCE */ 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci#define __HAVE_ARCH_MEMMOVE 1888c2ecf20Sopenharmony_civoid *memmove(void *dest, const void *src, size_t n); 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ciextern int memcmp(const void *, const void *, size_t); 1918c2ecf20Sopenharmony_ci#ifndef CONFIG_FORTIFY_SOURCE 1928c2ecf20Sopenharmony_ci#define memcmp __builtin_memcmp 1938c2ecf20Sopenharmony_ci#endif 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci#define __HAVE_ARCH_MEMCHR 1968c2ecf20Sopenharmony_ciextern void *memchr(const void *cs, int c, size_t count); 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_cistatic inline void *__memset_generic(void *s, char c, size_t count) 1998c2ecf20Sopenharmony_ci{ 2008c2ecf20Sopenharmony_ci int d0, d1; 2018c2ecf20Sopenharmony_ci asm volatile("rep\n\t" 2028c2ecf20Sopenharmony_ci "stosb" 2038c2ecf20Sopenharmony_ci : "=&c" (d0), "=&D" (d1) 2048c2ecf20Sopenharmony_ci : "a" (c), "1" (s), "0" (count) 2058c2ecf20Sopenharmony_ci : "memory"); 2068c2ecf20Sopenharmony_ci return s; 2078c2ecf20Sopenharmony_ci} 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci/* we might want to write optimized versions of these later */ 2108c2ecf20Sopenharmony_ci#define __constant_count_memset(s, c, count) __memset_generic((s), (c), (count)) 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci/* Added by Gertjan van Wingerde to make minix and sysv module work */ 2138c2ecf20Sopenharmony_ci#define __HAVE_ARCH_STRNLEN 2148c2ecf20Sopenharmony_ciextern size_t strnlen(const char *s, size_t count); 2158c2ecf20Sopenharmony_ci/* end of additional stuff */ 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci#define __HAVE_ARCH_STRSTR 2188c2ecf20Sopenharmony_ciextern char *strstr(const char *cs, const char *ct); 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci#define __memset(s, c, count) \ 2218c2ecf20Sopenharmony_ci (__builtin_constant_p(count) \ 2228c2ecf20Sopenharmony_ci ? __constant_count_memset((s), (c), (count)) \ 2238c2ecf20Sopenharmony_ci : __memset_generic((s), (c), (count))) 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci#define __HAVE_ARCH_MEMSET 2268c2ecf20Sopenharmony_ciextern void *memset(void *, int, size_t); 2278c2ecf20Sopenharmony_ci#ifndef CONFIG_FORTIFY_SOURCE 2288c2ecf20Sopenharmony_ci#define memset(s, c, count) __builtin_memset(s, c, count) 2298c2ecf20Sopenharmony_ci#endif /* !CONFIG_FORTIFY_SOURCE */ 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci#define __HAVE_ARCH_MEMSET16 2328c2ecf20Sopenharmony_cistatic inline void *memset16(uint16_t *s, uint16_t v, size_t n) 2338c2ecf20Sopenharmony_ci{ 2348c2ecf20Sopenharmony_ci int d0, d1; 2358c2ecf20Sopenharmony_ci asm volatile("rep\n\t" 2368c2ecf20Sopenharmony_ci "stosw" 2378c2ecf20Sopenharmony_ci : "=&c" (d0), "=&D" (d1) 2388c2ecf20Sopenharmony_ci : "a" (v), "1" (s), "0" (n) 2398c2ecf20Sopenharmony_ci : "memory"); 2408c2ecf20Sopenharmony_ci return s; 2418c2ecf20Sopenharmony_ci} 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ci#define __HAVE_ARCH_MEMSET32 2448c2ecf20Sopenharmony_cistatic inline void *memset32(uint32_t *s, uint32_t v, size_t n) 2458c2ecf20Sopenharmony_ci{ 2468c2ecf20Sopenharmony_ci int d0, d1; 2478c2ecf20Sopenharmony_ci asm volatile("rep\n\t" 2488c2ecf20Sopenharmony_ci "stosl" 2498c2ecf20Sopenharmony_ci : "=&c" (d0), "=&D" (d1) 2508c2ecf20Sopenharmony_ci : "a" (v), "1" (s), "0" (n) 2518c2ecf20Sopenharmony_ci : "memory"); 2528c2ecf20Sopenharmony_ci return s; 2538c2ecf20Sopenharmony_ci} 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci/* 2568c2ecf20Sopenharmony_ci * find the first occurrence of byte 'c', or 1 past the area if none 2578c2ecf20Sopenharmony_ci */ 2588c2ecf20Sopenharmony_ci#define __HAVE_ARCH_MEMSCAN 2598c2ecf20Sopenharmony_ciextern void *memscan(void *addr, int c, size_t size); 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ci#endif /* __KERNEL__ */ 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci#endif /* _ASM_X86_STRING_32_H */ 264