Added valider

This commit is contained in:
Erin 2023-06-06 22:56:28 +02:00 committed by ondra05
parent e67d512f89
commit bb3a472eeb
3 changed files with 80 additions and 7 deletions

View file

@ -9,7 +9,7 @@ macro_rules! constmod {
} }
constmod!(pub opcode(u8) { constmod!(pub opcode(u8) {
NOP = 0, // _ NOP = 0, // N
ADD = 1, // RRR ADD = 1, // RRR
SUB = 2, // RRR SUB = 2, // RRR
MUL = 3, // RRR MUL = 3, // RRR
@ -37,8 +37,8 @@ constmod!(pub opcode(u8) {
JMP = 100, // I JMP = 100, // I
JMPCOND = 101, // I JMPCOND = 101, // I
RET = 103, // _ RET = 103, // N
ECALL = 255, // _ ECALL = 255, // N
}); });
#[repr(packed)] pub struct ParamRRR(pub u8, pub u8, pub u8); #[repr(packed)] pub struct ParamRRR(pub u8, pub u8, pub u8);

View file

@ -1,14 +1,19 @@
use hbvm::{vm::Vm, RuntimeErrors}; use hbvm::{validate::validate, vm::Vm, RuntimeErrors};
fn main() -> Result<(), RuntimeErrors> { fn main() -> Result<(), RuntimeErrors> {
// TODO: Grab program from cmdline // TODO: Grab program from cmdline
#[rustfmt::skip] #[rustfmt::skip]
let prog = &[]; let prog = &[];
if let Err(e) = validate(prog) {
eprintln!("Program validation error: {e:?}");
return Ok(());
} else {
unsafe { unsafe {
let mut vm = Vm::new_unchecked(prog); let mut vm = Vm::new_unchecked(prog);
vm.run(); vm.run();
} }
}
Ok(()) Ok(())
} }

View file

@ -0,0 +1,68 @@
macro_rules! bail {
($kind:ident, $start:expr, $curr:expr, $offset:expr) => {
return Err(Error {
kind: ErrorKind::$kind,
index: ($curr.as_ptr() as usize) - ($start.as_ptr() as usize) + $offset
})
};
($kind:ident, $start:expr, $curr:expr) => {
bail!($kind, $start, $curr, 0)
};
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum ErrorKind {
InvalidInstruction,
InvalidRegister,
Unimplemented,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Error {
kind: ErrorKind,
index: usize,
}
pub fn validate(mut program: &[u8]) -> Result<(), Error> {
use crate::bytecode::opcode::*;
#[inline]
fn reg(regs: &[u8]) -> Option<usize> {
regs.iter()
.enumerate()
.filter_map(|(n, &r)| (r > 59).then_some(n))
.next()
}
let start = program;
loop {
program = match program {
[] => return Ok(()),
// N
[NOP | RET | ECALL, rest @ ..] => rest,
// RRR
[ADD..=XOR | ADDF..=DIVF, _, _, _, rest @ ..] => {
if let Some(n) = reg(&program[1..=3]) {
bail!(InvalidRegister, start, program, n + 1)
}
rest
}
// RR
[NOT, _, _, rest @ ..] => {
if let Some(n) = reg(&program[1..=2]) {
bail!(InvalidRegister, start, program, n + 1)
}
rest
}
// RI
[LI, reg, _, _, _, _, _, _, _, _, rest @ ..] => {
if *reg > 59 {
bail!(InvalidRegister, start, program, 1)
}
rest
}
[LD | ST, ..] => bail!(Unimplemented, start, program),
_ => bail!(InvalidInstruction, start, program),
}
}
}