1mod breakpoints;
2mod debug;
3mod events;
4mod functions;
5mod memory;
6
7use std::{cell::RefCell, cmp, rc::Rc, sync::Arc};
8
9use memory::Memory;
10use miden_assembly::{ast::ProcedureName, LibraryNamespace};
11use midenc_hir::{assert_matches, Felt, FieldElement, FunctionIdent, Ident, OperandStack, Stack};
12use rustc_hash::{FxHashMap, FxHashSet};
13
14use self::functions::{Activation, Stub};
15pub use self::{
16 breakpoints::*,
17 debug::{CallFrame, DebugInfo, DebugInfoWithStack},
18 events::{BreakpointEvent, ControlEffect, EmulatorEvent},
19 functions::{Instruction, InstructionWithOp, NativeFn},
20};
21use crate::{BlockId, Function, Module, Op, Program};
22
23#[derive(Debug, Clone, thiserror::Error, PartialEq)]
27pub enum EmulationError {
28 #[error("unable to load module: '{0}' is already loaded")]
30 AlreadyLoaded(Ident),
31 #[error("unable to load function: '{0}' is already loaded")]
33 DuplicateFunction(FunctionIdent),
34 #[error("unable to invoke function: '{0}' is not defined")]
36 UndefinedFunction(FunctionIdent),
37 #[error("system limit: out of memory")]
39 OutOfMemory,
40 #[error("execution terminated prematurely: maximum cycle count reached")]
42 CycleBudgetExceeded,
43 #[error("execution suspended by breakpoint")]
45 BreakpointHit(BreakpointEvent),
46 #[error("unable to start the emulator without an entrypoint")]
48 NoEntrypoint,
49}
50
51pub type Addr = u32;
53
54#[derive(Debug, Copy, Clone, PartialEq, Eq)]
55pub struct InstructionPointer {
56 pub block: BlockId,
58 pub index: usize,
60}
61impl InstructionPointer {
62 pub const fn new(block: BlockId) -> Self {
63 Self { block, index: 0 }
64 }
65}
66
67#[derive(Debug, Default)]
80enum Status {
81 #[default]
86 Init,
87 Loaded,
93 Started,
95 Suspended,
97 Stopped,
100 Faulted(EmulationError),
102}
103
104pub struct Emulator {
118 status: Status,
119 functions: FxHashMap<FunctionIdent, Stub>,
120 locals: FxHashMap<FunctionIdent, Addr>,
121 modules_loaded: FxHashMap<Ident, Arc<Module>>,
122 modules_pending: FxHashSet<Ident>,
123 memory: Memory,
124 stack: OperandStack<Felt>,
125 advice_stack: OperandStack<Felt>,
126 callstack: Vec<Activation>,
127 hp_start: u32,
128 hp: u32,
129 lp_start: u32,
130 lp: u32,
131 breakpoints: BreakpointManager,
132 step_over: Option<InstructionPointer>,
133 clk: usize,
134 clk_limit: usize,
135 entrypoint: Option<FunctionIdent>,
136 print_trace: bool,
137}
138impl Default for Emulator {
139 fn default() -> Self {
140 Self::new(
141 Self::DEFAULT_HEAP_SIZE,
142 Self::DEFAULT_HEAP_START,
143 Self::DEFAULT_LOCALS_START,
144 false,
145 )
146 }
147}
148impl Emulator {
149 pub const DEFAULT_HEAP_SIZE: u32 = (4 * Self::PAGE_SIZE) / 16;
150 pub const DEFAULT_HEAP_START: u32 = (2 * Self::PAGE_SIZE) / 16;
151 pub const DEFAULT_LOCALS_START: u32 = (3 * Self::PAGE_SIZE) / 16;
152 const PAGE_SIZE: u32 = 64 * 1024;
153
154 pub fn new(memory_size: u32, hp: u32, lp: u32, print_stack: bool) -> Self {
160 let memory = Memory::new(memory_size as usize);
161 Self {
162 status: Status::Init,
163 functions: Default::default(),
164 locals: Default::default(),
165 modules_loaded: Default::default(),
166 modules_pending: Default::default(),
167 memory,
168 stack: Default::default(),
169 advice_stack: Default::default(),
170 callstack: vec![],
171 hp_start: hp,
172 hp,
173 lp_start: lp,
174 lp,
175 breakpoints: Default::default(),
176 step_over: None,
177 clk: 0,
178 clk_limit: usize::MAX,
179 entrypoint: None,
180 print_trace: print_stack,
181 }
182 }
183
184 pub fn set_max_cycles(&mut self, max: usize) {
186 self.clk_limit = max;
187 }
188
189 pub fn watchpoints(&self) -> impl Iterator<Item = Watchpoint> + '_ {
191 self.breakpoints.watchpoints()
192 }
193
194 pub fn breakpoints(&self) -> impl Iterator<Item = Breakpoint> {
196 self.breakpoints.breakpoints()
197 }
198
199 pub fn set_breakpoint(&mut self, bp: Breakpoint) {
201 self.breakpoints.set(bp);
202 }
203
204 pub fn clear_breakpoint(&mut self, bp: Breakpoint) {
206 self.breakpoints.unset(bp);
207 }
208
209 pub fn clear_breakpoints(&mut self) {
211 self.breakpoints.unset_all();
212 }
213
214 pub fn set_watchpoint(&mut self, addr: Addr, size: u32, mode: WatchMode) -> WatchpointId {
216 self.breakpoints.watch(addr, size, mode)
217 }
218
219 pub fn clear_watchpoint(&mut self, id: WatchpointId) {
221 self.breakpoints.unwatch(id);
222 }
223
224 pub fn watchpoint_mode(&mut self, id: WatchpointId, mode: WatchMode) {
226 self.breakpoints.watch_mode(id, mode);
227 }
228
229 pub fn clear_watchpoints(&mut self) {
231 self.breakpoints.unwatch_all();
232 }
233
234 pub fn clear_break_and_watchpoints(&mut self) {
236 self.breakpoints.clear();
237 }
238
239 pub fn info(&self) -> Option<DebugInfo<'_>> {
241 let current = self.callstack.last()?;
242 let ip = current.peek_with_op();
246 Some(DebugInfo {
247 cycle: self.clk,
248 function: current.function().name,
249 fp: current.fp(),
250 ip,
251 stack: &self.stack,
252 })
253 }
254
255 pub fn stacktrace(&self) -> Vec<CallFrame> {
257 let mut frames = Vec::with_capacity(self.callstack.len());
258 for frame in self.callstack.iter() {
259 frames.push(CallFrame {
260 function: frame.function().name,
261 fp: frame.fp(),
262 ip: Some(frame.ip()),
263 })
264 }
265 frames
266 }
267
268 pub fn current_ip(&self) -> Option<Instruction> {
270 self.callstack.last().and_then(|activation| activation.peek())
271 }
272
273 pub fn current_function(&self) -> Option<FunctionIdent> {
275 self.callstack.last().map(|activation| activation.function().name)
276 }
277
278 pub fn stack(&mut self) -> &OperandStack<Felt> {
280 &self.stack
281 }
282
283 pub fn stack_mut(&mut self) -> &mut OperandStack<Felt> {
285 &mut self.stack
286 }
287
288 pub fn load_program(&mut self, program: Arc<Program>) -> Result<(), EmulationError> {
292 if !matches!(self.status, Status::Init) {
294 self.reset();
295 }
296
297 let modules = program.unwrap_frozen_modules();
298 let mut cursor = modules.front();
299 while let Some(module) = cursor.clone_pointer() {
300 self.load_module(module)?;
301 cursor.move_next();
302 }
303 self.entrypoint = Some(program.entrypoint());
304
305 self.status = Status::Loaded;
308
309 Ok(())
310 }
311
312 pub fn load_module(&mut self, module: Arc<Module>) -> Result<(), EmulationError> {
316 use std::collections::hash_map::Entry;
317
318 assert_matches!(
319 self.status,
320 Status::Init | Status::Loaded,
321 "cannot load modules once execution has started without calling stop() or reset() \
322 first"
323 );
324
325 match self.modules_loaded.entry(module.id) {
326 Entry::Occupied(_) => return Err(EmulationError::AlreadyLoaded(module.id)),
327 Entry::Vacant(entry) => {
328 entry.insert(module.clone());
329 }
330 }
331
332 for import in module.imports.iter() {
334 let name = Ident::with_empty_span(import.name);
335 if self.modules_loaded.contains_key(&name) {
336 continue;
337 }
338 self.modules_pending.insert(name);
339 }
340 self.modules_pending.remove(&module.id);
341
342 let functions = module.unwrap_frozen_functions();
344 let mut cursor = functions.front();
345 while let Some(function) = cursor.clone_pointer() {
346 self.load_function(function)?;
347 cursor.move_next();
348 }
349
350 self.status = Status::Loaded;
351
352 Ok(())
353 }
354
355 pub fn reload_module(&mut self, module: Arc<Module>) -> Result<(), EmulationError> {
359 self.unload_module(module.id);
360 self.load_module(module)
361 }
362
363 pub fn unload_module(&mut self, name: Ident) {
367 assert_matches!(
368 self.status,
369 Status::Loaded,
370 "cannot unload modules once execution has started without calling stop() or reset() \
371 first"
372 );
373
374 let prev = self
375 .modules_loaded
376 .remove(&name)
377 .expect("cannot reload a module that was not previously loaded");
378
379 for f in prev.functions() {
381 self.functions.remove(&f.name);
382 self.locals.remove(&f.name);
383 }
384
385 for module in self.modules_loaded.values() {
388 if module.imports.is_import(&name) {
389 self.modules_pending.insert(name);
390 break;
391 }
392 }
393 }
394
395 fn load_function(&mut self, function: Arc<Function>) -> Result<(), EmulationError> {
397 let id = function.name;
398 if self.functions.contains_key(&id) {
399 return Err(EmulationError::DuplicateFunction(id));
400 }
401 let fp = self.lp;
402 self.lp += function.locals().len() as u32;
403 self.functions.insert(id, Stub::Asm(function));
404 self.locals.insert(id, fp);
405
406 Ok(())
407 }
408
409 pub fn load_nif(
415 &mut self,
416 id: FunctionIdent,
417 function: Box<NativeFn>,
418 ) -> Result<(), EmulationError> {
419 assert_matches!(
420 self.status,
421 Status::Init | Status::Loaded,
422 "cannot load nifs once execution has started without calling stop() or reset() first"
423 );
424
425 if self.functions.contains_key(&id) {
426 return Err(EmulationError::DuplicateFunction(id));
427 }
428 self.functions.insert(id, Stub::Native(Rc::new(RefCell::new(function))));
429
430 Ok(())
431 }
432
433 pub fn write_bytes_to_memory(&mut self, value: &[u8]) -> u32 {
439 let addr = self.hp;
440 if value.is_empty() {
441 return addr;
442 }
443
444 let mut elem_idx = 0;
445 for chunk in value.chunks(4) {
446 let elem = match chunk.len() {
447 4 => u32::from_le_bytes([chunk[0], chunk[1], chunk[2], chunk[3]]),
448 3 => u32::from_le_bytes([chunk[0], chunk[1], chunk[2], 0]),
449 2 => u32::from_le_bytes([chunk[0], chunk[1], 0, 0]),
450 1 => u32::from_le_bytes([chunk[0], 0, 0, 0]),
451 0 => 0,
452 _ => unreachable!(),
453 };
454 if elem_idx == 4 {
455 elem_idx = 0;
456 assert!(self.hp + 1 < self.lp, "heap has overflowed into reserved region");
457 self.hp += 1;
458 }
459 self.memory[self.hp as usize][elem_idx] = Felt::new(elem as u64);
460 elem_idx += 1;
461 }
462
463 addr
464 }
465
466 pub fn malloc(&mut self, size: usize) -> u32 {
470 let addr = self.hp;
471
472 if size == 0 {
473 return addr;
474 }
475
476 let size = size as u32;
477 let extra = size % 16;
478 let words = (size / 16) + (extra > 0) as u32;
479 assert!(self.hp + words < self.lp, "heap has overflowed into reserved region");
480 self.hp += words;
481
482 addr * 16
483 }
484
485 pub fn store(&mut self, addr: usize, value: Felt) {
487 use crate::NativePtr;
488
489 let ptr = NativePtr::from_ptr(addr.try_into().expect("invalid address"));
490 let addr = ptr.waddr as usize;
491 assert_eq!(ptr.offset, 0, "invalid store: unaligned address {addr:#?}");
492 assert!(addr < self.memory.len(), "invalid address");
493
494 self.memory[addr][ptr.index as usize] = value;
495 }
496
497 pub fn start(&mut self) -> Result<OperandStack<Felt>, EmulationError> {
507 match self.status {
508 Status::Init => return Err(EmulationError::NoEntrypoint),
509 Status::Loaded => (),
510 Status::Stopped => {
511 self.stop();
512 }
513 Status::Started | Status::Suspended => panic!(
514 "cannot start the emulator when it is already started without calling stop() or \
515 reset() first"
516 ),
517 Status::Faulted(ref err) => return Err(err.clone()),
518 }
519
520 let main_fn = self.entrypoint.unwrap_or_else(|| FunctionIdent {
521 module: LibraryNamespace::EXEC_PATH.into(),
522 function: ProcedureName::MAIN_PROC_NAME.into(),
523 });
524
525 let stack = self.invoke(main_fn, &[]).map_err(|err| match err {
527 EmulationError::UndefinedFunction(f) if f == main_fn => EmulationError::NoEntrypoint,
528 err => err,
529 })?;
530
531 self.stop();
533
534 Ok(stack)
536 }
537
538 pub fn init(&mut self) -> Result<EmulatorEvent, EmulationError> {
547 match self.status {
548 Status::Init => return Err(EmulationError::NoEntrypoint),
549 Status::Loaded => (),
550 Status::Stopped => {
551 self.stop();
552 }
553 Status::Started | Status::Suspended => panic!(
554 "cannot start the emulator when it is already started without calling stop() or \
555 reset() first"
556 ),
557 Status::Faulted(ref err) => return Err(err.clone()),
558 }
559
560 let main_fn = FunctionIdent {
561 module: LibraryNamespace::EXEC_PATH.into(),
562 function: ProcedureName::MAIN_PROC_NAME.into(),
563 };
564
565 self.enter(main_fn, &[]).map_err(|err| match err {
567 EmulationError::UndefinedFunction(f) if f == main_fn => EmulationError::NoEntrypoint,
568 err => err,
569 })
570 }
571
572 pub fn stop(&mut self) {
579 self.callstack.clear();
580 self.stack.clear();
581 self.memory.reset();
582 self.hp = self.hp_start;
583 self.lp = self.lp_start;
584 self.step_over = None;
585 self.clk = 0;
586 self.status = Status::Loaded;
587 }
588
589 pub fn reset(&mut self) {
597 self.stop();
598 self.functions.clear();
599 self.locals.clear();
600 self.modules_loaded.clear();
601 self.modules_pending.clear();
602 self.breakpoints.clear();
603 self.status = Status::Init;
604 }
605
606 pub fn invoke(
616 &mut self,
617 callee: FunctionIdent,
618 args: &[Felt],
619 ) -> Result<OperandStack<Felt>, EmulationError> {
620 assert_matches!(
621 self.status,
622 Status::Loaded,
623 "cannot start executing a function when the emulator is already started without \
624 calling stop() or reset() first"
625 );
626 let fun = self
627 .functions
628 .get(&callee)
629 .cloned()
630 .ok_or(EmulationError::UndefinedFunction(callee))?;
631 self.status = Status::Started;
632 match fun {
633 Stub::Asm(ref function) => match self.invoke_function(function.clone(), args) {
634 done @ Ok(_) => {
635 self.status = Status::Stopped;
636 done
637 }
638 Err(err @ EmulationError::BreakpointHit(_)) => {
639 self.status = Status::Suspended;
640 Err(err)
641 }
642 Err(err) => {
643 self.status = Status::Faulted(err.clone());
644 Err(err)
645 }
646 },
647 Stub::Native(function) => {
648 let mut function = function.borrow_mut();
649 function(self, args)?;
650 Ok(self.stack.clone())
651 }
652 }
653 }
654
655 #[inline]
659 fn invoke_function(
660 &mut self,
661 function: Arc<Function>,
662 args: &[Felt],
663 ) -> Result<OperandStack<Felt>, EmulationError> {
664 for arg in args.iter().copied().rev() {
667 self.stack.push(arg);
668 }
669
670 let name = function.name;
672 let fp = self.locals[&name];
673 let state = Activation::new(function, fp);
674 self.callstack.push(state);
675
676 match self
677 .breakpoints
678 .handle_event(EmulatorEvent::EnterFunction(name), self.current_ip())
679 {
680 Some(bp) => Err(EmulationError::BreakpointHit(bp)),
681 None => {
682 self.run()?;
683
684 Ok(self.stack.clone())
685 }
686 }
687 }
688
689 pub fn enter(
699 &mut self,
700 callee: FunctionIdent,
701 args: &[Felt],
702 ) -> Result<EmulatorEvent, EmulationError> {
703 assert_matches!(
704 self.status,
705 Status::Loaded,
706 "cannot start executing a function when the emulator is already started without \
707 calling stop() or reset() first"
708 );
709
710 let fun = self
711 .functions
712 .get(&callee)
713 .cloned()
714 .ok_or(EmulationError::UndefinedFunction(callee))?;
715 self.status = Status::Started;
716 match fun {
717 Stub::Asm(ref function) => self.enter_function(function.clone(), args),
718 Stub::Native(function) => {
719 let mut function = function.borrow_mut();
720 function(self, args)?;
721 Ok(EmulatorEvent::ExitFunction(callee))
722 }
723 }
724 }
725
726 #[inline]
730 fn enter_function(
731 &mut self,
732 function: Arc<Function>,
733 args: &[Felt],
734 ) -> Result<EmulatorEvent, EmulationError> {
735 for arg in args.iter().copied().rev() {
738 self.stack.push(arg);
739 }
740
741 let name = function.name;
743 let fp = self.locals[&name];
744 let state = Activation::new(function, fp);
745 self.callstack.push(state);
746
747 self.status = Status::Suspended;
748
749 Ok(EmulatorEvent::Suspended)
750 }
751
752 #[inline]
754 pub fn resume(&mut self) -> Result<EmulatorEvent, EmulationError> {
755 assert_matches!(
756 self.status,
757 Status::Suspended,
758 "cannot resume the emulator from any state other than suspended"
759 );
760 self.run()
761 }
762}
763
764macro_rules! adv_pop {
766 ($emu:ident) => {
767 $emu.advice_stack.pop().expect("advice stack is empty")
768 };
769
770 ($emu:ident, $msg:literal) => {
771 $emu.advice_stack.pop().expect($msg)
772 };
773
774 ($emu:ident, $msg:literal, $($arg:expr),+) => {
775 match $emu.advice_stack.pop() {
776 Some(value) => value,
777 None => panic!($msg, $($arg),*),
778 }
779 }
780}
781
782macro_rules! adv_popw {
784 ($emu:ident) => {
785 $emu.advice_stack.popw().expect("advice stack does not contain a full word")
786 };
787
788 ($emu:ident, $msg:literal) => {
789 $emu.advice_stack.popw().expect($msg)
790 };
791
792 ($emu:ident, $msg:literal, $($arg:expr),+) => {{
793 match $emu.advice_stack.popw() {
794 Some(value) => value,
795 None => panic!($msg, $($arg),*),
796 }
797 }}
798}
799
800macro_rules! pop {
802 ($emu:ident) => {
803 $emu.stack.pop().expect("operand stack is empty")
804 };
805
806 ($emu:ident, $msg:literal) => {
807 $emu.stack.pop().expect($msg)
808 };
809
810 ($emu:ident, $msg:literal, $($arg:expr),+) => {
811 match $emu.stack.pop() {
812 Some(value) => value,
813 None => panic!($msg, $($arg),*),
814 }
815 }
816}
817
818macro_rules! peek {
820 ($emu:ident) => {
821 $emu.stack.peek().expect("operand stack is empty")
822 };
823
824 ($emu:ident, $msg:literal) => {
825 $emu.stack.peek().expect($msg)
826 };
827
828 ($emu:ident, $msg:literal, $($arg:expr),+) => {
829 match $emu.stack.peek() {
830 Some(value) => value,
831 None => panic!($msg, $($arg),*),
832 }
833 }
834}
835
836macro_rules! popw {
838 ($emu:ident) => {
839 $emu.stack.popw().expect("operand stack does not contain a full word")
840 };
841
842 ($emu:ident, $msg:literal) => {
843 $emu.stack.popw().expect($msg)
844 };
845
846 ($emu:ident, $msg:literal, $($arg:expr),+) => {{
847 match $emu.stack.popw() {
848 Some(value) => value,
849 None => panic!($msg, $($arg),*),
850 }
851 }}
852}
853
854macro_rules! pop2 {
856 ($emu:ident) => {{
857 let b = pop!($emu);
858 let a = pop!($emu);
859 (b, a)
860 }};
861}
862
863macro_rules! pop_u32 {
865 ($emu:ident) => {{
866 let value = pop!($emu).as_int();
867 assert!(value < 2u64.pow(32), "assertion failed: {value} is not a valid u32, value is out of range");
868 value as u32
869 }};
870
871 ($emu:ident, $format:literal $(, $args:expr)*) => {{
872 let value = pop!($emu).as_int();
873 assert!(value < 2u64.pow(32), $format, value, $($args),*);
874 value as u32
875 }}
876}
877
878#[allow(unused)]
880macro_rules! peek_u32 {
881 ($emu:ident) => {{
882 let value = peek!($emu).as_int();
883 assert!(value < 2u64.pow(32), "assertion failed: {value} is not a valid u32, value is out of range");
884 value as u32
885 }};
886
887 ($emu:ident, $format:literal $(, $args:expr)*) => {{
888 let value = peek!($emu).as_int();
889 assert!(value < 2u64.pow(32), $format, value, $($args),*);
890 value as u32
891 }}
892}
893
894macro_rules! pop_addr {
896 ($emu:ident) => {{
897 let addr = pop_u32!($emu, "expected valid 32-bit address, got {}") as usize;
898 assert!(
899 addr < $emu.memory.len(),
900 "out of bounds memory access, addr: {}, available memory: {}",
901 addr,
902 $emu.memory.len()
903 );
904 addr
905 }};
906}
907
908macro_rules! pop_bool {
910 ($emu:ident) => {{
911 let value = pop!($emu).as_int();
912 assert!(
913 value < 2,
914 "assertion failed: {value} is not a valid boolean, value must be either 1 or 0"
915 );
916 value == 1
917 }};
918}
919
920macro_rules! binop {
925 ($emu:ident, $op:ident) => {{
926 use core::ops::*;
927 let b = pop!($emu);
928 let a = pop!($emu);
929 $emu.stack.push(a.$op(b));
930 }};
931
932 ($emu:ident, $op:ident, $imm:expr) => {{
933 use core::ops::*;
934 let a = pop!($emu);
935 $emu.stack.push(a.$op($imm));
936 }};
937}
938
939macro_rules! binop32 {
944 ($emu:ident, $op:ident) => {{
945 #[allow(unused)]
946 use core::ops::*;
947 let b = pop_u32!($emu);
948 let a = pop_u32!($emu);
949 $emu.stack.push_u32(a.$op(b));
950 }};
951
952 ($emu:ident, $op:ident, $imm:expr) => {{
953 #[allow(unused)]
954 use core::ops::*;
955 let a = pop_u32!($emu);
956 $emu.stack.push_u32(a.$op($imm));
957 }};
958}
959
960macro_rules! binop_unchecked_u32 {
965 ($emu:ident, $op:ident) => {{
966 #[allow(unused)]
967 use core::ops::*;
968 let b = pop!($emu);
969 let a = pop!($emu);
970 $emu.stack.push(Felt::new(a.as_int().$op(b.as_int())));
971 }};
972
973 ($emu:ident, $op:ident, $imm:expr) => {{
974 #[allow(unused)]
975 use core::ops::*;
976 let a = pop!($emu);
977 $emu.stack.push(Felt::new(a.as_int().$op($imm)));
978 }};
979}
980
981macro_rules! binop_overflowing_u32 {
986 ($emu:ident, $op:ident) => {{
987 paste::paste! {
988 binop_overflowing_u32_impl!($emu, [<overflowing_ $op>]);
989 }
990 }};
991
992 ($emu:ident, $op:ident, $imm:expr) => {{
993 paste::paste! {
994 binop_overflowing_u32_impl!($emu, [<overflowing_ $op>], $imm);
995 }
996 }};
997}
998
999#[doc(hidden)]
1000macro_rules! binop_overflowing_u32_impl {
1001 ($emu:ident, $op:ident) => {{
1002 #[allow(unused)]
1003 use core::ops::*;
1004 let b = pop_u32!($emu);
1005 let a = pop_u32!($emu);
1006 let (result, overflowed) = a.$op(b);
1007 $emu.stack.push_u32(result);
1008 $emu.stack.push_u8(overflowed as u8);
1009 }};
1010
1011 ($emu:ident, $op:ident, $imm:expr) => {{
1012 #[allow(unused)]
1013 use core::ops::*;
1014 let a = pop_u32!($emu);
1015 let (result, overflowed) = a.$op($imm);
1016 $emu.stack.push_u32(result);
1017 $emu.stack.push_u8(overflowed as u8);
1018 }};
1019}
1020
1021macro_rules! binop_wrapping_u32 {
1026 ($emu:ident, $op:ident) => {{
1027 paste::paste! {
1028 binop_wrapping_u32_impl!($emu, [<wrapping_ $op>]);
1029 }
1030 }};
1031
1032 ($emu:ident, $op:ident, $imm:expr) => {{
1033 paste::paste! {
1034 binop_wrapping_u32_impl!($emu, [<wrapping_ $op>], $imm);
1035 }
1036 }};
1037}
1038
1039#[doc(hidden)]
1040macro_rules! binop_wrapping_u32_impl {
1041 ($emu:ident, $op:ident) => {{
1042 #[allow(unused)]
1043 use core::ops::*;
1044 let b = pop_u32!($emu);
1045 let a = pop_u32!($emu);
1046 $emu.stack.push_u32(a.$op(b));
1047 }};
1048
1049 ($emu:ident, $op:ident, $imm:expr) => {{
1050 #[allow(unused)]
1051 use core::ops::*;
1052 let a = pop_u32!($emu);
1053 $emu.stack.push_u32(a.$op($imm));
1054 }};
1055}
1056
1057macro_rules! comparison {
1062 ($emu:ident, $op:ident) => {{
1063 let b = pop!($emu).as_int();
1064 let a = pop!($emu).as_int();
1065 let result: bool = a.$op(&b);
1066 $emu.stack.push_u8(result as u8);
1067 }};
1068
1069 ($emu:ident, $op:ident, $imm:expr) => {{
1070 let a = pop!($emu).as_int();
1071 let result: bool = a.$op(&$imm);
1072 $emu.stack.push_u8(result as u8);
1073 }};
1074}
1075
1076impl Emulator {
1077 pub fn step(&mut self) -> Result<EmulatorEvent, EmulationError> {
1080 match self
1081 .breakpoints
1082 .handle_event(EmulatorEvent::CycleStart(self.clk), self.current_ip())
1083 {
1084 Some(bp) => {
1085 self.status = Status::Suspended;
1086 Ok(EmulatorEvent::Breakpoint(bp))
1087 }
1088 None => match self.run_once() {
1089 Ok(EmulatorEvent::Stopped) => {
1090 self.status = Status::Stopped;
1091 Ok(EmulatorEvent::Stopped)
1092 }
1093 suspended @ Ok(_) => {
1094 self.status = Status::Suspended;
1095 suspended
1096 }
1097 Err(err) => {
1098 self.status = Status::Faulted(err.clone());
1099 Err(err)
1100 }
1101 },
1102 }
1103 }
1104
1105 pub fn step_over(&mut self) -> Result<EmulatorEvent, EmulationError> {
1108 match self.step_over.take() {
1109 None => self.step(),
1110 Some(ip) => {
1111 self.breakpoints.set(Breakpoint::At(ip));
1112 match self.run() {
1113 Ok(EmulatorEvent::Stopped) => {
1114 self.status = Status::Stopped;
1115 Ok(EmulatorEvent::Stopped)
1116 }
1117 Ok(EmulatorEvent::Breakpoint(bp)) | Err(EmulationError::BreakpointHit(bp)) => {
1118 self.status = Status::Suspended;
1119 if self.current_ip().map(|ix| ix.ip) == Some(ip) {
1120 return Ok(EmulatorEvent::Suspended);
1121 }
1122 Ok(EmulatorEvent::Breakpoint(bp))
1123 }
1124 Ok(event) => panic!(
1125 "unexpected event produced by emulator loop when stepping over: {event:?}"
1126 ),
1127 Err(err) => {
1128 self.status = Status::Faulted(err.clone());
1129 Err(err)
1130 }
1131 }
1132 }
1133 }
1134 }
1135
1136 pub fn step_out(&mut self) -> Result<EmulatorEvent, EmulationError> {
1138 let current_function = self.current_function();
1139 self.breakpoints.break_on_return(true);
1140 match self.run() {
1141 Ok(EmulatorEvent::Stopped) => {
1142 self.status = Status::Stopped;
1143 Ok(EmulatorEvent::Stopped)
1144 }
1145 Ok(EmulatorEvent::Breakpoint(bp)) | Err(EmulationError::BreakpointHit(bp)) => {
1146 self.status = Status::Suspended;
1147 if self.current_function() == current_function {
1148 return Ok(EmulatorEvent::Suspended);
1149 }
1150 Ok(EmulatorEvent::Breakpoint(bp))
1151 }
1152 Ok(event) => {
1153 panic!("unexpected event produced by emulator loop when stepping over: {event:?}")
1154 }
1155 Err(err) => {
1156 self.status = Status::Faulted(err.clone());
1157 Err(err)
1158 }
1159 }
1160 }
1161
1162 #[inline(never)]
1169 fn run(&mut self) -> Result<EmulatorEvent, EmulationError> {
1170 let mut event = self.step()?;
1181 loop {
1182 match event {
1183 event @ EmulatorEvent::Breakpoint(_) => break Ok(event),
1185 event @ EmulatorEvent::Stopped => break Ok(event),
1186 ev => {
1187 match self.breakpoints.handle_event(ev, self.current_ip()) {
1189 Some(bp) => break Ok(EmulatorEvent::Breakpoint(bp)),
1190 None => match ev {
1191 EmulatorEvent::ExitFunction(_) => {
1196 if self.callstack.is_empty() {
1197 break Ok(EmulatorEvent::Stopped);
1198 }
1199 event = self.run_once()?;
1200 continue;
1201 }
1202 _ => {
1203 event = self.step()?;
1204 }
1205 },
1206 }
1207 }
1208 }
1209 }
1210 }
1211
1212 #[inline(never)]
1213 fn run_once(&mut self) -> Result<EmulatorEvent, EmulationError> {
1214 const U32_P: u64 = 2u64.pow(32);
1215
1216 if self.callstack.is_empty() {
1218 return Ok(EmulatorEvent::Stopped);
1219 }
1220
1221 self.clk += 1;
1223 if self.clk > self.clk_limit {
1224 return Err(EmulationError::CycleBudgetExceeded);
1225 }
1226
1227 let mut state = self.callstack.pop().unwrap();
1228 let current_function = state.function().name;
1229
1230 self.step_over = None;
1232
1233 if self.breakpoints.break_on_return || self.breakpoints.has_break_on_reached() {
1236 match state.peek() {
1237 Some(Instruction { ip, .. })
1238 if self.breakpoints.should_break_at(ip.block, ip.index) =>
1239 {
1240 self.callstack.push(state);
1241 return Ok(EmulatorEvent::Breakpoint(BreakpointEvent::Reached(ip)));
1242 }
1243 None if self.breakpoints.break_on_return => {
1244 self.callstack.push(state);
1245 self.breakpoints.break_on_return(false);
1246 return Ok(EmulatorEvent::Breakpoint(BreakpointEvent::StepOut));
1247 }
1248 _ => (),
1249 }
1250 }
1251
1252 let ix_with_op = state.next();
1256 if let Some(ix_with_op) = ix_with_op {
1257 if self.print_trace {
1258 eprintln!("mem: {:?}", self.memory);
1259 eprintln!("stk: {}", self.stack.debug());
1260 eprintln!("op>: {:?}", ix_with_op.op);
1261 }
1262 match ix_with_op.op {
1263 Op::Padw => {
1264 self.stack.padw();
1265 }
1266 Op::Push(v) => {
1267 self.stack.push(v);
1268 }
1269 Op::Push2([a, b]) => {
1270 self.stack.push(a);
1271 self.stack.push(b);
1272 }
1273 Op::Pushw(word) => {
1274 self.stack.pushw(word);
1275 }
1276 Op::PushU8(i) => {
1277 self.stack.push_u8(i);
1278 }
1279 Op::PushU16(i) => {
1280 self.stack.push_u16(i);
1281 }
1282 Op::PushU32(i) => {
1283 self.stack.push_u32(i);
1284 }
1285 Op::Drop => {
1286 self.stack.drop();
1287 }
1288 Op::Dropw => {
1289 self.stack.dropw();
1290 }
1291 Op::Dup(pos) => {
1292 self.stack.dup(pos as usize);
1293 }
1294 Op::Dupw(pos) => {
1295 self.stack.dupw(pos as usize);
1296 }
1297 Op::Swap(pos) => {
1298 self.stack.swap(pos as usize);
1299 }
1300 Op::Swapw(pos) => {
1301 self.stack.swapw(pos as usize);
1302 }
1303 Op::Swapdw => {
1304 self.stack.swapdw();
1305 }
1306 Op::Movup(pos) => {
1307 self.stack.movup(pos as usize);
1308 }
1309 Op::Movupw(pos) => {
1310 self.stack.movupw(pos as usize);
1311 }
1312 Op::Movdn(pos) => {
1313 self.stack.movdn(pos as usize);
1314 }
1315 Op::Movdnw(pos) => {
1316 self.stack.movdnw(pos as usize);
1317 }
1318 Op::Cswap => {
1319 let cond = pop_bool!(self);
1320 if cond {
1321 self.stack.swap(1);
1322 }
1323 }
1324 Op::Cswapw => {
1325 let cond = pop_bool!(self);
1326 if cond {
1327 self.stack.swapw(1);
1328 }
1329 }
1330 Op::Cdrop => {
1331 let cond = pop_bool!(self);
1332 let (b, a) = pop2!(self);
1333 if cond {
1334 self.stack.push(b);
1335 } else {
1336 self.stack.push(a);
1337 }
1338 }
1339 Op::Cdropw => {
1340 let cond = pop_bool!(self);
1341 let b = popw!(self);
1342 let a = popw!(self);
1343 if cond {
1344 self.stack.pushw(b);
1345 } else {
1346 self.stack.pushw(a);
1347 }
1348 }
1349 Op::AdvPush(n) => {
1350 assert!(
1351 n > 0 && n <= 16,
1352 "invalid adv_push operand: must be a value in the range 1..=16, got {n}"
1353 );
1354 for _ in 0..n {
1355 let value = adv_pop!(self);
1356 self.stack.push(value);
1357 }
1358 }
1359 Op::AdvLoadw => {
1360 let word = adv_popw!(self);
1361 self.stack.dropw();
1362 self.stack.pushw(word);
1363 }
1364 Op::AdvPipe => {
1365 self.stack.dropw();
1367 self.stack.dropw();
1368 let a = popw!(self);
1370 let addr = pop_addr!(self);
1372 self.stack.push_u32(addr as u32 + 2);
1374 self.stack.pushw(a);
1375 let d = adv_popw!(self);
1378 self.stack.pushw(d);
1379 self.memory[addr] = d;
1380 let e = adv_popw!(self);
1381 self.stack.pushw(e);
1382 self.memory[addr + 1] = e;
1383 self.callstack.push(state);
1386 return Ok(EmulatorEvent::MemoryWrite {
1387 addr: addr as u32,
1388 size: 16,
1389 });
1390 }
1391 Op::AdvInjectPushU64Div => {
1392 const HI_MASK: u64 = u64::MAX << 32;
1393 const LO_MASK: u64 = u32::MAX as u64;
1394 let b_hi = pop_u32!(self) as u64;
1395 let b_lo = pop_u32!(self) as u64;
1396 let b = (b_hi << 32) | b_lo;
1397 assert!(b > 0, "assertion failed: division by zero");
1398 let a_hi = pop_u32!(self) as u64;
1399 let a_lo = pop_u32!(self) as u64;
1400 let a = (a_hi << 32) | a_lo;
1401 let q = a / b;
1402 let q_hi = (q & HI_MASK) >> 32;
1403 let q_lo = q & LO_MASK;
1404 let r = a % b;
1405 let r_hi = (r & HI_MASK) >> 32;
1406 let r_lo = r & LO_MASK;
1407 self.advice_stack.push_u32(r_hi as u32);
1408 self.advice_stack.push_u32(r_lo as u32);
1409 self.advice_stack.push_u32(q_hi as u32);
1410 self.advice_stack.push_u32(q_lo as u32);
1411 self.stack.push_u32(a_lo as u32);
1412 self.stack.push_u32(a_hi as u32);
1413 self.stack.push_u32(b_lo as u32);
1414 self.stack.push_u32(b_hi as u32);
1415 }
1416 Op::AdvInjectInsertMem
1417 | Op::AdvInjectInsertHperm
1418 | Op::AdvInjectInsertHdword
1419 | Op::AdvInjectInsertHdwordImm(_)
1420 | Op::AdvInjectPushMTreeNode
1421 | Op::AdvInjectPushMapVal
1422 | Op::AdvInjectPushMapValImm(_)
1423 | Op::AdvInjectPushMapValN
1424 | Op::AdvInjectPushMapValNImm(_) => unimplemented!(),
1425 Op::Assert => {
1426 let cond = pop_bool!(self);
1427 assert!(cond, "assertion failed: expected true, got false");
1428 }
1429 Op::Assertz => {
1430 let cond = pop_bool!(self);
1431 assert!(!cond, "assertion failed: expected false, got true");
1432 }
1433 Op::AssertEq => {
1434 let (b, a) = pop2!(self);
1435 assert_eq!(a, b, "equality assertion failed");
1436 }
1437 Op::AssertEqw => {
1438 let b = popw!(self);
1439 let a = popw!(self);
1440 assert_eq!(a, b, "equality assertion failed");
1441 }
1442 Op::LocAddr(id) => {
1443 let addr = state.fp() + id.as_usize() as u32;
1444 debug_assert!(addr < self.memory.len() as u32);
1445 self.stack.push_u32(addr * 16);
1446 }
1447 Op::LocStore(id) => {
1448 let addr = (state.fp() + id.as_usize() as u32) as usize;
1449 debug_assert!(addr < self.memory.len());
1450 let value = pop!(self);
1451 self.memory[addr][0] = value;
1452 return Ok(EmulatorEvent::MemoryWrite {
1453 addr: addr as u32,
1454 size: 4,
1455 });
1456 }
1457 Op::LocStorew(id) => {
1458 let addr = (state.fp() + id.as_usize() as u32) as usize;
1459 assert!(addr < self.memory.len() - 4, "out of bounds memory access");
1460 let word =
1461 self.stack.peekw().expect("operand stack does not contain a full word");
1462 self.memory[addr] = word;
1463 return Ok(EmulatorEvent::MemoryWrite {
1464 addr: addr as u32,
1465 size: 16,
1466 });
1467 }
1468 Op::LocLoad(id) => {
1469 let addr = (state.fp() + id.as_usize() as u32) as usize;
1470 debug_assert!(addr < self.memory.len());
1471 self.stack.push(self.memory[addr][0]);
1472 }
1473 Op::LocLoadw(id) => {
1474 let addr = (state.fp() + id.as_usize() as u32) as usize;
1475 debug_assert!(addr < self.memory.len());
1476 self.stack.dropw();
1477 self.stack.pushw(self.memory[addr]);
1478 }
1479 Op::MemLoad => {
1480 let addr = pop_addr!(self);
1481 self.stack.push(self.memory[addr][0]);
1482 }
1483 Op::MemLoadImm(addr) => {
1484 let addr = addr as usize;
1485 assert!(addr < self.memory.len(), "out of bounds memory access");
1486 self.stack.push(self.memory[addr][0]);
1487 }
1488 Op::MemLoadw => {
1489 let addr = pop_addr!(self);
1490 self.stack.dropw();
1491 let mut word = self.memory[addr];
1492 word.reverse();
1493 self.stack.pushw(word);
1494 }
1495 Op::MemLoadwImm(addr) => {
1496 let addr = addr as usize;
1497 assert!(addr < self.memory.len() - 4, "out of bounds memory access");
1498 self.stack.dropw();
1499 let mut word = self.memory[addr];
1500 word.reverse();
1501 self.stack.pushw(word);
1502 }
1503 Op::MemStore => {
1504 let addr = pop_addr!(self);
1505 let value = pop!(self);
1506 self.memory[addr][0] = value;
1507 self.callstack.push(state);
1508 return Ok(EmulatorEvent::MemoryWrite {
1509 addr: addr as u32,
1510 size: 4,
1511 });
1512 }
1513 Op::MemStoreImm(addr) => {
1514 let addr = addr as usize;
1515 assert!(addr < self.memory.len(), "out of bounds memory access");
1516 let value = self.stack.pop().expect("operand stack is empty");
1517 self.memory[addr][0] = value;
1518 self.callstack.push(state);
1519 return Ok(EmulatorEvent::MemoryWrite {
1520 addr: addr as u32,
1521 size: 4,
1522 });
1523 }
1524 Op::MemStorew => {
1525 let addr = pop_addr!(self);
1526 let mut word =
1527 self.stack.peekw().expect("operand stack does not contain a full word");
1528 word.reverse();
1529 self.memory[addr] = word;
1530 self.callstack.push(state);
1531 return Ok(EmulatorEvent::MemoryWrite {
1532 addr: addr as u32,
1533 size: 16,
1534 });
1535 }
1536 Op::MemStorewImm(addr) => {
1537 let addr = addr as usize;
1538 assert!(addr < self.memory.len() - 4, "out of bounds memory access");
1539 let mut word =
1540 self.stack.peekw().expect("operand stack does not contain a full word");
1541 word.reverse();
1542 self.memory[addr] = word;
1543 self.callstack.push(state);
1544 return Ok(EmulatorEvent::MemoryWrite {
1545 addr: addr as u32,
1546 size: 16,
1547 });
1548 }
1549 Op::If(then_blk, else_blk) => {
1550 self.step_over = Some(state.ip());
1551 let cond = pop_bool!(self);
1552 let dest = if cond {
1553 state.enter_block(then_blk);
1554 then_blk
1555 } else {
1556 state.enter_block(else_blk);
1557 else_blk
1558 };
1559 self.callstack.push(state);
1560 return Ok(EmulatorEvent::Jump(dest));
1561 }
1562 Op::While(body_blk) => {
1563 self.step_over = Some(state.ip());
1564 let cond = pop_bool!(self);
1565 if cond {
1566 state.enter_while_loop(body_blk);
1567 self.callstack.push(state);
1568 return Ok(EmulatorEvent::EnterLoop(body_blk));
1569 }
1570 }
1571 Op::Repeat(n, body_blk) => {
1572 self.step_over = Some(state.ip());
1573 state.repeat_block(body_blk, n);
1574 self.callstack.push(state);
1575 return Ok(EmulatorEvent::EnterLoop(body_blk));
1576 }
1577 Op::Exec(callee) => {
1578 let fun = self
1579 .functions
1580 .get(&callee)
1581 .cloned()
1582 .ok_or(EmulationError::UndefinedFunction(callee))?;
1583 self.step_over = Some(state.ip());
1584 match fun {
1585 Stub::Asm(ref function) => {
1586 let fp = self.locals[&function.name];
1587 let callee_state = Activation::new(function.clone(), fp);
1588 self.callstack.push(state);
1590 self.callstack.push(callee_state);
1591 return Ok(EmulatorEvent::EnterFunction(function.name));
1592 }
1593 Stub::Native(_function) => unimplemented!(),
1594 }
1595 }
1596 Op::Call(_callee) | Op::Syscall(_callee) => unimplemented!(),
1597 Op::Add => binop!(self, add),
1598 Op::AddImm(imm) => binop!(self, add, imm),
1599 Op::Sub => binop!(self, sub),
1600 Op::SubImm(imm) => binop!(self, sub, imm),
1601 Op::Mul => binop!(self, mul),
1602 Op::MulImm(imm) => binop!(self, mul, imm),
1603 Op::Div => binop!(self, div),
1604 Op::DivImm(imm) => binop!(self, div, imm),
1605 Op::Neg => {
1606 let a = self.stack.pop().expect("operand stack is empty");
1607 self.stack.push(-a);
1608 }
1609 Op::Inv => {
1610 let a = self.stack.pop().expect("operand stack is empty");
1611 self.stack.push(a.inv());
1612 }
1613 Op::Incr => binop!(self, add, Felt::ONE),
1614 Op::Ilog2 => {
1615 let a = peek!(self).as_int();
1616 assert!(a > 0, "invalid ilog2 argument: expected {a} to be > 0");
1617 self.advice_stack.push_u32(a.ilog2());
1618 }
1619 Op::Pow2 => {
1620 let a = pop!(self).as_int();
1621 assert!(
1622 a < 64,
1623 "invalid power of two: expected {a} to be a value less than 64"
1624 );
1625 let two = Felt::new(2);
1626 self.stack.push(two.exp(a));
1627 }
1628 Op::Exp => {
1629 let (b, a) = pop2!(self);
1630 let b = b.as_int();
1631 assert!(
1632 b < 64,
1633 "invalid power of two: expected {b} to be a value less than 64"
1634 );
1635 self.stack.push(a.exp(b));
1636 }
1637 Op::ExpImm(pow) | Op::ExpBitLength(pow) => {
1638 let pow = pow as u64;
1639 let a = pop!(self);
1640 assert!(
1641 pow < 64,
1642 "invalid power of two: expected {pow} to be a value less than 64"
1643 );
1644 self.stack.push(a.exp(pow));
1645 }
1646 Op::Not => {
1647 let a = pop_bool!(self);
1648 self.stack.push_u8(!a as u8);
1649 }
1650 Op::And => {
1651 let b = pop_bool!(self);
1652 let a = pop_bool!(self);
1653 self.stack.push_u8((b & a) as u8);
1654 }
1655 Op::AndImm(b) => {
1656 let a = pop_bool!(self);
1657 self.stack.push_u8((a & b) as u8);
1658 }
1659 Op::Or => {
1660 let b = pop_bool!(self);
1661 let a = pop_bool!(self);
1662 self.stack.push_u8((b | a) as u8);
1663 }
1664 Op::OrImm(b) => {
1665 let a = pop_bool!(self);
1666 self.stack.push_u8((a | b) as u8);
1667 }
1668 Op::Xor => {
1669 let b = pop_bool!(self);
1670 let a = pop_bool!(self);
1671 self.stack.push_u8((b ^ a) as u8);
1672 }
1673 Op::XorImm(b) => {
1674 let a = pop_bool!(self);
1675 self.stack.push_u8((a ^ b) as u8);
1676 }
1677 Op::Eq => comparison!(self, eq),
1678 Op::EqImm(imm) => comparison!(self, eq, imm.as_int()),
1679 Op::Neq => comparison!(self, ne),
1680 Op::NeqImm(imm) => comparison!(self, ne, imm.as_int()),
1681 Op::Gt => comparison!(self, gt),
1682 Op::GtImm(imm) => comparison!(self, gt, imm.as_int()),
1683 Op::Gte => comparison!(self, ge),
1684 Op::GteImm(imm) => comparison!(self, ge, imm.as_int()),
1685 Op::Lt => comparison!(self, lt),
1686 Op::LtImm(imm) => comparison!(self, lt, imm.as_int()),
1687 Op::Lte => comparison!(self, le),
1688 Op::LteImm(imm) => comparison!(self, le, imm.as_int()),
1689 Op::IsOdd => {
1690 let a = pop!(self).as_int();
1691 self.stack.push_u8((a % 2 == 0) as u8);
1692 }
1693 Op::Eqw => {
1694 let b = popw!(self);
1695 let a = popw!(self);
1696 self.stack.push_u8((a == b) as u8);
1697 }
1698 Op::Clk => {
1699 self.stack.push(Felt::new(self.clk as u64));
1700 }
1701 Op::Sdepth => {
1702 self.stack.push(Felt::new(self.stack.len() as u64));
1703 }
1704 Op::U32Test => {
1705 let top = self.stack.peek().expect("operand stack is empty").as_int();
1706 self.stack.push_u8((top < U32_P) as u8);
1707 }
1708 Op::U32Testw => {
1709 let word = self.stack.peekw().expect("operand stack is empty");
1710 let is_true = word.iter().all(|elem| elem.as_int() < U32_P);
1711 self.stack.push_u8(is_true as u8);
1712 }
1713 Op::U32Assert => {
1714 let top = self.stack.peek().expect("operand stack is empty").as_int();
1715 assert!(top < U32_P, "assertion failed: {top} is larger than 2^32");
1716 }
1717 Op::U32Assert2 => {
1718 let a = self.stack.peek().expect("operand stack is empty").as_int();
1719 let b = self.stack.peek().expect("operand stack is empty").as_int();
1720 assert!(a < U32_P, "assertion failed: {a} is larger than 2^32");
1721 assert!(b < U32_P, "assertion failed: {b} is larger than 2^32");
1722 }
1723 Op::U32Assertw => {
1724 let word = self.stack.peekw().expect("operand stack is empty");
1725 for elem in word.into_iter() {
1726 assert!(
1727 elem.as_int() < U32_P,
1728 "assertion failed: {elem} is larger than 2^32"
1729 );
1730 }
1731 }
1732 Op::U32Cast => {
1733 let a = pop!(self).as_int();
1734 self.stack.push(Felt::new(a % U32_P));
1735 }
1736 Op::U32Split => {
1737 let a = pop!(self).as_int();
1738 let hi = a / U32_P;
1739 let lo = a % U32_P;
1740 self.stack.push(Felt::new(lo));
1741 self.stack.push(Felt::new(hi));
1742 }
1743 Op::U32OverflowingAdd => binop_overflowing_u32!(self, add),
1744 Op::U32OverflowingAddImm(imm) => binop_overflowing_u32!(self, add, imm),
1745 Op::U32WrappingAdd => binop_wrapping_u32!(self, add),
1746 Op::U32WrappingAddImm(imm) => binop_wrapping_u32!(self, add, imm),
1747 Op::U32OverflowingAdd3 => todo!(),
1748 Op::U32WrappingAdd3 => todo!(),
1749 Op::U32OverflowingSub => binop_overflowing_u32!(self, sub),
1750 Op::U32OverflowingSubImm(imm) => binop_overflowing_u32!(self, sub, imm),
1751 Op::U32WrappingSub => binop_wrapping_u32!(self, sub),
1752 Op::U32WrappingSubImm(imm) => binop_wrapping_u32!(self, sub, imm),
1753 Op::U32OverflowingMul => binop_overflowing_u32!(self, mul),
1754 Op::U32OverflowingMulImm(imm) => binop_overflowing_u32!(self, mul, imm),
1755 Op::U32WrappingMul => binop_wrapping_u32!(self, mul),
1756 Op::U32WrappingMulImm(imm) => binop_wrapping_u32!(self, mul, imm),
1757 Op::U32OverflowingMadd => {
1758 let b = pop_u32!(self) as u64;
1759 let a = pop_u32!(self) as u64;
1760 let c = pop_u32!(self) as u64;
1761 let result = a * b + c;
1762 let d = result % 2u64.pow(32);
1763 let e = result / 2u64.pow(32);
1764 self.stack.push(Felt::new(d));
1765 self.stack.push(Felt::new(e));
1766 }
1767 Op::U32WrappingMadd => {
1768 let b = pop_u32!(self) as u64;
1769 let a = pop_u32!(self) as u64;
1770 let c = pop_u32!(self) as u64;
1771 let d = (a * b + c) % 2u64.pow(32);
1772 self.stack.push(Felt::new(d));
1773 }
1774 Op::U32Div => binop_unchecked_u32!(self, div),
1775 Op::U32DivImm(imm) => binop_unchecked_u32!(self, div, imm as u64),
1776 Op::U32Mod => {
1777 let b = pop!(self).as_int();
1778 let a = pop!(self).as_int();
1779 self.stack.push(Felt::new(a % b));
1780 }
1781 Op::U32ModImm(imm) => {
1782 let a = pop!(self).as_int();
1783 self.stack.push(Felt::new(a % imm as u64));
1784 }
1785 Op::U32DivMod => {
1786 let b = pop!(self).as_int();
1787 let a = pop!(self).as_int();
1788 self.stack.push(Felt::new(a / b));
1789 self.stack.push(Felt::new(a % b));
1790 }
1791 Op::U32DivModImm(b) => {
1792 let b = b as u64;
1793 let a = pop!(self).as_int();
1794 self.stack.push(Felt::new(a / b));
1795 self.stack.push(Felt::new(a % b));
1796 }
1797 Op::U32And => binop32!(self, bitand),
1798 Op::U32Or => binop32!(self, bitor),
1799 Op::U32Xor => binop32!(self, bitxor),
1800 Op::U32Not => {
1801 let a = pop_u32!(self);
1802 self.stack.push_u32(!a);
1803 }
1804 Op::U32Shl => binop_wrapping_u32!(self, shl),
1805 Op::U32ShlImm(imm) => binop_wrapping_u32!(self, shl, imm),
1806 Op::U32Shr => binop_wrapping_u32!(self, shr),
1807 Op::U32ShrImm(imm) => binop_wrapping_u32!(self, shr, imm),
1808 Op::U32Rotl => {
1809 let b = pop_u32!(self);
1810 let a = pop_u32!(self);
1811 self.stack.push_u32(a.rotate_left(b));
1812 }
1813 Op::U32RotlImm(imm) => {
1814 let a = pop_u32!(self);
1815 self.stack.push_u32(a.rotate_left(imm));
1816 }
1817 Op::U32Rotr => {
1818 let b = pop_u32!(self);
1819 let a = pop_u32!(self);
1820 self.stack.push_u32(a.rotate_right(b));
1821 }
1822 Op::U32RotrImm(imm) => {
1823 let a = pop_u32!(self);
1824 self.stack.push_u32(a.rotate_right(imm));
1825 }
1826 Op::U32Popcnt => {
1827 let a = pop_u32!(self);
1828 self.stack.push_u32(a.count_ones());
1829 }
1830 Op::U32Clz => {
1831 let a = pop_u32!(self);
1832 self.stack.push_u32(a.leading_zeros());
1833 }
1834 Op::U32Clo => {
1835 let a = pop_u32!(self);
1836 self.stack.push_u32(a.leading_ones());
1837 }
1838 Op::U32Ctz => {
1839 let a = pop_u32!(self);
1840 self.stack.push_u32(a.trailing_zeros());
1841 }
1842 Op::U32Cto => {
1843 let a = pop_u32!(self);
1844 self.stack.push_u32(a.trailing_ones());
1845 }
1846 Op::U32Gt => comparison!(self, gt),
1847 Op::U32Gte => comparison!(self, ge),
1848 Op::U32Lt => comparison!(self, lt),
1849 Op::U32Lte => comparison!(self, le),
1850 Op::U32Min => {
1851 let b = pop!(self).as_int();
1852 let a = pop!(self).as_int();
1853 self.stack.push(Felt::new(cmp::min(a, b)));
1854 }
1855 Op::U32Max => {
1856 let b = pop!(self).as_int();
1857 let a = pop!(self).as_int();
1858 self.stack.push(Felt::new(cmp::max(a, b)));
1859 }
1860 Op::Breakpoint => {
1861 self.callstack.push(state);
1862 return Ok(EmulatorEvent::Breakpoint(BreakpointEvent::Step));
1863 }
1864 Op::DebugStack => {
1865 dbg!(self.stack.debug());
1866 }
1867 Op::DebugStackN(n) => {
1868 dbg!(self.stack.debug().take(n as usize));
1869 }
1870 Op::DebugMemory
1871 | Op::DebugMemoryAt(_)
1872 | Op::DebugMemoryRange(..)
1873 | Op::DebugFrame
1874 | Op::DebugFrameAt(_)
1875 | Op::DebugFrameRange(..) => (),
1876 Op::Emit(_) | Op::Trace(_) => (),
1877 op => unimplemented!("missing opcode implementation for {op:?}"),
1878 }
1879
1880 match ix_with_op.effect {
1881 ControlEffect::Repeat(_) | ControlEffect::Loopback => {
1882 self.callstack.push(state);
1883 return Ok(EmulatorEvent::EnterLoop(ix_with_op.ip.block));
1884 }
1885 ControlEffect::Enter => {
1886 self.callstack.push(state);
1887 return Ok(EmulatorEvent::Jump(ix_with_op.ip.block));
1888 }
1889 ControlEffect::Exit => {
1890 self.callstack.push(state);
1891 return Ok(EmulatorEvent::Jump(ix_with_op.ip.block));
1892 }
1893 ControlEffect::None => (),
1894 }
1895
1896 self.callstack.push(state);
1898
1899 Ok(EmulatorEvent::Suspended)
1900 } else {
1901 Ok(EmulatorEvent::ExitFunction(current_function))
1903 }
1904 }
1905}