feature/trap-handlers
Able 2023-05-06 07:33:40 -05:00
parent 46eb4c17a0
commit 5909b8e520
7 changed files with 81 additions and 55 deletions

View File

@ -5,17 +5,29 @@ pub enum Operations {
SUB = 2,
MUL = 3,
DIV = 4,
MOD = 5,
And = 6,
Or = 7,
Xor = 8,
Not = 9,
// LOADs a memory address/constant into a register
LOAD = 5,
LOAD = 15,
// STOREs a register/constant into a memory address
STORE = 6,
STORE = 16,
EnviromentCall = 10,
MapPage = 17,
UnmapPage = 18,
// SHIFT LEFT 16 A0
Shift = 20,
JUMP = 100,
JumpCond = 101,
RET = 103,
EnviromentCall = 255,
}
pub enum SubTypes {
@ -41,5 +53,7 @@ pub enum JumpConditionals {
Equal = 0,
NotEqual = 1,
LessThan = 2,
GreaterThan = 3,
LessThanOrEqualTo = 3,
GreaterThan = 4,
GreaterThanOrEqualTo = 5,
}

View File

@ -0,0 +1,3 @@
use super::Engine;
pub type EnviromentCall = fn(&mut Engine) -> Result<&mut Engine, u64>;

View File

@ -1,24 +1,27 @@
pub mod call_stack;
pub mod config;
pub mod enviroment_calls;
pub mod regs;
use crate::bytecode::ops::Operations::*;
use crate::bytecode::ops::*;
use crate::bytecode::types::*;
use crate::bytecode::{
ops::{Operations::*, *},
types::*,
};
use crate::engine::call_stack::FnCall;
use crate::memory;
use crate::HaltStatus;
use crate::RuntimeErrors;
use alloc::vec::Vec;
use config::EngineConfig;
use log::trace;
use regs::Registers;
use {
crate::{engine::call_stack::FnCall, memory, HaltStatus, RuntimeErrors},
alloc::vec::Vec,
config::EngineConfig,
log::trace,
regs::Registers,
};
use self::call_stack::CallStack;
// pub const PAGE_SIZE: usize = 8192;
#[derive(Debug, Clone, Copy)]
pub struct Page {
pub data: [u8; 4096 * 2],
pub data: [u8; 8192],
}
impl Page {
pub fn new() -> Self {
@ -27,18 +30,17 @@ impl Page {
}
}
}
pub type EnviromentCall = fn(Registers) -> Result<Registers, u64>;
pub fn empty_enviroment_call(reg: Registers) -> Result<Registers, u64> {
trace!("Registers {:?}", reg);
pub fn empty_enviroment_call(engine: &mut Engine) -> Result<&mut Engine, u64> {
trace!("Registers {:?}", engine.registers);
Err(0)
}
pub struct Engine {
pub index: usize,
program: Vec<u8>,
program: Vec<u8>,
registers: Registers,
config: EngineConfig,
config: EngineConfig,
/// BUG: This DOES NOT account for overflowing
last_timer_count: u32,
@ -47,7 +49,7 @@ pub struct Engine {
pub enviroment_call_table: [EnviromentCall; 256],
call_stack: CallStack,
}
use crate::engine::enviroment_calls::EnviromentCall;
impl Engine {
pub fn read_mem_addr_8(&mut self, address: u64) -> Result<u8, RuntimeErrors> {
// println!("{}", address);
@ -62,10 +64,9 @@ impl Engine {
pub fn new(program: Vec<u8>) -> Self {
let mut mem = memory::Memory::new();
for (addr, byte) in program.clone().into_iter().enumerate() {
let ret = mem.set_addr8(addr as u64, byte);
println!("{:?}", ret);
let _ = mem.set_addr8(addr as u64, byte);
}
println!("{:?}", mem.read_addr8(0));
trace!("{:?}", mem.read_addr8(0));
Self {
index: 0,
@ -75,7 +76,7 @@ impl Engine {
last_timer_count: 0,
timer_callback: None,
enviroment_call_table: [empty_enviroment_call; 256],
memory: memory::Memory::new(),
memory: mem,
call_stack: Vec::new(),
}
}
@ -165,8 +166,7 @@ F5-F9 {:016X} {:016X} {:016X} {:016X} {:016X}",
);
}
pub fn run(&mut self) -> Result<HaltStatus, RuntimeErrors> {
use HaltStatus::*;
use RuntimeErrors::*;
use {HaltStatus::*, RuntimeErrors::*};
loop {
// Break out of the loop
if self.index + 1 == self.program.len() {
@ -245,7 +245,7 @@ F5-F9 {:016X} {:016X} {:016X} {:016X} {:016X}",
}
}
self.index += 19;
self.index += 18;
}
(2, 1) => {
let lhs = self.program[self.index + 2];
@ -335,18 +335,25 @@ F5-F9 {:016X} {:016X} {:016X} {:016X} {:016X}",
trace!("addr {}", addr);
let ret = self.read_mem_addr_8(addr)?;
let reg = self.program[self.index + 10];
trace!("reg {}", reg);
self.set_register_8(reg, ret);
self.index += 9;
let ret = self.read_mem_addr_8(addr);
match ret {
Ok(ret) => {
let reg = self.program[self.index + 10];
trace!("reg {}", reg);
self.set_register_8(reg, ret);
self.index += 10;
}
Err(err) => trace!("{:?}", err),
}
}
(10, int) => {
println!("Enviroment Call {}", int);
let ret = self.enviroment_call_table[int as usize](self.registers);
trace!("Enviroment Call {}", int);
let ret = self.enviroment_call_table[int as usize](self);
match ret {
Ok(_) => {}
Ok(eng) => {
trace!("Resuming execution at {}", eng.index);
}
Err(err) => {
return Err(HostError(err));
}
@ -366,9 +373,9 @@ F5-F9 {:016X} {:016X} {:016X} {:016X} {:016X}",
.into_iter()
.enumerate()
{
trace!("byte {}", byte);
addr_array[index] = *byte;
}
let addr = usize::from_be_bytes(addr_array);
if addr > self.program.len() {
panic!("Invalid jump address {}", addr)

View File

@ -1,6 +1,6 @@
#[rustfmt::skip]
#[derive(Debug, Clone, Copy)]
pub struct Registers{
pub struct Registers {
pub a0: u8, pub b0: u8, pub c0: u8, pub d0: u64, pub e0: u64, pub f0: u64,
pub a1: u8, pub b1: u8, pub c1: u8, pub d1: u64, pub e1: u64, pub f1: u64,
pub a2: u8, pub b2: u8, pub c2: u8, pub d2: u64, pub e2: u64, pub f2: u64,

View File

@ -14,7 +14,7 @@ pub enum RuntimeErrors {
InvalidOpcode(u8),
RegisterTooSmall,
HostError(u64),
PageUnmapped(u64),
PageNotMapped(u64),
}
// If you solve the halting problem feel free to remove this

View File

@ -1,6 +1,6 @@
use holey_bytes::{
bytecode::ops::{Operations::*, RWSubTypes::*, SubTypes::*},
engine::{regs::Registers, Engine},
engine::Engine,
RuntimeErrors,
};
@ -8,8 +8,7 @@ fn main() -> Result<(), RuntimeErrors> {
#[rustfmt::skip]
let prog: Vec<u8> = vec![
NOP as u8, NOP as u8,
// 10, 10,
10, 10,
ADD as u8, EightBit as u8, 100, 20, 0xA7,
ADD as u8,
EightBit as u8, 1, 0, 0xB0,
@ -22,15 +21,16 @@ fn main() -> Result<(), RuntimeErrors> {
LOAD as u8, AddrToReg as u8,
0, 0, 0, 0, 0, 0, 0, 2,
0xA0,
JUMP as u8, 0, 0, 0, 0, 0, 0, 0, 5,
// JUMP as u8, 0, 0, 0, 0, 0, 0, 0, 0,
JUMP as u8, 0, 0, 0, 0, 0, 0, 0, 0,
];
let mut eng = Engine::new(prog);
println!("{:?}", eng.read_mem_addr_8(4));
// eng.set_timer_callback(time);
// eng.enviroment_call_table[10] = print_fn;
// eng.run()?;
// eng.dump();
eng.enviroment_call_table[10] = print_fn;
eng.run()?;
eng.dump();
Ok(())
}
@ -38,8 +38,7 @@ fn main() -> Result<(), RuntimeErrors> {
pub fn time() -> u32 {
9
}
pub fn print_fn(mut reg: Registers) -> Result<Registers, u64> {
println!("{:?}", reg);
Ok(reg)
pub fn print_fn(engine: &mut Engine) -> Result<&mut Engine, u64> {
println!("hello");
Ok(engine)
}

View File

@ -21,15 +21,18 @@ impl Memory {
impl Memory {
pub fn read_addr8(&mut self, address: u64) -> Result<u8, RuntimeErrors> {
let (page, offset) = addr_to_page(address);
println!("page {} offset {}", page, offset);
trace!("page {} offset {}", page, offset);
match self.inner.get(&page) {
Some(page) => {
let val = page.data[offset as usize];
trace!("Value {}", val);
Ok(val)
}
None => Err(RuntimeErrors::PageUnmapped(page)),
None => {
trace!("page not mapped");
Err(RuntimeErrors::PageNotMapped(page))
}
}
// trace!("Value read {} from page {} offset {}", val, page, offset);
}
pub fn read_addr64(&mut self, address: u64) -> u64 {
unimplemented!()