Skip to main content

gcrecomp_core/recompiler/
decoder.rs

1//! PowerPC Instruction Decoder
2//!
3//! This module provides comprehensive decoding of PowerPC instructions from 32-bit words.
4//! It extracts opcodes, instruction types, and operands, with aggressive memory optimization
5//! to minimize memory footprint (saving even single bits where possible).
6//!
7//! # Memory Optimizations
8//! - `InstructionType` uses `#[repr(u8)]` to save 3 bytes per enum (4 bytes -> 1 byte)
9//! - `Operand` uses `SmallVec` for most instructions (≤4 operands) to avoid heap allocation
10//! - Structs are packed to minimize padding
11//! - Register indices use `u8` (PowerPC has 32 GPRs, fits in 5 bits)
12//!
13//! # Decoding Algorithm
14//! The decoder uses a two-stage approach:
15//! 1. Extract primary opcode (bits 26-31)
16//! 2. For opcode 31 (extended), decode secondary opcode (bits 1-10)
17//!
18//! Most PowerPC instructions have 3-4 operands, making `SmallVec<[Operand; 4]>` optimal.
19
20use anyhow::{Context, Result};
21use smallvec::SmallVec;
22
23/// PowerPC instruction representation with optimized memory layout.
24///
25/// # Memory Layout
26/// - `opcode`: 6 bits (bits 26-31 of instruction word)
27/// - `instruction_type`: 1 byte (enum with `#[repr(u8)]`)
28/// - `operands`: SmallVec with inline capacity for 4 operands (most instructions have ≤4)
29#[derive(Debug, Clone)]
30#[repr(C)] // Ensure C-compatible layout for potential FFI
31pub struct Instruction {
32    /// Primary opcode (6 bits, stored as u32 for alignment but only uses 6 bits)
33    pub opcode: u32,
34    /// Instruction type category (1 byte enum)
35    pub instruction_type: InstructionType,
36    /// Instruction operands (register, immediate, address, etc.)
37    /// Uses SmallVec to avoid heap allocation for common case (≤4 operands)
38    pub operands: SmallVec<[Operand; 4]>,
39}
40
41/// PowerPC instruction type categories.
42///
43/// # Memory Optimization
44/// Uses `#[repr(u8)]` to reduce size from 4 bytes (default enum size) to 1 byte,
45/// saving 3 bytes per instruction. This is safe because we have <256 variants.
46#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
47#[repr(u8)] // Save 3 bytes per enum (4 bytes -> 1 byte)
48pub enum InstructionType {
49    /// Arithmetic operations (add, sub, mul, div, and, or, xor, etc.)
50    Arithmetic = 0,
51    /// Branch instructions (b, bl, bc, bclr, etc.)
52    Branch = 1,
53    /// Load instructions (lwz, lbz, lhz, etc.)
54    Load = 2,
55    /// Store instructions (stw, stb, sth, etc.)
56    Store = 3,
57    /// Compare instructions (cmpw, cmplw, cmpwi, etc.)
58    Compare = 4,
59    /// Move instructions (mr, mflr, mtlr, etc.)
60    Move = 5,
61    /// System instructions (sync, isync, cache control, etc.)
62    System = 6,
63    /// Floating-point operations (fadd, fsub, fmul, fdiv, etc.)
64    FloatingPoint = 7,
65    /// Condition register operations (mfcr, mtcr, crand, cror, etc.)
66    ConditionRegister = 8,
67    /// Shift operations (slw, srw, sraw, etc.)
68    Shift = 9,
69    /// Rotate operations (rlwinm, rlwnm, etc.)
70    Rotate = 10,
71    /// Unknown or unimplemented instruction
72    Unknown = 11,
73}
74
75/// PowerPC instruction operand representation.
76///
77/// # Memory Optimization
78/// Uses appropriate integer sizes:
79/// - Register indices: `u8` (PowerPC has 32 GPRs, fits in 5 bits)
80/// - Immediate values: `i16` for 16-bit immediates, `i32` for 32-bit
81/// - Addresses: `u32` (full 32-bit address space)
82/// - Special registers: `u16` (SPR encoding uses 10 bits)
83#[derive(Debug, Clone, Copy, PartialEq, Eq)]
84pub enum Operand {
85    /// General-purpose register (GPR) - 32 registers (r0-r31), stored as u8
86    Register(u8),
87    /// Floating-point register (FPR) - 32 registers (f0-f31), stored as u8
88    FpRegister(u8),
89    /// 16-bit signed immediate value (SI field in instruction)
90    Immediate(i16),
91    /// 32-bit signed immediate value (used for branch targets, etc.)
92    Immediate32(i32),
93    /// 32-bit address (absolute or relative)
94    Address(u32),
95    /// Condition register field (4 bits, stored as u8)
96    Condition(u8),
97    /// Special-purpose register (SPR) - 10-bit encoding, stored as u16
98    SpecialRegister(u16),
99    /// Shift amount (5 bits, stored as u8)
100    ShiftAmount(u8),
101    /// Rotate mask (32 bits, stored as u32)
102    Mask(u32),
103}
104
105/// Decoded PowerPC instruction with raw word and address for reference.
106///
107/// # Memory Layout
108/// Packed to minimize padding:
109/// - `instruction`: Contains opcode, type, and operands
110/// - `raw`: Original 32-bit instruction word
111/// - `address`: Memory address where this instruction is located (for function mapping)
112#[derive(Debug, Clone)]
113pub struct DecodedInstruction {
114    /// Decoded instruction structure
115    pub instruction: Instruction,
116    /// Raw 32-bit instruction word (for debugging and re-encoding)
117    pub raw: u32,
118    /// Memory address where this instruction is located in the original binary
119    /// Used for mapping instructions to functions and control flow analysis
120    pub address: u32,
121}
122
123impl Instruction {
124    /// Decode a 32-bit PowerPC instruction word into a structured representation.
125    ///
126    /// # Algorithm
127    /// 1. Extract primary opcode (bits 26-31)
128    /// 2. For opcode 31 (extended), extract secondary opcode (bits 1-10)
129    /// 3. Extract operands based on instruction format
130    /// 4. Return decoded instruction with type and operands
131    ///
132    /// # Arguments
133    /// * `word` - 32-bit instruction word in big-endian format
134    /// * `address` - Memory address where this instruction is located (for function mapping)
135    ///
136    /// # Returns
137    /// `Result<DecodedInstruction>` - Decoded instruction or error if invalid
138    ///
139    /// # Errors
140    /// Returns error if instruction cannot be decoded (invalid opcode, malformed format)
141    ///
142    /// # Examples
143    /// ```rust
144    /// // Decode an addi instruction: addi r3, r4, 42
145    /// let word: u32 = 0x3864002A; // addi r3, r4, 42
146    /// let address: u32 = 0x80000000;
147    /// let decoded = Instruction::decode(word, address)?;
148    /// assert_eq!(decoded.instruction.instruction_type, InstructionType::Arithmetic);
149    /// assert_eq!(decoded.address, address);
150    /// ```
151    #[inline] // Hot path - called for every instruction
152    pub fn decode(word: u32, address: u32) -> Result<DecodedInstruction> {
153        // Extract primary opcode (bits 26-31)
154        let opcode: u32 = (word >> 26) & 0x3F;
155        
156        // Decode instruction type and operands based on opcode
157        let (instruction_type, operands): (InstructionType, SmallVec<[Operand; 4]>) = match opcode {
158            // Opcode 31: Extended opcodes (arithmetic, logical, shifts, etc.)
159            // Secondary opcode is in bits 1-10
160            31 => Self::decode_extended(word)?,
161            
162            // Opcode 14: Add immediate (addi)
163            // Format: addi RT, RA, SI
164            // RT = bits 21-25, RA = bits 16-20, SI = bits 0-15 (sign-extended)
165            14 => {
166                let rt: u8 = ((word >> 21) & 0x1F) as u8;
167                let ra: u8 = ((word >> 16) & 0x1F) as u8;
168                let si: i16 = (word & 0xFFFF) as i16; // Sign-extend handled by cast
169                (
170                    InstructionType::Arithmetic,
171                    SmallVec::from_slice(&[
172                        Operand::Register(rt),
173                        Operand::Register(ra),
174                        Operand::Immediate(si),
175                    ]),
176                )
177            }
178            
179            // Opcode 15: Subtract from immediate (subfic)
180            // Format: subfic RT, RA, SI
181            15 => {
182                let rt: u8 = ((word >> 21) & 0x1F) as u8;
183                let ra: u8 = ((word >> 16) & 0x1F) as u8;
184                let si: i16 = (word & 0xFFFF) as i16;
185                (
186                    InstructionType::Arithmetic,
187                    SmallVec::from_slice(&[
188                        Operand::Register(rt),
189                        Operand::Register(ra),
190                        Operand::Immediate(si),
191                    ]),
192                )
193            }
194            
195            // Opcode 32: Load word and zero (lwz)
196            // Format: lwz RT, D(RA)
197            // RT = bits 21-25, RA = bits 16-20, D = bits 0-15 (sign-extended offset)
198            32 => {
199                let rt: u8 = ((word >> 21) & 0x1F) as u8;
200                let ra: u8 = ((word >> 16) & 0x1F) as u8;
201                let d: i16 = (word & 0xFFFF) as i16;
202                (
203                    InstructionType::Load,
204                    SmallVec::from_slice(&[
205                        Operand::Register(rt),
206                        Operand::Register(ra),
207                        Operand::Immediate(d),
208                    ]),
209                )
210            }
211            
212            // Opcode 36: Store word (stw)
213            // Format: stw RS, D(RA)
214            36 => {
215                let rs: u8 = ((word >> 21) & 0x1F) as u8;
216                let ra: u8 = ((word >> 16) & 0x1F) as u8;
217                let d: i16 = (word & 0xFFFF) as i16;
218                (
219                    InstructionType::Store,
220                    SmallVec::from_slice(&[
221                        Operand::Register(rs),
222                        Operand::Register(ra),
223                        Operand::Immediate(d),
224                    ]),
225                )
226            }
227            
228            // Opcode 18: Branch (b, ba, bl, bla)
229            // Format: b LI, AA, LK
230            // LI = bits 0-23 (24-bit signed offset, aligned to 4 bytes)
231            // AA = bit 1 (absolute address flag)
232            // LK = bit 0 (link flag - save return address)
233            18 => {
234                let li: i32 = ((word & 0x3FFFFFC) as i32) >> 2; // Sign-extend and align
235                let aa: u8 = ((word >> 1) & 1) as u8;
236                let lk: u8 = (word & 1) as u8;
237                (
238                    InstructionType::Branch,
239                    SmallVec::from_slice(&[
240                        Operand::Immediate32(li),
241                        Operand::Immediate(aa as i16),
242                        Operand::Immediate(lk as i16),
243                    ]),
244                )
245            }
246            
247            // Opcode 16: Branch conditional (bc, bca, bcl, bcla)
248            // Format: bc BO, BI, BD, AA, LK
249            // BO = bits 21-25 (branch options)
250            // BI = bits 16-20 (condition register bit)
251            // BD = bits 2-15 (14-bit signed branch displacement)
252            // AA = bit 1 (absolute address flag)
253            // LK = bit 0 (link flag)
254            16 => {
255                let bo: u8 = ((word >> 21) & 0x1F) as u8;
256                let bi: u8 = ((word >> 16) & 0x1F) as u8;
257                let bd: i16 = ((word & 0xFFFC) as i16) >> 2; // Sign-extend and align
258                let aa: u8 = ((word >> 1) & 1) as u8;
259                let lk: u8 = (word & 1) as u8;
260                (
261                    InstructionType::Branch,
262                    SmallVec::from_slice(&[
263                        Operand::Condition(bo),
264                        Operand::Condition(bi),
265                        Operand::Immediate32(bd as i32),
266                        Operand::Immediate(aa as i16),
267                        Operand::Immediate(lk as i16),
268                    ]),
269                )
270            }
271            
272            // Opcode 11: Compare word immediate (cmpwi)
273            // Format: cmpwi BF, RA, SI
274            // BF = bits 23-25 (condition register field)
275            // RA = bits 16-20
276            // SI = bits 0-15 (sign-extended)
277            11 => {
278                let bf: u8 = ((word >> 23) & 0x7) as u8;
279                let ra: u8 = ((word >> 16) & 0x1F) as u8;
280                let si: i16 = (word & 0xFFFF) as i16;
281                (
282                    InstructionType::Compare,
283                    SmallVec::from_slice(&[
284                        Operand::Condition(bf),
285                        Operand::Register(ra),
286                        Operand::Immediate(si),
287                    ]),
288                )
289            }
290            
291            // Opcode 10: Compare logical word immediate (cmplwi)
292            // Format: cmplwi BF, RA, UI
293            // UI = bits 0-15 (unsigned immediate)
294            10 => {
295                let bf: u8 = ((word >> 23) & 0x7) as u8;
296                let ra: u8 = ((word >> 16) & 0x1F) as u8;
297                let ui: u16 = (word & 0xFFFF) as u16;
298                (
299                    InstructionType::Compare,
300                    SmallVec::from_slice(&[
301                        Operand::Condition(bf),
302                        Operand::Register(ra),
303                        Operand::Immediate(ui as i16), // Store as i16 for consistency
304                    ]),
305                )
306            }
307            
308            // Opcode 28: AND immediate (andi.)
309            // Format: andi. RT, RA, UI
310            28 => {
311                let rs: u8 = ((word >> 21) & 0x1F) as u8;
312                let ra: u8 = ((word >> 16) & 0x1F) as u8;
313                let ui: u16 = (word & 0xFFFF) as u16;
314                (
315                    InstructionType::Arithmetic,
316                    SmallVec::from_slice(&[
317                        Operand::Register(rs),
318                        Operand::Register(ra),
319                        Operand::Immediate(ui as i16),
320                    ]),
321                )
322            }
323            
324            // Opcode 24: OR immediate (ori)
325            // Format: ori RT, RA, UI
326            24 => {
327                let rs: u8 = ((word >> 21) & 0x1F) as u8;
328                let ra: u8 = ((word >> 16) & 0x1F) as u8;
329                let ui: u16 = (word & 0xFFFF) as u16;
330                (
331                    InstructionType::Arithmetic,
332                    SmallVec::from_slice(&[
333                        Operand::Register(rs),
334                        Operand::Register(ra),
335                        Operand::Immediate(ui as i16),
336                    ]),
337                )
338            }
339            
340            // Opcode 26: XOR immediate (xori)
341            // Format: xori RT, RA, UI
342            26 => {
343                let rs: u8 = ((word >> 21) & 0x1F) as u8;
344                let ra: u8 = ((word >> 16) & 0x1F) as u8;
345                let ui: u16 = (word & 0xFFFF) as u16;
346                (
347                    InstructionType::Arithmetic,
348                    SmallVec::from_slice(&[
349                        Operand::Register(rs),
350                        Operand::Register(ra),
351                        Operand::Immediate(ui as i16),
352                    ]),
353                )
354            }
355            
356            // Opcode 34: Load byte and zero (lbz)
357            // Format: lbz RT, D(RA)
358            34 => {
359                let rt: u8 = ((word >> 21) & 0x1F) as u8;
360                let ra: u8 = ((word >> 16) & 0x1F) as u8;
361                let d: i16 = (word & 0xFFFF) as i16;
362                (
363                    InstructionType::Load,
364                    SmallVec::from_slice(&[
365                        Operand::Register(rt),
366                        Operand::Register(ra),
367                        Operand::Immediate(d),
368                    ]),
369                )
370            }
371            
372            // Opcode 40: Load halfword and zero (lhz)
373            // Format: lhz RT, D(RA)
374            40 => {
375                let rt: u8 = ((word >> 21) & 0x1F) as u8;
376                let ra: u8 = ((word >> 16) & 0x1F) as u8;
377                let d: i16 = (word & 0xFFFF) as i16;
378                (
379                    InstructionType::Load,
380                    SmallVec::from_slice(&[
381                        Operand::Register(rt),
382                        Operand::Register(ra),
383                        Operand::Immediate(d),
384                    ]),
385                )
386            }
387            
388            // Opcode 42: Load halfword algebraic (lha)
389            // Format: lha RT, D(RA)
390            42 => {
391                let rt: u8 = ((word >> 21) & 0x1F) as u8;
392                let ra: u8 = ((word >> 16) & 0x1F) as u8;
393                let d: i16 = (word & 0xFFFF) as i16;
394                (
395                    InstructionType::Load,
396                    SmallVec::from_slice(&[
397                        Operand::Register(rt),
398                        Operand::Register(ra),
399                        Operand::Immediate(d),
400                    ]),
401                )
402            }
403            
404            // Opcode 38: Store byte (stb)
405            // Format: stb RS, D(RA)
406            38 => {
407                let rs: u8 = ((word >> 21) & 0x1F) as u8;
408                let ra: u8 = ((word >> 16) & 0x1F) as u8;
409                let d: i16 = (word & 0xFFFF) as i16;
410                (
411                    InstructionType::Store,
412                    SmallVec::from_slice(&[
413                        Operand::Register(rs),
414                        Operand::Register(ra),
415                        Operand::Immediate(d),
416                    ]),
417                )
418            }
419            
420            // Opcode 44: Store halfword (sth)
421            // Format: sth RS, D(RA)
422            44 => {
423                let rs: u8 = ((word >> 21) & 0x1F) as u8;
424                let ra: u8 = ((word >> 16) & 0x1F) as u8;
425                let d: i16 = (word & 0xFFFF) as i16;
426                (
427                    InstructionType::Store,
428                    SmallVec::from_slice(&[
429                        Operand::Register(rs),
430                        Operand::Register(ra),
431                        Operand::Immediate(d),
432                    ]),
433                )
434            }
435            
436            // Opcode 33: Load word with update (lwzu)
437            // Format: lwzu RT, D(RA) - updates RA with effective address
438            33 => {
439                let rt: u8 = ((word >> 21) & 0x1F) as u8;
440                let ra: u8 = ((word >> 16) & 0x1F) as u8;
441                let d: i16 = (word & 0xFFFF) as i16;
442                (
443                    InstructionType::Load,
444                    SmallVec::from_slice(&[
445                        Operand::Register(rt),
446                        Operand::Register(ra),
447                        Operand::Immediate(d),
448                    ]),
449                )
450            }
451            
452            // Opcode 37: Store word with update (stwu)
453            // Format: stwu RS, D(RA) - updates RA with effective address
454            37 => {
455                let rs: u8 = ((word >> 21) & 0x1F) as u8;
456                let ra: u8 = ((word >> 16) & 0x1F) as u8;
457                let d: i16 = (word & 0xFFFF) as i16;
458                (
459                    InstructionType::Store,
460                    SmallVec::from_slice(&[
461                        Operand::Register(rs),
462                        Operand::Register(ra),
463                        Operand::Immediate(d),
464                    ]),
465                )
466            }
467            
468            // Opcode 48: Floating-point load single (lfs)
469            // Format: lfs FRT, D(RA)
470            48 => {
471                let frt: u8 = ((word >> 21) & 0x1F) as u8;
472                let ra: u8 = ((word >> 16) & 0x1F) as u8;
473                let d: i16 = (word & 0xFFFF) as i16;
474                (
475                    InstructionType::FloatingPoint,
476                    SmallVec::from_slice(&[
477                        Operand::FpRegister(frt),
478                        Operand::Register(ra),
479                        Operand::Immediate(d),
480                    ]),
481                )
482            }
483            
484            // Opcode 50: Floating-point load double (lfd)
485            // Format: lfd FRT, D(RA)
486            50 => {
487                let frt: u8 = ((word >> 21) & 0x1F) as u8;
488                let ra: u8 = ((word >> 16) & 0x1F) as u8;
489                let d: i16 = (word & 0xFFFF) as i16;
490                (
491                    InstructionType::FloatingPoint,
492                    SmallVec::from_slice(&[
493                        Operand::FpRegister(frt),
494                        Operand::Register(ra),
495                        Operand::Immediate(d),
496                    ]),
497                )
498            }
499            
500            // Opcode 52: Floating-point store single (stfs)
501            // Format: stfs FRS, D(RA)
502            52 => {
503                let frs: u8 = ((word >> 21) & 0x1F) as u8;
504                let ra: u8 = ((word >> 16) & 0x1F) as u8;
505                let d: i16 = (word & 0xFFFF) as i16;
506                (
507                    InstructionType::FloatingPoint,
508                    SmallVec::from_slice(&[
509                        Operand::FpRegister(frs),
510                        Operand::Register(ra),
511                        Operand::Immediate(d),
512                    ]),
513                )
514            }
515            
516            // Opcode 54: Floating-point store double (stfd)
517            // Format: stfd FRS, D(RA)
518            54 => {
519                let frs: u8 = ((word >> 21) & 0x1F) as u8;
520                let ra: u8 = ((word >> 16) & 0x1F) as u8;
521                let d: i16 = (word & 0xFFFF) as i16;
522                (
523                    InstructionType::FloatingPoint,
524                    SmallVec::from_slice(&[
525                        Operand::FpRegister(frs),
526                        Operand::Register(ra),
527                        Operand::Immediate(d),
528                    ]),
529                )
530            }
531            
532            // Opcode 35: Load byte with update (lbzu)
533            // Format: lbzu RT, D(RA) - updates RA with effective address
534            35 => {
535                let rt: u8 = ((word >> 21) & 0x1F) as u8;
536                let ra: u8 = ((word >> 16) & 0x1F) as u8;
537                let d: i16 = (word & 0xFFFF) as i16;
538                (
539                    InstructionType::Load,
540                    SmallVec::from_slice(&[
541                        Operand::Register(rt),
542                        Operand::Register(ra),
543                        Operand::Immediate(d),
544                    ]),
545                )
546            }
547            
548            // Opcode 41: Load halfword with update (lhzu)
549            // Format: lhzu RT, D(RA) - updates RA with effective address
550            41 => {
551                let rt: u8 = ((word >> 21) & 0x1F) as u8;
552                let ra: u8 = ((word >> 16) & 0x1F) as u8;
553                let d: i16 = (word & 0xFFFF) as i16;
554                (
555                    InstructionType::Load,
556                    SmallVec::from_slice(&[
557                        Operand::Register(rt),
558                        Operand::Register(ra),
559                        Operand::Immediate(d),
560                    ]),
561                )
562            }
563            
564            // Opcode 43: Load halfword algebraic with update (lhau)
565            // Format: lhau RT, D(RA) - updates RA with effective address
566            43 => {
567                let rt: u8 = ((word >> 21) & 0x1F) as u8;
568                let ra: u8 = ((word >> 16) & 0x1F) as u8;
569                let d: i16 = (word & 0xFFFF) as i16;
570                (
571                    InstructionType::Load,
572                    SmallVec::from_slice(&[
573                        Operand::Register(rt),
574                        Operand::Register(ra),
575                        Operand::Immediate(d),
576                    ]),
577                )
578            }
579            
580            // Opcode 39: Store byte with update (stbu)
581            // Format: stbu RS, D(RA) - updates RA with effective address
582            39 => {
583                let rs: u8 = ((word >> 21) & 0x1F) as u8;
584                let ra: u8 = ((word >> 16) & 0x1F) as u8;
585                let d: i16 = (word & 0xFFFF) as i16;
586                (
587                    InstructionType::Store,
588                    SmallVec::from_slice(&[
589                        Operand::Register(rs),
590                        Operand::Register(ra),
591                        Operand::Immediate(d),
592                    ]),
593                )
594            }
595            
596            // Opcode 45: Store halfword with update (sthu)
597            // Format: sthu RS, D(RA) - updates RA with effective address
598            45 => {
599                let rs: u8 = ((word >> 21) & 0x1F) as u8;
600                let ra: u8 = ((word >> 16) & 0x1F) as u8;
601                let d: i16 = (word & 0xFFFF) as i16;
602                (
603                    InstructionType::Store,
604                    SmallVec::from_slice(&[
605                        Operand::Register(rs),
606                        Operand::Register(ra),
607                        Operand::Immediate(d),
608                    ]),
609                )
610            }
611            
612            // Opcode 49: Floating-point load single with update (lfsu)
613            // Format: lfsu FRT, D(RA) - updates RA with effective address
614            49 => {
615                let frt: u8 = ((word >> 21) & 0x1F) as u8;
616                let ra: u8 = ((word >> 16) & 0x1F) as u8;
617                let d: i16 = (word & 0xFFFF) as i16;
618                (
619                    InstructionType::FloatingPoint,
620                    SmallVec::from_slice(&[
621                        Operand::FpRegister(frt),
622                        Operand::Register(ra),
623                        Operand::Immediate(d),
624                    ]),
625                )
626            }
627            
628            // Opcode 51: Floating-point load double with update (lfdu)
629            // Format: lfdu FRT, D(RA) - updates RA with effective address
630            51 => {
631                let frt: u8 = ((word >> 21) & 0x1F) as u8;
632                let ra: u8 = ((word >> 16) & 0x1F) as u8;
633                let d: i16 = (word & 0xFFFF) as i16;
634                (
635                    InstructionType::FloatingPoint,
636                    SmallVec::from_slice(&[
637                        Operand::FpRegister(frt),
638                        Operand::Register(ra),
639                        Operand::Immediate(d),
640                    ]),
641                )
642            }
643            
644            // Opcode 53: Floating-point store single with update (stfsu)
645            // Format: stfsu FRS, D(RA) - updates RA with effective address
646            53 => {
647                let frs: u8 = ((word >> 21) & 0x1F) as u8;
648                let ra: u8 = ((word >> 16) & 0x1F) as u8;
649                let d: i16 = (word & 0xFFFF) as i16;
650                (
651                    InstructionType::FloatingPoint,
652                    SmallVec::from_slice(&[
653                        Operand::FpRegister(frs),
654                        Operand::Register(ra),
655                        Operand::Immediate(d),
656                    ]),
657                )
658            }
659            
660            // Opcode 55: Floating-point store double with update (stfdu)
661            // Format: stfdu FRS, D(RA) - updates RA with effective address
662            55 => {
663                let frs: u8 = ((word >> 21) & 0x1F) as u8;
664                let ra: u8 = ((word >> 16) & 0x1F) as u8;
665                let d: i16 = (word & 0xFFFF) as i16;
666                (
667                    InstructionType::FloatingPoint,
668                    SmallVec::from_slice(&[
669                        Operand::FpRegister(frs),
670                        Operand::Register(ra),
671                        Operand::Immediate(d),
672                    ]),
673                )
674            }
675            
676            // Opcode 0: Illegal instruction (trap)
677            // Format: trap - causes system trap
678            0 => (InstructionType::System, SmallVec::new()),
679            
680            // Opcode 1: Trap word immediate (twi)
681            // Format: twi TO, RA, SI
682            // TO = bits 6-10 (trap conditions), RA = bits 16-20, SI = bits 0-15
683            1 => {
684                let to: u8 = ((word >> 6) & 0x1F) as u8;
685                let ra: u8 = ((word >> 16) & 0x1F) as u8;
686                let si: i16 = (word & 0xFFFF) as i16;
687                (
688                    InstructionType::System,
689                    SmallVec::from_slice(&[
690                        Operand::Condition(to),
691                        Operand::Register(ra),
692                        Operand::Immediate(si),
693                    ]),
694                )
695            }
696            
697            // Opcode 2: Multiply low immediate (mulli)
698            // Format: mulli RT, RA, SI
699            2 => {
700                let rt: u8 = ((word >> 21) & 0x1F) as u8;
701                let ra: u8 = ((word >> 16) & 0x1F) as u8;
702                let si: i16 = (word & 0xFFFF) as i16;
703                (
704                    InstructionType::Arithmetic,
705                    SmallVec::from_slice(&[
706                        Operand::Register(rt),
707                        Operand::Register(ra),
708                        Operand::Immediate(si),
709                    ]),
710                )
711            }
712            
713            // Opcode 3: Subtract from immediate carrying (subfic)
714            // Already implemented as opcode 15, but opcode 3 is also used for some variants
715            // Opcode 3: Load word algebraic (lwa) - 64-bit only, not on GameCube
716            // For GameCube compatibility, treat as unknown or similar to lwz
717            3 => {
718                // On GameCube, this might be used differently, but we'll decode it as load
719                let rt: u8 = ((word >> 21) & 0x1F) as u8;
720                let ra: u8 = ((word >> 16) & 0x1F) as u8;
721                let d: i16 = (word & 0xFFFF) as i16;
722                (
723                    InstructionType::Load,
724                    SmallVec::from_slice(&[
725                        Operand::Register(rt),
726                        Operand::Register(ra),
727                        Operand::Immediate(d),
728                    ]),
729                )
730            }
731            
732            // Opcode 4: Add carrying (addc)
733            // Format: addc RT, RA, RB - handled in extended opcodes
734            // Opcode 4: Load word and reserve indexed (lwarx) - extended opcode
735            // For primary opcode 4, treat as reserved/unknown on 32-bit
736            4 => (InstructionType::Unknown, SmallVec::new()),
737            
738            // Opcode 5: Subtract from carrying (subfc)
739            // Format: subfc RT, RA, RB - handled in extended opcodes
740            // Opcode 5: Store word conditional indexed (stwcx.) - extended opcode
741            // For primary opcode 5, treat as reserved/unknown on 32-bit
742            5 => (InstructionType::Unknown, SmallVec::new()),
743            
744            // Opcode 6: Add extended (adde)
745            // Format: adde RT, RA, RB - handled in extended opcodes
746            // Opcode 6: Load double word (ld) - 64-bit only, not on GameCube
747            6 => (InstructionType::Unknown, SmallVec::new()),
748            
749            // Opcode 7: Subtract from extended (subfe)
750            // Format: subfe RT, RA, RB - handled in extended opcodes
751            // Opcode 7: Store double word (std) - 64-bit only, not on GameCube
752            7 => (InstructionType::Unknown, SmallVec::new()),
753            
754            // Opcode 8: Add extended carrying (addze)
755            // Format: addze RT, RA - handled in extended opcodes
756            // Opcode 8: Load floating-point as integer word (lfq) - not on GameCube
757            8 => (InstructionType::Unknown, SmallVec::new()),
758            
759            // Opcode 9: Subtract from extended zero (subfze)
760            // Format: subfze RT, RA - handled in extended opcodes
761            // Opcode 9: Store floating-point as integer word (stfq) - not on GameCube
762            9 => (InstructionType::Unknown, SmallVec::new()),
763            
764            // Opcode 10: Compare logical word immediate (cmplwi) - already implemented above
765            
766            // Opcode 11: Compare word immediate (cmpwi) - already implemented above
767            
768            // Opcode 12: Add immediate shifted (addis)
769            // Format: addis RT, RA, SI
770            12 => {
771                let rt: u8 = ((word >> 21) & 0x1F) as u8;
772                let ra: u8 = ((word >> 16) & 0x1F) as u8;
773                let si: i16 = (word & 0xFFFF) as i16;
774                (
775                    InstructionType::Arithmetic,
776                    SmallVec::from_slice(&[
777                        Operand::Register(rt),
778                        Operand::Register(ra),
779                        Operand::Immediate(si),
780                    ]),
781                )
782            }
783            
784            // Opcode 13: Compare immediate (cmpi)
785            // Format: cmpi BF, L, RA, SI
786            // BF = bits 23-25, L = bit 21, RA = bits 16-20, SI = bits 0-15
787            13 => {
788                let bf: u8 = ((word >> 23) & 0x7) as u8;
789                let l: u8 = ((word >> 21) & 1) as u8;
790                let ra: u8 = ((word >> 16) & 0x1F) as u8;
791                let si: i16 = (word & 0xFFFF) as i16;
792                (
793                    InstructionType::Compare,
794                    SmallVec::from_slice(&[
795                        Operand::Condition(bf),
796                        Operand::Immediate(l as i16),
797                        Operand::Register(ra),
798                        Operand::Immediate(si),
799                    ]),
800                )
801            }
802            
803            // Opcode 14: Add immediate (addi) - already implemented above
804            
805            // Opcode 15: Subtract from immediate (subfic) - already implemented above
806            
807            // Opcode 16: Branch conditional (bc) - already implemented above
808            
809            // Opcode 17: Sc (system call) - not typically used on GameCube
810            17 => (InstructionType::System, SmallVec::new()),
811            
812            // Opcode 18: Branch (b) - already implemented above
813            
814            // Opcode 19: Branch conditional to count register (bcctr)
815            // Format: bcctr BO, BI, LK
816            // BO = bits 21-25, BI = bits 16-20, LK = bit 0
817            19 => {
818                let bo: u8 = ((word >> 21) & 0x1F) as u8;
819                let bi: u8 = ((word >> 16) & 0x1F) as u8;
820                let lk: u8 = (word & 1) as u8;
821                (
822                    InstructionType::Branch,
823                    SmallVec::from_slice(&[
824                        Operand::Condition(bo),
825                        Operand::Condition(bi),
826                        Operand::Immediate(lk as i16),
827                    ]),
828                )
829            }
830            
831            // Opcode 20: Rotate left word immediate then AND with mask (rlwimi)
832            // Format: rlwimi RA, RS, SH, MB, ME
833            // Handled in extended opcodes, but primary opcode 20 is also used
834            20 => {
835                let rs: u8 = ((word >> 21) & 0x1F) as u8;
836                let ra: u8 = ((word >> 16) & 0x1F) as u8;
837                let sh: u8 = ((word >> 11) & 0x1F) as u8;
838                let mb: u8 = ((word >> 6) & 0x1F) as u8;
839                let me: u8 = (word & 0x1F) as u8;
840                let mask: u32 = compute_mask(mb, me);
841                (
842                    InstructionType::Rotate,
843                    SmallVec::from_slice(&[
844                        Operand::Register(rs),
845                        Operand::Register(ra),
846                        Operand::ShiftAmount(sh),
847                        Operand::Mask(mask),
848                    ]),
849                )
850            }
851            
852            // Opcode 21: Rotate left word immediate then AND with mask (rlwinm)
853            // Format: rlwinm RA, RS, SH, MB, ME
854            21 => {
855                let rs: u8 = ((word >> 21) & 0x1F) as u8;
856                let ra: u8 = ((word >> 16) & 0x1F) as u8;
857                let sh: u8 = ((word >> 11) & 0x1F) as u8;
858                let mb: u8 = ((word >> 6) & 0x1F) as u8;
859                let me: u8 = (word & 0x1F) as u8;
860                let mask: u32 = compute_mask(mb, me);
861                (
862                    InstructionType::Rotate,
863                    SmallVec::from_slice(&[
864                        Operand::Register(rs),
865                        Operand::Register(ra),
866                        Operand::ShiftAmount(sh),
867                        Operand::Mask(mask),
868                    ]),
869                )
870            }
871            
872            // Opcode 22: Rotate left word then AND with mask (rlwnm)
873            // Format: rlwnm RA, RS, RB, MB, ME
874            // Handled in extended opcodes
875            22 => {
876                let rs: u8 = ((word >> 21) & 0x1F) as u8;
877                let ra: u8 = ((word >> 16) & 0x1F) as u8;
878                let rb: u8 = ((word >> 11) & 0x1F) as u8;
879                let mb: u8 = ((word >> 6) & 0x1F) as u8;
880                let me: u8 = (word & 0x1F) as u8;
881                let mask: u32 = compute_mask(mb, me);
882                (
883                    InstructionType::Rotate,
884                    SmallVec::from_slice(&[
885                        Operand::Register(rs),
886                        Operand::Register(ra),
887                        Operand::Register(rb),
888                        Operand::Mask(mask),
889                    ]),
890                )
891            }
892            
893            // Opcode 23: Rotate left word immediate then OR immediate (rlwimi)
894            // Format: rlwimi RA, RS, SH, MB, ME
895            // Similar to opcode 20, but with OR semantics
896            23 => {
897                let rs: u8 = ((word >> 21) & 0x1F) as u8;
898                let ra: u8 = ((word >> 16) & 0x1F) as u8;
899                let sh: u8 = ((word >> 11) & 0x1F) as u8;
900                let mb: u8 = ((word >> 6) & 0x1F) as u8;
901                let me: u8 = (word & 0x1F) as u8;
902                let mask: u32 = compute_mask(mb, me);
903                (
904                    InstructionType::Rotate,
905                    SmallVec::from_slice(&[
906                        Operand::Register(rs),
907                        Operand::Register(ra),
908                        Operand::ShiftAmount(sh),
909                        Operand::Mask(mask),
910                    ]),
911                )
912            }
913            
914            // Opcode 24: OR immediate (ori) - already implemented above
915            
916            // Opcode 25: OR immediate shifted (oris)
917            // Format: oris RT, RA, UI
918            25 => {
919                let rt: u8 = ((word >> 21) & 0x1F) as u8;
920                let ra: u8 = ((word >> 16) & 0x1F) as u8;
921                let ui: u16 = (word & 0xFFFF) as u16;
922                (
923                    InstructionType::Arithmetic,
924                    SmallVec::from_slice(&[
925                        Operand::Register(rt),
926                        Operand::Register(ra),
927                        Operand::Immediate(ui as i16),
928                    ]),
929                )
930            }
931            
932            // Opcode 26: XOR immediate (xori) - already implemented above
933            
934            // Opcode 27: XOR immediate shifted (xoris)
935            // Format: xoris RT, RA, UI
936            27 => {
937                let rt: u8 = ((word >> 21) & 0x1F) as u8;
938                let ra: u8 = ((word >> 16) & 0x1F) as u8;
939                let ui: u16 = (word & 0xFFFF) as u16;
940                (
941                    InstructionType::Arithmetic,
942                    SmallVec::from_slice(&[
943                        Operand::Register(rt),
944                        Operand::Register(ra),
945                        Operand::Immediate(ui as i16),
946                    ]),
947                )
948            }
949            
950            // Opcode 28: AND immediate (andi.) - already implemented above
951            
952            // Opcode 29: AND immediate shifted (andis.)
953            // Format: andis. RT, RA, UI
954            29 => {
955                let rt: u8 = ((word >> 21) & 0x1F) as u8;
956                let ra: u8 = ((word >> 16) & 0x1F) as u8;
957                let ui: u16 = (word & 0xFFFF) as u16;
958                (
959                    InstructionType::Arithmetic,
960                    SmallVec::from_slice(&[
961                        Operand::Register(rt),
962                        Operand::Register(ra),
963                        Operand::Immediate(ui as i16),
964                    ]),
965                )
966            }
967            
968            // Opcode 30: Load word and reserve (lwarx)
969            // Format: lwarx RT, RA, RB
970            // Handled in extended opcodes, but primary opcode 30 is reserved
971            30 => (InstructionType::Unknown, SmallVec::new()),
972            
973            // Opcode 31: Extended opcodes - already handled above
974            
975            // Opcode 32: Load word and zero (lwz) - already implemented above
976            
977            // Opcode 33: Load word with update (lwzu) - already implemented above
978            
979            // Opcode 34: Load byte and zero (lbz) - already implemented above
980            
981            // Opcode 35: Load byte with update (lbzu) - already implemented above
982            
983            // Opcode 36: Store word (stw) - already implemented above
984            
985            // Opcode 37: Store word with update (stwu) - already implemented above
986            
987            // Opcode 38: Store byte (stb) - already implemented above
988            
989            // Opcode 39: Store byte with update (stbu) - already implemented above
990            
991            // Opcode 40: Load halfword and zero (lhz) - already implemented above
992            
993            // Opcode 41: Load halfword with update (lhzu) - already implemented above
994            
995            // Opcode 42: Load halfword algebraic (lha) - already implemented above
996            
997            // Opcode 43: Load halfword algebraic with update (lhau) - already implemented above
998            
999            // Opcode 44: Store halfword (sth) - already implemented above
1000            
1001            // Opcode 45: Store halfword with update (sthu) - already implemented above
1002            
1003            // Opcode 46: Load multiple word (lmw)
1004            // Format: lmw RT, D(RA)
1005            46 => {
1006                let rt: u8 = ((word >> 21) & 0x1F) as u8;
1007                let ra: u8 = ((word >> 16) & 0x1F) as u8;
1008                let d: i16 = (word & 0xFFFF) as i16;
1009                (
1010                    InstructionType::Load,
1011                    SmallVec::from_slice(&[
1012                        Operand::Register(rt),
1013                        Operand::Register(ra),
1014                        Operand::Immediate(d),
1015                    ]),
1016                )
1017            }
1018            
1019            // Opcode 47: Store multiple word (stmw)
1020            // Format: stmw RS, D(RA)
1021            47 => {
1022                let rs: u8 = ((word >> 21) & 0x1F) as u8;
1023                let ra: u8 = ((word >> 16) & 0x1F) as u8;
1024                let d: i16 = (word & 0xFFFF) as i16;
1025                (
1026                    InstructionType::Store,
1027                    SmallVec::from_slice(&[
1028                        Operand::Register(rs),
1029                        Operand::Register(ra),
1030                        Operand::Immediate(d),
1031                    ]),
1032                )
1033            }
1034            
1035            // Opcode 48: Floating-point load single (lfs) - already implemented above
1036            
1037            // Opcode 49: Floating-point load single with update (lfsu) - already implemented above
1038            
1039            // Opcode 50: Floating-point load double (lfd) - already implemented above
1040            
1041            // Opcode 51: Floating-point load double with update (lfdu) - already implemented above
1042            
1043            // Opcode 52: Floating-point store single (stfs) - already implemented above
1044            
1045            // Opcode 53: Floating-point store single with update (stfsu) - already implemented above
1046            
1047            // Opcode 54: Floating-point store double (stfd) - already implemented above
1048            
1049            // Opcode 55: Floating-point store double with update (stfdu) - already implemented above
1050            
1051            // Opcode 56: Load floating-point as integer word (lfiwax)
1052            // Format: lfiwax FRT, RA, RB
1053            // Handled in extended opcodes
1054            56 => (InstructionType::Unknown, SmallVec::new()),
1055            
1056            // Opcode 57: Load floating-point as integer word zero (lfiwzx)
1057            // Format: lfiwzx FRT, RA, RB
1058            // Handled in extended opcodes
1059            57 => (InstructionType::Unknown, SmallVec::new()),
1060            
1061            // Opcode 58: Store floating-point as integer word (stfiwx)
1062            // Format: stfiwx FRS, RA, RB
1063            // Handled in extended opcodes
1064            58 => (InstructionType::Unknown, SmallVec::new()),
1065            
1066            // Opcode 59: Floating-point operations (primary opcode 59)
1067            // Format: Various floating-point instructions
1068            // Handled in extended opcodes (opcode 63)
1069            59 => (InstructionType::Unknown, SmallVec::new()),
1070            
1071            // Opcode 60: Floating-point operations (primary opcode 60)
1072            // Format: Various floating-point instructions
1073            // Handled in extended opcodes (opcode 63)
1074            60 => (InstructionType::Unknown, SmallVec::new()),
1075            
1076            // Opcode 61: Floating-point operations (primary opcode 61)
1077            // Format: Various floating-point instructions
1078            // Handled in extended opcodes (opcode 63)
1079            61 => (InstructionType::Unknown, SmallVec::new()),
1080            
1081            // Opcode 62: Floating-point operations (primary opcode 62)
1082            // Format: Various floating-point instructions
1083            // Handled in extended opcodes (opcode 63)
1084            62 => (InstructionType::Unknown, SmallVec::new()),
1085            
1086            // Opcode 63: Floating-point operations
1087            // Format: Various floating-point instructions (fadd, fsub, fmul, fdiv, etc.)
1088            // Handled in extended opcodes
1089            63 => Self::decode_extended(word)?,
1090            
1091            // Opcode 31 with specific patterns for move instructions
1092            // Move from link register (mflr) - extended opcode 8
1093            31 if ((word >> 21) & 0x1F) == 8 && (word & 0x7FF) == 0 => {
1094                let rt: u8 = ((word >> 21) & 0x1F) as u8;
1095                (
1096                    InstructionType::Move,
1097                    SmallVec::from_slice(&[Operand::Register(rt)]),
1098                )
1099            }
1100            // Move to link register (mtlr) - extended opcode 9
1101            31 if ((word >> 21) & 0x1F) == 9 && (word & 0x7FF) == 0 => {
1102                let rs: u8 = ((word >> 21) & 0x1F) as u8;
1103                (
1104                    InstructionType::Move,
1105                    SmallVec::from_slice(&[Operand::Register(rs)]),
1106                )
1107            }
1108            // Move from count register (mfctr) - extended opcode 9, sub-opcode 9
1109            31 if ((word >> 21) & 0x1F) == 9 && ((word >> 11) & 0x1F) == 9 && (word & 0x7FF) == 0 => {
1110                let rt: u8 = ((word >> 21) & 0x1F) as u8;
1111                (
1112                    InstructionType::Move,
1113                    SmallVec::from_slice(&[Operand::Register(rt)]),
1114                )
1115            }
1116            // Move to count register (mtctr) - extended opcode 9, sub-opcode 9
1117            31 if ((word >> 21) & 0x1F) == 9 && ((word >> 11) & 0x1F) == 9 && (word & 0x7FF) == 0 => {
1118                let rs: u8 = ((word >> 21) & 0x1F) as u8;
1119                (
1120                    InstructionType::Move,
1121                    SmallVec::from_slice(&[Operand::Register(rs)]),
1122                )
1123            }
1124            
1125            // Unknown opcode - return unknown instruction type
1126            _ => (InstructionType::Unknown, SmallVec::new()),
1127        };
1128
1129        Ok(DecodedInstruction {
1130            instruction: Instruction {
1131                opcode,
1132                instruction_type,
1133                operands,
1134            },
1135            raw: word,
1136            address,
1137        })
1138    }
1139
1140    /// Decode extended opcodes (opcode 31 instructions).
1141    ///
1142    /// Extended opcodes use a secondary opcode field in bits 1-10 of the instruction word.
1143    /// This function handles arithmetic, logical, shift, rotate, floating-point, and system instructions.
1144    ///
1145    /// # Arguments
1146    /// * `word` - 32-bit instruction word with opcode 31
1147    ///
1148    /// # Returns
1149    /// `Result<(InstructionType, SmallVec<[Operand; 4]>)>` - Instruction type and operands
1150    #[inline] // Hot path for extended opcodes
1151    fn decode_extended(word: u32) -> Result<(InstructionType, SmallVec<[Operand; 4]>)> {
1152    // Extract secondary opcode (bits 1-10)
1153    let extended_opcode: u32 = (word >> 1) & 0x3FF;
1154    
1155    // Extract common register fields
1156    let ra: u8 = ((word >> 16) & 0x1F) as u8;
1157    let rb: u8 = ((word >> 11) & 0x1F) as u8;
1158    let rs: u8 = ((word >> 21) & 0x1F) as u8;
1159    let rt: u8 = ((word >> 21) & 0x1F) as u8;
1160    let rc: bool = (word & 1) != 0; // Record bit (update condition register)
1161    
1162    // Check for specific instruction patterns first (move instructions)
1163    // Move from link register (mflr) - RT field = 8, all other fields = 0
1164    if ((word >> 21) & 0x1F) == 8 && (word & 0x7FF) == 0 {
1165        return Ok((
1166            InstructionType::Move,
1167            SmallVec::from_slice(&[Operand::Register(rt)]),
1168        ));
1169    }
1170    // Move to link register (mtlr) - RS field = 9, all other fields = 0
1171    if ((word >> 21) & 0x1F) == 9 && (word & 0x7FF) == 0 {
1172        return Ok((
1173            InstructionType::Move,
1174            SmallVec::from_slice(&[Operand::Register(rs)]),
1175        ));
1176    }
1177    
1178    // Decode based on extended opcode
1179    match extended_opcode {
1180        // Extended opcode 266: Add (add)
1181        // Format: add RT, RA, RB
1182        // Only if primary opcode is 31 (not 63)
1183        266 if (word >> 26) == 31 => Ok((
1184            InstructionType::Arithmetic,
1185            SmallVec::from_slice(&[
1186                Operand::Register(rt),
1187                Operand::Register(ra),
1188                Operand::Register(rb),
1189            ]),
1190        )),
1191        
1192        // Extended opcode 40: Subtract from (subf)
1193        // Format: subf RT, RA, RB (RT = RB - RA)
1194        // Only if primary opcode is 31 (not 63, which is fneg)
1195        40 if (word >> 26) == 31 => Ok((
1196            InstructionType::Arithmetic,
1197            SmallVec::from_slice(&[
1198                Operand::Register(rt),
1199                Operand::Register(ra),
1200                Operand::Register(rb),
1201            ]),
1202        )),
1203        
1204        // Extended opcode 138: Add carrying (addc)
1205        // Format: addc RT, RA, RB (RT = RA + RB, with carry)
1206        138 => Ok((
1207            InstructionType::Arithmetic,
1208            SmallVec::from_slice(&[
1209                Operand::Register(rt),
1210                Operand::Register(ra),
1211                Operand::Register(rb),
1212            ]),
1213        )),
1214        
1215        // Extended opcode 10: Add extended (adde)
1216        // Format: adde RT, RA, RB (RT = RA + RB + CA, with carry)
1217        10 => Ok((
1218            InstructionType::Arithmetic,
1219            SmallVec::from_slice(&[
1220                Operand::Register(rt),
1221                Operand::Register(ra),
1222                Operand::Register(rb),
1223            ]),
1224        )),
1225        
1226        // Extended opcode 202: Add extended carrying (addze)
1227        // Format: addze RT, RA (RT = RA + CA, with carry)
1228        202 => Ok((
1229            InstructionType::Arithmetic,
1230            SmallVec::from_slice(&[
1231                Operand::Register(rt),
1232                Operand::Register(ra),
1233            ]),
1234        )),
1235        
1236        // Extended opcode 234: Add to minus one extended (addme)
1237        // Format: addme RT, RA (RT = RA + CA - 1, with carry)
1238        234 => Ok((
1239            InstructionType::Arithmetic,
1240            SmallVec::from_slice(&[
1241                Operand::Register(rt),
1242                Operand::Register(ra),
1243            ]),
1244        )),
1245        
1246        // Extended opcode 74: Subtract from extended zero (subfze)
1247        // Format: subfze RT, RA (RT = CA - RA - 1, with carry)
1248        74 => Ok((
1249            InstructionType::Arithmetic,
1250            SmallVec::from_slice(&[
1251                Operand::Register(rt),
1252                Operand::Register(ra),
1253            ]),
1254        )),
1255        
1256        // Extended opcode 106: Subtract from minus one extended (subfme)
1257        // Format: subfme RT, RA (RT = CA - RA - 2, with carry)
1258        106 => Ok((
1259            InstructionType::Arithmetic,
1260            SmallVec::from_slice(&[
1261                Operand::Register(rt),
1262                Operand::Register(ra),
1263            ]),
1264        )),
1265        
1266        // Extended opcode 75: Negate (neg)
1267        // Format: neg RT, RA (RT = -RA)
1268        75 => Ok((
1269            InstructionType::Arithmetic,
1270            SmallVec::from_slice(&[
1271                Operand::Register(rt),
1272                Operand::Register(ra),
1273            ]),
1274        )),
1275        
1276        // Extended opcode 104: Negate with overflow (nego)
1277        // Format: nego RT, RA (RT = -RA, sets overflow)
1278        104 if (word >> 26) == 31 && ra != 0 => Ok((
1279            InstructionType::Arithmetic,
1280            SmallVec::from_slice(&[
1281                Operand::Register(rt),
1282                Operand::Register(ra),
1283            ]),
1284        )),
1285        
1286        // Extended opcode 232: Add carrying with overflow (addco)
1287        // Format: addco RT, RA, RB (RT = RA + RB, with carry and overflow)
1288        232 => Ok((
1289            InstructionType::Arithmetic,
1290            SmallVec::from_slice(&[
1291                Operand::Register(rt),
1292                Operand::Register(ra),
1293                Operand::Register(rb),
1294            ]),
1295        )),
1296        
1297        // Extended opcode 233: Add extended with overflow (addeo)
1298        // Format: addeo RT, RA, RB (RT = RA + RB + CA, with carry and overflow)
1299        233 if (word >> 26) == 31 => Ok((
1300            InstructionType::Arithmetic,
1301            SmallVec::from_slice(&[
1302                Operand::Register(rt),
1303                Operand::Register(ra),
1304                Operand::Register(rb),
1305            ]),
1306        )),
1307        
1308        // Extended opcode 234: Add to minus one extended with overflow (addmeo)
1309        // Format: addmeo RT, RA (RT = RA + CA - 1, with carry and overflow)
1310        234 if (word >> 26) == 31 => Ok((
1311            InstructionType::Arithmetic,
1312            SmallVec::from_slice(&[
1313                Operand::Register(rt),
1314                Operand::Register(ra),
1315            ]),
1316        )),
1317        
1318        // Extended opcode 202: Add extended carrying with overflow (addzeo)
1319        // Format: addzeo RT, RA (RT = RA + CA, with carry and overflow)
1320        202 if (word >> 26) == 31 => Ok((
1321            InstructionType::Arithmetic,
1322            SmallVec::from_slice(&[
1323                Operand::Register(rt),
1324                Operand::Register(ra),
1325            ]),
1326        )),
1327        
1328        // Extended opcode 8: Subtract from carrying with overflow (subfco)
1329        // Format: subfco RT, RA, RB (RT = RB - RA, with carry and overflow)
1330        8 if (word >> 26) == 31 => Ok((
1331            InstructionType::Arithmetic,
1332            SmallVec::from_slice(&[
1333                Operand::Register(rt),
1334                Operand::Register(ra),
1335                Operand::Register(rb),
1336            ]),
1337        )),
1338        
1339        // Extended opcode 136: Subtract from extended with overflow (subfeo)
1340        // Format: subfeo RT, RA, RB (RT = RB - RA - (1 - CA), with carry and overflow)
1341        136 if (word >> 26) == 31 && ra != 0 => Ok((
1342            InstructionType::Arithmetic,
1343            SmallVec::from_slice(&[
1344                Operand::Register(rt),
1345                Operand::Register(ra),
1346                Operand::Register(rb),
1347            ]),
1348        )),
1349        
1350        // Extended opcode 74: Subtract from extended zero with overflow (subfzeo)
1351        // Format: subfzeo RT, RA (RT = CA - RA - 1, with carry and overflow)
1352        74 if (word >> 26) == 31 => Ok((
1353            InstructionType::Arithmetic,
1354            SmallVec::from_slice(&[
1355                Operand::Register(rt),
1356                Operand::Register(ra),
1357            ]),
1358        )),
1359        
1360        // Extended opcode 106: Subtract from minus one extended with overflow (subfmeo)
1361        // Format: subfmeo RT, RA (RT = CA - RA - 2, with carry and overflow)
1362        106 if (word >> 26) == 31 => Ok((
1363            InstructionType::Arithmetic,
1364            SmallVec::from_slice(&[
1365                Operand::Register(rt),
1366                Operand::Register(ra),
1367            ]),
1368        )),
1369        
1370        // Extended opcode 107: Multiply low word with overflow (mullwo)
1371        // Format: mullwo RT, RA, RB (RT = RA * RB, sets overflow)
1372        107 => Ok((
1373            InstructionType::Arithmetic,
1374            SmallVec::from_slice(&[
1375                Operand::Register(rt),
1376                Operand::Register(ra),
1377                Operand::Register(rb),
1378            ]),
1379        )),
1380        
1381        // Extended opcode 200: Divide word with overflow (divwo)
1382        // Format: divwo RT, RA, RB (RT = RA / RB, sets overflow)
1383        200 if (word >> 26) == 31 => Ok((
1384            InstructionType::Arithmetic,
1385            SmallVec::from_slice(&[
1386                Operand::Register(rt),
1387                Operand::Register(ra),
1388                Operand::Register(rb),
1389            ]),
1390        )),
1391        
1392        // Extended opcode 201: Divide word unsigned with overflow (divwuo)
1393        // Format: divwuo RT, RA, RB (RT = RA / RB unsigned, sets overflow)
1394        201 => Ok((
1395            InstructionType::Arithmetic,
1396            SmallVec::from_slice(&[
1397                Operand::Register(rt),
1398                Operand::Register(ra),
1399                Operand::Register(rb),
1400            ]),
1401        )),
1402        
1403        // Extended opcode 235: Multiply low word (mullw)
1404        // Format: mullw RT, RA, RB
1405        235 => Ok((
1406            InstructionType::Arithmetic,
1407            SmallVec::from_slice(&[
1408                Operand::Register(rt),
1409                Operand::Register(ra),
1410                Operand::Register(rb),
1411            ]),
1412        )),
1413        
1414        // Extended opcode 233: Multiply high word (mulhw)
1415        // Format: mulhw RT, RA, RB
1416        233 => Ok((
1417            InstructionType::Arithmetic,
1418            SmallVec::from_slice(&[
1419                Operand::Register(rt),
1420                Operand::Register(ra),
1421                Operand::Register(rb),
1422            ]),
1423        )),
1424        
1425        // Extended opcode 11: Multiply high word unsigned (mulhwu)
1426        // Format: mulhwu RT, RA, RB
1427        11 => Ok((
1428            InstructionType::Arithmetic,
1429            SmallVec::from_slice(&[
1430                Operand::Register(rt),
1431                Operand::Register(ra),
1432                Operand::Register(rb),
1433            ]),
1434        )),
1435        
1436        // Extended opcode 200: Divide word unsigned (divwu)
1437        // Format: divwu RT, RA, RB (RT = RA / RB, unsigned)
1438        200 => Ok((
1439            InstructionType::Arithmetic,
1440            SmallVec::from_slice(&[
1441                Operand::Register(rt),
1442                Operand::Register(ra),
1443                Operand::Register(rb),
1444            ]),
1445        )),
1446        
1447        // Extended opcode 104: Divide word (divw) - already implemented above
1448        // Extended opcode 40: Subtract from (subf) - already implemented above
1449        
1450        // Extended opcode 8: Subtract from carrying (subfc)
1451        // Format: subfc RT, RA, RB (RT = RB - RA, with carry)
1452        8 => Ok((
1453            InstructionType::Arithmetic,
1454            SmallVec::from_slice(&[
1455                Operand::Register(rt),
1456                Operand::Register(ra),
1457                Operand::Register(rb),
1458            ]),
1459        )),
1460        
1461        // Extended opcode 136: Subtract from extended (subfe)
1462        // Format: subfe RT, RA, RB (RT = RB - RA - (1 - CA), with carry)
1463        // Only if primary opcode is 31 (not 63, which is fnabs)
1464        136 if (word >> 26) == 31 => Ok((
1465            InstructionType::Arithmetic,
1466            SmallVec::from_slice(&[
1467                Operand::Register(rt),
1468                Operand::Register(ra),
1469                Operand::Register(rb),
1470            ]),
1471        )),
1472        
1473        // Extended opcode 104: Divide word (divw)
1474        // Format: divw RT, RA, RB (RT = RA / RB)
1475        // Only if primary opcode is 31 (not 63)
1476        104 if (word >> 26) == 31 => Ok((
1477            InstructionType::Arithmetic,
1478            SmallVec::from_slice(&[
1479                Operand::Register(rt),
1480                Operand::Register(ra),
1481                Operand::Register(rb),
1482            ]),
1483        )),
1484        
1485        // Extended opcode 28: AND (and)
1486        // Format: and RS, RA, RB
1487        // Only if primary opcode is 31 (not 63)
1488        28 if (word >> 26) == 31 => Ok((
1489            InstructionType::Arithmetic,
1490            SmallVec::from_slice(&[
1491                Operand::Register(rs),
1492                Operand::Register(ra),
1493                Operand::Register(rb),
1494            ]),
1495        )),
1496        
1497        // Extended opcode 60: AND with complement (andc)
1498        // Format: andc RS, RA, RB (RS = RA & ~RB)
1499        60 => Ok((
1500            InstructionType::Arithmetic,
1501            SmallVec::from_slice(&[
1502                Operand::Register(rs),
1503                Operand::Register(ra),
1504                Operand::Register(rb),
1505            ]),
1506        )),
1507        
1508        // Extended opcode 444: OR (or)
1509        // Format: or RS, RA, RB
1510        // Only if primary opcode is 31 (not 63)
1511        444 if (word >> 26) == 31 => Ok((
1512            InstructionType::Arithmetic,
1513            SmallVec::from_slice(&[
1514                Operand::Register(rs),
1515                Operand::Register(ra),
1516                Operand::Register(rb),
1517            ]),
1518        )),
1519        
1520        // Extended opcode 412: OR with complement (orc)
1521        // Format: orc RS, RA, RB (RS = RA | ~RB)
1522        412 => Ok((
1523            InstructionType::Arithmetic,
1524            SmallVec::from_slice(&[
1525                Operand::Register(rs),
1526                Operand::Register(ra),
1527                Operand::Register(rb),
1528            ]),
1529        )),
1530        
1531        // Extended opcode 316: XOR (xor)
1532        // Format: xor RS, RA, RB
1533        // Only if primary opcode is 31 (not 63)
1534        316 if (word >> 26) == 31 => Ok((
1535            InstructionType::Arithmetic,
1536            SmallVec::from_slice(&[
1537                Operand::Register(rs),
1538                Operand::Register(ra),
1539                Operand::Register(rb),
1540            ]),
1541        )),
1542        
1543        // Extended opcode 476: NAND (nand)
1544        // Format: nand RS, RA, RB
1545        // Only if primary opcode is 31 (not 63)
1546        476 if (word >> 26) == 31 => Ok((
1547            InstructionType::Arithmetic,
1548            SmallVec::from_slice(&[
1549                Operand::Register(rs),
1550                Operand::Register(ra),
1551                Operand::Register(rb),
1552            ]),
1553        )),
1554        
1555        // Extended opcode 124: NOR (nor)
1556        // Format: nor RS, RA, RB
1557        // Only if primary opcode is 31 (not 63)
1558        124 if (word >> 26) == 31 => Ok((
1559            InstructionType::Arithmetic,
1560            SmallVec::from_slice(&[
1561                Operand::Register(rs),
1562                Operand::Register(ra),
1563                Operand::Register(rb),
1564            ]),
1565        )),
1566        
1567        // Extended opcode 284: Equivalent (eqv)
1568        // Format: eqv RS, RA, RB (RS = ~(RA ^ RB))
1569        284 => Ok((
1570            InstructionType::Arithmetic,
1571            SmallVec::from_slice(&[
1572                Operand::Register(rs),
1573                Operand::Register(ra),
1574                Operand::Register(rb),
1575            ]),
1576        )),
1577        
1578        // Extended opcode 24: Shift left word (slw)
1579        // Format: slw RA, RS, RB (RA = RS << (RB & 0x1F))
1580        // Only if primary opcode is 31 (not 63)
1581        24 if (word >> 26) == 31 => {
1582            let sh: u8 = ((word >> 11) & 0x1F) as u8;
1583            Ok((
1584                InstructionType::Shift,
1585                SmallVec::from_slice(&[
1586                    Operand::Register(rs),
1587                    Operand::Register(ra),
1588                    Operand::ShiftAmount(sh),
1589                ]),
1590            ))
1591        }
1592        
1593        // Extended opcode 536: Shift right word (srw)
1594        // Format: srw RA, RS, RB (RA = RS >> (RB & 0x1F))
1595        // Only if primary opcode is 31 (not 63)
1596        536 if (word >> 26) == 31 => {
1597            let sh: u8 = ((word >> 11) & 0x1F) as u8;
1598            Ok((
1599                InstructionType::Shift,
1600                SmallVec::from_slice(&[
1601                    Operand::Register(rs),
1602                    Operand::Register(ra),
1603                    Operand::ShiftAmount(sh),
1604                ]),
1605            ))
1606        }
1607        
1608        // Extended opcode 824: Shift left word immediate (slwi)
1609        // Format: slwi RA, RS, SH (RA = RS << SH)
1610        // This is actually rlwinm with MB=0, ME=31-SH
1611        824 => {
1612            let sh: u8 = ((word >> 11) & 0x1F) as u8;
1613            Ok((
1614                InstructionType::Shift,
1615                SmallVec::from_slice(&[
1616                    Operand::Register(rs),
1617                    Operand::Register(ra),
1618                    Operand::ShiftAmount(sh),
1619                ]),
1620            ))
1621        }
1622        
1623        // Extended opcode 792: Shift right word immediate (srwi)
1624        // Format: srwi RA, RS, SH (RA = RS >> SH)
1625        // This is actually rlwinm with SH=32-SH, MB=SH, ME=31
1626        792 if (word >> 26) == 31 => {
1627            let sh: u8 = ((word >> 11) & 0x1F) as u8;
1628            Ok((
1629                InstructionType::Shift,
1630                SmallVec::from_slice(&[
1631                    Operand::Register(rs),
1632                    Operand::Register(ra),
1633                    Operand::ShiftAmount(sh),
1634                ]),
1635            ))
1636        }
1637        
1638        // Extended opcode 794: Shift right algebraic word (sraw)
1639        // Format: sraw RA, RS, RB (arithmetic right shift)
1640        794 => {
1641            let sh: u8 = ((word >> 11) & 0x1F) as u8;
1642            Ok((
1643                InstructionType::Shift,
1644                SmallVec::from_slice(&[
1645                    Operand::Register(rs),
1646                    Operand::Register(ra),
1647                    Operand::ShiftAmount(sh),
1648                ]),
1649            ))
1650        }
1651        
1652        // Extended opcode 826: Shift right algebraic word immediate (srawi)
1653        // Format: srawi RA, RS, SH (arithmetic right shift by immediate)
1654        826 => {
1655            let sh: u8 = ((word >> 11) & 0x1F) as u8;
1656            Ok((
1657                InstructionType::Shift,
1658                SmallVec::from_slice(&[
1659                    Operand::Register(rs),
1660                    Operand::Register(ra),
1661                    Operand::ShiftAmount(sh),
1662                ]),
1663            ))
1664        }
1665        
1666        // Extended opcode 26: Count leading zeros word (cntlzw)
1667        // Format: cntlzw RA, RS
1668        26 => Ok((
1669            InstructionType::Arithmetic,
1670            SmallVec::from_slice(&[
1671                Operand::Register(rs),
1672                Operand::Register(ra),
1673            ]),
1674        )),
1675        
1676        // Extended opcode 0: Compare word (cmpw)
1677        // Format: cmpw BF, RA, RB
1678        // Only if primary opcode is 31 and extended opcode is 0
1679        0 if (word >> 26) == 31 && ((word >> 1) & 0x3FF) == 0 => {
1680            let bf: u8 = ((word >> 23) & 0x7) as u8;
1681            Ok((
1682                InstructionType::Compare,
1683                SmallVec::from_slice(&[
1684                    Operand::Condition(bf),
1685                    Operand::Register(ra),
1686                    Operand::Register(rb),
1687                ]),
1688            ))
1689        }
1690        
1691        // Extended opcode 32: Compare logical word (cmplw)
1692        // Format: cmplw BF, RA, RB
1693        32 => {
1694            let bf: u8 = ((word >> 23) & 0x7) as u8;
1695            Ok((
1696                InstructionType::Compare,
1697                SmallVec::from_slice(&[
1698                    Operand::Condition(bf),
1699                    Operand::Register(ra),
1700                    Operand::Register(rb),
1701                ]),
1702            ))
1703        }
1704        
1705        // Extended opcode 20: Load word and reserve indexed (lwarx)
1706        // Format: lwarx RT, RA, RB (load word and set reservation)
1707        20 if (word >> 26) == 31 => Ok((
1708            InstructionType::Load,
1709            SmallVec::from_slice(&[
1710                Operand::Register(rt),
1711                Operand::Register(ra),
1712                Operand::Register(rb),
1713            ]),
1714        )),
1715        
1716        // Extended opcode 23: Load word indexed (lwzx)
1717        // Format: lwzx RT, RA, RB
1718        23 => Ok((
1719            InstructionType::Load,
1720            SmallVec::from_slice(&[
1721                Operand::Register(rt),
1722                Operand::Register(ra),
1723                Operand::Register(rb),
1724            ]),
1725        )),
1726        
1727        // Extended opcode 150: Store word conditional indexed (stwcx.)
1728        // Format: stwcx. RS, RA, RB (store word conditional, sets CR0)
1729        150 if (word >> 26) == 31 => Ok((
1730            InstructionType::Store,
1731            SmallVec::from_slice(&[
1732                Operand::Register(rs),
1733                Operand::Register(ra),
1734                Operand::Register(rb),
1735            ]),
1736        )),
1737        
1738        // Extended opcode 87: Load byte indexed (lbzx)
1739        // Format: lbzx RT, RA, RB
1740        87 => Ok((
1741            InstructionType::Load,
1742            SmallVec::from_slice(&[
1743                Operand::Register(rt),
1744                Operand::Register(ra),
1745                Operand::Register(rb),
1746            ]),
1747        )),
1748        
1749        // Extended opcode 279: Load halfword indexed (lhzx)
1750        // Format: lhzx RT, RA, RB
1751        279 => Ok((
1752            InstructionType::Load,
1753            SmallVec::from_slice(&[
1754                Operand::Register(rt),
1755                Operand::Register(ra),
1756                Operand::Register(rb),
1757            ]),
1758        )),
1759        
1760        // Extended opcode 343: Load halfword algebraic indexed (lhax)
1761        // Format: lhax RT, RA, RB
1762        343 => Ok((
1763            InstructionType::Load,
1764            SmallVec::from_slice(&[
1765                Operand::Register(rt),
1766                Operand::Register(ra),
1767                Operand::Register(rb),
1768            ]),
1769        )),
1770        
1771        // Extended opcode 151: Store word indexed (stwx)
1772        // Format: stwx RS, RA, RB
1773        151 => Ok((
1774            InstructionType::Store,
1775            SmallVec::from_slice(&[
1776                Operand::Register(rs),
1777                Operand::Register(ra),
1778                Operand::Register(rb),
1779            ]),
1780        )),
1781        
1782        // Extended opcode 215: Store byte indexed (stbx)
1783        // Format: stbx RS, RA, RB
1784        215 => Ok((
1785            InstructionType::Store,
1786            SmallVec::from_slice(&[
1787                Operand::Register(rs),
1788                Operand::Register(ra),
1789                Operand::Register(rb),
1790            ]),
1791        )),
1792        
1793        // Extended opcode 407: Store halfword indexed (sthx)
1794        // Format: sthx RS, RA, RB
1795        407 => Ok((
1796            InstructionType::Store,
1797            SmallVec::from_slice(&[
1798                Operand::Register(rs),
1799                Operand::Register(ra),
1800                Operand::Register(rb),
1801            ]),
1802        )),
1803        
1804        // Extended opcode 55: Load word with update indexed (lwzux)
1805        // Format: lwzux RT, RA, RB - updates RA with effective address
1806        55 => Ok((
1807            InstructionType::Load,
1808            SmallVec::from_slice(&[
1809                Operand::Register(rt),
1810                Operand::Register(ra),
1811                Operand::Register(rb),
1812            ]),
1813        )),
1814        
1815        // Extended opcode 119: Load byte with update indexed (lbzux)
1816        // Format: lbzux RT, RA, RB - updates RA with effective address
1817        119 => Ok((
1818            InstructionType::Load,
1819            SmallVec::from_slice(&[
1820                Operand::Register(rt),
1821                Operand::Register(ra),
1822                Operand::Register(rb),
1823            ]),
1824        )),
1825        
1826        // Extended opcode 311: Load halfword with update indexed (lhzux)
1827        // Format: lhzux RT, RA, RB - updates RA with effective address
1828        311 => Ok((
1829            InstructionType::Load,
1830            SmallVec::from_slice(&[
1831                Operand::Register(rt),
1832                Operand::Register(ra),
1833                Operand::Register(rb),
1834            ]),
1835        )),
1836        
1837        // Extended opcode 375: Store word with update indexed (stwux)
1838        // Format: stwux RS, RA, RB - updates RA with effective address
1839        375 => Ok((
1840            InstructionType::Store,
1841            SmallVec::from_slice(&[
1842                Operand::Register(rs),
1843                Operand::Register(ra),
1844                Operand::Register(rb),
1845            ]),
1846        )),
1847        
1848        // Extended opcode 439: Store byte with update indexed (stbux)
1849        // Format: stbux RS, RA, RB - updates RA with effective address
1850        439 => Ok((
1851            InstructionType::Store,
1852            SmallVec::from_slice(&[
1853                Operand::Register(rs),
1854                Operand::Register(ra),
1855                Operand::Register(rb),
1856            ]),
1857        )),
1858        
1859        // Extended opcode 695: Store halfword with update indexed (sthux)
1860        // Format: sthux RS, RA, RB - updates RA with effective address
1861        695 => Ok((
1862            InstructionType::Store,
1863            SmallVec::from_slice(&[
1864                Operand::Register(rs),
1865                Operand::Register(ra),
1866                Operand::Register(rb),
1867            ]),
1868        )),
1869        
1870        // Extended opcode 567: Floating-point load single indexed (lfsx)
1871        // Format: lfsx FRT, RA, RB
1872        567 => {
1873            let frt: u8 = ((word >> 21) & 0x1F) as u8;
1874            Ok((
1875                InstructionType::FloatingPoint,
1876                SmallVec::from_slice(&[
1877                    Operand::FpRegister(frt),
1878                    Operand::Register(ra),
1879                    Operand::Register(rb),
1880                ]),
1881            ))
1882        }
1883        
1884        // Extended opcode 599: Floating-point load double indexed (lfdx)
1885        // Format: lfdx FRT, RA, RB
1886        599 => {
1887            let frt: u8 = ((word >> 21) & 0x1F) as u8;
1888            Ok((
1889                InstructionType::FloatingPoint,
1890                SmallVec::from_slice(&[
1891                    Operand::FpRegister(frt),
1892                    Operand::Register(ra),
1893                    Operand::Register(rb),
1894                ]),
1895            ))
1896        }
1897        
1898        // Extended opcode 663: Floating-point store single indexed (stfsx)
1899        // Format: stfsx FRS, RA, RB
1900        663 => {
1901            let frs: u8 = ((word >> 21) & 0x1F) as u8;
1902            Ok((
1903                InstructionType::FloatingPoint,
1904                SmallVec::from_slice(&[
1905                    Operand::FpRegister(frs),
1906                    Operand::Register(ra),
1907                    Operand::Register(rb),
1908                ]),
1909            ))
1910        }
1911        
1912        // Extended opcode 727: Floating-point store double indexed (stfdx)
1913        // Format: stfdx FRS, RA, RB
1914        727 => {
1915            let frs: u8 = ((word >> 21) & 0x1F) as u8;
1916            Ok((
1917                InstructionType::FloatingPoint,
1918                SmallVec::from_slice(&[
1919                    Operand::FpRegister(frs),
1920                    Operand::Register(ra),
1921                    Operand::Register(rb),
1922                ]),
1923            ))
1924        }
1925        
1926        // Extended opcode 597: Load multiple word (lmw)
1927        // Format: lmw RT, D(RA) - loads words from RA+D to RT, RT+1, ..., RT+31
1928        // Note: Conflicts with lswi, but lmw uses primary opcode 46, lswi uses extended opcode
1929        // This is handled in primary opcode 46
1930        
1931        // Extended opcode 533: Store multiple word (stmw)
1932        // Format: stmw RS, D(RA) - stores words from RS, RS+1, ..., RS+31 to RA+D
1933        // Note: Conflicts with stswi, but stmw uses primary opcode 47, stswi uses extended opcode
1934        // This is handled in primary opcode 47
1935        
1936        // Extended opcode 16: Branch to link register (blr)
1937        // Format: blr - branch to address in link register
1938        16 if (word & 0x03E00001) == 0x00000001 => Ok((
1939            InstructionType::Branch,
1940            SmallVec::from_slice(&[Operand::Register(0)]), // Placeholder for LR
1941        )),
1942        
1943        // Extended opcode 528: Branch to count register (bctr)
1944        // Format: bctr - branch to address in count register
1945        // Only if primary opcode is 31 (not 63)
1946        528 if (word >> 26) == 31 && (word & 0x03E00001) == 0x00000001 => Ok((
1947            InstructionType::Branch,
1948            SmallVec::from_slice(&[Operand::Register(9)]), // Placeholder for CTR
1949        )),
1950        
1951        // Extended opcode 528: Branch conditional to count register (bcctr)
1952        // Format: bcctr BO, BI - conditional branch to CTR
1953        // Only if primary opcode is 31 (not 63)
1954        528 if (word >> 26) == 31 => {
1955            let bo: u8 = ((word >> 21) & 0x1F) as u8;
1956            let bi: u8 = ((word >> 16) & 0x1F) as u8;
1957            Ok((
1958                InstructionType::Branch,
1959                SmallVec::from_slice(&[
1960                    Operand::Condition(bo),
1961                    Operand::Condition(bi),
1962                ]),
1963            ))
1964        }
1965        
1966        // Extended opcode 16: Branch conditional to link register (bclr)
1967        // Format: bclr BO, BI - conditional branch to LR
1968        // Only if primary opcode is 31 (not 63)
1969        16 if (word >> 26) == 31 => {
1970            let bo: u8 = ((word >> 21) & 0x1F) as u8;
1971            let bi: u8 = ((word >> 16) & 0x1F) as u8;
1972            Ok((
1973                InstructionType::Branch,
1974                SmallVec::from_slice(&[
1975                    Operand::Condition(bo),
1976                    Operand::Condition(bi),
1977                ]),
1978            ))
1979        }
1980        
1981        // Extended opcode 21: Rotate left word immediate then mask insert (rlwinm)
1982        // Format: rlwinm RA, RS, SH, MB, ME
1983        // Only if primary opcode is 31 (to distinguish from floating-point add)
1984        21 if (word >> 26) == 31 => {
1985            let sh: u8 = ((word >> 11) & 0x1F) as u8;
1986            let mb: u8 = ((word >> 6) & 0x1F) as u8;
1987            let me: u8 = (word & 0x1F) as u8;
1988            let mask: u32 = compute_mask(mb, me);
1989            Ok((
1990                InstructionType::Rotate,
1991                SmallVec::from_slice(&[
1992                    Operand::Register(rs),
1993                    Operand::Register(ra),
1994                    Operand::ShiftAmount(sh),
1995                    Operand::Mask(mask),
1996                ]),
1997            ))
1998        }
1999        
2000        // Extended opcode 20: Rotate left word then AND with mask (rlwnm)
2001        // Format: rlwnm RA, RS, RB, MB, ME
2002        // Only if primary opcode is 31
2003        20 if (word >> 26) == 31 => {
2004            let mb: u8 = ((word >> 6) & 0x1F) as u8;
2005            let me: u8 = (word & 0x1F) as u8;
2006            let mask: u32 = compute_mask(mb, me);
2007            Ok((
2008                InstructionType::Rotate,
2009                SmallVec::from_slice(&[
2010                    Operand::Register(rs),
2011                    Operand::Register(ra),
2012                    Operand::Register(rb),
2013                    Operand::Mask(mask),
2014                ]),
2015            ))
2016        }
2017        
2018        // Extended opcode 19: Rotate left word immediate then mask insert (rlwimi)
2019        // Format: rlwimi RA, RS, SH, MB, ME
2020        // Only if primary opcode is 31
2021        19 if (word >> 26) == 31 => {
2022            let sh: u8 = ((word >> 11) & 0x1F) as u8;
2023            let mb: u8 = ((word >> 6) & 0x1F) as u8;
2024            let me: u8 = (word & 0x1F) as u8;
2025            let mask: u32 = compute_mask(mb, me);
2026            Ok((
2027                InstructionType::Rotate,
2028                SmallVec::from_slice(&[
2029                    Operand::Register(rs),
2030                    Operand::Register(ra),
2031                    Operand::ShiftAmount(sh),
2032                    Operand::Mask(mask),
2033                ]),
2034            ))
2035        }
2036        
2037        // Extended opcode 21: Floating-point add (fadd)
2038        // Format: fadd FRT, FRA, FRB
2039        // Only if primary opcode is 63 (floating-point instruction)
2040        21 => {
2041            let frt: u8 = ((word >> 21) & 0x1F) as u8;
2042            let fra: u8 = ((word >> 16) & 0x1F) as u8;
2043            let frb: u8 = ((word >> 11) & 0x1F) as u8;
2044            Ok((
2045                InstructionType::FloatingPoint,
2046                SmallVec::from_slice(&[
2047                    Operand::FpRegister(frt),
2048                    Operand::FpRegister(fra),
2049                    Operand::FpRegister(frb),
2050                ]),
2051            ))
2052        }
2053        
2054        // Extended opcode 20: Floating-point subtract (fsub)
2055        // Format: fsub FRT, FRA, FRB
2056        20 => {
2057            let frt: u8 = ((word >> 21) & 0x1F) as u8;
2058            let fra: u8 = ((word >> 16) & 0x1F) as u8;
2059            let frb: u8 = ((word >> 11) & 0x1F) as u8;
2060            Ok((
2061                InstructionType::FloatingPoint,
2062                SmallVec::from_slice(&[
2063                    Operand::FpRegister(frt),
2064                    Operand::FpRegister(fra),
2065                    Operand::FpRegister(frb),
2066                ]),
2067            ))
2068        }
2069        
2070        // Extended opcode 25: Floating-point multiply (fmul)
2071        // Format: fmul FRT, FRA, FRC, FRB (FRA * FRC for some variants)
2072        // Only if primary opcode is 63
2073        25 if (word >> 26) == 63 => {
2074            let frt: u8 = ((word >> 21) & 0x1F) as u8;
2075            let fra: u8 = ((word >> 16) & 0x1F) as u8;
2076            let frc: u8 = ((word >> 6) & 0x1F) as u8;
2077            let frb: u8 = ((word >> 11) & 0x1F) as u8;
2078            Ok((
2079                InstructionType::FloatingPoint,
2080                SmallVec::from_slice(&[
2081                    Operand::FpRegister(frt),
2082                    Operand::FpRegister(fra),
2083                    Operand::FpRegister(frc),
2084                    Operand::FpRegister(frb),
2085                ]),
2086            ))
2087        }
2088        
2089        // Extended opcode 14: Floating-point multiply-add (fmadd)
2090        // Format: fmadd FRT, FRA, FRC, FRB (FRT = FRA * FRC + FRB)
2091        // Only if primary opcode is 63
2092        14 if (word >> 26) == 63 => {
2093            let frt: u8 = ((word >> 21) & 0x1F) as u8;
2094            let fra: u8 = ((word >> 16) & 0x1F) as u8;
2095            let frc: u8 = ((word >> 6) & 0x1F) as u8;
2096            let frb: u8 = ((word >> 11) & 0x1F) as u8;
2097            Ok((
2098                InstructionType::FloatingPoint,
2099                SmallVec::from_slice(&[
2100                    Operand::FpRegister(frt),
2101                    Operand::FpRegister(fra),
2102                    Operand::FpRegister(frc),
2103                    Operand::FpRegister(frb),
2104                ]),
2105            ))
2106        }
2107        
2108        // Extended opcode 15: Floating-point multiply-subtract (fmsub)
2109        // Format: fmsub FRT, FRA, FRC, FRB (FRT = FRA * FRC - FRB)
2110        // Only if primary opcode is 63
2111        15 if (word >> 26) == 63 => {
2112            let frt: u8 = ((word >> 21) & 0x1F) as u8;
2113            let fra: u8 = ((word >> 16) & 0x1F) as u8;
2114            let frc: u8 = ((word >> 6) & 0x1F) as u8;
2115            let frb: u8 = ((word >> 11) & 0x1F) as u8;
2116            Ok((
2117                InstructionType::FloatingPoint,
2118                SmallVec::from_slice(&[
2119                    Operand::FpRegister(frt),
2120                    Operand::FpRegister(fra),
2121                    Operand::FpRegister(frc),
2122                    Operand::FpRegister(frb),
2123                ]),
2124            ))
2125        }
2126        
2127        // Extended opcode 28: Floating-point negative multiply-add (fnmadd)
2128        // Format: fnmadd FRT, FRA, FRC, FRB (FRT = -(FRA * FRC + FRB))
2129        // Only if primary opcode is 63
2130        28 if (word >> 26) == 63 => {
2131            let frt: u8 = ((word >> 21) & 0x1F) as u8;
2132            let fra: u8 = ((word >> 16) & 0x1F) as u8;
2133            let frc: u8 = ((word >> 6) & 0x1F) as u8;
2134            let frb: u8 = ((word >> 11) & 0x1F) as u8;
2135            Ok((
2136                InstructionType::FloatingPoint,
2137                SmallVec::from_slice(&[
2138                    Operand::FpRegister(frt),
2139                    Operand::FpRegister(fra),
2140                    Operand::FpRegister(frc),
2141                    Operand::FpRegister(frb),
2142                ]),
2143            ))
2144        }
2145        
2146        // Extended opcode 29: Floating-point negative multiply-subtract (fnmsub)
2147        // Format: fnmsub FRT, FRA, FRC, FRB (FRT = -(FRA * FRC - FRB))
2148        // Only if primary opcode is 63
2149        29 if (word >> 26) == 63 => {
2150            let frt: u8 = ((word >> 21) & 0x1F) as u8;
2151            let fra: u8 = ((word >> 16) & 0x1F) as u8;
2152            let frc: u8 = ((word >> 6) & 0x1F) as u8;
2153            let frb: u8 = ((word >> 11) & 0x1F) as u8;
2154            Ok((
2155                InstructionType::FloatingPoint,
2156                SmallVec::from_slice(&[
2157                    Operand::FpRegister(frt),
2158                    Operand::FpRegister(fra),
2159                    Operand::FpRegister(frc),
2160                    Operand::FpRegister(frb),
2161                ]),
2162            ))
2163        }
2164        
2165        // Extended opcode 32: Floating-point square root (fsqrt)
2166        // Format: fsqrt FRT, FRB
2167        // Only if primary opcode is 63
2168        32 if (word >> 26) == 63 => {
2169            let frt: u8 = ((word >> 21) & 0x1F) as u8;
2170            let frb: u8 = ((word >> 11) & 0x1F) as u8;
2171            Ok((
2172                InstructionType::FloatingPoint,
2173                SmallVec::from_slice(&[
2174                    Operand::FpRegister(frt),
2175                    Operand::FpRegister(frb),
2176                ]),
2177            ))
2178        }
2179        
2180        // Extended opcode 33: Floating-point square root single (fsqrts)
2181        // Format: fsqrts FRT, FRB
2182        // Only if primary opcode is 63
2183        33 if (word >> 26) == 63 => {
2184            let frt: u8 = ((word >> 21) & 0x1F) as u8;
2185            let frb: u8 = ((word >> 11) & 0x1F) as u8;
2186            Ok((
2187                InstructionType::FloatingPoint,
2188                SmallVec::from_slice(&[
2189                    Operand::FpRegister(frt),
2190                    Operand::FpRegister(frb),
2191                ]),
2192            ))
2193        }
2194        
2195        // Extended opcode 38: Floating-point select (fsel)
2196        // Format: fsel FRT, FRA, FRC, FRB (FRT = FRA >= 0 ? FRC : FRB)
2197        // Only if primary opcode is 63
2198        38 if (word >> 26) == 63 => {
2199            let frt: u8 = ((word >> 21) & 0x1F) as u8;
2200            let fra: u8 = ((word >> 16) & 0x1F) as u8;
2201            let frc: u8 = ((word >> 6) & 0x1F) as u8;
2202            let frb: u8 = ((word >> 11) & 0x1F) as u8;
2203            Ok((
2204                InstructionType::FloatingPoint,
2205                SmallVec::from_slice(&[
2206                    Operand::FpRegister(frt),
2207                    Operand::FpRegister(fra),
2208                    Operand::FpRegister(frc),
2209                    Operand::FpRegister(frb),
2210                ]),
2211            ))
2212        }
2213        
2214        // Extended opcode 72: Floating-point move register (fmr)
2215        // Format: fmr FRT, FRB
2216        // Only if primary opcode is 63
2217        72 if (word >> 26) == 63 => {
2218            let frt: u8 = ((word >> 21) & 0x1F) as u8;
2219            let frb: u8 = ((word >> 11) & 0x1F) as u8;
2220            Ok((
2221                InstructionType::FloatingPoint,
2222                SmallVec::from_slice(&[
2223                    Operand::FpRegister(frt),
2224                    Operand::FpRegister(frb),
2225                ]),
2226            ))
2227        }
2228        
2229        // Extended opcode 583: Floating-point move from integer word (fctiw)
2230        // Format: fctiw FRT, FRB (convert integer word to FP)
2231        // Only if primary opcode is 63
2232        583 if (word >> 26) == 63 => {
2233            let frt: u8 = ((word >> 21) & 0x1F) as u8;
2234            let frb: u8 = ((word >> 11) & 0x1F) as u8;
2235            Ok((
2236                InstructionType::FloatingPoint,
2237                SmallVec::from_slice(&[
2238                    Operand::FpRegister(frt),
2239                    Operand::FpRegister(frb),
2240                ]),
2241            ))
2242        }
2243        
2244        // Extended opcode 711: Floating-point move from integer word zero (fctiwz)
2245        // Format: fctiwz FRT, FRB (convert integer word to FP, zero upper)
2246        // Only if primary opcode is 63
2247        711 if (word >> 26) == 63 => {
2248            let frt: u8 = ((word >> 21) & 0x1F) as u8;
2249            let frb: u8 = ((word >> 11) & 0x1F) as u8;
2250            Ok((
2251                InstructionType::FloatingPoint,
2252                SmallVec::from_slice(&[
2253                    Operand::FpRegister(frt),
2254                    Operand::FpRegister(frb),
2255                ]),
2256            ))
2257        }
2258        
2259        // Extended opcode 815: Floating-point move to integer word zero (fctiwz)
2260        // Format: fctiwz FRT, FRB (convert FP to integer word, round toward zero)
2261        // Only if primary opcode is 63
2262        815 if (word >> 26) == 63 => {
2263            let frt: u8 = ((word >> 21) & 0x1F) as u8;
2264            let frb: u8 = ((word >> 11) & 0x1F) as u8;
2265            Ok((
2266                InstructionType::FloatingPoint,
2267                SmallVec::from_slice(&[
2268                    Operand::FpRegister(frt),
2269                    Operand::FpRegister(frb),
2270                ]),
2271            ))
2272        }
2273        
2274        // Extended opcode 70: Floating-point move to condition register (mffs)
2275        // Format: mffs FRT (move FPSCR to FRT)
2276        // Only if primary opcode is 63
2277        70 if (word >> 26) == 63 => {
2278            let frt: u8 = ((word >> 21) & 0x1F) as u8;
2279            Ok((
2280                InstructionType::FloatingPoint,
2281                SmallVec::from_slice(&[Operand::FpRegister(frt)]),
2282            ))
2283        }
2284        
2285        // Extended opcode 134: Floating-point move from condition register (mtfsf)
2286        // Format: mtfsf BF, FRB (move FRB to FPSCR field BF)
2287        // Only if primary opcode is 63
2288        134 if (word >> 26) == 63 => {
2289            let bf: u8 = ((word >> 23) & 0x7) as u8;
2290            let frb: u8 = ((word >> 11) & 0x1F) as u8;
2291            Ok((
2292                InstructionType::FloatingPoint,
2293                SmallVec::from_slice(&[
2294                    Operand::Condition(bf),
2295                    Operand::FpRegister(frb),
2296                ]),
2297            ))
2298        }
2299        
2300        // Extended opcode 711: Floating-point move from condition register field (mtfsfi)
2301        // Format: mtfsfi BF, IMM (move immediate to FPSCR field BF)
2302        // Only if primary opcode is 63
2303        711 if (word >> 26) == 63 && ((word >> 12) & 0x7) != 0 => {
2304            let bf: u8 = ((word >> 23) & 0x7) as u8;
2305            let imm: u8 = ((word >> 12) & 0xF) as u8;
2306            Ok((
2307                InstructionType::FloatingPoint,
2308                SmallVec::from_slice(&[
2309                    Operand::Condition(bf),
2310                    Operand::Immediate(imm as i16),
2311                ]),
2312            ))
2313        }
2314        
2315        // Extended opcode 18: Floating-point divide (fdiv)
2316        // Format: fdiv FRT, FRA, FRB
2317        // Only if primary opcode is 63
2318        18 if (word >> 26) == 63 => {
2319            let frt: u8 = ((word >> 21) & 0x1F) as u8;
2320            let fra: u8 = ((word >> 16) & 0x1F) as u8;
2321            let frb: u8 = ((word >> 11) & 0x1F) as u8;
2322            Ok((
2323                InstructionType::FloatingPoint,
2324                SmallVec::from_slice(&[
2325                    Operand::FpRegister(frt),
2326                    Operand::FpRegister(fra),
2327                    Operand::FpRegister(frb),
2328                ]),
2329            ))
2330        }
2331        
2332        // Extended opcode 0: Floating-point compare (fcmpu/fcmpo)
2333        // Format: fcmpu BF, FRA, FRB
2334        // Only if primary opcode is 63
2335        0 if (word >> 26) == 63 => {
2336            let bf: u8 = ((word >> 23) & 0x7) as u8;
2337            let fra: u8 = ((word >> 16) & 0x1F) as u8;
2338            let frb: u8 = ((word >> 11) & 0x1F) as u8;
2339            Ok((
2340                InstructionType::FloatingPoint,
2341                SmallVec::from_slice(&[
2342                    Operand::Condition(bf),
2343                    Operand::FpRegister(fra),
2344                    Operand::FpRegister(frb),
2345                ]),
2346            ))
2347        }
2348        
2349        // Extended opcode 15: Floating-point convert to integer word (fctiw)
2350        // Format: fctiw FRT, FRB
2351        // Only if primary opcode is 63
2352        15 if (word >> 26) == 63 => {
2353            let frt: u8 = ((word >> 21) & 0x1F) as u8;
2354            let frb: u8 = ((word >> 11) & 0x1F) as u8;
2355            Ok((
2356                InstructionType::FloatingPoint,
2357                SmallVec::from_slice(&[
2358                    Operand::FpRegister(frt),
2359                    Operand::FpRegister(frb),
2360                ]),
2361            ))
2362        }
2363        
2364        // Extended opcode 31: Floating-point convert to integer word with round toward zero (fctiwz)
2365        // Format: fctiwz FRT, FRB
2366        // Only if primary opcode is 63
2367        31 if (word >> 26) == 63 => {
2368            let frt: u8 = ((word >> 21) & 0x1F) as u8;
2369            let frb: u8 = ((word >> 11) & 0x1F) as u8;
2370            Ok((
2371                InstructionType::FloatingPoint,
2372                SmallVec::from_slice(&[
2373                    Operand::FpRegister(frt),
2374                    Operand::FpRegister(frb),
2375                ]),
2376            ))
2377        }
2378        
2379        // Extended opcode 12: Floating-point round to single precision (frsp)
2380        // Format: frsp FRT, FRB
2381        // Only if primary opcode is 63
2382        12 if (word >> 26) == 63 => {
2383            let frt: u8 = ((word >> 21) & 0x1F) as u8;
2384            let frb: u8 = ((word >> 11) & 0x1F) as u8;
2385            Ok((
2386                InstructionType::FloatingPoint,
2387                SmallVec::from_slice(&[
2388                    Operand::FpRegister(frt),
2389                    Operand::FpRegister(frb),
2390                ]),
2391            ))
2392        }
2393        
2394        // Extended opcode 264: Floating-point absolute value (fabs)
2395        // Format: fabs FRT, FRB
2396        // Only if primary opcode is 63
2397        264 if (word >> 26) == 63 => {
2398            let frt: u8 = ((word >> 21) & 0x1F) as u8;
2399            let frb: u8 = ((word >> 11) & 0x1F) as u8;
2400            Ok((
2401                InstructionType::FloatingPoint,
2402                SmallVec::from_slice(&[
2403                    Operand::FpRegister(frt),
2404                    Operand::FpRegister(frb),
2405                ]),
2406            ))
2407        }
2408        
2409        // Extended opcode 136: Floating-point negative absolute value (fnabs)
2410        // Format: fnabs FRT, FRB
2411        // Only if primary opcode is 63
2412        136 if (word >> 26) == 63 => {
2413            let frt: u8 = ((word >> 21) & 0x1F) as u8;
2414            let frb: u8 = ((word >> 11) & 0x1F) as u8;
2415            Ok((
2416                InstructionType::FloatingPoint,
2417                SmallVec::from_slice(&[
2418                    Operand::FpRegister(frt),
2419                    Operand::FpRegister(frb),
2420                ]),
2421            ))
2422        }
2423        
2424        // Extended opcode 40: Floating-point negate (fneg)
2425        // Format: fneg FRT, FRB
2426        // Only if primary opcode is 63
2427        40 if (word >> 26) == 63 => {
2428            let frt: u8 = ((word >> 21) & 0x1F) as u8;
2429            let frb: u8 = ((word >> 11) & 0x1F) as u8;
2430            Ok((
2431                InstructionType::FloatingPoint,
2432                SmallVec::from_slice(&[
2433                    Operand::FpRegister(frt),
2434                    Operand::FpRegister(frb),
2435                ]),
2436            ))
2437        }
2438        
2439        // Extended opcode 339: Move from special-purpose register (mfspr)
2440        // Format: mfspr RT, SPR
2441        // SPR encoding: ((SPR[0:4] << 5) | SPR[5:9])
2442        339 => {
2443            let rt: u8 = ((word >> 21) & 0x1F) as u8;
2444            let spr: u16 = ((((word >> 16) & 0x1F) << 5) | ((word >> 11) & 0x1F)) as u16;
2445            Ok((
2446                InstructionType::System,
2447                SmallVec::from_slice(&[
2448                    Operand::Register(rt),
2449                    Operand::SpecialRegister(spr),
2450                ]),
2451            ))
2452        }
2453
2454        // Extended opcode 467: Move to special-purpose register (mtspr)
2455        // Format: mtspr SPR, RS
2456        467 => {
2457            let rs: u8 = ((word >> 21) & 0x1F) as u8;
2458            let spr: u16 = ((((word >> 16) & 0x1F) << 5) | ((word >> 11) & 0x1F)) as u16;
2459            Ok((
2460                InstructionType::System,
2461                SmallVec::from_slice(&[
2462                    Operand::Register(rs),
2463                    Operand::SpecialRegister(spr),
2464                ]),
2465            ))
2466        }
2467        
2468        // Extended opcode 19: Move from condition register (mfcr)
2469        // Format: mfcr RT
2470        // Only if primary opcode is 31 (not 63)
2471        19 if (word >> 26) == 31 => {
2472            let rt: u8 = ((word >> 21) & 0x1F) as u8;
2473            Ok((
2474                InstructionType::ConditionRegister,
2475                SmallVec::from_slice(&[Operand::Register(rt)]),
2476            ))
2477        }
2478        
2479        // Extended opcode 83: Move from condition register field (mfcrf)
2480        // Format: mfcrf RT, CRM (move specific CR field)
2481        83 => {
2482            let rt: u8 = ((word >> 21) & 0x1F) as u8;
2483            let crm: u8 = ((word >> 12) & 0xFF) as u8;
2484            Ok((
2485                InstructionType::ConditionRegister,
2486                SmallVec::from_slice(&[
2487                    Operand::Register(rt),
2488                    Operand::Condition(crm),
2489                ]),
2490            ))
2491        }
2492        
2493        // Extended opcode 144: Move to condition register (mtcr)
2494        // Format: mtcr RS
2495        // Only if primary opcode is 31 (not 63)
2496        144 if (word >> 26) == 31 => {
2497            let rs: u8 = ((word >> 21) & 0x1F) as u8;
2498            Ok((
2499                InstructionType::ConditionRegister,
2500                SmallVec::from_slice(&[Operand::Register(rs)]),
2501            ))
2502        }
2503        
2504        // Extended opcode 146: Move to condition register field (mtcrf)
2505        // Format: mtcrf CRM, RS (move to specific CR field)
2506        146 => {
2507            let rs: u8 = ((word >> 21) & 0x1F) as u8;
2508            let crm: u8 = ((word >> 12) & 0xFF) as u8;
2509            Ok((
2510                InstructionType::ConditionRegister,
2511                SmallVec::from_slice(&[
2512                    Operand::Register(rs),
2513                    Operand::Condition(crm),
2514                ]),
2515            ))
2516        }
2517        
2518        // Extended opcode 210: Move from XER (mfxer)
2519        // Format: mfxer RT
2520        210 => {
2521            let rt: u8 = ((word >> 21) & 0x1F) as u8;
2522            Ok((
2523                InstructionType::System,
2524                SmallVec::from_slice(&[Operand::Register(rt)]),
2525            ))
2526        }
2527        
2528        // Extended opcode 242: Move to XER (mtxer)
2529        // Format: mtxer RS
2530        242 => {
2531            let rs: u8 = ((word >> 21) & 0x1F) as u8;
2532            Ok((
2533                InstructionType::System,
2534                SmallVec::from_slice(&[Operand::Register(rs)]),
2535            ))
2536        }
2537        
2538        // Extended opcode 512: Move from link register (mflr)
2539        // Format: mflr RT
2540        512 => {
2541            let rt: u8 = ((word >> 21) & 0x1F) as u8;
2542            Ok((
2543                InstructionType::Move,
2544                SmallVec::from_slice(&[Operand::Register(rt)]),
2545            ))
2546        }
2547        
2548        // Extended opcode 576: Move to link register (mtlr)
2549        // Format: mtlr RS
2550        576 => {
2551            let rs: u8 = ((word >> 21) & 0x1F) as u8;
2552            Ok((
2553                InstructionType::Move,
2554                SmallVec::from_slice(&[Operand::Register(rs)]),
2555            ))
2556        }
2557        
2558        // Extended opcode 528: Move from count register (mfctr)
2559        // Format: mfctr RT
2560        528 if (word >> 26) == 31 => {
2561            let rt: u8 = ((word >> 21) & 0x1F) as u8;
2562            Ok((
2563                InstructionType::Move,
2564                SmallVec::from_slice(&[Operand::Register(rt)]),
2565            ))
2566        }
2567        
2568        // Extended opcode 592: Move to count register (mtctr)
2569        // Format: mtctr RS
2570        592 => {
2571            let rs: u8 = ((word >> 21) & 0x1F) as u8;
2572            Ok((
2573                InstructionType::Move,
2574                SmallVec::from_slice(&[Operand::Register(rs)]),
2575            ))
2576        }
2577        
2578        // Extended opcode 257: Condition register AND (crand)
2579        // Format: crand BT, BA, BB
2580        257 => {
2581            let bt: u8 = ((word >> 21) & 0x1F) as u8;
2582            let ba: u8 = ((word >> 16) & 0x1F) as u8;
2583            let bb: u8 = ((word >> 11) & 0x1F) as u8;
2584            Ok((
2585                InstructionType::ConditionRegister,
2586                SmallVec::from_slice(&[
2587                    Operand::Condition(bt),
2588                    Operand::Condition(ba),
2589                    Operand::Condition(bb),
2590                ]),
2591            ))
2592        }
2593        
2594        // Extended opcode 449: Condition register OR (cror)
2595        // Format: cror BT, BA, BB
2596        449 => {
2597            let bt: u8 = ((word >> 21) & 0x1F) as u8;
2598            let ba: u8 = ((word >> 16) & 0x1F) as u8;
2599            let bb: u8 = ((word >> 11) & 0x1F) as u8;
2600            Ok((
2601                InstructionType::ConditionRegister,
2602                SmallVec::from_slice(&[
2603                    Operand::Condition(bt),
2604                    Operand::Condition(ba),
2605                    Operand::Condition(bb),
2606                ]),
2607            ))
2608        }
2609        
2610        // Extended opcode 193: Condition register XOR (crxor)
2611        // Format: crxor BT, BA, BB
2612        193 => {
2613            let bt: u8 = ((word >> 21) & 0x1F) as u8;
2614            let ba: u8 = ((word >> 16) & 0x1F) as u8;
2615            let bb: u8 = ((word >> 11) & 0x1F) as u8;
2616            Ok((
2617                InstructionType::ConditionRegister,
2618                SmallVec::from_slice(&[
2619                    Operand::Condition(bt),
2620                    Operand::Condition(ba),
2621                    Operand::Condition(bb),
2622                ]),
2623            ))
2624        }
2625        
2626        // Extended opcode 225: Condition register NAND (crnand)
2627        // Format: crnand BT, BA, BB
2628        225 => {
2629            let bt: u8 = ((word >> 21) & 0x1F) as u8;
2630            let ba: u8 = ((word >> 16) & 0x1F) as u8;
2631            let bb: u8 = ((word >> 11) & 0x1F) as u8;
2632            Ok((
2633                InstructionType::ConditionRegister,
2634                SmallVec::from_slice(&[
2635                    Operand::Condition(bt),
2636                    Operand::Condition(ba),
2637                    Operand::Condition(bb),
2638                ]),
2639            ))
2640        }
2641        
2642        // Extended opcode 33: Condition register NOR (crnor)
2643        // Format: crnor BT, BA, BB
2644        33 => {
2645            let bt: u8 = ((word >> 21) & 0x1F) as u8;
2646            let ba: u8 = ((word >> 16) & 0x1F) as u8;
2647            let bb: u8 = ((word >> 11) & 0x1F) as u8;
2648            Ok((
2649                InstructionType::ConditionRegister,
2650                SmallVec::from_slice(&[
2651                    Operand::Condition(bt),
2652                    Operand::Condition(ba),
2653                    Operand::Condition(bb),
2654                ]),
2655            ))
2656        }
2657        
2658        // Extended opcode 289: Condition register equivalent (creqv)
2659        // Format: creqv BT, BA, BB
2660        289 => {
2661            let bt: u8 = ((word >> 21) & 0x1F) as u8;
2662            let ba: u8 = ((word >> 16) & 0x1F) as u8;
2663            let bb: u8 = ((word >> 11) & 0x1F) as u8;
2664            Ok((
2665                InstructionType::ConditionRegister,
2666                SmallVec::from_slice(&[
2667                    Operand::Condition(bt),
2668                    Operand::Condition(ba),
2669                    Operand::Condition(bb),
2670                ]),
2671            ))
2672        }
2673        
2674        // Extended opcode 129: Condition register AND with complement (crandc)
2675        // Format: crandc BT, BA, BB
2676        129 => {
2677            let bt: u8 = ((word >> 21) & 0x1F) as u8;
2678            let ba: u8 = ((word >> 16) & 0x1F) as u8;
2679            let bb: u8 = ((word >> 11) & 0x1F) as u8;
2680            Ok((
2681                InstructionType::ConditionRegister,
2682                SmallVec::from_slice(&[
2683                    Operand::Condition(bt),
2684                    Operand::Condition(ba),
2685                    Operand::Condition(bb),
2686                ]),
2687            ))
2688        }
2689        
2690        // Extended opcode 417: Condition register OR with complement (crorc)
2691        // Format: crorc BT, BA, BB
2692        417 => {
2693            let bt: u8 = ((word >> 21) & 0x1F) as u8;
2694            let ba: u8 = ((word >> 16) & 0x1F) as u8;
2695            let bb: u8 = ((word >> 11) & 0x1F) as u8;
2696            Ok((
2697                InstructionType::ConditionRegister,
2698                SmallVec::from_slice(&[
2699                    Operand::Condition(bt),
2700                    Operand::Condition(ba),
2701                    Operand::Condition(bb),
2702                ]),
2703            ))
2704        }
2705        
2706        // Cache control instructions (system instructions)
2707        // Extended opcode 86: Data cache block flush (dcbf)
2708        // Format: dcbf RA, RB
2709        86 => Ok((
2710            InstructionType::System,
2711            SmallVec::from_slice(&[
2712                Operand::Register(ra),
2713                Operand::Register(rb),
2714            ]),
2715        )),
2716        // Extended opcode 54: Data cache block store (dcbst)
2717        // Format: dcbst RA, RB
2718        54 => Ok((
2719            InstructionType::System,
2720            SmallVec::from_slice(&[
2721                Operand::Register(ra),
2722                Operand::Register(rb),
2723            ]),
2724        )),
2725        // Extended opcode 278: Data cache block touch (dcbt)
2726        // Format: dcbt RA, RB
2727        278 => Ok((
2728            InstructionType::System,
2729            SmallVec::from_slice(&[
2730                Operand::Register(ra),
2731                Operand::Register(rb),
2732            ]),
2733        )),
2734        // Extended opcode 246: Data cache block touch for store (dcbtst)
2735        // Format: dcbtst RA, RB
2736        246 => Ok((
2737            InstructionType::System,
2738            SmallVec::from_slice(&[
2739                Operand::Register(ra),
2740                Operand::Register(rb),
2741            ]),
2742        )),
2743        // Extended opcode 1014: Data cache block set to zero (dcbz)
2744        // Format: dcbz RA, RB
2745        1014 => Ok((
2746            InstructionType::System,
2747            SmallVec::from_slice(&[
2748                Operand::Register(ra),
2749                Operand::Register(rb),
2750            ]),
2751        )),
2752        // Extended opcode 470: Instruction cache block invalidate (icbi)
2753        // Format: icbi RA, RB
2754        470 => Ok((
2755            InstructionType::System,
2756            SmallVec::from_slice(&[
2757                Operand::Register(ra),
2758                Operand::Register(rb),
2759            ]),
2760        )),
2761        
2762        // Memory synchronization instructions
2763        // Extended opcode 598: Synchronize (sync)
2764        598 => Ok((InstructionType::System, SmallVec::new())),
2765        // Extended opcode 150: Instruction synchronize (isync)
2766        150 => Ok((InstructionType::System, SmallVec::new())),
2767        // Extended opcode 854: Enforce in-order execution of I/O (eieio)
2768        854 => Ok((InstructionType::System, SmallVec::new())),
2769        
2770        // String operations (rare on GameCube, but included for completeness)
2771        // Extended opcode 597: Load string word immediate (lswi)
2772        // Format: lswi RT, RA, NB - loads NB bytes starting at RA into RT, RT+1, ...
2773        // Note: This conflicts with lmw, but lswi uses different encoding
2774        // Extended opcode 533: Store string word immediate (stswi)
2775        // Format: stswi RS, RA, NB - stores NB bytes from RS, RS+1, ... starting at RA
2776        // Note: This conflicts with stmw, but stswi uses different encoding
2777        // Extended opcode 534: Load string word indexed (lswx)
2778        // Format: lswx RT, RA, RB - loads bytes starting at RA+RB into RT, RT+1, ...
2779        // Only if primary opcode is 31 (not 63)
2780        534 if (word >> 26) == 31 => Ok((
2781            InstructionType::Load,
2782            SmallVec::from_slice(&[
2783                Operand::Register(rt),
2784                Operand::Register(ra),
2785                Operand::Register(rb),
2786            ]),
2787        )),
2788        // Extended opcode 662: Store string word indexed (stswx)
2789        // Format: stswx RS, RA, RB - stores bytes from RS, RS+1, ... starting at RA+RB
2790        // Only if primary opcode is 31 (not 63)
2791        662 if (word >> 26) == 31 => Ok((
2792            InstructionType::Store,
2793            SmallVec::from_slice(&[
2794                Operand::Register(rs),
2795                Operand::Register(ra),
2796                Operand::Register(rb),
2797            ]),
2798        )),
2799        
2800        // Extended opcode 597: Load string word immediate (lswi)
2801        // Format: lswi RT, RA, NB - loads NB bytes starting at RA into RT, RT+1, ...
2802        // Only if primary opcode is 31 (not 63)
2803        597 if (word >> 26) == 31 => {
2804            let rt: u8 = ((word >> 21) & 0x1F) as u8;
2805            let ra: u8 = ((word >> 16) & 0x1F) as u8;
2806            let nb: u8 = ((word >> 11) & 0x1F) as u8;
2807            Ok((
2808                InstructionType::Load,
2809                SmallVec::from_slice(&[
2810                    Operand::Register(rt),
2811                    Operand::Register(ra),
2812                    Operand::Immediate(nb as i16),
2813                ]),
2814            ))
2815        }
2816        
2817        // Extended opcode 533: Store string word immediate (stswi)
2818        // Format: stswi RS, RA, NB - stores NB bytes from RS, RS+1, ... starting at RA
2819        // Only if primary opcode is 31 (not 63)
2820        533 if (word >> 26) == 31 => {
2821            let rs: u8 = ((word >> 21) & 0x1F) as u8;
2822            let ra: u8 = ((word >> 16) & 0x1F) as u8;
2823            let nb: u8 = ((word >> 11) & 0x1F) as u8;
2824            Ok((
2825                InstructionType::Store,
2826                SmallVec::from_slice(&[
2827                    Operand::Register(rs),
2828                    Operand::Register(ra),
2829                    Operand::Immediate(nb as i16),
2830                ]),
2831            ))
2832        }
2833        
2834        // TLB management instructions (system-level, rare)
2835        // Extended opcode 306: TLB invalidate entry (tlbie)
2836        // Format: tlbie RA, RB
2837        306 => Ok((
2838            InstructionType::System,
2839            SmallVec::from_slice(&[
2840                Operand::Register(ra),
2841                Operand::Register(rb),
2842            ]),
2843        )),
2844        // Extended opcode 566: TLB synchronize (tlbsync)
2845        // Format: tlbsync
2846        566 => Ok((InstructionType::System, SmallVec::new())),
2847        
2848        // Unknown extended opcode
2849        _ => Ok((InstructionType::Unknown, SmallVec::new())),
2850    }
2851    }
2852}
2853
2854/// Compute rotate mask from MB (mask begin) and ME (mask end) fields.
2855///
2856/// The mask is used in rotate-and-mask instructions (rlwinm, rlwnm, etc.).
2857/// MB and ME are 5-bit fields specifying which bits to preserve.
2858///
2859/// # Arguments
2860/// * `mb` - Mask begin (5 bits, 0-31)
2861/// * `me` - Mask end (5 bits, 0-31)
2862///
2863/// # Returns
2864/// `u32` - 32-bit mask with bits MB through ME set
2865///
2866/// # Algorithm
2867/// If MB <= ME: set bits MB through ME (inclusive)
2868/// If MB > ME: wraparound case - set bits 0 through ME and MB through 31
2869#[inline] // Called frequently for rotate instructions
2870fn compute_mask(mb: u8, me: u8) -> u32 {
2871    let mut mask: u32 = 0u32;
2872    
2873    if mb <= me {
2874        // Normal case: set bits MB through ME (inclusive)
2875        for i in mb..=me {
2876            mask |= 1u32 << (31u32 - i as u32);
2877        }
2878    } else {
2879        // Wraparound case: set bits 0 through ME and MB through 31
2880        for i in 0u8..=me {
2881            mask |= 1u32 << (31u32 - i as u32);
2882        }
2883        for i in mb..32u8 {
2884            mask |= 1u32 << (31u32 - i as u32);
2885        }
2886    }
2887    
2888    mask
2889}