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 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, 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; }
214 fn bank(&self) -> u8 {
215 self.sfrs[(0xfe0 - self.sfr_start) as usize] }
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 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 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 }
414 }
415 },
416 0xaa => {
417 match self.eecon_state {
418 EECON_STATE::Prep1 => {
419 self.eecon_state = EECON_STATE::Ready;
420 },
421 _ => {
422 }
424 }
425 },
426 _ => {
427 }
429 }
430 },
431 SFRS::EECON1 => {
432 self.sfrs[SFRS::EECON1 as usize] = what;
433 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 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 _ => { }
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 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 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 let value = self.get_byte(dest_file as u32).unwrap().wrapping_add(1);
1038 self.psr_z = value == 0;
1040 self.psr_n = value > 0x7f;
1041 self.psr_c = value == 0x00; 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; }
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 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 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 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 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 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 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 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 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 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 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 self.set_byte_noupdate(dest_file as u32, value).unwrap();
1429 } else {
1430 self.W = value;
1431 }
1432 },
1433 Opcode::RESET => {
1434 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}