9#include <unordered_map>
31 return OPERAND_TYPE_SIZE_BYTES;
205 return WireOpCode_WIRE_FORMAT;
213 return get_wire_opcode_wire_format();
218 return get_operand_type_size_bytes();
225bool is_wire_opcode_valid(uint8_t w_opcode)
254 const auto bytecode_length =
bytecode.size();
256 if (pos >= bytecode_length) {
257 std::string error_msg =
format(
"Invalid program counter ", pos,
", max is ", bytecode_length - 1);
262 const uint8_t opcode_byte =
bytecode[pos];
264 if (!is_wire_opcode_valid(opcode_byte)) {
265 std::string error_msg =
format(
"Opcode ",
266 static_cast<uint32_t
>(opcode_byte),
269 ") value is not in the range of valid opcodes (at PC ",
276 const auto opcode =
static_cast<WireOpCode>(opcode_byte);
277 const auto iter = get_wire_opcode_wire_format().find(opcode);
278 BB_ASSERT_DEBUG(iter != get_wire_opcode_wire_format().end(),
"Wire opcode not found in wire opcode wire format");
279 const auto& inst_format = iter->second;
283 if (pos + instruction_size > bytecode_length) {
284 std::string error_msg =
format(
"Instruction at PC ",
286 " does not fit in bytecode (instruction size: ",
289 bytecode_length - pos,
298 uint16_t addressing_mode = 0;
301 const auto operand_size = get_operand_type_size_bytes().at(op_type);
303 BB_ASSERT_DEBUG(pos + operand_size <= bytecode_length,
"Operand size is out of range");
308 operands.emplace_back(Operand::from<uint8_t>(
bytecode[pos]));
316 uint16_t operand_u16 = 0;
317 uint8_t
const* pos_ptr = &
bytecode[pos];
319 addressing_mode = operand_u16;
323 uint16_t operand_u16 = 0;
324 uint8_t
const* pos_ptr = &
bytecode[pos];
326 operands.emplace_back(Operand::from<uint16_t>(operand_u16));
330 uint32_t operand_u32 = 0;
331 uint8_t
const* pos_ptr = &
bytecode[pos];
333 operands.emplace_back(Operand::from<uint32_t>(operand_u32));
337 uint64_t operand_u64 = 0;
338 uint8_t
const* pos_ptr = &
bytecode[pos];
340 operands.emplace_back(Operand::from<uint64_t>(operand_u64));
345 uint8_t
const* pos_ptr = &
bytecode[pos];
347 operands.emplace_back(Operand::from<uint128_t>(operand_u128));
352 uint8_t
const* pos_ptr = &
bytecode[pos];
353 read(pos_ptr, operand_ff);
354 operands.emplace_back(Operand::from<FF>(operand_ff));
362 .addressing_mode = addressing_mode,
369 std::ostringstream oss;
371 for (
size_t operand_pos = 0; operand_pos <
operands.size(); ++operand_pos) {
372 const auto& operand =
operands[operand_pos];
399 std::vector<uint8_t> output;
401 output.emplace_back(
static_cast<uint8_t
>(
opcode));
402 size_t operand_pos = 0;
404 for (
const auto& operand_type : get_wire_opcode_wire_format().at(
opcode)) {
405 switch (operand_type) {
411 output.insert(output.end(),
417 output.emplace_back(
operands.at(operand_pos++).as<uint8_t>());
472 "Instruction does not contain a valid wire opcode.");
478 for (
const OperandType& operand_type : wire_format) {
492 vinfo(
"Instruction tag operand at position: ",
502 vinfo(
"Instruction operand at position: ",
504 " is longer than a byte.",
#define BB_ASSERT(expression,...)
#define BB_ASSERT_DEBUG(expression,...)
std::shared_ptr< Napi::ThreadSafeFunction > bytecode
std::string format(Args... args)
const std::unordered_map< OperandType, uint32_t > & get_operand_type_sizes()
const std::unordered_map< WireOpCode, std::vector< OperandType > > & get_instruction_wire_formats()
AVM range check gadget for witness generation.
const std::vector< OperandType > external_call_format
bool check_tag(const Instruction &instruction)
Checks whether the tag operand of an instruction is a valid MemoryTag. Called by bytecode managers du...
@ INSTRUCTION_OUT_OF_RANGE
const std::vector< OperandType > three_operand_format16
Instruction deserialize_instruction(std::span< const uint8_t > bytecode, size_t pos)
Attempts to deserialize the instruction at position pos in bytecode. Called by bytecode managers duri...
const std::vector< OperandType > kernel_input_operand_format
const std::vector< OperandType > three_operand_format8
std::string to_hex(T value)
bool is_operand_relative(uint16_t indirect_flag, size_t operand_index)
Checks if the operand at the given index is relative.
const std::unordered_map< WireOpCode, WireInstructionSpec > & get_wire_instruction_spec()
bool is_operand_indirect(uint16_t indirect_flag, size_t operand_index)
Checks if the operand at the given index is indirect.
void read(B &it, field2< base_field, Params > &value)
void read(auto &it, msgpack_concepts::HasMsgPack auto &obj)
Automatically derived read for any object that defines .msgpack() (implicitly defined by SERIALIZATIO...
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
std::string to_string(bb::avm2::ValueTag tag)
std::vector< uint8_t > to_buffer(T const &value)
unsigned __int128 uint128_t
std::string to_string() const
std::vector< uint8_t > serialize() const
std::vector< Operand > operands
size_t size_in_bytes() const
ExecutionOpCode get_exec_opcode() const