Play-/Source/ui_qt/DebugSupport/DisAsmWnd.cpp

651 lines
17 KiB
C++
Raw Normal View History

2019-12-11 21:38:57 +00:00
#include <QAction>
2019-12-12 00:20:49 +00:00
#include <QApplication>
#include <QClipboard>
#include <QVBoxLayout>
2019-12-11 21:38:57 +00:00
#include <QMenu>
2019-12-19 22:20:32 +00:00
#include <QString>
#include <QInputDialog>
#include <QMessageBox>
#include <QHeaderView>
2021-02-13 11:51:05 -05:00
#include <QTextLayout>
2021-03-03 20:23:38 +00:00
#include <cmath>
2019-12-19 22:20:32 +00:00
2019-12-11 14:52:12 +00:00
#include "DisAsmWnd.h"
2019-12-11 21:38:57 +00:00
#include "ee/VuAnalysis.h"
2024-03-21 14:24:08 -04:00
#include "DisAsmTableModel.h"
#include "DisAsmVuTableModel.h"
2019-12-19 22:20:32 +00:00
2019-12-11 21:38:57 +00:00
#include "countof.h"
2019-12-19 22:20:32 +00:00
#include "string_cast.h"
#include "string_format.h"
#include "lexical_cast_ex.h"
#include "DebugExpressionEvaluator.h"
#include "DebugUtils.h"
2019-12-11 14:52:12 +00:00
2024-03-21 14:24:08 -04:00
CDisAsmWnd::CDisAsmWnd(QWidget* parent, CVirtualMachine& virtualMachine, CMIPS* ctx, const char* name, uint64 size, CDisAsmTableModel::DISASM_TYPE disAsmType)
2020-02-05 21:35:11 +00:00
: QTableView(parent)
2019-12-19 22:20:32 +00:00
, m_virtualMachine(virtualMachine)
, m_ctx(ctx)
2019-12-11 21:38:57 +00:00
, m_disAsmType(disAsmType)
2019-12-11 14:52:12 +00:00
{
2019-12-19 14:14:25 +00:00
HistoryReset();
2019-12-11 14:52:12 +00:00
setFont(DebugUtils::CreateMonospaceFont());
2021-02-13 12:13:27 -05:00
2021-02-13 11:51:05 -05:00
m_numericalCellWidth = ComputeNumericalCellWidth();
2021-02-12 11:48:13 -05:00
2019-12-11 14:52:12 +00:00
resize(320, 240);
switch(disAsmType)
{
2024-03-21 14:24:08 -04:00
case CDisAsmTableModel::DISASM_STANDARD:
m_model = new CDisAsmTableModel(this, virtualMachine, ctx, size, 0x100000);
2019-12-19 22:20:32 +00:00
m_instructionSize = 4;
2019-12-11 14:52:12 +00:00
break;
2024-03-21 14:24:08 -04:00
case CDisAsmTableModel::DISASM_VU:
m_model = new CDisAsmVuTableModel(this, virtualMachine, ctx, size, 0);
2019-12-19 22:20:32 +00:00
m_instructionSize = 8;
2019-12-11 14:52:12 +00:00
break;
default:
assert(0);
break;
}
2019-12-19 22:20:32 +00:00
2020-02-05 21:35:11 +00:00
setModel(m_model);
auto header = horizontalHeader();
header->setMinimumSectionSize(1);
2019-12-19 22:20:32 +00:00
header->setSectionResizeMode(0, QHeaderView::ResizeToContents);
header->setSectionResizeMode(1, QHeaderView::ResizeToContents);
header->setSectionResizeMode(2, QHeaderView::ResizeToContents);
header->setSectionResizeMode(3, QHeaderView::ResizeToContents);
2020-08-07 11:45:23 +01:00
header->setSectionResizeMode(4, QHeaderView::Interactive);
header->setSectionResizeMode(5, QHeaderView::Interactive);
2024-03-21 14:24:08 -04:00
if(disAsmType == CDisAsmTableModel::DISASM_STANDARD)
2019-12-19 22:20:32 +00:00
{
header->setSectionResizeMode(6, QHeaderView::Stretch);
}
else
{
header->setSectionResizeMode(6, QHeaderView::Interactive);
header->setSectionResizeMode(7, QHeaderView::Interactive);
2019-12-19 22:20:32 +00:00
header->setSectionResizeMode(8, QHeaderView::Stretch);
}
2020-02-05 21:35:11 +00:00
verticalHeader()->hide();
resizeColumnsToContents();
2019-12-19 22:20:32 +00:00
2020-08-07 11:45:23 +01:00
header->resizeSection(4, 80);
header->resizeSection(5, 160);
2024-03-21 14:24:08 -04:00
if(disAsmType == CDisAsmTableModel::DISASM_VU)
{
header->resizeSection(6, 80);
header->resizeSection(7, 160);
}
2021-01-12 08:58:37 -05:00
2020-02-05 21:35:11 +00:00
setContextMenuPolicy(Qt::CustomContextMenu);
connect(this, &QTableView::customContextMenuRequested, this, &CDisAsmWnd::ShowContextMenu);
2019-12-11 23:41:09 +00:00
2020-02-05 21:35:11 +00:00
setSelectionBehavior(QAbstractItemView::SelectRows);
setSelectionMode(QAbstractItemView::ContiguousSelection);
connect(selectionModel(), &QItemSelectionModel::selectionChanged, this, &CDisAsmWnd::selectionChanged);
2019-12-12 00:20:49 +00:00
2019-12-19 21:37:47 +00:00
QAction* copyAction = new QAction("copy", this);
2019-12-12 00:20:49 +00:00
copyAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_C));
2022-08-07 17:26:52 -04:00
copyAction->setShortcutContext(Qt::WidgetShortcut);
2019-12-12 00:20:49 +00:00
connect(copyAction, &QAction::triggered, this, &CDisAsmWnd::OnCopy);
2020-02-05 21:35:11 +00:00
addAction(copyAction);
2019-12-12 01:18:27 +00:00
2019-12-19 21:37:47 +00:00
QAction* breakpointAction = new QAction("breakpoint toggle", this);
2019-12-12 01:18:27 +00:00
breakpointAction->setShortcut(QKeySequence(Qt::Key_F9));
connect(breakpointAction, &QAction::triggered, this, &CDisAsmWnd::OnListDblClick);
2020-02-05 21:35:11 +00:00
addAction(breakpointAction);
2019-12-12 01:18:27 +00:00
2019-12-19 21:37:47 +00:00
QAction* rightArrowAction = new QAction("Right Arrow", this);
rightArrowAction->setShortcut(QKeySequence(Qt::Key_Right));
2019-12-19 21:37:47 +00:00
connect(rightArrowAction, &QAction::triggered, [&]() {
if(m_selected != MIPS_INVALID_PC)
{
uint32 nOpcode = GetInstruction(m_selected);
if(m_ctx->m_pArch->IsInstructionBranch(m_ctx, m_selected, nOpcode) == MIPS_BRANCH_NORMAL)
{
m_address = m_selected; // Ensure history tracks where we came from
GotoEA();
SetSelectedAddress(m_address);
}
else if(HistoryHasNext())
{
HistoryGoForward();
SetSelectedAddress(m_address);
}
}
});
2020-02-05 21:35:11 +00:00
addAction(rightArrowAction);
2019-12-19 21:37:47 +00:00
QAction* leftArrowAction = new QAction("Left Arrow", this);
leftArrowAction->setShortcut(QKeySequence(Qt::Key_Left));
2019-12-19 21:37:47 +00:00
connect(leftArrowAction, &QAction::triggered, [&]() {
if(HistoryHasPrevious())
{
HistoryGoBack();
SetSelectedAddress(m_address);
}
});
2020-02-05 21:35:11 +00:00
addAction(leftArrowAction);
connect(this, &QTableView::doubleClicked, this, &CDisAsmWnd::OnListDblClick);
2019-12-11 14:52:12 +00:00
}
2021-02-13 11:51:05 -05:00
int CDisAsmWnd::ComputeNumericalCellWidth() const
{
int marginWidth = style()->pixelMetric(QStyle::PM_FocusFrameHMargin, nullptr, this) + 1;
//There's 8 characters in the address and instruction views
QTextLayout layout("00000000", font());
layout.beginLayout();
auto line = layout.createLine();
line.setLineWidth(1000);
int textWidth = ceil(line.naturalTextWidth());
layout.endLayout();
int result = textWidth + (2 * marginWidth) + 1;
return result;
}
2019-12-19 22:08:55 +00:00
void CDisAsmWnd::ShowContextMenu(const QPoint& pos)
2019-12-11 21:38:57 +00:00
{
2019-12-19 21:37:47 +00:00
QMenu* rightClickMenu = new QMenu(this);
2019-12-11 21:38:57 +00:00
2019-12-19 21:37:47 +00:00
QAction* goToPcAction = new QAction(this);
2019-12-11 21:38:57 +00:00
goToPcAction->setText("GoTo PC");
connect(goToPcAction, &QAction::triggered, std::bind(&CDisAsmWnd::GotoPC, this));
rightClickMenu->addAction(goToPcAction);
2019-12-19 21:37:47 +00:00
QAction* goToAddrAction = new QAction(this);
2019-12-11 21:38:57 +00:00
goToAddrAction->setText("Goto Address...");
connect(goToAddrAction, &QAction::triggered, std::bind(&CDisAsmWnd::GotoAddress, this));
rightClickMenu->addAction(goToAddrAction);
2019-12-19 21:37:47 +00:00
QAction* editCommentAction = new QAction(this);
2019-12-11 21:38:57 +00:00
editCommentAction->setText("Edit Comment...");
connect(editCommentAction, &QAction::triggered, std::bind(&CDisAsmWnd::EditComment, this));
rightClickMenu->addAction(editCommentAction);
2019-12-19 21:37:47 +00:00
QAction* findCallerAction = new QAction(this);
2019-12-11 21:38:57 +00:00
findCallerAction->setText("Find Callers");
connect(findCallerAction, &QAction::triggered, std::bind(&CDisAsmWnd::FindCallers, this));
rightClickMenu->addAction(findCallerAction);
2020-02-05 21:35:11 +00:00
auto index = currentIndex();
2019-12-11 21:38:57 +00:00
if(index.isValid())
{
2019-12-11 23:09:02 +00:00
if(m_selected != MIPS_INVALID_PC)
2019-12-11 21:38:57 +00:00
{
uint32 nOpcode = GetInstruction(m_selected);
if(m_ctx->m_pArch->IsInstructionBranch(m_ctx, m_selected, nOpcode) == MIPS_BRANCH_NORMAL)
{
char sTemp[256];
uint32 nAddress = m_ctx->m_pArch->GetInstructionEffectiveAddress(m_ctx, m_selected, nOpcode);
if(nAddress != MIPS_INVALID_PC)
{
snprintf(sTemp, countof(sTemp), ("Go to 0x%08X"), nAddress);
QAction* goToEaAction = new QAction(this);
goToEaAction->setText(sTemp);
connect(goToEaAction, &QAction::triggered, std::bind(&CDisAsmWnd::GotoEA, this));
rightClickMenu->addAction(goToEaAction);
}
2019-12-11 21:38:57 +00:00
}
}
}
if(HistoryHasPrevious())
{
char sTemp[256];
snprintf(sTemp, countof(sTemp), ("Go back (0x%08X)"), HistoryGetPrevious());
2019-12-19 21:37:47 +00:00
QAction* goToEaAction = new QAction(this);
2019-12-11 21:38:57 +00:00
goToEaAction->setText(sTemp);
connect(goToEaAction, &QAction::triggered, std::bind(&CDisAsmWnd::HistoryGoBack, this));
rightClickMenu->addAction(goToEaAction);
}
if(HistoryHasNext())
{
char sTemp[256];
snprintf(sTemp, countof(sTemp), ("Go forward (0x%08X)"), HistoryGetNext());
2019-12-19 21:37:47 +00:00
QAction* goToEaAction = new QAction(this);
2019-12-11 21:38:57 +00:00
goToEaAction->setText(sTemp);
connect(goToEaAction, &QAction::triggered, std::bind(&CDisAsmWnd::HistoryGoForward, this));
rightClickMenu->addAction(goToEaAction);
}
2024-03-21 14:24:08 -04:00
if(m_disAsmType == CDisAsmTableModel::DISASM_VU)
2019-12-11 21:38:57 +00:00
{
2019-12-19 21:37:47 +00:00
QAction* analyseVuction = new QAction(this);
2019-12-11 21:38:57 +00:00
analyseVuction->setText("Analyse Microprogram");
connect(analyseVuction, &QAction::triggered,
2019-12-19 21:37:47 +00:00
[&]() {
CVuAnalysis::Analyse(m_ctx, 0, 0x4000);
m_model->Redraw();
});
2019-12-11 21:38:57 +00:00
rightClickMenu->addAction(analyseVuction);
}
2020-02-05 21:35:11 +00:00
rightClickMenu->popup(viewport()->mapToGlobal(pos));
2019-12-11 21:38:57 +00:00
}
bool CDisAsmWnd::isAddressInView(QModelIndex& index) const
{
auto startRow = indexAt(rect().topLeft());
auto endRow = indexAt(rect().bottomRight());
return index.row() >= startRow.row() && index.row() <= endRow.row();
}
int CDisAsmWnd::sizeHintForColumn(int col) const
{
if(col == 0 || col == 2)
{
2021-02-12 11:48:13 -05:00
//The added units is to account for margins
return m_model->GetLinePixMapWidth() + 11;
}
else
{
2021-02-13 11:51:05 -05:00
return m_numericalCellWidth;
}
}
void CDisAsmWnd::verticalScrollbarValueChanged(int value)
{
auto topLeftIndex = indexAt(rect().topLeft());
m_address = m_model->TranslateModelIndexToAddress(topLeftIndex);
QTableView::verticalScrollbarValueChanged(value);
}
2019-12-19 22:20:32 +00:00
void CDisAsmWnd::SetAddress(uint32 address)
{
2024-03-20 19:33:37 -04:00
m_model->SetWindowCenter(address);
m_model->Redraw();
2021-01-04 18:05:53 +00:00
auto addressRow = m_model->TranslateAddressToModelIndex(address);
if(!isAddressInView(addressRow))
2024-03-20 19:33:37 -04:00
{
scrollTo(addressRow, QAbstractItemView::PositionAtTop);
2024-03-20 19:33:37 -04:00
}
2019-12-19 22:20:32 +00:00
m_address = address;
}
void CDisAsmWnd::SetCenterAtAddress(uint32 address)
{
2024-03-20 19:33:37 -04:00
m_model->SetWindowCenter(address);
m_model->Redraw();
2021-01-04 23:35:49 +00:00
auto addressRow = m_model->TranslateAddressToModelIndex(address);
if(!isAddressInView(addressRow))
2024-03-20 19:33:37 -04:00
{
scrollTo(addressRow, QAbstractItemView::PositionAtCenter);
2024-03-20 19:33:37 -04:00
}
2019-12-11 23:09:02 +00:00
m_address = address;
2019-12-19 22:20:32 +00:00
}
void CDisAsmWnd::SetSelectedAddress(uint32 address)
2019-12-11 14:52:12 +00:00
{
2024-03-20 19:33:37 -04:00
m_model->SetWindowCenter(address);
m_model->Redraw();
2019-12-19 22:20:32 +00:00
m_selectionEnd = -1;
m_selected = address;
2021-01-04 23:35:49 +00:00
auto index = m_model->TranslateAddressToModelIndex(address);
if(!isAddressInView(index))
2024-03-20 19:33:37 -04:00
{
scrollTo(index, QAbstractItemView::PositionAtTop);
2024-03-20 19:33:37 -04:00
}
2020-02-05 21:35:11 +00:00
setCurrentIndex(index);
2019-12-11 14:52:12 +00:00
}
void CDisAsmWnd::HandleMachineStateChange()
{
2019-12-19 22:20:32 +00:00
m_model->Redraw();
2019-12-11 14:52:12 +00:00
}
void CDisAsmWnd::HandleRunningStateChange(CVirtualMachine::STATUS newState)
{
2019-12-19 22:20:32 +00:00
if(newState == CVirtualMachine::STATUS::PAUSED)
{
//Recenter view if we just got into paused state
m_address = m_ctx->m_State.nPC & ~(m_instructionSize - 1);
SetCenterAtAddress(m_address);
}
m_model->Redraw();
2019-12-11 14:52:12 +00:00
}
2019-12-19 22:20:32 +00:00
void CDisAsmWnd::GotoAddress()
{
if(m_virtualMachine.GetStatus() == CVirtualMachine::RUNNING)
{
QApplication::beep();
2019-12-19 22:20:32 +00:00
return;
}
2019-12-11 14:52:12 +00:00
2019-12-19 22:20:32 +00:00
bool ok;
QString sValue = QInputDialog::getText(this, ("Goto Address"),
2019-12-19 21:37:47 +00:00
("Enter new address:"), QLineEdit::Normal,
((("0x") + lexical_cast_hex<std::string>(m_address, 8)).c_str()), &ok);
if(!ok || sValue.isEmpty())
2019-12-19 22:20:32 +00:00
return;
2019-12-11 14:52:12 +00:00
2019-12-19 22:20:32 +00:00
{
try
{
uint32 nAddress = CDebugExpressionEvaluator::Evaluate(sValue.toStdString().c_str(), m_ctx);
if(nAddress & (m_instructionSize - 1))
{
2019-12-18 12:34:04 +00:00
QMessageBox::warning(this, tr("Warning"),
tr("Invalid address"),
2019-12-19 21:37:47 +00:00
QMessageBox::Ok, QMessageBox::Ok);
2019-12-19 22:20:32 +00:00
return;
}
if(m_address != nAddress)
{
HistorySave(m_address);
}
m_address = nAddress;
SetAddress(nAddress);
}
catch(const std::exception& exception)
{
std::string message = std::string("Error evaluating expression: ") + exception.what();
2019-12-18 12:34:04 +00:00
QMessageBox::critical(this, tr("Error"),
2019-12-19 21:37:47 +00:00
tr(message.c_str()),
QMessageBox::Ok, QMessageBox::Ok);
2019-12-19 22:20:32 +00:00
}
}
}
void CDisAsmWnd::GotoPC()
{
if(m_virtualMachine.GetStatus() == CVirtualMachine::RUNNING)
{
QApplication::beep();
2019-12-19 22:20:32 +00:00
return;
}
m_address = m_ctx->m_State.nPC;
SetAddress(m_ctx->m_State.nPC);
}
void CDisAsmWnd::GotoEA()
{
if(m_virtualMachine.GetStatus() == CVirtualMachine::RUNNING)
{
QApplication::beep();
2019-12-19 22:20:32 +00:00
return;
}
uint32 nOpcode = GetInstruction(m_selected);
if(m_ctx->m_pArch->IsInstructionBranch(m_ctx, m_selected, nOpcode) == MIPS_BRANCH_NORMAL)
{
uint32 nAddress = m_ctx->m_pArch->GetInstructionEffectiveAddress(m_ctx, m_selected, nOpcode);
assert(nAddress != MIPS_INVALID_PC);
2019-12-19 22:20:32 +00:00
if(m_address != nAddress)
{
HistorySave(m_address);
}
m_address = nAddress;
SetAddress(nAddress);
}
}
void CDisAsmWnd::EditComment()
{
if(m_virtualMachine.GetStatus() == CVirtualMachine::RUNNING)
{
QApplication::beep();
2019-12-19 22:20:32 +00:00
return;
}
const char* comment = m_ctx->m_Comments.Find(m_selected);
std::string commentConv;
if(comment != nullptr)
{
commentConv = comment;
}
else
{
commentConv = ("");
}
bool ok;
QString value = QInputDialog::getText(this, ("Edit Comment"),
2019-12-19 21:37:47 +00:00
("Enter new comment:"), QLineEdit::Normal,
(commentConv.c_str()), &ok);
2021-01-02 19:00:51 +00:00
if(!ok)
2019-12-19 22:20:32 +00:00
return;
if(!value.isEmpty())
{
m_ctx->m_Comments.InsertTag(m_selected, value.toStdString().c_str());
}
else
{
m_ctx->m_Comments.RemoveTag(m_selected);
}
2023-08-21 20:36:41 -04:00
m_ctx->m_Comments.OnTagListChange();
2019-12-18 12:34:21 +00:00
m_model->Redraw(m_selected);
2019-12-19 22:20:32 +00:00
}
void CDisAsmWnd::FindCallers()
{
if(m_virtualMachine.GetStatus() == CVirtualMachine::RUNNING)
{
QApplication::beep();
2019-12-19 22:20:32 +00:00
return;
}
FindCallersRequested(m_selected);
}
CDisAsmWnd::SelectionRangeType CDisAsmWnd::GetSelectionRange()
{
if(m_selectionEnd == -1)
{
return SelectionRangeType(m_selected, m_selected);
}
if(m_selectionEnd > m_selected)
{
return SelectionRangeType(m_selected, m_selectionEnd);
}
else
{
return SelectionRangeType(m_selectionEnd, m_selected);
}
}
void CDisAsmWnd::HistoryReset()
{
m_historyPosition = -1;
m_historySize = 0;
memset(m_history, 0, sizeof(uint32) * HISTORY_STACK_MAX);
}
void CDisAsmWnd::HistorySave(uint32 nAddress)
{
if(m_historySize == HISTORY_STACK_MAX)
{
memmove(m_history + 1, m_history, HISTORY_STACK_MAX - 1);
m_historySize--;
}
m_history[m_historySize] = nAddress;
m_historyPosition = m_historySize;
m_historySize++;
}
void CDisAsmWnd::HistoryGoBack()
{
if(m_historyPosition == -1) return;
uint32 address = HistoryGetPrevious();
m_history[m_historyPosition] = m_address;
m_address = address;
2019-12-11 14:52:12 +00:00
2019-12-19 22:20:32 +00:00
m_historyPosition--;
SetAddress(address);
}
void CDisAsmWnd::HistoryGoForward()
{
if(m_historyPosition == m_historySize) return;
uint32 address = HistoryGetNext();
m_historyPosition++;
m_history[m_historyPosition] = m_address;
m_address = address;
SetAddress(address);
}
uint32 CDisAsmWnd::HistoryGetPrevious()
{
return m_history[m_historyPosition];
}
uint32 CDisAsmWnd::HistoryGetNext()
{
if(m_historyPosition == m_historySize) return 0;
return m_history[m_historyPosition + 1];
}
bool CDisAsmWnd::HistoryHasPrevious()
{
return (m_historySize != 0) && (m_historyPosition != -1);
}
bool CDisAsmWnd::HistoryHasNext()
{
return (m_historySize != 0) && (m_historyPosition != (m_historySize - 1));
}
uint32 CDisAsmWnd::GetInstruction(uint32 address)
{
2024-03-20 19:33:37 -04:00
uint32 physAddr = m_ctx->m_pAddrTranslator(m_ctx, address);
return m_ctx->m_pMemoryMap->GetInstruction(physAddr);
2019-12-19 22:20:32 +00:00
}
void CDisAsmWnd::ToggleBreakpoint(uint32 address)
{
if(m_virtualMachine.GetStatus() == CVirtualMachine::RUNNING)
{
QApplication::beep();
2019-12-19 22:20:32 +00:00
return;
}
uint32 physAddress = m_ctx->m_pAddrTranslator(m_ctx, address);
m_ctx->ToggleBreakpoint(physAddress);
2019-12-19 22:20:32 +00:00
m_model->Redraw(address);
}
2019-12-11 23:41:09 +00:00
void CDisAsmWnd::selectionChanged()
{
2020-02-05 21:35:11 +00:00
auto indexes = selectionModel()->selectedIndexes();
2019-12-11 23:41:09 +00:00
if(!indexes.empty())
{
2021-01-04 18:05:53 +00:00
auto selected = m_model->TranslateModelIndexToAddress(indexes.first());
auto selectionEnd = m_model->TranslateModelIndexToAddress(indexes.last());
2019-12-11 23:41:09 +00:00
m_selected = selected;
m_selectionEnd = (selectionEnd == selected) ? -1 : selectionEnd;
}
}
2019-12-12 00:20:49 +00:00
void CDisAsmWnd::OnCopy()
{
std::string text;
auto selectionRange = GetSelectionRange();
2024-03-22 17:18:50 -04:00
for(uint32 address = selectionRange.first; address <= selectionRange.second; address += m_instructionSize)
2019-12-12 00:20:49 +00:00
{
if(address != selectionRange.first)
{
text += ("\r\n");
}
2024-03-21 14:24:08 -04:00
if(m_disAsmType == CDisAsmTableModel::DISASM_STANDARD)
2019-12-12 00:20:49 +00:00
{
text += GetInstructionDetailsText(address);
}
else
{
text += GetInstructionDetailsTextVu(address);
}
}
QApplication::clipboard()->setText(text.c_str());
}
std::string CDisAsmWnd::GetInstructionDetailsText(uint32 address)
{
uint32 opcode = GetInstruction(address);
std::string result;
result += lexical_cast_hex<std::string>(address, 8) + (" ");
result += lexical_cast_hex<std::string>(opcode, 8) + (" ");
char disasm[256];
m_ctx->m_pArch->GetInstructionMnemonic(m_ctx, address, opcode, disasm, countof(disasm));
result += disasm;
for(auto j = strlen(disasm); j < 15; j++)
{
result += (" ");
}
m_ctx->m_pArch->GetInstructionOperands(m_ctx, address, opcode, disasm, countof(disasm));
result += disasm;
return result;
}
std::string CDisAsmWnd::GetInstructionDetailsTextVu(uint32 address)
{
uint32 lowerInstruction = GetInstruction(address + 0);
uint32 upperInstruction = GetInstruction(address + 4);
std::string result;
result += lexical_cast_hex<std::string>(address, 8) + (" ");
result += lexical_cast_hex<std::string>(upperInstruction, 8) + (" ") + lexical_cast_hex<std::string>(lowerInstruction, 8) + (" ");
char disasm[256];
m_ctx->m_pArch->GetInstructionMnemonic(m_ctx, address + 4, upperInstruction, disasm, countof(disasm));
result += disasm;
for(auto j = strlen(disasm); j < 15; j++)
{
result += (" ");
}
m_ctx->m_pArch->GetInstructionOperands(m_ctx, address + 4, upperInstruction, disasm, countof(disasm));
result += disasm;
for(auto j = strlen(disasm); j < 31; j++)
{
result += (" ");
}
m_ctx->m_pArch->GetInstructionMnemonic(m_ctx, address + 0, lowerInstruction, disasm, countof(disasm));
result += disasm;
for(auto j = strlen(disasm); j < 16; j++)
{
result += (" ");
}
m_ctx->m_pArch->GetInstructionOperands(m_ctx, address + 0, lowerInstruction, disasm, countof(disasm));
result += disasm;
return result;
}
2019-12-12 01:18:27 +00:00
void CDisAsmWnd::OnListDblClick()
{
ToggleBreakpoint(m_selected);
}