xref: /openbmc/linux/arch/x86/include/asm/string_32.h (revision 03ab8e6297acd1bc0eedaa050e2a1635c576fd11)
1*b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
21965aae3SH. Peter Anvin #ifndef _ASM_X86_STRING_32_H
31965aae3SH. Peter Anvin #define _ASM_X86_STRING_32_H
4bb898558SAl Viro 
5bb898558SAl Viro #ifdef __KERNEL__
6bb898558SAl Viro 
7bb898558SAl Viro /* Let gcc decide whether to inline or use the out of line functions */
8bb898558SAl Viro 
9bb898558SAl Viro #define __HAVE_ARCH_STRCPY
10bb898558SAl Viro extern char *strcpy(char *dest, const char *src);
11bb898558SAl Viro 
12bb898558SAl Viro #define __HAVE_ARCH_STRNCPY
13bb898558SAl Viro extern char *strncpy(char *dest, const char *src, size_t count);
14bb898558SAl Viro 
15bb898558SAl Viro #define __HAVE_ARCH_STRCAT
16bb898558SAl Viro extern char *strcat(char *dest, const char *src);
17bb898558SAl Viro 
18bb898558SAl Viro #define __HAVE_ARCH_STRNCAT
19bb898558SAl Viro extern char *strncat(char *dest, const char *src, size_t count);
20bb898558SAl Viro 
21bb898558SAl Viro #define __HAVE_ARCH_STRCMP
22bb898558SAl Viro extern int strcmp(const char *cs, const char *ct);
23bb898558SAl Viro 
24bb898558SAl Viro #define __HAVE_ARCH_STRNCMP
25bb898558SAl Viro extern int strncmp(const char *cs, const char *ct, size_t count);
26bb898558SAl Viro 
27bb898558SAl Viro #define __HAVE_ARCH_STRCHR
28bb898558SAl Viro extern char *strchr(const char *s, int c);
29bb898558SAl Viro 
30bb898558SAl Viro #define __HAVE_ARCH_STRLEN
31bb898558SAl Viro extern size_t strlen(const char *s);
32bb898558SAl Viro 
__memcpy(void * to,const void * from,size_t n)33bb898558SAl Viro static __always_inline void *__memcpy(void *to, const void *from, size_t n)
34bb898558SAl Viro {
35bb898558SAl Viro 	int d0, d1, d2;
36bb898558SAl Viro 	asm volatile("rep ; movsl\n\t"
37bb898558SAl Viro 		     "movl %4,%%ecx\n\t"
38bb898558SAl Viro 		     "andl $3,%%ecx\n\t"
39bb898558SAl Viro 		     "jz 1f\n\t"
40bb898558SAl Viro 		     "rep ; movsb\n\t"
41bb898558SAl Viro 		     "1:"
42bb898558SAl Viro 		     : "=&c" (d0), "=&D" (d1), "=&S" (d2)
43bb898558SAl Viro 		     : "0" (n / 4), "g" (n), "1" ((long)to), "2" ((long)from)
44bb898558SAl Viro 		     : "memory");
45bb898558SAl Viro 	return to;
46bb898558SAl Viro }
47bb898558SAl Viro 
48bb898558SAl Viro /*
49bb898558SAl Viro  * This looks ugly, but the compiler can optimize it totally,
50bb898558SAl Viro  * as the count is constant.
51bb898558SAl Viro  */
__constant_memcpy(void * to,const void * from,size_t n)52bb898558SAl Viro static __always_inline void *__constant_memcpy(void *to, const void *from,
53bb898558SAl Viro 					       size_t n)
54bb898558SAl Viro {
55bb898558SAl Viro 	long esi, edi;
56bb898558SAl Viro 	if (!n)
57bb898558SAl Viro 		return to;
58bb898558SAl Viro 
59bb898558SAl Viro 	switch (n) {
60bb898558SAl Viro 	case 1:
61bb898558SAl Viro 		*(char *)to = *(char *)from;
62bb898558SAl Viro 		return to;
63bb898558SAl Viro 	case 2:
64bb898558SAl Viro 		*(short *)to = *(short *)from;
65bb898558SAl Viro 		return to;
66bb898558SAl Viro 	case 4:
67bb898558SAl Viro 		*(int *)to = *(int *)from;
68bb898558SAl Viro 		return to;
69bb898558SAl Viro 	case 3:
70bb898558SAl Viro 		*(short *)to = *(short *)from;
71bb898558SAl Viro 		*((char *)to + 2) = *((char *)from + 2);
72bb898558SAl Viro 		return to;
73bb898558SAl Viro 	case 5:
74bb898558SAl Viro 		*(int *)to = *(int *)from;
75bb898558SAl Viro 		*((char *)to + 4) = *((char *)from + 4);
76bb898558SAl Viro 		return to;
77bb898558SAl Viro 	case 6:
78bb898558SAl Viro 		*(int *)to = *(int *)from;
79bb898558SAl Viro 		*((short *)to + 2) = *((short *)from + 2);
80bb898558SAl Viro 		return to;
81bb898558SAl Viro 	case 8:
82bb898558SAl Viro 		*(int *)to = *(int *)from;
83bb898558SAl Viro 		*((int *)to + 1) = *((int *)from + 1);
84bb898558SAl Viro 		return to;
85bb898558SAl Viro 	}
86bb898558SAl Viro 
87bb898558SAl Viro 	esi = (long)from;
88bb898558SAl Viro 	edi = (long)to;
89bb898558SAl Viro 	if (n >= 5 * 4) {
90bb898558SAl Viro 		/* large block: use rep prefix */
91bb898558SAl Viro 		int ecx;
92bb898558SAl Viro 		asm volatile("rep ; movsl"
93bb898558SAl Viro 			     : "=&c" (ecx), "=&D" (edi), "=&S" (esi)
94bb898558SAl Viro 			     : "0" (n / 4), "1" (edi), "2" (esi)
95bb898558SAl Viro 			     : "memory"
96bb898558SAl Viro 		);
97bb898558SAl Viro 	} else {
98bb898558SAl Viro 		/* small block: don't clobber ecx + smaller code */
99bb898558SAl Viro 		if (n >= 4 * 4)
100bb898558SAl Viro 			asm volatile("movsl"
101bb898558SAl Viro 				     : "=&D"(edi), "=&S"(esi)
102bb898558SAl Viro 				     : "0"(edi), "1"(esi)
103bb898558SAl Viro 				     : "memory");
104bb898558SAl Viro 		if (n >= 3 * 4)
105bb898558SAl Viro 			asm volatile("movsl"
106bb898558SAl Viro 				     : "=&D"(edi), "=&S"(esi)
107bb898558SAl Viro 				     : "0"(edi), "1"(esi)
108bb898558SAl Viro 				     : "memory");
109bb898558SAl Viro 		if (n >= 2 * 4)
110bb898558SAl Viro 			asm volatile("movsl"
111bb898558SAl Viro 				     : "=&D"(edi), "=&S"(esi)
112bb898558SAl Viro 				     : "0"(edi), "1"(esi)
113bb898558SAl Viro 				     : "memory");
114bb898558SAl Viro 		if (n >= 1 * 4)
115bb898558SAl Viro 			asm volatile("movsl"
116bb898558SAl Viro 				     : "=&D"(edi), "=&S"(esi)
117bb898558SAl Viro 				     : "0"(edi), "1"(esi)
118bb898558SAl Viro 				     : "memory");
119bb898558SAl Viro 	}
120bb898558SAl Viro 	switch (n % 4) {
121bb898558SAl Viro 		/* tail */
122bb898558SAl Viro 	case 0:
123bb898558SAl Viro 		return to;
124bb898558SAl Viro 	case 1:
125bb898558SAl Viro 		asm volatile("movsb"
126bb898558SAl Viro 			     : "=&D"(edi), "=&S"(esi)
127bb898558SAl Viro 			     : "0"(edi), "1"(esi)
128bb898558SAl Viro 			     : "memory");
129bb898558SAl Viro 		return to;
130bb898558SAl Viro 	case 2:
131bb898558SAl Viro 		asm volatile("movsw"
132bb898558SAl Viro 			     : "=&D"(edi), "=&S"(esi)
133bb898558SAl Viro 			     : "0"(edi), "1"(esi)
134bb898558SAl Viro 			     : "memory");
135bb898558SAl Viro 		return to;
136bb898558SAl Viro 	default:
137bb898558SAl Viro 		asm volatile("movsw\n\tmovsb"
138bb898558SAl Viro 			     : "=&D"(edi), "=&S"(esi)
139bb898558SAl Viro 			     : "0"(edi), "1"(esi)
140bb898558SAl Viro 			     : "memory");
141bb898558SAl Viro 		return to;
142bb898558SAl Viro 	}
143bb898558SAl Viro }
144bb898558SAl Viro 
145bb898558SAl Viro #define __HAVE_ARCH_MEMCPY
1466974f0c4SDaniel Micay extern void *memcpy(void *, const void *, size_t);
147bb898558SAl Viro 
1486974f0c4SDaniel Micay #ifndef CONFIG_FORTIFY_SOURCE
149bb898558SAl Viro 
150ff60fab7SArjan van de Ven #define memcpy(t, f, n) __builtin_memcpy(t, f, n)
151bb898558SAl Viro 
1526974f0c4SDaniel Micay #endif /* !CONFIG_FORTIFY_SOURCE */
153bb898558SAl Viro 
154bb898558SAl Viro #define __HAVE_ARCH_MEMMOVE
155bb898558SAl Viro void *memmove(void *dest, const void *src, size_t n);
156bb898558SAl Viro 
1576974f0c4SDaniel Micay extern int memcmp(const void *, const void *, size_t);
1586974f0c4SDaniel Micay #ifndef CONFIG_FORTIFY_SOURCE
159bb898558SAl Viro #define memcmp __builtin_memcmp
1606974f0c4SDaniel Micay #endif
161bb898558SAl Viro 
162bb898558SAl Viro #define __HAVE_ARCH_MEMCHR
163bb898558SAl Viro extern void *memchr(const void *cs, int c, size_t count);
164bb898558SAl Viro 
__memset_generic(void * s,char c,size_t count)165bb898558SAl Viro static inline void *__memset_generic(void *s, char c, size_t count)
166bb898558SAl Viro {
167bb898558SAl Viro 	int d0, d1;
168bb898558SAl Viro 	asm volatile("rep\n\t"
169bb898558SAl Viro 		     "stosb"
170bb898558SAl Viro 		     : "=&c" (d0), "=&D" (d1)
171bb898558SAl Viro 		     : "a" (c), "1" (s), "0" (count)
172bb898558SAl Viro 		     : "memory");
173bb898558SAl Viro 	return s;
174bb898558SAl Viro }
175bb898558SAl Viro 
176bb898558SAl Viro /* we might want to write optimized versions of these later */
177bb898558SAl Viro #define __constant_count_memset(s, c, count) __memset_generic((s), (c), (count))
178bb898558SAl Viro 
179bb898558SAl Viro /* Added by Gertjan van Wingerde to make minix and sysv module work */
180bb898558SAl Viro #define __HAVE_ARCH_STRNLEN
181bb898558SAl Viro extern size_t strnlen(const char *s, size_t count);
182bb898558SAl Viro /* end of additional stuff */
183bb898558SAl Viro 
184bb898558SAl Viro #define __HAVE_ARCH_STRSTR
185bb898558SAl Viro extern char *strstr(const char *cs, const char *ct);
186bb898558SAl Viro 
187bb898558SAl Viro #define __memset(s, c, count)				\
188bb898558SAl Viro 	(__builtin_constant_p(count)			\
189bb898558SAl Viro 	 ? __constant_count_memset((s), (c), (count))	\
190bb898558SAl Viro 	 : __memset_generic((s), (c), (count)))
191bb898558SAl Viro 
192bb898558SAl Viro #define __HAVE_ARCH_MEMSET
1936974f0c4SDaniel Micay extern void *memset(void *, int, size_t);
1946974f0c4SDaniel Micay #ifndef CONFIG_FORTIFY_SOURCE
195ff60fab7SArjan van de Ven #define memset(s, c, count) __builtin_memset(s, c, count)
1966974f0c4SDaniel Micay #endif /* !CONFIG_FORTIFY_SOURCE */
197bb898558SAl Viro 
1984c512485SMatthew Wilcox #define __HAVE_ARCH_MEMSET16
memset16(uint16_t * s,uint16_t v,size_t n)1994c512485SMatthew Wilcox static inline void *memset16(uint16_t *s, uint16_t v, size_t n)
2004c512485SMatthew Wilcox {
2014c512485SMatthew Wilcox 	int d0, d1;
2024c512485SMatthew Wilcox 	asm volatile("rep\n\t"
2034c512485SMatthew Wilcox 		     "stosw"
2044c512485SMatthew Wilcox 		     : "=&c" (d0), "=&D" (d1)
2054c512485SMatthew Wilcox 		     : "a" (v), "1" (s), "0" (n)
2064c512485SMatthew Wilcox 		     : "memory");
2074c512485SMatthew Wilcox 	return s;
2084c512485SMatthew Wilcox }
2094c512485SMatthew Wilcox 
2104c512485SMatthew Wilcox #define __HAVE_ARCH_MEMSET32
memset32(uint32_t * s,uint32_t v,size_t n)2114c512485SMatthew Wilcox static inline void *memset32(uint32_t *s, uint32_t v, size_t n)
2124c512485SMatthew Wilcox {
2134c512485SMatthew Wilcox 	int d0, d1;
2144c512485SMatthew Wilcox 	asm volatile("rep\n\t"
2154c512485SMatthew Wilcox 		     "stosl"
2164c512485SMatthew Wilcox 		     : "=&c" (d0), "=&D" (d1)
2174c512485SMatthew Wilcox 		     : "a" (v), "1" (s), "0" (n)
2184c512485SMatthew Wilcox 		     : "memory");
2194c512485SMatthew Wilcox 	return s;
2204c512485SMatthew Wilcox }
2214c512485SMatthew Wilcox 
222bb898558SAl Viro /*
223bb898558SAl Viro  * find the first occurrence of byte 'c', or 1 past the area if none
224bb898558SAl Viro  */
225bb898558SAl Viro #define __HAVE_ARCH_MEMSCAN
226bb898558SAl Viro extern void *memscan(void *addr, int c, size_t size);
227bb898558SAl Viro 
228bb898558SAl Viro #endif /* __KERNEL__ */
229bb898558SAl Viro 
2301965aae3SH. Peter Anvin #endif /* _ASM_X86_STRING_32_H */
231