From 969af86eba231a59717e237ee497bede54915fe0 Mon Sep 17 00:00:00 2001 From: eladash Date: Fri, 29 Mar 2019 16:49:19 +0300 Subject: [PATCH] SPU: Implement BISLED DFCMGT instruction removed, it was wrong to add to begin with ASMJIT: Fix compilation of double compare instructions, move exception to runtime instead of compiletime! Jarves confirmed that he implemented this instruction because of that bug with asmjit only, affected God Of War 3 --- rpcs3/Emu/Cell/SPUASMJITRecompiler.cpp | 37 ++++++++++++++++---------- rpcs3/Emu/Cell/SPUInterpreter.cpp | 16 +++++++---- rpcs3/Emu/Cell/SPURecompiler.cpp | 14 +++++++--- 3 files changed, 44 insertions(+), 23 deletions(-) diff --git a/rpcs3/Emu/Cell/SPUASMJITRecompiler.cpp b/rpcs3/Emu/Cell/SPUASMJITRecompiler.cpp index d71278e324..21be3d4af0 100644 --- a/rpcs3/Emu/Cell/SPUASMJITRecompiler.cpp +++ b/rpcs3/Emu/Cell/SPUASMJITRecompiler.cpp @@ -1,4 +1,4 @@ -#include "stdafx.h" +#include "stdafx.h" #include "Emu/Memory/vm.h" #include "Emu/System.h" #include "Emu/IdManager.h" @@ -2681,7 +2681,23 @@ void spu_recompiler::IRET(spu_opcode_t op) void spu_recompiler::BISLED(spu_opcode_t op) { - fmt::throw_exception("Unimplemented instruction" HERE); + c->mov(*addr, SPU_OFF_32(gpr, op.ra, &v128::_u32, 3)); + c->and_(*addr, 0x3fffc); + + const XmmLink& vr = XmmAlloc(); + c->movdqa(vr, XmmConst(_mm_set_epi32(spu_branch_target(m_pos + 4), 0, 0, 0))); + c->movdqa(SPU_OFF_128(gpr, op.rt), vr); + + asmjit::Label branch_label = c->newLabel(); + get_events(); + c->jne(branch_label); + + after.emplace_back([=] + { + c->align(asmjit::kAlignCode, 16); + c->bind(branch_label); + branch_indirect(op); + }); } void spu_recompiler::HBR(spu_opcode_t op) @@ -3429,7 +3445,7 @@ void spu_recompiler::FCGT(spu_opcode_t op) void spu_recompiler::DFCGT(spu_opcode_t op) { - fmt::throw_exception("Unexpected instruction" HERE); + UNK(op); } void spu_recompiler::FA(spu_opcode_t op) @@ -3572,14 +3588,7 @@ void spu_recompiler::FCMGT(spu_opcode_t op) void spu_recompiler::DFCMGT(spu_opcode_t op) { - const auto mask = XmmConst(_mm_set1_epi64x(0x7fffffffffffffff)); - const XmmLink& va = XmmGet(op.ra, XmmType::Double); - const XmmLink& vb = XmmGet(op.rb, XmmType::Double); - - c->andpd(va, mask); - c->andpd(vb, mask); - c->cmppd(vb, va, 1); - c->movaps(SPU_OFF_128(gpr, op.rt), vb); + UNK(op); } void spu_recompiler::DFA(spu_opcode_t op) @@ -3798,7 +3807,7 @@ void spu_recompiler::FSCRWR(spu_opcode_t op) void spu_recompiler::DFTSV(spu_opcode_t op) { - fmt::throw_exception("Unexpected instruction" HERE); + UNK(op); } void spu_recompiler::FCEQ(spu_opcode_t op) @@ -3811,7 +3820,7 @@ void spu_recompiler::FCEQ(spu_opcode_t op) void spu_recompiler::DFCEQ(spu_opcode_t op) { - fmt::throw_exception("Unexpected instruction" HERE); + UNK(op); } void spu_recompiler::MPY(spu_opcode_t op) @@ -3876,7 +3885,7 @@ void spu_recompiler::FCMEQ(spu_opcode_t op) void spu_recompiler::DFCMEQ(spu_opcode_t op) { - fmt::throw_exception("Unexpected instruction" HERE); + UNK(op); } void spu_recompiler::MPYU(spu_opcode_t op) diff --git a/rpcs3/Emu/Cell/SPUInterpreter.cpp b/rpcs3/Emu/Cell/SPUInterpreter.cpp index 5518ed864c..c94ccc8852 100644 --- a/rpcs3/Emu/Cell/SPUInterpreter.cpp +++ b/rpcs3/Emu/Cell/SPUInterpreter.cpp @@ -496,7 +496,16 @@ bool spu_interpreter::IRET(spu_thread& spu, spu_opcode_t op) bool spu_interpreter::BISLED(spu_thread& spu, spu_opcode_t op) { - fmt::throw_exception("Unimplemented instruction" HERE); + const u32 target = spu_branch_target(spu.gpr[op.ra]._u32[3]); + spu.gpr[op.rt] = v128::from32r(spu_branch_target(spu.pc + 4)); + + if (spu.get_events()) + { + spu.pc = target; + set_interrupt_status(spu, op); + return false; + } + return true; } @@ -1043,10 +1052,7 @@ bool spu_interpreter_fast::FCMGT(spu_thread& spu, spu_opcode_t op) bool spu_interpreter::DFCMGT(spu_thread& spu, spu_opcode_t op) { - const auto mask = _mm_castsi128_pd(_mm_set1_epi64x(0x7fffffffffffffff)); - const auto ra = _mm_and_pd(spu.gpr[op.ra].vd, mask); - const auto rb = _mm_and_pd(spu.gpr[op.rb].vd, mask); - spu.gpr[op.rt].vd = _mm_cmpgt_pd(ra, rb); + fmt::throw_exception("Unexpected Instruction" HERE); return true; } diff --git a/rpcs3/Emu/Cell/SPURecompiler.cpp b/rpcs3/Emu/Cell/SPURecompiler.cpp index bd4c71f1d4..3bb3ced322 100644 --- a/rpcs3/Emu/Cell/SPURecompiler.cpp +++ b/rpcs3/Emu/Cell/SPURecompiler.cpp @@ -1001,7 +1001,7 @@ const std::vector& spu_recompiler_base::analyse(const be_t* ls, u32 en case spu_itype::DFCEQ: case spu_itype::DFCMEQ: case spu_itype::DFCGT: - //case spu_itype::DFCMGT: + case spu_itype::DFCMGT: case spu_itype::DFTSV: { // Stop before invalid instructions (TODO) @@ -3706,7 +3706,7 @@ public: case spu_itype::DFCEQ: case spu_itype::DFCMEQ: case spu_itype::DFCGT: - //case spu_itype::DFCMGT: + case spu_itype::DFCMGT: case spu_itype::DFTSV: case spu_itype::STOP: case spu_itype::STOPD: @@ -5854,7 +5854,7 @@ public: void DFCMGT(spu_opcode_t op) // { - set_vr(op.rt, sext(fcmp(fabs(get_vr(op.ra)), fabs(get_vr(op.rb))))); + return UNK(op); } void DFCMEQ(spu_opcode_t op) // @@ -6785,7 +6785,13 @@ public: void BISLED(spu_opcode_t op) // { - UNK(op); + if (m_block) m_block->block_end = m_ir->GetInsertBlock(); + const auto addr = eval(extract(get_vr(op.ra), 3) & 0x3fffc); + set_link(op); + value_t res; + res.value = call(&exec_get_events, m_thread); + const auto target = add_block_indirect(op, addr); + m_ir->CreateCondBr(m_ir->CreateICmpNE(res.value, m_ir->getInt32(0)), target, add_block_next()); } void BRZ(spu_opcode_t op) //