2 * bitops.h --- Bitmap frobbing code. The byte swapping routines are
5 * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
8 * This file may be redistributed under the terms of the GNU Public
12 * i386 bitops operations taken from <asm/bitops.h>, Copyright 1992,
17 extern int ext2fs_set_bit(int nr,void * addr);
18 extern int ext2fs_clear_bit(int nr, void * addr);
19 extern int ext2fs_test_bit(int nr, const void * addr);
20 extern __u16 ext2fs_swab16(__u16 val);
21 extern __u32 ext2fs_swab32(__u32 val);
23 #ifdef WORDS_BIGENDIAN
24 #define ext2fs_cpu_to_le32(x) ext2fs_swab32((x))
25 #define ext2fs_le32_to_cpu(x) ext2fs_swab32((x))
26 #define ext2fs_cpu_to_le16(x) ext2fs_swab16((x))
27 #define ext2fs_le16_to_cpu(x) ext2fs_swab16((x))
28 #define ext2fs_cpu_to_be32(x) ((__u32)(x))
29 #define ext2fs_be32_to_cpu(x) ((__u32)(x))
30 #define ext2fs_cpu_to_be16(x) ((__u16)(x))
31 #define ext2fs_be16_to_cpu(x) ((__u16)(x))
33 #define ext2fs_cpu_to_le32(x) ((__u32)(x))
34 #define ext2fs_le32_to_cpu(x) ((__u32)(x))
35 #define ext2fs_cpu_to_le16(x) ((__u16)(x))
36 #define ext2fs_le16_to_cpu(x) ((__u16)(x))
37 #define ext2fs_cpu_to_be32(x) ext2fs_swab32((x))
38 #define ext2fs_be32_to_cpu(x) ext2fs_swab32((x))
39 #define ext2fs_cpu_to_be16(x) ext2fs_swab16((x))
40 #define ext2fs_be16_to_cpu(x) ext2fs_swab16((x))
44 * EXT2FS bitmap manipulation routines.
47 /* Support for sending warning messages from the inline subroutines */
48 extern const char *ext2fs_block_string;
49 extern const char *ext2fs_inode_string;
50 extern const char *ext2fs_mark_string;
51 extern const char *ext2fs_unmark_string;
52 extern const char *ext2fs_test_string;
53 extern void ext2fs_warn_bitmap(errcode_t errcode, unsigned long arg,
54 const char *description);
55 extern void ext2fs_warn_bitmap2(ext2fs_generic_bitmap bitmap,
56 int code, unsigned long arg);
58 extern int ext2fs_mark_block_bitmap(ext2fs_block_bitmap bitmap, blk_t block);
59 extern int ext2fs_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
61 extern int ext2fs_test_block_bitmap(ext2fs_block_bitmap bitmap, blk_t block);
63 extern int ext2fs_mark_inode_bitmap(ext2fs_inode_bitmap bitmap, ext2_ino_t inode);
64 extern int ext2fs_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
66 extern int ext2fs_test_inode_bitmap(ext2fs_inode_bitmap bitmap, ext2_ino_t inode);
68 extern void ext2fs_fast_mark_block_bitmap(ext2fs_block_bitmap bitmap,
70 extern void ext2fs_fast_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
72 extern int ext2fs_fast_test_block_bitmap(ext2fs_block_bitmap bitmap,
75 extern void ext2fs_fast_mark_inode_bitmap(ext2fs_inode_bitmap bitmap,
77 extern void ext2fs_fast_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
79 extern int ext2fs_fast_test_inode_bitmap(ext2fs_inode_bitmap bitmap,
81 extern blk_t ext2fs_get_block_bitmap_start(ext2fs_block_bitmap bitmap);
82 extern ext2_ino_t ext2fs_get_inode_bitmap_start(ext2fs_inode_bitmap bitmap);
83 extern blk_t ext2fs_get_block_bitmap_end(ext2fs_block_bitmap bitmap);
84 extern ext2_ino_t ext2fs_get_inode_bitmap_end(ext2fs_inode_bitmap bitmap);
86 extern void ext2fs_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
87 blk_t block, int num);
88 extern void ext2fs_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
89 blk_t block, int num);
90 extern int ext2fs_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
91 blk_t block, int num);
92 extern void ext2fs_fast_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
93 blk_t block, int num);
94 extern void ext2fs_fast_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
95 blk_t block, int num);
96 extern int ext2fs_fast_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
97 blk_t block, int num);
98 extern void ext2fs_set_bitmap_padding(ext2fs_generic_bitmap map);
100 /* These two routines moved to gen_bitmap.c */
101 extern int ext2fs_mark_generic_bitmap(ext2fs_generic_bitmap bitmap,
103 extern int ext2fs_unmark_generic_bitmap(ext2fs_generic_bitmap bitmap,
106 * The inline routines themselves...
108 * If NO_INLINE_FUNCS is defined, then we won't try to do inline
109 * functions at all; they will be included as normal functions in
112 #ifdef NO_INLINE_FUNCS
113 #if (defined(__GNUC__) && (defined(__i386__) || defined(__i486__) || \
114 defined(__i586__) || defined(__mc68000__) || \
116 /* This prevents bitops.c from trying to include the C */
117 /* function version of these functions */
118 #define _EXT2_HAVE_ASM_BITOPS_
120 #endif /* NO_INLINE_FUNCS */
122 #if (defined(INCLUDE_INLINE_FUNCS) || !defined(NO_INLINE_FUNCS))
123 #ifdef INCLUDE_INLINE_FUNCS
124 #define _INLINE_ extern
127 #define _INLINE_ extern __inline__
128 #else /* For Watcom C */
129 #define _INLINE_ extern inline
133 #if ((defined __GNUC__) && !defined(_EXT2_USE_C_VERSIONS_) && \
134 (defined(__i386__) || defined(__i486__) || defined(__i586__)))
136 #define _EXT2_HAVE_ASM_BITOPS_
137 #define _EXT2_HAVE_ASM_SWAB_
138 #define _EXT2_HAVE_ASM_FINDBIT_
141 * These are done by inline assembly for speed reasons.....
143 * All bitoperations return 0 if the bit was cleared before the
144 * operation and != 0 if it was not. Bit 0 is the LSB of addr; bit 32
145 * is the LSB of (addr+1).
149 * Some hacks to defeat gcc over-optimizations..
151 struct __dummy_h { unsigned long a[100]; };
152 #define EXT2FS_ADDR (*(struct __dummy_h *) addr)
153 #define EXT2FS_CONST_ADDR (*(const struct __dummy_h *) addr)
155 _INLINE_ int ext2fs_set_bit(int nr, void * addr)
159 __asm__ __volatile__("btsl %2,%1\n\tsbbl %0,%0"
160 :"=r" (oldbit),"=m" (EXT2FS_ADDR)
165 _INLINE_ int ext2fs_clear_bit(int nr, void * addr)
169 __asm__ __volatile__("btrl %2,%1\n\tsbbl %0,%0"
170 :"=r" (oldbit),"=m" (EXT2FS_ADDR)
175 _INLINE_ int ext2fs_test_bit(int nr, const void * addr)
179 __asm__ __volatile__("btl %2,%1\n\tsbbl %0,%0"
181 :"m" (EXT2FS_CONST_ADDR),"r" (nr));
186 _INLINE_ int ext2fs_find_first_bit_set(void * addr, unsigned size)
193 /* This looks at memory. Mark it volatile to tell gcc not to move it around */
194 __asm__ __volatile__(
196 "xorl %%eax,%%eax\n\t"
197 "xorl %%edx,%%edx\n\t"
200 "movl -4(%%edi),%%eax\n\t"
203 "1:\tsubl %%esi,%%edi\n\t"
206 :"=d" (res), "=&c" (d0), "=&D" (d1), "=&a" (d2)
207 :"1" ((size + 31) >> 5), "2" (addr), "S" (addr));
211 _INLINE_ int ext2fs_find_next_bit_set (void * addr, int size, int offset)
213 unsigned long * p = ((unsigned long *) addr) + (offset >> 5);
214 int set = 0, bit = offset & 31, res;
218 * Look for zero in first byte
220 __asm__("bsfl %1,%0\n\t"
226 if (set < (32 - bit))
232 * No bit found yet, search remaining full bytes for a bit
234 res = ext2fs_find_first_bit_set(p, size - 32 * (p - (unsigned long *) addr));
235 return (offset + set + res);
239 #ifdef EXT2FS_ENABLE_SWAPFS
240 _INLINE_ __u32 ext2fs_swab32(__u32 val)
242 #ifdef EXT2FS_REQUIRE_486
243 __asm__("bswap %0" : "=r" (val) : "0" (val));
245 __asm__("xchgb %b0,%h0\n\t" /* swap lower bytes */
246 "rorl $16,%0\n\t" /* swap words */
247 "xchgb %b0,%h0" /* swap higher bytes */
254 _INLINE_ __u16 ext2fs_swab16(__u16 val)
256 __asm__("xchgb %b0,%h0" /* swap bytes */ \
269 #define _EXT2_HAVE_ASM_BITOPS_
271 _INLINE_ int ext2fs_set_bit(int nr,void * addr)
275 __asm__ __volatile__ ("bfset %2@{%1:#1}; sne %0"
276 : "=d" (retval) : "d" (nr^7), "a" (addr));
281 _INLINE_ int ext2fs_clear_bit(int nr, void * addr)
285 __asm__ __volatile__ ("bfclr %2@{%1:#1}; sne %0"
286 : "=d" (retval) : "d" (nr^7), "a" (addr));
291 _INLINE_ int ext2fs_test_bit(int nr, const void * addr)
295 __asm__ __volatile__ ("bftst %2@{%1:#1}; sne %0"
296 : "=d" (retval) : "d" (nr^7), "a" (addr));
301 #endif /* __mc68000__ */
305 #define _EXT2_HAVE_ASM_BITOPS_
307 #ifndef EXT2_OLD_BITOPS
310 * Do the bitops so that we are compatible with the standard i386
314 _INLINE_ int ext2fs_set_bit(int nr,void * addr)
318 unsigned char *ADDR = (unsigned char *) addr;
321 mask = 1 << (nr & 0x07);
322 __asm__ __volatile__("ldub [%0], %%g6\n\t"
323 "or %%g6, %2, %%g5\n\t"
327 : "0" (ADDR), "r" (mask)
332 unsigned char *ADDR = (unsigned char *) addr;
335 mask = 1 << (nr & 0x07);
336 retval = (mask & *ADDR) != 0;
342 _INLINE_ int ext2fs_clear_bit(int nr, void * addr)
346 unsigned char *ADDR = (unsigned char *) addr;
349 mask = 1 << (nr & 0x07);
350 __asm__ __volatile__("ldub [%0], %%g6\n\t"
351 "andn %%g6, %2, %%g5\n\t"
355 : "0" (ADDR), "r" (mask)
361 unsigned char *ADDR = (unsigned char *) addr;
364 mask = 1 << (nr & 0x07);
365 retval = (mask & *ADDR) != 0;
371 _INLINE_ int ext2fs_test_bit(int nr, const void * addr)
374 const unsigned char *ADDR = (const unsigned char *) addr;
377 mask = 1 << (nr & 0x07);
378 return ((mask & *ADDR) != 0);
383 /* Do things the old, unplesant way. */
385 _INLINE_ int ext2fs_set_bit(int nr, void *addr)
388 unsigned long *ADDR = (unsigned long *) addr;
391 mask = 1 << (nr & 31);
392 retval = ((mask & *ADDR) != 0);
397 _INLINE_ int ext2fs_clear_bit(int nr, void *addr)
400 unsigned long *ADDR = (unsigned long *) addr;
403 mask = 1 << (nr & 31);
404 retval = ((mask & *ADDR) != 0);
409 _INLINE_ int ext2fs_test_bit(int nr, const void *addr)
412 const unsigned long *ADDR = (const unsigned long *) addr;
415 mask = 1 << (nr & 31);
416 return ((mask & *ADDR) != 0);
420 #endif /* __sparc__ */
422 #if !defined(_EXT2_HAVE_ASM_SWAB_) && defined(EXT2FS_ENABLE_SWAPFS)
424 _INLINE_ __u16 ext2fs_swab16(__u16 val)
426 return (val >> 8) | (val << 8);
429 _INLINE_ __u32 ext2fs_swab32(__u32 val)
431 return ((val>>24) | ((val>>8)&0xFF00) |
432 ((val<<8)&0xFF0000) | (val<<24));
435 #endif /* !_EXT2_HAVE_ASM_SWAB */
437 #if !defined(_EXT2_HAVE_ASM_FINDBIT_)
438 _INLINE_ int ext2fs_find_first_bit_set(void * addr, unsigned size)
440 char *cp = (unsigned char *) addr;
446 while ((size > res) && (*cp == 0)) {
457 _INLINE_ int ext2fs_find_next_bit_set (void * addr, int size, int offset)
460 int set = 0, bit = offset & 7, res = 0, d0;
463 p = ((unsigned char *) addr) + res;
466 set = ffs(*p & ~((1 << bit) - 1));
468 return (offset & ~7) + set - 1;
472 while ((size > res) && (*p == 0)) {
480 return (res + d0 - 1);
484 _INLINE_ int ext2fs_test_generic_bitmap(ext2fs_generic_bitmap bitmap,
487 _INLINE_ int ext2fs_test_generic_bitmap(ext2fs_generic_bitmap bitmap,
490 if ((bitno < bitmap->start) || (bitno > bitmap->end)) {
491 ext2fs_warn_bitmap2(bitmap, EXT2FS_TEST_ERROR, bitno);
494 return ext2fs_test_bit(bitno - bitmap->start, bitmap->bitmap);
497 _INLINE_ int ext2fs_mark_block_bitmap(ext2fs_block_bitmap bitmap,
500 return ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap)
505 _INLINE_ int ext2fs_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
508 return ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap,
512 _INLINE_ int ext2fs_test_block_bitmap(ext2fs_block_bitmap bitmap,
515 return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap) bitmap,
519 _INLINE_ int ext2fs_mark_inode_bitmap(ext2fs_inode_bitmap bitmap,
522 return ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap) bitmap,
526 _INLINE_ int ext2fs_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
529 return ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap,
533 _INLINE_ int ext2fs_test_inode_bitmap(ext2fs_inode_bitmap bitmap,
536 return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap) bitmap,
540 _INLINE_ void ext2fs_fast_mark_block_bitmap(ext2fs_block_bitmap bitmap,
543 #ifdef EXT2FS_DEBUG_FAST_OPS
544 if ((block < bitmap->start) || (block > bitmap->end)) {
545 ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_MARK, block,
546 bitmap->description);
550 ext2fs_set_bit(block - bitmap->start, bitmap->bitmap);
553 _INLINE_ void ext2fs_fast_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
556 #ifdef EXT2FS_DEBUG_FAST_OPS
557 if ((block < bitmap->start) || (block > bitmap->end)) {
558 ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_UNMARK,
559 block, bitmap->description);
563 ext2fs_clear_bit(block - bitmap->start, bitmap->bitmap);
566 _INLINE_ int ext2fs_fast_test_block_bitmap(ext2fs_block_bitmap bitmap,
569 #ifdef EXT2FS_DEBUG_FAST_OPS
570 if ((block < bitmap->start) || (block > bitmap->end)) {
571 ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_TEST,
572 block, bitmap->description);
576 return ext2fs_test_bit(block - bitmap->start, bitmap->bitmap);
579 _INLINE_ void ext2fs_fast_mark_inode_bitmap(ext2fs_inode_bitmap bitmap,
582 #ifdef EXT2FS_DEBUG_FAST_OPS
583 if ((inode < bitmap->start) || (inode > bitmap->end)) {
584 ext2fs_warn_bitmap(EXT2_ET_BAD_INODE_MARK,
585 inode, bitmap->description);
589 ext2fs_set_bit(inode - bitmap->start, bitmap->bitmap);
592 _INLINE_ void ext2fs_fast_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
595 #ifdef EXT2FS_DEBUG_FAST_OPS
596 if ((inode < bitmap->start) || (inode > bitmap->end)) {
597 ext2fs_warn_bitmap(EXT2_ET_BAD_INODE_UNMARK,
598 inode, bitmap->description);
602 ext2fs_clear_bit(inode - bitmap->start, bitmap->bitmap);
605 _INLINE_ int ext2fs_fast_test_inode_bitmap(ext2fs_inode_bitmap bitmap,
608 #ifdef EXT2FS_DEBUG_FAST_OPS
609 if ((inode < bitmap->start) || (inode > bitmap->end)) {
610 ext2fs_warn_bitmap(EXT2_ET_BAD_INODE_TEST,
611 inode, bitmap->description);
615 return ext2fs_test_bit(inode - bitmap->start, bitmap->bitmap);
618 _INLINE_ blk_t ext2fs_get_block_bitmap_start(ext2fs_block_bitmap bitmap)
620 return bitmap->start;
623 _INLINE_ ext2_ino_t ext2fs_get_inode_bitmap_start(ext2fs_inode_bitmap bitmap)
625 return bitmap->start;
628 _INLINE_ blk_t ext2fs_get_block_bitmap_end(ext2fs_block_bitmap bitmap)
633 _INLINE_ ext2_ino_t ext2fs_get_inode_bitmap_end(ext2fs_inode_bitmap bitmap)
638 _INLINE_ int ext2fs_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
639 blk_t block, int num)
643 if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
644 ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_TEST,
645 block, bitmap->description);
648 for (i=0; i < num; i++) {
649 if (ext2fs_fast_test_block_bitmap(bitmap, block+i))
655 _INLINE_ int ext2fs_fast_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
656 blk_t block, int num)
660 #ifdef EXT2FS_DEBUG_FAST_OPS
661 if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
662 ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_TEST,
663 block, bitmap->description);
667 for (i=0; i < num; i++) {
668 if (ext2fs_fast_test_block_bitmap(bitmap, block+i))
674 _INLINE_ void ext2fs_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
675 blk_t block, int num)
679 if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
680 ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_MARK, block,
681 bitmap->description);
684 for (i=0; i < num; i++)
685 ext2fs_set_bit(block + i - bitmap->start, bitmap->bitmap);
688 _INLINE_ void ext2fs_fast_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
689 blk_t block, int num)
693 #ifdef EXT2FS_DEBUG_FAST_OPS
694 if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
695 ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_MARK, block,
696 bitmap->description);
700 for (i=0; i < num; i++)
701 ext2fs_set_bit(block + i - bitmap->start, bitmap->bitmap);
704 _INLINE_ void ext2fs_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
705 blk_t block, int num)
709 if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
710 ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_UNMARK, block,
711 bitmap->description);
714 for (i=0; i < num; i++)
715 ext2fs_clear_bit(block + i - bitmap->start, bitmap->bitmap);
718 _INLINE_ void ext2fs_fast_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
719 blk_t block, int num)
723 #ifdef EXT2FS_DEBUG_FAST_OPS
724 if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
725 ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_UNMARK, block,
726 bitmap->description);
730 for (i=0; i < num; i++)
731 ext2fs_clear_bit(block + i - bitmap->start, bitmap->bitmap);