1use yaxpeax_arch::Decoder;
2use arch::MCU;
3use yaxpeax_arch::LengthedInstruction;
4use yaxpeax_arch::Arch;
5use yaxpeax_arch::ShowContextual;
6use memory::MemoryRange;
7use memory::repr::FlatMemoryRepr;
8use debug;
9use debug::DebugTarget;
10use arch::pic17;
11use arch::pic17::{FullInstructionContext, PIC17, SFRS};
12use yaxpeax_pic17::{Operand, Opcode};
13use arch::pic17::deps::{updates_of, dependencies_of};
14use arch::pic17::MergedContextTable;
15
16pub struct PIC17DebugTarget<'a> {
17 pub target: &'a mut pic17::cpu::CPU,
18 break_conditions: Vec<BreakCondition>,
19 watch_targets: Vec<WatchTarget>
20}
21
22impl <'a> PIC17DebugTarget<'a> {
23 fn check_breakpoints(&self) -> bool {
24 for bp in &self.break_conditions {
25 match bp {
26 BreakCondition::IPValue(ip) => {
27 if &self.target.ip == ip { return true; }
28 },
29 BreakCondition::Other(f) => {
30 if f(&self.target) { return true; }
31 },
32 BreakCondition::MemoryAccess(dest) => {
33 let instr = self.target.decode();
38 match instr {
39 Ok(instr) => {
40 match instr.operands[0] {
41 Operand::File(f) => {
42 if self.target.debank(f) == *dest {
43 return true;
44 }
45 },
46 _ => { }
47 };
48
49 match instr.operands[1] {
50 Operand::File(f) => {
51 if self.target.debank(f) == *dest {
52 return true;
53 }
54 },
55 _ => { }
56 };
57 },
58 Err(_) => { }
59 };
60 },
61 BreakCondition::IO => {
62 if self.target.would_IO().is_some() { return true; }
63 }
64 }
65 }
66 false
67 }
68 fn show_watches(&self) {
69 for watch in &self.watch_targets {
70 println!("WATCH: {}", watch.reify(&self.target));
71 }
72 }
73}
74
75impl WatchTarget {
76 fn pointee(&self, cpu: &pic17::cpu::CPU) -> Option<u16> {
78 match self {
79 WatchTarget::Pointee(target) => {
80 target.pointee(cpu).and_then(|value| {
81 if value > cpu.memory.len() as u16 - 2 {
82 return None
83 };
84
85 Some(cpu.get_byte_noupdate(value).unwrap() as u16 |
86 ((cpu.get_byte_noupdate(value + 1).unwrap() as u16) << 8))
87 })
88 },
89 WatchTarget::MemoryLocation(addr) => {
90 cpu.get_byte_noupdate(*addr).and_then(|low| {
91 cpu.get_byte_noupdate(*addr + 1).map(|high| {
92 ((high as u16) << 8) | (low as u16)
93 })
94 }).ok()
95 },
96 WatchTarget::W => Some(cpu.W as u16)
97 }
98 }
99 fn reify(&self, cpu: &pic17::cpu::CPU) -> String {
100 match self {
101 WatchTarget::Pointee(target) => {
102 match target.pointee(cpu) {
103 Some(pointee) => {
104 format!("[{}]: 0x{:x}", target.reify(cpu), pointee)
105 }
106 None => {
107 format!("[{}]: invalid", target.reify(cpu))
108 }
109 }
110 }
111 WatchTarget::MemoryLocation(addr) => {
112 format!("[{}]: 0x{:x}", pic17::named_file(*addr), cpu.get_byte_noupdate(*addr).unwrap())
113 },
114 WatchTarget::W => {
115 format!("W: 0x{:x}", cpu.W)
116 }
117 }
118 }
119}
120
121impl FullInstructionContext for pic17::cpu::CPU {
122 fn memory(&self, addr: u16) -> u8 { self.memory[addr as usize] }
123 fn bsr(&self) -> u8 {
124 self.memory[SFRS::BSR as usize]
125 }
126 fn pclath(&self) -> u8 {
127 self.memory[SFRS::PCLATH as usize]
128 }
129}
130
131#[derive(Debug)]
132pub enum WatchTarget {
133 Pointee(Box<WatchTarget>),
134 MemoryLocation(u16),
135 W
136}
137pub enum BreakCondition {
138 IPValue(u16),
139 Other(fn(&pic17::cpu::CPU) -> bool),
140 MemoryAccess(u16),
141 IO
142}
143
144impl <'a> DebugTarget<'a, pic17::cpu::CPU> for PIC17DebugTarget<'a> {
145 type WatchTarget = WatchTarget;
146 type BreakCondition = BreakCondition;
147 fn attach(cpu: &'a mut pic17::cpu::CPU) -> Self {
148 PIC17DebugTarget {
149 target: cpu,
150 break_conditions: vec![],
151 watch_targets: vec![]
152 }
153 }
154 fn single_step(&mut self) -> Result<(), String> {
155 self.show_watches();
156 self.target.emulate()
157 }
158 fn run(&mut self) -> debug::RunResult {
159 println!("Running...");
160 match self.target.emulate() {
161 Ok(()) => { },
162 Err(msg) => {
163 return debug::RunResult::ExecutionError(msg);
164 }
165 }
166 loop {
167 if self.check_breakpoints() {
168 return debug::RunResult::HitBreakCondition;
169 }
170 match self.target.emulate() {
171 Ok(()) => { },
172 Err(msg) => {
173 return debug::RunResult::ExecutionError(msg);
174 }
175 }
176 }
177 }
178 fn add_watch(&mut self, watch: WatchTarget) -> Result<(), String> {
179 self.watch_targets.push(watch);
180 Ok(())
181 }
182 fn add_break_condition(&mut self, break_cond: Self::BreakCondition) -> Result<(), String> {
183 self.break_conditions.push(break_cond);
184 Ok(())
185 }
186}
187
188enum IOCause {
189 UART,
190 PORT
191}
192
193use arch::pic17::PartialInstructionContext;
194
195pub fn try_debank<T>(f: u8, ctx: Option<&T>) -> Option<u16> where T: PartialInstructionContext {
196 if f < 0x10 {
197 Some(f as u16)
198 } else if f < 0x18 {
199 ctx.and_then(|c| c.bsr_sfr()).map(|bank| ((bank as u16) << 8) | f as u16)
200 } else {
201 ctx.and_then(|c| c.bsr_gpr()).map(|bank| ((bank as u16) << 8) | f as u16)
202 }
203}
204
205pub fn debank(f: u8, bsr: u8) -> u16 {
206 if f < 0x10 {
207 f as u16
208 } else if f < 0x18 {
209 f as u16 | ((bsr as u16 & 0x0f) << 8)
210 } else {
211 f as u16 | ((bsr as u16 & 0xf0) << 4)
212 }
213}
214
215#[allow(non_snake_case)]
216#[derive(Debug)]
217pub struct CPU {
218 pub W: u8,
219 pub ip: u16, psr_z: bool,
221 psr_c: bool,
222 psr_v: bool,
223 psr_dc: bool,
224 stkptr: usize,
225 stack: [u16; 16],
226 tablat: [u8; 2],
227 fsr0_post: u8,
228 fsr1_post: u8,
229 pub program: Vec<u8>,
230 pub memory: Vec<u8>,
231 pub memsize: usize,
232 tsr: u8,
233 tsr_len: u8
234}
235
236impl CPU {
237 pub fn new(progsize: u32, memsize: u32) -> Self {
238 let mut cpu = CPU {
239 W: 0,
240 ip: 0,
241 psr_z: false,
242 psr_c: false,
243 psr_v: false,
244 psr_dc: false,
245 stkptr: 0,
246 stack: [0u16; 16],
247 tablat: [0u8; 2],
248 fsr0_post: 0,
249 fsr1_post: 0,
250 program: vec![0; progsize as usize],
251 memory: vec![0; 0x1000], memsize: memsize as usize,
253 tsr: 0,
254 tsr_len: 0
255 };
256
257 cpu.memory[SFRS::TXSTA1 as usize] |= 0b00000010;
258 cpu.memory[SFRS::TXSTA2 as usize] |= 0b00000010;
259
260 cpu
261 }
262 fn push(&mut self, value: u16) -> Result<(), String> {
263 let ptr = self.stkptr;
264 if ptr >= 16 {
265 return Err("Stack overflow".to_owned());
266 }
267
268 self.stack[ptr as usize] = value;
269
270 self.stkptr += 1;
271 Ok(())
272 }
273 fn pop(&mut self) -> Result<u16, String> {
274 let mut ptr = self.stkptr;
275 if ptr == 0 {
276 return Err("Stack underflow".to_owned());
277 }
278
279 ptr -= 1;
280
281 let result = self.stack[ptr as usize];
282
283 self.stkptr = ptr;
284 Ok(result)
285 }
286 fn txen1(&self) -> bool { self.memory[SFRS::TXSTA1 as usize] & 0b00100000 != 0 }
287 fn txen2(&self) -> bool { self.memory[SFRS::TXSTA2 as usize] & 0b00100000 != 0 }
288
289 #[allow(non_snake_case)]
290 fn would_IO(&self) -> Option<IOCause> {
291 if self.tsr_len > 0 && (self.txen1() || self.txen2()) {
292 return Some(IOCause::UART);
293 }
294
295 match self.decode() {
296 Ok(instr) => {
297 fn does_io(cpu: &CPU, op: Operand) -> Option<IOCause> {
298 match op {
299 Operand::File(f) => {
300 match cpu.debank(f) {
301 SFRS::PORTA |
302 SFRS::PORTB |
303 SFRS::PORTC |
304 SFRS::PORTD |
305 SFRS::PORTE |
306 SFRS::PORTF |
307 SFRS::PORTG => Some(IOCause::PORT),
308 _ => None
309 }
310 },
311 _ => None
312 }
313 }
314
315 does_io(self, instr.operands[0]).or(does_io(self, instr.operands[1]))
316 }
317 Err(_) => {
318 return None;
319 }
320 }
321 }
322 fn set_sfr_bank(&mut self, value: u8) {
323 self.memory[SFRS::BSR as usize] &= 0xf0;
324 self.memory[SFRS::BSR as usize] |= value & 0x0f;
325 }
326 fn set_gpr_bank(&mut self, value: u8) {
327 self.memory[SFRS::BSR as usize] &= 0x0f;
328 self.memory[SFRS::BSR as usize] |= value & 0xf0;
329 }
330 fn get_fsr(&self, fsr: u8) -> u16 {
336 match fsr {
338 0 => {
339 self.memory[SFRS::FSR0 as usize] as u16
340 },
341 1 => {
342 self.memory[SFRS::FSR1 as usize] as u16
343 },
344 _ => { unreachable!(); }
345 }
346 }
347 pub fn debank(&self, f: u8) -> u16 {
348 pic17::cpu::debank(f, self.memory[SFRS::BSR as usize])
349 }
350 pub fn get_byte(&mut self, addr: u16) -> Result<u8, String> {
351 self.get_byte_noupdate(addr)
352 }
353 pub fn get_byte_noupdate(&self, addr: u16) -> Result<u8, String> {
354 let value = match addr {
355 SFRS::PCL => { self.ip as u8 },
356 SFRS::WREG => { self.W },
357 SFRS::ALUSTA => {
358 (self.fsr1_post << 6) |
359 (self.fsr0_post << 4) |
360 (if self.psr_v { 1 } else { 0 } << 3) |
361 (if self.psr_z { 1 } else { 0 } << 2) |
362 (if self.psr_dc { 1 } else { 0 } << 1) |
363 (if self.psr_c { 1 } else { 0 } << 0)
364 },
365 SFRS::INDF0 => {
366 let real_addr = self.get_fsr(0);
367 self.memory[real_addr as usize]
368 },
369 SFRS::INDF1 => {
370 let real_addr = self.get_fsr(1);
371 self.memory[real_addr as usize]
372 }
373 _ => {
374 let real_limit = self.memsize + 0x20 +
378 (self.memsize / 0x100) * 0x20;
379 if addr as usize > real_limit && addr as u8 >= 0x20 {
380 return Err(format!("Invalid dest address: {:x}", addr));
381 }
382 self.memory[addr as usize]
383 }
384 };
385
386 Ok(value)
387 }
388 pub fn set_byte_noupdate(&mut self, addr: u16, what: u8) -> Result<(), String> {
389 match addr {
390 SFRS::PCL => { },
391 SFRS::WREG => { self.W = what; },
392 SFRS::ALUSTA => {
393 self.memory[SFRS::ALUSTA as usize] = what;
394 self.fsr1_post = (what & 0xc0) >> 6;
395 self.fsr0_post = (what & 0x30) >> 6;
396 self.psr_v = (what & 0x08) == 0x08;
397 self.psr_z = (what & 0x04) == 0x04;
398 self.psr_dc = (what & 0x02) == 0x02;
399 self.psr_c = (what & 0x01) == 0x01;
400 },
401 SFRS::CPUSTA => {
402 let value = (self.memory[SFRS::CPUSTA as usize] & 0b11101100) |
403 (what & 0b00010011);
404 self.memory[SFRS::CPUSTA as usize] = value;
405 },
406 SFRS::INDF0 => {
407 let real_addr = self.get_fsr(0);
409 self.memory[real_addr as usize] = what;
410 },
411 SFRS::INDF1 => {
412 let real_addr = self.get_fsr(1);
413 self.memory[real_addr as usize] = what;
414 },
415 SFRS::TXSTA1 => {
416 let masked = what & 0b11110001;
417 self.memory[SFRS::TXSTA1 as usize] = masked;
418 },
419 SFRS::TXSTA2 => {
420 let masked = what & 0b11110001;
421 self.memory[SFRS::TXSTA2 as usize] = masked;
422 },
423 _ => {
424 let real_limit = self.memsize + 0x20 +
428 (self.memsize / 0x100) * 0x20;
429 if addr as usize > real_limit && addr as u8 >= 0x20 {
430 return Err(format!("Invalid dest address: {:x}", addr));
431 }
432
433 self.memory[addr as usize] = what;
434 }
435 };
436 Ok(())
437 }
438 pub fn set_byte(&mut self, addr: u16, what: u8) -> Result<(), String> {
439 self.set_byte_noupdate(addr, what)
440 }
441 pub fn tblptr(&self) -> u16 {
442 ((self.memory[SFRS::TBLPTRL as usize] as u16)) |
443 ((self.memory[SFRS::TBLPTRH as usize] as u16) << 8)
444 }
445 pub fn set_tblptr(&mut self, tblptr: u16) {
446 self.memory[SFRS::TBLPTRL as usize] = tblptr as u8;
447 self.memory[SFRS::TBLPTRH as usize] = (tblptr >> 8) as u8;
448 }
449 pub fn describe(&self) {
450 println!("pic17: C: {}, Z: {}, DC: {}, V: {}", self.psr_c, self.psr_z, self.psr_dc, self.psr_v);
451 println!("ip=0x{:x}, W=0x{:x}, stkptr=0x{:x}", self.ip, self.W, self.stkptr);
452 match self.decode() {
453 Ok(instr) => {
454 let _ctx: Option<&pic17::cpu::CPU> = Some(self);
455 let mut s = String::new();
456 let ctx: Option<&MergedContextTable> = None;
457 instr.contextualize(&yaxpeax_arch::NoColors, self.ip, ctx, &mut s).unwrap();
458 println!("instruction: {}", s);
459 },
460 Err(e) => println!("[invalid: {}]", e)
461 };
462 println!("stack:");
463 for i in 0..self.stkptr {
464 println!(" 0x{:x}", self.stack[i as usize]);
465 }
466 println!("------");
467 println!("tblptr: 0x{:x}", self.tblptr());
468 println!("");
469 }
470 pub fn program<T: MemoryRange<PIC17>>(&mut self, program: Option<T>, config: Option<FlatMemoryRepr>) -> Result<(), String> {
471 match program.and_then(|x| x.as_flat()) {
472 Some(flat) => {
473 let data = flat.data();
474 if data.len() > self.program.len() {
475 return Err(
476 format!(
477 "Data is larger than the chip: 0x{:x} bytes of memory but 0x{:x} available",
478 data.len(),
479 self.program.len()
480 )
481 );
482 }
483 println!("DEBUG: writing 0x{:x} bytes of program...", data.len());
484 self.program[0..data.len()].copy_from_slice(data);
485 },
486 None => {
487 println!("WARN: Provided program includes no code.");
488 }
489 };
490
491 match config {
493 Some(_config) => {
494 println!("WARN: ignoring config");
495 },
496 None => {
497 }
498 };
499
500 Ok(())
501 }
502}
503
504use data::AliasInfo;
505impl AliasInfo for Dependence {
507 fn aliases_of(&self) -> Vec<Self> { vec![] }
508 fn maximal_alias_of(&self) -> Self { self.clone() }
509}
510
511use data::types::{Typed, TypeAtlas, TypeSpec};
512impl Typed for Data {
513 fn type_of(&self, _: &TypeAtlas) -> TypeSpec {
514 TypeSpec::Unknown
515 }
516}
517
518#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
519pub enum Data {
520 Constant(u8)
521}
522
523use analyses::static_single_assignment::{SSAValues};
524use arch::pic17::{Dependence, Update};
525impl SSAValues for PIC17 {
526 type Data = Data; }
528
529use crate::ColorSettings;
530impl<'data, 'colors> crate::analyses::static_single_assignment::DataDisplay<'data, 'colors> for Data {
531 type Displayer = &'static str;
532 fn display(&'data self, _detailed: bool, _colors: Option<&'colors ColorSettings>) -> &'static str {
533 unimplemented!()
534 }
535}
536
537use data::Direction;
538use data::ValueLocations;
539impl ValueLocations for PIC17 {
540 type Location = Dependence;
541
542 fn decompose(instr: &Self::Instruction) -> Vec<(Option<Self::Location>, Direction)> {
543 use arch::pic17::MergedContext;
544 let ctx = MergedContext {
545 computed: None,
546 user: None
547 };
548 let mut result: Vec<(Option<Self::Location>, Direction)> = Vec::new();
549 for update in updates_of(instr, &ctx).into_iter() {
550 let as_dep = match update {
551 Update::W => Some(Dependence::W),
552 Update::Memory(_) => None,
553 Update::Program(_) => None,
554Update::Carry => Some(Dependence::Carry),
556 Update::BSR_SFR => Some(Dependence::BSR_SFR),
557 Update::BSR_GPR => Some(Dependence::BSR_GPR),
558 Update::Unknown => None
559 };
560 result.push((as_dep, Direction::Write));
561 }
562 for dependence in dependencies_of(instr, &ctx).into_iter() {
563 let as_dep = match dependence {
564 Dependence::W => Some(Dependence::W),
565 Dependence::Memory(_) => None,
566 Dependence::Program(_) => None,
567 Dependence::Stack(_) => None,
568 Dependence::Carry => Some(Dependence::Carry),
569 Dependence::BSR_SFR => Some(Dependence::BSR_SFR),
570 Dependence::BSR_GPR => Some(Dependence::BSR_GPR),
571 Dependence::Unknown => None
572 };
573 result.push((as_dep, Direction::Read));
574 }
575 result
576 }
577}
578
579
580impl MCU for CPU {
581 type Addr = u16;
582 type Instruction = <PIC17 as Arch>::Instruction;
583 fn emulate(&mut self) -> Result<(), String> {
584 fn store_operand(cpu: &mut CPU, new_value: u8, dest: Operand) {
585 match dest {
586 Operand::File(f) => {
587 let dest_file = cpu.debank(f);
588 cpu.set_byte_noupdate(dest_file, new_value).unwrap();
589 },
590 Operand::W => {
591 cpu.W = new_value;
592 }
593 _ => {
594 unreachable!();
595 }
596 }
597 }
598 let mut skip_next = false;
599 let eval_result = match self.decode() {
600 Ok(instr) => {
601 match instr.opcode {
602 Opcode::TLRDL => {
603 let dest_file = self.debank(instr.operands[0].file_value());
604 let value = self.tablat[0];
605 self.set_byte(dest_file, value).unwrap();
606 },
607 Opcode::TLRDH => {
608 let dest_file = self.debank(instr.operands[0].file_value());
609 let value = self.tablat[1];
610 self.set_byte(dest_file, value).unwrap();
611 },
612 Opcode::TLWTL => {
613 let source_file = self.debank(instr.operands[0].file_value());
614 self.tablat[0] = self.get_byte(source_file).unwrap();
615 },
616 Opcode::TLWTH => {
617 let source_file = self.debank(instr.operands[0].file_value());
618 self.tablat[1] = self.get_byte(source_file).unwrap();
619 },
620 Opcode::TABLRDL => {
621 self.tablat[0] = self.program[(self.tblptr() * 2) as usize];
622 self.tablat[1] = self.program[(self.tblptr() * 2 + 1) as usize];
623 let dest_file = self.debank(instr.operands[0].file_value());
624 let value = self.tablat[0];
625 self.set_byte(dest_file, value).unwrap();
626 },
627 Opcode::TABLRDLI => {
628 let tblptr = self.tblptr();
629 self.tablat[0] = self.program[(self.tblptr() * 2) as usize];
630 self.tablat[1] = self.program[(self.tblptr() * 2 + 1) as usize];
631 self.set_tblptr(tblptr + 1);
632 let dest_file = self.debank(instr.operands[0].file_value());
633 let value = self.tablat[0];
634 self.set_byte(dest_file, value).unwrap();
635 },
636 Opcode::TABLRDH => {
637 self.tablat[0] = self.program[(self.tblptr() * 2) as usize];
638 self.tablat[1] = self.program[(self.tblptr() * 2 + 1) as usize];
639 let dest_file = self.debank(instr.operands[0].file_value());
640 let value = self.tablat[1];
641 self.set_byte(dest_file, value).unwrap();
642 },
643 Opcode::TABLRDHI => {
644 let tblptr = self.tblptr();
645 self.tablat[0] = self.program[(self.tblptr() * 2) as usize];
646 self.tablat[1] = self.program[(self.tblptr() * 2 + 1) as usize];
647 self.set_tblptr(tblptr + 1);
648 let dest_file = self.debank(instr.operands[0].file_value());
649 let value = self.tablat[1];
650 self.set_byte(dest_file, value).unwrap();
651 },
652 Opcode::TABLWTL => {
653 let source_file = self.debank(instr.operands[0].file_value());
654 self.tablat[0] = self.get_byte(source_file).unwrap();
655 let tblptr = self.tblptr();
656 self.program[(tblptr * 2) as usize] = self.tablat[0];
657 self.program[(tblptr * 2 + 1) as usize] = self.tablat[1];
658 },
659 Opcode::TABLWTLI => {
660 let source_file = self.debank(instr.operands[0].file_value());
661 self.tablat[0] = self.get_byte(source_file).unwrap();
662 let mut tblptr = self.tblptr();
663 self.program[(tblptr * 2) as usize] = self.tablat[0];
664 self.program[(tblptr * 2 + 1) as usize] = self.tablat[1];
665 tblptr += 1;
666 self.set_tblptr(tblptr);
667 },
668 Opcode::TABLWTH => {
669 let source_file = self.debank(instr.operands[0].file_value());
670 self.tablat[1] = self.get_byte(source_file).unwrap();
671 let tblptr = self.tblptr();
672 self.program[(tblptr * 2) as usize] = self.tablat[0];
673 self.program[(tblptr * 2 + 1) as usize] = self.tablat[1];
674 },
675 Opcode::TABLWTHI => {
676 let source_file = self.debank(instr.operands[0].file_value());
677 self.tablat[1] = self.get_byte(source_file).unwrap();
678 let mut tblptr = self.tblptr();
679 self.program[(tblptr * 2) as usize] = self.tablat[0];
680 self.program[(tblptr * 2 + 1) as usize] = self.tablat[1];
681 tblptr += 1;
682 self.set_tblptr(tblptr);
683 },
684 Opcode::SUBLW => {
685 self.W = self.W.wrapping_sub(
686 instr.operands[0].imm8_value()
687 );
688 }
689 Opcode::IORLW => {
690 self.W |= instr.operands[0].imm8_value();
691 }
692 Opcode::XORLW => {
693 self.W ^= instr.operands[0].imm8_value();
694 }
695 Opcode::ANDLW => {
696 self.W &= instr.operands[0].imm8_value();
697 }
698 Opcode::RETLW => {
699 self.W = instr.operands[0].imm8_value();
700 self.ip = self.pop().unwrap();
701 return Ok(());
702 }
703 Opcode::MULWF => {
704 let f = self.debank(instr.operands[0].file_value());
705
706 let result = (self.get_byte(f).unwrap() as u16) * (self.W as u16);
707 self.memory[SFRS::PRODH as usize] = (result >> 8) as u8;
708 self.memory[SFRS::PRODL as usize] = result as u8;
709 }
710 Opcode::MULLW => {
711 let literal = instr.operands[0].imm8_value();
712
713 let result = (literal as u16) * (self.W as u16);
714 self.memory[SFRS::PRODH as usize] = (result >> 8) as u8;
715 self.memory[SFRS::PRODL as usize] = result as u8;
716 }
717 Opcode::MOVLW => {
718 self.W = instr.operands[0].imm8_value();
719 },
720 Opcode::ADDLW => {
721 self.W = self.W.wrapping_add(
722 instr.operands[0].imm8_value()
723 );
724 }
725 Opcode::MOVLB => {
726 self.set_sfr_bank(
727 instr.operands[0].imm8_value()
728 );
729 },
730 Opcode::MOVLR => {
731 self.set_gpr_bank(
732 instr.operands[0].imm8_value()
733 );
734 },
735 Opcode::GOTO => {
736 self.ip = instr.operands[0].imm32_value() as u16;
738 return Ok(());
739 },
740 Opcode::CALL => {
741 let return_address = self.ip + instr.len();
742 self.push(return_address).unwrap();
743 self.ip = instr.operands[0].imm32_value() as u16;
744 return Ok(());
745 },
746 Opcode::RETURN => {
747 self.ip = self.pop().unwrap();
748 return Ok(());
749 },
750 Opcode::RRNCF => {
751 let source_file = self.debank(instr.operands[0].file_value());
752
753 let new_value = self.get_byte(source_file).unwrap()
754 .rotate_right(1);
755
756 store_operand(self, new_value, instr.operands[1]);
757 },
758 Opcode::RRCF => {
759 let source_file = self.debank(instr.operands[0].file_value());
760
761 let mut new_value = self.get_byte(source_file).unwrap();
762 let new_carry = (new_value >> 7) & 0x01 == 0x01;
763 new_value >>= 1;
764 if self.psr_c {
765 new_value |= 0x80;
766 }
767
768 self.psr_c = new_carry;
769 store_operand(self, new_value, instr.operands[1]);
770 },
771 Opcode::RLNCF => {
772 let source_file = self.debank(instr.operands[0].file_value());
773
774 let new_value = self.get_byte(source_file).unwrap()
775 .rotate_left(1);
776 store_operand(self, new_value, instr.operands[1]);
777 },
778 Opcode::RLCF => {
779 let source_file = self.debank(instr.operands[0].file_value());
780
781 let mut new_value = self.get_byte(source_file).unwrap();
782 let new_carry = new_value & 0x01 == 0x01;
783 new_value <<= 1;
784 if self.psr_c {
785 new_value |= 0x01;
786 }
787
788 self.psr_c = new_carry;
789 store_operand(self, new_value, instr.operands[1]);
790 },
791 Opcode::NOP => {
792
793 },
794 Opcode::DCFSNZ => {
795 let source_file = self.debank(instr.operands[0].file_value());
796
797 let value = self.get_byte(source_file).unwrap().wrapping_sub(1);
798 skip_next = value != 0;
799 store_operand(self, value, instr.operands[1]);
800 },
801 Opcode::INCF => {
802 let source_file = self.debank(instr.operands[0].file_value());
803
804 let value = self.get_byte(source_file).unwrap().wrapping_add(1);
805 self.psr_z = value == 0;
807 self.psr_c = value == 0x00; store_operand(self, value, instr.operands[1]);
809 },
810 Opcode::DECF => {
811 let source_file = self.debank(instr.operands[0].file_value());
812
813 let (value, carry) = self.get_byte(source_file).unwrap().overflowing_add(0xff);
814 self.psr_z = value == 0;
815 self.psr_c = carry;
816
817 store_operand(self, value, instr.operands[1]);
818 },
819 Opcode::DECFSZ => {
820 let source_file = self.debank(instr.operands[0].file_value());
821
822 let value = self.get_byte(source_file).unwrap().wrapping_sub(1);
823 skip_next = value == 0;
824
825 store_operand(self, value, instr.operands[1]);
826 },
827 Opcode::INFSNZ => {
828 let source_file = self.debank(instr.operands[0].file_value());
829
830 let value = self.get_byte(source_file).unwrap().wrapping_add(1);
831 skip_next = value != 0;
832
833 store_operand(self, value, instr.operands[1]);
834 },
835 Opcode::INCFSZ => {
836 let source_file = self.debank(instr.operands[0].file_value());
837
838 let value = self.get_byte(source_file).unwrap().wrapping_add(1);
839 skip_next = value == 0;
840
841 store_operand(self, value, instr.operands[1]);
842 },
843 Opcode::TSTFSZ => {
844 let source_file = self.debank(instr.operands[0].file_value());
845
846 let value = self.get_byte(source_file).unwrap();
848 skip_next = value == 0;
849 },
850 Opcode::MOVWF => {
851 let source_file = self.debank(instr.operands[0].file_value());
852
853 let value = self.W.clone();
854 self.set_byte(source_file, value).unwrap();
855 },
856 Opcode::MOVFP => {
857 let source_file = self.debank(instr.operands[0].file_value());
858 let dest_file = self.debank(instr.operands[1].file_value());
859
860 let value = self.get_byte(source_file).unwrap();
862 self.set_byte(dest_file, value).unwrap();
863 },
864 Opcode::MOVPF => {
865 let source_file = self.debank(instr.operands[0].file_value());
866 let dest_file = self.debank(instr.operands[1].file_value());
867
868 let value = self.get_byte(source_file).unwrap();
870 self.set_byte(dest_file, value).unwrap();
871 },
872 Opcode::SWAPF => {
873 let source_file = self.debank(instr.operands[0].file_value());
874
875 let value = self.get_byte(source_file).unwrap();
877 let new_value = (value & 0xf0 >> 4) | (value & 0x0f << 4);
878 self.set_byte(source_file, new_value).unwrap();
879 }
880 Opcode::CLRF => {
881 let source_file = self.debank(instr.operands[0].file_value());
882
883 self.set_byte(source_file, 0).unwrap();
884
885 match instr.operands[1] {
886 Operand::W => {
887 self.W = 0;
888 },
889 _ => { }
890 }
891 },
892 Opcode::BSF => {
893 let source_file = self.debank(instr.operands[0].file_value());
894 let bit = self.debank(instr.operands[1].imm8_value());
895
896 let mut value = self.get_byte(source_file).unwrap();
897 value |= 1 << bit;
898 self.set_byte_noupdate(source_file, value).unwrap();
899 }
900 Opcode::BCF => {
901 let source_file = self.debank(instr.operands[0].file_value());
902 let bit = self.debank(instr.operands[1].imm8_value());
903
904 let mut value = self.get_byte(source_file).unwrap();
905 value &= !(1 << bit);
906 self.set_byte_noupdate(source_file, value).unwrap();
907 }
908 Opcode::BTG => {
909 let source_file = self.debank(instr.operands[0].file_value());
910 let bit = self.debank(instr.operands[1].imm8_value());
911
912 let mut value = self.get_byte(source_file).unwrap();
913 value ^= 1 << bit;
914 self.set_byte_noupdate(source_file, value).unwrap();
915 }
916 Opcode::BTFSS => {
917 let source_file = self.debank(instr.operands[0].file_value());
918 let bit = self.debank(instr.operands[1].imm8_value());
919
920 let value = self.get_byte(source_file).unwrap();
921 let read = value & (1 << bit);
922
923 if read != 0 {
924 skip_next = true;
925 }
926 },
927 Opcode::BTFSC => {
928 let source_file = self.debank(instr.operands[0].file_value());
929 let bit = self.debank(instr.operands[1].imm8_value());
930
931 let value = self.get_byte(source_file).unwrap();
932 let read = value & (1 << bit);
933
934 if read == 0 {
935 skip_next = true;
936 }
937 },
938 Opcode::ANDWF => {
939 let source_file = self.debank(instr.operands[0].file_value());
940
941 let value = self.get_byte(source_file).unwrap() & self.W;
942
943 self.psr_z = value == 0;
944
945 store_operand(self, value, instr.operands[1]);
946 },
947 Opcode::XORWF => {
948 let source_file = self.debank(instr.operands[0].file_value());
949
950 let value = self.get_byte(source_file).unwrap() ^ self.W;
951
952 self.psr_z = value == 0;
953
954 store_operand(self, value, instr.operands[1]);
955 },
956 Opcode::IORWF => {
957 let source_file = self.debank(instr.operands[0].file_value());
958
959 let value = self.get_byte(source_file).unwrap() | self.W;
960
961 self.psr_z = value == 0;
962
963 store_operand(self, value, instr.operands[1]);
964 },
965 Opcode::ADDWF => {
966 let source_file = self.debank(instr.operands[0].file_value());
967
968 let (value, carry) = self.get_byte(source_file).unwrap().overflowing_add(self.W);
969 self.psr_c = carry;
970 self.psr_z = value == 0;
971
972 store_operand(self, value, instr.operands[1]);
973 },
974 Opcode::ADDWFC => {
975 let source_file = self.debank(instr.operands[0].file_value());
976
977 let (intermediate, carry1) = self.W.overflowing_add(self.get_byte(source_file).unwrap());
978 let (value, carry2) = intermediate.overflowing_add(if self.psr_c { 1 } else { 0 });
979 let carry = carry1 | carry2;
980
981 self.psr_c = carry;
982 self.psr_z = value == 0;
983
984 store_operand(self, value, instr.operands[1]);
985 }
986 Opcode::SUBWF => {
987 let source_file = self.debank(instr.operands[0].file_value());
988
989 let (intermediate, carry1) = self.get_byte(source_file).unwrap().overflowing_add(!self.W);
990 let (value, carry2) = intermediate.overflowing_add(1);
991 let carry = carry1 | carry2;
992
993 self.psr_c = carry;
994 self.psr_z = value == 0;
995
996 store_operand(self, value, instr.operands[1]);
997 },
998 Opcode::SUBWFB => {
999 let source_file = self.debank(instr.operands[0].file_value());
1000
1001 let (intermediate, carry1) = self.get_byte(source_file).unwrap().overflowing_add(!self.W);
1002 let (value, carry2) = intermediate.overflowing_add(if self.psr_c { 1 } else { 0 });
1003 let carry = carry1 | carry2;
1004
1005 self.psr_c = carry;
1006 self.psr_z = value == 0;
1007
1008 store_operand(self, value, instr.operands[1]);
1009 },
1010 Opcode::CPFSGT => {
1011 let source_file = self.debank(instr.operands[0].file_value());
1012
1013 if source_file != SFRS::WREG {
1014 let value = self.get_byte(source_file).unwrap().wrapping_add(1);
1015 skip_next = value > self.W;
1016 }
1017 },
1018 Opcode::CPFSEQ => {
1019 let source_file = self.debank(instr.operands[0].file_value());
1020
1021 if source_file != SFRS::WREG {
1022 let value = self.get_byte(source_file).unwrap().wrapping_add(1);
1023 skip_next = value == self.W;
1024 }
1025 },
1026 Opcode::CPFSLT => {
1027 let source_file = self.debank(instr.operands[0].file_value());
1028
1029 if source_file != SFRS::WREG {
1030 let value = self.get_byte(source_file).unwrap().wrapping_add(1);
1031 skip_next = value < self.W;
1032 }
1033 },
1034 _ => {
1035 return Err(format!("unhandled opcode: {:?}", instr.opcode));
1036 }
1037 };
1038 self.ip += instr.len();
1039 Ok(())
1040 },
1041 Err(msg) => { std::panic::panic_any(msg); }
1042 };
1043 if skip_next {
1044 match self.decode() {
1045 Ok(next_instr) => {
1046 self.ip += next_instr.len();
1047 Ok(())
1048 },
1049 Err(msg) => { std::panic::panic_any(msg); }
1050 }
1051 } else {
1052 eval_result
1053 }
1054 }
1055
1056 fn decode(&self) -> Result<Self::Instruction, String> {
1057 let cursor: crate::memory::repr::cursor::ReadCursor<PIC17, Vec<u8>> = self.memory.range_from(self.ip).unwrap();
1058 <PIC17 as Arch>::Decoder::default().decode(&mut cursor.to_reader())
1059 .map_err(|err| {
1060 format!(
1061 "Unable to decode bytes at 0x{:x}: {:x?}, {}",
1062 self.ip,
1063 self.program[(self.ip as usize)..((self.ip + 4) as usize)].iter().collect::<Vec<&u8>>(),
1064 err
1065 )
1066 })
1067 }
1068}