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