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 ry, 2
mul rx, ry, rx
mul rx, ry, rx
mul rx, ry, rx
mul rx, ry, rx
mul rx, ry, rx
mul rx, ry, rx
mul rx, ry, rx
mul rx, ry, rx
mul rx, ry, rx
reg ra, 1
reg rb, 2
label double
mul ra, rb, ra
jmp double
+41
View File
@@ -8,6 +8,8 @@ pub enum Instruction {
Sub(u8, u8, u8),
Mul(u8, u8, u8),
Div(u8, u8, u8),
Label(String),
Jmp(String),
}
impl Display for Instruction {
@@ -22,7 +24,46 @@ impl Display for Instruction {
Instruction::Sub(a, b, c) => format!("SUB {a}, {b}, {c}"),
Instruction::Mul(a, b, c) => format!("MUL {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 registry;
use std::fmt::Display;
use std::{collections::HashMap, fmt::Display};
use osui::state::{DependencyHandler, State};
@@ -12,6 +12,7 @@ pub struct Emulator {
pub instructions: Vec<Instruction>,
pub registers: Registry,
pub inst: State<Instruction>,
pub labels: State<HashMap<String, usize>>,
}
impl Emulator {
@@ -56,6 +57,18 @@ impl Emulator {
let y = self.registers.get(*ry);
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 {
break;
+20 -13
View File
@@ -1,21 +1,17 @@
mod binary;
mod emulator;
mod text;
use std::{fs, sync::Arc};
use std::{collections::HashMap, fs, sync::Arc};
use osui::prelude::*;
use crate::{
emulator::{instruction::Instruction, registry::Registry},
text::from_text,
};
use crate::emulator::{instruction::Instruction, registry::Registry};
fn main() {
let screen = Screen::new();
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();
}
@@ -24,11 +20,13 @@ fn app(_screen: &Arc<Screen>, instructions: Vec<Instruction>) -> Rsx {
let pc = use_state::<usize>(0);
let inst = use_state::<Instruction>(Instruction::Hlt);
let registers = Registry(use_state([0; 8]));
let labels = use_state(HashMap::new());
let emulator = emulator::Emulator {
pc: pc.clone(),
registers: registers.clone(),
inst: inst.clone(),
labels: labels.clone(),
instructions,
};
@@ -38,18 +36,27 @@ fn app(_screen: &Arc<Screen>, instructions: Vec<Instruction>) -> Rsx {
FlexRow, gap: 1, {
@Style { foreground: None, background: Background::RoundedOutline(0x0000ff) };
@Transform::new().padding(1, 1);
FlexCol, gap: 1, {
%pc
"Program Counter: {pc}"
@Style { foreground: None, background: Background::RoundedOutline(0xff0000) };
@Transform::new().padding(1, 1);
%registers
"{registers}"
"|"
%labels
"Labels: {labels:?}"
}
@Style { foreground: None, background: Background::RoundedOutline(0x0000ff) };
@Transform::center().padding(2, 2);
@Style { foreground: None, background: Background::RoundedOutline(0xff0000) };
@Transform::new().padding(1, 1);
FlexCol, gap: 1, {
%registers
"{registers}"
"|"
%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()
}