122 lines
3.9 KiB
Rust

pub struct InstructionUtil {}
impl InstructionUtil {
/// Byte To Bools
/// Convert a u8 byte to an array of bool
pub fn byte_to_bools(to_convert: u8) -> [bool; 8] {
let mut return_values = [false; 8];
for i in 0..8 {
let new_value = to_convert >> i & 0x1 == 1;
return_values[i as usize] = new_value;
}
return_values
}
/// Byte To Bools
/// Convert an array of bool to a u8
pub fn bools_to_byte(to_convert: [bool; 8]) -> u8 {
let mut return_value = 0u8;
for i in 0..to_convert.len() {
let new_bit = 0x1 << i;
if to_convert[i] {
return_value |= new_bit
}
}
return_value
}
/// Split Bytes
/// Split a u16 into a pair of u8 values for high and low byte
pub fn split_bytes(to_split: u16) -> (u8, u8) {
let high = to_split.rotate_left(8) as u8;
let low = (to_split & 0xff) as u8;
(high, low)
}
/// Join Bytes
/// Joins 2 u8 into a single u16 with high and low
/// bytes provided
pub fn join_bytes(high: u8, low: u8) -> u16 {
(high as u16) << 8 | low as u16
}
/// Swap Endian
/// Swaps the endianess of a value
/// 0xabcd -> 0xcdab
pub fn swap_endian(to_swap:u16) -> u16 {
let low = to_swap & 0xff;
let high = to_swap & 0xff00;
low << 8 | high >> 8
}
/// Split Bytes Swap Endian
/// Swaps endianness and return both bytes separately
pub fn split_bytes_swap_endian(to_split: u16) -> (u8, u8) {
InstructionUtil::split_bytes(InstructionUtil::swap_endian(to_split))
}
/// Join Bytes Swap Endian
/// Swaps endianness and returns the combined bytes
pub fn join_bytes_swap_endian(high :u8, low: u8) -> u16 {
InstructionUtil::swap_endian(InstructionUtil::join_bytes(high, low))
}
/// Read Address from Instruction
/// Reads the 'address' portion of an instruction
/// Returns the 12 LSB
/// 0xabcd -> 0x0bcd
pub fn read_addr_from_instruction(instruction_to_read_from: u16) -> u16 {
instruction_to_read_from & 0x0FFF
}
/// Read Nibble from Instruction
/// Returns the lowest 4 bits of the instruction
/// 0xabcd -> 0x0d
pub fn read_nibble_from_instruction(instruction_to_read_from: u16) -> u8 {
( instruction_to_read_from & 0x000F )as u8
}
/// Read X From Instruction
/// Returns the 4 LSB of the high byte of the instruction
/// Returns bits 9-13
/// 0xabcd -> 0x0b
pub fn read_x_from_instruction(instruction_to_read_from: u16) -> u8 {
(instruction_to_read_from & 0x0F00).rotate_right(8) as u8
}
/// Read Y from Instruction
/// Returns the 4 MSB from the low byte of the instruction
/// Returns bits 5-8
/// 0xabcd -> 0x0c
pub fn read_y_from_instruction(instruction_to_read_from: u16) -> u8 {
(instruction_to_read_from & 0x00F0).rotate_right(4) as u8
}
/// Read Byte from Instruction
/// Returns the 8 LSB from the instruction
/// Returns bits 0-7
/// 0xabcd -> 0xcd
pub fn read_byte_from_instruction(instruction_to_read_from: u16) -> u8 {
(instruction_to_read_from & 0x00FF) as u8
}
/// Alias for read_x_from_instruction
pub fn read_upper_byte_lower_nibble(to_read_from: u16) -> u8 {
InstructionUtil::read_x_from_instruction(to_read_from)
}
pub fn read_bits_from_instruction(instruction_bytes: u16, first_bit: u8, last_bit: u8) -> u16 {
// shift the value over by the 'first bit' bits
let working = instruction_bytes.rotate_right(first_bit as u32);
let mut working_mask: i32 = 0x00;
// build the mask
for _ in first_bit..=last_bit {
working_mask = working_mask.rotate_left(1) | 0x01;
}
// apply the mask to the working value
working & working_mask as u16
}
}