mirror of
https://github.com/saymrwulf/pulp-runtime.git
synced 2026-05-16 21:00:16 +00:00
285 lines
8.7 KiB
C
285 lines
8.7 KiB
C
// 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>
|
|
|
|
#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);
|
|
}
|
|
|
|
/**
|
|
* 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`.
|
|
*/
|
|
BITFIELD_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`.
|
|
*/
|
|
BITFIELD_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`.
|
|
*/
|
|
BITFIELD_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`.
|
|
*/
|
|
BITFIELD_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.
|
|
*/
|
|
BITFIELD_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.
|
|
*/
|
|
BITFIELD_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_
|