ab_riscv_primitives/instructions/rv32/zk/zkn/
zknd.rs1#[cfg(test)]
4mod tests;
5
6use crate::hart::HartConfig;
7use crate::instructions::{ImplementedExtension, Instruction, IsaExtension};
8use crate::registers::general_purpose::Register;
9use ab_riscv_macros::instruction;
10use core::fmt;
11
12#[derive(Debug, Clone, Copy)]
16#[derive_const(PartialEq, Eq)]
17#[repr(u8)]
18pub enum Rv32AesBs {
19 B0 = 0,
20 B1 = 1,
21 B2 = 2,
22 B3 = 3,
23}
24
25impl From<Rv32AesBs> for u8 {
26 #[inline(always)]
27 fn from(bs: Rv32AesBs) -> Self {
28 bs as u8
29 }
30}
31
32impl From<Rv32AesBs> for usize {
33 #[inline(always)]
34 fn from(bs: Rv32AesBs) -> Self {
35 usize::from(bs as u8)
36 }
37}
38
39impl fmt::Display for Rv32AesBs {
40 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
41 fmt::Display::fmt(&(*self as u8), f)
42 }
43}
44
45impl Rv32AesBs {
46 #[inline(always)]
48 pub const fn from_bits(bits: u8) -> Option<Self> {
49 match bits {
50 0 => Some(Self::B0),
51 1 => Some(Self::B1),
52 2 => Some(Self::B2),
53 3 => Some(Self::B3),
54 _ => None,
55 }
56 }
57}
58
59#[instruction]
61#[derive(Debug, Clone, Copy)]
62#[derive_const(PartialEq, Eq)]
63pub enum Rv32ZkndInstruction<Hart>
64where
65 Hart: HartConfig,
66{
67 Aes32Dsi {
72 rd: Hart::Reg,
73 rs1: Hart::Reg,
74 rs2: Hart::Reg,
75 bs: Rv32AesBs,
76 },
77 Aes32Dsmi {
82 rd: Hart::Reg,
83 rs1: Hart::Reg,
84 rs2: Hart::Reg,
85 bs: Rv32AesBs,
86 },
87}
88
89#[instruction]
109const impl<Reg, Hart> Instruction for Rv32ZkndInstruction<Hart>
110where
111 Reg: [const] Register<Type = u32>,
112 Hart: [const] HartConfig<Reg = Reg>,
113{
114 const OWN_ISA_EXTENSIONS: &'static [IsaExtension] = &[IsaExtension::new("zknd", 1, 0)];
115
116 const ALIGNMENT: u8 = align_of::<u32>() as u8;
117
118 type Hart = Hart;
119
120 #[inline(always)]
121 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
122 fn try_decode(instruction: u32) -> Option<Self> {
123 let opcode = (instruction & 0b111_1111) as u8;
124 let rd_bits = ((instruction >> 7) & 0x1f) as u8;
125 let funct3 = ((instruction >> 12) & 0b111) as u8;
126 let rs1_bits = ((instruction >> 15) & 0x1f) as u8;
127 let rs2_bits = ((instruction >> 20) & 0x1f) as u8;
128 let funct5 = ((instruction >> 25) & 0b1_1111) as u8;
129 let bs_bits = ((instruction >> 30) & 0b11) as u8;
130
131 if opcode != 0b011_0011 {
133 None?;
134 }
135 if funct3 != 0b000 {
136 None?;
137 }
138
139 let rd = Reg::from_bits(rd_bits)?;
140 let rs1 = Reg::from_bits(rs1_bits)?;
141 let rs2 = Reg::from_bits(rs2_bits)?;
142 let bs = Rv32AesBs::from_bits(bs_bits)?;
143
144 match funct5 {
145 0b1_0101 => Some(Self::Aes32Dsi { rd, rs1, rs2, bs }),
147 0b1_0111 => Some(Self::Aes32Dsmi { rd, rs1, rs2, bs }),
149 _ => None,
150 }
151 }
152
153 #[inline(always)]
154 fn size(&self) -> u8 {
155 size_of::<u32>() as u8
156 }
157}
158
159#[instruction]
160impl<Reg, Hart> fmt::Display for Rv32ZkndInstruction<Hart>
161where
162 Reg: fmt::Display,
163 Hart: HartConfig<Reg = Reg>,
164{
165 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
166 match self {
167 Self::Aes32Dsi { rd, rs1, rs2, bs } => {
168 write!(f, "aes32dsi {rd}, {rs1}, {rs2}, {bs}")
169 }
170 Self::Aes32Dsmi { rd, rs1, rs2, bs } => {
171 write!(f, "aes32dsmi {rd}, {rs1}, {rs2}, {bs}")
172 }
173 }
174 }
175}