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