diff --git a/src/backend/x64/a32_emit_x64.cpp b/src/backend/x64/a32_emit_x64.cpp index aaadde84..3ae0968c 100644 --- a/src/backend/x64/a32_emit_x64.cpp +++ b/src/backend/x64/a32_emit_x64.cpp @@ -1230,14 +1230,8 @@ void A32EmitX64::EmitTerminalImpl(IR::Term::PopRSBHint, IR::LocationDescriptor) code.or_(ebx, dword[r15 + offsetof(A32JitState, CPSR_et)]); code.or_(rbx, rcx); - code.mov(eax, dword[r15 + offsetof(A32JitState, rsb_ptr)]); - code.sub(eax, 1); - code.and_(eax, u32(A32JitState::RSBPtrMask)); - code.mov(dword[r15 + offsetof(A32JitState, rsb_ptr)], eax); - code.cmp(rbx, qword[r15 + offsetof(A32JitState, rsb_location_descriptors) + rax * sizeof(u64)]); - code.jne(code.GetReturnFromRunCodeAddress()); - code.mov(rax, qword[r15 + offsetof(A32JitState, rsb_codeptrs) + rax * sizeof(u64)]); - code.jmp(rax); +void A32EmitX64::EmitTerminalImpl(IR::Term::FastDispatchHint, IR::LocationDescriptor initial_location) { + EmitTerminalImpl(IR::Term::ReturnToDispatch{}, initial_location); } void A32EmitX64::EmitTerminalImpl(IR::Term::If terminal, IR::LocationDescriptor initial_location) { diff --git a/src/backend/x64/a32_emit_x64.h b/src/backend/x64/a32_emit_x64.h index c559fecb..01bfb0cf 100644 --- a/src/backend/x64/a32_emit_x64.h +++ b/src/backend/x64/a32_emit_x64.h @@ -77,6 +77,7 @@ protected: void EmitTerminalImpl(IR::Term::LinkBlock terminal, IR::LocationDescriptor initial_location) override; void EmitTerminalImpl(IR::Term::LinkBlockFast terminal, IR::LocationDescriptor initial_location) override; void EmitTerminalImpl(IR::Term::PopRSBHint terminal, IR::LocationDescriptor initial_location) override; + void EmitTerminalImpl(IR::Term::FastDispatchHint terminal, IR::LocationDescriptor initial_location) override; void EmitTerminalImpl(IR::Term::If terminal, IR::LocationDescriptor initial_location) override; void EmitTerminalImpl(IR::Term::CheckBit terminal, IR::LocationDescriptor initial_location) override; void EmitTerminalImpl(IR::Term::CheckHalt terminal, IR::LocationDescriptor initial_location) override; diff --git a/src/backend/x64/a64_emit_x64.cpp b/src/backend/x64/a64_emit_x64.cpp index 12610147..46e2c74b 100644 --- a/src/backend/x64/a64_emit_x64.cpp +++ b/src/backend/x64/a64_emit_x64.cpp @@ -1070,6 +1070,10 @@ void A64EmitX64::EmitTerminalImpl(IR::Term::PopRSBHint, IR::LocationDescriptor) code.jmp(rax); } +void A64EmitX64::EmitTerminalImpl(IR::Term::FastDispatchHint, IR::LocationDescriptor initial_location) { + EmitTerminalImpl(IR::Term::ReturnToDispatch{}, initial_location); +} + void A64EmitX64::EmitTerminalImpl(IR::Term::If terminal, IR::LocationDescriptor initial_location) { switch (terminal.if_) { case IR::Cond::AL: diff --git a/src/backend/x64/a64_emit_x64.h b/src/backend/x64/a64_emit_x64.h index 5b9a6178..8a169a89 100644 --- a/src/backend/x64/a64_emit_x64.h +++ b/src/backend/x64/a64_emit_x64.h @@ -83,6 +83,7 @@ protected: void EmitTerminalImpl(IR::Term::LinkBlock terminal, IR::LocationDescriptor initial_location) override; void EmitTerminalImpl(IR::Term::LinkBlockFast terminal, IR::LocationDescriptor initial_location) override; void EmitTerminalImpl(IR::Term::PopRSBHint terminal, IR::LocationDescriptor initial_location) override; + void EmitTerminalImpl(IR::Term::FastDispatchHint terminal, IR::LocationDescriptor initial_location) override; void EmitTerminalImpl(IR::Term::If terminal, IR::LocationDescriptor initial_location) override; void EmitTerminalImpl(IR::Term::CheckBit terminal, IR::LocationDescriptor initial_location) override; void EmitTerminalImpl(IR::Term::CheckHalt terminal, IR::LocationDescriptor initial_location) override; diff --git a/src/backend/x64/emit_x64.h b/src/backend/x64/emit_x64.h index c0d329c4..57dbf8b3 100644 --- a/src/backend/x64/emit_x64.h +++ b/src/backend/x64/emit_x64.h @@ -100,6 +100,7 @@ protected: virtual void EmitTerminalImpl(IR::Term::LinkBlock terminal, IR::LocationDescriptor initial_location) = 0; virtual void EmitTerminalImpl(IR::Term::LinkBlockFast terminal, IR::LocationDescriptor initial_location) = 0; virtual void EmitTerminalImpl(IR::Term::PopRSBHint terminal, IR::LocationDescriptor initial_location) = 0; + virtual void EmitTerminalImpl(IR::Term::FastDispatchHint terminal, IR::LocationDescriptor initial_location) = 0; virtual void EmitTerminalImpl(IR::Term::If terminal, IR::LocationDescriptor initial_location) = 0; virtual void EmitTerminalImpl(IR::Term::CheckBit terminal, IR::LocationDescriptor initial_location) = 0; virtual void EmitTerminalImpl(IR::Term::CheckHalt terminal, IR::LocationDescriptor initial_location) = 0; diff --git a/src/frontend/ir/terminal.h b/src/frontend/ir/terminal.h index 0bbf9cc7..a6a24292 100644 --- a/src/frontend/ir/terminal.h +++ b/src/frontend/ir/terminal.h @@ -29,7 +29,7 @@ struct Interpret { /** * This terminal instruction returns control to the dispatcher. - * The dispatcher will use the value in R15 to determine what comes next. + * The dispatcher will use the current cpu state to determine what comes next. */ struct ReturnToDispatch {}; @@ -57,14 +57,21 @@ struct LinkBlockFast { }; /** - * This terminal instruction checks the top of the Return Stack Buffer against R15. - * If RSB lookup fails, control is returned to the dispatcher. + * This terminal instruction checks the top of the Return Stack Buffer against the current + * location descriptor. If RSB lookup fails, control is returned to the dispatcher. * This is an optimization for faster function calls. A backend that doesn't support * this optimization or doesn't have a RSB may choose to implement this exactly as * ReturnToDispatch. */ struct PopRSBHint {}; +/** + * This terminal instruction performs a lookup of the current location descriptor in the + * fast dispatch lookup table. A backend that doesn't support this optimization may choose + * to implement this exactly as ReturnToDispatch. + */ +struct FastDispatchHint {}; + struct If; struct CheckBit; struct CheckHalt; @@ -76,6 +83,7 @@ using Terminal = boost::variant< LinkBlock, LinkBlockFast, PopRSBHint, + FastDispatchHint, boost::recursive_wrapper, boost::recursive_wrapper, boost::recursive_wrapper