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)]
15#[rustfmt::skip]
16pub enum Rv32ZaamoInstruction<Reg> {
17 Amoswap { rd: Reg, rs1: Reg, rs2: Reg, aq: bool, rl: bool },
18 Amoadd { rd: Reg, rs1: Reg, rs2: Reg, aq: bool, rl: bool },
19 Amoxor { rd: Reg, rs1: Reg, rs2: Reg, aq: bool, rl: bool },
20 Amoand { rd: Reg, rs1: Reg, rs2: Reg, aq: bool, rl: bool },
21 Amoor { rd: Reg, rs1: Reg, rs2: Reg, aq: bool, rl: bool },
22 Amomin { rd: Reg, rs1: Reg, rs2: Reg, aq: bool, rl: bool },
23 Amomax { rd: Reg, rs1: Reg, rs2: Reg, aq: bool, rl: bool },
24 Amominu { rd: Reg, rs1: Reg, rs2: Reg, aq: bool, rl: bool },
25 Amomaxu { rd: Reg, rs1: Reg, rs2: Reg, aq: bool, rl: bool },
26}
27
28#[instruction]
29const impl<Reg> Instruction for Rv32ZaamoInstruction<Reg>
30where
31 Reg: [const] Register<Type = u32>,
32{
33 type Reg = Reg;
34
35 #[inline(always)]
36 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
37 fn try_decode(instruction: u32) -> Option<Self> {
38 let opcode = (instruction & 0b111_1111) as u8;
39 let rd_bits = ((instruction >> 7) & 0x1f) as u8;
40 let funct3 = ((instruction >> 12) & 0b111) as u8;
41 let rs1_bits = ((instruction >> 15) & 0x1f) as u8;
42 let rs2_bits = ((instruction >> 20) & 0x1f) as u8;
43 let funct7 = ((instruction >> 25) & 0b111_1111) as u8;
44
45 match (opcode, funct3) {
46 (0b010_1111, 0b010) => {
48 let rd = Reg::from_bits(rd_bits)?;
49 let rs1 = Reg::from_bits(rs1_bits)?;
50 let rs2 = Reg::from_bits(rs2_bits)?;
51 let funct5 = funct7 >> 2;
52 let aq = (funct7 & 0b10) != 0;
53 let rl = (funct7 & 0b01) != 0;
54
55 match funct5 {
56 0b00001 => Some(Self::Amoswap {
57 rd,
58 rs1,
59 rs2,
60 aq,
61 rl,
62 }),
63 0b00000 => Some(Self::Amoadd {
64 rd,
65 rs1,
66 rs2,
67 aq,
68 rl,
69 }),
70 0b00100 => Some(Self::Amoxor {
71 rd,
72 rs1,
73 rs2,
74 aq,
75 rl,
76 }),
77 0b01100 => Some(Self::Amoand {
78 rd,
79 rs1,
80 rs2,
81 aq,
82 rl,
83 }),
84 0b01000 => Some(Self::Amoor {
85 rd,
86 rs1,
87 rs2,
88 aq,
89 rl,
90 }),
91 0b10000 => Some(Self::Amomin {
92 rd,
93 rs1,
94 rs2,
95 aq,
96 rl,
97 }),
98 0b10100 => Some(Self::Amomax {
99 rd,
100 rs1,
101 rs2,
102 aq,
103 rl,
104 }),
105 0b11000 => Some(Self::Amominu {
106 rd,
107 rs1,
108 rs2,
109 aq,
110 rl,
111 }),
112 0b11100 => Some(Self::Amomaxu {
113 rd,
114 rs1,
115 rs2,
116 aq,
117 rl,
118 }),
119 _ => None,
120 }
121 }
122 _ => None,
123 }
124 }
125
126 #[inline(always)]
127 fn alignment() -> u8 {
128 align_of::<u32>() as u8
129 }
130
131 #[inline(always)]
132 fn size(&self) -> u8 {
133 size_of::<u32>() as u8
134 }
135}
136
137#[inline(always)]
139fn aq_rl_suffix(aq: &bool, rl: &bool) -> &'static str {
140 match (*aq, *rl) {
141 (false, false) => "",
142 (true, false) => ".aq",
143 (false, true) => ".rl",
144 (true, true) => ".aqrl",
145 }
146}
147
148#[instruction]
149impl<Reg> fmt::Display for Rv32ZaamoInstruction<Reg>
150where
151 Reg: fmt::Display,
152{
153 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
154 #[rustfmt::skip]
155 match self {
156 Self::Amoswap { rd, rs1, rs2, aq, rl } => write!(f, "amoswap.w{} {rd}, {rs2}, ({rs1})", aq_rl_suffix(aq, rl)),
157 Self::Amoadd { rd, rs1, rs2, aq, rl } => write!(f, "amoadd.w{} {rd}, {rs2}, ({rs1})", aq_rl_suffix(aq, rl)),
158 Self::Amoxor { rd, rs1, rs2, aq, rl } => write!(f, "amoxor.w{} {rd}, {rs2}, ({rs1})", aq_rl_suffix(aq, rl)),
159 Self::Amoand { rd, rs1, rs2, aq, rl } => write!(f, "amoand.w{} {rd}, {rs2}, ({rs1})", aq_rl_suffix(aq, rl)),
160 Self::Amoor { rd, rs1, rs2, aq, rl } => write!(f, "amoor.w{} {rd}, {rs2}, ({rs1})", aq_rl_suffix(aq, rl)),
161 Self::Amomin { rd, rs1, rs2, aq, rl } => write!(f, "amomin.w{} {rd}, {rs2}, ({rs1})", aq_rl_suffix(aq, rl)),
162 Self::Amomax { rd, rs1, rs2, aq, rl } => write!(f, "amomax.w{} {rd}, {rs2}, ({rs1})", aq_rl_suffix(aq, rl)),
163 Self::Amominu { rd, rs1, rs2, aq, rl } => write!(f, "amominu.w{} {rd}, {rs2}, ({rs1})", aq_rl_suffix(aq, rl)),
164 Self::Amomaxu { rd, rs1, rs2, aq, rl } => write!(f, "amomaxu.w{} {rd}, {rs2}, ({rs1})", aq_rl_suffix(aq, rl)),
165 }
166 }
167}