diff --git a/src/bytecode.rs b/src/bytecode.rs index 5082bf2..21185ff 100644 --- a/src/bytecode.rs +++ b/src/bytecode.rs @@ -79,6 +79,7 @@ impl Bytecode { 0x6C => (Instruction::DivideInt(), 1), 0x6D => (Instruction::DivideLong(), 1), + 0x78 => (Instruction::ArithmeticShiftIntLeft(), 1), 0x7A => (Instruction::ArithmeticShiftIntRight(), 1), 0x7C => (Instruction::LogicalShiftIntRight(), 1), 0x7E => (Instruction::AndInt(), 1), @@ -324,7 +325,8 @@ pub enum Instruction { DivideInt() = 0x6C, // integer division, round toward zero and more rules DivideLong() = 0x6D, // long division - ArithmeticShiftIntRight() = 0x7A, // shift int + ArithmeticShiftIntLeft() = 0x78, // shift int left, preserve sign + ArithmeticShiftIntRight() = 0x7A, // shift int right, preserve sign LogicalShiftIntRight() = 0x7C, // shift int right with zero extension AndInt() = 0x7E, // bitwise and diff --git a/src/jvm.rs b/src/jvm.rs index 1879548..108a53a 100644 --- a/src/jvm.rs +++ b/src/jvm.rs @@ -678,13 +678,20 @@ impl JVM { wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(value_0 + value_1)))?; } + Instruction::ArithmeticShiftIntLeft() => { + let shift = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))? as u8 & 0b00011111; + let int = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?; + + // rust does arithmetic shift on singed values + wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(int << shift)))?; + } Instruction::ArithmeticShiftIntRight() => { let shift = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))? as u8 & 0b00011111; let int = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?; // rust does arithmetic shift on singed values wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(int >> shift)))?; - }, + } Instruction::ArrayLength() => { let array_reference = wrap_stackframe_error(class, method, frame.operand_stack.pop_reference(0))?; @@ -1554,7 +1561,14 @@ impl JVM { let new_object = self.heap_area.make_object(&self.class_store, class_index); wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Reference(new_object)))?; - }, + } + + Instruction::OrInt() => { + let value_0 = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?; + let value_1 = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?; + + wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(value_0 | value_1)))?; + } Instruction::Pop() => { wrap_stackframe_error(class, method, frame.operand_stack.pop_computational_1(0))?;