openvm_bigint_transpiler/
lib.rs
1use openvm_bigint_guest::{Int256Funct7, BEQ256_FUNCT3, INT256_FUNCT3, OPCODE};
2use openvm_instructions::{
3 instruction::Instruction, riscv::RV32_REGISTER_NUM_LIMBS, utils::isize_to_field, LocalOpcode,
4 VmOpcode,
5};
6use openvm_instructions_derive::LocalOpcode;
7use openvm_rv32im_transpiler::{
8 BaseAluOpcode, BranchEqualOpcode, BranchLessThanOpcode, LessThanOpcode, MulOpcode, ShiftOpcode,
9};
10use openvm_stark_backend::p3_field::PrimeField32;
11use openvm_transpiler::{util::from_r_type, TranspilerExtension, TranspilerOutput};
12use rrs_lib::instruction_formats::{BType, RType};
13use strum::IntoEnumIterator;
14
15#[derive(Copy, Clone, Debug, LocalOpcode)]
20#[opcode_offset = 0x400]
21pub struct Rv32BaseAlu256Opcode(pub BaseAluOpcode);
22
23impl Rv32BaseAlu256Opcode {
24 pub fn iter() -> impl Iterator<Item = Self> {
25 BaseAluOpcode::iter().map(Self)
26 }
27}
28
29#[derive(Copy, Clone, Debug, LocalOpcode)]
30#[opcode_offset = 0x405]
31pub struct Rv32Shift256Opcode(pub ShiftOpcode);
32
33impl Rv32Shift256Opcode {
34 pub fn iter() -> impl Iterator<Item = Self> {
35 ShiftOpcode::iter().map(Self)
36 }
37}
38
39#[derive(Copy, Clone, Debug, LocalOpcode)]
40#[opcode_offset = 0x408]
41pub struct Rv32LessThan256Opcode(pub LessThanOpcode);
42
43impl Rv32LessThan256Opcode {
44 pub fn iter() -> impl Iterator<Item = Self> {
45 LessThanOpcode::iter().map(Self)
46 }
47}
48
49#[derive(Copy, Clone, Debug, LocalOpcode)]
50#[opcode_offset = 0x420]
51pub struct Rv32BranchEqual256Opcode(pub BranchEqualOpcode);
52
53impl Rv32BranchEqual256Opcode {
54 pub fn iter() -> impl Iterator<Item = Self> {
55 BranchEqualOpcode::iter().map(Self)
56 }
57}
58
59#[derive(Copy, Clone, Debug, LocalOpcode)]
60#[opcode_offset = 0x425]
61pub struct Rv32BranchLessThan256Opcode(pub BranchLessThanOpcode);
62
63impl Rv32BranchLessThan256Opcode {
64 pub fn iter() -> impl Iterator<Item = Self> {
65 BranchLessThanOpcode::iter().map(Self)
66 }
67}
68
69#[derive(Copy, Clone, Debug, LocalOpcode)]
70#[opcode_offset = 0x450]
71pub struct Rv32Mul256Opcode(pub MulOpcode);
72
73impl Rv32Mul256Opcode {
74 pub fn iter() -> impl Iterator<Item = Self> {
75 MulOpcode::iter().map(Self)
76 }
77}
78
79#[derive(Default)]
80pub struct Int256TranspilerExtension;
81
82impl<F: PrimeField32> TranspilerExtension<F> for Int256TranspilerExtension {
83 fn process_custom(&self, instruction_stream: &[u32]) -> Option<TranspilerOutput<F>> {
84 if instruction_stream.is_empty() {
85 return None;
86 }
87 let instruction_u32 = instruction_stream[0];
88 let opcode = (instruction_u32 & 0x7f) as u8;
89 let funct3 = ((instruction_u32 >> 12) & 0b111) as u8;
90
91 if opcode != OPCODE {
92 return None;
93 }
94 if funct3 != INT256_FUNCT3 && funct3 != BEQ256_FUNCT3 {
95 return None;
96 }
97
98 let dec_insn = RType::new(instruction_u32);
99 let instruction = match funct3 {
100 INT256_FUNCT3 => {
101 let global_opcode = match Int256Funct7::from_repr(dec_insn.funct7 as u8) {
102 Some(Int256Funct7::Add) => {
103 BaseAluOpcode::ADD as usize + Rv32BaseAlu256Opcode::CLASS_OFFSET
104 }
105 Some(Int256Funct7::Sub) => {
106 BaseAluOpcode::SUB as usize + Rv32BaseAlu256Opcode::CLASS_OFFSET
107 }
108 Some(Int256Funct7::Xor) => {
109 BaseAluOpcode::XOR as usize + Rv32BaseAlu256Opcode::CLASS_OFFSET
110 }
111 Some(Int256Funct7::Or) => {
112 BaseAluOpcode::OR as usize + Rv32BaseAlu256Opcode::CLASS_OFFSET
113 }
114 Some(Int256Funct7::And) => {
115 BaseAluOpcode::AND as usize + Rv32BaseAlu256Opcode::CLASS_OFFSET
116 }
117 Some(Int256Funct7::Sll) => {
118 ShiftOpcode::SLL as usize + Rv32Shift256Opcode::CLASS_OFFSET
119 }
120 Some(Int256Funct7::Srl) => {
121 ShiftOpcode::SRL as usize + Rv32Shift256Opcode::CLASS_OFFSET
122 }
123 Some(Int256Funct7::Sra) => {
124 ShiftOpcode::SRA as usize + Rv32Shift256Opcode::CLASS_OFFSET
125 }
126 Some(Int256Funct7::Slt) => {
127 LessThanOpcode::SLT as usize + Rv32LessThan256Opcode::CLASS_OFFSET
128 }
129 Some(Int256Funct7::Sltu) => {
130 LessThanOpcode::SLTU as usize + Rv32LessThan256Opcode::CLASS_OFFSET
131 }
132 Some(Int256Funct7::Mul) => {
133 MulOpcode::MUL as usize + Rv32Mul256Opcode::CLASS_OFFSET
134 }
135 _ => unimplemented!(),
136 };
137 Some(from_r_type(global_opcode, 2, &dec_insn, true))
138 }
139 BEQ256_FUNCT3 => {
140 let dec_insn = BType::new(instruction_u32);
141 Some(Instruction::new(
142 VmOpcode::from_usize(
143 BranchEqualOpcode::BEQ.local_usize()
144 + Rv32BranchEqual256Opcode::CLASS_OFFSET,
145 ),
146 F::from_canonical_usize(RV32_REGISTER_NUM_LIMBS * dec_insn.rs1),
147 F::from_canonical_usize(RV32_REGISTER_NUM_LIMBS * dec_insn.rs2),
148 isize_to_field(dec_insn.imm as isize),
149 F::ONE,
150 F::TWO,
151 F::ZERO,
152 F::ZERO,
153 ))
154 }
155 _ => None,
156 };
157 instruction.map(TranspilerOutput::one_to_one)
158 }
159}