1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2025-02-13 03:40:49 +00:00

SPU Debugger: Implement float registers view + General debugger fixes ()

* SPU Debugger: Fix try_get_insert_mask_info
* Debugger: Always update thread state on context's data change
No longer needing to press on thread's instructions for actions to work!
This commit is contained in:
Eladash 2020-11-15 07:45:28 +02:00 committed by GitHub
parent dfae7bd073
commit b1710bb712
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 67 additions and 22 deletions

@ -218,6 +218,12 @@ typename SPUDisAsm::insert_mask_info SPUDisAsm::try_get_insert_mask_info(v128 ma
return {};
}
if (size == 16)
{
// 0x0, 0x1, 0x2, .. 0xE, 0xF is not allowed
return {};
}
// [type size, dst index, src index]
return {size, first / size, src_first / size};
}

@ -1194,9 +1194,11 @@ std::string spu_thread::dump_regs() const
{
std::string ret;
const bool floats_only = debugger_float_mode.load();
for (u32 i = 0; i < 128; i++, ret += '\n')
{
fmt::append(ret, "r%d: ", i);
fmt::append(ret, "%s: ", spu_reg_name[i]);
const auto r = gpr[i];
@ -1217,9 +1219,25 @@ std::string spu_thread::dump_regs() const
}
}
const u32 i3 = r._u32[3];
auto to_f64 = [](u32 bits)
{
const u32 abs = bits & 0x7fff'ffff;
constexpr u32 scale = (1 << 23);
return std::copysign(abs < scale ? 0 : std::ldexp((scale + (abs % scale)) / f64{scale}, static_cast<int>(abs >> 23) - 127), bits >> 31 ? -1 : 1);
};
if (v128::from32p(i3) == r)
const double array[]{to_f64(r.u32r[0]), to_f64(r.u32r[1]), to_f64(r.u32r[2]), to_f64(r.u32r[3])};
const u32 i3 = r._u32[3];
const bool is_packed = v128::from32p(i3) == r;
if (floats_only)
{
fmt::append(ret, "%g, %g, %g, %g", array[0], array[1], array[2], array[3]);
continue;
}
if (is_packed)
{
// Shortand formatting
fmt::append(ret, "%08x", i3);
@ -1229,8 +1247,6 @@ std::string spu_thread::dump_regs() const
fmt::append(ret, "%08x %08x %08x %08x", r.u32r[0], r.u32r[1], r.u32r[2], r.u32r[3]);
}
// TODO: SPU floats fomatting
if (i3 >= 0x80 && is_exec_code(i3))
{
SPUDisAsm dis_asm(CPUDisAsm_NormalMode);
@ -1239,6 +1255,18 @@ std::string spu_thread::dump_regs() const
dis_asm.disasm(i3);
fmt::append(ret, " -> %s", dis_asm.last_opcode);
}
if (std::any_of(std::begin(array), std::end(array), [](f64 v){ return v != 0; }))
{
if (is_packed)
{
fmt::append(ret, " (%g)", array[0]);
}
else
{
fmt::append(ret, " (%g, %g, %g, %g)", array[0], array[1], array[2], array[3]);
}
}
}
const auto events = ch_events.load();

@ -764,6 +764,8 @@ public:
const char* current_func{}; // Current STOP or RDCH blocking function
u64 start_time{}; // Starting time of STOP or RDCH bloking function
atomic_t<u8> debugger_float_mode = 0;
void push_snr(u32 number, u32 value);
static void do_dma_transfer(spu_thread* _this, const spu_mfc_cmd& args, u8* ls);
bool do_dma_check(const spu_mfc_cmd& args);

