Skip to main content

ab_riscv_primitives/instructions/rv64/b/
zba.rs

1//! RV64 Zba 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 Zba instruction (Address generation)
12#[instruction]
13#[derive(Debug, Clone, Copy)]
14#[derive_const(PartialEq, Eq)]
15pub enum Rv64ZbaInstruction<Reg> {
16    AddUw { rd: Reg, rs1: Reg, rs2: Reg },
17    Sh1add { rd: Reg, rs1: Reg, rs2: Reg },
18    Sh1addUw { rd: Reg, rs1: Reg, rs2: Reg },
19    Sh2add { rd: Reg, rs1: Reg, rs2: Reg },
20    Sh2addUw { rd: Reg, rs1: Reg, rs2: Reg },
21    Sh3add { rd: Reg, rs1: Reg, rs2: Reg },
22    Sh3addUw { rd: Reg, rs1: Reg, rs2: Reg },
23    SlliUw { rd: Reg, rs1: Reg, shamt: u8 },
24}
25
26#[instruction]
27const impl<Reg> Instruction for Rv64ZbaInstruction<Reg>
28where
29    Reg: [const] Register<Type = u64>,
30{
31    type Reg = Reg;
32
33    #[inline(always)]
34    #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
35    fn try_decode(instruction: u32) -> Option<Self> {
36        let opcode = (instruction & 0b111_1111) as u8;
37        let rd_bits = ((instruction >> 7) & 0x1f) as u8;
38        let funct3 = ((instruction >> 12) & 0b111) as u8;
39        let rs1_bits = ((instruction >> 15) & 0x1f) as u8;
40        let rs2_bits = ((instruction >> 20) & 0x1f) as u8;
41        let funct7 = ((instruction >> 25) & 0b111_1111) as u8;
42        let funct6 = ((instruction >> 26) & 0b11_1111) as u8;
43
44        match opcode {
45            // R-type
46            0b011_0011 => {
47                let rd = Reg::from_bits(rd_bits)?;
48                let rs1 = Reg::from_bits(rs1_bits)?;
49                let rs2 = Reg::from_bits(rs2_bits)?;
50                match (funct3, funct7) {
51                    (0b010, 0b001_0000) => Some(Self::Sh1add { rd, rs1, rs2 }),
52                    (0b100, 0b001_0000) => Some(Self::Sh2add { rd, rs1, rs2 }),
53                    (0b110, 0b001_0000) => Some(Self::Sh3add { rd, rs1, rs2 }),
54                    _ => None,
55                }
56            }
57            // I-type W (OP-IMM-32)
58            0b001_1011 => {
59                let rd = Reg::from_bits(rd_bits)?;
60                let rs1 = Reg::from_bits(rs1_bits)?;
61                // shamt is 6 bits: [25:20]
62                let shamt = ((instruction >> 20) & 0x3f) as u8;
63                match (funct3, funct6) {
64                    (0b001, 0b00_0010) => Some(Self::SlliUw { rd, rs1, shamt }),
65                    _ => None,
66                }
67            }
68            // R-type W (OP-32)
69            0b011_1011 => {
70                let rd = Reg::from_bits(rd_bits)?;
71                let rs1 = Reg::from_bits(rs1_bits)?;
72                match funct3 {
73                    0b000 => {
74                        let rs2 = Reg::from_bits(rs2_bits)?;
75                        match funct7 {
76                            0b000_0100 => Some(Self::AddUw { rd, rs1, rs2 }),
77                            _ => None,
78                        }
79                    }
80                    0b010 => {
81                        let rs2 = Reg::from_bits(rs2_bits)?;
82                        match funct7 {
83                            0b001_0000 => Some(Self::Sh1addUw { rd, rs1, rs2 }),
84                            _ => None,
85                        }
86                    }
87                    0b100 => {
88                        let rs2 = Reg::from_bits(rs2_bits)?;
89                        match funct7 {
90                            0b001_0000 => Some(Self::Sh2addUw { rd, rs1, rs2 }),
91                            _ => None,
92                        }
93                    }
94                    0b110 => {
95                        let rs2 = Reg::from_bits(rs2_bits)?;
96                        match funct7 {
97                            0b001_0000 => Some(Self::Sh3addUw { rd, rs1, rs2 }),
98                            _ => None,
99                        }
100                    }
101                    _ => None,
102                }
103            }
104            _ => None,
105        }
106    }
107
108    #[inline(always)]
109    fn alignment() -> u8 {
110        align_of::<u32>() as u8
111    }
112
113    #[inline(always)]
114    fn size(&self) -> u8 {
115        size_of::<u32>() as u8
116    }
117}
118
119#[instruction]
120impl<Reg> fmt::Display for Rv64ZbaInstruction<Reg>
121where
122    Reg: fmt::Display,
123{
124    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
125        match self {
126            Self::AddUw { rd, rs1, rs2 } => write!(f, "add.uw {rd}, {rs1}, {rs2}"),
127            Self::Sh1add { rd, rs1, rs2 } => write!(f, "sh1add {rd}, {rs1}, {rs2}"),
128            Self::Sh1addUw { rd, rs1, rs2 } => write!(f, "sh1add.uw {rd}, {rs1}, {rs2}"),
129            Self::Sh2add { rd, rs1, rs2 } => write!(f, "sh2add {rd}, {rs1}, {rs2}"),
130            Self::Sh2addUw { rd, rs1, rs2 } => write!(f, "sh2add.uw {rd}, {rs1}, {rs2}"),
131            Self::Sh3add { rd, rs1, rs2 } => write!(f, "sh3add {rd}, {rs1}, {rs2}"),
132            Self::Sh3addUw { rd, rs1, rs2 } => write!(f, "sh3add.uw {rd}, {rs1}, {rs2}"),
133            Self::SlliUw { rd, rs1, shamt } => write!(f, "slli.uw {rd}, {rs1}, {shamt}"),
134        }
135    }
136}