Implemented more opcodes and unsafe stuff
This commit is contained in:
parent
dfb6060df9
commit
d38d5b2897
5 changed files with 340 additions and 84 deletions
101
src/jvm.rs
101
src/jvm.rs
|
@ -706,8 +706,8 @@ impl JVM {
|
|||
}
|
||||
|
||||
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))?;
|
||||
let shift = wrap_stackframe_error(class, method, frame.operand_stack.pop_int_compatible(0))? as u8 & 0b00011111;
|
||||
let int = wrap_stackframe_error(class, method, frame.operand_stack.pop_int_compatible(0))?;
|
||||
|
||||
// rust does arithmetic shift on singed values
|
||||
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(int << shift)))?;
|
||||
|
@ -746,8 +746,8 @@ impl JVM {
|
|||
}
|
||||
|
||||
Instruction::AndInt() => {
|
||||
let value_1 = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
|
||||
let value_2 = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
|
||||
let value_1 = wrap_stackframe_error(class, method, frame.operand_stack.pop_int_compatible(0))?;
|
||||
let value_2 = wrap_stackframe_error(class, method, frame.operand_stack.pop_int_compatible(0))?;
|
||||
|
||||
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(value_1 & value_2)))?;
|
||||
}
|
||||
|
@ -758,8 +758,8 @@ impl JVM {
|
|||
}
|
||||
|
||||
Instruction::BranchIntEquality(branch_offset) => {
|
||||
let value_2 = 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))?;
|
||||
let value_2 = wrap_stackframe_error(class, method, frame.operand_stack.pop_int_compatible(0))?;
|
||||
let value_1 = wrap_stackframe_error(class, method, frame.operand_stack.pop_int_compatible(0))?;
|
||||
|
||||
if value_1 == value_2 {
|
||||
frame.instruction_pointer -= offset as u32;
|
||||
|
@ -768,8 +768,8 @@ impl JVM {
|
|||
}
|
||||
|
||||
Instruction::BranchIntGreaterEquals(branch_offset) => {
|
||||
let value_2 = 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))?;
|
||||
let value_2 = wrap_stackframe_error(class, method, frame.operand_stack.pop_int_compatible(0))?;
|
||||
let value_1 = wrap_stackframe_error(class, method, frame.operand_stack.pop_int_compatible(0))?;
|
||||
|
||||
if value_1 >= value_2 {
|
||||
frame.instruction_pointer -= offset as u32;
|
||||
|
@ -778,8 +778,8 @@ impl JVM {
|
|||
}
|
||||
|
||||
Instruction::BranchIntGreaterThan(branch_offset) => {
|
||||
let value_2 = 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))?;
|
||||
let value_2 = wrap_stackframe_error(class, method, frame.operand_stack.pop_int_compatible(0))?;
|
||||
let value_1 = wrap_stackframe_error(class, method, frame.operand_stack.pop_int_compatible(0))?;
|
||||
|
||||
if value_1 > value_2 {
|
||||
frame.instruction_pointer -= offset as u32;
|
||||
|
@ -788,8 +788,8 @@ impl JVM {
|
|||
}
|
||||
|
||||
Instruction::BranchIntInequality(branch_offset) => {
|
||||
let value_2 = 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))?;
|
||||
let value_2 = wrap_stackframe_error(class, method, frame.operand_stack.pop_int_compatible(0))?;
|
||||
let value_1 = wrap_stackframe_error(class, method, frame.operand_stack.pop_int_compatible(0))?;
|
||||
|
||||
if value_1 != value_2 {
|
||||
frame.instruction_pointer -= offset as u32;
|
||||
|
@ -798,8 +798,8 @@ impl JVM {
|
|||
}
|
||||
|
||||
Instruction::BranchIntLessEquals(branch_offset) => {
|
||||
let value_2 = 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))?;
|
||||
let value_2 = wrap_stackframe_error(class, method, frame.operand_stack.pop_int_compatible(0))?;
|
||||
let value_1 = wrap_stackframe_error(class, method, frame.operand_stack.pop_int_compatible(0))?;
|
||||
|
||||
if value_1 <= value_2 {
|
||||
frame.instruction_pointer -= offset as u32;
|
||||
|
@ -1100,6 +1100,18 @@ impl JVM {
|
|||
wrap_stackframe_error(class, method, frame.operand_stack.push(popped_value))?;
|
||||
}
|
||||
|
||||
Instruction::DuplicateComputationalValue() => {
|
||||
if frame.operand_stack.computational_type_at(0) == 1 {
|
||||
let popped_value = wrap_stackframe_error(class, method, frame.operand_stack.pop_computational_1(0))?;
|
||||
wrap_stackframe_error(class, method, frame.operand_stack.push(popped_value))?;
|
||||
wrap_stackframe_error(class, method, frame.operand_stack.push(popped_value))?;
|
||||
} else {
|
||||
let popped_value = wrap_stackframe_error(class, method, frame.operand_stack.pop_computational_2(0))?;
|
||||
wrap_stackframe_error(class, method, frame.operand_stack.push_field_value(popped_value))?;
|
||||
wrap_stackframe_error(class, method, frame.operand_stack.push_field_value(popped_value))?;
|
||||
}
|
||||
}
|
||||
|
||||
Instruction::DuplicateInsertDown() => {
|
||||
let value_1 = wrap_stackframe_error(class, method, frame.operand_stack.pop_computational_1(0))?;
|
||||
let value_2 = wrap_stackframe_error(class, method, frame.operand_stack.pop_computational_1(0))?;
|
||||
|
@ -1182,34 +1194,39 @@ impl JVM {
|
|||
Instruction::InstanceOf(classref_index) => {
|
||||
let class_name = class.gather_class(classref_index)?;
|
||||
let object = wrap_stackframe_error(class, method, frame.operand_stack.peek_reference(0))?;
|
||||
let native_class_name = self.heap_area.object_area.get_reference_native_class_name(object, &self.class_store);
|
||||
|
||||
if class_name.starts_with("[") {
|
||||
// TODO: Create array class on demand
|
||||
let instruction_result = if object == ObjectReference::NULL {
|
||||
frame.operand_stack.pop_reference(0).unwrap();
|
||||
0
|
||||
} else {
|
||||
if ! self.class_store.have_class(class_name) {
|
||||
frame.instruction_pointer -= offset as u32;
|
||||
return Ok(JVMCallbackOperation::LoadClass(class_name.to_string()));
|
||||
let native_class_name = self.heap_area.object_area.get_reference_native_class_name(object, &self.class_store);
|
||||
|
||||
if class_name.starts_with("[") {
|
||||
// TODO: Create array class on demand
|
||||
} else {
|
||||
if ! self.class_store.have_class(class_name) {
|
||||
frame.instruction_pointer -= offset as u32;
|
||||
return Ok(JVMCallbackOperation::LoadClass(class_name.to_string()));
|
||||
}
|
||||
if ! self.class_store.was_init(class_name).unwrap() {
|
||||
frame.instruction_pointer -= offset as u32;
|
||||
return Ok(JVMCallbackOperation::InitClass(class_name.to_string()));
|
||||
}
|
||||
}
|
||||
if ! self.class_store.was_init(class_name).unwrap() {
|
||||
frame.instruction_pointer -= offset as u32;
|
||||
return Ok(JVMCallbackOperation::InitClass(class_name.to_string()));
|
||||
|
||||
frame.operand_stack.pop_reference(0).unwrap();
|
||||
|
||||
if class_name == native_class_name {
|
||||
1
|
||||
} else {
|
||||
let class_index = self.class_store.class_idx_from_name(class_name).unwrap();
|
||||
let class_object_ref = self.class_store.get_class_objectref_from_index(class_index);
|
||||
let native_class_description = self.heap_area.object_area.get_class_ref_native_class_name(class_object_ref, &self.class_store);
|
||||
let class_description = AbstractTypeDescription::parse_full(native_class_description)?;
|
||||
|
||||
let object_description = AbstractTypeDescription::parse_full(native_class_name)?;
|
||||
if self.class_store.are_types_compatible(&object_description, &class_description) { 1 } else { 0 }
|
||||
}
|
||||
}
|
||||
|
||||
frame.operand_stack.pop_reference(0).unwrap();
|
||||
|
||||
|
||||
let instruction_result = if class_name == native_class_name {
|
||||
1
|
||||
} else {
|
||||
let class_index = self.class_store.class_idx_from_name(class_name).unwrap();
|
||||
let class_object_ref = self.class_store.get_class_objectref_from_index(class_index);
|
||||
let native_class_description = self.heap_area.object_area.get_class_ref_native_class_name(class_object_ref, &self.class_store);
|
||||
let class_description = AbstractTypeDescription::parse_full(native_class_description)?;
|
||||
|
||||
let object_description = AbstractTypeDescription::parse_full(native_class_name)?;
|
||||
if self.class_store.are_types_compatible(&object_description, &class_description) { 1 } else { 0 }
|
||||
};
|
||||
|
||||
|
||||
|
@ -1924,6 +1941,13 @@ impl JVM {
|
|||
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(5)))?;
|
||||
}
|
||||
|
||||
Instruction::PushConstLong0() => {
|
||||
wrap_stackframe_error(class, method, frame.operand_stack.push_long(0))?;
|
||||
}
|
||||
Instruction::PushConstLong1() => {
|
||||
wrap_stackframe_error(class, method, frame.operand_stack.push_long(1))?;
|
||||
}
|
||||
|
||||
Instruction::PushNull() => {
|
||||
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Reference(ObjectReference::NULL)))?;
|
||||
}
|
||||
|
@ -1937,6 +1961,7 @@ impl JVM {
|
|||
StackValue::Int(i) => {
|
||||
match expected_field_descriptor.as_str() {
|
||||
"Z" => FieldValue::Boolean(i != 0),
|
||||
"B" => FieldValue::Byte(i as i8),
|
||||
_ => FieldValue::Int(i)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue