252 lines
8.1 KiB
Rust
252 lines
8.1 KiB
Rust
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<u8> 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<u8> 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"),
|
|
}
|
|
}
|
|
}
|