@@ -455,6 +455,54 @@ TEST_F(AvmExecutionTests, jumpAndCalldatacopy)
455
455
gen_proof_and_validate (bytecode, std::move (trace), std::vector<FF>{ 13 , 156 });
456
456
}
457
457
458
+ // Positive test with MOV.
459
+ TEST_F (AvmExecutionTests, movOpcode)
460
+ {
461
+ std::string bytecode_hex = to_hex (OpCode::SET) + // opcode SET
462
+ " 00" // Indirect flag
463
+ " 01" // U8
464
+ " 13" // val 19
465
+ " 000000AB" // dst_offset 171
466
+ + to_hex (OpCode::MOV) + // opcode MOV
467
+ " 00" // Indirect flag
468
+ " 000000AB" // src_offset 171
469
+ " 00000021" // dst_offset 33
470
+ + to_hex (OpCode::RETURN) + // opcode RETURN
471
+ " 00" // Indirect flag
472
+ " 00000000" // ret offset 0
473
+ " 00000000" ; // ret size 0
474
+
475
+ auto bytecode = hex_to_bytes (bytecode_hex);
476
+ auto instructions = Deserialization::parse (bytecode);
477
+
478
+ ASSERT_THAT (instructions, SizeIs (3 ));
479
+
480
+ // SET
481
+ EXPECT_THAT (instructions.at (0 ),
482
+ AllOf (Field (&Instruction::op_code, OpCode::SET),
483
+ Field (&Instruction::operands,
484
+ ElementsAre (VariantWith<uint8_t >(0 ),
485
+ VariantWith<AvmMemoryTag>(AvmMemoryTag::U8),
486
+ VariantWith<uint8_t >(19 ),
487
+ VariantWith<uint32_t >(171 )))));
488
+
489
+ // MOV
490
+ EXPECT_THAT (
491
+ instructions.at (1 ),
492
+ AllOf (Field (&Instruction::op_code, OpCode::MOV),
493
+ Field (&Instruction::operands,
494
+ ElementsAre (VariantWith<uint8_t >(0 ), VariantWith<uint32_t >(171 ), VariantWith<uint32_t >(33 )))));
495
+
496
+ auto trace = Execution::gen_trace (instructions);
497
+
498
+ // Find the first row enabling the MOV selector
499
+ auto row = std::ranges::find_if (trace.begin (), trace.end (), [](Row r) { return r.avm_main_sel_mov == 1 ; });
500
+ EXPECT_EQ (row->avm_main_ia , 19 );
501
+ EXPECT_EQ (row->avm_main_ic , 19 );
502
+
503
+ gen_proof_and_validate (bytecode, std::move (trace), {});
504
+ }
505
+
458
506
// Negative test detecting an invalid opcode byte.
459
507
TEST_F (AvmExecutionTests, invalidOpcode)
460
508
{
0 commit comments