1 //! Encoding support for pulley bytecode.
2
3 use crate::imms::*;
4 use crate::opcode::{ExtendedOpcode, Opcode};
5 use crate::regs::*;
6
7 /// Helper trait to encode instructions into a "sink".
8 pub trait Encode {
9 /// The encoded width of this instruction.
10 const WIDTH: u8;
11
12 /// Encodes this operand or instruction into the provided `sink`.
encode<E>(&self, sink: &mut E) where E: Extend<u8>13 fn encode<E>(&self, sink: &mut E)
14 where
15 E: Extend<u8>;
16 }
17
18 impl Encode for u8 {
19 const WIDTH: u8 = 1;
20
encode<E>(&self, sink: &mut E) where E: Extend<u8>,21 fn encode<E>(&self, sink: &mut E)
22 where
23 E: Extend<u8>,
24 {
25 sink.extend(core::iter::once(*self));
26 }
27 }
28
29 impl Encode for u16 {
30 const WIDTH: u8 = 2;
31
encode<E>(&self, sink: &mut E) where E: Extend<u8>,32 fn encode<E>(&self, sink: &mut E)
33 where
34 E: Extend<u8>,
35 {
36 sink.extend(self.to_le_bytes());
37 }
38 }
39
40 impl Encode for u32 {
41 const WIDTH: u8 = 4;
42
encode<E>(&self, sink: &mut E) where E: Extend<u8>,43 fn encode<E>(&self, sink: &mut E)
44 where
45 E: Extend<u8>,
46 {
47 sink.extend(self.to_le_bytes());
48 }
49 }
50
51 impl Encode for u64 {
52 const WIDTH: u8 = 8;
53
encode<E>(&self, sink: &mut E) where E: Extend<u8>,54 fn encode<E>(&self, sink: &mut E)
55 where
56 E: Extend<u8>,
57 {
58 sink.extend(self.to_le_bytes());
59 }
60 }
61
62 impl Encode for u128 {
63 const WIDTH: u8 = 16;
64
encode<E>(&self, sink: &mut E) where E: Extend<u8>,65 fn encode<E>(&self, sink: &mut E)
66 where
67 E: Extend<u8>,
68 {
69 sink.extend(self.to_le_bytes());
70 }
71 }
72
73 impl Encode for i8 {
74 const WIDTH: u8 = 1;
75
encode<E>(&self, sink: &mut E) where E: Extend<u8>,76 fn encode<E>(&self, sink: &mut E)
77 where
78 E: Extend<u8>,
79 {
80 sink.extend(core::iter::once(*self as u8));
81 }
82 }
83
84 impl Encode for i16 {
85 const WIDTH: u8 = 2;
86
encode<E>(&self, sink: &mut E) where E: Extend<u8>,87 fn encode<E>(&self, sink: &mut E)
88 where
89 E: Extend<u8>,
90 {
91 sink.extend(self.to_le_bytes());
92 }
93 }
94
95 impl Encode for i32 {
96 const WIDTH: u8 = 4;
97
encode<E>(&self, sink: &mut E) where E: Extend<u8>,98 fn encode<E>(&self, sink: &mut E)
99 where
100 E: Extend<u8>,
101 {
102 sink.extend(self.to_le_bytes());
103 }
104 }
105
106 impl Encode for i64 {
107 const WIDTH: u8 = 8;
108
encode<E>(&self, sink: &mut E) where E: Extend<u8>,109 fn encode<E>(&self, sink: &mut E)
110 where
111 E: Extend<u8>,
112 {
113 sink.extend(self.to_le_bytes());
114 }
115 }
116
117 impl Encode for i128 {
118 const WIDTH: u8 = 16;
119
encode<E>(&self, sink: &mut E) where E: Extend<u8>,120 fn encode<E>(&self, sink: &mut E)
121 where
122 E: Extend<u8>,
123 {
124 sink.extend(self.to_le_bytes());
125 }
126 }
127
128 impl Encode for XReg {
129 const WIDTH: u8 = 1;
130
encode<E>(&self, sink: &mut E) where E: Extend<u8>,131 fn encode<E>(&self, sink: &mut E)
132 where
133 E: Extend<u8>,
134 {
135 sink.extend(core::iter::once(self.to_u8()));
136 }
137 }
138
139 impl Encode for FReg {
140 const WIDTH: u8 = 1;
141
encode<E>(&self, sink: &mut E) where E: Extend<u8>,142 fn encode<E>(&self, sink: &mut E)
143 where
144 E: Extend<u8>,
145 {
146 sink.extend(core::iter::once(self.to_u8()));
147 }
148 }
149
150 impl Encode for VReg {
151 const WIDTH: u8 = 1;
152
encode<E>(&self, sink: &mut E) where E: Extend<u8>,153 fn encode<E>(&self, sink: &mut E)
154 where
155 E: Extend<u8>,
156 {
157 sink.extend(core::iter::once(self.to_u8()));
158 }
159 }
160
161 impl Encode for PcRelOffset {
162 const WIDTH: u8 = 4;
163
encode<E>(&self, sink: &mut E) where E: Extend<u8>,164 fn encode<E>(&self, sink: &mut E)
165 where
166 E: Extend<u8>,
167 {
168 i32::from(*self).encode(sink);
169 }
170 }
171
172 impl<D: Reg, S1: Reg, S2: Reg> Encode for BinaryOperands<D, S1, S2> {
173 const WIDTH: u8 = 2;
174
encode<E>(&self, sink: &mut E) where E: Extend<u8>,175 fn encode<E>(&self, sink: &mut E)
176 where
177 E: Extend<u8>,
178 {
179 self.to_bits().encode(sink);
180 }
181 }
182
183 impl<D: Reg, S1: Reg> Encode for BinaryOperands<D, S1, U6> {
184 const WIDTH: u8 = 2;
185
encode<E>(&self, sink: &mut E) where E: Extend<u8>,186 fn encode<E>(&self, sink: &mut E)
187 where
188 E: Extend<u8>,
189 {
190 self.to_bits().encode(sink);
191 }
192 }
193
194 impl<R: Reg + Encode> Encode for UpperRegSet<R> {
195 const WIDTH: u8 = 2;
196
encode<E>(&self, sink: &mut E) where E: Extend<u8>,197 fn encode<E>(&self, sink: &mut E)
198 where
199 E: Extend<u8>,
200 {
201 self.to_bitset().0.encode(sink);
202 }
203 }
204
205 impl Encode for AddrO32 {
206 const WIDTH: u8 = 5;
207
encode<E>(&self, sink: &mut E) where E: Extend<u8>,208 fn encode<E>(&self, sink: &mut E)
209 where
210 E: Extend<u8>,
211 {
212 self.addr.encode(sink);
213 self.offset.encode(sink);
214 }
215 }
216
217 impl Encode for AddrZ {
218 const WIDTH: u8 = 5;
219
encode<E>(&self, sink: &mut E) where E: Extend<u8>,220 fn encode<E>(&self, sink: &mut E)
221 where
222 E: Extend<u8>,
223 {
224 self.addr.encode(sink);
225 self.offset.encode(sink);
226 }
227 }
228
229 impl Encode for AddrG32 {
230 const WIDTH: u8 = 4;
231
encode<E>(&self, sink: &mut E) where E: Extend<u8>,232 fn encode<E>(&self, sink: &mut E)
233 where
234 E: Extend<u8>,
235 {
236 self.to_bits().encode(sink);
237 }
238 }
239
240 impl Encode for AddrG32Bne {
241 const WIDTH: u8 = 4;
242
encode<E>(&self, sink: &mut E) where E: Extend<u8>,243 fn encode<E>(&self, sink: &mut E)
244 where
245 E: Extend<u8>,
246 {
247 self.to_bits().encode(sink);
248 }
249 }
250
251 macro_rules! impl_encoders {
252 (
253 $(
254 $( #[$attr:meta] )*
255 $snake_name:ident = $name:ident $( {
256 $(
257 $( #[$field_attr:meta] )*
258 $field:ident : $field_ty:ty
259 ),*
260 } )? ;
261 )*
262 ) => {
263 $(
264 $( #[$attr] )*
265 pub fn $snake_name<E>(into: &mut E $( $( , $field : impl Into<$field_ty> )* )? )
266 where
267 E: Extend<u8>,
268 {
269 into.extend(core::iter::once(Opcode::$name as u8));
270 $(
271 $(
272 $field.into().encode(into);
273 )*
274 )?
275 }
276
277 impl Encode for crate::op::$name {
278 const WIDTH: u8 = 1 $($( + <$field_ty as Encode>::WIDTH)*)?;
279
280 fn encode<E>(&self, sink: &mut E)
281 where
282 E: Extend<u8>,
283 {
284 let Self { $( $( $field ),* )? } = *self;
285 $snake_name(sink $( $(, $field)* )?)
286 }
287 }
288 )*
289 };
290 }
291 for_each_op!(impl_encoders);
292
293 macro_rules! impl_extended_encoders {
294 (
295 $(
296 $( #[$attr:meta] )*
297 $snake_name:ident = $name:ident $( {
298 $(
299 $( #[$field_attr:meta] )*
300 $field:ident : $field_ty:ty
301 ),*
302 } )? ;
303 )*
304 ) => {
305 $(
306 $( #[$attr] )*
307 pub fn $snake_name<E>(into: &mut E $( $( , $field : impl Into<$field_ty> )* )? )
308 where
309 E: Extend<u8>,
310 {
311 into.extend(core::iter::once(Opcode::ExtendedOp as u8));
312 into.extend((ExtendedOpcode::$name as u16).to_le_bytes());
313 $(
314 $(
315 $field.into().encode(into);
316 )*
317 )?
318 }
319
320 impl Encode for crate::op::$name {
321 const WIDTH: u8 = 3 $($( + <$field_ty as Encode>::WIDTH)*)?;
322
323 fn encode<E>(&self, sink: &mut E)
324 where
325 E: Extend<u8>,
326 {
327 let Self { $( $( $field ),* )? } = *self;
328 $snake_name(sink $( $(, $field)* )?)
329 }
330 }
331 )*
332 };
333 }
334 for_each_extended_op!(impl_extended_encoders);
335
336 #[test]
337 #[cfg(feature = "std")]
nop_is_single_byte()338 fn nop_is_single_byte() {
339 // NOP needs to be a single byte so that it can be used to NOP out
340 // an instruction sequence of any length.
341 let inst = crate::op::Nop {};
342 let mut bytes = vec![];
343 inst.encode(&mut bytes);
344 assert_eq!(bytes.len(), 1);
345 }
346