Hook up COP2 vector ops.

This commit is contained in:
Hans-Kristian Arntzen 2020-01-31 23:45:46 +01:00
parent b39d147496
commit fd50bf22e8
3 changed files with 77 additions and 10 deletions

View File

@ -153,4 +153,5 @@ if (PARALLEL_RSP_TESTS)
rsp_add_test(cop0)
rsp_add_test(cop2-basic)
rsp_add_test(cop2-ls)
rsp_add_test(cop2-vector)
endif()

View File

@ -0,0 +1,18 @@
.data
buffer:
.hword 10, 20, 30, 40, 50, 60, 70, 80
.hword 20, 30, 40, 50, 60, 70, 80, 90
.text
.set noreorder
.global main
main:
la $t0, buffer
# lqv 2, 0, 0(t0)
.word (0x32 << 26) | (4 << 11) | (2 << 16) | (0 << 7) | (0 << 0) | (8 << 21)
# lqv 3, 0, 1(t0)
.word (0x32 << 26) | (4 << 11) | (3 << 16) | (0 << 7) | (1 << 0) | (8 << 21)
.word (0x25 << 25) | (4 << 6) | (2 << 11) | (3 << 16) | (17 << 0) | (0 << 21)
# vsub v4, v2, v3, 0
break

View File

@ -727,6 +727,60 @@ void CPU::jit_instruction(jit_state_t *_jit, uint32_t pc, uint32_t instr,
// VU
if ((instr >> 25) == 0x25)
{
// VU instruction. COP2, and high bit of opcode is set.
uint32_t op = instr & 63;
uint32_t vd = (instr >> 6) & 31;
uint32_t vs = (instr >> 11) & 31;
uint32_t vt = (instr >> 16) & 31;
uint32_t e = (instr >> 21) & 15;
static const char *ops_str[64] = {
"VMULF", "VMULU", nullptr, nullptr, "VMUDL", "VMUDM", "VMUDN", "VMUDH", "VMACF", "VMACU", nullptr,
nullptr, "VMADL", "VMADM", "VMADN", "VMADH", "VADD", "VSUB", nullptr, "VABS", "VADDC", "VSUBC",
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, "VSAR", nullptr, nullptr, "VLT",
"VEQ", "VNE", "VGE", "VCL", "VCH", "VCR", "VMRG", "VAND", "VNAND", "VOR", "VNOR",
"VXOR", "VNXOR", nullptr, nullptr, "VRCP", "VRCPL", "VRCPH", "VMOV", "VRSQ", "VRSQL", "VRSQH",
"VNOP",
};
using VUOp = void (*)(RSP::CPUState *, unsigned vd, unsigned vs, unsigned vt, unsigned e);
static const VUOp ops[64] = {
RSP_VMULF, RSP_VMULU, nullptr, nullptr, RSP_VMUDL, RSP_VMUDM, RSP_VMUDN, RSP_VMUDH, RSP_VMACF, RSP_VMACU, nullptr,
nullptr, RSP_VMADL, RSP_VMADM, RSP_VMADN, RSP_VMADH, RSP_VADD, RSP_VSUB, nullptr, RSP_VABS, RSP_VADDC, RSP_VSUBC,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, RSP_VSAR, nullptr, nullptr, RSP_VLT,
RSP_VEQ, RSP_VNE, RSP_VGE, RSP_VCL, RSP_VCH, RSP_VCR, RSP_VMRG, RSP_VAND, RSP_VNAND, RSP_VOR, RSP_VNOR,
RSP_VXOR, RSP_VNXOR, nullptr, nullptr, RSP_VRCP, RSP_VRCPL, RSP_VRCPH, RSP_VMOV, RSP_VRSQ, RSP_VRSQL, RSP_VRSQH,
RSP_VNOP,
};
const char *op_str = ops_str[op];
VUOp vuop;
if (op_str)
{
DISASM("%s v%u, v%u, v%u[%u]\n", op_str, vd, vs, vt, e);
vuop = ops[op];
}
else
{
DISASM("cop2 %u reserved\n", op);
vuop = RSP_RESERVED;
}
if (last_info.conditional)
jit_save_cond_branch_taken(_jit);
jit_prepare();
jit_pushargr(JIT_REGISTER_STATE);
jit_pushargi(vd);
jit_pushargi(vs);
jit_pushargi(vt);
jit_pushargi(e);
jit_finishi(reinterpret_cast<jit_pointer_t>(vuop));
if (last_info.conditional)
jit_restore_cond_branch_taken(_jit);
return;
}
@ -1394,15 +1448,12 @@ void CPU::jit_instruction(jit_state_t *_jit, uint32_t pc, uint32_t instr,
unsigned imm = (instr >> 7) & 15;
static const char *lwc2_ops[32] = {
"LBV", "LSV", "LLV", "LDV", "LQV", "LRV", "LPV", "LUV", "LHV", nullptr, nullptr,
"LTV", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
"LBV", "LSV", "LLV", "LDV", "LQV", "LRV", "LPV", "LUV", "LHV", nullptr, nullptr, "LTV",
};
using LWC2Op = void (*)(RSP::CPUState *, unsigned rt, unsigned imm, int simm, unsigned rs);
static const LWC2Op ops[32] = {
RSP_LBV, RSP_LSV, RSP_LLV, RSP_LDV, RSP_LQV, RSP_LRV, RSP_LPV, RSP_LUV, RSP_LHV, nullptr, nullptr,
RSP_LTV,
RSP_LBV, RSP_LSV, RSP_LLV, RSP_LDV, RSP_LQV, RSP_LRV, RSP_LPV, RSP_LUV, RSP_LHV, nullptr, nullptr, RSP_LTV,
};
const char *op = lwc2_ops[rd];
@ -1439,15 +1490,12 @@ void CPU::jit_instruction(jit_state_t *_jit, uint32_t pc, uint32_t instr,
unsigned imm = (instr >> 7) & 15;
static const char *swc2_ops[32] = {
"SBV", "SSV", "SLV", "SDV", "SQV", "SRV", "SPV", "SUV", "SHV", "SFV", nullptr,
"STV", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
"SBV", "SSV", "SLV", "SDV", "SQV", "SRV", "SPV", "SUV", "SHV", "SFV", nullptr, "STV",
};
using SWC2Op = void (*)(RSP::CPUState *, unsigned rt, unsigned imm, int simm, unsigned rs);
static const SWC2Op ops[32] = {
RSP_SBV, RSP_SSV, RSP_SLV, RSP_SDV, RSP_SQV, RSP_SRV, RSP_SPV, RSP_SUV, RSP_SHV, RSP_SFV, nullptr,
RSP_STV,
RSP_SBV, RSP_SSV, RSP_SLV, RSP_SDV, RSP_SQV, RSP_SRV, RSP_SPV, RSP_SUV, RSP_SHV, RSP_SFV, nullptr, RSP_STV,
};
const char *op = swc2_ops[rd];