1 #ifndef _GPXE_BITOPS_H 2 #define _GPXE_BITOPS_H 3 4 /* 5 * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>. 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License as 9 * published by the Free Software Foundation; either version 2 of the 10 * License, or any later version. 11 * 12 * This program is distributed in the hope that it will be useful, but 13 * WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 */ 21 22 FILE_LICENCE ( GPL2_OR_LATER ); 23 24 /** 25 * @file 26 * 27 * Bit operations 28 * 29 */ 30 31 #include <stdint.h> 32 #include <byteswap.h> 33 34 /* Endianness selection. 35 * 36 * This is a property of the NIC, not a property of the host CPU. 37 */ 38 #ifdef BITOPS_LITTLE_ENDIAN 39 #define cpu_to_BIT64 cpu_to_le64 40 #define cpu_to_BIT32 cpu_to_le32 41 #define BIT64_to_cpu le64_to_cpu 42 #define BIT32_to_cpu le32_to_cpu 43 #endif 44 #ifdef BITOPS_BIG_ENDIAN 45 #define cpu_to_BIT64 cpu_to_be64 46 #define cpu_to_BIT32 cpu_to_be32 47 #define BIT64_to_cpu be64_to_cpu 48 #define BIT32_to_cpu be32_to_cpu 49 #endif 50 51 /** Datatype used to represent a bit in the pseudo-structures */ 52 typedef unsigned char pseudo_bit_t; 53 54 /** 55 * Wrapper structure for pseudo_bit_t structures 56 * 57 * This structure provides a wrapper around pseudo_bit_t structures. 58 * It has the correct size, and also encapsulates type information 59 * about the underlying pseudo_bit_t-based structure, which allows the 60 * BIT_FILL() etc. macros to work without requiring explicit type 61 * information. 62 */ 63 #define PSEUDO_BIT_STRUCT( _structure ) \ 64 union { \ 65 uint8_t bytes[ sizeof ( _structure ) / 8 ]; \ 66 uint32_t dwords[ sizeof ( _structure ) / 32 ]; \ 67 uint64_t qwords[ sizeof ( _structure ) / 64 ]; \ 68 _structure *dummy[0]; \ 69 } u 70 71 /** Get pseudo_bit_t structure type from wrapper structure pointer */ 72 #define PSEUDO_BIT_STRUCT_TYPE( _ptr ) \ 73 typeof ( *((_ptr)->u.dummy[0]) ) 74 75 /** Bit offset of a field within a pseudo_bit_t structure */ 76 #define BIT_OFFSET( _ptr, _field ) \ 77 offsetof ( PSEUDO_BIT_STRUCT_TYPE ( _ptr ), _field ) 78 79 /** Bit width of a field within a pseudo_bit_t structure */ 80 #define BIT_WIDTH( _ptr, _field ) \ 81 sizeof ( ( ( PSEUDO_BIT_STRUCT_TYPE ( _ptr ) * ) NULL )->_field ) 82 83 /** Qword offset of a field within a pseudo_bit_t structure */ 84 #define QWORD_OFFSET( _ptr, _field ) \ 85 ( BIT_OFFSET ( _ptr, _field ) / 64 ) 86 87 /** Qword bit offset of a field within a pseudo_bit_t structure */ 88 #define QWORD_BIT_OFFSET( _ptr, _index, _field ) \ 89 ( BIT_OFFSET ( _ptr, _field ) - ( 64 * (_index) ) ) 90 91 /** Bit mask for a field within a pseudo_bit_t structure */ 92 #define BIT_MASK( _ptr, _field ) \ 93 ( ( ~( ( uint64_t ) 0 ) ) >> \ 94 ( 64 - BIT_WIDTH ( _ptr, _field ) ) ) 95 96 /* 97 * Assemble native-endian qword from named fields and values 98 * 99 */ 100 101 #define BIT_ASSEMBLE_1( _ptr, _index, _field, _value ) \ 102 ( ( ( uint64_t) (_value) ) << \ 103 QWORD_BIT_OFFSET ( _ptr, _index, _field ) ) 104 105 #define BIT_ASSEMBLE_2( _ptr, _index, _field, _value, ... ) \ 106 ( BIT_ASSEMBLE_1 ( _ptr, _index, _field, _value ) | \ 107 BIT_ASSEMBLE_1 ( _ptr, _index, __VA_ARGS__ ) ) 108 109 #define BIT_ASSEMBLE_3( _ptr, _index, _field, _value, ... ) \ 110 ( BIT_ASSEMBLE_1 ( _ptr, _index, _field, _value ) | \ 111 BIT_ASSEMBLE_2 ( _ptr, _index, __VA_ARGS__ ) ) 112 113 #define BIT_ASSEMBLE_4( _ptr, _index, _field, _value, ... ) \ 114 ( BIT_ASSEMBLE_1 ( _ptr, _index, _field, _value ) | \ 115 BIT_ASSEMBLE_3 ( _ptr, _index, __VA_ARGS__ ) ) 116 117 #define BIT_ASSEMBLE_5( _ptr, _index, _field, _value, ... ) \ 118 ( BIT_ASSEMBLE_1 ( _ptr, _index, _field, _value ) | \ 119 BIT_ASSEMBLE_4 ( _ptr, _index, __VA_ARGS__ ) ) 120 121 #define BIT_ASSEMBLE_6( _ptr, _index, _field, _value, ... ) \ 122 ( BIT_ASSEMBLE_1 ( _ptr, _index, _field, _value ) | \ 123 BIT_ASSEMBLE_5 ( _ptr, _index, __VA_ARGS__ ) ) 124 125 #define BIT_ASSEMBLE_7( _ptr, _index, _field, _value, ... ) \ 126 ( BIT_ASSEMBLE_1 ( _ptr, _index, _field, _value ) | \ 127 BIT_ASSEMBLE_6 ( _ptr, _index, __VA_ARGS__ ) ) 128 129 /* 130 * Build native-endian (positive) qword bitmasks from named fields 131 * 132 */ 133 134 #define BIT_MASK_1( _ptr, _index, _field ) \ 135 ( BIT_MASK ( _ptr, _field ) << \ 136 QWORD_BIT_OFFSET ( _ptr, _index, _field ) ) 137 138 #define BIT_MASK_2( _ptr, _index, _field, ... ) \ 139 ( BIT_MASK_1 ( _ptr, _index, _field ) | \ 140 BIT_MASK_1 ( _ptr, _index, __VA_ARGS__ ) ) 141 142 #define BIT_MASK_3( _ptr, _index, _field, ... ) \ 143 ( BIT_MASK_1 ( _ptr, _index, _field ) | \ 144 BIT_MASK_2 ( _ptr, _index, __VA_ARGS__ ) ) 145 146 #define BIT_MASK_4( _ptr, _index, _field, ... ) \ 147 ( BIT_MASK_1 ( _ptr, _index, _field ) | \ 148 BIT_MASK_3 ( _ptr, _index, __VA_ARGS__ ) ) 149 150 #define BIT_MASK_5( _ptr, _index, _field, ... ) \ 151 ( BIT_MASK_1 ( _ptr, _index, _field ) | \ 152 BIT_MASK_4 ( _ptr, _index, __VA_ARGS__ ) ) 153 154 #define BIT_MASK_6( _ptr, _index, _field, ... ) \ 155 ( BIT_MASK_1 ( _ptr, _index, _field ) | \ 156 BIT_MASK_5 ( _ptr, _index, __VA_ARGS__ ) ) 157 158 #define BIT_MASK_7( _ptr, _index, _field, ... ) \ 159 ( BIT_MASK_1 ( _ptr, _index, _field ) | \ 160 BIT_MASK_6 ( _ptr, _index, __VA_ARGS__ ) ) 161 162 /* 163 * Populate little-endian qwords from named fields and values 164 * 165 */ 166 167 #define BIT_FILL( _ptr, _index, _assembled ) do { \ 168 uint64_t *__ptr = &(_ptr)->u.qwords[(_index)]; \ 169 uint64_t __assembled = (_assembled); \ 170 *__ptr = cpu_to_BIT64 ( __assembled ); \ 171 } while ( 0 ) 172 173 #define BIT_FILL_1( _ptr, _field1, ... ) \ 174 BIT_FILL ( _ptr, QWORD_OFFSET ( _ptr, _field1 ), \ 175 BIT_ASSEMBLE_1 ( _ptr, QWORD_OFFSET ( _ptr, _field1 ), \ 176 _field1, __VA_ARGS__ ) ) 177 178 #define BIT_FILL_2( _ptr, _field1, ... ) \ 179 BIT_FILL ( _ptr, QWORD_OFFSET ( _ptr, _field1 ), \ 180 BIT_ASSEMBLE_2 ( _ptr, QWORD_OFFSET ( _ptr, _field1 ), \ 181 _field1, __VA_ARGS__ ) ) 182 183 #define BIT_FILL_3( _ptr, _field1, ... ) \ 184 BIT_FILL ( _ptr, QWORD_OFFSET ( _ptr, _field1 ), \ 185 BIT_ASSEMBLE_3 ( _ptr, QWORD_OFFSET ( _ptr, _field1 ), \ 186 _field1, __VA_ARGS__ ) ) 187 188 #define BIT_FILL_4( _ptr, _field1, ... ) \ 189 BIT_FILL ( _ptr, QWORD_OFFSET ( _ptr, _field1 ), \ 190 BIT_ASSEMBLE_4 ( _ptr, QWORD_OFFSET ( _ptr, _field1 ), \ 191 _field1, __VA_ARGS__ ) ) 192 193 #define BIT_FILL_5( _ptr, _field1, ... ) \ 194 BIT_FILL ( _ptr, QWORD_OFFSET ( _ptr, _field1 ), \ 195 BIT_ASSEMBLE_5 ( _ptr, QWORD_OFFSET ( _ptr, _field1 ), \ 196 _field1, __VA_ARGS__ ) ) 197 198 #define BIT_FILL_6( _ptr, _field1, ... ) \ 199 BIT_FILL ( _ptr, QWORD_OFFSET ( _ptr, _field1 ), \ 200 BIT_ASSEMBLE_6 ( _ptr, QWORD_OFFSET ( _ptr, _field1 ), \ 201 _field1, __VA_ARGS__ ) ) 202 203 /** Extract value of named field */ 204 #define BIT_GET64( _ptr, _field ) \ 205 ( { \ 206 unsigned int __index = QWORD_OFFSET ( _ptr, _field ); \ 207 uint64_t *__ptr = &(_ptr)->u.qwords[__index]; \ 208 uint64_t __value = BIT64_to_cpu ( *__ptr ); \ 209 __value >>= \ 210 QWORD_BIT_OFFSET ( _ptr, __index, _field ); \ 211 __value &= BIT_MASK ( _ptr, _field ); \ 212 __value; \ 213 } ) 214 215 /** Extract value of named field (for fields up to the size of a long) */ 216 #define BIT_GET( _ptr, _field ) \ 217 ( ( unsigned long ) BIT_GET64 ( _ptr, _field ) ) 218 219 #define BIT_SET( _ptr, _field, _value ) do { \ 220 unsigned int __index = QWORD_OFFSET ( _ptr, _field ); \ 221 uint64_t *__ptr = &(_ptr)->u.qwords[__index]; \ 222 unsigned int __shift = \ 223 QWORD_BIT_OFFSET ( _ptr, __index, _field ); \ 224 uint64_t __value = (_value); \ 225 *__ptr &= cpu_to_BIT64 ( ~( BIT_MASK ( _ptr, _field ) << \ 226 __shift ) ); \ 227 *__ptr |= cpu_to_BIT64 ( __value << __shift ); \ 228 } while ( 0 ) 229 230 #endif /* _GPXE_BITOPS_H */ 231