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
205macro_rules! impl_encoders {
206    (
207        $(
208            $( #[$attr:meta] )*
209                $snake_name:ident = $name:ident $( {
210                $(
211                    $( #[$field_attr:meta] )*
212                    $field:ident : $field_ty:ty
213                ),*
214            } )? ;
215        )*
216    ) => {
217        $(
218            $( #[$attr] )*
219            pub fn $snake_name<E>(into: &mut E $( $( , $field : impl Into<$field_ty> )* )? )
220            where
221                E: Extend<u8>,
222            {
223                into.extend(core::iter::once(Opcode::$name as u8));
224                $(
225                    $(
226                        $field.into().encode(into);
227                    )*
228                )?
229            }
230
231            impl Encode for crate::op::$name {
232                const WIDTH: u8 = 1 $($( + <$field_ty as Encode>::WIDTH)*)?;
233
234                fn encode<E>(&self, sink: &mut E)
235                where
236                    E: Extend<u8>,
237                {
238                    let Self { $(  $( $field ),* )? } = *self;
239                    $snake_name(sink $( $(, $field)* )?)
240                }
241            }
242        )*
243    };
244}
245for_each_op!(impl_encoders);
246
247macro_rules! impl_extended_encoders {
248    (
249        $(
250            $( #[$attr:meta] )*
251                $snake_name:ident = $name:ident $( {
252                    $(
253                        $( #[$field_attr:meta] )*
254                        $field:ident : $field_ty:ty
255                    ),*
256                } )? ;
257        )*
258    ) => {
259        $(
260            $( #[$attr] )*
261            pub fn $snake_name<E>(into: &mut E $( $( , $field : impl Into<$field_ty> )* )? )
262            where
263                E: Extend<u8>,
264            {
265                into.extend(core::iter::once(Opcode::ExtendedOp as u8));
266                into.extend((ExtendedOpcode::$name as u16).to_le_bytes());
267                $(
268                    $(
269                        $field.into().encode(into);
270                    )*
271                )?
272            }
273
274            impl Encode for crate::op::$name {
275                const WIDTH: u8 = 3 $($( + <$field_ty as Encode>::WIDTH)*)?;
276
277                fn encode<E>(&self, sink: &mut E)
278                where
279                    E: Extend<u8>,
280                {
281                    let Self { $(  $( $field ),* )? } = *self;
282                    $snake_name(sink $( $(, $field)* )?)
283                }
284            }
285        )*
286    };
287}
288for_each_extended_op!(impl_extended_encoders);