use crate::MemSpace;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct EncodedInstruction {
pub word0: u32,
pub word1: Option<u32>,
}
#[derive(Debug)]
pub struct EncodeError {
pub msg: String,
}
impl std::fmt::Display for EncodeError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "encode error: {}", self.msg)
}
}
impl std::error::Error for EncodeError {}
pub type Result<T> = std::result::Result<T, EncodeError>;
pub fn enc_err(msg: &str) -> EncodeError {
EncodeError {
msg: msg.to_string(),
}
}
pub fn word(w0: u32) -> EncodedInstruction {
EncodedInstruction {
word0: w0 & 0xFFFFFF,
word1: None,
}
}
pub fn words(w0: u32, w1: u32) -> EncodedInstruction {
EncodedInstruction {
word0: w0 & 0xFFFFFF,
word1: Some(w1 & 0xFFFFFF),
}
}
pub fn space_bit(space: MemSpace) -> u32 {
match space {
MemSpace::X => 0,
MemSpace::Y => 1,
MemSpace::P => 0,
}
}
pub fn encode_rel9(rel9: u32) -> u32 {
((rel9 & 0x1E0) << 1) | (rel9 & 0x1F)
}
pub fn encode_ea_mode(mode: u8, reg: u8) -> u8 {
(mode << 3) | (reg & 7)
}
pub fn pack_loop_count(count: u32) -> (u32, u32) {
(count & 0xFF, (count >> 8) & 0xF)
}
pub fn pm4_reg_split(reg_idx: u32) -> (u32, u32) {
let v = reg_idx & 0x1F;
((v >> 3) & 3, v & 7)
}
pub fn l_reg_split(lreg_idx: u32) -> (u32, u32) {
((lreg_idx >> 2) & 1, lreg_idx & 3)
}
pub fn pack_xy_imm_offset(off7: u32) -> (u32, u32) {
((off7 >> 1) & 0x3F, off7 & 1)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::MemSpace;
#[test]
fn test_space_bit() {
assert_eq!(space_bit(MemSpace::X), 0);
assert_eq!(space_bit(MemSpace::Y), 1);
assert_eq!(space_bit(MemSpace::P), 0);
}
#[test]
fn test_encode_rel9() {
assert_eq!(encode_rel9(0x1F), 0x1F);
assert_eq!(encode_rel9(0x1E0), 0x3C0);
assert_eq!(encode_rel9(0x1FF), 0x3DF);
assert_eq!(encode_rel9(0), 0);
}
#[test]
fn test_encode_ea_mode() {
assert_eq!(encode_ea_mode(0, 0), 0b000_000);
assert_eq!(encode_ea_mode(3, 2), 0b011_010);
assert_eq!(encode_ea_mode(7, 7), 0b111_111);
assert_eq!(encode_ea_mode(1, 0b1001), 0b001_001);
}
}