• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Data Structures
  • Files
  • Directories
  • File List
  • Globals

bit_scan.h

Go to the documentation of this file.
00001 /* 
00002  * $Id$
00003  * 
00004  * Copyright (C) 2007 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  */
00044 /* 
00045  * History:
00046  * --------
00047  *  2007-06-23  created by andrei
00048  */
00049 
00050 #ifndef _bit_scan_h
00051 #define _bit_scan_h
00052 
00053 #include <limits.h>
00054 
00056 #if defined __CPU_i386 && ! defined __CPU_x86
00057 #define __CPU_x86
00058 #endif
00059 
00060 
00061 #ifdef CC_GCC_LIKE_ASM
00062 #if defined __CPU_x86 || defined __CPU_x86_64
00063 #define BIT_SCAN_ASM
00064 #endif
00065 #endif
00066 
00067 
00071 #ifdef BIT_SCAN_ASM
00072 /* have asm => use it */
00073 
00074 #define bit_scan_forward32(i)   bit_scan_forward_asm32(i)
00075 #define bit_scan_forward64(i)   bit_scan_forward_asm64(i)
00076 #define bit_scan_reverse32(i)   bit_scan_reverse_asm32(i)
00077 #define bit_scan_reverse64(i)   bit_scan_reverse_asm64(i)
00078 
00079 #elif defined __CPU_x86 || defined __CPU_x86_64
00080 /* no asm (e.g. no CC_GCC_LIKE_ASM) => debruijn for bit_scan_forward and
00081  *  br for bit_scan_reverse */
00082 /* make sure debruijn an branch version are enabled */
00083 #ifndef BIT_SCAN_DEBRUIJN
00084 #define BIT_SCAN_DEBRUIJN
00085 #endif
00086 #ifndef BIT_SCAN_BRANCH
00087 #define BIT_SCAN_BRANCH
00088 #endif
00089 
00090 #define bit_scan_forward32(i)   bit_scan_forward_debruijn32(i)
00091 #define bit_scan_forward64(i)   bit_scan_forward_debruijn64(i)
00092 #define bit_scan_reverse32(i)   bit_scan_reverse_br32(i)
00093 #define bit_scan_reverse64(i)   bit_scan_reverse_br64(i)
00094 
00095 #elif defined __CPU_sparc64
00096 /* no asm yet => use branch for everything in 64 bit mode
00097  *               and debruijn + branch in 32 bit mode
00098  *  (in 64bit mode the branch method is slightly faster then debruijn,
00099  *   however note that in 32 bit mode the roles are reversed for _forward)*/
00100 #ifndef BIT_SCAN_BRANCH
00101 #define BIT_SCAN_BRANCH
00102 #endif
00103 
00104 #define bit_scan_reverse32(i)   bit_scan_reverse_br32(i)
00105 #define bit_scan_reverse64(i)   bit_scan_reverse_br64(i)
00106 #ifdef LP64
00107 #define bit_scan_forward32(i)   bit_scan_forward_br32(i)
00108 #define bit_scan_forward64(i)   bit_scan_forward_br64(i)
00109 #else /* LP64 */
00110 
00111 #ifndef BIT_SCAN_DEBRUIJN
00112 #define BIT_SCAN_DEBRUIJN
00113 #endif
00114 #define bit_scan_forward32(i)   bit_scan_forward_debruijn32(i)
00115 #define bit_scan_forward64(i)   bit_scan_forward_debruijn64(i)
00116 #endif /* LP64 */
00117 
00118 #else /* __CPU_XXX */
00119 /* default - like x86 no asm */
00120 /* make sure debruijn an branch version are enabled */
00121 #ifndef BIT_SCAN_DEBRUIJN
00122 #define BIT_SCAN_DEBRUIJN
00123 #endif
00124 #ifndef BIT_SCAN_BRANCH
00125 #define BIT_SCAN_BRANCH
00126 #endif
00127 
00128 #define bit_scan_forward32(i)   bit_scan_forward_debruijn32(i)
00129 #define bit_scan_forward64(i)   bit_scan_forward_debruijn64(i)
00130 #define bit_scan_reverse32(i)   bit_scan_reverse_br32(i)
00131 #define bit_scan_reverse64(i)   bit_scan_reverse_br64(i)
00132 
00133 #endif /* __CPU_XXX */
00134 
00135 
00138 #if (defined (ULONG_MAX) && ULONG_MAX > 4294967295) || defined LP64
00139 
00140 #define bit_scan_forward(l)     bit_scan_forward64((unsigned long long)(l))
00141 #define bit_scan_reverse(l)     bit_scan_reverse64((unsigned long long)(l))
00142 
00143 #else
00144 
00145 #define bit_scan_forward(l)     bit_scan_forward32((l))
00146 #define bit_scan_reverse(l)     bit_scan_reverse32((l))
00147 #endif
00148 
00149 
00150 
00151 
00152 #ifdef BIT_SCAN_DEBRUIJN
00153 
00164 extern unsigned char _debruijn_hash32[32]; /* see bit_scan.c */
00165 extern unsigned char _debruijn_hash64[64]; /* see bit_scan.c */
00166 
00167 #define DEBRUIJN_CT32  0x04653ADFU
00168 #define DEBRUIJN_CT64  0x0218A392CD3D5DBFULL 
00169 
00170 #define DEBRUIJN_HASH32(x)\
00171         (((x)*DEBRUIJN_CT32)>>(sizeof(x)*8-5))
00172 
00173 #define DEBRUIJN_HASH64(x)\
00174         (((x)*DEBRUIJN_CT64)>>(sizeof(x)*8-6))
00175 
00176 #define bit_scan_forward_debruijn32(x) \
00177         ( _debruijn_hash32[DEBRUIJN_HASH32((x) & (-(x)))])
00178 
00179 #define bit_scan_forward_debruijn64(x) \
00180         ( _debruijn_hash64[DEBRUIJN_HASH64((x) & (-(x)))])
00181 
00182 
00183 static inline int bit_scan_reverse_debruijn32(unsigned int v)
00184 {
00185         unsigned int last;
00186         
00187         do{
00188                 last=v;
00189                 v=v&(v-1);
00190         }while(v); /* => last is 2^k */
00191         return _debruijn_hash32[DEBRUIJN_HASH32(last)];
00192 }
00193 
00194 
00195 static inline int bit_scan_reverse_debruijn64(unsigned long long v)
00196 {
00197         unsigned long long last;
00198         
00199         do{
00200                 last=v;
00201                 v=v&(v-1);
00202         }while(v); /* => last is 2^k */
00203         return _debruijn_hash64[DEBRUIJN_HASH64(last)];
00204 }
00205 
00206 
00207 #endif /* BIT_SCAN_DEBRUIJN */
00208 
00209 #ifdef BIT_SCAN_SLOW
00210 /* only for reference purposes (testing the other versions against it) */
00211 
00212 static inline int bit_scan_forward_slow32(unsigned int v)
00213 {
00214         int r;
00215         for(r=0; r<(sizeof(v)*8); r++, v>>=1)
00216                 if (v&1) return r;
00217         return 0;
00218 }
00219 
00220 
00221 static inline int bit_scan_reverse_slow32(unsigned int v)
00222 {
00223         int r;
00224         for(r=sizeof(v)*8-1; r>0; r--, v<<=1)
00225                 if (v& (1UL<<(sizeof(v)*8-1))) return r;
00226         return 0;
00227 }
00228 
00229 
00230 static inline int bit_scan_forward_slow64(unsigned long long v)
00231 {
00232         int r;
00233         for(r=0; r<(sizeof(v)*8); r++, v>>=1)
00234                 if (v&1ULL) return r;
00235         return 0;
00236 }
00237 
00238 
00239 static inline int bit_scan_reverse_slow64(unsigned long long v)
00240 {
00241         int r;
00242         for(r=sizeof(v)*8-1; r>0; r--, v<<=1)
00243                 if (v& (1ULL<<(sizeof(v)*8-1))) return r;
00244         return 0;
00245 }
00246 
00247 
00248 #endif /* BIT_SCAN_SLOW */
00249 
00250 
00251 #ifdef BIT_SCAN_BRANCH
00252 
00253 static inline int bit_scan_forward_br32(unsigned int v)
00254 {
00255         int b;
00256         
00257         b=0;
00258         if (v&0x01)
00259                 return 0;
00260         if (!(v & 0xffff)){
00261                 b+=16;
00262                 v>>=16;
00263         }
00264         if (!(v&0xff)){
00265                 b+=8;
00266                 v>>=8;
00267         }
00268         if (!(v&0x0f)){
00269                 b+=4;
00270                 v>>=4;
00271         }
00272         if (!(v&0x03)){
00273                 b+=2;
00274                 v>>=2;
00275         }
00276         b+= !(v&0x01);
00277         return b;
00278 }
00279 
00280 
00281 static inline int bit_scan_reverse_br32(unsigned int v)
00282 {
00283         int b;
00284         
00285         b=0;
00286         if (v & 0xffff0000){
00287                 b+=16;
00288                 v>>=16;
00289         }
00290         if (v&0xff00){
00291                 b+=8;
00292                 v>>=8;
00293         }
00294         if (v&0xf0){
00295                 b+=4;
00296                 v>>=4;
00297         }
00298         if (v&0x0c){
00299                 b+=2;
00300                 v>>=2;
00301         }
00302         b+= !!(v&0x02);
00303         return b;
00304 }
00305 
00306 
00307 static inline int bit_scan_forward_br64(unsigned long long v)
00308 {
00309         int b;
00310         
00311         b=0;
00312         if (v&0x01ULL)
00313                 return 0;
00314         if (!(v & 0xffffffffULL)){
00315                 b+=32;
00316                 v>>=32;
00317         }
00318         if (!(v & 0xffffULL)){
00319                 b+=16;
00320                 v>>=16;
00321         }
00322         if (!(v&0xffULL)){
00323                 b+=8;
00324                 v>>=8;
00325         }
00326         if (!(v&0x0fULL)){
00327                 b+=4;
00328                 v>>=4;
00329         }
00330         if (!(v&0x03ULL)){
00331                 b+=2;
00332                 v>>=2;
00333         }
00334         b+= !(v&0x01ULL);
00335         return b;
00336 }
00337 
00338 
00339 static inline int bit_scan_reverse_br64(unsigned long long v)
00340 {
00341         int b;
00342         
00343         b=0;
00344         if (v & 0xffffffff00000000ULL){
00345                 b+=32;
00346                 v>>=32;
00347         }
00348         if (v & 0xffff0000ULL){
00349                 b+=16;
00350                 v>>=16;
00351         }
00352         if (v&0xff00ULL){
00353                 b+=8;
00354                 v>>=8;
00355         }
00356         if (v&0xf0ULL){
00357                 b+=4;
00358                 v>>=4;
00359         }
00360         if (v&0x0cULL){
00361                 b+=2;
00362                 v>>=2;
00363         }
00364         b+= !!(v&0x02ULL);
00365         return b;
00366 }
00367 #endif  /* BIT_SCAN_BRANCH */
00368 
00369 
00370 
00371 #ifdef BIT_SCAN_ASM
00372 #if defined __CPU_x86 || defined __CPU_x86_64
00373 #define HAS_BIT_SCAN_ASM
00374 
00375 static inline int bit_scan_forward_asm32(unsigned int v)
00376 {
00377         int r;
00378         asm volatile(" bsfl %1, %0": "=r"(r): "rm"(v) );
00379         return r;
00380 }
00381 
00382 static inline int bit_scan_reverse_asm32(unsigned int v)
00383 {
00384         int r;
00385         asm volatile(" bsrl %1, %0": "=r"(r): "rm"(v) );
00386         return r;
00387 }
00388 
00389 #ifdef __CPU_x86_64
00390 static inline int bit_scan_forward_asm64(unsigned long long v)
00391 {
00392         long r;
00393         asm volatile(" bsfq %1, %0": "=r"(r): "rm"(v) );
00394         return r;
00395 }
00396 
00397 static inline int bit_scan_reverse_asm64(unsigned long long v)
00398 {
00399         long r;
00400         asm volatile(" bsrq %1, %0": "=r"(r): "rm"(v) );
00401         return r;
00402 }
00403 #else
00404 static inline int bit_scan_forward_asm64(unsigned long long v)
00405 {
00406         if ((unsigned int)v)
00407                 return bit_scan_forward_asm32((unsigned int)v);
00408         return 32+bit_scan_forward_asm32(*(((unsigned int*)(void*)&v)+1));
00409 }
00410 
00411 static inline int bit_scan_reverse_asm64(unsigned long long v)
00412 {
00413         if (v & 0xffffffff00000000ULL)
00414                 return 32+bit_scan_reverse_asm32(*(((unsigned int*)(void*)&v)+1));
00415         return bit_scan_reverse_asm32((unsigned int)v);
00416 }
00417 #endif /* __CPU_x86_64 */
00418 
00419 #endif /* __CPU_x86 || __CPU_x86_64 */
00420 #endif /* BIT_SCAN_ASM */
00421 
00422 #endif

Generated on Tue May 22 2012 13:10:03 for SIP Router by  doxygen 1.7.1