1use std::collections::BTreeMap;
2
3use openvm_instructions::{
4 exe::SparseMemoryImage,
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> {
45 if dec_insn.rd == 0 {
46 return nop();
47 }
48 Instruction::new(
49 VmOpcode::from_usize(opcode),
50 F::from_canonical_usize(RV32_REGISTER_NUM_LIMBS * dec_insn.rd),
51 F::from_canonical_usize(RV32_REGISTER_NUM_LIMBS * dec_insn.rs1),
52 F::from_canonical_u32(i12_to_u24(dec_insn.imm)),
53 F::ONE, F::ZERO, F::ZERO,
56 F::ZERO,
57 )
58}
59
60pub fn from_load<F: PrimeField32>(opcode: usize, dec_insn: &IType) -> Instruction<F> {
62 Instruction::new(
63 VmOpcode::from_usize(opcode),
64 F::from_canonical_usize(RV32_REGISTER_NUM_LIMBS * dec_insn.rd),
65 F::from_canonical_usize(RV32_REGISTER_NUM_LIMBS * dec_insn.rs1),
66 F::from_canonical_u32((dec_insn.imm as u32) & 0xffff),
67 F::ONE, F::TWO, F::from_bool(dec_insn.rd != 0), F::from_bool(dec_insn.imm < 0), )
72}
73
74pub fn from_i_type_shamt<F: PrimeField32>(opcode: usize, dec_insn: &ITypeShamt) -> Instruction<F> {
77 if dec_insn.rd == 0 {
78 return nop();
79 }
80 Instruction::new(
81 VmOpcode::from_usize(opcode),
82 F::from_canonical_usize(RV32_REGISTER_NUM_LIMBS * dec_insn.rd),
83 F::from_canonical_usize(RV32_REGISTER_NUM_LIMBS * dec_insn.rs1),
84 F::from_canonical_u32(dec_insn.shamt),
85 F::ONE, F::ZERO, F::ZERO,
88 F::ZERO,
89 )
90}
91
92pub fn from_s_type<F: PrimeField32>(opcode: usize, dec_insn: &SType) -> Instruction<F> {
94 Instruction::new(
95 VmOpcode::from_usize(opcode),
96 F::from_canonical_usize(RV32_REGISTER_NUM_LIMBS * dec_insn.rs2),
97 F::from_canonical_usize(RV32_REGISTER_NUM_LIMBS * dec_insn.rs1),
98 F::from_canonical_u32((dec_insn.imm as u32) & 0xffff),
99 F::ONE,
100 F::TWO,
101 F::ONE,
102 F::from_bool(dec_insn.imm < 0),
103 )
104}
105
106pub fn from_b_type<F: PrimeField32>(opcode: usize, dec_insn: &BType) -> Instruction<F> {
108 Instruction::new(
109 VmOpcode::from_usize(opcode),
110 F::from_canonical_usize(RV32_REGISTER_NUM_LIMBS * dec_insn.rs1),
111 F::from_canonical_usize(RV32_REGISTER_NUM_LIMBS * dec_insn.rs2),
112 isize_to_field(dec_insn.imm as isize),
113 F::ONE, F::ONE, F::ZERO,
116 F::ZERO,
117 )
118}
119
120pub fn from_j_type<F: PrimeField32>(opcode: usize, dec_insn: &JType) -> Instruction<F> {
122 Instruction::new(
123 VmOpcode::from_usize(opcode),
124 F::from_canonical_usize(RV32_REGISTER_NUM_LIMBS * dec_insn.rd),
125 F::ZERO,
126 isize_to_field(dec_insn.imm as isize),
127 F::ONE, F::ZERO,
129 F::from_bool(dec_insn.rd != 0), F::ZERO,
131 )
132}
133
134pub fn from_u_type<F: PrimeField32>(opcode: usize, dec_insn: &UType) -> Instruction<F> {
136 if dec_insn.rd == 0 {
137 return nop();
138 }
139 Instruction::new(
140 VmOpcode::from_usize(opcode),
141 F::from_canonical_usize(RV32_REGISTER_NUM_LIMBS * dec_insn.rd),
142 F::ZERO,
143 F::from_canonical_u32((dec_insn.imm as u32 >> 12) & 0xfffff),
144 F::ONE, F::ZERO,
146 F::ZERO,
147 F::ZERO,
148 )
149}
150
151pub fn unimp<F: PrimeField32>() -> Instruction<F> {
154 Instruction {
155 opcode: SystemOpcode::TERMINATE.global_opcode(),
156 c: F::TWO,
157 ..Default::default()
158 }
159}
160
161pub fn nop<F: PrimeField32>() -> Instruction<F> {
162 Instruction {
163 opcode: SystemOpcode::PHANTOM.global_opcode(),
164 ..Default::default()
165 }
166}
167
168pub fn elf_memory_image_to_openvm_memory_image(
170 memory_image: BTreeMap<u32, u32>,
171) -> SparseMemoryImage {
172 let mut result = SparseMemoryImage::new();
173 for (addr, word) in memory_image {
174 for (i, byte) in word.to_le_bytes().into_iter().enumerate() {
175 result.insert((RV32_MEMORY_AS, addr + i as u32), byte);
176 }
177 }
178 result
179}