[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:
parent
c263b6af6f
commit
72973fe582
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue