update parallel rsp

This commit is contained in:
Logan McNaughton
2024-03-22 11:41:49 -06:00
parent 99e37c54f7
commit bd5f4f35cc
9 changed files with 123 additions and 66 deletions
-1
View File
@@ -41,7 +41,6 @@ add_library(${NAME_PLUGIN_SIMPLE64} SHARED
arch/simd/rsp/vcmp.h
arch/simd/rsp/vdivh.h
arch/simd/rsp/vmac.h
arch/simd/rsp/vmov.h
arch/simd/rsp/vmrg.h
arch/simd/rsp/vmudh.h
arch/simd/rsp/vmul.h
+3 -3
View File
@@ -1,11 +1,11 @@
Written by Themaister.
The code is heavily reliant on MarathonMan's CEN64 RSP implementation, as well as CXD4's RSP implementation.
The code is heavily reliant on MarathonMan's CEN64 RSP implementation, as well as Ares and CXD4's RSP implementations.
MIPS core: Rewritten from scratch
CP0: Near copy-pasta from CEN64
CP0: Near copy-pasta from CEN64, with some fixes from Ares brought in
CP2: Near copy-pasta from CEN64
LS pipe: Near copy-pasta from CXD4
LS pipe: Ported from Ares
Mupen64plus glue code: Reused most of CXD4.
Lightning jitter interface: Written from scratch
-1
View File
@@ -12,7 +12,6 @@
#include "vcr.h"
#include "vdivh.h"
#include "vmac.h"
#include "vmov.h"
#include "vmrg.h"
#include "vmul.h"
#include "vmulh.h"
-18
View File
@@ -1,18 +0,0 @@
//
// arch/x86_64/rsp/vmov.c
//
// This file is subject to the terms and conditions defined in
// 'LICENSE', which is part of this source code package.
//
inline __m128i rsp_vmov(RSP::CPUState *rsp, unsigned src, unsigned e, unsigned dest, unsigned de)
{
uint16_t data;
// Get the element from VT.
data = rsp->cp2.regs[src].e[e & 0x7];
// Write out the upper part of the result.
rsp->cp2.regs[dest].e[de & 0x7] = data;
return rsp_vect_load_unshuffled_operand(rsp->cp2.regs[dest].e);
}
+6 -4
View File
@@ -26,9 +26,9 @@ extern "C"
rsp->sr[rt] = res;
#ifdef PARALLEL_INTEGRATION
if (rd == CP0_REGISTER_SP_RESERVED)
if (rd == CP0_REGISTER_SP_SEMAPHORE)
{
*rsp->cp0.cr[CP0_REGISTER_SP_RESERVED] = 1;
*rsp->cp0.cr[CP0_REGISTER_SP_SEMAPHORE] = 1;
return MODE_EXIT;
}
// We don't return control to the CPU if the RDP FREEZE bit is set, doing so seems to cause flickering
@@ -207,6 +207,7 @@ extern "C"
*rsp->cp0.cr[CP0_REGISTER_DMA_DRAM] = source;
*rsp->cp0.cr[CP0_REGISTER_DMA_CACHE] = dest;
*rsp->cp0.cr[CP0_REGISTER_DMA_READ_LENGTH] = 0xff8;
#ifdef INTENSE_DEBUG
log_rsp_mem_parallel();
@@ -255,6 +256,7 @@ extern "C"
*rsp->cp0.cr[CP0_REGISTER_DMA_CACHE] = source;
*rsp->cp0.cr[CP0_REGISTER_DMA_DRAM] = dest;
*rsp->cp0.cr[CP0_REGISTER_DMA_WRITE_LENGTH] = 0xff8;
#ifdef INTENSE_DEBUG
log_rsp_mem_parallel();
#endif
@@ -293,8 +295,8 @@ extern "C"
case CP0_REGISTER_SP_STATUS:
return rsp_status_write(rsp, val);
case CP0_REGISTER_SP_RESERVED:
*rsp->cp0.cr[CP0_REGISTER_SP_RESERVED] = 0;
case CP0_REGISTER_SP_SEMAPHORE:
*rsp->cp0.cr[CP0_REGISTER_SP_SEMAPHORE] = 0;
break;
case CP0_REGISTER_CMD_START:
+103 -11
View File
@@ -25,6 +25,13 @@
extern "C"
{
static inline int32_t clamp16s(int32_t x)
{
if (x > 0x7fff) return 0x7fff;
if (x < -0x8000) return -0x8000;
return x;
}
//
// VABS
//
@@ -297,6 +304,25 @@ extern "C"
STORE_RESULT();
}
void RSP_VMACQ(RSP::CPUState *rsp, unsigned vd, unsigned, unsigned, unsigned)
{
TRACE_VU(VMACQ);
uint16_t *acc = rsp->cp2.acc.e;
for (unsigned i = 0; i < 8; i++)
{
int32_t prod = (int16_t)acc[i] << 16;
prod |= acc[8+i];
if (prod < 0 && !(prod & 1 << 5))
prod += 32;
else if (prod >= 32 && !(prod & 1 << 5))
prod -= 32;
acc[i] = prod >> 16;
acc[8+i] = prod & 0xffffu;
rsp->cp2.regs[vd].e[i] = clamp16s(prod >> 1) & ~15;
}
}
//
// VMADH
// VMUDH
@@ -464,10 +490,9 @@ extern "C"
{
TRACE_VU(VMOV);
uint16_t *acc = rsp->cp2.acc.e;
unsigned de = vs & 0x7;
write_acc_lo(acc, LOAD_VT());
__m128i result = rsp_vmov(rsp, vt, e, vd, de);
STORE_RESULT();
vs &= 0x7;
rsp->cp2.regs[vd].e[vs] = rsp->cp2.acc.e[16+vs];
}
//
@@ -489,6 +514,7 @@ extern "C"
//
// VMULF
// VMULQ
// VMULU
//
void RSP_VMULF(RSP::CPUState *rsp, unsigned vd, unsigned vs, unsigned vt, unsigned e)
@@ -505,6 +531,28 @@ extern "C"
STORE_RESULT();
}
void RSP_VMULQ(RSP::CPUState *rsp, unsigned vd, unsigned vs, unsigned vt, unsigned e)
{
TRACE_VU(VMULQ);
uint16_t *acc = rsp->cp2.acc.e;
uint16_t *vde = rsp->cp2.regs[vd].e;
int16_t *vse = (int16_t*)rsp->cp2.regs[vs].e;
int16_t vte[8];
rsp_vect_t vtt = LOAD_VT();
rsp_vect_write_operand((uint16_t*)vte, vtt);
for (unsigned i = 0; i < 8; i++)
{
int32_t prod = vse[i] * vte[i];
if (prod < 0) prod += 31;
acc[i] = prod >> 16;
acc[8+i] = prod & 0xffff;
acc[16+i] = 0;
vde[i] = clamp16s(prod >> 1) & ~15;
}
}
void RSP_VMULU(RSP::CPUState *rsp, unsigned vd, unsigned vs, unsigned vt, unsigned e)
{
TRACE_VU(VMULU);
@@ -519,6 +567,52 @@ extern "C"
STORE_RESULT();
}
//
// VRNDP
// VRNDN
//
static inline void RSP_VRND(RSP::CPUState *rsp, unsigned vd, unsigned vs, unsigned vt, unsigned e, uint_fast8_t variant)
{
int16_t vte[8];
rsp_vect_t vtt = LOAD_VT();
rsp_vect_write_operand((uint16_t*)vte, vtt);
uint16_t *acc = rsp->cp2.acc.e;
uint16_t *vde = rsp->cp2.regs[vd].e;
for (unsigned i = 0; i < 8; i++)
{
int64_t acc48 =
((int64_t)(int16_t)acc[i] << 32) |
((int64_t)acc[8+i] << 16) |
(int64_t)acc[16+i];
const uint_fast8_t negative_acc = acc48 < 0;
if (!!variant xor !!negative_acc)
{
int64_t value = (int64_t)(int16_t)vte[i];
if (vs & 1) value <<= 16;
acc48 += value;
}
acc[i] = (acc48 >> 32) & 0xffff;
acc[8+i] = (acc48 >> 16) & 0xffff;
acc[16+i] = acc48 & 0xffff;
vde[i] = clamp16s((int32_t)(acc48 >> 16));
}
}
void RSP_VRNDN(RSP::CPUState *rsp, unsigned vd, unsigned vs, unsigned vt, unsigned e)
{
TRACE_VU(RSP_VRNDN);
RSP_VRND(rsp, vd, vs, vt, e, 0);
}
void RSP_VRNDP(RSP::CPUState *rsp, unsigned vd, unsigned vs, unsigned vt, unsigned e)
{
TRACE_VU(RSP_VRNDP);
RSP_VRND(rsp, vd, vs, vt, e, 1);
}
//
// VNOP
//
@@ -563,7 +657,6 @@ extern "C"
TRACE_VU(VRCP);
uint16_t *acc = rsp->cp2.acc.e;
unsigned de = vs & 0x7;
e &= 0x7;
write_acc_lo(acc, LOAD_VT());
@@ -577,7 +670,6 @@ extern "C"
TRACE_VU(VRCPL);
uint16_t *acc = rsp->cp2.acc.e;
unsigned de = vs & 0x7;
e &= 0x7;
write_acc_lo(acc, LOAD_VT());
@@ -593,7 +685,6 @@ extern "C"
TRACE_VU(VRSQ);
uint16_t *acc = rsp->cp2.acc.e;
unsigned de = vs & 0x7;
e &= 0x7;
write_acc_lo(acc, LOAD_VT());
@@ -607,7 +698,6 @@ extern "C"
TRACE_VU(VRSQL);
uint16_t *acc = rsp->cp2.acc.e;
unsigned de = vs & 0x7;
e &= 0x7;
write_acc_lo(acc, LOAD_VT());
@@ -627,7 +717,6 @@ extern "C"
TRACE_VU(VRCPH);
uint16_t *acc = rsp->cp2.acc.e;
unsigned de = vs & 0x7;
e &= 0x7;
write_acc_lo(acc, LOAD_VT());
@@ -643,7 +732,6 @@ extern "C"
TRACE_VU(VRSQH);
uint16_t *acc = rsp->cp2.acc.e;
unsigned de = vs & 0x7;
e &= 0x7;
write_acc_lo(acc, LOAD_VT());
@@ -745,9 +833,13 @@ extern "C"
}
// RESERVED
void RSP_RESERVED(RSP::CPUState *rsp, unsigned vd, unsigned, unsigned, unsigned)
void RSP_RESERVED(RSP::CPUState *rsp, unsigned vd, unsigned vs, unsigned vt, unsigned e)
{
rsp_vect_t result = rsp_vzero();
uint16_t *acc = rsp->cp2.acc.e;
rsp_vect_t result = _mm_add_epi16(LOAD_VS(), LOAD_VT());
write_acc_lo(acc, result);
result = rsp_vzero();
STORE_RESULT();
}
}
+7 -27
View File
@@ -269,19 +269,6 @@ extern "C"
(dram[off1] << 0)));
}
static jit_word_t rsp_unaligned_lwu(const uint8_t *dram, jit_word_t addr)
{
auto off0 = BYTE_ENDIAN_FIXUP(addr, 0);
auto off1 = BYTE_ENDIAN_FIXUP(addr, 1);
auto off2 = BYTE_ENDIAN_FIXUP(addr, 2);
auto off3 = BYTE_ENDIAN_FIXUP(addr, 3);
return jit_word_t((uint32_t(dram[off0]) << 24) |
(uint32_t(dram[off1]) << 16) |
(uint32_t(dram[off2]) << 8) |
(uint32_t(dram[off3]) << 0));
}
static void rsp_unaligned_sh(uint8_t *dram, jit_word_t addr, jit_word_t data)
{
auto off0 = BYTE_ENDIAN_FIXUP(addr, 0);
@@ -911,12 +898,12 @@ void CPU::jit_instruction(jit_state_t *_jit, uint32_t pc, uint32_t instr,
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,
RSP_VMULF, RSP_VMULU, RSP_VRNDP, RSP_VMULQ, RSP_VMUDL, RSP_VMUDM, RSP_VMUDN, RSP_VMUDH, RSP_VMACF, RSP_VMACU, RSP_VRNDN,
RSP_VMACQ, 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,
RSP_VNOP, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, RSP_VNOP
};
auto *vuop = ops[op];
@@ -1034,6 +1021,7 @@ void CPU::jit_instruction(jit_state_t *_jit, uint32_t pc, uint32_t instr,
case 007: // SRAV
{
NOP_IF_RD_ZERO();
unsigned rt_reg = regs.load_mips_register_sext(_jit, rt);
unsigned rs_reg = regs.load_mips_register_noext(_jit, rs);
unsigned rs_tmp_reg = regs.modify_mips_register(_jit, RegisterCache::SCRATCH_REGISTER0);
@@ -1434,7 +1422,8 @@ void CPU::jit_instruction(jit_state_t *_jit, uint32_t pc, uint32_t instr,
case 013: // SLTIU
{
TWO_REG_IMM_OP(lti_u, uint16_t, zext);
// SLTIU sign extends the immediate to 32 bit but then does an unsigned comparison
TWO_REG_IMM_OP(lti_u, int16_t, sext);
break;
}
@@ -1613,6 +1602,7 @@ void CPU::jit_instruction(jit_state_t *_jit, uint32_t pc, uint32_t instr,
}
case 043: // LW
case 047: // LWU
{
jit_emit_load_operation(_jit, pc, instr,
[](jit_state_t *_jit, unsigned a, unsigned b, unsigned c) { jit_ldxr_i(a, b, c); },
@@ -1642,16 +1632,6 @@ void CPU::jit_instruction(jit_state_t *_jit, uint32_t pc, uint32_t instr,
break;
}
case 047: // LWU
{
jit_emit_load_operation(_jit, pc, instr,
[](jit_state_t *_jit, unsigned a, unsigned b, unsigned c) { jit_ldxr_ui(a, b, c); },
"lwu",
reinterpret_cast<jit_pointer_t>(rsp_unaligned_lwu),
0, last_info);
break;
}
case 050: // SB
{
jit_emit_store_operation(_jit, pc, instr,
+3
View File
@@ -49,12 +49,15 @@ extern "C"
#define DECL_COP2(op) void RSP_##op(RSP::CPUState *rsp, unsigned vd, unsigned vs, unsigned vt, unsigned e)
DECL_COP2(VMULF);
DECL_COP2(VMULU);
DECL_COP2(VRNDP);
DECL_COP2(VMULQ);
DECL_COP2(VMUDL);
DECL_COP2(VMUDM);
DECL_COP2(VMUDN);
DECL_COP2(VMUDH);
DECL_COP2(VMACF);
DECL_COP2(VMACU);
DECL_COP2(VRNDN);
DECL_COP2(VMACQ);
DECL_COP2(VMADL);
DECL_COP2(VMADM);
+1 -1
View File
@@ -37,7 +37,7 @@ enum CP0Registers
CP0_REGISTER_SP_STATUS = 4,
CP0_REGISTER_DMA_FULL = 5,
CP0_REGISTER_DMA_BUSY = 6,
CP0_REGISTER_SP_RESERVED = 7,
CP0_REGISTER_SP_SEMAPHORE = 7,
CP0_REGISTER_CMD_START = 8,
CP0_REGISTER_CMD_END = 9,
CP0_REGISTER_CMD_CURRENT = 10,