diff --git a/src/emulator/mod.rs b/src/emulator/mod.rs index e69de29..3ca308d 100644 --- a/src/emulator/mod.rs +++ b/src/emulator/mod.rs @@ -0,0 +1,101 @@ +use std::fmt::Display; + +use osui::state::{DependencyHandler, State}; + +#[derive(Debug, Clone)] +pub struct Registry(pub State<[usize; 8]>); + +#[derive(Debug, Clone)] +pub enum Instruction { + HLT, + REG(u8, usize), + ADD(u8, u8, u8), +} + +pub struct Emulator { + pub pc: State, + pub instructions: Vec, + pub registers: Registry, + pub inst: State, +} + +impl Emulator { + pub fn run(&self) { + loop { + std::thread::sleep(std::time::Duration::from_millis(300)); + let mut pc = self.pc.get(); + if let Some(inst) = self.instructions.get(**pc) { + **self.inst.get() = inst.clone(); + match &inst { + // 1 | Halt + Instruction::HLT => break, + + // 2 | Registry set + Instruction::REG(r, v) => self.registers.set(*r, *v), + + // 3 | Add + Instruction::ADD(rx, ry, r) => { + let x = self.registers.get(*rx); + let y = self.registers.get(*ry); + self.registers.set(*r, x + y); + } + } + **pc += 1; + } else { + break; + } + } + } +} + +impl Registry { + pub fn get(&self, r: u8) -> usize { + match self.0.get().get(r as usize) { + Some(v) => *v, + None => 0, + } + } + + pub fn set(&self, r: u8, v: usize) { + if let Some(o) = self.0.get().get_mut(r as usize) { + *o = v; + } + } +} + +impl Display for Registry { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "rx: {}, ry: {}\nrz: {}, ra: {}", + self.get(0), + self.get(1), + self.get(2), + self.get(3), + ) + } +} + +impl DependencyHandler for Registry { + fn add(&self) { + self.0.add() + } + + fn check(&self) -> bool { + self.0.check() + } +} + +impl Display for Instruction { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "{}", + match self { + Instruction::HLT => format!("HLT"), + Instruction::REG(a, b) => format!("REG {a}, {b}"), + Instruction::ADD(a, b, c) => format!("ADD {a}, {b}, {c}"), + } + ) + } +} diff --git a/src/main.rs b/src/main.rs index 608fd7e..4130ae1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,29 +6,51 @@ use std::sync::Arc; use osui::prelude::*; +use crate::emulator::{Instruction, Registry}; + fn main() { let screen = Screen::new(); + let instructions = vec![ + Instruction::REG(0, 6), + Instruction::REG(1, 7), + Instruction::ADD(0, 1, 2), // 6 + 7 + ]; - app(&screen).draw(&screen); + app(&screen, instructions).draw(&screen); screen.run().unwrap(); } -fn app(_screen: &Arc) -> Rsx { - let pc = use_state::(0); +fn app(_screen: &Arc, instructions: Vec) -> Rsx { + let pc = use_state::(0); + let inst = use_state::(Instruction::HLT); + let registers = Registry(use_state([0; 8])); - // Spawn a thread to emulate the program - std::thread::spawn({ - let pc = pc.clone(); - move || loop { - **pc.get() += 1; - } - }); + let emulator = emulator::Emulator { + pc: pc.clone(), + registers: registers.clone(), + inst: inst.clone(), + instructions, + }; + + std::thread::spawn(move || emulator.run()); rsx! { - FlexRow { + FlexRow, gap: 1, { + @Style { foreground: None, background: Background::RoundedOutline(0x0000ff) }; + @Transform::new().padding(1, 1); %pc "Program Counter: {pc}" + + @Style { foreground: None, background: Background::RoundedOutline(0xff0000) }; + @Transform::new().padding(1, 1); + %registers + "{registers}" } + + @Style { foreground: None, background: Background::RoundedOutline(0x0000ff) }; + @Transform::center().padding(2, 2); + %inst + "Current instruction: {inst}" } }