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