Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
instruction.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <cstdint>
4#include <cstring>
5#include <stdexcept>
6#include <variant>
7
13
15
19
20 MemoryTagWrapper() = default;
24
25 operator MemoryTag() const { return value; }
26
27 void msgpack_pack(auto& packer) const
28 {
29 uint64_t value_to_serialize = static_cast<uint64_t>(this->value);
30 packer.pack_bin(sizeof(value_to_serialize));
31 packer.pack_bin_body((char*)&value_to_serialize, sizeof(value_to_serialize)); // NOLINT
32 }
33
34 void msgpack_unpack(msgpack::object const& o)
35 {
36 // Handle binary data unpacking
37 if (o.type == msgpack::type::BIN) {
38 auto bin = o.via.bin;
39 if (bin.size == sizeof(uint64_t)) {
40 uint64_t value_to_deserialize = 0;
41 std::memcpy(&value_to_deserialize, bin.ptr, sizeof(value_to_deserialize));
42 *this = MemoryTagWrapper(static_cast<MemoryTag>(value_to_deserialize));
43 } else {
44 throw std::runtime_error("Invalid binary data size for MemoryTag");
45 }
46 }
47 }
48};
49
50enum class AddressingMode : uint8_t {
51 Direct = 0,
52 Indirect = 1,
53 Relative = 2,
55};
56
60
65
66 operator AddressingMode() const { return value; }
67
68 void msgpack_pack(auto& packer) const
69 {
70 uint8_t value_to_serialize = static_cast<uint8_t>(this->value);
71 packer.pack_bin(sizeof(value_to_serialize));
72 packer.pack_bin_body((char*)&value_to_serialize, sizeof(value_to_serialize)); // NOLINT
73 }
74
75 void msgpack_unpack(msgpack::object const& o)
76 {
77 // Handle binary data unpacking
78 if (o.type == msgpack::type::BIN) {
79 auto bin = o.via.bin;
80 if (bin.size == sizeof(uint8_t)) {
81 uint8_t value_to_deserialize = 0;
82 std::memcpy(&value_to_deserialize, bin.ptr, sizeof(value_to_deserialize));
83 *this = AddressingModeWrapper(static_cast<AddressingMode>(value_to_deserialize));
84 } else {
85 throw std::runtime_error("Invalid binary data size for AddressingMode");
86 }
87 }
88 }
89};
90
112
123
125
136
137inline std::ostream& operator<<(std::ostream& os, const ResolvedAddress& address)
138{
139 os << "ResolvedAddress {\n";
140 os << " absolute_address: " << address.absolute_address << ",\n";
141 os << " operand_address: " << address.operand_address << ",\n";
142 os << " pointer_address: " << address.pointer_address.value() << ",\n";
143 os << " via_relative: " << address.via_relative << ",\n";
144 os << "}";
145 return os;
146}
147
155
163
171
179
186
194
202
210
218
226
234
240
248
256
264
272
280
288
297
305
313
321
329
337
345
353
360
368
376
384
392
400
408
414
422
430
439
448
456
459 uint16_t slot_index; // index of the slot in memory_manager.storage_addresses
460 AddressRef slot_address; // address where we set slot value
463};
464
471
477
487
496
503
510
517
525
531
550
555
563
570
575
586
594
602
612
616 ParamRef value_address; // FF: value to convert
617 ParamRef radix_address; // U32: the radix/base
618 ParamRef num_limbs_address; // U32: number of output limbs
619 ParamRef output_bits_address; // U1: whether output is bits
620 AddressRef dst_address; // destination for limbs
621 bool is_output_bits; // known at generation time for memory tracking (U1 if true, U8 if false)
623};
624
633
694
695template <class... Ts> struct overloaded : Ts... {
696 using Ts::operator()...;
697};
698template <class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
699
700inline std::ostream& operator<<(std::ostream& os, const MemoryTagWrapper& tag)
701{
702 os << tag.value;
703 return os;
704}
705
706inline std::ostream& operator<<(std::ostream& os, const VariableRef& variable)
707{
708 os << "VariableRef " << variable.tag << " " << variable.index << " "
709 << static_cast<int>(static_cast<AddressingMode>(variable.mode));
710 return os;
711}
712
713inline std::ostream& operator<<(std::ostream& os, const AddressRef& result_address)
714{
715 os << "AddressRef " << result_address.address << " "
716 << static_cast<int>(static_cast<AddressingMode>(result_address.mode));
717 return os;
718}
719
720inline std::ostream& operator<<(std::ostream& os, const ParamRef& param)
721{
722 std::visit([&](auto&& arg) { os << arg; }, param);
723 return os;
724}
725
726inline std::ostream& operator<<(std::ostream& os, const FuzzInstruction& instruction)
727{
728 std::visit(
730 [&](ADD_8_Instruction arg) {
731 os << "ADD_8_Instruction " << arg.a_address << " " << arg.b_address << " " << arg.result_address;
732 },
733 [&](SET_8_Instruction arg) {
734 os << "SET_8_Instruction " << arg.value_tag << " " << arg.result_address << " " << arg.value;
735 },
736 [&](SET_16_Instruction arg) {
737 os << "SET_16_Instruction " << arg.value_tag << " " << arg.result_address << " " << arg.value;
738 },
739 [&](SET_32_Instruction arg) {
740 os << "SET_32_Instruction " << arg.value_tag << " " << arg.result_address << " " << arg.value;
741 },
742 [&](SET_64_Instruction arg) {
743 os << "SET_64_Instruction " << arg.value_tag << " " << arg.result_address << " " << arg.value;
744 },
745 [&](SET_128_Instruction arg) {
746 os << "SET_128_Instruction " << arg.value_tag << " " << arg.result_address << " " << arg.value_high
747 << " " << arg.value_low;
748 },
749 [&](SET_FF_Instruction arg) {
750 os << "SET_FF_Instruction " << arg.value_tag << " " << arg.result_address << " " << arg.value;
751 },
752 [&](SUB_8_Instruction arg) {
753 os << "SUB_8_Instruction " << arg.a_address << " " << arg.b_address << " " << arg.result_address;
754 },
755 [&](MUL_8_Instruction arg) {
756 os << "MUL_8_Instruction " << arg.a_address << " " << arg.b_address << " " << arg.result_address;
757 },
758 [&](DIV_8_Instruction arg) {
759 os << "DIV_8_Instruction " << arg.a_address << " " << arg.b_address << " " << arg.result_address;
760 },
761 [&](FDIV_8_Instruction arg) {
762 os << "FDIV_8_Instruction " << arg.a_address << " " << arg.b_address << " " << arg.result_address;
763 },
764 [&](EQ_8_Instruction arg) {
765 os << "EQ_8_Instruction " << arg.a_address << " " << arg.b_address << " " << arg.result_address;
766 },
767 [&](LT_8_Instruction arg) {
768 os << "LT_8_Instruction " << arg.a_address << " " << arg.b_address << " " << arg.result_address;
769 },
770 [&](LTE_8_Instruction arg) {
771 os << "LTE_8_Instruction " << arg.a_address << " " << arg.b_address << " " << arg.result_address;
772 },
773 [&](AND_8_Instruction arg) {
774 os << "AND_8_Instruction " << arg.a_address << " " << arg.b_address << " " << arg.result_address;
775 },
776 [&](OR_8_Instruction arg) {
777 os << "OR_8_Instruction " << arg.a_address << " " << arg.b_address << " " << arg.result_address;
778 },
779 [&](XOR_8_Instruction arg) {
780 os << "XOR_8_Instruction " << arg.a_address << " " << arg.b_address << " " << arg.result_address;
781 },
782 [&](SHL_8_Instruction arg) {
783 os << "SHL_8_Instruction " << arg.a_address << " " << arg.b_address << " " << arg.result_address;
784 },
785 [&](SHR_8_Instruction arg) {
786 os << "SHR_8_Instruction " << arg.a_address << " " << arg.b_address << " " << arg.result_address;
787 },
788 [&](NOT_8_Instruction arg) { os << "NOT_8_Instruction " << arg.a_address << " " << arg.result_address; },
789 [&](ADD_16_Instruction arg) {
790 os << "ADD_16_Instruction " << arg.a_address << " " << arg.b_address << " " << arg.result_address;
791 },
792 [&](SUB_16_Instruction arg) {
793 os << "SUB_16_Instruction " << arg.a_address << " " << arg.b_address << " " << arg.result_address;
794 },
795 [&](MUL_16_Instruction arg) {
796 os << "MUL_16_Instruction " << arg.a_address << " " << arg.b_address << " " << arg.result_address;
797 },
798 [&](DIV_16_Instruction arg) {
799 os << "DIV_16_Instruction " << arg.a_address << " " << arg.b_address << " " << arg.result_address;
800 },
801 [&](FDIV_16_Instruction arg) {
802 os << "FDIV_16_Instruction " << arg.a_address << " " << arg.b_address << " " << arg.result_address;
803 },
804 [&](EQ_16_Instruction arg) {
805 os << "EQ_16_Instruction " << arg.a_address << " " << arg.b_address << " " << arg.result_address;
806 },
807 [&](LT_16_Instruction arg) {
808 os << "LT_16_Instruction " << arg.a_address << " " << arg.b_address << " " << arg.result_address;
809 },
810 [&](LTE_16_Instruction arg) {
811 os << "LTE_16_Instruction " << arg.a_address << " " << arg.b_address << " " << arg.result_address;
812 },
813 [&](AND_16_Instruction arg) {
814 os << "AND_16_Instruction " << arg.a_address << " " << arg.b_address << " " << arg.result_address;
815 },
816 [&](OR_16_Instruction arg) {
817 os << "OR_16_Instruction " << arg.a_address << " " << arg.b_address << " " << arg.result_address;
818 },
819 [&](XOR_16_Instruction arg) {
820 os << "XOR_16_Instruction " << arg.a_address << " " << arg.b_address << " " << arg.result_address;
821 },
822 [&](NOT_16_Instruction arg) { os << "NOT_16_Instruction " << arg.a_address << " " << arg.result_address; },
823 [&](SHL_16_Instruction arg) {
824 os << "SHL_16_Instruction " << arg.a_address << " " << arg.b_address << " " << arg.result_address;
825 },
826 [&](SHR_16_Instruction arg) {
827 os << "SHR_16_Instruction " << arg.a_address << " " << arg.b_address << " " << arg.result_address;
828 },
829 [&](CAST_8_Instruction arg) {
830 os << "CAST_8_Instruction " << arg.src_tag << " " << arg.src_address << " " << arg.result_address << " "
831 << arg.target_tag;
832 },
833 [&](CAST_16_Instruction arg) {
834 os << "CAST_16_Instruction " << arg.src_tag << " " << arg.src_address << " " << arg.result_address
835 << " " << arg.target_tag;
836 },
837 [&](MOV_8_Instruction arg) {
838 os << "MOV_8_Instruction " << arg.value_tag << " " << arg.src_address << " " << arg.result_address;
839 },
840 [&](MOV_16_Instruction arg) {
841 os << "MOV_16_Instruction " << arg.value_tag << " " << arg.src_address << " " << arg.result_address;
842 },
843 [&](SSTORE_Instruction arg) {
844 os << "SSTORE_Instruction " << arg.src_address << " " << arg.result_address << " " << arg.slot;
845 },
846 [&](SLOAD_Instruction arg) { os << "SLOAD_Instruction " << arg.slot_address << " " << arg.result_address; },
847 [&](GETENVVAR_Instruction arg) {
848 os << "GETENVVAR_Instruction " << arg.result_address << " " << static_cast<int>(arg.type);
849 },
850 [&](EMITNULLIFIER_Instruction arg) { os << "EMITNULIFIER_Instruction " << arg.nullifier_address; },
852 os << "NULLIFIEREXISTS_Instruction " << arg.nullifier_address << " " << arg.contract_address_address
853 << " " << arg.result_address;
854 },
856 os << "L1TOL2MSGEXISTS_Instruction " << arg.msg_hash_address << " " << arg.leaf_index_address << " "
857 << arg.result_address;
858 },
859 [&](EMITNOTEHASH_Instruction arg) {
860 os << "EMITNOTEHASH_Instruction " << arg.note_hash_address << " " << arg.note_hash;
861 },
863 os << "NOTEHASHEXISTS_Instruction " << arg.notehash_address << " " << arg.notehash_address << " "
864 << arg.leaf_index_address << " " << arg.result_address;
865 },
866 [&](CALLDATACOPY_Instruction arg) {
867 os << "CALLDATACOPY_Instruction " << arg.copy_size_address << " " << arg.cd_offset_address << " "
868 << arg.dst_address;
869 },
871 os << "SENDL2TOL1MSG_Instruction " << arg.recipient << " " << arg.recipient_address << " "
872 << arg.content << " " << arg.content_address;
873 },
875 os << "EMITUNENCRYPTEDLOG_Instruction " << arg.log_size_address << " " << arg.log_values_address;
876 },
877 [&](CALL_Instruction arg) {
878 os << "CALL_Instruction " << arg.l2_gas_address << " " << arg.da_gas_address << " "
879 << arg.contract_address_address << " " << arg.calldata_size_address << " " << arg.calldata_address
880 << " " << arg.is_static_call;
881 },
882 [&](RETURNDATASIZE_Instruction arg) { os << "RETURNDATASIZE_Instruction " << arg.dst_address; },
884 os << "RETURNDATACOPY_Instruction " << arg.copy_size_address << " " << arg.rd_offset_address << " "
885 << arg.dst_address;
886 },
887 [&](ECADD_Instruction arg) {
888 os << "ECADD_Instruction " << arg.p1_x << " " << arg.p1_y << " " << arg.p1_infinite << " " << arg.p2_x
889 << " " << arg.p2_y << " " << arg.p2_infinite << " " << arg.result;
890 },
892 os << "POSEIDON2PERM_Instruction " << arg.src_address << " " << arg.dst_address;
893 },
894 [&](KECCAKF1600_Instruction arg) {
895 os << "KECCAKF1600_Instruction " << arg.src_address << " " << arg.dst_address;
896 },
898 os << "SHA256COMPRESSION_Instruction " << arg.state_address << " " << arg.input_address << " "
899 << arg.dst_address;
900 },
901 [&](TORADIXBE_Instruction arg) {
902 os << "TORADIXBE_Instruction " << arg.value_address << " " << arg.radix_address << " "
903 << arg.num_limbs_address << " " << arg.output_bits_address << " " << arg.dst_address << " "
904 << arg.is_output_bits;
905 },
906 [&](DEBUGLOG_Instruction arg) {
907 os << "DEBUGLOG_Instruction " << arg.level_offset << " " << arg.message_offset << " "
908 << arg.fields_offset << " " << arg.fields_size_offset << " " << arg.message_size;
909 },
910 [&](auto) { os << "Unknown instruction"; },
911 },
913 return os;
914}
::FuzzInstruction FuzzInstruction
bb::avm2::MemoryTag MemoryTag
std::ostream & operator<<(std::ostream &os, const ResolvedAddress &address)
AddressingMode
std::variant< VariableRef, AddressRef > ParamRef
Instruction instruction
ValueTag MemoryTag
AvmFlavorSettings::FF FF
Definition field.hpp:10
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
mem[result_offset] = mem[a_address] + mem[b_address] (16-bit)
AddressRef result_address
MSGPACK_FIELDS(a_address, b_address, result_address)
mem[result_offset] = mem[a_address] + mem[b_address]
MSGPACK_FIELDS(a_address, b_address, result_address)
AddressRef result_address
mem[result_offset] = mem[a_address] & mem[b_address] (16-bit)
MSGPACK_FIELDS(a_address, b_address, result_address)
AddressRef result_address
mem[result_offset] = mem[a_address] & mem[b_address]
MSGPACK_FIELDS(a_address, b_address, result_address)
AddressRef result_address
MSGPACK_FIELDS(address, pointer_address_seed, mode)
AddressingModeWrapper mode
uint16_t pointer_address_seed
A seed for the generation of the pointer address Used for Indirect/IndirectRelative modes only.
uint32_t address
Wrapper for AddressingMode to allow for msgpack packing and unpacking.
AddressingModeWrapper()=default
void msgpack_unpack(msgpack::object const &o)
void msgpack_pack(auto &packer) const
AddressingModeWrapper(AddressingMode v)
AddressingMode value
ParamRef contract_address_address
ParamRef da_gas_address
AddressRef calldata_size_address
MSGPACK_FIELDS(l2_gas_address, da_gas_address, contract_address_address, calldata_address, calldata_size_address, calldata_size, is_static_call)
ParamRef l2_gas_address
ParamRef calldata_address
MSGPACK_FIELDS(copy_size_address, cd_offset_address, dst_address)
CAST_16: cast mem[src_offset_index] to target_tag and store at dst_offset.
AddressRef result_address
MSGPACK_FIELDS(src_tag, src_address, result_address, target_tag)
MemoryTagWrapper target_tag
MemoryTagWrapper src_tag
CAST_8: cast mem[src_offset_index] to target_tag and store at dst_offset.
MSGPACK_FIELDS(src_tag, src_address, result_address, target_tag)
AddressRef result_address
MemoryTagWrapper src_tag
MemoryTagWrapper target_tag
MSGPACK_FIELDS(level_offset, message_offset, fields_offset, fields_size_offset, message_size)
mem[result_offset] = mem[a_address] / mem[b_address] (16-bit)
AddressRef result_address
MSGPACK_FIELDS(a_address, b_address, result_address)
mem[result_offset] = mem[a_address] / mem[b_address]
AddressRef result_address
MSGPACK_FIELDS(a_address, b_address, result_address)
MSGPACK_FIELDS(p1_x, p1_y, p1_infinite, p2_x, p2_y, p2_infinite, result)
EMITNOTEHASH: M[note_hash_offset] = note_hash; emit note hash to the note hash tree.
MSGPACK_FIELDS(note_hash_address, note_hash)
EMITNULIFIER: inserts new nullifier to the nullifier tree.
MSGPACK_FIELDS(nullifier_address)
MSGPACK_FIELDS(log_size_address, log_values_address)
mem[result_offset] = mem[a_address] == mem[b_address] (16-bit)
MSGPACK_FIELDS(a_address, b_address, result_address)
AddressRef result_address
mem[result_offset] = mem[a_address] == mem[b_address]
MSGPACK_FIELDS(a_address, b_address, result_address)
AddressRef result_address
AddressRef result_address
MSGPACK_FIELDS(a_address, b_address, result_address)
MSGPACK_FIELDS(a_address, b_address, result_address)
AddressRef result_address
MSGPACK_FIELDS(contract_address_address, member_enum, dst_address)
GETENVVAR: M[result_offset] = getenvvar(type)
MSGPACK_FIELDS(result_address, type)
KECCAKF1600: Perform Keccak-f[1600] permutation on 25 U64 values M[dst_address:dst_address+25] = kecc...
MSGPACK_FIELDS(src_address, dst_address)
L1TOL2MSGEXISTS: Check if a L1 to L2 message exists M[result_address] = L1TOL2MSGEXISTS(M[msg_hash_ad...
MSGPACK_FIELDS(msg_hash_address, leaf_index_address, result_address)
mem[result_offset] = mem[a_address] < mem[b_address] (16-bit)
AddressRef result_address
MSGPACK_FIELDS(a_address, b_address, result_address)
mem[result_offset] = mem[a_address] < mem[b_address]
MSGPACK_FIELDS(a_address, b_address, result_address)
AddressRef result_address
mem[result_offset] = mem[a_address] <= mem[b_address] (16-bit)
MSGPACK_FIELDS(a_address, b_address, result_address)
AddressRef result_address
mem[result_offset] = mem[a_address] <= mem[b_address]
AddressRef result_address
MSGPACK_FIELDS(a_address, b_address, result_address)
MOV_16 instruction: mem[dst_offset] = mem[src_offset].
MemoryTagWrapper value_tag
MSGPACK_FIELDS(value_tag, src_address, result_address)
AddressRef result_address
MOV_8 instruction: mem[dst_offset] = mem[src_offset].
MemoryTagWrapper value_tag
MSGPACK_FIELDS(value_tag, src_address, result_address)
AddressRef result_address
mem[result_offset] = mem[a_address] * mem[b_address] (16-bit)
MSGPACK_FIELDS(a_address, b_address, result_address)
AddressRef result_address
mem[result_offset] = mem[a_address] * mem[b_address]
AddressRef result_address
MSGPACK_FIELDS(a_address, b_address, result_address)
Wrapper for MemoryTag to allow for msgpack packing and unpacking.
MemoryTagWrapper(MemoryTag v)
MemoryTagWrapper()=default
void msgpack_pack(auto &packer) const
void msgpack_unpack(msgpack::object const &o)
MSGPACK_FIELDS(a_address, result_address)
AddressRef result_address
AddressRef result_address
MSGPACK_FIELDS(a_address, result_address)
MSGPACK_FIELDS(notehash_address, leaf_index_address, result_address)
NULLIFIEREXISTS: checks if nullifier exists in the nullifier tree Gets contract's address by GETENVVA...
MSGPACK_FIELDS(nullifier_address, contract_address_address, result_address)
mem[result_offset] = mem[a_address] | mem[b_address] (16-bit)
AddressRef result_address
MSGPACK_FIELDS(a_address, b_address, result_address)
mem[result_offset] = mem[a_address] | mem[b_address]
AddressRef result_address
MSGPACK_FIELDS(a_address, b_address, result_address)
POSEIDON2PERM: Perform Poseidon2 permutation on 4 FF values M[dst_address:dst_address+4] = poseidon2_...
MSGPACK_FIELDS(src_address, dst_address)
MSGPACK_FIELDS(copy_size_address, rd_offset_address, dst_address)
Output of resolving an address in the memory manager In order to resolve a given absolute address wit...
uint32_t operand_address
uint32_t absolute_address
std::optional< uint32_t > pointer_address
MSGPACK_FIELDS(recipient, recipient_address, content, content_address)
SET_128 instruction.
MSGPACK_FIELDS(value_tag, result_address, value_low, value_high)
MemoryTagWrapper value_tag
AddressRef result_address
SET_16 instruction.
AddressRef result_address
MSGPACK_FIELDS(value_tag, result_address, value)
MemoryTagWrapper value_tag
SET_32 instruction.
MSGPACK_FIELDS(value_tag, result_address, value)
AddressRef result_address
MemoryTagWrapper value_tag
SET_64 instruction.
AddressRef result_address
MSGPACK_FIELDS(value_tag, result_address, value)
MemoryTagWrapper value_tag
SET_8 instruction.
MemoryTagWrapper value_tag
MSGPACK_FIELDS(value_tag, result_address, value)
AddressRef result_address
SET_FF instruction.
MSGPACK_FIELDS(value_tag, result_address, value)
MemoryTagWrapper value_tag
AddressRef result_address
SHA256COMPRESSION: Perform SHA256 compression M[dst_address:dst_address+8] = sha256_compression(M[sta...
MSGPACK_FIELDS(state_address, input_address, dst_address)
mem[result_offset] = mem[a_address] << mem[b_address] (16-bit)
AddressRef result_address
MSGPACK_FIELDS(a_address, b_address, result_address)
mem[result_offset] = mem[a_address] << mem[b_address]
AddressRef result_address
MSGPACK_FIELDS(a_address, b_address, result_address)
mem[result_offset] = mem[a_address] >> mem[b_address] (16-bit)
AddressRef result_address
MSGPACK_FIELDS(a_address, b_address, result_address)
mem[result_offset] = mem[a_address] >> mem[b_address]
MSGPACK_FIELDS(a_address, b_address, result_address)
AddressRef result_address
SLOAD: M[slot_offset] = slot; M[result_offset] = S[M[slotOffset]].
MSGPACK_FIELDS(slot_index, slot_address, result_address)
AddressRef result_address
AddressRef slot_address
SSTORE: M[slot_offset_index] = slot; S[M[slotOffset]] = M[srcOffset].
AddressRef result_address
MSGPACK_FIELDS(src_address, result_address, slot)
mem[result_offset] = mem[a_address] - mem[b_address] (16-bit)
AddressRef result_address
MSGPACK_FIELDS(a_address, b_address, result_address)
mem[result_offset] = mem[a_address] - mem[b_address]
AddressRef result_address
MSGPACK_FIELDS(a_address, b_address, result_address)
MSGPACK_FIELDS(dst_address)
TORADIXBE: Convert a field element to a vector of limbs in big-endian radix representation M[dst_addr...
MSGPACK_FIELDS(value_address, radix_address, num_limbs_address, output_bits_address, dst_address, is_output_bits)
AddressingModeWrapper mode
uint32_t index
Index of the variable in the memory_manager.stored_variables map.
MSGPACK_FIELDS(tag, index, pointer_address_seed, mode)
MemoryTagWrapper tag
uint16_t pointer_address_seed
A seed for the generation of the pointer address Used for Indirect/IndirectRelative modes only.
mem[result_offset] = mem[a_address] ^ mem[b_address] (16-bit)
MSGPACK_FIELDS(a_address, b_address, result_address)
AddressRef result_address
mem[result_offset] = mem[a_address] ^ mem[b_address]
MSGPACK_FIELDS(a_address, b_address, result_address)
AddressRef result_address