mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-08-14 04:24:31 +00:00
Compare commits
4 Commits
76bbb973c6
...
8827c30bee
| Author | SHA1 | Date | |
|---|---|---|---|
| 8827c30bee | |||
| c02fd907aa | |||
| 476a2366f2 | |||
| 90159c83c5 |
Vendored
+3
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
Vendored
+3
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#undef NDEBUG
|
||||
|
||||
Vendored
+3
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// this file is autogenerated DO NOT MODIFY
|
||||
#pragma once
|
||||
void ADD(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000214, rt, ra, rb, false, false); }
|
||||
|
||||
@@ -293,7 +293,7 @@ if ("riscv64" IN_LIST ARCHITECTURE)
|
||||
)
|
||||
message(WARNING "TODO: Incomplete frontend for this host architecture")
|
||||
endif()
|
||||
if ("ppc64" IN_LIST ARCHITECTURE)
|
||||
if ("powerpc64" IN_LIST ARCHITECTURE)
|
||||
target_link_libraries(dynarmic PRIVATE powah)
|
||||
target_sources(dynarmic PRIVATE
|
||||
backend/ppc64/abi.h
|
||||
|
||||
@@ -22,7 +22,7 @@ struct A32JitState {
|
||||
u32 exclusive_state = 0;
|
||||
u32 cpsr_nzcv = 0;
|
||||
u32 fpscr = 0;
|
||||
u8 check_bit = 0;
|
||||
u32 check_bit = 0;
|
||||
|
||||
IR::LocationDescriptor GetLocationDescriptor() const {
|
||||
return IR::LocationDescriptor{regs[15] | (u64(upper_location_descriptor) << 32)};
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
|
||||
#include <boost/icl/interval_set.hpp>
|
||||
|
||||
#include "dynarmic/common/assert.h"
|
||||
#include "dynarmic/common/common_types.h"
|
||||
#include "common/assert.h"
|
||||
#include "common/common_types.h"
|
||||
#include "dynarmic/frontend/A32/a32_location_descriptor.h"
|
||||
#include "dynarmic/frontend/A32/translate/a32_translate.h"
|
||||
#include "dynarmic/frontend/A32/FPSCR.h"
|
||||
|
||||
@@ -28,7 +28,7 @@ struct A64JitState {
|
||||
u32 fpcr = 0;
|
||||
u32 fpsr = 0;
|
||||
volatile u32 halt_reason = 0;
|
||||
u8 check_bit = 0;
|
||||
u32 check_bit = 0;
|
||||
|
||||
IR::LocationDescriptor GetLocationDescriptor() const {
|
||||
const u64 fpcr_u64 = u64(fpcr & A64::LocationDescriptor::fpcr_mask) << A64::LocationDescriptor::fpcr_shift;
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/icl/interval_set.hpp>
|
||||
#include "dynarmic/common/assert.h"
|
||||
#include "dynarmic/common/common_types.h"
|
||||
#include "common/assert.h"
|
||||
#include "common/common_types.h"
|
||||
|
||||
#include "dynarmic/frontend/A64/a64_location_descriptor.h"
|
||||
#include "dynarmic/frontend/A64/translate/a64_translate.h"
|
||||
@@ -75,18 +75,16 @@ struct A64AddressSpace final {
|
||||
ankerl::unordered_dense::map<u64, EmittedBlockInfo> block_infos;
|
||||
};
|
||||
|
||||
__attribute__((noinline)) HaltReason test_thunk(A64AddressSpace* a, A64JitState* b, volatile u32* c, void* d) {
|
||||
printf("%p,%p,%p,%p\n", a, b, c, d);
|
||||
return HaltReason::UserDefined2;
|
||||
}
|
||||
|
||||
struct A64Core final {
|
||||
using CodeFn = HaltReason (*)(A64AddressSpace*, A64JitState*, volatile u32*, void *fn);
|
||||
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 AbstractCodeFn = HaltReason (*)(A64AddressSpace*, A64JitState*, volatile u32*, void (*fn)());
|
||||
using CodeFn = HaltReason (*)(A64AddressSpace*, A64JitState*, volatile u32*, AbstractCodeFn fn);
|
||||
return (CodeFn(entry))(&process, &thread_ctx, halt_reason, AbstractCodeFn(test_thunk));
|
||||
HaltReason hr{};
|
||||
do {
|
||||
const auto loc = thread_ctx.GetLocationDescriptor();
|
||||
const auto entry = process.GetOrEmit(loc);
|
||||
hr = (CodeFn(entry))(&process, &thread_ctx, halt_reason, (void*)&A64Core::Run);
|
||||
} while (hr == HaltReason(0));
|
||||
return hr;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <powah_emit.hpp>
|
||||
#include "dynarmic/common/common_types.h"
|
||||
#include "common/common_types.h"
|
||||
|
||||
namespace Dynarmic::Backend::PPC64 {
|
||||
|
||||
@@ -49,7 +49,6 @@ constexpr powah::GPR RHALTREASON = powah::R5;
|
||||
constexpr powah::GPR RTOCPTR = powah::R6;
|
||||
// temporals
|
||||
constexpr powah::GPR RNZCV = powah::R7;
|
||||
constexpr powah::GPR RCHECKBIT = powah::R8;
|
||||
|
||||
constexpr powah::GPR ABI_PARAM1 = powah::R3;
|
||||
constexpr powah::GPR ABI_PARAM2 = powah::R4;
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
#include <new>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include "dynarmic/common/common_types.h"
|
||||
#include "dynarmic/common/assert.h"
|
||||
#include "common/common_types.h"
|
||||
#include "common/assert.h"
|
||||
|
||||
namespace Dynarmic::Backend::PPC64 {
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <powah_emit.hpp>
|
||||
#include "dynarmic/backend/ppc64/emit_ppc64.h"
|
||||
#include "dynarmic/backend/ppc64/reg_alloc.h"
|
||||
|
||||
@@ -19,6 +20,8 @@ struct EmitContext {
|
||||
RegAlloc& reg_alloc;
|
||||
const EmitConfig& emit_conf;
|
||||
EmittedBlockInfo& ebi;
|
||||
// label used when returning :)
|
||||
powah::Label l_return;
|
||||
};
|
||||
|
||||
} // namespace Dynarmic::Backend::RV64
|
||||
|
||||
@@ -144,22 +144,24 @@ void EmitIR<IR::Opcode::NZCVFromPackedFlags>(powah::Context&, EmitContext&, IR::
|
||||
}
|
||||
|
||||
namespace {
|
||||
void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::Terminal terminal, IR::LocationDescriptor initial_location, bool is_single_step);
|
||||
|
||||
void EmitLeafTerminal(powah::Context& code, EmitContext& ctx, IR::Term::LeafTerminal const& terminal, IR::LocationDescriptor initial_location, bool is_single_step);
|
||||
void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::Terminal const& terminal, IR::LocationDescriptor initial_location, bool is_single_step);
|
||||
|
||||
void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::ReturnToDispatch, IR::LocationDescriptor, bool) {
|
||||
ASSERT(false && "unimp");
|
||||
}
|
||||
|
||||
// r3 -> process
|
||||
// r4 -> thread_ctx
|
||||
// r5 -> halt_reason
|
||||
// r6 -> test_thunk
|
||||
void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::LinkBlock terminal, IR::LocationDescriptor initial_location, bool) {
|
||||
if (ctx.emit_conf.a64_variant) {
|
||||
auto const tmp = ctx.reg_alloc.ScratchGpr();
|
||||
code.LI(tmp, terminal.next.Value());
|
||||
code.STD(tmp, PPC64::RJIT, offsetof(A64JitState, pc));
|
||||
code.LD(tmp, PPC64::RTOCPTR, 0);
|
||||
code.MTCTR(tmp);
|
||||
code.LD(powah::R2, PPC64::RTOCPTR, 8);
|
||||
code.LD(powah::R11, PPC64::RTOCPTR, 16);
|
||||
code.BCTR();
|
||||
code.B(ctx.l_return);
|
||||
} else {
|
||||
auto const tmp = ctx.reg_alloc.ScratchGpr();
|
||||
code.LI(tmp, terminal.next.Value());
|
||||
@@ -168,22 +170,8 @@ void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::LinkBlock te
|
||||
}
|
||||
}
|
||||
|
||||
void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::LinkBlockFast terminal, IR::LocationDescriptor initial_location, bool) {
|
||||
if (ctx.emit_conf.a64_variant) {
|
||||
auto const tmp = ctx.reg_alloc.ScratchGpr();
|
||||
code.LI(tmp, terminal.next.Value());
|
||||
code.STD(tmp, PPC64::RJIT, offsetof(A64JitState, pc));
|
||||
code.LD(tmp, PPC64::RTOCPTR, 0);
|
||||
code.MTCTR(tmp);
|
||||
code.LD(powah::R2, PPC64::RTOCPTR, 8);
|
||||
code.LD(powah::R11, PPC64::RTOCPTR, 16);
|
||||
code.BCTR();
|
||||
} else {
|
||||
auto const tmp = ctx.reg_alloc.ScratchGpr();
|
||||
code.LI(tmp, terminal.next.Value());
|
||||
code.STW(tmp, PPC64::RJIT, offsetof(A32JitState, regs) + sizeof(u32) * 15);
|
||||
ASSERT(false && "unimp");
|
||||
}
|
||||
void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::LinkBlockFast terminal, IR::LocationDescriptor initial_location, bool is_single_step) {
|
||||
EmitTerminal(code, ctx, IR::Term::LinkBlock{terminal.next}, initial_location, is_single_step);
|
||||
}
|
||||
|
||||
void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::PopRSBHint, IR::LocationDescriptor, bool) {
|
||||
@@ -202,15 +190,15 @@ void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::CheckBit ter
|
||||
powah::Label const l_else = code.DefineLabel();
|
||||
powah::Label const l_end = code.DefineLabel();
|
||||
auto const tmp = ctx.reg_alloc.ScratchGpr();
|
||||
code.MR(tmp, PPC64::RCHECKBIT);
|
||||
code.LWZ(tmp, PPC64::RJIT, offsetof(A64JitState, check_bit));
|
||||
code.CMPLDI(tmp, 0);
|
||||
code.BEQ(powah::CR0, l_else);
|
||||
// CheckBit == 1
|
||||
EmitTerminal(code, ctx, terminal.then_, initial_location, is_single_step);
|
||||
EmitLeafTerminal(code, ctx, terminal.then_, initial_location, is_single_step);
|
||||
code.B(l_end);
|
||||
// CheckBit == 0
|
||||
code.LABEL(l_else);
|
||||
EmitTerminal(code, ctx, terminal.else_, initial_location, is_single_step);
|
||||
EmitLeafTerminal(code, ctx, terminal.else_, initial_location, is_single_step);
|
||||
code.LABEL(l_end);
|
||||
}
|
||||
|
||||
@@ -218,18 +206,37 @@ void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::CheckHalt te
|
||||
ASSERT(false && "unimp");
|
||||
}
|
||||
|
||||
void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::Terminal terminal, IR::LocationDescriptor initial_location, bool is_single_step) {
|
||||
boost::apply_visitor([&](const auto& t) {
|
||||
EmitTerminal(code, ctx, t, initial_location, is_single_step);
|
||||
}, terminal);
|
||||
void EmitLeafTerminal(powah::Context& code, EmitContext& ctx, IR::Term::LeafTerminal const& terminal, IR::LocationDescriptor initial_location, bool is_single_step) {
|
||||
if (auto const x = std::get_if<IR::Term::ReturnToDispatch>(&terminal))
|
||||
return EmitTerminal(code, ctx, *x, initial_location, is_single_step);
|
||||
if (auto const x = std::get_if<IR::Term::LinkBlock>(&terminal))
|
||||
return EmitTerminal(code, ctx, *x, initial_location, is_single_step);
|
||||
if (auto const x = std::get_if<IR::Term::LinkBlockFast>(&terminal))
|
||||
return EmitTerminal(code, ctx, *x, initial_location, is_single_step);
|
||||
if (auto const x = std::get_if<IR::Term::PopRSBHint>(&terminal))
|
||||
return EmitTerminal(code, ctx, *x, initial_location, is_single_step);
|
||||
if (auto const x = std::get_if<IR::Term::FastDispatchHint>(&terminal))
|
||||
return EmitTerminal(code, ctx, *x, initial_location, is_single_step);
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::Terminal const& terminal, IR::LocationDescriptor initial_location, bool is_single_step) {
|
||||
if (auto const x = std::get_if<IR::Term::LeafTerminal>(&terminal))
|
||||
return EmitLeafTerminal(code, ctx, *x, initial_location, is_single_step);
|
||||
if (auto const x = std::get_if<IR::Term::If>(&terminal))
|
||||
return EmitTerminal(code, ctx, *x, initial_location, is_single_step);
|
||||
if (auto const x = std::get_if<IR::Term::CheckBit>(&terminal))
|
||||
return EmitTerminal(code, ctx, *x, initial_location, is_single_step);
|
||||
if (auto const x = std::get_if<IR::Term::CheckHalt>(&terminal))
|
||||
return EmitTerminal(code, ctx, *x, initial_location, is_single_step);
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
EmittedBlockInfo EmitPPC64(powah::Context& code, IR::Block block, const EmitConfig& emit_conf) {
|
||||
EmittedBlockInfo ebi;
|
||||
RegAlloc reg_alloc{code};
|
||||
EmitContext ctx{block, reg_alloc, emit_conf, ebi};
|
||||
|
||||
EmitContext ctx{block, reg_alloc, emit_conf, ebi, code.DefineLabel()};
|
||||
size_t const stack_size = 112 + ABI_CALLEE_SAVED.size() * 8;
|
||||
auto const start_offset = code.offset;
|
||||
ebi.entry_point = &code.base[start_offset];
|
||||
@@ -268,15 +275,20 @@ EmittedBlockInfo EmitPPC64(powah::Context& code, IR::Block block, const EmitConf
|
||||
}
|
||||
|
||||
// auto const cycles_to_add = block.CycleCount();
|
||||
EmitTerminal(code, ctx, ctx.block.GetTerminal(), ctx.block.Location(), false);
|
||||
code.LABEL(ctx.l_return);
|
||||
code.ADDI(powah::R1, powah::R1, stack_size);
|
||||
for (size_t i = 0; i < gp_regs.size(); ++i)
|
||||
code.LD(gp_regs[i], powah::R1, -int32_t(gp_regs.size() - i) * 8);
|
||||
code.LD(powah::R0, powah::R1, 16);
|
||||
code.MTLR(powah::R0);
|
||||
EmitTerminal(code, ctx, ctx.block.GetTerminal(), ctx.block.Location(), false);
|
||||
code.LI(powah::R3, 0);
|
||||
} else {
|
||||
EmitTerminal(code, ctx, ctx.block.GetTerminal(), ctx.block.Location(), false);
|
||||
code.LABEL(ctx.l_return);
|
||||
code.LI(powah::R3, 67); //non-zero ret
|
||||
}
|
||||
code.BLR();
|
||||
code.ApplyRelocs();
|
||||
|
||||
/*
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include <powah_emit.hpp>
|
||||
#include "dynarmic/common/common_types.h"
|
||||
#include "common/common_types.h"
|
||||
|
||||
namespace biscuit {
|
||||
class Assembler;
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace Dynarmic::Backend::PPC64 {
|
||||
template<>
|
||||
void EmitIR<IR::Opcode::A64SetCheckBit>(powah::Context& code, EmitContext& ctx, IR::Inst* inst) {
|
||||
auto const value = ctx.reg_alloc.UseGpr(inst->GetArg(0));
|
||||
code.MR(PPC64::RCHECKBIT, value);
|
||||
code.STW(value, PPC64::RJIT, offsetof(A64JitState, check_bit));
|
||||
}
|
||||
|
||||
template<>
|
||||
@@ -48,14 +48,8 @@ void EmitIR<IR::Opcode::A64GetW>(powah::Context& code, EmitContext& ctx, IR::Ins
|
||||
if (inst->GetArg(0).GetType() == IR::Type::A64Reg) {
|
||||
auto const result = ctx.reg_alloc.ScratchGpr();
|
||||
// Need to account for endianess here...
|
||||
#ifdef __ORDER_BIG_ENDIAN__
|
||||
constexpr u32 pe_offset64 = 4;
|
||||
#else
|
||||
constexpr u32 pe_offset64 = 0;
|
||||
#endif
|
||||
auto const offs = offsetof(A64JitState, regs)
|
||||
+ A64::RegNumber(inst->GetArg(0).GetA64RegRef()) * sizeof(u64)
|
||||
+ pe_offset64;
|
||||
+ A64::RegNumber(inst->GetArg(0).GetA64RegRef()) * sizeof(u64);
|
||||
code.LWZ(result, PPC64::RJIT, offs);
|
||||
ctx.reg_alloc.DefineValue(inst, result);
|
||||
} else {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include <powah_emit.hpp>
|
||||
#include <fmt/ostream.h>
|
||||
|
||||
#include "dynarmic/common/assert.h"
|
||||
#include "common/assert.h"
|
||||
#include "dynarmic/backend/ppc64/a32_core.h"
|
||||
#include "dynarmic/backend/ppc64/abi.h"
|
||||
#include "dynarmic/backend/ppc64/emit_context.h"
|
||||
@@ -329,7 +329,7 @@ void EmitIR<IR::Opcode::ArithmeticShiftRight64>(powah::Context& code, EmitContex
|
||||
|
||||
// __builtin_rotateright32
|
||||
template<>
|
||||
void EmitIR<IR::Opcode::RotateRight32>(powah::Context& code, EmitContext& ctx, IR::Inst* inst) {
|
||||
void EmitIR<IR::Opcode::BitRotateRight32>(powah::Context& code, EmitContext& ctx, IR::Inst* inst) {
|
||||
auto const result = ctx.reg_alloc.ScratchGpr();
|
||||
auto const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0));
|
||||
auto const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(0));
|
||||
@@ -340,7 +340,7 @@ void EmitIR<IR::Opcode::RotateRight32>(powah::Context& code, EmitContext& ctx, I
|
||||
}
|
||||
|
||||
template<>
|
||||
void EmitIR<IR::Opcode::RotateRight64>(powah::Context& code, EmitContext& ctx, IR::Inst* inst) {
|
||||
void EmitIR<IR::Opcode::BitRotateRight64>(powah::Context& code, EmitContext& ctx, IR::Inst* inst) {
|
||||
auto const result = ctx.reg_alloc.ScratchGpr();
|
||||
auto const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0));
|
||||
auto const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(0));
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
#include "dynarmic/interface/exclusive_monitor.h"
|
||||
#include <algorithm>
|
||||
#include "dynarmic/common/assert.h"
|
||||
#include "common/assert.h"
|
||||
|
||||
namespace Dynarmic {
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "dynarmic/common/common_types.h"
|
||||
#include "common/common_types.h"
|
||||
|
||||
namespace Dynarmic::Backend::PPC64 {
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
|
||||
#include "dynarmic/backend/ppc64/reg_alloc.h"
|
||||
#include "dynarmic/backend/ppc64/abi.h"
|
||||
#include "dynarmic/common/assert.h"
|
||||
#include "dynarmic/common/common_types.h"
|
||||
#include "common/assert.h"
|
||||
#include "common/common_types.h"
|
||||
#include "dynarmic/common/always_false.h"
|
||||
|
||||
namespace Dynarmic::Backend::PPC64 {
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
#include <powah_emit.hpp>
|
||||
#include <ankerl/unordered_dense.h>
|
||||
|
||||
#include "dynarmic/common/assert.h"
|
||||
#include "dynarmic/common/common_types.h"
|
||||
#include "common/assert.h"
|
||||
#include "common/common_types.h"
|
||||
#include "dynarmic/backend/ppc64/stack_layout.h"
|
||||
#include "dynarmic/backend/ppc64/hostloc.h"
|
||||
#include "dynarmic/ir/cond.h"
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
#include <array>
|
||||
|
||||
#include "dynarmic/common/common_types.h"
|
||||
#include "common/common_types.h"
|
||||
|
||||
namespace Dynarmic::Backend::PPC64 {
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#include "dynarmic/backend/ppc64/abi.h"
|
||||
#include "dynarmic/backend/ppc64/hostloc.h"
|
||||
#include "dynarmic/common/spin_lock.h"
|
||||
#include "dynarmic/common/assert.h"
|
||||
#include "common/assert.h"
|
||||
|
||||
namespace Dynarmic {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user