use crate::ops;
#[inline]
pub fn bitmask(width: u32) -> u32 {
match width {
0 => 0,
w => 1u32.checked_shl(w).unwrap_or(0).wrapping_sub(1),
}
}
#[inline]
pub fn lrot(word: u32, shift: u32, width: u32) -> u32 {
let width = width % 32;
if width == 0 {
return 0;
}
let mask = bitmask(width);
let shift = shift % width;
let w = word & mask;
((w << shift) | (w >> (width - shift))) & mask
}
#[inline]
pub fn rrot(word: u32, shift: u32, width: u32) -> u32 {
let width = width % 32;
if width == 0 {
return 0;
}
let mask = bitmask(width);
let shift = shift % width;
let w = word & mask;
((w >> shift) | (w << (width - shift))) & mask
}
#[inline]
pub fn bitrange(word: u32, width: u32, start: u32, end: u32) -> u32 {
if start >= end || width == 0 {
return 0;
}
let clamped_end = end.min(width);
let clamped_start = start.min(clamped_end);
let len = clamped_end - clamped_start;
if len == 0 {
return 0;
}
let shift = width.saturating_sub(clamped_end);
(word >> shift) & bitmask(len)
}
#[inline]
pub fn setbit(word: u32, width: u32, pos: u32, bit: u32) -> u32 {
if width == 0 || pos >= width {
return word;
}
let mask = 1u32.checked_shl(width - pos - 1).unwrap_or(0);
if bit & 1 == 1 {
word | mask
} else {
word & !mask
}
}
#[inline]
pub fn tsb(word: u32, width: u32) -> u32 {
(word & bitmask(width)).trailing_ones()
}
#[inline]
pub fn rot2(label: u32) -> u32 {
match label & 3 {
0 => 0,
1 => 2,
2 => 1,
_ => 3,
}
}
#[inline]
pub fn gray2(word: u32) -> u32 {
ops::graycode(word) & 3
}