1 /* SPDX-License-Identifier: GPL-2.0 */ 2 #ifndef _ASM_X86_SHARED_STRING_H 3 #define _ASM_X86_SHARED_STRING_H 4 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 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 */ 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