forked from AbleOS/holey-bytes
Added valider
This commit is contained in:
parent
e67d512f89
commit
bb3a472eeb
|
@ -9,7 +9,7 @@ macro_rules! constmod {
|
|||
}
|
||||
|
||||
constmod!(pub opcode(u8) {
|
||||
NOP = 0, // _
|
||||
NOP = 0, // N
|
||||
ADD = 1, // RRR
|
||||
SUB = 2, // RRR
|
||||
MUL = 3, // RRR
|
||||
|
@ -37,8 +37,8 @@ constmod!(pub opcode(u8) {
|
|||
|
||||
JMP = 100, // I
|
||||
JMPCOND = 101, // I
|
||||
RET = 103, // _
|
||||
ECALL = 255, // _
|
||||
RET = 103, // N
|
||||
ECALL = 255, // N
|
||||
});
|
||||
|
||||
#[repr(packed)] pub struct ParamRRR(pub u8, pub u8, pub u8);
|
||||
|
|
|
@ -1,13 +1,18 @@
|
|||
use hbvm::{vm::Vm, RuntimeErrors};
|
||||
use hbvm::{validate::validate, vm::Vm, RuntimeErrors};
|
||||
|
||||
fn main() -> Result<(), RuntimeErrors> {
|
||||
// TODO: Grab program from cmdline
|
||||
#[rustfmt::skip]
|
||||
let prog = &[];
|
||||
|
||||
unsafe {
|
||||
let mut vm = Vm::new_unchecked(prog);
|
||||
vm.run();
|
||||
if let Err(e) = validate(prog) {
|
||||
eprintln!("Program validation error: {e:?}");
|
||||
return Ok(());
|
||||
} else {
|
||||
unsafe {
|
||||
let mut vm = Vm::new_unchecked(prog);
|
||||
vm.run();
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue