Add formatting options for viewing registers

All formatting are individual per registers and they all have one option to go back to their original hexadecimal form.

- GPR: signed integer, unsigned integer, float
- FPR: double

Also happened to come accross an issue where editing the PFR would ignore the higher 32 bits of the new value, this had to be fixed for the format to work.
This commit is contained in:
aldelaro5 2016-08-31 18:31:39 -04:00 committed by aldelaro5
parent f1964f90d6
commit ea2effcc7d
2 changed files with 258 additions and 42 deletions

View file

@ -27,14 +27,177 @@ enum
{
IDM_WATCHADDRESS,
IDM_VIEWMEMORY,
IDM_VIEWCODE
IDM_VIEWCODE,
IDM_VIEW_HEX8,
IDM_VIEW_HEX16,
IDM_VIEW_FLOAT,
IDM_VIEW_DOUBLE,
IDM_VIEW_UINT,
IDM_VIEW_INT
};
static const char* special_reg_names[] = {"PC", "LR", "CTR", "CR", "FPSCR",
"MSR", "SRR0", "SRR1", "Exceptions", "Int Mask",
"Int Cause", "DSISR", "DAR", "PT hashmask"};
enum class FormatSpecifier
{
Hex8,
Hex16,
Float,
Double,
UInt,
Int
};
static u32 GetSpecialRegValue(int reg)
constexpr const char* special_reg_names[] = {"PC", "LR", "CTR", "CR", "FPSCR",
"MSR", "SRR0", "SRR1", "Exceptions", "Int Mask",
"Int Cause", "DSISR", "DAR", "PT hashmask"};
CRegTable::CRegTable()
{
m_formatRegs.fill(FormatSpecifier::Hex8);
for (auto& entry : m_formatFRegs)
entry.fill(FormatSpecifier::Hex16);
memset(m_CachedRegs, 0, sizeof(m_CachedRegs));
memset(m_CachedSpecialRegs, 0, sizeof(m_CachedSpecialRegs));
memset(m_CachedFRegs, 0, sizeof(m_CachedFRegs));
memset(m_CachedRegHasChanged, 0, sizeof(m_CachedRegHasChanged));
memset(m_CachedSpecialRegHasChanged, 0, sizeof(m_CachedSpecialRegHasChanged));
memset(m_CachedFRegHasChanged, 0, sizeof(m_CachedFRegHasChanged));
}
wxString CRegTable::GetFormatString(FormatSpecifier specifier)
{
switch (specifier)
{
case FormatSpecifier::Hex8:
return wxString("%08x");
case FormatSpecifier::Hex16:
return wxString("%016llx");
case FormatSpecifier::Float:
return wxString("%g");
case FormatSpecifier::Double:
return wxString("%g");
case FormatSpecifier::UInt:
return wxString("%u");
case FormatSpecifier::Int:
return wxString("%i");
default:
return wxString("");
}
}
wxString CRegTable::FormatGPR(int reg_index)
{
if (m_formatRegs[reg_index] == FormatSpecifier::Int)
{
return wxString::Format(GetFormatString(m_formatRegs[reg_index]),
static_cast<s32>(GPR(reg_index)));
}
if (m_formatRegs[reg_index] == FormatSpecifier::Float)
{
float value;
std::memcpy(&value, &GPR(reg_index), sizeof(float));
return wxString::Format(GetFormatString(m_formatRegs[reg_index]), value);
}
return wxString::Format(GetFormatString(m_formatRegs[reg_index]), GPR(reg_index));
}
wxString CRegTable::FormatFPR(int reg_index, int reg_part)
{
if (m_formatFRegs[reg_index][reg_part] == FormatSpecifier::Double)
{
double reg = (reg_part == 0) ? rPS0(reg_index) : rPS1(reg_index);
return wxString::Format(GetFormatString(m_formatFRegs[reg_index][reg_part]), reg);
}
u64 reg = (reg_part == 0) ? riPS0(reg_index) : riPS1(reg_index);
return wxString::Format(GetFormatString(m_formatFRegs[reg_index][reg_part]), reg);
}
bool CRegTable::TryParseGPR(wxString str, FormatSpecifier format, u32* value)
{
if (format == FormatSpecifier::Hex8)
{
unsigned long val;
if (str.ToCULong(&val, 16))
{
*value = static_cast<u32>(val);
return true;
}
return false;
}
if (format == FormatSpecifier::Int)
{
long signed_val;
if (str.ToCLong(&signed_val))
{
*value = static_cast<u32>(signed_val);
return true;
}
return false;
}
if (format == FormatSpecifier::UInt)
{
unsigned long val;
if (str.ToCULong(&val))
{
*value = static_cast<u32>(val);
return true;
}
return false;
}
if (format == FormatSpecifier::Float)
{
double double_val;
if (str.ToCDouble(&double_val))
{
float float_val = static_cast<float>(double_val);
std::memcpy(value, &float_val, sizeof(float));
return true;
}
return false;
}
return false;
}
bool CRegTable::TryParseFPR(wxString str, FormatSpecifier format, unsigned long long* value)
{
if (format == FormatSpecifier::Hex16)
{
return str.ToULongLong(value, 16);
}
if (format == FormatSpecifier::Double)
{
double double_val;
if (str.ToCDouble(&double_val))
{
std::memcpy(value, &double_val, sizeof(u64));
return true;
}
return false;
}
return false;
}
void CRegTable::SetRegisterFormat(int col, int row, FormatSpecifier specifier)
{
if (row >= 32)
return;
switch (col)
{
case 1:
m_formatRegs[row] = specifier;
return;
case 3:
m_formatFRegs[row][0] = specifier;
return;
case 4:
m_formatFRegs[row][1] = specifier;
return;
}
}
u32 CRegTable::GetSpecialRegValue(int reg)
{
switch (reg)
{
@ -71,7 +234,7 @@ static u32 GetSpecialRegValue(int reg)
}
}
static wxString GetValueByRowCol(int row, int col)
wxString CRegTable::GetValue(int row, int col)
{
if (row < 32)
{
@ -80,13 +243,13 @@ static wxString GetValueByRowCol(int row, int col)
case 0:
return StrToWxStr(GekkoDisassembler::GetGPRName(row));
case 1:
return wxString::Format("%08x", GPR(row));
return FormatGPR(row);
case 2:
return StrToWxStr(GekkoDisassembler::GetFPRName(row));
case 3:
return wxString::Format("%016llx", riPS0(row));
return FormatFPR(row, 0);
case 4:
return wxString::Format("%016llx", riPS1(row));
return FormatFPR(row, 1);
case 5:
{
if (row < 4)
@ -162,12 +325,7 @@ static wxString GetValueByRowCol(int row, int col)
return wxEmptyString;
}
wxString CRegTable::GetValue(int row, int col)
{
return GetValueByRowCol(row, col);
}
static void SetSpecialRegValue(int reg, u32 value)
void CRegTable::SetSpecialRegValue(int reg, u32 value)
{
switch (reg)
{
@ -216,24 +374,34 @@ static void SetSpecialRegValue(int reg, u32 value)
void CRegTable::SetValue(int row, int col, const wxString& strNewVal)
{
u32 newVal = 0;
if (TryParse("0x" + WxStrToStr(strNewVal), &newVal))
if (row < 32)
{
if (row < 32)
if (col == 1)
{
if (col == 1)
GPR(row) = newVal;
else if (col == 3)
riPS0(row) = newVal;
else if (col == 4)
riPS1(row) = newVal;
u32 new_val = 0;
if (TryParseGPR(strNewVal, m_formatRegs[row], &new_val))
GPR(row) = new_val;
}
else
else if (col == 3)
{
if ((row - 32 < NUM_SPECIALS) && (col == 1))
{
SetSpecialRegValue(row - 32, newVal);
}
unsigned long long new_val = 0;
if (TryParseFPR(strNewVal, m_formatFRegs[row][0], &new_val))
riPS0(row) = new_val;
}
else if (col == 4)
{
unsigned long long new_val = 0;
if (TryParseFPR(strNewVal, m_formatFRegs[row][1], &new_val))
riPS1(row) = new_val;
}
}
else
{
if ((row - 32 < NUM_SPECIALS) && (col == 1))
{
u32 new_val = 0;
if (TryParse("0x" + WxStrToStr(strNewVal), &new_val))
SetSpecialRegValue(row - 32, new_val);
}
}
}
@ -318,16 +486,33 @@ void CRegisterView::Update()
void CRegisterView::OnMouseDownR(wxGridEvent& event)
{
// popup menu
int row = event.GetRow();
int col = event.GetCol();
m_selectedRow = event.GetRow();
m_selectedColumn = event.GetCol();
wxString strNewVal = GetValueByRowCol(row, col);
wxString strNewVal = m_register_table->GetValue(m_selectedRow, m_selectedColumn);
TryParse("0x" + WxStrToStr(strNewVal), &m_selectedAddress);
wxMenu menu;
menu.Append(IDM_WATCHADDRESS, _("Add to &watch"));
menu.Append(IDM_VIEWMEMORY, _("View &memory"));
menu.Append(IDM_VIEWCODE, _("View &code"));
if (m_selectedRow < 32 &&
(m_selectedColumn == 1 || m_selectedColumn == 3 || m_selectedColumn == 4))
{
menu.AppendSeparator();
if (m_selectedColumn == 1)
{
menu.Append(IDM_VIEW_HEX8, _("View as hexadecimal"));
menu.Append(IDM_VIEW_INT, _("View as signed integer"));
menu.Append(IDM_VIEW_UINT, _("View as unsigned integer"));
menu.Append(IDM_VIEW_FLOAT, _("View as float"));
}
else
{
menu.Append(IDM_VIEW_HEX16, _("View as hexadecimal"));
menu.Append(IDM_VIEW_DOUBLE, _("View as double"));
}
}
PopupMenu(&menu);
}
@ -355,6 +540,30 @@ void CRegisterView::OnPopupMenu(wxCommandEvent& event)
code_window->JumpToAddress(m_selectedAddress);
Refresh();
break;
case IDM_VIEW_HEX8:
m_register_table->SetRegisterFormat(m_selectedColumn, m_selectedRow, FormatSpecifier::Hex8);
Refresh();
break;
case IDM_VIEW_HEX16:
m_register_table->SetRegisterFormat(m_selectedColumn, m_selectedRow, FormatSpecifier::Hex16);
Refresh();
break;
case IDM_VIEW_INT:
m_register_table->SetRegisterFormat(m_selectedColumn, m_selectedRow, FormatSpecifier::Int);
Refresh();
break;
case IDM_VIEW_UINT:
m_register_table->SetRegisterFormat(m_selectedColumn, m_selectedRow, FormatSpecifier::UInt);
Refresh();
break;
case IDM_VIEW_FLOAT:
m_register_table->SetRegisterFormat(m_selectedColumn, m_selectedRow, FormatSpecifier::Float);
Refresh();
break;
case IDM_VIEW_DOUBLE:
m_register_table->SetRegisterFormat(m_selectedColumn, m_selectedRow, FormatSpecifier::Double);
Refresh();
break;
}
event.Skip();
}

View file

@ -4,6 +4,7 @@
#pragma once
#include <array>
#include <cstring>
#include <wx/grid.h>
@ -27,25 +28,19 @@
#define NUM_SPECIALS 14
enum class FormatSpecifier;
class CRegTable : public wxGridTableBase
{
public:
CRegTable()
{
memset(m_CachedRegs, 0, sizeof(m_CachedRegs));
memset(m_CachedSpecialRegs, 0, sizeof(m_CachedSpecialRegs));
memset(m_CachedFRegs, 0, sizeof(m_CachedFRegs));
memset(m_CachedRegHasChanged, 0, sizeof(m_CachedRegHasChanged));
memset(m_CachedSpecialRegHasChanged, 0, sizeof(m_CachedSpecialRegHasChanged));
memset(m_CachedFRegHasChanged, 0, sizeof(m_CachedFRegHasChanged));
}
CRegTable();
int GetNumberCols() override { return 9; }
int GetNumberRows() override { return 32 + NUM_SPECIALS; }
bool IsEmptyCell(int row, int col) override { return row > 31 && col > 2; }
wxString GetValue(int row, int col) override;
void SetValue(int row, int col, const wxString&) override;
wxGridCellAttr* GetAttr(int, int, wxGridCellAttr::wxAttrKind) override;
void SetRegisterFormat(int col, int row, FormatSpecifier specifier);
void UpdateCachedRegs();
private:
@ -55,6 +50,16 @@ private:
bool m_CachedRegHasChanged[32];
bool m_CachedSpecialRegHasChanged[NUM_SPECIALS];
bool m_CachedFRegHasChanged[32][2];
std::array<FormatSpecifier, 32> m_formatRegs;
std::array<std::array<FormatSpecifier, 2>, 32> m_formatFRegs;
u32 GetSpecialRegValue(int reg);
void SetSpecialRegValue(int reg, u32 value);
wxString GetFormatString(FormatSpecifier specifier);
wxString FormatGPR(int reg_index);
wxString FormatFPR(int reg_index, int reg_part);
bool TryParseGPR(wxString str, FormatSpecifier format, u32* value);
bool TryParseFPR(wxString str, FormatSpecifier format, unsigned long long int* value);
DECLARE_NO_COPY_CLASS(CRegTable);
};
@ -70,6 +75,8 @@ private:
void OnPopupMenu(wxCommandEvent& event);
u32 m_selectedAddress = 0;
int m_selectedRow = 0;
int m_selectedColumn = 0;
// Owned by wx. Deleted implicitly upon destruction.
CRegTable* m_register_table;