xref: /linux/arch/x86/include/asm/shared/string.h (revision 40082fb4015712084df977bb8e7f0aa681a56a1a)
15b6fe004SMauricio Faria de Oliveira /* SPDX-License-Identifier: GPL-2.0 */
25b6fe004SMauricio Faria de Oliveira #ifndef _ASM_X86_SHARED_STRING_H
35b6fe004SMauricio Faria de Oliveira #define _ASM_X86_SHARED_STRING_H
45b6fe004SMauricio Faria de Oliveira 
__inline_memcpy(void * to,const void * from,size_t len)5*85f11c17SMauricio Faria de Oliveira static __always_inline void *__inline_memcpy(void *to, const void *from, size_t len)
6*85f11c17SMauricio Faria de Oliveira {
7*85f11c17SMauricio Faria de Oliveira 	void *ret = to;
8*85f11c17SMauricio Faria de Oliveira 
9*85f11c17SMauricio Faria de Oliveira 	asm volatile("rep movsb"
10*85f11c17SMauricio Faria de Oliveira 		     : "+D" (to), "+S" (from), "+c" (len)
11*85f11c17SMauricio Faria de Oliveira 		     : : "memory");
12*85f11c17SMauricio Faria de Oliveira 	return ret;
13*85f11c17SMauricio Faria de Oliveira }
14*85f11c17SMauricio Faria de Oliveira 
__inline_memset(void * s,int v,size_t n)15*85f11c17SMauricio Faria de Oliveira static __always_inline void *__inline_memset(void *s, int v, size_t n)
16*85f11c17SMauricio Faria de Oliveira {
17*85f11c17SMauricio Faria de Oliveira 	void *ret = s;
18*85f11c17SMauricio Faria de Oliveira 
19*85f11c17SMauricio Faria de Oliveira 	asm volatile("rep stosb"
20*85f11c17SMauricio Faria de Oliveira 		     : "+D" (s), "+c" (n)
21*85f11c17SMauricio Faria de Oliveira 		     : "a" ((uint8_t)v)
22*85f11c17SMauricio Faria de Oliveira 		     : "memory");
23*85f11c17SMauricio Faria de Oliveira 	return ret;
24*85f11c17SMauricio Faria de Oliveira }
25*85f11c17SMauricio Faria de Oliveira 
265b6fe004SMauricio Faria de Oliveira /*
275b6fe004SMauricio Faria de Oliveira  * Returns:	0 (equal)
285b6fe004SMauricio Faria de Oliveira  * 		1 (not equal)
295b6fe004SMauricio Faria de Oliveira  *
305b6fe004SMauricio Faria de Oliveira  * In contrast, the regular memcmp() follows glibc return value semantics.
315b6fe004SMauricio Faria de Oliveira  */
__inline_memcmp(const void * s1,const void * s2,size_t len)325b6fe004SMauricio Faria de Oliveira static __always_inline int __inline_memcmp(const void *s1, const void *s2, size_t len)
335b6fe004SMauricio Faria de Oliveira {
345b6fe004SMauricio Faria de Oliveira 	bool diff;
355b6fe004SMauricio Faria de Oliveira 
365b6fe004SMauricio Faria de Oliveira 	/*
375b6fe004SMauricio Faria de Oliveira 	 * Make sure ZF is properly set in the len==0 case because in it,
385b6fe004SMauricio Faria de Oliveira 	 * RCX==0 and the REPE; CMPSB won't get executed.
395b6fe004SMauricio Faria de Oliveira 	 *
405b6fe004SMauricio Faria de Oliveira 	 * The "cc" clobber has no meaning anymore, just source compatibility.
415b6fe004SMauricio Faria de Oliveira 	 * On x86 the flag status bits are automatically added to the clobber
425b6fe004SMauricio Faria de Oliveira 	 * set when there are no =@ccXY constraints. Keep it as documentation.
435b6fe004SMauricio Faria de Oliveira 	 */
445b6fe004SMauricio Faria de Oliveira 	asm volatile("test %3, %3\n\t"
455b6fe004SMauricio Faria de Oliveira 		     "repe cmpsb"
465b6fe004SMauricio Faria de Oliveira 		     : "=@ccnz" (diff), "+D" (s1), "+S" (s2), "+c" (len)
475b6fe004SMauricio Faria de Oliveira 		     : : /* "cc", */ "memory");
485b6fe004SMauricio Faria de Oliveira 
495b6fe004SMauricio Faria de Oliveira 	return diff;
505b6fe004SMauricio Faria de Oliveira }
515b6fe004SMauricio Faria de Oliveira 
525b6fe004SMauricio Faria de Oliveira #endif /* _ASM_X86_SHARED_STRING_H */
53