| // Copyright lowRISC contributors. | 
 | // Licensed under the Apache License, Version 2.0, see LICENSE for details. | 
 | // SPDX-License-Identifier: Apache-2.0 | 
 |  | 
 | #ifndef OPENTITAN_SW_DEVICE_LIB_BASE_BITFIELD_H_ | 
 | #define OPENTITAN_SW_DEVICE_LIB_BASE_BITFIELD_H_ | 
 |  | 
 | #include <stdbool.h> | 
 | #include <stdint.h> | 
 |  | 
 | #include "sw/device/lib/base/macros.h" | 
 |  | 
 | #ifdef __cplusplus | 
 | extern "C" { | 
 | #endif  // __cplusplus | 
 |  | 
 | /** | 
 |  * @file | 
 |  * @brief Bitfield Manipulation Functions | 
 |  */ | 
 |  | 
 | /** | 
 |  * A field of a 32-bit bitfield. | 
 |  * | 
 |  * The following field definition: `{ .mask = 0b11, .index = 12 }` | 
 |  * | 
 |  * Denotes the X-marked bits in the following 32-bit bitfield: | 
 |  * | 
 |  *     field:  0b--------'--------'--XX----'-------- | 
 |  *     index:   31                                 0 | 
 |  * | 
 |  * Restrictions: The index plus the width of the mask must not be greater than | 
 |  * 31. | 
 |  */ | 
 | typedef struct bitfield_field32 { | 
 |   /** The field mask. Usually all ones. */ | 
 |   uint32_t mask; | 
 |   /** The field position in the bitfield, counting from the zero-bit. */ | 
 |   uint32_t index; | 
 | } bitfield_field32_t; | 
 |  | 
 | /** | 
 |  * Reads a value from `field` in `bitfield`. | 
 |  * | 
 |  * This function uses the `field` parameter to read the value from `bitfield`. | 
 |  * The resulting value will be shifted right and zero-extended so the field's | 
 |  * zero-bit is the return value's zero-bit. | 
 |  * | 
 |  * @param bitfield Bitfield to get the field from. | 
 |  * @param field Field to read out from. | 
 |  * @return Zero-extended `field` from `bitfield`. | 
 |  */ | 
 | OT_WARN_UNUSED_RESULT | 
 | inline uint32_t bitfield_field32_read(uint32_t bitfield, | 
 |                                       bitfield_field32_t field) { | 
 |   return (bitfield >> field.index) & field.mask; | 
 | } | 
 |  | 
 | /** | 
 |  * Writes `value` to `field` in `bitfield`. | 
 |  * | 
 |  * This function uses the `field` parameter to set specific bits in `bitfield`. | 
 |  * The relevant portion of `bitfield` is zeroed before the bits are set to | 
 |  * `value`. | 
 |  * | 
 |  * @param bitfield Bitfield to set the field in. | 
 |  * @param field Field within bitfield to be set. | 
 |  * @param value Value for the new field. | 
 |  * @return `bitfield` with `field` set to `value`. | 
 |  */ | 
 | OT_WARN_UNUSED_RESULT | 
 | inline uint32_t bitfield_field32_write(uint32_t bitfield, | 
 |                                        bitfield_field32_t field, | 
 |                                        uint32_t value) { | 
 |   bitfield &= ~(field.mask << field.index); | 
 |   bitfield |= (value & field.mask) << field.index; | 
 |   return bitfield; | 
 | } | 
 |  | 
 | /** | 
 |  * A single bit in a 32-bit bitfield. | 
 |  * | 
 |  * This denotes the position of a single bit, counting from the zero-bit. | 
 |  * | 
 |  * For instance, `(bitfield_bit_index_t)4` denotes the X-marked bit in the | 
 |  * following 32-bit bitfield: | 
 |  * | 
 |  *     field:  0b--------'--------'--------'---X---- | 
 |  *     index:   31                                 0 | 
 |  * | 
 |  * Restrictions: The value must not be greater than 31. | 
 |  */ | 
 | typedef uint32_t bitfield_bit32_index_t; | 
 |  | 
 | /** | 
 |  * Turns a `bitfield_bit32_index_t` into a `bitfield_field32_t` (which is more | 
 |  * general). | 
 |  * | 
 |  * @param bit_index The corresponding single bit to turn into a field. | 
 |  * @return A 1-bit field that corresponds to `bit_index`. | 
 |  */ | 
 | OT_WARN_UNUSED_RESULT | 
 | inline bitfield_field32_t bitfield_bit32_to_field32( | 
 |     bitfield_bit32_index_t bit_index) { | 
 |   return (bitfield_field32_t){ | 
 |       .mask = 0x1, .index = bit_index, | 
 |   }; | 
 | } | 
 |  | 
 | /** | 
 |  * Reads the `bit_index`th bit in `bitfield`. | 
 |  * | 
 |  * @param bitfield Bitfield to get the bit from. | 
 |  * @param bit_index Bit to read. | 
 |  * @return `true` if the bit was one, `false` otherwise. | 
 |  */ | 
 | OT_WARN_UNUSED_RESULT | 
 | inline bool bitfield_bit32_read(uint32_t bitfield, | 
 |                                 bitfield_bit32_index_t bit_index) { | 
 |   return bitfield_field32_read(bitfield, | 
 |                                bitfield_bit32_to_field32(bit_index)) == 0x1u; | 
 | } | 
 |  | 
 | /** | 
 |  * Writes `value` to the `bit_index`th bit in `bitfield`. | 
 |  * | 
 |  * @param bitfield Bitfield to update the bit in. | 
 |  * @param bit_index Bit to update. | 
 |  * @param value Bit value to write to `bitfield`. | 
 |  * @return `bitfield` with the `bit_index`th bit set to `value`. | 
 |  */ | 
 | OT_WARN_UNUSED_RESULT | 
 | inline uint32_t bitfield_bit32_write(uint32_t bitfield, | 
 |                                      bitfield_bit32_index_t bit_index, | 
 |                                      bool value) { | 
 |   return bitfield_field32_write(bitfield, bitfield_bit32_to_field32(bit_index), | 
 |                                 value ? 0x1u : 0x0u); | 
 | } | 
 |  | 
 | /** | 
 |  * Find First Set Bit | 
 |  * | 
 |  * Returns one plus the index of the least-significant 1-bit of a 32-bit word. | 
 |  * | 
 |  * For instance, `bitfield_find_first_set32(field)` of the below 32-bit value | 
 |  * returns `5`. | 
 |  * | 
 |  *     field:  0b00000000'00000000'11111111'00010000 | 
 |  *     index:   31                                 0 | 
 |  * | 
 |  * This is the canonical definition for the GCC/Clang builtin `__builtin_ffs`, | 
 |  * and hence takes and returns a signed integer. | 
 |  * | 
 |  * @param bitfield Bitfield to find the first set bit in. | 
 |  * @return One plus the index of the least-significant 1-bit of `bitfield`. | 
 |  */ | 
 | OT_WARN_UNUSED_RESULT | 
 | inline int32_t bitfield_find_first_set32(int32_t bitfield) { | 
 |   return __builtin_ffs(bitfield); | 
 | } | 
 |  | 
 | /** | 
 |  * Count Leading Zeroes | 
 |  * | 
 |  * Returns the number of leading 0-bits in `bitfield`, starting at the most | 
 |  * significant bit position. If `bitfield` is 0, the result is 32, to match the | 
 |  * RISC-V B Extension. | 
 |  * | 
 |  * For instance, `bitfield_count_leading_zeroes32(field)` of the below 32-bit | 
 |  * value returns `16`. | 
 |  * | 
 |  *     field:  0b00000000'00000000'11111111'00010000 | 
 |  *     index:   31                                 0 | 
 |  * | 
 |  * This is the canonical definition for the GCC/Clang builtin `__builtin_clz`, | 
 |  * and hence returns a signed integer. | 
 |  * | 
 |  * @param bitfield Bitfield to count leading 0-bits from. | 
 |  * @return The number of leading 0-bits in `bitfield`. | 
 |  */ | 
 | OT_WARN_UNUSED_RESULT | 
 | inline int32_t bitfield_count_leading_zeroes32(uint32_t bitfield) { | 
 |   return (bitfield != 0) ? __builtin_clz(bitfield) : 32; | 
 | } | 
 |  | 
 | /** | 
 |  * Count Trailing Zeroes | 
 |  * | 
 |  * Returns the number of trailing 0-bits in `bitfield`, starting at the least | 
 |  * significant bit position. If `bitfield` is 0, the result is 32, to match the | 
 |  * RISC-V B Extension. | 
 |  * | 
 |  * For instance, `bitfield_count_trailing_zeroes32(field)` of the below 32-bit | 
 |  * value returns `4`. | 
 |  * | 
 |  *     field:  0b00000000'00000000'11111111'00010000 | 
 |  *     index:   31                                 0 | 
 |  * | 
 |  * This is the canonical definition for the GCC/Clang builtin `__builtin_ctz`, | 
 |  * and hence returns a signed integer. | 
 |  * | 
 |  * @param bitfield Bitfield to count trailing 0-bits from. | 
 |  * @return The number of trailing 0-bits in `bitfield`. | 
 |  */ | 
 | OT_WARN_UNUSED_RESULT | 
 | inline int32_t bitfield_count_trailing_zeroes32(uint32_t bitfield) { | 
 |   return (bitfield != 0) ? __builtin_ctz(bitfield) : 32; | 
 | } | 
 |  | 
 | /** | 
 |  * Count Set Bits | 
 |  * | 
 |  * Returns the number of 1-bits in `bitfield`. | 
 |  * | 
 |  * For instance, `bitfield_popcount32(field)` of the below 32-bit value returns | 
 |  * `9`. | 
 |  * | 
 |  *     field:  0b00000000'00000000'11111111'00010000 | 
 |  *     index:   31                                 0 | 
 |  * | 
 |  * This is the canonical definition for the GCC/Clang builtin | 
 |  * `__builtin_popcount`, and hence returns a signed integer. | 
 |  * | 
 |  * @param bitfield Bitfield to count 1-bits from. | 
 |  * @return The number of 1-bits in `bitfield`. | 
 |  */ | 
 | OT_WARN_UNUSED_RESULT | 
 | inline int32_t bitfield_popcount32(uint32_t bitfield) { | 
 |   return __builtin_popcount(bitfield); | 
 | } | 
 |  | 
 | /** | 
 |  * Parity | 
 |  * | 
 |  * Returns the number of 1-bits in `bitfield`, modulo 2. | 
 |  * | 
 |  * For instance, `bitfield_parity32(field)` of the below 32-bit value returns | 
 |  * `1`. | 
 |  * | 
 |  *     field:  0b00000000'00000000'11111111'00010000 | 
 |  *     index:   31                                 0 | 
 |  * | 
 |  * This is the canonical definition for the GCC/Clang builtin | 
 |  * `__builtin_parity`, and hence returns a signed integer. | 
 |  * | 
 |  * @param bitfield Bitfield to count 1-bits from. | 
 |  * @return The number of 1-bits in `bitfield`, modulo 2. | 
 |  */ | 
 | OT_WARN_UNUSED_RESULT | 
 | inline int32_t bitfield_parity32(uint32_t bitfield) { | 
 |   return __builtin_parity(bitfield); | 
 | } | 
 |  | 
 | /** | 
 |  * Byte Swap | 
 |  * | 
 |  * Returns `field` with the order of the bytes reversed. Bytes here always means | 
 |  * exactly 8 bits. | 
 |  * | 
 |  * For instance, `byteswap(field)` of the below 32-bit value returns `1`. | 
 |  * | 
 |  *     field:  0bAAAAAAAA'BBBBBBBB'CCCCCCCC'DDDDDDDD | 
 |  *     index:   31                                 0 | 
 |  *    returns: 0bDDDDDDDD'CCCCCCCC'BBBBBBBB'AAAAAAAA | 
 |  * | 
 |  * This is the canonical definition for the GCC/Clang builtin | 
 |  * `__builtin_bswap32`. | 
 |  * | 
 |  * @param bitfield Bitfield to reverse bytes of. | 
 |  * @return `bitfield` with the order of bytes reversed. | 
 |  */ | 
 | OT_WARN_UNUSED_RESULT | 
 | inline uint32_t bitfield_byteswap32(uint32_t bitfield) { | 
 |   return __builtin_bswap32(bitfield); | 
 | } | 
 |  | 
 | #ifdef __cplusplus | 
 | }  // extern "C" | 
 | #endif  // __cplusplus | 
 |  | 
 | #endif  // OPENTITAN_SW_DEVICE_LIB_BASE_BITFIELD_H_ |