#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub(crate) enum Barrel {
Left,
ArithmeticRight,
LogicalRight,
FillRight,
Rotate,
}
pub(crate) fn swap_nibbles(accumulator: u8) -> u8 {
accumulator.rotate_left(4)
}
pub(crate) fn mirror(accumulator: u8) -> u8 {
accumulator.reverse_bits()
}
pub(crate) fn multiply(de: u16) -> u16 {
let [high, low] = de.to_be_bytes();
u16::from(high) * u16::from(low)
}
pub(crate) fn add_accumulator(pair: u16, accumulator: u8) -> u16 {
pair.wrapping_add(u16::from(accumulator))
}
pub(crate) fn add_immediate(pair: u16, immediate: u16) -> u16 {
pair.wrapping_add(immediate)
}
pub(crate) fn bit_from_low_three(e: u8) -> u8 {
0x80 >> (e & 0x07)
}
pub(crate) fn pixel_address(de: u16) -> u16 {
let [d, e] = de.to_be_bytes();
let high = 0b0100_0000 | ((d & 0b1100_0000) >> 3) | (d & 0b0000_0111);
let low = ((d & 0b0011_1000) << 2) | ((e & 0b1111_1000) >> 3);
u16::from_be_bytes([high, low])
}
pub(crate) fn pixel_down(hl: u16) -> u16 {
let [h, l] = hl.to_be_bytes();
let counted = ((h & 0b0001_1000) << 3) | ((l & 0b1110_0000) >> 2) | (h & 0b0000_0111);
let stepped = counted.wrapping_add(1);
let high = (h & 0b1110_0000) | ((stepped & 0b1100_0000) >> 3) | (stepped & 0b0000_0111);
let low = ((stepped & 0b0011_1000) << 2) | (l & 0b0001_1111);
u16::from_be_bytes([high, low])
}
pub(crate) fn barrel(de: u16, count: u8, kind: Barrel) -> u16 {
let places = u32::from(count & 0x1F);
match kind {
Barrel::Rotate => de.rotate_left(places % 16),
Barrel::Left => de.checked_shl(places).unwrap_or(0),
Barrel::LogicalRight => de.checked_shr(places).unwrap_or(0),
Barrel::ArithmeticRight => {
let signed = de.cast_signed();
if places >= 16 {
if signed < 0 { 0xFFFF } else { 0 }
} else {
(signed >> places).cast_unsigned()
}
}
Barrel::FillRight => {
if places >= 16 {
0xFFFF
} else if places == 0 {
de
} else {
(de >> places) | !(u16::MAX >> places)
}
}
}
}
#[cfg(test)]
#[path = "extended_tests.rs"]
mod tests;