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    const ALIGNMENT: u8 = align_of::<u32>() as u8;
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        let funct6 = ((instruction >> 26) & 0b11_1111) as u8;
45
46        match opcode {
47            // R-type
48            0b011_0011 => {
49                let rd = Reg::from_bits(rd_bits)?;
50                let rs1 = Reg::from_bits(rs1_bits)?;
51                let rs2 = Reg::from_bits(rs2_bits)?;
52                match (funct3, funct7) {
53                    (0b010, 0b001_0000) => Some(Self::Sh1add { rd, rs1, rs2 }),
54                    (0b100, 0b001_0000) => Some(Self::Sh2add { rd, rs1, rs2 }),
55                    (0b110, 0b001_0000) => Some(Self::Sh3add { rd, rs1, rs2 }),
56                    _ => None,
57                }
58            }
59            // I-type W (OP-IMM-32)
60            0b001_1011 => {
61                let rd = Reg::from_bits(rd_bits)?;
62                let rs1 = Reg::from_bits(rs1_bits)?;
63                // shamt is 6 bits: [25:20]
64                let shamt = ((instruction >> 20) & 0x3f) as u8;
65                match (funct3, funct6) {
66                    (0b001, 0b00_0010) => Some(Self::SlliUw { rd, rs1, shamt }),
67                    _ => None,
68                }
69            }
70            // R-type W (OP-32)
71            0b011_1011 => {
72                let rd = Reg::from_bits(rd_bits)?;
73                let rs1 = Reg::from_bits(rs1_bits)?;
74                match funct3 {
75                    0b000 => {
76                        let rs2 = Reg::from_bits(rs2_bits)?;
77                        match funct7 {
78                            0b000_0100 => Some(Self::AddUw { rd, rs1, rs2 }),
79                            _ => None,
80                        }
81                    }
82                    0b010 => {
83                        let rs2 = Reg::from_bits(rs2_bits)?;
84                        match funct7 {
85                            0b001_0000 => Some(Self::Sh1addUw { rd, rs1, rs2 }),
86                            _ => None,
87                        }
88                    }
89                    0b100 => {
90                        let rs2 = Reg::from_bits(rs2_bits)?;
91                        match funct7 {
92                            0b001_0000 => Some(Self::Sh2addUw { rd, rs1, rs2 }),
93                            _ => None,
94                        }
95                    }
96                    0b110 => {
97                        let rs2 = Reg::from_bits(rs2_bits)?;
98                        match funct7 {
99                            0b001_0000 => Some(Self::Sh3addUw { rd, rs1, rs2 }),
100                            _ => None,
101                        }
102                    }
103                    _ => None,
104                }
105            }
106            _ => None,
107        }
108    }
109
110    #[inline(always)]
111    fn size(&self) -> u8 {
112        size_of::<u32>() as u8
113    }
114}
115
116#[instruction]
117impl<Reg> fmt::Display for Rv64ZbaInstruction<Reg>
118where
119    Reg: fmt::Display,
120{
121    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
122        match self {
123            Self::AddUw { rd, rs1, rs2 } => write!(f, "add.uw {rd}, {rs1}, {rs2}"),
124            Self::Sh1add { rd, rs1, rs2 } => write!(f, "sh1add {rd}, {rs1}, {rs2}"),
125            Self::Sh1addUw { rd, rs1, rs2 } => write!(f, "sh1add.uw {rd}, {rs1}, {rs2}"),
126            Self::Sh2add { rd, rs1, rs2 } => write!(f, "sh2add {rd}, {rs1}, {rs2}"),
127            Self::Sh2addUw { rd, rs1, rs2 } => write!(f, "sh2add.uw {rd}, {rs1}, {rs2}"),
128            Self::Sh3add { rd, rs1, rs2 } => write!(f, "sh3add {rd}, {rs1}, {rs2}"),
129            Self::Sh3addUw { rd, rs1, rs2 } => write!(f, "sh3add.uw {rd}, {rs1}, {rs2}"),
130            Self::SlliUw { rd, rs1, shamt } => write!(f, "slli.uw {rd}, {rs1}, {shamt}"),
131        }
132    }
133}