This commit is contained in:
2025-10-29 18:18:07 +01:00
parent 0c93e78ea1
commit 66e51b39cf
5 changed files with 84 additions and 62 deletions
+6 -11
View File
@@ -1,11 +1,6 @@
reg rx, 1 reg ra, 1
reg ry, 2 reg rb, 2
mul rx, ry, rx
mul rx, ry, rx label double
mul rx, ry, rx mul ra, rb, ra
mul rx, ry, rx jmp double
mul rx, ry, rx
mul rx, ry, rx
mul rx, ry, rx
mul rx, ry, rx
mul rx, ry, rx
+41
View File
@@ -8,6 +8,8 @@ pub enum Instruction {
Sub(u8, u8, u8), Sub(u8, u8, u8),
Mul(u8, u8, u8), Mul(u8, u8, u8),
Div(u8, u8, u8), Div(u8, u8, u8),
Label(String),
Jmp(String),
} }
impl Display for Instruction { impl Display for Instruction {
@@ -22,7 +24,46 @@ impl Display for Instruction {
Instruction::Sub(a, b, c) => format!("SUB {a}, {b}, {c}"), Instruction::Sub(a, b, c) => format!("SUB {a}, {b}, {c}"),
Instruction::Mul(a, b, c) => format!("MUL {a}, {b}, {c}"), Instruction::Mul(a, b, c) => format!("MUL {a}, {b}, {c}"),
Instruction::Div(a, b, c) => format!("DIV {a}, {b}, {c}"), Instruction::Div(a, b, c) => format!("DIV {a}, {b}, {c}"),
Instruction::Label(a) => format!("LABEL {a}"),
Instruction::Jmp(a) => format!("JMP {a}"),
} }
) )
} }
} }
impl Instruction {
pub fn from_text(s: &str) -> Vec<Instruction> {
s.lines()
.filter_map(|v| {
let (name, args) = v.split_once(' ')?;
let args: Vec<&str> = args.split(',').map(str::trim).collect();
match name.to_lowercase().as_str() {
"hlt" => Some(Instruction::Hlt),
"reg" => Some(Instruction::Reg(reg(args[0]), num(args[1]))),
"add" => Some(Instruction::Add(reg(args[0]), reg(args[1]), reg(args[2]))),
"sub" => Some(Instruction::Sub(reg(args[0]), reg(args[1]), reg(args[2]))),
"mul" => Some(Instruction::Mul(reg(args[0]), reg(args[1]), reg(args[2]))),
"div" => Some(Instruction::Div(reg(args[0]), reg(args[1]), reg(args[2]))),
"label" => Some(Instruction::Label(args[0].to_string())),
"jmp" => Some(Instruction::Jmp(args[0].to_string())),
_ => None,
}
})
.collect()
}
}
fn reg(r: &str) -> u8 {
match r.to_lowercase().as_str() {
"ra" => 0,
"rb" => 1,
"rc" => 2,
"rd" => 3,
_ => 0,
}
}
fn num(r: &str) -> usize {
r.parse().unwrap()
}
+14 -1
View File
@@ -1,7 +1,7 @@
pub mod instruction; pub mod instruction;
pub mod registry; pub mod registry;
use std::fmt::Display; use std::{collections::HashMap, fmt::Display};
use osui::state::{DependencyHandler, State}; use osui::state::{DependencyHandler, State};
@@ -12,6 +12,7 @@ pub struct Emulator {
pub instructions: Vec<Instruction>, pub instructions: Vec<Instruction>,
pub registers: Registry, pub registers: Registry,
pub inst: State<Instruction>, pub inst: State<Instruction>,
pub labels: State<HashMap<String, usize>>,
} }
impl Emulator { impl Emulator {
@@ -56,6 +57,18 @@ impl Emulator {
let y = self.registers.get(*ry); let y = self.registers.get(*ry);
self.registers.set(*r, x / y); self.registers.set(*r, x / y);
} }
// 6 | Label
Instruction::Label(l) => {
self.labels.get().insert(l.clone(), **pc);
}
// 7 | Jump
Instruction::Jmp(l) => {
if let Some(v) = self.labels.get().get(l) {
**pc = *v;
}
}
} }
} else { } else {
break; break;
+20 -13
View File
@@ -1,21 +1,17 @@
mod binary; mod binary;
mod emulator; mod emulator;
mod text;
use std::{fs, sync::Arc}; use std::{collections::HashMap, fs, sync::Arc};
use osui::prelude::*; use osui::prelude::*;
use crate::{ use crate::emulator::{instruction::Instruction, registry::Registry};
emulator::{instruction::Instruction, registry::Registry},
text::from_text,
};
fn main() { fn main() {
let screen = Screen::new(); let screen = Screen::new();
let s = fs::read_to_string("input.fg").unwrap(); let s = fs::read_to_string("input.fg").unwrap();
app(&screen, from_text(&s)).draw(&screen); app(&screen, Instruction::from_text(&s)).draw(&screen);
screen.run().unwrap(); screen.run().unwrap();
} }
@@ -24,11 +20,13 @@ fn app(_screen: &Arc<Screen>, instructions: Vec<Instruction>) -> Rsx {
let pc = use_state::<usize>(0); let pc = use_state::<usize>(0);
let inst = use_state::<Instruction>(Instruction::Hlt); let inst = use_state::<Instruction>(Instruction::Hlt);
let registers = Registry(use_state([0; 8])); let registers = Registry(use_state([0; 8]));
let labels = use_state(HashMap::new());
let emulator = emulator::Emulator { let emulator = emulator::Emulator {
pc: pc.clone(), pc: pc.clone(),
registers: registers.clone(), registers: registers.clone(),
inst: inst.clone(), inst: inst.clone(),
labels: labels.clone(),
instructions, instructions,
}; };
@@ -38,18 +36,27 @@ fn app(_screen: &Arc<Screen>, instructions: Vec<Instruction>) -> Rsx {
FlexRow, gap: 1, { FlexRow, gap: 1, {
@Style { foreground: None, background: Background::RoundedOutline(0x0000ff) }; @Style { foreground: None, background: Background::RoundedOutline(0x0000ff) };
@Transform::new().padding(1, 1); @Transform::new().padding(1, 1);
FlexCol, gap: 1, {
%pc %pc
"Program Counter: {pc}" "Program Counter: {pc}"
@Style { foreground: None, background: Background::RoundedOutline(0xff0000) }; "|"
@Transform::new().padding(1, 1);
%registers %labels
"{registers}" "Labels: {labels:?}"
} }
@Style { foreground: None, background: Background::RoundedOutline(0x0000ff) }; @Style { foreground: None, background: Background::RoundedOutline(0xff0000) };
@Transform::center().padding(2, 2); @Transform::new().padding(1, 1);
FlexCol, gap: 1, {
%registers
"{registers}"
"|"
%inst %inst
"Current instruction: {inst}" "Current instruction: {inst}"
} }
} }
}
}
-34
View File
@@ -1,34 +0,0 @@
use crate::emulator::instruction::Instruction;
pub fn reg(r: &str) -> u8 {
match r.to_lowercase().as_str() {
"rx" => 0,
"ry" => 1,
"rz" => 2,
"ra" => 3,
_ => 0,
}
}
pub fn num(r: &str) -> usize {
r.parse().unwrap()
}
pub fn from_text(s: &str) -> Vec<Instruction> {
s.lines()
.filter_map(|v| {
let (name, args) = v.split_once(' ')?;
let args: Vec<&str> = args.split(',').map(str::trim).collect();
match name.to_lowercase().as_str() {
"hlt" => Some(Instruction::Hlt),
"reg" => Some(Instruction::Reg(reg(args[0]), num(args[1]))),
"add" => Some(Instruction::Add(reg(args[0]), reg(args[1]), reg(args[2]))),
"sub" => Some(Instruction::Sub(reg(args[0]), reg(args[1]), reg(args[2]))),
"mul" => Some(Instruction::Mul(reg(args[0]), reg(args[1]), reg(args[2]))),
"div" => Some(Instruction::Div(reg(args[0]), reg(args[1]), reg(args[2]))),
_ => None,
}
})
.collect()
}