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