gbf_core/decompiler/handlers/
special_three_operand.rs1#![deny(missing_docs)]
2
3use std::backtrace::Backtrace;
4
5use crate::{
6 decompiler::{
7 ProcessedInstruction, ProcessedInstructionBuilder,
8 ast::{bin_op::BinOpType, new_array_access, new_assignment, new_bin_op, new_range},
9 function_decompiler::FunctionDecompilerError,
10 function_decompiler_context::FunctionDecompilerContext,
11 },
12 instruction::Instruction,
13 opcode::Opcode,
14};
15
16use super::OpcodeHandler;
17
18pub struct SpecialThreeOperandHandler;
20
21impl OpcodeHandler for SpecialThreeOperandHandler {
22 fn handle_instruction(
23 &self,
24 context: &mut FunctionDecompilerContext,
25 instruction: &Instruction,
26 ) -> Result<ProcessedInstruction, FunctionDecompilerError> {
27 match instruction.opcode {
28 Opcode::AssignArray => {
29 let rhs = context.pop_expression()?;
30 let lhs_ind = context.pop_expression()?;
31 let lhs_arr = context.pop_expression()?;
32
33 let arr_access = new_array_access(lhs_arr, lhs_ind);
34 let stmt = new_assignment(arr_access, rhs);
35
36 Ok(ProcessedInstructionBuilder::new()
37 .push_to_region(stmt.into())
38 .build())
39 }
40 Opcode::InRange => {
41 let last = context.pop_expression()?;
42 let first = context.pop_expression()?;
43 let lhs = context.pop_expression()?;
44
45 let range = new_range(first, last);
46 let bin_op = new_bin_op(lhs, range, BinOpType::In).map_err(|e| {
47 FunctionDecompilerError::AstNodeError {
48 source: e,
49 context: context.get_error_context(),
50 backtrace: Backtrace::capture(),
51 }
52 })?;
53
54 context.push_one_node(bin_op.into())?;
55 Ok(ProcessedInstructionBuilder::new().build())
56 }
57 Opcode::AssignMultiDimensionalArrayIndex => {
58 let ind_2 = context.pop_expression()?;
59 let ind_1 = context.pop_expression()?;
60 let arr = context.pop_expression()?;
61
62 let arr_access = new_array_access(new_array_access(arr, ind_1), ind_2);
63
64 context.push_one_node(arr_access.into())?;
65 Ok(ProcessedInstructionBuilder::new().build())
66 }
67 Opcode::AssignMultiDimensionalArray => {
68 let assign_var = context.pop_expression()?;
69 let ind_2 = context.pop_expression()?;
70 let ind_1 = context.pop_expression()?;
71 let arr = context.pop_expression()?;
72
73 let arr_access = new_array_access(new_array_access(arr, ind_1), ind_2);
74
75 let stmt = new_assignment(arr_access, assign_var);
76 Ok(ProcessedInstructionBuilder::new()
77 .push_to_region(stmt.into())
78 .build())
79 }
80 _ => Err(FunctionDecompilerError::UnimplementedOpcode {
81 opcode: instruction.opcode,
82 context: context.get_error_context(),
83 backtrace: Backtrace::capture(),
84 }),
85 }
86 }
87}