yaxpeax_hexagon/
lib.rs

1//! qualcomm `hexagon` decoder implemented as part of the `yaxpeax` project. implements traits
2//! provided by `yaxpeax-arch`.
3//!
4//! decoder is written against the ISA described in `Qualcomm Hexagon V73`:
5//! * retrieved 2024-09-21 from https://docs.qualcomm.com/bundle/publicresource/80-N2040-53_REV_AB_Qualcomm_Hexagon_V73_Programmers_Reference_Manual.pdf
6//! * sha256: `44ebafd1119f725bd3c6ffb87499232520df9a0a6e3e3dc6ea329b15daed11a8`
7
8use yaxpeax_arch::{AddressDiff, Arch, Decoder, LengthedInstruction, Reader};
9use yaxpeax_arch::StandardDecodeError as DecodeError;
10
11#[cfg(feature = "fmt")]
12mod display;
13
14#[derive(Debug)]
15pub struct Hexagon;
16
17impl Arch for Hexagon {
18    type Word = u8;
19    /// V73 Section 3.3.7:
20    /// > Packets should not wrap the *4GB address space*.
21    type Address = u32;
22    type Instruction = InstructionPacket;
23    type DecodeError = yaxpeax_arch::StandardDecodeError;
24    type Decoder = InstDecoder;
25    type Operand = Operand;
26}
27
28#[derive(Debug, Copy, Clone, Default, PartialEq)]
29struct Predicate {
30    state: u8,
31}
32
33#[derive(Debug, Copy, Clone, PartialEq)]
34enum BranchHint {
35    Taken,
36    NotTaken,
37}
38
39macro_rules! opcode_check {
40    ($e:expr) => {
41        if !$e {
42            return Err(DecodeError::InvalidOpcode);
43        }
44    }
45}
46
47macro_rules! operand_check {
48    ($e:expr) => {
49        if !$e {
50            return Err(DecodeError::InvalidOperand);
51        }
52    }
53}
54
55macro_rules! decode_opcode {
56    ($e:expr) => {
57        match $e {
58            Some(v) => v,
59            None => {
60                return Err(DecodeError::InvalidOpcode);
61            }
62        }
63    }
64}
65
66macro_rules! decode_operand {
67    ($e:expr) => {
68        match $e {
69            Some(v) => v,
70            None => {
71                return Err(DecodeError::InvalidOperand);
72            }
73        }
74    }
75}
76
77// some configurations leave some helpers unused.
78// this probably should be public for programmatic inspection..
79#[allow(dead_code)]
80impl Predicate {
81    fn reg(num: u8) -> Self {
82        assert!(num <= 0b11);
83        Self { state: num }
84    }
85
86    fn num(&self) -> u8 {
87        self.state & 0b11
88    }
89
90    fn set_negated(mut self, bit: bool) -> Self {
91        if bit {
92            assert!(self.state & 0b0100 == 0);
93            self.state |= 0b0100;
94        }
95        self
96    }
97
98    fn negated(&self) -> bool {
99        self.state & 0b0100 != 0
100    }
101
102    fn set_pred_new(mut self, bit: bool) -> Self {
103        if bit {
104            assert!(self.state & 0b1000 == 0);
105            self.state |= 0b1000;
106        }
107        self
108    }
109
110    fn pred_new(&self) -> bool {
111        self.state & 0b1000 != 0
112    }
113}
114
115#[derive(Debug, Copy, Clone, Default, PartialEq)]
116pub struct LoopEnd {
117    loops_ended: u8
118}
119
120impl LoopEnd {
121    pub fn end_0(&self) -> bool {
122        self.loops_ended & 0b01 != 0
123    }
124
125    pub fn end_1(&self) -> bool {
126        self.loops_ended & 0b10 != 0
127    }
128
129    pub fn end_any(&self) -> bool {
130        self.loops_ended != 0
131    }
132
133    /// NOT FOR PUBLIC
134    fn mark_end(&mut self, lp: u8) {
135        self.loops_ended |= 1 << lp;
136    }
137}
138
139/// V73 Section 3.3.3:
140/// > The assembler automatically rejects packets that oversubscribe the hardware resources.
141///
142/// but such bit patterns may exist. invalid packets likely mean the disassembler has walked into
143/// invalid code, but should be decoded and shown as-is; the application using `yaxpeax-hexagon`
144/// must decide what to do with bogus instruction packets.
145///
146/// duplex instructions are decoded into a pair of [`Instruction`] in their enclosing packet.
147/// instruction packets with a duplex instruction may have no more than two other instructions in
148/// the packet; from V73 `Section 10.3 Duplexes`:
149/// > An instruction packet can contain one duplex and up to two other (non-duplex) instructions.
150/// > The duplex must always appear as the last word in a packet.
151///
152/// even with duplex instructions in bundles, `InstructionPacket` will hold no more than four
153/// `Instruction`.
154#[derive(Debug, Copy, Clone, Default)]
155pub struct InstructionPacket {
156    /// each packet has up to four instructions (V73 Section 1.1.3)
157    instructions: [Instruction; 4],
158    /// the actual number of instructions in this packet
159    instruction_count: u8,
160    /// the number of 4-byte instruction words this packet occupies
161    word_count: u8,
162    /// how this packet interacts with hardware loops 0 and/or 1
163    loop_effect: LoopEnd,
164}
165
166impl PartialEq for InstructionPacket {
167    fn eq(&self, other: &Self) -> bool {
168        let instructions = self.instruction_count as usize;
169        self.instruction_count == other.instruction_count &&
170            self.word_count == other.word_count &&
171            self.loop_effect == other.loop_effect &&
172            self.instructions[..instructions] == other.instructions[..instructions]
173    }
174}
175
176/// a decoded `hexagon` instruction. this is only one of potentially several instructions in an
177/// [`InstructionPacket`].
178///
179/// `Instruction` has some noteworthy quirks, as `hexagon` instructions can have ... varied shapes.
180///
181/// a general rule that is upheld by an instruction described by `Instruction` is that any operand
182/// between parentheses is recorded as a "source", and operands not in parentheses are recorded as
183/// "destination". for the simplest instructions, `opcode(operand)` or `opcode(op0, op1, ...)`,
184/// there will be no destination, and all operands are in `sources`. for an instruction like
185/// `r4 = add(r3, r5)`, `r4` is recorded as a destination, with `r3` and `r5` recorded as sources.
186///
187/// an exception to the above are stores, which look something like
188/// ```text
189/// memh(r4 + r2<<3) = r30
190/// ```
191/// in these cases the the operands are an `Operand::RegShiftedReg` describing the operand in
192/// parentheses, and an `Operand::Gpr` describing the source of the store on the right-hand side.
193///
194/// some instructions are more complex while not, themselves, duplex instructions. some conditional
195/// branches set a predicate, while others only compare with a new register value and leave
196/// predicate registers unaffected. the former look like
197/// ```text
198/// p0 = cmp.gtu(r15, #40); if (!p0.new) jump:t #354
199/// ```
200/// while the latter look like
201/// ```text
202/// if (cmp.eq(r4.new, r2)) jump:t #812
203/// ```
204///
205/// in the former case, there are two "destinations", `p0` and `PCRel32` for the jump target. `p0`
206/// is even used as a source later in the instruction. in the latter case there is only one
207/// destination (again, `PCRel32`), but the instruction is still more complex than a simple
208/// `result=op(src, src, src)` style.
209///
210/// to describe this, `yaxpeax-hexagon` has special rules for rendering several categories of
211/// instruction, and best effort is taken to describe special operand rules on the corresponding
212/// variant of `Instruction` that would be used with such special instructions.
213///
214/// additionally, useful excerpts from the `hexagon` manual to understand the meaning of
215/// disassembly listings either in this crate or test files are included below.
216///
217/// V5x Section 1.7.2 describes register access syntax. paraphrased:
218///
219/// registers may be written as `Rds[.elst]`.
220///
221/// `ds` describes the operand type and bit size:
222/// | Symbol | Operand Type | Size (in Bits) |
223/// |--------|--------------|----------------|
224/// | d      | Destination  | 32             |
225/// | dd     | Destination  | 64             |
226/// | s      | Source 1     | 32             |
227/// | ss     | Source 1     | 64             |
228/// | t      | Source 2     | 32             |
229/// | tt     | Source 2     | 64             |
230/// | u      | Source 3     | 32             |
231/// | uu     | Source 3     | 64             |
232/// | x      | Source+Dest  | 32             |
233/// | xx     | Source+Dest  | 64             |
234///
235/// `elst` describes access of the bit fields in register `Rds`. V5x Figure 1-4:
236///
237/// ```text
238/// |  .b[7] |  .b[6] |  .b[5] |  .b[4] |  .b[3] |  .b[2] |  .b[1] |  .b[0] |     signed bytes
239/// | .ub[7] | .ub[6] | .ub[5] | .ub[4] | .ub[3] | .ub[2] | .ub[1] | .ub[0] |   unsigned bytes
240/// |       .h[3]     |       .h[2]     |       .h[1]     |       .h[0]     |     signed halfwords
241/// |      .uh[3]     |      .uh[2]     |      .uh[1]     |      .uh[0]     |   unsigned halfwords
242/// |                .w[1]              |                .w[0]              |     signed words
243/// |               .uw[1]              |               .uw[0]              |   unsigned words
244/// ```
245///
246/// meanwhile a register can be accessed as a single element with some trailing specifiers. V5x
247/// Table 1-2:
248///
249/// ```text
250/// | Symbol | Meaning |
251/// |--------|---------|
252/// | .sN    | Bits `[N-1:0]` are treated as an N-bit signed number. For example, r0.s16 means the least significant 16 bits of r0 are treated as a 16-bit signed number. |
253/// | .uN    | Bits `[N-1:0]` are treated as an N-bit unsigned number. |
254/// | .H     | The most significant 16 bits of a 32-bit register. |
255/// | .L     | The least significant 16 bits of a 32-bit register. |
256/// ```
257///
258/// and finally, "Duplex instructions" (V73 Section 3.6):
259/// > Unlike Compound instructions, duplex instructions do not have distinctive syntax – in
260/// > assembly code they appear identical to the instructions they are composed of. The assembler
261/// > is responsible for recognizing when a pair of instructions can be encoded as a single duplex
262/// > rather than a pair of regular instruction words.
263///
264/// V73 Section 10.3 discusses duplex instructions in more detail:
265/// > A duplex is encoded as a 32-bit instruction with bits [15:14] set to 00. The sub-instructions
266/// > that comprise a duplex are encoded as 13-bit fields in the duplex.
267/// >
268/// > The sub-instructions in a duplex always execute in slot 0 and slot 1.
269///
270/// the representation of duplex instructions are described in more detail in
271/// [`InstructionPacket`].
272#[derive(Debug, Copy, Clone)]
273pub struct Instruction {
274    opcode: Opcode,
275    dest: Option<Operand>,
276    // an alternate destination operand for the handful of instructions that write to two
277    // destinations. in most cases, these are very close to duplex instructions (some operation;
278    // some other related operation), but it's not clear if instruction packets would error if
279    // these instruction cohabitate with three other instructions in a packet. for duplex
280    // instructions, it is simply an error to have duplex + 3 more slots, so duplex can be much
281    // more simply decoded into a series of instrucitons..
282    //
283    // the outliers here are store-conditional, where one operand is a register (address) and the
284    // other is a predicate register updated to indicate the successfulness of the store.
285    alt_dest: Option<Operand>,
286    flags: InstFlags,
287
288    sources: [Operand; 3],
289    sources_count: u8,
290}
291
292#[derive(Debug, Copy, Clone, PartialEq)]
293enum RoundingMode {
294    Round,
295    Cround,
296    Raw,
297    Pos,
298    Neg,
299}
300
301impl RoundingMode {
302    // if there's no `fmt` we don't need labels, for now.
303    // if RoundingMode were inspectable this might be useful even without fmt?
304    #[cfg(feature = "fmt")]
305    fn as_label(&self) -> &'static str {
306        match self {
307            RoundingMode::Round => ":rnd",
308            RoundingMode::Cround => ":crnd",
309            RoundingMode::Raw => ":raw",
310            RoundingMode::Pos => ":pos",
311            RoundingMode::Neg => ":neg",
312        }
313    }
314}
315
316#[derive(Debug, Copy, Clone, PartialEq)]
317enum AssignMode {
318    AddAssign,
319    SubAssign,
320    AndAssign,
321    OrAssign,
322    XorAssign,
323    ClrBit,
324    SetBit,
325}
326
327#[derive(Debug, Copy, Clone, PartialEq)]
328enum RawMode {
329    Lo,
330    Hi,
331}
332
333#[derive(Debug, Copy, Clone, PartialEq)]
334struct InstFlags {
335    predicate: Option<Predicate>,
336    branch_hint: Option<BranchHint>,
337    negated: bool,
338    saturate: bool,
339    scale: bool,
340    library: bool,
341    chop: bool,
342    rounded: Option<RoundingMode>,
343    threads: Option<DomainHint>,
344    assign_mode: Option<AssignMode>,
345    raw_mode: Option<RawMode>,
346    shift_left: Option<u8>,
347    shift_right: Option<u8>,
348    carry: bool,
349    deprecated: bool,
350}
351
352#[derive(Debug, Copy, Clone, PartialEq)]
353enum DomainHint {
354    Same,
355    All,
356}
357
358impl Default for InstFlags {
359    fn default() -> Self {
360        Self {
361            predicate: None,
362            branch_hint: None,
363            negated: false,
364            saturate: false,
365            scale: false,
366            library: false,
367            chop: false,
368            rounded: None,
369            threads: None,
370            assign_mode: None,
371            raw_mode: None,
372            shift_left: None,
373            shift_right: None,
374            carry: false,
375            deprecated: false,
376        }
377    }
378}
379
380/// V73 Section 3.1 indicates that jumps have taken/not-taken hints, saturation can be a hint,
381/// rounding can be a hint, predicate can be used for carry in/out, result shifting by fixed
382/// counts, and load/store reordering prevention are all kinds of hints that may be present.
383///
384/// additionally, V73 Section 3.2 outlines instruction classes which relate to the available
385/// execution units:
386/// ```text
387/// XTYPE
388///     XTYPE ALU           64-bit ALU operations
389///     XTYPE BIT           Bit operations
390///     XTYPE COMLPEX
391///     XTYPE FP
392///     XTYPE MPY
393///     XTYPE PERM          Vector permut and format conversion
394///     XTYPE PRED          Predicate operations
395///     XTYPE SHIFT         Shift operations (with optional ALU)
396/// ALU32                   32-bit ALU operations
397///     ALU32 ALU           Arithmetic and logical
398///     ALU32 PERM          Permute
399///     ALU32 PRED          Predicate operations
400/// CR
401/// JR
402/// J
403/// LD
404/// MEMOP
405/// NV
406///     NV J
407///     NV ST
408/// ST
409/// SYSTEM
410///     SYSTEM USER
411/// ```
412#[allow(non_camel_case_types)]
413#[derive(Debug, Copy, Clone, PartialEq, Eq)]
414#[repr(u16)]
415pub enum Opcode {
416    // this variant should never be seen externally.
417    #[doc(hidden)]
418    BUG,
419
420    Nop,
421
422    // V73 page 214 ("Jump to address")
423    Jump,
424    Jumpr,
425    Jumprh,
426    Call,
427    Callr,
428    Callrh,
429    Hintjr,
430
431    LoadMemb,
432    LoadMemub,
433    LoadMemh,
434    LoadMemuh,
435    LoadMemw,
436    LoadMemd,
437
438    StoreMemb,
439    StoreMemh,
440    StoreMemw,
441    StoreMemd,
442
443    Memb, Memub, Memh, Memuh, Memw, Memd,
444
445    Membh,
446    MemhFifo,
447    Memubh,
448    MembFifo,
449
450    Aslh,
451    Asrh,
452    TransferRegister,
453    /// the register to be transferred to is recorded in `alt_dest`. the jump target is in `dest`.
454    TransferRegisterJump,
455    Zxtb,
456    Sxtb,
457    Zxth,
458    Sxth,
459
460    TransferImmediate,
461    /// the register to be transferred to is recorded in `alt_dest`. the jump target is in `dest`.
462    TransferImmediateJump,
463
464    Mux,
465
466    Combine,
467    CmpEq,
468    CmpGt,
469    CmpGtu,
470    CmpbEq,
471    CmphEq,
472    CmpbGtu,
473    CmphGtu,
474    CmpbGt,
475    CmphGt,
476
477    JumpEq,
478    JumpNeq,
479    JumpGt,
480    JumpLe,
481    JumpGtu,
482    JumpLeu,
483    JumpBitSet,
484    JumpBitClear,
485
486    /// predicate register used for branch condition is part of normal predication bits
487    TestClrJump,
488    /// predicate register used for branch condition is part of normal predication bits
489    CmpEqJump,
490    /// predicate register used for branch condition is part of normal predication bits
491    CmpGtJump,
492    /// predicate register used for branch condition is part of normal predication bits
493    CmpGtuJump,
494
495    /// jump conditioned on a register being equal to zero
496    ///
497    /// source 1 is the register used for jump conditioning, source 2 is the relative branch
498    JumpRegZ,
499    /// jump conditioned on a register being nonzero
500    ///
501    /// source 1 is the register used for jump conditioning, source 2 is the relative branch
502    JumpRegNz,
503    /// jump conditioned on a register being greater than or equal to zero
504    ///
505    /// source 1 is the register used for jump conditioning, source 2 is the relative branch
506    JumpRegGez,
507    /// jump conditioned on a register being less than or equal to zero
508    ///
509    /// source 1 is the register used for jump conditioning, source 2 is the relative branch
510    JumpRegLez,
511
512    Add,
513    And,
514    And_nRR,
515    And_RnR,
516    Sub,
517    Or,
518    Or_nRR,
519    Or_RnR,
520    Xor,
521    Contains,
522
523    Tlbw,
524    Tlbr,
525    Tlbp,
526    TlbInvAsid,
527    Ctlbw,
528    Tlboc,
529
530    Asr,
531    Lsr,
532    Asl,
533    /// logical left shift. is this different from arithmetic left shift? who knows?!
534    Lsl,
535    Rol,
536    Vsathub,
537    Vsatwuh,
538    Vsatwh,
539    Vsathb,
540
541    Vabsh,
542    Vabsw,
543    Vasrw,
544    Vasrh,
545    Vlsrw,
546    Vlsrh,
547    Vaslw,
548    Vaslh,
549    Vlslw,
550    Vlslh,
551
552    Vabsdiffb,
553    Vabsdiffub,
554    Vabsdiffh,
555    Vabsdiffw,
556
557    Not,
558    Neg,
559    Abs,
560    Vconj,
561
562    Deinterleave,
563    Interleave,
564    Brev,
565
566    Extractu,
567    Extract,
568    Insert,
569
570    Trap0,
571    Trap1,
572    Pause,
573    Icinva,
574    Isync,
575    Unpause,
576
577    DfAdd,
578    DfSub,
579    DfMax,
580    DfMin,
581
582    SfSub,
583    SfAdd,
584    SfMpy,
585    SfMax,
586    SfMin,
587    SfCmpEq,
588    SfCmpGt,
589    SfCmpGe,
590    SfCmpUo,
591
592    DfCmpEq,
593    DfCmpGt,
594    DfCmpGe,
595    DfCmpUo,
596    DfMpyll,
597    DfMpylh,
598    DfMpyhh,
599    DfMpyfix,
600
601    Cmpy,
602    Cmpyiw,
603    Cmpyrw,
604    Cmpyiwh,
605    Cmpyrwh,
606    Cmpyi,
607    Cmpyr,
608    Vcmpyi,
609    Vcmpyr,
610    Vmpybu,
611    Vmpyh,
612    Vmpyhsu,
613    Vmpybsu,
614    Vrmpybsu,
615    Vdmpybsu,
616    Vrmpybu,
617    Vrmpyh,
618
619    Pmpyw,
620    Vpmpyh,
621    Lfs,
622
623    Vxaddsubh,
624    Vxaddsubw,
625    Vxsubaddh,
626    Vxsubaddw,
627
628    Vraddub,
629    Vraddh,
630    Vradduh,
631    Vrsadub,
632    Vaddub,
633    Vaddh,
634    Vaddhub,
635    Vadduh,
636    Vaddw,
637    Vsubub,
638    Vsubw,
639    Vsubh,
640    Vsubuh,
641    Vavgub,
642    Vavgw,
643    Vavguw,
644    Vavgh,
645    Vavguh,
646    Vnavgh,
647    Vnavgw,
648
649    Packhl,
650
651    DcCleanA,
652    DcInvA,
653    DcCleanInvA,
654    DcZeroA,
655    DcKill,
656    IcKill,
657    L2Fetch,
658    L2Kill,
659    L2Gunlock,
660    L2Gclean,
661    L2Gcleaninv,
662    DmSyncHt,
663    SyncHt,
664
665    Release,
666    Barrier,
667    AllocFrame,
668    MemwRl,
669    MemdRl,
670
671    DeallocFrame,
672    DeallocReturn,
673    Dcfetch,
674
675    MemwLockedLoad,
676    MemwStoreCond,
677    MemwAq,
678    MemdLockedLoad,
679    MemdStoreCond,
680    MemdAq,
681
682    Pmemcpy,
683    Linecpy,
684
685    Loop0,
686    Loop1,
687    Sp1Loop0,
688    Sp2Loop0,
689    Sp3Loop0,
690    Trace,
691    Diag,
692    Diag0,
693    Diag1,
694
695    Movlen,
696
697    Fastcorner9,
698    Any8,
699    All8,
700
701    Max,
702    Maxu,
703    Min,
704    Minu,
705
706    Valignb,
707    Vspliceb,
708    Vsxtbh,
709    Vzxtbh,
710    Vsxthw,
711    Vzxthw,
712    Vsplath,
713    Vsplatb,
714    Vcrotate,
715    Vrcrotate,
716    Vmaxb,
717    Vmaxub,
718    Vminb,
719    Vminuw,
720    Vminh,
721    Vminuh,
722    Vminw,
723    Vmaxw,
724    Vmaxuw,
725    Vmaxh,
726    Vmaxuh,
727    Vrmaxh,
728    Vrmaxw,
729    Vrminh,
730    Vrminw,
731    Vrmaxuh,
732    Vrmaxuw,
733    Vrminuh,
734    Vrminuw,
735    Vnegh,
736    Vcnegh,
737    Vrcnegh,
738
739    ConvertDf2D,
740    ConvertDf2Ud,
741    ConvertSf2W,
742    ConvertSf2D,
743    ConvertSf2Df,
744    ConvertDf2Sf,
745    ConvertSf2Uw,
746    ConvertSf2Ud,
747    ConvertUd2Df,
748    ConvertUd2Sf,
749    ConvertUw2Sf,
750    ConvertUw2Df,
751    ConvertW2Sf,
752    ConvertW2Df,
753    ConvertD2Df,
754    ConvertD2Sf,
755    Mask,
756    Setbit,
757    Clrbit,
758    Togglebit,
759    Tstbit,
760    Bitsclr,
761    Bitsset,
762    Modwrap,
763    SfClass,
764    DfClass,
765    SfMake,
766    DfMake,
767    Tableidxb,
768    Tableidxh,
769    Tableidxw,
770    Tableidxd,
771
772    Vasrhub,
773    Vrndwh,
774    Vtrunohb,
775    Vtrunowh,
776    Vtrunehb,
777    Vtrunewh,
778    Normamt,
779    Popcount,
780    Sat,
781    Sath,
782    Satb,
783    Satuh,
784    Satub,
785    Round,
786    Cround,
787    Bitsplit,
788    Clip,
789    Vclip,
790    Clb,
791    Cl0,
792    Cl1,
793    Ct0,
794    Ct1,
795    Vitpack,
796    SfFixupr,
797    SfFixupn,
798    SfFixupd,
799    Swiz,
800    Shuffeb,
801    Shuffob,
802    Shuffeh,
803    Shuffoh,
804    Decbin,
805
806    Parity,
807    Vmux,
808    VcmpwEq,
809    VcmpwGt,
810    VcmpwGtu,
811    VcmphEq,
812    VcmphGt,
813    VcmphGtu,
814    VcmpbEq,
815    VcmpbGt,
816    VcmpbGtu,
817    Tlbmatch,
818    Boundscheck,
819
820    Mpy,
821    Mpyu,
822    Mpyi,
823    Mpysu,
824    Vcmpyh,
825    Vrcmpys,
826    Vdmpy,
827    Vmpyeh,
828    Vmpyweh,
829    Vmpywoh,
830    Vmpyweuh,
831    Vmpywouh,
832    Vrmpyweh,
833    Vrmpywoh,
834    Vrmpyu,
835    Vrmpysu,
836
837    // `Rd=addasl(Rt,Rs,#u3)` wants the "typical" operand rending rules, rather than
838    // `add(x, asl(y, z))` that would be used below. terrible.
839    AddAslRegReg,
840
841    Swi,
842    Cswi,
843    Ciad,
844    Wait,
845    Resume,
846    Stop,
847    Start,
848    Nmi,
849    Setimask,
850    Siad,
851    Brkpt,
852    TlbLock,
853    K0Lock,
854    Crswap,
855    Getimask,
856    Iassignr,
857    Icdatar,
858    Ictagr,
859    Ictagw,
860    Icinvidx,
861
862    AndAnd = 0x8000,
863    AndOr,
864    OrAnd,
865    AndNot,
866    OrOr,
867    AndAndNot,
868    AndOrNot,
869    OrAndNot,
870    OrNot,
871    OrOrNot,
872    AndLsr,
873    OrLsr,
874    AddLsr,
875    SubLsr,
876    AddLsl,
877    AddAsl,
878    SubAsl,
879    AndAsl,
880    OrAsl,
881    AddClb,
882    AddAdd,
883    AddSub,
884    Vacsh,
885    Vminub,
886    SfRecipa,
887    SfInvsqrta,
888    Any8VcmpbEq,
889
890    AddMpyi,
891    MpyiNeg,
892    MpyiPos,
893}
894
895impl Opcode {
896    // if there's no `fmt` we don't need labels, for now.
897    // if RoundingMode were inspectable this might be useful even without fmt?
898    #[cfg(feature = "fmt")]
899    fn cmp_str(&self) -> Option<&'static str> {
900        match self {
901            Opcode::JumpEq => { Some("cmp.eq") },
902            Opcode::JumpNeq => { Some("!cmp.eq") },
903            Opcode::JumpGt => { Some("cmp.gt") },
904            Opcode::JumpLe => { Some("!cmp.gt") },
905            Opcode::JumpGtu => { Some("cmp.gtu") },
906            Opcode::JumpLeu => { Some("!cmp.gtu") },
907            Opcode::JumpBitSet => { Some("tstbit") },
908            Opcode::JumpBitClear => { Some("!tstbit") },
909            Opcode::CmpEqJump => { Some("cmp.eq") },
910            Opcode::CmpGtJump => { Some("cmp.gt") },
911            Opcode::CmpGtuJump => { Some("cmp.gtu") },
912            Opcode::TestClrJump => { Some("tstbit") },
913            _ => None
914        }
915    }
916}
917
918impl Instruction {
919    fn sources(&self) -> &[Operand] {
920        &self.sources[..self.sources_count as usize]
921    }
922}
923
924impl PartialEq for Instruction {
925    fn eq(&self, other: &Self) -> bool {
926        let Instruction {
927            opcode: leftop,
928            dest: leftdest,
929            alt_dest: leftaltdest,
930            flags: leftflags,
931            ..
932        } = self;
933        let Instruction {
934            opcode: rightop,
935            dest: rightdest,
936            alt_dest: rightaltdest,
937            flags: rightflags,
938            ..
939        } = other;
940
941        leftop == rightop &&
942            leftdest == rightdest &&
943            leftaltdest == rightaltdest &&
944            leftflags == rightflags &&
945            self.sources() == other.sources()
946    }
947}
948
949impl Default for Instruction {
950    fn default() -> Instruction {
951        Instruction {
952            opcode: Opcode::BUG,
953            dest: None,
954            alt_dest: None,
955            flags: InstFlags::default(),
956            sources: [Operand::Nothing, Operand::Nothing, Operand::Nothing],
957            sources_count: 0,
958        }
959    }
960}
961
962impl LengthedInstruction for InstructionPacket {
963    type Unit = AddressDiff<<Hexagon as Arch>::Address>;
964    fn min_size() -> Self::Unit {
965        AddressDiff::from_const(4)
966    }
967    fn len(&self) -> Self::Unit {
968        AddressDiff::from_const(self.word_count as u32 * 4)
969    }
970}
971
972impl yaxpeax_arch::Instruction for InstructionPacket {
973    // only know how to decode well-formed instructions at the moment
974    fn well_defined(&self) -> bool { true }
975}
976
977#[derive(Debug, Copy, Clone, PartialEq, Eq)]
978pub enum Operand {
979    Nothing,
980
981    PCRel32 { rel: i32 },
982
983    /// `rR`, a 32-bit register `r<reg>`
984    ///
985    /// V73 Section 2.1:
986    /// > thirty-two 32-bit general-purpose registers (named r0 through r31)
987    ///
988    /// the last three, `r29, r30, r31` are, when possible, shown as `sp, fr, lr`. they are not
989    /// necessarily required to serve the purposes of stack pointer, frame register, or link
990    /// register. they are, however, described as such by the manual and almost certainly used that
991    /// way by actual code.
992    Gpr { reg: u8 },
993    /// `Cn`, a 32-bit control register `C<reg>`
994    ///
995    /// V73 Section 2.2:
996    /// > the Hexagon processor includes a set of 32-bit control registers that provide access to
997    /// > processor features such as the program counter, hardware loops, and vector predicates.
998    /// >
999    /// > unlike general registers, control registers are used as instruction operands only in the
1000    /// > following cases:
1001    /// > * instructions that require a specific control register as an operand
1002    /// > * register transfer instructions
1003    /// >
1004    /// > NOTE: when a control register is used in a register transfer, the other operand must be a
1005    /// > general register.
1006    ///
1007    /// also V73 Section 2.2:
1008    /// > the control registers have numeric aliases (C0 through C31).
1009    Cr { reg: u8 },
1010    /// `Sn`, a 32-bit supervisor register `S<reg>`
1011    Sr { reg: u8 },
1012    /// `rN.new`, the version of a 32-bit register `R<reg>` after being written in this instruction
1013    /// packet.
1014    GprNew { reg: u8 },
1015    /// `rN.l`, low 16 bits of `r<reg>`
1016    GprLow { reg: u8 },
1017    /// `rN.h`, high 16 bits of `r<reg>`
1018    GprHigh { reg: u8 },
1019
1020    /// the complex conjugate of `r<reg>`. this is only used in a few instructions performing
1021    /// complex multiplies, and is displayed as `rN*`.
1022    GprConjugate { reg: u8 },
1023    /// `rN:M`, register pair forming a 64-bit value
1024    ///
1025    /// V73 Section 2.1:
1026    /// > the general registers can be specified as a pair that represent a single 64-bit register.
1027    /// >
1028    /// > NOTE: the first register in a register pair must always be odd-numbered, and the second must be
1029    /// > the next lower register.
1030    ///
1031    /// from Table 2-2, note there is an entry of `r31:r30 (lr:fp)`
1032    Gpr64b { reg_low: u8 },
1033    /// `rN:M*`, a register pair interpreted as a complex number, conjugated
1034    ///
1035    /// this is only used for forms of `cmpy*w`
1036    Gpr64bConjugate { reg_low: u8 },
1037    /// `cN:M`, control register pair forming a 64-bit location
1038    Cr64b { reg_low: u8 },
1039    /// `sN:M`, control register pair forming a 64-bit location
1040    Sr64b { reg_low: u8 },
1041
1042    /// `pN`, a predicate register
1043    PredicateReg { reg: u8 },
1044
1045    RegOffset { base: u8, offset: u32 },
1046
1047    RegOffsetInc { base: u8, offset: u32 },
1048
1049    RegShiftedReg { base: u8, index: u8, shift: u8 },
1050
1051    RegShiftOffset { base: u8, shift: u8, offset: u32 },
1052
1053    ImmU8 { imm: u8 },
1054
1055    ImmU16 { imm: u16 },
1056
1057    ImmI8 { imm: i8 },
1058
1059    ImmI16 { imm: i16 },
1060
1061    ImmI32 { imm: i32 },
1062
1063    ImmU32 { imm: u32 },
1064
1065    Immext { imm: u32 },
1066
1067    // TODO: offset should be signed, check if test cases exercise this..
1068    RegOffsetCirc { base: u8, offset: u32, mu: u8 },
1069
1070    RegCirc { base: u8, mu: u8 },
1071
1072    RegStoreAssign { base: u8, addr: u32 },
1073
1074    RegMemIndexed { base: u8, mu: u8 },
1075
1076    RegMemIndexedBrev { base: u8, mu: u8 },
1077
1078    Absolute { addr: u32 },
1079
1080    GpOffset { offset: u32 },
1081}
1082
1083impl Operand {
1084    fn gpr(num: u8) -> Self {
1085        Self::Gpr { reg: num }
1086    }
1087
1088    fn gpr_low(num: u8) -> Self {
1089        Self::GprLow { reg: num }
1090    }
1091
1092    fn gpr_high(num: u8) -> Self {
1093        Self::GprHigh { reg: num }
1094    }
1095
1096    fn gpr_conjugate(num: u8) -> Self {
1097        Self::GprConjugate { reg: num }
1098    }
1099
1100    /// decode a 4-bit `num` into a full register, according to
1101    /// `Table 10-3 Sub-instruction registers`
1102    fn gpr_4b(num: u8) -> Self {
1103        debug_assert!(num < 0b10000);
1104        // the whole table can be described as "pick bit 3, move it left by one"
1105        let decoded = (num & 0b111) | ((num & 0b1000) << 1);
1106        Self::Gpr { reg: decoded }
1107    }
1108
1109    fn cr(num: u8) -> Self {
1110        Self::Cr { reg: num }
1111    }
1112
1113    fn sr(num: u8) -> Self {
1114        Self::Sr { reg: num }
1115    }
1116
1117    fn gpr_new(num: u8) -> Self {
1118        Self::GprNew { reg: num }
1119    }
1120
1121    fn gprpair(num: u8) -> Result<Self, yaxpeax_arch::StandardDecodeError> {
1122        operand_check!(num & 1 == 0);
1123        Ok(Self::Gpr64b { reg_low: num })
1124    }
1125
1126    fn gprpair_conjugate(num: u8) -> Result<Self, yaxpeax_arch::StandardDecodeError> {
1127        operand_check!(num & 1 == 0);
1128        Ok(Self::Gpr64bConjugate { reg_low: num })
1129    }
1130
1131    fn crpair(num: u8) -> Result<Self, yaxpeax_arch::StandardDecodeError> {
1132        operand_check!(num & 1 == 0);
1133        Ok(Self::Cr64b { reg_low: num })
1134    }
1135
1136    fn srpair(num: u8) -> Result<Self, yaxpeax_arch::StandardDecodeError> {
1137        operand_check!(num & 1 == 0);
1138        Ok(Self::Sr64b { reg_low: num })
1139    }
1140
1141    fn pred(num: u8) -> Self {
1142        Self::PredicateReg { reg: num }
1143    }
1144
1145    fn imm_i8(num: i8) -> Self {
1146        Self::ImmI8 { imm: num }
1147    }
1148
1149    fn imm_u8(num: u8) -> Self {
1150        Self::ImmU8 { imm: num }
1151    }
1152
1153    fn imm_i16(num: i16) -> Self {
1154        Self::ImmI16 { imm: num }
1155    }
1156
1157    fn imm_u16(num: u16) -> Self {
1158        Self::ImmU16 { imm: num }
1159    }
1160
1161    fn imm_i32(num: i32) -> Self {
1162        Self::ImmI32 { imm: num }
1163    }
1164
1165    fn imm_u32(num: u32) -> Self {
1166        Self::ImmU32 { imm: num }
1167    }
1168
1169    fn with_extension(
1170        i: u32, extender: &mut Option<u32>,
1171        extended: impl FnOnce(u32) -> Result<Self, yaxpeax_arch::StandardDecodeError>,
1172        no_extender: impl FnOnce(u32) -> Result<Self, yaxpeax_arch::StandardDecodeError>,
1173    ) -> Result<Self, yaxpeax_arch::StandardDecodeError> {
1174        if let Some(extender) = extender.take() {
1175            operand_check!(i & !0x3f == 0);
1176            extended(i | (extender << 6))
1177        } else {
1178            no_extender(i)
1179        }
1180    }
1181
1182    fn immext(
1183        i: u32, extender: &mut Option<u32>,
1184        unextended: impl FnOnce(u32) -> Result<Self, yaxpeax_arch::StandardDecodeError>,
1185    ) -> Result<Self, yaxpeax_arch::StandardDecodeError> {
1186        Self::with_extension(
1187            i, extender,
1188            |imm| Ok(Self::Immext { imm }),
1189            unextended
1190        )
1191    }
1192}
1193
1194#[derive(Debug)]
1195pub struct InstDecoder { }
1196
1197impl Default for InstDecoder {
1198    fn default() -> Self {
1199        InstDecoder {}
1200    }
1201}
1202
1203trait DecodeHandler<T: Reader<<Hexagon as Arch>::Address, <Hexagon as Arch>::Word>> {
1204    #[inline(always)]
1205    fn read_u32(&mut self, words: &mut T) -> Result<u32, <Hexagon as Arch>::DecodeError> {
1206        let mut buf = [0u8; 4];
1207        words.next_n(&mut buf).ok().ok_or(DecodeError::ExhaustedInput)?;
1208        self.on_word_read(buf[0]);
1209        self.on_word_read(buf[1]);
1210        self.on_word_read(buf[2]);
1211        self.on_word_read(buf[3]);
1212        Ok(u32::from_le_bytes(buf))
1213    }
1214    fn read_inst_word(&mut self, words: &mut T) -> Result<u32, <Hexagon as Arch>::DecodeError>;
1215    fn on_decode_start(&mut self) {}
1216    fn on_decode_end(&mut self) {}
1217    fn start_instruction(&mut self) -> Result<(), <Hexagon as Arch>::DecodeError> { Ok(()) }
1218    fn end_instruction(&mut self) -> Result<(), <Hexagon as Arch>::DecodeError> { Ok(()) }
1219    /// register an instruction with a new-value operand. this is described in more detail
1220    /// by `10.10 New-value operands` (as of the V73 manual). specifically, this registers
1221    /// that the current instruction has a new-value register operand that is produced by some
1222    /// instruction "ahead" in the same packet. "ahead" means "at lower memory address", which also
1223    /// means the producer ought to have been decoded already.
1224    fn on_nv_register(&mut self, _dist: u8) -> Result<(), <Hexagon as Arch>::DecodeError> { Ok(()) }
1225    fn on_loop_end(&mut self, loop_num: u8);
1226    fn on_opcode_decoded(&mut self, _opcode: Opcode) -> Result<(), <Hexagon as Arch>::DecodeError> { Ok(()) }
1227    fn on_source_decoded(&mut self, _operand: Operand) -> Result<(), <Hexagon as Arch>::DecodeError> { Ok(()) }
1228    fn on_dest_decoded(&mut self, _operand: Operand) -> Result<(), <Hexagon as Arch>::DecodeError> { Ok(()) }
1229    fn assign_mode(&mut self, _assign_mode: AssignMode) -> Result<(), <Hexagon as Arch>::DecodeError> { Ok(()) }
1230    fn inst_predicated(&mut self, _num: u8, _negated: bool, _pred_new: bool) -> Result<(), <Hexagon as Arch>::DecodeError> { Ok(()) }
1231    fn negate_result(&mut self) -> Result<(), <Hexagon as Arch>::DecodeError> { Ok(()) }
1232    fn saturate(&mut self) -> Result<(), <Hexagon as Arch>::DecodeError> { Ok(()) }
1233    fn scale(&mut self) -> Result<(), <Hexagon as Arch>::DecodeError> { Ok(()) }
1234    fn library(&mut self) -> Result<(), <Hexagon as Arch>::DecodeError> { Ok(()) }
1235    fn branch_hint(&mut self, _hint_taken: bool) -> Result<(), <Hexagon as Arch>::DecodeError> { Ok(()) }
1236    fn domain_hint(&mut self, _domain: DomainHint) -> Result<(), <Hexagon as Arch>::DecodeError> { Ok(()) }
1237    fn rounded(&mut self, _mode: RoundingMode) -> Result<(), <Hexagon as Arch>::DecodeError> { Ok(()) }
1238    fn chop(&mut self) -> Result<(), <Hexagon as Arch>::DecodeError> { Ok(()) }
1239    fn raw_mode(&mut self, _mode: RawMode) -> Result<(), <Hexagon as Arch>::DecodeError> { Ok(()) }
1240    fn shift_left(&mut self, _shiftamt: u8) -> Result<(), <Hexagon as Arch>::DecodeError> { Ok(()) }
1241    fn shift_right(&mut self, _shiftamt: u8) -> Result<(), <Hexagon as Arch>::DecodeError> { Ok(()) }
1242    fn carry(&mut self) -> Result<(), <Hexagon as Arch>::DecodeError> { Ok(()) }
1243    fn deprecated(&mut self) -> Result<(), <Hexagon as Arch>::DecodeError> { Ok(()) }
1244    fn on_word_read(&mut self, _word: <Hexagon as Arch>::Word) {}
1245}
1246
1247impl<T: yaxpeax_arch::Reader<<Hexagon as Arch>::Address, <Hexagon as Arch>::Word>> DecodeHandler<T> for InstructionPacket {
1248    fn on_decode_start(&mut self) {
1249        self.instructions = [Instruction::default(); 4];
1250        self.instruction_count = 0;
1251        self.word_count = 0;
1252    }
1253    fn on_loop_end(&mut self, loop_num: u8) {
1254        self.loop_effect.mark_end(loop_num);
1255    }
1256    fn on_opcode_decoded(&mut self, opcode: Opcode) -> Result<(), <Hexagon as Arch>::DecodeError> {
1257        self.instructions[self.instruction_count as usize].opcode = opcode;
1258        Ok(())
1259    }
1260    fn on_source_decoded(&mut self, operand: Operand) -> Result<(), <Hexagon as Arch>::DecodeError> {
1261        let inst = &mut self.instructions[self.instruction_count as usize];
1262        inst.sources[inst.sources_count as usize] = operand;
1263        inst.sources_count += 1;
1264        Ok(())
1265    }
1266    fn on_dest_decoded(&mut self, operand: Operand) -> Result<(), <Hexagon as Arch>::DecodeError> {
1267        let inst = &mut self.instructions[self.instruction_count as usize];
1268        if inst.dest.is_some() {
1269            assert!(inst.alt_dest.is_none());
1270            inst.alt_dest = Some(operand);
1271        } else {
1272            inst.dest = Some(operand);
1273        }
1274        Ok(())
1275    }
1276    fn on_nv_register(&mut self, dist: u8) -> Result<(), <Hexagon as Arch>::DecodeError> {
1277        // from the manual:
1278        // > Nt[0] is reserved and must always be encoded as zero. A nonzero value produces
1279        // > undefined results.
1280        operand_check!(dist & 1 == 0);
1281
1282        let dist = dist >> 1;
1283        // Nt[2:1] = 00 // Reserved
1284        operand_check!(dist != 0);
1285
1286        operand_check!(self.instruction_count >= dist);
1287        let producer_idx = self.instruction_count - dist;
1288
1289        let source = match self.instructions.get(producer_idx as usize) {
1290            Some(inst) => {
1291                match inst.dest {
1292                    Some(Operand::Gpr { reg }) => {
1293                        reg
1294                    }
1295                    // note that GprPair is ignored here:
1296                    // > Instructions with 64-bit register pair destinations cannot produce
1297                    // > new-values. The assembler flags this case with an error, as the result is
1298                    // > undefined.
1299                    _ => {
1300                        // the instruction `dist` slots ahead had an instruction but it did not
1301                        // produce a new register?
1302                        return Err(DecodeError::InvalidOperand);
1303                    }
1304                }
1305            }
1306            None => {
1307                return Err(DecodeError::InvalidOperand);
1308            }
1309        };
1310
1311        <Self as DecodeHandler<T>>::on_source_decoded(self, Operand::gpr_new(source))
1312    }
1313    fn assign_mode(&mut self, assign_mode: AssignMode) -> Result<(), <Hexagon as Arch>::DecodeError> {
1314        let inst = &mut self.instructions[self.instruction_count as usize];
1315        inst.flags.assign_mode = Some(assign_mode);
1316        Ok(())
1317    }
1318    fn inst_predicated(&mut self, num: u8, negated: bool, pred_new: bool) -> Result<(), <Hexagon as Arch>::DecodeError> {
1319        let flags = &mut self.instructions[self.instruction_count as usize].flags;
1320        assert!(flags.predicate.is_none());
1321        flags.predicate = Some(Predicate::reg(num).set_negated(negated).set_pred_new(pred_new));
1322        Ok(())
1323    }
1324    fn negate_result(&mut self) -> Result<(), <Hexagon as Arch>::DecodeError> {
1325        let flags = &mut self.instructions[self.instruction_count as usize].flags;
1326        assert!(!flags.negated);
1327        flags.negated = true;
1328        Ok(())
1329    }
1330    fn saturate(&mut self) -> Result<(), <Hexagon as Arch>::DecodeError> {
1331        let flags = &mut self.instructions[self.instruction_count as usize].flags;
1332        assert!(!flags.saturate);
1333        flags.saturate = true;
1334        Ok(())
1335    }
1336    fn scale(&mut self) -> Result<(), <Hexagon as Arch>::DecodeError> {
1337        let flags = &mut self.instructions[self.instruction_count as usize].flags;
1338        assert!(!flags.scale);
1339        flags.scale = true;
1340        Ok(())
1341    }
1342    fn library(&mut self) -> Result<(), <Hexagon as Arch>::DecodeError> {
1343        let flags = &mut self.instructions[self.instruction_count as usize].flags;
1344        assert!(!flags.scale);
1345        flags.library = true;
1346        Ok(())
1347    }
1348    fn branch_hint(&mut self, hint_taken: bool) -> Result<(), <Hexagon as Arch>::DecodeError> {
1349        let flags = &mut self.instructions[self.instruction_count as usize].flags;
1350        assert!(flags.branch_hint.is_none());
1351        if hint_taken {
1352            flags.branch_hint = Some(BranchHint::Taken);
1353        } else {
1354            flags.branch_hint = Some(BranchHint::NotTaken);
1355        }
1356        Ok(())
1357    }
1358    fn domain_hint(&mut self, domain: DomainHint) -> Result<(), <Hexagon as Arch>::DecodeError> {
1359        let flags = &mut self.instructions[self.instruction_count as usize].flags;
1360        assert!(flags.threads.is_none());
1361        flags.threads = Some(domain);
1362        Ok(())
1363    }
1364    fn rounded(&mut self, mode: RoundingMode) -> Result<(), <Hexagon as Arch>::DecodeError> {
1365        let flags = &mut self.instructions[self.instruction_count as usize].flags;
1366        assert!(flags.rounded.is_none());
1367        flags.rounded = Some(mode);
1368        Ok(())
1369    }
1370    fn chop(&mut self) -> Result<(), <Hexagon as Arch>::DecodeError> {
1371        let flags = &mut self.instructions[self.instruction_count as usize].flags;
1372        assert!(!flags.chop);
1373        flags.chop = true;
1374        Ok(())
1375    }
1376    fn raw_mode(&mut self, mode: RawMode) -> Result<(), <Hexagon as Arch>::DecodeError> {
1377        let flags = &mut self.instructions[self.instruction_count as usize].flags;
1378        assert!(flags.raw_mode.is_none());
1379        flags.raw_mode = Some(mode);
1380        Ok(())
1381    }
1382    fn shift_left(&mut self, shiftamt: u8) -> Result<(), <Hexagon as Arch>::DecodeError> {
1383        let flags = &mut self.instructions[self.instruction_count as usize].flags;
1384        assert!(flags.shift_left.is_none());
1385        assert!(flags.shift_right.is_none());
1386        // if the result would be shifted by zero, ignore it so as to not print
1387        // <<0 when rendering the instruction.
1388        if shiftamt == 0 {
1389            return Ok(());
1390        }
1391        flags.shift_left = Some(shiftamt);
1392        Ok(())
1393    }
1394    fn shift_right(&mut self, shiftamt: u8) -> Result<(), <Hexagon as Arch>::DecodeError> {
1395        let flags = &mut self.instructions[self.instruction_count as usize].flags;
1396        assert!(flags.shift_left.is_none());
1397        assert!(flags.shift_right.is_none());
1398        // if the result would be shifted by zero, ignore it so as to not print
1399        // >>0 when rendering the instruction.
1400        if shiftamt == 0 {
1401            return Ok(());
1402        }
1403        flags.shift_right = Some(shiftamt);
1404        Ok(())
1405    }
1406    fn carry(&mut self) -> Result<(), <Hexagon as Arch>::DecodeError> {
1407        let flags = &mut self.instructions[self.instruction_count as usize].flags;
1408        assert!(!flags.carry);
1409        flags.carry = true;
1410        Ok(())
1411    }
1412    fn deprecated(&mut self) -> Result<(), <Hexagon as Arch>::DecodeError> {
1413        let flags = &mut self.instructions[self.instruction_count as usize].flags;
1414        assert!(!flags.deprecated);
1415        flags.deprecated = true;
1416        Ok(())
1417    }
1418    #[inline(always)]
1419    fn read_inst_word(&mut self, words: &mut T) -> Result<u32, <Hexagon as Arch>::DecodeError> {
1420        self.word_count += 1;
1421        self.read_u32(words)
1422    }
1423    fn on_word_read(&mut self, _word: <Hexagon as Arch>::Word) { }
1424    fn start_instruction(&mut self) -> Result<(), <Hexagon as Arch>::DecodeError> {
1425        opcode_check!(self.instruction_count < self.instructions.len() as u8);
1426        Ok(())
1427    }
1428    fn end_instruction(&mut self) -> Result<(), <Hexagon as Arch>::DecodeError> {
1429        self.instruction_count += 1;
1430        Ok(())
1431    }
1432}
1433
1434impl Decoder<Hexagon> for InstDecoder {
1435    fn decode_into<T: Reader<<Hexagon as Arch>::Address, <Hexagon as Arch>::Word>>(&self, packet: &mut InstructionPacket, words: &mut T) -> Result<(), <Hexagon as Arch>::DecodeError> {
1436        decode_packet(self, packet, words)
1437    }
1438}
1439
1440fn reg_b0(inst: u32) -> u8 { (inst & 0b11111) as u8 }
1441fn reg_b8(inst: u32) -> u8 { ((inst >> 8) & 0b11111) as u8 }
1442fn reg_b16(inst: u32) -> u8 { ((inst >> 16) & 0b11111) as u8 }
1443
1444// general store procedure for stores in iclass 0100 and 1010. the addressing modes change, and bit
1445// locations change (a bit) so callers must provide them, but once the bits are provided the
1446// mechanism to decode into an opcode and operands is roughly shared.
1447//
1448// one example of this is how for opbits 000..111 there are stores:
1449// * 000: memb(Rx++I:circ*Mu))=Rt
1450// * 001: memh(Rx++I:circ*Mu))=Rt
1451// * 010: memh(Rx++I:circ*Mu))=Rt.H
1452// * 011: memw(Rx++I:circ*Mu))=Rt
1453// * 101.00: memb(Rx++I:circ*Mu))=Nt.new
1454// * 101.01: memh(Rx++I:circ*Mu))=Nt.new
1455// * 101.10: memw(Rx++I:circ*Mu))=Nt.new
1456// * 110: memd(Rx++I:circ*Mu))=Rtt
1457// * invalid
1458fn decode_store_ops<
1459    T: Reader<<Hexagon as Arch>::Address, <Hexagon as Arch>::Word>,
1460    H: DecodeHandler<T>,
1461>(
1462    handler: &mut H, opbits: u8, srcreg: u8,
1463    dest_op: impl FnOnce(u8) -> Result<Operand, DecodeError>
1464) -> Result<(), DecodeError> {
1465    if opbits == 0b101 {
1466        handler.on_nv_register(srcreg & 0b111)?;
1467        let opbits = (srcreg >> 3) & 0b11;
1468        static OPS: [Option<Opcode>; 4] = [
1469            Some(Opcode::StoreMemb), Some(Opcode::StoreMemh),
1470            Some(Opcode::StoreMemw), None,
1471        ];
1472        handler.on_opcode_decoded(decode_opcode!(OPS[opbits as usize]))?;
1473        handler.on_dest_decoded(dest_op(opbits)?)?;
1474    } else {
1475        match opbits {
1476            0b000 => {
1477                handler.on_opcode_decoded(Opcode::StoreMemb)?;
1478                handler.on_source_decoded(Operand::gpr(srcreg))?;
1479                handler.on_dest_decoded(dest_op(0)?)?;
1480            }
1481            0b010 => {
1482                handler.on_opcode_decoded(Opcode::StoreMemh)?;
1483                handler.on_source_decoded(Operand::gpr(srcreg))?;
1484                handler.on_dest_decoded(dest_op(1)?)?;
1485            }
1486            0b011 => {
1487                handler.on_opcode_decoded(Opcode::StoreMemh)?;
1488                handler.on_source_decoded(Operand::gpr_high(srcreg))?;
1489                handler.on_dest_decoded(dest_op(1)?)?;
1490            }
1491            0b100 => {
1492                handler.on_opcode_decoded(Opcode::StoreMemw)?;
1493                handler.on_source_decoded(Operand::gpr(srcreg))?;
1494                handler.on_dest_decoded(dest_op(2)?)?;
1495            }
1496            0b110 => {
1497                handler.on_opcode_decoded(Opcode::StoreMemd)?;
1498                handler.on_source_decoded(Operand::gprpair(srcreg)?)?;
1499                handler.on_dest_decoded(dest_op(3)?)?;
1500            }
1501            _ => {
1502                return Err(DecodeError::InvalidOpcode);
1503            }
1504        }
1505    }
1506    Ok(())
1507}
1508
1509// very much like `decode_store_ops`, except for some instructions the strategy is for loads
1510// instead.
1511fn decode_load_ops<
1512    T: Reader<<Hexagon as Arch>::Address, <Hexagon as Arch>::Word>,
1513    H: DecodeHandler<T>,
1514>(
1515    handler: &mut H, opbits: u8, dstreg: u8,
1516    src_op: impl FnOnce(u8) -> Result<Operand, DecodeError>
1517) -> Result<(), DecodeError> {
1518    // for loads, there's none of the carveout for `R<n>.new` or high register halves.
1519    // just mem{b,ub,h,uh,w,d}
1520    match opbits {
1521        0b000 => {
1522            handler.on_opcode_decoded(Opcode::LoadMemb)?;
1523            handler.on_dest_decoded(Operand::gpr(dstreg))?;
1524            handler.on_source_decoded(src_op(0)?)?;
1525        }
1526        0b001 => {
1527            handler.on_opcode_decoded(Opcode::LoadMemub)?;
1528            handler.on_dest_decoded(Operand::gpr(dstreg))?;
1529            handler.on_source_decoded(src_op(0)?)?;
1530        }
1531        0b010 => {
1532            handler.on_opcode_decoded(Opcode::LoadMemh)?;
1533            handler.on_dest_decoded(Operand::gpr(dstreg))?;
1534            handler.on_source_decoded(src_op(1)?)?;
1535        }
1536        0b011 => {
1537            handler.on_opcode_decoded(Opcode::LoadMemuh)?;
1538            handler.on_dest_decoded(Operand::gpr(dstreg))?;
1539            handler.on_source_decoded(src_op(1)?)?;
1540        }
1541        0b100 => {
1542            handler.on_opcode_decoded(Opcode::LoadMemw)?;
1543            handler.on_dest_decoded(Operand::gpr(dstreg))?;
1544            handler.on_source_decoded(src_op(2)?)?;
1545        }
1546        0b110 => {
1547            handler.on_opcode_decoded(Opcode::LoadMemd)?;
1548            handler.on_dest_decoded(Operand::gprpair(dstreg)?)?;
1549            handler.on_source_decoded(src_op(3)?)?;
1550        }
1551        _ => {
1552            return Err(DecodeError::InvalidOpcode);
1553        }
1554    }
1555    Ok(())
1556}
1557
1558fn subinstr_gprpair_b0(word: u16) -> u8 {
1559    let word = word & 0b111;
1560    if word < 0b100 {
1561        word as u8
1562    } else {
1563        (word + 16) as u8
1564    }
1565}
1566
1567fn subinstr_gpr_b0(word: u16) -> u8 {
1568    let word = word & 0b1111;
1569    if word < 0b1000 {
1570        word as u8
1571    } else {
1572        (word + 8) as u8
1573    }
1574}
1575
1576fn subinstr_gpr_b4(word: u16) -> u8 {
1577    let word = (word >> 4) & 0b1111;
1578    if word < 0b1000 {
1579        word as u8
1580    } else {
1581        (word + 8) as u8
1582    }
1583}
1584
1585fn subinstr_l1<
1586    T: Reader<<Hexagon as Arch>::Address, <Hexagon as Arch>::Word>,
1587    H: DecodeHandler<T>,
1588>(handler: &mut H, word: u16, _extender: &mut Option<u32>) -> Result<(), <Hexagon as Arch>::DecodeError> {
1589    handler.on_dest_decoded(Operand::gpr(subinstr_gpr_b0(word)))?;
1590
1591    let offset = ((word >> 8) & 0b1111) as i8;
1592    let offset = offset << 4 >> 4;
1593
1594    if word & 0b1_0000_0000_0000 == 0 {
1595        handler.on_opcode_decoded(Opcode::Memw)?;
1596        let source = Operand::RegOffset {
1597            base: subinstr_gpr_b4(word),
1598            offset: (offset << 2) as i32 as u32,
1599        };
1600        handler.on_source_decoded(source)?;
1601    } else {
1602        handler.on_opcode_decoded(Opcode::Memub)?;
1603        let source = Operand::RegOffset {
1604            base: subinstr_gpr_b4(word),
1605            offset: offset as i32 as u32,
1606        };
1607        handler.on_source_decoded(source)?;
1608    }
1609
1610    Ok(())
1611}
1612
1613fn subinstr_s1<
1614    T: Reader<<Hexagon as Arch>::Address, <Hexagon as Arch>::Word>,
1615    H: DecodeHandler<T>,
1616>(handler: &mut H, word: u16, _extender: &mut Option<u32>) -> Result<(), <Hexagon as Arch>::DecodeError> {
1617    handler.on_source_decoded(Operand::gpr(subinstr_gpr_b0(word)))?;
1618
1619    let offset = ((word >> 8) & 0b1111) as i8;
1620    let offset = offset >> 4 << 4;
1621
1622    if word & 0b1_0000_0000_0000 == 0 {
1623        handler.on_opcode_decoded(Opcode::StoreMemw)?;
1624        let dest = Operand::RegOffset {
1625            base: subinstr_gpr_b4(word),
1626            offset: (offset << 2) as i32 as u32,
1627        };
1628        handler.on_dest_decoded(dest)?;
1629    } else {
1630        handler.on_opcode_decoded(Opcode::StoreMemb)?;
1631        let dest = Operand::RegOffset {
1632            base: subinstr_gpr_b4(word),
1633            offset: offset as i32 as u32,
1634        };
1635        handler.on_dest_decoded(dest)?;
1636    }
1637
1638    Ok(())
1639}
1640
1641fn subinstr_l2<
1642    T: Reader<<Hexagon as Arch>::Address, <Hexagon as Arch>::Word>,
1643    H: DecodeHandler<T>,
1644>(handler: &mut H, word: u16, _extender: &mut Option<u32>) -> Result<(), <Hexagon as Arch>::DecodeError> {
1645    // top five bits get us through the major categories..
1646    let upper = word >> 8;
1647
1648    if upper < 0b11000 {
1649        let (opc, shamt) = if upper < 0b01000 {
1650            (Opcode::Memb, 0)
1651        } else if upper < 0b10000 {
1652            (Opcode::Memh, 2)
1653        } else {
1654            (Opcode::Memuh, 2)
1655        };
1656        let offset = ((upper & 0b111) as i8) << 5 >> 5;
1657        let source = Operand::RegOffset {
1658            base: subinstr_gpr_b4(word),
1659            offset: (offset << shamt) as i32 as u32,
1660        };
1661        handler.on_opcode_decoded(opc)?;
1662        handler.on_source_decoded(source)?;
1663        handler.on_dest_decoded(Operand::gpr(subinstr_gpr_b0(word)))?;
1664        return Ok(());
1665    }
1666
1667    let upper = upper & 0b111;
1668    if upper < 0b11100 {
1669        opcode_check!(false);
1670    } else if upper < 0b11110 {
1671        handler.on_opcode_decoded(Opcode::Memw)?;
1672        handler.on_dest_decoded(Operand::gpr(subinstr_gpr_b0(word)))?;
1673        let offset = ((word >> 4) & 0b11111) as i8;
1674        let offset = offset << 3 >> 3;
1675        handler.on_source_decoded(Operand::RegOffset {
1676            base: 29,
1677            offset: (offset << 2) as i32 as u32,
1678        })?;
1679
1680        return Ok(());
1681    } else if upper < 0b11111 {
1682        handler.on_opcode_decoded(Opcode::Memd)?;
1683        handler.on_dest_decoded(Operand::gprpair(subinstr_gprpair_b0(word))?)?;
1684        let offset = ((word >> 3) & 0b11111) as i8;
1685        let offset = offset << 3 >> 3;
1686        handler.on_source_decoded(Operand::RegOffset {
1687            base: 29,
1688            offset: (offset << 3) as i32 as u32,
1689        })?;
1690
1691        return Ok(());
1692    }
1693
1694    if word & 0b0100 != 0 {
1695        // predicated, low two bits configure it
1696        opcode_check!(word & 0b01111100 == 0b01000100);
1697
1698        let negated = word & 0b01 != 0;
1699        let dotnew = word & 0b10 != 0;
1700        handler.inst_predicated(0 as u8, negated, dotnew)?;
1701
1702        // not-taken is really indicated with the same bit as .new ????
1703        let hint_taken = word & 0b10 == 0;
1704        handler.branch_hint(hint_taken)?;
1705
1706        if word & 0b10000000 == 0 {
1707            handler.on_opcode_decoded(Opcode::DeallocReturn)?;
1708            handler.on_dest_decoded(Operand::gprpair(30)?)?;
1709            handler.on_source_decoded(Operand::gpr(30))?;
1710        } else {
1711            handler.on_opcode_decoded(Opcode::Jumpr)?;
1712            handler.on_dest_decoded(Operand::gpr(31))?;
1713        }
1714    } else {
1715        opcode_check!(word & 0b00111111 == 0);
1716        let op = (word >> 6) & 0b11;
1717        match op {
1718            0b00 => {
1719                // deallocframe
1720                handler.on_opcode_decoded(Opcode::DeallocFrame)?;
1721                handler.on_dest_decoded(Operand::gprpair(30)?)?;
1722                handler.on_source_decoded(Operand::gpr(30))?;
1723            }
1724            0b01 => {
1725                // deallocreturn
1726                handler.on_opcode_decoded(Opcode::DeallocReturn)?;
1727                handler.on_dest_decoded(Operand::gprpair(30)?)?;
1728                handler.on_source_decoded(Operand::gpr(30))?;
1729            }
1730            0b10 => {
1731                // nothing at 1111110000000
1732                opcode_check!(false);
1733            }
1734            _ => {
1735                // jumpr r31
1736                handler.on_opcode_decoded(Opcode::Jumpr)?;
1737                handler.on_dest_decoded(Operand::gpr(31))?;
1738            }
1739        }
1740    }
1741
1742    Ok(())
1743}
1744
1745fn subinstr_s2<
1746    T: Reader<<Hexagon as Arch>::Address, <Hexagon as Arch>::Word>,
1747    H: DecodeHandler<T>,
1748>(handler: &mut H, word: u16, _extender: &mut Option<u32>) -> Result<(), <Hexagon as Arch>::DecodeError> {
1749    // top five bits get us through the major categories..
1750    let upper = word >> 8;
1751
1752    let top = upper >> 3;
1753
1754    if top < 0b01 {
1755        handler.on_opcode_decoded(Opcode::StoreMemh)?;
1756        let offset = (((word >> 8) & 0b111) as i8) << 5 >> 5;
1757        handler.on_dest_decoded(Operand::RegOffset {
1758            base: subinstr_gpr_b4(word),
1759            offset: (offset << 1) as i32 as u32,
1760        })?;
1761        handler.on_source_decoded(Operand::gpr(subinstr_gpr_b0(word)))?;
1762    } else if top < 0b10 {
1763        opcode_check!(word & 0b00100 == 0);
1764        if word & 0b0001 == 0 {
1765            handler.on_opcode_decoded(Opcode::StoreMemw)?;
1766            let offset = (((word >> 4) & 0b11111) as i8) << 3 >> 3;
1767            handler.on_dest_decoded(Operand::RegOffset {
1768                base: 29,
1769                offset: (offset << 2) as i32 as u32,
1770            })?;
1771            handler.on_source_decoded(Operand::gpr(subinstr_gpr_b0(word)))?;
1772        } else {
1773            handler.on_opcode_decoded(Opcode::StoreMemd)?;
1774            let offset = (((word >> 3) & 0b111111) as i8) << 2 >> 2;
1775            handler.on_dest_decoded(Operand::RegOffset {
1776                base: 29,
1777                offset: (offset as i32 as u32) << 3,
1778            })?;
1779            handler.on_source_decoded(Operand::gprpair(subinstr_gprpair_b0(word))?)?;
1780        }
1781    } else if top < 0b11 {
1782        opcode_check!(word & 0b00100 == 0);
1783        let offset = ((word & 0b1111) as i8) << 4 >> 4;
1784
1785        if word & 0b0001 == 0 {
1786            handler.on_opcode_decoded(Opcode::StoreMemw)?;
1787            handler.on_dest_decoded(Operand::RegOffset {
1788                base: subinstr_gpr_b4(word),
1789                offset: (offset as i32 as u32) << 2,
1790            })?;
1791            handler.on_source_decoded(Operand::imm_u32((word as u32 >> 8) & 1))?;
1792        } else {
1793            handler.on_opcode_decoded(Opcode::StoreMemb)?;
1794            handler.on_dest_decoded(Operand::RegOffset {
1795                base: subinstr_gpr_b4(word),
1796                offset: offset as i32 as u32,
1797            })?;
1798            handler.on_source_decoded(Operand::imm_u32((word as u32 >> 8) & 1))?;
1799        }
1800    } else {
1801        opcode_check!(word & 0b1111 == 0);
1802        handler.on_opcode_decoded(Opcode::AllocFrame)?;
1803        let imm = (word >> 4) & 0b11111;
1804        handler.on_source_decoded(Operand::imm_u16((imm as u16) << 3))?;
1805    }
1806
1807    Ok(())
1808}
1809
1810fn subinstr_a<
1811    T: Reader<<Hexagon as Arch>::Address, <Hexagon as Arch>::Word>,
1812    H: DecodeHandler<T>,
1813>(handler: &mut H, word: u16, extender: &mut Option<u32>) -> Result<(), <Hexagon as Arch>::DecodeError> {
1814    // from the V79 manual, only two instructions are documented as being extendable here:
1815    // > Constant extenders expand the range of the immediate operand of an instruction to 32 bits,
1816    // > and can expand the following sub-instructions:
1817    // >
1818    // > Rx = add(Rx,#s7)
1819    // > Rd = #u6
1820
1821    // top five bits get us through the major categories..
1822    let upper = word >> 8;
1823
1824    let top = upper >> 3;
1825
1826    if top == 0b00 {
1827        // Rx = add(Rx, #i)
1828        handler.on_opcode_decoded(Opcode::Add)?;
1829        handler.on_dest_decoded(Operand::gpr(subinstr_gpr_b0(word)))?;
1830        handler.on_source_decoded(Operand::gpr(subinstr_gpr_b0(word)))?;
1831        let imm = (word >> 4) & 0b1111111;
1832        handler.on_source_decoded(Operand::immext(imm as u32, extender, |imm| {
1833            Ok(Operand::imm_i8((imm as i8) << 1 >> 1))
1834        })?)?;
1835    } else if top == 0b01 {
1836        // Rd = #i or Rd = add(r29, #i)
1837
1838        let imm = (word >> 4) & 0b111111;
1839        handler.on_dest_decoded(Operand::gpr(subinstr_gpr_b0(word)))?;
1840
1841        if upper & 0b00100 == 0 {
1842            // Rd = #i
1843            handler.on_opcode_decoded(Opcode::TransferImmediate)?;
1844            handler.on_source_decoded(Operand::immext(imm as u32, extender, |imm| {
1845                Ok(Operand::imm_i8((imm as i8) << 2 >> 2))
1846            })?)?;
1847        } else {
1848            // Rd = add(r29, #i)
1849            handler.on_opcode_decoded(Opcode::Add)?;
1850            handler.on_source_decoded(Operand::gpr(29))?;
1851            handler.on_source_decoded(Operand::imm_i8((imm as i8) << 2 >> 2))?;
1852        }
1853    } else if top == 0b10 {
1854        // Rd = {Rs,add,sxth,...}
1855        handler.on_dest_decoded(Operand::gpr(subinstr_gpr_b0(word)))?;
1856        handler.on_source_decoded(Operand::gpr(subinstr_gpr_b4(word)))?;
1857
1858        let op = (word >> 8) & 0b111;
1859        match op {
1860            0b000 => {
1861                handler.on_opcode_decoded(Opcode::TransferRegister)?;
1862            }
1863            0b001 => {
1864                handler.on_opcode_decoded(Opcode::Add)?;
1865                handler.on_source_decoded(Operand::imm_i8(1))?;
1866            }
1867            0b010 => {
1868                handler.on_opcode_decoded(Opcode::And)?;
1869                handler.on_source_decoded(Operand::imm_i8(1))?;
1870            }
1871            0b011 => {
1872                handler.on_opcode_decoded(Opcode::Add)?;
1873                handler.on_source_decoded(Operand::imm_i8(-1))?;
1874            }
1875            0b100 => {
1876                handler.on_opcode_decoded(Opcode::Sxth)?;
1877            }
1878            0b101 => {
1879                handler.on_opcode_decoded(Opcode::Sxtb)?;
1880            }
1881            0b110 => {
1882                handler.on_opcode_decoded(Opcode::Zxth)?;
1883            }
1884            _ => {
1885                handler.on_opcode_decoded(Opcode::Zxtb)?;
1886            }
1887        }
1888    } else {
1889        // top == 0b11
1890        let rest = upper & 0b111;
1891        match rest {
1892            0b000 => {
1893                handler.on_dest_decoded(Operand::gpr(subinstr_gpr_b0(word)))?;
1894                handler.on_opcode_decoded(Opcode::Add)?;
1895                handler.on_source_decoded(Operand::gpr(subinstr_gpr_b0(word)))?;
1896                handler.on_source_decoded(Operand::gpr(subinstr_gpr_b4(word)))?;
1897            }
1898            0b001 => {
1899                handler.on_dest_decoded(Operand::pred(0))?;
1900                handler.on_opcode_decoded(Opcode::CmpEq)?;
1901                handler.on_source_decoded(Operand::gpr(subinstr_gpr_b0(word)))?;
1902                let imm = ((word & 0b1111) as i8) << 4 >> 4;
1903                handler.on_source_decoded(Operand::imm_i8(imm))?;
1904            }
1905            0b010 => {
1906                handler.on_dest_decoded(Operand::gpr(subinstr_gpr_b0(word)))?;
1907                handler.on_opcode_decoded(Opcode::TransferImmediate)?;
1908                if (word >> 6) & 1 == 0 {
1909                    handler.on_source_decoded(Operand::imm_i8(-1))?;
1910                } else {
1911                    let negated = word & 0b01 != 0;
1912                    // HELP: idp_hexagon says this is how the .new suffix is decided, but that's
1913                    // inconsistent with other predication...
1914                    let dotnew = word & 0b10 == 0;
1915                    handler.inst_predicated(0 as u8, negated, dotnew)?;
1916                    handler.on_source_decoded(Operand::imm_i8(0))?;
1917                }
1918            }
1919            0b100 => {
1920                opcode_check!(word & 0b10000000 == 0);
1921                handler.on_dest_decoded(Operand::gprpair(subinstr_gprpair_b0(word))?)?;
1922                handler.on_opcode_decoded(Opcode::Combine)?;
1923                handler.on_source_decoded(Operand::imm_u8((word >> 3) as u8 & 0b11))?;
1924                handler.on_source_decoded(Operand::imm_u8((word >> 5) as u8 & 0b11))?;
1925            }
1926            0b101 => {
1927                handler.on_dest_decoded(Operand::gprpair(subinstr_gprpair_b0(word))?)?;
1928                handler.on_opcode_decoded(Opcode::Combine)?;
1929                let source_reg = Operand::gpr(subinstr_gpr_b4(word));
1930                if word & 0b1000 == 0 {
1931                    handler.on_source_decoded(Operand::imm_u8(0))?;
1932                    handler.on_source_decoded(source_reg)?;
1933                } else {
1934                    handler.on_source_decoded(source_reg)?;
1935                    handler.on_source_decoded(Operand::imm_u8(0))?;
1936                }
1937            }
1938            _ => {
1939                opcode_check!(false);
1940            }
1941        }
1942    }
1943
1944    Ok(())
1945}
1946
1947fn decode_packet<
1948    T: Reader<<Hexagon as Arch>::Address, <Hexagon as Arch>::Word>,
1949    H: DecodeHandler<T>,
1950>(decoder: &<Hexagon as Arch>::Decoder, handler: &mut H, words: &mut T) -> Result<(), <Hexagon as Arch>::DecodeError> {
1951    handler.on_decode_start();
1952
1953    let mut current_word = 0;
1954
1955    // V73 Section 10.6:
1956    // > In addition to encoding the last instruction in a packet, the Parse field of the
1957    // > instruction word (Section 10.5) encodes the last packet in a hardware loop.
1958    //
1959    // accumulate Parse fields to comapre against V73 Table 10-7 once we've read the whole
1960    // packet.
1961    //
1962    // TODO: if the first instruction is a duplex, does that mean the packet cannot indicate
1963    // loop end?
1964    let mut loop_bits: u8 = 0b0000;
1965
1966    // V74 Section 10.6:
1967    // > A constant extender is encoded as a 32-bit instruction with the 4-bit ICLASS field set to
1968    // > 0 and the 2-bit Parse field set to its usual value (Section 10.5). The remaining 26 bits in
1969    // > the instruction word store the data bits that are prepended to an operand as small as six
1970    // > bits to create a full 32-bit value.
1971    // > ...
1972    // > If the instruction operand to extend is longer than six bits, the overlapping bits in the
1973    // > base instruction must be encoded as zeros. The value in the constant extender always
1974    // > supplies the upper 26 bits.
1975    let mut extender: Option<u32> = None;
1976
1977    // have we seen an end of packet?
1978    let mut end = false;
1979
1980    while !end {
1981        if current_word >= 4 {
1982            return Err(DecodeError::InvalidOpcode);
1983        }
1984
1985        let inst: u32 = handler.read_inst_word(words)?;
1986
1987        // V73 Section 10.5:
1988        // > Instruction packets are encoded using two bits of the instruction word (15:14), whic
1989        // > are referred to as the Parse field of the instruction word.
1990        let parse = (inst >> 14) & 0b11;
1991
1992        if current_word == 0 {
1993            loop_bits |= parse as u8;
1994        } else if current_word == 1 {
1995            loop_bits |= (parse as u8) << 2;
1996        }
1997
1998        // V73 Section 10.5:
1999        // > 11 indicates that an instruction is the last instruction in a packet
2000        // > 01 or 10 indicate that an instruction is not the last instruction in a packet
2001        // > 00 indicates a duplex
2002        match parse {
2003            0b00 => {
2004                /* duplex instruction */
2005                // see table 10-2
2006                // exactly how subinstructions are encoded is unclear...
2007                //
2008                // this is best guesses derived from real firmwares, radare, and idp_hexagon..
2009                //
2010                // HELP! really need tests for duplex instructions, not certain this is transcribed
2011                // correctly or that idp_hexagon is correct for all these. especially unsure about
2012                // sign extension of immediates...
2013
2014                let iclass_lo = (inst >> 13) & 0b1;
2015                let iclass_hi = (inst >> 29) & 0b111;
2016                let iclass = iclass_lo | (iclass_hi << 1);
2017
2018                let subinstr_low = inst & 0x1fff;
2019                let subinstr_high = (inst >> 16) & 0x1fff;
2020
2021                struct DuplexParse<
2022                    'a, T, H,
2023                > {
2024                    handler: &'a mut H,
2025                    _phantom: std::marker::PhantomData<T>,
2026                    extender: &'a mut Option<u32>,
2027                    subinstr_low: u16,
2028                    subinstr_high: u16,
2029                }
2030
2031                impl<
2032                    'a,
2033                    T: Reader<<Hexagon as Arch>::Address, <Hexagon as Arch>::Word>,
2034                    H: DecodeHandler<T>
2035                > DuplexParse<'a, T, H> {
2036                    fn parse(
2037                        self,
2038                        parse_lo: fn(&mut H, u16, &mut Option<u32>) -> Result<(), <Hexagon as Arch>::DecodeError>,
2039                        parse_hi: fn(&mut H, u16, &mut Option<u32>) -> Result<(), <Hexagon as Arch>::DecodeError>,
2040                    ) -> Result<(), yaxpeax_arch::StandardDecodeError> {
2041                        self.handler.start_instruction()?;
2042                        parse_lo(self.handler, self.subinstr_low, self.extender)?;
2043                        self.handler.end_instruction()?;
2044                        self.handler.start_instruction()?;
2045                        parse_hi(self.handler, self.subinstr_high, self.extender)?;
2046                        self.handler.end_instruction()?;
2047                        Ok(())
2048                    }
2049                }
2050
2051                let ctx = DuplexParse {
2052                    handler,
2053                    _phantom: std::marker::PhantomData,
2054                    extender: &mut extender,
2055                    subinstr_low: subinstr_low as u16,
2056                    subinstr_high: subinstr_high as u16,
2057                };
2058
2059                match iclass {
2060                    0b0000 => {
2061                        ctx.parse(subinstr_l1, subinstr_l1)?;
2062                    },
2063                    0b0001 => {
2064                        ctx.parse(subinstr_l2, subinstr_l1)?;
2065                    },
2066                    0b0010 => {
2067                        ctx.parse(subinstr_l2, subinstr_l2)?;
2068                    },
2069                    0b0011 => {
2070                        ctx.parse(subinstr_a, subinstr_a)?;
2071                    },
2072                    0b0100 => {
2073                        ctx.parse(subinstr_l1, subinstr_a)?;
2074                    },
2075                    0b0101 => {
2076                        ctx.parse(subinstr_l2, subinstr_a)?;
2077                    },
2078                    0b0110 => {
2079                        ctx.parse(subinstr_s1, subinstr_a)?;
2080                    },
2081                    0b0111 => {
2082                        ctx.parse(subinstr_s2, subinstr_a)?;
2083                    },
2084                    0b1000 => {
2085                        ctx.parse(subinstr_s1, subinstr_l1)?;
2086                    },
2087                    0b1001 => {
2088                        ctx.parse(subinstr_s1, subinstr_l2)?;
2089                    },
2090                    0b1010 => {
2091                        ctx.parse(subinstr_s1, subinstr_s1)?;
2092                    },
2093                    0b1011 => {
2094                        ctx.parse(subinstr_s2, subinstr_s1)?;
2095                    },
2096                    0b1100 => {
2097                        ctx.parse(subinstr_s2, subinstr_l1)?;
2098                    },
2099                    0b1101 => {
2100                        ctx.parse(subinstr_s2, subinstr_l2)?;
2101                    },
2102                    0b1110 => {
2103                        ctx.parse(subinstr_s2, subinstr_s2)?;
2104                    },
2105                    _ => {
2106                        // 0b1111 is the last possible pattern, but _ makes this exhaustive anyway
2107                        opcode_check!(false);
2108                    }
2109                }
2110
2111                // from the V79 manual:
2112                // > The duplex must always appear as the last word in a packet.
2113                handler.on_decode_end();
2114
2115                return Ok(());
2116            }
2117            0b01 | 0b10 => { /* nothing to do here */ }
2118            0b11 => {
2119                end = true;
2120
2121                if loop_bits & 0b0111 == 0b0110 {
2122                    handler.on_loop_end(0);
2123                } else if loop_bits == 0b1001 {
2124                    handler.on_loop_end(1);
2125                } else if loop_bits == 0b1010 {
2126                    handler.on_loop_end(0);
2127                    handler.on_loop_end(1);
2128                }
2129            }
2130            _ => {
2131                unreachable!();
2132            }
2133        }
2134
2135        let iclass = (inst >> 28) & 0b1111;
2136
2137        if iclass == 0b0000 {
2138            extender = Some((inst & 0x3fff) | ((inst >> 2) & 0x3ffc000));
2139        } else {
2140            handler.start_instruction()?;
2141            decode_instruction(decoder, handler, inst, &mut extender)?;
2142            // V73 section 10.9:
2143            // > The constant extender serves as a prefix for an instruction: it does not execute
2144            // > in a slot, nor does it consume slot resources.
2145            // > ...
2146            // > If a constant extender is encoded in a packet for an instruction that does not
2147            // > accept a constant extender, the execution result is undefined. The assembler
2148            // > normally ensures that only valid constant extenders are generated.
2149            //
2150            // the extender must extend the instruction word that follows it.
2151            if extender.is_some() {
2152                // if the extender was not consumed, the instruction (packet) is invalid
2153                return Err(DecodeError::InvalidOpcode);
2154            }
2155            handler.end_instruction()?;
2156        }
2157
2158        current_word += 1;
2159    }
2160
2161    opcode_check!(extender.is_none());
2162
2163    handler.on_decode_end();
2164
2165    Ok(())
2166}
2167
2168fn decode_instruction<
2169    T: Reader<<Hexagon as Arch>::Address, <Hexagon as Arch>::Word>,
2170    H: DecodeHandler<T>,
2171>(_decoder: &<Hexagon as Arch>::Decoder, handler: &mut H, inst: u32, extender: &mut Option<u32>) -> Result<(), <Hexagon as Arch>::DecodeError> {
2172    let iclass = (inst >> 28) & 0b1111;
2173
2174    use Opcode::*;
2175
2176    // this is *called* "RegType" in the manual but it seem to more often describe
2177    // opcodes?
2178    let reg_type = (inst >> 24) & 0b1111;
2179    let min_op = (inst >> 21) & 0b111;
2180
2181    match iclass {
2182        0b0001 => {
2183            // everything at
2184            // 0001 |1xxxxxxx.. is an undefined encoding
2185            opcode_check!((inst >> 27) & 1 == 0);
2186
2187            let opbits = (inst >> 22) & 0b11111;
2188            let ssss = (inst >> 16) & 0b1111;
2189            let dddd = (inst >> 8) & 0b1111;
2190            let i_hi = (inst >> 20) & 0b11;
2191            let i_lo = (inst >> 1) & 0b111_1111;
2192            let i9 = ((i_hi << 7) | i_lo) as i32;
2193            let i9 = i9 << 23 >> 23;
2194
2195            if opbits < 0b11000 {
2196                // one of a few kinds of compare+jump
2197                opcode_check!(opbits <= 0b10110);
2198
2199                handler.on_dest_decoded(Operand::PCRel32 { rel: i9 << 2 })?;
2200                handler.on_source_decoded(Operand::gpr_4b(ssss as u8))?;
2201
2202                // TODO: might be nice to push negation through to the opcode. "TestJumpClr" being
2203                // used for `p1=tstbit(Rs,#0); if (!p1.new) jump:t` is a very confusing way to say
2204                // "TestJumpSet".
2205
2206                let hint_taken = (inst >> 13) & 1 == 1;
2207                handler.branch_hint(hint_taken)?;
2208
2209                let negated = opbits & 1 == 1;
2210
2211                static HIGH_OPS: [Option<Opcode>; 4] = [
2212                    Some(CmpEqJump), Some(CmpGtJump),
2213                    Some(CmpGtuJump), None,
2214                ];
2215
2216                if opbits < 0b10000 {
2217                    // among other things, predicate register selected by bit a higher bit
2218                    let p = (opbits >> 3) & 1;
2219                    handler.inst_predicated(p as u8, negated, true)?;
2220
2221                    if let Some(opc) = HIGH_OPS[((opbits as usize) >> 1) & 0b11] {
2222                        handler.on_opcode_decoded(opc)?;
2223                        let lllll = (inst >> 8) & 0b11111;
2224                        handler.on_source_decoded(Operand::imm_u32(lllll))?;
2225                    } else {
2226                        const LOW_OPS: [Option<Opcode>; 4] = [
2227                            Some(CmpEqJump), Some(CmpGtJump),
2228                            None, Some(TestClrJump),
2229                        ];
2230                        let low_opbits = (inst as usize >> 8) & 0b11;
2231                        handler.on_opcode_decoded(decode_opcode!(LOW_OPS[low_opbits]))?;
2232                        if low_opbits == 0b11 {
2233                            handler.on_source_decoded(Operand::imm_u8(0))?;
2234                        } else {
2235                            handler.on_source_decoded(Operand::imm_i32(-1))?;
2236                        }
2237                    }
2238                } else {
2239                    // predicate picked by one of the lowest bits now...
2240                    let p = (inst >> 12) & 1;
2241                    handler.inst_predicated(p as u8, negated, true)?;
2242                    let tttt = inst >> 8 & 0b1111;
2243                    handler.on_opcode_decoded(decode_opcode!(HIGH_OPS[((opbits as usize) >> 1) & 0b11]))?;
2244                    handler.on_source_decoded(Operand::gpr_4b(tttt as u8))?;
2245                }
2246            } else {
2247                handler.on_dest_decoded(Operand::PCRel32 { rel: i9 << 2 })?;
2248                if opbits < 0b11100 {
2249                    let llllll = (inst >> 8) & 0b11_1111;
2250                    // this one breaks the pattern, uses the otherwise-ssss field as dddd
2251                    handler.on_opcode_decoded(Opcode::TransferImmediateJump)?;
2252                    handler.on_source_decoded(Operand::imm_u32(llllll))?;
2253                    handler.on_dest_decoded(Operand::gpr_4b(ssss as u8))?;
2254                } else {
2255                    handler.on_opcode_decoded(Opcode::TransferRegisterJump)?;
2256                    handler.on_source_decoded(Operand::gpr_4b(ssss as u8))?;
2257                    handler.on_dest_decoded(Operand::gpr_4b(dddd as u8))?;
2258                }
2259            }
2260        }
2261        0b0010 => {
2262            // everything at
2263            // 0010 |1xxxxxxx.. is an undefined encoding
2264            opcode_check!((inst >> 27) & 1 == 0);
2265
2266            let hint_taken = (inst >> 13) & 1 == 1;
2267            let op = (inst >> 22) & 0b11111;
2268
2269            let r_lo = (inst >> 1) & 0b111_1111;
2270            let r_hi = (inst >> 20) & 0b11;
2271            let r = (((r_hi << 7) | r_lo) << 2) as i16;
2272            let r = r << 5 >> 5;
2273
2274            let sss = ((inst >> 16) & 0b111) as u8;
2275
2276            handler.on_dest_decoded(Operand::PCRel32 {
2277                rel: r as i32
2278            })?;
2279
2280            handler.branch_hint(hint_taken)?;
2281
2282            if op < 0b10000 {
2283                // these are `if([!]cmp.op(Ns.new,Rt)) jump:[n]t #r9:2`
2284                let ttttt = reg_b8(inst);
2285
2286                if op < 0b0110 {
2287                    handler.on_nv_register(sss)?;
2288                    handler.on_source_decoded(Operand::gpr(ttttt))?;
2289                } else {
2290                    handler.on_source_decoded(Operand::gpr(ttttt))?;
2291                    handler.on_nv_register(sss)?;
2292                }
2293
2294                static OPS: [Option<Opcode>; 16] = [
2295                    Some(JumpEq), Some(JumpNeq), Some(JumpGt), Some(JumpLe),
2296                    Some(JumpGtu), Some(JumpLeu), Some(JumpGt), Some(JumpLe),
2297                    Some(JumpGtu), Some(JumpLeu), None, None,
2298                    None, None, None, None,
2299                ];
2300
2301                handler.on_opcode_decoded(decode_opcode!(OPS[op as usize]))?;
2302            } else {
2303                handler.on_nv_register(sss)?;
2304
2305                if op < 0b10110 {
2306                    let lllll = reg_b8(inst);
2307                    static OPS: &[Opcode; 6] = &[
2308                        JumpEq, JumpNeq, JumpGt, JumpLe,
2309                        JumpGtu, JumpLeu
2310                    ];
2311
2312                    handler.on_source_decoded(Operand::immext(lllll as u32, extender, |i| Ok(Operand::imm_u32(i)))?)?;
2313                    handler.on_opcode_decoded(OPS[op as usize - 0b10000])?;
2314                } else if op < 0b11000 {
2315                    let opc = if op == 0b10110 {
2316                        JumpBitSet
2317                    } else {
2318                        JumpBitClear
2319                    };
2320                    handler.on_source_decoded(Operand::imm_u32(0))?;
2321                    handler.on_opcode_decoded(opc)?;
2322                } else if op < 0b11100 {
2323                    static OPS: &[Opcode; 4] = &[
2324                        JumpEq, JumpNeq, JumpGt, JumpLe,
2325                    ];
2326                    handler.on_source_decoded(Operand::imm_i32(-1))?;
2327                    handler.on_opcode_decoded(OPS[op as usize - 0b11000])?;
2328                } else {
2329                    return Err(DecodeError::InvalidOpcode);
2330                }
2331            }
2332        }
2333        0b0011 => {
2334            let upper = reg_type >> 2;
2335            match upper {
2336                0b00 => {
2337                    // 0011 | 00xxxxxxx
2338                    // everything under this is a predicated load
2339                    let nn = (inst >> 24) & 0b11;
2340
2341                    let negated = nn & 1 == 1;
2342                    let pred_new = nn >> 1 == 1;
2343
2344                    let ddddd = reg_b0(inst);
2345                    let vv = ((inst >> 5) & 0b11) as u8;
2346                    let i_lo = (inst >> 7) & 0b1;
2347                    let ttttt = reg_b8(inst);
2348                    let i_hi = ((inst >> 13) & 0b1) << 1;
2349                    let ii = (i_lo | i_hi) as u8;
2350                    let sssss = reg_b16(inst);
2351                    let op = (inst >> 21) & 0b111;
2352
2353                    handler.inst_predicated(vv, negated, pred_new)?;
2354
2355                    handler.on_source_decoded(Operand::RegShiftedReg { base: sssss, index: ttttt, shift: ii })?;
2356                    if op == 0b110 {
2357                        handler.on_dest_decoded(Operand::gprpair(ddddd)?)?;
2358                    } else {
2359                        handler.on_dest_decoded(Operand::gpr(ddddd))?;
2360                    }
2361
2362                    use Opcode::*;
2363                    static OPCODES: [Option<Opcode>; 8] = [
2364                        Some(LoadMemb), Some(LoadMemub), Some(LoadMemh), Some(LoadMemuh),
2365                        Some(LoadMemw), None,        Some(LoadMemd), None,
2366                    ];
2367                    handler.on_opcode_decoded(OPCODES[op as usize].ok_or(DecodeError::InvalidOpcode)?)?;
2368                }
2369                0b01 => {
2370                    // 00011 | 01xxxxxxx
2371                    // everything under this is a predicated store
2372                    let nn = (inst >> 24) & 0b11;
2373
2374                    let negated = nn & 1 == 1;
2375                    let pred_new = nn >> 1 == 1;
2376
2377                    let ttttt = reg_b0(inst);
2378                    let vv = ((inst >> 5) & 0b11) as u8;
2379                    let i_lo = (inst >> 7) & 0b1;
2380                    let uuuuu = reg_b8(inst);
2381                    let i_hi = ((inst >> 13) & 0b1) << 1;
2382                    let ii = (i_lo | i_hi) as u8;
2383                    let sssss = reg_b16(inst);
2384                    let op = (inst >> 21) & 0b111;
2385
2386                    handler.inst_predicated(vv, negated, pred_new)?;
2387                    handler.on_dest_decoded(Operand::RegShiftedReg { base: sssss, index: uuuuu, shift: ii })?;
2388
2389                    if op == 0b101 {
2390                        // more complicated procedure, and registers are `Nt.new`
2391                        let op = (inst >> 3) & 0b11;
2392                        let ttt = inst & 0b111;
2393                        static OPCODES: [Option<Opcode>; 4] = [
2394                            Some(StoreMemb), Some(StoreMemh),
2395                            Some(StoreMemw), None,
2396                        ];
2397                        handler.on_opcode_decoded(decode_opcode!(OPCODES[op as usize]))?;
2398                        handler.on_nv_register(ttt as u8)?;
2399                    } else {
2400                        static OPCODES: [Option<Opcode>; 8] = [
2401                            Some(StoreMemb), None, Some(StoreMemh), Some(StoreMemh),
2402                            Some(StoreMemw), None,        Some(StoreMemd), None,
2403                        ];
2404                        handler.on_opcode_decoded(decode_opcode!(OPCODES[op as usize]))?;
2405                        if op == 0b011 {
2406                            handler.on_source_decoded(Operand::GprHigh { reg: ttttt })?;
2407                        } else if op == 0b110 {
2408                            handler.on_source_decoded(Operand::gpr(ttttt))?;
2409                        } else {
2410                            handler.on_source_decoded(Operand::gprpair(ttttt)?)?;
2411                        }
2412                    }
2413                }
2414                0b10 => {
2415                    // 00011 | 10xxxxxxx
2416                    // some predicated stores, but also some predicated loads
2417                    let sssss = reg_b16(inst);
2418
2419                    let predicate_store = (inst >> 25) & 0b1 == 0;
2420                    if predicate_store {
2421                        let nn = (inst >> 23) & 0b11;
2422
2423                        let l_lo = reg_b0(inst);
2424                        let vv = ((inst >> 5) & 0b11) as u8;
2425                        let iiiiii = (inst >> 7) & 0b11_1111;
2426                        let l_hi = (((inst >> 13) & 0b1) << 5) as u8;
2427                        let llllll = (l_lo | l_hi) as u32;
2428                        let op = (inst >> 21) & 0b11;
2429
2430                        let negated = nn & 1 == 1;
2431                        let pred_new = nn >> 1 == 1;
2432
2433                        handler.inst_predicated(vv, negated, pred_new)?;
2434
2435                        let offset = iiiiii;
2436                        handler.on_dest_decoded(Operand::RegOffset { base: sssss, offset })?;
2437
2438                        match op {
2439                            0b00 => {
2440                                handler.on_opcode_decoded(Opcode::StoreMemb)?;
2441
2442                                let imm = Operand::with_extension(llllll, extender,
2443                                    |imm| Ok(Operand::imm_u32(imm)),
2444                                    |imm| Ok(Operand::imm_i8((imm as i8) << 2 >> 2)),
2445                                )?;
2446                                handler.on_source_decoded(imm)?;
2447                            }
2448                            0b01 => {
2449                                handler.on_opcode_decoded(Opcode::StoreMemh)?;
2450
2451                                let imm = Operand::with_extension(llllll, extender,
2452                                    |imm| Ok(Operand::imm_u32(imm)),
2453                                    |imm| Ok(Operand::imm_i16((imm as i16) << 10 >> 10)),
2454                                )?;
2455                                handler.on_source_decoded(imm)?;
2456                            }
2457                            0b10 => {
2458                                handler.on_opcode_decoded(Opcode::StoreMemw)?;
2459                                let imm = (llllll as i32) << 26 >> 26;
2460                                handler.on_source_decoded(Operand::imm_i32(imm))?;
2461
2462                                let imm = Operand::with_extension(llllll, extender,
2463                                    |imm| Ok(Operand::imm_u32(imm)),
2464                                    |imm| Ok(Operand::imm_i32((imm as i32) << 26 >> 26)),
2465                                )?;
2466                                handler.on_source_decoded(imm)?;
2467                            }
2468                            _ => {
2469                                return Err(DecodeError::InvalidOpcode);
2470                            }
2471                        }
2472                    } else {
2473                        // op determined by min_op
2474                        let store = (inst >> 24) & 1 == 1;
2475
2476                        let reg_low = reg_b0(inst);
2477                        let reg_mid = reg_b8(inst);
2478                        let sssss = reg_b16(inst);
2479
2480                        let i_lo = ((inst >> 7) & 1) as u8;
2481                        let i_hi = (((inst >> 13) & 0b1) << 1) as u8;
2482                        let ii = i_hi | i_lo;
2483
2484                        if store {
2485                            // StoreMem*
2486                            handler.on_dest_decoded(Operand::RegShiftedReg { base: sssss, index: reg_mid, shift: ii })?;
2487                            match min_op {
2488                                0b010 => {
2489                                    handler.on_opcode_decoded(Opcode::StoreMemh)?;
2490                                    handler.on_source_decoded(Operand::gpr(reg_low))?;
2491                                },
2492                                0b011 => {
2493                                    handler.on_opcode_decoded(Opcode::StoreMemh)?;
2494                                    handler.on_source_decoded(Operand::GprHigh { reg: reg_low})?;
2495                                },
2496                                0b100 => {
2497                                    handler.on_opcode_decoded(Opcode::StoreMemb)?;
2498                                    handler.on_source_decoded(Operand::gprpair(reg_low)?)?;
2499                                }
2500                                0b101 => {
2501                                    // more complicated procedure, and registers are `Nt.new`
2502                                    let op = (inst >> 3) & 0b11;
2503                                    let ttt = inst & 0b111;
2504                                    static OPCODES: [Option<Opcode>; 4] = [
2505                                        Some(StoreMemb), Some(StoreMemh),
2506                                        Some(StoreMemw), None,
2507                                    ];
2508                                    handler.on_opcode_decoded(decode_opcode!(OPCODES[op as usize]))?;
2509                                    handler.on_nv_register(ttt as u8)?;
2510                                },
2511                                0b0110 => {
2512                                    handler.on_opcode_decoded(Opcode::StoreMemd)?;
2513                                    handler.on_source_decoded(Operand::gprpair(reg_low)?)?;
2514                                }
2515                                _ => {
2516                                    return Err(DecodeError::InvalidOpcode);
2517                                }
2518                            }
2519                        } else {
2520                            // LoadMem*
2521                            static OPCODES: [Option<Opcode>; 8] = [
2522                                Some(LoadMemb), Some(LoadMemub), Some(LoadMemh), Some(LoadMemh),
2523                                Some(LoadMemw), None,        Some(LoadMemd), None,
2524                            ];
2525
2526                            handler.on_opcode_decoded(decode_opcode!(OPCODES[min_op as usize]))?;
2527                            handler.on_source_decoded(Operand::RegShiftedReg { base: sssss, index: reg_mid, shift: ii })?;
2528                            if min_op == 0b110 {
2529                                handler.on_dest_decoded(Operand::gprpair(reg_low)?)?;
2530                            } else {
2531                                handler.on_dest_decoded(Operand::gpr(reg_low))?;
2532                            }
2533                        }
2534                    }
2535                }
2536                _other => {
2537                    // 0b11, so bits are like 0011|11xxxx
2538                    // these are all stores to Rs+#u6:N, shift is determined by op size.
2539                    // the first few are stores of immediates, most others operate on registers.
2540                    let opc_bits = (inst >> 21) & 0b11111;
2541                    let opc_upper = opc_bits >> 3;
2542                    let opc_lower = opc_bits & 0b11;
2543                    let uuuuuu = (inst >> 7) & 0b111111;
2544                    let sssss = (inst >> 16) & 0b11111;
2545
2546                    match opc_upper {
2547                        0b00 |
2548                        0b01 => {
2549                            let i7 = inst & 0b111_1111;
2550                            let i_hi = ((inst >> 13) & 0b1) << 7;
2551                            let i = i_hi | i7;
2552
2553                            handler.on_opcode_decoded(match opc_lower {
2554                                0b00 => {
2555                                    Opcode::StoreMemb
2556                                }
2557                                0b01 => {
2558                                    Opcode::StoreMemh
2559                                }
2560                                0b10 => {
2561                                    Opcode::StoreMemw
2562                                }
2563                                _ => { return Err(DecodeError::InvalidOpcode); }
2564                            })?;
2565                            handler.on_source_decoded(Operand::imm_i8(i as i8))?;
2566                            handler.on_dest_decoded(Operand::RegOffset {
2567                                base: sssss as u8,
2568                                offset: (uuuuuu as u32) << opc_lower,
2569                            })?;
2570                        },
2571                        0b10 => {
2572                            opcode_check!(inst & 0b0010_0000_0000_0000 == 0);
2573                            let ttttt = inst & 0b11111;
2574                            let assign_mode = (inst >> 5) & 0b11;
2575
2576                            handler.on_opcode_decoded(match opc_lower {
2577                                0b00 => {
2578                                    Opcode::StoreMemb
2579                                }
2580                                0b01 => {
2581                                    Opcode::StoreMemh
2582                                }
2583                                0b10 => {
2584                                    Opcode::StoreMemw
2585                                }
2586                                _ => { return Err(DecodeError::InvalidOpcode); }
2587                            })?;
2588                            handler.assign_mode(match assign_mode {
2589                                0b00 => AssignMode::AddAssign,
2590                                0b01 => AssignMode::SubAssign,
2591                                0b10 => AssignMode::AndAssign,
2592                                _ => AssignMode::OrAssign,
2593                            })?;
2594                            handler.on_source_decoded(Operand::gpr(ttttt as u8))?;
2595                            handler.on_dest_decoded(Operand::RegOffset {
2596                                base: sssss as u8,
2597                                offset: (uuuuuu as u32) << opc_lower,
2598                            })?;
2599                        },
2600                        _ => {
2601                            opcode_check!(inst & 0b0010_0000_0000_0000 == 0);
2602                            let ttttt = inst & 0b11111;
2603                            let assign_mode = (inst >> 5) & 0b11;
2604
2605                            handler.on_opcode_decoded(match opc_lower {
2606                                0b00 => {
2607                                    Opcode::StoreMemb
2608                                }
2609                                0b01 => {
2610                                    Opcode::StoreMemh
2611                                }
2612                                0b10 => {
2613                                    Opcode::StoreMemw
2614                                }
2615                                _ => { return Err(DecodeError::InvalidOpcode); }
2616                            })?;
2617                            handler.assign_mode(match assign_mode {
2618                                0b00 => AssignMode::AddAssign,
2619                                0b01 => AssignMode::SubAssign,
2620                                0b10 => AssignMode::ClrBit,
2621                                _ => AssignMode::SetBit,
2622                            })?;
2623                            handler.on_source_decoded(Operand::imm_u8(ttttt as u8))?;
2624                            handler.on_dest_decoded(Operand::RegOffset {
2625                                base: sssss as u8,
2626                                offset: (uuuuuu as u32) << opc_lower,
2627                            })?;
2628                        }
2629                    }
2630                }
2631            }
2632        }
2633        0b0100 => {
2634            // 0 1 0 0|...
2635            // loads and stores with large (6b+) offsets
2636            let predicated = (inst >> 27) & 1 == 0;
2637            let store = (inst >> 24) & 1 == 0;
2638
2639            if predicated {
2640                let dotnew = (inst >> 26) & 0b1 == 1;
2641                let negated = (inst >> 25) & 0b1 == 1;
2642
2643                let opbits = (inst >> 21) & 0b111;
2644                let sssss = reg_b16(inst);
2645
2646                if store {
2647                    let pred_reg = inst & 0b11;
2648                    handler.inst_predicated(pred_reg as u8, negated, dotnew)?;
2649
2650                    let srcreg = reg_b8(inst);
2651                    let i5 = (inst >> 3) & 0b11111;
2652                    let i = ((inst >> 13) & 1) << 5;
2653                    let iiiiii = i | i5;
2654
2655                    decode_store_ops(handler, opbits as u8, srcreg as u8, |shamt| {
2656                        Operand::with_extension(
2657                            iiiiii, extender,
2658                            |offset| Ok(Operand::RegOffset {
2659                                base: sssss as u8,
2660                                offset,
2661                            }),
2662                            |offset| Ok(Operand::RegOffset {
2663                                base: sssss as u8,
2664                                offset: offset << shamt,
2665                            }),
2666                        )
2667                    })?;
2668                } else {
2669                    let pred_reg = (inst >> 11) & 0b11;
2670                    handler.inst_predicated(pred_reg as u8, negated, dotnew)?;
2671
2672                    let dstreg = reg_b0(inst);
2673                    let iiiiii = (inst >> 5) & 0b111111;
2674
2675                    decode_load_ops(handler, opbits as u8, dstreg as u8, |shamt| {
2676                        Operand::with_extension(
2677                            iiiiii, extender,
2678                            |offset| Ok(Operand::RegOffset {
2679                                base: sssss as u8,
2680                                offset,
2681                            }),
2682                            |offset| Ok(Operand::RegOffset {
2683                                base: sssss as u8,
2684                                offset: offset << shamt,
2685                            }),
2686                        )
2687                    })?;
2688                }
2689            } else {
2690                let i14 = (inst >> 25) & 0b11;
2691                let i9 = (inst >> 16) & 0b11111;
2692                let i_8 = (inst >> 13) & 0b1;
2693
2694                let opbits = ((inst >> 21) & 0b111) as u8;
2695
2696                if store {
2697                    let i_lo = inst & 0b1111_1111;
2698                    let i = (i14 << 14) | (i9 << 9) | (i_8 << 8) | i_lo;
2699                    let ttttt = reg_b8(inst);
2700
2701                    decode_store_ops(handler, opbits, ttttt, |shamt| {
2702                        Operand::with_extension(
2703                            i, extender,
2704                            |imm| Ok(Operand::Immext { imm }),
2705                            |offset| Ok(Operand::GpOffset {
2706                                offset: offset << shamt,
2707                            }),
2708                        )
2709                    })?;
2710                } else {
2711                    let i_lo = (inst >> 5) & 0b1111_1111;
2712                    let i = (i14 << 14) | (i9 << 9) | (i_8 << 8) | i_lo;
2713                    let ddddd = reg_b0(inst);
2714
2715                    decode_load_ops(handler, opbits, ddddd, |shamt| {
2716                        Operand::with_extension(
2717                            i, extender,
2718                            |imm| Ok(Operand::Immext { imm }),
2719                            |offset| Ok(Operand::GpOffset {
2720                                offset: offset << shamt,
2721                            }),
2722                        )
2723                    })?;
2724                }
2725            }
2726        },
2727        0b0101 => {
2728            let majop = (inst >> 25) & 0b111;
2729            match majop {
2730                0b000 => {
2731                    // 0 1 0 1 | 0 0 0 ...
2732                    // call to register, may be predicated
2733                    let op = (inst >> 21) & 0b1111;
2734                    let sssss = reg_b16(inst);
2735                    handler.on_dest_decoded(Operand::gpr(sssss))?;
2736
2737                    if op >= 0b1000 {
2738                        // predicated callr
2739                        opcode_check!(op < 0b1010);
2740                        handler.on_opcode_decoded(Opcode::Callr)?;
2741                        let negated = op & 1 == 1;
2742                        let uu = (inst >> 8) & 0b11;
2743                        handler.inst_predicated(uu as u8, negated, false)?;
2744                    } else {
2745                        // unconditional callr/callrh
2746                        opcode_check!(op == 0b101 || op == 0b110);
2747                        if op == 0b101 {
2748                            handler.on_opcode_decoded(Opcode::Callr)?;
2749                        } else {
2750                            handler.on_opcode_decoded(Opcode::Callrh)?;
2751                        }
2752                    }
2753                },
2754                0b001 => {
2755                    // 0 1 0 1 | 0 0 1 ...
2756                    // jump to register, may be predicated
2757                    let op = (inst >> 21) & 0b1111;
2758                    let sssss = reg_b16(inst);
2759
2760                    if op >= 0b1000 {
2761                        // predicated jumpr
2762                        opcode_check!(op == 0b0100 || op == 0b0101 || op == 0b0110 || op == 0b1010 || op == 0b1011);
2763                        handler.on_opcode_decoded(Opcode::Jumpr)?;
2764                        handler.on_dest_decoded(Operand::gpr(sssss))?;
2765                        let negated = op & 1 == 1;
2766                        let dotnew = (inst >> 11) & 1 == 1;
2767                        let hint_taken = (inst >> 12) & 1 == 1;
2768                        let uu = (inst >> 8) & 0b11;
2769                        handler.inst_predicated(uu as u8, negated, dotnew)?;
2770                        handler.branch_hint(hint_taken)?;
2771                    } else {
2772                        // unconditional jumpr/jumprh
2773                        opcode_check!(op == 0b100 || op == 0b101 || op == 0b110);
2774                        if op == 0b100 {
2775                            handler.on_opcode_decoded(Opcode::Jumpr)?;
2776                            handler.on_dest_decoded(Operand::gpr(sssss))?;
2777                        } else if op == 0b101 {
2778                            handler.on_opcode_decoded(Opcode::Hintjr)?;
2779                            handler.on_source_decoded(Operand::gpr(sssss))?;
2780                        } else {
2781                            handler.on_opcode_decoded(Opcode::Jumprh)?;
2782                            handler.on_dest_decoded(Operand::gpr(sssss))?;
2783                        }
2784                    }
2785                },
2786                0b010 => {
2787                    // trap0, pause, trap1
2788                    let minbits = (inst >> 22) & 0b111;
2789                    let u_low = (inst >> 2) & 0b111;
2790                    let u_mid = (inst >> 8) & 0b11111;
2791                    let u_8 = (u_mid << 3) | u_low;
2792
2793                    if minbits == 0b000 {
2794                        handler.on_opcode_decoded(Opcode::Trap0)?;
2795                        handler.on_source_decoded(Operand::imm_u8(u_8 as u8))?;
2796                    } else if minbits == 0b001 {
2797                        handler.on_opcode_decoded(Opcode::Pause)?;
2798                        let u_high = (inst >> 16) & 0b11;
2799                        let u_10 = (u_high << 8) | u_8;
2800                        handler.on_source_decoded(Operand::imm_u16(u_10 as u16))?;
2801                    } else if minbits == 0b010 {
2802                        handler.on_opcode_decoded(Opcode::Trap1)?;
2803                        let xxxxx = reg_b16(inst);
2804                        handler.on_source_decoded(Operand::gpr(xxxxx))?;
2805                        handler.on_source_decoded(Operand::imm_u8(u_8 as u8))?;
2806                    } else if minbits == 0b110 {
2807                        opcode_check!(inst & (1 << 21) != 0);
2808                        handler.on_opcode_decoded(Opcode::Icdatar)?;
2809                        handler.on_dest_decoded(Operand::gpr(reg_b0(inst)))?;
2810                        handler.on_source_decoded(Operand::gpr(reg_b16(inst)))?;
2811                    } else if minbits == 0b111 {
2812                        if inst & (1 << 21) == 0 {
2813                            handler.on_opcode_decoded(Opcode::Ictagw)?;
2814                            handler.on_source_decoded(Operand::gpr(reg_b16(inst)))?;
2815                            handler.on_source_decoded(Operand::gpr(reg_b8(inst)))?;
2816                        } else {
2817                            handler.on_opcode_decoded(Opcode::Ictagr)?;
2818                            handler.on_dest_decoded(Operand::gpr(reg_b0(inst)))?;
2819                            handler.on_source_decoded(Operand::gpr(reg_b16(inst)))?;
2820                        }
2821                    } else {
2822                        opcode_check!(false);
2823                    }
2824                },
2825                0b011 => {
2826                    // icinva, isync, unpause
2827                    let minbits = (inst >> 21) & 0b1111;
2828
2829                    if minbits == 0b0110 {
2830                        let op = (inst >> 11) & 0b111;
2831                        if op == 0b000 {
2832                            handler.on_opcode_decoded(Opcode::Icinva)?;
2833                            handler.on_source_decoded(Operand::gpr(reg_b16(inst)))?;
2834                        } else if op == 0b010 {
2835                            handler.on_opcode_decoded(Opcode::IcKill)?;
2836                        } else {
2837                            opcode_check!(false);
2838                        }
2839                    } else if minbits == 0b0111 {
2840                        handler.on_opcode_decoded(Opcode::Icinvidx)?;
2841                        handler.on_source_decoded(Operand::gpr(reg_b16(inst)))?;
2842                    } else if minbits == 0b1110 {
2843                        handler.on_opcode_decoded(Opcode::Isync)?;
2844                        opcode_check!(inst & 0x1f23ff == 0x000002);
2845                    } else if minbits == 0b1111 {
2846                        handler.on_opcode_decoded(Opcode::Unpause)?;
2847                        opcode_check!(inst & 0x10e0 == 0x1000);
2848                    } else {
2849                        opcode_check!(false);
2850                    }
2851                },
2852                0b100 => {
2853                    // V73 Jump to address
2854                    // 0 1 0 1 | 1 0 0 i...
2855                    handler.on_opcode_decoded(Opcode::Jump)?;
2856                    let imm = ((inst >> 1) & 0x1fff) | ((inst >> 3) & 0xffe000);
2857                    let imm = ((imm as i32) << 10) >> 10;
2858                    handler.on_dest_decoded(
2859                        Operand::with_extension(
2860                            imm as u32, extender,
2861                            |rel| Ok(Operand::PCRel32 { rel: rel as i32 }),
2862                            |rel| Ok(Operand::PCRel32 { rel: (rel << 2) as i32 }),
2863                        )?
2864                    )?;
2865                },
2866                0b101 => {
2867                    // V73 Call to address
2868                    // 0 1 0 1 | 1 0 1 i...
2869                    if inst & 0 != 0 {
2870                        // unlike jump, for some reason, the last bit is defined to be 0
2871                        return Err(DecodeError::InvalidOpcode);
2872                    }
2873                    handler.on_opcode_decoded(Opcode::Call)?;
2874                    let imm = ((inst >> 1) & 0x1fff) | ((inst >> 3) & 0xffe000);
2875                    let imm = ((imm as i32) << 10) >> 10;
2876                    handler.on_dest_decoded(
2877                        Operand::with_extension(
2878                            imm as u32, extender,
2879                            |rel| Ok(Operand::PCRel32 { rel: rel as i32 }),
2880                            |rel| Ok(Operand::PCRel32 { rel: (rel << 2) as i32 }),
2881                        )?
2882                    )?;
2883                },
2884                0b110 => {
2885                    // V73 Predicated jump/call relative
2886                    let negated = (inst >> 21) & 1 == 1;
2887                    let dotnew = (inst >> 11) & 1 == 1;
2888                    let uu = (inst >> 8) & 0b11;
2889                    let hint_taken = (inst >> 11) == 1;
2890
2891                    let i_lo = (inst >> 1) & 0x7f;
2892                    let i_8 = (inst >> 13) & 1;
2893                    let i_mid = (inst >> 16) & 0x1f;
2894                    let i_hi = (inst >> 22) & 0b11;
2895                    let i15 = i_lo | (i_8 << 7) | (i_mid << 8) | (i_hi << 13);
2896                    let i15 = (i15 as i32) << 17 >> 17;
2897
2898                    let is_call = (inst >> 24) & 1 == 1;
2899
2900                    if is_call {
2901                        handler.on_opcode_decoded(Opcode::Call)?;
2902                        handler.inst_predicated(uu as u8, negated, false)?;
2903                        opcode_check!(!dotnew);
2904                    } else {
2905                        // ... not shown as extended in the manual? does have an
2906                        // `apply_extension()` though
2907                        handler.on_opcode_decoded(Opcode::Jump)?;
2908                        handler.inst_predicated(uu as u8, negated, dotnew)?;
2909                        handler.branch_hint(hint_taken)?;
2910                    }
2911                    handler.on_dest_decoded(
2912                        Operand::with_extension(
2913                            i15 as u32, extender,
2914                            |rel| Ok(Operand::PCRel32 { rel: rel as i32 }),
2915                            |rel| Ok(Operand::PCRel32 { rel: (rel << 2) as i32 }),
2916                        )?
2917                    )?;
2918                }
2919                0b111 => {
2920                    return Err(DecodeError::InvalidOpcode);
2921                }
2922                _ => {
2923                    opcode_check!(false);
2924                }
2925            }
2926        },
2927        0b0110 => {
2928            let opbits = (inst >> 21) & 0b1111111;
2929
2930            match opbits {
2931                0b0000000 => {
2932                    let sssss = reg_b16(inst);
2933                    let iiiii = reg_b8(inst);
2934                    let ii = ((inst >> 3) & 0b11) as u8;
2935                    let i7 = (iiiii << 2) | ii;
2936                    let rel = ((i7 << 1) as i8 as i32) << 1;
2937
2938                    handler.on_opcode_decoded(Opcode::Loop0)?;
2939                    handler.on_source_decoded(
2940                        Operand::with_extension(
2941                            rel as u32, extender,
2942                            |rel| Ok(Operand::PCRel32 { rel: rel as i32 }),
2943                            |rel| Ok(Operand::PCRel32 { rel: rel as i32 }),
2944                        )?
2945                    )?;
2946                    handler.on_source_decoded(Operand::gpr(sssss))?;
2947                }
2948                0b0000001 => {
2949                    let sssss = reg_b16(inst);
2950                    let iiiii = reg_b8(inst);
2951                    let ii = ((inst >> 3) & 0b11) as u8;
2952                    let i7 = (iiiii << 2) | ii;
2953                    let rel = ((i7 << 1) as i8 as i32) << 1;
2954
2955                    handler.on_opcode_decoded(Opcode::Loop1)?;
2956                    handler.on_source_decoded(
2957                        Operand::with_extension(
2958                            rel as u32, extender,
2959                            |rel| Ok(Operand::PCRel32 { rel: rel as i32 }),
2960                            |rel| Ok(Operand::PCRel32 { rel: rel as i32 }),
2961                        )?
2962                    )?;
2963                    handler.on_source_decoded(Operand::gpr(sssss))?;
2964                }
2965                0b0000010 | 0b0000011 => {
2966                    return Err(DecodeError::InvalidOpcode);
2967                }
2968                0b0000101 => {
2969                    let sssss = reg_b16(inst);
2970                    let iiiii = reg_b8(inst);
2971                    let ii = ((inst >> 3) & 0b11) as u8;
2972                    let i7 = (iiiii << 2) | ii;
2973                    let rel = ((i7 << 1) as i8 as i32) << 1;
2974
2975                    handler.on_opcode_decoded(Opcode::Sp1Loop0)?;
2976                    handler.on_source_decoded(
2977                        Operand::with_extension(
2978                            rel as u32, extender,
2979                            |rel| Ok(Operand::PCRel32 { rel: rel as i32 }),
2980                            |rel| Ok(Operand::PCRel32 { rel: rel as i32 }),
2981                        )?
2982                    )?;
2983                    handler.on_source_decoded(Operand::gpr(sssss))?;
2984                    handler.on_dest_decoded(Operand::pred(3))?;
2985                }
2986                0b0000110 => {
2987                    let sssss = reg_b16(inst);
2988                    let iiiii = reg_b8(inst);
2989                    let ii = ((inst >> 3) & 0b11) as u8;
2990                    let i7 = (iiiii << 2) | ii;
2991                    let rel = ((i7 << 1) as i8 as i32) << 1;
2992
2993                    handler.on_opcode_decoded(Opcode::Sp2Loop0)?;
2994                    handler.on_source_decoded(
2995                        Operand::with_extension(
2996                            rel as u32, extender,
2997                            |rel| Ok(Operand::PCRel32 { rel: rel as i32 }),
2998                            |rel| Ok(Operand::PCRel32 { rel: rel as i32 }),
2999                        )?
3000                    )?;
3001                    handler.on_source_decoded(Operand::gpr(sssss))?;
3002                    handler.on_dest_decoded(Operand::pred(3))?;
3003                }
3004                0b0000111 => {
3005                    let sssss = reg_b16(inst);
3006                    let iiiii = reg_b8(inst);
3007                    let ii = ((inst >> 3) & 0b11) as u8;
3008                    let i7 = (iiiii << 2) | ii;
3009                    let rel = ((i7 << 1) as i8 as i32) << 1;
3010
3011                    handler.on_opcode_decoded(Opcode::Sp3Loop0)?;
3012                    handler.on_source_decoded(
3013                        Operand::with_extension(
3014                            rel as u32, extender,
3015                            |rel| Ok(Operand::PCRel32 { rel: rel as i32 }),
3016                            |rel| Ok(Operand::PCRel32 { rel: rel as i32 }),
3017                        )?
3018                    )?;
3019                    handler.on_source_decoded(Operand::gpr(sssss))?;
3020                    handler.on_dest_decoded(Operand::pred(3))?;
3021                }
3022                0b0001000 | 0b0001001 => {
3023                    let sssss = reg_b16(inst);
3024                    let i11 = (inst >> 1) & 0b111_1111_1111;
3025                    let i_mid = (inst >> 13) & 1;
3026                    let i_hi = (inst >> 21) & 1;
3027                    let i13 = i11 | (i_mid << 11) | (i_hi << 12);
3028                    let rel = (i13 << 3) as i16 as i32 >> 1;
3029
3030                    let taken = (inst >> 12) & 1 == 1;
3031                    handler.branch_hint(taken)?;
3032                    handler.on_opcode_decoded(Opcode::JumpRegNz)?;
3033                    handler.on_source_decoded(Operand::gpr(sssss))?;
3034                    handler.on_dest_decoded(Operand::PCRel32 { rel })?;
3035                }
3036                0b0001010 | 0b0001011 => {
3037                    let sssss = reg_b16(inst);
3038                    let i11 = (inst >> 1) & 0b111_1111_1111;
3039                    let i_mid = (inst >> 13) & 1;
3040                    let i_hi = (inst >> 21) & 1;
3041                    let i13 = i11 | (i_mid << 11) | (i_hi << 12);
3042                    let rel = (i13 << 3) as i16 as i32 >> 1;
3043
3044                    let taken = (inst >> 12) & 1 == 1;
3045                    handler.branch_hint(taken)?;
3046                    handler.on_opcode_decoded(Opcode::JumpRegGez)?;
3047                    handler.on_source_decoded(Operand::gpr(sssss))?;
3048                    handler.on_dest_decoded(Operand::PCRel32 { rel })?;
3049                }
3050                0b0001100 | 0b0001101 => {
3051                    let sssss = reg_b16(inst);
3052                    let i11 = (inst >> 1) & 0b111_1111_1111;
3053                    let i_mid = (inst >> 13) & 1;
3054                    let i_hi = (inst >> 21) & 1;
3055                    let i13 = i11 | (i_mid << 11) | (i_hi << 12);
3056                    let rel = (i13 << 3) as i16 as i32 >> 1;
3057
3058                    let taken = (inst >> 12) & 1 == 1;
3059                    handler.branch_hint(taken)?;
3060                    handler.on_opcode_decoded(Opcode::JumpRegZ)?;
3061                    handler.on_source_decoded(Operand::gpr(sssss))?;
3062                    handler.on_dest_decoded(Operand::PCRel32 { rel })?;
3063                }
3064                0b0001110 | 0b0001111 => {
3065                    let sssss = reg_b16(inst);
3066                    let i11 = (inst >> 1) & 0b111_1111_1111;
3067                    let i_mid = (inst >> 13) & 1;
3068                    let i_hi = (inst >> 21) & 1;
3069                    let i13 = i11 | (i_mid << 11) | (i_hi << 12);
3070                    let rel = (i13 << 3) as i16 as i32 >> 1;
3071
3072                    let taken = (inst >> 12) & 1 == 1;
3073                    handler.branch_hint(taken)?;
3074                    handler.on_opcode_decoded(Opcode::JumpRegLez)?;
3075                    handler.on_source_decoded(Operand::gpr(sssss))?;
3076                    handler.on_dest_decoded(Operand::PCRel32 { rel })?;
3077                }
3078                0b0010001 => {
3079                    let sssss = reg_b16(inst);
3080                    let ddddd = reg_b0(inst);
3081                    handler.on_opcode_decoded(Opcode::TransferRegister)?;
3082                    handler.on_source_decoded(Operand::gpr(sssss))?;
3083                    handler.on_dest_decoded(Operand::cr(ddddd))?;
3084                }
3085                0b0010010 => {
3086                    let opc = (inst >> 5) & 0b111;
3087                    let sssss = reg_b16(inst);
3088                    let ttttt = reg_b8(inst);
3089                    match opc {
3090                        0b000 => {
3091                            handler.on_opcode_decoded(Opcode::Trace)?;
3092                            handler.on_source_decoded(Operand::gpr(sssss))?;
3093                        },
3094                        0b001 => {
3095                            handler.on_opcode_decoded(Opcode::Diag)?;
3096                            handler.on_source_decoded(Operand::gpr(sssss))?;
3097                        },
3098                        0b010 => {
3099                            handler.on_opcode_decoded(Opcode::Diag0)?;
3100                            handler.on_source_decoded(Operand::gprpair(sssss)?)?;
3101                            handler.on_source_decoded(Operand::gprpair(ttttt)?)?;
3102                        },
3103                        0b011 => {
3104                            handler.on_opcode_decoded(Opcode::Diag1)?;
3105                            handler.on_source_decoded(Operand::gprpair(sssss)?)?;
3106                            handler.on_source_decoded(Operand::gprpair(ttttt)?)?;
3107                        },
3108                        _ => { return Err(DecodeError::InvalidOpcode); }
3109                    };
3110                }
3111                0b0100000 => {
3112                    // 000 -> swi
3113                    // 001 -> cswi
3114                    // 011 -> ciad
3115                    static OPS: [Option<Opcode>; 8] = [
3116                        Some(Opcode::Swi), Some(Opcode::Cswi), None, Some(Opcode::Ciad),
3117                        None, None, None, None,
3118                    ];
3119                    handler.on_opcode_decoded(decode_opcode!(OPS[((inst >> 5) & 0b111) as usize]))?;
3120                    handler.on_source_decoded(Operand::gpr(reg_b16(inst)))?;
3121                }
3122                0b0100010 => {
3123                    // 000 -> wait
3124                    // 010 -> resume
3125                    static OPS: [Option<Opcode>; 8] = [
3126                        Some(Opcode::Wait), None, Some(Opcode::Resume), None,
3127                        None, None, None, None,
3128                    ];
3129                    handler.on_opcode_decoded(decode_opcode!(OPS[((inst >> 5) & 0b111) as usize]))?;
3130                    handler.on_source_decoded(Operand::gpr(reg_b16(inst)))?;
3131                }
3132                0b0100011 => {
3133                    // 000 -> stop
3134                    // 001 -> start
3135                    // 010 -> nmi
3136                    static OPS: [Option<Opcode>; 8] = [
3137                        Some(Opcode::Stop), Some(Opcode::Start), Some(Opcode::Nmi), None,
3138                        None, None, None, None,
3139                    ];
3140                    handler.on_opcode_decoded(decode_opcode!(OPS[((inst >> 5) & 0b111) as usize]))?;
3141                    handler.on_source_decoded(Operand::gpr(reg_b16(inst)))?;
3142                }
3143                0b0100100 => {
3144                    // 000 -> setimask
3145                    // 011 -> siad
3146                    static OPS: [Option<Opcode>; 8] = [
3147                        Some(Opcode::Setimask), None, None, Some(Opcode::Siad),
3148                        None, None, None, None,
3149                    ];
3150                    let opc = (inst >> 5) & 0b111;
3151                    handler.on_opcode_decoded(decode_opcode!(OPS[opc as usize]))?;
3152                    if opc == 0b000 {
3153                        handler.on_source_decoded(Operand::pred(reg_b0(inst) & 0b11))?;
3154                    }
3155                    handler.on_source_decoded(Operand::gpr(reg_b16(inst)))?;
3156                }
3157                0b0101000 => {
3158                    handler.on_opcode_decoded(Opcode::Crswap)?;
3159                    handler.on_source_decoded(Operand::gpr(reg_b16(inst)))?;
3160                    handler.on_source_decoded(Operand::sr(0))?;
3161                }
3162                0b0101001 => {
3163                    handler.on_opcode_decoded(Opcode::Crswap)?;
3164                    handler.on_source_decoded(Operand::gpr(reg_b16(inst)))?;
3165                    handler.on_source_decoded(Operand::sr(1))?;
3166                }
3167                0b0110000 => {
3168                    handler.on_opcode_decoded(Opcode::Getimask)?;
3169                    handler.on_dest_decoded(Operand::gpr(reg_b0(inst)))?;
3170                    handler.on_source_decoded(Operand::gpr(reg_b16(inst)))?;
3171                }
3172                0b0111000 => {
3173                    // not in V73! store to supervisor register?
3174                    let sssss = reg_b16(inst);
3175                    let dddddd = inst & 0b11_1111;
3176                    handler.on_opcode_decoded(Opcode::TransferRegister)?;
3177                    handler.on_dest_decoded(Operand::sr(dddddd as u8))?;
3178                    handler.on_source_decoded(Operand::gpr(sssss))?;
3179                }
3180                // TODO: 1001000 loop0 goes here
3181                0b1100001 => {
3182                    // 000 -> brkpt
3183                    // 001 -> tlblock
3184                    // 011 -> k0lock
3185                    static OPS: [Option<Opcode>; 8] = [
3186                        Some(Opcode::Brkpt), Some(Opcode::TlbLock), None, Some(Opcode::K0Lock),
3187                        None, None, None, None,
3188                    ];
3189                    handler.on_opcode_decoded(decode_opcode!(OPS[((inst >> 5) & 0b111) as usize]))?;
3190                }
3191                0b1101000 => {
3192                    // not in V73! store to supervisor register?
3193                    let sssss = reg_b16(inst);
3194                    let ddddddd = inst & 0b111_1111;
3195                    handler.on_opcode_decoded(Opcode::TransferRegister)?;
3196                    handler.on_dest_decoded(Operand::srpair(ddddddd as u8)?)?;
3197                    handler.on_source_decoded(Operand::gprpair(sssss)?)?;
3198                }
3199                0b1101100 => {
3200                    operand_check!(reg_b0(inst) == 0);
3201                    handler.on_opcode_decoded(Opcode::Crswap)?;
3202                    handler.on_source_decoded(Operand::gprpair(reg_b16(inst))?)?;
3203                    handler.on_source_decoded(Operand::srpair(0)?)?;
3204                }
3205                0b1110011 => {
3206                    handler.on_opcode_decoded(Opcode::Iassignr)?;
3207                    handler.on_dest_decoded(Operand::gpr(reg_b0(inst)))?;
3208                    handler.on_source_decoded(Operand::gpr(reg_b16(inst)))?;
3209                }
3210                0b1110100 | 0b1110101 |
3211                0b1110110 | 0b1110111 => {
3212                    // not in V73! load supervisor register?
3213                    let sssss = reg_b0(inst);
3214                    let dddddd = (inst >> 16) & 0b11_1111;
3215                    handler.on_opcode_decoded(Opcode::TransferRegister)?;
3216                    handler.on_source_decoded(Operand::sr(dddddd as u8))?;
3217                    handler.on_dest_decoded(Operand::gpr(sssss))?;
3218                }
3219                0b1111000 | 0b1111001 |
3220                0b1111010 | 0b1111011 => {
3221                    // not in V73! load supervisor register?
3222                    let sssss = reg_b0(inst);
3223                    let ddddddd = (inst >> 16) & 0b111_1111;
3224                    handler.on_opcode_decoded(Opcode::TransferRegister)?;
3225                    handler.on_source_decoded(Operand::srpair(ddddddd as u8)?)?;
3226                    handler.on_dest_decoded(Operand::gprpair(sssss)?)?;
3227                }
3228                0b0011001 => {
3229                    let sssss = reg_b16(inst);
3230                    let ddddd = reg_b0(inst);
3231                    handler.on_opcode_decoded(Opcode::TransferRegister)?;
3232                    handler.on_source_decoded(Operand::gprpair(sssss)?)?;
3233                    handler.on_dest_decoded(Operand::crpair(ddddd)?)?;
3234                }
3235                0b1000000 => {
3236                    let sssss = reg_b16(inst);
3237                    let ddddd = reg_b0(inst);
3238                    handler.on_opcode_decoded(Opcode::TransferRegister)?;
3239                    handler.on_source_decoded(Operand::crpair(sssss)?)?;
3240                    handler.on_dest_decoded(Operand::gprpair(ddddd)?)?;
3241                }
3242                0b1001000 => {
3243                    let lllll = reg_b16(inst) as u32;
3244                    let l_mid = (inst >> 5) & 0b111;
3245                    let l_low = inst & 0b11;
3246                    let l10 = l_low | (l_mid << 2) | (lllll << 5);
3247
3248                    let iiiii = reg_b8(inst);
3249                    let ii = ((inst >> 3) & 0b11) as u8;
3250                    let i7 = (iiiii << 2) | ii;
3251                    let rel = ((i7 << 1) as i8 as i32) << 1;
3252
3253                    handler.on_opcode_decoded(Opcode::Loop0)?;
3254                    handler.on_source_decoded(Operand::PCRel32 { rel })?;
3255                    handler.on_source_decoded(Operand::ImmU16 { imm: l10 as u16 })?;
3256                }
3257                0b1001001 => {
3258                    let lllll = reg_b16(inst) as u32;
3259                    let l_mid = (inst >> 5) & 0b111;
3260                    let l_low = inst & 0b11;
3261                    let l10 = l_low | (l_mid << 2) | (lllll << 5);
3262
3263                    let iiiii = reg_b8(inst);
3264                    let ii = ((inst >> 3) & 0b11) as u8;
3265                    let i7 = (iiiii << 2) | ii;
3266                    let rel = ((i7 << 1) as i8 as i32) << 1;
3267
3268                    handler.on_opcode_decoded(Opcode::Loop1)?;
3269                    handler.on_source_decoded(Operand::PCRel32 { rel })?;
3270                    handler.on_source_decoded(Operand::ImmU16 { imm: l10 as u16 })?;
3271                }
3272                0b1001101 => {
3273                    let lllll = reg_b16(inst) as u32;
3274                    let l_mid = (inst >> 5) & 0b111;
3275                    let l_low = inst & 0b11;
3276                    let l10 = l_low | (l_mid << 2) | (lllll << 5);
3277
3278                    let iiiii = reg_b8(inst);
3279                    let ii = ((inst >> 3) & 0b11) as u8;
3280                    let i7 = (iiiii << 2) | ii;
3281                    let rel = ((i7 << 1) as i8 as i32) << 1;
3282
3283                    handler.on_opcode_decoded(Opcode::Sp1Loop0)?;
3284                    handler.on_source_decoded(Operand::PCRel32 { rel })?;
3285                    handler.on_source_decoded(Operand::ImmU16 { imm: l10 as u16 })?;
3286                    handler.on_dest_decoded(Operand::pred(3))?;
3287                }
3288                0b1001110 => {
3289                    let lllll = reg_b16(inst) as u32;
3290                    let l_mid = (inst >> 5) & 0b111;
3291                    let l_low = inst & 0b11;
3292                    let l10 = l_low | (l_mid << 2) | (lllll << 5);
3293
3294                    let iiiii = reg_b8(inst);
3295                    let ii = ((inst >> 3) & 0b11) as u8;
3296                    let i7 = (iiiii << 2) | ii;
3297                    let rel = ((i7 << 1) as i8 as i32) << 1;
3298
3299                    handler.on_opcode_decoded(Opcode::Sp2Loop0)?;
3300                    handler.on_source_decoded(Operand::PCRel32 { rel })?;
3301                    handler.on_source_decoded(Operand::ImmU16 { imm: l10 as u16 })?;
3302                    handler.on_dest_decoded(Operand::pred(3))?;
3303                }
3304                0b1001111 => {
3305                    let lllll = reg_b16(inst) as u32;
3306                    let l_mid = (inst >> 5) & 0b111;
3307                    let l_low = inst & 0b11;
3308                    let l10 = l_low | (l_mid << 2) | (lllll << 5);
3309
3310                    let iiiii = reg_b8(inst);
3311                    let ii = ((inst >> 3) & 0b11) as u8;
3312                    let i7 = (iiiii << 2) | ii;
3313                    let rel = ((i7 << 1) as i8 as i32) << 1;
3314
3315                    handler.on_opcode_decoded(Opcode::Sp3Loop0)?;
3316                    handler.on_source_decoded(Operand::PCRel32 { rel })?;
3317                    handler.on_source_decoded(Operand::ImmU16 { imm: l10 as u16 })?;
3318                    handler.on_dest_decoded(Operand::pred(3))?;
3319                }
3320                0b1010000 => {
3321                    let sssss = reg_b16(inst);
3322                    let ddddd = reg_b0(inst);
3323                    handler.on_opcode_decoded(Opcode::TransferRegister)?;
3324                    handler.on_source_decoded(Operand::cr(sssss))?;
3325                    handler.on_dest_decoded(Operand::gpr(ddddd))?;
3326                }
3327                0b1010010 => {
3328                    if (inst >> 16) & 0b11111 != 0b01001 {
3329                        // TODO: this is checking for register number 9 aka PC.
3330                        // if other register numbers are specified here, can you add from other
3331                        // control registers into a GPR?
3332                        return Err(DecodeError::InvalidOperand);
3333                    }
3334
3335                    let iiiiii = (inst >> 7) & 0b111111;
3336                    let ddddd = reg_b0(inst);
3337                    handler.on_opcode_decoded(Opcode::Add)?;
3338                    handler.on_source_decoded(Operand::cr(9))?;
3339                    handler.on_source_decoded(
3340                        Operand::immext(iiiiii, extender, |i| Ok(Operand::imm_u8(i as u8)) )?
3341                    )?;
3342                    handler.on_dest_decoded(Operand::gpr(ddddd))?;
3343                }
3344                o if o & 0b1111000 == 0b1011000 => {
3345                    let opc = (inst >> 20) & 0b1111;
3346                    let dd = (inst & 0b11) as u8;
3347                    let uu = ((inst >> 6) & 0b11) as u8;
3348                    let tt = ((inst >> 8) & 0b11) as u8;
3349                    let ss = ((inst >> 16) & 0b11) as u8;
3350                    let b13 = (inst >> 13) & 0b1;
3351
3352                    handler.on_dest_decoded(Operand::pred(dd))?;
3353
3354                    match opc {
3355                        0b0000 => {
3356                            if b13 == 0 {
3357                                handler.on_opcode_decoded(Opcode::And)?;
3358                                handler.on_source_decoded(Operand::pred(tt))?;
3359                                handler.on_source_decoded(Operand::pred(ss))?;
3360                            } else {
3361                                opcode_check!(inst & 0b10010000 == 0b10010000);
3362                                handler.on_opcode_decoded(Opcode::Fastcorner9)?;
3363                                handler.on_source_decoded(Operand::pred(ss))?;
3364                                handler.on_source_decoded(Operand::pred(tt))?;
3365                            }
3366                        },
3367                        0b0001 => {
3368                            if b13 == 0 {
3369                                handler.on_opcode_decoded(Opcode::AndAnd)?;
3370                                handler.on_source_decoded(Operand::pred(tt))?;
3371                                handler.on_source_decoded(Operand::pred(ss))?;
3372                                handler.on_source_decoded(Operand::pred(uu))?;
3373                            } else {
3374                                opcode_check!(inst & 0b10010000 == 0b10010000);
3375                                handler.on_opcode_decoded(Opcode::Fastcorner9)?;
3376                                handler.negate_result()?;
3377                                handler.on_source_decoded(Operand::pred(ss))?;
3378                                handler.on_source_decoded(Operand::pred(tt))?;
3379                            }
3380                        },
3381                        0b0010 => {
3382                            opcode_check!(b13 == 0);
3383                            handler.on_opcode_decoded(Opcode::Or)?;
3384                            handler.on_source_decoded(Operand::pred(tt))?;
3385                            handler.on_source_decoded(Operand::pred(ss))?;
3386                        },
3387                        0b0011 => {
3388                            opcode_check!(b13 == 0);
3389                            handler.on_opcode_decoded(Opcode::AndOr)?;
3390                            handler.on_source_decoded(Operand::pred(ss))?;
3391                            handler.on_source_decoded(Operand::pred(tt))?;
3392                            handler.on_source_decoded(Operand::pred(uu))?;
3393                        },
3394                        0b0100 => {
3395                            opcode_check!(b13 == 0);
3396                            handler.on_opcode_decoded(Opcode::Xor)?;
3397                            handler.on_source_decoded(Operand::pred(tt))?;
3398                            handler.on_source_decoded(Operand::pred(ss))?;
3399                        },
3400                        0b0101 => {
3401                            opcode_check!(b13 == 0);
3402                            handler.on_opcode_decoded(Opcode::OrAnd)?;
3403                            handler.on_source_decoded(Operand::pred(ss))?;
3404                            handler.on_source_decoded(Operand::pred(tt))?;
3405                            handler.on_source_decoded(Operand::pred(uu))?;
3406                        },
3407                        0b0110 => {
3408                            opcode_check!(b13 == 0);
3409                            handler.on_opcode_decoded(Opcode::AndNot)?;
3410                            handler.on_source_decoded(Operand::pred(tt))?;
3411                            handler.on_source_decoded(Operand::pred(ss))?;
3412                        },
3413                        0b0111 => {
3414                            opcode_check!(b13 == 0);
3415                            handler.on_opcode_decoded(Opcode::OrOr)?;
3416                            handler.on_source_decoded(Operand::pred(ss))?;
3417                            handler.on_source_decoded(Operand::pred(tt))?;
3418                            handler.on_source_decoded(Operand::pred(uu))?;
3419                        },
3420                        0b1000 => {
3421                            opcode_check!(b13 == 0);
3422                            handler.on_opcode_decoded(Opcode::Any8)?;
3423                            handler.on_source_decoded(Operand::pred(ss))?;
3424                        },
3425                        0b1001 => {
3426                            opcode_check!(b13 == 0);
3427                            handler.on_opcode_decoded(Opcode::AndAndNot)?;
3428                            handler.on_source_decoded(Operand::pred(ss))?;
3429                            handler.on_source_decoded(Operand::pred(tt))?;
3430                            handler.on_source_decoded(Operand::pred(uu))?;
3431                        },
3432                        0b1010 => {
3433                            opcode_check!(b13 == 0);
3434                            handler.on_opcode_decoded(Opcode::All8)?;
3435                            handler.on_source_decoded(Operand::pred(ss))?;
3436                        },
3437                        0b1011 => {
3438                            opcode_check!(b13 == 0);
3439                            handler.on_opcode_decoded(Opcode::AndOrNot)?;
3440                            handler.on_source_decoded(Operand::pred(ss))?;
3441                            handler.on_source_decoded(Operand::pred(tt))?;
3442                            handler.on_source_decoded(Operand::pred(uu))?;
3443                        },
3444                        0b1100 => {
3445                            opcode_check!(b13 == 0);
3446                            handler.on_opcode_decoded(Opcode::Not)?;
3447                            handler.on_source_decoded(Operand::pred(ss))?;
3448                        },
3449                        0b1101 => {
3450                            opcode_check!(b13 == 0);
3451                            handler.on_opcode_decoded(Opcode::OrAndNot)?;
3452                            handler.on_source_decoded(Operand::pred(ss))?;
3453                            handler.on_source_decoded(Operand::pred(tt))?;
3454                            handler.on_source_decoded(Operand::pred(uu))?;
3455                        },
3456                        0b1110 => {
3457                            opcode_check!(b13 == 0);
3458                            handler.on_opcode_decoded(Opcode::OrNot)?;
3459                            handler.on_source_decoded(Operand::pred(tt))?;
3460                            handler.on_source_decoded(Operand::pred(ss))?;
3461                        },
3462                        // 0b1111
3463                        _ => {
3464                            opcode_check!(b13 == 0);
3465                            handler.on_opcode_decoded(Opcode::OrOrNot)?;
3466                            handler.on_source_decoded(Operand::pred(ss))?;
3467                            handler.on_source_decoded(Operand::pred(tt))?;
3468                            handler.on_source_decoded(Operand::pred(uu))?;
3469                        },
3470                    }
3471                }
3472                0b1100000 => {
3473                    opcode_check!(inst & 0x2000 == 0);
3474                    let sssss = reg_b16(inst);
3475                    let ttttt = reg_b8(inst);
3476                    handler.on_opcode_decoded(Opcode::Tlbw)?;
3477                    handler.on_source_decoded(Operand::gprpair(sssss)?)?;
3478                    handler.on_source_decoded(Operand::gpr(ttttt))?;
3479                }
3480                0b1100010 => {
3481                    let sssss = reg_b16(inst);
3482                    let ddddd = reg_b0(inst);
3483                    handler.on_opcode_decoded(Opcode::Tlbr)?;
3484                    handler.on_source_decoded(Operand::gpr(sssss))?;
3485                    handler.on_dest_decoded(Operand::gprpair(ddddd)?)?;
3486                }
3487                0b1100100 => {
3488                    let sssss = reg_b16(inst);
3489                    let ddddd = reg_b0(inst);
3490                    handler.on_opcode_decoded(Opcode::Tlbp)?;
3491                    handler.on_source_decoded(Operand::gpr(sssss))?;
3492                    handler.on_dest_decoded(Operand::gpr(ddddd))?;
3493                }
3494                0b1100101 => {
3495                    let sssss = reg_b16(inst);
3496                    handler.on_opcode_decoded(Opcode::TlbInvAsid)?;
3497                    handler.on_source_decoded(Operand::gpr(sssss))?;
3498                }
3499                0b1100110 => {
3500                    opcode_check!(inst & 0x2000 == 0);
3501                    let sssss = reg_b16(inst);
3502                    let ttttt = reg_b8(inst);
3503                    let ddddd = reg_b0(inst);
3504                    handler.on_opcode_decoded(Opcode::Ctlbw)?;
3505                    handler.on_source_decoded(Operand::gprpair(sssss)?)?;
3506                    handler.on_source_decoded(Operand::gpr(ttttt))?;
3507                    handler.on_dest_decoded(Operand::gpr(ddddd))?;
3508                }
3509                0b1100111 => {
3510                    let sssss = reg_b16(inst);
3511                    let ddddd = reg_b0(inst);
3512                    handler.on_opcode_decoded(Opcode::Tlboc)?;
3513                    handler.on_source_decoded(Operand::gprpair(sssss)?)?;
3514                    handler.on_dest_decoded(Operand::gpr(ddddd))?;
3515                }
3516                0b1111111 => {
3517                    opcode_check!((inst >> 5) & 0b100000111 == 0b010);
3518                    let ddddd = reg_b0(inst);
3519                    let sssss = reg_b8(inst);
3520                    let ttttt = reg_b16(inst);
3521                    handler.on_opcode_decoded(Opcode::Movlen)?;
3522                    handler.on_dest_decoded(Operand::gpr(ddddd))?;
3523                    handler.on_source_decoded(Operand::gpr(sssss))?;
3524                    handler.on_source_decoded(Operand::gprpair(ttttt)?)?;
3525                }
3526                _ => {
3527                    opcode_check!(false);
3528                }
3529            }
3530        }
3531        0b0111 => {
3532            match reg_type {
3533            0b0000 => {
3534                static OPS: [Option<Opcode>; 8] = [
3535                    Some(Opcode::Aslh), Some(Opcode::Asrh), None, Some(Opcode::TransferRegister),
3536                    Some(Opcode::Zxtb), Some(Opcode::Sxtb), Some(Opcode::Zxth), Some(Opcode::Sxth),
3537                ];
3538
3539                let opcode = decode_opcode!(OPS[min_op as usize]);
3540
3541                let ddddd = reg_b0(inst);
3542                let sssss = reg_b16(inst);
3543                let predicated = (inst >> 13) & 1 != 0;
3544
3545                if opcode == Opcode::TransferRegister {
3546                    // no support for predicated register transfer..?
3547                    opcode_check!(!predicated);
3548                } else if opcode == Opcode::Zxtb {
3549                    // non-predicated zext is assembled as `Rd=and(Rs,#255)`
3550                    // really curious if hardware supports this instruction anyway...
3551                    opcode_check!(predicated);
3552                }
3553
3554                handler.on_opcode_decoded(opcode)?;
3555
3556                if predicated {
3557                    let pred_bits = (inst >> 10) & 0b11;
3558                    let negated = pred_bits >> 1 != 0;
3559                    let dotnew = pred_bits & 1 != 0;
3560                    let pred_number = (inst >> 8) & 0b11;
3561
3562                    handler.inst_predicated(pred_number as u8, negated, dotnew)?;
3563                }
3564
3565                handler.on_dest_decoded(Operand::Gpr { reg: ddddd })?;
3566                handler.on_source_decoded(Operand::Gpr { reg: sssss })?;
3567            }
3568            0b0001 => {
3569                opcode_check!(min_op & 1 == 1);
3570
3571                let i_high = ((inst >> 8) & 0xc000) as u16;
3572                let i_low = (inst & 0x3fff) as u16;
3573                let i = i_high | i_low;
3574                let xxxxx = reg_b16(inst);
3575
3576                handler.on_opcode_decoded(Opcode::TransferImmediate)?;
3577                handler.on_dest_decoded(Operand::GprLow { reg: xxxxx })?;
3578                handler.on_source_decoded(Operand::ImmU16 { imm: i })?;
3579            }
3580            0b0010 => {
3581                opcode_check!(min_op & 1 == 1);
3582
3583                let i_high = ((inst >> 8) & 0xc000) as u16;
3584                let i_low = (inst & 0x3fff) as u16;
3585                let i = i_high | i_low;
3586                let xxxxx = reg_b16(inst);
3587
3588                handler.on_opcode_decoded(Opcode::TransferImmediate)?;
3589                handler.on_dest_decoded(Operand::GprHigh { reg: xxxxx })?;
3590                handler.on_source_decoded(Operand::ImmU16 { imm: i })?;
3591            }
3592            0b0011 => {
3593                // in either case there is a #s8, but the exact operation is still TBD
3594                let i = ((inst >> 5) & 0xff) as i8;
3595
3596                if inst & 0x2000 != 0 {
3597                    let sssss = reg_b16(inst);
3598                    let ddddd = reg_b0(inst);
3599
3600                    let op = if min_op & 0b010 == 0 {
3601                        handler.on_dest_decoded(Operand::gprpair(ddddd)?)?;
3602                        Opcode::Combine
3603                    } else {
3604                        handler.on_dest_decoded(Operand::gpr(ddddd))?;
3605                        Opcode::CmpEq
3606                    };
3607                    handler.on_opcode_decoded(op)?;
3608
3609                    let min_low = min_op & 0b11;
3610
3611                    if min_low == 0b11 {
3612                        handler.negate_result()?;
3613                    }
3614
3615                    if min_low == 0b01 {
3616                        handler.on_source_decoded(
3617                            Operand::immext(
3618                                i as u32, extender,
3619                                |i: u32| Ok(Operand::imm_i8(i as i8))
3620                            )?
3621                        )?;
3622                        handler.on_source_decoded(Operand::gpr(sssss))?;
3623                    } else {
3624                        handler.on_source_decoded(Operand::gpr(sssss))?;
3625                        handler.on_source_decoded(
3626                            Operand::immext(
3627                                i as u32, extender,
3628                                |i: u32| Ok(Operand::imm_i8(i as i8))
3629                            )?
3630                        )?;
3631                    }
3632                } else {
3633                    let sssss = reg_b16(inst);
3634                    let ddddd = reg_b0(inst);
3635                    let uu = min_op as u8 & 0b11;
3636
3637                    handler.on_opcode_decoded(Opcode::Mux)?;
3638                    handler.on_dest_decoded(Operand::gpr(ddddd))?;
3639                    handler.on_source_decoded(Operand::pred(uu))?;
3640
3641                    let reg_first = min_op & 0b100 == 0;
3642
3643                    if reg_first {
3644                        handler.on_source_decoded(Operand::gpr(sssss))?;
3645                        handler.on_source_decoded(Operand::immext(i as u32, extender, |i| Ok(Operand::imm_i8(i as i8)))?)?;
3646                    } else {
3647                        handler.on_source_decoded(Operand::immext(i as u32, extender, |i| Ok(Operand::imm_i8(i as i8)))?)?;
3648                        handler.on_source_decoded(Operand::gpr(sssss))?;
3649                    }
3650                }
3651            }
3652            0b0100 => {
3653                let sssss = reg_b16(inst);
3654                let ddddd = reg_b0(inst);
3655
3656                handler.on_opcode_decoded(Opcode::Add)?;
3657
3658                let negated = (min_op >> 2) & 1 == 1;
3659                let pred_number = min_op & 0b11;
3660                let dotnew = inst >> 13 & 1 == 1;
3661                let i = ((inst >> 5) & 0xff) as i8;
3662
3663                handler.inst_predicated(pred_number as u8, negated, dotnew)?;
3664                handler.on_dest_decoded(Operand::gpr(ddddd))?;
3665                handler.on_source_decoded(Operand::gpr(sssss))?;
3666                handler.on_source_decoded(Operand::immext(i as u32, extender, |i| Ok(Operand::imm_i8(i as i8)))?)?;
3667            }
3668            0b0101 => {
3669                let sssss = reg_b16(inst);
3670                let ddddd = reg_b0(inst);
3671                let dd = ddddd & 0b11;
3672                operand_check!(ddddd & 0b01100 == 0);
3673
3674                let i_hi = ((min_op & 0b1) as i16) << 15 >> 6;
3675                let i_lo = ((inst >> 5) as i16) & 0b1_1111_1111;
3676                let i = i_lo | i_hi;
3677
3678                let op_bits = min_op >> 1;
3679
3680                static OPS: [Option<Opcode>; 4] = [
3681                    Some(Opcode::CmpEq), Some(Opcode::CmpGt),
3682                    Some(Opcode::CmpGtu), None,
3683                ];
3684
3685                let opcode = decode_opcode!(OPS[op_bits as usize]);
3686
3687                let negated = ddddd & 0b10000 != 0;
3688                if negated {
3689                    handler.negate_result()?;
3690                }
3691
3692                handler.on_opcode_decoded(opcode)?;
3693                handler.on_dest_decoded(Operand::pred(dd))?;
3694                handler.on_source_decoded(Operand::gpr(sssss))?;
3695                if opcode == Opcode::CmpGtu {
3696                    operand_check!(i >= 0);
3697                    handler.on_source_decoded(Operand::immext(i as u32, extender, |i| Ok(Operand::imm_u16(i as u16)))?)?;
3698                } else {
3699                    handler.on_source_decoded(Operand::immext(i as u32, extender, |i| Ok(Operand::imm_i16(i as i16)))?)?;
3700                }
3701            }
3702            0b0110 => {
3703                let sssss = reg_b16(inst);
3704                let ddddd = reg_b0(inst);
3705
3706                let i_hi = ((min_op & 0b1) as i16) << 15 >> 6;
3707                let i_lo = ((inst >> 5) as i16) & 0b1_1111_1111;
3708                let i = i_lo | i_hi;
3709
3710                let op_bits = min_op >> 1;
3711
3712                static OPS: [Option<Opcode>; 4] = [
3713                    Some(Opcode::And), Some(Opcode::Sub),
3714                    Some(Opcode::Or), None,
3715                ];
3716
3717                let opcode = decode_opcode!(OPS[op_bits as usize]);
3718
3719                handler.on_opcode_decoded(opcode)?;
3720                handler.on_dest_decoded(Operand::gpr(ddddd))?;
3721                if opcode == Opcode::Sub {
3722                    handler.on_source_decoded(
3723                        Operand::immext(
3724                            i as u32, extender,
3725                            |i: u32| Ok(Operand::imm_i16(i as i16))
3726                        )?
3727                    )?;
3728                    handler.on_source_decoded(Operand::gpr(sssss))?;
3729                } else {
3730                    handler.on_source_decoded(Operand::gpr(sssss))?;
3731                    handler.on_source_decoded(
3732                        Operand::immext(
3733                            i as u32, extender,
3734                            |i: u32| Ok(Operand::imm_i16(i as i16))
3735                        )?
3736                    )?;
3737                }
3738            }
3739            0b0111 => {
3740                return Err(DecodeError::InvalidOpcode);
3741            }
3742            0b1000 => {
3743                let ddddd = reg_b0(inst);
3744
3745                let i_hi = (min_op >> 1) as i16;
3746                let i_mid = reg_b16(inst) as i16;
3747                let i_lo = ((inst >> 5) as i16) & 0b1_1111_1111;
3748                let i = i_lo | (i_mid << 5) | (i_hi << 14);
3749
3750                handler.on_opcode_decoded(Opcode::TransferImmediate)?;
3751                handler.on_dest_decoded(Operand::gpr(ddddd))?;
3752                handler.on_source_decoded(
3753                    Operand::immext(
3754                        i as u32, extender,
3755                        |i: u32| Ok(Operand::imm_i16(i as i16))
3756                    )?
3757                )?;
3758            }
3759            0b1010 |
3760            0b1011 => {
3761                let ddddd = reg_b0(inst);
3762
3763                let i = (inst >> 5) as i8;
3764                let uu = (inst >> 23) & 0b11;
3765                let l_lo = ((inst >> 13) & 0b01) as i8;
3766                let l_hi = ((inst >> 16) & 0x7f) as i8;
3767                let l = l_lo | (l_hi << 1);
3768
3769                handler.on_opcode_decoded(Opcode::Mux)?;
3770                handler.on_dest_decoded(Operand::gpr(ddddd))?;
3771                handler.on_source_decoded(Operand::pred(uu as u8))?;
3772                handler.on_source_decoded(Operand::immext(i as u32, extender, |i| Ok(Operand::imm_i8(i as i8)))?)?;
3773                handler.on_source_decoded(Operand::imm_i8(l))?;
3774            }
3775            0b1100 => {
3776                let ddddd = reg_b0(inst);
3777
3778                let i = (inst >> 5) as i8;
3779                let l_lo = ((inst >> 13) & 0b01) as i8;
3780                let l_hi = ((inst >> 16) & 0x7f) as i8;
3781                let l = l_lo | (l_hi << 1);
3782
3783                handler.on_opcode_decoded(Opcode::Combine)?;
3784                handler.on_dest_decoded(Operand::gprpair(ddddd)?)?;
3785                if min_op & 0b100 == 0 {
3786                    handler.on_source_decoded(Operand::immext(i as u32, extender, |i| Ok(Operand::imm_i8(i as i8)))?)?;
3787                    handler.on_source_decoded(Operand::imm_i8(l))?;
3788                } else {
3789                    handler.on_source_decoded(Operand::imm_i8(i))?;
3790                    // TODO: technically more restrictive than the manual - these bits are
3791                    // dontcare, not 0
3792                    let l = l as u8;
3793                    operand_check!(l & 0xc0 == 0);
3794                    handler.on_source_decoded(Operand::immext(l as u32, extender, |l| Ok(Operand::imm_u8(l as u8)))?)?;
3795                }
3796            }
3797            0b1101 => {
3798                return Err(DecodeError::InvalidOpcode);
3799            }
3800            0b1110 => {
3801                let iiii = reg_b16(inst) as i16;
3802                operand_check!(iiii & 0b1_0000 == 0);
3803
3804                let ddddd = reg_b0(inst);
3805
3806                handler.on_opcode_decoded(Opcode::TransferImmediate)?;
3807
3808                let negated = (min_op >> 2) & 1 == 1;
3809                let pred_number = min_op & 0b11;
3810                let dotnew = inst >> 13 & 1 == 1;
3811
3812                let i_lo = ((inst >> 5) & 0xff) as i16;
3813                let i_hi = iiii << 12 >> 4 as i16;
3814                let i = i_lo | i_hi;
3815
3816                handler.inst_predicated(pred_number as u8, negated, dotnew)?;
3817                handler.on_dest_decoded(Operand::gpr(ddddd))?;
3818                handler.on_source_decoded(Operand::immext(i as u32, extender, |i| Ok(Operand::imm_i16(i as i16)))?)?;
3819            }
3820            0b1111 => {
3821                // 0b0111_1111_...
3822                handler.on_opcode_decoded(Opcode::Nop)?;
3823            }
3824            _ => {
3825                // anything left unhandled is invalid..
3826                opcode_check!(false);
3827            }
3828            }
3829        }
3830        0b1000 => {
3831            let ddddd = reg_b0(inst);
3832            let iiiiii = ((inst >> 8) & 0b111111) as u8;
3833            let sssss = reg_b16(inst);
3834
3835            let majbits = (inst >> 24) & 0b1111;
3836            let minbits = (inst >> 21) & 0b111;
3837            let op_low = (inst >> 5) & 0b111;
3838
3839            match majbits {
3840                0b0000 => {
3841                    handler.on_source_decoded(Operand::gprpair(sssss)?)?;
3842                    handler.on_dest_decoded(Operand::gprpair(ddddd)?)?;
3843                    match minbits {
3844                        0b000 => {
3845                            static OPS: [Opcode; 8] = [
3846                                Asr, Lsr, Asl, Rol,
3847                                Vsathub, Vsatwuh, Vsatwh, Vsathb,
3848                            ];
3849                            handler.on_opcode_decoded(OPS[op_low as usize])?;
3850                            if op_low < 0b100 {
3851                                handler.on_source_decoded(Operand::imm_u8(iiiiii))?;
3852                            }
3853                        }
3854                        0b001 => {
3855                            opcode_check!(inst & 0x00e0 == 0);
3856                            operand_check!(inst & 0x3000 == 0);
3857                            handler.on_source_decoded(Operand::imm_u8(iiiiii))?;
3858                            handler.on_opcode_decoded(Opcode::Vasrh)?;
3859                            handler.rounded(RoundingMode::Raw)?;
3860                        }
3861                        0b010 => {
3862                            static OPS: [Option<Opcode>; 8] = [
3863                                Some(Vasrw), Some(Vlsrw), Some(Vaslw), None,
3864                                Some(Vabsh), Some(Vabsh), Some(Vabsw), Some(Vabsw),
3865                            ];
3866                            handler.on_opcode_decoded(decode_opcode!(OPS[op_low as usize]))?;
3867                            if op_low < 0b100 {
3868                                operand_check!(inst & 0x2000 == 0);
3869                                handler.on_source_decoded(Operand::imm_u8(iiiiii))?;
3870                            } else {
3871                                if op_low & 1 == 1 {
3872                                    handler.saturate()?;
3873                                }
3874                            }
3875                        }
3876                        0b011 |
3877                        0b101 => {
3878                            return Err(DecodeError::InvalidOpcode);
3879                        }
3880                        0b100 => {
3881                            static OPS: [Option<Opcode>; 8] = [
3882                                Some(Vasrh), Some(Vlsrh), Some(Vaslh), None,
3883                                Some(Not), Some(Neg), Some(Abs), Some(Vconj),
3884                            ];
3885                            handler.on_opcode_decoded(decode_opcode!(OPS[op_low as usize]))?;
3886                            if op_low < 0b100 {
3887                                operand_check!(inst & 0x3000 == 0);
3888                                handler.on_source_decoded(Operand::imm_u8(iiiiii))?;
3889                            } else {
3890                                if op_low == 0b111 {
3891                                    handler.saturate()?;
3892                                }
3893                            }
3894                        },
3895                        0b110 => {
3896                            static OPS: [Option<Opcode>; 8] = [
3897                                None, None, None, None,
3898                                Some(Deinterleave), Some(Interleave), Some(Brev), Some(Asr),
3899                            ];
3900                            handler.on_opcode_decoded(decode_opcode!(OPS[op_low as usize]))?;
3901                            if op_low == 0b111 {
3902                                handler.rounded(RoundingMode::Round)?;
3903                                handler.on_source_decoded(Operand::imm_u8(iiiiii))?;
3904                            }
3905                        }
3906                        other => {
3907                            debug_assert!(other == 0b111);
3908
3909                            static OPS: [Option<Opcode>; 8] = [
3910                                Some(ConvertDf2D), Some(ConvertDf2Ud), Some(ConvertUd2Df), Some(ConvertD2Df),
3911                                None, None, Some(ConvertDf2D), Some(ConvertDf2Ud),
3912                            ];
3913                            handler.on_opcode_decoded(decode_opcode!(OPS[op_low as usize]))?;
3914                            opcode_check!(inst & 0x2000 == 0);
3915                            if op_low >= 0b100 {
3916                                handler.chop()?;
3917                            }
3918                        }
3919                    }
3920                },
3921                0b0001 => {
3922                    handler.on_source_decoded(Operand::gprpair(sssss)?)?;
3923                    handler.on_dest_decoded(Operand::gprpair(ddddd)?)?;
3924                    handler.on_opcode_decoded(Opcode::Extractu)?;
3925                    handler.on_source_decoded(Operand::imm_u8(iiiiii))?;
3926
3927                    let l_low = ((inst >> 5) & 0b111) as u8;
3928                    let l_high = ((inst >> 21) & 0b111) as u8;
3929                    let llllll = (l_high << 3) | l_low;
3930                    handler.on_source_decoded(Operand::imm_u8(llllll))?;
3931                }
3932                0b0010 => {
3933                    let opc_hi = (inst >> 22) & 0b11;
3934                    let opc_lo = (inst >> 5) & 0b111;
3935                    let opc = (opc_hi << 3) | opc_lo;
3936
3937                    let assign_mode_bits = opc >> 2;
3938                    let shift_op_bits = opc & 0b11;
3939
3940                    let assign_mode = match assign_mode_bits {
3941                        0b000 => AssignMode::SubAssign,
3942                        0b001 => AssignMode::AddAssign,
3943                        0b010 => AssignMode::AndAssign,
3944                        0b011 => AssignMode::OrAssign,
3945                        0b100 => AssignMode::XorAssign,
3946                        _ => {
3947                            return Err(DecodeError::InvalidOpcode);
3948                        }
3949                    };
3950                    let opc = match shift_op_bits {
3951                        0b00 => Opcode::Asr,
3952                        0b01 => Opcode::Lsr,
3953                        0b10 => Opcode::Asl,
3954                        _ => Opcode::Rol,
3955                    };
3956                    let sssss = reg_b16(inst);
3957                    let xxxxx = reg_b0(inst);
3958                    let u6 = ((inst >> 8) & 0b11_1111) as u8;
3959                    handler.assign_mode(assign_mode)?;
3960                    handler.on_opcode_decoded(opc)?;
3961                    handler.on_dest_decoded(Operand::gprpair(xxxxx)?)?;
3962                    handler.on_source_decoded(Operand::gprpair(sssss)?)?;
3963                    handler.on_source_decoded(Operand::imm_u8(u6))?;
3964                }
3965                0b0011 => {
3966                    let xxxxx = reg_b0(inst);
3967                    let sssss = reg_b16(inst);
3968
3969                    // TODO: it's not clear which immediate is the #u6 versus #U6
3970                    // they may be backwards in the decoding..
3971                    handler.on_dest_decoded(Operand::gprpair(xxxxx)?)?;
3972                    handler.on_source_decoded(Operand::gprpair(sssss)?)?;
3973                    handler.on_opcode_decoded(Opcode::Insert)?;
3974
3975                    let iiiiii = (inst >> 8) & 0b111111;
3976                    let l_lo = (inst >> 5) & 0b111;
3977                    let l_hi = (inst >> 21) & 0b111;
3978                    let llllll = l_lo | (l_hi << 3);
3979
3980                    handler.on_source_decoded(Operand::imm_u8(iiiiii as u8))?;
3981                    handler.on_source_decoded(Operand::imm_u8(llllll as u8))?;
3982                }
3983                0b0100 => {
3984                    let ddddd = reg_b0(inst);
3985                    let sssss = reg_b16(inst);
3986
3987                    handler.on_dest_decoded(Operand::gprpair(ddddd)?)?;
3988                    handler.on_source_decoded(Operand::gpr(sssss))?;
3989
3990                    let opc_lo = (inst >> 5) & 0b111;
3991                    let opc_hi = (inst >> 21) & 0b111;
3992
3993                    if opc_hi >= 0b100 {
3994                        // convert...
3995                        static CONVERT_OPS: [Option<(Opcode, bool)>; 8] = [
3996                            Some((ConvertSf2Df, false)), Some((ConvertUw2Df, false)),
3997                            Some((ConvertW2Df, false)), Some((ConvertSf2Ud, true)),
3998                            Some((ConvertSf2D, true)), Some((ConvertSf2Ud, true)),
3999                            Some((ConvertSf2D, true)), None,
4000                        ];
4001                        let (opc, check_b13_zero) = decode_opcode!(CONVERT_OPS[opc_lo as usize]);
4002                        opcode_check!(!check_b13_zero || (inst & 0b0010_0000_0000_0000) == 0);
4003                        handler.on_opcode_decoded(opc)?;
4004
4005                        if opc_lo > 0b100 {
4006                            handler.chop()?;
4007                        }
4008                    } else if opc_hi >= 0b010 {
4009                        // vsplat
4010                        if opc_lo == 0b010 || opc_lo == 0b011 {
4011                            handler.on_opcode_decoded(Opcode::Vsplath)?;
4012                        } else if opc_lo == 0b100 || opc_lo == 0b101 {
4013                            handler.on_opcode_decoded(Opcode::Vsplatb)?;
4014                        } else {
4015                            return Err(DecodeError::InvalidOpcode);
4016                        }
4017                    } else {
4018                        static EXT_OPS: [Opcode; 4] = [
4019                            Vsxtbh, Vzxtbh, Vsxthw, Vzxthw
4020                        ];
4021                        handler.on_opcode_decoded(EXT_OPS[(opc_lo >> 1) as usize])?;
4022                    }
4023                }
4024                0b0101 => {
4025                    let opc_hi = (inst >> 21) & 0b111;
4026                    let i6 = (inst >> 8) & 0b111111;
4027                    let dd = (inst & 0b11) as u8;
4028                    let sssss = reg_b16(inst);
4029
4030                    handler.on_dest_decoded(Operand::pred(dd as u8))?;
4031                    handler.on_source_decoded(Operand::gpr(sssss))?;
4032
4033                    match opc_hi {
4034                        0b000 => {
4035                            handler.on_opcode_decoded(Opcode::Tstbit)?;
4036                            operand_check!(i6 & 0b10_0000 == 0);
4037                            handler.on_source_decoded(Operand::imm_u8(i6 as u8))?;
4038                        }
4039                        0b001 => {
4040                            handler.on_opcode_decoded(Opcode::Tstbit)?;
4041                            operand_check!(i6 & 0b10_0000 == 0);
4042                            handler.on_source_decoded(Operand::imm_u8(i6 as u8))?;
4043                            handler.negate_result()?;
4044                        }
4045                        0b010 => {
4046                            handler.on_opcode_decoded(Opcode::TransferRegister)?;
4047                        }
4048                        0b100 => {
4049                            handler.on_opcode_decoded(Opcode::Bitsclr)?;
4050                            handler.on_source_decoded(Operand::imm_u8(i6 as u8))?;
4051                        }
4052                        0b101 => {
4053                            handler.on_opcode_decoded(Opcode::Bitsclr)?;
4054                            handler.on_source_decoded(Operand::imm_u8(i6 as u8))?;
4055                            handler.negate_result()?;
4056                        }
4057                        0b111 => {
4058                            handler.on_opcode_decoded(Opcode::SfClass)?;
4059                            operand_check!(i6 & 0b10_0000 == 0);
4060                            handler.on_source_decoded(Operand::imm_u8(i6 as u8))?;
4061                        }
4062                        _ => {
4063                            return Err(DecodeError::InvalidOpcode);
4064                        }
4065                    }
4066                }
4067                0b0110 => {
4068                    handler.on_opcode_decoded(Opcode::Mask)?;
4069                    handler.on_dest_decoded(Operand::gprpair(reg_b0(inst))?)?;
4070                    handler.on_source_decoded(Operand::pred(reg_b8(inst) & 0b11))?;
4071                }
4072                0b0111 => {
4073                    let l6 = (inst >> 8) & 0b111111;
4074                    let l6 = ((l6 as i8) << 2) >> 2;
4075                    let i3 = (inst >> 5) & 0b111;
4076                    let i_hi = (inst >> 21) & 0b1;
4077                    let i4 = (i_hi << 3) | i3;
4078                    let opc = (inst >> 22) & 0b11;
4079                    static TABLEIDX_OPS: [Opcode; 4] = [
4080                        Opcode::Tableidxb, Opcode::Tableidxh,
4081                        Opcode::Tableidxw, Opcode::Tableidxd
4082                    ];
4083
4084                    handler.on_opcode_decoded(TABLEIDX_OPS[opc as usize])?;
4085                    handler.on_dest_decoded(Operand::gpr(reg_b0(inst)))?;
4086                    handler.on_source_decoded(Operand::gpr(reg_b16(inst)))?;
4087                    handler.on_source_decoded(Operand::imm_u8(i4 as u8))?;
4088                    handler.on_source_decoded(Operand::imm_i8(l6))?;
4089                    handler.rounded(RoundingMode::Raw)?;
4090                }
4091                0b1000 => {
4092                    // 1000|1000...
4093                    let ddddd = reg_b0(inst);
4094                    let sssss = reg_b16(inst);
4095                    let opc_lo = (inst >> 5) & 0b111;
4096                    let opc_hi = (inst >> 21) & 0b111;
4097                    let opc = opc_lo | (opc_hi << 3);
4098
4099                    static OPCODES: [Option<Opcode>; 64] = [
4100                        // 000
4101                        Some(Vsathub), Some(ConvertDf2Sf), Some(Vsatwh), None, Some(Vsatwuh), None, Some(Vsathb), None,
4102                        // 001
4103                        None, Some(ConvertUd2Sf), None, None, None, None, None, None,
4104                        // 010
4105                        Some(Clb), Some(ConvertD2Sf), Some(Cl0), None, Some(Cl1), None, None, None,
4106                        // 011
4107                        Some(Normamt), Some(ConvertSf2Ud), Some(AddClb), Some(Popcount), Some(Vasrhub), Some(Vasrhub), None, None,
4108                        // 100
4109                        Some(Vtrunohb), Some(ConvertSf2D), Some(Vtrunehb), None, Some(Vrndwh), None, Some(Vrndwh), None,
4110                        // 101
4111                        None, Some(ConvertSf2Ud), None, None, None, None, None, None,
4112                        // 110
4113                        Some(Sat), Some(Round), Some(Vasrw), None, Some(Bitsplit), Some(Clip), Some(Vclip), None,
4114                        // 111
4115                        None, Some(ConvertSf2D), Some(Ct0), None, Some(Ct1), None, None, None,
4116                    ];
4117
4118                    let op = decode_opcode!(OPCODES[opc as usize]);
4119                    handler.on_opcode_decoded(op)?;
4120
4121                    let i6 = (inst >> 8) & 0b111111;
4122
4123                    match opc {
4124                        0b100110 |
4125                        0b110001 => {
4126                            operand_check!(i6 < 0b100000);
4127                            handler.on_dest_decoded(Operand::gpr(ddddd))?;
4128                            handler.on_source_decoded(Operand::gprpair(sssss)?)?;
4129                            handler.saturate()?;
4130                        }
4131                        0b110101 => {
4132                            operand_check!(i6 < 0b100000);
4133                            handler.on_dest_decoded(Operand::gpr(ddddd))?;
4134                            handler.on_source_decoded(Operand::gpr(sssss))?;
4135                            handler.on_source_decoded(Operand::imm_u8(i6 as u8))?;
4136                        }
4137                        0b110110 => {
4138                            operand_check!(i6 < 0b100000);
4139                            handler.on_dest_decoded(Operand::gprpair(ddddd)?)?;
4140                            handler.on_source_decoded(Operand::gprpair(sssss)?)?;
4141                            handler.on_source_decoded(Operand::imm_u8(i6 as u8))?;
4142                        }
4143                        0b110010 => {
4144                            operand_check!(i6 < 0b100000);
4145                            handler.on_dest_decoded(Operand::gpr(ddddd))?;
4146                            handler.on_source_decoded(Operand::gprpair(sssss)?)?;
4147                            let i6 = (i6 as i8) << 3 >> 3;
4148                            handler.on_source_decoded(Operand::imm_i8(i6))?;
4149                        }
4150                        0b011001 => {
4151                            operand_check!(i6 < 0b100000);
4152                            handler.on_dest_decoded(Operand::gprpair(ddddd)?)?;
4153                            handler.on_source_decoded(Operand::gpr(sssss))?;
4154                        }
4155                        0b011010 => {
4156                            handler.on_dest_decoded(Operand::gpr(ddddd))?;
4157                            handler.on_source_decoded(Operand::gprpair(sssss)?)?;
4158                            handler.on_source_decoded(Operand::imm_i8((i6 as i8) << 2 >> 2))?;
4159                        }
4160                        0b011100 => {
4161                            operand_check!(i6 < 0b10000);
4162                            handler.rounded(RoundingMode::Raw)?;
4163                            handler.on_dest_decoded(Operand::gpr(ddddd))?;
4164                            handler.on_source_decoded(Operand::gprpair(sssss)?)?;
4165                            handler.on_source_decoded(Operand::imm_u8(i6 as u8))?;
4166                        }
4167                        0b011101 => {
4168                            operand_check!(i6 < 0b10000);
4169                            handler.saturate()?;
4170                            handler.on_dest_decoded(Operand::gpr(ddddd))?;
4171                            handler.on_source_decoded(Operand::gprpair(sssss)?)?;
4172                            handler.on_source_decoded(Operand::imm_u8(i6 as u8))?;
4173                        }
4174                        0b110100 => {
4175                            operand_check!(i6 < 0b10000);
4176                            handler.on_dest_decoded(Operand::gprpair(ddddd)?)?;
4177                            handler.on_source_decoded(Operand::gpr(sssss))?;
4178                            handler.on_source_decoded(Operand::imm_u8(i6 as u8))?;
4179                        }
4180                        0b100001 => {
4181                            handler.on_dest_decoded(Operand::gprpair(ddddd)?)?;
4182                            handler.on_source_decoded(Operand::gpr(sssss))?;
4183                        }
4184                        0b101001 |
4185                        0b111001 => {
4186                            operand_check!(i6 & 0b10_0000 == 0);
4187                            handler.on_dest_decoded(Operand::gprpair(ddddd)?)?;
4188                            handler.on_source_decoded(Operand::gpr(sssss))?;
4189                            handler.chop()?;
4190                        }
4191                        _ => {
4192                            handler.on_dest_decoded(Operand::gpr(ddddd))?;
4193                            handler.on_source_decoded(Operand::gprpair(sssss)?)?;
4194                        }
4195                    }
4196                }
4197                0b1001 => {
4198                    // 1000|1001...
4199                    let opc_hi = (inst >> 21) & 0b111;
4200
4201                    let ddddd = reg_b0(inst);
4202                    let tt = reg_b8(inst) & 0b11;
4203                    let ss = reg_b16(inst) & 0b11;
4204
4205                    if opc_hi & 0b011 == 0b000 {
4206                        // vitpack
4207                        handler.on_dest_decoded(Operand::gpr(ddddd))?;
4208                        handler.on_source_decoded(Operand::pred(ss))?;
4209                        handler.on_source_decoded(Operand::pred(tt))?;
4210                        handler.on_opcode_decoded(Opcode::Vitpack)?;
4211                    } else if opc_hi & 0b010 == 0b010 {
4212                        // mov?
4213                        handler.on_dest_decoded(Operand::gpr(ddddd))?;
4214                        handler.on_source_decoded(Operand::pred(ss))?;
4215                        handler.on_opcode_decoded(Opcode::TransferRegister)?;
4216                    } else {
4217                        return Err(DecodeError::InvalidOpcode);
4218                    }
4219                }
4220                0b1010 => {
4221                    // 1000|1010...
4222                    let ddddd = reg_b0(inst);
4223                    let sssss = reg_b16(inst);
4224                    let l_lo = (inst >> 5) & 0b111;
4225                    let l_hi = (inst >> 21) & 0b111;
4226                    let l6 = l_lo | (l_hi << 3);
4227                    let i6 = (inst >> 8) & 0b111111;
4228
4229                    handler.on_opcode_decoded(Extract)?;
4230                    handler.on_dest_decoded(Operand::gprpair(ddddd)?)?;
4231                    handler.on_source_decoded(Operand::gprpair(sssss)?)?;
4232                    handler.on_source_decoded(Operand::imm_u8(i6 as u8))?;
4233                    handler.on_source_decoded(Operand::imm_u8(l6 as u8))?;
4234                }
4235                0b1011 => {
4236                    // 1000|1011...
4237                    let ddddd = reg_b0(inst);
4238                    let sssss = reg_b16(inst);
4239                    let op_lo = ((inst >> 5) & 0b111) as u8;
4240                    let op_hi = ((inst >> 21) & 0b111) as u8;
4241                    let i6 = (inst >> 8) & 0b111111;
4242
4243                    handler.on_dest_decoded(Operand::gpr(ddddd))?;
4244                    handler.on_source_decoded(Operand::gpr(sssss))?;
4245
4246                    match (op_hi, op_lo) {
4247                        (0b001, 0b000) => {
4248                            handler.on_opcode_decoded(Opcode::ConvertUw2Sf)?;
4249                        }
4250                        (0b010, 0b000) => {
4251                            handler.on_opcode_decoded(Opcode::ConvertW2Sf)?;
4252                        }
4253                        (0b011, 0b000) => {
4254                            operand_check!(i6 & 0b10_0000 == 0);
4255                            handler.on_opcode_decoded(Opcode::ConvertSf2Uw)?;
4256                        }
4257                        (0b011, 0b001) => {
4258                            operand_check!(i6 & 0b10_0000 == 0);
4259                            handler.on_opcode_decoded(Opcode::ConvertSf2Uw)?;
4260                            handler.chop()?;
4261                        }
4262                        (0b100, 0b010) => {
4263                            operand_check!(i6 & 0b10_0000 == 0);
4264                            handler.on_opcode_decoded(Opcode::ConvertSf2W)?;
4265                        }
4266                        (0b100, 0b011) => {
4267                            operand_check!(i6 & 0b10_0000 == 0);
4268                            handler.on_opcode_decoded(Opcode::ConvertSf2W)?;
4269                            handler.chop()?;
4270                        }
4271                        (0b101, 0b000) => {
4272                            handler.on_opcode_decoded(Opcode::SfFixupr)?;
4273                        }
4274                        (0b111, low) => {
4275                            operand_check!(low & 0b100 == 0);
4276                            let ee = (low & 0b11) as u8;
4277                            handler.on_opcode_decoded(Opcode::SfInvsqrta)?;
4278                            handler.on_dest_decoded(Operand::pred(ee))?;
4279                        }
4280                        _ => {
4281                            return Err(DecodeError::InvalidOpcode);
4282                        }
4283                    }
4284                }
4285                0b1100 => {
4286                    let opc_lo = (inst >> 5) & 0b111;
4287                    let opc_hi = (inst >> 21) & 0b111;
4288                    let opc = opc_lo | (opc_hi << 3);
4289                    let ddddd = reg_b0(inst);
4290                    let sssss = reg_b16(inst);
4291                    let i6 = ((inst >> 8) & 0b11_1111) as u8;
4292
4293                    if opc & 0b111110 == 0b111010 {
4294                        handler.on_dest_decoded(Operand::gprpair(ddddd)?)?;
4295                        handler.on_source_decoded(Operand::gprpair(sssss)?)?;
4296                    } else {
4297                        handler.on_dest_decoded(Operand::gpr(ddddd))?;
4298                        handler.on_source_decoded(Operand::gpr(sssss))?;
4299                    }
4300
4301                    match opc {
4302                        0b000_000 => {
4303                            operand_check!(i6 & 0b10_0000 == 0);
4304                            handler.on_opcode_decoded(Opcode::Asr)?;
4305                            handler.on_source_decoded(Operand::imm_u8(i6))?;
4306                        }
4307                        0b000_001 => {
4308                            operand_check!(i6 & 0b10_0000 == 0);
4309                            handler.on_opcode_decoded(Opcode::Lsr)?;
4310                            handler.on_source_decoded(Operand::imm_u8(i6))?;
4311                        }
4312                        0b000_010 => {
4313                            operand_check!(i6 & 0b10_0000 == 0);
4314                            handler.on_opcode_decoded(Opcode::Asl)?;
4315                            handler.on_source_decoded(Operand::imm_u8(i6))?;
4316                        }
4317                        0b000_011 => {
4318                            operand_check!(i6 & 0b10_0000 == 0);
4319                            handler.on_opcode_decoded(Opcode::Rol)?;
4320                            handler.on_source_decoded(Operand::imm_u8(i6))?;
4321                        }
4322                        0b000_100 => {
4323                            handler.on_opcode_decoded(Opcode::Clb)?;
4324                        }
4325                        0b000_101 => {
4326                            handler.on_opcode_decoded(Opcode::Cl0)?;
4327                        }
4328                        0b000_110 => {
4329                            handler.on_opcode_decoded(Opcode::Cl1)?;
4330                        }
4331                        0b000_111 => {
4332                            handler.on_opcode_decoded(Opcode::Normamt)?;
4333                        }
4334                        0b001_000 => {
4335                            handler.on_opcode_decoded(Opcode::AddClb)?;
4336                            handler.on_source_decoded(Operand::imm_i8((i6 as i8) << 2 >> 2))?;
4337                        }
4338                        0b010_000 => {
4339                            operand_check!(i6 & 0b10_0000 == 0);
4340                            handler.on_opcode_decoded(Opcode::Asr)?;
4341                            handler.on_source_decoded(Operand::imm_u8(i6))?;
4342                            handler.rounded(RoundingMode::Round)?;
4343                        }
4344                        0b010_010 => {
4345                            operand_check!(i6 & 0b10_0000 == 0);
4346                            handler.on_opcode_decoded(Opcode::Asl)?;
4347                            handler.on_source_decoded(Operand::imm_u8(i6))?;
4348                            handler.saturate()?;
4349                        }
4350                        0b010_100 => {
4351                            handler.on_opcode_decoded(Opcode::Ct0)?;
4352                        }
4353                        0b010_101 => {
4354                            handler.on_opcode_decoded(Opcode::Ct1)?;
4355                        }
4356                        0b010_110 => {
4357                            handler.on_opcode_decoded(Opcode::Brev)?;
4358                        }
4359                        0b010_111 => {
4360                            handler.on_opcode_decoded(Opcode::Vsplatb)?;
4361                        }
4362                        _ if opc & 0b110_110 == 0b100_000 => {
4363                            handler.on_opcode_decoded(Opcode::Vsathb)?;
4364                        }
4365                        _ if opc & 0b110_110 == 0b100_010 => {
4366                            handler.on_opcode_decoded(Opcode::Vsathub)?;
4367                        }
4368                        0b100_100 => {
4369                            handler.on_opcode_decoded(Opcode::Abs)?;
4370                        }
4371                        0b100_101 => {
4372                            handler.on_opcode_decoded(Opcode::Abs)?;
4373                            handler.saturate()?;
4374                        }
4375                        0b100_110 => {
4376                            handler.on_opcode_decoded(Opcode::Neg)?;
4377                            handler.saturate()?;
4378                        }
4379                        0b100_111 => {
4380                            handler.on_opcode_decoded(Opcode::Swiz)?;
4381                        }
4382                        0b110_000 => {
4383                            operand_check!(i6 & 0b10_0000 == 0);
4384                            handler.on_opcode_decoded(Opcode::Setbit)?;
4385                            handler.on_source_decoded(Operand::imm_u8(i6))?;
4386                        }
4387                        0b110_001 => {
4388                            operand_check!(i6 & 0b10_0000 == 0);
4389                            handler.on_opcode_decoded(Opcode::Clrbit)?;
4390                            handler.on_source_decoded(Operand::imm_u8(i6))?;
4391                        }
4392                        0b110_010 => {
4393                            operand_check!(i6 & 0b10_0000 == 0);
4394                            handler.on_opcode_decoded(Opcode::Togglebit)?;
4395                            handler.on_source_decoded(Operand::imm_u8(i6))?;
4396                        }
4397                        0b110_100 => {
4398                            handler.on_opcode_decoded(Opcode::Sath)?;
4399                        }
4400                        0b110_101 => {
4401                            handler.on_opcode_decoded(Opcode::Satuh)?;
4402                        }
4403                        0b110_110 => {
4404                            handler.on_opcode_decoded(Opcode::Satub)?;
4405                        }
4406                        0b110_111 => {
4407                            handler.on_opcode_decoded(Opcode::Satb)?;
4408                        }
4409                        0b111_000 | 0b111_001 => {
4410                            operand_check!(i6 & 0b10_0000 == 0);
4411                            handler.on_opcode_decoded(Opcode::Cround)?;
4412                            handler.on_source_decoded(Operand::imm_u8(i6))?;
4413                        }
4414                        0b111_010 | 0b111_011 => {
4415                            operand_check!(i6 & 0b10_0000 == 0);
4416                            handler.on_opcode_decoded(Opcode::Cround)?;
4417                            handler.on_source_decoded(Operand::imm_u8(i6))?;
4418                        }
4419                        0b111_100 | 0b111_101 => {
4420                            operand_check!(i6 & 0b10_0000 == 0);
4421                            handler.on_opcode_decoded(Opcode::Round)?;
4422                            handler.on_source_decoded(Operand::imm_u8(i6))?;
4423                        }
4424                        0b111_110 | 0b111_111 => {
4425                            operand_check!(i6 & 0b10_0000 == 0);
4426                            handler.on_opcode_decoded(Opcode::Round)?;
4427                            handler.saturate()?;
4428                            handler.on_source_decoded(Operand::imm_u8(i6))?;
4429                        }
4430                        _ => {
4431                            return Err(DecodeError::InvalidOpcode);
4432                        }
4433                    }
4434                }
4435                0b1101 => {
4436                    let ddddd = reg_b0(inst);
4437                    let sssss = reg_b16(inst);
4438                    let iiiii = reg_b8(inst);
4439                    let lll = (inst >> 5) & 0b111;
4440                    let ll = (inst >> 21) & 0b11;
4441                    let lllll = (lll | (ll << 3)) as u8;
4442                    let opc_lo = (inst >> 13) & 1;
4443                    let opc_hi = (inst >> 23) & 1;
4444                    let opc = opc_lo | (opc_hi << 1);
4445
4446                    handler.on_dest_decoded(Operand::gpr(ddddd))?;
4447
4448                    match opc {
4449                        0b00 => {
4450                            handler.on_opcode_decoded(Opcode::Extractu)?;
4451                            handler.on_source_decoded(Operand::gpr(sssss))?;
4452                        }
4453                        0b01 => {
4454                            handler.on_opcode_decoded(Opcode::Mask)?;
4455                        }
4456                        0b10 => {
4457                            handler.on_opcode_decoded(Opcode::Extract)?;
4458                            handler.on_source_decoded(Operand::gpr(sssss))?;
4459                        }
4460                        _ => {
4461                            return Err(DecodeError::InvalidOpcode);
4462                        }
4463                    }
4464
4465                    handler.on_source_decoded(Operand::imm_u8(iiiii))?;
4466                    handler.on_source_decoded(Operand::imm_u8(lllll))?;
4467                }
4468                0b1110 => {
4469                    let opc_hi = (inst >> 22) & 0b11;
4470                    let opc_lo = (inst >> 5) & 0b111;
4471                    let opc = (opc_hi << 3) | opc_lo;
4472                    let sssss = reg_b16(inst);
4473                    let xxxxx = reg_b0(inst);
4474                    let iiiiii = ((inst >> 8) & 0b111111) as u8;
4475
4476                    let assign_mode_bits = (opc >> 2) & 0b111;
4477                    let shift_op_bits = opc & 0b11;
4478
4479                    let assign_mode = match assign_mode_bits {
4480                        0b000 => AssignMode::SubAssign,
4481                        0b001 => AssignMode::AddAssign,
4482                        0b010 => AssignMode::AndAssign,
4483                        0b011 => AssignMode::OrAssign,
4484                        0b100 => AssignMode::XorAssign,
4485                        _ => {
4486                            return Err(DecodeError::InvalidOpcode);
4487                        }
4488                    };
4489                    let opc = match shift_op_bits {
4490                        0b00 => Opcode::Asr,
4491                        0b01 => Opcode::Lsr,
4492                        0b10 => Opcode::Asl,
4493                        _ => Opcode::Rol,
4494                    };
4495                    handler.on_opcode_decoded(opc)?;
4496                    handler.assign_mode(assign_mode)?;
4497
4498                    if assign_mode_bits < 0b010 {
4499                        handler.on_dest_decoded(Operand::gprpair(xxxxx)?)?;
4500                        handler.on_source_decoded(Operand::gprpair(sssss)?)?;
4501                        handler.on_source_decoded(Operand::imm_u8(iiiiii))?;
4502                    } else {
4503                        operand_check!(iiiiii & 0b10_0000 == 0);
4504                        handler.on_dest_decoded(Operand::gpr(xxxxx))?;
4505                        handler.on_source_decoded(Operand::gpr(sssss))?;
4506                        handler.on_source_decoded(Operand::imm_u8(iiiiii))?;
4507                    }
4508                }
4509                0b1111 => {
4510                    opcode_check!(inst & 0x00102000 == 0);
4511                    handler.on_source_decoded(Operand::gpr(sssss))?;
4512                    handler.on_dest_decoded(Operand::gpr(ddddd))?;
4513                    handler.on_opcode_decoded(Opcode::Insert)?;
4514                    handler.on_source_decoded(Operand::imm_u8(iiiiii))?;
4515
4516                    let l_low = ((inst >> 5) & 0b111) as u8;
4517                    let l_high = ((inst >> 21) & 0b111) as u8;
4518                    let llllll = (l_high << 3) | l_low;
4519                    handler.on_source_decoded(Operand::imm_u8(llllll))?;
4520                }
4521                _ => {
4522                    unreachable!("impossible bit pattern");
4523                }
4524            }
4525        }
4526        0b1001 => {
4527            if (inst >> 27) & 1 != 0 {
4528                let opc_high = (inst >> 24) & 0b111;
4529
4530                let op = (inst >> 21) & 0b111;
4531
4532                let ddddd = reg_b0(inst);
4533                let xxxxx = reg_b16(inst);
4534
4535                use Opcode::*;
4536                static MEM_FIFO_OPS: [Option<(Opcode, bool, u8)>; 8] = [
4537                    None,      Some((Membh, false, 0x01)), Some((MemhFifo, true, 0x01)), Some((Memubh, false, 0x01)),
4538                    Some((MembFifo, true, 0x00)), Some((Memubh, true, 0x02)), None, Some((Membh, true, 0x02)),
4539                ];
4540                static MEM_OPCODES: [Option<(Opcode, bool, u8)>; 8] = [
4541                    Some((Memb, false, 0x00)), Some((Memub, false, 0x00)), Some((Memh, false, 0x01)), Some((Memuh, false, 0x01)),
4542                    Some((Memw, false, 0x02)), None, Some((Memd, true, 0x03)), None,
4543                ];
4544
4545                match opc_high {
4546                    0b000 => {
4547                        let (op, wide, samt) = decode_opcode!(MEM_FIFO_OPS[op as usize]);
4548                        let src_offset = (inst >> 9) & 1 == 0;
4549                        let iiii = (inst >> 5) & 0b1111;
4550                        let mu = ((inst >> 13) & 1) as u8;
4551
4552
4553                        if src_offset {
4554                            let s4 = (iiii << 4) as i8 >> 4;
4555                            handler.on_source_decoded(Operand::RegOffsetCirc { base: xxxxx, offset: (s4 << samt) as u32, mu })?;
4556                        } else {
4557                            operand_check!(iiii & 0b0100 == 0);
4558                            handler.on_source_decoded(Operand::RegCirc { base: xxxxx, mu })?;
4559                        }
4560                        if !wide {
4561                            handler.on_dest_decoded(Operand::gpr(ddddd))?;
4562                        } else {
4563                            handler.on_dest_decoded(Operand::gprpair(ddddd)?)?;
4564                        }
4565                        handler.on_opcode_decoded(op)?;
4566                    }
4567                    0b001 => {
4568                        if op == 0b111 {
4569                            let sssss = reg_b8(inst);
4570                            let ttttt = reg_b16(inst);
4571                            // a couple extra instructions are stashed in here...
4572                            // 1001 | 1001111 | ttttt | PP | 0 sssss OPC | ddddd |
4573                            handler.on_source_decoded(Operand::gpr(sssss))?;
4574                            handler.on_source_decoded(Operand::gprpair(ttttt)?)?;
4575                            handler.on_dest_decoded(Operand::gprpair(ddddd)?)?;
4576
4577                            opcode_check!(inst & 0b0010_0000_0000_0000 == 0);
4578                            let opc = (inst >> 5) & 0b111;
4579                            let op = match opc {
4580                                0b000 => Opcode::Pmemcpy,
4581                                0b001 => Opcode::Linecpy,
4582                                _ => {
4583                                    return Err(DecodeError::InvalidOpcode);
4584                                }
4585                            };
4586                            handler.on_opcode_decoded(op)?;
4587                            return Ok(());
4588                        }
4589
4590                        let (op, wide, samt) = decode_opcode!(MEM_OPCODES[op as usize]);
4591                        let src_offset = (inst >> 9) & 1 == 0;
4592                        let iiii = (inst >> 5) & 0b1111;
4593                        let mu = ((inst >> 13) & 1) as u8;
4594
4595
4596                        if src_offset {
4597                            let s4 = (iiii << 4) as i8 >> 4;
4598                            handler.on_source_decoded(Operand::RegOffsetCirc { base: xxxxx, offset: (s4 << samt) as u32, mu })?;
4599                        } else {
4600                            operand_check!(iiii & 0b0100 == 0);
4601                            handler.on_source_decoded(Operand::RegCirc { base: xxxxx, mu })?;
4602                        }
4603                        if !wide {
4604                            handler.on_dest_decoded(Operand::gpr(ddddd))?;
4605                        } else {
4606                            handler.on_dest_decoded(Operand::gprpair(ddddd)?)?;
4607                        }
4608                        handler.on_opcode_decoded(op)?;
4609                    }
4610                    0b010 => {
4611                        opcode_check!(inst & 0b0010_0000_0000_0000 == 0);
4612
4613                        let (op, wide, samt) = decode_opcode!(MEM_FIFO_OPS[op as usize]);
4614
4615                        if inst & 0b0001_0000_0000_0000 == 0 {
4616                            let iiii = (inst >> 5) & 0b1111;
4617                            handler.on_source_decoded(Operand::RegOffsetInc { base: xxxxx, offset: (iiii << samt) })?;
4618                        } else {
4619                            let u2 = (inst >> 5) & 0b11;
4620                            let u4 = (inst >> 8) & 0b1111;
4621                            let uuuuuu = u2 | (u4 << 2);
4622                            handler.on_source_decoded(
4623                                Operand::with_extension(uuuuuu, extender,
4624                                    |addr| Ok(Operand::RegStoreAssign { base: xxxxx, addr }),
4625                                    |addr| Ok(Operand::RegStoreAssign { base: xxxxx, addr }),
4626                                )?
4627                            )?;
4628                        }
4629                        if !wide {
4630                            handler.on_dest_decoded(Operand::gpr(ddddd))?;
4631                        } else {
4632                            handler.on_dest_decoded(Operand::gprpair(ddddd)?)?;
4633                        }
4634                        handler.on_opcode_decoded(op)?;
4635                    }
4636                    0b011 => {
4637                        let predicated = inst & 0b0010_0000_0000_0000 != 0;
4638
4639                        let (op, wide, samt) = decode_opcode!(MEM_OPCODES[op as usize]);
4640
4641                        if !predicated {
4642                            if inst & 0b0001_0000_0000_0000 == 0 {
4643                                let iiii = (inst >> 5) & 0b1111;
4644                                handler.on_source_decoded(Operand::RegOffsetInc { base: xxxxx, offset: (iiii << samt) })?;
4645                            } else {
4646                                let u2 = (inst >> 5) & 0b11;
4647                                let u4 = (inst >> 8) & 0b1111;
4648                                let uuuuuu = (u2 | (u4 << 2)) as u32;
4649                                handler.on_source_decoded(
4650                                    Operand::with_extension(uuuuuu, extender,
4651                                        |addr| Ok(Operand::RegStoreAssign { base: xxxxx, addr }),
4652                                        |addr| Ok(Operand::RegStoreAssign { base: xxxxx, addr }),
4653                                    )?
4654                                )?;
4655                            }
4656                            if !wide {
4657                                handler.on_dest_decoded(Operand::gpr(ddddd))?;
4658                            } else {
4659                                handler.on_dest_decoded(Operand::gprpair(ddddd)?)?;
4660                            }
4661                            handler.on_opcode_decoded(op)?;
4662                        } else {
4663                            let iiii = (inst >> 5) & 0b1111;
4664                            let tt = (inst >> 9) & 0b11;
4665                            let negated = (inst >> 11) & 0b1 != 0;
4666                            let dotnew = (inst >> 12) & 0b1 != 0;
4667
4668                            handler.inst_predicated(tt as u8, negated, dotnew)?;
4669                            handler.on_source_decoded(Operand::RegOffsetInc { base: xxxxx, offset: (iiii << samt) })?;
4670                            if !wide {
4671                                handler.on_dest_decoded(Operand::gpr(ddddd))?;
4672                            } else {
4673                                handler.on_dest_decoded(Operand::gprpair(ddddd)?)?;
4674                            }
4675                            handler.on_opcode_decoded(op)?;
4676                        }
4677                    }
4678                    0b100 => {
4679                        let shifted_reg = inst & 0b0001_0000_0000_0000 != 0;
4680
4681                        let (op, wide, _samt) = decode_opcode!(MEM_FIFO_OPS[op as usize]);
4682
4683                        if !wide {
4684                            handler.on_dest_decoded(Operand::gpr(ddddd))?;
4685                        } else {
4686                            handler.on_dest_decoded(Operand::gprpair(ddddd)?)?;
4687                        }
4688                        handler.on_opcode_decoded(op)?;
4689
4690                        if !shifted_reg {
4691                            operand_check!(inst & 0b0000_0000_1000_0000 == 0);
4692
4693                            let mu = ((inst >> 13) & 1) as u8;
4694
4695                            handler.on_source_decoded(Operand::RegMemIndexed { base: xxxxx, mu })?;
4696                        } else {
4697                            let i_hi = (inst >> 13) & 1;
4698                            let i_lo = (inst >> 7) & 1;
4699                            let ii = ((i_hi << 1) | i_lo) as u8;
4700
4701                            let u2 = (inst >> 5) & 0b11;
4702                            let u4 = (inst >> 8) & 0b1111;
4703                            let uuuuuu = u2 | (u4 << 2);
4704
4705                            handler.on_source_decoded(
4706                                Operand::with_extension(uuuuuu, extender,
4707                                    |offset| Ok(Operand::RegShiftOffset { base: xxxxx, shift: ii, offset }),
4708                                    |offset| Ok(Operand::RegShiftOffset { base: xxxxx, shift: ii, offset }),
4709                                )?
4710                            )?;
4711                        }
4712                    }
4713                    0b101 => {
4714                        let shifted_reg = inst & 0b0001_0000_0000_0000 != 0;
4715
4716                        let (op, wide, _samt) = decode_opcode!(MEM_OPCODES[op as usize]);
4717
4718                        if !wide {
4719                            handler.on_dest_decoded(Operand::gpr(ddddd))?;
4720                        } else {
4721                            handler.on_dest_decoded(Operand::gprpair(ddddd)?)?;
4722                        }
4723                        handler.on_opcode_decoded(op)?;
4724
4725                        if !shifted_reg {
4726                            operand_check!(inst & 0b0000_0000_1000_0000 == 0);
4727
4728                            let mu = ((inst >> 13) & 1) as u8;
4729
4730                            handler.on_source_decoded(Operand::RegMemIndexed { base: xxxxx, mu })?;
4731                        } else {
4732                            let i_hi = (inst >> 13) & 1;
4733                            let i_lo = (inst >> 7) & 1;
4734                            let ii = ((i_hi << 1) | i_lo) as u8;
4735
4736                            let u2 = (inst >> 5) & 0b11;
4737                            let u4 = (inst >> 8) & 0b1111;
4738                            let uuuuuu = u2 | (u4 << 2);
4739
4740                            handler.on_source_decoded(
4741                                Operand::with_extension(uuuuuu, extender,
4742                                    |offset| Ok(Operand::RegShiftOffset { base: xxxxx, shift: ii, offset }),
4743                                    |offset| Ok(Operand::RegShiftOffset { base: xxxxx, shift: ii, offset }),
4744                                )?
4745                            )?;
4746                        }
4747                    }
4748                    0b110 => {
4749                        operand_check!(inst & 0b0001_0000_1000_0000 == 0);
4750
4751                        let (op, wide, _samt) = decode_opcode!(MEM_FIFO_OPS[op as usize]);
4752
4753                        let mu = ((inst >> 13) & 1) as u8;
4754                        handler.on_source_decoded(Operand::RegMemIndexedBrev { base: xxxxx, mu })?;
4755                        if !wide {
4756                            handler.on_dest_decoded(Operand::gpr(ddddd))?;
4757                        } else {
4758                            handler.on_dest_decoded(Operand::gprpair(ddddd)?)?;
4759                        }
4760                        handler.on_opcode_decoded(op)?;
4761                    }
4762                    _ => {
4763                        // 0b111
4764                        let predicated = inst & 0b0000_0000_1000_0000 != 0;
4765
4766                        let (op, wide, _samt) = decode_opcode!(MEM_OPCODES[op as usize]);
4767
4768                        if !predicated {
4769                            operand_check!(inst & 0b0001_0000_0000_0000 == 0);
4770                            let mu = ((inst >> 13) & 1) as u8;
4771                            handler.on_source_decoded(Operand::RegMemIndexedBrev { base: xxxxx, mu })?;
4772                            if !wide {
4773                                handler.on_dest_decoded(Operand::gpr(ddddd))?;
4774                            } else {
4775                                handler.on_dest_decoded(Operand::gprpair(ddddd)?)?;
4776                            }
4777                            handler.on_opcode_decoded(op)?;
4778                        } else {
4779                            let i5 = reg_b16(inst);
4780                            let i = ((inst >> 8) & 1) as u8;
4781                            let iiiiii = (i5 << 1) | i;
4782                            let ddddd = reg_b0(inst);
4783
4784                            let tt = (inst >> 9) & 0b11;
4785                            let negated = (inst >> 11) & 0b1 != 0;
4786                            let dotnew = (inst >> 12) & 0b1 != 0;
4787
4788                            handler.inst_predicated(tt as u8, negated, dotnew)?;
4789                            handler.on_source_decoded(
4790                                Operand::immext(iiiiii as u32, extender, |i6| {
4791                                    Ok(Operand::imm_u32(i6))
4792                                })?
4793                            )?;
4794                            if !wide {
4795                                handler.on_dest_decoded(Operand::gpr(ddddd))?;
4796                            } else {
4797                                handler.on_dest_decoded(Operand::gprpair(ddddd)?)?;
4798                            }
4799                            handler.on_opcode_decoded(op)?;
4800                        }
4801                    }
4802                }
4803            } else {
4804                let ddddd = reg_b0(inst);
4805                let sssss = reg_b16(inst);
4806                let op = (inst >> 21) & 0b1111;
4807
4808                if op == 0b0000 {
4809                    // some special handling here
4810                    let op_high = (inst >> 25) & 0b11;
4811                    match op_high {
4812                        0b00 => {
4813                            opcode_check!(inst & 0b10000_00000000 == 0);
4814
4815                            handler.on_source_decoded(Operand::gpr(sssss))?;
4816                            handler.on_dest_decoded(Operand::gprpair(ddddd)?)?;
4817                            handler.on_opcode_decoded(Opcode::DeallocFrame)?;
4818                        }
4819                        0b01 => {
4820                            opcode_check!(inst & 0b100000_111_00000 == 0);
4821                            let op_low = (inst >> 11) & 0b11;
4822                            static OP: [Opcode; 4] = [
4823                                Opcode::MemwLockedLoad, Opcode::MemwAq,
4824                                Opcode::MemdLockedLoad, Opcode::MemdAq,
4825                            ];
4826                            handler.on_source_decoded(Operand::gpr(sssss))?;
4827                            if op_low > 0b01 {
4828                                handler.on_dest_decoded(Operand::gprpair(ddddd)?)?;
4829                            } else {
4830                                handler.on_dest_decoded(Operand::gpr(ddddd))?;
4831                            }
4832                            handler.on_opcode_decoded(OP[op_low as usize])?;
4833                        }
4834                        0b10 => {
4835                            let i11 = inst & 0b111111_11111;
4836                            handler.on_source_decoded(Operand::RegOffset { base: sssss, offset: i11 << 3 })?;
4837                            handler.on_opcode_decoded(Opcode::Dcfetch)?;
4838                        }
4839                        _ => { /* 0b11 */
4840                            opcode_check!(inst & 0b1_00000_00000 == 0);
4841
4842                            handler.on_source_decoded(Operand::gpr(sssss))?;
4843                            handler.on_dest_decoded(Operand::gprpair(ddddd)?)?;
4844                            handler.on_opcode_decoded(Opcode::DeallocReturn)?;
4845
4846                            let hints = (inst >> 11) & 0b111;
4847                            if hints == 0 {
4848                                // no predication, not hint, just deallocreturn().
4849                            } else if hints == 0b100 {
4850                                // hint 100 is not valid (would be unpredicated negated
4851                                // dealloc_return()?)
4852                                return Err(DecodeError::InvalidOpcode);
4853                            } else {
4854                                let dotnew = (hints & 0b001) != 0;
4855                                let negated = (hints & 0b100) != 0;
4856                                let pred = (inst >> 8) & 0b11;
4857
4858                                handler.inst_predicated(pred as u8, negated, dotnew)?;
4859                                if dotnew {
4860                                    let taken = hints & 0b010 != 0;
4861                                    handler.branch_hint(taken)?;
4862                                }
4863                            }
4864                        }
4865                    }
4866                } else {
4867                    let i_lo = (inst >> 5) & 0b1_1111_1111;
4868                    let i_hi = (inst >> 25) & 0b11;
4869                    let i = i_lo | (i_hi << 9);
4870
4871                    use Opcode::*;
4872                    static OPCODES: [Option<(Opcode, bool, u8)>; 16] = [
4873                        None,      Some((Membh, false, 0x01)), Some((MemhFifo, true, 0x01)), Some((Memubh, false, 0x01)),
4874                        Some((MembFifo, true, 0x00)), Some((Memubh, true, 0x02)), None, Some((Membh, true, 0x02)),
4875                        Some((Memb, false, 0x00)), Some((Memub, false, 0x00)), Some((Memh, false, 0x01)), Some((Memuh, false, 0x01)),
4876                        Some((Memw, false, 0x02)), None, Some((Memd, true, 0x03)), None,
4877                    ];
4878                    let (op, wide, shamt) = decode_opcode!(OPCODES[op as usize]);
4879                    // the manuals through V79 do not describe constant extenders being applicable
4880                    // to memb_fifo or meubh or ... but it turns out each of these opcodes include
4881                    // an `apply_extension()` clause in their behavior, so this seems like a
4882                    // deficiency in the manual rather. assume this operand can be extended for all
4883                    // opcodes.
4884                    handler.on_source_decoded(
4885                        Operand::with_extension(
4886                            i as u32, extender,
4887                            |offset| Ok(Operand::RegOffset { base: sssss, offset }),
4888                            |offset| Ok(Operand::RegOffset {
4889                                base: sssss, offset: offset << shamt
4890                            }),
4891                        )?
4892                    )?;
4893                    if !wide {
4894                        handler.on_dest_decoded(Operand::gpr(ddddd))?;
4895                    } else {
4896                        handler.on_dest_decoded(Operand::gprpair(ddddd)?)?;
4897                    }
4898                    handler.on_opcode_decoded(op)?;
4899                }
4900            }
4901        }
4902        0b1010 => {
4903            if inst >> 27 & 1 == 0 {
4904                // lower chunk: 1010|0 ....
4905
4906                // may also be xxxxx, depends on instruction.
4907                let sssss = reg_b16(inst);
4908                #[allow(non_snake_case)]
4909                let Rs = Operand::gpr(sssss);
4910
4911                if inst >> 24 & 1 == 0 {
4912                    // 1010|0..0... these are semi-special memory operations.
4913                    let opc_upper = inst >> 25 & 0b11;
4914                    if opc_upper == 0b00 {
4915                        let opc_lower = (inst >> 21) & 0b111;
4916                        match opc_lower {
4917                            0b000 => {
4918                                handler.on_opcode_decoded(Opcode::DcCleanA)?;
4919                                handler.on_source_decoded(Rs)?;
4920                            },
4921                            0b001 => {
4922                                handler.on_opcode_decoded(Opcode::DcInvA)?;
4923                                handler.on_source_decoded(Rs)?;
4924                            },
4925                            0b010 => {
4926                                handler.on_opcode_decoded(Opcode::DcCleanInvA)?;
4927                                handler.on_source_decoded(Rs)?;
4928                            },
4929                            0b011 => {
4930                                opcode_check!(inst & 0b11100 == 0b01100);
4931                                handler.on_opcode_decoded(Opcode::Release)?;
4932                                handler.on_source_decoded(Rs)?;
4933                                if (inst >> 5) & 1 == 0 {
4934                                    handler.domain_hint(DomainHint::All)?;
4935                                } else {
4936                                    handler.domain_hint(DomainHint::Same)?;
4937                                }
4938                            },
4939                            0b100 => {
4940                                handler.on_opcode_decoded(Opcode::AllocFrame)?;
4941                                let i11 = inst & 0b111_11111111;
4942                                operand_check!(inst & 0b111000_00000000 == 0);
4943                                handler.on_source_decoded(Rs)?;
4944                                handler.on_source_decoded(Operand::imm_u16((i11 as u16) << 3))?;
4945                            }
4946                            0b101 => {
4947                                handler.on_dest_decoded(Rs)?;
4948                                handler.on_source_decoded(Operand::gpr((inst >> 8) as u8 & 0b11111))?;
4949                                if inst & 0b1100 == 0b0000 {
4950                                    handler.on_opcode_decoded(Opcode::MemwStoreCond)?;
4951                                    handler.on_dest_decoded(Operand::pred(inst as u8 & 0b11))?;
4952                                } else if inst & 0b11100 == 0b01000 {
4953                                    handler.on_opcode_decoded(Opcode::MemwRl)?;
4954                                    if (inst >> 5) & 1 == 0 {
4955                                        handler.domain_hint(DomainHint::All)?;
4956                                    } else {
4957                                        handler.domain_hint(DomainHint::Same)?;
4958                                    }
4959                                } else {
4960                                    return Err(DecodeError::InvalidOpcode);
4961                                }
4962                            },
4963                            0b110 => {
4964                                opcode_check!((inst >> 13) & 1 == 0);
4965                                handler.on_opcode_decoded(Opcode::DcZeroA)?;
4966                                handler.on_source_decoded(Rs)?;
4967                            }
4968                            _ => {
4969                                // 1010|0000|111
4970                                handler.on_dest_decoded(Rs)?;
4971                                handler.on_source_decoded(Operand::gprpair((inst >> 8) as u8 & 0b11111)?)?;
4972                                if inst & 0b1100 == 0b0000 {
4973                                    handler.on_opcode_decoded(Opcode::MemdStoreCond)?;
4974                                    handler.on_dest_decoded(Operand::pred(inst as u8 & 0b11))?;
4975                                } else if inst & 0b11100 == 0b01000 {
4976                                    handler.on_opcode_decoded(Opcode::MemdRl)?;
4977                                    if (inst >> 5) & 1 == 0 {
4978                                        handler.domain_hint(DomainHint::All)?;
4979                                    } else {
4980                                        handler.domain_hint(DomainHint::Same)?;
4981                                    }
4982                                } else {
4983                                    return Err(DecodeError::InvalidOpcode);
4984                                }
4985                            },
4986                        }
4987                    } else if opc_upper == 0b01 {
4988                        // 1010|0010
4989                        // in V65, not in V73, in LLVM definitions: dckill
4990                        handler.on_opcode_decoded(Opcode::DcKill)?;
4991                    } else {
4992                        // if there are any encodings like 1010|010, they are not in the V73
4993                        // manual...
4994                        //
4995                        // ... surprise! L2 cache management instructions are system instructions
4996                        // and last described in the V65 manual.
4997                        opcode_check!(opc_upper == 0b11);
4998                        let opc_lower = (inst >> 21) & 0b111;
4999
5000                        let ttttt = reg_b8(inst);
5001                        match opc_lower {
5002                            0b000 => {
5003                                handler.on_opcode_decoded(Opcode::L2Fetch)?;
5004                                handler.on_source_decoded(Rs)?;
5005                                opcode_check!((inst >> 5) & 0b111 == 0b000);
5006                                handler.on_source_decoded(Operand::gpr(ttttt))?;
5007                            }
5008                            0b100 => {
5009                                handler.on_opcode_decoded(Opcode::L2Fetch)?;
5010                                handler.on_source_decoded(Rs)?;
5011                                handler.on_source_decoded(Operand::gprpair(ttttt)?)?;
5012                            }
5013                            0b101 => {
5014                                handler.on_opcode_decoded(Opcode::L2Gclean)?;
5015                                handler.on_source_decoded(Operand::gprpair(ttttt)?)?;
5016                            }
5017                            0b110 => {
5018                                handler.on_opcode_decoded(Opcode::L2Gcleaninv)?;
5019                                handler.on_source_decoded(Operand::gprpair(ttttt)?)?;
5020                            }
5021                            _ => {
5022                                opcode_check!(false);
5023                            }
5024                        }
5025                    }
5026                } else {
5027                    // 1010|0ii1ooo: stores with some large signed offset, operation picked by ooo
5028                    let opc = ((inst >> 21) & 0b111) as u8;
5029                    let i_high = (inst >> 25) & 0b11;
5030                    let i_mid = (inst >> 13) & 1;
5031                    let i_low = inst & 0b11111111;
5032                    let ttttt = reg_b8(inst);
5033
5034                    let i11 = i_low | (i_mid << 8) | (i_high << 9);
5035
5036                    decode_store_ops(handler, opc, ttttt, |shamt| {
5037                        Operand::with_extension(
5038                            i11, extender,
5039                            |offset| Ok(Operand::RegOffset { base: sssss, offset }),
5040                            |offset| Ok(Operand::RegOffset {
5041                                base: sssss, offset: offset << shamt
5042                            }),
5043                        )
5044                    })?;
5045
5046                }
5047            } else {
5048                // upper chunk: 1010|1 ....
5049                let majbits = (inst >> 24) & 0b111;
5050
5051                let minbits = ((inst >> 21) & 0b111) as u8;
5052                match majbits {
5053                    0b000 => {
5054                        // barrier, dmsyncht, syncht. not much here (maybe these are supervisor
5055                        // instructions?)
5056                        //
5057                        // ... yes! l2 cache operations are packed in here.
5058                        if inst & 0x00_e0_00_e0 == 0 {
5059                            handler.on_opcode_decoded(Opcode::Barrier)?;
5060                        } else if inst & 0x00_e0_00_00 == 0x00_20_00_00 {
5061                            let op = (inst >> 10) & 0b111;
5062                            static OPCODES: [Option<Opcode>; 8] = [
5063                                Some(L2Kill), None, Some(L2Gunlock), None,
5064                                Some(L2Gclean), None, Some(L2Gcleaninv), None,
5065                            ];
5066                            handler.on_opcode_decoded(decode_opcode!(OPCODES[op as usize]))?;
5067                        } else if inst & 0x00_e0_01_e0 == 0x00_00_00_e0 {
5068                            handler.on_opcode_decoded(Opcode::DmSyncHt)?;
5069                            handler.on_dest_decoded(Operand::gpr(inst as u8 & 0b11111))?;
5070                        } else if inst & 0x00_e0_00_00 == 0x00_40_00_00 {
5071                            handler.on_opcode_decoded(Opcode::SyncHt)?;
5072                        } else {
5073                            return Err(DecodeError::InvalidOpcode);
5074                        }
5075                    }
5076                    0b001 => {
5077                        let xxxxx = reg_b16(inst);
5078                        let ttttt = reg_b8(inst);
5079                        let u = ((inst >> 13) & 1) as u8;
5080                        // seems to be nothing at bit 1 here (yet?)
5081                        opcode_check!((inst >> 7) & 1 == 0);
5082                        if (inst >> 1) & 1 == 0 {
5083                            let iiii = (inst >> 3) & 0b1111;
5084                            decode_store_ops(handler, minbits, ttttt, |shamt| {
5085                                Ok(Operand::RegOffsetCirc { base: xxxxx, offset: iiii << shamt, mu: u })
5086                            })?;
5087                        } else {
5088                            decode_store_ops(handler, minbits, ttttt, |_shamt| {
5089                                Ok(Operand::RegCirc { base: xxxxx, mu: u })
5090                            })?;
5091                        }
5092                    }
5093                    0b010 => {
5094                        return Err(DecodeError::InvalidOpcode);
5095                    }
5096                    0b011 => {
5097                        let xxxxx = reg_b16(inst);
5098                        let ttttt = reg_b8(inst);
5099                        if (inst >> 13) & 1 == 0 {
5100                            // 1010|1011...|.....|PP|0...
5101                            if (inst >> 7) & 1 == 0 {
5102                                opcode_check!(inst & 2 == 0);
5103                                let iiii = ((inst >> 3) & 0b1111) as u32;
5104                                decode_store_ops(handler, minbits, ttttt, |shamt| {
5105                                    Ok(Operand::RegOffset { base: xxxxx, offset: iiii << shamt })
5106                                })?;
5107                            } else {
5108                                let uuuuuu = inst & 0b111111;
5109                                decode_store_ops(handler, minbits, ttttt, |_shamt| {
5110                                    Operand::with_extension(uuuuuu, extender,
5111                                        |addr| Ok(Operand::RegStoreAssign { base: xxxxx, addr }),
5112                                        |addr| Ok(Operand::RegStoreAssign { base: xxxxx, addr }),
5113                                    )
5114                                })?;
5115                            }
5116                        } else {
5117                            // 1010|1011...|.....|PP|1...
5118                            // predicated store
5119                            let vv = inst & 0b11;
5120                            let negated = (inst >> 2) & 1 == 1;
5121                            let iiii = (inst >> 3) & 0b1111;
5122                            let dotnew = (inst >> 7) & 1 == 1;
5123                            decode_store_ops(handler, minbits, ttttt, |shamt| {
5124                                Ok(Operand::RegOffsetInc { base: xxxxx, offset: iiii << shamt })
5125                            })?;
5126                            handler.inst_predicated(vv as u8, negated, dotnew)?;
5127                        }
5128                    }
5129                    0b100 => {
5130                        return Err(DecodeError::InvalidOpcode);
5131                    }
5132                    0b101 => {
5133                        let xxxxx = reg_b16(inst);
5134                        let ttttt = reg_b8(inst);
5135                        if (inst >> 7) & 1 == 0 {
5136                            let u = (inst >> 13) & 1;
5137                            decode_store_ops(handler, minbits, ttttt, |_shamt| {
5138                                Ok(Operand::RegMemIndexed { base: xxxxx, mu: u as u8 })
5139                            })?;
5140                        } else {
5141                            let i_hi = (inst >> 13) & 1;
5142                            let i_lo = (inst >> 6) & 1;
5143                            let i = ((i_hi << 1) | i_lo) as u8;
5144                            let uuuuuu = inst & 0b111111;
5145                            decode_store_ops(handler, minbits, ttttt, |_shamt| {
5146                                Operand::with_extension(uuuuuu, extender,
5147                                    |offset| Ok(Operand::RegShiftOffset { base: xxxxx, shift: i, offset }),
5148                                    |offset| Ok(Operand::RegShiftOffset { base: xxxxx, shift: i, offset }),
5149                                )
5150                            })?;
5151                        }
5152                    },
5153                    0b110 => {
5154                        return Err(DecodeError::InvalidOpcode);
5155                    }
5156                    _ => { /* 0b111 */
5157                        let xxxxx = reg_b16(inst);
5158                        let ttttt = reg_b8(inst);
5159                        if (inst >> 7) & 1 == 0 {
5160                            let u = (inst >> 13) & 1;
5161                            decode_store_ops(handler, minbits, ttttt, |_shamt| {
5162                                Ok(Operand::RegMemIndexedBrev { base: xxxxx, mu: u as u8 })
5163                            })?;
5164                        } else {
5165                            // 1010|1111...|.....|PP|1...
5166                            // predicated store
5167                            let vv = inst & 0b11;
5168                            let negated = (inst >> 2) & 1 == 1;
5169                            let iiii = ((inst >> 3) & 0b1111) as u8;
5170                            let ii_high = xxxxx & 0b11;
5171                            let i6 = ((ii_high << 4) | iiii) as i8;
5172                            let dotnew = (inst >> 13) & 1 == 1;
5173                            decode_store_ops(handler, minbits, ttttt, |_shamt| {
5174                                Operand::with_extension(i6 as u32, extender,
5175                                    |addr| Ok(Operand::Absolute { addr }),
5176                                    |addr| Ok(Operand::Absolute { addr }),
5177                                )
5178                            })?;
5179                            handler.inst_predicated(vv as u8, negated, dotnew)?;
5180                        }
5181                    }
5182                }
5183            }
5184        }
5185        0b1011 => {
5186            handler.on_opcode_decoded(Opcode::Add)?;
5187
5188            let ddddd = reg_b0(inst);
5189            let sssss = reg_b16(inst);
5190
5191            let i_hi = (inst >> 21) & 0b111_1111;
5192            let i_lo = (inst >> 5) & 0b1_1111_1111;
5193            let i = (i_hi << 9) | i_lo;
5194
5195            handler.on_dest_decoded(Operand::gpr(ddddd))?;
5196            handler.on_source_decoded(Operand::gpr(sssss))?;
5197            handler.on_source_decoded(Operand::immext(i, extender, |i| Ok(Operand::imm_i16(i as i16)))?)?;
5198        }
5199        0b1100 => {
5200            let ddddd = reg_b0(inst);
5201            let ttttt = reg_b8(inst);
5202            let sssss = reg_b16(inst);
5203
5204            let majbits = (inst >> 24) & 0b1111;
5205            match majbits {
5206                0b0000 => {
5207                    // 1100|0000|...
5208                    let op = (inst >> 23) & 1;
5209
5210                    let iii = (inst >> 5) & 0b111;
5211
5212                    handler.on_dest_decoded(Operand::gprpair(ddddd)?)?;
5213
5214                    if op == 0 {
5215                        handler.on_opcode_decoded(Opcode::Valignb)?;
5216                        handler.on_source_decoded(Operand::gprpair(ttttt)?)?;
5217                        handler.on_source_decoded(Operand::gprpair(sssss)?)?;
5218                    } else {
5219                        handler.on_opcode_decoded(Opcode::Vspliceb)?;
5220                        handler.on_source_decoded(Operand::gprpair(sssss)?)?;
5221                        handler.on_source_decoded(Operand::gprpair(ttttt)?)?;
5222                    }
5223                    handler.on_source_decoded(Operand::imm_u8(iii as u8))?;
5224                }
5225                0b0001 => {
5226                    let op_lo = (inst >> 5) & 0b111;
5227                    let op_hi = (inst >> 22) & 011;
5228
5229                    match op_hi {
5230                        0b00 => {
5231                            static OPCODES: [Opcode; 8] = [
5232                                Opcode::Extractu, Opcode::Extractu, Opcode::Shuffeb, Opcode::Shuffeb,
5233                                Opcode::Shuffob, Opcode::Shuffob, Opcode::Shuffeh, Opcode::Shuffeh,
5234                            ];
5235
5236                            handler.on_opcode_decoded(OPCODES[op_lo as usize])?;
5237                            handler.on_dest_decoded(Operand::gprpair(ddddd)?)?;
5238                            if op_lo < 0b100 {
5239                                handler.on_source_decoded(Operand::gprpair(sssss)?)?;
5240                                handler.on_source_decoded(Operand::gprpair(ttttt)?)?;
5241                            } else {
5242                                handler.on_source_decoded(Operand::gprpair(ttttt)?)?;
5243                                handler.on_source_decoded(Operand::gprpair(sssss)?)?;
5244                            }
5245                        },
5246                        0b01 => {
5247                            static OPCODES: [Option<Opcode>; 8] = [
5248                                Some(Vxaddsubw), Some(Vaddhub), Some(Vxsubaddw), None,
5249                                Some(Vxaddsubh), None         , Some(Vxsubaddh), None,
5250                            ];
5251
5252                            let op_lo = (inst >> 5) as usize & 0b111;
5253
5254                            handler.on_opcode_decoded(decode_opcode!(OPCODES[op_lo]))?;
5255                            handler.saturate()?;
5256                            if op_lo == 0b001 {
5257                                handler.on_dest_decoded(Operand::gpr(ddddd))?;
5258                            } else {
5259                                handler.on_dest_decoded(Operand::gprpair(ddddd)?)?;
5260                            }
5261                            handler.on_source_decoded(Operand::gprpair(sssss)?)?;
5262                            handler.on_source_decoded(Operand::gprpair(ttttt)?)?;
5263                        }
5264                        0b10 => {
5265                            static OPCODES: [Option<Opcode>; 8] = [
5266                                Some(Shuffoh),   None, Some(Vtrunewh), Some(Vtrunehb),
5267                                Some(Vtrunowh), Some(Vtrunohb), Some(Lfs), None,
5268                            ];
5269
5270                            let op_lo = (inst >> 5) as usize & 0b111;
5271
5272                            handler.on_opcode_decoded(decode_opcode!(OPCODES[op_lo]))?;
5273                            handler.on_dest_decoded(Operand::gprpair(ddddd)?)?;
5274
5275                            if op_lo == 0b000 {
5276                                handler.on_source_decoded(Operand::gprpair(ttttt)?)?;
5277                                handler.on_source_decoded(Operand::gprpair(sssss)?)?;
5278                            } else {
5279                                handler.on_source_decoded(Operand::gprpair(sssss)?)?;
5280                                handler.on_source_decoded(Operand::gprpair(ttttt)?)?;
5281                            }
5282                        }
5283                        _ => {
5284                            static OPCODES: [Opcode; 8] = [
5285                                Opcode::Vxaddsubh, Opcode::Vxaddsubh, Opcode::Vxsubaddh, Opcode::Vxsubaddh,
5286                                Opcode::Extractu, Opcode::Extractu, Opcode::Decbin, Opcode::Decbin,
5287                            ];
5288
5289                            handler.on_opcode_decoded(OPCODES[op_lo as usize])?;
5290                            handler.on_dest_decoded(Operand::gprpair(ddddd)?)?;
5291                            handler.on_source_decoded(Operand::gprpair(sssss)?)?;
5292                            handler.on_source_decoded(Operand::gprpair(ttttt)?)?;
5293
5294                            if op_lo < 0b100 {
5295                                handler.rounded(RoundingMode::Round)?;
5296                                handler.shift_right(1)?;
5297                                handler.saturate()?;
5298                            }
5299                        }
5300                    }
5301                }
5302                0b0010 => {
5303                    let minbits = (inst >> 21) & 0b111;
5304
5305                    let uu = ((inst >> 5) & 0b11) as u8;
5306
5307                    handler.on_dest_decoded(Operand::gprpair(ddddd)?)?;
5308                    if minbits & 0b100 == 0 {
5309                        handler.on_source_decoded(Operand::gprpair(ttttt)?)?;
5310                        handler.on_source_decoded(Operand::gprpair(sssss)?)?;
5311                    } else {
5312                        handler.on_source_decoded(Operand::gprpair(sssss)?)?;
5313                        handler.on_source_decoded(Operand::gprpair(ttttt)?)?;
5314                    }
5315                    handler.on_source_decoded(Operand::pred(uu))?;
5316
5317                    if minbits & 0b100 == 0 {
5318                        handler.on_opcode_decoded(Opcode::Valignb)?;
5319                    } else if minbits == 0b100 {
5320                        handler.on_opcode_decoded(Opcode::Vspliceb)?;
5321                    } else if minbits == 0b110 {
5322                        handler.on_opcode_decoded(Opcode::Add)?;
5323                        handler.carry()?;
5324                    } else if minbits == 0b111 {
5325                        handler.on_opcode_decoded(Opcode::Sub)?;
5326                        handler.carry()?;
5327                    } else {
5328                        return Err(DecodeError::InvalidOpcode);
5329                    }
5330                }
5331                0b0011 => {
5332                    let minbits = (inst >> 22) & 0b11;
5333                    let op_lo = (inst >> 6) & 0b11;
5334
5335                    let opc = op_lo | (minbits << 2);
5336
5337                    handler.on_dest_decoded(Operand::gprpair(ddddd)?)?;
5338                    handler.on_source_decoded(Operand::gprpair(sssss)?)?;
5339                    handler.on_source_decoded(Operand::gpr(ttttt))?;
5340
5341                    if minbits == 0b11 {
5342                        if op_lo == 0b00 {
5343                            handler.on_opcode_decoded(Opcode::Vcrotate)?;
5344                        } else if op_lo == 0b01 {
5345                            handler.on_opcode_decoded(Opcode::Vcnegh)?;
5346                        } else if op_lo == 0b11 {
5347                            handler.on_opcode_decoded(Opcode::Vrcrotate)?;
5348                            let u_lo = (inst >> 5) & 1;
5349                            let u_hi = (inst >> 13) & 1;
5350                            let u = u_lo | (u_hi << 1);
5351                            handler.on_source_decoded(Operand::imm_u8(u as u8))?;
5352                        } else {
5353                            return Err(DecodeError::InvalidOpcode);
5354                        }
5355                    } else {
5356                        static OPCODES: [Option<Opcode>; 16] = [
5357                            Some(Vasrw), Some(Vlsrw), Some(Vaslw), Some(Vlslw),
5358                            Some(Vasrh), Some(Vlsrh), Some(Vaslh), Some(Vlslh),
5359                            Some(Asr), Some(Lsr), Some(Asl), Some(Lsl),
5360                            None, None, None, None,
5361                        ];
5362
5363                        handler.on_opcode_decoded(decode_opcode!(OPCODES[opc as usize]))?;
5364                    }
5365
5366                }
5367                0b0100 => {
5368                    let minbits = (inst >> 21) & 0b111;
5369                    opcode_check!(minbits == 0b000);
5370                    operand_check!(inst & 0b0010_0000_0000_0000 == 0);
5371
5372                    handler.on_opcode_decoded(Opcode::AddAslRegReg)?;
5373                    handler.on_dest_decoded(Operand::gpr(ddddd))?;
5374                    handler.on_source_decoded(Operand::gpr(ttttt))?;
5375                    handler.on_source_decoded(Operand::gpr(sssss))?;
5376                    handler.on_source_decoded(Operand::imm_u8(((inst >> 5) & 0b111) as u8))?;
5377                }
5378                0b0101 => {
5379                    let minbits = (inst >> 5) & 0b111;
5380
5381                    handler.on_dest_decoded(Operand::gpr(ddddd))?;
5382
5383                    if minbits < 0b100 {
5384                        opcode_check!(minbits == 0b010);
5385                        handler.on_opcode_decoded(Opcode::Vasrw)?;
5386                        handler.on_source_decoded(Operand::gpr(sssss))?;
5387                        handler.on_source_decoded(Operand::gpr(ttttt))?;
5388                    } else {
5389                        handler.shift_left(1)?;
5390                        handler.rounded(RoundingMode::Round)?;
5391                        handler.saturate()?;
5392                        if minbits & 0b010 == 0 {
5393                            handler.on_opcode_decoded(Opcode::Cmpyiwh)?;
5394                        } else {
5395                            handler.on_opcode_decoded(Opcode::Cmpyrwh)?;
5396                        }
5397                        handler.on_source_decoded(Operand::gprpair(sssss)?)?;
5398                        if minbits & 0b001 == 0 {
5399                            handler.on_source_decoded(Operand::gpr(ttttt))?;
5400                        } else {
5401                            handler.on_source_decoded(Operand::gpr_conjugate(ttttt))?;
5402                        }
5403                    }
5404                }
5405                0b0110 => {
5406                    // opc bits are both inst[6:7] and inst[22:23]
5407                    let op_lo = (inst >> 6) & 0b11;
5408                    let op_hi = (inst >> 22) & 0b11;
5409                    let opc = op_lo | (op_hi << 2);
5410
5411                    match opc {
5412                        0b0000 => {
5413                            handler.on_opcode_decoded(Opcode::Asr)?;
5414                            handler.saturate()?;
5415                        },
5416                        0b0010 => {
5417                            handler.on_opcode_decoded(Opcode::Asl)?;
5418                            handler.saturate()?;
5419                        },
5420                        0b0100 => {
5421                            handler.on_opcode_decoded(Opcode::Asr)?;
5422                        },
5423                        0b0101 => {
5424                            handler.on_opcode_decoded(Opcode::Lsr)?;
5425                        },
5426                        0b0110 => {
5427                            handler.on_opcode_decoded(Opcode::Asl)?;
5428                        },
5429                        0b0111 => {
5430                            handler.on_opcode_decoded(Opcode::Lsl)?;
5431                        },
5432                        0b1011 => {
5433                            let i_hi = reg_b16(inst);
5434                            let i_lo = ((inst >> 5) & 1) as u8;
5435                            let i6 = i_lo | (i_hi << 1);
5436                            let i6 = i6 as i8;
5437
5438                            handler.on_opcode_decoded(Opcode::Lsl)?;
5439                            handler.on_dest_decoded(Operand::gpr(reg_b0(inst)))?;
5440                            handler.on_source_decoded(Operand::imm_i8(i6 << 2  >> 2))?;
5441                            handler.on_source_decoded(Operand::gpr(reg_b8(inst)))?;
5442                            return Ok(());
5443                        },
5444                        0b1100 => {
5445                            handler.on_opcode_decoded(Opcode::Cround)?;
5446                        },
5447                        0b1101 => {
5448                            handler.on_opcode_decoded(Opcode::Cround)?;
5449                            handler.on_dest_decoded(Operand::gprpair(reg_b0(inst))?)?;
5450                            handler.on_source_decoded(Operand::gprpair(reg_b16(inst))?)?;
5451                            handler.on_source_decoded(Operand::gpr(reg_b8(inst)))?;
5452                            return Ok(());
5453                        },
5454                        0b1110 => {
5455                            handler.on_opcode_decoded(Opcode::Round)?;
5456                        },
5457                        0b1111 => {
5458                            handler.on_opcode_decoded(Opcode::Round)?;
5459                            handler.saturate()?;
5460                        },
5461                        _ => {
5462                            opcode_check!(false);
5463                        }
5464                    }
5465
5466                    handler.on_dest_decoded(Operand::gpr(reg_b0(inst)))?;
5467                    handler.on_source_decoded(Operand::gpr(reg_b16(inst)))?;
5468                    handler.on_source_decoded(Operand::gpr(reg_b8(inst)))?;
5469                }
5470                0b0111 => {
5471                    let op_hi = (inst >> 21) & 0b111;
5472                    let op_lo = (inst >> 5) & 0b111;
5473
5474                    handler.on_dest_decoded(Operand::pred(reg_b0(inst) & 0b11))?;
5475                    handler.on_source_decoded(Operand::gpr(reg_b16(inst)))?;
5476                    handler.on_source_decoded(Operand::gpr(reg_b8(inst)))?;
5477
5478                    if op_hi < 0b110 {
5479                        if op_hi & 0b001 == 1 {
5480                            handler.negate_result()?;
5481                        }
5482                        match op_hi >> 1 {
5483                            0b00 => {
5484                                handler.on_opcode_decoded(Opcode::Tstbit)?;
5485                            }
5486                            0b01 => {
5487                                handler.on_opcode_decoded(Opcode::Bitsset)?;
5488                            }
5489                            _ => {
5490                                handler.on_opcode_decoded(Opcode::Bitsclr)?;
5491                            }
5492                        }
5493                    } else if op_hi == 0b110 {
5494                        static OPCODES: [Option<Opcode>; 8] = [
5495                            None, None,
5496                            Some(Opcode::CmpbGt), Some(Opcode::CmphGt),
5497                            Some(Opcode::CmphEq), Some(Opcode::CmphGtu),
5498                            Some(Opcode::CmpbEq), Some(Opcode::CmpbGtu),
5499                        ];
5500                        handler.on_opcode_decoded(decode_opcode!(OPCODES[op_lo as usize]))?;
5501                    } else {
5502                        // 1 1 0 0|0 1 1 1|1 1 1...
5503                        static OPCODES: [Option<Opcode>; 8] = [
5504                            Some(Opcode::SfCmpGe), Some(Opcode::SfCmpUo),
5505                            None, Some(Opcode::SfCmpEq),
5506                            Some(Opcode::SfCmpGt), None,
5507                            None, None,
5508                        ];
5509                        handler.on_opcode_decoded(decode_opcode!(OPCODES[op_lo as usize]))?;
5510                    }
5511                }
5512                0b1000 => {
5513                    handler.on_opcode_decoded(Opcode::Insert)?;
5514                    handler.on_dest_decoded(Operand::gpr(reg_b0(inst)))?;
5515                    handler.on_source_decoded(Operand::gpr(reg_b16(inst)))?;
5516                    handler.on_source_decoded(Operand::gprpair(reg_b8(inst))?)?;
5517                }
5518                0b1001 => {
5519                    opcode_check!((inst >> 22) & 0b11 == 0b11);
5520                    let minbits = (inst >> 6) & 0b11;
5521
5522                    handler.on_dest_decoded(Operand::gpr(reg_b0(inst)))?;
5523                    handler.on_source_decoded(Operand::gpr(reg_b16(inst)))?;
5524                    handler.on_source_decoded(Operand::gprpair(reg_b8(inst))?)?;
5525
5526                    if minbits == 0b00 {
5527                        handler.on_opcode_decoded(Opcode::Extractu)?;
5528                    } else if minbits == 0b01 {
5529                        handler.on_opcode_decoded(Opcode::Extract)?;
5530                    } else {
5531                        opcode_check!(false);
5532                    }
5533                }
5534                0b1010 => {
5535                    let minbits = (inst >> 21) & 0b111;
5536                    opcode_check!(inst & 0b0010_0000_0000_0000 == 0);
5537                    if minbits & 0b100 == 0 {
5538                        handler.on_opcode_decoded(Opcode::Insert)?;
5539                        handler.on_dest_decoded(Operand::gprpair(reg_b0(inst))?)?;
5540                        handler.on_source_decoded(Operand::gprpair(reg_b16(inst))?)?;
5541                        handler.on_source_decoded(Operand::gprpair(reg_b8(inst))?)?;
5542                    } else if minbits & 0b110 == 0b100 {
5543                        opcode_check!((inst >> 5) & 0b111 == 0);
5544                        handler.on_opcode_decoded(Opcode::Xor)?;
5545                        handler.assign_mode(AssignMode::XorAssign)?;
5546                        handler.on_dest_decoded(Operand::gprpair(reg_b0(inst))?)?;
5547                        handler.on_source_decoded(Operand::gprpair(reg_b16(inst))?)?;
5548                        handler.on_source_decoded(Operand::gprpair(reg_b8(inst))?)?;
5549                    } else {
5550                        opcode_check!(false);
5551                    }
5552                }
5553                0b1011 => {
5554                    let minbits = (inst >> 21) & 0b111;
5555                    let op_bits = (inst >> 5) & 0b111;
5556                    let xxxxx = reg_b0(inst);
5557                    let ttttt = reg_b8(inst);
5558                    let sssss = reg_b16(inst);
5559
5560                    handler.on_dest_decoded(Operand::gprpair(xxxxx)?)?;
5561                    handler.on_source_decoded(Operand::gprpair(sssss)?)?;
5562                    handler.on_source_decoded(Operand::gpr(ttttt))?;
5563
5564                    if minbits == 0b001 {
5565                        static OPS: [Option<Opcode>; 16] = [
5566                            None, Some(Opcode::Vrmaxh), Some(Opcode::Vrmaxw), None,
5567                            None, Some(Opcode::Vrminh), Some(Opcode::Vrminw), None,
5568                            None, Some(Opcode::Vrmaxuh), Some(Opcode::Vrmaxuw), None,
5569                            None, Some(Opcode::Vrminuh), Some(Opcode::Vrminuw), Some(Opcode::Vrcnegh),
5570                        ];
5571                        let op_hi = (inst >> 13) & 1;
5572                        let op = op_bits | (op_hi << 3);
5573                        let op = decode_opcode!(OPS[op as usize]);
5574                        handler.on_opcode_decoded(op)?;
5575                        if op == Opcode::Vrcnegh {
5576                            handler.assign_mode(AssignMode::AddAssign)?;
5577                        }
5578                        return Ok(());
5579                    } else if minbits == 0b101 {
5580                        handler.on_opcode_decoded(Opcode::Vrcrotate)?;
5581                        handler.assign_mode(AssignMode::AddAssign)?;
5582                        let i_lo = (inst >> 5) & 1;
5583                        let i_hi = (inst >> 13) & 1;
5584                        let ii = i_lo | (i_hi << 1);
5585                        handler.on_source_decoded(Operand::imm_u8(ii as u8))?;
5586                        return Ok(());
5587                    }
5588
5589                    let assign_mode = match minbits {
5590                        0b000 => AssignMode::OrAssign,
5591                        0b010 => AssignMode::AndAssign,
5592                        0b011 => AssignMode::XorAssign,
5593                        0b100 => AssignMode::SubAssign,
5594                        0b110 => AssignMode::AddAssign,
5595                        _ => {
5596                            return Err(DecodeError::InvalidOpcode);
5597                        }
5598                    };
5599                    let opc = match op_bits >> 1 {
5600                        0b00 => Opcode::Asr,
5601                        0b01 => Opcode::Lsr,
5602                        0b10 => Opcode::Asl,
5603                        _ => Opcode::Lsl,
5604                    };
5605                    handler.on_opcode_decoded(opc)?;
5606                    handler.assign_mode(assign_mode)?;
5607                }
5608                0b1100 => {
5609                    let minbits = (inst >> 22) & 0b11;
5610                    let op_bits = (inst >> 6) & 0b11;
5611                    let xxxxx = reg_b0(inst);
5612                    let ttttt = reg_b8(inst);
5613                    let sssss = reg_b16(inst);
5614
5615                    let assign_mode = match minbits {
5616                        0b00 => AssignMode::OrAssign,
5617                        0b01 => AssignMode::AndAssign,
5618                        0b10 => AssignMode::SubAssign,
5619                        0b11 => AssignMode::AddAssign,
5620                        _ => {
5621                            return Err(DecodeError::InvalidOpcode);
5622                        }
5623                    };
5624                    let opc = match op_bits {
5625                        0b00 => Opcode::Asr,
5626                        0b01 => Opcode::Lsr,
5627                        0b10 => Opcode::Asl,
5628                        _ => Opcode::Lsl,
5629                    };
5630                    handler.on_opcode_decoded(opc)?;
5631                    handler.assign_mode(assign_mode)?;
5632                    handler.on_dest_decoded(Operand::gpr(xxxxx))?;
5633                    handler.on_source_decoded(Operand::gpr(sssss))?;
5634                    handler.on_source_decoded(Operand::gpr(ttttt))?;
5635                }
5636                0b1101 |
5637                0b1110 |
5638                _ => { /* 0b1111 */
5639                    opcode_check!(false);
5640                }
5641            }
5642        }
5643        0b1101 => {
5644            let opc_hi = (inst >> 24) & 0b1111;
5645            let ddddd = reg_b0(inst);
5646            let ttttt = reg_b8(inst);
5647            let sssss = reg_b16(inst);
5648
5649            match opc_hi {
5650                0b0000 => {
5651                    handler.on_dest_decoded(Operand::gpr(ddddd))?;
5652                    handler.on_source_decoded(Operand::gprpair(sssss)?)?;
5653                    handler.on_source_decoded(Operand::gprpair(ttttt)?)?;
5654                    handler.on_opcode_decoded(Opcode::Parity)?;
5655                }
5656                0b0001 => {
5657                    let uu = ((inst >> 5) & 0b11) as u8;
5658                    handler.on_dest_decoded(Operand::gprpair(ddddd)?)?;
5659                    handler.on_source_decoded(Operand::pred(uu))?;
5660                    handler.on_source_decoded(Operand::gprpair(sssss)?)?;
5661                    handler.on_source_decoded(Operand::gprpair(ttttt)?)?;
5662                    handler.on_opcode_decoded(Opcode::Vmux)?;
5663                }
5664                0b0010 => {
5665                    let vector = inst & 0x80_00_00 == 0;
5666
5667                    let ophi = (inst >> 13) & 1;
5668                    let oplo = (inst >> 5) & 0b111;
5669                    let opc = oplo | (ophi << 3);
5670                    let dd = (ddddd & 0b11) as u8;
5671
5672                    if vector {
5673                        handler.on_dest_decoded(Operand::pred(dd))?;
5674                        handler.on_source_decoded(Operand::gprpair(sssss)?)?;
5675                        if opc != 0b1011 {
5676                            handler.on_source_decoded(Operand::gprpair(ttttt)?)?;
5677                        } else {
5678                            handler.on_source_decoded(Operand::gpr(ttttt))?;
5679                        }
5680
5681                        match opc {
5682                            0b0000 => {
5683                                handler.on_opcode_decoded(Opcode::VcmpwEq)?;
5684                            }
5685                            0b0001 => {
5686                                handler.on_opcode_decoded(Opcode::VcmpwGt)?;
5687                            }
5688                            0b0010 => {
5689                                handler.on_opcode_decoded(Opcode::VcmpwGtu)?;
5690                            }
5691                            0b0011 => {
5692                                handler.on_opcode_decoded(Opcode::VcmphEq)?;
5693                            }
5694                            0b0100 => {
5695                                handler.on_opcode_decoded(Opcode::VcmphGt)?;
5696                            }
5697                            0b0101 => {
5698                                handler.on_opcode_decoded(Opcode::VcmphGtu)?;
5699                            }
5700                            0b0110 => {
5701                                handler.on_opcode_decoded(Opcode::VcmpbEq)?;
5702                            }
5703                            0b0111 => {
5704                                handler.on_opcode_decoded(Opcode::VcmpbGtu)?;
5705                            }
5706                            0b1000 => {
5707                                handler.on_opcode_decoded(Opcode::Any8VcmpbEq)?;
5708                            }
5709                            0b1001 => {
5710                                handler.on_opcode_decoded(Opcode::Any8VcmpbEq)?;
5711                                handler.negate_result()?;
5712                            }
5713                            0b1010 => {
5714                                handler.on_opcode_decoded(Opcode::VcmpbGt)?;
5715                            }
5716                            0b1011 => {
5717                                handler.on_opcode_decoded(Opcode::Tlbmatch)?;
5718                            }
5719                            0b1100 => {
5720                                handler.on_opcode_decoded(Opcode::Boundscheck)?;
5721                                handler.raw_mode(RawMode::Lo)?;
5722                            }
5723                            0b1101 => {
5724                                handler.on_opcode_decoded(Opcode::Boundscheck)?;
5725                                handler.raw_mode(RawMode::Hi)?;
5726                            }
5727                            _ => {
5728                                return Err(DecodeError::InvalidOpcode);
5729                            }
5730                        }
5731                    } else {
5732                        opcode_check!(inst & 0x00_60_00_00 == 0);
5733                        handler.on_dest_decoded(Operand::pred(dd))?;
5734                        handler.on_source_decoded(Operand::gprpair(sssss)?)?;
5735                        handler.on_source_decoded(Operand::gprpair(ttttt)?)?;
5736
5737                        match oplo {
5738                            0b000 => {
5739                                handler.on_opcode_decoded(Opcode::CmpGt)?;
5740                            }
5741                            0b010 => {
5742                                handler.on_opcode_decoded(Opcode::CmpEq)?;
5743                            }
5744                            0b0100 => {
5745                                handler.on_opcode_decoded(Opcode::CmpGtu)?;
5746                            }
5747                            _ => {
5748                                opcode_check!(false);
5749                            }
5750                        }
5751                    }
5752                }
5753
5754                0b0011 => {
5755                    // 1101|0011
5756                    let ddddd = reg_b0(inst);
5757                    let ttttt = reg_b8(inst);
5758                    let sssss = reg_b16(inst);
5759
5760                    let op_lo = ((inst >> 5) & 0b111) as u8;
5761                    let op_hi = ((inst >> 21) & 0b111) as u8;
5762
5763                    type OpRes = Result<Operand, DecodeError>;
5764
5765                    let do_decode_dst = |handler: &mut H, op: Opcode, dest: fn(u8) -> OpRes, op1: fn(u8) -> OpRes, op2: fn(u8) -> OpRes| {
5766                        handler.on_opcode_decoded(op)?;
5767                        handler.on_dest_decoded(dest(ddddd)?)?;
5768                        handler.on_source_decoded(op1(sssss)?)?;
5769                        handler.on_source_decoded(op2(ttttt)?)?;
5770                        Ok::<(), DecodeError>(())
5771                    };
5772
5773                    let do_decode_dts = |handler: &mut H, op: Opcode, dest: fn(u8) -> OpRes, op1: fn(u8) -> OpRes, op2: fn(u8) -> OpRes| {
5774                        handler.on_opcode_decoded(op)?;
5775                        handler.on_dest_decoded(dest(ddddd)?)?;
5776                        handler.on_source_decoded(op1(ttttt)?)?;
5777                        handler.on_source_decoded(op2(sssss)?)?;
5778                        Ok::<(), DecodeError>(())
5779                    };
5780
5781                    let opc = op_lo | (op_hi << 3);
5782                    match opc {
5783                        0b000000 => {
5784                            do_decode_dst(handler, Opcode::Vaddub, Operand::gprpair, Operand::gprpair, Operand::gprpair)?;
5785                        }
5786                        0b000001 => {
5787                            do_decode_dst(handler, Opcode::Vaddub, Operand::gprpair, Operand::gprpair, Operand::gprpair)?;
5788                            handler.saturate()?;
5789                        }
5790                        0b000010 => {
5791                            do_decode_dst(handler, Opcode::Vaddh, Operand::gprpair, Operand::gprpair, Operand::gprpair)?;
5792                        }
5793                        0b000011 => {
5794                            do_decode_dst(handler, Opcode::Vaddh, Operand::gprpair, Operand::gprpair, Operand::gprpair)?;
5795                            handler.saturate()?;
5796                        }
5797                        0b000100 => {
5798                            do_decode_dst(handler, Opcode::Vadduh, Operand::gprpair, Operand::gprpair, Operand::gprpair)?;
5799                            handler.saturate()?;
5800                        }
5801                        0b000101 => {
5802                            do_decode_dst(handler, Opcode::Vaddw, Operand::gprpair, Operand::gprpair, Operand::gprpair)?;
5803                        }
5804                        0b000110 => {
5805                            do_decode_dst(handler, Opcode::Vaddw, Operand::gprpair, Operand::gprpair, Operand::gprpair)?;
5806                            handler.saturate()?;
5807                        }
5808                        0b000111 => {
5809                            do_decode_dst(handler, Opcode::Add, Operand::gprpair, Operand::gprpair, Operand::gprpair)?;
5810                        }
5811                        0b001000 => {
5812                            do_decode_dts(handler, Opcode::Vsubub, Operand::gprpair, Operand::gprpair, Operand::gprpair)?;
5813                        }
5814                        0b001001 => {
5815                            do_decode_dts(handler, Opcode::Vsubub, Operand::gprpair, Operand::gprpair, Operand::gprpair)?;
5816                            handler.saturate()?;
5817                        }
5818                        0b001010 => {
5819                            do_decode_dts(handler, Opcode::Vsubh, Operand::gprpair, Operand::gprpair, Operand::gprpair)?;
5820                        }
5821                        0b001011 => {
5822                            do_decode_dts(handler, Opcode::Vsubh, Operand::gprpair, Operand::gprpair, Operand::gprpair)?;
5823                            handler.saturate()?;
5824                        }
5825                        0b001100 => {
5826                            do_decode_dts(handler, Opcode::Vsubuh, Operand::gprpair, Operand::gprpair, Operand::gprpair)?;
5827                            handler.saturate()?;
5828                        }
5829                        0b001101 => {
5830                            do_decode_dts(handler, Opcode::Vsubw, Operand::gprpair, Operand::gprpair, Operand::gprpair)?;
5831                        }
5832                        0b001110 => {
5833                            do_decode_dts(handler, Opcode::Vsubw, Operand::gprpair, Operand::gprpair, Operand::gprpair)?;
5834                            handler.saturate()?;
5835                        }
5836                        0b001111 => {
5837                            do_decode_dts(handler, Opcode::Sub, Operand::gprpair, Operand::gprpair, Operand::gprpair)?;
5838                        }
5839                        0b010000 => {
5840                            do_decode_dst(handler, Opcode::Vavgub, Operand::gprpair, Operand::gprpair, Operand::gprpair)?;
5841                        }
5842                        0b010001 => {
5843                            do_decode_dst(handler, Opcode::Vavgub, Operand::gprpair, Operand::gprpair, Operand::gprpair)?;
5844                            handler.rounded(RoundingMode::Round)?;
5845                        }
5846                        0b010010 => {
5847                            do_decode_dst(handler, Opcode::Vavgh, Operand::gprpair, Operand::gprpair, Operand::gprpair)?;
5848                        }
5849                        0b010011 => {
5850                            do_decode_dst(handler, Opcode::Vavgh, Operand::gprpair, Operand::gprpair, Operand::gprpair)?;
5851                            handler.rounded(RoundingMode::Round)?;
5852                        }
5853                        0b010100 => {
5854                            do_decode_dst(handler, Opcode::Vavgh, Operand::gprpair, Operand::gprpair, Operand::gprpair)?;
5855                            handler.rounded(RoundingMode::Cround)?;
5856                        }
5857                        0b010101 => {
5858                            do_decode_dst(handler, Opcode::Vavguh, Operand::gprpair, Operand::gprpair, Operand::gprpair)?;
5859                        }
5860                        0b010110 | 0b010111 => {
5861                            do_decode_dst(handler, Opcode::Vavguh, Operand::gprpair, Operand::gprpair, Operand::gprpair)?;
5862                            handler.rounded(RoundingMode::Round)?;
5863                        }
5864                        0b011000 => {
5865                            do_decode_dst(handler, Opcode::Vavgw, Operand::gprpair, Operand::gprpair, Operand::gprpair)?;
5866                        }
5867                        0b011001 => {
5868                            do_decode_dst(handler, Opcode::Vavgw, Operand::gprpair, Operand::gprpair, Operand::gprpair)?;
5869                            handler.rounded(RoundingMode::Round)?;
5870                        }
5871                        0b011010 => {
5872                            do_decode_dst(handler, Opcode::Vavgw, Operand::gprpair, Operand::gprpair, Operand::gprpair)?;
5873                            handler.rounded(RoundingMode::Cround)?;
5874                        }
5875                        0b011011 => {
5876                            do_decode_dst(handler, Opcode::Vavguw, Operand::gprpair, Operand::gprpair, Operand::gprpair)?;
5877                        }
5878                        0b011100 => {
5879                            do_decode_dst(handler, Opcode::Vavguw, Operand::gprpair, Operand::gprpair, Operand::gprpair)?;
5880                            handler.rounded(RoundingMode::Round)?;
5881                        }
5882                        0b011101 => {
5883                            do_decode_dst(handler, Opcode::Add, Operand::gprpair, Operand::gprpair, Operand::gprpair)?;
5884                            handler.saturate()?;
5885                        }
5886                        0b011110 => {
5887                            do_decode_dst(handler, Opcode::Add, Operand::gprpair, Operand::gprpair, Operand::gprpair)?;
5888                            handler.raw_mode(RawMode::Lo)?;
5889                        }
5890                        0b011111 => {
5891                            do_decode_dst(handler, Opcode::Add, Operand::gprpair, Operand::gprpair, Operand::gprpair)?;
5892                            handler.raw_mode(RawMode::Hi)?;
5893                        }
5894                        0b100000 => {
5895                            do_decode_dts(handler, Opcode::Vnavgh, Operand::gprpair, Operand::gprpair, Operand::gprpair)?;
5896                        }
5897                        0b100001 => {
5898                            do_decode_dts(handler, Opcode::Vnavgh, Operand::gprpair, Operand::gprpair, Operand::gprpair)?;
5899                            handler.rounded(RoundingMode::Round)?;
5900                            handler.saturate()?;
5901                        }
5902                        0b100010 => {
5903                            do_decode_dts(handler, Opcode::Vnavgh, Operand::gprpair, Operand::gprpair, Operand::gprpair)?;
5904                            handler.rounded(RoundingMode::Cround)?;
5905                            handler.saturate()?;
5906                        }
5907                        0b100011 => {
5908                            do_decode_dts(handler, Opcode::Vnavgw, Operand::gprpair, Operand::gprpair, Operand::gprpair)?;
5909                        }
5910                        // low bit of opc is `-`
5911                        0b100100 | 0b100101 => {
5912                            do_decode_dts(handler, Opcode::Vnavgw, Operand::gprpair, Operand::gprpair, Operand::gprpair)?;
5913                            handler.rounded(RoundingMode::Round)?;
5914                            handler.saturate()?;
5915                        }
5916                        // low bit of opc is `-`
5917                        0b100110 | 0b100111  => {
5918                            do_decode_dts(handler, Opcode::Vnavgw, Operand::gprpair, Operand::gprpair, Operand::gprpair)?;
5919                            handler.rounded(RoundingMode::Cround)?;
5920                            handler.saturate()?;
5921                        }
5922                        0b101000 => {
5923                            do_decode_dts(handler, Opcode::Vminub, Operand::gprpair, Operand::gprpair, Operand::gprpair)?;
5924                        }
5925                        0b101001 => {
5926                            do_decode_dts(handler, Opcode::Vminh, Operand::gprpair, Operand::gprpair, Operand::gprpair)?;
5927                        }
5928                        0b101010 => {
5929                            do_decode_dts(handler, Opcode::Vminuh, Operand::gprpair, Operand::gprpair, Operand::gprpair)?;
5930                        }
5931                        0b101011 => {
5932                            do_decode_dts(handler, Opcode::Vminw, Operand::gprpair, Operand::gprpair, Operand::gprpair)?;
5933                        }
5934                        0b101100 => {
5935                            do_decode_dts(handler, Opcode::Vminuw, Operand::gprpair, Operand::gprpair, Operand::gprpair)?;
5936                        }
5937                        0b101101 => {
5938                            do_decode_dts(handler, Opcode::Vmaxuw, Operand::gprpair, Operand::gprpair, Operand::gprpair)?;
5939                        }
5940                        0b101110 => {
5941                            do_decode_dts(handler, Opcode::Min, Operand::gprpair, Operand::gprpair, Operand::gprpair)?;
5942                        }
5943                        0b101111 => {
5944                            do_decode_dts(handler, Opcode::Minu, Operand::gprpair, Operand::gprpair, Operand::gprpair)?;
5945                        }
5946                        0b110000 => {
5947                            do_decode_dts(handler, Opcode::Vmaxub, Operand::gprpair, Operand::gprpair, Operand::gprpair)?;
5948                        }
5949                        0b110001 => {
5950                            do_decode_dts(handler, Opcode::Vmaxh, Operand::gprpair, Operand::gprpair, Operand::gprpair)?;
5951                        }
5952                        0b110010 => {
5953                            do_decode_dts(handler, Opcode::Vmaxuh, Operand::gprpair, Operand::gprpair, Operand::gprpair)?;
5954                        }
5955                        0b110011 => {
5956                            do_decode_dts(handler, Opcode::Vmaxw, Operand::gprpair, Operand::gprpair, Operand::gprpair)?;
5957                        }
5958                        0b110100 => {
5959                            do_decode_dst(handler, Opcode::Max, Operand::gprpair, Operand::gprpair, Operand::gprpair)?;
5960                        }
5961                        0b110101 => {
5962                            do_decode_dst(handler, Opcode::Maxu, Operand::gprpair, Operand::gprpair, Operand::gprpair)?;
5963                        }
5964                        0b110110 => {
5965                            do_decode_dts(handler, Opcode::Vmaxb, Operand::gprpair, Operand::gprpair, Operand::gprpair)?;
5966                        }
5967                        0b110111 => {
5968                            do_decode_dts(handler, Opcode::Vminb, Operand::gprpair, Operand::gprpair, Operand::gprpair)?;
5969                        }
5970                        0b111000 => {
5971                            do_decode_dst(handler, Opcode::And, Operand::gprpair, Operand::gprpair, Operand::gprpair)?;
5972                        }
5973                        0b111001 => {
5974                            do_decode_dst(handler, Opcode::And_RnR, Operand::gprpair, Operand::gprpair, Operand::gprpair)?;
5975                        }
5976                        0b111010 => {
5977                            do_decode_dst(handler, Opcode::Or, Operand::gprpair, Operand::gprpair, Operand::gprpair)?;
5978                        }
5979                        0b111011 => {
5980                            do_decode_dst(handler, Opcode::Or_RnR, Operand::gprpair, Operand::gprpair, Operand::gprpair)?;
5981                        }
5982                        0b111100 => {
5983                            do_decode_dst(handler, Opcode::Xor, Operand::gprpair, Operand::gprpair, Operand::gprpair)?;
5984                        }
5985                        0b111111 => {
5986                            handler.on_opcode_decoded(Opcode::Modwrap)?;
5987                            handler.on_dest_decoded(Operand::gpr(ddddd))?;
5988                            handler.on_source_decoded(Operand::gpr(sssss))?;
5989                            handler.on_source_decoded(Operand::gpr(ttttt))?;
5990                        }
5991                        _ => {
5992                            return Err(DecodeError::InvalidOpcode);
5993                        }
5994                    }
5995                }
5996                0b0100 => {
5997                    // 1101|0100
5998                    let ddddd = reg_b0(inst);
5999                    let ttttt = reg_b8(inst);
6000                    let sssss = reg_b16(inst);
6001
6002                    opcode_check!((inst >> 21) & 1 == 1);
6003
6004                    handler.on_opcode_decoded(Opcode::Bitsplit)?;
6005                    handler.on_dest_decoded(Operand::gprpair(ddddd)?)?;
6006                    handler.on_source_decoded(Operand::gpr(sssss))?;
6007                    handler.on_source_decoded(Operand::gpr(ttttt))?;
6008                }
6009                0b0101 => {
6010                    // 1101|0101
6011                    let ddddd = reg_b0(inst);
6012                    let ttttt = reg_b8(inst);
6013                    let sssss = reg_b16(inst);
6014
6015                    let op_hi = (inst >> 21) & 0b111;
6016                    let op_lo = (inst >> 5) & 0b111;
6017
6018                    if op_hi < 0b100 {
6019                        let addsub = op_hi & 0b001;
6020                        let shl = op_hi & 0b010 != 0;
6021                        let sat = op_lo & 0b100 != 0;
6022
6023                        handler.on_dest_decoded(Operand::gpr(ddddd))?;
6024
6025                        if addsub == 0 {
6026                            handler.on_opcode_decoded(Opcode::Add)?;
6027                        } else {
6028                            handler.on_opcode_decoded(Opcode::Sub)?;
6029                        }
6030
6031                        if sat {
6032                            handler.saturate()?;
6033                        }
6034
6035                        if shl {
6036                            // 1101|0101|X1X|sssss|PP|-ttttt|xxx|ddddd
6037                            handler.shift_left(16)?;
6038                            if op_lo & 0b010 == 0 {
6039                                handler.on_source_decoded(Operand::gpr_low(ttttt))?;
6040                            } else {
6041                                handler.on_source_decoded(Operand::gpr_high(ttttt))?;
6042                            }
6043                            if op_lo & 0b001 == 0 {
6044                                handler.on_source_decoded(Operand::gpr_low(sssss))?;
6045                            } else {
6046                                handler.on_source_decoded(Operand::gpr_high(sssss))?;
6047                            }
6048                        } else {
6049                            // 1101|0101|X0X|sssss|PP|-ttttt|xxx|ddddd
6050                            handler.on_source_decoded(Operand::gpr_low(ttttt))?;
6051                            if op_lo & 0b010 == 0 {
6052                                handler.on_source_decoded(Operand::gpr_low(sssss))?;
6053                            } else {
6054                                handler.on_source_decoded(Operand::gpr_high(sssss))?;
6055                            }
6056                        }
6057                    } else {
6058                        handler.on_dest_decoded(Operand::gpr(ddddd))?;
6059                        let op = ((inst >> 7) & 1) | (op_hi & 0b11) << 1;
6060                        if op == 0b001 {
6061                            handler.on_source_decoded(Operand::gpr(ttttt))?;
6062                            handler.on_source_decoded(Operand::gpr(sssss))?;
6063                        } else {
6064                            handler.on_source_decoded(Operand::gpr(sssss))?;
6065                            handler.on_source_decoded(Operand::gpr(ttttt))?;
6066                        }
6067                        match op {
6068                            0b000 => {
6069                                handler.on_opcode_decoded(Opcode::Add)?;
6070                                handler.saturate()?;
6071                                handler.deprecated()?;
6072                            }
6073                            0b001 => {
6074                                handler.on_opcode_decoded(Opcode::Sub)?;
6075                                handler.saturate()?;
6076                                handler.deprecated()?;
6077                            }
6078                            0b010 => {
6079                                handler.on_opcode_decoded(Opcode::Min)?;
6080                            }
6081                            0b011 => {
6082                                handler.on_opcode_decoded(Opcode::Minu)?;
6083                            }
6084                            0b100 => {
6085                                handler.on_opcode_decoded(Opcode::Max)?;
6086                            }
6087                            0b101 => {
6088                                handler.on_opcode_decoded(Opcode::Maxu)?;
6089                            }
6090                            _o => {
6091                                handler.on_opcode_decoded(Opcode::Parity)?;
6092                            }
6093                        }
6094                    }
6095                }
6096                0b0110 => {
6097                    // 1101|0110
6098                    let op_hi = (inst >> 21) & 0b111;
6099                    let op_lo = (inst >> 5) & 0b111;
6100
6101                    if op_hi & 0b100 == 0 {
6102                        let i9 = (inst >> 5) & 0b1_1111_1111;
6103                        let i_hi = (inst >> 21) & 1;
6104                        let i = i9 | (i_hi << 9);
6105
6106                        handler.on_opcode_decoded(Opcode::SfMake)?;
6107                        handler.on_dest_decoded(Operand::gpr(reg_b0(inst)))?;
6108                        handler.on_source_decoded(Operand::imm_u16(i as u16))?;
6109                        if op_hi & 0b010 == 0 {
6110                            handler.rounded(RoundingMode::Pos)?;
6111                        } else {
6112                            handler.rounded(RoundingMode::Neg)?;
6113                        }
6114                    } else {
6115                        opcode_check!(op_hi == 0b111);
6116                        static OPCODES: [Option<Opcode>; 8] = [
6117                            Some(Opcode::DfCmpEq), Some(Opcode::DfCmpGt), None, Some(Opcode::DfCmpGe),
6118                            Some(Opcode::DfCmpUo), None, None, None,
6119                        ];
6120
6121                        handler.on_opcode_decoded(decode_opcode!(OPCODES[op_lo as usize]))?;
6122                        handler.on_dest_decoded(Operand::pred(reg_b0(inst) & 0b11))?;
6123                        handler.on_source_decoded(Operand::gprpair(reg_b16(inst))?)?;
6124                        handler.on_source_decoded(Operand::gprpair(reg_b8(inst))?)?;
6125                    }
6126                }
6127                0b0111 => {
6128                    // 1101|0111
6129                    let ddddd = reg_b0(inst);
6130                    let ttttt = reg_b8(inst);
6131                    let sssss = reg_b16(inst);
6132
6133                    opcode_check!(inst & 0x80_00_00 == 0);
6134
6135                    let i_lo = (inst >> 5) & 0b111;
6136                    let i_mid = (inst >> 13) & 0b1;
6137                    let i_hi = (inst >> 21) & 0b11;
6138                    let i = i_lo | (i_mid << 3) | (i_hi << 4);
6139
6140                    handler.on_opcode_decoded(Opcode::AddMpyi)?;
6141                    handler.on_dest_decoded(Operand::gpr(ddddd))?;
6142                    handler.on_source_decoded(
6143                        Operand::immext(i, extender, |i| Ok(Operand::imm_u8(i as u8)))?
6144                    )?;
6145                    handler.on_source_decoded(Operand::gpr(sssss))?;
6146                    handler.on_source_decoded(Operand::gpr(ttttt))?;
6147                }
6148                0b1000 => {
6149                    // 1101|1000
6150                    let lllll = reg_b0(inst);
6151                    let ddddd = reg_b8(inst);
6152                    let sssss = reg_b16(inst);
6153
6154                    let l_hi = ((inst >> 23) & 0b1) as u8;
6155                    let l = lllll | (l_hi << 5);
6156
6157                    let i_lo = (inst >> 5) & 0b111;
6158                    let i_mid = (inst >> 13) & 0b1;
6159                    let i_hi = (inst >> 21) & 0b11;
6160                    let i = i_lo | (i_mid << 3) | (i_hi << 4);
6161
6162                    handler.on_opcode_decoded(Opcode::AddMpyi)?;
6163                    handler.on_dest_decoded(Operand::gpr(ddddd))?;
6164                    handler.on_source_decoded(
6165                        Operand::immext(i, extender, |i| Ok(Operand::imm_u8(i as u8)))?
6166                    )?;
6167                    handler.on_source_decoded(Operand::gpr(sssss))?;
6168                    handler.on_source_decoded(Operand::imm_u8(l as u8))?;
6169                }
6170                0b1001 => {
6171                    // 1101|1001
6172                    let ddddd = reg_b0(inst);
6173
6174                    let i9 = (inst >> 5) & 0b1_1111_1111;
6175                    let i_hi = (inst >> 21) & 1;
6176                    let i10 = i9 | (i_hi << 9);
6177                    let i = (i10 as u16) << 6 >> 6;
6178
6179                    let op = (inst >> 22) & 0b11;
6180
6181                    opcode_check!(op & 0b10 == 0);
6182
6183                    handler.on_dest_decoded(Operand::gpr(ddddd))?;
6184                    handler.on_opcode_decoded(Opcode::DfMake)?;
6185                    handler.on_source_decoded(Operand::imm_u16(i))?;
6186                    if op == 0 {
6187                        handler.rounded(RoundingMode::Pos)?;
6188                    } else {
6189                        handler.rounded(RoundingMode::Neg)?;
6190                    }
6191                }
6192                0b1010 => {
6193                    // 1101|1010
6194                    let uuuuu = reg_b0(inst);
6195                    let sssss = reg_b16(inst);
6196
6197                    let op = (inst >> 22) & 0b11;
6198
6199                    match op {
6200                        0b00 => {
6201                            let i9 = (inst >> 5) & 0b1_1111_1111;
6202                            let i_hi = (inst >> 21) & 1;
6203                            let i10 = i9 | (i_hi << 9);
6204                            let i = (i10 as i16) << 6 >> 6;
6205                            handler.on_opcode_decoded(Opcode::And)?;
6206                            handler.assign_mode(AssignMode::OrAssign)?;
6207                            handler.on_dest_decoded(Operand::gpr(uuuuu))?;
6208                            handler.on_source_decoded(Operand::gpr(sssss))?;
6209                            handler.on_source_decoded(Operand::imm_i16(i))?;
6210                        }
6211                        0b01 => {
6212                            let i9 = (inst >> 5) & 0b1_1111_1111;
6213                            let i_hi = (inst >> 21) & 1;
6214                            let i10 = i9 | (i_hi << 9);
6215                            handler.on_opcode_decoded(Opcode::OrAnd)?;
6216                            handler.on_dest_decoded(Operand::gpr(reg_b16(inst)))?;
6217                            handler.on_source_decoded(Operand::gpr(reg_b0(inst)))?;
6218                            handler.on_source_decoded(Operand::gpr(reg_b16(inst)))?;
6219                            handler.on_source_decoded(
6220                                Operand::immext(i10, extender, |i| Ok(Operand::imm_i16((i as i16) << 6 >> 6)))?
6221                            )?;
6222                        }
6223                        0b10 => {
6224                            let i9 = (inst >> 5) & 0b1_1111_1111;
6225                            let i_hi = (inst >> 21) & 1;
6226                            let i10 = i9 | (i_hi << 9);
6227                            let i = (i10 as i16) << 6 >> 6;
6228                            handler.on_opcode_decoded(Opcode::Or)?;
6229                            handler.assign_mode(AssignMode::OrAssign)?;
6230                            handler.on_dest_decoded(Operand::gpr(uuuuu))?;
6231                            handler.on_source_decoded(Operand::gpr(sssss))?;
6232                            handler.on_source_decoded(Operand::imm_i16(i))?;
6233                        }
6234                        _ => {
6235                            return Err(DecodeError::InvalidOpcode);
6236                        }
6237                    }
6238                }
6239                0b1011 => {
6240                    // 1101|1011
6241                    let uuuuu = reg_b0(inst);
6242                    let ddddd = reg_b8(inst);
6243                    let sssss = reg_b16(inst);
6244
6245                    let i_lo = (inst >> 5) & 0b111;
6246                    let i_mid = (inst >> 13) & 0b1;
6247                    let i_hi = (inst >> 21) & 0b11;
6248                    let i = i_lo | (i_mid << 3) | (i_hi << 4);
6249
6250                    let op = (inst >> 23) & 1;
6251
6252                    handler.on_dest_decoded(Operand::gpr(ddddd))?;
6253                    handler.on_source_decoded(Operand::gpr(sssss))?;
6254                    if op == 0 {
6255                        handler.on_opcode_decoded(Opcode::AddAdd)?;
6256                        handler.on_source_decoded(Operand::gpr(uuuuu))?;
6257                        handler.on_source_decoded(
6258                            Operand::immext(i, extender, |i| Ok(Operand::imm_i8((i as i8) << 2 >> 2)))?
6259                        )?;
6260                    } else {
6261                        handler.on_opcode_decoded(Opcode::AddSub)?;
6262                        handler.on_source_decoded(
6263                            Operand::immext(i, extender, |i| Ok(Operand::imm_i8((i as i8) << 2 >> 2)))?
6264                        )?;
6265                        handler.on_source_decoded(Operand::gpr(uuuuu))?;
6266                    }
6267                }
6268                0b1100 => {
6269                    // 1101|1100
6270                    let dd = (inst & 0b11) as u8;
6271                    let imm = (inst >> 5) & 0b1111_1111;
6272                    let sssss = reg_b16(inst);
6273                    let op_lo = (inst >> 3) & 0b11;
6274                    let op_hi = (inst >> 21) & 0b111;
6275                    let opc = op_lo | (op_hi << 2);
6276
6277                    handler.on_dest_decoded(Operand::pred(dd))?;
6278                    handler.on_source_decoded(Operand::gprpair(sssss)?)?;
6279                    if opc >= 0b10000 {
6280                        operand_check!(imm < 0b100000);
6281                    } else if opc >= 0b1000 {
6282                        operand_check!(imm < 0b10000000);
6283                    }
6284                    handler.on_source_decoded(Operand::imm_u8(imm as u8))?;
6285
6286                    const OPCODES: [Option<Opcode>; 32] = [
6287                        Some(Opcode::VcmpbEq), Some(Opcode::VcmphEq), Some(Opcode::VcmpwEq), None,
6288                        Some(Opcode::VcmpbGt), Some(Opcode::VcmphGt), Some(Opcode::VcmpwGt), None,
6289                        // 0b01000
6290                        Some(Opcode::VcmpbGtu), Some(Opcode::VcmphGtu), Some(Opcode::VcmpwGtu), None,
6291                        None, None, None, None,
6292                        // 0b10000
6293                        None, None, Some(DfClass), None,
6294                        None, None, None, None,
6295                        None, None, None, None,
6296                        None, None, None, None,
6297                    ];
6298
6299                    handler.on_opcode_decoded(decode_opcode!(OPCODES[opc as usize]))?;
6300                }
6301                0b1101 => {
6302                    let dd = (inst & 0b11) as u8;
6303                    let imm = (inst >> 5) & 0b1111_1111;
6304                    let sssss = reg_b16(inst);
6305                    let op_lo = ((inst >> 3) & 0b11) as u8;
6306                    let op_hi = ((inst >> 21) & 0b11) as u8;
6307
6308                    const OPCODES: [Option<Opcode>; 16] = [
6309                        Some(Opcode::CmpbGt), Some(Opcode::CmphGt), None, None,
6310                        Some(Opcode::CmpbEq), Some(Opcode::CmphEq), None, None,
6311                        Some(Opcode::CmpbGtu), Some(Opcode::CmphGtu), None, None,
6312                        None, None, None, None,
6313                    ];
6314
6315                    let opc = op_lo | (op_hi << 2);
6316
6317                    handler.on_opcode_decoded(decode_opcode!(OPCODES[opc as usize]))?;
6318                    handler.on_dest_decoded(Operand::pred(dd))?;
6319                    handler.on_source_decoded(Operand::gpr(sssss))?;
6320                    if opc & 0b10_00 != 0 {
6321                        operand_check!(imm < 0b1000_0000);
6322                    }
6323                    handler.on_source_decoded(
6324                        Operand::immext(imm, extender, |imm| Ok(Operand::imm_u8(imm as u8)))?
6325                    )?;
6326                }
6327                0b1110 => {
6328                    let xxxxx = reg_b16(inst);
6329                    let op_lo = (inst >> 1) & 0b11;
6330                    let op_hi = (inst >> 4) & 0b1;
6331                    let opc = op_lo | (op_hi << 2);
6332                    let i_lo = (inst >> 3) & 0b1;
6333                    let i_lo3 = (inst >> 5) & 0b111;
6334                    let i_mid = (inst >> 13) & 0b1;
6335                    let i_hi = (inst >> 21) & 0b11;
6336                    let i = i_lo | (i_lo3 << 1) | (i_mid << 4) | (i_hi << 6);
6337                    let u5 = reg_b8(inst);
6338
6339                    handler.on_dest_decoded(Operand::gpr(xxxxx))?;
6340                    handler.on_source_decoded(
6341                        Operand::immext(i, extender, |i| Ok(Operand::imm_u8(i as u8)))?
6342                    )?;
6343                    handler.on_source_decoded(Operand::gpr(xxxxx))?;
6344                    handler.on_source_decoded(Operand::imm_u8(u5))?;
6345
6346                    const OPCODES: [Opcode; 8] = [
6347                        AndAsl, OrAsl,
6348                        AddAsl, SubAsl,
6349                        AndLsr, OrLsr,
6350                        AddLsr, SubLsr,
6351                    ];
6352
6353                    handler.on_opcode_decoded(OPCODES[opc as usize])?;
6354                }
6355                0b1111 => {
6356                    let order = (inst >> 23) & 1;
6357                    let uuuuu = reg_b0(inst);
6358                    let ddddd = reg_b8(inst);
6359                    let sssss = reg_b16(inst);
6360                    let i_lo = (inst >> 5) & 0b111;
6361                    let i_mid = (inst >> 13) & 0b1;
6362                    let i_hi = (inst >> 21) & 0b11;
6363                    let i6 = (i_lo | (i_mid << 3) | (i_hi << 4)) as u8;
6364
6365                    handler.on_opcode_decoded(Opcode::AddMpyi)?;
6366                    handler.on_dest_decoded(Operand::gpr(ddddd))?;
6367                    handler.on_source_decoded(Operand::gpr(uuuuu))?;
6368
6369                    if order == 0 {
6370                        handler.on_source_decoded(Operand::imm_u8(i6 << 2))?;
6371                        handler.on_source_decoded(Operand::gpr(sssss))?;
6372                    } else {
6373                        handler.on_source_decoded(Operand::gpr(sssss))?;
6374                        handler.on_source_decoded(Operand::imm_u8(i6 << 2))?;
6375                    }
6376                }
6377                _ => {
6378                    todo!("other");
6379                },
6380            }
6381        }
6382        0b1110 => {
6383            let ddddd = reg_b0(inst);
6384            let ttttt = reg_b8(inst);
6385            let sssss = reg_b16(inst);
6386
6387            let opc = (inst >> 24) & 0b1111;
6388
6389            let op_hi = ((inst >> 21) & 0b111) as u8;
6390            let op_lo = ((inst >> 5) & 0b111) as u8;
6391
6392            match opc {
6393                0b0000 => {
6394                    // mpyi +/-
6395                    operand_check!(inst & 0b10_0000 == 0);
6396                    let i = (inst >> 5) & 0b1111_1111;
6397                    handler.on_dest_decoded(Operand::gpr(ddddd))?;
6398                    handler.on_source_decoded(Operand::gpr(sssss))?;
6399                    handler.on_source_decoded(Operand::imm_u8(i as u8))?;
6400                    if op_hi < 0b100 {
6401                        handler.on_opcode_decoded(Opcode::MpyiPos)?;
6402                    } else {
6403                        handler.on_opcode_decoded(Opcode::MpyiNeg)?;
6404                    }
6405                }
6406                0b0001 => {
6407                    // mpyi +/-
6408                    operand_check!(inst & 0b10_0000 == 0);
6409                    let i = (inst >> 5) & 0b1111_1111;
6410                    handler.on_opcode_decoded(Opcode::Mpyi)?;
6411                    handler.on_dest_decoded(Operand::gpr(reg_b0(inst)))?;
6412                    handler.on_source_decoded(Operand::gpr(sssss))?;
6413                    handler.on_source_decoded(Operand::immext(i, extender, |i| Ok(Operand::imm_u8(i as u8)))?)?;
6414                    if op_hi < 0b100 {
6415                        handler.assign_mode(AssignMode::AddAssign)?;
6416                    } else {
6417                        handler.assign_mode(AssignMode::SubAssign)?;
6418                    }
6419                }
6420                0b0010 => {
6421                    operand_check!(inst & 0b10_0000 == 0);
6422                    let i = (inst >> 5) & 0b1111_1111;
6423                    handler.on_opcode_decoded(Opcode::Add)?;
6424                    handler.on_dest_decoded(Operand::gpr(reg_b0(inst)))?;
6425                    handler.on_source_decoded(Operand::gpr(sssss))?;
6426                    handler.on_source_decoded(Operand::immext(i, extender, |i| Ok(Operand::imm_i8(i as i8)))?)?;
6427                    if op_hi < 0b100 {
6428                        handler.assign_mode(AssignMode::AddAssign)?;
6429                    } else {
6430                        handler.assign_mode(AssignMode::SubAssign)?;
6431                    }
6432                }
6433                0b0011 => {
6434                    let uuuuu = reg_b0(inst);
6435                    let yyyyy = reg_b8(inst);
6436                    handler.on_opcode_decoded(Opcode::AddMpyi)?;
6437                    handler.on_dest_decoded(Operand::gpr(yyyyy))?;
6438                    handler.on_source_decoded(Operand::gpr(uuuuu))?;
6439                    handler.on_source_decoded(Operand::gpr(yyyyy))?;
6440                    handler.on_source_decoded(Operand::gpr(sssss))?;
6441                }
6442                0b0100 => {
6443                    handler.on_dest_decoded(Operand::gprpair(ddddd)?)?;
6444                    let opbits = op_hi & 0b11;
6445                    match opbits {
6446                        0b00 => {
6447                            handler.on_opcode_decoded(Opcode::Mpy)?;
6448                        }
6449                        0b01 => {
6450                            handler.on_opcode_decoded(Opcode::Mpy)?;
6451                            handler.rounded(RoundingMode::Round)?;
6452                        }
6453                        0b10 => {
6454                            handler.on_opcode_decoded(Opcode::Mpyu)?;
6455                        }
6456                        _ => {
6457                            return Err(DecodeError::InvalidOpcode);
6458                        }
6459                    };
6460
6461                    if op_lo & 0b10 == 0 {
6462                        handler.on_source_decoded(Operand::gpr_low(sssss))?;
6463                    } else {
6464                        handler.on_source_decoded(Operand::gpr_high(sssss))?;
6465                    }
6466                    if op_lo & 0b01 == 0 {
6467                        handler.on_source_decoded(Operand::gpr_low(ttttt))?;
6468                    } else {
6469                        handler.on_source_decoded(Operand::gpr_high(ttttt))?;
6470                    }
6471
6472                    let shift = (op_hi >> 2) & 1;
6473                    if shift != 0 {
6474                        handler.shift_left(shift)?;
6475                    }
6476                }
6477                0b0101 => {
6478                    // some more mpy
6479
6480                    let opc = op_lo | (op_hi << 3);
6481
6482                    handler.on_dest_decoded(Operand::gprpair(ddddd)?)?;
6483
6484                    let masked = opc & 0b011_111;
6485                    if masked == 0b00101 {
6486                        handler.on_opcode_decoded(Opcode::Vmpyh)?;
6487                        handler.on_source_decoded(Operand::gprpair(sssss)?)?;
6488                        handler.on_source_decoded(Operand::gprpair(ttttt)?)?;
6489                        let shift = opc >> 5;
6490                        if shift != 0 {
6491                            handler.shift_left((opc >> 5) as u8)?;
6492                        }
6493                        handler.saturate()?;
6494                        return Ok(());
6495                    }
6496
6497                    handler.on_source_decoded(Operand::gpr(sssss))?;
6498
6499                    if masked == 0b00110 {
6500                        handler.on_opcode_decoded(Opcode::Cmpy)?;
6501                        handler.on_source_decoded(Operand::gpr(ttttt))?;
6502                        handler.shift_left((opc >> 5) as u8)?;
6503                        handler.saturate()?;
6504                        return Ok(());
6505                    } else if masked == 0b00111 {
6506                        handler.on_opcode_decoded(Opcode::Vmpyhsu)?;
6507                        handler.on_source_decoded(Operand::gpr(ttttt))?;
6508                        handler.shift_left((opc >> 5) as u8)?;
6509                        handler.saturate()?;
6510                        return Ok(());
6511                    } else if masked == 0b10110 {
6512                        handler.on_opcode_decoded(Opcode::Cmpy)?;
6513                        handler.on_source_decoded(Operand::gpr_conjugate(ttttt))?;
6514                        handler.shift_left((opc >> 5) as u8)?;
6515                        handler.saturate()?;
6516                        return Ok(());
6517                    }
6518
6519                    handler.on_source_decoded(Operand::gpr(ttttt))?;
6520
6521                    static OPCODES: [Option<Opcode>; 64] = [
6522                        Some(Mpy), Some(Cmpyi), Some(Cmpyr), None, None, None, None, None,
6523                        None, None, None, None, None, None, None, None,
6524                        Some(Mpyu), Some(Vmpybsu), None, None, None, None, None, Some(Pmpyw),
6525                        None, None, None, None, None, None, None, None,
6526                        None, Some(Vmpybu), None, None, None, None, None, None,
6527                        None, None, None, None, None, None, None, None,
6528                        None, None, None, None, None, None, None, Some(Vpmpyh),
6529                        None, None, None, None, None, None, None, None,
6530                    ];
6531
6532                    handler.on_opcode_decoded(decode_opcode!(OPCODES[opc as usize]))?;
6533                }
6534                0b0110 => {
6535                    // 1110|0110...
6536
6537                    if op_hi & 0b010 == 0 {
6538                        handler.on_opcode_decoded(Opcode::Mpy)?;
6539                    } else {
6540                        handler.on_opcode_decoded(Opcode::Mpyu)?;
6541                    }
6542                    if op_hi & 0b001 == 0 {
6543                        handler.assign_mode(AssignMode::AddAssign)?;
6544                    } else {
6545                        handler.assign_mode(AssignMode::SubAssign)?;
6546                    }
6547
6548                    operand_check!(op_lo & 0b100 == 0);
6549                    handler.on_dest_decoded(Operand::gprpair(ddddd)?)?;
6550                    if op_lo & 0b10 == 0 {
6551                        handler.on_source_decoded(Operand::gpr_low(sssss))?;
6552                    } else {
6553                        handler.on_source_decoded(Operand::gpr_high(sssss))?;
6554                    }
6555                    if op_lo & 0b01 == 0 {
6556                        handler.on_source_decoded(Operand::gpr_low(ttttt))?;
6557                    } else {
6558                        handler.on_source_decoded(Operand::gpr_high(ttttt))?;
6559                    }
6560
6561                    handler.shift_left((op_hi >> 2) & 1)?;
6562                }
6563                0b0111 => {
6564                    opcode_check!(inst & 0b0010_0000_0000_0000 == 0);
6565                    let xxxxx = reg_b0(inst);
6566                    let ttttt = reg_b8(inst);
6567                    let sssss = reg_b16(inst);
6568
6569                    match op_lo {
6570                        0b000 => {
6571                            opcode_check!(op_hi & 0b100 == 0);
6572                            if op_hi & 0b010 == 0 {
6573                                handler.on_opcode_decoded(Opcode::Mpy)?;
6574                            } else {
6575                                handler.on_opcode_decoded(Opcode::Mpyu)?;
6576                            }
6577                            if op_hi & 0b001 == 0 {
6578                                handler.assign_mode(AssignMode::AddAssign)?;
6579                            } else {
6580                                handler.assign_mode(AssignMode::SubAssign)?;
6581                            }
6582                            handler.on_dest_decoded(Operand::gprpair(xxxxx)?)?;
6583                            handler.on_source_decoded(Operand::gpr(sssss))?;
6584                            handler.on_source_decoded(Operand::gpr(ttttt))?;
6585                        }
6586                        0b001 => {
6587                            handler.on_dest_decoded(Operand::gprpair(xxxxx)?)?;
6588                            if op_hi == 0b000 {
6589                                handler.on_source_decoded(Operand::gpr(sssss))?;
6590                                handler.on_source_decoded(Operand::gpr(ttttt))?;
6591                            } else {
6592                                handler.on_source_decoded(Operand::gprpair(sssss)?)?;
6593                                handler.on_source_decoded(Operand::gprpair(ttttt)?)?;
6594                            }
6595                            static OPCODES: [Option<Opcode>; 8] = [
6596                                Some(Cmpyi), Some(Vmpyh), None, None,
6597                                Some(Vmpybu), None, Some(Vmpybsu), None,
6598                            ];
6599                            handler.assign_mode(AssignMode::AddAssign)?;
6600                            handler.on_opcode_decoded(decode_opcode!(OPCODES[op_hi as usize]))?;
6601                        }
6602                        0b010 => {
6603                            opcode_check!(op_hi == 0);
6604                            handler.on_dest_decoded(Operand::gprpair(xxxxx)?)?;
6605                            handler.on_source_decoded(Operand::gpr(sssss))?;
6606                            handler.on_source_decoded(Operand::gpr(ttttt))?;
6607                            handler.assign_mode(AssignMode::AddAssign)?;
6608                            handler.on_opcode_decoded(Opcode::Cmpyr)?;
6609                        }
6610                        0b101 => {
6611                            handler.on_dest_decoded(Operand::gprpair(xxxxx)?)?;
6612                            handler.shift_left(op_hi >> 2)?;
6613                            handler.saturate()?;
6614                            handler.assign_mode(AssignMode::AddAssign)?;
6615
6616                            match op_hi & 0b11 {
6617                                0b00 => {
6618                                    handler.on_opcode_decoded(Opcode::Vmpyh)?;
6619                                    handler.on_source_decoded(Operand::gprpair(sssss)?)?;
6620                                    handler.on_source_decoded(Operand::gprpair(ttttt)?)?;
6621                                }
6622                                0b11 => {
6623                                    handler.on_opcode_decoded(Opcode::Vmpyhsu)?;
6624                                    handler.on_source_decoded(Operand::gpr(sssss))?;
6625                                    handler.on_source_decoded(Operand::gpr(ttttt))?;
6626                                }
6627                                _ => { return Err(DecodeError::InvalidOpcode); }
6628                            }
6629                        }
6630                        0b110 => {
6631                            handler.on_opcode_decoded(Opcode::Cmpy)?;
6632                            handler.on_dest_decoded(Operand::gprpair(xxxxx)?)?;
6633                            handler.on_source_decoded(Operand::gpr(sssss))?;
6634                            if op_hi & 0b010 == 0 {
6635                                handler.on_source_decoded(Operand::gpr(ttttt))?;
6636                            } else {
6637                                handler.on_source_decoded(Operand::gpr_conjugate(ttttt))?;
6638                            }
6639                            handler.assign_mode(AssignMode::AddAssign)?;
6640                            handler.shift_left(op_hi >> 2)?;
6641                            handler.saturate()?;
6642                        }
6643                        0b111 => {
6644                            handler.on_dest_decoded(Operand::gprpair(xxxxx)?)?;
6645                            handler.on_source_decoded(Operand::gpr(sssss))?;
6646                            if op_hi & 0b011 == 0b010 {
6647                                handler.on_source_decoded(Operand::gpr_conjugate(ttttt))?;
6648                            } else {
6649                                handler.on_source_decoded(Operand::gpr(ttttt))?;
6650                            }
6651                            match op_hi {
6652                                0b000 | 0b100 |
6653                                0b010 | 0b110 => {
6654                                    handler.assign_mode(AssignMode::SubAssign)?;
6655                                    handler.saturate()?;
6656                                    handler.on_opcode_decoded(Opcode::Cmpy)?;
6657                                    handler.shift_left(op_hi >> 2)?;
6658                                }
6659                                0b001 => {
6660                                    handler.assign_mode(AssignMode::XorAssign)?;
6661                                    handler.on_opcode_decoded(Opcode::Pmpyw)?;
6662                                }
6663                                0b101 => {
6664                                    handler.assign_mode(AssignMode::XorAssign)?;
6665                                    handler.on_opcode_decoded(Opcode::Vpmpyh)?;
6666                                }
6667                                _ => {
6668                                    return Err(DecodeError::InvalidOpcode);
6669                                }
6670                            }
6671                        }
6672                        _ => {
6673                            return Err(DecodeError::InvalidOpcode);
6674                        }
6675                    }
6676                }
6677                0b1000 => {
6678                    // 1110|1000
6679                    opcode_check!(inst & 0b0010_0000_0000_0000 == 0);
6680                    let ddddd = reg_b0(inst);
6681                    let ttttt = reg_b8(inst);
6682                    let sssss = reg_b16(inst);
6683
6684                    handler.on_dest_decoded(Operand::gprpair(ddddd)?)?;
6685
6686                    if op_lo & 0b100 == 0b100 || (op_lo == 0b010 && op_hi & 0b011 == 0b001) {
6687                        // all of these may have `<<N`, though some are only valid with `<<1`.
6688                        let n = (op_hi >> 2) & 1;
6689                        handler.shift_left(n)?;
6690                        handler.on_source_decoded(Operand::gprpair(sssss)?)?;
6691                        handler.on_source_decoded(Operand::gprpair(ttttt)?)?;
6692
6693                        if op_lo == 0b010 && op_hi & 0b011 == 0b001 {
6694                            handler.on_opcode_decoded(Vrmpywoh)?;
6695                        } else {
6696                            let opc = (op_lo & 0b11) | ((op_hi & 0b11) << 2);
6697                            match opc {
6698                                0b0000 => {
6699                                    handler.on_opcode_decoded(Vdmpy)?;
6700                                    handler.saturate()?;
6701                                }
6702                                0b0001 => {
6703                                    handler.on_opcode_decoded(Vmpyweh)?;
6704                                    handler.saturate()?;
6705                                }
6706                                0b0010 => {
6707                                    handler.on_opcode_decoded(Vmpyeh)?;
6708                                    handler.saturate()?;
6709                                }
6710                                0b0011 => {
6711                                    handler.on_opcode_decoded(Vmpywoh)?;
6712                                    handler.saturate()?;
6713                                }
6714                                0b0100 => {
6715                                    opcode_check!(op_hi & 0b100 != 0);
6716                                    handler.on_opcode_decoded(Vrcmpys)?;
6717                                    handler.saturate()?;
6718                                    handler.raw_mode(RawMode::Hi)?;
6719                                }
6720                                0b0101 => {
6721                                    handler.on_opcode_decoded(Vmpyweh)?;
6722                                    handler.saturate()?;
6723                                    handler.rounded(RoundingMode::Round)?;
6724                                }
6725                                0b0110 => {
6726                                    handler.on_opcode_decoded(Vcmpyr)?;
6727                                    handler.saturate()?;
6728                                }
6729                                0b0111 => {
6730                                    handler.on_opcode_decoded(Vmpywoh)?;
6731                                    handler.saturate()?;
6732                                    handler.rounded(RoundingMode::Round)?;
6733                                }
6734                                0b1000 => {
6735                                    handler.on_opcode_decoded(Vrmpywoh)?;
6736                                }
6737                                0b1001 => {
6738                                    handler.on_opcode_decoded(Vmpyweuh)?;
6739                                    handler.saturate()?;
6740                                }
6741                                0b1010 => {
6742                                    handler.on_opcode_decoded(Vcmpyi)?;
6743                                    handler.saturate()?;
6744                                }
6745                                0b1011 => {
6746                                    handler.on_opcode_decoded(Vmpywouh)?;
6747                                    handler.saturate()?;
6748                                }
6749                                0b1100 => {
6750                                    opcode_check!(inst & 0b100 != 0);
6751                                    handler.on_opcode_decoded(Vrcmpys)?;
6752                                    handler.saturate()?;
6753                                    handler.raw_mode(RawMode::Lo)?;
6754                                }
6755                                0b1101 => {
6756                                    handler.on_opcode_decoded(Vmpyweuh)?;
6757                                    handler.rounded(RoundingMode::Round)?;
6758                                    handler.saturate()?;
6759                                }
6760                                0b1111 => {
6761                                    handler.on_opcode_decoded(Vmpywouh)?;
6762                                    handler.rounded(RoundingMode::Round)?;
6763                                    handler.saturate()?;
6764                                }
6765                                _ => {
6766                                    return Err(DecodeError::InvalidOpcode);
6767                                }
6768                            }
6769                        }
6770                    } else {
6771                        static OPCODES: [Option<Opcode>; 32] = [
6772                            None, None, Some(Vrmpyh), Some(DfAdd),
6773                            Some(Vabsdiffw), None, None, Some(DfMax),
6774                            None, Some(Vraddub), Some(Vrsadub), Some(DfMpyfix),
6775                            Some(Vabsdiffh), None, Some(Cmpyiw), None,
6776                            None, Some(Vrmpyu), Some(Cmpyrw), Some(DfSub),
6777                            Some(Vabsdiffub), Some(Vdmpybsu), None, Some(DfMpyll),
6778                            None, Some(Vrmpysu), Some(Cmpyrw), Some(DfMin),
6779                            Some(Vabsdiffb), None, Some(Cmpyiw), None,
6780                        ];
6781                        let opc = (op_lo & 0b11) | (op_hi << 2);
6782                        handler.on_opcode_decoded(decode_opcode!(OPCODES[opc as usize]))?;
6783
6784                        if opc == 0b0101 || opc == 0b10101 {
6785                            handler.saturate()?;
6786                        }
6787
6788                        if (op_lo & 0b11) == 0b00 {
6789                            handler.on_source_decoded(Operand::gprpair(ttttt)?)?;
6790                            handler.on_source_decoded(Operand::gprpair(sssss)?)?;
6791                        } else if opc == 0b11010 || opc == 0b11110 {
6792                            handler.on_source_decoded(Operand::gprpair(sssss)?)?;
6793                            handler.on_source_decoded(Operand::gprpair_conjugate(ttttt)?)?;
6794                        } else {
6795                            handler.on_source_decoded(Operand::gprpair(sssss)?)?;
6796                            handler.on_source_decoded(Operand::gprpair(ttttt)?)?;
6797                        }
6798                    }
6799                }
6800                0b1001 => {
6801                    // 1110|1001
6802                    let opc = op_lo | (op_hi << 3);
6803
6804                    let mut rtt_star = false;
6805                    let mut saturate = true;
6806                    let mut shift_amt = 1;
6807
6808                    handler.on_dest_decoded(Operand::gpr(ddddd))?;
6809                    handler.on_source_decoded(Operand::gprpair(sssss)?)?;
6810
6811                    match opc {
6812                        o if o & 0b100011 == 0b000001 => {
6813                            handler.on_opcode_decoded(Opcode::Vradduh)?;
6814                            saturate = false;
6815                            shift_amt = 0;
6816                        }
6817                        o if o & 0b101111 == 0b001111 => {
6818                            handler.on_opcode_decoded(Opcode::Vraddh)?;
6819                            saturate = false;
6820                            shift_amt = 0;
6821                        }
6822                        0b000100 => {
6823                            handler.on_opcode_decoded(Opcode::Cmpyiw)?;
6824                            rtt_star = true;
6825                        }
6826                        0b001000 => {
6827                            handler.on_opcode_decoded(Opcode::Cmpyiw)?;
6828                        }
6829                        0b010000 => {
6830                            handler.on_opcode_decoded(Opcode::Cmpyrw)?;
6831                        }
6832                        0b011000 => {
6833                            handler.on_opcode_decoded(Opcode::Cmpyrw)?;
6834                            rtt_star = true;
6835                        }
6836                        o if o & 0b101111 == 0b101110 => {
6837                            handler.on_opcode_decoded(Opcode::Vrcmpys)?;
6838                            handler.rounded(RoundingMode::Round)?;
6839                            handler.raw_mode(RawMode::Hi)?;
6840                        }
6841                        o if o & 0b101111 == 0b101111 => {
6842                            handler.on_opcode_decoded(Opcode::Vrcmpys)?;
6843                            handler.rounded(RoundingMode::Round)?;
6844                            handler.raw_mode(RawMode::Lo)?;
6845                        }
6846                        0b100100 => {
6847                            handler.on_opcode_decoded(Opcode::Cmpyiw)?;
6848                            handler.rounded(RoundingMode::Round)?;
6849                            rtt_star = true;
6850                        }
6851                        0b101000 => {
6852                            handler.on_opcode_decoded(Opcode::Cmpyiw)?;
6853                            handler.rounded(RoundingMode::Round)?;
6854                        }
6855                        0b110000 => {
6856                            handler.on_opcode_decoded(Opcode::Cmpyrw)?;
6857                            handler.rounded(RoundingMode::Round)?;
6858                        }
6859                        0b111000 => {
6860                            handler.on_opcode_decoded(Opcode::Cmpyrw)?;
6861                            handler.rounded(RoundingMode::Round)?;
6862                            rtt_star = true;
6863                        }
6864                        o if o & 0b011111 == 0b000000 => {
6865                            handler.on_opcode_decoded(Opcode::Vdmpy)?;
6866                            handler.rounded(RoundingMode::Round)?;
6867                            if o & 0b100000 == 0 {
6868                                shift_amt = 0;
6869                            }
6870                        }
6871                        _other => {
6872                            return Err(DecodeError::InvalidOpcode);
6873                        }
6874                    }
6875
6876                    if saturate {
6877                        handler.saturate()?;
6878                    }
6879                    if shift_amt == 1 {
6880                        handler.shift_left(shift_amt)?;
6881                    }
6882                    if rtt_star {
6883                        handler.on_source_decoded(Operand::gprpair_conjugate(ttttt)?)?;
6884                    } else {
6885                        handler.on_source_decoded(Operand::gprpair(ttttt)?)?;
6886                    }
6887                }
6888                0b1010 => {
6889                    // 1110|1010
6890                    opcode_check!(inst & 0b0010_0000_0000_0000 == 0);
6891
6892                    let opc = op_lo | (op_hi << 3);
6893
6894                    handler.on_dest_decoded(Operand::gprpair(ddddd)?)?;
6895                    handler.on_source_decoded(Operand::gprpair(sssss)?)?;
6896                    let mut rtt_star = false;
6897                    let mut add_assign = true;
6898
6899                    match opc {
6900                        0b000010 => {
6901                            handler.on_opcode_decoded(Opcode::Vrmpyh)?;
6902                        }
6903                        0b000011 => {
6904                            handler.on_opcode_decoded(Opcode::DfMpylh)?;
6905                        }
6906                        0b001001 => {
6907                            handler.on_opcode_decoded(Opcode::Vdmpybsu)?;
6908                            handler.saturate()?;
6909                        }
6910                        0b001010 => {
6911                            handler.on_opcode_decoded(Opcode::Vmpyeh)?;
6912                        }
6913                        0b001100 => {
6914                            handler.on_opcode_decoded(Opcode::Vcmpyr)?;
6915                            handler.saturate()?;
6916                        }
6917                        0b010001 => {
6918                            handler.on_opcode_decoded(Opcode::Vraddub)?;
6919                        }
6920                        0b010010 => {
6921                            handler.on_opcode_decoded(Opcode::Vrsadub)?;
6922                        }
6923                        0b010100 => {
6924                            handler.on_opcode_decoded(Opcode::Vcmpyi)?;
6925                            handler.saturate()?;
6926                        }
6927                        0b010110 => {
6928                            handler.on_opcode_decoded(Opcode::Cmpyiw)?;
6929                            rtt_star = true;
6930                        }
6931                        0b011010 => {
6932                            handler.on_opcode_decoded(Opcode::Cmpyiw)?;
6933                        }
6934                        0b100001 => {
6935                            handler.on_opcode_decoded(Opcode::Vrmpybu)?;
6936                        }
6937                        0b100010 => {
6938                            handler.on_opcode_decoded(Opcode::Cmpyrw)?;
6939                        }
6940                        0b100011 => {
6941                            handler.on_opcode_decoded(Opcode::DfMpyhh)?;
6942                        }
6943                        o if o & 0b111100 == 0b101000 => {
6944                            handler.on_opcode_decoded(Opcode::Vacsh)?;
6945                            handler.on_dest_decoded(Operand::pred(o as u8 & 0b11))?;
6946                        }
6947                        0b101100 => {
6948                            handler.on_opcode_decoded(Opcode::Vrcmpys)?;
6949                            handler.shift_left(1)?;
6950                            handler.saturate()?;
6951                            handler.raw_mode(RawMode::Hi)?;
6952                        }
6953                        0b110001 => {
6954                            handler.on_opcode_decoded(Opcode::Vrmpybsu)?;
6955                        }
6956                        0b110010 => {
6957                            handler.on_opcode_decoded(Opcode::Cmpyrw)?;
6958                            rtt_star = true;
6959                        }
6960                        o if o & 0b111100 == 0b111000 => {
6961                            handler.on_opcode_decoded(Opcode::Vminub)?;
6962                            handler.on_dest_decoded(Operand::pred(o & 0b11))?;
6963                            add_assign = false;
6964                        }
6965                        0b111100 => {
6966                            handler.on_opcode_decoded(Opcode::Vrcmpys)?;
6967                            handler.shift_left(1)?;
6968                            handler.saturate()?;
6969                            handler.raw_mode(RawMode::Lo)?;
6970                        }
6971                        0b000_100 | 0b100_100 => {
6972                            handler.on_opcode_decoded(Opcode::Vdmpy)?;
6973                            handler.saturate()?;
6974                            handler.shift_left((opc >> 5) as u8)?;
6975                        }
6976                        0b000_101 | 0b100_101 => {
6977                            handler.on_opcode_decoded(Opcode::Vmpyweh)?;
6978                            handler.saturate()?;
6979                            handler.shift_left((opc >> 5) as u8)?;
6980                        }
6981                        0b000_110 | 0b100_110 => {
6982                            handler.on_opcode_decoded(Opcode::Vmpyeh)?;
6983                            handler.saturate()?;
6984                            handler.shift_left((opc >> 5) as u8)?;
6985                        }
6986                        0b000_111 | 0b100_111 => {
6987                            handler.on_opcode_decoded(Opcode::Vmpywoh)?;
6988                            handler.saturate()?;
6989                            handler.shift_left((opc >> 5) as u8)?;
6990                        }
6991                        0b001_101 | 0b101_101 => {
6992                            handler.on_opcode_decoded(Opcode::Vmpyweh)?;
6993                            handler.saturate()?;
6994                            handler.rounded(RoundingMode::Round)?;
6995                            handler.shift_left((opc >> 5) as u8)?;
6996                        }
6997                        0b001_110 | 0b101_110 => {
6998                            handler.on_opcode_decoded(Opcode::Vrmpyweh)?;
6999                            handler.shift_left((opc >> 5) as u8)?;
7000                        }
7001                        0b001_111 | 0b101_111 => {
7002                            handler.on_opcode_decoded(Opcode::Vmpywoh)?;
7003                            handler.saturate()?;
7004                            handler.rounded(RoundingMode::Round)?;
7005                            handler.shift_left((opc >> 5) as u8)?;
7006                        }
7007                        0b010_101 | 0b110_101 => {
7008                            handler.on_opcode_decoded(Opcode::Vmpyweuh)?;
7009                            handler.saturate()?;
7010                            handler.shift_left((opc >> 5) as u8)?;
7011                        }
7012                        0b010_111 | 0b110_111 => {
7013                            handler.on_opcode_decoded(Opcode::Vmpywouh)?;
7014                            handler.saturate()?;
7015                            handler.shift_left((opc >> 5) as u8)?;
7016                        }
7017                        0b011_101 | 0b111_101 => {
7018                            handler.on_opcode_decoded(Opcode::Vmpyweuh)?;
7019                            handler.saturate()?;
7020                            handler.rounded(RoundingMode::Round)?;
7021                            handler.shift_left((opc >> 5) as u8)?;
7022                        }
7023                        0b011_110 | 0b111_110 => {
7024                            handler.on_opcode_decoded(Opcode::Vrmpywoh)?;
7025                            handler.shift_left((opc >> 5) as u8)?;
7026                        }
7027                        0b011_111 | 0b111_111 => {
7028                            handler.on_opcode_decoded(Opcode::Vmpywouh)?;
7029                            handler.saturate()?;
7030                            handler.rounded(RoundingMode::Round)?;
7031                            handler.shift_left((opc >> 5) as u8)?;
7032                        }
7033                        _ => {
7034                            return Err(DecodeError::InvalidOpcode);
7035                        }
7036                    }
7037
7038                    if rtt_star {
7039                        handler.on_source_decoded(Operand::gprpair_conjugate(ttttt)?)?;
7040                    } else {
7041                        handler.on_source_decoded(Operand::gprpair(ttttt)?)?;
7042                    }
7043                    if add_assign {
7044                        handler.assign_mode(AssignMode::AddAssign)?;
7045                    }
7046                }
7047                0b1011 => {
7048                    // 1110|1011
7049                    opcode_check!(inst & 0b0010_0000_0000_0000 == 0);
7050                    handler.on_dest_decoded(Operand::gpr(ddddd))?;
7051                    handler.on_source_decoded(Operand::gpr(sssss))?;
7052                    handler.on_source_decoded(Operand::gpr(ttttt))?;
7053
7054                    let opc = op_lo | (op_hi << 3);
7055
7056                    match opc {
7057                        0b000_001 => {
7058                            handler.on_opcode_decoded(SfSub)?;
7059                        }
7060                        0b000_011 => {
7061                            handler.on_opcode_decoded(SfAdd)?;
7062                        }
7063                        0b010_000 => {
7064                            handler.on_opcode_decoded(SfMpy)?;
7065                        }
7066                        0b100_000 => {
7067                            handler.on_opcode_decoded(SfMax)?;
7068                        }
7069                        0b100_001 => {
7070                            handler.on_opcode_decoded(SfMin)?;
7071                        }
7072                        0b110_000 => {
7073                            handler.on_opcode_decoded(SfFixupn)?;
7074                        }
7075                        0b110_001 => {
7076                            handler.on_opcode_decoded(SfFixupd)?;
7077                        }
7078                        o if o >= 0b111100 => {
7079                            let ee = o & 0b11;
7080                            handler.on_opcode_decoded(SfRecipa)?;
7081                            handler.on_dest_decoded(Operand::pred(ee))?;
7082                        }
7083                        _ => {
7084                            opcode_check!(false);
7085                        }
7086                    }
7087                }
7088                0b1100 => {
7089                    handler.on_opcode_decoded(Opcode::Mpy)?;
7090                    handler.on_dest_decoded(Operand::gpr(ddddd))?;
7091                    if op_hi & 0b100 != 0 {
7092                        handler.shift_left(1)?;
7093                    }
7094                    opcode_check!(op_hi & 0b010 == 0);
7095                    if op_hi & 0b001 != 0 {
7096                        handler.rounded(RoundingMode::Round)?;
7097                    }
7098                    if op_lo & 0b100 != 0 {
7099                        handler.saturate()?;
7100                    }
7101                    if op_lo & 0b010 != 0 {
7102                        handler.on_source_decoded(Operand::gpr_high(sssss))?;
7103                    } else {
7104                        handler.on_source_decoded(Operand::gpr_low(sssss))?;
7105                    }
7106                    if op_lo & 0b001 != 0 {
7107                        handler.on_source_decoded(Operand::gpr_high(ttttt))?;
7108                    } else {
7109                        handler.on_source_decoded(Operand::gpr_low(ttttt))?;
7110                    }
7111                }
7112                0b1101 => {
7113                    // 1110|1101
7114                    opcode_check!(inst & 0b0010_0000_0000_0000 == 0);
7115
7116                    handler.on_dest_decoded(Operand::gpr(reg_b0(inst)))?;
7117                    handler.on_source_decoded(Operand::gpr(reg_b16(inst)))?;
7118
7119                    match op_lo {
7120                        0b000 => {
7121                            if op_hi == 0b000 {
7122                                handler.on_opcode_decoded(Opcode::Mpyi)?;
7123                                handler.on_source_decoded(Operand::gpr(reg_b8(inst)))?;
7124                            } else if op_hi == 0b101 {
7125                                handler.on_opcode_decoded(Opcode::Mpy)?;
7126                                handler.on_source_decoded(Operand::gpr_high(reg_b8(inst)))?;
7127                                handler.shift_left(1)?;
7128                                handler.saturate()?;
7129                            } else if op_hi == 0b111 {
7130                                handler.on_opcode_decoded(Opcode::Mpy)?;
7131                                handler.on_source_decoded(Operand::gpr(reg_b8(inst)))?;
7132                                handler.shift_left(1)?;
7133                                handler.saturate()?;
7134                            } else {
7135                                opcode_check!(false);
7136                            }
7137                        }
7138                        0b001 => {
7139                            match op_hi {
7140                                0b000 => {
7141                                    handler.on_opcode_decoded(Opcode::Mpy)?;
7142                                    handler.on_source_decoded(Operand::gpr(reg_b8(inst)))?;
7143                                }
7144                                0b001 => {
7145                                    handler.on_opcode_decoded(Opcode::Mpy)?;
7146                                    handler.rounded(RoundingMode::Round)?;
7147                                    handler.on_source_decoded(Operand::gpr(reg_b8(inst)))?;
7148                                }
7149                                0b010 => {
7150                                    handler.on_opcode_decoded(Opcode::Mpyu)?;
7151                                    handler.on_source_decoded(Operand::gpr(reg_b8(inst)))?;
7152                                }
7153                                0b011 => {
7154                                    handler.on_opcode_decoded(Opcode::Mpysu)?;
7155                                    handler.on_source_decoded(Operand::gpr(reg_b8(inst)))?;
7156                                }
7157                                0b101 => {
7158                                    handler.on_opcode_decoded(Opcode::Mpy)?;
7159                                    handler.on_source_decoded(Operand::gpr_low(reg_b8(inst)))?;
7160                                    handler.shift_left(1)?;
7161                                    handler.saturate()?;
7162                                }
7163                                _ => {
7164                                    opcode_check!(false);
7165                                }
7166                            }
7167                        }
7168                        0b010 => {
7169                            opcode_check!(op_hi == 0b101);
7170                            handler.on_opcode_decoded(Opcode::Mpy)?;
7171                            handler.on_source_decoded(Operand::gpr(reg_b8(inst)))?;
7172                            handler.shift_left(1)?;
7173                        }
7174                        0b100 => {
7175                            handler.on_opcode_decoded(Opcode::Mpy)?;
7176                            handler.shift_left(1)?;
7177                            handler.rounded(RoundingMode::Round)?;
7178                            handler.saturate()?;
7179                            if op_hi == 0b101 {
7180                                handler.on_source_decoded(Operand::gpr_high(reg_b8(inst)))?;
7181                            } else if op_hi == 0b111 {
7182                                handler.on_source_decoded(Operand::gpr_low(reg_b8(inst)))?;
7183                            } else {
7184                                opcode_check!(false);
7185                            }
7186                        }
7187                        0b110 => {
7188                            opcode_check!(op_hi & 0b001 == 0b001);
7189                            handler.on_opcode_decoded(Opcode::Cmpy)?;
7190                            handler.shift_left(op_hi >> 2)?;
7191                            if op_hi & 0b010 == 0 {
7192                                handler.on_source_decoded(Operand::gpr(reg_b8(inst)))?;
7193                            } else {
7194                                handler.on_source_decoded(Operand::gpr_conjugate(reg_b8(inst)))?;
7195                            }
7196                            handler.rounded(RoundingMode::Round)?;
7197                            handler.saturate()?;
7198                        }
7199                        0b111 => {
7200                            opcode_check!(op_hi & 0b011 == 0b001);
7201                            handler.on_opcode_decoded(Opcode::Vmpyh)?;
7202                            handler.shift_left(op_hi >> 2)?;
7203                            handler.on_dest_decoded(Operand::gpr(reg_b0(inst)))?;
7204                            handler.on_source_decoded(Operand::gpr(reg_b8(inst)))?;
7205                            handler.rounded(RoundingMode::Round)?;
7206                            handler.saturate()?;
7207                        }
7208                        _ => {
7209                            opcode_check!(false);
7210                        }
7211                    }
7212                }
7213                0b1110 => {
7214                    handler.on_opcode_decoded(Opcode::Mpy)?;
7215                    handler.on_dest_decoded(Operand::gpr(ddddd))?;
7216                    if op_hi & 0b100 != 0 {
7217                        handler.shift_left(1)?;
7218                    }
7219                    opcode_check!(op_hi & 0b010 == 0);
7220                    if op_hi & 0b001 == 0 {
7221                        handler.assign_mode(AssignMode::AddAssign)?;
7222                    } else {
7223                        handler.assign_mode(AssignMode::SubAssign)?;
7224                    }
7225                    if op_lo & 0b100 != 0 {
7226                        handler.saturate()?;
7227                    }
7228                    if op_lo & 0b010 != 0 {
7229                        handler.on_source_decoded(Operand::gpr_high(sssss))?;
7230                    } else {
7231                        handler.on_source_decoded(Operand::gpr_low(sssss))?;
7232                    }
7233                    if op_lo & 0b001 != 0 {
7234                        handler.on_source_decoded(Operand::gpr_high(ttttt))?;
7235                    } else {
7236                        handler.on_source_decoded(Operand::gpr_low(ttttt))?;
7237                    }
7238                }
7239                _ => { // only remaining pattern is 0b1111
7240                    opcode_check!(inst & 0b0010_0000_0000_0000 == 0);
7241
7242                    let opc = op_lo | (op_hi << 3);
7243
7244                    use AssignMode::*;
7245
7246                    static OPCODES: [Option<(AssignMode, Opcode)>; 64] = [
7247                        // 000_000
7248                        Some((AddAssign, Mpyi)), Some((AddAssign, Add)), None, Some((AddAssign, Sub)),
7249                        Some((AddAssign, SfMpy)), Some((SubAssign, SfMpy)), Some((AddAssign, SfMpy)), Some((SubAssign, SfMpy)),
7250                        // 001_000
7251                        Some((OrAssign, AndNot)), Some((AndAssign, AndNot)), Some((XorAssign, AndNot)), None,
7252                        None, None, None, None,
7253                        // 010_000
7254                        Some((AndAssign, And)), Some((AndAssign, Or)), Some((AndAssign, Xor)), Some((OrAssign, And)),
7255                        None, None, None, None,
7256                        // 011_000
7257                        Some((AddAssign, Mpy)), Some((SubAssign, Mpy)), None, None,
7258                        Some((AddAssign, SfMpy)), Some((AddAssign, SfMpy)), Some((AddAssign, SfMpy)), Some((AddAssign, SfMpy)),
7259                        // 100_000
7260                        Some((SubAssign, Mpyi)), Some((SubAssign, Add)), None, Some((XorAssign, Xor)),
7261                        None, None, None, None,
7262                        // 101_000
7263                        None, None, None, None,
7264                        None, None, None, None,
7265                        // 110_000
7266                        Some((OrAssign, Or)), Some((OrAssign, Xor)), Some((XorAssign, And)), Some((XorAssign, Or)),
7267                        None, None, None, None,
7268                        // 111_000
7269                        None, None, None, None,
7270                        None, None, None, None,
7271                    ];
7272
7273                    let (assign_mode, opcode) = decode_operand!(OPCODES[opc as usize]);
7274                    handler.on_opcode_decoded(opcode)?;
7275                    handler.assign_mode(assign_mode)?;
7276                    handler.on_dest_decoded(Operand::gpr(ddddd))?;
7277
7278                    if opcode == Opcode::Sub {
7279                        handler.on_source_decoded(Operand::gpr(ttttt))?;
7280                        handler.on_source_decoded(Operand::gpr(sssss))?;
7281                    } else {
7282                        handler.on_source_decoded(Operand::gpr(sssss))?;
7283                        handler.on_source_decoded(Operand::gpr(ttttt))?;
7284                    }
7285
7286                    if opc == 0b000110 || opc == 0b000111 {
7287                        handler.library()?;
7288                    }
7289
7290                    if opc == 0b011000 || opc == 0b011001 {
7291                        handler.shift_left(1)?;
7292                        handler.saturate()?;
7293                    } else if opc >= 0b011100 && opc < 0b100000 {
7294                        handler.on_source_decoded(Operand::pred(op_lo & 0b11))?;
7295                        handler.scale()?;
7296                    }
7297                }
7298            }
7299        }
7300        0b1111 => {
7301            let ddddd = reg_b0(inst);
7302            let ttttt = reg_b8(inst);
7303            let sssss = reg_b16(inst);
7304            let uu = (inst >> 5) & 0b11;
7305
7306            let majbits = (inst >> 24) & 0b111;
7307            let predicated = (inst >> 27) & 1 == 1;
7308            if !predicated {
7309                // one set of instructions. for most, the opcode bits actually overlap (e.g.
7310                // Rd=and(Rs,Rt) predicated with this bit set). this does not apply for *all*
7311                // though, so just handle the two sets of instructions individually...
7312                let minbits = (inst >> 21) & 0b111;
7313                match majbits {
7314                    0b001 => {
7315                        handler.on_dest_decoded(Operand::gpr(ddddd))?;
7316                        handler.on_source_decoded(Operand::gpr(sssss))?;
7317                        handler.on_source_decoded(Operand::gpr(ttttt))?;
7318                        static OPC: [Option<Opcode>; 8] = [
7319                            Some(Opcode::And), Some(Opcode::Or), None, Some(Opcode::Xor),
7320                            Some(Opcode::And_nRR), Some(Opcode::Or_nRR), None, None,
7321                        ];
7322                        handler.on_opcode_decoded(decode_opcode!(OPC[minbits as usize]))?;
7323                    },
7324                    0b010 => {
7325                        operand_check!(ddddd & 0b1100 == 0b0000);
7326                        handler.on_dest_decoded(Operand::pred(ddddd & 0b11))?;
7327                        handler.on_source_decoded(Operand::gpr(sssss))?;
7328                        handler.on_source_decoded(Operand::gpr(ttttt))?;
7329                        let op_low = (inst >> 4) & 1;
7330                        static OPC: [Option<Opcode>; 8] = [
7331                            Some(Opcode::CmpEq), None, Some(Opcode::CmpGt), Some(Opcode::CmpGtu),
7332                            Some(Opcode::CmpEq), None, Some(Opcode::CmpGt), Some(Opcode::CmpGtu),
7333                        ];
7334                        if op_low == 1 {
7335                            handler.negate_result()?;
7336                        }
7337                        handler.on_opcode_decoded(decode_opcode!(OPC[minbits as usize]))?;
7338                    }
7339                    0b011 => {
7340                        if minbits >= 0b100 {
7341                            handler.on_opcode_decoded(Opcode::Combine)?;
7342                        }
7343                        handler.on_dest_decoded(Operand::gpr(ddddd))?;
7344                        match minbits {
7345                            0b000 => {
7346                                handler.on_source_decoded(Operand::gpr(sssss))?;
7347                                handler.on_source_decoded(Operand::gpr(ttttt))?;
7348                                handler.on_opcode_decoded(Opcode::Add)?;
7349                            },
7350                            0b001 => {
7351                                handler.on_source_decoded(Operand::gpr(ttttt))?;
7352                                handler.on_source_decoded(Operand::gpr(sssss))?;
7353                                handler.on_opcode_decoded(Opcode::Sub)?;
7354                            }
7355                            0b010 => {
7356                                handler.on_source_decoded(Operand::gpr(sssss))?;
7357                                handler.on_source_decoded(Operand::gpr(ttttt))?;
7358                                handler.on_opcode_decoded(Opcode::CmpEq)?;
7359                            }
7360                            0b011 => {
7361                                handler.on_source_decoded(Operand::gpr(sssss))?;
7362                                handler.on_source_decoded(Operand::gpr(ttttt))?;
7363                                handler.on_opcode_decoded(Opcode::CmpEq)?;
7364                                handler.negate_result()?;
7365                            }
7366                            0b100 => {
7367                                handler.on_source_decoded(Operand::gpr_high(ttttt))?;
7368                                handler.on_source_decoded(Operand::gpr_high(sssss))?;
7369                            }
7370                            0b101 => {
7371                                handler.on_source_decoded(Operand::gpr_high(ttttt))?;
7372                                handler.on_source_decoded(Operand::gpr_low(sssss))?;
7373                            }
7374                            0b110 => {
7375                                handler.on_source_decoded(Operand::gpr_low(ttttt))?;
7376                                handler.on_source_decoded(Operand::gpr_high(sssss))?;
7377                            }
7378                            _ => {
7379                                handler.on_source_decoded(Operand::gpr_low(ttttt))?;
7380                                handler.on_source_decoded(Operand::gpr_low(sssss))?;
7381                            }
7382                        }
7383                    }
7384                    0b100 => {
7385                        handler.on_opcode_decoded(Opcode::Mux)?;
7386                        handler.on_dest_decoded(Operand::gpr(ddddd))?;
7387                        let uu = (inst >> 5) & 0b11;
7388                        handler.on_source_decoded(Operand::pred(uu as u8))?;
7389                        handler.on_source_decoded(Operand::gpr(sssss))?;
7390                        handler.on_source_decoded(Operand::gpr(ttttt))?;
7391                    }
7392                    0b101 => {
7393                        let op = (inst >> 23) & 1 == 1;
7394
7395                        handler.on_dest_decoded(Operand::gprpair(ddddd)?)?;
7396                        handler.on_source_decoded(Operand::gpr(sssss))?;
7397                        handler.on_source_decoded(Operand::gpr(ttttt))?;
7398
7399                        if !op {
7400                            opcode_check!((inst >> 13) & 1 == 0);
7401                            handler.on_opcode_decoded(Opcode::Combine)?;
7402                        } else {
7403                            handler.on_opcode_decoded(Opcode::Packhl)?;
7404                        }
7405                    }
7406                    0b110 => {
7407                        let opc = (inst >> 21) & 0b111;
7408                        static OPCODES: [Opcode; 8] = [
7409                            Vaddh, Vaddh, Add, Vadduh,
7410                            Vsubh, Vsubh, Sub, Vsubuh,
7411                        ];
7412                        handler.on_opcode_decoded(OPCODES[opc as usize])?;
7413
7414                        handler.on_dest_decoded(Operand::gpr(ddddd))?;
7415                        if opc < 0b100 {
7416                            handler.on_source_decoded(Operand::gpr(sssss))?;
7417                            handler.on_source_decoded(Operand::gpr(ttttt))?;
7418                        } else {
7419                            handler.on_source_decoded(Operand::gpr(ttttt))?;
7420                            handler.on_source_decoded(Operand::gpr(sssss))?;
7421                        }
7422                        if opc & 0b11 != 0 {
7423                            handler.saturate()?;
7424                        }
7425                    }
7426                    0b111 => {
7427                        handler.on_dest_decoded(Operand::gpr(ddddd))?;
7428
7429                        if (inst >> 22) & 1 == 0 {
7430                            handler.on_opcode_decoded(Vavgh)?;
7431                            if (inst >> 21) & 1 == 1 {
7432                                handler.saturate()?;
7433                            }
7434                            handler.on_source_decoded(Operand::gpr(sssss))?;
7435                            handler.on_source_decoded(Operand::gpr(ttttt))?;
7436                        } else {
7437                            handler.on_opcode_decoded(Vnavgh)?;
7438                            opcode_check!((inst >> 21) & 1 == 1);
7439                            handler.on_source_decoded(Operand::gpr(sssss))?;
7440                            handler.on_source_decoded(Operand::gpr(ttttt))?;
7441                        }
7442                    }
7443                    _ => {
7444                        opcode_check!(false);
7445                    }
7446                }
7447            } else {
7448                handler.on_source_decoded(Operand::gpr(sssss))?;
7449                handler.on_source_decoded(Operand::gpr(ttttt))?;
7450
7451                let negated = (inst >> 7) & 1 == 1;
7452                let dotnew = (inst >> 13) & 1 == 1;
7453                handler.inst_predicated(uu as u8, negated, dotnew)?;
7454                if majbits == 0b001 {
7455                    handler.on_dest_decoded(Operand::gpr(ddddd))?;
7456                    static OPS: [Option<Opcode>; 4] = [
7457                        Some(Opcode::And), Some(Opcode::Or), None, Some(Opcode::Xor)
7458                    ];
7459                    let opbits = (inst >> 21) & 0b11;
7460                    handler.on_opcode_decoded(decode_opcode!(OPS[opbits as usize]))?;
7461                } else if majbits == 0b011 {
7462                    handler.on_dest_decoded(Operand::gpr(ddddd))?;
7463                    opcode_check!((inst >> 23) & 1 == 0);
7464                    if (inst >> 21) & 1 == 0 {
7465                        handler.on_opcode_decoded(Opcode::Add)?;
7466                    } else {
7467                        handler.on_opcode_decoded(Opcode::Sub)?;
7468                    }
7469                } else if majbits == 0b101 {
7470                    handler.on_dest_decoded(Operand::gprpair(ddddd)?)?;
7471                    handler.on_opcode_decoded(Opcode::Contains)?;
7472                    opcode_check!((inst >> 21) & 0b111 == 0b000);
7473                } else {
7474                    opcode_check!(false);
7475                }
7476            }
7477        }
7478        _ => {
7479            opcode_check!(false);
7480        }
7481    }
7482
7483    Ok(())
7484}