From c6f4a231743738c3a5afcddfa64f3d21c26fb661 Mon Sep 17 00:00:00 2001 From: Jur van den Berg Date: Sat, 2 Jun 2018 16:26:21 +0200 Subject: [PATCH] Add next_instruction helper and bump version --- Cargo.toml | 2 +- src/bin/ijvm.rs | 18 ++++++++---------- src/machine.rs | 41 ++++++++++++++++++++++++++++++++++++++++- 3 files changed, 49 insertions(+), 12 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 888ca5f..b587d3f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rustijvm" -version = "0.1.0" +version = "1.0.0" authors = ["Jur van den Berg "] [dependencies] diff --git a/src/bin/ijvm.rs b/src/bin/ijvm.rs index faa1087..553a2ac 100644 --- a/src/bin/ijvm.rs +++ b/src/bin/ijvm.rs @@ -15,16 +15,14 @@ fn main() { let ijvmfile = &args[1]; let mut machine = Machine::new_from_file(ijvmfile).unwrap(); - while machine.has_step() { - match machine.step() { - Ok(_) => (), - Err(str) => { - println!("\n\nERROR: pc=0x{:x} fp=0x{:x}: {}\nProgram exit", - machine.get_program_counter(), - machine.frame.len() - 1, - str); - return; - } + match machine.run() { + Ok(_) => (), + Err(str) => { + println!("\n\nERROR: pc=0x{:x} fp=0x{:x}: {}\nProgram exit", + machine.get_program_counter(), + machine.frame.len() - 1, + str); + return; } } } \ No newline at end of file diff --git a/src/machine.rs b/src/machine.rs index 5a74f64..cb77740 100644 --- a/src/machine.rs +++ b/src/machine.rs @@ -3,7 +3,7 @@ use std::sync::{Mutex, Arc}; use Result; use block::Block; -use ops::Operation; +use ops::{Operation, Args, num_to_op}; use ijvmreader::IJVMReader; use binread::{BinRead, BinReadable}; use frame::Frame; @@ -135,6 +135,45 @@ impl Machine { self.block[self.get_program_counter()] } + pub fn next_instruction(&mut self) -> Result<(String, Vec)> { + let checkpoint = self.block.cur(); + + let mut opcode = self.block.read_u8()?; + let mut params = Vec::new(); + let mut wide = false; + + // WIDE + if opcode == 0xC4 { + wide = true; + opcode = self.block.read_u8()?; + } + + let (name, args) = match num_to_op(opcode) { + Operation::Invalid(_) => return Err("Invalid operation"), + Operation::Op(name, _, args) => (name, args), + }; + + for arg in &args { + let v = match arg { + Args::Byte => self.block.read_i8()? as i32, + Args::Short => self.block.read_i16()? as i32, + Args::Var => { + if wide { + self.block.read_u16()? as i32 + } else { + self.block.read_u8()? as i32 + } + }, + Args::Label => self.block.read_i16()? as i32, + Args::Constant => self.block.read_u16()? as i32, + }; + params.push(v); + } + + self.block.seek(checkpoint).unwrap(); + Ok((name.to_string(), params)) + } + // pub fn get_stack_pointer(&self) -> usize { // return self.frame.last().unwrap().stack.len(); // }