mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-01-29 00:33:01 +00:00
SPU ASMJIT: inline WRCH
This commit is contained in:
parent
9516250bec
commit
738a7cac4f
@ -2235,6 +2235,8 @@ void spu_recompiler::MTSPR(spu_opcode_t op)
|
||||
|
||||
void spu_recompiler::WRCH(spu_opcode_t op)
|
||||
{
|
||||
using namespace asmjit;
|
||||
|
||||
auto gate = [](SPUThread* _spu, u32 ch, u32 value)
|
||||
{
|
||||
if (_spu->set_ch_value(ch, value))
|
||||
@ -2251,6 +2253,137 @@ void spu_recompiler::WRCH(spu_opcode_t op)
|
||||
c->mov(SPU_OFF_32(srr0), *addr);
|
||||
return;
|
||||
}
|
||||
case SPU_WrOutIntrMbox:
|
||||
{
|
||||
auto sub = [](SPUThread* _spu, spu_function_t _ret, u32 value)
|
||||
{
|
||||
if (!_spu->set_ch_value(SPU_WrOutIntrMbox, value))
|
||||
{
|
||||
fmt::raw_error("spu_recompiler::WRCH(): unexpected SPUThread::set_ch_value(SPU_WrOutIntrMbox) call");
|
||||
}
|
||||
|
||||
// Continue
|
||||
_ret(*_spu, _spu->_ptr<u8>(0), nullptr);
|
||||
};
|
||||
|
||||
Label ret = c->newLabel();
|
||||
Label wait = c->newLabel();
|
||||
c->mov(SPU_OFF_32(pc), m_pos);
|
||||
c->mov(qw0->r32(), SPU_OFF_32(gpr, op.rt, &v128::_u32, 3));
|
||||
c->bt(SPU_OFF_64(ch_out_intr_mbox), spu_channel::off_count);
|
||||
c->jc(wait);
|
||||
|
||||
after.emplace_back([=]
|
||||
{
|
||||
// Do not continue after waiting
|
||||
c->bind(wait);
|
||||
c->mov(*ls, op.ra);
|
||||
c->jmp(imm_ptr<void(*)(SPUThread*, u32, u32)>(gate));
|
||||
});
|
||||
|
||||
c->lea(*ls, x86::qword_ptr(ret));
|
||||
c->jmp(imm_ptr<void(*)(SPUThread*, spu_function_t, u32)>(sub));
|
||||
c->align(kAlignCode, 16);
|
||||
c->bind(ret);
|
||||
return;
|
||||
}
|
||||
case SPU_WrOutMbox:
|
||||
{
|
||||
Label wait = c->newLabel();
|
||||
Label again = c->newLabel();
|
||||
c->mov(qw0->r32(), SPU_OFF_32(gpr, op.rt, &v128::_u32, 3));
|
||||
c->mov(addr->r64(), SPU_OFF_64(ch_out_mbox));
|
||||
c->align(kAlignCode, 16);
|
||||
c->bind(again);
|
||||
c->mov(qw0->r32(), qw0->r32());
|
||||
c->bt(addr->r64(), spu_channel::off_count);
|
||||
c->jc(wait);
|
||||
|
||||
after.emplace_back([=, pos = m_pos]
|
||||
{
|
||||
// Do not continue after waiting
|
||||
c->bind(wait);
|
||||
c->mov(SPU_OFF_32(pc), pos);
|
||||
c->mov(*ls, op.ra);
|
||||
c->jmp(imm_ptr<void(*)(SPUThread*, u32, u32)>(gate));
|
||||
});
|
||||
|
||||
c->bts(*qw0, spu_channel::off_count);
|
||||
c->lock().cmpxchg(SPU_OFF_64(ch_out_mbox), *qw0);
|
||||
c->jnz(again);
|
||||
return;
|
||||
}
|
||||
case MFC_WrTagMask:
|
||||
{
|
||||
Label upd = c->newLabel();
|
||||
Label ret = c->newLabel();
|
||||
c->mov(qw0->r32(), SPU_OFF_32(gpr, op.rt, &v128::_u32, 3));
|
||||
c->mov(SPU_OFF_32(ch_tag_mask), qw0->r32());
|
||||
c->cmp(SPU_OFF_32(ch_tag_upd), 0);
|
||||
c->jnz(upd);
|
||||
|
||||
after.emplace_back([=, pos = m_pos]
|
||||
{
|
||||
auto sub = [](SPUThread* _spu, spu_function_t _ret, u32 value)
|
||||
{
|
||||
if (!_spu->set_ch_value(MFC_WrTagMask, value))
|
||||
{
|
||||
fmt::raw_error("spu_recompiler::WRCH(): unexpected SPUThread::set_ch_value(MFC_WrTagMask) call");
|
||||
}
|
||||
|
||||
// Continue
|
||||
_ret(*_spu, _spu->_ptr<u8>(0), nullptr);
|
||||
};
|
||||
|
||||
c->bind(upd);
|
||||
c->mov(SPU_OFF_32(pc), pos);
|
||||
c->lea(*ls, x86::qword_ptr(ret));
|
||||
c->jmp(imm_ptr<void(*)(SPUThread*, spu_function_t, u32)>(sub));
|
||||
});
|
||||
|
||||
c->bind(ret);
|
||||
return;
|
||||
}
|
||||
case MFC_WrTagUpdate:
|
||||
{
|
||||
Label fail = c->newLabel();
|
||||
Label zero = c->newLabel();
|
||||
Label ret = c->newLabel();
|
||||
c->mov(qw0->r32(), SPU_OFF_32(gpr, op.rt, &v128::_u32, 3));
|
||||
c->cmp(qw0->r32(), 2);
|
||||
c->ja(fail);
|
||||
|
||||
after.emplace_back([=, pos = m_pos]
|
||||
{
|
||||
c->bind(fail);
|
||||
c->mov(SPU_OFF_32(pc), pos);
|
||||
c->mov(*ls, op.ra);
|
||||
c->jmp(imm_ptr<void(*)(SPUThread*, u32, u32)>(gate));
|
||||
|
||||
c->bind(zero);
|
||||
c->mov(SPU_OFF_32(ch_tag_upd), qw0->r32());
|
||||
c->mov(SPU_OFF_64(ch_tag_stat), 0);
|
||||
c->jmp(ret);
|
||||
});
|
||||
|
||||
// addr = completed mask, will be compared with qw1
|
||||
c->mov(*addr, SPU_OFF_32(mfc_fence));
|
||||
c->not_(*addr);
|
||||
c->and_(*addr, SPU_OFF_32(ch_tag_mask));
|
||||
c->mov(qw1->r32(), *addr);
|
||||
c->test(*addr, *addr);
|
||||
c->cmovz(qw1->r32(), qw0->r32());
|
||||
c->cmp(qw0->r32(), 1);
|
||||
c->cmovb(qw1->r32(), *addr);
|
||||
c->cmova(qw1->r32(), SPU_OFF_32(ch_tag_mask));
|
||||
c->cmp(*addr, qw1->r32());
|
||||
c->jne(zero);
|
||||
c->bts(addr->r64(), spu_channel::off_count);
|
||||
c->mov(SPU_OFF_32(ch_tag_upd), 0);
|
||||
c->mov(SPU_OFF_64(ch_tag_stat), addr->r64());
|
||||
c->bind(ret);
|
||||
return;
|
||||
}
|
||||
case MFC_LSA:
|
||||
{
|
||||
c->mov(*addr, SPU_OFF_32(gpr, op.rt, &v128::_u32, 3));
|
||||
@ -2272,15 +2405,117 @@ void spu_recompiler::WRCH(spu_opcode_t op)
|
||||
case MFC_Size:
|
||||
{
|
||||
c->mov(*addr, SPU_OFF_32(gpr, op.rt, &v128::_u32, 3));
|
||||
c->and_(*addr, 0x7fff);
|
||||
c->mov(SPU_OFF_16(ch_mfc_cmd, &spu_mfc_cmd::size), addr->r16());
|
||||
return;
|
||||
}
|
||||
case MFC_TagID:
|
||||
{
|
||||
c->mov(*addr, SPU_OFF_32(gpr, op.rt, &v128::_u32, 3));
|
||||
c->and_(*addr, 0x1f);
|
||||
c->mov(SPU_OFF_8(ch_mfc_cmd, &spu_mfc_cmd::tag), addr->r8());
|
||||
return;
|
||||
}
|
||||
case MFC_Cmd:
|
||||
{
|
||||
// TODO
|
||||
auto sub = [](SPUThread* _spu, spu_function_t _ret)
|
||||
{
|
||||
if (!_spu->process_mfc_cmd(_spu->ch_mfc_cmd))
|
||||
{
|
||||
throw cpu_flag::ret;
|
||||
}
|
||||
|
||||
_ret(*_spu, _spu->_ptr<u8>(0), nullptr);
|
||||
};
|
||||
|
||||
Label ret = c->newLabel();
|
||||
c->mov(*addr, SPU_OFF_32(gpr, op.rt, &v128::_u32, 3));
|
||||
c->mov(SPU_OFF_8(ch_mfc_cmd, &spu_mfc_cmd::cmd), addr->r8());
|
||||
c->mov(SPU_OFF_32(pc), m_pos);
|
||||
c->lea(*ls, x86::qword_ptr(ret));
|
||||
c->jmp(imm_ptr<void(*)(SPUThread*, spu_function_t)>(sub));
|
||||
c->align(kAlignCode, 16);
|
||||
c->bind(ret);
|
||||
return;
|
||||
}
|
||||
case MFC_WrListStallAck:
|
||||
{
|
||||
auto sub = [](SPUThread* _spu, spu_function_t _ret)
|
||||
{
|
||||
_spu->do_mfc(true);
|
||||
_ret(*_spu, _spu->_ptr<u8>(0), nullptr);
|
||||
};
|
||||
|
||||
Label ret = c->newLabel();
|
||||
c->mov(qw0->r32(), SPU_OFF_32(gpr, op.rt, &v128::_u32, 3));
|
||||
c->and_(qw0->r32(), 0x1f);
|
||||
c->btr(SPU_OFF_32(ch_stall_mask), qw0->r32());
|
||||
c->jnc(ret);
|
||||
c->lea(*ls, x86::qword_ptr(ret));
|
||||
c->jmp(imm_ptr<void(*)(SPUThread*, spu_function_t)>(sub));
|
||||
c->align(kAlignCode, 16);
|
||||
c->bind(ret);
|
||||
return;
|
||||
}
|
||||
case SPU_WrDec:
|
||||
{
|
||||
auto sub = [](SPUThread* _spu, spu_function_t _ret)
|
||||
{
|
||||
_spu->ch_dec_start_timestamp = get_timebased_time();
|
||||
_ret(*_spu, _spu->_ptr<u8>(0), nullptr);
|
||||
};
|
||||
|
||||
Label ret = c->newLabel();
|
||||
c->lea(*ls, x86::qword_ptr(ret));
|
||||
c->jmp(imm_ptr<void(*)(SPUThread*, spu_function_t)>(sub));
|
||||
c->align(kAlignCode, 16);
|
||||
c->bind(ret);
|
||||
c->mov(qw0->r32(), SPU_OFF_32(gpr, op.rt, &v128::_u32, 3));
|
||||
c->mov(SPU_OFF_32(ch_dec_value), qw0->r32());
|
||||
return;
|
||||
}
|
||||
case SPU_WrEventMask:
|
||||
{
|
||||
Label fail = c->newLabel();
|
||||
c->mov(qw0->r32(), SPU_OFF_32(gpr, op.rt, &v128::_u32, 3));
|
||||
c->mov(*addr, ~SPU_EVENT_IMPLEMENTED);
|
||||
c->mov(qw1->r32(), ~SPU_EVENT_INTR_IMPLEMENTED);
|
||||
c->bt(SPU_OFF_8(interrupts_enabled), 0);
|
||||
c->cmovc(*addr, qw1->r32());
|
||||
c->test(qw0->r32(), *addr);
|
||||
c->jnz(fail);
|
||||
|
||||
after.emplace_back([=, pos = m_pos]
|
||||
{
|
||||
c->bind(fail);
|
||||
c->mov(SPU_OFF_32(pc), pos);
|
||||
c->mov(*ls, op.ra);
|
||||
c->jmp(imm_ptr<void(*)(SPUThread*, u32, u32)>(gate));
|
||||
});
|
||||
|
||||
c->mov(SPU_OFF_32(ch_event_mask), qw0->r32());
|
||||
return;
|
||||
}
|
||||
case SPU_WrEventAck:
|
||||
{
|
||||
Label fail = c->newLabel();
|
||||
c->mov(qw0->r32(), SPU_OFF_32(gpr, op.rt, &v128::_u32, 3));
|
||||
c->test(qw0->r32(), ~SPU_EVENT_IMPLEMENTED);
|
||||
c->jnz(fail);
|
||||
|
||||
after.emplace_back([=, pos = m_pos]
|
||||
{
|
||||
c->bind(fail);
|
||||
c->mov(SPU_OFF_32(pc), pos);
|
||||
c->mov(*ls, op.ra);
|
||||
c->jmp(imm_ptr<void(*)(SPUThread*, u32, u32)>(gate));
|
||||
});
|
||||
|
||||
c->not_(qw0->r32());
|
||||
c->lock().and_(SPU_OFF_32(ch_event_stat), qw0->r32());
|
||||
return;
|
||||
}
|
||||
case 69:
|
||||
{
|
||||
return;
|
||||
@ -2290,7 +2525,7 @@ void spu_recompiler::WRCH(spu_opcode_t op)
|
||||
c->mov(SPU_OFF_32(pc), m_pos);
|
||||
c->mov(*ls, op.ra);
|
||||
c->mov(qw0->r32(), SPU_OFF_32(gpr, op.rt, &v128::_u32, 3));
|
||||
c->jmp(asmjit::imm_ptr<void(*)(SPUThread*, u32, u32)>(gate));
|
||||
c->jmp(imm_ptr<void(*)(SPUThread*, u32, u32)>(gate));
|
||||
m_pos = -1;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user