1use crate::relocations::{Relocation, RelocationSize, RelocationKind, ImpossibleRelocation, fits_signed_bitfield};
28use byteorder::{ByteOrder, LittleEndian};
29use std::convert::TryFrom;
30use crate::Register;
31
32#[derive(Debug, Clone)]
34#[allow(missing_docs)]
35pub enum RiscvRelocation {
36 B,
39 J,
42 BC,
45 JC,
48 HI20,
51 LO12,
54 LO12S,
57 SPLIT32,
60 SPLIT32S,
63 Plain(RelocationSize),
65}
66
67impl RiscvRelocation {
68 fn bitsize(&self) -> (u8, u8) {
69 match self {
70 Self::B => (12, 1),
71 Self::J => (20, 1),
72 Self::BC => (9, 1),
73 Self::JC => (12, 1),
74
75 Self::HI20 => (32, 0),
76 Self::LO12 => (32, 0),
77 Self::LO12S => (32, 0),
78
79 Self::SPLIT32 => (32, 0),
80 Self::SPLIT32S => (32, 0),
81 Self::Plain(s) => ((s.size() * 8) as u8, 0)
82 }
83 }
84}
85
86impl Relocation for RiscvRelocation {
87 type Encoding = (u8,);
88 fn from_encoding(encoding: Self::Encoding) -> Self {
89 match encoding.0 {
90 0 => Self::B,
91 1 => Self::J,
92 2 => Self::BC,
93 3 => Self::JC,
94 4 => Self::HI20,
95 5 => Self::LO12,
96 6 => Self::LO12S,
97 7 => Self::SPLIT32,
98 8 => Self::SPLIT32S,
99 x => Self::Plain(RelocationSize::from_encoding(x - 8))
100 }
101 }
102 fn from_size(size: RelocationSize) -> Self {
103 Self::Plain(size)
104 }
105 fn size(&self) -> usize {
106 match self {
107 Self::BC
108 | Self::JC => 2,
109 Self::B
110 | Self::J
111 | Self::HI20
112 | Self::LO12
113 | Self::LO12S => 4,
114 Self::SPLIT32
115 | Self::SPLIT32S => 8,
116 Self::Plain(s) => s.size(),
117 }
118 }
119 fn write_value(&self, buf: &mut [u8], value: isize) -> Result<(), ImpossibleRelocation> {
120 let value = i64::try_from(value).map_err(|_| ImpossibleRelocation { } )?;
122
123 let (bits, scaling) = self.bitsize();
124 let mask = (1i64 << scaling) - 1;
125 match self {
134 Self::HI20
135 | Self::LO12
136 | Self::LO12S
137 | Self::SPLIT32
138 | Self::SPLIT32S => {
139 if value < -0x8000_0800 || value > 0x7FFF_F7FF {
140 return Err(ImpossibleRelocation { } );
141 }
142 },
143 _ => {
144 if !fits_signed_bitfield(value, bits) || (value & mask) != 0 {
145 return Err(ImpossibleRelocation { } );
146 }
147 }
148 }
149
150 let val_cast = value as u32;
152
153 match self {
154 Self::Plain(s) => s.write_value(buf, value as isize)?,
155 Self::B => {
156 let mut instr = LittleEndian::read_u32(buf);
157 instr &= 0x01FF_F07F;
158
159 instr |= ((val_cast >> 12) & 0x1) << 31;
160 instr |= ((val_cast >> 5) & 0x3F) << 25;
161 instr |= ((val_cast >> 1) & 0xF) << 8;
162 instr |= ((val_cast >> 11) & 0x1) << 7;
163
164 LittleEndian::write_u32(buf, instr);
165 },
166 Self::J => {
167 let mut instr = LittleEndian::read_u32(buf);
168 instr &= 0x0000_0FFF;
169
170 instr |= ((val_cast >> 20) & 0x1) << 31;
171 instr |= ((val_cast >> 1) & 0x3FF) << 21;
172 instr |= ((val_cast >> 11) & 0x1) << 20;
173 instr |= ((val_cast >> 12) & 0xFF) << 12;
174
175 LittleEndian::write_u32(buf, instr);
176 },
177 Self::BC => {
178 let mut instr = LittleEndian::read_u16(buf);
179 instr &= 0xE383;
180
181 instr |= (((val_cast >> 8) & 0x1) as u16) << 12;
182 instr |= (((val_cast >> 3) & 0x3) as u16) << 10;
183 instr |= (((val_cast >> 6) & 0x3) as u16) << 5;
184 instr |= (((val_cast >> 1) & 0x3) as u16) << 3;
185 instr |= (((val_cast >> 5) & 0x1) as u16) << 2;
186
187 LittleEndian::write_u16(buf, instr);
188 },
189 Self::JC => {
190 let mut instr = LittleEndian::read_u16(buf);
191 instr &= 0xE003;
192
193 instr |= (((val_cast >> 11) & 0x1) as u16) << 12;
194 instr |= (((val_cast >> 4) & 0x1) as u16) << 11;
195 instr |= (((val_cast >> 8) & 0x3) as u16) << 9;
196 instr |= (((val_cast >> 10) & 0x1) as u16) << 8;
197 instr |= (((val_cast >> 6) & 0x1) as u16) << 7;
198 instr |= (((val_cast >> 7) & 0x1) as u16) << 6;
199 instr |= (((val_cast >> 1) & 0x7) as u16) << 3;
200 instr |= (((val_cast >> 5) & 0x1) as u16) << 2;
201
202 LittleEndian::write_u16(buf, instr);
203 },
204 Self::HI20 => {
205 let mut instr = LittleEndian::read_u32(buf);
206 instr &= 0x0000_0FFF;
207
208 let val_round: u32 = val_cast.wrapping_add(0x800);
209 instr |= val_round & 0xFFFF_F000;
210
211 LittleEndian::write_u32(buf, instr);
212 },
213 Self::LO12 => {
214 let mut instr = LittleEndian::read_u32(buf);
215 instr &= 0x000F_FFFF;
216
217 instr |= (val_cast & 0xFFF) << 20;
218
219 LittleEndian::write_u32(buf, instr);
220 },
221 Self::LO12S => {
222 let mut instr = LittleEndian::read_u32(buf);
223 instr &= 0x01FF_F07F;
224
225 instr |= (val_cast & 0x1F) << 7;
226 instr |= ((val_cast >> 5) & 0x7F) << 25;
227
228 LittleEndian::write_u32(buf, instr);
229 },
230 Self::SPLIT32 => {
231 let mut instr1 = LittleEndian::read_u32(&buf[..4]);
232 let mut instr2 = LittleEndian::read_u32(&buf[4..]);
233 instr1 &= 0x0000_0FFF;
234 instr2 &= 0x000F_FFFF;
235
236 let val_round: u32 = val_cast.wrapping_add(0x800);
237 instr1 |= val_round & 0xFFFF_F000;
238 instr2 |= (val_cast & 0xFFF) << 20;
239
240 LittleEndian::write_u32(&mut buf[..4], instr1);
241 LittleEndian::write_u32(&mut buf[4..], instr2);
242 },
243 Self::SPLIT32S => {
244 let mut instr1 = LittleEndian::read_u32(&buf[..4]);
245 let mut instr2 = LittleEndian::read_u32(&buf[4..]);
246 instr1 &= 0x0000_0FFF;
247 instr2 &= 0x01FF_F07F;
248
249 let val_round: u32 = val_cast.wrapping_add(0x800);
250 instr1 |= val_round & 0xFFFF_F000;
251 instr2 |= (val_cast & 0x1F) << 7;
252 instr2 |= ((val_cast >> 5) & 0x7F) << 25;
253
254 LittleEndian::write_u32(&mut buf[..4], instr1);
255 LittleEndian::write_u32(&mut buf[4..], instr2);
256 },
257 };
258
259 Ok(())
260 }
261 fn read_value(&self, buf: &[u8]) -> isize {
262 let bits;
263 let mut unpacked;
264
265 match self {
266 Self::Plain(s) => {
267 return s.read_value(buf)
268 },
269 Self::B => {
270 bits = 12;
271 let instr = LittleEndian::read_u32(buf);
272
273 unpacked = ((instr >> 31) & 0x1) << 12;
274 unpacked |= ((instr >> 25) & 0x3F) << 5;
275 unpacked |= ((instr >> 8) & 0xF) << 1;
276 unpacked |= ((instr >> 7) & 0x1) << 11;
277 },
278 Self::J => {
279 bits = 20;
280 let instr = LittleEndian::read_u32(buf);
281
282 unpacked = ((instr >> 31) & 0x1) << 20;
283 unpacked |= ((instr >> 21) & 0x3FF) << 1;
284 unpacked |= ((instr >> 20) & 0x1) << 11;
285 unpacked |= ((instr >> 12) & 0xFF) << 12;
286 },
287 Self::BC => {
288 bits = 9;
289 let instr = u32::from(LittleEndian::read_u16(buf));
290
291 unpacked = ((instr >> 12) & 0x1) << 8;
292 unpacked |= ((instr >> 10) & 0x3) << 3;
293 unpacked |= ((instr >> 5) & 0x3) << 6;
294 unpacked |= ((instr >> 3) & 0x3) << 1;
295 unpacked |= ((instr >> 2) & 0x1) << 5;
296 },
297 Self::JC => {
298 bits = 12;
299 let instr = u32::from(LittleEndian::read_u16(buf));
300
301 unpacked = ((instr >> 12) & 0x1) << 11;
302 unpacked |= ((instr >> 11) & 0x1) << 4;
303 unpacked |= ((instr >> 9) & 0x3) << 8;
304 unpacked |= ((instr >> 8) & 0x1) << 10;
305 unpacked |= ((instr >> 7) & 0x1) << 6;
306 unpacked |= ((instr >> 6) & 0x1) << 7;
307 unpacked |= ((instr >> 3) & 0x7) << 1;
308 unpacked |= ((instr >> 2) & 0x1) << 5;
309 },
310 Self::HI20 => {
311 bits = 32;
312 let instr = LittleEndian::read_u32(buf);
313
314 unpacked = ((instr >> 12) & 0xFFFFF) << 12;
315 },
321 Self::LO12 => {
322 bits = 12;
323 let instr = LittleEndian::read_u32(buf);
324
325 unpacked = (instr >> 20) & 0xFFF;
326 },
327 Self::LO12S => {
328 bits = 12;
329 let instr = LittleEndian::read_u32(buf);
330
331 unpacked = (instr >> 7) & 0x1F;
332 unpacked |= ((instr >> 25) & 0x7F) << 5;
333 },
334 Self::SPLIT32 => {
335 bits = 32;
336 let instr1 = LittleEndian::read_u32(&buf[..4]);
337 let instr2 = LittleEndian::read_u32(&buf[4..]);
338
339 unpacked = ((instr1 >> 12) & 0xFFFFF) << 12;
340 let mut lower: u32 = (instr2 >> 20) & 0xFFF;
341
342 lower = (lower ^ 0x800).wrapping_sub(0x800);
344 unpacked = unpacked.wrapping_add(lower)
345
346 },
347 Self::SPLIT32S => {
348 bits = 32;
349 let instr1 = LittleEndian::read_u32(&buf[..4]);
350 let instr2 = LittleEndian::read_u32(&buf[4..]);
351
352 unpacked = ((instr1 >> 12) & 0xFFFFF) << 12;
353 let mut lower: u32 = (instr2 >> 7) & 0x1F;
354 lower |= ((instr2 >> 25) & 0x7F) << 5;
355
356 lower = (lower ^ 0x800).wrapping_sub(0x800);
358 unpacked = unpacked.wrapping_add(lower)
359 },
360 }
361
362 let offset = 1u64 << (bits - 1);
364 let value: u64 = (unpacked as u64 ^ offset).wrapping_sub(offset);
365
366 value as i64 as isize
367 }
368 fn kind(&self) -> RelocationKind {
369 RelocationKind::Relative
370 }
371 fn page_size() -> usize {
372 4096
373 }
374}
375
376pub type Assembler = crate::Assembler<RiscvRelocation>;
378pub type AssemblyModifier<'a> = crate::Modifier<'a, RiscvRelocation>;
380pub type UncommittedModifier<'a> = crate::UncommittedModifier<'a>;
382
383#[inline(never)]
388pub fn immediate_out_of_range_unsigned_32(immediate: u32) -> ! {
389 panic!("Cannot assemble this RISC-V instruction. Immediate {immediate} is out of range.")
390}
391
392#[inline(never)]
394pub fn immediate_out_of_range_signed_32(immediate: i32) -> ! {
395 panic!("Cannot assemble this RISC-V instruction. Immediate {immediate} is out of range.")
396}
397#[inline(never)]
399pub fn immediate_out_of_range_unsigned_64(immediate: u64) -> ! {
400 panic!("Cannot assemble this RISC-V instruction. Immediate {immediate} is out of range.")
401}
402
403#[inline(never)]
405pub fn immediate_out_of_range_signed_64(immediate: i64) -> ! {
406 panic!("Cannot assemble this RISC-V instruction. Immediate {immediate} is out of range.")
407}
408
409#[inline(never)]
411pub fn invalid_register(register: u8) -> ! {
412 panic!("Cannot assemble this RISC-V instruction. Register x{register} cannot be encoded.")
413}
414
415
416#[allow(missing_docs)]
419#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
420pub enum RX {
421 X0 = 0x00, X1 = 0x01, X2 = 0x02, X3 = 0x03,
422 X4 = 0x04, X5 = 0x05, X6 = 0x06, X7 = 0x07,
423 X8 = 0x08, X9 = 0x09, X10= 0x0A, X11= 0x0B,
424 X12= 0x0C, X13= 0x0D, X14= 0x0E, X15= 0x0F,
425 X16= 0x10, X17= 0x11, X18= 0x12, X19= 0x13,
426 X20= 0x14, X21= 0x15, X22= 0x16, X23= 0x17,
427 X24= 0x18, X25= 0x19, X26= 0x1A, X27= 0x1B,
428 X28= 0x1C, X29= 0x1D, X30= 0x1E, X31= 0x1F,
429}
430reg_impls!(RX);
431
432#[allow(missing_docs)]
434#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
435pub enum RF {
436 F0 = 0x00, F1 = 0x01, F2 = 0x02, F3 = 0x03,
437 F4 = 0x04, F5 = 0x05, F6 = 0x06, F7 = 0x07,
438 F8 = 0x08, F9 = 0x09, F10= 0x0A, F11= 0x0B,
439 F12= 0x0C, F13= 0x0D, F14= 0x0E, F15= 0x0F,
440 F16= 0x10, F17= 0x11, F18= 0x12, F19= 0x13,
441 F20= 0x14, F21= 0x15, F22= 0x16, F23= 0x17,
442 F24= 0x18, F25= 0x19, F26= 0x1A, F27= 0x1B,
443 F28= 0x1C, F29= 0x1D, F30= 0x1E, F31= 0x1F,
444}
445reg_impls!(RF);
446
447
448#[cfg(test)]
449mod tests {
450 use super::RX::*;
451 use crate::Register;
452
453 #[test]
454 fn reg_code() {
455 assert_eq!(X2.code(), 2);
456 }
457
458 #[test]
459 fn reg_code_from() {
460 assert_eq!(u8::from(X24), 0x18);
461 }
462}