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`. 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 macro_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 } 245 for_each_op!(impl_encoders); 246 247 macro_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 } 288 for_each_extended_op!(impl_extended_encoders); 289