1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef _ASM_X86_SHARED_STRING_H
3 #define _ASM_X86_SHARED_STRING_H
4
__inline_memcpy(void * to,const void * from,size_t len)5 static __always_inline void *__inline_memcpy(void *to, const void *from, size_t len)
6 {
7 void *ret = to;
8
9 asm volatile("rep movsb"
10 : "+D" (to), "+S" (from), "+c" (len)
11 : : "memory");
12 return ret;
13 }
14
__inline_memset(void * s,int v,size_t n)15 static __always_inline void *__inline_memset(void *s, int v, size_t n)
16 {
17 void *ret = s;
18
19 asm volatile("rep stosb"
20 : "+D" (s), "+c" (n)
21 : "a" ((uint8_t)v)
22 : "memory");
23 return ret;
24 }
25
26 /*
27 * Returns: 0 (equal)
28 * 1 (not equal)
29 *
30 * In contrast, the regular memcmp() follows glibc return value semantics.
31 */
__inline_memcmp(const void * s1,const void * s2,size_t len)32 static __always_inline int __inline_memcmp(const void *s1, const void *s2, size_t len)
33 {
34 bool diff;
35
36 /*
37 * Make sure ZF is properly set in the len==0 case because in it,
38 * RCX==0 and the REPE; CMPSB won't get executed.
39 *
40 * The "cc" clobber has no meaning anymore, just source compatibility.
41 * On x86 the flag status bits are automatically added to the clobber
42 * set when there are no =@ccXY constraints. Keep it as documentation.
43 */
44 asm volatile("test %3, %3\n\t"
45 "repe cmpsb"
46 : "=@ccnz" (diff), "+D" (s1), "+S" (s2), "+c" (len)
47 : : /* "cc", */ "memory");
48
49 return diff;
50 }
51
52 #endif /* _ASM_X86_SHARED_STRING_H */
53