/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _ASM_X86_SHARED_STRING_H #define _ASM_X86_SHARED_STRING_H static __always_inline void *__inline_memcpy(void *to, const void *from, size_t len) { void *ret = to; asm volatile("rep movsb" : "+D" (to), "+S" (from), "+c" (len) : : "memory"); return ret; } static __always_inline void *__inline_memset(void *s, int v, size_t n) { void *ret = s; asm volatile("rep stosb" : "+D" (s), "+c" (n) : "a" ((uint8_t)v) : "memory"); return ret; } /* * Returns: 0 (equal) * 1 (not equal) * * In contrast, the regular memcmp() follows glibc return value semantics. */ static __always_inline int __inline_memcmp(const void *s1, const void *s2, size_t len) { bool diff; /* * Make sure ZF is properly set in the len==0 case because in it, * RCX==0 and the REPE; CMPSB won't get executed. * * The "cc" clobber has no meaning anymore, just source compatibility. * On x86 the flag status bits are automatically added to the clobber * set when there are no =@ccXY constraints. Keep it as documentation. */ asm volatile("test %3, %3\n\t" "repe cmpsb" : "=@ccnz" (diff), "+D" (s1), "+S" (s2), "+c" (len) : : /* "cc", */ "memory"); return diff; } #endif /* _ASM_X86_SHARED_STRING_H */