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   ({})fp, ({})fp, {}, {}, {}",
182                    dst, src, var_index, size, offset
183                )
184            }
185            AsmInstruction::LoadEI(dst, src, var_index, size, offset) => {
186                write!(
187                    f,
188                    "lei   ({})fp, ({})fp, {}, {}, {}",
189                    dst, src, var_index, size, offset
190                )
191            }
192            AsmInstruction::StoreFI(dst, src, var_index, size, offset) => {
193                write!(
194                    f,
195                    "swi   ({})fp, ({})fp, {}, {}, {}",
196                    dst, src, var_index, size, offset
197                )
198            }
199            AsmInstruction::StoreEI(dst, src, var_index, size, offset) => {
200                write!(
201                    f,
202                    "sei   ({})fp, ({})fp, {}, {}, {}",
203                    dst, src, var_index, size, offset
204                )
205            }
206            AsmInstruction::ImmF(dst, src) => {
207                write!(f, "imm   ({})fp, ({})", dst, src)
208            }
209            AsmInstruction::CopyF(dst, src) => {
210                write!(f, "copy  ({})fp, ({})", dst, src)
211            }
212            AsmInstruction::AddF(dst, lhs, rhs) => {
213                write!(f, "add   ({})fp, ({})fp, ({})fp", dst, lhs, rhs)
214            }
215            AsmInstruction::AddFI(dst, lhs, rhs) => {
216                write!(f, "addi  ({})fp, ({})fp, {}", dst, lhs, rhs)
217            }
218            AsmInstruction::SubF(dst, lhs, rhs) => {
219                write!(f, "sub   ({})fp, ({})fp, ({})fp", dst, lhs, rhs)
220            }
221            AsmInstruction::SubFI(dst, lhs, rhs) => {
222                write!(f, "subi  ({})fp, ({})fp, {}", dst, lhs, rhs)
223            }
224            AsmInstruction::SubFIN(dst, lhs, rhs) => {
225                write!(f, "subin ({})fp, {}, ({})fp", dst, lhs, rhs)
226            }
227            AsmInstruction::MulF(dst, lhs, rhs) => {
228                write!(f, "mul   ({})fp, ({})fp, ({})fp", dst, lhs, rhs)
229            }
230            AsmInstruction::MulFI(dst, lhs, rhs) => {
231                write!(f, "muli  ({})fp, ({})fp, {}", dst, lhs, rhs)
232            }
233            AsmInstruction::DivF(dst, lhs, rhs) => {
234                write!(f, "div   ({})fp, ({})fp, ({})fp", dst, lhs, rhs)
235            }
236            AsmInstruction::DivFI(dst, lhs, rhs) => {
237                write!(f, "divi  ({})fp, ({})fp, {}", dst, lhs, rhs)
238            }
239            AsmInstruction::DivFIN(dst, lhs, rhs) => {
240                write!(f, "divi  ({})fp, {}, ({})fp", dst, lhs, rhs)
241            }
242            AsmInstruction::AddE(dst, lhs, rhs) => {
243                write!(f, "eadd ({})fp, ({})fp, ({})fp", dst, lhs, rhs)
244            }
245            AsmInstruction::SubE(dst, lhs, rhs) => {
246                write!(f, "esub  ({})fp, ({})fp, ({})fp", dst, lhs, rhs)
247            }
248            AsmInstruction::MulE(dst, lhs, rhs) => {
249                write!(f, "emul  ({})fp, ({})fp, ({})fp", dst, lhs, rhs)
250            }
251            AsmInstruction::DivE(dst, lhs, rhs) => {
252                write!(f, "ediv  ({})fp, ({})fp, ({})fp", dst, lhs, rhs)
253            }
254            AsmInstruction::Jump(dst, label) => {
255                write!(
256                    f,
257                    "j     ({})fp, {}",
258                    dst,
259                    labels.get(label).unwrap_or(&format!(".L{}", label))
260                )
261            }
262            AsmInstruction::Bne(label, lhs, rhs) => {
263                write!(
264                    f,
265                    "bne   {}, ({})fp, ({})fp",
266                    labels.get(label).unwrap_or(&format!(".L{}", label)),
267                    lhs,
268                    rhs
269                )
270            }
271            AsmInstruction::BneI(label, lhs, rhs) => {
272                write!(
273                    f,
274                    "bnei  {}, ({})fp, {}",
275                    labels.get(label).unwrap_or(&format!(".L{}", label)),
276                    lhs,
277                    rhs
278                )
279            }
280            AsmInstruction::Beq(label, lhs, rhs) => {
281                write!(
282                    f,
283                    "beq  {}, ({})fp, ({})fp",
284                    labels.get(label).unwrap_or(&format!(".L{}", label)),
285                    lhs,
286                    rhs
287                )
288            }
289            AsmInstruction::BeqI(label, lhs, rhs) => {
290                write!(
291                    f,
292                    "beqi {}, ({})fp, {}",
293                    labels.get(label).unwrap_or(&format!(".L{}", label)),
294                    lhs,
295                    rhs
296                )
297            }
298            AsmInstruction::BneE(label, lhs, rhs) => {
299                write!(
300                    f,
301                    "ebne  {}, ({})fp, ({})fp",
302                    labels.get(label).unwrap_or(&format!(".L{}", label)),
303                    lhs,
304                    rhs
305                )
306            }
307            AsmInstruction::BneEI(label, lhs, rhs) => {
308                write!(
309                    f,
310                    "ebnei {}, ({})fp, {}",
311                    labels.get(label).unwrap_or(&format!(".L{}", label)),
312                    lhs,
313                    rhs
314                )
315            }
316            AsmInstruction::BeqE(label, lhs, rhs) => {
317                write!(
318                    f,
319                    "ebeq  {}, ({})fp, ({})fp",
320                    labels.get(label).unwrap_or(&format!(".L{}", label)),
321                    lhs,
322                    rhs
323                )
324            }
325            AsmInstruction::BeqEI(label, lhs, rhs) => {
326                write!(
327                    f,
328                    "ebeqi {}, ({})fp, {}",
329                    labels.get(label).unwrap_or(&format!(".L{}", label)),
330                    lhs,
331                    rhs
332                )
333            }
334            AsmInstruction::Trap => write!(f, "trap"),
335            AsmInstruction::Halt => write!(f, "halt"),
336            AsmInstruction::HintBits(src, len) => write!(f, "hint_bits ({})fp, {}", src, len),
337            AsmInstruction::Poseidon2Permute(dst, lhs) => {
338                write!(f, "poseidon2_permute ({})fp, ({})fp", dst, lhs)
339            }
340            AsmInstruction::Poseidon2Compress(result, src1, src2) => {
341                write!(
342                    f,
343                    "poseidon2_compress ({})fp, ({})fp, ({})fp",
344                    result, src1, src2
345                )
346            }
347            AsmInstruction::PrintF(dst) => {
348                write!(f, "print_f ({})fp", dst)
349            }
350            AsmInstruction::PrintV(dst) => {
351                write!(f, "print_v ({})fp", dst)
352            }
353            AsmInstruction::PrintE(dst) => {
354                write!(f, "print_e ({})fp", dst)
355            }
356            AsmInstruction::HintInputVec() => write!(f, "hint_vec"),
357            AsmInstruction::HintFelt() => write!(f, "hint_felt"),
358            AsmInstruction::StoreHintWordI(dst, offset) => {
359                write!(f, "shintw ({})fp {}", dst, offset)
360            }
361            AsmInstruction::StoreHintExtI(dst, offset) => {
362                write!(f, "shinte ({})fp {}", dst, offset)
363            }
364            AsmInstruction::HintLoad() => write!(f, "hint_load"),
365            AsmInstruction::Publish(val, index) => {
366                write!(f, "commit ({})fp ({})fp", val, index)
367            }
368            AsmInstruction::CycleTrackerStart() => {
369                write!(f, "cycle_tracker_start")
370            }
371            AsmInstruction::CycleTrackerEnd() => {
372                write!(f, "cycle_tracker_end")
373            }
374            AsmInstruction::FriReducedOpening(a, b, length, alpha, res, hint_id, is_init) => {
375                write!(
376                    f,
377                    "fri_mat_opening ({})fp, ({})fp, ({})fp, ({})fp, ({})fp, ({})fp, ({})fp",
378                    a, b, length, alpha, res, hint_id, is_init
379                )
380            }
381            AsmInstruction::VerifyBatchFelt(dim, opened, opened_length, sibling, index, commit) => {
382                write!(
383                    f,
384                    "verify_batch_felt ({})fp, ({})fp, ({})fp, ({})fp, ({})fp, ({})fp",
385                    dim, opened, opened_length, sibling, index, commit
386                )
387            }
388            AsmInstruction::VerifyBatchExt(dim, opened, opened_length, sibling, index, commit) => {
389                write!(
390                    f,
391                    "verify_batch_ext ({})fp, ({})fp, ({})fp, ({})fp, ({})fp, ({})fp",
392                    dim, opened, opened_length, sibling, index, commit
393                )
394            }
395            AsmInstruction::RangeCheck(fp, lo_bits, hi_bits) => {
396                write!(f, "range_check_fp ({})fp, ({}), ({})", fp, lo_bits, hi_bits)
397            }
398        }
399    }
400}