type Offset = u16; type Immediate = u16; #[derive(Copy, Clone, Debug, PartialEq)] pub enum Interrupt { Software(u8), } pub type Address = u32; impl Interrupt { fn as_u8(&self) -> u8 { match self { Interrupt::Software(code) => *code, } } } impl From for Interrupt { fn from(_code: u8) -> Self { todo!("implement this once a hardware interrupt convention is established"); #[allow(unreachable_code)] Interrupt::Software(_code) } } #[derive(Copy, Clone, Debug, PartialEq)] pub enum Register { // general purpose registers Rg0, Rg1, Rg2, Rg3, Rg4, Rg5, Rg6, Rg7, Rg8, Rg9, Rga, Rgb, Rgc, Rgd, Rge, Rgf, // special purpose registers Acc, Spr, Bpr, Ret, Idr, Mmr, Zero, None, // system registers - can't be written to by instructions. Mar, Mdr, Sts, Cir, Pcx, } impl From for Register { fn from(idx: u8) -> Register { match idx { // system registers are not indexable in the reg file so they cannot be modified by instructions. 0x0 => Register::Rg0, 0x1 => Register::Rg1, 0x2 => Register::Rg2, 0x3 => Register::Rg3, 0x4 => Register::Rg4, 0x5 => Register::Rg5, 0x6 => Register::Rg6, 0x7 => Register::Rg7, 0x8 => Register::Rg8, 0x9 => Register::Rg9, 0xA => Register::Rga, 0xB => Register::Rgb, 0xC => Register::Rgc, 0xD => Register::Rgd, 0xE => Register::Rge, 0xF => Register::Rgf, 0x10 => Register::Acc, 0x11 => Register::Spr, 0x12 => Register::Bpr, 0x13 => Register::Ret, 0x14 => Register::Idr, 0x15 => Register::Mmr, 0x16 => Register::Zero, 0x17 => Register::None, _ => panic!("invalid register"), } } } impl std::fmt::Display for Register { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Register::Rg0 => write!(f, "Rg0"), Register::Rg1 => write!(f, "Rg1"), Register::Rg2 => write!(f, "Rg2"), Register::Rg3 => write!(f, "Rg3"), Register::Rg4 => write!(f, "Rg4"), Register::Rg5 => write!(f, "Rg5"), Register::Rg6 => write!(f, "Rg6"), Register::Rg7 => write!(f, "Rg7"), Register::Rg8 => write!(f, "Rg8"), Register::Rg9 => write!(f, "Rg9"), Register::Rga => write!(f, "Rga"), Register::Rgb => write!(f, "Rgb"), Register::Rgc => write!(f, "Rgc"), Register::Rgd => write!(f, "Rgd"), Register::Rge => write!(f, "Rge"), Register::Rgf => write!(f, "Rgf"), Register::Acc => write!(f, "Acc"), Register::Spr => write!(f, "Spr"), Register::Bpr => write!(f, "Bpr"), Register::Ret => write!(f, "Ret"), Register::Idr => write!(f, "Idr"), Register::Mmr => write!(f, "Mmr"), Register::Zero => write!(f, "Zero"), Register::None => write!(f, "None"), Register::Mar => write!(f, "Mar"), Register::Mdr => write!(f, "Mdr"), Register::Sts => write!(f, "Sts"), Register::Cir => write!(f, "Cir"), Register::Pcx => write!(f, "Pcx"), } } } #[derive(Debug, Clone)] pub enum Instruction { // No-op Nop, // Data transfer instructions Mov(Register, Register), MovSigned(Register, Register), LoadByte(Register, Offset, Register), LoadByteSigned(Register, Offset, Register), LoadHalfword(Register, Offset, Register), LoadHalfwordSigned(Register, Offset, Register), LoadWord(Register, Offset, Register), StoreByte(Register, Offset, Register), StoreHalfword(Register, Offset, Register), StoreWord(Register, Offset, Register), LoadLowerImmediate(Register, Immediate), LoadUpperImmediate(Register, Immediate), // Jump Instructions Jump(Register, Offset), JumpEq(Register, Offset), JumpNeq(Register, Offset), JumpGt(Register, Offset), JumpGe(Register, Offset), JumpLt(Register, Offset), JumpLe(Register, Offset), // Comparison Compare(Register, Register), // Arithmetic Add(Register, Register, Register), Sub(Register, Register, Register), Increment(Register), Decrement(Register), ShiftLeft(Register, Register, Immediate), ShiftRight(Register, Register, Immediate), // Logical And(Register, Register, Register), Or(Register, Register, Register), Not(Register, Register), Xor(Register, Register, Register), Nand(Register, Register, Register), Nor(Register, Register, Register), Xnor(Register, Register, Register), // Misc Interrupt(Interrupt), IntReturn, Halt, } impl Instruction { pub fn encode(&self) -> u32 { todo!("imlement instruction encoding") } pub fn decode(data: u32) -> Self { // TODO: this needs to actually decode something Instruction::Nop } } impl std::fmt::Display for Instruction { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Instruction::Nop => write!(f, "No Operation"), Instruction::Mov(a, b) => write!(f, "MOV {}, {}", a, b), Instruction::MovSigned(a, b) => write!(f, "MOVS {}, {}", a, b), Instruction::LoadByte(a, b, c) => write!(f, "LDB {}, {}, {}", a, b, c), Instruction::LoadByteSigned(a, b, c) => write!(f, "LDBS {}, {}, {}", a, b, c), Instruction::LoadHalfword(a, b, c) => write!(f, "LDH {}, {}, {}", a, b, c), Instruction::LoadHalfwordSigned(a, b, c) => write!(f, "LDHS {}, {}, {}", a, b, c), Instruction::LoadWord(a, b, c) => write!(f, "LDW {}, {}, {}", a, b, c), Instruction::StoreByte(a, b, c) => write!(f, "STB {}, {}, {}", a, b, c), Instruction::StoreHalfword(a, b, c) => write!(f, "STH {}, {}, {}", a, b, c), Instruction::StoreWord(a, b, c) => write!(f, "STW {}, {}, {}", a, b, c), Instruction::LoadLowerImmediate(a, b) => write!(f, "LLI {}, {}", a, b), Instruction::LoadUpperImmediate(a, b) => write!(f, "LUI {}, {}", a, b), Instruction::Jump(a, b) => write!(f, "JMP {}, {}", a, b), Instruction::JumpEq(a, b) => write!(f, "JEQ {}, {}", a, b), Instruction::JumpNeq(a, b) => write!(f, "JNEQ {}, {}", a, b), Instruction::JumpGt(a, b) => write!(f, "JGT {}, {}", a, b), Instruction::JumpGe(a, b) => write!(f, "JGE {}, {}", a, b), Instruction::JumpLt(a, b) => write!(f, "JLT {}, {}", a, b), Instruction::JumpLe(a, b) => write!(f, "JLE {}, {}", a, b), Instruction::Compare(a, b) => write!(f, "CMP {}, {}", a, b), Instruction::Add(a, b, c) => write!(f, "ADD {}, {}, {}", a, b, c), Instruction::Sub(a, b, c) => write!(f, "SUB {}, {}, {}", a, b, c), Instruction::Increment(a) => write!(f, "INC {}", a), Instruction::Decrement(a) => write!(f, "DEC {}", a), Instruction::ShiftLeft(a, b, c) => write!(f, "SHL {}, {}, {}", a, b, c), Instruction::ShiftRight(a, b, c) => write!(f, "SHR {}, {}, {}", a, b, c), Instruction::And(a, b, c) => write!(f, "AND {}, {}, {}", a, b, c), Instruction::Or(a, b, c) => write!(f, "OR {}, {}, {}", a, b, c), Instruction::Not(a, b) => write!(f, "NOT {}, {}", a, b), Instruction::Xor(a, b, c) => write!(f, "XOR {}, {}, {}", a, b, c), Instruction::Nand(a, b, c) => write!(f, "NAND {}, {}, {}", a, b, c), Instruction::Nor(a, b, c) => write!(f, "NOR {}, {}, {}", a, b, c), Instruction::Xnor(a, b, c) => write!(f, "XNOR {}, {}, {}", a, b, c), Instruction::Interrupt(a) => write!(f, "INT {}", a.as_u8()), Instruction::IntReturn => write!(f, "INTR"), Instruction::Halt => write!(f, "HALT"), } } }