Skip to main content

ab_riscv_interpreter/rv32/zk/zkn/
zknh.rs

1//! RV32 Zknh extension
2
3pub mod rv32_zknh_helpers;
4#[cfg(test)]
5mod tests;
6
7use crate::{
8    ExecutableInstruction, ExecutableInstructionCsr, ExecutableInstructionOperands, ExecutionError,
9    ExecutionResult, FetchInstructionResult, InstructionFetcher, OpaqueThreadedExecutionResult,
10    RegisterFile, Rs1Rs2OperandValues, Rs1Rs2Operands, ThreadedExecutableInstruction,
11    ThreadedExecutionResult,
12};
13use ab_riscv_macros::instruction_execution;
14use ab_riscv_primitives::prelude::*;
15
16#[instruction_execution]
17const impl<Reg, Hart> ExecutableInstructionOperands for Rv32ZknhInstruction<Hart>
18where
19    Reg: Register<Type = u32>,
20    Hart: HartConfig<Reg = Reg>,
21{
22}
23
24#[instruction_execution]
25const impl<Reg, Hart, Env> ExecutableInstructionCsr<Env> for Rv32ZknhInstruction<Hart>
26where
27    Reg: Register<Type = u32>,
28    Hart: HartConfig<Reg = Reg>,
29{
30}
31
32#[instruction_execution]
33const impl<Reg, Hart, Regs, Env, Memory, PC> ExecutableInstruction<Regs, Env, Memory, PC>
34    for Rv32ZknhInstruction<Hart>
35where
36    Reg: [const] Register<Type = u32>,
37    Hart: HartConfig<Reg = Reg>,
38    Regs: [const] RegisterFile<Reg>,
39{
40    #[inline(always)]
41    #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
42    fn execute(
43        self,
44        Rs1Rs2OperandValues {
45            rs1_value,
46            rs2_value,
47        }: Rs1Rs2OperandValues<Reg::Type>,
48        _regs: &mut Regs,
49        _env: &mut Env,
50        _memory: &mut Memory,
51        _program_counter: &PC,
52    ) -> ExecutionResult<Reg> {
53        match self {
54            // SHA-256 (single-register)
55            Self::Sha256Sig0 { rd, rs1: _ } => {
56                let x = rs1_value;
57                ExecutionResult::Continue {
58                    rd,
59                    value: rv32_zknh_helpers::sha256sig0(x),
60                }
61            }
62            Self::Sha256Sig1 { rd, rs1: _ } => {
63                let x = rs1_value;
64                ExecutionResult::Continue {
65                    rd,
66                    value: rv32_zknh_helpers::sha256sig1(x),
67                }
68            }
69            Self::Sha256Sum0 { rd, rs1: _ } => {
70                let x = rs1_value;
71                ExecutionResult::Continue {
72                    rd,
73                    value: rv32_zknh_helpers::sha256sum0(x),
74                }
75            }
76            Self::Sha256Sum1 { rd, rs1: _ } => {
77                let x = rs1_value;
78                ExecutionResult::Continue {
79                    rd,
80                    value: rv32_zknh_helpers::sha256sum1(x),
81                }
82            }
83
84            // SHA-512 (two-register R-type)
85            //
86            // Register conventions (from the RISC-V scalar crypto spec, Sail pseudocode):
87            //
88            //   sha512sig0l, sha512sig1l : rs1 = LOW word,  rs2 = HIGH word
89            //   sha512sig0h, sha512sig1h : rs1 = HIGH word, rs2 = LOW word
90            //   sha512sum0r, sha512sum1r : rs1 = LOW word,  rs2 = HIGH word
91            //
92            // The Sail model for sum0r/sum1r assembles the operand as:
93            //   x[63:32] = X(rs2),  x[31:0] = X(rs1)
94            // and writes x[31:0] of the result to rd.
95            //
96            // The helpers receive (rs1, rs2) exactly as read from the register file;
97            // they handle the asymmetric convention internally.
98            Self::Sha512Sig0h { rd, rs1: _, rs2: _ } => {
99                let rs1_val = rs1_value;
100                let rs2_val = rs2_value;
101                ExecutionResult::Continue {
102                    rd,
103                    value: rv32_zknh_helpers::sha512sig0h(rs1_val, rs2_val),
104                }
105            }
106            Self::Sha512Sig0l { rd, rs1: _, rs2: _ } => {
107                let rs1_val = rs1_value;
108                let rs2_val = rs2_value;
109                ExecutionResult::Continue {
110                    rd,
111                    value: rv32_zknh_helpers::sha512sig0l(rs1_val, rs2_val),
112                }
113            }
114            Self::Sha512Sig1h { rd, rs1: _, rs2: _ } => {
115                let rs1_val = rs1_value;
116                let rs2_val = rs2_value;
117                ExecutionResult::Continue {
118                    rd,
119                    value: rv32_zknh_helpers::sha512sig1h(rs1_val, rs2_val),
120                }
121            }
122            Self::Sha512Sig1l { rd, rs1: _, rs2: _ } => {
123                let rs1_val = rs1_value;
124                let rs2_val = rs2_value;
125                ExecutionResult::Continue {
126                    rd,
127                    value: rv32_zknh_helpers::sha512sig1l(rs1_val, rs2_val),
128                }
129            }
130            Self::Sha512Sum0r { rd, rs1: _, rs2: _ } => {
131                let rs1_val = rs1_value;
132                let rs2_val = rs2_value;
133                ExecutionResult::Continue {
134                    rd,
135                    value: rv32_zknh_helpers::sha512sum0r(rs1_val, rs2_val),
136                }
137            }
138            Self::Sha512Sum1r { rd, rs1: _, rs2: _ } => {
139                let rs1_val = rs1_value;
140                let rs2_val = rs2_value;
141                ExecutionResult::Continue {
142                    rd,
143                    value: rv32_zknh_helpers::sha512sum1r(rs1_val, rs2_val),
144                }
145            }
146        }
147    }
148}