Small improvements
This commit is contained in:
parent
a34f2fc9f8
commit
da6ad6d2c7
|
@ -1,7 +1,10 @@
|
|||
use std::fmt::{Display, Formatter};
|
||||
use {
|
||||
logos::{Lexer, Logos, Span},
|
||||
std::{ops::Range, str::FromStr},
|
||||
std::{
|
||||
fmt::{Display, Formatter},
|
||||
ops::Range,
|
||||
str::FromStr,
|
||||
},
|
||||
};
|
||||
|
||||
macro_rules! tokendef {
|
||||
|
@ -131,23 +134,13 @@ pub fn assembly(code: &str, buf: &mut Vec<u8>) -> Result<(), Error> {
|
|||
}
|
||||
|
||||
fn rr(&mut self) -> Result<(), ErrorKind> {
|
||||
expect_matches!(
|
||||
self,
|
||||
Token::Register(r0),
|
||||
Token::PSep,
|
||||
Token::Register(r1),
|
||||
);
|
||||
expect_matches!(self, Token::Register(r0), Token::PSep, Token::Register(r1),);
|
||||
self.buf.extend([r0, r1]);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn ri(&mut self) -> Result<(), ErrorKind> {
|
||||
expect_matches!(
|
||||
self,
|
||||
Token::Register(r0),
|
||||
Token::PSep,
|
||||
Token::Integer(r1),
|
||||
);
|
||||
expect_matches!(self, Token::Register(r0), Token::PSep, Token::Integer(r1),);
|
||||
|
||||
self.buf.push(r0);
|
||||
self.buf.extend(r1.to_le_bytes());
|
||||
|
@ -169,10 +162,7 @@ pub fn assembly(code: &str, buf: &mut Vec<u8>) -> Result<(), Error> {
|
|||
}
|
||||
|
||||
fn i(&mut self) -> Result<(), ErrorKind> {
|
||||
expect_matches!(
|
||||
self,
|
||||
Token::Integer(imm),
|
||||
);
|
||||
expect_matches!(self, Token::Integer(imm),);
|
||||
self.buf.extend(imm.to_le_bytes());
|
||||
Ok(())
|
||||
}
|
||||
|
@ -185,6 +175,6 @@ pub fn assembly(code: &str, buf: &mut Vec<u8>) -> Result<(), Error> {
|
|||
|
||||
asm.assemble().map_err(|kind| Error {
|
||||
kind,
|
||||
span: asm.lexer.span()
|
||||
span: asm.lexer.span(),
|
||||
})
|
||||
}
|
||||
|
|
|
@ -49,10 +49,14 @@ constmod!(pub opcode(u8) {
|
|||
ECALL = 30, // N; Issue system call
|
||||
});
|
||||
|
||||
#[repr(packed)] pub struct ParamRRR(pub u8, pub u8, pub u8);
|
||||
#[repr(packed)] pub struct ParamRRI(pub u8, pub u8, pub u64);
|
||||
#[repr(packed)] pub struct ParamRR(pub u8, pub u8);
|
||||
#[repr(packed)] pub struct ParamRI(pub u8, pub u64);
|
||||
#[repr(packed)]
|
||||
pub struct ParamRRR(pub u8, pub u8, pub u8);
|
||||
#[repr(packed)]
|
||||
pub struct ParamRRI(pub u8, pub u8, pub u64);
|
||||
#[repr(packed)]
|
||||
pub struct ParamRR(pub u8, pub u8);
|
||||
#[repr(packed)]
|
||||
pub struct ParamRI(pub u8, pub u64);
|
||||
|
||||
/// # Safety
|
||||
/// TODO.
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
use std::io::{Read, stdin};
|
||||
use hbvm::{validate::validate, vm::Vm, RuntimeErrors};
|
||||
use {
|
||||
hbvm::{validate::validate, vm::Vm, RuntimeErrors},
|
||||
std::io::{stdin, Read},
|
||||
};
|
||||
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let mut prog = vec![];
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
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: ErrorKind::$kind,
|
||||
index: ($curr.as_ptr() as usize) - ($start.as_ptr() as usize) + $offset,
|
||||
})
|
||||
};
|
||||
($kind:ident, $start:expr, $curr:expr) => {
|
||||
|
@ -62,12 +62,12 @@ pub fn validate(mut program: &[u8]) -> Result<(), Error> {
|
|||
rest
|
||||
}
|
||||
// RRI
|
||||
[LD..=SO, _, _, _, _, _, _, _, _, _, _, rest @ ..] => {
|
||||
[LB..=SO, _, _, _, _, _, _, _, _, _, _, rest @ ..] => {
|
||||
if let Some(n) = reg(&program[1..=2]) {
|
||||
bail!(InvalidRegister, start, program, n + 1);
|
||||
}
|
||||
rest
|
||||
},
|
||||
}
|
||||
_ => bail!(InvalidInstruction, start, program),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,11 +5,11 @@ use {
|
|||
ma_size::MemAccessSize,
|
||||
};
|
||||
|
||||
pub const PAGE_SIZE: u64 = 8192;
|
||||
pub const PAGE_SIZE: usize = 8192;
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct Memory {
|
||||
pages: HashMap<u64, Box<[u8; PAGE_SIZE as usize]>>,
|
||||
pages: HashMap<u64, Box<[u8; PAGE_SIZE]>>,
|
||||
}
|
||||
|
||||
impl Memory {
|
||||
|
@ -17,8 +17,8 @@ impl Memory {
|
|||
// implemented.
|
||||
pub fn insert_test_page(&mut self) {
|
||||
self.pages.insert(0, unsafe {
|
||||
use alloc::alloc::{alloc_zeroed, Layout, handle_alloc_error};
|
||||
let layout = Layout::new::<[u8; PAGE_SIZE as usize]>();
|
||||
use alloc::alloc::{alloc_zeroed, handle_alloc_error, Layout};
|
||||
let layout = Layout::new::<[u8; PAGE_SIZE]>();
|
||||
let ptr = alloc_zeroed(layout);
|
||||
if ptr.is_null() {
|
||||
handle_alloc_error(layout);
|
||||
|
@ -29,13 +29,13 @@ impl Memory {
|
|||
|
||||
pub fn load<S: MemAccessSize>(&self, addr: u64) -> Option<Value> {
|
||||
let (page, offset) = split_addr(addr);
|
||||
if offset + u16::from(S::BYTES) <= (PAGE_SIZE as u16 - 1) {
|
||||
if offset + S::BYTES <= PAGE_SIZE - 1 {
|
||||
let mut value = MaybeUninit::<Value>::zeroed();
|
||||
unsafe {
|
||||
core::ptr::copy_nonoverlapping(
|
||||
self.pages.get(&page)?.as_ptr().add(usize::from(offset)),
|
||||
self.pages.get(&page)?.as_ptr().add(offset),
|
||||
value.as_mut_ptr().cast(),
|
||||
S::BYTES.into(),
|
||||
S::BYTES,
|
||||
);
|
||||
Some(value.assume_init())
|
||||
}
|
||||
|
@ -46,7 +46,7 @@ impl Memory {
|
|||
|
||||
pub fn store<S: MemAccessSize>(&mut self, addr: u64, value: Value) -> Result<(), ()> {
|
||||
let (page, offset) = split_addr(addr);
|
||||
if offset + u16::from(S::BYTES) <= (PAGE_SIZE as u16 - 1) {
|
||||
if offset + S::BYTES <= PAGE_SIZE - 1 {
|
||||
unsafe {
|
||||
core::ptr::copy_nonoverlapping(
|
||||
(&value as *const Value).cast::<u8>(),
|
||||
|
@ -54,8 +54,8 @@ impl Memory {
|
|||
.get_mut(&page)
|
||||
.ok_or(())?
|
||||
.as_mut_ptr()
|
||||
.add(usize::from(offset)),
|
||||
S::BYTES.into(),
|
||||
.add(offset),
|
||||
S::BYTES,
|
||||
)
|
||||
};
|
||||
Ok(())
|
||||
|
@ -66,21 +66,24 @@ impl Memory {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub const fn split_addr(addr: u64) -> (u64, u16) {
|
||||
(addr >> PAGE_SIZE.count_ones(), (addr & PAGE_SIZE) as u16)
|
||||
pub const fn split_addr(addr: u64) -> (u64, usize) {
|
||||
(addr >> PAGE_SIZE.count_ones(), (addr as usize & PAGE_SIZE))
|
||||
}
|
||||
|
||||
macro_rules! size_markers {
|
||||
($($name:ident = $size:expr),* $(,)?) => {
|
||||
pub mod ma_size {
|
||||
/// # Safety
|
||||
/// Implementor has to assure that [`MemAccessSize::BYTES`] won't be larger than
|
||||
/// size of [`Value`]
|
||||
pub unsafe trait MemAccessSize {
|
||||
const BYTES: u8;
|
||||
const BYTES: usize;
|
||||
}
|
||||
|
||||
$(
|
||||
pub struct $name;
|
||||
unsafe impl MemAccessSize for $name {
|
||||
const BYTES: u8 = $size;
|
||||
const BYTES: usize = $size;
|
||||
}
|
||||
)*
|
||||
}
|
||||
|
|
|
@ -1,8 +1,3 @@
|
|||
use crate::validate;
|
||||
|
||||
mod mem;
|
||||
mod value;
|
||||
|
||||
use {
|
||||
core::ops,
|
||||
hbbytecode::{OpParam, ParamRI, ParamRR, ParamRRI, ParamRRR},
|
||||
|
@ -11,6 +6,11 @@ use {
|
|||
value::Value,
|
||||
};
|
||||
|
||||
use crate::validate;
|
||||
|
||||
mod mem;
|
||||
mod value;
|
||||
|
||||
macro_rules! param {
|
||||
($self:expr, $ty:ty) => {{
|
||||
assert_impl_one!($ty: OpParam);
|
||||
|
@ -26,7 +26,14 @@ macro_rules! param {
|
|||
macro_rules! binary_op {
|
||||
($self:expr, $ty:ident, $handler:expr) => {{
|
||||
let ParamRRR(tg, a0, a1) = param!($self, ParamRRR);
|
||||
$self.write_reg(tg, $handler(Value::$ty(&$self.read_reg(a0)), Value::$ty(&$self.read_reg(a1))).into());
|
||||
$self.write_reg(
|
||||
tg,
|
||||
$handler(
|
||||
Value::$ty(&$self.read_reg(a0)),
|
||||
Value::$ty(&$self.read_reg(a1)),
|
||||
)
|
||||
.into(),
|
||||
);
|
||||
}};
|
||||
}
|
||||
|
||||
|
@ -35,9 +42,10 @@ macro_rules! load {
|
|||
let ParamRRI(tg, a0, offset) = param!($self, ParamRRI);
|
||||
$self.write_reg(
|
||||
tg,
|
||||
$self.memory
|
||||
$self
|
||||
.memory
|
||||
.load::<$size>($self.read_reg(a0).int() + offset)
|
||||
.ok_or(Exception::LoadAccess)?
|
||||
.ok_or(Exception::LoadAccess)?,
|
||||
);
|
||||
}};
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue