Skip to main content

ab_riscv_primitives/instructions/rv64/b/
zbb.rs

1//! RV64 Zbb 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 RV64 Zbb instruction (Basic bit manipulation)
12#[instruction]
13#[derive(Debug, Clone, Copy)]
14#[derive_const(PartialEq, Eq)]
15pub enum Rv64ZbbInstruction<Reg> {
16    // RV64 Zbb instructions
17    Andn { rd: Reg, rs1: Reg, rs2: Reg },
18    Orn { rd: Reg, rs1: Reg, rs2: Reg },
19    Xnor { rd: Reg, rs1: Reg, rs2: Reg },
20    Clz { rd: Reg, rs1: Reg },
21    Clzw { rd: Reg, rs1: Reg },
22    Ctz { rd: Reg, rs1: Reg },
23    Ctzw { rd: Reg, rs1: Reg },
24    Cpop { rd: Reg, rs1: Reg },
25    Cpopw { rd: Reg, rs1: Reg },
26    Max { rd: Reg, rs1: Reg, rs2: Reg },
27    Maxu { rd: Reg, rs1: Reg, rs2: Reg },
28    Min { rd: Reg, rs1: Reg, rs2: Reg },
29    Minu { rd: Reg, rs1: Reg, rs2: Reg },
30    Sextb { rd: Reg, rs1: Reg },
31    Sexth { rd: Reg, rs1: Reg },
32    Zexth { rd: Reg, rs1: Reg },
33    Rol { rd: Reg, rs1: Reg, rs2: Reg },
34    Rolw { rd: Reg, rs1: Reg, rs2: Reg },
35    Ror { rd: Reg, rs1: Reg, rs2: Reg },
36    Rori { rd: Reg, rs1: Reg, shamt: u8 },
37    Roriw { rd: Reg, rs1: Reg, shamt: u8 },
38    Rorw { rd: Reg, rs1: Reg, rs2: Reg },
39    Orcb { rd: Reg, rs1: Reg },
40    Rev8 { rd: Reg, rs1: Reg },
41}
42
43#[instruction]
44const impl<Reg> Instruction for Rv64ZbbInstruction<Reg>
45where
46    Reg: [const] Register<Type = u64>,
47{
48    const ALIGNMENT: u8 = align_of::<u32>() as u8;
49
50    type Reg = Reg;
51
52    #[inline(always)]
53    #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
54    fn try_decode(instruction: u32) -> Option<Self> {
55        let opcode = (instruction & 0b111_1111) as u8;
56        let rd_bits = ((instruction >> 7) & 0x1f) as u8;
57        let funct3 = ((instruction >> 12) & 0b111) as u8;
58        let rs1_bits = ((instruction >> 15) & 0x1f) as u8;
59        let rs2_bits = ((instruction >> 20) & 0x1f) as u8;
60        let funct7 = ((instruction >> 25) & 0b111_1111) as u8;
61        let funct6 = ((instruction >> 26) & 0b11_1111) as u8;
62        // bits 25:20 for I-type distinctions
63        let low6 = ((instruction >> 20) & 0x3f) as u8;
64        let funct12 = ((instruction >> 20) & 0xfff) as u16;
65
66        match opcode {
67            // OP-IMM
68            0b001_0011 => {
69                let rd = Reg::from_bits(rd_bits)?;
70                let rs1 = Reg::from_bits(rs1_bits)?;
71                match funct3 {
72                    0b001 => {
73                        if funct6 == 0b01_1000 {
74                            match low6 {
75                                0 => Some(Self::Clz { rd, rs1 }),
76                                1 => Some(Self::Ctz { rd, rs1 }),
77                                2 => Some(Self::Cpop { rd, rs1 }),
78                                4 => Some(Self::Sextb { rd, rs1 }),
79                                5 => Some(Self::Sexth { rd, rs1 }),
80                                _ => None,
81                            }
82                        } else {
83                            None
84                        }
85                    }
86                    0b101 => {
87                        if funct12 == 0b0010_1000_0111 {
88                            Some(Self::Orcb { rd, rs1 })
89                        } else if funct12 == 0b0110_1011_1000 {
90                            Some(Self::Rev8 { rd, rs1 })
91                        } else if funct6 == 0b01_1000 {
92                            Some(Self::Rori {
93                                rd,
94                                rs1,
95                                shamt: low6,
96                            })
97                        } else {
98                            None
99                        }
100                    }
101                    _ => None,
102                }
103            }
104            // OP / R-type
105            0b011_0011 => {
106                let rd = Reg::from_bits(rd_bits)?;
107                let rs1 = Reg::from_bits(rs1_bits)?;
108                let rs2 = Reg::from_bits(rs2_bits)?;
109                match funct3 {
110                    0b001 => {
111                        if funct7 == 0b011_0000 {
112                            Some(Self::Rol { rd, rs1, rs2 })
113                        } else {
114                            None
115                        }
116                    }
117                    0b100 => match funct7 {
118                        0b010_0000 => Some(Self::Xnor { rd, rs1, rs2 }),
119                        0b000_0101 => Some(Self::Min { rd, rs1, rs2 }),
120                        _ => None,
121                    },
122                    0b101 => match funct7 {
123                        0b011_0000 => Some(Self::Ror { rd, rs1, rs2 }),
124                        0b000_0101 => Some(Self::Minu { rd, rs1, rs2 }),
125                        _ => None,
126                    },
127                    0b110 => match funct7 {
128                        0b010_0000 => Some(Self::Orn { rd, rs1, rs2 }),
129                        0b000_0101 => Some(Self::Max { rd, rs1, rs2 }),
130                        _ => None,
131                    },
132                    0b111 => match funct7 {
133                        0b010_0000 => Some(Self::Andn { rd, rs1, rs2 }),
134                        0b000_0101 => Some(Self::Maxu { rd, rs1, rs2 }),
135                        _ => None,
136                    },
137                    _ => None,
138                }
139            }
140            // OP-IMM-32
141            0b001_1011 => {
142                let rd = Reg::from_bits(rd_bits)?;
143                let rs1 = Reg::from_bits(rs1_bits)?;
144                match funct3 {
145                    0b001 => {
146                        if funct7 == 0b011_0000 {
147                            match rs2_bits {
148                                0 => Some(Self::Clzw { rd, rs1 }),
149                                1 => Some(Self::Ctzw { rd, rs1 }),
150                                2 => Some(Self::Cpopw { rd, rs1 }),
151                                _ => None,
152                            }
153                        } else {
154                            None
155                        }
156                    }
157                    0b101 => {
158                        if funct7 == 0b011_0000 {
159                            let shamt = rs2_bits;
160                            Some(Self::Roriw { rd, rs1, shamt })
161                        } else {
162                            None
163                        }
164                    }
165                    _ => None,
166                }
167            }
168            // OP-32
169            0b011_1011 => {
170                let rd = Reg::from_bits(rd_bits)?;
171                let rs1 = Reg::from_bits(rs1_bits)?;
172                let rs2 = Reg::from_bits(rs2_bits)?;
173                match funct3 {
174                    0b001 => {
175                        if funct7 == 0b011_0000 {
176                            Some(Self::Rolw { rd, rs1, rs2 })
177                        } else {
178                            None
179                        }
180                    }
181                    0b100 => {
182                        if funct7 == 0b000_0100 && rs2_bits == 0 {
183                            Some(Self::Zexth { rd, rs1 })
184                        } else {
185                            None
186                        }
187                    }
188                    0b101 => {
189                        if funct7 == 0b011_0000 {
190                            Some(Self::Rorw { rd, rs1, rs2 })
191                        } else {
192                            None
193                        }
194                    }
195                    _ => None,
196                }
197            }
198            _ => None,
199        }
200    }
201
202    #[inline(always)]
203    fn size(&self) -> u8 {
204        size_of::<u32>() as u8
205    }
206}
207
208#[instruction]
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}