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