[dynarmic] fix NSBU regressions (#3533)

Signed-off-by: lizzie <lizzie@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3533
Reviewed-by: Maufeat <sahyno1996@gmail.com>
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Co-authored-by: lizzie <lizzie@eden-emu.dev>
Co-committed-by: lizzie <lizzie@eden-emu.dev>
This commit is contained in:
lizzie 2026-02-13 11:51:34 +01:00 committed by crueter
parent c263b6af6f
commit 72973fe582
No known key found for this signature in database
GPG Key ID: 425ACD2D4830EBC6
4 changed files with 45 additions and 42 deletions

View File

@ -65,11 +65,10 @@ static Optimization::PolyfillOptions GenPolyfillOptions(const BlockOfCode& code)
struct Jit::Impl { struct Jit::Impl {
Impl(Jit* jit, A32::UserConfig conf) noexcept Impl(Jit* jit, A32::UserConfig conf) noexcept
: ir_block{LocationDescriptor(0, PSR(0), FPSCR(0), false)} : block_of_code(GenRunCodeCallbacks(conf.callbacks, &GetCurrentBlockThunk, this, conf), JitStateInfo{jit_state}, conf.code_cache_size, GenRCP(conf))
, conf(std::move(conf))
, block_of_code(GenRunCodeCallbacks(conf.callbacks, &GetCurrentBlockThunk, this, conf), JitStateInfo{jit_state}, conf.code_cache_size, GenRCP(conf))
, emitter(block_of_code, conf, jit) , emitter(block_of_code, conf, jit)
, polyfill_options(GenPolyfillOptions(block_of_code)) , polyfill_options(GenPolyfillOptions(block_of_code))
, conf(std::move(conf))
, jit_interface(jit) , jit_interface(jit)
{} {}
@ -204,8 +203,7 @@ private:
} }
A32EmitX64::BlockDescriptor GetBasicBlock(IR::LocationDescriptor descriptor) { A32EmitX64::BlockDescriptor GetBasicBlock(IR::LocationDescriptor descriptor) {
auto block = emitter.GetBasicBlock(descriptor); if (auto block = emitter.GetBasicBlock(descriptor))
if (block)
return *block; return *block;
constexpr size_t MINIMUM_REMAINING_CODESIZE = 1 * 1024 * 1024; constexpr size_t MINIMUM_REMAINING_CODESIZE = 1 * 1024 * 1024;
@ -215,8 +213,10 @@ private:
} }
block_of_code.EnsureMemoryCommitted(MINIMUM_REMAINING_CODESIZE); block_of_code.EnsureMemoryCommitted(MINIMUM_REMAINING_CODESIZE);
ir_block.Reset(descriptor); // LocationDescriptor ctor() does important ops (like tflags) do not skip
A32::Translate(ir_block, A32::LocationDescriptor{descriptor}, conf.callbacks, {conf.arch_version, conf.define_unpredictable_behaviour, conf.hook_hint_instructions}); auto const arch_descriptor = A32::LocationDescriptor{descriptor};
ir_block.Reset(arch_descriptor);
A32::Translate(ir_block, arch_descriptor, conf.callbacks, {conf.arch_version, conf.define_unpredictable_behaviour, conf.hook_hint_instructions});
Optimization::Optimize(ir_block, conf, polyfill_options); Optimization::Optimize(ir_block, conf, polyfill_options);
return emitter.Emit(ir_block); return emitter.Emit(ir_block);
} }
@ -243,12 +243,13 @@ private:
} }
} }
IR::Block ir_block; IR::Block ir_block = {LocationDescriptor(0, PSR(0), FPSCR(0), false)};
const A32::UserConfig conf;
A32JitState jit_state; A32JitState jit_state;
BlockOfCode block_of_code; BlockOfCode block_of_code;
A32EmitX64 emitter; A32EmitX64 emitter;
Optimization::PolyfillOptions polyfill_options; Optimization::PolyfillOptions polyfill_options;
// Keep it here, you don't wanna mess with the fuckery that's initializer lists
const A32::UserConfig conf;
Jit* jit_interface; Jit* jit_interface;
// Requests made during execution to invalidate the cache are queued up here. // Requests made during execution to invalidate the cache are queued up here.

View File

