yaxpeax_core/arch/pic18/
cpu.rs

1use arch;
2use arch::MCU;
3use yaxpeax_arch::{Arch, AddressBase, AddressDiff, Decoder, LengthedInstruction};
4use memory::MemoryRange;
5use memory::repr::FlatMemoryRepr;
6use debug;
7use debug::DebugTarget;
8use arch::pic18;
9use yaxpeax_pic18::consts::SFRS;
10use yaxpeax_pic18::{PIC18, Operand, Opcode};
11
12pub struct PIC18DebugTarget<'a> {
13    pub target: &'a mut pic18::cpu::CPU,
14    break_conditions: Vec<BreakCondition>,
15    watch_targets: Vec<WatchTarget>
16}
17
18impl <'a> PIC18DebugTarget<'a> {
19    fn check_breakpoints(&self) -> bool {
20        for bp in &self.break_conditions {
21            match bp {
22                BreakCondition::IPValue(ip) => {
23                    if &self.target.ip == ip { return true; }
24                },
25                BreakCondition::Other(f) => {
26                    if f(&self.target) { return true; }
27                }
28            }
29        }
30        false
31    }
32    fn show_watches(&self) {
33        for watch in &self.watch_targets {
34            println!("WATCH: {}", watch.reify(&self.target));
35        }
36    }
37}
38
39impl WatchTarget {
40    /// Builds a pointer from the target of the watch.
41    fn pointee(&self, cpu: &arch::pic18::cpu::CPU) -> Option<u16> {
42        match self {
43            WatchTarget::Pointee(target) => {
44                target.pointee(cpu).and_then(|value| {
45                    if value > cpu.memory.len() as u16 - 2 {
46                        return None
47                    };
48
49                    Some(cpu.get_byte_noupdate(value as u32).unwrap() as u16 |
50                        ((cpu.get_byte_noupdate(value as u32 + 1).unwrap() as u16) << 8))
51                })
52            },
53            WatchTarget::MemoryLocation(addr) => {
54                cpu.get_byte_noupdate(*addr as u32).and_then(|low| {
55                    cpu.get_byte_noupdate(*addr as u32 + 1).map(|high| {
56                        ((high as u16) << 8) | (low as u16)
57                    })
58                }).ok()
59            },
60            WatchTarget::W => Some(((cpu.bank() as u16) << 8) | cpu.W as u16)
61        }
62    }
63    fn reify(&self, cpu: &arch::pic18::cpu::CPU) -> String {
64        match self {
65            WatchTarget::Pointee(target) => {
66                match target.pointee(cpu) {
67                    Some(pointee) => {
68                        format!("[{}]: 0x{:x}", target.reify(cpu), pointee)
69                    }
70                    None => {
71                        format!("[{}]: invalid", target.reify(cpu))
72                    }
73                }
74            }
75            WatchTarget::MemoryLocation(addr) => {
76                format!("[{}]: 0x{:x}", yaxpeax_pic18::consts::named_file(*addr), cpu.get_byte_noupdate(*addr as u32).unwrap())
77            },
78            WatchTarget::W => {
79                format!("W: 0x{:x}", cpu.W)
80            }
81        }
82    }
83}
84
85#[allow(dead_code)]
86#[derive(Debug)]
87pub enum WatchTarget {
88    Pointee(Box<WatchTarget>),
89    MemoryLocation(u16),
90    W
91}
92pub enum BreakCondition {
93    IPValue(u32),
94    Other(fn(&arch::pic18::cpu::CPU) -> bool)
95}
96
97impl <'a> DebugTarget<'a, pic18::cpu::CPU> for PIC18DebugTarget<'a> {
98    type WatchTarget = WatchTarget;
99    type BreakCondition = BreakCondition;
100    fn attach(cpu: &'a mut pic18::cpu::CPU) -> Self {
101        PIC18DebugTarget {
102            target: cpu,
103            break_conditions: vec![],
104            watch_targets: vec![]
105        }
106    }
107    fn single_step(&mut self) -> Result<(), String> {
108        self.show_watches();
109        self.target.emulate()
110    }
111    fn run(&mut self) -> debug::RunResult {
112        println!("Running...");
113        match self.target.emulate() {
114            Ok(()) => { },
115            Err(msg) => {
116                return debug::RunResult::ExecutionError(msg);
117            }
118        }
119        loop {
120            if self.check_breakpoints() {
121                return debug::RunResult::HitBreakCondition;
122            }
123            match self.target.emulate() {
124                Ok(()) => { },
125                Err(msg) => {
126                    return debug::RunResult::ExecutionError(msg);
127                }
128            }
129        }
130    }
131    fn add_watch(&mut self, watch: WatchTarget) -> Result<(), String> {
132        self.watch_targets.push(watch);
133        Ok(())
134    }
135    fn add_break_condition(&mut self, break_cond: Self::BreakCondition) -> Result<(), String> {
136        self.break_conditions.push(break_cond);
137        Ok(())
138    }
139}
140
141#[allow(non_camel_case_types)]
142#[derive(Debug)]
143enum EECON_STATE {
144    Default,
145    Prep1,
146    Ready
147}
148
149#[allow(non_snake_case)]
150#[derive(Debug)]
151pub struct CPU {
152    W: u8,
153    pub ip: u32, // might be limited to u18?
154    psr_z: bool,
155    psr_c: bool,
156    psr_v: bool,
157    psr_n: bool,
158    stack: [u32; 31],
159    holding_registers: [u8; 32],
160    eecon_state: EECON_STATE,
161    pub program: Vec<u8>,
162    pub memory: Vec<u8>,
163    sfr_start: u16,
164    sfr_end: u16,
165    sfrs: Vec<u8>
166}
167
168impl CPU {
169    pub fn new(progsize: u32, memsize: u32) -> Self {
170        CPU {
171            W: 0,
172            ip: 0,
173            psr_z: false,
174            psr_c: false,
175            psr_v: false,
176            psr_n: false,
177            stack: [0u32; 31],
178            holding_registers: [0u8; 32],
179            eecon_state: EECON_STATE::Default,
180            program: vec![0; progsize as usize],
181            memory: vec![0; memsize as usize],
182            sfr_start: 0xf60,
183            sfr_end: 0x1000,
184            sfrs: vec![0; 0x1000 - 0xf60]
185        }
186    }
187    fn push(&mut self, value: u32) -> Result<(), String> {
188        let ptr = self.sfrs[SFRS::STKPTR as usize];
189        if ptr >= 31 {
190            return Err("Stack overflow".to_owned());
191        }
192
193        self.stack[ptr as usize] = value;
194
195        self.sfrs[SFRS::STKPTR as usize] = ptr + 1;
196        Ok(())
197    }
198    fn pop(&mut self) -> Result<u32, String> {
199        let mut ptr = self.sfrs[SFRS::STKPTR as usize];
200        if ptr == 0 {
201            return Err("Stack underflow".to_owned());
202        }
203
204        ptr -= 1;
205
206        let result = self.stack[ptr as usize];
207
208        self.sfrs[SFRS::STKPTR as usize] = ptr;
209        Ok(result)
210    }
211    fn set_bank(&mut self, value: u8) {
212        self.sfrs[(0xfe0 - self.sfr_start) as usize] = value; // TODO this should be configured somehow...
213    }
214    fn bank(&self) -> u8 {
215        self.sfrs[(0xfe0 - self.sfr_start) as usize] // TODO this should be configured somehow...
216    }
217    fn get_fsr(&self, fsr: u8) -> u16 {
218        match fsr {
219            0 => {
220                self.sfrs[SFRS::FSR0L as usize] as u16 |
221                    ((self.sfrs[SFRS::FSR0H as usize] as u16) << 8)
222            },
223            1 => {
224                self.sfrs[SFRS::FSR1L as usize] as u16 |
225                    ((self.sfrs[SFRS::FSR1H as usize] as u16) << 8)
226            },
227            2 => {
228                self.sfrs[SFRS::FSR2L as usize] as u16 |
229                    ((self.sfrs[SFRS::FSR2H as usize] as u16) << 8)
230            },
231            _ => { unreachable!(); }
232        }
233    }
234    fn set_fsr(&mut self, fsr: u8, value: u16) {
235         match fsr {
236            0 => {
237                self.sfrs[SFRS::FSR0L as usize] = value as u8;
238                self.sfrs[SFRS::FSR0H as usize] = (value >> 8) as u8;
239            },
240            1 => {
241                self.sfrs[SFRS::FSR1L as usize] = value as u8;
242                self.sfrs[SFRS::FSR1H as usize] = (value >> 8) as u8;
243            },
244            2 => {
245                self.sfrs[SFRS::FSR2L as usize] = value as u8;
246                self.sfrs[SFRS::FSR2H as usize] = (value >> 8) as u8;
247            },
248            _ => { unreachable!(); }
249        }
250    }
251    fn debank(&self, f: u8, banked: bool) -> u16 {
252        if banked {
253            (f as u16) | ((self.bank() as u16) << 8)
254        } else {
255            if f < 0x80 {
256                f as u16
257            } else {
258                (f as u16) | 0xf00u16
259            }
260        }
261    }
262    fn is_sfr_addr(&self, addr: u32) -> bool {
263        if addr > 0xffff {
264            return false;
265        } else {
266            return (addr as u16) >= self.sfr_start && (addr as u16) < self.sfr_end;
267        }
268    }
269    pub fn get_byte(&mut self, addr: u32) -> Result<u8, String> {
270        if self.is_sfr_addr(addr) {
271            let sfr_addr = (addr as u16) - self.sfr_start;
272            match sfr_addr {
273                SFRS::PREINC2 => {
274                    let real_addr = self.get_fsr(2).wrapping_add(1);
275                    self.set_fsr(2, real_addr);
276                    self.get_byte_noupdate(addr)
277                },
278                SFRS::POSTINC2 => {
279                    let real_addr = self.get_fsr(2).wrapping_add(1);
280                    let value = self.get_byte_noupdate(addr);
281                    self.set_fsr(2, real_addr);
282                    value
283                },
284                SFRS::POSTDEC2 => {
285                    let real_addr = self.get_fsr(2).wrapping_sub(1);
286                    let value = self.get_byte_noupdate(addr);
287                    self.set_fsr(2, real_addr);
288                    value
289                },
290                SFRS::PREINC1 => {
291                    let real_addr = self.get_fsr(1).wrapping_add(1);
292                    self.set_fsr(1, real_addr);
293                    self.get_byte_noupdate(addr)
294                },
295                SFRS::POSTINC1 => {
296                    let real_addr = self.get_fsr(1).wrapping_add(1);
297                    let value = self.get_byte_noupdate(addr);
298                    self.set_fsr(1, real_addr);
299                    value
300                },
301                SFRS::POSTDEC1 => {
302                    let real_addr = self.get_fsr(1).wrapping_sub(1);
303                    let value = self.get_byte_noupdate(addr);
304                    self.set_fsr(1, real_addr);
305                    value
306                },
307                SFRS::PREINC0 => {
308                    let real_addr = self.get_fsr(0).wrapping_add(1);
309                    self.set_fsr(0, real_addr);
310                    self.get_byte_noupdate(addr)
311                },
312                SFRS::POSTINC0 => {
313                    let real_addr = self.get_fsr(0).wrapping_add(1);
314                    let value = self.get_byte_noupdate(addr);
315                    self.set_fsr(0, real_addr);
316                    value
317                },
318                SFRS::POSTDEC0 => {
319                    let real_addr = self.get_fsr(0).wrapping_sub(1);
320                    let value = self.get_byte_noupdate(addr);
321                    self.set_fsr(0, real_addr);
322                    value
323                },
324                _ => {
325                    self.get_byte_noupdate(addr)
326                }
327            }
328        } else {
329            self.get_byte_noupdate(addr)
330        }
331    }
332    pub fn get_byte_noupdate(&self, addr: u32) -> Result<u8, String> {
333        if self.is_sfr_addr(addr) {
334            let sfr_addr = (addr as u16) - self.sfr_start;
335            let value = match sfr_addr {
336                /* indf0 */
337                SFRS::PLUSW0 => {
338                    let real_addr = self.get_fsr(0)
339                        .wrapping_add(self.W as i8 as i16 as u16);
340                    self.memory[real_addr as usize]
341                },
342                SFRS::PREINC0 |
343                SFRS::POSTINC0 |
344                SFRS::POSTDEC0 |
345                SFRS::INDF0 => {
346                    let real_addr = self.get_fsr(0);
347                    self.memory[real_addr as usize]
348                },
349                SFRS::PLUSW1 => {
350                    let real_addr = self.get_fsr(1)
351                        .wrapping_add(self.W as i8 as i16 as u16);
352                    self.memory[real_addr as usize]
353                },
354                SFRS::PREINC1 |
355                SFRS::POSTINC1 |
356                SFRS::POSTDEC1 |
357                SFRS::INDF1 => {
358                    let real_addr = self.get_fsr(1);
359                    self.memory[real_addr as usize]
360                }
361                _ => {
362                    self.sfrs[sfr_addr as usize]
363                }
364            };
365
366            Ok(value)
367        } else {
368            if addr as usize > 0xffff {
369                return Err("Invalid dest address".to_owned());
370            }
371
372            Ok(self.memory[addr as usize])
373        }
374    }
375    pub fn set_byte_noupdate(&mut self, addr: u32, what: u8) -> Result<(), String> {
376        if self.is_sfr_addr(addr) {
377            let sfr_addr = (addr as u16) - self.sfr_start;
378            match sfr_addr {
379                /* indf0 */
380                SFRS::PLUSW0 => {
381                    let real_addr = self.get_fsr(0)
382                        .wrapping_add(self.W as i8 as i16 as u16);
383                    self.memory[real_addr as usize] = what;
384                },
385                SFRS::PREINC0 |
386                SFRS::POSTINC0 |
387                SFRS::POSTDEC0 |
388                SFRS::INDF0 => {
389                    let real_addr = self.get_fsr(0);
390                    self.memory[real_addr as usize] = what;
391                },
392                SFRS::PLUSW1 => {
393                    let real_addr = self.get_fsr(1)
394                        .wrapping_add(self.W as i8 as i16 as u16);
395                    self.memory[real_addr as usize] = what;
396                },
397                SFRS::PREINC1 |
398                SFRS::POSTINC1 |
399                SFRS::POSTDEC1 |
400                SFRS::INDF1 => {
401                    let real_addr = self.get_fsr(1);
402                    self.memory[real_addr as usize] = what;
403                }
404                SFRS::EECON2 => {
405                    match what {
406                        0x55 => {
407                            match self.eecon_state {
408                                EECON_STATE::Default => {
409                                    self.eecon_state = EECON_STATE::Prep1;
410                                },
411                                _ => {
412                                    /* TODO: what happens?? */
413                                }
414                            }
415                        },
416                        0xaa => {
417                            match self.eecon_state {
418                                EECON_STATE::Prep1 => {
419                                    self.eecon_state = EECON_STATE::Ready;
420                                },
421                                _ => {
422                                    /* TODO: what happens?? */
423                                }
424                            }
425                        },
426                        _ => {
427                            // TODO what does this do?
428                        }
429                    }
430                },
431                SFRS::EECON1 => {
432                    self.sfrs[SFRS::EECON1 as usize] = what;
433                    // TODO: more closely implement real behavior here..
434                    if what & 0x02 == 0x02 {
435                        match self.eecon_state {
436                            EECON_STATE::Ready => {
437                                if what & 0x80 == 0x80 &&
438                                    what & 0x40 == 0x00 &&
439                                    what & 0x04 == 0x04 {
440                                    /* write latches to memory! */
441                                    let start_addr = self.tblptr() & 0xffffe0;
442                                    for i in 0..0x1f {
443                                        self.program[(start_addr + i) as usize] &= self.holding_registers[i as usize];
444                                        self.holding_registers[i as usize] = 0xff;
445                                    }
446                                } else {
447                                    return Err(format!("Unsure how to handle write initiate with state 0x{:x}", what));
448                                }
449                            },
450                            _ => { /* do nothing */ }
451                        }
452                    }
453                }
454                _ => {
455                    self.sfrs[sfr_addr as usize] = what;
456                }
457            };
458        } else {
459            if addr as usize > 0xffff {
460                return Err("Invalid dest address".to_owned());
461            }
462
463            self.memory[addr as usize] = what;
464        }
465
466        Ok(())
467    }
468    pub fn set_byte(&mut self, addr: u32, what: u8) -> Result<(), String> {
469        if self.is_sfr_addr(addr) {
470            let sfr_addr = (addr as u16) - self.sfr_start;
471            match sfr_addr {
472                SFRS::PREINC2 => {
473                    let real_addr = self.get_fsr(2).wrapping_add(1);
474                    self.set_fsr(2, real_addr);
475                    self.set_byte_noupdate(addr, what)
476                },
477                SFRS::POSTINC2 => {
478                    let real_addr = self.get_fsr(2).wrapping_add(1);
479                    let value = self.set_byte_noupdate(addr, what);
480                    self.set_fsr(2, real_addr);
481                    value
482                },
483                SFRS::POSTDEC2 => {
484                    let real_addr = self.get_fsr(2).wrapping_sub(1);
485                    let value = self.set_byte_noupdate(addr, what);
486                    self.set_fsr(2, real_addr);
487                    value
488                },
489                SFRS::PREINC1 => {
490                    let real_addr = self.get_fsr(1).wrapping_add(1);
491                    self.set_fsr(1, real_addr);
492                    self.set_byte_noupdate(addr, what)
493                },
494                SFRS::POSTINC1 => {
495                    let real_addr = self.get_fsr(1).wrapping_add(1);
496                    let value = self.set_byte_noupdate(addr, what);
497                    self.set_fsr(1, real_addr);
498                    value
499                },
500                SFRS::POSTDEC1 => {
501                    let real_addr = self.get_fsr(1).wrapping_sub(1);
502                    let value = self.set_byte_noupdate(addr, what);
503                    self.set_fsr(1, real_addr);
504                    value
505                },
506                SFRS::PREINC0 => {
507                    let real_addr = self.get_fsr(0).wrapping_add(1);
508                    self.set_fsr(0, real_addr);
509                    self.set_byte_noupdate(addr, what)
510                },
511                SFRS::POSTINC0 => {
512                    let real_addr = self.get_fsr(0).wrapping_add(1);
513                    let value = self.set_byte_noupdate(addr, what);
514                    self.set_fsr(0, real_addr);
515                    value
516                },
517                SFRS::POSTDEC0 => {
518                    let real_addr = self.get_fsr(0).wrapping_sub(1);
519                    let value = self.set_byte_noupdate(addr, what);
520                    self.set_fsr(0, real_addr);
521                    value
522                },
523                _ => {
524                    self.set_byte_noupdate(addr, what)
525                }
526            }
527        } else {
528            self.set_byte_noupdate(addr, what)
529        }
530    }
531    pub fn set_word(&mut self, addr: u32, what: u32) -> Result<(), String> {
532        if self.is_sfr_addr(addr) {
533            let sfr_addr = (addr as u16) - self.sfr_start;
534
535            let low = what as u8;
536            let high = (what >> 8) as u8;
537            self.sfrs[sfr_addr as usize] = low;
538            self.sfrs[(sfr_addr + 1) as u16 as usize] = high;
539        } else {
540            if addr as usize > 0xffff {
541                return Err("Invalid dest address".to_owned());
542            }
543
544            if what > 0xffff {
545                return Err("Invalid data to write".to_owned());
546            }
547
548            let low = what as u8;
549            let high = (what >> 8) as u8;
550            self.memory[addr as usize] = low;
551            self.memory[(addr + 1) as u16 as usize] = high;
552        }
553
554        Ok(())
555    }
556    pub fn tblptr(&self) -> u32 {
557        ((self.sfrs[SFRS::TBLPTRL as usize] as u32)) |
558        ((self.sfrs[SFRS::TBLPTRH as usize] as u32) << 8) |
559        ((self.sfrs[SFRS::TBLPTRU as usize] as u32) << 16)
560    }
561    pub fn describe(&self) {
562        println!("pic18: C: {}, Z: {}, N: {}, V: {}", self.psr_c, self.psr_z, self.psr_n, self.psr_v);
563        println!("ip=0x{:x}, W=0x{:x}, stkptr=0x{:x}", self.ip, self.W, self.sfrs[SFRS::STKPTR as usize]);
564        match self.decode() {
565            Ok(instr) => println!("instruction: {}", instr),
566            Err(e) => println!("[invalid: {}]", e)
567        };
568        println!("stack:");
569        for i in 0..self.sfrs[SFRS::STKPTR as usize] {
570            println!("  0x{:x}", self.stack[i as usize]);
571        }
572        println!("------");
573        println!("tblptr: 0x{:x}", self.tblptr());
574        println!("");
575    }
576    pub fn program<T: MemoryRange<PIC18>>(&mut self, program: Option<T>, config: Option<FlatMemoryRepr>) -> Result<(), String> {
577        match program.and_then(|x| x.as_flat()) {
578            Some(flat) => {
579                let data = flat.data();
580                if data.len() > self.program.len() {
581                    return Err(
582                        format!(
583                            "Data is larger than the chip: 0x{:x} bytes of memory but 0x{:x} available",
584                            data.len(),
585                            self.program.len()
586                        )
587                    );
588                }
589                println!("DEBUG: writing 0x{:x} bytes of program...", data.len());
590                self.program[0..data.len()].copy_from_slice(data);
591            },
592            None => {
593                println!("WARN: Provided program includes no code.");
594            }
595        };
596
597        match config {
598            Some(_config) => {
599                println!("WARN: ignoring config");
600            },
601            None => {
602            }
603        };
604
605        Ok(())
606    }
607}
608
609impl MCU for CPU {
610    type Addr = u32;
611    type Instruction = <PIC18 as Arch>::Instruction;
612    fn emulate(&mut self) -> Result<(), String> {
613        let mut skip_next = false;
614        let eval_result = match self.decode() {
615            Ok(instr) => {
616                match instr.opcode {
617                    Opcode::TBLWT_S => {
618                        let ptr = self.tblptr();
619                        self.holding_registers[(ptr & 0x1f) as usize] = self.sfrs[SFRS::TABLAT as usize];
620                    }
621                    Opcode::TBLRD_S => {
622                        let ptr = self.tblptr();
623                        self.sfrs[SFRS::TABLAT as usize] = self.program[ptr as usize];
624                    }
625                    Opcode::TBLRD_S_I => {
626                        let mut ptr = self.tblptr();
627                        self.sfrs[SFRS::TABLAT as usize] = self.program[ptr as usize];
628                        ptr += 1;
629                        self.sfrs[SFRS::TBLPTRL as usize] = ptr as u8;
630                        self.sfrs[SFRS::TBLPTRH as usize] = (ptr >> 8) as u8;
631                        self.sfrs[SFRS::TBLPTRU as usize] = (ptr >> 16) as u8;
632                    }
633                    Opcode::SUBLW => {
634                        match instr.operands[0] {
635                            Operand::ImmediateU8(value) => {
636                                self.W = self.W.wrapping_sub(value)
637                            },
638                            _ => { unreachable!(); }
639                        }
640                    }
641                    Opcode::IORLW => {
642                        match instr.operands[0] {
643                            Operand::ImmediateU8(value) => {
644                                self.W |= value
645                            },
646                            _ => { unreachable!(); }
647                        }
648                    }
649                    Opcode::XORLW => {
650                        match instr.operands[0] {
651                            Operand::ImmediateU8(value) => {
652                                self.W ^= value
653                            },
654                            _ => { unreachable!(); }
655                        }
656                    }
657                    Opcode::ANDLW => {
658                        match instr.operands[0] {
659                            Operand::ImmediateU8(value) => {
660                                self.W &= value
661                            },
662                            _ => { unreachable!(); }
663                        }
664                    }
665                    Opcode::RETLW => {
666                        match instr.operands[0] {
667                            Operand::ImmediateU8(value) => {
668                                self.W = value
669                            },
670                            _ => { unreachable!(); }
671                        };
672                        self.ip = self.pop().unwrap();
673                        return Ok(());
674                    }
675                    Opcode::MULWF => {
676                        let f = match instr.operands[0] {
677                            Operand::File(value, a) => self.debank(value, a),
678                            _ => { unreachable!(); }
679                        };
680
681                        let result = (self.get_byte(f as u32).unwrap() as u16) * (self.W as u16);
682                        self.sfrs[SFRS::PRODH as usize] = (result >> 8) as u8;
683                        self.sfrs[SFRS::PRODL as usize] = result as u8;
684                    }
685                    Opcode::MULLW => {
686                        let literal = match instr.operands[0] {
687                            Operand::ImmediateU8(value) => {
688                                value as u16
689                            },
690                            _ => { unreachable!(); }
691                        };
692
693                        let result = literal * (self.W as u16);
694                        self.sfrs[SFRS::PRODH as usize] = (result >> 8) as u8;
695                        self.sfrs[SFRS::PRODL as usize] = result as u8;
696                    }
697                    Opcode::MOVLW => {
698                        match instr.operands[0] {
699                            Operand::ImmediateU8(value) => {
700                                self.W = value
701                            },
702                            _ => {
703                                unreachable!();
704                            }
705                        }
706                    },
707                    Opcode::ADDLW => {
708                        match instr.operands[0] {
709                            Operand::ImmediateU8(value) => {
710                                self.W = self.W.wrapping_add(value)
711                            },
712                            _ => { unreachable!(); }
713                        }
714                    }
715                    Opcode::MOVLB => {
716                        match instr.operands[0] {
717                            Operand::ImmediateU8(value) => {
718                                self.set_bank(value);
719                            },
720                            _ => {
721                                unreachable!();
722                            }
723                        }
724                    },
725                    Opcode::GOTO => {
726                        match instr.operands[0] {
727                            Operand::ImmediateU32(addr) => {
728                                self.ip = addr;
729                                return Ok(());
730                            },
731                            _ => {
732                                unreachable!();
733                            }
734                        }
735                    },
736                    Opcode::CALL => {
737                        match instr.operands[0] {
738                            Operand::ImmediateU32(addr) => {
739                                let return_address = self.ip + instr.len();
740                                self.push(return_address).unwrap();
741                                self.ip = addr;
742                                return Ok(());
743                            },
744                            _ => {
745                                unreachable!();
746                            }
747                        }
748                    },
749                    Opcode::RETURN => {
750                        self.ip = self.pop().unwrap();
751                        return Ok(());
752                    },
753                    Opcode::BRA => {
754                        match instr.operands[0] {
755                            Operand::ImmediateU32(rel) => {
756                                self.ip = self.ip
757                                    .wrapping_offset(instr.len())
758                                    .wrapping_offset(AddressDiff::from_const((rel << 1) as i8 as i32 as u32));
759                                return Ok(());
760                            },
761                            _ => {
762                                unreachable!();
763                            }
764                        }
765                    },
766                    Opcode::RCALL => {
767                        match instr.operands[0] {
768                            Operand::ImmediateU32(rel) => {
769                                let return_address = self.ip + instr.len();
770                                self.push(return_address).unwrap();
771                                self.ip = return_address
772                                    .wrapping_add((rel << 1) as i8 as i32 as u32);
773                                return Ok(());
774                            },
775                            _ => {
776                                unreachable!();
777                            }
778                        }
779                    },
780                    Opcode::BZ => {
781                        match instr.operands[0] {
782                            Operand::ImmediateU8(rel) => {
783                                if self.psr_z {
784                                    self.ip = self.ip
785                                        .wrapping_offset(instr.len())
786                                        .wrapping_offset(AddressDiff::from_const((rel << 1) as i8 as i32 as u32));
787                                    return Ok(());
788                                }
789                            },
790                            _ => {
791                                unreachable!();
792                            }
793                        }
794                    },
795                    Opcode::BNZ => {
796                        match instr.operands[0] {
797                            Operand::ImmediateU8(rel) => {
798                                if ! self.psr_z {
799                                    self.ip = self.ip
800                                        .wrapping_offset(instr.len())
801                                        .wrapping_offset(AddressDiff::from_const((rel << 1) as i8 as i32 as u32));
802                                    return Ok(());
803                                }
804                            },
805                            _ => {
806                                unreachable!();
807                            }
808                        }
809                    },
810                    Opcode::BC => {
811                        match instr.operands[0] {
812                            Operand::ImmediateU8(rel) => {
813                                if self.psr_c {
814                                    self.ip = self.ip
815                                        .wrapping_offset(instr.len())
816                                        .wrapping_offset(AddressDiff::from_const((rel << 1) as i8 as i32 as u32));
817                                    return Ok(());
818                                }
819                            },
820                            _ => {
821                                unreachable!();
822                            }
823                        }
824                    },
825                    Opcode::BNC => {
826                        match instr.operands[0] {
827                            Operand::ImmediateU8(rel) => {
828                                if ! self.psr_c {
829                                    self.ip = self.ip
830                                        .wrapping_offset(instr.len())
831                                        .wrapping_offset(AddressDiff::from_const((rel << 1) as i8 as i32 as u32));
832                                    return Ok(());
833                                }
834                            },
835                            _ => {
836                                unreachable!();
837                            }
838                        }
839                    },
840                    Opcode::BOV => {
841                        match instr.operands[0] {
842                            Operand::ImmediateU8(rel) => {
843                                if self.psr_v {
844                                    self.ip = self.ip
845                                        .wrapping_offset(instr.len())
846                                        .wrapping_offset(AddressDiff::from_const((rel << 1) as i8 as i32 as u32));
847                                    return Ok(());
848                                }
849                            },
850                            _ => {
851                                unreachable!();
852                            }
853                        }
854                    },
855                    Opcode::BNOV => {
856                        match instr.operands[0] {
857                            Operand::ImmediateU8(rel) => {
858                                if ! self.psr_v {
859                                    self.ip = self.ip
860                                        .wrapping_offset(instr.len())
861                                        .wrapping_offset(AddressDiff::from_const((rel << 1) as i8 as i32 as u32));
862                                    return Ok(());
863                                }
864                            },
865                            _ => {
866                                unreachable!();
867                            }
868                        }
869                    },
870                    Opcode::BN => {
871                        match instr.operands[0] {
872                            Operand::ImmediateU8(rel) => {
873                                if self.psr_n {
874                                    self.ip = self.ip
875                                        .wrapping_offset(instr.len())
876                                        .wrapping_offset(AddressDiff::from_const((rel << 1) as i8 as i32 as u32));
877                                    return Ok(());
878                                }
879                            },
880                            _ => {
881                                unreachable!();
882                            }
883                        }
884                    },
885                    Opcode::BNN => {
886                        match instr.operands[0] {
887                            Operand::ImmediateU8(rel) => {
888                                if ! self.psr_n {
889                                    self.ip = self.ip
890                                        .wrapping_offset(instr.len())
891                                        .wrapping_offset(AddressDiff::from_const((rel << 1) as i8 as i32 as u32));
892                                    return Ok(());
893                                }
894                            },
895                            _ => {
896                                unreachable!();
897                            }
898                        }
899                    },
900                    Opcode::RRNCF => {
901                        let (dest_file, to_file) = match instr.operands[0] {
902                            Operand::RedirectableFile(f, banked, direction) => (self.debank(f, banked), direction),
903                            _ => {
904                                unreachable!();
905                            }
906                        };
907
908                        let new_value = self.get_byte(dest_file as u32).unwrap()
909                            .rotate_right(1);
910
911                        if to_file {
912                            self.set_byte_noupdate(dest_file as u32, new_value).unwrap();
913                        } else {
914                            self.W = new_value;
915                        }
916                    },
917                    Opcode::RRCF => {
918                        let (dest_file, to_file) = match instr.operands[0] {
919                            Operand::RedirectableFile(f, banked, direction) => (self.debank(f, banked), direction),
920                            _ => {
921                                unreachable!();
922                            }
923                        };
924
925                        let mut new_value = self.get_byte(dest_file as u32).unwrap();
926                        let new_carry = (new_value >> 7) & 0x01 == 0x01;
927                        new_value >>= 1;
928                        if self.psr_c {
929                            new_value |= 0x80;
930                        }
931
932                        self.psr_c = new_carry;
933
934                        if to_file {
935                            self.set_byte_noupdate(dest_file as u32, new_value).unwrap();
936                        } else {
937                            self.W = new_value;
938                        }
939                    },
940                    Opcode::RLNCF => {
941                        let (dest_file, to_file) = match instr.operands[0] {
942                            Operand::RedirectableFile(f, banked, direction) => (self.debank(f, banked), direction),
943                            _ => {
944                                unreachable!();
945                            }
946                        };
947
948                        let new_value = self.get_byte(dest_file as u32).unwrap()
949                            .rotate_left(1);
950
951                        if to_file {
952                            self.set_byte_noupdate(dest_file as u32, new_value).unwrap();
953                        } else {
954                            self.W = new_value;
955                        }
956                    },
957                    Opcode::RLCF => {
958                        let (dest_file, to_file) = match instr.operands[0] {
959                            Operand::RedirectableFile(f, banked, direction) => (self.debank(f, banked), direction),
960                            _ => {
961                                unreachable!();
962                            }
963                        };
964
965                        let mut new_value = self.get_byte(dest_file as u32).unwrap();
966                        let new_carry = new_value & 0x01 == 0x01;
967                        new_value <<= 1;
968                        if self.psr_c {
969                            new_value |= 0x01;
970                        }
971
972                        self.psr_c = new_carry;
973
974                        if to_file {
975                            self.set_byte_noupdate(dest_file as u32, new_value).unwrap();
976                        } else {
977                            self.W = new_value;
978                        }
979                    },
980                    Opcode::NOP => {
981
982                    },
983                    Opcode::LFSR => {
984                        let dest_file = match instr.operands[0] {
985                            Operand::FileFSR(f) => {
986                                // math
987                                match f {
988                                    0 => 0xfe9,
989                                    1 => 0xfe1,
990                                    2 => 0xfd9,
991                                    _ => panic!("Invalid FSRf")
992                                }
993                            },
994                            _ => {
995                                unreachable!();
996                            }
997                        };
998
999                        let imm = match instr.operands[1] {
1000                            Operand::ImmediateU32(imm) => {
1001                                imm
1002                            },
1003                            _ => {
1004                                unreachable!();
1005                            }
1006                        };
1007
1008                        self.set_word(dest_file, imm).unwrap();
1009                    },
1010                    Opcode::DCFSNZ => {
1011                        let (dest_file, to_file) = match instr.operands[0] {
1012                            Operand::RedirectableFile(f, banked, direction) => (self.debank(f, banked), direction),
1013                            _ => { unreachable!() }
1014                        };
1015
1016
1017                        if to_file {
1018                            // TODO: verify
1019                            let value = self.get_byte(dest_file as u32).unwrap().wrapping_sub(1);
1020                            skip_next = value != 0;
1021                            self.set_byte_noupdate(dest_file as u32, value).unwrap();
1022                        } else {
1023                            self.W = self.get_byte(dest_file as u32).unwrap();
1024                            self.W = self.W.wrapping_sub(1);
1025                            skip_next = self.W != 0;
1026                        }
1027                    },
1028                    Opcode::INCF => {
1029                        let (dest_file, to_file) = match instr.operands[0] {
1030                            Operand::RedirectableFile(f, banked, direction) => (self.debank(f, banked), direction),
1031                            _ => { unreachable!() }
1032                        };
1033
1034
1035                        if to_file {
1036                            // TODO: verify how this interacts with postinc/postdec,
1037                            let value = self.get_byte(dest_file as u32).unwrap().wrapping_add(1);
1038                            // what about C, OV, DC?
1039                            self.psr_z = value == 0;
1040                            self.psr_n = value > 0x7f;
1041                            self.psr_c = value == 0x00; // just rolled over.
1042                            self.set_byte_noupdate(dest_file as u32, value).unwrap();
1043                        } else {
1044                            self.W = self.get_byte(dest_file as u32).unwrap();
1045                            self.W = self.W.wrapping_add(1);
1046                            self.psr_z = self.W == 0;
1047                            self.psr_n = self.W > 0x7f;
1048                            self.psr_c = self.W == 0x00; // just rolled over.
1049                        }
1050                    },
1051                    Opcode::DECF => {
1052                        let (dest_file, to_file) = match instr.operands[0] {
1053                            Operand::RedirectableFile(f, banked, direction) => (self.debank(f, banked), direction),
1054                            _ => { unreachable!() }
1055                        };
1056
1057
1058                        let (value, carry) = self.get_byte(dest_file as u32).unwrap().overflowing_add(0xff);
1059                        self.psr_z = value == 0;
1060                        self.psr_n = value > 0x7f;
1061                        self.psr_c = carry;
1062
1063                        if to_file {
1064                            // TODO: verify how this interacts with postinc/postdec,
1065                            self.set_byte_noupdate(dest_file as u32, value).unwrap();
1066                        } else {
1067                            self.W = value;
1068                        }
1069                    },
1070                    Opcode::DECFSZ => {
1071                        let (dest_file, to_file) = match instr.operands[0] {
1072                            Operand::RedirectableFile(f, banked, direction) => (self.debank(f, banked), direction),
1073                            _ => { unreachable!() }
1074                        };
1075
1076
1077                        if to_file {
1078                            // TODO: verify
1079                            let value = self.get_byte(dest_file as u32).unwrap().wrapping_sub(1);
1080                            skip_next = value == 0;
1081                            self.set_byte_noupdate(dest_file as u32, value).unwrap();
1082                        } else {
1083                            self.W = self.get_byte(dest_file as u32).unwrap();
1084                            self.W = self.W.wrapping_sub(1);
1085                            skip_next = self.W == 0;
1086                        }
1087                    },
1088                    Opcode::INFSNZ => {
1089                        let (dest_file, to_file) = match instr.operands[0] {
1090                            Operand::RedirectableFile(f, banked, direction) => (self.debank(f, banked), direction),
1091                            _ => { unreachable!() }
1092                        };
1093
1094
1095                        if to_file {
1096                            // TODO: verify
1097                            let value = self.get_byte(dest_file as u32).unwrap().wrapping_add(1);
1098                            skip_next = value != 0;
1099                            self.set_byte_noupdate(dest_file as u32, value).unwrap();
1100                        } else {
1101                            self.W = self.get_byte(dest_file as u32).unwrap();
1102                            self.W = self.W.wrapping_add(1);
1103                            skip_next = self.W != 0;
1104                        }
1105                    },
1106                    Opcode::INCFSZ => {
1107                        let (dest_file, to_file) = match instr.operands[0] {
1108                            Operand::RedirectableFile(f, banked, direction) => (self.debank(f, banked), direction),
1109                            _ => { unreachable!() }
1110                        };
1111
1112
1113                        if to_file {
1114                            // TODO: verify
1115                            let value = self.get_byte(dest_file as u32).unwrap().wrapping_add(1);
1116                            skip_next = value == 0;
1117                            self.set_byte_noupdate(dest_file as u32, value).unwrap();
1118                        } else {
1119                            self.W = self.get_byte(dest_file as u32).unwrap();
1120                            self.W = self.W.wrapping_add(1);
1121                            skip_next = self.W == 0;
1122                        }
1123                    },
1124                    Opcode::TSTFSZ => {
1125                        let dest_file = match instr.operands[0] {
1126                            Operand::File(f, banked) => self.debank(f, banked),
1127                            _ => { unreachable!() }
1128                        };
1129
1130
1131                        // TODO: verify
1132                        let value = self.get_byte(dest_file as u32).unwrap();
1133                        skip_next = value == 0;
1134                    },
1135                    Opcode::MOVF => {
1136                        let (dest_file, to_file) = match instr.operands[0] {
1137                            Operand::RedirectableFile(f, banked, direction) => (self.debank(f, banked), direction),
1138                            _ => { unreachable!() }
1139                        };
1140
1141
1142                        if to_file {
1143                            // TODO: verify
1144                            let value = self.get_byte(dest_file as u32).unwrap();
1145                            self.psr_n = value > 0x7f;
1146                            self.psr_z = value == 0x00;
1147                            self.set_byte_noupdate(dest_file as u32, value).unwrap();
1148                        } else {
1149                            self.W = self.get_byte(dest_file as u32).unwrap();
1150                            self.psr_n = self.W > 0x7f;
1151                            self.psr_z = self.W == 0x00;
1152                        }
1153                    },
1154                    Opcode::MOVFF => {
1155                        let src_file = match instr.operands[0] {
1156                            Operand::AbsoluteFile(f) => f,
1157                            _ => { unreachable!() }
1158                        };
1159
1160                        let dest_file = match instr.operands[1] {
1161                            Operand::AbsoluteFile(f) => f,
1162                            _ => { unreachable!() }
1163                        };
1164
1165                        let value = self.get_byte(src_file as u32).unwrap();
1166                        self.set_byte(dest_file as u32, value).unwrap();
1167                    },
1168                    Opcode::MOVWF => {
1169                        let dest_file = match instr.operands[0] {
1170                            Operand::File(f, banked) => self.debank(f, banked),
1171                            _ => { unreachable!() }
1172                        };
1173
1174                        let value = self.W.clone();
1175                        self.set_byte(dest_file as u32, value).unwrap();
1176                    },
1177                    Opcode::CLRF => {
1178                        let dest_file = match instr.operands[0] {
1179                            Operand::File(f, banked) => self.debank(f, banked),
1180                            _ => { unreachable!() }
1181                        };
1182
1183                        self.set_byte(dest_file as u32, 0).unwrap();
1184                    },
1185                    Opcode::BSF => {
1186                        let dest_file = match instr.operands[0] {
1187                            Operand::File(f, banked) => self.debank(f, banked),
1188                            _ => { unreachable!() }
1189                        };
1190
1191                        let bit = match instr.operands[1] {
1192                            Operand::ImmediateU8(bit) => {
1193                                bit
1194                            },
1195                            _ => { unreachable!() }
1196                        };
1197
1198                        let mut value = self.get_byte(dest_file as u32).unwrap();
1199                        value |= 1 << bit;
1200                        self.set_byte_noupdate(dest_file as u32, value).unwrap();
1201                    }
1202                    Opcode::BCF => {
1203                        let dest_file = match instr.operands[0] {
1204                            Operand::File(f, banked) => self.debank(f, banked),
1205                            _ => { unreachable!() }
1206                        };
1207
1208                        let bit = match instr.operands[1] {
1209                            Operand::ImmediateU8(bit) => {
1210                                bit
1211                            },
1212                            _ => { unreachable!() }
1213                        };
1214
1215                        let mut value = self.get_byte(dest_file as u32).unwrap();
1216                        value &= !(1 << bit);
1217                        self.set_byte_noupdate(dest_file as u32, value).unwrap();
1218                    }
1219                    Opcode::BTG => {
1220                        let dest_file = match instr.operands[0] {
1221                            Operand::File(f, banked) => self.debank(f, banked),
1222                            _ => { unreachable!() }
1223                        };
1224
1225                        let bit = match instr.operands[1] {
1226                            Operand::ImmediateU8(bit) => {
1227                                bit
1228                            },
1229                            _ => { unreachable!() }
1230                        };
1231
1232                        let mut value = self.get_byte(dest_file as u32).unwrap();
1233                        value ^= 1 << bit;
1234                        self.set_byte_noupdate(dest_file as u32, value).unwrap();
1235                    }
1236                    Opcode::BTFSS => {
1237                        let dest_file = match instr.operands[0] {
1238                            Operand::File(f, banked) => self.debank(f, banked),
1239                            _ => { unreachable!() }
1240                        };
1241
1242                        let bit = match instr.operands[1] {
1243                            Operand::ImmediateU8(bit) => {
1244                                bit
1245                            },
1246                            _ => { unreachable!() }
1247                        };
1248
1249                        let value = self.get_byte(dest_file as u32).unwrap();
1250                        let read = value & (1 << bit);
1251
1252                        if read != 0 {
1253                            skip_next = true;
1254                        }
1255                    },
1256                    Opcode::BTFSC => {
1257                        let dest_file = match instr.operands[0] {
1258                            Operand::File(f, banked) => self.debank(f, banked),
1259                            _ => { unreachable!() }
1260                        };
1261
1262                        let bit = match instr.operands[1] {
1263                            Operand::ImmediateU8(bit) => {
1264                                bit
1265                            },
1266                            _ => { unreachable!() }
1267                        };
1268
1269                        let value = self.get_byte(dest_file as u32).unwrap();
1270                        let read = value & (1 << bit);
1271
1272                        if read == 0 {
1273                            skip_next = true;
1274                        }
1275                    },
1276                    Opcode::ANDWF => {
1277                        let (dest_file, to_file) = match instr.operands[0] {
1278                            Operand::RedirectableFile(f, banked, direction) => (self.debank(f, banked), direction),
1279                            _ => { unreachable!() }
1280                        };
1281
1282                        let value = self.get_byte(dest_file as u32).unwrap() & self.W;
1283
1284                        self.psr_z = value == 0;
1285                        self.psr_n = value > 0x7f;
1286
1287                        if to_file {
1288                            self.set_byte_noupdate(dest_file as u32, value).unwrap();
1289                        } else {
1290                            self.W = value;
1291                        }
1292                    },
1293                    Opcode::XORWF => {
1294                        let (dest_file, to_file) = match instr.operands[0] {
1295                            Operand::RedirectableFile(f, banked, direction) => (self.debank(f, banked), direction),
1296                            _ => { unreachable!() }
1297                        };
1298
1299                        let value = self.get_byte(dest_file as u32).unwrap() ^ self.W;
1300
1301                        self.psr_z = value == 0;
1302                        self.psr_n = value > 0x7f;
1303
1304                        if to_file {
1305                            self.set_byte_noupdate(dest_file as u32, value).unwrap();
1306                        } else {
1307                            self.W = value;
1308                        }
1309                    },
1310                    Opcode::IORWF => {
1311                        let (dest_file, to_file) = match instr.operands[0] {
1312                            Operand::RedirectableFile(f, banked, direction) => (self.debank(f, banked), direction),
1313                            _ => { unreachable!() }
1314                        };
1315
1316                        let value = self.get_byte(dest_file as u32).unwrap() | self.W;
1317
1318                        self.psr_z = value == 0;
1319                        self.psr_n = value > 0x7f;
1320
1321                        if to_file {
1322                            self.set_byte_noupdate(dest_file as u32, value).unwrap();
1323                        } else {
1324                            self.W = value;
1325                        }
1326                    },
1327                    Opcode::ADDWF => {
1328                        let (dest_file, to_file) = match instr.operands[0] {
1329                            Operand::RedirectableFile(f, banked, direction) => (self.debank(f, banked), direction),
1330                            _ => { unreachable!() }
1331                        };
1332
1333                        if to_file {
1334                            // TODO: verify how this interacts with postinc/postdec,
1335                            let (value, carry) = self.get_byte(dest_file as u32).unwrap().overflowing_add(self.W);
1336                            self.psr_c = carry;
1337                            self.psr_z = value == 0;
1338                            self.psr_n = value > 0x7f;
1339                            self.set_byte_noupdate(dest_file as u32, value).unwrap();
1340                        } else {
1341                            let (value, carry) = self.get_byte(dest_file as u32).unwrap().overflowing_add(self.W);
1342                            self.psr_c = carry;
1343                            self.psr_z = value == 0;
1344                            self.psr_n = value > 0x7f;
1345                            self.W = value;
1346                        }
1347                    },
1348                    Opcode::ADDWFC => {
1349                        let (dest_file, to_file) = match instr.operands[0] {
1350                            Operand::RedirectableFile(f, banked, direction) => (self.debank(f, banked), direction),
1351                            _ => { unreachable!() }
1352                        };
1353
1354                        let (intermediate, carry1) = self.W.overflowing_add(self.get_byte(dest_file as u32).unwrap());
1355                        let (value, carry2) = intermediate.overflowing_add(if self.psr_c { 1 } else { 0 });
1356                        let carry = carry1 | carry2;
1357
1358                        self.psr_c = carry;
1359                        self.psr_z = value == 0;
1360                        self.psr_n = value > 0x7f;
1361
1362                        if to_file {
1363                            // TODO: verify how this interacts with postinc/postdec,
1364                            self.set_byte_noupdate(dest_file as u32, value).unwrap();
1365                        } else {
1366                            self.W = value;
1367                        }
1368
1369                    }
1370                    Opcode::SUBWF => {
1371                        let (dest_file, to_file) = match instr.operands[0] {
1372                            Operand::RedirectableFile(f, banked, direction) => (self.debank(f, banked), direction),
1373                            _ => { unreachable!() }
1374                        };
1375
1376                        let (intermediate, carry1) = self.get_byte(dest_file as u32).unwrap().overflowing_add(!self.W);
1377                        let (value, carry2) = intermediate.overflowing_add(1);
1378                        let carry = carry1 | carry2;
1379
1380                        self.psr_c = carry;
1381                        self.psr_z = value == 0;
1382                        self.psr_n = value > 0x7f;
1383
1384                        if to_file {
1385                            // TODO: verify how this interacts with postinc/postdec,
1386                            self.set_byte_noupdate(dest_file as u32, value).unwrap();
1387                        } else {
1388                            self.W = value;
1389                        }
1390                    },
1391                    Opcode::SUBWFB => {
1392                        let (dest_file, to_file) = match instr.operands[0] {
1393                            Operand::RedirectableFile(f, banked, direction) => (self.debank(f, banked), direction),
1394                            _ => { unreachable!() }
1395                        };
1396
1397                        let (intermediate, carry1) = self.get_byte(dest_file as u32).unwrap().overflowing_add(!self.W);
1398                        let (value, carry2) = intermediate.overflowing_add(if self.psr_c { 1 } else { 0 });
1399                        let carry = carry1 | carry2;
1400
1401                        self.psr_c = carry;
1402                        self.psr_z = value == 0;
1403                        self.psr_n = value > 0x7f;
1404
1405                        if to_file {
1406                            // TODO: verify how this interacts with postinc/postdec,
1407                            self.set_byte_noupdate(dest_file as u32, value).unwrap();
1408                        } else {
1409                            self.W = value;
1410                        }
1411                    },
1412                    Opcode::SUBFWB => {
1413                        let (dest_file, to_file) = match instr.operands[0] {
1414                            Operand::RedirectableFile(f, banked, direction) => (self.debank(f, banked), direction),
1415                            _ => { unreachable!() }
1416                        };
1417
1418                        let (intermediate, carry1) = self.W.overflowing_add(!self.get_byte(dest_file as u32).unwrap());
1419                        let (value, carry2) = intermediate.overflowing_add(if self.psr_c { 1 } else { 0 });
1420                        let carry = carry1 | carry2;
1421
1422                        self.psr_c = carry;
1423                        self.psr_z = value == 0;
1424                        self.psr_n = value > 0x7f;
1425
1426                        if to_file {
1427                            // TODO: verify how this interacts with postinc/postdec,
1428                            self.set_byte_noupdate(dest_file as u32, value).unwrap();
1429                        } else {
1430                            self.W = value;
1431                        }
1432                    },
1433                    Opcode::RESET => {
1434                        /* TODO: reset ALL state */
1435                        self.psr_z = false;
1436                        self.psr_c = false;
1437                        self.psr_n = false;
1438                        self.psr_v = false;
1439                        self.W = 0;
1440                        self.stack = [0u32; 31];
1441                        self.holding_registers = [0u8; 32];
1442                        self.eecon_state = EECON_STATE::Default;
1443                        self.sfrs = vec![0u8; self.sfrs.len()];
1444                        self.ip = 0;
1445                        println!("Reset.");
1446                        return Ok(());
1447                    },
1448                    _ => {
1449                        return Err(format!("unhandled opcode: {:?}", instr.opcode));
1450                    }
1451                };
1452                self.ip += instr.len();
1453                Ok(())
1454            },
1455            Err(msg) => { std::panic::panic_any(msg); }
1456        };
1457        if skip_next {
1458            match self.decode() {
1459                Ok(next_instr) => {
1460                    self.ip += next_instr.len();
1461                    Ok(())
1462                },
1463                Err(msg) => { std::panic::panic_any(msg); }
1464            }
1465        } else {
1466            eval_result
1467        }
1468    }
1469
1470    fn decode(&self) -> Result<Self::Instruction, String> {
1471        let cursor: crate::memory::repr::cursor::ReadCursor<PIC18, Vec<u8>> = self.memory.range_from(self.ip).unwrap();
1472        <PIC18 as Arch>::Decoder::default().decode(&mut cursor.to_reader())
1473            .map_err(|e| {
1474                format!(
1475                    "Unable to decode bytes at 0x{:x}: {:x?}, {}",
1476                    self.ip,
1477                    self.program[(self.ip as usize)..((self.ip + 4) as usize)].iter().collect::<Vec<&u8>>(),
1478                    e
1479                )
1480            })
1481    }
1482}