Optimization: Make SVC use RSB

This commit is contained in:
MerryMage 2016-08-15 15:02:08 +01:00
parent 6c45619aa1
commit 7d7ac0af71
8 changed files with 30 additions and 7 deletions

View file

@ -1674,6 +1674,9 @@ void EmitX64::EmitTerminal(IR::Terminal terminal, Arm::LocationDescriptor initia
case 6:
EmitTerminalIf(boost::get<IR::Term::If>(terminal), initial_location);
return;
case 7:
EmitTerminalCheckHalt(boost::get<IR::Term::CheckHalt>(terminal), initial_location);
return;
default:
ASSERT_MSG(0, "Invalid Terminal. Bad programmer.");
return;
@ -1776,6 +1779,12 @@ void EmitX64::EmitTerminalIf(IR::Term::If terminal, Arm::LocationDescriptor init
EmitTerminal(terminal.then_, initial_location);
}
void EmitX64::EmitTerminalCheckHalt(IR::Term::CheckHalt terminal, Arm::LocationDescriptor initial_location) {
code->CMP(8, MDisp(R15, offsetof(JitState, halt_requested)), Imm8(0));
code->J_CC(CC_NE, code->GetReturnFromRunCodeAddress(), true);
EmitTerminal(terminal.else_, initial_location);
}
void EmitX64::Patch(Arm::LocationDescriptor desc, CodePtr bb) {
u8* const save_code_ptr = code->GetWritableCodePtr();

View file

@ -64,6 +64,7 @@ private:
void EmitTerminalLinkBlockFast(IR::Term::LinkBlockFast terminal, Arm::LocationDescriptor initial_location);
void EmitTerminalPopRSBHint(IR::Term::PopRSBHint terminal, Arm::LocationDescriptor initial_location);
void EmitTerminalIf(IR::Term::If terminal, Arm::LocationDescriptor initial_location);
void EmitTerminalCheckHalt(IR::Term::CheckHalt terminal, Arm::LocationDescriptor initial_location);
void Patch(Arm::LocationDescriptor desc, CodePtr bb);
// Per-block state

View file

@ -112,10 +112,10 @@ size_t Jit::Run(size_t cycle_count) {
is_executing = true;
SCOPE_EXIT({ this->is_executing = false; });
halt_requested = false;
impl->jit_state.halt_requested = false;
size_t cycles_executed = 0;
while (cycles_executed < cycle_count && !halt_requested) {
while (cycles_executed < cycle_count && !impl->jit_state.halt_requested) {
cycles_executed += impl->Execute(cycle_count - cycles_executed);
}
@ -136,7 +136,7 @@ void Jit::Reset() {
void Jit::HaltExecution() {
ASSERT(is_executing);
halt_requested = true;
impl->jit_state.halt_requested = true;
// TODO: Uh do other stuff to JitState pls.
}

View file

@ -32,6 +32,7 @@ struct JitState {
u32 guest_MXCSR = 0x00001f80;
u32 save_host_MXCSR = 0;
s64 cycles_remaining = 0;
bool halt_requested = false;
// Exclusive state
static constexpr u32 RESERVATION_GRANULE_MASK = 0xFFFFFFF8;

View file

@ -166,6 +166,7 @@ struct LinkBlockFast {
struct PopRSBHint {};
struct If;
struct CheckHalt;
/// A Terminal is the terminal instruction in a MicroBlock.
using Terminal = boost::variant<
Invalid,
@ -174,7 +175,8 @@ using Terminal = boost::variant<
LinkBlock,
LinkBlockFast,
PopRSBHint,
boost::recursive_wrapper<If>
boost::recursive_wrapper<If>,
boost::recursive_wrapper<CheckHalt>
>;
/**
@ -188,6 +190,15 @@ struct If {
Terminal else_;
};
/**
* This terminal instruction checks if a halt was requested. If it wasn't, else_ is
* executed.
*/
struct CheckHalt {
CheckHalt(Terminal else_) : else_(else_) {}
Terminal else_;
};
} // namespace Term
using Term::Terminal;

View file

@ -17,9 +17,10 @@ bool ArmTranslatorVisitor::arm_SVC(Cond cond, Imm24 imm24) {
u32 imm32 = imm24;
// SVC<c> #<imm24>
if (ConditionPassed(cond)) {
ir.PushRSB(ir.current_location.AdvancePC(4));
ir.BranchWritePC(ir.Imm32(ir.current_location.PC() + 4));
ir.CallSupervisor(ir.Imm32(imm32));
ir.SetTerm(IR::Term::ReturnToDispatch{});
ir.SetTerm(IR::Term::CheckHalt{IR::Term::PopRSBHint{}});
return false;
}
return true;

View file

@ -773,8 +773,9 @@ struct ThumbTranslatorVisitor final {
u32 imm32 = imm8;
// SVC #<imm8>
ir.BranchWritePC(ir.Imm32(ir.current_location.PC() + 2));
ir.PushRSB(ir.current_location.AdvancePC(2));
ir.CallSupervisor(ir.Imm32(imm32));
ir.SetTerm(IR::Term::ReturnToDispatch{});
ir.SetTerm(IR::Term::CheckHalt{IR::Term::PopRSBHint{}});
return false;
}

View file

@ -99,7 +99,6 @@ public:
std::string Disassemble(const Arm::LocationDescriptor& descriptor);
private:
bool halt_requested = false;
bool is_executing = false;
struct Impl;