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 == 0b001010000111 {
84 Some(Self::Orcb { rd, rs1 })
85 } else if funct12 == 0b011010111000 {
86 Some(Self::Rev8 { rd, rs1 })
87 } else if funct6 == 0b011000 {
88 Some(Self::Rori {
89 rd,
90 rs1,
91 shamt: low6,
92 })
93 } else {
94 None
95 }
96 }
97 _ => None,
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 Some(Self::Rol { rd, rs1, rs2 })
109 } else {
110 None
111 }
112 }
113 0b100 => match funct7 {
114 0b0100000 => Some(Self::Xnor { rd, rs1, rs2 }),
115 0b0000101 => Some(Self::Min { rd, rs1, rs2 }),
116 _ => None,
117 },
118 0b101 => match funct7 {
119 0b0110000 => Some(Self::Ror { rd, rs1, rs2 }),
120 0b0000101 => Some(Self::Minu { rd, rs1, rs2 }),
121 _ => None,
122 },
123 0b110 => match funct7 {
124 0b0100000 => Some(Self::Orn { rd, rs1, rs2 }),
125 0b0000101 => Some(Self::Max { rd, rs1, rs2 }),
126 _ => None,
127 },
128 0b111 => match funct7 {
129 0b0100000 => Some(Self::Andn { rd, rs1, rs2 }),
130 0b0000101 => Some(Self::Maxu { rd, rs1, rs2 }),
131 _ => None,
132 },
133 _ => None,
134 }
135 }
136 0b0011011 => {
138 let rd = Reg::from_bits(rd_bits)?;
139 let rs1 = Reg::from_bits(rs1_bits)?;
140 match funct3 {
141 0b001 => {
142 if funct7 == 0b0110000 {
143 match rs2_bits {
144 0 => Some(Self::Clzw { rd, rs1 }),
145 1 => Some(Self::Ctzw { rd, rs1 }),
146 2 => Some(Self::Cpopw { rd, rs1 }),
147 _ => None,
148 }
149 } else {
150 None
151 }
152 }
153 0b101 => {
154 if funct7 == 0b0110000 {
155 let shamt = rs2_bits;
156 Some(Self::Roriw { rd, rs1, shamt })
157 } else {
158 None
159 }
160 }
161 _ => None,
162 }
163 }
164 0b0111011 => {
166 let rd = Reg::from_bits(rd_bits)?;
167 let rs1 = Reg::from_bits(rs1_bits)?;
168 let rs2 = Reg::from_bits(rs2_bits)?;
169 match funct3 {
170 0b001 => {
171 if funct7 == 0b0110000 {
172 Some(Self::Rolw { rd, rs1, rs2 })
173 } else {
174 None
175 }
176 }
177 0b100 => {
178 if funct7 == 0b0000100 && rs2_bits == 0 {
179 Some(Self::Zexth { rd, rs1 })
180 } else {
181 None
182 }
183 }
184 0b101 => {
185 if funct7 == 0b0110000 {
186 Some(Self::Rorw { rd, rs1, rs2 })
187 } else {
188 None
189 }
190 }
191 _ => None,
192 }
193 }
194 _ => None,
195 }
196 }
197
198 #[inline(always)]
199 fn alignment() -> u8 {
200 size_of::<u32>() as u8
201 }
202
203 #[inline(always)]
204 fn size(&self) -> u8 {
205 size_of::<u32>() as u8
206 }
207}
208
209impl<Reg> fmt::Display for Rv64ZbbInstruction<Reg>
210where
211 Reg: fmt::Display,
212{
213 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
214 match self {
215 Self::Andn { rd, rs1, rs2 } => write!(f, "andn {}, {}, {}", rd, rs1, rs2),
216 Self::Orn { rd, rs1, rs2 } => write!(f, "orn {}, {}, {}", rd, rs1, rs2),
217 Self::Xnor { rd, rs1, rs2 } => write!(f, "xnor {}, {}, {}", rd, rs1, rs2),
218 Self::Clz { rd, rs1 } => write!(f, "clz {}, {}", rd, rs1),
219 Self::Clzw { rd, rs1 } => write!(f, "clzw {}, {}", rd, rs1),
220 Self::Ctz { rd, rs1 } => write!(f, "ctz {}, {}", rd, rs1),
221 Self::Ctzw { rd, rs1 } => write!(f, "ctzw {}, {}", rd, rs1),
222 Self::Cpop { rd, rs1 } => write!(f, "cpop {}, {}", rd, rs1),
223 Self::Cpopw { rd, rs1 } => write!(f, "cpopw {}, {}", rd, rs1),
224 Self::Max { rd, rs1, rs2 } => write!(f, "max {}, {}, {}", rd, rs1, rs2),
225 Self::Maxu { rd, rs1, rs2 } => write!(f, "maxu {}, {}, {}", rd, rs1, rs2),
226 Self::Min { rd, rs1, rs2 } => write!(f, "min {}, {}, {}", rd, rs1, rs2),
227 Self::Minu { rd, rs1, rs2 } => write!(f, "minu {}, {}, {}", rd, rs1, rs2),
228 Self::Sextb { rd, rs1 } => write!(f, "sext.b {}, {}", rd, rs1),
229 Self::Sexth { rd, rs1 } => write!(f, "sext.h {}, {}", rd, rs1),
230 Self::Zexth { rd, rs1 } => write!(f, "zext.h {}, {}", rd, rs1),
231 Self::Rol { rd, rs1, rs2 } => write!(f, "rol {}, {}, {}", rd, rs1, rs2),
232 Self::Rolw { rd, rs1, rs2 } => write!(f, "rolw {}, {}, {}", rd, rs1, rs2),
233 Self::Ror { rd, rs1, rs2 } => write!(f, "ror {}, {}, {}", rd, rs1, rs2),
234 Self::Rori { rd, rs1, shamt } => write!(f, "rori {}, {}, {}", rd, rs1, shamt),
235 Self::Roriw { rd, rs1, shamt } => write!(f, "roriw {}, {}, {}", rd, rs1, shamt),
236 Self::Rorw { rd, rs1, rs2 } => write!(f, "rorw {}, {}, {}", rd, rs1, rs2),
237 Self::Orcb { rd, rs1 } => write!(f, "orc.b {}, {}", rd, rs1),
238 Self::Rev8 { rd, rs1 } => write!(f, "rev8 {}, {}", rd, rs1),
239 }
240 }
241}