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