2023-07-25 18:11:21 -05:00
|
|
|
//! HoleyBytes Virtual Machine
|
|
|
|
//!
|
|
|
|
//! # Alloc feature
|
|
|
|
//! - Enabled by default
|
2023-08-07 20:03:15 -05:00
|
|
|
//! - Provides mapping / unmapping, as well as [`Default`] and [`Drop`]
|
|
|
|
//! implementations for soft-paged memory implementation
|
2023-07-25 18:11:21 -05:00
|
|
|
|
|
|
|
// # General safety notice:
|
|
|
|
// - Validation has to assure there is 256 registers (r0 - r255)
|
|
|
|
// - Instructions have to be valid as specified (values and sizes)
|
|
|
|
// - Mapped pages should be at least 4 KiB
|
|
|
|
|
2023-05-09 03:36:37 -05:00
|
|
|
#![no_std]
|
2023-07-26 13:54:24 -05:00
|
|
|
#![cfg_attr(feature = "nightly", feature(fn_align))]
|
2023-08-17 19:31:49 -05:00
|
|
|
#![warn(missing_docs)]
|
2023-07-26 13:54:24 -05:00
|
|
|
|
2023-08-17 19:31:49 -05:00
|
|
|
use mem::{Memory, Address};
|
2023-08-17 18:41:05 -05:00
|
|
|
|
2023-07-25 18:11:21 -05:00
|
|
|
#[cfg(feature = "alloc")]
|
2023-04-22 16:06:33 -05:00
|
|
|
extern crate alloc;
|
|
|
|
|
2023-08-15 09:32:59 -05:00
|
|
|
pub mod mem;
|
2023-07-25 18:11:21 -05:00
|
|
|
pub mod value;
|
|
|
|
|
2023-08-07 20:03:15 -05:00
|
|
|
mod bmc;
|
2023-08-17 18:41:05 -05:00
|
|
|
mod vmrun;
|
2023-08-07 20:03:15 -05:00
|
|
|
|
2023-08-17 18:41:05 -05:00
|
|
|
use {bmc::BlockCopier, value::Value};
|
2023-07-25 18:11:21 -05:00
|
|
|
|
|
|
|
/// HoleyBytes Virtual Machine
|
2023-08-08 19:33:03 -05:00
|
|
|
pub struct Vm<Mem, const TIMER_QUOTIENT: usize> {
|
2023-07-25 18:11:21 -05:00
|
|
|
/// Holds 256 registers
|
|
|
|
///
|
|
|
|
/// Writing to register 0 is considered undefined behaviour
|
|
|
|
/// in terms of HoleyBytes program execution
|
|
|
|
pub registers: [Value; 256],
|
|
|
|
|
|
|
|
/// Memory implementation
|
2023-08-07 20:03:15 -05:00
|
|
|
pub memory: Mem,
|
2023-07-25 18:11:21 -05:00
|
|
|
|
|
|
|
/// Program counter
|
2023-08-17 19:31:49 -05:00
|
|
|
pub pc: Address,
|
2023-07-25 18:11:21 -05:00
|
|
|
|
|
|
|
/// Program timer
|
|
|
|
timer: usize,
|
2023-07-25 19:04:26 -05:00
|
|
|
|
|
|
|
/// Saved block copier
|
|
|
|
copier: Option<BlockCopier>,
|
2023-07-25 18:11:21 -05:00
|
|
|
}
|
|
|
|
|
2023-08-08 19:33:03 -05:00
|
|
|
impl<Mem, const TIMER_QUOTIENT: usize> Vm<Mem, TIMER_QUOTIENT>
|
2023-08-07 19:48:47 -05:00
|
|
|
where
|
2023-08-07 20:03:15 -05:00
|
|
|
Mem: Memory,
|
2023-07-25 18:11:21 -05:00
|
|
|
{
|
|
|
|
/// Create a new VM with program and trap handler
|
|
|
|
///
|
|
|
|
/// # Safety
|
|
|
|
/// Program code has to be validated
|
2023-08-17 19:31:49 -05:00
|
|
|
pub unsafe fn new(memory: Mem, entry: Address) -> Self {
|
2023-07-25 18:11:21 -05:00
|
|
|
Self {
|
|
|
|
registers: [Value::from(0_u64); 256],
|
|
|
|
memory,
|
2023-08-17 19:31:49 -05:00
|
|
|
pc: entry,
|
2023-07-25 18:11:21 -05:00
|
|
|
timer: 0,
|
2023-07-25 19:04:26 -05:00
|
|
|
copier: None,
|
2023-07-25 18:11:21 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Virtual machine halt error
|
|
|
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
|
|
|
#[repr(u8)]
|
|
|
|
pub enum VmRunError {
|
|
|
|
/// Tried to execute invalid instruction
|
|
|
|
InvalidOpcode(u8),
|
|
|
|
|
|
|
|
/// Unhandled load access exception
|
2023-08-17 19:31:49 -05:00
|
|
|
LoadAccessEx(Address),
|
2023-07-25 18:11:21 -05:00
|
|
|
|
2023-08-08 19:33:03 -05:00
|
|
|
/// Unhandled instruction load access exception
|
2023-08-17 19:31:49 -05:00
|
|
|
ProgramFetchLoadEx(Address),
|
2023-08-08 19:33:03 -05:00
|
|
|
|
2023-07-25 18:11:21 -05:00
|
|
|
/// Unhandled store access exception
|
2023-08-17 19:31:49 -05:00
|
|
|
StoreAccessEx(Address),
|
2023-07-25 18:11:21 -05:00
|
|
|
|
|
|
|
/// Register out-of-bounds access
|
|
|
|
RegOutOfBounds,
|
|
|
|
|
2023-07-25 19:28:14 -05:00
|
|
|
/// Address out-of-bounds
|
|
|
|
AddrOutOfBounds,
|
|
|
|
|
2023-07-25 18:11:21 -05:00
|
|
|
/// Reached unreachable code
|
|
|
|
Unreachable,
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Virtual machine halt ok
|
|
|
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
|
|
|
pub enum VmRunOk {
|
|
|
|
/// Program has eached its end
|
|
|
|
End,
|
|
|
|
|
|
|
|
/// Program was interrupted by a timer
|
|
|
|
Timer,
|
|
|
|
|
|
|
|
/// Environment call
|
|
|
|
Ecall,
|
|
|
|
}
|