Linux 6.13-rc4
[linux.git] / fs / bcachefs / bkey_cmp.h
blob5f42a6e693606b27175044f60b917a7ff46722f4
1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef _BCACHEFS_BKEY_CMP_H
3 #define _BCACHEFS_BKEY_CMP_H
5 #include "bkey.h"
7 #ifdef CONFIG_X86_64
8 static inline int __bkey_cmp_bits(const u64 *l, const u64 *r,
9 unsigned nr_key_bits)
11 long d0, d1, d2, d3;
12 int cmp;
14 /* we shouldn't need asm for this, but gcc is being retarded: */
16 asm(".intel_syntax noprefix;"
17 "xor eax, eax;"
18 "xor edx, edx;"
19 "1:;"
20 "mov r8, [rdi];"
21 "mov r9, [rsi];"
22 "sub ecx, 64;"
23 "jl 2f;"
25 "cmp r8, r9;"
26 "jnz 3f;"
28 "lea rdi, [rdi - 8];"
29 "lea rsi, [rsi - 8];"
30 "jmp 1b;"
32 "2:;"
33 "not ecx;"
34 "shr r8, 1;"
35 "shr r9, 1;"
36 "shr r8, cl;"
37 "shr r9, cl;"
38 "cmp r8, r9;"
40 "3:\n"
41 "seta al;"
42 "setb dl;"
43 "sub eax, edx;"
44 ".att_syntax prefix;"
45 : "=&D" (d0), "=&S" (d1), "=&d" (d2), "=&c" (d3), "=&a" (cmp)
46 : "0" (l), "1" (r), "3" (nr_key_bits)
47 : "r8", "r9", "cc", "memory");
49 return cmp;
51 #else
52 static inline int __bkey_cmp_bits(const u64 *l, const u64 *r,
53 unsigned nr_key_bits)
55 u64 l_v, r_v;
57 if (!nr_key_bits)
58 return 0;
60 /* for big endian, skip past header */
61 nr_key_bits += high_bit_offset;
62 l_v = *l & (~0ULL >> high_bit_offset);
63 r_v = *r & (~0ULL >> high_bit_offset);
65 while (1) {
66 if (nr_key_bits < 64) {
67 l_v >>= 64 - nr_key_bits;
68 r_v >>= 64 - nr_key_bits;
69 nr_key_bits = 0;
70 } else {
71 nr_key_bits -= 64;
74 if (!nr_key_bits || l_v != r_v)
75 break;
77 l = next_word(l);
78 r = next_word(r);
80 l_v = *l;
81 r_v = *r;
84 return cmp_int(l_v, r_v);
86 #endif
88 static inline __pure __flatten
89 int __bch2_bkey_cmp_packed_format_checked_inlined(const struct bkey_packed *l,
90 const struct bkey_packed *r,
91 const struct btree *b)
93 const struct bkey_format *f = &b->format;
94 int ret;
96 EBUG_ON(!bkey_packed(l) || !bkey_packed(r));
97 EBUG_ON(b->nr_key_bits != bkey_format_key_bits(f));
99 ret = __bkey_cmp_bits(high_word(f, l),
100 high_word(f, r),
101 b->nr_key_bits);
103 EBUG_ON(ret != bpos_cmp(bkey_unpack_pos(b, l),
104 bkey_unpack_pos(b, r)));
105 return ret;
108 static inline __pure __flatten
109 int bch2_bkey_cmp_packed_inlined(const struct btree *b,
110 const struct bkey_packed *l,
111 const struct bkey_packed *r)
113 struct bkey unpacked;
115 if (likely(bkey_packed(l) && bkey_packed(r)))
116 return __bch2_bkey_cmp_packed_format_checked_inlined(l, r, b);
118 if (bkey_packed(l)) {
119 __bkey_unpack_key_format_checked(b, &unpacked, l);
120 l = (void *) &unpacked;
121 } else if (bkey_packed(r)) {
122 __bkey_unpack_key_format_checked(b, &unpacked, r);
123 r = (void *) &unpacked;
126 return bpos_cmp(((struct bkey *) l)->p, ((struct bkey *) r)->p);
129 #endif /* _BCACHEFS_BKEY_CMP_H */