Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

pseudobit.h 8.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. #ifndef _IPXE_PSEUDOBIT_H
  2. #define _IPXE_PSEUDOBIT_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., 51 Franklin Street, Fifth Floor, Boston, MA
  19. * 02110-1301, USA.
  20. *
  21. * You can also choose to distribute this program under the terms of
  22. * the Unmodified Binary Distribution Licence (as given in the file
  23. * COPYING.UBDL), provided that you have satisfied its requirements.
  24. */
  25. FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
  26. /**
  27. * @file
  28. *
  29. * Pseudo-bit structures
  30. *
  31. */
  32. #include <stdint.h>
  33. #include <byteswap.h>
  34. /* Endianness selection.
  35. *
  36. * This is a property of the device, not a property of the host CPU.
  37. */
  38. #ifdef PSEUDOBIT_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. #define QWORD_SHIFT( offset, width ) (offset)
  44. #endif
  45. #ifdef PSEUDOBIT_BIG_ENDIAN
  46. #define cpu_to_BIT64 cpu_to_be64
  47. #define cpu_to_BIT32 cpu_to_be32
  48. #define BIT64_to_cpu be64_to_cpu
  49. #define BIT32_to_cpu be32_to_cpu
  50. #define QWORD_SHIFT( offset, width ) ( 64 - (offset) - (width) )
  51. #endif
  52. /** Datatype used to represent a bit in the pseudo-structures */
  53. typedef unsigned char pseudo_bit_t;
  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. } __attribute__ (( packed )) u
  70. /** Get pseudo_bit_t structure type from wrapper structure pointer */
  71. #define PSEUDO_BIT_STRUCT_TYPE( _ptr ) \
  72. typeof ( *((_ptr)->u.dummy[0]) )
  73. /** Bit offset of a field within a pseudo_bit_t structure */
  74. #define BIT_OFFSET( _ptr, _field ) \
  75. offsetof ( PSEUDO_BIT_STRUCT_TYPE ( _ptr ), _field )
  76. /** Bit width of a field within a pseudo_bit_t structure */
  77. #define BIT_WIDTH( _ptr, _field ) \
  78. sizeof ( ( ( PSEUDO_BIT_STRUCT_TYPE ( _ptr ) * ) NULL )->_field )
  79. /** Qword offset of a field within a pseudo_bit_t structure */
  80. #define QWORD_OFFSET( _ptr, _field ) \
  81. ( BIT_OFFSET ( _ptr, _field ) / 64 )
  82. /** Qword bit offset of a field within a pseudo_bit_t structure */
  83. #define QWORD_BIT_OFFSET( _ptr, _index, _field ) \
  84. ( BIT_OFFSET ( _ptr, _field ) - ( 64 * (_index) ) )
  85. /** Qword bit shift for a field within a pseudo_bit_t structure */
  86. #define QWORD_BIT_SHIFT( _ptr, _index, _field ) \
  87. QWORD_SHIFT ( QWORD_BIT_OFFSET ( _ptr, _index, _field ), \
  88. BIT_WIDTH ( _ptr, _field ) )
  89. /** Bit mask for a field within a pseudo_bit_t structure */
  90. #define BIT_MASK( _ptr, _field ) \
  91. ( ( ~( ( uint64_t ) 0 ) ) >> \
  92. ( 64 - BIT_WIDTH ( _ptr, _field ) ) )
  93. /*
  94. * Assemble native-endian qword from named fields and values
  95. *
  96. */
  97. #define BIT_ASSEMBLE_1( _ptr, _index, _field, _value ) \
  98. ( ( ( uint64_t) (_value) ) << \
  99. QWORD_BIT_SHIFT ( _ptr, _index, _field ) )
  100. #define BIT_ASSEMBLE_2( _ptr, _index, _field, _value, ... ) \
  101. ( BIT_ASSEMBLE_1 ( _ptr, _index, _field, _value ) | \
  102. BIT_ASSEMBLE_1 ( _ptr, _index, __VA_ARGS__ ) )
  103. #define BIT_ASSEMBLE_3( _ptr, _index, _field, _value, ... ) \
  104. ( BIT_ASSEMBLE_1 ( _ptr, _index, _field, _value ) | \
  105. BIT_ASSEMBLE_2 ( _ptr, _index, __VA_ARGS__ ) )
  106. #define BIT_ASSEMBLE_4( _ptr, _index, _field, _value, ... ) \
  107. ( BIT_ASSEMBLE_1 ( _ptr, _index, _field, _value ) | \
  108. BIT_ASSEMBLE_3 ( _ptr, _index, __VA_ARGS__ ) )
  109. #define BIT_ASSEMBLE_5( _ptr, _index, _field, _value, ... ) \
  110. ( BIT_ASSEMBLE_1 ( _ptr, _index, _field, _value ) | \
  111. BIT_ASSEMBLE_4 ( _ptr, _index, __VA_ARGS__ ) )
  112. #define BIT_ASSEMBLE_6( _ptr, _index, _field, _value, ... ) \
  113. ( BIT_ASSEMBLE_1 ( _ptr, _index, _field, _value ) | \
  114. BIT_ASSEMBLE_5 ( _ptr, _index, __VA_ARGS__ ) )
  115. #define BIT_ASSEMBLE_7( _ptr, _index, _field, _value, ... ) \
  116. ( BIT_ASSEMBLE_1 ( _ptr, _index, _field, _value ) | \
  117. BIT_ASSEMBLE_6 ( _ptr, _index, __VA_ARGS__ ) )
  118. /*
  119. * Build native-endian (positive) qword bitmasks from named fields
  120. *
  121. */
  122. #define BIT_MASK_1( _ptr, _index, _field ) \
  123. ( BIT_MASK ( _ptr, _field ) << \
  124. QWORD_BIT_SHIFT ( _ptr, _index, _field ) )
  125. #define BIT_MASK_2( _ptr, _index, _field, ... ) \
  126. ( BIT_MASK_1 ( _ptr, _index, _field ) | \
  127. BIT_MASK_1 ( _ptr, _index, __VA_ARGS__ ) )
  128. #define BIT_MASK_3( _ptr, _index, _field, ... ) \
  129. ( BIT_MASK_1 ( _ptr, _index, _field ) | \
  130. BIT_MASK_2 ( _ptr, _index, __VA_ARGS__ ) )
  131. #define BIT_MASK_4( _ptr, _index, _field, ... ) \
  132. ( BIT_MASK_1 ( _ptr, _index, _field ) | \
  133. BIT_MASK_3 ( _ptr, _index, __VA_ARGS__ ) )
  134. #define BIT_MASK_5( _ptr, _index, _field, ... ) \
  135. ( BIT_MASK_1 ( _ptr, _index, _field ) | \
  136. BIT_MASK_4 ( _ptr, _index, __VA_ARGS__ ) )
  137. #define BIT_MASK_6( _ptr, _index, _field, ... ) \
  138. ( BIT_MASK_1 ( _ptr, _index, _field ) | \
  139. BIT_MASK_5 ( _ptr, _index, __VA_ARGS__ ) )
  140. #define BIT_MASK_7( _ptr, _index, _field, ... ) \
  141. ( BIT_MASK_1 ( _ptr, _index, _field ) | \
  142. BIT_MASK_6 ( _ptr, _index, __VA_ARGS__ ) )
  143. /*
  144. * Populate device-endian qwords from named fields and values
  145. *
  146. */
  147. #define BIT_FILL( _ptr, _index, _assembled ) do { \
  148. uint64_t *__ptr = &(_ptr)->u.qwords[(_index)]; \
  149. uint64_t __assembled = (_assembled); \
  150. *__ptr = cpu_to_BIT64 ( __assembled ); \
  151. } while ( 0 )
  152. #define BIT_FILL_1( _ptr, _field1, ... ) \
  153. BIT_FILL ( _ptr, QWORD_OFFSET ( _ptr, _field1 ), \
  154. BIT_ASSEMBLE_1 ( _ptr, QWORD_OFFSET ( _ptr, _field1 ), \
  155. _field1, __VA_ARGS__ ) )
  156. #define BIT_FILL_2( _ptr, _field1, ... ) \
  157. BIT_FILL ( _ptr, QWORD_OFFSET ( _ptr, _field1 ), \
  158. BIT_ASSEMBLE_2 ( _ptr, QWORD_OFFSET ( _ptr, _field1 ), \
  159. _field1, __VA_ARGS__ ) )
  160. #define BIT_FILL_3( _ptr, _field1, ... ) \
  161. BIT_FILL ( _ptr, QWORD_OFFSET ( _ptr, _field1 ), \
  162. BIT_ASSEMBLE_3 ( _ptr, QWORD_OFFSET ( _ptr, _field1 ), \
  163. _field1, __VA_ARGS__ ) )
  164. #define BIT_FILL_4( _ptr, _field1, ... ) \
  165. BIT_FILL ( _ptr, QWORD_OFFSET ( _ptr, _field1 ), \
  166. BIT_ASSEMBLE_4 ( _ptr, QWORD_OFFSET ( _ptr, _field1 ), \
  167. _field1, __VA_ARGS__ ) )
  168. #define BIT_FILL_5( _ptr, _field1, ... ) \
  169. BIT_FILL ( _ptr, QWORD_OFFSET ( _ptr, _field1 ), \
  170. BIT_ASSEMBLE_5 ( _ptr, QWORD_OFFSET ( _ptr, _field1 ), \
  171. _field1, __VA_ARGS__ ) )
  172. #define BIT_FILL_6( _ptr, _field1, ... ) \
  173. BIT_FILL ( _ptr, QWORD_OFFSET ( _ptr, _field1 ), \
  174. BIT_ASSEMBLE_6 ( _ptr, QWORD_OFFSET ( _ptr, _field1 ), \
  175. _field1, __VA_ARGS__ ) )
  176. #define BIT_QWORD_PTR( _ptr, _field ) \
  177. ( { \
  178. unsigned int __index = QWORD_OFFSET ( _ptr, _field ); \
  179. uint64_t *__ptr = &(_ptr)->u.qwords[__index]; \
  180. __ptr; \
  181. } )
  182. /** Extract value of named field */
  183. #define BIT_GET64( _ptr, _field ) \
  184. ( { \
  185. unsigned int __index = QWORD_OFFSET ( _ptr, _field ); \
  186. uint64_t *__ptr = &(_ptr)->u.qwords[__index]; \
  187. uint64_t __value = BIT64_to_cpu ( *__ptr ); \
  188. __value >>= \
  189. QWORD_BIT_SHIFT ( _ptr, __index, _field ); \
  190. __value &= BIT_MASK ( _ptr, _field ); \
  191. __value; \
  192. } )
  193. /** Extract value of named field (for fields up to the size of a long) */
  194. #define BIT_GET( _ptr, _field ) \
  195. ( ( unsigned long ) BIT_GET64 ( _ptr, _field ) )
  196. #define BIT_SET( _ptr, _field, _value ) do { \
  197. unsigned int __index = QWORD_OFFSET ( _ptr, _field ); \
  198. uint64_t *__ptr = &(_ptr)->u.qwords[__index]; \
  199. unsigned int __shift = \
  200. QWORD_BIT_SHIFT ( _ptr, __index, _field ); \
  201. uint64_t __value = (_value); \
  202. *__ptr &= cpu_to_BIT64 ( ~( BIT_MASK ( _ptr, _field ) << \
  203. __shift ) ); \
  204. *__ptr |= cpu_to_BIT64 ( __value << __shift ); \
  205. } while ( 0 )
  206. #endif /* _IPXE_PSEUDOBIT_H */