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