1use std::collections::BTreeMap;
2
3use openvm_instructions::{
4 exe::MemoryImage,
5 instruction::Instruction,
6 riscv::{RV32_MEMORY_AS, RV32_REGISTER_NUM_LIMBS},
7 utils::isize_to_field,
8 LocalOpcode, SystemOpcode, VmOpcode,
9};
10use openvm_stark_backend::p3_field::PrimeField32;
11use rrs_lib::instruction_formats::{BType, IType, ITypeShamt, JType, RType, SType, UType};
12
13fn i12_to_u24(imm: i32) -> u32 {
14 (imm as u32) & 0xffffff
15}
16
17pub fn from_r_type<F: PrimeField32>(
19 opcode: usize,
20 e_as: usize,
21 dec_insn: &RType,
22 allow_rd_zero: bool,
23) -> Instruction<F> {
24 if !allow_rd_zero && dec_insn.rd == 0 {
28 return nop();
29 }
30 Instruction::new(
31 VmOpcode::from_usize(opcode),
32 F::from_canonical_usize(RV32_REGISTER_NUM_LIMBS * dec_insn.rd),
33 F::from_canonical_usize(RV32_REGISTER_NUM_LIMBS * dec_insn.rs1),
34 F::from_canonical_usize(RV32_REGISTER_NUM_LIMBS * dec_insn.rs2),
35 F::ONE, F::from_canonical_usize(e_as), F::ZERO,
38 F::ZERO,
39 )
40}
41
42pub fn from_i_type<F: PrimeField32>(opcode: usize, dec_insn: &IType) -> Instruction<F> {
44 if dec_insn.rd == 0 {
45 return nop();
46 }
47 Instruction::new(
48 VmOpcode::from_usize(opcode),
49 F::from_canonical_usize(RV32_REGISTER_NUM_LIMBS * dec_insn.rd),
50 F::from_canonical_usize(RV32_REGISTER_NUM_LIMBS * dec_insn.rs1),
51 F::from_canonical_u32(i12_to_u24(dec_insn.imm)),
52 F::ONE, F::ZERO, F::ZERO,
55 F::ZERO,
56 )
57}
58
59pub fn from_load<F: PrimeField32>(opcode: usize, dec_insn: &IType) -> Instruction<F> {
61 Instruction::new(
62 VmOpcode::from_usize(opcode),
63 F::from_canonical_usize(RV32_REGISTER_NUM_LIMBS * dec_insn.rd),
64 F::from_canonical_usize(RV32_REGISTER_NUM_LIMBS * dec_insn.rs1),
65 F::from_canonical_u32((dec_insn.imm as u32) & 0xffff),
66 F::ONE, F::TWO, F::from_bool(dec_insn.rd != 0), F::from_bool(dec_insn.imm < 0), )
71}
72
73pub fn from_i_type_shamt<F: PrimeField32>(opcode: usize, dec_insn: &ITypeShamt) -> Instruction<F> {
76 if dec_insn.rd == 0 {
77 return nop();
78 }
79 Instruction::new(
80 VmOpcode::from_usize(opcode),
81 F::from_canonical_usize(RV32_REGISTER_NUM_LIMBS * dec_insn.rd),
82 F::from_canonical_usize(RV32_REGISTER_NUM_LIMBS * dec_insn.rs1),
83 F::from_canonical_u32(dec_insn.shamt),
84 F::ONE, F::ZERO, F::ZERO,
87 F::ZERO,
88 )
89}
90
91pub fn from_s_type<F: PrimeField32>(opcode: usize, dec_insn: &SType) -> Instruction<F> {
93 Instruction::new(
94 VmOpcode::from_usize(opcode),
95 F::from_canonical_usize(RV32_REGISTER_NUM_LIMBS * dec_insn.rs2),
96 F::from_canonical_usize(RV32_REGISTER_NUM_LIMBS * dec_insn.rs1),
97 F::from_canonical_u32((dec_insn.imm as u32) & 0xffff),
98 F::ONE,
99 F::TWO,
100 F::ONE,
101 F::from_bool(dec_insn.imm < 0),
102 )
103}
104
105pub fn from_b_type<F: PrimeField32>(opcode: usize, dec_insn: &BType) -> Instruction<F> {
107 Instruction::new(
108 VmOpcode::from_usize(opcode),
109 F::from_canonical_usize(RV32_REGISTER_NUM_LIMBS * dec_insn.rs1),
110 F::from_canonical_usize(RV32_REGISTER_NUM_LIMBS * dec_insn.rs2),
111 isize_to_field(dec_insn.imm as isize),
112 F::ONE, F::ONE, F::ZERO,
115 F::ZERO,
116 )
117}
118
119pub fn from_j_type<F: PrimeField32>(opcode: usize, dec_insn: &JType) -> Instruction<F> {
121 Instruction::new(
122 VmOpcode::from_usize(opcode),
123 F::from_canonical_usize(RV32_REGISTER_NUM_LIMBS * dec_insn.rd),
124 F::ZERO,
125 isize_to_field(dec_insn.imm as isize),
126 F::ONE, F::ZERO,
128 F::from_bool(dec_insn.rd != 0), F::ZERO,
130 )
131}
132
133pub fn from_u_type<F: PrimeField32>(opcode: usize, dec_insn: &UType) -> Instruction<F> {
135 if dec_insn.rd == 0 {
136 return nop();
137 }
138 Instruction::new(
139 VmOpcode::from_usize(opcode),
140 F::from_canonical_usize(RV32_REGISTER_NUM_LIMBS * dec_insn.rd),
141 F::ZERO,
142 F::from_canonical_u32((dec_insn.imm as u32 >> 12) & 0xfffff),
143 F::ONE, F::ZERO,
145 F::ZERO,
146 F::ZERO,
147 )
148}
149
150pub fn unimp<F: PrimeField32>() -> Instruction<F> {
152 Instruction {
153 opcode: SystemOpcode::TERMINATE.global_opcode(),
154 c: F::TWO,
155 ..Default::default()
156 }
157}
158
159pub fn nop<F: PrimeField32>() -> Instruction<F> {
160 Instruction {
161 opcode: SystemOpcode::PHANTOM.global_opcode(),
162 ..Default::default()
163 }
164}
165
166pub fn elf_memory_image_to_openvm_memory_image<F: PrimeField32>(
168 memory_image: BTreeMap<u32, u32>,
169) -> MemoryImage<F> {
170 let mut result = MemoryImage::new();
171 for (addr, word) in memory_image {
172 for (i, byte) in word.to_le_bytes().into_iter().enumerate() {
173 result.insert(
174 (RV32_MEMORY_AS, addr + i as u32),
175 F::from_canonical_u8(byte),
176 );
177 }
178 }
179 result
180}