metaemu_machine/
machine.rs

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        // NO-OP to avoid wrapping in an option in absence of a Default
18        // for PCode
19        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        // Check if still within bound
316        while !bound.reached(&*location.address()) {
317            bound = bound.deplete(&*location.address());
318            // Execute the instruction at the current location
319            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}