This commit is contained in:
Able 2023-04-22 13:00:19 -05:00
parent 28958d0810
commit fef23d0f93
9 changed files with 209 additions and 38 deletions

View file

@ -5,6 +5,14 @@ this leaves us with an amount of registers that should be defined
I'd like to use a letter and a number to represent registers
like `a0` or `d0` the first of which would be reserved for 8 bit numbers and the later of which 64 bit.
holeybytes will be a load-store machine
instructions
### NOP
`0`

4
assets/example.asm Normal file
View file

@ -0,0 +1,4 @@
load 0 a0 ;; 05 00 A0
load 10 a1 ;; 05 10 A1
add a0 1 a0 ;; 01 A0 01 A0
jump_neq a0 a1 0 ;; a1 A0 A1 0

4
assets/example.bytes Normal file
View file

@ -0,0 +1,4 @@
load 10 A1
load 0 A0
add A0 1
jump_less_than A0 A1

3
rustfmt.toml Normal file
View file

@ -0,0 +1,3 @@
hex_literal_case = "Upper"
imports_granularity = "One"
struct_field_align_threshold = 5

View file

@ -6,27 +6,38 @@ pub enum Operations {
MUL = 3,
DIV = 4,
// READs a register/memory address/constant into a register
READ = 5,
// WRITEs a register/memory address/constant into a memory address
WRITE = 6,
// LOADs a memory address/constant into a register
LOAD = 5,
// STOREs a register/constant into a memory address
STORE = 6,
JUMP = 100,
JumpEq = 101,
JumpNeq = 102,
JumpCond = 101,
RET = 103,
}
pub enum MathTypes {
pub enum SubTypes {
EightBit = 1,
SixtyFourBit = 2,
Register8 = 3,
Register64 = 4,
}
pub enum MathOpSubTypes {
Unsigned = 0,
Signed = 1,
FloatingPoint = 2,
}
pub enum RWTypes {
RegisterToAddress = 0,
RegisterToRegister = 1,
ConstantToAddress = 2,
ConstantToRegister = 3,
AddressToRegister = 4,
AddressToAddress = 5,
pub enum RWSubTypes {
AddrToReg = 0,
RegToAddr,
ConstToReg,
ConstToAddr,
}
pub enum JumpConditionals {
Equal = 0,
NotEqual = 1,
LessThan = 2,
GreaterThan = 3,
}

View file

@ -1,4 +1,4 @@
pub type CallStack = Vec<FnCall>;
pub struct FnCall {
ret: usize,
pub ret: usize,
}

View file

@ -2,17 +2,22 @@ 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::Page;
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>,
@ -26,6 +31,13 @@ pub struct Engine {
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 {
@ -129,11 +141,11 @@ F5-F9 {:016X} {:016X} {:016X} {:016X} {:016X}",
use RuntimeErrors::*;
loop {
// Break out of the loop
if self.index == self.program.len() {
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);
// println!("OP {} INDEX {}", op.0, self.index);
match op {
(0, _) => {
println!("NO OP");
@ -142,9 +154,9 @@ F5-F9 {:016X} {:016X} {:016X} {:016X} {:016X}",
// Add a 8 bit num
(1, 1) => {
let lhs = self.program[self.index + 2];
println!("LHS 8BIT {}", lhs);
// println!("LHS 8BIT {}", lhs);
let rhs = self.program[self.index + 3];
println!("RHS 8BIT {}", rhs);
// println!("RHS 8BIT {}", rhs);
let ret = lhs + rhs;
let reg = self.program[self.index + 4];
@ -161,7 +173,7 @@ F5-F9 {:016X} {:016X} {:016X} {:016X} {:016X}",
}
}
self.index += 5;
self.index += 4;
}
// Add a 64 bit num
(1, 2) => {
@ -175,7 +187,7 @@ F5-F9 {:016X} {:016X} {:016X} {:016X} {:016X}",
lhs_array[index] = *byte;
}
let lhs = u64::from_be_bytes(lhs_array);
println!("LHS 64BIT {}", lhs);
// println!("LHS 64BIT {}", lhs);
for (index, byte) in self.program[self.index + 10..self.index + 18]
.into_iter()
@ -186,12 +198,12 @@ F5-F9 {:016X} {:016X} {:016X} {:016X} {:016X}",
let rhs = u64::from_be_bytes(rhs_array);
println!("RHS 64BIT {}", rhs);
// println!("RHS 64BIT {}", rhs);
let ret = lhs + rhs;
let reg = self.program[self.index + 18];
println!("Store {} in {:02X}", ret, reg);
// println!("Store {} in {:02X}", ret, reg);
match reg {
0xA0..=0xC9 => {
@ -207,8 +219,132 @@ F5-F9 {:016X} {:016X} {:016X} {:016X} {:016X}",
self.index += 19;
}
op_pair => {
println!("OP Pair {}", op_pair.0);
(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;
}
}

View file

@ -1,13 +1,10 @@
pub mod bytecode;
pub mod engine;
use bytecode::ops::*;
use bytecode::types::{CONST_F64, CONST_U8};
use engine::Engine;
pub struct Page {
pub data: [u8; 4096 * 2],
}
pub fn time() -> u32 {
9
}

View file

@ -1,21 +1,29 @@
use holey_bytes::bytecode::ops::Operations::*;
use holey_bytes::bytecode::types::CONST_U64;
use holey_bytes::RuntimeErrors;
use holey_bytes::{bytecode::types::CONST_U8, engine::Engine};
use holey_bytes::{
bytecode::{
ops::{Operations::*, RWSubTypes, RWSubTypes::*, SubTypes::*},
types::*,
},
engine::Engine,
RuntimeErrors,
};
fn main() -> Result<(), RuntimeErrors> {
use holey_bytes::bytecode::ops::MathTypes::*;
#[rustfmt::skip]
let prog: Vec<u8> = vec![
NOP as u8, NOP as u8,
// NOP as u8, NOP as u8,
ADD as u8, EightBit as u8, 100, 20, 0xA7,
ADD as u8,
EightBit as u8, 1, 0, 0xB0,
ADD as u8,
SixtyFourBit as u8,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 2, 0xD0
0, 0, 0, 0, 0, 0, 0, 2, 0xD0,
SUB as u8, EightBit as u8, 255, 0, 0xA7,
ADD as u8, Register8 as u8, 0xA7, 0xB0, 0xA7,
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,
];
let mut eng = Engine::new(prog);
// eng.timer_callback = Some(time);