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 Rv32Instruction<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 Addi { rd: Reg, rs1: Reg, imm: i16 },
35 Slti { rd: Reg, rs1: Reg, imm: i16 },
36 Sltiu { rd: Reg, rs1: Reg, imm: i16 },
37 Xori { rd: Reg, rs1: Reg, imm: i16 },
38 Ori { rd: Reg, rs1: Reg, imm: i16 },
39 Andi { rd: Reg, rs1: Reg, imm: i16 },
40 Slli { rd: Reg, rs1: Reg, shamt: u8 },
41 Srli { rd: Reg, rs1: Reg, shamt: u8 },
42 Srai { rd: Reg, rs1: Reg, shamt: u8 },
43
44 Lb { rd: Reg, rs1: Reg, imm: i16 },
46 Lh { rd: Reg, rs1: Reg, imm: i16 },
47 Lw { rd: Reg, rs1: Reg, imm: i16 },
48 Lbu { rd: Reg, rs1: Reg, imm: i16 },
49 Lhu { rd: Reg, rs1: Reg, imm: i16 },
50
51 Jalr { rd: Reg, rs1: Reg, imm: i16 },
53
54 Sb { rs2: Reg, rs1: Reg, imm: i16 },
56 Sh { rs2: Reg, rs1: Reg, imm: i16 },
57 Sw { rs2: Reg, rs1: Reg, imm: i16 },
58
59 Beq { rs1: Reg, rs2: Reg, imm: I24 },
61 Bne { rs1: Reg, rs2: Reg, imm: I24 },
62 Blt { rs1: Reg, rs2: Reg, imm: I24 },
63 Bge { rs1: Reg, rs2: Reg, imm: I24 },
64 Bltu { rs1: Reg, rs2: Reg, imm: I24 },
65 Bgeu { rs1: Reg, rs2: Reg, imm: I24 },
66
67 Lui { rd: Reg, imm: I24WithZeroedBits<12> },
69
70 Auipc { rd: Reg, imm: I24WithZeroedBits<12> },
72
73 Jal { rd: Reg, imm: I24 },
75
76 Fence { pred: u8, succ: u8 },
78 FenceTso,
79
80 Ecall,
82 Ebreak,
83
84 Unimp,
86}
87
88#[instruction]
89impl<Reg> const Instruction for Rv32Instruction<Reg>
90where
91 Reg: [const] Register<Type = u32>,
92{
93 type Reg = Reg;
94
95 #[inline(always)]
96 fn try_decode(instruction: u32) -> Option<Self> {
97 let opcode = (instruction & 0b111_1111) as u8;
98 let rd_bits = ((instruction >> 7) & 0x1f) as u8;
99 let funct3 = ((instruction >> 12) & 0b111) as u8;
100 let rs1_bits = ((instruction >> 15) & 0x1f) as u8;
101 let rs2_bits = ((instruction >> 20) & 0x1f) as u8;
102 let funct7 = ((instruction >> 25) & 0b111_1111) as u8;
103
104 match opcode {
105 0b011_0011 => {
107 let rd = Reg::from_bits(rd_bits)?;
108 let rs1 = Reg::from_bits(rs1_bits)?;
109 let rs2 = Reg::from_bits(rs2_bits)?;
110 match (funct3, funct7) {
111 (0b000, 0b000_0000) => Some(Self::Add { rd, rs1, rs2 }),
112 (0b000, 0b010_0000) => Some(Self::Sub { rd, rs1, rs2 }),
113 (0b001, 0b000_0000) => Some(Self::Sll { rd, rs1, rs2 }),
114 (0b010, 0b000_0000) => Some(Self::Slt { rd, rs1, rs2 }),
115 (0b011, 0b000_0000) => Some(Self::Sltu { rd, rs1, rs2 }),
116 (0b100, 0b000_0000) => Some(Self::Xor { rd, rs1, rs2 }),
117 (0b101, 0b000_0000) => Some(Self::Srl { rd, rs1, rs2 }),
118 (0b101, 0b010_0000) => Some(Self::Sra { rd, rs1, rs2 }),
119 (0b110, 0b000_0000) => Some(Self::Or { rd, rs1, rs2 }),
120 (0b111, 0b000_0000) => Some(Self::And { rd, rs1, rs2 }),
121 _ => None,
122 }
123 }
124 0b001_0011 => {
126 let rd = Reg::from_bits(rd_bits)?;
127 let rs1 = Reg::from_bits(rs1_bits)?;
128 let imm = (instruction.cast_signed() >> 20) as i16;
129 match funct3 {
130 0b000 => Some(Self::Addi { rd, rs1, imm }),
131 0b010 => Some(Self::Slti { rd, rs1, imm }),
132 0b011 => Some(Self::Sltiu { rd, rs1, imm }),
133 0b100 => Some(Self::Xori { rd, rs1, imm }),
134 0b110 => Some(Self::Ori { rd, rs1, imm }),
135 0b111 => Some(Self::Andi { rd, rs1, imm }),
136 0b001 => {
137 let shamt = (instruction >> 20) as u8 & 0b1_1111;
139 if funct7 == 0b000_0000 {
140 Some(Self::Slli { rd, rs1, shamt })
141 } else {
142 None
143 }
144 }
145 0b101 => {
146 let shamt = (instruction >> 20) as u8 & 0b1_1111;
148 match funct7 {
149 0b000_0000 => Some(Self::Srli { rd, rs1, shamt }),
150 0b010_0000 => Some(Self::Srai { rd, rs1, shamt }),
151 _ => None,
152 }
153 }
154 _ => None,
155 }
156 }
157 0b000_0011 => {
159 let rd = Reg::from_bits(rd_bits)?;
160 let rs1 = Reg::from_bits(rs1_bits)?;
161 let imm = (instruction.cast_signed() >> 20) as i16;
162 match funct3 {
163 0b000 => Some(Self::Lb { rd, rs1, imm }),
164 0b001 => Some(Self::Lh { rd, rs1, imm }),
165 0b010 => Some(Self::Lw { rd, rs1, imm }),
166 0b100 => Some(Self::Lbu { rd, rs1, imm }),
167 0b101 => Some(Self::Lhu { rd, rs1, imm }),
168 _ => None,
169 }
170 }
171 0b110_0111 => {
173 let rd = Reg::from_bits(rd_bits)?;
174 let rs1 = Reg::from_bits(rs1_bits)?;
175 if funct3 == 0b000 {
176 let imm = (instruction.cast_signed() >> 20) as i16;
177 Some(Self::Jalr { rd, rs1, imm })
178 } else {
179 None
180 }
181 }
182 0b010_0011 => {
184 let rs1 = Reg::from_bits(rs1_bits)?;
185 let rs2 = Reg::from_bits(rs2_bits)?;
186 let imm11_5 = ((instruction >> 25) & 0b111_1111).cast_signed();
187 let imm4_0 = ((instruction >> 7) & 0b1_1111).cast_signed();
188 let imm = (imm11_5 << 5) | imm4_0;
189 let imm = ((imm << 20) >> 20) as i16;
191 match funct3 {
192 0b000 => Some(Self::Sb { rs2, rs1, imm }),
193 0b001 => Some(Self::Sh { rs2, rs1, imm }),
194 0b010 => Some(Self::Sw { rs2, rs1, imm }),
195 _ => None,
196 }
197 }
198 0b110_0011 => {
200 let rs1 = Reg::from_bits(rs1_bits)?;
201 let rs2 = Reg::from_bits(rs2_bits)?;
202 let imm12 = ((instruction >> 31) & 1).cast_signed();
203 let imm10_5 = ((instruction >> 25) & 0b11_1111).cast_signed();
204 let imm4_1 = ((instruction >> 8) & 0b1111).cast_signed();
205 let imm11 = ((instruction >> 7) & 1).cast_signed();
206 let imm = (imm12 << 12) | (imm11 << 11) | (imm10_5 << 5) | (imm4_1 << 1);
207 let imm = I24::from_i32((imm << 19) >> 19);
209 match funct3 {
210 0b000 => Some(Self::Beq { rs1, rs2, imm }),
211 0b001 => Some(Self::Bne { rs1, rs2, imm }),
212 0b100 => Some(Self::Blt { rs1, rs2, imm }),
213 0b101 => Some(Self::Bge { rs1, rs2, imm }),
214 0b110 => Some(Self::Bltu { rs1, rs2, imm }),
215 0b111 => Some(Self::Bgeu { rs1, rs2, imm }),
216 _ => None,
217 }
218 }
219 0b011_0111 => {
221 let rd = Reg::from_bits(rd_bits)?;
222 let imm = I24WithZeroedBits::from_i32((instruction & 0xffff_f000).cast_signed());
223 Some(Self::Lui { rd, imm })
224 }
225 0b001_0111 => {
227 let rd = Reg::from_bits(rd_bits)?;
228 let imm = I24WithZeroedBits::from_i32((instruction & 0xffff_f000).cast_signed());
229 Some(Self::Auipc { rd, imm })
230 }
231 0b110_1111 => {
233 let rd = Reg::from_bits(rd_bits)?;
234 let imm20 = ((instruction >> 31) & 1).cast_signed();
235 let imm10_1 = ((instruction >> 21) & 0b11_1111_1111).cast_signed();
236 let imm11 = ((instruction >> 20) & 1).cast_signed();
237 let imm19_12 = ((instruction >> 12) & 0b1111_1111).cast_signed();
238 let imm = (imm20 << 20) | (imm19_12 << 12) | (imm11 << 11) | (imm10_1 << 1);
239 let imm = I24::from_i32((imm << 11) >> 11);
241 Some(Self::Jal { rd, imm })
242 }
243 0b000_1111 => {
245 if funct3 == 0b000 && rd_bits == 0 && rs1_bits == 0 {
246 let fm = (instruction >> 28) & 0b1111;
247 let pred = ((instruction >> 24) & 0xf) as u8;
248 let succ = ((instruction >> 20) & 0xf) as u8;
249 match fm {
250 0b0000 => Some(Self::Fence { pred, succ }),
251 0b1000 => {
252 if pred == 0b0011 && succ == 0b0011 {
254 Some(Self::FenceTso)
255 } else {
256 None
257 }
258 }
259 _ => None,
260 }
261 } else {
262 None
263 }
264 }
265 0b111_0011 => {
267 let imm = (instruction >> 20) & 0xfff;
268 if funct3 == 0 && rd_bits == 0 && rs1_bits == 0 {
269 match imm {
270 0 => Some(Self::Ecall),
271 1 => Some(Self::Ebreak),
272 _ => None,
273 }
274 } else if funct3 == 0b001 && rd_bits == 0 && rs1_bits == 0 && imm == 0xc00 {
275 Some(Self::Unimp)
278 } else {
279 None
280 }
281 }
282 _ => None,
283 }
284 }
285
286 #[inline(always)]
287 fn alignment() -> u8 {
288 align_of::<u32>() as u8
289 }
290
291 #[inline(always)]
292 fn size(&self) -> u8 {
293 size_of::<u32>() as u8
294 }
295}
296
297#[instruction]
298impl<Reg> fmt::Display for Rv32Instruction<Reg>
299where
300 Reg: fmt::Display,
301{
302 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
303 match self {
304 Self::Add { rd, rs1, rs2 } => write!(f, "add {rd}, {rs1}, {rs2}"),
305 Self::Sub { rd, rs1, rs2 } => write!(f, "sub {rd}, {rs1}, {rs2}"),
306 Self::Sll { rd, rs1, rs2 } => write!(f, "sll {rd}, {rs1}, {rs2}"),
307 Self::Slt { rd, rs1, rs2 } => write!(f, "slt {rd}, {rs1}, {rs2}"),
308 Self::Sltu { rd, rs1, rs2 } => write!(f, "sltu {rd}, {rs1}, {rs2}"),
309 Self::Xor { rd, rs1, rs2 } => write!(f, "xor {rd}, {rs1}, {rs2}"),
310 Self::Srl { rd, rs1, rs2 } => write!(f, "srl {rd}, {rs1}, {rs2}"),
311 Self::Sra { rd, rs1, rs2 } => write!(f, "sra {rd}, {rs1}, {rs2}"),
312 Self::Or { rd, rs1, rs2 } => write!(f, "or {rd}, {rs1}, {rs2}"),
313 Self::And { rd, rs1, rs2 } => write!(f, "and {rd}, {rs1}, {rs2}"),
314
315 Self::Addi { rd, rs1, imm } => write!(f, "addi {rd}, {rs1}, {imm}"),
316 Self::Slti { rd, rs1, imm } => write!(f, "slti {rd}, {rs1}, {imm}"),
317 Self::Sltiu { rd, rs1, imm } => write!(f, "sltiu {rd}, {rs1}, {imm}"),
318 Self::Xori { rd, rs1, imm } => write!(f, "xori {rd}, {rs1}, {imm}"),
319 Self::Ori { rd, rs1, imm } => write!(f, "ori {rd}, {rs1}, {imm}"),
320 Self::Andi { rd, rs1, imm } => write!(f, "andi {rd}, {rs1}, {imm}"),
321 Self::Slli { rd, rs1, shamt } => write!(f, "slli {rd}, {rs1}, {shamt}"),
322 Self::Srli { rd, rs1, shamt } => write!(f, "srli {rd}, {rs1}, {shamt}"),
323 Self::Srai { rd, rs1, shamt } => write!(f, "srai {rd}, {rs1}, {shamt}"),
324
325 Self::Lb { rd, rs1, imm } => write!(f, "lb {rd}, {imm}({rs1})"),
326 Self::Lh { rd, rs1, imm } => write!(f, "lh {rd}, {imm}({rs1})"),
327 Self::Lw { rd, rs1, imm } => write!(f, "lw {rd}, {imm}({rs1})"),
328 Self::Lbu { rd, rs1, imm } => write!(f, "lbu {rd}, {imm}({rs1})"),
329 Self::Lhu { rd, rs1, imm } => write!(f, "lhu {rd}, {imm}({rs1})"),
330
331 Self::Jalr { rd, rs1, imm } => write!(f, "jalr {rd}, {imm}({rs1})"),
332
333 Self::Sb { rs2, rs1, imm } => write!(f, "sb {rs2}, {imm}({rs1})"),
334 Self::Sh { rs2, rs1, imm } => write!(f, "sh {rs2}, {imm}({rs1})"),
335 Self::Sw { rs2, rs1, imm } => write!(f, "sw {rs2}, {imm}({rs1})"),
336
337 Self::Beq { rs1, rs2, imm } => write!(f, "beq {rs1}, {rs2}, {imm}"),
338 Self::Bne { rs1, rs2, imm } => write!(f, "bne {rs1}, {rs2}, {imm}"),
339 Self::Blt { rs1, rs2, imm } => write!(f, "blt {rs1}, {rs2}, {imm}"),
340 Self::Bge { rs1, rs2, imm } => write!(f, "bge {rs1}, {rs2}, {imm}"),
341 Self::Bltu { rs1, rs2, imm } => write!(f, "bltu {rs1}, {rs2}, {imm}"),
342 Self::Bgeu { rs1, rs2, imm } => write!(f, "bgeu {rs1}, {rs2}, {imm}"),
343
344 Self::Lui { rd, imm } => write!(f, "lui {rd}, 0x{:x}", imm.to_i32() >> 12),
345
346 Self::Auipc { rd, imm } => write!(f, "auipc {rd}, 0x{:x}", imm.to_i32() >> 12),
347
348 Self::Jal { rd, imm } => write!(f, "jal {rd}, {imm}"),
349
350 Self::Fence { pred, succ } => write!(f, "fence {pred}, {succ}"),
351 Self::FenceTso => write!(f, "fence.tso"),
352
353 Self::Ecall => write!(f, "ecall"),
354 Self::Ebreak => write!(f, "ebreak"),
355
356 Self::Unimp => write!(f, "unimp"),
357 }
358 }
359}