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