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