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