diff --git a/rpcs3/Emu/Cell/PPUThread.cpp b/rpcs3/Emu/Cell/PPUThread.cpp index 02026158a3..a6b5469fa3 100644 --- a/rpcs3/Emu/Cell/PPUThread.cpp +++ b/rpcs3/Emu/Cell/PPUThread.cpp @@ -1292,26 +1292,31 @@ void ppu_thread::fast_call(u32 addr, u32 rtoc) at_ret(); } -u32 ppu_thread::stack_push(u32 size, u32 align_v) +std::pair ppu_thread::stack_push(u32 size, u32 align_v) { if (auto cpu = get_current_cpu_thread()) { ppu_thread& context = static_cast(*cpu); const u32 old_pos = vm::cast(context.gpr[1]); - context.gpr[1] -= utils::align(size + 4, 8); // room minimal possible size + context.gpr[1] -= size; // room minimal possible size context.gpr[1] &= ~(u64{align_v} - 1); // fix stack alignment - if (old_pos >= context.stack_addr && old_pos < context.stack_addr + context.stack_size && context.gpr[1] < context.stack_addr) + auto is_stack = [&](u64 addr) + { + return addr >= context.stack_addr && addr < context.stack_addr + context.stack_size; + }; + + // TODO: This check does not care about custom stack memory + if (is_stack(old_pos) != is_stack(context.gpr[1])) { fmt::throw_exception("Stack overflow (size=0x%x, align=0x%x, SP=0x%llx, stack=*0x%x)", size, align_v, old_pos, context.stack_addr); } else { const u32 addr = static_cast(context.gpr[1]); - vm::_ref>(addr + size) = old_pos; std::memset(vm::base(addr), 0, size); - return addr; + return {vm::cast(addr), old_pos - addr}; } } @@ -1330,7 +1335,7 @@ void ppu_thread::stack_pop_verbose(u32 addr, u32 size) noexcept return; } - context.gpr[1] = vm::_ref>(static_cast(context.gpr[1]) + size); + context.gpr[1] += size; return; } diff --git a/rpcs3/Emu/Cell/PPUThread.h b/rpcs3/Emu/Cell/PPUThread.h index 201d72feb1..825f934f91 100644 --- a/rpcs3/Emu/Cell/PPUThread.h +++ b/rpcs3/Emu/Cell/PPUThread.h @@ -308,7 +308,7 @@ public: void exec_task(); void fast_call(u32 addr, u32 rtoc); - static u32 stack_push(u32 size, u32 align_v); + static std::pair stack_push(u32 size, u32 align_v); static void stack_pop_verbose(u32 addr, u32 size) noexcept; }; diff --git a/rpcs3/Emu/Memory/vm_var.h b/rpcs3/Emu/Memory/vm_var.h index f31c1b8782..323699ae6f 100644 --- a/rpcs3/Emu/Memory/vm_var.h +++ b/rpcs3/Emu/Memory/vm_var.h @@ -9,23 +9,23 @@ namespace vm template struct page_allocator { - static inline vm::addr_t alloc(u32 size, u32 align) + static inline std::pair alloc(u32 size, u32 align) { - return vm::cast(vm::alloc(size, Location, std::max(align, 0x10000))); + return {vm::cast(vm::alloc(size, Location, std::max(align, 0x10000))), size}; } - static inline void dealloc(u32 addr, u32 /*size*/ = 0) noexcept + static inline void dealloc(u32 addr, u32 size) noexcept { - ensure(vm::dealloc(addr, Location)); + ensure(vm::dealloc(addr, Location) >= size); } }; template struct stack_allocator { - static inline vm::addr_t alloc(u32 size, u32 align) + static inline std::pair alloc(u32 size, u32 align) { - return vm::cast(T::stack_push(size, align)); + return T::stack_push(size, align); } static inline void dealloc(u32 addr, u32 size) noexcept @@ -40,6 +40,14 @@ namespace vm { using pointer = _ptr_base; + const u32 m_mem_size; + + _var_base(std::pair alloc_info) + : pointer(alloc_info.first) + , m_mem_size(alloc_info.second) + { + } + public: // Unmoveable object _var_base(const _var_base&) = delete; @@ -49,7 +57,7 @@ namespace vm using enable_bitcopy = std::false_type; // Disable bitcopy inheritence _var_base() - : pointer(A::alloc(sizeof(T), alignof(T))) + : _var_base(A::alloc(sizeof(T), alignof(T))) { } @@ -63,7 +71,7 @@ namespace vm { if (pointer::addr()) { - A::dealloc(pointer::addr(), sizeof(T)); + A::dealloc(pointer::addr(), m_mem_size); } } }; @@ -74,7 +82,15 @@ namespace vm { using pointer = _ptr_base; - u32 m_size; + const u32 m_mem_size; + const u32 m_size; + + _var_base(u32 count, std::pair alloc_info) + : pointer(alloc_info.first) + , m_mem_size(alloc_info.second) + , m_size(u32{sizeof(T)} * count) + { + } public: _var_base(const _var_base&) = delete; @@ -84,8 +100,7 @@ namespace vm using enable_bitcopy = std::false_type; // Disable bitcopy inheritence _var_base(u32 count) - : pointer(A::alloc(u32{sizeof(T)} * count, alignof(T))) - , m_size(u32{sizeof(T)} * count) + : _var_base(count, A::alloc(u32{sizeof(T)} * count, alignof(T))) { } @@ -101,7 +116,7 @@ namespace vm { if (pointer::addr()) { - A::dealloc(pointer::addr(), m_size); + A::dealloc(pointer::addr(), m_mem_size); } }