yaxpeax_avr/
lib.rs

1//! AVR decoders implemented as part of the `yaxpeax` project. Implements traits
2//! provided by `yaxpeax-arch`.
3//!
4//! Instruction set manual references are with respect to the document
5//! [`Atmel-0856-AVR-Instruction-Set-Manual.pdf`](http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-0856-AVR-Instruction-Set-Manual.pdf)
6//! as of 2020-04-13. `sha256: dbf578218c9f52f2fd22ccc538f53b9db4890320835725678c02b7b58f641981`
7//!
8//! References to the ATmega48A/PA/88A/PA/168A/PA/328/P datasheet are with
9//! respect to the document [`ATmega48A-PA-88A-PA-168A-PA-328-P-DS-DS40002061A.pdf`](http://ww1.microchip.com/downloads/en/DeviceDoc/ATmega48A-PA-88A-PA-168A-PA-328-P-DS-DS40002061A.pdf)
10//! as of 2020-04-13. `sha256: bf1c2e470f8ec7d4db340984f57556342557fed3eb9c457dd174b08db5993af6`
11//!
12//! Known "issues":
13//! - The `brbc` and `brbs` instructions are displayed as their equivalent
14//!   pseudo-instructions, based on the bit they test: `brbc 0, label` becomes
15//!   `brsh label`. In this case specifically, `brcc` also exists (and is
16//!   identical), however `brsh` will be displayed.
17//! - Target specification is limited to enabling/disabling support for 16-bit
18//!   `sts` and `lds` instructions (as they can collide with other instructions
19//!   cores with support for them don't have). Valid instructions (even if they
20//!   might be unsupported by a core) are never rejected. Bytes which don't
21//!   resemble an instruction from _any_ instruction set subset are still
22//!   invalid.
23extern crate yaxpeax_arch;
24
25use yaxpeax_arch::{Arch, AddressDiff, Decoder, LengthedInstruction, Reader, StandardDecodeError};
26
27use std::fmt;
28
29#[derive(Debug, Copy, Clone, PartialEq)]
30pub enum SREGBit {
31    C, Z, N, V, S, H, T, I
32}
33
34impl SREGBit {
35    fn from_bit_index(idx: u8) -> SREGBit {
36        use SREGBit::*;
37        match idx {
38            0 => C,
39            1 => Z,
40            2 => N,
41            3 => V,
42            4 => S,
43            5 => H,
44            6 => T,
45            7 => I,
46            _ => panic!("invalid sreg bit index"),
47        }
48    }
49}
50
51impl fmt::Display for SREGBit {
52    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
53        use SREGBit::*;
54        write!(f, "{}", match self {
55            C => 'c',
56            Z => 'z',
57            N => 'n',
58            V => 'v',
59            S => 's',
60            H => 'h',
61            T => 't',
62            I => 'i',
63        })
64    }
65}
66
67#[derive(Debug, Copy, Clone, PartialEq)]
68pub enum Opcode {
69    ADC,
70    ADD,
71    ADIW,
72    AND,
73    ANDI,
74    ASR,
75    BCLR(SREGBit),
76    BLD,
77    BRBC(SREGBit),
78    BRBS(SREGBit),
79    BREAK,
80    BSET(SREGBit),
81    BST,
82    CALL,
83    CBI,
84    COM,
85    CP,
86    CPC,
87    CPI,
88    CPSE,
89    DEC,
90    DES,
91    EICALL,
92    EIJMP,
93    ELPM,
94    EOR,
95    FMUL,
96    FMULS,
97    FMULSU,
98    ICALL,
99    IJMP,
100    IN,
101    INC,
102    JMP,
103    LAC,
104    LAS,
105    LAT,
106    LD,
107    LDD,
108    LDI,
109    LDS,
110    LPM,
111    LSR,
112    MOV,
113    MOVW,
114    MUL,
115    MULS,
116    MULSU,
117    NEG,
118    NOP,
119    OR,
120    ORI,
121    OUT,
122    POP,
123    PUSH,
124    RCALL,
125    RET,
126    RETI,
127    RJMP,
128    ROR,
129    SBC,
130    SBCI,
131    SBI,
132    SBIC,
133    SBIS,
134    SBIW,
135    SBRC,
136    SBRS,
137    SLEEP,
138    SPM,
139    ST,
140    STD,
141    STS,
142    SUB,
143    SUBI,
144    SWAP,
145    WDR,
146    XCH,
147}
148
149impl fmt::Display for Opcode {
150    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
151        match self {
152            Opcode::ADC => write!(f, "adc"),
153            Opcode::ADD => write!(f, "add"),
154            Opcode::ADIW => write!(f, "adiw"),
155            Opcode::AND => write!(f, "and"),
156            Opcode::ANDI => write!(f, "andi"),
157            Opcode::ASR => write!(f, "asr"),
158            Opcode::BCLR(bit) => write!(f, "cl{}", bit),
159            Opcode::BLD => write!(f, "bld"),
160            Opcode::BRBC(_) | Opcode::BRBS(_) => {
161                let (bit, is_clear) = match self {
162                    Opcode::BRBC(bit) => (bit, true),
163                    Opcode::BRBS(bit) => (bit, false),
164                    _ => unreachable!(),
165                };
166
167                let (suffix_clear, suffix_set) = match bit {
168                    SREGBit::C => ("sh", "lo"),
169                    SREGBit::Z => ("ne", "eq"),
170                    SREGBit::N => ("pl", "mi"),
171                    SREGBit::V => ("vc", "vs"),
172                    SREGBit::S => ("ge", "lt"),
173                    SREGBit::H => ("hc", "hs"),
174                    SREGBit::T => ("tc", "ts"),
175                    SREGBit::I => ("id", "ie"),
176                };
177                let suffix = if is_clear {
178                    suffix_clear
179                } else {
180                    suffix_set
181                };
182
183                write!(f, "br{}", suffix)
184            },
185            Opcode::BREAK => write!(f, "break"),
186            Opcode::BSET(bit) => write!(f, "se{}", bit),
187            Opcode::BST => write!(f, "bst"),
188            Opcode::CALL => write!(f, "call"),
189            Opcode::CBI => write!(f, "cbi"),
190            Opcode::COM => write!(f, "com"),
191            Opcode::CP => write!(f, "cp"),
192            Opcode::CPC => write!(f, "cpc"),
193            Opcode::CPI => write!(f, "cpi"),
194            Opcode::CPSE => write!(f, "cpse"),
195            Opcode::DEC => write!(f, "dec"),
196            Opcode::DES => write!(f, "des"),
197            Opcode::EICALL => write!(f, "eicall"),
198            Opcode::EIJMP => write!(f, "eijmp"),
199            Opcode::ELPM => write!(f, "elpm"),
200            Opcode::EOR => write!(f, "eor"),
201            Opcode::FMUL => write!(f, "fmul"),
202            Opcode::FMULS => write!(f, "fmuls"),
203            Opcode::FMULSU => write!(f, "fmulsu"),
204            Opcode::ICALL => write!(f, "icall"),
205            Opcode::IJMP => write!(f, "ijmp"),
206            Opcode::IN => write!(f, "in"),
207            Opcode::INC => write!(f, "inc"),
208            Opcode::JMP => write!(f, "jmp"),
209            Opcode::LAC => write!(f, "lac"),
210            Opcode::LAS => write!(f, "las"),
211            Opcode::LAT => write!(f, "lat"),
212            Opcode::LD => write!(f, "ld"),
213            Opcode::LDD => write!(f, "ldd"),
214            Opcode::LDI => write!(f, "ldi"),
215            Opcode::LDS => write!(f, "lds"),
216            Opcode::LPM => write!(f, "lpm"),
217            Opcode::LSR => write!(f, "lsr"),
218            Opcode::MOV => write!(f, "mov"),
219            Opcode::MOVW => write!(f, "movw"),
220            Opcode::MUL => write!(f, "mul"),
221            Opcode::MULS => write!(f, "muls"),
222            Opcode::MULSU => write!(f, "mulsu"),
223            Opcode::NEG => write!(f, "neg"),
224            Opcode::NOP => write!(f, "nop"),
225            Opcode::OR => write!(f, "or"),
226            Opcode::ORI => write!(f, "ori"),
227            Opcode::OUT => write!(f, "out"),
228            Opcode::POP => write!(f, "pop"),
229            Opcode::PUSH => write!(f, "push"),
230            Opcode::RCALL => write!(f, "rcall"),
231            Opcode::RET => write!(f, "ret"),
232            Opcode::RETI => write!(f, "reti"),
233            Opcode::RJMP => write!(f, "rjmp"),
234            Opcode::ROR => write!(f, "ror"),
235            Opcode::SBC => write!(f, "sbc"),
236            Opcode::SBCI => write!(f, "sbci"),
237            Opcode::SBI => write!(f, "sbi"),
238            Opcode::SBIC => write!(f, "sbic"),
239            Opcode::SBIS => write!(f, "sbis"),
240            Opcode::SBIW => write!(f, "sbiw"),
241            Opcode::SBRC => write!(f, "sbrc"),
242            Opcode::SBRS => write!(f, "sbrs"),
243            Opcode::SLEEP => write!(f, "sleep"),
244            Opcode::SPM => write!(f, "spm"),
245            Opcode::ST => write!(f, "st"),
246            Opcode::STD => write!(f, "std"),
247            Opcode::STS => write!(f, "sts"),
248            Opcode::SUB => write!(f, "sub"),
249            Opcode::SUBI => write!(f, "subi"),
250            Opcode::SWAP => write!(f, "swap"),
251            Opcode::WDR => write!(f, "wdr"),
252            Opcode::XCH => write!(f, "xch"),
253        }
254    }
255}
256
257#[derive(Debug, Copy, Clone, PartialEq)]
258pub enum IndexRegister {
259    X,
260    Y,
261    Z
262}
263
264#[derive(Debug, Copy, Clone, PartialEq)]
265pub enum IndexRegisterModifier {
266    Unchanged,
267    PostIncrement,
268    PreDecrement,
269    Displacement(u8),
270}
271
272#[derive(Debug, Copy, Clone, PartialEq)]
273pub enum Register {
274    Register(u8),
275    /// A register pair (Rn+1:Rn), where `low` stores `n >> 1`
276    RegisterPair { low: u8 },
277    IndexRegister(IndexRegister, IndexRegisterModifier)
278}
279
280#[derive(Debug, Copy, Clone)]
281enum OperandSpec {
282    Nothing,
283    ImpliedRegister(Register),
284    /// `.... ...d dddd ....`
285    DestRegister,
286    /// `.... ..r. .... rrrr`
287    SrcRegister,
288    /// `.... .... dddd ....`, where `dddd` is the register index minus 16
289    DestRegister16_31,
290    /// `.... .... .... rrrr`, where `rrrr` is the register index minus 16
291    SrcRegister16_31,
292    /// `.... .... ..dd ....`, where `dd` is an index into `[24, 26, 28, 30]`
293    /// for the low register of the pair
294    RegisterPair24_26_28_30,
295    /// `.... .... .ddd ....` where `ddd` is the register index minus 16
296    DestRegister16_23,
297    /// `.... .... .... .rrr` where `rrr` is the register index minus 16
298    SrcRegister16_23,
299    /// `.... .... dddd ....` where `dddd` is `d >> 1` from `Rd+1:Rd`
300    DestRegisterPair,
301    /// `.... .... .... rrrr` where `rrrr` is `r >> 1` from `Rr+1:Rr`
302    SrcRegisterPair,
303    /// `.... .... .... .bbb` or `.... .... .... .sss`
304    Imm3,
305    /// `.... .... KKKK ....`
306    Imm4,
307    /// `.... .... KK.. KKKK`
308    Imm6,
309    /// `.... KKKK .... KKKK`
310    Imm8,
311    /// `..q. qq.. .... .qqq`
312    RegDisp6(IndexRegister),
313    /// `.... ..kk kkkk k...`
314    BranchDisp7,
315    /// `.... kkkk kkkk kkkk`
316    RCALLJMPDisp12,
317    /// `.... .... AAAA A...`
318    Addr5,
319    /// `.... .AA. .... AAAA`
320    Addr6,
321    /// `.... .kkk .... kkkk`
322    Addr7,
323    /// `.... .... .... ....` `kkkk kkkk kkkk kkkk` (two words)
324    Addr16,
325    /// `.... ...k kkkk ...k` `kkkk kkkk kkkk kkkk` (two words)
326    Addr22,
327}
328
329#[derive(Debug, Copy, Clone, PartialEq)]
330pub enum Operand {
331    Nothing,
332    Register(Register),
333    ImmediateU8(u8),
334    AddrPCRelative(i16),
335    AddrAbsolute(u32),
336    BitIndex(u8),
337}
338
339impl fmt::Display for Operand {
340    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
341        match self {
342            Operand::Nothing => panic!("can't display empty operand"),
343            Operand::Register(r) => match r {
344                Register::Register(i) => write!(f, "r{}", i),
345                Register::RegisterPair { low } => {
346                    let base = low * 2;
347                    write!(f, "r{}:r{}", base + 1, base)
348                },
349                Register::IndexRegister(r, modifier) => {
350                    let reg_name = match r {
351                        IndexRegister::X => "x",
352                        IndexRegister::Y => "y",
353                        IndexRegister::Z => "z",
354                    };
355
356                    match modifier {
357                        IndexRegisterModifier::Unchanged => write!(f, "{}", reg_name),
358                        IndexRegisterModifier::PostIncrement => write!(f, "{}+", reg_name),
359                        IndexRegisterModifier::PreDecrement => write!(f, "-{}", reg_name),
360                        IndexRegisterModifier::Displacement(d) => write!(f, "{}+{}", reg_name, d),
361                    }
362                }
363            }
364            Operand::ImmediateU8(v) => write!(f, "${:02X}", v),
365            Operand::AddrPCRelative(v) => if *v == 0 {
366                write!(f, "pc")
367            } else {
368                write!(f, "pc{:+}", v)
369            },
370            Operand::AddrAbsolute(v) => write!(f, "${:X}", v),
371            Operand::BitIndex(i) => write!(f, "{}", i),
372        }
373    }
374}
375
376#[derive(Debug, Copy, Clone, PartialEq)]
377pub struct Instruction {
378    pub opcode: Opcode,
379    pub operands: [Operand; 2],
380    length: u8,
381}
382
383impl Default for Instruction {
384    fn default() -> Self {
385        Instruction {
386            opcode: Opcode::NOP,
387            operands: [Operand::Nothing, Operand::Nothing],
388            length: 2,
389        }
390    }
391}
392
393impl fmt::Display for Instruction {
394    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
395        write!(f, "{}", self.opcode)?;
396        match &self.operands[0] {
397            Operand::Nothing => return Ok(()),
398            operand => write!(f, " {}", operand)?,
399        }
400        match &self.operands[1] {
401            Operand::Nothing => return Ok(()),
402            operand => write!(f, ", {}", operand)?,
403        }
404
405        Ok(())
406    }
407}
408
409impl yaxpeax_arch::Instruction for Instruction {
410    // TODO: this is wrong!!
411    fn well_defined(&self) -> bool {
412        true
413    }
414}
415
416impl LengthedInstruction for Instruction {
417    type Unit = AddressDiff<<AVR as Arch>::Address>;
418
419    fn min_size() -> Self::Unit {
420        AddressDiff::from_const(2)
421    }
422
423    fn len(&self) -> Self::Unit {
424        AddressDiff::from_const(self.length as <AVR as Arch>::Address)
425    }
426}
427
428#[derive(Debug, Copy, Clone, PartialEq)]
429pub struct Target {
430    /// True if the target supports the 16-bit variants of the `lds` and `sts`
431    /// instructions.
432    pub has_16_bit_lds_sts: bool
433}
434
435fn decode_opcode(fullword: u16, target: &Target) -> Option<(Opcode, [OperandSpec; 2])> {
436    // vvvv prefix4
437    // xxxx xxxx xxxx xxxx
438    // ^^^^ ^^^^ ^ prefix9
439    let prefix4 = fullword >> (16 - 4);
440    let prefix5 = fullword >> (16 - 5);
441    let prefix6 = fullword >> (16 - 6);
442    let prefix7 = fullword >> (16 - 7);
443    let prefix8 = fullword >> (16 - 8);
444    let prefix9 = fullword >> (16 - 9);
445
446    //                vvvv suffix4
447    // xxxx xxxx xxxx xxxx < suffix4_1
448    //                ^^^
449    //          suffix4_3
450    let suffix4 = fullword & 0b1111;
451    let suffix4_3 = suffix4 >> 1;
452    let suffix4_1 = suffix4 & 0b1;
453
454    match fullword {
455        0b1001_0101_1001_1000 => return Some((Opcode::BREAK, [OperandSpec::Nothing, OperandSpec::Nothing])),
456        0b1001_0101_0001_1001 => return Some((Opcode::EICALL, [OperandSpec::Nothing, OperandSpec::Nothing])),
457        0b1001_0100_0001_1001 => return Some((Opcode::EIJMP, [OperandSpec::Nothing, OperandSpec::Nothing])),
458        0b1001_0101_1101_1000 => return Some((Opcode::ELPM, [OperandSpec::Nothing, OperandSpec::Nothing])),
459        0b1001_0101_0000_1001 => return Some((Opcode::ICALL, [OperandSpec::Nothing, OperandSpec::Nothing])),
460        0b1001_0100_0000_1001 => return Some((Opcode::IJMP, [OperandSpec::Nothing, OperandSpec::Nothing])),
461        0b1001_0101_1100_1000 => return Some((Opcode::LPM, [OperandSpec::Nothing, OperandSpec::Nothing])),
462        0b0000_0000_0000_0000 => return Some((Opcode::NOP, [OperandSpec::Nothing, OperandSpec::Nothing])),
463        0b1001_0101_0000_1000 => return Some((Opcode::RET, [OperandSpec::Nothing, OperandSpec::Nothing])),
464        0b1001_0101_0001_1000 => return Some((Opcode::RETI, [OperandSpec::Nothing, OperandSpec::Nothing])),
465        0b1001_0101_1000_1000 => return Some((Opcode::SLEEP, [OperandSpec::Nothing, OperandSpec::Nothing])),
466        // In the instruction set reference ("116. SPM", pg. 169), this
467        // instruction is shown with an implied operand of "Z+", but the
468        // ATmega328 datasheet (a processor which has only the single SPM
469        // instruction) shows that it's only a "Z" operand. This seems
470        // consistent on every processor that only has a single SPM instruction.
471        // Since it's consistently a "Z" operand, we'll leave it off to make the
472        // output compatible with both (`avrasm2` rejects `spm z` on cores
473        // without an `spm z+`)
474        0b1001_0101_1110_1000 => return Some((Opcode::SPM, [OperandSpec::Nothing, OperandSpec::Nothing])),
475        0b1001_0101_1111_1000 => return Some((Opcode::SPM, [OperandSpec::ImpliedRegister(Register::IndexRegister(IndexRegister::Z, IndexRegisterModifier::PostIncrement)), OperandSpec::Nothing])),
476        0b1001_0101_1010_1000 => return Some((Opcode::WDR, [OperandSpec::Nothing, OperandSpec::Nothing])),
477        _ => {},
478    }
479
480    match prefix4 {
481        0b0111 => return Some((Opcode::ANDI, [OperandSpec::DestRegister16_31, OperandSpec::Imm8])),
482        0b0011 => return Some((Opcode::CPI, [OperandSpec::DestRegister16_31, OperandSpec::Imm8])),
483        0b1110 => return Some((Opcode::LDI, [OperandSpec::DestRegister16_31, OperandSpec::Imm8])),
484        0b0110 => return Some((Opcode::ORI, [OperandSpec::DestRegister16_31, OperandSpec::Imm8])),
485        0b1101 => return Some((Opcode::RCALL, [OperandSpec::RCALLJMPDisp12, OperandSpec::Nothing])),
486        0b1100 => return Some((Opcode::RJMP, [OperandSpec::RCALLJMPDisp12, OperandSpec::Nothing])),
487        0b0100 => return Some((Opcode::SBCI, [OperandSpec::DestRegister16_31, OperandSpec::Imm8])),
488        0b0101 => return Some((Opcode::SUBI, [OperandSpec::DestRegister16_31, OperandSpec::Imm8])),
489        _ => {},
490    }
491
492    match prefix5 {
493        0b1011_0 => return Some((Opcode::IN, [OperandSpec::DestRegister, OperandSpec::Addr6])),
494        0b1011_1 => return Some((Opcode::OUT, [OperandSpec::Addr6, OperandSpec::DestRegister])),
495        _ => {},
496    }
497
498    match prefix6 {
499        0b0001_11 => return Some((Opcode::ADC, [OperandSpec::DestRegister, OperandSpec::SrcRegister])),
500        0b0000_11 => return Some((Opcode::ADD, [OperandSpec::DestRegister, OperandSpec::SrcRegister])),
501        0b0010_00 => return Some((Opcode::AND, [OperandSpec::DestRegister, OperandSpec::SrcRegister])),
502        0b1111_01 | 0b1111_00 => {
503            // This is basically an Imm3, but we've got to decode it now
504            // to stuff it into the opcode itself, rather rather than as
505            // an operand.
506            let bit = SREGBit::from_bit_index((fullword & 0b111) as u8);
507            return Some((
508                if prefix6 & 1 != 0 { Opcode::BRBC(bit) } else { Opcode::BRBS(bit) },
509                [OperandSpec::BranchDisp7, OperandSpec::Nothing],
510            ))
511        },
512        0b0001_01 => return Some((Opcode::CP, [OperandSpec::DestRegister, OperandSpec::SrcRegister])),
513        0b0000_01 => return Some((Opcode::CPC, [OperandSpec::DestRegister, OperandSpec::SrcRegister])),
514        0b0001_00 => return Some((Opcode::CPSE, [OperandSpec::DestRegister, OperandSpec::SrcRegister])),
515        0b0010_01 => return Some((Opcode::EOR, [OperandSpec::DestRegister, OperandSpec::SrcRegister])),
516        0b0010_11 => return Some((Opcode::MOV, [OperandSpec::DestRegister, OperandSpec::SrcRegister])),
517        0b1001_11 => return Some((Opcode::MUL, [OperandSpec::DestRegister, OperandSpec::SrcRegister])),
518        0b0010_10 => return Some((Opcode::OR, [OperandSpec::DestRegister, OperandSpec::SrcRegister])),
519        0b0000_10 => return Some((Opcode::SBC, [OperandSpec::DestRegister, OperandSpec::SrcRegister])),
520        0b0001_10 => return Some((Opcode::SUB, [OperandSpec::DestRegister, OperandSpec::SrcRegister])),
521        _ => {},
522    }
523
524    match (prefix7, suffix4_3, suffix4_1) {
525        (0b1001_010, 0b010, 0b1) => return Some((Opcode::ASR, [OperandSpec::DestRegister, OperandSpec::Nothing])),
526        (0b1111_100, _, _) => return Some((Opcode::BLD, [OperandSpec::DestRegister, OperandSpec::Imm3])),
527        (0b1111_101, _, _) => return Some((Opcode::BST, [OperandSpec::DestRegister, OperandSpec::Imm3])),
528        (0b1001_010, 0b111, _) => return Some((Opcode::CALL, [OperandSpec::Addr22, OperandSpec::Nothing])),
529        (0b1001_010, 0b000, 0b0) => return Some((Opcode::COM, [OperandSpec::DestRegister, OperandSpec::Nothing])),
530        (0b1001_010, 0b101, 0b0) => return Some((Opcode::DEC, [OperandSpec::DestRegister, OperandSpec::Nothing])),
531        (0b1001_000, 0b011, 0b0) => return Some((Opcode::ELPM, [OperandSpec::DestRegister, OperandSpec::ImpliedRegister(Register::IndexRegister(IndexRegister::Z, IndexRegisterModifier::Unchanged))])),
532        (0b1001_000, 0b011, 0b1) => return Some((Opcode::ELPM, [OperandSpec::DestRegister, OperandSpec::ImpliedRegister(Register::IndexRegister(IndexRegister::Z, IndexRegisterModifier::PostIncrement))])),
533        (0b1001_010, 0b001, 0b1) => return Some((Opcode::INC, [OperandSpec::DestRegister, OperandSpec::Nothing])),
534        (0b1001_010, 0b110, _) => return Some((Opcode::JMP, [OperandSpec::Addr22, OperandSpec::Nothing])),
535        (0b1001_001, 0b011, 0b0) => return Some((Opcode::LAC, [OperandSpec::ImpliedRegister(Register::IndexRegister(IndexRegister::Z, IndexRegisterModifier::Unchanged)), OperandSpec::DestRegister])),
536        (0b1001_001, 0b010, 0b1) => return Some((Opcode::LAS, [OperandSpec::ImpliedRegister(Register::IndexRegister(IndexRegister::Z, IndexRegisterModifier::Unchanged)), OperandSpec::DestRegister])),
537        (0b1001_001, 0b011, 0b1) => return Some((Opcode::LAT, [OperandSpec::ImpliedRegister(Register::IndexRegister(IndexRegister::Z, IndexRegisterModifier::Unchanged)), OperandSpec::DestRegister])),
538        (0b1001_000, 0b110, 0b0) => return Some((Opcode::LD, [OperandSpec::DestRegister, OperandSpec::ImpliedRegister(Register::IndexRegister(IndexRegister::X, IndexRegisterModifier::Unchanged))])),
539        (0b1001_000, 0b110, 0b1) => return Some((Opcode::LD, [OperandSpec::DestRegister, OperandSpec::ImpliedRegister(Register::IndexRegister(IndexRegister::X, IndexRegisterModifier::PostIncrement))])),
540        (0b1001_000, 0b111, 0b0) => return Some((Opcode::LD, [OperandSpec::DestRegister, OperandSpec::ImpliedRegister(Register::IndexRegister(IndexRegister::X, IndexRegisterModifier::PreDecrement))])),
541        (0b1000_000, 0b100, 0b0) => return Some((Opcode::LD, [OperandSpec::DestRegister, OperandSpec::ImpliedRegister(Register::IndexRegister(IndexRegister::Y, IndexRegisterModifier::Unchanged))])),
542        (0b1001_000, 0b100, 0b1) => return Some((Opcode::LD, [OperandSpec::DestRegister, OperandSpec::ImpliedRegister(Register::IndexRegister(IndexRegister::Y, IndexRegisterModifier::PostIncrement))])),
543        (0b1001_000, 0b101, 0b0) => return Some((Opcode::LD, [OperandSpec::DestRegister, OperandSpec::ImpliedRegister(Register::IndexRegister(IndexRegister::Y, IndexRegisterModifier::PreDecrement))])),
544        (0b1000_000, 0b000, 0b0) => return Some((Opcode::LD, [OperandSpec::DestRegister, OperandSpec::ImpliedRegister(Register::IndexRegister(IndexRegister::Z, IndexRegisterModifier::Unchanged))])),
545        (0b1001_000, 0b000, 0b1) => return Some((Opcode::LD, [OperandSpec::DestRegister, OperandSpec::ImpliedRegister(Register::IndexRegister(IndexRegister::Z, IndexRegisterModifier::PostIncrement))])),
546        (0b1001_000, 0b001, 0b0) => return Some((Opcode::LD, [OperandSpec::DestRegister, OperandSpec::ImpliedRegister(Register::IndexRegister(IndexRegister::Z, IndexRegisterModifier::PreDecrement))])),
547        (0b1001_000, 0b010, 0b0) => return Some((Opcode::LPM, [OperandSpec::DestRegister, OperandSpec::ImpliedRegister(Register::IndexRegister(IndexRegister::Z, IndexRegisterModifier::Unchanged))])),
548        (0b1001_000, 0b010, 0b1) => return Some((Opcode::LPM, [OperandSpec::DestRegister, OperandSpec::ImpliedRegister(Register::IndexRegister(IndexRegister::Z, IndexRegisterModifier::PostIncrement))])),
549        // This is the only instruction in this form, so match the first half
550        // then deal with the second half inside the block. This is fine, since
551        // the prefix 0b1111_11x is only used by these two instructions anyway.
552        (0b1111_110, r, _) => {
553            if (r & 0b100) == 0b000 {
554                return Some((Opcode::SBRC, [OperandSpec::DestRegister, OperandSpec::Imm3]));
555            }
556        },
557        (0b1111_111, r, _) => {
558            if (r & 0b100) == 0b000 {
559                return Some((Opcode::SBRS, [OperandSpec::DestRegister, OperandSpec::Imm3]));
560            }
561        },
562        (0b1001_001, 0b110, 0b0) => return Some((Opcode::ST, [OperandSpec::ImpliedRegister(Register::IndexRegister(IndexRegister::X, IndexRegisterModifier::Unchanged)), OperandSpec::DestRegister])),
563        (0b1001_001, 0b110, 0b1) => return Some((Opcode::ST, [OperandSpec::ImpliedRegister(Register::IndexRegister(IndexRegister::X, IndexRegisterModifier::PostIncrement)), OperandSpec::DestRegister])),
564        (0b1001_001, 0b111, 0b0) => return Some((Opcode::ST, [OperandSpec::ImpliedRegister(Register::IndexRegister(IndexRegister::X, IndexRegisterModifier::PreDecrement)), OperandSpec::DestRegister])),
565        (0b1000_001, 0b100, 0b0) => return Some((Opcode::ST, [OperandSpec::ImpliedRegister(Register::IndexRegister(IndexRegister::Y, IndexRegisterModifier::Unchanged)), OperandSpec::DestRegister])),
566        (0b1001_001, 0b100, 0b1) => return Some((Opcode::ST, [OperandSpec::ImpliedRegister(Register::IndexRegister(IndexRegister::Y, IndexRegisterModifier::PostIncrement)), OperandSpec::DestRegister])),
567        (0b1001_001, 0b101, 0b0) => return Some((Opcode::ST, [OperandSpec::ImpliedRegister(Register::IndexRegister(IndexRegister::Y, IndexRegisterModifier::PreDecrement)), OperandSpec::DestRegister])),
568        (0b1000_001, 0b000, 0b0) => return Some((Opcode::ST, [OperandSpec::ImpliedRegister(Register::IndexRegister(IndexRegister::Z, IndexRegisterModifier::Unchanged)), OperandSpec::DestRegister])),
569        (0b1001_001, 0b000, 0b1) => return Some((Opcode::ST, [OperandSpec::ImpliedRegister(Register::IndexRegister(IndexRegister::Z, IndexRegisterModifier::PostIncrement)), OperandSpec::DestRegister])),
570        (0b1001_001, 0b001, 0b0) => return Some((Opcode::ST, [OperandSpec::ImpliedRegister(Register::IndexRegister(IndexRegister::Z, IndexRegisterModifier::PreDecrement)), OperandSpec::DestRegister])),
571        (0b1001_000, 0b000, 0b0) => return Some((Opcode::LDS, [OperandSpec::DestRegister, OperandSpec::Addr16])),
572        (0b1001_010, 0b011, 0b0) => return Some((Opcode::LSR, [OperandSpec::DestRegister, OperandSpec::Nothing])),
573        (0b1001_010, 0b000, 0b1) => return Some((Opcode::NEG, [OperandSpec::DestRegister, OperandSpec::Nothing])),
574        (0b1001_000, 0b111, 0b1) => return Some((Opcode::POP, [OperandSpec::DestRegister, OperandSpec::Nothing])),
575        (0b1001_001, 0b111, 0b1) => return Some((Opcode::PUSH, [OperandSpec::DestRegister, OperandSpec::Nothing])),
576        (0b1001_010, 0b011, 0b1) => return Some((Opcode::ROR, [OperandSpec::DestRegister, OperandSpec::Nothing])),
577        (0b1001_001, 0b000, 0b0) => return Some((Opcode::STS, [OperandSpec::Addr16, OperandSpec::DestRegister])),
578        (0b1001_010, 0b001, 0b0) => return Some((Opcode::SWAP, [OperandSpec::DestRegister, OperandSpec::Nothing])),
579        (0b1001_001, 0b010, 0b0) => return Some((Opcode::XCH, [OperandSpec::ImpliedRegister(Register::IndexRegister(IndexRegister::Z, IndexRegisterModifier::Unchanged)), OperandSpec::DestRegister])),
580        _ => {},
581    };
582
583    match (prefix8, suffix4) {
584        (0b1001_0110, _) => return Some((Opcode::ADIW, [OperandSpec::RegisterPair24_26_28_30, OperandSpec::Imm6])),
585        (0b1001_1000, _) => return Some((Opcode::CBI, [OperandSpec::Addr5, OperandSpec::Imm3])),
586        (0b1001_0100, 0b1011) => return Some((Opcode::DES, [OperandSpec::Imm4, OperandSpec::Nothing])),
587        (0b0000_0001, _) => return Some((Opcode::MOVW, [OperandSpec::DestRegisterPair, OperandSpec::SrcRegisterPair])),
588        (0b0000_0010, _) => return Some((Opcode::MULS, [OperandSpec::DestRegister16_31, OperandSpec::SrcRegister16_31])),
589        (0b1001_1010, _) => return Some((Opcode::SBI, [OperandSpec::Addr5, OperandSpec::Imm3])),
590        (0b1001_1001, _) => return Some((Opcode::SBIC, [OperandSpec::Addr5, OperandSpec::Imm3])),
591        (0b1001_1011, _) => return Some((Opcode::SBIS, [OperandSpec::Addr5, OperandSpec::Imm3])),
592        (0b1001_0111, _) => return Some((Opcode::SBIW, [OperandSpec::RegisterPair24_26_28_30, OperandSpec::Imm6])),
593        _ => {},
594    }
595
596    match (prefix9, suffix4) {
597        (0b1001_0100_1, 0b1000) | (0b1001_0100_0, 0b1000) => return Some((
598            {
599                let bit = (fullword >> 4) & 0b111;
600                let bit = SREGBit::from_bit_index(bit as u8);
601
602                match prefix9 & 1 {
603                    0 => Opcode::BSET(bit),
604                    1 => Opcode::BCLR(bit),
605                    _ => unreachable!(),
606                }
607            },
608            [OperandSpec::Nothing, OperandSpec::Nothing]
609        )),
610        (0b0000_0011_0, _) | (0b0000_0011_1, _) => return Some((
611            match (prefix9 & 1, suffix4 >> 3) {
612                (0, 0) => Opcode::MULSU,
613                (0, 1) => Opcode::FMUL,
614                (1, 0) => Opcode::FMULS,
615                (1, 1) => Opcode::FMULSU,
616                _ => unreachable!(),
617            },
618            [OperandSpec::DestRegister16_23, OperandSpec::SrcRegister16_23]
619        )),
620        _ => {},
621    }
622
623    if target.has_16_bit_lds_sts {
624        match prefix5 {
625            0b1010_0 => return Some((Opcode::LDS, [OperandSpec::DestRegister16_31, OperandSpec::Addr7])),
626            0b1010_1 => return Some((Opcode::STS, [OperandSpec::Addr7, OperandSpec::DestRegister16_31])),
627            _ => {},
628        }
629    } else {
630        match fullword & 0b1101_0010_0000_1000 {
631            //1101 0010 0000 1000 - mask
632            0b1000_0000_0000_1000 => return Some((Opcode::LDD, [OperandSpec::DestRegister, OperandSpec::RegDisp6(IndexRegister::Y)])),
633            0b1000_0000_0000_0000 => return Some((Opcode::LDD, [OperandSpec::DestRegister, OperandSpec::RegDisp6(IndexRegister::Z)])),
634            0b1000_0010_0000_1000 => return Some((Opcode::STD, [OperandSpec::RegDisp6(IndexRegister::Y), OperandSpec::DestRegister])),
635            0b1000_0010_0000_0000 => return Some((Opcode::STD, [OperandSpec::RegDisp6(IndexRegister::Z), OperandSpec::DestRegister])),
636            _ => {},
637        }
638    }
639
640    None
641}
642
643#[derive(Debug)]
644pub struct InstDecoder {
645    target: Target,
646}
647
648impl InstDecoder {
649    pub fn new(target: Target) -> InstDecoder {
650        InstDecoder { target }
651    }
652}
653
654impl Default for InstDecoder {
655    fn default() -> Self {
656        InstDecoder {
657            // This is any core other than an AVRTiny, so it's basically 99% of
658            // all AVRs
659            target: Target { has_16_bit_lds_sts: false }
660        }
661    }
662}
663
664impl Decoder<AVR> for InstDecoder {
665    // Variable names in the interpretation match block try and copy the
666    // instruction set manual, which leads to variable names like 'K' and 'A'.
667    // We'll prefer matching the manual's conventions than pleasing rustc.
668    #[allow(non_snake_case)]
669    fn decode_into<T: Reader<<AVR as Arch>::Address, <AVR as Arch>::Word>>(
670        &self,
671        instr: &mut Instruction,
672        words: &mut T,
673    ) -> Result<(), <AVR as Arch>::DecodeError> {
674        words.mark();
675        let fullword = (words.next()? as u16) | ((words.next()? as u16) << 8);
676
677        let (opcode, interpretation) = decode_opcode(fullword, &self.target)
678            .ok_or(StandardDecodeError::InvalidOpcode)?;
679        instr.opcode = opcode;
680
681        for (interp, operand) in interpretation.iter().zip(instr.operands.iter_mut()) {
682            *operand = match interp {
683                OperandSpec::Nothing => { return Ok(()) },
684                OperandSpec::ImpliedRegister(r) => Operand::Register(*r),
685                OperandSpec::DestRegister => {
686                    let d = (fullword >> 4) & 0b1_1111;
687                    Operand::Register(Register::Register(d as u8))
688                },
689                OperandSpec::SrcRegister => {
690                    let r = ((fullword >> 5) & 0b1_0000) | (fullword & 0b1111);
691                    Operand::Register(Register::Register(r as u8))
692                },
693                OperandSpec::DestRegister16_31 => {
694                    let d = (fullword >> 4) & 0b1111;
695                    Operand::Register(Register::Register((d + 16) as u8))
696                },
697                OperandSpec::SrcRegister16_31 => {
698                    let r = fullword & 0b1111;
699                    Operand::Register(Register::Register((r + 16) as u8))
700                },
701                OperandSpec::RegisterPair24_26_28_30 => {
702                    let d = (fullword >> 4) & 0b11;
703
704                    // We're storing the base register's index shifted right
705                    // one, so instead of [24, 26, 28, 30] as provided in the
706                    // manual (for an example see "7. ADIW", pg. 33) we're using
707                    // the values divided by 2.
708                    Operand::Register(Register::RegisterPair { low: [12, 13, 14, 15][d as usize] })
709                },
710                OperandSpec::DestRegister16_23 => {
711                    let d = (fullword >> 4) & 0b111;
712                    Operand::Register(Register::Register((d + 16) as u8))
713                },
714                OperandSpec::SrcRegister16_23 => {
715                    let r = fullword & 0b111;
716                    Operand::Register(Register::Register((r + 16) as u8))
717                },
718                OperandSpec::DestRegisterPair => {
719                    let d = (fullword >> 4) & 0b1111;
720                    Operand::Register(Register::RegisterPair { low: d as u8 })
721                },
722                OperandSpec::SrcRegisterPair => {
723                    let r = fullword & 0b1111;
724                    Operand::Register(Register::RegisterPair { low: r as u8 })
725                },
726                OperandSpec::Imm3 => {
727                    let K = fullword & 0b111;
728                    Operand::BitIndex(K as u8)
729                },
730                OperandSpec::Imm4 => {
731                    let K = (fullword >> 4) & 0b1111;
732                    Operand::ImmediateU8(K as u8)
733                },
734                OperandSpec::Imm6 => {
735                    let K = ((fullword >> 2) & 0b11_0000) | (fullword & 0b1111);
736                    Operand::ImmediateU8(K as u8)
737                },
738                OperandSpec::Imm8 => {
739                    let K = ((fullword >> 4) & 0b1111_0000) | (fullword & 0b1111);
740                    Operand::ImmediateU8(K as u8)
741                },
742                OperandSpec::RegDisp6(r) => {
743                    let q = ((fullword >> 8) & 0b10_0000) | ((fullword >> 7) & 0b1_1000) | (fullword & 0b111);
744                    Operand::Register(Register::IndexRegister(*r, IndexRegisterModifier::Displacement(q as u8)))
745                },
746                OperandSpec::BranchDisp7 => {
747                    // Operand is a signed 7-bit value, -64 <= k <= +63
748                    // Need to sign extend - 1 more sign bit for an i8, which we
749                    // can then "freely" (i.e. make Rust do it for us) sign
750                    // extend to an i16
751                    let k = (fullword >> 3) & 0b111_1111;
752                    // Perform sign extension, and add once since final
753                    // displacement range is (pc - 63) <= dest <= (pc + 64)
754                    let k = ((k | ((k & 0b100_0000) << 1)) as i8) as i16 + 1;
755
756                    Operand::AddrPCRelative(k as i16)
757                },
758                OperandSpec::RCALLJMPDisp12 => {
759                    let k = fullword & 0b1111_1111_1111;
760                    // Operand is a signed 12-bit value, -2048 <= k <= 2047
761                    // Need to sign extend - 4 more sign bits for an i16
762                    let signbit = fullword & 0b1000_0000_0000;
763                    let signext = (signbit << 4) | (signbit << 3) | (signbit << 2) | (signbit << 1);
764                    // Perform sign extension, and add one since final
765                    // displacement range is (pc - 2047) <= dest <= (pc + 2048)
766                    let k = (signext | k) as i16 + 1;
767
768                    Operand::AddrPCRelative(k)
769                },
770                OperandSpec::Addr5 => {
771                    let A = (fullword >> 3) & 0b1_1111;
772
773                    Operand::AddrAbsolute(A as u32)
774                },
775                OperandSpec::Addr6 => {
776                    let A = ((fullword >> 5) & 0b11_0000) | (fullword & 0b1111);
777
778                    Operand::AddrAbsolute(A as u32)
779                },
780                OperandSpec::Addr7 => {
781                    // This transformation is described in the instruction set
782                    // manual ("75. LDS (16-bit)", pg. 117) as
783                    // addr[7:0] = {
784                    //     ~inst[8], inst[8], inst[10], inst[9],
785                    //     inst[3], inst[2], inst[1], inst[0]
786                    // }
787                    let inst8 = (fullword >> 8) & 0b1;
788                    let ninst8 = inst8 ^ 1;
789                    let k = (ninst8 << 7) | (inst8 << 6) | ((fullword >> 5) & 0b11_0000) | (fullword & 0b1111);
790
791                    Operand::AddrAbsolute(k as u32)
792                },
793                OperandSpec::Addr16 => {
794                    let k = (words.next()? as u16) | ((words.next()? as u16) << 8);
795
796                    Operand::AddrAbsolute(k as u32)
797                },
798                OperandSpec::Addr22 => {
799                    let A_high = ((fullword >> 3) & 0b11_1110) | (fullword & 0b1);
800                    let A_low = (words.next()? as u16) | ((words.next()? as u16) << 8);
801
802                    let A = ((A_high as u32) << 16) | (A_low as u32);
803                    // Word address (into program memory), convert to bytes
804                    let A = A * 2;
805
806                    Operand::AddrAbsolute(A)
807                }
808            }
809        }
810
811        instr.length = words.offset() as u8;
812        Ok(())
813    }
814}
815
816#[derive(Debug)]
817pub struct AVR;
818
819impl Arch for AVR {
820    // TODO: Possibly distinguish between program memory and data memory
821    // addresses
822    type Address = u32;
823    type Word = u8;
824    type Instruction = Instruction;
825    type DecodeError = StandardDecodeError;
826    type Decoder = InstDecoder;
827    type Operand = Operand;
828}