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
This commit is contained in:
eladash 2019-03-29 16:49:19 +03:00 committed by Ivan
parent b307aff9eb
commit 969af86eba
3 changed files with 44 additions and 23 deletions

View File

@ -1,4 +1,4 @@
#include "stdafx.h" #include "stdafx.h"
#include "Emu/Memory/vm.h" #include "Emu/Memory/vm.h"
#include "Emu/System.h" #include "Emu/System.h"
#include "Emu/IdManager.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) 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) 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) void spu_recompiler::DFCGT(spu_opcode_t op)
{ {
fmt::throw_exception("Unexpected instruction" HERE); UNK(op);
} }
void spu_recompiler::FA(spu_opcode_t 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) void spu_recompiler::DFCMGT(spu_opcode_t op)
{ {
const auto mask = XmmConst(_mm_set1_epi64x(0x7fffffffffffffff)); UNK(op);
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);
} }
void spu_recompiler::DFA(spu_opcode_t 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) void spu_recompiler::DFTSV(spu_opcode_t op)
{ {
fmt::throw_exception("Unexpected instruction" HERE); UNK(op);
} }
void spu_recompiler::FCEQ(spu_opcode_t 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) void spu_recompiler::DFCEQ(spu_opcode_t op)
{ {
fmt::throw_exception("Unexpected instruction" HERE); UNK(op);
} }
void spu_recompiler::MPY(spu_opcode_t 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) void spu_recompiler::DFCMEQ(spu_opcode_t op)
{ {
fmt::throw_exception("Unexpected instruction" HERE); UNK(op);
} }
void spu_recompiler::MPYU(spu_opcode_t op) void spu_recompiler::MPYU(spu_opcode_t op)

View File

@ -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) 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; 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) bool spu_interpreter::DFCMGT(spu_thread& spu, spu_opcode_t op)
{ {
const auto mask = _mm_castsi128_pd(_mm_set1_epi64x(0x7fffffffffffffff)); fmt::throw_exception("Unexpected Instruction" HERE);
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);
return true; return true;
} }

View File

@ -1001,7 +1001,7 @@ const std::vector<u32>& spu_recompiler_base::analyse(const be_t<u32>* ls, u32 en
case spu_itype::DFCEQ: case spu_itype::DFCEQ:
case spu_itype::DFCMEQ: case spu_itype::DFCMEQ:
case spu_itype::DFCGT: case spu_itype::DFCGT:
//case spu_itype::DFCMGT: case spu_itype::DFCMGT:
case spu_itype::DFTSV: case spu_itype::DFTSV:
{ {
// Stop before invalid instructions (TODO) // Stop before invalid instructions (TODO)
@ -3706,7 +3706,7 @@ public:
case spu_itype::DFCEQ: case spu_itype::DFCEQ:
case spu_itype::DFCMEQ: case spu_itype::DFCMEQ:
case spu_itype::DFCGT: case spu_itype::DFCGT:
//case spu_itype::DFCMGT: case spu_itype::DFCMGT:
case spu_itype::DFTSV: case spu_itype::DFTSV:
case spu_itype::STOP: case spu_itype::STOP:
case spu_itype::STOPD: case spu_itype::STOPD:
@ -5854,7 +5854,7 @@ public:
void DFCMGT(spu_opcode_t op) // void DFCMGT(spu_opcode_t op) //
{ {
set_vr(op.rt, sext<u64[2]>(fcmp<llvm::FCmpInst::FCMP_OGT>(fabs(get_vr<f64[2]>(op.ra)), fabs(get_vr<f64[2]>(op.rb))))); return UNK(op);
} }
void DFCMEQ(spu_opcode_t op) // void DFCMEQ(spu_opcode_t op) //
@ -6785,7 +6785,13 @@ public:
void BISLED(spu_opcode_t op) // 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<u32> 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) // void BRZ(spu_opcode_t op) //