]>
Commit | Line | Data |
---|---|---|
b2441318 | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
d2a5f499 YS |
2 | #ifndef _H8300_BITOPS_H |
3 | #define _H8300_BITOPS_H | |
4 | ||
5 | /* | |
6 | * Copyright 1992, Linus Torvalds. | |
7 | * Copyright 2002, Yoshinori Sato | |
8 | */ | |
9 | ||
10 | #include <linux/compiler.h> | |
11 | ||
12 | #ifdef __KERNEL__ | |
13 | ||
14 | #ifndef _LINUX_BITOPS_H | |
15 | #error only <linux/bitops.h> can be included directly | |
16 | #endif | |
17 | ||
18 | /* | |
19 | * Function prototypes to keep gcc -Wall happy | |
20 | */ | |
21 | ||
22 | /* | |
23 | * ffz = Find First Zero in word. Undefined if no zero exists, | |
24 | * so code should check against ~0UL first.. | |
25 | */ | |
26 | static inline unsigned long ffz(unsigned long word) | |
27 | { | |
28 | unsigned long result; | |
29 | ||
30 | result = -1; | |
31 | __asm__("1:\n\t" | |
32 | "shlr.l %2\n\t" | |
33 | "adds #1,%0\n\t" | |
34 | "bcs 1b" | |
35 | : "=r"(result) | |
36 | : "0"(result), "r"(word)); | |
37 | return result; | |
38 | } | |
39 | ||
40 | #define H8300_GEN_BITOP(FNAME, OP) \ | |
41 | static inline void FNAME(int nr, volatile unsigned long *addr) \ | |
42 | { \ | |
43 | unsigned char *b_addr; \ | |
44 | unsigned char bit = nr & 7; \ | |
45 | \ | |
46 | b_addr = (unsigned char *)addr + ((nr >> 3) ^ 3); \ | |
47 | if (__builtin_constant_p(nr)) { \ | |
48 | __asm__(OP " %1,%0" : "+WU"(*b_addr) : "i"(nr & 7)); \ | |
49 | } else { \ | |
50 | __asm__(OP " %s1,%0" : "+WU"(*b_addr) : "r"(bit)); \ | |
51 | } \ | |
52 | } | |
53 | ||
54 | /* | |
55 | * clear_bit() doesn't provide any barrier for the compiler. | |
56 | */ | |
57 | #define smp_mb__before_clear_bit() barrier() | |
58 | #define smp_mb__after_clear_bit() barrier() | |
59 | ||
60 | H8300_GEN_BITOP(set_bit, "bset") | |
61 | H8300_GEN_BITOP(clear_bit, "bclr") | |
62 | H8300_GEN_BITOP(change_bit, "bnot") | |
63 | #define __set_bit(nr, addr) set_bit((nr), (addr)) | |
64 | #define __clear_bit(nr, addr) clear_bit((nr), (addr)) | |
65 | #define __change_bit(nr, addr) change_bit((nr), (addr)) | |
66 | ||
67 | #undef H8300_GEN_BITOP | |
68 | ||
69 | static inline int test_bit(int nr, const unsigned long *addr) | |
70 | { | |
71 | int ret = 0; | |
72 | unsigned char *b_addr; | |
73 | unsigned char bit = nr & 7; | |
74 | ||
75 | b_addr = (unsigned char *)addr + ((nr >> 3) ^ 3); | |
76 | if (__builtin_constant_p(nr)) { | |
77 | __asm__("bld %Z2,%1\n\t" | |
78 | "rotxl %0\n\t" | |
79 | : "=r"(ret) | |
80 | : "WU"(*b_addr), "i"(nr & 7), "0"(ret) : "cc"); | |
81 | } else { | |
82 | __asm__("btst %w2,%1\n\t" | |
83 | "beq 1f\n\t" | |
84 | "inc.l #1,%0\n" | |
85 | "1:" | |
86 | : "=r"(ret) | |
87 | : "WU"(*b_addr), "r"(bit), "0"(ret) : "cc"); | |
88 | } | |
89 | return ret; | |
90 | } | |
91 | ||
92 | #define __test_bit(nr, addr) test_bit(nr, addr) | |
93 | ||
94 | #define H8300_GEN_TEST_BITOP(FNNAME, OP) \ | |
95 | static inline int FNNAME(int nr, void *addr) \ | |
96 | { \ | |
97 | int retval = 0; \ | |
98 | char ccrsave; \ | |
99 | unsigned char *b_addr; \ | |
100 | unsigned char bit = nr & 7; \ | |
101 | \ | |
102 | b_addr = (unsigned char *)addr + ((nr >> 3) ^ 3); \ | |
103 | if (__builtin_constant_p(nr)) { \ | |
104 | __asm__("stc ccr,%s2\n\t" \ | |
105 | "orc #0x80,ccr\n\t" \ | |
106 | "bld %4,%1\n\t" \ | |
107 | OP " %4,%1\n\t" \ | |
108 | "rotxl.l %0\n\t" \ | |
109 | "ldc %s2,ccr" \ | |
110 | : "=r"(retval), "+WU" (*b_addr), "=&r"(ccrsave) \ | |
111 | : "0"(retval), "i"(nr & 7) : "cc"); \ | |
112 | } else { \ | |
113 | __asm__("stc ccr,%t3\n\t" \ | |
114 | "orc #0x80,ccr\n\t" \ | |
115 | "btst %s3,%1\n\t" \ | |
116 | OP " %s3,%1\n\t" \ | |
117 | "beq 1f\n\t" \ | |
118 | "inc.l #1,%0\n\t" \ | |
119 | "1:\n" \ | |
120 | "ldc %t3,ccr" \ | |
121 | : "=r"(retval), "+WU" (*b_addr) \ | |
122 | : "0" (retval), "r"(bit) : "cc"); \ | |
123 | } \ | |
124 | return retval; \ | |
125 | } \ | |
126 | \ | |
127 | static inline int __ ## FNNAME(int nr, void *addr) \ | |
128 | { \ | |
129 | int retval = 0; \ | |
130 | unsigned char *b_addr; \ | |
131 | unsigned char bit = nr & 7; \ | |
132 | \ | |
133 | b_addr = (unsigned char *)addr + ((nr >> 3) ^ 3); \ | |
134 | if (__builtin_constant_p(nr)) { \ | |
135 | __asm__("bld %3,%1\n\t" \ | |
136 | OP " %3,%1\n\t" \ | |
137 | "rotxl.l %0\n\t" \ | |
138 | : "=r"(retval), "+WU"(*b_addr) \ | |
139 | : "0" (retval), "i"(nr & 7)); \ | |
140 | } else { \ | |
141 | __asm__("btst %s3,%1\n\t" \ | |
142 | OP " %s3,%1\n\t" \ | |
143 | "beq 1f\n\t" \ | |
144 | "inc.l #1,%0\n\t" \ | |
145 | "1:" \ | |
146 | : "=r"(retval), "+WU"(*b_addr) \ | |
147 | : "0" (retval), "r"(bit)); \ | |
148 | } \ | |
149 | return retval; \ | |
150 | } | |
151 | ||
152 | H8300_GEN_TEST_BITOP(test_and_set_bit, "bset") | |
153 | H8300_GEN_TEST_BITOP(test_and_clear_bit, "bclr") | |
154 | H8300_GEN_TEST_BITOP(test_and_change_bit, "bnot") | |
155 | #undef H8300_GEN_TEST_BITOP | |
156 | ||
157 | #include <asm-generic/bitops/ffs.h> | |
158 | ||
159 | static inline unsigned long __ffs(unsigned long word) | |
160 | { | |
161 | unsigned long result; | |
162 | ||
163 | result = -1; | |
164 | __asm__("1:\n\t" | |
165 | "shlr.l %2\n\t" | |
166 | "adds #1,%0\n\t" | |
167 | "bcc 1b" | |
168 | : "=r" (result) | |
169 | : "0"(result), "r"(word)); | |
170 | return result; | |
171 | } | |
172 | ||
173 | #include <asm-generic/bitops/find.h> | |
174 | #include <asm-generic/bitops/sched.h> | |
175 | #include <asm-generic/bitops/hweight.h> | |
176 | #include <asm-generic/bitops/lock.h> | |
177 | #include <asm-generic/bitops/le.h> | |
178 | #include <asm-generic/bitops/ext2-atomic.h> | |
179 | ||
180 | #endif /* __KERNEL__ */ | |
181 | ||
182 | #include <asm-generic/bitops/fls.h> | |
183 | #include <asm-generic/bitops/__fls.h> | |
184 | #include <asm-generic/bitops/fls64.h> | |
185 | ||
186 | #endif /* _H8300_BITOPS_H */ |