00001 /* 00002 * $Id$ 00003 * 00004 * Copyright (C) 2010 iptelorg GmbH 00005 * 00006 * Permission to use, copy, modify, and distribute this software for any 00007 * purpose with or without fee is hereby granted, provided that the above 00008 * copyright notice and this permission notice appear in all copies. 00009 * 00010 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 00011 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 00012 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 00013 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 00014 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 00015 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 00016 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 00017 * 00018 * History 00019 * ------- 00020 * 2010-04-26 Initial version (Miklos) 00021 * 2011-01-05 bit_test_and_reset added (Miklos) 00022 */ 00023 00024 /* Bit test functions: 00025 * - int bit_test(int offset, unsigned int *addr) 00026 * Returns the bit found at offset position 00027 * in a bitstring pointed by addr. 00028 * 00029 * - int bit_test_and_set(int offset, unsigned int *addr) 00030 * Returns the bit found at offset position 00031 * in a bitstring pointed by addr, and sets 00032 * the bit at the given offset. 00033 * 00034 * - int bit_test_and_reset(int offset, unsigned int *addr) 00035 * Returns the bit found at offset position 00036 * in a bitstring pointed by addr, and resets 00037 * the bit at the given offset. 00038 * 00039 * Note that 0 <= offset <= 128, Make sure that addr points to 00040 * a large enough memory area. 00041 */ 00042 00043 #ifndef _BIT_TEST_H 00044 #define _BIT_TEST_H 00045 00046 /* fix __CPU_i386 -> __CPU_x86 */ 00047 #if defined __CPU_i386 && ! defined __CPU_x86 00048 #define __CPU_x86 00049 #endif 00050 00051 #ifdef CC_GCC_LIKE_ASM 00052 #if defined __CPU_x86 || defined __CPU_x86_64 00053 #define BIT_TEST_ASM 00054 #endif 00055 #endif 00056 00057 #ifdef BIT_TEST_ASM 00058 00059 /* Returns the bit found at offset position in the bitstring 00060 * pointed by addr. 00061 * Note that the CPU can access 4 bytes starting from addr, 00062 * hence 0 <= offset < 128 holds. Make sure that addr points 00063 * to a memory area that is large enough. 00064 */ 00065 static inline int bit_test(int offset, unsigned int *addr) 00066 { 00067 unsigned char v; 00068 00069 asm volatile( 00070 " bt %2, %1 \n\t" 00071 " setc %0 \n\t" 00072 : "=qm" (v) : "m" (*addr), "r" (offset) 00073 ); 00074 return (int)v; 00075 } 00076 00077 /* Returns the bit found at offset position in the bitstring 00078 * pointed by addr and sets it to 1. 00079 * Note that the CPU can access 4 bytes starting from addr, 00080 * hence 0 <= offset < 128 holds. Make sure that addr points 00081 * to a memory area that is large enough. 00082 */ 00083 static inline int bit_test_and_set(int offset, unsigned int *addr) 00084 { 00085 unsigned char v; 00086 00087 asm volatile( 00088 " bts %2, %1 \n\t" 00089 " setc %0 \n\t" 00090 : "=qm" (v) : "m" (*addr), "r" (offset) 00091 ); 00092 return (int)v; 00093 } 00094 00095 /* Returns the bit found at offset position in the bitstring 00096 * pointed by addr and resets it to 0. 00097 * Note that the CPU can access 4 bytes starting from addr, 00098 * hence 0 <= offset < 128 holds. Make sure that addr points 00099 * to a memory area that is large enough. 00100 */ 00101 static inline int bit_test_and_reset(int offset, unsigned int *addr) 00102 { 00103 unsigned char v; 00104 00105 asm volatile( 00106 " btr %2, %1 \n\t" 00107 " setc %0 \n\t" 00108 : "=qm" (v) : "m" (*addr), "r" (offset) 00109 ); 00110 return (int)v; 00111 } 00112 00113 #else /* BIT_TEST_ASM */ 00114 00115 /* Returns the bit found at offset position in the bitstring 00116 * pointed by addr. 00117 * Note that offset can be grater than 32, make sure that addr points 00118 * to a memory area that is large enough. 00119 */ 00120 static inline int bit_test(int offset, unsigned int *addr) 00121 { 00122 return ((*(addr + offset/32)) & (1U << (offset % 32))) ? 1 : 0; 00123 } 00124 00125 /* Returns the bit found at offset position in the bitstring 00126 * pointed by addr and sets it to 1. 00127 * Note that offset can be grater than 32, make sure that addr points 00128 * to a memory area that is large enough. 00129 */ 00130 static inline int bit_test_and_set(int offset, unsigned int *addr) 00131 { 00132 unsigned int *i; 00133 int mask, res; 00134 00135 i = addr + offset/32; 00136 mask = 1U << (offset % 32); 00137 res = ((*i) & mask) ? 1 : 0; 00138 (*i) |= mask; 00139 00140 return res; 00141 } 00142 00143 /* Returns the bit found at offset position in the bitstring 00144 * pointed by addr and resets it to 0. 00145 * Note that offset can be grater than 32, make sure that addr points 00146 * to a memory area that is large enough. 00147 */ 00148 static inline int bit_test_and_reset(int offset, unsigned int *addr) 00149 { 00150 unsigned int *i; 00151 int mask, res; 00152 00153 i = addr + offset/32; 00154 mask = 1U << (offset % 32); 00155 res = ((*i) & mask) ? 1 : 0; 00156 (*i) &= ~mask; 00157 00158 return res; 00159 } 00160 00161 #endif /* BIT_TEST_ASM */ 00162 00163 #endif /* #ifndef _BIT_TEST_H */
1.7.1