fxos/lib/disassembly.cpp

74 lines
1.4 KiB
C++

#include <fxos/disassembly.h>
#include <optional>
#include <array>
namespace FxOS {
/* Instruction map */
static std::array<std::optional<Instruction>,65536> insmap;
/* Register an instruction at a given opcode. */
void register_instruction(Instruction ins)
{
uint16_t opcode = ins.opcode;
if(insmap[opcode])
{
throw std::logic_error("opcode collision");
}
insmap[opcode] = ins;
}
//---
// Concrete (instanciated) arguments and instructions
//---
ConcreteInstructionArg::ConcreteInstructionArg():
loc {}, type {}, syscall_id {-1}
{
reg_address = -1;
}
ConcreteInstruction::ConcreteInstruction(Instruction &inst):
inst {inst}, jmpt {}, jmpf {}, leader {false}
{
}
//---
// Disassembler interface
//---
Disassembly::Disassembly(Target &target):
m_target {target}, m_instructions {}
{
}
ConcreteInstruction &Disassembly::readins(uint32_t pc)
{
if(pc & 1) throw std::runtime_error("Disassembly::readins at odd PC");
try
{
return m_instructions.at(pc);
}
catch(std::out_of_range &e)
{
uint16_t opcode = m_target.read_u16(pc);
if(!insmap[opcode])
{
throw std::runtime_error("No instruction for opcode");
}
Instruction &inst = *insmap[opcode];
ConcreteInstruction ci(inst);
// std::pair<uint32_t, ConcreteInstruction> p(pc, ci);
// m_instructions.emplace(std::make_pair(pc, ci));
return m_instructions.at(pc);
}
}
} /* namespace FxOS */