Whamcloud - gitweb
7c3f056d6f73b6ad975f66782ec3c173afd72156
[tools/e2fsprogs.git] / lib / ext2fs / bitops.h
1 /*
2  * bitops.h --- Bitmap frobbing code.  The byte swapping routines are
3  *      also included here.
4  *
5  * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
6  *
7  * %Begin-Header%
8  * This file may be redistributed under the terms of the GNU Public
9  * License.
10  * %End-Header%
11  *
12  * i386 bitops operations taken from <asm/bitops.h>, Copyright 1992,
13  * Linus Torvalds.
14  */
15
16
17 extern int ext2fs_set_bit(unsigned int nr,void * addr);
18 extern int ext2fs_clear_bit(unsigned int nr, void * addr);
19 extern int ext2fs_test_bit(unsigned int nr, const void * addr);
20 extern void ext2fs_fast_set_bit(unsigned int nr,void * addr);
21 extern void ext2fs_fast_clear_bit(unsigned int nr, void * addr);
22 extern int ext2fs_set_bit64(__u64 nr,void * addr);
23 extern int ext2fs_clear_bit64(__u64 nr, void * addr);
24 extern int ext2fs_test_bit64(__u64 nr, const void * addr);
25 extern void ext2fs_fast_set_bit64(__u64 nr,void * addr);
26 extern void ext2fs_fast_clear_bit64(__u64 nr, void * addr);
27 extern __u16 ext2fs_swab16(__u16 val);
28 extern __u32 ext2fs_swab32(__u32 val);
29 extern __u64 ext2fs_swab64(__u64 val);
30
31 #ifdef WORDS_BIGENDIAN
32 #define ext2fs_cpu_to_le64(x) ext2fs_swab64((x))
33 #define ext2fs_le64_to_cpu(x) ext2fs_swab64((x))
34 #define ext2fs_cpu_to_le32(x) ext2fs_swab32((x))
35 #define ext2fs_le32_to_cpu(x) ext2fs_swab32((x))
36 #define ext2fs_cpu_to_le16(x) ext2fs_swab16((x))
37 #define ext2fs_le16_to_cpu(x) ext2fs_swab16((x))
38 #define ext2fs_cpu_to_be32(x) ((__u32)(x))
39 #define ext2fs_be32_to_cpu(x) ((__u32)(x))
40 #define ext2fs_cpu_to_be16(x) ((__u16)(x))
41 #define ext2fs_be16_to_cpu(x) ((__u16)(x))
42 #else
43 #define ext2fs_cpu_to_le64(x) ((__u64)(x))
44 #define ext2fs_le64_to_cpu(x) ((__u64)(x))
45 #define ext2fs_cpu_to_le32(x) ((__u32)(x))
46 #define ext2fs_le32_to_cpu(x) ((__u32)(x))
47 #define ext2fs_cpu_to_le16(x) ((__u16)(x))
48 #define ext2fs_le16_to_cpu(x) ((__u16)(x))
49 #define ext2fs_cpu_to_be32(x) ext2fs_swab32((x))
50 #define ext2fs_be32_to_cpu(x) ext2fs_swab32((x))
51 #define ext2fs_cpu_to_be16(x) ext2fs_swab16((x))
52 #define ext2fs_be16_to_cpu(x) ext2fs_swab16((x))
53 #endif
54
55 /*
56  * EXT2FS bitmap manipulation routines.
57  */
58
59 /* Support for sending warning messages from the inline subroutines */
60 extern const char *ext2fs_block_string;
61 extern const char *ext2fs_inode_string;
62 extern const char *ext2fs_mark_string;
63 extern const char *ext2fs_unmark_string;
64 extern const char *ext2fs_test_string;
65 extern void ext2fs_warn_bitmap(errcode_t errcode, unsigned long arg,
66                                const char *description);
67 extern void ext2fs_warn_bitmap2(ext2fs_generic_bitmap bitmap,
68                                 int code, unsigned long arg);
69
70 extern int ext2fs_mark_block_bitmap(ext2fs_block_bitmap bitmap, blk_t block);
71 extern int ext2fs_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
72                                        blk_t block);
73 extern int ext2fs_test_block_bitmap(ext2fs_block_bitmap bitmap, blk_t block);
74
75 extern int ext2fs_mark_inode_bitmap(ext2fs_inode_bitmap bitmap, ext2_ino_t inode);
76 extern int ext2fs_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
77                                        ext2_ino_t inode);
78 extern int ext2fs_test_inode_bitmap(ext2fs_inode_bitmap bitmap, ext2_ino_t inode);
79
80 extern void ext2fs_fast_mark_block_bitmap(ext2fs_block_bitmap bitmap,
81                                           blk_t block);
82 extern void ext2fs_fast_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
83                                             blk_t block);
84 extern int ext2fs_fast_test_block_bitmap(ext2fs_block_bitmap bitmap,
85                                          blk_t block);
86
87 extern void ext2fs_fast_mark_inode_bitmap(ext2fs_inode_bitmap bitmap,
88                                           ext2_ino_t inode);
89 extern void ext2fs_fast_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
90                                             ext2_ino_t inode);
91 extern int ext2fs_fast_test_inode_bitmap(ext2fs_inode_bitmap bitmap,
92                                          ext2_ino_t inode);
93 extern blk_t ext2fs_get_block_bitmap_start(ext2fs_block_bitmap bitmap);
94 extern ext2_ino_t ext2fs_get_inode_bitmap_start(ext2fs_inode_bitmap bitmap);
95 extern blk_t ext2fs_get_block_bitmap_end(ext2fs_block_bitmap bitmap);
96 extern ext2_ino_t ext2fs_get_inode_bitmap_end(ext2fs_inode_bitmap bitmap);
97
98 extern void ext2fs_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
99                                            blk_t block, int num);
100 extern void ext2fs_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
101                                              blk_t block, int num);
102 extern int ext2fs_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
103                                           blk_t block, int num);
104 extern int ext2fs_test_inode_bitmap_range(ext2fs_inode_bitmap bitmap,
105                                           ino_t inode, int num);
106 extern void ext2fs_fast_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
107                                                 blk_t block, int num);
108 extern void ext2fs_fast_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
109                                                   blk_t block, int num);
110 extern int ext2fs_fast_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
111                                                blk_t block, int num);
112 extern void ext2fs_set_bitmap_padding(ext2fs_generic_bitmap map);
113
114 /* These routines moved to gen_bitmap.c */
115 extern int ext2fs_mark_generic_bitmap(ext2fs_generic_bitmap bitmap,
116                                          __u32 bitno);
117 extern int ext2fs_unmark_generic_bitmap(ext2fs_generic_bitmap bitmap,
118                                            blk_t bitno);
119 extern int ext2fs_test_generic_bitmap(ext2fs_generic_bitmap bitmap,
120                                       blk_t bitno);
121 extern int ext2fs_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
122                                           blk_t block, int num);
123 extern __u32 ext2fs_get_generic_bitmap_start(ext2fs_generic_bitmap bitmap);
124 extern __u32 ext2fs_get_generic_bitmap_end(ext2fs_generic_bitmap bitmap);
125
126 /*
127  * The inline routines themselves...
128  *
129  * If NO_INLINE_FUNCS is defined, then we won't try to do inline
130  * functions at all; they will be included as normal functions in
131  * inline.c
132  */
133 #ifdef NO_INLINE_FUNCS
134 #if (defined(__GNUC__) && (defined(__i386__) || defined(__i486__) || \
135                            defined(__i586__) || defined(__mc68000__)))
136         /* This prevents bitops.c from trying to include the C */
137         /* function version of these functions */
138 #define _EXT2_HAVE_ASM_BITOPS_
139 #endif
140 #endif /* NO_INLINE_FUNCS */
141
142 #if (defined(INCLUDE_INLINE_FUNCS) || !defined(NO_INLINE_FUNCS))
143 #ifdef INCLUDE_INLINE_FUNCS
144 #define _INLINE_ extern
145 #else
146 #ifdef __GNUC__
147 #define _INLINE_ extern __inline__
148 #else                           /* For Watcom C */
149 #define _INLINE_ extern inline
150 #endif
151 #endif
152
153 /*
154  * Fast bit set/clear functions that doesn't need to return the
155  * previous bit value.
156  */
157
158 _INLINE_ void ext2fs_fast_set_bit(unsigned int nr,void * addr)
159 {
160         unsigned char   *ADDR = (unsigned char *) addr;
161
162         ADDR += nr >> 3;
163         *ADDR |= (1 << (nr & 0x07));
164 }
165
166 _INLINE_ void ext2fs_fast_clear_bit(unsigned int nr, void * addr)
167 {
168         unsigned char   *ADDR = (unsigned char *) addr;
169
170         ADDR += nr >> 3;
171         *ADDR &= ~(1 << (nr & 0x07));
172 }
173
174
175 _INLINE_ void ext2fs_fast_set_bit64(__u64 nr, void * addr)
176 {
177         unsigned char   *ADDR = (unsigned char *) addr;
178
179         ADDR += nr >> 3;
180         *ADDR |= (1 << (nr & 0x07));
181 }
182
183 _INLINE_ void ext2fs_fast_clear_bit64(__u64 nr, void * addr)
184 {
185         unsigned char   *ADDR = (unsigned char *) addr;
186
187         ADDR += nr >> 3;
188         *ADDR &= ~(1 << (nr & 0x07));
189 }
190
191
192 #if ((defined __GNUC__) && !defined(_EXT2_USE_C_VERSIONS_) && \
193      (defined(__i386__) || defined(__i486__) || defined(__i586__)))
194
195 #define _EXT2_HAVE_ASM_BITOPS_
196 #define _EXT2_HAVE_ASM_SWAB_
197
198 /*
199  * These are done by inline assembly for speed reasons.....
200  *
201  * All bitoperations return 0 if the bit was cleared before the
202  * operation and != 0 if it was not.  Bit 0 is the LSB of addr; bit 32
203  * is the LSB of (addr+1).
204  */
205
206 /*
207  * Some hacks to defeat gcc over-optimizations..
208  */
209 struct __dummy_h { unsigned long a[100]; };
210 #define EXT2FS_ADDR (*(struct __dummy_h *) addr)
211 #define EXT2FS_CONST_ADDR (*(const struct __dummy_h *) addr)
212
213 _INLINE_ int ext2fs_set_bit(unsigned int nr, void * addr)
214 {
215         int oldbit;
216
217         addr = (void *) (((unsigned char *) addr) + (nr >> 3));
218         __asm__ __volatile__("btsl %2,%1\n\tsbbl %0,%0"
219                 :"=r" (oldbit),"+m" (EXT2FS_ADDR)
220                 :"r" (nr & 7));
221         return oldbit;
222 }
223
224 _INLINE_ int ext2fs_clear_bit(unsigned int nr, void * addr)
225 {
226         int oldbit;
227
228         addr = (void *) (((unsigned char *) addr) + (nr >> 3));
229         __asm__ __volatile__("btrl %2,%1\n\tsbbl %0,%0"
230                 :"=r" (oldbit),"+m" (EXT2FS_ADDR)
231                 :"r" (nr & 7));
232         return oldbit;
233 }
234
235 _INLINE_ int ext2fs_test_bit(unsigned int nr, const void * addr)
236 {
237         int oldbit;
238
239         addr = (const void *) (((const unsigned char *) addr) + (nr >> 3));
240         __asm__ __volatile__("btl %2,%1\n\tsbbl %0,%0"
241                 :"=r" (oldbit)
242                 :"m" (EXT2FS_CONST_ADDR),"r" (nr & 7));
243         return oldbit;
244 }
245
246 _INLINE_ __u32 ext2fs_swab32(__u32 val)
247 {
248 #ifdef EXT2FS_REQUIRE_486
249         __asm__("bswap %0" : "=r" (val) : "0" (val));
250 #else
251         __asm__("xchgb %b0,%h0\n\t"     /* swap lower bytes     */
252                 "rorl $16,%0\n\t"       /* swap words           */
253                 "xchgb %b0,%h0"         /* swap higher bytes    */
254                 :"=q" (val)
255                 : "0" (val));
256 #endif
257         return val;
258 }
259
260 _INLINE_ __u16 ext2fs_swab16(__u16 val)
261 {
262         __asm__("xchgb %b0,%h0"         /* swap bytes           */ \
263                 : "=q" (val) \
264                 :  "0" (val)); \
265                 return val;
266 }
267
268 #undef EXT2FS_ADDR
269
270 #endif  /* i386 */
271
272 #if ((defined __GNUC__) && !defined(_EXT2_USE_C_VERSIONS_) && \
273      (defined(__mc68000__)))
274
275 #define _EXT2_HAVE_ASM_BITOPS_
276
277 _INLINE_ int ext2fs_set_bit(unsigned int nr,void * addr)
278 {
279         char retval;
280
281         __asm__ __volatile__ ("bfset %2@{%1:#1}; sne %0"
282              : "=d" (retval) : "d" (nr^7), "a" (addr));
283
284         return retval;
285 }
286
287 _INLINE_ int ext2fs_clear_bit(unsigned int nr, void * addr)
288 {
289         char retval;
290
291         __asm__ __volatile__ ("bfclr %2@{%1:#1}; sne %0"
292              : "=d" (retval) : "d" (nr^7), "a" (addr));
293
294         return retval;
295 }
296
297 _INLINE_ int ext2fs_test_bit(unsigned int nr, const void * addr)
298 {
299         char retval;
300
301         __asm__ __volatile__ ("bftst %2@{%1:#1}; sne %0"
302              : "=d" (retval) : "d" (nr^7), "a" (addr));
303
304         return retval;
305 }
306
307 #endif /* __mc68000__ */
308
309
310 #if !defined(_EXT2_HAVE_ASM_SWAB_)
311
312 _INLINE_ __u16 ext2fs_swab16(__u16 val)
313 {
314         return (val >> 8) | (val << 8);
315 }
316
317 _INLINE_ __u32 ext2fs_swab32(__u32 val)
318 {
319         return ((val>>24) | ((val>>8)&0xFF00) |
320                 ((val<<8)&0xFF0000) | (val<<24));
321 }
322
323 #endif /* !_EXT2_HAVE_ASM_SWAB */
324
325 _INLINE_ __u64 ext2fs_swab64(__u64 val)
326 {
327         return (ext2fs_swab32(val >> 32) |
328                 (((__u64)ext2fs_swab32(val & 0xFFFFFFFFUL)) << 32));
329 }
330
331 _INLINE_ int ext2fs_mark_block_bitmap(ext2fs_block_bitmap bitmap,
332                                        blk_t block)
333 {
334         return ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap) bitmap,
335                                           block);
336 }
337
338 _INLINE_ int ext2fs_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
339                                          blk_t block)
340 {
341         return ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap,
342                                             block);
343 }
344
345 _INLINE_ int ext2fs_test_block_bitmap(ext2fs_block_bitmap bitmap,
346                                        blk_t block)
347 {
348         return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap) bitmap,
349                                           block);
350 }
351
352 _INLINE_ int ext2fs_mark_inode_bitmap(ext2fs_inode_bitmap bitmap,
353                                        ext2_ino_t inode)
354 {
355         return ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap) bitmap,
356                                           inode);
357 }
358
359 _INLINE_ int ext2fs_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
360                                          ext2_ino_t inode)
361 {
362         return ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap,
363                                      inode);
364 }
365
366 _INLINE_ int ext2fs_test_inode_bitmap(ext2fs_inode_bitmap bitmap,
367                                        ext2_ino_t inode)
368 {
369         return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap) bitmap,
370                                           inode);
371 }
372
373 _INLINE_ void ext2fs_fast_mark_block_bitmap(ext2fs_block_bitmap bitmap,
374                                             blk_t block)
375 {
376         ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap) bitmap, block);
377 }
378
379 _INLINE_ void ext2fs_fast_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
380                                               blk_t block)
381 {
382         ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap, block);
383 }
384
385 _INLINE_ int ext2fs_fast_test_block_bitmap(ext2fs_block_bitmap bitmap,
386                                             blk_t block)
387 {
388         return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap) bitmap,
389                                           block);
390 }
391
392 _INLINE_ void ext2fs_fast_mark_inode_bitmap(ext2fs_inode_bitmap bitmap,
393                                             ext2_ino_t inode)
394 {
395         ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap) bitmap, inode);
396 }
397
398 _INLINE_ void ext2fs_fast_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
399                                               ext2_ino_t inode)
400 {
401         ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap, inode);
402 }
403
404 _INLINE_ int ext2fs_fast_test_inode_bitmap(ext2fs_inode_bitmap bitmap,
405                                            ext2_ino_t inode)
406 {
407         return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap) bitmap,
408                                           inode);
409 }
410
411 _INLINE_ blk_t ext2fs_get_block_bitmap_start(ext2fs_block_bitmap bitmap)
412 {
413         return ext2fs_get_generic_bitmap_start((ext2fs_generic_bitmap) bitmap);
414 }
415
416 _INLINE_ ext2_ino_t ext2fs_get_inode_bitmap_start(ext2fs_inode_bitmap bitmap)
417 {
418         return ext2fs_get_generic_bitmap_start((ext2fs_generic_bitmap) bitmap);
419 }
420
421 _INLINE_ blk_t ext2fs_get_block_bitmap_end(ext2fs_block_bitmap bitmap)
422 {
423         return ext2fs_get_generic_bitmap_end((ext2fs_generic_bitmap) bitmap);
424 }
425
426 _INLINE_ ext2_ino_t ext2fs_get_inode_bitmap_end(ext2fs_inode_bitmap bitmap)
427 {
428         return ext2fs_get_generic_bitmap_end((ext2fs_generic_bitmap) bitmap);
429 }
430
431 _INLINE_ int ext2fs_fast_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
432                                                  blk_t block, int num)
433 {
434         return ext2fs_test_block_bitmap_range(bitmap, block, num);
435 }
436
437 _INLINE_ void ext2fs_fast_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
438                                                   blk_t block, int num)
439 {
440         ext2fs_mark_block_bitmap_range(bitmap, block, num);
441 }
442
443 _INLINE_ void ext2fs_fast_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
444                                                     blk_t block, int num)
445 {
446         ext2fs_unmark_block_bitmap_range(bitmap, block, num);
447 }
448 #undef _INLINE_
449 #endif
450