openvm_sha2_transpiler/
lib.rs1use openvm_instructions::{riscv::RV32_MEMORY_AS, LocalOpcode};
2use openvm_instructions_derive::LocalOpcode;
3use openvm_sha2_guest::{Sha2BaseFunct7, OPCODE, SHA2_FUNCT3};
4use openvm_stark_backend::p3_field::PrimeField32;
5use openvm_transpiler::{util::from_r_type, TranspilerExtension, TranspilerOutput};
6use rrs_lib::instruction_formats::RType;
7use strum::{EnumCount, EnumIter, FromRepr};
8
9#[derive(
12 Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, EnumCount, EnumIter, FromRepr, LocalOpcode,
13)]
14#[opcode_offset = 0x320]
15#[repr(usize)]
16pub enum Rv32Sha2Opcode {
17 SHA256,
18 SHA512,
19}
20
21#[derive(Default)]
22pub struct Sha2TranspilerExtension;
23
24impl<F: PrimeField32> TranspilerExtension<F> for Sha2TranspilerExtension {
25 fn process_custom(&self, instruction_stream: &[u32]) -> Option<TranspilerOutput<F>> {
26 if instruction_stream.is_empty() {
27 return None;
28 }
29 let instruction_u32 = instruction_stream[0];
30 let opcode = (instruction_u32 & 0x7f) as u8;
31 let funct3 = ((instruction_u32 >> 12) & 0b111) as u8;
32
33 if (opcode, funct3) != (OPCODE, SHA2_FUNCT3) {
34 return None;
35 }
36 let dec_insn = RType::new(instruction_u32);
37
38 if dec_insn.funct7 == Sha2BaseFunct7::Sha256 as u32 {
39 let instruction = from_r_type(
40 Rv32Sha2Opcode::SHA256.global_opcode().as_usize(),
41 RV32_MEMORY_AS as usize,
42 &dec_insn,
43 true,
44 );
45 Some(TranspilerOutput::one_to_one(instruction))
46 } else if dec_insn.funct7 == Sha2BaseFunct7::Sha512 as u32 {
47 let instruction = from_r_type(
48 Rv32Sha2Opcode::SHA512.global_opcode().as_usize(),
49 RV32_MEMORY_AS as usize,
50 &dec_insn,
51 true,
52 );
53 Some(TranspilerOutput::one_to_one(instruction))
54 } else {
55 None
56 }
57 }
58}