1use derive_more::Display;
4
5use super::Instruction;
6use crate::opcode::{Mnemonic, OpCode};
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Display)]
10#[display("{}", self.opcode())]
11pub struct Pop;
12
13impl Instruction for Pop {
14 fn opcode(&self) -> OpCode {
15 OpCode::Known(Mnemonic::POP)
16 }
17}
18
19#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Display)]
22#[display("{}", self.opcode())]
23pub struct Push<const N: usize>([u8; N]);
24
25impl<const N: usize> Push<N> {
26 const VALID: () = assert!(N <= 32, "immediate value size cannot be greater than 32");
28
29 #[must_use]
44 pub const fn new(immediate: [u8; N]) -> Self {
45 () = Self::VALID;
47 Self(immediate)
48 }
49
50 #[must_use]
59 pub const fn immediate(&self) -> &[u8; N] {
60 &self.0
61 }
62
63 #[must_use]
73 #[expect(
74 clippy::cast_possible_truncation,
75 reason = "N cannot be greater than 32"
76 )]
77 pub const fn size(&self) -> u8 {
78 N as u8
80 }
81}
82
83impl<const N: usize> Instruction for Push<N> {
84 fn opcode(&self) -> OpCode {
85 match N {
86 0 => OpCode::Known(Mnemonic::PUSH0),
87 1 => OpCode::Known(Mnemonic::PUSH1),
88 2 => OpCode::Known(Mnemonic::PUSH2),
89 3 => OpCode::Known(Mnemonic::PUSH3),
90 4 => OpCode::Known(Mnemonic::PUSH4),
91 5 => OpCode::Known(Mnemonic::PUSH5),
92 6 => OpCode::Known(Mnemonic::PUSH6),
93 7 => OpCode::Known(Mnemonic::PUSH7),
94 8 => OpCode::Known(Mnemonic::PUSH8),
95 9 => OpCode::Known(Mnemonic::PUSH9),
96 10 => OpCode::Known(Mnemonic::PUSH10),
97 11 => OpCode::Known(Mnemonic::PUSH11),
98 12 => OpCode::Known(Mnemonic::PUSH12),
99 13 => OpCode::Known(Mnemonic::PUSH13),
100 14 => OpCode::Known(Mnemonic::PUSH14),
101 15 => OpCode::Known(Mnemonic::PUSH15),
102 16 => OpCode::Known(Mnemonic::PUSH16),
103 17 => OpCode::Known(Mnemonic::PUSH17),
104 18 => OpCode::Known(Mnemonic::PUSH18),
105 19 => OpCode::Known(Mnemonic::PUSH19),
106 20 => OpCode::Known(Mnemonic::PUSH20),
107 21 => OpCode::Known(Mnemonic::PUSH21),
108 22 => OpCode::Known(Mnemonic::PUSH22),
109 23 => OpCode::Known(Mnemonic::PUSH23),
110 24 => OpCode::Known(Mnemonic::PUSH24),
111 25 => OpCode::Known(Mnemonic::PUSH25),
112 26 => OpCode::Known(Mnemonic::PUSH26),
113 27 => OpCode::Known(Mnemonic::PUSH27),
114 28 => OpCode::Known(Mnemonic::PUSH28),
115 29 => OpCode::Known(Mnemonic::PUSH29),
116 30 => OpCode::Known(Mnemonic::PUSH30),
117 31 => OpCode::Known(Mnemonic::PUSH31),
118 32 => OpCode::Known(Mnemonic::PUSH32),
119 _ => unreachable!(),
120 }
121 }
122}
123
124#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Display)]
127#[display("{}", self.opcode())]
128pub struct Dup<const N: u8> {
129 _private: (),
131}
132
133impl<const N: u8> Dup<N> {
134 const VALID: () = assert!(N >= 1 && N <= 16, "invalid DUP instruction");
136
137 #[must_use]
152 pub const fn new() -> Self {
153 () = Self::VALID;
154 Self { _private: () }
155 }
156}
157
158impl<const N: u8> Default for Dup<N> {
159 fn default() -> Self {
160 Self::new()
161 }
162}
163
164impl<const N: u8> Instruction for Dup<N> {
165 fn opcode(&self) -> OpCode {
166 match N {
167 1 => OpCode::Known(Mnemonic::DUP1),
168 2 => OpCode::Known(Mnemonic::DUP2),
169 3 => OpCode::Known(Mnemonic::DUP3),
170 4 => OpCode::Known(Mnemonic::DUP4),
171 5 => OpCode::Known(Mnemonic::DUP5),
172 6 => OpCode::Known(Mnemonic::DUP6),
173 7 => OpCode::Known(Mnemonic::DUP7),
174 8 => OpCode::Known(Mnemonic::DUP8),
175 9 => OpCode::Known(Mnemonic::DUP9),
176 10 => OpCode::Known(Mnemonic::DUP10),
177 11 => OpCode::Known(Mnemonic::DUP11),
178 12 => OpCode::Known(Mnemonic::DUP12),
179 13 => OpCode::Known(Mnemonic::DUP13),
180 14 => OpCode::Known(Mnemonic::DUP14),
181 15 => OpCode::Known(Mnemonic::DUP15),
182 16 => OpCode::Known(Mnemonic::DUP16),
183 _ => unreachable!(),
184 }
185 }
186}
187
188#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Display)]
191#[display("{}", self.opcode())]
192pub struct Swap<const N: u8> {
193 _private: (),
195}
196
197impl<const N: u8> Swap<N> {
198 const VALID: () = assert!(N >= 1 && N <= 16, "invalid SWAP instruction");
200
201 #[must_use]
216 pub const fn new() -> Self {
217 () = Self::VALID;
218 Self { _private: () }
219 }
220}
221
222impl<const N: u8> Default for Swap<N> {
223 fn default() -> Self {
224 Self::new()
225 }
226}
227
228impl<const N: u8> Instruction for Swap<N> {
229 fn opcode(&self) -> OpCode {
230 match N {
231 1 => OpCode::Known(Mnemonic::SWAP1),
232 2 => OpCode::Known(Mnemonic::SWAP2),
233 3 => OpCode::Known(Mnemonic::SWAP3),
234 4 => OpCode::Known(Mnemonic::SWAP4),
235 5 => OpCode::Known(Mnemonic::SWAP5),
236 6 => OpCode::Known(Mnemonic::SWAP6),
237 7 => OpCode::Known(Mnemonic::SWAP7),
238 8 => OpCode::Known(Mnemonic::SWAP8),
239 9 => OpCode::Known(Mnemonic::SWAP9),
240 10 => OpCode::Known(Mnemonic::SWAP10),
241 11 => OpCode::Known(Mnemonic::SWAP11),
242 12 => OpCode::Known(Mnemonic::SWAP12),
243 13 => OpCode::Known(Mnemonic::SWAP13),
244 14 => OpCode::Known(Mnemonic::SWAP14),
245 15 => OpCode::Known(Mnemonic::SWAP15),
246 16 => OpCode::Known(Mnemonic::SWAP16),
247 _ => panic!("invalid Swap type"),
248 }
249 }
250}
251
252#[cfg(test)]
253mod tests {
254 use super::*;
255
256 #[test]
257 fn push_sanity() {
258 let push = Push::new([1, 2, 3, 4]);
259 assert_eq!(push.size(), 4);
260 assert_eq!(push.immediate(), &[1, 2, 3, 4]);
261 assert_eq!(push.opcode(), Mnemonic::PUSH4);
262 }
263}