You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

bitops.h 8.1KB

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