1use std::fmt;
2
3use super::opcode::Opcode;
4
5#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
12pub struct Instruction {
13 pub op: Opcode,
14 pub a: u8,
15 pub b: u8,
16 pub c: u8,
17 pub imm: i32,
18}
19
20impl Instruction {
21 pub fn new(op: Opcode, a: u8, b: u8, c: u8, imm: i32) -> Self {
22 Instruction { op, a, b, c, imm }
23 }
24
25 pub fn nullary(op: Opcode) -> Self {
26 Instruction::new(op, 0, 0, 0, 0)
27 }
28
29 pub fn abc(op: Opcode, a: u8, b: u8, c: u8) -> Self {
30 Instruction::new(op, a, b, c, 0)
31 }
32
33 pub fn a_imm(op: Opcode, a: u8, imm: i32) -> Self {
34 Instruction::new(op, a, 0, 0, imm)
35 }
36
37 pub fn only_imm(op: Opcode, imm: i32) -> Self {
38 Instruction::new(op, 0, 0, 0, imm)
39 }
40}
41
42impl fmt::Display for Instruction {
43 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
44 match self.op {
45 Opcode::Halt | Opcode::Yield | Opcode::Nop => write!(f, "{}", self.op),
46 Opcode::LoadConst => write!(f, "{} r{}, const[{}]", self.op, self.a, self.imm),
47 Opcode::Move => write!(f, "{} r{}, r{}", self.op, self.a, self.b),
48 Opcode::LoadImm => write!(f, "{} r{}, {}", self.op, self.a, self.imm),
49 Opcode::Add | Opcode::Sub | Opcode::Mul | Opcode::Div | Opcode::Mod | Opcode::Eq
50 | Opcode::Lt | Opcode::Le => {
51 write!(f, "{} r{}, r{}, r{}", self.op, self.a, self.b, self.c)
52 }
53 Opcode::Neg => write!(f, "{} r{}, r{}", self.op, self.a, self.b),
54 Opcode::Jump => write!(f, "{} {:+}", self.op, self.imm),
55 Opcode::Branch => write!(f, "{} r{}, {:+}", self.op, self.a, self.imm),
56 Opcode::Call | Opcode::CallNative => {
57 write!(f, "{} r{}, fn[{}], argc={}", self.op, self.a, self.imm, self.b)
58 }
59 Opcode::Return | Opcode::Exit | Opcode::Sleep | Opcode::Receive | Opcode::SelfPid => {
60 write!(f, "{} r{}", self.op, self.a)
61 }
62 Opcode::Spawn => write!(
63 f,
64 "{} r{}, fn[{}], argc={}",
65 self.op, self.a, self.imm, self.b
66 ),
67 Opcode::Send => write!(f, "{} r{}, r{}", self.op, self.a, self.b),
68 Opcode::ReceiveTimeout | Opcode::ReceiveMatch => {
69 write!(f, "{} r{}, r{}", self.op, self.a, self.b)
70 }
71 Opcode::ReceiveMatchImm => write!(f, "{} r{}, tag={}", self.op, self.a, self.imm),
72 Opcode::Ask => write!(
73 f,
74 "{} r{}, r{}, r{}",
75 self.op, self.a, self.b, self.c
76 ),
77 Opcode::Trap => write!(f, "{} {}", self.op, self.imm),
78 }
79 }
80}