| // 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); |
| } |
| |
| /** |
| * Copies a bit from one bit set to the other. |
| * |
| * @param dest Bitfield to write to. |
| * @param dest_bit Bit to write to. |
| * @param src Bitfield to read from. |
| * @param src_bit Bit to read from. |
| * @return `dest` with the copied bit applied. |
| */ |
| OT_WARN_UNUSED_RESULT |
| inline uint32_t bitfield_bit32_copy(uint32_t dest, |
| bitfield_bit32_index_t dest_bit, |
| uint32_t src, |
| bitfield_bit32_index_t src_bit) { |
| return bitfield_bit32_write(dest, dest_bit, |
| bitfield_bit32_read(src, src_bit)); |
| } |
| |
| /** |
| * 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); |
| } |
| |
| /** |
| * Check whether the bitfield value is power of two aligned. |
| * |
| * Zero will also return false. |
| * |
| * @param bitfield Value to be verified. |
| * @return True if bitfield is power of two, otherwise false. |
| */ |
| inline bool bitfield_is_power_of_two32(uint32_t bitfield) { |
| return bitfield != 0 && (bitfield & (bitfield - 1)) == 0; |
| } |
| |
| #ifdef __cplusplus |
| } // extern "C" |
| #endif // __cplusplus |
| |
| #endif // OPENTITAN_SW_DEVICE_LIB_BASE_BITFIELD_H_ |