holey-bytes/hbvm/src/validate.rs

75 lines
2.1 KiB
Rust
Raw Normal View History

2023-06-06 15:56:28 -05:00
macro_rules! bail {
($kind:ident, $start:expr, $curr:expr, $offset:expr) => {
return Err(Error {
2023-06-08 16:23:23 -05:00
kind: ErrorKind::$kind,
index: ($curr.as_ptr() as usize) - ($start.as_ptr() as usize) + $offset,
2023-06-06 15:56:28 -05:00
})
};
($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> {
2023-06-07 08:07:37 -05:00
use hbbytecode::opcode::*;
2023-06-06 15:56:28 -05:00
#[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
2023-06-09 11:25:37 -05:00
[ADD..=CMPU | ADDF..=DIVF, _, _, _, rest @ ..] => {
2023-06-06 15:56:28 -05:00
if let Some(n) = reg(&program[1..=3]) {
2023-06-07 17:25:38 -05:00
bail!(InvalidRegister, start, program, n + 1);
2023-06-06 15:56:28 -05:00
}
rest
}
// RR
2023-06-06 17:02:27 -05:00
[NOT | CP, _, _, rest @ ..] => {
2023-06-06 15:56:28 -05:00
if let Some(n) = reg(&program[1..=2]) {
2023-06-07 17:25:38 -05:00
bail!(InvalidRegister, start, program, n + 1);
2023-06-06 15:56:28 -05:00
}
rest
}
// RI
2023-06-07 17:52:24 -05:00
[LI | JMP, reg, _, _, _, _, _, _, _, _, rest @ ..] => {
2023-06-06 15:56:28 -05:00
if *reg > 59 {
2023-06-07 17:25:38 -05:00
bail!(InvalidRegister, start, program, 1);
2023-06-06 15:56:28 -05:00
}
rest
}
2023-06-07 17:25:38 -05:00
// RRI
2023-06-08 18:55:09 -05:00
[ADDI..=MULFI | LB..=SO | JEQ..=JGTU, _, _, _, _, _, _, _, _, _, _, rest @ ..] => {
2023-06-07 17:25:38 -05:00
if let Some(n) = reg(&program[1..=2]) {
bail!(InvalidRegister, start, program, n + 1);
}
rest
2023-06-08 16:23:23 -05:00
}
2023-06-06 15:56:28 -05:00
_ => bail!(InvalidInstruction, start, program),
}
}
}