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