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
461 ParamRef contract_address_address; // address where the contract address will be stored
464};
465
472
478
486
495
502
509
516
522
528
547
552
560
567
572
583
591
599
609
613 ParamRef value_address; // FF: value to convert
614 ParamRef radix_address; // U32: the radix/base
615 ParamRef num_limbs_address; // U32: number of output limbs
616 ParamRef output_bits_address; // U1: whether output is bits
617 AddressRef dst_address; // destination for limbs
618 bool is_output_bits; // known at generation time for memory tracking (U1 if true, U8 if false)
620};
621
630
691
692template <class... Ts> struct overloaded : Ts... {
693 using Ts::operator()...;
694};
695template <class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
696
697inline std::ostream& operator<<(std::ostream& os, const MemoryTagWrapper& tag)
698{
699 os << tag.value;
700 return os;
701}
702
703inline std::ostream& operator<<(std::ostream& os, const VariableRef& variable)
704{
705 os << "VariableRef " << variable.tag << " " << variable.index << " "
706 << static_cast<int>(static_cast<AddressingMode>(variable.mode));
707 return os;
708}
709
710inline std::ostream& operator<<(std::ostream& os, const AddressRef& result_address)
711{
712 os << "AddressRef " << result_address.address << " "
713 << static_cast<int>(static_cast<AddressingMode>(result_address.mode));
714 return os;
715}
716
717inline std::ostream& operator<<(std::ostream& os, const ParamRef& param)
718{
719 std::visit([&](auto&& arg) { os << arg; }, param);
720 return os;
721}
722
723inline std::ostream& operator<<(std::ostream& os, const FuzzInstruction& instruction)
724{
725 std::visit(
727 [&](ADD_8_Instruction arg) {
728 os << "ADD_8_Instruction " << arg.a_address << " " << arg.b_address << " " << arg.result_address;
729 },
730 [&](SET_8_Instruction arg) {
731 os << "SET_8_Instruction " << arg.value_tag << " " << arg.result_address << " " << arg.value;
732 },
733 [&](SET_16_Instruction arg) {
734 os << "SET_16_Instruction " << arg.value_tag << " " << arg.result_address << " " << arg.value;
735 },
736 [&](SET_32_Instruction arg) {
737 os << "SET_32_Instruction " << arg.value_tag << " " << arg.result_address << " " << arg.value;
738 },
739 [&](SET_64_Instruction arg) {
740 os << "SET_64_Instruction " << arg.value_tag << " " << arg.result_address << " " << arg.value;
741 },
742 [&](SET_128_Instruction arg) {
743 os << "SET_128_Instruction " << arg.value_tag << " " << arg.result_address << " " << arg.value_high
744 << " " << arg.value_low;
745 },
746 [&](SET_FF_Instruction arg) {
747 os << "SET_FF_Instruction " << arg.value_tag << " " << arg.result_address << " " << arg.value;
748 },
749 [&](SUB_8_Instruction arg) {
750 os << "SUB_8_Instruction " << arg.a_address << " " << arg.b_address << " " << arg.result_address;
751 },
752 [&](MUL_8_Instruction arg) {
753 os << "MUL_8_Instruction " << arg.a_address << " " << arg.b_address << " " << arg.result_address;
754 },
755 [&](DIV_8_Instruction arg) {
756 os << "DIV_8_Instruction " << arg.a_address << " " << arg.b_address << " " << arg.result_address;
757 },
758 [&](FDIV_8_Instruction arg) {
759 os << "FDIV_8_Instruction " << arg.a_address << " " << arg.b_address << " " << arg.result_address;
760 },
761 [&](EQ_8_Instruction arg) {
762 os << "EQ_8_Instruction " << arg.a_address << " " << arg.b_address << " " << arg.result_address;
763 },
764 [&](LT_8_Instruction arg) {
765 os << "LT_8_Instruction " << arg.a_address << " " << arg.b_address << " " << arg.result_address;
766 },
767 [&](LTE_8_Instruction arg) {
768 os << "LTE_8_Instruction " << arg.a_address << " " << arg.b_address << " " << arg.result_address;
769 },
770 [&](AND_8_Instruction arg) {
771 os << "AND_8_Instruction " << arg.a_address << " " << arg.b_address << " " << arg.result_address;
772 },
773 [&](OR_8_Instruction arg) {
774 os << "OR_8_Instruction " << arg.a_address << " " << arg.b_address << " " << arg.result_address;
775 },
776 [&](XOR_8_Instruction arg) {
777 os << "XOR_8_Instruction " << arg.a_address << " " << arg.b_address << " " << arg.result_address;
778 },
779 [&](SHL_8_Instruction arg) {
780 os << "SHL_8_Instruction " << arg.a_address << " " << arg.b_address << " " << arg.result_address;
781 },
782 [&](SHR_8_Instruction arg) {
783 os << "SHR_8_Instruction " << arg.a_address << " " << arg.b_address << " " << arg.result_address;
784 },
785 [&](NOT_8_Instruction arg) { os << "NOT_8_Instruction " << arg.a_address << " " << arg.result_address; },
786 [&](ADD_16_Instruction arg) {
787 os << "ADD_16_Instruction " << arg.a_address << " " << arg.b_address << " " << arg.result_address;
788 },
789 [&](SUB_16_Instruction arg) {
790 os << "SUB_16_Instruction " << arg.a_address << " " << arg.b_address << " " << arg.result_address;
791 },
792 [&](MUL_16_Instruction arg) {
793 os << "MUL_16_Instruction " << arg.a_address << " " << arg.b_address << " " << arg.result_address;
794 },
795 [&](DIV_16_Instruction arg) {
796 os << "DIV_16_Instruction " << arg.a_address << " " << arg.b_address << " " << arg.result_address;
797 },
798 [&](FDIV_16_Instruction arg) {
799 os << "FDIV_16_Instruction " << arg.a_address << " " << arg.b_address << " " << arg.result_address;
800 },
801 [&](EQ_16_Instruction arg) {
802 os << "EQ_16_Instruction " << arg.a_address << " " << arg.b_address << " " << arg.result_address;
803 },
804 [&](LT_16_Instruction arg) {
805 os << "LT_16_Instruction " << arg.a_address << " " << arg.b_address << " " << arg.result_address;
806 },
807 [&](LTE_16_Instruction arg) {
808 os << "LTE_16_Instruction " << arg.a_address << " " << arg.b_address << " " << arg.result_address;
809 },
810 [&](AND_16_Instruction arg) {
811 os << "AND_16_Instruction " << arg.a_address << " " << arg.b_address << " " << arg.result_address;
812 },
813 [&](OR_16_Instruction arg) {
814 os << "OR_16_Instruction " << arg.a_address << " " << arg.b_address << " " << arg.result_address;
815 },
816 [&](XOR_16_Instruction arg) {
817 os << "XOR_16_Instruction " << arg.a_address << " " << arg.b_address << " " << arg.result_address;
818 },
819 [&](NOT_16_Instruction arg) { os << "NOT_16_Instruction " << arg.a_address << " " << arg.result_address; },
820 [&](SHL_16_Instruction arg) {
821 os << "SHL_16_Instruction " << arg.a_address << " " << arg.b_address << " " << arg.result_address;
822 },
823 [&](SHR_16_Instruction arg) {
824 os << "SHR_16_Instruction " << arg.a_address << " " << arg.b_address << " " << arg.result_address;
825 },
826 [&](CAST_8_Instruction arg) {
827 os << "CAST_8_Instruction " << arg.src_tag << " " << arg.src_address << " " << arg.result_address << " "
828 << arg.target_tag;
829 },
830 [&](CAST_16_Instruction arg) {
831 os << "CAST_16_Instruction " << arg.src_tag << " " << arg.src_address << " " << arg.result_address
832 << " " << arg.target_tag;
833 },
834 [&](MOV_8_Instruction arg) {
835 os << "MOV_8_Instruction " << arg.value_tag << " " << arg.src_address << " " << arg.result_address;
836 },
837 [&](MOV_16_Instruction arg) {
838 os << "MOV_16_Instruction " << arg.value_tag << " " << arg.src_address << " " << arg.result_address;
839 },
840 [&](SSTORE_Instruction arg) {
841 os << "SSTORE_Instruction " << arg.src_address << " " << arg.result_address << " " << arg.slot;
842 },
843 [&](SLOAD_Instruction arg) { os << "SLOAD_Instruction " << arg.slot_address << " " << arg.result_address; },
844 [&](GETENVVAR_Instruction arg) {
845 os << "GETENVVAR_Instruction " << arg.result_address << " " << static_cast<int>(arg.type);
846 },
847 [&](EMITNULLIFIER_Instruction arg) { os << "EMITNULIFIER_Instruction " << arg.nullifier_address; },
849 os << "NULLIFIEREXISTS_Instruction " << arg.siloed_nullifier_address << " " << arg.result_address;
850 },
852 os << "L1TOL2MSGEXISTS_Instruction " << arg.msg_hash_address << " " << arg.leaf_index_address << " "
853 << arg.result_address;
854 },
855 [&](EMITNOTEHASH_Instruction arg) {
856 os << "EMITNOTEHASH_Instruction " << arg.note_hash_address << " " << arg.note_hash;
857 },
859 os << "NOTEHASHEXISTS_Instruction " << arg.notehash_address << " " << arg.notehash_address << " "
860 << arg.leaf_index_address << " " << arg.result_address;
861 },
862 [&](CALLDATACOPY_Instruction arg) {
863 os << "CALLDATACOPY_Instruction " << arg.copy_size_address << " " << arg.cd_offset_address << " "
864 << arg.dst_address;
865 },
867 os << "SENDL2TOL1MSG_Instruction " << arg.recipient_address << " " << arg.content_address;
868 },
870 os << "EMITPUBLICLOG_Instruction " << arg.log_size_address << " " << arg.log_values_address;
871 },
872 [&](CALL_Instruction arg) {
873 os << "CALL_Instruction " << arg.l2_gas_address << " " << arg.da_gas_address << " "
874 << arg.contract_address_address << " " << arg.calldata_size_address << " " << arg.calldata_address
875 << " " << arg.is_static_call;
876 },
877 [&](RETURNDATASIZE_Instruction arg) { os << "RETURNDATASIZE_Instruction " << arg.dst_address; },
879 os << "RETURNDATACOPY_Instruction " << arg.copy_size_address << " " << arg.rd_offset_address << " "
880 << arg.dst_address;
881 },
882 [&](ECADD_Instruction arg) {
883 os << "ECADD_Instruction " << arg.p1_x << " " << arg.p1_y << " " << arg.p1_infinite << " " << arg.p2_x
884 << " " << arg.p2_y << " " << arg.p2_infinite << " " << arg.result;
885 },
887 os << "POSEIDON2PERM_Instruction " << arg.src_address << " " << arg.dst_address;
888 },
889 [&](KECCAKF1600_Instruction arg) {
890 os << "KECCAKF1600_Instruction " << arg.src_address << " " << arg.dst_address;
891 },
893 os << "SHA256COMPRESSION_Instruction " << arg.state_address << " " << arg.input_address << " "
894 << arg.dst_address;
895 },
896 [&](TORADIXBE_Instruction arg) {
897 os << "TORADIXBE_Instruction " << arg.value_address << " " << arg.radix_address << " "
898 << arg.num_limbs_address << " " << arg.output_bits_address << " " << arg.dst_address << " "
899 << arg.is_output_bits;
900 },
901 [&](DEBUGLOG_Instruction arg) {
902 os << "DEBUGLOG_Instruction " << arg.level_offset << " " << arg.message_offset << " "
903 << arg.fields_offset << " " << arg.fields_size_offset << " " << arg.message_size;
904 },
905 [&](auto) { os << "Unknown instruction"; },
906 },
908 return os;
909}
::FuzzInstruction FuzzInstruction
bb::avm2::MemoryTag MemoryTag
std::ostream & operator<<(std::ostream &os, const ResolvedAddress &address)
AddressingMode
std::variant< VariableRef, AddressRef > ParamRef
Instruction instruction
AvmFlavorSettings::FF FF
Definition field.hpp:10
ValueTag MemoryTag
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 a siloed nullifier exists in the nullifier tree M[result_address] = NULLIF...
MSGPACK_FIELDS(siloed_nullifier_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_address, 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]].
AddressRef result_address
MSGPACK_FIELDS(slot_index, slot_address, contract_address_address, result_address)
ParamRef contract_address_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