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::{ExecutableInstruction, ExecutionError, RegisterFile};
8use ab_riscv_macros::instruction_execution;
9use ab_riscv_primitives::prelude::*;
10use core::ops::ControlFlow;
11
12#[instruction_execution]
13impl<Reg, Regs, ExtState, Memory, PC, InstructionHandler, CustomError>
14    ExecutableInstruction<Regs, ExtState, Memory, PC, InstructionHandler, CustomError>
15    for Rv32ZknhInstruction<Reg>
16where
17    Reg: Register<Type = u32>,
18    Regs: RegisterFile<Reg>,
19{
20    #[inline(always)]
21    fn execute(
22        self,
23        regs: &mut Regs,
24        _ext_state: &mut ExtState,
25        _memory: &mut Memory,
26        _program_counter: &mut PC,
27        _system_instruction_handler: &mut InstructionHandler,
28    ) -> Result<ControlFlow<()>, ExecutionError<Reg::Type, CustomError>> {
29        match self {
30            // SHA-256 (single-register)
31            Self::Sha256Sig0 { rd, rs1 } => {
32                let x = regs.read(rs1);
33                regs.write(rd, rv32_zknh_helpers::sha256sig0(x));
34            }
35            Self::Sha256Sig1 { rd, rs1 } => {
36                let x = regs.read(rs1);
37                regs.write(rd, rv32_zknh_helpers::sha256sig1(x));
38            }
39            Self::Sha256Sum0 { rd, rs1 } => {
40                let x = regs.read(rs1);
41                regs.write(rd, rv32_zknh_helpers::sha256sum0(x));
42            }
43            Self::Sha256Sum1 { rd, rs1 } => {
44                let x = regs.read(rs1);
45                regs.write(rd, rv32_zknh_helpers::sha256sum1(x));
46            }
47
48            // SHA-512 (two-register R-type)
49            //
50            // Register conventions (from the RISC-V scalar crypto spec, Sail pseudocode):
51            //
52            //   sha512sig0l, sha512sig1l : rs1 = LOW word,  rs2 = HIGH word
53            //   sha512sig0h, sha512sig1h : rs1 = HIGH word, rs2 = LOW word
54            //   sha512sum0r, sha512sum1r : rs1 = LOW word,  rs2 = HIGH word
55            //
56            // The Sail model for sum0r/sum1r assembles the operand as:
57            //   x[63:32] = X(rs2),  x[31:0] = X(rs1)
58            // and writes x[31:0] of the result to rd.
59            //
60            // The helpers receive (rs1, rs2) exactly as read from the register file;
61            // they handle the asymmetric convention internally.
62            Self::Sha512Sig0h { rd, rs1, rs2 } => {
63                let rs1_val = regs.read(rs1);
64                let rs2_val = regs.read(rs2);
65                regs.write(rd, rv32_zknh_helpers::sha512sig0h(rs1_val, rs2_val));
66            }
67            Self::Sha512Sig0l { rd, rs1, rs2 } => {
68                let rs1_val = regs.read(rs1);
69                let rs2_val = regs.read(rs2);
70                regs.write(rd, rv32_zknh_helpers::sha512sig0l(rs1_val, rs2_val));
71            }
72            Self::Sha512Sig1h { rd, rs1, rs2 } => {
73                let rs1_val = regs.read(rs1);
74                let rs2_val = regs.read(rs2);
75                regs.write(rd, rv32_zknh_helpers::sha512sig1h(rs1_val, rs2_val));
76            }
77            Self::Sha512Sig1l { rd, rs1, rs2 } => {
78                let rs1_val = regs.read(rs1);
79                let rs2_val = regs.read(rs2);
80                regs.write(rd, rv32_zknh_helpers::sha512sig1l(rs1_val, rs2_val));
81            }
82            Self::Sha512Sum0r { rd, rs1, rs2 } => {
83                let rs1_val = regs.read(rs1);
84                let rs2_val = regs.read(rs2);
85                regs.write(rd, rv32_zknh_helpers::sha512sum0r(rs1_val, rs2_val));
86            }
87            Self::Sha512Sum1r { rd, rs1, rs2 } => {
88                let rs1_val = regs.read(rs1);
89                let rs2_val = regs.read(rs2);
90                regs.write(rd, rv32_zknh_helpers::sha512sum1r(rs1_val, rs2_val));
91            }
92        }
93
94        Ok(ControlFlow::Continue(()))
95    }
96}