Retrieving AVR8 target registers and including them in the TargetDescriptor
This commit is contained in:
@@ -39,6 +39,78 @@ void Avr8::initFromTargetDescriptionFile() {
|
|||||||
this->targetParameters = this->targetDescriptionFile->getTargetParameters();
|
this->targetParameters = this->targetDescriptionFile->getTargetParameters();
|
||||||
this->padDescriptorsByName = this->targetDescriptionFile->getPadDescriptorsMappedByName();
|
this->padDescriptorsByName = this->targetDescriptionFile->getPadDescriptorsMappedByName();
|
||||||
this->targetVariantsById = this->targetDescriptionFile->getVariantsMappedById();
|
this->targetVariantsById = this->targetDescriptionFile->getVariantsMappedById();
|
||||||
|
|
||||||
|
if (!this->targetParameters->stackPointerRegisterLowAddress.has_value()) {
|
||||||
|
throw Exception("Failed to load sufficient AVR8 target paramters - missting stack pointer start address");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this->targetParameters->statusRegisterStartAddress.has_value()) {
|
||||||
|
throw Exception("Failed to load sufficient AVR8 target parameters - missting status register start address");
|
||||||
|
}
|
||||||
|
|
||||||
|
this->loadTargetRegisterDescriptors();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Avr8::loadTargetRegisterDescriptors() {
|
||||||
|
this->targetRegisterDescriptorsByType = this->targetDescriptionFile->getRegisterDescriptorsMappedByType();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* All AVR8 targets possess 32 general purpose CPU registers. These are not described in the TDF, so we
|
||||||
|
* construct the descriptors for them here.
|
||||||
|
*/
|
||||||
|
for (std::uint8_t i = 0; i <= 31; i++) {
|
||||||
|
auto generalPurposeRegisterDescriptor = TargetRegisterDescriptor();
|
||||||
|
generalPurposeRegisterDescriptor.id = i;
|
||||||
|
generalPurposeRegisterDescriptor.startAddress =
|
||||||
|
this->targetParameters->gpRegisterStartAddress.value_or(0) + i;
|
||||||
|
generalPurposeRegisterDescriptor.size = 1;
|
||||||
|
generalPurposeRegisterDescriptor.type = TargetRegisterType::GENERAL_PURPOSE_REGISTER;
|
||||||
|
generalPurposeRegisterDescriptor.name = "R" + std::to_string(i);
|
||||||
|
generalPurposeRegisterDescriptor.groupName = "General Purpose CPU Registers";
|
||||||
|
|
||||||
|
this->targetRegisterDescriptorsByType[generalPurposeRegisterDescriptor.type].emplace_back(
|
||||||
|
generalPurposeRegisterDescriptor
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The SP and SREG registers are described in the TDF, so we could just use the descriptors extracted from the
|
||||||
|
* TDF. The problem with that is, sometimes the SP register consists of two bytes; an SPL and an SPH. These need
|
||||||
|
* to be combined into one register descriptor. This is why we just use what we already have in
|
||||||
|
* this->targetParameters.
|
||||||
|
*/
|
||||||
|
auto stackPointerRegisterDescriptor = TargetRegisterDescriptor();
|
||||||
|
stackPointerRegisterDescriptor.type = TargetRegisterType::STACK_POINTER;
|
||||||
|
stackPointerRegisterDescriptor.startAddress = this->targetParameters->stackPointerRegisterLowAddress.value();
|
||||||
|
stackPointerRegisterDescriptor.size = this->targetParameters->stackPointerRegisterSize.value();
|
||||||
|
stackPointerRegisterDescriptor.name = "SP";
|
||||||
|
stackPointerRegisterDescriptor.groupName = "CPU";
|
||||||
|
stackPointerRegisterDescriptor.description = "Stack Pointer Register";
|
||||||
|
|
||||||
|
auto statusRegisterDescriptor = TargetRegisterDescriptor();
|
||||||
|
statusRegisterDescriptor.type = TargetRegisterType::STATUS_REGISTER;
|
||||||
|
statusRegisterDescriptor.startAddress = this->targetParameters->statusRegisterStartAddress.value();
|
||||||
|
statusRegisterDescriptor.size = this->targetParameters->statusRegisterSize.value();
|
||||||
|
statusRegisterDescriptor.name = "SREG";
|
||||||
|
statusRegisterDescriptor.groupName = "CPU";
|
||||||
|
statusRegisterDescriptor.description = "Status Register";
|
||||||
|
|
||||||
|
auto programCounterRegisterDescriptor = TargetRegisterDescriptor();
|
||||||
|
programCounterRegisterDescriptor.type = TargetRegisterType::PROGRAM_COUNTER;
|
||||||
|
programCounterRegisterDescriptor.size = 4;
|
||||||
|
programCounterRegisterDescriptor.name = "PC";
|
||||||
|
programCounterRegisterDescriptor.groupName = "CPU";
|
||||||
|
programCounterRegisterDescriptor.description = "Program Counter";
|
||||||
|
|
||||||
|
this->targetRegisterDescriptorsByType[stackPointerRegisterDescriptor.type].emplace_back(
|
||||||
|
stackPointerRegisterDescriptor
|
||||||
|
);
|
||||||
|
this->targetRegisterDescriptorsByType[statusRegisterDescriptor.type].emplace_back(
|
||||||
|
statusRegisterDescriptor
|
||||||
|
);
|
||||||
|
this->targetRegisterDescriptorsByType[programCounterRegisterDescriptor.type].emplace_back(
|
||||||
|
programCounterRegisterDescriptor
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
TargetSignature Avr8::getId() {
|
TargetSignature Avr8::getId() {
|
||||||
@@ -153,6 +225,7 @@ TargetDescriptor Avr8Bit::Avr8::getDescriptor() {
|
|||||||
descriptor.id = this->getHumanReadableId();
|
descriptor.id = this->getHumanReadableId();
|
||||||
descriptor.name = this->getName();
|
descriptor.name = this->getName();
|
||||||
descriptor.ramSize = this->targetParameters.value().ramSize.value_or(0);
|
descriptor.ramSize = this->targetParameters.value().ramSize.value_or(0);
|
||||||
|
descriptor.registerDescriptorsByType = this->targetRegisterDescriptorsByType;
|
||||||
|
|
||||||
std::transform(
|
std::transform(
|
||||||
this->targetVariantsById.begin(),
|
this->targetVariantsById.begin(),
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ namespace Bloom::Targets::Microchip::Avr::Avr8Bit
|
|||||||
std::optional<TargetParameters> targetParameters;
|
std::optional<TargetParameters> targetParameters;
|
||||||
std::map<std::string, PadDescriptor> padDescriptorsByName;
|
std::map<std::string, PadDescriptor> padDescriptorsByName;
|
||||||
std::map<int, TargetVariant> targetVariantsById;
|
std::map<int, TargetVariant> targetVariantsById;
|
||||||
|
std::map<TargetRegisterType, std::vector<TargetRegisterDescriptor>> targetRegisterDescriptorsByType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolves the appropriate TDF for the AVR8 target and populates this->targetDescriptionFile.
|
* Resolves the appropriate TDF for the AVR8 target and populates this->targetDescriptionFile.
|
||||||
@@ -40,6 +41,12 @@ namespace Bloom::Targets::Microchip::Avr::Avr8Bit
|
|||||||
*/
|
*/
|
||||||
void initFromTargetDescriptionFile();
|
void initFromTargetDescriptionFile();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Populates this->targetRegisterDescriptorsByType with registers extracted from the TDF, as well as general
|
||||||
|
* purpose and other CPU registers.
|
||||||
|
*/
|
||||||
|
void loadTargetRegisterDescriptors();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extracts the ID from the target's memory.
|
* Extracts the ID from the target's memory.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ using Bloom::Targets::TargetDescription::MemorySegment;
|
|||||||
using Bloom::Targets::TargetDescription::MemorySegmentType;
|
using Bloom::Targets::TargetDescription::MemorySegmentType;
|
||||||
using Bloom::Targets::TargetDescription::Register;
|
using Bloom::Targets::TargetDescription::Register;
|
||||||
using Bloom::Targets::TargetVariant;
|
using Bloom::Targets::TargetVariant;
|
||||||
|
using Bloom::Targets::TargetRegisterDescriptor;
|
||||||
|
|
||||||
TargetDescriptionFile::TargetDescriptionFile(
|
TargetDescriptionFile::TargetDescriptionFile(
|
||||||
const TargetSignature& targetSignature,
|
const TargetSignature& targetSignature,
|
||||||
@@ -93,6 +94,7 @@ void TargetDescriptionFile::init(const QDomDocument& xml) {
|
|||||||
this->loadDebugPhysicalInterfaces();
|
this->loadDebugPhysicalInterfaces();
|
||||||
this->loadPadDescriptors();
|
this->loadPadDescriptors();
|
||||||
this->loadTargetVariants();
|
this->loadTargetVariants();
|
||||||
|
this->loadTargetRegisterDescriptors();
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonObject TargetDescriptionFile::getTargetDescriptionMapping() {
|
QJsonObject TargetDescriptionFile::getTargetDescriptionMapping() {
|
||||||
@@ -460,6 +462,34 @@ void TargetDescriptionFile::loadTargetVariants() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TargetDescriptionFile::loadTargetRegisterDescriptors() {
|
||||||
|
auto& modulesByName = this->modulesMappedByName;
|
||||||
|
auto& peripheralModulesByName = this->peripheralModulesMappedByName;
|
||||||
|
|
||||||
|
for (const auto& [moduleName, module] : modulesByName) {
|
||||||
|
auto moduleRegisterAddressOffset = this->getRegisterAddressOffsetByModuleName(moduleName);
|
||||||
|
for (const auto& [registerGroupName, registerGroup] : module.registerGroupsMappedByName) {
|
||||||
|
for (const auto& [moduleRegisterName, moduleRegister] : registerGroup.registersMappedByName) {
|
||||||
|
if (moduleRegister.size < 1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto registerDescriptor = TargetRegisterDescriptor();
|
||||||
|
registerDescriptor.type = TargetRegisterType::OTHER;
|
||||||
|
registerDescriptor.name = moduleRegisterName;
|
||||||
|
registerDescriptor.groupName = registerGroupName;
|
||||||
|
registerDescriptor.size = moduleRegister.size;
|
||||||
|
registerDescriptor.startAddress = moduleRegister.offset + moduleRegisterAddressOffset;
|
||||||
|
|
||||||
|
if (moduleRegister.caption.has_value() && !moduleRegister.caption->empty()) {
|
||||||
|
registerDescriptor.description = moduleRegister.caption;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->targetRegisterDescriptorsByType[registerDescriptor.type].emplace_back(registerDescriptor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::optional<MemorySegment> TargetDescriptionFile::getFlashMemorySegment() const {
|
std::optional<MemorySegment> TargetDescriptionFile::getFlashMemorySegment() const {
|
||||||
auto& addressMapping = this->addressSpacesMappedById;
|
auto& addressMapping = this->addressSpacesMappedById;
|
||||||
@@ -1068,3 +1098,36 @@ void TargetDescriptionFile::loadUpdiTargetParameters(TargetParameters& targetPar
|
|||||||
targetParameters.lockbitsSegmentStartAddress = lockbitsMemorySegment->startAddress;
|
targetParameters.lockbitsSegmentStartAddress = lockbitsMemorySegment->startAddress;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::uint32_t TargetDescriptionFile::getRegisterAddressOffsetByModuleName(const std::string& moduleName) const {
|
||||||
|
if (this->peripheralModulesMappedByName.contains(moduleName)) {
|
||||||
|
auto& peripheralModule = this->peripheralModulesMappedByName.at(moduleName);
|
||||||
|
|
||||||
|
if (peripheralModule.instancesMappedByName.contains(moduleName)) {
|
||||||
|
auto& moduleInstance = peripheralModule.instancesMappedByName.at(moduleName);
|
||||||
|
|
||||||
|
if (moduleInstance.registerGroupsMappedByName.contains(moduleName)) {
|
||||||
|
auto& registerGroup = moduleInstance.registerGroupsMappedByName.at(moduleName);
|
||||||
|
|
||||||
|
if (!registerGroup.moduleName.has_value() || registerGroup.moduleName.value() == moduleName) {
|
||||||
|
return registerGroup.offset.value_or(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we get here, that means we couldn't find the right register group by module name. This will happen
|
||||||
|
* if the register group name doesn't match the module name attribute ("name-in-module") against the
|
||||||
|
* register group node, in the TDF.
|
||||||
|
*
|
||||||
|
* As a final attempt, we'll brute force search all register groups in the module instance.
|
||||||
|
*/
|
||||||
|
for (const auto& [registerGroupName, registerGroup] : moduleInstance.registerGroupsMappedByName) {
|
||||||
|
if (registerGroup.moduleName.has_value() && registerGroup.moduleName.value() == moduleName) {
|
||||||
|
return registerGroup.offset.value_or(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|||||||
@@ -55,6 +55,8 @@ namespace Bloom::Targets::Microchip::Avr::Avr8Bit::TargetDescription
|
|||||||
std::map<std::string, PadDescriptor> padDescriptorsByName;
|
std::map<std::string, PadDescriptor> padDescriptorsByName;
|
||||||
std::map<int, TargetVariant> targetVariantsById;
|
std::map<int, TargetVariant> targetVariantsById;
|
||||||
|
|
||||||
|
std::map<TargetRegisterType, TargetRegisterDescriptors> targetRegisterDescriptorsByType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Populates this->supportedDebugPhysicalInterfaces with physical interfaces defined in the TDF.
|
* Populates this->supportedDebugPhysicalInterfaces with physical interfaces defined in the TDF.
|
||||||
*/
|
*/
|
||||||
@@ -70,6 +72,11 @@ namespace Bloom::Targets::Microchip::Avr::Avr8Bit::TargetDescription
|
|||||||
*/
|
*/
|
||||||
void loadTargetVariants();
|
void loadTargetVariants();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads all register descriptors from the TDF, and populates this->targetRegisterDescriptorsByType.
|
||||||
|
*/
|
||||||
|
void loadTargetRegisterDescriptors();
|
||||||
|
|
||||||
[[nodiscard]] std::optional<Targets::TargetDescription::MemorySegment> getFlashMemorySegment() const;
|
[[nodiscard]] std::optional<Targets::TargetDescription::MemorySegment> getFlashMemorySegment() const;
|
||||||
[[nodiscard]] std::optional<Targets::TargetDescription::MemorySegment> getRamMemorySegment() const;
|
[[nodiscard]] std::optional<Targets::TargetDescription::MemorySegment> getRamMemorySegment() const;
|
||||||
[[nodiscard]] std::optional<Targets::TargetDescription::MemorySegment> getIoMemorySegment() const;
|
[[nodiscard]] std::optional<Targets::TargetDescription::MemorySegment> getIoMemorySegment() const;
|
||||||
@@ -117,6 +124,14 @@ namespace Bloom::Targets::Microchip::Avr::Avr8Bit::TargetDescription
|
|||||||
*/
|
*/
|
||||||
virtual void loadUpdiTargetParameters(TargetParameters& targetParameters) const;
|
virtual void loadUpdiTargetParameters(TargetParameters& targetParameters) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the register address offset, for registers from a particular module.
|
||||||
|
*
|
||||||
|
* @param moduleName
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
[[nodiscard]] virtual std::uint32_t getRegisterAddressOffsetByModuleName(const std::string& moduleName) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* Will resolve the target description file using the target description JSON mapping and a given target signature.
|
* Will resolve the target description file using the target description JSON mapping and a given target signature.
|
||||||
@@ -177,6 +192,15 @@ namespace Bloom::Targets::Microchip::Avr::Avr8Bit::TargetDescription
|
|||||||
|
|
||||||
[[nodiscard]] const auto& getVariantsMappedById() const {
|
[[nodiscard]] const auto& getVariantsMappedById() const {
|
||||||
return this->targetVariantsById;
|
return this->targetVariantsById;
|
||||||
};
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a mapping of all target register descriptors extracted from the TDF, by type.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
[[nodiscard]] const auto& getRegisterDescriptorsMappedByType() const {
|
||||||
|
return this->targetRegisterDescriptorsByType;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ namespace Bloom::Targets::TargetDescription
|
|||||||
struct Register
|
struct Register
|
||||||
{
|
{
|
||||||
std::string name;
|
std::string name;
|
||||||
|
std::optional<std::string> caption;
|
||||||
std::uint16_t offset;
|
std::uint16_t offset;
|
||||||
std::uint16_t size;
|
std::uint16_t size;
|
||||||
};
|
};
|
||||||
@@ -17,6 +18,7 @@ namespace Bloom::Targets::TargetDescription
|
|||||||
struct RegisterGroup
|
struct RegisterGroup
|
||||||
{
|
{
|
||||||
std::string name;
|
std::string name;
|
||||||
|
std::optional<std::string> moduleName;
|
||||||
std::optional<std::uint16_t> offset;
|
std::optional<std::uint16_t> offset;
|
||||||
std::map<std::string, Register> registersMappedByName;
|
std::map<std::string, Register> registersMappedByName;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -169,6 +169,10 @@ RegisterGroup TargetDescriptionFile::generateRegisterGroupFromXml(const QDomElem
|
|||||||
throw Exception("Empty register group name");
|
throw Exception("Empty register group name");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
registerGroup.moduleName = xmlElement.hasAttribute("name-in-module")
|
||||||
|
? xmlElement.attribute("name-in-module").toLower().toStdString()
|
||||||
|
: registerGroup.name;
|
||||||
|
|
||||||
if (xmlElement.hasAttribute("offset")) {
|
if (xmlElement.hasAttribute("offset")) {
|
||||||
registerGroup.offset = xmlElement.attribute("offset").toInt(nullptr, 16);
|
registerGroup.offset = xmlElement.attribute("offset").toInt(nullptr, 16);
|
||||||
}
|
}
|
||||||
@@ -207,6 +211,10 @@ Register TargetDescriptionFile::generateRegisterFromXml(const QDomElement& xmlEl
|
|||||||
throw Exception("Empty register name");
|
throw Exception("Empty register name");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (xmlElement.hasAttribute("caption")) {
|
||||||
|
reg.caption = xmlElement.attribute("caption").toStdString();
|
||||||
|
}
|
||||||
|
|
||||||
bool conversionStatus;
|
bool conversionStatus;
|
||||||
reg.size = xmlElement.attribute("size").toUShort(nullptr, 10);
|
reg.size = xmlElement.attribute("size").toUShort(nullptr, 10);
|
||||||
reg.offset = xmlElement.attribute("offset").toUShort(&conversionStatus, 16);
|
reg.offset = xmlElement.attribute("offset").toUShort(&conversionStatus, 16);
|
||||||
|
|||||||
@@ -3,7 +3,9 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#include "TargetRegister.hpp"
|
||||||
#include "TargetVariant.hpp"
|
#include "TargetVariant.hpp"
|
||||||
|
|
||||||
namespace Bloom::Targets
|
namespace Bloom::Targets
|
||||||
@@ -13,6 +15,7 @@ namespace Bloom::Targets
|
|||||||
std::string name;
|
std::string name;
|
||||||
std::string id;
|
std::string id;
|
||||||
std::uint32_t ramSize;
|
std::uint32_t ramSize;
|
||||||
|
std::map<TargetRegisterType, std::vector<TargetRegisterDescriptor>> registerDescriptorsByType;
|
||||||
std::vector<TargetVariant> variants;
|
std::vector<TargetVariant> variants;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,14 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <optional>
|
||||||
|
#include <cstdint>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
|
#include "TargetMemory.hpp"
|
||||||
|
|
||||||
namespace Bloom::Targets
|
namespace Bloom::Targets
|
||||||
{
|
{
|
||||||
enum class TargetRegisterType: int
|
enum class TargetRegisterType: int
|
||||||
@@ -17,12 +22,18 @@ namespace Bloom::Targets
|
|||||||
|
|
||||||
struct TargetRegisterDescriptor
|
struct TargetRegisterDescriptor
|
||||||
{
|
{
|
||||||
std::optional<size_t> id;
|
std::optional<std::uint32_t> startAddress;
|
||||||
|
std::uint32_t size = 0;
|
||||||
TargetRegisterType type = TargetRegisterType::OTHER;
|
TargetRegisterType type = TargetRegisterType::OTHER;
|
||||||
|
|
||||||
|
std::optional<std::size_t> id;
|
||||||
|
std::optional<std::string> name = "";
|
||||||
|
std::optional<std::string> groupName;
|
||||||
|
std::optional<std::string> description;
|
||||||
|
|
||||||
TargetRegisterDescriptor() = default;
|
TargetRegisterDescriptor() = default;
|
||||||
explicit TargetRegisterDescriptor(TargetRegisterType type): type(type) {};
|
explicit TargetRegisterDescriptor(TargetRegisterType type): type(type) {};
|
||||||
TargetRegisterDescriptor(size_t id, TargetRegisterType type): id(id), type(type) {};
|
TargetRegisterDescriptor(std::size_t id, TargetRegisterType type): id(id), type(type) {};
|
||||||
|
|
||||||
bool operator == (const TargetRegisterDescriptor& other) const {
|
bool operator == (const TargetRegisterDescriptor& other) const {
|
||||||
return this->id == other.id && this->type == other.type;
|
return this->id == other.id && this->type == other.type;
|
||||||
@@ -32,22 +43,23 @@ namespace Bloom::Targets
|
|||||||
struct TargetRegister
|
struct TargetRegister
|
||||||
{
|
{
|
||||||
TargetRegisterDescriptor descriptor;
|
TargetRegisterDescriptor descriptor;
|
||||||
std::vector<unsigned char> value;
|
TargetMemoryBuffer value;
|
||||||
|
|
||||||
TargetRegister(TargetRegisterDescriptor descriptor, std::vector<unsigned char> value): value(std::move(value)),
|
TargetRegister(TargetRegisterDescriptor descriptor, std::vector<unsigned char> value): value(std::move(value)),
|
||||||
descriptor(descriptor) {};
|
descriptor(std::move(descriptor)) {};
|
||||||
|
|
||||||
[[nodiscard]] size_t size() const {
|
[[nodiscard]] std::size_t size() const {
|
||||||
return this->value.size();
|
return this->value.size();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
using TargetRegisterMap = std::map<size_t, TargetRegister>;
|
using TargetRegisterMap = std::map<std::size_t, TargetRegister>;
|
||||||
using TargetRegisters = std::vector<TargetRegister>;
|
using TargetRegisters = std::vector<TargetRegister>;
|
||||||
using TargetRegisterDescriptors = std::vector<TargetRegisterDescriptor>;
|
using TargetRegisterDescriptors = std::vector<TargetRegisterDescriptor>;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace std {
|
namespace std
|
||||||
|
{
|
||||||
/**
|
/**
|
||||||
* Hashing function for TargetRegisterDescriptor type.
|
* Hashing function for TargetRegisterDescriptor type.
|
||||||
*
|
*
|
||||||
@@ -55,10 +67,11 @@ namespace std {
|
|||||||
* class)
|
* class)
|
||||||
*/
|
*/
|
||||||
template<>
|
template<>
|
||||||
class hash<Bloom::Targets::TargetRegisterDescriptor> {
|
class hash<Bloom::Targets::TargetRegisterDescriptor>
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
size_t operator()(const Bloom::Targets::TargetRegisterDescriptor& descriptor) const {
|
std::size_t operator()(const Bloom::Targets::TargetRegisterDescriptor& descriptor) const {
|
||||||
return descriptor.id.value_or(0) + static_cast<size_t>(descriptor.type);
|
return descriptor.startAddress.value_or(0) + static_cast<std::size_t>(descriptor.type);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user