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<R: Reg + Encode> Encode for RegSet<R> { 184 const WIDTH: u8 = 4; 185 186 fn encode<E>(&self, sink: &mut E) 187 where 188 E: Extend<u8>, 189 { 190 self.to_bitset().0.encode(sink); 191 } 192 } 193 194 macro_rules! impl_encoders { 195 ( 196 $( 197 $( #[$attr:meta] )* 198 $snake_name:ident = $name:ident $( { 199 $( 200 $( #[$field_attr:meta] )* 201 $field:ident : $field_ty:ty 202 ),* 203 } )? ; 204 )* 205 ) => { 206 $( 207 $( #[$attr] )* 208 pub fn $snake_name<E>(into: &mut E $( $( , $field : impl Into<$field_ty> )* )? ) 209 where 210 E: Extend<u8>, 211 { 212 into.extend(core::iter::once(Opcode::$name as u8)); 213 $( 214 $( 215 $field.into().encode(into); 216 )* 217 )? 218 } 219 220 impl Encode for crate::op::$name { 221 const WIDTH: u8 = 1 $($( + <$field_ty as Encode>::WIDTH)*)?; 222 223 fn encode<E>(&self, sink: &mut E) 224 where 225 E: Extend<u8>, 226 { 227 let Self { $( $( $field ),* )? } = *self; 228 $snake_name(sink $( $(, $field)* )?) 229 } 230 } 231 )* 232 }; 233 } 234 for_each_op!(impl_encoders); 235 236 macro_rules! impl_extended_encoders { 237 ( 238 $( 239 $( #[$attr:meta] )* 240 $snake_name:ident = $name:ident $( { 241 $( 242 $( #[$field_attr:meta] )* 243 $field:ident : $field_ty:ty 244 ),* 245 } )? ; 246 )* 247 ) => { 248 $( 249 $( #[$attr] )* 250 pub fn $snake_name<E>(into: &mut E $( $( , $field : impl Into<$field_ty> )* )? ) 251 where 252 E: Extend<u8>, 253 { 254 into.extend(core::iter::once(Opcode::ExtendedOp as u8)); 255 into.extend((ExtendedOpcode::$name as u16).to_le_bytes()); 256 $( 257 $( 258 $field.into().encode(into); 259 )* 260 )? 261 } 262 263 impl Encode for crate::op::$name { 264 const WIDTH: u8 = 3 $($( + <$field_ty as Encode>::WIDTH)*)?; 265 266 fn encode<E>(&self, sink: &mut E) 267 where 268 E: Extend<u8>, 269 { 270 let Self { $( $( $field ),* )? } = *self; 271 $snake_name(sink $( $(, $field)* )?) 272 } 273 } 274 )* 275 }; 276 } 277 for_each_extended_op!(impl_extended_encoders); 278