1#[cfg(test)]
4mod tests;
5
6use crate::hart::HartConfig;
7use crate::instructions::rv32::a::zaamo::Rv32ZaamoInstruction;
8use crate::instructions::{ImplementedExtension, Instruction, IsaExtension};
9use crate::registers::general_purpose::Register;
10use ab_riscv_macros::instruction;
11use core::fmt;
12
13#[instruction(inherit = [Rv32ZaamoInstruction])]
15#[derive(Debug, Clone, Copy)]
16#[derive_const(PartialEq, Eq)]
17#[rustfmt::skip]
18pub enum Rv32ZabhaInstruction<Hart>
19where
20 Hart: HartConfig,
21{
22 AmoswapB { rd: Hart::Reg, rs1: Hart::Reg, rs2: Hart::Reg, aq: bool, rl: bool },
23 AmoswapH { rd: Hart::Reg, rs1: Hart::Reg, rs2: Hart::Reg, aq: bool, rl: bool },
24 AmoaddB { rd: Hart::Reg, rs1: Hart::Reg, rs2: Hart::Reg, aq: bool, rl: bool },
25 AmoaddH { rd: Hart::Reg, rs1: Hart::Reg, rs2: Hart::Reg, aq: bool, rl: bool },
26 AmoxorB { rd: Hart::Reg, rs1: Hart::Reg, rs2: Hart::Reg, aq: bool, rl: bool },
27 AmoxorH { rd: Hart::Reg, rs1: Hart::Reg, rs2: Hart::Reg, aq: bool, rl: bool },
28 AmoandB { rd: Hart::Reg, rs1: Hart::Reg, rs2: Hart::Reg, aq: bool, rl: bool },
29 AmoandH { rd: Hart::Reg, rs1: Hart::Reg, rs2: Hart::Reg, aq: bool, rl: bool },
30 AmoorB { rd: Hart::Reg, rs1: Hart::Reg, rs2: Hart::Reg, aq: bool, rl: bool },
31 AmoorH { rd: Hart::Reg, rs1: Hart::Reg, rs2: Hart::Reg, aq: bool, rl: bool },
32 AmominB { rd: Hart::Reg, rs1: Hart::Reg, rs2: Hart::Reg, aq: bool, rl: bool },
33 AmominH { rd: Hart::Reg, rs1: Hart::Reg, rs2: Hart::Reg, aq: bool, rl: bool },
34 AmomaxB { rd: Hart::Reg, rs1: Hart::Reg, rs2: Hart::Reg, aq: bool, rl: bool },
35 AmomaxH { rd: Hart::Reg, rs1: Hart::Reg, rs2: Hart::Reg, aq: bool, rl: bool },
36 AmominuB { rd: Hart::Reg, rs1: Hart::Reg, rs2: Hart::Reg, aq: bool, rl: bool },
37 AmominuH { rd: Hart::Reg, rs1: Hart::Reg, rs2: Hart::Reg, aq: bool, rl: bool },
38 AmomaxuB { rd: Hart::Reg, rs1: Hart::Reg, rs2: Hart::Reg, aq: bool, rl: bool },
39 AmomaxuH { rd: Hart::Reg, rs1: Hart::Reg, rs2: Hart::Reg, aq: bool, rl: bool },
40 #[instruction(if = [Rv32ZacasInstruction])]
42 AmocasB { rd: Hart::Reg, rs1: Hart::Reg, rs2: Hart::Reg, aq: bool, rl: bool },
43 #[instruction(if = [Rv32ZacasInstruction])]
45 AmocasH { rd: Hart::Reg, rs1: Hart::Reg, rs2: Hart::Reg, aq: bool, rl: bool },
46}
47
48#[instruction]
49const impl<Reg, Hart> Instruction for Rv32ZabhaInstruction<Hart>
50where
51 Reg: [const] Register<Type = u32>,
52 Hart: [const] HartConfig<Reg = Reg>,
53{
54 const OWN_ISA_EXTENSIONS: &'static [IsaExtension] = &[IsaExtension::new("zabha", 1, 0)];
55
56 const ALIGNMENT: u8 = align_of::<u32>() as u8;
57
58 type Hart = Hart;
59
60 #[inline(always)]
61 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
62 fn try_decode(instruction: u32) -> Option<Self> {
63 let opcode = (instruction & 0b111_1111) as u8;
64 let rd_bits = ((instruction >> 7) & 0x1f) as u8;
65 let funct3 = ((instruction >> 12) & 0b111) as u8;
66 let rs1_bits = ((instruction >> 15) & 0x1f) as u8;
67 let rs2_bits = ((instruction >> 20) & 0x1f) as u8;
68 let funct7 = ((instruction >> 25) & 0b111_1111) as u8;
69
70 match (opcode, funct3) {
71 (0b010_1111, 0b000 | 0b001) => {
73 let rd = Reg::from_bits(rd_bits)?;
74 let rs1 = Reg::from_bits(rs1_bits)?;
75 let rs2 = Reg::from_bits(rs2_bits)?;
76 let funct5 = funct7 >> 2;
77 let aq = (funct7 & 0b10) != 0;
78 let rl = (funct7 & 0b01) != 0;
79
80 if funct3 == 0b000 {
81 match funct5 {
82 0b00001 => Some(Self::AmoswapB {
83 rd,
84 rs1,
85 rs2,
86 aq,
87 rl,
88 }),
89 0b00000 => Some(Self::AmoaddB {
90 rd,
91 rs1,
92 rs2,
93 aq,
94 rl,
95 }),
96 0b00100 => Some(Self::AmoxorB {
97 rd,
98 rs1,
99 rs2,
100 aq,
101 rl,
102 }),
103 0b01100 => Some(Self::AmoandB {
104 rd,
105 rs1,
106 rs2,
107 aq,
108 rl,
109 }),
110 0b01000 => Some(Self::AmoorB {
111 rd,
112 rs1,
113 rs2,
114 aq,
115 rl,
116 }),
117 0b10000 => Some(Self::AmominB {
118 rd,
119 rs1,
120 rs2,
121 aq,
122 rl,
123 }),
124 0b10100 => Some(Self::AmomaxB {
125 rd,
126 rs1,
127 rs2,
128 aq,
129 rl,
130 }),
131 0b11000 => Some(Self::AmominuB {
132 rd,
133 rs1,
134 rs2,
135 aq,
136 rl,
137 }),
138 0b11100 => Some(Self::AmomaxuB {
139 rd,
140 rs1,
141 rs2,
142 aq,
143 rl,
144 }),
145 0b00101 => Some(Self::AmocasB {
146 rd,
147 rs1,
148 rs2,
149 aq,
150 rl,
151 }),
152 _ => None,
153 }
154 } else {
155 match funct5 {
156 0b00001 => Some(Self::AmoswapH {
157 rd,
158 rs1,
159 rs2,
160 aq,
161 rl,
162 }),
163 0b00000 => Some(Self::AmoaddH {
164 rd,
165 rs1,
166 rs2,
167 aq,
168 rl,
169 }),
170 0b00100 => Some(Self::AmoxorH {
171 rd,
172 rs1,
173 rs2,
174 aq,
175 rl,
176 }),
177 0b01100 => Some(Self::AmoandH {
178 rd,
179 rs1,
180 rs2,
181 aq,
182 rl,
183 }),
184 0b01000 => Some(Self::AmoorH {
185 rd,
186 rs1,
187 rs2,
188 aq,
189 rl,
190 }),
191 0b10000 => Some(Self::AmominH {
192 rd,
193 rs1,
194 rs2,
195 aq,
196 rl,
197 }),
198 0b10100 => Some(Self::AmomaxH {
199 rd,
200 rs1,
201 rs2,
202 aq,
203 rl,
204 }),
205 0b11000 => Some(Self::AmominuH {
206 rd,
207 rs1,
208 rs2,
209 aq,
210 rl,
211 }),
212 0b11100 => Some(Self::AmomaxuH {
213 rd,
214 rs1,
215 rs2,
216 aq,
217 rl,
218 }),
219 0b00101 => Some(Self::AmocasH {
220 rd,
221 rs1,
222 rs2,
223 aq,
224 rl,
225 }),
226 _ => None,
227 }
228 }
229 }
230 _ => None,
231 }
232 }
233
234 #[inline(always)]
235 fn size(&self) -> u8 {
236 size_of::<u32>() as u8
237 }
238}
239
240#[inline(always)]
242fn aq_rl_suffix(aq: &bool, rl: &bool) -> &'static str {
243 match (*aq, *rl) {
244 (false, false) => "",
245 (true, false) => ".aq",
246 (false, true) => ".rl",
247 (true, true) => ".aqrl",
248 }
249}
250
251#[instruction]
252impl<Reg, Hart> fmt::Display for Rv32ZabhaInstruction<Hart>
253where
254 Reg: fmt::Display + Copy,
255 Hart: HartConfig<Reg = Reg>,
256{
257 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
258 #[rustfmt::skip]
259 match self {
260 Self::AmoswapB { rd, rs1, rs2, aq, rl } => write!(f, "amoswap.b{} {rd}, {rs2}, ({rs1})", aq_rl_suffix(aq, rl)),
261 Self::AmoswapH { rd, rs1, rs2, aq, rl } => write!(f, "amoswap.h{} {rd}, {rs2}, ({rs1})", aq_rl_suffix(aq, rl)),
262 Self::AmoaddB { rd, rs1, rs2, aq, rl } => write!(f, "amoadd.b{} {rd}, {rs2}, ({rs1})", aq_rl_suffix(aq, rl)),
263 Self::AmoaddH { rd, rs1, rs2, aq, rl } => write!(f, "amoadd.h{} {rd}, {rs2}, ({rs1})", aq_rl_suffix(aq, rl)),
264 Self::AmoxorB { rd, rs1, rs2, aq, rl } => write!(f, "amoxor.b{} {rd}, {rs2}, ({rs1})", aq_rl_suffix(aq, rl)),
265 Self::AmoxorH { rd, rs1, rs2, aq, rl } => write!(f, "amoxor.h{} {rd}, {rs2}, ({rs1})", aq_rl_suffix(aq, rl)),
266 Self::AmoandB { rd, rs1, rs2, aq, rl } => write!(f, "amoand.b{} {rd}, {rs2}, ({rs1})", aq_rl_suffix(aq, rl)),
267 Self::AmoandH { rd, rs1, rs2, aq, rl } => write!(f, "amoand.h{} {rd}, {rs2}, ({rs1})", aq_rl_suffix(aq, rl)),
268 Self::AmoorB { rd, rs1, rs2, aq, rl } => write!(f, "amoor.b{} {rd}, {rs2}, ({rs1})", aq_rl_suffix(aq, rl)),
269 Self::AmoorH { rd, rs1, rs2, aq, rl } => write!(f, "amoor.h{} {rd}, {rs2}, ({rs1})", aq_rl_suffix(aq, rl)),
270 Self::AmominB { rd, rs1, rs2, aq, rl } => write!(f, "amomin.b{} {rd}, {rs2}, ({rs1})", aq_rl_suffix(aq, rl)),
271 Self::AmominH { rd, rs1, rs2, aq, rl } => write!(f, "amomin.h{} {rd}, {rs2}, ({rs1})", aq_rl_suffix(aq, rl)),
272 Self::AmomaxB { rd, rs1, rs2, aq, rl } => write!(f, "amomax.b{} {rd}, {rs2}, ({rs1})", aq_rl_suffix(aq, rl)),
273 Self::AmomaxH { rd, rs1, rs2, aq, rl } => write!(f, "amomax.h{} {rd}, {rs2}, ({rs1})", aq_rl_suffix(aq, rl)),
274 Self::AmominuB { rd, rs1, rs2, aq, rl } => write!(f, "amominu.b{} {rd}, {rs2}, ({rs1})", aq_rl_suffix(aq, rl)),
275 Self::AmominuH { rd, rs1, rs2, aq, rl } => write!(f, "amominu.h{} {rd}, {rs2}, ({rs1})", aq_rl_suffix(aq, rl)),
276 Self::AmomaxuB { rd, rs1, rs2, aq, rl } => write!(f, "amomaxu.b{} {rd}, {rs2}, ({rs1})", aq_rl_suffix(aq, rl)),
277 Self::AmomaxuH { rd, rs1, rs2, aq, rl } => write!(f, "amomaxu.h{} {rd}, {rs2}, ({rs1})", aq_rl_suffix(aq, rl)),
278 Self::AmocasB { rd, rs1, rs2, aq, rl } => write!(f, "amocas.b{} {rd}, {rs2}, ({rs1})", aq_rl_suffix(aq, rl)),
279 Self::AmocasH { rd, rs1, rs2, aq, rl } => write!(f, "amocas.h{} {rd}, {rs2}, ({rs1})", aq_rl_suffix(aq, rl)),
280 }
281 }
282}