mirror of
https://git.eden-emu.dev/eden-emu/eden
synced 2026-07-11 02:16:39 +02:00
[dynarmic] use LinkBlockFast for branches which are guarnateed to be unconditional (or conditionally unconditional) (#4177)
CBZ is basically
```c
if (thing) {
jump(A);
} else {
jump(B);
}
```
those jumps are locally unconditional so we can add the LinkBlockFast
without much repercussions for a small win in JIT opts
Signed-off-by: lizzie <lizzie@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4177
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
This commit is contained in:
@@ -311,8 +311,9 @@ dispatcher, which will return control to the host.
|
||||
SetTerm(IR::Term::LinkBlockFast{next})
|
||||
```
|
||||
|
||||
This terminal instruction jumps to the basic block described by `next` unconditionally.
|
||||
This promises guarantees that must be held at runtime - i.e that the program wont hang,
|
||||
This terminal instruction jumps to the basic block described by `next` unconditionally. This promises guarantees that must be held at runtime - i.e that the program wont hang,
|
||||
|
||||
This is a valid expression if contained within another block (say a `Terminal::If`) and the semantics allow it to be so.
|
||||
|
||||
### Terminal: PopRSBHint
|
||||
|
||||
|
||||
@@ -17,10 +17,14 @@ bool TranslatorVisitor::arm_B(Cond cond, Imm<24> imm24) {
|
||||
if (!ArmConditionPassed(cond)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const u32 imm32 = mcl::bit::sign_extend<26, u32>(imm24.ZeroExtend() << 2) + 8;
|
||||
const auto new_location = ir.current_location.AdvancePC(imm32);
|
||||
ir.SetTerm(IR::Term::LinkBlock{new_location});
|
||||
// pattern match => b .
|
||||
if (imm32 == 0) {
|
||||
ir.SetTerm(IR::Term::LinkBlock{new_location});
|
||||
} else {
|
||||
ir.SetTerm(IR::Term::LinkBlockFast{new_location});
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -35,7 +39,7 @@ bool TranslatorVisitor::arm_BL(Cond cond, Imm<24> imm24) {
|
||||
|
||||
const u32 imm32 = mcl::bit::sign_extend<26, u32>(imm24.ZeroExtend() << 2) + 8;
|
||||
const auto new_location = ir.current_location.AdvancePC(imm32);
|
||||
ir.SetTerm(IR::Term::LinkBlock{new_location});
|
||||
ir.SetTerm(IR::Term::LinkBlockFast{new_location});
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -46,7 +50,7 @@ bool TranslatorVisitor::arm_BLX_imm(bool H, Imm<24> imm24) {
|
||||
|
||||
const u32 imm32 = mcl::bit::sign_extend<26, u32>((imm24.ZeroExtend() << 2)) + (H ? 2 : 0) + 8;
|
||||
const auto new_location = ir.current_location.AdvancePC(imm32).SetTFlag(true);
|
||||
ir.SetTerm(IR::Term::LinkBlock{new_location});
|
||||
ir.SetTerm(IR::Term::LinkBlockFast{new_location});
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -56,11 +56,10 @@ bool TranslatorVisitor::arm_MSR_imm(Cond cond, unsigned mask, int rotate, Imm<8>
|
||||
if (write_e) {
|
||||
const bool E = (imm32 & 0x00000200) != 0;
|
||||
if (E != ir.current_location.EFlag()) {
|
||||
ir.SetTerm(IR::Term::LinkBlock{ir.current_location.AdvancePC(4).SetEFlag(E)});
|
||||
ir.SetTerm(IR::Term::LinkBlockFast{ir.current_location.AdvancePC(4).SetEFlag(E)});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -112,7 +111,7 @@ bool TranslatorVisitor::arm_RFE() {
|
||||
|
||||
// SETEND <endian_specifier>
|
||||
bool TranslatorVisitor::arm_SETEND(bool E) {
|
||||
ir.SetTerm(IR::Term::LinkBlock{ir.current_location.AdvancePC(4).SetEFlag(E)});
|
||||
ir.SetTerm(IR::Term::LinkBlockFast{ir.current_location.AdvancePC(4).SetEFlag(E)});
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -803,7 +803,7 @@ bool TranslatorVisitor::thumb16_SETEND(bool E) {
|
||||
return true;
|
||||
}
|
||||
|
||||
ir.SetTerm(IR::Term::LinkBlock{ir.current_location.AdvancePC(2).SetEFlag(E).AdvanceIT()});
|
||||
ir.SetTerm(IR::Term::LinkBlockFast{ir.current_location.AdvancePC(2).SetEFlag(E).AdvanceIT()});
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -906,9 +906,8 @@ bool TranslatorVisitor::thumb16_CBZ_CBNZ(bool nonzero, Imm<1> i, Imm<5> imm5, Re
|
||||
ir.SetCheckBit(ir.IsZero(rn));
|
||||
|
||||
const auto [cond_pass, cond_fail] = [this, imm, nonzero] {
|
||||
const auto skip = IR::Term::LinkBlock{ir.current_location.AdvancePC(2).AdvanceIT()};
|
||||
const auto branch = IR::Term::LinkBlock{ir.current_location.AdvancePC(imm + 4).AdvanceIT()};
|
||||
|
||||
const auto skip = IR::Term::LinkBlockFast{ir.current_location.AdvancePC(2).AdvanceIT()};
|
||||
const auto branch = IR::Term::LinkBlockFast{ir.current_location.AdvancePC(imm + 4).AdvanceIT()};
|
||||
if (nonzero) {
|
||||
return std::make_pair(skip, branch);
|
||||
} else {
|
||||
@@ -975,10 +974,10 @@ bool TranslatorVisitor::thumb16_B_t1(Cond cond, Imm<8> imm8) {
|
||||
}
|
||||
|
||||
const s32 imm32 = static_cast<s32>((imm8.SignExtend<u32>() << 1) + 4);
|
||||
const auto then_location = ir.current_location.AdvancePC(imm32).AdvanceIT();
|
||||
const auto else_location = ir.current_location.AdvancePC(2).AdvanceIT();
|
||||
const auto then_ = IR::Term::LinkBlockFast{ir.current_location.AdvancePC(imm32).AdvanceIT()};
|
||||
const auto else_ = IR::Term::LinkBlockFast{ir.current_location.AdvancePC(2).AdvanceIT()};
|
||||
|
||||
ir.SetTerm(IR::Term::If{cond, IR::Term::LinkBlock{then_location}, IR::Term::LinkBlock{else_location}});
|
||||
ir.SetTerm(IR::Term::If{cond, then_, else_});
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -990,8 +989,12 @@ bool TranslatorVisitor::thumb16_B_t2(Imm<11> imm11) {
|
||||
|
||||
const s32 imm32 = static_cast<s32>((imm11.SignExtend<u32>() << 1) + 4);
|
||||
const auto next_location = ir.current_location.AdvancePC(imm32).AdvanceIT();
|
||||
|
||||
ir.SetTerm(IR::Term::LinkBlock{next_location});
|
||||
// pattern (b +#0)
|
||||
if (imm32 == 0) {
|
||||
ir.SetTerm(IR::Term::LinkBlock{next_location});
|
||||
} else {
|
||||
ir.SetTerm(IR::Term::LinkBlockFast{next_location});
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
/* This file is part of the dynarmic project.
|
||||
* Copyright (c) 2016 MerryMage
|
||||
* SPDX-License-Identifier: 0BSD
|
||||
@@ -20,10 +23,8 @@ bool TranslatorVisitor::thumb32_BL_imm(Imm<1> S, Imm<10> hi, Imm<1> j1, Imm<1> j
|
||||
ir.SetRegister(Reg::LR, ir.Imm32((ir.current_location.PC() + 4) | 1));
|
||||
|
||||
const s32 imm32 = static_cast<s32>((concatenate(S, i1, i2, hi, lo).SignExtend<u32>() << 1) + 4);
|
||||
const auto new_location = ir.current_location
|
||||
.AdvancePC(imm32)
|
||||
.AdvanceIT();
|
||||
ir.SetTerm(IR::Term::LinkBlock{new_location});
|
||||
auto const new_location = ir.current_location.AdvancePC(imm32).AdvanceIT();
|
||||
ir.SetTerm(IR::Term::LinkBlockFast{new_location});
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -44,11 +45,8 @@ bool TranslatorVisitor::thumb32_BLX_imm(Imm<1> S, Imm<10> hi, Imm<1> j1, Imm<1>
|
||||
ir.SetRegister(Reg::LR, ir.Imm32((ir.current_location.PC() + 4) | 1));
|
||||
|
||||
const s32 imm32 = static_cast<s32>(concatenate(S, i1, i2, hi, lo).SignExtend<u32>() << 1);
|
||||
const auto new_location = ir.current_location
|
||||
.SetPC(ir.AlignPC(4) + imm32)
|
||||
.SetTFlag(false)
|
||||
.AdvanceIT();
|
||||
ir.SetTerm(IR::Term::LinkBlock{new_location});
|
||||
const auto new_location = ir.current_location.SetPC(ir.AlignPC(4) + imm32).SetTFlag(false).AdvanceIT();
|
||||
ir.SetTerm(IR::Term::LinkBlockFast{new_location});
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -61,10 +59,13 @@ bool TranslatorVisitor::thumb32_B(Imm<1> S, Imm<10> hi, Imm<1> j1, Imm<1> j2, Im
|
||||
}
|
||||
|
||||
const s32 imm32 = static_cast<s32>((concatenate(S, i1, i2, hi, lo).SignExtend<u32>() << 1) + 4);
|
||||
const auto new_location = ir.current_location
|
||||
.AdvancePC(imm32)
|
||||
.AdvanceIT();
|
||||
ir.SetTerm(IR::Term::LinkBlock{new_location});
|
||||
auto const new_location = ir.current_location.AdvancePC(imm32).AdvanceIT();
|
||||
// Pattern to halt execution (b +#0)
|
||||
if (imm32 == 0) {
|
||||
ir.SetTerm(IR::Term::LinkBlock{new_location});
|
||||
} else {
|
||||
ir.SetTerm(IR::Term::LinkBlockFast{new_location});
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -75,13 +76,9 @@ bool TranslatorVisitor::thumb32_B_cond(Imm<1> S, Cond cond, Imm<6> hi, Imm<1> i1
|
||||
|
||||
// Note: i1 and i2 were not inverted from encoding and are opposite compared to the other B instructions.
|
||||
const s32 imm32 = static_cast<s32>((concatenate(S, i2, i1, hi, lo).SignExtend<u32>() << 1) + 4);
|
||||
const auto then_location = ir.current_location
|
||||
.AdvancePC(imm32)
|
||||
.AdvanceIT();
|
||||
const auto else_location = ir.current_location
|
||||
.AdvancePC(4)
|
||||
.AdvanceIT();
|
||||
ir.SetTerm(IR::Term::If{cond, IR::Term::LinkBlock{then_location}, IR::Term::LinkBlock{else_location}});
|
||||
const auto then_ = IR::Term::LinkBlockFast{ir.current_location.AdvancePC(imm32).AdvanceIT()};
|
||||
const auto else_ = IR::Term::LinkBlockFast{ir.current_location.AdvancePC(4).AdvanceIT()};
|
||||
ir.SetTerm(IR::Term::If{cond, then_, else_});
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -14,8 +14,8 @@ bool TranslatorVisitor::B_cond(Imm<19> imm19, Cond cond) {
|
||||
const s64 offset = concatenate(imm19, Imm<2>{0}).SignExtend<s64>();
|
||||
const u64 target = ir.PC() + offset;
|
||||
|
||||
const auto cond_pass = IR::Term::LinkBlock{ir.current_location->SetPC(target)};
|
||||
const auto cond_fail = IR::Term::LinkBlock{ir.current_location->AdvancePC(4)};
|
||||
const auto cond_pass = IR::Term::LinkBlockFast{ir.current_location->SetPC(target)};
|
||||
const auto cond_fail = IR::Term::LinkBlockFast{ir.current_location->AdvancePC(4)};
|
||||
ir.SetTerm(IR::Term::If{cond, cond_pass, cond_fail});
|
||||
return false;
|
||||
}
|
||||
@@ -26,9 +26,9 @@ bool TranslatorVisitor::B_uncond(Imm<26> imm26) {
|
||||
// Pattern to halt execution (B .)
|
||||
if (target == ir.PC()) {
|
||||
ir.SetTerm(IR::Term::LinkBlock{ir.current_location->SetPC(target)});
|
||||
return false;
|
||||
} else {
|
||||
ir.SetTerm(IR::Term::LinkBlockFast{ir.current_location->SetPC(target)});
|
||||
}
|
||||
ir.SetTerm(IR::Term::LinkBlockFast{ir.current_location->SetPC(target)});
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -79,8 +79,8 @@ bool TranslatorVisitor::CBZ(bool sf, Imm<19> imm19, Reg Rt) {
|
||||
ir.SetCheckBit(ir.IsZero(operand1));
|
||||
|
||||
const u64 target = ir.PC() + offset;
|
||||
const auto cond_pass = IR::Term::LinkBlock{ir.current_location->SetPC(target)};
|
||||
const auto cond_fail = IR::Term::LinkBlock{ir.current_location->AdvancePC(4)};
|
||||
const auto cond_pass = IR::Term::LinkBlockFast{ir.current_location->SetPC(target)};
|
||||
const auto cond_fail = IR::Term::LinkBlockFast{ir.current_location->AdvancePC(4)};
|
||||
ir.SetTerm(IR::Term::CheckBit{cond_pass, cond_fail});
|
||||
return false;
|
||||
}
|
||||
@@ -94,8 +94,8 @@ bool TranslatorVisitor::CBNZ(bool sf, Imm<19> imm19, Reg Rt) {
|
||||
ir.SetCheckBit(ir.IsZero(operand1));
|
||||
|
||||
const u64 target = ir.PC() + offset;
|
||||
const auto cond_pass = IR::Term::LinkBlock{ir.current_location->AdvancePC(4)};
|
||||
const auto cond_fail = IR::Term::LinkBlock{ir.current_location->SetPC(target)};
|
||||
const auto cond_pass = IR::Term::LinkBlockFast{ir.current_location->AdvancePC(4)};
|
||||
const auto cond_fail = IR::Term::LinkBlockFast{ir.current_location->SetPC(target)};
|
||||
ir.SetTerm(IR::Term::CheckBit{cond_pass, cond_fail});
|
||||
return false;
|
||||
}
|
||||
@@ -110,8 +110,8 @@ bool TranslatorVisitor::TBZ(Imm<1> b5, Imm<5> b40, Imm<14> imm14, Reg Rt) {
|
||||
ir.SetCheckBit(ir.TestBit(operand, ir.Imm8(bit_pos)));
|
||||
|
||||
const u64 target = ir.PC() + offset;
|
||||
const auto cond_1 = IR::Term::LinkBlock{ir.current_location->AdvancePC(4)};
|
||||
const auto cond_0 = IR::Term::LinkBlock{ir.current_location->SetPC(target)};
|
||||
const auto cond_1 = IR::Term::LinkBlockFast{ir.current_location->AdvancePC(4)};
|
||||
const auto cond_0 = IR::Term::LinkBlockFast{ir.current_location->SetPC(target)};
|
||||
ir.SetTerm(IR::Term::CheckBit{cond_1, cond_0});
|
||||
return false;
|
||||
}
|
||||
@@ -126,8 +126,8 @@ bool TranslatorVisitor::TBNZ(Imm<1> b5, Imm<5> b40, Imm<14> imm14, Reg Rt) {
|
||||
ir.SetCheckBit(ir.TestBit(operand, ir.Imm8(bit_pos)));
|
||||
|
||||
const u64 target = ir.PC() + offset;
|
||||
const auto cond_1 = IR::Term::LinkBlock{ir.current_location->SetPC(target)};
|
||||
const auto cond_0 = IR::Term::LinkBlock{ir.current_location->AdvancePC(4)};
|
||||
const auto cond_1 = IR::Term::LinkBlockFast{ir.current_location->SetPC(target)};
|
||||
const auto cond_0 = IR::Term::LinkBlockFast{ir.current_location->AdvancePC(4)};
|
||||
ir.SetTerm(IR::Term::CheckBit{cond_1, cond_0});
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user