New DynamicRegisterValue for inspecting and manipulating register bit fields, via bit field descriptors
This commit is contained in:
@@ -15,6 +15,7 @@ target_sources(
|
|||||||
${CMAKE_CURRENT_SOURCE_DIR}/TargetVariantDescriptor.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/TargetVariantDescriptor.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/TargetMemoryCache.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/TargetMemoryCache.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/TargetPhysicalInterface.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/TargetPhysicalInterface.cpp
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/DynamicRegisterValue.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/TargetDescription/TargetDescriptionFile.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/TargetDescription/TargetDescriptionFile.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/Microchip/AVR8/Avr8.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/Microchip/AVR8/Avr8.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/Microchip/AVR8/Avr8TargetConfig.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/Microchip/AVR8/Avr8TargetConfig.cpp
|
||||||
|
|||||||
89
src/Targets/DynamicRegisterValue.cpp
Normal file
89
src/Targets/DynamicRegisterValue.cpp
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
#include "DynamicRegisterValue.hpp"
|
||||||
|
|
||||||
|
#include <bitset>
|
||||||
|
|
||||||
|
namespace Targets
|
||||||
|
{
|
||||||
|
DynamicRegisterValue::DynamicRegisterValue(const TargetRegisterDescriptorAndValuePair& pair)
|
||||||
|
: DynamicRegisterValue(pair.first, pair.second)
|
||||||
|
{}
|
||||||
|
|
||||||
|
DynamicRegisterValue::DynamicRegisterValue(
|
||||||
|
const TargetRegisterDescriptor& registerDescriptor,
|
||||||
|
TargetMemoryBufferSpan value
|
||||||
|
)
|
||||||
|
: registerDescriptor(registerDescriptor)
|
||||||
|
, value(std::uint64_t{0})
|
||||||
|
{
|
||||||
|
assert(registerDescriptor.size <= 8);
|
||||||
|
assert(value.size() == this->registerDescriptor.size);
|
||||||
|
|
||||||
|
for (const auto byte : value) {
|
||||||
|
this->value = (this->value << 8) | byte;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DynamicRegisterValue::DynamicRegisterValue(const TargetRegisterDescriptor& registerDescriptor, std::uint64_t value)
|
||||||
|
: registerDescriptor(registerDescriptor)
|
||||||
|
, value(value)
|
||||||
|
{
|
||||||
|
assert(registerDescriptor.size <= 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DynamicRegisterValue::setBitField(
|
||||||
|
const TargetBitFieldDescriptor& bitFieldDescriptor,
|
||||||
|
std::uint64_t inputValue
|
||||||
|
) {
|
||||||
|
auto valueBitset = std::bitset<64>{this->value};
|
||||||
|
|
||||||
|
const auto maskBitset = std::bitset<64>{bitFieldDescriptor.mask};
|
||||||
|
auto inputValueIndex = std::size_t{0};
|
||||||
|
for (auto maskIndex = std::size_t{0}; maskIndex < maskBitset.size(); ++maskIndex) {
|
||||||
|
if (maskBitset[maskIndex]) {
|
||||||
|
valueBitset.set(maskIndex, static_cast<bool>(inputValue & (0x01 << inputValueIndex++)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this->value = valueBitset.to_ullong();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DynamicRegisterValue::setBitField(const std::string& bitFieldKey, std::uint64_t value) {
|
||||||
|
return this->setBitField(this->registerDescriptor.getBitFieldDescriptor(bitFieldKey), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::uint64_t DynamicRegisterValue::bitField(const TargetBitFieldDescriptor& bitFieldDescriptor) const {
|
||||||
|
auto output = std::bitset<64>{0};
|
||||||
|
|
||||||
|
const auto maskBitset = std::bitset<64>{bitFieldDescriptor.mask};
|
||||||
|
auto outputIndex = std::size_t{0};
|
||||||
|
for (auto maskIndex = std::size_t{0}; maskIndex < maskBitset.size(); ++maskIndex) {
|
||||||
|
if (maskBitset[maskIndex]) {
|
||||||
|
output.set(outputIndex++, static_cast<bool>(this->value & (0x01 << maskIndex)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return output.to_ullong();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::uint64_t DynamicRegisterValue::bitField(const std::string& bitFieldKey) const {
|
||||||
|
return this->bitField(this->registerDescriptor.getBitFieldDescriptor(bitFieldKey));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DynamicRegisterValue::bitFieldFlag(const TargetBitFieldDescriptor& bitFieldDescriptor) const {
|
||||||
|
return static_cast<bool>(this->bitField(bitFieldDescriptor));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DynamicRegisterValue::bitFieldFlag(const std::string& bitFieldKey) const {
|
||||||
|
return this->bitFieldFlag(this->registerDescriptor.getBitFieldDescriptor(bitFieldKey));
|
||||||
|
}
|
||||||
|
|
||||||
|
TargetMemoryBuffer DynamicRegisterValue::data() const {
|
||||||
|
auto output = TargetMemoryBuffer(this->registerDescriptor.size, 0x00);
|
||||||
|
|
||||||
|
for (auto i = TargetMemorySize{0}; i < this->registerDescriptor.size; ++i) {
|
||||||
|
output[i] = static_cast<unsigned char>(this->value >> ((this->registerDescriptor.size - i - 1) * 8));
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
}
|
||||||
32
src/Targets/DynamicRegisterValue.hpp
Normal file
32
src/Targets/DynamicRegisterValue.hpp
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "TargetRegisterDescriptor.hpp"
|
||||||
|
#include "TargetBitFieldDescriptor.hpp"
|
||||||
|
#include "TargetMemory.hpp"
|
||||||
|
|
||||||
|
namespace Targets
|
||||||
|
{
|
||||||
|
class DynamicRegisterValue
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const TargetRegisterDescriptor& registerDescriptor;
|
||||||
|
std::uint64_t value;
|
||||||
|
|
||||||
|
explicit DynamicRegisterValue(const TargetRegisterDescriptorAndValuePair& pair);
|
||||||
|
DynamicRegisterValue(const TargetRegisterDescriptor& registerDescriptor, TargetMemoryBufferSpan value);
|
||||||
|
DynamicRegisterValue(const TargetRegisterDescriptor& registerDescriptor, std::uint64_t value);
|
||||||
|
|
||||||
|
void setBitField(const TargetBitFieldDescriptor& bitFieldDescriptor, std::uint64_t inputValue);
|
||||||
|
void setBitField(const std::string& bitFieldKey, std::uint64_t inputValue);
|
||||||
|
|
||||||
|
[[nodiscard]] std::uint64_t bitField(const TargetBitFieldDescriptor& bitFieldDescriptor) const;
|
||||||
|
[[nodiscard]] std::uint64_t bitField(const std::string& bitFieldKey) const;
|
||||||
|
[[nodiscard]] bool bitFieldFlag(const TargetBitFieldDescriptor& bitFieldDescriptor) const;
|
||||||
|
[[nodiscard]] bool bitFieldFlag(const std::string& bitFieldKey) const;
|
||||||
|
|
||||||
|
[[nodiscard]] TargetMemoryBuffer data() const;
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -309,6 +309,28 @@ namespace Targets::RiscV
|
|||||||
return this->programmingMode;
|
return this->programmingMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TargetMemoryBuffer RiscV::readRegister(const TargetRegisterDescriptor& descriptor) {
|
||||||
|
return this->readRegisters({&descriptor}).front().second;
|
||||||
|
}
|
||||||
|
|
||||||
|
DynamicRegisterValue RiscV::readRegisterDynamicValue(const TargetRegisterDescriptor& descriptor) {
|
||||||
|
return DynamicRegisterValue{descriptor, this->readRegister(descriptor)};
|
||||||
|
}
|
||||||
|
|
||||||
|
void RiscV::writeRegister(const TargetRegisterDescriptor& descriptor, TargetMemoryBufferSpan value) {
|
||||||
|
this->writeRegisters({{descriptor, TargetMemoryBuffer{value.begin(), value.end()}}});
|
||||||
|
}
|
||||||
|
|
||||||
|
void RiscV::writeRegister(const TargetRegisterDescriptor& descriptor, std::uint64_t value) {
|
||||||
|
auto data = TargetMemoryBuffer(descriptor.size, 0x00);
|
||||||
|
|
||||||
|
for (auto i = TargetMemorySize{0}; i < descriptor.size; ++i) {
|
||||||
|
data[i] = static_cast<unsigned char>(value >> ((descriptor.size - i - 1) * 8));
|
||||||
|
}
|
||||||
|
|
||||||
|
this->writeRegister(descriptor, data);
|
||||||
|
}
|
||||||
|
|
||||||
bool RiscV::probeMemory(
|
bool RiscV::probeMemory(
|
||||||
const TargetAddressSpaceDescriptor& addressSpaceDescriptor,
|
const TargetAddressSpaceDescriptor& addressSpaceDescriptor,
|
||||||
const TargetMemorySegmentDescriptor& memorySegmentDescriptor,
|
const TargetMemorySegmentDescriptor& memorySegmentDescriptor,
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
#include "src/Targets/TargetAddressSpaceDescriptor.hpp"
|
#include "src/Targets/TargetAddressSpaceDescriptor.hpp"
|
||||||
#include "src/Targets/TargetRegisterGroupDescriptor.hpp"
|
#include "src/Targets/TargetRegisterGroupDescriptor.hpp"
|
||||||
|
#include "src/Targets/DynamicRegisterValue.hpp"
|
||||||
|
|
||||||
#include "src/DebugToolDrivers/TargetInterfaces/RiscV/RiscVDebugInterface.hpp"
|
#include "src/DebugToolDrivers/TargetInterfaces/RiscV/RiscVDebugInterface.hpp"
|
||||||
|
|
||||||
@@ -122,6 +123,11 @@ namespace Targets::RiscV
|
|||||||
|
|
||||||
bool programmingMode = false;
|
bool programmingMode = false;
|
||||||
|
|
||||||
|
TargetMemoryBuffer readRegister(const TargetRegisterDescriptor& descriptor);
|
||||||
|
DynamicRegisterValue readRegisterDynamicValue(const TargetRegisterDescriptor& descriptor);
|
||||||
|
void writeRegister(const TargetRegisterDescriptor& descriptor, TargetMemoryBufferSpan value);
|
||||||
|
void writeRegister(const TargetRegisterDescriptor& descriptor, std::uint64_t value);
|
||||||
|
|
||||||
bool probeMemory(
|
bool probeMemory(
|
||||||
const TargetAddressSpaceDescriptor& addressSpaceDescriptor,
|
const TargetAddressSpaceDescriptor& addressSpaceDescriptor,
|
||||||
const TargetMemorySegmentDescriptor& memorySegmentDescriptor,
|
const TargetMemorySegmentDescriptor& memorySegmentDescriptor,
|
||||||
|
|||||||
Reference in New Issue
Block a user