Website Summary Files Commits Branches @commit @diff @stats
path: root / vm / src
diff options
context:
space:
mode:
Commite7656f12d0ab604c40df10d6777ddb8c608a5bfd (patch)
Author
 Syndamia <kamen@syndamia.com>
2025-02-15 09:05:27 +0200
Committer
 Syndamia <kamen@syndamia.com>
2025-02-15 09:05:27 +0200
Filesf091122e6d24011b828030f35b5abeaa316c4b95 /vm/src
tonkobali-e7656f12d0ab604c40df10d6777ddb8c608a5bfd.tar
tonkobali-e7656f12d0ab604c40df10d6777ddb8c608a5bfd.tar.gz
tonkobali-e7656f12d0ab604c40df10d6777ddb8c608a5bfd.zip
Parentcde6e64005b8cc1b426b1aea15398eb7acb11d08 (diff)
feat(vm): Single-step mode
4 files changed, 115 insertions, 11 deletions
-rw-r--r--vm/src/vm/mod.rs37
-rw-r--r--vm/src/vm/primitive.rs48
-rw-r--r--vm/src/vmm/command.rs31
-rw-r--r--vm/src/vmm/mod.rs10
diff --git a/vm/src/vm/mod.rs b/vm/src/vm/mod.rs
index b5675ea..cec5eee 100644
--- a/vm/src/vm/mod.rs
+++ b/vm/src/vm/mod.rs
@@ -11,13 +11,24 @@ pub(crate) use memory::Word;
pub(crate) type VirtualMachine = Arc<Mutex<PrimitiveVirtualMachine>>;
pub(crate) trait VirtualMachineInterface {
+ /* Init */
fn create(tick_gap: u64) -> VirtualMachine;
fn create_from_file(tick_gap: u64, path: &str) -> VirtualMachine;
fn spawn(&self);
+
+ /* Run mode */
fn start(&self);
- fn is_halted(&self) -> bool;
fn set_start(&mut self, index: Word);
+ fn set_halt(&mut self, value: bool);
+ fn is_halted(&self) -> bool;
+
+ /* Single step mode */
+ fn step(&mut self);
+ fn set_single_step(&mut self, value: bool);
+ fn is_single_step(&self) -> bool;
+
+ /* IO */
fn set_word(&mut self, index: usize, value: Word);
fn get_word(&self, index: usize) -> Word;
}
@@ -27,6 +38,7 @@ fn create_with_memory(tick_gap: u64, mem: &Vec<Word>) -> VirtualMachine {
}
impl VirtualMachineInterface for VirtualMachine {
+ /* Init */
fn create(tick_gap: u64) -> VirtualMachine {
Arc::new(Mutex::new(PrimitiveVirtualMachine::new(tick_gap)))
}
@@ -47,6 +59,7 @@ impl VirtualMachineInterface for VirtualMachine {
});
}
+ /* Run mode */
fn start(&self) {
let tick_gap = {
let vm = (*self).lock().unwrap();
@@ -69,11 +82,33 @@ impl VirtualMachineInterface for VirtualMachine {
vm.start_again(index);
}
+ fn set_halt(&mut self, value: bool) {
+ let mut vm = (*self).lock().unwrap();
+ vm.set_halt(value);
+ }
+
fn is_halted(&self) -> bool {
let vm = (*self).lock().unwrap();
vm.is_halted()
}
+ /* Single step mode */
+ fn step(&mut self) {
+ let mut vm = (*self).lock().unwrap();
+ vm.step_next();
+ }
+
+ fn set_single_step(&mut self, value: bool) {
+ let mut vm = (*self).lock().unwrap();
+ vm.set_single_step(value);
+ }
+
+ fn is_single_step(&self) -> bool {
+ let vm = (*self).lock().unwrap();
+ vm.is_single_step()
+ }
+
+ /* IO */
fn set_word(&mut self, index: usize, value: Word) {
let mut vm = (*self).lock().unwrap();
vm.set_word(index, value);
diff --git a/vm/src/vm/primitive.rs b/vm/src/vm/primitive.rs
index 9b63d20..ff17b4d 100644
--- a/vm/src/vm/primitive.rs
+++ b/vm/src/vm/primitive.rs
@@ -11,6 +11,13 @@ pub struct PrimitiveVirtualMachine {
pub(crate) tick_gap: u64,
pub(crate) mem: Memory,
halted: bool,
+ single_step: bool,
+}
+
+macro_rules! above {
+ ($str:expr) => {
+ print!("\x1B7\x1B[1F{}\x1B8", $str)
+ };
}
impl PrimitiveVirtualMachine {
@@ -25,12 +32,16 @@ impl PrimitiveVirtualMachine {
pub fn new_with_memory(tick_gap: u64, mem: &Vec<Word>) -> PrimitiveVirtualMachine {
PrimitiveVirtualMachine {
halted: false,
+ single_step: false,
tick_gap,
mem: Memory::new_from(mem),
}
}
+ /* Run and single step modes */
pub fn step(&mut self) -> VirtualMachineStatus {
+ let pc = *self.pc();
+
let mut addrs = Memory::parse_address(*self.current_word());
if addrs.len() == 1 {
self.increment_pc();
@@ -44,6 +55,10 @@ impl PrimitiveVirtualMachine {
);
}
+ if self.single_step {
+ above!(format!("{}: subleq {} {} {}", pc, addrs[0], addrs[1], addrs[2]));
+ }
+
let a = self.mem[addrs[0]];
let b = self.mem.get_mut(addrs[1]);
let c = addrs[2] as Word;
@@ -57,8 +72,7 @@ impl PrimitiveVirtualMachine {
self.increment_pc();
}
-
- if *self.pc() == 0 {
+ if *self.pc() == 0 || self.single_step {
self.halted = true;
VirtualMachineStatus::Halt
}
@@ -67,23 +81,43 @@ impl PrimitiveVirtualMachine {
}
}
+ /* Run mode */
+ pub fn set_halt(&mut self, value: bool) {
+ self.halted = value;
+ }
+
pub fn is_halted(&self) -> bool {
self.halted
}
- pub fn get_word(&self, index: usize) -> Word {
- self.mem[index]
+ pub fn start_again(&mut self, pc: Word) {
+ *self.pc_mut() = pc;
+ self.halted = false;
}
+ /* Single step mode */
+ pub fn set_single_step(&mut self, value: bool) {
+ self.single_step = value;
+ }
+
+ pub fn is_single_step(&self) -> bool {
+ self.single_step
+ }
+
+ pub fn step_next(&mut self) {
+ self.halted = false;
+ }
+
+ /* IO */
pub fn set_word(&mut self, index: usize, value: Word) {
*self.mem.get_mut(index) = value;
}
- pub fn start_again(&mut self, pc: Word) {
- *self.pc_mut() = pc;
- self.halted = false;
+ pub fn get_word(&self, index: usize) -> Word {
+ self.mem[index]
}
+ /* Internal */
fn current_word(&self) -> &Word {
&self.mem[*self.pc() as usize]
}
diff --git a/vm/src/vmm/command.rs b/vm/src/vmm/command.rs
index 628a30f..6791663 100644
--- a/vm/src/vmm/command.rs
+++ b/vm/src/vmm/command.rs
@@ -71,6 +71,7 @@ pub(super) fn parse_and_exec(input: String, vm: &mut VirtualMachine) -> Result<(
}
match args[0] {
+ /* Run mode */
"r" | "run" => {
expects_n_args(&args, 1)?;
if ! vm.is_halted() {
@@ -78,6 +79,36 @@ pub(super) fn parse_and_exec(input: String, vm: &mut VirtualMachine) -> Result<(
}
vm.set_start(args[1].parse().unwrap());
},
+
+ /* Single step mode */
+ "s" | "single" => {
+ expects_n_args(&args, 1)?;
+ if ! vm.is_halted() {
+ return Err(format!("Machine already running!"));
+ }
+ if vm.is_single_step() {
+ return Err(format!("Machine already in single-step mode!"));
+ }
+ vm.set_single_step(true);
+ vm.set_start(args[1].parse().unwrap());
+ },
+ "c" | "continue" => {
+ expects_n_args(&args, 0)?;
+ if ! vm.is_single_step() {
+ return Err(format!("Machine not in single-step mode!"));
+ }
+ vm.set_single_step(false);
+ vm.set_halt(false);
+ },
+ "n" | "next" => {
+ expects_n_args(&args, 0)?;
+ if ! vm.is_single_step() {
+ return Err(format!("Machine not in single-step mode!"));
+ }
+ vm.step();
+ },
+
+ /* Other */
"q" | "quit" | "e" | "exit" => return Err(String::new()),
_ => {
for arg in args {
diff --git a/vm/src/vmm/mod.rs b/vm/src/vmm/mod.rs
index 0bfca73..6f42b4e 100644
--- a/vm/src/vmm/mod.rs
+++ b/vm/src/vmm/mod.rs
@@ -51,16 +51,20 @@ impl VirtualMachineMonitor {
println!("{}", msg);
}
}
+ else if vm.is_single_step() {
+ println!("");
+ }
info!();
},
_ => {},
}
- {
- if vm.is_halted() {
- }
+ if vm.is_single_step() {
+ info!("STEP");
}
+ else if vm.is_halted() {
info!(error "HALTED");
+ }
let _ = stdout().flush();
thread::sleep(time::Duration::from_millis(self.refresh_rate));