yaxpeax_core/arch/msp430/
cpu.rs

1use arch::{Decoder, MCU};
2use memory::{MemoryRange, MemoryRepr};
3use debug;
4use debug::DebugTarget;
5use arch::msp430;
6use yaxpeax_msp430::{MSP430, Operand};
7use yaxpeax_arch::Arch;
8
9pub struct MSP430DebugTarget<'a> {
10    pub target: &'a mut msp430::cpu::CPU,
11    break_conditions: Vec<BreakCondition>,
12    watch_targets: Vec<WatchTarget>
13}
14
15impl <'a> MSP430DebugTarget<'a> {
16    fn check_breakpoints(&self) -> bool {
17        for bp in &self.break_conditions {
18            match bp {
19                BreakCondition::IPValue(ip) => {
20                    if &self.target.ip() == ip { return true; }
21                },
22                BreakCondition::Other(f) => {
23                    if f(&self.target) { return true; }
24                },
25                BreakCondition::MemoryAccess(_dest) => {
26                    unimplemented!("memory access breakpoints not yet supported for MSP430");
27                },
28                BreakCondition::IO => {
29                    unimplemented!("IO breakpoints not yet supported for MSP430");
30                }
31            }
32        }
33        false
34    }
35    fn show_watches(&self) {
36        for watch in &self.watch_targets {
37            tracing::info!("WATCH: {}", watch.reify(&self.target));
38        }
39    }
40}
41
42impl WatchTarget {
43    /// Builds a pointer from the target of the watch.
44    #[allow(dead_code)]
45    fn pointee(&self, _cpu: &msp430::cpu::CPU) -> Option<u16> {
46        match self {
47            WatchTarget::Pointee(_target) => {
48                unimplemented!("MSP430 watches not yet supported");
49            },
50            WatchTarget::MemoryLocation(_addr) => {
51                unimplemented!("MSP430 watches not yet supported");
52            }
53        }
54    }
55    #[allow(dead_code)]
56    fn reify(&self, _cpu: &msp430::cpu::CPU) -> String {
57        match self {
58            WatchTarget::Pointee(_target) => {
59                unimplemented!("MSP430 watches not yet supported");
60            }
61            WatchTarget::MemoryLocation(_addr) => {
62                unimplemented!("MSP430 watches not yet supported");
63            },
64        }
65    }
66}
67
68trait InstructionContext {
69//    fn debank(&self, banked: u8) -> u16;
70}
71
72impl InstructionContext for msp430::cpu::CPU {
73}
74
75trait Contextual<T> {
76    fn contextualize(&self, _ctx: &T) -> String;
77}
78
79impl <T> Contextual<T> for yaxpeax_msp430::Instruction
80    where T: InstructionContext
81{
82    fn contextualize(&self, ctx: &T) -> String {
83        fn contextualize_op<T: InstructionContext>(_op: yaxpeax_msp430::Operand, _ctx: &T) -> String {
84            unimplemented!("unimplemented");
85        }
86
87        let mut result = format!("{}", self.opcode);
88        match self.operands[0] {
89            Operand::Nothing => { return result; },
90            x @ _ => {
91                result = format!("{} {}", result, contextualize_op(x, ctx));
92            }
93        }
94        match self.operands[1] {
95            Operand::Nothing => { return result; },
96            x @ _ => {
97                result = format!("{}, {}", result, contextualize_op(x, ctx));
98            }
99        }
100        return result;
101    }
102}
103
104#[derive(Debug)]
105pub enum WatchTarget {
106    Pointee(Box<WatchTarget>),
107    MemoryLocation(u16),
108}
109pub enum BreakCondition {
110    IPValue(u16),
111    Other(fn(&msp430::cpu::CPU) -> bool),
112    MemoryAccess(u16),
113    IO
114}
115
116impl <'a> DebugTarget<'a, msp430::cpu::CPU> for MSP430DebugTarget<'a> {
117    type WatchTarget = WatchTarget;
118    type BreakCondition = BreakCondition;
119    fn attach(cpu: &'a mut msp430::cpu::CPU) -> Self {
120        MSP430DebugTarget {
121            target: cpu,
122            break_conditions: vec![],
123            watch_targets: vec![]
124        }
125    }
126    fn single_step(&mut self) -> Result<(), String> {
127        self.show_watches();
128        self.target.emulate()
129    }
130    fn run(&mut self) -> debug::RunResult {
131        println!("Running...");
132        match self.target.emulate() {
133            Ok(()) => { },
134            Err(msg) => {
135                return debug::RunResult::ExecutionError(msg);
136            }
137        }
138        loop {
139            if self.check_breakpoints() {
140                return debug::RunResult::HitBreakCondition;
141            }
142            match self.target.emulate() {
143                Ok(()) => { },
144                Err(msg) => {
145                    return debug::RunResult::ExecutionError(msg);
146                }
147            }
148        }
149    }
150    fn add_watch(&mut self, watch: WatchTarget) -> Result<(), String> {
151        self.watch_targets.push(watch);
152        Ok(())
153    }
154    fn add_break_condition(&mut self, break_cond: Self::BreakCondition) -> Result<(), String> {
155        self.break_conditions.push(break_cond);
156        Ok(())
157    }
158}
159
160#[allow(dead_code)]
161enum IOCause {
162    UART,
163    PORT
164}
165
166#[allow(non_snake_case)]
167#[derive(Debug)]
168pub struct CPU {
169    pub registers: [u16; 16],
170    pub memory: Vec<u8>,
171    disable: bool
172}
173
174impl CPU {
175    pub fn new() -> Self {
176        CPU {
177            registers: [0u16; 16],
178            memory: vec![0; 0x10000],
179            disable: false
180        }
181    }
182    pub fn ip(&self) -> u16 {
183        self.registers[0]
184    }
185    pub fn set_ip(&mut self, newval: u16) {
186        self.registers[0] = newval;
187    }
188    #[allow(dead_code)]
189    fn push(&mut self, _value: u32) -> Result<(), String> {
190        unimplemented!("msp430 push");
191    }
192    #[allow(dead_code)]
193    fn pop(&mut self) -> Result<u32, String> {
194        unimplemented!("msp430 pop");
195    }
196
197    /*
198    #[allow(non_snake_case)]
199    fn would_IO(&self) -> Option<IOCause> {
200    }
201    */
202    pub fn get_byte(&mut self, addr: u16) -> Result<u8, String> {
203        self.get_byte_noupdate(addr)
204    }
205    pub fn get_byte_noupdate(&self, _addr: u16) -> Result<u8, String> {
206        unimplemented!("msp430 memory access");
207    }
208    pub fn set_byte_noupdate(&mut self, _addr: u16, _what: u8) -> Result<(), String> {
209        unimplemented!("msp430 memory access");
210    }
211    pub fn set_byte(&mut self, addr: u16, what: u8) -> Result<(), String> {
212        self.set_byte_noupdate(addr, what)
213    }
214    pub fn describe(&self) {
215        println!("msp430: ");
216        println!("ip=0x{:x}", self.ip());
217        match self.decode() {
218            Ok(instr) => println!("instruction: {}", instr.contextualize(self)),
219            Err(e) => println!("[invalid: {}]", e)
220        };
221    }
222    pub fn program<T: MemoryRepr<MSP430>>(&mut self, program: Option<T>) -> Result<(), String> {
223        match program.and_then(|x| x.as_flat()) {
224            Some(flat) => {
225                let data = flat.data();
226                if data.len() > self.memory.len() {
227                    return Err(
228                        format!(
229                            "Data is larger than the chip: 0x{:x} bytes of memory but 0x{:x} available",
230                            data.len(),
231                            self.memory.len()
232                        )
233                    );
234                }
235                tracing::debug!("writing 0x{:x} bytes of program...", data.len());
236                self.memory[0..data.len()].copy_from_slice(data);
237            },
238            None => {
239                tracing::warn!("provided program includes no code.");
240            }
241        };
242
243        let initial_ip = ((self.memory[0xffff] as u16) << 8) | (self.memory[0xfffe] as u16);
244        if initial_ip == 0xffff {
245            self.disable = true;
246        } else {
247            self.set_ip(initial_ip);
248        }
249
250        Ok(())
251    }
252}
253
254impl MCU for CPU {
255    type Addr = u16;
256    type Instruction = <MSP430 as Arch>::Instruction;
257    fn emulate(&mut self) -> Result<(), String> {
258        if self.disable {
259            return Ok(());
260        }
261
262        match self.decode() {
263            Ok(_instr) => {
264                unimplemented!("msp430 emulation not yet supported");
265            },
266            Err(msg) => { std::panic::panic_any(msg); }
267        };
268    }
269
270    fn decode(&self) -> Result<Self::Instruction, String> {
271        let cursor: crate::memory::repr::cursor::ReadCursor<MSP430, Vec<u8>> = self.memory.range_from(self.ip()).unwrap();
272        <MSP430 as Arch>::Decoder::default().decode(&mut cursor.to_reader())
273            .map_err(|_| {
274                format!(
275                    "Unable to decode bytes at 0x{:x}: {:x?}",
276                    self.ip(),
277                    self.memory[(self.ip() as usize)..((self.ip() + 4) as usize)].iter().collect::<Vec<&u8>>()
278                )
279            })
280    }
281}