1use fugue::ir::{AddressValue, IntoAddress};
2use fugue::ir::il::Location;
3use fugue::ir::il::pcode::{PCode, PCodeOp};
4
5use crate::traits::Interpreter;
6use crate::types::{Bound, Branch, BranchOutcome, OrOutcome, Outcome, StepOutcome, StepState};
7
8#[derive(Clone)]
9pub struct Machine<I: Interpreter> {
10 interpreter: I,
11 step_state: StepState,
12 ignore_errors: bool,
13}
14
15impl<I> From<I> for Machine<I> where I: Interpreter {
16 fn from(interpreter: I) -> Self {
17 let step_state = StepState::from(PCode::nop(
20 AddressValue::new(interpreter.interpreter_space(), 0),
21 0,
22 ));
23
24 Self {
25 interpreter,
26 step_state,
27 ignore_errors: false,
28 }
29 }
30}
31
32impl<I> Machine<I> where I: Interpreter {
33 #[inline(always)]
34 pub fn new(interpreter: I) -> Self {
35 Self::from(interpreter)
36 }
37
38 #[inline(always)]
39 pub fn new_with(interpreter: I, ignore_errors: bool) -> Self {
40 let mut machine = Self::new(interpreter);
41 machine.ignore_errors = ignore_errors;
42 machine
43 }
44
45 #[deprecated(since = "2.10", note = "use Machine::ignore_errors")]
46 pub fn set_ignore_errors(&mut self, ignore_errors: bool) {
47 self.ignore_errors = ignore_errors;
48 }
49
50 pub fn ignore_errors(&mut self, ignore_errors: bool) {
51 self.ignore_errors = ignore_errors;
52 }
53
54 pub fn step<L>(&mut self, location: L) -> Result<StepOutcome<I::Outcome>, I::Error>
55 where L: Into<Location> {
56
57 let location = location.into();
58 let address = location.address();
59
60 match self.interpreter.lift(&*address)? {
61 OrOutcome::Branch(location) => return self.step(location),
62 OrOutcome::Continue(step_state) => {
63 self.step_state = step_state.with_location(&location);
64 },
65 OrOutcome::Halt(outcome) => return Ok(StepOutcome::Halt(outcome)),
66 }
67
68 while let Some(op) = self.step_state.current() {
69 match self.interpreter.operation(&self.step_state.location(), op)? {
70 OrOutcome::Branch(location) => return self.step(location),
71 OrOutcome::Halt(outcome) => return Ok(StepOutcome::Halt(outcome)),
72 OrOutcome::Continue(_) => (),
73 };
74
75 let action_res = match op {
76 PCodeOp::Copy { ref source, ref destination } => {
77 self.interpreter.copy(source, destination)
78 },
79 PCodeOp::Load { ref source, ref destination, space } => {
80 self.interpreter.load(source, destination, space.clone())
81 },
82 PCodeOp::Store { ref source, ref destination, space } => {
83 self.interpreter.store(source, destination, space.clone())
84 },
85 PCodeOp::Branch { ref destination } => {
86 self.interpreter.branch(destination)
87 },
88 PCodeOp::CBranch { ref destination, ref condition } => {
89 self.interpreter.cbranch(destination, condition)
90 },
91 PCodeOp::IBranch { ref destination } => {
92 self.interpreter.ibranch(destination)
93 },
94 PCodeOp::Call { ref destination } => {
95 self.interpreter.call(destination)
96 },
97 PCodeOp::ICall { ref destination } => {
98 self.interpreter.icall(destination)
99 },
100 PCodeOp::Intrinsic { name, ref operands, ref result } => {
101 self.interpreter.intrinsic(name, operands.as_ref(), result.as_ref())
102 },
103 PCodeOp::Return { ref destination } => {
104 self.interpreter.return_(destination)
105 },
106
107 PCodeOp::IntEq { ref result, operands: [ref operand1, ref operand2] } => {
108 self.interpreter.int_eq(result, operand1, operand2)
109 },
110 PCodeOp::IntNotEq { ref result, operands: [ref operand1, ref operand2] } => {
111 self.interpreter.int_not_eq(result, operand1, operand2)
112 },
113 PCodeOp::IntLess { ref result, operands: [ref operand1, ref operand2] } => {
114 self.interpreter.int_less(result, operand1, operand2)
115 },
116 PCodeOp::IntLessEq { ref result, operands: [ref operand1, ref operand2] } => {
117 self.interpreter.int_less_eq(result, operand1, operand2)
118 },
119 PCodeOp::IntSLess { ref result, operands: [ref operand1, ref operand2] } => {
120 self.interpreter.int_sless(result, operand1, operand2)
121 },
122 PCodeOp::IntSLessEq { ref result, operands: [ref operand1, ref operand2] } => {
123 self.interpreter.int_sless_eq(result, operand1, operand2)
124 },
125
126 PCodeOp::IntZExt { ref result, ref operand } => {
127 self.interpreter.int_zext(result, operand)
128 },
129 PCodeOp::IntSExt { ref result, ref operand } => {
130 self.interpreter.int_sext(result, operand)
131 },
132
133 PCodeOp::IntAdd { ref result, operands: [ref operand1, ref operand2] } => {
134 self.interpreter.int_add(result, operand1, operand2)
135 },
136 PCodeOp::IntSub { ref result, operands: [ref operand1, ref operand2] } => {
137 self.interpreter.int_sub(result, operand1, operand2)
138 },
139 PCodeOp::IntCarry { ref result, operands: [ref operand1, ref operand2] } => {
140 self.interpreter.int_carry(result, operand1, operand2)
141 },
142 PCodeOp::IntSCarry { ref result, operands: [ref operand1, ref operand2] } => {
143 self.interpreter.int_scarry(result, operand1, operand2)
144 },
145 PCodeOp::IntSBorrow { ref result, operands: [ref operand1, ref operand2] } => {
146 self.interpreter.int_sborrow(result, operand1, operand2)
147 },
148
149 PCodeOp::IntNeg { ref result, ref operand } => {
150 self.interpreter.int_neg(result, operand)
151 },
152 PCodeOp::IntNot { ref result, ref operand } => {
153 self.interpreter.int_not(result, operand)
154 },
155
156 PCodeOp::IntXor { ref result, operands: [ref operand1, ref operand2] } => {
157 self.interpreter.int_xor(result, operand1, operand2)
158 },
159 PCodeOp::IntAnd { ref result, operands: [ref operand1, ref operand2] } => {
160 self.interpreter.int_and(result, operand1, operand2)
161 },
162 PCodeOp::IntOr { ref result, operands: [ref operand1, ref operand2] } => {
163 self.interpreter.int_or(result, operand1, operand2)
164 },
165 PCodeOp::IntLeftShift { ref result, operands: [ref operand1, ref operand2] } => {
166 self.interpreter.int_left_shift(result, operand1, operand2)
167 },
168 PCodeOp::IntRightShift { ref result, operands: [ref operand1, ref operand2] } => {
169 self.interpreter.int_right_shift(result, operand1, operand2)
170 },
171 PCodeOp::IntSRightShift { ref result, operands: [ref operand1, ref operand2] } => {
172 self.interpreter.int_sright_shift(result, operand1, operand2)
173 },
174
175 PCodeOp::IntMul { ref result, operands: [ref operand1, ref operand2] } => {
176 self.interpreter.int_mul(result, operand1, operand2)
177 },
178 PCodeOp::IntDiv { ref result, operands: [ref operand1, ref operand2] } => {
179 self.interpreter.int_div(result, operand1, operand2)
180 },
181 PCodeOp::IntSDiv { ref result, operands: [ref operand1, ref operand2] } => {
182 self.interpreter.int_sdiv(result, operand1, operand2)
183 },
184 PCodeOp::IntRem { ref result, operands: [ref operand1, ref operand2] } => {
185 self.interpreter.int_rem(result, operand1, operand2)
186 },
187 PCodeOp::IntSRem { ref result, operands: [ref operand1, ref operand2] } => {
188 self.interpreter.int_srem(result, operand1, operand2)
189 },
190
191 PCodeOp::BoolNot { ref result, ref operand } => {
192 self.interpreter.bool_not(result, operand)
193 },
194 PCodeOp::BoolXor { ref result, operands: [ref operand1, ref operand2] } => {
195 self.interpreter.bool_xor(result, operand1, operand2)
196 },
197 PCodeOp::BoolAnd { ref result, operands: [ref operand1, ref operand2] } => {
198 self.interpreter.bool_and(result, operand1, operand2)
199 },
200 PCodeOp::BoolOr { ref result, operands: [ref operand1, ref operand2] } => {
201 self.interpreter.bool_or(result, operand1, operand2)
202 },
203
204 PCodeOp::FloatEq { ref result, operands: [ref operand1, ref operand2] } => {
205 self.interpreter.float_eq(result, operand1, operand2)
206 },
207 PCodeOp::FloatNotEq { ref result, operands: [ref operand1, ref operand2] } => {
208 self.interpreter.float_not_eq(result, operand1, operand2)
209 },
210 PCodeOp::FloatLess { ref result, operands: [ref operand1, ref operand2] } => {
211 self.interpreter.float_less(result, operand1, operand2)
212 },
213 PCodeOp::FloatLessEq { ref result, operands: [ref operand1, ref operand2] } => {
214 self.interpreter.float_less_eq(result, operand1, operand2)
215 },
216
217 PCodeOp::FloatIsNaN { ref result, ref operand } => {
218 self.interpreter.float_is_nan(result, operand)
219 },
220
221 PCodeOp::FloatAdd { ref result, operands: [ref operand1, ref operand2] } => {
222 self.interpreter.float_add(result, operand1, operand2)
223 },
224 PCodeOp::FloatDiv { ref result, operands: [ref operand1, ref operand2] } => {
225 self.interpreter.float_div(result, operand1, operand2)
226 },
227 PCodeOp::FloatMul { ref result, operands: [ref operand1, ref operand2] } => {
228 self.interpreter.float_mul(result, operand1, operand2)
229 },
230 PCodeOp::FloatSub { ref result, operands: [ref operand1, ref operand2] } => {
231 self.interpreter.float_sub(result, operand1, operand2)
232 },
233
234 PCodeOp::FloatNeg { ref result, ref operand } => {
235 self.interpreter.float_neg(result, operand)
236 },
237 PCodeOp::FloatAbs { ref result, ref operand } => {
238 self.interpreter.float_abs(result, operand)
239 },
240 PCodeOp::FloatSqrt { ref result, ref operand } => {
241 self.interpreter.float_sqrt(result, operand)
242 },
243
244 PCodeOp::FloatOfInt { ref result, ref operand } => {
245 self.interpreter.float_of_int(result, operand)
246 },
247 PCodeOp::FloatOfFloat { ref result, ref operand } => {
248 self.interpreter.float_of_float(result, operand)
249 },
250
251 PCodeOp::FloatTruncate { ref result, ref operand } => {
252 self.interpreter.float_truncate(result, operand)
253 },
254 PCodeOp::FloatCeiling { ref result, ref operand } => {
255 self.interpreter.float_ceiling(result, operand)
256 },
257 PCodeOp::FloatFloor { ref result, ref operand } => {
258 self.interpreter.float_floor(result, operand)
259 },
260 PCodeOp::FloatRound { ref result, ref operand } => {
261 self.interpreter.float_round(result, operand)
262 },
263
264 PCodeOp::Subpiece { ref result, ref operand, ref amount } => {
265 self.interpreter.subpiece(result, operand, amount)
266 },
267 PCodeOp::PopCount { ref result, ref operand } => {
268 self.interpreter.pop_count(result, operand)
269 },
270
271 PCodeOp::Skip => {
272 self.interpreter.skip()
273 },
274 };
275
276 match action_res {
277 Err(e) => {
278 if self.ignore_errors {
279 if let BranchOutcome::Global(address) = self.step_state.branch(&Branch::Next) {
280 return Ok(StepOutcome::Branch(address))
281 } else {
282 continue
283 }
284 } else {
285 return Err(e);
286 }
287 },
288 Ok(action) => {
289 match action {
290 Outcome::Halt(outcome) => {
291 return Ok(StepOutcome::Halt(outcome))
292 },
293 Outcome::Branch(ref branch) => if let BranchOutcome::Global(address) = self.step_state.branch(branch) {
294 return Ok(StepOutcome::Branch(address))
295 } else {
296 continue
297 },
298 }
299 },
300
301 }
302 }
303
304 Ok(StepOutcome::Branch(self.step_state.fallthrough()))
305 }
306
307 pub fn step_until<L, B>(&mut self, location: L, until: Bound<B>) -> Result<(Bound<AddressValue>, StepOutcome<I::Outcome>), I::Error>
308 where L: Into<Location>,
309 B: IntoAddress {
310
311 let space = self.interpreter.interpreter_space();
312 let mut bound = until.in_space(&*space);
313 let mut location = location.into();
314
315 while !bound.reached(&*location.address()) {
317 bound = bound.deplete(&*location.address());
318 match self.step(location)? {
320 StepOutcome::Branch(next_address) => {
321 location = Location::from(next_address);
322 },
323 v => {
324 return Ok((bound, v))
325 }
326 }
327 }
328
329 Ok((bound, StepOutcome::Reached))
330 }
331
332 pub fn step_state(&self) -> &StepState {
333 &self.step_state
334 }
335
336 pub fn step_state_mut(&mut self) -> &mut StepState {
337 &mut self.step_state
338 }
339
340 pub fn interpreter(&self) -> &I {
341 &self.interpreter
342 }
343
344 pub fn interpreter_mut(&mut self) -> &mut I {
345 &mut self.interpreter
346 }
347}