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
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
#![allow(unused)]
use std::fmt;
use super::super::instruction::Instruction;
use super::super::operand::{
FromDestination, FromSource,
Register, RawRegister, Global, Immediate, ConstantKey,
WildDestination, WildSource,
};
use super::common;
#[derive(Debug, Copy, Clone)]
#[repr(u32)]
pub enum Subcode {
Jump = 0b_00_00,
Move = 0b_01_00,
Call = 0b_10_00,
Interrupt = 0b_11_00,
}
impl Subcode {
pub const OFFSET: u32 = 2;
pub const MASK: u32 = 0b_11;
}
impl From<Instruction> for Subcode {
fn from(instruction: Instruction) -> Self {
use Subcode::*;
match instruction.0 >> Self::OFFSET & Self::MASK {
0b_00 => Jump,
0b_01 => Move,
0b_10 => Call,
0b_11 => Interrupt,
_ => unreachable!(),
}
}
}
impl From<Subcode> for Instruction {
fn from(subcode: Subcode) -> Instruction {
Instruction(subcode as u32)
}
}
pub mod jump_subcode {
use super::*;
#[derive(Debug, Copy, Clone)]
#[repr(u32)]
pub enum Reason {
Special = 0b_00_0000,
Always = 0b_01_0000,
IfFalse = 0b_10_0000,
IfTrue = 0b_11_0000,
}
impl Reason {
pub const OFFSET: u32 = 4;
pub const MASK: u32 = 0b_11;
}
impl From<Instruction> for Reason {
fn from(instruction: Instruction) -> Self {
use Reason::*;
match instruction.0 >> Self::OFFSET & Self::MASK {
0b_00 => Special,
0b_01 => Always,
0b_10 => IfFalse,
0b_11 => IfTrue,
_ => unreachable!(),
}
}
}
impl fmt::Display for Reason {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use Reason::*;
match self {
Special => write!(f, "special"),
Always => write!(f, "always"),
IfFalse => write!(f, "if false"),
IfTrue => write!(f, "if true"),
}
}
}
impl From<Reason> for Instruction {
fn from(reason: Reason) -> Instruction {
Instruction(reason as u32)
}
}
#[derive(Debug, Copy, Clone)]
#[repr(u32)]
pub enum Special {
NoOp = 0b_00_000000,
Return = 0b_01_000000,
Xa = 0b_10_000000,
Xb = 0b_11_000000,
}
impl Special {
pub const OFFSET: u32 = 6;
pub const MASK: u32 = 0b_11;
}
impl From<Instruction> for Special {
fn from(instruction: Instruction) -> Self {
use Special::*;
match instruction.0 >> Self::OFFSET & Self::MASK {
0b_00 => NoOp,
0b_01 => Return,
0b_10 => Xa,
0b_11 => Xb,
_ => unreachable!(),
}
}
}
impl From<Special> for Instruction {
fn from(special: Special) -> Instruction {
Instruction(special as u32)
}
}
pub type ConditionType = common::WildDestinationType<6>;
}
pub mod move_subcode {
use super::*;
pub type DestinationType = common::WildDestinationType<4>;
pub type SourceType = common::WildSourceType<5>;
pub struct DecodedMove {
pub destination: WildDestination<RawRegister>,
pub source: WildSource<RawRegister>,
}
pub fn decode(instruction: Instruction) -> DecodedMove {
let destination_type = DestinationType::from(instruction);
let source_type = SourceType::from(instruction);
let destination: WildDestination<RawRegister> = match destination_type {
DestinationType::Register => RawRegister::from_destination(instruction).into(),
DestinationType::Global => Global::from_destination(instruction).into(),
};
let source: WildSource<RawRegister> = match source_type {
SourceType::Register => RawRegister::from_first(instruction).into(),
SourceType::Global => Global::from_first(instruction).into(),
SourceType::Immediate => Immediate::from_first(instruction).into(),
SourceType::Constant => ConstantKey::from_first(instruction).into(),
};
DecodedMove { destination, source }
}
}
pub mod call_subcode {
use super::*;
#[derive(Debug, Copy, Clone)]
#[repr(transparent)]
pub struct ArgCount(pub u8);
impl ArgCount {
pub const OFFSET: u32 = 4;
pub const MASK: u32 = 0b_1111;
}
impl From<Instruction> for ArgCount {
fn from(instruction: Instruction) -> ArgCount {
ArgCount((instruction.0 >> ArgCount::OFFSET & ArgCount::MASK) as u8)
}
}
impl From<ArgCount> for Instruction {
fn from(arg_count: ArgCount) -> Instruction {
Instruction((arg_count.0 as u32) << ArgCount::OFFSET)
}
}
}