Added zero register + relative jump

This commit is contained in:
Erin 2023-06-08 00:52:24 +02:00 committed by ondra05
parent fce7a96e50
commit a34f2fc9f8
5 changed files with 33 additions and 26 deletions

View file

@ -99,9 +99,8 @@ pub fn assembly(code: &str, buf: &mut Vec<u8>) -> Result<(), Error> {
NOP | RET | ECALL => Ok(()), NOP | RET | ECALL => Ok(()),
ADD..=XOR | ADDF..=DIVF => self.rrr(), ADD..=XOR | ADDF..=DIVF => self.rrr(),
NOT | CP => self.rr(), NOT | CP => self.rr(),
LI => self.ri(), LI | JMP => self.ri(),
LB..=SO => self.rri(), LB..=SO => self.rri(),
JMP => self.i(),
_ => unreachable!(), _ => unreachable!(),
}?; }?;
match self.next() { match self.next() {

View file

@ -43,7 +43,7 @@ constmod!(pub opcode(u8) {
PAGEUNMAP = 25, // ?; Unmap a page PAGEUNMAP = 25, // ?; Unmap a page
PAGEMP = 26, // ?; Page modify protection flags PAGEMP = 26, // ?; Page modify protection flags
JMP = 27, // I; Unconditional jump JMP = 27, // RI; Unconditional jump [#0 + imm #1]
JMPCOND = 28, // ?; Conditional jump JMPCOND = 28, // ?; Conditional jump
RET = 29, // N; Return RET = 29, // N; Return
ECALL = 30, // N; Issue system call ECALL = 30, // N; Issue system call

View file

@ -1,19 +1,19 @@
use hbbytecode::opcode; use std::io::{Read, stdin};
use hbvm::{validate::validate, vm::Vm, RuntimeErrors}; use hbvm::{validate::validate, vm::Vm, RuntimeErrors};
fn main() -> Result<(), RuntimeErrors> { fn main() -> Result<(), Box<dyn std::error::Error>> {
// TODO: Grab program from cmdline let mut prog = vec![];
#[rustfmt::skip] stdin().read_to_end(&mut prog)?;
let prog = &[];
if let Err(e) = validate(prog) { if let Err(e) = validate(&prog) {
eprintln!("Program validation error: {e:?}"); eprintln!("Program validation error: {e:?}");
return Ok(()); return Ok(());
} else { } else {
unsafe { unsafe {
let mut vm = Vm::new_unchecked(prog); let mut vm = Vm::new_unchecked(&prog);
vm.memory.insert_test_page(); vm.memory.insert_test_page();
vm.run(); vm.run();
println!("{:?}", vm.registers);
} }
} }
Ok(()) Ok(())

View file

@ -55,7 +55,7 @@ pub fn validate(mut program: &[u8]) -> Result<(), Error> {
rest rest
} }
// RI // RI
[LI, reg, _, _, _, _, _, _, _, _, rest @ ..] => { [LI | JMP, reg, _, _, _, _, _, _, _, _, rest @ ..] => {
if *reg > 59 { if *reg > 59 {
bail!(InvalidRegister, start, program, 1); bail!(InvalidRegister, start, program, 1);
} }

View file

@ -26,17 +26,19 @@ macro_rules! param {
macro_rules! binary_op { macro_rules! binary_op {
($self:expr, $ty:ident, $handler:expr) => {{ ($self:expr, $ty:ident, $handler:expr) => {{
let ParamRRR(tg, a0, a1) = param!($self, ParamRRR); 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 { macro_rules! load {
($self:expr, $size:ty) => {{ ($self:expr, $size:ty) => {{
let ParamRRI(tg, a0, offset) = param!($self, ParamRRI); let ParamRRI(tg, a0, offset) = param!($self, ParamRRI);
*$self.reg_mut(tg) = $self $self.write_reg(
.memory tg,
.load::<$size>($self.reg(a0).int() + offset) $self.memory
.ok_or(Exception::LoadAccess)?; .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); let ParamRRI(src, a0, offset) = param!($self, ParamRRI);
$self $self
.memory .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)?; .map_err(|_| Exception::StoreAccess)?;
}}; }};
} }
@ -93,7 +95,7 @@ impl<'a> Vm<'a> {
XOR => binary_op!(self, int, ops::BitXor::bitxor), XOR => binary_op!(self, int, ops::BitXor::bitxor),
NOT => { NOT => {
let param = param!(self, ParamRR); 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), ADDF => binary_op!(self, float, ops::Add::add),
SUBF => binary_op!(self, float, ops::Sub::sub), SUBF => binary_op!(self, float, ops::Sub::sub),
@ -101,11 +103,11 @@ impl<'a> Vm<'a> {
DIVF => binary_op!(self, float, ops::Div::div), DIVF => binary_op!(self, float, ops::Div::div),
CP => { CP => {
let param = param!(self, ParamRR); 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 => { LI => {
let param = param!(self, ParamRI); 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), LB => load!(self, ma_size::Byte),
LD => load!(self, ma_size::Doublet), LD => load!(self, ma_size::Doublet),
@ -116,8 +118,8 @@ impl<'a> Vm<'a> {
SQ => store!(self, ma_size::Quadlet), SQ => store!(self, ma_size::Quadlet),
SO => store!(self, ma_size::Octlet), SO => store!(self, ma_size::Octlet),
JMP => { JMP => {
self.pc = let ParamRI(reg, offset) = param!(self, ParamRI);
self.program.as_ptr().add(self.pc + 1).cast::<u64>().read() as usize; self.pc = (self.read_reg(reg).int() + offset) as usize;
} }
_ => core::hint::unreachable_unchecked(), _ => core::hint::unreachable_unchecked(),
} }
@ -126,13 +128,19 @@ impl<'a> Vm<'a> {
} }
#[inline] #[inline]
unsafe fn reg(&self, n: u8) -> &Value { unsafe fn read_reg(&self, n: u8) -> Value {
self.registers.get_unchecked(n as usize) if n == 0 {
0.into()
} else {
*self.registers.get_unchecked(n as usize)
}
} }
#[inline] #[inline]
unsafe fn reg_mut(&mut self, n: u8) -> &mut Value { unsafe fn write_reg(&mut self, n: u8, value: Value) {
self.registers.get_unchecked_mut(n as usize) if n != 0 {
*self.registers.get_unchecked_mut(n as usize) = value;
}
} }
} }