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]
105impl<Reg> const Instruction for Rv64Instruction<Reg>
106where
107 Reg: [const] Register<Type = u64>,
108{
109 type Reg = Reg;
110
111 #[inline(always)]
112 fn try_decode(instruction: u32) -> Option<Self> {
113 let opcode = (instruction & 0b111_1111) as u8;
114 let rd_bits = ((instruction >> 7) & 0x1f) as u8;
115 let funct3 = ((instruction >> 12) & 0b111) as u8;
116 let rs1_bits = ((instruction >> 15) & 0x1f) as u8;
117 let rs2_bits = ((instruction >> 20) & 0x1f) as u8;
118 let funct7 = ((instruction >> 25) & 0b111_1111) as u8;
119
120 match opcode {
121 0b0110011 => {
123 let rd = Reg::from_bits(rd_bits)?;
124 let rs1 = Reg::from_bits(rs1_bits)?;
125 let rs2 = Reg::from_bits(rs2_bits)?;
126 match (funct3, funct7) {
127 (0b000, 0b0000000) => Some(Self::Add { rd, rs1, rs2 }),
128 (0b000, 0b0100000) => Some(Self::Sub { rd, rs1, rs2 }),
129 (0b001, 0b0000000) => Some(Self::Sll { rd, rs1, rs2 }),
130 (0b010, 0b0000000) => Some(Self::Slt { rd, rs1, rs2 }),
131 (0b011, 0b0000000) => Some(Self::Sltu { rd, rs1, rs2 }),
132 (0b100, 0b0000000) => Some(Self::Xor { rd, rs1, rs2 }),
133 (0b101, 0b0000000) => Some(Self::Srl { rd, rs1, rs2 }),
134 (0b101, 0b0100000) => Some(Self::Sra { rd, rs1, rs2 }),
135 (0b110, 0b0000000) => Some(Self::Or { rd, rs1, rs2 }),
136 (0b111, 0b0000000) => Some(Self::And { rd, rs1, rs2 }),
137 _ => None,
138 }
139 }
140 0b0111011 => {
142 let rd = Reg::from_bits(rd_bits)?;
143 let rs1 = Reg::from_bits(rs1_bits)?;
144 let rs2 = Reg::from_bits(rs2_bits)?;
145 match (funct3, funct7) {
146 (0b000, 0b0000000) => Some(Self::Addw { rd, rs1, rs2 }),
147 (0b000, 0b0100000) => Some(Self::Subw { rd, rs1, rs2 }),
148 (0b001, 0b0000000) => Some(Self::Sllw { rd, rs1, rs2 }),
149 (0b101, 0b0000000) => Some(Self::Srlw { rd, rs1, rs2 }),
150 (0b101, 0b0100000) => Some(Self::Sraw { rd, rs1, rs2 }),
151 _ => None,
152 }
153 }
154 0b0010011 => {
156 let rd = Reg::from_bits(rd_bits)?;
157 let rs1 = Reg::from_bits(rs1_bits)?;
158 let imm = (instruction.cast_signed() >> 20) as i16;
159 match funct3 {
160 0b000 => Some(Self::Addi { rd, rs1, imm }),
161 0b010 => Some(Self::Slti { rd, rs1, imm }),
162 0b011 => Some(Self::Sltiu { rd, rs1, imm }),
163 0b100 => Some(Self::Xori { rd, rs1, imm }),
164 0b110 => Some(Self::Ori { rd, rs1, imm }),
165 0b111 => Some(Self::Andi { rd, rs1, imm }),
166 0b001 => {
167 let shamt = (instruction >> 20) as u8 & 0b11_1111;
168 let funct6 = (instruction >> 26) & 0b11_1111;
169 if funct6 == 0b000000 {
170 Some(Self::Slli { rd, rs1, shamt })
171 } else {
172 None
173 }
174 }
175 0b101 => {
176 let shamt = (instruction >> 20) as u8 & 0b11_1111;
177 let funct6 = (instruction >> 26) & 0b11_1111;
178 match funct6 {
179 0b000000 => Some(Self::Srli { rd, rs1, shamt }),
180 0b010000 => Some(Self::Srai { rd, rs1, shamt }),
181 _ => None,
182 }
183 }
184 _ => None,
185 }
186 }
187 0b0011011 => {
189 let rd = Reg::from_bits(rd_bits)?;
190 let rs1 = Reg::from_bits(rs1_bits)?;
191 let imm = (instruction.cast_signed() >> 20) as i16;
192 let shamt = (instruction >> 20) as u8 & 0b1_1111;
194 match funct3 {
195 0b000 => Some(Self::Addiw { rd, rs1, imm }),
196 0b001 => {
197 if funct7 == 0b0000000 {
198 Some(Self::Slliw { rd, rs1, shamt })
199 } else {
200 None
201 }
202 }
203 0b101 => match funct7 {
204 0b0000000 => Some(Self::Srliw { rd, rs1, shamt }),
205 0b0100000 => Some(Self::Sraiw { rd, rs1, shamt }),
206 _ => None,
207 },
208 _ => None,
209 }
210 }
211 0b0000011 => {
213 let rd = Reg::from_bits(rd_bits)?;
214 let rs1 = Reg::from_bits(rs1_bits)?;
215 let imm = (instruction.cast_signed() >> 20) as i16;
216 match funct3 {
217 0b000 => Some(Self::Lb { rd, rs1, imm }),
218 0b001 => Some(Self::Lh { rd, rs1, imm }),
219 0b010 => Some(Self::Lw { rd, rs1, imm }),
220 0b011 => Some(Self::Ld { rd, rs1, imm }),
221 0b100 => Some(Self::Lbu { rd, rs1, imm }),
222 0b101 => Some(Self::Lhu { rd, rs1, imm }),
223 0b110 => Some(Self::Lwu { rd, rs1, imm }),
224 _ => None,
225 }
226 }
227 0b1100111 => {
229 let rd = Reg::from_bits(rd_bits)?;
230 let rs1 = Reg::from_bits(rs1_bits)?;
231 if funct3 == 0b000 {
232 let imm = (instruction.cast_signed() >> 20) as i16;
233 Some(Self::Jalr { rd, rs1, imm })
234 } else {
235 None
236 }
237 }
238 0b0100011 => {
240 let rs1 = Reg::from_bits(rs1_bits)?;
241 let rs2 = Reg::from_bits(rs2_bits)?;
242 let imm11_5 = ((instruction >> 25) & 0b111_1111).cast_signed();
243 let imm4_0 = ((instruction >> 7) & 0b1_1111).cast_signed();
244 let imm = (imm11_5 << 5) | imm4_0;
245 let imm = ((imm << 20) >> 20) as i16;
247 match funct3 {
248 0b000 => Some(Self::Sb { rs2, rs1, imm }),
249 0b001 => Some(Self::Sh { rs2, rs1, imm }),
250 0b010 => Some(Self::Sw { rs2, rs1, imm }),
251 0b011 => Some(Self::Sd { rs2, rs1, imm }),
252 _ => None,
253 }
254 }
255 0b1100011 => {
257 let rs1 = Reg::from_bits(rs1_bits)?;
258 let rs2 = Reg::from_bits(rs2_bits)?;
259 let imm12 = ((instruction >> 31) & 1).cast_signed();
260 let imm10_5 = ((instruction >> 25) & 0b11_1111).cast_signed();
261 let imm4_1 = ((instruction >> 8) & 0b1111).cast_signed();
262 let imm11 = ((instruction >> 7) & 1).cast_signed();
263 let imm = (imm12 << 12) | (imm11 << 11) | (imm10_5 << 5) | (imm4_1 << 1);
264 let imm = I24::from_i32((imm << 19) >> 19);
266 match funct3 {
267 0b000 => Some(Self::Beq { rs1, rs2, imm }),
268 0b001 => Some(Self::Bne { rs1, rs2, imm }),
269 0b100 => Some(Self::Blt { rs1, rs2, imm }),
270 0b101 => Some(Self::Bge { rs1, rs2, imm }),
271 0b110 => Some(Self::Bltu { rs1, rs2, imm }),
272 0b111 => Some(Self::Bgeu { rs1, rs2, imm }),
273 _ => None,
274 }
275 }
276 0b0110111 => {
278 let rd = Reg::from_bits(rd_bits)?;
279 let imm = I24WithZeroedBits::from_i32((instruction & 0xffff_f000).cast_signed());
280 Some(Self::Lui { rd, imm })
281 }
282 0b0010111 => {
284 let rd = Reg::from_bits(rd_bits)?;
285 let imm = I24WithZeroedBits::from_i32((instruction & 0xffff_f000).cast_signed());
286 Some(Self::Auipc { rd, imm })
287 }
288 0b1101111 => {
290 let rd = Reg::from_bits(rd_bits)?;
291 let imm20 = ((instruction >> 31) & 1).cast_signed();
292 let imm10_1 = ((instruction >> 21) & 0b11_1111_1111).cast_signed();
293 let imm11 = ((instruction >> 20) & 1).cast_signed();
294 let imm19_12 = ((instruction >> 12) & 0b1111_1111).cast_signed();
295 let imm = (imm20 << 20) | (imm19_12 << 12) | (imm11 << 11) | (imm10_1 << 1);
296 let imm = I24::from_i32((imm << 11) >> 11);
298 Some(Self::Jal { rd, imm })
299 }
300 0b0001111 => {
302 if funct3 == 0b000 && rd_bits == 0 && rs1_bits == 0 {
303 let fm = (instruction >> 28) & 0b1111;
304 let pred = ((instruction >> 24) & 0xf) as u8;
305 let succ = ((instruction >> 20) & 0xf) as u8;
306 match fm {
307 0b0000 => Some(Self::Fence { pred, succ }),
308 0b1000 => {
309 if pred == 0b0011 && succ == 0b0011 {
311 Some(Self::FenceTso)
312 } else {
313 None
314 }
315 }
316 _ => None,
317 }
318 } else {
319 None
320 }
321 }
322 0b1110011 => {
324 let imm = (instruction >> 20) & 0xfff;
325 if funct3 == 0 && rd_bits == 0 && rs1_bits == 0 {
326 match imm {
327 0 => Some(Self::Ecall),
328 1 => Some(Self::Ebreak),
329 _ => None,
330 }
331 } else if funct3 == 0b001 && rd_bits == 0 && rs1_bits == 0 && imm == 0xc00 {
332 Some(Self::Unimp)
335 } else {
336 None
337 }
338 }
339 _ => None,
340 }
341 }
342
343 #[inline(always)]
344 fn alignment() -> u8 {
345 align_of::<u32>() as u8
346 }
347
348 #[inline(always)]
349 fn size(&self) -> u8 {
350 size_of::<u32>() as u8
351 }
352}
353
354#[instruction]
355impl<Reg> fmt::Display for Rv64Instruction<Reg>
356where
357 Reg: fmt::Display,
358{
359 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
360 match self {
361 Self::Add { rd, rs1, rs2 } => write!(f, "add {}, {}, {}", rd, rs1, rs2),
362 Self::Sub { rd, rs1, rs2 } => write!(f, "sub {}, {}, {}", rd, rs1, rs2),
363 Self::Sll { rd, rs1, rs2 } => write!(f, "sll {}, {}, {}", rd, rs1, rs2),
364 Self::Slt { rd, rs1, rs2 } => write!(f, "slt {}, {}, {}", rd, rs1, rs2),
365 Self::Sltu { rd, rs1, rs2 } => write!(f, "sltu {}, {}, {}", rd, rs1, rs2),
366 Self::Xor { rd, rs1, rs2 } => write!(f, "xor {}, {}, {}", rd, rs1, rs2),
367 Self::Srl { rd, rs1, rs2 } => write!(f, "srl {}, {}, {}", rd, rs1, rs2),
368 Self::Sra { rd, rs1, rs2 } => write!(f, "sra {}, {}, {}", rd, rs1, rs2),
369 Self::Or { rd, rs1, rs2 } => write!(f, "or {}, {}, {}", rd, rs1, rs2),
370 Self::And { rd, rs1, rs2 } => write!(f, "and {}, {}, {}", rd, rs1, rs2),
371
372 Self::Addw { rd, rs1, rs2 } => write!(f, "addw {}, {}, {}", rd, rs1, rs2),
373 Self::Subw { rd, rs1, rs2 } => write!(f, "subw {}, {}, {}", rd, rs1, rs2),
374 Self::Sllw { rd, rs1, rs2 } => write!(f, "sllw {}, {}, {}", rd, rs1, rs2),
375 Self::Srlw { rd, rs1, rs2 } => write!(f, "srlw {}, {}, {}", rd, rs1, rs2),
376 Self::Sraw { rd, rs1, rs2 } => write!(f, "sraw {}, {}, {}", rd, rs1, rs2),
377
378 Self::Addi { rd, rs1, imm } => write!(f, "addi {}, {}, {}", rd, rs1, imm),
379 Self::Slti { rd, rs1, imm } => write!(f, "slti {}, {}, {}", rd, rs1, imm),
380 Self::Sltiu { rd, rs1, imm } => write!(f, "sltiu {}, {}, {}", rd, rs1, imm),
381 Self::Xori { rd, rs1, imm } => write!(f, "xori {}, {}, {}", rd, rs1, imm),
382 Self::Ori { rd, rs1, imm } => write!(f, "ori {}, {}, {}", rd, rs1, imm),
383 Self::Andi { rd, rs1, imm } => write!(f, "andi {}, {}, {}", rd, rs1, imm),
384 Self::Slli { rd, rs1, shamt } => write!(f, "slli {}, {}, {}", rd, rs1, shamt),
385 Self::Srli { rd, rs1, shamt } => write!(f, "srli {}, {}, {}", rd, rs1, shamt),
386 Self::Srai { rd, rs1, shamt } => write!(f, "srai {}, {}, {}", rd, rs1, shamt),
387
388 Self::Addiw { rd, rs1, imm } => write!(f, "addiw {}, {}, {}", rd, rs1, imm),
389 Self::Slliw { rd, rs1, shamt } => write!(f, "slliw {}, {}, {}", rd, rs1, shamt),
390 Self::Srliw { rd, rs1, shamt } => write!(f, "srliw {}, {}, {}", rd, rs1, shamt),
391 Self::Sraiw { rd, rs1, shamt } => write!(f, "sraiw {}, {}, {}", rd, rs1, shamt),
392
393 Self::Lb { rd, rs1, imm } => write!(f, "lb {}, {}({})", rd, imm, rs1),
394 Self::Lh { rd, rs1, imm } => write!(f, "lh {}, {}({})", rd, imm, rs1),
395 Self::Lw { rd, rs1, imm } => write!(f, "lw {}, {}({})", rd, imm, rs1),
396 Self::Ld { rd, rs1, imm } => write!(f, "ld {}, {}({})", rd, imm, rs1),
397 Self::Lbu { rd, rs1, imm } => write!(f, "lbu {}, {}({})", rd, imm, rs1),
398 Self::Lhu { rd, rs1, imm } => write!(f, "lhu {}, {}({})", rd, imm, rs1),
399 Self::Lwu { rd, rs1, imm } => write!(f, "lwu {}, {}({})", rd, imm, rs1),
400
401 Self::Jalr { rd, rs1, imm } => write!(f, "jalr {}, {}({})", rd, imm, rs1),
402
403 Self::Sb { rs2, rs1, imm } => write!(f, "sb {}, {}({})", rs2, imm, rs1),
404 Self::Sh { rs2, rs1, imm } => write!(f, "sh {}, {}({})", rs2, imm, rs1),
405 Self::Sw { rs2, rs1, imm } => write!(f, "sw {}, {}({})", rs2, imm, rs1),
406 Self::Sd { rs2, rs1, imm } => write!(f, "sd {}, {}({})", rs2, imm, rs1),
407
408 Self::Beq { rs1, rs2, imm } => write!(f, "beq {}, {}, {}", rs1, rs2, imm),
409 Self::Bne { rs1, rs2, imm } => write!(f, "bne {}, {}, {}", rs1, rs2, imm),
410 Self::Blt { rs1, rs2, imm } => write!(f, "blt {}, {}, {}", rs1, rs2, imm),
411 Self::Bge { rs1, rs2, imm } => write!(f, "bge {}, {}, {}", rs1, rs2, imm),
412 Self::Bltu { rs1, rs2, imm } => write!(f, "bltu {}, {}, {}", rs1, rs2, imm),
413 Self::Bgeu { rs1, rs2, imm } => write!(f, "bgeu {}, {}, {}", rs1, rs2, imm),
414
415 Self::Lui { rd, imm } => write!(f, "lui {}, 0x{:x}", rd, imm.to_i32() >> 12),
416
417 Self::Auipc { rd, imm } => write!(f, "auipc {}, 0x{:x}", rd, imm.to_i32() >> 12),
418
419 Self::Jal { rd, imm } => write!(f, "jal {}, {}", rd, imm),
420
421 Self::Fence { pred, succ } => write!(f, "fence {}, {}", pred, succ),
422 Self::FenceTso => write!(f, "fence.tso"),
423
424 Self::Ecall => write!(f, "ecall"),
425 Self::Ebreak => write!(f, "ebreak"),
426
427 Self::Unimp => write!(f, "unimp"),
428 }
429 }
430}