db_sqlite: rename database scheme files, to allow automatic updates
[sip-router] / bit_test.h
1 /*
2  * $Id$
3  *
4  * Copyright (C) 2010 iptelorg GmbH
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  *
18  * History
19  * -------
20  *  2010-04-26  Initial version (Miklos)
21  *  2011-01-05  bit_test_and_reset added (Miklos)
22  */
23
24 /* Bit test functions:
25  *  - int bit_test(int offset, unsigned int *addr)
26  *      Returns the bit found at offset position 
27  *      in a bitstring pointed by addr.
28  *
29  *  - int bit_test_and_set(int offset, unsigned int *addr)
30  *      Returns the bit found at offset position 
31  *      in a bitstring pointed by addr, and sets
32  *      the bit at the given offset.
33  *
34  *  - int bit_test_and_reset(int offset, unsigned int *addr)
35  *      Returns the bit found at offset position 
36  *      in a bitstring pointed by addr, and resets
37  *      the bit at the given offset.
38  *
39  * Note that 0 <= offset <= 128, Make sure that addr points to
40  * a large enough memory area.
41  */
42
43 #ifndef _BIT_TEST_H
44 #define _BIT_TEST_H
45
46 /* fix __CPU_i386 -> __CPU_x86 */
47 #if defined __CPU_i386 && ! defined __CPU_x86
48 #define __CPU_x86
49 #endif
50  
51 #ifdef CC_GCC_LIKE_ASM
52 #if defined __CPU_x86 || defined __CPU_x86_64
53 #define BIT_TEST_ASM
54 #endif
55 #endif
56
57 #ifdef BIT_TEST_ASM
58
59 /* Returns the bit found at offset position in the bitstring
60  * pointed by addr.
61  * Note that the CPU can access 4 bytes starting from addr,
62  * hence 0 <= offset < 128 holds. Make sure that addr points
63  * to a memory area that is large enough.
64  */
65 static inline int bit_test(int offset, unsigned int *addr)
66 {
67         unsigned char   v;
68
69         asm volatile(
70                 " bt %2, %1 \n\t"
71                 " setc %0 \n\t"
72                 : "=qm" (v) : "m" (*addr), "r" (offset)
73         );
74         return (int)v;
75 }
76
77 /* Returns the bit found at offset position in the bitstring
78  * pointed by addr and sets it to 1.
79  * Note that the CPU can access 4 bytes starting from addr,
80  * hence 0 <= offset < 128 holds. Make sure that addr points
81  * to a memory area that is large enough.
82  */
83 static inline int bit_test_and_set(int offset, unsigned int *addr)
84 {
85         unsigned char   v;
86
87         asm volatile(
88                 " bts %2, %1 \n\t"
89                 " setc %0 \n\t"
90                 : "=qm" (v) : "m" (*addr), "r" (offset)
91         );
92         return (int)v;
93 }
94
95 /* Returns the bit found at offset position in the bitstring
96  * pointed by addr and resets it to 0.
97  * Note that the CPU can access 4 bytes starting from addr,
98  * hence 0 <= offset < 128 holds. Make sure that addr points
99  * to a memory area that is large enough.
100  */
101 static inline int bit_test_and_reset(int offset, unsigned int *addr)
102 {
103         unsigned char   v;
104
105         asm volatile(
106                 " btr %2, %1 \n\t"
107                 " setc %0 \n\t"
108                 : "=qm" (v) : "m" (*addr), "r" (offset)
109         );
110         return (int)v;
111 }
112
113 #else /* BIT_TEST_ASM */
114
115 /* Returns the bit found at offset position in the bitstring
116  * pointed by addr.
117  * Note that offset can be grater than 32, make sure that addr points
118  * to a memory area that is large enough.
119  */
120 static inline int bit_test(int offset, unsigned int *addr)
121 {
122         return ((*(addr + offset/32)) & (1U << (offset % 32))) ? 1 : 0;
123 }
124
125 /* Returns the bit found at offset position in the bitstring
126  * pointed by addr and sets it to 1.
127  * Note that offset can be grater than 32, make sure that addr points
128  * to a memory area that is large enough.
129  */
130 static inline int bit_test_and_set(int offset, unsigned int *addr)
131 {
132         unsigned int    *i;
133         int     mask, res;
134
135         i = addr + offset/32;
136         mask = 1U << (offset % 32);
137         res = ((*i) & mask) ? 1 : 0;
138         (*i) |= mask;
139
140         return res;
141 }
142
143 /* Returns the bit found at offset position in the bitstring
144  * pointed by addr and resets it to 0.
145  * Note that offset can be grater than 32, make sure that addr points
146  * to a memory area that is large enough.
147  */
148 static inline int bit_test_and_reset(int offset, unsigned int *addr)
149 {
150         unsigned int    *i;
151         int     mask, res;
152
153         i = addr + offset/32;
154         mask = 1U << (offset % 32);
155         res = ((*i) & mask) ? 1 : 0;
156         (*i) &= ~mask;
157
158         return res;
159 }
160
161 #endif /* BIT_TEST_ASM */
162
163 #endif /* #ifndef _BIT_TEST_H */