spinlocks, annoyances with organistaion
Signed-off-by: lizzie <lizzie@eden-emu.dev>
This commit is contained in:
parent
738cdeadcf
commit
3426ef21ad
|
|
@ -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) {"
|
||||
|
|
|
|||
|
|
@ -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); }
|
||||
|
|
|
|||
|
|
@ -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); }
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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};
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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…
Reference in New Issue