forked from AbleOS/holey-bytes
Update
This commit is contained in:
parent
28958d0810
commit
fef23d0f93
|
@ -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
|
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.
|
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
|
instructions
|
||||||
### NOP
|
### NOP
|
||||||
`0`
|
`0`
|
||||||
|
|
4
assets/example.asm
Normal file
4
assets/example.asm
Normal 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
4
assets/example.bytes
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
load 10 A1
|
||||||
|
load 0 A0
|
||||||
|
add A0 1
|
||||||
|
jump_less_than A0 A1
|
3
rustfmt.toml
Normal file
3
rustfmt.toml
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
hex_literal_case = "Upper"
|
||||||
|
imports_granularity = "One"
|
||||||
|
struct_field_align_threshold = 5
|
|
@ -6,27 +6,38 @@ pub enum Operations {
|
||||||
MUL = 3,
|
MUL = 3,
|
||||||
DIV = 4,
|
DIV = 4,
|
||||||
|
|
||||||
// READs a register/memory address/constant into a register
|
// LOADs a memory address/constant into a register
|
||||||
READ = 5,
|
LOAD = 5,
|
||||||
// WRITEs a register/memory address/constant into a memory address
|
// STOREs a register/constant into a memory address
|
||||||
WRITE = 6,
|
STORE = 6,
|
||||||
|
|
||||||
JUMP = 100,
|
JUMP = 100,
|
||||||
JumpEq = 101,
|
JumpCond = 101,
|
||||||
JumpNeq = 102,
|
|
||||||
RET = 103,
|
RET = 103,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum MathTypes {
|
pub enum SubTypes {
|
||||||
EightBit = 1,
|
EightBit = 1,
|
||||||
SixtyFourBit = 2,
|
SixtyFourBit = 2,
|
||||||
|
Register8 = 3,
|
||||||
|
Register64 = 4,
|
||||||
|
}
|
||||||
|
pub enum MathOpSubTypes {
|
||||||
|
Unsigned = 0,
|
||||||
|
Signed = 1,
|
||||||
|
FloatingPoint = 2,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum RWTypes {
|
pub enum RWSubTypes {
|
||||||
RegisterToAddress = 0,
|
AddrToReg = 0,
|
||||||
RegisterToRegister = 1,
|
RegToAddr,
|
||||||
ConstantToAddress = 2,
|
ConstToReg,
|
||||||
ConstantToRegister = 3,
|
ConstToAddr,
|
||||||
AddressToRegister = 4,
|
}
|
||||||
AddressToAddress = 5,
|
|
||||||
|
pub enum JumpConditionals {
|
||||||
|
Equal = 0,
|
||||||
|
NotEqual = 1,
|
||||||
|
LessThan = 2,
|
||||||
|
GreaterThan = 3,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
pub type CallStack = Vec<FnCall>;
|
pub type CallStack = Vec<FnCall>;
|
||||||
pub struct FnCall {
|
pub struct FnCall {
|
||||||
ret: usize,
|
pub ret: usize,
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,17 +2,22 @@ pub mod call_stack;
|
||||||
pub mod config;
|
pub mod config;
|
||||||
pub mod regs;
|
pub mod regs;
|
||||||
|
|
||||||
|
use crate::bytecode::ops::Operations::*;
|
||||||
use crate::bytecode::ops::*;
|
use crate::bytecode::ops::*;
|
||||||
use crate::bytecode::types::*;
|
use crate::bytecode::types::*;
|
||||||
|
|
||||||
|
use crate::engine::call_stack::FnCall;
|
||||||
use crate::HaltStatus;
|
use crate::HaltStatus;
|
||||||
use crate::Page;
|
|
||||||
use crate::RuntimeErrors;
|
use crate::RuntimeErrors;
|
||||||
use config::EngineConfig;
|
use config::EngineConfig;
|
||||||
use regs::Registers;
|
use regs::Registers;
|
||||||
|
|
||||||
use self::call_stack::CallStack;
|
use self::call_stack::CallStack;
|
||||||
|
|
||||||
|
pub struct Page {
|
||||||
|
pub data: [u8; 4096 * 2],
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Engine {
|
pub struct Engine {
|
||||||
pub index: usize,
|
pub index: usize,
|
||||||
program: Vec<u8>,
|
program: Vec<u8>,
|
||||||
|
@ -26,6 +31,13 @@ pub struct Engine {
|
||||||
call_stack: CallStack,
|
call_stack: CallStack,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Engine {
|
||||||
|
pub fn read_mem_addr(&mut self, address: u64) -> u8 {
|
||||||
|
// println!("{}", address);
|
||||||
|
255
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Engine {
|
impl Engine {
|
||||||
pub fn new(program: Vec<u8>) -> Self {
|
pub fn new(program: Vec<u8>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
@ -129,11 +141,11 @@ F5-F9 {:016X} {:016X} {:016X} {:016X} {:016X}",
|
||||||
use RuntimeErrors::*;
|
use RuntimeErrors::*;
|
||||||
loop {
|
loop {
|
||||||
// Break out of the loop
|
// Break out of the loop
|
||||||
if self.index == self.program.len() {
|
if self.index + 1 == self.program.len() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
let op = (self.program[self.index], self.program[self.index + 1]);
|
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 {
|
match op {
|
||||||
(0, _) => {
|
(0, _) => {
|
||||||
println!("NO OP");
|
println!("NO OP");
|
||||||
|
@ -142,9 +154,9 @@ F5-F9 {:016X} {:016X} {:016X} {:016X} {:016X}",
|
||||||
// Add a 8 bit num
|
// Add a 8 bit num
|
||||||
(1, 1) => {
|
(1, 1) => {
|
||||||
let lhs = self.program[self.index + 2];
|
let lhs = self.program[self.index + 2];
|
||||||
println!("LHS 8BIT {}", lhs);
|
// println!("LHS 8BIT {}", lhs);
|
||||||
let rhs = self.program[self.index + 3];
|
let rhs = self.program[self.index + 3];
|
||||||
println!("RHS 8BIT {}", rhs);
|
// println!("RHS 8BIT {}", rhs);
|
||||||
|
|
||||||
let ret = lhs + rhs;
|
let ret = lhs + rhs;
|
||||||
let reg = self.program[self.index + 4];
|
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
|
// Add a 64 bit num
|
||||||
(1, 2) => {
|
(1, 2) => {
|
||||||
|
@ -175,7 +187,7 @@ F5-F9 {:016X} {:016X} {:016X} {:016X} {:016X}",
|
||||||
lhs_array[index] = *byte;
|
lhs_array[index] = *byte;
|
||||||
}
|
}
|
||||||
let lhs = u64::from_be_bytes(lhs_array);
|
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]
|
for (index, byte) in self.program[self.index + 10..self.index + 18]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
@ -186,12 +198,12 @@ F5-F9 {:016X} {:016X} {:016X} {:016X} {:016X}",
|
||||||
|
|
||||||
let rhs = u64::from_be_bytes(rhs_array);
|
let rhs = u64::from_be_bytes(rhs_array);
|
||||||
|
|
||||||
println!("RHS 64BIT {}", rhs);
|
// println!("RHS 64BIT {}", rhs);
|
||||||
|
|
||||||
let ret = lhs + rhs;
|
let ret = lhs + rhs;
|
||||||
|
|
||||||
let reg = self.program[self.index + 18];
|
let reg = self.program[self.index + 18];
|
||||||
println!("Store {} in {:02X}", ret, reg);
|
// println!("Store {} in {:02X}", ret, reg);
|
||||||
|
|
||||||
match reg {
|
match reg {
|
||||||
0xA0..=0xC9 => {
|
0xA0..=0xC9 => {
|
||||||
|
@ -207,8 +219,132 @@ F5-F9 {:016X} {:016X} {:016X} {:016X} {:016X}",
|
||||||
|
|
||||||
self.index += 19;
|
self.index += 19;
|
||||||
}
|
}
|
||||||
op_pair => {
|
(2, 1) => {
|
||||||
println!("OP Pair {}", op_pair.0);
|
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;
|
self.index += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,10 @@
|
||||||
pub mod bytecode;
|
pub mod bytecode;
|
||||||
pub mod engine;
|
pub mod engine;
|
||||||
|
|
||||||
use bytecode::ops::*;
|
use bytecode::ops::*;
|
||||||
use bytecode::types::{CONST_F64, CONST_U8};
|
use bytecode::types::{CONST_F64, CONST_U8};
|
||||||
use engine::Engine;
|
use engine::Engine;
|
||||||
|
|
||||||
pub struct Page {
|
|
||||||
pub data: [u8; 4096 * 2],
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn time() -> u32 {
|
pub fn time() -> u32 {
|
||||||
9
|
9
|
||||||
}
|
}
|
||||||
|
|
24
src/main.rs
24
src/main.rs
|
@ -1,21 +1,29 @@
|
||||||
use holey_bytes::bytecode::ops::Operations::*;
|
use holey_bytes::{
|
||||||
use holey_bytes::bytecode::types::CONST_U64;
|
bytecode::{
|
||||||
use holey_bytes::RuntimeErrors;
|
ops::{Operations::*, RWSubTypes, RWSubTypes::*, SubTypes::*},
|
||||||
use holey_bytes::{bytecode::types::CONST_U8, engine::Engine};
|
types::*,
|
||||||
|
},
|
||||||
|
engine::Engine,
|
||||||
|
RuntimeErrors,
|
||||||
|
};
|
||||||
|
|
||||||
fn main() -> Result<(), RuntimeErrors> {
|
fn main() -> Result<(), RuntimeErrors> {
|
||||||
use holey_bytes::bytecode::ops::MathTypes::*;
|
|
||||||
#[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,
|
||||||
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,
|
||||||
ADD as u8,
|
ADD as u8,
|
||||||
SixtyFourBit as u8,
|
SixtyFourBit as u8,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
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);
|
let mut eng = Engine::new(prog);
|
||||||
// eng.timer_callback = Some(time);
|
// eng.timer_callback = Some(time);
|
||||||
|
|
Loading…
Reference in a new issue