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