bitops.h

Go to the documentation of this file.
00001 #ifndef _GPXE_BITOPS_H
00002 #define _GPXE_BITOPS_H
00003 
00004 /*
00005  * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License as
00009  * published by the Free Software Foundation; either version 2 of the
00010  * License, or any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful, but
00013  * WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00020  */
00021 
00022 FILE_LICENCE ( GPL2_OR_LATER );
00023 
00024 /**
00025  * @file
00026  *
00027  * Bit operations
00028  *
00029  */
00030 
00031 #include <stdint.h>
00032 #include <byteswap.h>
00033 
00034 /* Endianness selection.
00035  *
00036  * This is a property of the NIC, not a property of the host CPU.
00037  */
00038 #ifdef BITOPS_LITTLE_ENDIAN
00039 #define cpu_to_BIT64    cpu_to_le64
00040 #define cpu_to_BIT32    cpu_to_le32
00041 #define BIT64_to_cpu    le64_to_cpu
00042 #define BIT32_to_cpu    le32_to_cpu
00043 #endif
00044 #ifdef BITOPS_BIG_ENDIAN
00045 #define cpu_to_BIT64    cpu_to_be64
00046 #define cpu_to_BIT32    cpu_to_be32
00047 #define BIT64_to_cpu    be64_to_cpu
00048 #define BIT32_to_cpu    be32_to_cpu
00049 #endif
00050 
00051 /** Datatype used to represent a bit in the pseudo-structures */
00052 typedef unsigned char pseudo_bit_t;
00053 
00054 /**
00055  * Wrapper structure for pseudo_bit_t structures
00056  *
00057  * This structure provides a wrapper around pseudo_bit_t structures.
00058  * It has the correct size, and also encapsulates type information
00059  * about the underlying pseudo_bit_t-based structure, which allows the
00060  * BIT_FILL() etc. macros to work without requiring explicit type
00061  * information.
00062  */
00063 #define PSEUDO_BIT_STRUCT( _structure )                                       \
00064         union {                                                               \
00065                 uint8_t bytes[ sizeof ( _structure ) / 8 ];                   \
00066                 uint32_t dwords[ sizeof ( _structure ) / 32 ];                \
00067                 uint64_t qwords[ sizeof ( _structure ) / 64 ];                \
00068                 _structure *dummy[0];                                         \
00069         } u
00070 
00071 /** Get pseudo_bit_t structure type from wrapper structure pointer */
00072 #define PSEUDO_BIT_STRUCT_TYPE( _ptr )                                        \
00073         typeof ( *((_ptr)->u.dummy[0]) )
00074 
00075 /** Bit offset of a field within a pseudo_bit_t structure */
00076 #define BIT_OFFSET( _ptr, _field )                                            \
00077         offsetof ( PSEUDO_BIT_STRUCT_TYPE ( _ptr ), _field )
00078 
00079 /** Bit width of a field within a pseudo_bit_t structure */
00080 #define BIT_WIDTH( _ptr, _field )                                             \
00081         sizeof ( ( ( PSEUDO_BIT_STRUCT_TYPE ( _ptr ) * ) NULL )->_field )
00082 
00083 /** Qword offset of a field within a pseudo_bit_t structure */
00084 #define QWORD_OFFSET( _ptr, _field )                                          \
00085         ( BIT_OFFSET ( _ptr, _field ) / 64 )
00086 
00087 /** Qword bit offset of a field within a pseudo_bit_t structure */
00088 #define QWORD_BIT_OFFSET( _ptr, _index, _field )                              \
00089         ( BIT_OFFSET ( _ptr, _field ) - ( 64 * (_index) ) )
00090 
00091 /** Bit mask for a field within a pseudo_bit_t structure */
00092 #define BIT_MASK( _ptr, _field )                                              \
00093         ( ( ~( ( uint64_t ) 0 ) ) >>                                          \
00094           ( 64 - BIT_WIDTH ( _ptr, _field ) ) )
00095 
00096 /*
00097  * Assemble native-endian qword from named fields and values
00098  *
00099  */
00100 
00101 #define BIT_ASSEMBLE_1( _ptr, _index, _field, _value )                        \
00102         ( ( ( uint64_t) (_value) ) <<                                         \
00103           QWORD_BIT_OFFSET ( _ptr, _index, _field ) )
00104 
00105 #define BIT_ASSEMBLE_2( _ptr, _index, _field, _value, ... )                   \
00106         ( BIT_ASSEMBLE_1 ( _ptr, _index, _field, _value ) |                   \
00107           BIT_ASSEMBLE_1 ( _ptr, _index, __VA_ARGS__ ) )
00108 
00109 #define BIT_ASSEMBLE_3( _ptr, _index, _field, _value, ... )                   \
00110         ( BIT_ASSEMBLE_1 ( _ptr, _index, _field, _value ) |                   \
00111           BIT_ASSEMBLE_2 ( _ptr, _index, __VA_ARGS__ ) )
00112 
00113 #define BIT_ASSEMBLE_4( _ptr, _index, _field, _value, ... )                   \
00114         ( BIT_ASSEMBLE_1 ( _ptr, _index, _field, _value ) |                   \
00115           BIT_ASSEMBLE_3 ( _ptr, _index, __VA_ARGS__ ) )
00116 
00117 #define BIT_ASSEMBLE_5( _ptr, _index, _field, _value, ... )                   \
00118         ( BIT_ASSEMBLE_1 ( _ptr, _index, _field, _value ) |                   \
00119           BIT_ASSEMBLE_4 ( _ptr, _index, __VA_ARGS__ ) )
00120 
00121 #define BIT_ASSEMBLE_6( _ptr, _index, _field, _value, ... )                   \
00122         ( BIT_ASSEMBLE_1 ( _ptr, _index, _field, _value ) |                   \
00123           BIT_ASSEMBLE_5 ( _ptr, _index, __VA_ARGS__ ) )
00124 
00125 #define BIT_ASSEMBLE_7( _ptr, _index, _field, _value, ... )                   \
00126         ( BIT_ASSEMBLE_1 ( _ptr, _index, _field, _value ) |                   \
00127           BIT_ASSEMBLE_6 ( _ptr, _index, __VA_ARGS__ ) )
00128 
00129 /*
00130  * Build native-endian (positive) qword bitmasks from named fields
00131  *
00132  */
00133 
00134 #define BIT_MASK_1( _ptr, _index, _field )                                    \
00135         ( BIT_MASK ( _ptr, _field ) <<                                        \
00136           QWORD_BIT_OFFSET ( _ptr, _index, _field ) )
00137 
00138 #define BIT_MASK_2( _ptr, _index, _field, ... )                               \
00139         ( BIT_MASK_1 ( _ptr, _index, _field ) |                               \
00140           BIT_MASK_1 ( _ptr, _index, __VA_ARGS__ ) )
00141 
00142 #define BIT_MASK_3( _ptr, _index, _field, ... )                               \
00143         ( BIT_MASK_1 ( _ptr, _index, _field ) |                               \
00144           BIT_MASK_2 ( _ptr, _index, __VA_ARGS__ ) )
00145 
00146 #define BIT_MASK_4( _ptr, _index, _field, ... )                               \
00147         ( BIT_MASK_1 ( _ptr, _index, _field ) |                               \
00148           BIT_MASK_3 ( _ptr, _index, __VA_ARGS__ ) )
00149 
00150 #define BIT_MASK_5( _ptr, _index, _field, ... )                               \
00151         ( BIT_MASK_1 ( _ptr, _index, _field ) |                               \
00152           BIT_MASK_4 ( _ptr, _index, __VA_ARGS__ ) )
00153 
00154 #define BIT_MASK_6( _ptr, _index, _field, ... )                               \
00155         ( BIT_MASK_1 ( _ptr, _index, _field ) |                               \
00156           BIT_MASK_5 ( _ptr, _index, __VA_ARGS__ ) )
00157 
00158 #define BIT_MASK_7( _ptr, _index, _field, ... )                               \
00159         ( BIT_MASK_1 ( _ptr, _index, _field ) |                               \
00160           BIT_MASK_6 ( _ptr, _index, __VA_ARGS__ ) )
00161 
00162 /*
00163  * Populate little-endian qwords from named fields and values
00164  *
00165  */
00166 
00167 #define BIT_FILL( _ptr, _index, _assembled ) do {                             \
00168                 uint64_t *__ptr = &(_ptr)->u.qwords[(_index)];                \
00169                 uint64_t __assembled = (_assembled);                          \
00170                 *__ptr = cpu_to_BIT64 ( __assembled );                        \
00171         } while ( 0 )
00172 
00173 #define BIT_FILL_1( _ptr, _field1, ... )                                      \
00174         BIT_FILL ( _ptr, QWORD_OFFSET ( _ptr, _field1 ),                      \
00175                    BIT_ASSEMBLE_1 ( _ptr, QWORD_OFFSET ( _ptr, _field1 ),     \
00176                                     _field1, __VA_ARGS__ ) )
00177 
00178 #define BIT_FILL_2( _ptr, _field1, ... )                                      \
00179         BIT_FILL ( _ptr, QWORD_OFFSET ( _ptr, _field1 ),                      \
00180                    BIT_ASSEMBLE_2 ( _ptr, QWORD_OFFSET ( _ptr, _field1 ),     \
00181                                     _field1, __VA_ARGS__ ) )
00182 
00183 #define BIT_FILL_3( _ptr, _field1, ... )                                      \
00184         BIT_FILL ( _ptr, QWORD_OFFSET ( _ptr, _field1 ),                      \
00185                    BIT_ASSEMBLE_3 ( _ptr, QWORD_OFFSET ( _ptr, _field1 ),     \
00186                                     _field1, __VA_ARGS__ ) )
00187 
00188 #define BIT_FILL_4( _ptr, _field1, ... )                                      \
00189         BIT_FILL ( _ptr, QWORD_OFFSET ( _ptr, _field1 ),                      \
00190                    BIT_ASSEMBLE_4 ( _ptr, QWORD_OFFSET ( _ptr, _field1 ),     \
00191                                     _field1, __VA_ARGS__ ) )
00192 
00193 #define BIT_FILL_5( _ptr, _field1, ... )                                      \
00194         BIT_FILL ( _ptr, QWORD_OFFSET ( _ptr, _field1 ),                      \
00195                    BIT_ASSEMBLE_5 ( _ptr, QWORD_OFFSET ( _ptr, _field1 ),     \
00196                                     _field1, __VA_ARGS__ ) )
00197 
00198 #define BIT_FILL_6( _ptr, _field1, ... )                                      \
00199         BIT_FILL ( _ptr, QWORD_OFFSET ( _ptr, _field1 ),                      \
00200                    BIT_ASSEMBLE_6 ( _ptr, QWORD_OFFSET ( _ptr, _field1 ),     \
00201                                     _field1, __VA_ARGS__ ) )
00202 
00203 /** Extract value of named field */
00204 #define BIT_GET64( _ptr, _field )                                             \
00205         ( {                                                                   \
00206                 unsigned int __index = QWORD_OFFSET ( _ptr, _field );         \
00207                 uint64_t *__ptr = &(_ptr)->u.qwords[__index];                 \
00208                 uint64_t __value = BIT64_to_cpu ( *__ptr );                   \
00209                 __value >>=                                                   \
00210                     QWORD_BIT_OFFSET ( _ptr, __index, _field );               \
00211                 __value &= BIT_MASK ( _ptr, _field );                         \
00212                 __value;                                                      \
00213         } )
00214 
00215 /** Extract value of named field (for fields up to the size of a long) */
00216 #define BIT_GET( _ptr, _field )                                               \
00217         ( ( unsigned long ) BIT_GET64 ( _ptr, _field ) )
00218 
00219 #define BIT_SET( _ptr, _field, _value ) do {                                  \
00220                 unsigned int __index = QWORD_OFFSET ( _ptr, _field );         \
00221                 uint64_t *__ptr = &(_ptr)->u.qwords[__index];                 \
00222                 unsigned int __shift =                                        \
00223                         QWORD_BIT_OFFSET ( _ptr, __index, _field );           \
00224                 uint64_t __value = (_value);                                  \
00225                 *__ptr &= cpu_to_BIT64 ( ~( BIT_MASK ( _ptr, _field ) <<      \
00226                                             __shift ) );                      \
00227                 *__ptr |= cpu_to_BIT64 ( __value << __shift );                \
00228         } while ( 0 )
00229 
00230 #endif /* _GPXE_BITOPS_H */

Generated on Tue Apr 6 20:01:06 2010 for gPXE by  doxygen 1.5.7.1