Fix add instruction

- Add debug instruction
pull/1/head
trivernis 5 years ago
parent d4bc8781d9
commit 22cc821697

@ -16,6 +16,7 @@ A virtual machine for controlling a wifi led strip.
| write (rgd, rgp) | writes the value in the data register to the address of the pointer register | 0x06 | | write (rgd, rgp) | writes the value in the data register to the address of the pointer register | 0x06 |
| label (rgl) | creates a label with rgd as the name | 0x07 | | label (rgl) | creates a label with rgd as the name | 0x07 |
| goto (rgl) | goes to the label with name rgd | 0x08 | | goto (rgl) | goes to the label with name rgd | 0x08 |
| debug (*) | prints out the state for debug information | 0x09 |
| add (rgd, rgi, rgo) | adds the value of rgi to the value of rgd and writes the result into rgo | 0x10 | | add (rgd, rgi, rgo) | adds the value of rgi to the value of rgd and writes the result into rgo | 0x10 |
| sub (rgd, rgi, rgo) | substracts rgi from rgd and writes the result into rgo | 0x11 | | sub (rgd, rgi, rgo) | substracts rgi from rgd and writes the result into rgo | 0x11 |
| mul (rgd, rgi, rgo) | multiplies rgd by rgi and writes the result to rgo | 0x12 | | mul (rgd, rgi, rgo) | multiplies rgd by rgi and writes the result to rgo | 0x12 |
@ -27,8 +28,8 @@ A virtual machine for controlling a wifi led strip.
| jl (rgd, rgi, rgl) | jumps to rgl if rgd < rgi | 0x21 | | jl (rgd, rgi, rgl) | jumps to rgl if rgd < rgi | 0x21 |
| je (rgd, rgi, rgl) | jumps to rgl if rgd == rgi | 0x22 | | je (rgd, rgi, rgl) | jumps to rgl if rgd == rgi | 0x22 |
| pause (rgd) | pauses for rgd milliseconds | 0xF0 | | pause (rgd) | pauses for rgd milliseconds | 0xF0 |
| cmd (rgd) | executes the command in rgd | 0xF1 | | cmd (rgd) | executes the command in rgd | 0xF1 |
| send (rcr, rcg, rcb) | sends the values stored in the color registers to the strip | 0xF2 | send (rcr, rcg, rcb)| sends the values stored in the color registers to the strip | 0xF2 |
### Registers ### Registers
@ -50,4 +51,5 @@ A virtual machine for controlling a wifi led strip.
- the rgp register stores a pointer to "memory" space - the rgp register stores a pointer to "memory" space
- the rgi register stores the input for operations that require two input values - the rgi register stores the input for operations that require two input values
- the rgo register stores the result of operations - the rgo register stores the result of operations
- the rgl register stores as label name that can be jumped to - the rgl register stores as label name that can be jumped to
- comments start with #