@ -224,12 +224,12 @@ void debugger_frame::keyPressEvent(QKeyEvent* event)
const auto cpu = this->cpu.lock();
int i = m_debugger_list->currentRow();
if (!isActiveWindow() || i < 0 || !cpu || m_no_thread_selected)
if (!isActiveWindow() || !cpu || m_no_thread_selected)
{
return;
}
const u32 pc = m_debugger_list->m_pc + i * 4;
const u32 pc = i >= 0 ? m_debugger_list->m_pc + i * 4 : GetPc();
const auto modifiers = QApplication::keyboardModifiers();
@ -254,9 +254,19 @@ void debugger_frame::keyPressEvent(QKeyEvent* event)
dlg->show();
return;
}
case Qt::Key_F:
{
if (cpu->id_type() != 2)
{
return;
}
static_cast<spu_thread*>(cpu.get())->debugger_float_mode ^= 1; // Switch mode
return;
}
case Qt::Key_R:
{
register_editor_dialog* dlg = new register_editor_dialog(this, pc, cpu, m_disasm.get());
register_editor_dialog* dlg = new register_editor_dialog(this, cpu, m_disasm.get());
dlg->show();
return;
}
@ -264,9 +274,7 @@ void debugger_frame::keyPressEvent(QKeyEvent* event)
{
if (modifiers & Qt::AltModifier)
{
const auto cpu = this->cpu.lock();
if (!cpu || cpu->id_type() != 2)
if (cpu->id_type() != 2)
{
return;
}
@ -321,10 +329,10 @@ void debugger_frame::UpdateUI()
if (!cpu)
{
if (m_last_pc != umax || m_last_stat)
if (m_last_pc != umax || !m_last_query_state.empty())
{
m_last_query_state.clear();
m_last_pc = -1;
m_last_stat = 0;
DoUpdate();
}
@ -335,15 +343,18 @@ void debugger_frame::UpdateUI()
else
{
const auto cia = GetPc();
const auto state = cpu->state.load();
const auto size_context = cpu->id_type() == 1 ? sizeof(ppu_thread) : sizeof(spu_thread);
if (m_last_pc != cia || m_last_stat != static_cast<u32>(state))
if (m_last_pc != cia || m_last_query_state.size() != size_context || std::memcmp(m_last_query_state.data(), cpu.get(), size_context))
{
// Copy thread data
m_last_query_state.resize(size_context);
std::memcpy(m_last_query_state.data(), cpu.get(), size_context);
m_last_pc = cia;
m_last_stat = static_cast<u32>(state);
DoUpdate();
if (state & cpu_flag::dbg_pause)
if (cpu->state & cpu_flag::dbg_pause)
{
m_btn_run->setText(RunString);
m_btn_step->setEnabled(true);

@ -43,7 +43,7 @@ class debugger_frame : public custom_dock_widget
u64 m_threads_created = 0;
u64 m_threads_deleted = 0;
u32 m_last_pc = -1;
u32 m_last_stat = 0;
std::vector<char> m_last_query_state;
u32 m_last_step_over_breakpoint = -1;
bool m_no_thread_selected = true;

@ -55,9 +55,8 @@ enum registers : int
PC,
};
register_editor_dialog::register_editor_dialog(QWidget *parent, u32 _pc, const std::shared_ptr<cpu_thread>& _cpu, CPUDisAsm* _disasm)
register_editor_dialog::register_editor_dialog(QWidget *parent, const std::shared_ptr<cpu_thread>& _cpu, CPUDisAsm* _disasm)
: QDialog(parent)
, m_pc(_pc)
, m_disasm(_disasm)
, cpu(_cpu)
{

@ -13,7 +13,6 @@ class register_editor_dialog : public QDialog
{
Q_OBJECT
u32 m_pc;
CPUDisAsm* m_disasm;
QComboBox* m_register_combo;
QLineEdit* m_value_line;
@ -22,7 +21,7 @@ public:
std::weak_ptr<cpu_thread> cpu;
public:
register_editor_dialog(QWidget *parent, u32 _pc, const std::shared_ptr<cpu_thread>& _cpu, CPUDisAsm* _disasm);
register_editor_dialog(QWidget *parent, const std::shared_ptr<cpu_thread>& _cpu, CPUDisAsm* _disasm);
private:
void OnOkay(const std::shared_ptr<cpu_thread>& _cpu);