Skip to main content

ab_riscv_primitives/instructions/rv32/a/
zaamo.rs

1//! RV32 Zaamo extension
2
3#[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/// RISC-V RV32 Zaamo instruction (Atomic memory operations)
12#[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            // AMO, word-sized (only size that exists in RV32)
47            (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/// Format `aq`/`rl` suffix for display
138#[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}