emit_arm64: Remove is_a64

This commit is contained in:
Merry 2022-11-29 12:03:06 +00:00 committed by Liam
parent 167ba85ce8
commit 0707aa3a04
6 changed files with 63 additions and 52 deletions

View file

@ -303,21 +303,30 @@ EmittedBlockInfo A32AddressSpace::Emit(IR::Block block) {
mem.unprotect();
const EmitConfig emit_conf{
.tpidr_el0{},
.tpidrro_el0{},
.cntfreq_el0{},
.dczid_el0{},
.ctr_el0{},
.is_a64 = false,
.optimizations = conf.unsafe_optimizations ? conf.optimizations : conf.optimizations & all_safe_optimizations,
.hook_isb = conf.hook_isb,
.enable_cycle_counting = conf.enable_cycle_counting,
.cntfreq_el0{},
.ctr_el0{},
.dczid_el0{},
.tpidrro_el0{},
.tpidr_el0{},
.wall_clock_cntpct = conf.wall_clock_cntpct,
.enable_cycle_counting = conf.enable_cycle_counting,
.always_little_endian = conf.always_little_endian,
.descriptor_to_fpcr = [](const IR::LocationDescriptor& location) { return FP::FPCR{A32::LocationDescriptor{location}.FPSCR().Value()}; },
.emit_cond = EmitA32Cond,
.emit_condition_failed_terminal = EmitA32ConditionFailedTerminal,
.emit_terminal = EmitA32Terminal,
.state_nzcv_offset = offsetof(A32JitState, cpsr_nzcv),
.state_fpsr_offset = offsetof(A32JitState, fpsr),
.coprocessors = conf.coprocessors,
.optimizations = conf.unsafe_optimizations ? conf.optimizations : conf.optimizations & all_safe_optimizations,
};
EmittedBlockInfo block_info = EmitArm64(code, std::move(block), emit_conf);

View file

@ -433,21 +433,30 @@ EmittedBlockInfo A64AddressSpace::Emit(IR::Block block) {
mem.unprotect();
const EmitConfig emit_conf{
.optimizations = conf.unsafe_optimizations ? conf.optimizations : conf.optimizations & all_safe_optimizations,
.hook_isb = conf.hook_isb,
.tpidr_el0 = conf.tpidr_el0,
.tpidrro_el0 = conf.tpidrro_el0,
.cntfreq_el0 = conf.cntfrq_el0,
.dczid_el0 = conf.dczid_el0,
.ctr_el0 = conf.ctr_el0,
.is_a64 = true,
.hook_isb = conf.hook_isb,
.enable_cycle_counting = conf.enable_cycle_counting,
.wall_clock_cntpct = conf.wall_clock_cntpct,
.enable_cycle_counting = conf.enable_cycle_counting,
.always_little_endian = true,
.descriptor_to_fpcr = [](const IR::LocationDescriptor& location) { return A64::LocationDescriptor{location}.FPCR(); },
.emit_cond = EmitA64Cond,
.emit_condition_failed_terminal = EmitA64ConditionFailedTerminal,
.emit_terminal = EmitA64Terminal,
.state_nzcv_offset = offsetof(A64JitState, cpsr_nzcv),
.state_fpsr_offset = offsetof(A64JitState, fpsr),
.coprocessors{},
.optimizations = conf.unsafe_optimizations ? conf.optimizations : conf.optimizations & all_safe_optimizations,
};
EmittedBlockInfo block_info = EmitArm64(code, std::move(block), emit_conf);

View file

@ -8,7 +8,6 @@
#include <fmt/ostream.h>
#include <oaknut/oaknut.hpp>
#include "dynarmic/backend/arm64/a32_jitstate.h"
#include "dynarmic/backend/arm64/abi.h"
#include "dynarmic/backend/arm64/emit_context.h"
#include "dynarmic/backend/arm64/fpsr_manager.h"
@ -191,15 +190,9 @@ EmittedBlockInfo EmitArm64(oaknut::CodeGenerator& code, IR::Block block, const E
ASSERT(ctx.block.HasConditionFailedLocation());
oaknut::Label pass;
if (conf.is_a64) {
pass = EmitA64Cond(code, ctx, ctx.block.GetCondition());
EmitAddCycles(code, ctx, ctx.block.ConditionFailedCycleCount());
EmitA64ConditionFailedTerminal(code, ctx);
} else {
pass = EmitA32Cond(code, ctx, ctx.block.GetCondition());
EmitAddCycles(code, ctx, ctx.block.ConditionFailedCycleCount());
EmitA32ConditionFailedTerminal(code, ctx);
}
pass = conf.emit_cond(code, ctx, ctx.block.GetCondition());
EmitAddCycles(code, ctx, ctx.block.ConditionFailedCycleCount());
conf.emit_condition_failed_terminal(code, ctx);
code.l(pass);
}
@ -238,11 +231,7 @@ EmittedBlockInfo EmitArm64(oaknut::CodeGenerator& code, IR::Block block, const E
reg_alloc.AssertNoMoreUses();
EmitAddCycles(code, ctx, block.CycleCount());
if (conf.is_a64) {
EmitA64Terminal(code, ctx);
} else {
EmitA32Terminal(code, ctx);
}
conf.emit_terminal(code, ctx);
ebi.size = code.ptr<CodePtr>() - ebi.entry_point;
return ebi;

View file

@ -38,6 +38,8 @@ enum class Opcode;
namespace Dynarmic::Backend::Arm64 {
struct EmitContext;
using CodePtr = std::byte*;
enum class LinkTarget {
@ -90,31 +92,39 @@ struct EmittedBlockInfo {
};
struct EmitConfig {
u64* tpidr_el0;
const u64* tpidrro_el0;
u64 cntfreq_el0;
u32 dczid_el0;
u32 ctr_el0;
bool is_a64;
OptimizationFlag optimizations;
bool HasOptimization(OptimizationFlag f) const { return (f & optimizations) != no_optimizations; }
bool hook_isb;
bool enable_cycle_counting;
// System registers
u64 cntfreq_el0;
u32 ctr_el0;
u32 dczid_el0;
const u64* tpidrro_el0;
u64* tpidr_el0;
// Timing
bool wall_clock_cntpct;
bool enable_cycle_counting;
// Endianness
bool always_little_endian;
// Frontend specific callbacks
FP::FPCR (*descriptor_to_fpcr)(const IR::LocationDescriptor& descriptor);
oaknut::Label (*emit_cond)(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Cond cond);
void (*emit_condition_failed_terminal)(oaknut::CodeGenerator& code, EmitContext& ctx);
void (*emit_terminal)(oaknut::CodeGenerator& code, EmitContext& ctx);
// State offsets
size_t state_nzcv_offset;
size_t state_fpsr_offset;
// A32 specific
std::array<std::shared_ptr<A32::Coprocessor>, 16> coprocessors{};
OptimizationFlag optimizations;
bool HasOptimization(OptimizationFlag f) const { return (f & optimizations) != no_optimizations; }
};
struct EmitContext;
EmittedBlockInfo EmitArm64(oaknut::CodeGenerator& code, IR::Block block, const EmitConfig& emit_conf);
template<IR::Opcode op>

View file

@ -19,8 +19,6 @@ namespace Dynarmic::Backend::Arm64 {
using namespace oaknut::util;
static constexpr int nzcv_c_flag_shift = 29;
oaknut::Label EmitA64Cond(oaknut::CodeGenerator& code, EmitContext&, IR::Cond cond) {
oaknut::Label pass;
// TODO: Flags in host flags
@ -145,7 +143,7 @@ void EmitIR<IR::Opcode::A64GetCFlag>(oaknut::CodeGenerator& code, EmitContext& c
auto Wflag = ctx.reg_alloc.WriteW(inst);
RegAlloc::Realize(Wflag);
code.LDR(Wflag, Xstate, offsetof(A64JitState, cpsr_nzcv));
code.AND(Wflag, Wflag, 1 << nzcv_c_flag_shift);
code.AND(Wflag, Wflag, 1 << 29);
}
template<>

View file

@ -258,7 +258,7 @@ void EmitToFixed(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst)
});
}
template<typename JitState, typename Lambda>
template<typename Lambda>
static void EmitTwoOpFallbackWithoutRegAlloc(oaknut::CodeGenerator& code, EmitContext& ctx, oaknut::QReg Qresult, oaknut::QReg Qarg1, Lambda lambda, bool fpcr_controlled) {
const auto fn = static_cast<mcl::equivalent_function_type<Lambda>*>(lambda);
@ -274,7 +274,7 @@ static void EmitTwoOpFallbackWithoutRegAlloc(oaknut::CodeGenerator& code, EmitCo
code.ADD(X0, Xscratch0, 0 * 16);
code.ADD(X1, Xscratch0, 1 * 16);
code.MOV(X2, fpcr);
code.ADD(X3, Xstate, offsetof(JitState, fpsr));
code.ADD(X3, Xstate, ctx.conf.state_fpsr_offset);
code.STR(Qarg1, X1);
code.BLR(Xscratch1);
@ -289,7 +289,7 @@ static void EmitTwoOpFallbackWithoutRegAlloc(oaknut::CodeGenerator& code, EmitCo
code.l(end);
}
template<size_t fpcr_controlled_arg_index = 1, typename JitState, typename Lambda>
template<size_t fpcr_controlled_arg_index = 1, typename Lambda>
static void EmitTwoOpFallback(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst, Lambda lambda) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
auto Qarg1 = ctx.reg_alloc.ReadQ(args[0]);
@ -300,7 +300,7 @@ static void EmitTwoOpFallback(oaknut::CodeGenerator& code, EmitContext& ctx, IR:
ctx.fpsr.Spill();
const bool fpcr_controlled = args[fpcr_controlled_arg_index].GetImmediateU1();
EmitTwoOpFallbackWithoutRegAlloc<JitState>(code, ctx, Qresult, Qarg1, lambda, fpcr_controlled);
EmitTwoOpFallbackWithoutRegAlloc(code, ctx, Qresult, Qarg1, lambda, fpcr_controlled);
}
template<>
@ -592,11 +592,7 @@ void EmitIR<IR::Opcode::FPVectorRoundInt16>(oaknut::CodeGenerator& code, EmitCon
},
mp::cartesian_product<rounding_list, exact_list>{});
if (ctx.conf.is_a64) {
EmitTwoOpFallback<3, A64JitState>(code, ctx, inst, lut.at(std::make_tuple(rounding, exact)));
} else {
EmitTwoOpFallback<3, A32JitState>(code, ctx, inst, lut.at(std::make_tuple(rounding, exact)));
}
EmitTwoOpFallback<3>(code, ctx, inst, lut.at(std::make_tuple(rounding, exact)));
}
template<>