avra_lib/
device.rs

1//! Contains device specific options of AVRA-rs
2
3use maplit::{btreeset, hashmap};
4use std::{
5    collections::{BTreeSet, HashMap},
6    sync::LazyLock,
7};
8
9#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
10pub enum DisabledOptions {
11    NoMul,
12    /// No JMP, CALL
13    NoJmp,
14    /// No X register
15    NoXreg,
16    /// No Y register
17    NoYreg,
18    /// AT90S1200, ATtiny10-12, no ADIW, SBIW, IJMP, ICALL, LDD, STD, LDS, STS, PUSH, POP
19    Tiny1x,
20    /// No LPM instruction
21    NoLpm,
22    /// No LPM Rd, Z or LPM Rd, Z+ instruction
23    NoLpmX,
24    /// No ELPM instruction
25    NoElpm,
26    /// No ELPM Rd, Z or ELPM Rd, Z+ instruction
27    NoElpmX,
28    /// No SPM instruction
29    NoSpm,
30    /// No ESPM instruction
31    NoEspm,
32    /// No MOVW instruction
33    NoMovw,
34    /// No BREAK instruction
35    NoBreak,
36    /// No EICALL instruction
37    NoEicall,
38    /// No EIJMP instruction
39    NoEijmp,
40    /// ATtiny10, 20, 40 no ADIW, SBIW, one word LDS/STS
41    Avr8l,
42}
43
44#[derive(Clone, PartialEq, Eq, Debug)]
45pub struct Device {
46    /// Flash size in words
47    pub flash_size: u32,
48    pub ram_start: u32,
49    pub ram_size: u32,
50    pub eeprom_size: u32,
51    pub disable_opts: BTreeSet<DisabledOptions>,
52}
53
54use DisabledOptions::*;
55
56use crate::instruction::operation::Operation;
57
58impl Device {
59    pub fn new(flash_size: u32) -> Self {
60        let flash_size = if flash_size == 0 { 4194304 } else { flash_size };
61        Self {
62            flash_size,
63            ram_start: 0x60,
64            ram_size: 8388608,
65            eeprom_size: 65536,
66            disable_opts: btreeset! {},
67        }
68    }
69
70    pub fn check_operation(&self, op: &Operation) -> bool {
71        match op {
72            Operation::Mul => self.allow(NoMul),
73            Operation::Jmp => self.allow(NoJmp),
74            Operation::Lpm => self.allow(NoLpm),
75            Operation::Elpm => self.allow(NoElpm),
76            Operation::Spm => self.allow(NoSpm),
77            Operation::Eicall => self.allow(NoEicall),
78            Operation::Eijmp => self.allow(NoEijmp),
79            Operation::Break => self.allow(NoBreak),
80            Operation::Movw => self.allow(NoMovw),
81            // AT90S1200, ATtiny10-12, no ADIW, SBIW, IJMP, ICALL, LDD, STD, LDS, STS, PUSH, POP
82            Operation::Adiw
83            | Operation::Sbiw
84            | Operation::Ijmp
85            | Operation::Icall
86            | Operation::Ldd
87            | Operation::Std
88            | Operation::Lds
89            | Operation::Sts
90            | Operation::Push
91            | Operation::Pop => {
92                if self.allow(Tiny1x) {
93                    // ATtiny10, 20, 40 no ADIW, SBIW, one word LDS/STS
94                    match op {
95                        Operation::Adiw | Operation::Sbiw => self.allow(Avr8l),
96                        _ => true,
97                    }
98                } else {
99                    false
100                }
101            }
102            _ => true,
103        }
104    }
105
106    pub fn is_avr8l(&self) -> bool {
107        self.disable_opts.contains(&Avr8l)
108    }
109
110    pub fn allow(&self, o: DisabledOptions) -> bool {
111        !self.disable_opts.contains(&o)
112    }
113}
114
115pub static DEVICES: LazyLock<HashMap<&'static str, Device>> = LazyLock::new(|| {
116    hashmap! {
117        /* Name => Flash(words), RAM start, RAM size, EEPROM, disable options */
118        /* ATtiny Series */
119        // ATtiny4
120        // ATtiny5
121        // ATtiny9
122        "ATtiny10" => Device {flash_size: 512, ram_start: 0x00, ram_size: 0, eeprom_size: 0, disable_opts: btreeset!{NoMul, NoJmp, Tiny1x, NoXreg, NoYreg, NoLpmX, NoElpm, NoSpm, NoEspm, NoMovw, NoBreak, NoEicall, NoEijmp} },
123        "ATtiny11" => Device {flash_size: 512, ram_start: 0x00, ram_size: 0, eeprom_size: 0, disable_opts: btreeset!{NoMul, NoJmp, Tiny1x, NoXreg, NoYreg, NoLpmX, NoElpm, NoSpm, NoEspm, NoMovw, NoBreak, NoEicall, NoEijmp} },
124        "ATtiny12" => Device {flash_size: 512, ram_start: 0x00, ram_size: 0, eeprom_size: 64, disable_opts: btreeset!{NoMul, NoJmp, Tiny1x, NoXreg, NoYreg, NoLpmX, NoElpm, NoSpm, NoEspm, NoMovw, NoBreak, NoEicall, NoEijmp} },
125        "ATtiny13" => Device {flash_size: 512, ram_start: 0x60, ram_size: 64, eeprom_size: 64, disable_opts: btreeset!{NoMul, NoJmp, NoElpm, NoEspm, NoEicall, NoEijmp} },
126        "ATtiny13A" => Device {flash_size: 512, ram_start: 0x60, ram_size: 64, eeprom_size: 64, disable_opts: btreeset!{NoMul, NoJmp, NoElpm, NoEspm, NoEicall, NoEijmp} },
127        "ATtiny15" => Device {flash_size: 512, ram_start: 0x00, ram_size: 0, eeprom_size: 64, disable_opts: btreeset!{NoMul, NoJmp, Tiny1x, NoXreg, NoYreg, NoLpmX, NoElpm, NoSpm, NoEspm, NoMovw, NoBreak, NoEicall, NoEijmp} },
128        "ATtiny20" => Device {flash_size: 2048, ram_start: 0x40, ram_size: 128, eeprom_size: 0, disable_opts: btreeset!{Avr8l, NoJmp, NoMul, NoEijmp, NoEicall, NoMovw, NoLpm, NoElpm, NoSpm, NoEspm, NoBreak} },
129        "ATtiny22" => Device {flash_size: 1024, ram_start: 0x60, ram_size: 128, eeprom_size: 128, disable_opts: btreeset!{NoMul, NoJmp, NoLpmX, NoElpm, NoSpm, NoEspm, NoMovw, NoBreak, NoEicall, NoEijmp} },
130        "ATtiny24" => Device {flash_size: 1024, ram_start: 0x60, ram_size: 128, eeprom_size: 128, disable_opts: btreeset!{NoMul, NoJmp, NoElpm, NoEspm, NoEicall, NoEijmp} },
131        "ATtiny24A" => Device {flash_size: 1024, ram_start: 0x60, ram_size: 128, eeprom_size: 128, disable_opts: btreeset!{NoMul, NoJmp, NoElpm, NoEspm, NoEicall, NoEijmp} },
132        "ATtiny25" => Device {flash_size: 1024, ram_start: 0x60, ram_size: 128, eeprom_size: 128, disable_opts: btreeset!{NoMul, NoJmp, NoElpm, NoEspm, NoEicall, NoEijmp} },
133        "ATtiny26" => Device {flash_size: 1024, ram_start: 0x60, ram_size: 128, eeprom_size: 128, disable_opts: btreeset!{NoMul, NoJmp, NoElpm, NoSpm, NoEspm, NoMovw, NoBreak, NoEicall, NoEijmp} },
134        "ATtiny28" => Device {flash_size: 1024, ram_start: 0x00, ram_size: 0, eeprom_size: 0, disable_opts: btreeset!{NoMul, NoJmp, Tiny1x, NoXreg, NoYreg, NoLpmX, NoElpm, NoSpm, NoEspm, NoMovw, NoBreak, NoEicall, NoEijmp} },
135        // ATtiny43U
136        "ATtiny44" => Device {flash_size: 2048, ram_start: 0x60, ram_size: 256, eeprom_size: 256, disable_opts: btreeset!{NoMul, NoJmp, NoElpm, NoEspm, NoEicall, NoEijmp} },
137        "ATtiny44A" => Device {flash_size: 2048, ram_start: 0x60, ram_size: 256, eeprom_size: 256, disable_opts: btreeset!{NoMul, NoJmp, NoElpm, NoEspm, NoEicall, NoEijmp} },
138        "ATtiny45" => Device {flash_size: 2048, ram_start: 0x60, ram_size: 256, eeprom_size: 256, disable_opts: btreeset!{NoMul, NoJmp, NoElpm, NoEspm, NoEicall, NoEijmp} },
139        "ATtiny48" => Device {flash_size: 2048, ram_start: 0x100, ram_size: 256, eeprom_size: 64, disable_opts: btreeset!{NoMul, NoJmp, NoElpm, NoEspm, NoEicall, NoEijmp} },
140        "ATtiny84" => Device {flash_size: 4096, ram_start: 0x60, ram_size: 512, eeprom_size: 512, disable_opts: btreeset!{NoMul, NoJmp, NoElpm, NoEspm, NoEicall, NoEijmp} },
141        "ATtiny85" => Device {flash_size: 4096, ram_start: 0x60, ram_size: 512, eeprom_size: 512, disable_opts: btreeset!{NoMul, NoJmp, NoElpm, NoEspm, NoEicall, NoEijmp} },
142        "ATtiny88" => Device {flash_size: 4096, ram_start: 0x100, ram_size: 512, eeprom_size: 64, disable_opts: btreeset!{NoMul, NoJmp, NoElpm, NoEspm, NoEicall, NoEijmp} },
143        // ATtiny87
144        // ATtiny167
145        // ATtiny261A
146        // ATtiny461A
147        // ATtiny861A
148        "ATtiny2313" => Device {flash_size: 1024, ram_start: 0x60, ram_size: 128, eeprom_size: 128, disable_opts: btreeset!{NoMul, NoJmp, NoElpm, NoEspm, NoEicall, NoEijmp} },
149        "ATtiny2313A" => Device {flash_size: 1024, ram_start: 0x60, ram_size: 128, eeprom_size: 128, disable_opts: btreeset!{NoMul, NoJmp, NoElpm, NoEspm, NoEicall, NoEijmp} },
150        "ATtiny4313" => Device {flash_size: 2048, ram_start: 0x60, ram_size: 256, eeprom_size: 256, disable_opts: btreeset!{NoMul, NoJmp, NoElpm, NoEspm, NoEicall, NoEijmp} },
151        /* AT90 series */
152        "AT90S1200" => Device {flash_size: 512, ram_start: 0x00, ram_size: 0, eeprom_size: 64, disable_opts: btreeset!{NoMul, NoJmp, Tiny1x, NoXreg, NoYreg, NoLpm, NoElpm, NoSpm, NoEspm, NoMovw, NoBreak, NoEicall, NoEijmp} }, // 137 - MUL(6) - JMP(2) - TINY(10)
153        "AT90S2313" => Device {flash_size: 1024, ram_start: 0x60, ram_size: 128, eeprom_size: 128, disable_opts: btreeset!{NoMul, NoJmp, NoLpmX, NoElpm, NoSpm, NoEspm, NoMovw, NoBreak, NoEicall, NoEijmp} },
154        "AT90S2323" => Device {flash_size: 1024, ram_start: 0x60, ram_size: 128, eeprom_size: 128, disable_opts: btreeset!{NoMul, NoJmp, NoLpmX, NoElpm, NoSpm, NoEspm, NoMovw, NoBreak, NoEicall, NoEijmp} },
155        "AT90S2333" => Device {flash_size: 1024, ram_start: 0x60, ram_size: 128, eeprom_size: 128, disable_opts: btreeset!{NoMul, NoJmp, NoLpmX, NoElpm, NoSpm, NoEspm, NoMovw, NoBreak, NoEicall, NoEijmp} },
156        "AT90S2343" => Device {flash_size: 1024, ram_start: 0x60, ram_size: 128, eeprom_size: 128, disable_opts: btreeset!{NoMul, NoJmp, NoLpmX, NoElpm, NoSpm, NoEspm, NoMovw, NoBreak, NoEicall, NoEijmp} },
157        "AT90S4414" => Device {flash_size: 2048, ram_start: 0x60, ram_size: 256, eeprom_size: 256, disable_opts: btreeset!{NoMul, NoJmp, NoLpmX, NoElpm, NoSpm, NoEspm, NoMovw, NoBreak, NoEicall, NoEijmp} },
158        "AT90S4433" => Device {flash_size: 2048, ram_start: 0x60, ram_size: 128, eeprom_size: 256, disable_opts: btreeset!{NoMul, NoJmp, NoLpmX, NoElpm, NoSpm, NoEspm, NoMovw, NoBreak, NoEicall, NoEijmp} },
159        "AT90S4434" => Device {flash_size: 2048, ram_start: 0x60, ram_size: 256, eeprom_size: 256, disable_opts: btreeset!{NoMul, NoJmp, NoLpmX, NoElpm, NoSpm, NoEspm, NoMovw, NoBreak, NoEicall, NoEijmp} },
160        "AT90S8515" => Device {flash_size: 4096, ram_start: 0x60, ram_size: 512, eeprom_size: 512, disable_opts: btreeset!{NoMul, NoJmp, NoLpmX, NoElpm, NoSpm, NoEspm, NoMovw, NoBreak, NoEicall, NoEijmp} }, // 137 - MUL(6) - JMP(2) - LPM_X(2) - ELPM(3) - SPM - ESPM - MOVW - BREAK - EICALL - EIJMP = 118
161        "AT90C8534" => Device {flash_size: 4096, ram_start: 0x60, ram_size: 256, eeprom_size: 512, disable_opts: btreeset!{NoMul, NoJmp, NoLpmX, NoElpm, NoSpm, NoEspm, NoMovw, NoBreak, NoEicall, NoEijmp} },
162        "AT90S8535" => Device {flash_size: 4096, ram_start: 0x60, ram_size: 512, eeprom_size: 512, disable_opts: btreeset!{NoMul, NoJmp, NoLpmX, NoElpm, NoSpm, NoEspm, NoMovw, NoBreak, NoEicall, NoEijmp} },
163        /* AT90USB series*/
164        // AT90USB168
165        // AT90USB1287
166        /* ATmega series */
167        "ATmega8" => Device {flash_size: 4096, ram_start: 0x60, ram_size: 1024, eeprom_size: 512, disable_opts: btreeset!{NoJmp, NoEicall, NoEijmp, NoElpm, NoEspm} },
168        "ATmega161" => Device {flash_size: 8192, ram_start: 0x60, ram_size: 1024, eeprom_size: 512, disable_opts: btreeset!{NoEicall, NoEijmp, NoElpm, NoEspm} },
169        "ATmega162" => Device {flash_size: 8192, ram_start: 0x100, ram_size: 1024, eeprom_size: 512, disable_opts: btreeset!{NoEicall, NoEijmp, NoElpm, NoEspm} },
170        "ATmega163" => Device {flash_size: 8192, ram_start: 0x60, ram_size: 1024, eeprom_size: 512, disable_opts: btreeset!{NoEicall, NoEijmp, NoElpm, NoEspm} },
171        "ATmega16" => Device {flash_size: 8192, ram_start: 0x60, ram_size: 1024, eeprom_size: 512, disable_opts: btreeset!{NoEicall, NoEijmp, NoElpm, NoEspm} },
172        "ATmega323" => Device {flash_size: 16384, ram_start: 0x60, ram_size: 2048, eeprom_size: 1024, disable_opts: btreeset!{NoEicall, NoEijmp, NoElpm, NoEspm} }, // 137 - EICALL - EIJMP - ELPM(3) - ESPM = 131 (Data sheet says 130 but it's wrong)
173        "ATmega328P" => Device {flash_size: 16384, ram_start: 0x100, ram_size: 2048, eeprom_size: 1024, disable_opts: btreeset!{NoEicall, NoEijmp, NoElpm, NoEspm} },
174        "ATmega32" => Device {flash_size: 16384, ram_start: 0x60, ram_size: 2048, eeprom_size: 1024, disable_opts: btreeset!{NoEicall, NoEijmp, NoElpm, NoEspm} },
175        "ATmega603" => Device {flash_size: 32768, ram_start: 0x60, ram_size: 4096, eeprom_size: 2048, disable_opts: btreeset!{NoEicall, NoEijmp, NoMul, NoMovw, NoLpmX, NoElpm, NoSpm, NoEspm, NoBreak} },
176        "ATmega103" => Device {flash_size: 65536, ram_start: 0x60, ram_size: 4096, eeprom_size: 4096, disable_opts: btreeset!{NoEicall, NoEijmp, NoMul, NoMovw, NoLpmX, NoElpmX, NoSpm, NoEspm, NoBreak} }, // 137 - EICALL - EIJMP - MUL(6) - MOVW - LPM_X(2) - ELPM_X(2) - SPM - ESPM - BREAK = 121
177        "ATmega104" => Device {flash_size: 65536, ram_start: 0x60, ram_size: 4096, eeprom_size: 4096, disable_opts: btreeset!{NoEicall, NoEijmp, NoEspm} }, // Old name for mega128
178        "ATmega128" => Device {flash_size: 65536, ram_start: 0x100, ram_size: 4096, eeprom_size: 4096, disable_opts: btreeset!{NoEicall, NoEijmp, NoEspm} }, // 137 - EICALL - EIJMP - ESPM = 134 (Data sheet says 133 but it's wrong)
179        "ATmega48" => Device {flash_size: 2048, ram_start: 0x100, ram_size: 512, eeprom_size: 256, disable_opts: btreeset!{NoEicall, NoEijmp, NoElpm, NoEspm} },
180        "ATmega88" => Device {flash_size: 4096, ram_start: 0x100, ram_size: 1024, eeprom_size: 512, disable_opts: btreeset!{NoEicall, NoEijmp, NoElpm, NoEspm} },
181        "ATmega168" => Device {flash_size: 8192, ram_start: 0x100, ram_size: 1024, eeprom_size: 512, disable_opts: btreeset!{NoEicall, NoEijmp, NoElpm, NoEspm} },
182        "ATmega644" => Device {flash_size: 65536, ram_start: 0x100, ram_size: 4096, eeprom_size: 2048, disable_opts: btreeset!{NoEicall, NoEijmp, NoElpm, NoEspm} },
183        "ATmega8515" => Device {flash_size: 8192, ram_start: 0x60, ram_size: 512, eeprom_size: 512, disable_opts: btreeset!{NoEicall, NoEijmp, NoElpm, NoEspm} },
184        "ATmega1280" => Device {flash_size: 65536, ram_start: 0x200, ram_size: 8192, eeprom_size: 4096, disable_opts: btreeset!{NoEicall, NoEijmp, NoEspm} },
185        "ATmega2560" => Device {flash_size: 262144, ram_start: 0x200, ram_size: 8192, eeprom_size: 4096, disable_opts: btreeset!{NoEspm} },
186        /* Other */
187        "AT94K" => Device {flash_size: 8192, ram_start: 0x60, ram_size: 16384, eeprom_size: 0, disable_opts: btreeset!{NoEicall, NoEijmp, NoElpm, NoSpm, NoEspm, NoBreak} }, // 137 - EICALL - EIJMP - ELPM(3) - SPM - ESPM - BREAK = 129
188    }
189});