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