Core/Jits: Adds an option to disable the register cache.
This will help to disable all inter-instruction dependencies. So android users can check if only a single instruction is broken without compiling dolphin on their own.
This commit is contained in:
parent
fe39e1e6d8
commit
3ebcc445de
|
@ -640,6 +640,8 @@ public final class SettingsFragmentPresenter
|
||||||
Setting jitSystemRegistersOff =
|
Setting jitSystemRegistersOff =
|
||||||
debugSection.getSetting(SettingsFile.KEY_DEBUG_JITSYSTEMREGISTEROFF);
|
debugSection.getSetting(SettingsFile.KEY_DEBUG_JITSYSTEMREGISTEROFF);
|
||||||
Setting jitBranchOff = debugSection.getSetting(SettingsFile.KEY_DEBUG_JITBRANCHOFF);
|
Setting jitBranchOff = debugSection.getSetting(SettingsFile.KEY_DEBUG_JITBRANCHOFF);
|
||||||
|
Setting jitRegisterCacheOff =
|
||||||
|
debugSection.getSetting(SettingsFile.KEY_DEBUG_JITREGISTERCACHEOFF);
|
||||||
|
|
||||||
sl.add(new HeaderSetting(null, null, R.string.debug_warning, 0));
|
sl.add(new HeaderSetting(null, null, R.string.debug_warning, 0));
|
||||||
|
|
||||||
|
@ -672,6 +674,9 @@ public final class SettingsFragmentPresenter
|
||||||
sl.add(new CheckBoxSetting(SettingsFile.KEY_DEBUG_JITBRANCHOFF, Settings.SECTION_DEBUG,
|
sl.add(new CheckBoxSetting(SettingsFile.KEY_DEBUG_JITBRANCHOFF, Settings.SECTION_DEBUG,
|
||||||
R.string.debug_jitbranchoff, 0, false,
|
R.string.debug_jitbranchoff, 0, false,
|
||||||
jitBranchOff));
|
jitBranchOff));
|
||||||
|
sl.add(new CheckBoxSetting(SettingsFile.KEY_DEBUG_JITREGISTERCACHEOFF, Settings.SECTION_DEBUG,
|
||||||
|
R.string.debug_jitregistercacheoff, 0, false,
|
||||||
|
jitRegisterCacheOff));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addStereoSettings(ArrayList<SettingsItem> sl)
|
private void addStereoSettings(ArrayList<SettingsItem> sl)
|
||||||
|
|
|
@ -102,6 +102,7 @@ public final class SettingsFile
|
||||||
public static final String KEY_DEBUG_JITPAIREDOFF = "JitPairedOff";
|
public static final String KEY_DEBUG_JITPAIREDOFF = "JitPairedOff";
|
||||||
public static final String KEY_DEBUG_JITSYSTEMREGISTEROFF = "JitSystemRegistersOff";
|
public static final String KEY_DEBUG_JITSYSTEMREGISTEROFF = "JitSystemRegistersOff";
|
||||||
public static final String KEY_DEBUG_JITBRANCHOFF = "JitBranchOff";
|
public static final String KEY_DEBUG_JITBRANCHOFF = "JitBranchOff";
|
||||||
|
public static final String KEY_DEBUG_JITREGISTERCACHEOFF = "JitRegisterCacheOff";
|
||||||
|
|
||||||
public static final String KEY_GCPAD_TYPE = "SIDevice";
|
public static final String KEY_GCPAD_TYPE = "SIDevice";
|
||||||
public static final String KEY_GCPAD_G_TYPE = "PadType";
|
public static final String KEY_GCPAD_G_TYPE = "PadType";
|
||||||
|
|
|
@ -254,6 +254,7 @@
|
||||||
<string name="debug_jitpairedoff">Jit Paired Disabled</string>
|
<string name="debug_jitpairedoff">Jit Paired Disabled</string>
|
||||||
<string name="debug_jitsystemregistersoffr">Jit System Registers Disabled</string>
|
<string name="debug_jitsystemregistersoffr">Jit System Registers Disabled</string>
|
||||||
<string name="debug_jitbranchoff">Jit Branch Disabled</string>
|
<string name="debug_jitbranchoff">Jit Branch Disabled</string>
|
||||||
|
<string name="debug_jitregistercacheoff">Jit Register Cache Disabled</string>
|
||||||
|
|
||||||
<!-- Miscellaneous -->
|
<!-- Miscellaneous -->
|
||||||
<string name="yes">Yes</string>
|
<string name="yes">Yes</string>
|
||||||
|
|
|
@ -352,6 +352,7 @@ void SConfig::SaveJitDebugSettings(IniFile& ini)
|
||||||
section->Set("JitPairedOff", bJITPairedOff);
|
section->Set("JitPairedOff", bJITPairedOff);
|
||||||
section->Set("JitSystemRegistersOff", bJITSystemRegistersOff);
|
section->Set("JitSystemRegistersOff", bJITSystemRegistersOff);
|
||||||
section->Set("JitBranchOff", bJITBranchOff);
|
section->Set("JitBranchOff", bJITBranchOff);
|
||||||
|
section->Set("JitRegisterCacheOff", bJITRegisterCacheOff);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SConfig::LoadSettings()
|
void SConfig::LoadSettings()
|
||||||
|
@ -644,6 +645,7 @@ void SConfig::LoadJitDebugSettings(IniFile& ini)
|
||||||
section->Get("JitPairedOff", &bJITPairedOff, false);
|
section->Get("JitPairedOff", &bJITPairedOff, false);
|
||||||
section->Get("JitSystemRegistersOff", &bJITSystemRegistersOff, false);
|
section->Get("JitSystemRegistersOff", &bJITSystemRegistersOff, false);
|
||||||
section->Get("JitBranchOff", &bJITBranchOff, false);
|
section->Get("JitBranchOff", &bJITBranchOff, false);
|
||||||
|
section->Get("JitRegisterCacheOff", &bJITRegisterCacheOff, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SConfig::ResetRunningGameMetadata()
|
void SConfig::ResetRunningGameMetadata()
|
||||||
|
@ -800,6 +802,7 @@ void SConfig::LoadDefaults()
|
||||||
bJITPairedOff = false;
|
bJITPairedOff = false;
|
||||||
bJITSystemRegistersOff = false;
|
bJITSystemRegistersOff = false;
|
||||||
bJITBranchOff = false;
|
bJITBranchOff = false;
|
||||||
|
bJITRegisterCacheOff = false;
|
||||||
|
|
||||||
ResetRunningGameMetadata();
|
ResetRunningGameMetadata();
|
||||||
}
|
}
|
||||||
|
|
|
@ -105,6 +105,7 @@ struct SConfig
|
||||||
bool bJITPairedOff = false;
|
bool bJITPairedOff = false;
|
||||||
bool bJITSystemRegistersOff = false;
|
bool bJITSystemRegistersOff = false;
|
||||||
bool bJITBranchOff = false;
|
bool bJITBranchOff = false;
|
||||||
|
bool bJITRegisterCacheOff = false;
|
||||||
|
|
||||||
bool bFastmem;
|
bool bFastmem;
|
||||||
bool bFPRF = false;
|
bool bFPRF = false;
|
||||||
|
|
|
@ -997,15 +997,23 @@ u8* Jit64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)
|
||||||
SetJumpTarget(noBreakpoint);
|
SetJumpTarget(noBreakpoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we have an input register that is going to be used again, load it pre-emptively,
|
if (SConfig::GetInstance().bJITRegisterCacheOff)
|
||||||
// even if the instruction doesn't strictly need it in a register, to avoid redundant
|
{
|
||||||
// loads later. Of course, don't do this if we're already out of registers.
|
gpr.Flush();
|
||||||
// As a bit of a heuristic, make sure we have at least one register left over for the
|
fpr.Flush();
|
||||||
// output, which needs to be bound in the actual instruction compilation.
|
}
|
||||||
// TODO: make this smarter in the case that we're actually register-starved, i.e.
|
else
|
||||||
// prioritize the more important registers.
|
{
|
||||||
gpr.PreloadRegisters(op.regsIn & op.gprInReg);
|
// If we have an input register that is going to be used again, load it pre-emptively,
|
||||||
fpr.PreloadRegisters(op.fregsIn & op.fprInXmm);
|
// even if the instruction doesn't strictly need it in a register, to avoid redundant
|
||||||
|
// loads later. Of course, don't do this if we're already out of registers.
|
||||||
|
// As a bit of a heuristic, make sure we have at least one register left over for the
|
||||||
|
// output, which needs to be bound in the actual instruction compilation.
|
||||||
|
// TODO: make this smarter in the case that we're actually register-starved, i.e.
|
||||||
|
// prioritize the more important registers.
|
||||||
|
gpr.PreloadRegisters(op.regsIn & op.gprInReg);
|
||||||
|
fpr.PreloadRegisters(op.fregsIn & op.fprInXmm);
|
||||||
|
}
|
||||||
|
|
||||||
CompileInstruction(op);
|
CompileInstruction(op);
|
||||||
|
|
||||||
|
|
|
@ -776,6 +776,13 @@ void JitArm64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)
|
||||||
js.firstFPInstructionFound = true;
|
js.firstFPInstructionFound = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (SConfig::GetInstance().bJITRegisterCacheOff)
|
||||||
|
{
|
||||||
|
gpr.Flush(FLUSH_ALL);
|
||||||
|
fpr.Flush(FLUSH_ALL);
|
||||||
|
FlushCarry();
|
||||||
|
}
|
||||||
|
|
||||||
CompileInstruction(op);
|
CompileInstruction(op);
|
||||||
if (!CanMergeNextInstructions(1) || js.op[1].opinfo->type != ::OpType::Integer)
|
if (!CanMergeNextInstructions(1) || js.op[1].opinfo->type != ::OpType::Integer)
|
||||||
FlushCarry();
|
FlushCarry();
|
||||||
|
|
|
@ -142,7 +142,7 @@ void MenuBar::OnEmulationStateChanged(Core::State state)
|
||||||
{m_jit_off, m_jit_loadstore_off, m_jit_loadstore_lbzx_off, m_jit_loadstore_lxz_off,
|
{m_jit_off, m_jit_loadstore_off, m_jit_loadstore_lbzx_off, m_jit_loadstore_lxz_off,
|
||||||
m_jit_loadstore_lwz_off, m_jit_loadstore_floating_off, m_jit_loadstore_paired_off,
|
m_jit_loadstore_lwz_off, m_jit_loadstore_floating_off, m_jit_loadstore_paired_off,
|
||||||
m_jit_floatingpoint_off, m_jit_integer_off, m_jit_paired_off, m_jit_systemregisters_off,
|
m_jit_floatingpoint_off, m_jit_integer_off, m_jit_paired_off, m_jit_systemregisters_off,
|
||||||
m_jit_branch_off})
|
m_jit_branch_off, m_jit_register_cache_off})
|
||||||
{
|
{
|
||||||
action->setEnabled(running && !playing);
|
action->setEnabled(running && !playing);
|
||||||
}
|
}
|
||||||
|
@ -896,6 +896,14 @@ void MenuBar::AddJITMenu()
|
||||||
SConfig::GetInstance().bJITBranchOff = enabled;
|
SConfig::GetInstance().bJITBranchOff = enabled;
|
||||||
ClearCache();
|
ClearCache();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
m_jit_register_cache_off = m_jit->addAction(tr("JIT Register Cache Off"));
|
||||||
|
m_jit_register_cache_off->setCheckable(true);
|
||||||
|
m_jit_register_cache_off->setChecked(SConfig::GetInstance().bJITRegisterCacheOff);
|
||||||
|
connect(m_jit_register_cache_off, &QAction::toggled, [this](bool enabled) {
|
||||||
|
SConfig::GetInstance().bJITRegisterCacheOff = enabled;
|
||||||
|
ClearCache();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void MenuBar::AddSymbolsMenu()
|
void MenuBar::AddSymbolsMenu()
|
||||||
|
|
|
@ -261,6 +261,7 @@ private:
|
||||||
QAction* m_jit_paired_off;
|
QAction* m_jit_paired_off;
|
||||||
QAction* m_jit_systemregisters_off;
|
QAction* m_jit_systemregisters_off;
|
||||||
QAction* m_jit_branch_off;
|
QAction* m_jit_branch_off;
|
||||||
|
QAction* m_jit_register_cache_off;
|
||||||
|
|
||||||
bool m_game_selected = false;
|
bool m_game_selected = false;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue