Qt/Debugger: Invalidate blocks on manual memory edit

Ensures recompiler isn't executing stale code.
This commit is contained in:
Stenzek 2024-09-09 20:19:26 +10:00
parent 830e0ad3ad
commit eeca12467c
No known key found for this signature in database
3 changed files with 51 additions and 11 deletions

View file

@ -6,9 +6,12 @@
#include "qthost.h" #include "qthost.h"
#include "qtutils.h" #include "qtutils.h"
#include "common/assert.h" #include "core/bus.h"
#include "core/cpu_code_cache.h"
#include "core/cpu_core_private.h" #include "core/cpu_core_private.h"
#include "common/assert.h"
#include <QtCore/QSignalBlocker> #include <QtCore/QSignalBlocker>
#include <QtGui/QCursor> #include <QtGui/QCursor>
#include <QtGui/QFontDatabase> #include <QtGui/QFontDatabase>
@ -568,10 +571,27 @@ void DebuggerWindow::setMemoryViewRegion(Bus::MemoryRegion region)
m_active_memory_region = region; m_active_memory_region = region;
static constexpr auto edit_ram_callback = [](size_t offset, size_t count) {
// shouldn't happen
if (offset > Bus::g_ram_size)
return;
const u32 start_page = static_cast<u32>(offset) / HOST_PAGE_SIZE;
const u32 end_page = static_cast<u32>(offset + count - 1) / HOST_PAGE_SIZE;
for (u32 i = start_page; i <= end_page; i++)
{
if (Bus::g_ram_code_bits[i])
CPU::CodeCache::InvalidateBlocksWithPageIndex(i);
}
};
const PhysicalMemoryAddress start = Bus::GetMemoryRegionStart(region); const PhysicalMemoryAddress start = Bus::GetMemoryRegionStart(region);
const PhysicalMemoryAddress end = Bus::GetMemoryRegionEnd(region); const PhysicalMemoryAddress end = Bus::GetMemoryRegionEnd(region);
m_ui.memoryView->setData(start, Bus::GetMemoryRegionPointer(region), end - start, void* const mem_ptr = Bus::GetMemoryRegionPointer(region);
Bus::IsMemoryRegionWritable(region)); const bool mem_writable = Bus::IsMemoryRegionWritable(region);
const MemoryViewWidget::EditCallback edit_callback =
((region == Bus::MemoryRegion::RAM) ? edit_ram_callback : nullptr);
m_ui.memoryView->setData(start, mem_ptr, end - start, mem_writable, edit_callback);
#define SET_REGION_RADIO_BUTTON(name, rb_region) \ #define SET_REGION_RADIO_BUTTON(name, rb_region) \
do \ do \

View file

