projects/linux·blob master · refs

52 lines · 1.3 KiB

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