machine_check_avr/
system.rs

1#[allow(non_snake_case)]
2#[allow(clippy::if_same_then_else)]
3#[machine_check::machine_description]
4pub mod machine_module {
5    use ::machine_check::{Bitvector, BitvectorArray, Ext, Signed, Unsigned};
6    use ::std::{
7        clone::Clone,
8        cmp::{Eq, PartialEq},
9        convert::Into,
10        fmt::Debug,
11        hash::Hash,
12        panic, unimplemented,
13    };
14
15    /// ATmega328P system input.
16    #[derive(Clone, PartialEq, Eq, Hash, Debug)]
17    pub struct Input {
18        // --- Uninitialized Registers and Memory ---
19        /// Uninitialized general-purpose working registers.
20        pub uninit_R: BitvectorArray<5, 8>,
21        /// Uninitialized SRAM.
22        pub uninit_SRAM: BitvectorArray<11, 8>,
23
24        // --- General Purpose I/O ---
25        /// I/O address 0x3: pin read.
26        pub PINB: Bitvector<8>,
27
28        /// I/O address 0x6: pin read.
29        ///
30        /// Only low 7 bits are read, the high bit is always zero.
31        pub PINC: Bitvector<7>,
32
33        /// I/O address 0x9: pin read.
34        pub PIND: Bitvector<8>,
35    }
36
37    impl ::machine_check::Input for Input {}
38
39    /// ATmega328P system state.
40    #[derive(Clone, PartialEq, Eq, Hash, Debug)]
41    pub struct State {
42        // --- Program Counter ---
43        /// Program counter.
44        pub PC: Bitvector<14>,
45
46        // --- Working Registers ---
47        // Data addresses 0x00..0x20
48        /// General-purpose working registers.
49        ///
50        /// 32 (2<sup>5</sup>) 8-bit registers.
51        pub R: BitvectorArray<5, 8>,
52
53        // --- I/O Registers ---
54        // 64 addresses, only some are true registers
55        // Data addresses 0x20..0x40
56
57        // Port B
58        // I/O address 0x3: reads pins, write XORs output/pullup register.
59        // ---
60        /// I/O address 0x4: data direction register.
61        pub DDRB: Bitvector<8>,
62        /// I/O address 0x5: output/pullup register.
63        pub PORTB: Bitvector<8>,
64
65        // Port C: lacks the highest bit
66        // I/O address 0x6: reads pins, write XORs output/pullup register.
67        // ---
68        /// I/O address 0x7: data direction register.
69        pub DDRC: Bitvector<7>,
70        /// I/O address 0x8: output/pullup register.
71        pub PORTC: Bitvector<7>,
72
73        // Port D
74        // I/O address 0x9: reads pins, write XORs output/pullup register.
75        // ---
76        /// I/O address 0xA: data direction register.
77        pub DDRD: Bitvector<8>,
78        /// I/O address 0xB: output/pullup register.
79        pub PORTD: Bitvector<8>,
80
81        // General Purpose I/O registers
82        /// I/O address 0x1E: General Purpose I/O register 0.
83        pub GPIOR0: Bitvector<8>,
84        /// I/O address 0x2A: General Purpose I/O register 1.
85        pub GPIOR1: Bitvector<8>,
86        /// I/O address 0x2B: General Purpose I/O register 2.
87        pub GPIOR2: Bitvector<8>,
88
89        /// I/O address 0x3D: Stack Pointer Low.
90        pub SPL: Bitvector<8>,
91
92        /// I/O address 0x3E: Stack Pointer High.
93        pub SPH: Bitvector<8>,
94
95        /// I/O address 0x3F: Status Register.
96        pub SREG: Bitvector<8>,
97
98        // TODO: other I/O registers
99
100        // --- Extended I/O Registers ---
101        // TODO: extended I/O registers
102
103        // --- SRAM ---
104        /// Static RAM.
105        ///
106        /// Contains 2K (2<sup>11</sup>) 8-bit cells.
107        pub SRAM: BitvectorArray<11, 8>,
108        // --- EEPROM ---
109        // unchangeable as SPM instruction is not supported
110    }
111
112    impl ::machine_check::State for State {}
113
114    /// ATmega328P system.
115    ///
116    /// Program memory is treated as unchanging as the SPM instruction is not implemented.
117    #[derive(Clone, PartialEq, Eq, Hash, Debug)]
118    pub struct ATmega328P {
119        /// Program memory.
120        ///
121        /// ATmega328P program memory is 32 KB, i.e. 16K (2<sup>14</sup>) 16-bit words.
122        pub PROGMEM: BitvectorArray<14, 16>,
123    }
124
125    impl ATmega328P {
126        fn instruction_skip(&self, pc: Bitvector<14>) -> Bitvector<14> {
127            // PC is already incremented to point to the next instruction
128            let mut result_pc = pc;
129            let instruction = self.PROGMEM[result_pc];
130            ::machine_check::bitmask_switch!(instruction {
131                // LDS or STS (two-word)
132                // STS (two-word)
133                "1001_00-d_dddd_0000" => {
134                    result_pc = result_pc + Bitvector::<14>::new(2);
135                }
136                // JMP
137                "1001_010k_kkkk_110k" => {
138                    result_pc = result_pc + Bitvector::<14>::new(2);
139                }
140                // CALL
141                "1001_010k_kkkk_111k" => {
142                    result_pc = result_pc + Bitvector::<14>::new(2);
143                }
144                // otherwise, we are skipping a one-word instruction
145                _ => {
146                    result_pc = result_pc + Bitvector::<14>::new(1);
147                }
148            });
149            result_pc
150        }
151
152        #[allow(unreachable_code)]
153        fn read_io_reg(state: &State, input: &Input, io_index: Bitvector<6>) -> Bitvector<8> {
154            let result;
155            if io_index == Bitvector::<6>::new(0x03) {
156                result = input.PINB;
157            } else if io_index == Bitvector::<6>::new(0x04) {
158                result = state.DDRB;
159            } else if io_index == Bitvector::<6>::new(0x05) {
160                result = state.PORTB;
161            } else if io_index == Bitvector::<6>::new(0x06) {
162                // port C has only 7 bits, zero-extend
163                result = Into::<Bitvector<8>>::into(Ext::<8>::ext(Into::<Unsigned<7>>::into(
164                    input.PINC,
165                )));
166            } else if io_index == Bitvector::<6>::new(0x07) {
167                // port C has only 7 bits, zero-extend
168                result = Into::<Bitvector<8>>::into(Ext::<8>::ext(Into::<Unsigned<7>>::into(
169                    state.DDRC,
170                )));
171            } else if io_index == Bitvector::<6>::new(0x08) {
172                // port C has only 7 bits, zero-extend
173                result = Into::<Bitvector<8>>::into(Ext::<8>::ext(Into::<Unsigned<7>>::into(
174                    state.PORTC,
175                )));
176            } else if io_index == Bitvector::<6>::new(0x09) {
177                result = input.PIND;
178            } else if io_index == Bitvector::<6>::new(0x0A) {
179                result = state.DDRD;
180            } else if io_index == Bitvector::<6>::new(0x0B) {
181                result = state.PORTD;
182            } else if io_index == Bitvector::<6>::new(0x1E) {
183                result = state.GPIOR0;
184            } else if io_index == Bitvector::<6>::new(0x2A) {
185                result = state.GPIOR1;
186            } else if io_index == Bitvector::<6>::new(0x2B) {
187                result = state.GPIOR2;
188            } else if io_index == Bitvector::<6>::new(0x3D) {
189                result = state.SPL;
190            } else if io_index == Bitvector::<6>::new(0x3E) {
191                result = state.SPH;
192            } else if io_index == Bitvector::<6>::new(0x3F) {
193                result = state.SREG;
194            } else {
195                panic!("Unimplemented or invalid read from I/O register");
196                // TODO: discover that panic diverges and no assignment is necessary
197                result = Bitvector::<8>::new(0);
198            }
199
200            result
201        }
202
203        fn write_io_reg(state: &State, io_index: Bitvector<6>, value: Bitvector<8>) -> State {
204            let PC = state.PC;
205            let R = Clone::clone(&state.R);
206            let mut DDRB = state.DDRB;
207            let mut PORTB = state.PORTB;
208            let mut DDRC = state.DDRC;
209            let mut PORTC = state.PORTC;
210            let mut DDRD = state.DDRD;
211            let mut PORTD = state.PORTD;
212            let mut GPIOR0 = state.GPIOR0;
213            let mut GPIOR1 = state.GPIOR1;
214            let mut GPIOR2 = state.GPIOR2;
215            let mut SPL = state.SPL;
216            let mut SPH = state.SPH;
217            let mut SREG = state.SREG;
218            let SRAM = Clone::clone(&state.SRAM);
219
220            if io_index == Bitvector::<6>::new(0x03) {
221                // instead of writing to PINB, exclusive-or PORTB
222                PORTB = PORTB ^ value;
223            } else if io_index == Bitvector::<6>::new(0x04) {
224                DDRB = value;
225            } else if io_index == Bitvector::<6>::new(0x05) {
226                PORTB = value;
227            } else if (io_index == Bitvector::<6>::new(0x06))
228                | (io_index == Bitvector::<6>::new(0x07))
229                | (io_index == Bitvector::<6>::new(0x08))
230            {
231                // port C has only 7 bits
232                // ensure written bit 8 is zero
233                let bit_8_mask = Bitvector::<8>::new(0b1000_0000);
234                let bit_8_masked = value & bit_8_mask;
235                if bit_8_masked != Bitvector::<8>::new(0) {
236                    panic!("Port C bit 8 should not have 1 written to it");
237                };
238                //  drop bit 8
239                let value_ext =
240                    Into::<Bitvector<7>>::into(Ext::<7>::ext(Into::<Unsigned<8>>::into(value)));
241                if io_index == Bitvector::<6>::new(0x06) {
242                    // instead of writing to PINC, exclusive-or PORTC
243                    PORTC = PORTC ^ value_ext;
244                } else if io_index == Bitvector::<6>::new(0x07) {
245                    DDRC = value_ext;
246                } else if io_index == Bitvector::<6>::new(0x08) {
247                    PORTC = value_ext;
248                };
249            } else if io_index == Bitvector::<6>::new(0x09) {
250                // instead of writing to PIND, exclusive-or PORTD
251                PORTD = PORTD ^ value;
252            } else if io_index == Bitvector::<6>::new(0x0A) {
253                DDRD = value;
254            } else if io_index == Bitvector::<6>::new(0x0B) {
255                PORTD = value;
256            } else if io_index == Bitvector::<6>::new(0x1E) {
257                GPIOR0 = value;
258            } else if io_index == Bitvector::<6>::new(0x2A) {
259                GPIOR1 = value;
260            } else if io_index == Bitvector::<6>::new(0x2B) {
261                GPIOR2 = value;
262            } else if io_index == Bitvector::<6>::new(0x3D) {
263                SPL = value;
264            } else if io_index == Bitvector::<6>::new(0x3E) {
265                SPH = value;
266            } else if io_index == Bitvector::<6>::new(0x3F) {
267                SREG = value;
268            } else {
269                panic!("Unimplemented or invalid write to I/O register");
270            }
271
272            State {
273                PC,
274                R,
275                DDRB,
276                PORTB,
277                DDRC,
278                PORTC,
279                DDRD,
280                PORTD,
281                GPIOR0,
282                GPIOR1,
283                GPIOR2,
284                SPL,
285                SPH,
286                SREG,
287                SRAM,
288            }
289        }
290
291        #[allow(unreachable_code)]
292        fn read_data_mem(state: &State, input: &Input, data_index: Bitvector<16>) -> Bitvector<8> {
293            let unsigned_data_index = Into::<Unsigned<16>>::into(data_index);
294            let result;
295            if unsigned_data_index < Unsigned::<16>::new(0x0020) {
296                // working registers
297                let reg_index = Into::<Bitvector<5>>::into(Ext::<5>::ext(unsigned_data_index));
298                result = state.R[reg_index];
299            } else if unsigned_data_index < Unsigned::<16>::new(0x0060) {
300                // I/O registers
301                let io_reg_index = Into::<Bitvector<6>>::into(Ext::<6>::ext(
302                    unsigned_data_index - Unsigned::<16>::new(0x0020),
303                ));
304                result = Self::read_io_reg(state, input, io_reg_index);
305            } else if unsigned_data_index < Unsigned::<16>::new(0x100) {
306                // extended I/O registers, none implemented yet
307                panic!("Unimplemented or invalid read from extended I/O register");
308                // TODO: discover that panic diverges and no assignment is necessary
309                result = Bitvector::<8>::new(0);
310            } else {
311                let sram_full_index = unsigned_data_index - Unsigned::<16>::new(0x0100);
312                let sram_index = Ext::<11>::ext(sram_full_index);
313                if sram_full_index == Ext::<16>::ext(sram_index) {
314                    // inside SRAM
315                    result = state.SRAM[Into::<Bitvector<11>>::into(sram_index)];
316                } else {
317                    // outside SRAM
318                    panic!("Illegal read after data memory end");
319                    // TODO: discover that panic diverges and no assignment is necessary
320                    result = Bitvector::<8>::new(0);
321                };
322            }
323            result
324        }
325
326        #[allow(unreachable_code)]
327        fn write_data_mem(state: &State, data_index: Bitvector<16>, value: Bitvector<8>) -> State {
328            let PC = state.PC;
329            let DDRB = state.DDRB;
330            let PORTB = state.PORTB;
331            let DDRC = state.DDRC;
332            let PORTC = state.PORTC;
333            let DDRD = state.DDRD;
334            let PORTD = state.PORTD;
335            let GPIOR0 = state.GPIOR0;
336            let GPIOR1 = state.GPIOR1;
337            let GPIOR2 = state.GPIOR2;
338            let SPL = state.SPL;
339            let SPH = state.SPH;
340            let SREG = state.SREG;
341
342            let result;
343            let unsigned_data_index = Into::<Unsigned<16>>::into(data_index);
344            if unsigned_data_index < Unsigned::<16>::new(0x0020) {
345                // working registers
346                let reg_index = Into::<Bitvector<5>>::into(Ext::<5>::ext(unsigned_data_index));
347
348                let mut R = Clone::clone(&state.R);
349                let SRAM = Clone::clone(&state.SRAM);
350                R[reg_index] = value;
351
352                result = State {
353                    PC,
354                    R,
355                    DDRB,
356                    PORTB,
357                    DDRC,
358                    PORTC,
359                    DDRD,
360                    PORTD,
361                    GPIOR0,
362                    GPIOR1,
363                    GPIOR2,
364                    SPL,
365                    SPH,
366                    SREG,
367                    SRAM,
368                };
369            } else if unsigned_data_index < Unsigned::<16>::new(0x0060) {
370                // I/O registers
371                let io_reg_index = Into::<Bitvector<6>>::into(Ext::<6>::ext(
372                    unsigned_data_index - Unsigned::<16>::new(0x0020),
373                ));
374                result = Self::write_io_reg(state, io_reg_index, value);
375            } else if unsigned_data_index < Unsigned::<16>::new(0x100) {
376                // extended I/O registers, none implemented yet
377                panic!("Unimplemented or invalid read from extended I/O register");
378                // TODO: discover that panic diverges and no assignment is necessary
379                result = Clone::clone(state);
380            } else {
381                let sram_full_index = unsigned_data_index - Unsigned::<16>::new(0x0100);
382                let sram_index = Ext::<11>::ext(sram_full_index);
383                if sram_full_index != Ext::<16>::ext(sram_index) {
384                    // outside SRAM
385                    panic!("Illegal write after data memory end");
386                }
387                // inside SRAM
388                let R = Clone::clone(&state.R);
389                let mut SRAM = Clone::clone(&state.SRAM);
390                SRAM[Into::<Bitvector<11>>::into(sram_index)] = value;
391
392                result = State {
393                    PC,
394                    R,
395                    DDRB,
396                    PORTB,
397                    DDRC,
398                    PORTC,
399                    DDRD,
400                    PORTD,
401                    GPIOR0,
402                    GPIOR1,
403                    GPIOR2,
404                    SPL,
405                    SPH,
406                    SREG,
407                    SRAM,
408                };
409            }
410            result
411        }
412
413        // for instructions AND, EOR, OR
414        // Ru: destination register after being set
415        fn compute_status_logical(sreg: Bitvector<8>, Ru: Bitvector<8>) -> Bitvector<8> {
416            let retained_flags = Unsigned::<8>::new(0b1110_0001);
417            let mut result = Into::<Unsigned<8>>::into(sreg) & retained_flags;
418
419            let Ru_unsigned = Into::<Unsigned<8>>::into(Ru);
420
421            let Ru7 = Ext::<1>::ext(Ru_unsigned >> Unsigned::<8>::new(7));
422
423            // Z - zero flag, bit 1
424            if Ru == Bitvector::<8>::new(0) {
425                result = result | Unsigned::<8>::new(0b0000_0010);
426            };
427
428            // N - negative flag, bit 2
429            // the sign is in bit 7 of scrutinee
430            // move into lowest bit first
431            let flag_N = Ru7;
432
433            result = result | (Ext::<8>::ext(flag_N) << Unsigned::<8>::new(2));
434
435            // V - two's complement overflow flag, bit 3
436            // just constant zero here, already taken care of by not retaining flag
437
438            // S - sign flag, bit 4
439            // equal to N ^ V, but V is constant zero, so just use N
440            result = result | (Ext::<8>::ext(flag_N) << Unsigned::<8>::new(4));
441
442            Into::<Bitvector<8>>::into(result)
443        }
444
445        // for instructions: ADD, ADC
446        // Rd: destination register before being set
447        // Rr: other register
448        // Ru: destination register after being set
449        fn compute_status_add(
450            sreg: Bitvector<8>,
451            Rd: Bitvector<8>,
452            Rr: Bitvector<8>,
453            Ru: Bitvector<8>,
454        ) -> Bitvector<8> {
455            let retained_flags = Unsigned::<8>::new(0b1100_0000);
456            let mut result = Into::<Unsigned<8>>::into(sreg) & retained_flags;
457
458            let Rd_unsigned = Into::<Unsigned<8>>::into(Rd);
459            let Rr_unsigned = Into::<Unsigned<8>>::into(Rr);
460            let Ru_unsigned = Into::<Unsigned<8>>::into(Ru);
461
462            let Rd7 = Ext::<1>::ext(Rd_unsigned >> Unsigned::<8>::new(7));
463            let Rr7 = Ext::<1>::ext(Rr_unsigned >> Unsigned::<8>::new(7));
464            let Ru7 = Ext::<1>::ext(Ru_unsigned >> Unsigned::<8>::new(7));
465
466            // C - carry flag, bit 0
467            let flag_C = (Rd7 & Rr7) | (Rr7 & !Ru7) | (!Ru7 & Rd7);
468            result = result | Ext::<8>::ext(flag_C);
469
470            // Z - zero flag, bit 1
471            if Ru == Bitvector::<8>::new(0) {
472                result = result | Unsigned::<8>::new(0b0000_0010);
473            };
474
475            // N - negative flag, bit 2
476            let flag_N = Ru7;
477            result = result | (Ext::<8>::ext(flag_N) << Unsigned::<8>::new(2));
478
479            // V - two's complement overflow flag, bit 3
480            let flag_V = (Rd7 & Rr7 & !Ru7) | (!Rd7 & !Rr7 & Ru7);
481            result = result | (Ext::<8>::ext(flag_V) << Unsigned::<8>::new(3));
482
483            // S - sign flag (N ^ V), bit 4
484            let flag_S = flag_N ^ flag_V;
485            result = result | (Ext::<8>::ext(flag_S) << Unsigned::<8>::new(4));
486
487            let Rd3 = Ext::<1>::ext(Rd_unsigned >> Unsigned::<8>::new(3));
488            let Rr3 = Ext::<1>::ext(Rr_unsigned >> Unsigned::<8>::new(3));
489            let Ru3 = Ext::<1>::ext(Ru_unsigned >> Unsigned::<8>::new(3));
490
491            // H - half carry flag, bit 5
492            let flag_H = (Rd3 & Rr3) | (Rr3 & !Ru3) | (!Ru3 & Rd3);
493            result = result | (Ext::<8>::ext(flag_H) << Unsigned::<8>::new(4));
494
495            Into::<Bitvector<8>>::into(result)
496        }
497
498        // for instructions ASR, LSR, ROR
499        // Rd: register before being shifted
500        // Ru: register after being shifted
501        // LSR has N flag always zero, but that
502        // will also happen due to zero Ru[[7]]
503        fn compute_status_right_shift(
504            sreg: Bitvector<8>,
505            Rd: Bitvector<8>,
506            Ru: Bitvector<8>,
507        ) -> Bitvector<8> {
508            // first, set like logical
509            let logical_status: Bitvector<8> = Self::compute_status_logical(sreg, Ru);
510            let mut result = Into::<Unsigned<8>>::into(logical_status);
511
512            let retained_flags = Unsigned::<8>::new(0b1111_0110);
513            result = result & retained_flags;
514
515            // C - carry flag, bit 0
516            // set to shifted-out bit
517            let shifted_out = Into::<Unsigned<8>>::into(Rd) & Unsigned::<8>::new(0b0000_0001);
518            let flag_C = Ext::<1>::ext(shifted_out);
519            result = result | shifted_out;
520
521            // V - two's complement overflow flag, bit 3
522            // set to N ^ C after shift
523            // N is in bit 2
524            let flag_N = Ext::<1>::ext(result >> Unsigned::<8>::new(2));
525            let flag_V = flag_N ^ flag_C;
526            result = result | (Ext::<8>::ext(flag_V) << Unsigned::<8>::new(3));
527
528            Into::<Bitvector<8>>::into(result)
529        }
530
531        // for instruction COM
532        // Ru: destination register after being set
533        fn compute_status_com(sreg: Bitvector<8>, Ru: Bitvector<8>) -> Bitvector<8> {
534            // C - carry flag, bit 0
535            // is set to one
536            let mut result = sreg | Bitvector::<8>::new(0b0000_0001);
537
538            // others are set like logical, which retains carry
539            result = Self::compute_status_logical(result, Ru);
540            result
541        }
542
543        // for instructions SUB, SUBI, CP, CPI
544        // Rd: destination register before being set
545        // Rr: other register
546        // Ru: destination register after being set
547        fn compute_status_sub(
548            sreg: Bitvector<8>,
549            Rd: Bitvector<8>,
550            Rr: Bitvector<8>,
551            Ru: Bitvector<8>,
552        ) -> Bitvector<8> {
553            // like compute_status_add, but with different negations in C, V, H flags
554
555            let retained_flags = Unsigned::<8>::new(0b1100_0000);
556            let mut result = Into::<Unsigned<8>>::into(sreg) & retained_flags;
557
558            let Rd_unsigned = Into::<Unsigned<8>>::into(Rd);
559            let Rr_unsigned = Into::<Unsigned<8>>::into(Rr);
560            let Ru_unsigned = Into::<Unsigned<8>>::into(Ru);
561
562            let Rd7 = Ext::<1>::ext(Rd_unsigned >> Unsigned::<8>::new(7));
563            let Rr7 = Ext::<1>::ext(Rr_unsigned >> Unsigned::<8>::new(7));
564            let Ru7 = Ext::<1>::ext(Ru_unsigned >> Unsigned::<8>::new(7));
565
566            // C - carry flag, bit 0
567            let flag_C = (!Rd7 & Rr7) | (Rr7 & Ru7) | (Ru7 & !Rd7);
568            result = result | Ext::<8>::ext(flag_C);
569
570            // Z - zero flag, bit 1
571            if Ru == Bitvector::<8>::new(0) {
572                result = result | Unsigned::<8>::new(0b0000_0010);
573            };
574
575            // N - negative flag, bit 2
576            let flag_N = Ru7;
577            result = result | (Ext::<8>::ext(flag_N) << Unsigned::<8>::new(2));
578
579            // V - two's complement overflow flag, bit 3
580            let flag_V = (Rd7 & !Rr7 & !Ru7) | (!Rd7 & Rr7 & Ru7);
581            result = result | (Ext::<8>::ext(flag_V) << Unsigned::<8>::new(3));
582
583            // S - sign flag (N ^ V), bit 4
584            let flag_S = flag_N ^ flag_V;
585            result = result | (Ext::<8>::ext(flag_S) << Unsigned::<8>::new(4));
586
587            let Rd3 = Ext::<1>::ext(Rd_unsigned >> Unsigned::<8>::new(3));
588            let Rr3 = Ext::<1>::ext(Rr_unsigned >> Unsigned::<8>::new(3));
589            let Ru3 = Ext::<1>::ext(Ru_unsigned >> Unsigned::<8>::new(3));
590
591            // H - half carry flag, bit 5
592            let flag_H = (!Rd3 & Rr3) | (Rr3 & Ru3) | (Ru3 & !Rd3);
593            result = result | (Ext::<8>::ext(flag_H) << Unsigned::<8>::new(4));
594
595            Into::<Bitvector<8>>::into(result)
596        }
597
598        // for instructions SBC, SBCI, CPC
599        // differs from compute_status_sub in zero flag treatment
600        // Rd: destination register before being set
601        // Rr: other register
602        // Ru: destination register after being set
603        fn compute_status_sbc(
604            sreg: Bitvector<8>,
605            Rd: Bitvector<8>,
606            Rr: Bitvector<8>,
607            Ru: Bitvector<8>,
608        ) -> Bitvector<8> {
609            // remember previous zero flag (bit 1 of SREG)
610            let prev_sreg_zero_flag = sreg & Bitvector::<8>::new(0b0000_0010);
611
612            let mut result = Self::compute_status_sub(sreg, Rd, Rr, Ru);
613
614            // Z - zero flag, bit 1
615            // if result is zero, the flag must remain unchanged
616            // otherwise, it is cleared as normal
617            if Ru == Bitvector::<8>::new(0) {
618                // the zero flag is now wrongly cleared, set previous
619                result = result | prev_sreg_zero_flag;
620            }
621
622            result
623        }
624
625        // for instructions INC/DEC
626        // Ru: destination register after being decremented
627        // flag_V: whether the two's complement overflow flag is set
628        fn compute_status_inc_dec(
629            sreg: Bitvector<8>,
630            Ru: Bitvector<8>,
631            flag_V: Bitvector<1>,
632        ) -> Bitvector<8> {
633            let retained_flags = Unsigned::<8>::new(0b1110_0001);
634            let mut result = Into::<Unsigned<8>>::into(sreg) & retained_flags;
635
636            let Ru_unsigned = Into::<Unsigned<8>>::into(Ru);
637            let Ru7 = Ext::<1>::ext(Ru_unsigned >> Unsigned::<8>::new(7));
638
639            // Z - zero flag, bit 1
640            if Ru == Bitvector::<8>::new(0) {
641                result = result | Unsigned::<8>::new(0b0000_0010);
642            };
643
644            // N - negative flag, bit 2
645            let flag_N = Ru7;
646            result = result | (Ext::<8>::ext(flag_N) << Unsigned::<8>::new(2));
647
648            // V - two's complement overflow flag, bit 3
649            // the only practical difference between INC and DEC status flags is given by V
650            // so we take it by parameter
651
652            let flag_V_unsigned = Into::<Unsigned<1>>::into(flag_V);
653            result = result | (Ext::<8>::ext(flag_V_unsigned) << Unsigned::<8>::new(3));
654
655            // S - sign flag (N ^ V), bit 4
656            let flag_S = flag_N ^ flag_V_unsigned;
657            result = result | (Ext::<8>::ext(flag_S) << Unsigned::<8>::new(4));
658
659            Into::<Bitvector<8>>::into(result)
660        }
661
662        // for instruction NEG
663        // Rd: register before being negated
664        // Ru: register after being negated
665        fn compute_status_neg(
666            sreg: Bitvector<8>,
667            Rd: Bitvector<8>,
668            Ru: Bitvector<8>,
669        ) -> Bitvector<8> {
670            // like compute_status_sub, but with Rd being the subtrahend from zero
671
672            let retained_flags = Unsigned::<8>::new(0b1100_0000);
673            let mut result = Into::<Unsigned<8>>::into(sreg) & retained_flags;
674
675            let Rd_unsigned = Into::<Unsigned<8>>::into(Rd);
676            let Ru_unsigned = Into::<Unsigned<8>>::into(Ru);
677
678            let Ru7 = Ext::<1>::ext(Ru_unsigned >> Unsigned::<8>::new(7));
679
680            // C - carry flag, bit 0
681            // set if there is an implied borrow, i.e. exactly if Rd/Ru is not zero
682            // Z - zero flag, bit 1
683            // set either the Z or C flag depending on Ru being zero
684            if Ru == Bitvector::<8>::new(0) {
685                result = result | Unsigned::<8>::new(0b0000_0010);
686            } else {
687                result = result | Unsigned::<8>::new(0b0000_0001);
688            }
689
690            // N - negative flag, bit 2
691            let flag_N = Ru7;
692            result = result | (Ext::<8>::ext(flag_N) << Unsigned::<8>::new(2));
693
694            // V - two's complement overflow flag, bit 3
695            // set if and only if Ru is 0x80
696            let mut flag_V = Unsigned::<1>::new(0);
697            if Ru == Bitvector::<8>::new(0x80) {
698                flag_V = Unsigned::<1>::new(1);
699            }
700
701            // S - sign flag (N ^ V), bit 4
702            let flag_S = flag_N ^ flag_V;
703            result = result | (Ext::<8>::ext(flag_S) << Unsigned::<8>::new(4));
704
705            let Rd3 = Ext::<1>::ext(Rd_unsigned >> Unsigned::<8>::new(3));
706            let Ru3 = Ext::<1>::ext(Ru_unsigned >> Unsigned::<8>::new(3));
707
708            // H - half carry flag, bit 5
709            // set exactly if there was a borrow from bit 3
710            let flag_H = Ru3 & !Rd3;
711            result = result | (Ext::<8>::ext(flag_H) << Unsigned::<8>::new(4));
712
713            Into::<Bitvector<8>>::into(result)
714        }
715
716        // for instruction ADIW
717        // Rd: register pair before addition
718        // R: register pair after addition
719        fn compute_status_adiw(
720            sreg: Bitvector<8>,
721            Rd: Bitvector<16>,
722            Ru: Bitvector<16>,
723        ) -> Bitvector<8> {
724            let retained_flags = Unsigned::<8>::new(0b1110_0000);
725            let mut result = Into::<Unsigned<8>>::into(sreg) & retained_flags;
726
727            let Rd_unsigned = Into::<Unsigned<16>>::into(Rd);
728            let Ru_unsigned = Into::<Unsigned<16>>::into(Ru);
729
730            let Rd15 = Ext::<1>::ext(Rd_unsigned >> Unsigned::<16>::new(15));
731            let Ru15 = Ext::<1>::ext(Ru_unsigned >> Unsigned::<16>::new(15));
732
733            // C - carry flag, bit 0
734            let flag_C = !Ru15 & Rd15;
735            result = result | Ext::<8>::ext(flag_C);
736
737            // Z - zero flag, bit 1
738            if Ru == Bitvector::<16>::new(0) {
739                result = result | Unsigned::<8>::new(0b0000_0010);
740            };
741
742            // N - negative flag, bit 2
743            let flag_N = Ru15;
744            result = result | (Ext::<8>::ext(flag_N) << Unsigned::<8>::new(2));
745
746            // V - two's complement overflow flag, bit 3
747            let flag_V = !Rd15 & Ru15;
748            result = result | (Ext::<8>::ext(flag_V) << Unsigned::<8>::new(3));
749
750            // S - sign flag (N ^ V), bit 4
751            let flag_S = flag_N ^ flag_V;
752            result = result | (Ext::<8>::ext(flag_S) << Unsigned::<8>::new(4));
753
754            Into::<Bitvector<8>>::into(result)
755        }
756
757        // for instruction SBIW
758        // Rd: register pair before subtraction
759        // R: register pair after subtraction
760        fn compute_status_sbiw(
761            sreg: Bitvector<8>,
762            Rd: Bitvector<16>,
763            Ru: Bitvector<16>,
764        ) -> Bitvector<8> {
765            let retained_flags = Unsigned::<8>::new(0b1110_0000);
766            let mut result = Into::<Unsigned<8>>::into(sreg) & retained_flags;
767
768            let Rd_unsigned = Into::<Unsigned<16>>::into(Rd);
769            let Ru_unsigned = Into::<Unsigned<16>>::into(Ru);
770
771            let Rd15 = Ext::<1>::ext(Rd_unsigned >> Unsigned::<16>::new(15));
772            let Ru15 = Ext::<1>::ext(Ru_unsigned >> Unsigned::<16>::new(15));
773
774            // C - carry flag, bit 0
775            let flag_C = Ru15 & !Rd15;
776            result = result | Ext::<8>::ext(flag_C);
777
778            // Z - zero flag, bit 1
779            if Ru == Bitvector::<16>::new(0) {
780                result = result | Unsigned::<8>::new(0b0000_0010);
781            };
782
783            // N - negative flag, bit 2
784            let flag_N = Ru15;
785            result = result | (Ext::<8>::ext(flag_N) << Unsigned::<8>::new(2));
786
787            // V - two's complement overflow flag, bit 3
788            let flag_V = Ru15 & !Rd15;
789            result = result | (Ext::<8>::ext(flag_V) << Unsigned::<8>::new(3));
790
791            // S - sign flag (N ^ V), bit 4
792            let flag_S = flag_N ^ flag_V;
793            result = result | (Ext::<8>::ext(flag_S) << Unsigned::<8>::new(4));
794
795            Into::<Bitvector<8>>::into(result)
796        }
797
798        // for instructions: MUL, MULS, MULSU, FMUL, FMULS, FMULSU
799        // Rt: multiplication result (before shifting in fractional multiplies)
800        // Ru: final multiplication result
801        fn compute_status_mul(
802            sreg: Bitvector<8>,
803            Rt: Bitvector<16>,
804            Ru: Bitvector<16>,
805        ) -> Bitvector<8> {
806            let retained_flags = Unsigned::<8>::new(0b1111_1100);
807            let mut result = Into::<Unsigned<8>>::into(sreg) & retained_flags;
808
809            let Rt_unsigned = Into::<Unsigned<16>>::into(Rt);
810            let Rt15 = Ext::<1>::ext(Rt_unsigned >> Unsigned::<16>::new(15));
811
812            // C - carry flag, bit 0
813            // copies bit 15 of result (before shifting in fractional multiplies)
814            let flag_C = Rt15;
815            result = result | Ext::<8>::ext(flag_C);
816
817            // Z - zero flag, bit 1
818            // whether the final result is zero
819            if Ru == Bitvector::<16>::new(0) {
820                result = result | Unsigned::<8>::new(0b0000_0010);
821            };
822
823            Into::<Bitvector<8>>::into(result)
824        }
825
826        fn next_0000(state: &State, instruction: Bitvector<16>) -> State {
827            let PC = state.PC;
828            let mut R = Clone::clone(&state.R);
829            let DDRB = state.DDRB;
830            let PORTB = state.PORTB;
831            let DDRC = state.DDRC;
832            let PORTC = state.PORTC;
833            let DDRD = state.DDRD;
834            let PORTD = state.PORTD;
835            let GPIOR0 = state.GPIOR0;
836            let GPIOR1 = state.GPIOR1;
837            let GPIOR2 = state.GPIOR2;
838            let SPL = state.SPL;
839            let SPH = state.SPH;
840            let mut SREG = state.SREG;
841            let SRAM = Clone::clone(&state.SRAM);
842
843            ::machine_check::bitmask_switch!(instruction {
844                // NOP
845                "----_0000_0000_0000" => {
846                    // do nothing
847                },
848
849                // other 255 opcodes starting with 0000_0000 are reserved
850                "----_0000_0000_0001" => {
851                    panic!("Reserved opcode");
852                }
853                "----_0000_0000_001-" => {
854                    panic!("Reserved opcode");
855                }
856                "----_0000_0000_01--" => {
857                    panic!("Reserved opcode");
858                }
859                "----_0000_0000_1---" => {
860                    panic!("Reserved opcode");
861                }
862                "----_0000_0001_----" => {
863                    panic!("Reserved opcode");
864                }
865                "----_0000_001-_----" => {
866                    panic!("Reserved opcode");
867                }
868                "----_0000_01--_----" => {
869                    panic!("Reserved opcode");
870                }
871                "----_0000_1---_----" => {
872                    panic!("Reserved opcode");
873                }
874
875                // MOVW
876                "----_0001_dddd_rrrr" => {
877                    // copy register pair
878                    let d_unsigned = Into::<Unsigned<4>>::into(d);
879                    let d_ext_unsigned = Ext::<5>::ext(d_unsigned);
880                    let d_ext = Into::<Bitvector<5>>::into(d_ext_unsigned);
881
882                    let r_unsigned = Into::<Unsigned<4>>::into(r);
883                    let r_ext_unsigned = Ext::<5>::ext(r_unsigned);
884                    let r_ext = Into::<Bitvector<5>>::into(r_ext_unsigned);
885
886                    R[d_ext + d_ext] = R[r_ext + r_ext];
887
888                    let five_bit_one = Bitvector::<5>::new(1);
889                    R[d_ext + d_ext + five_bit_one] = R[r_ext + r_ext + five_bit_one];
890                }
891
892                // MULS
893                "----_0010_dddd_rrrr" => {
894                    // the operand registers are 16 to 31
895                    let reg_d = Into::<Bitvector<5>>::into(Ext::<5>::ext(Into::<Unsigned<4>>::into(d))) + Bitvector::<5>::new(16);
896                    let reg_r = Into::<Bitvector<5>>::into(Ext::<5>::ext(Into::<Unsigned<4>>::into(r))) + Bitvector::<5>::new(16);
897
898                    // multiply signed by signed
899                    let d_ext = Into::<Bitvector<16>>::into(Ext::<16>::ext(Into::<Signed<8>>::into(state.R[reg_d])));
900                    let r_ext = Into::<Bitvector<16>>::into(Ext::<16>::ext(Into::<Signed<8>>::into(state.R[reg_r])));
901
902                    let mul_result = d_ext * r_ext;
903                    let mul_result_lo = Into::<Bitvector<8>>::into(Ext::<8>::ext(Into::<Unsigned<16>>::into(mul_result)));
904                    let mul_result_hi = Into::<Bitvector<8>>::into(Ext::<8>::ext(Into::<Unsigned<16>>::into(mul_result) >> Unsigned::<16>::new(8)));
905
906                    // store result low byte into register 0 and high byte into register 1
907                    R[Bitvector::<5>::new(0)] = mul_result_lo;
908                    R[Bitvector::<5>::new(1)] = mul_result_hi;
909
910                    // update status register
911                    SREG = Self::compute_status_mul(state.SREG, mul_result, mul_result);
912
913                }
914                // MULSU
915                "----_0011_0ddd_0rrr" => {
916                    // the operand registers are 16 to 23
917                    let reg_d = Into::<Bitvector<5>>::into(Ext::<5>::ext(Into::<Unsigned<3>>::into(d))) + Bitvector::<5>::new(16);
918                    let reg_r = Into::<Bitvector<5>>::into(Ext::<5>::ext(Into::<Unsigned<3>>::into(r))) + Bitvector::<5>::new(16);
919
920                    // multiply signed by unsigned
921                    let d_ext = Into::<Bitvector<16>>::into(Ext::<16>::ext(Into::<Signed<8>>::into(state.R[reg_d])));
922                    let r_ext = Into::<Bitvector<16>>::into(Ext::<16>::ext(Into::<Unsigned<8>>::into(state.R[reg_r])));
923
924                    let mul_result = d_ext * r_ext;
925                    let mul_result_lo = Into::<Bitvector<8>>::into(Ext::<8>::ext(Into::<Unsigned<16>>::into(mul_result)));
926                    let mul_result_hi = Into::<Bitvector<8>>::into(Ext::<8>::ext(Into::<Unsigned<16>>::into(mul_result) >> Unsigned::<16>::new(8)));
927
928                    // store result low byte into register 0 and high byte into register 1
929                    R[Bitvector::<5>::new(0)] = mul_result_lo;
930                    R[Bitvector::<5>::new(1)] = mul_result_hi;
931
932                    // update status register
933                    SREG = Self::compute_status_mul(state.SREG, mul_result, mul_result);
934                }
935
936                // FMUL
937                "----_0011_0ddd_1rrr" => {
938                    // the operand registers are 16 to 23
939                    let reg_d = Into::<Bitvector<5>>::into(Ext::<5>::ext(Into::<Unsigned<3>>::into(d))) + Bitvector::<5>::new(16);
940                    let reg_r = Into::<Bitvector<5>>::into(Ext::<5>::ext(Into::<Unsigned<3>>::into(r))) + Bitvector::<5>::new(16);
941
942                    // multiply unsigned by unsigned
943                    let d_ext = Into::<Bitvector<16>>::into(Ext::<16>::ext(Into::<Unsigned<8>>::into(state.R[reg_d])));
944                    let r_ext = Into::<Bitvector<16>>::into(Ext::<16>::ext(Into::<Unsigned<8>>::into(state.R[reg_r])));
945
946                    let mul_result = d_ext * r_ext;
947
948                    // shift multiplication result left by one position
949                    let fmul_result = mul_result << Bitvector::<16>::new(1);
950
951                    let fmul_result_lo = Into::<Bitvector<8>>::into(Ext::<8>::ext(Into::<Unsigned<16>>::into(fmul_result)));
952                    let fmul_result_hi = Into::<Bitvector<8>>::into(Ext::<8>::ext(Into::<Unsigned<16>>::into(fmul_result) >> Unsigned::<16>::new(8)));
953
954                    // store fractional result low byte into register 0 and high byte into register 1
955                    R[Bitvector::<5>::new(0)] = fmul_result_lo;
956                    R[Bitvector::<5>::new(1)] = fmul_result_hi;
957
958                    // update status register
959                    SREG = Self::compute_status_mul(state.SREG, mul_result, fmul_result);
960                }
961
962                // FMULS
963                "----_0011_1ddd_0rrr" => {
964                    // the operand registers are 16 to 23
965                    let reg_d = Into::<Bitvector<5>>::into(Ext::<5>::ext(Into::<Unsigned<3>>::into(d))) + Bitvector::<5>::new(16);
966                    let reg_r = Into::<Bitvector<5>>::into(Ext::<5>::ext(Into::<Unsigned<3>>::into(r))) + Bitvector::<5>::new(16);
967
968                    // multiply signed by signed
969                    let d_ext = Into::<Bitvector<16>>::into(Ext::<16>::ext(Into::<Signed<8>>::into(state.R[reg_d])));
970                    let r_ext = Into::<Bitvector<16>>::into(Ext::<16>::ext(Into::<Signed<8>>::into(state.R[reg_r])));
971
972                    let mul_result = d_ext * r_ext;
973
974                    // shift multiplication result left by one position
975                    let fmul_result = mul_result << Bitvector::<16>::new(1);
976
977                    let fmul_result_lo = Into::<Bitvector<8>>::into(Ext::<8>::ext(Into::<Unsigned<16>>::into(fmul_result)));
978                    let fmul_result_hi = Into::<Bitvector<8>>::into(Ext::<8>::ext(Into::<Unsigned<16>>::into(fmul_result) >> Unsigned::<16>::new(8)));
979
980                    // store fractional result low byte into register 0 and high byte into register 1
981                    R[Bitvector::<5>::new(0)] = fmul_result_lo;
982                    R[Bitvector::<5>::new(1)] = fmul_result_hi;
983
984                    // update status register
985                    SREG = Self::compute_status_mul(state.SREG, mul_result, fmul_result);
986                }
987
988                // FMULSU
989                "----_0011_1ddd_1rrr" => {
990                    // the operand registers are 16 to 23
991                    let reg_d = Into::<Bitvector<5>>::into(Ext::<5>::ext(Into::<Unsigned<3>>::into(d))) + Bitvector::<5>::new(16);
992                    let reg_r = Into::<Bitvector<5>>::into(Ext::<5>::ext(Into::<Unsigned<3>>::into(r))) + Bitvector::<5>::new(16);
993
994                    // multiply signed by unsigned
995                    let d_ext = Into::<Bitvector<16>>::into(Ext::<16>::ext(Into::<Signed<8>>::into(state.R[reg_d])));
996                    let r_ext = Into::<Bitvector<16>>::into(Ext::<16>::ext(Into::<Unsigned<8>>::into(state.R[reg_r])));
997
998                    let mul_result = d_ext * r_ext;
999
1000                    // shift multiplication result left by one position
1001                    let fmul_result = mul_result << Bitvector::<16>::new(1);
1002
1003                    let fmul_result_lo = Into::<Bitvector<8>>::into(Ext::<8>::ext(Into::<Unsigned<16>>::into(fmul_result)));
1004                    let fmul_result_hi = Into::<Bitvector<8>>::into(Ext::<8>::ext(Into::<Unsigned<16>>::into(fmul_result) >> Unsigned::<16>::new(8)));
1005
1006                    // store fractional result low byte into register 0 and high byte into register 1
1007                    R[Bitvector::<5>::new(0)] = fmul_result_lo;
1008                    R[Bitvector::<5>::new(1)] = fmul_result_hi;
1009
1010                    // update status register
1011                    SREG = Self::compute_status_mul(state.SREG, mul_result, fmul_result);
1012                }
1013
1014                // CPC
1015                "----_01rd_dddd_rrrr" => {
1016                    // compare with carry, same as SBC without actually saving the computed value
1017                    // carry is in bit 0
1018                    let carry = SREG & Bitvector::<8>::new(0b0000_0001);
1019                    let result = R[d] - R[r] - carry;
1020                    SREG = Self::compute_status_sbc(SREG, R[d], R[r], result);
1021                }
1022
1023                // SBC
1024                "----_10rd_dddd_rrrr" => {
1025                    // subtract with carry
1026                    let prev = R[d];
1027                    // carry is in bit 0
1028                    let carry = SREG & Bitvector::<8>::new(0b0000_0001);
1029                    R[d] = R[d] - R[r] - carry;
1030                    SREG = Self::compute_status_sbc(SREG, prev, R[r], R[d]);
1031                }
1032
1033                // ADD
1034                "----_11rd_dddd_rrrr" => {
1035                    let prev = R[d];
1036                    R[d] = R[d] + R[r];
1037                    SREG = Self::compute_status_add(SREG, prev, R[r], R[d]);
1038                }
1039            });
1040
1041            State {
1042                PC,
1043                R,
1044                DDRB,
1045                PORTB,
1046                DDRC,
1047                PORTC,
1048                DDRD,
1049                PORTD,
1050                GPIOR0,
1051                GPIOR1,
1052                GPIOR2,
1053                SPL,
1054                SPH,
1055                SREG,
1056                SRAM,
1057            }
1058        }
1059
1060        fn next_0001(&self, state: &State, instruction: Bitvector<16>) -> State {
1061            let mut PC = state.PC;
1062            let mut R = Clone::clone(&state.R);
1063            let DDRB = state.DDRB;
1064            let PORTB = state.PORTB;
1065            let DDRC = state.DDRC;
1066            let PORTC = state.PORTC;
1067            let DDRD = state.DDRD;
1068            let PORTD = state.PORTD;
1069            let GPIOR0 = state.GPIOR0;
1070            let GPIOR1 = state.GPIOR1;
1071            let GPIOR2 = state.GPIOR2;
1072            let SPL = state.SPL;
1073            let SPH = state.SPH;
1074            let mut SREG = state.SREG;
1075            let SRAM = Clone::clone(&state.SRAM);
1076
1077            ::machine_check::bitmask_switch!(instruction {
1078                // CPSE
1079                "----_00rd_dddd_rrrr" => {
1080                    // compare skip if equal
1081                    // similar to other skips, but with register comparison
1082                    if R[d] == R[r] {
1083                        // they are equal, skip next instruction
1084                        PC = Self::instruction_skip(self, PC);
1085                    } else {
1086                        // they are not equal, do nothing
1087                    };
1088                }
1089
1090                // CP
1091                "----_01rd_dddd_rrrr" => {
1092                    // compare, same as SUB without actually saving the computed value
1093                    let result = R[d] - R[r];
1094                    SREG = Self::compute_status_sub(SREG, R[d], R[r], result);
1095                }
1096
1097                // SUB
1098                "----_10rd_dddd_rrrr" => {
1099                    let prev = R[d];
1100                    R[d] = R[d] - R[r];
1101                    SREG = Self::compute_status_sub(SREG, prev, R[r], R[d]);
1102                }
1103
1104                // ADC
1105                "----_11rd_dddd_rrrr" => {
1106                    // add with carry
1107                    let prev = R[d];
1108                    // carry is in bit 0
1109                    let carry = SREG & Bitvector::<8>::new(0b0000_0001);
1110                    R[d] = R[d] + R[r] + carry;
1111                    SREG = Self::compute_status_add(SREG, prev, R[r], R[d]);
1112                }
1113            });
1114
1115            State {
1116                PC,
1117                R,
1118                DDRB,
1119                PORTB,
1120                DDRC,
1121                PORTC,
1122                DDRD,
1123                PORTD,
1124                GPIOR0,
1125                GPIOR1,
1126                GPIOR2,
1127                SPL,
1128                SPH,
1129                SREG,
1130                SRAM,
1131            }
1132        }
1133
1134        fn next_0010(state: &State, instruction: Bitvector<16>) -> State {
1135            let PC = state.PC;
1136            let mut R = Clone::clone(&state.R);
1137            let DDRB = state.DDRB;
1138            let PORTB = state.PORTB;
1139            let DDRC = state.DDRC;
1140            let PORTC = state.PORTC;
1141            let DDRD = state.DDRD;
1142            let PORTD = state.PORTD;
1143            let GPIOR0 = state.GPIOR0;
1144            let GPIOR1 = state.GPIOR1;
1145            let GPIOR2 = state.GPIOR2;
1146            let SPL = state.SPL;
1147            let SPH = state.SPH;
1148            let mut SREG = state.SREG;
1149            let SRAM = Clone::clone(&state.SRAM);
1150
1151            ::machine_check::bitmask_switch!(instruction {
1152
1153                // AND
1154                "----_00rd_dddd_rrrr" => {
1155                    // logical and
1156                    R[d] =  R[d] & R[r];
1157                    SREG = Self::compute_status_logical(SREG, R[d]);
1158
1159                }
1160
1161                // EOR
1162                "----_01rd_dddd_rrrr" => {
1163
1164                    // exclusive or
1165
1166                    // kludge: when zeroing the register through EOR,
1167                    // bypass unknown values by setting zero directly
1168                    // this is due to this special case being widely
1169                    // used to set a register to zero
1170                    if r == d {
1171                        R[d] = Bitvector::<8>::new(0);
1172                    } else {
1173                        R[d] = R[d] ^ R[r];
1174                    };
1175
1176                    SREG = Self::compute_status_logical(SREG, R[d]);
1177
1178                }
1179
1180                // OR
1181                "----_10rd_dddd_rrrr" => {
1182                    // logical or
1183                    R[d] = R[d] | R[r];
1184                    SREG = Self::compute_status_logical(SREG, R[d]);
1185                }
1186
1187                // MOV
1188                "----_11rd_dddd_rrrr" => {
1189                    // copy register, status flags not affected
1190                    R[d] = R[r];
1191                }
1192            });
1193
1194            State {
1195                PC,
1196                R,
1197                DDRB,
1198                PORTB,
1199                DDRC,
1200                PORTC,
1201                DDRD,
1202                PORTD,
1203                GPIOR0,
1204                GPIOR1,
1205                GPIOR2,
1206                SPL,
1207                SPH,
1208                SREG,
1209                SRAM,
1210            }
1211        }
1212
1213        fn next_0011(state: &State, instruction: Bitvector<16>) -> State {
1214            let PC = state.PC;
1215            let R = Clone::clone(&state.R);
1216            let DDRB = state.DDRB;
1217            let PORTB = state.PORTB;
1218            let DDRC = state.DDRC;
1219            let PORTC = state.PORTC;
1220            let DDRD = state.DDRD;
1221            let PORTD = state.PORTD;
1222            let GPIOR0 = state.GPIOR0;
1223            let GPIOR1 = state.GPIOR1;
1224            let GPIOR2 = state.GPIOR2;
1225            let SPL = state.SPL;
1226            let SPH = state.SPH;
1227            let mut SREG = state.SREG;
1228            let SRAM = Clone::clone(&state.SRAM);
1229
1230            ::machine_check::bitmask_switch!(instruction {
1231                // CPI
1232                "----_kkkk_dddd_kkkk" => {
1233                    // extend d to five bits and add 16
1234                    let d_unsigned = Into::<Unsigned<4>>::into(d);
1235                    let d_ext_unsigned = Ext::<5>::ext(d_unsigned);
1236                    let d_ext = Into::<Bitvector<5>>::into(d_ext_unsigned);
1237                    let reg_num = d_ext + Bitvector::<5>::new(16);
1238
1239                    // compare with immediate
1240                    let result = R[reg_num] - k;
1241
1242                    SREG = Self::compute_status_sub(SREG, R[reg_num], k, result);
1243                }
1244            });
1245
1246            State {
1247                PC,
1248                R,
1249                DDRB,
1250                PORTB,
1251                DDRC,
1252                PORTC,
1253                DDRD,
1254                PORTD,
1255                GPIOR0,
1256                GPIOR1,
1257                GPIOR2,
1258                SPL,
1259                SPH,
1260                SREG,
1261                SRAM,
1262            }
1263        }
1264
1265        fn next_01(state: &State, instruction: Bitvector<16>) -> State {
1266            let PC = state.PC;
1267            let mut R = Clone::clone(&state.R);
1268            let DDRB = state.DDRB;
1269            let PORTB = state.PORTB;
1270            let DDRC = state.DDRC;
1271            let PORTC = state.PORTC;
1272            let DDRD = state.DDRD;
1273            let PORTD = state.PORTD;
1274            let GPIOR0 = state.GPIOR0;
1275            let GPIOR1 = state.GPIOR1;
1276            let GPIOR2 = state.GPIOR2;
1277            let SPL = state.SPL;
1278            let SPH = state.SPH;
1279            let mut SREG = state.SREG;
1280            let SRAM = Clone::clone(&state.SRAM);
1281
1282            ::machine_check::bitmask_switch!(instruction {
1283
1284                // SBCI
1285                "--00_kkkk_dddd_kkkk" => {
1286                    // extend d to five bits and add 16
1287                    let d_unsigned = Into::<Unsigned<4>>::into(d);
1288                    let d_ext_unsigned = Ext::<5>::ext(d_unsigned);
1289                    let d_ext = Into::<Bitvector<5>>::into(d_ext_unsigned);
1290                    let reg_num = d_ext + Bitvector::<5>::new(16);
1291
1292                    // subtract immediate with carry
1293                    let prev = R[reg_num];
1294                    // carry is in bit 0
1295                    let carry = SREG & Bitvector::<8>::new(0b0000_0001);
1296                    R[reg_num] = R[reg_num] - k - carry;
1297                    SREG = Self::compute_status_sbc(SREG, prev, k, R[reg_num]);
1298                }
1299                // SUBI
1300                "--01_kkkk_dddd_kkkk" => {
1301                    // extend d to five bits and add 16
1302                    let d_unsigned = Into::<Unsigned<4>>::into(d);
1303                    let d_ext_unsigned = Ext::<5>::ext(d_unsigned);
1304                    let d_ext = Into::<Bitvector<5>>::into(d_ext_unsigned);
1305                    let reg_num = d_ext + Bitvector::<5>::new(16);
1306
1307                    // subtract immediate
1308                    let prev = R[reg_num];
1309                    R[reg_num] = R[reg_num] - k;
1310
1311                    SREG = Self::compute_status_sub(SREG, prev, k, R[reg_num]);
1312                }
1313                // ORI
1314                "--10_kkkk_dddd_kkkk" => {
1315                    // extend d to five bits and add 16
1316                    let d_unsigned = Into::<Unsigned<4>>::into(d);
1317                    let d_ext_unsigned = Ext::<5>::ext(d_unsigned);
1318                    let d_ext = Into::<Bitvector<5>>::into(d_ext_unsigned);
1319                    let reg_num = d_ext + Bitvector::<5>::new(16);
1320
1321                    // logical or with immediate
1322                    R[reg_num] = R[reg_num] | k;
1323                    SREG = Self::compute_status_logical(SREG, R[reg_num]);
1324                }
1325                // ANDI
1326                "--11_kkkk_dddd_kkkk" => {
1327                    // extend d to five bits and add 16
1328                    let d_unsigned = Into::<Unsigned<4>>::into(d);
1329                    let d_ext_unsigned = Ext::<5>::ext(d_unsigned);
1330                    let d_ext = Into::<Bitvector<5>>::into(d_ext_unsigned);
1331                    let reg_num = d_ext + Bitvector::<5>::new(16);
1332
1333                    // logical and with immediate
1334                    R[reg_num] = R[reg_num] & k;
1335                    SREG = Self::compute_status_logical(SREG, R[reg_num]);
1336                }
1337            });
1338
1339            State {
1340                PC,
1341                R,
1342                DDRB,
1343                PORTB,
1344                DDRC,
1345                PORTC,
1346                DDRD,
1347                PORTD,
1348                GPIOR0,
1349                GPIOR1,
1350                GPIOR2,
1351                SPL,
1352                SPH,
1353                SREG,
1354                SRAM,
1355            }
1356        }
1357
1358        fn load_with_displacement(
1359            state: &State,
1360            input: &Input,
1361            address_lo_index: Bitvector<5>,
1362            result_reg_index: Bitvector<5>,
1363            displacement: Bitvector<6>,
1364        ) -> BitvectorArray<5, 8> {
1365            let mut R = Clone::clone(&state.R);
1366
1367            let address_hi_index = address_lo_index + Bitvector::<5>::new(1);
1368
1369            let address_lo = Ext::<16>::ext(Into::<Unsigned<8>>::into(R[address_lo_index]));
1370            let address_hi = Ext::<16>::ext(Into::<Unsigned<8>>::into(R[address_hi_index]));
1371            let address = (address_hi << Unsigned::<16>::new(8)) | address_lo;
1372
1373            // add displacement, it is interpreted as 6-bit unsigned
1374            let address_with_displacement =
1375                address + Ext::<16>::ext(Into::<Unsigned<6>>::into(displacement));
1376
1377            // load
1378            let read_result: Bitvector<8> = Self::read_data_mem(
1379                state,
1380                input,
1381                Into::<Bitvector<16>>::into(address_with_displacement),
1382            );
1383            R[result_reg_index] = read_result;
1384            R
1385        }
1386
1387        fn store_with_displacement(
1388            state: &State,
1389            address_lo_index: Bitvector<5>,
1390            value_reg_index: Bitvector<5>,
1391            displacement: Bitvector<6>,
1392        ) -> State {
1393            let address_hi_index = address_lo_index + Bitvector::<5>::new(1);
1394
1395            let address_lo = Ext::<16>::ext(Into::<Unsigned<8>>::into(state.R[address_lo_index]));
1396            let address_hi = Ext::<16>::ext(Into::<Unsigned<8>>::into(state.R[address_hi_index]));
1397            let address = (address_hi << Unsigned::<16>::new(8)) | address_lo;
1398
1399            // add displacement, it is interpreted as 6-bit unsigned
1400            let address_with_displacement =
1401                address + Ext::<16>::ext(Into::<Unsigned<6>>::into(displacement));
1402
1403            let value = state.R[value_reg_index];
1404
1405            // store
1406            let write_result: State = Self::write_data_mem(
1407                state,
1408                Into::<Bitvector<16>>::into(address_with_displacement),
1409                value,
1410            );
1411            write_result
1412        }
1413
1414        fn next_10q0(state: &State, input: &Input, instruction: Bitvector<16>) -> State {
1415            let PC = state.PC;
1416            let DDRB = state.DDRB;
1417            let PORTB = state.PORTB;
1418            let DDRC = state.DDRC;
1419            let PORTC = state.PORTC;
1420            let DDRD = state.DDRD;
1421            let PORTD = state.PORTD;
1422            let GPIOR0 = state.GPIOR0;
1423            let GPIOR1 = state.GPIOR1;
1424            let GPIOR2 = state.GPIOR2;
1425            let SPL = state.SPL;
1426            let SPH = state.SPH;
1427            let SREG = state.SREG;
1428
1429            let mut result = Clone::clone(state);
1430
1431            ::machine_check::bitmask_switch!(instruction {
1432                // LD Rd, Z+q
1433                "--q-_qq0d_dddd_0qqq" => {
1434                    // load data memory pointed to by Z (30:31) with displacement
1435                    let SRAM = Clone::clone(&state.SRAM);
1436                    let R: BitvectorArray<5, 8> = Self::load_with_displacement(state, input, Bitvector::<5>::new(30), d, q);
1437                    result = State {
1438                        PC,
1439                        R,
1440                        DDRB,
1441                        PORTB,
1442                        DDRC,
1443                        PORTC,
1444                        DDRD,
1445                        PORTD,
1446                        GPIOR0,
1447                        GPIOR1,
1448                        GPIOR2,
1449                        SPL,
1450                        SPH,
1451                        SREG,
1452                        SRAM,
1453                    };
1454                }
1455
1456                // LD Rd, Y+q
1457                "--q-_qq0d_dddd_1qqq" => {
1458                    // load data memory pointed to by Y (28:29) with displacement
1459                    let SRAM = Clone::clone(&state.SRAM);
1460                    let R: BitvectorArray<5, 8>  = Self::load_with_displacement(state, input, Bitvector::<5>::new(28), d, q);
1461                    result = State {
1462                        PC,
1463                        R,
1464                        DDRB,
1465                        PORTB,
1466                        DDRC,
1467                        PORTC,
1468                        DDRD,
1469                        PORTD,
1470                        GPIOR0,
1471                        GPIOR1,
1472                        GPIOR2,
1473                        SPL,
1474                        SPH,
1475                        SREG,
1476                        SRAM,
1477                    };
1478                }
1479
1480                // ST Z+q, Rr
1481                "--q-_qq1r_rrrr_0qqq" => {
1482                    // store data memory pointed to by Y (30:31) with displacement
1483                    result = Self::store_with_displacement(state, Bitvector::<5>::new(30), r, q);
1484                }
1485
1486                // ST Y+q, Rr
1487                "--q-_qq1r_rrrr_1qqq" => {
1488                    // store data memory pointed to by Y (28:29) with displacement
1489                    result = Self::store_with_displacement(state, Bitvector::<5>::new(28), r, q);
1490                }
1491            });
1492            result
1493        }
1494
1495        fn load_post_increment(
1496            state: &State,
1497            input: &Input,
1498            address_lo_index: Bitvector<5>,
1499            result_reg_index: Bitvector<5>,
1500        ) -> BitvectorArray<5, 8> {
1501            let mut R = Clone::clone(&state.R);
1502
1503            let address_hi_index = address_lo_index + Bitvector::<5>::new(1);
1504
1505            let address_lo = Ext::<16>::ext(Into::<Unsigned<8>>::into(R[address_lo_index]));
1506            let address_hi = Ext::<16>::ext(Into::<Unsigned<8>>::into(R[address_hi_index]));
1507            let address = (address_hi << Unsigned::<16>::new(8)) | address_lo;
1508
1509            // load
1510            let read_result: Bitvector<8> =
1511                Self::read_data_mem(state, input, Into::<Bitvector<16>>::into(address));
1512            R[result_reg_index] = read_result;
1513
1514            // post-increment
1515            if (result_reg_index == address_lo_index) | (result_reg_index == address_hi_index) {
1516                panic!("Illegal load with post-increment from part of address register");
1517            }
1518            let address_post = address + Unsigned::<16>::new(1);
1519            let address_lo_post = Into::<Bitvector<8>>::into(Ext::<8>::ext(address_post));
1520            let address_hi_post =
1521                Into::<Bitvector<8>>::into(Ext::<8>::ext(address_post >> Unsigned::<16>::new(8)));
1522            R[address_lo_index] = address_lo_post;
1523            R[address_hi_index] = address_hi_post;
1524            R
1525        }
1526
1527        fn load_pre_decrement(
1528            state: &State,
1529            input: &Input,
1530            address_lo_index: Bitvector<5>,
1531            result_reg_index: Bitvector<5>,
1532        ) -> BitvectorArray<5, 8> {
1533            let mut R = Clone::clone(&state.R);
1534
1535            let address_hi_index = address_lo_index + Bitvector::<5>::new(1);
1536
1537            if (result_reg_index == address_lo_index) | (result_reg_index == address_hi_index) {
1538                panic!("Illegal load with pre-decrement from part of address register");
1539            }
1540
1541            let old_address_lo = Ext::<16>::ext(Into::<Unsigned<8>>::into(R[address_lo_index]));
1542            let old_address_hi = Ext::<16>::ext(Into::<Unsigned<8>>::into(R[address_hi_index]));
1543            let old_address = (old_address_hi << Unsigned::<16>::new(8)) | old_address_lo;
1544
1545            // pre-decrement
1546            let address = old_address - Unsigned::<16>::new(1);
1547            let address_lo = Into::<Bitvector<8>>::into(Ext::<8>::ext(address));
1548            let address_hi =
1549                Into::<Bitvector<8>>::into(Ext::<8>::ext(address >> Unsigned::<16>::new(8)));
1550            R[address_lo_index] = address_lo;
1551            R[address_hi_index] = address_hi;
1552
1553            // load
1554            let read_result: Bitvector<8> =
1555                Self::read_data_mem(state, input, Into::<Bitvector<16>>::into(address));
1556            R[result_reg_index] = read_result;
1557            R
1558        }
1559
1560        fn next_1001_000d(
1561            &self,
1562            state: &State,
1563            input: &Input,
1564            instruction: Bitvector<16>,
1565        ) -> State {
1566            let mut PC = state.PC;
1567            let mut R = Clone::clone(&state.R);
1568            let DDRB = state.DDRB;
1569            let PORTB = state.PORTB;
1570            let DDRC = state.DDRC;
1571            let PORTC = state.PORTC;
1572            let DDRD = state.DDRD;
1573            let PORTD = state.PORTD;
1574            let GPIOR0 = state.GPIOR0;
1575            let GPIOR1 = state.GPIOR1;
1576            let GPIOR2 = state.GPIOR2;
1577            let mut SPL = state.SPL;
1578            let mut SPH = state.SPH;
1579            let SREG = state.SREG;
1580            let SRAM = Clone::clone(&state.SRAM);
1581
1582            ::machine_check::bitmask_switch!(instruction {
1583                // LDS - 2 words
1584                "----_---d_dddd_0000" => {
1585                    // load direct from data space to register d
1586
1587                    // LDS is a 2-word instruction, the address is in program memory in the next instruction location
1588                    // PC is already incremented to point to the next instruction, fetch it and increment PC once again
1589                    let address = self.PROGMEM[PC];
1590                    PC = PC + Bitvector::<14>::new(1);
1591
1592                    let read_result: Bitvector<8> = Self::read_data_mem(state, input, Into::<Bitvector<16>>::into(address));
1593                    R[d] = read_result;
1594                }
1595
1596                // LD Rd, Z+
1597                "----_---d_dddd_0001" => {
1598                    // load data memory pointed to by Z (30:31) with post-increment
1599                    R = Self::load_post_increment(state, input, Bitvector::<5>::new(30), d);
1600                }
1601
1602                // LD Rd, -Z
1603                "----_---d_dddd_0010" => {
1604                    // load data memory pointed to by Z (30:31) with pre-decrement
1605                    R = Self::load_pre_decrement(state, input, Bitvector::<5>::new(30), d);
1606                }
1607
1608                // 0011 reserved
1609                "----_---d_dddd_0011" => {
1610                    panic!("Reserved opcode");
1611                }
1612
1613                // LPM Rd, Z
1614                "----_---d_dddd_0100" => {
1615                    unimplemented!("LPM instruction");
1616                    /*
1617                    // load program memory
1618                    //R[d] = fetchProgramByte(Z);
1619                    unimplemented();
1620
1621                    // LPM is a three-cycle instruction
1622                    increment_cycle_count();
1623                    increment_cycle_count();
1624                    */
1625                }
1626
1627                // LPM Rd, Z+
1628                "----_---d_dddd_0101" => {
1629                    unimplemented!("LPM instruction");
1630                    /*
1631                    // load program memory with post-increment
1632                    //R[d] = fetchProgramByte(Z);
1633                    unimplemented();
1634
1635                    Z = Z + 1;
1636
1637                    // LPM is a three-cycle instruction
1638                    increment_cycle_count();
1639                    increment_cycle_count();
1640                    */
1641                }
1642
1643                // ELPM Rd, Z
1644                "----_---d_dddd_0110" => {
1645                    unimplemented!("ELPM instruction");
1646                    //R[d] = PROGRAM[RAMPZ:Z];
1647                }
1648
1649                // ELPM Rd, Z+
1650                "----_---d_dddd_0111" => {
1651                    unimplemented!("ELPM instruction");
1652                    //R[d] = PROGRAM[RAMPZ:Z]; (RAMPZ:Z) = (RAMPZ:Z) + 1;
1653                }
1654
1655                // 1000 reserved
1656                "----_---d_dddd_1000" => {
1657                    panic!("Reserved opcode");
1658                }
1659
1660                // LD Rd, Y+
1661                "----_---d_dddd_1001" => {
1662                    // load data memory pointed to by Y (28:29) with post-increment
1663                    R = Self::load_post_increment(state, input, Bitvector::<5>::new(28), d);
1664                }
1665
1666                // LD Rd, -Y
1667                "----_---d_dddd_1010" => {
1668                    // load data memory pointed to by Y (28:29) with pre-decrement
1669                    R = Self::load_pre_decrement(state, input, Bitvector::<5>::new(28), d);
1670                }
1671
1672                // 1011  reserved
1673                "----_---d_dddd_1011" => {
1674                    panic!("Reserved opcode");
1675                }
1676
1677                // LD Rd, X
1678                "----_---d_dddd_1100" => {
1679                    // load data memory pointed to by X (26:27) into working register
1680                    // register X does not support displacement, it is always 0
1681                    R = Self::load_with_displacement(state, input, Bitvector::<5>::new(26), d, Bitvector::<6>::new(0));
1682                }
1683
1684                // LD Rd, X+
1685                "----_---d_dddd_1101" => {
1686                    // load data memory pointed to by X (26:27) with post-increment
1687                    R = Self::load_post_increment(state, input, Bitvector::<5>::new(26), d);
1688                }
1689
1690                // LD Rd, -X
1691                "----_---d_dddd_1110" => {
1692                    // load data memory pointed to by X (26:27) with pre-decrement
1693                    R = Self::load_pre_decrement(state, input, Bitvector::<5>::new(26), d);
1694                }
1695
1696                // POP Rd
1697                "----_---d_dddd_1111" => {
1698                    // pre-increment stack pointer, then load byte to register d
1699
1700                    // TODO: detect stack underflow/outside data memory
1701
1702                    let old_stack_lo = Ext::<16>::ext(Into::<Unsigned<8>>::into(SPL));
1703                    let old_stack_hi = Ext::<16>::ext(Into::<Unsigned<8>>::into(SPH));
1704                    let old_stack = (old_stack_hi << Unsigned::<16>::new(8)) | old_stack_lo;
1705
1706                    // pre-increment
1707                    let stack = old_stack + Unsigned::<16>::new(1);
1708                    let stack_lo = Into::<Bitvector<8>>::into(Ext::<8>::ext(stack));
1709                    let stack_hi =
1710                        Into::<Bitvector<8>>::into(Ext::<8>::ext(stack >> Unsigned::<16>::new(8)));
1711                    SPL = stack_lo;
1712                    SPH = stack_hi;
1713
1714                    // stack value should be in data memory
1715                    if stack < Unsigned::<16>::new(0x0100) {
1716                        panic!("Pop with overflowed stack");
1717                    };
1718                    let sram_address_full = stack - Unsigned::<16>::new(0x0100);
1719
1720                    let sram_address = Ext::<11>::ext(sram_address_full);
1721
1722                    if Ext::<16>::ext(sram_address) != sram_address_full {
1723                        panic!("Pop underflows stack from data memory");
1724                    };
1725
1726                    // load byte
1727                    R[d] = SRAM[Into::<Bitvector<11>>::into(sram_address)];
1728
1729                    // POP is a two-cycle instruction
1730                }
1731            });
1732
1733            State {
1734                PC,
1735                R,
1736                DDRB,
1737                PORTB,
1738                DDRC,
1739                PORTC,
1740                DDRD,
1741                PORTD,
1742                GPIOR0,
1743                GPIOR1,
1744                GPIOR2,
1745                SPL,
1746                SPH,
1747                SREG,
1748                SRAM,
1749            }
1750        }
1751
1752        fn store_post_increment(
1753            state: &State,
1754            address_lo_index: Bitvector<5>,
1755            value_reg_index: Bitvector<5>,
1756        ) -> State {
1757            let address_hi_index = address_lo_index + Bitvector::<5>::new(1);
1758
1759            if (value_reg_index == address_lo_index) | (value_reg_index == address_hi_index) {
1760                panic!("Illegal store with post-increment to part of address register");
1761            }
1762
1763            let value = state.R[value_reg_index];
1764
1765            let address_lo = Ext::<16>::ext(Into::<Unsigned<8>>::into(state.R[address_lo_index]));
1766            let address_hi = Ext::<16>::ext(Into::<Unsigned<8>>::into(state.R[address_hi_index]));
1767            let address = (address_hi << Unsigned::<16>::new(8)) | address_lo;
1768
1769            // store
1770            let write_state: State =
1771                Self::write_data_mem(state, Into::<Bitvector<16>>::into(address), value);
1772
1773            let PC = write_state.PC;
1774            let mut R = Clone::clone(&write_state.R);
1775            let DDRB = write_state.DDRB;
1776            let PORTB = write_state.PORTB;
1777            let DDRC = write_state.DDRC;
1778            let PORTC = write_state.PORTC;
1779            let DDRD = write_state.DDRD;
1780            let PORTD = write_state.PORTD;
1781            let GPIOR0 = write_state.GPIOR0;
1782            let GPIOR1 = write_state.GPIOR1;
1783            let GPIOR2 = write_state.GPIOR2;
1784            let SPL = write_state.SPL;
1785            let SPH = write_state.SPH;
1786            let SREG = write_state.SREG;
1787            let SRAM = Clone::clone(&write_state.SRAM);
1788
1789            // post-increment
1790            let address_post = address + Unsigned::<16>::new(1);
1791            let address_lo_post = Into::<Bitvector<8>>::into(Ext::<8>::ext(address_post));
1792            let address_hi_post =
1793                Into::<Bitvector<8>>::into(Ext::<8>::ext(address_post >> Unsigned::<16>::new(8)));
1794            R[address_lo_index] = address_lo_post;
1795            R[address_hi_index] = address_hi_post;
1796
1797            State {
1798                PC,
1799                R,
1800                DDRB,
1801                PORTB,
1802                DDRC,
1803                PORTC,
1804                DDRD,
1805                PORTD,
1806                GPIOR0,
1807                GPIOR1,
1808                GPIOR2,
1809                SPL,
1810                SPH,
1811                SREG,
1812                SRAM,
1813            }
1814        }
1815
1816        fn store_pre_decrement(
1817            state: &State,
1818            address_lo_index: Bitvector<5>,
1819            value_reg_index: Bitvector<5>,
1820        ) -> State {
1821            let PC = state.PC;
1822            let mut R = Clone::clone(&state.R);
1823            let DDRB = state.DDRB;
1824            let PORTB = state.PORTB;
1825            let DDRC = state.DDRC;
1826            let PORTC = state.PORTC;
1827            let DDRD = state.DDRD;
1828            let PORTD = state.PORTD;
1829            let GPIOR0 = state.GPIOR0;
1830            let GPIOR1 = state.GPIOR1;
1831            let GPIOR2 = state.GPIOR2;
1832            let SPL = state.SPL;
1833            let SPH = state.SPH;
1834            let SREG = state.SREG;
1835            let SRAM = Clone::clone(&state.SRAM);
1836
1837            let address_hi_index = address_lo_index + Bitvector::<5>::new(1);
1838
1839            if (value_reg_index == address_lo_index) | (value_reg_index == address_hi_index) {
1840                panic!("Illegal store with pre-decrement to part of address register");
1841            }
1842
1843            let value = R[value_reg_index];
1844
1845            let old_address_lo = Ext::<16>::ext(Into::<Unsigned<8>>::into(R[address_lo_index]));
1846            let old_address_hi = Ext::<16>::ext(Into::<Unsigned<8>>::into(R[address_hi_index]));
1847            let old_address = (old_address_hi << Unsigned::<16>::new(8)) | old_address_lo;
1848
1849            // pre-decrement
1850            let address = old_address - Unsigned::<16>::new(1);
1851            let address_lo = Into::<Bitvector<8>>::into(Ext::<8>::ext(address));
1852            let address_hi =
1853                Into::<Bitvector<8>>::into(Ext::<8>::ext(address >> Unsigned::<16>::new(8)));
1854            R[address_lo_index] = address_lo;
1855            R[address_hi_index] = address_hi;
1856
1857            let pre_decrement_state = State {
1858                PC,
1859                R,
1860                DDRB,
1861                PORTB,
1862                DDRC,
1863                PORTC,
1864                DDRD,
1865                PORTD,
1866                GPIOR0,
1867                GPIOR1,
1868                GPIOR2,
1869                SPL,
1870                SPH,
1871                SREG,
1872                SRAM,
1873            };
1874
1875            // store
1876            let write_result: State = Self::write_data_mem(
1877                &pre_decrement_state,
1878                Into::<Bitvector<16>>::into(address),
1879                value,
1880            );
1881            write_result
1882        }
1883
1884        fn next_1001_001r(&self, state: &State, instruction: Bitvector<16>) -> State {
1885            let mut result = Clone::clone(state);
1886
1887            ::machine_check::bitmask_switch!(instruction {
1888
1889                // STS - 2 words
1890                "----_---r_rrrr_0000" => {
1891                    // store direct to data space from register r
1892
1893                    let mut PC = state.PC;
1894                    let R = Clone::clone(&state.R);
1895                    let DDRB = state.DDRB;
1896                    let PORTB = state.PORTB;
1897                    let DDRC = state.DDRC;
1898                    let PORTC = state.PORTC;
1899                    let DDRD = state.DDRD;
1900                    let PORTD = state.PORTD;
1901                    let GPIOR0 = state.GPIOR0;
1902                    let GPIOR1 = state.GPIOR1;
1903                    let GPIOR2 = state.GPIOR2;
1904                    let SPL = state.SPL;
1905                    let SPH = state.SPH;
1906                    let SREG = state.SREG;
1907                    let SRAM = Clone::clone(&state.SRAM);
1908
1909                    let value = R[r];
1910
1911                    // STS is a 2-word instruction, the address is in program memory in the next instruction location
1912                    // PC is already incremented to point to the next instruction, fetch it and increment PC once again before writing
1913                    let address = self.PROGMEM[PC];
1914                    PC = PC + Bitvector::<14>::new(1);
1915
1916                    let pc_incremented_state = State {
1917                        PC,
1918                        R,
1919                        DDRB,
1920                        PORTB,
1921                        DDRC,
1922                        PORTC,
1923                        DDRD,
1924                        PORTD,
1925                        GPIOR0,
1926                        GPIOR1,
1927                        GPIOR2,
1928                        SPL,
1929                        SPH,
1930                        SREG,
1931                        SRAM,
1932                    };
1933
1934                    result = Self::write_data_mem(&pc_incremented_state, Into::<Bitvector<16>>::into(address), value);
1935                }
1936
1937
1938                // ST Z+, Rr
1939                "----_---r_rrrr_0001" => {
1940                    // store to data memory pointed to by Z (30:31) with post-increment
1941                    result = Self::store_post_increment(state, Bitvector::<5>::new(30), r);
1942                }
1943
1944                // ST -Z, Rr
1945                "----_---r_rrrr_0010" => {
1946                    // store to data memory pointed to by Z (30:31) with pre-decrement
1947                    result = Self::store_pre_decrement(state, Bitvector::<5>::new(30), r);
1948                }
1949
1950                // 0011, 01--, 1000 reserved
1951                "----_---r_rrrr_0011" => {
1952                    panic!("Reserved opcode");
1953                }
1954                "----_---r_rrrr_01--" => {
1955                    panic!("Reserved opcode");
1956                }
1957                "----_---r_rrrr_1000" => {
1958                    panic!("Reserved opcode");
1959                }
1960
1961                // ST Y+, Rr
1962                "----_---r_rrrr_1001" => {
1963                    // store to data memory pointed to by Y (28:29) with post-increment
1964                    result = Self::store_post_increment(state, Bitvector::<5>::new(28), r);
1965                }
1966
1967                // ST -Y, Rr
1968                "----_---r_rrrr_1010" => {
1969                    // store to data memory pointed to by Y (28:29) with pre-decrement
1970                    result = Self::store_pre_decrement(state, Bitvector::<5>::new(28), r);
1971                }
1972
1973                // 1011 reserved
1974                "----_---r_rrrr_1011" => {
1975                    panic!("Reserved opcode");
1976                }
1977
1978                // ST X, Rr
1979                "----_---r_rrrr_1100" => {
1980                    // store data memory pointed to by X (26:27)
1981                    // register X does not support displacement, it is always 0
1982                    result = Self::store_with_displacement(state, Bitvector::<5>::new(26), r, Bitvector::<6>::new(0));
1983                }
1984
1985                // ST X+, Rr
1986                "----_---r_rrrr_1101" => {
1987                    // store to data memory pointed to by X (26:27) with post-increment
1988                    result = Self::store_post_increment(state, Bitvector::<5>::new(26), r);
1989                }
1990
1991                // ST -X, Rr
1992                "----_---r_rrrr_1110"  => {
1993                    // store to data memory pointed to by X (26:27) with pre-decrement
1994                    result = Self::store_pre_decrement(state, Bitvector::<5>::new(26), r);
1995                }
1996
1997                // PUSH
1998                "----_---r_rrrr_1111" => {
1999                    // store to data memory pointed to by stack pointer and post-decrement
2000
2001                    // note the instruction set manual uses 'd' for the push register opcode
2002                    // but it is referred to as 'r' everywhere else
2003
2004                    let value = state.R[r];
2005
2006                    let stack_lo = Ext::<16>::ext(Into::<Unsigned<8>>::into(state.SPL));
2007                    let stack_hi = Ext::<16>::ext(Into::<Unsigned<8>>::into(state.SPH));
2008                    let stack = (stack_hi << Unsigned::<16>::new(8)) | stack_lo;
2009                    let stack_post = stack - Unsigned::<16>::new(1);
2010
2011                    // make sure that the stack does not overflow from data memory down to extended I/O
2012                    // pointing to last extended I/O is not an overflow, as the data is not written there
2013                    if (stack < Unsigned::<16>::new(0x0099)) | (stack_post < Unsigned::<16>::new(0x0099)) {
2014                        panic!("Push overflows stack from data memory to extended I/O");
2015                    };
2016
2017                    let stack_sram_address_full = stack - Unsigned::<16>::new(0x0100);
2018
2019                    // only SRAM can be written to
2020                    let stack_sram_address = Ext::<11>::ext(stack_sram_address_full);
2021
2022                    if Ext::<16>::ext(stack_sram_address) != stack_sram_address_full {
2023                        panic!("Stack address higher than data memory on push");
2024                    };
2025
2026                    let PC = state.PC;
2027                    let R = Clone::clone(&state.R);
2028                    let DDRB = state.DDRB;
2029                    let PORTB = state.PORTB;
2030                    let DDRC = state.DDRC;
2031                    let PORTC = state.PORTC;
2032                    let DDRD = state.DDRD;
2033                    let PORTD = state.PORTD;
2034                    let GPIOR0 = state.GPIOR0;
2035                    let GPIOR1 = state.GPIOR1;
2036                    let GPIOR2 = state.GPIOR2;
2037                    let SREG = state.SREG;
2038                    let mut SRAM = Clone::clone(&state.SRAM);
2039
2040                    // write pushed value
2041                    SRAM[Into::<Bitvector<11>>::into(stack_sram_address)] = value;
2042
2043                    // update SPL/SPH to post-decrement
2044                    let SPL = Into::<Bitvector<8>>::into(Ext::<8>::ext(stack_post));
2045                    let SPH = Into::<Bitvector<8>>::into(Ext::<8>::ext(stack_post >> Unsigned::<16>::new(8)));
2046
2047                    result = State {
2048                        PC,
2049                        R,
2050                        DDRB,
2051                        PORTB,
2052                        DDRC,
2053                        PORTC,
2054                        DDRD,
2055                        PORTD,
2056                        GPIOR0,
2057                        GPIOR1,
2058                        GPIOR2,
2059                        SPL,
2060                        SPH,
2061                        SREG,
2062                        SRAM,
2063                    };
2064                    // PUSH is a two-cycle instruction
2065                }
2066            });
2067
2068            result
2069        }
2070
2071        fn next_1001_010x(&self, state: &State, instruction: Bitvector<16>) -> State {
2072            let mut PC = state.PC;
2073            let mut R = Clone::clone(&state.R);
2074            let DDRB = state.DDRB;
2075            let PORTB = state.PORTB;
2076            let DDRC = state.DDRC;
2077            let PORTC = state.PORTC;
2078            let DDRD = state.DDRD;
2079            let PORTD = state.PORTD;
2080            let GPIOR0 = state.GPIOR0;
2081            let GPIOR1 = state.GPIOR1;
2082            let GPIOR2 = state.GPIOR2;
2083            let mut SPL = state.SPL;
2084            let mut SPH = state.SPH;
2085            let mut SREG = state.SREG;
2086            let mut SRAM = Clone::clone(&state.SRAM);
2087
2088            ::machine_check::bitmask_switch!(instruction {
2089                // COM Rd
2090                "----_---d_dddd_0000" => {
2091                    // one's complement
2092                    R[d] = Bitvector::<8>::new(0xFF) - R[d];
2093                    SREG = Self::compute_status_com(SREG, R[d]);
2094                }
2095
2096                // NEG Rd
2097                "----_---d_dddd_0001" => {
2098                    // two's complement
2099                    let prev = R[d];
2100                    R[d] = Bitvector::<8>::new(0x00) - R[d];
2101                    SREG = Self::compute_status_neg(SREG, prev, R[d]);
2102                }
2103
2104                // SWAP Rd
2105                "----_---d_dddd_0010" => {
2106
2107                    let prev_unsigned = Into::<Unsigned<8>>::into(R[d]);
2108                    // swap nibbles in register, status flags not affected
2109                    let prev_lo_half = prev_unsigned & Unsigned::<8>::new(0x0F);
2110                    let prev_hi_half = prev_unsigned & Unsigned::<8>::new(0xF0);
2111                    let current_lo_half = prev_hi_half >> Unsigned::<8>::new(4);
2112                    let current_hi_half = prev_lo_half << Unsigned::<8>::new(4);
2113                    R[d] = Into::<Bitvector<8>>::into(current_hi_half | current_lo_half);
2114                }
2115
2116                // INC Rd
2117                "----_---d_dddd_0011" => {
2118
2119                    // increment
2120                    R[d] = R[d] + Bitvector::<8>::new(1);
2121
2122                    // the V flag is set exactly when R[d] after increment is 0x80
2123                    let mut flag_V = Bitvector::<1>::new(0);
2124                    if R[d] == Bitvector::<8>::new(0x7F) {
2125                        flag_V = Bitvector::<1>::new(1);
2126                    }
2127
2128                    SREG = Self::compute_status_inc_dec(SREG, R[d], flag_V);
2129                }
2130
2131                // 0100 is reserved
2132                "----_---d_dddd_0100" => {
2133                    panic!("Reserved opcode");
2134                }
2135
2136                // ASR Rd
2137                "----_---d_dddd_0101" => {
2138                    // arithmetic shift right
2139                    // treat as signed and shift one place right
2140                    let prev = R[d];
2141                    let prev_signed = Into::<Signed<8>>::into(prev);
2142                    let shifted_signed = prev_signed >> Into::<Signed<8>>::into(Bitvector::<8>::new(1));
2143                    R[d] = Into::<Bitvector<8>>::into(shifted_signed);
2144                    SREG = Self::compute_status_right_shift(SREG, prev, R[d]);
2145                }
2146
2147                // LSR Rd
2148                "----_---d_dddd_0110" => {
2149                    // logical shift right
2150                    // treat as unsigned and shift one place right
2151                    let prev = R[d];
2152                    let prev_unsigned = Into::<Unsigned<8>>::into(prev);
2153                    let shifted_unsigned = prev_unsigned >> Unsigned::<8>::new(1);
2154                    R[d] = Into::<Bitvector<8>>::into(shifted_unsigned);
2155                    SREG = Self::compute_status_right_shift(SREG, prev, R[d]);
2156                }
2157
2158                // ROR Rd
2159                "----_---d_dddd_0111" => {
2160                    // logical shift right
2161                    // first, treat as unsigned and shift one place right
2162                    let prev = R[d];
2163                    let prev_unsigned = Into::<Unsigned<8>>::into(prev);
2164                    let shifted_unsigned = prev_unsigned >> Unsigned::<8>::new(1);
2165                    R[d] = Into::<Bitvector<8>>::into(shifted_unsigned);
2166
2167                    // emplace the carry bit into the highest bit of new Rd
2168                    // the carry bit is in bit 0 of SREG, so mask it and shift up to bit 7
2169                    let SREG_masked_carry = SREG & Bitvector::<8>::new(0b0000_0000);
2170                    R[d] = R[d] | (SREG_masked_carry << Bitvector::<8>::new(7));
2171
2172                    // compute status like normal, the shifted-out bit will be rotated to carry
2173                    SREG = Self::compute_status_right_shift(SREG, prev, R[d]);
2174                }
2175
2176                // - opcodes only in 1011_0101 -
2177
2178                // BSET s
2179                "----_---0_0sss_1000" => {
2180                    // bit set in status register
2181                    let amount = Ext::<8>::ext(Into::<Unsigned<3>>::into(s));
2182                    SREG = SREG | Into::<Bitvector<8>>::into(Unsigned::<8>::new(1) << amount);
2183                }
2184
2185                // BCLR s
2186                "----_---0_1sss_1000" => {
2187                    // bit clear in status register
2188                    let amount = Ext::<8>::ext(Into::<Unsigned<3>>::into(s));
2189                    SREG = SREG & !(Into::<Bitvector<8>>::into(Unsigned::<8>::new(1) << amount));
2190                }
2191
2192                // IJMP
2193                "----_---0_0000_1001" => {
2194                    unimplemented!("IJMP instruction");
2195                }
2196
2197                // EIJMP
2198                "----_---0_0001_1001" => {
2199                    unimplemented!("EIJMP instruction");
2200                }
2201
2202                // other 1001_0100_----_1001 reserved
2203                "----_---0_001-_1001" => {
2204                    panic!("Reserved opcode");
2205                }
2206                "----_---0_01--_1001" => {
2207                    panic!("Reserved opcode");
2208                }
2209                "----_---0_1---_1001" => {
2210                    panic!("Reserved opcode");
2211                }
2212
2213                // DEC Rd
2214                "----_---d_dddd_1010" => {
2215
2216                    // decrement
2217                    R[d] = R[d] - Bitvector::<8>::new(1);
2218
2219                    // the V flag is set exactly when R[d] after decrement is 0x7F
2220                    let mut flag_V = Bitvector::<1>::new(0);
2221                    if R[d] == Bitvector::<8>::new(0x7F) {
2222                        flag_V = Bitvector::<1>::new(1);
2223                    }
2224
2225
2226                    SREG = Self::compute_status_inc_dec(SREG, R[d], flag_V);
2227
2228                }
2229
2230                // DES on ATxmega, reserved for non-ATxmega
2231                "----_---0_----_1011" => {
2232                    panic!("Reserved opcode (DES on ATxmega)");
2233                }
2234
2235                // JMP - 2 words
2236                "----_---k_kkkk_110k" => {
2237                    // PC is 14-bit on ATmega328p, the higher bits should be zero
2238                    if k != Bitvector::<6>::new(0) {
2239                        panic!("Jump outside program memory due to high word bits");
2240                    }
2241
2242                    let low_word = Into::<Unsigned<16>>::into(self.PROGMEM[PC]);
2243                    let target_pc = Ext::<14>::ext(low_word);
2244                    if Ext::<16>::ext(target_pc) != low_word {
2245                        panic!("Jump outside program memory due to low word bits");
2246                    }
2247
2248                    PC = Into::<Bitvector<14>>::into(target_pc);
2249
2250                    // JMP is a three-cycle instruction
2251                }
2252
2253                // CALL - 2 words
2254                "----_---k_kkkk_111k" => {
2255                    // call subroutine
2256                    // save 2-byte return address to stack and post-decrement SP
2257
2258                    // PC is 14-bit on ATmega328p, the higher bits should be zero
2259                    if k != Bitvector::<6>::new(0) {
2260                        panic!("Call outside program memory due to high word bits");
2261                    }
2262
2263                    let low_word = Into::<Unsigned<16>>::into(self.PROGMEM[PC]);
2264                    let target_pc = Ext::<14>::ext(low_word);
2265                    if Ext::<16>::ext(target_pc) != low_word {
2266                        panic!("Call outside program memory due to low word bits");
2267                    }
2268
2269                    let stack_lo = Ext::<16>::ext(Into::<Unsigned<8>>::into(SPL));
2270                    let stack_hi = Ext::<16>::ext(Into::<Unsigned<8>>::into(SPH));
2271                    let stack = (stack_hi << Unsigned::<16>::new(8)) | stack_lo;
2272
2273                    // the stack is decremented by 2 at the end
2274                    let stack_post = stack - Unsigned::<16>::new(2);
2275
2276                    // make sure that the stack does not overflow from data memory down to extended I/O
2277                    // pointing to last extended I/O is not an overflow, as the data is not written there
2278                    if (stack < Unsigned::<16>::new(0x0099)) | (stack_post < Unsigned::<16>::new(0x0099)) {
2279                        panic!("Call overflows stack from data memory to extended I/O");
2280                    };
2281
2282                    let stack_sram_address_full = stack - Unsigned::<16>::new(0x0100);
2283
2284                    // only SRAM can be written to
2285                    let stack_sram_address = Ext::<11>::ext(stack_sram_address_full);
2286                    let stack_sram_address_minus_1 = stack_sram_address - Unsigned::<11>::new(1);
2287
2288                    if Ext::<16>::ext(stack_sram_address) != stack_sram_address_full {
2289                        panic!("Stack address higher than data memory on call");
2290                    };
2291
2292                    // the address after the 2-byte call instruction is loaded
2293                    // PC was already incremented once, increment a second time to get the return address
2294                    let pc_unsigned = Into::<Unsigned<14>>::into(PC);
2295                    let return_address_unsigned = pc_unsigned + Unsigned::<14>::new(1);
2296                    let return_address_lo = Into::<Bitvector<8>>::into(Ext::<8>::ext(return_address_unsigned));
2297                    let return_address_hi = Into::<Bitvector<8>>::into(Ext::<8>::ext(return_address_unsigned >> Unsigned::<14>::new(8)));
2298
2299                    SRAM[Into::<Bitvector<11>>::into(stack_sram_address)] = return_address_lo;
2300                    SRAM[Into::<Bitvector<11>>::into(stack_sram_address_minus_1)] = return_address_hi;
2301
2302                    // update PC
2303                    PC = Into::<Bitvector<14>>::into(target_pc);
2304
2305                    // update SPL/SPH
2306                    SPL = Into::<Bitvector<8>>::into(Ext::<8>::ext(stack_post));
2307                    SPH = Into::<Bitvector<8>>::into(Ext::<8>::ext(stack_post >> Unsigned::<16>::new(8)));
2308
2309                    // CALL is a four-cycle instruction on 16-bit PC devices
2310                }
2311
2312                // -  opcodes only in 1011_0110 -
2313
2314                // RET
2315                "----_---1_0000_1000" => {
2316                    // return from subroutine
2317                    // pre-increment SP and load 2-byte PC value from stack
2318
2319                    let old_stack_lo = Ext::<16>::ext(Into::<Unsigned<8>>::into(SPL));
2320                    let old_stack_hi = Ext::<16>::ext(Into::<Unsigned<8>>::into(SPH));
2321                    let old_stack = (old_stack_hi << Unsigned::<16>::new(8)) | old_stack_lo;
2322                    let address_pc_hi = old_stack + Unsigned::<16>::new(1);
2323                    let address_pc_lo = address_pc_hi + Unsigned::<16>::new(1);
2324
2325                    let new_stack = address_pc_lo;
2326
2327                    // update SPL/SPH
2328                    SPL = Into::<Bitvector<8>>::into(Ext::<8>::ext(new_stack));
2329                    SPH = Into::<Bitvector<8>>::into(Ext::<8>::ext(new_stack >> Unsigned::<16>::new(8)));
2330
2331                    // stack should be in data memory
2332                    if address_pc_hi < Unsigned::<16>::new(0x0100) {
2333                        panic!("Return with overflowed stack");
2334                    };
2335                    let sram_address_pc_hi_full = address_pc_hi - Unsigned::<16>::new(0x0100);
2336                    let sram_address_pc_lo_full = address_pc_lo - Unsigned::<16>::new(0x0100);
2337
2338                    let sram_address_pc_hi = Ext::<11>::ext(sram_address_pc_hi_full);
2339                    let sram_address_pc_lo = Ext::<11>::ext(sram_address_pc_lo_full);
2340
2341                    if (Ext::<16>::ext(sram_address_pc_hi) != sram_address_pc_hi_full)
2342                    | (Ext::<16>::ext(sram_address_pc_lo) != sram_address_pc_lo_full) {
2343                        panic!("Return underflows stack from data memory");
2344                    };
2345
2346                    let pc_lo = SRAM[Into::<Bitvector<11>>::into(sram_address_pc_lo)];
2347                    let pc_hi = SRAM[Into::<Bitvector<11>>::into(sram_address_pc_hi)];
2348
2349                    let pc_lo_ext = Ext::<16>::ext(Into::<Unsigned<8>>::into(pc_lo));
2350                    let pc_hi_ext = Ext::<16>::ext(Into::<Unsigned<8>>::into(pc_hi));
2351                    let new_pc_full = (pc_hi_ext << Unsigned::<16>::new(8)) | pc_lo_ext;
2352
2353                    let new_pc = Ext::<14>::ext(new_pc_full);
2354                    if Ext::<16>::ext(new_pc) != new_pc_full {
2355                        panic!("Return address does not fit into program counter");
2356                    }
2357
2358                    PC = Into::<Bitvector<14>>::into(new_pc);
2359
2360                    // RET is a four-cycle instruction on 16-bit PC devices
2361                }
2362
2363                // RETI
2364                "----_---1_0001_1000" => {
2365                    unimplemented!("RETI instruction");
2366                }
2367
2368                // next 6 reserved
2369
2370                "----_---1_001-_1000" => {
2371                    panic!("Reserved opcode");
2372                }
2373
2374                "----_---1_01--_1000" => {
2375                    panic!("Reserved opcode");
2376                }
2377
2378                // SLEEP
2379                "----_---1_1000_1000" => {
2380                    unimplemented!("SLEEP instruction");
2381                }
2382
2383                // BREAK
2384                "----_---1_1001_1000" => {
2385                    // break the execution when debugging
2386                    unimplemented!("BREAK instruction");
2387                }
2388
2389                // WDR
2390                "----_---1_1010_1000" => {
2391                    unimplemented!("WDR instruction");
2392                }
2393
2394                // next one reserved
2395                "----_---1_1011_1000" => {
2396                    unimplemented!("WDR instruction");
2397                }
2398
2399                // LPM (implied R0 destination)
2400                "----_---1_1100_1000" => {
2401                    unimplemented!("LPM instruction");
2402                    /*
2403                    // load program memory
2404
2405                    //R[0] = fetchProgramByte(Z);
2406                    unimplemented();
2407
2408                    // LPM is a three-cycle instruction
2409                    increment_cycle_count();
2410                    increment_cycle_count();
2411                    */
2412                }
2413
2414                // ELPM
2415                "----_---1_1101_1000" => {
2416                    unimplemented!("ELPM instruction");
2417                    /*
2418                    //R[0] = PROGRAM[RAMPZ:Z];
2419                    */
2420                }
2421
2422                // SPM
2423                "----_---1_1110_1000" => {
2424                    unimplemented!("SPM instruction");
2425                }
2426
2427                // next one reserved (SPM on ATxmega)
2428
2429                "----_---1_1111_1000" => {
2430                    unimplemented!("Reserved opcode (SPM on ATxmega)");
2431                }
2432
2433                // ICALL
2434                "----_---1_0000_1001" => {
2435                    unimplemented!("ICALL instruction");
2436                }
2437
2438                // EICALL
2439                "----_---1_0001_1001" => {
2440                    unimplemented!("EICALL instruction");
2441                }
2442
2443                // other 1001_010-_----_1001 reserved
2444                "----_---1_001-_1001" => {
2445                    panic!("Reserved opcode");
2446                }
2447                "----_---1_01--_1001" => {
2448                    panic!("Reserved opcode");
2449                }
2450                "----_---1_1---_1001" => {
2451                    panic!("Reserved opcode");
2452                }
2453                "----_---1_----_1011" => {
2454                    panic!("Reserved opcode");
2455                }
2456
2457            });
2458
2459            State {
2460                PC,
2461                R,
2462                DDRB,
2463                PORTB,
2464                DDRC,
2465                PORTC,
2466                DDRD,
2467                PORTD,
2468                GPIOR0,
2469                GPIOR1,
2470                GPIOR2,
2471                SPL,
2472                SPH,
2473                SREG,
2474                SRAM,
2475            }
2476        }
2477
2478        fn next_1001_011x(state: &State, instruction: Bitvector<16>) -> State {
2479            let PC = state.PC;
2480            let mut R = Clone::clone(&state.R);
2481            let DDRB = state.DDRB;
2482            let PORTB = state.PORTB;
2483            let DDRC = state.DDRC;
2484            let PORTC = state.PORTC;
2485            let DDRD = state.DDRD;
2486            let PORTD = state.PORTD;
2487            let GPIOR0 = state.GPIOR0;
2488            let GPIOR1 = state.GPIOR1;
2489            let GPIOR2 = state.GPIOR2;
2490            let SPL = state.SPL;
2491            let SPH = state.SPH;
2492            let mut SREG = state.SREG;
2493            let SRAM = Clone::clone(&state.SRAM);
2494
2495            ::machine_check::bitmask_switch!(instruction {
2496                // ADIW Rd, K
2497                "----_---0_kkdd_kkkk" => {
2498
2499                    // add immediate to register word
2500                    // only available for register pairs r24:r25, r26:r27, r28:29, r30:r31
2501                    // extend d to five bits, double it, and add 24 to get low register index
2502                    let d_unsigned = Into::<Unsigned<2>>::into(d);
2503                    let d_ext = Into::<Bitvector<5>>::into(Ext::<5>::ext(d_unsigned));
2504                    let double_d_ext = d_ext + d_ext;
2505                    let lo_reg_num = double_d_ext + Bitvector::<5>::new(24);
2506                    let hi_reg_num = lo_reg_num + Bitvector::<5>::new(1);
2507
2508                    // construct the little-endian pair (low index corresponds to low bits)
2509                    let lo_reg_unsigned = Into::<Unsigned<8>>::into(R[lo_reg_num]);
2510                    let hi_reg_unsigned = Into::<Unsigned<8>>::into(R[hi_reg_num]);
2511
2512                    let lo_reg_ext = Ext::<16>::ext(lo_reg_unsigned);
2513                    let hi_reg_ext = Ext::<16>::ext(hi_reg_unsigned);
2514                    let pair = (hi_reg_ext << Unsigned::<16>::new(8)) | lo_reg_ext;
2515
2516                    let k_unsigned = Into::<Unsigned<6>>::into(k);
2517                    let result_pair = pair + Ext::<16>::ext(k_unsigned);
2518
2519                    let result_lo = Ext::<8>::ext(result_pair);
2520                    let result_hi = Ext::<8>::ext(result_pair >> Unsigned::<16>::new(8));
2521
2522                    R[lo_reg_num] = Into::<Bitvector<8>>::into(result_lo);
2523                    R[hi_reg_num] = Into::<Bitvector<8>>::into(result_hi);
2524
2525
2526
2527                    SREG = Self::compute_status_adiw(SREG, Into::<Bitvector<16>>::into(pair), Into::<Bitvector<16>>::into(result_pair));
2528
2529                    // ADIW is a two-cycle instruction
2530
2531                }
2532
2533                // SBIW Rd, K
2534                "----_---1_kkdd_kkkk" => {
2535                    // subtract immediate from register word
2536                    // only available for register pairs r24:r25, r26:r27, r28:29, r30:r31
2537                    // extend d to five bits, double it, and add 24 to get low register index
2538                    let d_unsigned = Into::<Unsigned<2>>::into(d);
2539                    let d_ext = Into::<Bitvector<5>>::into(Ext::<5>::ext(d_unsigned));
2540                    let double_d_ext = d_ext + d_ext;
2541                    let lo_reg_num = double_d_ext + Bitvector::<5>::new(24);
2542                    let hi_reg_num = lo_reg_num + Bitvector::<5>::new(1);
2543
2544                    // construct the little-endian pair (low index corresponds to low bits)
2545                    let lo_reg_unsigned = Into::<Unsigned<8>>::into(R[lo_reg_num]);
2546                    let hi_reg_unsigned = Into::<Unsigned<8>>::into(R[hi_reg_num]);
2547
2548                    let lo_reg_ext = Ext::<16>::ext(lo_reg_unsigned);
2549                    let hi_reg_ext = Ext::<16>::ext(hi_reg_unsigned);
2550                    let pair = (hi_reg_ext << Unsigned::<16>::new(8)) | lo_reg_ext;
2551
2552                    let k_unsigned = Into::<Unsigned<6>>::into(k);
2553                    let result_pair = pair - Ext::<16>::ext(k_unsigned);
2554
2555
2556                    let result_lo = Ext::<8>::ext(result_pair);
2557                    let result_hi = Ext::<8>::ext(result_pair >> Unsigned::<16>::new(8));
2558
2559                    R[lo_reg_num] = Into::<Bitvector<8>>::into(result_lo);
2560                    R[hi_reg_num] = Into::<Bitvector<8>>::into(result_hi);
2561
2562                    SREG = Self::compute_status_sbiw(SREG, Into::<Bitvector<16>>::into(pair), Into::<Bitvector<16>>::into(result_pair));
2563
2564                    // SBIW is a two-cycle instruction
2565                }
2566            });
2567
2568            State {
2569                PC,
2570                R,
2571                DDRB,
2572                PORTB,
2573                DDRC,
2574                PORTC,
2575                DDRD,
2576                PORTD,
2577                GPIOR0,
2578                GPIOR1,
2579                GPIOR2,
2580                SPL,
2581                SPH,
2582                SREG,
2583                SRAM,
2584            }
2585        }
2586
2587        fn next_1001(&self, state: &State, input: &Input, instruction: Bitvector<16>) -> State {
2588            let mut result = Clone::clone(state);
2589
2590            ::machine_check::bitmask_switch!(instruction {
2591                "----_000-_----_----" => {
2592                    result = Self::next_1001_000d(self, state, input, instruction);
2593                }
2594                "----_001-_----_----" => {
2595                    result = Self::next_1001_001r(self, state, instruction);
2596                }
2597                "----_010-_----_----" => {
2598                    result = Self::next_1001_010x(self, state, instruction);
2599                }
2600                "----_011-_----_----" => {
2601                    result = Self::next_1001_011x(state, instruction);
2602                }
2603
2604                // v=0: CBI A, b
2605                // v=1: SBI A, b
2606                "----_10v0_aaaa_abbb" => {
2607                    // clear/set bit in I/O register, status flags not affected
2608
2609                    // we can do this by read-modify-write
2610                    // on all implemented I/O registers except for PINx, resolve these differently
2611
2612                    let b_shift = Into::<Bitvector<8>>::into(Ext::<8>::ext(Into::<Unsigned<3>>::into(b)));
2613                    let b_mask = Bitvector::<8>::new(1) << b_shift;
2614                    let b_value = Into::<Bitvector<8>>::into(Ext::<8>::ext(Into::<Unsigned<1>>::into(v))) << b_shift;
2615
2616                    // PINx can be set with all other bits being 0, so they do not flip
2617                    let mut retained_bits = Bitvector::<8>::new(0);
2618
2619                    // only lower 32 registers are supported by SBI/CBI, zero-extend
2620                    let ext_a = Into::<Bitvector<6>>::into(Ext::<6>::ext(Into::<Unsigned<5>>::into(a)));
2621
2622                    // get the retained bits for all others
2623                    if (a != Bitvector::<5>::new(0x3)) & (a != Bitvector::<5>::new(0x6)) & (a == Bitvector::<5>::new(0x9)) {
2624                        let read_bits: Bitvector<8> = Self::read_io_reg(state, input, ext_a);
2625                        retained_bits = read_bits & !b_mask;
2626                    }
2627                    // write the bits
2628                    let write_bits = retained_bits | b_value;
2629                    result = Self::write_io_reg(state, ext_a, write_bits);
2630                    // CBI / SBI is a two-cycle instruction
2631                }
2632
2633                // v=0: SBIC A, b
2634                // v=1: SBIS A, b
2635                "----_10v1_aaaa_abbb" => {
2636                    // skip if bit in I/O register is cleared/set
2637
2638                    // read I/O register value and determine if we should skip
2639
2640                    let b_shift = Into::<Bitvector<8>>::into(Ext::<8>::ext(Into::<Unsigned<3>>::into(b)));
2641                    let b_mask = Bitvector::<8>::new(1) << b_shift;
2642                    let b_value = Into::<Bitvector<8>>::into(Ext::<8>::ext(Into::<Unsigned<1>>::into(v))) << b_shift;
2643
2644                    // only lower 32 registers are supported by SBIS/SBIC, zero-extend
2645                    let ext_a = Into::<Bitvector<6>>::into(Ext::<6>::ext(Into::<Unsigned<5>>::into(a)));
2646
2647                    // read bits
2648                    let read_bits: Bitvector<8> = Self::read_io_reg(state, input, ext_a);
2649
2650                    let R = Clone::clone(&result.R);
2651                    let mut PC = state.PC;
2652                    let DDRB = state.DDRB;
2653                    let PORTB = state.PORTB;
2654                    let DDRC = state.DDRC;
2655                    let PORTC = state.PORTC;
2656                    let DDRD = state.DDRD;
2657                    let PORTD = state.PORTD;
2658                    let GPIOR0 = state.GPIOR0;
2659                    let GPIOR1 = state.GPIOR1;
2660                    let GPIOR2 = state.GPIOR2;
2661                    let SPL = state.SPL;
2662                    let SPH = state.SPH;
2663                    let SREG = state.SREG;
2664                    let SRAM = Clone::clone(&result.SRAM);
2665
2666                    // determine if we should skip
2667                    if (read_bits & b_mask) == b_value {
2668                        // skip next instruction
2669                        PC = Self::instruction_skip(self, PC);
2670                    }
2671
2672                    result =
2673                    State {
2674                        PC,
2675                        R,
2676                        DDRB,
2677                        PORTB,
2678                        DDRC,
2679                        PORTC,
2680                        DDRD,
2681                        PORTD,
2682                        GPIOR0,
2683                        GPIOR1,
2684                        GPIOR2,
2685                        SPL,
2686                        SPH,
2687                        SREG,
2688                        SRAM,
2689                    };
2690                }
2691
2692                // MUL
2693                "----_11rd_dddd_rrrr" => {
2694                    // multiply unsigned by unsigned
2695                    let d_ext = Into::<Bitvector<16>>::into(Ext::<16>::ext(Into::<Unsigned<8>>::into(state.R[d])));
2696                    let r_ext = Into::<Bitvector<16>>::into(Ext::<16>::ext(Into::<Unsigned<8>>::into(state.R[r])));
2697
2698                    let mul_result = d_ext * r_ext;
2699                    let mul_result_lo = Into::<Bitvector<8>>::into(Ext::<8>::ext(Into::<Unsigned<16>>::into(mul_result)));
2700                    let mul_result_hi = Into::<Bitvector<8>>::into(Ext::<8>::ext(Into::<Unsigned<16>>::into(mul_result) >> Unsigned::<16>::new(8)));
2701
2702                    let mut R = Clone::clone(&result.R);
2703                    let PC = state.PC;
2704                    let DDRB = state.DDRB;
2705                    let PORTB = state.PORTB;
2706                    let DDRC = state.DDRC;
2707                    let PORTC = state.PORTC;
2708                    let DDRD = state.DDRD;
2709                    let PORTD = state.PORTD;
2710                    let GPIOR0 = state.GPIOR0;
2711                    let GPIOR1 = state.GPIOR1;
2712                    let GPIOR2 = state.GPIOR2;
2713                    let SPL = state.SPL;
2714                    let SPH = state.SPH;
2715                    let SRAM = Clone::clone(&result.SRAM);
2716
2717                    // store result low byte into register 0 and high byte into register 1
2718                    R[Bitvector::<5>::new(0)] = mul_result_lo;
2719                    R[Bitvector::<5>::new(1)] = mul_result_hi;
2720
2721                    // update status register
2722                    let SREG: Bitvector<8> = Self::compute_status_mul(state.SREG, mul_result, mul_result);
2723
2724                    result =
2725                    State {
2726                        PC,
2727                        R,
2728                        DDRB,
2729                        PORTB,
2730                        DDRC,
2731                        PORTC,
2732                        DDRD,
2733                        PORTD,
2734                        GPIOR0,
2735                        GPIOR1,
2736                        GPIOR2,
2737                        SPL,
2738                        SPH,
2739                        SREG,
2740                        SRAM,
2741                    };
2742                }
2743            });
2744
2745            result
2746        }
2747
2748        fn next_1011(state: &State, input: &Input, instruction: Bitvector<16>) -> State {
2749            let mut result = Clone::clone(state);
2750
2751            ::machine_check::bitmask_switch!(instruction {
2752                // IN
2753                "----_0aad_dddd_aaaa" => {
2754                    // load I/O location to register, status flags not affected
2755                    let PC = state.PC;
2756                    let mut R = Clone::clone(&state.R);
2757                    let DDRB = state.DDRB;
2758                    let PORTB = state.PORTB;
2759                    let DDRC = state.DDRC;
2760                    let PORTC = state.PORTC;
2761                    let DDRD = state.DDRD;
2762                    let PORTD = state.PORTD;
2763                    let GPIOR0 = state.GPIOR0;
2764                    let GPIOR1 = state.GPIOR1;
2765                    let GPIOR2 = state.GPIOR2;
2766                    let SPL = state.SPL;
2767                    let SPH = state.SPH;
2768                    let SREG = state.SREG;
2769                    let SRAM = Clone::clone(&state.SRAM);
2770
2771                    let io_result: Bitvector<8> = Self::read_io_reg(state, input, a);
2772                    R[d] = io_result;
2773
2774                    result = State {
2775                        PC,
2776                        R,
2777                        DDRB,
2778                        PORTB,
2779                        DDRC,
2780                        PORTC,
2781                        DDRD,
2782                        PORTD,
2783                        GPIOR0,
2784                        GPIOR1,
2785                        GPIOR2,
2786                        SPL,
2787                        SPH,
2788                        SREG,
2789                        SRAM,
2790                    };
2791                }
2792
2793                // OUT
2794                "----_1aar_rrrr_aaaa" => {
2795                    // store register to I/O location, status flags not affected
2796                    result = Self::write_io_reg(state, a, state.R[r]);
2797                }
2798            });
2799
2800            result
2801        }
2802
2803        fn next_11(&self, state: &State, instruction: Bitvector<16>) -> State {
2804            let mut PC = state.PC;
2805            let mut R = Clone::clone(&state.R);
2806            let DDRB = state.DDRB;
2807            let PORTB = state.PORTB;
2808            let DDRC = state.DDRC;
2809            let PORTC = state.PORTC;
2810            let DDRD = state.DDRD;
2811            let PORTD = state.PORTD;
2812            let GPIOR0 = state.GPIOR0;
2813            let GPIOR1 = state.GPIOR1;
2814            let GPIOR2 = state.GPIOR2;
2815            let SPL = state.SPL;
2816            let SPH = state.SPH;
2817            let mut SREG = state.SREG;
2818            let SRAM = Clone::clone(&state.SRAM);
2819
2820            ::machine_check::bitmask_switch!(instruction {
2821
2822                // RJMP
2823                "--00_kkkk_kkkk_kkkk" => {
2824
2825                    // relative jump
2826                    // we have already added 1 before case, just add adjusted k
2827                    // it is represented in 12-bit two's complement, we need to sign-extend to 14 bits
2828                    let k_signed = Into::<Signed<12>>::into(k);
2829                    let k_signed_ext = Ext::<14>::ext(k_signed);
2830                    let k_ext = Into::<Bitvector<14>>::into(k_signed_ext);
2831                    // jump
2832                    PC = PC + k_ext;
2833
2834                    // RJMP is a two-cycle instruction
2835                }
2836
2837                // --- 1101 ---
2838
2839                // RCALL
2840                "--01_kkkk_kkkk_kkkk" => {
2841                    unimplemented!("RCALL instruction");
2842                }
2843
2844                // --- 1110 ---
2845                // LDI
2846                "--10_kkkk_dddd_kkkk" => {
2847                    // extend d to five bits and add 16
2848                    let d_unsigned = Into::<Unsigned<4>>::into(d);
2849                    let d_ext_unsigned = Ext::<5>::ext(d_unsigned);
2850                    let d_ext = Into::<Bitvector<5>>::into(d_ext_unsigned);
2851                    let reg_num = d_ext + Bitvector::<5>::new(16);
2852
2853                    // load immediate, status flags not affected
2854                    R[reg_num] = k;
2855                }
2856
2857                // --- 1111 ---
2858
2859                // BRBS
2860                "--11_00kk_kkkk_ksss" => {
2861                    let s_unsigned = Into::<Unsigned<3>>::into(s);
2862                    let s_unsigned_ext =  Ext::<8>::ext(s_unsigned);
2863                    let unsigned_bit_mask = Unsigned::<8>::new(1) << s_unsigned_ext;
2864                    let bit_mask = Into::<Bitvector<8>>::into(unsigned_bit_mask);
2865
2866                    // branch if bit in SREG is set
2867                    // we have already added 1 to PC before case
2868                    if SREG & bit_mask == bit_mask {
2869                        // it is set, branch
2870                        // represent k as signed and sign-extend
2871
2872                        let k_signed = Into::<Signed<7>>::into(k);
2873                        let k_signed_ext = Ext::<14>::ext(k_signed);
2874                        let k_ext = Into::<Bitvector<14>>::into(k_signed_ext);
2875                        // jump
2876                        PC = PC + k_ext;
2877                        // since we branched, one more cycle is taken by this instruction
2878                    } else {
2879                        // it is cleared, do nothing
2880                    };
2881                }
2882
2883                // BRBC
2884                "--11_01kk_kkkk_ksss" => {
2885                    let s_unsigned = Into::<Unsigned<3>>::into(s);
2886                    let s_unsigned_ext =  Ext::<8>::ext(s_unsigned);
2887                    let unsigned_bit_mask = Unsigned::<8>::new(1) << s_unsigned_ext;
2888                    let bit_mask = Into::<Bitvector<8>>::into(unsigned_bit_mask);
2889
2890                    // branch if bit in SREG is cleared
2891                    // we have already added 1 to PC before case
2892                    if SREG & bit_mask == bit_mask {
2893                        // it is set, do nothing
2894                    } else {
2895                        // it is cleared, branch
2896                        // represent k as signed and sign-extend
2897
2898                        let k_signed = Into::<Signed<7>>::into(k);
2899                        let k_signed_ext = Ext::<14>::ext(k_signed);
2900                        let k_ext = Into::<Bitvector<14>>::into(k_signed_ext);
2901                        // jump
2902                        PC = PC + k_ext;
2903                        // since we branched, one more cycle is taken by this instruction
2904                    };
2905                }
2906
2907                // BLD
2908                "--11_100d_dddd_0bbb" => {
2909                    // copy from flag T (bit 6) of SREG to bit b of register Rd
2910
2911                    let SREG_unsigned = Into::<Unsigned<8>>::into(SREG);
2912                    let SREG_masked = SREG_unsigned & Unsigned::<8>::new(0b0100_0000);
2913                    let lowest_bit_T = SREG_masked >> Unsigned::<8>::new(6);
2914
2915                    let amount = Ext::<8>::ext(Into::<Unsigned<3>>::into(b));
2916                    let bit_only_mask = Into::<Bitvector<8>>::into(Unsigned::<8>::new(1) << amount);
2917                    let bit_only_T = Into::<Bitvector<8>>::into(lowest_bit_T << amount);
2918
2919                    R[d] = (R[d] & !bit_only_mask) | bit_only_T;
2920                }
2921
2922                // 1xxx part reserved
2923                "--11_100-_----_1---" => {
2924                    panic!("Reserved opcode");
2925                }
2926
2927                // BST
2928                "--11_101d_dddd_0bbb" => {
2929                    // store bit b from register Rd to flag T (bit 6) of SREG
2930                    let amount = Ext::<8>::ext(Into::<Unsigned<3>>::into(b));
2931                    let Rd_unsigned = Into::<Unsigned<8>>::into(R[d]);
2932                    let lowest_bit_T = (Rd_unsigned >> amount) & Unsigned::<8>::new(1);
2933
2934                    let retained_flags = Bitvector::<8>::new(0b1011_1111);
2935                    let bit_only_T = Into::<Bitvector<8>>::into(lowest_bit_T << Unsigned::<8>::new(6));
2936
2937                    SREG = (SREG & retained_flags) | bit_only_T;
2938                }
2939
2940                // 1xxx part reserved
2941                "--11_101-_----_1---" => {
2942                    panic!("Reserved opcode");
2943                }
2944
2945                // SBRC
2946                "--11_110r_rrrr_0bbb" => {
2947                    // skip if bit in register is cleared
2948                    let b_unsigned = Into::<Unsigned<3>>::into(b);
2949                    let b_unsigned_ext =  Ext::<8>::ext(b_unsigned);
2950                    let unsigned_bit_mask = Unsigned::<8>::new(1) << b_unsigned_ext;
2951                    let bit_mask = Into::<Bitvector<8>>::into(unsigned_bit_mask);
2952
2953                    if R[r] & bit_mask == bit_mask {
2954                        // it is set, do nothing
2955                    } else {
2956                        // it is cleared, skip next instruction
2957                        PC = Self::instruction_skip(self, PC);
2958                    };
2959                }
2960
2961                // 1xxx part reserved
2962                "--11_110-_----_1---" => {
2963                    panic!("Reserved opcode");
2964                }
2965
2966                // SBRS
2967                "--11_111r_rrrr_0bbb" => {
2968                    // skip if bit in register is set
2969                    let b_unsigned = Into::<Unsigned<3>>::into(b);
2970                    let b_unsigned_ext =  Ext::<8>::ext(b_unsigned);
2971                    let unsigned_bit_mask = Unsigned::<8>::new(1) << b_unsigned_ext;
2972                    let bit_mask = Into::<Bitvector<8>>::into(unsigned_bit_mask);
2973
2974                    if R[r] & bit_mask == bit_mask {
2975                        // it is set, skip next instruction
2976                        PC = Self::instruction_skip(self, PC);
2977                    } else {
2978                        // it is cleared, do nothing
2979                    };
2980                }
2981
2982                // 1xxx part reserved
2983                "--11_111-_----_1---" => {
2984                    panic!("Reserved opcode");
2985                }
2986            });
2987
2988            State {
2989                PC,
2990                R,
2991                DDRB,
2992                PORTB,
2993                DDRC,
2994                PORTC,
2995                DDRD,
2996                PORTD,
2997                GPIOR0,
2998                GPIOR1,
2999                GPIOR2,
3000                SPL,
3001                SPH,
3002                SREG,
3003                SRAM,
3004            }
3005        }
3006    }
3007
3008    impl ::machine_check::Machine for ATmega328P {
3009        type Input = Input;
3010        type State = State;
3011
3012        fn init(&self, input: &Input) -> State {
3013            // --- Program Counter ---
3014            // initialized to 0 after reset
3015            let PC = Bitvector::<14>::new(0);
3016
3017            // --- General Purpose Registers ---
3018            // uninitialized after reset
3019            let R = Clone::clone(&input.uninit_R);
3020
3021            // --- I/O Registers ---
3022
3023            // Port B: DDRB and PORTB initialized to 0 after reset
3024            let DDRB = Bitvector::<8>::new(0);
3025            let PORTB = Bitvector::<8>::new(0);
3026
3027            // Port C: DDRC and PORTC initialized to 0 after reset
3028            let DDRC = Bitvector::<7>::new(0);
3029            let PORTC = Bitvector::<7>::new(0);
3030
3031            // Port D: DDRD and PORTD initialized to 0 after reset
3032            let DDRD = Bitvector::<8>::new(0);
3033            let PORTD = Bitvector::<8>::new(0);
3034
3035            // General Purpose I/O registers
3036            // initialized to 0 after reset
3037            let GPIOR0 = Bitvector::<8>::new(0);
3038            let GPIOR1 = Bitvector::<8>::new(0);
3039            let GPIOR2 = Bitvector::<8>::new(0);
3040
3041            // Stack Pointer
3042            // initialized to last address of SRAM, known as RAMEND
3043            // in case of ATmega328P, RAMEND is 0x8FF (7810D–AVR–01/15 p. 13, 18)
3044            // SP = 0x08FF;
3045            let SPL = Bitvector::<8>::new(0xFF);
3046            let SPH = Bitvector::<8>::new(0x08);
3047
3048            // Status Register
3049            // initialized to 0 after reset
3050            let SREG = Bitvector::<8>::new(0x00);
3051
3052            // --- SRAM ---
3053            let SRAM = Clone::clone(&input.uninit_SRAM);
3054
3055            // --- EEPROM ---
3056            // EEPROM is unchangeable as SPM is not supported
3057
3058            State {
3059                PC,
3060                R,
3061                DDRB,
3062                PORTB,
3063                DDRC,
3064                PORTC,
3065                DDRD,
3066                PORTD,
3067                GPIOR0,
3068                GPIOR1,
3069                GPIOR2,
3070                SPL,
3071                SPH,
3072                SREG,
3073                SRAM,
3074            }
3075        }
3076
3077        fn next(&self, state: &State, input: &Input) -> State {
3078            let mut PC = state.PC;
3079            let R = Clone::clone(&state.R);
3080            let DDRB = state.DDRB;
3081            let PORTB = state.PORTB;
3082            let DDRC = state.DDRC;
3083            let PORTC = state.PORTC;
3084            let DDRD = state.DDRD;
3085            let PORTD = state.PORTD;
3086            let GPIOR0 = state.GPIOR0;
3087            let GPIOR1 = state.GPIOR1;
3088            let GPIOR2 = state.GPIOR2;
3089            let SPL = state.SPL;
3090            let SPH = state.SPH;
3091            let SREG = state.SREG;
3092            let SRAM = Clone::clone(&state.SRAM);
3093
3094            // --- Instruction Step ---
3095
3096            // fetch instruction and increment PC
3097            let instruction = self.PROGMEM[state.PC];
3098
3099            // increment PC
3100            PC = PC + Bitvector::<14>::new(1);
3101
3102            let state = State {
3103                PC,
3104                R,
3105                DDRB,
3106                PORTB,
3107                DDRC,
3108                PORTC,
3109                DDRD,
3110                PORTD,
3111                GPIOR0,
3112                GPIOR1,
3113                GPIOR2,
3114                SPL,
3115                SPH,
3116                SREG,
3117                SRAM,
3118            };
3119
3120            let mut result = Clone::clone(&state);
3121
3122            ::machine_check::bitmask_switch!(instruction {
3123                "0000_----_----_----" => {
3124                    result = Self::next_0000(&state, instruction);
3125                }
3126                "0001_----_----_----" => {
3127                    result = Self::next_0001(self, &state, instruction);
3128                }
3129                "0010_----_----_----" => {
3130                    result = Self::next_0010(&state, instruction);
3131                }
3132                "0011_----_----_----" => {
3133                    result = Self::next_0011(&state, instruction);
3134                }
3135                "01--_----_----_----" => {
3136                    result = Self::next_01(&state, instruction);
3137                }
3138                "10-0_----_----_----" => {
3139                    result = Self::next_10q0(&state, input, instruction);
3140                }
3141                "1001_----_----_----" => {
3142                    result = Self::next_1001(self, &state, input, instruction);
3143                }
3144                "1011_----_----_----" => {
3145                    result = Self::next_1011(&state, input, instruction);
3146
3147                }
3148                "11--_----_----_----" => {
3149                    result = Self::next_11(self, &state, instruction);
3150                }
3151            });
3152
3153            // interrupts are not implemented, so make sure the Global Interrupt Flag
3154            // is not enabled
3155            if result.SREG & Bitvector::<8>::new(0x80) != Bitvector::<8>::new(0x00) {
3156                unimplemented!("Interrupts");
3157            }
3158
3159            result
3160        }
3161    }
3162}