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, SUB = 2,
MUL = 3, MUL = 3,
DIV = 4, DIV = 4,
MOD = 5,
And = 6,
Or = 7,
Xor = 8,
Not = 9,
// LOADs a memory address/constant into a register // LOADs a memory address/constant into a register
LOAD = 5, LOAD = 15,
// STOREs a register/constant into a memory address // 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, JUMP = 100,
JumpCond = 101, JumpCond = 101,
RET = 103, RET = 103,
EnviromentCall = 255,
} }
pub enum SubTypes { pub enum SubTypes {
@ -41,5 +53,7 @@ pub enum JumpConditionals {
Equal = 0, Equal = 0,
NotEqual = 1, NotEqual = 1,
LessThan = 2, 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 call_stack;
pub mod config; pub mod config;
pub mod enviroment_calls;
pub mod regs; pub mod regs;
use crate::bytecode::ops::Operations::*; use crate::bytecode::{
use crate::bytecode::ops::*; ops::{Operations::*, *},
use crate::bytecode::types::*; types::*,
};
use crate::engine::call_stack::FnCall; use {
use crate::memory; crate::{engine::call_stack::FnCall, memory, HaltStatus, RuntimeErrors},
use crate::HaltStatus; alloc::vec::Vec,
use crate::RuntimeErrors; config::EngineConfig,
use alloc::vec::Vec; log::trace,
use config::EngineConfig; regs::Registers,
use log::trace; };
use regs::Registers;
use self::call_stack::CallStack; use self::call_stack::CallStack;
// pub const PAGE_SIZE: usize = 8192;
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub struct Page { pub struct Page {
pub data: [u8; 4096 * 2], pub data: [u8; 8192],
} }
impl Page { impl Page {
pub fn new() -> Self { 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> { pub fn empty_enviroment_call(engine: &mut Engine) -> Result<&mut Engine, u64> {
trace!("Registers {:?}", reg); trace!("Registers {:?}", engine.registers);
Err(0) Err(0)
} }
pub struct Engine { pub struct Engine {
pub index: usize, pub index: usize,
program: Vec<u8>, program: Vec<u8>,
registers: Registers, registers: Registers,
config: EngineConfig, config: EngineConfig,
/// BUG: This DOES NOT account for overflowing /// BUG: This DOES NOT account for overflowing
last_timer_count: u32, last_timer_count: u32,
@ -47,7 +49,7 @@ pub struct Engine {
pub enviroment_call_table: [EnviromentCall; 256], pub enviroment_call_table: [EnviromentCall; 256],
call_stack: CallStack, call_stack: CallStack,
} }
use crate::engine::enviroment_calls::EnviromentCall;
impl Engine { impl Engine {
pub fn read_mem_addr_8(&mut self, address: u64) -> Result<u8, RuntimeErrors> { pub fn read_mem_addr_8(&mut self, address: u64) -> Result<u8, RuntimeErrors> {
// println!("{}", address); // println!("{}", address);
@ -62,10 +64,9 @@ impl Engine {
pub fn new(program: Vec<u8>) -> Self { pub fn new(program: Vec<u8>) -> Self {
let mut mem = memory::Memory::new(); let mut mem = memory::Memory::new();
for (addr, byte) in program.clone().into_iter().enumerate() { for (addr, byte) in program.clone().into_iter().enumerate() {
let ret = mem.set_addr8(addr as u64, byte); let _ = mem.set_addr8(addr as u64, byte);
println!("{:?}", ret);
} }
println!("{:?}", mem.read_addr8(0)); trace!("{:?}", mem.read_addr8(0));
Self { Self {
index: 0, index: 0,
@ -75,7 +76,7 @@ impl Engine {
last_timer_count: 0, last_timer_count: 0,
timer_callback: None, timer_callback: None,
enviroment_call_table: [empty_enviroment_call; 256], enviroment_call_table: [empty_enviroment_call; 256],
memory: memory::Memory::new(), memory: mem,
call_stack: Vec::new(), call_stack: Vec::new(),
} }
} }
@ -165,8 +166,7 @@ F5-F9 {:016X} {:016X} {:016X} {:016X} {:016X}",
); );
} }
pub fn run(&mut self) -> Result<HaltStatus, RuntimeErrors> { pub fn run(&mut self) -> Result<HaltStatus, RuntimeErrors> {
use HaltStatus::*; use {HaltStatus::*, RuntimeErrors::*};
use RuntimeErrors::*;
loop { loop {
// Break out of the loop // Break out of the loop
if self.index + 1 == self.program.len() { 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) => { (2, 1) => {
let lhs = self.program[self.index + 2]; let lhs = self.program[self.index + 2];
@ -335,18 +335,25 @@ F5-F9 {:016X} {:016X} {:016X} {:016X} {:016X}",
trace!("addr {}", addr); trace!("addr {}", addr);
let ret = self.read_mem_addr_8(addr)?; let ret = self.read_mem_addr_8(addr);
let reg = self.program[self.index + 10]; match ret {
trace!("reg {}", reg); Ok(ret) => {
self.set_register_8(reg, ret); let reg = self.program[self.index + 10];
self.index += 9; trace!("reg {}", reg);
self.set_register_8(reg, ret);
self.index += 10;
}
Err(err) => trace!("{:?}", err),
}
} }
(10, int) => { (10, int) => {
println!("Enviroment Call {}", int); trace!("Enviroment Call {}", int);
let ret = self.enviroment_call_table[int as usize](self.registers); let ret = self.enviroment_call_table[int as usize](self);
match ret { match ret {
Ok(_) => {} Ok(eng) => {
trace!("Resuming execution at {}", eng.index);
}
Err(err) => { Err(err) => {
return Err(HostError(err)); return Err(HostError(err));
} }
@ -366,9 +373,9 @@ F5-F9 {:016X} {:016X} {:016X} {:016X} {:016X}",
.into_iter() .into_iter()
.enumerate() .enumerate()
{ {
trace!("byte {}", byte);
addr_array[index] = *byte; addr_array[index] = *byte;
} }
let addr = usize::from_be_bytes(addr_array); let addr = usize::from_be_bytes(addr_array);
if addr > self.program.len() { if addr > self.program.len() {
panic!("Invalid jump address {}", addr) panic!("Invalid jump address {}", addr)

View File

@ -1,6 +1,6 @@
#[rustfmt::skip] #[rustfmt::skip]
#[derive(Debug, Clone, Copy)] #[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 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 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, 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), InvalidOpcode(u8),
RegisterTooSmall, RegisterTooSmall,
HostError(u64), HostError(u64),
PageUnmapped(u64), PageNotMapped(u64),
} }
// If you solve the halting problem feel free to remove this // If you solve the halting problem feel free to remove this

View File

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

View File

@ -21,15 +21,18 @@ impl Memory {
impl Memory { impl Memory {
pub fn read_addr8(&mut self, address: u64) -> Result<u8, RuntimeErrors> { pub fn read_addr8(&mut self, address: u64) -> Result<u8, RuntimeErrors> {
let (page, offset) = addr_to_page(address); let (page, offset) = addr_to_page(address);
println!("page {} offset {}", page, offset); trace!("page {} offset {}", page, offset);
match self.inner.get(&page) { match self.inner.get(&page) {
Some(page) => { Some(page) => {
let val = page.data[offset as usize]; let val = page.data[offset as usize];
trace!("Value {}", val);
Ok(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 { pub fn read_addr64(&mut self, address: u64) -> u64 {
unimplemented!() unimplemented!()