@ -1,8 +1,8 @@
use ledstrip_vm::registers::get_register_code_by_name; use ledstrip_vm::registers::get_register_code_by_name;
use ledstrip_vm::tokens::{ use ledstrip_vm::tokens::{
AddToken, ClearToken, CmdToken, CopyToken, DivToken, ExitToken, GotoToken, JeToken, JgToken, AddToken, ClearToken, CmdToken, CopyToken, DebugToken, DivToken, ExitToken, GotoToken, JeToken,
JlToken, LabelToken, LoadToken, LshToken, ModToken, MulToken, PauseToken, RshToken, SendToken, JgToken, JlToken, LabelToken, LoadToken, LshToken, ModToken, MulToken, PauseToken, RshToken,
SetToken, SubToken, Token, WriteToken, SendToken, SetToken, SubToken, Token, WriteToken,
}; };
use std::fs::{read_to_string, File}; use std::fs::{read_to_string, File};
use std::io; use std::io;
@ -38,12 +38,14 @@ fn main() -> io::Result<()> {
line_number += 1; line_number += 1;
if let Some(token) = get_token(line) { if let Some(token) = get_token(line) {
Some(token.to_bytecode()) Some(token.to_bytecode())
} else { } else if line.replace("\\s", "").len() > 0 && !line.starts_with("#") {
println!( println!(
"Failed to parse instruction '{}' \n-> {}:{}", "Failed to parse instruction '{}' \n-> {}:{}",
line, &input_file_name, line_number line, &input_file_name, line_number
); );
None None
} else {
None
} }
}) })
.for_each(|code| { .for_each(|code| {
@ -80,6 +82,7 @@ fn get_token(line: &str) -> Option<Box<dyn Token>> {
"write" => some_box!(WriteToken), "write" => some_box!(WriteToken),
"label" => some_box!(LabelToken), "label" => some_box!(LabelToken),
"goto" => some_box!(GotoToken), "goto" => some_box!(GotoToken),
"debug" => some_box!(DebugToken),
"add" => some_box!(AddToken), "add" => some_box!(AddToken),
"sub" => some_box!(SubToken), "sub" => some_box!(SubToken),
"mul" => some_box!(MulToken), "mul" => some_box!(MulToken),

@ -1,6 +1,7 @@
use ledstrip_vm::runtime::Runtime; use ledstrip_vm::runtime::Runtime;
use std::fs::read; use std::fs::read;
use std::io; use std::io;
use std::time::Instant;
use structopt::StructOpt; use structopt::StructOpt;
#[derive(StructOpt, Debug)] #[derive(StructOpt, Debug)]
@ -20,11 +21,22 @@ fn main() -> io::Result<()> {
let bytecode = read(opts.input_file)?; let bytecode = read(opts.input_file)?;
let mut runtime = Runtime::new(&opts.ip, opts.port); let mut runtime = Runtime::new(&opts.ip, opts.port);
let start = Instant::now();
runtime.parse_bytecode(bytecode); runtime.parse_bytecode(bytecode);
println!("Parsing took {:?}\n", start.elapsed());
let start = Instant::now();
match runtime.run() { match runtime.run() {
Ok(code) => println!("Runtime exited with code {}", code), Ok(code) => println!(
Err(e) => println!("Runtime exited with error {:?}", e), "Runtime exited with code {} after {:?}",
code,
start.elapsed()
),
Err(e) => println!(
"Runtime exited with error {:?} after {:?}",
e,
start.elapsed()
),
} }
Ok(()) Ok(())

@ -3,11 +3,11 @@ use crate::registers::{
Rcb, Rcg, Rcr, Rcs, Register, Rgd, Rgi, Rgl, Rgo, Rgp, RCB, RCG, RCR, RGD, RGI, RGL, RGO, RGP, Rcb, Rcg, Rcr, Rcs, Register, Rgd, Rgi, Rgl, Rgo, Rgp, RCB, RCG, RCR, RGD, RGI, RGL, RGO, RGP,
}; };
use crate::tokens::{ use crate::tokens::{
AddToken, ClearToken, CmdToken, CopyToken, DivToken, ExitToken, FromBytecode, GotoToken, AddToken, ClearToken, CmdToken, CopyToken, DebugToken, DivToken, ExitToken, FromBytecode,
JeToken, JgToken, JlToken, LabelToken, LoadToken, LshToken, ModToken, MulToken, PauseToken, GotoToken, JeToken, JgToken, JlToken, LabelToken, LoadToken, LshToken, ModToken, MulToken,
RshToken, SendToken, SetToken, SubToken, Token, WriteToken, T_ADD, T_CLEAR, T_CMD, T_COPY, PauseToken, RshToken, SendToken, SetToken, SubToken, Token, WriteToken, T_ADD, T_CLEAR, T_CMD,
T_DIV, T_EXIT, T_GOTO, T_JE, T_JG, T_JL, T_LABEL, T_LOAD, T_LSH, T_MOD, T_MUL, T_PAUSE, T_RSH, T_COPY, T_DEBUG, T_DIV, T_EXIT, T_GOTO, T_JE, T_JG, T_JL, T_LABEL, T_LOAD, T_LSH, T_MOD, T_MUL,
T_SEND, T_SET, T_SUB, T_WRITE, T_PAUSE, T_RSH, T_SEND, T_SET, T_SUB, T_WRITE,
}; };
use std::cell::RefCell; use std::cell::RefCell;
use std::collections::HashMap; use std::collections::HashMap;
@ -62,56 +62,46 @@ impl Runtime {
/// that can be executed /// that can be executed
pub fn parse_bytecode(&mut self, bytecode: Vec<u8>) { pub fn parse_bytecode(&mut self, bytecode: Vec<u8>) {
let mut code_iter = bytecode.iter(); let mut code_iter = bytecode.iter();
let mut text = self.text.borrow_mut();
while let Some(instruction) = code_iter.next() { while let Some(instruction) = code_iter.next() {
match *instruction { match *instruction {
T_EXIT => self T_EXIT => text.push(Box::new(ExitToken::from_bytecode(&[
.text instruction,
.borrow_mut() code_iter.next().unwrap(),
.push(Box::new(ExitToken::from_bytecode(&[ ]))),
instruction, T_SET => text.push(Box::new(SetToken::from_bytecode(&[
code_iter.next().unwrap(), instruction,
]))), code_iter.next().unwrap(),
T_SET => self code_iter.next().unwrap(),
.text ]))),
.borrow_mut() T_COPY => text.push(Box::new(CopyToken::from_bytecode(&[
.push(Box::new(SetToken::from_bytecode(&[ instruction,
instruction, code_iter.next().unwrap(),
code_iter.next().unwrap(), code_iter.next().unwrap(),
code_iter.next().unwrap(), ]))),
]))), T_LOAD => text.push(Box::new(LoadToken)),
T_COPY => self T_CLEAR => text.push(Box::new(ClearToken::from_bytecode(&[
.text instruction,
.borrow_mut() code_iter.next().unwrap(),
.push(Box::new(CopyToken::from_bytecode(&[ ]))),
instruction, T_WRITE => text.push(Box::new(WriteToken)),
code_iter.next().unwrap(), T_LABEL => text.push(Box::new(LabelToken)),
code_iter.next().unwrap(), T_GOTO => text.push(Box::new(GotoToken)),
]))), T_DEBUG => text.push(Box::new(DebugToken)),
T_LOAD => self.text.borrow_mut().push(Box::new(LoadToken)), T_ADD => text.push(Box::new(AddToken)),
T_CLEAR => self T_SUB => text.push(Box::new(SubToken)),
.text T_MUL => text.push(Box::new(MulToken)),
.borrow_mut() T_DIV => text.push(Box::new(DivToken)),
.push(Box::new(ClearToken::from_bytecode(&[ T_MOD => text.push(Box::new(ModToken)),
instruction, T_LSH => text.push(Box::new(LshToken)),
code_iter.next().unwrap(), T_RSH => text.push(Box::new(RshToken)),
]))), T_JG => text.push(Box::new(JgToken)),
T_WRITE => self.text.borrow_mut().push(Box::new(WriteToken)), T_JL => text.push(Box::new(JlToken)),
T_LABEL => self.text.borrow_mut().push(Box::new(LabelToken)), T_JE => text.push(Box::new(JeToken)),
T_GOTO => self.text.borrow_mut().push(Box::new(GotoToken)), T_PAUSE => text.push(Box::new(PauseToken)),
T_ADD => self.text.borrow_mut().push(Box::new(AddToken)), T_CMD => text.push(Box::new(CmdToken)),
T_SUB => self.text.borrow_mut().push(Box::new(SubToken)), T_SEND => text.push(Box::new(SendToken)),
T_MUL => self.text.borrow_mut().push(Box::new(MulToken)),
T_DIV => self.text.borrow_mut().push(Box::new(DivToken)),
T_MOD => self.text.borrow_mut().push(Box::new(ModToken)),
T_LSH => self.text.borrow_mut().push(Box::new(LshToken)),
T_RSH => self.text.borrow_mut().push(Box::new(RshToken)),
T_JG => self.text.borrow_mut().push(Box::new(JgToken)),
T_JL => self.text.borrow_mut().push(Box::new(JlToken)),
T_JE => self.text.borrow_mut().push(Box::new(JeToken)),
T_PAUSE => self.text.borrow_mut().push(Box::new(PauseToken)),
T_CMD => self.text.borrow_mut().push(Box::new(CmdToken)),
T_SEND => self.text.borrow_mut().push(Box::new(SendToken)),
_ => panic!("unknown instruction {}", instruction), _ => panic!("unknown instruction {}", instruction),
}; };
} }

@ -13,6 +13,7 @@ pub const T_CLEAR: u8 = 0x05;
pub const T_WRITE: u8 = 0x06; pub const T_WRITE: u8 = 0x06;
pub const T_LABEL: u8 = 0x07; pub const T_LABEL: u8 = 0x07;
pub const T_GOTO: u8 = 0x08; pub const T_GOTO: u8 = 0x08;
pub const T_DEBUG: u8 = 0x09;
pub const T_ADD: u8 = 0x10; pub const T_ADD: u8 = 0x10;
pub const T_SUB: u8 = 0x11; pub const T_SUB: u8 = 0x11;
pub const T_MUL: u8 = 0x12; pub const T_MUL: u8 = 0x12;
@ -137,13 +138,18 @@ impl Token for CopyToken {
value = rg.get(); value = rg.get();
} else if self.register_1 == RCS { } else if self.register_1 == RCS {
value = runtime.rcs.get() as u32; value = runtime.rcs.get() as u32;
} else {
panic!("unknown register {}", self.register_1);
} }
if let Some(mut rg) = runtime.get_1byte_register(self.register_2) { if let Some(mut rg) = runtime.get_1byte_register(self.register_2) {
rg.set(value as u8); rg.set(value as u8);
} else if let Some(mut rg) = runtime.get_4byte_register(self.register_2) { } else if let Some(mut rg) = runtime.get_4byte_register(self.register_2) {
rg.set(value); rg.set(value);
} else if self.register_2 == RCS { } else if self.register_2 == RCS {
runtime.rcs.set(value == 0); runtime.rcs.set(value == 0);
} else {
panic!("unknown register {}", self.register_2);
} }
Ok(()) Ok(())
@ -269,6 +275,33 @@ impl Token for GotoToken {
} }
} }
#[derive(Debug, Clone)]
pub struct DebugToken;
impl Token for DebugToken {
fn to_bytecode(&self) -> Vec<u8> {
vec![T_DEBUG]
}
fn invoke(&self, runtime: &mut Runtime) -> io::Result<()> {
println!("--- Registers --");
println!("rcs: {}", runtime.rcs.get());
println!("rcr: {}", runtime.rcr.get());
println!("rcg: {}", runtime.rcg.get());
println!("rcb: {}", runtime.rcb.get());
println!("rgd: {}", runtime.rgd.get());
println!("rgp: {}", runtime.rgp.get());
println!("rgi: {}", runtime.rgi.get());
println!("rgo: {}", runtime.rgo.get());
println!("rgl: {}", runtime.rgl.get());
println!("\n--- Runtime ---");
println!("Memory: {:?}", runtime.memory);
println!();
Ok(())
}
}
impl FromBytecode for GotoToken { impl FromBytecode for GotoToken {
fn from_bytecode(_: &[&u8]) -> Self { fn from_bytecode(_: &[&u8]) -> Self {
Self Self
@ -284,7 +317,7 @@ impl Token for AddToken {
} }
fn invoke(&self, runtime: &mut Runtime) -> io::Result<()> { fn invoke(&self, runtime: &mut Runtime) -> io::Result<()> {
runtime.rgo.set(runtime.rgo.get() + runtime.rgi.get()); runtime.rgo.set(runtime.rgd.get() + runtime.rgi.get());
Ok(()) Ok(())
} }

Loading…
Cancel
Save