mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-22 02:32:36 +01:00
threads: replace magic number id_type with thread_class
This commit is contained in:
parent
aff2588cce
commit
dfee5b9a6c
@ -1520,7 +1520,7 @@ bool handle_access_violation(u32 addr, bool is_writing, ucontext_t* context) noe
|
|||||||
return area->falloc(addr & -0x10000, 0x10000) || vm::check_addr(addr, is_writing ? vm::page_writable : vm::page_readable);
|
return area->falloc(addr & -0x10000, 0x10000) || vm::check_addr(addr, is_writing ? vm::page_writable : vm::page_readable);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (cpu && (cpu->id_type() == 1 || cpu->id_type() == 2))
|
if (cpu && (cpu->get_class() == thread_class::ppu || cpu->get_class() == thread_class::spu))
|
||||||
{
|
{
|
||||||
vm::temporary_unlock(*cpu);
|
vm::temporary_unlock(*cpu);
|
||||||
u32 pf_port_id = 0;
|
u32 pf_port_id = 0;
|
||||||
@ -1587,7 +1587,7 @@ bool handle_access_violation(u32 addr, bool is_writing, ucontext_t* context) noe
|
|||||||
auto& pf_events = g_fxo->get<page_fault_event_entries>();
|
auto& pf_events = g_fxo->get<page_fault_event_entries>();
|
||||||
|
|
||||||
// De-schedule
|
// De-schedule
|
||||||
if (cpu->id_type() == 1)
|
if (cpu->get_class() == thread_class::ppu)
|
||||||
{
|
{
|
||||||
cpu->state -= cpu_flag::signal; // Cannot use check_state here and signal must be removed if exists
|
cpu->state -= cpu_flag::signal; // Cannot use check_state here and signal must be removed if exists
|
||||||
lv2_obj::sleep(*cpu);
|
lv2_obj::sleep(*cpu);
|
||||||
@ -1611,7 +1611,7 @@ bool handle_access_violation(u32 addr, bool is_writing, ucontext_t* context) noe
|
|||||||
sig_log.warning("Page_fault %s location 0x%x because of %s memory", is_writing ? "writing" : "reading",
|
sig_log.warning("Page_fault %s location 0x%x because of %s memory", is_writing ? "writing" : "reading",
|
||||||
addr, data3 == SYS_MEMORY_PAGE_FAULT_CAUSE_READ_ONLY ? "writing read-only" : "using unmapped");
|
addr, data3 == SYS_MEMORY_PAGE_FAULT_CAUSE_READ_ONLY ? "writing read-only" : "using unmapped");
|
||||||
|
|
||||||
if (cpu->id_type() == 1)
|
if (cpu->get_class() == thread_class::ppu)
|
||||||
{
|
{
|
||||||
if (const auto func = static_cast<ppu_thread*>(cpu)->current_function)
|
if (const auto func = static_cast<ppu_thread*>(cpu)->current_function)
|
||||||
{
|
{
|
||||||
@ -1661,7 +1661,7 @@ bool handle_access_violation(u32 addr, bool is_writing, ucontext_t* context) noe
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cpu->id_type() == 2)
|
if (cpu->get_class() == thread_class::spu)
|
||||||
{
|
{
|
||||||
if (!g_tls_access_violation_recovered)
|
if (!g_tls_access_violation_recovered)
|
||||||
{
|
{
|
||||||
@ -1708,7 +1708,7 @@ bool handle_access_violation(u32 addr, bool is_writing, ucontext_t* context) noe
|
|||||||
// Do not log any further access violations in this case.
|
// Do not log any further access violations in this case.
|
||||||
if (!g_tls_access_violation_recovered)
|
if (!g_tls_access_violation_recovered)
|
||||||
{
|
{
|
||||||
vm_log.fatal("Access violation %s location 0x%x (%s)", is_writing ? "writing" : (cpu && cpu->id_type() == 1 && cpu->get_pc() == addr ? "executing" : "reading"), addr, (is_writing && vm::check_addr(addr)) ? "read-only memory" : "unmapped memory");
|
vm_log.fatal("Access violation %s location 0x%x (%s)", is_writing ? "writing" : (cpu && cpu->get_class() == thread_class::ppu && cpu->get_pc() == addr ? "executing" : "reading"), addr, (is_writing && vm::check_addr(addr)) ? "read-only memory" : "unmapped memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
while (Emu.IsPaused())
|
while (Emu.IsPaused())
|
||||||
|
@ -36,6 +36,17 @@ enum class thread_state : u32
|
|||||||
mask = 3
|
mask = 3
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static inline thread_class get_thread_class(u32 thread_id_type)
|
||||||
|
{
|
||||||
|
switch (thread_id_type)
|
||||||
|
{
|
||||||
|
case 1: return thread_class::ppu;
|
||||||
|
case 2: return thread_class::spu;
|
||||||
|
case 0x55: return thread_class::rsx;
|
||||||
|
default: return thread_class::general;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template <class Context>
|
template <class Context>
|
||||||
class named_thread;
|
class named_thread;
|
||||||
|
|
||||||
|
@ -388,10 +388,10 @@ namespace cpu_counter
|
|||||||
{
|
{
|
||||||
void add(cpu_thread* _this) noexcept
|
void add(cpu_thread* _this) noexcept
|
||||||
{
|
{
|
||||||
switch (_this->id_type())
|
switch (_this->get_class())
|
||||||
{
|
{
|
||||||
case 1:
|
case thread_class::ppu:
|
||||||
case 2:
|
case thread_class::spu:
|
||||||
break;
|
break;
|
||||||
default: return;
|
default: return;
|
||||||
}
|
}
|
||||||
@ -521,7 +521,7 @@ void cpu_thread::operator()()
|
|||||||
|
|
||||||
if (g_cfg.core.thread_scheduler != thread_scheduler_mode::os)
|
if (g_cfg.core.thread_scheduler != thread_scheduler_mode::os)
|
||||||
{
|
{
|
||||||
thread_ctrl::set_thread_affinity_mask(thread_ctrl::get_affinity_mask(id_type() == 1 ? thread_class::ppu : thread_class::spu));
|
thread_ctrl::set_thread_affinity_mask(thread_ctrl::get_affinity_mask(get_class()));
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!g_fxo->is_init<cpu_profiler>())
|
while (!g_fxo->is_init<cpu_profiler>())
|
||||||
@ -535,14 +535,14 @@ void cpu_thread::operator()()
|
|||||||
thread_ctrl::wait_for(1000);
|
thread_ctrl::wait_for(1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (id_type())
|
switch (get_class())
|
||||||
{
|
{
|
||||||
case 1:
|
case thread_class::ppu:
|
||||||
{
|
{
|
||||||
//g_fxo->get<cpu_profiler>().registered.push(id);
|
//g_fxo->get<cpu_profiler>().registered.push(id);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 2:
|
case thread_class::spu:
|
||||||
{
|
{
|
||||||
if (g_cfg.core.spu_prof)
|
if (g_cfg.core.spu_prof)
|
||||||
{
|
{
|
||||||
@ -557,7 +557,7 @@ void cpu_thread::operator()()
|
|||||||
// Register thread in g_cpu_array
|
// Register thread in g_cpu_array
|
||||||
s_cpu_counter++;
|
s_cpu_counter++;
|
||||||
|
|
||||||
atomic_wait_engine::set_notify_callback(g_use_rtm || id_type() != 1 /* PPU */ ? nullptr : +[](const void*, u64 progress)
|
atomic_wait_engine::set_notify_callback(g_use_rtm || get_class() != thread_class::ppu ? nullptr : +[](const void*, u64 progress)
|
||||||
{
|
{
|
||||||
static thread_local bool wait_set = false;
|
static thread_local bool wait_set = false;
|
||||||
|
|
||||||
@ -676,6 +676,7 @@ cpu_thread::~cpu_thread()
|
|||||||
|
|
||||||
cpu_thread::cpu_thread(u32 id)
|
cpu_thread::cpu_thread(u32 id)
|
||||||
: id(id)
|
: id(id)
|
||||||
|
, m_class(get_thread_class(id_type()))
|
||||||
{
|
{
|
||||||
while (Emu.GetStatus() == system_state::paused)
|
while (Emu.GetStatus() == system_state::paused)
|
||||||
{
|
{
|
||||||
@ -1027,18 +1028,27 @@ void cpu_thread::notify()
|
|||||||
state.notify_one();
|
state.notify_one();
|
||||||
|
|
||||||
// Downcast to correct type
|
// Downcast to correct type
|
||||||
if (id_type() == 1)
|
switch (get_class())
|
||||||
|
{
|
||||||
|
case thread_class::ppu:
|
||||||
{
|
{
|
||||||
thread_ctrl::notify(*static_cast<named_thread<ppu_thread>*>(this));
|
thread_ctrl::notify(*static_cast<named_thread<ppu_thread>*>(this));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else if (id_type() == 2)
|
case thread_class::spu:
|
||||||
{
|
{
|
||||||
thread_ctrl::notify(*static_cast<named_thread<spu_thread>*>(this));
|
thread_ctrl::notify(*static_cast<named_thread<spu_thread>*>(this));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else if (id_type() != 0x55)
|
case thread_class::rsx:
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
{
|
{
|
||||||
fmt::throw_exception("Invalid cpu_thread type");
|
fmt::throw_exception("Invalid cpu_thread type");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cpu_thread& cpu_thread::operator=(thread_state)
|
cpu_thread& cpu_thread::operator=(thread_state)
|
||||||
@ -1108,13 +1118,13 @@ void cpu_thread::add_remove_flags(bs_t<cpu_flag> to_add, bs_t<cpu_flag> to_remov
|
|||||||
std::string cpu_thread::get_name() const
|
std::string cpu_thread::get_name() const
|
||||||
{
|
{
|
||||||
// Downcast to correct type
|
// Downcast to correct type
|
||||||
switch (id_type())
|
switch (get_class())
|
||||||
{
|
{
|
||||||
case 1:
|
case thread_class::ppu:
|
||||||
{
|
{
|
||||||
return thread_ctrl::get_name(*static_cast<const named_thread<ppu_thread>*>(this));
|
return thread_ctrl::get_name(*static_cast<const named_thread<ppu_thread>*>(this));
|
||||||
}
|
}
|
||||||
case 2:
|
case thread_class::spu:
|
||||||
{
|
{
|
||||||
return thread_ctrl::get_name(*static_cast<const named_thread<spu_thread>*>(this));
|
return thread_ctrl::get_name(*static_cast<const named_thread<spu_thread>*>(this));
|
||||||
}
|
}
|
||||||
@ -1125,7 +1135,7 @@ std::string cpu_thread::get_name() const
|
|||||||
return thread_ctrl::get_name();
|
return thread_ctrl::get_name();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (id_type() == 0x55)
|
if (get_class() == thread_class::rsx)
|
||||||
{
|
{
|
||||||
return fmt::format("rsx::thread");
|
return fmt::format("rsx::thread");
|
||||||
}
|
}
|
||||||
@ -1139,19 +1149,19 @@ u32 cpu_thread::get_pc() const
|
|||||||
{
|
{
|
||||||
const u32* pc = nullptr;
|
const u32* pc = nullptr;
|
||||||
|
|
||||||
switch (id_type())
|
switch (get_class())
|
||||||
{
|
{
|
||||||
case 1:
|
case thread_class::ppu:
|
||||||
{
|
{
|
||||||
pc = &static_cast<const ppu_thread*>(this)->cia;
|
pc = &static_cast<const ppu_thread*>(this)->cia;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 2:
|
case thread_class::spu:
|
||||||
{
|
{
|
||||||
pc = &static_cast<const spu_thread*>(this)->pc;
|
pc = &static_cast<const spu_thread*>(this)->pc;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0x55:
|
case thread_class::rsx:
|
||||||
{
|
{
|
||||||
const auto ctrl = static_cast<const rsx::thread*>(this)->ctrl;
|
const auto ctrl = static_cast<const rsx::thread*>(this)->ctrl;
|
||||||
return ctrl ? ctrl->get.load() : umax;
|
return ctrl ? ctrl->get.load() : umax;
|
||||||
@ -1164,17 +1174,17 @@ u32 cpu_thread::get_pc() const
|
|||||||
|
|
||||||
u32* cpu_thread::get_pc2()
|
u32* cpu_thread::get_pc2()
|
||||||
{
|
{
|
||||||
switch (id_type())
|
switch (get_class())
|
||||||
{
|
{
|
||||||
case 1:
|
case thread_class::ppu:
|
||||||
{
|
{
|
||||||
return &static_cast<ppu_thread*>(this)->dbg_step_pc;
|
return &static_cast<ppu_thread*>(this)->dbg_step_pc;
|
||||||
}
|
}
|
||||||
case 2:
|
case thread_class::spu:
|
||||||
{
|
{
|
||||||
return &static_cast<spu_thread*>(this)->dbg_step_pc;
|
return &static_cast<spu_thread*>(this)->dbg_step_pc;
|
||||||
}
|
}
|
||||||
case 0x55:
|
case thread_class::rsx:
|
||||||
{
|
{
|
||||||
const auto ctrl = static_cast<rsx::thread*>(this)->ctrl;
|
const auto ctrl = static_cast<rsx::thread*>(this)->ctrl;
|
||||||
return ctrl ? &static_cast<rsx::thread*>(this)->dbg_step_pc : nullptr;
|
return ctrl ? &static_cast<rsx::thread*>(this)->dbg_step_pc : nullptr;
|
||||||
@ -1187,13 +1197,13 @@ u32* cpu_thread::get_pc2()
|
|||||||
|
|
||||||
cpu_thread* cpu_thread::get_next_cpu()
|
cpu_thread* cpu_thread::get_next_cpu()
|
||||||
{
|
{
|
||||||
switch (id_type())
|
switch (get_class())
|
||||||
{
|
{
|
||||||
case 1:
|
case thread_class::ppu:
|
||||||
{
|
{
|
||||||
return static_cast<ppu_thread*>(this)->next_cpu;
|
return static_cast<ppu_thread*>(this)->next_cpu;
|
||||||
}
|
}
|
||||||
case 2:
|
case thread_class::spu:
|
||||||
{
|
{
|
||||||
return static_cast<spu_thread*>(this)->next_cpu;
|
return static_cast<spu_thread*>(this)->next_cpu;
|
||||||
}
|
}
|
||||||
@ -1259,7 +1269,7 @@ std::vector<std::pair<u32, u32>> cpu_thread::dump_callstack_list() const
|
|||||||
|
|
||||||
std::string cpu_thread::dump_misc() const
|
std::string cpu_thread::dump_misc() const
|
||||||
{
|
{
|
||||||
return fmt::format("Type: %s; State: %s\n", id_type() == 1 ? "PPU" : id_type() == 2 ? "SPU" : "RSX", state.load());
|
return fmt::format("Type: %s; State: %s\n", get_class() == thread_class::ppu ? "PPU" : get_class() == thread_class::spu ? "SPU" : "RSX", state.load());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cpu_thread::suspend_work::push(cpu_thread* _this) noexcept
|
bool cpu_thread::suspend_work::push(cpu_thread* _this) noexcept
|
||||||
|
@ -118,6 +118,11 @@ public:
|
|||||||
return id >> 24;
|
return id >> 24;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
thread_class get_class() const
|
||||||
|
{
|
||||||
|
return m_class;
|
||||||
|
}
|
||||||
|
|
||||||
template <DerivedFrom<cpu_thread> T>
|
template <DerivedFrom<cpu_thread> T>
|
||||||
T* try_get()
|
T* try_get()
|
||||||
{
|
{
|
||||||
@ -296,6 +301,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
static thread_local cpu_thread* g_tls_this_thread;
|
static thread_local cpu_thread* g_tls_this_thread;
|
||||||
|
const thread_class m_class;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <DerivedFrom<cpu_thread> T = cpu_thread>
|
template <DerivedFrom<cpu_thread> T = cpu_thread>
|
||||||
|
@ -2401,7 +2401,7 @@ void spu_thread::do_dma_transfer(spu_thread* _this, const spu_mfc_cmd& args, u8*
|
|||||||
|
|
||||||
if (!_this) [[unlikely]]
|
if (!_this) [[unlikely]]
|
||||||
{
|
{
|
||||||
if (_cpu->id_type() == 2)
|
if (_cpu->get_class() == thread_class::spu)
|
||||||
{
|
{
|
||||||
// Use range_lock of current SPU thread for range locks
|
// Use range_lock of current SPU thread for range locks
|
||||||
range_lock = static_cast<spu_thread*>(_cpu)->range_lock;
|
range_lock = static_cast<spu_thread*>(_cpu)->range_lock;
|
||||||
@ -3900,7 +3900,7 @@ void do_cell_atomic_128_store(u32 addr, const void* to_write)
|
|||||||
mov_rdata(sdata, *static_cast<const spu_rdata_t*>(to_write));
|
mov_rdata(sdata, *static_cast<const spu_rdata_t*>(to_write));
|
||||||
vm::reservation_acquire(addr) += 32;
|
vm::reservation_acquire(addr) += 32;
|
||||||
}
|
}
|
||||||
else if (cpu->id_type() != 2)
|
else if (cpu->get_class() != thread_class::spu)
|
||||||
{
|
{
|
||||||
u64 stx, ftx;
|
u64 stx, ftx;
|
||||||
result = spu_putlluc_tx(addr, to_write, &stx, &ftx);
|
result = spu_putlluc_tx(addr, to_write, &stx, &ftx);
|
||||||
@ -5319,7 +5319,7 @@ s64 spu_thread::get_ch_value(u32 ch)
|
|||||||
atomic_wait_engine::set_one_time_use_wait_callback(+[](u64) -> bool
|
atomic_wait_engine::set_one_time_use_wait_callback(+[](u64) -> bool
|
||||||
{
|
{
|
||||||
const auto _this = static_cast<spu_thread*>(cpu_thread::get_current());
|
const auto _this = static_cast<spu_thread*>(cpu_thread::get_current());
|
||||||
AUDIT(_this->id_type() == 1);
|
AUDIT(_this->get_class() == thread_class::ppu);
|
||||||
|
|
||||||
return !_this->is_stopped();
|
return !_this->is_stopped();
|
||||||
});
|
});
|
||||||
@ -5333,7 +5333,7 @@ s64 spu_thread::get_ch_value(u32 ch)
|
|||||||
atomic_wait_engine::set_one_time_use_wait_callback(mask1 != SPU_EVENT_LR ? nullptr : +[](u64 attempts) -> bool
|
atomic_wait_engine::set_one_time_use_wait_callback(mask1 != SPU_EVENT_LR ? nullptr : +[](u64 attempts) -> bool
|
||||||
{
|
{
|
||||||
const auto _this = static_cast<spu_thread*>(cpu_thread::get_current());
|
const auto _this = static_cast<spu_thread*>(cpu_thread::get_current());
|
||||||
AUDIT(_this->id_type() == 2);
|
AUDIT(_this->get_class() == thread_class::spu);
|
||||||
|
|
||||||
const auto old = +_this->state;
|
const auto old = +_this->state;
|
||||||
|
|
||||||
|
@ -1325,7 +1325,7 @@ bool lv2_obj::sleep(cpu_thread& cpu, const u64 timeout)
|
|||||||
prepare_for_sleep(cpu);
|
prepare_for_sleep(cpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cpu.id_type() == 1)
|
if (cpu.get_class() == thread_class::ppu)
|
||||||
{
|
{
|
||||||
if (u32 addr = static_cast<ppu_thread&>(cpu).res_notify)
|
if (u32 addr = static_cast<ppu_thread&>(cpu).res_notify)
|
||||||
{
|
{
|
||||||
@ -1571,7 +1571,7 @@ bool lv2_obj::sleep_unlocked(cpu_thread& thread, u64 timeout, u64 current_time)
|
|||||||
bool lv2_obj::awake_unlocked(cpu_thread* cpu, s32 prio)
|
bool lv2_obj::awake_unlocked(cpu_thread* cpu, s32 prio)
|
||||||
{
|
{
|
||||||
// Check thread type
|
// Check thread type
|
||||||
AUDIT(!cpu || cpu->id_type() == 1);
|
AUDIT(!cpu || cpu->get_class() == thread_class::ppu);
|
||||||
|
|
||||||
bool push_first = false;
|
bool push_first = false;
|
||||||
|
|
||||||
|
@ -851,7 +851,7 @@ error_code mmapper_thread_recover_page_fault(cpu_thread* cpu)
|
|||||||
|
|
||||||
pf_events.events.erase(pf_event_ind);
|
pf_events.events.erase(pf_event_ind);
|
||||||
|
|
||||||
if (cpu->id_type() == 1u)
|
if (cpu->get_class() == thread_class::ppu)
|
||||||
{
|
{
|
||||||
lv2_obj::awake(cpu);
|
lv2_obj::awake(cpu);
|
||||||
}
|
}
|
||||||
|
@ -104,7 +104,7 @@ bool rsx::thread::send_event(u64 data1, u64 event_flags, u64 data3)
|
|||||||
{
|
{
|
||||||
auto cpu = get_current_cpu_thread();
|
auto cpu = get_current_cpu_thread();
|
||||||
|
|
||||||
if (cpu && cpu->id_type() == 1)
|
if (cpu && cpu->get_class() == thread_class::ppu)
|
||||||
{
|
{
|
||||||
// Deschedule
|
// Deschedule
|
||||||
lv2_obj::sleep(*cpu, 100);
|
lv2_obj::sleep(*cpu, 100);
|
||||||
@ -113,7 +113,7 @@ bool rsx::thread::send_event(u64 data1, u64 event_flags, u64 data3)
|
|||||||
// Wait a bit before resending event
|
// Wait a bit before resending event
|
||||||
thread_ctrl::wait_for(100);
|
thread_ctrl::wait_for(100);
|
||||||
|
|
||||||
if (cpu && cpu->id_type() == 0x55)
|
if (cpu && cpu->get_class() == thread_class::rsx)
|
||||||
cpu->cpu_wait({});
|
cpu->cpu_wait({});
|
||||||
|
|
||||||
if (Emu.IsStopped() || (cpu && cpu->check_state()))
|
if (Emu.IsStopped() || (cpu && cpu->check_state()))
|
||||||
|
@ -82,15 +82,18 @@ bool check_errno_again()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string u32_to_hex(u32 i) {
|
std::string u32_to_hex(u32 i)
|
||||||
|
{
|
||||||
return fmt::format("%x", i);
|
return fmt::format("%x", i);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string u64_to_padded_hex(u64 value) {
|
std::string u64_to_padded_hex(u64 value)
|
||||||
|
{
|
||||||
return fmt::format("%.16x", value);
|
return fmt::format("%.16x", value);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string u32_to_padded_hex(u32 value) {
|
std::string u32_to_padded_hex(u32 value)
|
||||||
|
{
|
||||||
return fmt::format("%.8x", value);
|
return fmt::format("%.8x", value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -230,7 +233,8 @@ char gdb_thread::read_char()
|
|||||||
{
|
{
|
||||||
char result;
|
char result;
|
||||||
int cnt = read(&result, 1);
|
int cnt = read(&result, 1);
|
||||||
if (!cnt) {
|
if (!cnt)
|
||||||
|
{
|
||||||
fmt::throw_exception("Tried to read char, but no data was available");
|
fmt::throw_exception("Tried to read char, but no data was available");
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@ -248,18 +252,22 @@ bool gdb_thread::try_read_cmd(gdb_cmd& out_cmd)
|
|||||||
{
|
{
|
||||||
char c = read_char();
|
char c = read_char();
|
||||||
//interrupt
|
//interrupt
|
||||||
if (c == 0x03) [[unlikely]] {
|
if (c == 0x03) [[unlikely]]
|
||||||
|
{
|
||||||
out_cmd.cmd = '\x03';
|
out_cmd.cmd = '\x03';
|
||||||
out_cmd.data = "";
|
out_cmd.data = "";
|
||||||
out_cmd.checksum = 0;
|
out_cmd.checksum = 0;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (c != '$') [[unlikely]] {
|
if (c != '$') [[unlikely]]
|
||||||
|
{
|
||||||
//gdb starts conversation with + for some reason
|
//gdb starts conversation with + for some reason
|
||||||
if (c == '+') {
|
if (c == '+')
|
||||||
|
{
|
||||||
c = read_char();
|
c = read_char();
|
||||||
}
|
}
|
||||||
if (c != '$') {
|
if (c != '$')
|
||||||
|
{
|
||||||
fmt::throw_exception("Expected start of packet character '$', got '%c' instead", c);
|
fmt::throw_exception("Expected start of packet character '$', got '%c' instead", c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -269,28 +277,36 @@ bool gdb_thread::try_read_cmd(gdb_cmd& out_cmd)
|
|||||||
out_cmd.checksum = 0;
|
out_cmd.checksum = 0;
|
||||||
bool cmd_part = true;
|
bool cmd_part = true;
|
||||||
u8 checksum = 0;
|
u8 checksum = 0;
|
||||||
while(true) {
|
while (true)
|
||||||
|
{
|
||||||
c = read_char();
|
c = read_char();
|
||||||
if (c == '#') {
|
if (c == '#')
|
||||||
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
checksum = (checksum + reinterpret_cast<u8&>(c)) % 256;
|
checksum = (checksum + reinterpret_cast<u8&>(c)) % 256;
|
||||||
//escaped char
|
//escaped char
|
||||||
if (c == '}') {
|
if (c == '}')
|
||||||
|
{
|
||||||
c = read_char() ^ 0x20;
|
c = read_char() ^ 0x20;
|
||||||
checksum = (checksum + reinterpret_cast<u8&>(c)) % 256;
|
checksum = (checksum + reinterpret_cast<u8&>(c)) % 256;
|
||||||
}
|
}
|
||||||
//cmd-data splitters
|
//cmd-data splitters
|
||||||
if (cmd_part && ((c == ':') || (c == '.') || (c == ';'))) {
|
if (cmd_part && ((c == ':') || (c == '.') || (c == ';')))
|
||||||
|
{
|
||||||
cmd_part = false;
|
cmd_part = false;
|
||||||
}
|
}
|
||||||
if (cmd_part) {
|
if (cmd_part)
|
||||||
|
{
|
||||||
out_cmd.cmd += c;
|
out_cmd.cmd += c;
|
||||||
//only q and v commands can have multi-char command
|
//only q and v commands can have multi-char command
|
||||||
if ((out_cmd.cmd.length() == 1) && (c != 'q') && (c != 'v')) {
|
if ((out_cmd.cmd.length() == 1) && (c != 'q') && (c != 'v'))
|
||||||
|
{
|
||||||
cmd_part = false;
|
cmd_part = false;
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
out_cmd.data += c;
|
out_cmd.data += c;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -360,12 +376,14 @@ void gdb_thread::send_cmd(const std::string& cmd)
|
|||||||
|
|
||||||
bool gdb_thread::send_cmd_ack(const std::string& cmd)
|
bool gdb_thread::send_cmd_ack(const std::string& cmd)
|
||||||
{
|
{
|
||||||
while (true) {
|
while (true)
|
||||||
|
{
|
||||||
send_cmd(cmd);
|
send_cmd(cmd);
|
||||||
char c = read_char();
|
char c = read_char();
|
||||||
if (c == '+') [[likely]]
|
if (c == '+') [[likely]]
|
||||||
return true;
|
return true;
|
||||||
if (c != '-') [[unlikely]] {
|
if (c != '-') [[unlikely]]
|
||||||
|
{
|
||||||
GDB.error("Wrong acknowledge character received: '%c'.", c);
|
GDB.error("Wrong acknowledge character received: '%c'.", c);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -376,7 +394,8 @@ bool gdb_thread::send_cmd_ack(const std::string& cmd)
|
|||||||
u8 gdb_thread::append_encoded_char(char c, std::string& str)
|
u8 gdb_thread::append_encoded_char(char c, std::string& str)
|
||||||
{
|
{
|
||||||
u8 checksum = 0;
|
u8 checksum = 0;
|
||||||
if ((c == '#') || (c == '$') || (c == '}')) [[unlikely]] {
|
if ((c == '#') || (c == '$') || (c == '}')) [[unlikely]]
|
||||||
|
{
|
||||||
str += '}';
|
str += '}';
|
||||||
c ^= 0x20;
|
c ^= 0x20;
|
||||||
checksum = '}';
|
checksum = '}';
|
||||||
@ -417,7 +436,8 @@ std::string gdb_thread::get_reg(ppu_thread* thread, u32 rid)
|
|||||||
{
|
{
|
||||||
//ids from gdb/features/rs6000/powerpc-64.c
|
//ids from gdb/features/rs6000/powerpc-64.c
|
||||||
//pc
|
//pc
|
||||||
switch (rid) {
|
switch (rid)
|
||||||
|
{
|
||||||
case 64:
|
case 64:
|
||||||
return u64_to_padded_hex(thread->cia);
|
return u64_to_padded_hex(thread->cia);
|
||||||
//msr?
|
//msr?
|
||||||
@ -445,7 +465,8 @@ std::string gdb_thread::get_reg(ppu_thread* thread, u32 rid)
|
|||||||
|
|
||||||
bool gdb_thread::set_reg(ppu_thread* thread, u32 rid, std::string value)
|
bool gdb_thread::set_reg(ppu_thread* thread, u32 rid, std::string value)
|
||||||
{
|
{
|
||||||
switch (rid) {
|
switch (rid)
|
||||||
|
{
|
||||||
case 64:
|
case 64:
|
||||||
thread->cia = static_cast<u32>(hex_to_u64(value));
|
thread->cia = static_cast<u32>(hex_to_u64(value));
|
||||||
return true;
|
return true;
|
||||||
@ -469,10 +490,13 @@ bool gdb_thread::set_reg(ppu_thread* thread, u32 rid, std::string value)
|
|||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
if (rid > 70) return false;
|
if (rid > 70) return false;
|
||||||
if (rid > 31) {
|
if (rid > 31)
|
||||||
|
{
|
||||||
u64 val = hex_to_u64(value);
|
u64 val = hex_to_u64(value);
|
||||||
thread->fpr[rid - 32] = std::bit_cast<f64>(val);
|
thread->fpr[rid - 32] = std::bit_cast<f64>(val);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
thread->gpr[rid] = hex_to_u64(value);
|
thread->gpr[rid] = hex_to_u64(value);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -481,13 +505,15 @@ bool gdb_thread::set_reg(ppu_thread* thread, u32 rid, std::string value)
|
|||||||
|
|
||||||
u32 gdb_thread::get_reg_size(ppu_thread*, u32 rid)
|
u32 gdb_thread::get_reg_size(ppu_thread*, u32 rid)
|
||||||
{
|
{
|
||||||
switch (rid) {
|
switch (rid)
|
||||||
|
{
|
||||||
case 66:
|
case 66:
|
||||||
case 69:
|
case 69:
|
||||||
case 70:
|
case 70:
|
||||||
return 4;
|
return 4;
|
||||||
default:
|
default:
|
||||||
if (rid > 70) {
|
if (rid > 70)
|
||||||
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return 8;
|
return 8;
|
||||||
@ -516,7 +542,9 @@ void gdb_thread::wait_with_interrupts()
|
|||||||
|
|
||||||
GDB.error("Error during socket read.");
|
GDB.error("Error during socket read.");
|
||||||
fmt::throw_exception("Error during socket read");
|
fmt::throw_exception("Error during socket read");
|
||||||
} else if (c == 0x03) {
|
}
|
||||||
|
else if (c == 0x03)
|
||||||
|
{
|
||||||
paused = true;
|
paused = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -542,7 +570,8 @@ bool gdb_thread::cmd_thread_info(gdb_cmd&)
|
|||||||
std::string result;
|
std::string result;
|
||||||
const auto on_select = [&](u32, cpu_thread& cpu)
|
const auto on_select = [&](u32, cpu_thread& cpu)
|
||||||
{
|
{
|
||||||
if (!result.empty()) {
|
if (!result.empty())
|
||||||
|
{
|
||||||
result += ",";
|
result += ",";
|
||||||
}
|
}
|
||||||
result += u64_to_padded_hex(static_cast<u64>(cpu.id));
|
result += u64_to_padded_hex(static_cast<u64>(cpu.id));
|
||||||
@ -563,7 +592,8 @@ bool gdb_thread::cmd_current_thread(gdb_cmd&)
|
|||||||
|
|
||||||
bool gdb_thread::cmd_read_register(gdb_cmd& cmd)
|
bool gdb_thread::cmd_read_register(gdb_cmd& cmd)
|
||||||
{
|
{
|
||||||
if (!select_thread(general_ops_thread_id)) {
|
if (!select_thread(general_ops_thread_id))
|
||||||
|
{
|
||||||
return send_cmd_ack("E02");
|
return send_cmd_ack("E02");
|
||||||
}
|
}
|
||||||
auto th = selected_thread.lock();
|
auto th = selected_thread.lock();
|
||||||
@ -571,7 +601,8 @@ bool gdb_thread::cmd_read_register(gdb_cmd& cmd)
|
|||||||
{
|
{
|
||||||
u32 rid = hex_to_u32(cmd.data);
|
u32 rid = hex_to_u32(cmd.data);
|
||||||
std::string result = get_reg(ppu, rid);
|
std::string result = get_reg(ppu, rid);
|
||||||
if (result.empty()) {
|
if (result.empty())
|
||||||
|
{
|
||||||
GDB.warning("Wrong register id %d.", rid);
|
GDB.warning("Wrong register id %d.", rid);
|
||||||
return send_cmd_ack("E01");
|
return send_cmd_ack("E01");
|
||||||
}
|
}
|
||||||
@ -583,20 +614,24 @@ bool gdb_thread::cmd_read_register(gdb_cmd& cmd)
|
|||||||
|
|
||||||
bool gdb_thread::cmd_write_register(gdb_cmd& cmd)
|
bool gdb_thread::cmd_write_register(gdb_cmd& cmd)
|
||||||
{
|
{
|
||||||
if (!select_thread(general_ops_thread_id)) {
|
if (!select_thread(general_ops_thread_id))
|
||||||
|
{
|
||||||
return send_cmd_ack("E02");
|
return send_cmd_ack("E02");
|
||||||
}
|
}
|
||||||
auto th = selected_thread.lock();
|
auto th = selected_thread.lock();
|
||||||
if (th->id_type() == 1) {
|
if (th->get_class() == thread_class::ppu)
|
||||||
|
{
|
||||||
auto ppu = static_cast<named_thread<ppu_thread>*>(th.get());
|
auto ppu = static_cast<named_thread<ppu_thread>*>(th.get());
|
||||||
usz eq_pos = cmd.data.find('=');
|
usz eq_pos = cmd.data.find('=');
|
||||||
if (eq_pos == umax) {
|
if (eq_pos == umax)
|
||||||
|
{
|
||||||
GDB.warning("Wrong write_register cmd data '%s'.", cmd.data);
|
GDB.warning("Wrong write_register cmd data '%s'.", cmd.data);
|
||||||
return send_cmd_ack("E02");
|
return send_cmd_ack("E02");
|
||||||
}
|
}
|
||||||
u32 rid = hex_to_u32(cmd.data.substr(0, eq_pos));
|
u32 rid = hex_to_u32(cmd.data.substr(0, eq_pos));
|
||||||
std::string value = cmd.data.substr(eq_pos + 1);
|
std::string value = cmd.data.substr(eq_pos + 1);
|
||||||
if (!set_reg(ppu, rid, value)) {
|
if (!set_reg(ppu, rid, value))
|
||||||
|
{
|
||||||
GDB.warning("Wrong register id %d.", rid);
|
GDB.warning("Wrong register id %d.", rid);
|
||||||
return send_cmd_ack("E01");
|
return send_cmd_ack("E01");
|
||||||
}
|
}
|
||||||
@ -613,15 +648,20 @@ bool gdb_thread::cmd_read_memory(gdb_cmd& cmd)
|
|||||||
u32 len = hex_to_u32(cmd.data.substr(s + 1));
|
u32 len = hex_to_u32(cmd.data.substr(s + 1));
|
||||||
std::string result;
|
std::string result;
|
||||||
result.reserve(len * 2);
|
result.reserve(len * 2);
|
||||||
for (u32 i = 0; i < len; ++i) {
|
for (u32 i = 0; i < len; ++i)
|
||||||
if (vm::check_addr(addr)) {
|
{
|
||||||
|
if (vm::check_addr(addr))
|
||||||
|
{
|
||||||
result += to_hexbyte(vm::read8(addr + i));
|
result += to_hexbyte(vm::read8(addr + i));
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
break;
|
break;
|
||||||
//result += "xx";
|
//result += "xx";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (len && result.empty()) {
|
if (len && result.empty())
|
||||||
|
{
|
||||||
//nothing read
|
//nothing read
|
||||||
return send_cmd_ack("E01");
|
return send_cmd_ack("E01");
|
||||||
}
|
}
|
||||||
@ -632,24 +672,30 @@ bool gdb_thread::cmd_write_memory(gdb_cmd& cmd)
|
|||||||
{
|
{
|
||||||
usz s = cmd.data.find(',');
|
usz s = cmd.data.find(',');
|
||||||
usz s2 = cmd.data.find(':');
|
usz s2 = cmd.data.find(':');
|
||||||
if ((s == umax) || (s2 == umax)) {
|
if ((s == umax) || (s2 == umax))
|
||||||
|
{
|
||||||
GDB.warning("Malformed write memory request received: '%s'.", cmd.data);
|
GDB.warning("Malformed write memory request received: '%s'.", cmd.data);
|
||||||
return send_cmd_ack("E01");
|
return send_cmd_ack("E01");
|
||||||
}
|
}
|
||||||
u32 addr = hex_to_u32(cmd.data.substr(0, s));
|
u32 addr = hex_to_u32(cmd.data.substr(0, s));
|
||||||
u32 len = hex_to_u32(cmd.data.substr(s + 1, s2 - s - 1));
|
u32 len = hex_to_u32(cmd.data.substr(s + 1, s2 - s - 1));
|
||||||
const char* data_ptr = (cmd.data.c_str()) + s2 + 1;
|
const char* data_ptr = (cmd.data.c_str()) + s2 + 1;
|
||||||
for (u32 i = 0; i < len; ++i) {
|
for (u32 i = 0; i < len; ++i)
|
||||||
if (vm::check_addr(addr + i, vm::page_writable)) {
|
{
|
||||||
|
if (vm::check_addr(addr + i, vm::page_writable))
|
||||||
|
{
|
||||||
u8 val;
|
u8 val;
|
||||||
int res = sscanf_s(data_ptr, "%02hhX", &val);
|
int res = sscanf_s(data_ptr, "%02hhX", &val);
|
||||||
if (!res) {
|
if (!res)
|
||||||
|
{
|
||||||
GDB.warning("Couldn't read u8 from string '%s'.", data_ptr);
|
GDB.warning("Couldn't read u8 from string '%s'.", data_ptr);
|
||||||
return send_cmd_ack("E02");
|
return send_cmd_ack("E02");
|
||||||
}
|
}
|
||||||
data_ptr += 2;
|
data_ptr += 2;
|
||||||
vm::write8(addr + i, val);
|
vm::write8(addr + i, val);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
return send_cmd_ack("E03");
|
return send_cmd_ack("E03");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -662,11 +708,13 @@ bool gdb_thread::cmd_read_all_registers(gdb_cmd&)
|
|||||||
select_thread(general_ops_thread_id);
|
select_thread(general_ops_thread_id);
|
||||||
|
|
||||||
auto th = selected_thread.lock();
|
auto th = selected_thread.lock();
|
||||||
if (th->id_type() == 1) {
|
if (th->get_class() == thread_class::ppu)
|
||||||
|
{
|
||||||
auto ppu = static_cast<named_thread<ppu_thread>*>(th.get());
|
auto ppu = static_cast<named_thread<ppu_thread>*>(th.get());
|
||||||
//68 64-bit registers, and 3 32-bit
|
//68 64-bit registers, and 3 32-bit
|
||||||
result.reserve(68*16 + 3*8);
|
result.reserve(68*16 + 3*8);
|
||||||
for (int i = 0; i < 71; ++i) {
|
for (int i = 0; i < 71; ++i)
|
||||||
|
{
|
||||||
result += get_reg(ppu, i);
|
result += get_reg(ppu, i);
|
||||||
}
|
}
|
||||||
return send_cmd_ack(result);
|
return send_cmd_ack(result);
|
||||||
@ -679,10 +727,12 @@ bool gdb_thread::cmd_write_all_registers(gdb_cmd& cmd)
|
|||||||
{
|
{
|
||||||
select_thread(general_ops_thread_id);
|
select_thread(general_ops_thread_id);
|
||||||
auto th = selected_thread.lock();
|
auto th = selected_thread.lock();
|
||||||
if (th->id_type() == 1) {
|
if (th->get_class() == thread_class::ppu)
|
||||||
|
{
|
||||||
auto ppu = static_cast<named_thread<ppu_thread>*>(th.get());
|
auto ppu = static_cast<named_thread<ppu_thread>*>(th.get());
|
||||||
int ptr = 0;
|
int ptr = 0;
|
||||||
for (int i = 0; i < 71; ++i) {
|
for (int i = 0; i < 71; ++i)
|
||||||
|
{
|
||||||
int sz = get_reg_size(ppu, i);
|
int sz = get_reg_size(ppu, i);
|
||||||
set_reg(ppu, i, cmd.data.substr(ptr, sz * 2));
|
set_reg(ppu, i, cmd.data.substr(ptr, sz * 2));
|
||||||
ptr += sz * 2;
|
ptr += sz * 2;
|
||||||
@ -698,12 +748,16 @@ bool gdb_thread::cmd_set_thread_ops(gdb_cmd& cmd)
|
|||||||
char type = cmd.data[0];
|
char type = cmd.data[0];
|
||||||
std::string thread = cmd.data.substr(1);
|
std::string thread = cmd.data.substr(1);
|
||||||
u64 id = thread == "-1" ? ALL_THREADS : hex_to_u64(thread);
|
u64 id = thread == "-1" ? ALL_THREADS : hex_to_u64(thread);
|
||||||
if (type == 'c') {
|
if (type == 'c')
|
||||||
|
{
|
||||||
continue_ops_thread_id = id;
|
continue_ops_thread_id = id;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
general_ops_thread_id = id;
|
general_ops_thread_id = id;
|
||||||
}
|
}
|
||||||
if (select_thread(id)) {
|
if (select_thread(id))
|
||||||
|
{
|
||||||
return send_cmd_ack("OK");
|
return send_cmd_ack("OK");
|
||||||
}
|
}
|
||||||
GDB.warning("Client asked to use thread 0x%x for %s, but no matching thread was found.", id, type == 'c' ? "continue ops" : "general ops");
|
GDB.warning("Client asked to use thread 0x%x for %s, but no matching thread was found.", id, type == 'c' ? "continue ops" : "general ops");
|
||||||
@ -732,21 +786,27 @@ bool gdb_thread::cmd_vcont(gdb_cmd& cmd)
|
|||||||
{
|
{
|
||||||
//todo: handle multiple actions and thread ids
|
//todo: handle multiple actions and thread ids
|
||||||
this->from_breakpoint = false;
|
this->from_breakpoint = false;
|
||||||
if (cmd.data[1] == 'c' || cmd.data[1] == 's') {
|
if (cmd.data[1] == 'c' || cmd.data[1] == 's')
|
||||||
|
{
|
||||||
select_thread(continue_ops_thread_id);
|
select_thread(continue_ops_thread_id);
|
||||||
auto ppu = std::static_pointer_cast<named_thread<ppu_thread>>(selected_thread.lock());
|
auto ppu = std::static_pointer_cast<named_thread<ppu_thread>>(selected_thread.lock());
|
||||||
paused = false;
|
paused = false;
|
||||||
if (cmd.data[1] == 's') {
|
if (cmd.data[1] == 's')
|
||||||
|
{
|
||||||
ppu->state += cpu_flag::dbg_step;
|
ppu->state += cpu_flag::dbg_step;
|
||||||
}
|
}
|
||||||
ppu->state -= cpu_flag::dbg_pause;
|
ppu->state -= cpu_flag::dbg_pause;
|
||||||
//special case if app didn't start yet (only loaded)
|
//special case if app didn't start yet (only loaded)
|
||||||
if (Emu.IsReady()) {
|
if (Emu.IsReady())
|
||||||
|
{
|
||||||
Emu.Run(true);
|
Emu.Run(true);
|
||||||
}
|
}
|
||||||
if (Emu.IsPaused()) {
|
if (Emu.IsPaused())
|
||||||
|
{
|
||||||
Emu.Resume();
|
Emu.Resume();
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
ppu->state.notify_one();
|
ppu->state.notify_one();
|
||||||
}
|
}
|
||||||
wait_with_interrupts();
|
wait_with_interrupts();
|
||||||
@ -769,14 +829,17 @@ bool gdb_thread::cmd_set_breakpoint(gdb_cmd& cmd)
|
|||||||
{
|
{
|
||||||
char type = cmd.data[0];
|
char type = cmd.data[0];
|
||||||
//software breakpoint
|
//software breakpoint
|
||||||
if (type == '0') {
|
if (type == '0')
|
||||||
|
{
|
||||||
u32 addr = INVALID_PTR;
|
u32 addr = INVALID_PTR;
|
||||||
if (cmd.data.find(';') != umax) {
|
if (cmd.data.find(';') != umax)
|
||||||
|
{
|
||||||
GDB.warning("Received request to set breakpoint with condition, but they are not supported.");
|
GDB.warning("Received request to set breakpoint with condition, but they are not supported.");
|
||||||
return send_cmd_ack("E01");
|
return send_cmd_ack("E01");
|
||||||
}
|
}
|
||||||
sscanf_s(cmd.data.c_str(), "0,%x", &addr);
|
sscanf_s(cmd.data.c_str(), "0,%x", &addr);
|
||||||
if (addr == INVALID_PTR) {
|
if (addr == INVALID_PTR)
|
||||||
|
{
|
||||||
GDB.warning("Can't parse breakpoint request, data: '%s'.", cmd.data);
|
GDB.warning("Can't parse breakpoint request, data: '%s'.", cmd.data);
|
||||||
return send_cmd_ack("E02");
|
return send_cmd_ack("E02");
|
||||||
}
|
}
|
||||||
@ -791,10 +854,12 @@ bool gdb_thread::cmd_remove_breakpoint(gdb_cmd& cmd)
|
|||||||
{
|
{
|
||||||
char type = cmd.data[0];
|
char type = cmd.data[0];
|
||||||
//software breakpoint
|
//software breakpoint
|
||||||
if (type == '0') {
|
if (type == '0')
|
||||||
|
{
|
||||||
u32 addr = INVALID_PTR;
|
u32 addr = INVALID_PTR;
|
||||||
sscanf_s(cmd.data.c_str(), "0,%x", &addr);
|
sscanf_s(cmd.data.c_str(), "0,%x", &addr);
|
||||||
if (addr == INVALID_PTR) {
|
if (addr == INVALID_PTR)
|
||||||
|
{
|
||||||
GDB.warning("Can't parse breakpoint remove request, data: '%s'.", cmd.data);
|
GDB.warning("Can't parse breakpoint remove request, data: '%s'.", cmd.data);
|
||||||
return send_cmd_ack("E01");
|
return send_cmd_ack("E01");
|
||||||
}
|
}
|
||||||
|
@ -705,12 +705,12 @@ namespace vm
|
|||||||
{
|
{
|
||||||
const auto _cpu = get_current_cpu_thread();
|
const auto _cpu = get_current_cpu_thread();
|
||||||
|
|
||||||
if (_cpu && _cpu->id_type() == 1)
|
if (_cpu && _cpu->get_class() == thread_class::ppu)
|
||||||
{
|
{
|
||||||
// TODO: PPU g_escape
|
// TODO: PPU g_escape
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_cpu && _cpu->id_type() == 2)
|
if (_cpu && _cpu->get_class() == thread_class::spu)
|
||||||
{
|
{
|
||||||
spu_runtime::g_escape(static_cast<spu_thread*>(_cpu));
|
spu_runtime::g_escape(static_cast<spu_thread*>(_cpu));
|
||||||
}
|
}
|
||||||
|
@ -76,7 +76,7 @@ namespace rsx
|
|||||||
added_wait |= !self->state.test_and_set(cpu_flag::wait);
|
added_wait |= !self->state.test_and_set(cpu_flag::wait);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!self || self->id_type() != 0x55u)
|
if (!self || self->get_class() != thread_class::rsx)
|
||||||
{
|
{
|
||||||
mutex_.lock();
|
mutex_.lock();
|
||||||
continue;
|
continue;
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
constexpr auto qstr = QString::fromStdString;
|
constexpr auto qstr = QString::fromStdString;
|
||||||
|
|
||||||
extern bool is_using_interpreter(u32 id_type);
|
extern bool is_using_interpreter(thread_class t_class);
|
||||||
|
|
||||||
breakpoint_list::breakpoint_list(QWidget* parent, breakpoint_handler* handler) : QListWidget(parent), m_ppu_breakpoint_handler(handler)
|
breakpoint_list::breakpoint_list(QWidget* parent, breakpoint_handler* handler) : QListWidget(parent), m_ppu_breakpoint_handler(handler)
|
||||||
{
|
{
|
||||||
@ -107,15 +107,15 @@ void breakpoint_list::HandleBreakpointRequest(u32 loc, bool only_add)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_using_interpreter(m_cpu->id_type()))
|
if (!is_using_interpreter(m_cpu->get_class()))
|
||||||
{
|
{
|
||||||
QMessageBox::warning(this, tr("Interpreters-Only Feature!"), tr("Cannot set breakpoints on non-interpreter decoders."));
|
QMessageBox::warning(this, tr("Interpreters-Only Feature!"), tr("Cannot set breakpoints on non-interpreter decoders."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (m_cpu->id_type())
|
switch (m_cpu->get_class())
|
||||||
{
|
{
|
||||||
case 2:
|
case thread_class::spu:
|
||||||
{
|
{
|
||||||
if (loc >= SPU_LS_SIZE || loc % 4)
|
if (loc >= SPU_LS_SIZE || loc % 4)
|
||||||
{
|
{
|
||||||
@ -155,7 +155,8 @@ void breakpoint_list::HandleBreakpointRequest(u32 loc, bool only_add)
|
|||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case 1: break;
|
case thread_class::ppu:
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
QMessageBox::warning(this, tr("Unimplemented Breakpoints For Thread Type!"), tr("Cannot set breakpoints on a thread not an PPU/SPU currently, sorry."));
|
QMessageBox::warning(this, tr("Unimplemented Breakpoints For Thread Type!"), tr("Cannot set breakpoints on a thread not an PPU/SPU currently, sorry."));
|
||||||
return;
|
return;
|
||||||
|
@ -43,23 +43,23 @@ extern atomic_t<bool> g_debugger_pause_all_threads_on_bp;
|
|||||||
|
|
||||||
extern const ppu_decoder<ppu_itype> g_ppu_itype;
|
extern const ppu_decoder<ppu_itype> g_ppu_itype;
|
||||||
|
|
||||||
extern bool is_using_interpreter(u32 id_type)
|
extern bool is_using_interpreter(thread_class t_class)
|
||||||
{
|
{
|
||||||
switch (id_type)
|
switch (t_class)
|
||||||
{
|
{
|
||||||
case 1: return g_cfg.core.ppu_decoder != ppu_decoder_type::llvm;
|
case thread_class::ppu: return g_cfg.core.ppu_decoder != ppu_decoder_type::llvm;
|
||||||
case 2: return g_cfg.core.spu_decoder != spu_decoder_type::asmjit && g_cfg.core.spu_decoder != spu_decoder_type::llvm;
|
case thread_class::spu: return g_cfg.core.spu_decoder != spu_decoder_type::asmjit && g_cfg.core.spu_decoder != spu_decoder_type::llvm;
|
||||||
default: return true;
|
default: return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern std::shared_ptr<CPUDisAsm> make_disasm(const cpu_thread* cpu)
|
extern std::shared_ptr<CPUDisAsm> make_disasm(const cpu_thread* cpu)
|
||||||
{
|
{
|
||||||
switch (cpu->id_type())
|
switch (cpu->get_class())
|
||||||
{
|
{
|
||||||
case 1: return std::make_shared<PPUDisAsm>(cpu_disasm_mode::interpreter, vm::g_sudo_addr);
|
case thread_class::ppu: return std::make_shared<PPUDisAsm>(cpu_disasm_mode::interpreter, vm::g_sudo_addr);
|
||||||
case 2: return std::make_shared<SPUDisAsm>(cpu_disasm_mode::interpreter, static_cast<const spu_thread*>(cpu)->ls);
|
case thread_class::spu: return std::make_shared<SPUDisAsm>(cpu_disasm_mode::interpreter, static_cast<const spu_thread*>(cpu)->ls);
|
||||||
case 0x55: return std::make_shared<RSXDisAsm>(cpu_disasm_mode::interpreter, vm::g_sudo_addr, 0, cpu);
|
case thread_class::rsx: return std::make_shared<RSXDisAsm>(cpu_disasm_mode::interpreter, vm::g_sudo_addr, 0, cpu);
|
||||||
default: return nullptr;
|
default: return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -388,7 +388,7 @@ void debugger_frame::keyPressEvent(QKeyEvent* event)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const u32 address_limits = (cpu->id_type() == 2 ? 0x3fffc : ~3);
|
const u32 address_limits = (cpu->get_class() == thread_class::spu ? 0x3fffc : ~3);
|
||||||
const u32 pc = (m_debugger_list->m_pc & address_limits);
|
const u32 pc = (m_debugger_list->m_pc & address_limits);
|
||||||
const u32 selected = (m_debugger_list->m_showing_selected_instruction ? m_debugger_list->m_selected_instruction : cpu->get_pc()) & address_limits;
|
const u32 selected = (m_debugger_list->m_showing_selected_instruction ? m_debugger_list->m_selected_instruction : cpu->get_pc()) & address_limits;
|
||||||
|
|
||||||
@ -485,7 +485,7 @@ void debugger_frame::keyPressEvent(QKeyEvent* event)
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
if (cpu->id_type() == 2 && g_cfg.core.mfc_debug)
|
if (cpu->get_class() == thread_class::spu && g_cfg.core.mfc_debug)
|
||||||
{
|
{
|
||||||
const u32 max = get_max_allowed(tr("Max MFC cmds logged"), tr("Decimal only, max allowed is %0."), spu_thread::max_mfc_dump_idx);
|
const u32 max = get_max_allowed(tr("Max MFC cmds logged"), tr("Decimal only, max allowed is %0."), spu_thread::max_mfc_dump_idx);
|
||||||
|
|
||||||
@ -541,7 +541,7 @@ void debugger_frame::keyPressEvent(QKeyEvent* event)
|
|||||||
|
|
||||||
spu_log.success("SPU MFC dump of '%s': %s", cpu->get_name(), ret);
|
spu_log.success("SPU MFC dump of '%s': %s", cpu->get_name(), ret);
|
||||||
}
|
}
|
||||||
else if (cpu->id_type() == 1 && g_cfg.core.ppu_call_history)
|
else if (cpu->get_class() == thread_class::ppu && g_cfg.core.ppu_call_history)
|
||||||
{
|
{
|
||||||
const u32 max = get_max_allowed(tr("Max PPU calls logged"), tr("Decimal only, max allowed is %0."), ppu_thread::call_history_max_size);
|
const u32 max = get_max_allowed(tr("Max PPU calls logged"), tr("Decimal only, max allowed is %0."), ppu_thread::call_history_max_size);
|
||||||
|
|
||||||
@ -603,7 +603,7 @@ void debugger_frame::keyPressEvent(QKeyEvent* event)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cpu->id_type() == 1 || cpu->id_type() == 2)
|
if (cpu->get_class() == thread_class::ppu || cpu->get_class() == thread_class::spu)
|
||||||
{
|
{
|
||||||
if (!m_inst_editor)
|
if (!m_inst_editor)
|
||||||
{
|
{
|
||||||
@ -622,7 +622,7 @@ void debugger_frame::keyPressEvent(QKeyEvent* event)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cpu->id_type() == 1)
|
if (cpu->get_class() == thread_class::ppu)
|
||||||
{
|
{
|
||||||
static_cast<ppu_thread*>(cpu)->debugger_mode.atomic_op([](ppu_debugger_mode& mode)
|
static_cast<ppu_thread*>(cpu)->debugger_mode.atomic_op([](ppu_debugger_mode& mode)
|
||||||
{
|
{
|
||||||
@ -631,7 +631,7 @@ void debugger_frame::keyPressEvent(QKeyEvent* event)
|
|||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (cpu->id_type() == 2)
|
if (cpu->get_class() == thread_class::spu)
|
||||||
{
|
{
|
||||||
static_cast<spu_thread*>(cpu)->debugger_mode.atomic_op([](spu_debugger_mode& mode)
|
static_cast<spu_thread*>(cpu)->debugger_mode.atomic_op([](spu_debugger_mode& mode)
|
||||||
{
|
{
|
||||||
@ -650,9 +650,9 @@ void debugger_frame::keyPressEvent(QKeyEvent* event)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cpu->id_type() == 1 || cpu->id_type() == 2)
|
if (cpu->get_class() == thread_class::ppu || cpu->get_class() == thread_class::spu)
|
||||||
{
|
{
|
||||||
if (cpu->id_type() == 2 && modifiers & Qt::AltModifier)
|
if (cpu->get_class() == thread_class::spu && modifiers & Qt::AltModifier)
|
||||||
{
|
{
|
||||||
static_cast<spu_thread*>(cpu)->try_load_debug_capture();
|
static_cast<spu_thread*>(cpu)->try_load_debug_capture();
|
||||||
return;
|
return;
|
||||||
@ -677,7 +677,7 @@ void debugger_frame::keyPressEvent(QKeyEvent* event)
|
|||||||
|
|
||||||
if (modifiers & Qt::AltModifier)
|
if (modifiers & Qt::AltModifier)
|
||||||
{
|
{
|
||||||
if (cpu->id_type() == 0x55)
|
if (cpu->get_class() == thread_class::rsx)
|
||||||
{
|
{
|
||||||
if (u32 addr = static_cast<rsx::thread*>(cpu)->label_addr)
|
if (u32 addr = static_cast<rsx::thread*>(cpu)->label_addr)
|
||||||
{
|
{
|
||||||
@ -688,13 +688,13 @@ void debugger_frame::keyPressEvent(QKeyEvent* event)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cpu->id_type() == 1)
|
if (cpu->get_class() == thread_class::ppu)
|
||||||
{
|
{
|
||||||
new elf_memory_dumping_dialog(pc, m_gui_settings, this);
|
new elf_memory_dumping_dialog(pc, m_gui_settings, this);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cpu->id_type() != 2)
|
if (cpu->get_class() != thread_class::spu)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -720,14 +720,14 @@ void debugger_frame::keyPressEvent(QKeyEvent* event)
|
|||||||
|
|
||||||
const u32 selected = (m_debugger_list->m_showing_selected_instruction ? m_debugger_list->m_selected_instruction : cpu->get_pc()) & address_limits;
|
const u32 selected = (m_debugger_list->m_showing_selected_instruction ? m_debugger_list->m_selected_instruction : cpu->get_pc()) & address_limits;
|
||||||
|
|
||||||
switch (cpu->id_type())
|
switch (cpu->get_class())
|
||||||
{
|
{
|
||||||
case 2:
|
case thread_class::spu:
|
||||||
{
|
{
|
||||||
res = op_branch_targets(selected, spu_opcode_t{static_cast<spu_thread*>(cpu)->_ref<u32>(selected)});
|
res = op_branch_targets(selected, spu_opcode_t{static_cast<spu_thread*>(cpu)->_ref<u32>(selected)});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 1:
|
case thread_class::ppu:
|
||||||
{
|
{
|
||||||
be_t<ppu_opcode_t> op{};
|
be_t<ppu_opcode_t> op{};
|
||||||
|
|
||||||
@ -751,7 +751,7 @@ void debugger_frame::keyPressEvent(QKeyEvent* event)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_disasm && cpu->id_type() == 2)
|
if (m_disasm && cpu->get_class() == thread_class::spu)
|
||||||
{
|
{
|
||||||
// Save shared pointer to shared memory handle, ensure the destructor will not be called until the SPUDisAsm is destroyed
|
// Save shared pointer to shared memory handle, ensure the destructor will not be called until the SPUDisAsm is destroyed
|
||||||
static_cast<SPUDisAsm*>(m_disasm.get())->set_shm(static_cast<const spu_thread*>(cpu)->shm);
|
static_cast<SPUDisAsm*>(m_disasm.get())->set_shm(static_cast<const spu_thread*>(cpu)->shm);
|
||||||
@ -911,8 +911,8 @@ void debugger_frame::UpdateUI()
|
|||||||
else if (m_ui_update_ctr % 5 == 0 || m_ui_update_ctr < m_ui_fast_update_permission_deadline)
|
else if (m_ui_update_ctr % 5 == 0 || m_ui_update_ctr < m_ui_fast_update_permission_deadline)
|
||||||
{
|
{
|
||||||
const auto cia = cpu->get_pc();
|
const auto cia = cpu->get_pc();
|
||||||
const auto size_context = cpu->id_type() == 1 ? sizeof(ppu_thread) :
|
const auto size_context = cpu->get_class() == thread_class::ppu ? sizeof(ppu_thread) :
|
||||||
cpu->id_type() == 2 ? sizeof(spu_thread) : sizeof(cpu_thread);
|
cpu->get_class() == thread_class::spu ? sizeof(spu_thread) : sizeof(cpu_thread);
|
||||||
|
|
||||||
if (m_last_pc != cia || m_last_query_state.size() != size_context || std::memcmp(m_last_query_state.data(), static_cast<void *>(cpu), size_context))
|
if (m_last_pc != cia || m_last_query_state.size() != size_context || std::memcmp(m_last_query_state.data(), static_cast<void *>(cpu), size_context))
|
||||||
{
|
{
|
||||||
@ -940,7 +940,7 @@ void debugger_frame::UpdateUI()
|
|||||||
ShowPC();
|
ShowPC();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_using_interpreter(cpu->id_type()))
|
if (is_using_interpreter(cpu->get_class()))
|
||||||
{
|
{
|
||||||
m_btn_step->setEnabled(paused);
|
m_btn_step->setEnabled(paused);
|
||||||
m_btn_step_over->setEnabled(paused);
|
m_btn_step_over->setEnabled(paused);
|
||||||
@ -1188,7 +1188,7 @@ void debugger_frame::ShowGotoAddressDialog()
|
|||||||
expression_input->setFont(m_mono);
|
expression_input->setFont(m_mono);
|
||||||
expression_input->setMaxLength(18);
|
expression_input->setMaxLength(18);
|
||||||
|
|
||||||
if (const auto thread = get_cpu(); !thread || thread->id_type() != 2)
|
if (const auto thread = get_cpu(); !thread || thread->get_class() != thread_class::spu)
|
||||||
{
|
{
|
||||||
expression_input->setValidator(new QRegularExpressionValidator(QRegularExpression("^(0[xX])?0*[a-fA-F0-9]{0,8}$"), this));
|
expression_input->setValidator(new QRegularExpressionValidator(QRegularExpression("^(0[xX])?0*[a-fA-F0-9]{0,8}$"), this));
|
||||||
}
|
}
|
||||||
@ -1343,7 +1343,7 @@ void debugger_frame::DoStep(bool step_over)
|
|||||||
{
|
{
|
||||||
if (const auto cpu = get_cpu())
|
if (const auto cpu = get_cpu())
|
||||||
{
|
{
|
||||||
bool should_step_over = step_over && cpu->id_type() == 1;
|
bool should_step_over = step_over && cpu->get_class() == thread_class::ppu;
|
||||||
|
|
||||||
// If stepping over, lay at the same spot and wait for the thread to finish the call
|
// If stepping over, lay at the same spot and wait for the thread to finish the call
|
||||||
// If not, fixate on the current pointed instruction
|
// If not, fixate on the current pointed instruction
|
||||||
@ -1354,7 +1354,7 @@ void debugger_frame::DoStep(bool step_over)
|
|||||||
m_debugger_list->ShowAddress(cpu->get_pc() + 4, false);
|
m_debugger_list->ShowAddress(cpu->get_pc() + 4, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (step_over && cpu->id_type() == 0x55)
|
if (step_over && cpu->get_class() == thread_class::rsx)
|
||||||
{
|
{
|
||||||
const bool was_paused = cpu->is_paused();
|
const bool was_paused = cpu->is_paused();
|
||||||
static_cast<rsx::thread*>(cpu)->pause_on_draw = true;
|
static_cast<rsx::thread*>(cpu)->pause_on_draw = true;
|
||||||
@ -1370,7 +1370,7 @@ void debugger_frame::DoStep(bool step_over)
|
|||||||
|
|
||||||
if (const auto _state = +cpu->state; _state & s_pause_flags && _state & cpu_flag::wait && !(_state & cpu_flag::dbg_step))
|
if (const auto _state = +cpu->state; _state & s_pause_flags && _state & cpu_flag::wait && !(_state & cpu_flag::dbg_step))
|
||||||
{
|
{
|
||||||
if (should_step_over && cpu->id_type() == 1)
|
if (should_step_over && cpu->get_class() == thread_class::ppu)
|
||||||
{
|
{
|
||||||
const u32 current_instruction_pc = cpu->get_pc();
|
const u32 current_instruction_pc = cpu->get_pc();
|
||||||
|
|
||||||
@ -1480,7 +1480,7 @@ void debugger_frame::EnableButtons(bool enable)
|
|||||||
|
|
||||||
if (!cpu) enable = false;
|
if (!cpu) enable = false;
|
||||||
|
|
||||||
const bool step = enable && is_using_interpreter(cpu->id_type());
|
const bool step = enable && is_using_interpreter(cpu->get_class());
|
||||||
|
|
||||||
m_go_to_addr->setEnabled(enable);
|
m_go_to_addr->setEnabled(enable);
|
||||||
m_go_to_pc->setEnabled(enable);
|
m_go_to_pc->setEnabled(enable);
|
||||||
|
@ -46,7 +46,7 @@ debugger_list::debugger_list(QWidget* parent, std::shared_ptr<gui_settings> gui_
|
|||||||
|
|
||||||
u32 pc = m_start_addr;
|
u32 pc = m_start_addr;
|
||||||
|
|
||||||
for (; m_cpu && m_cpu->id_type() == 0x55 && row; row--)
|
for (; m_cpu && m_cpu->get_class() == thread_class::rsx && row; row--)
|
||||||
{
|
{
|
||||||
// If scrolling forwards (downwards), we can skip entire commands
|
// If scrolling forwards (downwards), we can skip entire commands
|
||||||
pc += std::max<u32>(m_disasm->disasm(pc), 4);
|
pc += std::max<u32>(m_disasm->disasm(pc), 4);
|
||||||
@ -73,12 +73,12 @@ u32 debugger_list::GetStartAddress(u32 address)
|
|||||||
const u32 steps = m_item_count / 3;
|
const u32 steps = m_item_count / 3;
|
||||||
const u32 inst_count_jump_on_step = std::min<u32>(steps, 4);
|
const u32 inst_count_jump_on_step = std::min<u32>(steps, 4);
|
||||||
|
|
||||||
const bool is_spu = m_cpu && m_cpu->id_type() == 2;
|
const bool is_spu = m_cpu && m_cpu->get_class() == thread_class::spu;
|
||||||
const u32 address_mask = (is_spu ? 0x3fffc : ~3);
|
const u32 address_mask = (is_spu ? 0x3fffc : ~3);
|
||||||
|
|
||||||
u32 result = address & address_mask;
|
u32 result = address & address_mask;
|
||||||
|
|
||||||
if (m_cpu && m_cpu->id_type() == 0x55)
|
if (m_cpu && m_cpu->get_class() == thread_class::rsx)
|
||||||
{
|
{
|
||||||
if (auto [count, res] = static_cast<rsx::thread*>(m_cpu)->try_get_pc_of_x_cmds_backwards(steps, address); count == steps)
|
if (auto [count, res] = static_cast<rsx::thread*>(m_cpu)->try_get_pc_of_x_cmds_backwards(steps, address); count == steps)
|
||||||
{
|
{
|
||||||
@ -92,7 +92,7 @@ u32 debugger_list::GetStartAddress(u32 address)
|
|||||||
|
|
||||||
u32 upper_bound = (m_start_addr + (steps * 4)) & address_mask;
|
u32 upper_bound = (m_start_addr + (steps * 4)) & address_mask;
|
||||||
|
|
||||||
if (m_cpu && m_cpu->id_type() == 0x55)
|
if (m_cpu && m_cpu->get_class() == thread_class::rsx)
|
||||||
{
|
{
|
||||||
if (auto [count, res] = static_cast<rsx::thread*>(m_cpu)->try_get_pc_of_x_cmds_backwards(0 - steps, m_start_addr); count == steps)
|
if (auto [count, res] = static_cast<rsx::thread*>(m_cpu)->try_get_pc_of_x_cmds_backwards(0 - steps, m_start_addr); count == steps)
|
||||||
{
|
{
|
||||||
@ -133,20 +133,20 @@ void debugger_list::ShowAddress(u32 addr, bool select_addr, bool direct)
|
|||||||
{
|
{
|
||||||
const decltype(spu_thread::local_breakpoints)* spu_bps_list{};
|
const decltype(spu_thread::local_breakpoints)* spu_bps_list{};
|
||||||
|
|
||||||
if (m_cpu && m_cpu->id_type() == 2)
|
if (m_cpu && m_cpu->get_class() == thread_class::spu)
|
||||||
{
|
{
|
||||||
spu_bps_list = &static_cast<spu_thread*>(m_cpu)->local_breakpoints;
|
spu_bps_list = &static_cast<spu_thread*>(m_cpu)->local_breakpoints;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto IsBreakpoint = [&](u32 pc)
|
auto IsBreakpoint = [&](u32 pc)
|
||||||
{
|
{
|
||||||
switch (m_cpu ? m_cpu->id_type() : 0)
|
switch (m_cpu ? m_cpu->get_class() : thread_class::general)
|
||||||
{
|
{
|
||||||
case 1:
|
case thread_class::ppu:
|
||||||
{
|
{
|
||||||
return m_ppu_breakpoint_handler->HasBreakpoint(pc);
|
return m_ppu_breakpoint_handler->HasBreakpoint(pc);
|
||||||
}
|
}
|
||||||
case 2:
|
case thread_class::spu:
|
||||||
{
|
{
|
||||||
const u32 pos_at = pc / 4;
|
const u32 pos_at = pc / 4;
|
||||||
const u32 pos_bit = 1u << (pos_at % 8);
|
const u32 pos_bit = 1u << (pos_at % 8);
|
||||||
@ -202,7 +202,7 @@ void debugger_list::ShowAddress(u32 addr, bool select_addr, bool direct)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const bool is_spu = m_cpu->id_type() == 2;
|
const bool is_spu = m_cpu->get_class() == thread_class::spu;
|
||||||
const u32 address_limits = (is_spu ? 0x3fffc : ~3);
|
const u32 address_limits = (is_spu ? 0x3fffc : ~3);
|
||||||
const u32 current_pc = m_cpu->get_pc();
|
const u32 current_pc = m_cpu->get_pc();
|
||||||
m_start_addr &= address_limits;
|
m_start_addr &= address_limits;
|
||||||
@ -238,14 +238,14 @@ void debugger_list::ShowAddress(u32 addr, bool select_addr, bool direct)
|
|||||||
list_item->setBackground(default_background);
|
list_item->setBackground(default_background);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_cpu->id_type() == 1 && !vm::check_addr(pc, 0))
|
if (m_cpu->get_class() == thread_class::ppu && !vm::check_addr(pc, 0))
|
||||||
{
|
{
|
||||||
list_item->setText((IsBreakpoint(pc) ? ">> " : " ") + qstr(fmt::format("[%08x] ?? ?? ?? ??:", pc)));
|
list_item->setText((IsBreakpoint(pc) ? ">> " : " ") + qstr(fmt::format("[%08x] ?? ?? ?? ??:", pc)));
|
||||||
count = 4;
|
count = 4;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_cpu->id_type() == 1 && !vm::check_addr(pc, vm::page_executable))
|
if (m_cpu->get_class() == thread_class::ppu && !vm::check_addr(pc, vm::page_executable))
|
||||||
{
|
{
|
||||||
const u32 data = *vm::get_super_ptr<atomic_be_t<u32>>(pc);
|
const u32 data = *vm::get_super_ptr<atomic_be_t<u32>>(pc);
|
||||||
list_item->setText((IsBreakpoint(pc) ? ">> " : " ") + qstr(fmt::format("[%08x] %02x %02x %02x %02x:", pc,
|
list_item->setText((IsBreakpoint(pc) ? ">> " : " ") + qstr(fmt::format("[%08x] %02x %02x %02x %02x:", pc,
|
||||||
@ -287,13 +287,13 @@ void debugger_list::EnableThreadFollowing(bool enable)
|
|||||||
|
|
||||||
void debugger_list::scroll(s32 steps)
|
void debugger_list::scroll(s32 steps)
|
||||||
{
|
{
|
||||||
for (; m_cpu && m_cpu->id_type() == 0x55 && steps > 0; steps--)
|
for (; m_cpu && m_cpu->get_class() == thread_class::rsx && steps > 0; steps--)
|
||||||
{
|
{
|
||||||
// If scrolling forwards (downwards), we can skip entire commands
|
// If scrolling forwards (downwards), we can skip entire commands
|
||||||
m_start_addr += std::max<u32>(m_disasm->disasm(m_start_addr), 4);
|
m_start_addr += std::max<u32>(m_disasm->disasm(m_start_addr), 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_cpu && m_cpu->id_type() == 0x55 && steps < 0)
|
if (m_cpu && m_cpu->get_class() == thread_class::rsx && steps < 0)
|
||||||
{
|
{
|
||||||
// If scrolling backwards (upwards), try to obtain the start of commands tail
|
// If scrolling backwards (upwards), try to obtain the start of commands tail
|
||||||
if (auto [count, res] = static_cast<rsx::thread*>(m_cpu)->try_get_pc_of_x_cmds_backwards(-steps, m_start_addr); count == 0u - steps)
|
if (auto [count, res] = static_cast<rsx::thread*>(m_cpu)->try_get_pc_of_x_cmds_backwards(-steps, m_start_addr); count == 0u - steps)
|
||||||
@ -347,7 +347,7 @@ void debugger_list::keyPressEvent(QKeyEvent* event)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_cpu && m_cpu->id_type() == 0x55)
|
if (m_cpu && m_cpu->get_class() == thread_class::rsx)
|
||||||
{
|
{
|
||||||
create_rsx_command_detail(m_showing_selected_instruction ? m_selected_instruction : m_pc);
|
create_rsx_command_detail(m_showing_selected_instruction ? m_selected_instruction : m_pc);
|
||||||
return;
|
return;
|
||||||
@ -420,7 +420,7 @@ void debugger_list::mouseDoubleClickEvent(QMouseEvent* event)
|
|||||||
|
|
||||||
u32 pc = m_start_addr;
|
u32 pc = m_start_addr;
|
||||||
|
|
||||||
for (; m_cpu && m_cpu->id_type() == 0x55 && i; i--)
|
for (; m_cpu && m_cpu->get_class() == thread_class::rsx && i; i--)
|
||||||
{
|
{
|
||||||
// If scrolling forwards (downwards), we can skip entire commands
|
// If scrolling forwards (downwards), we can skip entire commands
|
||||||
pc += std::max<u32>(m_disasm->disasm(pc), 4);
|
pc += std::max<u32>(m_disasm->disasm(pc), 4);
|
||||||
|
@ -29,7 +29,7 @@ instruction_editor_dialog::instruction_editor_dialog(QWidget *parent, u32 _pc, C
|
|||||||
|
|
||||||
const auto cpu = m_get_cpu();
|
const auto cpu = m_get_cpu();
|
||||||
|
|
||||||
m_cpu_offset = cpu && cpu->id_type() == 2 ? static_cast<spu_thread&>(*cpu).ls : vm::g_sudo_addr;
|
m_cpu_offset = cpu && cpu->get_class() == thread_class::spu ? static_cast<spu_thread&>(*cpu).ls : vm::g_sudo_addr;
|
||||||
|
|
||||||
QVBoxLayout* vbox_panel(new QVBoxLayout());
|
QVBoxLayout* vbox_panel(new QVBoxLayout());
|
||||||
QHBoxLayout* hbox_panel(new QHBoxLayout());
|
QHBoxLayout* hbox_panel(new QHBoxLayout());
|
||||||
@ -60,7 +60,7 @@ instruction_editor_dialog::instruction_editor_dialog(QWidget *parent, u32 _pc, C
|
|||||||
vbox_right_panel->addWidget(m_instr);
|
vbox_right_panel->addWidget(m_instr);
|
||||||
vbox_right_panel->addWidget(m_preview);
|
vbox_right_panel->addWidget(m_preview);
|
||||||
|
|
||||||
if (cpu && cpu->id_type() == 2)
|
if (cpu && cpu->get_class() == thread_class::spu)
|
||||||
{
|
{
|
||||||
// Print block information as if this instruction is its beginning
|
// Print block information as if this instruction is its beginning
|
||||||
vbox_left_panel->addWidget(new QLabel(tr("Block Info: ")));
|
vbox_left_panel->addWidget(new QLabel(tr("Block Info: ")));
|
||||||
@ -70,7 +70,7 @@ instruction_editor_dialog::instruction_editor_dialog(QWidget *parent, u32 _pc, C
|
|||||||
m_func_info->setText(qstr(format_spu_func_info(m_pc, cpu)));
|
m_func_info->setText(qstr(format_spu_func_info(m_pc, cpu)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cpu && cpu->id_type() == 2)
|
if (cpu && cpu->get_class() == thread_class::spu)
|
||||||
{
|
{
|
||||||
const auto& spu = static_cast<spu_thread&>(*cpu);
|
const auto& spu = static_cast<spu_thread&>(*cpu);
|
||||||
|
|
||||||
@ -118,7 +118,7 @@ instruction_editor_dialog::instruction_editor_dialog(QWidget *parent, u32 _pc, C
|
|||||||
|
|
||||||
const be_t<u32> swapped{static_cast<u32>(opcode)};
|
const be_t<u32> swapped{static_cast<u32>(opcode)};
|
||||||
|
|
||||||
if (cpu->id_type() == 1)
|
if (cpu->get_class() == thread_class::ppu)
|
||||||
{
|
{
|
||||||
if (!ppu_patch(m_pc, static_cast<u32>(opcode)))
|
if (!ppu_patch(m_pc, static_cast<u32>(opcode)))
|
||||||
{
|
{
|
||||||
|
@ -341,7 +341,7 @@ void kernel_explorer::update()
|
|||||||
{
|
{
|
||||||
for (; cpu; cpu = cpu->get_next_cpu())
|
for (; cpu; cpu = cpu->get_next_cpu())
|
||||||
{
|
{
|
||||||
add_leaf(tree, qstr(fmt::format("Waiter: ID: 0x%x", cpu->id_type() == 2 ? static_cast<spu_thread*>(cpu)->lv2_id : cpu->id)));
|
add_leaf(tree, qstr(fmt::format("Waiter: ID: 0x%x", cpu->get_class() == thread_class::spu ? static_cast<spu_thread*>(cpu)->lv2_id : cpu->id)));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -41,9 +41,9 @@ memory_viewer_panel::memory_viewer_panel(QWidget* parent, std::shared_ptr<CPUDis
|
|||||||
const auto cpu = m_get_cpu();
|
const auto cpu = m_get_cpu();
|
||||||
|
|
||||||
if (!cpu) return thread_type::none;
|
if (!cpu) return thread_type::none;
|
||||||
if (cpu->id_type() == 1) return thread_type::ppu;
|
if (cpu->get_class() == thread_class::ppu) return thread_type::ppu;
|
||||||
if (cpu->id_type() == 0x55) return thread_type::rsx;
|
if (cpu->get_class() == thread_class::rsx) return thread_type::rsx;
|
||||||
if (cpu->id_type() == 2) return thread_type::spu;
|
if (cpu->get_class() == thread_class::spu) return thread_type::spu;
|
||||||
|
|
||||||
fmt::throw_exception("Unknown CPU type (0x%x)", cpu->id_type());
|
fmt::throw_exception("Unknown CPU type (0x%x)", cpu->id_type());
|
||||||
}())
|
}())
|
||||||
|
@ -106,7 +106,7 @@ register_editor_dialog::register_editor_dialog(QWidget *parent, CPUDisAsm* _disa
|
|||||||
|
|
||||||
if (const auto cpu = m_get_cpu())
|
if (const auto cpu = m_get_cpu())
|
||||||
{
|
{
|
||||||
if (cpu->id_type() == 1)
|
if (cpu->get_class() == thread_class::ppu)
|
||||||
{
|
{
|
||||||
for (int i = ppu_r0; i <= ppu_r31; i++) m_register_combo->addItem(qstr(fmt::format("r%d", i % 32)), i);
|
for (int i = ppu_r0; i <= ppu_r31; i++) m_register_combo->addItem(qstr(fmt::format("r%d", i % 32)), i);
|
||||||
for (int i = ppu_f0; i <= ppu_f31; i++) m_register_combo->addItem(qstr(fmt::format("f%d", i % 32)), i);
|
for (int i = ppu_f0; i <= ppu_f31; i++) m_register_combo->addItem(qstr(fmt::format("f%d", i % 32)), i);
|
||||||
@ -122,7 +122,7 @@ register_editor_dialog::register_editor_dialog(QWidget *parent, CPUDisAsm* _disa
|
|||||||
m_register_combo->addItem("Priority", +PPU_PRIO);
|
m_register_combo->addItem("Priority", +PPU_PRIO);
|
||||||
//m_register_combo->addItem("Priority 2", +PPU_PRIO2);
|
//m_register_combo->addItem("Priority 2", +PPU_PRIO2);
|
||||||
}
|
}
|
||||||
else if (cpu->id_type() == 2)
|
else if (cpu->get_class() == thread_class::spu)
|
||||||
{
|
{
|
||||||
for (int i = spu_r0; i <= spu_r127; i++) m_register_combo->addItem(qstr(fmt::format("r%d", i % 128)), i);
|
for (int i = spu_r0; i <= spu_r127; i++) m_register_combo->addItem(qstr(fmt::format("r%d", i % 128)), i);
|
||||||
m_register_combo->addItem("MFC Pending Events", +MFC_PEVENTS);
|
m_register_combo->addItem("MFC Pending Events", +MFC_PEVENTS);
|
||||||
@ -174,7 +174,7 @@ void register_editor_dialog::updateRegister(int reg) const
|
|||||||
if (!cpu)
|
if (!cpu)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
else if (cpu->id_type() == 1)
|
else if (cpu->get_class() == thread_class::ppu)
|
||||||
{
|
{
|
||||||
const auto& ppu = *static_cast<const ppu_thread*>(cpu);
|
const auto& ppu = *static_cast<const ppu_thread*>(cpu);
|
||||||
|
|
||||||
@ -199,7 +199,7 @@ void register_editor_dialog::updateRegister(int reg) const
|
|||||||
else if (reg == RESERVATION_LOST) str = sstr(ppu.raddr ? tr("Lose reservation on OK") : tr("Reservation is inactive"));
|
else if (reg == RESERVATION_LOST) str = sstr(ppu.raddr ? tr("Lose reservation on OK") : tr("Reservation is inactive"));
|
||||||
else if (reg == PC) str = fmt::format("%08x", ppu.cia);
|
else if (reg == PC) str = fmt::format("%08x", ppu.cia);
|
||||||
}
|
}
|
||||||
else if (cpu->id_type() == 2)
|
else if (cpu->get_class() == thread_class::spu)
|
||||||
{
|
{
|
||||||
const auto& spu = *static_cast<const spu_thread*>(cpu);
|
const auto& spu = *static_cast<const spu_thread*>(cpu);
|
||||||
|
|
||||||
@ -263,7 +263,7 @@ void register_editor_dialog::OnOkay()
|
|||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (cpu->id_type() == 1)
|
else if (cpu->get_class() == thread_class::ppu)
|
||||||
{
|
{
|
||||||
auto& ppu = *static_cast<ppu_thread*>(cpu);
|
auto& ppu = *static_cast<ppu_thread*>(cpu);
|
||||||
|
|
||||||
@ -350,7 +350,7 @@ void register_editor_dialog::OnOkay()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (cpu->id_type() == 2)
|
else if (cpu->get_class() == thread_class::spu)
|
||||||
{
|
{
|
||||||
auto& spu = *static_cast<spu_thread*>(cpu);
|
auto& spu = *static_cast<spu_thread*>(cpu);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user