fixed a lot of bugs with the emulator, instruction set and assembler
This commit is contained in:
@@ -27,10 +27,11 @@ pub fn run_emulator(
|
||||
|
||||
let mut running = Running::Paused;
|
||||
let mut addr = 0u32;
|
||||
let mut history = Vec::<(u32, Instruction)>::new();
|
||||
let size = 256;
|
||||
|
||||
let memory_view = processor.memory.read_range(addr, size);
|
||||
let initial_state = state(&mut processor, running, 0, memory_view);
|
||||
let initial_state = state(&mut processor, running, 0, memory_view, &mut history);
|
||||
let _ = state_tx.send(initial_state);
|
||||
|
||||
let mut instruction_count = 0;
|
||||
@@ -79,7 +80,9 @@ pub fn run_emulator(
|
||||
|
||||
// Execute one cycle.
|
||||
match processor.cycle() {
|
||||
Ok(_) => {}
|
||||
Ok((addr, instruction)) => {
|
||||
history.push((addr, instruction.clone()));
|
||||
}
|
||||
Err(why) => {
|
||||
let pcx = processor.get(Register::Pcx);
|
||||
eprintln!(
|
||||
@@ -103,7 +106,15 @@ pub fn run_emulator(
|
||||
}
|
||||
|
||||
let memory_view = processor.memory.read_range(addr, size);
|
||||
let state = state(&mut processor, running, instruction_count, memory_view);
|
||||
let state = state(
|
||||
&mut processor,
|
||||
running,
|
||||
instruction_count,
|
||||
memory_view,
|
||||
&mut history,
|
||||
);
|
||||
|
||||
println!("state");
|
||||
|
||||
let _ = state_tx.send(state);
|
||||
}
|
||||
@@ -121,10 +132,12 @@ pub fn run_emulator(
|
||||
}
|
||||
};
|
||||
|
||||
history.push(instruction.clone());
|
||||
|
||||
// let instruction = match Instruction::decode(cpu_lock.get(Register::Cir))
|
||||
// {};
|
||||
|
||||
if matches!(instruction, Instruction::Halt) {
|
||||
if matches!(instruction.1, Instruction::Halt) {
|
||||
running = Running::Halted;
|
||||
update = true;
|
||||
}
|
||||
@@ -138,8 +151,13 @@ pub fn run_emulator(
|
||||
|
||||
if update {
|
||||
let memory_view = processor.memory.read_range(addr, size);
|
||||
let state =
|
||||
state(&mut processor, running, instruction_count, memory_view);
|
||||
let state = state(
|
||||
&mut processor,
|
||||
running,
|
||||
instruction_count,
|
||||
memory_view,
|
||||
&mut history,
|
||||
);
|
||||
let _ = state_tx.send(state);
|
||||
}
|
||||
} else {
|
||||
@@ -153,7 +171,11 @@ fn state(
|
||||
running: Running,
|
||||
instruction_count: usize,
|
||||
memory_view: Vec<u8>,
|
||||
history: &mut Vec<(u32, Instruction)>,
|
||||
) -> State {
|
||||
let hsclone = history.clone();
|
||||
history.clear();
|
||||
|
||||
State {
|
||||
// TODO: Replace with actual register access from your CPU.
|
||||
reg_file: cpu_lock.registers,
|
||||
@@ -163,5 +185,6 @@ fn state(
|
||||
memory_view,
|
||||
display_view: cpu_lock.display(),
|
||||
error: None,
|
||||
history: hsclone,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -205,6 +205,7 @@ pub struct State {
|
||||
pub stack_view: Vec<u8>,
|
||||
pub memory_view: Vec<u8>,
|
||||
pub display_view: Vec<u8>,
|
||||
pub history: Vec<(u32, Instruction)>,
|
||||
pub error: Option<String>,
|
||||
}
|
||||
|
||||
@@ -217,6 +218,7 @@ impl Default for State {
|
||||
stack_view: vec![],
|
||||
memory_view: vec![],
|
||||
display_view: vec![],
|
||||
history: vec![],
|
||||
error: None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ impl Processor {
|
||||
self.memory.reset();
|
||||
}
|
||||
|
||||
pub fn cycle(&mut self) -> Result<Instruction, InstructionDecodeError> {
|
||||
pub fn cycle(&mut self) -> Result<(u32, Instruction), InstructionDecodeError> {
|
||||
self.halted = false;
|
||||
|
||||
// Get value from PCX.
|
||||
@@ -58,7 +58,7 @@ impl Processor {
|
||||
|
||||
instruction.execute(self);
|
||||
|
||||
Ok(instruction)
|
||||
Ok((addr, instruction))
|
||||
}
|
||||
|
||||
fn fetch(&self) -> u32 {
|
||||
@@ -405,11 +405,11 @@ impl Executable for Instruction {
|
||||
|
||||
// mathematical and logical functions & other operations
|
||||
const fn add(a: u32, b: u32) -> u32 {
|
||||
a + b
|
||||
a.wrapping_add(b)
|
||||
}
|
||||
|
||||
const fn sub(a: u32, b: u32) -> u32 {
|
||||
a - b
|
||||
a.wrapping_sub(b)
|
||||
}
|
||||
|
||||
const fn and(a: u32, b: u32) -> u32 {
|
||||
@@ -417,11 +417,11 @@ const fn and(a: u32, b: u32) -> u32 {
|
||||
}
|
||||
|
||||
const fn inc(a: u32) -> u32 {
|
||||
a + 1
|
||||
a.wrapping_add(1)
|
||||
}
|
||||
|
||||
const fn dec(a: u32) -> u32 {
|
||||
a - 1
|
||||
a.wrapping_sub(1)
|
||||
}
|
||||
|
||||
const fn shl(a: u32, amount: u8) -> u32 {
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
use std::{ffi::OsStr, path::PathBuf, sync::mpsc::Sender};
|
||||
|
||||
use common::prelude::Instruction;
|
||||
use egui::{Align, Context, Key, Layout, Ui};
|
||||
use rfd::FileDialog;
|
||||
|
||||
use dsa_editor::{CodeEditor, ColorTheme, Syntax};
|
||||
|
||||
use crate::emulator::{
|
||||
system::model::{Command, State},
|
||||
ui::interface::Component,
|
||||
};
|
||||
|
||||
pub struct History {
|
||||
visible: bool,
|
||||
history: Vec<(u32, Instruction)>,
|
||||
}
|
||||
|
||||
impl Component for History {
|
||||
fn name(&self) -> &'static str {
|
||||
"Instruction History"
|
||||
}
|
||||
|
||||
fn visible(&mut self) -> &mut bool {
|
||||
&mut self.visible
|
||||
}
|
||||
|
||||
fn category(&self) -> super::interface::Category {
|
||||
super::interface::Category::Control
|
||||
}
|
||||
|
||||
fn render(&mut self, state: &mut State, ui: &mut Ui, ctx: &Context) {
|
||||
self.update(state);
|
||||
|
||||
egui::ScrollArea::vertical()
|
||||
.id_salt("output_scroll")
|
||||
.max_width(400.0)
|
||||
.show(ui, |ui| {
|
||||
if self.history.is_empty() {
|
||||
ui.label(
|
||||
egui::RichText::new("No output data")
|
||||
.font(egui::FontId::monospace(12.0))
|
||||
.color(egui::Color32::GRAY),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
egui::Grid::new("output_grid")
|
||||
.spacing([5.0, 2.0]) // Horizontal and vertical spacing
|
||||
.num_columns(4)
|
||||
.striped(false)
|
||||
.show(ui, |ui| {
|
||||
// Process bytes in chunks of 4
|
||||
for (idx, instruction) in self.history.iter().enumerate() {
|
||||
ui.label(format!("{}: ", idx));
|
||||
|
||||
// Hex column
|
||||
let addr = instruction.0;
|
||||
ui.label(
|
||||
egui::RichText::new(format!("0x{addr:08X}"))
|
||||
.font(egui::FontId::monospace(12.0))
|
||||
.color(egui::Color32::from_rgb(255, 200, 200)),
|
||||
);
|
||||
|
||||
ui.label(
|
||||
egui::RichText::new(instruction.1.to_string())
|
||||
.font(egui::FontId::monospace(12.0))
|
||||
.color(egui::Color32::from_rgb(200, 255, 200)),
|
||||
);
|
||||
|
||||
ui.end_row();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl History {
|
||||
#[must_use]
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
visible: false,
|
||||
history: Vec::with_capacity(1000),
|
||||
}
|
||||
}
|
||||
|
||||
fn update(&mut self, state: &mut State) {
|
||||
self.history.extend(state.history.clone());
|
||||
state.history.clear();
|
||||
if self.history.len() > 1000 {
|
||||
let len = self.history.len() - 1000;
|
||||
self.history.drain(..len);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
pub mod control_unit;
|
||||
pub mod display;
|
||||
pub mod editor;
|
||||
pub mod history;
|
||||
pub mod interface;
|
||||
pub mod memory_inspector;
|
||||
pub mod menu;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::io::Read;
|
||||
|
||||
use crate::emulator::{system::model::State, ui::interface::Component};
|
||||
|
||||
use common::instructions::Register;
|
||||
@@ -47,11 +49,14 @@ impl Component for StackInspector {
|
||||
ui.label("Value");
|
||||
ui.end_row();
|
||||
|
||||
for (i, value) in (0u32..).zip(state.stack_view.iter().take(32)) {
|
||||
for (i, value) in
|
||||
state.stack_view.chunks(4).take(32).enumerate()
|
||||
{
|
||||
let value = u32::from_be_bytes(value.try_into().unwrap());
|
||||
ui.label(format!(
|
||||
"{} [{}]",
|
||||
i,
|
||||
state.reg_file.get(Register::Spr) - i * 4
|
||||
state.reg_file.get(Register::Spr) - i as u32 * 4
|
||||
));
|
||||
ui.label(format!("0x{value:08X} ({value})"));
|
||||
ui.end_row();
|
||||
|
||||
@@ -101,5 +101,8 @@ fn setup_ui(cmd_sender: Sender<Command>, state_reciever: Receiver<State>) -> Emu
|
||||
let display = Display::new();
|
||||
ui.add_component(Box::new(display));
|
||||
|
||||
let history = dsa_rs::emulator::ui::history::History::new();
|
||||
ui.add_component(Box::new(history));
|
||||
|
||||
ui
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user