mirror of https://github.com/PCSX2/pcsx2.git
Delete sVU macro mode code (was obsolete and got broken somewhere along the way...)
Some more vu changes (no functional changes yet) git-svn-id: http://pcsx2.googlecode.com/svn/trunk@2631 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
f86876f9fe
commit
3afa45d34b
|
@ -550,7 +550,6 @@ TraceLogFilters& SetTraceConfig();
|
|||
|
||||
// ------------ CPU / Recompiler Options ---------------
|
||||
|
||||
#define CHECK_MACROVU0 // If defined uses mVU for VU Macro (COP2), else uses sVU
|
||||
#define CHECK_MICROVU0 (EmuConfig.Cpu.Recompiler.UseMicroVU0)
|
||||
#define CHECK_MICROVU1 (EmuConfig.Cpu.Recompiler.UseMicroVU1)
|
||||
#define CHECK_EEREC (EmuConfig.Cpu.Recompiler.EnableEE && GetSysCoreAlloc().IsRecAvailable_EE())
|
||||
|
|
|
@ -422,20 +422,9 @@ __forceinline void _cpuBranchTest_Shared()
|
|||
}
|
||||
|
||||
// ---- VU0 -------------
|
||||
|
||||
if (VU0.VI[REG_VPU_STAT].UL & 0x1)
|
||||
{
|
||||
// We're in a BranchTest. All dynarec registers are flushed
|
||||
// so there is no need to freeze registers here.
|
||||
CpuVU0->ExecuteBlock(vu0RunCycles);
|
||||
DevCon.Warning("VU0 running when in BranchTest");
|
||||
// This might be needed to keep the EE and VU0 in sync.
|
||||
// A better fix will require hefty changes to the VU recs. -_-
|
||||
// Fixme:
|
||||
// Check Silver Surfer. Currently has SPS varying with different branch deltas set below.
|
||||
if(VU0.VI[REG_VPU_STAT].UL & 0x1)
|
||||
cpuSetNextBranchDelta( 768 );
|
||||
}
|
||||
CpuVU0->ExecuteBlock();
|
||||
|
||||
// Note: We don't update the VU1 here because it runs it's micro-programs in
|
||||
// one shot always. That is, when a program is executed the VU1 doesn't even
|
||||
|
|
|
@ -65,15 +65,11 @@ __forceinline void _vu0run(bool breakOnMbit, bool addCycles) {
|
|||
if (!(VU0.VI[REG_VPU_STAT].UL & 1)) return;
|
||||
|
||||
int startcycle = VU0.cycle;
|
||||
u32 runCycles = breakOnMbit ? vu0RunCycles : 0x7fffffff;
|
||||
VU0.flags &= ~VUFLAG_MFLAGSET;
|
||||
|
||||
do {
|
||||
// knockout kings 2002 loops here with sVU
|
||||
if (breakOnMbit && (VU0.cycle-startcycle > 0x1000)) {
|
||||
Console.Warning("VU0 stuck in infinite loop? Breaking execution!");
|
||||
break; // Do games still need this?
|
||||
}
|
||||
CpuVU0->ExecuteBlock(vu0RunCycles);
|
||||
do { // Run VU until it finishes or M-Bit
|
||||
CpuVU0->Execute(runCycles);
|
||||
} while ((VU0.VI[REG_VPU_STAT].UL & 1) // E-bit Termination
|
||||
&& (!breakOnMbit || !(VU0.flags & VUFLAG_MFLAGSET))); // M-bit Break
|
||||
|
||||
|
|
|
@ -56,12 +56,7 @@ void __fastcall vu0ExecMicro(u32 addr) {
|
|||
|
||||
if ((s32)addr != -1) VU0.VI[REG_TPC].UL = addr;
|
||||
_vuExecMicroDebug(VU0);
|
||||
CpuVU0->ExecuteBlock(vu0RunCycles);
|
||||
|
||||
// If the VU0 program didn't finish then we'll want to finish it up
|
||||
// pretty soon. This fixes vmhacks in some games (Naruto Ultimate Ninja 2)
|
||||
if(VU0.VI[REG_VPU_STAT].UL & 0x1)
|
||||
cpuSetNextBranchDelta( 192 ); // fixme : ideally this should be higher, like 512 or so.
|
||||
CpuVU0->ExecuteBlock(1);
|
||||
}
|
||||
|
||||
void VU0unknown() {
|
||||
|
|
|
@ -195,6 +195,7 @@ void vu0Exec(VURegs* VU)
|
|||
// --------------------------------------------------------------------------------------
|
||||
InterpVU0::InterpVU0()
|
||||
{
|
||||
m_Idx = 0;
|
||||
IsInterpreter = true;
|
||||
}
|
||||
|
||||
|
@ -203,7 +204,7 @@ void InterpVU0::Step()
|
|||
vu0Exec( &VU0 );
|
||||
}
|
||||
|
||||
void InterpVU0::ExecuteBlock(u32 cycles)
|
||||
void InterpVU0::Execute(u32 cycles)
|
||||
{
|
||||
for (int i = 128; i--;)
|
||||
{
|
||||
|
|
|
@ -46,7 +46,7 @@ void __fastcall vu1ExecMicro(u32 addr)
|
|||
{
|
||||
while(VU0.VI[REG_VPU_STAT].UL & 0x100) {
|
||||
VUM_LOG("vu1ExecMicro > Stalling until current microprogram finishes");
|
||||
CpuVU1->ExecuteBlock(vu1RunCycles);
|
||||
CpuVU1->Execute(vu1RunCycles);
|
||||
}
|
||||
|
||||
VUM_LOG("vu1ExecMicro %x", addr);
|
||||
|
@ -59,7 +59,7 @@ void __fastcall vu1ExecMicro(u32 addr)
|
|||
if ((s32)addr != -1) VU1.VI[REG_TPC].UL = addr;
|
||||
_vuExecMicroDebug(VU1);
|
||||
|
||||
CpuVU1->ExecuteBlock(vu1RunCycles);
|
||||
CpuVU1->Execute(vu1RunCycles);
|
||||
}
|
||||
|
||||
_vuRegsTables(VU1, VU1regs);
|
||||
|
|
|
@ -178,6 +178,7 @@ void vu1Exec(VURegs* VU)
|
|||
|
||||
InterpVU1::InterpVU1()
|
||||
{
|
||||
m_Idx = 1;
|
||||
IsInterpreter = true;
|
||||
}
|
||||
|
||||
|
@ -186,7 +187,7 @@ void InterpVU1::Step()
|
|||
vu1Exec( &VU1 );
|
||||
}
|
||||
|
||||
void InterpVU1::ExecuteBlock(u32 cycles)
|
||||
void InterpVU1::Execute(u32 cycles)
|
||||
{
|
||||
for (int i = 128; i--;)
|
||||
{
|
||||
|
|
116
pcsx2/VUmicro.h
116
pcsx2/VUmicro.h
|
@ -16,6 +16,7 @@
|
|||
#pragma once
|
||||
#include "VU.h"
|
||||
#include "VUops.h"
|
||||
#include "R5900.h"
|
||||
#define vuRunCycles (512*12) // Cycles to run ExecuteBlockJIT() for (called from within recs)
|
||||
#define vu0RunCycles (512*12) // Cycles to run vu0 for whenever ExecuteBlock() is called
|
||||
#define vu1RunCycles (3000000) // mVU1 uses this for inf loop detection on dev builds
|
||||
|
@ -62,9 +63,10 @@ public:
|
|||
virtual void Allocate()=0;
|
||||
virtual void Shutdown()=0;
|
||||
virtual void Reset()=0;
|
||||
virtual void Execute(u32 cycles)=0;
|
||||
virtual void ExecuteBlock(bool startUp)=0;
|
||||
|
||||
virtual void Step()=0;
|
||||
virtual void ExecuteBlock(u32 cycles)=0;
|
||||
virtual void Clear(u32 Addr, u32 Size)=0;
|
||||
|
||||
// C++ Calling Conventions are unstable, and some compilers don't even allow us to take the
|
||||
|
@ -72,7 +74,7 @@ public:
|
|||
// recompiled code.
|
||||
static void __fastcall ExecuteBlockJIT( BaseCpuProvider* cpu )
|
||||
{
|
||||
cpu->ExecuteBlock(vuRunCycles);
|
||||
cpu->Execute(vuRunCycles);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -82,8 +84,15 @@ public:
|
|||
// Layer class for possible future implementation (currently is nothing more than a type-safe
|
||||
// type define).
|
||||
//
|
||||
class BaseVUmicroCPU : public BaseCpuProvider
|
||||
{
|
||||
class BaseVUmicroCPU : public BaseCpuProvider {
|
||||
protected:
|
||||
u32 m_lastEEcycles;
|
||||
int m_Idx;
|
||||
BaseVUmicroCPU() {
|
||||
m_Idx = 0;
|
||||
m_lastEEcycles = 0;
|
||||
}
|
||||
virtual ~BaseVUmicroCPU() throw() {}
|
||||
public:
|
||||
|
||||
// Called by the PS2 VM's event manager for every internal vertical sync (occurs at either
|
||||
|
@ -99,16 +108,63 @@ public:
|
|||
//
|
||||
virtual void Vsync() throw() { }
|
||||
|
||||
virtual void Step()
|
||||
{
|
||||
virtual void Step() {
|
||||
// Ideally this would fall back on interpretation for executing single instructions
|
||||
// for all CPU types, but due to VU complexities and large discrepancies between
|
||||
// clamping in recs and ints, it's not really worth bothering with yet.
|
||||
}
|
||||
|
||||
protected:
|
||||
BaseVUmicroCPU() {}
|
||||
virtual ~BaseVUmicroCPU() throw() {}
|
||||
// Execute VU for the number of VU cycles (recs might go over 0~30 cycles)
|
||||
//virtual void Execute(u32 cycles)=0;
|
||||
|
||||
// Executes a Block based on static preset cycles
|
||||
virtual void ExecuteBlock(bool startUp=0) {
|
||||
const int vuRunning = m_Idx ? 0x100 : 1;
|
||||
if (!(VU0.VI[REG_VPU_STAT].UL & vuRunning)) return;
|
||||
if (startUp) { // Start Executing a microprogram
|
||||
Execute(vu0RunCycles); // Kick start VU
|
||||
// If the VU0 program didn't finish then we'll want to finish it up
|
||||
// pretty soon. This fixes vmhacks in some games (Naruto Ultimate Ninja 2)
|
||||
if(VU0.VI[REG_VPU_STAT].UL & 0x1)
|
||||
cpuSetNextBranchDelta( 192 ); // fixme : ideally this should be higher, like 512 or so.
|
||||
}
|
||||
else {
|
||||
Execute(vu0RunCycles);
|
||||
DevCon.Warning("VU0 running when in BranchTest");
|
||||
// This helps keep the EE and VU0 in sync.
|
||||
// Check Silver Surfer. Currently has SPS varying with different branch deltas set below.
|
||||
if(VU0.VI[REG_VPU_STAT].UL & 0x1)
|
||||
cpuSetNextBranchDelta( 768 );
|
||||
}
|
||||
}
|
||||
|
||||
// Executes a Block based on EE delta time
|
||||
/*virtual void ExecuteBlock(bool startUp=0) {
|
||||
const int vuRunning = m_Idx ? 0x100 : 1;
|
||||
const int c = 1024;
|
||||
if (!(VU0.VI[REG_VPU_STAT].UL & vuRunning)) return;
|
||||
if (startUp) { // Start Executing a microprogram
|
||||
Execute(c); // Kick start VU
|
||||
m_lastEEcycles = cpuRegs.cycle + (c*2);
|
||||
if (VU0.VI[REG_VPU_STAT].UL & vuRunning)
|
||||
cpuSetNextBranchDelta(c*4); // Let VUs run behind EE instead of ahead
|
||||
}
|
||||
else { // Continue Executing (VU roughly half the mhz of EE)
|
||||
s32 delta = (s32)(u32)(cpuRegs.cycle - m_lastEEcycles);
|
||||
if (delta > 0) {
|
||||
delta>>=1;
|
||||
DevCon.WriteLn("Event Test1: Running VU0 for %d cycles", delta);
|
||||
Execute(delta);
|
||||
m_lastEEcycles = cpuRegs.cycle;
|
||||
if (VU0.VI[REG_VPU_STAT].UL & vuRunning)
|
||||
cpuSetNextBranchDelta(c*2); // Let VUs run behind EE instead of in front
|
||||
}
|
||||
else {
|
||||
cpuSetNextBranchDelta(-delta);
|
||||
DevCon.WriteLn("Event Test2: Running VU0 for %d cycles", delta/2);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
};
|
||||
|
||||
|
||||
|
@ -129,7 +185,7 @@ public:
|
|||
void Reset() { }
|
||||
|
||||
void Step();
|
||||
void ExecuteBlock(u32 cycles);
|
||||
void Execute(u32 cycles);
|
||||
void Clear(u32 addr, u32 size) {}
|
||||
};
|
||||
|
||||
|
@ -147,7 +203,7 @@ public:
|
|||
void Reset() { }
|
||||
|
||||
void Step();
|
||||
void ExecuteBlock(u32 cycles);
|
||||
void Execute(u32 cycles);
|
||||
void Clear(u32 addr, u32 size) {}
|
||||
};
|
||||
|
||||
|
@ -167,7 +223,7 @@ public:
|
|||
void Shutdown() throw();
|
||||
|
||||
void Reset();
|
||||
void ExecuteBlock(u32 cycles);
|
||||
void Execute(u32 cycles);
|
||||
void Clear(u32 addr, u32 size);
|
||||
void Vsync() throw();
|
||||
};
|
||||
|
@ -184,11 +240,45 @@ public:
|
|||
void Allocate();
|
||||
void Shutdown() throw();
|
||||
void Reset();
|
||||
void ExecuteBlock(u32 cycles);
|
||||
void Execute(u32 cycles);
|
||||
void Clear(u32 addr, u32 size);
|
||||
void Vsync() throw();
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// recSuperVU0 / recSuperVU1
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
||||
class recSuperVU0 : public BaseVUmicroCPU
|
||||
{
|
||||
public:
|
||||
recSuperVU0();
|
||||
|
||||
const char* GetShortName() const { return "sVU0"; }
|
||||
wxString GetLongName() const { return L"SuperVU0 Recompiler"; }
|
||||
|
||||
void Allocate();
|
||||
void Shutdown() throw();
|
||||
void Reset();
|
||||
void Execute(u32 cycles);
|
||||
void Clear(u32 Addr, u32 Size);
|
||||
};
|
||||
|
||||
class recSuperVU1 : public BaseVUmicroCPU
|
||||
{
|
||||
public:
|
||||
recSuperVU1();
|
||||
|
||||
const char* GetShortName() const { return "sVU1"; }
|
||||
wxString GetLongName() const { return L"SuperVU1 Recompiler"; }
|
||||
|
||||
void Allocate();
|
||||
void Shutdown() throw();
|
||||
void Reset();
|
||||
void Execute(u32 cycles);
|
||||
void Clear(u32 Addr, u32 Size);
|
||||
};
|
||||
|
||||
extern BaseVUmicroCPU* CpuVU0;
|
||||
extern BaseVUmicroCPU* CpuVU1;
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ __forceinline void vif1FLUSH()
|
|||
{
|
||||
int _cycles = VU1.cycle;
|
||||
|
||||
do { CpuVU1->ExecuteBlock(vu1RunCycles); }
|
||||
do { CpuVU1->Execute(vu1RunCycles); }
|
||||
while (VU0.VI[REG_VPU_STAT].UL & 0x100);
|
||||
|
||||
g_vifCycles += (VU1.cycle - _cycles) * BIAS;
|
||||
|
|
|
@ -932,10 +932,6 @@
|
|||
RelativePath="..\..\x86\iCOP0.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\x86\iCOP2.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\x86\iFPU.cpp"
|
||||
>
|
||||
|
|
|
@ -1,669 +0,0 @@
|
|||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2009 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include "PrecompiledHeader.h"
|
||||
|
||||
#include "Common.h"
|
||||
#include "R5900OpcodeTables.h"
|
||||
#include "iR5900.h"
|
||||
|
||||
#include "Common.h"
|
||||
#include "DebugTools/Debug.h"
|
||||
#include "R5900.h"
|
||||
#include "R5900OpcodeTables.h"
|
||||
#include "VUmicro.h"
|
||||
#include "sVU_Micro.h"
|
||||
using namespace x86Emitter;
|
||||
extern void _vu0WaitMicro();
|
||||
|
||||
#ifndef CHECK_MACROVU0
|
||||
|
||||
#define _Ft_ _Rt_
|
||||
#define _Fs_ _Rd_
|
||||
#define _Fd_ _Sa_
|
||||
|
||||
#define _Fsf_ ((cpuRegs.code >> 21) & 0x03)
|
||||
#define _Ftf_ ((cpuRegs.code >> 23) & 0x03)
|
||||
#define _Cc_ (cpuRegs.code & 0x03)
|
||||
|
||||
#define REC_COP2_VU0(f) \
|
||||
void recV##f( s32 info ) { \
|
||||
recVUMI_##f( &VU0, info ); \
|
||||
}
|
||||
|
||||
#define INTERPRETATE_COP2_FUNC(f) \
|
||||
void recV##f(s32 info) { \
|
||||
MOV32ItoM((uptr)&cpuRegs.code, cpuRegs.code); \
|
||||
MOV32ItoM((uptr)&cpuRegs.pc, pc); \
|
||||
iFlushCall(FLUSH_EVERYTHING); \
|
||||
CALLFunc((uptr)V##f); \
|
||||
_freeX86regs(); \
|
||||
}
|
||||
|
||||
void recCOP2(s32 info);
|
||||
void recCOP2_SPECIAL(s32 info);
|
||||
void recCOP2_BC2(s32 info);
|
||||
void recCOP2_SPECIAL2(s32 info);
|
||||
void rec_C2UNK( s32 info ) {
|
||||
Console.Error("Cop2 bad opcode: %x", cpuRegs.code);
|
||||
}
|
||||
void _vuRegs_C2UNK(VURegs * VU, _VURegsNum *VUregsn) {
|
||||
Console.Error("Cop2 bad _vuRegs code:%x", cpuRegs.code);
|
||||
}
|
||||
|
||||
static void recCFC2(s32 info)
|
||||
{
|
||||
int mmreg;
|
||||
|
||||
if (cpuRegs.code & 1) {
|
||||
iFlushCall(FLUSH_NOCONST);
|
||||
CALLFunc((uptr)_vu0WaitMicro);
|
||||
}
|
||||
|
||||
if(!_Rt_) return;
|
||||
|
||||
_deleteGPRtoXMMreg(_Rt_, 2);
|
||||
mmreg = _checkMMXreg(MMX_GPR+_Rt_, MODE_WRITE);
|
||||
|
||||
if (mmreg >= 0) {
|
||||
if( _Fs_ >= 16 ) {
|
||||
MOVDMtoMMX(mmreg, (uptr)&VU0.VI[ _Fs_ ].UL);
|
||||
if (EEINST_ISLIVE1(_Rt_)) { _signExtendGPRtoMMX(mmreg, _Rt_, 0); }
|
||||
else { EEINST_RESETHASLIVE1(_Rt_); }
|
||||
}
|
||||
else MOVDMtoMMX(mmreg, (uptr)&VU0.VI[ _Fs_ ].UL);
|
||||
SetMMXstate();
|
||||
}
|
||||
else {
|
||||
MOV32MtoR(EAX, (uptr)&VU0.VI[ _Fs_ ].UL);
|
||||
MOV32RtoM((uptr)&cpuRegs.GPR.r[_Rt_].UL[0],EAX);
|
||||
|
||||
if(EEINST_ISLIVE1(_Rt_)) {
|
||||
if( _Fs_ < 16 ) {
|
||||
// no sign extending
|
||||
MOV32ItoM((uptr)&cpuRegs.GPR.r[_Rt_].UL[1],0);
|
||||
}
|
||||
else {
|
||||
CDQ();
|
||||
MOV32RtoM((uptr)&cpuRegs.GPR.r[_Rt_].UL[1], EDX);
|
||||
}
|
||||
}
|
||||
else { EEINST_RESETHASLIVE1(_Rt_); }
|
||||
}
|
||||
|
||||
_eeOnWriteReg(_Rt_, 1);
|
||||
}
|
||||
|
||||
static void recCTC2(s32 info)
|
||||
{
|
||||
if (cpuRegs.code & 1) {
|
||||
iFlushCall(FLUSH_NOCONST);
|
||||
CALLFunc((uptr)_vu0WaitMicro);
|
||||
}
|
||||
|
||||
if(!_Fs_) return;
|
||||
|
||||
if( GPR_IS_CONST1(_Rt_) )
|
||||
{
|
||||
switch(_Fs_) {
|
||||
case REG_MAC_FLAG: // read-only
|
||||
case REG_TPC: // read-only
|
||||
case REG_VPU_STAT: // read-only
|
||||
break;
|
||||
case REG_FBRST:
|
||||
if( g_cpuConstRegs[_Rt_].UL[0] & 0x202 )
|
||||
iFlushCall(FLUSH_FREE_TEMPX86);
|
||||
|
||||
_deleteX86reg(X86TYPE_VI, REG_FBRST, 2);
|
||||
|
||||
if( g_cpuConstRegs[_Rt_].UL[0] & 2 )
|
||||
CALLFunc((uptr)vu0ResetRegs);
|
||||
if( g_cpuConstRegs[_Rt_].UL[0] & 0x200 )
|
||||
CALLFunc((uptr)vu1ResetRegs);
|
||||
MOV16ItoM((uptr)&VU0.VI[REG_FBRST].UL,g_cpuConstRegs[_Rt_].UL[0]&0x0c0c);
|
||||
break;
|
||||
case REG_CMSAR1: // REG_CMSAR1
|
||||
iFlushCall(FLUSH_NOCONST);
|
||||
pxAssert( _checkX86reg(X86TYPE_VI, REG_VPU_STAT, 0) < 0 &&
|
||||
_checkX86reg(X86TYPE_VI, REG_TPC, 0) < 0 );
|
||||
// Execute VU1 Micro SubRoutine
|
||||
|
||||
xMOV( ecx, g_cpuConstRegs[_Rt_].UL[0]&0xffff );
|
||||
xCALL( vu1ExecMicro );
|
||||
break;
|
||||
default:
|
||||
{
|
||||
if( _Fs_ < 16 )
|
||||
pxAssert( (g_cpuConstRegs[_Rt_].UL[0]&0xffff0000)==0);
|
||||
|
||||
// a lot of games have vu0 spinning on some integer
|
||||
// then they modify the register and expect vu0 to stop spinning within 10 cycles (donald duck)
|
||||
|
||||
// Use vu0ExecMicro instead because it properly stalls for already-running micro
|
||||
// instructions, and also sets the nextBranchCycle as needed. (air)
|
||||
|
||||
MOV32ItoM((uptr)&VU0.VI[_Fs_].UL,g_cpuConstRegs[_Rt_].UL[0]);
|
||||
iFlushCall(FLUSH_NOCONST);
|
||||
xMOV(ecx, (uptr)CpuVU0 );
|
||||
xCALL(BaseCpuProvider::ExecuteBlockJIT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(_Fs_) {
|
||||
case REG_MAC_FLAG: // read-only
|
||||
case REG_TPC: // read-only
|
||||
case REG_VPU_STAT: // read-only
|
||||
break;
|
||||
case REG_FBRST:
|
||||
iFlushCall(FLUSH_FREE_TEMPX86);
|
||||
pxAssert( _checkX86reg(X86TYPE_VI, REG_FBRST, 0) < 0 );
|
||||
|
||||
_eeMoveGPRtoR(EAX, _Rt_);
|
||||
|
||||
TEST32ItoR(EAX,0x2);
|
||||
j8Ptr[0] = JZ8(0);
|
||||
CALLFunc((uptr)vu0ResetRegs);
|
||||
_eeMoveGPRtoR(EAX, _Rt_);
|
||||
x86SetJ8(j8Ptr[0]);
|
||||
|
||||
TEST32ItoR(EAX,0x200);
|
||||
j8Ptr[0] = JZ8(0);
|
||||
CALLFunc((uptr)vu1ResetRegs);
|
||||
_eeMoveGPRtoR(EAX, _Rt_);
|
||||
x86SetJ8(j8Ptr[0]);
|
||||
|
||||
AND32ItoR(EAX,0x0C0C);
|
||||
MOV16RtoM((uptr)&VU0.VI[REG_FBRST].UL,EAX);
|
||||
break;
|
||||
case REG_CMSAR1: // REG_CMSAR1 (Execute VU1micro Subroutine)
|
||||
iFlushCall(FLUSH_NOCONST);
|
||||
_eeMoveGPRtoR(ECX, _Rt_);
|
||||
xCALL( vu1ExecMicro );
|
||||
break;
|
||||
default:
|
||||
_eeMoveGPRtoM((uptr)&VU0.VI[_Fs_].UL,_Rt_);
|
||||
|
||||
// a lot of games have vu0 spinning on some integer
|
||||
// then they modify the register and expect vu0 to stop spinning within 10 cycles (donald duck)
|
||||
iFlushCall(FLUSH_NOCONST);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void recQMFC2(s32 info)
|
||||
{
|
||||
int t0reg, fsreg;
|
||||
|
||||
if (cpuRegs.code & 1) {
|
||||
iFlushCall(FLUSH_NOCONST);
|
||||
CALLFunc((uptr)_vu0WaitMicro);
|
||||
}
|
||||
|
||||
if(!_Rt_) return;
|
||||
|
||||
_deleteMMXreg(MMX_GPR+_Rt_, 2);
|
||||
_deleteX86reg(X86TYPE_GPR, _Rt_, 2);
|
||||
_eeOnWriteReg(_Rt_, 0);
|
||||
|
||||
// could 'borrow' the reg
|
||||
fsreg = _checkXMMreg(XMMTYPE_VFREG, _Fs_, MODE_READ);
|
||||
|
||||
if( fsreg >= 0 ) {
|
||||
if ( xmmregs[fsreg].mode & MODE_WRITE ) {
|
||||
_xmmregs temp;
|
||||
|
||||
t0reg = _allocGPRtoXMMreg(-1, _Rt_, MODE_WRITE);
|
||||
SSEX_MOVDQA_XMM_to_XMM(t0reg, fsreg);
|
||||
|
||||
// change regs
|
||||
temp = xmmregs[t0reg];
|
||||
xmmregs[t0reg] = xmmregs[fsreg];
|
||||
xmmregs[fsreg] = temp;
|
||||
}
|
||||
else {
|
||||
// swap regs
|
||||
t0reg = _allocGPRtoXMMreg(-1, _Rt_, MODE_WRITE);
|
||||
|
||||
xmmregs[fsreg] = xmmregs[t0reg];
|
||||
xmmregs[t0reg].inuse = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
t0reg = _allocGPRtoXMMreg(-1, _Rt_, MODE_WRITE);
|
||||
|
||||
if (t0reg >= 0) SSE_MOVAPS_M128_to_XMM( t0reg, (uptr)&VU0.VF[_Fs_].UD[0]);
|
||||
else _recMove128MtoM((uptr)&cpuRegs.GPR.r[_Rt_].UL[0], (uptr)&VU0.VF[_Fs_].UL[0]);
|
||||
}
|
||||
|
||||
_clearNeededXMMregs();
|
||||
}
|
||||
|
||||
static void recQMTC2(s32 info)
|
||||
{
|
||||
int mmreg;
|
||||
|
||||
if (cpuRegs.code & 1) {
|
||||
iFlushCall(FLUSH_NOCONST);
|
||||
CALLFunc((uptr)_vu0WaitMicro);
|
||||
}
|
||||
|
||||
if (!_Fs_) return;
|
||||
|
||||
mmreg = _checkXMMreg(XMMTYPE_GPRREG, _Rt_, MODE_READ);
|
||||
|
||||
if( mmreg >= 0) {
|
||||
int fsreg = _checkXMMreg(XMMTYPE_VFREG, _Fs_, MODE_WRITE);
|
||||
int flag = ((xmmregs[mmreg].mode&MODE_WRITE) && (g_pCurInstInfo->regs[_Rt_]&(EEINST_LIVE0|EEINST_LIVE1|EEINST_LIVE2)));
|
||||
|
||||
if( fsreg >= 0 ) {
|
||||
|
||||
if (flag) {
|
||||
SSE_MOVAPS_XMM_to_XMM(fsreg, mmreg);
|
||||
}
|
||||
else {
|
||||
// swap regs
|
||||
xmmregs[mmreg] = xmmregs[fsreg];
|
||||
xmmregs[mmreg].mode = MODE_WRITE;
|
||||
xmmregs[fsreg].inuse = 0;
|
||||
g_xmmtypes[mmreg] = XMMT_FPS;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (flag) SSE_MOVAPS_XMM_to_M128((uptr)&cpuRegs.GPR.r[_Rt_], mmreg);
|
||||
|
||||
// swap regs
|
||||
xmmregs[mmreg].type = XMMTYPE_VFREG;
|
||||
xmmregs[mmreg].VU = 0;
|
||||
xmmregs[mmreg].reg = _Fs_;
|
||||
xmmregs[mmreg].mode = MODE_WRITE;
|
||||
g_xmmtypes[mmreg] = XMMT_FPS;
|
||||
}
|
||||
}
|
||||
else {
|
||||
int fsreg = _allocVFtoXMMreg(&VU0, -1, _Fs_, MODE_WRITE);
|
||||
|
||||
if( fsreg >= 0 ) {
|
||||
mmreg = _checkMMXreg(MMX_GPR+_Rt_, MODE_READ);
|
||||
|
||||
if( mmreg >= 0) {
|
||||
SetMMXstate();
|
||||
SSE2_MOVQ2DQ_MM_to_XMM(fsreg, mmreg);
|
||||
SSE_MOVHPS_M64_to_XMM(fsreg, (uptr)&cpuRegs.GPR.r[_Rt_].UL[2]);
|
||||
}
|
||||
else {
|
||||
if( GPR_IS_CONST1( _Rt_ ) ) {
|
||||
pxAssert( _checkXMMreg(XMMTYPE_GPRREG, _Rt_, MODE_READ) == -1 );
|
||||
_flushConstReg(_Rt_);
|
||||
}
|
||||
|
||||
SSE_MOVAPS_M128_to_XMM(fsreg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
_deleteEEreg(_Rt_, 0);
|
||||
_recMove128MtoM((uptr)&VU0.VF[_Fs_].UL[0], (uptr)&cpuRegs.GPR.r[_Rt_].UL[0]);
|
||||
}
|
||||
}
|
||||
|
||||
_clearNeededXMMregs();
|
||||
}
|
||||
|
||||
// Removed _cop2AnalyzeOp because it was outdated and unreliable (And currently unused).
|
||||
// A new version should be rebuilt using the SuperVU's AnalyzeOp as a reference. (air)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// BC2: Instructions
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
using namespace R5900::Dynarec;
|
||||
|
||||
static void _setupBranchTest()
|
||||
{
|
||||
_eeFlushAllUnused();
|
||||
|
||||
// COP2 branch conditionals are based on the following equation:
|
||||
// ((VU0.VI[REG_VPU_STAT].US[0] >> 8) & 1)
|
||||
// BC2F checks if the statement is false, BC2T checks if the statement is true.
|
||||
|
||||
TEST32ItoM((uptr)&VU0.VI[REG_VPU_STAT].UL, 0x100);
|
||||
}
|
||||
|
||||
void recBC2F( s32 info )
|
||||
{
|
||||
_setupBranchTest();
|
||||
recDoBranchImm(JNZ32(0));
|
||||
}
|
||||
|
||||
void recBC2T( s32 info )
|
||||
{
|
||||
_setupBranchTest();
|
||||
recDoBranchImm(JZ32(0));
|
||||
}
|
||||
|
||||
void recBC2FL( s32 info )
|
||||
{
|
||||
_setupBranchTest();
|
||||
recDoBranchImm_Likely(JNZ32(0));
|
||||
}
|
||||
|
||||
void recBC2TL( s32 info )
|
||||
{
|
||||
_setupBranchTest();
|
||||
recDoBranchImm_Likely(JZ32(0));
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Special1 instructions
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//TODO: redirect all the opcodes to the ivu0micro same functions
|
||||
REC_COP2_VU0(IADD);
|
||||
REC_COP2_VU0(IADDI);
|
||||
REC_COP2_VU0(ISUB);
|
||||
REC_COP2_VU0(IOR);
|
||||
REC_COP2_VU0(IAND);
|
||||
REC_COP2_VU0(OPMSUB);
|
||||
REC_COP2_VU0(MADDq);
|
||||
REC_COP2_VU0(MADDi);
|
||||
REC_COP2_VU0(MSUBq);
|
||||
REC_COP2_VU0(MSUBi);
|
||||
REC_COP2_VU0(SUBi);
|
||||
REC_COP2_VU0(SUBq);
|
||||
REC_COP2_VU0(MULi);
|
||||
REC_COP2_VU0(MULq);
|
||||
REC_COP2_VU0(MAXi);
|
||||
REC_COP2_VU0(MINIi);
|
||||
REC_COP2_VU0(MUL);
|
||||
REC_COP2_VU0(MAX);
|
||||
REC_COP2_VU0(MADD);
|
||||
REC_COP2_VU0(MSUB);
|
||||
|
||||
REC_COP2_VU0(MINIx);
|
||||
REC_COP2_VU0(MINIy);
|
||||
REC_COP2_VU0(MINIz);
|
||||
REC_COP2_VU0(MINIw);
|
||||
|
||||
REC_COP2_VU0(MAXx);
|
||||
REC_COP2_VU0(MAXy);
|
||||
REC_COP2_VU0(MAXz);
|
||||
REC_COP2_VU0(MAXw);
|
||||
|
||||
REC_COP2_VU0(MULx);
|
||||
REC_COP2_VU0(MULy);
|
||||
REC_COP2_VU0(MULz);
|
||||
REC_COP2_VU0(MULw);
|
||||
|
||||
REC_COP2_VU0(ADD);
|
||||
REC_COP2_VU0(ADDi);
|
||||
REC_COP2_VU0(ADDq);
|
||||
REC_COP2_VU0(ADDx);
|
||||
REC_COP2_VU0(ADDy);
|
||||
REC_COP2_VU0(ADDz);
|
||||
REC_COP2_VU0(ADDw);
|
||||
|
||||
REC_COP2_VU0(SUBx);
|
||||
REC_COP2_VU0(SUBy);
|
||||
REC_COP2_VU0(SUBz);
|
||||
REC_COP2_VU0(SUBw);
|
||||
|
||||
REC_COP2_VU0(MADDx);
|
||||
REC_COP2_VU0(MADDy);
|
||||
REC_COP2_VU0(MADDz);
|
||||
REC_COP2_VU0(MADDw);
|
||||
|
||||
REC_COP2_VU0(MSUBx);
|
||||
REC_COP2_VU0(MSUBy);
|
||||
REC_COP2_VU0(MSUBz);
|
||||
REC_COP2_VU0(MSUBw);
|
||||
|
||||
REC_COP2_VU0(SUB);
|
||||
REC_COP2_VU0(MINI);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Special2 instructions
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
REC_COP2_VU0(CLIP);
|
||||
REC_COP2_VU0(LQI);
|
||||
REC_COP2_VU0(SQI);
|
||||
REC_COP2_VU0(LQD);
|
||||
REC_COP2_VU0(SQD);
|
||||
REC_COP2_VU0(MTIR);
|
||||
REC_COP2_VU0(MFIR);
|
||||
REC_COP2_VU0(ILWR);
|
||||
REC_COP2_VU0(ISWR);
|
||||
REC_COP2_VU0(RINIT);
|
||||
REC_COP2_VU0(RXOR);
|
||||
REC_COP2_VU0(RNEXT);
|
||||
REC_COP2_VU0(RGET);
|
||||
|
||||
REC_COP2_VU0(ITOF0);
|
||||
REC_COP2_VU0(ITOF4);
|
||||
REC_COP2_VU0(ITOF12);
|
||||
REC_COP2_VU0(ITOF15);
|
||||
REC_COP2_VU0(FTOI0);
|
||||
REC_COP2_VU0(FTOI4);
|
||||
REC_COP2_VU0(FTOI12);
|
||||
REC_COP2_VU0(FTOI15);
|
||||
REC_COP2_VU0(MADDA);
|
||||
REC_COP2_VU0(MSUBA);
|
||||
REC_COP2_VU0(MADDAi);
|
||||
REC_COP2_VU0(MADDAq);
|
||||
REC_COP2_VU0(MADDAx);
|
||||
REC_COP2_VU0(MADDAy);
|
||||
REC_COP2_VU0(MADDAz);
|
||||
REC_COP2_VU0(MADDAw);
|
||||
REC_COP2_VU0(MSUBAi);
|
||||
REC_COP2_VU0(MSUBAq);
|
||||
REC_COP2_VU0(MSUBAx);
|
||||
REC_COP2_VU0(MSUBAy);
|
||||
REC_COP2_VU0(MSUBAz);
|
||||
REC_COP2_VU0(MSUBAw);
|
||||
REC_COP2_VU0(ADDAi);
|
||||
REC_COP2_VU0(ADDA);
|
||||
REC_COP2_VU0(SUBA);
|
||||
REC_COP2_VU0(MULA);
|
||||
REC_COP2_VU0(ADDAq);
|
||||
REC_COP2_VU0(ADDAx);
|
||||
REC_COP2_VU0(ADDAy);
|
||||
REC_COP2_VU0(ADDAz);
|
||||
REC_COP2_VU0(ADDAw);
|
||||
REC_COP2_VU0(SUBAi);
|
||||
REC_COP2_VU0(SUBAq);
|
||||
REC_COP2_VU0(SUBAx);
|
||||
REC_COP2_VU0(SUBAy);
|
||||
REC_COP2_VU0(SUBAz);
|
||||
REC_COP2_VU0(SUBAw);
|
||||
REC_COP2_VU0(MULAi);
|
||||
REC_COP2_VU0(MULAq);
|
||||
REC_COP2_VU0(MULAx);
|
||||
REC_COP2_VU0(MULAy);
|
||||
REC_COP2_VU0(MULAz);
|
||||
REC_COP2_VU0(MULAw);
|
||||
REC_COP2_VU0(OPMULA);
|
||||
REC_COP2_VU0(MOVE);
|
||||
REC_COP2_VU0(DIV);
|
||||
REC_COP2_VU0(SQRT);
|
||||
REC_COP2_VU0(RSQRT);
|
||||
REC_COP2_VU0(MR32);
|
||||
REC_COP2_VU0(ABS);
|
||||
|
||||
void recVNOP(s32 info){}
|
||||
void recVWAITQ(s32 info){}
|
||||
INTERPRETATE_COP2_FUNC(CALLMS);
|
||||
INTERPRETATE_COP2_FUNC(CALLMSR);
|
||||
|
||||
void _vuRegsCOP2_SPECIAL(VURegs * VU, _VURegsNum *VUregsn);
|
||||
void _vuRegsCOP2_SPECIAL2(VURegs * VU, _VURegsNum *VUregsn);
|
||||
|
||||
// information
|
||||
void _vuRegsQMFC2(VURegs * VU, _VURegsNum *VUregsn) {
|
||||
VUregsn->VFread0 = _Fs_;
|
||||
VUregsn->VFr0xyzw= 0xf;
|
||||
}
|
||||
|
||||
void _vuRegsCFC2(VURegs * VU, _VURegsNum *VUregsn) {
|
||||
VUregsn->VIread = 1<<_Fs_;
|
||||
}
|
||||
|
||||
void _vuRegsQMTC2(VURegs * VU, _VURegsNum *VUregsn) {
|
||||
VUregsn->VFwrite = _Fs_;
|
||||
VUregsn->VFwxyzw= 0xf;
|
||||
}
|
||||
|
||||
void _vuRegsCTC2(VURegs * VU, _VURegsNum *VUregsn) {
|
||||
VUregsn->VIwrite = 1<<_Fs_;
|
||||
}
|
||||
|
||||
void (*_vuRegsCOP2t[32])(VURegs * VU, _VURegsNum *VUregsn) = {
|
||||
_vuRegs_C2UNK, _vuRegsQMFC2, _vuRegsCFC2, _vuRegs_C2UNK, _vuRegs_C2UNK, _vuRegsQMTC2, _vuRegsCTC2, _vuRegs_C2UNK,
|
||||
_vuRegsNOP, _vuRegs_C2UNK, _vuRegs_C2UNK, _vuRegs_C2UNK, _vuRegs_C2UNK, _vuRegs_C2UNK, _vuRegs_C2UNK, _vuRegs_C2UNK,
|
||||
_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,
|
||||
_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,
|
||||
};
|
||||
|
||||
void (*_vuRegsCOP2SPECIAL1t[64])(VURegs * VU, _VURegsNum *VUregsn) = {
|
||||
_vuRegsADDx, _vuRegsADDy, _vuRegsADDz, _vuRegsADDw, _vuRegsSUBx, _vuRegsSUBy, _vuRegsSUBz, _vuRegsSUBw,
|
||||
_vuRegsMADDx, _vuRegsMADDy, _vuRegsMADDz, _vuRegsMADDw, _vuRegsMSUBx, _vuRegsMSUBy, _vuRegsMSUBz, _vuRegsMSUBw,
|
||||
_vuRegsMAXx, _vuRegsMAXy, _vuRegsMAXz, _vuRegsMAXw, _vuRegsMINIx, _vuRegsMINIy, _vuRegsMINIz, _vuRegsMINIw,
|
||||
_vuRegsMULx, _vuRegsMULy, _vuRegsMULz, _vuRegsMULw, _vuRegsMULq, _vuRegsMAXi, _vuRegsMULi, _vuRegsMINIi,
|
||||
_vuRegsADDq, _vuRegsMADDq, _vuRegsADDi, _vuRegsMADDi, _vuRegsSUBq, _vuRegsMSUBq, _vuRegsSUBi, _vuRegsMSUBi,
|
||||
_vuRegsADD, _vuRegsMADD, _vuRegsMUL, _vuRegsMAX, _vuRegsSUB, _vuRegsMSUB, _vuRegsOPMSUB, _vuRegsMINI,
|
||||
_vuRegsIADD, _vuRegsISUB, _vuRegsIADDI, _vuRegs_C2UNK, _vuRegsIAND, _vuRegsIOR, _vuRegs_C2UNK, _vuRegs_C2UNK,
|
||||
_vuRegsNOP, _vuRegsNOP, _vuRegs_C2UNK, _vuRegs_C2UNK, _vuRegsCOP2_SPECIAL2,_vuRegsCOP2_SPECIAL2,_vuRegsCOP2_SPECIAL2,_vuRegsCOP2_SPECIAL2,
|
||||
};
|
||||
|
||||
void (*_vuRegsCOP2SPECIAL2t[128])(VURegs * VU, _VURegsNum *VUregsn) = {
|
||||
_vuRegsADDAx ,_vuRegsADDAy ,_vuRegsADDAz ,_vuRegsADDAw ,_vuRegsSUBAx ,_vuRegsSUBAy ,_vuRegsSUBAz ,_vuRegsSUBAw,
|
||||
_vuRegsMADDAx ,_vuRegsMADDAy ,_vuRegsMADDAz ,_vuRegsMADDAw ,_vuRegsMSUBAx ,_vuRegsMSUBAy ,_vuRegsMSUBAz ,_vuRegsMSUBAw,
|
||||
_vuRegsITOF0 ,_vuRegsITOF4 ,_vuRegsITOF12 ,_vuRegsITOF15 ,_vuRegsFTOI0 ,_vuRegsFTOI4 ,_vuRegsFTOI12 ,_vuRegsFTOI15,
|
||||
_vuRegsMULAx ,_vuRegsMULAy ,_vuRegsMULAz ,_vuRegsMULAw ,_vuRegsMULAq ,_vuRegsABS ,_vuRegsMULAi ,_vuRegsCLIP,
|
||||
_vuRegsADDAq ,_vuRegsMADDAq ,_vuRegsADDAi ,_vuRegsMADDAi ,_vuRegsSUBAq ,_vuRegsMSUBAq ,_vuRegsSUBAi ,_vuRegsMSUBAi,
|
||||
_vuRegsADDA ,_vuRegsMADDA ,_vuRegsMULA ,_vuRegs_C2UNK ,_vuRegsSUBA ,_vuRegsMSUBA ,_vuRegsOPMULA ,_vuRegsNOP,
|
||||
_vuRegsMOVE ,_vuRegsMR32 ,_vuRegs_C2UNK ,_vuRegs_C2UNK ,_vuRegsLQI ,_vuRegsSQI ,_vuRegsLQD ,_vuRegsSQD,
|
||||
_vuRegsDIV ,_vuRegsSQRT ,_vuRegsRSQRT ,_vuRegsWAITQ ,_vuRegsMTIR ,_vuRegsMFIR ,_vuRegsILWR ,_vuRegsISWR,
|
||||
_vuRegsRNEXT ,_vuRegsRGET ,_vuRegsRINIT ,_vuRegsRXOR ,_vuRegs_C2UNK ,_vuRegs_C2UNK ,_vuRegs_C2UNK ,_vuRegs_C2UNK,
|
||||
_vuRegs_C2UNK ,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,
|
||||
_vuRegs_C2UNK ,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,
|
||||
_vuRegs_C2UNK ,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,
|
||||
_vuRegs_C2UNK ,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,
|
||||
_vuRegs_C2UNK ,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,
|
||||
_vuRegs_C2UNK ,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,
|
||||
_vuRegs_C2UNK ,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,
|
||||
};
|
||||
|
||||
void _vuRegsCOP22(VURegs * VU, _VURegsNum *VUregsn)
|
||||
{
|
||||
_vuRegsCOP2t[_Rs_](VU, VUregsn);
|
||||
}
|
||||
|
||||
void _vuRegsCOP2_SPECIAL(VURegs * VU, _VURegsNum *VUregsn)
|
||||
{
|
||||
_vuRegsCOP2SPECIAL1t[_Funct_](VU, VUregsn);
|
||||
}
|
||||
|
||||
void _vuRegsCOP2_SPECIAL2(VURegs * VU, _VURegsNum *VUregsn)
|
||||
{
|
||||
int opc=(cpuRegs.code & 0x3) | ((cpuRegs.code >> 4) & 0x7c);
|
||||
_vuRegsCOP2SPECIAL2t[opc](VU, VUregsn);
|
||||
}
|
||||
|
||||
// recompilation
|
||||
void (*recCOP2t[32])(s32 info) = {
|
||||
rec_C2UNK, recQMFC2, recCFC2, rec_C2UNK, rec_C2UNK, recQMTC2, recCTC2, rec_C2UNK,
|
||||
recCOP2_BC2, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK,
|
||||
recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,
|
||||
recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,
|
||||
};
|
||||
|
||||
void (*recCOP2_BC2t[32])(s32 info) = {
|
||||
recBC2F, recBC2T, recBC2FL, recBC2TL, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK,
|
||||
rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK,
|
||||
rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK,
|
||||
rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK,
|
||||
};
|
||||
|
||||
void (*recCOP2SPECIAL1t[64])(s32 info) = {
|
||||
recVADDx, recVADDy, recVADDz, recVADDw, recVSUBx, recVSUBy, recVSUBz, recVSUBw,
|
||||
recVMADDx, recVMADDy, recVMADDz, recVMADDw, recVMSUBx, recVMSUBy, recVMSUBz, recVMSUBw,
|
||||
recVMAXx, recVMAXy, recVMAXz, recVMAXw, recVMINIx, recVMINIy, recVMINIz, recVMINIw,
|
||||
recVMULx, recVMULy, recVMULz, recVMULw, recVMULq, recVMAXi, recVMULi, recVMINIi,
|
||||
recVADDq, recVMADDq, recVADDi, recVMADDi, recVSUBq, recVMSUBq, recVSUBi, recVMSUBi,
|
||||
recVADD, recVMADD, recVMUL, recVMAX, recVSUB, recVMSUB, recVOPMSUB, recVMINI,
|
||||
recVIADD, recVISUB, recVIADDI, rec_C2UNK, recVIAND, recVIOR, rec_C2UNK, rec_C2UNK,
|
||||
recVCALLMS, recVCALLMSR, rec_C2UNK, rec_C2UNK, recCOP2_SPECIAL2,recCOP2_SPECIAL2,recCOP2_SPECIAL2,recCOP2_SPECIAL2,
|
||||
};
|
||||
|
||||
void (*recCOP2SPECIAL2t[128])(s32 info) = {
|
||||
recVADDAx ,recVADDAy ,recVADDAz ,recVADDAw ,recVSUBAx ,recVSUBAy ,recVSUBAz ,recVSUBAw,
|
||||
recVMADDAx ,recVMADDAy ,recVMADDAz ,recVMADDAw ,recVMSUBAx ,recVMSUBAy ,recVMSUBAz ,recVMSUBAw,
|
||||
recVITOF0 ,recVITOF4 ,recVITOF12 ,recVITOF15 ,recVFTOI0 ,recVFTOI4 ,recVFTOI12 ,recVFTOI15,
|
||||
recVMULAx ,recVMULAy ,recVMULAz ,recVMULAw ,recVMULAq ,recVABS ,recVMULAi ,recVCLIP,
|
||||
recVADDAq ,recVMADDAq ,recVADDAi ,recVMADDAi ,recVSUBAq ,recVMSUBAq ,recVSUBAi ,recVMSUBAi,
|
||||
recVADDA ,recVMADDA ,recVMULA ,rec_C2UNK ,recVSUBA ,recVMSUBA ,recVOPMULA ,recVNOP,
|
||||
recVMOVE ,recVMR32 ,rec_C2UNK ,rec_C2UNK ,recVLQI ,recVSQI ,recVLQD ,recVSQD,
|
||||
recVDIV ,recVSQRT ,recVRSQRT ,recVWAITQ ,recVMTIR ,recVMFIR ,recVILWR ,recVISWR,
|
||||
recVRNEXT ,recVRGET ,recVRINIT ,recVRXOR ,rec_C2UNK ,rec_C2UNK ,rec_C2UNK ,rec_C2UNK,
|
||||
rec_C2UNK ,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,
|
||||
rec_C2UNK ,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,
|
||||
rec_C2UNK ,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,
|
||||
rec_C2UNK ,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,
|
||||
rec_C2UNK ,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,
|
||||
rec_C2UNK ,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,
|
||||
rec_C2UNK ,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,
|
||||
};
|
||||
|
||||
namespace R5900 {
|
||||
namespace Dynarec {
|
||||
namespace OpcodeImpl
|
||||
{
|
||||
void recCOP2()
|
||||
{
|
||||
VU0.code = cpuRegs.code;
|
||||
|
||||
g_pCurInstInfo->vuregs.pipe = 0xff; // to notify eeVURecompileCode that COP2
|
||||
s32 info = eeVURecompileCode(&VU0, &g_pCurInstInfo->vuregs);
|
||||
|
||||
info |= PROCESS_VU_COP2;
|
||||
info |= PROCESS_VU_UPDATEFLAGS;
|
||||
|
||||
recCOP2t[_Rs_]( info );
|
||||
|
||||
_freeX86regs();
|
||||
}
|
||||
}}}
|
||||
|
||||
void recCOP2_SPECIAL(s32 info )
|
||||
{
|
||||
recCOP2SPECIAL1t[_Funct_]( info );
|
||||
}
|
||||
|
||||
void recCOP2_BC2(s32 info)
|
||||
{
|
||||
recCOP2_BC2t[_Rt_](info);
|
||||
}
|
||||
|
||||
void recCOP2_SPECIAL2(s32 info)
|
||||
{
|
||||
int opc=(cpuRegs.code & 0x3) | ((cpuRegs.code >> 4) & 0x7c);
|
||||
recCOP2SPECIAL2t[opc](info);
|
||||
}
|
||||
|
||||
#endif // CHECK_MACROVU0
|
|
@ -331,8 +331,8 @@ _mVUt _f int mVUsearchProg() {
|
|||
static u32 mvu0_allocated = 0;
|
||||
static u32 mvu1_allocated = 0;
|
||||
|
||||
recMicroVU0::recMicroVU0() { IsInterpreter = false; }
|
||||
recMicroVU1::recMicroVU1() { IsInterpreter = false; }
|
||||
recMicroVU0::recMicroVU0() { m_Idx = 0; IsInterpreter = false; }
|
||||
recMicroVU1::recMicroVU1() { m_Idx = 1; IsInterpreter = false; }
|
||||
void recMicroVU0::Vsync() throw() { mVUvsyncUpdate(µVU0); }
|
||||
void recMicroVU1::Vsync() throw() { mVUvsyncUpdate(µVU1); }
|
||||
|
||||
|
@ -375,7 +375,7 @@ void recMicroVU1::Reset() {
|
|||
mVUreset(µVU1);
|
||||
}
|
||||
|
||||
void recMicroVU0::ExecuteBlock(u32 cycles) {
|
||||
void recMicroVU0::Execute(u32 cycles) {
|
||||
pxAssert(mvu0_allocated); // please allocate me first! :|
|
||||
|
||||
if(!(VU0.VI[REG_VPU_STAT].UL & 1)) return;
|
||||
|
@ -387,13 +387,13 @@ void recMicroVU0::ExecuteBlock(u32 cycles) {
|
|||
((mVUrecCall)microVU0.startFunct)(VU0.VI[REG_TPC].UL, cycles);
|
||||
XMMRegisters::Thaw();
|
||||
}
|
||||
void recMicroVU1::ExecuteBlock(u32 cycles) {
|
||||
void recMicroVU1::Execute(u32 cycles) {
|
||||
pxAssert(mvu1_allocated); // please allocate me first! :|
|
||||
|
||||
if(!(VU0.VI[REG_VPU_STAT].UL & 0x100)) return;
|
||||
|
||||
XMMRegisters::Freeze();
|
||||
((mVUrecCall)microVU1.startFunct)(VU1.VI[REG_TPC].UL, cycles);
|
||||
((mVUrecCall)microVU1.startFunct)(VU1.VI[REG_TPC].UL, vu1RunCycles);
|
||||
XMMRegisters::Thaw();
|
||||
}
|
||||
|
||||
|
|
|
@ -64,7 +64,7 @@ _f void mVUendProgram(mV, microFlagCycles* mFC, int isEbit) {
|
|||
}
|
||||
|
||||
// Save Flag Instances
|
||||
#ifdef CHECK_MACROVU0
|
||||
#if 1 // CHECK_MACROVU0 - Always on now
|
||||
getFlagReg(fStatus, fStatus);
|
||||
MOV32RtoM((uptr)&mVU->regs->VI[REG_STATUS_FLAG].UL, fStatus);
|
||||
#else
|
||||
|
|
|
@ -298,8 +298,8 @@ _f void mVUtestCycles(microVU* mVU) {
|
|||
//u32* vu0jmp;
|
||||
iPC = mVUstartPC;
|
||||
mVUdebugNOW(0);
|
||||
SUB32ItoM((uptr)&mVU->cycles, mVUcycles);
|
||||
if (doEarlyExit(mVU)) {
|
||||
CMP32ItoM((uptr)&mVU->cycles, 0);
|
||||
u32* jmp32 = JG32(0);
|
||||
//if (!isVU1) { TEST32ItoM((uptr)&mVU->regs->flags, VUFLAG_MFLAGSET); vu0jmp = JZ32(0); }
|
||||
MOV32ItoR(gprT2, (uptr)mVU);
|
||||
|
@ -310,6 +310,7 @@ _f void mVUtestCycles(microVU* mVU) {
|
|||
//if (!isVU1) x86SetJ32(vu0jmp);
|
||||
x86SetJ32(jmp32);
|
||||
}
|
||||
SUB32ItoM((uptr)&mVU->cycles, mVUcycles);
|
||||
}
|
||||
|
||||
// Initialize VI Constants (vi15 propagates through blocks)
|
||||
|
|
|
@ -42,7 +42,7 @@ void mVUdispatcherA(mV) {
|
|||
xLDMXCSR(g_sseVUMXCSR);
|
||||
|
||||
// Load Regs
|
||||
#ifdef CHECK_MACROVU0
|
||||
#if 1 // CHECK_MACROVU0 - Always on now
|
||||
MOV32MtoR(gprF0, (uptr)&mVU->regs->VI[REG_STATUS_FLAG].UL);
|
||||
MOV32RtoR(gprF1, gprF0);
|
||||
MOV32RtoR(gprF2, gprF0);
|
||||
|
|
|
@ -13,8 +13,6 @@
|
|||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef CHECK_MACROVU0
|
||||
|
||||
#pragma once
|
||||
|
||||
extern void _vu0WaitMicro();
|
||||
|
@ -432,5 +430,3 @@ namespace OpcodeImpl { void recCOP2() { recCOP2t[_Rs_](); }}}}
|
|||
void recCOP2_BC2 () { recCOP2_BC2t[_Rt_](); }
|
||||
void recCOP2_SPEC1() { recCOP2SPECIAL1t[_Funct_](); }
|
||||
void recCOP2_SPEC2() { recCOP2SPECIAL2t[(cpuRegs.code&3)|((cpuRegs.code>>4)&0x7c)](); }
|
||||
|
||||
#endif // CHECK_MACROVU0
|
||||
|
|
|
@ -4610,6 +4610,7 @@ void recVUunknown(VURegs* VU, s32 info)
|
|||
// --------------------------------------------------------------------------------------
|
||||
recSuperVU0::recSuperVU0()
|
||||
{
|
||||
m_Idx = 0;
|
||||
IsInterpreter = false;
|
||||
}
|
||||
|
||||
|
@ -4628,7 +4629,7 @@ void recSuperVU0::Reset()
|
|||
SuperVUReset( 0 );
|
||||
}
|
||||
|
||||
void recSuperVU0::ExecuteBlock(u32 cycles)
|
||||
void recSuperVU0::Execute(u32 cycles)
|
||||
{
|
||||
if ((VU0.VI[REG_VPU_STAT].UL & 1) == 0) return;
|
||||
|
||||
|
@ -4648,6 +4649,7 @@ void recSuperVU0::Clear(u32 Addr, u32 Size)
|
|||
// --------------------------------------------------------------------------------------
|
||||
recSuperVU1::recSuperVU1()
|
||||
{
|
||||
m_Idx = 1;
|
||||
IsInterpreter = false;
|
||||
}
|
||||
|
||||
|
@ -4666,7 +4668,7 @@ void recSuperVU1::Reset()
|
|||
SuperVUReset( 1 );
|
||||
}
|
||||
|
||||
void recSuperVU1::ExecuteBlock(u32 cycles)
|
||||
void recSuperVU1::Execute(u32 cycles)
|
||||
{
|
||||
if ((VU0.VI[REG_VPU_STAT].UL & 0x100) == 0) return;
|
||||
pxAssert( (VU1.VI[REG_TPC].UL&7) == 0 );
|
||||
|
|
|
@ -40,34 +40,3 @@ extern u32 SuperVUGetVIAddr(int reg, int read);
|
|||
|
||||
// if p == 0, flush q else flush p; if wait is != 0, waits for p/q
|
||||
extern void SuperVUFlush(int p, int wait);
|
||||
|
||||
|
||||
class recSuperVU0 : public BaseVUmicroCPU
|
||||
{
|
||||
public:
|
||||
recSuperVU0();
|
||||
|
||||
const char* GetShortName() const { return "sVU0"; }
|
||||
wxString GetLongName() const { return L"SuperVU0 Recompiler"; }
|
||||
|
||||
void Allocate();
|
||||
void Shutdown() throw();
|
||||
void Reset();
|
||||
void ExecuteBlock(u32 cycles);
|
||||
void Clear(u32 Addr, u32 Size);
|
||||
};
|
||||
|
||||
class recSuperVU1 : public BaseVUmicroCPU
|
||||
{
|
||||
public:
|
||||
recSuperVU1();
|
||||
|
||||
const char* GetShortName() const { return "sVU1"; }
|
||||
wxString GetLongName() const { return L"SuperVU1 Recompiler"; }
|
||||
|
||||
void Allocate();
|
||||
void Shutdown() throw();
|
||||
void Reset();
|
||||
void ExecuteBlock(u32 cycles);
|
||||
void Clear(u32 Addr, u32 Size);
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue