1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
use crate::emulate::*;
use crate::jxx::*;
use crate::single_operand::*;
use crate::two_operand::*;

use std::fmt;

/// A container that holds all types of instructions (including emulated)
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Instruction {
    // single operand instructions
    Rrc(Rrc),
    Swpb(Swpb),
    Rra(Rra),
    Sxt(Sxt),
    Push(Push),
    Call(Call),
    Reti(Reti),

    // Jxx instructions
    Jnz(Jnz),
    Jz(Jz),
    Jlo(Jlo),
    Jc(Jc),
    Jn(Jn),
    Jge(Jge),
    Jl(Jl),
    Jmp(Jmp),

    // two operand instructions
    Mov(Mov),
    Add(Add),
    Addc(Addc),
    Subc(Subc),
    Sub(Sub),
    Cmp(Cmp),
    Dadd(Dadd),
    Bit(Bit),
    Bic(Bic),
    Bis(Bis),
    Xor(Xor),
    And(And),

    // emulated
    Adc(Adc),
    Br(Br),
    Clr(Clr),
    Clrc(Clrc),
    Clrn(Clrn),
    Clrz(Clrz),
    Dadc(Dadc),
    Dec(Dec),
    Decd(Decd),
    Dint(Dint),
    Eint(Eint),
    Inc(Inc),
    Incd(Incd),
    Inv(Inv),
    Nop(Nop),
    Pop(Pop),
    Ret(Ret),
    Rla(Rla),
    Rlc(Rlc),
    Sbc(Sbc),
    Setc(Setc),
    Setn(Setn),
    Setz(Setz),
    Tst(Tst),
}

impl Instruction {
    pub fn size(&self) -> usize {
        match self {
            Self::Rrc(inst) => inst.size(),
            Self::Swpb(inst) => inst.size(),
            Self::Rra(inst) => inst.size(),
            Self::Sxt(inst) => inst.size(),
            Self::Push(inst) => inst.size(),
            Self::Call(inst) => inst.size(),
            Self::Reti(inst) => inst.size(),
            Self::Jnz(inst) => inst.size(),
            Self::Jz(inst) => inst.size(),
            Self::Jlo(inst) => inst.size(),
            Self::Jc(inst) => inst.size(),
            Self::Jn(inst) => inst.size(),
            Self::Jge(inst) => inst.size(),
            Self::Jl(inst) => inst.size(),
            Self::Jmp(inst) => inst.size(),
            Self::Mov(inst) => inst.size(),
            Self::Add(inst) => inst.size(),
            Self::Addc(inst) => inst.size(),
            Self::Subc(inst) => inst.size(),
            Self::Sub(inst) => inst.size(),
            Self::Cmp(inst) => inst.size(),
            Self::Dadd(inst) => inst.size(),
            Self::Bit(inst) => inst.size(),
            Self::Bic(inst) => inst.size(),
            Self::Bis(inst) => inst.size(),
            Self::Xor(inst) => inst.size(),
            Self::And(inst) => inst.size(),
            Self::Adc(inst) => inst.size(),
            Self::Br(inst) => inst.size(),
            Self::Clr(inst) => inst.size(),
            Self::Clrc(inst) => inst.size(),
            Self::Clrn(inst) => inst.size(),
            Self::Clrz(inst) => inst.size(),
            Self::Dadc(inst) => inst.size(),
            Self::Dec(inst) => inst.size(),
            Self::Decd(inst) => inst.size(),
            Self::Dint(inst) => inst.size(),
            Self::Eint(inst) => inst.size(),
            Self::Inc(inst) => inst.size(),
            Self::Incd(inst) => inst.size(),
            Self::Inv(inst) => inst.size(),
            Self::Nop(inst) => inst.size(),
            Self::Pop(inst) => inst.size(),
            Self::Ret(inst) => inst.size(),
            Self::Rla(inst) => inst.size(),
            Self::Rlc(inst) => inst.size(),
            Self::Sbc(inst) => inst.size(),
            Self::Setc(inst) => inst.size(),
            Self::Setn(inst) => inst.size(),
            Self::Setz(inst) => inst.size(),
            Self::Tst(inst) => inst.size(),
        }
    }
}

impl fmt::Display for Instruction {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Self::Rrc(inst) => write!(f, "{}", inst),
            Self::Swpb(inst) => write!(f, "{}", inst),
            Self::Rra(inst) => write!(f, "{}", inst),
            Self::Sxt(inst) => write!(f, "{}", inst),
            Self::Push(inst) => write!(f, "{}", inst),
            Self::Call(inst) => write!(f, "{}", inst),
            Self::Reti(inst) => write!(f, "{}", inst),
            Self::Jnz(inst) => write!(f, "{}", inst),
            Self::Jz(inst) => write!(f, "{}", inst),
            Self::Jlo(inst) => write!(f, "{}", inst),
            Self::Jc(inst) => write!(f, "{}", inst),
            Self::Jn(inst) => write!(f, "{}", inst),
            Self::Jge(inst) => write!(f, "{}", inst),
            Self::Jl(inst) => write!(f, "{}", inst),
            Self::Jmp(inst) => write!(f, "{}", inst),
            Self::Mov(inst) => write!(f, "{}", inst),
            Self::Add(inst) => write!(f, "{}", inst),
            Self::Addc(inst) => write!(f, "{}", inst),
            Self::Subc(inst) => write!(f, "{}", inst),
            Self::Sub(inst) => write!(f, "{}", inst),
            Self::Cmp(inst) => write!(f, "{}", inst),
            Self::Dadd(inst) => write!(f, "{}", inst),
            Self::Bit(inst) => write!(f, "{}", inst),
            Self::Bic(inst) => write!(f, "{}", inst),
            Self::Bis(inst) => write!(f, "{}", inst),
            Self::Xor(inst) => write!(f, "{}", inst),
            Self::And(inst) => write!(f, "{}", inst),
            Self::Adc(inst) => write!(f, "{}", inst),
            Self::Br(inst) => write!(f, "{}", inst),
            Self::Clr(inst) => write!(f, "{}", inst),
            Self::Clrc(inst) => write!(f, "{}", inst),
            Self::Clrn(inst) => write!(f, "{}", inst),
            Self::Clrz(inst) => write!(f, "{}", inst),
            Self::Dadc(inst) => write!(f, "{}", inst),
            Self::Dec(inst) => write!(f, "{}", inst),
            Self::Decd(inst) => write!(f, "{}", inst),
            Self::Dint(inst) => write!(f, "{}", inst),
            Self::Eint(inst) => write!(f, "{}", inst),
            Self::Inc(inst) => write!(f, "{}", inst),
            Self::Incd(inst) => write!(f, "{}", inst),
            Self::Inv(inst) => write!(f, "{}", inst),
            Self::Nop(inst) => write!(f, "{}", inst),
            Self::Pop(inst) => write!(f, "{}", inst),
            Self::Ret(inst) => write!(f, "{}", inst),
            Self::Rla(inst) => write!(f, "{}", inst),
            Self::Rlc(inst) => write!(f, "{}", inst),
            Self::Sbc(inst) => write!(f, "{}", inst),
            Self::Setc(inst) => write!(f, "{}", inst),
            Self::Setn(inst) => write!(f, "{}", inst),
            Self::Setz(inst) => write!(f, "{}", inst),
            Self::Tst(inst) => write!(f, "{}", inst),
        }
    }
}