use crate::ram::Ram; use std::fmt; #[derive(Debug, Clone)] pub enum Opcode { Nop, Push, Pop, Illegal, Sjmp, } #[derive(Debug, Clone)] pub struct Op { opcode: Opcode, size: usize, operand1: Option, operand2: Option, operand3: Option, } const OPCODE_NOP: u8 = 0x00; const OPCODE_PUSH: u8 = 0xC0; const OPCODE_POP: u8 = 0xD0; const OPCODE_SJMP: u8 = 0xD2; impl fmt::Display for Opcode { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{:?}", self) } } impl fmt::Display for Op { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{:?}", self) } } pub struct Core { pc: u16, ram: Ram, } impl Core { pub fn with_ram_from_hex(hex: String) -> Self { Self { pc: 0, ram: Ram::from_hex(hex) } } pub fn step(&mut self) -> u16 { let op = self.fetch(); self.exec(op); self.pc } pub fn op(&self) -> Opcode { self.ram.array[self.pc as usize].op().0 } /// /// Increment PC /// Return the whole operation /// fn fetch(&mut self) -> Op { let mut operand1 = None; let opcode = self.ram.array[self.pc as usize].opcode(); let size = self.ram.array[self.pc as usize].opsize(); if size == 2 { operand1 = Some(self.ram.array[self.pc as usize]); } self.pc += size as u16; Op { opcode, size, operand1, operand2: None, operand3: None, } } fn exec(&mut self, op: Op) { match op.opcode { Opcode::Nop => (), Opcode::Illegal => (), Opcode::Push => (), Opcode::Pop => (), Opcode::Sjmp => self.sjmp(op.operand1.unwrap() as i8), } } fn sjmp(&mut self, reladdr: i8) { self.pc = (self.pc as i16 + reladdr as i16) as u16; } } type Register = u8; pub trait Isa8051 { fn op(&self) -> (Opcode, usize, Option); fn opcode(&self) -> Opcode; fn opsize(&self) -> usize; fn opreg(&self) -> Option; } impl Isa8051 for u8 { fn op(&self) -> (Opcode, usize, Option) { match *self { OPCODE_NOP => (Opcode::Nop, 1, None), OPCODE_PUSH => (Opcode::Push, 2, None), OPCODE_POP => (Opcode::Pop, 2, None), OPCODE_SJMP => (Opcode::Sjmp, 2, None), _ => (Opcode::Illegal, 1, None), } } fn opcode(&self) -> Opcode { self.op().0 } fn opsize(&self) -> usize { self.op().1 } fn opreg(&self) -> Option { self.op().2 } }