162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci#ifndef _ASM_X86_STRING_32_H 362306a36Sopenharmony_ci#define _ASM_X86_STRING_32_H 462306a36Sopenharmony_ci 562306a36Sopenharmony_ci#ifdef __KERNEL__ 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci/* Let gcc decide whether to inline or use the out of line functions */ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#define __HAVE_ARCH_STRCPY 1062306a36Sopenharmony_ciextern char *strcpy(char *dest, const char *src); 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#define __HAVE_ARCH_STRNCPY 1362306a36Sopenharmony_ciextern char *strncpy(char *dest, const char *src, size_t count); 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#define __HAVE_ARCH_STRCAT 1662306a36Sopenharmony_ciextern char *strcat(char *dest, const char *src); 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci#define __HAVE_ARCH_STRNCAT 1962306a36Sopenharmony_ciextern char *strncat(char *dest, const char *src, size_t count); 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci#define __HAVE_ARCH_STRCMP 2262306a36Sopenharmony_ciextern int strcmp(const char *cs, const char *ct); 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci#define __HAVE_ARCH_STRNCMP 2562306a36Sopenharmony_ciextern int strncmp(const char *cs, const char *ct, size_t count); 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci#define __HAVE_ARCH_STRCHR 2862306a36Sopenharmony_ciextern char *strchr(const char *s, int c); 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci#define __HAVE_ARCH_STRLEN 3162306a36Sopenharmony_ciextern size_t strlen(const char *s); 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_cistatic __always_inline void *__memcpy(void *to, const void *from, size_t n) 3462306a36Sopenharmony_ci{ 3562306a36Sopenharmony_ci int d0, d1, d2; 3662306a36Sopenharmony_ci asm volatile("rep ; movsl\n\t" 3762306a36Sopenharmony_ci "movl %4,%%ecx\n\t" 3862306a36Sopenharmony_ci "andl $3,%%ecx\n\t" 3962306a36Sopenharmony_ci "jz 1f\n\t" 4062306a36Sopenharmony_ci "rep ; movsb\n\t" 4162306a36Sopenharmony_ci "1:" 4262306a36Sopenharmony_ci : "=&c" (d0), "=&D" (d1), "=&S" (d2) 4362306a36Sopenharmony_ci : "0" (n / 4), "g" (n), "1" ((long)to), "2" ((long)from) 4462306a36Sopenharmony_ci : "memory"); 4562306a36Sopenharmony_ci return to; 4662306a36Sopenharmony_ci} 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci/* 4962306a36Sopenharmony_ci * This looks ugly, but the compiler can optimize it totally, 5062306a36Sopenharmony_ci * as the count is constant. 5162306a36Sopenharmony_ci */ 5262306a36Sopenharmony_cistatic __always_inline void *__constant_memcpy(void *to, const void *from, 5362306a36Sopenharmony_ci size_t n) 5462306a36Sopenharmony_ci{ 5562306a36Sopenharmony_ci long esi, edi; 5662306a36Sopenharmony_ci if (!n) 5762306a36Sopenharmony_ci return to; 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci switch (n) { 6062306a36Sopenharmony_ci case 1: 6162306a36Sopenharmony_ci *(char *)to = *(char *)from; 6262306a36Sopenharmony_ci return to; 6362306a36Sopenharmony_ci case 2: 6462306a36Sopenharmony_ci *(short *)to = *(short *)from; 6562306a36Sopenharmony_ci return to; 6662306a36Sopenharmony_ci case 4: 6762306a36Sopenharmony_ci *(int *)to = *(int *)from; 6862306a36Sopenharmony_ci return to; 6962306a36Sopenharmony_ci case 3: 7062306a36Sopenharmony_ci *(short *)to = *(short *)from; 7162306a36Sopenharmony_ci *((char *)to + 2) = *((char *)from + 2); 7262306a36Sopenharmony_ci return to; 7362306a36Sopenharmony_ci case 5: 7462306a36Sopenharmony_ci *(int *)to = *(int *)from; 7562306a36Sopenharmony_ci *((char *)to + 4) = *((char *)from + 4); 7662306a36Sopenharmony_ci return to; 7762306a36Sopenharmony_ci case 6: 7862306a36Sopenharmony_ci *(int *)to = *(int *)from; 7962306a36Sopenharmony_ci *((short *)to + 2) = *((short *)from + 2); 8062306a36Sopenharmony_ci return to; 8162306a36Sopenharmony_ci case 8: 8262306a36Sopenharmony_ci *(int *)to = *(int *)from; 8362306a36Sopenharmony_ci *((int *)to + 1) = *((int *)from + 1); 8462306a36Sopenharmony_ci return to; 8562306a36Sopenharmony_ci } 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci esi = (long)from; 8862306a36Sopenharmony_ci edi = (long)to; 8962306a36Sopenharmony_ci if (n >= 5 * 4) { 9062306a36Sopenharmony_ci /* large block: use rep prefix */ 9162306a36Sopenharmony_ci int ecx; 9262306a36Sopenharmony_ci asm volatile("rep ; movsl" 9362306a36Sopenharmony_ci : "=&c" (ecx), "=&D" (edi), "=&S" (esi) 9462306a36Sopenharmony_ci : "0" (n / 4), "1" (edi), "2" (esi) 9562306a36Sopenharmony_ci : "memory" 9662306a36Sopenharmony_ci ); 9762306a36Sopenharmony_ci } else { 9862306a36Sopenharmony_ci /* small block: don't clobber ecx + smaller code */ 9962306a36Sopenharmony_ci if (n >= 4 * 4) 10062306a36Sopenharmony_ci asm volatile("movsl" 10162306a36Sopenharmony_ci : "=&D"(edi), "=&S"(esi) 10262306a36Sopenharmony_ci : "0"(edi), "1"(esi) 10362306a36Sopenharmony_ci : "memory"); 10462306a36Sopenharmony_ci if (n >= 3 * 4) 10562306a36Sopenharmony_ci asm volatile("movsl" 10662306a36Sopenharmony_ci : "=&D"(edi), "=&S"(esi) 10762306a36Sopenharmony_ci : "0"(edi), "1"(esi) 10862306a36Sopenharmony_ci : "memory"); 10962306a36Sopenharmony_ci if (n >= 2 * 4) 11062306a36Sopenharmony_ci asm volatile("movsl" 11162306a36Sopenharmony_ci : "=&D"(edi), "=&S"(esi) 11262306a36Sopenharmony_ci : "0"(edi), "1"(esi) 11362306a36Sopenharmony_ci : "memory"); 11462306a36Sopenharmony_ci if (n >= 1 * 4) 11562306a36Sopenharmony_ci asm volatile("movsl" 11662306a36Sopenharmony_ci : "=&D"(edi), "=&S"(esi) 11762306a36Sopenharmony_ci : "0"(edi), "1"(esi) 11862306a36Sopenharmony_ci : "memory"); 11962306a36Sopenharmony_ci } 12062306a36Sopenharmony_ci switch (n % 4) { 12162306a36Sopenharmony_ci /* tail */ 12262306a36Sopenharmony_ci case 0: 12362306a36Sopenharmony_ci return to; 12462306a36Sopenharmony_ci case 1: 12562306a36Sopenharmony_ci asm volatile("movsb" 12662306a36Sopenharmony_ci : "=&D"(edi), "=&S"(esi) 12762306a36Sopenharmony_ci : "0"(edi), "1"(esi) 12862306a36Sopenharmony_ci : "memory"); 12962306a36Sopenharmony_ci return to; 13062306a36Sopenharmony_ci case 2: 13162306a36Sopenharmony_ci asm volatile("movsw" 13262306a36Sopenharmony_ci : "=&D"(edi), "=&S"(esi) 13362306a36Sopenharmony_ci : "0"(edi), "1"(esi) 13462306a36Sopenharmony_ci : "memory"); 13562306a36Sopenharmony_ci return to; 13662306a36Sopenharmony_ci default: 13762306a36Sopenharmony_ci asm volatile("movsw\n\tmovsb" 13862306a36Sopenharmony_ci : "=&D"(edi), "=&S"(esi) 13962306a36Sopenharmony_ci : "0"(edi), "1"(esi) 14062306a36Sopenharmony_ci : "memory"); 14162306a36Sopenharmony_ci return to; 14262306a36Sopenharmony_ci } 14362306a36Sopenharmony_ci} 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci#define __HAVE_ARCH_MEMCPY 14662306a36Sopenharmony_ciextern void *memcpy(void *, const void *, size_t); 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci#ifndef CONFIG_FORTIFY_SOURCE 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci#define memcpy(t, f, n) __builtin_memcpy(t, f, n) 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci#endif /* !CONFIG_FORTIFY_SOURCE */ 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci#define __HAVE_ARCH_MEMMOVE 15562306a36Sopenharmony_civoid *memmove(void *dest, const void *src, size_t n); 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ciextern int memcmp(const void *, const void *, size_t); 15862306a36Sopenharmony_ci#ifndef CONFIG_FORTIFY_SOURCE 15962306a36Sopenharmony_ci#define memcmp __builtin_memcmp 16062306a36Sopenharmony_ci#endif 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci#define __HAVE_ARCH_MEMCHR 16362306a36Sopenharmony_ciextern void *memchr(const void *cs, int c, size_t count); 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_cistatic inline void *__memset_generic(void *s, char c, size_t count) 16662306a36Sopenharmony_ci{ 16762306a36Sopenharmony_ci int d0, d1; 16862306a36Sopenharmony_ci asm volatile("rep\n\t" 16962306a36Sopenharmony_ci "stosb" 17062306a36Sopenharmony_ci : "=&c" (d0), "=&D" (d1) 17162306a36Sopenharmony_ci : "a" (c), "1" (s), "0" (count) 17262306a36Sopenharmony_ci : "memory"); 17362306a36Sopenharmony_ci return s; 17462306a36Sopenharmony_ci} 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci/* we might want to write optimized versions of these later */ 17762306a36Sopenharmony_ci#define __constant_count_memset(s, c, count) __memset_generic((s), (c), (count)) 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci/* Added by Gertjan van Wingerde to make minix and sysv module work */ 18062306a36Sopenharmony_ci#define __HAVE_ARCH_STRNLEN 18162306a36Sopenharmony_ciextern size_t strnlen(const char *s, size_t count); 18262306a36Sopenharmony_ci/* end of additional stuff */ 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci#define __HAVE_ARCH_STRSTR 18562306a36Sopenharmony_ciextern char *strstr(const char *cs, const char *ct); 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci#define __memset(s, c, count) \ 18862306a36Sopenharmony_ci (__builtin_constant_p(count) \ 18962306a36Sopenharmony_ci ? __constant_count_memset((s), (c), (count)) \ 19062306a36Sopenharmony_ci : __memset_generic((s), (c), (count))) 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci#define __HAVE_ARCH_MEMSET 19362306a36Sopenharmony_ciextern void *memset(void *, int, size_t); 19462306a36Sopenharmony_ci#ifndef CONFIG_FORTIFY_SOURCE 19562306a36Sopenharmony_ci#define memset(s, c, count) __builtin_memset(s, c, count) 19662306a36Sopenharmony_ci#endif /* !CONFIG_FORTIFY_SOURCE */ 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci#define __HAVE_ARCH_MEMSET16 19962306a36Sopenharmony_cistatic inline void *memset16(uint16_t *s, uint16_t v, size_t n) 20062306a36Sopenharmony_ci{ 20162306a36Sopenharmony_ci int d0, d1; 20262306a36Sopenharmony_ci asm volatile("rep\n\t" 20362306a36Sopenharmony_ci "stosw" 20462306a36Sopenharmony_ci : "=&c" (d0), "=&D" (d1) 20562306a36Sopenharmony_ci : "a" (v), "1" (s), "0" (n) 20662306a36Sopenharmony_ci : "memory"); 20762306a36Sopenharmony_ci return s; 20862306a36Sopenharmony_ci} 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci#define __HAVE_ARCH_MEMSET32 21162306a36Sopenharmony_cistatic inline void *memset32(uint32_t *s, uint32_t v, size_t n) 21262306a36Sopenharmony_ci{ 21362306a36Sopenharmony_ci int d0, d1; 21462306a36Sopenharmony_ci asm volatile("rep\n\t" 21562306a36Sopenharmony_ci "stosl" 21662306a36Sopenharmony_ci : "=&c" (d0), "=&D" (d1) 21762306a36Sopenharmony_ci : "a" (v), "1" (s), "0" (n) 21862306a36Sopenharmony_ci : "memory"); 21962306a36Sopenharmony_ci return s; 22062306a36Sopenharmony_ci} 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci/* 22362306a36Sopenharmony_ci * find the first occurrence of byte 'c', or 1 past the area if none 22462306a36Sopenharmony_ci */ 22562306a36Sopenharmony_ci#define __HAVE_ARCH_MEMSCAN 22662306a36Sopenharmony_ciextern void *memscan(void *addr, int c, size_t size); 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci#endif /* __KERNEL__ */ 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci#endif /* _ASM_X86_STRING_32_H */ 231