2023-09-07 23:31:29 +01:00
|
|
|
#include "Decoder.hpp"
|
|
|
|
|
|
|
|
|
|
#include <iterator>
|
|
|
|
|
|
|
|
|
|
#include "Opcodes.hpp"
|
|
|
|
|
|
|
|
|
|
#include "Exceptions/DecodeFailure.hpp"
|
|
|
|
|
|
|
|
|
|
namespace Targets::Microchip::Avr::Avr8Bit::OpcodeDecoder
|
|
|
|
|
{
|
|
|
|
|
Decoder::InstructionMapping Decoder::decode(
|
|
|
|
|
Targets::TargetMemoryAddress startByteAddress,
|
|
|
|
|
const TargetMemoryBuffer& data,
|
|
|
|
|
bool throwOnFailure
|
|
|
|
|
) {
|
|
|
|
|
auto output = Decoder::InstructionMapping();
|
|
|
|
|
|
|
|
|
|
static const auto decoders = Decoder::opcodeDecoders();
|
|
|
|
|
|
|
|
|
|
auto instructionByteAddress = startByteAddress;
|
|
|
|
|
auto dataIt = data.begin();
|
|
|
|
|
const auto dataEndIt = data.end();
|
|
|
|
|
|
|
|
|
|
while(dataIt != dataEndIt) {
|
|
|
|
|
auto opcodeMatched = false;
|
2023-09-14 21:10:57 +01:00
|
|
|
const auto wordAvailable = std::distance(dataIt, dataEndIt) >= 2;
|
2023-09-07 23:31:29 +01:00
|
|
|
|
|
|
|
|
for (const auto& decoder : decoders) {
|
|
|
|
|
auto instruction = decoder(dataIt, dataEndIt);
|
|
|
|
|
|
|
|
|
|
if (instruction.has_value()) {
|
|
|
|
|
const auto instructionSize = instruction->byteSize;
|
|
|
|
|
output.insert(std::pair(instructionByteAddress, std::move(*instruction)));
|
|
|
|
|
|
|
|
|
|
dataIt += instructionSize;
|
|
|
|
|
instructionByteAddress += instructionSize;
|
|
|
|
|
opcodeMatched = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!opcodeMatched) {
|
|
|
|
|
if (throwOnFailure) {
|
|
|
|
|
throw Exceptions::DecodeFailure(
|
|
|
|
|
instructionByteAddress,
|
2023-09-14 21:10:57 +01:00
|
|
|
wordAvailable
|
2023-09-07 23:31:29 +01:00
|
|
|
? static_cast<std::uint32_t>(*(dataIt + 1) << 8) | *dataIt
|
|
|
|
|
: *dataIt
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
output.insert(std::pair(instructionByteAddress, std::nullopt));
|
|
|
|
|
|
2023-09-14 21:10:57 +01:00
|
|
|
if (!wordAvailable) {
|
2023-09-07 23:31:29 +01:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dataIt += 2;
|
|
|
|
|
instructionByteAddress += 2;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return output;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Decoder::OpcodeDecoders Decoder::opcodeDecoders() {
|
|
|
|
|
/*
|
|
|
|
|
* The decoders will be used in the order given here.
|
|
|
|
|
*
|
|
|
|
|
* I've used the same order that is used in the AVR implementation of GDB.
|
|
|
|
|
*/
|
|
|
|
|
return Decoder::OpcodeDecoders({
|
2023-09-14 21:10:57 +01:00
|
|
|
std::bind(&Opcodes::UndefinedOrErased::decode, std::placeholders::_1, std::placeholders::_2),
|
2023-09-07 23:31:29 +01:00
|
|
|
std::bind(&Opcodes::Clc::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Clh::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Cli::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Cln::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Cls::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Clt::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Clv::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Clz::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Sec::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Seh::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Sei::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Sen::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Ses::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Set::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Sev::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Sez::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Bclr::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Bset::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Icall::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Ijmp::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Lpm1::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Lpm2::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Lpm3::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Elpm1::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Elpm2::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Elpm3::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Nop::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Ret::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Reti::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Sleep::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Break::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Wdr::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Spm1::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Spm2::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Adc::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Add::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::And::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Cp::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Cpc::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Cpse::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Eor::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Mov::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Mul::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Or::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Sbc::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Sub::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Clr::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Lsl::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Rol::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Tst::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Andi::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Cbr::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Ldi::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Ser::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Ori::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Sbr::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Cpi::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Sbci::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Subi::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Sbrc::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Sbrs::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Bld::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Bst::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::In::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Out::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Adiw::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Sbiw::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Cbi::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Sbi::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Sbic::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Sbis::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Brcc::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Brcs::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Breq::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Brge::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Brhc::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Brhs::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Brid::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Brie::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Brlo::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Brlt::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Brmi::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Brne::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Brpl::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Brsh::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Brtc::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Brts::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Brvc::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Brvs::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Brbc::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Brbs::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Rcall::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Rjmp::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Call::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Jmp::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Asr::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Com::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Dec::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Inc::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Lsr::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Neg::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Pop::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Push::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Ror::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Swap::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Xch::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Las::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Lac::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Lat::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Movw::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Muls::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Mulsu::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Fmul::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Fmuls::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Fmulsu::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Sts1::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Sts2::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Lds1::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Lds2::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::LddY::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::LddZ::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::LdX1::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::LdX2::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::LdX3::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::LdY1::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::LdY2::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::LdY3::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::LdZ1::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::LdZ2::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::LdZ3::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::StdY::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::StdZ::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::StX1::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::StX2::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::StX3::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::StY1::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::StY2::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::StY3::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::StZ1::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::StZ2::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::StZ3::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Eicall::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Eijmp::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
std::bind(&Opcodes::Des::decode, std::placeholders::_1, std::placeholders::_2),
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|