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