Compare commits

...

4 Commits

Author SHA1 Message Date
lizzie 8827c30bee fix for tests?!?!? 2026-08-13 00:01:15 +00:00
lizzie c02fd907aa use common return point to not corrupt regs also use jit state for checkbit :) 2026-08-12 23:21:09 +00:00
lizzie 476a2366f2 appropriate new terminals 2026-08-12 22:11:07 +00:00
lizzie 90159c83c5 fix ppc build errs as well 2026-08-12 22:02:57 +00:00
21 changed files with 88 additions and 73 deletions
+3
View File
@@ -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>
+3
View File
@@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#undef NDEBUG
+3
View File
@@ -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); }
+1 -1
View File
@@ -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 {