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}