diff --git a/rpcs3/Emu/CPU/CPUThread.cpp b/rpcs3/Emu/CPU/CPUThread.cpp index f055e72cf8..bb952393aa 100644 --- a/rpcs3/Emu/CPU/CPUThread.cpp +++ b/rpcs3/Emu/CPU/CPUThread.cpp @@ -145,7 +145,7 @@ void CPUThread::NextPc(u8 instr_size) } } -void CPUThread::SetBranch(const u64 pc) +void CPUThread::SetBranch(const u64 pc, bool record_branch) { if(!Memory.IsGoodAddr(m_offset + pc)) { @@ -155,6 +155,9 @@ void CPUThread::SetBranch(const u64 pc) m_is_branch = true; nPC = pc; + + if(record_branch) + CallStackBranch(pc); } void CPUThread::SetPc(const u64 pc) diff --git a/rpcs3/Emu/CPU/CPUThread.h b/rpcs3/Emu/CPU/CPUThread.h index bc8d4a0cad..bde7140c8b 100644 --- a/rpcs3/Emu/CPU/CPUThread.h +++ b/rpcs3/Emu/CPU/CPUThread.h @@ -132,7 +132,7 @@ public: int ThreadStatus(); void NextPc(u8 instr_size); - void SetBranch(const u64 pc); + void SetBranch(const u64 pc, bool record_branch = false); void SetPc(const u64 pc); void SetEntry(const u64 entry); @@ -171,15 +171,50 @@ public: virtual void Exec(); void ExecOnce(); - Stack m_call_stack; + struct CallStackItem + { + u64 pc; + u64 branch_pc; + }; + + Stack m_call_stack; + wxString CallStackToString() { wxString ret = "Call Stack:\n==========\n"; + for(uint i=0; i 0x%llx\n", m_call_stack[i].pc, m_call_stack[i].branch_pc); + } + return ret; } + void CallStackBranch(u64 pc) + { + for(int i=m_call_stack.GetCount() - 1; i >= 0; --i) + { + if(CallStackGetNextPC(m_call_stack[i].pc) == pc) + { + m_call_stack.RemoveAt(i, m_call_stack.GetCount() - i); + return; + } + } + + CallStackItem new_item; + + new_item.branch_pc = pc; + new_item.pc = PC; + + m_call_stack.AddCpy(new_item); + } + + virtual u64 CallStackGetNextPC(u64 pc) + { + return pc + 4; + } + protected: virtual void DoReset()=0; virtual void DoRun()=0; diff --git a/rpcs3/Emu/Cell/PPUInterpreter.h b/rpcs3/Emu/Cell/PPUInterpreter.h index 96c0856b61..44c5eb67fd 100644 --- a/rpcs3/Emu/Cell/PPUInterpreter.h +++ b/rpcs3/Emu/Cell/PPUInterpreter.h @@ -2059,7 +2059,7 @@ private: void BC(u32 bo, u32 bi, s32 bd, u32 aa, u32 lk) { if(!CheckCondition(bo, bi)) return; - CPU.SetBranch(branchTarget((aa ? 0 : CPU.PC), bd)); + CPU.SetBranch(branchTarget((aa ? 0 : CPU.PC), bd), lk); if(lk) CPU.LR = CPU.PC + 4; } void SC(s32 sc_code) @@ -2074,9 +2074,8 @@ private: } void B(s32 ll, u32 aa, u32 lk) { - CPU.SetBranch(branchTarget(aa ? 0 : CPU.PC, ll)); + CPU.SetBranch(branchTarget(aa ? 0 : CPU.PC, ll), lk); if(lk) CPU.LR = CPU.PC + 4; - CPU.m_call_stack.Push(branchTarget(aa ? 0 : CPU.PC, ll)); //This does not affect emulation } void MCRF(u32 crfd, u32 crfs) { @@ -2085,9 +2084,8 @@ private: void BCLR(u32 bo, u32 bi, u32 bh, u32 lk) { if(!CheckCondition(bo, bi)) return; - CPU.SetBranch(branchTarget(0, CPU.LR)); + CPU.SetBranch(branchTarget(0, CPU.LR), true); if(lk) CPU.LR = CPU.PC + 4; - CPU.m_call_stack.Pop(); //This does not affect emulation } void CRNOR(u32 crbd, u32 crba, u32 crbb) { @@ -2136,7 +2134,7 @@ private: { if(bo & 0x10 || CPU.IsCR(bi) == (bo & 0x8)) { - CPU.SetBranch(branchTarget(0, CPU.CTR)); + CPU.SetBranch(branchTarget(0, CPU.CTR), true); if(lk) CPU.LR = CPU.PC + 4; } }