| // 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> |
| |
| // Header Extern Guard (so header can be used from C and C++) |
| #ifdef __cplusplus |
| extern "C" { |
| #endif // __cplusplus |
| |
| /** |
| * @file |
| * @brief Bitfield Manipulation Functions |
| */ |
| |
| /** |
| * All the bitfield functions are pure (they do not modify their arguments), so |
| * the result must be used. We enable warnings to ensure this happens. |
| */ |
| #define BITFIELD_WARN_UNUSED_RESULT __attribute__((warn_unused_result)) |
| |
| /** |
| * 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`. |
| */ |
| BITFIELD_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`. |
| */ |
| BITFIELD_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`. |
| */ |
| BITFIELD_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. |
| */ |
| BITFIELD_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`. |
| */ |
| BITFIELD_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); |
| } |
| |
| #ifdef __cplusplus |
| } // extern "C" |
| #endif // __cplusplus |
| |
| #endif // OPENTITAN_SW_DEVICE_LIB_BASE_BITFIELD_H_ |