yaxpeax_core/arch/msp430/
cpu.rs1use 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 #[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}
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 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}