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}/TargetMemoryCache.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/TargetPhysicalInterface.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/DynamicRegisterValue.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/TargetDescription/TargetDescriptionFile.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/Microchip/AVR8/Avr8.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;
|
||||
}
|
||||
|
||||
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(
|
||||
const TargetAddressSpaceDescriptor& addressSpaceDescriptor,
|
||||
const TargetMemorySegmentDescriptor& memorySegmentDescriptor,
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
#include "src/Targets/TargetAddressSpaceDescriptor.hpp"
|
||||
#include "src/Targets/TargetRegisterGroupDescriptor.hpp"
|
||||
#include "src/Targets/DynamicRegisterValue.hpp"
|
||||
|
||||
#include "src/DebugToolDrivers/TargetInterfaces/RiscV/RiscVDebugInterface.hpp"
|
||||
|
||||
@@ -122,6 +123,11 @@ namespace Targets::RiscV
|
||||
|
||||
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(
|
||||
const TargetAddressSpaceDescriptor& addressSpaceDescriptor,
|
||||
const TargetMemorySegmentDescriptor& memorySegmentDescriptor,
|
||||
|
||||
Reference in New Issue
Block a user