mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-20 19:45:20 +00:00
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:
parent
b307aff9eb
commit
969af86eba
3 changed files with 44 additions and 23 deletions
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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::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<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) //
|
||||
|
@ -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<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) //
|
||||
|
|
Loading…
Add table
Reference in a new issue