1#[cfg(test)]
4mod tests;
5
6use crate::instructions::Instruction;
7use crate::registers::general_purpose::Register;
8use ab_riscv_macros::instruction;
9use core::fmt;
10
11#[instruction]
13#[derive(Debug, Clone, Copy, PartialEq, Eq)]
14pub enum Rv32ZbbInstruction<Reg> {
15 Andn { rd: Reg, rs1: Reg, rs2: Reg },
16 Orn { rd: Reg, rs1: Reg, rs2: Reg },
17 Xnor { rd: Reg, rs1: Reg, rs2: Reg },
18 Clz { rd: Reg, rs1: Reg },
19 Ctz { rd: Reg, rs1: Reg },
20 Cpop { rd: Reg, rs1: Reg },
21 Max { rd: Reg, rs1: Reg, rs2: Reg },
22 Maxu { rd: Reg, rs1: Reg, rs2: Reg },
23 Min { rd: Reg, rs1: Reg, rs2: Reg },
24 Minu { rd: Reg, rs1: Reg, rs2: Reg },
25 Sextb { rd: Reg, rs1: Reg },
26 Sexth { rd: Reg, rs1: Reg },
27 Zexth { rd: Reg, rs1: Reg },
28 Rol { rd: Reg, rs1: Reg, rs2: Reg },
29 Ror { rd: Reg, rs1: Reg, rs2: Reg },
30 Rori { rd: Reg, rs1: Reg, shamt: u8 },
31 Orcb { rd: Reg, rs1: Reg },
32 Rev8 { rd: Reg, rs1: Reg },
33}
34
35#[instruction]
36impl<Reg> const Instruction for Rv32ZbbInstruction<Reg>
37where
38 Reg: [const] Register<Type = u32>,
39{
40 type Reg = Reg;
41
42 #[inline(always)]
43 fn try_decode(instruction: u32) -> Option<Self> {
44 let opcode = (instruction & 0b111_1111) as u8;
45 let rd_bits = ((instruction >> 7) & 0x1f) as u8;
46 let funct3 = ((instruction >> 12) & 0b111) as u8;
47 let rs1_bits = ((instruction >> 15) & 0x1f) as u8;
48 let rs2_bits = ((instruction >> 20) & 0x1f) as u8;
49 let funct7 = ((instruction >> 25) & 0b111_1111) as u8;
50 let funct6 = ((instruction >> 26) & 0b11_1111) as u8;
51 let low5 = ((instruction >> 20) & 0x1f) as u8;
53 let funct12 = ((instruction >> 20) & 0xfff) as u16;
54
55 match opcode {
56 0b0010011 => {
58 let rd = Reg::from_bits(rd_bits)?;
59 let rs1 = Reg::from_bits(rs1_bits)?;
60 match funct3 {
61 0b001 => {
62 if funct7 == 0b0110000 {
64 match rs2_bits {
65 0 => Some(Self::Clz { rd, rs1 }),
66 1 => Some(Self::Ctz { rd, rs1 }),
67 2 => Some(Self::Cpop { rd, rs1 }),
68 4 => Some(Self::Sextb { rd, rs1 }),
69 5 => Some(Self::Sexth { rd, rs1 }),
70 _ => None,
71 }
72 } else {
73 None
74 }
75 }
76 0b101 => {
77 if funct12 == 0b001010000111 {
81 Some(Self::Orcb { rd, rs1 })
82 } else if funct12 == 0b011010011000 {
83 Some(Self::Rev8 { rd, rs1 })
84 } else if funct6 == 0b011000 {
85 Some(Self::Rori {
86 rd,
87 rs1,
88 shamt: low5,
89 })
90 } else {
91 None
92 }
93 }
94 _ => None,
95 }
96 }
97 0b0110011 => {
99 let rd = Reg::from_bits(rd_bits)?;
100 let rs1 = Reg::from_bits(rs1_bits)?;
101 let rs2 = Reg::from_bits(rs2_bits)?;
102 match funct3 {
103 0b001 => {
104 if funct7 == 0b0110000 {
105 Some(Self::Rol { rd, rs1, rs2 })
106 } else {
107 None
108 }
109 }
110 0b100 => match funct7 {
111 0b0100000 => Some(Self::Xnor { rd, rs1, rs2 }),
112 0b0000101 => Some(Self::Min { rd, rs1, rs2 }),
113 0b0000100 => {
115 if rs2_bits == 0 {
116 Some(Self::Zexth { rd, rs1 })
117 } else {
118 None
119 }
120 }
121 _ => None,
122 },
123 0b101 => match funct7 {
124 0b0110000 => Some(Self::Ror { rd, rs1, rs2 }),
125 0b0000101 => Some(Self::Minu { rd, rs1, rs2 }),
126 _ => None,
127 },
128 0b110 => match funct7 {
129 0b0100000 => Some(Self::Orn { rd, rs1, rs2 }),
130 0b0000101 => Some(Self::Max { rd, rs1, rs2 }),
131 _ => None,
132 },
133 0b111 => match funct7 {
134 0b0100000 => Some(Self::Andn { rd, rs1, rs2 }),
135 0b0000101 => Some(Self::Maxu { rd, rs1, rs2 }),
136 _ => None,
137 },
138 _ => None,
139 }
140 }
141 _ => None,
142 }
143 }
144
145 #[inline(always)]
146 fn alignment() -> u8 {
147 size_of::<u32>() as u8
148 }
149
150 #[inline(always)]
151 fn size(&self) -> u8 {
152 size_of::<u32>() as u8
153 }
154}
155
156impl<Reg> fmt::Display for Rv32ZbbInstruction<Reg>
157where
158 Reg: fmt::Display,
159{
160 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
161 match self {
162 Self::Andn { rd, rs1, rs2 } => write!(f, "andn {}, {}, {}", rd, rs1, rs2),
163 Self::Orn { rd, rs1, rs2 } => write!(f, "orn {}, {}, {}", rd, rs1, rs2),
164 Self::Xnor { rd, rs1, rs2 } => write!(f, "xnor {}, {}, {}", rd, rs1, rs2),
165 Self::Clz { rd, rs1 } => write!(f, "clz {}, {}", rd, rs1),
166 Self::Ctz { rd, rs1 } => write!(f, "ctz {}, {}", rd, rs1),
167 Self::Cpop { rd, rs1 } => write!(f, "cpop {}, {}", rd, rs1),
168 Self::Max { rd, rs1, rs2 } => write!(f, "max {}, {}, {}", rd, rs1, rs2),
169 Self::Maxu { rd, rs1, rs2 } => write!(f, "maxu {}, {}, {}", rd, rs1, rs2),
170 Self::Min { rd, rs1, rs2 } => write!(f, "min {}, {}, {}", rd, rs1, rs2),
171 Self::Minu { rd, rs1, rs2 } => write!(f, "minu {}, {}, {}", rd, rs1, rs2),
172 Self::Sextb { rd, rs1 } => write!(f, "sext.b {}, {}", rd, rs1),
173 Self::Sexth { rd, rs1 } => write!(f, "sext.h {}, {}", rd, rs1),
174 Self::Zexth { rd, rs1 } => write!(f, "zext.h {}, {}", rd, rs1),
175 Self::Rol { rd, rs1, rs2 } => write!(f, "rol {}, {}, {}", rd, rs1, rs2),
176 Self::Ror { rd, rs1, rs2 } => write!(f, "ror {}, {}, {}", rd, rs1, rs2),
177 Self::Rori { rd, rs1, shamt } => write!(f, "rori {}, {}, {}", rd, rs1, shamt),
178 Self::Orcb { rd, rs1 } => write!(f, "orc.b {}, {}", rd, rs1),
179 Self::Rev8 { rd, rs1 } => write!(f, "rev8 {}, {}", rd, rs1),
180 }
181 }
182}