Implemented more opcodes and unsafe stuff

This commit is contained in:
vegowotenks 2024-11-07 10:35:02 +01:00
parent dfb6060df9
commit d38d5b2897
5 changed files with 340 additions and 84 deletions

View file

@ -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)
}
}