Files
damn_simple_architecture/src/common/instructions.rs
T

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"),
}
}
}