From a34f2fc9f8a027d108cd005fd53708588bac6075 Mon Sep 17 00:00:00 2001 From: Erin Date: Thu, 8 Jun 2023 00:52:24 +0200 Subject: [PATCH] Added zero register + relative jump --- hbasm/src/lib.rs | 3 +-- hbbytecode/src/lib.rs | 2 +- hbvm/src/main.rs | 14 +++++++------- hbvm/src/validate.rs | 2 +- hbvm/src/vm/mod.rs | 38 +++++++++++++++++++++++--------------- 5 files changed, 33 insertions(+), 26 deletions(-) diff --git a/hbasm/src/lib.rs b/hbasm/src/lib.rs index 6c9125f5..52a961be 100644 --- a/hbasm/src/lib.rs +++ b/hbasm/src/lib.rs @@ -99,9 +99,8 @@ pub fn assembly(code: &str, buf: &mut Vec) -> Result<(), Error> { NOP | RET | ECALL => Ok(()), ADD..=XOR | ADDF..=DIVF => self.rrr(), NOT | CP => self.rr(), - LI => self.ri(), + LI | JMP => self.ri(), LB..=SO => self.rri(), - JMP => self.i(), _ => unreachable!(), }?; match self.next() { diff --git a/hbbytecode/src/lib.rs b/hbbytecode/src/lib.rs index dd1552f7..62953211 100644 --- a/hbbytecode/src/lib.rs +++ b/hbbytecode/src/lib.rs @@ -43,7 +43,7 @@ constmod!(pub opcode(u8) { PAGEUNMAP = 25, // ?; Unmap a page PAGEMP = 26, // ?; Page modify protection flags - JMP = 27, // I; Unconditional jump + JMP = 27, // RI; Unconditional jump [#0 + imm #1] JMPCOND = 28, // ?; Conditional jump RET = 29, // N; Return ECALL = 30, // N; Issue system call diff --git a/hbvm/src/main.rs b/hbvm/src/main.rs index b484a9c6..34d0ac1b 100644 --- a/hbvm/src/main.rs +++ b/hbvm/src/main.rs @@ -1,19 +1,19 @@ -use hbbytecode::opcode; +use std::io::{Read, stdin}; use hbvm::{validate::validate, vm::Vm, RuntimeErrors}; -fn main() -> Result<(), RuntimeErrors> { - // TODO: Grab program from cmdline - #[rustfmt::skip] - let prog = &[]; +fn main() -> Result<(), Box> { + let mut prog = vec![]; + stdin().read_to_end(&mut prog)?; - if let Err(e) = validate(prog) { + if let Err(e) = validate(&prog) { eprintln!("Program validation error: {e:?}"); return Ok(()); } else { unsafe { - let mut vm = Vm::new_unchecked(prog); + let mut vm = Vm::new_unchecked(&prog); vm.memory.insert_test_page(); vm.run(); + println!("{:?}", vm.registers); } } Ok(()) diff --git a/hbvm/src/validate.rs b/hbvm/src/validate.rs index d2de30bf..91fac062 100644 --- a/hbvm/src/validate.rs +++ b/hbvm/src/validate.rs @@ -55,7 +55,7 @@ pub fn validate(mut program: &[u8]) -> Result<(), Error> { rest } // RI - [LI, reg, _, _, _, _, _, _, _, _, rest @ ..] => { + [LI | JMP, reg, _, _, _, _, _, _, _, _, rest @ ..] => { if *reg > 59 { bail!(InvalidRegister, start, program, 1); } diff --git a/hbvm/src/vm/mod.rs b/hbvm/src/vm/mod.rs index 40b4d625..90f80d49 100644 --- a/hbvm/src/vm/mod.rs +++ b/hbvm/src/vm/mod.rs @@ -26,17 +26,19 @@ macro_rules! param { macro_rules! binary_op { ($self:expr, $ty:ident, $handler:expr) => {{ let ParamRRR(tg, a0, a1) = param!($self, ParamRRR); - *$self.reg_mut(tg) = $handler(Value::$ty($self.reg(a0)), Value::$ty($self.reg(a1))).into(); + $self.write_reg(tg, $handler(Value::$ty(&$self.read_reg(a0)), Value::$ty(&$self.read_reg(a1))).into()); }}; } macro_rules! load { ($self:expr, $size:ty) => {{ let ParamRRI(tg, a0, offset) = param!($self, ParamRRI); - *$self.reg_mut(tg) = $self - .memory - .load::<$size>($self.reg(a0).int() + offset) - .ok_or(Exception::LoadAccess)?; + $self.write_reg( + tg, + $self.memory + .load::<$size>($self.read_reg(a0).int() + offset) + .ok_or(Exception::LoadAccess)? + ); }}; } @@ -45,7 +47,7 @@ macro_rules! store { let ParamRRI(src, a0, offset) = param!($self, ParamRRI); $self .memory - .store::<$size>($self.reg(a0).int() + offset, *$self.reg(src)) + .store::<$size>($self.read_reg(a0).int() + offset, $self.read_reg(src)) .map_err(|_| Exception::StoreAccess)?; }}; } @@ -93,7 +95,7 @@ impl<'a> Vm<'a> { XOR => binary_op!(self, int, ops::BitXor::bitxor), NOT => { let param = param!(self, ParamRR); - *self.reg_mut(param.0) = (!self.reg(param.1).int()).into(); + self.write_reg(param.0, (!self.read_reg(param.1).int()).into()); } ADDF => binary_op!(self, float, ops::Add::add), SUBF => binary_op!(self, float, ops::Sub::sub), @@ -101,11 +103,11 @@ impl<'a> Vm<'a> { DIVF => binary_op!(self, float, ops::Div::div), CP => { let param = param!(self, ParamRR); - *self.reg_mut(param.0) = *self.reg(param.1); + self.write_reg(param.0, self.read_reg(param.1)); } LI => { let param = param!(self, ParamRI); - *self.reg_mut(param.0) = param.1.into(); + self.write_reg(param.0, param.1.into()); } LB => load!(self, ma_size::Byte), LD => load!(self, ma_size::Doublet), @@ -116,8 +118,8 @@ impl<'a> Vm<'a> { SQ => store!(self, ma_size::Quadlet), SO => store!(self, ma_size::Octlet), JMP => { - self.pc = - self.program.as_ptr().add(self.pc + 1).cast::().read() as usize; + let ParamRI(reg, offset) = param!(self, ParamRI); + self.pc = (self.read_reg(reg).int() + offset) as usize; } _ => core::hint::unreachable_unchecked(), } @@ -126,13 +128,19 @@ impl<'a> Vm<'a> { } #[inline] - unsafe fn reg(&self, n: u8) -> &Value { - self.registers.get_unchecked(n as usize) + unsafe fn read_reg(&self, n: u8) -> Value { + if n == 0 { + 0.into() + } else { + *self.registers.get_unchecked(n as usize) + } } #[inline] - unsafe fn reg_mut(&mut self, n: u8) -> &mut Value { - self.registers.get_unchecked_mut(n as usize) + unsafe fn write_reg(&mut self, n: u8, value: Value) { + if n != 0 { + *self.registers.get_unchecked_mut(n as usize) = value; + } } }