Now with a hashmap for ops lookup
This commit is contained in:
123
src/ops.rs
123
src/ops.rs
@@ -1,8 +1,10 @@
|
||||
use binread::BinRead;
|
||||
use machine::Machine;
|
||||
use frame::Frame;
|
||||
use machine::Machine;
|
||||
use std::collections::HashMap;
|
||||
use std::io::Read;
|
||||
use std::num::Wrapping;
|
||||
use Result;
|
||||
use std::io::{Read};
|
||||
|
||||
pub type OpFunc = fn(&mut Machine) -> Result<()>;
|
||||
|
||||
@@ -17,61 +19,77 @@ pub enum Args {
|
||||
|
||||
pub enum Operation {
|
||||
Op(&'static str, OpFunc, Vec<Args>),
|
||||
Invalid(u8)
|
||||
Invalid,
|
||||
}
|
||||
|
||||
const JUMP_OFFSET: i32 = 3;
|
||||
const INVALID_OP: Operation = Operation::Invalid;
|
||||
|
||||
pub fn num_to_op(op: u8) -> Operation {
|
||||
match op {
|
||||
0x00 => Operation::Op("NOP", nop, vec![]),
|
||||
0x10 => Operation::Op("BIPUSH", bipush, vec![Args::Byte]),
|
||||
0x13 => Operation::Op("LDC_W", ldc_w, vec![Args::Constant]),
|
||||
0x15 => Operation::Op("ILOAD", iload, vec![Args::Var]),
|
||||
0x36 => Operation::Op("ISTORE", istore, vec![Args::Var]),
|
||||
0x57 => Operation::Op("POP", pop, vec![]),
|
||||
0x59 => Operation::Op("DUP", dup, vec![]),
|
||||
0x5F => Operation::Op("SWAP", swap, vec![]),
|
||||
0x60 => Operation::Op("IADD", iadd, vec![]),
|
||||
0x64 => Operation::Op("ISUB", isub, vec![]),
|
||||
0x7E => Operation::Op("IAND", iand, vec![]),
|
||||
0xB0 => Operation::Op("IOR", ior, vec![]),
|
||||
0x84 => Operation::Op("IINC", iinc, vec![Args::Var, Args::Byte]),
|
||||
0x99 => Operation::Op("IFEQ", ifeq, vec![Args::Label]),
|
||||
0x9b => Operation::Op("IFLT", iflt, vec![Args::Label]),
|
||||
0x9F => Operation::Op("IF_ICMPEQ", if_icmpeq, vec![Args::Label]),
|
||||
0xA7 => Operation::Op("GOTO", goto, vec![Args::Label]),
|
||||
0xAC => Operation::Op("IRETURN", ireturn, vec![]),
|
||||
0xB6 => Operation::Op("INVOKEVIRTUAL", invokevirtual, vec![Args::Constant]),
|
||||
0xC4 => Operation::Op("WIDE", wide, vec![]),
|
||||
0xFC => Operation::Op("IN", _in, vec![]),
|
||||
0xFD => Operation::Op("OUT", out, vec![]),
|
||||
0xFE => Operation::Op("ERR", err, vec![]),
|
||||
0xFF => Operation::Op("HALT", halt, vec![]),
|
||||
lazy_static! {
|
||||
static ref OPS_MAP: HashMap<u8, Operation> = {
|
||||
let mut m = HashMap::new();
|
||||
|
||||
m.insert(0x00, Operation::Op("NOP", nop, vec![]));
|
||||
m.insert(0x10, Operation::Op("BIPUSH", bipush, vec![Args::Byte]));
|
||||
m.insert(0x13, Operation::Op("LDC_W", ldc_w, vec![Args::Constant]));
|
||||
m.insert(0x15, Operation::Op("ILOAD", iload, vec![Args::Var]));
|
||||
m.insert(0x36, Operation::Op("ISTORE", istore, vec![Args::Var]));
|
||||
m.insert(0x57, Operation::Op("POP", pop, vec![]));
|
||||
m.insert(0x59, Operation::Op("DUP", dup, vec![]));
|
||||
m.insert(0x5F, Operation::Op("SWAP", swap, vec![]));
|
||||
m.insert(0x60, Operation::Op("IADD", iadd, vec![]));
|
||||
m.insert(0x64, Operation::Op("ISUB", isub, vec![]));
|
||||
m.insert(0x7E, Operation::Op("IAND", iand, vec![]));
|
||||
m.insert(0xB0, Operation::Op("IOR", ior, vec![]));
|
||||
m.insert(
|
||||
0x84,
|
||||
Operation::Op("IINC", iinc, vec![Args::Var, Args::Byte]),
|
||||
);
|
||||
m.insert(0x99, Operation::Op("IFEQ", ifeq, vec![Args::Label]));
|
||||
m.insert(0x9b, Operation::Op("IFLT", iflt, vec![Args::Label]));
|
||||
m.insert(
|
||||
0x9F,
|
||||
Operation::Op("IF_ICMPEQ", if_icmpeq, vec![Args::Label]),
|
||||
);
|
||||
m.insert(0xA7, Operation::Op("GOTO", goto, vec![Args::Label]));
|
||||
m.insert(0xAC, Operation::Op("IRETURN", ireturn, vec![]));
|
||||
m.insert(
|
||||
0xB6,
|
||||
Operation::Op("INVOKEVIRTUAL", invokevirtual, vec![Args::Constant]),
|
||||
);
|
||||
m.insert(0xC4, Operation::Op("WIDE", wide, vec![]));
|
||||
m.insert(0xFC, Operation::Op("IN", _in, vec![]));
|
||||
m.insert(0xFD, Operation::Op("OUT", out, vec![]));
|
||||
m.insert(0xFE, Operation::Op("ERR", err, vec![]));
|
||||
m.insert(0xFF, Operation::Op("HALT", halt, vec![]));
|
||||
|
||||
#[cfg(feature = "extra:sleep")]
|
||||
0xF0 => Operation::Op("SLP", slp, vec![Args::Byte]),
|
||||
m.insert(0xF0, Operation::Op("SLP", slp, vec![Args::Byte]));
|
||||
|
||||
#[cfg(feature = "bonus:network")]
|
||||
0xE1 => Operation::Op("NETBIND", netbind, vec![]),
|
||||
m.insert(0xE1, Operation::Op("NETBIND", netbind, vec![]));
|
||||
#[cfg(feature = "bonus:network")]
|
||||
0xE2 => Operation::Op("NETCONNECT", netconnect, vec![]),
|
||||
m.insert(0xE2, Operation::Op("NETCONNECT", netconnect, vec![]));
|
||||
#[cfg(feature = "bonus:network")]
|
||||
0xE3 => Operation::Op("NETIN", netin, vec![]),
|
||||
m.insert(0xE3, Operation::Op("NETIN", netin, vec![]));
|
||||
#[cfg(feature = "bonus:network")]
|
||||
0xE4 => Operation::Op("NETOUT", netout, vec![]),
|
||||
m.insert(0xE4, Operation::Op("NETOUT", netout, vec![]));
|
||||
#[cfg(feature = "bonus:network")]
|
||||
0xE5 => Operation::Op("NETCLOSE", netclose, vec![]),
|
||||
m.insert(0xE5, Operation::Op("NETCLOSE", netclose, vec![]));
|
||||
|
||||
#[cfg(feature = "bonus:heap")]
|
||||
0xD1 => Operation::Op("NEWARRAY", newarray, vec![]),
|
||||
m.insert(0xD1, Operation::Op("NEWARRAY", newarray, vec![]));
|
||||
#[cfg(feature = "bonus:heap")]
|
||||
0xD2 => Operation::Op("IALOAD", iaload, vec![]),
|
||||
m.insert(0xD2, Operation::Op("IALOAD", iaload, vec![]));
|
||||
#[cfg(feature = "bonus:heap")]
|
||||
0xD3 => Operation::Op("IASTORE", iastore, vec![]),
|
||||
m.insert(0xD3, Operation::Op("IASTORE", iastore, vec![]));
|
||||
|
||||
x => Operation::Invalid(x)
|
||||
}
|
||||
m
|
||||
};
|
||||
}
|
||||
|
||||
pub fn num_to_op(op: u8) -> &'static Operation {
|
||||
OPS_MAP.get(&op).unwrap_or(&INVALID_OP)
|
||||
}
|
||||
|
||||
fn nop(_: &mut Machine) -> Result<()> {
|
||||
@@ -108,16 +126,16 @@ fn pop(machine: &mut Machine) -> Result<()> {
|
||||
}
|
||||
|
||||
fn iadd(machine: &mut Machine) -> Result<()> {
|
||||
let a = machine.cur_stack().pop()?;
|
||||
let b = machine.cur_stack().pop()?;
|
||||
machine.cur_stack().push(a + b);
|
||||
let a = Wrapping(machine.cur_stack().pop()?);
|
||||
let b = Wrapping(machine.cur_stack().pop()?);
|
||||
machine.cur_stack().push((a + b).0);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn isub(machine: &mut Machine) -> Result<()> {
|
||||
let a = machine.cur_stack().pop()?;
|
||||
let b = machine.cur_stack().pop()?;
|
||||
machine.cur_stack().push(b - a);
|
||||
let a = Wrapping(machine.cur_stack().pop()?);
|
||||
let b = Wrapping(machine.cur_stack().pop()?);
|
||||
machine.cur_stack().push((b - a).0);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -150,7 +168,7 @@ fn halt(machine: &mut Machine) -> Result<()> {
|
||||
fn ifeq(machine: &mut Machine) -> Result<()> {
|
||||
let offset = i32::from(machine.block.read_i16()?) - JUMP_OFFSET;
|
||||
if machine.cur_stack().pop()? == 0 {
|
||||
return machine.block.jump(offset)
|
||||
return machine.block.jump(offset);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -158,7 +176,7 @@ fn ifeq(machine: &mut Machine) -> Result<()> {
|
||||
fn iflt(machine: &mut Machine) -> Result<()> {
|
||||
let offset = i32::from(machine.block.read_i16()?) - JUMP_OFFSET;
|
||||
if machine.cur_stack().pop()? < 0 {
|
||||
return machine.block.jump(offset)
|
||||
return machine.block.jump(offset);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -166,7 +184,7 @@ fn iflt(machine: &mut Machine) -> Result<()> {
|
||||
fn if_icmpeq(machine: &mut Machine) -> Result<()> {
|
||||
let offset = i32::from(machine.block.read_i16()?) - JUMP_OFFSET;
|
||||
if machine.cur_stack().pop()? == machine.cur_stack().pop()? {
|
||||
return machine.block.jump(offset)
|
||||
return machine.block.jump(offset);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -249,13 +267,12 @@ fn invokevirtual(machine: &mut Machine) -> Result<()> {
|
||||
|
||||
machine.frame.push(newframe);
|
||||
Ok(())
|
||||
|
||||
}
|
||||
|
||||
fn ireturn(machine: &mut Machine) -> Result<()> {
|
||||
let mut prev_frame: Frame = match machine.frame.pop() {
|
||||
Some(a) => a,
|
||||
None => return Err("Got no frame... somehow...")
|
||||
None => return Err("Got no frame... somehow..."),
|
||||
};
|
||||
let result = prev_frame.stack.pop()?;
|
||||
let return_addr = prev_frame.get(0)?;
|
||||
@@ -265,13 +282,13 @@ fn ireturn(machine: &mut Machine) -> Result<()> {
|
||||
|
||||
#[cfg(feature = "extra:sleep")]
|
||||
fn slp(machine: &mut Machine) -> Result<()> {
|
||||
use std::time;
|
||||
use std::thread;
|
||||
use std::time;
|
||||
let val = match machine.block.read_u8() {
|
||||
Ok(a) => u64::from(a),
|
||||
Err(_) => return Err("Expected argument"),
|
||||
};
|
||||
let slpdur = time::Duration::from_millis(val*100);
|
||||
let slpdur = time::Duration::from_millis(val * 100);
|
||||
thread::sleep(slpdur);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user