mirror of
https://github.com/simple64/simple64.git
synced 2026-09-03 02:44:31 +02:00
update parallel rsp
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user