@ -62,8 +62,7 @@ static Optimization::PolyfillOptions GenPolyfillOptions(const BlockOfCode& code)
struct Jit::Impl final { struct Jit::Impl final {
public: public:
Impl(Jit* jit, UserConfig conf) Impl(Jit* jit, UserConfig conf)
: ir_block{LocationDescriptor(0, FP::FPCR(0), false)} : conf(conf)
, conf(conf)
, block_of_code(GenRunCodeCallbacks(conf.callbacks, &GetCurrentBlockThunk, this, conf), JitStateInfo{jit_state}, conf.code_cache_size, GenRCP(conf)) , block_of_code(GenRunCodeCallbacks(conf.callbacks, &GetCurrentBlockThunk, this, conf), JitStateInfo{jit_state}, conf.code_cache_size, GenRCP(conf))
, emitter(block_of_code, conf, jit) , emitter(block_of_code, conf, jit)
, polyfill_options(GenPolyfillOptions(block_of_code)) , polyfill_options(GenPolyfillOptions(block_of_code))
@ -257,8 +256,8 @@ private:
return GetBlock(A64::LocationDescriptor{GetCurrentLocation()}.SetSingleStepping(true)); return GetBlock(A64::LocationDescriptor{GetCurrentLocation()}.SetSingleStepping(true));
} }
CodePtr GetBlock(IR::LocationDescriptor current_location) { CodePtr GetBlock(IR::LocationDescriptor descriptor) {
if (auto block = emitter.GetBasicBlock(current_location)) if (auto block = emitter.GetBasicBlock(descriptor))
return block->entrypoint; return block->entrypoint;
constexpr size_t MINIMUM_REMAINING_CODESIZE = 1 * 1024 * 1024; constexpr size_t MINIMUM_REMAINING_CODESIZE = 1 * 1024 * 1024;
@ -271,8 +270,10 @@ private:
// JIT Compile // JIT Compile
const auto get_code = [this](u64 vaddr) { return conf.callbacks->MemoryReadCode(vaddr); }; const auto get_code = [this](u64 vaddr) { return conf.callbacks->MemoryReadCode(vaddr); };
ir_block.Reset(current_location); // LocationDescriptor ctor() does important ops (like tflags) do not skip
A64::Translate(ir_block, A64::LocationDescriptor{current_location}, get_code, {conf.define_unpredictable_behaviour, conf.wall_clock_cntpct}); auto const arch_descriptor = A64::LocationDescriptor{descriptor};
ir_block.Reset(arch_descriptor);
A64::Translate(ir_block, arch_descriptor, get_code, {conf.define_unpredictable_behaviour, conf.wall_clock_cntpct});
Optimization::Optimize(ir_block, conf, polyfill_options); Optimization::Optimize(ir_block, conf, polyfill_options);
return emitter.Emit(ir_block).entrypoint; return emitter.Emit(ir_block).entrypoint;
} }
@ -299,7 +300,7 @@ private:
} }
} }
IR::Block ir_block; IR::Block ir_block = {LocationDescriptor(0, FP::FPCR(0), false)};
const UserConfig conf; const UserConfig conf;
A64JitState jit_state; A64JitState jit_state;
BlockOfCode block_of_code; BlockOfCode block_of_code;

View File

@ -22,13 +22,10 @@
namespace Dynarmic::IR { namespace Dynarmic::IR {
Block::Block(const LocationDescriptor& location) Block::Block(LocationDescriptor location) noexcept
: location{location}, : location{location}
end_location{location}, , end_location{location}
cond{Cond::AL} {}
{
}
/// Prepends a new instruction to this basic block before the insertion point, /// Prepends a new instruction to this basic block before the insertion point,
/// handling any allocations necessary to do so. /// handling any allocations necessary to do so.
@ -60,6 +57,21 @@ Block::iterator Block::PrependNewInst(iterator insertion_point, Opcode opcode, s
return instructions.insert_before(insertion_point, inst); return instructions.insert_before(insertion_point, inst);
} }
void Block::Reset(LocationDescriptor location_) noexcept {
mcl::intrusive_list<IR::Inst> tmp = {};
instructions.swap(tmp);
inlined_inst.clear();
pooled_inst.clear();
cond_failed.reset();
location = location_;
end_location = location_;
cond = Cond::AL;
terminal = Term::Invalid{};
cond_failed_cycle_count = 0;
cycle_count = 0;
ASSERT(instructions.size() == 0);
}
static std::string TerminalToString(const Terminal& terminal_variant) noexcept { static std::string TerminalToString(const Terminal& terminal_variant) noexcept {
struct : boost::static_visitor<std::string> { struct : boost::static_visitor<std::string> {
std::string operator()(const Term::Invalid&) const { std::string operator()(const Term::Invalid&) const {
@ -123,11 +135,11 @@ std::string DumpBlock(const IR::Block& block) noexcept {
case Type::A32ExtReg: return A32::ExtRegToString(arg.GetA32ExtRegRef()); case Type::A32ExtReg: return A32::ExtRegToString(arg.GetA32ExtRegRef());
case Type::A64Reg: return A64::RegToString(arg.GetA64RegRef()); case Type::A64Reg: return A64::RegToString(arg.GetA64RegRef());
case Type::A64Vec: return A64::VecToString(arg.GetA64VecRef()); case Type::A64Vec: return A64::VecToString(arg.GetA64VecRef());
case Type::CoprocInfo: return fmt::format("#<coproc>"); case Type::CoprocInfo: return fmt::format("$coproc{}", arg.GetCoprocInfo()[0]);
case Type::NZCVFlags: return fmt::format("#<NZCV flags>"); case Type::NZCVFlags: return fmt::format("$nzcv");
case Type::Cond: return fmt::format("#<cond={}>", A32::CondToString(arg.GetCond())); case Type::Cond: return fmt::format("$cond={}", A32::CondToString(arg.GetCond()));
case Type::Table: return fmt::format("#<table>"); case Type::Table: return fmt::format("$table");
case Type::AccType: return fmt::format("#<acc-type={}>", u32(arg.GetAccType())); case Type::AccType: return fmt::format("$acc-type={}", u32(arg.GetAccType()));
default: return fmt::format("<unknown immediate type {}>", arg.GetType()); default: return fmt::format("<unknown immediate type {}>", arg.GetType());
} }
}; };

View File

@ -43,7 +43,7 @@ public:
using reverse_iterator = instruction_list_type::reverse_iterator; using reverse_iterator = instruction_list_type::reverse_iterator;
using const_reverse_iterator = instruction_list_type::const_reverse_iterator; using const_reverse_iterator = instruction_list_type::const_reverse_iterator;
explicit Block(const LocationDescriptor& location); Block(LocationDescriptor location) noexcept;
~Block() = default; ~Block() = default;
Block(const Block&) = delete; Block(const Block&) = delete;
Block& operator=(const Block&) = delete; Block& operator=(const Block&) = delete;
@ -58,6 +58,7 @@ public:
return PrependNewInst(instructions.end(), opcode, args); return PrependNewInst(instructions.end(), opcode, args);
} }
iterator PrependNewInst(iterator insertion_point, Opcode op, std::initializer_list<Value> args) noexcept; iterator PrependNewInst(iterator insertion_point, Opcode op, std::initializer_list<Value> args) noexcept;
void Reset(LocationDescriptor location_) noexcept;
/// Gets a mutable reference to the instruction list for this basic block. /// Gets a mutable reference to the instruction list for this basic block.
inline instruction_list_type& Instructions() noexcept { inline instruction_list_type& Instructions() noexcept {
@ -140,18 +141,6 @@ public:
return cycle_count; return cycle_count;
} }
inline void Reset(LocationDescriptor location_) noexcept {
inlined_inst.clear();
pooled_inst.clear();
cond_failed.reset();
location = location_;
terminal = Term::Invalid{};
cond_failed_cycle_count = 0;
cycle_count = 0;
instruction_list_type tmp{};
instructions.swap(tmp);
}
/// "Hot cache" for small blocks so we don't call global allocator /// "Hot cache" for small blocks so we don't call global allocator
boost::container::static_vector<Inst, 30> inlined_inst; boost::container::static_vector<Inst, 30> inlined_inst;
/// List of instructions in this block. /// List of instructions in this block.
@ -165,7 +154,7 @@ public:
/// Description of the end location of this block /// Description of the end location of this block
LocationDescriptor end_location; LocationDescriptor end_location;
/// Conditional to pass in order to execute this block /// Conditional to pass in order to execute this block
Cond cond; Cond cond = Cond::AL;
/// Terminal instruction of this block. /// Terminal instruction of this block.
Terminal terminal = Term::Invalid{}; Terminal terminal = Term::Invalid{};
/// Number of cycles this block takes to execute if the conditional fails. /// Number of cycles this block takes to execute if the conditional fails.