yaxpeax_rx/
lib.rs

1//! renesas `rx` decoder implemented as part of the `yaxpeax` project. implements traits provided
2//! by `yaxpeax-arch`.
3//!
4//! decoder is aware of `rx` versions 1, 2, and 3, and is built from the following manuals:
5//! `rxv1`: RX Family RXv1 Instruction Set Architecture (User's Manual: Software), Rev. 1.30 (Dec 2019)
6//! * retrieved 2023-12-16 from https://www.renesas.com/us/en/document/mas/rx-family-rxv1-instruction-set-architecture-users-manual-software-rev130
7//! * sha256: `e659dd509141da6bb1cfabf26c9f9ab5996d02060acaad2b5702963116834415`
8//! `rxv2`: RX Family RXv2 Instruction Set Architecture (User's Manual: Software), Rev. 1.00 (Nov 2013)
9//! * retrieved 2023-12-16 from https://www.renesas.com/us/en/document/mas/rx-family-rxv2-instruction-set-architecture-users-manual-software
10//! * sha256: `c12fc8d16adf1530f2cad3f75974d2a29062580a984a71fd9461417b66bba18a`
11//! `rxv3`: RX Family RXv3 Instruction Set Architecture (User's Manual: Software), Rev. 1.00 (Nov 2018)
12//! * retrieved 2023-12-16 from https://www.renesas.com/us/en/document/mas/rx-family-rxv3-instruction-set-architecture-users-manual-software-rev100
13//! * sha256: `829815515a57d077bdfa418e0e167b512f2a04b3db3613329a4d8980399cf74c`
14
15use core::fmt;
16use core::cmp;
17
18use yaxpeax_arch::{AddressDiff, Arch, Decoder, LengthedInstruction, Reader, StandardDecodeError};
19
20#[derive(Debug)]
21pub struct RX;
22
23impl Arch for RX {
24    type Address = u32;
25    type Word = u8;
26    type Instruction = Instruction;
27    type DecodeError = StandardDecodeError;
28    type Decoder = InstDecoder;
29    type Operand = Operand;
30}
31
32#[derive(Debug)]
33pub struct Instruction {
34    opcode: Opcode,
35    operands: [Operand; 3],
36    length: u8,
37}
38
39impl PartialEq for Instruction {
40    fn eq(&self, other: &Self) -> bool {
41        let Instruction {
42            opcode: left_opcode,
43            operands: _, // we won't use this `operands`, but `.operands()` to not use stale extra operands
44            length: left_length,
45        } = self;
46        let Instruction {
47            opcode: right_opcode,
48            operands: _, // we won't use this `operands`, but `.operands()` to not use stale extra operands
49            length: right_length,
50        } = other;
51
52        left_opcode == right_opcode &&
53            left_length == right_length &&
54            self.operands() == other.operands()
55    }
56}
57
58impl Instruction {
59    pub fn opcode(&self) -> Opcode {
60        self.opcode
61    }
62
63    pub fn operands(&self) -> &[Operand] {
64        &self.operands[..self.operand_count() as usize]
65    }
66
67    pub fn length(&self) -> u8 {
68        self.length
69    }
70
71    fn operand_count(&self) -> u8 {
72        let mut operands = 0;
73        for op in self.operands.iter() {
74            if op == &Operand::Nothing {
75                return operands;
76            }
77            operands += 1;
78        }
79
80        operands
81    }
82}
83
84impl Default for Instruction {
85    fn default() -> Instruction {
86        Instruction {
87            opcode: Opcode::NOP,
88            operands: [Operand::Nothing, Operand::Nothing, Operand::Nothing],
89            length: 1,
90        }
91    }
92}
93
94impl fmt::Display for Instruction {
95    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
96        let ops = self.operands();
97        let mut size = None;
98        for op in ops {
99            match op {
100                Operand::Nothing => {},
101                Operand::Register { num: _ } => {},
102                Operand::RegisterRange { start_gpr: _, end_gpr: _ } => {},
103                Operand::Subreg { num: _, width } => {
104                    size = Some(*width);
105                    break;
106                },
107                Operand::Accumulator { num: _ } => {},
108                Operand::BitfieldSpec { bf_spec: _ } => {},
109                Operand::DoubleReg { num: _ } => {},
110                Operand::DoubleRegLow { num: _ } => {},
111                Operand::DoubleRegHigh { num: _ } => {},
112                Operand::ControlReg { reg: _ } => {},
113                Operand::PSWBit { bit: _ } => {},
114                Operand::Deref { gpr: _, disp: _, width } => {
115                    size = Some(*width);
116                    break;
117                },
118                Operand::DerefIndexed { base: _, index: _, width } => {
119                    size = Some(*width);
120                    break;
121                },
122                Operand::DoubleRegisterRange { start_reg: _, end_reg: _ } => {},
123                Operand::DoubleControlRegisterRange { start_reg: _, end_reg: _ } => {},
124                Operand::ImmB { imm: _ } => {},
125                Operand::ImmW { imm: _ } => {},
126                Operand::ImmL { imm: _ }  => {},
127                Operand::BrS { offset: _ } => {
128                    size = Some(SizeCode::S);
129                    break;
130                },
131                Operand::BrB { offset: _ } => {
132                    size = Some(SizeCode::B);
133                    break;
134                },
135                Operand::BrW { offset: _ } => {
136                    size = Some(SizeCode::W);
137                    break;
138                },
139                Operand::BrA { offset: _ } => {
140                    size = Some(SizeCode::A);
141                    break;
142                },
143            }
144        }
145        write!(f, "{}", self.opcode())?;
146
147        if let Some(size) = size {
148            write!(f, ".{}", size)?;
149        }
150        if let Some(op) = ops.get(0) {
151            write!(f, " {}", op)?;
152        }
153        if let Some(op) = ops.get(1) {
154            write!(f, ", {}", op)?;
155        }
156        if let Some(op) = ops.get(2) {
157            write!(f, ", {}", op)?;
158        }
159        Ok(())
160    }
161}
162
163impl LengthedInstruction for Instruction {
164    type Unit = AddressDiff<<RX as Arch>::Address>;
165    fn min_size() -> Self::Unit {
166        AddressDiff::from_const(1)
167    }
168    fn len(&self) -> Self::Unit {
169        AddressDiff::from_const(self.length as u32)
170    }
171}
172
173impl yaxpeax_arch::Instruction for Instruction {
174    // only know how to decode well-formed instructions at the moment
175    fn well_defined(&self) -> bool { true }
176}
177
178#[derive(Debug, Copy, Clone, PartialEq, Eq)]
179pub enum PSWBit {
180    C,
181    Z,
182    S,
183    O,
184    I,
185    U,
186}
187
188impl fmt::Display for PSWBit {
189    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
190        match self {
191            PSWBit::C => f.write_str("c"),
192            PSWBit::Z => f.write_str("z"),
193            PSWBit::S => f.write_str("s"),
194            PSWBit::O => f.write_str("o"),
195            PSWBit::I => f.write_str("i"),
196            PSWBit::U => f.write_str("u"),
197        }
198    }
199}
200
201#[derive(Debug, Copy, Clone, PartialEq, Eq)]
202pub enum ControlReg {
203    PSW,
204    PC,
205    USP,
206    FPSW,
207    BPSW,
208    BPC,
209    ISP,
210    FINTV,
211    INTB,
212    EXTB,
213    /// the four double-precision control registers listed here are in the same order they are
214    /// numbered for instructions like `dpushm`; `dpsw-depc` implies pushing all of `dpsw`, `dcmr`,
215    /// `decnt`, `depc`.
216    DPSW,
217    DCMR,
218    DECNT,
219    DEPC,
220}
221
222impl fmt::Display for ControlReg {
223    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
224        match self {
225            ControlReg::PSW => f.write_str("psw"),
226            ControlReg::PC => f.write_str("pc"),
227            ControlReg::USP => f.write_str("usp"),
228            ControlReg::FPSW => f.write_str("fpsw"),
229            ControlReg::BPSW => f.write_str("bpsw"),
230            ControlReg::BPC => f.write_str("bpc"),
231            ControlReg::ISP => f.write_str("isp"),
232            ControlReg::FINTV => f.write_str("fintv"),
233            ControlReg::INTB => f.write_str("intb"),
234            ControlReg::EXTB => f.write_str("extb"),
235            ControlReg::DPSW => f.write_str("dpsw"),
236            ControlReg::DCMR => f.write_str("dcmr"),
237            ControlReg::DECNT => f.write_str("decnt"),
238            ControlReg::DEPC => f.write_str("DEPC")
239        }
240    }
241}
242
243#[derive(Debug, Copy, Clone, PartialEq, Eq)]
244pub struct BitfieldSpec {
245    bits: u16,
246}
247
248impl fmt::Display for BitfieldSpec {
249    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
250        write!(f, "#{}, #{}, #{}", self.source_start_bit(), self.destination_start_bit(), self.width())
251    }
252}
253
254impl BitfieldSpec {
255    /// the least-significant bit to start moving from the source operand. this is also described
256    /// as `slsb` in the `rx` manuals.
257    fn source_start_bit(&self) -> u8 {
258        let dslb_and_slsb = ((self.bits >> 10) & 0b11111) as u8;
259        self.destination_start_bit().wrapping_sub(dslb_and_slsb) & 0x1f
260    }
261
262    /// the least-significant bit to start moving into in the destination operand. this is also
263    /// described as `dlsb` in the `rx` manuals.
264    fn destination_start_bit(&self) -> u8 {
265        ((self.bits >> 5) & 0b11111) as u8
266    }
267
268    /// the number of bits to move from the source operand to the destination operand.
269    fn width(&self) -> u8 {
270        let dslb_and_width = ((self.bits >> 10) & 0b11111) as u8;
271        dslb_and_width.wrapping_sub(self.destination_start_bit()) & 0x1f
272    }
273}
274
275#[derive(Debug, Copy, Clone, PartialEq, Eq)]
276pub enum Operand {
277    Nothing,
278    /// one of the 16 32-bit general purpose registers: `R0 (sp)` through `R15`.
279    Register { num: u8 },
280    /// a range of registers, from `start_gpr` to `end_gpr`
281    RegisterRange { start_gpr: u8, end_gpr: u8 },
282    /// one of the 16 32-bit general purpose registers, but a smaller part of it. typically
283    /// sign-extended to 32b for processing.
284    Subreg { num: u8, width: SizeCode },
285    Accumulator { num: u8 },
286    /// `bfmov` and `bfmovz`, textually, describe the bitfield to be moved with three parameters.
287    /// those three parameters are expressed as this one operand.
288    BitfieldSpec { bf_spec: BitfieldSpec },
289    /// one of the 16 64-bit double-precision floating point registers: `DR0` through `DR15`.
290    DoubleReg { num: u8 },
291    /// the low 32 bits of a double-precision floating point register.
292    DoubleRegLow { num: u8 },
293    /// the high 32 bits of a double-precision floating point register.
294    DoubleRegHigh { num: u8 },
295    ControlReg { reg: ControlReg },
296    PSWBit { bit: PSWBit },
297    /// access to memory at the address produced by adding `gpr + disp`. in this operand, `disp` is
298    /// the exact number of bytes used for the offset access - this is in contrast to hardware,
299    /// where displacements are scaled down by the size of the scaled item.
300    Deref { gpr: u8, disp: u32, width: SizeCode },
301    /// access to memory at the address produced by adding `gpr(base) + gpr(index) * size(width)`.
302    DerefIndexed { base: u8, index: u8, width: SizeCode },
303    /// a range of double-precision floating point registers, from `start_gpr` to `end_gpr`
304    DoubleRegisterRange { start_reg: u8, end_reg: u8 },
305    DoubleControlRegisterRange { start_reg: ControlReg, end_reg: ControlReg },
306    /// 8-bit immediate
307    ImmB { imm: u8 },
308    /// 16-bit immediate
309    ImmW { imm: u16 },
310    /// 32-bit immediate
311    ImmL { imm: u32 },
312    /// a branch offset in the range `[3, 10]`. this is the effective displacement of `pc`, not the
313    /// three bits stored in instructions using this operand.
314    BrS { offset: u8 },
315    /// a signed 1-byte branch offset, `[-128, 127]`.
316    BrB { offset: i8 },
317    /// a signed 1-byte branch offset, `[-32768, 32767]`.
318    BrW { offset: i16 },
319    /// a 24-bit immediate. this is used as a branch offset, and is treated as a sign-extended
320    /// 24-bit value, so it is represented as that extended form here. this branch offset can be in
321    /// the range `[-8388608, 8388607]`.
322    BrA { offset: i32 },
323}
324
325#[derive(Debug, Copy, Clone, PartialEq, Eq)]
326pub enum SizeCode {
327    S,
328    B,
329    W,
330    A,
331    L,
332    D,
333    UW,
334}
335
336impl fmt::Display for SizeCode {
337    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
338        let text = match self {
339            SizeCode::S => "s",
340            SizeCode::B => "b",
341            SizeCode::W => "w",
342            SizeCode::A => "a",
343            SizeCode::L => "l",
344            SizeCode::D => "d",
345            SizeCode::UW => "uw",
346        };
347
348        f.write_str(text)
349    }
350}
351
352impl SizeCode {
353    fn bytes(&self) -> u8 {
354        match self {
355            SizeCode::S => 1,
356            SizeCode::B => 1,
357            SizeCode::W => 2,
358            SizeCode::UW => 2,
359            SizeCode::A => 3,
360            SizeCode::L => 4,
361            SizeCode::D => 8,
362        }
363    }
364}
365
366impl fmt::Display for Operand {
367    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
368        match self {
369            Operand::Nothing => {
370                f.write_str("")
371            },
372            Operand::Register { num } => {
373                write!(f, "r{}", num)
374            },
375            Operand::RegisterRange { start_gpr, end_gpr } => {
376                write!(f, "r{}-r{}", start_gpr, end_gpr)
377            }
378            Operand::Subreg { num, width: _unused } => {
379                // the width of this register is communicated, textually, by a suffix on the
380                // mnemonic...
381                write!(f, "r{}", num)
382            }
383            Operand::Accumulator { num } => {
384                write!(f, "a{}", num)
385            },
386            Operand::BitfieldSpec { bf_spec } => {
387                fmt::Display::fmt(bf_spec, f)
388            }
389            Operand::DoubleReg { num } => {
390                write!(f, "dr{}", num)
391            },
392            Operand::DoubleRegLow { num } => {
393                write!(f, "drl{}", num)
394            },
395            Operand::DoubleRegHigh { num } => {
396                write!(f, "drh{}", num)
397            },
398            Operand::ControlReg { reg } => {
399                fmt::Display::fmt(reg, f)
400            },
401            Operand::PSWBit { bit } => {
402                fmt::Display::fmt(bit, f)
403            }
404            Operand::Deref { gpr, disp, .. } => {
405                if *disp == 0 {
406                    write!(f, "[r{}]", gpr)
407                } else {
408                    write!(f, "{:x}h[r{}]", disp, gpr)
409                }
410            },
411            Operand::DerefIndexed { base, index, .. } => {
412                // `ri` *is* scaled by the size of the access, but this is communicated as a suffix
413                // on the instruction...
414                write!(f, "[r{}, r{}]", base, index)
415            }
416            Operand::DoubleRegisterRange { start_reg, end_reg } => {
417                write!(f, "dr{}-dr{}", start_reg, end_reg)
418            }
419            Operand::DoubleControlRegisterRange { start_reg, end_reg } => {
420                write!(f, "{}-{}", start_reg, end_reg)
421            }
422            Operand::BrS { offset } => {
423                // a short branch `disp` bytes forward
424                write!(f, "$+{:#x}", offset)
425            }
426            Operand::BrB { offset } => {
427                // a branch by signed `offset` bytes
428                if *offset < 0 {
429                    write!(f, "$-{:#x}", -offset)
430                } else {
431                    write!(f, "$+{:#x}", offset)
432                }
433            }
434            Operand::BrW { offset } => {
435                // a branch by signed `offset` bytes
436                if *offset < 0 {
437                    write!(f, "$-{:#x}", -offset)
438                } else {
439                    write!(f, "$+{:#x}", offset)
440                }
441            }
442            Operand::BrA { offset } => {
443                // a branch by signed `offset` bytes
444                if *offset < 0 {
445                    write!(f, "$-{:#x}", -offset)
446                } else {
447                    write!(f, "$+{:#x}", offset)
448                }
449            }
450            Operand::ImmB { imm } => {
451                write!(f, "#{:x}h", imm)
452            }
453            Operand::ImmW { imm } => {
454                write!(f, "#{:x}h", imm)
455            }
456            Operand::ImmL { imm } => {
457                write!(f, "#{:x}h", imm)
458            }
459        }
460    }
461}
462
463#[allow(non_camel_case_types)]
464#[derive(Debug, Copy, Clone, PartialEq, Eq)]
465pub enum Opcode {
466    REVW,
467    REVL,
468    MSBHI,
469    MSBLH,
470    MSBLO,
471    EMSBA,
472    MVFACHI,
473    MVFACLO,
474    MVFACMI,
475    MVFACGU,
476    RACW,
477    RACL,
478    RDACW,
479    RDACL,
480    MVTACHI,
481    MVTACLO,
482    MVTACGU,
483    XOR,
484    OR,
485    AND,
486    MUL,
487    ADD,
488    SUB,
489    MOVU,
490    SHLL,
491    SHAR,
492    SHLR,
493    BRA,
494    NOP,
495    MOV,
496    DMOV,
497    ROTR,
498    ROTL,
499    SCEQ,
500    SCNE,
501    SCGEU,
502    SCLTU,
503    SCGTU,
504    SCLEU,
505    SCPZ,
506    SCN,
507    SCGE,
508    SCLT,
509    SCGT,
510    SCLE,
511    SCO,
512    SCNO,
513    BMEQ,
514    BMNE,
515    BMGEU,
516    BMLTU,
517    BMGTU,
518    BMLEU,
519    BMPZ,
520    BMN,
521    BMGE,
522    BMLT,
523    BMGT,
524    BMLE,
525    BMO,
526    BMNO,
527    BNOT,
528    FSUB,
529    FCMP,
530    FADD,
531    FMUL,
532    FDIV,
533    MVFC,
534    MVFDC,
535    MVTC,
536    MVTDC,
537    STNZ,
538    STZ,
539    TST,
540    DIVU,
541    DIV,
542    EMULU,
543    EMUL,
544    MIN,
545    MAX,
546    ITOD,
547    FTOD,
548    UTOD,
549    ADC,
550    RSTR,
551    SAVE,
552    MULHI,
553    MULLO,
554    MULLH,
555    EMULA,
556    MACHI,
557    MACLO,
558    MACLH,
559    EMACA,
560    FTOI,
561    ITOF,
562    FTOU,
563    UTOF,
564    FSQRT,
565    ROUND,
566    BSET,
567    BCLR,
568    BTST,
569    BFMOV,
570    BFMOVZ,
571    ABS,
572    NOT,
573    XCHG,
574    SBB,
575    RTFI,
576    RTE,
577    WAIT,
578    SETPSW,
579    CLRPSW,
580    RMPA_B,
581    RMPA_W,
582    RMPA_L,
583    SMOVF,
584    SATR,
585    SSTR_B,
586    SSTR_W,
587    SSTR_L,
588    SMOVB,
589    SWHILE_B,
590    SWHILE_W,
591    SWHILE_L,
592    SMOVU,
593    SUNTIL_B,
594    SUNTIL_W,
595    SUNTIL_L,
596    SCMPU,
597    JMP,
598    JSR,
599    POP,
600    POPC,
601    POPM,
602    PUSH,
603    PUSHC,
604    PUSHM,
605    RORC,
606    ROLC,
607    NEG,
608    DPUSHM,
609    DPOP,
610    DTOF,
611    DROUND,
612    DSQRT,
613    DTOI,
614    DTOU,
615    DABS,
616    DNEG,
617    DADD,
618    DSUB,
619    DMUL,
620    DDIV,
621    DCMPUN,
622    DCMPEQ,
623    DCMPLT,
624    DCMPLE,
625    INT,
626    MVTIPL,
627    MVFDR,
628    CMP,
629    SAT,
630    RTSD,
631    BSR,
632    BRK,
633    BEQ,
634    BNE,
635    BGEU,
636    BLTU,
637    BGTU,
638    BLEU,
639    BPZ,
640    BN,
641    BGE,
642    BLT,
643    BGT,
644    BLE,
645    BO,
646    BNO,
647    RTS,
648}
649
650impl fmt::Display for Opcode {
651    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
652        match self {
653            Opcode::REVW => f.write_str("revw"),
654            Opcode::REVL => f.write_str("revl"),
655            Opcode::MSBHI => f.write_str("msbhi"),
656            Opcode::MSBLH => f.write_str("msblh"),
657            Opcode::MSBLO => f.write_str("msblo"),
658            Opcode::EMSBA => f.write_str("emsba"),
659            Opcode::MVFACHI => f.write_str("mvfachi"),
660            Opcode::MVFACLO => f.write_str("mvfaclo"),
661            Opcode::MVFACMI => f.write_str("mvfacmi"),
662            Opcode::MVFACGU => f.write_str("mvfacgu"),
663            Opcode::RACW => f.write_str("racw"),
664            Opcode::RACL => f.write_str("racl"),
665            Opcode::RDACW => f.write_str("rdacw"),
666            Opcode::RDACL => f.write_str("rdacl"),
667            Opcode::MVTACHI => f.write_str("mvtachi"),
668            Opcode::MVTACLO => f.write_str("mvtaclo"),
669            Opcode::MVTACGU => f.write_str("mvtacgu"),
670            Opcode::XOR => f.write_str("xor"),
671            Opcode::OR => f.write_str("or"),
672            Opcode::AND => f.write_str("and"),
673            Opcode::MUL => f.write_str("mul"),
674            Opcode::ADD => f.write_str("add"),
675            Opcode::SUB => f.write_str("sub"),
676            Opcode::MOVU => f.write_str("movu"),
677            Opcode::SHLL => f.write_str("shll"),
678            Opcode::SHAR => f.write_str("shar"),
679            Opcode::SHLR => f.write_str("shlr"),
680            Opcode::BRA => f.write_str("bra"),
681            Opcode::NOP => f.write_str("nop"),
682            Opcode::MOV => f.write_str("mov"),
683            Opcode::DMOV => f.write_str("dmov"),
684            Opcode::ROTR => f.write_str("rotr"),
685            Opcode::ROTL => f.write_str("rotl"),
686            Opcode::SCEQ => f.write_str("sceq"),
687            Opcode::SCNE => f.write_str("scne"),
688            Opcode::SCGEU => f.write_str("scgeu"),
689            Opcode::SCLTU => f.write_str("scltu"),
690            Opcode::SCGTU => f.write_str("scgtu"),
691            Opcode::SCLEU => f.write_str("scleu"),
692            Opcode::SCPZ => f.write_str("scpz"),
693            Opcode::SCN => f.write_str("scn"),
694            Opcode::SCGE => f.write_str("scge"),
695            Opcode::SCLT => f.write_str("sclt"),
696            Opcode::SCGT => f.write_str("scgt"),
697            Opcode::SCLE => f.write_str("scle"),
698            Opcode::SCO => f.write_str("sco"),
699            Opcode::SCNO => f.write_str("scno"),
700            Opcode::BMEQ => f.write_str("bmeq"),
701            Opcode::BMNE => f.write_str("bmne"),
702            Opcode::BMGEU => f.write_str("bmgeu"),
703            Opcode::BMLTU => f.write_str("bmltu"),
704            Opcode::BMGTU => f.write_str("bmgtu"),
705            Opcode::BMLEU => f.write_str("bmleu"),
706            Opcode::BMPZ => f.write_str("bmpz"),
707            Opcode::BMN => f.write_str("bmn"),
708            Opcode::BMGE => f.write_str("bmge"),
709            Opcode::BMLT => f.write_str("bmlt"),
710            Opcode::BMGT => f.write_str("bmgt"),
711            Opcode::BMLE => f.write_str("bmle"),
712            Opcode::BMO => f.write_str("bmo"),
713            Opcode::BMNO => f.write_str("bmno"),
714            Opcode::BNOT => f.write_str("bnot"),
715            Opcode::FSUB => f.write_str("fsub"),
716            Opcode::FCMP => f.write_str("fcmp"),
717            Opcode::FADD => f.write_str("fadd"),
718            Opcode::FMUL => f.write_str("fmul"),
719            Opcode::FDIV => f.write_str("fdiv"),
720            Opcode::MVFC => f.write_str("mvfc"),
721            Opcode::MVFDC => f.write_str("mvfdc"),
722            Opcode::MVTC => f.write_str("mvtc"),
723            Opcode::MVTDC => f.write_str("mvtdc"),
724            Opcode::STNZ => f.write_str("stnz"),
725            Opcode::STZ => f.write_str("stz"),
726            Opcode::TST => f.write_str("tst"),
727            Opcode::DIVU => f.write_str("divu"),
728            Opcode::DIV => f.write_str("div"),
729            Opcode::EMULU => f.write_str("emulu"),
730            Opcode::EMUL => f.write_str("emul"),
731            Opcode::MIN => f.write_str("min"),
732            Opcode::MAX => f.write_str("max"),
733            Opcode::ITOD => f.write_str("itod"),
734            Opcode::FTOD => f.write_str("ftod"),
735            Opcode::UTOD => f.write_str("utod"),
736            Opcode::ADC => f.write_str("adc"),
737            Opcode::RSTR => f.write_str("rstr"),
738            Opcode::SAVE => f.write_str("save"),
739            Opcode::MULHI => f.write_str("mulhi"),
740            Opcode::MULLO => f.write_str("mullo"),
741            Opcode::MULLH => f.write_str("mullh"),
742            Opcode::EMULA => f.write_str("emula"),
743            Opcode::MACHI => f.write_str("machi"),
744            Opcode::MACLO => f.write_str("maclo"),
745            Opcode::MACLH => f.write_str("maclh"),
746            Opcode::EMACA => f.write_str("emaca"),
747            Opcode::FTOI => f.write_str("ftoi"),
748            Opcode::ITOF => f.write_str("itof"),
749            Opcode::FTOU => f.write_str("ftou"),
750            Opcode::UTOF => f.write_str("utof"),
751            Opcode::FSQRT => f.write_str("fsqrt"),
752            Opcode::ROUND => f.write_str("round"),
753            Opcode::BSET => f.write_str("bset"),
754            Opcode::BCLR => f.write_str("bclr"),
755            Opcode::BTST => f.write_str("btst"),
756            Opcode::BFMOV => f.write_str("bfmov"),
757            Opcode::BFMOVZ => f.write_str("bfmovz"),
758            Opcode::ABS => f.write_str("abs"),
759            Opcode::NOT => f.write_str("not"),
760            Opcode::XCHG => f.write_str("xchg"),
761            Opcode::SBB => f.write_str("sbb"),
762            Opcode::RTFI => f.write_str("rtfi"),
763            Opcode::RTE => f.write_str("rte"),
764            Opcode::WAIT => f.write_str("wait"),
765            Opcode::SETPSW => f.write_str("setpsw"),
766            Opcode::CLRPSW => f.write_str("clrpsw"),
767            Opcode::RMPA_B => f.write_str("rmpa_b"),
768            Opcode::RMPA_W => f.write_str("rmpa_w"),
769            Opcode::RMPA_L => f.write_str("rmpa_l"),
770            Opcode::SMOVF => f.write_str("smovf"),
771            Opcode::SATR => f.write_str("satr"),
772            Opcode::SSTR_B => f.write_str("sstr_b"),
773            Opcode::SSTR_W => f.write_str("sstr_w"),
774            Opcode::SSTR_L => f.write_str("sstr_l"),
775            Opcode::SMOVB => f.write_str("smovb"),
776            Opcode::SWHILE_B => f.write_str("swhile_b"),
777            Opcode::SWHILE_W => f.write_str("swhile_w"),
778            Opcode::SWHILE_L => f.write_str("swhile_l"),
779            Opcode::SMOVU => f.write_str("smovu"),
780            Opcode::SUNTIL_B => f.write_str("suntil_b"),
781            Opcode::SUNTIL_W => f.write_str("suntil_w"),
782            Opcode::SUNTIL_L => f.write_str("suntil_l"),
783            Opcode::SCMPU => f.write_str("scmpu"),
784            Opcode::JMP => f.write_str("jmp"),
785            Opcode::JSR => f.write_str("jsr"),
786            Opcode::POP => f.write_str("pop"),
787            Opcode::POPC => f.write_str("popc"),
788            Opcode::POPM => f.write_str("popm"),
789            Opcode::PUSH => f.write_str("push"),
790            Opcode::PUSHC => f.write_str("pushc"),
791            Opcode::PUSHM => f.write_str("pushm"),
792            Opcode::RORC => f.write_str("rorc"),
793            Opcode::ROLC => f.write_str("rolc"),
794            Opcode::NEG => f.write_str("neg"),
795            Opcode::DPUSHM => f.write_str("dpushm"),
796            Opcode::DPOP => f.write_str("dpop"),
797            Opcode::DTOF => f.write_str("dtof"),
798            Opcode::DROUND => f.write_str("dround"),
799            Opcode::DSQRT => f.write_str("dsqrt"),
800            Opcode::DTOI => f.write_str("dtoi"),
801            Opcode::DTOU => f.write_str("dtou"),
802            Opcode::DABS => f.write_str("dabs"),
803            Opcode::DNEG => f.write_str("dneg"),
804            Opcode::DADD => f.write_str("dadd"),
805            Opcode::DSUB => f.write_str("dsub"),
806            Opcode::DMUL => f.write_str("dmul"),
807            Opcode::DDIV => f.write_str("ddiv"),
808            Opcode::DCMPUN => f.write_str("dcmpun"),
809            Opcode::DCMPEQ => f.write_str("dcmpeq"),
810            Opcode::DCMPLT => f.write_str("dcmplt"),
811            Opcode::DCMPLE => f.write_str("dcmple"),
812            Opcode::INT => f.write_str("int"),
813            Opcode::MVTIPL => f.write_str("mvtipl"),
814            Opcode::MVFDR => f.write_str("mvfdr"),
815            Opcode::CMP => f.write_str("cmp"),
816            Opcode::SAT => f.write_str("sat"),
817            Opcode::RTSD => f.write_str("rtsd"),
818            Opcode::BSR => f.write_str("bsr"),
819            Opcode::BRK => f.write_str("brk"),
820            Opcode::BEQ => f.write_str("beq"),
821            Opcode::BNE => f.write_str("bne"),
822            Opcode::BGEU => f.write_str("bgeu"),
823            Opcode::BLTU => f.write_str("bltu"),
824            Opcode::BGTU => f.write_str("bgtu"),
825            Opcode::BLEU => f.write_str("bleu"),
826            Opcode::BPZ => f.write_str("bpz"),
827            Opcode::BN => f.write_str("bn"),
828            Opcode::BGE => f.write_str("bge"),
829            Opcode::BLT => f.write_str("blt"),
830            Opcode::BGT => f.write_str("bgt"),
831            Opcode::BLE => f.write_str("ble"),
832            Opcode::BO => f.write_str("bo"),
833            Opcode::BNO => f.write_str("bno"),
834            Opcode::RTS => f.write_str("rts"),
835        }
836    }
837}
838
839#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord)]
840#[repr(u8)]
841pub enum RxVersion {
842    V1,
843    V2,
844    V3,
845}
846
847impl PartialOrd for RxVersion {
848    fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
849        (*self as u8).partial_cmp(&(*other as u8))
850    }
851}
852
853#[test]
854fn versions_compare_right() {
855    assert!(RxVersion::V1 < RxVersion::V2);
856    assert!(RxVersion::V2 < RxVersion::V3);
857    assert!(RxVersion::V1 < RxVersion::V3);
858}
859
860#[derive(Debug)]
861pub struct InstDecoder {
862    version: RxVersion,
863}
864
865impl Default for InstDecoder {
866    /// the default version of a `yaxpeax_rx::InstDecoder` is to decode as RX v3. this is
867    /// backwards-compatible with older versions; it will decode code that is entirely RX v1 in the
868    /// same way an RX v1 processor would decode it.
869    fn default() -> Self {
870        Self::v3()
871    }
872}
873
874impl InstDecoder {
875    pub fn v1() -> Self {
876        Self { version: RxVersion::V1 }
877    }
878
879    pub fn v2() -> Self {
880        Self { version: RxVersion::V2 }
881    }
882
883    pub fn v3() -> Self {
884        Self { version: RxVersion::V3 }
885    }
886
887    fn num_to_psw_bit(&self, reg: u8) -> Result<Operand, <RX as Arch>::DecodeError> {
888        match reg {
889            0b0000 => Ok(Operand::PSWBit { bit: PSWBit::C }),
890            0b0001 => Ok(Operand::PSWBit { bit: PSWBit::Z }),
891            0b0010 => Ok(Operand::PSWBit { bit: PSWBit::S }),
892            0b0011 => Ok(Operand::PSWBit { bit: PSWBit::O }),
893            0b1000 => Ok(Operand::PSWBit { bit: PSWBit::I }),
894            0b1001 => Ok(Operand::PSWBit { bit: PSWBit::U }),
895            _ => Err(StandardDecodeError::InvalidOperand),
896        }
897    }
898
899    fn reg_to_control_reg(&self, reg: u8) -> Result<Operand, <RX as Arch>::DecodeError> {
900        match reg {
901            0b0000 => { Ok(Operand::ControlReg { reg: ControlReg::PSW }) },
902            0b0001 => { Ok(Operand::ControlReg { reg: ControlReg::PC }) },
903            0b0010 => { Ok(Operand::ControlReg { reg: ControlReg::USP }) },
904            0b0011 => { Ok(Operand::ControlReg { reg: ControlReg::FPSW}) },
905            0b1000 => { Ok(Operand::ControlReg { reg: ControlReg::BPSW }) },
906            0b1001 => { Ok(Operand::ControlReg { reg: ControlReg::BPC }) },
907            0b1010 => { Ok(Operand::ControlReg { reg: ControlReg::ISP }) },
908            0b1011 => { Ok(Operand::ControlReg { reg: ControlReg::FINTV }) },
909            0b1100 => { Ok(Operand::ControlReg { reg: ControlReg::INTB }) },
910            0b1101 => {
911                if self.version >= RxVersion::V3 {
912                    Ok(Operand::ControlReg { reg: ControlReg::EXTB })
913                } else {
914                    Err(StandardDecodeError::InvalidOperand)
915                }
916            },
917            _ => {
918                Err(StandardDecodeError::InvalidOperand)
919            }
920        }
921    }
922
923    fn reg_to_double_control_reg(&self, reg: u8) -> Result<Operand, <RX as Arch>::DecodeError> {
924        match reg {
925            0b0000 => { Ok(Operand::ControlReg { reg: ControlReg::DPSW }) },
926            0b0001 => { Ok(Operand::ControlReg { reg: ControlReg::DCMR }) },
927            0b0010 => { Ok(Operand::ControlReg { reg: ControlReg::DECNT }) },
928            0b0011 => { Ok(Operand::ControlReg { reg: ControlReg::DEPC }) },
929            _ => {
930                Err(StandardDecodeError::InvalidOperand)
931            }
932        }
933    }
934}
935
936trait DecodeHandler<T: Reader<<RX as Arch>::Address, <RX as Arch>::Word>> {
937    #[inline(always)]
938    fn read_u8(&mut self, words: &mut T) -> Result<u8, <RX as Arch>::DecodeError> {
939        let b = words.next()?;
940        self.on_word_read(b);
941        Ok(b)
942    }
943    #[inline(always)]
944    fn read_u16(&mut self, words: &mut T) -> Result<u16, <RX as Arch>::DecodeError> {
945        let mut buf = [0u8; 2];
946        words.next_n(&mut buf).ok().ok_or(StandardDecodeError::ExhaustedInput)?;
947        self.on_word_read(buf[0]);
948        self.on_word_read(buf[1]);
949        Ok(u16::from_le_bytes(buf))
950    }
951    #[inline(always)]
952    fn read_u24(&mut self, words: &mut T) -> Result<u32, <RX as Arch>::DecodeError> {
953        let mut buf = [0u8; 4];
954        // read into a four-byte buffer, filling the low 3 bytes so we can turn this whole thing
955        // into a u32 in-place
956        words.next_n(&mut buf[1..4]).ok().ok_or(StandardDecodeError::ExhaustedInput)?;
957        self.on_word_read(buf[0]);
958        self.on_word_read(buf[1]);
959        self.on_word_read(buf[2]);
960        Ok(u32::from_le_bytes(buf))
961    }
962    #[inline(always)]
963    fn read_i24(&mut self, words: &mut T) -> Result<i32, <RX as Arch>::DecodeError> {
964        let v = self.read_u24(words)?;
965        Ok(((v as i32) << 8) >> 8)
966    }
967    #[inline(always)]
968    fn read_u32(&mut self, words: &mut T) -> Result<u32, <RX as Arch>::DecodeError> {
969        let mut buf = [0u8; 4];
970        words.next_n(&mut buf).ok().ok_or(StandardDecodeError::ExhaustedInput)?;
971        self.on_word_read(buf[0]);
972        self.on_word_read(buf[1]);
973        self.on_word_read(buf[2]);
974        self.on_word_read(buf[3]);
975        Ok(u32::from_le_bytes(buf))
976    }
977    /// helper to decode the bits for an `ld`-style operand, with variants like "deref", "deref
978    /// with displacement", and "deref with larger displacement", into an `Operand`.
979    ///
980    /// it is not clear how `size` is handled, if at all, for instructions where `ld` would
981    /// indicate a register (non-deref). the manual does not indicate that sign or zero extension
982    /// of source registers is possible for register-register operand combinations, so the likely
983    /// cases are that either size!=L would trap, or is ignored and means full register width
984    /// regardless.
985    fn decode_mem_op(&mut self, rs: u8, ld: u8, size: SizeCode, words: &mut T) -> Result<Operand, <RX as Arch>::DecodeError> {
986        Ok(match ld {
987            0b00 => {
988                Operand::Deref { gpr: rs, disp: 0, width: size }
989            },
990            0b01 => {
991                let disp = self.read_u8(words)? as u32 * size.bytes() as u32;
992                Operand::Deref { gpr: rs, disp, width: size }
993            }
994            0b10 => {
995                let disp = self.read_u16(words)? as u32 * size.bytes() as u32;
996                Operand::Deref { gpr: rs, disp, width: size }
997            }
998            _ => {
999                // callers (should all be internal) should never pass larger `ld`..
1000                // it's not clear how ``
1001                debug_assert_eq!(ld, 0b11);
1002                Operand::Register { num: rs }
1003            }
1004        })
1005    }
1006    fn on_decode_start(&mut self) {}
1007    fn on_decode_end(&mut self) {}
1008    fn on_opcode_decoded(&mut self, _opcode: Opcode) -> Result<(), <RX as Arch>::DecodeError> { Ok(()) }
1009    fn on_operand_decoded(&mut self, _number: u8, _operand: Operand) -> Result<(), <RX as Arch>::DecodeError> { Ok(()) }
1010    fn on_word_read(&mut self, _word: <RX as Arch>::Word) {}
1011}
1012
1013impl<T: yaxpeax_arch::Reader<<RX as Arch>::Address, <RX as Arch>::Word>> DecodeHandler<T> for Instruction {
1014    fn on_decode_start(&mut self) {
1015        self.length = 0;
1016        self.opcode = Opcode::NOP;
1017        self.operands = [Operand::Nothing, Operand::Nothing, Operand::Nothing];
1018    }
1019    fn on_opcode_decoded(&mut self, opcode: Opcode) -> Result<(), <RX as Arch>::DecodeError> {
1020        self.opcode = opcode;
1021        Ok(())
1022    }
1023    fn on_operand_decoded(&mut self, number: u8, operand: Operand) -> Result<(), <RX as Arch>::DecodeError> {
1024        self.operands[number as usize] = operand;
1025        Ok(())
1026    }
1027    fn on_word_read(&mut self, _word: <RX as Arch>::Word) {
1028        self.length += 1;
1029    }
1030}
1031
1032impl Decoder<RX> for InstDecoder {
1033    fn decode_into<T: Reader<<RX as Arch>::Address, <RX as Arch>::Word>>(&self, inst: &mut Instruction, words: &mut T) -> Result<(), <RX as Arch>::DecodeError> {
1034        decode_inst(self, inst, words)
1035    }
1036}
1037
1038fn decode_inst<
1039    T: Reader<<RX as Arch>::Address, <RX as Arch>::Word>,
1040    H: DecodeHandler<T>,
1041>(decoder: &<RX as Arch>::Decoder, handler: &mut H, words: &mut T) -> Result<(), <RX as Arch>::DecodeError> {
1042    handler.on_decode_start();
1043
1044    let opc: u8 = handler.read_u8(words)?;
1045
1046    if opc == 0b0000_0000 {
1047        handler.on_opcode_decoded(Opcode::BRK)?;
1048    } else if opc == 0b0000_0001 {
1049        return Err(StandardDecodeError::InvalidOpcode);
1050    } else if opc == 0b0000_0010 {
1051        handler.on_opcode_decoded(Opcode::RTS)?;
1052    } else if opc == 0b0000_0011 {
1053        handler.on_opcode_decoded(Opcode::NOP)?;
1054    } else if opc == 0b0000_0100 {
1055        handler.on_opcode_decoded(Opcode::BRA)?;
1056        let offset = handler.read_i24(words)?;
1057        handler.on_operand_decoded(0, Operand::BrA { offset })?;
1058    } else if opc == 0b0000_0101 {
1059        handler.on_opcode_decoded(Opcode::BSR)?;
1060        let offset = handler.read_i24(words)?;
1061        handler.on_operand_decoded(0, Operand::BrA { offset })?;
1062    } else if opc == 0b0000_0110 {
1063        let next: u8 = handler.read_u8(words)?;
1064        let mi = (next >> 6) & 0b11;
1065        let ld = next & 0b11;
1066        let opc = (next >> 2) & 0b1111;
1067
1068        if opc < 0b0110 {
1069            const OPC_TABLE: [Opcode; 6] = [Opcode::SUB, Opcode::CMP, Opcode::ADD, Opcode::MUL, Opcode::AND, Opcode::OR];
1070
1071            handler.on_opcode_decoded(OPC_TABLE[opc as usize])?;
1072        } else if opc == 0b1000 {
1073            handler.on_opcode_decoded(match next {
1074                0b0_0000 => {
1075                    if mi == 0b10 && ld != 0b11 {
1076                        Opcode::SBB
1077                    } else {
1078                        return Err(StandardDecodeError::InvalidOperand);
1079                    }
1080                }
1081                0b0_0001 => {
1082                    return Err(StandardDecodeError::InvalidOpcode);
1083                }
1084                0b0_0010 => {
1085                    if mi == 0b10 && ld != 0b11 {
1086                        Opcode::ADC
1087                    } else {
1088                        return Err(StandardDecodeError::InvalidOperand);
1089                    }
1090                }
1091                0b0_0011 => {
1092                    return Err(StandardDecodeError::InvalidOpcode);
1093                }
1094                0b0_0100 => { Opcode::MAX },
1095                0b0_0101 => { Opcode::MIN },
1096                0b0_0110 => { Opcode::EMUL },
1097                0b0_0111 => { Opcode::EMULU },
1098                0b0_1000 => { Opcode::DIV },
1099                0b0_1001 => { Opcode::DIVU },
1100                0b0_1010 => { return Err(StandardDecodeError::InvalidOpcode); },
1101                0b0_1011 => { return Err(StandardDecodeError::InvalidOpcode); },
1102                0b0_1100 => { Opcode::TST },
1103                0b0_1101 => { Opcode::XOR },
1104                0b0_1110 => { return Err(StandardDecodeError::InvalidOpcode); },
1105                0b0_1111 => { return Err(StandardDecodeError::InvalidOpcode); },
1106                0b1_0000 => { Opcode::XCHG },
1107                0b1_0001 => { Opcode::ITOF },
1108                0b1_0010 => { return Err(StandardDecodeError::InvalidOpcode); },
1109                0b1_0011 => { return Err(StandardDecodeError::InvalidOpcode); },
1110                0b1_0100 => { return Err(StandardDecodeError::InvalidOpcode); },
1111                0b1_0101 => if decoder.version >= RxVersion::V2 {
1112                    Opcode::UTOF
1113                } else {
1114                    return Err(StandardDecodeError::InvalidOpcode);
1115                },
1116                0b1_0110 => { return Err(StandardDecodeError::InvalidOpcode); },
1117                0b1_0111 => { return Err(StandardDecodeError::InvalidOpcode); },
1118                0b1_1000 => { return Err(StandardDecodeError::InvalidOpcode); },
1119                0b1_1001 => { return Err(StandardDecodeError::InvalidOpcode); },
1120                0b1_1010 => { return Err(StandardDecodeError::InvalidOpcode); },
1121                0b1_1011 => { return Err(StandardDecodeError::InvalidOpcode); },
1122                0b1_1100 => { return Err(StandardDecodeError::InvalidOpcode); },
1123                0b1_1101 => { return Err(StandardDecodeError::InvalidOpcode); },
1124                0b1_1110 => { return Err(StandardDecodeError::InvalidOpcode); },
1125                0b1_1111 => { return Err(StandardDecodeError::InvalidOpcode); },
1126                // any of the upper three bits being set here are invalid
1127                _ => { return Err(StandardDecodeError::InvalidOpcode); },
1128            })?;
1129        } else {
1130            return Err(StandardDecodeError::InvalidOpcode);
1131        }
1132
1133        // read operands
1134        let next: u8 = handler.read_u8(words)?;
1135
1136        let rs = (next >> 4) & 0b1111;
1137        let rd = next & 0b1111;
1138
1139        let size = [SizeCode::B, SizeCode::W, SizeCode::L, SizeCode::UW][mi as usize];
1140        let src = handler.decode_mem_op(rs, ld, size, words)?;
1141
1142        handler.on_operand_decoded(0, src)?;
1143        handler.on_operand_decoded(1, Operand::Register { num: rd })?;
1144    } else if opc == 0b0000_0111 {
1145        return Err(StandardDecodeError::InvalidOpcode);
1146    } else if opc < 0b0001_0000 {
1147        handler.on_opcode_decoded(Opcode::BRA)?;
1148        let disp = opc & 0b111;
1149        let offset = if disp < 0b11 { disp + 8 } else { disp };
1150        handler.on_operand_decoded(0, Operand::BrS { offset })?;
1151    } else if opc < 0b0010_0000 {
1152        handler.on_opcode_decoded(if opc & 0b0000_1000 == 0 {
1153            Opcode::BEQ
1154        } else {
1155            Opcode::BNE
1156        })?;
1157        let disp = opc & 0b111;
1158        let offset = if disp < 0b11 { disp + 8 } else { disp };
1159        handler.on_operand_decoded(0, Operand::BrS { offset })?;
1160    } else if opc < 0b0011_0000 {
1161        // BCnd.B
1162        let cond = opc & 0b1111;
1163        const OPC_TABLE: &'static [Opcode] = &[
1164            Opcode::BEQ, Opcode::BNE, Opcode::BGEU, Opcode::BLTU,
1165            Opcode::BGTU, Opcode::BLEU, Opcode::BPZ, Opcode::BN,
1166            Opcode::BGE, Opcode::BLT, Opcode::BGT, Opcode::BLE,
1167            Opcode::BO, Opcode::BNO, Opcode::BRA, /* no branch for cnd=1111 */
1168        ];
1169
1170        if cond == 0b1110 {
1171            handler.on_opcode_decoded(Opcode::BRA)?;
1172            let imm = handler.read_u8(words)?;
1173            handler.on_operand_decoded(0, Operand::BrB { offset: imm as i8 })?;
1174        } else if let Some(op) = OPC_TABLE.get(cond as usize) {
1175            handler.on_opcode_decoded(*op)?;
1176            let imm = handler.read_u8(words)?;
1177            handler.on_operand_decoded(0, Operand::ImmB { imm })?;
1178        } else {
1179            return Err(StandardDecodeError::InvalidOpcode);
1180        }
1181    } else if opc < 0b0011_1000 {
1182        return Err(StandardDecodeError::InvalidOpcode);
1183    } else if opc == 0b0011_1000 {
1184        handler.on_opcode_decoded(Opcode::BRA)?;
1185        let imm = handler.read_u16(words)?;
1186        handler.on_operand_decoded(0, Operand::BrW { offset: imm as i16 })?;
1187    } else if opc == 0b0011_1001 {
1188        handler.on_opcode_decoded(Opcode::BSR)?;
1189        let imm = handler.read_u16(words)?;
1190        handler.on_operand_decoded(0, Operand::ImmW { imm })?;
1191    } else if opc == 0b0011_1010 {
1192        handler.on_opcode_decoded(Opcode::BEQ)?;
1193        let imm = handler.read_u16(words)?;
1194        handler.on_operand_decoded(0, Operand::ImmW { imm })?;
1195    } else if opc == 0b0011_1011 {
1196        handler.on_opcode_decoded(Opcode::BNE)?;
1197        let imm = handler.read_u16(words)?;
1198        handler.on_operand_decoded(0, Operand::ImmW { imm })?;
1199    } else if opc < 0b0011_1111 {
1200        // MOV.size
1201        handler.on_opcode_decoded(Opcode::MOV)?;
1202        let operands = handler.read_u8(words)?;
1203        let rd = (operands >> 4) & 0b111;
1204        let disp = (((operands >> 3) & 0b10000) | (operands & 0b1111)) as u8 as u32;
1205        let imm = handler.read_u8(words)?;
1206        match opc & 0b11 {
1207            0b00 => {
1208                handler.on_operand_decoded(0, Operand::ImmB { imm: imm as u8 })?;
1209                handler.on_operand_decoded(1, Operand::Deref { gpr: rd, disp: disp * 1, width: SizeCode::B })?;
1210            }
1211            0b01 => {
1212                handler.on_operand_decoded(0, Operand::ImmW { imm: imm as u8 as u16 })?;
1213                handler.on_operand_decoded(1, Operand::Deref { gpr: rd, disp: disp * 2, width: SizeCode::W })?;
1214            }
1215            0b10 => {
1216                handler.on_operand_decoded(0, Operand::ImmL { imm: imm as u8 as u32 })?;
1217                handler.on_operand_decoded(1, Operand::Deref { gpr: rd, disp: disp * 4, width: SizeCode::L })?;
1218            }
1219            _ => { unreachable!("sz=11 is rtsd") }
1220        };
1221    } else if opc == 0b0011_1111 {
1222        handler.on_opcode_decoded(Opcode::RTSD)?;
1223
1224        let operands = handler.read_u8(words)?;
1225        let imm = handler.read_u8(words)?;
1226        let rd = operands >> 4;
1227        let rd2 = operands & 0b1111;
1228        handler.on_operand_decoded(0, Operand::ImmB { imm })?;
1229        handler.on_operand_decoded(1, Operand::RegisterRange { start_gpr: rd, end_gpr: rd2 })?;
1230    } else if opc < 0b0110_0000 {
1231        let code = (opc >> 2) & 0b111;
1232        let opcode = [
1233            Opcode::SUB, Opcode::CMP, Opcode::ADD, Opcode::MUL,
1234            Opcode::AND, Opcode::OR, Opcode::MOVU, Opcode::MOVU,
1235        ][code as usize];
1236        handler.on_opcode_decoded(opcode)?;
1237
1238        let ld = opc & 0b11;
1239        let operands = handler.read_u8(words)?;
1240        let rs = operands >> 4;
1241        let rd = operands & 0b1111;
1242
1243        let size = [
1244            SizeCode::L, SizeCode::L, SizeCode::L, SizeCode::L,
1245            SizeCode::L, SizeCode::L, SizeCode::B, SizeCode::W,
1246        ][code as usize];
1247        let src = handler.decode_mem_op(rs, ld, size, words)?;
1248        handler.on_operand_decoded(0, src)?;
1249        handler.on_operand_decoded(1, Operand::Register { num: rd })?;
1250    } else if opc < 0b0111_0000 {
1251        // 0 1 1 0 ....
1252        let opc = opc & 0b1111;
1253        if opc < 0b1000 {
1254            // 0 1 1 0 0 ...
1255            // either sub/cmp/add/.. or rtsd
1256            let operands = handler.read_u8(words)?;
1257            if opc == 0b0111 {
1258                handler.on_opcode_decoded(Opcode::RTSD)?;
1259                handler.on_operand_decoded(0, Operand::ImmB { imm: operands })?;
1260            } else {
1261                let opcode = [
1262                    Opcode::SUB, Opcode::CMP, Opcode::ADD, Opcode::MUL,
1263                    Opcode::AND, Opcode::OR, Opcode::MOV
1264                ][opc as usize];
1265                handler.on_opcode_decoded(opcode)?;
1266                let imm = operands >> 4;
1267                let rd = operands & 0b1111;
1268                handler.on_operand_decoded(0, Operand::ImmB { imm })?;
1269                handler.on_operand_decoded(1, Operand::Register { num: rd })?;
1270            }
1271        } else if opc < 0b1110 {
1272            // 0 1 1 0 1 ...
1273            handler.on_opcode_decoded(match opc >> 1 {
1274                0b100 => Opcode::SHLR,
1275                0b101 => Opcode::SHAR,
1276                0b110 => Opcode::SHLL,
1277                _ => { unreachable!("implies opc=0b1111") }
1278            })?;
1279            let operands = handler.read_u8(words)?;
1280            let imm = operands >> 3;
1281            let rd = operands & 0b111;
1282            handler.on_operand_decoded(0, Operand::ImmB { imm })?;
1283            handler.on_operand_decoded(1, Operand::Register { num: rd })?;
1284        } else {
1285            // 0 1 1 0 1 1 1 x
1286            handler.on_opcode_decoded(if opc == 0b1110 {
1287                Opcode::PUSHM
1288            } else {
1289                Opcode::POPM
1290            })?;
1291            let operands = handler.read_u8(words)?;
1292            let reg_lo = operands >> 4;
1293            let reg_hi = operands & 0b1111;
1294            handler.on_operand_decoded(0, Operand::RegisterRange { start_gpr: reg_lo, end_gpr: reg_hi })?;
1295        }
1296    } else if opc < 0b0111_0100 {
1297        // 0 1 1 1 0 0 li
1298        handler.on_opcode_decoded(Opcode::ADD)?;
1299        let operands = handler.read_u8(words)?;
1300        let rs2 = operands >> 4;
1301        let rd = operands & 0b1111;
1302        let li = opc & 0b11;
1303        let imm = match li {
1304            0b00 => {
1305                handler.read_u32(words)?
1306            }
1307            0b01 => {
1308                handler.read_u8(words)? as i8 as i32 as u32
1309            }
1310            0b10 => {
1311                handler.read_u16(words)? as i16 as i32 as u32
1312            }
1313            _ => {
1314                debug_assert!(li == 0b11, "li is at most the low two bits set");
1315                handler.read_i24(words)? as u32
1316            }
1317        };
1318        handler.on_operand_decoded(0, Operand::ImmL { imm })?;
1319        handler.on_operand_decoded(1, Operand::Register { num: rs2 })?;
1320        handler.on_operand_decoded(2, Operand::Register { num: rd })?;
1321    } else if opc < 0b0111_1000 {
1322        // 0 1 1 1 0 1 li
1323        let li = opc & 0b11;
1324        let operands = handler.read_u8(words)?;
1325        let opc = operands >> 4;
1326        let opcode = match opc {
1327            0b0000 => Some(Opcode::CMP),
1328            0b0001 => Some(Opcode::MUL),
1329            0b0010 => Some(Opcode::AND),
1330            0b0011 => Some(Opcode::OR),
1331            0b0100 => {
1332                if li != 0b01 {
1333                    return Err(StandardDecodeError::InvalidOperand);
1334                }
1335                Some(Opcode::MOV)
1336            }
1337            0b0101 => {
1338                if li != 0b01 {
1339                    return Err(StandardDecodeError::InvalidOperand);
1340                }
1341                Some(Opcode::CMP)
1342            }
1343            _ => {
1344                // might still be a valid instruction, but we don't know the opcode for sure yet.
1345                // or we might be able to discern the opcode, but operands need extra checking
1346                // (like `int`).
1347                None
1348            }
1349        };
1350        let rd = operands & 0b1111;
1351        let imm = match li {
1352            0b00 => {
1353                handler.read_u32(words)?
1354            }
1355            0b01 => {
1356                handler.read_u8(words)? as i8 as i32 as u32
1357            }
1358            0b10 => {
1359                handler.read_u16(words)? as i16 as i32 as u32
1360            }
1361            _ => {
1362                debug_assert!(li == 0b11, "li is at most the low two bits set");
1363                handler.read_i24(words)? as u32
1364            }
1365        };
1366        if let Some(op) = opcode {
1367            handler.on_opcode_decoded(op)?;
1368            handler.on_operand_decoded(0, Operand::ImmL { imm })?;
1369            handler.on_operand_decoded(1, Operand::Register { num: rd })?;
1370        } else {
1371            if opc == 0b0110 {
1372                // might be `int`, depends on rd
1373                if rd == 0 {
1374                    handler.on_opcode_decoded(Opcode::INT)?;
1375                    handler.on_operand_decoded(0, Operand::ImmB { imm: imm as u8 })?;
1376                } else {
1377                    return Err(StandardDecodeError::InvalidOperand);
1378                }
1379            } else if opc == 0b0111 {
1380                // might be `mvitpl`
1381                if rd == 0 && (imm & 0b1111_0000 == 0) {
1382                    handler.on_opcode_decoded(Opcode::MVTIPL)?;
1383                    handler.on_operand_decoded(0, Operand::ImmB { imm: imm as u8 & 0b1111 })?;
1384                } else {
1385                    return Err(StandardDecodeError::InvalidOperand);
1386                }
1387            } else if opc == 0b1001 {
1388                // might be `mvfdr`, or other new double-precision instructions
1389                if decoder.version < RxVersion::V3 {
1390                    return Err(StandardDecodeError::InvalidOpcode);
1391                }
1392                if rd != 0 {
1393                    return Err(StandardDecodeError::InvalidOpcode);
1394                }
1395                if li == 0b01 {
1396                    if imm != 0b0001_1011 {
1397                        handler.on_opcode_decoded(Opcode::MVFDR)?;
1398                    } else {
1399                        return Err(StandardDecodeError::InvalidOperand);
1400                    }
1401                } else if li == 0b10 {
1402                    let rs = imm as u8;
1403                    let rd = (imm >> 4) as u8;
1404                    let opc = (imm >> 8) as u8;
1405                    let rs2 = (imm >> 12) as u8;
1406
1407                    let opcode = match opc {
1408                        0b0000 => Opcode::DADD,
1409                        0b0001 => Opcode::DSUB,
1410                        0b0010 => Opcode::DMUL,
1411                        /*0011 is invalid*/
1412                        0b0100 => Opcode::DDIV,
1413                        /*0101 and 0110 are invalid*/
1414                        0b0111 => {
1415                            // unlike others, dcmp has variants selected by `rd`
1416                            let opc = match rd {
1417                                0b0001 => Opcode::DCMPUN,
1418                                0b0010 => Opcode::DCMPEQ,
1419                                0b0100 => Opcode::DCMPLT,
1420                                0b0110 => Opcode::DCMPLE,
1421                                _ => {
1422                                    return Err(StandardDecodeError::InvalidOpcode);
1423                                }
1424                            };
1425                            handler.on_opcode_decoded(opc)?;
1426                            handler.on_operand_decoded(0, Operand::DoubleReg { num: rs })?;
1427                            handler.on_operand_decoded(1, Operand::DoubleReg { num: rs2 })?;
1428                            return Ok(());
1429                        }
1430                        0b1100 => {
1431                            // dmovd or a few others, depending on "rs"
1432                            let opc = match rs {
1433                                0b0000 => Opcode::DMOV,
1434                                0b0001 => Opcode::DABS,
1435                                0b0010 => Opcode::DNEG,
1436                                _ => {
1437                                    return Err(StandardDecodeError::InvalidOpcode);
1438                                }
1439                            };
1440                            handler.on_opcode_decoded(opc)?;
1441                            handler.on_operand_decoded(0, Operand::DoubleReg { num: rs })?;
1442                            handler.on_operand_decoded(1, Operand::DoubleReg { num: rd })?;
1443                            return Ok(());
1444                        }
1445                        0b1101 => {
1446                            // dsqrt or others, depending on "rs"
1447                            let opc = match rs {
1448                                0b0000 => Opcode::DSQRT,
1449                                0b1000 => Opcode::DTOI,
1450                                0b1001 => Opcode::DTOU,
1451                                0b1100 => Opcode::DTOF,
1452                                0b1101 => Opcode::DROUND,
1453                                _ => {
1454                                    return Err(StandardDecodeError::InvalidOpcode);
1455                                }
1456                            };
1457                            handler.on_opcode_decoded(opc)?;
1458                            handler.on_operand_decoded(0, Operand::DoubleReg { num: rs })?;
1459                            handler.on_operand_decoded(1, Operand::DoubleReg { num: rd })?;
1460                            return Ok(());
1461                        }
1462                        _ => {
1463                            return Err(StandardDecodeError::InvalidOperand);
1464                        }
1465                    };
1466                    handler.on_opcode_decoded(opcode)?;
1467                    handler.on_operand_decoded(0, Operand::DoubleReg { num: rs })?;
1468                    handler.on_operand_decoded(1, Operand::DoubleReg { num: rs2 })?;
1469                    handler.on_operand_decoded(2, Operand::DoubleReg { num: rd })?;
1470                } else {
1471                    return Err(StandardDecodeError::InvalidOperand);
1472                }
1473            } else if opc == 0b1010 {
1474                // dpushm.l/dpopm.l
1475                let opc = if rd == 0b000 {
1476                    Opcode::DPUSHM
1477                } else if rd == 0b1000 {
1478                    Opcode::DPOP
1479                } else {
1480                    return Err(StandardDecodeError::InvalidOperand);
1481                };
1482                handler.on_opcode_decoded(opc)?;
1483                let rs = (imm as u8 >> 4) & 0b1111;
1484                let nm = imm as u8 & 0b1111;
1485                let end_reg = rs + nm + 1;
1486                if end_reg > 15 {
1487                    return Err(StandardDecodeError::InvalidOperand);
1488                }
1489                let start_reg = if let Operand::ControlReg { reg } = decoder.reg_to_double_control_reg(rs)? {
1490                    reg
1491                } else {
1492                    panic!("impossible operand for double-precision control reg?");
1493                };
1494                let end_reg = if let Operand::ControlReg { reg } = decoder.reg_to_double_control_reg(end_reg)? {
1495                    reg
1496                } else {
1497                    panic!("impossible operand for double-precision control reg?");
1498                };
1499                handler.on_operand_decoded(0, Operand::DoubleControlRegisterRange { start_reg, end_reg })?;
1500            } else if opc == 0b1011 {
1501                // dpushm.d/dpopm.d
1502                let opc = if rd == 0b000 {
1503                    Opcode::DPUSHM
1504                } else if rd == 0b1000 {
1505                    Opcode::DPOP
1506                } else {
1507                    return Err(StandardDecodeError::InvalidOperand);
1508                };
1509                handler.on_opcode_decoded(opc)?;
1510                let rs = (imm as u8 >> 4) & 0b1111;
1511                let nm = imm as u8 & 0b1111;
1512                let end_reg = rs + nm + 1;
1513                if end_reg > 15 {
1514                    return Err(StandardDecodeError::InvalidOperand);
1515                }
1516                handler.on_operand_decoded(0, Operand::DoubleRegisterRange { start_reg: rs, end_reg })?;
1517            } else {
1518                return Err(StandardDecodeError::InvalidOperand);
1519            }
1520        }
1521    } else if opc < 0b0111_1110 {
1522        // 0 1 1 1 1 xx _
1523        // BSET, BCLR, BTST
1524        let operands = handler.read_u8(words)?;
1525        let imm = ((opc & 1) << 4) | (operands >> 4);
1526        let rd = operands & 0b1111;
1527        let opc = match (operands >> 1) & 0b11 {
1528            0b00 => Opcode::BSET,
1529            0b01 => Opcode::BCLR,
1530            // already tested for opc=11 by the `if` above, this is opc=10
1531            _ => Opcode::BTST,
1532        };
1533        handler.on_opcode_decoded(opc)?;
1534        handler.on_operand_decoded(0, Operand::ImmB { imm })?;
1535        handler.on_operand_decoded(1, Operand::Register { num: rd })?;
1536    } else if opc < 0b0111_1111 {
1537        // 0 1 1 1 1 1 1 0
1538        let operands = handler.read_u8(words)?;
1539        let opc = operands >> 4;
1540        let rd = operands & 0b1111;
1541        match opc {
1542            0b0000 => {
1543                handler.on_opcode_decoded(Opcode::NOT)?;
1544                handler.on_operand_decoded(0, Operand::Register { num: rd })?;
1545            }
1546            0b0001 => {
1547                handler.on_opcode_decoded(Opcode::NEG)?;
1548                handler.on_operand_decoded(0, Operand::Register { num: rd })?;
1549            }
1550            0b0010 => {
1551                handler.on_opcode_decoded(Opcode::ABS)?;
1552                handler.on_operand_decoded(0, Operand::Register { num: rd })?;
1553            }
1554            0b0011 => {
1555                handler.on_opcode_decoded(Opcode::SAT)?;
1556                handler.on_operand_decoded(0, Operand::Register { num: rd })?;
1557            }
1558            0b0100 => {
1559                handler.on_opcode_decoded(Opcode::RORC)?;
1560                handler.on_operand_decoded(0, Operand::Register { num: rd })?;
1561            }
1562            0b0101 => {
1563                handler.on_opcode_decoded(Opcode::ROLC)?;
1564                handler.on_operand_decoded(0, Operand::Register { num: rd })?;
1565            }
1566            0b1000 => {
1567                handler.on_opcode_decoded(Opcode::PUSH)?;
1568                handler.on_operand_decoded(0, Operand::Subreg { num: rd, width: SizeCode::B })?;
1569            }
1570            0b1001 => {
1571                handler.on_opcode_decoded(Opcode::PUSH)?;
1572                handler.on_operand_decoded(0, Operand::Subreg { num: rd, width: SizeCode::W })?;
1573            }
1574            0b1010 => {
1575                handler.on_opcode_decoded(Opcode::PUSH)?;
1576                handler.on_operand_decoded(0, Operand::Register { num: rd })?;
1577            }
1578            0b1011 => {
1579                handler.on_opcode_decoded(Opcode::POP)?;
1580                handler.on_operand_decoded(0, Operand::Register { num: rd })?;
1581            }
1582            0b1100 => {
1583                handler.on_opcode_decoded(Opcode::PUSHC)?;
1584                handler.on_operand_decoded(0, decoder.reg_to_control_reg(rd)?)?;
1585            }
1586            0b1110 => {
1587                handler.on_opcode_decoded(Opcode::POPC)?;
1588                // can't popc into pc
1589                if rd == 0b0001 {
1590                    return Err(StandardDecodeError::InvalidOperand);
1591                }
1592                handler.on_operand_decoded(0, decoder.reg_to_control_reg(rd)?)?;
1593            }
1594            _ => {
1595                return Err(StandardDecodeError::InvalidOpcode);
1596            }
1597        }
1598    } else if opc < 0b1000_0000 {
1599        // 0 1 1 1 1 1 1 1
1600        let operands = handler.read_u8(words)?;
1601        let opc = operands >> 4;
1602        if opc < 0b1000 {
1603            handler.on_operand_decoded(0, Operand::Register { num: operands & 0b1111 })?;
1604            let opcode = match opc {
1605                0b0000 => Opcode::JMP,
1606                0b0001 => Opcode::JSR,
1607                0b0100 => Opcode::BRA,
1608                0b0101 => Opcode::BRA,
1609                _ => {
1610                    return Err(StandardDecodeError::InvalidOpcode);
1611                }
1612            };
1613            handler.on_opcode_decoded(opcode)?;
1614        } else if opc == 0b1000 {
1615            // 0 1 1 1 1 1 1 1 | 1 0 0 0 ...
1616            let opcode = [
1617                Opcode::SUNTIL_B, Opcode::SUNTIL_W, Opcode::SUNTIL_L, Opcode::SCMPU,
1618                Opcode::SWHILE_B, Opcode::SWHILE_W, Opcode::SWHILE_L, Opcode::SMOVU,
1619                Opcode::SSTR_B, Opcode::SSTR_W, Opcode::SSTR_L, Opcode::SMOVB,
1620                Opcode::RMPA_B, Opcode::RMPA_W, Opcode::RMPA_L, Opcode::SMOVF,
1621            ][operands as usize & 0b1111];
1622            handler.on_opcode_decoded(opcode)?;
1623        } else if opc == 0b1001 {
1624            // 0 1 1 1 1 1 1 1 | 1 0 0 1 ...
1625            let opcode = match operands & 0b1111 {
1626                0b0011 => Opcode::SATR,
1627                0b0100 => Opcode::RTFI,
1628                0b0101 => Opcode::RTE,
1629                0b0110 => Opcode::WAIT,
1630                _ => {
1631                    return Err(StandardDecodeError::InvalidOpcode);
1632                }
1633            };
1634            handler.on_opcode_decoded(opcode)?;
1635        } else if opc == 0b1010 {
1636            // setpsw
1637            handler.on_operand_decoded(0, decoder.num_to_psw_bit(operands & 0b1111)?)?;
1638            handler.on_opcode_decoded(Opcode::SETPSW)?;
1639        } else if opc == 0b1011 {
1640            // clrpsw
1641            handler.on_operand_decoded(0, decoder.num_to_psw_bit(operands & 0b1111)?)?;
1642            handler.on_opcode_decoded(Opcode::CLRPSW)?;
1643        } else {
1644            return Err(StandardDecodeError::InvalidOpcode);
1645        }
1646    } else if opc < 0b1111_0000 {
1647        // 1 0 x x x x x x MOV
1648        // 1 1 x x <11 <11 MOV
1649        let sz = (opc >> 4) & 0b11;
1650        if sz == 0b11 {
1651            // definitely `1 0 1 1`: `1 1 1 1` would fail the branch above
1652            // disp[Rs], Rd
1653            handler.on_opcode_decoded(Opcode::MOVU)?;
1654            let sz = if (opc >> 3) & 0b1 != 0 {
1655                SizeCode::B
1656            } else {
1657                SizeCode::W
1658            };
1659            let operands = handler.read_u8(words)?;
1660            let rs = operands & 0b111;
1661            let rd = (operands >> 4) & 0b111;
1662            let displo = (operands >> 3) & 1;
1663            let dispmid = (operands >> 6) & 2;
1664            let disphi = (opc & 0b111) << 2;
1665            let disp = displo | dispmid | disphi;
1666            handler.on_operand_decoded(0, Operand::Deref { gpr: rs, disp: disp as u32 * sz.bytes() as u32, width: sz })?;
1667            handler.on_operand_decoded(1, Operand::Register { num: rd })?;
1668        } else {
1669            handler.on_opcode_decoded(Opcode::MOV)?;
1670            let sz = [SizeCode::B, SizeCode::W, SizeCode::L][sz as usize];
1671            // sz = 00, 01, 10, one of two styles of `mov`.
1672            if opc & 0b0100_0000 == 0 {
1673                // disp is 5-bit embedded form
1674                let operands = handler.read_u8(words)?;
1675                let rs = operands & 0b111;
1676                let rd = (operands >> 4) & 0b111;
1677                let displo = (operands >> 3) & 1;
1678                let dispmid = (operands >> 6) & 2;
1679                let disphi = (opc & 0b111) << 2;
1680                let disp = displo | dispmid | disphi;
1681                if opc & 0b0000_1000  == 0 {
1682                    handler.on_operand_decoded(0, Operand::Register { num: rs })?;
1683                    handler.on_operand_decoded(1, Operand::Deref { gpr: rd, disp: disp as u32 * sz.bytes() as u32, width: sz })?;
1684                } else {
1685                    // also swaps the meaning of the rs/rd fields in this encoding
1686                    let rs = (operands >> 4) & 0b111;
1687                    let rd = operands & 0b111;
1688                    handler.on_operand_decoded(0, Operand::Deref { gpr: rs, disp: disp as u32 * sz.bytes() as u32, width: sz })?;
1689                    handler.on_operand_decoded(1, Operand::Register { num: rd })?;
1690                }
1691            } else {
1692                // either operand may have displacement, may be mem-mem
1693                let ldd = (opc >> 2) & 0b11;
1694                let lds = opc & 0b11;
1695                let operands = handler.read_u8(words)?;
1696                let rs = operands & 0b1111;
1697                let rd = operands >> 4;
1698
1699                match (ldd, lds) {
1700                    (0b11, 0b11) => {
1701                        // encoding 7, explicitly reg-reg, might involve sign/zero extension
1702                        let source_op = if sz == SizeCode::L {
1703                            Operand::Register { num: rs }
1704                        } else {
1705                            Operand::Subreg { num: rs, width: sz }
1706                        };
1707                        handler.on_operand_decoded(0, source_op)?;
1708                        handler.on_operand_decoded(1, Operand::Register { num: rd })?;
1709                    }
1710                    (ld, 0b11) => {
1711                        handler.on_operand_decoded(0, Operand::Register { num: rs })?;
1712                        let op = handler.decode_mem_op(rd, ld, sz, words)?;
1713                        handler.on_operand_decoded(1, op)?;
1714                    },
1715                    (0b11, ld) => {
1716                        // for this one, rs and rd are reversed...
1717                        let rs = operands >> 4;
1718                        let rd = operands & 0b1111;
1719                        let op = handler.decode_mem_op(rs, ld, sz, words)?;
1720                        handler.on_operand_decoded(0, op)?;
1721                        handler.on_operand_decoded(1, Operand::Register { num: rd })?;
1722                    },
1723                    (ldd, lds) => {
1724                        let op = handler.decode_mem_op(rs, lds, sz, words)?;
1725                        handler.on_operand_decoded(0, op)?;
1726                        let op = handler.decode_mem_op(rd, ldd, sz, words)?;
1727                        handler.on_operand_decoded(1, op)?;
1728                    }
1729                }
1730            }
1731        }
1732    } else if opc < 0b1111_0100 {
1733        // 1 1 1 1 0 0 x x BSET/BCLR
1734        let ld = opc & 0b11;
1735        if ld == 0b11 {
1736            return Err(StandardDecodeError::InvalidOperand);
1737        }
1738
1739        let operands = handler.read_u8(words)?;
1740        let imm = operands & 0b111;
1741        let rd = operands >> 4;
1742
1743        let operand = handler.decode_mem_op(rd, ld, SizeCode::B, words)?;
1744
1745        let opcode = if operands & 0b0000_1000 == 0 {
1746            Opcode::BSET
1747        } else {
1748            Opcode::BCLR
1749        };
1750        handler.on_opcode_decoded(opcode)?;
1751        handler.on_operand_decoded(0, Operand::ImmB { imm })?;
1752        handler.on_operand_decoded(1, operand)?;
1753    } else if opc < 0b1111_1000 {
1754        // 1 1 1 1 0 1 x x BTST/PUSH
1755        let ld = opc & 0b11;
1756        if ld == 0b11 {
1757            return Err(StandardDecodeError::InvalidOperand);
1758        }
1759
1760        let operands = handler.read_u8(words)?;
1761        let rs = operands >> 4;
1762        if operands & 0b0000_1000 == 0 {
1763            let imm = operands & 0b111;
1764            let op = handler.decode_mem_op(rs, ld, SizeCode::B, words)?;
1765            handler.on_operand_decoded(1, op)?;
1766            handler.on_operand_decoded(0, Operand::ImmB { imm })?;
1767            handler.on_opcode_decoded(Opcode::BTST)?;
1768        } else if operands & 0b0000_1100 == 0b0000_1000 {
1769            let sz = match operands & 0b11 {
1770                0b00 => SizeCode::B,
1771                0b01 => SizeCode::W,
1772                0b10 => SizeCode::L,
1773                0b11 => { return Err(StandardDecodeError::InvalidOperand) },
1774                _ => { unreachable!("sz is only two bits"); }
1775            };
1776
1777            let op = handler.decode_mem_op(rs, ld, sz, words)?;
1778            handler.on_operand_decoded(0, op)?;
1779            handler.on_opcode_decoded(Opcode::PUSH)?;
1780        } else {
1781            return Err(StandardDecodeError::InvalidOperand);
1782        }
1783    } else if opc < 0b1111_1100 {
1784        // 1 1 1 1 1 0 x x MOV (or v3+, DMOV)
1785        let ld = opc & 0b11;
1786        let operands = handler.read_u8(words)?;
1787        let sz = operands & 0b11;
1788        if sz == 0b11 {
1789            if decoder.version < RxVersion::V3 {
1790                // rxv1 or rxv2, no dmov yet, so this is an invalid `sz` for `mov`
1791                return Err(StandardDecodeError::InvalidOperand);
1792            } else {
1793                // rxv3+, dmov.*
1794                if operands != 0b0000_0011 {
1795                    return Err(StandardDecodeError::InvalidOpcode);
1796                }
1797                let operands = handler.read_u8(words)?;
1798                let rd = operands >> 4;
1799                match operands & 0b1111 {
1800                    0b0000 => {
1801                        handler.on_opcode_decoded(Opcode::DMOV)?;
1802                        handler.on_operand_decoded(1, Operand::DoubleRegLow { num: rd })?;
1803                    },
1804                    0b0010 => {
1805                        handler.on_opcode_decoded(Opcode::DMOV)?;
1806                        handler.on_operand_decoded(1, Operand::DoubleRegHigh { num: rd })?;
1807                    },
1808                    0b0011 => {
1809                        // not really sure what makes the immediate D size here. does hardware
1810                        // expand the 32b float into a 64b float?
1811                        handler.on_opcode_decoded(Opcode::DMOV)?;
1812                        handler.on_operand_decoded(1, Operand::DoubleReg { num: rd })?;
1813                    },
1814                    _ => {
1815                        return Err(StandardDecodeError::InvalidOpcode);
1816                    }
1817                }
1818                let imm = handler.read_u32(words)?;
1819                handler.on_operand_decoded(0, Operand::ImmL { imm })?;
1820            }
1821        } else {
1822            let rd = operands >> 4;
1823            let li = (operands >> 2) & 0b11;
1824            let sz = [SizeCode::B, SizeCode::W, SizeCode::L][sz as usize];
1825            // note this is a bit of a lie: `li=10` is actually a 24b immediate, but for comparison
1826            // here L is close enough..
1827            let li_code = [SizeCode::B, SizeCode::W, SizeCode::L, SizeCode::L][li as usize];
1828            // what happens when `li` is larger than `sz`...??? undefined!
1829            if li_code.bytes() > sz.bytes() {
1830                return Err(StandardDecodeError::InvalidOperand);
1831            }
1832
1833            let operand = handler.decode_mem_op(rd, ld, sz, words)?;
1834            let imm = match li {
1835                0b00 => {
1836                    handler.read_u32(words)?
1837                }
1838                0b01 => {
1839                    handler.read_u8(words)? as i8 as i32 as u32
1840                }
1841                0b10 => {
1842                    handler.read_u16(words)? as i16 as i32 as u32
1843                }
1844                _ => {
1845                    debug_assert!(li == 0b11, "li is at most the low two bits set");
1846                    handler.read_i24(words)? as u32
1847                }
1848            };
1849            handler.on_opcode_decoded(Opcode::MOV)?;
1850            handler.on_operand_decoded(0, Operand::ImmL { imm })?;
1851            handler.on_operand_decoded(1, operand)?;
1852        }
1853    } else if opc == 0b1111_1100 {
1854        // many instructions
1855        let operands = handler.read_u8(words)?;
1856        let opc5 = (operands >> 2) & 0b11111;
1857        let ld = operands & 0b11;
1858
1859        let registers = handler.read_u8(words)?;
1860        let rd = registers & 0b1111;
1861        let rs = registers >> 4;
1862
1863        if operands & 0b1000_0000 == 0 {
1864            // 1 1 1 1 1 1 0 0 | 0 ..
1865            if opc5 < 0b10010 {
1866                // simple enough: `0 [ opc5 ] ld | [ rs  ] [ rd  ]`
1867                let opcode = match opc5 {
1868                    0b00000 => {
1869                        if ld != 0b11 {
1870                            return Err(StandardDecodeError::InvalidOperand);
1871                        }
1872                        Opcode::SBB
1873                    }
1874                    0b00001 => {
1875                        if ld != 0b11 {
1876                            return Err(StandardDecodeError::InvalidOperand);
1877                        }
1878                        Opcode::NEG
1879                    }
1880                    0b00010 => {
1881                        if ld != 0b11 {
1882                            return Err(StandardDecodeError::InvalidOperand);
1883                        }
1884                        Opcode::ADC
1885                    }
1886                    0b00011 => {
1887                        if ld != 0b11 {
1888                            return Err(StandardDecodeError::InvalidOperand);
1889                        }
1890                        Opcode::ABS
1891                    }
1892                    0b00100 => Opcode::MAX,
1893                    0b00101 => Opcode::MIN,
1894                    0b00110 => Opcode::EMUL,
1895                    0b00111 => Opcode::EMULU,
1896                    0b01000 => Opcode::DIV,
1897                    0b01001 => Opcode::DIVU,
1898                    0b01010 => { return Err(StandardDecodeError::InvalidOperand); },
1899                    0b01011 => { return Err(StandardDecodeError::InvalidOperand); },
1900                    0b01100 => Opcode::TST,
1901                    0b01101 => Opcode::XOR,
1902                    0b01110 => {
1903                        if ld != 0b11 {
1904                            return Err(StandardDecodeError::InvalidOperand);
1905                        }
1906                        Opcode::NOT
1907                    }
1908                    0b01111 => { return Err(StandardDecodeError::InvalidOperand); },
1909                    0b10000 => Opcode::XCHG,
1910                    _ => {
1911                        debug_assert!(opc5 == 0b10001, "checked opc is below 0b10010");
1912                        Opcode::ITOF
1913                    }
1914                };
1915                handler.on_opcode_decoded(opcode)?;
1916                let source = handler.decode_mem_op(rs, ld, SizeCode::L, words)?;
1917                handler.on_operand_decoded(0, source)?;
1918                handler.on_operand_decoded(1, Operand::Register { num: rd })?;
1919            } else if opc5 < 0b10100 {
1920                // opc is larger. decoding gets more custom..
1921                if decoder.version < RxVersion::V2 {
1922                    return Err(StandardDecodeError::InvalidOpcode);
1923                }
1924
1925                handler.on_opcode_decoded(if opc5 & 1 == 0 {
1926                    Opcode::STZ
1927                } else {
1928                    Opcode::STNZ
1929                })?;
1930                handler.on_operand_decoded(0, Operand::Register { num: rs })?;
1931                handler.on_operand_decoded(1, Operand::Register { num: rd })?;
1932            } else if opc5 < 0b10101 {
1933                // 1 1 1 1 1 1 0 0 | 0 1 0 1 0 0 ..
1934                // nothing here (yet?)
1935                return Err(StandardDecodeError::InvalidOpcode);
1936            } else if opc5 < 0b10110 {
1937                // 1 1 1 1 1 1 0 0 | 0 1 0 1 0 1 ..
1938                // utof
1939                if decoder.version < RxVersion::V2 {
1940                    return Err(StandardDecodeError::InvalidOpcode);
1941                }
1942                handler.on_opcode_decoded(Opcode::UTOF)?;
1943                let op = handler.decode_mem_op(rs, ld, SizeCode::L, words)?;
1944                handler.on_operand_decoded(0, op)?;
1945                handler.on_operand_decoded(1, Operand::Register { num: rd })?;
1946            } else if opc5 < 0b11000 {
1947                // 1 1 1 1 1 1 0 0 | 0 1 1 0 x x ..
1948                // bfmov{,z}
1949                if decoder.version < RxVersion::V3 {
1950                    return Err(StandardDecodeError::InvalidOpcode);
1951                }
1952                let regs = handler.read_u8(words)?;
1953                handler.on_opcode_decoded(if opc5 & 1 == 0 {
1954                    Opcode::BFMOVZ
1955                } else {
1956                    Opcode::BFMOV
1957                })?;
1958                let rs = regs >> 4;
1959                let rd = regs & 0b1111;
1960
1961                let bits = handler.read_u16(words)?;
1962                handler.on_operand_decoded(0, Operand::BitfieldSpec { bf_spec: BitfieldSpec { bits } })?;
1963                handler.on_operand_decoded(1, Operand::Register { num: rs })?;
1964                handler.on_operand_decoded(2, Operand::Register { num: rd })?;
1965            } else if opc5 < 0b11100 {
1966                let opcode = [Opcode::BSET, Opcode::BCLR, Opcode::BTST, Opcode::BNOT][opc5 as usize & 0b11];
1967                handler.on_opcode_decoded(opcode)?;
1968                handler.on_operand_decoded(0, Operand::Register { num: rs })?;
1969                let op = handler.decode_mem_op(rd, ld, SizeCode::B, words)?;
1970                handler.on_operand_decoded(1, op)?;
1971            } else if opc5 == 0b11110 {
1972                if decoder.version < RxVersion::V3 {
1973                    return Err(StandardDecodeError::InvalidOpcode);
1974                }
1975
1976                let regs = handler.read_u8(words)?;
1977                let regs_lo = regs & 0b1111;
1978                // this encoding of dmov.d just.. requires 1000 here? no reason as far as i can
1979                // see, it Just Does.
1980                if regs_lo != 0b1000 {
1981                    return Err(StandardDecodeError::InvalidOpcode);
1982                }
1983                let rd = regs >> 4;
1984                let dest_op = handler.decode_mem_op(rd, ld, SizeCode::D, words)?;
1985                let regs = handler.read_u8(words)?;
1986                let rs = regs >> 4;
1987                let regs_lo = regs & 0b1111;
1988                // similarly, just requires that the low four bits here are all 0.
1989                if regs_lo != 0b0000 {
1990                    return Err(StandardDecodeError::InvalidOpcode);
1991                }
1992
1993                handler.on_opcode_decoded(Opcode::DMOV)?;
1994                handler.on_operand_decoded(0, Operand::DoubleReg { num: rs })?;
1995                handler.on_operand_decoded(1, dest_op)?;
1996            } else {
1997                // 1 1 1 1 1 1 0 0 | 0 1 1 1 1 l ...
1998                return Err(StandardDecodeError::InvalidOpcode);
1999            }
2000        } else {
2001            // 1 1 1 1 1 1 0 0 | 1 ..
2002            if opc5 < 0b10000 {
2003                let opcode = match opc5 & 0b1111 {
2004                    0b0000 => Opcode::FSUB,
2005                    0b0001 => Opcode::FCMP,
2006                    0b0010 => Opcode::FADD,
2007                    0b0011 => Opcode::FMUL,
2008                    0b0100 => Opcode::FDIV,
2009                    0b0101 => Opcode::FTOI,
2010                    0b0110 => Opcode::ROUND,
2011                    0b1000 => {
2012                        if decoder.version < RxVersion::V2 {
2013                            return Err(StandardDecodeError::InvalidOpcode);
2014                        }
2015                        Opcode::FSQRT
2016                    },
2017                    0b1001 => {
2018                        if decoder.version < RxVersion::V2 {
2019                            return Err(StandardDecodeError::InvalidOpcode);
2020                        }
2021                        Opcode::FTOU
2022                    },
2023                    _ => {
2024                        return Err(StandardDecodeError::InvalidOpcode);
2025                    }
2026                };
2027                let regs = handler.read_u8(words)?;
2028                let rs = regs >> 4;
2029                let rd = regs & 0b1111;
2030                let source = handler.decode_mem_op(rs, ld, SizeCode::D, words)?;
2031                handler.on_opcode_decoded(opcode)?;
2032                handler.on_operand_decoded(0, source)?;
2033                handler.on_operand_decoded(1, Operand::DoubleReg { num: rd })?;
2034            } else if opc5 == 0b10010 {
2035                // 1 1 1 1 1 1 0 0 | 1 1 0 0 1 0 ..
2036                // dmovd
2037                if decoder.version < RxVersion::V3 {
2038                    return Err(StandardDecodeError::InvalidOpcode);
2039                }
2040
2041                let operands = handler.read_u8(words)?;
2042                let rs = operands >> 4;
2043                if operands & 0b1111 != 0b1000 {
2044                    return Err(StandardDecodeError::InvalidOpcode);
2045                }
2046                let source = handler.decode_mem_op(rs, ld, SizeCode::D, words)?;
2047                let operands = handler.read_u8(words)?;
2048                let rd = operands >> 4;
2049                if operands & 0b1111 != 0b0000 {
2050                    return Err(StandardDecodeError::InvalidOpcode);
2051                }
2052
2053                handler.on_opcode_decoded(Opcode::DMOV)?;
2054                handler.on_operand_decoded(0, source)?;
2055                handler.on_operand_decoded(1, Operand::DoubleReg { num: rd })?;
2056            } else if opc5 < 0b11000 {
2057                // 1 1 1 1 1 1 0 0 | 1 1 0 1 sz ..
2058                // SCCnd.size
2059                let operands = handler.read_u8(words)?;
2060                let rd = operands >> 4;
2061                let cnd = operands & 0b1111;
2062                let sz = match opc5 & 0b11 {
2063                    0b00 => SizeCode::B,
2064                    0b01 => SizeCode::W,
2065                    0b10 => SizeCode::L,
2066                    _ => {
2067                        return Err(StandardDecodeError::InvalidOperand);
2068                    }
2069                };
2070                if cnd >= 0b1110 {
2071                    return Err(StandardDecodeError::InvalidOpcode);
2072                }
2073                let opcode = [
2074                    Opcode::SCEQ, Opcode::SCNE, Opcode::SCGEU, Opcode::SCLTU,
2075                    Opcode::SCGTU, Opcode::SCLEU, Opcode::SCPZ, Opcode::SCN,
2076                    Opcode::SCGE, Opcode::SCLT, Opcode::SCGT, Opcode::SCLE,
2077                    Opcode::SCO, Opcode::SCNO, Opcode::NOP, Opcode::NOP // "NOP" is never reached: cnd>=1110, invalid above
2078                ][cnd as usize];
2079                handler.on_opcode_decoded(opcode)?;
2080                let op = handler.decode_mem_op(rd, ld, sz, words)?;
2081                handler.on_operand_decoded(0, op)?;
2082            } else if opc5 >= 0b11000 {
2083                // 1 1 1 1 1 1 0 0 | 1 1 1 [imm3] ..
2084                let operands = handler.read_u8(words)?;
2085                let rd = operands >> 4;
2086                let cnd = operands & 0b1111;
2087                let imm = opc5 & 0b111;
2088
2089                if ld == 0b11 {
2090                    return Err(StandardDecodeError::InvalidOperand);
2091                }
2092
2093                let opcode = if cnd == 0b1111 {
2094                    Opcode::BNOT
2095                } else if cnd == 0b1110 {
2096                    return Err(StandardDecodeError::InvalidOpcode);
2097                } else {
2098                    [
2099                        Opcode::BMEQ, Opcode::BMNE, Opcode::BMGEU, Opcode::BMLTU,
2100                        Opcode::BMGTU, Opcode::BMLEU, Opcode::BMPZ, Opcode::BMN,
2101                        Opcode::BMGE, Opcode::BMLT, Opcode::BMGT, Opcode::BMLE,
2102                        Opcode::BMO, Opcode::BMNO, Opcode::NOP, Opcode::NOP // "NOP" is never reached: cnd>=1110, invalid above
2103                    ][cnd as usize]
2104                };
2105                handler.on_opcode_decoded(opcode)?;
2106                handler.on_operand_decoded(0, Operand::ImmB { imm })?;
2107                let op = handler.decode_mem_op(rd, ld, SizeCode::B, words)?;
2108                handler.on_operand_decoded(1, op)?;
2109            } else {
2110                unreachable!("should be unreachable, fuzzing will tell..");
2111            }
2112        }
2113    } else if opc == 0b1111_1101 {
2114        // many instructions
2115        // for *almost* everything under this category, the next byte also picks opcodes. some use
2116        // bits here for operands though.
2117        let opcode = handler.read_u8(words)?;
2118
2119        if opcode < 0b1000_0000 {
2120            // 1 1 1 1 1 1 0 1 | 0 ....
2121            if opcode < 0b0001_0000 {
2122                let a = (opcode >> 3) & 1;
2123                if a != 0 && decoder.version < RxVersion::V2 {
2124                    return Err(StandardDecodeError::InvalidOperand);
2125                }
2126
2127                let regs = handler.read_u8(words)?;
2128                let rs = regs >> 4;
2129                let rs2 = regs & 0b1111;
2130
2131                // hokey, but this does filter for mullh, emula, maclh, and emaca
2132                if opcode & 0b010 != 0b000 && decoder.version < RxVersion::V2 {
2133                    return Err(StandardDecodeError::InvalidOpcode);
2134                }
2135
2136                let opcode = match opcode & 0b111 {
2137                    0b000 => Opcode::MULHI,
2138                    0b001 => Opcode::MULLO,
2139                    0b010 => Opcode::MULLH,
2140                    0b011 => Opcode::EMULA,
2141                    0b100 => Opcode::MACHI,
2142                    0b101 => Opcode::MACLO,
2143                    0b110 => Opcode::MACLH,
2144                    _ => Opcode::EMACA,
2145                };
2146                handler.on_opcode_decoded(opcode)?;
2147                handler.on_operand_decoded(0, Operand::Register { num: rs })?;
2148                handler.on_operand_decoded(1, Operand::Register { num: rs2 })?;
2149                handler.on_operand_decoded(2, Operand::Accumulator { num: a })?;
2150            } else if opcode == 0b0001_0111 {
2151                let operands = handler.read_u8(words)?;
2152                let rs = operands & 0b1111;
2153                let opc = (operands >> 4) & 0b111;
2154                let a = operands >> 7;
2155
2156                if a != 0 && decoder.version < RxVersion::V2 {
2157                    return Err(StandardDecodeError::InvalidOperand);
2158                }
2159
2160                let opcode = match opc {
2161                    0b000 => Opcode::MVTACHI,
2162                    0b001 => Opcode::MVTACLO,
2163                    0b011 => {
2164                        if decoder.version < RxVersion::V2 {
2165                            return Err(StandardDecodeError::InvalidOpcode);
2166                        }
2167                        Opcode::MVTACGU
2168                    }
2169                    _ => {
2170                        return Err(StandardDecodeError::InvalidOpcode);
2171                    }
2172                };
2173                handler.on_opcode_decoded(opcode)?;
2174                handler.on_operand_decoded(0, Operand::Register { num: rs })?;
2175                handler.on_operand_decoded(1, Operand::Accumulator { num: a })?;
2176            } else if opcode & 0b1111_1110 == 0b0001_1000 {
2177                // we can use the lowest bit of opcode to decide if this is racw/racl (0==racw)
2178                let wide = opcode & 1;
2179
2180                let operands = handler.read_u8(words)?;
2181                if operands & 0b1111 != 0 {
2182                    return Err(StandardDecodeError::InvalidOperand);
2183                }
2184                let imm = (operands >> 4) & 0b11;
2185                let opc = (operands >> 6) & 1;
2186                let a = operands >> 7;
2187
2188                if imm > 0b01 {
2189                    return Err(StandardDecodeError::InvalidOperand);
2190                }
2191
2192                if a != 0 && decoder.version < RxVersion::V2 {
2193                    return Err(StandardDecodeError::InvalidOperand);
2194                }
2195
2196                let opcode = if opc == 0 {
2197                    if wide == 0 { Opcode::RACW } else { Opcode::RACL }
2198                } else if decoder.version >= RxVersion::V2 {
2199                    if wide == 0 { Opcode::RDACW } else { Opcode::RDACL }
2200                } else {
2201                    return Err(StandardDecodeError::InvalidOpcode);
2202                };
2203                handler.on_opcode_decoded(opcode)?;
2204                handler.on_operand_decoded(0, Operand::ImmB { imm: imm + 1 })?;
2205                handler.on_operand_decoded(1, Operand::Accumulator { num: a })?;
2206            } else if opcode & 0b1111_1110 == 0b0001_1110 {
2207                let operands = handler.read_u8(words)?;
2208                let rd = operands & 0b1111;
2209                let immlo = (operands >> 6) & 1;
2210                let immhi = opcode & 1;
2211                let imm = (immhi << 1) | immlo;
2212                let opc = (operands >> 4) & 0b11;
2213                let a = operands >> 7;
2214
2215                let opcode = match opc {
2216                    0b00 => Opcode::MVFACHI,
2217                    0b01 => {
2218                        if decoder.version < RxVersion::V2 {
2219                            return Err(StandardDecodeError::InvalidOpcode);
2220                        }
2221                        Opcode::MVFACLO
2222                    }
2223                    0b10 => Opcode::MVFACMI,
2224                    _ => {
2225                        if decoder.version < RxVersion::V2 {
2226                            return Err(StandardDecodeError::InvalidOpcode);
2227                        }
2228                        Opcode::MVFACGU
2229                    }
2230                };
2231
2232                if imm != 0 && decoder.version < RxVersion::V2 {
2233                    return Err(StandardDecodeError::InvalidOperand);
2234                }
2235
2236                handler.on_opcode_decoded(opcode)?;
2237                handler.on_operand_decoded(0, Operand::ImmB { imm })?;
2238                handler.on_operand_decoded(1, Operand::Accumulator { num: a })?;
2239                handler.on_operand_decoded(2, Operand::Register { num: rd })?;
2240            } else if opcode < 0b0100_0000 {
2241                // 1 1 1 1 1 1 0 1 | 0 0 1 x x x x x
2242                // nothing here yet
2243                return Err(StandardDecodeError::InvalidOpcode);
2244            } else if opcode < 0b0101_0000 {
2245                // 1 1 1 1 1 1 0 1 | 0 1 0 0 a x x x
2246                if opcode & 0b0000_0100 != 0 {
2247                    // nothing here, msbhi and friends require bit above xx to be 1
2248                    return Err(StandardDecodeError::InvalidOpcode);
2249                }
2250
2251                if decoder.version < RxVersion::V2 {
2252                    return Err(StandardDecodeError::InvalidOpcode);
2253                }
2254
2255                let a = (opcode >> 3) & 1;
2256                let opc = opcode & 0b11;
2257                let operands = handler.read_u8(words)?;
2258                let rs = operands >> 4;
2259                let rs2 = operands & 0b1111;
2260
2261                let opcode = [Opcode::MSBHI, Opcode::MSBLH, Opcode::MSBLO, Opcode::EMSBA][opc as usize];
2262                handler.on_opcode_decoded(opcode)?;
2263                handler.on_operand_decoded(0, Operand::Register { num: rs })?;
2264                handler.on_operand_decoded(1, Operand::Register { num: rs2 })?;
2265                handler.on_operand_decoded(2, Operand::Accumulator { num: a })?;
2266            } else if opcode < 0b0110_0000 {
2267                // 1 1 1 1 1 1 0 1 | 0 1 0 1 x x x x
2268                // nothing here yet either
2269                return Err(StandardDecodeError::InvalidOpcode);
2270            } else if opcode < 0b0110_1000 {
2271                // 1 1 1 1 1 1 0 1 | 0 1 1 0 0 x x x
2272                let operands = handler.read_u8(words)?;
2273                let rd = operands & 0b1111;
2274                let rs = operands >> 4;
2275
2276                let opcode = match opcode & 0b111 {
2277                    0b000 => Opcode::SHLR,
2278                    0b001 => Opcode::SHAR,
2279                    0b010 => Opcode::SHLL,
2280                    0b011 => { return Err(StandardDecodeError::InvalidOpcode); },
2281                    0b100 => Opcode::ROTR,
2282                    0b101 => Opcode::REVW,
2283                    0b110 => Opcode::ROTL,
2284                    _ => Opcode::REVL,
2285                };
2286
2287                handler.on_opcode_decoded(opcode)?;
2288                handler.on_operand_decoded(0, Operand::Register { num: rs })?;
2289                handler.on_operand_decoded(1, Operand::Register { num: rd })?;
2290            } else if opcode == 0b0110_1000 {
2291                let operands = handler.read_u8(words)?;
2292                let cr = operands & 0b1111;
2293                let rs = operands >> 4;
2294
2295                if cr == 0b0010 {
2296                    // can't move to pc
2297                    return Err(StandardDecodeError::InvalidOperand);
2298                }
2299                handler.on_opcode_decoded(Opcode::MVTC)?;
2300                handler.on_operand_decoded(0, Operand::Register { num: rs })?;
2301                handler.on_operand_decoded(1, decoder.reg_to_control_reg(cr)?)?;
2302            } else if opcode == 0b0110_1010 {
2303                let operands = handler.read_u8(words)?;
2304                let rd = operands & 0b1111;
2305                let cr = operands >> 4;
2306
2307                handler.on_opcode_decoded(Opcode::MVFC)?;
2308                handler.on_operand_decoded(0, decoder.reg_to_control_reg(cr)?)?;
2309                handler.on_operand_decoded(1, Operand::Register { num: rd })?;
2310            } else if opcode < 0b0110_1100 {
2311                return Err(StandardDecodeError::InvalidOpcode);
2312            } else if opcode < 0b0111_0000 {
2313                // 1 1 1 1 1 1 0 1 | 0 1 1 0 1 1 x x
2314                // rotr/rotl
2315                let operands = handler.read_u8(words)?;
2316                let rd = operands & 0b1111;
2317                let immlo = operands >> 4;
2318                let immhi = opcode & 1;
2319                let imm = (immhi << 4) | immlo;
2320                handler.on_opcode_decoded(if opcode & 0b10 == 0 {
2321                    Opcode::ROTR
2322                } else {
2323                    Opcode::ROTL
2324                })?;
2325                handler.on_operand_decoded(0, Operand::ImmB { imm })?;
2326                handler.on_operand_decoded(1, Operand::Register { num: rd })?;
2327            } else if opcode == 0b0111_0101 {
2328                if decoder.version < RxVersion::V3 {
2329                    return Err(StandardDecodeError::InvalidOpcode);
2330                }
2331
2332                let operands = handler.read_u8(words)?;
2333                if operands & 0b1111_0000 != 0b1000_0000 {
2334                    return Err(StandardDecodeError::InvalidOpcode);
2335                }
2336                let rd = operands & 0b1111;
2337                let operands = handler.read_u8(words)?;
2338                let opc = operands & 0b1111;
2339                let rs = operands >> 4;
2340
2341                match opc {
2342                    0b0000 => {
2343                        handler.on_opcode_decoded(Opcode::DMOV)?;
2344                        handler.on_operand_decoded(0, Operand::DoubleRegLow { num: rs })?;
2345                        handler.on_operand_decoded(1, Operand::Register { num: rd })?;
2346                    }
2347                    0b0010 => {
2348                        handler.on_opcode_decoded(Opcode::DMOV)?;
2349                        handler.on_operand_decoded(0, Operand::DoubleRegHigh { num: rs })?;
2350                        handler.on_operand_decoded(1, Operand::Register { num: rd })?;
2351                    }
2352                    0b0100 => {
2353                        handler.on_opcode_decoded(Opcode::MVFDC)?;
2354                        handler.on_operand_decoded(0, Operand::DoubleRegHigh { num: rs })?;
2355                        handler.on_operand_decoded(1, decoder.reg_to_double_control_reg(rd)?)?;
2356                    }
2357                    _ => { return Err(StandardDecodeError::InvalidOpcode) }
2358                }
2359            } else if opcode == 0b0111_0110 {
2360                if decoder.version < RxVersion::V3 {
2361                    return Err(StandardDecodeError::InvalidOpcode);
2362                }
2363
2364                let operands = handler.read_u8(words)?;
2365                let opc = operands >> 4;
2366                let rs = operands & 0b1111;
2367                let imm = handler.read_u8(words)?;
2368
2369                match opc {
2370                    0b1100 => {
2371                        if imm != 0b0000_0000 {
2372                            return Err(StandardDecodeError::InvalidOperand);
2373                        }
2374                        handler.on_opcode_decoded(Opcode::SAVE)?;
2375                        handler.on_operand_decoded(0, Operand::Register { num: rs })?;
2376                    }
2377                    0b1101 => {
2378                        if imm != 0b0000_0000 {
2379                            return Err(StandardDecodeError::InvalidOperand);
2380                        }
2381                        handler.on_opcode_decoded(Opcode::RSTR)?;
2382                        handler.on_operand_decoded(0, Operand::Register { num: rs })?;
2383                    }
2384                    0b1110 => {
2385                        if rs != 0b0000_0000 {
2386                            return Err(StandardDecodeError::InvalidOperand);
2387                        }
2388                        handler.on_opcode_decoded(Opcode::SAVE)?;
2389                        handler.on_operand_decoded(0, Operand::ImmB { imm })?;
2390                    }
2391                    0b1111 => {
2392                        if rs != 0b0000_0000 {
2393                            return Err(StandardDecodeError::InvalidOperand);
2394                        }
2395                        handler.on_opcode_decoded(Opcode::RSTR)?;
2396                        handler.on_operand_decoded(0, Operand::ImmB { imm })?;
2397                    }
2398                    _ => { return Err(StandardDecodeError::InvalidOpcode) }
2399                };
2400            } else if opcode == 0b0111_0111 {
2401                if decoder.version < RxVersion::V3 {
2402                    return Err(StandardDecodeError::InvalidOpcode);
2403                }
2404
2405                let operands = handler.read_u8(words)?;
2406                if operands & 0b1111_0000 != 0b1000_0000 {
2407                    return Err(StandardDecodeError::InvalidOpcode);
2408                }
2409                let rs = operands & 0b1111;
2410                let operands = handler.read_u8(words)?;
2411                let rd = operands >> 4;
2412                let opc = operands & 0b1111;
2413                match opc {
2414                    0b0000 => {
2415                        // dmov.l from gpr to drlN (encoding 3)
2416                        handler.on_opcode_decoded(Opcode::DMOV)?;
2417                        handler.on_operand_decoded(0, Operand::Register { num: rs })?;
2418                        handler.on_operand_decoded(1, Operand::DoubleRegLow { num: rd })?;
2419                    }
2420                    0b0010 => {
2421                        // dmov.l from gpr to drhN (encoding 2)
2422                        handler.on_opcode_decoded(Opcode::DMOV)?;
2423                        handler.on_operand_decoded(0, Operand::Register { num: rs })?;
2424                        handler.on_operand_decoded(1, Operand::DoubleRegHigh { num: rd })?;
2425                    }
2426                    0b0011 => {
2427                        // mov.d from gpr to drhN (encoding 1) (... ? what ... )
2428                        handler.on_opcode_decoded(Opcode::DMOV)?;
2429                        handler.on_operand_decoded(0, Operand::Register { num: rs })?;
2430                        handler.on_operand_decoded(1, Operand::DoubleReg { num: rd })?;
2431                    }
2432                    0b0100 => {
2433                        // mvtdc
2434                        let cr = decoder.reg_to_double_control_reg(rd)?;
2435                        handler.on_opcode_decoded(Opcode::MVTDC)?;
2436                        handler.on_operand_decoded(0, Operand::Register { num: rs })?;
2437                        handler.on_operand_decoded(1, cr)?;
2438                    }
2439                    0b1001 => {
2440                        // itod
2441                        handler.on_opcode_decoded(Opcode::ITOD)?;
2442                        handler.on_operand_decoded(0, Operand::Register { num: rs })?;
2443                        handler.on_operand_decoded(1, Operand::DoubleReg { num: rd })?;
2444                    }
2445                    0b1010 => {
2446                        // ftod
2447                        handler.on_opcode_decoded(Opcode::FTOD)?;
2448                        handler.on_operand_decoded(0, Operand::Register { num: rs })?;
2449                        handler.on_operand_decoded(1, Operand::DoubleReg { num: rd })?;
2450                    }
2451                    0b1101 => {
2452                        // utod
2453                        handler.on_opcode_decoded(Opcode::UTOD)?;
2454                        handler.on_operand_decoded(0, Operand::Register { num: rs })?;
2455                        handler.on_operand_decoded(1, Operand::DoubleReg { num: rd })?;
2456                    }
2457                    _ => {
2458                        return Err(StandardDecodeError::InvalidOpcode);
2459                    }
2460                }
2461            } else if opcode < 0b0111_0000 {
2462                // any unhandled cases below 0111_0000, which need more... careful handling.
2463                return Err(StandardDecodeError::InvalidOpcode);
2464            } else {
2465                let li = (opcode >> 2) & 0b11;
2466                let opc_lo = opcode & 0b11;
2467                if opc_lo == 0b00 {
2468                    // 1 1 1 1 1 1 0 1 | 0 1 1 1 xx  0 0 | ...
2469                    // <op> imm, reg
2470                    let opcode = handler.read_u8(words)?;
2471                    let rd = opcode & 0b1111;
2472                    let opcode = opcode >> 4;
2473                    let opcode = match opcode {
2474                        0b0010 => Opcode::ADC,
2475                        0b0100 => Opcode::MAX,
2476                        0b0101 => Opcode::MIN,
2477                        0b0110 => Opcode::EMUL,
2478                        0b0111 => Opcode::EMULU,
2479                        0b1000 => Opcode::DIV,
2480                        0b1001 => Opcode::DIVU,
2481                        0b1100 => Opcode::TST,
2482                        0b1101 => Opcode::XOR,
2483                        0b1110 => Opcode::STZ,
2484                        0b1111 => Opcode::STNZ,
2485                        _ => { return Err(StandardDecodeError::InvalidOpcode) }
2486                    };
2487                    handler.on_opcode_decoded(opcode)?;
2488                    let imm = match li {
2489                        0b00 => {
2490                            handler.read_u32(words)?
2491                        }
2492                        0b01 => {
2493                            handler.read_u8(words)? as i8 as i32 as u32
2494                        }
2495                        0b10 => {
2496                            handler.read_u16(words)? as i16 as i32 as u32
2497                        }
2498                        _ => {
2499                            debug_assert!(li == 0b11, "li is at most the low two bits set");
2500                            handler.read_i24(words)? as u32
2501                        }
2502                    };
2503                    handler.on_operand_decoded(0, Operand::ImmL { imm })?;
2504                    handler.on_operand_decoded(1, Operand::Register { num: rd })?;
2505                } else if opc_lo == 0b11 {
2506                    // 1 1 1 1 1 1 0 1 | 0 1 1 1 xx  1 1 | ...
2507                    // mvtc imm, creg
2508                    let opcode = handler.read_u8(words)?;
2509                    let rd = opcode & 0b1111;
2510                    let opcode = opcode >> 4;
2511                    if opcode != 0b0000 {
2512                        return Err(StandardDecodeError::InvalidOpcode);
2513                    }
2514                    if rd == 0b0001 {
2515                        // can't set pc
2516                        return Err(StandardDecodeError::InvalidOperand);
2517                    }
2518                    let cr = decoder.reg_to_control_reg(rd)?;
2519                    handler.on_opcode_decoded(Opcode::MVTC)?;
2520                    let imm = match li {
2521                        0b00 => {
2522                            handler.read_u32(words)?
2523                        }
2524                        0b01 => {
2525                            handler.read_u8(words)? as i8 as i32 as u32
2526                        }
2527                        0b10 => {
2528                            handler.read_u16(words)? as i16 as i32 as u32
2529                        }
2530                        _ => {
2531                            debug_assert!(li == 0b11, "li is at most the low two bits set");
2532                            handler.read_i24(words)? as u32
2533                        }
2534                    };
2535                    handler.on_operand_decoded(0, Operand::ImmL { imm })?;
2536                    handler.on_operand_decoded(1, cr)?;
2537                } else if opc_lo == 0b10 {
2538                    // 1 1 1 1 1 1 0 1 | 0 1 1 1 xx  1 0 | ...
2539                    // <float op> imm, reg
2540                    if li != 0b00 {
2541                        return Err(StandardDecodeError::InvalidOperand);
2542                    }
2543
2544                    let opcode = handler.read_u8(words)?;
2545                    let rd = opcode & 0b1111;
2546                    let opcode = opcode >> 4;
2547                    if opcode > 0b100 {
2548                        return Err(StandardDecodeError::InvalidOpcode);
2549                    }
2550                    handler.on_opcode_decoded(
2551                        [Opcode::FSUB, Opcode::FCMP, Opcode::FADD, Opcode::FMUL, Opcode::FDIV][opcode as usize]
2552                    )?;
2553                    let imm = handler.read_u32(words)?;
2554                    handler.on_operand_decoded(0, Operand::ImmL { imm })?;
2555                    handler.on_operand_decoded(1, Operand::Register { num: rd })?;
2556                } else {
2557                    return Err(StandardDecodeError::InvalidOpcode);
2558                }
2559            }
2560        } else {
2561            // 1 1 1 1 1 1 0 1 | 1 ....
2562            let opc = (opcode >> 5) & 0b11;
2563            let imm5 = opcode & 0b1_1111;
2564
2565            let operands = handler.read_u8(words)?;
2566            let rd = operands & 0b1111;
2567            let rs2 = operands >> 4;
2568
2569            if opc == 0b11 {
2570                // bmcnd/bnot
2571                let cnd = rs2;
2572                let opcode = [
2573                    Opcode::BMEQ, Opcode::BMNE, Opcode::BMGEU, Opcode::BMLTU,
2574                    Opcode::BMGTU, Opcode::BMLEU, Opcode::BMPZ, Opcode::BMN,
2575                    Opcode::BMGE, Opcode::BMLT, Opcode::BMGT, Opcode::BMLE,
2576                    Opcode::BMO, Opcode::BMNO, Opcode::NOP, Opcode::BNOT // "NOP" is never reached: cnd>=1110, invalid above
2577                ][cnd as usize];
2578                handler.on_opcode_decoded(opcode)?;
2579                handler.on_operand_decoded(0, Operand::ImmB { imm: imm5 })?;
2580                handler.on_operand_decoded(1, Operand::Register { num: rd })?;
2581            } else {
2582                let opcode = [Opcode::SHLR, Opcode::SHAR, Opcode::SHLL][opc as usize];
2583                handler.on_opcode_decoded(opcode)?;
2584                handler.on_operand_decoded(0, Operand::ImmB { imm: imm5 })?;
2585                handler.on_operand_decoded(1, Operand::Register { num: rs2 })?;
2586                handler.on_operand_decoded(2, Operand::Register { num: rd })?;
2587            }
2588        }
2589    } else if opc == 0b1111_1110 {
2590        // mov
2591        let operands = handler.read_u8(words)?;
2592        let next_regs = handler.read_u8(words)?;
2593        let ri = operands & 0b1111;
2594        let rb = next_regs >> 4;
2595        let rd = next_regs & 0b1111;
2596        let sz = (operands >> 4) & 0b11;
2597
2598        if sz == 0b11 {
2599            return Err(StandardDecodeError::InvalidOperand);
2600        }
2601
2602        let sz = [SizeCode::B, SizeCode::W, SizeCode::L][sz as usize];
2603
2604        if operands < 0b0100_0000 {
2605            handler.on_opcode_decoded(Opcode::MOV)?;
2606            handler.on_operand_decoded(0, Operand::Register { num: rd })?;
2607            handler.on_operand_decoded(1, Operand::DerefIndexed { base: rb, index: ri, width: sz })?;
2608        } else if operands < 0b1000_0000 {
2609            handler.on_opcode_decoded(Opcode::MOV)?;
2610            handler.on_operand_decoded(0, Operand::DerefIndexed { base: rb, index: ri, width: sz })?;
2611            handler.on_operand_decoded(1, Operand::Register { num: rd })?;
2612        } else if operands < 0b1100_0000 {
2613            // 1 1 1 1 1 1 1 0 | 1 0 ..
2614            // nothing encoded here
2615            return Err(StandardDecodeError::InvalidOpcode);
2616        } else if operands < 0b1110_0000 {
2617            if sz == SizeCode::L {
2618                return Err(StandardDecodeError::InvalidOperand);
2619            }
2620
2621            handler.on_opcode_decoded(Opcode::MOVU)?;
2622            handler.on_operand_decoded(0, Operand::DerefIndexed { base: rb, index: ri, width: sz })?;
2623            handler.on_operand_decoded(1, Operand::Register { num: rd })?;
2624        } else {
2625            return Err(StandardDecodeError::InvalidOpcode);
2626        }
2627    } else if opc == 0b1111_1111 {
2628        // 3-operand instructions
2629        let operands = handler.read_u8(words)?;
2630        let rd = operands & 0b1111;
2631        let opc = operands >> 4;
2632        let extra_regs = handler.read_u8(words)?;
2633        let rs2 = extra_regs & 0b1111;
2634        let rs = extra_regs >> 4;
2635
2636        let opc = match opc {
2637            0b0000 => Opcode::SUB,
2638            0b0010 => Opcode::ADD,
2639            0b0011 => Opcode::MUL,
2640            0b0100 => Opcode::AND,
2641            0b0101 => Opcode::OR,
2642            0b0110 => {
2643                if decoder.version >= RxVersion::V3 {
2644                    Opcode::XOR
2645                } else {
2646                    return Err(StandardDecodeError::InvalidOpcode);
2647                }
2648            },
2649            0b1000 => {
2650                if decoder.version >= RxVersion::V2 {
2651                    Opcode::FSUB
2652                } else {
2653                    return Err(StandardDecodeError::InvalidOpcode);
2654                }
2655            },
2656            0b1010 => {
2657                if decoder.version >= RxVersion::V2 {
2658                    Opcode::FADD
2659                } else {
2660                    return Err(StandardDecodeError::InvalidOpcode);
2661                }
2662            },
2663            0b1011 => {
2664                if decoder.version >= RxVersion::V2 {
2665                    Opcode::FMUL
2666                } else {
2667                    return Err(StandardDecodeError::InvalidOpcode);
2668                }
2669            },
2670            _ => {
2671                return Err(StandardDecodeError::InvalidOpcode);
2672            }
2673        };
2674
2675        handler.on_opcode_decoded(opc)?;
2676        handler.on_operand_decoded(0, Operand::Register { num: rs })?;
2677        handler.on_operand_decoded(1, Operand::Register { num: rs2 })?;
2678        handler.on_operand_decoded(2, Operand::Register { num: rd })?;
2679    } else {
2680        unreachable!("fuzzing should show this to be unreachable");
2681    }
2682
2683    Ok(())
2684}