fugue_ir/il/pcode/
mod.rs

1use std::fmt;
2use crate::disassembly::lift::UserOpStr;
3use crate::disassembly::{Opcode, VarnodeData};
4use crate::address::AddressValue;
5use crate::space::AddressSpaceId;
6use crate::space_manager::SpaceManager;
7
8use crate::register::RegisterNames;
9
10pub mod operand;
11pub use operand::Operand;
12
13pub mod register;
14pub use register::Register;
15
16use smallvec::SmallVec;
17
18use unsafe_unwrap::UnsafeUnwrap;
19
20#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
21#[derive(serde::Deserialize, serde::Serialize)]
22pub enum PCodeOp {
23    Copy {
24        source: Operand,
25        destination: Operand,
26    },
27    Load {
28        source: Operand,
29        destination: Operand,
30        space: AddressSpaceId,
31    },
32    Store {
33        source: Operand,
34        destination: Operand,
35        space: AddressSpaceId,
36    },
37
38    Branch {
39        destination: Operand,
40    },
41    CBranch {
42        destination: Operand,
43        condition: Operand,
44    },
45    IBranch {
46        destination: Operand,
47    },
48
49    Call {
50        destination: Operand,
51    },
52    ICall {
53        destination: Operand,
54    },
55    Intrinsic {
56        name: UserOpStr,
57        operands: SmallVec<[Operand; 4]>,
58        result: Option<Operand>,
59    },
60    Return {
61        destination: Operand,
62    },
63
64    IntEq {
65        result: Operand,
66        operands: [Operand; 2],
67    },
68    IntNotEq {
69        result: Operand,
70        operands: [Operand; 2],
71    },
72    IntLess {
73        result: Operand,
74        operands: [Operand; 2],
75    },
76    IntLessEq {
77        result: Operand,
78        operands: [Operand; 2],
79    },
80    IntSLess {
81        result: Operand,
82        operands: [Operand; 2],
83    },
84    IntSLessEq {
85        result: Operand,
86        operands: [Operand; 2],
87    },
88    IntZExt {
89        result: Operand,
90        operand: Operand,
91    },
92    IntSExt {
93        result: Operand,
94        operand: Operand,
95    },
96    IntAdd {
97        result: Operand,
98        operands: [Operand; 2],
99    },
100    IntSub {
101        result: Operand,
102        operands: [Operand; 2],
103    },
104    IntCarry {
105        result: Operand,
106        operands: [Operand; 2],
107    },
108    IntSCarry {
109        result: Operand,
110        operands: [Operand; 2],
111    },
112    IntSBorrow {
113        result: Operand,
114        operands: [Operand; 2],
115    },
116    IntNeg {
117        result: Operand,
118        operand: Operand,
119    },
120    IntNot {
121        result: Operand,
122        operand: Operand,
123    },
124    IntXor {
125        result: Operand,
126        operands: [Operand; 2],
127    },
128    IntAnd {
129        result: Operand,
130        operands: [Operand; 2],
131    },
132    IntOr {
133        result: Operand,
134        operands: [Operand; 2],
135    },
136    IntLeftShift {
137        result: Operand,
138        operands: [Operand; 2],
139    },
140    IntRightShift {
141        result: Operand,
142        operands: [Operand; 2],
143    },
144    IntSRightShift {
145        result: Operand,
146        operands: [Operand; 2],
147    },
148    IntMul {
149        result: Operand,
150        operands: [Operand; 2],
151    },
152    IntDiv {
153        result: Operand,
154        operands: [Operand; 2],
155    },
156    IntSDiv {
157        result: Operand,
158        operands: [Operand; 2],
159    },
160    IntRem {
161        result: Operand,
162        operands: [Operand; 2],
163    },
164    IntSRem {
165        result: Operand,
166        operands: [Operand; 2],
167    },
168
169    BoolNot {
170        result: Operand,
171        operand: Operand,
172    },
173    BoolXor {
174        result: Operand,
175        operands: [Operand; 2],
176    },
177    BoolAnd {
178        result: Operand,
179        operands: [Operand; 2],
180    },
181    BoolOr {
182        result: Operand,
183        operands: [Operand; 2],
184    },
185
186    FloatEq {
187        result: Operand,
188        operands: [Operand; 2],
189    },
190    FloatNotEq {
191        result: Operand,
192        operands: [Operand; 2],
193    },
194    FloatLess {
195        result: Operand,
196        operands: [Operand; 2],
197    },
198    FloatLessEq {
199        result: Operand,
200        operands: [Operand; 2],
201    },
202
203    FloatIsNaN {
204        result: Operand,
205        operand: Operand,
206    },
207
208    FloatAdd {
209        result: Operand,
210        operands: [Operand; 2],
211    },
212    FloatDiv {
213        result: Operand,
214        operands: [Operand; 2],
215    },
216    FloatMul {
217        result: Operand,
218        operands: [Operand; 2],
219    },
220    FloatSub {
221        result: Operand,
222        operands: [Operand; 2],
223    },
224    FloatNeg {
225        result: Operand,
226        operand: Operand,
227    },
228    FloatAbs {
229        result: Operand,
230        operand: Operand,
231    },
232    FloatSqrt {
233        result: Operand,
234        operand: Operand,
235    },
236
237    FloatOfInt {
238        result: Operand,
239        operand: Operand,
240    },
241    FloatOfFloat {
242        result: Operand,
243        operand: Operand,
244    },
245    FloatTruncate {
246        result: Operand,
247        operand: Operand,
248    },
249    FloatCeiling {
250        result: Operand,
251        operand: Operand,
252    },
253    FloatFloor {
254        result: Operand,
255        operand: Operand,
256    },
257    FloatRound {
258        result: Operand,
259        operand: Operand,
260    },
261
262    Subpiece {
263        result: Operand,
264        operand: Operand,
265        amount: Operand,
266    },
267    PopCount {
268        result: Operand,
269        operand: Operand,
270    },
271
272    Skip,
273}
274
275impl fmt::Display for PCodeOp {
276    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
277        match self {
278            Self::Copy { destination, source } => write!(f, "{} ← {}", destination, source)?,
279            Self::Load { destination, source, .. } => write!(f, "{} ← *{}", destination, source)?,
280            Self::Store { destination, source, .. } => write!(f, "*{} ← {}", destination, source)?,
281
282            Self::Branch { destination } => write!(f, "goto {}", destination)?,
283            Self::CBranch { destination, condition } => write!(f, "goto {} if {} == 0x1", destination, condition)?,
284            Self::IBranch { destination } => write!(f, "goto [{}]", destination)?,
285
286            Self::Call { destination } => write!(f, "call {}", destination)?,
287            Self::ICall { destination } => write!(f, "call [{}]", destination)?,
288            Self::Return { destination } => write!(f, "return [{}]", destination)?,
289
290            Self::Intrinsic { name, operands, result } => {
291                if let Some(result) = result {
292                    write!(f, "{} ← ", result)?;
293                }
294                write!(f, "{}(", name.to_lowercase())?;
295                if operands.len() > 0 {
296                    write!(f, "{}", operands[0])?;
297                    for oper in &operands[1..] {
298                        write!(f, ", {}", oper)?;
299                    }
300                }
301                write!(f, ")")?;
302            },
303
304            Self::IntEq { result, operands } => write!(f, "{} ← {} == {}", result, operands[0], operands[1])?,
305            Self::IntNotEq { result, operands } => write!(f, "{} ← {} != {}", result, operands[0], operands[1])?,
306            Self::IntSLess { result, operands } => write!(f, "{} ← {} s< {}", result, operands[0], operands[1])?,
307            Self::IntSLessEq { result, operands } => write!(f, "{} ← {} s<= {}", result, operands[0], operands[1])?,
308            Self::IntLess { result, operands } => write!(f, "{} ← {} < {}", result, operands[0], operands[1])?,
309            Self::IntLessEq { result, operands } => write!(f, "{} ← {} <= {}", result, operands[0], operands[1])?,
310
311            Self::IntZExt { result, operand } => write!(f, "{} ← zext({}, {})", result, operand, result.size() * 8)?,
312            Self::IntSExt { result, operand } => write!(f, "{} ← sext({}, {})", result, operand, result.size() * 8)?,
313
314            Self::IntAdd { result, operands } => write!(f, "{} ← {} + {}", result, operands[0], operands[1])?,
315            Self::IntSub { result, operands } => write!(f, "{} ← {} - {}", result, operands[0], operands[1])?,
316            Self::IntCarry { result, operands } => write!(f, "{} ← carry({}, {})", result, operands[0], operands[1])?,
317            Self::IntSCarry { result, operands } => write!(f, "{} ← scarry({}, {})", result, operands[0], operands[1])?,
318            Self::IntSBorrow { result, operands } => write!(f, "{} ← sborrow({}, {})", result, operands[0], operands[1])?,
319
320            Self::IntNeg { result, operand } => write!(f, "{} ← -{}", result, operand)?,
321            Self::IntNot { result, operand } => write!(f, "{} ← ~{}", result, operand)?,
322
323            Self::IntXor { result, operands } => write!(f, "{} ← {} ^ {}", result, operands[0], operands[1])?,
324            Self::IntAnd { result, operands } => write!(f, "{} ← {} & {}", result, operands[0], operands[1])?,
325            Self::IntOr { result, operands } => write!(f, "{} ← {} | {}", result, operands[0], operands[1])?,
326            Self::IntLeftShift { result, operands } => write!(f, "{} ← {} << {}", result, operands[0], operands[1])?,
327            Self::IntRightShift { result, operands } => write!(f, "{} ← {} >> {}", result, operands[0], operands[1])?,
328            Self::IntSRightShift { result, operands } => write!(f, "{} ← {} s>> {}", result, operands[0], operands[1])?,
329
330            Self::IntMul { result, operands } => write!(f, "{} ← {} * {}", result, operands[0], operands[1])?,
331            Self::IntDiv { result, operands } => write!(f, "{} ← {} / {}", result, operands[0], operands[1])?,
332            Self::IntSDiv { result, operands } => write!(f, "{} ← {} s/ {}", result, operands[0], operands[1])?,
333            Self::IntRem { result, operands } => write!(f, "{} ← {} % {}", result, operands[0], operands[1])?,
334            Self::IntSRem { result, operands } => write!(f, "{} ← {} s% {}", result, operands[0], operands[1])?,
335
336            Self::BoolNot { result, operand } => write!(f, "{} ← !{}", result, operand)?,
337            Self::BoolXor { result, operands } => write!(f, "{} ← {} ^ {}", result, operands[0], operands[1])?,
338            Self::BoolAnd { result, operands } => write!(f, "{} ← {} & {}", result, operands[0], operands[1])?,
339            Self::BoolOr { result, operands } => write!(f, "{} ← {} | {}", result, operands[0], operands[1])?,
340
341            Self::FloatEq { result, operands } => write!(f, "{} ← {} f== {}", result, operands[0], operands[1])?,
342            Self::FloatNotEq { result, operands } => write!(f, "{} ← {} f!= {}", result, operands[0], operands[1])?,
343            Self::FloatLess { result, operands } => write!(f, "{} ← {} f< {}", result, operands[0], operands[1])?,
344            Self::FloatLessEq { result, operands } => write!(f, "{} ← {} f<= {}", result, operands[0], operands[1])?,
345
346            Self::FloatIsNaN { result, operand } => write!(f, "{} ← nan({})", result, operand)?,
347
348            Self::FloatAdd { result, operands } => write!(f, "{} ← {} f+ {}", result, operands[0], operands[1])?,
349            Self::FloatDiv { result, operands } => write!(f, "{} ← {} f/ {}", result, operands[0], operands[1])?,
350            Self::FloatMul { result, operands } => write!(f, "{} ← {} f* {}", result, operands[0], operands[1])?,
351            Self::FloatSub { result, operands } => write!(f, "{} ← {} f- {}", result, operands[0], operands[1])?,
352
353            Self::FloatNeg { result, operand } => write!(f, "{} ← f-{}", result, operand)?,
354            Self::FloatAbs { result, operand } => write!(f, "{} ← abs({})", result, operand)?,
355            Self::FloatSqrt { result, operand } => write!(f, "{} ← sqrt({})", result, operand)?,
356
357            Self::FloatOfInt { result, operand } => write!(f, "{} ← float-of-int{}({})", result.size() * 8, result, operand)?,
358            Self::FloatOfFloat { result, operand } => write!(f, "{} ← float-of-float{}({})", result.size() * 8, result, operand)?,
359            Self::FloatTruncate { result, operand } => write!(f, "{} ← truncate({}, {})", result, operand, result.size() * 8)?,
360            Self::FloatCeiling { result, operand } => write!(f, "{} ← ceiling({})", result, operand)?,
361            Self::FloatFloor { result, operand } => write!(f, "{} ← floor({})", result, operand)?,
362            Self::FloatRound { result, operand } => write!(f, "{} ← round({})", result, operand)?,
363
364            Self::Subpiece { result, operand, amount } => write!(f, "{} ← subpiece({}, {})", result, operand, amount)?,
365            Self::PopCount { result, operand } => write!(f, "{} ← popcount({})", result, operand)?,
366            Self::Skip => write!(f, "skip")?,
367        }
368        Ok(())
369    }
370}
371
372impl PCodeOp {
373    pub(crate) fn from_parts<I: ExactSizeIterator<Item=VarnodeData>>(
374        manager: &SpaceManager,
375        registers: &RegisterNames,
376        user_ops: &[UserOpStr],
377        opcode: Opcode,
378        inputs: I,
379        output: Option<VarnodeData>,
380    ) -> Self {
381        let mut inputs = inputs.into_iter();
382
383        if cfg!(feature = "extra-logging") {
384            log::trace!("lifting opcode {opcode:?}");
385        }
386
387        unsafe { match opcode {
388            Opcode::Copy => PCodeOp::Copy {
389                destination: Operand::from_varnodedata(manager, registers, output.unsafe_unwrap()),
390                source: Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
391            },
392            Opcode::Load => {
393                let space = manager.spaces()[inputs.next().unsafe_unwrap().offset() as usize].id();
394                let destination = output.unsafe_unwrap();
395                let source = inputs.next().unsafe_unwrap();
396
397                PCodeOp::Load {
398                    destination: Operand::from_varnodedata(manager, registers, destination),
399                    source: Operand::from_varnodedata(manager, registers, source),
400                    space,
401                }
402            },
403            Opcode::Store => {
404                let space = manager.spaces()[inputs.next().unsafe_unwrap().offset() as usize].id();
405                let destination = inputs.next().unsafe_unwrap();
406                let source = inputs.next().unsafe_unwrap();
407
408                PCodeOp::Store {
409                    destination: Operand::from_varnodedata(manager, registers, destination),
410                    source: Operand::from_varnodedata(manager, registers, source),
411                    space,
412                }
413            },
414            Opcode::Branch => PCodeOp::Branch {
415                destination: Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
416            },
417            Opcode::CBranch => PCodeOp::CBranch {
418                destination: Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
419                condition: Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
420            },
421            Opcode::IBranch => PCodeOp::IBranch {
422                destination: Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
423            },
424            Opcode::Call => PCodeOp::Call {
425                destination: Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
426            },
427            Opcode::ICall => PCodeOp::ICall {
428                destination: Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
429            },
430            Opcode::CallOther => {
431                let name = user_ops[inputs.next().unsafe_unwrap().offset() as usize].clone();
432                let result = output.map(|output| Operand::from_varnodedata(manager, registers, output));
433
434                let mut operands = SmallVec::with_capacity(inputs.len());
435                operands.extend(inputs.into_iter().map(|vnd| Operand::from_varnodedata(manager, registers, vnd)));
436
437                PCodeOp::Intrinsic {
438                    name,
439                    operands,
440                    result,
441                }
442            },
443            Opcode::Return => PCodeOp::Return {
444                destination: Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
445            },
446            Opcode::Subpiece => PCodeOp::Subpiece {
447                operand: Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
448                amount: Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
449                result: Operand::from_varnodedata(manager, registers, output.unsafe_unwrap()),
450            },
451            Opcode::PopCount => PCodeOp::PopCount {
452                operand: Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
453                result: Operand::from_varnodedata(manager, registers, output.unsafe_unwrap()),
454            },
455            Opcode::BoolNot => PCodeOp::BoolNot {
456                operand: Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
457                result: Operand::from_varnodedata(manager, registers, output.unsafe_unwrap()),
458            },
459            Opcode::BoolAnd => PCodeOp::BoolAnd {
460                operands: [
461                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
462                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
463                ],
464                result: Operand::from_varnodedata(manager, registers, output.unsafe_unwrap()),
465            },
466            Opcode::BoolOr => PCodeOp::BoolOr {
467                operands: [
468                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
469                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
470                ],
471                result: Operand::from_varnodedata(manager, registers, output.unsafe_unwrap()),
472            },
473            Opcode::BoolXor => PCodeOp::BoolXor {
474                operands: [
475                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
476                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
477                ],
478                result: Operand::from_varnodedata(manager, registers, output.unsafe_unwrap()),
479            },
480            Opcode::IntNeg => PCodeOp::IntNeg {
481                operand: Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
482                result: Operand::from_varnodedata(manager, registers, output.unsafe_unwrap()),
483            },
484            Opcode::IntNot => PCodeOp::IntNot {
485                operand: Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
486                result: Operand::from_varnodedata(manager, registers, output.unsafe_unwrap()),
487            },
488            Opcode::IntSExt => PCodeOp::IntSExt {
489                operand: Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
490                result: Operand::from_varnodedata(manager, registers, output.unsafe_unwrap()),
491            },
492            Opcode::IntZExt => PCodeOp::IntZExt {
493                operand: Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
494                result: Operand::from_varnodedata(manager, registers, output.unsafe_unwrap()),
495            },
496            Opcode::IntEq => PCodeOp::IntEq {
497                operands: [
498                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
499                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
500                ],
501                result: Operand::from_varnodedata(manager, registers, output.unsafe_unwrap()),
502            },
503            Opcode::IntNotEq => PCodeOp::IntNotEq {
504                operands: [
505                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
506                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
507                ],
508                result: Operand::from_varnodedata(manager, registers, output.unsafe_unwrap()),
509            },
510            Opcode::IntLess => PCodeOp::IntLess {
511                operands: [
512                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
513                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
514                ],
515                result: Operand::from_varnodedata(manager, registers, output.unsafe_unwrap()),
516            },
517            Opcode::IntLessEq => PCodeOp::IntLessEq {
518                operands: [
519                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
520                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
521                ],
522                result: Operand::from_varnodedata(manager, registers, output.unsafe_unwrap()),
523            },
524            Opcode::IntSLess => PCodeOp::IntSLess {
525                operands: [
526                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
527                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
528                ],
529                result: Operand::from_varnodedata(manager, registers, output.unsafe_unwrap()),
530            },
531            Opcode::IntSLessEq => PCodeOp::IntSLessEq {
532                operands: [
533                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
534                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
535                ],
536                result: Operand::from_varnodedata(manager, registers, output.unsafe_unwrap()),
537            },
538            Opcode::IntCarry => PCodeOp::IntCarry {
539                operands: [
540                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
541                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
542                ],
543                result: Operand::from_varnodedata(manager, registers, output.unsafe_unwrap()),
544            },
545            Opcode::IntSCarry => PCodeOp::IntSCarry {
546                operands: [
547                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
548                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
549                ],
550                result: Operand::from_varnodedata(manager, registers, output.unsafe_unwrap()),
551            },
552            Opcode::IntSBorrow => PCodeOp::IntSBorrow {
553                operands: [
554                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
555                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
556                ],
557                result: Operand::from_varnodedata(manager, registers, output.unsafe_unwrap()),
558            },
559            Opcode::IntAdd => PCodeOp::IntAdd {
560                operands: [
561                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
562                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
563                ],
564                result: Operand::from_varnodedata(manager, registers, output.unsafe_unwrap()),
565            },
566            Opcode::IntSub => PCodeOp::IntSub {
567                operands: [
568                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
569                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
570                ],
571                result: Operand::from_varnodedata(manager, registers, output.unsafe_unwrap()),
572            },
573            Opcode::IntDiv => PCodeOp::IntDiv {
574                operands: [
575                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
576                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
577                ],
578                result: Operand::from_varnodedata(manager, registers, output.unsafe_unwrap()),
579            },
580            Opcode::IntSDiv => PCodeOp::IntSDiv {
581                operands: [
582                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
583                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
584                ],
585                result: Operand::from_varnodedata(manager, registers, output.unsafe_unwrap()),
586            },
587            Opcode::IntMul => PCodeOp::IntMul {
588                operands: [
589                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
590                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
591                ],
592                result: Operand::from_varnodedata(manager, registers, output.unsafe_unwrap()),
593            },
594            Opcode::IntRem => PCodeOp::IntRem {
595                operands: [
596                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
597                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
598                ],
599                result: Operand::from_varnodedata(manager, registers, output.unsafe_unwrap()),
600            },
601            Opcode::IntSRem => PCodeOp::IntSRem {
602                operands: [
603                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
604                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
605                ],
606                result: Operand::from_varnodedata(manager, registers, output.unsafe_unwrap()),
607            },
608            Opcode::IntLShift => PCodeOp::IntLeftShift {
609                operands: [
610                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
611                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
612                ],
613                result: Operand::from_varnodedata(manager, registers, output.unsafe_unwrap()),
614            },
615            Opcode::IntRShift => PCodeOp::IntRightShift {
616                operands: [
617                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
618                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
619                ],
620                result: Operand::from_varnodedata(manager, registers, output.unsafe_unwrap()),
621            },
622            Opcode::IntSRShift => PCodeOp::IntSRightShift {
623                operands: [
624                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
625                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
626                ],
627                result: Operand::from_varnodedata(manager, registers, output.unsafe_unwrap()),
628            },
629            Opcode::IntAnd => PCodeOp::IntAnd {
630                operands: [
631                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
632                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
633                ],
634                result: Operand::from_varnodedata(manager, registers, output.unsafe_unwrap()),
635            },
636            Opcode::IntOr => PCodeOp::IntOr {
637                operands: [
638                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
639                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
640                ],
641                result: Operand::from_varnodedata(manager, registers, output.unsafe_unwrap()),
642            },
643            Opcode::IntXor => PCodeOp::IntXor {
644                operands: [
645                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
646                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
647                ],
648                result: Operand::from_varnodedata(manager, registers, output.unsafe_unwrap()),
649            },
650            Opcode::FloatIsNaN => PCodeOp::FloatIsNaN {
651                operand: Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
652                result: Operand::from_varnodedata(manager, registers, output.unsafe_unwrap()),
653            },
654            Opcode::FloatAbs => PCodeOp::FloatAbs {
655                operand: Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
656                result: Operand::from_varnodedata(manager, registers, output.unsafe_unwrap()),
657            },
658            Opcode::FloatNeg => PCodeOp::FloatNeg {
659                operand: Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
660                result: Operand::from_varnodedata(manager, registers, output.unsafe_unwrap()),
661            },
662            Opcode::FloatSqrt => PCodeOp::FloatSqrt {
663                operand: Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
664                result: Operand::from_varnodedata(manager, registers, output.unsafe_unwrap()),
665            },
666            Opcode::FloatFloor => PCodeOp::FloatFloor {
667                operand: Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
668                result: Operand::from_varnodedata(manager, registers, output.unsafe_unwrap()),
669            },
670            Opcode::FloatCeiling => PCodeOp::FloatCeiling {
671                operand: Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
672                result: Operand::from_varnodedata(manager, registers, output.unsafe_unwrap()),
673            },
674            Opcode::FloatRound => PCodeOp::FloatRound {
675                operand: Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
676                result: Operand::from_varnodedata(manager, registers, output.unsafe_unwrap()),
677            },
678            Opcode::FloatEq => PCodeOp::FloatEq {
679                operands: [
680                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
681                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
682                ],
683                result: Operand::from_varnodedata(manager, registers, output.unsafe_unwrap()),
684            },
685            Opcode::FloatNotEq => PCodeOp::FloatNotEq {
686                operands: [
687                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
688                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
689                ],
690                result: Operand::from_varnodedata(manager, registers, output.unsafe_unwrap()),
691            },
692            Opcode::FloatLess => PCodeOp::FloatLess {
693                operands: [
694                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
695                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
696                ],
697                result: Operand::from_varnodedata(manager, registers, output.unsafe_unwrap()),
698            },
699            Opcode::FloatLessEq => PCodeOp::FloatLessEq {
700                operands: [
701                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
702                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
703                ],
704                result: Operand::from_varnodedata(manager, registers, output.unsafe_unwrap()),
705            },
706            Opcode::FloatAdd => PCodeOp::FloatAdd {
707                operands: [
708                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
709                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
710                ],
711                result: Operand::from_varnodedata(manager, registers, output.unsafe_unwrap()),
712            },
713            Opcode::FloatSub => PCodeOp::FloatSub {
714                operands: [
715                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
716                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
717                ],
718                result: Operand::from_varnodedata(manager, registers, output.unsafe_unwrap()),
719            },
720            Opcode::FloatDiv => PCodeOp::FloatDiv {
721                operands: [
722                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
723                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
724                ],
725                result: Operand::from_varnodedata(manager, registers, output.unsafe_unwrap()),
726            },
727            Opcode::FloatMul => PCodeOp::FloatMul {
728                operands: [
729                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
730                    Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
731                ],
732                result: Operand::from_varnodedata(manager, registers, output.unsafe_unwrap()),
733            },
734            Opcode::FloatOfFloat => PCodeOp::FloatOfFloat {
735                operand: Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
736                result: Operand::from_varnodedata(manager, registers, output.unsafe_unwrap()),
737            },
738            Opcode::FloatOfInt => PCodeOp::FloatOfInt {
739                operand: Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
740                result: Operand::from_varnodedata(manager, registers, output.unsafe_unwrap()),
741            },
742            Opcode::FloatTruncate => PCodeOp::FloatTruncate {
743                operand: Operand::from_varnodedata(manager, registers, inputs.next().unsafe_unwrap()),
744                result: Operand::from_varnodedata(manager, registers, output.unsafe_unwrap()),
745            },
746            Opcode::Label => PCodeOp::Skip,
747            Opcode::Build
748            | Opcode::CrossBuild
749            | Opcode::CPoolRef
750            | Opcode::Piece
751            | Opcode::Extract
752            | Opcode::DelaySlot
753            | Opcode::New
754            | Opcode::Insert
755            | Opcode::Cast
756            | Opcode::SegmentOp => {
757                panic!("{:?} unimplemented due to spec", opcode)
758            }
759        } }
760    }
761
762    pub fn skip() -> Self {
763        PCodeOp::Skip
764    }
765}
766
767#[derive(Debug, Clone)]
768#[derive(serde::Deserialize, serde::Serialize)]
769pub struct PCode {
770    pub address: AddressValue,
771    pub operations: SmallVec<[PCodeOp; 8]>,
772    pub delay_slots: usize,
773    pub length: usize,
774}
775
776impl PCode {
777    pub fn nop(address: AddressValue, length: usize) -> Self {
778        Self {
779            address,
780            operations: SmallVec::new(),
781            delay_slots: 0,
782            length,
783        }
784    }
785
786    pub fn address(&self) -> AddressValue {
787        self.address.clone()
788    }
789
790    pub fn operations(&self) -> &[PCodeOp] {
791        self.operations.as_ref()
792    }
793
794    pub fn delay_slots(&self) -> usize {
795        self.delay_slots
796    }
797
798    pub fn length(&self) -> usize {
799        self.length
800    }
801
802    pub fn display<'pcode>(&'pcode self) -> PCodeFormatter<'pcode> {
803        PCodeFormatter { pcode: self }
804    }
805}
806
807pub struct PCodeFormatter<'pcode> {
808    pcode: &'pcode PCode,
809}
810
811impl<'pcode> fmt::Display for PCodeFormatter<'pcode> {
812    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
813        let len =  self.pcode.operations.len();
814        if len > 0 {
815            for (i, op) in self.pcode.operations.iter().enumerate() {
816                write!(f, "{}.{:02}: {}{}", self.pcode.address, i,
817                       op,
818                       if i == len - 1 { "" } else { "\n" })?;
819            }
820            Ok(())
821        } else {
822            write!(f, "{}.00: skip", self.pcode.address)
823        }
824    }
825}