pulley_interpreter/
encode.rs

1//! Encoding support for pulley bytecode.
2
3use crate::imms::*;
4use crate::opcode::{ExtendedOpcode, Opcode};
5use crate::regs::*;
6
7/// Helper trait to encode instructions into a "sink".
8pub trait Encode {
9    /// The encoded width of this instruction.
10    const WIDTH: u8;
11
12    /// Encodes this operand or instruction into the provided `sink`.
13    fn encode<E>(&self, sink: &mut E)
14    where
15        E: Extend<u8>;
16}
17
18impl Encode for u8 {
19    const WIDTH: u8 = 1;
20
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
29impl Encode for u16 {
30    const WIDTH: u8 = 2;
31
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
40impl Encode for u32 {
41    const WIDTH: u8 = 4;
42
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
51impl Encode for u64 {
52    const WIDTH: u8 = 8;
53
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
62impl Encode for u128 {
63    const WIDTH: u8 = 16;
64
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
73impl Encode for i8 {
74    const WIDTH: u8 = 1;
75
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
84impl Encode for i16 {
85    const WIDTH: u8 = 2;
86
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
95impl Encode for i32 {
96    const WIDTH: u8 = 4;
97
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
106impl Encode for i64 {
107    const WIDTH: u8 = 8;
108
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
117impl Encode for i128 {
118    const WIDTH: u8 = 16;
119
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
128impl Encode for XReg {
129    const WIDTH: u8 = 1;
130
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
139impl Encode for FReg {
140    const WIDTH: u8 = 1;
141
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
150impl Encode for VReg {
151    const WIDTH: u8 = 1;
152
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
161impl Encode for PcRelOffset {
162    const WIDTH: u8 = 4;
163
164    fn encode<E>(&self, sink: &mut E)
165    where
166        E: Extend<u8>,
167    {
168        i32::from(*self).encode(sink);
169    }
170}
171
172impl<D: Reg, S1: Reg, S2: Reg> Encode for BinaryOperands<D, S1, S2> {
173    const WIDTH: u8 = 2;
174
175    fn encode<E>(&self, sink: &mut E)
176    where
177        E: Extend<u8>,
178    {
179        self.to_bits().encode(sink);
180    }
181}
182
183impl<D: Reg, S1: Reg> Encode for BinaryOperands<D, S1, U6> {
184    const WIDTH: u8 = 2;
185
186    fn encode<E>(&self, sink: &mut E)
187    where
188        E: Extend<u8>,
189    {
190        self.to_bits().encode(sink);
191    }
192}
193
194impl<R: Reg + Encode> Encode for UpperRegSet<R> {
195    const WIDTH: u8 = 2;
196
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
205impl Encode for AddrO32 {
206    const WIDTH: u8 = 5;
207
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
217impl Encode for AddrZ {
218    const WIDTH: u8 = 5;
219
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
229impl Encode for AddrG32 {
230    const WIDTH: u8 = 4;
231
232    fn encode<E>(&self, sink: &mut E)
233    where
234        E: Extend<u8>,
235    {
236        self.to_bits().encode(sink);
237    }
238}
239
240impl Encode for AddrG32Bne {
241    const WIDTH: u8 = 4;
242
243    fn encode<E>(&self, sink: &mut E)
244    where
245        E: Extend<u8>,
246    {
247        self.to_bits().encode(sink);
248    }
249}
250
251macro_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}
291for_each_op!(impl_encoders);
292
293macro_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}
334for_each_extended_op!(impl_extended_encoders);