diff --git a/Utilities/SleepQueue.h b/Utilities/SleepQueue.h index e11c5417df..3169828c34 100644 --- a/Utilities/SleepQueue.h +++ b/Utilities/SleepQueue.h @@ -9,10 +9,8 @@ static struct defer_sleep_tag {} constexpr defer_sleep{}; template using sleep_queue = std::deque; // Automatic object handling a thread pointer (T*) in the sleep queue -// Sleep is called in the constructor (if not null) -// Awake is called in the destructor (if not null) // Sleep queue is actually std::deque with pointers, be careful about the lifetime -template +template class sleep_entry final { sleep_queue& m_queue; @@ -24,7 +22,6 @@ public: : m_queue(queue) , m_thread(entry) { - if (Sleep) (m_thread.*Sleep)(); } // Constructor; calls enter() @@ -38,7 +35,6 @@ public: ~sleep_entry() { leave(); - if (Awake) (m_thread.*Awake)(); } // Add thread to the sleep queue diff --git a/Utilities/types.h b/Utilities/types.h index 89c8dadef5..114042928f 100644 --- a/Utilities/types.h +++ b/Utilities/types.h @@ -543,6 +543,62 @@ using any16 = any_pod; using any32 = any_pod; using any64 = any_pod; +struct cmd64 : any64 +{ + struct pair_t + { + any32 arg1; + any32 arg2; + }; + + cmd64() = default; + + template + cmd64(const T& value) + : any64(value) + { + } + + template + cmd64(const T1& arg1, const T2& arg2) + : any64(pair_t{arg1, arg2}) + { + } + + explicit operator bool() const + { + return as() != 0; + } + + // TODO: compatibility with std::pair/std::tuple? + + template + decltype(auto) arg1() + { + return as().arg1.as(); + } + + template + decltype(auto) arg1() const + { + return as().arg1.as(); + } + + template + decltype(auto) arg2() + { + return as().arg2.as(); + } + + template + decltype(auto) arg2() const + { + return as().arg2.as(); + } +}; + +static_assert(sizeof(cmd64) == 8 && std::is_pod::value, "Incorrect cmd64 type"); + // Allows to define integer convertible to multiple types template struct multicast : multicast diff --git a/rpcs3/Emu/CPU/CPUThread.cpp b/rpcs3/Emu/CPU/CPUThread.cpp index bb853a21d8..47dab45ee0 100644 --- a/rpcs3/Emu/CPU/CPUThread.cpp +++ b/rpcs3/Emu/CPU/CPUThread.cpp @@ -5,38 +5,22 @@ #include template<> -void fmt_class_string::format(std::string& out, u64 arg) +void fmt_class_string::format(std::string& out, u64 arg) { - format_enum(out, arg, [](auto arg) - { - switch (arg) - { - STR_CASE(cpu_type::ppu); - STR_CASE(cpu_type::spu); - STR_CASE(cpu_type::arm); - } - - return unknown; - }); -} - -template<> -void fmt_class_string::format(std::string& out, u64 arg) -{ - format_enum(out, arg, [](cpu_state f) + format_enum(out, arg, [](cpu_flag f) { switch (f) { - STR_CASE(cpu_state::stop); - STR_CASE(cpu_state::exit); - STR_CASE(cpu_state::suspend); - STR_CASE(cpu_state::ret); - STR_CASE(cpu_state::signal); - STR_CASE(cpu_state::dbg_global_pause); - STR_CASE(cpu_state::dbg_global_stop); - STR_CASE(cpu_state::dbg_pause); - STR_CASE(cpu_state::dbg_step); - case cpu_state::__bitset_enum_max: break; + STR_CASE(cpu_flag::stop); + STR_CASE(cpu_flag::exit); + STR_CASE(cpu_flag::suspend); + STR_CASE(cpu_flag::ret); + STR_CASE(cpu_flag::signal); + STR_CASE(cpu_flag::dbg_global_pause); + STR_CASE(cpu_flag::dbg_global_stop); + STR_CASE(cpu_flag::dbg_pause); + STR_CASE(cpu_flag::dbg_step); + case cpu_flag::__bitset_enum_max: break; } return unknown; @@ -44,16 +28,16 @@ void fmt_class_string::format(std::string& out, u64 arg) } template<> -void fmt_class_string>::format(std::string& out, u64 arg) +void fmt_class_string>::format(std::string& out, u64 arg) { - format_bitset(out, arg, "[", "|", "]", &fmt_class_string::format); + format_bitset(out, arg, "[", "|", "]", &fmt_class_string::format); } thread_local cpu_thread* g_tls_current_cpu_thread = nullptr; void cpu_thread::on_task() { - state -= cpu_state::exit; + state -= cpu_flag::exit; g_tls_current_cpu_thread = this; @@ -62,12 +46,12 @@ void cpu_thread::on_task() std::unique_lock lock(*this); // Check thread status - while (!test(state & cpu_state::exit)) + while (!test(state & cpu_flag::exit)) { CHECK_EMU_STATUS; // check stop status - if (!test(state & cpu_state::stop)) + if (!test(state & cpu_flag::stop)) { if (lock) lock.unlock(); @@ -75,7 +59,7 @@ void cpu_thread::on_task() { cpu_task(); } - catch (cpu_state _s) + catch (cpu_flag _s) { state += _s; } @@ -85,7 +69,7 @@ void cpu_thread::on_task() throw; } - state -= cpu_state::ret; + state -= cpu_flag::ret; continue; } @@ -101,7 +85,7 @@ void cpu_thread::on_task() void cpu_thread::on_stop() { - state += cpu_state::exit; + state += cpu_flag::exit; lock_notify(); } @@ -109,8 +93,7 @@ cpu_thread::~cpu_thread() { } -cpu_thread::cpu_thread(cpu_type type) - : type(type) +cpu_thread::cpu_thread() { } @@ -122,7 +105,7 @@ bool cpu_thread::check_state() { CHECK_EMU_STATUS; // check at least once - if (test(state & cpu_state::exit)) + if (test(state & cpu_flag::exit)) { return true; } @@ -143,15 +126,15 @@ bool cpu_thread::check_state() const auto state_ = state.load(); - if (test(state_, cpu_state::ret + cpu_state::stop)) + if (test(state_, cpu_flag::ret + cpu_flag::stop)) { return true; } - if (test(state_, cpu_state::dbg_step)) + if (test(state_, cpu_flag::dbg_step)) { - state += cpu_state::dbg_pause; - state -= cpu_state::dbg_step; + state += cpu_flag::dbg_pause; + state -= cpu_flag::dbg_step; } return false; @@ -159,6 +142,6 @@ bool cpu_thread::check_state() void cpu_thread::run() { - state -= cpu_state::stop; + state -= cpu_flag::stop; lock_notify(); } diff --git a/rpcs3/Emu/CPU/CPUThread.h b/rpcs3/Emu/CPU/CPUThread.h index 7507f16ea7..2bc666df5e 100644 --- a/rpcs3/Emu/CPU/CPUThread.h +++ b/rpcs3/Emu/CPU/CPUThread.h @@ -3,16 +3,8 @@ #include "../Utilities/Thread.h" #include "../Utilities/bit_set.h" -// CPU Thread Type (TODO: probably remove, use id and idm to classify threads) -enum class cpu_type : u8 -{ - ppu, // PPU Thread - spu, // SPU Thread - arm, // ARMv7 Thread -}; - -// CPU Thread State flags (TODO: use u32 once cpu_type is removed) -enum class cpu_state : u16 +// cpu_thread state flags +enum class cpu_flag : u32 { stop, // Thread not running (HLE, initial state) exit, // Irreversible exit @@ -28,8 +20,8 @@ enum class cpu_state : u16 __bitset_enum_max }; -// CPU Thread State flags: pause state union -constexpr bs_t cpu_state_pause = cpu_state::suspend + cpu_state::dbg_global_pause + cpu_state::dbg_pause; +// cpu_flag set for pause state +constexpr bs_t cpu_state_pause = cpu_flag::suspend + cpu_flag::dbg_global_pause + cpu_flag::dbg_pause; class cpu_thread : public named_thread { @@ -40,12 +32,11 @@ public: virtual ~cpu_thread() override; const id_value<> id{}; - const cpu_type type; - cpu_thread(cpu_type type); + cpu_thread(); // Public thread state - atomic_t> state{+cpu_state::stop}; + atomic_t> state{+cpu_flag::stop}; // Object associated with sleep state, possibly synchronization primitive (mutex, semaphore, etc.) atomic_t owner{}; diff --git a/rpcs3/Emu/Cell/Modules/cellFs.cpp b/rpcs3/Emu/Cell/Modules/cellFs.cpp index 792d53ded2..4d5216c648 100644 --- a/rpcs3/Emu/Cell/Modules/cellFs.cpp +++ b/rpcs3/Emu/Cell/Modules/cellFs.cpp @@ -699,11 +699,11 @@ struct fs_aio_thread : ppu_thread virtual void cpu_task() override { - while (ppu_cmd cmd = cmd_wait()) + while (cmd64 cmd = cmd_wait()) { const u32 type = cmd.arg1(); const s32 xid = cmd.arg2(); - const ppu_cmd cmd2 = cmd_queue[cmd_queue.peek() + 1]; + const cmd64 cmd2 = cmd_get(1); const auto aio = cmd2.arg1>(); const auto func = cmd2.arg2(); cmd_pop(1); diff --git a/rpcs3/Emu/Cell/Modules/cellSpursSpu.cpp b/rpcs3/Emu/Cell/Modules/cellSpursSpu.cpp index 817d333298..68930eabcb 100644 --- a/rpcs3/Emu/Cell/Modules/cellSpursSpu.cpp +++ b/rpcs3/Emu/Cell/Modules/cellSpursSpu.cpp @@ -1819,7 +1819,7 @@ void spursTasksetDispatch(SPUThread& spu) { // TODO: Figure this out spu.status |= SPU_STATUS_STOPPED_BY_STOP; - throw cpu_state::stop; + throw cpu_flag::stop; } spursTasksetStartTask(spu, taskInfo->args); @@ -1873,7 +1873,7 @@ void spursTasksetDispatch(SPUThread& spu) { // TODO: Figure this out spu.status |= SPU_STATUS_STOPPED_BY_STOP; - throw cpu_state::stop; + throw cpu_flag::stop; } spu.gpr[3].clear(); diff --git a/rpcs3/Emu/Cell/Modules/cellVdec.cpp b/rpcs3/Emu/Cell/Modules/cellVdec.cpp index 4d297e0f19..2cb793059a 100644 --- a/rpcs3/Emu/Cell/Modules/cellVdec.cpp +++ b/rpcs3/Emu/Cell/Modules/cellVdec.cpp @@ -25,7 +25,7 @@ vm::gvar _cell_vdec_prx_ver; // ??? enum class vdec_cmd : u32 { - none = 0, + null, start_seq, end_seq, @@ -150,7 +150,7 @@ struct vdec_thread : ppu_thread virtual void cpu_task() override { - while (ppu_cmd cmd = cmd_wait()) + while (cmd64 cmd = cmd_wait()) { switch (vdec_cmd vcmd = cmd.arg1()) { @@ -182,14 +182,13 @@ struct vdec_thread : ppu_thread if (vcmd == vdec_cmd::decode) { - const u32 pos = cmd_queue.peek(); au_type = cmd.arg2(); // TODO - au_addr = cmd_queue[pos + 1].load().arg1(); - au_size = cmd_queue[pos + 1].load().arg2(); - au_pts = cmd_queue[pos + 2].load().as(); - au_dts = cmd_queue[pos + 3].load().as(); - au_usrd = cmd_queue[pos + 4].load().as(); // TODO - au_spec = cmd_queue[pos + 5].load().as(); // TODO + au_addr = cmd_get(1).arg1(); + au_size = cmd_get(1).arg2(); + au_pts = cmd_get(2).as(); + au_dts = cmd_get(3).as(); + au_usrd = cmd_get(4).as(); // TODO + au_spec = cmd_get(5).as(); // TODO cmd_pop(5); packet.data = vm::_ptr(au_addr); @@ -349,7 +348,7 @@ struct vdec_thread : ppu_thread case vdec_cmd::close: { cmd_pop(); - state += cpu_state::exit; + state += cpu_flag::exit; return; } diff --git a/rpcs3/Emu/Cell/PPUFunction.cpp b/rpcs3/Emu/Cell/PPUFunction.cpp index ebee4e9916..c91ea73bc4 100644 --- a/rpcs3/Emu/Cell/PPUFunction.cpp +++ b/rpcs3/Emu/Cell/PPUFunction.cpp @@ -2359,7 +2359,7 @@ s32 ppu_error_code::report(s32 error, const char* text) { if (auto thread = get_current_cpu_thread()) { - if (thread->type == cpu_type::ppu) + if (thread->id >= ppu_thread::id_min) { if (auto func = static_cast(thread)->last_function) { @@ -2383,7 +2383,7 @@ std::vector& ppu_function_manager::access() static std::vector list { nullptr, - [](ppu_thread& ppu) { ppu.state += cpu_state::ret; }, + [](ppu_thread& ppu) { ppu.state += cpu_flag::ret; }, }; return list; diff --git a/rpcs3/Emu/Cell/PPUModule.cpp b/rpcs3/Emu/Cell/PPUModule.cpp index cba5e0b3ba..3745d8247e 100644 --- a/rpcs3/Emu/Cell/PPUModule.cpp +++ b/rpcs3/Emu/Cell/PPUModule.cpp @@ -144,7 +144,7 @@ extern void ppu_execute_function(ppu_thread& ppu, u32 index) if (index < g_ppu_function_cache.size()) { // If autopause occures, check_status() will hold the thread until unpaused. - if (debug::autopause::pause_function(g_ppu_fnid_cache[index]) && ppu.check_state()) throw cpu_state::ret; + if (debug::autopause::pause_function(g_ppu_fnid_cache[index]) && ppu.check_state()) throw cpu_flag::ret; if (const auto func = g_ppu_function_cache[index]) { diff --git a/rpcs3/Emu/Cell/PPUThread.cpp b/rpcs3/Emu/Cell/PPUThread.cpp index 513869a162..0c44c24fb5 100644 --- a/rpcs3/Emu/Cell/PPUThread.cpp +++ b/rpcs3/Emu/Cell/PPUThread.cpp @@ -118,12 +118,11 @@ void ppu_thread::cpu_task() //SetHostRoundingMode(FPSCR_RN_NEAR); // Execute cmd_queue - while (ppu_cmd cmd = cmd_wait()) + while (cmd64 cmd = cmd_wait()) { - const u32 pos = cmd_queue.peek() + 1; // Additional arguments start from [pos] const u32 arg = cmd.arg2(); // 32-bit arg extracted - switch (u32 type = cmd.arg1()) + switch (auto type = cmd.arg1()) { case ppu_cmd::opcode: { @@ -137,7 +136,7 @@ void ppu_thread::cpu_task() fmt::throw_exception("Invalid ppu_cmd::set_gpr arg (0x%x)" HERE, arg); } - gpr[arg % 32] = cmd_queue[pos].load().as(); + gpr[arg % 32] = cmd_get(1).as(); cmd_pop(1); break; } @@ -150,7 +149,7 @@ void ppu_thread::cpu_task() for (u32 i = 0; i < arg; i++) { - gpr[i + 3] = cmd_queue[pos + i].load().as(); + gpr[i + 3] = cmd_get(1 + i).as(); } cmd_pop(arg); @@ -169,7 +168,7 @@ void ppu_thread::cpu_task() } default: { - fmt::throw_exception("Unknown ppu_cmd(0x%x)" HERE, type); + fmt::throw_exception("Unknown ppu_cmd(0x%x)" HERE, (u32)type); } } } @@ -249,7 +248,7 @@ ppu_thread::~ppu_thread() } ppu_thread::ppu_thread(const std::string& name, u32 prio, u32 stack) - : cpu_thread(cpu_type::ppu) + : cpu_thread() , prio(prio) , stack_size(std::max(stack, 0x4000)) , stack_addr(vm::alloc(stack_size, vm::stack)) @@ -263,7 +262,7 @@ ppu_thread::ppu_thread(const std::string& name, u32 prio, u32 stack) gpr[1] = ::align(stack_addr + stack_size, 0x200) - 0x200; } -void ppu_thread::cmd_push(ppu_cmd cmd) +void ppu_thread::cmd_push(cmd64 cmd) { // Reserve queue space const u32 pos = cmd_queue.push_begin(); @@ -272,7 +271,7 @@ void ppu_thread::cmd_push(ppu_cmd cmd) cmd_queue[pos] = cmd; } -void ppu_thread::cmd_list(std::initializer_list list) +void ppu_thread::cmd_list(std::initializer_list list) { // Reserve queue space const u32 pos = cmd_queue.push_begin(static_cast(list.size())); @@ -295,14 +294,14 @@ void ppu_thread::cmd_pop(u32 count) // Clean command buffer for command tail for (u32 i = 1; i <= count; i++) { - cmd_queue[pos + i].raw() = ppu_cmd{}; + cmd_queue[pos + i].raw() = cmd64{}; } // Free cmd_queue.pop_end(count + 1); } -ppu_cmd ppu_thread::cmd_wait() +cmd64 ppu_thread::cmd_wait() { std::unique_lock lock(*this, std::defer_lock); @@ -314,12 +313,12 @@ ppu_cmd ppu_thread::cmd_wait() if (check_state()) // check_status() requires unlocked mutex { - return ppu_cmd{}; + return cmd64{}; } } // Lightweight queue doesn't care about mutex state - if (ppu_cmd result = cmd_queue[cmd_queue.peek()].exchange(ppu_cmd{})) + if (cmd64 result = cmd_queue[cmd_queue.peek()].exchange(cmd64{})) { return result; } @@ -365,15 +364,15 @@ void ppu_thread::fast_call(u32 addr, u32 rtoc) { exec_task(); - if (gpr[1] != old_stack && !test(state, cpu_state::ret + cpu_state::exit)) // gpr[1] shouldn't change + if (gpr[1] != old_stack && !test(state, cpu_flag::ret + cpu_flag::exit)) // gpr[1] shouldn't change { fmt::throw_exception("Stack inconsistency (addr=0x%x, rtoc=0x%x, SP=0x%llx, old=0x%llx)", addr, rtoc, gpr[1], old_stack); } } - catch (cpu_state _s) + catch (cpu_flag _s) { state += _s; - if (_s != cpu_state::ret) throw; + if (_s != cpu_flag::ret) throw; } catch (EmulationStopped) { @@ -388,7 +387,7 @@ void ppu_thread::fast_call(u32 addr, u32 rtoc) throw; } - state -= cpu_state::ret; + state -= cpu_flag::ret; cia = old_pc; gpr[1] = old_stack; @@ -398,6 +397,51 @@ void ppu_thread::fast_call(u32 addr, u32 rtoc) g_tls_log_prefix = old_fmt; } +u32 ppu_thread::stack_push(u32 size, u32 align_v) +{ + if (auto cpu = get_current_cpu_thread()) if (cpu->id >= id_min) + { + ppu_thread& context = static_cast(*cpu); + + const u32 old_pos = vm::cast(context.gpr[1], HERE); + context.gpr[1] -= align(size + 4, 8); // room minimal possible size + context.gpr[1] &= ~(align_v - 1); // fix stack alignment + + if (context.gpr[1] < context.stack_addr) + { + fmt::throw_exception("Stack overflow (size=0x%x, align=0x%x, SP=0x%llx, stack=*0x%x)" HERE, size, align_v, old_pos, context.stack_addr); + } + else + { + const u32 addr = static_cast(context.gpr[1]); + vm::ps3::_ref>(addr + size) = old_pos; + std::memset(vm::base(addr), 0, size); + return addr; + } + } + + fmt::throw_exception("Invalid thread" HERE); +} + +void ppu_thread::stack_pop_verbose(u32 addr, u32 size) noexcept +{ + if (auto cpu = get_current_cpu_thread()) if (cpu->id >= id_min) + { + ppu_thread& context = static_cast(*cpu); + + if (context.gpr[1] != addr) + { + LOG_ERROR(PPU, "Stack inconsistency (addr=0x%x, SP=0x%llx, size=0x%x)", addr, context.gpr[1], size); + return; + } + + context.gpr[1] = vm::ps3::_ref>(context.gpr[1] + size); + return; + } + + LOG_ERROR(PPU, "Invalid thread" HERE); +} + const ppu_decoder s_ppu_itype; extern u64 get_timebased_time(); diff --git a/rpcs3/Emu/Cell/PPUThread.h b/rpcs3/Emu/Cell/PPUThread.h index 7bf4f1e82b..2a681ab5cb 100644 --- a/rpcs3/Emu/Cell/PPUThread.h +++ b/rpcs3/Emu/Cell/PPUThread.h @@ -5,75 +5,25 @@ #include "../Memory/vm.h" #include "Utilities/lockless.h" -// Lightweight PPU command queue element -struct ppu_cmd : any64 +enum class ppu_cmd : u32 { - enum : u32 - { - none = 0, + null, - opcode, // Execute PPU instruction from arg - set_gpr, // Set gpr[arg] (+1 cmd) - set_args, // Set general-purpose args (+arg cmd) - lle_call, // Load addr and rtoc at *arg or *gpr[arg] and execute - hle_call, // Execute function by index (arg) - }; - - struct pair_t - { - any32 arg1; - any32 arg2; - }; - - ppu_cmd() = default; - - template - ppu_cmd(const T& value) - : any64(value) - { - } - - template - ppu_cmd(const T1& arg1, const T2& arg2) - : any64(pair_t{arg1, arg2}) - { - } - - explicit operator bool() const - { - return as() != 0; - } - - template - decltype(auto) arg1() - { - return as().arg1.as(); - } - - template - decltype(auto) arg1() const - { - return as().arg1.as(); - } - - template - decltype(auto) arg2() - { - return as().arg2.as(); - } - - template - decltype(auto) arg2() const - { - return as().arg2.as(); - } + opcode, // Execute PPU instruction from arg + set_gpr, // Set gpr[arg] (+1 cmd) + set_args, // Set general-purpose args (+arg cmd) + lle_call, // Load addr and rtoc at *arg or *gpr[arg] and execute + hle_call, // Execute function by index (arg) }; -static_assert(sizeof(ppu_cmd) == 8 && std::is_pod::value, "Incorrect ppu_cmd struct"); - class ppu_thread : public cpu_thread { public: + using id_base = ppu_thread; + + static constexpr u32 id_min = 0x80000000; // TODO (used to determine thread type) + static constexpr u32 id_max = 0x8fffffff; + virtual std::string get_name() const override; virtual std::string dump() const override; virtual void cpu_init() override final {} @@ -174,12 +124,13 @@ public: bool is_joinable = true; bool is_joining = false; - lf_fifo, 255> cmd_queue; // Command queue for asynchronous operations. + lf_fifo, 255> cmd_queue; // Command queue for asynchronous operations. - void cmd_push(ppu_cmd); - void cmd_list(std::initializer_list); + void cmd_push(cmd64); + void cmd_list(std::initializer_list); void cmd_pop(u32 = 0); - ppu_cmd cmd_wait(); // Empty command means caller must return, like true from cpu_thread::check_status(). + cmd64 cmd_wait(); // Empty command means caller must return, like true from cpu_thread::check_status(). + cmd64 cmd_get(u32 index) { return cmd_queue[cmd_queue.peek() + index].load(); } const char* last_function{}; // Last function name for diagnosis, optimized for speed. @@ -200,6 +151,9 @@ public: be_t* get_stack_arg(s32 i, u64 align = alignof(u64)); void exec_task(); void fast_call(u32 addr, u32 rtoc); + + static u32 stack_push(u32 size, u32 align_v); + static void stack_pop_verbose(u32 addr, u32 size) noexcept; }; template diff --git a/rpcs3/Emu/Cell/RawSPUThread.cpp b/rpcs3/Emu/Cell/RawSPUThread.cpp index ba503b9ba3..17d7f12be6 100644 --- a/rpcs3/Emu/Cell/RawSPUThread.cpp +++ b/rpcs3/Emu/Cell/RawSPUThread.cpp @@ -183,7 +183,7 @@ bool RawSPUThread::write_reg(const u32 addr, const u32 value) else if (value == SPU_RUNCNTL_STOP_REQUEST) { status &= ~SPU_STATUS_RUNNING; - state += cpu_state::stop; + state += cpu_flag::stop; } else { diff --git a/rpcs3/Emu/Cell/SPUASMJITRecompiler.cpp b/rpcs3/Emu/Cell/SPUASMJITRecompiler.cpp index e614e626e0..131bfd95a9 100644 --- a/rpcs3/Emu/Cell/SPUASMJITRecompiler.cpp +++ b/rpcs3/Emu/Cell/SPUASMJITRecompiler.cpp @@ -14,11 +14,11 @@ #include "asmjit.h" -#define SPU_OFF_128(x) asmjit::host::oword_ptr(*cpu, OFFSET_32(SPUThread, x)) -#define SPU_OFF_64(x) asmjit::host::qword_ptr(*cpu, OFFSET_32(SPUThread, x)) -#define SPU_OFF_32(x) asmjit::host::dword_ptr(*cpu, OFFSET_32(SPUThread, x)) -#define SPU_OFF_16(x) asmjit::host::word_ptr(*cpu, OFFSET_32(SPUThread, x)) -#define SPU_OFF_8(x) asmjit::host::byte_ptr(*cpu, OFFSET_32(SPUThread, x)) +#define SPU_OFF_128(x) asmjit::host::oword_ptr(*cpu, (std::conditional_t)OFFSET_32(SPUThread, x)) +#define SPU_OFF_64(x) asmjit::host::qword_ptr(*cpu, (std::conditional_t)OFFSET_32(SPUThread, x)) +#define SPU_OFF_32(x) asmjit::host::dword_ptr(*cpu, (std::conditional_t)OFFSET_32(SPUThread, x)) +#define SPU_OFF_16(x) asmjit::host::word_ptr(*cpu, (std::conditional_t)OFFSET_32(SPUThread, x)) +#define SPU_OFF_8(x) asmjit::host::byte_ptr(*cpu, (std::conditional_t)OFFSET_32(SPUThread, x)) const spu_decoder s_spu_interpreter; // TODO: remove const spu_decoder s_spu_decoder; @@ -345,7 +345,7 @@ void spu_recompiler::FunctionCall() // Proceed recursively spu_recompiler_base::enter(*_spu); - if (test(_spu->state & cpu_state::ret)) + if (test(_spu->state & cpu_flag::ret)) { break; } @@ -2186,7 +2186,7 @@ void spu_recompiler::BR(spu_opcode_t op) c->mov(*addr, target | 0x2000000); //c->cmp(asmjit::host::dword_ptr(*ls, m_pos), 0x32); // compare instruction opcode with BR-to-self //c->je(labels[target / 4]); - c->lock().or_(SPU_OFF_16(state), static_cast(cpu_state::stop + cpu_state::ret)); + c->lock().or_(SPU_OFF_32(state), static_cast(cpu_flag::stop + cpu_flag::ret)); c->jmp(*end); c->unuse(*addr); return; diff --git a/rpcs3/Emu/Cell/SPURecompiler.cpp b/rpcs3/Emu/Cell/SPURecompiler.cpp index 8d1669e58b..173f94c573 100644 --- a/rpcs3/Emu/Cell/SPURecompiler.cpp +++ b/rpcs3/Emu/Cell/SPURecompiler.cpp @@ -24,7 +24,7 @@ void spu_recompiler_base::enter(SPUThread& spu) // Reset callstack if necessary if (func->does_reset_stack && spu.recursion_level) { - spu.state += cpu_state::ret; + spu.state += cpu_flag::ret; return; } diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index 159cdc9e5b..f5d5c92196 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -237,7 +237,7 @@ SPUThread::~SPUThread() } SPUThread::SPUThread(const std::string& name) - : cpu_thread(cpu_type::spu) + : cpu_thread() , m_name(name) , index(0) , offset(0) @@ -245,7 +245,7 @@ SPUThread::SPUThread(const std::string& name) } SPUThread::SPUThread(const std::string& name, u32 index) - : cpu_thread(cpu_type::spu) + : cpu_thread() , m_name(name) , index(index) , offset(vm::alloc(0x40000, vm::main)) @@ -599,9 +599,9 @@ bool SPUThread::get_ch_value(u32 ch, u32& out) { if (!channel.try_pop(out)) { - thread_lock{*this}, thread_ctrl::wait(WRAP_EXPR(test(state & cpu_state::stop) || channel.try_pop(out))); + thread_lock{*this}, thread_ctrl::wait(WRAP_EXPR(test(state & cpu_flag::stop) || channel.try_pop(out))); - return !test(state & cpu_state::stop); + return !test(state & cpu_flag::stop); } return true; @@ -630,7 +630,7 @@ bool SPUThread::get_ch_value(u32 ch, u32& out) CHECK_EMU_STATUS; - if (test(state & cpu_state::stop)) + if (test(state & cpu_flag::stop)) { return false; } @@ -702,14 +702,14 @@ bool SPUThread::get_ch_value(u32 ch, u32& out) if (ch_event_mask & SPU_EVENT_LR) { // register waiter if polling reservation status is required - vm::wait_op(last_raddr, 128, WRAP_EXPR(get_events(true) || test(state & cpu_state::stop))); + vm::wait_op(last_raddr, 128, WRAP_EXPR(get_events(true) || test(state & cpu_flag::stop))); } else { lock.lock(); // simple waiting loop otherwise - while (!get_events(true) && !test(state & cpu_state::stop)) + while (!get_events(true) && !test(state & cpu_flag::stop)) { CHECK_EMU_STATUS; @@ -719,7 +719,7 @@ bool SPUThread::get_ch_value(u32 ch, u32& out) ch_event_stat &= ~SPU_EVENT_WAITING; - if (test(state & cpu_state::stop)) + if (test(state & cpu_flag::stop)) { return false; } @@ -759,7 +759,7 @@ bool SPUThread::set_ch_value(u32 ch, u32 value) { CHECK_EMU_STATUS; - if (test(state & cpu_state::stop)) + if (test(state & cpu_flag::stop)) { return false; } @@ -966,7 +966,7 @@ bool SPUThread::set_ch_value(u32 ch, u32 value) { CHECK_EMU_STATUS; - if (test(state & cpu_state::stop)) + if (test(state & cpu_flag::stop)) { return false; } @@ -1136,7 +1136,7 @@ bool SPUThread::stop_and_signal(u32 code) }); int_ctrl[2].set(SPU_INT2_STAT_SPU_STOP_AND_SIGNAL_INT); - state += cpu_state::stop; + state += cpu_flag::stop; return true; // ??? } @@ -1150,7 +1150,7 @@ bool SPUThread::stop_and_signal(u32 code) case 0x002: { - state += cpu_state::ret; + state += cpu_flag::ret; return true; } @@ -1231,7 +1231,7 @@ bool SPUThread::stop_and_signal(u32 code) { CHECK_EMU_STATUS; - if (test(state & cpu_state::stop)) + if (test(state & cpu_flag::stop)) { return false; } @@ -1248,7 +1248,7 @@ bool SPUThread::stop_and_signal(u32 code) { if (thread) { - thread->state += cpu_state::suspend; + thread->state += cpu_flag::suspend; } } } @@ -1268,11 +1268,11 @@ bool SPUThread::stop_and_signal(u32 code) sleep_entry waiter(queue->thread_queue(lv2_lock), *this); // wait on the event queue - while (!state.test_and_reset(cpu_state::signal)) + while (!state.test_and_reset(cpu_flag::signal)) { CHECK_EMU_STATUS; - if (test(state & cpu_state::stop)) + if (test(state & cpu_flag::stop)) { return false; } @@ -1301,12 +1301,12 @@ bool SPUThread::stop_and_signal(u32 code) { if (thread && thread.get() != this) { - thread->state -= cpu_state::suspend; + thread->state -= cpu_flag::suspend; thread->lock_notify(); } } - state -= cpu_state::suspend; + state -= cpu_flag::suspend; group->cv.notify_all(); return true; @@ -1340,7 +1340,7 @@ bool SPUThread::stop_and_signal(u32 code) { if (thread && thread.get() != this) { - thread->state += cpu_state::stop; + thread->state += cpu_flag::stop; thread->lock_notify(); } } @@ -1350,7 +1350,7 @@ bool SPUThread::stop_and_signal(u32 code) group->join_state |= SPU_TGJSF_GROUP_EXIT; group->cv.notify_one(); - state += cpu_state::stop; + state += cpu_flag::stop; return true; } @@ -1377,7 +1377,7 @@ bool SPUThread::stop_and_signal(u32 code) status |= SPU_STATUS_STOPPED_BY_STOP; group->cv.notify_one(); - state += cpu_state::stop; + state += cpu_flag::stop; return true; } } @@ -1406,7 +1406,7 @@ void SPUThread::halt() int_ctrl[2].set(SPU_INT2_STAT_SPU_HALT_OR_STEP_INT); - throw cpu_state::stop; + throw cpu_flag::stop; } status |= SPU_STATUS_STOPPED_BY_HALT; @@ -1431,13 +1431,13 @@ void SPUThread::fast_call(u32 ls_addr) { cpu_task(); } - catch (cpu_state _s) + catch (cpu_flag _s) { state += _s; - if (_s != cpu_state::ret) throw; + if (_s != cpu_flag::ret) throw; } - state -= cpu_state::ret; + state -= cpu_flag::ret; pc = old_pc; gpr[0]._u32[3] = old_lr; diff --git a/rpcs3/Emu/Cell/lv2/lv2.cpp b/rpcs3/Emu/Cell/lv2/lv2.cpp index 965a80c580..da32ca7563 100644 --- a/rpcs3/Emu/Cell/lv2/lv2.cpp +++ b/rpcs3/Emu/Cell/lv2/lv2.cpp @@ -913,7 +913,7 @@ extern void ppu_execute_syscall(ppu_thread& ppu, u64 code) if (code < g_ppu_syscall_table.size()) { // If autopause occures, check_status() will hold the thread till unpaused. - if (debug::autopause::pause_syscall(code) && ppu.check_state()) throw cpu_state::ret; + if (debug::autopause::pause_syscall(code) && ppu.check_state()) throw cpu_flag::ret; if (auto func = g_ppu_syscall_table[code]) { diff --git a/rpcs3/Emu/Cell/lv2/sys_cond.cpp b/rpcs3/Emu/Cell/lv2/sys_cond.cpp index 3e0d750a36..f18a97f5da 100644 --- a/rpcs3/Emu/Cell/lv2/sys_cond.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_cond.cpp @@ -25,7 +25,7 @@ void lv2_cond_t::notify(lv2_lock_t, cpu_thread* thread) { mutex->owner = idm::get(thread->id); - VERIFY(!thread->state.test_and_set(cpu_state::signal)); + VERIFY(!thread->state.test_and_set(cpu_flag::signal)); thread->notify(); } } @@ -198,7 +198,7 @@ s32 sys_cond_wait(ppu_thread& ppu, u32 cond_id, u64 timeout) // potential mutex waiter (not added immediately) sleep_entry mutex_waiter(cond->mutex->sq, ppu, defer_sleep); - while (!ppu.state.test_and_reset(cpu_state::signal)) + while (!ppu.state.test_and_reset(cpu_flag::signal)) { CHECK_EMU_STATUS; diff --git a/rpcs3/Emu/Cell/lv2/sys_event.cpp b/rpcs3/Emu/Cell/lv2/sys_event.cpp index 59f62411ea..c3290c639a 100644 --- a/rpcs3/Emu/Cell/lv2/sys_event.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_event.cpp @@ -61,7 +61,7 @@ void lv2_event_queue_t::push(lv2_lock_t, u64 source, u64 data1, u64 data2, u64 d // notify waiter; protocol is ignored in current implementation auto& thread = m_sq.front(); - if (type == SYS_PPU_QUEUE && thread->type == cpu_type::ppu) + if (type == SYS_PPU_QUEUE && thread->id >= ppu_thread::id_min) { // store event data in registers auto& ppu = static_cast(*thread); @@ -71,7 +71,7 @@ void lv2_event_queue_t::push(lv2_lock_t, u64 source, u64 data1, u64 data2, u64 d ppu.gpr[6] = data2; ppu.gpr[7] = data3; } - else if (type == SYS_SPU_QUEUE && thread->type == cpu_type::spu) + else if (type == SYS_SPU_QUEUE && thread->id < ppu_thread::id_min) { // store event data in In_MBox auto& spu = static_cast(*thread); @@ -80,10 +80,10 @@ void lv2_event_queue_t::push(lv2_lock_t, u64 source, u64 data1, u64 data2, u64 d } else { - fmt::throw_exception("Unexpected (queue type=%d, thread type=%d)" HERE, type, (s32)thread->type); + fmt::throw_exception("Unexpected (queue type=%d, tid=%s)" HERE, type, thread->id); } - VERIFY(!thread->state.test_and_set(cpu_state::signal)); + VERIFY(!thread->state.test_and_set(cpu_flag::signal)); thread->notify(); return m_sq.pop_front(); @@ -163,20 +163,20 @@ s32 sys_event_queue_destroy(u32 equeue_id, s32 mode) // signal all threads to return CELL_ECANCELED for (auto& thread : queue->thread_queue(lv2_lock)) { - if (queue->type == SYS_PPU_QUEUE && thread->type == cpu_type::ppu) + if (queue->type == SYS_PPU_QUEUE && thread->id >= ppu_thread::id_min) { static_cast(*thread).gpr[3] = 1; } - else if (queue->type == SYS_SPU_QUEUE && thread->type == cpu_type::spu) + else if (queue->type == SYS_SPU_QUEUE && thread->id < ppu_thread::id_min) { static_cast(*thread).ch_in_mbox.set_values(1, CELL_ECANCELED); } else { - fmt::throw_exception("Unexpected (queue.type=%d, thread.type=%d)" HERE, queue->type, thread->type); + fmt::throw_exception("Unexpected (queue type=%d, tid=%s)" HERE, queue->type, thread->id); } - thread->state += cpu_state::signal; + thread->state += cpu_flag::signal; thread->notify(); } @@ -253,7 +253,7 @@ s32 sys_event_queue_receive(ppu_thread& ppu, u32 equeue_id, vm::ptr // add waiter; protocol is ignored in current implementation sleep_entry waiter(queue->thread_queue(lv2_lock), ppu); - while (!ppu.state.test_and_reset(cpu_state::signal)) + while (!ppu.state.test_and_reset(cpu_flag::signal)) { CHECK_EMU_STATUS; diff --git a/rpcs3/Emu/Cell/lv2/sys_event_flag.cpp b/rpcs3/Emu/Cell/lv2/sys_event_flag.cpp index c5eb2b887d..9e18658909 100644 --- a/rpcs3/Emu/Cell/lv2/sys_event_flag.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_event_flag.cpp @@ -29,7 +29,7 @@ void lv2_event_flag_t::notify_all(lv2_lock_t) // save pattern ppu.gpr[4] = clear_pattern(bitptn, mode); - VERIFY(!thread->state.test_and_set(cpu_state::signal)); + VERIFY(!thread->state.test_and_set(cpu_flag::signal)); thread->notify(); return true; @@ -146,7 +146,7 @@ s32 sys_event_flag_wait(ppu_thread& ppu, u32 id, u64 bitptn, u32 mode, vm::ptr waiter(eflag->sq, ppu); - while (!ppu.state.test_and_reset(cpu_state::signal)) + while (!ppu.state.test_and_reset(cpu_flag::signal)) { CHECK_EMU_STATUS; @@ -292,7 +292,7 @@ s32 sys_event_flag_cancel(u32 id, vm::ptr num) // clear "mode" as a sign of cancellation ppu.gpr[5] = 0; - VERIFY(!thread->state.test_and_set(cpu_state::signal)); + VERIFY(!thread->state.test_and_set(cpu_flag::signal)); thread->notify(); } diff --git a/rpcs3/Emu/Cell/lv2/sys_interrupt.cpp b/rpcs3/Emu/Cell/lv2/sys_interrupt.cpp index 01ed65b9b6..f48a2856c4 100644 --- a/rpcs3/Emu/Cell/lv2/sys_interrupt.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_interrupt.cpp @@ -34,7 +34,7 @@ void lv2_int_serv_t::join(ppu_thread& ppu, lv2_lock_t lv2_lock) thread->lock_notify(); // Join thread (TODO) - while (!test(thread->state & cpu_state::exit)) + while (!test(thread->state & cpu_flag::exit)) { CHECK_EMU_STATUS; @@ -91,7 +91,7 @@ s32 _sys_interrupt_thread_establish(vm::ptr ih, u32 intrtag, u32 intrthread } // If interrupt thread is running, it's already established on another interrupt tag - if (!test(it->state & cpu_state::stop)) + if (!test(it->state & cpu_flag::stop)) { return CELL_EAGAIN; } @@ -139,13 +139,13 @@ void sys_interrupt_thread_eoi(ppu_thread& ppu) // Low-level PPU function example // Low-level function body must guard all C++-ish calls and all objects with non-trivial destructors thread_guard{ppu}, sys_interrupt.trace("sys_interrupt_thread_eoi()"); - ppu.state += cpu_state::ret; + ppu.state += cpu_flag::ret; // Throw if this syscall was not called directly by the SC instruction (hack) if (ppu.lr == 0 || ppu.gpr[11] != 88) { // Low-level function must disable interrupts before throwing (not related to sys_interrupt_*, it's rather coincidence) ppu->interrupt_disable(); - throw cpu_state::ret; + throw cpu_flag::ret; } } diff --git a/rpcs3/Emu/Cell/lv2/sys_lwcond.cpp b/rpcs3/Emu/Cell/lv2/sys_lwcond.cpp index ab40749756..98012eeb25 100644 --- a/rpcs3/Emu/Cell/lv2/sys_lwcond.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_lwcond.cpp @@ -30,7 +30,7 @@ void lv2_lwcond_t::notify(lv2_lock_t, cpu_thread* thread, const std::shared_ptr< mutex->signaled--; } - VERIFY(!thread->state.test_and_set(cpu_state::signal)); + VERIFY(!thread->state.test_and_set(cpu_flag::signal)); thread->notify(); } @@ -180,7 +180,7 @@ s32 _sys_lwcond_queue_wait(ppu_thread& ppu, u32 lwcond_id, u32 lwmutex_id, u64 t // potential mutex waiter (not added immediately) sleep_entry mutex_waiter(cond->sq, ppu, defer_sleep); - while (!ppu.state.test_and_reset(cpu_state::signal)) + while (!ppu.state.test_and_reset(cpu_flag::signal)) { CHECK_EMU_STATUS; diff --git a/rpcs3/Emu/Cell/lv2/sys_lwmutex.cpp b/rpcs3/Emu/Cell/lv2/sys_lwmutex.cpp index dafe153c90..980c5d613f 100644 --- a/rpcs3/Emu/Cell/lv2/sys_lwmutex.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_lwmutex.cpp @@ -21,7 +21,7 @@ void lv2_lwmutex_t::unlock(lv2_lock_t) if (sq.size()) { auto& thread = sq.front(); - VERIFY(!thread->state.test_and_set(cpu_state::signal)); + VERIFY(!thread->state.test_and_set(cpu_flag::signal)); thread->notify(); sq.pop_front(); @@ -100,7 +100,7 @@ s32 _sys_lwmutex_lock(ppu_thread& ppu, u32 lwmutex_id, u64 timeout) // add waiter; protocol is ignored in current implementation sleep_entry waiter(mutex->sq, ppu); - while (!ppu.state.test_and_reset(cpu_state::signal)) + while (!ppu.state.test_and_reset(cpu_flag::signal)) { CHECK_EMU_STATUS; diff --git a/rpcs3/Emu/Cell/lv2/sys_mutex.cpp b/rpcs3/Emu/Cell/lv2/sys_mutex.cpp index 1ae9cd13cc..6564611e47 100644 --- a/rpcs3/Emu/Cell/lv2/sys_mutex.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_mutex.cpp @@ -20,7 +20,7 @@ void lv2_mutex_t::unlock(lv2_lock_t) // pick new owner; protocol is ignored in current implementation owner = idm::get(sq.front()->id); - VERIFY(!owner->state.test_and_set(cpu_state::signal)); + VERIFY(!owner->state.test_and_set(cpu_flag::signal)); owner->notify(); } } @@ -135,7 +135,7 @@ s32 sys_mutex_lock(ppu_thread& ppu, u32 mutex_id, u64 timeout) // add waiter; protocol is ignored in current implementation sleep_entry waiter(mutex->sq, ppu); - while (!ppu.state.test_and_reset(cpu_state::signal)) + while (!ppu.state.test_and_reset(cpu_flag::signal)) { CHECK_EMU_STATUS; diff --git a/rpcs3/Emu/Cell/lv2/sys_ppu_thread.cpp b/rpcs3/Emu/Cell/lv2/sys_ppu_thread.cpp index a654e2195f..de895a5f3f 100644 --- a/rpcs3/Emu/Cell/lv2/sys_ppu_thread.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_ppu_thread.cpp @@ -19,7 +19,7 @@ void _sys_ppu_thread_exit(ppu_thread& ppu, u64 errorcode) LV2_LOCK; - ppu.state += cpu_state::exit; + ppu.state += cpu_flag::exit; // Delete detached thread if (!ppu.is_joinable) @@ -30,7 +30,7 @@ void _sys_ppu_thread_exit(ppu_thread& ppu, u64 errorcode) // Throw if this syscall was not called directly by the SC instruction (hack) if (ppu.lr == 0 || ppu.gpr[11] != 41) { - throw cpu_state::exit; + throw cpu_flag::exit; } } @@ -68,7 +68,7 @@ s32 sys_ppu_thread_join(ppu_thread& ppu, u32 thread_id, vm::ptr vptr) thread->is_joining = true; // join thread - while (!test(thread->state & cpu_state::exit)) + while (!test(thread->state & cpu_flag::exit)) { CHECK_EMU_STATUS; diff --git a/rpcs3/Emu/Cell/lv2/sys_rwlock.cpp b/rpcs3/Emu/Cell/lv2/sys_rwlock.cpp index 292f505206..51b2879d6b 100644 --- a/rpcs3/Emu/Cell/lv2/sys_rwlock.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_rwlock.cpp @@ -18,7 +18,7 @@ void lv2_rwlock_t::notify_all(lv2_lock_t) { writer = idm::get(wsq.front()->id); - VERIFY(!writer->state.test_and_set(cpu_state::signal)); + VERIFY(!writer->state.test_and_set(cpu_flag::signal)); writer->notify(); return wsq.pop_front(); @@ -31,7 +31,7 @@ void lv2_rwlock_t::notify_all(lv2_lock_t) for (auto& thread : rsq) { - VERIFY(!thread->state.test_and_set(cpu_state::signal)); + VERIFY(!thread->state.test_and_set(cpu_flag::signal)); thread->notify(); } @@ -118,7 +118,7 @@ s32 sys_rwlock_rlock(ppu_thread& ppu, u32 rw_lock_id, u64 timeout) // add waiter; protocol is ignored in current implementation sleep_entry waiter(rwlock->rsq, ppu); - while (!ppu.state.test_and_reset(cpu_state::signal)) + while (!ppu.state.test_and_reset(cpu_flag::signal)) { CHECK_EMU_STATUS; @@ -229,7 +229,7 @@ s32 sys_rwlock_wlock(ppu_thread& ppu, u32 rw_lock_id, u64 timeout) // add waiter; protocol is ignored in current implementation sleep_entry waiter(rwlock->wsq, ppu); - while (!ppu.state.test_and_reset(cpu_state::signal)) + while (!ppu.state.test_and_reset(cpu_flag::signal)) { CHECK_EMU_STATUS; diff --git a/rpcs3/Emu/Cell/lv2/sys_semaphore.cpp b/rpcs3/Emu/Cell/lv2/sys_semaphore.cpp index e73e9886bb..17e38689c7 100644 --- a/rpcs3/Emu/Cell/lv2/sys_semaphore.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_semaphore.cpp @@ -93,7 +93,7 @@ s32 sys_semaphore_wait(ppu_thread& ppu, u32 sem_id, u64 timeout) // add waiter; protocol is ignored in current implementation sleep_entry waiter(sem->sq, ppu); - while (!ppu.state.test_and_reset(cpu_state::signal)) + while (!ppu.state.test_and_reset(cpu_flag::signal)) { CHECK_EMU_STATUS; @@ -173,7 +173,7 @@ s32 sys_semaphore_post(u32 sem_id, s32 count) count--; auto& thread = sem->sq.front(); - VERIFY(!thread->state.test_and_set(cpu_state::signal)); + VERIFY(!thread->state.test_and_set(cpu_flag::signal)); thread->notify(); sem->sq.pop_front(); diff --git a/rpcs3/Emu/Cell/lv2/sys_spu.cpp b/rpcs3/Emu/Cell/lv2/sys_spu.cpp index e4b9a87f2c..3400c340c9 100644 --- a/rpcs3/Emu/Cell/lv2/sys_spu.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_spu.cpp @@ -374,7 +374,7 @@ s32 sys_spu_thread_group_suspend(u32 id) { if (thread) { - thread->state += cpu_state::suspend; + thread->state += cpu_flag::suspend; } } @@ -418,7 +418,7 @@ s32 sys_spu_thread_group_resume(u32 id) { if (thread) { - thread->state -= cpu_state::suspend; + thread->state -= cpu_flag::suspend; thread->lock_notify(); } } @@ -501,7 +501,7 @@ s32 sys_spu_thread_group_terminate(u32 id, s32 value) { if (thread) { - thread->state += cpu_state::stop; + thread->state += cpu_flag::stop; thread->lock_notify(); } } @@ -1169,7 +1169,7 @@ s32 sys_raw_spu_destroy(ppu_thread& ppu, u32 id) // TODO: CELL_EBUSY is not returned // Stop thread - thread->state += cpu_state::stop; + thread->state += cpu_flag::stop; // Clear interrupt handlers for (auto& intr : thread->int_ctrl) diff --git a/rpcs3/Emu/Memory/vm.cpp b/rpcs3/Emu/Memory/vm.cpp index 03c2b696be..d4ba7d49df 100644 --- a/rpcs3/Emu/Memory/vm.cpp +++ b/rpcs3/Emu/Memory/vm.cpp @@ -817,127 +817,6 @@ namespace vm g_locations.clear(); } - u32 stack_push(u32 size, u32 align_v) - { - if (auto cpu = get_current_cpu_thread()) switch (cpu->type) - { - case cpu_type::ppu: - { - ppu_thread& context = static_cast(*cpu); - - const u32 old_pos = vm::cast(context.gpr[1], HERE); - context.gpr[1] -= align(size + 4, 8); // room minimal possible size - context.gpr[1] &= ~(align_v - 1); // fix stack alignment - - if (context.gpr[1] < context.stack_addr) - { - fmt::throw_exception("Stack overflow (size=0x%x, align=0x%x, SP=0x%llx, stack=*0x%x)" HERE, size, align_v, old_pos, context.stack_addr); - } - else - { - const u32 addr = static_cast(context.gpr[1]); - vm::ps3::_ref>(addr + size) = old_pos; - std::memset(vm::base(addr), 0, size); - return addr; - } - } - - case cpu_type::spu: - { - SPUThread& context = static_cast(*cpu); - - const u32 old_pos = context.gpr[1]._u32[3]; - context.gpr[1]._u32[3] -= align(size + 4, 16); - context.gpr[1]._u32[3] &= ~(align_v - 1); - - if (context.gpr[1]._u32[3] >= 0x40000) // extremely rough - { - fmt::throw_exception("Stack overflow (size=0x%x, align=0x%x, SP=LS:0x%05x)" HERE, size, align_v, old_pos); - } - else - { - const u32 addr = context.gpr[1]._u32[3] + context.offset; - vm::ps3::_ref>(addr + size) = old_pos; - return addr; - } - } - - case cpu_type::arm: - { - ARMv7Thread& context = static_cast(*cpu); - - const u32 old_pos = context.SP; - context.SP -= align(size + 4, 4); // room minimal possible size - context.SP &= ~(align_v - 1); // fix stack alignment - - if (context.SP < context.stack_addr) - { - fmt::throw_exception("Stack overflow (size=0x%x, align=0x%x, SP=0x%x, stack=*0x%x)" HERE, size, align_v, context.SP, context.stack_addr); - } - else - { - vm::psv::_ref>(context.SP + size) = old_pos; - return context.SP; - } - } - - default: - { - fmt::throw_exception("Invalid thread type (%u)" HERE, cpu->type); - } - } - - fmt::throw_exception("Invalid thread" HERE); - } - - void stack_pop_verbose(u32 addr, u32 size) noexcept - { - if (auto cpu = get_current_cpu_thread()) switch (cpu->type) - { - case cpu_type::ppu: - { - ppu_thread& context = static_cast(*cpu); - - if (context.gpr[1] != addr) - { - LOG_ERROR(MEMORY, "Stack inconsistency (addr=0x%x, SP=0x%llx, size=0x%x)", addr, context.gpr[1], size); - return; - } - - context.gpr[1] = vm::ps3::_ref>(context.gpr[1] + size); - return; - } - - case cpu_type::spu: - { - SPUThread& context = static_cast(*cpu); - - if (context.gpr[1]._u32[3] + context.offset != addr) - { - LOG_ERROR(MEMORY, "Stack inconsistency (addr=0x%x, SP=LS:0x%05x, size=0x%x)", addr, context.gpr[1]._u32[3], size); - return; - } - - context.gpr[1]._u32[3] = vm::ps3::_ref>(context.gpr[1]._u32[3] + context.offset + size); - return; - } - - case cpu_type::arm: - { - ARMv7Thread& context = static_cast(*cpu); - - if (context.SP != addr) - { - LOG_ERROR(MEMORY, "Stack inconsistency (addr=0x%x, SP=0x%x, size=0x%x)", addr, context.SP, size); - return; - } - - context.SP = vm::psv::_ref>(context.SP + size); - return; - } - } - } - [[noreturn]] void throw_access_violation(u64 addr, const char* cause) { throw access_violation(addr, cause); diff --git a/rpcs3/Emu/Memory/vm.h b/rpcs3/Emu/Memory/vm.h index 77ed6e4155..f5fb86e476 100644 --- a/rpcs3/Emu/Memory/vm.h +++ b/rpcs3/Emu/Memory/vm.h @@ -360,9 +360,6 @@ namespace vm void close(); - u32 stack_push(u32 size, u32 align_v); - void stack_pop_verbose(u32 addr, u32 size) noexcept; - extern thread_local u64 g_tls_fault_count; } diff --git a/rpcs3/Emu/Memory/vm_var.h b/rpcs3/Emu/Memory/vm_var.h index 7467919ae1..41b677cea5 100644 --- a/rpcs3/Emu/Memory/vm_var.h +++ b/rpcs3/Emu/Memory/vm_var.h @@ -18,16 +18,17 @@ namespace vm } }; + template struct stack_allocator { static inline vm::addr_t alloc(u32 size, u32 align) { - return vm::cast(vm::stack_push(size, align)); + return vm::cast(T::stack_push(size, align)); } static inline void dealloc(u32 addr, u32 size) noexcept { - vm::stack_pop_verbose(addr, size); + T::stack_pop_verbose(addr, size); } }; @@ -98,21 +99,30 @@ namespace vm }; // LE variable - template using varl = _var_base, A>; + template using varl = _var_base, A>; // BE variable - template using varb = _var_base, A>; + template using varb = _var_base, A>; namespace ps3 { // BE variable - template using var = varb; + template> using var = varb; // Make BE variable initialized from value - template + template> inline auto make_var(const T& value) { - return varb(value); + return varb(value); + } + + // Make char[] variable initialized from std::string + template> + static auto make_str(const std::string& str) + { + var var_(size32(str) + 1); + std::memcpy(var_.get_ptr(), str.c_str(), str.size() + 1); + return var_; } // Global HLE variable @@ -125,13 +135,22 @@ namespace vm namespace psv { // LE variable - template using var = varl; + template> using var = varl; // Make LE variable initialized from value - template + template> inline auto make_var(const T& value) { - return varl(value); + return var(value); + } + + // Make char[] variable initialized from std::string + template> + static auto make_str(const std::string& str) + { + var var_(size32(str) + 1); + std::memcpy(var_.get_ptr(), str.c_str(), str.size() + 1); + return var_; } // Global HLE variable @@ -140,12 +159,4 @@ namespace vm { }; } - - // Make char[] variable initialized from std::string - static auto make_str(const std::string& str) - { - _var_base var(size32(str) + 1); - std::memcpy(var.get_ptr(), str.c_str(), str.size() + 1); - return var; - } } diff --git a/rpcs3/Emu/PSP2/ARMv7Function.cpp b/rpcs3/Emu/PSP2/ARMv7Function.cpp index 7d9154e60e..6f33f39e03 100644 --- a/rpcs3/Emu/PSP2/ARMv7Function.cpp +++ b/rpcs3/Emu/PSP2/ARMv7Function.cpp @@ -39,22 +39,19 @@ s32 arm_error_code::report(s32 error, const char* text) { if (auto thread = get_current_cpu_thread()) { - if (thread->type == cpu_type::arm) + if (auto func = static_cast(thread)->last_function) { - if (auto func = static_cast(thread)->last_function) - { - LOG_ERROR(ARMv7, "Function '%s' failed with 0x%08x : %s", func, error, text); - } - else - { - LOG_ERROR(ARMv7, "Unknown function failed with 0x%08x : %s", error, text); - } - - return error; + LOG_ERROR(ARMv7, "Function '%s' failed with 0x%08x : %s", func, error, text); } + else + { + LOG_ERROR(ARMv7, "Unknown function failed with 0x%08x : %s", error, text); + } + + return error; } - LOG_ERROR(ARMv7, "Illegal call to ppu_report_error(0x%x, '%s')!"); + LOG_ERROR(ARMv7, "Illegal call to arm_report_error(0x%x, '%s')!"); return error; } @@ -63,7 +60,7 @@ std::vector& arm_function_manager::access() static std::vector list { nullptr, - [](ARMv7Thread& cpu) { cpu.state += cpu_state::ret; }, + [](ARMv7Thread& cpu) { cpu.state += cpu_flag::ret; }, }; return list; diff --git a/rpcs3/Emu/PSP2/ARMv7Thread.cpp b/rpcs3/Emu/PSP2/ARMv7Thread.cpp index d461514234..91a890e3f0 100644 --- a/rpcs3/Emu/PSP2/ARMv7Thread.cpp +++ b/rpcs3/Emu/PSP2/ARMv7Thread.cpp @@ -120,7 +120,7 @@ ARMv7Thread::~ARMv7Thread() } ARMv7Thread::ARMv7Thread(const std::string& name) - : cpu_thread(cpu_type::arm) + : cpu_thread() , m_name(name) { } @@ -142,15 +142,15 @@ void ARMv7Thread::fast_call(u32 addr) { cpu_task_main(); - if (SP != old_SP && !test(state, cpu_state::ret + cpu_state::exit)) // SP shouldn't change + if (SP != old_SP && !test(state, cpu_flag::ret + cpu_flag::exit)) // SP shouldn't change { fmt::throw_exception("Stack inconsistency (addr=0x%x, SP=0x%x, old=0x%x)", addr, SP, old_SP); } } - catch (cpu_state _s) + catch (cpu_flag _s) { state += _s; - if (_s != cpu_state::ret) throw; + if (_s != cpu_flag::ret) throw; } catch (EmulationStopped) { @@ -165,7 +165,7 @@ void ARMv7Thread::fast_call(u32 addr) throw; } - state -= cpu_state::ret; + state -= cpu_flag::ret; PC = old_PC; SP = old_SP; @@ -173,3 +173,46 @@ void ARMv7Thread::fast_call(u32 addr) custom_task = std::move(old_task); last_function = old_func; } + +u32 ARMv7Thread::stack_push(u32 size, u32 align_v) +{ + if (auto cpu = get_current_cpu_thread()) + { + ARMv7Thread& context = static_cast(*cpu); + + const u32 old_pos = context.SP; + context.SP -= align(size + 4, 4); // room minimal possible size + context.SP &= ~(align_v - 1); // fix stack alignment + + if (context.SP < context.stack_addr) + { + fmt::throw_exception("Stack overflow (size=0x%x, align=0x%x, SP=0x%x, stack=*0x%x)" HERE, size, align_v, context.SP, context.stack_addr); + } + else + { + vm::psv::_ref>(context.SP + size) = old_pos; + return context.SP; + } + } + + fmt::throw_exception("Invalid thread" HERE); +} + +void ARMv7Thread::stack_pop_verbose(u32 addr, u32 size) noexcept +{ + if (auto cpu = get_current_cpu_thread()) + { + ARMv7Thread& context = static_cast(*cpu); + + if (context.SP != addr) + { + LOG_ERROR(ARMv7, "Stack inconsistency (addr=0x%x, SP=0x%x, size=0x%x)", addr, context.SP, size); + return; + } + + context.SP = vm::psv::_ref>(context.SP + size); + return; + } + + LOG_ERROR(ARMv7, "Invalid thread" HERE); +} diff --git a/rpcs3/Emu/PSP2/ARMv7Thread.h b/rpcs3/Emu/PSP2/ARMv7Thread.h index 721277ab2e..d310281ba4 100644 --- a/rpcs3/Emu/PSP2/ARMv7Thread.h +++ b/rpcs3/Emu/PSP2/ARMv7Thread.h @@ -196,6 +196,9 @@ public: } void fast_call(u32 addr); + + static u32 stack_push(u32 size, u32 align_v); + static void stack_pop_verbose(u32 addr, u32 size) noexcept; }; template diff --git a/rpcs3/Emu/PSP2/Modules/sceLibKernel.cpp b/rpcs3/Emu/PSP2/Modules/sceLibKernel.cpp index 05061e7e83..641b6039e5 100644 --- a/rpcs3/Emu/PSP2/Modules/sceLibKernel.cpp +++ b/rpcs3/Emu/PSP2/Modules/sceLibKernel.cpp @@ -138,7 +138,7 @@ arm_error_code sceKernelExitThread(ARMv7Thread& cpu, s32 exitStatus) sceLibKernel.warning("sceKernelExitThread(exitStatus=0x%x)", exitStatus); // Exit status is stored in r0 - cpu.state += cpu_state::exit; + cpu.state += cpu_flag::exit; return SCE_OK; } @@ -170,7 +170,7 @@ arm_error_code sceKernelExitDeleteThread(ARMv7Thread& cpu, s32 exitStatus) { sceLibKernel.warning("sceKernelExitDeleteThread(exitStatus=0x%x)", exitStatus); - //cpu.state += cpu_state::stop; + //cpu.state += cpu_flag::stop; // Delete current thread; exit status is stored in r0 fxm::get()->free(cpu.TLS); @@ -517,7 +517,7 @@ struct psp2_event_flag final { idm::get(cmd.arg, [&](u32, ARMv7Thread& cpu) { - cpu.state += cpu_state::signal; + cpu.state += cpu_flag::signal; cpu.lock_notify(); }); @@ -545,11 +545,11 @@ struct psp2_event_flag final { if (!exec(task::signal, cpu.id)) { - thread_lock{cpu}, thread_ctrl::wait(WRAP_EXPR(cpu.state.test_and_reset(cpu_state::signal))); + thread_lock{cpu}, thread_ctrl::wait(WRAP_EXPR(cpu.state.test_and_reset(cpu_flag::signal))); } else { - cpu.state -= cpu_state::signal; + cpu.state -= cpu_flag::signal; } } } @@ -579,7 +579,7 @@ private: { cpu.GPR[0] = SCE_OK; cpu.GPR[1] = pattern; - cpu.state += cpu_state::signal; + cpu.state += cpu_flag::signal; cpu->lock_notify(); } else @@ -679,7 +679,7 @@ private: { cpu.GPR[0] = SCE_OK; cpu.GPR[1] = old_pattern; - cpu.state += cpu_state::signal; + cpu.state += cpu_flag::signal; cpu.owner = nullptr; cpu->unlock(); cpu->notify(); @@ -713,7 +713,7 @@ private: { cpu.GPR[0] = error; cpu.GPR[1] = pattern; - cpu.state += cpu_state::signal; + cpu.state += cpu_flag::signal; cpu.owner = nullptr; cpu->unlock(); cpu->notify(); @@ -858,7 +858,7 @@ arm_error_code sceKernelWaitEventFlag(ARMv7Thread& cpu, s32 evfId, u32 bitPatter cpu.GPR[1] = bitPattern; // Second chance - if (evf->exec(psp2_event_flag::task::wait, cpu.id) && cpu.state.test_and_reset(cpu_state::signal)) + if (evf->exec(psp2_event_flag::task::wait, cpu.id) && cpu.state.test_and_reset(cpu_flag::signal)) { if (pResultPat) *pResultPat = cpu.GPR[1]; return SCE_OK; @@ -866,7 +866,7 @@ arm_error_code sceKernelWaitEventFlag(ARMv7Thread& cpu, s32 evfId, u32 bitPatter thread_lock entry(cpu); - if (!thread_ctrl::wait_for(timeout, WRAP_EXPR(cpu.state.test_and_reset(cpu_state::signal)))) + if (!thread_ctrl::wait_for(timeout, WRAP_EXPR(cpu.state.test_and_reset(cpu_flag::signal)))) { // Timeout cleanup cpu.owner = nullptr; diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index 4a96ceb908..ed3028ba61 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -25,6 +25,8 @@ #include +system_type g_system; + cfg::bool_entry g_cfg_autostart(cfg::root.misc, "Always start after boot", true); cfg::bool_entry g_cfg_autoexit(cfg::root.misc, "Exit RPCS3 when process finishes"); @@ -208,6 +210,7 @@ void Emulator::Load() else if (ppu_exec.open(elf_file) == elf_error::ok) { // PS3 executable + g_system = system_type::ps3; m_status = Ready; vm::ps3::init(); @@ -276,6 +279,7 @@ void Emulator::Load() else if (ppu_prx.open(elf_file) == elf_error::ok) { // PPU PRX (experimental) + g_system = system_type::ps3; m_status = Ready; vm::ps3::init(); ppu_load_prx(ppu_prx); @@ -283,6 +287,7 @@ void Emulator::Load() else if (spu_exec.open(elf_file) == elf_error::ok) { // SPU executable (experimental) + g_system = system_type::ps3; m_status = Ready; vm::ps3::init(); spu_load_exec(spu_exec); @@ -290,6 +295,7 @@ void Emulator::Load() else if (arm_exec.open(elf_file) == elf_error::ok) { // ARMv7 executable + g_system = system_type::psv; m_status = Ready; vm::psv::init(); arm_load_exec(arm_exec); @@ -370,7 +376,7 @@ bool Emulator::Pause() idm::select([](u32, cpu_thread& cpu) { - cpu.state += cpu_state::dbg_global_pause; + cpu.state += cpu_flag::dbg_global_pause; }); SendDbgCommand(DID_PAUSED_EMU); @@ -404,7 +410,7 @@ void Emulator::Resume() idm::select([](u32, cpu_thread& cpu) { - cpu.state -= cpu_state::dbg_global_pause; + cpu.state -= cpu_flag::dbg_global_pause; cpu.lock_notify(); }); @@ -430,7 +436,7 @@ void Emulator::Stop() idm::select([](u32, cpu_thread& cpu) { - cpu.state += cpu_state::dbg_global_stop; + cpu.state += cpu_flag::dbg_global_stop; cpu->lock(); cpu->set_exception(std::make_exception_ptr(EmulationStopped())); cpu->unlock(); diff --git a/rpcs3/Emu/System.h b/rpcs3/Emu/System.h index f7ad3c12d4..97b1b1d2bb 100644 --- a/rpcs3/Emu/System.h +++ b/rpcs3/Emu/System.h @@ -3,6 +3,16 @@ #include "VFS.h" #include "DbgCommand.h" +enum class system_type +{ + ps3, + psv, // Experimental + //psp, // Hypothetical +}; + +// Current process type +extern system_type g_system; + enum class frame_type; struct EmuCallbacks diff --git a/rpcs3/Gui/InstructionEditor.cpp b/rpcs3/Gui/InstructionEditor.cpp index 85fec55814..19d7e2bbd2 100644 --- a/rpcs3/Gui/InstructionEditor.cpp +++ b/rpcs3/Gui/InstructionEditor.cpp @@ -1,8 +1,10 @@ #include "stdafx.h" #include "stdafx_gui.h" +#include "Emu/System.h" #include "Emu/Memory/Memory.h" #include "Emu/CPU/CPUThread.h" #include "Emu/CPU/CPUDisAsm.h" +#include "Emu/Cell/PPUThread.h" #include "Emu/Cell/SPUThread.h" #include "InstructionEditor.h" @@ -59,7 +61,7 @@ InstructionEditorDialog::InstructionEditorDialog(wxPanel *parent, u32 _pc, cpu_t s_panel_margin_x->Add(s_panel_margin_y); s_panel_margin_x->AddSpacer(12); - const u32 cpu_offset = cpu->type == cpu_type::spu ? static_cast(*cpu).offset : 0; + const u32 cpu_offset = g_system == system_type::ps3 && cpu->id < ppu_thread::id_min ? static_cast(*cpu).offset : 0; this->Connect(wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler(InstructionEditorDialog::updatePreview)); t2_instr->SetValue(wxString::Format("%08x", vm::ps3::read32(cpu_offset + pc).value())); @@ -81,7 +83,7 @@ void InstructionEditorDialog::updatePreview(wxCommandEvent& event) ulong opcode; if (t2_instr->GetValue().ToULong(&opcode, 16)) { - if (cpu->type == cpu_type::arm) + if (g_system == system_type::psv) { t3_preview->SetLabel("Preview for ARMv7Thread not implemented yet."); } diff --git a/rpcs3/Gui/InterpreterDisAsm.cpp b/rpcs3/Gui/InterpreterDisAsm.cpp index d0d305c236..0bdd406c3e 100644 --- a/rpcs3/Gui/InterpreterDisAsm.cpp +++ b/rpcs3/Gui/InterpreterDisAsm.cpp @@ -23,11 +23,10 @@ std::map g_breakpoints; u32 InterpreterDisAsmFrame::GetPc() const { - switch (cpu->type) + switch (g_system) { - case cpu_type::ppu: return static_cast(cpu)->cia; - case cpu_type::spu: return static_cast(cpu)->pc; - case cpu_type::arm: return static_cast(cpu)->PC; + case system_type::ps3: return cpu->id >= ppu_thread::id_min ? static_cast(cpu)->cia : static_cast(cpu)->pc; + case system_type::psv: return static_cast(cpu)->PC; } return 0xabadcafe; @@ -137,21 +136,23 @@ void InterpreterDisAsmFrame::OnSelectUnit(wxCommandEvent& event) if (cpu = (cpu_thread*)event.GetClientData()) { - switch (cpu->type) + switch (g_system) { - case cpu_type::ppu: + case system_type::ps3: { - m_disasm = std::make_unique(CPUDisAsm_InterpreterMode); + if (cpu->id >= ppu_thread::id_min) + { + m_disasm = std::make_unique(CPUDisAsm_InterpreterMode); + } + else + { + m_disasm = std::make_unique(CPUDisAsm_InterpreterMode); + } + break; } - case cpu_type::spu: - { - m_disasm = std::make_unique(CPUDisAsm_InterpreterMode); - break; - } - - case cpu_type::arm: + case system_type::psv: { m_disasm = std::make_unique(CPUDisAsm_InterpreterMode); break; @@ -249,7 +250,7 @@ void InterpreterDisAsmFrame::ShowAddr(u32 addr) } else { - const u32 cpu_offset = cpu->type == cpu_type::spu ? static_cast(*cpu).offset : 0; + const u32 cpu_offset = g_system == system_type::ps3 && cpu->id < ppu_thread::id_min ? static_cast(*cpu).offset : 0; m_disasm->offset = (u8*)vm::base(cpu_offset); for (uint i = 0, count = 4; istate & cpu_state_pause)) { - cpu->state -= cpu_state::dbg_pause; + cpu->state -= cpu_flag::dbg_pause; (*cpu)->lock_notify(); } } @@ -447,7 +448,7 @@ void InterpreterDisAsmFrame::DoPause(wxCommandEvent& WXUNUSED(event)) { if (cpu) { - cpu->state += cpu_state::dbg_pause; + cpu->state += cpu_flag::dbg_pause; } } @@ -455,10 +456,10 @@ void InterpreterDisAsmFrame::DoStep(wxCommandEvent& WXUNUSED(event)) { if (cpu) { - if (test(cpu_state::dbg_pause, cpu->state.fetch_op([](bs_t& state) + if (test(cpu_flag::dbg_pause, cpu->state.fetch_op([](bs_t& state) { - state += cpu_state::dbg_step; - state -= cpu_state::dbg_pause; + state += cpu_flag::dbg_step; + state -= cpu_flag::dbg_pause; }))) { (*cpu)->lock_notify(); diff --git a/rpcs3/Gui/RegisterEditor.cpp b/rpcs3/Gui/RegisterEditor.cpp index 5e2ddc2731..3a74168328 100644 --- a/rpcs3/Gui/RegisterEditor.cpp +++ b/rpcs3/Gui/RegisterEditor.cpp @@ -1,5 +1,6 @@ #include "stdafx.h" #include "stdafx_gui.h" +#include "Emu/System.h" #include "Emu/CPU/CPUThread.h" #include "Emu/CPU/CPUDisAsm.h" #include "Emu/Cell/PPUThread.h" @@ -53,22 +54,28 @@ RegisterEditorDialog::RegisterEditorDialog(wxPanel *parent, u32 _pc, cpu_thread* Bind(wxEVT_COMBOBOX, &RegisterEditorDialog::updateRegister, this); - switch (cpu->type) + switch (g_system) { - case cpu_type::ppu: - for (int i = 0; i<32; i++) t1_register->Append(wxString::Format("GPR[%d]", i)); - for (int i = 0; i<32; i++) t1_register->Append(wxString::Format("FPR[%d]", i)); - for (int i = 0; i<32; i++) t1_register->Append(wxString::Format("VR[%d]", i)); - t1_register->Append("CR"); - t1_register->Append("LR"); - t1_register->Append("CTR"); - //t1_register->Append("XER"); - //t1_register->Append("FPSCR"); - break; + case system_type::ps3: + { + if (_cpu->id >= ppu_thread::id_min) + { + for (int i = 0; i < 32; i++) t1_register->Append(wxString::Format("GPR[%d]", i)); + for (int i = 0; i < 32; i++) t1_register->Append(wxString::Format("FPR[%d]", i)); + for (int i = 0; i < 32; i++) t1_register->Append(wxString::Format("VR[%d]", i)); + t1_register->Append("CR"); + t1_register->Append("LR"); + t1_register->Append("CTR"); + //t1_register->Append("XER"); + //t1_register->Append("FPSCR"); + } + else + { + for (int i = 0; i < 128; i++) t1_register->Append(wxString::Format("GPR[%d]", i)); + } - case cpu_type::spu: - for (int i = 0; i<128; i++) t1_register->Append(wxString::Format("GPR[%d]", i)); break; + } default: wxMessageBox("Not supported thread.", "Error"); @@ -82,33 +89,28 @@ RegisterEditorDialog::RegisterEditorDialog(wxPanel *parent, u32 _pc, cpu_thread* std::string reg = fmt::ToUTF8(t1_register->GetStringSelection()); std::string value = fmt::ToUTF8(t2_value->GetValue()); - switch (cpu->type) - { - case cpu_type::ppu: + if (g_system == system_type::ps3 && cpu->id >= ppu_thread::id_min) { auto& ppu = *static_cast(cpu); while (value.length() < 32) value = "0" + value; - std::string::size_type first_brk = reg.find('['); + const auto first_brk = reg.find('['); try { - if (first_brk != std::string::npos) + if (first_brk != -1) { - long reg_index = atol(reg.substr(first_brk + 1, reg.length() - first_brk - 2).c_str()); + const long reg_index = std::atol(reg.substr(first_brk + 1, reg.length() - first_brk - 2).c_str()); if (reg.find("GPR") == 0 || reg.find("FPR") == 0) { - unsigned long long reg_value; - reg_value = std::stoull(value.substr(16, 31), 0, 16); + const ullong reg_value = std::stoull(value.substr(16, 31), 0, 16); if (reg.find("GPR") == 0) ppu.gpr[reg_index] = (u64)reg_value; if (reg.find("FPR") == 0) (u64&)ppu.fpr[reg_index] = (u64)reg_value; return; } if (reg.find("VR") == 0) { - unsigned long long reg_value0; - unsigned long long reg_value1; - reg_value0 = std::stoull(value.substr(16, 31), 0, 16); - reg_value1 = std::stoull(value.substr(0, 15), 0, 16); + const ullong reg_value0 = std::stoull(value.substr(16, 31), 0, 16); + const ullong reg_value1 = std::stoull(value.substr(0, 15), 0, 16); ppu.vr[reg_index]._u64[0] = (u64)reg_value0; ppu.vr[reg_index]._u64[1] = (u64)reg_value1; return; @@ -116,58 +118,46 @@ RegisterEditorDialog::RegisterEditorDialog(wxPanel *parent, u32 _pc, cpu_thread* } if (reg == "LR" || reg == "CTR") { - unsigned long long reg_value; - reg_value = std::stoull(value.substr(16, 31), 0, 16); + const ullong reg_value = std::stoull(value.substr(16, 31), 0, 16); if (reg == "LR") ppu.lr = (u64)reg_value; if (reg == "CTR") ppu.ctr = (u64)reg_value; return; } if (reg == "CR") { - unsigned long long reg_value; - reg_value = std::stoull(value.substr(24, 31), 0, 16); + const ullong reg_value = std::stoull(value.substr(24, 31), 0, 16); if (reg == "CR") ppu.cr_unpack((u32)reg_value); return; } } - catch (std::invalid_argument&)//if any of the stoull conversion fail + catch (std::invalid_argument&) //if any of the stoull conversion fail { - break; } - - break; } - case cpu_type::spu: + else if (g_system == system_type::ps3 && cpu->id < ppu_thread::id_min) { auto& spu = *static_cast(cpu); while (value.length() < 32) value = "0" + value; - std::string::size_type first_brk = reg.find('['); - if (first_brk != std::string::npos) + const auto first_brk = reg.find('['); + try { - long reg_index; - reg_index = atol(reg.substr(first_brk + 1, reg.length() - 2).c_str()); - if (reg.find("GPR") == 0) + if (first_brk != -1) { - ullong reg_value0; - ullong reg_value1; - try + const long reg_index = std::atol(reg.substr(first_brk + 1, reg.length() - 2).c_str()); + if (reg.find("GPR") == 0) { - reg_value0 = std::stoull(value.substr(16, 31), 0, 16); - reg_value1 = std::stoull(value.substr(0, 15), 0, 16); + const ullong reg_value0 = std::stoull(value.substr(16, 31), 0, 16); + const ullong reg_value1 = std::stoull(value.substr(0, 15), 0, 16); + spu.gpr[reg_index]._u64[0] = (u64)reg_value0; + spu.gpr[reg_index]._u64[1] = (u64)reg_value1; + return; } - catch (std::invalid_argument& /*e*/) - { - break; - } - spu.gpr[reg_index]._u64[0] = (u64)reg_value0; - spu.gpr[reg_index]._u64[1] = (u64)reg_value1; - return; } } - - break; - } + catch (std::invalid_argument&) + { + } } wxMessageBox("This value could not be converted.\nNo changes were made.", "Error"); @@ -179,9 +169,7 @@ void RegisterEditorDialog::updateRegister(wxCommandEvent& event) std::string reg = fmt::ToUTF8(t1_register->GetStringSelection()); std::string str; - switch (cpu->type) - { - case cpu_type::ppu: + if (g_system == system_type::ps3 && cpu->id >= ppu_thread::id_min) { auto& ppu = *static_cast(cpu); @@ -196,9 +184,8 @@ void RegisterEditorDialog::updateRegister(wxCommandEvent& event) if (reg == "CR") str = fmt::format("%08x", ppu.cr_pack()); if (reg == "LR") str = fmt::format("%016llx", ppu.lr); if (reg == "CTR") str = fmt::format("%016llx", ppu.ctr); - break; } - case cpu_type::spu: + else if (g_system == system_type::ps3 && cpu->id < ppu_thread::id_min) { auto& spu = *static_cast(cpu); @@ -209,8 +196,6 @@ void RegisterEditorDialog::updateRegister(wxCommandEvent& event) reg_index = atol(reg.substr(first_brk + 1, reg.length() - 2).c_str()); if (reg.find("GPR") == 0) str = fmt::format("%016llx%016llx", spu.gpr[reg_index]._u64[1], spu.gpr[reg_index]._u64[0]); } - break; - } } t2_value->SetValue(fmt::FromUTF8(str));