openvm_pairing_transpiler/
lib.rs1use openvm_instructions::{
2 instruction::Instruction, riscv::RV32_REGISTER_NUM_LIMBS, PhantomDiscriminant,
3};
4use openvm_pairing_guest::{PairingBaseFunct7, OPCODE, PAIRING_FUNCT3};
5use openvm_stark_backend::p3_field::PrimeField32;
6use openvm_transpiler::{TranspilerExtension, TranspilerOutput};
7use rrs_lib::instruction_formats::RType;
8use strum::FromRepr;
9
10#[derive(Copy, Clone, Debug, PartialEq, Eq, FromRepr)]
11#[repr(u16)]
12pub enum PairingPhantom {
13 HintFinalExp = 0x30,
18}
19
20#[derive(Default)]
21pub struct PairingTranspilerExtension;
22
23impl<F: PrimeField32> TranspilerExtension<F> for PairingTranspilerExtension {
24 fn process_custom(&self, instruction_stream: &[u32]) -> Option<TranspilerOutput<F>> {
25 if instruction_stream.is_empty() {
26 return None;
27 }
28 let instruction_u32 = instruction_stream[0];
29 let opcode = (instruction_u32 & 0x7f) as u8;
30 let funct3 = ((instruction_u32 >> 12) & 0b111) as u8;
31
32 if opcode != OPCODE {
33 return None;
34 }
35 if funct3 != PAIRING_FUNCT3 {
36 return None;
37 }
38
39 let dec_insn = RType::new(instruction_u32);
40 let base_funct7 = (dec_insn.funct7 as u8) % PairingBaseFunct7::PAIRING_MAX_KINDS;
41 let pairing_idx = ((dec_insn.funct7 as u8) / PairingBaseFunct7::PAIRING_MAX_KINDS) as usize;
42 if let Some(PairingBaseFunct7::HintFinalExp) = PairingBaseFunct7::from_repr(base_funct7) {
43 assert_eq!(dec_insn.rd, 0);
44 return Some(TranspilerOutput::one_to_one(Instruction::phantom(
46 PhantomDiscriminant(PairingPhantom::HintFinalExp as u16),
47 F::from_canonical_usize(RV32_REGISTER_NUM_LIMBS * dec_insn.rs1),
48 F::from_canonical_usize(RV32_REGISTER_NUM_LIMBS * dec_insn.rs2),
49 pairing_idx as u16,
50 )));
51 }
52 None
53 }
54}