openvm_native_transpiler/
lib.rs
1use openvm_instructions::{instruction::Instruction, VmOpcode};
2use openvm_transpiler::{TranspilerExtension, TranspilerOutput};
3use p3_field::PrimeField32;
4
5const OPCODE: u32 = 0x0b;
14const FUNCT3: u32 = 0b111;
15pub const LONG_FORM_INSTRUCTION_INDICATOR: u32 = (FUNCT3 << 12) + OPCODE;
16pub const GAP_INDICATOR: u32 = (1 << 25) + (FUNCT3 << 12) + OPCODE;
17
18pub struct LongFormTranspilerExtension;
19
20impl<F: PrimeField32> TranspilerExtension<F> for LongFormTranspilerExtension {
21 fn process_custom(&self, instruction_stream: &[u32]) -> Option<TranspilerOutput<F>> {
22 if instruction_stream[0] == LONG_FORM_INSTRUCTION_INDICATOR {
23 let num_operands = instruction_stream[1] as usize;
24 let opcode = VmOpcode::from_usize(instruction_stream[2] as usize);
25 let mut operands = vec![];
26 let mut j = 3;
27 for _ in 0..num_operands {
28 operands.push(F::from_canonical_u32(instruction_stream[j]));
29 j += 1;
30 }
31 while operands.len() < 7 {
32 operands.push(F::ZERO);
33 }
34 let instruction = Instruction {
35 opcode,
36 a: operands[0],
37 b: operands[1],
38 c: operands[2],
39 d: operands[3],
40 e: operands[4],
41 f: operands[5],
42 g: operands[6],
43 };
44 if operands.len() == 7 {
45 Some(TranspilerOutput::many_to_one(instruction, j))
46 } else {
47 None
48 }
49 } else if instruction_stream[0] == GAP_INDICATOR {
50 Some(TranspilerOutput::gap(instruction_stream[1] as usize, 2))
51 } else {
52 None
53 }
54 }
55}
56
57pub fn serialize_defined_instructions<F: PrimeField32>(
58 instructions: &[Instruction<F>],
59) -> Vec<u32> {
60 let mut words = vec![];
61 for instruction in instructions {
62 words.push(LONG_FORM_INSTRUCTION_INDICATOR);
63 let operands = instruction.operands();
64 words.push(operands.len() as u32);
65 words.push(instruction.opcode.as_usize() as u32);
66 words.extend(operands.iter().map(F::as_canonical_u32))
67 }
68 words
69}
70
71pub fn deserialize_defined_instructions<F: PrimeField32>(words: &[u32]) -> Vec<Instruction<F>> {
73 let mut index = 0;
74 let mut instructions = vec![];
75 while index < words.len() {
76 let next = LongFormTranspilerExtension
77 .process_custom(&words[index..])
78 .unwrap();
79 instructions.extend(next.instructions.into_iter().map(Option::unwrap));
80 index += next.used_u32s;
81 }
82 instructions
83}