1pub mod a;
4pub mod b;
5pub mod c;
6pub mod m;
7#[cfg(test)]
8mod tests;
9pub mod zabha;
10pub mod zacas;
11pub mod zalasr;
12pub mod zce;
13pub mod zk;
14
15use crate::hart::HartConfig;
16use crate::instructions::utils::{I24, I24WithZeroedBits, Shamt};
17use crate::instructions::{ImplementedExtension, Instruction, IsaExtension};
18use crate::registers::general_purpose::Register;
19use ab_riscv_macros::instruction;
20use core::fmt;
21
22#[instruction]
24#[derive(Debug, Clone, Copy)]
25#[derive_const(PartialEq, Eq)]
26#[rustfmt::skip]
27pub enum Rv64Instruction<Hart>
28where
29 Hart: HartConfig,
30{
31 Add { rd: Hart::Reg, rs1: Hart::Reg, rs2: Hart::Reg },
33 Sub { rd: Hart::Reg, rs1: Hart::Reg, rs2: Hart::Reg },
34 Sll { rd: Hart::Reg, rs1: Hart::Reg, rs2: Hart::Reg },
35 Slt { rd: Hart::Reg, rs1: Hart::Reg, rs2: Hart::Reg },
36 Sltu { rd: Hart::Reg, rs1: Hart::Reg, rs2: Hart::Reg },
37 Xor { rd: Hart::Reg, rs1: Hart::Reg, rs2: Hart::Reg },
38 Srl { rd: Hart::Reg, rs1: Hart::Reg, rs2: Hart::Reg },
39 Sra { rd: Hart::Reg, rs1: Hart::Reg, rs2: Hart::Reg },
40 Or { rd: Hart::Reg, rs1: Hart::Reg, rs2: Hart::Reg },
41 And { rd: Hart::Reg, rs1: Hart::Reg, rs2: Hart::Reg },
42
43 Addw { rd: Hart::Reg, rs1: Hart::Reg, rs2: Hart::Reg },
45 Subw { rd: Hart::Reg, rs1: Hart::Reg, rs2: Hart::Reg },
46 Sllw { rd: Hart::Reg, rs1: Hart::Reg, rs2: Hart::Reg },
47 Srlw { rd: Hart::Reg, rs1: Hart::Reg, rs2: Hart::Reg },
48 Sraw { rd: Hart::Reg, rs1: Hart::Reg, rs2: Hart::Reg },
49
50 Addi { rd: Hart::Reg, rs1: Hart::Reg, imm: i16 },
52 Slti { rd: Hart::Reg, rs1: Hart::Reg, imm: i16 },
53 Sltiu { rd: Hart::Reg, rs1: Hart::Reg, imm: i16 },
54 Xori { rd: Hart::Reg, rs1: Hart::Reg, imm: i16 },
55 Ori { rd: Hart::Reg, rs1: Hart::Reg, imm: i16 },
56 Andi { rd: Hart::Reg, rs1: Hart::Reg, imm: i16 },
57 Slli { rd: Hart::Reg, rs1: Hart::Reg, shamt: Shamt<u64> },
58 Srli { rd: Hart::Reg, rs1: Hart::Reg, shamt: Shamt<u64> },
59 Srai { rd: Hart::Reg, rs1: Hart::Reg, shamt: Shamt<u64> },
60
61 Addiw { rd: Hart::Reg, rs1: Hart::Reg, imm: i16 },
63 Slliw { rd: Hart::Reg, rs1: Hart::Reg, shamt: Shamt<u32> },
64 Srliw { rd: Hart::Reg, rs1: Hart::Reg, shamt: Shamt<u32> },
65 Sraiw { rd: Hart::Reg, rs1: Hart::Reg, shamt: Shamt<u32> },
66
67 Lb { rd: Hart::Reg, rs1: Hart::Reg, imm: i16 },
69 Lh { rd: Hart::Reg, rs1: Hart::Reg, imm: i16 },
70 Lw { rd: Hart::Reg, rs1: Hart::Reg, imm: i16 },
71 Ld { rd: Hart::Reg, rs1: Hart::Reg, imm: i16 },
72 Lbu { rd: Hart::Reg, rs1: Hart::Reg, imm: i16 },
73 Lhu { rd: Hart::Reg, rs1: Hart::Reg, imm: i16 },
74 Lwu { rd: Hart::Reg, rs1: Hart::Reg, imm: i16 },
75
76 Jalr { rd: Hart::Reg, rs1: Hart::Reg, imm: i16 },
78
79 Sb { rs2: Hart::Reg, rs1: Hart::Reg, imm: i16 },
81 Sh { rs2: Hart::Reg, rs1: Hart::Reg, imm: i16 },
82 Sw { rs2: Hart::Reg, rs1: Hart::Reg, imm: i16 },
83 Sd { rs2: Hart::Reg, rs1: Hart::Reg, imm: i16 },
84
85 Beq { rs1: Hart::Reg, rs2: Hart::Reg, imm: i16 },
87 Bne { rs1: Hart::Reg, rs2: Hart::Reg, imm: i16 },
88 Blt { rs1: Hart::Reg, rs2: Hart::Reg, imm: i16 },
89 Bge { rs1: Hart::Reg, rs2: Hart::Reg, imm: i16 },
90 Bltu { rs1: Hart::Reg, rs2: Hart::Reg, imm: i16 },
91 Bgeu { rs1: Hart::Reg, rs2: Hart::Reg, imm: i16 },
92
93 Lui { rd: Hart::Reg, imm: I24WithZeroedBits<12> },
95
96 Auipc { rd: Hart::Reg, imm: I24WithZeroedBits<12> },
98
99 Jal { rd: Hart::Reg, imm: I24 },
101
102 Fence { pred: u8, succ: u8 },
104 FenceTso,
105
106 Ecall,
108 Ebreak,
109
110 Unimp,
112}
113
114#[instruction]
115const impl<Reg, Hart> Instruction for Rv64Instruction<Hart>
116where
117 Reg: [const] Register<Type = u64>,
118 Hart: [const] HartConfig<Reg = Reg>,
119{
120 const OWN_ISA_EXTENSIONS: &'static [IsaExtension] = if Reg::RVE {
121 &[IsaExtension::new("e", 2, 0)]
122 } else {
123 &[IsaExtension::new("i", 2, 1)]
124 };
125
126 const ALIGNMENT: u8 = align_of::<u32>() as u8;
127
128 type Hart = Hart;
129
130 #[inline(always)]
131 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
132 fn try_decode(instruction: u32) -> Option<Self> {
133 let opcode = (instruction & 0b111_1111) as u8;
134 let rd_bits = ((instruction >> 7) & 0x1f) as u8;
135 let funct3 = ((instruction >> 12) & 0b111) as u8;
136 let rs1_bits = ((instruction >> 15) & 0x1f) as u8;
137 let rs2_bits = ((instruction >> 20) & 0x1f) as u8;
138 let funct7 = ((instruction >> 25) & 0b111_1111) as u8;
139
140 match opcode {
141 0b011_0011 => {
143 let rd = Reg::from_bits(rd_bits)?;
144 let rs1 = Reg::from_bits(rs1_bits)?;
145 let rs2 = Reg::from_bits(rs2_bits)?;
146 match (funct3, funct7) {
147 (0b000, 0b000_0000) => Some(Self::Add { rd, rs1, rs2 }),
148 (0b000, 0b010_0000) => Some(Self::Sub { rd, rs1, rs2 }),
149 (0b001, 0b000_0000) => Some(Self::Sll { rd, rs1, rs2 }),
150 (0b010, 0b000_0000) => Some(Self::Slt { rd, rs1, rs2 }),
151 (0b011, 0b000_0000) => Some(Self::Sltu { rd, rs1, rs2 }),
152 (0b100, 0b000_0000) => Some(Self::Xor { rd, rs1, rs2 }),
153 (0b101, 0b000_0000) => Some(Self::Srl { rd, rs1, rs2 }),
154 (0b101, 0b010_0000) => Some(Self::Sra { rd, rs1, rs2 }),
155 (0b110, 0b000_0000) => Some(Self::Or { rd, rs1, rs2 }),
156 (0b111, 0b000_0000) => Some(Self::And { rd, rs1, rs2 }),
157 _ => None,
158 }
159 }
160 0b011_1011 => {
162 let rd = Reg::from_bits(rd_bits)?;
163 let rs1 = Reg::from_bits(rs1_bits)?;
164 let rs2 = Reg::from_bits(rs2_bits)?;
165 match (funct3, funct7) {
166 (0b000, 0b000_0000) => Some(Self::Addw { rd, rs1, rs2 }),
167 (0b000, 0b010_0000) => Some(Self::Subw { rd, rs1, rs2 }),
168 (0b001, 0b000_0000) => Some(Self::Sllw { rd, rs1, rs2 }),
169 (0b101, 0b000_0000) => Some(Self::Srlw { rd, rs1, rs2 }),
170 (0b101, 0b010_0000) => Some(Self::Sraw { rd, rs1, rs2 }),
171 _ => None,
172 }
173 }
174 0b001_0011 => {
176 let rd = Reg::from_bits(rd_bits)?;
177 let rs1 = Reg::from_bits(rs1_bits)?;
178 let imm = (instruction.cast_signed() >> 20) as i16;
179 match funct3 {
180 0b000 => Some(Self::Addi { rd, rs1, imm }),
181 0b010 => Some(Self::Slti { rd, rs1, imm }),
182 0b011 => Some(Self::Sltiu { rd, rs1, imm }),
183 0b100 => Some(Self::Xori { rd, rs1, imm }),
184 0b110 => Some(Self::Ori { rd, rs1, imm }),
185 0b111 => Some(Self::Andi { rd, rs1, imm }),
186 0b001 => {
187 let shamt = Shamt::<u64>::new((instruction >> 20) as u8 & 0b11_1111)?;
188 let funct6 = (instruction >> 26) & 0b11_1111;
189 if funct6 == 0b00_0000 {
190 Some(Self::Slli { rd, rs1, shamt })
191 } else {
192 None
193 }
194 }
195 0b101 => {
196 let shamt = Shamt::<u64>::new((instruction >> 20) as u8 & 0b11_1111)?;
197 let funct6 = (instruction >> 26) & 0b11_1111;
198 match funct6 {
199 0b00_0000 => Some(Self::Srli { rd, rs1, shamt }),
200 0b01_0000 => Some(Self::Srai { rd, rs1, shamt }),
201 _ => None,
202 }
203 }
204 _ => None,
205 }
206 }
207 0b001_1011 => {
209 let rd = Reg::from_bits(rd_bits)?;
210 let rs1 = Reg::from_bits(rs1_bits)?;
211 let imm = (instruction.cast_signed() >> 20) as i16;
212 let shamt = Shamt::<u32>::new((instruction >> 20) as u8 & 0b1_1111)?;
214 match funct3 {
215 0b000 => Some(Self::Addiw { rd, rs1, imm }),
216 0b001 => {
217 if funct7 == 0b000_0000 {
218 Some(Self::Slliw { rd, rs1, shamt })
219 } else {
220 None
221 }
222 }
223 0b101 => match funct7 {
224 0b000_0000 => Some(Self::Srliw { rd, rs1, shamt }),
225 0b010_0000 => Some(Self::Sraiw { rd, rs1, shamt }),
226 _ => None,
227 },
228 _ => None,
229 }
230 }
231 0b000_0011 => {
233 let rd = Reg::from_bits(rd_bits)?;
234 let rs1 = Reg::from_bits(rs1_bits)?;
235 let imm = (instruction.cast_signed() >> 20) as i16;
236 match funct3 {
237 0b000 => Some(Self::Lb { rd, rs1, imm }),
238 0b001 => Some(Self::Lh { rd, rs1, imm }),
239 0b010 => Some(Self::Lw { rd, rs1, imm }),
240 0b011 => Some(Self::Ld { rd, rs1, imm }),
241 0b100 => Some(Self::Lbu { rd, rs1, imm }),
242 0b101 => Some(Self::Lhu { rd, rs1, imm }),
243 0b110 => Some(Self::Lwu { rd, rs1, imm }),
244 _ => None,
245 }
246 }
247 0b110_0111 => {
249 let rd = Reg::from_bits(rd_bits)?;
250 let rs1 = Reg::from_bits(rs1_bits)?;
251 if funct3 == 0b000 {
252 let imm = (instruction.cast_signed() >> 20) as i16;
253 Some(Self::Jalr { rd, rs1, imm })
254 } else {
255 None
256 }
257 }
258 0b010_0011 => {
260 let rs1 = Reg::from_bits(rs1_bits)?;
261 let rs2 = Reg::from_bits(rs2_bits)?;
262 let imm11_5 = ((instruction >> 25) & 0b111_1111).cast_signed();
263 let imm4_0 = ((instruction >> 7) & 0b1_1111).cast_signed();
264 let imm = (imm11_5 << 5) | imm4_0;
265 let imm = ((imm << 20) >> 20) as i16;
267 match funct3 {
268 0b000 => Some(Self::Sb { rs2, rs1, imm }),
269 0b001 => Some(Self::Sh { rs2, rs1, imm }),
270 0b010 => Some(Self::Sw { rs2, rs1, imm }),
271 0b011 => Some(Self::Sd { rs2, rs1, imm }),
272 _ => None,
273 }
274 }
275 0b110_0011 => {
277 let rs1 = Reg::from_bits(rs1_bits)?;
278 let rs2 = Reg::from_bits(rs2_bits)?;
279 let imm12 = ((instruction >> 31) & 1).cast_signed();
280 let imm10_5 = ((instruction >> 25) & 0b11_1111).cast_signed();
281 let imm4_1 = ((instruction >> 8) & 0b1111).cast_signed();
282 let imm11 = ((instruction >> 7) & 1).cast_signed();
283 let imm = (imm12 << 12) | (imm11 << 11) | (imm10_5 << 5) | (imm4_1 << 1);
284 let imm = ((imm << 19) >> 19) as i16;
286 match funct3 {
287 0b000 => Some(Self::Beq { rs1, rs2, imm }),
288 0b001 => Some(Self::Bne { rs1, rs2, imm }),
289 0b100 => Some(Self::Blt { rs1, rs2, imm }),
290 0b101 => Some(Self::Bge { rs1, rs2, imm }),
291 0b110 => Some(Self::Bltu { rs1, rs2, imm }),
292 0b111 => Some(Self::Bgeu { rs1, rs2, imm }),
293 _ => None,
294 }
295 }
296 0b011_0111 => {
298 let rd = Reg::from_bits(rd_bits)?;
299 let imm = I24WithZeroedBits::from_i32((instruction & 0xffff_f000).cast_signed());
300 Some(Self::Lui { rd, imm })
301 }
302 0b001_0111 => {
304 let rd = Reg::from_bits(rd_bits)?;
305 let imm = I24WithZeroedBits::from_i32((instruction & 0xffff_f000).cast_signed());
306 Some(Self::Auipc { rd, imm })
307 }
308 0b110_1111 => {
310 let rd = Reg::from_bits(rd_bits)?;
311 let imm20 = ((instruction >> 31) & 1).cast_signed();
312 let imm10_1 = ((instruction >> 21) & 0b11_1111_1111).cast_signed();
313 let imm11 = ((instruction >> 20) & 1).cast_signed();
314 let imm19_12 = ((instruction >> 12) & 0b1111_1111).cast_signed();
315 let imm = (imm20 << 20) | (imm19_12 << 12) | (imm11 << 11) | (imm10_1 << 1);
316 let imm = I24::from_i32((imm << 11) >> 11);
318 Some(Self::Jal { rd, imm })
319 }
320 0b000_1111 => {
322 if funct3 == 0b000 {
323 let fm = (instruction >> 28) & 0b1111;
324 let pred = ((instruction >> 24) & 0xf) as u8;
325 let succ = ((instruction >> 20) & 0xf) as u8;
326 if fm == 0b1000 && pred == 0b0011 && succ == 0b0011 {
327 Some(Self::FenceTso)
329 } else {
330 Some(Self::Fence { pred, succ })
335 }
336 } else {
337 None
338 }
339 }
340 0b111_0011 => {
342 let imm = (instruction >> 20) & 0xfff;
343 if funct3 == 0 && rd_bits == 0 && rs1_bits == 0 {
344 match imm {
345 0 => Some(Self::Ecall),
346 1 => Some(Self::Ebreak),
347 _ => None,
348 }
349 } else if funct3 == 0b001 && rd_bits == 0 && rs1_bits == 0 && imm == 0xc00 {
350 Some(Self::Unimp)
353 } else {
354 None
355 }
356 }
357 _ => None,
358 }
359 }
360
361 #[inline(always)]
362 fn size(&self) -> u8 {
363 size_of::<u32>() as u8
364 }
365}
366
367#[instruction]
368impl<Reg, Hart> fmt::Display for Rv64Instruction<Hart>
369where
370 Reg: fmt::Display,
371 Hart: HartConfig<Reg = Reg>,
372{
373 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
374 match self {
375 Self::Add { rd, rs1, rs2 } => write!(f, "add {rd}, {rs1}, {rs2}"),
376 Self::Sub { rd, rs1, rs2 } => write!(f, "sub {rd}, {rs1}, {rs2}"),
377 Self::Sll { rd, rs1, rs2 } => write!(f, "sll {rd}, {rs1}, {rs2}"),
378 Self::Slt { rd, rs1, rs2 } => write!(f, "slt {rd}, {rs1}, {rs2}"),
379 Self::Sltu { rd, rs1, rs2 } => write!(f, "sltu {rd}, {rs1}, {rs2}"),
380 Self::Xor { rd, rs1, rs2 } => write!(f, "xor {rd}, {rs1}, {rs2}"),
381 Self::Srl { rd, rs1, rs2 } => write!(f, "srl {rd}, {rs1}, {rs2}"),
382 Self::Sra { rd, rs1, rs2 } => write!(f, "sra {rd}, {rs1}, {rs2}"),
383 Self::Or { rd, rs1, rs2 } => write!(f, "or {rd}, {rs1}, {rs2}"),
384 Self::And { rd, rs1, rs2 } => write!(f, "and {rd}, {rs1}, {rs2}"),
385
386 Self::Addw { rd, rs1, rs2 } => write!(f, "addw {rd}, {rs1}, {rs2}"),
387 Self::Subw { rd, rs1, rs2 } => write!(f, "subw {rd}, {rs1}, {rs2}"),
388 Self::Sllw { rd, rs1, rs2 } => write!(f, "sllw {rd}, {rs1}, {rs2}"),
389 Self::Srlw { rd, rs1, rs2 } => write!(f, "srlw {rd}, {rs1}, {rs2}"),
390 Self::Sraw { rd, rs1, rs2 } => write!(f, "sraw {rd}, {rs1}, {rs2}"),
391
392 Self::Addi { rd, rs1, imm } => write!(f, "addi {rd}, {rs1}, {imm}"),
393 Self::Slti { rd, rs1, imm } => write!(f, "slti {rd}, {rs1}, {imm}"),
394 Self::Sltiu { rd, rs1, imm } => write!(f, "sltiu {rd}, {rs1}, {imm}"),
395 Self::Xori { rd, rs1, imm } => write!(f, "xori {rd}, {rs1}, {imm}"),
396 Self::Ori { rd, rs1, imm } => write!(f, "ori {rd}, {rs1}, {imm}"),
397 Self::Andi { rd, rs1, imm } => write!(f, "andi {rd}, {rs1}, {imm}"),
398 Self::Slli { rd, rs1, shamt } => write!(f, "slli {rd}, {rs1}, {shamt}"),
399 Self::Srli { rd, rs1, shamt } => write!(f, "srli {rd}, {rs1}, {shamt}"),
400 Self::Srai { rd, rs1, shamt } => write!(f, "srai {rd}, {rs1}, {shamt}"),
401
402 Self::Addiw { rd, rs1, imm } => write!(f, "addiw {rd}, {rs1}, {imm}"),
403 Self::Slliw { rd, rs1, shamt } => write!(f, "slliw {rd}, {rs1}, {shamt}"),
404 Self::Srliw { rd, rs1, shamt } => write!(f, "srliw {rd}, {rs1}, {shamt}"),
405 Self::Sraiw { rd, rs1, shamt } => write!(f, "sraiw {rd}, {rs1}, {shamt}"),
406
407 Self::Lb { rd, rs1, imm } => write!(f, "lb {rd}, {imm}({rs1})"),
408 Self::Lh { rd, rs1, imm } => write!(f, "lh {rd}, {imm}({rs1})"),
409 Self::Lw { rd, rs1, imm } => write!(f, "lw {rd}, {imm}({rs1})"),
410 Self::Ld { rd, rs1, imm } => write!(f, "ld {rd}, {imm}({rs1})"),
411 Self::Lbu { rd, rs1, imm } => write!(f, "lbu {rd}, {imm}({rs1})"),
412 Self::Lhu { rd, rs1, imm } => write!(f, "lhu {rd}, {imm}({rs1})"),
413 Self::Lwu { rd, rs1, imm } => write!(f, "lwu {rd}, {imm}({rs1})"),
414
415 Self::Jalr { rd, rs1, imm } => write!(f, "jalr {rd}, {imm}({rs1})"),
416
417 Self::Sb { rs2, rs1, imm } => write!(f, "sb {rs2}, {imm}({rs1})"),
418 Self::Sh { rs2, rs1, imm } => write!(f, "sh {rs2}, {imm}({rs1})"),
419 Self::Sw { rs2, rs1, imm } => write!(f, "sw {rs2}, {imm}({rs1})"),
420 Self::Sd { rs2, rs1, imm } => write!(f, "sd {rs2}, {imm}({rs1})"),
421
422 Self::Beq { rs1, rs2, imm } => write!(f, "beq {rs1}, {rs2}, {imm}"),
423 Self::Bne { rs1, rs2, imm } => write!(f, "bne {rs1}, {rs2}, {imm}"),
424 Self::Blt { rs1, rs2, imm } => write!(f, "blt {rs1}, {rs2}, {imm}"),
425 Self::Bge { rs1, rs2, imm } => write!(f, "bge {rs1}, {rs2}, {imm}"),
426 Self::Bltu { rs1, rs2, imm } => write!(f, "bltu {rs1}, {rs2}, {imm}"),
427 Self::Bgeu { rs1, rs2, imm } => write!(f, "bgeu {rs1}, {rs2}, {imm}"),
428
429 Self::Lui { rd, imm } => write!(f, "lui {rd}, 0x{:x}", imm.to_i32() >> 12),
430
431 Self::Auipc { rd, imm } => write!(f, "auipc {rd}, 0x{:x}", imm.to_i32() >> 12),
432
433 Self::Jal { rd, imm } => write!(f, "jal {rd}, {imm}"),
434
435 Self::Fence { pred, succ } => write!(f, "fence {pred}, {succ}"),
436 Self::FenceTso => write!(f, "fence.tso"),
437
438 Self::Ecall => write!(f, "ecall"),
439 Self::Ebreak => write!(f, "ebreak"),
440
441 Self::Unimp => write!(f, "unimp"),
442 }
443 }
444}