@ -8,7 +8,7 @@
MemoryViewWidget::MemoryViewWidget(QWidget* parent /* = nullptr */, size_t address_offset /* = 0 */, MemoryViewWidget::MemoryViewWidget(QWidget* parent /* = nullptr */, size_t address_offset /* = 0 */,
void* data_ptr /* = nullptr */, size_t data_size /* = 0 */, void* data_ptr /* = nullptr */, size_t data_size /* = 0 */,
bool data_editable /* = false */) bool data_editable /* = false */, EditCallback edit_callback /* = nullptr */)
: QAbstractScrollArea(parent) : QAbstractScrollArea(parent)
{ {
m_bytes_per_line = 16; m_bytes_per_line = 16;
@ -19,7 +19,7 @@ MemoryViewWidget::MemoryViewWidget(QWidget* parent /* = nullptr */, size_t addre
connect(horizontalScrollBar(), &QScrollBar::valueChanged, this, &MemoryViewWidget::adjustContent); connect(horizontalScrollBar(), &QScrollBar::valueChanged, this, &MemoryViewWidget::adjustContent);
if (data_ptr) if (data_ptr)
setData(address_offset, data_ptr, data_size, data_editable); setData(address_offset, data_ptr, data_size, data_editable, edit_callback);
} }
MemoryViewWidget::~MemoryViewWidget() = default; MemoryViewWidget::~MemoryViewWidget() = default;
@ -46,13 +46,15 @@ void MemoryViewWidget::updateMetrics()
m_char_height = fm.height(); m_char_height = fm.height();
} }
void MemoryViewWidget::setData(size_t address_offset, void* data_ptr, size_t data_size, bool data_editable) void MemoryViewWidget::setData(size_t address_offset, void* data_ptr, size_t data_size, bool data_editable,
EditCallback edit_callback)
{ {
m_data = data_ptr; m_data = data_ptr;
m_data_size = data_size; m_data_size = data_size;
m_data_editable = data_editable; m_data_editable = data_editable;
m_address_offset = address_offset; m_address_offset = address_offset;
m_selected_address = INVALID_SELECTED_ADDRESS; m_selected_address = INVALID_SELECTED_ADDRESS;
m_edit_callback = edit_callback;
m_last_data_start_offset = 0; m_last_data_start_offset = 0;
m_last_data.clear(); m_last_data.clear();
adjustContent(); adjustContent();
@ -137,7 +139,15 @@ void MemoryViewWidget::keyPressEvent(QKeyEvent* event)
if (m_selection_was_ascii) if (m_selection_was_ascii)
{ {
expandCurrentDataToInclude(m_selected_address); expandCurrentDataToInclude(m_selected_address);
std::memcpy(static_cast<unsigned char*>(m_data) + m_selected_address, &ch, sizeof(unsigned char));
unsigned char* pdata = static_cast<unsigned char*>(m_data) + m_selected_address;
if (static_cast<unsigned char>(ch) != *pdata)
{
*pdata = static_cast<unsigned char>(ch);
if (m_edit_callback)
m_edit_callback(m_selected_address, 1);
}
m_selected_address = std::min(m_selected_address + 1, m_data_size - 1); m_selected_address = std::min(m_selected_address + 1, m_data_size - 1);
forceRefresh(); forceRefresh();
} }
@ -157,7 +167,14 @@ void MemoryViewWidget::keyPressEvent(QKeyEvent* event)
expandCurrentDataToInclude(m_selected_address); expandCurrentDataToInclude(m_selected_address);
unsigned char* pdata = static_cast<unsigned char*>(m_data) + m_selected_address; unsigned char* pdata = static_cast<unsigned char*>(m_data) + m_selected_address;
*pdata = (*pdata & ~(0xf0 >> (m_editing_nibble * 4))) | (nibble << ((1 - m_editing_nibble) * 4)); const unsigned char new_value =
(*pdata & ~(0xf0 >> (m_editing_nibble * 4))) | (nibble << ((1 - m_editing_nibble) * 4));
if (*pdata != new_value)
{
*pdata = new_value;
if (m_edit_callback)
m_edit_callback(m_selected_address, 1);
}
if (m_editing_nibble == 1) if (m_editing_nibble == 1)
{ {

View file

@ -9,16 +9,18 @@
class MemoryViewWidget : public QAbstractScrollArea class MemoryViewWidget : public QAbstractScrollArea
{ {
public:
Q_OBJECT Q_OBJECT
public: public:
using EditCallback = void (*)(size_t offset, size_t bytes);
MemoryViewWidget(QWidget* parent = nullptr, size_t address_offset = 0, void* data_ptr = nullptr, size_t data_size = 0, MemoryViewWidget(QWidget* parent = nullptr, size_t address_offset = 0, void* data_ptr = nullptr, size_t data_size = 0,
bool data_editable = false); bool data_editable = false, EditCallback edit_callback = nullptr);
~MemoryViewWidget(); ~MemoryViewWidget();
size_t addressOffset() const { return m_address_offset; } size_t addressOffset() const { return m_address_offset; }
void setData(size_t address_offset, void* data_ptr, size_t data_size, bool data_editable); void setData(size_t address_offset, void* data_ptr, size_t data_size, bool data_editable, EditCallback edit_callback);
void setHighlightRange(size_t start, size_t end); void setHighlightRange(size_t start, size_t end);
void clearHighlightRange(); void clearHighlightRange();
void scrolltoOffset(size_t offset); void scrolltoOffset(size_t offset);
@ -71,6 +73,7 @@ private:
int m_rows_visible; int m_rows_visible;
EditCallback m_edit_callback = nullptr;
std::vector<u8> m_last_data; std::vector<u8> m_last_data;
size_t m_last_data_start_offset = 0; size_t m_last_data_start_offset = 0;
}; };