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