holey-bytes/src/engine/mod.rs

446 lines
15 KiB
Rust

pub mod call_stack;
pub mod config;
pub mod regs;
use crate::bytecode::ops::Operations::*;
use crate::bytecode::ops::*;
use crate::bytecode::types::*;
use crate::engine::call_stack::FnCall;
use crate::HaltStatus;
use crate::RuntimeErrors;
use config::EngineConfig;
use regs::Registers;
use self::call_stack::CallStack;
pub struct Page {
pub data: [u8; 4096 * 2],
}
pub struct Engine {
pub index: usize,
program: Vec<u8>,
registers: Registers,
config: EngineConfig,
/// BUG: This DOES NOT account for overflowing
last_timer_count: u32,
timer_callback: Option<fn() -> u32>,
memory: Vec<Page>,
call_stack: CallStack,
}
impl Engine {
pub fn read_mem_addr(&mut self, address: u64) -> u8 {
// println!("{}", address);
255
}
}
impl Engine {
pub fn new(program: Vec<u8>) -> Self {
Self {
index: 0,
program,
registers: Registers::new(),
config: EngineConfig::default(),
last_timer_count: 0,
timer_callback: None,
memory: vec![],
call_stack: vec![],
}
}
pub fn dump(&self) {
println!("Registers");
println!(
"A {:02X} {:02X} {:02X} {:02X} {:02X} {:02X} {:02X} {:02X} {:02X} {:02X}",
self.registers.a0,
self.registers.a1,
self.registers.a2,
self.registers.a3,
self.registers.a4,
self.registers.a5,
self.registers.a6,
self.registers.a7,
self.registers.a8,
self.registers.a9,
);
println!(
"B {:02X} {:02X} {:02X} {:02X} {:02X} {:02X} {:02X} {:02X} {:02X} {:02X}",
self.registers.b0,
self.registers.b1,
self.registers.b2,
self.registers.b3,
self.registers.b4,
self.registers.b5,
self.registers.b6,
self.registers.b7,
self.registers.b8,
self.registers.b9,
);
println!(
"C {:02X} {:02X} {:02X} {:02X} {:02X} {:02X} {:02X} {:02X} {:02X} {:02X}",
self.registers.c0,
self.registers.c1,
self.registers.c2,
self.registers.c3,
self.registers.c4,
self.registers.c5,
self.registers.c6,
self.registers.c7,
self.registers.c8,
self.registers.c9,
);
println!(
"D0-D4 {:016X} {:016X} {:016X} {:016X} {:016X}
D5-D9 {:016X} {:016X} {:016X} {:016X} {:016X}",
self.registers.d0,
self.registers.d1,
self.registers.d2,
self.registers.d3,
self.registers.d4,
self.registers.d5,
self.registers.d6,
self.registers.d7,
self.registers.d8,
self.registers.d9,
);
println!(
"E0-E4 {:016X} {:016X} {:016X} {:016X} {:016X}
E5-E9 {:016X} {:016X} {:016X} {:016X} {:016X}",
self.registers.e0,
self.registers.e1,
self.registers.e2,
self.registers.e3,
self.registers.e4,
self.registers.e5,
self.registers.e6,
self.registers.e7,
self.registers.e8,
self.registers.e9,
);
println!(
"F0-F4 {:016X} {:016X} {:016X} {:016X} {:016X}
F5-F9 {:016X} {:016X} {:016X} {:016X} {:016X}",
self.registers.f0,
self.registers.f1,
self.registers.f2,
self.registers.f3,
self.registers.f4,
self.registers.f5,
self.registers.f6,
self.registers.f7,
self.registers.f8,
self.registers.f9,
);
}
pub fn run(&mut self) -> Result<HaltStatus, RuntimeErrors> {
use HaltStatus::*;
use RuntimeErrors::*;
loop {
// Break out of the loop
if self.index + 1 == self.program.len() {
break;
}
let op = (self.program[self.index], self.program[self.index + 1]);
// println!("OP {} INDEX {}", op.0, self.index);
match op {
(0, _) => {
println!("NO OP");
self.index += 1;
}
// Add a 8 bit num
(1, 1) => {
let lhs = self.program[self.index + 2];
// println!("LHS 8BIT {}", lhs);
let rhs = self.program[self.index + 3];
// println!("RHS 8BIT {}", rhs);
let ret = lhs + rhs;
let reg = self.program[self.index + 4];
match reg {
0xA0..=0xC9 => {
self.set_register_8(reg, ret);
}
0xD0..=0xF9 => {
panic!("Register oversized")
}
_ => {
panic!("Not a register.")
}
}
self.index += 4;
}
// Add a 64 bit num
(1, 2) => {
let mut lhs_array = [0; 8];
let mut rhs_array = [0; 8];
for (index, byte) in self.program[self.index + 2..self.index + 10]
.into_iter()
.enumerate()
{
lhs_array[index] = *byte;
}
let lhs = u64::from_be_bytes(lhs_array);
// println!("LHS 64BIT {}", lhs);
for (index, byte) in self.program[self.index + 10..self.index + 18]
.into_iter()
.enumerate()
{
rhs_array[index] = *byte;
}
let rhs = u64::from_be_bytes(rhs_array);
// println!("RHS 64BIT {}", rhs);
let ret = lhs + rhs;
let reg = self.program[self.index + 18];
// println!("Store {} in {:02X}", ret, reg);
match reg {
0xA0..=0xC9 => {
panic!("Register undersized")
}
0xD0..=0xF9 => {
self.set_register_64(reg, ret);
}
_ => {
panic!("Not a register.")
}
}
self.index += 19;
}
(2, 1) => {
let lhs = self.program[self.index + 2];
// println!("LHS 8BIT {}", lhs);
let rhs = self.program[self.index + 3];
// println!("RHS 8BIT {}", rhs);
let ret = lhs - rhs;
let reg = self.program[self.index + 4];
match reg {
0xA0..=0xC9 => {
self.set_register_8(reg, ret);
}
0xD0..=0xF9 => {
panic!("Register oversized")
}
_ => {
panic!("Not a register.")
}
}
self.index += 4;
}
(2, 2) => {
let mut lhs_array = [0; 8];
let mut rhs_array = [0; 8];
for (index, byte) in self.program[self.index + 2..self.index + 10]
.into_iter()
.enumerate()
{
lhs_array[index] = *byte;
}
let lhs = u64::from_be_bytes(lhs_array);
// println!("LHS 64BIT {}", lhs);
for (index, byte) in self.program[self.index + 10..self.index + 18]
.into_iter()
.enumerate()
{
rhs_array[index] = *byte;
}
let rhs = u64::from_be_bytes(rhs_array);
// println!("RHS 64BIT {}", rhs);
let ret = lhs - rhs;
let reg = self.program[self.index + 18];
// println!("Store {} in {:02X}", ret, reg);
match reg {
0xA0..=0xC9 => {
panic!("Register undersized")
}
0xD0..=0xF9 => {
self.set_register_64(reg, ret);
}
_ => {
panic!("Not a register.")
}
}
self.index += 19;
}
(2, 3) => {
// 8 bit
self.index += 4;
}
// TODO: Implement 64 bit register to register subtraction
(2, 4) => {
// 64 bit
self.index += 19;
}
// Read from address to register
(5, 0) => {
let mut addr_array = [0; 8];
for (index, byte) in self.program[self.index + 2..self.index + 10]
.into_iter()
.enumerate()
{
addr_array[index] = *byte;
}
let addr = u64::from_be_bytes(addr_array);
println!("addr {}", addr);
let ret = self.read_mem_addr(addr);
let reg = self.program[self.index + 10];
println!("reg {}", reg);
self.set_register_8(reg, ret);
self.index += 9;
}
(100, _) => {
if self.call_stack.len() > self.config.call_stack_depth {
panic!("Callstack {}", self.call_stack.len());
}
let mut addr_array = [0; 8];
for (index, byte) in self.program[self.index + 1..self.index + 9]
.into_iter()
.enumerate()
{
println!("byte {}", byte);
addr_array[index] = *byte;
}
let addr = usize::from_be_bytes(addr_array);
if addr > self.program.len() {
panic!("Invalid jump address {}", addr)
} else {
let call = FnCall { ret: self.index };
self.call_stack.push(call);
self.index = addr;
println!("Jumping to {}", addr);
self.dump();
// panic!();
}
}
_op_pair => {
// println!("OP Pair {}", op_pair.0);
self.index += 1;
}
}
// Finish step
if self.timer_callback.is_some() {
let ret = self.timer_callback.unwrap()();
if (ret - self.last_timer_count) >= self.config.quantum {
return Ok(Running);
}
}
}
Ok(Halted)
}
pub fn set_register_8(&mut self, register: u8, value: u8) {
match register {
0xA0 => self.registers.a0 = value,
0xA1 => self.registers.a1 = value,
0xA2 => self.registers.a2 = value,
0xA3 => self.registers.a3 = value,
0xA4 => self.registers.a4 = value,
0xA5 => self.registers.a5 = value,
0xA6 => self.registers.a6 = value,
0xA7 => self.registers.a7 = value,
0xA8 => self.registers.a8 = value,
0xA9 => self.registers.a9 = value,
//
0xB0 => self.registers.b0 = value,
0xB1 => self.registers.b1 = value,
0xB2 => self.registers.b2 = value,
0xB3 => self.registers.b3 = value,
0xB4 => self.registers.b4 = value,
0xB5 => self.registers.b5 = value,
0xB6 => self.registers.b6 = value,
0xB7 => self.registers.b7 = value,
0xB8 => self.registers.b8 = value,
0xB9 => self.registers.b9 = value,
//
0xC0 => self.registers.c0 = value,
0xC1 => self.registers.c1 = value,
0xC2 => self.registers.c2 = value,
0xC3 => self.registers.c3 = value,
0xC4 => self.registers.c4 = value,
0xC5 => self.registers.c5 = value,
0xC6 => self.registers.c6 = value,
0xC7 => self.registers.c7 = value,
0xC8 => self.registers.c8 = value,
0xC9 => self.registers.c9 = value,
_ => {
panic!("Unlikely you are here if everyone behaved.\nThis register is not 8 bit")
}
}
}
pub fn set_register_64(&mut self, register: u8, value: u64) {
match register {
0xD0 => self.registers.d0 = value,
0xD1 => self.registers.d1 = value,
0xD2 => self.registers.d2 = value,
0xD3 => self.registers.d3 = value,
0xD4 => self.registers.d4 = value,
0xD5 => self.registers.d5 = value,
0xD6 => self.registers.d6 = value,
0xD7 => self.registers.d7 = value,
0xD8 => self.registers.d8 = value,
0xD9 => self.registers.d9 = value,
//
0xE0 => self.registers.f0 = value,
0xE1 => self.registers.f1 = value,
0xE2 => self.registers.f2 = value,
0xE3 => self.registers.f3 = value,
0xE4 => self.registers.f4 = value,
0xE5 => self.registers.f5 = value,
0xE6 => self.registers.f6 = value,
0xE7 => self.registers.f7 = value,
0xE8 => self.registers.f8 = value,
0xE9 => self.registers.f9 = value,
//
0xF0 => self.registers.f0 = value,
0xF1 => self.registers.f1 = value,
0xF2 => self.registers.f2 = value,
0xF3 => self.registers.f3 = value,
0xF4 => self.registers.f4 = value,
0xF5 => self.registers.f5 = value,
0xF6 => self.registers.f6 = value,
0xF7 => self.registers.f7 = value,
0xF8 => self.registers.f8 = value,
0xF9 => self.registers.f9 = value,
_ => {
panic!("Unlikely you are here if everyone behaved.\nThis register is not 64 bit")
}
}
}
}