1#[cfg(test)]
4mod tests;
5
6use crate::instruction::Instruction;
7use crate::instruction::rv64::Rv64Instruction;
8use crate::registers::Register;
9use core::fmt;
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq)]
13pub enum Rv64ZbbInstruction<Reg> {
14 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 Clzw { rd: Reg, rs1: Reg },
20 Ctz { rd: Reg, rs1: Reg },
21 Ctzw { rd: Reg, rs1: Reg },
22 Cpop { rd: Reg, rs1: Reg },
23 Cpopw { rd: Reg, rs1: Reg },
24 Max { rd: Reg, rs1: Reg, rs2: Reg },
25 Maxu { rd: Reg, rs1: Reg, rs2: Reg },
26 Min { rd: Reg, rs1: Reg, rs2: Reg },
27 Minu { rd: Reg, rs1: Reg, rs2: Reg },
28 Sextb { rd: Reg, rs1: Reg },
29 Sexth { rd: Reg, rs1: Reg },
30 Zexth { rd: Reg, rs1: Reg },
31 Rol { rd: Reg, rs1: Reg, rs2: Reg },
32 Rolw { rd: Reg, rs1: Reg, rs2: Reg },
33 Ror { rd: Reg, rs1: Reg, rs2: Reg },
34 Rori { rd: Reg, rs1: Reg, shamt: u8 },
35 Roriw { rd: Reg, rs1: Reg, shamt: u8 },
36 Rorw { rd: Reg, rs1: Reg, rs2: Reg },
37 Orcb { rd: Reg, rs1: Reg },
38 Rev8 { rd: Reg, rs1: Reg },
39}
40
41impl<Reg> const Instruction for Rv64ZbbInstruction<Reg>
42where
43 Reg: [const] Register<Type = u64>,
44{
45 type Base = Rv64Instruction<Reg>;
46
47 #[inline(always)]
48 fn try_decode(instruction: u32) -> Option<Self> {
49 let opcode = (instruction & 0b111_1111) as u8;
50 let rd_bits = ((instruction >> 7) & 0x1f) as u8;
51 let funct3 = ((instruction >> 12) & 0b111) as u8;
52 let rs1_bits = ((instruction >> 15) & 0x1f) as u8;
53 let rs2_bits = ((instruction >> 20) & 0x1f) as u8;
54 let funct7 = ((instruction >> 25) & 0b111_1111) as u8;
55 let funct6 = ((instruction >> 26) & 0b11_1111) as u8;
56 let low6 = ((instruction >> 20) & 0x3f) as u8;
58 let funct12 = ((instruction >> 20) & 0xfff) as u16;
59
60 Some(match opcode {
61 0b0010011 => {
63 let rd = Reg::from_bits(rd_bits)?;
64 let rs1 = Reg::from_bits(rs1_bits)?;
65 match funct3 {
66 0b001 => {
67 if funct6 == 0b011000 {
68 match low6 {
69 0 => Self::Clz { rd, rs1 },
70 1 => Self::Ctz { rd, rs1 },
71 2 => Self::Cpop { rd, rs1 },
72 4 => Self::Sextb { rd, rs1 },
73 5 => Self::Sexth { rd, rs1 },
74 _ => {
75 return None;
76 }
77 }
78 } else {
79 return None;
80 }
81 }
82 0b101 => {
83 if funct12 == 0b011010111000 {
84 Self::Rev8 { rd, rs1 }
85 } else if funct6 == 0b011000 {
86 Self::Rori {
87 rd,
88 rs1,
89 shamt: low6,
90 }
91 } else {
92 return None;
93 }
94 }
95 _ => {
96 return None;
97 }
98 }
99 }
100 0b0110011 => {
102 let rd = Reg::from_bits(rd_bits)?;
103 let rs1 = Reg::from_bits(rs1_bits)?;
104 let rs2 = Reg::from_bits(rs2_bits)?;
105 match funct3 {
106 0b001 => {
107 if funct7 == 0b0110000 {
108 Self::Rol { rd, rs1, rs2 }
109 } else {
110 return None;
111 }
112 }
113 0b010 => {
114 if funct7 == 0b0000101 {
115 Self::Min { rd, rs1, rs2 }
116 } else {
117 return None;
118 }
119 }
120 0b011 => {
121 if funct7 == 0b0000101 {
122 Self::Minu { rd, rs1, rs2 }
123 } else {
124 return None;
125 }
126 }
127 0b100 => match funct7 {
128 0b0100000 => Self::Xnor { rd, rs1, rs2 },
129 0b0000101 => Self::Max { rd, rs1, rs2 },
130 _ => {
131 return None;
132 }
133 },
134 0b101 => match funct7 {
135 0b0110000 => Self::Ror { rd, rs1, rs2 },
136 0b0000101 => {
137 if rs2_bits == 0b00111 {
138 Self::Orcb { rd, rs1 }
139 } else {
140 Self::Maxu { rd, rs1, rs2 }
141 }
142 }
143 _ => {
144 return None;
145 }
146 },
147 0b110 => {
148 if funct7 == 0b0100000 {
149 Self::Orn { rd, rs1, rs2 }
150 } else {
151 return None;
152 }
153 }
154 0b111 => {
155 if funct7 == 0b0100000 {
156 Self::Andn { rd, rs1, rs2 }
157 } else {
158 return None;
159 }
160 }
161 _ => {
162 return None;
163 }
164 }
165 }
166 0b0011011 => {
168 let rd = Reg::from_bits(rd_bits)?;
169 let rs1 = Reg::from_bits(rs1_bits)?;
170 match funct3 {
171 0b001 => {
172 if funct7 == 0b0110000 {
173 match rs2_bits {
174 0 => Self::Clzw { rd, rs1 },
175 1 => Self::Ctzw { rd, rs1 },
176 2 => Self::Cpopw { rd, rs1 },
177 _ => {
178 return None;
179 }
180 }
181 } else {
182 return None;
183 }
184 }
185 0b101 => {
186 if funct7 == 0b0110000 {
187 let shamt = rs2_bits;
188 Self::Roriw { rd, rs1, shamt }
189 } else {
190 return None;
191 }
192 }
193 _ => {
194 return None;
195 }
196 }
197 }
198 0b0111011 => {
200 let rd = Reg::from_bits(rd_bits)?;
201 let rs1 = Reg::from_bits(rs1_bits)?;
202 let rs2 = Reg::from_bits(rs2_bits)?;
203 match funct3 {
204 0b001 => {
205 if funct7 == 0b0110000 {
206 Self::Rolw { rd, rs1, rs2 }
207 } else {
208 return None;
209 }
210 }
211 0b100 => {
212 if funct7 == 0b0000100 && rs2_bits == 0 {
213 Self::Zexth { rd, rs1 }
214 } else {
215 return None;
216 }
217 }
218 0b101 => {
219 if funct7 == 0b0110000 {
220 Self::Rorw { rd, rs1, rs2 }
221 } else {
222 return None;
223 }
224 }
225 _ => {
226 return None;
227 }
228 }
229 }
230 _ => {
231 return None;
232 }
233 })
234 }
235
236 #[inline(always)]
237 fn size(&self) -> u8 {
238 size_of::<u32>() as u8
239 }
240}
241
242impl<Reg> fmt::Display for Rv64ZbbInstruction<Reg>
243where
244 Reg: fmt::Display,
245{
246 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
247 match self {
248 Self::Andn { rd, rs1, rs2 } => write!(f, "andn {}, {}, {}", rd, rs1, rs2),
249 Self::Orn { rd, rs1, rs2 } => write!(f, "orn {}, {}, {}", rd, rs1, rs2),
250 Self::Xnor { rd, rs1, rs2 } => write!(f, "xnor {}, {}, {}", rd, rs1, rs2),
251 Self::Clz { rd, rs1 } => write!(f, "clz {}, {}", rd, rs1),
252 Self::Clzw { rd, rs1 } => write!(f, "clzw {}, {}", rd, rs1),
253 Self::Ctz { rd, rs1 } => write!(f, "ctz {}, {}", rd, rs1),
254 Self::Ctzw { rd, rs1 } => write!(f, "ctzw {}, {}", rd, rs1),
255 Self::Cpop { rd, rs1 } => write!(f, "cpop {}, {}", rd, rs1),
256 Self::Cpopw { rd, rs1 } => write!(f, "cpopw {}, {}", rd, rs1),
257 Self::Max { rd, rs1, rs2 } => write!(f, "max {}, {}, {}", rd, rs1, rs2),
258 Self::Maxu { rd, rs1, rs2 } => write!(f, "maxu {}, {}, {}", rd, rs1, rs2),
259 Self::Min { rd, rs1, rs2 } => write!(f, "min {}, {}, {}", rd, rs1, rs2),
260 Self::Minu { rd, rs1, rs2 } => write!(f, "minu {}, {}, {}", rd, rs1, rs2),
261 Self::Sextb { rd, rs1 } => write!(f, "sext.b {}, {}", rd, rs1),
262 Self::Sexth { rd, rs1 } => write!(f, "sext.h {}, {}", rd, rs1),
263 Self::Zexth { rd, rs1 } => write!(f, "zext.h {}, {}", rd, rs1),
264 Self::Rol { rd, rs1, rs2 } => write!(f, "rol {}, {}, {}", rd, rs1, rs2),
265 Self::Rolw { rd, rs1, rs2 } => write!(f, "rolw {}, {}, {}", rd, rs1, rs2),
266 Self::Ror { rd, rs1, rs2 } => write!(f, "ror {}, {}, {}", rd, rs1, rs2),
267 Self::Rori { rd, rs1, shamt } => write!(f, "rori {}, {}, {}", rd, rs1, shamt),
268 Self::Roriw { rd, rs1, shamt } => write!(f, "roriw {}, {}, {}", rd, rs1, shamt),
269 Self::Rorw { rd, rs1, rs2 } => write!(f, "rorw {}, {}, {}", rd, rs1, rs2),
270 Self::Orcb { rd, rs1 } => write!(f, "orc.b {}, {}", rd, rs1),
271 Self::Rev8 { rd, rs1 } => write!(f, "rev8 {}, {}", rd, rs1),
272 }
273 }
274}