yaxpeax_m16c/
lib.rs

1#![no_std]
2
3#![allow(non_snake_case)]
4
5#[cfg(feature="use-serde")]
6#[macro_use]
7extern crate serde_derive;
8
9use core::fmt;
10
11use yaxpeax_arch::{Arch, AddressDiff, Decoder, LengthedInstruction, Reader, StandardDecodeError};
12
13#[allow(non_camel_case_types)]
14#[derive(Debug, Copy, Clone)]
15pub enum Opcode {
16    ABS,
17    ADC(Size),
18    ADCF(Size),
19    ADD(Size),
20    ADJNZ(Size),
21    AND(Size),
22    BAND,
23    BCLR,
24    BMEQ,
25    BMGEU,
26    BMGT,
27    BMGTU,
28    BMLE,
29    BMLEU,
30    BMLTU,
31    BMLT,
32    BMNO,
33    BMGE,
34    BMN,
35    BMNE,
36    BMO,
37    BMPZ,
38    BNAND,
39    BNOR,
40    BNOT,
41    BNTST,
42    BNXOR,
43    BOR,
44    BRK,
45    BSET,
46    BTST,
47    BTSTC,
48    BTSTS,
49    BXOR,
50    CMP(Size),
51    DADC,
52    DADD,
53    DEC(Size),
54    DIV(Size),
55    DIVU(Size),
56    DIVX(Size),
57    DSBB,
58    DSUB,
59    ENTER,
60    EXITD,
61    EXTS,
62    GE,
63    INC(Size),
64    INT,
65    INTO,
66    JEQ,
67    JGE,
68    JGEU,
69    JGT,
70    JGTU,
71    JLE,
72    JLEU,
73    JLT,
74    JLTU,
75    JMPI,
76    JMPS,
77    JMP(Size),
78    JN,
79    JNE,
80    JNO,
81    JO,
82    JPZ,
83    JSRI,
84    JSRS,
85    JSR(Size),
86    LDC,
87    LDCTX,
88    LDE,
89    LDIPL,
90    LT,
91    MOV(Size),
92    MOVA,
93    MOVHH,
94    MOVHL,
95    MOVLH,
96    MOVLL,
97    MUL,
98    MULU(Size),
99    NEG,
100    NO,
101    NOP,
102    NOT(Size),
103    OR(Size),
104    POP,
105    POPC,
106    POPM,
107    PUSH(Size),
108    PUSHA,
109    PUSHC,
110    PUSHM,
111    REIT,
112    RMPA(Size),
113    ROLC,
114    RORC,
115    ROT(Size),
116    RTS,
117    SBB(Size),
118    SHA(Size),
119    SHL(Size),
120    SMOVB(Size),
121    SMOVF(Size),
122    SSTR(Size),
123    STC,
124    STCTX,
125    STE,
126    STNZ,
127    STX,
128    STZ,
129    STZX,
130    SUB(Size),
131    TST(Size),
132    UND,
133    WAIT,
134    XCHG(Size),
135    XOR(Size),
136}
137
138impl fmt::Display for Opcode {
139    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
140        match self {
141            Opcode::ABS => write!(f, "abs"),
142            Opcode::ADC(size) => write!(f, "adc.{}", size),
143            Opcode::ADCF(size) => write!(f, "adcf.{}", size),
144            Opcode::ADD(size) => write!(f, "add.{}", size),
145            Opcode::ADJNZ(size) => write!(f, "adjnz.{}", size),
146            Opcode::AND(size) => write!(f, "and.{}", size),
147            Opcode::BAND => write!(f, "band"),
148            Opcode::BCLR => write!(f, "bclr"),
149            Opcode::BMEQ => write!(f, "bmeq"),
150            Opcode::BMGEU => write!(f, "bmgeu"),
151            Opcode::BMGT => write!(f, "bmgt"),
152            Opcode::BMGTU => write!(f, "bmgtu"),
153            Opcode::BMLE => write!(f, "bmle"),
154            Opcode::BMLEU => write!(f, "bmleu"),
155            Opcode::BMLTU => write!(f, "bmltu"),
156            Opcode::BMLT => write!(f, "bmlt"),
157            Opcode::BMNO => write!(f, "bmno"),
158            Opcode::BMGE => write!(f, "bmge"),
159            Opcode::BMN => write!(f, "bmn"),
160            Opcode::BMNE => write!(f, "bmne"),
161            Opcode::BMO => write!(f, "bmo"),
162            Opcode::BMPZ => write!(f, "bmpz"),
163            Opcode::BNAND => write!(f, "bnand"),
164            Opcode::BNOR => write!(f, "bnor"),
165            Opcode::BNOT => write!(f, "bnot"),
166            Opcode::BNTST => write!(f, "bntst"),
167            Opcode::BNXOR => write!(f, "bnxor"),
168            Opcode::BOR => write!(f, "bor"),
169            Opcode::BRK => write!(f, "brk"),
170            Opcode::BSET => write!(f, "bset"),
171            Opcode::BTST => write!(f, "btst"),
172            Opcode::BTSTC => write!(f, "btstc"),
173            Opcode::BTSTS => write!(f, "btsts"),
174            Opcode::BXOR => write!(f, "bxor"),
175            Opcode::CMP(size) => write!(f, "cmp.{}", size),
176            Opcode::DADC => write!(f, "dadc"),
177            Opcode::DADD => write!(f, "dadd"),
178            Opcode::DEC(size) => write!(f, "dec.{}", size),
179            Opcode::DIV(size) => write!(f, "div.{}", size),
180            Opcode::DIVU(size) => write!(f, "divu.{}", size),
181            Opcode::DIVX(size) => write!(f, "divx.{}", size),
182            Opcode::DSBB => write!(f, "dsbb"),
183            Opcode::DSUB => write!(f, "dsub"),
184            Opcode::ENTER => write!(f, "enter"),
185            Opcode::EXITD => write!(f, "exitd"),
186            Opcode::EXTS => write!(f, "exts"),
187            Opcode::GE => write!(f, "ge"),
188            Opcode::INC(size) => write!(f, "inc.{}", size),
189            Opcode::INT => write!(f, "int"),
190            Opcode::INTO => write!(f, "into"),
191            Opcode::JEQ => write!(f, "jeq"),
192            Opcode::JGE => write!(f, "jge"),
193            Opcode::JGEU => write!(f, "jgeu"),
194            Opcode::JGT => write!(f, "jgt"),
195            Opcode::JGTU => write!(f, "jgtu"),
196            Opcode::JLE => write!(f, "jle"),
197            Opcode::JLEU => write!(f, "jleu"),
198            Opcode::JLT => write!(f, "jlt"),
199            Opcode::JLTU => write!(f, "jltu"),
200            Opcode::JMPI => write!(f, "jmpi"),
201            Opcode::JMPS => write!(f, "jmps"),
202            Opcode::JMP(size) => write!(f, "jmp.{}", size),
203            Opcode::JN => write!(f, "jn"),
204            Opcode::JNE => write!(f, "jne"),
205            Opcode::JNO => write!(f, "jno"),
206            Opcode::JO => write!(f, "jo"),
207            Opcode::JPZ => write!(f, "jpz"),
208            Opcode::JSRI => write!(f, "jsri"),
209            Opcode::JSRS => write!(f, "jsrs"),
210            Opcode::JSR(size) => write!(f, "jsr.{}", size),
211            Opcode::LDC => write!(f, "ldc"),
212            Opcode::LDCTX => write!(f, "ldctx"),
213            Opcode::LDE => write!(f, "lde"),
214            Opcode::LDIPL => write!(f, "ldipl"),
215            Opcode::LT => write!(f, "lt"),
216            Opcode::MOV(size) => write!(f, "mov.{}", size),
217            Opcode::MOVA => write!(f, "mova"),
218            Opcode::MOVHH => write!(f, "movhh"),
219            Opcode::MOVHL => write!(f, "movhl"),
220            Opcode::MOVLH => write!(f, "movlh"),
221            Opcode::MOVLL => write!(f, "movll"),
222            Opcode::MUL => write!(f, "mul"),
223            Opcode::MULU(size) => write!(f, "mulu.{}", size),
224            Opcode::NEG => write!(f, "neg"),
225            Opcode::NO => write!(f, "no"),
226            Opcode::NOP => write!(f, "nop"),
227            Opcode::NOT(size) => write!(f, "not.{}", size),
228            Opcode::OR(size) => write!(f, "or.{}", size),
229            Opcode::POP => write!(f, "pop"),
230            Opcode::POPC => write!(f, "popc"),
231            Opcode::POPM => write!(f, "popm"),
232            Opcode::PUSH(size) => write!(f, "push.{}", size),
233            Opcode::PUSHA => write!(f, "pusha"),
234            Opcode::PUSHC => write!(f, "pushc"),
235            Opcode::PUSHM => write!(f, "pushm"),
236            Opcode::REIT => write!(f, "reit"),
237            Opcode::RMPA(size) => write!(f, "rmpa.{}", size),
238            Opcode::ROLC => write!(f, "rolc"),
239            Opcode::RORC => write!(f, "rorc"),
240            Opcode::ROT(size) => write!(f, "rot.{}", size),
241            Opcode::RTS => write!(f, "rts"),
242            Opcode::SBB(size) => write!(f, "sbb.{}", size),
243            Opcode::SHA(size) => write!(f, "sha.{}", size),
244            Opcode::SHL(size) => write!(f, "shl.{}", size),
245            Opcode::SMOVB(size) => write!(f, "smovb.{}", size),
246            Opcode::SMOVF(size) => write!(f, "smovf.{}", size),
247            Opcode::SSTR(size) => write!(f, "sstr.{}", size),
248            Opcode::STC => write!(f, "stc"),
249            Opcode::STCTX => write!(f, "stctx"),
250            Opcode::STE => write!(f, "ste"),
251            Opcode::STNZ => write!(f, "stnz"),
252            Opcode::STX => write!(f, "stx"),
253            Opcode::STZ => write!(f, "stz"),
254            Opcode::STZX => write!(f, "stzx"),
255            Opcode::SUB(size) => write!(f, "sub.{}", size),
256            Opcode::TST(size) => write!(f, "tst.{}", size),
257            Opcode::UND => write!(f, "und"),
258            Opcode::WAIT => write!(f, "wait"),
259            Opcode::XCHG(size) => write!(f, "xchg.{}", size),
260            Opcode::XOR(size) => write!(f, "xor.{}", size),
261        }
262    }
263}
264
265#[derive(Debug, Copy, Clone)]
266pub enum Register {
267    R0L,
268    R0H,
269    R1L,
270    R1H,
271    R0,
272    R1,
273    R2,
274    R3,
275    R2R0,
276    R3R1,
277    A0,
278    A1,
279    A1A0,
280    FB,
281    SB,
282    SP,
283    INTBL,
284    INTBH,
285    FLG,
286    ISP,
287}
288
289impl fmt::Display for Register {
290    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
291        use Register::*;
292        match self {
293            R0L => write!(f, "r0l"),
294            R0H => write!(f, "r0h"),
295            R1L => write!(f, "r1l"),
296            R1H => write!(f, "r1h"),
297            R0 => write!(f, "r0"),
298            R1 => write!(f, "r1"),
299            R2 => write!(f, "r2"),
300            R3 => write!(f, "r3"),
301            R2R0 => write!(f, "r2r0"),
302            R3R1 => write!(f, "r3r1"),
303            A0 => write!(f, "a0"),
304            A1 => write!(f, "a1"),
305            A1A0 => write!(f, "a1a0"),
306            FB => write!(f, "fb"),
307            SB => write!(f, "sb"),
308            SP => write!(f, "sp"),
309            INTBL => write!(f, "intbl"),
310            INTBH => write!(f, "intbh"),
311            FLG => write!(f, "flg"),
312            ISP => write!(f, "isp"),
313        }
314    }
315}
316
317#[derive(Debug, Copy, Clone)]
318pub enum Operand {
319    Register(Register),
320    RegisterBit(Register, u8),
321    ImmediateI16(i16),
322    ImmediateU16(u16),
323    RegDerefBit(Register),
324    A0A1DispBit(Register, u16),
325    RegDispBit(Register, u16, u8),
326    RegDeref(Register, i16),
327    AbsoluteBit(u16),
328    Absolute(u32),
329    JmpAbsolute(u32),
330    Displacement(i16),
331    JmpDisplacement(i16),
332    RegList(u8),
333}
334
335impl fmt::Display for Operand {
336    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
337        match self {
338            Operand::RegList(list) => {
339                let regs = [
340                    Register::FB,
341                    Register::SB,
342                    Register::A1,
343                    Register::A0,
344                    Register::R3,
345                    Register::R2,
346                    Register::R1,
347                    Register::R0,
348                ];
349
350                let mut printed = false;
351
352                for i in 0..8 {
353                    if list & (1 << i) != 0 {
354                        if printed {
355                            write!(f, ", ")?;
356                        } else {
357                            printed = true;
358                        }
359                        write!(f, "{}", regs[i as usize])?;
360                    }
361                }
362
363                Ok(())
364            }
365            Operand::Register(reg) => write!(f, "{}", reg),
366            Operand::ImmediateI16(imm) => {
367                if *imm == core::i16::MIN {
368                    write!(f, "#-8000h")
369                } else if *imm < 0 {
370                    write!(f, "#-{:02x}h", -*imm)
371                } else {
372                    write!(f, "#{:02x}h", *imm)
373                }
374            },
375            Operand::ImmediateU16(imm) => write!(f, "#{:02x}h", imm),
376            Operand::RegDerefBit(reg) => {
377                write!(f, "bit,[{}]", reg)
378            }
379            Operand::A0A1DispBit(reg, offset) => {
380                write!(f, "{}[{}]", offset, reg)
381            }
382            Operand::RegDispBit(reg, offset, bit) => {
383                write!(f, "{},{}[{}]", bit, offset, reg)
384            }
385            Operand::RegDeref(reg, offset) => {
386                if *offset == core::i16::MIN {
387                    write!(f, "#-8000h")
388                } else if *offset == 0 {
389                    write!(f, "[{}]", reg)
390                } else if *offset < 0 {
391                    write!(f, "-{}[{}]", -offset, reg)
392                } else {
393                    write!(f, "{}[{}]", offset, reg)
394                }
395            }
396            Operand::JmpDisplacement(offset) => {
397                if *offset == core::i16::MIN {
398                    write!(f, "$-32768")
399                } else if *offset < 0 {
400                    write!(f, "$-{}", -*offset)
401                } else {
402                    write!(f, "$+{}", *offset)
403                }
404            }
405            Operand::Displacement(offset) => {
406                if *offset == core::i16::MIN {
407                    write!(f, "[$-32768]")
408                } else if *offset < 0 {
409                    write!(f, "[$-{}]", -*offset)
410                } else {
411                    write!(f, "[$+{}]", *offset)
412                }
413            }
414            Operand::AbsoluteBit(addr) => {
415                write!(f, "[#{:x}h]", addr)
416            }
417            // `Absolute` can be a 20-bit address, so `addr` here is u32 rathere than u16 above.
418            Operand::Absolute(addr) => {
419                write!(f, "[#{:x}h]", addr)
420            }
421            Operand::JmpAbsolute(addr) => {
422                write!(f, "#{:x}h", addr)
423            }
424            Operand::RegisterBit(reg, bit) => {
425                write!(f, "{},{}", bit, reg)
426            }
427        }
428    }
429}
430
431#[allow(non_camel_case_types)]
432#[derive(Debug, Copy, Clone, PartialEq)]
433enum OperandSpec {
434    Nothing,
435    Zero,
436    Imm4,
437    Imm8,
438    Imm82, // Imm8, part t2. used in STZX.
439    Imm16,
440    Label8,
441    Bit0,
442    Bit1,
443    Bit2,
444    Bit3,
445    Bit4,
446    Bit5,
447    Bit6,
448    Bit7,
449    R0L,
450    R0H,
451    R1L,
452    R1H,
453    R0,
454    R1,
455    R2,
456    R3,
457    R2R0,
458    R3R1,
459    A0,
460    A1,
461    A1A0,
462    Bit_R0,
463    Bit_R1,
464    Bit_R2,
465    Bit_R3,
466    Bit_A0,
467    Bit_A1,
468    Bit_Deref_A0,
469    Bit_Deref_A1,
470    Bit_Disp8_A0,
471    Bit_Disp8_A1,
472    Bit_Disp8_SB,
473    Bit_Disp8_FB,
474    Bit_Disp16_A0,
475    Bit_Disp16_A1,
476    Bit_Disp16_SB,
477    Bit_Abs16,
478    Disp8_A0,
479    Disp8_A1,
480    Disp8_SB,
481    Disp8_FB,
482    Disp8_SP,
483    Disp16_A0,
484    Disp16_A1,
485    Disp16_SB,
486    Disp20_A0,
487    Disp20_A1,
488    Deref_A0,
489    Deref_A1,
490    Deref_A1A0,
491    Abs16,
492    Disp2_8_A0,
493    Disp2_8_A1,
494    Disp2_8_SB,
495    Disp2_8_FB,
496    Disp2_16_A0,
497    Disp2_16_A1,
498    Disp2_16_SB,
499    Abs2_16,
500    Abs20,
501    JmpAbs20,
502    Disp8,
503    JmpDisp8,
504    JmpDisp16,
505    RegList,
506    INTBL,
507    INTBH,
508    FLG,
509    ISP,
510    SP,
511    SB,
512    FB,
513}
514
515#[derive(Debug, Copy, Clone, PartialEq)]
516pub enum Size {
517    B, // 0 in almost(?) all places a size bit is present
518    W, // 1 in almost(?) all places a size bit is present
519    L, // for sha.l/shl.l
520    S, // for jmp.s, three bits.
521    A, // for jmp.a, twenty bit absolute.
522}
523
524impl fmt::Display for Size {
525    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
526        match self {
527            Size::B => write!(f, "b"),
528            Size::W => write!(f, "w"),
529            Size::L => write!(f, "l"),
530            Size::S => write!(f, "s"),
531            Size::A => write!(f, "a"),
532        }
533    }
534}
535
536impl Size {
537    fn as_bytes(&self) -> u8 {
538        match self {
539            Size::B => 1,
540            Size::W => 2,
541            Size::L => { panic!("should not have to get number of bytes for L"); },
542            Size::S => { panic!("should not have to get number of bytes for S"); },
543            Size::A => { panic!("should not have to get number of bytes for A"); },
544        }
545    }
546}
547
548#[derive(Debug, Copy, Clone)]
549pub struct Instruction {
550    pub opcode: Opcode,
551    operands: [OperandSpec; 3],
552    // we need both `dispabs` and `imm_wide` to handle the widest instructions we can see:
553    // LDE or STE with 20-bit displacement and 16-bit displacement.
554    // either an Imm16, an Imm8, or Imm82:Imm8. mutually exclusive with 20-bit disp/abs, so put those here too.
555    //
556    // Imm4 will sometimes cohabitate with two displacements (ADJNZ with displacement dest and
557    // label), so cram the label byte into here as well. accessed as `OperandSpec::Label8`.
558    imm_wide: u32,
559    dispabs: u16, // 8 or 16-bit displacement or absolute address
560    length: u8,
561}
562
563impl Instruction {
564    pub fn operand(&self, idx: u8) -> Option<Operand> {
565        use OperandSpec::*;
566        let operand = match self.operands[idx as usize] {
567            Nothing => { return None; },
568            Zero => Operand::ImmediateU16(0),
569            Imm4 => Operand::ImmediateI16(self.imm_wide as u8 as i8 as i16),
570            Imm8 => Operand::ImmediateI16(self.imm_wide as u8 as i8 as i16),
571            Imm16 => Operand::ImmediateI16(self.imm_wide as i16),
572            // Imm8 part 2 is used in STZX, and is the second byte of imm_wide
573            Imm82 |
574            // and Label8 is used in ADJNZ, also stored in the second byte of inn_wide
575            Label8 => Operand::ImmediateI16((self.imm_wide as i16) >> 8),
576            Bit0 => Operand::ImmediateU16(0),
577            Bit1 => Operand::ImmediateU16(1),
578            Bit2 => Operand::ImmediateU16(2),
579            Bit3 => Operand::ImmediateU16(3),
580            Bit4 => Operand::ImmediateU16(4),
581            Bit5 => Operand::ImmediateU16(5),
582            Bit6 => Operand::ImmediateU16(6),
583            Bit7 => Operand::ImmediateU16(7),
584            R0L => Operand::Register(Register::R0L),
585            R0H => Operand::Register(Register::R0H),
586            R1L => Operand::Register(Register::R1L),
587            R1H => Operand::Register(Register::R1H),
588            R0 => Operand::Register(Register::R0),
589            R1 => Operand::Register(Register::R1),
590            R2 => Operand::Register(Register::R2),
591            R3 => Operand::Register(Register::R3),
592            R2R0 => Operand::Register(Register::R2R0),
593            R3R1 => Operand::Register(Register::R3R1),
594            A0 => Operand::Register(Register::A0),
595            A1 => Operand::Register(Register::A1),
596            A1A0 => Operand::Register(Register::A1A0),
597            Bit_R0 => Operand::RegisterBit(Register::R0, self.dispabs as u8),
598            Bit_R1 => Operand::RegisterBit(Register::R1, self.dispabs as u8),
599            Bit_R2 => Operand::RegisterBit(Register::R2, self.dispabs as u8),
600            Bit_R3 => Operand::RegisterBit(Register::R3, self.dispabs as u8),
601            Bit_A0 => Operand::RegisterBit(Register::A0, self.dispabs as u8),
602            Bit_A1 => Operand::RegisterBit(Register::A1, self.dispabs as u8),
603            Bit_Deref_A0 => Operand::RegDerefBit(Register::A0),
604            Bit_Deref_A1 => Operand::RegDerefBit(Register::A1),
605            Bit_Disp8_A0 => Operand::A0A1DispBit(Register::A0, self.dispabs as u8 as u16),
606            Bit_Disp8_A1 => Operand::A0A1DispBit(Register::A1, self.dispabs as u8 as u16),
607            Bit_Disp8_SB => Operand::RegDispBit(Register::SB, (self.dispabs as u8 >> 3) as u16, self.dispabs as u8 & 0b111),
608            Bit_Disp8_FB => Operand::RegDispBit(Register::FB, (self.dispabs as u8 >> 3) as u16, self.dispabs as u8 & 0b111),
609            Bit_Disp16_A0 => Operand::A0A1DispBit(Register::A0, self.dispabs as u16),
610            Bit_Disp16_A1 => Operand::A0A1DispBit(Register::A1, self.dispabs as u16),
611            Bit_Disp16_SB => Operand::RegDispBit(Register::SB, self.dispabs as u16 >> 4, self.dispabs as u8 & 0b1111),
612            Bit_Abs16 => Operand::AbsoluteBit(self.dispabs),
613            Disp8_A0 => Operand::RegDeref(Register::A0, self.dispabs as i8 as i16),
614            Disp8_A1 => Operand::RegDeref(Register::A1, self.dispabs as i8 as i16),
615            Disp8_SB => Operand::RegDeref(Register::SB, self.dispabs as i8 as i16),
616            Disp8_FB => Operand::RegDeref(Register::FB, self.dispabs as i8 as i16),
617            Disp8_SP => Operand::RegDeref(Register::SP, self.dispabs as i8 as i16),
618            Disp16_A0 => Operand::RegDeref(Register::A0, self.dispabs as i16),
619            Disp16_A1 => Operand::RegDeref(Register::A1, self.dispabs as i16),
620            Disp16_SB => Operand::RegDeref(Register::SB, self.dispabs as i16),
621            Disp20_A0 => Operand::RegDeref(Register::A0, self.imm_wide as i16),
622            Disp20_A1 => Operand::RegDeref(Register::A1, self.imm_wide as i16),
623            Deref_A0 => Operand::RegDeref(Register::A0, self.dispabs as i16),
624            Deref_A1 => Operand::RegDeref(Register::A1, self.dispabs as i16),
625            Deref_A1A0 => Operand::RegDeref(Register::A1A0, self.dispabs as i16),
626            Abs16 => Operand::Absolute(self.dispabs as u32),
627            Disp2_8_A0 => Operand::RegDeref(Register::A0, self.imm_wide as i8 as i16),
628            Disp2_8_A1 => Operand::RegDeref(Register::A1, self.imm_wide as i8 as i16),
629            Disp2_8_SB => Operand::RegDeref(Register::SB, self.imm_wide as i8 as i16),
630            Disp2_8_FB => Operand::RegDeref(Register::FB, self.imm_wide as i8 as i16),
631            Disp2_16_A0 => Operand::RegDeref(Register::A0, self.imm_wide as i16),
632            Disp2_16_A1 => Operand::RegDeref(Register::A1, self.imm_wide as i16),
633            Disp2_16_SB => Operand::RegDeref(Register::SB, self.imm_wide as i16),
634            Abs2_16 => Operand::Absolute(self.imm_wide),
635            Abs20 => Operand::Absolute(self.imm_wide),
636            JmpAbs20 => Operand::JmpAbsolute(self.imm_wide),
637            Disp8 => Operand::Displacement(self.dispabs as u8 as i8 as i16),
638            JmpDisp8 => Operand::JmpDisplacement(self.dispabs as u8 as i8 as i16),
639            JmpDisp16 => Operand::JmpDisplacement(self.dispabs as i16),
640            RegList => Operand::RegList(self.imm_wide as u8),
641            INTBL => Operand::Register(Register::INTBL),
642            INTBH => Operand::Register(Register::INTBH),
643            FLG => Operand::Register(Register::FLG),
644            ISP => Operand::Register(Register::ISP),
645            SP => Operand::Register(Register::SP),
646            SB => Operand::Register(Register::SB),
647            FB => Operand::Register(Register::FB),
648        };
649        Some(operand)
650    }
651}
652
653#[cfg_attr(feature="use-serde", derive(Serialize, Deserialize))]
654#[derive(Debug)]
655pub struct M16C;
656
657impl Arch for M16C {
658    type Address = u32;
659    type Word = u8;
660    type Instruction = Instruction;
661    type DecodeError = StandardDecodeError;
662    type Decoder = InstDecoder;
663    type Operand = Operand;
664}
665
666impl fmt::Display for Instruction {
667    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
668        write!(f, "{}", self.opcode)?;
669        match self.operand(0) {
670            None => return Ok(()),
671            Some(op) => { write!(f, " {}", op)?; }
672        }
673        match self.operand(1) {
674            None => return Ok(()),
675            Some(op) => { write!(f, ", {}", op)?; }
676        }
677        Ok(())
678    }
679}
680
681impl LengthedInstruction for Instruction {
682    type Unit = AddressDiff<<M16C as Arch>::Address>;
683
684    fn min_size() -> Self::Unit {
685        AddressDiff::from_const(1)
686    }
687    fn len(&self) -> Self::Unit {
688        AddressDiff::from_const(self.length as u32)
689    }
690}
691
692impl Default for Instruction {
693    fn default() -> Self {
694        Instruction {
695            opcode: Opcode::NOP,
696            operands: [OperandSpec::Nothing, OperandSpec::Nothing, OperandSpec::Nothing],
697            imm_wide: 0,
698            dispabs: 0,
699            length: 0
700        }
701    }
702}
703
704impl yaxpeax_arch::Instruction for Instruction {
705    // currently only accept instructions that are well-defined.
706    fn well_defined(&self) -> bool { true }
707}
708
709#[derive(Default, Debug)]
710pub struct InstDecoder {}
711
712impl fmt::Display for InstDecoder {
713    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
714        write!(f, "m16c")
715    }
716}
717
718impl Decoder<M16C> for InstDecoder {
719    fn decode_into<T: Reader<<M16C as Arch>::Address, <M16C as Arch>::Word>>(&self, inst: &mut Instruction, words: &mut T) -> Result<(), <M16C as Arch>::DecodeError> {
720        decode(self, inst, words)
721    }
722}
723
724enum OperandCategory {
725    ADJNZ,
726    Op74,
727    Op76,
728    Op78,
729    Op7A,
730    Op7B,
731    Op7C,
732    Op7D,
733    Op7E,
734    OpEB,
735    SrcDestRegOrDeref,
736    Imm4Dest,
737    JmpDispOpcodeLow3,
738}
739
740enum OperandInterpretation {
741    Just([OperandSpec; 3]),
742    Reinterpret(OperandCategory)
743}
744
745fn decode<T: Reader<<M16C as Arch>::Address, <M16C as Arch>::Word>>(_decoder: &InstDecoder, inst: &mut Instruction, words: &mut T) -> Result<(), <M16C as Arch>::DecodeError> {
746    let byte = words.next()?;
747    inst.length += 1;
748    // IF there is a size bit, it is the low bit of the first byte.
749    let size = if byte & 1 == 0 {
750        Size::B
751    } else {
752        Size::W
753    };
754    use OperandInterpretation::*;
755    let (opcode, interpretation) = match byte {
756        0b0000_0000 => (Opcode::BRK, Just([OperandSpec::Nothing, OperandSpec::Nothing, OperandSpec::Nothing])),
757        0b0000_0001 => (Opcode::MOV(Size::B), Just([OperandSpec::R0L, OperandSpec::Disp8_SB, OperandSpec::Nothing])),
758        0b0000_0010 => (Opcode::MOV(Size::B), Just([OperandSpec::R0L, OperandSpec::Disp8_FB, OperandSpec::Nothing])),
759        0b0000_0011 => (Opcode::MOV(Size::B), Just([OperandSpec::R0L, OperandSpec::Abs16, OperandSpec::Nothing])),
760        0b0000_0100 => (Opcode::NOP, Just([OperandSpec::Nothing, OperandSpec::Nothing, OperandSpec::Nothing])),
761        0b0000_0101 => (Opcode::MOV(Size::B), Just([OperandSpec::R0H, OperandSpec::Disp8_SB, OperandSpec::Nothing])),
762        0b0000_0110 => (Opcode::MOV(Size::B), Just([OperandSpec::R0H, OperandSpec::Disp8_FB, OperandSpec::Nothing])),
763        0b0000_0111 => (Opcode::MOV(Size::B), Just([OperandSpec::R0H, OperandSpec::Abs16, OperandSpec::Nothing])),
764        0b0000_1000 => (Opcode::MOV(Size::B), Just([OperandSpec::R0H, OperandSpec::R0L, OperandSpec::Nothing])),
765        0b0000_1001 => (Opcode::MOV(Size::B), Just([OperandSpec::Disp8_SB, OperandSpec::R0L, OperandSpec::Nothing])),
766        0b0000_1010 => (Opcode::MOV(Size::B), Just([OperandSpec::Disp8_FB, OperandSpec::R0L, OperandSpec::Nothing])),
767        0b0000_1011 => (Opcode::MOV(Size::B), Just([OperandSpec::Abs16, OperandSpec::R0L, OperandSpec::Nothing])),
768        0b0000_1100 => (Opcode::MOV(Size::B), Just([OperandSpec::R0L, OperandSpec::R0H, OperandSpec::Nothing])),
769        0b0000_1101 => (Opcode::MOV(Size::B), Just([OperandSpec::Disp8_SB, OperandSpec::R0H, OperandSpec::Nothing])),
770        0b0000_1110 => (Opcode::MOV(Size::B), Just([OperandSpec::Disp8_FB, OperandSpec::R0H, OperandSpec::Nothing])),
771        0b0000_1111 => (Opcode::MOV(Size::B), Just([OperandSpec::Abs16, OperandSpec::R0H, OperandSpec::Nothing])),
772        0b0001_0000 => (Opcode::AND(Size::B), Just([OperandSpec::R0H, OperandSpec::R0L, OperandSpec::Nothing])), // src is written R0L/R0H, what picks the register?
773        0b0001_0001 => (Opcode::AND(Size::B), Just([OperandSpec::Disp8_SB, OperandSpec::R0L, OperandSpec::Nothing])),
774        0b0001_0010 => (Opcode::AND(Size::B), Just([OperandSpec::Disp8_FB, OperandSpec::R0L, OperandSpec::Nothing])),
775        0b0001_0011 => (Opcode::AND(Size::B), Just([OperandSpec::Abs16, OperandSpec::R0L, OperandSpec::Nothing])),
776        0b0001_0100 => (Opcode::AND(Size::B), Just([OperandSpec::R0L, OperandSpec::R0H, OperandSpec::Nothing])), // src is written R0L/R0H, what picks the register?
777        0b0001_0101 => (Opcode::AND(Size::B), Just([OperandSpec::Disp8_SB, OperandSpec::R0H, OperandSpec::Nothing])),
778        0b0001_0110 => (Opcode::AND(Size::B), Just([OperandSpec::Disp8_FB, OperandSpec::R0H, OperandSpec::Nothing])),
779        0b0001_0111 => (Opcode::AND(Size::B), Just([OperandSpec::Abs16, OperandSpec::R0H, OperandSpec::Nothing])),
780        0b0001_1000 => (Opcode::OR(Size::B), Just([OperandSpec::R0H, OperandSpec::R0L, OperandSpec::Nothing])), // src is written R0L/R0H, what picks the register?
781        0b0001_1001 => (Opcode::OR(Size::B), Just([OperandSpec::Disp8_SB, OperandSpec::R0L, OperandSpec::Nothing])),
782        0b0001_1010 => (Opcode::OR(Size::B), Just([OperandSpec::Disp8_FB, OperandSpec::R0L, OperandSpec::Nothing])),
783        0b0001_1011 => (Opcode::OR(Size::B), Just([OperandSpec::Abs16, OperandSpec::R0L, OperandSpec::Nothing])),
784        0b0001_1100 => (Opcode::OR(Size::B), Just([OperandSpec::R0L, OperandSpec::R0H, OperandSpec::Nothing])), // src is written R0L/R0H, what picks the register?
785        0b0001_1101 => (Opcode::OR(Size::B), Just([OperandSpec::Disp8_SB, OperandSpec::R0H, OperandSpec::Nothing])),
786        0b0001_1110 => (Opcode::OR(Size::B), Just([OperandSpec::Disp8_FB, OperandSpec::R0H, OperandSpec::Nothing])),
787        0b0001_1111 => (Opcode::OR(Size::B), Just([OperandSpec::Abs16, OperandSpec::R0H, OperandSpec::Nothing])),
788        0b0010_0000 => (Opcode::ADD(Size::B), Just([OperandSpec::R0H, OperandSpec::R0L, OperandSpec::Nothing])), // src is written R0L/R0H, what picks the register?
789        0b0010_0001 => (Opcode::ADD(Size::B), Just([OperandSpec::Disp8_SB, OperandSpec::R0L, OperandSpec::Nothing])),
790        0b0010_0010 => (Opcode::ADD(Size::B), Just([OperandSpec::Disp8_FB, OperandSpec::R0L, OperandSpec::Nothing])),
791        0b0010_0011 => (Opcode::ADD(Size::B), Just([OperandSpec::Abs16, OperandSpec::R0L, OperandSpec::Nothing])),
792        0b0010_0100 => (Opcode::ADD(Size::B), Just([OperandSpec::R0L, OperandSpec::R0H, OperandSpec::Nothing])), // src is written R0L/R0H, what picks the register?
793        0b0010_0101 => (Opcode::ADD(Size::B), Just([OperandSpec::Disp8_SB, OperandSpec::R0H, OperandSpec::Nothing])),
794        0b0010_0110 => (Opcode::ADD(Size::B), Just([OperandSpec::Disp8_FB, OperandSpec::R0H, OperandSpec::Nothing])),
795        0b0010_0111 => (Opcode::ADD(Size::B), Just([OperandSpec::Abs16, OperandSpec::R0H, OperandSpec::Nothing])),
796        0b0010_1000 => (Opcode::SUB(Size::B), Just([OperandSpec::R0H, OperandSpec::R0L, OperandSpec::Nothing])), // src is written R0L/R0H, what picks the register?
797        0b0010_1001 => (Opcode::SUB(Size::B), Just([OperandSpec::Disp8_SB, OperandSpec::R0L, OperandSpec::Nothing])),
798        0b0010_1010 => (Opcode::SUB(Size::B), Just([OperandSpec::Disp8_FB, OperandSpec::R0L, OperandSpec::Nothing])),
799        0b0010_1011 => (Opcode::SUB(Size::B), Just([OperandSpec::Abs16, OperandSpec::R0L, OperandSpec::Nothing])),
800        0b0010_1100 => (Opcode::SUB(Size::B), Just([OperandSpec::R0L, OperandSpec::R0H, OperandSpec::Nothing])), // src is written R0L/R0H, what picks the register?
801        0b0010_1101 => (Opcode::SUB(Size::B), Just([OperandSpec::Disp8_SB, OperandSpec::R0H, OperandSpec::Nothing])),
802        0b0010_1110 => (Opcode::SUB(Size::B), Just([OperandSpec::Disp8_FB, OperandSpec::R0H, OperandSpec::Nothing])),
803        0b0010_1111 => (Opcode::SUB(Size::B), Just([OperandSpec::Abs16, OperandSpec::R0H, OperandSpec::Nothing])),
804        0b0011_0000 => (Opcode::MOV(Size::B), Just([OperandSpec::R0H, OperandSpec::A0, OperandSpec::Nothing])), // src is written R0L/R0H, what picks the register?
805        0b0011_0001 => (Opcode::MOV(Size::B), Just([OperandSpec::Disp8_SB, OperandSpec::A0, OperandSpec::Nothing])),
806        0b0011_0010 => (Opcode::MOV(Size::B), Just([OperandSpec::Disp8_FB, OperandSpec::A0, OperandSpec::Nothing])),
807        0b0011_0011 => (Opcode::MOV(Size::B), Just([OperandSpec::Abs16, OperandSpec::A0, OperandSpec::Nothing])),
808        0b0011_0100 => (Opcode::MOV(Size::B), Just([OperandSpec::R0L, OperandSpec::A1, OperandSpec::Nothing])), // src is written R0L/R0H, what picks the register?
809        0b0011_0101 => (Opcode::MOV(Size::B), Just([OperandSpec::Disp8_SB, OperandSpec::A1, OperandSpec::Nothing])),
810        0b0011_0110 => (Opcode::MOV(Size::B), Just([OperandSpec::Disp8_FB, OperandSpec::A1, OperandSpec::Nothing])),
811        0b0011_0111 => (Opcode::MOV(Size::B), Just([OperandSpec::Abs16, OperandSpec::A1, OperandSpec::Nothing])),
812        0b0011_1000 => (Opcode::CMP(Size::B), Just([OperandSpec::R0H, OperandSpec::R0L, OperandSpec::Nothing])), // src is written R0L/R0H, what picks the register?
813        0b0011_1001 => (Opcode::CMP(Size::B), Just([OperandSpec::Disp8_SB, OperandSpec::R0L, OperandSpec::Nothing])),
814        0b0011_1010 => (Opcode::CMP(Size::B), Just([OperandSpec::Disp8_FB, OperandSpec::R0L, OperandSpec::Nothing])),
815        0b0011_1011 => (Opcode::CMP(Size::B), Just([OperandSpec::Abs16, OperandSpec::R0L, OperandSpec::Nothing])),
816        0b0011_1100 => (Opcode::CMP(Size::B), Just([OperandSpec::R0L, OperandSpec::R0H, OperandSpec::Nothing])), // src is written R0L/R0H, what picks the register?
817        0b0011_1101 => (Opcode::CMP(Size::B), Just([OperandSpec::Disp8_SB, OperandSpec::R0H, OperandSpec::Nothing])),
818        0b0011_1110 => (Opcode::CMP(Size::B), Just([OperandSpec::Disp8_FB, OperandSpec::R0H, OperandSpec::Nothing])),
819        0b0011_1111 => (Opcode::CMP(Size::B), Just([OperandSpec::Abs16, OperandSpec::R0H, OperandSpec::Nothing])),
820        0b0100_0000 => (Opcode::BCLR, Just([OperandSpec::Bit0, OperandSpec::Disp8_SB, OperandSpec::Nothing])),
821        0b0100_0001 => (Opcode::BCLR, Just([OperandSpec::Bit1, OperandSpec::Disp8_SB, OperandSpec::Nothing])),
822        0b0100_0010 => (Opcode::BCLR, Just([OperandSpec::Bit2, OperandSpec::Disp8_SB, OperandSpec::Nothing])),
823        0b0100_0011 => (Opcode::BCLR, Just([OperandSpec::Bit3, OperandSpec::Disp8_SB, OperandSpec::Nothing])),
824        0b0100_0100 => (Opcode::BCLR, Just([OperandSpec::Bit4, OperandSpec::Disp8_SB, OperandSpec::Nothing])),
825        0b0100_0101 => (Opcode::BCLR, Just([OperandSpec::Bit5, OperandSpec::Disp8_SB, OperandSpec::Nothing])),
826        0b0100_0110 => (Opcode::BCLR, Just([OperandSpec::Bit6, OperandSpec::Disp8_SB, OperandSpec::Nothing])),
827        0b0100_0111 => (Opcode::BCLR, Just([OperandSpec::Bit7, OperandSpec::Disp8_SB, OperandSpec::Nothing])),
828        0b0100_1000 => (Opcode::BSET, Just([OperandSpec::Bit0, OperandSpec::Disp8_SB, OperandSpec::Nothing])),
829        0b0100_1001 => (Opcode::BSET, Just([OperandSpec::Bit1, OperandSpec::Disp8_SB, OperandSpec::Nothing])),
830        0b0100_1010 => (Opcode::BSET, Just([OperandSpec::Bit2, OperandSpec::Disp8_SB, OperandSpec::Nothing])),
831        0b0100_1011 => (Opcode::BSET, Just([OperandSpec::Bit3, OperandSpec::Disp8_SB, OperandSpec::Nothing])),
832        0b0100_1100 => (Opcode::BSET, Just([OperandSpec::Bit4, OperandSpec::Disp8_SB, OperandSpec::Nothing])),
833        0b0100_1101 => (Opcode::BSET, Just([OperandSpec::Bit5, OperandSpec::Disp8_SB, OperandSpec::Nothing])),
834        0b0100_1110 => (Opcode::BSET, Just([OperandSpec::Bit6, OperandSpec::Disp8_SB, OperandSpec::Nothing])),
835        0b0100_1111 => (Opcode::BSET, Just([OperandSpec::Bit7, OperandSpec::Disp8_SB, OperandSpec::Nothing])),
836        0b0101_0000 => (Opcode::BNOT, Just([OperandSpec::Bit0, OperandSpec::Disp8_SB, OperandSpec::Nothing])),
837        0b0101_0001 => (Opcode::BNOT, Just([OperandSpec::Bit1, OperandSpec::Disp8_SB, OperandSpec::Nothing])),
838        0b0101_0010 => (Opcode::BNOT, Just([OperandSpec::Bit2, OperandSpec::Disp8_SB, OperandSpec::Nothing])),
839        0b0101_0011 => (Opcode::BNOT, Just([OperandSpec::Bit3, OperandSpec::Disp8_SB, OperandSpec::Nothing])),
840        0b0101_0100 => (Opcode::BNOT, Just([OperandSpec::Bit4, OperandSpec::Disp8_SB, OperandSpec::Nothing])),
841        0b0101_0101 => (Opcode::BNOT, Just([OperandSpec::Bit5, OperandSpec::Disp8_SB, OperandSpec::Nothing])),
842        0b0101_0110 => (Opcode::BNOT, Just([OperandSpec::Bit6, OperandSpec::Disp8_SB, OperandSpec::Nothing])),
843        0b0101_0111 => (Opcode::BNOT, Just([OperandSpec::Bit7, OperandSpec::Disp8_SB, OperandSpec::Nothing])),
844        0b0101_1000 => (Opcode::BTST, Just([OperandSpec::Bit0, OperandSpec::Disp8_SB, OperandSpec::Nothing])),
845        0b0101_1001 => (Opcode::BTST, Just([OperandSpec::Bit1, OperandSpec::Disp8_SB, OperandSpec::Nothing])),
846        0b0101_1010 => (Opcode::BTST, Just([OperandSpec::Bit2, OperandSpec::Disp8_SB, OperandSpec::Nothing])),
847        0b0101_1011 => (Opcode::BTST, Just([OperandSpec::Bit3, OperandSpec::Disp8_SB, OperandSpec::Nothing])),
848        0b0101_1100 => (Opcode::BTST, Just([OperandSpec::Bit4, OperandSpec::Disp8_SB, OperandSpec::Nothing])),
849        0b0101_1101 => (Opcode::BTST, Just([OperandSpec::Bit5, OperandSpec::Disp8_SB, OperandSpec::Nothing])),
850        0b0101_1110 => (Opcode::BTST, Just([OperandSpec::Bit6, OperandSpec::Disp8_SB, OperandSpec::Nothing])),
851        0b0101_1111 => (Opcode::BTST, Just([OperandSpec::Bit7, OperandSpec::Disp8_SB, OperandSpec::Nothing])),
852        0b0110_0000 => (Opcode::JMP(Size::S), Reinterpret(OperandCategory::JmpDispOpcodeLow3)),
853        0b0110_0001 => (Opcode::JMP(Size::S), Reinterpret(OperandCategory::JmpDispOpcodeLow3)),
854        0b0110_0010 => (Opcode::JMP(Size::S), Reinterpret(OperandCategory::JmpDispOpcodeLow3)),
855        0b0110_0011 => (Opcode::JMP(Size::S), Reinterpret(OperandCategory::JmpDispOpcodeLow3)),
856        0b0110_0100 => (Opcode::JMP(Size::S), Reinterpret(OperandCategory::JmpDispOpcodeLow3)),
857        0b0110_0101 => (Opcode::JMP(Size::S), Reinterpret(OperandCategory::JmpDispOpcodeLow3)),
858        0b0110_0110 => (Opcode::JMP(Size::S), Reinterpret(OperandCategory::JmpDispOpcodeLow3)),
859        0b0110_0111 => (Opcode::JMP(Size::S), Reinterpret(OperandCategory::JmpDispOpcodeLow3)),
860        0b0110_1000 => (Opcode::JGEU, Just([OperandSpec::JmpDisp8, OperandSpec::Nothing, OperandSpec::Nothing])),
861        0b0110_1001 => (Opcode::JGTU, Just([OperandSpec::JmpDisp8, OperandSpec::Nothing, OperandSpec::Nothing])),
862        0b0110_1010 => (Opcode::JEQ, Just([OperandSpec::JmpDisp8, OperandSpec::Nothing, OperandSpec::Nothing])),
863        0b0110_1011 => (Opcode::JN, Just([OperandSpec::JmpDisp8, OperandSpec::Nothing, OperandSpec::Nothing])),
864        0b0110_1100 => (Opcode::JLTU, Just([OperandSpec::JmpDisp8, OperandSpec::Nothing, OperandSpec::Nothing])),
865        0b0110_1101 => (Opcode::JLEU, Just([OperandSpec::JmpDisp8, OperandSpec::Nothing, OperandSpec::Nothing])),
866        0b0110_1110 => (Opcode::JNE, Just([OperandSpec::JmpDisp8, OperandSpec::Nothing, OperandSpec::Nothing])),
867        0b0110_1111 => (Opcode::JPZ, Just([OperandSpec::JmpDisp8, OperandSpec::Nothing, OperandSpec::Nothing])),
868        0b0111_0000 => (Opcode::MULU(size), Reinterpret(OperandCategory::SrcDestRegOrDeref)),
869        0b0111_0001 => (Opcode::MULU(size), Reinterpret(OperandCategory::SrcDestRegOrDeref)),
870        0b0111_0010 => (Opcode::MOV(size), Reinterpret(OperandCategory::SrcDestRegOrDeref)),
871        0b0111_0011 => (Opcode::MOV(size), Reinterpret(OperandCategory::SrcDestRegOrDeref)),
872        0b0111_0100 => (Opcode::NOP, Reinterpret(OperandCategory::Op74)),
873        0b0111_0101 => (Opcode::NOP, Reinterpret(OperandCategory::Op74)),
874        0b0111_0110 => (Opcode::NOP, Reinterpret(OperandCategory::Op76)),
875        0b0111_0111 => (Opcode::NOP, Reinterpret(OperandCategory::Op76)),
876        0b0111_1000 => (Opcode::NOP, Reinterpret(OperandCategory::Op78)),
877        0b0111_1001 => (Opcode::NOP, Reinterpret(OperandCategory::Op78)),
878        0b0111_1010 => (Opcode::NOP, Reinterpret(OperandCategory::Op7A)),
879        0b0111_1011 => (Opcode::NOP, Reinterpret(OperandCategory::Op7B)),
880        0b0111_1100 => (Opcode::NOP, Reinterpret(OperandCategory::Op7C)),
881        0b0111_1101 => (Opcode::NOP, Reinterpret(OperandCategory::Op7D)),
882        0b0111_1110 => (Opcode::NOP, Reinterpret(OperandCategory::Op7E)),
883        0b0111_1111 => { return Err(StandardDecodeError::InvalidOperand); },
884        0b1000_0000 => (Opcode::TST(size), Reinterpret(OperandCategory::SrcDestRegOrDeref)),
885        0b1000_0001 => (Opcode::TST(size), Reinterpret(OperandCategory::SrcDestRegOrDeref)),
886        0b1000_0010 => (Opcode::PUSH(Size::B), Just([OperandSpec::R0L, OperandSpec::Nothing, OperandSpec::Nothing])),
887        0b1000_0011 => (Opcode::ADD(Size::B), Just([OperandSpec::Imm8, OperandSpec::R0H, OperandSpec::Nothing])),
888        0b1000_0100 => (Opcode::ADD(Size::B), Just([OperandSpec::Imm8, OperandSpec::R0L, OperandSpec::Nothing])),
889        0b1000_0101 => (Opcode::ADD(Size::B), Just([OperandSpec::Imm8, OperandSpec::Disp8_SB, OperandSpec::Nothing])),
890        0b1000_0110 => (Opcode::ADD(Size::B), Just([OperandSpec::Imm8, OperandSpec::Disp8_FB, OperandSpec::Nothing])),
891        0b1000_0111 => (Opcode::ADD(Size::B), Just([OperandSpec::Imm8, OperandSpec::Abs16, OperandSpec::Nothing])),
892        0b1000_1000 => (Opcode::XOR(size), Reinterpret(OperandCategory::SrcDestRegOrDeref)),
893        0b1000_1001 => (Opcode::XOR(size), Reinterpret(OperandCategory::SrcDestRegOrDeref)),
894        0b1000_1010 => (Opcode::PUSH(Size::B), Just([OperandSpec::R0H, OperandSpec::Nothing, OperandSpec::Nothing])),
895        0b1000_1011 => (Opcode::SUB(Size::B), Just([OperandSpec::Imm8, OperandSpec::R0H, OperandSpec::Nothing])),
896        0b1000_1100 => (Opcode::SUB(Size::B), Just([OperandSpec::Imm8, OperandSpec::R0L, OperandSpec::Nothing])),
897        0b1000_1101 => (Opcode::SUB(Size::B), Just([OperandSpec::Imm8, OperandSpec::Disp8_SB, OperandSpec::Nothing])),
898        0b1000_1110 => (Opcode::SUB(Size::B), Just([OperandSpec::Imm8, OperandSpec::Disp8_FB, OperandSpec::Nothing])),
899        0b1000_1111 => (Opcode::SUB(Size::B), Just([OperandSpec::Imm8, OperandSpec::Abs16, OperandSpec::Nothing])),
900        0b1001_0000 => (Opcode::AND(size), Reinterpret(OperandCategory::SrcDestRegOrDeref)),
901        0b1001_0001 => (Opcode::AND(size), Reinterpret(OperandCategory::SrcDestRegOrDeref)),
902        0b1001_0010 => (Opcode::POP, Just([OperandSpec::R0L, OperandSpec::Nothing, OperandSpec::Nothing])),
903        0b1001_0011 => (Opcode::AND(Size::B), Just([OperandSpec::Imm8, OperandSpec::R0H, OperandSpec::Nothing])),
904        0b1001_0100 => (Opcode::AND(Size::B), Just([OperandSpec::Imm8, OperandSpec::R0L, OperandSpec::Nothing])),
905        0b1001_0101 => (Opcode::AND(Size::B), Just([OperandSpec::Imm8, OperandSpec::Disp8_SB, OperandSpec::Nothing])),
906        0b1001_0110 => (Opcode::AND(Size::B), Just([OperandSpec::Imm8, OperandSpec::Disp8_FB, OperandSpec::Nothing])),
907        0b1001_0111 => (Opcode::AND(Size::B), Just([OperandSpec::Imm8, OperandSpec::Abs16, OperandSpec::Nothing])),
908        0b1001_1000 => (Opcode::OR(size), Reinterpret(OperandCategory::SrcDestRegOrDeref)),
909        0b1001_1001 => (Opcode::OR(size), Reinterpret(OperandCategory::SrcDestRegOrDeref)),
910        0b1001_1010 => (Opcode::POP, Just([OperandSpec::R0H, OperandSpec::Nothing, OperandSpec::Nothing])),
911        0b1001_1011 => (Opcode::OR(Size::B), Just([OperandSpec::Imm8, OperandSpec::R0H, OperandSpec::Nothing])),
912        0b1001_1100 => (Opcode::OR(Size::B), Just([OperandSpec::Imm8, OperandSpec::R0L, OperandSpec::Nothing])),
913        0b1001_1101 => (Opcode::OR(Size::B), Just([OperandSpec::Imm8, OperandSpec::Disp8_SB, OperandSpec::Nothing])),
914        0b1001_1110 => (Opcode::OR(Size::B), Just([OperandSpec::Imm8, OperandSpec::Disp8_FB, OperandSpec::Nothing])),
915        0b1001_1111 => (Opcode::OR(Size::B), Just([OperandSpec::Imm8, OperandSpec::Abs16, OperandSpec::Nothing])),
916        0b1010_0000 => (Opcode::ADD(size), Reinterpret(OperandCategory::SrcDestRegOrDeref)),
917        0b1010_0001 => (Opcode::ADD(size), Reinterpret(OperandCategory::SrcDestRegOrDeref)),
918        0b1010_0010 => (Opcode::MOV(Size::W), Just([OperandSpec::Imm16, OperandSpec::A0, OperandSpec::Nothing])),
919        0b1010_0011 => (Opcode::INC(Size::B), Just([OperandSpec::R0H, OperandSpec::Nothing, OperandSpec::Nothing])),
920        0b1010_0100 => (Opcode::INC(Size::B), Just([OperandSpec::R0L, OperandSpec::Nothing, OperandSpec::Nothing])),
921        0b1010_0101 => (Opcode::INC(Size::B), Just([OperandSpec::Disp8_SB, OperandSpec::Nothing, OperandSpec::Nothing])),
922        0b1010_0110 => (Opcode::INC(Size::B), Just([OperandSpec::Disp8_FB, OperandSpec::Nothing, OperandSpec::Nothing])),
923        0b1010_0111 => (Opcode::INC(Size::B), Just([OperandSpec::Abs16, OperandSpec::Nothing, OperandSpec::Nothing])),
924        0b1010_1000 => (Opcode::SUB(size), Reinterpret(OperandCategory::SrcDestRegOrDeref)),
925        0b1010_1001 => (Opcode::SUB(size), Reinterpret(OperandCategory::SrcDestRegOrDeref)),
926        0b1010_1010 => (Opcode::MOV(Size::W), Just([OperandSpec::Imm16, OperandSpec::A1, OperandSpec::Nothing])),
927        0b1010_1011 => (Opcode::DEC(Size::B), Just([OperandSpec::R0H, OperandSpec::Nothing, OperandSpec::Nothing])),
928        0b1010_1100 => (Opcode::DEC(Size::B), Just([OperandSpec::R0L, OperandSpec::Nothing, OperandSpec::Nothing])),
929        0b1010_1101 => (Opcode::DEC(Size::B), Just([OperandSpec::Disp8_SB, OperandSpec::Nothing, OperandSpec::Nothing])),
930        0b1010_1110 => (Opcode::DEC(Size::B), Just([OperandSpec::Disp8_FB, OperandSpec::Nothing, OperandSpec::Nothing])),
931        0b1010_1111 => (Opcode::DEC(Size::B), Just([OperandSpec::Abs16, OperandSpec::Nothing, OperandSpec::Nothing])),
932        0b1011_0000 => (Opcode::ADC(size), Reinterpret(OperandCategory::SrcDestRegOrDeref)),
933        0b1011_0001 => (Opcode::ADC(size), Reinterpret(OperandCategory::SrcDestRegOrDeref)),
934        0b1011_0010 => (Opcode::INC(Size::W), Just([OperandSpec::A0, OperandSpec::Nothing, OperandSpec::Nothing])),
935        0b1011_0011 => (Opcode::MOV(Size::B), Just([OperandSpec::Zero, OperandSpec::R0H, OperandSpec::Nothing])),
936        0b1011_0100 => (Opcode::MOV(Size::B), Just([OperandSpec::Zero, OperandSpec::R0L, OperandSpec::Nothing])),
937        0b1011_0101 => (Opcode::MOV(Size::B), Just([OperandSpec::Zero, OperandSpec::Disp8_SB, OperandSpec::Nothing])),
938        0b1011_0110 => (Opcode::MOV(Size::B), Just([OperandSpec::Zero, OperandSpec::Disp8_FB, OperandSpec::Nothing])),
939        0b1011_0111 => (Opcode::MOV(Size::B), Just([OperandSpec::Zero, OperandSpec::Abs16, OperandSpec::Nothing])),
940        0b1011_1000 => (Opcode::SBB(size), Reinterpret(OperandCategory::SrcDestRegOrDeref)),
941        0b1011_1001 => (Opcode::SBB(size), Reinterpret(OperandCategory::SrcDestRegOrDeref)),
942        0b1011_1010 => (Opcode::INC(Size::W), Just([OperandSpec::A1, OperandSpec::Nothing, OperandSpec::Nothing])),
943        0b1011_1011 => (Opcode::NOT(Size::B), Just([OperandSpec::R0H, OperandSpec::Nothing, OperandSpec::Nothing])),
944        0b1011_1100 => (Opcode::NOT(Size::B), Just([OperandSpec::R0L, OperandSpec::Nothing, OperandSpec::Nothing])),
945        0b1011_1101 => (Opcode::NOT(Size::B), Just([OperandSpec::Disp8_SB, OperandSpec::Nothing, OperandSpec::Nothing])),
946        0b1011_1110 => (Opcode::NOT(Size::B), Just([OperandSpec::Disp8_FB, OperandSpec::Nothing, OperandSpec::Nothing])),
947        0b1011_1111 => (Opcode::NOT(Size::B), Just([OperandSpec::Abs16, OperandSpec::Nothing, OperandSpec::Nothing])),
948        0b1100_0000 => (Opcode::CMP(size), Reinterpret(OperandCategory::SrcDestRegOrDeref)),
949        0b1100_0001 => (Opcode::CMP(size), Reinterpret(OperandCategory::SrcDestRegOrDeref)),
950        0b1100_0010 => (Opcode::PUSH(Size::W), Just([OperandSpec::A0, OperandSpec::Nothing, OperandSpec::Nothing])),
951        0b1100_0011 => (Opcode::MOV(Size::B), Just([OperandSpec::Imm8, OperandSpec::R0H, OperandSpec::Nothing])),
952        0b1100_0100 => (Opcode::MOV(Size::B), Just([OperandSpec::Imm8, OperandSpec::R0L, OperandSpec::Nothing])),
953        0b1100_0101 => (Opcode::MOV(Size::B), Just([OperandSpec::Imm8, OperandSpec::Disp8_SB, OperandSpec::Nothing])),
954        0b1100_0110 => (Opcode::MOV(Size::B), Just([OperandSpec::Imm8, OperandSpec::Disp8_FB, OperandSpec::Nothing])),
955        0b1100_0111 => (Opcode::MOV(Size::B), Just([OperandSpec::Imm8, OperandSpec::Abs16, OperandSpec::Nothing])),
956        0b1100_1000 => (Opcode::ADD(size), Reinterpret(OperandCategory::Imm4Dest)),
957        0b1100_1001 => (Opcode::ADD(size), Reinterpret(OperandCategory::Imm4Dest)),
958        0b1100_1010 => (Opcode::PUSH(Size::W), Just([OperandSpec::A1, OperandSpec::Nothing, OperandSpec::Nothing])),
959        0b1100_1011 => (Opcode::STZ, Just([OperandSpec::Imm8, OperandSpec::R0H, OperandSpec::Nothing])),
960        0b1100_1100 => (Opcode::STZ, Just([OperandSpec::Imm8, OperandSpec::R0L, OperandSpec::Nothing])),
961        0b1100_1101 => (Opcode::STZ, Just([OperandSpec::Imm8, OperandSpec::Disp8_SB, OperandSpec::Nothing])),
962        0b1100_1110 => (Opcode::STX, Just([OperandSpec::Imm8, OperandSpec::Disp8_FB, OperandSpec::Nothing])),
963        0b1100_1111 => (Opcode::STZ, Just([OperandSpec::Imm8, OperandSpec::Abs16, OperandSpec::Nothing])),
964        0b1101_0000 => (Opcode::CMP(size), Reinterpret(OperandCategory::Imm4Dest)),
965        0b1101_0001 => (Opcode::CMP(size), Reinterpret(OperandCategory::Imm4Dest)),
966        0b1101_0010 => (Opcode::POP, Just([OperandSpec::A0, OperandSpec::Nothing, OperandSpec::Nothing])),
967        0b1101_0011 => (Opcode::STNZ, Just([OperandSpec::Imm8, OperandSpec::R0H, OperandSpec::Nothing])),
968        0b1101_0100 => (Opcode::STNZ, Just([OperandSpec::Imm8, OperandSpec::R0L, OperandSpec::Nothing])),
969        0b1101_0101 => (Opcode::STNZ, Just([OperandSpec::Imm8, OperandSpec::Disp8_SB, OperandSpec::Nothing])),
970        0b1101_0110 => (Opcode::STNZ, Just([OperandSpec::Imm8, OperandSpec::Disp8_FB, OperandSpec::Nothing])),
971        0b1101_0111 => (Opcode::STNZ, Just([OperandSpec::Imm8, OperandSpec::Abs16, OperandSpec::Nothing])),
972        0b1101_1000 => (Opcode::MOV(size), Reinterpret(OperandCategory::Imm4Dest)),
973        0b1101_1001 => (Opcode::MOV(size), Reinterpret(OperandCategory::Imm4Dest)),
974        0b1101_1010 => (Opcode::POP, Just([OperandSpec::A1, OperandSpec::Nothing, OperandSpec::Nothing])),
975        0b1101_1011 => (Opcode::STZX, Just([OperandSpec::Imm8, OperandSpec::R0H, OperandSpec::Imm82])),
976        0b1101_1100 => (Opcode::STZX, Just([OperandSpec::Imm8, OperandSpec::R0L, OperandSpec::Imm82])),
977        0b1101_1101 => (Opcode::STZX, Just([OperandSpec::Imm8, OperandSpec::Disp8_SB, OperandSpec::Imm82])),
978        0b1101_1110 => (Opcode::STZX, Just([OperandSpec::Imm8, OperandSpec::Disp8_FB, OperandSpec::Imm82])),
979        0b1101_1111 => (Opcode::STZX, Just([OperandSpec::Imm8, OperandSpec::Abs16, OperandSpec::Imm82])),
980        0b1110_0000 => (Opcode::ROT(size), Reinterpret(OperandCategory::Imm4Dest)),
981        0b1110_0001 => (Opcode::ROT(size), Reinterpret(OperandCategory::Imm4Dest)),
982        0b1110_0010 => (Opcode::MOV(Size::B), Just([OperandSpec::Imm8, OperandSpec::A0, OperandSpec::Nothing])),
983        0b1110_0011 => (Opcode::CMP(Size::B), Just([OperandSpec::Imm8, OperandSpec::R0H, OperandSpec::Nothing])),
984        0b1110_0100 => (Opcode::CMP(Size::B), Just([OperandSpec::Imm8, OperandSpec::R0L, OperandSpec::Nothing])),
985        0b1110_0101 => (Opcode::CMP(Size::B), Just([OperandSpec::Imm8, OperandSpec::Disp8_SB, OperandSpec::Nothing])),
986        0b1110_0110 => (Opcode::CMP(Size::B), Just([OperandSpec::Imm8, OperandSpec::Disp8_FB, OperandSpec::Nothing])),
987        0b1110_0111 => (Opcode::CMP(Size::B), Just([OperandSpec::Imm8, OperandSpec::Abs16, OperandSpec::Nothing])),
988        0b1110_1000 => (Opcode::SHA(size), Reinterpret(OperandCategory::Imm4Dest)),
989        0b1110_1001 => (Opcode::SHA(size), Reinterpret(OperandCategory::Imm4Dest)),
990        0b1110_1010 => (Opcode::MOV(Size::B), Just([OperandSpec::Imm8, OperandSpec::A1, OperandSpec::Nothing])),
991        0b1110_1011 => (Opcode::NOP, Reinterpret(OperandCategory::OpEB)), // Opcode will be discarded
992        0b1110_1100 => (Opcode::PUSHM, Just([OperandSpec::RegList, OperandSpec::Nothing, OperandSpec::Nothing])),
993        0b1110_1101 => (Opcode::POPM, Just([OperandSpec::RegList, OperandSpec::Nothing, OperandSpec::Nothing])),
994        0b1110_1110 => (Opcode::JMPS, Just([OperandSpec::Imm8, OperandSpec::Nothing, OperandSpec::Nothing])),
995        0b1110_1111 => (Opcode::JSRS, Just([OperandSpec::Imm8, OperandSpec::Nothing, OperandSpec::Nothing])),
996        0b1111_0000 => (Opcode::SHA(size), Reinterpret(OperandCategory::Imm4Dest)),
997        0b1111_0001 => (Opcode::SHA(size), Reinterpret(OperandCategory::Imm4Dest)),
998        0b1111_0010 => (Opcode::DEC(Size::W), Just([OperandSpec::A0, OperandSpec::Nothing, OperandSpec::Nothing])),
999        0b1111_0011 => (Opcode::RTS, Just([OperandSpec::Nothing, OperandSpec::Nothing, OperandSpec::Nothing])),
1000        0b1111_0100 => (Opcode::JMP(Size::W), Just([OperandSpec::JmpDisp16, OperandSpec::Nothing, OperandSpec::Nothing])),
1001        0b1111_0101 => (Opcode::JSR(Size::W), Just([OperandSpec::JmpDisp16, OperandSpec::Nothing, OperandSpec::Nothing])),
1002        0b1111_0110 => (Opcode::INTO, Just([OperandSpec::Nothing, OperandSpec::Nothing, OperandSpec::Nothing])),
1003        0b1111_0111 => { return Err(StandardDecodeError::InvalidOperand); },
1004        0b1111_1000 => (Opcode::ADJNZ(size), Reinterpret(OperandCategory::ADJNZ)),
1005        0b1111_1001 => (Opcode::ADJNZ(size), Reinterpret(OperandCategory::ADJNZ)),
1006        0b1111_1010 => (Opcode::DEC(Size::W), Just([OperandSpec::A1, OperandSpec::Nothing, OperandSpec::Nothing])),
1007        0b1111_1011 => (Opcode::REIT, Just([OperandSpec::Nothing, OperandSpec::Nothing, OperandSpec::Nothing])),
1008        0b1111_1100 => (Opcode::JMP(Size::A), Just([OperandSpec::JmpAbs20, OperandSpec::Nothing, OperandSpec::Nothing])),
1009        0b1111_1101 => (Opcode::JSR(Size::A), Just([OperandSpec::JmpAbs20, OperandSpec::Nothing, OperandSpec::Nothing])),
1010        0b1111_1110 => (Opcode::JMP(Size::B), Just([OperandSpec::JmpDisp8, OperandSpec::Nothing, OperandSpec::Nothing])),
1011        0b1111_1111 => (Opcode::UND, Just([OperandSpec::Nothing, OperandSpec::Nothing, OperandSpec::Nothing])),
1012    };
1013    inst.opcode = opcode;
1014    match interpretation {
1015        Just(operands) => {
1016            inst.operands = operands;
1017
1018            // in the base opcode map, if an immediate is specified it comes before bytes for
1019            // displacement/absolute address that may be part of a destination.
1020            //
1021            // additionally, Imm8 or Imm16 is the first operand, if present. so look for that
1022            // first.
1023            if let OperandSpec::Imm8 = inst.operands[0] {
1024                inst.imm_wide = read_imm(words, 1)? as u32;
1025                inst.length += 1;
1026            }
1027
1028            // now, read bytes for remaining operands, EXCEPT STZX which we read most but not all
1029            // of. it specifies a second imm8 after optional disp/abs
1030            for op in inst.operands.iter() {
1031                use OperandSpec::*;
1032                match op {
1033                    RegList => {
1034                        inst.imm_wide = read_imm(words, 1)? as u32;
1035                        inst.length += 1;
1036
1037                        // internally, the register list is given one order.
1038                        // however, the m16c encoding specifies reverse order for pushm/popm
1039                        // register lists.. so, reverse it here and make it correct for everyone
1040                        // else.
1041                        if let Opcode::POPM = inst.opcode {
1042                            let mut replacement_imm = 0u8;
1043                            for i in 0..8 {
1044                                if inst.imm_wide & (1 << i) != 0 {
1045                                    replacement_imm |= 1 << (7 - i);
1046                                }
1047                            }
1048                            inst.imm_wide = replacement_imm as u32;
1049                        }
1050                    },
1051                    JmpDisp8 |
1052                    Disp8 |
1053                    Disp8_FB |
1054                    Disp8_SB => {
1055                        // have to sign extend in case these displacements are negative
1056                        inst.dispabs = read_imm(words, 1)? as i8 as i16 as u16;
1057                        inst.length += 1;
1058                    }
1059                    JmpDisp16 |
1060                    Abs16 => {
1061                        inst.dispabs = read_imm(words, 2)? as u16;
1062                        inst.length += 2;
1063                    }
1064                    JmpAbs20 |
1065                    Abs20 => {
1066                        inst.imm_wide = read_imm(words, 3)? as u32 & 0x0f_ff_ff;
1067                        inst.length += 3;
1068                    }
1069                    Disp8_A0 |
1070                    Disp8_A1 |
1071                    Disp8_SP |
1072                    Disp16_A0 |
1073                    Disp16_A1 |
1074                    Disp16_SB |
1075                    Disp20_A0 |
1076                    Disp20_A1 |
1077                    Deref_A0 |
1078                    Deref_A1 |
1079                    Deref_A1A0 |
1080                    Disp2_8_A0 |
1081                    Disp2_8_A1 |
1082                    Disp2_8_SB |
1083                    Disp2_8_FB |
1084                    Disp2_16_A0 |
1085                    Disp2_16_A1 |
1086                    Disp2_16_SB |
1087                    Abs2_16 |
1088                    Bit_Disp8_A0 |
1089                    Bit_Disp8_A1 |
1090                    Bit_Disp8_SB |
1091                    Bit_Disp8_FB |
1092                    Bit_Disp16_A0 |
1093                    Bit_Disp16_A1 |
1094                    Bit_Disp16_SB |
1095                    Bit_Abs16 => {
1096                        panic!("unexpected operand spec for Just set of operands: {:?}", op);
1097                    }
1098                    // and other operands? yeah just ignore em
1099                    _ => {}
1100                }
1101            }
1102
1103            // now for STZX, really,...
1104            if let OperandSpec::Imm82 = inst.operands[2] {
1105                inst.imm_wide |= (words.next()? as u32) << 8;
1106                inst.length += 1;
1107            }
1108
1109            return Ok(());
1110        },
1111        Reinterpret(OperandCategory::Op74) => {
1112            return decode_op74(inst, size, words);
1113        },
1114        Reinterpret(OperandCategory::Op76) => {
1115            return decode_op76(inst, size, words);
1116        },
1117        Reinterpret(OperandCategory::Op78) => {
1118            return decode_op78(inst, size, words);
1119        },
1120        Reinterpret(OperandCategory::Op7A) => {
1121            return decode_op7A(inst, size, words);
1122        },
1123        Reinterpret(OperandCategory::Op7B) => {
1124            return decode_op7B(inst, size, words);
1125        },
1126        Reinterpret(OperandCategory::Op7C) => {
1127            return decode_op7C(inst, size, words);
1128        },
1129        Reinterpret(OperandCategory::Op7D) => {
1130            return decode_op7D(inst, size, words);
1131        },
1132        Reinterpret(OperandCategory::Op7E) => {
1133            return decode_op7E(inst, size, words);
1134        },
1135        Reinterpret(OperandCategory::OpEB) => {
1136            return decode_opEB(inst, size, words);
1137        },
1138        Reinterpret(OperandCategory::Imm4Dest) => {
1139            let operands = words.next()?;
1140            inst.length += 1;
1141            inst.imm_wide = (operands as i8 >> 4) as i32 as u32;
1142            inst.operands[0] = OperandSpec::Imm4;
1143            inst.operands[1] = Operand_RegDerefDispAbs(operands & 0b1111, size, inst, words)?;
1144            inst.operands[2] = OperandSpec::Nothing;
1145        }
1146        Reinterpret(OperandCategory::JmpDispOpcodeLow3) => {
1147            inst.dispabs = (byte & 0b111) as u16;
1148            inst.operands[0] = OperandSpec::Disp8;
1149            inst.operands[1] = OperandSpec::Nothing;
1150            inst.operands[2] = OperandSpec::Nothing;
1151        }
1152        Reinterpret(OperandCategory::ADJNZ) => {
1153            // ADJNZ has operands like any other [IMM4|DEST] operand, but takes an additional byte
1154            // for the destination label.
1155            let operands = words.next()?;
1156            inst.length += 1;
1157            inst.imm_wide = ((operands as i8) >> 4) as u32;
1158            inst.operands[0] = OperandSpec::Imm4;
1159            inst.operands[1] = Operand_RegDerefDispAbs(operands & 0b1111, size, inst, words)?;
1160            inst.operands[2] = OperandSpec::Label8;
1161        }
1162        Reinterpret(OperandCategory::SrcDestRegOrDeref) => {
1163            // these instructions can read two disp8/disp16, so the first one can be handled
1164            // normally, but the second will need some fixing up...
1165            let operands = words.next()?;
1166            inst.length += 1;
1167            inst.operands[0] = Operand_RegDerefDispAbs(operands >> 4, size, inst, words)?;
1168            inst.operands[1] = Operand_second_RegDerefDispAbs(operands & 0b1111, size, inst, words)?;
1169            inst.operands[2] = OperandSpec::Nothing;
1170        }
1171    }
1172    Ok(())
1173}
1174
1175fn decode_op74<T: Reader<<M16C as Arch>::Address, <M16C as Arch>::Word>>(inst: &mut Instruction, size: Size, words: &mut T) -> Result<(), <M16C as Arch>::DecodeError> {
1176    let byte = words.next()?;
1177    inst.length += 1;
1178    match byte >> 4 {
1179        0b0000 => {
1180            inst.opcode = Opcode::STE;
1181            inst.operands[0] = Operand_RegDerefDispAbs(byte & 0b1111, size, inst, words)?;
1182            inst.operands[1] = OperandSpec::Abs20;
1183            inst.imm_wide = read_imm(words, 3)? & 0x0f_ff_ff;
1184            inst.length += 3;
1185        }
1186        0b0001 => {
1187            inst.opcode = Opcode::STE;
1188            inst.operands[0] = Operand_RegDerefDispAbs(byte & 0b1111, size, inst, words)?;
1189            inst.operands[1] = OperandSpec::Disp20_A0;
1190            inst.imm_wide = read_imm(words, 3)? & 0x0f_ff_ff;
1191            inst.length += 3;
1192        }
1193        0b0010 => {
1194            inst.opcode = Opcode::STE;
1195            inst.operands[0] = Operand_RegDerefDispAbs(byte & 0b1111, size, inst, words)?;
1196            inst.operands[1] = OperandSpec::Deref_A1A0;
1197        }
1198        0b0011 => {
1199            inst.opcode = Opcode::MOV(size);
1200            inst.operands[0] = Operand_RegDerefDispAbs(byte & 0b1111, size, inst, words)?;
1201            inst.operands[1] = OperandSpec::Disp8_SP;
1202        }
1203        0b0100 => {
1204            inst.opcode = Opcode::PUSH(size);
1205            inst.operands[0] = Operand_RegDerefDispAbs(byte & 0b1111, size, inst, words)?;
1206            inst.operands[1] = OperandSpec::Nothing;
1207        }
1208        0b0101 => {
1209            inst.opcode = Opcode::NEG;
1210            inst.operands[0] = Operand_RegDerefDispAbs(byte & 0b1111, size, inst, words)?;
1211            inst.operands[1] = OperandSpec::Nothing;
1212        }
1213        0b0110 => {
1214            inst.opcode = Opcode::ROT(size);
1215            if size == Size::W && byte & 0b1111 == 0b0001 {
1216                // invalid dest, would be R1
1217                return Err(StandardDecodeError::InvalidOperand);
1218            } else if size == Size::B && byte & 0b1111 == 0b0011 {
1219                // invalid dest, would be R1H
1220                return Err(StandardDecodeError::InvalidOperand);
1221            }
1222
1223            inst.operands[0] = OperandSpec::R1H;
1224            inst.operands[1] = Operand_RegDerefDispAbs(byte & 0b1111, size, inst, words)?;
1225        }
1226        0b0111 => {
1227            inst.opcode = Opcode::NOT(size);
1228            inst.operands[0] = Operand_RegDerefDispAbs(byte & 0b1111, size, inst, words)?;
1229            inst.operands[1] = OperandSpec::Nothing;
1230        }
1231        0b1000 => {
1232            inst.opcode = Opcode::LDE;
1233            inst.operands[0] = OperandSpec::Abs20;
1234            inst.operands[1] = Operand_RegDerefDispAbs(byte & 0b1111, size, inst, words)?;
1235            // careful! abs20 comes after dest disp/abs
1236            inst.imm_wide = read_imm(words, 3)? & 0x0f_ff_ff;
1237            inst.length += 3;
1238        }
1239        0b1001 => {
1240            inst.opcode = Opcode::LDE;
1241            inst.operands[0] = OperandSpec::Disp20_A0;
1242            inst.operands[1] = Operand_RegDerefDispAbs(byte & 0b1111, size, inst, words)?;
1243            // careful! disp20 comes after dest disp/abs
1244            inst.imm_wide = read_imm(words, 3)? & 0x0f_ff_ff;
1245            inst.length += 3;
1246        }
1247        0b1010 => {
1248            inst.opcode = Opcode::LDE;
1249            inst.operands[0] = OperandSpec::Deref_A1A0;
1250            inst.operands[1] = Operand_RegDerefDispAbs(byte & 0b1111, size, inst, words)?;
1251        }
1252        0b1011 => {
1253            inst.opcode = Opcode::MOV(size);
1254            inst.operands[0] = OperandSpec::Disp8_SP;
1255            inst.operands[1] = Operand_RegDerefDispAbs(byte & 0b1111, size, inst, words)?;
1256            // careful! disp8 comes after dest disp/abs
1257            inst.dispabs = read_imm(words, 1)? as u16;
1258            inst.length += 1;
1259        }
1260        0b1100 => {
1261            inst.opcode = Opcode::MOV(size);
1262            inst.operands[0] = if size == Size::W { OperandSpec::Imm16 } else { OperandSpec::Imm8 };
1263            inst.operands[1] = Operand_RegDerefDispAbs(byte & 0b1111, size, inst, words)?;
1264            // careful! imm comes after dest disp/abs
1265            inst.imm_wide = read_imm(words, size.as_bytes())? as u32;
1266            inst.length += size.as_bytes();
1267        }
1268        0b1101 => {
1269            inst.opcode = Opcode::POP;
1270            inst.operands[0] = Operand_RegDerefDispAbs(byte & 0b1111, size, inst, words)?;
1271            inst.operands[1] = OperandSpec::Nothing;
1272        }
1273        0b1110 => {
1274            inst.opcode = Opcode::SHL(size);
1275            if size == Size::W && byte & 0b1111 == 0b0001 {
1276                // invalid dest, would be R1
1277                return Err(StandardDecodeError::InvalidOperand);
1278            } else if size == Size::B && byte & 0b1111 == 0b0011 {
1279                // invalid dest, would be R1H
1280                return Err(StandardDecodeError::InvalidOperand);
1281            }
1282
1283            inst.operands[0] = OperandSpec::R1H;
1284            inst.operands[1] = Operand_RegDerefDispAbs(byte & 0b1111, size, inst, words)?;
1285        }
1286        0b1111 => {
1287            inst.opcode = Opcode::SHA(size);
1288            if size == Size::W && byte & 0b1111 == 0b0001 {
1289                // invalid dest, would be R1
1290                return Err(StandardDecodeError::InvalidOperand);
1291            } else if size == Size::B && byte & 0b1111 == 0b0011 {
1292                // invalid dest, would be R1H
1293                return Err(StandardDecodeError::InvalidOperand);
1294            }
1295
1296            inst.operands[0] = OperandSpec::R1H;
1297            inst.operands[1] = Operand_RegDerefDispAbs(byte & 0b1111, size, inst, words)?;
1298        }
1299        _ => {
1300            unreachable!("opcode selector is four bits");
1301        }
1302    }
1303
1304    Ok(())
1305}
1306
1307fn decode_op76<T: Reader<<M16C as Arch>::Address, <M16C as Arch>::Word>>(inst: &mut Instruction, size: Size, words: &mut T) -> Result<(), <M16C as Arch>::DecodeError> {
1308    let byte = words.next()?;
1309    inst.length += 1;
1310    let opc_selector = byte >> 4;
1311    if opc_selector < 0b1001 {
1312        inst.opcode = [
1313            Opcode::TST(size), Opcode::XOR(size), Opcode::AND(size),
1314            Opcode::OR(size), Opcode::ADD(size), Opcode::SUB(size),
1315            Opcode::ADC(size), Opcode::SBB(size), Opcode::CMP(size)
1316        ][opc_selector as usize];
1317        inst.operands[1] = Operand_RegDerefDispAbs(byte & 0b1111, size, inst, words)?;
1318        inst.operands[0] = if size == Size::W { OperandSpec::Imm16 } else { OperandSpec::Imm8 };
1319        inst.imm_wide = read_imm(words, size.as_bytes())?;
1320        inst.length += size.as_bytes();
1321    } else {
1322        match opc_selector {
1323            0b1001 => {
1324                inst.opcode = Opcode::DIVX(size);
1325                inst.operands[0] = if size == Size::W { OperandSpec::Imm16 } else { OperandSpec::Imm8 };
1326                inst.imm_wide = read_imm(words, size.as_bytes())?;
1327                inst.length += size.as_bytes();
1328            }
1329            0b1010 => {
1330                inst.opcode = Opcode::ROLC;
1331                inst.operands[0] = Operand_RegDerefDispAbs(byte & 0b1111, size, inst, words)?;
1332                inst.operands[1] = OperandSpec::Nothing;
1333            }
1334            0b1011 => {
1335                inst.opcode = Opcode::RORC;
1336                inst.operands[0] = Operand_RegDerefDispAbs(byte & 0b1111, size, inst, words)?;
1337                inst.operands[1] = OperandSpec::Nothing;
1338            }
1339            0b1100 => {
1340                inst.opcode = Opcode::DIVU(size);
1341                inst.operands[0] = if size == Size::W { OperandSpec::Imm16 } else { OperandSpec::Imm8 };
1342                inst.imm_wide = read_imm(words, size.as_bytes())?;
1343                inst.length += size.as_bytes();
1344            }
1345            0b1101 => {
1346                inst.opcode = Opcode::DIV(size);
1347                inst.operands[0] = Operand_RegDerefDispAbs(byte & 0b1111, size, inst, words)?;
1348                inst.operands[1] = OperandSpec::Nothing;
1349            }
1350            0b1110 => {
1351                inst.opcode = Opcode::ADCF(size);
1352                inst.operands[1] = Operand_RegDerefDispAbs(byte & 0b1111, size, inst, words)?;
1353                inst.operands[0] = if size == Size::W { OperandSpec::Imm16 } else { OperandSpec::Imm8 };
1354                inst.imm_wide = read_imm(words, size.as_bytes())?;
1355                inst.length += size.as_bytes();
1356            }
1357            0b1111 => {
1358                inst.opcode = Opcode::ABS;
1359                inst.operands[0] = Operand_RegDerefDispAbs(byte & 0b1111, size, inst, words)?;
1360                inst.operands[1] = OperandSpec::Nothing;
1361            }
1362            _ => {
1363                unreachable!("opcode selector is four bits");
1364            }
1365        }
1366    }
1367
1368    Ok(())
1369}
1370
1371fn decode_op78<T: Reader<<M16C as Arch>::Address, <M16C as Arch>::Word>>(inst: &mut Instruction, size: Size, words: &mut T) -> Result<(), <M16C as Arch>::DecodeError> {
1372    let byte = words.next()?;
1373    inst.length += 1;
1374    inst.opcode = Opcode::MUL;
1375    inst.operands[0] = Operand_RegDerefDispAbs(byte >> 4, size, inst, words)?;
1376    let dest_code = byte & 0b1111;
1377    match (size, dest_code) {
1378        (Size::B, 0b0001) |
1379        (Size::W, 0b0010) |
1380        (_, 0b0011) |
1381        (_, 0b0101) => {
1382            return Err(StandardDecodeError::InvalidOperand);
1383        }
1384        _ => {}
1385    }
1386    inst.operands[1] = Operand_RegDerefDispAbs(dest_code, size, inst, words)?;
1387
1388    Ok(())
1389}
1390
1391fn decode_op7A<T: Reader<<M16C as Arch>::Address, <M16C as Arch>::Word>>(inst: &mut Instruction, size: Size, words: &mut T) -> Result<(), <M16C as Arch>::DecodeError> {
1392    let byte = words.next()?;
1393    inst.length += 1;
1394    if byte >= 0b10000000 {
1395        inst.opcode = Opcode::LDC;
1396        inst.operands[0] = Operand_RegDerefDispAbs(byte & 0b1111, size, inst, words)?;
1397        inst.operands[1] = Operand_IntFlgSpSbFb((byte >> 4) & 0b111)?;
1398    } else {
1399        inst.opcode = Opcode::XCHG(size);
1400        assert_eq!(size, Size::B);
1401        if byte >= 0b01000000 {
1402            return Err(StandardDecodeError::InvalidOperand);
1403        }
1404        inst.operands[0] = [
1405            OperandSpec::R0L, OperandSpec::R0H,
1406            OperandSpec::R1L, OperandSpec::R1H,
1407        ][(byte >> 4) as usize];
1408        inst.operands[1] = Operand_RegDerefDispAbs(byte & 0b1111, size, inst, words)?;
1409    }
1410
1411    Ok(())
1412}
1413
1414fn decode_op7B<T: Reader<<M16C as Arch>::Address, <M16C as Arch>::Word>>(inst: &mut Instruction, size: Size, words: &mut T) -> Result<(), <M16C as Arch>::DecodeError> {
1415    let byte = words.next()?;
1416    inst.length += 1;
1417    if byte >= 0b10000000 {
1418        inst.opcode = Opcode::STC;
1419        inst.operands[1] = Operand_IntFlgSpSbFb((byte >> 4) & 0b111)?;
1420        inst.operands[0] = Operand_RegDerefDispAbs(byte & 0b1111, size, inst, words)?;
1421    } else {
1422        inst.opcode = Opcode::XCHG(size);
1423        assert_eq!(size, Size::W);
1424        if byte >= 0b01000000 {
1425            return Err(StandardDecodeError::InvalidOperand);
1426        }
1427        inst.operands[0] = [
1428            OperandSpec::R0, OperandSpec::R1,
1429            OperandSpec::R2, OperandSpec::R3,
1430        ][(byte >> 4) as usize];
1431        inst.operands[1] = Operand_RegDerefDispAbs(byte & 0b1111, size, inst, words)?;
1432    }
1433
1434    Ok(())
1435}
1436
1437fn decode_op7C<T: Reader<<M16C as Arch>::Address, <M16C as Arch>::Word>>(inst: &mut Instruction, size: Size, words: &mut T) -> Result<(), <M16C as Arch>::DecodeError> {
1438    let byte = words.next()?;
1439    inst.length += 1;
1440    match byte >> 4 {
1441        op @ 0b0000 |
1442        op @ 0b0001 |
1443        op @ 0b0010 |
1444        op @ 0b0011 => {
1445            inst.opcode = [
1446                Opcode::MOVLL, Opcode::MOVLH,
1447                Opcode::MOVHL, Opcode::MOVHH,
1448            ][op as usize];
1449            inst.operands[0] = Operand_RegDerefDispAbs(byte & 0b1111, size, inst, words)?;
1450            inst.operands[1] = OperandSpec::R0L;
1451        },
1452        0b0100 => {
1453            inst.opcode = Opcode::MULU(size);
1454            inst.operands[0] = if size == Size::W { OperandSpec::Imm16 } else { OperandSpec::Imm8 };
1455            inst.operands[1] = Operand_RegDerefDispAbs(byte >> 4, size, inst, words)?;
1456            let dest_code = byte & 0b1111;
1457            match (size, dest_code) {
1458                (Size::B, 0b0001) |
1459                (Size::W, 0b0010) |
1460                (_, 0b0011) |
1461                (_, 0b0101) => {
1462                    return Err(StandardDecodeError::InvalidOperand);
1463                }
1464                _ => {}
1465            }
1466            // careful! imm comes after dest disp/abs
1467            inst.imm_wide = read_imm(words, size.as_bytes())?;
1468            inst.length += size.as_bytes();
1469        },
1470        0b0101 => {
1471            inst.opcode = Opcode::MUL;
1472            inst.operands[0] = if size == Size::W { OperandSpec::Imm16 } else { OperandSpec::Imm8 };
1473            inst.operands[1] = Operand_RegDerefDispAbs(byte >> 4, size, inst, words)?;
1474            let dest_code = byte & 0b1111;
1475            match (size, dest_code) {
1476                (Size::B, 0b0001) |
1477                (Size::W, 0b0010) |
1478                (_, 0b0011) |
1479                (_, 0b0101) => {
1480                    return Err(StandardDecodeError::InvalidOperand);
1481                }
1482                _ => {}
1483            }
1484            // careful! imm comes after dest disp/abs
1485            inst.imm_wide = read_imm(words, size.as_bytes())?;
1486            inst.length += size.as_bytes();
1487        }
1488        0b0110 => {
1489            // byte is 0b0110_xxxx
1490            inst.opcode = Opcode::EXTS;
1491            match byte & 0b1111 {
1492                0b0001 |
1493                0b0011 |
1494                0b0100 |
1495                0b0101 => {
1496                    return Err(StandardDecodeError::InvalidOperand);
1497                }
1498                _ => {}
1499            }
1500            inst.operands[0] = Operand_RegDerefDispAbs(byte & 0b1111, size, inst, words)?;
1501            inst.operands[1] = OperandSpec::Nothing;
1502        }
1503        op @ 0b1000 |
1504        op @ 0b1001 |
1505        op @ 0b1010 |
1506        op @ 0b1011 => {
1507            inst.opcode = [
1508                Opcode::MOVLL, Opcode::MOVLH,
1509                Opcode::MOVHL, Opcode::MOVHH,
1510            ][(op & 0b11) as usize];
1511            inst.operands[0] = OperandSpec::R0L;
1512            inst.operands[1] = Operand_RegDerefDispAbs(byte & 0b1111, size, inst, words)?;
1513        }
1514        0b1100 => {
1515            inst.opcode = Opcode::EXTS;
1516            let dest = match byte & 0b1111 {
1517                0b0010 |
1518                0b0011 |
1519                0b0101 => {
1520                    return Err(StandardDecodeError::InvalidOperand);
1521                }
1522                0b0000 => OperandSpec::R2R0,
1523                0b0001 => OperandSpec::R3R1,
1524                0b0100 => OperandSpec::A1A0,
1525                code => {
1526                    Operand_RegDerefDispAbs(code, size, inst, words)?
1527                }
1528            };
1529            inst.operands[0] = dest;
1530            inst.operands[1] = OperandSpec::Nothing;
1531        }
1532        0b1110 => {
1533            let code = byte & 0b1111;
1534            if code & 0b111 < 0b100 {
1535                match code {
1536                    op @ 0b0000 |
1537                    op @ 0b0001 |
1538                    op @ 0b0010 |
1539                    op @ 0b0011 => {
1540                        inst.opcode = [
1541                            Opcode::DIVU(size), Opcode::DIV(size),
1542                            Opcode::PUSH(size), Opcode::DIVX(size),
1543                        ][op as usize];
1544                        inst.operands[0] = if size == Size::W { OperandSpec::Imm16 } else { OperandSpec::Imm8 };
1545                        inst.operands[1] = OperandSpec::Nothing;
1546                        inst.operands[2] = OperandSpec::Nothing;
1547                        inst.imm_wide = read_imm(words, size.as_bytes())?;
1548                        inst.length += size.as_bytes();
1549                    }
1550                    op @ 0b1000 |
1551                    op @ 0b1001 |
1552                    op @ 0b1010 => {
1553                        inst.opcode = [
1554                            Opcode::SMOVF(size), Opcode::SMOVB(size),
1555                            Opcode::SSTR(size),
1556                        ][(op & 0b11) as usize];
1557                        inst.operands = [OperandSpec::Nothing, OperandSpec::Nothing, OperandSpec::Nothing];
1558                    }
1559                    0b1011 => {
1560                        inst.opcode = Opcode::ADD(size);
1561                        inst.operands[0] = if size == Size::W { OperandSpec::Imm16 } else { OperandSpec::Imm8 };
1562                        inst.operands[1] = OperandSpec::SP;
1563                        inst.operands[2] = OperandSpec::Nothing;
1564                        inst.imm_wide = read_imm(words, size.as_bytes())?;
1565                        inst.length += size.as_bytes();
1566                    }
1567                    _ => { unreachable!("this should be an invalid bit pattern"); }
1568                }
1569            } else {
1570                inst.opcode = [
1571                    Opcode::DADD, Opcode::DSUB,
1572                    Opcode::DADC, Opcode::DSBB,
1573                ][(code & 0b11) as usize];
1574                if code < 0b1000 {
1575                    // reg-reg variants of these opcodes
1576                    inst.operands[0] = OperandSpec::R0H;
1577                    inst.operands[1] = OperandSpec::R0L;
1578                } else {
1579                    // reg-imm8 variants of these opcodes
1580                    inst.operands[0] = OperandSpec::Imm8;
1581                    inst.operands[1] = OperandSpec::R0L;
1582                    assert_eq!(size, Size::B);
1583                    inst.imm_wide = read_imm(words, size.as_bytes())?;
1584                    inst.length += size.as_bytes();
1585                }
1586            }
1587        }
1588        0b1111 => {
1589            match byte & 0b1111 {
1590                0b0000 => {
1591                    inst.opcode = Opcode::LDCTX;
1592                    inst.operands[0] = OperandSpec::Abs16;
1593                    inst.dispabs = read_imm(words, 2)? as u16;
1594                    inst.length += 2;
1595                    inst.operands[1] = OperandSpec::Abs20;
1596                    inst.imm_wide = read_imm(words, 3)? & 0x0f_ff_ff;
1597                    inst.length += 3;
1598                }
1599                0b0001 => {
1600                    inst.opcode = Opcode::RMPA(size);
1601                    inst.operands[0] = OperandSpec::Nothing;
1602                    inst.operands[1] = OperandSpec::Nothing;
1603                }
1604                0b0010 => {
1605                    inst.opcode = Opcode::ENTER;
1606                    inst.operands[0] = OperandSpec::Imm8;
1607                    inst.imm_wide = read_imm(words, 1)?;
1608                    inst.length += 1;
1609                    inst.operands[1] = OperandSpec::Nothing;
1610                }
1611                0b0011 => {
1612                    inst.opcode = Opcode::EXTS;
1613                    inst.operands[0] = OperandSpec::R0;
1614                    inst.operands[1] = OperandSpec::Nothing;
1615                }
1616                _ => {
1617                    return Err(StandardDecodeError::InvalidOpcode);
1618                }
1619            }
1620        }
1621        _ => {
1622            return Err(StandardDecodeError::InvalidOpcode);
1623        }
1624    }
1625
1626    Ok(())
1627}
1628
1629fn decode_op7D<T: Reader<<M16C as Arch>::Address, <M16C as Arch>::Word>>(inst: &mut Instruction, size: Size, words: &mut T) -> Result<(), <M16C as Arch>::DecodeError> {
1630    let byte = words.next()?;
1631    inst.length += 1;
1632    match byte >> 4 {
1633        op @ 0b0000 |
1634        op @ 0b0001 |
1635        op @ 0b0010 |
1636        op @ 0b0011 => {
1637            inst.opcode = [
1638                Opcode::JMPI, Opcode::JSRI,
1639                Opcode::JMPI, Opcode::JSRI,
1640            ][op as usize];
1641            inst.operands[0] = Operand_RegDerefDisp20Abs(byte & 0b1111, inst, words)?;
1642            inst.operands[1] = OperandSpec::Nothing;
1643        }
1644        0b0100 => {
1645            inst.opcode = Opcode::MULU(size);
1646            inst.operands[0] = if size == Size::W { OperandSpec::Imm16 } else { OperandSpec::Imm8 };
1647            inst.operands[1] = Operand_RegDerefDispAbs(byte >> 4, size, inst, words)?;
1648            let dest_code = byte & 0b1111;
1649            match (size, dest_code) {
1650                (Size::B, 0b0001) |
1651                (Size::W, 0b0010) |
1652                (_, 0b0011) |
1653                (_, 0b0101) => {
1654                    return Err(StandardDecodeError::InvalidOperand);
1655                }
1656                _ => {}
1657            }
1658            // careful! imm comes after dest disp/abs
1659            inst.imm_wide = read_imm(words, size.as_bytes())?;
1660            inst.length += size.as_bytes();
1661        },
1662        0b0101 => {
1663            inst.opcode = Opcode::MUL;
1664            inst.operands[0] = if size == Size::W { OperandSpec::Imm16 } else { OperandSpec::Imm8 };
1665            inst.operands[1] = Operand_RegDerefDispAbs(byte >> 4, size, inst, words)?;
1666            let dest_code = byte & 0b1111;
1667            match (size, dest_code) {
1668                (Size::B, 0b0001) |
1669                (Size::W, 0b0010) |
1670                (_, 0b0011) |
1671                (_, 0b0101) => {
1672                    return Err(StandardDecodeError::InvalidOperand);
1673                }
1674                _ => {}
1675            }
1676            // careful! imm comes after dest disp/abs
1677            inst.imm_wide = read_imm(words, size.as_bytes())?;
1678            inst.length += size.as_bytes();
1679        }
1680        0b1001 => {
1681            // byte is 0b1001_xxxx
1682            if byte < 0b1001_1000 {
1683                return Err(StandardDecodeError::InvalidOperand);
1684            }
1685            // byte is 0b1001_1xxx
1686
1687            inst.opcode = Opcode::PUSHA;
1688            // while the low eight forms of this encoding are invalid, they would have been rejected above.
1689            inst.operands[0] = Operand_RegDerefDispAbs(byte & 0b1111, size, inst, words)?;
1690            inst.operands[1] = OperandSpec::Nothing;
1691        }
1692        0b1010 => {
1693            if byte >= 0b1010_1000 {
1694                return Err(StandardDecodeError::InvalidOperand);
1695            }
1696            inst.opcode = Opcode::LDIPL;
1697            inst.operands[0] = OperandSpec::Imm8;
1698            inst.operands[1] = OperandSpec::Nothing;
1699            inst.imm_wide = ((((byte & 0b111) as i8) << 5) >> 5) as i32 as u32;
1700        }
1701        0b1011 => {
1702            // byte is 0b1011_xxxx
1703            inst.opcode = Opcode::ADD(size);
1704            inst.operands[0] = OperandSpec::Imm8;
1705            inst.operands[1] = OperandSpec::SP;
1706            inst.imm_wide = ((((byte & 0b111) as i8) << 4) >> 4) as i32 as u32;
1707        }
1708        0b1100 => {
1709            inst.opcode = match byte & 0b1111 {
1710                0b1000 => Opcode::JLE,
1711                0b1001 => Opcode::JO,
1712                0b1010 => Opcode::JGE,
1713                0b1100 => Opcode::JGT,
1714                0b1101 => Opcode::JNO,
1715                0b1110 => Opcode::JLT,
1716                _ => {
1717                    return Err(StandardDecodeError::InvalidOpcode);
1718                }
1719            };
1720            inst.operands[0] = OperandSpec::Disp8;
1721            inst.operands[1] = OperandSpec::Nothing;
1722            inst.imm_wide = read_imm(words, 1)?;
1723            inst.length += 1;
1724        }
1725        0b1101 => {
1726            let code = byte & 0b1111;
1727            if code == 0b1011 || code == 0b1111 {
1728                return Err(StandardDecodeError::InvalidOpcode);
1729            }
1730            // the NOP here fill gaps that are invalid encodings as tested above.
1731            inst.opcode = [
1732                Opcode::BMGEU, Opcode::BMGTU, Opcode::BMEQ, Opcode::BMN,
1733                Opcode::BMLTU, Opcode::BMLEU, Opcode::BMNE, Opcode::BMPZ,
1734                Opcode::BMLE,  Opcode::BMO,   Opcode::GE,   Opcode::NOP,
1735                Opcode::BMGT,  Opcode::NO,    Opcode::LT,   Opcode::NOP,
1736            ][code as usize];
1737            inst.operands[0] = OperandSpec::Nothing;
1738            inst.operands[1] = OperandSpec::Nothing;
1739        }
1740        0b1110 => {
1741            let code = byte & 0b1111;
1742            if code & 0b111 < 0b100 {
1743                match code {
1744                    op @ 0b0000 |
1745                    op @ 0b0001 |
1746                    op @ 0b0010 |
1747                    op @ 0b0011 => {
1748                        inst.opcode = [
1749                            Opcode::DIVU(size), Opcode::DIV(size),
1750                            Opcode::PUSH(size), Opcode::DIVX(size),
1751                        ][op as usize];
1752                        inst.operands[0] = if size == Size::W { OperandSpec::Imm16 } else { OperandSpec::Imm8 };
1753                        inst.operands[1] = OperandSpec::Nothing;
1754                        inst.operands[2] = OperandSpec::Nothing;
1755                        inst.imm_wide = read_imm(words, size.as_bytes())?;
1756                        inst.length += size.as_bytes();
1757                    }
1758                    op @ 0b1000 |
1759                    op @ 0b1001 |
1760                    op @ 0b1010 => {
1761                        inst.opcode = [
1762                            Opcode::SMOVF(size), Opcode::SMOVB(size),
1763                            Opcode::SSTR(size),
1764                        ][(op & 0b11) as usize];
1765                        inst.operands = [OperandSpec::Nothing, OperandSpec::Nothing, OperandSpec::Nothing];
1766                    }
1767                    0b1011 => {
1768                        inst.opcode = Opcode::ADD(size);
1769                        inst.operands[0] = if size == Size::W { OperandSpec::Imm16 } else { OperandSpec::Imm8 };
1770                        inst.operands[1] = OperandSpec::SP;
1771                        inst.operands[2] = OperandSpec::Nothing;
1772                        inst.imm_wide = read_imm(words, size.as_bytes())?;
1773                        inst.length += size.as_bytes();
1774                    }
1775                    _ => { unreachable!("this should be an invalid bit pattern"); }
1776                }
1777            } else {
1778                inst.opcode = [
1779                    Opcode::DADD, Opcode::DSUB,
1780                    Opcode::DADC, Opcode::DSBB,
1781                ][(code & 0b11) as usize];
1782                if code < 0b1000 {
1783                    // reg-reg variants of these opcodes
1784                    inst.operands[0] = OperandSpec::R1;
1785                    inst.operands[1] = OperandSpec::R0;
1786                } else {
1787                    // reg-imm16 variants of these opcodes
1788                    inst.operands[0] = OperandSpec::Imm16;
1789                    inst.operands[1] = OperandSpec::R0;
1790                    assert_eq!(size, Size::W);
1791                    inst.imm_wide = read_imm(words, size.as_bytes())?;
1792                    inst.length += size.as_bytes();
1793                }
1794            }
1795        }
1796        0b1111 => {
1797            // byte is 0b1111_xxxx
1798            match byte & 0b1111 {
1799                0b0000 => {
1800                    inst.opcode = Opcode::STCTX;
1801                    inst.operands[0] = OperandSpec::Abs16;
1802                    inst.dispabs = read_imm(words, 2)? as u16;
1803                    inst.length += 2;
1804                    inst.operands[1] = OperandSpec::Abs20;
1805                    inst.imm_wide = read_imm(words, 3)? & 0x0f_ff_ff;
1806                    inst.length += 3;
1807                }
1808                0b0001 => {
1809                    inst.opcode = Opcode::RMPA(size);
1810                    inst.operands[0] = OperandSpec::Nothing;
1811                    inst.operands[1] = OperandSpec::Nothing;
1812                }
1813                0b0010 => {
1814                    inst.opcode = Opcode::EXITD;
1815                    inst.operands[0] = OperandSpec::Nothing;
1816                    inst.operands[1] = OperandSpec::Nothing;
1817                }
1818                0b0011 => {
1819                    inst.opcode = Opcode::WAIT;
1820                    inst.operands[0] = OperandSpec::Nothing;
1821                    inst.operands[1] = OperandSpec::Nothing;
1822                }
1823                _ => {
1824                    return Err(StandardDecodeError::InvalidOpcode);
1825                }
1826            }
1827        }
1828        _ => {
1829            return Err(StandardDecodeError::InvalidOpcode);
1830        }
1831    }
1832
1833    Ok(())
1834}
1835
1836fn decode_op7E<T: Reader<<M16C as Arch>::Address, <M16C as Arch>::Word>>(inst: &mut Instruction, _size: Size, words: &mut T) -> Result<(), <M16C as Arch>::DecodeError> {
1837    let byte = words.next()?;
1838    inst.length += 1;
1839    let op = byte >> 4;
1840    let code = byte & 0b1111;
1841    if op > 0b1101 {
1842        return Err(StandardDecodeError::InvalidOpcode);
1843    }
1844    if op == 0b0010 {
1845        // handle BMCMD specifically
1846        inst.operands[0] = Operand_BitRegDerefDispAbs(code, inst, words)?;
1847        inst.operands[1] = OperandSpec::Nothing;
1848        let cnd = read_imm(words, 1)? as u8;
1849        inst.length += 1;
1850        inst.opcode = match cnd {
1851            0b0000_0000 => Opcode::BMGEU,
1852            0b0000_0001 => Opcode::BMGTU,
1853            0b0000_0010 => Opcode::BMEQ,
1854            0b0000_0011 => Opcode::BMN,
1855            0b0000_0100 => Opcode::BMLE,
1856            0b0000_0101 => Opcode::BMO,
1857            0b0000_0110 => Opcode::BMGE,
1858            0b1111_1000 => Opcode::BMLTU,
1859            0b1111_1001 => Opcode::BMLEU,
1860            0b1111_1010 => Opcode::BMNE,
1861            0b1111_1011 => Opcode::BMPZ,
1862            0b1111_1100 => Opcode::BMGT,
1863            0b1111_1101 => Opcode::BMNO,
1864            0b1111_1110 => Opcode::BMLT,
1865            _ => {
1866                return Err(StandardDecodeError::InvalidOpcode);
1867            }
1868        };
1869    } else {
1870        inst.opcode = [
1871            Opcode::BTSTC, Opcode::BTSTS, Opcode::NOP, // NOP is unreachable, tested above
1872            Opcode::BNTST, Opcode::BAND,  Opcode::BNAND,
1873            Opcode::BOR,   Opcode::BNOR,  Opcode::BCLR,
1874            Opcode::BSET,  Opcode::BNOT,  Opcode::BTST,
1875            Opcode::BXOR,  Opcode::BNXOR,
1876        ][op as usize];
1877        inst.operands[0] = Operand_BitRegDerefDispAbs(code, inst, words)?;
1878        inst.operands[1] = OperandSpec::Nothing;
1879    }
1880
1881    Ok(())
1882}
1883
1884fn decode_opEB<T: Reader<<M16C as Arch>::Address, <M16C as Arch>::Word>>(inst: &mut Instruction, _size: Size, words: &mut T) -> Result<(), <M16C as Arch>::DecodeError> {
1885    let byte = words.next()?;
1886    inst.length += 1;
1887    let upper = byte >> 4;
1888    let lower = byte & 0b1111;
1889    if upper < 0b1000 {
1890        // SHL, SHA, LDC, POPC, MOVA, PUSHC, FSET, or FCLR
1891        match lower {
1892            0b0000 => {
1893                // LDC
1894                inst.opcode = Opcode::LDC;
1895                inst.operands[0] = OperandSpec::Imm16;
1896                inst.operands[1] = Operand_IntFlgSpSbFb((byte >> 4) & 0b111)?;
1897                inst.imm_wide = read_imm(words, 2)?;
1898                inst.length += 2;
1899            }
1900            0b0001 => {
1901                // SHL/SHA
1902                inst.opcode = if upper & 2 == 0 { Opcode::SHL(Size::L) } else { Opcode::SHA(Size::L) };
1903                inst.operands[0] = OperandSpec::R1H;
1904                inst.operands[1] = if upper & 1 == 0 { OperandSpec::R2R0 } else { OperandSpec::R3R1 };
1905            }
1906            0b0010 => {
1907                // PUSHC
1908                inst.opcode = Opcode::PUSHC;
1909                inst.operands[0] = Operand_IntFlgSpSbFb((byte >> 4) & 0b111)?;
1910                inst.operands[1] = OperandSpec::Nothing;
1911            },
1912            0b0011 => {
1913                // POPC
1914                inst.opcode = Opcode::POPC;
1915                inst.operands[0] = Operand_IntFlgSpSbFb((byte >> 4) & 0b111)?;
1916                inst.operands[1] = OperandSpec::Nothing;
1917            }
1918            0b0100 => {
1919                // FSET
1920            }
1921            0b0101 => {
1922                // FCLR
1923            }
1924            _ => {
1925                // MOVA
1926                inst.opcode = Opcode::MOVA;
1927                let src = byte & 0b1111;
1928                if src < 0b1000 {
1929                    return Err(StandardDecodeError::InvalidOperand);
1930                }
1931                inst.operands[0] = Operand_RegDerefDispAbs(src, Size::W, inst, words)?;
1932                let dest = byte >> 4;
1933                if dest >= 0b1000 {
1934                    return Err(StandardDecodeError::InvalidOperand);
1935                }
1936                inst.operands[1] = Operand_RegDerefDispAbs(dest, Size::W, inst, words)?;
1937            }
1938        }
1939    } else {
1940        // SHL Imm4, SHA Imm4, or INT
1941        if upper >= 0b1100 {
1942            inst.opcode = Opcode::INT;
1943            inst.operands[0] = OperandSpec::Imm8;
1944            inst.operands[1] = OperandSpec::Nothing;
1945            inst.imm_wide = (byte & 0b0011_1111) as u32;
1946        } else {
1947            inst.opcode = if upper & 2 == 0 { Opcode::SHL(Size::L) } else { Opcode::SHA(Size::L) };
1948            inst.operands[0] = OperandSpec::Imm4;
1949            inst.imm_wide = lower as u32;
1950            inst.operands[1] = if upper & 1 == 0 { OperandSpec::R2R0 } else { OperandSpec::R3R1 };
1951        }
1952    }
1953
1954    Ok(())
1955}
1956
1957fn read_imm<T: Reader<<M16C as Arch>::Address, <M16C as Arch>::Word>>(words: &mut T, mut size: u8) -> Result<u32, <M16C as Arch>::DecodeError> {
1958    let mut imm: u32 = 0;
1959    let mut offset = 0;
1960
1961    while size > 0 {
1962        imm |= (words.next()? as u32) << (8 * offset);
1963        offset += 1;
1964        size -= 1;
1965    }
1966
1967    Ok(imm)
1968}
1969
1970
1971fn Operand_BitRegDerefDispAbs<T: Reader<<M16C as Arch>::Address, <M16C as Arch>::Word>>(code: u8, inst: &mut Instruction, words: &mut T) -> Result<OperandSpec, <M16C as Arch>::DecodeError> {
1972    use OperandSpec::*;
1973    // "bit,<reg>" addressing modes taking their bit selector from a following byte is left mostly
1974    // unspoken in the manual, aside from the "bit,Rn" and "bit,An" modes taking an extra byte.
1975    let (imm_size, spec) = match code {
1976        0b0000 => (1, Bit_R0),
1977        0b0001 => (1, Bit_R1),
1978        0b0010 => (1, Bit_R2),
1979        0b0011 => (1, Bit_R3),
1980        0b0100 => (1, Bit_A0),
1981        0b0101 => (1, Bit_A1),
1982        0b0110 => (0, Bit_Deref_A0),
1983        0b0111 => (0, Bit_Deref_A1),
1984        0b1000 => (1, Bit_Disp8_A0),
1985        0b1001 => (1, Bit_Disp8_A1),
1986        0b1010 => (1, Bit_Disp8_SB),
1987        0b1011 => (1, Bit_Disp8_FB),
1988        0b1100 => (2, Bit_Disp16_A0),
1989        0b1101 => (2, Bit_Disp16_A1),
1990        0b1110 => (2, Bit_Disp16_SB),
1991        0b1111 => (2, Bit_Abs16),
1992        _ => { unreachable!("invalid code provided, >0b1111"); }
1993    };
1994
1995    if imm_size > 0 {
1996        inst.dispabs = words.next()? as u16;
1997        inst.length += 1;
1998
1999        if imm_size == 2 {
2000            inst.dispabs |= (words.next()? as u16) << 8;
2001            inst.length += 1;
2002        }
2003    }
2004
2005    Ok(spec)
2006
2007}
2008
2009fn Operand_RegDerefDispAbs<T: Reader<<M16C as Arch>::Address, <M16C as Arch>::Word>>(code: u8, size: Size, inst: &mut Instruction, words: &mut T) -> Result<OperandSpec, <M16C as Arch>::DecodeError> {
2010    use OperandSpec::*;
2011    let (imm_size, spec) = match code {
2012        0b0000 => (0, { if size == Size::B { R0L } else { R0 } }),
2013        0b0001 => (0, { if size == Size::B { R0H } else { R1 } }),
2014        0b0010 => (0, { if size == Size::B { R1L } else { R2 } }),
2015        0b0011 => (0, { if size == Size::B { R1H } else { R3 } }),
2016        0b0100 => (0, A0),
2017        0b0101 => (0, A1),
2018        0b0110 => (0, Deref_A0),
2019        0b0111 => (0, Deref_A1),
2020        0b1000 => (1, Disp8_A0),
2021        0b1001 => (1, Disp8_A1),
2022        0b1010 => (1, Disp8_SB),
2023        0b1011 => (1, Disp8_FB),
2024        0b1100 => (2, Disp16_A0),
2025        0b1101 => (2, Disp16_A1),
2026        0b1110 => (2, Disp16_SB),
2027        0b1111 => (2, Abs16),
2028        _ => { unreachable!("invalid code provided, >0b1111"); }
2029    };
2030
2031    if imm_size > 0 {
2032        inst.dispabs = words.next()? as u16;
2033        inst.length += 1;
2034
2035        if imm_size == 2 {
2036            inst.dispabs |= (words.next()? as u16) << 8;
2037            inst.length += 1;
2038        }
2039    }
2040
2041    Ok(spec)
2042}
2043
2044fn Operand_second_RegDerefDispAbs<T: Reader<<M16C as Arch>::Address, <M16C as Arch>::Word>>(code: u8, size: Size, inst: &mut Instruction, words: &mut T) -> Result<OperandSpec, <M16C as Arch>::DecodeError> {
2045    use OperandSpec::*;
2046    let (imm_size, spec) = match code {
2047        0b0000 => (0, { if size == Size::B { R0L } else { R0 } }),
2048        0b0001 => (0, { if size == Size::B { R0H } else { R1 } }),
2049        0b0010 => (0, { if size == Size::B { R1L } else { R2 } }),
2050        0b0011 => (0, { if size == Size::B { R1H } else { R3 } }),
2051        0b0100 => (0, A0),
2052        0b0101 => (0, A1),
2053        0b0110 => (0, Deref_A0),
2054        0b0111 => (0, Deref_A1),
2055        0b1000 => (1, Disp2_8_A0),
2056        0b1001 => (1, Disp2_8_A1),
2057        0b1010 => (1, Disp2_8_SB),
2058        0b1011 => (1, Disp2_8_FB),
2059        0b1100 => (2, Disp2_16_A0),
2060        0b1101 => (2, Disp2_16_A1),
2061        0b1110 => (2, Disp2_16_SB),
2062        0b1111 => (2, Abs2_16),
2063        _ => { unreachable!("invalid code provided, >0b1111"); }
2064    };
2065
2066    if imm_size > 0 {
2067        inst.imm_wide = words.next()? as u32;
2068        inst.length += 1;
2069
2070        if imm_size == 2 {
2071            inst.imm_wide |= (words.next()? as u32) << 8;
2072            inst.length += 1;
2073        }
2074    }
2075
2076    Ok(spec)
2077}
2078
2079fn Operand_RegDerefDisp20Abs<T: Reader<<M16C as Arch>::Address, <M16C as Arch>::Word>>(code: u8, inst: &mut Instruction, words: &mut T) -> Result<OperandSpec, <M16C as Arch>::DecodeError> {
2080    use OperandSpec::*;
2081    let (imm_size, spec) = match code {
2082        0b0000 => (0, R2R0),
2083        0b0001 => (0, R3R1),
2084        0b0010 => { return Err(StandardDecodeError::InvalidOperand); },
2085        0b0011 => { return Err(StandardDecodeError::InvalidOperand); },
2086        0b0100 => (0, A1A0),
2087        0b0101 => { return Err(StandardDecodeError::InvalidOperand); },
2088        0b0110 => (0, Deref_A0),
2089        0b0111 => (0, Deref_A1),
2090        0b1000 => (1, Disp8_A0),
2091        0b1001 => (1, Disp8_A1),
2092        0b1010 => (1, Disp8_SB),
2093        0b1011 => (1, Disp8_FB),
2094        0b1100 => (3, Disp20_A0),
2095        0b1101 => (3, Disp20_A1),
2096        0b1110 => (2, Disp16_SB),
2097        0b1111 => (2, Abs16),
2098        _ => { unreachable!("invalid code provided, >0b1111"); }
2099    };
2100
2101    match imm_size {
2102        0 => {}
2103        1 => {
2104            inst.dispabs = words.next()? as u16;
2105            inst.length += 1;
2106        }
2107        2 => {
2108            inst.dispabs = words.next()? as u16;
2109            inst.dispabs |= (words.next()? as u16) << 8;
2110            inst.length += 2;
2111        }
2112        3 => {
2113            inst.imm_wide = words.next()? as u32;
2114            inst.imm_wide |= (words.next()? as u32) << 8;
2115            inst.imm_wide |= ((words.next()? & 0x0f) as u32) << 16;
2116            inst.length += 3;
2117        }
2118        _ => {
2119            unreachable!();
2120        }
2121    }
2122
2123    Ok(spec)
2124}
2125
2126fn Operand_IntFlgSpSbFb(code: u8) -> Result<OperandSpec, <M16C as Arch>::DecodeError> {
2127    use OperandSpec::*;
2128
2129    match code {
2130        0b001 => Ok(INTBL),
2131        0b010 => Ok(INTBH),
2132        0b011 => Ok(FLG),
2133        0b100 => Ok(ISP),
2134        0b101 => Ok(SP),
2135        0b110 => Ok(SB),
2136        0b111 => Ok(FB),
2137        _ => Err(StandardDecodeError::InvalidOperand)
2138    }
2139}