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 impl 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 217 impl 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 229 impl 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 240 impl 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 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")] 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