From fef23d0f93e83371f6b809b71de7a91e3117b7d4 Mon Sep 17 00:00:00 2001 From: Able Date: Sat, 22 Apr 2023 13:00:19 -0500 Subject: [PATCH] Update --- DESIGN_DOC.md | 8 ++ assets/example.asm | 4 + assets/example.bytes | 4 + rustfmt.toml | 3 + src/bytecode/ops.rs | 39 ++++++---- src/engine/call_stack.rs | 2 +- src/engine/mod.rs | 158 ++++++++++++++++++++++++++++++++++++--- src/lib.rs | 5 +- src/main.rs | 24 ++++-- 9 files changed, 209 insertions(+), 38 deletions(-) create mode 100644 assets/example.asm create mode 100644 assets/example.bytes create mode 100644 rustfmt.toml diff --git a/DESIGN_DOC.md b/DESIGN_DOC.md index 5a101893..eea8b58c 100644 --- a/DESIGN_DOC.md +++ b/DESIGN_DOC.md @@ -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` diff --git a/assets/example.asm b/assets/example.asm new file mode 100644 index 00000000..1f666ba6 --- /dev/null +++ b/assets/example.asm @@ -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 \ No newline at end of file diff --git a/assets/example.bytes b/assets/example.bytes new file mode 100644 index 00000000..3a9c6240 --- /dev/null +++ b/assets/example.bytes @@ -0,0 +1,4 @@ +load 10 A1 +load 0 A0 +add A0 1 +jump_less_than A0 A1 diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 00000000..3807d4c6 --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,3 @@ +hex_literal_case = "Upper" +imports_granularity = "One" +struct_field_align_threshold = 5 diff --git a/src/bytecode/ops.rs b/src/bytecode/ops.rs index c8a22f1d..510aae88 100644 --- a/src/bytecode/ops.rs +++ b/src/bytecode/ops.rs @@ -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, } diff --git a/src/engine/call_stack.rs b/src/engine/call_stack.rs index 00739a38..c69db8b0 100644 --- a/src/engine/call_stack.rs +++ b/src/engine/call_stack.rs @@ -1,4 +1,4 @@ pub type CallStack = Vec; pub struct FnCall { - ret: usize, + pub ret: usize, } diff --git a/src/engine/mod.rs b/src/engine/mod.rs index e1f330fa..861b0eb0 100644 --- a/src/engine/mod.rs +++ b/src/engine/mod.rs @@ -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, @@ -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) -> 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; } } diff --git a/src/lib.rs b/src/lib.rs index 52d5da53..f2aea92a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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 } diff --git a/src/main.rs b/src/main.rs index b116ffc8..3e3d6a01 100644 --- a/src/main.rs +++ b/src/main.rs @@ -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 = 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);