1use crate::instruction::{BaseInstruction, Instruction};
4use crate::registers::Register;
5use core::fmt;
6
7pub mod b;
8pub mod m;
9#[cfg(test)]
10mod tests;
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq)]
14pub enum Rv64Instruction<Reg> {
15 Add { rd: Reg, rs1: Reg, rs2: Reg },
17 Sub { rd: Reg, rs1: Reg, rs2: Reg },
18 Sll { rd: Reg, rs1: Reg, rs2: Reg },
19 Slt { rd: Reg, rs1: Reg, rs2: Reg },
20 Sltu { rd: Reg, rs1: Reg, rs2: Reg },
21 Xor { rd: Reg, rs1: Reg, rs2: Reg },
22 Srl { rd: Reg, rs1: Reg, rs2: Reg },
23 Sra { rd: Reg, rs1: Reg, rs2: Reg },
24 Or { rd: Reg, rs1: Reg, rs2: Reg },
25 And { rd: Reg, rs1: Reg, rs2: Reg },
26
27 Addw { rd: Reg, rs1: Reg, rs2: Reg },
29 Subw { rd: Reg, rs1: Reg, rs2: Reg },
30 Sllw { rd: Reg, rs1: Reg, rs2: Reg },
31 Srlw { rd: Reg, rs1: Reg, rs2: Reg },
32 Sraw { rd: Reg, rs1: Reg, rs2: Reg },
33
34 Addi { rd: Reg, rs1: Reg, imm: i32 },
36 Slti { rd: Reg, rs1: Reg, imm: i32 },
37 Sltiu { rd: Reg, rs1: Reg, imm: i32 },
38 Xori { rd: Reg, rs1: Reg, imm: i32 },
39 Ori { rd: Reg, rs1: Reg, imm: i32 },
40 Andi { rd: Reg, rs1: Reg, imm: i32 },
41 Slli { rd: Reg, rs1: Reg, shamt: u32 },
42 Srli { rd: Reg, rs1: Reg, shamt: u32 },
43 Srai { rd: Reg, rs1: Reg, shamt: u32 },
44
45 Addiw { rd: Reg, rs1: Reg, imm: i32 },
47 Slliw { rd: Reg, rs1: Reg, shamt: u32 },
48 Srliw { rd: Reg, rs1: Reg, shamt: u32 },
49 Sraiw { rd: Reg, rs1: Reg, shamt: u32 },
50
51 Lb { rd: Reg, rs1: Reg, imm: i32 },
53 Lh { rd: Reg, rs1: Reg, imm: i32 },
54 Lw { rd: Reg, rs1: Reg, imm: i32 },
55 Ld { rd: Reg, rs1: Reg, imm: i32 },
56 Lbu { rd: Reg, rs1: Reg, imm: i32 },
57 Lhu { rd: Reg, rs1: Reg, imm: i32 },
58 Lwu { rd: Reg, rs1: Reg, imm: i32 },
59
60 Jalr { rd: Reg, rs1: Reg, imm: i32 },
62
63 Sb { rs2: Reg, rs1: Reg, imm: i32 },
65 Sh { rs2: Reg, rs1: Reg, imm: i32 },
66 Sw { rs2: Reg, rs1: Reg, imm: i32 },
67 Sd { rs2: Reg, rs1: Reg, imm: i32 },
68
69 Beq { rs1: Reg, rs2: Reg, imm: i32 },
71 Bne { rs1: Reg, rs2: Reg, imm: i32 },
72 Blt { rs1: Reg, rs2: Reg, imm: i32 },
73 Bge { rs1: Reg, rs2: Reg, imm: i32 },
74 Bltu { rs1: Reg, rs2: Reg, imm: i32 },
75 Bgeu { rs1: Reg, rs2: Reg, imm: i32 },
76
77 Lui { rd: Reg, imm: i32 },
79
80 Auipc { rd: Reg, imm: i32 },
82
83 Jal { rd: Reg, imm: i32 },
85
86 Fence { pred: u8, succ: u8, fm: u8 },
88
89 Ecall,
91 Ebreak,
92
93 Unimp,
95
96 Invalid(u32),
98}
99
100impl<Reg> const Instruction for Rv64Instruction<Reg>
101where
102 Reg: [const] Register<Type = u64>,
103{
104 type Base = Rv64Instruction<Reg>;
105
106 #[inline(always)]
107 fn try_decode(instruction: u32) -> Option<Self> {
108 let opcode = (instruction & 0b111_1111) as u8;
109 let rd_bits = ((instruction >> 7) & 0x1f) as u8;
110 let funct3 = ((instruction >> 12) & 0b111) as u8;
111 let rs1_bits = ((instruction >> 15) & 0x1f) as u8;
112 let rs2_bits = ((instruction >> 20) & 0x1f) as u8;
113 let funct7 = ((instruction >> 25) & 0b111_1111) as u8;
114
115 Some(match opcode {
116 0b0110011 => {
118 let rd = Reg::from_bits(rd_bits)?;
119 let rs1 = Reg::from_bits(rs1_bits)?;
120 let rs2 = Reg::from_bits(rs2_bits)?;
121 match (funct3, funct7) {
122 (0b000, 0b0000000) => Self::Add { rd, rs1, rs2 },
123 (0b000, 0b0100000) => Self::Sub { rd, rs1, rs2 },
124 (0b001, 0b0000000) => Self::Sll { rd, rs1, rs2 },
125 (0b010, 0b0000000) => Self::Slt { rd, rs1, rs2 },
126 (0b011, 0b0000000) => Self::Sltu { rd, rs1, rs2 },
127 (0b100, 0b0000000) => Self::Xor { rd, rs1, rs2 },
128 (0b101, 0b0000000) => Self::Srl { rd, rs1, rs2 },
129 (0b101, 0b0100000) => Self::Sra { rd, rs1, rs2 },
130 (0b110, 0b0000000) => Self::Or { rd, rs1, rs2 },
131 (0b111, 0b0000000) => Self::And { rd, rs1, rs2 },
132 _ => {
133 return None;
134 }
135 }
136 }
137 0b0111011 => {
139 let rd = Reg::from_bits(rd_bits)?;
140 let rs1 = Reg::from_bits(rs1_bits)?;
141 let rs2 = Reg::from_bits(rs2_bits)?;
142 match (funct3, funct7) {
143 (0b000, 0b0000000) => Self::Addw { rd, rs1, rs2 },
144 (0b000, 0b0100000) => Self::Subw { rd, rs1, rs2 },
145 (0b001, 0b0000000) => Self::Sllw { rd, rs1, rs2 },
146 (0b101, 0b0000000) => Self::Srlw { rd, rs1, rs2 },
147 (0b101, 0b0100000) => Self::Sraw { rd, rs1, rs2 },
148 _ => {
149 return None;
150 }
151 }
152 }
153 0b0010011 => {
155 let rd = Reg::from_bits(rd_bits)?;
156 let rs1 = Reg::from_bits(rs1_bits)?;
157 let imm = instruction.cast_signed() >> 20;
158 match funct3 {
159 0b000 => Self::Addi { rd, rs1, imm },
160 0b010 => Self::Slti { rd, rs1, imm },
161 0b011 => Self::Sltiu { rd, rs1, imm },
162 0b100 => Self::Xori { rd, rs1, imm },
163 0b110 => Self::Ori { rd, rs1, imm },
164 0b111 => Self::Andi { rd, rs1, imm },
165 0b001 => {
166 let shamt = (instruction >> 20) & 0b11_1111;
167 let funct6 = (instruction >> 26) & 0b11_1111;
168 if funct6 == 0b000000 {
169 Self::Slli { rd, rs1, shamt }
170 } else {
171 {
172 return None;
173 }
174 }
175 }
176 0b101 => {
177 let shamt = (instruction >> 20) & 0b11_1111;
178 let funct6 = (instruction >> 26) & 0b11_1111;
179 match funct6 {
180 0b000000 => Self::Srli { rd, rs1, shamt },
181 0b010000 => Self::Srai { rd, rs1, shamt },
182 _ => {
183 return None;
184 }
185 }
186 }
187 _ => {
188 return None;
189 }
190 }
191 }
192 0b0011011 => {
194 let rd = Reg::from_bits(rd_bits)?;
195 let rs1 = Reg::from_bits(rs1_bits)?;
196 let imm = instruction.cast_signed() >> 20;
197 let shamt = (instruction >> 20) & 0b1_1111; match funct3 {
199 0b000 => Self::Addiw { rd, rs1, imm },
200 0b001 => {
201 if funct7 == 0b0000000 {
202 Self::Slliw { rd, rs1, shamt }
203 } else {
204 {
205 return None;
206 }
207 }
208 }
209 0b101 => match funct7 {
210 0b0000000 => Self::Srliw { rd, rs1, shamt },
211 0b0100000 => Self::Sraiw { rd, rs1, shamt },
212 _ => {
213 return None;
214 }
215 },
216 _ => {
217 return None;
218 }
219 }
220 }
221 0b0000011 => {
223 let rd = Reg::from_bits(rd_bits)?;
224 let rs1 = Reg::from_bits(rs1_bits)?;
225 let imm = instruction.cast_signed() >> 20;
226 match funct3 {
227 0b000 => Self::Lb { rd, rs1, imm },
228 0b001 => Self::Lh { rd, rs1, imm },
229 0b010 => Self::Lw { rd, rs1, imm },
230 0b011 => Self::Ld { rd, rs1, imm },
231 0b100 => Self::Lbu { rd, rs1, imm },
232 0b101 => Self::Lhu { rd, rs1, imm },
233 0b110 => Self::Lwu { rd, rs1, imm },
234 _ => {
235 return None;
236 }
237 }
238 }
239 0b1100111 => {
241 let rd = Reg::from_bits(rd_bits)?;
242 let rs1 = Reg::from_bits(rs1_bits)?;
243 if funct3 == 0b000 {
244 let imm = instruction.cast_signed() >> 20;
245 Self::Jalr { rd, rs1, imm }
246 } else {
247 {
248 return None;
249 }
250 }
251 }
252 0b0100011 => {
254 let rs1 = Reg::from_bits(rs1_bits)?;
255 let rs2 = Reg::from_bits(rs2_bits)?;
256 let imm11_5 = ((instruction >> 25) & 0b111_1111).cast_signed();
257 let imm4_0 = ((instruction >> 7) & 0b1_1111).cast_signed();
258 let imm = (imm11_5 << 5) | imm4_0;
259 let imm = (imm << 20) >> 20;
261 match funct3 {
262 0b000 => Self::Sb { rs2, rs1, imm },
263 0b001 => Self::Sh { rs2, rs1, imm },
264 0b010 => Self::Sw { rs2, rs1, imm },
265 0b011 => Self::Sd { rs2, rs1, imm },
266 _ => {
267 return None;
268 }
269 }
270 }
271 0b1100011 => {
273 let rs1 = Reg::from_bits(rs1_bits)?;
274 let rs2 = Reg::from_bits(rs2_bits)?;
275 let imm12 = ((instruction >> 31) & 1).cast_signed();
276 let imm10_5 = ((instruction >> 25) & 0b11_1111).cast_signed();
277 let imm4_1 = ((instruction >> 8) & 0b1111).cast_signed();
278 let imm11 = ((instruction >> 7) & 1).cast_signed();
279 let imm = (imm12 << 12) | (imm11 << 11) | (imm10_5 << 5) | (imm4_1 << 1);
280 let imm = (imm << 19) >> 19;
282 match funct3 {
283 0b000 => Self::Beq { rs1, rs2, imm },
284 0b001 => Self::Bne { rs1, rs2, imm },
285 0b100 => Self::Blt { rs1, rs2, imm },
286 0b101 => Self::Bge { rs1, rs2, imm },
287 0b110 => Self::Bltu { rs1, rs2, imm },
288 0b111 => Self::Bgeu { rs1, rs2, imm },
289 _ => {
290 return None;
291 }
292 }
293 }
294 0b0110111 => {
296 let rd = Reg::from_bits(rd_bits)?;
297 let imm = (instruction & 0xffff_f000).cast_signed();
298 Self::Lui { rd, imm }
299 }
300 0b0010111 => {
302 let rd = Reg::from_bits(rd_bits)?;
303 let imm = (instruction & 0xffff_f000).cast_signed();
304 Self::Auipc { rd, imm }
305 }
306 0b1101111 => {
308 let rd = Reg::from_bits(rd_bits)?;
309 let imm20 = ((instruction >> 31) & 1).cast_signed();
310 let imm10_1 = ((instruction >> 21) & 0b11_1111_1111).cast_signed();
311 let imm11 = ((instruction >> 20) & 1).cast_signed();
312 let imm19_12 = ((instruction >> 12) & 0b1111_1111).cast_signed();
313 let imm = (imm20 << 20) | (imm19_12 << 12) | (imm11 << 11) | (imm10_1 << 1);
314 let imm = (imm << 11) >> 11;
316 Self::Jal { rd, imm }
317 }
318 0b0001111 => {
320 if funct3 == 0b000 {
321 if rd_bits != 0 || rs1_bits != 0 {
322 return None;
323 }
324 let pred = ((instruction >> 24) & 0xf) as u8;
325 let succ = ((instruction >> 20) & 0xf) as u8;
326 let fm = ((instruction >> 28) & 0xf) as u8;
327 Self::Fence { pred, succ, fm }
328 } else {
329 {
330 return None;
331 }
332 }
333 }
334 0b1110011 => {
336 let imm = (instruction >> 20) & 0xfff;
337 if funct3 == 0 && rd_bits == 0 && rs1_bits == 0 {
338 match imm {
339 0 => Self::Ecall,
340 1 => Self::Ebreak,
341 _ => {
342 return None;
343 }
344 }
345 } else if funct3 == 0b001 && rd_bits == 0 && rs1_bits == 0 && imm == 0xc00 {
346 Self::Unimp
349 } else {
350 {
351 return None;
352 }
353 }
354 }
355 _ => {
356 return None;
357 }
358 })
359 }
360
361 #[inline(always)]
362 fn size(&self) -> u8 {
363 size_of::<u32>() as u8
364 }
365}
366
367impl<Reg> const BaseInstruction for Rv64Instruction<Reg>
368where
369 Reg: [const] Register<Type = u64>,
370{
371 type Reg = Reg;
372
373 #[inline(always)]
374 fn from_base(base: Self::Base) -> Self {
375 base
376 }
377
378 #[inline]
379 fn decode(instruction: u32) -> Self {
380 if let Some(instruction) = Self::try_decode(instruction) {
381 instruction
382 } else {
383 Self::Invalid(instruction)
384 }
385 }
386}
387
388impl<Reg> fmt::Display for Rv64Instruction<Reg>
389where
390 Reg: fmt::Display,
391{
392 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
393 match self {
394 Self::Add { rd, rs1, rs2 } => write!(f, "add {}, {}, {}", rd, rs1, rs2),
395 Self::Sub { rd, rs1, rs2 } => write!(f, "sub {}, {}, {}", rd, rs1, rs2),
396 Self::Sll { rd, rs1, rs2 } => write!(f, "sll {}, {}, {}", rd, rs1, rs2),
397 Self::Slt { rd, rs1, rs2 } => write!(f, "slt {}, {}, {}", rd, rs1, rs2),
398 Self::Sltu { rd, rs1, rs2 } => write!(f, "sltu {}, {}, {}", rd, rs1, rs2),
399 Self::Xor { rd, rs1, rs2 } => write!(f, "xor {}, {}, {}", rd, rs1, rs2),
400 Self::Srl { rd, rs1, rs2 } => write!(f, "srl {}, {}, {}", rd, rs1, rs2),
401 Self::Sra { rd, rs1, rs2 } => write!(f, "sra {}, {}, {}", rd, rs1, rs2),
402 Self::Or { rd, rs1, rs2 } => write!(f, "or {}, {}, {}", rd, rs1, rs2),
403 Self::And { rd, rs1, rs2 } => write!(f, "and {}, {}, {}", rd, rs1, rs2),
404
405 Self::Addw { rd, rs1, rs2 } => write!(f, "addw {}, {}, {}", rd, rs1, rs2),
406 Self::Subw { rd, rs1, rs2 } => write!(f, "subw {}, {}, {}", rd, rs1, rs2),
407 Self::Sllw { rd, rs1, rs2 } => write!(f, "sllw {}, {}, {}", rd, rs1, rs2),
408 Self::Srlw { rd, rs1, rs2 } => write!(f, "srlw {}, {}, {}", rd, rs1, rs2),
409 Self::Sraw { rd, rs1, rs2 } => write!(f, "sraw {}, {}, {}", rd, rs1, rs2),
410
411 Self::Addi { rd, rs1, imm } => write!(f, "addi {}, {}, {}", rd, rs1, imm),
412 Self::Slti { rd, rs1, imm } => write!(f, "slti {}, {}, {}", rd, rs1, imm),
413 Self::Sltiu { rd, rs1, imm } => write!(f, "sltiu {}, {}, {}", rd, rs1, imm),
414 Self::Xori { rd, rs1, imm } => write!(f, "xori {}, {}, {}", rd, rs1, imm),
415 Self::Ori { rd, rs1, imm } => write!(f, "ori {}, {}, {}", rd, rs1, imm),
416 Self::Andi { rd, rs1, imm } => write!(f, "andi {}, {}, {}", rd, rs1, imm),
417 Self::Slli { rd, rs1, shamt } => write!(f, "slli {}, {}, {}", rd, rs1, shamt),
418 Self::Srli { rd, rs1, shamt } => write!(f, "srli {}, {}, {}", rd, rs1, shamt),
419 Self::Srai { rd, rs1, shamt } => write!(f, "srai {}, {}, {}", rd, rs1, shamt),
420
421 Self::Addiw { rd, rs1, imm } => write!(f, "addiw {}, {}, {}", rd, rs1, imm),
422 Self::Slliw { rd, rs1, shamt } => write!(f, "slliw {}, {}, {}", rd, rs1, shamt),
423 Self::Srliw { rd, rs1, shamt } => write!(f, "srliw {}, {}, {}", rd, rs1, shamt),
424 Self::Sraiw { rd, rs1, shamt } => write!(f, "sraiw {}, {}, {}", rd, rs1, shamt),
425
426 Self::Lb { rd, rs1, imm } => write!(f, "lb {}, {}({})", rd, imm, rs1),
427 Self::Lh { rd, rs1, imm } => write!(f, "lh {}, {}({})", rd, imm, rs1),
428 Self::Lw { rd, rs1, imm } => write!(f, "lw {}, {}({})", rd, imm, rs1),
429 Self::Ld { rd, rs1, imm } => write!(f, "ld {}, {}({})", rd, imm, rs1),
430 Self::Lbu { rd, rs1, imm } => write!(f, "lbu {}, {}({})", rd, imm, rs1),
431 Self::Lhu { rd, rs1, imm } => write!(f, "lhu {}, {}({})", rd, imm, rs1),
432 Self::Lwu { rd, rs1, imm } => write!(f, "lwu {}, {}({})", rd, imm, rs1),
433
434 Self::Jalr { rd, rs1, imm } => write!(f, "jalr {}, {}({})", rd, imm, rs1),
435
436 Self::Sb { rs2, rs1, imm } => write!(f, "sb {}, {}({})", rs2, imm, rs1),
437 Self::Sh { rs2, rs1, imm } => write!(f, "sh {}, {}({})", rs2, imm, rs1),
438 Self::Sw { rs2, rs1, imm } => write!(f, "sw {}, {}({})", rs2, imm, rs1),
439 Self::Sd { rs2, rs1, imm } => write!(f, "sd {}, {}({})", rs2, imm, rs1),
440
441 Self::Beq { rs1, rs2, imm } => write!(f, "beq {}, {}, {}", rs1, rs2, imm),
442 Self::Bne { rs1, rs2, imm } => write!(f, "bne {}, {}, {}", rs1, rs2, imm),
443 Self::Blt { rs1, rs2, imm } => write!(f, "blt {}, {}, {}", rs1, rs2, imm),
444 Self::Bge { rs1, rs2, imm } => write!(f, "bge {}, {}, {}", rs1, rs2, imm),
445 Self::Bltu { rs1, rs2, imm } => write!(f, "bltu {}, {}, {}", rs1, rs2, imm),
446 Self::Bgeu { rs1, rs2, imm } => write!(f, "bgeu {}, {}, {}", rs1, rs2, imm),
447
448 Self::Lui { rd, imm } => write!(f, "lui {}, 0x{:x}", rd, imm >> 12),
449
450 Self::Auipc { rd, imm } => write!(f, "auipc {}, 0x{:x}", rd, imm >> 12),
451
452 Self::Jal { rd, imm } => write!(f, "jal {}, {}", rd, imm),
453
454 Self::Fence { pred, succ, fm } => write!(f, "fence {}, {}, {}", pred, succ, fm),
455
456 Self::Ecall => write!(f, "ecall"),
457 Self::Ebreak => write!(f, "ebreak"),
458
459 Self::Unimp => write!(f, "unimp"),
460
461 Self::Invalid(instruction) => write!(f, "invalid {instruction:#010x}"),
462 }
463 }
464}