mirror of
https://git.eden-emu.dev/eden-emu/eden
synced 2026-05-31 05:47:12 +02:00
inline a32core/a64core
Signed-off-by: lizzie <lizzie@eden-emu.dev>
This commit is contained in:
parent
af617cef09
commit
d4aced9a7c
4 changed files with 120 additions and 158 deletions
|
|
@ -28,31 +28,4 @@ struct A32JitState {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class A32AddressSpace final {
|
|
||||||
public:
|
|
||||||
explicit A32AddressSpace(const A32::UserConfig& conf);
|
|
||||||
CodePtr GetOrEmit(IR::LocationDescriptor descriptor);
|
|
||||||
void ClearCache();
|
|
||||||
private:
|
|
||||||
friend class A32Core;
|
|
||||||
EmittedBlockInfo Emit(IR::Block ir_block);
|
|
||||||
void Link(EmittedBlockInfo& block);
|
|
||||||
const A32::UserConfig conf;
|
|
||||||
CodeBlock cb;
|
|
||||||
powah::Context as;
|
|
||||||
ankerl::unordered_dense::map<u64, CodePtr> block_entries;
|
|
||||||
ankerl::unordered_dense::map<u64, EmittedBlockInfo> block_infos;
|
|
||||||
};
|
|
||||||
|
|
||||||
class A32Core final {
|
|
||||||
public:
|
|
||||||
explicit A32Core(const A32::UserConfig&) {}
|
|
||||||
HaltReason Run(A32AddressSpace& process, A32JitState& thread_ctx, volatile u32* halt_reason) {
|
|
||||||
auto const loc = thread_ctx.GetLocationDescriptor();
|
|
||||||
auto const entry = process.GetOrEmit(loc);
|
|
||||||
using CodeFn = HaltReason (*)(A32JitState*, volatile u32*);
|
|
||||||
return (CodeFn(entry))(&thread_ctx, halt_reason);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Dynarmic::Backend::RV64
|
} // namespace Dynarmic::Backend::RV64
|
||||||
|
|
|
||||||
|
|
@ -17,71 +17,83 @@
|
||||||
#include "dynarmic/ir/opt_passes.h"
|
#include "dynarmic/ir/opt_passes.h"
|
||||||
#include "dynarmic/interface/A32/a32.h"
|
#include "dynarmic/interface/A32/a32.h"
|
||||||
|
|
||||||
namespace Dynarmic::Backend::PPC64 {
|
|
||||||
|
|
||||||
A32AddressSpace::A32AddressSpace(const A32::UserConfig& conf)
|
|
||||||
: conf(conf)
|
|
||||||
, cb(conf.code_cache_size)
|
|
||||||
, as(cb.ptr<u8*>(), conf.code_cache_size) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
CodePtr A32AddressSpace::GetOrEmit(IR::LocationDescriptor desc) {
|
|
||||||
if (auto const it = block_entries.find(desc.Value()); it != block_entries.end())
|
|
||||||
return it->second;
|
|
||||||
|
|
||||||
IR::Block ir_block = A32::Translate(A32::LocationDescriptor{desc}, conf.callbacks, {conf.arch_version, conf.define_unpredictable_behaviour, conf.hook_hint_instructions});
|
|
||||||
Optimization::Optimize(ir_block, conf, {});
|
|
||||||
const EmittedBlockInfo block_info = Emit(std::move(ir_block));
|
|
||||||
|
|
||||||
block_infos.insert_or_assign(desc.Value(), block_info);
|
|
||||||
block_entries.insert_or_assign(desc.Value(), block_info.entry_point);
|
|
||||||
return block_info.entry_point;
|
|
||||||
}
|
|
||||||
|
|
||||||
void A32AddressSpace::ClearCache() {
|
|
||||||
block_entries.clear();
|
|
||||||
block_infos.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
EmittedBlockInfo A32AddressSpace::Emit(IR::Block block) {
|
|
||||||
EmittedBlockInfo block_info = EmitPPC64(as, std::move(block), {
|
|
||||||
.enable_cycle_counting = conf.enable_cycle_counting,
|
|
||||||
.always_little_endian = conf.always_little_endian,
|
|
||||||
.a64_variant = false
|
|
||||||
});
|
|
||||||
Link(block_info);
|
|
||||||
return block_info;
|
|
||||||
}
|
|
||||||
|
|
||||||
void A32AddressSpace::Link(EmittedBlockInfo& block_info) {
|
|
||||||
//UNREACHABLE();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
|
|
||||||
using namespace Dynarmic::Backend::PPC64;
|
using namespace Dynarmic::Backend::PPC64;
|
||||||
|
|
||||||
|
struct A32AddressSpace final {
|
||||||
|
explicit A32AddressSpace(const A32::UserConfig& conf)
|
||||||
|
: conf(conf)
|
||||||
|
, cb(conf.code_cache_size)
|
||||||
|
, as(cb.ptr<u8*>(), conf.code_cache_size) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
CodePtr GetOrEmit(IR::LocationDescriptor desc) {
|
||||||
|
if (auto const it = block_entries.find(desc.Value()); it != block_entries.end())
|
||||||
|
return it->second;
|
||||||
|
|
||||||
|
IR::Block ir_block = A32::Translate(A32::LocationDescriptor{desc}, conf.callbacks, {conf.arch_version, conf.define_unpredictable_behaviour, conf.hook_hint_instructions});
|
||||||
|
Optimization::Optimize(ir_block, conf, {});
|
||||||
|
const EmittedBlockInfo block_info = Emit(std::move(ir_block));
|
||||||
|
|
||||||
|
block_infos.insert_or_assign(desc.Value(), block_info);
|
||||||
|
block_entries.insert_or_assign(desc.Value(), block_info.entry_point);
|
||||||
|
return block_info.entry_point;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClearCache() {
|
||||||
|
block_entries.clear();
|
||||||
|
block_infos.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
EmittedBlockInfo Emit(IR::Block block) {
|
||||||
|
EmittedBlockInfo block_info = EmitPPC64(as, std::move(block), {
|
||||||
|
.enable_cycle_counting = conf.enable_cycle_counting,
|
||||||
|
.always_little_endian = conf.always_little_endian,
|
||||||
|
.a64_variant = false
|
||||||
|
});
|
||||||
|
Link(block_info);
|
||||||
|
return block_info;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Link(EmittedBlockInfo& block_info) {
|
||||||
|
//UNREACHABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
const A32::UserConfig conf;
|
||||||
|
CodeBlock cb;
|
||||||
|
powah::Context as;
|
||||||
|
ankerl::unordered_dense::map<u64, CodePtr> block_entries;
|
||||||
|
ankerl::unordered_dense::map<u64, EmittedBlockInfo> block_infos;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct A32Core final {
|
||||||
|
static HaltReason Run(A32AddressSpace& process, A32JitState& thread_ctx, volatile u32* halt_reason) {
|
||||||
|
auto const loc = thread_ctx.GetLocationDescriptor();
|
||||||
|
auto const entry = process.GetOrEmit(loc);
|
||||||
|
using CodeFn = HaltReason (*)(A32JitState*, volatile u32*);
|
||||||
|
return (CodeFn(entry))(&thread_ctx, halt_reason);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct Jit::Impl final {
|
struct Jit::Impl final {
|
||||||
Impl(Jit* jit_interface, A32::UserConfig conf)
|
Impl(Jit* jit_interface, A32::UserConfig conf)
|
||||||
: conf(conf)
|
: conf(conf)
|
||||||
, current_address_space(conf)
|
, current_address_space(conf)
|
||||||
, core(conf)
|
|
||||||
, jit_interface(jit_interface) {}
|
, jit_interface(jit_interface) {}
|
||||||
|
|
||||||
HaltReason Run() {
|
HaltReason Run() {
|
||||||
ASSERT(!is_executing);
|
ASSERT(!is_executing);
|
||||||
is_executing = false;
|
is_executing = false;
|
||||||
HaltReason hr = core.Run(current_address_space, jit_state, &halt_reason);
|
HaltReason hr = A32Core::Run(current_address_space, jit_state, &halt_reason);
|
||||||
is_executing = true;
|
is_executing = true;
|
||||||
RequestCacheInvalidation();
|
RequestCacheInvalidation();
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
HaltReason Step() {
|
HaltReason Step() {
|
||||||
// HaltReason hr = core.Step(current_address_space, jit_state, &halt_reason);
|
// HaltReason hr = A32Core::Step(current_address_space, jit_state, &halt_reason);
|
||||||
// RequestCacheInvalidation();
|
// RequestCacheInvalidation();
|
||||||
return HaltReason{};
|
return HaltReason{};
|
||||||
}
|
}
|
||||||
|
|
@ -156,7 +168,6 @@ private:
|
||||||
A32::UserConfig conf;
|
A32::UserConfig conf;
|
||||||
A32JitState jit_state{};
|
A32JitState jit_state{};
|
||||||
A32AddressSpace current_address_space;
|
A32AddressSpace current_address_space;
|
||||||
A32Core core;
|
|
||||||
Jit* jit_interface;
|
Jit* jit_interface;
|
||||||
volatile u32 halt_reason = 0;
|
volatile u32 halt_reason = 0;
|
||||||
bool is_executing = false;
|
bool is_executing = false;
|
||||||
|
|
|
||||||
|
|
@ -34,33 +34,4 @@ struct A64JitState {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class A64AddressSpace final {
|
|
||||||
public:
|
|
||||||
explicit A64AddressSpace(const A64::UserConfig& conf);
|
|
||||||
CodePtr GetOrEmit(IR::LocationDescriptor descriptor);
|
|
||||||
void ClearCache();
|
|
||||||
private:
|
|
||||||
friend class A64Core;
|
|
||||||
void EmitPrelude();
|
|
||||||
EmittedBlockInfo Emit(IR::Block ir_block);
|
|
||||||
void Link(EmittedBlockInfo& block);
|
|
||||||
|
|
||||||
const A64::UserConfig conf;
|
|
||||||
CodeBlock cb;
|
|
||||||
powah::Context as;
|
|
||||||
ankerl::unordered_dense::map<u64, CodePtr> block_entries;
|
|
||||||
ankerl::unordered_dense::map<u64, EmittedBlockInfo> block_infos;
|
|
||||||
};
|
|
||||||
|
|
||||||
class A64Core final {
|
|
||||||
public:
|
|
||||||
explicit A64Core(const A64::UserConfig&) {}
|
|
||||||
HaltReason Run(A64AddressSpace& process, A64JitState& thread_ctx, volatile u32* halt_reason) {
|
|
||||||
const auto loc = thread_ctx.GetLocationDescriptor();
|
|
||||||
const auto entry = process.GetOrEmit(loc);
|
|
||||||
using CodeFn = HaltReason (*)(A64JitState*, volatile u32*);
|
|
||||||
return (CodeFn(entry))(&thread_ctx, halt_reason);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Dynarmic::Backend::RV64
|
} // namespace Dynarmic::Backend::RV64
|
||||||
|
|
|
||||||
|
|
@ -16,79 +16,87 @@
|
||||||
#include "dynarmic/ir/opt_passes.h"
|
#include "dynarmic/ir/opt_passes.h"
|
||||||
#include "dynarmic/interface/A64/a64.h"
|
#include "dynarmic/interface/A64/a64.h"
|
||||||
|
|
||||||
namespace Dynarmic::Backend::PPC64 {
|
|
||||||
|
|
||||||
A64AddressSpace::A64AddressSpace(const A64::UserConfig& conf)
|
|
||||||
: conf(conf)
|
|
||||||
, cb(conf.code_cache_size)
|
|
||||||
, as(cb.ptr<u8*>(), conf.code_cache_size) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
CodePtr A64AddressSpace::GetOrEmit(IR::LocationDescriptor desc) {
|
|
||||||
if (auto const it = block_entries.find(desc.Value()); it != block_entries.end())
|
|
||||||
return it->second;
|
|
||||||
|
|
||||||
const auto get_code = [this](u64 vaddr) {
|
|
||||||
return conf.callbacks->MemoryReadCode(vaddr);
|
|
||||||
};
|
|
||||||
IR::Block ir_block = A64::Translate(A64::LocationDescriptor{desc}, get_code, {conf.define_unpredictable_behaviour, conf.wall_clock_cntpct});
|
|
||||||
Optimization::Optimize(ir_block, conf, {});
|
|
||||||
|
|
||||||
fmt::print("IR:\n");
|
|
||||||
fmt::print("{}\n", IR::DumpBlock(ir_block));
|
|
||||||
|
|
||||||
const EmittedBlockInfo block_info = Emit(std::move(ir_block));
|
|
||||||
|
|
||||||
block_infos.insert_or_assign(desc.Value(), block_info);
|
|
||||||
block_entries.insert_or_assign(desc.Value(), block_info.entry_point);
|
|
||||||
return block_info.entry_point;
|
|
||||||
}
|
|
||||||
|
|
||||||
void A64AddressSpace::ClearCache() {
|
|
||||||
block_entries.clear();
|
|
||||||
block_infos.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
EmittedBlockInfo A64AddressSpace::Emit(IR::Block block) {
|
|
||||||
EmittedBlockInfo block_info = EmitPPC64(as, std::move(block), {
|
|
||||||
.enable_cycle_counting = conf.enable_cycle_counting,
|
|
||||||
.always_little_endian = true,
|
|
||||||
.a64_variant = true
|
|
||||||
});
|
|
||||||
Link(block_info);
|
|
||||||
return block_info;
|
|
||||||
}
|
|
||||||
|
|
||||||
void A64AddressSpace::Link(EmittedBlockInfo& block_info) {
|
|
||||||
// TODO(lizzie): Block linking
|
|
||||||
// UNREACHABLE();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Dynarmic::A64 {
|
namespace Dynarmic::A64 {
|
||||||
|
|
||||||
using namespace Dynarmic::Backend::PPC64;
|
using namespace Dynarmic::Backend::PPC64;
|
||||||
|
|
||||||
|
struct A64AddressSpace final {
|
||||||
|
explicit A64AddressSpace(const A64::UserConfig& conf)
|
||||||
|
: conf(conf)
|
||||||
|
, cb(conf.code_cache_size)
|
||||||
|
, as(cb.ptr<u8*>(), conf.code_cache_size) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
CodePtr GetOrEmit(IR::LocationDescriptor desc) {
|
||||||
|
if (auto const it = block_entries.find(desc.Value()); it != block_entries.end())
|
||||||
|
return it->second;
|
||||||
|
|
||||||
|
const auto get_code = [this](u64 vaddr) {
|
||||||
|
return conf.callbacks->MemoryReadCode(vaddr);
|
||||||
|
};
|
||||||
|
IR::Block ir_block = A64::Translate(A64::LocationDescriptor{desc}, get_code, {conf.define_unpredictable_behaviour, conf.wall_clock_cntpct});
|
||||||
|
Optimization::Optimize(ir_block, conf, {});
|
||||||
|
fmt::print("IR:\n{}\n", IR::DumpBlock(ir_block));
|
||||||
|
const EmittedBlockInfo block_info = Emit(std::move(ir_block));
|
||||||
|
block_infos.insert_or_assign(desc.Value(), block_info);
|
||||||
|
block_entries.insert_or_assign(desc.Value(), block_info.entry_point);
|
||||||
|
return block_info.entry_point;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClearCache() {
|
||||||
|
block_entries.clear();
|
||||||
|
block_infos.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
EmittedBlockInfo Emit(IR::Block block) {
|
||||||
|
EmittedBlockInfo block_info = EmitPPC64(as, std::move(block), {
|
||||||
|
.enable_cycle_counting = conf.enable_cycle_counting,
|
||||||
|
.always_little_endian = true,
|
||||||
|
.a64_variant = true
|
||||||
|
});
|
||||||
|
Link(block_info);
|
||||||
|
return block_info;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Link(EmittedBlockInfo& block_info) {
|
||||||
|
// TODO(lizzie): Block linking
|
||||||
|
// UNREACHABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
const A64::UserConfig conf;
|
||||||
|
CodeBlock cb;
|
||||||
|
powah::Context as;
|
||||||
|
ankerl::unordered_dense::map<u64, CodePtr> block_entries;
|
||||||
|
ankerl::unordered_dense::map<u64, EmittedBlockInfo> block_infos;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct A64Core final {
|
||||||
|
static HaltReason Run(A64AddressSpace& process, A64JitState& thread_ctx, volatile u32* halt_reason) {
|
||||||
|
const auto loc = thread_ctx.GetLocationDescriptor();
|
||||||
|
const auto entry = process.GetOrEmit(loc);
|
||||||
|
using CodeFn = HaltReason (*)(A64JitState*, volatile u32*);
|
||||||
|
return (CodeFn(entry))(&thread_ctx, halt_reason);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct Jit::Impl final {
|
struct Jit::Impl final {
|
||||||
Impl(Jit* jit_interface, A64::UserConfig conf)
|
Impl(Jit* jit_interface, A64::UserConfig conf)
|
||||||
: conf(conf)
|
: conf(conf)
|
||||||
, current_address_space(conf)
|
, current_address_space(conf)
|
||||||
, core(conf)
|
|
||||||
, jit_interface(jit_interface) {}
|
, jit_interface(jit_interface) {}
|
||||||
|
|
||||||
HaltReason Run() {
|
HaltReason Run() {
|
||||||
ASSERT(!is_executing);
|
ASSERT(!is_executing);
|
||||||
is_executing = true;
|
is_executing = true;
|
||||||
HaltReason hr = core.Run(current_address_space, jit_state, &halt_reason);
|
HaltReason hr = A64Core::Run(current_address_space, jit_state, &halt_reason);
|
||||||
current_address_space.ClearCache(); // TODO: dont just invalidate everything
|
|
||||||
is_executing = false;
|
is_executing = false;
|
||||||
RequestCacheInvalidation();
|
RequestCacheInvalidation();
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
HaltReason Step() {
|
HaltReason Step() {
|
||||||
// HaltReason hr = core.Step(current_address_space, jit_state, &halt_reason);
|
// HaltReason hr = A64Core::Step(current_address_space, jit_state, &halt_reason);
|
||||||
// RequestCacheInvalidation();
|
// RequestCacheInvalidation();
|
||||||
return HaltReason{};
|
return HaltReason{};
|
||||||
}
|
}
|
||||||
|
|
@ -223,7 +231,6 @@ private:
|
||||||
A64::UserConfig conf;
|
A64::UserConfig conf;
|
||||||
A64JitState jit_state{};
|
A64JitState jit_state{};
|
||||||
A64AddressSpace current_address_space;
|
A64AddressSpace current_address_space;
|
||||||
A64Core core;
|
|
||||||
Jit* jit_interface;
|
Jit* jit_interface;
|
||||||
volatile u32 halt_reason = 0;
|
volatile u32 halt_reason = 0;
|
||||||
bool is_executing = false;
|
bool is_executing = false;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue