Browse Source

spinlocks, annoyances with organistaion

Signed-off-by: lizzie <lizzie@eden-emu.dev>
dynarmic-ppc64
lizzie 2 months ago
parent
commit
172ff8e76c
No known key found for this signature in database GPG Key ID: 287378CADCAB13
  1. 107
      externals/powah/data2code.c
  2. 14
      externals/powah/powah_emit.hpp
  3. 20
      externals/powah/powah_gen_base.hpp
  4. 4
      src/dynarmic/src/dynarmic/CMakeLists.txt
  5. 4
      src/dynarmic/src/dynarmic/backend/ppc64/a32_core.h
  6. 16
      src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp
  7. 15
      src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h
  8. 84
      src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp
  9. 8
      src/dynarmic/src/dynarmic/backend/ppc64/abi.h
  10. 2
      src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_data_processing.cpp
  11. 50
      src/dynarmic/src/dynarmic/backend/ppc64/exclusive_monitor.cpp
  12. 26
      src/dynarmic/src/dynarmic/backend/ppc64/hostloc.h
  13. 43
      src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.cpp
  14. 14
      src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.h
  15. 71
      src/dynarmic/src/dynarmic/common/spin_lock_ppc64.cpp
  16. 13
      src/dynarmic/src/dynarmic/common/spin_lock_ppc64.h

107
externals/powah/data2code.c

@ -51,30 +51,53 @@ int main(int argc, char *argv[]) {
int i_extopc = atoi(sec);
//printf("// %s\n", mem);
if (!strcmp(form, "XO")) {
if (strcmp(mem, "ADDC") == 0 || strcmp(mem, "SUBFC") == 0)
printf("//");
printf(
"void %s(GPR const rt, GPR const ra, GPR const rb) {"
" emit_%s(0x%08x, rt, ra, rb, false, false); "
"}\n"
, mem, form, (i_opcode << 26) | (i_extopc << 1));
printf(
"void %sC(GPR const rt, GPR const ra, GPR const rb) {"
" emit_%s(0x%08x, rt, ra, rb, true, false); "
"}\n"
, mem, form, (i_opcode << 26) | (i_extopc << 1));
if (strcmp(mem, "ADDC") == 0 || strcmp(mem, "SUBFC") == 0)
printf("//");
printf(
"void %s_(GPR const rt, GPR const ra, GPR const rb) {"
" emit_%s(0x%08x, rt, ra, rb, false, true); "
"}\n"
, mem, form, (i_opcode << 26) | (i_extopc << 1));
printf(
"void %sC_(GPR const rt, GPR const ra, GPR const rb) {"
" emit_%s(0x%08x, rt, ra, rb, true, true); "
"}\n"
, mem, form, (i_opcode << 26) | (i_extopc << 1));
if (!strcmp(mem, "EXTSH")) {
printf(
"void %s(GPR const rt, GPR const ra) {"
" emit_%s(0x%08x, rt, ra, R0, false, false); "
"}\n"
, mem, form, (i_opcode << 26) | (i_extopc << 1));
printf(
"void %sC(GPR const rt, GPR const ra) {"
" emit_%s(0x%08x, rt, ra, R0, true, false); "
"}\n"
, mem, form, (i_opcode << 26) | (i_extopc << 1));
printf(
"void %s_(GPR const rt, GPR const ra) {"
" emit_%s(0x%08x, rt, ra, R0, false, true); "
"}\n"
, mem, form, (i_opcode << 26) | (i_extopc << 1));
printf(
"void %sC_(GPR const rt, GPR const ra) {"
" emit_%s(0x%08x, rt, ra, R0, true, true); "
"}\n"
, mem, form, (i_opcode << 26) | (i_extopc << 1));
} else {
if (strcmp(mem, "ADDC") == 0 || strcmp(mem, "SUBFC") == 0)
printf("//");
printf(
"void %s(GPR const rt, GPR const ra, GPR const rb) {"
" emit_%s(0x%08x, rt, ra, rb, false, false); "
"}\n"
, mem, form, (i_opcode << 26) | (i_extopc << 1));
printf(
"void %sC(GPR const rt, GPR const ra, GPR const rb) {"
" emit_%s(0x%08x, rt, ra, rb, true, false); "
"}\n"
, mem, form, (i_opcode << 26) | (i_extopc << 1));
if (strcmp(mem, "ADDC") == 0 || strcmp(mem, "SUBFC") == 0)
printf("//");
printf(
"void %s_(GPR const rt, GPR const ra, GPR const rb) {"
" emit_%s(0x%08x, rt, ra, rb, false, true); "
"}\n"
, mem, form, (i_opcode << 26) | (i_extopc << 1));
printf(
"void %sC_(GPR const rt, GPR const ra, GPR const rb) {"
" emit_%s(0x%08x, rt, ra, rb, true, true); "
"}\n"
, mem, form, (i_opcode << 26) | (i_extopc << 1));
}
} else if (!strcmp(form, "X")) {
if (!strcmp(mem, "CMPL")
|| !strcmp(mem, "CMP")) {
@ -83,7 +106,8 @@ int main(int argc, char *argv[]) {
" emit_%s(0x%08x, GPR{(bf << 2) | l}, ra, rb, false); "
"}\n"
, mem, form, i_opcode << 26);
} else if (strcmp(mem, "CNTLZD") == 0 || strcmp(mem, "CNTLZW") == 0) {
} else if (!strcmp(mem, "CNTLZD") || !strcmp(mem, "CNTLZW")
|| !strcmp(mem, "EXTSB") || !strcmp(mem, "EXTSH") || !strcmp(mem, "EXTSW")) {
printf(
"void %s(GPR const rt, GPR const ra) {"
" emit_%s(0x%08x, rt, ra, R0, false); "
@ -204,16 +228,29 @@ int main(int argc, char *argv[]) {
, mem, form, (i_opcode << 26) | (i_extopc << 1));
}
} else if (!strcmp(form, "M")) {
printf(
"void %s(GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, uint32_t me = 0) {"
" emit_%s(0x%08x, rs, ra, sh, mb, me, false); "
"}\n"
, mem, form, (i_opcode << 26) | (i_extopc << 1));
printf(
"void %s_(GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, uint32_t me = 0) {"
" emit_%s(0x%08x, rs, ra, sh, mb, me, true); "
"}\n"
, mem, form, (i_opcode << 26) | (i_extopc << 1));
if (!strcmp(mem, "RLWNM")) {
printf(
"void %s(GPR const rs, GPR const ra, GPR const rb, uint32_t mb, uint32_t me = 0) {"
" emit_%s(0x%08x, rs, ra, rb.index, mb, me, false); "
"}\n"
, mem, form, (i_opcode << 26) | (i_extopc << 1));
printf(
"void %s_(GPR const rs, GPR const ra, GPR const rb, uint32_t mb, uint32_t me = 0) {"
" emit_%s(0x%08x, rs, ra, rb.index, mb, me, true); "
"}\n"
, mem, form, (i_opcode << 26) | (i_extopc << 1));
} else {
printf(
"void %s(GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, uint32_t me = 0) {"
" emit_%s(0x%08x, rs, ra, sh, mb, me, false); "
"}\n"
, mem, form, (i_opcode << 26) | (i_extopc << 1));
printf(
"void %s_(GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, uint32_t me = 0) {"
" emit_%s(0x%08x, rs, ra, sh, mb, me, true); "
"}\n"
, mem, form, (i_opcode << 26) | (i_extopc << 1));
}
} else if (!strcmp(form, "MD")) {
printf(
"void %s(GPR const rs, GPR const ra, uint32_t mb, uint32_t sh) {"

14
externals/powah/powah_emit.hpp

@ -110,6 +110,7 @@ constexpr inline CPR CR6{24};
constexpr inline CPR CR7{28};
struct Context {
Context() = default;
Context(void* ptr, size_t size)
: base{reinterpret_cast<uint32_t*>(ptr)}
, offset{0}
@ -280,6 +281,8 @@ struct Context {
// Extended Memmonics, hand coded :)
void MR(GPR const ra, GPR const rs) { OR(ra, rs, rs); }
void NOP() { ORI(R0, R0, 0); }
void NOT(GPR const ra, GPR const rs) { NOR(ra, rs, rs); }
void ROTLDI(GPR const ra, GPR const rs, uint32_t n) { RLDICL(ra, rs, n, 0); }
void ROTRDI(GPR const ra, GPR const rs, uint32_t n) { RLDICL(ra, rs, 64 - n, 0); }
@ -287,6 +290,9 @@ struct Context {
void ROTLWI(GPR const ra, GPR const rs, uint32_t n) { RLWINM(ra, rs, n, 0, 31); }
void ROTRWI(GPR const ra, GPR const rs, uint32_t n) { RLWINM(ra, rs, 32 - n, 0, 31); }
void ROTLW(GPR const ra, GPR const rs, GPR const rb) { RLWNM(ra, rs, rb, 0, 31); }
void ROTLD(GPR const ra, GPR const rs, GPR const rb) { RLDCL(ra, rs, rb, 0); }
void EXTLDI(GPR const ra, GPR const rs, uint32_t n, uint32_t b) { RLDICR(ra, rs, b, n - 1); }
void SLDI(GPR const ra, GPR const rs, uint32_t n) { RLDICR(ra, rs, n, 63 - n); }
void CLRLDI(GPR const ra, GPR const rs, uint32_t n) { RLDICL(ra, rs, 0, n); }
@ -298,7 +304,7 @@ struct Context {
void EXTLWI(GPR const ra, GPR const rs, uint32_t n, uint32_t b) { RLWINM(ra, rs, b, 0, n - 1); }
void SRWI(GPR const ra, GPR const rs, uint32_t n) { RLWINM(ra, rs, 32 - n, n, 31); }
void CLRRWI(GPR const ra, GPR const rs, uint32_t n, uint32_t b) { RLWINM(ra, rs, 0, 0, 31 - n); }
void CLRRWI(GPR const ra, GPR const rs, uint32_t n) { RLWINM(ra, rs, 0, 0, 31 - n); }
void CRSET(CPR const bx) { CREQV(bx, bx, bx); }
void CRCLR(CPR const bx) { CRXOR(bx, bx, bx); }
@ -320,8 +326,14 @@ struct Context {
void CMPDI(CPR const cr, GPR const rx, uint32_t si) { CMPI(cr.index / 4, 1, rx, si); }
void CMPD(CPR const cr, GPR const rx, GPR const ry) { CMP(cr.index / 4, 1, rx, ry); }
void BLR() { BCLR(R0, CR0, R0); }
// TODO: PowerPC 11 stuff
void ISEL(GPR const rd, GPR const ra, GPR const rb, uint32_t d) {
(void)rd;
(void)ra;
(void)rb;
(void)d;
std::unreachable();
}
void ISELLT(GPR const rd, GPR const ra, GPR const rb) { ISEL(rd, ra, rb, 0); }

20
externals/powah/powah_gen_base.hpp

@ -124,14 +124,14 @@ void EIEIO(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0006ac, rt, ra
void EIEIO_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0006ac, rt, ra, rb, true); }
void EQV(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000238, rt, ra, rb, false); }
void EQV_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000238, rt, ra, rb, true); }
void EXTSB(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000774, rt, ra, rb, false); }
void EXTSB_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000774, rt, ra, rb, true); }
void EXTSH(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000734, rt, ra, rb, false, false); }
void EXTSHC(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000734, rt, ra, rb, true, false); }
void EXTSH_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000734, rt, ra, rb, false, true); }
void EXTSHC_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000734, rt, ra, rb, true, true); }
void EXTSW(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0007b4, rt, ra, rb, false); }
void EXTSW_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0007b4, rt, ra, rb, true); }
void EXTSB(GPR const rt, GPR const ra) { emit_X(0x7c000774, rt, ra, R0, false); }
void EXTSB_(GPR const rt, GPR const ra) { emit_X(0x7c000774, rt, ra, R0, true); }
void EXTSH(GPR const rt, GPR const ra) { emit_XO(0x7c000734, rt, ra, R0, false, false); }
void EXTSHC(GPR const rt, GPR const ra) { emit_XO(0x7c000734, rt, ra, R0, true, false); }
void EXTSH_(GPR const rt, GPR const ra) { emit_XO(0x7c000734, rt, ra, R0, false, true); }
void EXTSHC_(GPR const rt, GPR const ra) { emit_XO(0x7c000734, rt, ra, R0, true, true); }
void EXTSW(GPR const rt, GPR const ra) { emit_X(0x7c0007b4, rt, ra, R0, false); }
void EXTSW_(GPR const rt, GPR const ra) { emit_X(0x7c0007b4, rt, ra, R0, true); }
void FABS(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc000210, rt, ra, rb, false); }
void FABS_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc000210, rt, ra, rb, true); }
void FADD(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xfc00002a, frt, fra, frb, frc, false); }
@ -349,8 +349,8 @@ void RLWIMI(GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, uint32_t me =
void RLWIMI_(GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, uint32_t me = 0) { emit_M(0x50000000, rs, ra, sh, mb, me, true); }
void RLWINM(GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, uint32_t me = 0) { emit_M(0x54000000, rs, ra, sh, mb, me, false); }
void RLWINM_(GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, uint32_t me = 0) { emit_M(0x54000000, rs, ra, sh, mb, me, true); }
void RLWNM(GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, uint32_t me = 0) { emit_M(0x5c000000, rs, ra, sh, mb, me, false); }
void RLWNM_(GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, uint32_t me = 0) { emit_M(0x5c000000, rs, ra, sh, mb, me, true); }
void RLWNM(GPR const rs, GPR const ra, GPR const rb, uint32_t mb, uint32_t me = 0) { emit_M(0x5c000000, rs, ra, rb.index, mb, me, false); }
void RLWNM_(GPR const rs, GPR const ra, GPR const rb, uint32_t mb, uint32_t me = 0) { emit_M(0x5c000000, rs, ra, rb.index, mb, me, true); }
void SC(uint32_t lev) { emit_SC(0x44000000, lev); }
void SI(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x30000000, rt, ra, d); }
void SI_(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x34000000, rt, ra, d); }

4
src/dynarmic/src/dynarmic/CMakeLists.txt

@ -304,9 +304,13 @@ if ("ppc64" IN_LIST ARCHITECTURE)
backend/ppc64/emit_ppc64_vector.cpp
backend/ppc64/emit_ppc64.cpp
backend/ppc64/emit_ppc64.h
backend/ppc64/exclusive_monitor.cpp
backend/ppc64/reg_alloc.cpp
backend/ppc64/reg_alloc.h
backend/ppc64/stack_layout.h
backend/ppc64/hostloc.h
common/spin_lock_ppc64.cpp
common/spin_lock_ppc64.h
# A32
backend/ppc64/a32_core.h
backend/ppc64/a32_interface.cpp

4
src/dynarmic/src/dynarmic/backend/ppc64/a32_core.h

@ -16,12 +16,12 @@
namespace Dynarmic::Backend::PPC64 {
struct A32JitState {
alignas(16) std::array<u32, 64> vec{};
alignas(16) std::array<u32, 64> ext_regs{};
std::array<u32, 16> regs{};
u32 upper_location_descriptor;
u32 exclusive_state = 0;
u32 cpsr_nzcv = 0;
u32 fpsr = 0;
u32 fpscr = 0;
IR::LocationDescriptor GetLocationDescriptor() const {
return IR::LocationDescriptor{regs[15] | (u64(upper_location_descriptor) << 32)};
}

16
src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp

@ -9,8 +9,12 @@
#include <mcl/scope_exit.hpp>
#include "dynarmic/common/common_types.h"
#include "dynarmic/frontend/A32/a32_location_descriptor.h"
#include "dynarmic/frontend/A32/translate/a32_translate.h"
#include "dynarmic/interface/A32/config.h"
#include "dynarmic/backend/ppc64/a32_core.h"
#include "dynarmic/common/atomic.h"
#include "dynarmic/ir/opt_passes.h"
#include "dynarmic/interface/A32/a32.h"
namespace Dynarmic::Backend::PPC64 {
@ -69,8 +73,12 @@ void A32AddressSpace::Link(EmittedBlockInfo& block_info) {
UNREACHABLE();
}
}
namespace Dynarmic::A32 {
using namespace Dynarmic::Backend::PPC64;
struct Jit::Impl final {
Impl(Jit* jit_interface, A32::UserConfig conf)
: jit_interface(jit_interface)
@ -130,19 +138,19 @@ struct Jit::Impl final {
}
u32 Cpsr() const {
return current_state.Cpsr();
return current_state.cpsr_nzcv;
}
void SetCpsr(u32 value) {
current_state.SetCpsr(value);
current_state.cpsr_nzcv = value;
}
u32 Fpscr() const {
return current_state.Fpscr();
return current_state.fpscr;
}
void SetFpscr(u32 value) {
current_state.SetFpscr(value);
current_state.fpscr = value;
}
void ClearExclusiveState() {

15
src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h

@ -20,10 +20,15 @@ struct A64JitState {
using ProgramCounterType = u32;
alignas(16) std::array<u64, 64> vec{};
std::array<u64, 31> regs{};
u64 sp = 0;
u64 pc = 0;
u32 upper_location_descriptor;
u32 exclusive_state = 0;
u32 cpsr_nzcv = 0;
u32 pstate = 0;
u32 fpcr = 0;
u32 fpsr = 0;
volatile u32 halt_reason = 0;
IR::LocationDescriptor GetLocationDescriptor() const {
return IR::LocationDescriptor{regs[15] | (u64(upper_location_descriptor) << 32)};
}
@ -32,15 +37,9 @@ struct A64JitState {
class A64AddressSpace final {
public:
explicit A64AddressSpace(const A64::UserConfig& conf);
IR::Block GenerateIR(IR::LocationDescriptor) const;
CodePtr Get(IR::LocationDescriptor descriptor);
CodePtr GetOrEmit(IR::LocationDescriptor descriptor);
void ClearCache();
private:
friend class A64Core;
@ -49,16 +48,12 @@ private:
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;
struct PreludeInfo {
CodePtr end_of_prelude;
using RunCodeFuncType = HaltReason (*)(CodePtr entry_point, A64JitState* context, volatile u32* halt_reason);
RunCodeFuncType run_code;
CodePtr return_from_run_code;

84
src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp

@ -8,9 +8,12 @@
#include "dynarmic/common/assert.h"
#include "dynarmic/common/common_types.h"
#include "dynarmic/backend/ppc64/a64_core.h"
#include "dynarmic/frontend/A64/a64_location_descriptor.h"
#include "dynarmic/frontend/A64/translate/a64_translate.h"
#include "dynarmic/interface/A64/config.h"
#include "dynarmic/backend/ppc64/a64_core.h"
#include "dynarmic/common/atomic.h"
#include "dynarmic/ir/opt_passes.h"
#include "dynarmic/interface/A64/a64.h"
namespace Dynarmic::Backend::PPC64 {
@ -22,28 +25,25 @@ A64AddressSpace::A64AddressSpace(const A64::UserConfig& conf)
EmitPrelude();
}
IR::Block A64AddressSpace::GenerateIR(IR::LocationDescriptor descriptor) const {
IR::Block ir_block = A64::Translate(A64::LocationDescriptor{descriptor}, conf.callbacks, {conf.arch_version, conf.define_unpredictable_behaviour, conf.hook_hint_instructions});
Optimization::Optimize(ir_block, conf, {});
return ir_block;
}
CodePtr A64AddressSpace::Get(IR::LocationDescriptor descriptor) {
if (const auto iter = block_entries.find(descriptor.Value()); iter != block_entries.end())
if (auto const iter = block_entries.find(descriptor.Value()); iter != block_entries.end())
return iter->second;
return nullptr;
}
CodePtr A64AddressSpace::GetOrEmit(IR::LocationDescriptor descriptor) {
if (CodePtr block_entry = Get(descriptor)) {
CodePtr A64AddressSpace::GetOrEmit(IR::LocationDescriptor desc) {
if (CodePtr block_entry = Get(desc))
return block_entry;
}
IR::Block ir_block = GenerateIR(descriptor);
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, {});
const EmittedBlockInfo block_info = Emit(std::move(ir_block));
block_infos.insert_or_assign(descriptor.Value(), block_info);
block_entries.insert_or_assign(descriptor.Value(), block_info.entry_point);
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;
}
@ -59,7 +59,7 @@ void A64AddressSpace::EmitPrelude() {
EmittedBlockInfo A64AddressSpace::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,
.always_little_endian = true,
});
Link(block_info);
return block_info;
@ -72,18 +72,19 @@ void A64AddressSpace::Link(EmittedBlockInfo& block_info) {
namespace Dynarmic::A64 {
using namespace Dynarmic::Backend::PPC64;
struct Jit::Impl final {
Impl(Jit* jit_interface, A64::UserConfig conf)
: jit_interface(jit_interface)
, conf(conf)
, current_address_space(conf)
, core(conf) {}
: conf(conf)
, emitter(conf) {}
HaltReason Run() {
ASSERT(!is_executing);
//PerformRequestedCacheInvalidation(HaltReason(Atomic::Load(&jit_state.halt_reason)));
is_executing = true;
const HaltReason hr = block_of_code.RunCode(&jit_state, current_code_ptr);
auto const current_loc = jit_state.GetLocationDescriptor();
const HaltReason hr = {};//block_of_code.RunCode(&jit_state, jit_state.GetOrEmit(current_loc));
//PerformRequestedCacheInvalidation(hr);
is_executing = false;
return hr;
@ -91,12 +92,13 @@ struct Jit::Impl final {
HaltReason Step() {
ASSERT(!is_executing);
//PerformRequestedCacheInvalidation(HaltReason(Atomic::Load(&jit_state.halt_reason)));
is_executing = true;
const HaltReason hr = block_of_code.StepCode(&jit_state, GetCurrentSingleStep());
//PerformRequestedCacheInvalidation(hr);
is_executing = false;
return hr;
// //PerformRequestedCacheInvalidation(HaltReason(Atomic::Load(&jit_state.halt_reason)));
// is_executing = true;
// //const HaltReason hr = block_of_code.StepCode(&jit_state, GetCurrentSingleStep());
// //PerformRequestedCacheInvalidation(hr);
// is_executing = false;
// return hr;
return {};
}
void ClearCache() {
@ -142,23 +144,21 @@ struct Jit::Impl final {
}
u64 GetRegister(size_t index) const {
if (index == 31)
return GetSP();
return jit_state.reg.at(index);
return index == 31 ? GetSP() : jit_state.regs.at(index);
}
void SetRegister(size_t index, u64 value) {
if (index == 31)
return SetSP(value);
jit_state.reg.at(index) = value;
jit_state.regs.at(index) = value;
}
std::array<u64, 31> GetRegisters() const {
return jit_state.reg;
return jit_state.regs;
}
void SetRegisters(const std::array<u64, 31>& value) {
jit_state.reg = value;
jit_state.regs = value;
}
Vector GetVector(size_t index) const {
@ -183,27 +183,27 @@ struct Jit::Impl final {
}
u32 GetFpcr() const {
return jit_state.GetFpcr();
return jit_state.fpcr;
}
void SetFpcr(u32 value) {
jit_state.SetFpcr(value);
jit_state.fpcr = value;
}
u32 GetFpsr() const {
return jit_state.GetFpsr();
return jit_state.fpsr;
}
void SetFpsr(u32 value) {
jit_state.SetFpsr(value);
jit_state.fpsr = value;
}
u32 GetPstate() const {
return jit_state.GetPstate();
return jit_state.pstate;
}
void SetPstate(u32 value) {
jit_state.SetPstate(value);
jit_state.pstate = value;
}
void ClearExclusiveState() {
@ -214,6 +214,13 @@ struct Jit::Impl final {
return is_executing;
}
std::string Disassemble() const {
// const size_t size = reinterpret_cast<const char*>(block_of_code.getCurr()) - reinterpret_cast<const char*>(block_of_code.GetCodeBegin());
// auto const* p = reinterpret_cast<const char*>(block_of_code.GetCodeBegin());
// return Common::DisassemblePPC64(p, p + size);
return {};
}
private:
void RequestCacheInvalidation() {
// UNREACHABLE();
@ -225,7 +232,6 @@ private:
const UserConfig conf;
A64JitState jit_state;
A64AddressSpace emitter;
BlockOfCode block_of_code;
Optimization::PolyfillOptions polyfill_options;
bool invalidate_entire_cache = false;
boost::icl::interval_set<u64> invalid_cache_ranges;

8
src/dynarmic/src/dynarmic/backend/ppc64/abi.h

@ -3,10 +3,18 @@
#pragma once
#include <powah_emit.hpp>
#include "dynarmic/common/common_types.h"
namespace Dynarmic::Backend::PPC64 {
constexpr powah::GPR RJIT = powah::R31;
constexpr powah::GPR ABI_PARAM1 = powah::R3;
constexpr powah::GPR ABI_PARAM2 = powah::R4;
constexpr powah::GPR ABI_PARAM3 = powah::R5;
constexpr powah::GPR ABI_PARAM4 = powah::R6;
constexpr std::initializer_list<u32> GPR_ORDER{8, 9, 18, 19, 20, 21, 22, 23, 24, 25, 5, 6, 7, 28, 29, 10, 11, 12, 13, 14, 15, 16, 17};
constexpr std::initializer_list<u32> FPR_ORDER{8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31};

2
src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_data_processing.cpp

@ -423,7 +423,7 @@ void EmitIR<IR::Opcode::ArithmeticShiftRightMasked64>(powah::Context& code, Emit
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
powah::GPR const result = ctx.reg_alloc.ScratchGpr();
powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]);
code.SRAL(result, source, source);
code.SRAD(result, source, source);
ctx.reg_alloc.DefineValue(inst, result);
}

50
src/dynarmic/src/dynarmic/backend/ppc64/exclusive_monitor.cpp

@ -0,0 +1,50 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include "dynarmic/interface/exclusive_monitor.h"
#include <algorithm>
#include "dynarmic/common/assert.h"
namespace Dynarmic {
ExclusiveMonitor::ExclusiveMonitor(std::size_t processor_count)
: exclusive_addresses(processor_count, INVALID_EXCLUSIVE_ADDRESS), exclusive_values(processor_count) {}
size_t ExclusiveMonitor::GetProcessorCount() const {
return exclusive_addresses.size();
}
void ExclusiveMonitor::Lock() {
lock.Lock();
}
void ExclusiveMonitor::Unlock() {
lock.Unlock();
}
bool ExclusiveMonitor::CheckAndClear(std::size_t processor_id, VAddr address) {
const VAddr masked_address = address & RESERVATION_GRANULE_MASK;
Lock();
if (exclusive_addresses[processor_id] != masked_address) {
Unlock();
return false;
}
for (VAddr& other_address : exclusive_addresses)
if (other_address == masked_address)
other_address = INVALID_EXCLUSIVE_ADDRESS;
return true;
}
void ExclusiveMonitor::Clear() {
Lock();
std::fill(exclusive_addresses.begin(), exclusive_addresses.end(), INVALID_EXCLUSIVE_ADDRESS);
Unlock();
}
void ExclusiveMonitor::ClearProcessor(size_t processor_id) {
Lock();
exclusive_addresses[processor_id] = INVALID_EXCLUSIVE_ADDRESS;
Unlock();
}
} // namespace Dynarmic

26
src/dynarmic/src/dynarmic/backend/ppc64/hostloc.h

@ -0,0 +1,26 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include "dynarmic/common/common_types.h"
namespace Dynarmic::Backend::PPC64 {
enum class HostLoc : uint8_t {
R0, R1, R2, R3, R4, R5, R6, R7, R8, R9,
R10, R11, R12, R13, R14, R15, R16, R17, R18, R19,
R20, R21, R22, R23, R24, R25, R26, R27, R28, R29,
R30, R31,
FR0, FR1, FR2, FR3, FR4, FR5, FR6, FR7, FR8, FR9,
FR10, FR11, FR12, FR13, FR14, FR15, FR16, FR17, FR18, FR19,
FR20, FR21, FR22, FR23, FR24, FR25, FR26, FR27, FR28, FR29,
FR30, FR31,
VR0, VR1, VR2, VR3, VR4, VR5, VR6, VR7, VR8, VR9,
VR10, VR11, VR12, VR13, VR14, VR15, VR16, VR17, VR18, VR19,
VR20, VR21, VR22, VR23, VR24, VR25, VR26, VR27, VR28, VR29,
VR30, VR31,
FirstSpill,
};
} // namespace Dynarmic::Backend::PPC64

43
src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.cpp

@ -5,6 +5,7 @@
#include <algorithm>
#include <array>
#include <ranges>
#include "dynarmic/common/assert.h"
#include <mcl/mp/metavalue/lift_value.hpp>
@ -175,42 +176,42 @@ u32 RegAlloc::FindFreeSpill() const {
}
std::optional<HostLoc> RegAlloc::ValueLocation(const IR::Inst* value) const {
const auto contains_value = [value](const HostLocInfo& info) {
const auto fn = [value](const HostLocInfo& info) {
return info.Contains(value);
};
if (const auto iter = std::find_if(gprs.begin(), gprs.end(), contains_value); iter != gprs.end()) {
return HostLoc{HostLoc::Kind::Gpr, static_cast<u32>(iter - gprs.begin())};
} else if (const auto iter = std::find_if(fprs.begin(), fprs.end(), contains_value); iter != fprs.end()) {
return HostLoc{HostLoc::Kind::Fpr, static_cast<u32>(iter - fprs.begin())};
} else if (const auto iter = std::find_if(spills.begin(), spills.end(), contains_value); iter != spills.end()) {
return HostLoc{HostLoc::Kind::Spill, static_cast<u32>(iter - spills.begin())};
}
if (const auto iter = std::ranges::find_if(gprs, fn); iter != gprs.end())
return HostLoc(u32(HostLoc::R0) + u32(iter - gprs.begin()));
else if (const auto iter = std::ranges::find_if(fprs, fn); iter != fprs.end())
return HostLoc(u32(HostLoc::FR0) + u32(iter - fprs.begin()));
else if (const auto iter = std::ranges::find_if(vprs, fn); iter != vprs.end())
return HostLoc(u32(HostLoc::VR0) + u32(iter - vprs.begin()));
else if (const auto iter = std::ranges::find_if(spills, fn); iter != spills.end())
return HostLoc(u32(HostLoc::FirstSpill) + u32(iter - spills.begin()));
return std::nullopt;
}
HostLocInfo& RegAlloc::ValueInfo(HostLoc host_loc) {
switch (host_loc.kind) {
case HostLoc::Kind::Gpr:
return gprs[size_t(host_loc.index)];
case HostLoc::Kind::Fpr:
return fprs[size_t(host_loc.index)];
case HostLoc::Kind::Spill:
return spills[size_t(host_loc.index)];
}
// switch (host_loc.kind) {
// case HostLoc::Kind::Gpr:
// return gprs[size_t(host_loc.index)];
// case HostLoc::Kind::Fpr:
// return fprs[size_t(host_loc.index)];
// case HostLoc::Kind::Spill:
// return spills[size_t(host_loc.index)];
// }
UNREACHABLE();
}
HostLocInfo& RegAlloc::ValueInfo(const IR::Inst* value) {
const auto contains_value = [value](const HostLocInfo& info) {
const auto fn = [value](const HostLocInfo& info) {
return info.Contains(value);
};
if (const auto iter = std::find_if(gprs.begin(), gprs.end(), contains_value); iter != gprs.end()) {
if (const auto iter = std::find_if(gprs.begin(), gprs.end(), fn); iter != gprs.end())
return *iter;
} else if (const auto iter = std::find_if(fprs.begin(), fprs.end(), contains_value); iter != gprs.end()) {
else if (const auto iter = std::find_if(fprs.begin(), fprs.end(), fn); iter != fprs.end())
return *iter;
} else if (const auto iter = std::find_if(spills.begin(), spills.end(), contains_value); iter != gprs.end()) {
else if (const auto iter = std::find_if(spills.begin(), spills.end(), fn); iter != spills.end())
return *iter;
}
UNREACHABLE();
}

14
src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.h

@ -15,6 +15,7 @@
#include <ankerl/unordered_dense.h>
#include "dynarmic/backend/ppc64/stack_layout.h"
#include "dynarmic/backend/ppc64/hostloc.h"
#include "dynarmic/ir/cond.h"
#include "dynarmic/ir/microinstruction.h"
#include "dynarmic/ir/value.h"
@ -23,18 +24,6 @@ namespace Dynarmic::Backend::PPC64 {
class RegAlloc;
enum class HostLoc : uint8_t {
R0, R1, R2, R3, R4, R5, R6, R7, R8, R9,
R10, R11, R12, R13, R14, R15, R16, R17, R18, R19,
R20, R21, R22, R23, R24, R25, R26, R27, R28, R29,
R30, R31,
VR0, VR1, VR2, VR3, VR4, VR5, VR6, VR7, VR8, VR9,
VR10, VR11, VR12, VR13, VR14, VR15, VR16, VR17, VR18, VR19,
VR20, VR21, VR22, VR23, VR24, VR25, VR26, VR27, VR28, VR29,
VR30, VR31,
FirstSpill,
};
struct Argument {
public:
using copyable_reference = std::reference_wrapper<Argument>;
@ -108,6 +97,7 @@ private:
powah::Context& as;
std::array<HostLocInfo, 32> gprs;
std::array<HostLocInfo, 32> fprs;
std::array<HostLocInfo, 32> vprs;
std::array<HostLocInfo, SpillCount> spills;
};

71
src/dynarmic/src/dynarmic/common/spin_lock_ppc64.cpp

@ -0,0 +1,71 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include <mutex>
#include <sys/mman.h>
#include <powah_emit.hpp>
#include "dynarmic/backend/ppc64/abi.h"
#include "dynarmic/backend/ppc64/hostloc.h"
#include "dynarmic/common/spin_lock.h"
#include "dynarmic/common/assert.h"
namespace Dynarmic {
/*
void acquire(atomic_flag* lock) {
while(atomic_flag_test_and_set_explicit( lock, memory_order_acquire))
;
}
*/
void EmitSpinLockLock(powah::Context& code, powah::GPR const ptr, powah::GPR const tmp) {
}
/*
void release(atomic_flag* lock) {
atomic_flag_clear_explicit(lock, memory_order_release);
}
*/
void EmitSpinLockUnlock(powah::Context& code, powah::GPR const ptr, powah::GPR const tmp) {
}
namespace {
struct SpinLockImpl {
void Initialize();
powah::Context code;
void* page = nullptr;
void (*lock)(volatile int*);
void (*unlock)(volatile int*);
};
std::once_flag flag;
SpinLockImpl impl;
void SpinLockImpl::Initialize() {
page = mmap(nullptr, 4096, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE, -1, 0);
ASSERT(page != nullptr);
code = powah::Context(page, 4096);
lock = reinterpret_cast<void (*)(volatile int*)>(code.base);
EmitSpinLockLock(code, Backend::PPC64::ABI_PARAM1, Backend::PPC64::ABI_PARAM2);
code.BLR();
unlock = reinterpret_cast<void (*)(volatile int*)>(code.base);
EmitSpinLockUnlock(code, Backend::PPC64::ABI_PARAM1, Backend::PPC64::ABI_PARAM2);
code.BLR();
// TODO: free the page, rework the stupid spinlock API
}
} // namespace
void SpinLock::Lock() noexcept {
std::call_once(flag, &SpinLockImpl::Initialize, impl);
impl.lock(&storage);
}
void SpinLock::Unlock() noexcept {
std::call_once(flag, &SpinLockImpl::Initialize, impl);
impl.unlock(&storage);
}
} // namespace Dynarmic

13
src/dynarmic/src/dynarmic/common/spin_lock_ppc64.h

@ -0,0 +1,13 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include <powah_emit.hpp>
namespace Dynarmic {
void EmitSpinLockLock(powah::Context& code, powah::GPR const ptr, powah::GPR const tmp);
void EmitSpinLockUnlock(powah::Context& code, powah::GPR const ptr, powah::GPR const tmp);
} // namespace Dynarmic
Loading…
Cancel
Save