mirror of https://github.com/PCSX2/pcsx2.git
Removed VU-Skip [helps simplify the frameskipper logic] -- Use the VU Cycle Stealer hack instead for better, faster, more stable speedups of the VU1 unit.
git-svn-id: http://pcsx2.googlecode.com/svn/trunk@1114 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
f8f4c7f136
commit
a69cfcc464
|
@ -54,7 +54,6 @@ extern SessionOverrideFlags g_Session;
|
|||
#define PCSX2_FRAMELIMIT_NORMAL 0x000
|
||||
#define PCSX2_FRAMELIMIT_LIMIT 0x400
|
||||
#define PCSX2_FRAMELIMIT_SKIP 0x800
|
||||
#define PCSX2_FRAMELIMIT_VUSKIP 0xc00
|
||||
|
||||
#define CHECK_FRAMELIMIT (Config.Options&PCSX2_FRAMELIMIT_MASK)
|
||||
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
using namespace Threading;
|
||||
|
||||
extern u8 psxhblankgate;
|
||||
u32 g_vu1SkipCount; // number of frames to disable/skip VU1
|
||||
|
||||
static const uint EECNT_FUTURE_TARGET = 0x10000000;
|
||||
|
||||
|
@ -50,8 +49,6 @@ SyncCounter vsyncCounter;
|
|||
u32 nextsCounter; // records the cpuRegs.cycle value of the last call to rcntUpdate()
|
||||
s32 nextCounter; // delta from nextsCounter, in cycles, until the next rcntUpdate()
|
||||
|
||||
// VUSkip Locals and Globals
|
||||
|
||||
void rcntReset(int index) {
|
||||
counters[index].count = 0;
|
||||
counters[index].sCycleT = cpuRegs.cycle;
|
||||
|
@ -264,9 +261,6 @@ u32 UpdateVSyncRate()
|
|||
m_iStart = GetCPUTicks();
|
||||
cpuRcntSet();
|
||||
|
||||
// Initialize VU Skip Stuff...
|
||||
g_vu1SkipCount = 0;
|
||||
|
||||
return (u32)m_iTicks;
|
||||
}
|
||||
|
||||
|
@ -363,17 +357,7 @@ static __forceinline void VSyncEnd(u32 sCycle)
|
|||
|
||||
iFrame++;
|
||||
|
||||
if( g_vu1SkipCount > 0 )
|
||||
{
|
||||
gsPostVsyncEnd( false );
|
||||
AtomicDecrement( g_vu1SkipCount );
|
||||
vu1MicroEnableSkip();
|
||||
}
|
||||
else
|
||||
{
|
||||
gsPostVsyncEnd( true );
|
||||
vu1MicroDisableSkip();
|
||||
}
|
||||
gsPostVsyncEnd( true );
|
||||
|
||||
hwIntcIrq(INTC_VBLANK_E); // HW Irq
|
||||
psxVBlankEnd(); // psxCounters vBlank End
|
||||
|
|
41
pcsx2/GS.cpp
41
pcsx2/GS.cpp
|
@ -165,16 +165,10 @@ void gsSetVideoRegionType( u32 isPal )
|
|||
// Make sure framelimiter options are in sync with the plugin's capabilities.
|
||||
void gsInit()
|
||||
{
|
||||
switch(CHECK_FRAMELIMIT)
|
||||
if( (CHECK_FRAMELIMIT == PCSX2_FRAMELIMIT_SKIP) && (GSsetFrameSkip == NULL) )
|
||||
{
|
||||
case PCSX2_FRAMELIMIT_SKIP:
|
||||
case PCSX2_FRAMELIMIT_VUSKIP:
|
||||
if( GSsetFrameSkip == NULL )
|
||||
{
|
||||
Config.Options &= ~PCSX2_FRAMELIMIT_MASK;
|
||||
Console::WriteLn("Notice: Disabling frameskip -- GS plugin does not support it.");
|
||||
}
|
||||
break;
|
||||
Config.Options &= ~PCSX2_FRAMELIMIT_MASK;
|
||||
Console::WriteLn("Notice: Disabling frameskip -- GS plugin does not support it.");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -619,8 +613,7 @@ __forceinline void gsFrameSkip( bool forceskip )
|
|||
static u8 FramesToRender = 0;
|
||||
static u8 FramesToSkip = 0;
|
||||
|
||||
if( CHECK_FRAMELIMIT != PCSX2_FRAMELIMIT_SKIP &&
|
||||
CHECK_FRAMELIMIT != PCSX2_FRAMELIMIT_VUSKIP ) return;
|
||||
if( CHECK_FRAMELIMIT != PCSX2_FRAMELIMIT_SKIP ) return;
|
||||
|
||||
// FrameSkip and VU-Skip Magic!
|
||||
// Skips a sequence of consecutive frames after a sequence of rendered frames
|
||||
|
@ -652,14 +645,6 @@ __forceinline void gsFrameSkip( bool forceskip )
|
|||
return;
|
||||
}
|
||||
|
||||
// if we've already given the EE a skipcount assignment then don't do anything more.
|
||||
// Otherwise we could start compounding the issue and skips would be too long.
|
||||
if( g_vu1SkipCount > 0 )
|
||||
{
|
||||
//Console::Status("- Already Assigned a Skipcount.. %d", params g_vu1SkipCount );
|
||||
return;
|
||||
}
|
||||
|
||||
if( FramesToRender == 0 )
|
||||
{
|
||||
// -- Standard operation section --
|
||||
|
@ -680,20 +665,9 @@ __forceinline void gsFrameSkip( bool forceskip )
|
|||
if( (m_justSkipped && (sSlowDeltaTime > m_iSlowTicks)) ||
|
||||
(sSlowDeltaTime > m_iSlowTicks*2) )
|
||||
{
|
||||
//Console::Status( "Frameskip Initiated! Lateness: %d", params (int)( (sSlowDeltaTime*100) / m_iSlowTicks ) );
|
||||
|
||||
if( CHECK_FRAMELIMIT == PCSX2_FRAMELIMIT_VUSKIP )
|
||||
{
|
||||
// For best results we have to wait for the EE to
|
||||
// tell us when to skip, so that VU skips are synched with GS skips.
|
||||
AtomicExchangeAdd( g_vu1SkipCount, yesSkipFrames+1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
GSsetFrameSkip(1);
|
||||
FramesToRender = noSkipFrames+1;
|
||||
FramesToSkip = yesSkipFrames;
|
||||
}
|
||||
GSsetFrameSkip(1);
|
||||
FramesToRender = noSkipFrames+1;
|
||||
FramesToSkip = yesSkipFrames;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -771,7 +745,6 @@ void gsPostVsyncEnd( bool updategs )
|
|||
|
||||
void _gs_ResetFrameskip()
|
||||
{
|
||||
g_vu1SkipCount = 0; // set to 0 so that EE will re-enable the VU at the next vblank.
|
||||
GSsetFrameSkip( 0 );
|
||||
}
|
||||
|
||||
|
|
|
@ -331,7 +331,6 @@ void mfifoGIFtransfer(int qwc);
|
|||
int _GIFchain();
|
||||
void gifMFIFOInterrupt();
|
||||
|
||||
extern u32 g_vu1SkipCount;
|
||||
extern u32 CSRw;
|
||||
extern u64 m_iSlowStart;
|
||||
|
||||
|
|
|
@ -39,8 +39,6 @@ void OnCpu_Ok(GtkButton *button, gpointer user_data)
|
|||
newopts |= PCSX2_FRAMELIMIT_LIMIT;
|
||||
else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(CpuDlg, "GtkRadioButton_LimitFS"))))
|
||||
newopts |= PCSX2_FRAMELIMIT_SKIP;
|
||||
else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(CpuDlg, "GtkRadioButton_VUSkip"))))
|
||||
newopts |= PCSX2_FRAMELIMIT_VUSKIP;
|
||||
|
||||
Config.CustomFps = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(lookup_widget(CpuDlg, "CustomFPSLimit")));
|
||||
Config.CustomFrameSkip = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(lookup_widget(CpuDlg, "FrameThreshold")));
|
||||
|
@ -88,7 +86,6 @@ void OnConf_Cpu(GtkMenuItem *menuitem, gpointer user_data)
|
|||
gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(lookup_widget(CpuDlg, "GtkRadioButton_LimitNormal")), CHECK_FRAMELIMIT == PCSX2_FRAMELIMIT_NORMAL);
|
||||
gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(lookup_widget(CpuDlg, "GtkRadioButton_LimitLimit")), CHECK_FRAMELIMIT == PCSX2_FRAMELIMIT_LIMIT);
|
||||
gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(lookup_widget(CpuDlg, "GtkRadioButton_LimitFS")), CHECK_FRAMELIMIT == PCSX2_FRAMELIMIT_SKIP);
|
||||
gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(lookup_widget(CpuDlg, "GtkRadioButton_VUSkip")), CHECK_FRAMELIMIT == PCSX2_FRAMELIMIT_VUSKIP);
|
||||
|
||||
sprintf(str, "Cpu Vendor: %s", cpuinfo.x86ID);
|
||||
gtk_label_set_text(GTK_LABEL(lookup_widget(CpuDlg, "GtkLabel_CpuVendor")), str);
|
||||
|
|
|
@ -447,12 +447,19 @@ void CycleFrameLimit(int dir)
|
|||
newFrameLimit = 0;
|
||||
} else
|
||||
newFrameLimit = oldFrameLimit;
|
||||
} else if (dir > 0) {
|
||||
// next
|
||||
newFrameLimit = (curFrameLimit + PCSX2_FRAMELIMIT_LIMIT) & PCSX2_FRAMELIMIT_MASK;
|
||||
} else {
|
||||
// previous
|
||||
newFrameLimit = (curFrameLimit + PCSX2_FRAMELIMIT_VUSKIP) & PCSX2_FRAMELIMIT_MASK;
|
||||
}
|
||||
else if (dir > 0) // next
|
||||
{
|
||||
newFrameLimit = curFrameLimit + PCSX2_FRAMELIMIT_LIMIT;
|
||||
if( newFrameLimit > PCSX2_FRAMELIMIT_SKIP )
|
||||
newFrameLimit = 0;
|
||||
}
|
||||
else // previous
|
||||
{
|
||||
if( newFrameLimit == 0 )
|
||||
newFrameLimit = PCSX2_FRAMELIMIT_SKIP;
|
||||
else
|
||||
newFrameLimit = curFrameLimit - PCSX2_FRAMELIMIT_LIMIT;
|
||||
}
|
||||
|
||||
newOptions = (Config.Options & ~PCSX2_FRAMELIMIT_MASK) | newFrameLimit;
|
||||
|
@ -467,7 +474,6 @@ void CycleFrameLimit(int dir)
|
|||
limitMsg = "Limit";
|
||||
break;
|
||||
case PCSX2_FRAMELIMIT_SKIP:
|
||||
case PCSX2_FRAMELIMIT_VUSKIP:
|
||||
if( GSsetFrameSkip == NULL )
|
||||
{
|
||||
newOptions &= ~PCSX2_FRAMELIMIT_MASK;
|
||||
|
@ -479,7 +485,7 @@ void CycleFrameLimit(int dir)
|
|||
// When enabling Skipping we have to make sure Skipper (GS) and Limiter (EE)
|
||||
// are properly synchronized.
|
||||
gsDynamicSkipEnable();
|
||||
limitMsg = ((newOptions & PCSX2_FRAMELIMIT_MASK) == PCSX2_FRAMELIMIT_SKIP) ? "Skip" : "VUSkip";
|
||||
limitMsg = "Skip";
|
||||
}
|
||||
|
||||
break;
|
||||
|
|
|
@ -319,9 +319,6 @@ void SysClearExecutionCache()
|
|||
psxCpu->Reset();
|
||||
|
||||
vuMicroCpuReset();
|
||||
|
||||
// make sure the VU1 doesn't have lingering "skip" enabled.
|
||||
vu1MicroDisableSkip();
|
||||
}
|
||||
|
||||
__forceinline void SysUpdate()
|
||||
|
|
|
@ -123,10 +123,6 @@ 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();
|
||||
void VU0_UPPER_FD_10();
|
||||
|
|
|
@ -38,21 +38,6 @@ static void DummyExecuteVU1Block(void)
|
|||
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()
|
||||
{
|
||||
CpuVU0 = CHECK_VU0REC ? recVU0 : intVU0;
|
||||
|
|
|
@ -580,13 +580,6 @@ static void VIFunpack(u32 *data, vifCode *v, unsigned int size, const unsigned i
|
|||
vif = &vif1;
|
||||
vifRow = g_vifRow1;
|
||||
assert(v->addr < memsize);
|
||||
|
||||
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);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
dest = (u32*)(VU->Mem + v->addr);
|
||||
|
|
|
@ -134,7 +134,6 @@ BOOL CALLBACK CpuDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|||
if( SendDlgItemMessage(hW,IDC_CPU_FL_NORMAL,BM_GETCHECK,0,0) ) newopts |= PCSX2_FRAMELIMIT_NORMAL;
|
||||
else if( SendDlgItemMessage(hW,IDC_CPU_FL_LIMIT,BM_GETCHECK,0,0) ) newopts |= PCSX2_FRAMELIMIT_LIMIT;
|
||||
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;
|
||||
|
||||
GetDlgItemText(hW, IDC_CUSTOMFPS, cfps, 20);
|
||||
Config.CustomFps = atoi(cfps);
|
||||
|
|
|
@ -828,7 +828,7 @@ BEGIN
|
|||
CONTROL "EE Counters log",IDC_EECNTLOG,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,5,140,64,11
|
||||
END
|
||||
|
||||
IDD_CPUDLG DIALOGEX 0, 0, 563, 321
|
||||
IDD_CPUDLG DIALOGEX 0, 0, 563, 305
|
||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
|
@ -843,13 +843,11 @@ BEGIN
|
|||
CONTROL "Normal - All frames are rendered as fast as possible.",IDC_CPU_FL_NORMAL,
|
||||
"Button",BS_AUTORADIOBUTTON | BS_MULTILINE | WS_GROUP,309,17,221,17
|
||||
CONTROL "Limit - Force frames to normal speeds if too fast.\n (You can set a custom FPS limit below.)",IDC_CPU_FL_LIMIT,
|
||||
"Button",BS_AUTORADIOBUTTON | BS_MULTILINE,309,33,222,15
|
||||
"Button",BS_AUTORADIOBUTTON | BS_MULTILINE,309,37,222,15
|
||||
CONTROL "Frame Skip - In order to achieve normal speeds,\n some frames are skipped (fast).\n Fps displayed counts skipped frames too.",IDC_CPU_FL_SKIP,
|
||||
"Button",BS_AUTORADIOBUTTON | BS_MULTILINE,309,48,221,28
|
||||
CONTROL "VU Skip - Same as 'Frame Skip', but tries to skip more.\n Artifacts might be present, but will be faster.",IDC_CPU_FL_SKIPVU,
|
||||
"Button",BS_AUTORADIOBUTTON | BS_MULTILINE,309,75,220,25
|
||||
DEFPUSHBUTTON "OK",IDOK,210,298,61,14
|
||||
PUSHBUTTON "Cancel",IDCANCEL,282,298,61,14,NOT WS_TABSTOP
|
||||
"Button",BS_AUTORADIOBUTTON | BS_MULTILINE,309,56,221,28
|
||||
DEFPUSHBUTTON "OK",IDOK,210,287,61,14
|
||||
PUSHBUTTON "Cancel",IDCANCEL,282,287,61,14,NOT WS_TABSTOP
|
||||
LTEXT "CPU Vendor",IDC_VENDORNAME,12,23,88,8
|
||||
LTEXT "Family",IDC_FAMILYNAME,12,41,88,8
|
||||
LTEXT "Cpu Speed",IDC_CPUSPEEDNAME,12,60,88,8
|
||||
|
@ -860,19 +858,19 @@ BEGIN
|
|||
GROUPBOX "VU Recompilers - All options are set by default",IDC_CPU_VUGROUP,7,119,265,46
|
||||
LTEXT "Features",IDC_FEATURESNAME,12,78,88,8
|
||||
GROUPBOX "",IDC_STATIC,7,7,265,90
|
||||
LTEXT "Custom FPS Limit (0=auto):",IDC_CUSTOM_FPS,327,113,124,12
|
||||
EDITTEXT IDC_CUSTOMFPS,456,113,53,13,ES_AUTOHSCROLL | ES_NUMBER
|
||||
EDITTEXT IDC_CUSTOM_FRAMESKIP,456,130,53,13,ES_AUTOHSCROLL | ES_NUMBER
|
||||
EDITTEXT IDC_CUSTOM_CONSECUTIVE_FRAMES,456,148,53,13,ES_AUTOHSCROLL | ES_NUMBER
|
||||
LTEXT "Skip Frames when slower than:\n(See Note 1)",IDC_FRAMESKIP_LABEL1,327,129,106,20
|
||||
LTEXT "Consecutive Frames before skipping:\n(See Note 2)",IDC_FRAMESKIP_LABEL2,327,149,121,17
|
||||
GROUPBOX "Frame Limiting (F4 key switches the mode in-game!)",IDC_FRAMELIMIT,301,7,250,280
|
||||
GROUPBOX "Detailed Settings",IDC_FRAMELIMIT_OPTIONS,310,99,234,185
|
||||
LTEXT "*Note 1: Will only skip when slower than this fps number.\n (0 = Auto) ; (9999 = Forced-Frameskip regardless of speed.)\n (e.g. If set to 45, will only skip when slower than 45fps.)",IDC_FRAMESKIP_LABEL3,318,189,217,26
|
||||
LTEXT "*Note 2: Will render this number of consecutive frames before\n skipping the next frame. (0=default)\n (e.g. If set to 2, will render 2 frames before skipping 1.)",IDC_FRAMESKIP_LABEL4,318,216,217,25
|
||||
EDITTEXT IDC_CUSTOM_CONSECUTIVE_SKIP,456,166,53,13,ES_AUTOHSCROLL | ES_NUMBER
|
||||
LTEXT "Consecutive Frames to skip:\n(See Note 3)",IDC_FRAMESKIP_LABEL5,327,167,121,17
|
||||
LTEXT "*Note 3: Will skip this number of frames before\n rendering the next sequence of frames. (0=default)\n (e.g. If set to 2, will skip 2 consecutive frames whenever its time\n to skip.)",IDC_FRAMESKIP_LABEL6,318,244,217,32
|
||||
LTEXT "Custom FPS Limit (0=auto):",IDC_CUSTOM_FPS,327,103,124,12
|
||||
EDITTEXT IDC_CUSTOMFPS,456,103,53,13,ES_AUTOHSCROLL | ES_NUMBER
|
||||
EDITTEXT IDC_CUSTOM_FRAMESKIP,456,121,53,13,ES_AUTOHSCROLL | ES_NUMBER
|
||||
EDITTEXT IDC_CUSTOM_CONSECUTIVE_FRAMES,456,139,53,13,ES_AUTOHSCROLL | ES_NUMBER
|
||||
LTEXT "Skip Frames when slower than:\n(See Note 1)",IDC_FRAMESKIP_LABEL1,327,119,106,20
|
||||
LTEXT "Consecutive Frames before skipping:\n(See Note 2)",IDC_FRAMESKIP_LABEL2,327,139,121,17
|
||||
GROUPBOX "Frame Limiting (F4 key switches the mode in-game!)",IDC_FRAMELIMIT,301,7,250,274
|
||||
GROUPBOX "Detailed Settings",IDC_FRAMELIMIT_OPTIONS,310,89,234,185
|
||||
LTEXT "*Note 1: Will only skip when slower than this fps number.\n (0 = Auto) ; (9999 = Forced-Frameskip regardless of speed.)\n (e.g. If set to 45, will only skip when slower than 45fps.)",IDC_FRAMESKIP_LABEL3,318,179,217,26
|
||||
LTEXT "*Note 2: Will render this number of consecutive frames before\n skipping the next frame. (0=default)\n (e.g. If set to 2, will render 2 frames before skipping 1.)",IDC_FRAMESKIP_LABEL4,318,206,217,25
|
||||
EDITTEXT IDC_CUSTOM_CONSECUTIVE_SKIP,456,157,53,13,ES_AUTOHSCROLL | ES_NUMBER
|
||||
LTEXT "Consecutive Frames to skip:\n(See Note 3)",IDC_FRAMESKIP_LABEL5,327,157,121,17
|
||||
LTEXT "*Note 3: Will skip this number of frames before\n rendering the next sequence of frames. (0=default)\n (e.g. If set to 2, will skip 2 consecutive frames whenever its time\n to skip.)",IDC_FRAMESKIP_LABEL6,318,234,217,32
|
||||
END
|
||||
|
||||
|
||||
|
|
|
@ -424,7 +424,7 @@ PCSX2_ALIGNED16( static u8 manual_counter[Ps2MemSize::Base >> 12] );
|
|||
////////////////////////////////////////////////////
|
||||
void recResetEE( void )
|
||||
{
|
||||
DbgCon::Status( "iR5900-32 > Resetting recompiler memory and structures." );
|
||||
Console::Status( "Issuing EE/iR5900-32 Recompiler Reset [mem/structure cleanup]" );
|
||||
|
||||
maxrecmem = 0;
|
||||
|
||||
|
@ -1258,7 +1258,6 @@ void recRecompile( const u32 startpc )
|
|||
|
||||
// if recPtr reached the mem limit reset whole mem
|
||||
if ( ( (uptr)recPtr - (uptr)recMem ) >= REC_CACHEMEM-0x40000 || dumplog == 0xffffffff) {
|
||||
DevCon::WriteLn( "EE Recompiler data reset" );
|
||||
recResetEE();
|
||||
}
|
||||
if ( ( (uptr)recStackPtr - (uptr)recStack ) >= RECSTACK_SIZE-0x100 ) {
|
||||
|
@ -1334,10 +1333,7 @@ void recRecompile( const u32 startpc )
|
|||
willbranch3 = 1;
|
||||
s_nEndBlock = i;
|
||||
|
||||
// Log the pagesplits verbosely for now, until we see if any games are affected
|
||||
// adversely by excessive splits.
|
||||
DevCon::Notice( "Pagesplit @ %08X : size=%d insts", params startpc, (i-startpc) / 4 );
|
||||
|
||||
//DevCon::Notice( "Pagesplit @ %08X : size=%d insts", params startpc, (i-startpc) / 4 );
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1508,86 +1504,80 @@ StartRecomp:
|
|||
iDumpBlock(startpc, recPtr);
|
||||
#endif
|
||||
|
||||
// fixme! The following manual/protected block code can be greatly simplified now.
|
||||
// It originally had to account for cross-page blocks, but we have since guaranteed
|
||||
// that no block will cross a page boundary.
|
||||
|
||||
u32 sz = (s_nEndBlock-startpc) >> 2;
|
||||
u32 inpage_ptr = HWADDR(startpc);
|
||||
u32 inpage_sz = sz*4;
|
||||
|
||||
while(inpage_sz)
|
||||
{
|
||||
int PageType = mmap_GetRamPageInfo((u32*)PSM(inpage_ptr));
|
||||
u32 inpage_offs = inpage_ptr & 0xFFF;
|
||||
u32 pgsz = std::min(0x1000 - inpage_offs, inpage_sz);
|
||||
// note: blocks are guaranteed to reside within the confines of a single page.
|
||||
|
||||
if(PageType!=-1)
|
||||
const int PageType = mmap_GetRamPageInfo((u32*)PSM(inpage_ptr));
|
||||
const u32 inpage_offs = inpage_ptr & 0xFFF;
|
||||
//const u32 pgsz = std::min(0x1000 - inpage_offs, inpage_sz);
|
||||
const u32 pgsz = inpage_sz;
|
||||
|
||||
if(PageType!=-1)
|
||||
{
|
||||
if (PageType==0) {
|
||||
mmap_MarkCountedRamPage(PSM(inpage_ptr),inpage_ptr&~0xFFF);
|
||||
manual_page[inpage_ptr >> 12] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (PageType==0) {
|
||||
mmap_MarkCountedRamPage(PSM(inpage_ptr),inpage_ptr&~0xFFF);
|
||||
manual_page[inpage_ptr >> 12] = 0;
|
||||
xMOV( ecx, inpage_ptr );
|
||||
xMOV( edx, pgsz / 4 );
|
||||
//xMOV( eax, startpc ); // uncomment this to access startpc (as eax) in dyna_block_discard
|
||||
|
||||
u32 lpc = inpage_ptr;
|
||||
u32 stg = pgsz;
|
||||
while(stg>0)
|
||||
{
|
||||
xCMP( ptr32[PSM(lpc)], *(u32*)PSM(lpc) );
|
||||
xJNE( dyna_block_discard );
|
||||
|
||||
stg -= 4;
|
||||
lpc += 4;
|
||||
}
|
||||
|
||||
// Tweakpoint! 3 is a 'magic' number representing the number of times a counted block
|
||||
// is re-protected before the recompiler gives up and sets it up as an uncounted (permanent)
|
||||
// manual block. Higher thresholds result in more recompilations for blocks that share code
|
||||
// and data on the same page. Side effects of a lower threshold: over extended gameplay
|
||||
// with several map changes, a game's overall performance could degrade.
|
||||
|
||||
// (ideally, perhaps, manual_counter should be reset to 0 every few minutes?)
|
||||
|
||||
if (startpc != 0x81fc0 && manual_counter[inpage_ptr >> 12] <= 3) {
|
||||
|
||||
// Counted blocks add a weighted (by block size) value into manual_page each time they're
|
||||
// run. If the block gets run a lot, it resets and re-protects itself in the hope
|
||||
// that whatever forced it to be manually-checked before was a 1-time deal.
|
||||
|
||||
// Counted blocks have a secondary threshold check in manual_counter, which forces a block
|
||||
// to 'uncounted' mode if it's recompiled several time. This protects against excessive
|
||||
// recompilation of blocks that reside on the same codepage as data.
|
||||
|
||||
// fixme? Currently this algo is kinda dumb and results in the forced recompilation of a
|
||||
// lot of blocks before it decides to mark a 'busy' page as uncounted. There might be
|
||||
// be a more clever approach that could streamline this process, by doing a first-pass
|
||||
// test using the vtlb memory protection (without recompilation!) to reprotect a counted
|
||||
// block. But unless a new also is relatively simple in implementation, it's probably
|
||||
// not worth the effort (tests show that we have lots of recompiler memory to spare, and
|
||||
// that the current amount of recompilation is fairly cheap).
|
||||
|
||||
xADD(ptr16[&manual_page[inpage_ptr >> 12]], sz);
|
||||
xJC( dyna_page_reset );
|
||||
|
||||
// note: clearcnt is measured per-page, not per-block!
|
||||
DbgCon::WriteLn( "Manual block @ %08X : size=%3d page/offs=%05X/%03X inpgsz=%d clearcnt=%d",
|
||||
params startpc, sz, inpage_ptr>>12, inpage_offs, inpage_sz, manual_counter[inpage_ptr >> 12] );
|
||||
}
|
||||
else
|
||||
{
|
||||
xMOV( ecx, inpage_ptr );
|
||||
xMOV( edx, pgsz / 4 );
|
||||
//xMOV( eax, startpc ); // uncomment this to access startpc (as eax) in dyna_block_discard
|
||||
|
||||
u32 lpc = inpage_ptr;
|
||||
u32 stg = pgsz;
|
||||
while(stg>0)
|
||||
{
|
||||
xCMP( ptr32[PSM(lpc)], *(u32*)PSM(lpc) );
|
||||
xJNE( dyna_block_discard );
|
||||
|
||||
stg -= 4;
|
||||
lpc += 4;
|
||||
}
|
||||
|
||||
// Tweakpoint! 3 is a 'magic' number representing the number of times a counted block
|
||||
// is re-protected before the recompiler gives up and sets it up as an uncounted (permanent)
|
||||
// manual block. 4 definitely seemed too high, but 2 might be better? Side effects of a
|
||||
// lower threshold: over extended gameplay with several map changes, a game's overall
|
||||
// performance could degrade.
|
||||
|
||||
// (ideally, perhaps, manual_counter should be reset to 0 every few minutes?)
|
||||
|
||||
if (startpc != 0x81fc0 && manual_counter[inpage_ptr >> 12] <= 3) {
|
||||
|
||||
// Counted blocks add a weighted (by block size) value into manual_page each time they're
|
||||
// run. If the block gets run a lot, it resets and re-protects itself in the hope
|
||||
// that whatever forced it to be manually-checked before was a 1-time deal.
|
||||
|
||||
// Counted blocks have a secondary threshold check in manual_counter, which forces a block
|
||||
// to 'uncounted' mode if it's recompiled several time. This protects against excessive
|
||||
// recompilation of blocks that reside on the same codepage as data.
|
||||
|
||||
// fixme? Currently this algo is kinda dumb and results in the forced recompilation of a
|
||||
// lot of blocks before it decides to mark a 'busy' page as uncounted. There might be
|
||||
// be a more clever approach that could streamline this process, by doing a first-pass
|
||||
// test using the vtlb memory protection (without recompilation!) to reprotect a counted
|
||||
// block. But unless a new also is relatively simple in implementation, it's probably
|
||||
// not worth the effort (tests show that we have lots of recompiler memory to spare, and
|
||||
// that the current amount of recompilation is fairly cheap).
|
||||
|
||||
xADD(ptr16[&manual_page[inpage_ptr >> 12]], sz);
|
||||
xJC( dyna_page_reset );
|
||||
|
||||
// note: clearcnt is measured per-page, not per-block!
|
||||
DbgCon::WriteLn( "Manual block @ %08X : size=%3d page/offs=%05X/%03X inpgsz=%d clearcnt=%d",
|
||||
params startpc, sz, inpage_ptr>>12, inpage_offs, inpage_sz, manual_counter[inpage_ptr >> 12] );
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgCon::Notice( "Uncounted Manual block @ %08X : size=%3d page/offs=%05X/%03X inpgsz=%d",
|
||||
params startpc, sz, inpage_ptr>>12, inpage_offs, pgsz, inpage_sz );
|
||||
}
|
||||
|
||||
DbgCon::Notice( "Uncounted Manual block @ %08X : size=%3d page/offs=%05X/%03X inpgsz=%d",
|
||||
params startpc, sz, inpage_ptr>>12, inpage_offs, pgsz, inpage_sz );
|
||||
}
|
||||
|
||||
}
|
||||
inpage_ptr += pgsz;
|
||||
inpage_sz -= pgsz;
|
||||
}
|
||||
|
||||
// Finally: Generate x86 recompiled code!
|
||||
|
|
Loading…
Reference in New Issue