forked from AbleOS/holey-bytes
Added zero register + relative jump
This commit is contained in:
parent
fce7a96e50
commit
a34f2fc9f8
|
@ -99,9 +99,8 @@ pub fn assembly(code: &str, buf: &mut Vec<u8>) -> Result<(), Error> {
|
||||||
NOP | RET | ECALL => Ok(()),
|
NOP | RET | ECALL => Ok(()),
|
||||||
ADD..=XOR | ADDF..=DIVF => self.rrr(),
|
ADD..=XOR | ADDF..=DIVF => self.rrr(),
|
||||||
NOT | CP => self.rr(),
|
NOT | CP => self.rr(),
|
||||||
LI => self.ri(),
|
LI | JMP => self.ri(),
|
||||||
LB..=SO => self.rri(),
|
LB..=SO => self.rri(),
|
||||||
JMP => self.i(),
|
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}?;
|
}?;
|
||||||
match self.next() {
|
match self.next() {
|
||||||
|
|
|
@ -43,7 +43,7 @@ constmod!(pub opcode(u8) {
|
||||||
PAGEUNMAP = 25, // ?; Unmap a page
|
PAGEUNMAP = 25, // ?; Unmap a page
|
||||||
PAGEMP = 26, // ?; Page modify protection flags
|
PAGEMP = 26, // ?; Page modify protection flags
|
||||||
|
|
||||||
JMP = 27, // I; Unconditional jump
|
JMP = 27, // RI; Unconditional jump [#0 + imm #1]
|
||||||
JMPCOND = 28, // ?; Conditional jump
|
JMPCOND = 28, // ?; Conditional jump
|
||||||
RET = 29, // N; Return
|
RET = 29, // N; Return
|
||||||
ECALL = 30, // N; Issue system call
|
ECALL = 30, // N; Issue system call
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
use hbbytecode::opcode;
|
use std::io::{Read, stdin};
|
||||||
use hbvm::{validate::validate, vm::Vm, RuntimeErrors};
|
use hbvm::{validate::validate, vm::Vm, RuntimeErrors};
|
||||||
|
|
||||||
fn main() -> Result<(), RuntimeErrors> {
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
// TODO: Grab program from cmdline
|
let mut prog = vec![];
|
||||||
#[rustfmt::skip]
|
stdin().read_to_end(&mut prog)?;
|
||||||
let prog = &[];
|
|
||||||
|
|
||||||
if let Err(e) = validate(prog) {
|
if let Err(e) = validate(&prog) {
|
||||||
eprintln!("Program validation error: {e:?}");
|
eprintln!("Program validation error: {e:?}");
|
||||||
return Ok(());
|
return Ok(());
|
||||||
} else {
|
} else {
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut vm = Vm::new_unchecked(prog);
|
let mut vm = Vm::new_unchecked(&prog);
|
||||||
vm.memory.insert_test_page();
|
vm.memory.insert_test_page();
|
||||||
vm.run();
|
vm.run();
|
||||||
|
println!("{:?}", vm.registers);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -55,7 +55,7 @@ pub fn validate(mut program: &[u8]) -> Result<(), Error> {
|
||||||
rest
|
rest
|
||||||
}
|
}
|
||||||
// RI
|
// RI
|
||||||
[LI, reg, _, _, _, _, _, _, _, _, rest @ ..] => {
|
[LI | JMP, reg, _, _, _, _, _, _, _, _, rest @ ..] => {
|
||||||
if *reg > 59 {
|
if *reg > 59 {
|
||||||
bail!(InvalidRegister, start, program, 1);
|
bail!(InvalidRegister, start, program, 1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,17 +26,19 @@ macro_rules! param {
|
||||||
macro_rules! binary_op {
|
macro_rules! binary_op {
|
||||||
($self:expr, $ty:ident, $handler:expr) => {{
|
($self:expr, $ty:ident, $handler:expr) => {{
|
||||||
let ParamRRR(tg, a0, a1) = param!($self, ParamRRR);
|
let ParamRRR(tg, a0, a1) = param!($self, ParamRRR);
|
||||||
*$self.reg_mut(tg) = $handler(Value::$ty($self.reg(a0)), Value::$ty($self.reg(a1))).into();
|
$self.write_reg(tg, $handler(Value::$ty(&$self.read_reg(a0)), Value::$ty(&$self.read_reg(a1))).into());
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! load {
|
macro_rules! load {
|
||||||
($self:expr, $size:ty) => {{
|
($self:expr, $size:ty) => {{
|
||||||
let ParamRRI(tg, a0, offset) = param!($self, ParamRRI);
|
let ParamRRI(tg, a0, offset) = param!($self, ParamRRI);
|
||||||
*$self.reg_mut(tg) = $self
|
$self.write_reg(
|
||||||
.memory
|
tg,
|
||||||
.load::<$size>($self.reg(a0).int() + offset)
|
$self.memory
|
||||||
.ok_or(Exception::LoadAccess)?;
|
.load::<$size>($self.read_reg(a0).int() + offset)
|
||||||
|
.ok_or(Exception::LoadAccess)?
|
||||||
|
);
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,7 +47,7 @@ macro_rules! store {
|
||||||
let ParamRRI(src, a0, offset) = param!($self, ParamRRI);
|
let ParamRRI(src, a0, offset) = param!($self, ParamRRI);
|
||||||
$self
|
$self
|
||||||
.memory
|
.memory
|
||||||
.store::<$size>($self.reg(a0).int() + offset, *$self.reg(src))
|
.store::<$size>($self.read_reg(a0).int() + offset, $self.read_reg(src))
|
||||||
.map_err(|_| Exception::StoreAccess)?;
|
.map_err(|_| Exception::StoreAccess)?;
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
@ -93,7 +95,7 @@ impl<'a> Vm<'a> {
|
||||||
XOR => binary_op!(self, int, ops::BitXor::bitxor),
|
XOR => binary_op!(self, int, ops::BitXor::bitxor),
|
||||||
NOT => {
|
NOT => {
|
||||||
let param = param!(self, ParamRR);
|
let param = param!(self, ParamRR);
|
||||||
*self.reg_mut(param.0) = (!self.reg(param.1).int()).into();
|
self.write_reg(param.0, (!self.read_reg(param.1).int()).into());
|
||||||
}
|
}
|
||||||
ADDF => binary_op!(self, float, ops::Add::add),
|
ADDF => binary_op!(self, float, ops::Add::add),
|
||||||
SUBF => binary_op!(self, float, ops::Sub::sub),
|
SUBF => binary_op!(self, float, ops::Sub::sub),
|
||||||
|
@ -101,11 +103,11 @@ impl<'a> Vm<'a> {
|
||||||
DIVF => binary_op!(self, float, ops::Div::div),
|
DIVF => binary_op!(self, float, ops::Div::div),
|
||||||
CP => {
|
CP => {
|
||||||
let param = param!(self, ParamRR);
|
let param = param!(self, ParamRR);
|
||||||
*self.reg_mut(param.0) = *self.reg(param.1);
|
self.write_reg(param.0, self.read_reg(param.1));
|
||||||
}
|
}
|
||||||
LI => {
|
LI => {
|
||||||
let param = param!(self, ParamRI);
|
let param = param!(self, ParamRI);
|
||||||
*self.reg_mut(param.0) = param.1.into();
|
self.write_reg(param.0, param.1.into());
|
||||||
}
|
}
|
||||||
LB => load!(self, ma_size::Byte),
|
LB => load!(self, ma_size::Byte),
|
||||||
LD => load!(self, ma_size::Doublet),
|
LD => load!(self, ma_size::Doublet),
|
||||||
|
@ -116,8 +118,8 @@ impl<'a> Vm<'a> {
|
||||||
SQ => store!(self, ma_size::Quadlet),
|
SQ => store!(self, ma_size::Quadlet),
|
||||||
SO => store!(self, ma_size::Octlet),
|
SO => store!(self, ma_size::Octlet),
|
||||||
JMP => {
|
JMP => {
|
||||||
self.pc =
|
let ParamRI(reg, offset) = param!(self, ParamRI);
|
||||||
self.program.as_ptr().add(self.pc + 1).cast::<u64>().read() as usize;
|
self.pc = (self.read_reg(reg).int() + offset) as usize;
|
||||||
}
|
}
|
||||||
_ => core::hint::unreachable_unchecked(),
|
_ => core::hint::unreachable_unchecked(),
|
||||||
}
|
}
|
||||||
|
@ -126,13 +128,19 @@ impl<'a> Vm<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn reg(&self, n: u8) -> &Value {
|
unsafe fn read_reg(&self, n: u8) -> Value {
|
||||||
self.registers.get_unchecked(n as usize)
|
if n == 0 {
|
||||||
|
0.into()
|
||||||
|
} else {
|
||||||
|
*self.registers.get_unchecked(n as usize)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn reg_mut(&mut self, n: u8) -> &mut Value {
|
unsafe fn write_reg(&mut self, n: u8, value: Value) {
|
||||||
self.registers.get_unchecked_mut(n as usize)
|
if n != 0 {
|
||||||
|
*self.registers.get_unchecked_mut(n as usize) = value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue