openvm_native_compiler/asm/
instruction.rs

1use alloc::{collections::BTreeMap, format};
2use core::fmt;
3
4use openvm_stark_backend::p3_field::{ExtensionField, PrimeField32};
5
6use super::A0;
7
8#[derive(Debug, Clone)]
9pub enum AsmInstruction<F, EF> {
10    /// Load word (dst, src, var_index, size, offset).
11    ///
12    /// Load a value from the address stored at src(fp) into dst(fp) with given index and offset.
13    LoadFI(i32, i32, F, F, F),
14
15    /// Load extension word (dst, src, var_index, size, offset).
16    ///
17    /// Load an extension from the address stored at src(fp) into dst(fp) with given index and offset.
18    LoadEI(i32, i32, F, F, F),
19
20    /// Store word (val, addr, var_index, size, offset)
21    ///
22    /// Store a value from val(fp) into the address stored at addr(fp) with given index and offset.
23    StoreFI(i32, i32, F, F, F),
24
25    /// Store extension word (val, addr, var_index, size, offset)
26    ///
27    /// Store an extension from val(fp) into the address stored at addr(fp) with given index and offset.
28    StoreEI(i32, i32, F, F, F),
29
30    /// Set dst = imm.
31    ImmF(i32, F),
32
33    /// Copy, dst = src.
34    CopyF(i32, i32),
35
36    /// Add, dst = lhs + rhs.
37    AddF(i32, i32, i32),
38
39    /// Add immediate, dst = lhs + rhs.
40    AddFI(i32, i32, F),
41
42    /// Subtract, dst = lhs - rhs.
43    SubF(i32, i32, i32),
44
45    /// Subtract immediate, dst = lhs - rhs.
46    SubFI(i32, i32, F),
47
48    /// Subtract value from immediate, dst = lhs - rhs.
49    SubFIN(i32, F, i32),
50
51    /// Multiply, dst = lhs * rhs.
52    MulF(i32, i32, i32),
53
54    /// Multiply immediate.
55    MulFI(i32, i32, F),
56
57    /// Divide, dst = lhs / rhs.
58    DivF(i32, i32, i32),
59
60    /// Divide immediate, dst = lhs / rhs.
61    DivFI(i32, i32, F),
62
63    /// Divide value from immediate, dst = lhs / rhs.
64    DivFIN(i32, F, i32),
65
66    /// Add extension, dst = lhs + rhs.
67    AddE(i32, i32, i32),
68
69    /// Subtract extension, dst = lhs - rhs.
70    SubE(i32, i32, i32),
71
72    /// Multiply extension, dst = lhs * rhs.
73    MulE(i32, i32, i32),
74
75    /// Divide extension, dst = lhs / rhs.
76    DivE(i32, i32, i32),
77
78    /// Jump.
79    Jump(i32, F),
80
81    /// Branch not equal.
82    Bne(F, i32, i32),
83
84    /// Branch not equal immediate.
85    BneI(F, i32, F),
86
87    /// Branch equal.
88    Beq(F, i32, i32),
89
90    /// Branch equal immediate.
91    BeqI(F, i32, F),
92
93    /// Branch not equal extension.
94    BneE(F, i32, i32),
95
96    /// Branch not equal immediate extension.
97    BneEI(F, i32, EF),
98
99    /// Branch equal extension.
100    BeqE(F, i32, i32),
101
102    /// Branch equal immediate extension.
103    BeqEI(F, i32, EF),
104
105    /// Trap.
106    Trap,
107
108    /// Halt.
109    Halt,
110
111    /// Perform a Poseidon2 permutation on state starting at address `lhs`
112    /// and store new state at `rhs`.
113    /// (a, b) are pointers to (lhs, rhs).
114    Poseidon2Permute(i32, i32),
115    /// Perform 2-to-1 cryptographic compression using Poseidon2.
116    /// (a, b, c) are memory pointers to (dst, lhs, rhs)
117    Poseidon2Compress(i32, i32, i32),
118
119    /// (a, b, res, alpha, hint_id, hint_offset, is_init)
120    FriReducedOpening(i32, i32, i32, i32, i32, i32, i32),
121
122    /// (dim, opened, opened_length, sibling, index, commit)
123    /// opened values are field elements
124    VerifyBatchFelt(i32, i32, i32, i32, i32, i32),
125
126    /// (dim, opened, opened_length, sibling, index, commit)
127    /// opened values are extension field elements
128    VerifyBatchExt(i32, i32, i32, i32, i32, i32),
129
130    /// (v, x_bit, y_bit)
131    /// Assert that v = x + y * 2^16 where x < 2^x_bit and y < 2^y_bit.
132    RangeCheck(i32, i32, i32),
133
134    /// Print a variable.
135    PrintV(i32),
136
137    /// Print a felt.
138    PrintF(i32),
139
140    /// Print an extension element.
141    PrintE(i32),
142
143    /// Add next input vector to hint stream.
144    HintInputVec(),
145    /// Add next felt to hint stream,
146    HintFelt(),
147
148    /// HintBits(src, len).
149    ///
150    /// Bit decompose the field element at pointer `src` to the first `len` little endian bits and add to hint stream.
151    HintBits(i32, u32),
152
153    HintLoad(),
154
155    /// Stores the next hint stream word into value stored at addr + value.
156    StoreHintWordI(i32, F),
157
158    /// Stores the next hint stream ext into value stored at addr + value.
159    StoreHintExtI(i32, F),
160
161    /// Publish(val, index).
162    Publish(i32, i32),
163
164    CycleTrackerStart(),
165    CycleTrackerEnd(),
166}
167
168impl<F: PrimeField32, EF: ExtensionField<F>> AsmInstruction<F, EF> {
169    pub fn j(label: F) -> Self {
170        AsmInstruction::Jump(A0, label)
171    }
172
173    pub fn fmt(&self, labels: &BTreeMap<F, String>, f: &mut fmt::Formatter) -> fmt::Result {
174        match self {
175            AsmInstruction::LoadFI(dst, src, var_index, size, offset) => {
176                write!(
177                    f,
178                    "lwi   ({})fp, ({})fp, {}, {}, {}",
179                    dst, src, var_index, size, offset
180                )
181            }
182            AsmInstruction::LoadEI(dst, src, var_index, size, offset) => {
183                write!(
184                    f,
185                    "lei   ({})fp, ({})fp, {}, {}, {}",
186                    dst, src, var_index, size, offset
187                )
188            }
189            AsmInstruction::StoreFI(dst, src, var_index, size, offset) => {
190                write!(
191                    f,
192                    "swi   ({})fp, ({})fp, {}, {}, {}",
193                    dst, src, var_index, size, offset
194                )
195            }
196            AsmInstruction::StoreEI(dst, src, var_index, size, offset) => {
197                write!(
198                    f,
199                    "sei   ({})fp, ({})fp, {}, {}, {}",
200                    dst, src, var_index, size, offset
201                )
202            }
203            AsmInstruction::ImmF(dst, src) => {
204                write!(f, "imm   ({})fp, ({})", dst, src)
205            }
206            AsmInstruction::CopyF(dst, src) => {
207                write!(f, "copy  ({})fp, ({})", dst, src)
208            }
209            AsmInstruction::AddF(dst, lhs, rhs) => {
210                write!(f, "add   ({})fp, ({})fp, ({})fp", dst, lhs, rhs)
211            }
212            AsmInstruction::AddFI(dst, lhs, rhs) => {
213                write!(f, "addi  ({})fp, ({})fp, {}", dst, lhs, rhs)
214            }
215            AsmInstruction::SubF(dst, lhs, rhs) => {
216                write!(f, "sub   ({})fp, ({})fp, ({})fp", dst, lhs, rhs)
217            }
218            AsmInstruction::SubFI(dst, lhs, rhs) => {
219                write!(f, "subi  ({})fp, ({})fp, {}", dst, lhs, rhs)
220            }
221            AsmInstruction::SubFIN(dst, lhs, rhs) => {
222                write!(f, "subin ({})fp, {}, ({})fp", dst, lhs, rhs)
223            }
224            AsmInstruction::MulF(dst, lhs, rhs) => {
225                write!(f, "mul   ({})fp, ({})fp, ({})fp", dst, lhs, rhs)
226            }
227            AsmInstruction::MulFI(dst, lhs, rhs) => {
228                write!(f, "muli  ({})fp, ({})fp, {}", dst, lhs, rhs)
229            }
230            AsmInstruction::DivF(dst, lhs, rhs) => {
231                write!(f, "div   ({})fp, ({})fp, ({})fp", dst, lhs, rhs)
232            }
233            AsmInstruction::DivFI(dst, lhs, rhs) => {
234                write!(f, "divi  ({})fp, ({})fp, {}", dst, lhs, rhs)
235            }
236            AsmInstruction::DivFIN(dst, lhs, rhs) => {
237                write!(f, "divi  ({})fp, {}, ({})fp", dst, lhs, rhs)
238            }
239            AsmInstruction::AddE(dst, lhs, rhs) => {
240                write!(f, "eadd ({})fp, ({})fp, ({})fp", dst, lhs, rhs)
241            }
242            AsmInstruction::SubE(dst, lhs, rhs) => {
243                write!(f, "esub  ({})fp, ({})fp, ({})fp", dst, lhs, rhs)
244            }
245            AsmInstruction::MulE(dst, lhs, rhs) => {
246                write!(f, "emul  ({})fp, ({})fp, ({})fp", dst, lhs, rhs)
247            }
248            AsmInstruction::DivE(dst, lhs, rhs) => {
249                write!(f, "ediv  ({})fp, ({})fp, ({})fp", dst, lhs, rhs)
250            }
251            AsmInstruction::Jump(dst, label) => {
252                write!(
253                    f,
254                    "j     ({})fp, {}",
255                    dst,
256                    labels.get(label).unwrap_or(&format!(".L{}", label))
257                )
258            }
259            AsmInstruction::Bne(label, lhs, rhs) => {
260                write!(
261                    f,
262                    "bne   {}, ({})fp, ({})fp",
263                    labels.get(label).unwrap_or(&format!(".L{}", label)),
264                    lhs,
265                    rhs
266                )
267            }
268            AsmInstruction::BneI(label, lhs, rhs) => {
269                write!(
270                    f,
271                    "bnei  {}, ({})fp, {}",
272                    labels.get(label).unwrap_or(&format!(".L{}", label)),
273                    lhs,
274                    rhs
275                )
276            }
277            AsmInstruction::Beq(label, lhs, rhs) => {
278                write!(
279                    f,
280                    "beq  {}, ({})fp, ({})fp",
281                    labels.get(label).unwrap_or(&format!(".L{}", label)),
282                    lhs,
283                    rhs
284                )
285            }
286            AsmInstruction::BeqI(label, lhs, rhs) => {
287                write!(
288                    f,
289                    "beqi {}, ({})fp, {}",
290                    labels.get(label).unwrap_or(&format!(".L{}", label)),
291                    lhs,
292                    rhs
293                )
294            }
295            AsmInstruction::BneE(label, lhs, rhs) => {
296                write!(
297                    f,
298                    "ebne  {}, ({})fp, ({})fp",
299                    labels.get(label).unwrap_or(&format!(".L{}", label)),
300                    lhs,
301                    rhs
302                )
303            }
304            AsmInstruction::BneEI(label, lhs, rhs) => {
305                write!(
306                    f,
307                    "ebnei {}, ({})fp, {}",
308                    labels.get(label).unwrap_or(&format!(".L{}", label)),
309                    lhs,
310                    rhs
311                )
312            }
313            AsmInstruction::BeqE(label, lhs, rhs) => {
314                write!(
315                    f,
316                    "ebeq  {}, ({})fp, ({})fp",
317                    labels.get(label).unwrap_or(&format!(".L{}", label)),
318                    lhs,
319                    rhs
320                )
321            }
322            AsmInstruction::BeqEI(label, lhs, rhs) => {
323                write!(
324                    f,
325                    "ebeqi {}, ({})fp, {}",
326                    labels.get(label).unwrap_or(&format!(".L{}", label)),
327                    lhs,
328                    rhs
329                )
330            }
331            AsmInstruction::Trap => write!(f, "trap"),
332            AsmInstruction::Halt => write!(f, "halt"),
333            AsmInstruction::HintBits(src, len) => write!(f, "hint_bits ({})fp, {}", src, len),
334            AsmInstruction::Poseidon2Permute(dst, lhs) => {
335                write!(f, "poseidon2_permute ({})fp, ({})fp", dst, lhs)
336            }
337            AsmInstruction::Poseidon2Compress(result, src1, src2) => {
338                write!(
339                    f,
340                    "poseidon2_compress ({})fp, ({})fp, ({})fp",
341                    result, src1, src2
342                )
343            }
344            AsmInstruction::PrintF(dst) => {
345                write!(f, "print_f ({})fp", dst)
346            }
347            AsmInstruction::PrintV(dst) => {
348                write!(f, "print_v ({})fp", dst)
349            }
350            AsmInstruction::PrintE(dst) => {
351                write!(f, "print_e ({})fp", dst)
352            }
353            AsmInstruction::HintInputVec() => write!(f, "hint_vec"),
354            AsmInstruction::HintFelt() => write!(f, "hint_felt"),
355            AsmInstruction::StoreHintWordI(dst, offset) => {
356                write!(f, "shintw ({})fp {}", dst, offset)
357            }
358            AsmInstruction::StoreHintExtI(dst, offset) => {
359                write!(f, "shinte ({})fp {}", dst, offset)
360            }
361            AsmInstruction::HintLoad() => write!(f, "hint_load"),
362            AsmInstruction::Publish(val, index) => {
363                write!(f, "commit ({})fp ({})fp", val, index)
364            }
365            AsmInstruction::CycleTrackerStart() => {
366                write!(f, "cycle_tracker_start")
367            }
368            AsmInstruction::CycleTrackerEnd() => {
369                write!(f, "cycle_tracker_end")
370            }
371            AsmInstruction::FriReducedOpening(a, b, length, alpha, res, hint_id, is_init) => {
372                write!(
373                    f,
374                    "fri_mat_opening ({})fp, ({})fp, ({})fp, ({})fp, ({})fp, ({})fp, ({})fp",
375                    a, b, length, alpha, res, hint_id, is_init
376                )
377            }
378            AsmInstruction::VerifyBatchFelt(dim, opened, opened_length, sibling, index, commit) => {
379                write!(
380                    f,
381                    "verify_batch_felt ({})fp, ({})fp, ({})fp, ({})fp, ({})fp, ({})fp",
382                    dim, opened, opened_length, sibling, index, commit
383                )
384            }
385            AsmInstruction::VerifyBatchExt(dim, opened, opened_length, sibling, index, commit) => {
386                write!(
387                    f,
388                    "verify_batch_ext ({})fp, ({})fp, ({})fp, ({})fp, ({})fp, ({})fp",
389                    dim, opened, opened_length, sibling, index, commit
390                )
391            }
392            AsmInstruction::RangeCheck(fp, lo_bits, hi_bits) => {
393                write!(f, "range_check_fp ({})fp, ({}), ({})", fp, lo_bits, hi_bits)
394            }
395        }
396    }
397}