General improvements to the emulator's reset and recovery code, including several fixes the the VM build (but it's still not entirely stable, but seems to work for many games), and fixed a bug where starting new games wouldn't pick up the CRC correctly.

Did a little code cleanup on the VUSkip, and fixed a problem where-by VU-skip enabled could cause odd behavior when exiting/re-entering emulation.

Removed the unused REC_COP2 option (it was not useful anyway since the COP2 and EE are always recompiled together)

Made a few more __fastcalls out of IPU functions.

git-svn-id: http://pcsx2-playground.googlecode.com/svn/trunk@588 a6443dda-0b58-4228-96e9-037be469359c
This commit is contained in:
Jake.Stine 2009-01-14 23:48:24 +00:00 committed by Gregory Hainaut
parent f1bdbd59a8
commit 1eabf946bb
23 changed files with 231 additions and 152 deletions

View File

@ -30,9 +30,6 @@ using namespace Threading;
extern u8 psxhblankgate;
u32 g_vu1SkipCount; // number of frames to disable/skip VU1
static void (*s_prevExecuteVU1Block)() = NULL; // old VU1 block (either Int or Rec)
extern void DummyExecuteVU1Block(void);
namespace R5900
{
@ -263,8 +260,6 @@ u32 UpdateVSyncRate()
cpuRcntSet();
// Initialize VU Skip Stuff...
assert(CpuVU1 != NULL && CpuVU1->ExecuteBlock != NULL );
s_prevExecuteVU1Block = CpuVU1->ExecuteBlock;
g_vu1SkipCount = 0;
return (u32)m_iTicks;
@ -402,7 +397,7 @@ static __forceinline void frameLimit()
static __forceinline void VSyncStart(u32 sCycle)
{
EECNT_LOG( "//////// EE COUNTER VSYNC START \\\\\\\\ (frame: %d)\n", iFrame );
EECNT_LOG( "///////// EE COUNTER VSYNC START \\\\\\\\\\ (frame: %d)\n", iFrame );
vSyncDebugStuff(); // EE Profiling and Debug code
if ((CSRw & 0x8)) GSCSRr|= 0x8;
@ -434,7 +429,7 @@ static __forceinline void VSyncStart(u32 sCycle)
static __forceinline void VSyncEnd(u32 sCycle)
{
EECNT_LOG( "//////// EE COUNTER VSYNC END \\\\\\\\ (frame: %d)\n", iFrame );
EECNT_LOG( "///////// EE COUNTER VSYNC END \\\\\\\\\\ (frame: %d)\n", iFrame );
iFrame++;
@ -442,12 +437,12 @@ static __forceinline void VSyncEnd(u32 sCycle)
{
gsPostVsyncEnd( false );
AtomicDecrement( g_vu1SkipCount );
CpuVU1->ExecuteBlock = DummyExecuteVU1Block;
vu1MicroEnableSkip();
}
else
{
gsPostVsyncEnd( true );
CpuVU1->ExecuteBlock = s_prevExecuteVU1Block;
vu1MicroDisableSkip();
}
hwIntcIrq(3); // HW Irq

View File

@ -76,7 +76,6 @@ PCSX2_ALIGNED16(u32 fifo_input[32]);
PCSX2_ALIGNED16(u32 fifo_output[32]);
void ReorderBitstream();
u16 FillInternalBuffer(u32 * pointer, u32 advance, u32 size);
// the BP doesn't advance and returns -1 if there is no data to be read
tIPU_BP g_BP;
@ -1011,7 +1010,7 @@ void ReorderBitstream()
// If FP is 1, there's 1 qword in buffer. Second qword is only loaded
// incase there are less than 32bits available in the first qword.
// \return Number of bits available (clamps at 16 bits)
u16 FillInternalBuffer(u32 * pointer, u32 advance, u32 size)
u16 __fastcall FillInternalBuffer(u32 * pointer, u32 advance, u32 size)
{
if(g_BP.FP == 0)
{
@ -1050,7 +1049,7 @@ u16 FillInternalBuffer(u32 * pointer, u32 advance, u32 size)
// whenever reading fractions of bytes. The low bits always come from the next byte
// while the high bits come from the current byte
u8 getBits32(u8 *address, u32 advance)
u8 __fastcall getBits32(u8 *address, u32 advance)
{
register u32 mask, shift=0;
u8* readpos;
@ -1078,7 +1077,7 @@ u8 getBits32(u8 *address, u32 advance)
return 1;
}
u8 getBits16(u8 *address, u32 advance)
__forceinline u8 __fastcall getBits16(u8 *address, u32 advance)
{
register u32 mask, shift=0;
u8* readpos;
@ -1108,7 +1107,7 @@ u8 getBits16(u8 *address, u32 advance)
return 1;
}
u8 getBits8(u8 *address, u32 advance)
u8 __fastcall getBits8(u8 *address, u32 advance)
{
register u32 mask, shift=0;
u8* readpos;
@ -1135,7 +1134,7 @@ u8 getBits8(u8 *address, u32 advance)
return 1;
}
int getBits(u8 *address, u32 size, u32 advance)
int __fastcall getBits(u8 *address, u32 size, u32 advance)
{
register u32 mask = 0, shift=0, howmuch;
u8* oldbits, *oldaddr = address;
@ -1382,7 +1381,7 @@ int FIFOto_write(u32* pMem, int size)
{ \
int qwc = ipu1dma->qwc; \
pMem = (u32*)dmaGetAddr(ipu1dma->madr); \
if (pMem == NULL) { SysPrintf("ipu1dma NULL!\n"); return totalqwc; } \
if (pMem == NULL) { Console::Error("ipu1dma NULL!"); return totalqwc; } \
qwc = FIFOto_write(pMem, qwc); \
ipu1dma->madr += qwc<< 4; \
ipu1dma->qwc -= qwc; \

View File

@ -217,15 +217,15 @@ namespace Dynarec
extern void IPUCMD_WRITE(u32 val);
extern void ipuSoftReset();
extern u16 FillInternalBuffer(u32 * pointer, u32 advance, u32 size);
extern void IPUProcessInterrupt();
extern void ipu0Interrupt();
extern void ipu1Interrupt();
u8 getBits32(u8 *address, u32 advance);
u8 getBits16(u8 *address, u32 advance);
u8 getBits8(u8 *address, u32 advance);
int getBits(u8 *address, u32 size, u32 advance);
extern u16 __fastcall FillInternalBuffer(u32 * pointer, u32 advance, u32 size);
extern u8 __fastcall getBits32(u8 *address, u32 advance);
extern u8 __fastcall getBits16(u8 *address, u32 advance);
extern u8 __fastcall getBits8(u8 *address, u32 advance);
extern int __fastcall getBits(u8 *address, u32 size, u32 advance);
// returns number of qw read
int FIFOfrom_write(u32 * value, int size);

View File

@ -92,8 +92,7 @@ namespace R5900
namespace Interpreter
{
int branch2 = 0;
static u32 branchPC;
static int branch2 = 0;
// These macros are used to assemble the repassembler functions
@ -128,21 +127,40 @@ static __forceinline void execI()
opcode.interpret();
}
static void doBranch(u32 tar) {
branch2 = cpuRegs.branch = 1;
branchPC = tar;
execI();
cpuRegs.branch = 0;
cpuRegs.pc = branchPC;
static bool EventRaised = false;
cpuRegs.cycle += cpuBlockCycles >> 3;
cpuBlockCycles &= (1<<3)-1;
IntcpuBranchTest();
static __forceinline void _doBranch_shared(u32 tar)
{
// fixme: first off, cpuRegs.pc is assigned after execI(), which breaks exceptions
// that might be thrown by execI(). I need to research how exceptions work again,
// and make sure I record the correct PC
branch2 = cpuRegs.branch = 1;
const u32 oldBranchPC = cpuRegs.pc;
execI();
// branch being 0 means an exception was thrown, since only the exception
// handler should ever clear it.
if( cpuRegs.branch != 0 )
{
cpuRegs.pc = tar;
cpuRegs.branch = 0;
}
}
void intDoBranch(u32 target) {
static void __fastcall doBranch( u32 target )
{
_doBranch_shared( target );
cpuRegs.cycle += cpuBlockCycles >> 3;
cpuBlockCycles &= (1<<3)-1;
EventRaised |= intEventTest();
}
void __fastcall intDoBranch(u32 target)
{
//SysPrintf("Interpreter Branch \n");
doBranch(target);
_doBranch_shared( target );
}
void intSetBranch() {
@ -361,7 +379,7 @@ void DSRLV(){ if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = (u64)(cpuRegs.GPR.r
*********************************************************/
#define RepBranchi32(op) \
if (cpuRegs.GPR.r[_Rs_].SD[0] op cpuRegs.GPR.r[_Rt_].SD[0]) doBranch(_BranchTarget_); \
else IntcpuBranchTest();
else intEventTest();
void BEQ() { RepBranchi32(==) } // Branch if Rs == Rt
@ -374,13 +392,13 @@ void BNE() { RepBranchi32(!=) } // Branch if Rs != Rt
#define RepZBranchi32(op) \
if(cpuRegs.GPR.r[_Rs_].SD[0] op 0) { \
doBranch(_BranchTarget_); \
} else IntcpuBranchTest();
}
#define RepZBranchLinki32(op) \
_SetLink(31); \
if(cpuRegs.GPR.r[_Rs_].SD[0] op 0) { \
doBranch(_BranchTarget_); \
} else IntcpuBranchTest();
}
void BGEZ() { RepZBranchi32(>=) } // Branch if Rs >= 0
void BGEZAL() { RepZBranchLinki32(>=) } // Branch if Rs >= 0 and link
@ -397,18 +415,18 @@ void BLTZAL() { RepZBranchLinki32(<) } // Branch if Rs < 0 and link
#define RepZBranchi32Likely(op) \
if(cpuRegs.GPR.r[_Rs_].SD[0] op 0) { \
doBranch(_BranchTarget_); \
} else { cpuRegs.pc +=4; IntcpuBranchTest(); }
} else { cpuRegs.pc +=4; intEventTest(); }
#define RepZBranchLinki32Likely(op) \
_SetLink(31); \
if(cpuRegs.GPR.r[_Rs_].SD[0] op 0) { \
doBranch(_BranchTarget_); \
} else { cpuRegs.pc +=4; IntcpuBranchTest(); }
} else { cpuRegs.pc +=4; intEventTest(); }
#define RepBranchi32Likely(op) \
if(cpuRegs.GPR.r[_Rs_].SD[0] op cpuRegs.GPR.r[_Rt_].SD[0]) { \
doBranch(_BranchTarget_); \
} else { cpuRegs.pc +=4; IntcpuBranchTest(); }
} else { cpuRegs.pc +=4; intEventTest(); }
void BEQL() { RepBranchi32Likely(==) } // Branch if Rs == Rt
@ -980,29 +998,56 @@ void MTSAH() {
////////////////////////////////////////////////////////
void intAlloc() {
// fixme : detect cpu for use the optimaze asm code
void intAlloc()
{
// fixme : detect cpu for use the optimize asm code
}
void intReset() {
void intReset()
{
cpuRegs.branch = 0;
branch2 = 0;
}
void intExecute() {
for (;;) execI();
bool intEventTest()
{
// Perform counters, ints, and IOP updates:
return _cpuBranchTest_Shared();
}
static void intExecuteBlock() {
void intExecute()
{
g_EEFreezeRegs = false;
// Mem protection should be handled by the caller here so that it can be
// done in a more optimized fashion.
EventRaised = false;
while( !EventRaised )
{
execI();
}
}
static void intExecuteBlock()
{
g_EEFreezeRegs = false;
PCSX2_MEM_PROTECT_BEGIN()
branch2 = 0;
while (!branch2) execI();
PCSX2_MEM_PROTECT_END()
}
void intStep() {
void intStep()
{
g_EEFreezeRegs = false;
execI();
}
void intClear(u32 Addr, u32 Size) {
void intClear(u32 Addr, u32 Size)
{
}
void intShutdown() {

View File

@ -95,7 +95,6 @@ extern SessionOverrideFlags g_Session;
#define PCSX2_EEREC 0x10
#define PCSX2_VU0REC 0x20
#define PCSX2_VU1REC 0x40
#define PCSX2_COP2REC 0x80
#define PCSX2_FRAMELIMIT_MASK 0xc00
#define PCSX2_FRAMELIMIT_NORMAL 0x000
#define PCSX2_FRAMELIMIT_LIMIT 0x400

View File

@ -51,9 +51,6 @@ PCSX2_ALIGNED16(psxRegisters psxRegs);
void psxReset()
{
psxCpu = CHECK_EEREC ? &psxRec : &psxInt;
psxCpu->Reset();
memzero_obj(psxRegs);
psxRegs.pc = 0xbfc00000; // Start in bootstrap

View File

@ -27,8 +27,6 @@
#include "GS.h"
#include "IPU/IPU.h"
#include "iVUzerorec.h" // for SuperVUReset
#include "Paths.h"
namespace R5900
@ -45,7 +43,7 @@ PCSX2_ALIGNED16(tlbs tlb[48]);
PCSX2_ALIGNED16(GPR_reg64 g_cpuConstRegs[32]) = {0};
u32 g_cpuHasConstReg = 0, g_cpuFlushedConstReg = 0;
R5900cpu *Cpu;
R5900cpu *Cpu = NULL;
u32 bExecBIOS = 0; // set if the BIOS has already been executed
@ -80,19 +78,16 @@ void cpuReset()
cpuIsInitialized = true;
}
Cpu = CHECK_EEREC ? &recCpu : &intCpu;
// safeguard the VUcpu structs. None of the memReset ops should try to
// use them, and this ensures if they do it'll assert/DEP.
CpuVU0 = CpuVU1 = NULL;
#ifdef PCSX2_VIRTUAL_MEM
// VM Builds require the exception handler during memInit/Reset operations and
// during the savestate load/save code.
PCSX2_MEM_PROTECT_BEGIN();
#endif
memReset();
psxMemReset();
vuMicroMemReset();
Cpu->Reset();
memset(&cpuRegs, 0, sizeof(cpuRegs));
memset(&fpuRegs, 0, sizeof(fpuRegs));
memset(&tlb, 0, sizeof(tlb));
@ -114,17 +109,15 @@ void cpuReset()
if( CHECK_EE_CYCLERATE > 1 )
eeWaitCycles += 1024;
// SuperVUreset will do nothing is none of the recs are initialized.
Dynarec::SuperVUReset(-1);
vu0Reset();
vu1Reset();
hwReset();
vif0Reset();
vif1Reset();
rcntInit();
psxReset();
#ifdef PCSX2_VIRTUAL_MEM
PCSX2_MEM_PROTECT_END();
#endif
}
void cpuShutdown()
@ -142,7 +135,11 @@ void cpuShutdown()
//Cpu->Shutdown();
}
void cpuException(u32 code, u32 bd) {
void cpuException(u32 code, u32 bd)
{
cpuRegs.branch = 0; // Tells the interpreter that an exception occurred during a branch.
u32 offset;
cpuRegs.CP0.n.Cause = code & 0xffff;
@ -642,10 +639,6 @@ void cpuTestHwInts() {
void cpuExecuteBios()
{
// filter CPU options
if( CHECK_EEREC ) Config.Options |= PCSX2_COP2REC;
else Config.Options &= ~PCSX2_COP2REC;
// Set the video mode to user's default request:
// (right now we always default to NTSC)
gsSetVideoRegionType( Config.PsxType & 1 );
@ -680,17 +673,6 @@ void cpuExecuteBios()
//GSprintf(5, "PCSX2 " PCSX2_VERSION "\nExecuteBios Complete\n");
}
// for interpreter only
void IntcpuBranchTest()
{
g_EEFreezeRegs = false;
// Perform counters, ints, and IOP updates:
_cpuBranchTest_Shared();
g_EEFreezeRegs = true;
}
__forceinline void CPU_INT( u32 n, s32 ecycle)
{
cpuRegs.interrupt|= 1 << n;

View File

@ -223,7 +223,6 @@ void cpuExecuteBios();
void cpuException(u32 code, u32 bd);
void cpuTlbMissR(u32 addr, u32 bd);
void cpuTlbMissW(u32 addr, u32 bd);
void IntcpuBranchTest();
extern void cpuTestHwInts();
extern bool _cpuBranchTest_Shared(); // for internal use by the Dynarecs and Ints inside R5900:
@ -237,10 +236,14 @@ extern void cpuTestTIMRInts();
namespace Interpreter
{
void intDoBranch(u32 target);
bool intEventTest();
void intSetBranch();
void intExecuteVU0Block();
void intExecuteVU1Block();
// This is a special form of the interpreter's doBranch that is run from various
// parts of the Recs (namely COP0's branch codes and stuff).
void __fastcall intDoBranch(u32 target);
}
void JumpCheckSym(u32 addr, u32 pc);

View File

@ -110,6 +110,12 @@ void SaveState::FreezeAll()
if( IsLoading() )
PreLoadPrep();
#ifdef PCSX2_VIRTUAL_MEM
// VM Builds require the exception handler during memInit/Reset operations and
// during the savestate load/save code.
PCSX2_MEM_PROTECT_BEGIN();
#endif
FreezeMem(PS2MEM_BASE, Ps2MemSize::Base); // 32 MB main memory
FreezeMem(PS2MEM_ROM, Ps2MemSize::Rom); // 4 mb rom memory
FreezeMem(PS2MEM_ROM1, Ps2MemSize::Rom1); // 256kb rom1 memory
@ -159,6 +165,10 @@ void SaveState::FreezeAll()
FreezePlugin( "DEV9", DEV9freeze );
FreezePlugin( "USB", USBfreeze );
#ifdef PCSX2_VIRTUAL_MEM
PCSX2_MEM_PROTECT_END();
#endif
if( IsLoading() )
PostLoadPrep();
}

View File

@ -23,7 +23,9 @@
#include "VUmicro.h"
#include "Threading.h"
#include "iVUzerorec.h"
#include "iR5900.h"
#include "iVUzerorec.h" // for SuperVUReset
#include "x86/ix86/ix86.h"
@ -57,7 +59,7 @@ static void trim( string& line )
bool encountered_characters = false;
// find the start of chracters in the string
// find the start of characters in the string
while ( (beginning_of_string < string_size) && (!encountered_characters) )
{
if ( (line[ beginning_of_string ] != ' ') && (line[ beginning_of_string ] != '\t') )
@ -297,4 +299,31 @@ void SysShutdownDynarecs()
psxRec.Shutdown();
R5900::recCpu.Shutdown();
}
// Resets all PS2 cpu execution states, which does not affect that actual PS2 state/condition.
// This can be called at any time outside the context of a Cpu->Execute() block without
// bad things happening (recompilers will slow down for a brief moment since rec code blocks
// are dumped).
// Use this method to reset the recs when important global pointers like the MTGS are re-assigned.
void SysResetExecutionState()
{
if( CHECK_EEREC )
{
R5900::Cpu = &R5900::recCpu;
psxCpu = &psxRec;
}
else
{
R5900::Cpu = &R5900::intCpu;
psxCpu = &psxInt;
}
R5900::Cpu->Reset();
psxCpu->Reset();
// make sure the VU1 doesn't have lingering "skip" enabled.
vu1MicroDisableSkip();
vuMicroCpuReset();
}

View File

@ -33,6 +33,7 @@ bool SysAllocateMem(); // allocates memory for all PS2 systems; returns FALSe
void SysAllocateDynarecs(); // allocates memory for all dynarecs, and force-disables any failures.
void SysShutdownDynarecs();
void SysShutdownMem();
void SysResetExecutionState();
void *SysLoadLibrary(const char *lib); // Loads Library
void *SysLoadSym(void *lib, const char *sym); // Loads Symbol from Library

View File

@ -66,12 +66,6 @@ void vu0ResetRegs()
vif0Regs->stat &= ~4;
}
void vu0Reset()
{
CpuVU0 = CHECK_VU0REC ? &recVU0 : &intVU0;
CpuVU0->Reset();
}
void VU0MI_XGKICK() {
}

View File

@ -71,12 +71,6 @@ void vu1ResetRegs()
vif1Regs->stat &= ~4;
}
void vu1Reset()
{
CpuVU1 = CHECK_VU1REC ? &recVU1 : &intVU1;
CpuVU1->Reset();
}
static int count;
void vu1ExecMicro(u32 addr)

View File

@ -46,6 +46,9 @@ void vuMicroMemAlloc();
void vuMicroMemShutdown();
void vuMicroMemReset();
// Resets VUs and assigns the cpuVU0 / cpuVU1 pointers as according to
// the CHECK_VU0REC / CHECK_VU1REC config options.
void vuMicroCpuReset();
/////////////////////////////////////////////////////////////////
// Everything else does stuff on a per-VU basis.
@ -53,6 +56,7 @@ void vuMicroMemReset();
void iDumpVU0Registers();
void iDumpVU1Registers();
extern void (*VU0_LOWER_OPCODE[128])();
extern void (*VU0_UPPER_OPCODE[64])();
@ -86,18 +90,20 @@ extern void (*VU1regs_UPPER_FD_10_TABLE[32])(_VURegsNum *VUregsn);
extern void (*VU1regs_UPPER_FD_11_TABLE[32])(_VURegsNum *VUregsn);
// VU0
void vu0Reset();
void vu0ResetRegs();
void vu0ExecMicro(u32 addr);
void vu0Exec(VURegs* VU);
void vu0Finish();
void recResetVU0( void );
extern void vu0ResetRegs();
extern void vu0ExecMicro(u32 addr);
extern void vu0Exec(VURegs* VU);
extern void vu0Finish();
extern void recResetVU0( void );
// VU1
void vu1Reset();
void vu1ResetRegs();
void vu1ExecMicro(u32 addr);
void vu1Exec(VURegs* VU);
extern void vu1ResetRegs();
extern void vu1ExecMicro(u32 addr);
extern void vu1Exec(VURegs* VU);
extern void vu1MicroEnableSkip();
extern void vu1MicroDisableSkip();
extern bool vu1MicroIsSkipping();
void VU0_UPPER_FD_00();
void VU0_UPPER_FD_01();

View File

@ -34,6 +34,39 @@ extern PSMEMORYMAP *memLUT;
VUmicroCpu *CpuVU0;
VUmicroCpu *CpuVU1;
static void DummyExecuteVU1Block(void)
{
VU0.VI[ REG_VPU_STAT ].UL &= ~0x100;
VU1.vifRegs->stat &= ~4; // also reset the bit (grandia 3 works)
}
void vu1MicroEnableSkip()
{
CpuVU1->ExecuteBlock = DummyExecuteVU1Block;
}
void vu1MicroDisableSkip()
{
CpuVU1->ExecuteBlock = CHECK_VU1REC ? recVU1.ExecuteBlock : intVU1.ExecuteBlock;
}
bool vu1MicroIsSkipping()
{
return CpuVU1->ExecuteBlock == DummyExecuteVU1Block;
}
void vuMicroCpuReset()
{
CpuVU1 = CHECK_VU1REC ? &recVU1 : &intVU1;
CpuVU0 = CHECK_VU0REC ? &recVU0 : &intVU0;
CpuVU0->Reset();
CpuVU1->Reset();
// SuperVUreset will do nothing is none of the recs are initialized.
// But it's needed if one or the other is initialized.
Dynarec::SuperVUReset(-1);
}
void vuMicroMemAlloc()
{
#ifdef PCSX2_VIRTUAL_MEM
@ -146,8 +179,6 @@ void vuMicroMemReset()
jASSUME( VU0.Mem != NULL );
jASSUME( VU1.Mem != NULL );
PCSX2_MEM_PROTECT_BEGIN();
// === VU0 Initialization ===
memzero_obj(VU0.ACC);
memzero_obj(VU0.VF);
@ -190,7 +221,6 @@ void vuMicroMemReset()
VU1.vuExec = vu1Exec;
VU1.vifRegs = vif1Regs;
PCSX2_MEM_PROTECT_END();
}
void SaveState::vuMicroFreeze()

View File

@ -237,12 +237,6 @@ __forceinline static int _limit( int a, int max ) {
return ( a > max ? max : a );
}
void DummyExecuteVU1Block(void)
{
VU0.VI[ REG_VPU_STAT ].UL &= ~0x100;
VU1.vifRegs->stat &= ~4; // also reset the bit (grandia 3 works)
}
static void ProcessMemSkip(int size, unsigned int unpackType, const unsigned int VIFdmanum){
const VIFUnpackFuncTable *unpack;
vifStruct *vif;
@ -365,7 +359,7 @@ static void VIFunpack(u32 *data, vifCode *v, int size, const unsigned int VIFdma
assert( v->addr < memsize );
//v->addr &= 0x3fff;
if( CpuVU1->ExecuteBlock == DummyExecuteVU1Block ) {
if( vu1MicroIsSkipping() ) {
// don't process since the frame is dummy
vif->tag.addr += (size / (VIFfuncTable[ vif->cmd & 0xf ].gsize* vifRegs->cycle.wl)) * ((vifRegs->cycle.cl - vifRegs->cycle.wl)*16);
// unpacktotal += GetCPUTick()-basetick;

View File

@ -136,8 +136,6 @@ BOOL CALLBACK CpuDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam)
else if( SendDlgItemMessage(hW,IDC_CPU_FL_SKIP,BM_GETCHECK,0,0) ) newopts |= PCSX2_FRAMELIMIT_SKIP;
else if( SendDlgItemMessage(hW,IDC_CPU_FL_SKIPVU,BM_GETCHECK,0,0) ) newopts |= PCSX2_FRAMELIMIT_VUSKIP;
if( newopts & PCSX2_EEREC ) newopts |= PCSX2_COP2REC;
GetDlgItemText(hW, IDC_CUSTOMFPS, cfps, 20);
Config.CustomFps = atoi(cfps);

View File

@ -628,10 +628,7 @@ LRESULT WINAPI MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
return FALSE;
case ID_FILE_RUNCD:
g_EmulationInProgress = false;
safe_delete( g_RecoveryState );
safe_delete( g_gsRecoveryState );
ResetPlugins();
SysReset();
RunExecute( NULL );
return FALSE;
@ -647,6 +644,7 @@ LRESULT WINAPI MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
case ID_PATCHBROWSER:
DialogBox(gApp.hInstance, MAKEINTRESOURCE(IDD_PATCHBROWSER), hWnd, (DLGPROC)PatchBDlgProc);
return FALSE;
case ID_CONFIG_CONFIGURE:
Pcsx2Configure(hWnd);
ReleasePlugins();

View File

@ -24,14 +24,10 @@
#include "Common.h"
#include "PsxCommon.h"
#include "VUmicro.h"
#include "iR5900.h"
namespace R5900 { namespace Interpreter
{
extern void intExecute();
} }
using namespace R5900;
int UseGui = 1;
@ -233,12 +229,12 @@ void ExecuteCpu()
// Optimization: We hardcode two versions of the EE here -- one for recs and one for ints.
// This is because recs are performance critical, and being able to inline them into the
// function here helps considerably.
// function here helps a small bit (not much but every small bit counts!).
timeBeginPeriod( 1 );
PCSX2_MEM_PROTECT_BEGIN();
if( Cpu == &R5900::recCpu )
if( CHECK_EEREC )
{
while( !g_ReturnToGui )
{
@ -246,11 +242,11 @@ void ExecuteCpu()
SysUpdate();
}
}
else if( Cpu == &R5900::intCpu )
else
{
while( !g_ReturnToGui )
{
R5900::Interpreter::intExecute();
Cpu->Execute();
SysUpdate();
}
}
@ -286,6 +282,8 @@ void RunExecute( const char* elf_file, bool use_bios )
if (OpenPlugins(g_TestRun.ptitle) == -1)
return;
SysResetExecutionState();
if( elf_file == NULL )
{
if(g_RecoveryState != NULL)
@ -349,8 +347,8 @@ public:
// just copy the data from src to dst.
// the normal savestate doesn't expect a length prefix for internal structures,
// so don't copy that part.
u32& pluginlen = *((u32*)g_gsRecoveryState->GetPtr());
u32& gslen = *((u32*)g_gsRecoveryState->GetPtr(pluginlen+4));
const u32 pluginlen = *((u32*)g_gsRecoveryState->GetPtr());
const u32 gslen = *((u32*)g_gsRecoveryState->GetPtr(pluginlen+4));
memcpy( m_memory.GetPtr(m_idx), g_gsRecoveryState->GetPtr(pluginlen+8), gslen );
m_idx += gslen;
}
@ -364,7 +362,7 @@ public:
{
// Gs data is already in memory, so just copy from src to dest:
// length of the GS data is stored as the first u32, so use that to run the copy:
u32& len = *((u32*)g_gsRecoveryState->GetPtr());
const u32 len = *((u32*)g_gsRecoveryState->GetPtr());
memcpy( m_memory.GetPtr(m_idx), g_gsRecoveryState->GetPtr(), len+4 );
m_idx += len+4;
}
@ -748,16 +746,20 @@ void SysReset()
// Oops! (air)
StatusBar_Notice(_("Resetting..."));
Console::SetTitle(_("Resetting..."));
g_EmulationInProgress = false;
safe_delete( g_RecoveryState );
safe_delete( g_gsRecoveryState );
ResetPlugins();
ElfCRC = 0;
// Note : No need to call cpuReset() here. It gets called automatically before the
// emulator resumes execution.
StatusBar_Notice(_("Ready"));
Console::SetTitle(_("*PCSX2* Emulation state is reset."));
}
bool SysInit()

View File

@ -128,7 +128,7 @@ public:
//cpu
SetCurrentSection( "Cpu" );
Entry( "Options", Conf.Options, PCSX2_EEREC|PCSX2_VU0REC|PCSX2_VU1REC|PCSX2_COP2REC );
Entry( "Options", Conf.Options, PCSX2_EEREC|PCSX2_VU0REC|PCSX2_VU1REC );
Entry( "sseMXCSR", Conf.sseMXCSR, DEFAULT_sseMXCSR );
Entry( "sseVUMXCSR", Conf.sseVUMXCSR, DEFAULT_sseVUMXCSR );
Entry( "eeOptions", Conf.eeOptions, DEFAULT_eeOptions );

View File

@ -1742,10 +1742,15 @@ void recQFSRV()
//u8* pshift1, *pshift2, *poldptr, *pnewptr;
if ( ! _Rd_ ) return;
/*
CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED)
if( _Rs_ == 0 ) {
if( _Rs_ == 0 )
{
// Special case using the Zero register as a source.
// not Implemented yet.
MOV32MtoR(EAX, (uptr)&cpuRegs.sa);
SHR32ItoR(EAX, 3);
@ -1762,7 +1767,8 @@ CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED)
MOV8RtoM((uptr)pshift1, EAX);
x86Ptr = pnewptr;
}
else {
else
{
int t0reg = _allocTempXMMreg(XMMT_INT, -1);
MOV32MtoR(EAX, (uptr)&cpuRegs.sa);
@ -1794,7 +1800,8 @@ CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED)
_freeXMMreg(t0reg);
}
CPU_SSE_XMMCACHE_END*/
CPU_SSE_XMMCACHE_END
*/
recCall( Interp::QFSRV, _Rd_ );
}

View File

@ -48,9 +48,9 @@ namespace R5900
// to the current cpu cycle.
MOV32ItoM( (uptr)&cpuRegs.code, cpuRegs.code );
MOV32MtoR( ECX, (uptr)&cpuRegs.cycle );
MOV32MtoR( EAX, (uptr)&cpuRegs.cycle );
MOV32ItoM( (uptr)&cpuRegs.pc, pc );
MOV32RtoM( (uptr)&g_nextBranchCycle, ECX );
MOV32RtoM( (uptr)&g_nextBranchCycle, EAX );
// Might as well flush everything -- it'll all get flushed when the
// recompiler inserts the branchtest anyway.
@ -61,14 +61,9 @@ namespace R5900
void recCall( void (*func)(), int delreg )
{
// In order to make sure a branch test is performed, the nextBranchCycle is set
// to the current cpu cycle.
MOV32ItoM( (uptr)&cpuRegs.code, cpuRegs.code );
MOV32ItoM( (uptr)&cpuRegs.pc, pc );
// Might as well flush everything -- it'll all get flushed when the
// recompiler inserts the branchtest anyway.
iFlushCall(FLUSH_EVERYTHING);
if( delreg > 0 ) _deleteEEreg(delreg, 0);
CALLFunc( (uptr)func );

View File

@ -672,13 +672,14 @@ static __forceinline bool recEventTest()
__forceinline void recExecute()
{
//PCSX2_MEM_PROTECT_BEGIN()
// Mem protection should be handled by the caller here so that it can be
// done in a more optimized fashion.
while( true )
{
execute();
if( recEventTest() ) break;
}
//PCSX2_MEM_PROTECT_END()
}
static void recExecuteBlock()