Fix add instruction

- Add debug instruction
pull/1/head
trivernis 4 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 |
| label (rgl) | creates a label with rgd as the name | 0x07 |
| 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 |
| 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 |
@ -27,8 +28,8 @@ A virtual machine for controlling a wifi led strip.
| jl (rgd, rgi, rgl) | jumps to rgl if rgd < rgi | 0x21 |
| je (rgd, rgi, rgl) | jumps to rgl if rgd == rgi | 0x22 |
| pause (rgd) | pauses for rgd milliseconds | 0xF0 |
| cmd (rgd) | executes the command in rgd | 0xF1 |
| send (rcr, rcg, rcb) | sends the values stored in the color registers to the strip | 0xF2
| cmd (rgd) | executes the command in rgd | 0xF1 |
| send (rcr, rcg, rcb)| sends the values stored in the color registers to the strip | 0xF2 |
### Registers
@ -50,4 +51,5 @@ A virtual machine for controlling a wifi led strip.
- the rgp register stores a pointer to "memory" space
- the rgi register stores the input for operations that require two input values
- 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::tokens::{
AddToken, ClearToken, CmdToken, CopyToken, DivToken, ExitToken, GotoToken, JeToken, JgToken,
JlToken, LabelToken, LoadToken, LshToken, ModToken, MulToken, PauseToken, RshToken, SendToken,
SetToken, SubToken, Token, WriteToken,
AddToken, ClearToken, CmdToken, CopyToken, DebugToken, DivToken, ExitToken, GotoToken, JeToken,
JgToken, JlToken, LabelToken, LoadToken, LshToken, ModToken, MulToken, PauseToken, RshToken,
SendToken, SetToken, SubToken, Token, WriteToken,
};
use std::fs::{read_to_string, File};
use std::io;
@ -38,12 +38,14 @@ fn main() -> io::Result<()> {
line_number += 1;
if let Some(token) = get_token(line) {
Some(token.to_bytecode())
} else {
} else if line.replace("\\s", "").len() > 0 && !line.starts_with("#") {
println!(
"Failed to parse instruction '{}' \n-> {}:{}",
line, &input_file_name, line_number
);
None
} else {
None
}
})
.for_each(|code| {
@ -80,6 +82,7 @@ fn get_token(line: &str) -> Option<Box<dyn Token>> {
"write" => some_box!(WriteToken),
"label" => some_box!(LabelToken),
"goto" => some_box!(GotoToken),
"debug" => some_box!(DebugToken),
"add" => some_box!(AddToken),
"sub" => some_box!(SubToken),
"mul" => some_box!(MulToken),

@ -1,6 +1,7 @@
use ledstrip_vm::runtime::Runtime;
use std::fs::read;
use std::io;
use std::time::Instant;
use structopt::StructOpt;
#[derive(StructOpt, Debug)]
@ -20,11 +21,22 @@ fn main() -> io::Result<()> {
let bytecode = read(opts.input_file)?;
let mut runtime = Runtime::new(&opts.ip, opts.port);
let start = Instant::now();
runtime.parse_bytecode(bytecode);
println!("Parsing took {:?}\n", start.elapsed());
let start = Instant::now();
match runtime.run() {
Ok(code) => println!("Runtime exited with code {}", code),
Err(e) => println!("Runtime exited with error {:?}", e),
Ok(code) => println!(
"Runtime exited with code {} after {:?}",
code,
start.elapsed()
),
Err(e) => println!(
"Runtime exited with error {:?} after {:?}",
e,
start.elapsed()
),
}
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,
};
use crate::tokens::{
AddToken, ClearToken, CmdToken, CopyToken, DivToken, ExitToken, FromBytecode, GotoToken,
JeToken, JgToken, JlToken, LabelToken, LoadToken, LshToken, ModToken, MulToken, PauseToken,
RshToken, SendToken, SetToken, SubToken, Token, WriteToken, T_ADD, T_CLEAR, T_CMD, T_COPY,
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_SEND, T_SET, T_SUB, T_WRITE,
AddToken, ClearToken, CmdToken, CopyToken, DebugToken, DivToken, ExitToken, FromBytecode,
GotoToken, JeToken, JgToken, JlToken, LabelToken, LoadToken, LshToken, ModToken, MulToken,
PauseToken, RshToken, SendToken, SetToken, SubToken, Token, WriteToken, T_ADD, T_CLEAR, T_CMD,
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_PAUSE, T_RSH, T_SEND, T_SET, T_SUB, T_WRITE,
};
use std::cell::RefCell;
use std::collections::HashMap;
@ -62,56 +62,46 @@ impl Runtime {
/// that can be executed
pub fn parse_bytecode(&mut self, bytecode: Vec<u8>) {
let mut code_iter = bytecode.iter();
let mut text = self.text.borrow_mut();
while let Some(instruction) = code_iter.next() {
match *instruction {
T_EXIT => self
.text
.borrow_mut()
.push(Box::new(ExitToken::from_bytecode(&[
instruction,
code_iter.next().unwrap(),
]))),
T_SET => self
.text
.borrow_mut()
.push(Box::new(SetToken::from_bytecode(&[
instruction,
code_iter.next().unwrap(),
code_iter.next().unwrap(),
]))),
T_COPY => self
.text
.borrow_mut()
.push(Box::new(CopyToken::from_bytecode(&[
instruction,
code_iter.next().unwrap(),
code_iter.next().unwrap(),
]))),
T_LOAD => self.text.borrow_mut().push(Box::new(LoadToken)),
T_CLEAR => self
.text
.borrow_mut()
.push(Box::new(ClearToken::from_bytecode(&[
instruction,
code_iter.next().unwrap(),
]))),
T_WRITE => self.text.borrow_mut().push(Box::new(WriteToken)),
T_LABEL => self.text.borrow_mut().push(Box::new(LabelToken)),
T_GOTO => self.text.borrow_mut().push(Box::new(GotoToken)),
T_ADD => self.text.borrow_mut().push(Box::new(AddToken)),
T_SUB => self.text.borrow_mut().push(Box::new(SubToken)),
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)),
T_EXIT => text.push(Box::new(ExitToken::from_bytecode(&[
instruction,
code_iter.next().unwrap(),
]))),
T_SET => text.push(Box::new(SetToken::from_bytecode(&[
instruction,
code_iter.next().unwrap(),
code_iter.next().unwrap(),
]))),
T_COPY => text.push(Box::new(CopyToken::from_bytecode(&[
instruction,
code_iter.next().unwrap(),
code_iter.next().unwrap(),
]))),
T_LOAD => text.push(Box::new(LoadToken)),
T_CLEAR => text.push(Box::new(ClearToken::from_bytecode(&[
instruction,
code_iter.next().unwrap(),
]))),
T_WRITE => text.push(Box::new(WriteToken)),
T_LABEL => text.push(Box::new(LabelToken)),
T_GOTO => text.push(Box::new(GotoToken)),
T_DEBUG => text.push(Box::new(DebugToken)),
T_ADD => text.push(Box::new(AddToken)),
T_SUB => text.push(Box::new(SubToken)),
T_MUL => text.push(Box::new(MulToken)),
T_DIV => text.push(Box::new(DivToken)),
T_MOD => text.push(Box::new(ModToken)),
T_LSH => text.push(Box::new(LshToken)),
T_RSH => text.push(Box::new(RshToken)),
T_JG => text.push(Box::new(JgToken)),
T_JL => text.push(Box::new(JlToken)),
T_JE => text.push(Box::new(JeToken)),
T_PAUSE => text.push(Box::new(PauseToken)),
T_CMD => text.push(Box::new(CmdToken)),
T_SEND => text.push(Box::new(SendToken)),
_ => panic!("unknown instruction {}", instruction),
};
}

@ -13,6 +13,7 @@ pub const T_CLEAR: u8 = 0x05;
pub const T_WRITE: u8 = 0x06;
pub const T_LABEL: u8 = 0x07;
pub const T_GOTO: u8 = 0x08;
pub const T_DEBUG: u8 = 0x09;
pub const T_ADD: u8 = 0x10;
pub const T_SUB: u8 = 0x11;
pub const T_MUL: u8 = 0x12;
@ -137,13 +138,18 @@ impl Token for CopyToken {
value = rg.get();
} else if self.register_1 == RCS {
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) {
rg.set(value as u8);
} else if let Some(mut rg) = runtime.get_4byte_register(self.register_2) {
rg.set(value);
} else if self.register_2 == RCS {
runtime.rcs.set(value == 0);
} else {
panic!("unknown register {}", self.register_2);
}
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 {
fn from_bytecode(_: &[&u8]) -> Self {
Self
@ -284,7 +317,7 @@ impl Token for AddToken {
}
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(())
}

Loading…
Cancel
Save