tci/runtime/
interpreter.rs

1use super::error::*;
2use super::memory::*;
3use super::types::*;
4use crate::util::*;
5
6pub fn run_op_count(memory: &mut Memory, count: u32) -> (u32, Result<Option<EcallExt>, IError>) {
7    for idx in 0..count {
8        match run_op(memory) {
9            Ok(None) => {}
10            Ok(Some(ecall)) => return (idx + 1, Ok(Some(ecall))),
11            Err(ierr) => return (idx, Err(ierr)),
12        }
13    }
14
15    return (count, Ok(None));
16}
17
18pub fn run_op(memory: &mut Memory) -> Result<Option<EcallExt>, IError> {
19    let op: Opcode = memory.read_pc()?;
20
21    match op {
22        Opcode::Func => {
23            // this opcode is handled by Memory
24            return Err(ierror!(
25                "InvalidOpcode",
26                "Found Func opcode (this is an error in TCI)"
27            ));
28        }
29        Opcode::Loc => {
30            let loc = memory.read_pc()?;
31            memory.set_loc(loc);
32        }
33        Opcode::StackAlloc => {
34            let bytes: u32 = memory.read_pc()?;
35            memory.add_stack_var(bytes)?;
36        }
37        Opcode::StackDealloc => {
38            memory.pop_stack_var()?;
39        }
40
41        Opcode::Make8 => {
42            let val: u8 = memory.read_pc()?;
43            memory.push(val);
44        }
45        Opcode::Make16 => {
46            let val: u16 = memory.read_pc()?;
47            memory.push(val);
48        }
49        Opcode::Make32 => {
50            let val: u32 = memory.read_pc()?;
51            memory.push(val);
52        }
53        Opcode::Make64 => {
54            let val: u64 = memory.read_pc()?;
55            memory.push(val);
56        }
57        Opcode::MakeSp => {
58            let var_offset: i16 = memory.read_pc()?;
59            let stack_len = memory.stack.len() as u16;
60            let var = (stack_len as i16 + var_offset) as u16;
61
62            memory.push(VarPointer::new_stack(var, 0));
63        }
64        Opcode::MakeFp => {
65            let var_offset: i16 = memory.read_pc()?;
66            let var = (memory.fp as i16 + var_offset) as u16;
67
68            memory.push(VarPointer::new_stack(var, 0));
69        }
70
71        Opcode::PushUndef => {
72            let bytes: u32 = memory.read_pc()?;
73            let stack_len = memory.expr_stack.len();
74            memory.expr_stack.resize(stack_len + bytes as usize, 0);
75        }
76        Opcode::Pop => {
77            let bytes = memory.read_pc()?;
78            memory.pop_bytes(bytes)?;
79        }
80        Opcode::Swap => {
81            let top_bytes = memory.read_pc()?;
82            let bottom_bytes = memory.read_pc()?;
83            memory.swap_bytes(top_bytes, bottom_bytes)?;
84        }
85        Opcode::Dup => {
86            let bytes = memory.read_pc()?;
87            memory.dup_bytes(bytes)?;
88        }
89        Opcode::PushDyn => {
90            let ptr: VarPointer = memory.pop()?;
91            let size: u32 = memory.pop()?;
92            memory.read_bytes_to_stack(ptr, size)?;
93        }
94
95        Opcode::I8ToF32 => {
96            let n: i8 = memory.pop()?;
97            memory.push(n as f32);
98        }
99        Opcode::U8ToF32 => {
100            let n: u8 = memory.pop()?;
101            memory.push(n as f32);
102        }
103        Opcode::I8ToF64 => {
104            let n: i8 = memory.pop()?;
105            memory.push(n as f64);
106        }
107        Opcode::U8ToF64 => {
108            let n: i8 = memory.pop()?;
109            memory.push(n as f64);
110        }
111        Opcode::I16ToF32 => {
112            let n: i16 = memory.pop()?;
113            memory.push(n as f32);
114        }
115        Opcode::U16ToF32 => {
116            let n: u16 = memory.pop()?;
117            memory.push(n as f32);
118        }
119        Opcode::I16ToF64 => {
120            let n: i16 = memory.pop()?;
121            memory.push(n as f64);
122        }
123        Opcode::U16ToF64 => {
124            let n: i16 = memory.pop()?;
125            memory.push(n as f64);
126        }
127        Opcode::I32ToF32 => {
128            let n: i32 = memory.pop()?;
129            memory.push(n as f32);
130        }
131        Opcode::U32ToF32 => {
132            let n: u32 = memory.pop()?;
133            memory.push(n as f32);
134        }
135        Opcode::I32ToF64 => {
136            let n: i32 = memory.pop()?;
137            memory.push(n as f64);
138        }
139        Opcode::U32ToF64 => {
140            let n: i32 = memory.pop()?;
141            memory.push(n as f64);
142        }
143        Opcode::I64ToF32 => {
144            let n: i64 = memory.pop()?;
145            memory.push(n as f32);
146        }
147        Opcode::U64ToF32 => {
148            let n: u64 = memory.pop()?;
149            memory.push(n as f32);
150        }
151        Opcode::I64ToF64 => {
152            let n: i64 = memory.pop()?;
153            memory.push(n as f64);
154        }
155        Opcode::U64ToF64 => {
156            let n: i64 = memory.pop()?;
157            memory.push(n as f64);
158        }
159
160        Opcode::F32ToI8 => {
161            let f: f32 = memory.pop()?;
162            memory.push(f as i8);
163        }
164        Opcode::F32ToU8 => {
165            let f: f32 = memory.pop()?;
166            memory.push(f as u8);
167        }
168        Opcode::F64ToI8 => {
169            let f: f64 = memory.pop()?;
170            memory.push(f as i8);
171        }
172        Opcode::F64ToU8 => {
173            let f: f64 = memory.pop()?;
174            memory.push(f as u8);
175        }
176        Opcode::F32ToI16 => {
177            let f: f32 = memory.pop()?;
178            memory.push(f as i16);
179        }
180        Opcode::F32ToU16 => {
181            let f: f32 = memory.pop()?;
182            memory.push(f as u16);
183        }
184        Opcode::F64ToI16 => {
185            let f: f64 = memory.pop()?;
186            memory.push(f as i16);
187        }
188        Opcode::F64ToU16 => {
189            let f: f64 = memory.pop()?;
190            memory.push(f as u16);
191        }
192        Opcode::F32ToI32 => {
193            let f: f32 = memory.pop()?;
194            memory.push(f as i32);
195        }
196        Opcode::F32ToU32 => {
197            let f: f32 = memory.pop()?;
198            memory.push(f as u32);
199        }
200        Opcode::F64ToI32 => {
201            let f: f64 = memory.pop()?;
202            memory.push(f as i32);
203        }
204        Opcode::F64ToU32 => {
205            let f: f64 = memory.pop()?;
206            memory.push(f as u32);
207        }
208        Opcode::F32ToI64 => {
209            let f: f32 = memory.pop()?;
210            memory.push(f as i64);
211        }
212        Opcode::F32ToU64 => {
213            let f: f32 = memory.pop()?;
214            memory.push(f as u64);
215        }
216        Opcode::F64ToI64 => {
217            let f: f64 = memory.pop()?;
218            memory.push(f as i64);
219        }
220        Opcode::F64ToU64 => {
221            let f: f64 = memory.pop()?;
222            memory.push(f as u64);
223        }
224
225        Opcode::F32ToF64 => {
226            let f: f32 = memory.pop()?;
227            memory.push(f as f64);
228        }
229        Opcode::F64ToF32 => {
230            let f: f64 = memory.pop()?;
231            memory.push(f as f32);
232        }
233
234        Opcode::SExtend8To16 => {
235            let val = memory.pop::<i8>()?;
236            memory.push(val as i16);
237        }
238        Opcode::SExtend8To32 => {
239            let val = memory.pop::<i8>()?;
240            memory.push(val as i32);
241        }
242        Opcode::SExtend8To64 => {
243            let val = memory.pop::<i8>()?;
244            memory.push(val as i64);
245        }
246        Opcode::SExtend16To32 => {
247            let val: i16 = memory.pop()?;
248            memory.push(val as i32);
249        }
250        Opcode::SExtend16To64 => {
251            let val: i16 = memory.pop()?;
252            memory.push(val as i64);
253        }
254        Opcode::SExtend32To64 => {
255            let val: i32 = memory.pop()?;
256            memory.push(val as i64);
257        }
258
259        Opcode::ZExtend8To16 => {
260            let val = memory.pop::<u8>()?;
261            memory.push(val as u16);
262        }
263        Opcode::ZExtend8To32 => {
264            let val = memory.pop::<u8>()?;
265            memory.push(val as u32);
266        }
267        Opcode::ZExtend8To64 => {
268            let val = memory.pop::<u8>()?;
269            memory.push(val as u64);
270        }
271        Opcode::ZExtend16To32 => {
272            let val: u16 = memory.pop()?;
273            memory.push(val as u32);
274        }
275        Opcode::ZExtend16To64 => {
276            let val: u16 = memory.pop()?;
277            memory.push(val as u64);
278        }
279        Opcode::ZExtend32To64 => {
280            let val: u32 = memory.pop()?;
281            memory.push(val as u64);
282        }
283
284        Opcode::Get => {
285            let bytes = memory.read_pc()?;
286            let ptr: VarPointer = memory.pop()?;
287
288            memory.read_bytes_to_stack(ptr, bytes)?;
289        }
290        Opcode::Set => {
291            let bytes = memory.read_pc()?;
292            let ptr: VarPointer = memory.pop()?;
293            memory.write_bytes_from_stack(ptr, bytes)?;
294        }
295
296        Opcode::BoolNorm8 => {
297            let bytes: u8 = memory.pop()?;
298            memory.push(if bytes != 0 { 1u8 } else { 0u8 });
299        }
300        Opcode::BoolNorm16 => {
301            let bytes: u16 = memory.pop()?;
302            memory.push(if bytes != 0 { 1u8 } else { 0u8 });
303        }
304        Opcode::BoolNorm32 => {
305            let bytes: u32 = memory.pop()?;
306            memory.push(if bytes != 0 { 1u8 } else { 0u8 });
307        }
308        Opcode::BoolNorm64 => {
309            let bytes: u64 = memory.pop()?;
310            memory.push(if bytes != 0 { 1u8 } else { 0u8 });
311        }
312
313        Opcode::BoolNot8 => {
314            let bytes: u8 = memory.pop()?;
315            memory.push(if bytes == 0 { 1u8 } else { 0u8 });
316        }
317        Opcode::BoolNot16 => {
318            let bytes: u16 = memory.pop()?;
319            memory.push(if bytes == 0 { 1u8 } else { 0u8 });
320        }
321        Opcode::BoolNot32 => {
322            let bytes: u32 = memory.pop()?;
323            memory.push(if bytes == 0 { 1u8 } else { 0u8 });
324        }
325        Opcode::BoolNot64 => {
326            let bytes: u64 = memory.pop()?;
327            memory.push(if bytes == 0 { 1u8 } else { 0u8 });
328        }
329
330        Opcode::CompLeqI8 => {
331            let word2: i8 = memory.pop()?;
332            let word1: i8 = memory.pop()?;
333            memory.push(if word1 <= word2 { 1u8 } else { 0u8 });
334        }
335        Opcode::CompLeqU8 => {
336            let word2: u8 = memory.pop()?;
337            let word1: u8 = memory.pop()?;
338            memory.push(if word1 <= word2 { 1u8 } else { 0u8 });
339        }
340        Opcode::CompLeqI16 => {
341            let word2: i16 = memory.pop()?;
342            let word1: i16 = memory.pop()?;
343            memory.push(if word1 <= word2 { 1u8 } else { 0u8 });
344        }
345        Opcode::CompLeqU16 => {
346            let word2: u16 = memory.pop()?;
347            let word1: u16 = memory.pop()?;
348            memory.push(if word1 <= word2 { 1u8 } else { 0u8 });
349        }
350        Opcode::CompLeqI32 => {
351            let word2: i32 = memory.pop()?;
352            let word1: i32 = memory.pop()?;
353            memory.push(if word1 <= word2 { 1u8 } else { 0u8 });
354        }
355        Opcode::CompLeqU32 => {
356            let word2: u32 = memory.pop()?;
357            let word1: u32 = memory.pop()?;
358            memory.push(if word1 <= word2 { 1u8 } else { 0u8 });
359        }
360        Opcode::CompLeqI64 => {
361            let word2: i64 = memory.pop()?;
362            let word1: i64 = memory.pop()?;
363            memory.push(if word1 <= word2 { 1u8 } else { 0u8 });
364        }
365        Opcode::CompLeqU64 => {
366            let word2: u64 = memory.pop()?;
367            let word1: u64 = memory.pop()?;
368            memory.push(if word1 <= word2 { 1u8 } else { 0u8 });
369        }
370        Opcode::CompLeqF32 => {
371            let word2: f32 = memory.pop()?;
372            let word1: f32 = memory.pop()?;
373            memory.push(if word1 < word2 { 1u8 } else { 0u8 });
374        }
375        Opcode::CompLeqF64 => {
376            let word2: f64 = memory.pop()?;
377            let word1: f64 = memory.pop()?;
378            memory.push(if word1 <= word2 { 1u8 } else { 0u8 });
379        }
380
381        Opcode::CompLtI8 => {
382            let word2: i8 = memory.pop()?;
383            let word1: i8 = memory.pop()?;
384            memory.push(if word1 <= word2 { 1u8 } else { 0u8 });
385        }
386        Opcode::CompLtU8 => {
387            let word2: u8 = memory.pop()?;
388            let word1: u8 = memory.pop()?;
389            memory.push(if word1 < word2 { 1u8 } else { 0u8 });
390        }
391        Opcode::CompLtI16 => {
392            let word2: i16 = memory.pop()?;
393            let word1: i16 = memory.pop()?;
394            memory.push(if word1 < word2 { 1u8 } else { 0u8 });
395        }
396        Opcode::CompLtU16 => {
397            let word2: u16 = memory.pop()?;
398            let word1: u16 = memory.pop()?;
399            memory.push(if word1 < word2 { 1u8 } else { 0u8 });
400        }
401        Opcode::CompLtI32 => {
402            let word2: i32 = memory.pop()?;
403            let word1: i32 = memory.pop()?;
404            memory.push(if word1 < word2 { 1u8 } else { 0u8 });
405        }
406        Opcode::CompLtU32 => {
407            let word2: u32 = memory.pop()?;
408            let word1: u32 = memory.pop()?;
409            memory.push(if word1 < word2 { 1u8 } else { 0u8 });
410        }
411        Opcode::CompLtI64 => {
412            let word2: i64 = memory.pop()?;
413            let word1: i64 = memory.pop()?;
414            memory.push(if word1 < word2 { 1u8 } else { 0u8 });
415        }
416        Opcode::CompLtU64 => {
417            let word2: u64 = memory.pop()?;
418            let word1: u64 = memory.pop()?;
419            memory.push(if word1 < word2 { 1u8 } else { 0u8 });
420        }
421        Opcode::CompLtF32 => {
422            let word2: f32 = memory.pop()?;
423            let word1: f32 = memory.pop()?;
424            memory.push(if word1 < word2 { 1u8 } else { 0u8 });
425        }
426        Opcode::CompLtF64 => {
427            let word2: f64 = memory.pop()?;
428            let word1: f64 = memory.pop()?;
429            memory.push(if word1 < word2 { 1u8 } else { 0u8 });
430        }
431
432        Opcode::CompEq8 => {
433            let word2: u8 = memory.pop()?;
434            let word1: u8 = memory.pop()?;
435            memory.push(if word1 == word2 { 1u8 } else { 0u8 });
436        }
437        Opcode::CompEq16 => {
438            let word2: u16 = memory.pop()?;
439            let word1: u16 = memory.pop()?;
440            memory.push(if word1 == word2 { 1u8 } else { 0u8 });
441        }
442        Opcode::CompEq32 => {
443            let word2: u32 = memory.pop()?;
444            let word1: u32 = memory.pop()?;
445            memory.push(if word1 == word2 { 1u8 } else { 0u8 });
446        }
447        Opcode::CompEq64 => {
448            let word2: u64 = memory.pop()?;
449            let word1: u64 = memory.pop()?;
450            memory.push(if word1 == word2 { 1u8 } else { 0u8 });
451        }
452        Opcode::CompEqF32 => {
453            let word2: f32 = memory.pop()?;
454            let word1: f32 = memory.pop()?;
455            memory.push(if word1 == word2 { 1u8 } else { 0u8 });
456        }
457        Opcode::CompEqF64 => {
458            let word2: f64 = memory.pop()?;
459            let word1: f64 = memory.pop()?;
460            memory.push(if word1 == word2 { 1u8 } else { 0u8 });
461        }
462
463        Opcode::CompNeq8 => {
464            let word2: i8 = memory.pop()?;
465            let word1: i8 = memory.pop()?;
466            memory.push(if word1 != word2 { 1u8 } else { 0u8 });
467        }
468        Opcode::CompNeq16 => {
469            let word2: i16 = memory.pop()?;
470            let word1: i16 = memory.pop()?;
471            memory.push(if word1 != word2 { 1u8 } else { 0u8 });
472        }
473        Opcode::CompNeq32 => {
474            let word2: i32 = memory.pop()?;
475            let word1: i32 = memory.pop()?;
476            memory.push(if word1 != word2 { 1u8 } else { 0u8 });
477        }
478        Opcode::CompNeq64 => {
479            let word2: i64 = memory.pop()?;
480            let word1: i64 = memory.pop()?;
481            memory.push(if word1 != word2 { 1u8 } else { 0u8 });
482        }
483        Opcode::CompNeqF32 => {
484            let word2: f32 = memory.pop()?;
485            let word1: f32 = memory.pop()?;
486            memory.push(if word1 != word2 { 1u8 } else { 0u8 });
487        }
488        Opcode::CompNeqF64 => {
489            let word2: f64 = memory.pop()?;
490            let word1: f64 = memory.pop()?;
491            memory.push(if word1 != word2 { 1u8 } else { 0u8 });
492        }
493
494        Opcode::Add8 => {
495            let word2: u8 = memory.pop()?;
496            let word1: u8 = memory.pop()?;
497            memory.push(word1.wrapping_add(word2));
498        }
499        Opcode::Add16 => {
500            let word2: u16 = memory.pop()?;
501            let word1: u16 = memory.pop()?;
502
503            memory.push(word1.wrapping_add(word2));
504        }
505        Opcode::Add32 => {
506            let word2: u32 = memory.pop()?;
507            let word1: u32 = memory.pop()?;
508            memory.push(word1.wrapping_add(word2));
509        }
510        Opcode::Add64 => {
511            let word2: u64 = memory.pop()?;
512            let word1: u64 = memory.pop()?;
513            memory.push(word1.wrapping_add(word2));
514        }
515        Opcode::AddF32 => {
516            let word2: f32 = memory.pop()?;
517            let word1: f32 = memory.pop()?;
518            memory.push(word1 + word2);
519        }
520        Opcode::AddF64 => {
521            let word2: f64 = memory.pop()?;
522            let word1: f64 = memory.pop()?;
523            memory.push(word1 + word2);
524        }
525
526        Opcode::SubI8 => {
527            let word2: i8 = memory.pop()?;
528            let word1: i8 = memory.pop()?;
529            memory.push(word1.wrapping_sub(word2));
530        }
531        Opcode::SubU8 => {
532            let word2: u8 = memory.pop()?;
533            let word1: u8 = memory.pop()?;
534            memory.push(word1.wrapping_sub(word2));
535        }
536        Opcode::SubI16 => {
537            let word2: i16 = memory.pop()?;
538            let word1: i16 = memory.pop()?;
539            memory.push(word1.wrapping_sub(word2));
540        }
541        Opcode::SubU16 => {
542            let word2: u16 = memory.pop()?;
543            let word1: u16 = memory.pop()?;
544            memory.push(word1.wrapping_sub(word2));
545        }
546        Opcode::SubI32 => {
547            let word2: i32 = memory.pop()?;
548            let word1: i32 = memory.pop()?;
549            memory.push(word1.wrapping_sub(word2));
550        }
551        Opcode::SubU32 => {
552            let word2: u32 = memory.pop()?;
553            let word1: u32 = memory.pop()?;
554            memory.push(word1.wrapping_sub(word2));
555        }
556        Opcode::SubI64 => {
557            let word2: i64 = memory.pop()?;
558            let word1: i64 = memory.pop()?;
559            memory.push(word1.wrapping_sub(word2));
560        }
561        Opcode::SubU64 => {
562            let word2: u64 = memory.pop()?;
563            let word1: u64 = memory.pop()?;
564            memory.push(word1.wrapping_sub(word2));
565        }
566        Opcode::SubF32 => {
567            let word2: f32 = memory.pop()?;
568            let word1: f32 = memory.pop()?;
569            memory.push(word1 - word2);
570        }
571        Opcode::SubF64 => {
572            let word2: f64 = memory.pop()?;
573            let word1: f64 = memory.pop()?;
574            memory.push(word1 - word2);
575        }
576
577        Opcode::MulU8 => {
578            let word2: u8 = memory.pop()?;
579            let word1: u8 = memory.pop()?;
580            memory.push(word1.wrapping_mul(word2));
581        }
582        Opcode::MulI8 => {
583            let word2: i8 = memory.pop()?;
584            let word1: i8 = memory.pop()?;
585            memory.push(word1.wrapping_mul(word2));
586        }
587        Opcode::MulI16 => {
588            let word2: i16 = memory.pop()?;
589            let word1: i16 = memory.pop()?;
590            memory.push(word1.wrapping_mul(word2));
591        }
592        Opcode::MulU16 => {
593            let word2: u16 = memory.pop()?;
594            let word1: u16 = memory.pop()?;
595            memory.push(word1.wrapping_mul(word2));
596        }
597        Opcode::MulU32 => {
598            let word2: u32 = memory.pop()?;
599            let word1: u32 = memory.pop()?;
600            memory.push(word1.wrapping_mul(word2));
601        }
602        Opcode::MulI32 => {
603            let word2: i32 = memory.pop()?;
604            let word1: i32 = memory.pop()?;
605            memory.push(word1.wrapping_mul(word2));
606        }
607        Opcode::MulI64 => {
608            let word2: i64 = memory.pop()?;
609            let word1: i64 = memory.pop()?;
610            memory.push(word1.wrapping_mul(word2));
611        }
612        Opcode::MulU64 => {
613            let word2: u64 = memory.pop()?;
614            let word1: u64 = memory.pop()?;
615            memory.push(word1.wrapping_mul(word2));
616        }
617        Opcode::MulF32 => {
618            let word2: f32 = memory.pop()?;
619            let word1: f32 = memory.pop()?;
620            memory.push(word1 * word2);
621        }
622        Opcode::MulF64 => {
623            let word2: f64 = memory.pop()?;
624            let word1: f64 = memory.pop()?;
625            memory.push(word1 * word2);
626        }
627
628        Opcode::DivU8 => {
629            let word2: u8 = memory.pop()?;
630            let word1: u8 = memory.pop()?;
631            memory.push(word1.wrapping_div(word2));
632        }
633        Opcode::DivI8 => {
634            let word2: i8 = memory.pop()?;
635            let word1: i8 = memory.pop()?;
636            memory.push(word1.wrapping_div(word2));
637        }
638        Opcode::DivI16 => {
639            let word2: i16 = memory.pop()?;
640            let word1: i16 = memory.pop()?;
641            memory.push(word1.wrapping_div(word2));
642        }
643        Opcode::DivU16 => {
644            let word2: u16 = memory.pop()?;
645            let word1: u16 = memory.pop()?;
646            memory.push(word1.wrapping_div(word2));
647        }
648        Opcode::DivU32 => {
649            let word2: u32 = memory.pop()?;
650            let word1: u32 = memory.pop()?;
651            memory.push(word1.wrapping_div(word2));
652        }
653        Opcode::DivI32 => {
654            let word2: i32 = memory.pop()?;
655            let word1: i32 = memory.pop()?;
656            memory.push(word1.wrapping_div(word2));
657        }
658        Opcode::DivI64 => {
659            let word2: i64 = memory.pop()?;
660            let word1: i64 = memory.pop()?;
661            memory.push(word1.wrapping_div(word2));
662        }
663        Opcode::DivU64 => {
664            let word2: u64 = memory.pop()?;
665            let word1: u64 = memory.pop()?;
666            memory.push(word1.wrapping_div(word2));
667        }
668        Opcode::DivF32 => {
669            let word2: f32 = memory.pop()?;
670            let word1: f32 = memory.pop()?;
671            memory.push(word1 / word2);
672        }
673        Opcode::DivF64 => {
674            let word2: f64 = memory.pop()?;
675            let word1: f64 = memory.pop()?;
676            memory.push(word1 / word2);
677        }
678
679        Opcode::ModU8 => {
680            let word2: u8 = memory.pop()?;
681            let word1: u8 = memory.pop()?;
682            memory.push(word1 % word2);
683        }
684        Opcode::ModI8 => {
685            let word2: i8 = memory.pop()?;
686            let word1: i8 = memory.pop()?;
687            memory.push(word1 % word2);
688        }
689        Opcode::ModI16 => {
690            let word2: i16 = memory.pop()?;
691            let word1: i16 = memory.pop()?;
692            memory.push(word1 % word2);
693        }
694        Opcode::ModU16 => {
695            let word2: u16 = memory.pop()?;
696            let word1: u16 = memory.pop()?;
697            memory.push(word1 % word2);
698        }
699        Opcode::ModU32 => {
700            let word2: u32 = memory.pop()?;
701            let word1: u32 = memory.pop()?;
702            memory.push(word1 % word2);
703        }
704        Opcode::ModI32 => {
705            let word2: i32 = memory.pop()?;
706            let word1: i32 = memory.pop()?;
707            memory.push(word1 % word2);
708        }
709        Opcode::ModI64 => {
710            let word2: i64 = memory.pop()?;
711            let word1: i64 = memory.pop()?;
712            memory.push(word1 % word2);
713        }
714        Opcode::ModU64 => {
715            let word2: u64 = memory.pop()?;
716            let word1: u64 = memory.pop()?;
717            memory.push(word1 % word2);
718        }
719        Opcode::ModF32 => {
720            let word2: f32 = memory.pop()?;
721            let word1: f32 = memory.pop()?;
722            memory.push(word1 % word2);
723        }
724        Opcode::ModF64 => {
725            let word2: f64 = memory.pop()?;
726            let word1: f64 = memory.pop()?;
727            memory.push(word1 % word2);
728        }
729
730        Opcode::RShiftI8 => {
731            let word2: u8 = memory.pop()?;
732            let word1: i8 = memory.pop()?;
733            memory.push(word1.wrapping_shr(word2 as u32));
734        }
735        Opcode::RShiftU8 => {
736            let word2: u8 = memory.pop()?;
737            let word1: u8 = memory.pop()?;
738            memory.push(word1.wrapping_shr(word2 as u32));
739        }
740        Opcode::RShiftI16 => {
741            let word2: u8 = memory.pop()?;
742            let word1: i16 = memory.pop()?;
743            memory.push(word1.wrapping_shr(word2 as u32));
744        }
745        Opcode::RShiftU16 => {
746            let word2: u8 = memory.pop()?;
747            let word1: u16 = memory.pop()?;
748            memory.push(word1.wrapping_shr(word2 as u32));
749        }
750        Opcode::RShiftI32 => {
751            let word2: u8 = memory.pop()?;
752            let word1: i32 = memory.pop()?;
753            memory.push(word1.wrapping_shr(word2 as u32));
754        }
755        Opcode::RShiftU32 => {
756            let word2: u8 = memory.pop()?;
757            let word1: u32 = memory.pop()?;
758            memory.push(word1.wrapping_shr(word2 as u32));
759        }
760        Opcode::RShiftI64 => {
761            let word2: u8 = memory.pop()?;
762            let word1: i64 = memory.pop()?;
763            memory.push(word1.wrapping_shr(word2 as u32));
764        }
765        Opcode::RShiftU64 => {
766            let word2: u8 = memory.pop()?;
767            let word1: u64 = memory.pop()?;
768            memory.push(word1.wrapping_shr(word2 as u32));
769        }
770
771        Opcode::LShiftI8 => {
772            let word2: u8 = memory.pop()?;
773            let word1: i8 = memory.pop()?;
774            memory.push(word1.wrapping_shl(word2 as u32));
775        }
776        Opcode::LShiftU8 => {
777            let word2: u8 = memory.pop()?;
778            let word1: u8 = memory.pop()?;
779            memory.push(word1.wrapping_shl(word2 as u32));
780        }
781        Opcode::LShiftI16 => {
782            let word2: u8 = memory.pop()?;
783            let word1: i16 = memory.pop()?;
784            memory.push(word1.wrapping_shl(word2 as u32));
785        }
786        Opcode::LShiftU16 => {
787            let word2: u8 = memory.pop()?;
788            let word1: u16 = memory.pop()?;
789            memory.push(word1.wrapping_shl(word2 as u32));
790        }
791        Opcode::LShiftI32 => {
792            let word2: u8 = memory.pop()?;
793            let word1: i32 = memory.pop()?;
794            memory.push(word1.wrapping_shl(word2 as u32));
795        }
796        Opcode::LShiftU32 => {
797            let word2: u8 = memory.pop()?;
798            let word1: u32 = memory.pop()?;
799            memory.push(word1.wrapping_shl(word2 as u32));
800        }
801        Opcode::LShiftI64 => {
802            let word2: u8 = memory.pop()?;
803            let word1: i64 = memory.pop()?;
804            memory.push(word1.wrapping_shl(word2 as u32));
805        }
806        Opcode::LShiftU64 => {
807            let word2: u8 = memory.pop()?;
808            let word1: u64 = memory.pop()?;
809            memory.push(word1.wrapping_shl(word2 as u32));
810        }
811
812        Opcode::BitAnd8 => {
813            let word2: u8 = memory.pop()?;
814            let word1: u8 = memory.pop()?;
815            memory.push(word1 & word2);
816        }
817        Opcode::BitAnd16 => {
818            let word2: u16 = memory.pop()?;
819            let word1: u16 = memory.pop()?;
820            memory.push(word1 & word2);
821        }
822        Opcode::BitAnd32 => {
823            let word2: u32 = memory.pop()?;
824            let word1: u32 = memory.pop()?;
825            memory.push(word1 & word2);
826        }
827        Opcode::BitAnd64 => {
828            let word2: u64 = memory.pop()?;
829            let word1: u64 = memory.pop()?;
830            memory.push(word1 & word2);
831        }
832
833        Opcode::BitOr8 => {
834            let word2: u8 = memory.pop()?;
835            let word1: u8 = memory.pop()?;
836            memory.push(word1 | word2);
837        }
838        Opcode::BitOr16 => {
839            let word2: u16 = memory.pop()?;
840            let word1: u16 = memory.pop()?;
841            memory.push(word1 | word2);
842        }
843        Opcode::BitOr32 => {
844            let word2: u32 = memory.pop()?;
845            let word1: u32 = memory.pop()?;
846            memory.push(word1 | word2);
847        }
848        Opcode::BitOr64 => {
849            let word2: u64 = memory.pop()?;
850            let word1: u64 = memory.pop()?;
851            memory.push(word1 | word2);
852        }
853
854        Opcode::BitXor8 => {
855            let word2: u8 = memory.pop()?;
856            let word1: u8 = memory.pop()?;
857            memory.push(word1 ^ word2);
858        }
859        Opcode::BitXor16 => {
860            let word2: u16 = memory.pop()?;
861            let word1: u16 = memory.pop()?;
862            memory.push(word1 ^ word2);
863        }
864        Opcode::BitXor32 => {
865            let word2: u32 = memory.pop()?;
866            let word1: u32 = memory.pop()?;
867            memory.push(word1 ^ word2);
868        }
869        Opcode::BitXor64 => {
870            let word2: u64 = memory.pop()?;
871            let word1: u64 = memory.pop()?;
872            memory.push(word1 ^ word2);
873        }
874
875        Opcode::BitNot8 => {
876            let word: u8 = memory.pop()?;
877            memory.push(!word);
878        }
879        Opcode::BitNot16 => {
880            let word: u16 = memory.pop()?;
881            memory.push(!word);
882        }
883        Opcode::BitNot32 => {
884            let word: u32 = memory.pop()?;
885            memory.push(!word);
886        }
887        Opcode::BitNot64 => {
888            let word: u64 = memory.pop()?;
889            memory.push(!word);
890        }
891
892        Opcode::Jump => {
893            let target = memory.read_pc()?;
894            memory.jump(target);
895        }
896
897        Opcode::JumpIfZero8 => {
898            let target = memory.read_pc()?;
899            let value: u8 = memory.pop()?;
900            if value == 0 {
901                memory.jump(target);
902            }
903        }
904        Opcode::JumpIfZero16 => {
905            let target = memory.read_pc()?;
906            let value: u16 = memory.pop()?;
907            if value == 0 {
908                memory.jump(target);
909            }
910        }
911        Opcode::JumpIfZero32 => {
912            let target = memory.read_pc()?;
913            let value: u32 = memory.pop()?;
914            if value == 0 {
915                memory.jump(target);
916            }
917        }
918        Opcode::JumpIfZero64 => {
919            let target = memory.read_pc()?;
920            let value: u64 = memory.pop()?;
921            if value == 0 {
922                memory.jump(target);
923            }
924        }
925
926        Opcode::JumpIfNotZero8 => {
927            let target = memory.read_pc()?;
928            let value: u8 = memory.pop()?;
929            if value != 0 {
930                memory.jump(target);
931            }
932        }
933        Opcode::JumpIfNotZero16 => {
934            let target = memory.read_pc()?;
935            let value: u16 = memory.pop()?;
936            if value != 0 {
937                memory.jump(target);
938            }
939        }
940        Opcode::JumpIfNotZero32 => {
941            let target = memory.read_pc()?;
942            let value: u32 = memory.pop()?;
943            if value != 0 {
944                memory.jump(target);
945            }
946        }
947        Opcode::JumpIfNotZero64 => {
948            let target = memory.read_pc()?;
949            let value: u64 = memory.pop()?;
950            if value != 0 {
951                memory.jump(target);
952            }
953        }
954
955        Opcode::Ret => {
956            memory.ret()?;
957        }
958        Opcode::Call => {
959            let func: VarPointer = memory.pop()?;
960            memory.call(func)?;
961        }
962
963        Opcode::Throw => {
964            let skip_frames: u32 = memory.pop()?;
965            let message_ptr: VarPointer = memory.pop()?;
966            let name_ptr: VarPointer = memory.pop()?;
967
968            let message_bytes = memory.cstring_bytes(message_ptr)?;
969            let name_bytes = memory.cstring_bytes(name_ptr)?;
970
971            let mut message = String::new();
972            string_append_utf8_lossy(&mut message, message_bytes);
973            let mut name = String::new();
974            string_append_utf8_lossy(&mut name, name_bytes);
975
976            for _ in 0..skip_frames {
977                memory.ret()?;
978            }
979
980            return Err(IError::new(name, message));
981        }
982
983        Opcode::AllocBegin => {
984            let var_pointer: VarPointer = memory.pop()?;
985            if memory.read::<u8>(var_pointer).is_ok() {
986                memory.push(var_pointer.with_offset(0));
987            } else {
988                memory.push(0 as u64);
989            }
990        }
991        Opcode::AllocEnd => {
992            let var_pointer: VarPointer = memory.pop()?;
993            if let Some(ptr) = memory.upper_bound(var_pointer) {
994                memory.push(ptr);
995            } else {
996                memory.push(0 as u64);
997            }
998        }
999
1000        Opcode::CopySrcToDest => {
1001            let destination: VarPointer = memory.pop()?;
1002            let source: VarPointer = memory.pop()?;
1003            let length: u64 = memory.pop()?;
1004
1005            memory.push(destination);
1006        }
1007        Opcode::Memset => {
1008            let destination: VarPointer = memory.pop()?;
1009            let value: u8 = memory.pop()?;
1010            let length: u64 = memory.pop()?;
1011
1012            memory.push(destination);
1013        }
1014
1015        Opcode::HeapAlloc => {
1016            let skip: u32 = memory.pop()?;
1017            let size: u64 = memory.pop()?;
1018            let ptr = memory.add_heap_var(size as u32, skip)?;
1019            memory.push(ptr);
1020        }
1021        Opcode::HeapDealloc => {
1022            let skip: u32 = memory.pop()?;
1023            let ptr: VarPointer = memory.pop()?;
1024            memory.free(ptr, skip)?;
1025            memory.push(0u64);
1026        }
1027
1028        Opcode::Ecall => match memory.pop()? {
1029            Ecall::Exit => {
1030                let exit: i32 = memory.pop()?;
1031                return Ok(Some(EcallExt::Exit(exit)));
1032            }
1033
1034            Ecall::OpenFd => {
1035                let open_mode: OpenMode = memory.pop()?;
1036                let name: VarPointer = memory.pop()?;
1037                return Ok(Some(EcallExt::OpenFd { name, open_mode }));
1038            }
1039            Ecall::ReadFd => {
1040                let len: u32 = memory.pop()?;
1041                let buf: VarPointer = memory.pop()?;
1042                let begin: u32 = memory.pop()?;
1043                let fd: u32 = memory.pop()?;
1044
1045                #[rustfmt::skip]
1046                return Ok(Some(EcallExt::ReadFd { len, buf, begin, fd, }));
1047            }
1048            Ecall::WriteFd => {
1049                let len: u32 = memory.pop()?;
1050                let buf: VarPointer = memory.pop()?;
1051                let begin: u32 = memory.pop()?;
1052                let fd: u32 = memory.pop()?;
1053
1054                #[rustfmt::skip]
1055                return Ok(Some(EcallExt::WriteFd { buf, len, begin, fd }));
1056            }
1057            Ecall::AppendFd => {
1058                let len: u32 = memory.pop()?;
1059                let buf: VarPointer = memory.pop()?;
1060                let fd: u32 = memory.pop()?;
1061
1062                #[rustfmt::skip]
1063                return Ok(Some(EcallExt::AppendFd { buf, len, fd }));
1064            }
1065
1066            call => {
1067                return ierr!(
1068                    "InvalidEnviromentCall",
1069                    "invalid ecall value of {}",
1070                    call as u32
1071                )
1072            }
1073        },
1074
1075        Opcode::AssertStr => {
1076            let string = memory.pop()?;
1077            memory.cstring_bytes(string)?;
1078        }
1079    }
1080
1081    return Ok(None);
1082}