Skip to main content

gcrecomp_core/recompiler/codegen/
mod.rs

1// Rust code generator with optimizations
2pub mod register;
3pub mod memory;
4
5use anyhow::{Result, Context};
6use crate::recompiler::decoder::{DecodedInstruction, InstructionType, Operand};
7use crate::recompiler::analysis::FunctionMetadata;
8use std::collections::HashMap;
9
10pub struct CodeGenerator {
11    indent_level: usize,
12    register_map: HashMap<u8, String>,
13    next_temp: usize,
14    register_values: HashMap<u8, RegisterValue>,
15    label_counter: usize,
16    optimize: bool,
17    function_calls: Vec<u32>, // Track function call targets
18    basic_block_map: HashMap<u32, usize>, // Map addresses to basic block indices
19}
20
21#[derive(Debug, Clone)]
22enum RegisterValue {
23    Constant(u32),
24    Variable(String),
25    Unknown,
26}
27
28impl CodeGenerator {
29    pub fn new() -> Self {
30        Self {
31            indent_level: 0,
32            register_map: HashMap::new(),
33            next_temp: 0,
34            register_values: HashMap::new(),
35            label_counter: 0,
36            optimize: true,
37            function_calls: Vec::new(),
38            basic_block_map: HashMap::new(),
39        }
40    }
41
42    pub fn with_optimizations(mut self, optimize: bool) -> Self {
43        self.optimize = optimize;
44        self
45    }
46
47    pub fn generate_function(
48        &mut self,
49        metadata: &FunctionMetadata,
50        instructions: &[DecodedInstruction],
51    ) -> Result<String> {
52        let mut code = String::new();
53
54        // Generate function signature
55        code.push_str(&self.generate_function_signature(metadata)?);
56        code.push_str(" {\n");
57
58        self.indent_level += 1;
59
60        // Generate function body
61        code.push_str(&self.generate_function_body(instructions)?);
62
63        self.indent_level -= 1;
64        code.push_str("}\n");
65
66        Ok(code)
67    }
68
69    fn generate_function_signature(&self, metadata: &FunctionMetadata) -> Result<String> {
70        let mut sig = String::new();
71
72        // Function name - include address for uniqueness and dispatcher matching
73        let func_name = if metadata.name.is_empty() || metadata.name.starts_with("sub_") {
74            format!("func_0x{:08X}", metadata.address)
75        } else {
76            format!("{}_{:08X}", self.sanitize_identifier(&metadata.name), metadata.address)
77        };
78
79        sig.push_str("pub fn ");
80        sig.push_str(&func_name);
81        sig.push_str("(");
82
83        // Standard function signature: ctx and memory (PowerPC calling convention)
84        sig.push_str("ctx: &mut CpuContext, memory: &mut MemoryManager");
85
86        // Note: Parameters are passed via registers (r3-r10) in PowerPC calling convention
87        // They're already in ctx when the function is called, so we don't need explicit parameters
88
89        sig.push_str(") -> Result<Option<u32>>");
90
91        Ok(sig)
92    }
93
94    fn generate_function_body(&mut self, instructions: &[DecodedInstruction]) -> Result<String> {
95        // Use control flow analysis to generate better code
96        let cfg = crate::recompiler::analysis::control_flow::ControlFlowAnalyzer::build_cfg(instructions, 0)
97            .unwrap_or_else(|_| {
98                // Fallback to basic block construction
99                crate::recompiler::analysis::control_flow::ControlFlowGraph {
100                    nodes: vec![],
101                    edges: vec![],
102                    entry_block: 0,
103                }
104            });
105
106        // Use data flow analysis for optimizations
107        let def_use_chains = crate::recompiler::analysis::data_flow::DataFlowAnalyzer::build_def_use_chains(instructions);
108        let live_analysis = if !cfg.nodes.is_empty() {
109            Some(crate::recompiler::analysis::data_flow::DataFlowAnalyzer::live_variable_analysis(&cfg))
110        } else {
111            None
112        };
113
114        // Optimize instructions using data flow analysis
115        let optimized_instructions = if let Some(ref live) = live_analysis {
116            crate::recompiler::analysis::data_flow::DataFlowAnalyzer::eliminate_dead_code(instructions, live)
117        } else {
118            instructions.to_vec()
119        };
120
121        self.generate_function_body_impl(&optimized_instructions)
122    }
123
124    fn generate_function_body_impl(&mut self, instructions: &[DecodedInstruction]) -> Result<String> {
125        let mut code = String::new();
126
127        // Note: ctx and memory are passed as parameters, no need to initialize
128        // Parameters are already in registers r3-r10 per PowerPC calling convention
129        // No need to load them explicitly - they're already in ctx when function is called
130
131        code.push('\n');
132
133        // Setup stack frame if function has local variables
134        if !instructions.is_empty() {
135            code.push_str(&self.indent());
136            code.push_str("// Stack frame setup\n");
137            code.push_str(&self.indent());
138            code.push_str("let stack_base = ctx.get_register(1); // r1 is stack pointer\n");
139            code.push('\n');
140        }
141
142        // Build control flow graph for better code generation
143        // Clone instructions into basic blocks to avoid borrow issues
144        let mut basic_blocks: Vec<Vec<DecodedInstruction>> = Vec::new();
145        let mut current_block: Vec<DecodedInstruction> = Vec::new();
146
147        for inst in instructions {
148            current_block.push(inst.clone());
149
150            // If this is a branch, end the block
151            if matches!(inst.instruction.instruction_type, InstructionType::Branch) {
152                basic_blocks.push(current_block);
153                current_block = Vec::new();
154            }
155        }
156
157        // Add remaining instructions as final block
158        if !current_block.is_empty() {
159            basic_blocks.push(current_block);
160        }
161
162        // Generate code for each basic block
163        for (block_idx, block) in basic_blocks.iter().enumerate() {
164            if block_idx > 0 {
165                code.push_str(&self.indent());
166                code.push_str(&format!("// Basic block {}\n", block_idx));
167            }
168
169            for (inst_idx, instruction) in block.iter().enumerate() {
170                match self.generate_instruction(instruction) {
171                    Ok(inst_code) => {
172                        code.push_str(&inst_code);
173                    }
174                    Err(e) => {
175                        // Comprehensive error recovery
176                        code.push_str(&self.indent());
177                        code.push_str(&format!(
178                            "// Error generating instruction {}: {}\n",
179                            inst_idx, e
180                        ));
181                        code.push_str(&self.indent());
182                        code.push_str(&format!("// Raw instruction: 0x{:08X}\n", instruction.raw));
183                        code.push_str(&self.indent());
184                        code.push_str(&format!("// Instruction type: {:?}\n", instruction.instruction.instruction_type));
185                        code.push_str(&self.indent());
186                        code.push_str("// Fallback: generating generic instruction handler\n");
187                        code.push_str(&self.indent());
188                        code.push_str(&format!(
189                            "// TODO: Implement proper handling for opcode 0x{:02X}\n",
190                            instruction.instruction.opcode
191                        ));
192                        code.push_str(&self.indent());
193                        code.push_str("// Continuing with next instruction...\n");
194
195                        // Try to generate at least something
196                        if let Ok(fallback) = self.generate_generic(instruction) {
197                            code.push_str(&fallback);
198                        }
199                    }
200                }
201            }
202        }
203
204        // Teardown stack frame
205        if !instructions.is_empty() {
206            code.push('\n');
207            code.push_str(&self.indent());
208            code.push_str("// Stack frame teardown\n");
209            code.push_str(&self.indent());
210            code.push_str("ctx.set_register(1, stack_base);\n");
211        }
212
213        // Return value (PowerPC calling convention: return value in r3)
214        code.push_str(&self.indent());
215        code.push_str("// Return value is in r3 (PowerPC calling convention)\n");
216        code.push_str(&self.indent());
217        code.push_str("Ok(Some(ctx.get_register(3)))\n");
218
219        Ok(code)
220    }
221
222    fn build_basic_blocks<'a>(&self, instructions: &'a [DecodedInstruction]) -> Result<Vec<Vec<&'a DecodedInstruction>>> {
223        // Simple basic block construction: split at branches
224        let mut blocks = Vec::new();
225        let mut current_block = Vec::new();
226
227        for inst in instructions {
228            current_block.push(inst);
229
230            // If this is a branch, end the block
231            if matches!(inst.instruction.instruction_type, InstructionType::Branch) {
232                blocks.push(current_block);
233                current_block = Vec::new();
234            }
235        }
236
237        // Add remaining instructions as final block
238        if !current_block.is_empty() {
239            blocks.push(current_block);
240        }
241
242        Ok(blocks)
243    }
244
245    fn generate_instruction(&mut self, inst: &DecodedInstruction) -> Result<String> {
246        let mut code = String::new();
247
248        // Add instruction address comment for debugging
249        if self.optimize {
250            code.push_str(&self.indent());
251            code.push_str(&format!("// 0x{:08X}: ", inst.raw));
252        }
253
254        match inst.instruction.instruction_type {
255            InstructionType::Arithmetic => {
256                code.push_str(&self.generate_arithmetic(inst)?);
257            }
258            InstructionType::Load => {
259                code.push_str(&self.generate_load(inst)?);
260            }
261            InstructionType::Store => {
262                code.push_str(&self.generate_store(inst)?);
263            }
264            InstructionType::Branch => {
265                code.push_str(&self.generate_branch(inst)?);
266            }
267            InstructionType::Compare => {
268                code.push_str(&self.generate_compare(inst)?);
269            }
270            InstructionType::Move => {
271                code.push_str(&self.generate_move(inst)?);
272            }
273            InstructionType::System => {
274                code.push_str(&self.generate_system(inst)?);
275            }
276            InstructionType::FloatingPoint => {
277                code.push_str(&self.generate_floating_point(inst)?);
278            }
279            InstructionType::ConditionRegister => {
280                code.push_str(&self.generate_condition_register(inst)?);
281            }
282            InstructionType::Shift => {
283                code.push_str(&self.generate_shift(inst)?);
284            }
285            InstructionType::Rotate => {
286                code.push_str(&self.generate_rotate(inst)?);
287            }
288            _ => {
289                // Try to generate a generic instruction handler
290                code.push_str(&self.generate_generic(inst)?);
291            }
292        }
293
294        Ok(code)
295    }
296
297    fn generate_arithmetic(&mut self, inst: &DecodedInstruction) -> Result<String> {
298        let mut code = String::new();
299
300        if inst.instruction.operands.len() < 2 {
301            anyhow::bail!("Arithmetic instruction requires at least 2 operands");
302        }
303
304        let rt_reg = match &inst.instruction.operands[0] {
305            Operand::Register(r) => *r,
306            _ => anyhow::bail!("First operand must be a register"),
307        };
308
309        let ra_reg = match &inst.instruction.operands[1] {
310            Operand::Register(r) => *r,
311            _ => anyhow::bail!("Second operand must be a register"),
312        };
313
314        // Determine operation based on opcode and extended opcode
315        let (op, update_cr) = match inst.instruction.opcode {
316            14 => ("+", false),  // addi
317            15 => ("-", false),   // subi
318            12 => ("&", false),   // andi
319            13 => ("|", false),   // ori
320            10 => ("^", false),   // xori
321            11 => ("&", false),   // andis
322            31 => {
323                // Extended opcode - decode from instruction
324                let ext_opcode = (inst.raw >> 1) & 0x3FF;
325                match ext_opcode {
326                    266 => ("+", false),  // add
327                    40 => ("-", false),   // subf
328                    28 => ("&", false),   // and
329                    444 => ("|", false),  // or
330                    316 => ("^", false),  // xor
331                    235 => ("*", false),  // mullw
332                    233 => ("*", false),  // mulhw
333                    104 => ("/", false),  // divw
334                    536 => ("<<", false), // slw
335                    824 => (">>", false), // srw
336                    792 => (">>", false), // sraw
337                    _ => ("+", false),
338                }
339            }
340            _ => ("+", false),
341        };
342
343        // Get second operand (register or immediate)
344        let (rb_expr, rb_value) = if inst.instruction.operands.len() > 2 {
345            match &inst.instruction.operands[2] {
346                Operand::Register(r) => {
347                    let reg_val = self.get_register_value(*r);
348                    (format!("ctx.get_register({})", r), reg_val)
349                }
350                Operand::Immediate(i) => {
351                    let val = *i as u32;
352                    (format!("{}u32", val), Some(RegisterValue::Constant(val)))
353                }
354                Operand::Immediate32(i) => {
355                    let val = *i as u32;
356                    (format!("{}u32", val), Some(RegisterValue::Constant(val)))
357                }
358                _ => ("0u32".to_string(), Some(RegisterValue::Constant(0))),
359            }
360        } else {
361            ("0u32".to_string(), Some(RegisterValue::Constant(0)))
362        };
363
364        // Handle shift operations specially
365        let operation_code = if op == "<<" || op == ">>" {
366            if op == "<<" {
367                format!("ctx.get_register({}) << ({} & 0x1F)", ra_reg, rb_expr)
368            } else {
369                format!("ctx.get_register({}) >> ({} & 0x1F)", ra_reg, rb_expr)
370            }
371        } else {
372            format!("ctx.get_register({}) {} {}", ra_reg, op, rb_expr)
373        };
374
375        // Optimize: if both operands are constants, compute at compile time
376        let ra_value = self.get_register_value(ra_reg);
377        if let (Some(RegisterValue::Constant(a)), Some(RegisterValue::Constant(b))) = (ra_value, rb_value) {
378            let result = match op {
379                "+" => a.wrapping_add(b),
380                "-" => a.wrapping_sub(b),
381                "*" => a.wrapping_mul(b),
382                "&" => a & b,
383                "|" => a | b,
384                "^" => a ^ b,
385                "<<" => a << (b & 0x1F),
386                ">>" => a >> (b & 0x1F),
387                _ => a,
388            };
389            code.push_str(&self.indent());
390            code.push_str(&format!(
391                "ctx.set_register({}, {}u32); // Optimized: constant folding\n",
392                rt_reg, result
393            ));
394            self.set_register_value(rt_reg, RegisterValue::Constant(result));
395        } else {
396            code.push_str(&self.indent());
397            code.push_str(&format!(
398                "ctx.set_register({}, {});\n",
399                rt_reg, operation_code
400            ));
401            self.set_register_value(rt_reg, RegisterValue::Unknown);
402        }
403
404        // Update condition register if needed
405        if update_cr {
406            code.push_str(&self.indent());
407            code.push_str(&format!(
408                "let result = ctx.get_register({});\n",
409                rt_reg
410            ));
411            code.push_str(&self.indent());
412            code.push_str("let cr_field = if result == 0 { 0x2u8 } else if (result as i32) < 0 { 0x8u8 } else { 0x4u8 };\n");
413            code.push_str(&self.indent());
414            code.push_str("ctx.set_cr_field(0, cr_field);\n");
415        }
416
417        Ok(code)
418    }
419
420    fn get_register_value(&self, reg: u8) -> Option<RegisterValue> {
421        self.register_values.get(&reg).cloned()
422    }
423
424    fn set_register_value(&mut self, reg: u8, value: RegisterValue) {
425        self.register_values.insert(reg, value);
426    }
427
428    fn generate_load(&mut self, inst: &DecodedInstruction) -> Result<String> {
429        let mut code = String::new();
430
431        if inst.instruction.operands.len() < 3 {
432            anyhow::bail!("Load instruction requires 3 operands");
433        }
434
435        let rt_reg = match &inst.instruction.operands[0] {
436            Operand::Register(r) => *r,
437            _ => anyhow::bail!("First operand must be a register"),
438        };
439
440        let ra_reg = match &inst.instruction.operands[1] {
441            Operand::Register(r) => *r,
442            _ => anyhow::bail!("Second operand must be a register"),
443        };
444
445        let offset = match &inst.instruction.operands[2] {
446            Operand::Immediate(i) => *i as i32,
447            _ => 0,
448        };
449
450        // Optimize: if base address is constant, compute address at compile time
451        let base_value = self.get_register_value(ra_reg);
452        if let Some(RegisterValue::Constant(base)) = base_value {
453            let addr = base.wrapping_add(offset as u32);
454            code.push_str(&self.indent());
455            code.push_str(&format!(
456                "let value = memory.read_u32(0x{:08X}u32).unwrap_or(0u32); // Optimized: constant address\n",
457                addr
458            ));
459        } else {
460            code.push_str(&self.indent());
461            code.push_str(&format!(
462                "let addr = ctx.get_register({}) as u32 + {}i32 as u32;\n",
463                ra_reg, offset
464            ));
465            code.push_str(&self.indent());
466            code.push_str("let value = memory.read_u32(addr).unwrap_or(0u32);\n");
467        }
468
469        code.push_str(&self.indent());
470        code.push_str(&format!("ctx.set_register({}, value);\n", rt_reg));
471        self.set_register_value(rt_reg, RegisterValue::Unknown);
472
473        Ok(code)
474    }
475
476    fn generate_store(&mut self, inst: &DecodedInstruction) -> Result<String> {
477        let mut code = String::new();
478
479        if inst.instruction.operands.len() < 3 {
480            anyhow::bail!("Store instruction requires 3 operands");
481        }
482
483        let rs_reg = match &inst.instruction.operands[0] {
484            Operand::Register(r) => *r,
485            _ => anyhow::bail!("First operand must be a register"),
486        };
487
488        let ra_reg = match &inst.instruction.operands[1] {
489            Operand::Register(r) => *r,
490            _ => anyhow::bail!("Second operand must be a register"),
491        };
492
493        let offset = match &inst.instruction.operands[2] {
494            Operand::Immediate(i) => *i as i32,
495            _ => 0,
496        };
497
498        // Optimize: if base address is constant, compute address at compile time
499        let base_value = self.get_register_value(ra_reg);
500        let value_expr = if let Some(RegisterValue::Constant(val)) = self.get_register_value(rs_reg) {
501            format!("{}u32", val)
502        } else {
503            format!("ctx.get_register({})", rs_reg)
504        };
505
506        if let Some(RegisterValue::Constant(base)) = base_value {
507            let addr = base.wrapping_add(offset as u32);
508            code.push_str(&self.indent());
509            code.push_str(&format!(
510                "memory.write_u32(0x{:08X}u32, {}).unwrap_or(()); // Optimized: constant address\n",
511                addr, value_expr
512            ));
513        } else {
514            code.push_str(&self.indent());
515            code.push_str(&format!(
516                "let addr = ctx.get_register({}) as u32 + {}i32 as u32;\n",
517                ra_reg, offset
518            ));
519            code.push_str(&self.indent());
520            code.push_str(&format!("memory.write_u32(addr, {}).unwrap_or(());\n", value_expr));
521        }
522
523        Ok(code)
524    }
525
526    fn generate_branch(&mut self, inst: &DecodedInstruction) -> Result<String> {
527        let mut code = String::new();
528
529        if inst.instruction.operands.is_empty() {
530            anyhow::bail!("Branch instruction requires operands");
531        }
532
533        // Handle different branch types
534        match inst.instruction.operands.len() {
535            1 => {
536                // Unconditional branch (b, ba, bl, bla)
537                let target = match &inst.instruction.operands[0] {
538                    Operand::Immediate32(li) => *li,
539                    Operand::Address(addr) => *addr as i32,
540                    _ => anyhow::bail!("Branch target must be immediate or address"),
541                };
542
543                // Check if this is a function call (bl/bla) or regular branch
544                let is_call = inst.instruction.opcode == 18 && (inst.raw & 1) != 0; // Link bit set
545
546                if is_call {
547                    self.function_calls.push(target as u32);
548                    code.push_str(&self.indent());
549                    code.push_str(&format!(
550                        "// Function call to 0x{:08X}\n",
551                        target
552                    ));
553                    code.push_str(&self.indent());
554                    code.push_str("// Save return address in link register\n");
555                    code.push_str(&self.indent());
556                    code.push_str("let saved_lr = ctx.lr;\n");
557                    code.push_str(&self.indent());
558                    code.push_str("ctx.lr = ctx.pc + 4;\n");
559                    code.push_str(&self.indent());
560                    code.push_str("// Call recompiled function via dispatcher\n");
561                    code.push_str(&self.indent());
562                    code.push_str(&format!(
563                        "match call_function_by_address(0x{:08X}u32, ctx, memory) {{\n",
564                        target
565                    ));
566                    self.indent_level += 1;
567                    code.push_str(&self.indent());
568                    code.push_str("Ok(result) => {\n");
569                    self.indent_level += 1;
570                    code.push_str(&self.indent());
571                    code.push_str("// Function call succeeded, result in r3 (PowerPC calling convention)\n");
572                    code.push_str(&self.indent());
573                    code.push_str("if let Some(ret_val) = result {\n");
574                    self.indent_level += 1;
575                    code.push_str(&self.indent());
576                    code.push_str("ctx.set_register(3, ret_val); // Return value in r3\n");
577                    self.indent_level -= 1;
578                    code.push_str(&self.indent());
579                    code.push_str("}\n");
580                    code.push_str(&self.indent());
581                    code.push_str("ctx.lr = saved_lr; // Restore link register\n");
582                    self.indent_level -= 1;
583                    code.push_str(&self.indent());
584                    code.push_str("}\n");
585                    code.push_str(&self.indent());
586                    code.push_str("Err(e) => {\n");
587                    self.indent_level += 1;
588                    code.push_str(&self.indent());
589                    code.push_str(&format!(
590                        "log::warn!(\"Function call to 0x{:08X} failed: {{:?}}\", e);\n",
591                        target
592                    ));
593                    code.push_str(&self.indent());
594                    code.push_str("ctx.lr = saved_lr; // Restore link register\n");
595                    self.indent_level -= 1;
596                    code.push_str(&self.indent());
597                    code.push_str("}\n");
598                    self.indent_level -= 1;
599                    code.push_str(&self.indent());
600                    code.push_str("}\n");
601                } else {
602                    code.push_str(&self.indent());
603                    code.push_str(&format!(
604                        "ctx.pc = 0x{:08X}u32; // Unconditional branch\n",
605                        target
606                    ));
607                    code.push_str(&self.indent());
608                    code.push_str("return; // Branch out of function\n");
609                }
610            }
611            3..=5 => {
612                // Conditional branch (bc, bca, bcl, bcla)
613                let bo = match &inst.instruction.operands[0] {
614                    Operand::Condition(c) => *c,
615                    _ => anyhow::bail!("First operand must be condition"),
616                };
617
618                let bi = if inst.instruction.operands.len() > 1 {
619                    match &inst.instruction.operands[1] {
620                        Operand::Condition(c) => *c,
621                        _ => anyhow::bail!("Second operand must be condition"),
622                    }
623                } else {
624                    0
625                };
626
627                let target = if inst.instruction.operands.len() > 2 {
628                    match &inst.instruction.operands[2] {
629                        Operand::Immediate(bd) => *bd as i32,
630                        Operand::Address(addr) => *addr as i32,
631                        _ => 0,
632                    }
633                } else {
634                    0
635                };
636
637                let _label = self.next_label();
638                code.push_str(&self.indent());
639                code.push_str(&format!(
640                    "let cr_bit = (ctx.get_cr_field({}) >> {}) & 1;\n",
641                    bi / 4, bi % 4
642                ));
643                code.push_str(&self.indent());
644                code.push_str("if cr_bit != 0 {\n");
645                self.indent_level += 1;
646                code.push_str(&self.indent());
647                code.push_str(&format!(
648                    "ctx.pc = ctx.pc + {}i32 as u32; // Conditional branch\n",
649                    target
650                ));
651                code.push_str(&self.indent());
652                code.push_str("return; // Branch taken\n");
653                self.indent_level -= 1;
654                code.push_str(&self.indent());
655                code.push_str("}\n");
656            }
657            _ => {
658                code.push_str(&self.indent());
659                code.push_str("// Complex branch instruction\n");
660            }
661        }
662
663        Ok(code)
664    }
665
666    fn next_label(&mut self) -> String {
667        let label = format!("label_{}", self.label_counter);
668        self.label_counter += 1;
669        label
670    }
671
672    fn generate_compare(&mut self, inst: &DecodedInstruction) -> Result<String> {
673        let mut code = String::new();
674
675        if inst.instruction.operands.len() < 2 {
676            anyhow::bail!("Compare instruction requires at least 2 operands");
677        }
678
679        let bf = match &inst.instruction.operands[0] {
680            Operand::Condition(c) => *c,
681            _ => 0, // Default to CR0
682        };
683
684        let ra_reg = match &inst.instruction.operands[1] {
685            Operand::Register(r) => *r,
686            _ => anyhow::bail!("Second operand must be a register"),
687        };
688
689        // Handle different compare types (cmpwi, cmplwi, cmpw, cmplw)
690        let compare_value = if inst.instruction.operands.len() > 2 {
691            match &inst.instruction.operands[2] {
692                Operand::Register(rb) => {
693                    format!("ctx.get_register({})", rb)
694                }
695                Operand::Immediate(i) => {
696                    let val = *i as i32;
697                    format!("{}i32", val)
698                }
699                _ => "0i32".to_string(),
700            }
701        } else {
702            "0i32".to_string()
703        };
704
705        // Determine if unsigned comparison (cmplwi, cmplw)
706        let is_unsigned = inst.instruction.opcode == 10; // cmplwi
707
708        code.push_str(&self.indent());
709        code.push_str(&format!(
710            "let ra_val = ctx.get_register({}) as {};\n",
711            ra_reg,
712            if is_unsigned { "u32" } else { "i32" }
713        ));
714        code.push_str(&self.indent());
715        code.push_str(&format!(
716            "let rb_val = {} as {};\n",
717            compare_value,
718            if is_unsigned { "u32" } else { "i32" }
719        ));
720
721        // Set condition register field (LT, GT, EQ bits)
722        code.push_str(&self.indent());
723        code.push_str("let cr_field = if ra_val < rb_val {\n");
724        self.indent_level += 1;
725        code.push_str(&self.indent());
726        code.push_str("0x8u8 // Less than\n");
727        self.indent_level -= 1;
728        code.push_str(&self.indent());
729        code.push_str("} else if ra_val > rb_val {\n");
730        self.indent_level += 1;
731        code.push_str(&self.indent());
732        code.push_str("0x4u8 // Greater than\n");
733        self.indent_level -= 1;
734        code.push_str(&self.indent());
735        code.push_str("} else {\n");
736        self.indent_level += 1;
737        code.push_str(&self.indent());
738        code.push_str("0x2u8 // Equal\n");
739        self.indent_level -= 1;
740        code.push_str(&self.indent());
741        code.push_str("};\n");
742        code.push_str(&self.indent());
743        code.push_str(&format!("ctx.set_cr_field({}, cr_field);\n", bf));
744
745        Ok(code)
746    }
747
748    fn generate_move(&mut self, inst: &DecodedInstruction) -> Result<String> {
749        let mut code = String::new();
750
751        if inst.instruction.operands.is_empty() {
752            anyhow::bail!("Move instruction requires at least one operand");
753        }
754
755        // Handle move from/to link register (mflr/mtlr)
756        if inst.instruction.operands.len() == 1 {
757            let reg = match &inst.instruction.operands[0] {
758                Operand::Register(r) => *r,
759                _ => anyhow::bail!("Move operand must be a register"),
760            };
761
762            // Check if this is mflr (move from link register) or mtlr (move to link register)
763            // This would be determined by the opcode, but for now we'll handle both
764            code.push_str(&self.indent());
765            code.push_str(&format!(
766                "ctx.set_register({}, ctx.lr); // Move from/to link register\n",
767                reg
768            ));
769        }
770
771        Ok(code)
772    }
773
774    fn generate_floating_point(&mut self, inst: &DecodedInstruction) -> Result<String> {
775        let mut code = String::new();
776
777        if inst.instruction.operands.is_empty() {
778            anyhow::bail!("Floating point instruction requires operands");
779        }
780
781        // Handle different FP instruction types based on opcode
782        match inst.instruction.operands.len() {
783            3 => {
784                // Binary operations (fadd, fsub, fmul, fdiv)
785                let frt = match &inst.instruction.operands[0] {
786                    Operand::FpRegister(r) => *r,
787                    _ => anyhow::bail!("First operand must be FP register"),
788                };
789                let fra = match &inst.instruction.operands[1] {
790                    Operand::FpRegister(r) => *r,
791                    _ => anyhow::bail!("Second operand must be FP register"),
792                };
793                let frb = match &inst.instruction.operands[2] {
794                    Operand::FpRegister(r) => *r,
795                    _ => anyhow::bail!("Third operand must be FP register"),
796                };
797
798                // Determine operation based on extended opcode
799                let ext_opcode = (inst.raw >> 1) & 0x3FF;
800                let op = match ext_opcode {
801                    21 => "+",  // fadd
802                    20 => "-",  // fsub
803                    25 => "*",  // fmul
804                    18 => "/",  // fdiv
805                    14 => "+",  // fmadd (FRA * FRC + FRB)
806                    15 => "-",  // fmsub (FRA * FRC - FRB)
807                    28 => "-",  // fnmadd (-(FRA * FRC + FRB))
808                    29 => "-",  // fnmsub (-(FRA * FRC - FRB))
809                    _ => "+",   // Default to add
810                };
811
812                // Handle multiply-add/subtract operations
813                if ext_opcode == 14 || ext_opcode == 15 || ext_opcode == 28 || ext_opcode == 29 {
814                    // These have 4 operands: FRT, FRA, FRC, FRB
815                    if inst.instruction.operands.len() >= 4 {
816                        let frc = match &inst.instruction.operands[2] {
817                            Operand::FpRegister(r) => *r,
818                            _ => anyhow::bail!("Third operand must be FP register for multiply-add"),
819                        };
820                        code.push_str(&self.indent());
821                        code.push_str(&format!(
822                            "let mul_result = ctx.get_fpr({}) * ctx.get_fpr({});\n",
823                            fra, frc
824                        ));
825                        code.push_str(&self.indent());
826                        if ext_opcode == 28 || ext_opcode == 29 {
827                            code.push_str("let mul_result = -mul_result;\n");
828                        }
829                        code.push_str(&self.indent());
830                        code.push_str(&format!(
831                            "let result = mul_result {} ctx.get_fpr({});\n",
832                            if ext_opcode == 15 || ext_opcode == 29 { "-" } else { "+" },
833                            frb
834                        ));
835                        if ext_opcode == 29 {
836                            code.push_str(&self.indent());
837                            code.push_str("let result = -result;\n");
838                        }
839                    } else {
840                        anyhow::bail!("Multiply-add/subtract requires 4 operands");
841                    }
842                } else {
843                    code.push_str(&self.indent());
844                    code.push_str(&format!(
845                        "let result = ctx.get_fpr({}) {} ctx.get_fpr({});\n",
846                        fra, op, frb
847                    ));
848                }
849                code.push_str(&self.indent());
850                code.push_str(&format!("ctx.set_fpr({}, result);\n", frt));
851            }
852            2 => {
853                // Load/Store operations
854                let frt = match &inst.instruction.operands[0] {
855                    Operand::FpRegister(r) => *r,
856                    _ => anyhow::bail!("First operand must be FP register"),
857                };
858                let ra = match &inst.instruction.operands[1] {
859                    Operand::Register(r) => *r,
860                    _ => anyhow::bail!("Second operand must be register"),
861                };
862
863                code.push_str(&self.indent());
864                code.push_str(&format!(
865                    "let addr = ctx.get_register({}) as u32;\n",
866                    ra
867                ));
868                code.push_str(&self.indent());
869                code.push_str("let value = f64::from_bits(memory.read_u64(addr).unwrap_or(0));\n");
870                code.push_str(&self.indent());
871                code.push_str(&format!("ctx.set_fpr({}, value);\n", frt));
872            }
873            _ => {
874                code.push_str(&self.indent());
875                code.push_str("// Complex floating point instruction\n");
876            }
877        }
878
879        Ok(code)
880    }
881
882    fn generate_condition_register(&mut self, inst: &DecodedInstruction) -> Result<String> {
883        let mut code = String::new();
884
885        if inst.instruction.operands.len() == 1 {
886            // Move from/to condition register
887            let reg = match &inst.instruction.operands[0] {
888                Operand::Register(r) => *r,
889                _ => anyhow::bail!("Operand must be register"),
890            };
891            code.push_str(&self.indent());
892            code.push_str(&format!(
893                "ctx.set_register({}, ctx.cr); // Move from/to condition register\n",
894                reg
895            ));
896        } else if inst.instruction.operands.len() == 3 {
897            // CR logical operations (crand, cror, etc.)
898            let bt = match &inst.instruction.operands[0] {
899                Operand::Condition(c) => *c,
900                _ => anyhow::bail!("First operand must be condition"),
901            };
902            let ba = match &inst.instruction.operands[1] {
903                Operand::Condition(c) => *c,
904                _ => anyhow::bail!("Second operand must be condition"),
905            };
906            let bb = match &inst.instruction.operands[2] {
907                Operand::Condition(c) => *c,
908                _ => anyhow::bail!("Third operand must be condition"),
909            };
910
911            code.push_str(&self.indent());
912            code.push_str(&format!(
913                "let cr_a = ctx.get_cr_field({});\n",
914                ba / 4
915            ));
916            code.push_str(&self.indent());
917            code.push_str(&format!(
918                "let cr_b = ctx.get_cr_field({});\n",
919                bb / 4
920            ));
921            // Determine operation based on extended opcode
922            let ext_opcode = (inst.raw >> 1) & 0x3FF;
923            let cr_op = match ext_opcode {
924                257 => "&",   // crand
925                449 => "|",   // cror
926                193 => "^",   // crxor
927                225 => "&",   // crnand (result = !(cr_a & cr_b))
928                33 => "|",    // crnor (result = !(cr_a | cr_b))
929                289 => "^",   // creqv (result = !(cr_a ^ cr_b))
930                129 => "&",   // crandc (result = cr_a & !cr_b)
931                417 => "|",   // crorc (result = cr_a | !cr_b)
932                _ => "&",     // Default to AND
933            };
934
935            code.push_str(&self.indent());
936            if ext_opcode == 225 || ext_opcode == 33 || ext_opcode == 289 {
937                // NAND, NOR, or EQV - need to negate result
938                code.push_str(&format!(
939                    "let cr_result = !(ctx.get_cr_field({}) {} ctx.get_cr_field({}));\n",
940                    ba / 4, cr_op, bb / 4
941                ));
942            } else if ext_opcode == 129 {
943                // AND with complement
944                code.push_str(&format!(
945                    "let cr_result = ctx.get_cr_field({}) & !ctx.get_cr_field({});\n",
946                    ba / 4, bb / 4
947                ));
948            } else if ext_opcode == 417 {
949                // OR with complement
950                code.push_str(&format!(
951                    "let cr_result = ctx.get_cr_field({}) | !ctx.get_cr_field({});\n",
952                    ba / 4, bb / 4
953                ));
954            } else {
955                code.push_str(&format!(
956                    "let cr_result = ctx.get_cr_field({}) {} ctx.get_cr_field({});\n",
957                    ba / 4, cr_op, bb / 4
958                ));
959            }
960            code.push_str(&self.indent());
961            code.push_str(&format!(
962                "ctx.set_cr_field({}, cr_result);\n",
963                bt / 4
964            ));
965        }
966
967        Ok(code)
968    }
969
970    fn generate_shift(&mut self, inst: &DecodedInstruction) -> Result<String> {
971        let mut code = String::new();
972
973        if inst.instruction.operands.len() < 3 {
974            anyhow::bail!("Shift instruction requires at least 3 operands");
975        }
976
977        let rs = match &inst.instruction.operands[0] {
978            Operand::Register(r) => *r,
979            _ => anyhow::bail!("First operand must be register"),
980        };
981        let ra = match &inst.instruction.operands[1] {
982            Operand::Register(r) => *r,
983            _ => anyhow::bail!("Second operand must be register"),
984        };
985        let sh = match &inst.instruction.operands[2] {
986            Operand::ShiftAmount(s) => *s,
987            Operand::Register(r) => {
988                // Shift amount from register
989                code.push_str(&self.indent());
990                code.push_str(&format!(
991                    "let sh_amount = ctx.get_register({}) & 0x1F;\n",
992                    r
993                ));
994                0 // Will use sh_amount variable
995            }
996            _ => anyhow::bail!("Third operand must be shift amount or register"),
997        };
998
999        // Determine shift direction (would need opcode check)
1000        code.push_str(&self.indent());
1001        if sh > 0 {
1002            code.push_str(&format!(
1003                "ctx.set_register({}, ctx.get_register({}) << {});\n",
1004                ra, rs, sh
1005            ));
1006        } else {
1007            code.push_str(&format!(
1008                "ctx.set_register({}, ctx.get_register({}) >> sh_amount);\n",
1009                ra, rs
1010            ));
1011        }
1012
1013        Ok(code)
1014    }
1015
1016    fn generate_rotate(&mut self, inst: &DecodedInstruction) -> Result<String> {
1017        let mut code = String::new();
1018
1019        if inst.instruction.operands.len() < 4 {
1020            anyhow::bail!("Rotate instruction requires 4 operands");
1021        }
1022
1023        let rs = match &inst.instruction.operands[0] {
1024            Operand::Register(r) => *r,
1025            _ => anyhow::bail!("First operand must be register"),
1026        };
1027        let ra = match &inst.instruction.operands[1] {
1028            Operand::Register(r) => *r,
1029            _ => anyhow::bail!("Second operand must be register"),
1030        };
1031        let sh = match &inst.instruction.operands[2] {
1032            Operand::ShiftAmount(s) => *s,
1033            _ => anyhow::bail!("Third operand must be shift amount"),
1034        };
1035        let mask = match &inst.instruction.operands[3] {
1036            Operand::Mask(m) => *m,
1037            _ => anyhow::bail!("Fourth operand must be mask"),
1038        };
1039
1040        code.push_str(&self.indent());
1041        code.push_str(&format!(
1042            "let rotated = ctx.get_register({}).rotate_left({} as u32);\n",
1043            rs, sh
1044        ));
1045        code.push_str(&self.indent());
1046        code.push_str(&format!(
1047            "let masked = rotated & 0x{:08X}u32;\n",
1048            mask
1049        ));
1050        code.push_str(&self.indent());
1051        code.push_str(&format!(
1052            "ctx.set_register({}, masked);\n",
1053            ra
1054        ));
1055
1056        Ok(code)
1057    }
1058
1059    fn generate_system(&mut self, inst: &DecodedInstruction) -> Result<String> {
1060        let mut code = String::new();
1061
1062        // Handle system instructions
1063        if !inst.instruction.operands.is_empty() {
1064            if let Operand::SpecialRegister(spr) = &inst.instruction.operands[0] {
1065                code.push_str(&self.indent());
1066                code.push_str(&format!(
1067                    "// System register operation: SPR {}\n",
1068                    spr
1069                ));
1070                if inst.instruction.operands.len() > 1 {
1071                    if let Operand::Register(rt) = &inst.instruction.operands[1] {
1072                        code.push_str(&self.indent());
1073                        code.push_str(&format!(
1074                            "// Move from/to SPR {} to/from r{}\n",
1075                            spr, rt
1076                        ));
1077                    }
1078                }
1079            } else {
1080                code.push_str(&self.indent());
1081                code.push_str("// Cache control or memory synchronization\n");
1082            }
1083        } else {
1084            code.push_str(&self.indent());
1085            code.push_str(&format!("// System instruction: opcode 0x{:02X}\n", inst.instruction.opcode));
1086            code.push_str(&self.indent());
1087            code.push_str("// System instructions typically require special handling\n");
1088        }
1089
1090        Ok(code)
1091    }
1092
1093    fn generate_generic(&mut self, inst: &DecodedInstruction) -> Result<String> {
1094        let mut code = String::new();
1095        code.push_str(&self.indent());
1096        code.push_str(&format!("// Instruction type: {:?}, opcode: 0x{:02X}\n",
1097            inst.instruction.instruction_type, inst.instruction.opcode));
1098        code.push_str(&self.indent());
1099        code.push_str(&format!("// Raw: 0x{:08X}\n", inst.raw));
1100        code.push_str(&self.indent());
1101        code.push_str("// TODO: Implement proper handling for this instruction\n");
1102
1103        // Try to generate at least register operations if we can identify them
1104        if !inst.instruction.operands.is_empty() {
1105            if let Operand::Register(rt) = &inst.instruction.operands[0] {
1106                code.push_str(&self.indent());
1107                code.push_str(&format!(
1108                    "// First operand is register r{}\n",
1109                    rt
1110                ));
1111            }
1112        }
1113
1114        Ok(code)
1115    }
1116
1117    fn type_to_rust(&self, ty: &crate::recompiler::analysis::TypeInfo) -> String {
1118        match ty {
1119            crate::recompiler::analysis::TypeInfo::Void => "()".to_string(),
1120            crate::recompiler::analysis::TypeInfo::Integer { signed, size } => {
1121                match (*signed, *size) {
1122                    (true, 8) => "i8".to_string(),
1123                    (false, 8) => "u8".to_string(),
1124                    (true, 16) => "i16".to_string(),
1125                    (false, 16) => "u16".to_string(),
1126                    (true, 32) => "i32".to_string(),
1127                    (false, 32) => "u32".to_string(),
1128                    (true, 64) => "i64".to_string(),
1129                    (false, 64) => "u64".to_string(),
1130                    _ => "u32".to_string(),
1131                }
1132            }
1133            crate::recompiler::analysis::TypeInfo::Pointer { pointee } => {
1134                format!("*mut {}", self.type_to_rust(pointee))
1135            }
1136            _ => "u32".to_string(),
1137        }
1138    }
1139
1140    pub fn sanitize_identifier(&self, name: &str) -> String {
1141        name.replace(' ', "_")
1142            .replace('-', "_")
1143            .replace('.', "_")
1144            .chars()
1145            .filter(|c| c.is_alphanumeric() || *c == '_')
1146            .collect()
1147    }
1148
1149    fn indent(&self) -> String {
1150        "    ".repeat(self.indent_level)
1151    }
1152}
1153
1154impl Default for CodeGenerator {
1155    fn default() -> Self {
1156        Self::new()
1157    }
1158}