blob: 6344d06390b9fea57456b694cdff7a52dc99b910 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/* bitops.h: bit operations for the Fujitsu FR-V CPUs
2 *
3 * For an explanation of how atomic ops work in this arch, see:
4 * Documentation/fujitsu/frv/atomic-ops.txt
5 *
6 * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
7 * Written by David Howells (dhowells@redhat.com)
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version
12 * 2 of the License, or (at your option) any later version.
13 */
14#ifndef _ASM_BITOPS_H
15#define _ASM_BITOPS_H
16
17#include <linux/config.h>
18#include <linux/compiler.h>
19#include <asm/byteorder.h>
20#include <asm/system.h>
21#include <asm/atomic.h>
22
23#ifdef __KERNEL__
24
Akinobu Mita1f6d7a92006-03-26 01:39:22 -080025#include <asm-generic/bitops/ffz.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070026
27/*
28 * clear_bit() doesn't provide any barrier for the compiler.
29 */
30#define smp_mb__before_clear_bit() barrier()
31#define smp_mb__after_clear_bit() barrier()
32
33static inline int test_and_clear_bit(int nr, volatile void *addr)
34{
35 volatile unsigned long *ptr = addr;
36 unsigned long mask = 1UL << (nr & 31);
37 ptr += nr >> 5;
38 return (atomic_test_and_ANDNOT_mask(mask, ptr) & mask) != 0;
39}
40
41static inline int test_and_set_bit(int nr, volatile void *addr)
42{
43 volatile unsigned long *ptr = addr;
44 unsigned long mask = 1UL << (nr & 31);
45 ptr += nr >> 5;
46 return (atomic_test_and_OR_mask(mask, ptr) & mask) != 0;
47}
48
49static inline int test_and_change_bit(int nr, volatile void *addr)
50{
51 volatile unsigned long *ptr = addr;
52 unsigned long mask = 1UL << (nr & 31);
53 ptr += nr >> 5;
54 return (atomic_test_and_XOR_mask(mask, ptr) & mask) != 0;
55}
56
57static inline void clear_bit(int nr, volatile void *addr)
58{
59 test_and_clear_bit(nr, addr);
60}
61
62static inline void set_bit(int nr, volatile void *addr)
63{
64 test_and_set_bit(nr, addr);
65}
66
67static inline void change_bit(int nr, volatile void * addr)
68{
69 test_and_change_bit(nr, addr);
70}
71
72static inline void __clear_bit(int nr, volatile void * addr)
73{
74 volatile unsigned long *a = addr;
75 int mask;
76
77 a += nr >> 5;
78 mask = 1 << (nr & 31);
79 *a &= ~mask;
80}
81
82static inline void __set_bit(int nr, volatile void * addr)
83{
84 volatile unsigned long *a = addr;
85 int mask;
86
87 a += nr >> 5;
88 mask = 1 << (nr & 31);
89 *a |= mask;
90}
91
92static inline void __change_bit(int nr, volatile void *addr)
93{
94 volatile unsigned long *a = addr;
95 int mask;
96
97 a += nr >> 5;
98 mask = 1 << (nr & 31);
99 *a ^= mask;
100}
101
102static inline int __test_and_clear_bit(int nr, volatile void * addr)
103{
104 volatile unsigned long *a = addr;
105 int mask, retval;
106
107 a += nr >> 5;
108 mask = 1 << (nr & 31);
109 retval = (mask & *a) != 0;
110 *a &= ~mask;
111 return retval;
112}
113
114static inline int __test_and_set_bit(int nr, volatile void * addr)
115{
116 volatile unsigned long *a = addr;
117 int mask, retval;
118
119 a += nr >> 5;
120 mask = 1 << (nr & 31);
121 retval = (mask & *a) != 0;
122 *a |= mask;
123 return retval;
124}
125
126static inline int __test_and_change_bit(int nr, volatile void * addr)
127{
128 volatile unsigned long *a = addr;
129 int mask, retval;
130
131 a += nr >> 5;
132 mask = 1 << (nr & 31);
133 retval = (mask & *a) != 0;
134 *a ^= mask;
135 return retval;
136}
137
138/*
139 * This routine doesn't need to be atomic.
140 */
141static inline int __constant_test_bit(int nr, const volatile void * addr)
142{
143 return ((1UL << (nr & 31)) & (((const volatile unsigned int *) addr)[nr >> 5])) != 0;
144}
145
146static inline int __test_bit(int nr, const volatile void * addr)
147{
148 int * a = (int *) addr;
149 int mask;
150
151 a += nr >> 5;
152 mask = 1 << (nr & 0x1f);
153 return ((mask & *a) != 0);
154}
155
156#define test_bit(nr,addr) \
157(__builtin_constant_p(nr) ? \
158 __constant_test_bit((nr),(addr)) : \
159 __test_bit((nr),(addr)))
160
Akinobu Mita1f6d7a92006-03-26 01:39:22 -0800161#include <asm-generic/bitops/ffs.h>
162#include <asm-generic/bitops/__ffs.h>
163#include <asm-generic/bitops/find.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -0700164
165/*
166 * fls: find last bit set.
167 */
168#define fls(x) \
169({ \
170 int bit; \
171 \
172 asm("scan %1,gr0,%0" : "=r"(bit) : "r"(x)); \
173 \
174 bit ? 33 - bit : bit; \
175})
Linus Torvalds1da177e2005-04-16 15:20:36 -0700176
Akinobu Mita1f6d7a92006-03-26 01:39:22 -0800177#include <asm-generic/bitops/fls64.h>
178#include <asm-generic/bitops/sched.h>
179#include <asm-generic/bitops/hweight.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -0700180
Akinobu Mita1f6d7a92006-03-26 01:39:22 -0800181#include <asm-generic/bitops/ext2-non-atomic.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -0700182
Akinobu Mita67b0ad52006-03-26 01:39:05 -0800183#define ext2_set_bit_atomic(lock,nr,addr) test_and_set_bit ((nr) ^ 0x18, (addr))
184#define ext2_clear_bit_atomic(lock,nr,addr) test_and_clear_bit((nr) ^ 0x18, (addr))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700185
Akinobu Mita1f6d7a92006-03-26 01:39:22 -0800186#include <asm-generic/bitops/minix-le.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -0700187
188#endif /* __KERNEL__ */
189
190#endif /* _ASM_BITOPS_H */