From f832f6a04a9ff706e089c37c5b0907d3e2065d61 Mon Sep 17 00:00:00 2001 From: Erin Date: Fri, 9 Jun 2023 21:58:59 +0200 Subject: [PATCH] asdasdasdasdasdasdasdasd --- hbbytecode/src/lib.rs | 124 ++++++++++++++++++++++++------------------ hbvm/src/validate.rs | 6 +- hbvm/src/vm/mem.rs | 11 ++++ hbvm/src/vm/mod.rs | 18 ++++-- hbvm/src/vm/value.rs | 2 +- 5 files changed, 98 insertions(+), 63 deletions(-) diff --git a/hbbytecode/src/lib.rs b/hbbytecode/src/lib.rs index eb13eda4..595e3f4c 100644 --- a/hbbytecode/src/lib.rs +++ b/hbbytecode/src/lib.rs @@ -1,83 +1,99 @@ #![no_std] macro_rules! constmod { - ($vis:vis $mname:ident($repr:ty) { $($cname:ident = $val:expr),* $(,)? }) => { + ($vis:vis $mname:ident($repr:ty) { + $(#![doc = $mdoc:literal])? + $($cname:ident = $val:expr $(,$doc:literal)?;)* + }) => { + $(#[doc = $mdoc])? $vis mod $mname { - $(pub const $cname: $repr = $val;)* + $( + $(#[doc = $doc])? + pub const $cname: $repr = $val; + )* } }; } constmod!(pub opcode(u8) { - NOP = 0, // N; Do nothing + //! Opcode constant module - ADD = 1, // RRR; #0 ← #1 + #2 - SUB = 2, // RRR; #0 ← #1 - #2 - MUL = 3, // RRR; #0 ← #1 × #2 - DIV = 4, // RRR; #0 ← #1 ÷ #2 - REM = 5, // RRR; #0 ← #1 % #2 - AND = 6, // RRR; #0 ← #1 & #2 - OR = 7, // RRR; #0 ← #1 | #2 - XOR = 8, // RRR; #0 ← #1 ^ #2 - SL = 9, // RRR; #0 ← #1 « #2 - SR = 10, // RRR; #0 ← #1 » #2 - SRS = 11, // RRR; #0 ← #1 » #2 (signed) - CMP = 12, // RRR; #0 ← #1 <=> #2 - CMPU = 13, // RRR; #0 ← #1 <=> #2 (unsigned) - NOT = 14, // RR; #0 ← !#1 + NOP = 0, "N; Do nothing"; - ADDF = 15, // RRR; #0 ← #1 +. #2 - SUBF = 16, // RRR; #0 ← #1 +. #2 - MULF = 17, // RRR; #0 ← #1 +. #2 - DIVF = 18, // RRR; #0 ← #1 +. #2 - ADDI = 19, // RRI; #0 ← #1 + imm #2 - MULI = 20, // RRI; #0 ← #1 × imm #2 - REMI = 21, // RRI; #0 ← #1 % imm #2 - ANDI = 22, // RRI; #0 ← #1 & imm #2 - ORI = 23, // RRI; #0 ← #1 | imm #2 - XORI = 24, // RRI; #0 ← #1 ^ imm #2 - SLI = 25, // RRI; #0 ← #1 « imm #2 - SRI = 26, // RRI; #0 ← #1 » imm #2 - SRSI = 27, // RRI; #0 ← #1 » imm #2 (signed) - CMPI = 28, // RRI; #0 ← #1 <=> imm #2 - CMPUI = 29, // RRI; #0 ← #1 <=> imm #2 (unsigned) + ADD = 1, "RRR; #0 ← #1 + #2"; + SUB = 2, "RRR; #0 ← #1 - #2"; + MUL = 3, "RRR; #0 ← #1 × #2"; + DIV = 4, "RRR; #0 ← #1 ÷ #2"; + REM = 5, "RRR; #0 ← #1 % #2"; + AND = 6, "RRR; #0 ← #1 & #2"; + OR = 7, "RRR; #0 ← #1 | #2"; + XOR = 8, "RRR; #0 ← #1 ^ #2"; + SL = 9, "RRR; #0 ← #1 « #2"; + SR = 10, "RRR; #0 ← #1 » #2"; + SRS = 11, "RRR; #0 ← #1 » #2 (signed)"; + CMP = 12, "RRR; #0 ← #1 <=> #2"; + CMPU = 13, "RRR; #0 ← #1 <=> #2 (unsigned)"; + NOT = 14, "RR; #0 ← !#1"; - ADDFI = 30, // RRI; #0 ← #1 +. imm #2 - MULFI = 31, // RRI; #0 ← #1 *. imm #2 + ADDF = 15, "RRR; #0 ← #1 +. #2"; + SUBF = 16, "RRR; #0 ← #1 +. #2"; + MULF = 17, "RRR; #0 ← #1 +. #2"; + DIVF = 18, "RRR; #0 ← #1 +. #2"; + ADDI = 19, "RRI; #0 ← #1 + imm #2"; + MULI = 20, "RRI; #0 ← #1 × imm #2"; + REMI = 21, "RRI; #0 ← #1 % imm #2"; + ANDI = 22, "RRI; #0 ← #1 & imm #2"; + ORI = 23, "RRI; #0 ← #1 | imm #2"; + XORI = 24, "RRI; #0 ← #1 ^ imm #2"; + SLI = 25, "RRI; #0 ← #1 « imm #2"; + SRI = 26, "RRI; #0 ← #1 » imm #2"; + SRSI = 27, "RRI; #0 ← #1 » imm #2 (signed)"; + CMPI = 28, "RRI; #0 ← #1 <=> imm #2"; + CMPUI = 29, "RRI; #0 ← #1 <=> imm #2 (unsigned)"; - CP = 32, // RR; Copy #0 ← #1 - LI = 33, // RI; Load immediate, #0 ← imm #1 - LB = 34, // RRI; Load byte (8 bits), #0 ← [#1 + imm #2] - LD = 35, // RRI; Load doublet (16 bits) - LQ = 36, // RRI; Load quadlet (32 bits) - LO = 37, // RRI; Load octlet (64 bits) - SB = 38, // RRI; Store byte, [#1 + imm #2] ← #0 - SD = 39, // RRI; Store doublet - SQ = 40, // RRI; Store quadlet - SO = 41, // RRI; Store octlet + ADDFI = 30, "RRI; #0 ← #1 +. imm #2"; + MULFI = 31, "RRI; #0 ← #1 *. imm #2"; - JMP = 42, // RI; Unconditional jump [#0 + imm #1] - JEQ = 43, // RRI; if #0 = #1 → jump imm #2 - JNE = 44, // RRI; if #0 ≠ #1 → jump imm #2 - JLT = 45, // RRI; if #0 < #1 → jump imm #2 - JGT = 46, // RRI; if #0 > #1 → jump imm #2 - JLTU = 47, // RRI; if #0 < #1 → jump imm #2 (unsigned) - JGTU = 48, // RRI; if #0 > #1 → jump imm #2 (unsigned) - RET = 49, // N; Return - ECALL = 50, // N; Issue system call + CP = 32, "RR; Copy #0 ← #1"; + LI = 33, "RI; Load immediate, #0 ← imm #1"; + LB = 34, "RRI; Load byte (8 bits), #0 ← [#1 + imm #2]"; + LD = 35, "RRI; Load doublet (16 bits)"; + LQ = 36, "RRI; Load quadlet (32 bits)"; + LO = 37, "RRI; Load octlet (64 bits)"; + SB = 38, "RRI; Store byte, [#1 + imm #2] ← #0"; + SD = 39, "RRI; Store doublet"; + SQ = 40, "RRI; Store quadlet"; + SO = 41, "RRI; Store octlet"; + + JMP = 42, "RI; Unconditional jump [#0 + imm #1]"; + JEQ = 43, "RRI; if #0 = #1 → jump imm #2"; + JNE = 44, "RRI; if #0 ≠ #1 → jump imm #2"; + JLT = 45, "RRI; if #0 < #1 → jump imm #2"; + JGT = 46, "RRI; if #0 > #1 → jump imm #2"; + JLTU = 47, "RRI; if #0 < #1 → jump imm #2 (unsigned)"; + JGTU = 48, "RRI; if #0 > #1 → jump imm #2 (unsigned)"; + RET = 49, "N; Return"; + ECALL = 50, "N; Issue system call"; }); +/// Register-register-register instruction parameter #[repr(packed)] pub struct ParamRRR(pub u8, pub u8, pub u8); + +/// Register-register-immediate intruction parameter #[repr(packed)] pub struct ParamRRI(pub u8, pub u8, pub u64); + +/// Register-register instruction parameter #[repr(packed)] pub struct ParamRR(pub u8, pub u8); + +/// Register-immediate instruction parameter #[repr(packed)] pub struct ParamRI(pub u8, pub u64); /// # Safety -/// TODO. +/// Has to be valid to be decoded from bytecode. pub unsafe trait OpParam {} unsafe impl OpParam for ParamRRR {} unsafe impl OpParam for ParamRRI {} diff --git a/hbvm/src/validate.rs b/hbvm/src/validate.rs index d58af8df..35bb917a 100644 --- a/hbvm/src/validate.rs +++ b/hbvm/src/validate.rs @@ -1,7 +1,7 @@ macro_rules! bail { ($kind:ident, $start:expr, $curr:expr, $offset:expr) => { return Err(Error { - kind: ErrorKind::$kind, + kind: ErrorKind::$kind, index: ($curr.as_ptr() as usize) - ($start.as_ptr() as usize) + $offset, }) }; @@ -19,8 +19,8 @@ pub enum ErrorKind { #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub struct Error { - kind: ErrorKind, - index: usize, + pub kind: ErrorKind, + pub index: usize, } pub fn validate(mut program: &[u8]) -> Result<(), Error> { diff --git a/hbvm/src/vm/mem.rs b/hbvm/src/vm/mem.rs index ec7b17f9..759ea1ac 100644 --- a/hbvm/src/vm/mem.rs +++ b/hbvm/src/vm/mem.rs @@ -27,8 +27,11 @@ impl Memory { }); } + /// Load value from an address pub fn load(&self, addr: u64) -> Option { let (page, offset) = split_addr(addr); + + // Check if copy won't get over page boundary (TODO: make it go over) if offset + S::BYTES <= PAGE_SIZE - 1 { let mut value = MaybeUninit::::zeroed(); unsafe { @@ -37,6 +40,9 @@ impl Memory { value.as_mut_ptr().cast(), S::BYTES, ); + + // Even zeroed [`Value`] if holding valid variants as defined is valid, + // this is always valid. Some(value.assume_init()) } } else { @@ -44,8 +50,12 @@ impl Memory { } } + + /// Store value to an address pub fn store(&mut self, addr: u64, value: Value) -> Result<(), ()> { let (page, offset) = split_addr(addr); + + // Check if copy won't get over page boundary (TODO: make it go over) if offset + S::BYTES <= PAGE_SIZE - 1 { unsafe { core::ptr::copy_nonoverlapping( @@ -65,6 +75,7 @@ impl Memory { } } +/// Split address into page number and in-page offset #[inline] pub const fn split_addr(addr: u64) -> (u64, usize) { (addr >> PAGE_SIZE.count_ones(), (addr as usize & PAGE_SIZE)) diff --git a/hbvm/src/vm/mod.rs b/hbvm/src/vm/mod.rs index 170874de..93b1bdf0 100644 --- a/hbvm/src/vm/mod.rs +++ b/hbvm/src/vm/mod.rs @@ -1,4 +1,17 @@ +//! HoleyBytes Virtual Machine +//! +//! All unsafe code here should be sound, if input bytecode passes validation. + +// # General safety notice: +// - Validation has to assure there is 60 registers (r0 - r59) +// - Instructions has to be valid as specified (values and sizes) +// - Mapped pages should be at least 8 KiB + +mod mem; +mod value; + use { + crate::validate, core::ops, hbbytecode::{OpParam, ParamRI, ParamRR, ParamRRI, ParamRRR}, mem::{ma_size, Memory}, @@ -6,11 +19,6 @@ use { value::Value, }; -use crate::validate; - -mod mem; -mod value; - macro_rules! param { ($self:expr, $ty:ty) => {{ assert_impl_one!($ty: OpParam); diff --git a/hbvm/src/vm/value.rs b/hbvm/src/vm/value.rs index e0cf69cd..47dbb158 100644 --- a/hbvm/src/vm/value.rs +++ b/hbvm/src/vm/value.rs @@ -2,7 +2,7 @@ use core::fmt::Debug; /// # Safety /// The macro invoker shall make sure that byte reinterpret-cast -/// won't cause undefined behaviour. +/// or zero-init won't cause undefined behaviour. macro_rules! value_def { ($($fname:ident : $fty:ident, $getter:ident);* $(;)?) => { #[derive(Clone, Copy)]