diff --git a/src/Targets/CMakeLists.txt b/src/Targets/CMakeLists.txt index a432955b..cc109daf 100755 --- a/src/Targets/CMakeLists.txt +++ b/src/Targets/CMakeLists.txt @@ -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 diff --git a/src/Targets/DynamicRegisterValue.cpp b/src/Targets/DynamicRegisterValue.cpp new file mode 100644 index 00000000..34b4c626 --- /dev/null +++ b/src/Targets/DynamicRegisterValue.cpp @@ -0,0 +1,89 @@ +#include "DynamicRegisterValue.hpp" + +#include + +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(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(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(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(this->value >> ((this->registerDescriptor.size - i - 1) * 8)); + } + + return output; + } +} diff --git a/src/Targets/DynamicRegisterValue.hpp b/src/Targets/DynamicRegisterValue.hpp new file mode 100644 index 00000000..fb7e6057 --- /dev/null +++ b/src/Targets/DynamicRegisterValue.hpp @@ -0,0 +1,32 @@ +#pragma once + +#include +#include + +#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; + }; +} diff --git a/src/Targets/RiscV/RiscV.cpp b/src/Targets/RiscV/RiscV.cpp index 928433b6..cc1f7a8d 100644 --- a/src/Targets/RiscV/RiscV.cpp +++ b/src/Targets/RiscV/RiscV.cpp @@ -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(value >> ((descriptor.size - i - 1) * 8)); + } + + this->writeRegister(descriptor, data); + } + bool RiscV::probeMemory( const TargetAddressSpaceDescriptor& addressSpaceDescriptor, const TargetMemorySegmentDescriptor& memorySegmentDescriptor, diff --git a/src/Targets/RiscV/RiscV.hpp b/src/Targets/RiscV/RiscV.hpp index a85ff68d..31259e9b 100644 --- a/src/Targets/RiscV/RiscV.hpp +++ b/src/Targets/RiscV/RiscV.hpp @@ -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,